📄 valueaxis.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.
*
* --------------
* ValueAxis.java
* --------------
* (C) Copyright 2000-2003, by Object Refinery Limited and Contributors.
*
* Original Author: David Gilbert (for Object Refinery Limited);
* Contributor(s): Jonathan Nash;
*
* $Id: ValueAxis.java,v 1.12 2003/07/24 10:49:15 mungady Exp $
*
* Changes (from 18-Sep-2001)
* --------------------------
* 18-Sep-2001 : Added standard header and fixed DOS encoding problem (DG);
* 23-Nov-2001 : Overhauled standard tick unit code (DG);
* 04-Dec-2001 : Changed constructors to protected, and tidied up default values (DG);
* 12-Dec-2001 : Fixed vertical gridlines bug (DG);
* 16-Jan-2002 : Added an optional crosshair, based on the implementation by Jonathan Nash (DG);
* 23-Jan-2002 : Moved the minimum and maximum values to here from NumberAxis, and changed the type
* from Number to double (DG);
* 25-Feb-2002 : Added default value for autoRange. Changed autoAdjustRange from public to
* protected. Updated import statements (DG);
* 23-Apr-2002 : Added setRange(...) method (DG);
* 29-Apr-2002 : Added range adjustment methods (DG);
* 13-Jun-2002 : Modified setCrosshairValue(...) to notify listeners only when the crosshairs are
* visible, to avoid unnecessary repaints, as suggested by Kees Kuip (DG);
* 25-Jul-2002 : Moved lower and upper margin attributes from the NumberAxis class (DG);
* 05-Sep-2002 : Updated constructor for changes in Axis class (DG);
* 01-Oct-2002 : Fixed errors reported by Checkstyle (DG);
* 04-Oct-2002 : Moved standardTickUnits from NumberAxis --> ValueAxis (DG);
* 08-Nov-2002 : Moved to new package com.jrefinery.chart.axis (DG);
* 19-Nov-2002 : Removed grid settings (now controlled by the plot) (DG);
* 27-Nov-2002 : Moved the 'inverted' attributed from NumberAxis to ValueAxis (DG);
* 03-Jan-2003 : Small fix to ensure auto-range minimum is observed immediately (DG);
* 14-Jan-2003 : Changed autoRangeMinimumSize from Number --> double (DG);
* 20-Jan-2003 : Replaced monolithic constructor (DG);
* 26-Mar-2003 : Implemented Serializable (DG);
* 09-May-2003 : Added AxisLocation parameter to translation methods (DG);
*
*/
package org.jfree.chart.axis;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Paint;
import java.awt.Shape;
import java.awt.Stroke;
import java.awt.geom.AffineTransform;
import java.awt.geom.GeneralPath;
import java.awt.geom.Line2D;
import java.awt.geom.Rectangle2D;
import java.io.Serializable;
import org.jfree.chart.event.AxisChangeEvent;
import org.jfree.data.Range;
import org.jfree.ui.RectangleEdge;
/**
* The base class for axes that display value data, where values are measured using the
* <code>double</code> primitive. The two key subclasses are {@link DateAxis} and
* {@link NumberAxis}.
*
* @author David Gilbert
*/
public abstract class ValueAxis extends Axis implements Serializable {
/** The default axis range. */
public static final Range DEFAULT_RANGE = new Range(0.0, 1.0);
/** The default auto-range value. */
public static final boolean DEFAULT_AUTO_RANGE = true;
/** The default inverted flag setting. */
public static final boolean DEFAULT_INVERTED = false;
/** The default minimum auto range. */
public static final double DEFAULT_AUTO_RANGE_MINIMUM_SIZE = 0.0000001;
/** The default value for the lower margin (0.05 = 5%). */
public static final double DEFAULT_LOWER_MARGIN = 0.05;
/** The default value for the upper margin (0.05 = 5%). */
public static final double DEFAULT_UPPER_MARGIN = 0.05;
/** The default lower bound for the axis. */
public static final double DEFAULT_LOWER_BOUND = 0.0;
/** The default upper bound for the axis. */
public static final double DEFAULT_UPPER_BOUND = 1.0;
/** The default auto-tick-unit-selection value. */
public static final boolean DEFAULT_AUTO_TICK_UNIT_SELECTION = true;
/** The maximum tick count. */
public static final int MAXIMUM_TICK_COUNT = 500;
/** A flag that controls whether or not a line is drawn for the axis. */
private boolean axisLineVisible;
/** A flag that controls whether an arrow is drawn at the positive end of the axis line. */
private boolean axisLineHasPositiveArrow;
/** A flag that controls whether an arrow is drawn at the negative end of the axis line. */
private boolean axisLineHasNegativeArrow;
/** The shape used for an up arrow. */
private Shape upArrow;
/** The shape used for a down arrow. */
private Shape downArrow;
/** The shape used for a left arrow. */
private Shape leftArrow;
/** The shape used for a right arrow. */
private Shape rightArrow;
/** The paint used for the axis line. */
private Paint axisLinePaint = Color.gray;
/** The stroke used for the axis line. */
private Stroke axisLineStroke = new BasicStroke(1.0f);
/** A flag that affects the orientation of the values on the axis. */
private boolean inverted;
/** The axis range. */
private Range range;
/** Flag that indicates whether the axis automatically scales to fit the chart data. */
private boolean autoRange;
/** The minimum size for the 'auto' axis range (excluding margins). */
private double autoRangeMinimumSize;
/**
* The upper margin percentage. This indicates the amount by which the maximum axis value
* exceeds the maximum data value (as a percentage of the range on the axis) when the axis
* range is determined automatically.
*/
private double upperMargin;
/**
* The lower margin. This is a percentage that indicates the amount by
* which the minimum axis value is "less than" the minimum data value when
* the axis range is determined automatically.
*/
private double lowerMargin;
/**
* If this value is positive, the amount is subtracted from the maximum
* data value to determine the lower axis range. This can be used to
* provide a fixed "window" on dynamic data.
*/
private double fixedAutoRange;
/** Flag that indicates whether or not the tick unit is selected automatically. */
private boolean autoTickUnitSelection;
/** The standard tick units for the axis. */
private TickUnits standardTickUnits;
/** An index into an array of standard tick values. */
private int autoTickIndex;
/** A temporary record of the amount of space reserved for the tick labels. */
protected double reservedForTickLabels;
/** A temporary record of the amount of space reserved for the axis label. */
protected double reservedForAxisLabel;
/** A flag indicating whether or not tick labels are rotated to vertical. */
private boolean verticalTickLabels;
/**
* Constructs a value axis.
*
* @param label the axis label.
* @param standardTickUnits a collection of standard tick units.
*/
protected ValueAxis(String label,
TickUnits standardTickUnits) {
super(label);
this.axisLineVisible = true;
this.axisLineHasPositiveArrow = false;
this.axisLineHasNegativeArrow = false;
this.axisLinePaint = Color.gray;
this.axisLineStroke = new BasicStroke(1.0f);
this.range = DEFAULT_RANGE;
this.autoRange = DEFAULT_AUTO_RANGE;
this.inverted = DEFAULT_INVERTED;
this.autoRangeMinimumSize = DEFAULT_AUTO_RANGE_MINIMUM_SIZE;
this.lowerMargin = DEFAULT_LOWER_MARGIN;
this.upperMargin = DEFAULT_UPPER_MARGIN;
this.fixedAutoRange = 0.0;
this.autoTickUnitSelection = DEFAULT_AUTO_TICK_UNIT_SELECTION;
this.standardTickUnits = standardTickUnits;
// this.anchorValue = 0.0;
GeneralPath path1 = new GeneralPath();
path1.moveTo(0.0f, 0.0f);
path1.lineTo(-2.0f, 2.0f);
path1.lineTo(2.0f, 2.0f);
path1.closePath();
this.upArrow = path1;
GeneralPath path2 = new GeneralPath();
path2.moveTo(0.0f, 0.0f);
path2.lineTo(-2.0f, -2.0f);
path2.lineTo(2.0f, -2.0f);
path2.closePath();
this.downArrow = path2;
GeneralPath path3 = new GeneralPath();
path3.moveTo(0.0f, 0.0f);
path3.lineTo(-2.0f, -2.0f);
path3.lineTo(-2.0f, 2.0f);
path3.closePath();
this.rightArrow = path3;
GeneralPath path4 = new GeneralPath();
path4.moveTo(0.0f, 0.0f);
path4.lineTo(2.0f, -2.0f);
path4.lineTo(2.0f, 2.0f);
path4.closePath();
this.leftArrow = path4;
this.verticalTickLabels = false;
}
/**
* Returns true if the tick labels should be rotated (to vertical), and false otherwise.
*
* @return <code>true</code> or <code>false</code>.
*/
public boolean isVerticalTickLabels() {
return this.verticalTickLabels;
}
/**
* Sets the flag that controls whether the tick labels are displayed vertically (that is,
* rotated 90 degrees from horizontal).
* <P>
* If the flag is changed, an {@link AxisChangeEvent} is sent to all registered listeners.
*
* @param flag the flag.
*/
public void setVerticalTickLabels(boolean flag) {
if (this.verticalTickLabels != flag) {
this.verticalTickLabels = flag;
notifyListeners(new AxisChangeEvent(this));
}
}
/**
* A flag that controls whether or not the axis line is drawn.
*
* @return A boolean.
*/
public boolean isAxisLineVisible() {
return this.axisLineVisible;
}
/**
* Sets a flag that controls whether or not the axis line is visible.
*
* @param visible the flag.
*/
public void setAxisLineVisible(boolean visible) {
this.axisLineVisible = visible;
notifyListeners(new AxisChangeEvent(this));
}
/**
* Draws an axis line at the current cursor position and edge.
*
* @param g2 the graphics device.
* @param cursor the cursor position.
* @param dataArea the data area.
* @param edge the edge.
*/
protected void drawAxisLine(Graphics2D g2, double cursor,
Rectangle2D dataArea, RectangleEdge edge) {
Line2D axisLine = null;
if (edge == RectangleEdge.TOP) {
axisLine = new Line2D.Double(dataArea.getX(), cursor, dataArea.getMaxX(), cursor);
}
else if (edge == RectangleEdge.BOTTOM) {
axisLine = new Line2D.Double(dataArea.getX(), cursor, dataArea.getMaxX(), cursor);
}
else if (edge == RectangleEdge.LEFT) {
axisLine = new Line2D.Double(cursor, dataArea.getY(), cursor, dataArea.getMaxY());
}
else if (edge == RectangleEdge.RIGHT) {
axisLine = new Line2D.Double(cursor, dataArea.getY(), cursor, dataArea.getMaxY());
}
g2.setPaint(this.axisLinePaint);
g2.draw(axisLine);
if (this.axisLineHasPositiveArrow) {
double x = 0.0;
double y = 0.0;
Shape arrow = null;
if (edge == RectangleEdge.TOP || edge == RectangleEdge.BOTTOM) {
x = dataArea.getMaxX();
y = cursor;
arrow = this.rightArrow;
}
else if (edge == RectangleEdge.LEFT || edge == RectangleEdge.RIGHT) {
x = cursor;
y = dataArea.getMinY();
arrow = this.upArrow;
}
// draw an arrow at the positive end...
AffineTransform transformer = new AffineTransform();
transformer.setToTranslation(x, y);
Shape shape = transformer.createTransformedShape(arrow);
g2.fill(shape);
g2.draw(shape);
}
if (this.axisLineHasNegativeArrow) {
double x = 0.0;
double y = 0.0;
Shape arrow = null;
if (edge == RectangleEdge.TOP || edge == RectangleEdge.BOTTOM) {
x = dataArea.getMinX();
y = cursor;
arrow = this.leftArrow;
}
else if (edge == RectangleEdge.LEFT || edge == RectangleEdge.RIGHT) {
x = cursor;
y = dataArea.getMaxY();
arrow = this.downArrow;
}
// draw an arrow at the positive end...
AffineTransform transformer = new AffineTransform();
transformer.setToTranslation(x, y);
Shape shape = transformer.createTransformedShape(arrow);
g2.fill(shape);
g2.draw(shape);
}
}
/**
* Returns a flag that controls the direction of values on the axis.
* <P>
* For a regular axis, values increase from left to right (for a horizontal
* axis) and bottom to top (for a vertical axis). When the axis is
* 'inverted', the values increase in the opposite direction.
*
* @return the flag.
*/
public boolean isInverted() {
return this.inverted;
}
/**
* Sets a flag that controls the direction of values on the axis, and
* notifies registered listeners that the axis has changed.
*
* @param flag the flag.
*/
public void setInverted(boolean flag) {
if (this.inverted != flag) {
this.inverted = flag;
notifyListeners(new AxisChangeEvent(this));
}
}
/**
* Returns true if the axis range is automatically adjusted to fit the data.
*
* @return the auto-range flag.
*/
public boolean isAutoRange() {
return autoRange;
}
/**
* Sets a flag that determines whether or not the axis range is
* automatically adjusted to fit the data, and notifies registered
* listeners that the axis has been modified.
*
* @param auto the new value of the flag.
*/
public void setAutoRange(boolean auto) {
setAutoRange(auto, true);
}
/**
* Sets the auto range attribute. If the <code>notify</code> flag is set, an
* {@link AxisChangeEvent} is sent to registered listeners.
*
* @param auto the new value of the flag.
* @param notify notify listeners?
*/
protected void setAutoRange(boolean auto, boolean notify) {
if (this.autoRange != auto) {
this.autoRange = auto;
if (this.autoRange) {
autoAdjustRange();
}
if (notify) {
notifyListeners(new AxisChangeEvent(this));
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -