cf9735aebe524e131deab3519b43b4a8d08e6815
[Mograsim.git] /
1 package net.mograsim.logic.model.model.components.atomic;
2
3 import org.eclipse.swt.graphics.Color;
4
5 import net.haspamelodica.swt.helper.gcs.GeneralGC;
6 import net.haspamelodica.swt.helper.swtobjectwrappers.Font;
7 import net.haspamelodica.swt.helper.swtobjectwrappers.Point;
8 import net.haspamelodica.swt.helper.swtobjectwrappers.Rectangle;
9 import net.mograsim.logic.core.LogicObserver;
10 import net.mograsim.logic.core.components.CoreManualSwitch;
11 import net.mograsim.logic.core.types.Bit;
12 import net.mograsim.logic.core.types.BitVector;
13 import net.mograsim.logic.core.types.BitVectorFormatter;
14 import net.mograsim.logic.model.model.LogicModelModifiable;
15 import net.mograsim.logic.model.model.components.ModelComponent;
16 import net.mograsim.logic.model.model.wires.Pin;
17 import net.mograsim.logic.model.model.wires.PinUsage;
18 import net.mograsim.logic.model.modeladapter.LogicCoreAdapter;
19 import net.mograsim.logic.model.modeladapter.componentadapters.ManualSwitchAdapter;
20 import net.mograsim.logic.model.serializing.IdentifyParams;
21 import net.mograsim.logic.model.serializing.IndirectModelComponentCreator;
22 import net.mograsim.logic.model.snippets.HighLevelStateHandler;
23 import net.mograsim.preferences.Preferences;
24
25 public class ModelManualSwitch extends ModelComponent
26 {
27         private static final double width = 20;
28         private static final double height = 15;
29         private static final double fontHeight = 5;
30         private static final double heightMiniButtons = 4; // 0 is disabled
31
32         public final int logicWidth;
33         private final Pin outputPin;
34
35         private final LogicObserver logicObs;
36         private CoreManualSwitch manualSwitch;
37
38         public ModelManualSwitch(LogicModelModifiable model, int logicWidth)
39         {
40                 this(model, logicWidth, null);
41         }
42
43         public ModelManualSwitch(LogicModelModifiable model, int logicWidth, String name)
44         {
45                 super(model, name, false);
46                 this.logicWidth = logicWidth;
47                 logicObs = (i) -> model.requestRedraw();
48
49                 setSize(width, height);
50                 addPin(this.outputPin = new Pin(model, this, "", logicWidth, PinUsage.OUTPUT, width, height / 2));
51
52                 setHighLevelStateHandler(new HighLevelStateHandler()
53                 {
54                         @Override
55                         public Object getHighLevelState(String stateID)
56                         {
57                                 switch (stateID)
58                                 {
59                                 case "out":
60                                         if (manualSwitch != null)
61                                                 return manualSwitch.getValues();
62                                         return null;
63                                 default:
64                                         throw new IllegalArgumentException("No high level state with ID " + stateID);
65                                 }
66                         }
67
68                         @Override
69                         public void setHighLevelState(String stateID, Object newState)
70                         {
71                                 switch (stateID)
72                                 {
73                                 case "out":
74                                         if (manualSwitch != null)
75                                                 manualSwitch.setState((BitVector) newState);
76                                         break;
77                                 default:
78                                         throw new IllegalArgumentException("No high level state with ID " + stateID);
79                                 }
80                         }
81
82                         @Override
83                         public String getIDForSerializing(IdentifyParams idParams)
84                         {
85                                 return null;
86                         }
87
88                         @Override
89                         public Object getParamsForSerializing(IdentifyParams idParams)
90                         {
91                                 return null;
92                         }
93                 });
94
95                 init();
96         }
97
98         @Override
99         public void render(GeneralGC gc, Rectangle visibleRegion)
100         {
101                 Color foreground = Preferences.current().getColor("net.mograsim.logic.model.color.foreground");
102                 if (foreground != null)
103                         gc.setForeground(foreground);
104                 gc.drawRectangle(getBounds());
105                 String label = BitVectorFormatter.formatAsString(manualSwitch == null ? null : manualSwitch.getValues());
106                 Font oldFont = gc.getFont();
107                 Font labelFont = new Font(oldFont.getName(), fontHeight, oldFont.getStyle());
108                 gc.setFont(labelFont);
109                 Point textExtent = gc.textExtent(label);
110                 Color textColor = Preferences.current().getColor("net.mograsim.logic.model.color.text");
111                 if (textColor != null)
112                         gc.setForeground(textColor);
113                 gc.drawText(label, getPosX() + (width - textExtent.x) / 2, getPosY() + (height - textExtent.y) / 2, true);
114                 gc.setFont(oldFont);
115
116                 if (manualSwitch != null && logicWidth > 1 && heightMiniButtons > 0 && visibleRegion.y < getPosY() + heightMiniButtons)
117                 {
118                         double x = getPosX();
119                         double y = getPosY();
120                         gc.drawLine(x, y + heightMiniButtons, x + width, y + heightMiniButtons);
121                         Color c = gc.getBackground();
122                         gc.setBackground(gc.getForeground());
123                         BitVector bv = manualSwitch.getValues();
124                         double part = width / bv.length();
125                         for (int i = 0; i < bv.length(); i++)
126                         {
127                                 double start = x + part * i;
128                                 if (i != 0)
129                                         gc.drawLine(start, y, start, y + heightMiniButtons);
130                                 if (bv.getMSBit(i) == Bit.ONE)
131                                 {
132 //                                      gc.fillRectangle(start, y, part, heightMiniButtons); // alternative, but not always visible what Bit is where 
133                                         gc.drawLine(start, y, start + part, y + heightMiniButtons);
134                                         gc.drawLine(start + part, y, start, y + heightMiniButtons);
135                                 }
136                         }
137                         gc.setBackground(c);
138                 }
139         }
140
141         public void setCoreModelBinding(CoreManualSwitch logicSwitch)
142         {
143                 if (this.manualSwitch != null)
144                         this.manualSwitch.deregisterObserver(logicObs);
145                 this.manualSwitch = logicSwitch;
146                 if (logicSwitch != null)
147                         logicSwitch.registerObserver(logicObs);
148         }
149
150         public boolean hasCoreModelBinding()
151         {
152                 return manualSwitch != null;
153         }
154
155         @Override
156         public boolean clicked(double x, double y)
157         {
158                 if (manualSwitch != null)
159                 {
160                         if (heightMiniButtons > 0 && y - getPosY() < heightMiniButtons)
161                         {
162                                 int part = (int) ((x - getPosX()) * logicWidth / width);
163                                 manualSwitch.setState(manualSwitch.getValues().withBitChanged(part, Bit::not));
164                         } else
165                         {
166                                 manualSwitch.toggle();
167                         }
168                 }
169                 return true;
170         }
171
172         public CoreManualSwitch getManualSwitch()
173         {
174                 return manualSwitch;
175         }
176
177         public Pin getOutputPin()
178         {
179                 return outputPin;
180         }
181
182         @Override
183         public String getIDForSerializing(IdentifyParams idParams)
184         {
185                 return "ManualSwitch";
186         }
187
188         @Override
189         public Integer getParamsForSerializing(IdentifyParams idParams)
190         {
191                 return logicWidth;
192         }
193
194         static
195         {
196                 LogicCoreAdapter.addComponentAdapter(new ManualSwitchAdapter());
197                 IndirectModelComponentCreator.setComponentSupplier(ModelManualSwitch.class.getName(),
198                                 (m, p, n) -> new ModelManualSwitch(m, p.getAsInt(), n));
199         }
200 }