Java tutorial
/* * 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 edu.wisc.ssec.mcidasv.McIDASV; import org.jfree.chart.*; import org.jfree.chart.axis.*; import org.jfree.chart.event.*; import org.jfree.chart.plot.*; import org.jfree.chart.renderer.*; import org.jfree.chart.renderer.xy.*; import org.jfree.data.*; import org.jfree.data.general.*; import org.jfree.data.time.*; import org.jfree.data.xy.*; import org.jfree.ui.*; import ucar.unidata.data.DataAlias; import ucar.unidata.data.DataChoice; import ucar.unidata.data.DataInstance; import ucar.unidata.data.grid.GridUtil; import ucar.unidata.data.point.*; import ucar.unidata.data.sounding.TrackDataSource; import ucar.unidata.gis.SpatialGrid; import ucar.unidata.idv.control.DisplayControlImpl; import ucar.unidata.ui.TableSorter; import ucar.unidata.ui.symbol.*; import ucar.unidata.ui.symbol.StationModelManager; import ucar.unidata.util.FileManager; import ucar.unidata.util.GuiUtils; import ucar.unidata.util.LogUtil; import ucar.unidata.util.Misc; import ucar.unidata.util.ObjectListener; import ucar.unidata.util.StringUtil; import ucar.unidata.util.TwoFacedObject; import ucar.unidata.view.geoloc.NavigatedDisplay; import ucar.unidata.xml.XmlObjectStore; import ucar.visad.Util; import visad.*; import visad.georef.EarthLocation; import java.awt.*; import java.awt.event.*; import java.awt.geom.Rectangle2D; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.rmi.RemoteException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Comparator; import java.util.Date; import java.util.GregorianCalendar; import java.util.Hashtable; import java.util.List; import java.util.TimeZone; import java.util.Vector; import javax.swing.*; import javax.swing.event.*; import javax.swing.table.*; //import com.lavantech.gui.comp.*; /** * Abstract class for chart implementations * * * @author IDV Development Team * @version $Revision: 1.15 $ */ public abstract class PlotWrapper extends ChartWrapper implements KeyListener { /** Used by the MyChartPanel event bridge */ protected static final boolean EVENT_PASSON = false; /** Used by the MyChartPanel event bridge */ protected static final boolean EVENT_DONTPASSON = true; /** The bg color */ private Color backgroundColor = Color.lightGray; /** The color to use for the data area */ private Color dataAreaColor = Color.white; /** line state */ private LineState domainLineState = new LineState(); /** line state */ private LineState rangeLineState = new LineState(); /** The main chart gui component */ protected MyChartPanel chartPanel; /** The chart */ protected JFreeChart chart; /** For properties dialog */ private JComponent backgroundSwatch; /** For properties dialog */ private JComponent dataAreaSwatch; /** properties widget */ private JCheckBox autoRangeCbx; /** Do we do auto range */ private boolean autoRange = true; /** * Default ctor */ public PlotWrapper() { } /** * Ctor * * @param name The name * @param dataChoices List of data choices */ public PlotWrapper(String name, List dataChoices) { super(name, dataChoices); } /** * Noop * * @param e The event */ public void keyReleased(KeyEvent e) { } /** * Noop * * @param e The event */ public void keyTyped(KeyEvent e) { } /** * Is the annotation ok to draw * * @param annotation The annotation * * @return ok to draw */ public boolean okToDraw(ChartAnnotation annotation) { return true; } /** * Can this chart do colors * * @return true */ protected boolean canDoColors() { return true; } /** * The annotation changed somehow * * @param chartAnnotation The annotation */ public void annotationChanged(ChartAnnotation chartAnnotation) { signalChartChanged(); } /** * Get the list of tab names for the properties dialog * * @return List of tab names */ public String[] getPropertyTabs() { return new String[] { "Data", "Display" }; } public DisplayControlImpl getControl() { return displayControl; } /** * Create the properties contents * * @param comps List of components * @param tabIdx Which tab */ protected void getPropertiesComponents(List comps, int tabIdx) { super.getPropertiesComponents(comps, tabIdx); if (tabIdx != 1) { autoRangeCbx = new JCheckBox("", autoRange); comps.add(GuiUtils.rLabel("Auto Range: ")); comps.add(autoRangeCbx); return; } if (canDoColors()) { XmlObjectStore store; if (this.displayControl != null) { store = this.displayControl.getStore(); } else { store = McIDASV.getStaticMcv().getStore(); } backgroundSwatch = GuiUtils.makeColorSwatchWidget(store, backgroundColor, "")[0]; dataAreaSwatch = GuiUtils.makeColorSwatchWidget(store, dataAreaColor, "")[0]; comps.add(GuiUtils.rLabel("Color: ")); List colorComps = Misc.newList(new JLabel("Background:"), backgroundSwatch, new JLabel("Data Area:"), dataAreaSwatch); comps.add(GuiUtils.left(GuiUtils.hbox(colorComps, 4))); comps.add(GuiUtils.rLabel("Domain Lines: ")); comps.add(domainLineState.getPropertyContents(store)); comps.add(GuiUtils.rLabel("Range Lines: ")); comps.add(rangeLineState.getPropertyContents(store)); } } /** * Apply properties * * * @return Was successful */ protected boolean applyProperties() { if (!super.applyProperties()) { return false; } if (!domainLineState.applyProperties()) { return false; } if (!rangeLineState.applyProperties()) { return false; } if (autoRangeCbx.isSelected() != autoRange) { autoRange = autoRangeCbx.isSelected(); resetPlot(); } backgroundColor = backgroundSwatch.getBackground(); dataAreaColor = dataAreaSwatch.getBackground(); Plot plot = chart.getPlot(); plot.setBackgroundPaint(dataAreaColor); // getContents().setBackground(backgroundColor); if (plot instanceof XYPlot) { ((XYPlot) plot).setDomainGridlinesVisible(domainLineState.getVisible()); ((XYPlot) plot).setRangeGridlinesVisible(rangeLineState.getVisible()); ((XYPlot) plot).setDomainGridlinePaint(domainLineState.getColor()); ((XYPlot) plot).setRangeGridlinePaint(rangeLineState.getColor()); ((XYPlot) plot).setDomainGridlineStroke(domainLineState.getStroke()); ((XYPlot) plot).setRangeGridlineStroke(rangeLineState.getStroke()); } return true; } /** * Get the menu items * * @param items List of menu items * * @return The items list */ protected List getPopupMenuItems(List items) { super.getPopupMenuItems(items); ((MyChartPanel) chartPanel).addChartMenuItems(items); return items; } /** * Class MyChartPanel adds items to a popup menu * * * @author IDV Development Team * @version $Revision: 1.15 $ */ protected class MyChartPanel extends ChartPanel { /** Last x */ public int lastEventX = 0; /** Last y */ public int lastEventY = 0; /** * ctor * * @param chart the chart */ public MyChartPanel(JFreeChart chart) { super(chart, true); } /** * Hook to pass through to the chartwrapper * * @param event The event * * @return The tooltip text */ public String getToolTipText(MouseEvent event) { String fromChart = chartPanelGetToolTipText(event); if (fromChart == null) { return super.getToolTipText(); } return fromChart; } /** * Show the popup menu. Add items if not done so. * * @param x x * @param y y */ protected void displayPopupMenu(int x, int y) { showPopup(chartPanel, x, y); } /** * utility * * @param result The menu * @param label The label * @param cmd The command * * @return The item */ protected JMenuItem addChartMenuItem(JMenu result, String label, String cmd) { JMenuItem mi = new JMenuItem(label); mi.setActionCommand(cmd); mi.addActionListener(this); result.add(mi); return mi; } /** * add menu items * * * @param items List of menu items */ protected void addChartMenuItems(List items) { items.add(GuiUtils.MENU_SEPARATOR); JMenu chartMenu = new JMenu("Zoom"); items.add(chartMenu); JMenu[] menus = { new JMenu("Zoom In"), new JMenu("Zoom Out"), new JMenu("Auto Range") }; String[][] cmds = { { "Both Axes", ZOOM_IN_BOTH_COMMAND, "Domain Axis", ZOOM_IN_DOMAIN_COMMAND, "Range Axis", ZOOM_IN_RANGE_COMMAND }, { "Both Axes", ZOOM_OUT_BOTH_COMMAND, "Domain Axis", ZOOM_OUT_DOMAIN_COMMAND, "Range Axis", ZOOM_OUT_RANGE_COMMAND }, { "Both Axes", ZOOM_RESET_BOTH_COMMAND, "Domain Axis", ZOOM_RESET_DOMAIN_COMMAND, "Range Axis", ZOOM_RESET_RANGE_COMMAND } }; for (int i = 0; i < menus.length; i++) { chartMenu.add(menus[i]); for (int j = 0; j < cmds[i].length; j += 2) { addChartMenuItem(menus[i], cmds[i][j], cmds[i][j + 1]); } } } /** * Handle the event. Check with the ChartWrapper * * @param event The event */ public void mouseDragged(MouseEvent event) { lastEventX = event.getX(); lastEventY = event.getY(); if (chartPanelMouseDragged(event) == EVENT_DONTPASSON) { return; } super.mouseDragged(event); } /** * Handle the event. Check with the ChartWrapper * * @param event The event */ public void mouseReleased(MouseEvent event) { lastEventX = event.getX(); lastEventY = event.getY(); if (chartPanelMouseReleased(event) == EVENT_DONTPASSON) { return; } super.mouseReleased(event); } /** * Handle the event. Check with the ChartWrapper * * @param event The event */ public void mouseClicked(MouseEvent event) { lastEventX = event.getX(); lastEventY = event.getY(); if (chartPanelMouseClicked(event) == EVENT_DONTPASSON) { return; } super.mouseClicked(event); } /** * Handle the event. Check with the ChartWrapper * * @param event The event */ public void mousePressed(MouseEvent event) { lastEventX = event.getX(); lastEventY = event.getY(); requestFocus(); if (chartPanelMousePressed(event) == EVENT_DONTPASSON) { return; } super.mousePressed(event); } /** * Handle the event. Check with the ChartWrapper * * @param event the action */ public void actionPerformed(ActionEvent event) { String command = event.getActionCommand(); if (command.equals(PROPERTIES_COMMAND)) { PlotWrapper.this.showProperties(); return; } super.actionPerformed(event); } } /** * Set the Name property. * * @param value The new value for Name */ public void setName(String value) { super.setName(value); if (chart != null) { chart.setTitle(value); } } /** * Hook to intercept these calls on the chart * * @param event The event * * @return Was this event handled by the ChartWrapper */ public String chartPanelGetToolTipText(MouseEvent event) { return null; } /** * Hook to intercept these calls on the chart * * @param e The event * * @return Was this event handled by the ChartWrapper */ public boolean chartPanelMousePressed(MouseEvent e) { return EVENT_PASSON; } /** * Hook to intercept these calls on the chart * * @param e The event * * @return Was this event handled by the ChartWrapper */ public boolean chartPanelMouseClicked(MouseEvent e) { return EVENT_PASSON; } /** * Hook to intercept these calls on the chart * * @param event The event * * @return Was this event handled by the ChartWrapper */ public boolean chartPanelMouseDragged(MouseEvent event) { if (SwingUtilities.isRightMouseButton(event)) { return EVENT_DONTPASSON; } return EVENT_PASSON; } /** * Hook to intercept these calls on the chart * * * @param event The event * * @return Was this event handled by the ChartWrapper */ public boolean chartPanelMouseReleased(MouseEvent event) { return EVENT_PASSON; } /** * Get the chart * * @return The chart_ */ protected ChartPanel getChartPanel() { return chartPanel; } /** * update chart */ public void signalChartChanged() { if (chartPanel != null) { chartPanel.chartChanged(new ChartChangeEvent(this)); } } /** * Make the panel for the chart * * @param chart The chart * * @return The panel */ protected MyChartPanel doMakeChartPanel(JFreeChart chart) { if (chartPanel == null) { chartPanel = new MyChartPanel(chart); // chartPanel.setBackground(backgroundColor); chartPanel.addKeyListener(this); chartPanel.setPreferredSize(getPreferredChartSize()); chartPanel.setMouseZoomable(true, false); } return chartPanel; } /** * 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 (!(chart.getPlot() instanceof XYPlot)) { return; } XYPlot plot = (XYPlot) chart.getPlot(); int cnt = plot.getDomainAxisCount(); for (int i = 0; i < cnt; i++) { ValueAxis axis = (ValueAxis) plot.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); } } /** * Move plot up/down. * * @param up up */ private void upDownPlot(boolean up) { if (!(chart.getPlot() instanceof XYPlot)) { return; } XYPlot plot = (XYPlot) chart.getPlot(); int cnt = plot.getRangeAxisCount(); for (int i = 0; i < cnt; i++) { ValueAxis axis = (ValueAxis) plot.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); } } /** * reset the axis' */ private void resetPlot() { if (chart == null) { return; } if (!(chart.getPlot() instanceof XYPlot)) { return; } XYPlot plot = (XYPlot) chart.getPlot(); int rcnt = plot.getRangeAxisCount(); for (int i = 0; i < rcnt; i++) { ValueAxis axis = (ValueAxis) plot.getRangeAxis(i); System.err.println("range axis:" + axis); axis.setAutoRange(autoRange); } int dcnt = plot.getDomainAxisCount(); for (int i = 0; i < dcnt; i++) { ValueAxis axis = (ValueAxis) plot.getDomainAxis(i); System.err.println("domain axis:" + axis); axis.setAutoRange(autoRange); } } /** * 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()) { resetPlot(); } else { super.keyPressed(e); } } /** * Utility to init xy plots * * @param plot the plotx */ protected void initXYPlot(XYPlot plot) { plot.setBackgroundPaint(dataAreaColor); // plot.setAxisOffset(new RectangleInsets(6.0, 3.0, 3.0, 3.0)); plot.setDomainCrosshairVisible(true); plot.setRangeCrosshairVisible(true); plot.setDomainGridlinesVisible(domainLineState.getVisible()); plot.setRangeGridlinesVisible(rangeLineState.getVisible()); plot.setDomainGridlinePaint(domainLineState.getColor()); plot.setRangeGridlinePaint(rangeLineState.getColor()); plot.setDomainGridlineStroke(domainLineState.getStroke()); plot.setRangeGridlineStroke(rangeLineState.getStroke()); } /** * Get the chart size * * @return size */ protected Dimension getPreferredChartSize() { return new java.awt.Dimension(500, 270); } /** * 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; } /** * 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 AutoRange property. * * @param value The new value for AutoRange */ public void setAutoRange(boolean value) { autoRange = value; } /** * Get the AutoRange property. * * @return The AutoRange */ public boolean getAutoRange() { return autoRange; } }