Java tutorial
/* * Debrief - the Open Source Maritime Analysis Application * http://debrief.info * * (C) 2000-2014, PlanetMayo Ltd * * This library is free software; you can redistribute it and/or * modify it under the terms of the Eclipse Public License v1.0 * (http://www.eclipse.org/legal/epl-v10.html) * * 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. */ package MWC.GUI.JFreeChart; import java.awt.BasicStroke; import java.awt.Color; import java.awt.Graphics2D; import java.awt.Stroke; import java.awt.geom.Point2D; import java.awt.geom.Rectangle2D; import java.util.Date; import org.jfree.chart.axis.DateAxis; import org.jfree.chart.axis.NumberAxis; import org.jfree.chart.axis.ValueAxis; import org.jfree.chart.plot.PlotOrientation; import org.jfree.chart.plot.PlotRenderingInfo; import org.jfree.chart.plot.PlotState; import org.jfree.chart.plot.XYPlot; import org.jfree.chart.renderer.xy.XYItemRenderer; import org.jfree.data.xy.XYDataset; import MWC.GUI.CanvasType; import MWC.GUI.StepperListener; import MWC.GenericData.Duration; import MWC.GenericData.HiResDate; /** * ******************************************************************* embedded * class which extends free chart to give current DTG indication * ******************************************************************* */ public class StepperXYPlot extends XYPlot implements StepperListener { /** * */ private static final long serialVersionUID = 1L; /** * the step control we monitor */ private final StepperListener.StepperController _myStepper; /** * the current time we are looking at (or -1 for null) (micros) */ protected HiResDate _currentTime = null; /** whether to grow the axis with time * */ protected boolean _growWithTime = false; /** flag for if we need to reset the axes, after a grow setting * */ private boolean _resetAxes = false; /** * whether to actually show the line * */ private boolean _showLine = true; private Duration _fixedDuration; // //////////////////////////////////////////////// // constructor // //////////////////////////////////////////////// /** * Constructs an XYPlot with the specified axes (other attributes take default * values). * * @param data * The dataset. * @param domainAxis * The domain axis. * @param rangeAxis * The range axis. * @param theRenderer */ public StepperXYPlot(final XYDataset data, final RelativeDateAxis domainAxis, final ValueAxis rangeAxis, final StepperListener.StepperController stepper, final XYItemRenderer theRenderer) { super(data, domainAxis, rangeAxis, theRenderer); this._myStepper = stepper; if (_myStepper != null) { _myStepper.addStepperListener(this); } } // //////////////////////////////////////////////// // over-ride painting support // //////////////////////////////////////////////// public boolean isGrowWithTime() { return _growWithTime; } public void setGrowWithTime(final boolean growWithTime) { // do we need to reset the bounds? if (!growWithTime && isGrowWithTime()) { _resetAxes = true; } this._growWithTime = growWithTime; } /** * Draws the XY plot on a Java 2D graphics device (such as the screen or a * printer), together with a current time marker * <P> * XYPlot relies on an XYItemRenderer to draw each item in the plot. This * allows the visual representation of the data to be changed easily. * <P> * The optional info argument collects information about the rendering of the * plot (dimensions, tooltip information etc). Just pass in null if you do not * need this information. * * @param g2 * The graphics device. * @param plotArea * The area within which the plot (including axis labels) should be * drawn. * @param info * Collects chart drawing information (null permitted). */ public final void draw(final Graphics2D g2, final Rectangle2D plotArea, final Point2D anchor, final PlotState state, final PlotRenderingInfo info) { super.draw(g2, plotArea, anchor, state, info); // do we want to view the line? if (!_showLine) return; // do we have a time? if (_currentTime != null) { // find the screen area for the dataset final Rectangle2D dataArea = info.getDataArea(); // determine the time we are plotting the line at long theTime = _currentTime.getMicros(); // hmmm, how do we format the date final CanBeRelativeToTimeStepper axis = (CanBeRelativeToTimeStepper) this.getDomainAxis(); // are we working in relative time mode? if (axis.isRelativeTimes()) { if (_myStepper != null) { // yes, we now need to offset the time theTime = theTime - _myStepper.getTimeZero().getMicros(); } } // hmm, see if we are wroking with a date or number axis double linePosition = 0; if (axis instanceof DateAxis) { // ok, now scale the time to graph units final DateAxis dateAxis = (DateAxis) axis; // find the new x value linePosition = dateAxis.dateToJava2D(new Date(theTime / 1000), dataArea, this.getDomainAxisEdge()); if (_resetAxes) { dateAxis.setAutoRange(true); _resetAxes = false; } if (isGrowWithTime()) { final long endMillis = theTime / 1000; long startMillis; if (_fixedDuration != null) { startMillis = endMillis - _fixedDuration.getMillis(); } else { startMillis = (long) dateAxis.getLowerBound(); } final Date startDate = new Date(startMillis); final Date endDate = new Date(endMillis); dateAxis.setRange(startDate, endDate); } else { } } else { if (axis instanceof NumberAxis) { final NumberAxis numberAxis = (NumberAxis) axis; linePosition = numberAxis.valueToJava2D(theTime, dataArea, this.getDomainAxisEdge()); if (isGrowWithTime()) numberAxis.setRange(numberAxis.getRange().getLowerBound(), theTime); else { if (_resetAxes) { numberAxis.setAutoRange(true); _resetAxes = false; } } } } // ok, finally draw the line - if we're not showing the growing plot if (!isGrowWithTime()) plotStepperLine(g2, linePosition, dataArea); } } /** * draw the new stepper line into the plot * * @param g2 * @param linePosition * @param dataArea */ protected void plotStepperLine(final Graphics2D g2, final double linePosition, final Rectangle2D dataArea) { // prepare to draw final Stroke oldStroke = g2.getStroke(); g2.setXORMode(Color.darkGray); // thicken up the line g2.setStroke(new BasicStroke(3)); if (this.getOrientation() == PlotOrientation.VERTICAL) { // draw the line g2.drawLine((int) linePosition - 1, (int) dataArea.getY() + 1, (int) linePosition - 1, (int) dataArea.getY() + (int) dataArea.getHeight() - 1); } else { // draw the line g2.drawLine((int) dataArea.getY() + 1, (int) linePosition - 1, (int) dataArea.getY() + (int) dataArea.getHeight() - 1, (int) linePosition - 1); } // and restore everything g2.setStroke(oldStroke); g2.setPaintMode(); } // //////////////////////////////////////////////// // support for time stepper // //////////////////////////////////////////////// /** * the current time has changed */ public final void newTime(final HiResDate oldDTG, final HiResDate newDTG, final CanvasType canvas) { _currentTime = newDTG; } @Override public void zoom(final double percent) { this.getDomainAxis().setAutoRange(true); this.getRangeAxis().setAutoRange(true); } /** * the mode for stepping has changed */ public final void steppingModeChanged(final boolean on) { } /** * @param line * whether to actually show the line */ public void setShowLine(final boolean line) { _showLine = line; } public void setFixedDuration(final Duration dur) { _fixedDuration = dur; // do we need to reset the axes? if (_fixedDuration == null) _resetAxes = true; } public Duration getFixedDuration() { return _fixedDuration; } }