1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 package org.dishevelled.venn.swing;
25
26 import java.awt.GridLayout;
27
28 import java.beans.PropertyChangeEvent;
29 import java.beans.PropertyChangeListener;
30
31 import java.util.List;
32 import java.util.Set;
33
34 import javax.swing.Box;
35 import javax.swing.JList;
36 import javax.swing.JPanel;
37 import javax.swing.JScrollPane;
38 import javax.swing.ListSelectionModel;
39
40 import javax.swing.event.ListSelectionEvent;
41 import javax.swing.event.ListSelectionListener;
42
43 import ca.odell.glazedlists.swing.EventListModel;
44
45 import org.dishevelled.layout.LabelFieldPanel;
46
47 import org.dishevelled.observable.event.SetChangeEvent;
48 import org.dishevelled.observable.event.SetChangeListener;
49
50 import org.dishevelled.venn.BinaryVennModel;
51
52
53
54
55
56
57
58
59 public final class BinaryVennList<E>
60 extends AbstractBinaryVennDiagram<E>
61 {
62
63 private final JList first = new JList();
64
65
66 private final JList second = new JList();
67
68
69 private final JList firstOnly = new JList();
70
71
72 private final JList secondOnly = new JList();
73
74
75 private final JList intersection = new JList();
76
77
78 private final JList union = new JList();
79
80
81 private ObservableSetEventListAdapter<E> firstAdapter;
82
83
84 private ObservableSetEventListAdapter<E> secondAdapter;
85
86
87 private SetEventListAdapter<E> firstOnlyAdapter;
88
89
90 private SetEventListAdapter<E> secondOnlyAdapter;
91
92
93 private SetEventListAdapter<E> intersectionAdapter;
94
95
96 private SetEventListAdapter<E> unionAdapter;
97
98
99 private final PropertyChangeListener modelChange = new PropertyChangeListener()
100 {
101
102 public void propertyChange(final PropertyChangeEvent event)
103 {
104 uninstallListModels((BinaryVennModel<E>) event.getOldValue());
105 installListModels();
106 }
107 };
108
109
110 private final SetChangeListener<E> updateListModels = new SetChangeListener<E>()
111 {
112
113 public void setChanged(final SetChangeEvent<E> event)
114 {
115 updateListModels();
116 }
117 };
118
119
120 private final SetChangeListener<E> updateSelection = new SetChangeListener<E>()
121 {
122
123 public void setChanged(final SetChangeEvent<E> event)
124 {
125 updateSelection();
126 }
127 };
128
129
130
131
132
133 public BinaryVennList()
134 {
135 super();
136 installListModels();
137 installSelectionListeners();
138 layoutComponents();
139 addPropertyChangeListener("model", modelChange);
140 }
141
142
143
144
145
146
147
148
149
150 public BinaryVennList(final String firstLabelText, final Set<? extends E> first,
151 final String secondLabelText, final Set<? extends E> second)
152 {
153 super(firstLabelText, first, secondLabelText, second);
154 installListModels();
155 installSelectionListeners();
156 layoutComponents();
157 addPropertyChangeListener("model", modelChange);
158 }
159
160
161
162
163
164
165 public BinaryVennList(final BinaryVennModel<E> model)
166 {
167 super(model);
168 installListModels();
169 installSelectionListeners();
170 layoutComponents();
171 addPropertyChangeListener("model", modelChange);
172 }
173
174
175
176
177
178
179
180 public void clearSelection()
181 {
182 union.requestFocusInWindow();
183 getModel().selection().clear();
184 }
185
186
187
188
189 public void selectAll()
190 {
191 union.requestFocusInWindow();
192
193 getModel().selection().addAll(getModel().union());
194 }
195
196
197
198
199
200
201
202
203 public JList getFirst()
204 {
205 return first;
206 }
207
208
209
210
211
212
213
214
215 public JList getSecond()
216 {
217 return second;
218 }
219
220
221
222
223
224
225
226
227 public JList getFirstOnly()
228 {
229 return firstOnly;
230 }
231
232
233
234
235
236
237
238
239 public JList getSecondOnly()
240 {
241 return secondOnly;
242 }
243
244
245
246
247
248
249
250
251 public JList getIntersection()
252 {
253 return intersection;
254 }
255
256
257
258
259
260
261
262
263 public JList getUnion()
264 {
265 return union;
266 }
267
268
269
270
271 private void installListModels()
272 {
273 firstAdapter = new ObservableSetEventListAdapter<E>(getModel().first());
274 first.setModel(new EventListModel<E>(firstAdapter));
275 secondAdapter = new ObservableSetEventListAdapter<E>(getModel().second());
276 second.setModel(new EventListModel<E>(secondAdapter));
277
278 firstOnlyAdapter = new SetEventListAdapter<E>(getModel().firstOnly());
279 firstOnly.setModel(new EventListModel<E>(firstOnlyAdapter));
280 secondOnlyAdapter = new SetEventListAdapter<E>(getModel().secondOnly());
281 secondOnly.setModel(new EventListModel<E>(secondOnlyAdapter));
282 intersectionAdapter = new SetEventListAdapter<E>(getModel().intersection());
283 intersection.setModel(new EventListModel<E>(intersectionAdapter));
284 unionAdapter = new SetEventListAdapter<E>(getModel().union());
285 union.setModel(new EventListModel<E>(unionAdapter));
286
287 getModel().first().addSetChangeListener(updateListModels);
288 getModel().second().addSetChangeListener(updateListModels);
289 getModel().first().addSetChangeListener(updateSelection);
290 getModel().second().addSetChangeListener(updateSelection);
291 getModel().selection().addSetChangeListener(updateSelection);
292 }
293
294
295
296
297 private void updateListModels()
298 {
299 firstOnlyAdapter.updateEventList();
300 secondOnlyAdapter.updateEventList();
301 intersectionAdapter.updateEventList();
302 unionAdapter.updateEventList();
303 }
304
305
306
307
308
309
310 private void uninstallListModels(final BinaryVennModel<E> oldModel)
311 {
312 firstAdapter.dispose();
313 secondAdapter.dispose();
314 ((EventListModel<E>) first.getModel()).dispose();
315 ((EventListModel<E>) second.getModel()).dispose();
316 ((EventListModel<E>) firstOnly.getModel()).dispose();
317 ((EventListModel<E>) secondOnly.getModel()).dispose();
318 ((EventListModel<E>) intersection.getModel()).dispose();
319 ((EventListModel<E>) union.getModel()).dispose();
320 oldModel.first().removeSetChangeListener(updateListModels);
321 oldModel.second().removeSetChangeListener(updateListModels);
322 oldModel.first().removeSetChangeListener(updateSelection);
323 oldModel.second().removeSetChangeListener(updateSelection);
324 oldModel.selection().removeSetChangeListener(updateSelection);
325 }
326
327
328
329
330 private void installSelectionListeners()
331 {
332 first.addListSelectionListener(new UpdateSelectionView());
333 second.addListSelectionListener(new UpdateSelectionView());
334 firstOnly.addListSelectionListener(new UpdateSelectionView());
335 secondOnly.addListSelectionListener(new UpdateSelectionView());
336 intersection.addListSelectionListener(new UpdateSelectionView());
337 union.addListSelectionListener(new UpdateSelectionView());
338 }
339
340
341 protected void updateContents()
342 {
343
344 }
345
346
347
348
349 private void layoutComponents()
350 {
351 addFinalField(createMainPanel());
352 }
353
354
355
356
357
358
359 private JPanel createMainPanel()
360 {
361 JPanel panel = new JPanel();
362 panel.setLayout(new GridLayout(2, 4, 12, 12));
363
364 LabelFieldPanel f = new LabelFieldPanel();
365 f.addLabel(getFirstLabel());
366 f.addFinalField(new JScrollPane(first));
367 panel.add(f);
368
369 LabelFieldPanel s = new LabelFieldPanel();
370 s.addLabel(getSecondLabel());
371 s.addFinalField(new JScrollPane(second));
372 panel.add(s);
373
374 panel.add(Box.createGlue());
375 panel.add(Box.createGlue());
376
377 LabelFieldPanel fo = new LabelFieldPanel();
378 fo.addLabel(getFirstOnlyLabel());
379 fo.addFinalField(new JScrollPane(firstOnly));
380 panel.add(fo);
381
382 LabelFieldPanel so = new LabelFieldPanel();
383 so.addLabel(getSecondOnlyLabel());
384 so.addFinalField(new JScrollPane(secondOnly));
385 panel.add(so);
386
387 LabelFieldPanel n = new LabelFieldPanel();
388 n.addLabel(getIntersectionLabel());
389 n.addFinalField(new JScrollPane(intersection));
390 panel.add(n);
391
392 LabelFieldPanel u = new LabelFieldPanel();
393 u.addLabel(getUnionLabel());
394 u.addFinalField(new JScrollPane(union));
395 panel.add(u);
396
397 return panel;
398 }
399
400
401
402
403 private void updateSelection()
404 {
405 if (getModel().selection().isEmpty())
406 {
407 clearSelection(first);
408 clearSelection(second);
409 clearSelection(firstOnly);
410 clearSelection(secondOnly);
411 clearSelection(intersection);
412 clearSelection(union);
413 }
414 else
415 {
416
417 for (E e : getModel().selection())
418 {
419 addToSelection(getModel().first(), first, firstAdapter, e);
420 addToSelection(getModel().second(), second, secondAdapter, e);
421 addToSelection(getModel().firstOnly(), firstOnly, firstOnlyAdapter, e);
422 addToSelection(getModel().secondOnly(), secondOnly, secondOnlyAdapter, e);
423 addToSelection(getModel().intersection(), intersection, intersectionAdapter, e);
424 addToSelection(getModel().union(), union, unionAdapter, e);
425 }
426
427 removeFromSelection(getModel().first(), first, firstAdapter);
428 removeFromSelection(getModel().second(), second, secondAdapter);
429 removeFromSelection(getModel().firstOnly(), firstOnly, firstOnlyAdapter);
430 removeFromSelection(getModel().secondOnly(), secondOnly, secondOnlyAdapter);
431 removeFromSelection(getModel().intersection(), intersection, intersectionAdapter);
432 removeFromSelection(getModel().union(), union, unionAdapter);
433 }
434 }
435
436
437
438
439
440
441 private void clearSelection(final JList list)
442 {
443 if (!list.isFocusOwner())
444 {
445 list.clearSelection();
446 }
447 }
448
449
450
451
452
453
454
455
456
457
458 private void addToSelection(final Set<E> model, final JList list, final List<E> adapter, final E e)
459 {
460 if (!list.isFocusOwner() && model.contains(e))
461 {
462 int index = adapter.indexOf(e);
463 list.getSelectionModel().addSelectionInterval(index, index);
464 }
465 }
466
467
468
469
470
471
472
473
474
475 private void removeFromSelection(final Set<E> model, final JList list, final List<E> adapter)
476 {
477 if (!list.isFocusOwner())
478 {
479
480 for (E e : model)
481 {
482 if (!getModel().selection().contains(e))
483 {
484 int index = adapter.indexOf(e);
485 list.getSelectionModel().removeSelectionInterval(index, index);
486 }
487 }
488 }
489 }
490
491
492
493
494 private class UpdateSelectionView implements ListSelectionListener
495 {
496
497 public void valueChanged(final ListSelectionEvent event)
498 {
499 JList list = (JList) event.getSource();
500 if (list.isFocusOwner() && !event.getValueIsAdjusting())
501 {
502 ListSelectionModel selectionModel = list.getSelectionModel();
503 for (int index = event.getFirstIndex(); index < (event.getLastIndex() + 1); index++)
504 {
505 E e = (E) list.getModel().getElementAt(index);
506 if (selectionModel.isSelectedIndex(index))
507 {
508 if (!getModel().selection().contains(e))
509 {
510 getModel().selection().add(e);
511 }
512 }
513 else
514 {
515 if (getModel().selection().contains(e))
516 {
517 getModel().selection().remove(e);
518 }
519 }
520 }
521 }
522
523
524
525 }
526 }
527 }