diff --git a/rtdata/images/svg/bidirectional-arrow-horizontal-hicontrast.svg b/rtdata/images/svg/bidirectional-arrow-horizontal-hicontrast.svg new file mode 100644 index 000000000..b41979c6a --- /dev/null +++ b/rtdata/images/svg/bidirectional-arrow-horizontal-hicontrast.svg @@ -0,0 +1,127 @@ + + + + + + + + + + image/svg+xml + + + + + Lawrence + + + + + + + + RawTherapee icon. + + + + + + + + + + + + + + + + + + diff --git a/rtdata/images/svg/bidirectional-arrow-horizontal-prelight.svg b/rtdata/images/svg/bidirectional-arrow-horizontal-prelight.svg new file mode 100644 index 000000000..0ad40b970 --- /dev/null +++ b/rtdata/images/svg/bidirectional-arrow-horizontal-prelight.svg @@ -0,0 +1,127 @@ + + + + + + + + + + image/svg+xml + + + + + Lawrence + + + + + + + + RawTherapee icon. + + + + + + + + + + + + + + + + + + diff --git a/rtdata/images/svg/bidirectional-arrow-vertical-hicontrast.svg b/rtdata/images/svg/bidirectional-arrow-vertical-hicontrast.svg new file mode 100644 index 000000000..18d041279 --- /dev/null +++ b/rtdata/images/svg/bidirectional-arrow-vertical-hicontrast.svg @@ -0,0 +1,127 @@ + + + + + + + + + + image/svg+xml + + + + + Lawrence + + + + + + + + RawTherapee icon. + + + + + + + + + + + + + + + + + + diff --git a/rtdata/images/svg/bidirectional-arrow-vertical-prelight.svg b/rtdata/images/svg/bidirectional-arrow-vertical-prelight.svg new file mode 100644 index 000000000..3dc5034f4 --- /dev/null +++ b/rtdata/images/svg/bidirectional-arrow-vertical-prelight.svg @@ -0,0 +1,127 @@ + + + + + + + + + + image/svg+xml + + + + + Lawrence + + + + + + + + RawTherapee icon. + + + + + + + + + + + + + + + + + + diff --git a/rtgui/perspective.cc b/rtgui/perspective.cc index 1d72011fa..777278419 100644 --- a/rtgui/perspective.cc +++ b/rtgui/perspective.cc @@ -20,6 +20,7 @@ #include "perspective.h" #include "rtimage.h" +#include "rtsurface.h" #include "../rtengine/procparams.h" @@ -704,14 +705,22 @@ ControlLineManager::ControlLineManager(): canvas_area->filled = true; canvas_area->topLeft = Coord(0, 0); mouseOverGeometry.push_back(canvas_area); + + line_icon_h = Cairo::RefPtr(new RTSurface("bidirectional-arrow-horizontal-hicontrast.png")); + line_icon_v = Cairo::RefPtr(new RTSurface("bidirectional-arrow-vertical-hicontrast.png")); + line_icon_h_prelight = Cairo::RefPtr(new RTSurface("bidirectional-arrow-horizontal-prelight.png")); + line_icon_v_prelight = Cairo::RefPtr(new RTSurface("bidirectional-arrow-vertical-prelight.png")); } ControlLineManager::~ControlLineManager() { - for (auto i = mouseOverGeometry.begin(); i != mouseOverGeometry.end(); i++) { - delete *i; - } + delete canvas_area; for (auto i = control_lines.begin(); i != control_lines.end(); i++) { + delete (*i)->begin; + delete (*i)->end; + delete (*i)->line; + delete (*i)->icon_h; + delete (*i)->icon_v; delete *i; } } @@ -780,15 +789,19 @@ bool ControlLineManager::button1Pressed(int modifierKey) const int object = dataProvider->getObject(); if (object > 0) { // A control line. - selected_object = object; - action = Action::DRAGGING; + if (object % ::ControlLine::OBJ_COUNT == 2) { // Icon. + action = Action::PICKING; + } else { + selected_object = object; + action = Action::DRAGGING; + } } else if (draw_mode && (modifierKey & GDK_CONTROL_MASK)) { // Add new line. addLine(dataProvider->posImage, dataProvider->posImage); selected_object = mouseOverGeometry.size() - 1; // Select endpoint. action = Action::DRAGGING; } - return false; + return true; } bool ControlLineManager::button1Released(void) @@ -812,6 +825,42 @@ bool ControlLineManager::button3Pressed(int modifierKey) return false; } +bool ControlLineManager::pick1(bool picked) +{ + action = Action::NONE; + + if (!picked) { + return false; + } + + EditDataProvider* provider = getEditProvider(); + + if (!provider || provider->getObject() % ::ControlLine::OBJ_COUNT != 2) { + return false; + } + + // Change line type. + int object_id = provider->getObject(); + auto line = control_lines[(object_id - 1) / ::ControlLine::OBJ_COUNT]; + + if (line->type == rtengine::ControlLine::HORIZONTAL) { + line->icon = line->icon_v; + line->type = rtengine::ControlLine::VERTICAL; + } else if (line->type == rtengine::ControlLine::VERTICAL) { + line->icon = line->icon_h; + line->type = rtengine::ControlLine::HORIZONTAL; + } + + visibleGeometry[object_id - 1] = line->icon; + + auto state = calcLineState(*line); + line->begin->state = state; + line->end->state = state; + line->line->state = state; + + return true; +} + bool ControlLineManager::pick3(bool picked) { if (!picked) { @@ -824,7 +873,7 @@ bool ControlLineManager::pick3(bool picked) return false; } - removeLine((provider->getObject() - 1) / 3); + removeLine((provider->getObject() - 1) / ::ControlLine::OBJ_COUNT); return false; } @@ -836,8 +885,8 @@ bool ControlLineManager::drag1(int modifierKey) return false; } - ::ControlLine* control_line = control_lines[(selected_object - 1) / 3]; - int component = selected_object % 3; // 0 == end, 1 == line, 2 == begin + ::ControlLine* control_line = control_lines[(selected_object - 1) / ::ControlLine::OBJ_COUNT]; + int component = selected_object % ::ControlLine::OBJ_COUNT; // 0 == end, 1 == line, 2 == icon, 3 == begin Coord mouse = provider->posImage + provider->deltaImage; Coord delta = provider->deltaImage - drag_delta; int ih, iw; @@ -850,7 +899,8 @@ bool ControlLineManager::drag1(int modifierKey) control_line->line->end = control_line->end->center; control_line->end->state = Geometry::DRAGGED; break; - case (1): { // line + case (1): + case (2): { // line // Constrain delta so the end stays above the image. Coord new_delta = control_line->end->center + delta; new_delta.clip(iw, ih); @@ -868,7 +918,7 @@ bool ControlLineManager::drag1(int modifierKey) control_line->line->state = Geometry::DRAGGED; break; } - case (2): // begin + case (3): // begin control_line->begin->center = mouse; control_line->begin->center.clip(iw, ih); control_line->line->begin = control_line->begin->center; @@ -876,6 +926,12 @@ bool ControlLineManager::drag1(int modifierKey) break; } + control_line->icon_h->position.x = (control_line->begin->center.x + control_line->end->center.x) / 2; + control_line->icon_h->position.y = (control_line->begin->center.y + control_line->end->center.y) / 2; + control_line->icon_v->position.x = control_line->icon_h->position.x; + control_line->icon_v->position.y = control_line->icon_h->position.y; + + return false; } @@ -902,19 +958,22 @@ bool ControlLineManager::mouseOver(int modifierKey) } } else if (cur_obj < 0) { // Nothing cursor = CSArrow; + } else if (cur_obj % ::ControlLine::OBJ_COUNT == 2) { // Icon + visibleGeometry[cur_obj - 1]->state = Geometry::PRELIGHT; + cursor = CSArrow; } else { // Object visibleGeometry[cur_obj - 1]->state = Geometry::PRELIGHT; cursor = CSMove2D; } if (prev_obj != cur_obj && prev_obj > 0) { - auto state = calcLineState(*control_lines[(prev_obj - 1) / 3]); + auto state = calcLineState(*control_lines[(prev_obj - 1) / ::ControlLine::OBJ_COUNT]); visibleGeometry[prev_obj - 1]->state = state; } prev_obj = cur_obj; - return false; + return true; } void ControlLineManager::switchOffEditMode(void) @@ -934,6 +993,7 @@ void ControlLineManager::addLine(Coord begin, Coord end) constexpr int line_width = 2; constexpr int handle_radius = 6; Line* line; + OPIcon *icon_h, *icon_v; Circle *begin_c, *end_c; line = new Line(); @@ -942,6 +1002,16 @@ void ControlLineManager::addLine(Coord begin, Coord end) line->begin = begin; line->end = end; + const Cairo::RefPtr null_surface = Cairo::RefPtr(nullptr); + + icon_h = new OPIcon(line_icon_h, null_surface, line_icon_h_prelight, + null_surface, null_surface, Geometry::DP_CENTERCENTER); + icon_h->position = Coord((begin.x + end.x) / 2, (begin.y + end.y) / 2); + + icon_v = new OPIcon(line_icon_v, null_surface, line_icon_v_prelight, + null_surface, null_surface, Geometry::DP_CENTERCENTER); + icon_v->position = Coord((begin.x + end.x) / 2, (begin.y + end.y) / 2); + begin_c = new Circle(); begin_c->datum = Geometry::IMAGE; begin_c->filled = true; @@ -954,20 +1024,29 @@ void ControlLineManager::addLine(Coord begin, Coord end) end_c->radius = handle_radius; end_c->center = begin; + ::ControlLine* control_line = new ::ControlLine(); + control_line->begin = begin_c; + control_line->end = end_c; + control_line->icon_h = icon_h; + control_line->icon_v = icon_v; + if (draw_line_type == rtengine::ControlLine::HORIZONTAL) { + control_line->icon = icon_h; + } else if (draw_line_type == rtengine::ControlLine::VERTICAL) { + control_line->icon = icon_v; + } + control_line->line = line; + control_line->type = draw_line_type; + control_lines.push_back(control_line); + EditSubscriber::visibleGeometry.push_back(line); + EditSubscriber::visibleGeometry.push_back(control_line->icon); EditSubscriber::visibleGeometry.push_back(begin_c); EditSubscriber::visibleGeometry.push_back(end_c); EditSubscriber::mouseOverGeometry.push_back(line); + EditSubscriber::mouseOverGeometry.push_back(control_line->icon); EditSubscriber::mouseOverGeometry.push_back(begin_c); EditSubscriber::mouseOverGeometry.push_back(end_c); - - ::ControlLine* control_line = new ::ControlLine(); - control_line->begin = begin_c; - control_line->end = end_c; - control_line->line = line; - control_line->type = draw_line_type; - control_lines.push_back(control_line); } void ControlLineManager::removeLine(size_t line_id) @@ -982,10 +1061,10 @@ void ControlLineManager::removeLine(size_t line_id) delete line->line; delete line; control_lines.erase(control_lines.begin() + line_id); - visibleGeometry.erase(visibleGeometry.begin() + 3 * line_id, - visibleGeometry.begin() + 3 * line_id + 3); - mouseOverGeometry.erase(mouseOverGeometry.begin() + 3 * line_id + 1, - mouseOverGeometry.begin() + 3 * line_id + 4); + visibleGeometry.erase(visibleGeometry.begin() + ::ControlLine::OBJ_COUNT * line_id, + visibleGeometry.begin() + ::ControlLine::OBJ_COUNT * line_id + ::ControlLine::OBJ_COUNT); + mouseOverGeometry.erase(mouseOverGeometry.begin() + ::ControlLine::OBJ_COUNT * line_id + 1, + mouseOverGeometry.begin() + ::ControlLine::OBJ_COUNT * line_id + ::ControlLine::OBJ_COUNT + 1); } rtengine::ControlLine* ControlLineManager::toControlLines(void) const diff --git a/rtgui/perspective.h b/rtgui/perspective.h index 8a9933b19..5956c20c8 100644 --- a/rtgui/perspective.h +++ b/rtgui/perspective.h @@ -30,7 +30,10 @@ struct ControlLine { + static constexpr int OBJ_COUNT = 4; Line* line; + OPIcon* icon; + OPIcon *icon_h, *icon_v; Circle *begin, *end; rtengine::ControlLine::Type type; }; @@ -47,6 +50,8 @@ protected: std::vector control_lines; CursorShape cursor; bool draw_mode; + Cairo::RefPtr line_icon_h, line_icon_v; + Cairo::RefPtr line_icon_h_prelight, line_icon_v_prelight; int prev_obj; int selected_object; @@ -89,6 +94,7 @@ public: bool button1Pressed (int modifierKey) override; bool button1Released (void) override; bool button3Pressed (int modifierKey) override; + bool pick1 (bool picked) override; bool pick3 (bool picked) override; bool drag1 (int modifierKey) override; CursorShape getCursor (int objectID) const override;