Skip to content

DashboardEngine: add public setTimeRange(t0,t1) / getTimeRange() to focus the dashboard window programmatically #224

Description

@HanSur94

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:

  • resetTimeRangeprivate, 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.

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions