Those 2 snippets are all you need to add to the DateAxis to remove the last tick (and label) if it would get cut off.
I'm working myself on a modified DateAxis (or ValueAxis) that will allow tickmarks to be drawn even if the ticklabels are not (because they'd overlap for example).
Problem of course is that if the axis gets really dense (minute interval on a year long chart that's only a few hundred pixels wide for example) you'd get the tickmarks themselves too close together or overlapping.
Ideally the axis would allow a setting that would indicate how many tickmarks to draw between each printed ticklabel, but I'm far from achieving that.
To also get rid of first labels that run off the left of the axis, you need to do a bit more.
Code: Select all
private double tickLabelWidth;
private Double previous;
public boolean isHiddenValue(Date time, Rectangle2D area, RectangleEdge edge) {
boolean hidden = !getTimeline().containsDomainValue(time);
if (!hidden) {
double current = valueToJava2D(time.getTime(), area, edge);
if (previous != null) {
if ((current - previous) < tickLabelWidth) {
return true;
}
}
previous = current;
if (current < area.getX()) {
hidden = true;
} else if(current >= area.getMaxX()) {
hidden = true;
}
}
return hidden;
}
protected List refreshTicksHorizontal(Graphics2D g2, Rectangle2D dataArea,
RectangleEdge edge) {
previous = null;
List<Tick> result = new java.util.ArrayList<Tick>();
Font tickLabelFont = getTickLabelFont();
g2.setFont(tickLabelFont);
if (isAutoTickUnitSelection()) {
selectAutoTickUnit(g2, dataArea, edge);
}
Date lowerDate = getMinimumDate();
Date upperDate = getMaximumDate();
lowerDate = forwardToVisibleSectionIfHidden(getTimeline(), lowerDate);
upperDate = forwardToVisibleSectionIfHidden(getTimeline(), upperDate);
selectHorizontalAutoTickUnitEnhanced(g2, dataArea, edge,
lowerDate.getTime(), upperDate.getTime());
DateTickUnit unit = getTickUnit();
// Shift start date to the round units for this type
Date tickDate = alignToUnit(unit, lowerDate);
upperDate = alignToUnit(unit, upperDate);
boolean hiddenValue;
while (!tickDate.after(upperDate)) {
//while (tickDate.before(upperDate)) {
hiddenValue = isHiddenValue(tickDate, dataArea, edge);
if (hiddenValue) {
tickDate = unit.rollDate(tickDate);
tickDate = alignToUnit(unit, tickDate);
} else {
// work out the value, label and position
String tickLabel;
DateFormat formatter = getDateFormatOverride();
if (formatter != null) {
tickLabel = formatter.format(tickDate);
} else {
tickLabel = getTickUnit().dateToString(tickDate);
}
TextAnchor anchor = null;
TextAnchor rotationAnchor = null;
double angle = 0.0;
if (isVerticalTickLabels()) {
anchor = TextAnchor.CENTER_RIGHT;
rotationAnchor = TextAnchor.CENTER_RIGHT;
if (edge == RectangleEdge.TOP) {
angle = Math.PI / 2.0;
} else {
angle = -Math.PI / 2.0;
}
} else {
if (edge == RectangleEdge.TOP) {
anchor = TextAnchor.BOTTOM_CENTER;
rotationAnchor = TextAnchor.BOTTOM_CENTER;
} else {
anchor = TextAnchor.TOP_CENTER;
rotationAnchor = TextAnchor.TOP_CENTER;
}
}
Tick tick = new DateTick(tickDate, tickLabel, anchor,
rotationAnchor, angle);
result.add(tick);
tickDate = unit.addToDate(tickDate);
tickDate = alignToUnit(unit, tickDate);
}
}
if (result.size() >= 1) {
Tick tick = result.get(result.size() - 1);
if (tick instanceof DateTick && isRunsOffScale(g2, (DateTick) tick,
dataArea, edge)) {
result.remove(tick);
}
}
return result;
}
public boolean isRunsOffScale(Graphics2D g, DateTick tick,Rectangle2D dataArea,
RectangleEdge edge) {
double imageWidth = g.getClipBounds().getMaxX();
FontMetrics fm = g.getFontMetrics(g.getFont());
double position = valueToJava2D(tick.getDate().getTime(), dataArea, edge);
// divide stringWidth by 2 becayse valueToJava2D returns the centerpoint
// for the label, not the left edge
double right = position + (fm.stringWidth(tick.getText()) / 2);
boolean result = (right > imageWidth);
return result;
}