This repository has been archived by the owner on Mar 22, 2024. It is now read-only.
/
BasicMultiLineXYTextAnnotation.java
166 lines (139 loc) · 5.88 KB
/
BasicMultiLineXYTextAnnotation.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
package hep.aida.jfree.annotations;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;
import javax.swing.border.Border;
import org.jfree.chart.annotations.XYTextAnnotation;
import org.jfree.ui.TextAnchor;
import org.jfree.chart.axis.ValueAxis;
import org.jfree.chart.plot.Plot;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.PlotRenderingInfo;
import org.jfree.chart.plot.XYPlot;
import org.jfree.ui.RectangleEdge;
/**
* Basic multi-line text annotation for XYPlot.
*
* Currently does NOT support any of the following:
*
* -rotation
* -multiple fonts
* -TextAnchor settings
* -tooltips
*
* @author Jeremy McCormick <jeremym@slac.stanford.edu>
*/
public class BasicMultiLineXYTextAnnotation extends XYTextAnnotation {
List<String> lines = new ArrayList<String>();
boolean fontMetricsCalculated = false;
int lineHeight;
int lineSpacing;
int width;
int height;
int paddingLeft;
int paddingRight;
int paddingBottom;
Border border;
public BasicMultiLineXYTextAnnotation(String text, double x, double y) {
super(text, x, y);
splitLines(text);
}
private void splitLines(String text) {
StringTokenizer st = new StringTokenizer(text, "\n");
while (st.hasMoreTokens()) {
lines.add(st.nextToken());
}
}
public void setFont(Font font) {
super.setFont(font);
fontMetricsCalculated = false;
}
public void setBorder(Border border) {
this.border = border;
}
public void setLineSpacing(int lineSpacing) {
this.lineSpacing = lineSpacing;
}
private void calculateFontMetrics(Graphics2D graphics) {
if (!fontMetricsCalculated) {
FontMetrics metrics = graphics.getFontMetrics(this.getFont());
lineHeight = metrics.getHeight();
for (String line : lines) {
int lineWidth = metrics.stringWidth(line);
if (lineWidth > width) {
width = lineWidth;
}
}
paddingLeft = metrics.charWidth(' ');
paddingRight = metrics.charWidth(' ');
paddingBottom = metrics.charWidth(' ');
width += (paddingLeft + paddingRight);
height = (lineHeight * lines.size()) + paddingBottom;
fontMetricsCalculated = true;
}
}
public void addLine(String line) {
lines.add(line);
}
public void draw(Graphics2D g2, XYPlot plot, Rectangle2D dataArea,
ValueAxis domainAxis, ValueAxis rangeAxis,
int rendererIndex,
PlotRenderingInfo info) {
calculateFontMetrics(g2);
PlotOrientation orientation = plot.getOrientation();
RectangleEdge domainEdge = Plot.resolveDomainAxisLocation(
plot.getDomainAxisLocation(), orientation);
RectangleEdge rangeEdge = Plot.resolveRangeAxisLocation(
plot.getRangeAxisLocation(), orientation);
float textAnchorX = (float) domainAxis.valueToJava2D(
this.getX(), dataArea, domainEdge);
float textAnchorY = (float) rangeAxis.valueToJava2D(
this.getY(), dataArea, rangeEdge);
if (orientation == PlotOrientation.HORIZONTAL) {
float tempAnchor = textAnchorX;
textAnchorX = textAnchorY;
textAnchorY = tempAnchor;
}
// Now include the TextAnchor. The default calculations are meant for TOP_LEFT
final TextAnchor textAnchor = getTextAnchor();
// first the horizontal alignment
if (textAnchor.equals(TextAnchor.TOP_RIGHT) || textAnchor.equals(TextAnchor.BASELINE_RIGHT) || textAnchor.equals(TextAnchor.BOTTOM_RIGHT)
|| textAnchor.equals(TextAnchor.HALF_ASCENT_RIGHT) || textAnchor.equals(TextAnchor.CENTER_RIGHT)) {
textAnchorX -= width;
} else if (textAnchor.equals(TextAnchor.TOP_CENTER) || textAnchor.equals(TextAnchor.BASELINE_CENTER) || textAnchor.equals(TextAnchor.BOTTOM_CENTER)
|| textAnchor.equals(TextAnchor.HALF_ASCENT_CENTER) || textAnchor.equals(TextAnchor.CENTER)) {
textAnchorX -= width/2;
}
// and the vertical alignment
if (textAnchor.equals(TextAnchor.BOTTOM_RIGHT) || textAnchor.equals(TextAnchor.BOTTOM_CENTER) || textAnchor.equals(TextAnchor.BOTTOM_LEFT)
|| textAnchor.equals(TextAnchor.BASELINE_RIGHT) || textAnchor.equals(TextAnchor.BASELINE_CENTER) || textAnchor.equals(TextAnchor.BASELINE_LEFT)) {
textAnchorY -= height;
} else if (textAnchor.equals(TextAnchor.HALF_ASCENT_RIGHT) || textAnchor.equals(TextAnchor.HALF_ASCENT_CENTER) || textAnchor.equals(TextAnchor.HALF_ASCENT_LEFT)
|| textAnchor.equals(TextAnchor.CENTER_RIGHT) || textAnchor.equals(TextAnchor.CENTER) || textAnchor.equals(TextAnchor.CENTER_LEFT)) {
textAnchorY -= height/2;
}
float rectangleX = textAnchorX;
float rectangleY = textAnchorY;
textAnchorX += paddingLeft;
// Draw outline box.
Rectangle2D rectangle = new Rectangle2D.Float(rectangleX, rectangleY, width, height);
if (this.isOutlineVisible()) {
g2.setStroke(this.getOutlineStroke());
//g2.setPaint(this.getBackgroundPaint());
g2.setPaint(this.getOutlinePaint());
g2.draw(rectangle);
}
// Draw text lines.
g2.setFont(getFont());
g2.setPaint(getPaint());
textAnchorY += lineHeight;
for (String line : lines) {
g2.drawString(line, textAnchorX, textAnchorY);
textAnchorY += lineHeight;
}
}
}