com.tradedesksoftware.ets.client.charting.ChartShiftController.java Source code

Java tutorial

Introduction

Here is the source code for com.tradedesksoftware.ets.client.charting.ChartShiftController.java

Source

/*
 * Created on Jun 11, 2008
 *
 * This code is the proprietary confidential property of TradeDesk
 * Software Inc and may not be redistributed or used for any other
 * purpose without the express consent of TradeDesk Software Inc.
 * 
 * Copyright 2005-2007 TradeDesk Software Inc. All Rights Reserved
 */
package com.tradedesksoftware.ets.client.charting;

/**
 * @author tharter
 *
 *
 * $Id$
 */
/*
 * Copyright 2006 CPqD - Centro de Pesquisa e Desenvolvimento em Telecomunicaes.
 *
 * 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):  Ben Ogle;
 *
 * Changes
 * --------------------------
 * 26-Jan-2006 : First Version (GR);
 * 16-Mar-2007 : added mouse panning (BO);
 */

import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;

import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Cursor;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Display;
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 &larr; and &rarr; to shift the plot left and right; <br>
 * Use &uarr; and &darr; 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 ChartShiftController implements KeyListener, MouseMotionListener, MouseListener {

    /** 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 TooltipChartComposite 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;

    protected int oldx = -1;
    protected int oldy = -1;
    protected static final Cursor MOVE = new Cursor(Display.getCurrent(), SWT.CURSOR_HAND);
    protected static final Cursor ARROW = new Cursor(Display.getCurrent(), SWT.CURSOR_SIZEWE);

    /** 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 ChartShiftController(TooltipChartComposite 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 Rectangle scaledDataArea = chartPanel.getScreenDataArea();
            delta = axis.getRange().getLength() / (scaledDataArea.width);
            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) {
        if (e.getKeyCode() == KeyEvent.VK_CONTROL)
            chartPanel.setCursor(ARROW);
    }

    public void mouseDragged(MouseEvent mouseEvent) {
        if (!mouseEvent.isControlDown())
            return;

        if (oldx > -1 && oldy > -1) {
            ValueAxis domAxis = getPlotAxis(chartPanel.getChart(), !axesSwaped);
            ValueAxis rngAxis = getPlotAxis(chartPanel.getChart(), axesSwaped);

            int xdif = mouseEvent.getX() - oldx;
            int ydif = mouseEvent.getY() - oldy;

            final Rectangle scaledDataArea = chartPanel.getScreenDataArea();

            double xdelta = (double) xdif * domAxis.getRange().getLength() / (scaledDataArea.width);
            double ydelta = (double) ydif * rngAxis.getRange().getLength() / (scaledDataArea.height);

            domAxis.setRange(domAxis.getLowerBound() - xdelta, domAxis.getUpperBound() - xdelta);
            rngAxis.setRange(rngAxis.getLowerBound() + ydelta, rngAxis.getUpperBound() + ydelta);
        }

        oldx = mouseEvent.getX();
        oldy = mouseEvent.getY();
    }

    public void mouseMoved(MouseEvent mouseEvent) {
        if (mouseEvent.isControlDown()) {
            final Rectangle scaledDataArea = chartPanel.getScreenDataArea();
            if (mouseEvent.getX() > (int) scaledDataArea.x && mouseEvent.getY() > (int) scaledDataArea.y
                    && mouseEvent.getX() < (int) scaledDataArea.x + scaledDataArea.width
                    && mouseEvent.getY() < (int) scaledDataArea.y + scaledDataArea.height)
                chartPanel.setCursor(MOVE);
            else
                chartPanel.setCursor(ARROW);
        }
    }

    public void mouseReleased(MouseEvent mouseEvent) {
        oldx = -1;
        oldy = -1;
    }

    public void mouseClicked(MouseEvent mouseEvent) {
    }

    public void mousePressed(MouseEvent mouseEvent) {
    }

    public void mouseEntered(MouseEvent mouseEvent) {
    }

    public void mouseExited(MouseEvent mouseEvent) {
    }

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