Una de las mayores ventajas de definir componentes en Java es la posibilidad de que sean configurables a través de sus atributos. Como ejemplo, podríamos necesitar que el incrementador trabajase con cualquier número de bits; las dos clases que vienen a continuación muestran como es posible conseguirlo.
package com.cburch.incr;
import com.cburch.logisim.circuit.CircuitState;
import com.cburch.logisim.comp.ComponentDrawContext;
import com.cburch.logisim.comp.ComponentFactory;
import com.cburch.logisim.comp.EndData;
import com.cburch.logisim.comp.ManagedComponent;
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.Attributes;
import com.cburch.logisim.data.BitWidth;
import com.cburch.logisim.data.Location;
import com.cburch.logisim.data.Value;
/** Represents an incrementer that can work with any bit width. This component
* is designed to illustrate how to use attributes. */
class Incrementer extends ManagedComponent {
/** The attribute representing the bit width of the input and output. */
static final Attribute WIDTH_ATTRIBUTE = Attributes.forBitWidth("Bit Width");
/** The default value of the width attribute. */
static final BitWidth WIDTH_DEFAULT = BitWidth.create(8);
/** Listens for changes to the width attributes, because we need such
* changes to be reflected in the information about ends managed by the
* ManagedComponent
superclass. */
private class MyListener implements AttributeListener {
public void attributeListChanged(AttributeEvent e) { }
public void attributeValueChanged(AttributeEvent e) {
if(e.getAttribute() == WIDTH_ATTRIBUTE) computeEnds();
}
}
/** Represents the sole instance of MyListener. (The more common
* idioms for dealing with listeners do not involve such a
* local variable, but I strongly prefer this idiom, because
* I often find it useful to store listeners in the listened-to
* object using weak references to avoid situations analogous
* to memory leaks when the listened-to object persists beyond
* the intended life of the listening object. A side effect of
* this is that the listener would die immediately if the listening
* object doesn't maintain its own strong reference; hence the
* instance variable. [It happens that the AttributeSet used here
* uses strong references, but that's no guarantee that a future
* version will not.])
*/
private MyListener myListener = new MyListener();
/** Constructs an incrementer at the given location with the given
* attributes. */
Incrementer(Location loc, AttributeSet attrs) {
super(loc, attrs, 2);
attrs.addAttributeListener(myListener);
computeEnds();
}
/** Sets up the ends of this component. */
private void computeEnds() {
// Retrieve information needed for setting the ends - notice the
// access to the attribute set to retrieve the width.
Location loc = getLocation();
BitWidth width = (BitWidth) getAttributeSet().getValue(WIDTH_ATTRIBUTE);
// Now set up the ends.
setEnd(0, loc.translate(-30, 0), width, EndData.INPUT_ONLY);
setEnd(1, loc, width, EndData.OUTPUT_ONLY);
}
public ComponentFactory getFactory() {
return IncrementerFactory.instance;
}
public void propagate(CircuitState circuitState) {
Value in = circuitState.getValue(getEndLocation(0));
Value out;
if(in.isFullyDefined()) {
out = Value.createKnown(in.getBitWidth(), in.toIntValue() + 1);
} else if(in.isErrorValue()) {
out = Value.createError(in.getBitWidth());
} else {
out = Value.createUnknown(in.getBitWidth());
}
circuitState.setValue(getEndLocation(1), out, this,
in.getBitWidth().getWidth() + 1);
}
public void draw(ComponentDrawContext context) {
context.drawRectangle(this, "+1");
context.drawPins(this);
}
}
package com.cburch.incr; import com.cburch.logisim.comp.AbstractComponentFactory; import com.cburch.logisim.comp.Component; import com.cburch.logisim.data.AttributeSet; import com.cburch.logisim.data.AttributeSets; import com.cburch.logisim.data.Bounds; import com.cburch.logisim.data.Location; /** ManufacturesIncrementer
components. */ class IncrementerFactory extends AbstractComponentFactory { static final IncrementerFactory instance = new IncrementerFactory(); private IncrementerFactory() { } public String getName() { return "Incrementer"; } public String getDisplayName() { return "Incrementer (General)"; } /** Creates an attribute set holding all the initial default values. This * is the only change from theByteIncrementerClass
class, where * we simply kept the definition implemented in the parent class. Here, though, * we want to insert the attribute. */ public AttributeSet createAttributeSet() { return AttributeSets.fixedSet(Incrementer.WIDTH_ATTRIBUTE, Incrementer.WIDTH_DEFAULT); } public Component createComponent(Location loc, AttributeSet attrs) { return new Incrementer(loc, attrs); } public Bounds getOffsetBounds(AttributeSet attrs) { return Bounds.create(-30, -15, 30, 30); } }
Siguiente: Contador Básico .