📄 dateaxis.java
字号:
units.add(new DateTickUnit(DateTickUnit.YEAR, 1, DateTickUnit.MONTH, 1, f7));
units.add(new DateTickUnit(DateTickUnit.YEAR, 2, DateTickUnit.MONTH, 3, f7));
units.add(new DateTickUnit(DateTickUnit.YEAR, 5, DateTickUnit.YEAR, 1, f7));
units.add(new DateTickUnit(DateTickUnit.YEAR, 10, DateTickUnit.YEAR, 1, f7));
units.add(new DateTickUnit(DateTickUnit.YEAR, 25, DateTickUnit.YEAR, 5, f7));
units.add(new DateTickUnit(DateTickUnit.YEAR, 50, DateTickUnit.YEAR, 10, f7));
units.add(new DateTickUnit(DateTickUnit.YEAR, 100, DateTickUnit.YEAR, 20, f7));
return units;
}
/**
* Rescales the axis to ensure that all data is visible.
*/
protected void autoAdjustRange() {
Plot plot = getPlot();
if (plot == null) {
return; // no plot, no data
}
if (plot instanceof ValueAxisPlot) {
ValueAxisPlot vap = (ValueAxisPlot) plot;
Range r = vap.getDataRange(this);
if (r == null) {
if (this.timeline instanceof SegmentedTimeline) { //Timeline hasn't method getStartTime()
r = new DateRange(((SegmentedTimeline) this.timeline).getStartTime(),
((SegmentedTimeline) this.timeline).getStartTime() + 1);
} else {
r = new DateRange();
}
}
long upper = this.timeline.toTimelineValue(new Date((long) r.getUpperBound()));
long lower;
long fixedAutoRange = (long) getFixedAutoRange();
if (fixedAutoRange > 0.0) {
lower = upper - fixedAutoRange;
}
else {
lower = this.timeline.toTimelineValue(new Date((long) r.getLowerBound())); double range = upper - lower;
long minRange = (long) getAutoRangeMinimumSize();
if (range < minRange) {
long expand = (long) (minRange - range) / 2;
upper = upper + expand;
lower = lower - expand;
}
upper = upper + (long) (range * getUpperMargin());
lower = lower - (long) (range * getLowerMargin());
}
upper = this.timeline.toMillisecond(upper);
lower = this.timeline.toMillisecond(lower);
DateRange dr = new DateRange(new Date(lower), new Date(upper));
setRange(dr, false, false);
}
}
/**
* Selects an appropriate tick value for the axis. The strategy is to
* display as many ticks as possible (selected from an array of 'standard'
* tick units) without the labels overlapping.
*
* @param g2 the graphics device.
* @param drawArea the area in which the plot and axes should be drawn.
* @param dataArea the area defined by the axes.
* @param edge the axis location.
*/
protected void selectAutoTickUnit(Graphics2D g2, Rectangle2D drawArea, Rectangle2D dataArea,
RectangleEdge edge) {
if (RectangleEdge.isTopOrBottom(edge)) {
selectHorizontalAutoTickUnit(g2, drawArea, dataArea, edge);
}
else if (RectangleEdge.isLeftOrRight(edge)) {
selectVerticalAutoTickUnit(g2, drawArea, dataArea, edge);
}
}
/**
* Selects an appropriate tick size for the axis. The strategy is to
* display as many ticks as possible (selected from a collection of 'standard'
* tick units) without the labels overlapping.
*
* @param g2 the graphics device.
* @param drawArea the area in which the plot and axes should be drawn.
* @param dataArea the area defined by the axes.
* @param edge the axis location.
*/
protected void selectHorizontalAutoTickUnit(Graphics2D g2, Rectangle2D drawArea,
Rectangle2D dataArea, RectangleEdge edge) {
long shift = 0;
if (this.timeline instanceof SegmentedTimeline) {
shift = ((SegmentedTimeline) this.timeline).getStartTime();
}
double zero = translateValueToJava2D(shift + 0.0, dataArea, edge);
double tickLabelWidth = estimateMaximumTickLabelWidth(g2, getTickUnit());
// start with the current tick unit...
TickUnitSource tickUnits = getStandardTickUnits();
TickUnit unit1 = tickUnits.getCeilingTickUnit(getTickUnit());
double x1 = translateValueToJava2D(shift + unit1.getSize(), dataArea, edge);
double unit1Width = Math.abs(x1 - zero);
// then extrapolate...
double guess = (tickLabelWidth / unit1Width) * unit1.getSize();
DateTickUnit unit2 = (DateTickUnit) tickUnits.getCeilingTickUnit(guess);
double x2 = translateValueToJava2D(shift + unit2.getSize(), dataArea, edge); // TODO: _2
double unit2Width = Math.abs(x2 - zero);
tickLabelWidth = estimateMaximumTickLabelWidth(g2, unit2);
if (tickLabelWidth > unit2Width) {
unit2 = (DateTickUnit) tickUnits.getLargerTickUnit(unit2);
}
setTickUnit(unit2, false, false);
}
/**
* Selects an appropriate tick size for the axis. The strategy is to
* display as many ticks as possible (selected from a collection of 'standard'
* tick units) without the labels overlapping.
*
* @param g2 the graphics device.
* @param drawArea the area in which the plot and axes should be drawn.
* @param dataArea the area in which the plot should be drawn.
* @param edge the axis location.
*/
protected void selectVerticalAutoTickUnit(Graphics2D g2,
Rectangle2D drawArea,
Rectangle2D dataArea,
RectangleEdge edge) {
// start with the current tick unit...
TickUnitSource tickUnits = getStandardTickUnits();
double zero = translateValueToJava2D(0.0, dataArea, edge);
// start with a unit that is at least 1/10th of the axis length
double estimate1 = getRange().getLength() / 10.0;
DateTickUnit candidate1 = (DateTickUnit) tickUnits.getCeilingTickUnit(estimate1);
double labelHeight1 = estimateMaximumTickLabelHeight(g2, candidate1);
double y1 = translateValueToJava2D(candidate1.getSize(), dataArea, edge);
double candidate1UnitHeight = Math.abs(y1 - zero);
// now extrapolate based on label height and unit height...
double estimate2 = (labelHeight1 / candidate1UnitHeight) * candidate1.getSize();
DateTickUnit candidate2 = (DateTickUnit) tickUnits.getCeilingTickUnit(estimate2);
double labelHeight2 = estimateMaximumTickLabelHeight(g2, candidate2);
double y2 = translateValueToJava2D(candidate2.getSize(), dataArea, edge);
double unit2Height = Math.abs(y2 - zero);
// make final selection...
DateTickUnit finalUnit;
if (labelHeight2 < unit2Height) {
finalUnit = candidate2;
}
else {
finalUnit = (DateTickUnit) tickUnits.getLargerTickUnit(candidate2);
}
setTickUnit(finalUnit, false, false);
}
/**
* Estimates the maximum width of the tick labels, assuming the specified tick unit is used.
* <P>
* Rather than computing the string bounds of every tick on the axis, we just look at two
* values: the lower bound and the upper bound for the axis. These two values will usually
* be representative.
*
* @param g2 the graphics device.
* @param unit the tick unit to use for calculation.
*
* @return the estimated maximum width of the tick labels.
*/
private double estimateMaximumTickLabelWidth(Graphics2D g2, DateTickUnit unit) {
Insets tickLabelInsets = getTickLabelInsets();
double result = tickLabelInsets.left + tickLabelInsets.right;
Font tickLabelFont = getTickLabelFont();
FontRenderContext frc = g2.getFontRenderContext();
LineMetrics lm = tickLabelFont.getLineMetrics("ABCxyz", frc);
if (isVerticalTickLabels()) {
// all tick labels have the same width (equal to the height of the font)...
result += lm.getHeight();
}
else {
// look at lower and upper bounds...
DateRange range = (DateRange) getRange();
Date lower = range.getLowerDate();
Date upper = range.getUpperDate();
String lowerStr = null;
String upperStr = null;
DateFormat formatter = getDateFormatOverride();
if (formatter != null) {
lowerStr = formatter.format(lower);
upperStr = formatter.format(upper);
}
else {
lowerStr = unit.dateToString(lower);
upperStr = unit.dateToString(upper);
}
FontMetrics fm = g2.getFontMetrics(tickLabelFont);
double w1 = fm.stringWidth(lowerStr);
double w2 = fm.stringWidth(upperStr);
result += Math.max(w1, w2);
}
return result;
}
/**
* Estimates the maximum width of the tick labels, assuming the specified tick unit is used.
* <P>
* Rather than computing the string bounds of every tick on the axis, we just look at two
* values: the lower bound and the upper bound for the axis. These two values will usually
* be representative.
*
* @param g2 the graphics device.
* @param unit the tick unit to use for calculation.
*
* @return the estimated maximum width of the tick labels.
*/
private double estimateMaximumTickLabelHeight(Graphics2D g2, DateTickUnit unit) {
Insets tickLabelInsets = getTickLabelInsets();
double result = tickLabelInsets.top + tickLabelInsets.bottom;
Font tickLabelFont = getTickLabelFont();
FontRenderContext frc = g2.getFontRenderContext();
LineMetrics lm = tickLabelFont.getLineMetrics("ABCxyz", frc);
if (!isVerticalTickLabels()) {
// all tick labels have the same width (equal to the height of the font)...
result += lm.getHeight();
}
else {
// look at lower and upper bounds...
DateRange range = (DateRange) getRange();
Date lower = range.getLowerDate();
Date upper = range.getUpperDate();
String lowerStr = null;
String upperStr = null;
DateFormat formatter = getDateFormatOverride();
if (formatter != null) {
lowerStr = formatter.format(lower);
upperStr = formatter.format(upper);
}
else {
lowerStr = unit.dateToString(lower);
upperStr = unit.dateToString(upper);
}
FontMetrics fm = g2.getFontMetrics(tickLabelFont);
double w1 = fm.stringWidth(lowerStr);
double w2 = fm.stringWidth(upperStr);
result += Math.max(w1, w2);
}
return result;
}
/**
* Calculates the positions of the tick labels for the axis, storing the results in the
* tick label list (ready for drawing).
*
* @param g2 the graphics device.
* @param state the axis state.
* @param plotArea the area in which the plot and the axes should be drawn.
* @param dataArea the area in which the plot should be drawn.
* @param edge the location of the axis.
*
* @return A list of ticks.
*/
public List refreshTicks(Graphics2D g2,
AxisState state,
Rectangle2D plotArea,
Rectangle2D dataArea,
RectangleEdge edge) {
List result = null;
if (RectangleEdge.isTopOrBottom(edge)) {
result = refreshTicksHorizontal(g2, state.getCursor(), plotArea, dataArea, edge);
}
else if (RectangleEdge.isLeftOrRight(edge)) {
result = refreshTicksVertical(g2, state.getCursor(), plotArea, dataArea, edge);
}
return result;
}
/**
* Recalculates the ticks for the date axis.
*
* @param g2 the graphics device.
* @param cursor the cursor location.
* @param plotArea the area in which the axes and data are to be drawn.
* @param dataArea the area in which the data is to be drawn.
* @param edge the location of the axis.
*
* @return A list of ticks.
*/
protected List refreshTicksHorizontal(Graphics2D g2,
double cursor,
Rectangle2D plotArea,
Rectangle2D dataArea,
RectangleEdge edge) {
List result = new java.util.ArrayList();
Font tickLabelFont = getTickLabelFont();
g2.setFont(tickLabelFont);
if (isAutoTickUnitSelection()) {
selectAutoTickUnit(g2, plotArea, dataArea, edge);
}
DateTickUnit unit = getTickUnit();
Date tickDate = calculateLowestVisibleTickValue(unit);
Date upperDate = getMaximumDate();
// float lastX = Float.MIN_VALUE;
while (tickDate.before(upperDate)) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -