Class AbstractBigViewer.AbstractTracer

java.lang.Object
java.awt.event.MouseAdapter
sc.fiji.snt.viewer.AbstractBigViewer.AbstractTracer
All Implemented Interfaces:
MouseListener, MouseMotionListener, MouseWheelListener, EventListener
Enclosing class:
AbstractBigViewer

protected abstract class AbstractBigViewer.AbstractTracer extends MouseAdapter
Viewer-agnostic tracing state machine shared by Bvv and Bdv: manual/A*-assisted path construction from mouse clicks, fork-point resolution against currently rendered paths, single-step segment undo, and the batch-retrace channel/frame lock (see SNT.getBatchRetraceChannelFrame()).

Concrete subclasses supply only the genuinely viewer-specific bits: how a click resolves to a world position, how the path/click-highlight overlays are obtained, how the active channel/frame is derived from the viewer's own source-selection UI, and (optionally) how a status row/undo button reflect tracing state.

  • Field Details

    • tracingSettleUntilMs

      protected volatile long tracingSettleUntilMs
  • Constructor Details

    • AbstractTracer

      protected AbstractTracer(SNT snt)
  • Method Details

    • mousePressed

      public void mousePressed(MouseEvent e)
      Specified by:
      mousePressed in interface MouseListener
      Overrides:
      mousePressed in class MouseAdapter
    • mouseReleased

      public void mouseReleased(MouseEvent e)
      Specified by:
      mouseReleased in interface MouseListener
      Overrides:
      mouseReleased in class MouseAdapter
    • resolveClickWorldPosition

      protected abstract double[] resolveClickWorldPosition(MouseEvent e)
      Resolves the mouse event to a calibrated (x,y,z) world position. Viewer-specific: BVV resolves this via ray-max intensity picking with a focal-plane fallback ; BDV resolves it directly from the orthographic slice cursor position .
      Parameters:
      e - the mouse event that triggered the click
      Returns:
      calibrated world position, or null if it could not be resolved (a message has already been shown to the user in that case)
    • ensurePathOverlay

      protected abstract sc.fiji.snt.viewer.Bvv.PathOverlay ensurePathOverlay()
      Returns the path overlay used to preview/draw the in-progress tempPath, lazily initializing it first if necessary.
    • ensureTracingOverlay

      protected abstract Bvv.AnnotationOverlay ensureTracingOverlay()
      Returns the annotation overlay used to highlight clicked node locations, lazily initializing it first if necessary.
    • clearTracingOverlayContents

      protected abstract void clearTracingOverlayContents()
      Clears the click-highlight overlay's contents, if one has been initialized. No-op otherwise.
    • disposeTracingOverlay

      protected abstract void disposeTracingOverlay()
      Disposes of the click-highlight overlay, if one has been initialized, and forgets it.
    • clearPathOverlayPreview

      protected void clearPathOverlayPreview()
      Refreshes the path overlay so a stale preview segment (from a just-discarded/finished path) is no longer shown, if a path overlay has already been initialized. Deliberately does *not* force lazy initialization (unlike ensurePathOverlay()): if nothing has been drawn yet, there is nothing to clear and no reason to instantiate the overlay machinery early.
    • syncChannelFromActiveSource

      protected abstract void syncChannelFromActiveSource()
      Re-derives the pixel data, calibration, and channel/frame that A* search and path metadata should use, from whichever source is currently "active" in the viewer's own source-selection UI and the viewer's current timepoint. If the current source can't be resolved for any reason (should not normally happen), this should leave whatever image data/channel/frame SNT already had.
    • peekActiveChannelFrame

      protected abstract int[] peekActiveChannelFrame()
      Resolves what syncChannelFromActiveSource() would set channel/frame to, without mutating anything. Used to check whether starting a new path now would change the channel/frame away from one a background batch re-trace is locked to.
      Returns:
      {channel, frame} (1-based), or null if the active source can't be resolved
    • setTracingStatus

      protected void setTracingStatus(boolean busy, String message)
      Updates a tracing status row (progress bar/label + Cancel button), if the viewer has one. No-op by default; overridden by viewers that expose such UI
      Parameters:
      busy - true while a search is ongoing; false to reset to idle
      message - short status text (ignored/cleared when !busy)
    • onManualTraceModeChanged

      protected void onManualTraceModeChanged(boolean manualTraceFlag)
      Notifies the viewer that the manual-vs-A* tracing mode was just toggled, so it can enable/ disable any UI that only makes sense for one mode (e.g. the status row/Cancel button, which only apply to A* search). No-op by default; overridden by viewers with such UI (see
    • updateUndoButtonState

      protected void updateUndoButtonState(boolean hasUndo)
      Notifies the viewer that whether there is a confirmed segment available to undo has changed, so it can enable/disable an Undo button. No-op by default; overridden by viewers with such UI
      Parameters:
      hasUndo - true if undoLastSegment() would currently do something
    • findNearestRenderedPath

      protected Path findNearestRenderedPath(double[] worldPos)
      Finds the rendered Path nearest a 3D world position, restricted to what's currently rendered in this viewer's scene (AbstractBigViewer.getRenderedTrees()) rather than every path in the whole project. Used to auto-select the path a fork click is most likely aimed at, before running the precise fork-point search scoped to just that one path.

      When tree isolation is active (SNT.isTreeIsolationActive()), the isolated arbor is favored: a path in another arbor only wins if it is closer by more than SNTPrefs.NEAREST_PATH_ISOLATION_BIAS, so a pick that just grazes a neighboring structure still resolves to the arbor already in focus

      Parameters:
      worldPos - calibrated (x,y,z) position to search from
      Returns:
      the nearest rendered path, or null if nothing is currently rendered
      See Also:
      • Mirrors InteractiveTracerCanvas#selectNearestPathToMousePointer,
    • getSelectNearestPathAction

      protected AbstractAction getSelectNearestPathAction(boolean addToExistingSelection)
      Builds the G/Shift+G action: selects the rendered path nearest the current cursor position, mirroring InteractiveTracerCanvas#selectNearestPathToMousePointer on the classic canvas. No click is required, resolveClickWorldPosition(java.awt.event.MouseEvent) is called with a null event since both viewer overrides resolve the live cursor position rather than one carried by a MouseEvent
      Parameters:
      addToExistingSelection - true for Shift+G (add to selection), false for G (replace selection)
      See Also:
    • pickRadiusWorld

      protected double pickRadiusWorld(double screenPx)
      Converts a screen-space pixel radius into a world-space distance, using the scale of the current viewer transform. Used to make on-screen "pick" tolerances (e.g. snapping to an existing node to fork from) scale-invariant with respect to zoom.

      Same technique as BvvUtils#colMagnitudes(AffineTransform3D): sum-of-squares of a transform's linear part, applied to the viewer transform rather than a source transform. BVV/BDV viewer transforms are similarity transforms (rotation + uniform scale), so the three columns should agree closely; averaging them is a simplification, not an exact per-axis fix.

      NB> this ignores perspective foreshortening (scale technically also depends on depth along the camera axis in BVV). Good enough here because clicks are first centered onto the focal plane (see Bvv#registerCenterOnDoubleClickListener), where foreshortening is minimal

      Parameters:
      screenPx - the desired pick radius, in screen pixels
      Returns:
      the equivalent world-space distance at the current zoom level, or screenPx unscaled if the viewer transform isn't available (should not normally happen)
    • getFinishPathAction

      protected AbstractAction getFinishPathAction()
      Builds the Enter-key action: finishes the in-progress path, same as a double click, but without the spurious node a double click's own first (clickCount==1) click would leave behind. Deferred via pendingFinish if a segment is still being traced, exactly like the click-based finish path.
    • getDiscardPathAction

      protected AbstractAction getDiscardPathAction()
      Builds the Escape-key action: discards the in-progress path (see discardCurrentPath()) without exiting tracing mode, so the user can immediately start a new path.
    • discardCurrentPath

      protected void discardCurrentPath()
      Discards the current in-progress path: cancels any in-flight segment search, clears tempPath/previousNode and the preview overlay, and resets the tracing status row. Unlike exit(), tracingEnabled is left untouched, so the user stays in tracing mode and can start a new path right away. No-op if tracing is disabled or there is nothing pending.
    • cancelCurrentSearch

      protected void cancelCurrentSearch()
      Cancels the A* search currently in flight (if any), via Future.cancel(boolean). BiSearch's loop already checks for thread interruption, so this actually stops the search. Has no effect during manual tracing (nothing to cancel) or when idle.
    • isPathInProgress

      protected boolean isPathInProgress()
      Returns:
      whether a path is currently in progress on this viewer, i.e. at least one click has landed (see handleClick(MouseEvent)) but the path has not yet been finished (see finishPath()) or discarded (see discardCurrentPath()). Mirrors the same check finishPath() and discardCurrentPath() use internally to decide whether there is anything to commit/discard.
    • updateUndoButtonState

      protected void updateUndoButtonState()
      Recomputes whether anything is currently available to undo and notifies the viewer (see updateUndoButtonState(boolean)). Safe to call at any time, including before any undo-related UI exists.
    • undoLastSegment

      protected void undoLastSegment()
      Undoes the most recently confirmed segment, one click at a time (single-step; no redo). Ported from SNT#undoLastSegment(): pops the last segment's node count off confirmedSegmentSizes and removes that many trailing nodes from tempPath. If that empties tempPath entirely (undone back to the very first point), this falls back to discardCurrentPath(), exactly as the classic 2D canvas cancels the whole path in that case. No-op if tracing is disabled, nothing has been confirmed yet, or a segment is currently being traced (undoing mid-search would race with done()).
    • getUndoSegmentAction

      protected AbstractAction getUndoSegmentAction()
      Builds the undo action shared by an Undo button (if any) and the Cmd/Ctrl+Z hotkey.
      See Also:
    • getExtendSelectedPathAction

      protected AbstractAction getExtendSelectedPathAction()
      Builds the "Continue Extending Path" action: marks the currently selected path as toBeCombinedPath, so the next finished segment is appended onto its last node instead of being registered as a new path (see #combineWithPendingPath). Mirrors InteractiveTracerCanvas's menu item of the same name
    • exit

      protected void exit()
    • getToggleAction

      protected AbstractAction getToggleAction(boolean manualTraceFlag)
      Returns:
      the action for the manual/interactive tracing-mode buttons ("No tracing" has its own getDisableTracingAction()). With the three buttons now in a real, mutually- exclusive ButtonGroup (see installTracingModeButtons(javax.swing.JToggleButton, javax.swing.JToggleButton, javax.swing.JToggleButton)), this action only ever fires when manualTraceFlag's button is newly selected - a radio button that is already selected does not re-fire on click - so unlike the old none-selected-allowed group, there is no "turn off" branch to handle here any more.
    • getDisableTracingAction

      protected AbstractAction getDisableTracingAction()
      Returns:
      the action for the "No tracing" button; see disableTracing().
    • getToggleTracingHoldPressAction

      protected AbstractAction getToggleTracingHoldPressAction()
      Returns:
      the action bound to Space's key-down in Bdv/Bvv. Doesn't act immediately: starts a 200ms timer to tell a quick tap from a genuine hold (decided at key-up by getToggleTracingHoldReleaseAction()) - a tap commits a permanent flip of tracingEnabled (like clicking the button), a hold past the threshold previews "No tracing" for as long as it's held (mirrors the classic canvas's own hold-Space-to-pan convention, see InteractiveTracerCanvas#mousePressed) and snaps back on release. No-op (repeated OS key-repeat "pressed" events while already down are ignored) if a press is already in progress.
    • getToggleTracingHoldReleaseAction

      protected AbstractAction getToggleTracingHoldReleaseAction()
      Returns:
      the action bound to Space's key-up. Stops the pending threshold timer (see getToggleTracingHoldPressAction()) and either restores the pre-hold state (if the threshold was reached and actually engaged a preview), does nothing (threshold reached but nothing was previewed - a hold that started from "No tracing"), or, for a quick tap (threshold never reached), commits a permanent flip of tracingEnabled. The permanent-flip branch is a no-op (with a status message, instead of getToggleAction(boolean)'s blocking error dialog) if turning tracing on isn't currently possible. No-op overall if no press was seen (e.g. focus was lost mid-press, so this release has no matching press).
    • installTracingModeButtons

      protected void installTracingModeButtons(JToggleButton noTracing, JToggleButton manual, JToggleButton interactive)
      Wires the three mutually-exclusive tracing-mode buttons built by the viewer's own toolbar code (e.g. Bvv#sntToolbar/Bdv#sntAnnotationsCard) into this tracer, so setLockedByPause(boolean) can drive their selected/enabled state directly. Call once, right after adding the buttons to their ButtonGroup.
      Parameters:
      noTracing - the "No tracing" button; selected whenever tracingEnabled is false
      manual - the manual-tracing button (see getToggleAction(boolean) with true)
      interactive - the interactive/auto-tracing button (see getToggleAction(boolean) with false)
    • enableTracingExternally

      protected void enableTracingExternally(boolean manual)
      Enables tracing exactly as getToggleAction(boolean)'s own toolbar button would, for callers outside the toolbar itself (see AbstractBigViewer.enableTracing(boolean)).
      Parameters:
      manual - as in getToggleAction(boolean)
    • installExtendPathButton

      protected void installExtendPathButton(JToggleButton button)
      Wires the "Continue Extending Path" toggle button built by the viewer's own toolbar code into this tracer: kept selected for as long as toBeCombinedPath is set, and disabled outright while tracing is off (mirrors installTracingModeButtons(javax.swing.JToggleButton, javax.swing.JToggleButton, javax.swing.JToggleButton)). Call once, right after adding the button to the toolbar
      Parameters:
      button - the "Continue Extending Path" toggle button
      See Also:
      • setToBeCombinedPath(Path)
    • setLockedByPause

      protected void setLockedByPause(boolean locked)
      Locks/unlocks this viewer's tracing-mode buttons to "No tracing", in response to a global SNT_PAUSED/TRACING_PAUSED transition (see SNT#pause(boolean, boolean)/ SNT#pauseTracing(boolean, boolean)) - the Bvv/Bdv counterpart of SNT#setCanvasLabelAllPanes's "Tracing Paused"/"SNT Paused" canvas label for the classic canvas. While locked: tracing is turned off exactly as getDisableTracingAction() would (prompting to finish/discard an unfinished path first), and the manual/interactive buttons are disabled outright - not just deselected - so the user can't click straight back into a state the toolbar would then be lying about (every click is a no-op while paused; see #handleClick's own busy/paused early-return, which bails on these same two states). Unlocking re-enables the buttons but leaves "No tracing" selected by design: whichever mode was active before the pause is not auto-restored - the user re-picks it explicitly.
      Parameters:
      locked - whether a global pause is currently in effect