📄 intervalxydelegate.java
字号:
/* ===========================================================
* JFreeChart : a free chart library for the Java(tm) platform
* ===========================================================
*
* (C) Copyright 2000-2004, 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., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* [Java is a trademark or registered trademark of Sun Microsystems, Inc.
* in the United States and other countries.]
*
* -----------------------
* IntervalXYDelegate.java
* -----------------------
* (C) Copyright 2004, by Object Refinery Limited and Contributors.
*
* Original Author: Andreas Schroeder;
* Contributor(s): -;
*
* $Id: IntervalXYDelegate.java,v 1.1 2004/08/31 15:36:12 mungady Exp $
*
* Changes (from 31-Mar-2004)
* --------------------------
* 31-Mar-2004 : Version 1 (AS);
* 15-Jul-2004 : Switched getX() with getXValue() and getY() with getYValue() (DG);
* 18-Aug-2004 : Moved from org.jfree.data --> org.jfree.data.xy (DG);
*
*/
package org.jfree.data.xy;
import java.io.Serializable;
import org.jfree.data.DomainInfo;
import org.jfree.data.Range;
import org.jfree.data.general.DatasetUtilities;
import org.jfree.util.PublicCloneable;
/**
* A package only class for delegating xy-interval issues to.
* Enhances a XYDataset to an XYIntervalDataset. The decorator pattern
* was not used because of the several possibly implemented interfaces of
* the decorated instance (e.g. TableXYDataset, RangeInfo, DomainInfo etc.).
* <p>
* This class calculates the minimal interval width between two items. This width
* influences the width of bars displayed with this dataset.
* <p>
* The width can be set manually or calculated automatically. The switch
* autoWidth allows to determine which behavior is used. The behavior is
* transparent: The width is always calculated automatically in the background
* without affecting the manually set width. The switch simply determines which
* value is used. <br> As default manually set width, 1.0 is used. <br> If there
* is only one item in the series, the auto width calculation fails and falls
* back on the manually set interval width (which is itself defaulted to 1.0).
*
* @author andreas.schroeder
*/
class IntervalXYDelegate implements DomainInfo, Serializable, Cloneable, PublicCloneable {
/** For serialization. */
private static final long serialVersionUID = -685166711639592857L;
/**
* The dataset to enhance.
*/
private XYDataset dataset;
/**
* A flag to indicate wether the width should be calculated automatically.
*/
private boolean autoWidth;
/**
* A factor that determines the position of the gap between two bars - only
* relevant if the data is dispalyed with a bar renderer.
*/
private double intervalPositionFactor;
/**
* The manually set interval width.
*/
private double intervalWidth;
/**
* The automatically calculated interval width.
*/
private double autoIntervalWidth;
/**
* The lower value of the interval. Only used for autoWidth.
*/
private double lowerBound;
/**
* the upper value of the interval. Only used for autoWidth.
*/
private double upperBound;
/**
* Creates an XYIntervalDelegate.
*
* @param dataset the dataset for which this interval delegate works.
*/
public IntervalXYDelegate(final XYDataset dataset) {
this(dataset, true);
}
/**
* Creates an XYIntervalDelegate.
*
* @param dataset the dataset for which this interval delegate works.
* @param autoWidth ???.
*/
public IntervalXYDelegate(final XYDataset dataset, final boolean autoWidth) {
this.autoWidth = autoWidth;
this.dataset = dataset;
this.intervalPositionFactor = 0.5;
this.autoWidth = autoWidth;
this.autoIntervalWidth = Double.POSITIVE_INFINITY;
this.intervalWidth = 1.0;
}
/**
* Returns wether the interval width is automatically calculated or not.
*
* @return wether the width is automatically calcualted or not.
*/
public boolean isAutoWidth() {
return this.autoWidth;
}
/**
* Sets the flag that indicates wether the interval width is automatically
* calculated or not.
*
* @param b a boolean.
*/
public void setAutoWidth(final boolean b) {
this.autoWidth = b;
}
/**
* Returns the interval position factor.
*
* @return The interval position factor.
*/
public double getIntervalPositionFactor() {
return this.intervalPositionFactor;
}
/**
* Sets the interval position factor. Must be between 0.0 and 1.0 inclusive.
* If the factor is 0.5, the gap is in the middle of the x values. If it
* is lesser than 0.5, the gap is farther to the left and if greater than
* 0.5 it gets farther to the right.
*
* @param d the new interval position factor.
*/
public void setIntervalPositionFactor(final double d) {
if (d < 0.0 || 1.0 < d) {
return;
}
this.intervalPositionFactor = d;
}
/**
* Sets the interval width manually.
*
* @param d the new interval width.
*/
public void setIntervalWidth(final double d) {
this.intervalWidth = d;
}
/**
* returns the full interval width. For behavior of this method, see
* the class comments.
*
* @return the interval width to use.
*/
public double getIntervalWidth() {
if (isAutoWidth() && !Double.isInfinite(this.autoIntervalWidth)) {
// everything is fine: autoWidth is on, and an autoIntervalWidth was set.
return this.autoIntervalWidth;
}
else {
// either autoWidth is off or autoIntervalWidth was not set.
return this.intervalWidth;
}
}
/**
* returns the start x value based on the intervalWidth and the intervalPositionFactor.
*
* @param series the series index.
* @param item the item index.
* @return the start value based on the intervalWidth and the intervalPositionFactor.
*/
public Number getStartX(int series, int item) {
Number startX = null;
Number x = this.dataset.getX(series, item);
if (x != null) {
startX = new Double(x.doubleValue()
- (getIntervalPositionFactor() * getIntervalWidth()));
}
return startX;
}
/**
* returns the end x value based on the intervalWidth and the intervalPositionFactor.
*
* @param series the series index.
* @param item the item index.
* @return the end value based on the intervalWidth and the intervalPositionFactor.
*/
public Number getEndX(int series, int item) {
Number endX = null;
Number x = this.dataset.getX(series, item);
if (x != null) {
endX = new Double(x.doubleValue()
+ ((1.0 - getIntervalPositionFactor()) * getIntervalWidth()));
}
return endX;
}
/**
* Returns the domain range. If the dataset contains a single item in one
* series, the returned domain range is extended by the double interval
* width.
*
* @return the domain range.
*/
public Range getDomainRange() {
Range range = DatasetUtilities.iterateDomainExtent(this.dataset);
if (this.dataset.getSeriesCount() == 1 && this.dataset.getItemCount(0) == 1) {
/* if there is only one interval value, so add some space to the left
* and the right - otherwise one bar looks like a background
* coloration.
*/
range = new Range(
range.getLowerBound() - getIntervalWidth(),
range.getUpperBound() + getIntervalWidth()
);
}
return range;
}
/**
* Returns the maximum domain value of the delegating dataset.
*
* @return The maximum domain value.
*/
public Number getMaximumDomainValue() {
return new Double(getDomainRange().getUpperBound());
}
/**
* Returns the minimum domain value of the delegating dataset.
*
* @return The minimum domain value.
*/
public Number getMinimumDomainValue() {
return new Double(getDomainRange().getLowerBound());
}
/**
* updates the interval width if an item is added, i.e. relaxes the interval width to the
* minimum of the actual interval width, the distance between the actual x value and
* the previous x value and the distance between the next x value and the
* actual x value.
*
* @param item the number of the item.
* @param series the number of the series
*
*/
public void itemAdded(final int series, final int item) {
double x = this.dataset.getXValue(series, item);
if (item > 0) {
double before = this.dataset.getXValue(series, item - 1);
double delta = x - before;
if (delta < this.autoIntervalWidth) {
this.autoIntervalWidth = delta;
this.lowerBound = before;
this.upperBound = x;
}
}
if (item + 1 < this.dataset.getItemCount(series)) {
double after = this.dataset.getXValue(series, item + 1);
double delta = after - x;
if (delta < this.autoIntervalWidth) {
this.autoIntervalWidth = delta;
this.lowerBound = x;
this.upperBound = after;
}
}
}
/**
* updates the interval width if an item is removed, i.e. enlarges the
* interval width to the new interval minimum if the removed value was
* part of the minimum. For performance reason this methos should be called
* only if the x value was definitely removed from the series.
*
* @param x the x value of the removed item (that doesn't occur twice)
*/
public void itemRemoved(final double x) {
if (x == this.lowerBound || x == this.upperBound) {
recalculateIntervalWidth();
}
}
/**
* Recalculate the minimum width "from scratch".
*/
private void recalculateIntervalWidth() {
this.autoIntervalWidth = Double.POSITIVE_INFINITY;
for (int series = 0, seriesCount = this.dataset.getSeriesCount();
series < seriesCount; series++) {
calculateSeries(series);
}
}
/**
* Calculates the interval width for a given series.
*
* @param series the series index.
*/
private void calculateSeries(int series) {
int totalCount = this.dataset.getItemCount(series);
for (int item = 1, itemCount = totalCount; item < itemCount; item++) {
double lower = this.dataset.getXValue(series, item - 1);
double upper = this.dataset.getXValue(series, item);
double delta = upper - lower;
if (delta < this.autoIntervalWidth) {
this.autoIntervalWidth = delta;
this.lowerBound = lower;
this.upperBound = upper;
}
}
}
/**
* Convenience method for XYSeriesCollection.
*
* @param series the series index.
*/
public void seriesAdded(final int series) {
calculateSeries(series);
}
/**
* A convenience method for {@link XYSeriesCollection} which is called whenever a series
* is removed - the interval width is recalculated.
*/
public void seriesRemoved() {
recalculateIntervalWidth();
}
/**
* @return a clone of this delegate.
*
* @throws CloneNotSupportedException if the object cannot be cloned.
*/
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -