Skip to content

Map toolbar: long-press + flyout for line, rectangle, circle geometry helpers#11

Draft
tordans wants to merge 2 commits into
masterfrom
cursor/geometry-flyout-plus-4108
Draft

Map toolbar: long-press + flyout for line, rectangle, circle geometry helpers#11
tordans wants to merge 2 commits into
masterfrom
cursor/geometry-flyout-plus-4108

Conversation

@tordans

@tordans tordans commented May 31, 2026

Copy link
Copy Markdown
Owner

Problem

As a mapper, I want to long-press the + toolbar button and choose Line, Rectangle, or Circle so I can start structured way/area work on the map—without only dropping isolated nodes via a single short tap.

Today, short tap on + adds a node at the crosshair (same as right-click). Long-press on + previously did nothing useful after 0.5s. The display/layers button already uses a long-press action sheet; + should follow that pattern for geometry tools.


User interaction

Short press + (unchanged)

  • Duration < 0.5s, finger released inside the button → rightClick at crosshair → existing addNode / way-extension behavior.

Long press + (new)

  • Duration ≥ 0.5s, released inside the button → UIAlertController action sheet:
    • Line · Rectangle · Circle · Cancel
  • Cancel dismisses with no map state change.
  • Popover anchor: addNodeButton (iPad).

Dedicated map edit mode

Choosing a tool enters a geometry mode separate from normal single-tap node placement:

Tool Taps Result
Line Successive map taps at crosshair Open way via existing extendSelectedWay / addNode
Rectangle 3 crosshair taps (3 corners) Closed way; 4th corner computed with right-angle constraint
Circle 2 crosshair taps (diameter endpoints) Closed way approximating a circle (24 segments)

Vertices are placed at viewPort.screenCenterPoint() (crosshair), not at the finger location—consistent with how + targets the crosshair.

Live preview (rubber band)

Orange dashed CAShapeLayer on EditorMapLayer, updated on map pan/zoom via mapTransform.onChange:

  • Line: segment from last fixed point (pushpin anchor) to crosshair.
  • Rectangle: after tap 1 → segment to crosshair; after tap 2 → full rectangle preview toward crosshair with right angles preserved (3rd corner projected onto perpendicular through corner B).
  • Circle: after tap 1 → circle preview with crosshair as moving diameter endpoint.

Cancel / finish

  • Cancel mode: tap another object (selectObjectAtPoint calls cancelGeometryDraw()), or Undo for partial edits.
  • Line: no explicit “finish” button; mode stays active until cancel; closing a way by joining ends uses existing extendSelectedWay join logic.
  • Rectangle / circle: auto-commit on final tap; mode clears after shape creation.

Hold + while tapping map

If the user holds + and taps the map (existing gesture), geometry mode routes to geometryDrawTap(at: crosshair) instead of addNode(at: finger).


Implementation notes (by Cursor)

Phase A — UI (MainViewController)

  • plusButtonLongPressHandler: on .ended, if duration ≥ 0.5s and touch inside button → presentGeometryDrawFlyout().
  • Short-press path unchanged (< 0.5s → crosshair node).
  • Action sheet mirrors displayButtonLongPressHandler() pattern.

Phase B — Line mode

  • beginGeometryDraw(.line) places pushpin at crosshair; each map tap calls addNode(at:) (reuses extendSelectedWay).

Phase C — Rectangle / circle

  • GeometryDrawMath.swift — pure math (testable): rectangleCorners(cornerA:cornerB:thirdPointHint:), circleRing(diameterA:diameterB:), lat/lon plane helpers via lat2latp / latp2lat.
  • EditorMapLayer+GeometryDraw.swift — state (geometryDrawTool, geometryDrawFixedCorners, preview layer), tap handlers, commitClosedWay for rectangle/circle.
  • Preview subscription uses dedicated geometryDrawPreviewToken so onChange.unsubscribe does not remove the layer’s main layout observer.

Map routing (MapView)

  • handleTapGesture: if isGeometryDrawActivegeometryDrawTap(at: screenCenter).
  • rightClick: same when geometry mode active.
  • beginGeometryDraw(_:) entry point from flyout.

Tests

  • GeometryDrawMathTestCase: right angles on rectangle, perpendicular projection, circle radius, rubber-band polyline.

Files changed

File Role
MainViewController.swift Long-press threshold, action sheet
MapView.swift Tap/right-click routing, beginGeometryDraw
EditorMapLayer.swift Geometry draw state + preview token
EditorMapLayer+GeometryDraw.swift Mode machine, preview, commit
EditorMapLayer+Edit.swift Cancel geometry on object selection
GeometryDrawMath.swift Pure geometry
GeometryDrawMathTestCase.swift Unit tests
project.pbxproj New sources

Testing notes (by @tordans)

  1. Short tap + — node at crosshair; behavior matches baseline.
  2. Long-press + < 0.5s — still short tap (no sheet).
  3. Long-press + ≥ 0.5s → sheet; Cancel → no change.
  4. Line: 3–4 vertices; rubber-band follows crosshair; Undo steps back; select another object exits mode.
  5. Rectangle: 3 taps; preview stays rectangular while moving crosshair after tap 2; committed way is closed with 4 corners + closing node.
  6. Circle: 2 taps; preview circle; committed closed way looks circular at street zoom.
  7. Portrait + landscape + external display if available.
  8. Cancel mid-flow — preview layer removed, no stuck mode.
  9. Hold + and tap map during line mode — vertex at crosshair.
  10. Memory — cancel mid-rectangle; no leaked CAShapeLayer.
Open in Web Open in Cursor 

Long-press the map toolbar + button (≥0.5s) to open an action sheet with
Line, Rectangle, and Circle tools. Short press behavior is unchanged.

Each tool enters a dedicated map edit mode with rubber-band preview tied
to the crosshair. Rectangle and circle math live in GeometryDrawMath with
unit tests. Line mode reuses extendSelectedWay via successive crosshair taps.

Co-authored-by: Tobias <t@tobiasjordans.de>
@tordans tordans closed this Jun 6, 2026
@tordans tordans reopened this Jun 6, 2026
@cursor cursor Bot changed the title Long-press + flyout: line, rectangle, circle geometry tools Long-press + flyout (line/rectangle/circle) and localized kind labels on map Jun 6, 2026
@cursor cursor Bot force-pushed the cursor/geometry-flyout-plus-4108 branch from c4f3c0f to ed41fd1 Compare June 6, 2026 16:59
@cursor cursor Bot changed the title Long-press + flyout (line/rectangle/circle) and localized kind labels on map Map toolbar: long-press + flyout for line, rectangle, circle geometry helpers Jun 6, 2026
- Route map taps through geometryDrawHandleMapTap: hit object to cancel/select,
  empty map tap places vertex at crosshair
- Cancel geometry mode on long-press selection and on undo
- Group rectangle/circle commit into single undo step; rollback group on error
- Update flash hints to describe tap-object-to-cancel

Co-authored-by: Tobias <t@tobiasjordans.de>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants