Browse Source

Merge pull request #644 from csmith/master

Make the WindowManager track windows.
pull/645/head
Greg Holmes 8 years ago
parent
commit
f1689d71f3
2 changed files with 76 additions and 44 deletions
  1. 46
    25
      src/com/dmdirc/ui/WindowManager.java
  2. 30
    19
      test/com/dmdirc/ui/WindowManagerTest.java

+ 46
- 25
src/com/dmdirc/ui/WindowManager.java View File

@@ -30,8 +30,13 @@ import com.dmdirc.interfaces.WindowModel;
30 30
 import com.dmdirc.interfaces.ui.FrameListener;
31 31
 import com.dmdirc.util.collections.ListenerList;
32 32
 
33
+import com.google.common.collect.ArrayListMultimap;
34
+import com.google.common.collect.Multimap;
35
+
33 36
 import java.util.Collection;
34 37
 import java.util.Collections;
38
+import java.util.HashMap;
39
+import java.util.Map;
35 40
 import java.util.Optional;
36 41
 import java.util.concurrent.CopyOnWriteArrayList;
37 42
 
@@ -42,7 +47,6 @@ import net.engio.mbassy.listener.Handler;
42 47
 
43 48
 import static com.google.common.base.Preconditions.checkArgument;
44 49
 import static com.google.common.base.Preconditions.checkNotNull;
45
-import static com.google.common.base.Preconditions.checkState;
46 50
 
47 51
 /**
48 52
  * The WindowManager maintains a list of all open windows, and their parent/child relations.
@@ -52,6 +56,10 @@ public class WindowManager {
52 56
 
53 57
     /** A list of root windows. */
54 58
     private final Collection<WindowModel> rootWindows = new CopyOnWriteArrayList<>();
59
+    /** Mapping of windows to their parents. */
60
+    private final Map<WindowModel, WindowModel> parents = new HashMap<>();
61
+    /** Mapping of parents to their children. */
62
+    private final Multimap<WindowModel, WindowModel> children = ArrayListMultimap.create();
55 63
     /** A list of frame listeners. */
56 64
     private final ListenerList listeners = new ListenerList();
57 65
 
@@ -90,7 +98,7 @@ public class WindowManager {
90 98
         for (WindowModel root : rootWindows) {
91 99
             frameListener.addWindow(root, true);
92 100
 
93
-            for (WindowModel child : root.getChildren()) {
101
+            for (WindowModel child : getChildren(root)) {
94 102
                 fireAddWindow(frameListener, root, child);
95 103
             }
96 104
         }
@@ -108,7 +116,7 @@ public class WindowManager {
108 116
             final WindowModel parent, final WindowModel child) {
109 117
         listener.addWindow(parent, child, true);
110 118
 
111
-        for (WindowModel grandchild : child.getChildren()) {
119
+        for (WindowModel grandchild : getChildren(child)) {
112 120
             fireAddWindow(listener, child, grandchild);
113 121
         }
114 122
     }
@@ -122,6 +130,26 @@ public class WindowManager {
122 130
         listeners.remove(FrameListener.class, frameListener);
123 131
     }
124 132
 
133
+    /**
134
+     * Gets the parent of the specified window, if there is one.
135
+     *
136
+     * @param window The window to find the parent of.
137
+     * @return The window's parent, if one exists.
138
+     */
139
+    public Optional<WindowModel> getParent(final WindowModel window) {
140
+        return Optional.ofNullable(parents.get(window));
141
+    }
142
+
143
+    /**
144
+     * Gets the collection of children belonging to the specified window.
145
+     *
146
+     * @param window The window to find the children on.
147
+     * @return A (possibly empty) collection of children of the given window.
148
+     */
149
+    public Collection<WindowModel> getChildren(final WindowModel window) {
150
+        return Collections.unmodifiableCollection(children.get(window));
151
+    }
152
+
125 153
     /**
126 154
      * Adds a new root window to the Window Manager.
127 155
      *
@@ -167,8 +195,7 @@ public class WindowManager {
167 195
      * @since 0.6.4
168 196
      */
169 197
     @Precondition("The specified Windows are not null")
170
-    public void addWindow(final WindowModel parent,
171
-            final WindowModel child) {
198
+    public void addWindow(final WindowModel parent, final WindowModel child) {
172 199
         addWindow(parent, child, true);
173 200
     }
174 201
 
@@ -186,13 +213,14 @@ public class WindowManager {
186 213
         "The specified parent is in the window hierarchy already",
187 214
         "The specified child is NOT in the window hierarchy already"
188 215
     })
189
-    public void addWindow(final WindowModel parent,
190
-            final WindowModel child, final boolean focus) {
216
+    public void addWindow(final WindowModel parent, final WindowModel child, final boolean focus) {
191 217
         checkNotNull(parent);
192 218
         checkArgument(isInHierarchy(parent));
193 219
         checkNotNull(child);
194 220
 
195 221
         parent.addChild(child);
222
+        parents.put(child, parent);
223
+        children.put(parent, child);
196 224
 
197 225
         fireAddWindow(parent, child, focus);
198 226
     }
@@ -207,12 +235,7 @@ public class WindowManager {
207 235
      * @return True if the target is in the hierarchy, false otherwise
208 236
      */
209 237
     protected boolean isInHierarchy(final WindowModel target) {
210
-        if (rootWindows.contains(target)) {
211
-            return true;
212
-        }
213
-
214
-        final Optional<WindowModel> parent = target.getParent();
215
-        return parent.isPresent() && isInHierarchy(parent.get());
238
+        return rootWindows.contains(target) || parents.containsKey(target);
216 239
     }
217 240
 
218 241
     /**
@@ -232,16 +255,17 @@ public class WindowManager {
232 255
         checkNotNull(window);
233 256
         checkArgument(isInHierarchy(window));
234 257
 
235
-        window.getChildren().forEach(WindowModel::close);
258
+        children.get(window).forEach(WindowModel::close);
259
+        children.removeAll(window);
236 260
 
237 261
         if (rootWindows.contains(window)) {
238 262
             fireDeleteWindow(window);
239 263
             rootWindows.remove(window);
240 264
         } else {
241
-            final Optional<WindowModel> parent = window.getParent();
242
-            checkState(parent.isPresent());
243
-            fireDeleteWindow(parent.get(), window);
244
-            parent.get().removeChild(window);
265
+            final WindowModel parent = parents.get(window);
266
+            fireDeleteWindow(parent, window);
267
+            parent.removeChild(window);
268
+            parents.remove(parent);
245 269
         }
246 270
     }
247 271
 
@@ -278,7 +302,7 @@ public class WindowManager {
278 302
         checkNotNull(parent);
279 303
         checkNotNull(name);
280 304
 
281
-        return findCustomWindow(parent.getChildren(), name);
305
+        return findCustomWindow(getChildren(parent), name);
282 306
     }
283 307
 
284 308
     /**
@@ -290,11 +314,9 @@ public class WindowManager {
290 314
      *
291 315
      * @return The custom window if found, or null otherwise
292 316
      */
293
-    private WindowModel findCustomWindow(final Iterable<WindowModel> windows,
294
-            final String name) {
317
+    private WindowModel findCustomWindow(final Iterable<WindowModel> windows, final String name) {
295 318
         for (WindowModel window : windows) {
296
-            if (window instanceof CustomWindow
297
-                    && window.getName().equals(name)) {
319
+            if (window instanceof CustomWindow && window.getName().equals(name)) {
298 320
                 return window;
299 321
             }
300 322
         }
@@ -356,8 +378,7 @@ public class WindowManager {
356 378
      * @param parent The parent window
357 379
      * @param child  The child window that was removed
358 380
      */
359
-    private void fireDeleteWindow(final WindowModel parent,
360
-            final WindowModel child) {
381
+    private void fireDeleteWindow(final WindowModel parent, final WindowModel child) {
361 382
         for (FrameListener listener : listeners.get(FrameListener.class)) {
362 383
             listener.delWindow(parent, child);
363 384
         }

+ 30
- 19
test/com/dmdirc/ui/WindowManagerTest.java View File

@@ -86,6 +86,30 @@ public class WindowManagerTest {
86 86
         verify(frameListener).addWindow(same(container), same(child), eq(true));
87 87
     }
88 88
 
89
+    @Test
90
+    public void testGetParent() {
91
+        manager.addWindow(container);
92
+        manager.addListener(frameListener);
93
+        manager.addWindow(container, child);
94
+
95
+        assertEquals(Optional.of(container), manager.getParent(child));
96
+        assertEquals(Optional.empty(), manager.getParent(container));
97
+    }
98
+
99
+    @Test
100
+    public void testGetChildren() {
101
+        manager.addWindow(container);
102
+        manager.addListener(frameListener);
103
+        manager.addWindow(container, child);
104
+        manager.addWindow(container, grandchild);
105
+
106
+        assertEquals(2, manager.getChildren(container).size());
107
+        assertTrue(manager.getChildren(container).contains(child));
108
+        assertTrue(manager.getChildren(container).contains(grandchild));
109
+        assertEquals(0, manager.getChildren(child).size());
110
+        assertEquals(0, manager.getChildren(grandchild).size());
111
+    }
112
+
89 113
     @Test
90 114
     public void testRemoveRoot() {
91 115
         manager.addWindow(container);
@@ -102,8 +126,6 @@ public class WindowManagerTest {
102 126
         manager.addWindow(container, child);
103 127
         manager.addListener(frameListener);
104 128
 
105
-        when(child.getParent()).thenReturn(Optional.of(container));
106
-
107 129
         manager.removeWindow(child);
108 130
 
109 131
         verify(frameListener, never()).addWindow(anyObject(), anyBoolean());
@@ -134,10 +156,9 @@ public class WindowManagerTest {
134 156
 
135 157
     @Test
136 158
     public void testAddListenerAndSync() {
137
-        when(container.getChildren()).thenReturn(Arrays.asList(child));
138
-        when(child.getChildren()).thenReturn(Arrays.asList(grandchild));
139
-
140 159
         manager.addWindow(container);
160
+        manager.addWindow(container, child);
161
+        manager.addWindow(child, grandchild);
141 162
         manager.addListenerAndSync(frameListener);
142 163
 
143 164
         verify(frameListener).addWindow(container, true);
@@ -156,11 +177,9 @@ public class WindowManagerTest {
156 177
 
157 178
     @Test
158 179
     public void testRemoveWindowRootWindowWithChildren() {
159
-        when(container.getChildren()).thenReturn(Arrays.asList(child));
160
-        when(child.getParent()).thenReturn(Optional.of(container));
161
-
162 180
         manager.addListener(frameListener);
163 181
         manager.addWindow(container);
182
+        manager.addWindow(container, child);
164 183
         manager.removeWindow(container);
165 184
 
166 185
         verify(frameListener).delWindow(container);
@@ -169,11 +188,9 @@ public class WindowManagerTest {
169 188
 
170 189
     @Test
171 190
     public void testRemoveChildWindowNoChildren() {
172
-        when(container.getChildren()).thenReturn(Arrays.asList(child));
173
-        when(child.getParent()).thenReturn(Optional.of(container));
174
-
175 191
         manager.addListener(frameListener);
176 192
         manager.addWindow(container);
193
+        manager.addWindow(container, child);
177 194
         manager.removeWindow(child);
178 195
 
179 196
         verify(frameListener).delWindow(container, child);
@@ -182,12 +199,10 @@ public class WindowManagerTest {
182 199
 
183 200
     @Test
184 201
     public void testRemoveChildWindowWithChildren() {
185
-        when(container.getChildren()).thenReturn(Arrays.asList(child));
186
-        when(child.getChildren()).thenReturn(Arrays.asList(grandchild));
187
-        when(child.getParent()).thenReturn(Optional.of(container));
188
-
189 202
         manager.addListener(frameListener);
190 203
         manager.addWindow(container);
204
+        manager.addWindow(container, child);
205
+        manager.addWindow(child, grandchild);
191 206
         manager.removeWindow(child);
192 207
 
193 208
         verify(frameListener).delWindow(container, child);
@@ -236,8 +251,6 @@ public class WindowManagerTest {
236 251
 
237 252
         when(customContainer.getName()).thenReturn("test");
238 253
         when(customChild.getName()).thenReturn("test1");
239
-        when(customContainer.getChildren()).thenReturn(Arrays.asList(
240
-                new WindowModel[]{customChild, }));
241 254
 
242 255
         manager.addWindow(customContainer);
243 256
         manager.addWindow(customContainer, customChild);
@@ -252,8 +265,6 @@ public class WindowManagerTest {
252 265
 
253 266
         when(customContainer.getName()).thenReturn("test");
254 267
         when(customChild.getName()).thenReturn("test1");
255
-        when(customContainer.getChildren()).thenReturn(Arrays.asList(
256
-                new WindowModel[]{customChild, }));
257 268
 
258 269
         manager.addWindow(customContainer);
259 270
         manager.addWindow(customContainer, customChild);

Loading…
Cancel
Save