839d5f9af0cb9956a833c7df7b0c483b75273cc8
[Mograsim.git] / net.mograsim.logic.model / src / net / mograsim / logic / model / model / LogicModel.java
1 package net.mograsim.logic.model.model;
2
3 import java.util.ArrayList;
4 import java.util.Collections;
5 import java.util.HashMap;
6 import java.util.List;
7 import java.util.Map;
8 import java.util.function.Consumer;
9
10 import net.mograsim.logic.model.model.components.ModelComponent;
11 import net.mograsim.logic.model.model.wires.ModelWire;
12
13 public class LogicModel
14 {
15         private final Map<String, ModelComponent> components;
16         private final Map<String, Runnable> componentDestroyFunctions;
17         private final Map<String, ModelComponent> componentsUnmodifiable;
18         private final Map<String, ModelWire> wires;
19         private final Map<String, Runnable> wireDestroyFunctions;
20         private final Map<String, ModelWire> wiresUnmodifiable;
21
22         private final List<Consumer<? super ModelComponent>> componentAddedListeners;
23         private final List<Consumer<? super ModelComponent>> componentRemovedListeners;
24         private final List<Consumer<? super ModelWire>> wireAddedListeners;
25         private final List<Consumer<? super ModelWire>> wireRemovedListeners;
26         private final List<Consumer<? super Runnable>> redrawHandlerChangedListeners;
27
28         private Runnable redrawHandler;
29
30         protected LogicModel()
31         {
32                 components = new HashMap<>();
33                 componentDestroyFunctions = new HashMap<>();
34                 componentsUnmodifiable = Collections.unmodifiableMap(components);
35                 wires = new HashMap<>();
36                 wireDestroyFunctions = new HashMap<>();
37                 wiresUnmodifiable = Collections.unmodifiableMap(wires);
38
39                 componentAddedListeners = new ArrayList<>();
40                 componentRemovedListeners = new ArrayList<>();
41                 wireAddedListeners = new ArrayList<>();
42                 wireRemovedListeners = new ArrayList<>();
43                 redrawHandlerChangedListeners = new ArrayList<>();
44         }
45
46         /**
47          * Adds the given component to the list of components and calls all componentAddedListeners. Don't call this method from application
48          * code as it is automatically called in {@link ModelComponent}'s constructor.
49          * 
50          * @author Daniel Kirschten
51          */
52         protected void componentCreated(ModelComponent component, Runnable destroyed)
53         {
54                 if (components.containsKey(component.getName()))
55                         throw new IllegalStateException("Don't add the same component twice!");
56                 components.put(component.getName(), component);
57                 componentDestroyFunctions.put(component.getName(), destroyed);
58                 callComponentAddedListeners(component);
59                 requestRedraw();
60         }
61
62         /**
63          * Destroyes the given component, removes it from the list of components and calls all componentRemovedListeners.
64          * 
65          * @author Daniel Kirschten
66          */
67         protected void destroyComponent(ModelComponent component)
68         {
69                 componentDestroyFunctions.get(component.getName()).run();
70                 if (!components.containsKey(component.getName()))
71                         throw new IllegalStateException("Don't remove the same component twice!");
72                 components.remove(component.getName());
73                 callComponentRemovedListeners(component);
74                 requestRedraw();
75         }
76
77         /**
78          * Adds the given wire to the list of wires and calls all wireAddedListeners. Don't call this method from application code as it is
79          * automatically called in {@link ModelWire}'s constructor.
80          * 
81          * @author Daniel Kirschten
82          */
83         protected void wireCreated(ModelWire wire, Runnable destroyed)
84         {
85                 if (wires.containsKey(wire.name))
86                         throw new IllegalStateException("Don't add the same wire twice!");
87                 wires.put(wire.name, wire);
88                 wireDestroyFunctions.put(wire.name, destroyed);
89                 callWireAddedListeners(wire);
90                 requestRedraw();
91         }
92
93         /**
94          * Destroys the given wire, removes it from the list of wires and calls all wireRemovedListeners.
95          * 
96          * @author Daniel Kirschten
97          */
98         protected void destroyWire(ModelWire wire)
99         {
100                 wireDestroyFunctions.get(wire.name).run();
101                 if (!wires.containsKey(wire.name))
102                         throw new IllegalStateException("Don't remove the same wire twice!");
103                 wires.remove(wire.name);
104                 callWireRemovedListeners(wire);
105                 requestRedraw();
106         }
107
108         public Map<String, ModelComponent> getComponentsByName()
109         {
110                 return componentsUnmodifiable;
111         }
112
113         public Map<String, ModelWire> getWiresByName()
114         {
115                 return wiresUnmodifiable;
116         }
117
118         // @formatter:off
119         public void addComponentAddedListener         (Consumer<? super ModelComponent> listener) {componentAddedListeners      .add   (listener);}
120         public void addComponentRemovedListener       (Consumer<? super ModelComponent> listener) {componentRemovedListeners    .add   (listener);}
121         public void addWireAddedListener              (Consumer<? super ModelWire     > listener) {wireAddedListeners           .add   (listener);}
122         public void addWireRemovedListener            (Consumer<? super ModelWire     > listener) {wireRemovedListeners         .add   (listener);}
123         public void addRedrawHandlerChangedListener   (Consumer<? super Runnable    > listener) {redrawHandlerChangedListeners.add   (listener);}
124
125         public void removeComponentAddedListener      (Consumer<? super ModelComponent> listener) {componentAddedListeners      .remove(listener);}
126         public void removeComponentRemovedListener    (Consumer<? super ModelComponent> listener) {componentRemovedListeners    .remove(listener);}
127         public void removeWireAddedListener           (Consumer<? super ModelWire     > listener) {wireAddedListeners           .remove(listener);}
128         public void removeWireRemovedListener         (Consumer<? super ModelWire     > listener) {wireRemovedListeners         .remove(listener);}
129         public void removeRedrawHandlerChangedListener(Consumer<? super Runnable    > listener) {redrawHandlerChangedListeners.remove(listener);}
130
131         private void callComponentAddedListeners     (ModelComponent c) {componentAddedListeners      .forEach(l -> l.accept(c));}
132         private void callComponentRemovedListeners   (ModelComponent c) {componentRemovedListeners    .forEach(l -> l.accept(c));}
133         private void callWireAddedListeners          (ModelWire      w) {wireAddedListeners           .forEach(l -> l.accept(w));}
134         private void callWireRemovedListeners        (ModelWire      w) {wireRemovedListeners         .forEach(l -> l.accept(w));}
135         private void callRedrawHandlerChangedListener(Runnable     r) {redrawHandlerChangedListeners.forEach(l -> l.accept(r));}
136         // @formatter:on
137
138         public void setRedrawHandler(Runnable handler)
139         {
140                 this.redrawHandler = handler;
141                 callRedrawHandlerChangedListener(handler);
142         }
143
144         public Runnable getRedrawHandler()
145         {
146                 return redrawHandler;
147         }
148
149         public void requestRedraw()
150         {
151                 if (redrawHandler != null)
152                         redrawHandler.run();
153         }
154 }