Skip to content

Commit

Permalink
DrawPathTool: Highlight object that is going to be followed
Browse files Browse the repository at this point in the history
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 <[email protected]>
  • Loading branch information
lpechacek and dl3sdo committed Apr 3, 2024
1 parent f962f35 commit 9467052
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 10 deletions.
70 changes: 60 additions & 10 deletions src/tools/draw_path_tool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -64,6 +65,8 @@
#include "util/util.h"
#include "undo/object_undo.h"

#include <core/symbols/point_symbol.h>


namespace OpenOrienteering {

Expand All @@ -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<LineSymbol>())
, covering_red_dot(std::make_unique<LineSymbol>())
, follow_highlight_symbol(std::make_unique<CombinedSymbol>())
, 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);

Expand Down Expand Up @@ -884,7 +916,7 @@ void DrawPathTool::finishDrawing()
}

dragging = false;
following = false;
finishFollowing();
setEditingInProgress(false);
if (!ctrl_pressed)
angle_helper->setActive(false);
Expand All @@ -900,7 +932,7 @@ void DrawPathTool::finishDrawing()
void DrawPathTool::abortDrawing()
{
dragging = false;
following = false;
finishFollowing();
setEditingInProgress(false);
if (!ctrl_pressed)
angle_helper->setActive(false);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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<PathObject>(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()
Expand Down Expand Up @@ -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();
Expand Down
4 changes: 4 additions & 0 deletions src/tools/draw_path_tool.h
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,10 @@ protected slots:
std::unique_ptr<SnappingToolHelper> snap_helper;

PathObject* append_to_object;
std::unique_ptr<PathObject> followed_path;
std::unique_ptr<LineSymbol> covering_white_dot;
std::unique_ptr<LineSymbol> covering_red_dot;
std::unique_ptr<CombinedSymbol> follow_highlight_symbol;

std::unique_ptr<FollowPathToolHelper> follow_helper;
MapCoordVector::size_type follow_start_index;
Expand Down

0 comments on commit 9467052

Please sign in to comment.