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