Renamed ViewModel to LogicModel
[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.name))
55                         throw new IllegalStateException("Don't add the same component twice!");
56                 components.put(component.name, component);
57                 componentDestroyFunctions.put(component.name, 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.name).run();
70                 if (!components.containsKey(component.name))
71                         throw new IllegalStateException("Don't remove the same component twice!");
72                 components.remove(component.name);
73                 callComponentRemovedListeners(component);
74                 requestRedraw();
75         }
76
77         /**
78          * Adds the given wire to the list of wires and calls all wireAddedListeners.
79          * 
80          * @author Daniel Kirschten
81          */
82         protected void wireCreated(ModelWire wire, Runnable destroyed)
83         {
84                 if (wires.containsKey(wire.name))
85                         throw new IllegalStateException("Don't add the same wire twice!");
86                 wires.put(wire.name, wire);
87                 wireDestroyFunctions.put(wire.name, destroyed);
88                 callWireAddedListeners(wire);
89                 requestRedraw();
90         }
91
92         /**
93          * Destroys the given wire, removes it from the list of wires and calls all wireRemovedListeners.
94          * 
95          * @author Daniel Kirschten
96          */
97         protected void destroyWire(ModelWire wire)
98         {
99                 wireDestroyFunctions.get(wire.name).run();
100                 if (!wires.containsKey(wire.name))
101                         throw new IllegalStateException("Don't remove the same wire twice!");
102                 wires.remove(wire.name);
103                 callWireRemovedListeners(wire);
104                 requestRedraw();
105         }
106
107         public Map<String, ModelComponent> getComponentsByName()
108         {
109                 return componentsUnmodifiable;
110         }
111
112         public Map<String, ModelWire> getWiresByName()
113         {
114                 return wiresUnmodifiable;
115         }
116
117         // @formatter:off
118         public void addComponentAddedListener         (Consumer<? super ModelComponent> listener) {componentAddedListeners      .add   (listener);}
119         public void addComponentRemovedListener       (Consumer<? super ModelComponent> listener) {componentRemovedListeners    .add   (listener);}
120         public void addWireAddedListener              (Consumer<? super ModelWire     > listener) {wireAddedListeners           .add   (listener);}
121         public void addWireRemovedListener            (Consumer<? super ModelWire     > listener) {wireRemovedListeners         .add   (listener);}
122         public void addRedrawHandlerChangedListener   (Consumer<? super Runnable    > listener) {redrawHandlerChangedListeners.add   (listener);}
123
124         public void removeComponentAddedListener      (Consumer<? super ModelComponent> listener) {componentAddedListeners      .remove(listener);}
125         public void removeComponentRemovedListener    (Consumer<? super ModelComponent> listener) {componentRemovedListeners    .remove(listener);}
126         public void removeWireAddedListener           (Consumer<? super ModelWire     > listener) {wireAddedListeners           .remove(listener);}
127         public void removeWireRemovedListener         (Consumer<? super ModelWire     > listener) {wireRemovedListeners         .remove(listener);}
128         public void removeRedrawHandlerChangedListener(Consumer<? super Runnable    > listener) {redrawHandlerChangedListeners.remove(listener);}
129
130         private void callComponentAddedListeners     (ModelComponent c) {componentAddedListeners      .forEach(l -> l.accept(c));}
131         private void callComponentRemovedListeners   (ModelComponent c) {componentRemovedListeners    .forEach(l -> l.accept(c));}
132         private void callWireAddedListeners          (ModelWire      w) {wireAddedListeners           .forEach(l -> l.accept(w));}
133         private void callWireRemovedListeners        (ModelWire      w) {wireRemovedListeners         .forEach(l -> l.accept(w));}
134         private void callRedrawHandlerChangedListener(Runnable     r) {redrawHandlerChangedListeners.forEach(l -> l.accept(r));}
135         // @formatter:on
136
137         public void setRedrawHandler(Runnable handler)
138         {
139                 this.redrawHandler = handler;
140                 callRedrawHandlerChangedListener(handler);
141         }
142
143         public Runnable getRedrawHandler()
144         {
145                 return redrawHandler;
146         }
147
148         public void requestRedraw()
149         {
150                 if (redrawHandler != null)
151                         redrawHandler.run();
152         }
153 }