ucar.unidata.idv.control.chart.ChartHolder.java Source code

Java tutorial

Introduction

Here is the source code for ucar.unidata.idv.control.chart.ChartHolder.java

Source

/*
 * This file is part of McIDAS-V
 *
 * Copyright 2007-2019
 * Space Science and Engineering Center (SSEC)
 * University of Wisconsin - Madison
 * 1225 W. Dayton Street, Madison, WI 53706, USA
 * http://www.ssec.wisc.edu/mcidas
 * 
 * All Rights Reserved
 * 
 * McIDAS-V is built on Unidata's IDV and SSEC's VisAD libraries, and
 * some McIDAS-V source code is based on IDV and VisAD source code.  
 * 
 * McIDAS-V is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 * 
 * McIDAS-V 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 Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser Public License
 * along with this program.  If not, see http://www.gnu.org/licenses.
 */

package ucar.unidata.idv.control.chart;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
import java.util.TimeZone;

import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;

import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.AxisLocation;
import org.jfree.chart.axis.DateAxis;
import org.jfree.chart.axis.ValueAxis;
import org.jfree.chart.event.ChartChangeEvent;
import org.jfree.chart.plot.Plot;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYItemRenderer;
import org.jfree.data.xy.XYDataset;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ucar.unidata.ui.ImageUtils;
import ucar.unidata.util.FileManager;
import ucar.unidata.util.GuiUtils;
import ucar.unidata.util.LogUtil;
import ucar.unidata.util.Misc;

/**
 * Class ChartHolder hodls a chart
 *
 *
 * @author IDV Development Team
 * @version $Revision: 1.9 $
 */
public class ChartHolder {

    /** my manager */
    private ChartManager chartManager;

    /** last axis side */
    protected AxisLocation lastSide;

    /** how many params */
    private int paramCount = 0;

    /** am I being shown */
    private boolean beingShown = false;

    /** show thumbnail image */
    private boolean showThumbnail = true;

    /** my name */
    private String name = "Plot";

    /** The chart */
    private JFreeChart chart;

    /** my plot */
    private Plot plot;

    /** chart gui */
    private ChartPanel chartPanel;

    /** show title */
    private boolean showTitle = true;

    /** for the grid layout in the manager */
    private Rectangle layoutRect;

    /** line state */
    private LineState domainLineState = new LineState();

    /** line state */
    private LineState rangeLineState = new LineState();

    /** The bg color */
    private Color backgroundColor = null;

    /** The color to use for the data area */
    private Color dataAreaColor = Color.white;

    /** The date format to use for this chart */
    private String dateFormat = null;

    /** for gui */
    protected JCheckBox showThumbnailCbx;

    /** for gui */
    protected JCheckBox showTitleCbx;

    /** For properties dialog */
    protected JComponent backgroundSwatch;

    /** For properties dialog */
    protected JComponent dataAreaSwatch;

    /** for gui */
    protected JTextField nameFld;

    /** my size */
    private Dimension preferredSize;

    /** Combo box containing date formats available for selection.*/
    JComboBox dateFormatBox;

    /**
     * ctor
     */
    public ChartHolder() {
    }

    /**
     * ctor
     *
     *
     * @param chartManager The chart manager
     * @param name name
     * @param preferredSize size
     */
    public ChartHolder(ChartManager chartManager, String name, Dimension preferredSize) {
        this.chartManager = chartManager;
        this.name = name;
        this.preferredSize = preferredSize;
        init();
        resetChartPanel();
        applyPlotProperties();
    }

    /**
     * apply properties
     *
     * @return OK
     */
    protected boolean applyProperties() {
        if (backgroundSwatch != null) {
            backgroundColor = backgroundSwatch.getBackground();
        }
        if (dataAreaSwatch != null) {
            dataAreaColor = dataAreaSwatch.getBackground();
        }
        if (showThumbnailCbx != null) {
            setShowThumbnail(showThumbnailCbx.isSelected());
        }
        if (showTitleCbx != null) {
            setShowTitle(showTitleCbx.isSelected());
        }
        if (dateFormatBox != null) {
            dateFormat = (String) dateFormatBox.getSelectedItem();
        }
        return true;
    }

    /**
     * get properties widgets
     *
     * @param comps widgets
     */
    protected void getPropertiesComponents(List comps) {
        //        showThumbnailCbx = new JCheckBox("Thumbnail", showThumbnail);
        showTitleCbx = new JCheckBox("Title", showTitle);
        comps.add(GuiUtils.rLabel("Show:"));
        //        comps.add(GuiUtils.left(GuiUtils.hbox(showThumbnailCbx,showTitleCbx)));
        comps.add(GuiUtils.left(showTitleCbx));
    }

    /**
     * apply props
     */
    protected void applyPlotProperties() {
        if (plot == null) {
            return;
        }
        if (dataAreaColor != null) {
            plot.setBackgroundPaint(dataAreaColor);
        }
        if (backgroundColor != null) {
            chart.setBackgroundPaint(backgroundColor);
        }
        if ((backgroundColor != null) && (chartPanel != null)) {
            chartPanel.setBackground(backgroundColor);
        }
        if (showTitle) {
            chart.setTitle(getName());
        } else {
            chart.setTitle((String) null);
        }
        if (plot instanceof XYPlot) {
            final XYPlot p = (XYPlot) plot;
            p.setDomainGridlinesVisible(domainLineState.getVisible());
            p.setRangeGridlinesVisible(rangeLineState.getVisible());
            p.setDomainGridlinePaint(domainLineState.getColor());
            p.setRangeGridlinePaint(rangeLineState.getColor());
            p.setDomainGridlineStroke(domainLineState.getStroke());
            p.setRangeGridlineStroke(rangeLineState.getStroke());
            if (p.getDomainAxis() instanceof DateAxis && dateFormat != null) {
                final DateAxis ax = (DateAxis) p.getDomainAxis();
                final TimeZone tz = getChartManager().getControl().getIdv().getPreferenceManager()
                        .getDefaultTimeZone();
                final DateFormat df = new SimpleDateFormat(dateFormat);
                df.setTimeZone(tz);
                ax.setDateFormatOverride(df);
            }
        }
    }

    /**
     * init
     */
    protected void init() {
        if (plot == null) {
            plot = chartManager.doMakePlot();
            chart = new JFreeChart("", JFreeChart.DEFAULT_TITLE_FONT, plot, true);
            if (backgroundColor != null) {
                chart.setBackgroundPaint(backgroundColor);
            }

            applyPlotProperties();
        }
    }

    /**
     * Set the BeingShown property.
     *
     * @param value The new value for BeingShown
     */
    protected void setBeingShown(boolean value) {
        beingShown = value;
    }

    /**
     * Get the BeingShown property.
     *
     * @return The BeingShown
     */
    protected boolean getBeingShown() {
        return beingShown;
    }

    /**
     * get panel
     *
     * @return panel
     */
    protected ChartPanel getChartPanel() {
        if (plot == null) {
            init();
        }
        return chartPanel;
    }

    /**
     * get plot
     *
     * @return plot
     */
    public Plot getPlot() {
        if (plot == null) {
            init();
        }
        return plot;
    }

    /**
     * write image
     */
    public void doSaveAs() {
        String filename = FileManager.getWriteFile(FileManager.FILTER_IMAGEWRITE, FileManager.SUFFIX_JPG);
        if (filename == null) {
            return;
        }
        try {
            ImageUtils.writeImageToFile(chartPanel, filename);
        } catch (Exception exc) {
            LogUtil.logException("Capturing image", exc);
        }
    }

    /**
     * show dialog
     */
    public void showPropertiesDialog() {
        chartManager.showPropertiesDialog(this);

    }

    /**
     * get items
     *
     * @param items items
     */
    protected void getMenuItems(List items) {
        chartManager.getPopupMenuItems(this, items);
        if (items.size() > 0) {
            items.add(GuiUtils.MENU_SEPARATOR);
        }
        addZoomMenuItems(items);
        items.add(GuiUtils.MENU_SEPARATOR);
        items.add(GuiUtils.makeMenuItem("Save Chart As...", this, "doSaveAs"));
        items.add(GuiUtils.MENU_SEPARATOR);
        items.add(GuiUtils.makeMenuItem("Properties...", this, "showPropertiesDialog"));
    }

    /**
     * show popup
     *
     * @param event event
     */
    private void showPopupMenu(MouseEvent event) {
        List items = new ArrayList();
        getMenuItems(items);
        JPopupMenu popupMenu = GuiUtils.makePopupMenu(items);
        popupMenu.show(chartPanel, event.getX(), event.getY());
    }

    /**
     * Add in the zoom menu items
     *
     * @param items items
     */
    private void addZoomMenuItems(List items) {
        JMenuItem mi;
        JMenu menu;

        items.add(menu = new JMenu("Zoom In"));
        menu.add(mi = new JMenuItem("All Axes"));
        mi.setActionCommand(ChartPanel.ZOOM_IN_BOTH_COMMAND);
        mi.addActionListener(chartPanel);
        menu.addSeparator();

        menu.add(mi = new JMenuItem("Domain Axis"));
        mi.setActionCommand(ChartPanel.ZOOM_IN_DOMAIN_COMMAND);
        mi.addActionListener(chartPanel);

        menu.add(mi = new JMenuItem("Range Axis"));
        mi.setActionCommand(ChartPanel.ZOOM_IN_RANGE_COMMAND);
        mi.addActionListener(chartPanel);

        items.add(menu = new JMenu("Zoom Out"));

        menu.add(mi = new JMenuItem("All Axes"));
        mi.setActionCommand(ChartPanel.ZOOM_OUT_BOTH_COMMAND);
        mi.addActionListener(chartPanel);

        menu.addSeparator();

        menu.add(mi = new JMenuItem("Domain Axis"));
        mi.setActionCommand(ChartPanel.ZOOM_OUT_DOMAIN_COMMAND);
        mi.addActionListener(chartPanel);

        menu.add(mi = new JMenuItem("Range Axis"));
        mi.setActionCommand(ChartPanel.ZOOM_OUT_RANGE_COMMAND);
        mi.addActionListener(chartPanel);

        items.add(menu = new JMenu("Auto Range"));

        menu.add(mi = new JMenuItem("All Axes"));
        mi.setActionCommand(ChartPanel.ZOOM_RESET_BOTH_COMMAND);
        mi.addActionListener(chartPanel);

        menu.addSeparator();

        menu.add(mi = new JMenuItem("Domain Axis"));
        mi.setActionCommand(ChartPanel.ZOOM_RESET_DOMAIN_COMMAND);
        mi.addActionListener(chartPanel);

        menu.add(mi = new JMenuItem("Range Axis"));
        mi.setActionCommand(ChartPanel.ZOOM_RESET_RANGE_COMMAND);
        mi.addActionListener(chartPanel);
    }

    private static final Logger logger = LoggerFactory.getLogger(ChartHolder.class);

    /**
     * create new chart panel
     */
    protected void resetChartPanel() {
        if (plot == null) {
            init();
        }
        if (chartPanel != null) {
            chartPanel.setChart(null);
        }

        //        chartPanel = new ChartPanel(chart, false,false,false, true,true) {
        chartPanel = new ChartPanel(chart, true) {

            @Override
            public void paintComponent(Graphics g) {
                synchronized (chartManager.getMutex()) {
                    if (chartManager.getOkToDraw() && !chartManager.getSettingData()) {
                        super.paintComponent(g);
                    }
                }
            }

            @Override
            public void chartChanged(ChartChangeEvent event) {
                synchronized (chartManager.getMutex()) {
                    if (!chartManager.getSettingData()) {
                        super.chartChanged(event);
                    } else {
                        setRefreshBuffer(true);
                    }
                }
                Misc.runInABit(20, chartManager, "updateThumb", null);
            }
        };
        chartPanel.addKeyListener(new KeyAdapter() {
            public void keyPressed(KeyEvent e) {
                ChartHolder.this.keyPressed(e);
            }
        });

        if (preferredSize != null) {
            chartPanel.setPreferredSize(preferredSize);
        } else {
            chartPanel.setPreferredSize(new Dimension(300, 200));
        }
    }

    /**
     * Handle event
     *
     * @param e The event
     */
    public void keyPressed(KeyEvent e) {
        if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
            panPlot(true);
        } else if (e.getKeyCode() == KeyEvent.VK_LEFT) {
            panPlot(false);
        } else if (e.getKeyCode() == KeyEvent.VK_UP) {
            upDownPlot(true);
        } else if (e.getKeyCode() == KeyEvent.VK_DOWN) {
            upDownPlot(false);
        } else if ((e.getKeyCode() == KeyEvent.VK_R) && e.isControlDown()) {
            chartPanel.restoreAutoBounds();
        } else {
            //            super.keyPressed(e);
        }
    }

    /**
     * Move plot up/down.
     *
     * @param up up
     */
    private void upDownPlot(boolean up) {
        if (!(plot instanceof XYPlot)) {
            return;
        }
        XYPlot xyPlot = (XYPlot) plot;

        int cnt = xyPlot.getRangeAxisCount();
        for (int i = 0; i < cnt; i++) {
            ValueAxis axis = (ValueAxis) xyPlot.getRangeAxis(i);
            org.jfree.data.Range range = axis.getRange();
            double width = range.getUpperBound() - range.getLowerBound();
            double width2 = width / 2.0;
            double step = (up ? width * 0.1 : -width * 0.1);
            axis.centerRange(range.getLowerBound() + step + width2);
        }
    }

    /**
     * Pan plot
     *
     * @param right to right
     */
    protected void panPlot(boolean right) {
        panPlot(right, 0.1);
    }

    /**
     * Pan the plot
     *
     * @param right to right
     * @param percent by how much
     */
    protected void panPlot(boolean right, double percent) {
        if (!(plot instanceof XYPlot)) {
            return;
        }
        XYPlot xyPlot = (XYPlot) plot;
        int cnt = xyPlot.getDomainAxisCount();
        for (int i = 0; i < cnt; i++) {
            ValueAxis axis = (ValueAxis) xyPlot.getDomainAxis(i);
            org.jfree.data.Range range = axis.getRange();
            double width = range.getUpperBound() - range.getLowerBound();
            double width2 = width / 2.0;
            double step = (right ? width * percent : -width * percent);
            axis.centerRange(range.getLowerBound() + step + width2);
        }
    }

    /**
     * init
     */
    protected void initChart() {
        lastSide = null;
        paramCount = 0;
    }

    /** keeps track of which legend is visible          */
    Hashtable<Integer, Boolean> legendVisible = new Hashtable<Integer, Boolean>();

    /**
     * is the given legend visible
     *
     * @param param which legend
     *
     * @return is visible
     */
    private boolean isLegendVisible(int param) {
        Boolean b = legendVisible.get(param);
        if (b != null) {
            return b.booleanValue();
        }
        return true;
    }

    /**
     * add data set
     *
     * @param dataset dataset
     * @param rangeAxis axis
     * @param renderer renderer
     * @param side which side
     */
    protected void add(XYDataset dataset, ValueAxis rangeAxis, XYItemRenderer renderer, AxisLocation side) {
        synchronized (chartManager.getMutex()) {
            XYPlot xyPlot = (XYPlot) plot;
            xyPlot.setRangeAxis(paramCount, rangeAxis, false);
            xyPlot.setDataset(paramCount, dataset);
            xyPlot.mapDatasetToRangeAxis(paramCount, paramCount);
            xyPlot.setRenderer(paramCount, renderer);
            if (side != null) {
                xyPlot.setRangeAxisLocation(paramCount, side);
            }
            paramCount++;
        }
    }

    /**
     * ahs parameters
     *
     * @return has parameters
     */
    public boolean hasParameters() {
        return paramCount > 0;
    }

    /**
     * Set the LayoutRect property.
     *
     * @param value The new value for LayoutRect
     */
    public void setLayoutRect(Rectangle value) {
        layoutRect = value;
    }

    /**
     * Get the LayoutRect property.
     *
     * @return The LayoutRect
     */
    public Rectangle getLayoutRect() {
        return layoutRect;
    }

    /**
     * Set the Name property.
     *
     * @param value The new value for Name
     */
    public void setName(String value) {
        name = value;
    }

    /**
     * Get the Name property.
     *
     * @return The Name
     */
    public String getName() {
        return name;
    }

    /**
     * Set the ChartManager property.
     *
     * @param value The new value for ChartManager
     */
    public void setChartManager(ChartManager value) {
        chartManager = value;
    }

    /**
     * Get the ChartManager property.
     *
     * @return The ChartManager
     */
    public ChartManager getChartManager() {
        return chartManager;
    }

    /**
     * Set the DomainLineState property.
     *
     * @param value The new value for DomainLineState
     */
    public void setDomainLineState(LineState value) {
        domainLineState = value;
    }

    /**
     * Get the DomainLineState property.
     *
     * @return The DomainLineState
     */
    public LineState getDomainLineState() {
        return domainLineState;
    }

    /**
     * Set the RangeLineState property.
     *
     * @param value The new value for RangeLineState
     */
    public void setRangeLineState(LineState value) {
        rangeLineState = value;
    }

    /**
     * Get the RangeLineState property.
     *
     * @return The RangeLineState
     */
    public LineState getRangeLineState() {
        return rangeLineState;
    }

    /**
     * Set the ShowThumbnail property.
     *
     * @param value The new value for ShowThumbnail
     */
    public void setShowThumbnail(boolean value) {
        showThumbnail = value;
    }

    /**
     * Get the ShowThumbnail property.
     *
     * @return The ShowThumbnail
     */
    public boolean getShowThumbnail() {
        return showThumbnail;
    }

    /**
     * Set the BackgroundColor property.
     *
     * @param value The new value for BackgroundColor
     */
    public void setBackgroundColor(Color value) {
        backgroundColor = value;
    }

    /**
     * Get the BackgroundColor property.
     *
     * @return The BackgroundColor
     */
    public Color getBackgroundColor() {
        return backgroundColor;
    }

    /**
     * Set the DataAreaColor property.
     *
     * @param value The new value for DataAreaColor
     */
    public void setDataAreaColor(Color value) {
        dataAreaColor = value;
    }

    /**
     * Get the DataAreaColor property.
     *
     * @return The DataAreaColor
     */
    public Color getDataAreaColor() {
        return dataAreaColor;
    }

    /**
     * Get the date format for this plot.
     * 
     * @return the date format for this plot.
     */
    public String getDateFormat() {
        return dateFormat;
    }

    /**
     * Set the date format for this plot.
     * 
     * @param dateFormat The date format for this plot.
     */
    public void setDateFormat(final String dateFormat) {
        this.dateFormat = dateFormat;
    }

    /**
     *  Set the ShowTitle property.
     *
     *  @param value The new value for ShowTitle
     */
    public void setShowTitle(boolean value) {
        showTitle = value;
    }

    /**
     *  Get the ShowTitle property.
     *
     *  @return The ShowTitle
     */
    public boolean getShowTitle() {
        return showTitle;
    }

    /**
     *  Set the PreferredSize property.
     *
     *  @param value The new value for PreferredSize
     */
    public void setPreferredSize(Dimension value) {
        preferredSize = value;
    }

    /**
     *  Get the PreferredSize property.
     *
     *  @return The PreferredSize
     */
    public Dimension getPreferredSize() {
        return preferredSize;
    }

}