📄 categoryaxis.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.
*
* -----------------
* CategoryAxis.java
* -----------------
* (C) Copyright 2000-2003, by Object Refinery Limited.
*
* Original Author: David Gilbert;
* Contributor(s): -;
*
* $Id: CategoryAxis.java,v 1.10 2003/07/24 10:49:14 mungady Exp $
*
* Changes (from 21-Aug-2001)
* --------------------------
* 21-Aug-2001 : Added standard header. Fixed DOS encoding problem (DG);
* 18-Sep-2001 : Updated header (DG);
* 04-Dec-2001 : Changed constructors to protected, and tidied up default values (DG);
* 19-Apr-2002 : Updated import statements (DG);
* 05-Sep-2002 : Updated constructor for changes in Axis class (DG);
* 06-Nov-2002 : Moved margins from the CategoryPlot class (DG);
* 08-Nov-2002 : Moved to new package com.jrefinery.chart.axis (DG);
* 22-Jan-2002 : Removed monolithic constructor (DG);
* 26-Mar-2003 : Implemented Serializable (DG);
* 09-May-2003 : Merged HorizontalCategoryAxis and VerticalCategoryAxis into this class (DG);
*
*/
package org.jfree.chart.axis;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.font.FontRenderContext;
import java.awt.font.LineBreakMeasurer;
import java.awt.font.LineMetrics;
import java.awt.font.TextLayout;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import java.io.Serializable;
import java.text.AttributedCharacterIterator;
import java.text.AttributedString;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.jfree.chart.event.AxisChangeEvent;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.plot.Plot;
import org.jfree.ui.RectangleEdge;
import org.jfree.ui.RefineryUtilities;
/**
* The base class for axes that display categories.
*
* @author David Gilbert
*/
public class CategoryAxis extends Axis implements Serializable {
/** The default setting for rotated category labels. */
public static final boolean DEFAULT_VERTICAL_CATEGORY_LABELS = false;
/** The default margin for the axis (used for both lower and upper margins). */
public static final double DEFAULT_AXIS_MARGIN = 0.05;
/** The default margin between categories (a percentage of the overall axis length). */
public static final double DEFAULT_CATEGORY_MARGIN = 0.20;
/** The amount of space reserved at the start of the axis. */
private double lowerMargin;
/** The amount of space reserved at the end of the axis. */
private double upperMargin;
/** The amount of space reserved between categories. */
private double categoryMargin;
/** A flag that indicates whether the category labels should be rotated 90 degrees. */
private boolean verticalCategoryLabels; // need to replace this with rotation, so that it fits
// with both horizontal and vertical axes
/** A flag that controls whether to skip category labels to avoid overlapping. */
private boolean skipCategoryLabelsToFit;
/** Tick line count */
private int maxTickLineCount;
/** Temporary list of categories. */
private List categories;
/** 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;
/**
* Constructs a category axis, using default values where necessary.
*
* @param label the axis label (<code>null</code> permitted).
*/
public CategoryAxis(String label) {
super(label);
this.lowerMargin = DEFAULT_AXIS_MARGIN;
this.upperMargin = DEFAULT_AXIS_MARGIN;
this.categoryMargin = DEFAULT_CATEGORY_MARGIN;
this.verticalCategoryLabels = DEFAULT_VERTICAL_CATEGORY_LABELS;
this.setTickMarksVisible(false); // not supported by this axis type yet
this.categories = new java.util.ArrayList();
this.reservedForAxisLabel = 0.0;
this.reservedForTickLabels = 0.0;
}
/**
* Returns the lower margin for the axis.
*
* @return the margin.
*/
public double getLowerMargin() {
return this.lowerMargin;
}
/**
* Sets the lower margin for the axis. An {@link AxisChangeEvent} is sent to all registered
* listeners.
*
* @param margin the new margin.
*/
public void setLowerMargin(double margin) {
this.lowerMargin = margin;
notifyListeners(new AxisChangeEvent(this));
}
/**
* Returns the upper margin for the axis.
*
* @return the margin.
*/
public double getUpperMargin() {
return this.upperMargin;
}
/**
* Sets the upper margin for the axis. An {@link AxisChangeEvent} is sent to all registered
* listeners.
*
* @param margin the new margin.
*/
public void setUpperMargin(double margin) {
this.upperMargin = margin;
notifyListeners(new AxisChangeEvent(this));
}
/**
* Returns the category margin.
*
* @return the margin.
*/
public double getCategoryMargin() {
return this.categoryMargin;
}
/**
* Sets the category margin. An {@link AxisChangeEvent} is sent to all registered
* listeners.
*
* @param margin the new margin.
*/
public void setCategoryMargin(double margin) {
this.categoryMargin = margin;
notifyListeners(new AxisChangeEvent(this));
}
/**
* Returns a flag indicating whether the category labels are rotated to vertical.
*
* @return The flag.
*/
public boolean isVerticalCategoryLabels() {
return this.verticalCategoryLabels;
}
/**
* Sets the flag that determines whether the category labels are rotated to vertical.
*
* @param flag the flag.
*/
public void setVerticalCategoryLabels(boolean flag) {
if (this.verticalCategoryLabels != flag) {
this.verticalCategoryLabels = flag;
notifyListeners(new AxisChangeEvent(this));
}
}
/**
* Returns the flag that determines whether the category labels are to be
* skipped to avoid overlapping.
*
* @return The flag.
*/
public boolean getSkipCategoryLabelsToFit() {
return this.skipCategoryLabelsToFit;
}
/**
* Sets the flag that determines whether the category labels are to be
* skipped to avoid overlapping.
*
* @param flag the new value of the flag.
*/
public void setSkipCategoryLabelsToFit(boolean flag) {
if (this.skipCategoryLabelsToFit != flag) {
this.skipCategoryLabelsToFit = flag;
notifyListeners(new AxisChangeEvent(this));
}
}
/**
* Returns the Java 2D coordinate for a category.
*
* @param anchor the anchor point.
* @param category the category index.
* @param categoryCount the category count.
* @param area the data area.
* @param edge the location of the axis.
*
* @return The coordinate.
*/
public double getCategoryJava2DCoordinate(CategoryAnchor anchor,
int category, int categoryCount, Rectangle2D area,
RectangleEdge edge) {
double result = 0.0;
if (anchor == CategoryAnchor.START) {
result = getCategoryStart(category, categoryCount, area, edge);
}
else if (anchor == CategoryAnchor.MIDDLE) {
result = getCategoryMiddle(category, categoryCount, area, edge);
}
else if (anchor == CategoryAnchor.END) {
result = getCategoryEnd(category, categoryCount, area, edge);
}
return result;
}
/**
* Returns the starting coordinate for the specified category.
*
* @param category the category.
* @param categoryCount the number of categories.
* @param area the data area.
* @param edge the axis location.
*
* @return the coordinate.
*/
public double getCategoryStart(int category, int categoryCount, Rectangle2D area,
RectangleEdge edge) {
double result = 0.0;
if ((edge == RectangleEdge.TOP) || (edge == RectangleEdge.BOTTOM)) {
result = area.getX() + area.getWidth() * getLowerMargin();
}
else if ((edge == RectangleEdge.LEFT) || (edge == RectangleEdge.RIGHT)) {
result = area.getMinY() + area.getHeight() * getLowerMargin();
}
double categorySize = calculateCategorySize(categoryCount, area, edge);
double categoryGapWidth = calculateCategoryGapSize(categoryCount, area, edge);
result = result + category * (categorySize + categoryGapWidth);
return result;
}
/**
* Returns the middle coordinate for the specified category.
*
* @param category the category.
* @param categoryCount the number of categories.
* @param area the data area.
* @param edge the axis location.
*
* @return the coordinate.
*/
public double getCategoryMiddle(int category, int categoryCount, Rectangle2D area,
RectangleEdge edge) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -