diff --git a/rtgui/thumbbrowserbase.cc b/rtgui/thumbbrowserbase.cc index ed6366266..3536cc9b7 100644 --- a/rtgui/thumbbrowserbase.cc +++ b/rtgui/thumbbrowserbase.cc @@ -98,81 +98,85 @@ void ThumbBrowserBase::scrollPage (int direction) } } -void ThumbBrowserBase::selectSingle (ThumbBrowserEntryBase* fileDescr) +namespace { - for (size_t i = 0; i < selected.size(); i++) { - selected[i]->selected = false; - } + +typedef std::vector ThumbVector; +typedef ThumbVector::iterator ThumbIterator; + +inline void clearSelection (ThumbVector& selected) +{ + for (ThumbIterator thumb = selected.begin (); thumb != selected.end (); ++thumb) + (*thumb)->selected = false; selected.clear (); +} - if (fileDescr) { - selected.push_back (fileDescr); - fileDescr->selected = true; +inline void addToSelection (ThumbBrowserEntryBase* entry, ThumbVector& selected) +{ + if (entry->selected || entry->filtered) + return; + + entry->selected = true; + selected.push_back (entry); +} + +inline void removeFromSelection (const ThumbIterator& iterator, ThumbVector& selected) +{ + (*iterator)->selected = false; + selected.erase (iterator); +} + +} + +void ThumbBrowserBase::selectSingle (ThumbBrowserEntryBase* clicked) +{ + clearSelection (selected); + + if (clicked) + addToSelection (clicked, selected); +} + +void ThumbBrowserBase::selectRange (ThumbBrowserEntryBase* clicked, bool additional) +{ + if (selected.empty ()) { + addToSelection (clicked, selected); + return; + } + + if (!additional || !lastClicked) { + // Extend the current range w.r.t to first selected entry. + ThumbIterator front = std::find (fd.begin (), fd.end (), selected.front ()); + ThumbIterator current = std::find (fd.begin (), fd.end (), clicked); + + if (front > current) + std::swap (front, current); + + clearSelection (selected); + + for (; front <= current; ++front) + addToSelection (*front, selected); + } else { + // Add an additional range w.r.t. the last clicked entry. + ThumbIterator last = std::find (fd.begin (), fd.end (), lastClicked); + ThumbIterator current = std::find (fd.begin (), fd.end (), clicked); + + if (last > current) + std::swap (last, current); + + for (; last <= current; ++last) + addToSelection (*last, selected); } } -void ThumbBrowserBase::selectRange (ThumbBrowserEntryBase* fileDescr) +void ThumbBrowserBase::selectSet (ThumbBrowserEntryBase* clicked) { - if (selected.empty()) { - selected.push_back (fileDescr); - fileDescr->selected = true; + const ThumbIterator iterator = std::find (selected.begin (), selected.end (), clicked); + + if (iterator != selected.end ()) { + removeFromSelection (iterator, selected); } else { - // find the start and the end of the selection interval - size_t startx = fd.size() - 1; - - if (lastClicked) { - for (; startx > 0; startx--) - if (fd[startx] == lastClicked) { - break; - } - } else { - for (; startx > 0; startx--) - if (fd[startx] == selected[0]) { - break; - } - } - - size_t endx = 0; - - for (; endx < fd.size(); endx++) - if (fd[endx] == fileDescr) { - break; - } - - if (endx < startx) { - int tmp = endx; - endx = startx; - startx = tmp; - } - - // clear current selection - for (size_t i = 0; i < selected.size(); i++) { - selected[i]->selected = false; - } - - selected.clear (); - - // select thumbnails in the interval - for (size_t i = startx; i <= endx; i++) { - if (!fd[i]->filtered) { - fd[i]->selected = true; - selected.push_back (fd[i]); - } - } - } -} - -void ThumbBrowserBase::selectSet (ThumbBrowserEntryBase* fileDescr) -{ - std::vector::iterator i = std::find (selected.begin(), selected.end(), fileDescr); - - if (i != selected.end()) { - (*i)->selected = false; - selected.erase (i); - } else { - selected.push_back (fileDescr); - fileDescr->selected = true; + addToSelection (clicked, selected); } } @@ -828,7 +832,7 @@ void ThumbBrowserBase::buttonPressed (int x, int y, int button, GdkEventType typ doubleClicked (selected[0]); } else if (button == 1 && type == GDK_BUTTON_PRESS) { if (fileDescr && (state & GDK_SHIFT_MASK)) - selectRange (fileDescr); + selectRange (fileDescr, state & GDK_CONTROL_MASK); else if (fileDescr && (state & GDK_CONTROL_MASK)) selectSet (fileDescr); else diff --git a/rtgui/thumbbrowserbase.h b/rtgui/thumbbrowserbase.h index ee11f550e..a3ef08d80 100644 --- a/rtgui/thumbbrowserbase.h +++ b/rtgui/thumbbrowserbase.h @@ -111,9 +111,9 @@ public: void scrollPage (int direction); private: - void selectSingle (ThumbBrowserEntryBase* fileDescr); - void selectRange (ThumbBrowserEntryBase* fileDescr); - void selectSet (ThumbBrowserEntryBase* fileDescr); + void selectSingle (ThumbBrowserEntryBase* clicked); + void selectRange (ThumbBrowserEntryBase* clicked, bool additional); + void selectSet (ThumbBrowserEntryBase* clicked); public: void selectPrev (int distance, bool enlarge);