Skip to content

Annotation toolbar rework - #123

Merged
harleensachdev merged 11 commits into
BodyMaps:mainfrom
harleensachdev:feat/annotation-toolbar-rework
Aug 4, 2026
Merged

Annotation toolbar rework#123
harleensachdev merged 11 commits into
BodyMaps:mainfrom
harleensachdev:feat/annotation-toolbar-rework

Conversation

@harleensachdev

Copy link
Copy Markdown
Collaborator

Summary

Reworks the mask-editing UI (MaskEditPanelAnnotationToolbar + SegmentsPopup), adds several new segment-effect panels, extracts shared primitives (ApplyButton, NumberSliderField, OperationPicker, SliceAnchorPickerUI), refactors the lasso/scissors hooks onto a shared usePolygonDraw core, adds a generic replayable walkthrough system, and reorganizes some files in components/ into viewer/, segmentation/, and walkthrough/ subfolders.

  • Reorganisation: components/ split into viewer/, segmentation/, and walkthrough/ (pure moves — skim only).
  • New shared primitives + CornerstoneNifti2 API additions: maskFilter threaded through cutSegmentWithPolygon, lassoCommitPolygon, runDualScribbleFill, applyHollow, copySegmentAcrossSlices, and interpolateSegmentBetweenSlices; level tracing, morphology, and slice-anchor picking APIs added.
  • Hook refactors: usePolygonDraw extracted as the shared core for useLassoTool/useScissorsTool; useSliceAnchorPicker added; useSmartFill fixed (undo/redo per stroke, maskFilter threaded through); useDraggablePanel resize-jump fix; useKeyboardShortcuts renamed setShowEditPanelsetShowAnnotationToolbar.
  • New panels + walkthrough + SegmentsTable/SegmentsPopup (additive): Margin, Hollow, Islands, Logical Operators, Level Tracing, Grow-from-Seed, Smoothing, Copy Across Slices, Fill Between Slices, plus the generic ToolWalkthrough overlay.
  • AnnotationToolbar + VisualizationPage wiring (highest risk — please focus review time here): MaskEditPanel replaced by AnnotationToolbar; VisualizationPage rewired to the new toolbar, lasso/smart-fill mouse handlers, and morphPicker.
  • Cleanup: Removed the MaskEditPanel directory; SliceJumpInput is now forwardRef'd so the walkthrough can target its real rect.

…d shared primitives

Splits the flat components/ directory into viewer/, segmentation/,
walkthrough/ subfolders and replaces MaskEditPanel with
AnnotationToolbar + SegmentsPopup. Adds new segment-effect panels
(Margin, Hollow, Islands, Logical Ops, Level Tracing, Grow-from-seed,
Smoothing, Copy/Fill slices), shared primitives (ApplyButton,
NumberSliderField, OperationPicker, SliceAnchorPickerUI), and the
generic ToolWalkthrough overlay system.

Note: some files show as delete+add rather than rename since content
changed along with location.

:wq#:wq:wq:wq:wq
…y, and slice-anchor picking APIs

New exports consumed by the annotation toolbar rework:
- MaskFilter threaded through cutSegmentWithPolygon, lassoCommitPolygon,
  runDualScribbleFill, applyHollow, copySegmentAcrossSlices,
  interpolateSegmentBetweenSlices, etc.
- computeLevelTraceMask / commitLevelTraceMask / levelTraceMaskToCanvasPath
- computeLiveWirePath (Dijkstra-based magnetic lasso path)
- pickSliceAnchorAtClientPoint (backs useSliceAnchorPicker)
- getActualHollowMm, IslandsOperation additions

BUGFIX included here: cutSegmentWithPolygon in useScissorsTool was
previously called WITHOUT maskFilter, silently defaulting to
'everywhere' instead of respecting the configured mask. Flagged for
extra review attention.
… hooks

- setShowEditPanel -> setShowAnnotationToolbar throughout.
- editMode 'lasso' now drives usePolygonDraw-backed lasso with
  LiveWireOverlay preview.
- smartFill.handleMouseUp wired onto each pane wrapper's onMouseUp so
  a drag ending outside the originating pane still finalizes the
  stroke.
…AnchorPicker, fix useSmartFill/useDraggablePanel

- usePolygonDraw: shared click-to-place-corners polygon drawing core
  for Lasso and Scissors (optional live-wire magnet, keyboard undo,
  Esc/Enter).
- useSliceAnchorPicker: guided 2-click slice selection for Copy Across
  Slices / Fill Between Slices.
- useSmartFill: wraps each scribble stroke into one undo/redo entry,
  threads maskFilter through, fixes stale-preview bug on fast drags.
- useDraggablePanel: stops reclamping position on plain window resize.
- useKeyboardShortcuts: setShowEditPanel -> setShowAnnotationToolbar
  rename, no behavior change.
- useFocusedPane, useMorphPicker: supporting viewer state hooks.

BEHAVIOR CHANGE: Lasso and Scissors now share undo/cancel/close
semantics via the shared hook.
…ortcuts.ts

Rebase conflict resolution had left raw <<<<<<</=======/>>>>>>> markers
in the committed file, breaking the build with TS1185. Resolved to the
setShowAnnotationToolbar-based version (renamed from setShowEditPanel,
matching the AnnotationToolbar rename) and fixed the now-stale
MaskEditMode import to point at VisualizationPage.tsx, where the type
now lives after MaskEditPanel was removed.
File was committed as ToolWalkThrough.css but imported as
./ToolWalkthrough.css. Case-insensitive on macOS (worked locally),
case-sensitive on Linux CI runners (broke the build).
VisualizationPage.tsx calls buildMaskFilter via useMemo, but the
vi.mock for ../helpers/CornerstoneNifti2 didn't include it, so it
resolved to undefined and threw when called during render.

Add buildMaskFilter to the mock, returning a MaskFilter that
allows all voxels (no masking) — sufficient for the mount smoke
test, which doesn't exercise masking behavior.
…fti2 mocks

VisualizationPage.tsx calls both buildMaskFilter (line 953) and
hasSegmentationVolume (line 2235) unconditionally during render.
Neither test file's CornerstoneNifti2 mock listed them, so they
resolved to undefined and threw when called.

Add both to the mock in viewer.smoke.test.tsx and organStats.test.tsx.
Both test files manually enumerated CornerstoneNifti2's exports in
their vi.mock factories. Every time the module gained a new export
that VisualizationPage.tsx used, the mocks fell out of sync and CI
failed with 'No export defined on mock' — this happened repeatedly
(buildMaskFilter, hasSegmentationVolume, setBrushMaskingScope).

Switch both mocks to spread ...actual from importOriginal, only
overriding the functions that need stubbing for jsdom/no-GPU
environments. New exports now flow through automatically instead
of silently becoming undefined.
@harleensachdev
harleensachdev merged commit d5d7117 into BodyMaps:main Aug 4, 2026
8 checks passed
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.

1 participant