Skip to content

feat (display/rtplot): extract RTScaledWidgetRepresentation + add show_scale_labels to Tank - #3767

Open
emilioheredia-source wants to merge 1 commit into
ControlSystemStudio:masterfrom
emilioheredia-source:display/rtscaled-tank-refactor
Open

emilioheredia-source wants to merge 1 commit into
ControlSystemStudio:masterfrom
emilioheredia-source:display/rtscaled-tank-refactor

Conversation

@emilioheredia-source

Copy link
Copy Markdown

Summary

Refactors the Tank widget's JavaFX wiring to eliminate the duplication that
existed between TankRepresentation and (the future) RTProgressBarRepresentation,
and adds a new show_scale_labels property to TankWidget and the underlying
YAxisImpl canvas axis.

This PR depends on: tank_scale_refactor (already merged as #3760).
It is recommended to merge this after #3766
(parallel_rendering preference for RTTank), but the two PRs are independent —
each applies cleanly on top of master without the other.
Merging this PR, also sets up the base class and show_scale_labels infrastructure
needed by the RTTank-based Progress Bar refactor, which will be submitted as the next PR.


What Changed

New: RTScaledWidgetRepresentation<W> abstract base class

A generic base for all widget representations whose JFX node is an RTTank.
Handles everything that depends only on the ScaledPVWidget contract:

  • Creating and throttle-configuring the RTTank
  • Forwarding PV value and display-range changes to the tank
  • Evaluating alarm limit lines from PV metadata or widget properties
  • 90° orientation transform for horizontal layout
  • Scheduling representation updates on property changes

Subclasses provide four template methods:

Method Purpose
isHorizontal() Read the widget's own horizontal property
registerLookListeners() Add listeners on widget-specific appearance properties
unregisterLookListeners() Remove those listeners
applyLookToTank(w, h) Push current appearance to the tank

configureTank() is an optional no-op hook called once after tank creation.

Result: TankRepresentation collapses from ~270 lines to ~90 lines of
widget-specific code. RTProgressBarRepresentation (PR3) is ~110 lines.

ScaledPVWidget — new propShowScaleLabels descriptor

show_scale_labels (boolean, default true) is added to ScaledPVWidget
so both Tank and ProgressBar inherit it without duplication.

TankWidget — new show_scale_labels property

Exposes show_scale_labels in the property editor. Default true preserves
existing behaviour.

RTTanksetScaleLabelsVisible(boolean)

Delegates to both YAxisImpl instances (left and right scale). Each axis
fires requestLayout()/requestRefresh() internally via plot_part_listener
when its state changes, so no extra need_layout or requestUpdate() calls
are needed in RTTank.

YAxisImpl — ticks-only rendering mode (show_labels)

Method Behaviour when show_labels = false
getDesiredPixelSize Returns TICK_LENGTH (10 px) immediately — no label metrics computed
getPixelGaps Returns {0, 0} — rotated labels no longer overhang endpoints
paint Skips drawTickLabel and paintLabels; tick marks and axis line draw normally

show_labels is volatile because it is read on the Java2D render thread
and written on the JFX application thread.

setScaleLabelsVisible has an early-return guard to suppress spurious
relayout when the value has not actually changed.

Use case: stacked widgets sharing a single labelled scale


Backward Compatibility

  • Default show_scale_labels=true — existing .bob files load and display
    identically.
  • New XML element <show_scale_labels> is silently ignored by older Phoebus.
  • RTScaledWidgetRepresentation is package-private. No public API change.

Files Changed

RTScaledWidgetRepresentation.java | 343 +++ (new)
TankRepresentation.java | 241 +/--
RTTank.java | 102 ++-
YAxisImpl.java | 38 ++-
ScaledPVWidget.java | 36 ++-
TankWidget.java | 39 +/-
Messages.java | 2 +
messages.properties | 2 +
8 files changed, ~548 insertions, ~255 deletions


Design Decisions

Decision Rationale
show_labels as volatile The field is written on the JFX thread (setScaleLabelsVisible) and read on the Java2D render thread (paint, getDesiredPixelSize). Without volatile the write may not be visible to the render thread.
No extra requestUpdate in setScaleLabelsVisible The YAxisImpl axes call requestLayout()/requestRefresh() themselves when the value changes; these propagate to RTTank.need_layout and requestUpdate() via plot_part_listener. A second explicit call would cause a redundant double-render.
show_scale_labels in ScaledPVWidget Both Tank and ProgressBar benefit from the feature. Placing the descriptor in the base class avoids declaring it twice.
Descriptor only, not a defineProperties entry in ScaledPVWidget Each concrete widget decides whether to expose the property, allowing Tank to default true and a future Meter or Thermometer to choose differently.

@sonarqubecloud

sonarqubecloud Bot commented Apr 4, 2026

Copy link
Copy Markdown

@shroffk

shroffk commented Sep 18, 2026

Copy link
Copy Markdown
Member

This PR depends on: tank_scale_refactor (already merged as #3760).
It is recommended to merge this after #3766

both are merged

this PR is ready to test and merge now

@georgweiss

Copy link
Copy Markdown
Collaborator

@shroffk , will test next week

@shroffk

shroffk commented Sep 18, 2026

Copy link
Copy Markdown
Member

We could also do this at the codeathon

…scale_labels to Tank

Move everything in TankRepresentation that only depends on the
ScaledPVWidget contract into an abstract RTScaledWidgetRepresentation:
creating the RTTank, forwarding value and range updates, evaluating the
alarm limits, the orientation transform and the update scheduling.
TankRepresentation keeps the Tank specific listeners and colors. The
behaviour of the Tank widget does not change.

Add a 'show_scale_labels' property (default true) to the Tank so that
stacked widgets can share one labelled scale: with the property off,
YAxisImpl draws the tick marks and the axis line only. Tick positions
are the same as with labels.

TankWidgetUnitTest covers the new property.
@emilioheredia-source
emilioheredia-source force-pushed the display/rtscaled-tank-refactor branch from 64ee8fb to 6c28558 Compare September 18, 2026 20:38
@emilioheredia-source

Copy link
Copy Markdown
Author

Rebased onto current master (the branch was ~265 commits behind) and squashed into one commit; the diff is what it was, minus the items below.

The rebase turned up one real problem, now fixed: the branch had moved the Tank's border descriptor into ScaledPVWidget under the name border_width, which would have renamed the tank_border_width property that shipped with 5.0.x (that is what TankWidgetUnitTest caught). TankWidget keeps tank_border_width; the shared descriptor moves to #3768 where the new widgets need it.

Other changes since the April version, from a review pass before re-submitting:

  • YAxisImpl.getDesiredPixelSize() did not store the region in ticks-only mode, which could NPE in paint() if the labels were switched on between layout and paint; fixed. Ticks-only width is TICK_LENGTH + 1 so the tick is not clipped by one pixel, and the label layout is skipped in that mode.
  • RTScaledWidgetRepresentation no longer skips the range update on pure value updates (the April version did, with a justification that AxisPart.setValueRange() makes moot); behaviour is now exactly the old TankRepresentation.
  • setInnerPadding()/setFlatTrack() and the configureTank() hook are gone from this PR; nothing here used them, they come with feat (display): RTTank-based Progress Bar backend — scale, alarm limits, and stacking support (opt-in via preference) #3768.
  • The old last commit "remove Activator.parallel_rendering dependency" was dropped: master has that hook through perf(rtplot): add parallel_rendering preference for RTTank UpdateThrottle #3766, so after the rebase it had turned into a revert.
  • TankWidgetUnitTest covers show_scale_labels; French translation added.

Two related PRs, in case it helps to plan the codeathon:

@sonarqubecloud

Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants