Problem / motivation
The two Companion list panes are siblings, but only one is programmatically queryable for its current selection — a verified API asymmetry.
TagCatalogPane exposes its selection and a deselect mutator, and these are actually consumed by the rest of the Companion:
getSelectedKeys() (libs/FastSenseCompanion/TagCatalogPane.m:213)
getSelectedTags() (:220)
deselectKey(key) (:229)
- Consumers:
FastSenseCompanion.m:1954/1989/2295, CompanionEventViewer.m:1158.
- Its own docstring explains why a getter exists: "the event itself carries no payload" (
:215).
DashboardListPane has no selection query at all. Its public surface is just attach / detach / setTheme / refresh. The current selection lives in the private SelectedIdx_ (libs/FastSenseCompanion/DashboardListPane.m:40), and the pane only fires the payload-free DashboardSelected event (:21).
So there is no way to read which dashboard is currently selected without listening for the event and shadowing the index out-of-band — exactly the bookkeeping TagCatalogPane.getSelectedKeys() was added to eliminate. Verified clean: grep -rnE "getSelectedIdx|getSelectedDashboard" libs/FastSenseCompanion/ returns nothing.
Proposed feature
Give DashboardListPane the dashboard analog of the catalog pane's selection getters:
idx = getSelectedIdx(obj) → 1-based selected row index, or 0 when none selected.
eng = getSelectedDashboard(obj) → the selected DashboardEngine handle, or [] when none / stale.
Optional natural sibling (same theme): deselectDashboard(obj) — the analog of TagCatalogPane.deselectKey, clearing SelectedIdx_ and refreshing the row highlight.
Rough sketch
In libs/FastSenseCompanion/DashboardListPane.m, methods (Access = public):
function idx = getSelectedIdx(obj)
%GETSELECTEDIDX Return the 1-based selected row index (0 = none).
idx = obj.SelectedIdx_;
end
function eng = getSelectedDashboard(obj)
%GETSELECTEDDASHBOARD Return the selected DashboardEngine handle ([] if none).
eng = [];
idx = obj.SelectedIdx_;
if idx >= 1 && idx <= numel(obj.Engines_)
eng = obj.Engines_{idx};
end
end
The engine handles are already snapshotted in the private Engines_ cell (DashboardListPane.m:39), so getSelectedDashboard mirrors how getSelectedTags resolves keys against AllTags_. getSelectedIdx mirrors getSelectedKeys returning SelectedKeys_.
Value
Companion API parity for the dashboard list. The event-only model forces any consumer (the inspector, a test, future tooling that acts on "the selected dashboard") to mirror selection state itself. A read-back getter lets a caller ask the pane directly — and getSelectedDashboard returns the live engine handle ready to act on.
Constraints check
- Toolbox-free: ✅ field read + bounds check + cell index; base primitives only.
- Backward-compatible: ✅ brand-new methods;
attach/detach/refresh/setTheme, the events block, and SelectedIdx_ semantics are untouched. Panes aren't serialized, so no round-trip impact. Existing Companion scripts behave identically.
- Pure MATLAB/Octave: ✅ no
DashboardWidget/Tag contract involved (Companion-internal API).
Effort estimate
S — two tiny getters (plus an optional deselectDashboard mutator) in one file + a test: select row 2 → getSelectedIdx()==2 and getSelectedDashboard() is the right engine handle; no selection → 0/[]; stale index after a shorter refresh → [].
AI-proposed via /feature-scout — needs a human product decision before implementation.
Problem / motivation
The two Companion list panes are siblings, but only one is programmatically queryable for its current selection — a verified API asymmetry.
TagCatalogPaneexposes its selection and a deselect mutator, and these are actually consumed by the rest of the Companion:getSelectedKeys()(libs/FastSenseCompanion/TagCatalogPane.m:213)getSelectedTags()(:220)deselectKey(key)(:229)FastSenseCompanion.m:1954/1989/2295,CompanionEventViewer.m:1158.:215).DashboardListPanehas no selection query at all. Its public surface is justattach / detach / setTheme / refresh. The current selection lives in the privateSelectedIdx_(libs/FastSenseCompanion/DashboardListPane.m:40), and the pane only fires the payload-freeDashboardSelectedevent (:21).So there is no way to read which dashboard is currently selected without listening for the event and shadowing the index out-of-band — exactly the bookkeeping
TagCatalogPane.getSelectedKeys()was added to eliminate. Verified clean:grep -rnE "getSelectedIdx|getSelectedDashboard" libs/FastSenseCompanion/returns nothing.Proposed feature
Give
DashboardListPanethe dashboard analog of the catalog pane's selection getters:idx = getSelectedIdx(obj)→ 1-based selected row index, or0when none selected.eng = getSelectedDashboard(obj)→ the selectedDashboardEnginehandle, or[]when none / stale.Optional natural sibling (same theme):
deselectDashboard(obj)— the analog ofTagCatalogPane.deselectKey, clearingSelectedIdx_and refreshing the row highlight.Rough sketch
In
libs/FastSenseCompanion/DashboardListPane.m,methods (Access = public):The engine handles are already snapshotted in the private
Engines_cell (DashboardListPane.m:39), sogetSelectedDashboardmirrors howgetSelectedTagsresolves keys againstAllTags_.getSelectedIdxmirrorsgetSelectedKeysreturningSelectedKeys_.Value
Companion API parity for the dashboard list. The event-only model forces any consumer (the inspector, a test, future tooling that acts on "the selected dashboard") to mirror selection state itself. A read-back getter lets a caller ask the pane directly — and
getSelectedDashboardreturns the live engine handle ready to act on.Constraints check
attach/detach/refresh/setTheme, theeventsblock, andSelectedIdx_semantics are untouched. Panes aren't serialized, so no round-trip impact. Existing Companion scripts behave identically.DashboardWidget/Tagcontract involved (Companion-internal API).Effort estimate
S — two tiny getters (plus an optional
deselectDashboardmutator) in one file + a test: select row 2 →getSelectedIdx()==2andgetSelectedDashboard()is the right engine handle; no selection →0/[]; stale index after a shorterrefresh→[].AI-proposed via /feature-scout — needs a human product decision before implementation.