Renamed logic.ui to logic.model
[Mograsim.git] / net.mograsim.logic.model / src / net / mograsim / logic / model / model / ViewModel.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.GUIComponent;
11 import net.mograsim.logic.model.model.wires.GUIWire;
12
13 public class ViewModel
14 {
15         private final Map<String, GUIComponent> components;
16         private final Map<String, GUIComponent> componentsUnmodifiable;
17         private final List<GUIWire> wires;
18         private final List<GUIWire> wiresUnmodifiable;
19
20         private final List<Consumer<? super GUIComponent>> componentAddedListeners;
21         private final List<Consumer<? super GUIComponent>> componentRemovedListeners;
22         private final List<Consumer<? super GUIWire>> wireAddedListeners;
23         private final List<Consumer<? super GUIWire>> wireRemovedListeners;
24         private final List<Runnable> redrawListeners;
25
26         private final Runnable redrawListenerForSubcomponents;
27
28         protected ViewModel()
29         {
30                 components = new HashMap<>();
31                 componentsUnmodifiable = Collections.unmodifiableMap(components);
32                 wires = new ArrayList<>();
33                 wiresUnmodifiable = Collections.unmodifiableList(wires);
34
35                 componentAddedListeners = new ArrayList<>();
36                 componentRemovedListeners = new ArrayList<>();
37                 wireAddedListeners = new ArrayList<>();
38                 wireRemovedListeners = new ArrayList<>();
39                 redrawListeners = new ArrayList<>();
40
41                 redrawListenerForSubcomponents = this::callRedrawListeners;
42         }
43
44         /**
45          * Adds the given component to the list of components and calls all componentAddedListeners. Don't call this method from application
46          * code as it is automatically called in {@link GUIComponent}'s constructor.
47          */
48         protected void componentCreated(GUIComponent component)
49         {
50                 if (components.containsKey(component.name))
51                         throw new IllegalStateException("Don't add the same component twice!");
52                 components.put(component.name, component);
53                 callComponentAddedListeners(component);
54                 component.addRedrawListener(redrawListenerForSubcomponents);
55                 callRedrawListeners();
56         }
57
58         /**
59          * Removes the given component from the list of components and calls all componentRemovedListeners. Don't call this method from
60          * application code as it is automatically called in {@link GUIComponent#destroy()}.
61          */
62         protected void componentDestroyed(GUIComponent component)
63         {
64                 if (!components.containsKey(component.name))
65                         throw new IllegalStateException("Don't remove the same component twice!");
66                 components.remove(component.name);
67                 callComponentRemovedListeners(component);
68                 component.removeRedrawListener(redrawListenerForSubcomponents);
69                 callRedrawListeners();
70         }
71
72         /**
73          * Adds the given wire to the list of wires and calls all wireAddedListeners. Don't call this method from application code as it is
74          * automatically called in {@link GUIWire}'s constructor(s).
75          */
76         protected void wireCreated(GUIWire wire)
77         {
78                 if (wires.contains(wire))
79                         throw new IllegalStateException("Don't add the same wire twice!");
80                 wires.add(wire);
81                 callWireAddedListeners(wire);
82                 wire.addRedrawListener(redrawListenerForSubcomponents);
83                 callRedrawListeners();
84         }
85
86         /**
87          * Removes the given wire from the list of wires and calls all wireRemovedListeners. Don't call this method from application code as it
88          * is automatically called in {@link GUIWire#destroy()}.
89          */
90         protected void wireDestroyed(GUIWire wire)
91         {
92                 if (!wires.contains(wire))
93                         throw new IllegalStateException("Don't remove the same wire twice!");
94                 wires.remove(wire);
95                 callWireRemovedListeners(wire);
96                 wire.removeRedrawListener(redrawListenerForSubcomponents);
97                 callRedrawListeners();
98         }
99
100         public Map<String, GUIComponent> getComponentsByName()
101         {
102                 return componentsUnmodifiable;
103         }
104
105         public List<GUIWire> getWires()
106         {
107                 return wiresUnmodifiable;
108         }
109
110         // @formatter:off
111         public void addComponentAddedListener     (Consumer<? super GUIComponent> listener) {componentAddedListeners  .add   (listener);}
112         public void addComponentRemovedListener   (Consumer<? super GUIComponent> listener) {componentRemovedListeners.add   (listener);}
113         public void addWireAddedListener          (Consumer<? super GUIWire     > listener) {wireAddedListeners       .add   (listener);}
114         public void addWireRemovedListener        (Consumer<? super GUIWire     > listener) {wireRemovedListeners     .add   (listener);}
115         public void addRedrawListener             (Runnable                       listener) {redrawListeners          .add   (listener);}
116
117         public void removeComponentAddedListener  (Consumer<? super GUIComponent> listener) {componentAddedListeners  .remove(listener);}
118         public void removeComponentRemovedListener(Consumer<? super GUIComponent> listener) {componentRemovedListeners.remove(listener);}
119         public void removeWireAddedListener       (Consumer<? super GUIWire     > listener) {wireAddedListeners       .remove(listener);}
120         public void removeWireRemovedListener     (Consumer<? super GUIWire     > listener) {wireRemovedListeners     .remove(listener);}
121         public void removeRedrawListener          (Runnable                       listener) {redrawListeners          .remove(listener);}
122
123         private void callComponentAddedListeners  (GUIComponent c) {componentAddedListeners  .forEach(l -> l.accept(c));}
124         private void callComponentRemovedListeners(GUIComponent c) {componentRemovedListeners.forEach(l -> l.accept(c));}
125         private void callWireAddedListeners       (GUIWire w     ) {wireAddedListeners       .forEach(l -> l.accept(w));}
126         private void callWireRemovedListeners     (GUIWire w     ) {wireRemovedListeners     .forEach(l -> l.accept(w));}
127         private void callRedrawListeners          (              ) {redrawListeners          .forEach(l -> l.run(    ));}
128         // @formatter:on
129 }