Skip to content

GaugeWidget: draw a Target setpoint/reference marker on the gauge #270

Description

@HanSur94

Problem / motivation

A gauge is the canonical "actual vs. where it should be" widget — it most often
visualizes a controlled quantity: a pressure setpoint, a target RPM, a nominal
temperature, a commanded position. The single most common question an engineer asks a
gauge is "am I at target?"

Today GaugeWidget can show only the current value (a colored arc + needle, across the
arc / donut / bar / thermometer styles) and exposes no way to mark a
target/setpoint/nominal reference
. Verified the public properties are exactly
ValueFcn / Range / Units / StaticValue / Style / Threshold (GaugeWidget.m:9-16);
grep -nE "Target|Setpoint|Marker" over the file returns nothing. The dial therefore
shows a value with nothing to read it against.

This is distinct from the already-filed #235 (ShowZones), which draws threshold
bands (acceptable ranges), and from #232 (Format) and #229 (Reduce). A single explicit
target pip — the bright reference mark on a real pressure gauge — is a different, core
affordance.

Proposed feature

Add an opt-in Target reference marker to GaugeWidget: a static tick drawn on the
gauge at a caller-supplied value, so current-vs-target reads at a glance.

w = GaugeWidget('Sensor', pressureTag, 'Range', [0 100], ...
                'Units', 'bar', 'Target', 75);   % draws a reference pip at 75

Rough sketch

  • Lib / class: libs/Dashboard/GaugeWidget.m (single file).
  • Public API:
    • Target = [] — numeric scalar in Range units. Default []no marker
      (byte-identical to today). Optionally accept a 1xN vector for multiple pips
      (low/high commanded band) — scalar is the MVP.
    • TargetColor = [] — default → theme accent / sensible contrast color.
  • Render: in each render* style, after the background arc/track is drawn, map
    Target through the same value→fraction→angle mapping the needle / foreground arc
    already use (renderArc 240-deg sweep, 210-deg→-30-deg, GaugeWidget.m:341-352;
    analogous linear maps in renderBar / renderThermometer / renderDonut) and draw one
    short radial tick:
    line(obj.hAxes, [rInner rOuter]*cos(thetaTarget), [rInner rOuter]*sin(thetaTarget), 'Color', targetColor, 'LineWidth', 2)
    for the radial styles; a straight tick for bar / thermometer. Clamp to Range; skip
    cleanly when Target is [], NaN, or Range is empty/degenerate.
    • The marker is static (set once at render), so it adds zero per-tick cost — it
      does not touch the update* fast path and cannot degrade live refresh.
  • Serialize: emit s.target / s.targetColor in toStruct (GaugeWidget.m:176-193)
    only when non-default; read with isfield guards in fromStruct (:195-) defaulting to
    [] — exactly the range/units/style round-trip pattern already in the file. Old
    saves load with no marker and render unchanged.
  • Test: Target=75 with Range=[0 100] places the tick at the 75% sweep angle;
    Target=[] renders byte-identically to today; the value round-trips through serialization.

Value

High. The setpoint-vs-actual read is arguably the reason an engineer reaches for a gauge
rather than a NumberWidget. The marker closes that core gap with a familiar affordance and
composes cleanly with #235 (ShowZones bands = acceptable ranges) and #232 (Format).

Constraints check

  • Toolbox-free: ✅ only base line / cos / sin / fill.
  • Backward-compatible: ✅ default Target = [] → no marker, identical render; serialized
    dashboards untouched (non-default-only emit + isfield guards on load).
  • Pure MATLAB/Octave: ✅ no toolbox calls; works through the existing DashboardWidget
    contract (no base-class or layout change).
  • Performance: ✅ static marker drawn once at render; does not touch the live update*
    path → no refresh-rate impact.

Effort estimate

S — single file: two public props + a small drawTarget_ helper called from each
render* style + a toStruct/fromStruct round-trip + one test.


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