Hi,
I have submitted a patch for review:
https://gerrit.libreoffice.org/3260
To pull it, you can do:
git pull ssh://gerrit.libreoffice.org:29418/core refs/changes/60/3260/1
fdo#61390 - Thumbnail navigation by shift-click and shift-keyboard.
Change-Id: I0b107d0918e1914709de31fd52cd11480e7fd419
---
M sfx2/inc/sfx2/thumbnailview.hxx
M sfx2/source/control/thumbnailview.cxx
2 files changed, 189 insertions(+), 10 deletions(-)
diff --git a/sfx2/inc/sfx2/thumbnailview.hxx b/sfx2/inc/sfx2/thumbnailview.hxx
index 6d9f30e..1286385 100644
--- a/sfx2/inc/sfx2/thumbnailview.hxx
+++ b/sfx2/inc/sfx2/thumbnailview.hxx
@@ -305,6 +305,7 @@
ValueItemList mItemList;
ValueItemList mFilteredItemList; ///< Cache to store the filtered items
+ ValueItemList::iterator mpStartSelRange;
ScrollBar* mpScrBar;
Rectangle maItemListRect;
long mnHeaderHeight;
diff --git a/sfx2/source/control/thumbnailview.cxx b/sfx2/source/control/thumbnailview.cxx
index 725520c..8d03d5a 100644
--- a/sfx2/source/control/thumbnailview.cxx
+++ b/sfx2/source/control/thumbnailview.cxx
@@ -10,6 +10,8 @@
#include <sfx2/thumbnailview.hxx>
#include <sfx2/thumbnailviewitem.hxx>
+#include <utility>
+
#include "thumbnailviewacc.hxx"
#include <basegfx/color/bcolortools.hxx>
@@ -84,7 +86,20 @@
void ThumbnailView::AppendItem(ThumbnailViewItem *pItem)
{
if (maFilterFunc(pItem))
+ {
+ // Save current start,end range, iterator might get invalidated
+ size_t nSelStartPos = 0;
+ ThumbnailViewItem *pSelStartItem = NULL;
+
+ if (mpStartSelRange != mFilteredItemList.end())
+ {
+ pSelStartItem = *mpStartSelRange;
+ nSelStartPos = mpStartSelRange - mFilteredItemList.begin();
+ }
+
mFilteredItemList.push_back(pItem);
+ mpStartSelRange = pSelStartItem != NULL ? mFilteredItemList.begin() + nSelStartPos :
mFilteredItemList.end();
+ }
mItemList.push_back(pItem);
}
@@ -107,6 +122,7 @@
mbHasVisibleItems = false;
maFilterFunc = ViewFilterAll();
maColor = GetSettings().GetStyleSettings().GetFieldColor();
+ mpStartSelRange = mFilteredItemList.end();
// Create the processor and process the primitives
const drawinglayer::geometry::ViewInformation2D aNewViewInfos;
@@ -145,6 +161,8 @@
mItemList.clear();
mFilteredItemList.clear();
+
+ mpStartSelRange = mFilteredItemList.end();
}
void ThumbnailView::ImplInitSettings( bool bFont, bool bForeground, bool bBackground )
@@ -398,9 +416,9 @@
if ( maItemListRect.IsInside( rPos ) )
{
- for (size_t i = 0; i < mItemList.size(); ++i)
+ for (size_t i = 0; i < mFilteredItemList.size(); ++i)
{
- if (mItemList[i]->isVisible() && mItemList[i]->getDrawArea().IsInside(rPos))
+ if (mFilteredItemList[i]->isVisible() &&
mFilteredItemList[i]->getDrawArea().IsInside(rPos))
return i;
}
@@ -417,7 +435,7 @@
ThumbnailViewItem* ThumbnailView::ImplGetItem( size_t nPos )
{
- return ( nPos < mItemList.size() ) ? mItemList[nPos] : NULL;
+ return ( nPos < mFilteredItemList.size() ) ? mFilteredItemList[nPos] : NULL;
}
sal_uInt16 ThumbnailView::ImplGetVisibleItemCount() const
@@ -505,39 +523,68 @@
}
}
+ bool bValidRange = false;
+ bool bHasSelRange = mpStartSelRange != mFilteredItemList.end();
+ size_t nNextPos = nLastPos;
KeyCode aKeyCode = rKEvt.GetKeyCode();
ThumbnailViewItem* pNext = NULL;
+
+ if (aKeyCode.IsShift() && bHasSelRange)
+ {
+ //If the last elemented selected is the start range position
+ //search for the first selected item
+ size_t nSelPos = mpStartSelRange - mFilteredItemList.begin();
+
+ if (nLastPos == nSelPos)
+ {
+ while (nLastPos && mFilteredItemList[nLastPos-1]->isSelected())
+ --nLastPos;
+ }
+ }
+
switch ( aKeyCode.GetCode() )
{
case KEY_RIGHT:
{
- size_t nNextPos = nLastPos;
if ( bFoundLast && nLastPos < mFilteredItemList.size( ) - 1 )
+ {
+ bValidRange = true;
nNextPos = nLastPos + 1;
+ }
+
pNext = mFilteredItemList[nNextPos];
}
break;
case KEY_LEFT:
{
- size_t nNextPos = nLastPos;
if ( nLastPos > 0 )
+ {
+ bValidRange = true;
nNextPos = nLastPos - 1;
+ }
+
pNext = mFilteredItemList[nNextPos];
}
break;
case KEY_DOWN:
{
- size_t nNextPos = nLastPos;
if ( bFoundLast && nLastPos < mFilteredItemList.size( ) - mnCols )
+ {
+ bValidRange = true;
nNextPos = nLastPos + mnCols;
+ }
+
pNext = mFilteredItemList[nNextPos];
}
break;
case KEY_UP:
{
- size_t nNextPos = nLastPos;
if ( nLastPos >= mnCols )
+ {
+ bValidRange = true;
nNextPos = nLastPos - mnCols;
+ }
+
pNext = mFilteredItemList[nNextPos];
}
break;
@@ -552,8 +599,67 @@
if ( pNext )
{
- deselectItems();
- SelectItem(pNext->mnId);
+ if (aKeyCode.IsShift() && bValidRange)
+ {
+ std::pair<size_t,size_t> aRange;
+ size_t nSelPos = mpStartSelRange - mFilteredItemList.begin();
+
+ if (nLastPos < nSelPos)
+ {
+ if (nNextPos > nLastPos)
+ {
+ if ( nNextPos > nSelPos)
+ aRange = std::make_pair(nLastPos,nNextPos);
+ else
+ aRange = std::make_pair(nLastPos,nNextPos-1);
+ }
+ else
+ aRange = std::make_pair(nNextPos,nLastPos-1);
+ }
+ else if (nLastPos == nSelPos)
+ {
+ if (nNextPos > nLastPos)
+ aRange = std::make_pair(nLastPos+1,nNextPos);
+ else
+ aRange = std::make_pair(nNextPos,nLastPos-1);
+ }
+ else
+ {
+ if (nNextPos > nLastPos)
+ aRange = std::make_pair(nLastPos+1,nNextPos);
+ else
+ {
+ if ( nNextPos < nSelPos)
+ aRange = std::make_pair(nNextPos,nLastPos);
+ else
+ aRange = std::make_pair(nNextPos+1,nLastPos);
+ }
+ }
+
+ for (size_t i = aRange.first; i <= aRange.second; ++i)
+ {
+ if (i != nSelPos)
+ {
+ ThumbnailViewItem *pCurItem = mFilteredItemList[i];
+
+ pCurItem->setSelection(!pCurItem->isSelected());
+
+ if (pCurItem->isVisible())
+ DrawItem(pCurItem);
+
+ maItemStateHdl.Call(pCurItem);
+ }
+ }
+ }
+ else if (!aKeyCode.IsShift())
+ {
+ deselectItems();
+ SelectItem(pNext->mnId);
+
+ //Mark it as the selection range start position
+ mpStartSelRange = mFilteredItemList.begin() + nNextPos;
+ }
+
MakeItemVisible(pNext->mnId);
}
}
@@ -588,7 +694,8 @@
{
if ( rMEvt.IsLeft() )
{
- ThumbnailViewItem* pItem = ImplGetItem( ImplGetItem( rMEvt.GetPosPixel() ) );
+ size_t nPos = ImplGetItem(rMEvt.GetPosPixel());
+ ThumbnailViewItem* pItem = ImplGetItem(nPos);
if (pItem && pItem->isVisible())
{
@@ -598,6 +705,62 @@
{
//Keep selected item group state and just invert current desired one state
pItem->setSelection(!pItem->isSelected());
+
+ //This one becomes the selection range start position if it changes its state
to selected otherwise resets it
+ mpStartSelRange = pItem->isSelected() ? mFilteredItemList.begin() + nPos :
mFilteredItemList.end();
+ }
+ else if (rMEvt.IsShift() && mpStartSelRange != mFilteredItemList.end())
+ {
+ std::pair<size_t,size_t> aNewRange;
+ aNewRange.first = mpStartSelRange - mFilteredItemList.begin();
+ aNewRange.second = nPos;
+
+ if (aNewRange.first > aNewRange.second)
+ std::swap(aNewRange.first,aNewRange.second);
+
+ //Deselect the ones outside of it
+ for (size_t i = 0, n = mFilteredItemList.size(); i < n; ++i)
+ {
+ ThumbnailViewItem *pCurItem = mFilteredItemList[i];
+
+ if (pCurItem->isSelected() && (i < aNewRange.first || i >
aNewRange.second))
+ {
+ pCurItem->setSelection(false);
+
+ if (pCurItem->isVisible())
+ DrawItem(pCurItem);
+
+ maItemStateHdl.Call(pCurItem);
+ }
+ }
+
+ size_t nSelPos = mpStartSelRange - mFilteredItemList.begin();
+
+ //Select the items between start range and the selected item
+ if (nSelPos != nPos)
+ {
+ int dir = nSelPos < nPos ? 1 : -1;
+ size_t nCurPos = nSelPos + dir;
+
+ while (nCurPos != nPos)
+ {
+ ThumbnailViewItem *pCurItem = mFilteredItemList[nCurPos];
+
+ if (!pCurItem->isSelected())
+ {
+ pCurItem->setSelection(true);
+
+ if (pCurItem->isVisible())
+ DrawItem(pCurItem);
+
+ maItemStateHdl.Call(pCurItem);
+ }
+
+ nCurPos += dir;
+ }
+ }
+
+ pItem->setSelection(true);
}
else
{
@@ -606,6 +769,9 @@
pItem->setSelection(false);
deselectItems();
pItem->setSelection(true);
+
+ //Mark as initial selection range position and reset end one
+ mpStartSelRange = mFilteredItemList.begin() + nPos;
}
if (pItem->isSelected())
@@ -1053,6 +1219,11 @@
{
mnFirstLine = 0; // start at the top of the list instead of the current position
maFilterFunc = func;
+
+ size_t nSelPos = 0;
+ bool bHasSelRange = false;
+ ThumbnailViewItem *curSel = mpStartSelRange != mFilteredItemList.end() ? *mpStartSelRange :
NULL;
+
mFilteredItemList.clear();
for (size_t i = 0, n = mItemList.size(); i < n; ++i)
@@ -1061,6 +1232,12 @@
if (maFilterFunc(pItem))
{
+ if (curSel == pItem)
+ {
+ nSelPos = i;
+ bHasSelRange = true;
+ }
+
mFilteredItemList.push_back(pItem);
}
else
@@ -1082,6 +1259,7 @@
}
}
+ mpStartSelRange = bHasSelRange ? mFilteredItemList.begin() + nSelPos :
mFilteredItemList.end();
CalculateItemPositions();
Invalidate();
--
To view, visit https://gerrit.libreoffice.org/3260
To unsubscribe, visit https://gerrit.libreoffice.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I0b107d0918e1914709de31fd52cd11480e7fd419
Gerrit-PatchSet: 1
Gerrit-Project: core
Gerrit-Branch: libreoffice-4-0
Gerrit-Owner: Rafael Dominguez <venccsralph@gmail.com>
Context
- [PATCH libreoffice-4-0] fdo#61390 - Thumbnail navigation by shift-click and shift-ke... · Rafael Dominguez (via Code Review)
Privacy Policy |
Impressum (Legal Info) |
Copyright information: Unless otherwise specified, all text and images
on this website are licensed under the
Creative Commons Attribution-Share Alike 3.0 License.
This does not include the source code of LibreOffice, which is
licensed under the Mozilla Public License (
MPLv2).
"LibreOffice" and "The Document Foundation" are
registered trademarks of their corresponding registered owners or are
in actual use as trademarks in one or more countries. Their respective
logos and icons are also subject to international copyright laws. Use
thereof is explained in our
trademark policy.