Java tutorial
/** * Copyright (c) 2004-2007 Rensselaer Polytechnic Institute * Copyright (c) 2007 NEES Cyberinfrastructure Center * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * For more information: http://nees.rpi.edu/3dviewer/ */ package org.nees.rpi.vis.ui; //JFreeChart import org.jfree.chart.*; import org.jfree.data.xy.XYSeriesCollection; import org.jfree.data.xy.XYSeries; import org.jfree.chart.plot.*; import org.jfree.ui.RectangleEdge; //viewer3D import org.nees.rpi.vis.viewer3d.SelectableShape3D; import org.nees.rpi.vis.model.DVShape; import org.nees.rpi.vis.ui.widgets.VisSaveJChartPlotToImageButton; //util import org.nees.rpi.util.SelectionGroup; import javax.swing.*; import java.awt.event.ActionEvent; import java.awt.*; import java.util.Hashtable; import java.util.ArrayList; /** * */ public class XYChartPanelProxy { private JFreeChart chart; private ChartPanel chartPanel; private JPanel toolPanel; private JPanel chartAreaPanel; private XYSeriesCollection dataSet; private SelectionGroup selectionGroup; /** * A collection of all the selected shapes this class is aware of. * * Note that this duplicates functionality in the selectionGroup * instance variable but because the logic of SelectionGroup is tricky * and the SelectableShape3D objects stored in it do not capture all * the X/Y series information, the DVShape objects needed to be stored * also. However, this is just a hack until the selection code is * refactored and is decoupled from this class into a seperate * Selection Manager class. * * TODO: refactor code to decouple selection code into a sperate object */ private ArrayList<DVShape> selectedShapes = new ArrayList<DVShape>(); private String domainAxisLabel = "Time"; private String rangeAxisLabel = "Reading"; /** * A lookup counter used to store the number * of plotted series reffering to a given unit */ private Hashtable<String, Integer> unitsXCounter = new Hashtable<String, Integer>(); private Hashtable<String, Integer> unitsYCounter = new Hashtable<String, Integer>(); /** the profile plot frame */ private ProfilePlotFrame profilePlotter = new ProfilePlotFrame(); public XYChartPanelProxy() { this(400, 200); } public XYChartPanelProxy(int width, int height) { selectionGroup = new SelectionGroup(); selectionGroup.setSelection(true); dataSet = new XYSeriesCollection(); chart = ChartFactory.createXYLineChart(null, domainAxisLabel, rangeAxisLabel, dataSet, PlotOrientation.VERTICAL, true, true, false); chart.setBackgroundPaint(Color.WHITE); chart.getLegend().setPosition(RectangleEdge.RIGHT); chartPanel = new ChartPanel(chart); chartPanel.setPreferredSize(new java.awt.Dimension(width, height)); chartPanel.setFillZoomRectangle(true); chartPanel.setHorizontalAxisTrace(true); chartPanel.setVerticalAxisTrace(true); toolPanel = new JPanel(); toolPanel.setOpaque(false); toolPanel.setLayout(new BoxLayout(toolPanel, BoxLayout.Y_AXIS)); toolPanel.setBorder(BorderFactory.createTitledBorder("Plot Control")); toolPanel.setPreferredSize(new Dimension(155, 100)); chartAreaPanel = new JPanel(); chartAreaPanel.setOpaque(true); chartAreaPanel.setBackground(Color.white); chartAreaPanel.setLayout(new BorderLayout()); chartAreaPanel.add(chartPanel, BorderLayout.CENTER); chartAreaPanel.add(toolPanel, BorderLayout.WEST); initClearSelectionButton(toolPanel); initResetPlotButton(toolPanel); initSaveToImageButton(toolPanel); initShowAsProfilePlotButton(toolPanel); } private void initClearSelectionButton(Container parent) { VisLinkButton clearSelect = new VisLinkButton("Clear Selection(s)", getClass().getResource("/images/plotclear.png")); clearSelect.setToolTipText("Remove all series from the plot to clear it"); clearSelect.addActionListener(new ClearSelectionAction()); parent.add(clearSelect); } private void initResetPlotButton(Container parent) { VisLinkButton plotReset = new VisLinkButton("Reset Plot Zoom", getClass().getResource("/images/plotreset.png")); plotReset.setToolTipText("Reset the plot zoom level"); plotReset.addActionListener(new ResetPlotAction()); parent.add(plotReset); } private void initSaveToImageButton(Container parent) { VisLinkButton savePlot = new VisSaveJChartPlotToImageButton(VisUtils.getParentFrame(chartAreaPanel), chart); parent.add(savePlot); } private void initShowAsProfilePlotButton(Container parent) { VisLinkButton profilePlot = new VisLinkButton("View as Profile Plot", getClass().getResource("/images/plotprofile.png")); profilePlot.setToolTipText("Displays the currently selected sensors in a new profile plot"); profilePlot.addActionListener(new ShowAsProfilePlotAction()); parent.add(profilePlot); } public void setToolPanelVisible(boolean value) { toolPanel.setVisible(value); } public javax.swing.JPanel getChartPanel() { return chartAreaPanel; } public void removeAllSeries() { dataSet.removeAllSeries(); selectedShapes.clear(); selectionGroup.removeAll(); selectionGroup.setSelection(true); chartPanel.restoreAutoBounds(); clearAxisLabels(); } public void processDataObject(DVShape dvShape) { if (selectedShapes.contains(dvShape)) removeShape(dvShape); else addShape(dvShape); } private void addShape(DVShape dvShape) { selectedShapes.add(dvShape); dataSet.addSeries((XYSeries) dvShape.getDataSet()); selectionGroup.add((SelectableShape3D) dvShape.getShape3D()); addAxisLabels(dvShape); } private void removeShape(DVShape dvShape) { selectedShapes.remove(dvShape); dataSet.removeSeries((XYSeries) dvShape.getDataSet()); if (dataSet.getSeries().size() == 0) chartPanel.restoreAutoBounds(); selectionGroup.remove((SelectableShape3D) dvShape.getShape3D()); dvShape.unloadDataSet(); removeAxisLabels(dvShape); } private void clearAxisLabels() { unitsXCounter.clear(); unitsYCounter.clear(); resetAxisLabels(); } private void removeAxisLabels(DVShape dvShape) { int xCount = 0, yCount = 0; String xunit = dvShape.getXChannel().unit().get(); String yunit = dvShape.getYChannel().unit().get(); xunit = xunit == null ? domainAxisLabel : xunit; yunit = yunit == null ? rangeAxisLabel : yunit; xCount = unitsXCounter.get(xunit); yCount = unitsYCounter.get(yunit); unitsXCounter.put(xunit, --xCount); unitsYCounter.put(yunit, --yCount); resetAxisLabels(); } private void addAxisLabels(DVShape dvShape) { String dAxisLabel = dvShape.getXChannel().unit().get(); dAxisLabel = dAxisLabel == null ? domainAxisLabel : dAxisLabel; String rAxisLabel = dvShape.getYChannel().unit().get(); rAxisLabel = rAxisLabel == null ? rangeAxisLabel : rAxisLabel; int xCount = 0, yCount = 0; if (unitsXCounter.containsKey(dAxisLabel)) xCount = unitsXCounter.get(dAxisLabel); unitsXCounter.put(dAxisLabel, ++xCount); if (unitsYCounter.containsKey(rAxisLabel)) yCount = unitsYCounter.get(rAxisLabel); unitsYCounter.put(rAxisLabel, ++yCount); resetAxisLabels(); } private void resetAxisLabels() { chart.getXYPlot().getDomainAxis().setLabel(processLabelfromUnits(unitsXCounter, domainAxisLabel)); chart.getXYPlot().getRangeAxis().setLabel(processLabelfromUnits(unitsYCounter, rangeAxisLabel)); } private String processLabelfromUnits(Hashtable<String, Integer> h, String defaultLabel) { String axisLabel = ""; ArrayList<String> units = new ArrayList<String>(); for (String key : h.keySet()) if (h.get(key) > 0) units.add(key); for (String s : units) axisLabel += s + ", "; if (axisLabel.length() == 0) axisLabel = defaultLabel; else axisLabel = axisLabel.substring(0, axisLabel.length() - 2); return axisLabel; } class ClearSelectionAction extends AbstractAction { public void actionPerformed(ActionEvent e) { XYChartPanelProxy.this.removeAllSeries(); } } class ResetPlotAction extends AbstractAction { public void actionPerformed(ActionEvent e) { chartPanel.restoreAutoBounds(); } } class ShowAsProfilePlotAction extends AbstractAction { public void actionPerformed(ActionEvent e) { // reset the plot from the last usage profilePlotter.reset(); // add the selected time series to the profile plot and plot it if (selectedShapes.size() > 0) { profilePlotter.setTime(selectedShapes.get(0).getXChannel().data()); for (DVShape shape : selectedShapes) { profilePlotter.addSeries(shape.getName(), shape.getYChannel().data(), shape.getZ()); } profilePlotter.plot(); } profilePlotter.setVisible(true); } } }