From 817d0c867b541eefd9474752fce057a37e9008df Mon Sep 17 00:00:00 2001 From: Harald Wolff Date: Fri, 29 Apr 2016 02:38:55 +0200 Subject: [PATCH] =?UTF-8?q?JDiagram:=20Komplette=20=C3=9Cberarbeitung=20(D?= =?UTF-8?q?iagramm=20entfernt)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/org/hwo/ui/JDiagram.java | 566 ++++++++++++++++-- src/org/hwo/ui/JUITest.java | 61 +- .../hwo/ui/diagram/AnnotatedPlotProvider.java | 30 +- .../AnnotatedSortedMapPlotProvider.java | 6 +- src/org/hwo/ui/diagram/Diagram.java | 356 ----------- src/org/hwo/ui/diagram/LinearScaler.java | 69 +++ src/org/hwo/ui/diagram/LogarithmicScaler.java | 148 +++++ src/org/hwo/ui/diagram/PlotLabeler.java | 6 +- src/org/hwo/ui/diagram/PlotProvider2.java | 5 + src/org/hwo/ui/diagram/Scaler.java | 19 + src/org/hwo/ui/diagram/SimplePlotLabeler.java | 8 +- .../hwo/ui/diagram/SimplePlotProvider.java | 82 ++- src/org/hwo/ui/diagram/annotation/Plot.java | 1 + 13 files changed, 889 insertions(+), 468 deletions(-) delete mode 100644 src/org/hwo/ui/diagram/Diagram.java create mode 100644 src/org/hwo/ui/diagram/LinearScaler.java create mode 100644 src/org/hwo/ui/diagram/LogarithmicScaler.java create mode 100644 src/org/hwo/ui/diagram/Scaler.java diff --git a/src/org/hwo/ui/JDiagram.java b/src/org/hwo/ui/JDiagram.java index af7b440..1fdbd45 100644 --- a/src/org/hwo/ui/JDiagram.java +++ b/src/org/hwo/ui/JDiagram.java @@ -5,79 +5,531 @@ import java.awt.Dimension; import java.awt.Font; import java.awt.Graphics; import java.awt.Graphics2D; +import java.awt.Toolkit; import javax.swing.JComponent; import javax.swing.JPanel; import org.hwo.ui.diagram.Diagram; +import org.hwo.ui.diagram.LinePlotPainter; +import org.hwo.ui.diagram.LinearScaler; +import org.hwo.ui.diagram.PlotLabeler; +import org.hwo.ui.diagram.PlotPainter; +import org.hwo.ui.diagram.PlotProvider2; +import org.hwo.ui.diagram.Scaler; +import org.hwo.ui.diagram.SimplePlotLabeler; +import org.hwo.ui.diagram.SimplePlotProvider; -public class JDiagram extends JPanel { - - private Diagram diagram; +public class JDiagram extends JComponent { + private PlotProvider2 + plotProvider; + + private PlotLabeler + defaultLabeler; + + // Innenabstand zu Zeichnungselementen + private int bTop, + bBottom, + bLeft, + bRight; + + // Länge der Achsenmarkierungen + private int axMarkerLength; + + // Anzahl der Achsenmarkierungen - 1 + private int nOrdinateLabels, + nAbszissLabels; + + + + // Layout Merker + private int plotHeight, + plotWidth; + + private double abszissMinimum, + abszissMaximum, + abszissWindow; + + + private int screenDPI; + private int fontLineHeight; + + private boolean autoOrdinateLabeling; + private boolean drawHorizontalGrid; + private boolean drawVerticalGrid; + private boolean logarithmic; + private boolean preferLabelHints; + private boolean autoScale; + private boolean autoScaleMargins; + + private Color verticalGridColor; + + private OrdinateView[] + ordinateViews; + + private PlotPainter[] + plotPainters; + public JDiagram(){ setMinimumSize(new Dimension(80, 80)); - getDiagram(); - diagram.setFont( getFont() ); + setDoubleBuffered(true); + + defaultLabeler = new SimplePlotLabeler(); + + + bTop = bBottom = bLeft = 10; + bRight = 30; + axMarkerLength = 3; + + nOrdinateLabels = 11; + nAbszissLabels = 0; + + drawHorizontalGrid = true; + + verticalGridColor = new Color(192, 192, 192); + + setPlotProvider(new SimplePlotProvider(1, 0)); + } + + public void setPlotProvider(PlotProvider2 plotProvider) { + this.plotProvider = plotProvider; + fundamentalsChanged(); + } + public PlotProvider2 getPlotProvider() { + return plotProvider; + } + + public boolean isAutoOrdinateLabeling() { + return autoOrdinateLabeling; + } + public void setAutoOrdinateLabeling(boolean autoOrdinateLabeling) { + this.autoOrdinateLabeling = autoOrdinateLabeling; + } + + public boolean isDrawHorizontalGrid() { + return drawHorizontalGrid; + } + public void setDrawHorizontalGrid(boolean drawHorizontalGrid) { + this.drawHorizontalGrid = drawHorizontalGrid; + } + + public boolean isDrawVerticalGrid() { + return drawVerticalGrid; + } + public void setDrawVerticalGrid(boolean drawVerticalGrid) { + this.drawVerticalGrid = drawVerticalGrid; + } + + private void fundamentalsChanged(){ + ordinateViews = new OrdinateView[ plotProvider.getMaxOrdinate() + 1 ]; + for (int n=0; n < plotProvider.getMaxOrdinate() + 1; n++) + ordinateViews[n] = new OrdinateView(n); + + PlotPainter pp = new LinePlotPainter(); + plotPainters = new PlotPainter[plotProvider.getNumGraphs()]; + for (int n=0;n max[ordinate])) + max[ordinate] = value.doubleValue(); + }; + } + } + + for (int i=0;i 0) && ((scalerHints == null) || (!preferLabelHints))) { + if (nHints < 2) + nHints = 2; + + hints = new double[nHints]; + + for (n = 0; n < hints.length; n++){ + hints[n] = this.ordinateViews[ordinate].scaler.getMinValue() + (this.ordinateViews[ordinate].scaler.getWindow() * n / (hints.length-1)); + } + } else { + hints = scalerHints; + } + + return hints; + } + + public void paintOrdinates(Graphics2D g){ + double[][] labelValues = new double[ ordinateViews.length ][]; + + for (int ordinate=0; ordinate < ordinateViews.length; ordinate++){ + labelValues[ ordinate ] = getordinateLabelHints(ordinate); + int nMarkers = labelValues[ ordinate ].length - 1; + + int maxWidth = 0; + String[] labels = new String[ nMarkers + 1 ]; + int[] labelWidths = new int[ nMarkers + 1 ]; + + + this.ordinateViews[ ordinate ].scaler.setHeight( plotHeight ); + + g.setColor( this.ordinateViews[ ordinate ].colDraw ); + + for (int i=0;i<=nMarkers;i++){ + labels[i] = this.defaultLabeler.getOrdinateLabel( + this, + labelValues[ordinate][i] + ); + labelWidths[i] = g.getFontMetrics().stringWidth(labels[i]); + + if (labelWidths[i] > maxWidth) + maxWidth = labelWidths[i]; + } + + plotWidth -= maxWidth + 5; + + for (int i=0; i<=nMarkers ;i++){ + g.drawString( + labels[i], + getWidth() - bRight - plotWidth - labelWidths[i], + bTop + plotHeight - this.ordinateViews[ ordinate ].scaler.getPosition(labelValues[ordinate][i]) + (fontLineHeight/4) + ); + } + + plotWidth -= axMarkerLength; + + }; + + g.drawLine( + getWidth() - bRight - plotWidth, + bTop, + getWidth() - bRight - plotWidth, + bTop + plotHeight + ); + + for (int ordinate=0; ordinate < ordinateViews.length; ordinate++){ + int nMarkers = labelValues[ ordinate ].length - 1; + + for (int i=0;i<=nMarkers;i++){ + int yp = bTop + plotHeight - this.ordinateViews[ ordinate ].scaler.getPosition(labelValues[ordinate][i]); + + g.drawLine( + getWidth() - bRight - plotWidth, + yp, + getWidth() - bRight - plotWidth - axMarkerLength, + yp + ); + + if (drawHorizontalGrid){ + g.setColor( this.ordinateViews[ ordinate ].colGrid ); + g.drawLine( + getWidth() - bRight - plotWidth + 1, + yp, + getWidth() - bRight, + yp + ); + g.setColor( this.ordinateViews[ ordinate ].colDraw ); + } + } + + } + + } + + void paintAbszisse(Graphics2D g){ + int nMarker = nAbszissLabels; + + if (nMarker == 0){ + int w = g.getFontMetrics().stringWidth( this.defaultLabeler.getAbzisseLabel(this, (double)this.plotProvider.getPositionMaximum())); + nMarker = plotWidth / (w*2); + } + + abszissMinimum = this.plotProvider.getPositionMinimum(); + abszissMaximum = this.plotProvider.getPositionMaximum(); + abszissWindow = abszissMaximum - abszissMinimum; + + g.setColor(getForeground()); + + g.drawLine( + getWidth() - bRight - plotWidth, + bTop + plotHeight, + getWidth() - bRight, + bTop + plotHeight + ); + + for (int n=0;n <= nMarker; n++){ + int xpos = plotWidth * n / nMarker; + double pos = abszissMinimum + (abszissWindow * n / nMarker); + + String xlabel = this.defaultLabeler.getAbzisseLabel(this, pos); + int xlwidth = g.getFontMetrics().stringWidth(xlabel); + + g.drawString(xlabel, getWidth() - bRight - plotWidth + xpos - (xlwidth / 2) , getHeight() - bBottom); + g.drawLine( + getWidth() - bRight - plotWidth + xpos, + bTop + plotHeight, + getWidth() - bRight - plotWidth + xpos, + bTop + plotHeight + axMarkerLength + ); + + if (drawVerticalGrid){ + g.setColor(verticalGridColor); + g.drawLine( + getWidth() - bRight - plotWidth + xpos, + bTop, + getWidth() - bRight - plotWidth + xpos, + bTop + plotHeight + ); + g.setColor(getForeground()); + }; + + } + + } + + void paintGraphs(Graphics2D g){ + int ordinate; + Color graphColor; + Color[] graphColors = this.plotProvider.getColors(); + + for (int graph=0; graph < this.plotProvider.getNumGraphs(); graph++){ + + this.plotPainters[ graph ].reset(); + ordinate = this.plotProvider.getOrdinate(graph); + graphColor = graphColors[graph]; + + if (graphColor == null){ + graphColor = this.ordinateViews[ordinate].colDraw; + } + if (graphColor == null){ + graphColor = Color.BLACK; + } + + for (int n=0;n max[ordinate]) + max[ordinate] = v; + + } else { + plotPainter.reset(); + } + } + } + + for (int i=0;i values; + private int diagram; + public AnnotatedPlotProvider(Class clazz){ this.setClazz(clazz); this.setValues(new Object[0]); + this.diagram = 0; + } + + public AnnotatedPlotProvider(Class clazz,int diagram){ + this.diagram = diagram; + this.setClazz(clazz); + this.setValues(new Object[0]); } public void setClazz(Class clazz) { @@ -60,13 +69,15 @@ public class AnnotatedPlotProvider implements PlotProvider2{ for (Field f: this.clazz.getDeclaredFields()){ Plot plot = f.getAnnotation(Plot.class); if (plot != null){ - gdl.add(new GraphDefinition(f)); + if (plot.diagram() == this.diagram) + gdl.add(new GraphDefinition(f)); } } for (Method m: this.clazz.getDeclaredMethods()){ Plot plot = m.getAnnotation(Plot.class); if (plot != null){ - gdl.add(new GraphDefinition(m)); + if (plot.diagram() == this.diagram) + gdl.add(new GraphDefinition(m)); } } @@ -193,4 +204,19 @@ public class AnnotatedPlotProvider implements PlotProvider2{ } } + + @Override + public Float getPosition(int x, int graph) { + return (float)x; + } + + @Override + public Float getPositionMinimum() { + return 0.0f; + } + + @Override + public Float getPositionMaximum() { + return this.values.size()-1.0f; + } } diff --git a/src/org/hwo/ui/diagram/AnnotatedSortedMapPlotProvider.java b/src/org/hwo/ui/diagram/AnnotatedSortedMapPlotProvider.java index 4288cf2..1f40240 100644 --- a/src/org/hwo/ui/diagram/AnnotatedSortedMapPlotProvider.java +++ b/src/org/hwo/ui/diagram/AnnotatedSortedMapPlotProvider.java @@ -2,6 +2,8 @@ package org.hwo.ui.diagram; import java.util.SortedMap; +import org.hwo.ui.JDiagram; + public class AnnotatedSortedMapPlotProvider extends AnnotatedPlotProvider implements PlotProvider2,PlotLabeler { private SortedMap sortedMap; @@ -28,12 +30,12 @@ public class AnnotatedSortedMapPlotProvider extends AnnotatedPlotProvider imp @Override - public String getAbzisseLabel(Diagram diagram, int pos) { + public String getAbzisseLabel(JDiagram diagram, Double pos) { return ""; } @Override - public String getOrdinateLabel(Diagram diagram, Float value) { + public String getOrdinateLabel(JDiagram diagram, Double value) { return value.toString(); } diff --git a/src/org/hwo/ui/diagram/Diagram.java b/src/org/hwo/ui/diagram/Diagram.java deleted file mode 100644 index fd4d5b9..0000000 --- a/src/org/hwo/ui/diagram/Diagram.java +++ /dev/null @@ -1,356 +0,0 @@ -package org.hwo.ui.diagram; - -import java.awt.Color; -import java.awt.Desktop; -import java.awt.Font; -import java.awt.Graphics2D; -import java.awt.Toolkit; -import java.awt.image.BufferedImage; -import java.io.ObjectInputStream.GetField; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.LinkedList; -import java.util.List; - -public class Diagram { - - private PlotProvider2 plotProvider; - private PlotPainter plotPainter; - - private int x0, - x1, - y0, - y1; - - int yh,xw; - - private Float scaleBorder; - - private Float[] minValues,maxValues; - - private Float[] yscales; - private Float[] yoffsets; - - private boolean[] autoscale; - - private Font font; - - private int numLabels; - - private String labelFormatSpec; - private int xlabel_skip; - - private LinkedList coloredBackgrounds; - - private PlotLabeler defaultLabeler; - - private Color background, - foreground; - - private Float abMinimum, - abMaximum; - - public Diagram(){ - background = Color.WHITE; - foreground = Color.BLACK; - - coloredBackgrounds = new LinkedList(); - plotPainter = new LinePlotPainter(); - font = new Font("Arial", Font.PLAIN, 24); - numLabels = 0; - scaleBorder = 0.1f; - defaultLabeler = new SimplePlotLabeler(); - setPlotProvider(new AnnotatedPlotProvider(Object.class)); - } - - private void updatePlotProviderParams(){ - minValues = new Float[ plotProvider.getMaxOrdinate()+1]; - maxValues = new Float[ plotProvider.getMaxOrdinate()+1]; - yscales = new Float[ plotProvider.getMaxOrdinate()+1]; - yoffsets = new Float[ plotProvider.getMaxOrdinate()+1]; - autoscale = new boolean[ plotProvider.getMaxOrdinate()+1]; - - Arrays.fill(minValues, 0, minValues.length, Float.MAX_VALUE); - Arrays.fill(maxValues, 0, maxValues.length, Float.MIN_VALUE); - Arrays.fill(yscales, 0, yscales.length, new Float(1.0)); - Arrays.fill(yoffsets, 0, yoffsets.length, new Float(0.0)); - } - - public Color getBackground() { - return background; - } - public void setBackground(Color background) { - this.background = background; - } - public Color getForeground() { - return foreground; - } - public void setForeground(Color foreground) { - this.foreground = foreground; - } - - public float getYoffset(int graph) { - return yoffsets[graph]; - } - public void setYoffset(int graph,float yoffset) { - this.yoffsets[graph] = yoffset; - } - public float getYscale(int graph) { - return yscales[graph]; - } - public void setYscale(int graph,float yscale) { - this.yscales[graph] = yscale; - } - - public int getXlabel_skip() { - return xlabel_skip; - } - public void setXlabel_skip(int xlabel_skip) { - this.xlabel_skip = xlabel_skip; - } - - public Font getFont() { - return font; - } - public void setFont(Font font) { - this.font = font; - } - - public int getNumLabels() { - return numLabels; - } - public void setNumLabels(int numLabels) { - this.numLabels = numLabels; - } - - public PlotPainter getPlotPainter() { - return plotPainter; - } - public void setPlotPainter(PlotPainter plotPainter) { - this.plotPainter = plotPainter; - } - - public PlotProvider2 getPlotProvider() { - return plotProvider; - } - public void setPlotProvider(PlotProvider2 plotProvider) { - this.plotProvider = plotProvider; - updatePlotProviderParams(); - } - - public String getLabelFormatSpec() { - return labelFormatSpec; - } - public void setLabelFormatSpec(String labelFormatSpec) { - this.labelFormatSpec = labelFormatSpec; - } - - public List getColoredBackgrounds() { - return coloredBackgrounds; - } - - public void setYMinimum(int graph,Float minimum){ - setYoffset(graph,minimum); - } - public Float getYMinimum(int graph){ - return getYoffset(graph); - } - - public void setYMaximum(int graph,Float maximum){ - setYscale(graph,maximum - yoffsets[graph]); - } - public Float getYMaximum(int graph){ - return getYscale(graph) + yoffsets[graph]; - } - - public void autoscale(int ordinate){ - yscales[ordinate] = (maxValues[ordinate] - minValues[ordinate]) * (1.0f + scaleBorder); - yoffsets[ordinate] = minValues[ordinate] - ((maxValues[ordinate] - minValues[ordinate]) * scaleBorder); - - if (yscales[ordinate] == 0.0f){ - if (yoffsets[ordinate] == 0.0f){ - yoffsets[ordinate] = -1.0f; - yscales[ordinate] = 2.0f * (1.0f + scaleBorder); - } else { - yscales[ordinate] = yoffsets[ordinate] * (1.0f + scaleBorder); - yoffsets[ordinate] -= yscales[ordinate] / 2.0f; - } - } - - System.err.println(String.format("AutoScale Ordinate %d: %f x %f", ordinate, yoffsets[ordinate], yscales[ordinate])); - } - - public void autoScale(){ - for (int i=0;i mw) - mw = lw; - } - - x0 += mw; - - for (int i=0;i<=nLabels;i++){ - String l = this.defaultLabeler.getOrdinateLabel(this, (yoffsets[graph] + (yscales[graph] * i / nLabels))); - int lw = g.getFontMetrics().stringWidth(l); - - g.drawString(l, 2 + (x0 - lw), y0 - (yh * i / nLabels) + (lineHeight/4)); - } - - x0 += 5; - } - x0 += 10; - xw = x1 - x0; - - for (int i=0;i<=nLabels;i++){ - g.drawLine(x0 - 5, y0 - (yh * i / nLabels) , x0, y0 - (yh * i / nLabels)); - } - - for (int i=0;i max[ordinate]) - max[ordinate] = v; - - } else { - plotPainter.reset(); - } - } - } - - for (int i=0;i 0){ + d = Math.log10(minValue); + System.err.format("LS: d=%f\n", d); + if (!isInt(d) & (d < 0)) + d = d - 1; + minDecade = Math.floor(d); + minimum = Math.pow(10, minDecade); + + if (!useMargin){ + double step = minimum; + while ( (minimum + step) <= minValue ){ + minimum += step; + } + minDecade = Math.log10( minimum ); + } + } else { + minDecade = null; + minimum = 0; + } + + d = Math.log10(maxValue); + if (!isInt(d)) + d = d + 1; + maxDecade = Math.floor(d); + maximum = Math.pow(10, maxDecade); + + if (!useMargin){ + double step = maximum / 10.0; + while ( (maximum - step) >= maxValue ){ + maximum -= step; + } + maxDecade = Math.log10( maximum ); + } + + System.err.println(String.format("LogarithmicScaler: min: %f max: %f minDec: %.2f maxDec: %.2f", minimum, maximum, minDecade, maxDecade)); + } + + @Override + public int getPosition(double value) { + double max = maxDecade; + double pos = (Math.log10( value )); + double min = minDecade; + double win = max - min; + + int r = (int)((pos - min) * height / win); + return r; + } + + @Override + public double getValue(int position) { + return 0; + } + + @Override + public double getMinValue() { + return minimum; + } + + @Override + public double getMaxValue() { + return maximum; + } + + @Override + public double getWindow() { + return maximum - minimum; + } + + @Override + public double[] getMarkerHints() { + ArrayList hints = new ArrayList(); + + if (minDecade != null) + { + hints.add(minimum); + + double hValue = minimum; + int decade = minDecade.intValue(); + if (decade < 0) + decade--; + + double step = Math.pow(10, (double)decade ); + + while (hValue < maximum){ + hValue += step; + int nextDecade = new Double(Math.log10( hValue )).intValue(); + if (nextDecade > decade){ + step *= 10.0; + decade = nextDecade; + } + if (decade >= (maxDecade-2)) + hints.add(hValue); + } + } + + double[] result = new double[ hints.size() ]; + for (int i=0;i plots; - ArrayList labels; + ArrayList labels; + ArrayList ordinates; Color[] colors; public SimplePlotProvider(int plots,int points) { this.points = points; this.plots = new ArrayList(); this.labels = new ArrayList(); + this.ordinates = new ArrayList(); this.xmin = 0; this.colors = new Color[plots]; @@ -24,7 +26,8 @@ public class SimplePlotProvider implements PlotProvider { this.plots.add(new Float[points]); this.labels.add(String.format("Plot %d", i)); Arrays.fill(this.plots.get(i), 0.0f); - this.colors[i] = new Color(255,0,0); + this.colors[i] = null; + this.ordinates.add(0); } } @@ -34,33 +37,11 @@ public class SimplePlotProvider implements PlotProvider { public void setXmin(int xmin) { this.xmin = xmin; } - - - - @Override - public int getPoints() { - return this.points; - } - - @Override - public int getPlots() { - return this.plots.size(); - } - - @Override - public Float[][] getMatrix() { - return this.plots.toArray(new Float[][]{}); - } @Override public String getLabel(int plot) { return this.labels.get(plot); } - - @Override - public String getPointLabel(int point) { - return String.format("%d", (this.xmin + point)); - } @Override public Color[] getColors() { @@ -71,5 +52,56 @@ public class SimplePlotProvider implements PlotProvider { Float[] cv = Arrays.copyOf(values, points); this.plots.set(plot, cv); } + + public Float[] getPlot(int plot){ + return this.plots.get(plot); + } + @Override + public int getMaxOrdinate() { + int m = 0; + for (Integer o:ordinates) + if (o > m) + m = o; + return m; + } + + @Override + public int getLength() { + return this.points; + } + + @Override + public int getNumGraphs() { + return this.plots.size(); + } + + @Override + public Float getValue(int x, int graph) { + return this.plots.get(graph)[x]; + } + + @Override + public Float getPosition(int x, int graph) { + return (float)x; + } + + @Override + public int getOrdinate(int graph) { + return this.ordinates.get(graph); + } + + public void setOrdinate(int graph,int ordinate) { + this.ordinates.set(graph, ordinate); + } + + @Override + public Float getPositionMaximum() { + return (float)(this.points-1); + } + @Override + public Float getPositionMinimum() { + return (float)0; + } + } diff --git a/src/org/hwo/ui/diagram/annotation/Plot.java b/src/org/hwo/ui/diagram/annotation/Plot.java index cfe8e49..07803db 100644 --- a/src/org/hwo/ui/diagram/annotation/Plot.java +++ b/src/org/hwo/ui/diagram/annotation/Plot.java @@ -13,4 +13,5 @@ public @interface Plot { public int g() default 0; public int b() default 0; + public int diagram() default 0; }