Merge pull request #3036 from adamreichold/fix-range-selection

Fix range selection
This commit is contained in:
Beep6581 2015-12-20 23:24:14 +01:00
commit a345eb7c8a
3 changed files with 118 additions and 110 deletions

View File

@ -704,4 +704,20 @@ public:
#define MYWRITERLOCK_RELEASE(ln) ln.release();
#endif
#ifdef PROTECT_VECTORS
#define IFPV_MYREADERLOCK(l, e) MYREADERLOCK(l, e)
#define IFPV_MYWRITERLOCK(l, e) MYWRITERLOCK(l, e)
#define IFPV_MYREADERLOCK_ACQUIRE(l) MYREADERLOCK_ACQUIRE(l)
#define IFPV_MYWRITERLOCK_ACQUIRE(l) MYWRITERLOCK_ACQUIRE(l)
#define IFPV_MYREADERLOCK_RELEASE(l) MYREADERLOCK_RELEASE(l)
#define IFPV_MYWRITERLOCK_RELEASE(l) MYWRITERLOCK_RELEASE(l)
#else
#define IFPV_MYREADERLOCK(l, e)
#define IFPV_MYWRITERLOCK(l, e)
#define IFPV_MYREADERLOCK_ACQUIRE(l)
#define IFPV_MYWRITERLOCK_ACQUIRE(l)
#define IFPV_MYREADERLOCK_RELEASE(l)
#define IFPV_MYWRITERLOCK_RELEASE(l)
#endif
#endif /* _THREADUTILS_ */

View File

@ -98,6 +98,88 @@ void ThumbBrowserBase::scrollPage (int direction)
}
}
namespace
{
typedef std::vector<ThumbBrowserEntryBase*> ThumbVector;
typedef ThumbVector::iterator ThumbIterator;
inline void clearSelection (ThumbVector& selected)
{
for (ThumbIterator thumb = selected.begin (); thumb != selected.end (); ++thumb)
(*thumb)->selected = false;
selected.clear ();
}
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::selectSet (ThumbBrowserEntryBase* clicked)
{
const ThumbIterator iterator = std::find (selected.begin (), selected.end (), clicked);
if (iterator != selected.end ()) {
removeFromSelection (iterator, selected);
} else {
addToSelection (clicked, selected);
}
}
static void scrollToEntry (double& h, double& v, int iw, int ih, ThumbBrowserEntryBase* entry)
{
const int hmin = entry->getX ();
@ -726,9 +808,7 @@ void ThumbBrowserBase::buttonPressed (int x, int y, int button, GdkEventType typ
bool handled = false;
{
#if PROTECT_VECTORS
MYREADERLOCK(l, entryRW);
#endif
IFPV_MYREADERLOCK(l, entryRW);
for (size_t i = 0; i < fd.size(); i++)
if (fd[i]->drawable) {
@ -746,125 +826,31 @@ void ThumbBrowserBase::buttonPressed (int x, int y, int button, GdkEventType typ
}
{
#if PROTECT_VECTORS
MYWRITERLOCK(l, entryRW);
#endif
IFPV_MYWRITERLOCK(l, entryRW);
if (selected.size() == 1 && type == GDK_2BUTTON_PRESS && button == 1) {
doubleClicked (selected[0]);
} else if (button == 1 && type == GDK_BUTTON_PRESS) {
if (fileDescr && (state & GDK_SHIFT_MASK)) {
if (selected.empty()) {
selected.push_back (fileDescr);
fileDescr->selected = true;
lastClicked = fileDescr;
#if PROTECT_VECTORS
MYWRITERLOCK_RELEASE(l);
#endif
selectionChanged ();
} else {
// find the start and the end of the selection interval
size_t startx = fd.size() - 1;
if (fileDescr && (state & GDK_SHIFT_MASK))
selectRange (fileDescr, state & GDK_CONTROL_MASK);
else if (fileDescr && (state & GDK_CONTROL_MASK))
selectSet (fileDescr);
else
selectSingle (fileDescr);
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]);
}
}
lastClicked = fileDescr;
#if PROTECT_VECTORS
MYWRITERLOCK_RELEASE(l);
#endif
selectionChanged ();
}
} else if (fileDescr && (state & GDK_CONTROL_MASK)) {
std::vector<ThumbBrowserEntryBase*>::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;
}
lastClicked = fileDescr;
#if PROTECT_VECTORS
MYWRITERLOCK_RELEASE(l);
#endif
selectionChanged ();
} else {
for (size_t i = 0; i < selected.size(); i++) {
selected[i]->selected = false;
}
selected.clear ();
if (fileDescr) {
selected.push_back (fileDescr);
fileDescr->selected = true;
}
lastClicked = fileDescr;
#if PROTECT_VECTORS
MYWRITERLOCK_RELEASE(l);
#endif
selectionChanged ();
}
lastClicked = fileDescr;
IFPV_MYWRITERLOCK_RELEASE(l);
selectionChanged ();
} else if (fileDescr && button == 3 && type == GDK_BUTTON_PRESS) {
if (!fileDescr->selected) {
for (size_t i = 0; i < selected.size(); i++) {
selected[i]->selected = false;
}
selectSingle (fileDescr);
selected.clear ();
fileDescr->selected = true;
selected.push_back (fileDescr);
lastClicked = fileDescr;
#if PROTECT_VECTORS
MYWRITERLOCK_RELEASE(l);
#endif
IFPV_MYWRITERLOCK_RELEASE(l);
selectionChanged ();
}
#if PROTECT_VECTORS
MYWRITERLOCK_RELEASE(l);
#endif
IFPV_MYWRITERLOCK_RELEASE(l);
rightClicked (fileDescr);
}
} // end of MYWRITERLOCK(l, entryRW);

View File

@ -110,6 +110,12 @@ public:
void scroll (int direction);
void scrollPage (int direction);
private:
void selectSingle (ThumbBrowserEntryBase* clicked);
void selectRange (ThumbBrowserEntryBase* clicked, bool additional);
void selectSet (ThumbBrowserEntryBase* clicked);
public:
void selectPrev (int distance, bool enlarge);
void selectNext (int distance, bool enlarge);
void selectFirst (bool enlarge);