From f8f5960b9698813db13de48296ed2369db38ccc3 Mon Sep 17 00:00:00 2001 From: Sky Brewer Date: Thu, 5 Mar 2026 14:21:04 +0100 Subject: [PATCH] Add support for modifying the opacity and area color Adds two new columns to the traces: - AreaOpacity Which sets the opacity for the area, keeping the color from the trace - AreaColor Which is by default the trace color with the opacity from the AreaOpacity This allows the user when looking at more spiky data to easily see the min, max peaks. Right now mostly they resort to swapping to raw data. --- .../trends/databrowser3/Messages.java | 4 ++ .../trends/databrowser3/model/ModelItem.java | 44 +++++++++++++++++++ .../databrowser3/ui/plot/ModelBasedPlot.java | 1 + .../ui/properties/ChangeAreaColorCommand.java | 43 ++++++++++++++++++ .../properties/ChangeAreaOpacityCommand.java | 42 ++++++++++++++++++ .../databrowser3/ui/properties/TracesTab.java | 35 +++++++++++++++ .../trends/databrowser3/messages.properties | 4 ++ .../org/csstudio/javafx/rtplot/RTPlot.java | 41 ++++++++++++----- .../org/csstudio/javafx/rtplot/Trace.java | 6 +++ .../csstudio/javafx/rtplot/internal/Plot.java | 2 +- .../javafx/rtplot/internal/TraceImpl.java | 30 +++++++++++++ .../javafx/rtplot/internal/TracePainter.java | 5 +-- 12 files changed, 242 insertions(+), 15 deletions(-) create mode 100644 app/databrowser/src/main/java/org/csstudio/trends/databrowser3/ui/properties/ChangeAreaColorCommand.java create mode 100644 app/databrowser/src/main/java/org/csstudio/trends/databrowser3/ui/properties/ChangeAreaOpacityCommand.java diff --git a/app/databrowser/src/main/java/org/csstudio/trends/databrowser3/Messages.java b/app/databrowser/src/main/java/org/csstudio/trends/databrowser3/Messages.java index fc784ba6ac..d4f801f09b 100644 --- a/app/databrowser/src/main/java/org/csstudio/trends/databrowser3/Messages.java +++ b/app/databrowser/src/main/java/org/csstudio/trends/databrowser3/Messages.java @@ -37,6 +37,10 @@ public class Messages AddPV_PeriodTT, AppendSearchResults, AppendSearchResultsTT, + AreaColor, + AreaColorTT, + AreaOpacity, + AreaOpacityTT, ArchiveFetchDetailFmt, ArchiveFetchJobFmt, ArchiveFetchProgressFmt, diff --git a/app/databrowser/src/main/java/org/csstudio/trends/databrowser3/model/ModelItem.java b/app/databrowser/src/main/java/org/csstudio/trends/databrowser3/model/ModelItem.java index 12cc766d2b..6b2bf64ceb 100644 --- a/app/databrowser/src/main/java/org/csstudio/trends/databrowser3/model/ModelItem.java +++ b/app/databrowser/src/main/java/org/csstudio/trends/databrowser3/model/ModelItem.java @@ -57,6 +57,10 @@ abstract public class ModelItem */ private volatile Color color = null; + /** RGB for item's area color + */ + private volatile Color areaColor = null; + /** How to display the trace */ private volatile TraceType trace_type = Preferences.trace_type; @@ -72,6 +76,9 @@ abstract public class ModelItem /** Point size [pixel] */ private volatile int point_size = Preferences.line_width; + /** Area Opacity [percent] */ + private volatile int areaOpacity = Preferences.opacity; + /** Y-Axis */ private volatile AxisConfig axis = null; @@ -316,6 +323,43 @@ public void setPointSize(int size) fireItemLookChanged(); } + /** @return Area Opacity */ + public int getAreaOpacity() + { + return areaOpacity; + } + + /** @param opacity New area opacity */ + public void setAreaOpacity(int opacity) + { + if (opacity < 0) + opacity = 0; + if (opacity == this.areaOpacity) + return; + areaOpacity = opacity; + fireItemLookChanged(); + } + + /** Get item's area color. + * For new items, the area color is color until it's + * either set via setAreaColor() or by adding it to a {@link Model}. + * @return Item's area color + * @see #setAreaColor(Color) + */ + public Color getAreaColor() + { + return areaColor == null ? new Color(color.getRed(), color.getGreen(), color.getBlue(), (double) areaOpacity / 100) : areaColor; + } + + /** @param new_col New color for this item */ + public void setAreaColor(final Color new_col) + { + if (new_col.equals(areaColor)) + return; + areaColor = new_col; + fireItemLookChanged(); + } + /** @return Y-Axis */ public AxisConfig getAxis() { diff --git a/app/databrowser/src/main/java/org/csstudio/trends/databrowser3/ui/plot/ModelBasedPlot.java b/app/databrowser/src/main/java/org/csstudio/trends/databrowser3/ui/plot/ModelBasedPlot.java index 7e974e9ab4..434e7a081d 100644 --- a/app/databrowser/src/main/java/org/csstudio/trends/databrowser3/ui/plot/ModelBasedPlot.java +++ b/app/databrowser/src/main/java/org/csstudio/trends/databrowser3/ui/plot/ModelBasedPlot.java @@ -368,6 +368,7 @@ public void updateTrace(final ModelItem item) // These happen to not cause an immediate redraw, so // set even if no change trace.setColor(item.getPaintColor()); + trace.setAreaColor(item.getAreaColor()); trace.setType(item.getTraceType()); trace.setWidth(item.getLineWidth()); trace.setLineStyle(item.getLineStyle()); diff --git a/app/databrowser/src/main/java/org/csstudio/trends/databrowser3/ui/properties/ChangeAreaColorCommand.java b/app/databrowser/src/main/java/org/csstudio/trends/databrowser3/ui/properties/ChangeAreaColorCommand.java new file mode 100644 index 0000000000..ae1449aa0a --- /dev/null +++ b/app/databrowser/src/main/java/org/csstudio/trends/databrowser3/ui/properties/ChangeAreaColorCommand.java @@ -0,0 +1,43 @@ +package org.csstudio.trends.databrowser3.ui.properties; + +import javafx.scene.paint.Color; +import org.csstudio.trends.databrowser3.Messages; +import org.csstudio.trends.databrowser3.model.ModelItem; +import org.phoebus.ui.undo.UndoableAction; +import org.phoebus.ui.undo.UndoableActionManager; + +/** Undo-able command to change item's color + */ +public class ChangeAreaColorCommand extends UndoableAction +{ + private final ModelItem item; + private final Color oldAreaColor; + private final Color newAreaColor; + + /** Register and perform the command + * @param operationsManager OperationsManager where command will be reg'ed + * @param item Model item to configure + * @param newAreaColor New value + */ + public ChangeAreaColorCommand(final UndoableActionManager operationsManager, + final ModelItem item, final Color newAreaColor) + { + super(Messages.Color); + this.item = item; + this.oldAreaColor = item.getAreaColor(); + this.newAreaColor = newAreaColor; + operationsManager.execute(this); + } + + @Override + public void run() + { + item.setAreaColor(newAreaColor); + } + + @Override + public void undo() + { + item.setAreaColor(oldAreaColor); + } +} diff --git a/app/databrowser/src/main/java/org/csstudio/trends/databrowser3/ui/properties/ChangeAreaOpacityCommand.java b/app/databrowser/src/main/java/org/csstudio/trends/databrowser3/ui/properties/ChangeAreaOpacityCommand.java new file mode 100644 index 0000000000..d09a29c309 --- /dev/null +++ b/app/databrowser/src/main/java/org/csstudio/trends/databrowser3/ui/properties/ChangeAreaOpacityCommand.java @@ -0,0 +1,42 @@ +package org.csstudio.trends.databrowser3.ui.properties; + +import org.csstudio.trends.databrowser3.Messages; +import org.csstudio.trends.databrowser3.model.ModelItem; +import org.phoebus.ui.undo.UndoableAction; +import org.phoebus.ui.undo.UndoableActionManager; + +/** Undo-able command to change item's area opacity + */ +public class ChangeAreaOpacityCommand extends UndoableAction +{ + private final ModelItem item; + private final int oldOpacity; + private final int newOpacity; + + /** Register and perform the command + * @param operationsManager OperationsManager where command will be reg'ed + * @param item Model item to configure + * @param newOpacity New value + */ + public ChangeAreaOpacityCommand(final UndoableActionManager operationsManager, + final ModelItem item, final int newOpacity) + { + super(Messages.AreaOpacity); + this.item = item; + this.oldOpacity = item.getAreaOpacity(); + this.newOpacity = newOpacity; + operationsManager.execute(this); + } + + @Override + public void run() + { + item.setAreaOpacity(newOpacity); + } + + @Override + public void undo() + { + item.setAreaOpacity(oldOpacity); + } +} diff --git a/app/databrowser/src/main/java/org/csstudio/trends/databrowser3/ui/properties/TracesTab.java b/app/databrowser/src/main/java/org/csstudio/trends/databrowser3/ui/properties/TracesTab.java index 25888e768a..b08e3e8bd5 100644 --- a/app/databrowser/src/main/java/org/csstudio/trends/databrowser3/ui/properties/TracesTab.java +++ b/app/databrowser/src/main/java/org/csstudio/trends/databrowser3/ui/properties/TracesTab.java @@ -649,6 +649,41 @@ public void updateItem(String value, boolean empty) PropertyPanel.addTooltip(col, Messages.PointSizeTT); trace_table.getColumns().add(col); + // Area Opacity Column ---------- + col = new TableColumn<>(Messages.AreaOpacity); + col.setCellValueFactory(cell -> + new SimpleStringProperty(Integer.toString(cell.getValue().getAreaOpacity()))); + col.setCellFactory(TextFieldTableCell.forTableColumn()); + col.setOnEditCommit(event -> + { + final ModelItem item = event.getRowValue(); + try + { + new ChangeAreaOpacityCommand(undo, item, Integer.parseInt(event.getNewValue())); + } + catch (Exception e) + { + trace_table.refresh(); + } + }); + col.setEditable(true); + PropertyPanel.addTooltip(col, Messages.AreaOpacityTT); + trace_table.getColumns().add(col); + + // Area Colour Column + TableColumn area_color_col = new TableColumn<>(Messages.Color); + area_color_col.setCellValueFactory(cell -> + { + final Color color = cell.getValue().getAreaColor(); + final ColorPicker picker = PropertyPanel.ColorTableCell.createPicker(color); + picker.setOnAction(event -> + new ChangeAreaColorCommand(undo, cell.getValue(), picker.getValue())); + return new SimpleObjectProperty<>(picker); + }); + area_color_col.setCellFactory(cell -> new PropertyPanel.ColorTableCell<>()); + PropertyPanel.addTooltip(area_color_col, Messages.AreaColorTT); + trace_table.getColumns().add(area_color_col); + // Request Type Column ---------- final TableColumn req_col = new TableColumn<>(Messages.RequestType); req_col.setCellValueFactory(cell -> diff --git a/app/databrowser/src/main/resources/org/csstudio/trends/databrowser3/messages.properties b/app/databrowser/src/main/resources/org/csstudio/trends/databrowser3/messages.properties index 89a7537c48..46fbe3eb37 100644 --- a/app/databrowser/src/main/resources/org/csstudio/trends/databrowser3/messages.properties +++ b/app/databrowser/src/main/resources/org/csstudio/trends/databrowser3/messages.properties @@ -17,6 +17,10 @@ AddPV_PeriodTT=Enter scan period in seconds AddPVMsg=Enter PV name(s) and configure axis and scan period AppendSearchResults=Add... AppendSearchResultsTT=Append search results to list +AreaColor=Area Color +AreaColorTT=Color of area in between min and max curves +AreaOpacity=Area Opacity +AreaOpacityTT=Opacity of area in between min and max curves ArchiveFetchJobFmt=Read data: {0}, {1} - {2} ArchiveFetchStart=Reading data ArchiveFetchProgressFmt={0}, {1} sec diff --git a/app/rtplot/src/main/java/org/csstudio/javafx/rtplot/RTPlot.java b/app/rtplot/src/main/java/org/csstudio/javafx/rtplot/RTPlot.java index 6223e69c99..3f45e8286a 100644 --- a/app/rtplot/src/main/java/org/csstudio/javafx/rtplot/RTPlot.java +++ b/app/rtplot/src/main/java/org/csstudio/javafx/rtplot/RTPlot.java @@ -297,11 +297,6 @@ public void setBackground(final Color color) plot.setBackground(GraphicsUtils.convert(Objects.requireNonNull(color), (int) (255*color.getOpacity()))); } - /** Opacity (0 .. 100 %) of 'area' */ - public void setOpacity(final int opacity) - { - plot.setAreaOpacity(opacity); - } /** @param color Grid color */ public void setGridColor(final Color color) @@ -452,6 +447,30 @@ public void removeYAxis(final int index) plot.removeYAxis(index); } + /** @param name Name, must not be null + * @param units Units, may be null + * @param data + * @param color + * @param areaColor + * @param type + * @param width + * @param y_axis + * @return {@link Trace} that was added + */ + public Trace addTrace(final String name, final String units, + final PlotDataProvider data, + final Color color, + final Color areaColor, + final TraceType type, final int width, + final LineStyle line_style, + final PointType point_type, final int size, + final int y_axis) + { + final TraceImpl trace = new TraceImpl<>(name, units, data, color, areaColor, type, width, line_style, point_type, size, y_axis); + plot.addTrace(trace); + return trace; + } + /** @param name Name, must not be null * @param units Units, may be null * @param data @@ -462,12 +481,12 @@ public void removeYAxis(final int index) * @return {@link Trace} that was added */ public Trace addTrace(final String name, final String units, - final PlotDataProvider data, - final Color color, - final TraceType type, final int width, - final LineStyle line_style, - final PointType point_type, final int size, - final int y_axis) + final PlotDataProvider data, + final Color color, + final TraceType type, final int width, + final LineStyle line_style, + final PointType point_type, final int size, + final int y_axis) { final TraceImpl trace = new TraceImpl<>(name, units, data, color, type, width, line_style, point_type, size, y_axis); plot.addTrace(trace); diff --git a/app/rtplot/src/main/java/org/csstudio/javafx/rtplot/Trace.java b/app/rtplot/src/main/java/org/csstudio/javafx/rtplot/Trace.java index 17e786bce5..686c962231 100644 --- a/app/rtplot/src/main/java/org/csstudio/javafx/rtplot/Trace.java +++ b/app/rtplot/src/main/java/org/csstudio/javafx/rtplot/Trace.java @@ -68,6 +68,12 @@ default public String getLabel() /** @param color Color to use for this trace */ public void setColor(final Color color); + /** @return Color to use for this trace */ + public Color getAreaColor(); + + /** @param color Color to use for this trace */ + public void setAreaColor(final Color color); + /** @return How to draw this trace */ public TraceType getType(); diff --git a/app/rtplot/src/main/java/org/csstudio/javafx/rtplot/internal/Plot.java b/app/rtplot/src/main/java/org/csstudio/javafx/rtplot/internal/Plot.java index 9f06346629..c67ab41fc5 100644 --- a/app/rtplot/src/main/java/org/csstudio/javafx/rtplot/internal/Plot.java +++ b/app/rtplot/src/main/java/org/csstudio/javafx/rtplot/internal/Plot.java @@ -686,7 +686,7 @@ protected BufferedImage updateImageBuffer() for (YAxisImpl y_axis : y_axes) for (Trace trace : y_axis.getTraces()) - trace_painter.paint(gc, plot_area.getBounds(), opacity, x_transform, y_axis, trace); + trace_painter.paint(gc, plot_area.getBounds(), x_transform, y_axis, trace); drawPlotMarkers(gc); gc.setClip(null); diff --git a/app/rtplot/src/main/java/org/csstudio/javafx/rtplot/internal/TraceImpl.java b/app/rtplot/src/main/java/org/csstudio/javafx/rtplot/internal/TraceImpl.java index e4afbc3826..1c140bfa44 100644 --- a/app/rtplot/src/main/java/org/csstudio/javafx/rtplot/internal/TraceImpl.java +++ b/app/rtplot/src/main/java/org/csstudio/javafx/rtplot/internal/TraceImpl.java @@ -37,6 +37,8 @@ public class TraceImpl> implements Trace private volatile Color color; + private volatile Color areaColor; + private volatile TraceType type; private volatile int width; @@ -52,10 +54,23 @@ public class TraceImpl> implements Trace private volatile Optional> selected_sample = Optional.empty(); + public TraceImpl(final String name, + final String units, + final PlotDataProvider data, + final Color color, + final TraceType type, final int width, + final LineStyle line_style, + final PointType point_type, final int size, + final int y_axis) + { + this(name, units, data, color, color, type, width, line_style, point_type, size, y_axis); + } + public TraceImpl(final String name, final String units, final PlotDataProvider data, final Color color, + final Color areaColor, final TraceType type, final int width, final LineStyle line_style, final PointType point_type, final int size, @@ -65,6 +80,7 @@ public TraceImpl(final String name, this.units = units == null ? "" : units; this.data = Objects.requireNonNull(data); this.color = Objects.requireNonNull(color); + this.areaColor = Objects.requireNonNull(areaColor); this.type = Objects.requireNonNull(type); this.width = width; this.line_style = line_style; @@ -148,6 +164,20 @@ public void setColor(final Color color) this.color = Objects.requireNonNull(color); } + /** {@inheritDoc} */ + @Override + public Color getAreaColor() + { + return areaColor; + } + + /** {@inheritDoc} */ + @Override + public void setAreaColor(final Color areaColor) + { + this.areaColor = Objects.requireNonNull(areaColor); + } + /** {@inheritDoc} */ @Override public TraceType getType() diff --git a/app/rtplot/src/main/java/org/csstudio/javafx/rtplot/internal/TracePainter.java b/app/rtplot/src/main/java/org/csstudio/javafx/rtplot/internal/TracePainter.java index ddba1f3fa4..f1a5898bbe 100644 --- a/app/rtplot/src/main/java/org/csstudio/javafx/rtplot/internal/TracePainter.java +++ b/app/rtplot/src/main/java/org/csstudio/javafx/rtplot/internal/TracePainter.java @@ -77,11 +77,10 @@ final private int clipY(final int y) /** @param gc GC * @param bounds Clipping bounds within which to paint - * @param opacity Opacity (0 .. 100 %) of 'area' * @param x_transform Coordinate transform used by the x axis * @param trace Trace, has reference to its value axis */ - final public void paint(final Graphics2D gc, final Rectangle bounds, final int opacity, + final public void paint(final Graphics2D gc, final Rectangle bounds, final ScreenTransform x_transform, final YAxisImpl y_axis, final Trace trace) { @@ -104,7 +103,7 @@ final public void paint(final Graphics2D gc, final Rectangle bounds, final int o final Stroke old_width = gc.getStroke(); final Color color = GraphicsUtils.convert(trace.getColor()); - final Color tpcolor = new Color(color.getRed(), color.getGreen(), color.getBlue(), opacity); + final Color tpcolor = GraphicsUtils.convert(trace.getAreaColor()); gc.setColor(color); // TODO Optimize drawing