org.nees.rpi.vis.ui.XYChartPanelProxy.java Source code

Java tutorial

Introduction

Here is the source code for org.nees.rpi.vis.ui.XYChartPanelProxy.java

Source

/**
 * 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);
        }
    }
}