8971285a59b48b29fcae1c464b0caf1117bbc4fc
[Mograsim.git] /
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)
42         {
43                 this(model, id, name, centerText, true);
44         }
45
46         public SimpleRectangularHardcodedModelComponent(LogicModelModifiable model, String id, String name, String centerText, boolean callInit)
47         {
48                 super(model, name, false);
49                 this.id = id;
50                 this.outlineRenderer = new DefaultOutlineRenderer(this);
51                 CenteredTextParams centeredTextParams = new CenteredTextParams();
52                 centeredTextParams.text = centerText;
53                 centeredTextParams.fontHeight = centerTextHeight;
54                 this.centerTextRenderer = new CenteredTextSymbolRenderer(this, centeredTextParams);
55                 PinNamesParams pinNamesParams = new PinNamesParams();
56                 pinNamesParams.pinLabelHeight = pinNamesHeight;
57                 pinNamesParams.pinLabelMargin = pinNamesMargin;
58                 this.pinNamesRenderer = new PinNamesSymbolRenderer(this, pinNamesParams);
59                 addPinRemovedListener(this::pinRemoved);
60                 setHighLevelStateHandler(new HighLevelStateHandler()
61                 {
62                         @Override
63                         public String getIDForSerializing(IdentifyParams idParams)
64                         {
65                                 return null;// we don't need to serialize this; it's implicit since we are a SimpleRectangularHardcodedModelComponent
66                         }
67
68                         @Override
69                         public Object getParamsForSerializing(IdentifyParams idParams)
70                         {
71                                 return null;
72                         }
73
74                         @Override
75                         public Object getHighLevelState(String stateID)
76                         {
77                                 return SimpleRectangularHardcodedModelComponent.this.getHighLevelState(state.get(), stateID);
78                         }
79
80                         @Override
81                         public void setHighLevelState(String stateID, Object newState)
82                         {
83                                 state.updateAndGet(s -> SimpleRectangularHardcodedModelComponent.this.setHighLevelState(s, stateID, newState));
84                                 recalculate.run();
85                         }
86                 });
87
88                 if (callInit)
89                         init();
90         }
91
92         // pins
93
94         protected void addPin(Pin pin, Position namePosition)
95         {
96                 super.addPin(pin); // do this first to catch errors
97                 pinNamesRenderer.setPinPosition(pin, namePosition);
98         }
99
100         private void pinRemoved(Pin pin)
101         {
102                 pinNamesRenderer.setPinPosition(pin, null);
103         }
104
105         // high-level access
106
107         @SuppressWarnings({ "static-method", "unused" }) // this method is intended to be overridden
108         protected Object getHighLevelState(Object state, String stateID)
109         {
110                 throw new IllegalArgumentException("No high level state with ID " + stateID);
111         }
112
113         @SuppressWarnings({ "static-method", "unused" }) // this method is intended to be overridden
114         protected Object setHighLevelState(Object lastState, String stateID, Object newHighLevelState)
115         {
116                 throw new IllegalArgumentException("No high level state with ID " + stateID);
117         }
118
119         // logic
120
121         public abstract Object recalculate(Object lastState, Map<String, ReadEnd> readEnds, Map<String, ReadWriteEnd> readWriteEnds);
122
123         // core model binding
124
125         public void setCoreModelBindingAndResetState(AtomicReference<Object> state, Runnable recalculate)
126         {
127                 this.state = state;
128                 this.recalculate = recalculate;
129         }
130
131         // "graphical" operations
132
133         @Override
134         public void render(GeneralGC gc, Rectangle visibleRegion)
135         {
136                 outlineRenderer.render(gc, visibleRegion);
137                 centerTextRenderer.render(gc, visibleRegion);
138                 pinNamesRenderer.render(gc, visibleRegion);
139         }
140
141         // serializing
142
143         @Override
144         public String getIDForSerializing(IdentifyParams idParams)
145         {
146                 return id;
147         }
148
149         // operations no longer supported
150
151         @Override
152         protected void addPin(Pin pin)
153         {
154                 throw new UnsupportedOperationException("Can't add pins without setting usage, call addPin(Pin [, Position]) instead");
155         }
156
157         static
158         {
159                 LogicCoreAdapter.addComponentAdapter(new SimpleRectangularHardcodedModelComponentAdapter());
160         }
161 }