package net.mograsim.logic.core.components;\r
\r
+import java.util.ArrayList;\r
+import java.util.Collection;\r
import java.util.List;\r
\r
+import net.mograsim.logic.core.LogicObservable;\r
+import net.mograsim.logic.core.LogicObserver;\r
import net.mograsim.logic.core.timeline.Timeline;\r
import net.mograsim.logic.core.types.Bit;\r
import net.mograsim.logic.core.types.BitVector;\r
import net.mograsim.logic.core.wires.Wire.ReadEnd;\r
import net.mograsim.logic.core.wires.Wire.ReadWriteEnd;\r
\r
-public class BitDisplay extends BasicComponent\r
+public class BitDisplay extends BasicComponent implements LogicObservable\r
{\r
+ private Collection<LogicObserver> observers;\r
private final ReadEnd in;\r
private BitVector displayedValue;\r
\r
public BitDisplay(Timeline timeline, ReadEnd in)\r
{\r
super(timeline, 1);\r
+ observers = new ArrayList<>();\r
this.in = in;\r
in.registerObserver(this);\r
compute();\r
protected void compute()\r
{\r
displayedValue = in.getValues();\r
+ notifyObservers();\r
}\r
\r
public BitVector getDisplayedValue()\r
{\r
return List.of();\r
}\r
+\r
+ @Override\r
+ public void registerObserver(LogicObserver ob)\r
+ {\r
+ observers.add(ob);\r
+ }\r
+\r
+ @Override\r
+ public void deregisterObserver(LogicObserver ob)\r
+ {\r
+ observers.remove(ob);\r
+ }\r
+\r
+ @Override\r
+ public void notifyObservers()\r
+ {\r
+ observers.forEach(ob -> ob.update(this));\r
+ }\r
}\r
-package net.mograsim.logic.core.components;
-
-import java.util.List;
-
-import net.mograsim.logic.core.timeline.Timeline;
-import net.mograsim.logic.core.types.Bit;
-import net.mograsim.logic.core.wires.Wire.ReadEnd;
-import net.mograsim.logic.core.wires.Wire.ReadWriteEnd;
-
-/**
- * This class models a simple on/off (ONE/ZERO) switch for user interaction.
- *
- * @author Christian Femers
- *
- */
-public class ManualSwitch extends Component
-{
- private ReadWriteEnd output;
- private boolean isOn;
-
- public ManualSwitch(Timeline timeline, ReadWriteEnd output)
- {
- super(timeline);
- if (output.length() != 1)
- throw new IllegalArgumentException("Switch output can be only a single wire");
- this.output = output;
- }
-
- public void switchOn()
- {
- setState(true);
- }
-
- public void switchOff()
- {
- setState(false);
- }
-
- public void toggle()
- {
- setState(!isOn);
- }
-
- public void setState(boolean isOn)
- {
- if (this.isOn == isOn)
- return;
- this.isOn = isOn;
- output.feedSignals(getValue());
- }
-
- public boolean isOn()
- {
- return isOn;
- }
-
- public Bit getValue()
- {
- return isOn ? Bit.ONE : Bit.ZERO;
- }
-
- @Override
- public List<ReadEnd> getAllInputs()
- {
- return List.of();
- }
-
- @Override
- public List<ReadWriteEnd> getAllOutputs()
- {
- return List.of(output);
- }
-
-}
+package net.mograsim.logic.core.components;\r
+\r
+import java.util.ArrayList;\r
+import java.util.Collection;\r
+import java.util.List;\r
+\r
+import net.mograsim.logic.core.LogicObservable;\r
+import net.mograsim.logic.core.LogicObserver;\r
+import net.mograsim.logic.core.timeline.Timeline;\r
+import net.mograsim.logic.core.types.Bit;\r
+import net.mograsim.logic.core.wires.Wire.ReadEnd;\r
+import net.mograsim.logic.core.wires.Wire.ReadWriteEnd;\r
+\r
+/**\r
+ * This class models a simple on/off (ONE/ZERO) switch for user interaction.\r
+ *\r
+ * @author Christian Femers\r
+ *\r
+ */\r
+public class ManualSwitch extends Component implements LogicObservable\r
+{\r
+ private Collection<LogicObserver> observers;\r
+ private ReadWriteEnd output;\r
+ private boolean isOn;\r
+\r
+ public ManualSwitch(Timeline timeline, ReadWriteEnd output)\r
+ {\r
+ super(timeline);\r
+ observers = new ArrayList<>();\r
+ if (output.length() != 1)\r
+ throw new IllegalArgumentException("Switch output can be only a single wire");\r
+ this.output = output;\r
+ }\r
+\r
+ public void switchOn()\r
+ {\r
+ setState(true);\r
+ }\r
+\r
+ public void switchOff()\r
+ {\r
+ setState(false);\r
+ }\r
+\r
+ public void toggle()\r
+ {\r
+ setState(!isOn);\r
+ }\r
+\r
+ public void setState(boolean isOn)\r
+ {\r
+ if (this.isOn == isOn)\r
+ return;\r
+ this.isOn = isOn;\r
+ output.feedSignals(getValue());\r
+ notifyObservers();\r
+ }\r
+\r
+ public boolean isOn()\r
+ {\r
+ return isOn;\r
+ }\r
+\r
+ public Bit getValue()\r
+ {\r
+ return isOn ? Bit.ONE : Bit.ZERO;\r
+ }\r
+\r
+ @Override\r
+ public List<ReadEnd> getAllInputs()\r
+ {\r
+ return List.of();\r
+ }\r
+\r
+ @Override\r
+ public List<ReadWriteEnd> getAllOutputs()\r
+ {\r
+ return List.of(output);\r
+ }\r
+\r
+ @Override\r
+ public void registerObserver(LogicObserver ob)\r
+ {\r
+ observers.add(ob);\r
+ }\r
+\r
+ @Override\r
+ public void deregisterObserver(LogicObserver ob)\r
+ {\r
+ observers.remove(ob);\r
+ }\r
+\r
+ @Override\r
+ public void notifyObservers()\r
+ {\r
+ observers.forEach(ob -> ob.update(this));\r
+ }\r
+\r
+}\r
\r
private final List<Consumer<TimelineEvent>> eventAddedListener;\r
\r
+ public final LongSupplier stepByStepExec = () -> lastTimeUpdated;\r
+ public final LongSupplier realTimeExec = () -> System.currentTimeMillis();\r
+\r
+ /**\r
+ * Constructs a Timeline object. Per default the time function is set to step by step execution.\r
+ * \r
+ * @param initCapacity The initial capacity of the event queue.\r
+ */\r
public Timeline(int initCapacity)\r
{\r
events = new PriorityQueue<>(initCapacity);\r
-\r
eventAddedListener = new ArrayList<>();\r
- time = () -> lastTimeUpdated;\r
+ time = stepByStepExec;\r
}\r
\r
/**\r
* @param timestamp exclusive\r
- * @return true if the first event is later than the timestamp\r
+ * @return <code>true</code> if the first event in queue is later than the given timestamp\r
*/\r
public BooleanSupplier laterThan(long timestamp)\r
{\r
return () -> timeCmp(events.peek().getTiming(), timestamp) > 0;\r
}\r
\r
+ /**\r
+ * @return <code>true</code> if there is at least one event enqueued. <code>false</code> otherwise\r
+ */\r
public boolean hasNext()\r
{\r
return !events.isEmpty();\r
executeUntil(laterThan(first.getTiming()), -1);\r
}\r
\r
+ /**\r
+ * Executes all events enqueued in the {@link Timeline}. Use very carefully! Events may generate new events, causing an infinite loop.\r
+ */\r
public void executeAll()\r
{\r
while (hasNext())\r
* <code>EXEC_UNTIL_CONDITION</code> if the condition was met\r
* <code>EXEC_UNTIL_EMPTY</code> if events were executed until the {@link Timeline} was empty\r
* @formatter:on\r
- * @author Christian Femers, Fabian Stemmler\r
*/\r
public ExecutionResult executeUntil(BooleanSupplier condition, long stopMillis)\r
{\r
return hasNext() ? ExecutionResult.EXEC_UNTIL_EMPTY : ExecutionResult.EXEC_UNTIL_CONDITION;\r
}\r
\r
+ /**\r
+ * Sets the function, which defines the current simulation time at any time.\r
+ * \r
+ * @param time The return value of calling this function is the current simulation time.\r
+ */\r
public void setTimeFunction(LongSupplier time)\r
{\r
this.time = time;\r
}\r
\r
+ /**\r
+ * Calculates the current simulation time.\r
+ * \r
+ * @return The simulation time as defined by the time function.\r
+ */\r
public long getSimulationTime()\r
{\r
return time.getAsLong();\r
}\r
\r
+ /**\r
+ * Retrieves the timestamp of the next event.\r
+ * \r
+ * @return The timestamp of the next enqueued event, if the {@link Timeline} is not empty, -1 otherwise.\r
+ */\r
public long nextEventTime()\r
{\r
if (!hasNext())\r
return events.peek().getTiming();\r
}\r
\r
+ /**\r
+ * Clears the {@link Timeline} of enqueued events.\r
+ */\r
public void reset()\r
{\r
events.clear();\r
lastTimeUpdated = 0;\r
}\r
\r
+ /**\r
+ * Adds a listener, that is called when a {@link TimelineEvent} is added.\r
+ */\r
public void addEventAddedListener(Consumer<TimelineEvent> listener)\r
{\r
eventAddedListener.add(listener);\r
}\r
\r
+ /**\r
+ * Removes the listener, if possible. It will no longer be called when a {@link TimelineEvent} is added.\r
+ */\r
public void removeEventAddedListener(Consumer<TimelineEvent> listener)\r
{\r
eventAddedListener.remove(listener);\r
}\r
}\r
\r
- public static int timeCmp(long a, long b)\r
+ static int timeCmp(long a, long b)\r
{\r
return Long.signum(a - b);\r
}\r
\r
private void notifyObservers()\r
{\r
- for (ReadEnd o : attached)\r
- o.update();\r
+ attached.forEach(r -> r.update());\r
}\r
\r
/**\r
@Override\r
public void notifyObservers()\r
{\r
- for (LogicObserver ob : observers)\r
- ob.update(this);\r
+ observers.forEach(ob -> ob.update(this));\r
}\r
}\r
\r
-package net.mograsim.logic.ui.model.components;
-
-import net.mograsim.logic.ui.model.ViewModel;
-import net.mograsim.logic.ui.model.wires.Pin;
-import net.haspamelodica.swt.helper.gcs.GeneralGC;
-import net.haspamelodica.swt.helper.swtobjectwrappers.Font;
-import net.haspamelodica.swt.helper.swtobjectwrappers.Point;
-import net.haspamelodica.swt.helper.swtobjectwrappers.Rectangle;
-import net.mograsim.logic.core.components.ManualSwitch;
-import net.mograsim.logic.core.types.BitVectorFormatter;
-import net.mograsim.logic.core.wires.Wire.ReadEnd;
-
-public class GUIManualSwitch extends GUIComponent
-{
- private static final double width = 20;
- private static final double height = 15;
- private static final double fontHeight = 5;
-
- private final Pin outputPin;
-
- private ManualSwitch logicSwitch;
- private ReadEnd end;
-
- public GUIManualSwitch(ViewModel model)
- {
- super(model);
- setSize(width, height);
- addPin(this.outputPin = new Pin(this, 1, width, height / 2));
- }
-
- @Override
- public void render(GeneralGC gc, Rectangle visibleRegion)
- {
- double posX = getBounds().x;
- double posY = getBounds().y;
-
- gc.drawRectangle(posX, posY, width, height);
- String label = BitVectorFormatter.formatValueAsString(end);
- Font oldFont = gc.getFont();
- Font labelFont = new Font(oldFont.getName(), fontHeight, oldFont.getStyle());
- gc.setFont(labelFont);
- Point textExtent = gc.textExtent(label);
- gc.drawText(label, posX + (width - textExtent.x) / 2, posY + (height - textExtent.y) / 2, true);
- gc.setFont(oldFont);
- }
-
- public void setLogicModelBinding(ManualSwitch logicSwitch, ReadEnd end)
- {
- this.logicSwitch = logicSwitch;
- this.end = end;
- // TODO when ManualSwitch supports it, add listeners
- end.addObserver((i, o) -> callComponentLookChangedListeners());
- }
-
- @Override
- public boolean clicked(double x, double y)
- {
- if (logicSwitch != null)
- logicSwitch.toggle();
- return true;
- }
-
- public Pin getOutputPin()
- {
- return outputPin;
- }
+package net.mograsim.logic.ui.model.components;\r
+\r
+import net.mograsim.logic.ui.model.ViewModel;\r
+import net.mograsim.logic.ui.model.wires.Pin;\r
+import net.haspamelodica.swt.helper.gcs.GeneralGC;\r
+import net.haspamelodica.swt.helper.swtobjectwrappers.Font;\r
+import net.haspamelodica.swt.helper.swtobjectwrappers.Point;\r
+import net.haspamelodica.swt.helper.swtobjectwrappers.Rectangle;\r
+import net.mograsim.logic.core.components.ManualSwitch;\r
+import net.mograsim.logic.core.types.BitVectorFormatter;\r
+import net.mograsim.logic.core.wires.Wire.ReadEnd;\r
+\r
+public class GUIManualSwitch extends GUIComponent\r
+{\r
+ private static final double width = 20;\r
+ private static final double height = 15;\r
+ private static final double fontHeight = 5;\r
+\r
+ private final Pin outputPin;\r
+\r
+ private ManualSwitch logicSwitch;\r
+ private ReadEnd end;\r
+\r
+ public GUIManualSwitch(ViewModel model)\r
+ {\r
+ super(model);\r
+ setSize(width, height);\r
+ addPin(this.outputPin = new Pin(this, 1, width, height / 2));\r
+ }\r
+\r
+ @Override\r
+ public void render(GeneralGC gc, Rectangle visibleRegion)\r
+ {\r
+ double posX = getBounds().x;\r
+ double posY = getBounds().y;\r
+\r
+ gc.drawRectangle(posX, posY, width, height);\r
+ String label = BitVectorFormatter.formatValueAsString(end);\r
+ Font oldFont = gc.getFont();\r
+ Font labelFont = new Font(oldFont.getName(), fontHeight, oldFont.getStyle());\r
+ gc.setFont(labelFont);\r
+ Point textExtent = gc.textExtent(label);\r
+ gc.drawText(label, posX + (width - textExtent.x) / 2, posY + (height - textExtent.y) / 2, true);\r
+ gc.setFont(oldFont);\r
+ }\r
+\r
+ public void setLogicModelBinding(ManualSwitch logicSwitch, ReadEnd end)\r
+ {\r
+ this.logicSwitch = logicSwitch;\r
+ this.end = end;\r
+ // TODO when ManualSwitch supports it, add listeners\r
+ end.registerObserver((i) -> callComponentLookChangedListeners());\r
+ }\r
+\r
+ @Override\r
+ public boolean clicked(double x, double y)\r
+ {\r
+ if (logicSwitch != null)\r
+ logicSwitch.toggle();\r
+ return true;\r
+ }\r
+\r
+ public Pin getOutputPin()\r
+ {\r
+ return outputPin;\r
+ }\r
}
\ No newline at end of file
-package net.mograsim.logic.ui.model.wires;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.function.Consumer;
-
-import net.mograsim.logic.ui.ColorHelper;
-import net.mograsim.logic.ui.model.ViewModel;
-import net.haspamelodica.swt.helper.gcs.GeneralGC;
-import net.haspamelodica.swt.helper.swtobjectwrappers.Point;
-import net.mograsim.logic.core.types.BitVectorFormatter;
-import net.mograsim.logic.core.wires.Wire.ReadEnd;
-
-public class GUIWire
-{
- private final ViewModel model;
- public final int logicWidth;
- private Pin pin1;
- private Pin pin2;
- private double[] path;
-
- private final List<Consumer<? super GUIWire>> wireLookChangedListeners;
-
- private ReadEnd end;
-
- public GUIWire(ViewModel model, Pin pin1, Pin pin2, Point... path)
- {
- this.model = model;
- this.logicWidth = pin1.logicWidth;
- if (pin2.logicWidth != pin1.logicWidth)
- throw new IllegalArgumentException("Can't connect pins of different logic width");
- this.path = new double[path.length * 2 + 4];
- for (int srcI = 0, dstI = 2; srcI < path.length; srcI++, dstI += 2)
- {
- this.path[dstI + 0] = path[srcI].x;
- this.path[dstI + 1] = path[srcI].y;
- }
-
- this.pin1 = pin1;
- this.pin2 = pin2;
-
- wireLookChangedListeners = new ArrayList<>();
-
- pin1.addPinMovedListener(p -> pin1Moved());
- pin2.addPinMovedListener(p -> pin2Moved());
- pin1Moved();
- pin2Moved();
-
- model.wireCreated(this);
- }
-
- private void pin1Moved()
- {
- Point pos = pin1.getPos();
- this.path[0] = pos.x;
- this.path[1] = pos.y;
- }
-
- private void pin2Moved()
- {
- Point pos = pin2.getPos();
- this.path[this.path.length - 2] = pos.x;
- this.path[this.path.length - 1] = pos.y;
- }
-
- public void destroy()
- {
- model.wireDestroyed(this);
- }
-
- public void render(GeneralGC gc)
- {
- ColorHelper.executeWithDifferentForeground(gc, BitVectorFormatter.formatAsColor(end), () -> gc.drawPolyline(path));
- }
-
- public void setLogicModelBinding(ReadEnd end)
- {
- this.end = end;
- end.addObserver((i, o) -> callWireLookChangedListeners());
- }
-
- public Pin getPin1()
- {
- return pin1;
- }
-
- public Pin getPin2()
- {
- return pin2;
- }
-
- // @formatter:off
- public void addWireLookChangedListener (Consumer<? super GUIWire> listener) {wireLookChangedListeners.add (listener);}
-
- public void removeWireLookChangedListener(Consumer<? super GUIWire> listener) {wireLookChangedListeners.remove(listener);}
-
- private void callWireLookChangedListeners() {wireLookChangedListeners.forEach(l -> l.accept(this));}
- // @formatter:on
-
+package net.mograsim.logic.ui.model.wires;\r
+\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+import java.util.function.Consumer;\r
+\r
+import net.mograsim.logic.ui.ColorHelper;\r
+import net.mograsim.logic.ui.model.ViewModel;\r
+import net.haspamelodica.swt.helper.gcs.GeneralGC;\r
+import net.haspamelodica.swt.helper.swtobjectwrappers.Point;\r
+import net.mograsim.logic.core.types.BitVectorFormatter;\r
+import net.mograsim.logic.core.wires.Wire.ReadEnd;\r
+\r
+public class GUIWire\r
+{\r
+ private final ViewModel model;\r
+ public final int logicWidth;\r
+ private Pin pin1;\r
+ private Pin pin2;\r
+ private double[] path;\r
+\r
+ private final List<Consumer<? super GUIWire>> wireLookChangedListeners;\r
+\r
+ private ReadEnd end;\r
+\r
+ public GUIWire(ViewModel model, Pin pin1, Pin pin2, Point... path)\r
+ {\r
+ this.model = model;\r
+ this.logicWidth = pin1.logicWidth;\r
+ if (pin2.logicWidth != pin1.logicWidth)\r
+ throw new IllegalArgumentException("Can't connect pins of different logic width");\r
+ this.path = new double[path.length * 2 + 4];\r
+ for (int srcI = 0, dstI = 2; srcI < path.length; srcI++, dstI += 2)\r
+ {\r
+ this.path[dstI + 0] = path[srcI].x;\r
+ this.path[dstI + 1] = path[srcI].y;\r
+ }\r
+\r
+ this.pin1 = pin1;\r
+ this.pin2 = pin2;\r
+\r
+ wireLookChangedListeners = new ArrayList<>();\r
+\r
+ pin1.addPinMovedListener(p -> pin1Moved());\r
+ pin2.addPinMovedListener(p -> pin2Moved());\r
+ pin1Moved();\r
+ pin2Moved();\r
+\r
+ model.wireCreated(this);\r
+ }\r
+\r
+ private void pin1Moved()\r
+ {\r
+ Point pos = pin1.getPos();\r
+ this.path[0] = pos.x;\r
+ this.path[1] = pos.y;\r
+ }\r
+\r
+ private void pin2Moved()\r
+ {\r
+ Point pos = pin2.getPos();\r
+ this.path[this.path.length - 2] = pos.x;\r
+ this.path[this.path.length - 1] = pos.y;\r
+ }\r
+\r
+ public void destroy()\r
+ {\r
+ model.wireDestroyed(this);\r
+ }\r
+\r
+ public void render(GeneralGC gc)\r
+ {\r
+ ColorHelper.executeWithDifferentForeground(gc, BitVectorFormatter.formatAsColor(end), () -> gc.drawPolyline(path));\r
+ }\r
+\r
+ public void setLogicModelBinding(ReadEnd end)\r
+ {\r
+ this.end = end;\r
+ end.registerObserver((i) -> callWireLookChangedListeners());\r
+ }\r
+\r
+ public Pin getPin1()\r
+ {\r
+ return pin1;\r
+ }\r
+\r
+ public Pin getPin2()\r
+ {\r
+ return pin2;\r
+ }\r
+\r
+ // @formatter:off\r
+ public void addWireLookChangedListener (Consumer<? super GUIWire> listener) {wireLookChangedListeners.add (listener);}\r
+\r
+ public void removeWireLookChangedListener(Consumer<? super GUIWire> listener) {wireLookChangedListeners.remove(listener);}\r
+\r
+ private void callWireLookChangedListeners() {wireLookChangedListeners.forEach(l -> l.accept(this));}\r
+ // @formatter:on\r
+\r
}
\ No newline at end of file
-package net.mograsim.logic.ui.model.wires;
-
-import net.mograsim.logic.ui.ColorHelper;
-import net.mograsim.logic.ui.model.ViewModel;
-import net.mograsim.logic.ui.model.components.GUIComponent;
-import net.haspamelodica.swt.helper.gcs.GeneralGC;
-import net.haspamelodica.swt.helper.swtobjectwrappers.Rectangle;
-import net.mograsim.logic.core.types.BitVectorFormatter;
-import net.mograsim.logic.core.wires.Wire.ReadEnd;
-
-public class WireCrossPoint extends GUIComponent
-{
- private final Pin pin;
-
- private ReadEnd end;
- private final int logicWidth;
-
- public WireCrossPoint(ViewModel model, int logicWidth)
- {
- super(model);
- this.logicWidth = logicWidth;
- setSize(0, 0);
- addPin(this.pin = new Pin(this, logicWidth, 0, 0));
- }
-
- @Override
- public void render(GeneralGC gc, Rectangle visibleRegion)
- {
- Rectangle bounds = getBounds();
- ColorHelper.executeWithDifferentBackground(gc, BitVectorFormatter.formatAsColor(end),
- () -> gc.fillOval(bounds.x - 1, bounds.y - 1, 2, 2));
- }
-
- public void setLogicModelBinding(ReadEnd end)
- {
- this.end = end;
- end.addObserver((i, o) -> callComponentLookChangedListeners());
- }
-
- public int getLogicWidth()
- {
- return logicWidth;
- }
-
- public Pin getPin()
- {
- return pin;
- }
+package net.mograsim.logic.ui.model.wires;\r
+\r
+import net.mograsim.logic.ui.ColorHelper;\r
+import net.mograsim.logic.ui.model.ViewModel;\r
+import net.mograsim.logic.ui.model.components.GUIComponent;\r
+import net.haspamelodica.swt.helper.gcs.GeneralGC;\r
+import net.haspamelodica.swt.helper.swtobjectwrappers.Rectangle;\r
+import net.mograsim.logic.core.types.BitVectorFormatter;\r
+import net.mograsim.logic.core.wires.Wire.ReadEnd;\r
+\r
+public class WireCrossPoint extends GUIComponent\r
+{\r
+ private final Pin pin;\r
+\r
+ private ReadEnd end;\r
+ private final int logicWidth;\r
+\r
+ public WireCrossPoint(ViewModel model, int logicWidth)\r
+ {\r
+ super(model);\r
+ this.logicWidth = logicWidth;\r
+ setSize(0, 0);\r
+ addPin(this.pin = new Pin(this, logicWidth, 0, 0));\r
+ }\r
+\r
+ @Override\r
+ public void render(GeneralGC gc, Rectangle visibleRegion)\r
+ {\r
+ Rectangle bounds = getBounds();\r
+ ColorHelper.executeWithDifferentBackground(gc, BitVectorFormatter.formatAsColor(end),\r
+ () -> gc.fillOval(bounds.x - 1, bounds.y - 1, 2, 2));\r
+ }\r
+\r
+ public void setLogicModelBinding(ReadEnd end)\r
+ {\r
+ this.end = end;\r
+ end.registerObserver((i) -> callComponentLookChangedListeners());\r
+ }\r
+\r
+ public int getLogicWidth()\r
+ {\r
+ return logicWidth;\r
+ }\r
+\r
+ public Pin getPin()\r
+ {\r
+ return pin;\r
+ }\r
}
\ No newline at end of file