/*******************************************************************************
* This file is part of logisim-evolution.
*
* logisim-evolution 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 3 of the License, or
* (at your option) any later version.
*
* logisim-evolution 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 logisim-evolution. If not, see <http://www.gnu.org/licenses/>.
*
* Original code by Carl Burch (http://www.cburch.com), 2011.
* Subsequent modifications by :
* + Haute École Spécialisée Bernoise
* http://www.bfh.ch
* + Haute École du paysage, d'ingénierie et d'architecture de Genève
* http://hepia.hesge.ch/
* + Haute École d'Ingénierie et de Gestion du Canton de Vaud
* http://www.heig-vd.ch/
* The project is currently maintained by :
* + REDS Institute - HEIG-VD
* Yverdon-les-Bains, Switzerland
* http://reds.heig-vd.ch
*******************************************************************************/
package com.cburch.logisim.circuit;
import java.awt.Font;
import java.util.Arrays;
import java.util.List;
import javax.swing.JOptionPane;
import com.bfh.logisim.designrulecheck.CorrectLabel;
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;
import com.cburch.logisim.util.SyntaxChecker;
public class CircuitAttributes extends AbstractAttributeSet {
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(),e.getOldValue());
}
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();
}
}
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) {
String NewName = (String) e.getValue();
String OldName = e.getOldValue() == null ? "ThisShouldNotHappen" : (String) e.getOldValue();
if (!NewName.equals(OldName)) {
if (NewName.isEmpty()) {
JOptionPane.showMessageDialog(null, Strings.get("EmptyNameError"));
e.getSource().setValue(NAME_ATTR, OldName);
source.fireEvent(CircuitEvent.ACTION_SET_NAME, OldName);
return;
} else
if (!SyntaxChecker.isVariableNameAcceptable(NewName,true)) {
e.getSource().setValue(NAME_ATTR, OldName);
source.fireEvent(CircuitEvent.ACTION_SET_NAME, OldName);
return;
} else
if (CorrectLabel.IsKeyword(NewName,false)) {
JOptionPane.showMessageDialog(null, Strings.get("KeywordNameError"));
e.getSource().setValue(NAME_ATTR, OldName);
source.fireEvent(CircuitEvent.ACTION_SET_NAME, OldName);
return;
} else {
source.fireEvent(CircuitEvent.ACTION_CHECK_NAME, OldName);
source.fireEvent(CircuitEvent.ACTION_SET_NAME, NewName);
}
}
}
}
}
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;
}
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"));
public static final Attribute<Boolean> CIRCUIT_IS_VHDL_BOX = Attributes
.forBoolean("circuitvhdl", Strings.getter("circuitIsVhdl"));
public static final Attribute<String> CIRCUIT_VHDL_PATH = Attributes
.forString("circuitvhdlpath", Strings.getter("circuitVhdlPath"));
public static final Attribute<Boolean> NAMED_CIRCUIT_BOX = Attributes
.forBoolean("circuitnamedbox",Strings.getter("circuitNamedBox"));
private static final Attribute<?>[] STATIC_ATTRS = { NAME_ATTR,
CIRCUIT_LABEL_ATTR, CIRCUIT_LABEL_FACING_ATTR,
CIRCUIT_LABEL_FONT_ATTR,NAMED_CIRCUIT_BOX,
CIRCUIT_VHDL_PATH, };
private static final Object[] STATIC_DEFAULTS = { "", "", Direction.EAST,
StdAttr.DEFAULT_LABEL_FONT,
false, "", };
private static final List<Attribute<?>> INSTANCE_ATTRS = Arrays
.asList(new Attribute<?>[] { StdAttr.FACING, StdAttr.LABEL,
LABEL_LOCATION_ATTR, StdAttr.LABEL_FONT,StdAttr.LABEL_VISIBILITY,
CircuitAttributes.NAME_ATTR, CIRCUIT_LABEL_ATTR,
CIRCUIT_LABEL_FACING_ATTR, CIRCUIT_LABEL_FONT_ATTR,
NAMED_CIRCUIT_BOX,
CIRCUIT_VHDL_PATH, });
private Circuit source;
private Instance subcircInstance;
private Direction facing;
private String label;
private Direction labelLocation;
private Font labelFont;
private Boolean LabelVisable;
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;
LabelVisable = true;
pinInstances = new Instance[0];
}
@Override
protected void copyInto(AbstractAttributeSet dest) {
CircuitAttributes other = (CircuitAttributes) dest;
other.subcircInstance = null;
other.listener = null;
}
@Override
public List<Attribute<?>> getAttributes() {
return INSTANCE_ATTRS;
}
public Direction getFacing() {
return facing;
}
public Instance[] getPinInstances() {
return pinInstances;
}
@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 == StdAttr.LABEL_VISIBILITY)
return (E) LabelVisable;
if (attr == LABEL_LOCATION_ATTR)
return (E) labelLocation;
else
return source.getStaticAttributes().getValue(attr);
}
@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;
}
void setPinInstances(Instance[] value) {
pinInstances = value;
}
void setSubcircuit(Instance value) {
subcircInstance = value;
if (subcircInstance != null && listener == null) {
listener = new MyListener();
source.getStaticAttributes().addAttributeListener(listener);
source.getAppearance().addCircuitAppearanceListener(listener);
}
}
@Override
public <E> void setValue(Attribute<E> attr, E value) {
if (attr == StdAttr.FACING) {
Direction val = (Direction) value;
if (facing.equals(val))
return;
facing = val;
fireAttributeValueChanged(StdAttr.FACING, val,null);
if (subcircInstance != null)
subcircInstance.recomputeBounds();
} else if (attr == StdAttr.LABEL) {
String val = (String) value;
String oldval = label;
if (label.equals(val))
return;
label = val;
fireAttributeValueChanged(StdAttr.LABEL, val, oldval);
} else if (attr == StdAttr.LABEL_FONT) {
Font val = (Font) value;
if (labelFont.equals(val))
return;
labelFont = val;
fireAttributeValueChanged(StdAttr.LABEL_FONT, val,null);
} else if (attr == StdAttr.LABEL_VISIBILITY) {
Boolean val = (Boolean) value;
if (LabelVisable == value)
return;
LabelVisable = val;
fireAttributeValueChanged(StdAttr.LABEL_VISIBILITY, val,null);
} else if (attr == LABEL_LOCATION_ATTR) {
Direction val = (Direction) value;
if (labelLocation.equals(val))
return;
labelLocation = val;
fireAttributeValueChanged(LABEL_LOCATION_ATTR, val,null);
} else {
source.getStaticAttributes().setValue(attr, value);
if (attr == NAME_ATTR) {
source.fireEvent(CircuitEvent.ACTION_SET_NAME, value);
}
}
}
}