1
package figtree.treeviewer.painters;
3
import figtree.treeviewer.ScaleAxis;
4
import figtree.treeviewer.TreePane;
5
import figtree.treeviewer.decorators.Decorator;
6
import figtree.treeviewer.treelayouts.RectilinearTreeLayout;
7
import figtree.treeviewer.treelayouts.RadialTreeLayout;
8
import jebl.evolution.trees.Tree;
9
import jebl.util.Attributable;
10
import jam.controlpalettes.ControlPalette;
13
import java.awt.geom.Line2D;
14
import java.awt.geom.Rectangle2D;
15
import java.util.Collection;
19
* @author Andrew Rambaut
20
* @author Alexei Drummond
21
* @version $Id: ScaleBarPainter.java,v 1.7 2006/11/21 16:10:24 rambaut Exp $
23
public class ScaleAxisPainter extends LabelPainter<TreePane> implements ScalePainter {
24
private double majorTickSpacing = 1.0;
25
private double minorTickSpacing = 0.5;
27
public ScaleAxisPainter() {
30
public void setTreePane(TreePane treePane) {
31
this.treePane = treePane;
34
public void setAutomatic(boolean automatic) {
36
treePane.setAutomaticScale();
37
majorTickSpacing = treePane.getMajorTickSpacing();
38
minorTickSpacing = treePane.getMinorTickSpacing();
40
treePane.setTickSpacing(majorTickSpacing, minorTickSpacing);
45
public void setAxisReversed(final boolean isAxisReversed) {
46
treePane.setAxisReversed(isAxisReversed);
49
public void setAxisSpacing(double majorTickSpacing, double minorTickSpacing) {
50
treePane.setTickSpacing(majorTickSpacing, minorTickSpacing);
53
public double getAxisOrigin() {
57
public void setAxisOrigin(double axisOrigin) {
61
public double getMajorTickSpacing() {
62
return majorTickSpacing;
65
public double getMinorTickSpacing() {
66
return minorTickSpacing;
69
public Rectangle2D calibrate(Graphics2D g2, TreePane treePane) {
70
Font oldFont = g2.getFont();
71
g2.setFont(getFont());
73
FontMetrics fm = g2.getFontMetrics();
74
double labelHeight = fm.getHeight();
76
preferredWidth = treePane.getTreeBounds().getWidth();
77
preferredHeight = labelHeight + topMargin + bottomMargin + scaleBarStroke.getLineWidth() + majorTickSize;
79
if (!(treePane.getTreeLayout() instanceof RectilinearTreeLayout)) {
80
// if the tree layout is not rectilinear, we are not going to display
81
// an axis at the moment so make the height 0.
82
preferredHeight = 0.0;
85
tickLabelOffset = (float) (fm.getAscent() + topMargin + bottomMargin + majorTickSize) + scaleBarStroke.getLineWidth();
89
return new Rectangle2D.Double(0.0, 0.0, preferredWidth, preferredHeight);
92
public void paint(Graphics2D g2, TreePane treePane, Justification justification, Rectangle2D bounds) {
93
Font oldFont = g2.getFont();
94
Paint oldPaint = g2.getPaint();
95
Stroke oldStroke = g2.getStroke();
97
if (TreePane.DEBUG_OUTLINE) {
98
g2.setPaint(Color.red);
102
if (treePane.getTreeLayout() instanceof RadialTreeLayout) {
103
// Unless the layout is the rectilinear or polar one, the grid won't make sense...
107
if (getBackground() != null) {
108
g2.setPaint(getBackground());
112
if (getBorderPaint() != null && getBorderStroke() != null) {
113
g2.setPaint(getBorderPaint());
114
g2.setStroke(getBorderStroke());
118
g2.setFont(getFont());
120
g2.setPaint(getForeground());
121
g2.setStroke(getScaleBarStroke());
123
paintAxis(g2, bounds);
126
g2.setPaint(oldPaint);
127
g2.setStroke(oldStroke);
131
* Get the maximum width of the labels of an axis
135
protected double getMaxTickLabelWidth(Graphics2D g2)
141
ScaleAxis axis = treePane.getScaleAxis();
143
if (axis.getLabelFirst()) { // Draw first minor tick as a major one (with a label)
144
label = axis.getFormatter().format(axis.getMinorTickValue(0, -1));
145
width = g2.getFontMetrics().stringWidth(label);
146
if (maxWidth < width)
149
int n = axis.getMajorTickCount();
150
for (int i = 0; i < n; i++) {
151
label = axis.getFormatter().format(axis.getMajorTickValue(i));
152
width = g2.getFontMetrics().stringWidth(label);
153
if (maxWidth < width)
156
if (axis.getLabelLast()) { // Draw first minor tick as a major one (with a label)
157
label = axis.getFormatter().format(axis.getMinorTickValue(0, n - 1));
158
width = g2.getFontMetrics().stringWidth(label);
159
if (maxWidth < width)
166
protected void paintAxis(Graphics2D g2, Rectangle2D axisBounds)
168
ScaleAxis axis = treePane.getScaleAxis();
170
g2.setPaint(getForeground());
171
g2.setStroke(getScaleBarStroke());
173
double minX = treePane.scaleOnAxis(axis.getMinAxis());
174
double maxX = treePane.scaleOnAxis(axis.getMaxAxis());
176
Line2D line = new Line2D.Double(minX, axisBounds.getMinY(), maxX, axisBounds.getMinY());
179
int n1 = axis.getMajorTickCount();
182
n2 = axis.getMinorTickCount(-1);
183
if (axis.getLabelFirst()) { // Draw first minor tick as a major one (with a label)
185
paintMajorTick(g2, axisBounds, axis, axis.getMinorTickValue(0, -1));
187
for (j = 1; j < n2; j++) {
188
paintMinorTick(g2, axisBounds, axis.getMinorTickValue(j, -1));
192
for (j = 0; j < n2; j++) {
193
paintMinorTick(g2, axisBounds, axis.getMinorTickValue(j, -1));
197
for (i = 0; i < n1; i++) {
199
paintMajorTick(g2, axisBounds, axis, axis.getMajorTickValue(i));
200
n2 = axis.getMinorTickCount(i);
202
if (i == (n1-1) && axis.getLabelLast()) { // Draw last minor tick as a major one
204
paintMajorTick(g2, axisBounds, axis, axis.getMinorTickValue(0, i));
206
for (j = 1; j < n2; j++) {
207
paintMinorTick(g2, axisBounds, axis.getMinorTickValue(j, i));
211
for (j = 0; j < n2; j++) {
212
paintMinorTick(g2, axisBounds, axis.getMinorTickValue(j, i));
218
protected void paintMajorTick(Graphics2D g2, Rectangle2D axisBounds, ScaleAxis axis, double value)
220
g2.setPaint(getForeground());
221
g2.setStroke(getScaleBarStroke());
223
String label = axis.getFormatter().format(value);
224
double pos = treePane.scaleOnAxis(value);
226
Line2D line = new Line2D.Double(pos, axisBounds.getMinY(), pos, axisBounds.getMinY() + majorTickSize);
229
g2.setPaint(getForeground());
230
double width = g2.getFontMetrics().stringWidth(label);
231
g2.drawString(label, (float)(pos - (width / 2)), (float)(axisBounds.getMinY() + tickLabelOffset));
234
protected void paintMinorTick(Graphics2D g2, Rectangle2D axisBounds, double value)
237
g2.setPaint(getForeground());
238
g2.setStroke(getScaleBarStroke());
240
double pos = treePane.scaleOnAxis(value);
242
Line2D line = new Line2D.Double(pos, axisBounds.getMinY(), pos, axisBounds.getMinY() + minorTickSize);
246
public double getPreferredWidth() {
247
return preferredWidth;
250
public double getPreferredHeight() {
251
return preferredHeight;
254
public double getHeightBound() {
255
return preferredHeight + tickLabelOffset;
258
public BasicStroke getScaleBarStroke() {
259
return scaleBarStroke;
262
public void setScaleBarStroke(BasicStroke scaleBarStroke) {
263
this.scaleBarStroke = scaleBarStroke;
264
firePainterChanged();
267
public void setControlPalette(ControlPalette controlPalette) {
271
public String[] getAttributes() {
272
return new String[0];
275
public void setupAttributes(Collection<? extends Tree> trees) {
279
public void setDisplayAttribute(String displayAttribute) {
280
throw new UnsupportedOperationException("setDisplayAttribute not implemented in ScaleAxisPainter");
283
public void setTextDecorator(Decorator textDecorator) {
286
public Set<Attributable> getAttributableItems() {
290
private BasicStroke scaleBarStroke = new BasicStroke(1.0f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL);
292
private double topMargin = 4.0;
293
private double bottomMargin = 4.0;
295
private double majorTickSize = 5.0;
296
private double minorTickSize = 2.0;
297
private double tickLabelOffset = 4.0;
299
private double preferredHeight;
300
private double preferredWidth;
302
protected TreePane treePane;