Problem / motivation
DashboardEngine owns a global TimeRangeSelector_ (the time slider/strip) that, when dragged, syncs the visible window across every widget on every page. But there is no public, programmatic way to set that window. The only entry points are:
resetTimeRange — private, and restores the full DataTimeRange only (libs/Dashboard/DashboardEngine.m:3862).
broadcastTimeRange(t0,t1) — an internal sync helper (:2158) that pans widgets but does not move the selector UI / edge labels / current-view indicator and performs no input validation.
So a scripted workflow that wants to focus the whole dashboard on an incident window [t0,t1] and then export it has no supported API. The dashboard's own integration tests work around this by reaching into the private property: d.TimeRangeSelector_.setSelection(...) (tests/test_dashboard_range_selector_integration.m:48,64).
This is a clean sibling asymmetry. CompanionEventViewer — which wraps a TimeRangeSelector exactly the way DashboardEngine does — already exposes a public, documented, validated, and tested programmatic setter:
% libs/FastSenseCompanion/CompanionEventViewer.m:201
function setTimeRange(obj, tStart, tEnd) % validates: CompanionEventViewer:invalidTimeRange
(tested in tests/suite/TestCompanionEventViewer.m:158,168).
The primary object users script against (DashboardEngine) lacks the equivalent. Individual widgets (FastSenseWidget, GroupWidget) all have setTimeRange; the engine that owns the global selector does not expose a public one.
Proposed feature
Add two public methods to DashboardEngine:
setTimeRange(t0, t1) — set the dashboard's visible/selected time window and sync all widgets across all pages.
getTimeRange() — return the current [t0 t1] selection.
Enables the canonical scripted "focus then export" deliverable, pairing directly with the recently proposed export features (#210 data, #220 events, #221 image-pages):
d.render();
d.setTimeRange(tIncidentStart, tIncidentEnd); % zoom the whole board to the window
d.exportImagePages('incident_%d.png'); % export the focused view
Rough sketch
libs/Dashboard/DashboardEngine.m, mirroring CompanionEventViewer.setTimeRange and reusing the path resetTimeRange already relies on:
function setTimeRange(obj, t0, t1)
%SETTIMERANGE Set the dashboard's visible time window and sync all widgets.
if ~isnumeric(t0) || ~isnumeric(t1) || ~isscalar(t0) || ~isscalar(t1)
error('DashboardEngine:invalidTimeRange', ...
'setTimeRange requires two numeric scalars.');
end
if ~(t1 > t0)
error('DashboardEngine:invalidTimeRange', ...
'setTimeRange requires t1 > t0 (got [%g %g]).', t0, t1);
end
if isempty(obj.TimeRangeSelector_) || ~isa(obj.TimeRangeSelector_, 'TimeRangeSelector')
return; % pre-render: no-op (or stash for apply-on-render)
end
tr = obj.DataTimeRange; % clamp to available data
t0 = max(t0, tr(1)); t1 = min(t1, tr(2));
obj.TimeRangeSelector_.setSelection(t0, t1); % fires OnRangeChanged ->
% debounced broadcastTimeRange ->
% every widget's setTimeRange (all pages)
end
function rng = getTimeRange(obj)
%GETTIMERANGE Current [t0 t1] selection.
if ~isempty(obj.TimeRangeSelector_) && isa(obj.TimeRangeSelector_, 'TimeRangeSelector')
[a, b] = obj.TimeRangeSelector_.getSelection();
rng = [a b];
else
rng = obj.LastSyncedTimeRange_; % fallback
end
end
resetTimeRange then becomes the trivial full-range case (obj.setTimeRange(tr(1), tr(2))), if a follow-up wants to dedupe. The setSelection → OnRangeChanged → SliderDebounceTimer → broadcastTimeRange pipeline is the same one slider drag uses, so the selector UI, edge labels, and current-view indicator all stay correct (unlike calling broadcastTimeRange directly).
Value
High — programmatic focus-then-export is the canonical scripted report-automation workflow for a sensor-analysis engineer reviewing a recording, and it's the missing public counterpart to a method the sibling CompanionEventViewer already ships.
Constraints check
- Toolbox-free: yes — pure MATLAB/Octave; reuses existing
TimeRangeSelector.setSelection/getSelection.
- Backward-compatible: yes — new methods only; no change to serialized dashboards, the
DashboardWidget/Tag contracts, or existing behavior.
- Pure MATLAB/Octave: yes.
Effort estimate
S — two small public methods on DashboardEngine.m reusing an in-repo pattern + one headless test (setTimeRange narrows the selection and reaches widgets; round-trips via getTimeRange; invalid args raise DashboardEngine:invalidTimeRange; clamps to DataTimeRange).
AI-proposed via /feature-scout — needs a human product decision before implementation.
Problem / motivation
DashboardEngineowns a globalTimeRangeSelector_(the time slider/strip) that, when dragged, syncs the visible window across every widget on every page. But there is no public, programmatic way to set that window. The only entry points are:resetTimeRange— private, and restores the fullDataTimeRangeonly (libs/Dashboard/DashboardEngine.m:3862).broadcastTimeRange(t0,t1)— an internal sync helper (:2158) that pans widgets but does not move the selector UI / edge labels / current-view indicator and performs no input validation.So a scripted workflow that wants to focus the whole dashboard on an incident window
[t0,t1]and then export it has no supported API. The dashboard's own integration tests work around this by reaching into the private property:d.TimeRangeSelector_.setSelection(...)(tests/test_dashboard_range_selector_integration.m:48,64).This is a clean sibling asymmetry.
CompanionEventViewer— which wraps aTimeRangeSelectorexactly the wayDashboardEnginedoes — already exposes a public, documented, validated, and tested programmatic setter:(tested in
tests/suite/TestCompanionEventViewer.m:158,168).The primary object users script against (
DashboardEngine) lacks the equivalent. Individual widgets (FastSenseWidget,GroupWidget) all havesetTimeRange; the engine that owns the global selector does not expose a public one.Proposed feature
Add two public methods to
DashboardEngine:setTimeRange(t0, t1)— set the dashboard's visible/selected time window and sync all widgets across all pages.getTimeRange()— return the current[t0 t1]selection.Enables the canonical scripted "focus then export" deliverable, pairing directly with the recently proposed export features (#210 data, #220 events, #221 image-pages):
Rough sketch
libs/Dashboard/DashboardEngine.m, mirroringCompanionEventViewer.setTimeRangeand reusing the pathresetTimeRangealready relies on:resetTimeRangethen becomes the trivial full-range case (obj.setTimeRange(tr(1), tr(2))), if a follow-up wants to dedupe. ThesetSelection → OnRangeChanged → SliderDebounceTimer → broadcastTimeRangepipeline is the same one slider drag uses, so the selector UI, edge labels, and current-view indicator all stay correct (unlike callingbroadcastTimeRangedirectly).Value
High — programmatic focus-then-export is the canonical scripted report-automation workflow for a sensor-analysis engineer reviewing a recording, and it's the missing public counterpart to a method the sibling
CompanionEventVieweralready ships.Constraints check
TimeRangeSelector.setSelection/getSelection.DashboardWidget/Tagcontracts, or existing behavior.Effort estimate
S — two small public methods on
DashboardEngine.mreusing an in-repo pattern + one headless test (setTimeRange narrows the selection and reaches widgets; round-trips via getTimeRange; invalid args raiseDashboardEngine:invalidTimeRange; clamps toDataTimeRange).AI-proposed via /feature-scout — needs a human product decision before implementation.