Merge branch 'development' of
[Mograsim.git] / net.mograsim.logic.model / src / net / mograsim / logic / model / model / components / atomic / SimpleRectangularHardcodedModelComponent.java
1 package net.mograsim.logic.model.model.components.atomic;
2
3 import java.util.Map;
4 import java.util.concurrent.atomic.AtomicReference;
5
6 import net.haspamelodica.swt.helper.gcs.GeneralGC;
7 import net.haspamelodica.swt.helper.swtobjectwrappers.Rectangle;
8 import net.mograsim.logic.core.wires.CoreWire.ReadEnd;
9 import net.mograsim.logic.core.wires.CoreWire.ReadWriteEnd;
10 import net.mograsim.logic.model.model.LogicModelModifiable;
11 import net.mograsim.logic.model.model.components.ModelComponent;
12 import net.mograsim.logic.model.model.wires.Pin;
13 import net.mograsim.logic.model.modeladapter.LogicCoreAdapter;
14 import net.mograsim.logic.model.modeladapter.componentadapters.SimpleRectangularHardcodedModelComponentAdapter;
15 import net.mograsim.logic.model.serializing.IdentifyParams;
16 import net.mograsim.logic.model.snippets.HighLevelStateHandler;
17 import net.mograsim.logic.model.snippets.outlinerenderers.DefaultOutlineRenderer;
18 import net.mograsim.logic.model.snippets.symbolrenderers.CenteredTextSymbolRenderer;
19 import net.mograsim.logic.model.snippets.symbolrenderers.CenteredTextSymbolRenderer.CenteredTextParams;
20 import net.mograsim.logic.model.snippets.symbolrenderers.PinNamesSymbolRenderer;
21 import net.mograsim.logic.model.snippets.symbolrenderers.PinNamesSymbolRenderer.PinNamesParams;
22 import net.mograsim.logic.model.snippets.symbolrenderers.PinNamesSymbolRenderer.PinNamesParams.Position;
23
24 public abstract class SimpleRectangularHardcodedModelComponent extends ModelComponent
25 {
26         private static final double centerTextHeight = 5;
27         private static final double pinNamesHeight = 3.5;
28         private static final double pinNamesMargin = .5;
29
30         private final String id;
31
32         private final DefaultOutlineRenderer outlineRenderer;
33         private final CenteredTextSymbolRenderer centerTextRenderer;
34         private final PinNamesSymbolRenderer pinNamesRenderer;
35
36         private AtomicReference<Object> state;
37         private Runnable recalculate;
38
39         // creation and destruction
40
41         public SimpleRectangularHardcodedModelComponent(LogicModelModifiable model, String id, String name, String centerText, boolean callInit)
42         {
43                 super(model, name, false);
44                 this.id = id;
45                 this.outlineRenderer = new DefaultOutlineRenderer(this);
46                 CenteredTextParams centeredTextParams = new CenteredTextParams();
47                 centeredTextParams.text = centerText;
48                 centeredTextParams.fontHeight = centerTextHeight;
49                 this.centerTextRenderer = new CenteredTextSymbolRenderer(this, centeredTextParams);
50                 PinNamesParams pinNamesParams = new PinNamesParams();
51                 pinNamesParams.pinLabelHeight = pinNamesHeight;
52                 pinNamesParams.pinLabelMargin = pinNamesMargin;
53                 this.pinNamesRenderer = new PinNamesSymbolRenderer(this, pinNamesParams);
54                 addPinRemovedListener(this::pinRemoved);
55                 setHighLevelStateHandler(new HighLevelStateHandler()
56                 {
57                         @Override
58                         public String getIDForSerializing(IdentifyParams idParams)
59                         {
60                                 return null;// we don't need to serialize this; it's implicit since we are a SimpleRectangularHardcodedModelComponent
61                         }
62
63                         @Override
64                         public Object getParamsForSerializing(IdentifyParams idParams)
65                         {
66                                 return null;
67                         }
68
69                         @Override
70                         public Object getHighLevelState(String stateID)
71                         {
72                                 return SimpleRectangularHardcodedModelComponent.this.getHighLevelState(state.get(), stateID);
73                         }
74
75                         @Override
76                         public void setHighLevelState(String stateID, Object newState)
77                         {
78                                 state.updateAndGet(s -> SimpleRectangularHardcodedModelComponent.this.setHighLevelState(s, stateID, newState));
79                                 recalculate.run();
80                         }
81                 });
82
83                 if (callInit)
84                         init();
85         }
86
87         // pins
88
89         protected void addPin(Pin pin, Position namePosition)
90         {
91                 super.addPin(pin); // do this first to catch errors
92                 pinNamesRenderer.setPinPosition(pin, namePosition);
93         }
94
95         private void pinRemoved(Pin pin)
96         {
97                 pinNamesRenderer.setPinPosition(pin, null);
98         }
99
100         // high-level access
101
102         @SuppressWarnings({ "static-method", "unused" }) // this method is intended to be overridden
103         protected Object getHighLevelState(Object state, String stateID)
104         {
105                 throw new IllegalArgumentException("No high level state with ID " + stateID);
106         }
107
108         @SuppressWarnings({ "static-method", "unused" }) // this method is intended to be overridden
109         protected Object setHighLevelState(Object lastState, String stateID, Object newHighLevelState)
110         {
111                 throw new IllegalArgumentException("No high level state with ID " + stateID);
112         }
113
114         // logic
115
116         public abstract Object recalculate(Object lastState, Map<String, ReadEnd> readEnds, Map<String, ReadWriteEnd> readWriteEnds);
117
118         // core model binding
119
120         public void setCoreModelBindingAndResetState(AtomicReference<Object> state, Runnable recalculate)
121         {
122                 this.state = state;
123                 this.recalculate = recalculate;
124         }
125
126         // "graphical" operations
127
128         @Override
129         public void render(GeneralGC gc, Rectangle visibleRegion)
130         {
131                 outlineRenderer.render(gc, visibleRegion);
132                 centerTextRenderer.render(gc, visibleRegion);
133                 pinNamesRenderer.render(gc, visibleRegion);
134         }
135
136         // serializing
137
138         @Override
139         public String getIDForSerializing(IdentifyParams idParams)
140         {
141                 return id;
142         }
143
144         // operations no longer supported
145
146         @Override
147         protected void addPin(Pin pin)
148         {
149                 throw new UnsupportedOperationException("Can't add pins without setting usage, call addPin(Pin [, Position]) instead");
150         }
151
152         static
153         {
154                 LogicCoreAdapter.addComponentAdapter(new SimpleRectangularHardcodedModelComponentAdapter());
155         }
156 }