java-org.hwo.ui/src/org/hwo/ui/JDiagram.java

577 lines
14 KiB
Java
Raw Normal View History

2015-06-24 23:32:14 +02:00
package org.hwo.ui;
2016-04-28 16:29:16 +02:00
import java.awt.Color;
2015-06-24 23:32:14 +02:00
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Toolkit;
2015-06-24 23:32:14 +02:00
import javax.swing.JComponent;
import javax.swing.JPanel;
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;
2016-10-28 10:47:14 +02:00
import org.hwo.ui.diagram.PlotProviderListener;
import org.hwo.ui.diagram.Scaler;
import org.hwo.ui.diagram.SimplePlotLabeler;
import org.hwo.ui.diagram.SimplePlotProvider;
2015-06-24 23:32:14 +02:00
2016-10-28 10:47:14 +02:00
public class JDiagram extends JComponent implements PlotProviderListener {
private PlotProvider2
plotProvider;
private PlotLabeler
defaultLabeler,
abszissLabeler;
// 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;
2015-06-24 23:32:14 +02:00
private OrdinateView[]
ordinateViews;
2015-06-24 23:32:14 +02:00
private PlotPainter[]
plotPainters;
2015-06-24 23:32:14 +02:00
public JDiagram(){
setMinimumSize(new Dimension(80, 80));
setDoubleBuffered(true);
2016-10-28 10:47:14 +02:00
defaultLabeler = new SimplePlotLabeler();
abszissLabeler = defaultLabeler;
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));
2015-06-24 23:32:14 +02:00
}
public void setPlotProvider(PlotProvider2 plotProvider) {
2016-10-28 10:47:14 +02:00
if (this.plotProvider != null)
this.plotProvider.removePlotProviderListener(this);
this.plotProvider = plotProvider;
2016-10-28 10:47:14 +02:00
if (this.plotProvider != null)
this.plotProvider.addPlotProviderListener(this);
fundamentalsChanged();
2015-06-24 23:32:14 +02:00
}
public PlotProvider2 getPlotProvider() {
return plotProvider;
2015-06-24 23:32:14 +02:00
}
public boolean isAutoOrdinateLabeling() {
return autoOrdinateLabeling;
}
public void setAutoOrdinateLabeling(boolean autoOrdinateLabeling) {
this.autoOrdinateLabeling = autoOrdinateLabeling;
2015-06-24 23:32:14 +02:00
}
public boolean isDrawHorizontalGrid() {
return drawHorizontalGrid;
2015-06-24 23:32:14 +02:00
}
public void setDrawHorizontalGrid(boolean drawHorizontalGrid) {
this.drawHorizontalGrid = drawHorizontalGrid;
2015-06-24 23:32:14 +02:00
}
public boolean isDrawVerticalGrid() {
return drawVerticalGrid;
}
public void setDrawVerticalGrid(boolean drawVerticalGrid) {
this.drawVerticalGrid = drawVerticalGrid;
2015-06-24 23:32:14 +02:00
}
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<plotProvider.getNumGraphs();n++)
plotPainters[n] = pp;
2015-06-24 23:32:14 +02:00
}
public Scaler getScaler(int ordinate){
return this.ordinateViews[ordinate].scaler;
2015-06-24 23:32:14 +02:00
}
public void setScaler(int ordinate,Scaler scaler){
this.ordinateViews[ordinate].scaler = scaler;
2015-06-24 23:32:14 +02:00
}
public PlotPainter getPlotPainter(int graph){
return this.plotPainters[graph];
2016-04-28 16:29:16 +02:00
}
public void setPlotPainter(int graph,PlotPainter plotPainter){
this.plotPainters[graph] = plotPainter;
2016-04-28 16:29:16 +02:00
}
public int getAbszissLabels() {
return nAbszissLabels;
}
public void setAbszissLabels(int nAbszissLabels) {
this.nAbszissLabels = nAbszissLabels;
}
public int getOrdinateLabels() {
return nOrdinateLabels;
}
public void setOrdinateLabels(int nOrdinateLabels) {
this.nOrdinateLabels = nOrdinateLabels;
}
public Color getOrdinateColor(int ordinate){
return this.ordinateViews[ ordinate ].colDraw;
}
public void setOrdinateColor(int ordinate,Color color){
int r,g,b;
this.ordinateViews[ ordinate ].colDraw = color;
r = (color.getRed() + 768)/4;
g = (color.getGreen() + 768)/4;
b = (color.getBlue() + 768)/4;
this.ordinateViews[ ordinate ].colGrid = new Color(r,g,b);
}
public boolean isPreferLabelHints() {
return preferLabelHints;
}
public void setPreferLabelHints(boolean preferLabelHints) {
this.preferLabelHints = preferLabelHints;
2016-04-28 16:29:16 +02:00
}
public boolean isAutoScale() {
return autoScale;
}
public void setAutoScale(boolean autoScale) {
this.autoScale = autoScale;
}
public boolean isAutoScaleMargins() {
return autoScaleMargins;
}
public void setAutoScaleMargins(boolean autoScaleMargins) {
this.autoScaleMargins = autoScaleMargins;
}
public PlotLabeler getAbszissLabeler() {
return abszissLabeler;
}
public void setAbszissLabeler(PlotLabeler abszissLabeler) {
this.abszissLabeler = abszissLabeler;
}
public void autoscale(){
int ordinate;
Double[] max,min;
System.err.println("AutoScale...");
max = new Double[this.plotProvider.getMaxOrdinate()+1];
min = new Double[this.plotProvider.getMaxOrdinate()+1];
for (int graph=0; graph < this.plotProvider.getNumGraphs(); graph++){
ordinate = this.plotProvider.getOrdinate(graph);
for (int n=0;n<this.plotProvider.getLength(); n++){
Float value = this.plotProvider.getValue(n, graph);
if (value != null)
{
if ((min[ordinate] == null) || (value < min[ordinate]))
min[ordinate] = value.doubleValue();
if ((max[ordinate] == null) || (value > max[ordinate]))
max[ordinate] = value.doubleValue();
};
}
}
for (int i=0;i<this.plotProvider.getMaxOrdinate()+1;i++){
if (min[i] == null)
min[i] = 0.0;
if (max[i] == null)
max[i] = 1.0;
System.err.format("MIN: %f Max: %f\n", min[i], max[i]);
this.ordinateViews[i].scaler.scale(min[i], max[i], autoScaleMargins);
}
}
2016-04-28 16:29:16 +02:00
@Override
public void paint(Graphics g) {
screenDPI = Toolkit.getDefaultToolkit().getScreenResolution();
fontLineHeight = getFont().getSize() * screenDPI / 72;
plotHeight = getHeight() - bTop - bBottom - fontLineHeight - axMarkerLength;
plotWidth = getWidth() - bLeft - bRight;
g.setFont( getFont() );
// Hintergrund zeichnen
g.setColor(getBackground());
g.fillRect(0, 0, getWidth(), getHeight());
if (autoScale)
this.autoscale();
paintOrdinates ((Graphics2D) g);
paintAbszisse ((Graphics2D) g);
paintGraphs ((Graphics2D) g);
}
public double[] getordinateLabelHints(int ordinate){
double[] scalerHints = this.ordinateViews[ordinate].scaler.getMarkerHints();
double[] hints = null;
int nHints = autoOrdinateLabeling ? plotHeight / (fontLineHeight * 2) : nOrdinateLabels;
int n;
if ((nHints > 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;
2016-04-28 16:29:16 +02:00
}
public void paintOrdinates(Graphics2D g){
double[][] labelValues = new double[ ordinateViews.length ][];
Integer last_y = null,
y = null,
d = null;
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,
ordinate,
labelValues[ordinate][i]
);
labelWidths[i] = g.getFontMetrics().stringWidth(labels[i]);
if (labelWidths[i] > maxWidth)
maxWidth = labelWidths[i];
}
plotWidth -= maxWidth + 5;
last_y = null;
for (int i=0; i<=nMarkers ;i++){
y = bTop + plotHeight - this.ordinateViews[ ordinate ].scaler.getPosition(labelValues[ordinate][i]) + (fontLineHeight/4);
if (last_y == null){
d = null;
} else {
d = y -last_y;
if (d<0)
d = -d;
};
if ((d == null) || (d > fontLineHeight )) {
g.drawString(
labels[i],
getWidth() - bRight - plotWidth - labelWidths[i],
y
);
last_y = y;
}
}
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
);
if (nMarker > 0)
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<this.plotProvider.getLength(); n++){
int x,y;
Float value = this.plotProvider.getValue(n, graph);
Float position = this.plotProvider.getPosition(n, graph);
if ((value != null) && (position != null) )
{
x = getWidth() - bRight - plotWidth + (int)((position - abszissMinimum) * plotWidth / abszissWindow);
y = bTop + plotHeight - this.ordinateViews[ ordinate ].scaler.getPosition(value);
this.plotPainters[ graph ].paintPoint(g, graphColor, x, y);
};
}
}
}
/*
g.setColor(foreground);
g.drawLine(x0, y0 + 5, x0, y1 - 10);
g.drawLine(x0, y1 - 10 , x0 - 5, y1 - 5);
g.drawLine(x0, y1 - 10 , x0 + 5, y1 - 5);
g.drawLine(x0, y0, x1 + 10, y0);
g.drawLine(x1 + 10 , y0, x1 + 5, y0 - 5);
g.drawLine(x1 + 10 , y0, x1 + 5, y0 + 5);
Color[] colors = this.plotProvider.getColors();
double[] min,max;
min = new double[this.plotProvider.getMaxOrdinate()+1];
max = new double[this.plotProvider.getMaxOrdinate()+1];
Arrays.fill(min, double.MAX_VALUE);
Arrays.fill(max, double.MIN_VALUE);
for (int n=0;n<this.plotProvider.getNumGraphs();n++){
int ordinate = this.plotProvider.getOrdinate(n);
plotPainter.reset();
for (int i=0;i<this.plotProvider.getLength();i++){
int x,y;
double v = this.plotProvider.getValue(i, n);
if (v != null){
x = point2x(i);
y = value2y(ordinate,v);
plotPainter.paintPoint(g, colors[n], x, y);
if (v < min[ordinate])
min[ordinate] = v;
if (v > max[ordinate])
max[ordinate] = v;
} else {
plotPainter.reset();
}
}
}
for (int i=0;i<this.autoscale.length;i++){
if (this.autoscale[i]){
if (!(this.minValues[i].equals(min[i]) && this.maxValues[i].equals(max[i]))){
this.minValues[i] = min[i];
this.maxValues[i] = max[i];
this.autoscale(i);
rescaled = true;
}
}
}
if (rescaled){
this.plot(g,width,height);
}
}
*/
class OrdinateView {
int num;
Color colDraw,
colGrid;
int ordinateLabelWidth;
Scaler scaler;
public OrdinateView(int num) {
this.num = num;
this.colDraw = Color.BLACK;
this.colGrid = Color.LIGHT_GRAY;
this.scaler = new LinearScaler();
}
Scaler getScaler(){
return this.scaler;
}
void setScaler(Scaler scaler){
this.scaler = scaler;
}
}
2016-10-28 10:47:14 +02:00
@Override
public void fundamentalsChanged(PlotProvider2 plotProvider) {
fundamentalsChanged();
}
2015-06-24 23:32:14 +02:00
}