Keyboard navigation in File Browser (issue 1919, on behalf of Adam Reichold)
Select a thumbnail using the arrow keys, select multiple with Shift
This commit is contained in:
@@ -14,18 +14,18 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with RawTherapee. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <glibmm.h>
|
||||
#include "../rtengine/rt_math.h"
|
||||
|
||||
#include <glibmm.h>
|
||||
#include "../rtengine/rt_math.h"
|
||||
|
||||
#include "thumbbrowserbase.h"
|
||||
#include "multilangmgr.h"
|
||||
#include "options.h"
|
||||
#include "../rtengine/mytime.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
using namespace std;
|
||||
|
||||
ThumbBrowserBase::ThumbBrowserBase ()
|
||||
: lastClicked(NULL), previewHeight(options.thumbSize) {
|
||||
: lastClicked(NULL), previewHeight(options.thumbSize), numOfCols(1) {
|
||||
inTabMode=false; // corresponding to take thumbSize
|
||||
inW = -1; inH = -1;
|
||||
|
||||
@@ -91,6 +91,137 @@ void ThumbBrowserBase::scrollPage (int direction) {
|
||||
hscroll.set_value (hscroll.get_value() + (direction==GDK_SCROLL_DOWN ? +1 : -1) * hscroll.get_adjustment()->get_page_increment());
|
||||
}
|
||||
|
||||
static void scrollToEntry (double& h, double& v, int iw, int ih, ThumbBrowserEntryBase* entry) {
|
||||
const int hmin = entry->getX ();
|
||||
const int hmax = hmin + entry->getEffectiveWidth () - iw;
|
||||
const int vmin = entry->getY ();
|
||||
const int vmax = vmin + entry->getEffectiveHeight () - ih;
|
||||
|
||||
if (hmin < 0)
|
||||
h += hmin;
|
||||
else if (hmax > 0)
|
||||
h += hmax;
|
||||
|
||||
if(vmin < 0)
|
||||
v += vmin;
|
||||
else if (vmax > 0)
|
||||
v += vmax;
|
||||
}
|
||||
|
||||
void ThumbBrowserBase::selectPrev (int distance, bool enlarge) {
|
||||
double h, v;
|
||||
getScrollPosition (h, v);
|
||||
|
||||
{
|
||||
#if PROTECT_VECTORS
|
||||
MYWRITERLOCK(l, entryRW);
|
||||
#endif
|
||||
|
||||
if (!selected.empty ()) {
|
||||
std::vector<ThumbBrowserEntryBase*>::iterator front = std::find (fd.begin (), fd.end (), selected.front ());
|
||||
std::vector<ThumbBrowserEntryBase*>::iterator back = std::find (fd.begin (), fd.end (), selected.back ());
|
||||
|
||||
if(front > back)
|
||||
std::swap(front, back);
|
||||
|
||||
// find next thumbnail at filtered distance before 'front'
|
||||
for (; front >= fd.begin (); --front) {
|
||||
if(!(*front)->filtered) {
|
||||
if (distance-- == 0) {
|
||||
// clear current selection
|
||||
for (size_t i=0; i<selected.size (); ++i) {
|
||||
selected[i]->selected = false;
|
||||
redrawNeeded (selected[i]);
|
||||
}
|
||||
selected.clear ();
|
||||
|
||||
// make sure the newly selected thumbnail is visible
|
||||
scrollToEntry (h, v, internal.get_width (), internal.get_height (), *front);
|
||||
|
||||
// either enlarge current selection or set new selection
|
||||
for(; front <= back; ++front) {
|
||||
if(!(*front)->filtered) {
|
||||
(*front)->selected = true;
|
||||
redrawNeeded (*front);
|
||||
selected.push_back (*front);
|
||||
}
|
||||
|
||||
if(!enlarge)
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if PROTECT_VECTORS
|
||||
MYWRITERLOCK_RELEASE(l);
|
||||
#endif
|
||||
selectionChanged ();
|
||||
}
|
||||
|
||||
setScrollPosition (h, v);
|
||||
}
|
||||
|
||||
void ThumbBrowserBase::selectNext (int distance, bool enlarge) {
|
||||
double h, v;
|
||||
getScrollPosition (h, v);
|
||||
|
||||
{
|
||||
#if PROTECT_VECTORS
|
||||
MYWRITERLOCK(l, entryRW);
|
||||
#endif
|
||||
|
||||
if (!selected.empty ()) {
|
||||
std::vector<ThumbBrowserEntryBase*>::iterator front = std::find (fd.begin (), fd.end (), selected.front ());
|
||||
std::vector<ThumbBrowserEntryBase*>::iterator back = std::find (fd.begin (), fd.end (), selected.back ());
|
||||
|
||||
if(front > back)
|
||||
std::swap(front, back);
|
||||
|
||||
// find next thumbnail at filtered distance after 'back'
|
||||
for (; back < fd.end (); ++back) {
|
||||
if(!(*back)->filtered) {
|
||||
if (distance-- == 0) {
|
||||
// clear current selection
|
||||
for (size_t i=0; i<selected.size (); ++i) {
|
||||
selected[i]->selected = false;
|
||||
redrawNeeded (selected[i]);
|
||||
}
|
||||
selected.clear ();
|
||||
|
||||
// make sure the newly selected thumbnail is visible
|
||||
scrollToEntry (h, v, internal.get_width (), internal.get_height (), *back);
|
||||
|
||||
// either enlarge current selection or set new selection
|
||||
for(; back >= front; --back) {
|
||||
if(!(*back)->filtered) {
|
||||
(*back)->selected = true;
|
||||
redrawNeeded (*back);
|
||||
selected.push_back (*back);
|
||||
}
|
||||
|
||||
if(!enlarge)
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if PROTECT_VECTORS
|
||||
MYWRITERLOCK_RELEASE(l);
|
||||
#endif
|
||||
selectionChanged ();
|
||||
}
|
||||
|
||||
setScrollPosition (h, v);
|
||||
}
|
||||
|
||||
void ThumbBrowserBase::resizeThumbnailArea (int w, int h) {
|
||||
|
||||
inW = w;
|
||||
@@ -167,7 +298,7 @@ void ThumbBrowserBase::arrangeFiles () {
|
||||
rowHeight = fd[i]->getMinimalHeight ();
|
||||
|
||||
if (arrangement==TB_Horizontal) {
|
||||
|
||||
numOfCols = 1;
|
||||
int numOfRows = 1;
|
||||
// if (rowHeight>0) {
|
||||
// numOfRows = (internal.get_height()+rowHeight/2)/rowHeight;
|
||||
@@ -206,7 +337,7 @@ void ThumbBrowserBase::arrangeFiles () {
|
||||
else {
|
||||
int availWidth = internal.get_width();
|
||||
// initial number of columns
|
||||
int numOfCols = 0;
|
||||
numOfCols = 0;
|
||||
int colsWidth = 0;
|
||||
for (int i=0; i<N; i++)
|
||||
if (!fd[i]->filtered && colsWidth + fd[i]->getMinimalWidth() <= availWidth) {
|
||||
@@ -285,7 +416,7 @@ bool ThumbBrowserBase::Internal::on_query_tooltip (int x, int y, bool keyboard_t
|
||||
MYREADERLOCK(l, parent->entryRW);
|
||||
#endif
|
||||
|
||||
for (size_t i=0; i<parent->fd.size(); i++)
|
||||
for (size_t i=0; i<parent->fd.size(); i++)
|
||||
if (parent->fd[i]->drawable && parent->fd[i]->inside (x, y)) {
|
||||
ttip = parent->fd[i]->getToolTip (x, y);
|
||||
break;
|
||||
@@ -383,18 +514,18 @@ void ThumbBrowserBase::buttonPressed (int x, int y, int button, GdkEventType typ
|
||||
}
|
||||
else {
|
||||
// find the start and the end of the selection interval
|
||||
size_t startx = fd.size()-1;
|
||||
size_t startx = fd.size()-1;
|
||||
if (lastClicked) {
|
||||
for (; startx>0; startx--)
|
||||
for (; startx>0; startx--)
|
||||
if (fd[startx]==lastClicked)
|
||||
break;
|
||||
}
|
||||
else {
|
||||
for (; startx>0; startx--)
|
||||
for (; startx>0; startx--)
|
||||
if (fd[startx]==selected[0])
|
||||
break;
|
||||
}
|
||||
size_t endx = 0;
|
||||
size_t endx = 0;
|
||||
for (; endx<fd.size(); endx++)
|
||||
if (fd[endx]==fileDescr)
|
||||
break;
|
||||
@@ -404,7 +535,7 @@ void ThumbBrowserBase::buttonPressed (int x, int y, int button, GdkEventType typ
|
||||
startx = tmp;
|
||||
}
|
||||
// clear current selection
|
||||
for (size_t i=0; i<selected.size(); i++)
|
||||
for (size_t i=0; i<selected.size(); i++)
|
||||
selected[i]->selected = false;
|
||||
selected.clear ();
|
||||
// select thumbnails in the interval
|
||||
@@ -515,7 +646,7 @@ bool ThumbBrowserBase::Internal::on_button_release_event (GdkEventButton* event)
|
||||
MYREADERLOCK(l, parent->entryRW);
|
||||
#endif
|
||||
|
||||
for (size_t i=0; i<parent->fd.size(); i++)
|
||||
for (size_t i=0; i<parent->fd.size(); i++)
|
||||
if (parent->fd[i]->drawable && parent->fd[i]->insideWindow (0, 0, w, h)) {
|
||||
ThumbBrowserEntryBase* tbe = parent->fd[i];
|
||||
#if PROTECT_VECTORS
|
||||
@@ -539,7 +670,7 @@ bool ThumbBrowserBase::Internal::on_motion_notify_event (GdkEventMotion* event)
|
||||
MYREADERLOCK(l, parent->entryRW);
|
||||
#endif
|
||||
|
||||
for (size_t i=0; i<parent->fd.size(); i++)
|
||||
for (size_t i=0; i<parent->fd.size(); i++)
|
||||
if (parent->fd[i]->drawable && parent->fd[i]->insideWindow (0, 0, w, h)) {
|
||||
/*#if PROTECT_VECTORS
|
||||
MYREADERLOCK_RELEASE(l); // motionNotify calls the queue, which locks
|
||||
@@ -629,7 +760,7 @@ void ThumbBrowserBase::refreshEditedState (const std::set<Glib::ustring>& efiles
|
||||
MYREADERLOCK(l, entryRW);
|
||||
#endif
|
||||
|
||||
for (size_t i=0; i<fd.size(); i++)
|
||||
for (size_t i=0; i<fd.size(); i++)
|
||||
fd[i]->framed = editedFiles.find (fd[i]->filename)!=editedFiles.end();
|
||||
}
|
||||
|
||||
@@ -672,11 +803,11 @@ void ThumbBrowserBase::enableTabMode(bool enable) {
|
||||
#endif
|
||||
hscroll.set_value (min(h, hscroll.get_adjustment()->get_upper()));
|
||||
} else {
|
||||
double v=selected[0]->getStartY();
|
||||
double v=selected[0]->getStartY();
|
||||
#if PROTECT_VECTORS
|
||||
MYREADERLOCK_RELEASE(l);
|
||||
#endif
|
||||
vscroll.set_value (min(v, vscroll.get_adjustment()->get_upper()));
|
||||
vscroll.set_value (min(v, vscroll.get_adjustment()->get_upper()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -705,7 +836,7 @@ int ThumbBrowserBase::getEffectiveHeight() {
|
||||
#endif
|
||||
|
||||
// Filtered items do not change in size, so take a non-filtered
|
||||
for (size_t i=0;i<fd.size();i++)
|
||||
for (size_t i=0;i<fd.size();i++)
|
||||
if (!fd[i]->filtered) {
|
||||
h+=fd[i]->getEffectiveHeight();
|
||||
break;
|
||||
|
Reference in New Issue
Block a user