package jas.plot;
import jas.plot.java2.PlotGraphics12;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Insets;
import java.awt.LayoutManager2;
import java.util.Enumeration;
import java.util.Vector;
import javax.swing.BorderFactory;
import javax.swing.JLabel;
import javax.swing.JPopupMenu;
/**
* Represents a plot legend
*/
public class Legend extends MovableObject
{
private SetablePlotGraphics pg = new PlotGraphics12();
/**
* Create an empty legend
*/
public Legend()
{
super("Legend");
setLayout(new LegendLayout());
setBorder(BorderFactory.createLineBorder(Color.black));
}
/**
* Adds a legend entry to a legend
*/
public void add(final LegendEntry e)
{
super.add(new LegendComponent(e));
EditableLabel label = new EditableLabel(e.getTitle(),"Legend Entry",JLabel.LEFT)
{
protected void fireActionPerformed()
{
super.fireActionPerformed();
if (e instanceof MutableLegendEntry) ((MutableLegendEntry) e).setTitle(getText());
}
};
label.setShowFontMenuItem(false);
super.add(label);
}
/**
* Removes a legend entry from a legend
*/
public void remove(LegendEntry e)
{
int n = getComponentCount();
for (int i=0; i<n ; i++)
{
Component c = getComponent(i);
if (c instanceof LegendComponent &&
((LegendComponent) c).le == e)
{
remove(i);
remove(i); // remove the associated label
return;
}
}
}
/**
* Removes all entries from the legend
*/
public void clear()
{
removeAll();
}
/**
* Return the number of entries in the Legend
*/
public int getNEntries()
{
return getComponentCount()/2;
}
/**
* Return the current title for the legend entry.
* (After any user changes)
*/
public String getCurrentTitle(int index)
{
LegendEntry le = ((LegendComponent) getComponent(2*index)).le;
return le.getTitle();
}
/**
* True if the legend entry has been changed (by the user)
*/
public boolean isTitleChanged(int index)
{
LegendEntry le = ((LegendComponent) getComponent(2*index)).le;
if (le instanceof MutableLegendEntry) return ((MutableLegendEntry) le).titleIsChanged();
return false;
}
/**
* Set a new title for the legend entry
*/
public void setCurrentTitle(int index, String title)
{
LegendEntry le = ((LegendComponent) getComponent(2*index)).le;
if (le instanceof MutableLegendEntry) ((MutableLegendEntry) le).setTitle(title);
}
private class LegendComponent extends Component
{
LegendComponent(LegendEntry e)
{
this.le = e;
}
public void paint(Graphics g)
{
Dimension d = getSize();
pg.setGraphics(g);
le.paintIcon(pg,d.width,d.height);
}
public Dimension getPreferredSize()
{
return preferredIconSize;
}
LegendEntry le;
}
public void modifyPopupMenu(final JPopupMenu menu, final Component source)
{
if (menu.getComponentCount() > 0) menu.addSeparator();
menu.add(new FontMenuItem(this,getPrefix()));
super.modifyPopupMenu(menu,source);
}
public void setFont(Font font)
{
super.setFont(font);
int n = getComponentCount();
for (int i=1; i<n ; i+=2)
{
getComponent(i).setFont(font);
}
}
public void legendTextChanged()
{
int n = getComponentCount();
for (int i=0; i<n ; )
{
LegendComponent c = (LegendComponent) getComponent(i++);
EditableLabel el = (EditableLabel) getComponent(i++);
el.setText(c.le.getTitle());
}
}
private static final Dimension preferredIconSize = new Dimension(15,15);
}
class LegendLayout implements LayoutManager2
{
public void addLayoutComponent(Component c, Object constraints)
{
components.addElement(c);
}
public void removeLayoutComponent(Component c)
{
components.removeElement(c);
}
public void addLayoutComponent(String s, Component c)
{
addLayoutComponent(c,s);
}
public void layoutContainer(Container parent)
{
Dimension parentSize = parent.getSize();
Insets insets = parent.getInsets();
int y = insets.top + pad;
// Lay the components out vertically
Enumeration e = components.elements();
while (e.hasMoreElements())
{
Component icon = (Component) e.nextElement();
Component label = (Component) e.nextElement();
Dimension iconSize = icon.getPreferredSize();
Dimension labelSize = label.getPreferredSize();
icon.setSize(iconSize);
icon.setLocation(insets.left+pad,Math.max(y,y+(labelSize.height-iconSize.height)/2));
label.setSize(parentSize.width - 3*pad - iconSize.width - insets.left - insets.right,labelSize.height);
label.setLocation(insets.left+2*pad+iconSize.width,Math.max(y,y+(iconSize.height-labelSize.height)/2));
y += Math.max(iconSize.height,labelSize.height) + pad;
}
}
public Dimension minimumLayoutSize(Container parent)
{
return preferredLayoutSize(parent);
}
public Dimension maximumLayoutSize(Container parent)
{
return preferredLayoutSize(parent);
}
public Dimension preferredLayoutSize(Container parent)
{
int x = 0;
int y = 0;
Enumeration e = components.elements();
while (e.hasMoreElements())
{
Component icon = (Component) e.nextElement();
Component label = (Component) e.nextElement();
Dimension iconSize = icon.getPreferredSize();
Dimension labelSize = label.getPreferredSize();
x = Math.max(x,iconSize.width + labelSize.width);
y += Math.max(iconSize.height,labelSize.height) + pad;
}
Insets insets = parent.getInsets();
y += 2*pad + insets.top + insets.bottom;
x += 3*pad + insets.left + insets.right;
return new Dimension(x,y);
}
/**
* Returns the alignment along the x axis. This specifies how
* the component would like to be aligned relative to other
* components. The value should be a number between 0 and 1
* where 0 represents alignment along the origin, 1 is aligned
* the furthest away from the origin, 0.5 is centered, etc.
*/
public float getLayoutAlignmentX(Container parent)
{
return 0.5f;
}
/**
* Returns the alignment along the y axis. This specifies how
* the component would like to be aligned relative to other
* components. The value should be a number between 0 and 1
* where 0 represents alignment along the origin, 1 is aligned
* the furthest away from the origin, 0.5 is centered, etc.
*/
public float getLayoutAlignmentY(Container parent)
{
return 0.5f;
}
/**
* Invalidates the layout, indicating that if the layout manager
* has cached information it should be discarded.
*/
public void invalidateLayout(Container target)
{
}
private static final int pad = 3;
private Vector components = new Vector();
}