/* Copyright (c) 2010, Carl Burch. License information is located in the
* com.cburch.logisim.Main source code and at www.cburch.com/logisim/. */
package com.cburch.logisim.circuit;
import java.awt.Font;
import java.util.Arrays;
import java.util.List;
import com.cburch.logisim.circuit.appear.CircuitAppearanceEvent;
import com.cburch.logisim.circuit.appear.CircuitAppearanceListener;
import com.cburch.logisim.data.AbstractAttributeSet;
import com.cburch.logisim.data.Attribute;
import com.cburch.logisim.data.AttributeEvent;
import com.cburch.logisim.data.AttributeListener;
import com.cburch.logisim.data.AttributeSet;
import com.cburch.logisim.data.AttributeSets;
import com.cburch.logisim.data.Attributes;
import com.cburch.logisim.data.Direction;
import com.cburch.logisim.instance.Instance;
import com.cburch.logisim.instance.StdAttr;
public class CircuitAttributes extends AbstractAttributeSet {
public static final Attribute<String> NAME_ATTR
= Attributes.forString("circuit", Strings.getter("circuitName"));
public static final Attribute<Direction> LABEL_LOCATION_ATTR
= Attributes.forDirection("labelloc", Strings.getter("circuitLabelLocAttr"));
public static final Attribute<String> CIRCUIT_LABEL_ATTR
= Attributes.forString("clabel", Strings.getter("circuitLabelAttr"));
public static final Attribute<Direction> CIRCUIT_LABEL_FACING_ATTR
= Attributes.forDirection("clabelup", Strings.getter("circuitLabelDirAttr"));
public static final Attribute<Font> CIRCUIT_LABEL_FONT_ATTR
= Attributes.forFont("clabelfont", Strings.getter("circuitLabelFontAttr"));
private static final Attribute<?>[] STATIC_ATTRS = {
NAME_ATTR, CIRCUIT_LABEL_ATTR, CIRCUIT_LABEL_FACING_ATTR, CIRCUIT_LABEL_FONT_ATTR,
};
private static final Object[] STATIC_DEFAULTS = {
"", "", Direction.EAST, StdAttr.DEFAULT_LABEL_FONT,
};
private static final List<Attribute<?>> INSTANCE_ATTRS
= Arrays.asList(new Attribute<?>[] {
StdAttr.FACING, StdAttr.LABEL, LABEL_LOCATION_ATTR,
StdAttr.LABEL_FONT,
CircuitAttributes.NAME_ATTR, CIRCUIT_LABEL_ATTR,
CIRCUIT_LABEL_FACING_ATTR, CIRCUIT_LABEL_FONT_ATTR,
});
private static class StaticListener implements AttributeListener {
private Circuit source;
private StaticListener(Circuit s) { source = s; }
public void attributeListChanged(AttributeEvent e) { }
public void attributeValueChanged(AttributeEvent e) {
if (e.getAttribute() == NAME_ATTR) {
source.fireEvent(CircuitEvent.ACTION_SET_NAME, e.getValue());
}
}
}
private class MyListener implements AttributeListener, CircuitAppearanceListener {
public void attributeListChanged(AttributeEvent e) { }
public void attributeValueChanged(AttributeEvent e) {
@SuppressWarnings("unchecked")
Attribute<Object> a = (Attribute<Object>) e.getAttribute();
fireAttributeValueChanged(a, e.getValue());
}
public void circuitAppearanceChanged(CircuitAppearanceEvent e) {
SubcircuitFactory factory;
factory = (SubcircuitFactory) subcircInstance.getFactory();
if (e.isConcerning(CircuitAppearanceEvent.PORTS)) {
factory.computePorts(subcircInstance);
}
if (e.isConcerning(CircuitAppearanceEvent.BOUNDS)) {
subcircInstance.recomputeBounds();
}
subcircInstance.fireInvalidated();
}
}
static AttributeSet createBaseAttrs(Circuit source, String name) {
AttributeSet ret = AttributeSets.fixedSet(STATIC_ATTRS, STATIC_DEFAULTS);
ret.setValue(CircuitAttributes.NAME_ATTR, name);
ret.addAttributeListener(new StaticListener(source));
return ret;
}
private Circuit source;
private Instance subcircInstance;
private Direction facing;
private String label;
private Direction labelLocation;
private Font labelFont;
private MyListener listener;
private Instance[] pinInstances;
public CircuitAttributes(Circuit source) {
this.source = source;
subcircInstance = null;
facing = source.getAppearance().getFacing();
label = "";
labelLocation = Direction.NORTH;
labelFont = StdAttr.DEFAULT_LABEL_FONT;
pinInstances = new Instance[0];
}
void setSubcircuit(Instance value) {
subcircInstance = value;
if (subcircInstance != null && listener == null) {
listener = new MyListener();
source.getStaticAttributes().addAttributeListener(listener);
source.getAppearance().addCircuitAppearanceListener(listener);
}
}
Instance[] getPinInstances() {
return pinInstances;
}
void setPinInstances(Instance[] value) {
pinInstances = value;
}
public Direction getFacing() {
return facing;
}
@Override
protected void copyInto(AbstractAttributeSet dest) {
CircuitAttributes other = (CircuitAttributes) dest;
other.subcircInstance = null;
other.listener = null;
}
@Override
public boolean isToSave(Attribute<?> attr) {
Attribute<?>[] statics = STATIC_ATTRS;
for (int i = 0; i < statics.length; i++) {
if (statics[i] == attr) return false;
}
return true;
}
@Override
public List<Attribute<?>> getAttributes() {
return INSTANCE_ATTRS;
}
@Override
@SuppressWarnings("unchecked")
public <E> E getValue(Attribute<E> attr) {
if (attr == StdAttr.FACING) return (E) facing;
if (attr == StdAttr.LABEL) return (E) label;
if (attr == StdAttr.LABEL_FONT) return (E) labelFont;
if (attr == LABEL_LOCATION_ATTR) return (E) labelLocation;
else return source.getStaticAttributes().getValue(attr);
}
@Override
public <E> void setValue(Attribute<E> attr, E value) {
if (attr == StdAttr.FACING) {
Direction val = (Direction) value;
facing = val;
fireAttributeValueChanged(StdAttr.FACING, val);
if (subcircInstance != null) subcircInstance.recomputeBounds();
} else if (attr == StdAttr.LABEL) {
String val = (String) value;
label = val;
fireAttributeValueChanged(StdAttr.LABEL, val);
} else if (attr == StdAttr.LABEL_FONT) {
Font val = (Font) value;
labelFont = val;
fireAttributeValueChanged(StdAttr.LABEL_FONT, val);
} else if (attr == LABEL_LOCATION_ATTR) {
Direction val = (Direction) value;
labelLocation = val;
fireAttributeValueChanged(LABEL_LOCATION_ATTR, val);
} else {
source.getStaticAttributes().setValue(attr, value);
if (attr == NAME_ATTR) {
source.fireEvent(CircuitEvent.ACTION_SET_NAME, value);
}
}
}
}