/*
* @(#)AttributeFigure.java
*
* Project: JHotdraw - a GUI framework for technical drawings
* http://www.jhotdraw.org
* http://jhotdraw.sourceforge.net
* Copyright: ?by the original author(s) and all contributors
* License: Lesser GNU Public License (LGPL)
* http://www.opensource.org/licenses/lgpl-license.html
*/
package research;
import research.store.StorableOutput;
import research.store.StorableInput;
import java.awt.*;
import java.io.*;
import java.beans.PropertyChangeListener;
import javax.swing.event.SwingPropertyChangeSupport;
/**
* A figure that can keep track of an open ended set of attributes.
* The attributes are stored in a dictionary implemented by
* FigureAttributes.
*
* @see Figure
* @see Handle
* @see FigureAttributeMap
*
* @version <$CURRENT_VERSION$>
*/
public abstract class AttributeFigure implements Figure {
/**
* The attributes of a figure. Each figure can have
* an open ended set of attributes. Attributes are
* identified by name.
* @see #getAttribute
* @see #setAttribute
*/
private FigureAttributeMap fAttributes = null;
/**
* The default attributes associated with a figure.
* If a figure doesn't have an attribute set, a default
* value from this shared attribute set is returned.
* @see #getAttribute
* @see #setAttribute
*/
private final static FigureAttributeMap fgDefaultAttributes = new DefaultFigureAttributeMap();
protected SwingPropertyChangeSupport changeSupport;
/*
* Serialization support.
*/
private static final long serialVersionUID = -10857585979273442L;
private int attributeFigureSerializedDataVersion = 1;
/**
* Gets a the default value for a named attribute
* @see #getAttribute
*/
public static Object getDefaultAttribute(String name) {
return fgDefaultAttributes.get(name);
}
/**
* Returns the named attribute or null if a
* a figure doesn't have an attribute.
* All figures support the attribute names
* FillColor and FrameColor
*/
public Object getAttribute(String name) {
if (name.equals("fontName")) {
Font font = (Font) getAttribute("font");
return font.getName();
} else if (name.equals("fontStyle")) {
Font font = (Font) getAttribute("font");
return new Integer(font.getStyle());
} else if (name.equals("fontSize")) {
Font font = (Font) getAttribute("font");
return new Integer(font.getSize());
}
if (fAttributes != null) {
Object rv = fAttributes.get(name);
if (rv != null) {
return rv;
}
}
return getDefaultAttribute(name);
}
/**
* Sets the named attribute to the new value
*/
public abstract void setAttribute(String name, Object value);
protected void _setAttribute(String name, Object value) {
FigureAttributeDefinition fad = FigureAttributeDefinition.getInstance();
FigureAttribute fa = fad.get(name);
if (fa != null) {
if (fa.getAccessRule() == FigureAttribute.READ_ONLY) {
throw new RuntimeException("Access rule denied for setting attribure " + fa + ".");
}
if (!fa.getType().isInstance(value)) {
throw new IllegalArgumentException(value.getClass() + ":" + value + " is not a instance of " + fa.getType() + ".");
}
if (!fa.isValidValue(value)) {
throw new RuntimeException("not a valid value for attribute " + fa + ".");
}
}
if (name.equals("fontName")) {
Font font = (Font) getAttribute("font");
Font newFont = new Font((String) name, font.getStyle(), font.getSize());
setAttribute("font", newFont);
return;
} else if (name.equals("fontStyle")) {
Font font = (Font) getAttribute("font");
Font newFont = new Font(font.getName(), ((Integer) value).intValue(), font.getSize());
setAttribute("font", newFont);
return;
} else if (name.equals("fontSize")) {
Font font = (Font) getAttribute("font");
Font newFont = new Font(font.getName(), font.getStyle(), ((Integer) value).intValue());
setAttribute("font", newFont);
return;
}
Object oldValue = getAttribute(name);
if (fAttributes == null)
fAttributes = new FigureAttributeMap();
fAttributes.set(name, value);
Object newValue = getAttribute(name);
firePropertyChange(name, oldValue, newValue);
}
public synchronized void addAttributeChangeListener(PropertyChangeListener listener) {
if (changeSupport == null) {
changeSupport = new SwingPropertyChangeSupport(this);
}
changeSupport.addPropertyChangeListener(listener);
}
public synchronized void removeAttributeChangeListener(PropertyChangeListener listener) {
if (changeSupport == null) {
return;
}
changeSupport.removePropertyChangeListener(listener);
}
public synchronized void addAttributeChangeListener(String propertyName, PropertyChangeListener listener) {
if (changeSupport == null) {
changeSupport = new SwingPropertyChangeSupport(this);
}
changeSupport.addPropertyChangeListener(propertyName, listener);
}
public synchronized void removeAttributeChangeListener(String propertyName, PropertyChangeListener listener) {
if (changeSupport == null) {
return;
}
changeSupport.removePropertyChangeListener(propertyName, listener);
}
protected void firePropertyChange(String propertyName, Object oldValue, Object newValue) {
if (changeSupport == null || oldValue == newValue) {
return;
}
if (oldValue != null && newValue != null && oldValue.equals(newValue)) {
return;
}
changeSupport.firePropertyChange(propertyName, oldValue, newValue);
}
/**
* Stores the Figure to a StorableOutput.
*/
public void write(StorableOutput dw) {
if (fAttributes == null)
dw.writeString("no_attributes");
else {
dw.writeString("attributes");
fAttributes.write(dw);
}
}
/**
* Reads the Figure from a StorableInput.
*/
public void read(StorableInput dr) throws IOException {
String s = dr.readString();
if (s.toLowerCase().equals("attributes")) {
fAttributes = new FigureAttributeMap();
fAttributes.read(dr);
} else {
fAttributes = null;
}
}
/**
* Clones a figure. Creates a clone by using the storable
* mechanism to flatten the Figure to stream followed by
* resurrecting it from the same stream.
*
* @see Figure#clone
*/
public Object clone() {
Object clone = null;
ByteArrayOutputStream output = new ByteArrayOutputStream(200);
try {
ObjectOutput writer = new ObjectOutputStream(output);
writer.writeObject(this);
writer.close();
} catch (IOException e) {
System.err.println(e);
}
InputStream input = new ByteArrayInputStream(output.toByteArray());
try {
ObjectInput reader = new ObjectInputStream(input);
clone = (Object) reader.readObject();
} catch (IOException e) {
System.err.println(e);
} catch (ClassNotFoundException e) {
System.err.println(e);
}
return clone;
}
protected static class DefaultFigureAttributeMap extends FigureAttributeMap {
public DefaultFigureAttributeMap() {
super();
set("frameColor", Color.black);
set("fillColor", new Color(153, 204, 255, 128));
set("textColor", Color.black);
set("arrowMode", new Integer(0));
set("insets", new Insets(0, 0, 0, 0));
set("font", new Font("DialogInput", 12, Font.PLAIN));
set("visibility", Boolean.TRUE);
set("selectivity", Boolean.TRUE);
set("connectability", Boolean.TRUE);
set("connectorVisibility", Boolean.FALSE);
}
}
public int compareTo(Object o) {
return (this.hashCode() - o.hashCode());
}
}