Commit 87015be
Add crosshair-link toggle to FastSense dashboard widgets (260602-mri) (#184)
* feat(260602-mri-01): CrosshairLinked property + HoverCrosshair broadcast hook
- FastSenseWidget: add CrosshairLinked=false public property, setCrosshairLink(tf)
setter (validates logical/0/1, throws FastSenseWidget:invalidCrosshairLink),
toStruct omits field when false (legacy JSON byte-identical), fromStruct
restores flag pre-render (no graphics touch)
- HoverCrosshair: add BroadcastFcn_/BroadcastLeaveFcn_ callbacks + setBroadcastFcn;
onMoveExternal(x) sets SuppressLeaveUntil_=tic then drives onMove with
InBroadcast_=true; onLeaveExternal() clears suppress + hides; onMove fires
BroadcastFcn_ at tail; onLeave honors SuppressWindow_ guard and fires
BroadcastLeaveFcn_ when source leaves; delete() nulls callbacks first
- tests/test_fastsense_crosshair_link.m: 11 cases (6 PURE + 1 pure-engine +
2 render-guarded suppress-leave proof + broadcast-reentry proof +
2-widget mirror integration)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* feat(260602-mri-02): DashboardEngine active-page crosshair-link coordination
- collectLinkedCrosshairs_(widgets): pure flattening helper (public);
returns cell of {widget,hc} structs for linked+rendered FastSenseWidgets
- rewireCrosshairLinks_(): clears all active-page broadcast hooks then
re-primes linked crosshairs with engine broadcast closures
- broadcastCrosshairX_(sourceHc, x): mirrors data-x onto all OTHER linked
crosshairs via onMoveExternal
- broadcastCrosshairLeave_(sourceHc): tells all OTHER linked crosshairs to
hide via onLeaveExternal
- onCrosshairLinkToggle(widget): re-derives full active-page link set
- rewireCrosshairLinks_ called after rerenderWidgets, switchPage, detachWidget
(260512-eu2 re-establish-after-rerender lesson)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* feat(260602-mri-03): Crosshair-link 'X' toggle button on WidgetButtonBar
- DashboardLayout.realizeWidget: inject CrosshairLinkButton via
ismethod(widget,'setCrosshairLink') duck-type after addPlantLogToggle,
before final reflowChrome_
- addCrosshairLinkToggle(widget): idempotent 24x24 'X' pushbutton;
highlighted when CrosshairLinked=true via chooseYLimitActiveBg_;
calls onCrosshairLinkTogglePressed_ on click; tails with reflowChrome_
for callback-driven rebuilds
- onCrosshairLinkTogglePressed_: toggles CrosshairLinked, calls
EngineRef.onCrosshairLinkToggle, rebuilds button look; try/catch +
warning + non-blocking uialert mirrors addPlantLogToggle pattern
- reflowChrome_: re-anchors CrosshairLinkButton as LEFTMOST chrome button
(xVisible - gap - bw, left of V/A cluster) after resize
- DashboardWidget.clearPanelControls: add 'CrosshairLinkButton' to
protectedTags so button survives re-render sweeps
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* docs(260602-mri-01): complete crosshair-link plan SUMMARY
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix(260602-mri-04): deterministic crosshair-link suppress + leave-recursion fix
Orchestrator live-MATLAB verification found the suppress-leave tic-window
(SuppressLeaveUntil_/SuppressWindow_) was flaky: it depends on wall-clock
elapsed time inside a synchronous motion dispatch, so the crux test passed
in isolation (6.7ms) but failed in the full suite. Replaced with a
deterministic IsMirrored_ boolean - set by onMoveExternal, cleared when the
widget becomes the hover source (real onMove) or via onLeaveExternal.
Also fixes a latent unbounded leave ping-pong: onLeaveExternal now hides
directly via a new private hideGraphics_ helper instead of re-entering the
broadcasting onLeave (which would recurse across >=2 linked widgets and hang).
Test fixes: collectLinkedCrosshairs_ enumeration passes the widget list as a
parameter, and the 2-widget integration test uses addWidget(), since
DashboardEngine.Widgets is SetAccess=private.
Verified R2025a: test_fastsense_crosshair_link 11/11; regressions green
(test_hover_crosshair 11/11, test_fastsense_widget_ylimit_modes 11/11,
test_time_range_selector_reinstall_after_rerender pass,
test_dashboard_time_sync_all_pages 5/5); MISS_HIT clean; live UI smoke pass.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* docs(quick-260602-mri): crosshair-link toggle — plan, summary, state
Quick task 260602-mri complete and verified (R2025a live MATLAB):
a crosshair-link 'X' toggle on the FastSense widget grey bar mirrors the
hover crosshair across all FastSense widgets on the active dashboard page.
- PLAN.md: the executable plan (3 tasks) — now tracked
- SUMMARY.md: updated for the deterministic IsMirrored_ suppress redesign,
the latent leave-recursion fix, and the green test/lint/live-smoke results
- STATE.md: Quick Tasks Completed row + last-activity line
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>1 parent be70d4b commit 87015be
9 files changed
Lines changed: 1197 additions & 4 deletions
File tree
- .planning
- quick/260602-mri-add-crosshair-link-toggle-to-fastsense-w
- libs
- Dashboard
- FastSense
- tests
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
27 | 27 | | |
28 | 28 | | |
29 | 29 | | |
30 | | - | |
| 30 | + | |
31 | 31 | | |
32 | 32 | | |
33 | 33 | | |
| |||
96 | 96 | | |
97 | 97 | | |
98 | 98 | | |
| 99 | + | |
99 | 100 | | |
100 | 101 | | |
101 | 102 | | |
| |||
0 commit comments