Re-add inspector tab as an option (#5867)

- add option "inspectorWindow" to switch from tab to fullscreen view
- add option "zoomOnScroll" to configure scroll device for zoom or pan
- add both options to preferences
- filepanel creates tab if not inspectorWindow
- inspector adapts to settings inspectorWindow and zoomOnScroll
- filebrowser shows context menu item for inspector only if inspectorWindow
This commit is contained in:
rfranke
2020-08-11 18:27:50 +02:00
parent a449a01690
commit e63b800864
9 changed files with 139 additions and 69 deletions

View File

@@ -85,39 +85,57 @@ InspectorBuffer::~InspectorBuffer() {
Inspector::Inspector () : currImage(nullptr), scaled(false), scale(1.0), zoomScale(1.0), zoomScaleBegin(1.0), active(false), pinned(false), dirty(false)
{
set_name("Inspector");
window.set_visible(false);
window.set_title("RawTherapee Inspector");
window.add_events(Gdk::KEY_PRESS_MASK);
window.signal_key_release_event().connect(sigc::mem_fun(*this, &Inspector::on_key_release));
window.signal_key_press_event().connect(sigc::mem_fun(*this, &Inspector::on_key_press));
if (!options.inspectorWindow) {
window = nullptr;
}
else {
window = new Gtk::Window();
window->set_title("RawTherapee Inspector");
window->set_visible(false);
window->add_events(Gdk::KEY_PRESS_MASK);
window->signal_key_release_event().connect(sigc::mem_fun(*this, &Inspector::on_key_release));
window->signal_key_press_event().connect(sigc::mem_fun(*this, &Inspector::on_key_press));
add_events(Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_MOTION_MASK | Gdk::SCROLL_MASK | Gdk::SMOOTH_SCROLL_MASK);
gestureZoom = Gtk::GestureZoom::create(*this);
gestureZoom->signal_begin().connect(sigc::mem_fun(*this, &Inspector::on_zoom_begin));
gestureZoom->signal_scale_changed().connect(sigc::mem_fun(*this, &Inspector::on_zoom_scale_changed));
add_events(Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_MOTION_MASK | Gdk::SCROLL_MASK | Gdk::SMOOTH_SCROLL_MASK);
gestureZoom = Gtk::GestureZoom::create(*this);
gestureZoom->signal_begin().connect(sigc::mem_fun(*this, &Inspector::on_zoom_begin));
gestureZoom->signal_scale_changed().connect(sigc::mem_fun(*this, &Inspector::on_zoom_scale_changed));
window.add(*this);
window.set_size_request(400, 400);
window.show_all();
window.set_visible(false);
active = true; // always track inspected thumbnails
window->add(*this);
window->set_size_request(500, 500);
initialized = false; // delay init to avoid flickering on some systems
active = true; // always track inspected thumbnails
}
}
Inspector::~Inspector()
{
deleteBuffers();
if (window)
delete window;
}
void Inspector::showWindow(bool scaled, bool fullscreen)
{
if (!window)
return;
// initialize when shown first
if (!initialized) {
window->show_all();
window->set_visible(false);
initialized = true;
}
// show inspector window
this->scaled = scaled;
if (fullscreen)
window.fullscreen();
window->fullscreen();
else
window.unfullscreen();
window->unfullscreen();
this->fullscreen = fullscreen;
window.set_visible(true);
window->set_visible(true);
pinned = false;
// update content when becoming visible
@@ -127,12 +145,15 @@ void Inspector::showWindow(bool scaled, bool fullscreen)
bool Inspector::on_key_release(GdkEventKey *event)
{
if (!window)
return false;
if (!pinned) {
switch (event->keyval) {
case GDK_KEY_f:
case GDK_KEY_F:
zoomScale = 1.0;
window.set_visible(false);
window->set_visible(false);
return true;
}
}
@@ -141,6 +162,9 @@ bool Inspector::on_key_release(GdkEventKey *event)
bool Inspector::on_key_press(GdkEventKey *event)
{
if (!window)
return false;
switch (event->keyval) {
case GDK_KEY_z:
case GDK_KEY_F:
@@ -160,15 +184,15 @@ bool Inspector::on_key_press(GdkEventKey *event)
case GDK_KEY_F11:
// toggle fullscreen
if (fullscreen)
window.unfullscreen();
window->unfullscreen();
else
window.fullscreen();
window->fullscreen();
fullscreen = !fullscreen;
return true;
case GDK_KEY_Escape:
// hide window
zoomScale = 1.0;
window.set_visible(false);
window->set_visible(false);
return true;
}
@@ -177,6 +201,9 @@ bool Inspector::on_key_press(GdkEventKey *event)
bool Inspector::on_button_press_event(GdkEventButton *event)
{
if (!window)
return false;
if (event->type == GDK_BUTTON_PRESS) {
button_pos.set(event->x, event->y);
if (!pinned)
@@ -189,7 +216,7 @@ bool Inspector::on_button_press_event(GdkEventButton *event)
bool Inspector::on_motion_notify_event(GdkEventMotion *event)
{
if (!currImage)
if (!currImage || !window)
return false;
int deviceScale = get_scale_factor();
@@ -211,7 +238,7 @@ bool Inspector::on_motion_notify_event(GdkEventMotion *event)
bool Inspector::on_scroll_event(GdkEventScroll *event)
{
if (!currImage)
if (!currImage || !window)
return false;
bool alt = event->state & GDK_MOD1_MASK;
@@ -244,23 +271,19 @@ bool Inspector::on_scroll_event(GdkEventScroll *event)
break;
case GDK_SCROLL_DOWN:
delta_y = step_y * deviceScale * imH / 100;
alt = true; // zoom for non smooth scroll events (scroll wheel)
break;
case GDK_SCROLL_UP:
delta_y = -step_y * deviceScale * imH / 100;
alt = true; // zoom for non smooth scroll events (scroll wheel)
break;
case GDK_SCROLL_LEFT:
delta_x = step_x * deviceScale * imW / 100;
alt = true; // zoom for non smooth scroll events (scroll wheel)
break;
case GDK_SCROLL_RIGHT:
delta_x = -step_x * deviceScale * imW / 100;
alt = true; // zoom for non smooth scroll events (scroll wheel)
break;
}
if (alt) {
if ((options.zoomOnScroll && !alt) || (!options.zoomOnScroll && alt)) {
// zoom
beginZoom(event->x, event->y);
if (std::fabs(delta_y) > std::fabs(delta_x))
@@ -284,15 +307,15 @@ bool Inspector::on_scroll_event(GdkEventScroll *event)
void Inspector::moveCenter(int delta_x, int delta_y, int imW, int imH, int deviceScale)
{
rtengine::Coord margin; // limit to image size
margin.x = rtengine::min<int>(window.get_width() * deviceScale / scale, imW) / 2;
margin.y = rtengine::min<int>(window.get_height() * deviceScale / scale, imH) / 2;
margin.x = rtengine::min<int>(window->get_width() * deviceScale / scale, imW) / 2;
margin.y = rtengine::min<int>(window->get_height() * deviceScale / scale, imH) / 2;
center.set(rtengine::LIM<int>(center.x + delta_x, margin.x, imW - margin.x),
rtengine::LIM<int>(center.y + delta_y, margin.y, imH - margin.y));
}
void Inspector::beginZoom(double x, double y)
{
if (!currImage)
if (!currImage || !window)
return;
int deviceScale = get_scale_factor();
@@ -303,8 +326,8 @@ void Inspector::beginZoom(double x, double y)
moveCenter(0, 0, imW, imH, deviceScale);
// store center and current position for zooming
dcenterBegin.x = (x - window.get_width()/2) / scale * deviceScale;
dcenterBegin.y = (y - window.get_height()/2) / scale * deviceScale;
dcenterBegin.x = (x - window->get_width()/2) / scale * deviceScale;
dcenterBegin.y = (y - window->get_height()/2) / scale * deviceScale;
centerBegin = center;
zoomScaleBegin = zoomScale;
@@ -319,7 +342,7 @@ void Inspector::on_zoom_begin(GdkEventSequence *s)
void Inspector::on_zoom_scale_changed(double zscale)
{
if (!currImage)
if (!currImage || !window)
return;
zoomScale = rtengine::LIM<double>(zoomScaleBegin * zscale, 0.01, 16.0);
@@ -358,7 +381,7 @@ bool Inspector::on_draw(const ::Cairo::RefPtr< Cairo::Context> &cr)
rtengine::Coord availableSize;
rtengine::Coord topLeft;
rtengine::Coord dest(0, 0);
int deviceScale = get_scale_factor();
int deviceScale = window? get_scale_factor(): 1;
availableSize.x = win->get_width() * deviceScale;
availableSize.y = win->get_height() * deviceScale;
int imW = rtengine::max<int>(currImage->imgBuffer.getWidth(), 1);
@@ -417,19 +440,22 @@ bool Inspector::on_draw(const ::Cairo::RefPtr< Cairo::Context> &cr)
Gdk::RGBA c;
Glib::RefPtr<Gtk::StyleContext> style = get_style_context();
// draw the background
//style->render_background(cr, 0, 0, get_width(), get_height());
///* --- old method (the new method does not seem to work)
c = style->get_background_color (Gtk::STATE_FLAG_NORMAL);
cr->set_source_rgb (c.get_red(), c.get_green(), c.get_blue());
cr->set_line_width (0);
cr->rectangle (0, 0, availableSize.x, availableSize.y);
cr->fill ();
//*/
if (!window) {
// draw the background
style->render_background(cr, 0, 0, get_width(), get_height());
}
else {
///* --- old method (the new method does not seem to work)
c = style->get_background_color (Gtk::STATE_FLAG_NORMAL);
cr->set_source_rgb (c.get_red(), c.get_green(), c.get_blue());
cr->set_line_width (0);
cr->rectangle (0, 0, availableSize.x, availableSize.y);
cr->fill ();
//*/
}
bool scaledImage = scale != 1.0;
if (deviceScale == 1 && !scaledImage) {
if (!window || (deviceScale == 1 && !scaledImage)) {
// standard drawing
currImage->imgBuffer.copySurface(win);
}
@@ -454,14 +480,14 @@ bool Inspector::on_draw(const ::Cairo::RefPtr< Cairo::Context> &cr)
cr->paint();
}
/* --- not for separate window
// draw the frame
c = style->get_border_color (Gtk::STATE_FLAG_NORMAL);
cr->set_source_rgb (c.get_red(), c.get_green(), c.get_blue());
cr->set_line_width (1);
cr->rectangle (0.5, 0.5, availableSize.x - 1, availableSize.y - 1);
cr->stroke ();
*/
if (!window) {
// draw the frame
c = style->get_border_color (Gtk::STATE_FLAG_NORMAL);
cr->set_source_rgb (c.get_red(), c.get_green(), c.get_blue());
cr->set_line_width (1);
cr->rectangle (0.5, 0.5, availableSize.x - 1, availableSize.y - 1);
cr->stroke ();
}
}
return true;
@@ -476,7 +502,7 @@ void Inspector::mouseMove (rtengine::Coord2D pos, int transform)
next_image_pos = pos;
// skip actual update of content when not visible
if (!window.get_visible())
if (window && !window->get_visible())
return;
if (currImage) {
@@ -501,7 +527,7 @@ void Inspector::switchImage (const Glib::ustring &fullPath)
next_image_path = fullPath;
// skip actual update of content when not visible
if (!window.get_visible())
if (window && !window->get_visible())
return;
if (!options.inspectorDelay) {
@@ -601,7 +627,8 @@ void Inspector::setActive(bool state)
flushBuffers();
}
//active = state;
if (!window)
active = state;
}