TankWidget: dual scales, alarm limit lines, ScaleFormat enum, and ScaledPVWidget base class#3760
Open
emilioheredia-source wants to merge 7 commits intoControlSystemStudio:masterfrom
Conversation
…ale and outline LogTicks was producing overlapping labels on narrow widgets (such as Tank). Rework the tick-thinning logic so sub-decade ticks (2..9) are suppressed when available pixel height is too small, falling back to power-of-ten labels only. LinearTicks receives a matching minor adjustment for very small ranges. AxisPart gains a minor helper used by the new tank layout. YAxisImpl gains a force_text_up flag (default false). When true the tick labels always read bottom-to-top regardless of the is_right setting. This is needed by RTTank's right-side scale, which is a true YAxisImpl instance set to is_right=true; without force_text_up its labels read top-to-bottom (upside-down from the operator's perspective). RTTank is substantially extended: - Dual independent YAxisImpl instances (left + right) replacing the previous single-axis design. Both share the same range, log mode, format and tick settings. Inspired by CS-Studio BOY's tank that could render markers on both sides of the bar. - Alarm/warning limit lines (LOLO, LO, HI, HIHI) drawn as horizontal lines over the tank body. Lines sourced from PV metadata are solid; manually configured lines are dashed (2 px dash / 4 px gap) so the operator can distinguish the source at a glance. - Tank body outline via drawRoundRect in the foreground color. Edges that lack a neighbouring scale receive a 1 px inset so the outline stroke is not clipped by the canvas boundary. - setLimitsFromPV(), setAlarmColors(), setRightScaleVisible() API. - Constructor init-order fix: right_scale.setOnRight(true) moved after update_throttle creation to avoid a NPE via requestUpdate().
…alarm limits, dual scale, and format controls
ScaledPVWidget (new abstract class, extends PVWidget):
Consolidates properties common to scaled PV monitor widgets, following
the pattern of CS-Studio BOY's AbstractScaledWidget hierarchy.
Properties added on top of PVWidget:
limits_from_pv - use PV display range for min/max (existing)
minimum / maximum - manual display range (existing, moved here)
border_alarm_sensitive - alarm border (existing, repositioned for grouping)
alarm_limits_from_pv - use PV alarm metadata for LOLO/LO/HI/HIHI
show_alarm_limits - draw limit lines on the widget body
level_lolo/lo/hi/hihi - manual alarm thresholds (NaN = inactive)
minor_alarm_color / major_alarm_color - themed alarm line colors
Implementation notes:
* All new properties use types that stock Phoebus already knows
(boolean, double, color) so old versions silently skip unknown XML
elements; no ordinal-based enums are used (BooleanWidgetProperty
throws on ordinals >= 2, which broke round-trips in an earlier
enum-based approach).
* New properties default to values that reproduce existing behavior,
so existing .bob files open with no visual difference.
TankWidget (now extends ScaledPVWidget):
New own properties:
opposite_scale_visible - second scale on the right / bottom side
show_minor_ticks - toggle minor tick marks
perpendicular_tick_labels - rotate tick labels 90 degrees
format - numeric format (DEFAULT, DECIMAL, ...)
precision - decimal places (0-15)
log_scale - logarithmic axis
horizontal - horizontal tank orientation (existing)
TankRepresentation:
Wires all new model properties to RTTank. valueChanged() reads
alarm metadata from the PV (VType -> Display -> warning/alarmRange)
when alarm_limits_from_pv is true, falling back to the manual levels
otherwise. Passes a limitsFromPV flag to RTTank so it can render
PV-sourced limits solid and manual limits dashed.
TankWidgetUnitTest (JUnit 5 + hamcrest, 5 tests):
testScaledPVWidgetDefaults - verifies all ScaledPVWidget property defaults
testTankWidgetDefaults - verifies TankWidget-specific property defaults
testPropertyOrdering - alarm props grouped after max; opposite_scale
adjacent to scale_visible
testXmlRoundTrip - non-default values survive write/read cycle
testNewPropertiesAreOptional - default-valued properties omitted from XML
(backward-compatible with stock Phoebus)
PR_DESCRIPTION.md documents the changes, rationale, backward compatibility
analysis, and design decisions for the pull request.
Add a 'tank_border_width' integer property (default 0, range 0-100 px) to TankWidget. When zero (the default) no border is drawn, preserving the original widget appearance and backward compatibility with existing .bob files. Changes: - RTTank: add border_width field, setBorderWidth(int) setter, and conditional drawRoundRect guarded by border_width > 0 - TankWidget: define propTankBorderWidth descriptor (DISPLAY category, key 'tank_border_width') and expose via propBorderWidth() accessor - TankRepresentation: wire propBorderWidth to tank.setBorderWidth() in register/unregister/updateChanges - TankWidgetUnitTest: assert default=0, round-trip value=3, and that <tank_border_width> is absent at defaults (ModelWriter skips defaults) Property is named 'tank_border_width' rather than re-using the generic 'border_width' (MISC) to avoid unintended interaction with the CSS border mechanism in RegionBaseRepresentation and to keep all tank display properties consistently in the DISPLAY category.
…ANT) Add a new 'Significant' entry to the FormatOption enum that uses Java's %g specifier, matching EDM's GFloat format. Precision controls the total number of significant digits rather than fraction digits. The formatter chooses decimal or exponential notation per value depending on magnitude: sig3: 0.00123 / 1.23 / 123 / 1.23e+04 Wired through FormatOptionHandler (for TextUpdate and other widgets) and RTTank.setLabelFormat (for axis tick labels via a NumberFormat adapter). Tests added in FormatOptionHandlerTest and RTTankTest.
…dgets Introduce ScaleFormat enum in core/ui containing only the format options meaningful for numeric scale axes: DEFAULT, SIGNIFICANT, DECIMAL, EXPONENTIAL, ENGINEERING, COMPACT. Text-only formats (STRING, HEX, BINARY, SEXAGESIMAL) are excluded from the dropdown. Move format and precision properties from TankWidget into ScaledPVWidget so they are reusable by Thermometer, ProgressBar, etc. RTTank.setLabelFormat() now takes ScaleFormat instead of FormatOption. Files changed: - NEW core/ui/.../ScaleFormat.java - MOD app/rtplot/.../RTTank.java - MOD app/display/model/.../ScaledPVWidget.java - MOD app/display/model/.../TankWidget.java - MOD app/rtplot/test/.../RTTankTest.java - MOD app/display/model/test/.../TankWidgetUnitTest.java
When border_width > 0 the stroke is centred on the plot_bounds path, so half the stroke (half_bw = border_width/2) bleeds inward and the top/bottom ticks appeared displaced from the visible tank edge. Fix: expand the layout insets by half_bw on all sides in computeLayout() so the scale's first/last ticks land on the inner edge of the border. The border rect is then shifted outward by half_bw so its inner edge coincides with plot_bounds, keeping ticks, fill, and border visually flush. When border_width = 0 (the default), half_bw = 0 and behaviour is identical to before. fix(rtplot): align tank ticks with inner border edge When border_width > 0 the stroke is centred on the plot_bounds path, so half the stroke (half_bw = border_width/2) bleeds inward and the top/bottom ticks appeared displaced from the visible tank edge. Fix: expand the layout insets by half_bw on all sides in computeLayout() so the scale's first/last ticks land on the inner edge of the border. The border rect is then shifted outward by half_bw so its inner edge coincides with plot_bounds, keeping ticks, fill, and border visually flush. When border_width = 0 (the default), half_bw = 0 and behaviour is identical to before.
|
Author
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.




This PR extends the Tank widget with several features inspired by CS-Studio BOY and adds a new
ScaledPVWidgetabstract base class to avoid property duplication across scale-based widgets.New features:
ScaleFormatenum (DEFAULT,SIGNIFICANT/%g,DECIMAL,EXPONENTIAL,ENGINEERING,COMPACT) applied to tick labels.SIGNIFICANTis also added to the sharedFormatOptionenum for TextUpdate etc.LogTicksreworked to avoid overlapping labels at narrow widths.YAxisImplgains a two-pass visibility algorithm that always preserves the first and last tick labels.tank_border_width(0–5 px, default 0). Border centred on the plot-area boundary;drawRoundRectusesw−1, h−1to correct Java2D's asymmetric fill/draw space.New:
ScaledPVWidgetbase class — sits betweenPVWidgetandTankWidget, consolidatinglimits_from_pv,minimum,maximum,format,precision, and all alarm-limit properties.ThermometerWidgetandProgressBarWidgetalready use the sameCommonWidgetPropertiesdescriptors forlimits_from_pv/minimum/maximum, so migrating them to extendScaledPVWidgetwill be a drop-in change with no.bobformat impact.Backward compatibility — every new property defaults to reproduce the existing behavior (
show_alarm_limits=false,tank_border_width=0,opposite_scale_visible=false,format=DEFAULT).ModelWriteromits default-valued properties, so stock Phoebus silently ignores the new XML elements.TankWidgetUnitTest.testNewPropertiesAreOptional()confirms this.Tests — 5 new
TankWidgetUnitTest, 6 newRTTankTest, 1 newFormatOptionHandlerTestassertion. All 84 display/model and 37 rtplot pre-existing tests pass.