From 946705233d4c072c2645e6c2b271442a90a8094b Mon Sep 17 00:00:00 2001 From: Libor Pechacek Date: Wed, 3 Apr 2024 09:56:25 +0200 Subject: [PATCH] DrawPathTool: Highlight object that is going to be followed In complex map situations it is unclear which object will be followed when the user uses the Shift modifier key to follow lines or area object boundaries. This change makes the object selection more obvious. As part of the job we are hardening and making more use of finishFollowing() that removes the highlight renderables for us. Co-authored-by: Matthias Kuehlewein --- src/tools/draw_path_tool.cpp | 70 ++++++++++++++++++++++++++++++------ src/tools/draw_path_tool.h | 4 +++ 2 files changed, 64 insertions(+), 10 deletions(-) diff --git a/src/tools/draw_path_tool.cpp b/src/tools/draw_path_tool.cpp index 82fdd9b3c3..0c6417d9da 100644 --- a/src/tools/draw_path_tool.cpp +++ b/src/tools/draw_path_tool.cpp @@ -51,6 +51,7 @@ #include "core/path_coord.h" #include "core/virtual_coord_vector.h" #include "core/virtual_path.h" +#include "core/symbols/combined_symbol.h" #include "core/symbols/line_symbol.h" #include "core/symbols/symbol.h" #include "core/objects/object.h" @@ -64,6 +65,8 @@ #include "util/util.h" #include "undo/object_undo.h" +#include + namespace OpenOrienteering { @@ -73,9 +76,38 @@ DrawPathTool::DrawPathTool(MapEditorController* editor, QAction* tool_action, bo , angle_helper(new ConstrainAngleToolHelper()) , azimuth_helper(new AzimuthInfoHelper(cur_map_widget, active_color)) , snap_helper(new SnappingToolHelper(this)) +, covering_white_dot(std::make_unique()) +, covering_red_dot(std::make_unique()) +, follow_highlight_symbol(std::make_unique()) , follow_helper(new FollowPathToolHelper()) , allow_closing_paths(allow_closing_paths) { + auto const dot_distance = 500; + + covering_red_dot->setSegmentLength(dot_distance); + covering_red_dot->setMidSymbolsPerSpot(1); + auto* red_dot = new PointSymbol(); // yeah, we are leaking objects here and below -> FIXME + auto* red_color = new MapColor(MapColor::CoveringRed); + red_dot->setInnerColor(red_color); + red_dot->setInnerRadius(150); + covering_red_dot->setMidSymbol(red_dot); + + // We cannot use the outer width dot parameter due to the scaling hack for + // helper colors (PainterConfig::activate() / if (color_priority < 0 && + // color_priority != MapColor::Registration) ...). So we combine two dotted + // lines to get the red dots with white outline. + covering_white_dot->setSegmentLength(dot_distance); + covering_white_dot->setMidSymbolsPerSpot(1); + auto* white_dot = new PointSymbol(); + auto* white_color = new MapColor(MapColor::CoveringWhite); + white_dot->setInnerColor(white_color); + white_dot->setInnerRadius(180); + covering_white_dot->setMidSymbol(white_dot); + + follow_highlight_symbol->setNumParts(2); + follow_highlight_symbol->setPart(0, covering_white_dot.get(), false); + follow_highlight_symbol->setPart(1, covering_red_dot.get(), false); + angle_helper->setActive(false); connect(angle_helper.get(), &ConstrainAngleToolHelper::displayChanged, this, &DrawPathTool::updateDirtyRect); @@ -884,7 +916,7 @@ void DrawPathTool::finishDrawing() } dragging = false; - following = false; + finishFollowing(); setEditingInProgress(false); if (!ctrl_pressed) angle_helper->setActive(false); @@ -900,7 +932,7 @@ void DrawPathTool::finishDrawing() void DrawPathTool::abortDrawing() { dragging = false; - following = false; + finishFollowing(); setEditingInProgress(false); if (!ctrl_pressed) angle_helper->setActive(false); @@ -938,7 +970,10 @@ void DrawPathTool::updateDirtyRect() } if (shift_pressed || (!editingInProgress() && ctrl_pressed)) snap_helper->includeDirtyRect(rect); + includePreviewRects(rect); + if (followed_path) + rectInclude(rect, followed_path->getExtent()); if (is_helper_tool) emit dirtyRectChanged(rect); @@ -1056,6 +1091,15 @@ void DrawPathTool::startFollowing(SnappingToolHelperSnapInfo& snap_info, const M previous_point_is_curve_point = false; updatePreviewPath(); follow_start_index = preview_path->getCoordinateCount() - 1; + + const auto* followed_object = follow_helper->followedObject(); + const auto& part = followed_object->parts()[follow_helper->partIndex()]; + followed_path = std::make_unique(follow_highlight_symbol.get()); + for (auto i = part.first_index; i <= part.last_index; ++i) + followed_path->addCoordinate(followed_object->getCoordinate(i)); + followed_path->update(); + renderables->insertRenderablesOfObject(followed_path.get()); + updateDirtyRect(); } void DrawPathTool::updateFollowing() @@ -1090,17 +1134,23 @@ void DrawPathTool::finishFollowing() { following = false; - auto last = preview_path->getCoordinateCount() - 1; + renderables->removeRenderablesOfObject(followed_path.get(), false); + followed_path.reset(); - previous_point_is_curve_point = (last >= 3 && preview_path->getCoordinate(last - 3).isCurveStart()); - if (previous_point_is_curve_point) + if (preview_path) { - const MapCoord first = preview_path->getCoordinate(last - 1); - const MapCoord second = preview_path->getCoordinate(last); + auto last = preview_path->getCoordinateCount() - 1; - previous_point_direction = -atan2(second.x() - first.x(), first.y() - second.y()); - previous_pos_map = MapCoordF(second); - previous_drag_map = MapCoordF(2*second.x() - first.x(), 2*second.y() + - first.y()); + previous_point_is_curve_point = (last >= 3 && preview_path->getCoordinate(last - 3).isCurveStart()); + if (previous_point_is_curve_point) + { + const MapCoord first = preview_path->getCoordinate(last - 1); + const MapCoord second = preview_path->getCoordinate(last); + + previous_point_direction = -atan2(second.x() - first.x(), first.y() - second.y()); + previous_pos_map = MapCoordF(second); + previous_drag_map = MapCoordF(2*second.x() - first.x(), 2*second.y() + - first.y()); + } } updateAngleHelper(); diff --git a/src/tools/draw_path_tool.h b/src/tools/draw_path_tool.h index 87193c1ff2..56ab276336 100644 --- a/src/tools/draw_path_tool.h +++ b/src/tools/draw_path_tool.h @@ -152,6 +152,10 @@ protected slots: std::unique_ptr snap_helper; PathObject* append_to_object; + std::unique_ptr followed_path; + std::unique_ptr covering_white_dot; + std::unique_ptr covering_red_dot; + std::unique_ptr follow_highlight_symbol; std::unique_ptr follow_helper; MapCoordVector::size_type follow_start_index;