I was looking for some code to pan/shift a plot. I coudn't find anything
that suit my needs so I implemented this little class. Ideally it should be
incorporated to the ChartPanel
It only responds to keyboard events but shouldn't be hard to add mouse
control, just multiply the number of pixels the mouse travelled by the default delta for 1 pixel.
I've only tested with a XYPlot but it should work with similar plots.
Have fun!
- Code: Select all
/*
* Copyright 2006 CPqD - Centro de Pesquisa e Desenvolvimento em Telecomunicações.
* http://www.cpqd.com.br/
*
* File ChartPanelShiftController.java created on 26/01/2006 10:49:42
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*
* [Java is a trademark or registered trademark of Sun Microsystems, Inc.
* in the United States and other countries.]
*
* ------------------------
* ChartPanelShiftController.java
* ------------------------
* Original Author: Gustavo H. Sberze Ribas;
* Contributor(s): ;
*
* Changes
* --------------------------
* 26-Jan-2006 : First Version (GR);
*
*/
package br.com.cpqd.chart.tools;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.geom.Rectangle2D;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.ValueAxis;
import org.jfree.chart.plot.ContourPlot;
import org.jfree.chart.plot.FastScatterPlot;
import org.jfree.chart.plot.Plot;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
/**
* This class provides ways to shift (aka pan/scroll) a plot. The shift is done
* through the arrow keys and its step can be configured to be a fixed amount,
* a percentual of the current axis or a range in pixels.
* <p>
* This class only supports plots of type {@link org.jfree.chart.plot.XYPlot XYPlot},
* {@link org.jfree.chart.plot.ContourPlot ContourPlot} and
* {@link org.jfree.chart.plot.FastScatterPlot FastScatterPlot}.
* <p>
* Use ← and → to shift the plot left and right; <br>
* Use ↑ and ↓ to shift the plot up and down; <br>
* Press the SHIFT key to increase the shift by a factor of 10.
*
* @author Gustavo H. Sberze Ribas (CPqD)
* @version 0.1
*/
public class ChartPanelShiftController implements KeyListener{
/** PAN plot by a fixed percentual of the range (eg. 1%) */
public static final int SHIFT_PERCENTUAL = 1;
/** PAN plot by a fixed number of pixels (eg. 1px) */
public static final int SHIFT_PIXEL = 2;
/** PAN plot by a fixed amout (eg. 5 range units) */
public static final int SHIFT_FIXED = 3;
/** The chart panel we're using */
protected ChartPanel chartPanel;
/** Does this plot supports shifting? Pie charts for example don't. */
protected boolean plotSupported = false;
/** The shift type. (default {@link #SHIFT_PIXEL} ) */
protected int shiftType = SHIFT_PIXEL;
/** Fixed shift amount for domain axis */
protected double fixedDomainShiftUnits;
/** Fixed shift amount for range axis */
protected double fixedRangeShiftUnits;
/** By default we assume that the range axis is the vertical one (ie,
* PlotOrientation.VERTICAL (axesSwaped=false). If the range axis is the
* horizontal one (ie, PlotOrientation.HORIZONTAL) this variable should
* be set to true. */
protected boolean axesSwaped = false;
/**
* Creates a new controller to handle plot shifts.
* @param chartPanel The panel displaying the plot.
*/
public ChartPanelShiftController(ChartPanel chartPanel) {
super();
this.chartPanel = chartPanel;
// Check to see if plot is shiftable
Plot plot = chartPanel.getChart().getPlot();
if ((plot instanceof XYPlot) ||
(plot instanceof FastScatterPlot) ||
(plot instanceof ContourPlot)
) {
plotSupported = true;
axesSwaped = isHorizontalPlot(plot);
}
}
/**
* Returns the plot orientation.
* @return True = {@link org.jfree.chart.plot.PlotOrientation#VERTICAL VERTICAL};
* False = {@link org.jfree.chart.plot.PlotOrientation#HORIZONTAL HORIZONTAL}
*/
protected boolean isHorizontalPlot(Plot plot) {
if (plot instanceof XYPlot) {
return ((XYPlot)plot).getOrientation()==PlotOrientation.HORIZONTAL;
}
if (plot instanceof FastScatterPlot) {
return ((FastScatterPlot)plot).getOrientation()==PlotOrientation.HORIZONTAL;
}
return false;
}
/**
* Returns the ValueAxis for the plot or <code>null</code> if the plot
* doesn't have one.
* @param chart The chart
* @param domain True = get Domain axis. False = get Range axis.
* @return The selected ValueAxis or <code>null</code> if the plot doesn't
* have one.
*/
protected ValueAxis getPlotAxis(JFreeChart chart, boolean domain) {
// Where's the Shiftable interface when we need it ?? ;)
Plot plot = chart.getPlot();
if (plot instanceof XYPlot) {
return domain?((XYPlot)plot).getDomainAxis():((XYPlot)plot).getRangeAxis();
}
if (plot instanceof FastScatterPlot) {
return domain?((FastScatterPlot)plot).getDomainAxis():((FastScatterPlot)plot).getRangeAxis();
}
if (plot instanceof ContourPlot) {
return domain?((ContourPlot)plot).getDomainAxis():((ContourPlot)plot).getRangeAxis();
}
return null;
}
/**
* Pan/Shifts a plot if the arrow keys are pressed.
* @see java.awt.event.KeyListener#keyPressed(java.awt.event.KeyEvent)
*/
public void keyPressed(KeyEvent e) {
if (!plotSupported) return;
int keyCode = e.getKeyCode();
// we're only interested in arrows (code 37,38,39,40)
if ((keyCode < 37) || (keyCode > 40)) return;
// The axis we're gonna shift
ValueAxis axis = null;
// Delta is the amount we'll shift in axis units.
double delta;
boolean domainShift = false; // used for PAN_FIXED
// Calculations for the domain axis
if ((keyCode == KeyEvent.VK_LEFT) || (keyCode == KeyEvent.VK_RIGHT)) {
axis = getPlotAxis(chartPanel.getChart(),!axesSwaped);
domainShift = true;
}
// Calculations for the range axis
else {
axis = getPlotAxis(chartPanel.getChart(),axesSwaped);
}
// Let's calculate 'delta', the amount by which we'll shift the plot
switch (shiftType) {
case SHIFT_PERCENTUAL:
delta = (axis.getUpperBound()-axis.getLowerBound())/100.0;
break;
case SHIFT_FIXED:
delta = (domainShift ? fixedDomainShiftUnits : fixedRangeShiftUnits);
break;
case SHIFT_PIXEL: // also the default
default:
// Let's find out what's the range for 1 pixel.
final Rectangle2D scaledDataArea = chartPanel.getScreenDataArea();
delta = axis.getRange().getLength() / (scaledDataArea.getWidth());
break;
}
// Shift modifier multiplies delta by 10
if (e.isShiftDown()) {
delta *= 10;
}
switch (keyCode) {
case KeyEvent.VK_LEFT:
case KeyEvent.VK_DOWN:
axis.setRange(axis.getLowerBound()-delta,axis.getUpperBound()-delta);
break;
case KeyEvent.VK_UP:
case KeyEvent.VK_RIGHT:
axis.setRange(axis.getLowerBound()+delta,axis.getUpperBound()+delta);
break;
}
}
/*
* @see java.awt.event.KeyListener#keyTyped(java.awt.event.KeyEvent)
*/
public void keyTyped(KeyEvent e) {}
/*
* @see java.awt.event.KeyListener#keyReleased(java.awt.event.KeyEvent)
*/
public void keyReleased(KeyEvent e) {}
/**
* Returns the fixed shift step for the domain axis.
* @return the fixed shift step for the domain axis.
*/
public double getFixedDomainShiftUnits() {
return fixedDomainShiftUnits;
}
/**
* Sets the fixed shift step for the domain axis.
* @param fixedDomainShiftUnits the fixed shift step for the domain axis.
*/
public void setFixedDomainShiftUnits(double fixedDomainShiftUnits) {
this.fixedDomainShiftUnits = fixedDomainShiftUnits;
}
/**
* Returns the fixed shift step for the range axis.
* @return the fixed shift step for the range axis.
*/
public double getFixedRangeShiftUnits() {
return fixedRangeShiftUnits;
}
/**
* Sets the fixed shift step for the range axis.
* @param fixedRangeShiftUnits the fixed shift step for the range axis.
*/
public void setFixedRangeShiftUnits(double fixedRangeShiftUnits) {
this.fixedRangeShiftUnits = fixedRangeShiftUnits;
}
/**
* Returns the current shift type.
* @return the current shift type.
* @see #SHIFT_FIXED
* @see #SHIFT_PERCENTUAL
* @see #SHIFT_PIXEL
*/
public int getShiftType() {
return shiftType;
}
/**
* Sets the shift type.
* @param the new shift type.
* @see #SHIFT_FIXED
* @see #SHIFT_PERCENTUAL
* @see #SHIFT_PIXEL
*/
public void setShiftType(int shiftType) {
this.shiftType = shiftType;
}
/**
* Returns whether or not the plot supports shifting.
* @return True if plot can be shifted.
*/
public boolean isPlotSupported() {
return plotSupported;
}
}
