// This file is part of PleoCommand: // Interactively control Pleo with psychobiological parameters // // Copyright (C) 2010 Oliver Hoffmann - Hoffmann_Oliver@gmx.de // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 51 Franklin Street, Boston, USA. package pleocmd.itfc.gui.dgr; import java.awt.BasicStroke; import java.awt.Color; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.geom.Point2D.Double; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; import javax.swing.JMenu; import javax.swing.JMenuItem; import javax.swing.JPopupMenu; public final class DiagramDataSet { public enum DiagramType { LineDiagram, BarDiagram, ScatterPlotDiagram, IntersectionDiagram } private static final double MIN_VAL_PER_UNIT = 0.0000001; private final Diagram diagram; private final List<Double> points = new ArrayList<Double>(); private boolean prepared; private String label; private Pen pen; private DiagramType type = DiagramType.LineDiagram; private double valuePerUnitX = 1.0; private double valuePerUnitY = 1.0; private double cachedValueToPixXIncr; private double cachedValueToPixYIncr; private double cachedValueToPixXFactor; private double cachedValueToPixYFactor; protected DiagramDataSet(final Diagram diagram, final String label) { this.diagram = diagram; this.label = label; diagram.addDataSet(this); } public Diagram getDiagram() { return diagram; } public List<Double> getPoints() { return Collections.unmodifiableList(points); } public void setPoints(final List<Double> points) { synchronized (diagram) { this.points.clear(); this.points.addAll(points); prepared = false; diagram.repaint(); } } public String getLabel() { return label; } public void setLabel(final String label) { synchronized (diagram) { this.label = label; diagram.repaint(); } } public Pen getPen() { return pen; } public void setPen(final Pen pen) { synchronized (diagram) { this.pen = pen; diagram.repaint(); } } public boolean isPenAutomatic() { return pen == null; } public DiagramType getType() { return type; } public void setType(final DiagramType type) { synchronized (diagram) { this.type = type; diagram.repaint(); } } public double getValuePerUnitX() { return valuePerUnitX; } public void setValuePerUnitX(final double valuePerUnitX) { synchronized (diagram) { this.valuePerUnitX = valuePerUnitX; diagram.repaint(); } } public double getValuePerUnitY() { return valuePerUnitY; } public void setValuePerUnitY(final double valuePerUnitY) { synchronized (diagram) { this.valuePerUnitY = valuePerUnitY; diagram.repaint(); } } public void addPoint(final Double point) { synchronized (diagram) { points.add(point); prepared = false; diagram.repaint(); } } public void addSequence(final int[] values) { addSequence(values, 0); } public void addSequence(final int[] values, final int xStart) { addSequence(values, xStart, 1); } public void addSequence(final int[] values, final int xStart, final int xIncr) { synchronized (diagram) { int x = xStart; for (final int value : values) { points.add(new Double(x, value)); x += xIncr; } prepared = false; diagram.repaint(); } } public void addSequence(final double[] values) { addSequence(values, 0); } public void addSequence(final double[] values, final double xStart) { addSequence(values, xStart, 1); } public void addSequence(final double[] values, final double xStart, final int xIncr) { double x = xStart; for (final double value : values) { points.add(new Double(x, value)); x += xIncr; } prepared = false; diagram.repaint(); } void prepare() { if (prepared) return; prepared = true; if (type == DiagramType.LineDiagram) Collections.sort(points, new Comparator<Double>() { @Override public int compare(final Double p1, final Double p2) { return p1.x < p2.x ? -1 : p1.x > p2.x ? 1 : 0; } }); } public boolean isValid() { return !points.isEmpty() && valuePerUnitX >= MIN_VAL_PER_UNIT && valuePerUnitY >= MIN_VAL_PER_UNIT; } void updateCache() { cachedValueToPixXIncr = -diagram.getXAxis().getCachedMinVisUnit(); cachedValueToPixXFactor = diagram.getXAxis().getCachedPixelPerUnit(); cachedValueToPixYIncr = -diagram.getYAxis().getCachedMinVisUnit(); cachedValueToPixYFactor = diagram.getYAxis().getCachedPixelPerUnit(); } double valueToPixelX(final double value) { return (value / valuePerUnitX + cachedValueToPixXIncr) * cachedValueToPixXFactor; } double valueToPixelY(final double value) { return (value / valuePerUnitY + cachedValueToPixYIncr) * cachedValueToPixYFactor; } protected void createMenu(final JPopupMenu parent) { final JMenu menu = new JMenu("DataSet " + getLabel()); parent.add(menu); JMenuItem item = new JMenuItem("Set Default Pen"); menu.add(item); item.addActionListener(new ActionListener() { @Override public void actionPerformed(final ActionEvent e) { setPen(null); } }); final JMenu colorMenu = new JMenu("Set Color"); menu.add(colorMenu); for (int i = 0; i < Diagram.getDefaultColorCount(); ++i) { final int index = i; item = new JMenuItem(Diagram.getDefaultColor(i).getName()); item.setForeground(Diagram.getDefaultColor(i)); colorMenu.add(item); item.addActionListener(new ActionListener() { @Override public void actionPerformed(final ActionEvent e) { changePen(Diagram.getDefaultColor(index)); } }); item = new JMenuItem("dark " + Diagram.getDefaultColor(i).getName()); item.setForeground(Diagram.getDefaultColor(i).makeDarker()); colorMenu.add(item); item.addActionListener(new ActionListener() { @Override public void actionPerformed(final ActionEvent e) { changePen(Diagram.getDefaultColor(index).makeDarker()); } }); } final JMenu swMenu = new JMenu("Set Stroke Width"); menu.add(swMenu); for (float i = 0.25f; i <= 4.0f; i += 0.25f) { final float index = i; item = new JMenuItem(String.format("%.2f", i)); swMenu.add(item); item.addActionListener(new ActionListener() { @Override public void actionPerformed(final ActionEvent e) { changePen(index); } }); } final JMenu stMenu = new JMenu("Set Stroke Type"); menu.add(stMenu); item = new JMenuItem("solid"); stMenu.add(item); item.addActionListener(new ActionListener() { @Override public void actionPerformed(final ActionEvent e) { changePen(new float[] { 1 }); } }); item = new JMenuItem("dotted"); stMenu.add(item); item.addActionListener(new ActionListener() { @Override public void actionPerformed(final ActionEvent e) { changePen(new float[] { 2, 5 }); } }); item = new JMenuItem("dashed"); stMenu.add(item); item.addActionListener(new ActionListener() { @Override public void actionPerformed(final ActionEvent e) { changePen(new float[] { 10, 10 }); } }); item = new JMenuItem("dash-dotted"); stMenu.add(item); item.addActionListener(new ActionListener() { @Override public void actionPerformed(final ActionEvent e) { changePen(new float[] { 10, 6, 2, 6 }); } }); } public void changePen(final Color color) { final BasicStroke stroke = pen == null ? new BasicStroke(2.0f) : pen .getStroke(); setPen(new Pen(color, stroke)); } public void changePen(final float strokeWidth) { final Color color = pen == null ? diagram.detectPen( diagram.getDataSets().indexOf(this)).getColor() : pen .getColor(); final BasicStroke stroke = new BasicStroke(strokeWidth, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_MITER, 10.0f, pen == null ? null : pen.getStroke().getDashArray(), 0.0f); setPen(new Pen(color, stroke)); } public void changePen(final float[] dash) { final Color color = pen == null ? diagram.detectPen( diagram.getDataSets().indexOf(this)).getColor() : pen .getColor(); final BasicStroke stroke = new BasicStroke(pen == null ? 2.0f : pen .getStroke().getLineWidth(), BasicStroke.CAP_SQUARE, BasicStroke.JOIN_MITER, 10.0f, dash, 0.0f); setPen(new Pen(color, stroke)); } }