diff --git a/app/display/linearmeter/src/main/java/org/csstudio/display/extra/widgets/linearmeter/LinearMeterRepresentation.java b/app/display/linearmeter/src/main/java/org/csstudio/display/extra/widgets/linearmeter/LinearMeterRepresentation.java index 375c09a1bc..66b461401e 100644 --- a/app/display/linearmeter/src/main/java/org/csstudio/display/extra/widgets/linearmeter/LinearMeterRepresentation.java +++ b/app/display/linearmeter/src/main/java/org/csstudio/display/extra/widgets/linearmeter/LinearMeterRepresentation.java @@ -77,7 +77,8 @@ public Pane createJFXNode() widgetColorToAWTColor(model_widget.propNeedleColor().getValue()), model_widget.propKnobSize().getValue(), widgetColorToAWTColor(model_widget.propKnobColor().getValue()), - model_widget.propShowWarnings().getValue()); + model_widget.propShowWarnings().getValue(), + model_widget.propLogScale().getValue()); meter.setDisplayMode(model_widget.propDisplayMode().getValue()); meter.setSize(model_widget.propWidth().getValue(),model_widget.propHeight().getValue()); meter.setHorizontal(model_widget.propDisplayHorizontal().getValue()); @@ -108,6 +109,11 @@ protected void registerListeners() addUntypedWidgetPropertyListener(model_widget.propFont(), layoutChangedListener); addUntypedWidgetPropertyListener(model_widget.propNeedleColor(), layoutChangedListener); + addWidgetPropertyListener(model_widget.propLogScale(), (property, oldValue, newValue) -> { + meter.setLogScale(newValue); + layoutChanged(null, null, null); + }); + addWidgetPropertyListener(model_widget.propShowWarnings(), (property, oldValue, newValue) -> { meter.setShowWarnings(newValue); layoutChanged(null, null, null); diff --git a/app/display/linearmeter/src/main/java/org/csstudio/display/extra/widgets/linearmeter/LinearMeterScale.java b/app/display/linearmeter/src/main/java/org/csstudio/display/extra/widgets/linearmeter/LinearMeterScale.java index f17d6db822..60b6f0b933 100644 --- a/app/display/linearmeter/src/main/java/org/csstudio/display/extra/widgets/linearmeter/LinearMeterScale.java +++ b/app/display/linearmeter/src/main/java/org/csstudio/display/extra/widgets/linearmeter/LinearMeterScale.java @@ -6,6 +6,8 @@ import org.csstudio.javafx.rtplot.internal.*; import org.csstudio.javafx.rtplot.internal.util.GraphicsUtils; +import static org.csstudio.javafx.rtplot.internal.util.Log10.log10; + public class LinearMeterScale extends NumericAxis { @@ -39,10 +41,12 @@ public LinearMeterScale(PlotPartListener listener, int height, boolean horizontal, double min, - double max) + double max, + boolean isLogarithmic) { super("", listener, horizontal, min, max); super.setBounds(0, 0, width, height); + super.setLogarithmic(isLogarithmic); isHorizontal = horizontal; } @@ -102,26 +106,49 @@ public void paint(Graphics2D gc, Rectangle plot_bounds) FontMetrics scale_font_fontMetrics = gc.getFontMetrics(scale_font); for (MajorTick tick : ticks.getMajorTicks()) { - gc.drawLine((int) ((start_x + this.scale * (tick.getValue() - offset) )), + if (isLogarithmic()) { + gc.drawLine((int) ((start_x + this.scale * (log10(tick.getValue()) - log10(offset)) )), + (int) ((start_y - 0.5 * TICK_LENGTH)), + (int) ((start_x + this.scale * (log10(tick.getValue()) - log10(offset)) )), + (int) ((start_y + 0.5 * TICK_LENGTH))); + drawTickLabel(gc, + (int) ((start_x + this.scale * (log10(tick.getValue()) - log10(offset)) - scale_font_fontMetrics.stringWidth(tick.getLabel())/2)), + (int) (start_y + 0.5 * TICK_LENGTH + 2 + Math.round(Math.ceil((72.0 * (scale_font_fontMetrics.getAscent())) / 96.0))), + tick.getLabel()); + } + else { + gc.drawLine((int) ((start_x + this.scale * (tick.getValue() - offset) )), (int) ((start_y - 0.5 * TICK_LENGTH)), (int) ((start_x + this.scale * (tick.getValue() - offset) )), (int) ((start_y + 0.5 * TICK_LENGTH))); - drawTickLabel(gc, - (int) ((start_x + this.scale * (tick.getValue() - offset) - scale_font_fontMetrics.stringWidth(tick.getLabel())/2)), - (int) (start_y + 0.5 * TICK_LENGTH + 2 + Math.round(Math.ceil((72.0 * (scale_font_fontMetrics.getAscent())) / 96.0))), - tick.getLabel()); + drawTickLabel(gc, + (int) ((start_x + this.scale * (tick.getValue() - offset) - scale_font_fontMetrics.stringWidth(tick.getLabel())/2)), + (int) (start_y + 0.5 * TICK_LENGTH + 2 + Math.round(Math.ceil((72.0 * (scale_font_fontMetrics.getAscent())) / 96.0))), + tick.getLabel()); + } } } else { - for (MajorTick tick : ticks.getMajorTicks()) { - gc.drawLine((int) (start_x - 0.5 * TICK_LENGTH), + if (isLogarithmic()) { + gc.drawLine((int) (start_x - 0.5 * TICK_LENGTH), + (int) (start_y - this.scale * (log10(tick.getValue()) - log10(offset))), + (int) (start_x + 0.5 * TICK_LENGTH), + (int) (start_y - this.scale * (log10(tick.getValue()) - log10(offset)))); + drawTickLabel(gc, + (int) (start_x + 4), + (int) (start_y - this.scale * (log10(tick.getValue()) - log10(offset)) + Math.round((72.0 * scale_font.getSize()) / (96.0 * 2.0))), + tick.getLabel()); + } + else { + gc.drawLine((int) (start_x - 0.5 * TICK_LENGTH), (int) (start_y - this.scale * (tick.getValue() - offset)), (int) (start_x + 0.5 * TICK_LENGTH), (int) (start_y - this.scale * (tick.getValue() - offset))); - drawTickLabel(gc, - (int) (start_x + 4), - (int) (start_y - this.scale * (tick.getValue() - offset) + Math.round((72.0 * scale_font.getSize()) / (96.0 * 2.0))), - tick.getLabel()); + drawTickLabel(gc, + (int) (start_x + 4), + (int) (start_y - this.scale * (tick.getValue() - offset) + Math.round((72.0 * scale_font.getSize()) / (96.0 * 2.0))), + tick.getLabel()); + } } } diff --git a/app/display/linearmeter/src/main/java/org/csstudio/display/extra/widgets/linearmeter/LinearMeterWidget.java b/app/display/linearmeter/src/main/java/org/csstudio/display/extra/widgets/linearmeter/LinearMeterWidget.java index 736a949023..41a01e16dc 100644 --- a/app/display/linearmeter/src/main/java/org/csstudio/display/extra/widgets/linearmeter/LinearMeterWidget.java +++ b/app/display/linearmeter/src/main/java/org/csstudio/display/extra/widgets/linearmeter/LinearMeterWidget.java @@ -160,6 +160,10 @@ public EnumWidgetProperty createProperty(Widget widge } }; + private WidgetProperty logScale; + public static WidgetPropertyDescriptor propLogScale = + newBooleanPropertyDescriptor(WidgetPropertyCategory.DISPLAY, "logScale", Messages.WidgetProperties_LogScale); + public static WidgetPropertyDescriptor propNeedleColor = newColorPropertyDescriptor(WidgetPropertyCategory.MISC, "needle_color", Messages.WidgetProperties_NeedleColor); @@ -253,6 +257,7 @@ protected void defineProperties(List> properties) { super.defineProperties(properties); properties.add(display_mode = propDisplayMode.createProperty(this, RTLinearMeter.DisplayMode.NEEDLE)); + properties.add(logScale = propLogScale.createProperty(this, false)); properties.add(font = propFont.createProperty(this, WidgetFontService.get(NamedWidgetFonts.DEFAULT))); properties.add(format = propFormat.createProperty(this, FormatOption.DEFAULT)); properties.add(show_units = propShowUnits.createProperty(this, true)); @@ -439,4 +444,8 @@ public WidgetProperty propDisplayMode() { return display_mode; } + public WidgetProperty propLogScale() { + return logScale; + } + } diff --git a/app/display/linearmeter/src/main/java/org/csstudio/display/extra/widgets/linearmeter/RTLinearMeter.java b/app/display/linearmeter/src/main/java/org/csstudio/display/extra/widgets/linearmeter/RTLinearMeter.java index 95b3a21190..a65717d6b7 100644 --- a/app/display/linearmeter/src/main/java/org/csstudio/display/extra/widgets/linearmeter/RTLinearMeter.java +++ b/app/display/linearmeter/src/main/java/org/csstudio/display/extra/widgets/linearmeter/RTLinearMeter.java @@ -2,6 +2,7 @@ package org.csstudio.display.extra.widgets.linearmeter; import static org.csstudio.javafx.rtplot.Activator.logger; +import static org.csstudio.javafx.rtplot.internal.util.Log10.log10; import java.awt.BasicStroke; import java.awt.Canvas; @@ -91,7 +92,8 @@ public RTLinearMeter(double initialValue, Color needleColor, int knobSize, Color knobColor, - boolean showWarnings) + boolean showWarnings, + boolean logScale) { if (warningTriangle == null) { try { @@ -115,7 +117,8 @@ public RTLinearMeter(double initialValue, height, isHorizontal, min, - max); + max, + logScale); this.minMaxTolerance = minMaxTolerance; this.loLo = loLo; @@ -189,7 +192,8 @@ public void redrawLinearMeterScale() { linearMeterScale.getBounds().height, linearMeterScale.isHorizontal(), linearMeterScale.getValueRange().getLow(), - linearMeterScale.getValueRange().getHigh()); + linearMeterScale.getValueRange().getHigh(), + linearMeterScale.isLogarithmic()); linearMeterScale.setHorizontal(isHorizontal); }); } @@ -295,6 +299,12 @@ public void setDisplayMode(DisplayMode newDisplayMode) { private DisplayMode displayMode = DisplayMode.NEEDLE; + public void setLogScale(boolean logScale) { + withWriteLock(() -> { + linearMeterScale.setLogarithmic(logScale); + }); + } + private void runOnJavaFXThread(Runnable runnable) { if (Platform.isFxApplicationThread()) { runnable.run(); @@ -749,10 +759,20 @@ private Optional computeIndicatorPosition(double value) { } return withReadLock(() -> { if (linearMeterScale.isHorizontal()) { - return Optional.of((int) Math.round(marginLeft + pixelsPerScaleUnit * (value - linearMeterScale.getValueRange().getLow()))); + if (linearMeterScale.isLogarithmic()) { + return Optional.of((int) Math.round(marginLeft + pixelsPerScaleUnit * (log10(value) - log10(linearMeterScale.getValueRange().getLow())))); + } + else { + return Optional.of((int) Math.round(marginLeft + pixelsPerScaleUnit * (value - linearMeterScale.getValueRange().getLow()))); + } } else { - return Optional.of((int) Math.round(linearMeterScale.getBounds().height - marginBelow - pixelsPerScaleUnit * (value - linearMeterScale.getValueRange().getLow()))); + if (linearMeterScale.isLogarithmic()) { + return Optional.of((int) Math.round(linearMeterScale.getBounds().height - marginBelow - pixelsPerScaleUnit * (log10(value) - log10(linearMeterScale.getValueRange().getLow())))); + } + else { + return Optional.of((int) Math.round(linearMeterScale.getBounds().height - marginBelow - pixelsPerScaleUnit * (value - linearMeterScale.getValueRange().getLow()))); + } } }); } @@ -1323,14 +1343,34 @@ private void layout() { marginBelow += 1 + fontMetrics.getMaxAscent() + fontMetrics.getMaxDescent(); } - pixelsPerScaleUnit = (linearMeterScale.getBounds().width - marginLeft - marginRight - 1) / (linearMeterScale.getValueRange().getHigh() - linearMeterScale.getValueRange().getLow()); + if (linearMeterScale.isLogarithmic()) { + pixelsPerScaleUnit = (linearMeterScale.getBounds().width - marginLeft - marginRight - 1) / (log10(linearMeterScale.getValueRange().getHigh()) - log10(linearMeterScale.getValueRange().getLow())); + } + else { + pixelsPerScaleUnit = (linearMeterScale.getBounds().width - marginLeft - marginRight - 1) / (linearMeterScale.getValueRange().getHigh() - linearMeterScale.getValueRange().getLow()); + } meterBreadth = Math.round(linearMeterScale.getBounds().height - marginAbove - marginBelow) - 1; - double x_loLoRectangle = marginLeft; - double x_lowRectangle = marginLeft + pixelsPerScaleUnit * (displayedLoLo - linearMeterScale.getValueRange().getLow()); - double x_normalRectangle = marginLeft + pixelsPerScaleUnit * (displayedLow - linearMeterScale.getValueRange().getLow()); - double x_highRectangle = marginLeft + pixelsPerScaleUnit * (displayedHigh - linearMeterScale.getValueRange().getLow()); - double x_hiHiRectangle = marginLeft + pixelsPerScaleUnit * (displayedHiHi - linearMeterScale.getValueRange().getLow()); + double x_loLoRectangle; + double x_lowRectangle; + double x_normalRectangle; + double x_highRectangle; + double x_hiHiRectangle; + if (linearMeterScale.isLogarithmic()) { + x_loLoRectangle = marginLeft; + x_lowRectangle = marginLeft + pixelsPerScaleUnit * (log10(displayedLoLo) - log10(linearMeterScale.getValueRange().getLow())); + x_normalRectangle = marginLeft + pixelsPerScaleUnit * (log10(displayedLow) - log10(linearMeterScale.getValueRange().getLow())); + x_highRectangle = marginLeft + pixelsPerScaleUnit * (log10(displayedHigh) - log10(linearMeterScale.getValueRange().getLow())); + x_hiHiRectangle = marginLeft + pixelsPerScaleUnit * (log10(displayedHiHi) - log10(linearMeterScale.getValueRange().getLow())); + } + else { + x_loLoRectangle = marginLeft; + x_lowRectangle = marginLeft + pixelsPerScaleUnit * (displayedLoLo - linearMeterScale.getValueRange().getLow()); + x_normalRectangle = marginLeft + pixelsPerScaleUnit * (displayedLow - linearMeterScale.getValueRange().getLow()); + x_highRectangle = marginLeft + pixelsPerScaleUnit * (displayedHigh - linearMeterScale.getValueRange().getLow()); + x_hiHiRectangle = marginLeft + pixelsPerScaleUnit * (displayedHiHi - linearMeterScale.getValueRange().getLow()); + + } loLoRectangle = new Rectangle((int) Math.round(x_loLoRectangle), marginAbove, @@ -1352,9 +1392,16 @@ private void layout() { (int) (Math.round(x_hiHiRectangle) - Math.round(x_highRectangle)), meterBreadth); + int hihiWidth; + if (linearMeterScale.isLogarithmic()) { + hihiWidth = (int) (Math.round(pixelsPerScaleUnit * (log10(linearMeterScale.getValueRange().getHigh()) - log10(displayedHiHi)))); + } + else { + hihiWidth = (int) (Math.round(pixelsPerScaleUnit * (linearMeterScale.getValueRange().getHigh() - displayedHiHi))); + } hiHiRectangle = new Rectangle((int) Math.round(x_hiHiRectangle), marginAbove, - (int) (Math.round(pixelsPerScaleUnit * (linearMeterScale.getValueRange().getHigh() - displayedHiHi))), + hihiWidth, meterBreadth); } else { @@ -1381,13 +1428,30 @@ private void layout() { marginBelow += 1 + fontMetrics.getMaxAscent() + fontMetrics.getMaxDescent(); } - pixelsPerScaleUnit = (linearMeterScale.getBounds().height - marginAbove - marginBelow - 1) / (linearMeterScale.getValueRange().getHigh() - linearMeterScale.getValueRange().getLow()); + if (linearMeterScale.isLogarithmic()) { + pixelsPerScaleUnit = (linearMeterScale.getBounds().height - marginAbove - marginBelow - 1) / (log10(linearMeterScale.getValueRange().getHigh()) - log10(linearMeterScale.getValueRange().getLow())); + } + else { + pixelsPerScaleUnit = (linearMeterScale.getBounds().height - marginAbove - marginBelow - 1) / (linearMeterScale.getValueRange().getHigh() - linearMeterScale.getValueRange().getLow()); + } meterBreadth = Math.round(linearMeterScale.getBounds().width - marginLeft - marginRight); - double y_loLoRectangle = marginAbove + pixelsPerScaleUnit * (linearMeterScale.getValueRange().getHigh() - displayedLoLo); - double y_lowRectangle = marginAbove + pixelsPerScaleUnit * (linearMeterScale.getValueRange().getHigh() - displayedLow); - double y_normalRectangle = marginAbove + pixelsPerScaleUnit * (linearMeterScale.getValueRange().getHigh() - displayedHigh); - double y_highRectangle = marginAbove + pixelsPerScaleUnit * (linearMeterScale.getValueRange().getHigh() - displayedHiHi); + double y_loLoRectangle; + double y_lowRectangle; + double y_normalRectangle; + double y_highRectangle; + if (linearMeterScale.isLogarithmic()) { + y_loLoRectangle = marginAbove + pixelsPerScaleUnit * (log10(linearMeterScale.getValueRange().getHigh()) - log10(displayedLoLo)); + y_lowRectangle = marginAbove + pixelsPerScaleUnit * (log10(linearMeterScale.getValueRange().getHigh()) - log10(displayedLow)); + y_normalRectangle = marginAbove + pixelsPerScaleUnit * (log10(linearMeterScale.getValueRange().getHigh()) - log10(displayedHigh)); + y_highRectangle = marginAbove + pixelsPerScaleUnit * (log10(linearMeterScale.getValueRange().getHigh()) - log10(displayedHiHi)); + } + else { + y_loLoRectangle = marginAbove + pixelsPerScaleUnit * (linearMeterScale.getValueRange().getHigh() - displayedLoLo); + y_lowRectangle = marginAbove + pixelsPerScaleUnit * (linearMeterScale.getValueRange().getHigh() - displayedLow); + y_normalRectangle = marginAbove + pixelsPerScaleUnit * (linearMeterScale.getValueRange().getHigh() - displayedHigh); + y_highRectangle = marginAbove + pixelsPerScaleUnit * (linearMeterScale.getValueRange().getHigh() - displayedHiHi); + } loLoRectangle = new Rectangle(marginLeft, (int) Math.round(y_loLoRectangle), diff --git a/app/display/model/src/main/java/org/csstudio/display/builder/model/Messages.java b/app/display/model/src/main/java/org/csstudio/display/builder/model/Messages.java index feff995562..f0c46cd261 100644 --- a/app/display/model/src/main/java/org/csstudio/display/builder/model/Messages.java +++ b/app/display/model/src/main/java/org/csstudio/display/builder/model/Messages.java @@ -260,6 +260,7 @@ public class Messages WidgetProperties_LineColor, WidgetProperties_LineWidth, WidgetProperties_Locale, + WidgetProperties_LogScale, WidgetProperties_Macros, WidgetProperties_MajorTickSpace, WidgetProperties_MajorTickStepHint, diff --git a/app/display/model/src/main/resources/org/csstudio/display/builder/model/messages.properties b/app/display/model/src/main/resources/org/csstudio/display/builder/model/messages.properties index 9f2619903c..82e52e2889 100644 --- a/app/display/model/src/main/resources/org/csstudio/display/builder/model/messages.properties +++ b/app/display/model/src/main/resources/org/csstudio/display/builder/model/messages.properties @@ -246,6 +246,7 @@ WidgetProperties_LimitsFromPV=Limits from PV WidgetProperties_LineColor=Line Color WidgetProperties_LineWidth=Line Width WidgetProperties_Locale=Locale +WidgetProperties_LogScale=Logarithmic Scale WidgetProperties_Macros=Macros WidgetProperties_MajorTickSpace=Major Ticks Space WidgetProperties_MajorTickStepHint=Major Ticks Pixel Dist.