www.pudn.com > jfreechart-0.9.12.zip > Axis.java


/* ====================================== 
 * JFreeChart : a free Java chart library 
 * ====================================== 
 * 
 * Project Info:  http://www.jfree.org/jfreechart/index.html 
 * Project Lead:  David Gilbert (david.gilbert@object-refinery.com); 
 * 
 * (C) Copyright 2000-2003, by Object Refinery Limited and Contributors. 
 * 
 * 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., 59 Temple Place, Suite 330, 
 * Boston, MA 02111-1307, USA. 
 * 
 * --------- 
 * Axis.java 
 * --------- 
 * (C) Copyright 2000-2003, by Object Refinery Limited and Contributors. 
 * 
 * Original Author:  David Gilbert (for Object Refinery Limited); 
 * Contributor(s):   Bill Kelemen; 
 * 
 * $Id: Axis.java,v 1.18 2003/09/08 21:24:15 mungady Exp $ 
 * 
 * Changes (from 21-Aug-2001) 
 * -------------------------- 
 * 21-Aug-2001 : Added standard header, fixed DOS encoding problem (DG); 
 * 18-Sep-2001 : Updated header (DG); 
 * 07-Nov-2001 : Allow null axis labels (DG); 
 *             : Added default font values (DG); 
 * 13-Nov-2001 : Modified the setPlot(...) method to check compatibility between the axis and the 
 *               plot (DG); 
 * 30-Nov-2001 : Changed default font from "Arial" --> "SansSerif" (DG); 
 * 06-Dec-2001 : Allow null in setPlot(...) method (BK); 
 * 06-Mar-2002 : Added AxisConstants interface (DG); 
 * 23-Apr-2002 : Added a visible property.  Moved drawVerticalString to RefineryUtilities.  Added 
 *               fixedDimension property for use in combined plots (DG); 
 * 25-Jun-2002 : Removed unnecessary imports (DG); 
 * 05-Sep-2002 : Added attribute for tick mark paint (DG); 
 * 18-Sep-2002 : Fixed errors reported by Checkstyle (DG); 
 * 07-Nov-2002 : Added attributes to control the inside and outside length of the tick marks (DG); 
 * 08-Nov-2002 : Moved to new package com.jrefinery.chart.axis (DG); 
 * 18-Nov-2002 : Added axis location to refreshTicks(...) parameters (DG); 
 * 15-Jan-2003 : Removed monolithic constructor (DG); 
 * 17-Jan-2003 : Moved plot classes to separate package (DG); 
 * 26-Mar-2003 : Implemented Serializable (DG); 
 * 03-Jul-2003 : Modified reserveSpace method (DG); 
 * 13-Aug-2003 : Implemented Cloneable (DG); 
 * 
 */ 
 
package org.jfree.chart.axis; 
 
import java.awt.Font; 
import java.awt.Graphics2D; 
import java.awt.Insets; 
import java.awt.Paint; 
import java.awt.Shape; 
import java.awt.Stroke; 
import java.awt.font.FontRenderContext; 
import java.awt.font.LineMetrics; 
import java.awt.geom.AffineTransform; 
import java.awt.geom.Rectangle2D; 
import java.io.IOException; 
import java.io.ObjectInputStream; 
import java.io.ObjectOutputStream; 
import java.io.Serializable; 
import java.util.Iterator; 
import java.util.List; 
 
import javax.swing.event.EventListenerList; 
 
import org.jfree.chart.event.AxisChangeEvent; 
import org.jfree.chart.event.AxisChangeListener; 
import org.jfree.chart.plot.Plot; 
import org.jfree.chart.plot.PlotNotCompatibleException; 
import org.jfree.io.SerialUtilities; 
import org.jfree.ui.RectangleEdge; 
import org.jfree.ui.RefineryUtilities; 
import org.jfree.ui.TextAnchor; 
import org.jfree.util.ObjectUtils; 
 
/** 
 * The base class for all axes in JFreeChart.  Subclasses are divided into those that display 
 * values ({@link ValueAxis}) and those that display categories ({@link CategoryAxis}). 
 * 
 * @author David Gilbert 
 */ 
public abstract class Axis implements AxisConstants, Cloneable, Serializable { 
 
    /** A flag indicating whether or not the axis is visible. */ 
    private boolean visible; 
 
    /** The label for the axis. */ 
    private String label; 
 
    /** The font for displaying the axis label. */ 
    private Font labelFont; 
 
    /** The paint for drawing the axis label. */ 
    private transient Paint labelPaint; 
 
    /** The insets for the axis label. */ 
    private Insets labelInsets; 
 
    /** The label angle. */ 
    private double labelAngle; 
 
    /** A flag that indicates whether or not tick labels are visible for the axis. */ 
    private boolean tickLabelsVisible; 
 
    /** The font used to display the tick labels. */ 
    private Font tickLabelFont; 
 
    /** The color used to display the tick labels. */ 
    private transient Paint tickLabelPaint; 
 
    /** The blank space around each tick label. */ 
    private Insets tickLabelInsets; 
 
    /** A flag that indicates whether or not tick marks are visible for the axis. */ 
    private boolean tickMarksVisible; 
 
    /** The length of the tick mark inside the data area (zero permitted). */ 
    private float tickMarkInsideLength; 
 
    /** The length of the tick mark outside the data area (zero permitted). */ 
    private float tickMarkOutsideLength; 
 
    /** The stroke used to draw tick marks. */ 
    private transient Stroke tickMarkStroke; 
 
    /** The paint used to draw tick marks. */ 
    private transient Paint tickMarkPaint; 
 
    /** The fixed (horizontal or vertical) dimension for the axis. */ 
    private double fixedDimension; 
 
    /** A working list of ticks - this list is refreshed as required. */ 
    private transient List ticks; 
 
    /** A reference back to the plot that the axis is assigned to (can be null). */ 
    private transient Plot plot; 
 
    /** Storage for registered listeners. */ 
    private transient EventListenerList listenerList; 
 
    /** 
     * Constructs an axis, using default values where necessary. 
     * 
     * @param label  the axis label (null permitted). 
     */ 
    protected Axis(String label) { 
 
        this.label = label; 
        this.visible = DEFAULT_AXIS_VISIBLE; 
        this.labelFont = DEFAULT_AXIS_LABEL_FONT; 
        this.labelPaint = DEFAULT_AXIS_LABEL_PAINT; 
        this.labelInsets = DEFAULT_AXIS_LABEL_INSETS; 
        this.labelAngle = 0.0; 
        this.tickLabelsVisible = DEFAULT_TICK_LABELS_VISIBLE; 
        this.tickLabelFont = DEFAULT_TICK_LABEL_FONT; 
        this.tickLabelPaint = DEFAULT_TICK_LABEL_PAINT; 
        this.tickLabelInsets = DEFAULT_TICK_LABEL_INSETS; 
        this.tickMarksVisible = DEFAULT_TICK_MARKS_VISIBLE; 
        this.tickMarkStroke = DEFAULT_TICK_MARK_STROKE; 
        this.tickMarkPaint = DEFAULT_TICK_MARK_PAINT; 
        this.tickMarkInsideLength = DEFAULT_TICK_MARK_INSIDE_LENGTH; 
        this.tickMarkOutsideLength = DEFAULT_TICK_MARK_OUTSIDE_LENGTH; 
 
        this.plot = null; 
 
        this.ticks = new java.util.ArrayList(); 
        this.listenerList = new EventListenerList(); 
 
    } 
 
    /** 
     * Returns true if the axis is visible, and false otherwise. 
     * 
     * @return a flag indicating whether or not the axis is visible. 
     */ 
    public boolean isVisible() { 
        return this.visible; 
    } 
 
    /** 
     * Sets a flag that controls whether or not the axis is drawn on the chart.  An 
     * {@link AxisChangeEvent} is sent to all registered listeners. 
     * 
     * @param flag  the flag. 
     */ 
    public void setVisible(boolean flag) { 
 
        if (flag != this.visible) { 
            this.visible = flag; 
            notifyListeners(new AxisChangeEvent(this)); 
        } 
 
    } 
 
    /** 
     * Returns the label for the axis. 
     * 
     * @return the label for the axis (null possible). 
     */ 
    public String getLabel() { 
        return label; 
    } 
 
    /** 
     * Sets the label for the axis (null permitted).  An {@link AxisChangeEvent} is 
     * sent to all registered listeners. 
     * 
     * @param label  the new label. 
     */ 
    public void setLabel(String label) { 
 
        String existing = this.label; 
        if (existing != null) { 
            if (!existing.equals(label)) { 
                this.label = label; 
                notifyListeners(new AxisChangeEvent(this)); 
            } 
        } 
        else { 
            if (label != null) { 
                this.label = label; 
                notifyListeners(new AxisChangeEvent(this)); 
            } 
        } 
 
    } 
 
    /** 
     * Returns the font for the axis label. 
     * 
     * @return the font. 
     */ 
    public Font getLabelFont() { 
        return labelFont; 
    } 
 
    /** 
     * Sets the font for the axis label. 
     * 

* Registered listeners are notified of a general change to the axis. * * @param font the new label font. */ public void setLabelFont(Font font) { // check arguments... if (font == null) { throw new IllegalArgumentException("Axis.setLabelFont(...): null not permitted."); } // make the change (if necessary)... if (!this.labelFont.equals(font)) { this.labelFont = font; notifyListeners(new AxisChangeEvent(this)); } } /** * Returns the color/shade used to draw the axis label. * * @return the color/shade used to draw the axis label. */ public Paint getLabelPaint() { return this.labelPaint; } /** * Sets the color/shade used to draw the axis label. *

* Registered listeners are notified of a general change to the axis. * * @param paint the new color/shade for the axis label. */ public void setLabelPaint(Paint paint) { // check arguments... if (paint == null) { throw new IllegalArgumentException("Axis.setLabelPaint(...): null not permitted."); } // make the change (if necessary)... if (!this.labelPaint.equals(paint)) { this.labelPaint = paint; notifyListeners(new AxisChangeEvent(this)); } } /** * Returns the insets for the label (that is, the amount of blank space * that should be left around the label). * * @return the label insets. */ public Insets getLabelInsets() { return this.labelInsets; } /** * Sets the insets for the axis label, and notifies registered listeners * that the axis has been modified. * * @param insets the new label insets. */ public void setLabelInsets(Insets insets) { if (!insets.equals(this.labelInsets)) { this.labelInsets = insets; notifyListeners(new AxisChangeEvent(this)); } } /** * Returns the angle of the axis label. * * @return The angle. */ public double getLabelAngle() { return this.labelAngle; } /** * Sets the angle for the label. After the change is made, an {@link AxisChangeEvent} is sent * to all registered listeners. * * @param angle the angle (in radians). */ public void setLabelAngle(double angle) { this.labelAngle = angle; notifyListeners(new AxisChangeEvent(this)); } /** * Returns a flag indicating whether or not the tick labels are visible. * * @return the flag. */ public boolean isTickLabelsVisible() { return tickLabelsVisible; } /** * Sets the flag that determines whether or not the tick labels are visible. *

* Registered listeners are notified of a general change to the axis. * * @param flag the flag. */ public void setTickLabelsVisible(boolean flag) { if (flag != tickLabelsVisible) { tickLabelsVisible = flag; notifyListeners(new AxisChangeEvent(this)); } } /** * Returns the font used for the tick labels (if showing). * * @return The font (should never be null). */ public Font getTickLabelFont() { return tickLabelFont; } /** * Sets the font for the tick labels. An {@link AxisChangeEvent} is sent to all registered * listeners. * * @param font the font (null not allowed). */ public void setTickLabelFont(Font font) { // check arguments... if (font == null) { throw new IllegalArgumentException("Axis.setTickLabelFont(...): null not permitted."); } // apply change if necessary... if (!this.tickLabelFont.equals(font)) { this.tickLabelFont = font; notifyListeners(new AxisChangeEvent(this)); } } /** * Returns the color/shade used for the tick labels. * * @return the color/shade used for the tick labels. */ public Paint getTickLabelPaint() { return this.tickLabelPaint; } /** * Sets the color/shade used to draw tick labels (if they are showing). *

* Registered listeners are notified of a general change to the axis. * * @param paint the new color/shade. */ public void setTickLabelPaint(Paint paint) { // check arguments... if (paint == null) { throw new IllegalArgumentException("Axis.setTickLabelPaint(...): null not permitted."); } // make the change (if necessary)... if (!this.tickLabelPaint.equals(paint)) { this.tickLabelPaint = paint; notifyListeners(new AxisChangeEvent(this)); } } /** * Returns the insets for the tick labels. * * @return the insets for the tick labels. */ public Insets getTickLabelInsets() { return this.tickLabelInsets; } /** * Sets the insets for the tick labels, and notifies registered listeners * that the axis has been modified. * * @param insets the new tick label insets. */ public void setTickLabelInsets(Insets insets) { // check arguments... if (insets == null) { throw new IllegalArgumentException("Axis.setTickLabelInsets(...): null not permitted."); } // apply change if necessary... if (!this.tickLabelInsets.equals(insets)) { this.tickLabelInsets = insets; notifyListeners(new AxisChangeEvent(this)); } } /** * Returns the flag that indicates whether or not the tick marks are * showing. * * @return the flag that indicates whether or not the tick marks are showing. */ public boolean isTickMarksVisible() { return tickMarksVisible; } /** * Sets the flag that indicates whether or not the tick marks are showing. *

* Registered listeners are notified of a general change to the axis. * * @param flag the flag. */ public void setTickMarksVisible(boolean flag) { if (flag != tickMarksVisible) { tickMarksVisible = flag; notifyListeners(new AxisChangeEvent(this)); } } /** * Returns the inside length of the tick marks. * * @return the length. */ public float getTickMarkInsideLength() { return this.tickMarkInsideLength; } /** * Sets the inside length of the tick marks. * * @param length the new length. */ public void setTickMarkInsideLength(float length) { this.tickMarkInsideLength = length; notifyListeners(new AxisChangeEvent(this)); } /** * Returns the outside length of the tick marks. * * @return the length. */ public float getTickMarkOutsideLength() { return this.tickMarkOutsideLength; } /** * Sets the outside length of the tick marks. * * @param length the new length. */ public void setTickMarkOutsideLength(float length) { this.tickMarkOutsideLength = length; notifyListeners(new AxisChangeEvent(this)); } /** * Returns the pen/brush used to draw tick marks (if they are showing). * * @return the pen/brush used to draw tick marks. */ public Stroke getTickMarkStroke() { return tickMarkStroke; } /** * Sets the pen/brush used to draw tick marks (if they are showing). *

* Registered listeners are notified of a general change to the axis. * * @param stroke the new pen/brush (null not permitted). */ public void setTickMarkStroke(Stroke stroke) { // check arguments... if (stroke == null) { throw new IllegalArgumentException("Axis.setTickMarkStroke(...): null not permitted."); } // make the change (if necessary)... if (!this.tickMarkStroke.equals(stroke)) { this.tickMarkStroke = stroke; notifyListeners(new AxisChangeEvent(this)); } } /** * Returns the paint used to draw tick marks (if they are showing). * * @return the paint. */ public Paint getTickMarkPaint() { return tickMarkPaint; } /** * Sets the paint used to draw tick marks (if they are showing). *

* Registered listeners are notified of a general change to the axis. * * @param paint the new paint (null not permitted). */ public void setTickMarkPaint(Paint paint) { // check arguments... if (paint == null) { throw new IllegalArgumentException("Axis.setTickMarkPaint(...): null not permitted."); } // make the change (if necessary)... if (!this.tickMarkPaint.equals(paint)) { this.tickMarkPaint = paint; notifyListeners(new AxisChangeEvent(this)); } } /** * Returns the current list of ticks. * * @return the ticks. */ public List getTicks() { return this.ticks; } /** * Returns the plot that the axis is assigned to. *

* This method will return null if the axis is not currently assigned to a * plot. * * @return The plot that the axis is assigned to. */ public Plot getPlot() { return plot; } /** * Sets a reference to the plot that the axis is assigned to. *

* This method is used internally, you shouldn't need to call it yourself. * * @param plot the plot. * * @throws PlotNotCompatibleException if plot is not compatible. */ public void setPlot(Plot plot) throws PlotNotCompatibleException { if (isCompatiblePlot(plot) || plot == null) { this.plot = plot; configure(); } else { throw new PlotNotCompatibleException( "Axis.setPlot(...): plot not compatible with axis."); } } /** * Returns the fixed dimension for the axis. * * @return the fixed dimension. */ public double getFixedDimension() { return this.fixedDimension; } /** * Sets the fixed dimension for the axis. *

* This is used when combining more than one plot on a chart. In this case, * there may be several axes that need to have the same height or width so * that they are aligned. This method is used to fix a dimension for the * axis (the context determines whether the dimension is horizontal or * vertical). * * @param dimension the fixed dimension. */ public void setFixedDimension(double dimension) { this.fixedDimension = dimension; } /** * Configures the axis to work with the current plot. Override this method * to perform any special processing (such as auto-rescaling). */ public abstract void configure(); /** * Estimates the space (height or width) required to draw the axis. * * @param g2 the graphics device. * @param plot the plot that the axis belongs to. * @param plotArea the area within which the plot (including axes) should be drawn. * @param edge the axis location. * @param space space already reserved. * * @return the height required to draw the axis. */ public abstract AxisSpace reserveSpace(Graphics2D g2, Plot plot, Rectangle2D plotArea, RectangleEdge edge, AxisSpace space); /** * Draws the axis on a Java 2D graphics device (such as the screen or a printer). * * @param g2 the graphics device. * @param cursor the cursor location (determines where to draw the axis). * @param plotArea the area within which the axes and plot should be drawn. * @param dataArea the area within which the data should be drawn. * @param edge the axis location (TOP, BOTTOM, RIGHT or LEFT). * * @return The new cursor position. */ public abstract double draw(Graphics2D g2, double cursor, Rectangle2D plotArea, Rectangle2D dataArea, RectangleEdge edge); /** * Calculates the positions of the ticks for the axis, storing the results * in the tick list (ready for drawing). * * @param g2 the graphics device. * @param cursor the cursor location. * @param plotArea the area within which the axes and plot should be drawn. * @param dataArea the area inside the axes. * @param edge the edge on which the axis is located. */ public abstract void refreshTicks(Graphics2D g2, double cursor, Rectangle2D plotArea, Rectangle2D dataArea, RectangleEdge edge); /** * Returns the maximum width of the ticks in the working list (that is set * up by refreshTicks()). * * @param g2 the graphics device. * @param plotArea the area within which the plot is to be drawn. * * @return the maximum width of the ticks in the working list. */ protected double getMaxTickLabelWidth(Graphics2D g2, Rectangle2D plotArea) { double maxWidth = 0.0; Font font = getTickLabelFont(); FontRenderContext frc = g2.getFontRenderContext(); Iterator iterator = this.ticks.iterator(); while (iterator.hasNext()) { Tick tick = (Tick) iterator.next(); Rectangle2D labelBounds = font.getStringBounds(tick.getText(), frc); if (labelBounds.getWidth() > maxWidth) { maxWidth = labelBounds.getWidth(); } } return maxWidth; } /** * Returns true if the plot is compatible with the axis. * * @param plot the plot. * * @return true if the plot is compatible with the axis. */ protected abstract boolean isCompatiblePlot(Plot plot); /** * Registers an object for notification of changes to the axis. * * @param listener the object that is being registered. */ public void addChangeListener(AxisChangeListener listener) { this.listenerList.add(AxisChangeListener.class, listener); } /** * Deregisters an object for notification of changes to the axis. * * @param listener the object to deregister. */ public void removeChangeListener(AxisChangeListener listener) { this.listenerList.remove(AxisChangeListener.class, listener); } /** * Notifies all registered listeners that the axis has changed. * The AxisChangeEvent provides information about the change. * * @param event information about the change to the axis. */ protected void notifyListeners(AxisChangeEvent event) { Object[] listeners = this.listenerList.getListenerList(); for (int i = listeners.length - 2; i >= 0; i -= 2) { if (listeners[i] == AxisChangeListener.class) { ((AxisChangeListener) listeners[i + 1]).axisChanged(event); } } } /** * Returns a rectangle that encloses the axis label. This is typically used for layout * purposes (it gives the maximum dimensions of the label). * * @param g2 the graphics device. * @param edge the edge of the plot area along which the axis is measuring. * * @return The enclosing rectangle. */ protected Rectangle2D getLabelEnclosure(Graphics2D g2, RectangleEdge edge) { // calculate the width of the axis label... Rectangle2D result = new Rectangle2D.Double(); String axisLabel = getLabel(); if (axisLabel != null) { Font font = getLabelFont(); Rectangle2D bounds = font.getStringBounds(axisLabel, g2.getFontRenderContext()); Insets insets = getLabelInsets(); bounds.setRect(bounds.getX(), bounds.getY(), bounds.getWidth() + insets.left + insets.right, bounds.getHeight() + insets.top + insets.bottom); double angle = getLabelAngle(); if (edge == RectangleEdge.LEFT || edge == RectangleEdge.RIGHT) { angle = angle - Math.PI / 2.0; } double x = bounds.getCenterX(); double y = bounds.getCenterY(); AffineTransform transformer = AffineTransform.getRotateInstance(angle, x, y); Shape labelBounds = transformer.createTransformedShape(bounds); result = labelBounds.getBounds2D(); } return result; } /** * Draws the axis label. * * @param label the label text. * @param g2 the graphics device. * @param cursor the cursor value. * @param plotArea the plot area. * @param dataArea the area inside the axes. * @param edge the location of the axis. * * @return The width or height used for the label. */ protected double drawLabel(String label, Graphics2D g2, double cursor, Rectangle2D plotArea, Rectangle2D dataArea, RectangleEdge edge) { if ((label == null) || (label.equals(""))) { return 0.0; } Font font = getLabelFont(); Insets insets = getLabelInsets(); g2.setFont(font); g2.setPaint(getLabelPaint()); FontRenderContext frc = g2.getFontRenderContext(); Rectangle2D labelBounds = font.getStringBounds(label, frc); LineMetrics lm = font.getLineMetrics(label, frc); double used = 0.0; if (edge == RectangleEdge.TOP) { AffineTransform t = AffineTransform.getRotateInstance(getLabelAngle(), labelBounds.getCenterX(), labelBounds.getCenterY()); Shape rotatedLabelBounds = t.createTransformedShape(labelBounds); labelBounds = rotatedLabelBounds.getBounds2D(); double labelx = dataArea.getCenterX(); double labely = cursor - insets.bottom - labelBounds.getHeight() / 2.0; RefineryUtilities.drawRotatedString(label, g2, (float) labelx, (float) labely, TextAnchor.CENTER, TextAnchor.CENTER, getLabelAngle()); used = insets.top + labelBounds.getHeight() + insets.bottom; } else if (edge == RectangleEdge.BOTTOM) { AffineTransform t = AffineTransform.getRotateInstance(getLabelAngle(), labelBounds.getCenterX(), labelBounds.getCenterY()); Shape rotatedLabelBounds = t.createTransformedShape(labelBounds); labelBounds = rotatedLabelBounds.getBounds2D(); double labelx = dataArea.getCenterX(); double labely = cursor + insets.top + labelBounds.getHeight() / 2.0; RefineryUtilities.drawRotatedString(label, g2, (float) labelx, (float) labely, TextAnchor.CENTER, TextAnchor.CENTER, getLabelAngle()); used = insets.top + labelBounds.getHeight() + insets.bottom; } else if (edge == RectangleEdge.LEFT) { AffineTransform t = AffineTransform.getRotateInstance(getLabelAngle() - Math.PI / 2.0, labelBounds.getCenterX(), labelBounds.getCenterY()); Shape rotatedLabelBounds = t.createTransformedShape(labelBounds); labelBounds = rotatedLabelBounds.getBounds2D(); double labelx = cursor - insets.right - labelBounds.getWidth() / 2.0; double labely = dataArea.getY() + dataArea.getHeight() / 2.0; RefineryUtilities.drawRotatedString(label, g2, (float) labelx, (float) labely, TextAnchor.CENTER, TextAnchor.CENTER, getLabelAngle() - Math.PI / 2.0); used = insets.left + labelBounds.getWidth() + insets.right; } else if (edge == RectangleEdge.RIGHT) { AffineTransform t = AffineTransform.getRotateInstance(getLabelAngle() + Math.PI / 2.0, labelBounds.getCenterX(), labelBounds.getCenterY()); Shape rotatedLabelBounds = t.createTransformedShape(labelBounds); labelBounds = rotatedLabelBounds.getBounds2D(); double labelx = cursor + insets.left + labelBounds.getWidth() / 2.0; double labely = dataArea.getY() + dataArea.getHeight() / 2.0; RefineryUtilities.drawRotatedString(label, g2, (float) labelx, (float) labely, TextAnchor.CENTER, TextAnchor.CENTER, getLabelAngle() + Math.PI / 2.0); used = insets.left + labelBounds.getWidth() + insets.right; } return used; } /** * Returns a clone of the axis. * * @return A clone. * * @throws CloneNotSupportedException if some component of the axis does not support cloning. */ public Object clone() throws CloneNotSupportedException { Axis clone = (Axis) super.clone(); // boolean visible; // String label; // Font labelFont // Paint labelPaint; if (this.labelInsets != null) { clone.labelInsets = (Insets) this.labelInsets.clone(); } // double labelAngle; // boolean tickLabelsVisible; // Font tickLabelFont; // Paint tickLabelPaint; if (this.tickLabelInsets != null) { clone.tickLabelInsets = (Insets) this.tickLabelInsets.clone(); } // boolean tickMarksVisible; // float tickMarkInsideLength; // float tickMarkOutsideLength; // Stroke tickMarkStroke; // Paint tickMarkPaint; // List ticks; // Plot plot; // double fixedDimension; // EventListenerList listenerList; return clone; } /** * Tests this axis for equality with another object. * * @param obj the object. * * @return true or false. */ public boolean equals(Object obj) { if (obj == null) { return false; } if (obj == this) { return true; } if (obj instanceof Axis) { Axis axis = (Axis) obj; boolean b0 = (this.visible == axis.visible); boolean b1 = ObjectUtils.equal(this.label, axis.label); boolean b2 = ObjectUtils.equal(this.labelFont, axis.labelFont); boolean b3 = ObjectUtils.equal(this.labelPaint, axis.labelPaint); boolean b4 = ObjectUtils.equal(this.labelInsets, axis.labelInsets); boolean b15 = (Math.abs(this.labelAngle - axis.labelAngle) < 0.0000001); boolean b5 = (this.tickLabelsVisible == axis.tickLabelsVisible); boolean b6 = ObjectUtils.equal(this.tickLabelFont, axis.tickLabelFont); boolean b7 = ObjectUtils.equal(this.tickLabelPaint, axis.tickLabelPaint); boolean b8 = ObjectUtils.equal(this.tickLabelInsets, axis.tickLabelInsets); boolean b9 = (this.tickMarksVisible == axis.tickMarksVisible); boolean b10 = (Math.abs(this.tickMarkInsideLength - axis.tickMarkInsideLength) < 0.000001); boolean b11 = (Math.abs(this.tickMarkOutsideLength - axis.tickMarkOutsideLength) < 0.000001); boolean b12 = ObjectUtils.equal(this.tickMarkPaint, axis.tickMarkPaint); boolean b13 = ObjectUtils.equal(this.tickMarkStroke, axis.tickMarkStroke); boolean b14 = (Math.abs(this.fixedDimension - axis.fixedDimension) < 0.000001); return b0 && b1 && b2 && b3 && b4 && b5 && b6 && b7 && b8 && b9 && b10 && b11 && b12 && b13 && b14 && b15; } return false; } /** * Provides serialization support. * * @param stream the output stream. * * @throws IOException if there is an I/O error. */ private void writeObject(ObjectOutputStream stream) throws IOException { stream.defaultWriteObject(); SerialUtilities.writePaint(this.labelPaint, stream); SerialUtilities.writePaint(this.tickLabelPaint, stream); SerialUtilities.writeStroke(this.tickMarkStroke, stream); SerialUtilities.writePaint(this.tickMarkPaint, stream); } /** * 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(); this.labelPaint = SerialUtilities.readPaint(stream); this.tickLabelPaint = SerialUtilities.readPaint(stream); this.tickMarkStroke = SerialUtilities.readStroke(stream); this.tickMarkPaint = SerialUtilities.readPaint(stream); this.listenerList = new EventListenerList(); this.ticks = new java.util.ArrayList(); } }