Skip to content

Reliable selection and editing controls (#439, #440-#444) - #521

Closed
Remex9 wants to merge 6 commits into
oss-slu:mainfrom
Remex9:feature/439-selection-editing-controls
Closed

Remex9 wants to merge 6 commits into
oss-slu:mainfrom
Remex9:feature/439-selection-editing-controls

Conversation

@Remex9

@Remex9 Remex9 commented Nov 5, 2026

Copy link
Copy Markdown
Collaborator

Pull Request Summary

Closes #439, Closes #440, Closes #441, Closes #442, Closes #443, Closes #444

Makes selecting and editing objects in the Scene Editor predictable in crowded scenes. There is now one selection for images and annotations. Objects can be selected with the mouse or keyboard, and objects hidden under others can be reached by clicking again. A press only ever moves the selected object. Every edit can be undone and redone, and leaving the editor with unsaved changes now asks first.

PR Checklist

  • Project builds and runs (app run locally and each feature tried in a browser: selection, Tab, clicking through overlaps, dragging a covered image, undo/redo shortcuts)
  • Tests and linters pass (npx jest: 856 passed, 5 skipped; npm run lint clean)
  • Any related documentation has been updated, including JSDoc comments or docstrings

Detailed Description

#440 Select objects

  • state.selection ({ kind: "image" | "annotation", index } or null) replaces the separate image and annotation selection fields, through select/deselect helpers.
  • A click selects the object under it. Escape or a click on empty canvas clears the selection. Clicking a resize or crop handle without dragging no longer deselects the image.
  • Tab / Shift+Tab on the canvas step through objects from the top of the stack down. Past either end, focus leaves the canvas as usual.
  • Each selection is announced, for example Selected label "Ilium", 4 of 5 objects.

#441 Select overlapping objects

  • New objectsAt(scene, point) in sceneCanvas.js lists every drawn object under a point, topmost first. It handles rotated, flipped and cropped images, line hit width, polygon fills, linked annotations, and colored regions clipped to a crop.
  • Clicking again in the same spot selects the next object down, wrapping back to the top. Alt+click steps down from anywhere on the stack.
  • While objects overlap, a hint under the canvas (also announced) says how many there are and how to reach the next one.
  • Selecting or clearing keeps the canvas in place on screen. Before, the toolbar appearing above the canvas moved the scene out from under the pointer.
  • A double-click only opens a label for editing when the clicks left that label selected, so quick clicks keep stepping down the stack.

#442 Move and resize selected objects

  • A press anywhere on the selected object drags it, even where another object is drawn over it. A press on an unselected object never moves anything. This works through [Small Rock] Support Mouse Editing #446's pointer-event press handler.
  • Images get the same keyboard controls as annotations: arrow keys move by 1 (10 with Shift), and Delete or Backspace removes the image. Neither works while a crop is being edited.

#443 Undo and redo

  • Every recorded change to the working copy (images, annotations, import log) becomes an undo step, up to 100. Image src strings are shared between steps, not copied.
  • A run of small edits of one kind (typing a label, color, opacity, arrow-key nudges) undoes as one step. Selecting another object or saving starts a new step.
  • Revision numbers now only count up, so undoing or redoing back to the saved version shows Saved again.
  • There are Undo and Redo buttons next to Save. The shortcuts are Ctrl/Cmd+Z and Ctrl/Cmd+Shift+Z or Ctrl+Y; text fields keep their own undo.
  • History resets when another scene is opened or a version is reloaded, so undo never reaches into another scene.

#444 Warn about unsaved changes

  • The Back button, pressing Scene Editor again, and a scene's "view in the bone viewer" links now ask before leaving when there are unsaved changes.
  • Stay keeps the editor open. Leave keeps the working copy for when the user comes back, so nothing is discarded by leaving. Page close/reload, New, Delete, Duplicate and opening another scene already warned (Saving and restoring scenes #507).

Tests

  • sceneCanvas.test.js: objectsAt covering stacking order, rotation, crop with flip, line tolerance, polygons, undrawable objects, linked annotations, and clipped regions.
  • sceneAnnotationEditor.test.js, a new block for each issue:
    • selection of every type, announcements, and Tab order
    • stepping through overlapping objects, Alt+click, and the hint
    • dragging, nudging and resizing a covered image with a save/reopen round trip, plus no stray moves
    • undo/redo sequences, grouping, saved-state tracking, shortcuts, and scene isolation
    • the leave warning
  • scenes.test.js: "selects an image on click and deselects it on a second click" now expects the image to stay selected, because the second click is used for [Small Rock] Select Overlapping Objects #441.

Known limitations, not changed here

  • Image drags store unrounded coordinates (annotation drags round to 2 decimal places).
  • On an image that is both cropped and flipped, the selection outline sits on the unflipped crop area.
  • Keeping the canvas in place depends on the page being able to scroll. On a very short page it can still shift a few pixels.

🤖 Generated with Claude Code

Remex9 and others added 6 commits November 2, 2026 14:57
- Replace the separate image and annotation selection fields with one
  `state.selection` ({ kind, index } or null) behind select/deselect helpers.
- Clicking an object selects it; clicking it again keeps it selected (the
  second click is reserved for reaching overlapping objects in oss-slu#441).
  Clicking a resize or crop handle without dragging no longer deselects.
- Escape or a click on empty canvas clears the selection for every object type.
- Tab / Shift+Tab on the canvas step through drawn objects from the top of
  the stack down; past either end the selection clears and focus leaves.
- Each selection is announced with its type, label text, and stack position.

Part of oss-slu#439.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Add objectsAt(scene, point) to sceneCanvas.js: every drawn object under a
  scene point, topmost first, matching what renderScene draws (rotated and
  flipped crop areas, line hit width, polygon fill, linked annotations, and
  colored regions clipped to their image's crop).
- Clicking again in the same spot selects the next object down the stack,
  wrapping back to the top; Alt+click steps down from anywhere on the stack.
  A click in a new spot selects the topmost object there.
- While objects overlap, a hint under the canvas (also announced) says how
  many there are and how to reach the next one; it clears on any edit.
- Selecting or clearing keeps the canvas in place on screen, so the toolbar
  that appears above it no longer moves the scene out from under the pointer.
- A double-click only opens a label's text when the clicks left that label
  selected, so quick clicks keep stepping down the stack.

Part of oss-slu#439.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- A press anywhere on the selected object drags it, even where another
  object is drawn over it (an image reached under a highlight with oss-slu#441's
  click-again); a press on any unselected object never moves anything.
- The selected image now has the same keyboard controls as annotations:
  arrow keys move it by 1 scene pixel (10 with Shift), and Delete or
  Backspace removes it (announced). Both are off while a crop is edited.
- Tests cover a crowded scene: dragging, nudging, and resizing a covered
  image, then saving and reopening; drags on unselected objects moving
  nothing; a selected highlight moving under the label drawn on it; and
  deleting images from the keyboard.

Part of oss-slu#439.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…on-editing-controls

# Conflicts:
#	templates/js/scenes.js
#	templates/tests/sceneAnnotationEditor.test.js
- Every recorded change to the working copy (images, annotations, and the
  import log) becomes an undo step, up to 100. Image src strings, which can
  be megabytes of base64, are shared between steps rather than copied.
- A run of small edits of one kind on one object - typing a label, picking a
  color, dragging the opacity slider, nudging with the arrow keys - undoes as
  one step; selecting another object or saving starts a new step.
- Revisions now only count up, so undoing or redoing back to the saved
  version shows "Saved" again, and a new edit after an undo never looks saved.
- Undo and Redo buttons next to Save, plus Ctrl/Cmd+Z and Ctrl/Cmd+Shift+Z or
  Ctrl+Y; text fields keep their own undo. Each step is announced.
- The selected object stays selected if it still exists. History is cleared
  when another scene is opened or a version is reloaded, so undo never
  reaches into another scene.

Part of oss-slu#439.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- The Back button, pressing Scene Editor again, and a scene's "view in the
  bone viewer" links now ask before leaving when the open scene has unsaved
  changes. Choosing to stay keeps the editor open (announced); choosing to
  leave keeps the working copy, which is still there on coming back.
- With everything saved, the editor is left without asking, as before.
- Closing or reloading the page, opening another scene, New, Delete, and
  Duplicate already warned (oss-slu#507); this closes the remaining gap.

Part of oss-slu#439.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@sonarqubecloud

sonarqubecloud Bot commented Nov 5, 2026

Copy link
Copy Markdown

@Remex9 Remex9 closed this Nov 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant