setTickLabelFont(Comparable category, Font font)
setTickLabelPaint(Comparable category, Paint paint)
If no font or paint is found for the category, the default font/paint is used.
The methods overwritten are an exact copy of the implementation in CategoryAxis with the required changes. I had to implement the category tool tip code again because the categoryToolTips Collection object is not accessible ( no get/set ) in CategoryAxis.
Maybe this code can be incorporated into CategoryAxis code for a future release.
Code: Select all
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.Shape;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.jfree.chart.entity.EntityCollection;
import org.jfree.chart.entity.TickLabelEntity;
import org.jfree.chart.event.AxisChangeEvent;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.plot.Plot;
import org.jfree.chart.plot.PlotRenderingInfo;
import org.jfree.text.G2TextMeasurer;
import org.jfree.text.TextBlock;
import org.jfree.text.TextUtilities;
import org.jfree.ui.RectangleAnchor;
import org.jfree.ui.RectangleEdge;
import org.jfree.ui.Size2D;
import org.jfree.util.Log;
import org.jfree.util.LogContext;
import org.jfree.util.ObjectUtilities;
import org.jfree.util.ShapeUtilities;
import org.jfree.chart.axis.*;
import java.awt.*;
/**
* An axis that displays categories.
*/
public class NewCategoryAxis extends CategoryAxis {
/** Storage for the category label tooltips (if any). */
private Map categoryLabelToolTips = new HashMap();
/**
* Creates a new category axis with no label.
*/
public NewCategoryAxis() {
this(null);
}
/**
* Constructs a category axis, using default values where necessary.
*
* @param label the axis label (<code>null</code> permitted).
*/
public NewCategoryAxis(String label) {
super(label);
}
/**
* Adds a tooltip to the specified category and sends an
* {@link AxisChangeEvent} to all registered listeners.
*
* @param category the category (<code>null<code> not permitted).
* @param tooltip the tooltip text (<code>null</code> permitted).
*/
public void addCategoryLabelToolTip(Comparable category, String tooltip) {
if (category == null) {
throw new IllegalArgumentException("Null 'category' argument.");
}
this.categoryLabelToolTips.put(category, tooltip);
notifyListeners(new AxisChangeEvent(this));
}
/**
* Removes the tooltip for the specified category and sends an
* {@link AxisChangeEvent} to all registered listeners.
*
* @param category the category (<code>null<code> not permitted).
*/
public void removeCategoryLabelToolTip(Comparable category) {
if (category == null) {
throw new IllegalArgumentException("Null 'category' argument.");
}
this.categoryLabelToolTips.remove(category);
notifyListeners(new AxisChangeEvent(this));
}
/**
* Clears the category label tooltips and sends an {@link AxisChangeEvent}
* to all registered listeners.
*/
public void clearCategoryLabelToolTips() {
this.categoryLabelToolTips.clear();
notifyListeners(new AxisChangeEvent(this));
}
/**
* Draws the category labels and returns the updated axis state.
*
* @param g2 the graphics device (<code>null</code> not permitted).
* @param plotArea the plot area (<code>null</code> not permitted).
* @param dataArea the area inside the axes (<code>null</code> not
* permitted).
* @param edge the axis location (<code>null</code> not permitted).
* @param state the axis state (<code>null</code> not permitted).
* @param plotState collects information about the plot (<code>null</code>
* permitted).
*
* @return The updated axis state (never <code>null</code>).
*/
protected AxisState drawCategoryLabels(Graphics2D g2,
Rectangle2D plotArea,
Rectangle2D dataArea,
RectangleEdge edge,
AxisState state,
PlotRenderingInfo plotState) {
if (logger.isDebugEnabled()) {
logger.debug(
"Entering drawCategoryLabels() method, cursor = "
+ state.getCursor()
);
}
if (state == null) {
throw new IllegalArgumentException("Null 'state' argument.");
}
if (isTickLabelsVisible()) {
// g2.setFont(getTickLabelFont());
// g2.setPaint(getTickLabelPaint());
List ticks = refreshTicks(g2, state, plotArea, dataArea, edge);
state.setTicks(ticks);
int categoryIndex = 0;
Iterator iterator = ticks.iterator();
while (iterator.hasNext()) {
CategoryTick tick = (CategoryTick) iterator.next();
// g2.setPaint(getTickLabelPaint());
g2.setFont(getTickLabelFont(tick.getCategory()));
g2.setPaint(getTickLabelPaint(tick.getCategory()));
CategoryLabelPosition position
= this.getCategoryLabelPositions().getLabelPosition(edge);
double x0 = 0.0;
double x1 = 0.0;
double y0 = 0.0;
double y1 = 0.0;
if (edge == RectangleEdge.TOP) {
x0 = getCategoryStart(
categoryIndex, ticks.size(), dataArea, edge
);
x1 = getCategoryEnd(
categoryIndex, ticks.size(), dataArea, edge
);
y1 = state.getCursor() - this.getCategoryLabelPositionOffset();
y0 = y1 - state.getMax();
}
else if (edge == RectangleEdge.BOTTOM) {
x0 = getCategoryStart(
categoryIndex, ticks.size(), dataArea, edge
);
x1 = getCategoryEnd(
categoryIndex, ticks.size(), dataArea, edge
);
y0 = state.getCursor() + this.getCategoryLabelPositionOffset();
y1 = y0 + state.getMax();
}
else if (edge == RectangleEdge.LEFT) {
y0 = getCategoryStart(
categoryIndex, ticks.size(), dataArea, edge
);
y1 = getCategoryEnd(
categoryIndex, ticks.size(), dataArea, edge
);
x1 = state.getCursor() - this.getCategoryLabelPositionOffset();
x0 = x1 - state.getMax();
}
else if (edge == RectangleEdge.RIGHT) {
y0 = getCategoryStart(
categoryIndex, ticks.size(), dataArea, edge
);
y1 = getCategoryEnd(
categoryIndex, ticks.size(), dataArea, edge
);
x0 = state.getCursor() + this.getCategoryLabelPositionOffset();
x1 = x0 - state.getMax();
}
Rectangle2D area = new Rectangle2D.Double(
x0, y0, (x1 - x0), (y1 - y0)
);
Point2D anchorPoint = RectangleAnchor.coordinates(
area, position.getCategoryAnchor()
);
TextBlock block = tick.getLabel();
block.draw(
g2,
(float) anchorPoint.getX(), (float) anchorPoint.getY(),
position.getLabelAnchor(),
(float) anchorPoint.getX(), (float) anchorPoint.getY(),
position.getAngle()
);
Shape bounds = block.calculateBounds(
g2, (float) anchorPoint.getX(), (float) anchorPoint.getY(),
position.getLabelAnchor(),
(float) anchorPoint.getX(), (float) anchorPoint.getY(),
position.getAngle()
);
if (plotState != null) {
EntityCollection entities
= plotState.getOwner().getEntityCollection();
if (entities != null) {
String tooltip
= (String) this.categoryLabelToolTips.get(
tick.getCategory()
);
entities.add(
new TickLabelEntity(bounds, tooltip, null)
);
}
}
categoryIndex++;
}
if (edge.equals(RectangleEdge.TOP)) {
double h = state.getMax();
state.cursorUp(h);
}
else if (edge.equals(RectangleEdge.BOTTOM)) {
double h = state.getMax();
state.cursorDown(h);
}
else if (edge == RectangleEdge.LEFT) {
double w = state.getMax();
state.cursorLeft(w);
}
else if (edge == RectangleEdge.RIGHT) {
double w = state.getMax();
state.cursorRight(w);
}
}
return state;
}
/**
* Creates a temporary list of ticks that can be used when drawing the axis.
*
* @param g2 the graphics device (used to get font measurements).
* @param state the axis state.
* @param plotArea the area where the plot and axes will be drawn.
* @param dataArea the area inside the axes.
* @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 ticks = new java.util.ArrayList();
// sanity check for data area...
if (dataArea.getHeight() <= 0.0 || dataArea.getWidth() < 0.0) {
return ticks;
}
CategoryPlot plot = (CategoryPlot) getPlot();
List categories = plot.getCategories();
double max = 0.0;
if (categories != null) {
CategoryLabelPosition position
= this.getCategoryLabelPositions().getLabelPosition(edge);
float r = this.getMaximumCategoryLabelWidthRatio();
if (r <= 0.0) {
r = position.getWidthRatio();
}
float l = 0.0f;
if (position.getWidthType() == CategoryLabelWidthType.CATEGORY) {
l = (float) calculateCategorySize(
categories.size(), plotArea, edge
);
}
else {
if (RectangleEdge.isLeftOrRight(edge)) {
l = (float) plotArea.getWidth();
}
else {
l = (float) plotArea.getHeight();
}
}
int categoryIndex = 0;
Iterator iterator = categories.iterator();
while (iterator.hasNext()) {
Comparable category = (Comparable) iterator.next();
TextBlock label = createLabel(category, l * r, edge, g2);
g2.setFont(getTickLabelFont(category));
g2.setPaint(getTickLabelPaint(category));
if (edge == RectangleEdge.TOP || edge == RectangleEdge.BOTTOM) {
max = Math.max(
max, calculateTextBlockHeight(label, position, g2)
);
}
else if (edge == RectangleEdge.LEFT
|| edge == RectangleEdge.RIGHT) {
max = Math.max(
max, calculateTextBlockWidth(label, position, g2)
);
}
Tick tick = new CategoryTick(
category, label,
position.getLabelAnchor(), position.getRotationAnchor(),
position.getAngle()
);
ticks.add(tick);
categoryIndex = categoryIndex + 1;
}
}
state.setMax(max);
return ticks;
}
/**
* Creates a label.
*
* @param category the category.
* @param width the available width.
* @param edge the edge on which the axis appears.
* @param g2 the graphics device.
*
* @return A label.
*/
protected TextBlock createLabel(Comparable category, float width,
RectangleEdge edge, Graphics2D g2) {
TextBlock label = TextUtilities.createTextBlock(
category.toString(), getTickLabelFont(category), getTickLabelPaint(category),
width, this.getMaximumCategoryLabelLines(), new G2TextMeasurer(g2)
);
return label;
}
private Map tickLabelFonts;
public void setTickLabelFont(Comparable category, Font font) {
if ( tickLabelFonts == null )
tickLabelFonts = new HashMap();
tickLabelFonts.put(category, font);
}
public Font getTickLabelFont(Comparable category) {
if ( tickLabelFonts == null )
return getTickLabelFont();
Font font = (Font)tickLabelFonts.get(category);
return font != null?font:getTickLabelFont();
}
private Map tickLabelColors;
public void setTickLabelPaint(Comparable category, Color color) {
if ( tickLabelColors == null )
tickLabelColors = new HashMap();
tickLabelColors.put(category, color);
}
public Paint getTickLabelPaint(Comparable category) {
if ( tickLabelColors == null )
return getTickLabelPaint();
Paint paint = (Paint)tickLabelColors.get(category);
return paint != null?paint:getTickLabelPaint();
}
}