alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

jfreechart example source code file (CombinedRangeCategoryPlot.java)

This example jfreechart source code file (CombinedRangeCategoryPlot.java) is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Java - jfreechart tags/keywords

awt, axisspace, categoryplot, categoryplot, combinedrangecategoryplot, combinedrangecategoryplot, geometry, illegalargumentexception, io, iterator, legenditemcollection, list, plotrenderinginfo, rectangle2d, rectangle2d, util, valueaxis, valueaxis

The jfreechart CombinedRangeCategoryPlot.java source code

/* ===========================================================
 * JFreeChart : a free chart library for the Java(tm) platform
 * ===========================================================
 *
 * (C) Copyright 2000-2008, by Object Refinery Limited and Contributors.
 *
 * Project Info:  http://www.jfree.org/jfreechart/index.html
 *
 * 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.]
 *
 * ------------------------------
 * CombinedRangeCategoryPlot.java
 * ------------------------------
 * (C) Copyright 2003-2008, by Object Refinery Limited.
 *
 * Original Author:  David Gilbert (for Object Refinery Limited);
 * Contributor(s):   Nicolas Brodu;
 *
 * Changes:
 * --------
 * 16-May-2003 : Version 1 (DG);
 * 08-Aug-2003 : Adjusted totalWeight in remove() method (DG);
 * 19-Aug-2003 : Implemented Cloneable (DG);
 * 11-Sep-2003 : Fix cloning support (subplots) (NB);
 * 15-Sep-2003 : Implemented PublicCloneable.  Fixed errors in cloning and
 *               serialization (DG);
 * 16-Sep-2003 : Changed ChartRenderingInfo --> PlotRenderingInfo (DG);
 * 17-Sep-2003 : Updated handling of 'clicks' (DG);
 * 04-May-2004 : Added getter/setter methods for 'gap' attributes (DG);
 * 12-Nov-2004 : Implements the new Zoomable interface (DG);
 * 25-Nov-2004 : Small update to clone() implementation (DG);
 * 21-Feb-2005 : Fixed bug in remove() method (id = 1121172) (DG);
 * 21-Feb-2005 : The getLegendItems() method now returns the fixed legend
 *               items if set (DG);
 * 05-May-2005 : Updated draw() method parameters (DG);
 * 14-Nov-2007 : Updated setFixedDomainAxisSpaceForSubplots() method (DG);
 * 27-Mar-2008 : Add documentation for getDataRange() method (DG);
 * 31-Mar-2008 : Updated getSubplots() to return EMPTY_LIST for null
 *               subplots, as suggested by Richard West (DG);
 * 26-Jun-2008 : Fixed crosshair support (DG);
 * 11-Aug-2008 : Don't store totalWeight of subplots, calculate it as
 *               required (DG);
 *
 */

package org.jfree.chart.plot;

import java.awt.Graphics2D;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

import org.jfree.chart.LegendItemCollection;
import org.jfree.chart.axis.AxisSpace;
import org.jfree.chart.axis.AxisState;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.axis.ValueAxis;
import org.jfree.chart.event.PlotChangeEvent;
import org.jfree.chart.event.PlotChangeListener;
import org.jfree.data.Range;
import org.jfree.ui.RectangleEdge;
import org.jfree.ui.RectangleInsets;
import org.jfree.util.ObjectUtilities;

/**
 * A combined category plot where the range axis is shared.
 */
public class CombinedRangeCategoryPlot extends CategoryPlot
        implements PlotChangeListener {

    /** For serialization. */
    private static final long serialVersionUID = 7260210007554504515L;

    /** Storage for the subplot references. */
    private List subplots;

    /** The gap between subplots. */
    private double gap;

    /** Temporary storage for the subplot areas. */
    private transient Rectangle2D[] subplotArea;  // TODO: move to plot state

    /**
     * Default constructor.
     */
    public CombinedRangeCategoryPlot() {
        this(new NumberAxis());
    }

    /**
     * Creates a new plot.
     *
     * @param rangeAxis  the shared range axis.
     */
    public CombinedRangeCategoryPlot(ValueAxis rangeAxis) {
        super(null, null, rangeAxis, null);
        this.subplots = new java.util.ArrayList();
        this.gap = 5.0;
    }

    /**
     * Returns the space between subplots.
     *
     * @return The gap (in Java2D units).
     */
    public double getGap() {
        return this.gap;
    }

    /**
     * Sets the amount of space between subplots and sends a
     * {@link PlotChangeEvent} to all registered listeners.
     *
     * @param gap  the gap between subplots (in Java2D units).
     */
    public void setGap(double gap) {
        this.gap = gap;
        fireChangeEvent();
    }

    /**
     * Adds a subplot (with a default 'weight' of 1) and sends a
     * {@link PlotChangeEvent} to all registered listeners.
     * <br>
* You must ensure that the subplot has a non-null domain axis. The range * axis for the subplot will be set to <code>null. * * @param subplot the subplot (<code>null not permitted). */ public void add(CategoryPlot subplot) { // defer argument checking add(subplot, 1); } /** * Adds a subplot and sends a {@link PlotChangeEvent} to all registered * listeners. * <br>
* You must ensure that the subplot has a non-null domain axis. The range * axis for the subplot will be set to <code>null. * * @param subplot the subplot (<code>null not permitted). * @param weight the weight (must be >= 1). */ public void add(CategoryPlot subplot, int weight) { if (subplot == null) { throw new IllegalArgumentException("Null 'subplot' argument."); } if (weight <= 0) { throw new IllegalArgumentException("Require weight >= 1."); } // store the plot and its weight subplot.setParent(this); subplot.setWeight(weight); subplot.setInsets(new RectangleInsets(0.0, 0.0, 0.0, 0.0)); subplot.setRangeAxis(null); subplot.setOrientation(getOrientation()); subplot.addChangeListener(this); this.subplots.add(subplot); // configure the range axis... ValueAxis axis = getRangeAxis(); if (axis != null) { axis.configure(); } fireChangeEvent(); } /** * Removes a subplot from the combined chart. * * @param subplot the subplot (<code>null not permitted). */ public void remove(CategoryPlot subplot) { if (subplot == null) { throw new IllegalArgumentException(" Null 'subplot' argument."); } int position = -1; int size = this.subplots.size(); int i = 0; while (position == -1 && i < size) { if (this.subplots.get(i) == subplot) { position = i; } i++; } if (position != -1) { this.subplots.remove(position); subplot.setParent(null); subplot.removeChangeListener(this); ValueAxis range = getRangeAxis(); if (range != null) { range.configure(); } ValueAxis range2 = getRangeAxis(1); if (range2 != null) { range2.configure(); } fireChangeEvent(); } } /** * Returns the list of subplots. The returned list may be empty, but is * never <code>null. * * @return An unmodifiable list of subplots. */ public List getSubplots() { if (this.subplots != null) { return Collections.unmodifiableList(this.subplots); } else { return Collections.EMPTY_LIST; } } /** * Calculates the space required for the axes. * * @param g2 the graphics device. * @param plotArea the plot area. * * @return The space required for the axes. */ protected AxisSpace calculateAxisSpace(Graphics2D g2, Rectangle2D plotArea) { AxisSpace space = new AxisSpace(); PlotOrientation orientation = getOrientation(); // work out the space required by the domain axis... AxisSpace fixed = getFixedRangeAxisSpace(); if (fixed != null) { if (orientation == PlotOrientation.VERTICAL) { space.setLeft(fixed.getLeft()); space.setRight(fixed.getRight()); } else if (orientation == PlotOrientation.HORIZONTAL) { space.setTop(fixed.getTop()); space.setBottom(fixed.getBottom()); } } else { ValueAxis valueAxis = getRangeAxis(); RectangleEdge valueEdge = Plot.resolveRangeAxisLocation( getRangeAxisLocation(), orientation); if (valueAxis != null) { space = valueAxis.reserveSpace(g2, this, plotArea, valueEdge, space); } } Rectangle2D adjustedPlotArea = space.shrink(plotArea, null); // work out the maximum height or width of the non-shared axes... int n = this.subplots.size(); int totalWeight = 0; for (int i = 0; i < n; i++) { CategoryPlot sub = (CategoryPlot) this.subplots.get(i); totalWeight += sub.getWeight(); } // calculate plotAreas of all sub-plots, maximum vertical/horizontal // axis width/height this.subplotArea = new Rectangle2D[n]; double x = adjustedPlotArea.getX(); double y = adjustedPlotArea.getY(); double usableSize = 0.0; if (orientation == PlotOrientation.VERTICAL) { usableSize = adjustedPlotArea.getWidth() - this.gap * (n - 1); } else if (orientation == PlotOrientation.HORIZONTAL) { usableSize = adjustedPlotArea.getHeight() - this.gap * (n - 1); } for (int i = 0; i < n; i++) { CategoryPlot plot = (CategoryPlot) this.subplots.get(i); // calculate sub-plot area if (orientation == PlotOrientation.VERTICAL) { double w = usableSize * plot.getWeight() / totalWeight; this.subplotArea[i] = new Rectangle2D.Double(x, y, w, adjustedPlotArea.getHeight()); x = x + w + this.gap; } else if (orientation == PlotOrientation.HORIZONTAL) { double h = usableSize * plot.getWeight() / totalWeight; this.subplotArea[i] = new Rectangle2D.Double(x, y, adjustedPlotArea.getWidth(), h); y = y + h + this.gap; } AxisSpace subSpace = plot.calculateDomainAxisSpace(g2, this.subplotArea[i], null); space.ensureAtLeast(subSpace); } return space; } /** * Draws the plot on a Java 2D graphics device (such as the screen or a * printer). Will perform all the placement calculations for each * sub-plots and then tell these to draw themselves. * * @param g2 the graphics device. * @param area the area within which the plot (including axis labels) * should be drawn. * @param anchor the anchor point (<code>null permitted). * @param parentState the parent state. * @param info collects information about the drawing (<code>null * permitted). */ public void draw(Graphics2D g2, Rectangle2D area, Point2D anchor, PlotState parentState, PlotRenderingInfo info) { // set up info collection... if (info != null) { info.setPlotArea(area); } // adjust the drawing area for plot insets (if any)... RectangleInsets insets = getInsets(); insets.trim(area); // calculate the data area... AxisSpace space = calculateAxisSpace(g2, area); Rectangle2D dataArea = space.shrink(area, null); // set the width and height of non-shared axis of all sub-plots setFixedDomainAxisSpaceForSubplots(space); // draw the shared axis ValueAxis axis = getRangeAxis(); RectangleEdge rangeEdge = getRangeAxisEdge(); double cursor = RectangleEdge.coordinate(dataArea, rangeEdge); AxisState state = axis.draw(g2, cursor, area, dataArea, rangeEdge, info); if (parentState == null) { parentState = new PlotState(); } parentState.getSharedAxisStates().put(axis, state); // draw all the charts for (int i = 0; i < this.subplots.size(); i++) { CategoryPlot plot = (CategoryPlot) this.subplots.get(i); PlotRenderingInfo subplotInfo = null; if (info != null) { subplotInfo = new PlotRenderingInfo(info.getOwner()); info.addSubplotInfo(subplotInfo); } Point2D subAnchor = null; if (anchor != null && this.subplotArea[i].contains(anchor)) { subAnchor = anchor; } plot.draw(g2, this.subplotArea[i], subAnchor, parentState, subplotInfo); } if (info != null) { info.setDataArea(dataArea); } } /** * Sets the orientation for the plot (and all the subplots). * * @param orientation the orientation. */ public void setOrientation(PlotOrientation orientation) { super.setOrientation(orientation); Iterator iterator = this.subplots.iterator(); while (iterator.hasNext()) { CategoryPlot plot = (CategoryPlot) iterator.next(); plot.setOrientation(orientation); } } /** * Returns a range representing the extent of the data values in this plot * (obtained from the subplots) that will be rendered against the specified * axis. NOTE: This method is intended for internal JFreeChart use, and * is public only so that code in the axis classes can call it. Since * only the range axis is shared between subplots, the JFreeChart code * will only call this method for the range values (although this is not * checked/enforced). * * @param axis the axis. * * @return The range. */ public Range getDataRange(ValueAxis axis) { Range result = null; if (this.subplots != null) { Iterator iterator = this.subplots.iterator(); while (iterator.hasNext()) { CategoryPlot subplot = (CategoryPlot) iterator.next(); result = Range.combine(result, subplot.getDataRange(axis)); } } return result; } /** * Returns a collection of legend items for the plot. * * @return The legend items. */ public LegendItemCollection getLegendItems() { LegendItemCollection result = getFixedLegendItems(); if (result == null) { result = new LegendItemCollection(); if (this.subplots != null) { Iterator iterator = this.subplots.iterator(); while (iterator.hasNext()) { CategoryPlot plot = (CategoryPlot) iterator.next(); LegendItemCollection more = plot.getLegendItems(); result.addAll(more); } } } return result; } /** * Sets the size (width or height, depending on the orientation of the * plot) for the domain axis of each subplot. * * @param space the space. */ protected void setFixedDomainAxisSpaceForSubplots(AxisSpace space) { Iterator iterator = this.subplots.iterator(); while (iterator.hasNext()) { CategoryPlot plot = (CategoryPlot) iterator.next(); plot.setFixedDomainAxisSpace(space, false); } } /** * Handles a 'click' on the plot by updating the anchor value. * * @param x x-coordinate of the click. * @param y y-coordinate of the click. * @param info information about the plot's dimensions. * */ public void handleClick(int x, int y, PlotRenderingInfo info) { Rectangle2D dataArea = info.getDataArea(); if (dataArea.contains(x, y)) { for (int i = 0; i < this.subplots.size(); i++) { CategoryPlot subplot = (CategoryPlot) this.subplots.get(i); PlotRenderingInfo subplotInfo = info.getSubplotInfo(i); subplot.handleClick(x, y, subplotInfo); } } } /** * Receives a {@link PlotChangeEvent} and responds by notifying all * listeners. * * @param event the event. */ public void plotChanged(PlotChangeEvent event) { notifyListeners(event); } /** * Tests the plot for equality with an arbitrary object. * * @param obj the object (<code>null permitted). * * @return <code>true or false. */ public boolean equals(Object obj) { if (obj == this) { return true; } if (!(obj instanceof CombinedRangeCategoryPlot)) { return false; } CombinedRangeCategoryPlot that = (CombinedRangeCategoryPlot) obj; if (this.gap != that.gap) { return false; } if (!ObjectUtilities.equal(this.subplots, that.subplots)) { return false; } return super.equals(obj); } /** * Returns a clone of the plot. * * @return A clone. * * @throws CloneNotSupportedException this class will not throw this * exception, but subclasses (if any) might. */ public Object clone() throws CloneNotSupportedException { CombinedRangeCategoryPlot result = (CombinedRangeCategoryPlot) super.clone(); result.subplots = (List) ObjectUtilities.deepClone(this.subplots); for (Iterator it = result.subplots.iterator(); it.hasNext();) { Plot child = (Plot) it.next(); child.setParent(result); } // after setting up all the subplots, the shared range axis may need // reconfiguring ValueAxis rangeAxis = result.getRangeAxis(); if (rangeAxis != null) { rangeAxis.configure(); } return result; } /** * Provides serialization support. * * @param stream the input stream. * * @throws IOException if there is an I/O error. * @throws ClassNotFoundException if there is a classpath problem. */ private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException { stream.defaultReadObject(); // the range axis is deserialized before the subplots, so its value // range is likely to be incorrect... ValueAxis rangeAxis = getRangeAxis(); if (rangeAxis != null) { rangeAxis.configure(); } } }

Other jfreechart examples (source code examples)

Here is a short list of links related to this jfreechart CombinedRangeCategoryPlot.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.