From 1e73135d51938c5bc9731ab20ccc0a2124bfc523 Mon Sep 17 00:00:00 2001 From: Lawrence Lee Date: Fri, 31 Jul 2020 21:58:00 -0700 Subject: [PATCH] Add perspective edit button to toolbar The perspective control lines edit mode no longer piggybacks on the hand tool button on the toolbar. --- rtdata/languages/default | 1 + rtgui/cropwindow.cc | 7 ++-- rtgui/perspective.cc | 25 +++++++++++++ rtgui/perspective.h | 15 ++++++++ rtgui/toolbar.cc | 77 +++++++++++++++++++++++++++++++++++++++- rtgui/toolbar.h | 5 +++ rtgui/toolenum.h | 2 +- rtgui/toolpanelcoord.cc | 33 +++++++++++++++++ rtgui/toolpanelcoord.h | 5 +++ 9 files changed, 165 insertions(+), 5 deletions(-) diff --git a/rtdata/languages/default b/rtdata/languages/default index 9a3402f5f..08c74cc7a 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -1807,6 +1807,7 @@ THRESHOLDSELECTOR_TR;Top-right TOOLBAR_TOOLTIP_COLORPICKER;Lockable Color Picker\n\nWhen the tool is active:\n- Add a picker: left-click.\n- Drag a picker: left-click and drag.\n- Delete a picker: right-click.\n- Delete all pickers: Ctrl+Shift+right-click.\n- Revert to hand tool: right-click outside any picker. TOOLBAR_TOOLTIP_CROP;Crop selection.\nShortcut: c\nMove the crop using Shift+mouse drag. TOOLBAR_TOOLTIP_HAND;Hand tool.\nShortcut: h +TOOLBAR_TOOLTIP_PERSPECTIVE;Perspective Correction\n\nEdit control lines to correct perspective distortion. Click this button again to apply correction. TOOLBAR_TOOLTIP_STRAIGHTEN;Straighten / fine rotation.\nShortcut: s\n\nIndicate the vertical or horizontal by drawing a guide line over the image preview. Angle of rotation will be shown next to the guide line. Center of rotation is the geometrical center of the image. TOOLBAR_TOOLTIP_WB;Spot white balance.\nShortcut: w TP_BWMIX_ALGO;Algorithm OYCPM diff --git a/rtgui/cropwindow.cc b/rtgui/cropwindow.cc index 975bac15c..a862ed122 100644 --- a/rtgui/cropwindow.cc +++ b/rtgui/cropwindow.cc @@ -414,7 +414,8 @@ void CropWindow::buttonPress (int button, int type, int bstate, int x, int y) action_y = 0; needRedraw = true; } - } else if (iarea->getToolMode () == TMHand + } else if ((iarea->getToolMode () == TMHand + || iarea->getToolMode() == TMPerspective) && editSubscriber && cropgl && cropgl->inImageArea(iarea->posImage.x, iarea->posImage.y) @@ -429,7 +430,7 @@ void CropWindow::buttonPress (int button, int type, int bstate, int x, int y) state = SEditPick1; pickedObject = iarea->getObject(); pickModifierKey = bstate; - } else { + } else if (iarea->getToolMode() == TMPerspective) { state = SCropImgMove; } press_x = x; @@ -594,7 +595,7 @@ void CropWindow::buttonPress (int button, int type, int bstate, int x, int y) } } } else if (button == 3) { - if (iarea->getToolMode () == TMHand) { + if (iarea->getToolMode () == TMHand || iarea->getToolMode() == TMPerspective) { EditSubscriber *editSubscriber = iarea->getCurrSubscriber(); if (editSubscriber && editSubscriber->getEditingType() == ET_OBJECTS) { needRedraw = editSubscriber->button3Pressed(bstate); diff --git a/rtgui/perspective.cc b/rtgui/perspective.cc index 395729adb..55013ec4a 100644 --- a/rtgui/perspective.cc +++ b/rtgui/perspective.cc @@ -108,6 +108,7 @@ PerspCorrection::PerspCorrection () : FoldableToolPanel(this, "perspective", M(" EvPerspControlLines = mapper->newEvent(M_VOID, "HISTORY_MSG_PERSP_CTRL_LINE"); lens_geom_listener = nullptr; + panel_listener = nullptr; metadata = nullptr; Gtk::Image* ipers_draw(new RTImage ("draw.png")); @@ -613,6 +614,17 @@ void PerspCorrection::setAdjusterBehavior (bool badd, bool camera_focal_length_a projection_yaw->setAddMode(projection_angle_add); } +void PerspCorrection::setControlLineEditMode(bool active) +{ + // Only camera-based mode supports control lines, so the mode must be + // switched if not in camera-based mode. + if (method->get_active_row_number() != 1) { + method->set_active(1); + } + + lines_button_edit->set_active(active); +} + void PerspCorrection::setMetadata (const rtengine::FramesMetaData* metadata) { this->metadata = metadata; @@ -748,6 +760,9 @@ void PerspCorrection::linesEditButtonPressed(void) lines_button_apply->set_sensitive(true); lines_button_erase->set_sensitive(true); setCamBasedEventsActive(false); + if (panel_listener) { + panel_listener->controlLineEditModeChanged(true); + } } else { // Leave edit mode. setCamBasedEventsActive(true); lines_button_apply->set_sensitive(false); @@ -758,6 +773,9 @@ void PerspCorrection::linesEditButtonPressed(void) } lines->setDrawMode(false); lines->setActive(false); + if (panel_listener) { + panel_listener->controlLineEditModeChanged(false); + } } } @@ -766,6 +784,13 @@ void PerspCorrection::linesEraseButtonPressed(void) lines->removeAll(); } +void PerspCorrection::requestApplyControlLines(void) +{ + if (lines_button_apply->is_sensitive()) { + linesApplyButtonPressed(); + } +} + void PerspCorrection::setCamBasedEventsActive(bool active) { if (active) { diff --git a/rtgui/perspective.h b/rtgui/perspective.h index 0694ccb4e..6ba169b60 100644 --- a/rtgui/perspective.h +++ b/rtgui/perspective.h @@ -25,6 +25,14 @@ #include "lensgeomlistener.h" #include "toolpanel.h" +class PerspCorrectionPanelListener +{ +public: + virtual ~PerspCorrectionPanelListener() = default; + + virtual void controlLineEditModeChanged(bool active) = 0; +}; + class PerspCorrection final : public ToolParamBlock, public AdjusterListener, @@ -79,6 +87,7 @@ protected: rtengine::ProcEvent* event_persp_proj_rotate; rtengine::ProcEvent* event_persp_proj_angle; LensGeomListener* lens_geom_listener; + PerspCorrectionPanelListener* panel_listener; const rtengine::FramesMetaData* metadata; void applyControlLines (void); @@ -101,12 +110,18 @@ public: void linesEditButtonPressed (void); void linesEraseButtonPressed (void); void methodChanged (void); + void requestApplyControlLines(void); void setAdjusterBehavior (bool badd, bool camera_focal_length_add, bool camera_shift_add, bool camera_angle_add, bool projection_angle_add, bool projection_shift_add, bool projection_rotate_add); + void setControlLineEditMode(bool active); void setEditProvider (EditDataProvider* provider) override; void setLensGeomListener (LensGeomListener* listener) { lens_geom_listener = listener; } + void setPerspCorrectionPanelListener(PerspCorrectionPanelListener* listener) + { + panel_listener = listener; + } void setMetadata (const rtengine::FramesMetaData* metadata); void switchOffEditMode (void); void trimValues (rtengine::procparams::ProcParams* pp) override; diff --git a/rtgui/toolbar.cc b/rtgui/toolbar.cc index e642ae51b..5cdfc2787 100644 --- a/rtgui/toolbar.cc +++ b/rtgui/toolbar.cc @@ -77,6 +77,12 @@ ToolBar::ToolBar () : showColPickers(true), listener (nullptr), pickerListener(n pack_start (*straTool); + perspTool = Gtk::manage(new Gtk::ToggleButton()); + Gtk::Image* perspimg = Gtk::manage(new RTImage("perspective-vertical-bottom.png")); + perspTool->set_image(*perspimg); + perspTool->set_relief(Gtk::RELIEF_NONE); + pack_start(*perspTool); + handTool->set_active (true); current = TMHand; @@ -87,12 +93,14 @@ ToolBar::ToolBar () : showColPickers(true), listener (nullptr), pickerListener(n cpConn = colPickerTool->signal_button_press_event().connect_notify( sigc::mem_fun(*this, &ToolBar::colPicker_pressed)); cropConn = cropTool->signal_toggled().connect( sigc::mem_fun(*this, &ToolBar::crop_pressed)); straConn = straTool->signal_toggled().connect( sigc::mem_fun(*this, &ToolBar::stra_pressed)); + perspConn = perspTool->signal_toggled().connect( sigc::mem_fun(*this, &ToolBar::persp_pressed)); handTool->set_tooltip_markup (M("TOOLBAR_TOOLTIP_HAND")); wbTool->set_tooltip_markup (M("TOOLBAR_TOOLTIP_WB")); colPickerTool->set_tooltip_markup (M("TOOLBAR_TOOLTIP_COLORPICKER")); cropTool->set_tooltip_markup (M("TOOLBAR_TOOLTIP_CROP")); straTool->set_tooltip_markup (M("TOOLBAR_TOOLTIP_STRAIGHTEN")); + perspTool->set_tooltip_markup(M("TOOLBAR_TOOLTIP_PERSPECTIVE")); } // @@ -107,9 +115,10 @@ void ToolBar::setTool (ToolMode tool) ConnectionBlocker handBlocker(handConn); ConnectionBlocker straBlocker(straConn); ConnectionBlocker cropBlocker(cropConn); + ConnectionBlocker perspBlocker(perspConn); ConnectionBlocker wbWasBlocked(wbTool, wbConn), cpWasBlocked(colPickerTool, cpConn); - stopEdit = tool == TMHand && handTool->get_active() && editingMode && !blockEdit; + stopEdit = tool == TMHand && (handTool->get_active() || (perspTool && perspTool->get_active())) && editingMode && !blockEdit; handTool->set_active (false); @@ -122,6 +131,9 @@ void ToolBar::setTool (ToolMode tool) if (colPickerTool) { colPickerTool->set_active (false); } + if (perspTool) { + perspTool->set_active(false); + } if (tool == TMHand) { handTool->set_active (true); @@ -138,6 +150,12 @@ void ToolBar::setTool (ToolMode tool) if (colPickerTool) { colPickerTool->set_active (true); } + } else if (tool == TMPerspective) { + if (perspTool) { + perspTool->set_active(true); + // Perspective is a hand tool, but has its own button. + handTool->set_image(*handimg); + } } current = tool; @@ -160,6 +178,7 @@ void ToolBar::startEditMode() ConnectionBlocker handBlocker(handConn); ConnectionBlocker straBlocker(straConn); ConnectionBlocker cropBlocker(cropConn); + ConnectionBlocker perspBlocker(perspConn); ConnectionBlocker wbWasBlocked(wbTool, wbConn), cpWasBlocked(colPickerTool, cpConn); if (current != TMHand) { @@ -172,6 +191,9 @@ void ToolBar::startEditMode() cropTool->set_active (false); straTool->set_active (false); + if (perspTool) { + perspTool->set_active(false); + } current = TMHand; } handTool->set_active (true); @@ -204,6 +226,7 @@ void ToolBar::hand_pressed () ConnectionBlocker handBlocker(handConn); ConnectionBlocker straBlocker(straConn); ConnectionBlocker cropBlocker(cropConn); + ConnectionBlocker perspBlocker(perspConn); ConnectionBlocker wbWasBlocked(wbTool, wbConn), cpWasBlocked(colPickerTool, cpConn); if (editingMode && !blockEdit) { @@ -222,6 +245,9 @@ void ToolBar::hand_pressed () cropTool->set_active (false); straTool->set_active (false); + if (perspTool) { + perspTool->set_active(false); + } handTool->set_active (true); if (current != TMHand) { @@ -244,6 +270,7 @@ void ToolBar::wb_pressed () ConnectionBlocker handBlocker(handConn); ConnectionBlocker straBlocker(straConn); ConnectionBlocker cropBlocker(cropConn); + ConnectionBlocker perspBlocker(perspConn); ConnectionBlocker wbWasBlocked(wbTool, wbConn), cpWasBlocked(colPickerTool, cpConn); if (current != TMSpotWB) { @@ -256,6 +283,9 @@ void ToolBar::wb_pressed () handTool->set_active (false); cropTool->set_active (false); straTool->set_active (false); + if (perspTool) { + perspTool->set_active(false); + } if (colPickerTool) { colPickerTool->set_active(false); } @@ -288,6 +318,9 @@ void ToolBar::colPicker_pressed (GdkEventButton* event) wbTool->set_active (false); } straTool->set_active (false); + if (perspTool) { + perspTool->set_active(false); + } if (current != TMColorPicker) { // Disabling all other tools, enabling the Picker tool and entering the "visible pickers" mode @@ -359,6 +392,7 @@ void ToolBar::crop_pressed () ConnectionBlocker handBlocker(handConn); ConnectionBlocker straBlocker(straConn); ConnectionBlocker cropBlocker(cropConn); + ConnectionBlocker perspBlocker(perspConn); ConnectionBlocker wbWasBlocked(wbTool, wbConn), cpWasBlocked(colPickerTool, cpConn); if (editingMode) { @@ -376,6 +410,9 @@ void ToolBar::crop_pressed () } straTool->set_active (false); + if (perspTool) { + perspTool->set_active(false); + } cropTool->set_active (true); if (current != TMCropSelect) { @@ -399,6 +436,7 @@ void ToolBar::stra_pressed () ConnectionBlocker handBlocker(handConn); ConnectionBlocker straBlocker(straConn); ConnectionBlocker cropBlocker(cropConn); + ConnectionBlocker perspBlocker(perspConn); ConnectionBlocker wbWasBlocked(wbTool, wbConn), cpWasBlocked(colPickerTool, cpConn); if (editingMode) { @@ -416,6 +454,9 @@ void ToolBar::stra_pressed () } cropTool->set_active (false); + if (perspTool) { + perspTool->set_active(false); + } straTool->set_active (true); if (current != TMStraighten) { @@ -432,6 +473,35 @@ void ToolBar::stra_pressed () } } +void ToolBar::persp_pressed () +{ + if (listener && !perspTool->get_active()) { + listener->toolDeselected(TMPerspective); + return; + } + + // Unlike other modes, mode switching is handled by the perspective panel. + { + ConnectionBlocker handBlocker(handConn); + ConnectionBlocker straBlocker(straConn); + ConnectionBlocker cropBlocker(cropConn); + ConnectionBlocker perspBlocker(perspConn); + ConnectionBlocker wbWasBlocked(wbTool, wbConn), cpWasBlocked(colPickerTool, cpConn); + + if (editingMode) { + stopEditMode(); + if (listener) { + listener->editModeSwitchedOff(); + } + } + + } + + if (listener) { + listener->toolSelected(TMPerspective); + } +} + bool ToolBar::handleShortcutKey (GdkEventKey* event) { @@ -485,6 +555,11 @@ void ToolBar::setBatchMode() removeIfThere(this, colPickerTool, false); colPickerTool = nullptr; } + if (perspTool) { + perspConn.disconnect(); + removeIfThere(this, perspTool, false); + perspTool = nullptr; + } allowNoTool = true; switch (current) { diff --git a/rtgui/toolbar.h b/rtgui/toolbar.h index a4525019f..85a0c3345 100644 --- a/rtgui/toolbar.h +++ b/rtgui/toolbar.h @@ -30,6 +30,8 @@ class ToolBarListener public: virtual ~ToolBarListener() = default; + /// Callback when a tool is deselected. WARNING: Not yet called for most tools. + virtual void toolDeselected(ToolMode tool) = 0; /// Callback when a tool is selected virtual void toolSelected(ToolMode tool) = 0; @@ -51,6 +53,7 @@ private: void colPicker_pressed (GdkEventButton* event); void crop_pressed (); void stra_pressed (); + void persp_pressed (); bool showColorPickers(bool showCP); void switchColorPickersVisibility(); @@ -60,6 +63,7 @@ protected: Gtk::ToggleButton* colPickerTool; Gtk::ToggleButton* cropTool; Gtk::ToggleButton* straTool; + Gtk::ToggleButton* perspTool; ToolBarListener* listener; LockablePickerToolListener* pickerListener; ToolMode current; @@ -71,6 +75,7 @@ protected: sigc::connection cpConn; sigc::connection cropConn; sigc::connection straConn; + sigc::connection perspConn; public: ToolBar (); diff --git a/rtgui/toolenum.h b/rtgui/toolenum.h index c3bc873f1..424afca87 100644 --- a/rtgui/toolenum.h +++ b/rtgui/toolenum.h @@ -18,4 +18,4 @@ */ #pragma once -enum ToolMode {TMNone = -1, TMHand = 0, TMSpotWB = 1, TMCropSelect = 2, TMStraighten = 3, TMColorPicker = 4}; +enum ToolMode {TMNone = -1, TMHand = 0, TMSpotWB = 1, TMCropSelect = 2, TMStraighten = 3, TMColorPicker = 4, TMPerspective = 5}; diff --git a/rtgui/toolpanelcoord.cc b/rtgui/toolpanelcoord.cc index d25d6414d..1f4ccce06 100644 --- a/rtgui/toolpanelcoord.cc +++ b/rtgui/toolpanelcoord.cc @@ -282,6 +282,7 @@ ToolPanelCoordinator::ToolPanelCoordinator (bool batch) : ipc (nullptr), favorit lensgeom->setLensGeomListener(this); rotate->setLensGeomListener(this); perspective->setLensGeomListener(this); + perspective->setPerspCorrectionPanelListener(this); distortion->setLensGeomListener(this); crop->setCropPanelListener(this); icm->setICMPanelListener(this); @@ -1045,6 +1046,17 @@ void ToolPanelCoordinator::cropSelectRequested() toolBar->setTool(TMCropSelect); } +void ToolPanelCoordinator::controlLineEditModeChanged(bool active) +{ + if (!ipc) { + return; + } + + if (active) { + toolBar->setTool(TMPerspective); + } +} + void ToolPanelCoordinator::saveInputICCReference(const Glib::ustring& fname, bool apply_wb) { if (ipc) { @@ -1172,6 +1184,13 @@ void ToolPanelCoordinator::updateTPVScrollbar(bool hide) updateVScrollbars(hide); } +void ToolPanelCoordinator::toolDeselected(ToolMode tool) +{ + if (tool == TMPerspective) { + perspective->requestApplyControlLines(); + } +} + void ToolPanelCoordinator::toolSelected(ToolMode tool) { GThreadLock lock; // All GUI access from idle_add callbacks or separate thread HAVE to be protected @@ -1216,6 +1235,20 @@ void ToolPanelCoordinator::toolSelected(ToolMode tool) break; } + case TMPerspective: { + toolBar->blockEditDeactivation(false); // To allow deactivating Locallab when switching to another tool using toolbar + perspective->setControlLineEditMode(true); + perspective->setExpanded(true); + bool isFavorite = checkFavorite(perspective); + if (!isFavorite) { + isFavorite = checkFavorite(lensgeom); + lensgeom->setExpanded(true); + } + toolPanelNotebook->set_current_page(toolPanelNotebook->page_num(isFavorite ? *favoritePanelSW : *transformPanelSW)); + prevPage = toolPanelNotebook->get_nth_page(toolPanelNotebook->get_current_page()); // Updating prevPage as "signal_switch_page" event + break; + } + default: break; } diff --git a/rtgui/toolpanelcoord.h b/rtgui/toolpanelcoord.h index 3889e786c..0dcee59eb 100644 --- a/rtgui/toolpanelcoord.h +++ b/rtgui/toolpanelcoord.h @@ -102,6 +102,7 @@ class ToolPanelCoordinator : public LensGeomListener, public SpotWBListener, public CropPanelListener, + public PerspCorrectionPanelListener, public ICMPanelListener, public ImageAreaToolListener, public rtengine::ImageTypeListener, @@ -323,6 +324,9 @@ public: // croppanellistener interface void cropSelectRequested () override; + // PerspCorrectionPanelListener interface + void controlLineEditModeChanged(bool active) override; + // icmpanellistener interface void saveInputICCReference(const Glib::ustring& fname, bool apply_wb) override; @@ -339,6 +343,7 @@ public: bool handleShortcutKey(GdkEventKey* event); // ToolBarListener interface + void toolDeselected(ToolMode tool) override; void toolSelected (ToolMode tool) override; void editModeSwitchedOff () final;