📄 dateaxis.java
字号:
calendar.set(years, months, days, value, minutes, seconds); return calendar.getTime(); case (DateTickUnit.DAY) : years = calendar.get(Calendar.YEAR); months = calendar.get(Calendar.MONTH); if (this.tickMarkPosition == DateTickMarkPosition.START) { hours = 0; minutes = 0; seconds = 0; } else if (this.tickMarkPosition == DateTickMarkPosition.MIDDLE) { hours = 12; minutes = 0; seconds = 0; } else { hours = 23; minutes = 59; seconds = 59; } calendar.clear(Calendar.MILLISECOND); calendar.set(years, months, value, hours, 0, 0); long result = calendar.getTime().getTime(); if (result > date.getTime()) { calendar.set(years, months, value - 1, hours, 0, 0); } return calendar.getTime(); case (DateTickUnit.MONTH) : years = calendar.get(Calendar.YEAR); calendar.clear(Calendar.MILLISECOND); calendar.set(years, value, 1, 0, 0, 0); Month month = new Month(calendar.getTime()); Date standardDate = calculateDateForPosition(month, this.tickMarkPosition); long millis = standardDate.getTime(); if (millis > date.getTime()) { month = (Month) month.previous(); standardDate = calculateDateForPosition(month, this.tickMarkPosition); } return standardDate; case(DateTickUnit.YEAR) : if (this.tickMarkPosition == DateTickMarkPosition.START) { months = 0; } else if (this.tickMarkPosition == DateTickMarkPosition.MIDDLE) { months = 6; } else { months = 12; } calendar.clear(Calendar.MILLISECOND); calendar.set(value, months, 1, 0, 0, 0); return calendar.getTime(); default: return null; } } /** * Returns a {@link java.util.Date} corresponding to the specified position within a * {@link RegularTimePeriod}. * * @param period the period. * @param position the position (<code>null</code> not permitted). * * @return A date. */ private Date calculateDateForPosition(RegularTimePeriod period, DateTickMarkPosition position) { if (position == null) { throw new IllegalArgumentException("Null 'position' argument."); } Date result = null; if (position == DateTickMarkPosition.START) { result = new Date(period.getFirstMillisecond()); } else if (position == DateTickMarkPosition.MIDDLE) { result = new Date(period.getMiddleMillisecond()); } else if (position == DateTickMarkPosition.END) { result = new Date(period.getLastMillisecond()); } return result; } /** * Returns the first "standard" date (based on the specified field and units). * * @param date the reference date. * @param unit the date tick unit. * * @return the next "standard" date. */ protected Date nextStandardDate(Date date, DateTickUnit unit) { Date previous = previousStandardDate(date, unit); Calendar calendar = Calendar.getInstance(); calendar.setTime(previous); calendar.add(unit.getCalendarField(), unit.getCount()); return calendar.getTime(); } /** * Returns a collection of standard date tick units that uses the default time zone. * This collection will be used by default, but you are free to create your own collection if * you want to (see the setStandardTickUnits() method inherited from the ValueAxis class). * * @return A collection of standard date tick units. */ public static TickUnitSource createStandardDateTickUnits() { return createStandardDateTickUnits(TimeZone.getDefault()); } /** * Returns a collection of standard date tick units. This collection will be used by default, * but you are free to create your own collection if you want to (see the * setStandardTickUnits(...) method inherited from the ValueAxis class). * * @param zone the time zone. * * @return A collection of standard date tick units. */ public static TickUnitSource createStandardDateTickUnits(TimeZone zone) { TickUnits units = new TickUnits(); // date formatters DateFormat f1 = new SimpleDateFormat("HH:mm:ss.SSS"); DateFormat f2 = new SimpleDateFormat("HH:mm:ss"); DateFormat f3 = new SimpleDateFormat("HH:mm"); DateFormat f4 = new SimpleDateFormat("d-MMM, HH:mm"); DateFormat f5 = new SimpleDateFormat("d-MMM"); DateFormat f6 = new SimpleDateFormat("MMM-yyyy"); DateFormat f7 = new SimpleDateFormat("yyyy"); f1.setTimeZone(zone); f2.setTimeZone(zone); f3.setTimeZone(zone); f4.setTimeZone(zone); f5.setTimeZone(zone); f6.setTimeZone(zone); f7.setTimeZone(zone); // milliseconds units.add(new DateTickUnit(DateTickUnit.MILLISECOND, 1, f1)); units.add(new DateTickUnit(DateTickUnit.MILLISECOND, 5, DateTickUnit.MILLISECOND, 1, f1)); units.add(new DateTickUnit(DateTickUnit.MILLISECOND, 10, DateTickUnit.MILLISECOND, 1, f1)); units.add(new DateTickUnit(DateTickUnit.MILLISECOND, 25, DateTickUnit.MILLISECOND, 5, f1)); units.add(new DateTickUnit(DateTickUnit.MILLISECOND, 50, DateTickUnit.MILLISECOND, 10, f1)); units.add( new DateTickUnit(DateTickUnit.MILLISECOND, 100, DateTickUnit.MILLISECOND, 10, f1) ); units.add( new DateTickUnit(DateTickUnit.MILLISECOND, 250, DateTickUnit.MILLISECOND, 10, f1) ); units.add( new DateTickUnit(DateTickUnit.MILLISECOND, 500, DateTickUnit.MILLISECOND, 50, f1) ); // seconds units.add(new DateTickUnit(DateTickUnit.SECOND, 1, DateTickUnit.MILLISECOND, 50, f2)); units.add(new DateTickUnit(DateTickUnit.SECOND, 5, DateTickUnit.SECOND, 1, f2)); units.add(new DateTickUnit(DateTickUnit.SECOND, 10, DateTickUnit.SECOND, 1, f2)); units.add(new DateTickUnit(DateTickUnit.SECOND, 30, DateTickUnit.SECOND, 5, f2)); // minutes units.add(new DateTickUnit(DateTickUnit.MINUTE, 1, DateTickUnit.SECOND, 5, f3)); units.add(new DateTickUnit(DateTickUnit.MINUTE, 2, DateTickUnit.SECOND, 10, f3)); units.add(new DateTickUnit(DateTickUnit.MINUTE, 5, DateTickUnit.MINUTE, 1, f3)); units.add(new DateTickUnit(DateTickUnit.MINUTE, 10, DateTickUnit.MINUTE, 1, f3)); units.add(new DateTickUnit(DateTickUnit.MINUTE, 15, DateTickUnit.MINUTE, 5, f3)); units.add(new DateTickUnit(DateTickUnit.MINUTE, 20, DateTickUnit.MINUTE, 5, f3)); units.add(new DateTickUnit(DateTickUnit.MINUTE, 30, DateTickUnit.MINUTE, 5, f3)); // hours units.add(new DateTickUnit(DateTickUnit.HOUR, 1, DateTickUnit.MINUTE, 5, f3)); units.add(new DateTickUnit(DateTickUnit.HOUR, 2, DateTickUnit.MINUTE, 10, f3)); units.add(new DateTickUnit(DateTickUnit.HOUR, 4, DateTickUnit.MINUTE, 30, f3)); units.add(new DateTickUnit(DateTickUnit.HOUR, 6, DateTickUnit.HOUR, 1, f3)); units.add(new DateTickUnit(DateTickUnit.HOUR, 12, DateTickUnit.HOUR, 1, f4)); // days units.add(new DateTickUnit(DateTickUnit.DAY, 1, DateTickUnit.HOUR, 1, f5)); units.add(new DateTickUnit(DateTickUnit.DAY, 2, DateTickUnit.HOUR, 1, f5)); units.add(new DateTickUnit(DateTickUnit.DAY, 7, DateTickUnit.DAY, 1, f5)); units.add(new DateTickUnit(DateTickUnit.DAY, 15, DateTickUnit.DAY, 1, f5)); // months units.add(new DateTickUnit(DateTickUnit.MONTH, 1, DateTickUnit.DAY, 1, f6)); units.add(new DateTickUnit(DateTickUnit.MONTH, 2, DateTickUnit.DAY, 1, f6)); units.add(new DateTickUnit(DateTickUnit.MONTH, 3, DateTickUnit.MONTH, 1, f6)); units.add(new DateTickUnit(DateTickUnit.MONTH, 4, DateTickUnit.MONTH, 1, f6)); units.add(new DateTickUnit(DateTickUnit.MONTH, 6, DateTickUnit.MONTH, 1, f6)); // years 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); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -