/*
* LegendPainter.java
*
* Copyright (C) 2006-2014 Andrew Rambaut
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package figtree.treeviewer.painters;
import figtree.treeviewer.AttributeColourController;
import figtree.treeviewer.TreePane;
import figtree.treeviewer.decorators.*;
import jam.controlpalettes.ControlPalette;
import java.awt.*;
import java.awt.geom.Line2D;
import java.awt.geom.Rectangle2D;
/**
* @author Andrew Rambaut
* @version $Id$
*
* $HeadURL$
*
* $LastChangedBy$
* $LastChangedDate$
* $LastChangedRevision$
*/
public class LegendPainter extends LabelPainter<TreePane> implements ScalePainter {
public final static int CONTINUOUS_LENGTH = 320;
public LegendPainter(AttributeColourController attributeColourController) {
super(null);
this.attributeColourController = attributeColourController;
}
public void setTreePane(TreePane treePane) {
this.treePane = treePane;
}
public Decorator getBorderDecorator() {
return borderDecorator;
}
public void setBorderDecorator(Decorator borderDecorator) {
this.borderDecorator = borderDecorator;
firePainterSettingsChanged();
}
public Decorator getTextDecorator() {
return textDecorator;
}
public void setTextDecorator(Decorator textDecorator) {
this.textDecorator = textDecorator;
firePainterSettingsChanged();
}
public Rectangle2D calibrate(Graphics2D g2, TreePane treePane) {
final Font oldFont = g2.getFont();
if (textDecorator != null) {
g2.setFont(textDecorator.getFont(getFont()));
} else {
g2.setFont(getFont());
}
FontMetrics fm = g2.getFontMetrics();
preferredHeight = fm.getHeight();
preferredWidth = 0;
if (colourDecorator instanceof DiscreteColourDecorator) {
for (Object value : ((DiscreteColourDecorator)colourDecorator).getValues()) {
Rectangle2D rect = fm.getStringBounds(value.toString(), g2);
if (rect.getWidth() > preferredWidth) {
preferredWidth = rect.getWidth();
}
}
} else if (colourDecorator instanceof ContinuousColourDecorator){
// draw a continuous legend
ContinuousScale scale = ((ContinuousColourDecorator)colourDecorator).getContinuousScale();
double min = scale.getMinValue();
double max = scale.getMaxValue();
Rectangle2D rect = g2.getFontMetrics().getStringBounds(getNumberFormat().format(max), g2);
if (rect.getWidth() > preferredWidth) {
preferredWidth = rect.getWidth();
}
rect = g2.getFontMetrics().getStringBounds(getNumberFormat().format(min), g2);
if (rect.getWidth() > preferredWidth) {
preferredWidth = rect.getWidth();
}
} else if (colourDecorator != null) {
throw new IllegalArgumentException("Unrecognized ColourDecorator class");
}
g2.setFont(oldFont);
preferredWidth += insets.left + insets.right + fm.getHeight() * 2;
return new Rectangle2D.Double(0.0, 0.0, preferredWidth, preferredHeight);
}
public void paint(Graphics2D g2, TreePane treePane, Justification justification, Rectangle2D bounds) {
if (colourDecorator == null) {
return;
}
String attribute = colourDecorator.getAttributeName();
if (TreePane.DEBUG_OUTLINE) {
g2.setPaint(Color.red);
g2.draw(bounds);
}
Font oldFont = g2.getFont();
Paint oldPaint = g2.getPaint();
Stroke oldStroke = g2.getStroke();
if (getBackground() != null) {
g2.setPaint(getBackground());
g2.fill(bounds);
}
if (getBorderPaint() != null && getBorderStroke() != null) {
g2.setPaint(getBorderPaint());
g2.setStroke(getBorderStroke());
g2.draw(bounds);
}
g2.setFont(getFont());
Rectangle2D labelBounds = g2.getFontMetrics().getStringBounds("ty", g2);
// vertical inset
float y = (float)(insets.top);
float yOffset = (float)g2.getFontMetrics().getAscent();
float xOffset1 = (float)(insets.left);
float yDelta = (float)labelBounds.getHeight() * 1.5F;
float xOffset2 = (float)(insets.left + labelBounds.getHeight() * 2);
g2.setPaint(Color.BLACK);
g2.drawString(attribute, xOffset1, y + yOffset);
y += yDelta;
if (colourDecorator instanceof DiscreteColourDecorator) {
for (Object value : ((DiscreteColourDecorator)colourDecorator).getValues()) {
g2.setPaint(((DiscreteColourDecorator)colourDecorator).getColor(value));
Rectangle2D rect = new Rectangle2D.Double(xOffset1, y, labelBounds.getHeight(), labelBounds.getHeight());
g2.fill(rect);
g2.drawString(value.toString(), xOffset2, y + yOffset);
y += yDelta;
}
} else if (colourDecorator instanceof ContinuousColourDecorator){
// draw a continuous legend
ContinuousScale scale = ((ContinuousColourDecorator)colourDecorator).getContinuousScale();
double min = scale.getMinValue();
double max = scale.getMaxValue();
double delta = (max - min) / CONTINUOUS_LENGTH;
final String label = "0.0";
labelBounds = g2.getFontMetrics().getStringBounds(label, g2);
float y0 = y;
double v = max;
for (int i = 0; i < CONTINUOUS_LENGTH; i++) {
g2.setPaint(((ContinuousColourDecorator)colourDecorator).getColourForValue(v));
Rectangle2D rect = new Rectangle2D.Double(xOffset1, y, labelBounds.getHeight(), 1);
g2.fill(rect);
y += 1;
v -= delta;
}
g2.setPaint(Color.BLACK);
g2.drawString(getNumberFormat().format(max), xOffset2, y0 + (yOffset / 2));
g2.drawString(getNumberFormat().format(min), xOffset2, y + (yOffset / 2));
Line2D line = new Line2D.Double(xOffset1, y0, xOffset1 + labelBounds.getHeight() * 1.25, y0);
g2.draw(line);
line = new Line2D.Double(xOffset1, y, xOffset1 + labelBounds.getHeight() * 1.25, y);
g2.draw(line);
line = new Line2D.Double(xOffset1, y0, xOffset1, y);
g2.draw(line);
} else {
throw new IllegalArgumentException("Unrecognized ColourDecorator class");
}
g2.setFont(oldFont);
g2.setPaint(oldPaint);
g2.setStroke(oldStroke);
}
public double getPreferredWidth() {
return preferredWidth;
}
public double getPreferredHeight() {
return preferredHeight;
}
public double getHeightBound() {
return preferredHeight;
}
public void setColourDecorator(ColourDecorator colourDecorator) {
this.colourDecorator = colourDecorator;
firePainterChanged();
}
public void setControlPalette(ControlPalette controlPalette) {
// nothing to do
}
protected ColourDecorator colourDecorator;
private double preferredHeight;
private double preferredWidth;
protected final AttributeColourController attributeColourController;
protected TreePane treePane;
private Decorator textDecorator = null;
private Decorator borderDecorator = null;
private Insets insets = new Insets(8, 8, 8, 8);
@Override
public String getDisplayAttribute() {
throw new UnsupportedOperationException("getDisplayAttribute not implmented");
}
@Override
public void setDisplayAttribute(String displayAttribute) {
throw new UnsupportedOperationException("setDisplayAttribute not implmented - use setColourDecorator directly");
}
}