Creates an instance of AnnounceSubtitleCommand.
The application context.
The text view model.
The audio service.
The text service for mode-aware formatting.
The display service for scope management.
Protected ReadonlycontextProtected ReadonlytextProtected ReadonlyaudioProtected ReadonlytextProtected ReadonlydisplayProtectedrestoreRestores the scope to the previous scope before entering label mode. Uses DisplayService to properly manage the focus stack and restore the correct scope (TRACE, BRAILLE, etc.) regardless of which scope was active before entering label mode.
Only exits when a label scope (TRACE_LABEL or FIGURE_LABEL) is actually active. Every current caller (announce x/y/z/title/subtitle/caption) is bound only inside a label scope, so this guard is defensive: it keeps the command safe if a future keybinding ever invokes it from a non-label scope, where exiting unconditionally would flip navigation into TRACE scope via the stale focus stack and break subplot activation.
ProtectedresolveResolves the populated trace state whose labels (x / y / z) should be announced, regardless of the current navigation level:
Returns null when no populated trace is reachable (e.g. an empty state), so callers can fall back to an "unavailable" announcement.
Unique identifier for the layer/trace
Optionalintersections?: AudioState[] | nullArray of audio states for all lines that intersect at the current point. Used for intersection-aware audio playback in multiline plots. null/undefined for normal points (single line or no intersection).
OptionalgroupCount?: numberNumber of groups/series in the plot. Only present for multiline plots where plotType === 'multiline'.
Optionalgroup?: { label: string; value: string }Label and name of the group/series the cursor is currently on, e.g.
{ label: 'Group', value: 'Series 1' }. Only present for multiline
plots (plotType === 'multiline') whose data names its groups; absent
when the spec authors no names, so consumers can omit group wording
rather than announce a positional placeholder.
Optionalorientation?: OrientationPlot orientation, if applicable (e.g. bar, box, violin).
ProtectedlabelPrefix that names which subplot an announced label belongs to.
At the multi-panel figure lobby the cursor sits on one subplot at a time and each panel may carry different axes, so an axis/level announcement is prefixed with the focused subplot's position (e.g. "Subplot 2, "). Returns an empty string once the user is inside a subplot (trace/subplot level) or in a single-panel figure, where the source is already unambiguous — and in terse mode, which stays minimal by design.
ProtectedfigureThe authored figure-wide axis label to announce at the multi-panel figure lobby, or null when none was authored (so the caller falls back to the focused subplot's own axis). Only applies at the lobby (figure state): once the user is inside a subplot the trace's own axis is authoritative, so this returns null there and existing single-panel behavior is untouched.
Which figure-wide axis label to resolve.
ProtectedannounceShared X/Y axis announcement: an authored figure-wide label wins at the
lobby ("Figure X label is ..."), otherwise the focused subplot's own axis
is used ("Subplot N, X label is ...") — falling through to "not available"
when no populated trace is reachable. Z is intentionally not routed here:
it reads a different field (text.z) with different wording and has no
figure-wide equivalent.
Which axis to announce.
Executes the command to display the subtitle. Accesses subtitle from the figure level via Context, since subtitle is a figure-level property not available on trace state. Only announces when the JSON authored a subtitle; otherwise announces "No subtitle available", matching the unavailable phrasing used by sibling title and caption commands.
Command to describe the subtitle of the figure.