From 5c3b2f81d9df726729ee9d101abb860f43e7d017 Mon Sep 17 00:00:00 2001 From: Harald Wolff Date: Thu, 28 Apr 2016 16:29:16 +0200 Subject: [PATCH] Diagram: Work in Progress --- src/org/hwo/ui/JDiagram.java | 25 +- .../ui/diagram/AnnotatedDiagramProvider.java | 23 ++ .../hwo/ui/diagram/AnnotatedPlotProvider.java | 196 +++++++++++++ .../AnnotatedSortedMapPlotProvider.java | 40 +++ .../ui/diagram/ArrayDiagramDataProvider.java | 48 ++++ src/org/hwo/ui/diagram/Diagram.java | 261 ++++++++++++------ .../hwo/ui/diagram/DiagramDataProvider.java | 10 + src/org/hwo/ui/diagram/LinePlotPainter.java | 20 ++ src/org/hwo/ui/diagram/PlotLabeler.java | 8 + src/org/hwo/ui/diagram/PlotProvider2.java | 16 ++ src/org/hwo/ui/diagram/SimplePlotLabeler.java | 40 +++ .../hwo/ui/diagram/annotation/Abszisse.java | 9 + src/org/hwo/ui/diagram/annotation/Plot.java | 16 ++ 13 files changed, 633 insertions(+), 79 deletions(-) create mode 100644 src/org/hwo/ui/diagram/AnnotatedDiagramProvider.java create mode 100644 src/org/hwo/ui/diagram/AnnotatedPlotProvider.java create mode 100644 src/org/hwo/ui/diagram/AnnotatedSortedMapPlotProvider.java create mode 100644 src/org/hwo/ui/diagram/ArrayDiagramDataProvider.java create mode 100644 src/org/hwo/ui/diagram/DiagramDataProvider.java create mode 100644 src/org/hwo/ui/diagram/PlotLabeler.java create mode 100644 src/org/hwo/ui/diagram/PlotProvider2.java create mode 100644 src/org/hwo/ui/diagram/SimplePlotLabeler.java create mode 100644 src/org/hwo/ui/diagram/annotation/Abszisse.java create mode 100644 src/org/hwo/ui/diagram/annotation/Plot.java diff --git a/src/org/hwo/ui/JDiagram.java b/src/org/hwo/ui/JDiagram.java index c20cb82..af7b440 100644 --- a/src/org/hwo/ui/JDiagram.java +++ b/src/org/hwo/ui/JDiagram.java @@ -1,5 +1,6 @@ package org.hwo.ui; +import java.awt.Color; import java.awt.Dimension; import java.awt.Font; import java.awt.Graphics; @@ -16,7 +17,7 @@ public class JDiagram extends JPanel { public JDiagram(){ setMinimumSize(new Dimension(80, 80)); - diagram = new Diagram(); + getDiagram(); diagram.setFont( getFont() ); } @@ -26,6 +27,8 @@ public class JDiagram extends JPanel { } public Diagram getDiagram() { + if (diagram==null) + diagram = new Diagram(); return diagram; } public void setDiagram(Diagram diagram) { @@ -57,4 +60,24 @@ public class JDiagram extends JPanel { super.setFont(font); } + @Override + public Color getBackground() { + return getDiagram().getBackground(); + } + @Override + public void setBackground(Color bg) { + getDiagram().setBackground(bg); + repaint(); + } + + @Override + public void setForeground(Color fg) { + getDiagram().setForeground(fg); + repaint(); + } + @Override + public Color getForeground() { + return getDiagram().getForeground(); + } + } diff --git a/src/org/hwo/ui/diagram/AnnotatedDiagramProvider.java b/src/org/hwo/ui/diagram/AnnotatedDiagramProvider.java new file mode 100644 index 0000000..069fd20 --- /dev/null +++ b/src/org/hwo/ui/diagram/AnnotatedDiagramProvider.java @@ -0,0 +1,23 @@ +package org.hwo.ui.diagram; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.SortedSet; + +public class AnnotatedDiagramProvider extends AnnotatedPlotProvider{ + + ArrayList keys; + HashMap objects; + + public AnnotatedDiagramProvider(Class clazz) { + super(clazz); + } + + @Override + public Float getValue(int x, int graph) { + return super.getValue(x, graph); + } + + +} diff --git a/src/org/hwo/ui/diagram/AnnotatedPlotProvider.java b/src/org/hwo/ui/diagram/AnnotatedPlotProvider.java new file mode 100644 index 0000000..f0bf070 --- /dev/null +++ b/src/org/hwo/ui/diagram/AnnotatedPlotProvider.java @@ -0,0 +1,196 @@ +package org.hwo.ui.diagram; + +import java.awt.Color; +import java.beans.MethodDescriptor; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Type; +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; +import java.util.Vector; + +import org.hwo.ui.diagram.annotation.Plot; + +public class AnnotatedPlotProvider implements PlotProvider2{ + + private Class + clazz; + + private GraphDefinition[] + graphDefinitions; + + private int maxOrdinate; + + private Color[] colors; + + private Vector + values; + + public AnnotatedPlotProvider(Class clazz){ + this.setClazz(clazz); + this.setValues(new Object[0]); + } + + public void setClazz(Class clazz) { + this.clazz = clazz; + updateClazz(); + } + public Class getClazz() { + return clazz; + } + + + + public void setValues(Object[] values) { + this.values = new Vector(); + this.values.addAll(Arrays.asList(values)); + } + public void setValues(Vector v){ + this.values = v; + } + public Vector getValues() { + return values; + } + + private void updateClazz(){ + LinkedList gdl = new LinkedList(); + + for (Field f: this.clazz.getDeclaredFields()){ + Plot plot = f.getAnnotation(Plot.class); + if (plot != null){ + 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)); + } + } + + this.colors = new Color[ gdl.size() ]; + + for (GraphDefinition gd: gdl){ + if (gd.getOrdinate() > maxOrdinate) + maxOrdinate = gd.getOrdinate(); + this.colors[ gdl.indexOf(gd) ] = gd.getColor(); + } + + this.graphDefinitions = gdl.toArray(new GraphDefinition[0]); + } + + public Color getColor(int graph){ + return this.colors[graph]; + } + public void setColors(int graph,Color color) { + this.colors[graph] = color; + } + + @Override + public int getNumGraphs() { + return this.graphDefinitions.length; + } + + @Override + public Color[] getColors() { + return this.colors; + } + + public int getMaxOrdinate() { + return maxOrdinate; + } + + public int getLength(){ + return this.values.size(); + } + + public String getLabel(int graph){ + return this.graphDefinitions[graph].getLabel(); + } + + public Float getValue(int x,int graph){ + Object o = this.values.get(x); + if (o==null) + return null; + return this.graphDefinitions[graph].getValue(o); + } + + public int getOrdinate(int graph){ + return this.graphDefinitions[graph].getOrdinate(); + } + + class GraphDefinition{ + + Method method; + Field field; + + String label; + int ordinate; + + Color color; + + public GraphDefinition(Method method){ + this.method = method; + this.setPlot(method.getAnnotation(Plot.class)); + } + public GraphDefinition(Field field){ + this.field = field; + this.field.setAccessible(true); + this.setPlot(field.getAnnotation(Plot.class)); + } + + private void setPlot(Plot plot){ + this.label = plot.label(); + this.ordinate = plot.ordinate(); + this.color = new Color(plot.r(), plot.g(), plot.b()); + } + + public int getOrdinate() { + return ordinate; + } + public String getLabel() { + return label; + } + + public Color getColor() { + return color; + } + + public Float getValue(Object o){ + try { + if (field != null){ + if (field.getType().equals(Integer.class)){ + return ((Integer)field.get(o)).floatValue(); + }; + if (field.getType().equals(Double.class)){ + return ((Double)field.get(o)).floatValue(); + } + if (field.getType().equals(Float.class)){ + return (Float)field.get(o); + } + } + if (method != null){ + if (method.getReturnType().equals(Integer.class)){ + return ((Integer)method.invoke(o, null)).floatValue(); + } + if (method.getReturnType().equals(Double.class)){ + return ((Double)method.invoke(o, null)).floatValue(); + } + if (method.getReturnType().equals(Float.class)){ + return ((Float)method.invoke(o, null)); + } + } + } catch (IllegalAccessException illegalAccessException){ + illegalAccessException.printStackTrace(); + return null; + } catch (InvocationTargetException invocationTargetException){ + invocationTargetException.printStackTrace(); + return null; + } + return null; + } + + } +} diff --git a/src/org/hwo/ui/diagram/AnnotatedSortedMapPlotProvider.java b/src/org/hwo/ui/diagram/AnnotatedSortedMapPlotProvider.java new file mode 100644 index 0000000..4288cf2 --- /dev/null +++ b/src/org/hwo/ui/diagram/AnnotatedSortedMapPlotProvider.java @@ -0,0 +1,40 @@ +package org.hwo.ui.diagram; + +import java.util.SortedMap; + +public class AnnotatedSortedMapPlotProvider extends AnnotatedPlotProvider implements PlotProvider2,PlotLabeler { + + private SortedMap sortedMap; + private Object[] keys; + private T[] values; + + public AnnotatedSortedMapPlotProvider(Class clazz) { + super(clazz); + + this.sortedMap = null; + + } + + public void setSortedMap(SortedMap sortedMap) { + this.sortedMap = sortedMap; + } + public SortedMap getSortedMap() { + return sortedMap; + } + + public void sortedMapChanged(){ + this.keys = this.sortedMap.keySet().toArray(); + } + + + @Override + public String getAbzisseLabel(Diagram diagram, int pos) { + return ""; + } + + @Override + public String getOrdinateLabel(Diagram diagram, Float value) { + return value.toString(); + } + +} diff --git a/src/org/hwo/ui/diagram/ArrayDiagramDataProvider.java b/src/org/hwo/ui/diagram/ArrayDiagramDataProvider.java new file mode 100644 index 0000000..3c680fe --- /dev/null +++ b/src/org/hwo/ui/diagram/ArrayDiagramDataProvider.java @@ -0,0 +1,48 @@ +package org.hwo.ui.diagram; + +public class ArrayDiagramDataProvider implements DiagramDataProvider { + + private Object[] values; + private Float[] indeces; + + public ArrayDiagramDataProvider() { + this.values = new Object[0]; + this.indeces = new Float[0]; + } + + public void setValues(Object[] values) { + this.values = values; + + this.indeces = new Float[values.length]; + for (int i=0;i coloredBackgrounds; + private PlotLabeler defaultLabeler; + + private Color background, + foreground; + + private Float abMinimum, + abMaximum; + public Diagram(){ + background = Color.WHITE; + foreground = Color.BLACK; + coloredBackgrounds = new LinkedList(); - yoffset = -1.0f; - yscale = 2.0f; - plotProvider = new SimplePlotProvider(2, 2); plotPainter = new LinePlotPainter(); font = new Font("Arial", Font.PLAIN, 24); numLabels = 0; - labelFormatSpec = "%.4f"; - - coloredBackgrounds.add(new ColoredBackground(new Color(0.7f, 1.0f, 0.7f),-0.25f,0.25f)); - coloredBackgrounds.add(new ColoredBackground(new Color(1.0f, 1.0f, 0.5f),-0.5f,-0.25f)); - coloredBackgrounds.add(new ColoredBackground(new Color(1.0f, 1.0f, 0.5f),0.25f,0.5f)); - - + scaleBorder = 0.1f; + defaultLabeler = new SimplePlotLabeler(); + setPlotProvider(new AnnotatedPlotProvider(Object.class)); } - public float getYoffset() { - return yoffset; + 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 void setYoffset(float yoffset) { - this.yoffset = yoffset; + + public Color getBackground() { + return background; } - public float getYscale() { - return yscale; + public void setBackground(Color background) { + this.background = background; } - public void setYscale(float yscale) { - this.yscale = yscale; + 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() { @@ -86,11 +130,12 @@ public class Diagram { this.plotPainter = plotPainter; } - public PlotProvider getPlotProvider() { + public PlotProvider2 getPlotProvider() { return plotProvider; } - public void setPlotProvider(PlotProvider plotProvider) { + public void setPlotProvider(PlotProvider2 plotProvider) { this.plotProvider = plotProvider; + updatePlotProviderParams(); } public String getLabelFormatSpec() { @@ -104,42 +149,56 @@ public class Diagram { return coloredBackgrounds; } - public void setYMinimum(Float minimum){ - setYoffset(minimum); + public void setYMinimum(int graph,Float minimum){ + setYoffset(graph,minimum); } - public Float getYMinimum(){ - return getYoffset(); + public Float getYMinimum(int graph){ + return getYoffset(graph); } - public void setYMaximum(Float maximum){ - setYscale(maximum - yoffset); + public void setYMaximum(int graph,Float maximum){ + setYscale(graph,maximum - yoffsets[graph]); } - public Float getYMaximum(){ - return getYscale() + yoffset; + 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(){ - Float max = Float.MIN_VALUE,min = Float.MAX_VALUE; - Float[][] matrix = this.plotProvider.getMatrix(); - - - for (Float[] p:matrix){ - for (Float value: p){ - if (value == null) - continue; - if (value < min) - min = value; - if (value > max) - max = value; - } + for (int i=0;i x0) - x0 = lw; - } - for (int i=0;i<=nLabels;i++){ - String l = String.format(labelFormatSpec, (yoffset + (yscale * i / nLabels))); - int lw = g.getFontMetrics().stringWidth(l); + 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); + + if (lw > mw) + mw = lw; + } - g.drawString(l, 2 + (x0 - lw), y0 - (yh * i / nLabels) + (lineHeight/4)); + 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; @@ -206,16 +276,16 @@ public class Diagram { 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