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.cytoscape;
25
26 import static javax.swing.SwingUtilities.windowForComponent;
27 import static org.dishevelled.venn.cytoscape.VennDiagramsUtils.installCloseKeyBinding;
28 import static org.dishevelled.venn.cytoscape.VennDiagramsUtils.nameOf;
29
30 import java.awt.BorderLayout;
31 import java.awt.Toolkit;
32
33 import java.awt.event.ActionEvent;
34 import java.awt.event.InputEvent;
35 import java.awt.event.KeyEvent;
36
37 import java.awt.geom.Rectangle2D;
38
39 import java.util.ArrayList;
40 import java.util.HashSet;
41 import java.util.List;
42 import java.util.Set;
43
44 import javax.swing.AbstractAction;
45 import javax.swing.Action;
46 import javax.swing.InputMap;
47 import javax.swing.KeyStroke;
48 import javax.swing.JCheckBoxMenuItem;
49 import javax.swing.JComponent;
50 import javax.swing.JDialog;
51 import javax.swing.JList;
52 import javax.swing.JPanel;
53 import javax.swing.JPopupMenu;
54 import javax.swing.JScrollPane;
55 import javax.swing.SwingUtilities;
56
57 import javax.swing.border.EmptyBorder;
58
59 import javax.swing.event.ListSelectionEvent;
60 import javax.swing.event.ListSelectionListener;
61
62 import ca.odell.glazedlists.EventList;
63 import ca.odell.glazedlists.GlazedLists;
64
65 import ca.odell.glazedlists.swing.EventListModel;
66 import ca.odell.glazedlists.swing.EventSelectionModel;
67
68 import com.google.common.base.Joiner;
69
70 import cytoscape.CyNode;
71
72 import cytoscape.groups.CyGroup;
73 import cytoscape.groups.CyGroupChangeListener;
74 import cytoscape.groups.CyGroupManager;
75 import cytoscape.groups.CyGroupViewer;
76
77 import cytoscape.view.CyNetworkView;
78
79 import org.dishevelled.iconbundle.IconBundle;
80 import org.dishevelled.iconbundle.IconSize;
81
82 import org.dishevelled.iconbundle.impl.CachingIconBundle;
83 import org.dishevelled.iconbundle.impl.PNGIconBundle;
84
85 import org.dishevelled.identify.ContextMenuListener;
86 import org.dishevelled.identify.IdentifiableAction;
87 import org.dishevelled.identify.IdButton;
88 import org.dishevelled.identify.IdMenuItem;
89 import org.dishevelled.identify.IdToolBar;
90
91 import org.dishevelled.layout.ButtonPanel;
92 import org.dishevelled.layout.LabelFieldPanel;
93
94 import org.dishevelled.piccolo.venn.BinaryVennNode;
95 import org.dishevelled.piccolo.venn.TernaryVennNode;
96 import org.dishevelled.piccolo.venn.QuaternaryVennNode;
97 import org.dishevelled.piccolo.venn.VennNode;
98
99 import org.dishevelled.venn.VennModel;
100 import org.dishevelled.venn.VennLayout;
101 import org.dishevelled.venn.VennLayouter;
102 import org.dishevelled.venn.VennLayouter.PerformanceHint;
103
104 import org.dishevelled.venn.cytoscape.CyGroupListCellRenderer;
105 import org.dishevelled.venn.model.VennModels;
106
107 import org.dishevelled.venn.swing.BinaryVennList;
108 import org.dishevelled.venn.swing.TernaryVennList;
109 import org.dishevelled.venn.swing.QuaternaryVennList;
110
111 import org.cytoscape.venneuler.VennEulerLayouter;
112
113
114
115
116 final class GroupsView
117 extends JPanel
118 implements CyGroupChangeListener, CyGroupViewer
119 {
120
121 private final EventList<CyGroup> groups;
122
123
124 private final EventList<CyGroup> selected;
125
126
127 private final JList groupList;
128
129
130 private final JPopupMenu contextMenu;
131
132
133 private final IconBundle eulerDiagramIconBundle = new CachingIconBundle(new PNGIconBundle("/org/dishevelled/venn/cytoscape/eulerDiagram"));
134
135
136 private final IdentifiableAction eulerDiagram = new IdentifiableAction("Euler Diagram...", eulerDiagramIconBundle)
137 {
138
139 public void actionPerformed(final ActionEvent event)
140 {
141 if (selected.size() > 1)
142 {
143 eulerDiagram();
144 }
145 }
146 };
147
148
149 private final IconBundle vennDiagramIconBundle = new CachingIconBundle(new PNGIconBundle("/org/dishevelled/venn/cytoscape/vennDiagram"));
150
151
152 private final IdentifiableAction vennDiagram = new IdentifiableAction("Venn Diagram...", vennDiagramIconBundle)
153 {
154
155 public void actionPerformed(final ActionEvent event)
156 {
157 switch (selected.size())
158 {
159 case 2:
160 binaryDiagram();
161 break;
162 case 3:
163 ternaryDiagram();
164 break;
165 case 4:
166 quaternaryDiagram();
167 break;
168 default:
169 break;
170 }
171 }
172 };
173
174
175 private final IconBundle detailsIconBundle = new CachingIconBundle(new PNGIconBundle("/org/dishevelled/venn/cytoscape/details"));
176
177
178 private final IdentifiableAction details = new IdentifiableAction("Details...", detailsIconBundle)
179 {
180
181 public void actionPerformed(final ActionEvent event)
182 {
183 switch (selected.size())
184 {
185 case 2:
186 binaryDetails();
187 break;
188 case 3:
189 ternaryDetails();
190 break;
191 case 4:
192 quaternaryDetails();
193 break;
194 default:
195 break;
196 }
197 }
198 };
199
200
201 private final Action done = new AbstractAction("Done")
202 {
203
204 public void actionPerformed(final ActionEvent event)
205 {
206 done();
207 }
208 };
209
210
211 private final ListSelectionListener listSelectionListener = new ListSelectionListener()
212 {
213
214 public void valueChanged(final ListSelectionEvent event)
215 {
216 int size = selected.size();
217 eulerDiagram.setEnabled(size > 1);
218 vennDiagram.setEnabled(size > 1 && size < 5);
219 details.setEnabled(size > 1 && size < 5);
220 }
221 };
222
223
224 private final VennLayouter<CyNode> vennLayouter = new VennEulerLayouter<CyNode>();
225
226
227
228
229
230 GroupsView()
231 {
232 super();
233
234 groups = GlazedLists.eventList(CyGroupManager.getGroupList());
235 EventListModel<CyGroup> listModel = new EventListModel<CyGroup>(groups);
236 EventSelectionModel<CyGroup> selectionModel = new EventSelectionModel<CyGroup>(groups);
237 selected = selectionModel.getSelected();
238 selectionModel.addListSelectionListener(listSelectionListener);
239 groupList = new JList(listModel);
240 groupList.setSelectionModel(selectionModel);
241 groupList.setCellRenderer(new CyGroupListCellRenderer());
242
243 InputMap inputMap = getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
244 int menuKeyMask = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
245 KeyStroke ctrlShiftE = KeyStroke.getKeyStroke(KeyEvent.VK_E, menuKeyMask | InputEvent.SHIFT_DOWN_MASK);
246 KeyStroke ctrlShiftV = KeyStroke.getKeyStroke(KeyEvent.VK_V, menuKeyMask | InputEvent.SHIFT_DOWN_MASK);
247 KeyStroke ctrlShiftD = KeyStroke.getKeyStroke(KeyEvent.VK_D, menuKeyMask | InputEvent.SHIFT_DOWN_MASK);
248 inputMap.put(ctrlShiftE, "eulerDiagram");
249 inputMap.put(ctrlShiftV, "vennDiagram");
250 inputMap.put(ctrlShiftD, "details");
251 getActionMap().put("eulerDiagram", eulerDiagram);
252 getActionMap().put("vennDiagram", vennDiagram);
253 getActionMap().put("details", details);
254
255 IdMenuItem eulerDiagramMenuItem = new IdMenuItem(eulerDiagram);
256 eulerDiagramMenuItem.setAccelerator(ctrlShiftE);
257 IdMenuItem vennDiagramMenuItem = new IdMenuItem(vennDiagram);
258 vennDiagramMenuItem.setAccelerator(ctrlShiftV);
259 IdMenuItem detailsMenuItem = new IdMenuItem(details);
260 detailsMenuItem.setAccelerator(ctrlShiftD);
261
262 contextMenu = new JPopupMenu();
263 contextMenu.add(eulerDiagramMenuItem);
264 contextMenu.add(vennDiagramMenuItem);
265 contextMenu.add(detailsMenuItem);
266 groupList.addMouseListener(new ContextMenuListener(contextMenu));
267
268 eulerDiagram.setEnabled(false);
269 vennDiagram.setEnabled(false);
270 details.setEnabled(false);
271
272 layoutComponents();
273 CyGroupManager.registerGroupViewer(this);
274 CyGroupManager.addGroupChangeListener(this);
275 }
276
277
278
279
280 private void layoutComponents()
281 {
282 LabelFieldPanel mainPanel = new LabelFieldPanel();
283 mainPanel.setBorder(new EmptyBorder(12, 12, 0, 12));
284 mainPanel.addLabel("Groups:");
285 mainPanel.addFinalField(new JScrollPane(groupList));
286
287 IdToolBar toolBar = new IdToolBar();
288 IdButton eulerDiagramButton = toolBar.add(eulerDiagram);
289 eulerDiagramButton.setBorderPainted(false);
290 eulerDiagramButton.setFocusPainted(false);
291 IdButton vennDiagramButton = toolBar.add(vennDiagram);
292 vennDiagramButton.setBorderPainted(false);
293 vennDiagramButton.setFocusPainted(false);
294 IdButton detailsButton = toolBar.add(details);
295 detailsButton.setBorderPainted(false);
296 detailsButton.setFocusPainted(false);
297
298 toolBar.displayIcons();
299 toolBar.setIconSize(IconSize.DEFAULT_24X24);
300
301 JPopupMenu toolBarContextMenu = new JPopupMenu();
302 for (Object menuItem : toolBar.getDisplayMenuItems())
303 {
304 toolBarContextMenu.add((JCheckBoxMenuItem) menuItem);
305 }
306 toolBar.addMouseListener(new ContextMenuListener(toolBarContextMenu));
307
308 ButtonPanel buttonPanel = new ButtonPanel();
309 buttonPanel.setBorder(new EmptyBorder(24, 12, 12, 12));
310 buttonPanel.add(done);
311
312 setLayout(new BorderLayout());
313 add("North", toolBar);
314 add("Center", mainPanel);
315 add("South", buttonPanel);
316 }
317
318
319
320
321 private void done()
322 {
323 windowForComponent(this).setVisible(false);
324
325 }
326
327
328
329
330 private void eulerDiagram()
331 {
332 List<String> labels = new ArrayList<String>(selected.size());
333 List<Set<CyNode>> sets = new ArrayList<Set<CyNode>>(selected.size());
334 for (CyGroup selectedGroup : selected)
335 {
336 labels.add(nameOf(selectedGroup));
337 sets.add(new HashSet<CyNode>(selectedGroup.getNodes()));
338 }
339 final VennModel<CyNode> model = VennModels.createVennModel(sets);
340 final VennNode<CyNode> vennNode = new VennNode<CyNode>(model);
341
342 for (int i = 0, size = labels.size(); i < size; i++)
343 {
344 vennNode.setLabelText(i, labels.get(i));
345 }
346
347 JDialog dialog = new JDialog(windowForComponent(this), Joiner.on(", ").join(labels) + " Euler Diagram");
348 dialog.setContentPane(new DiagramView(vennNode));
349 dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
350 installCloseKeyBinding(dialog);
351
352
353 dialog.setBounds(100, 100, 600, 600);
354 if (model.size() > 4) {
355 dialog.setBounds(100, 100, 800, 800);
356 }
357 dialog.setVisible(true);
358
359
360 SwingUtilities.invokeLater(new Runnable()
361 {
362
363 public void run()
364 {
365 Rectangle2D.Double boundingRectangle = new Rectangle2D.Double(0.0d, 0.0d, 400.0d, 400.0d);
366 if (model.size() > 4) {
367 boundingRectangle.setRect(0.0d, 0.0d, 600.0d, 600.0d);
368 }
369 VennLayout layout = vennLayouter.layout(model, boundingRectangle, PerformanceHint.OPTIMIZE_FOR_SPEED);
370 vennNode.setLayout(layout);
371 }
372 });
373 }
374
375
376
377
378 private void binaryDiagram()
379 {
380 String firstLabel = selected.get(0).getGroupName();
381 String secondLabel = selected.get(1).getGroupName();
382 Set<CyNode> first = new HashSet<CyNode>(selected.get(0).getNodes());
383 Set<CyNode> second = new HashSet<CyNode>(selected.get(1).getNodes());
384 BinaryVennNode<CyNode> binaryVennNode = new BinaryVennNode<CyNode>(firstLabel, first, secondLabel, second);
385
386 JDialog dialog = new JDialog(windowForComponent(this), firstLabel + ", " + secondLabel + " Venn Diagram");
387 dialog.setContentPane(new DiagramView(binaryVennNode));
388 dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
389 installCloseKeyBinding(dialog);
390
391
392 dialog.setBounds(100, 100, 400, 400);
393 dialog.setVisible(true);
394 }
395
396
397
398
399 private void ternaryDiagram()
400 {
401 String firstLabel = selected.get(0).getGroupName();
402 String secondLabel = selected.get(1).getGroupName();
403 String thirdLabel = selected.get(2).getGroupName();
404 Set<CyNode> first = new HashSet<CyNode>(selected.get(0).getNodes());
405 Set<CyNode> second = new HashSet<CyNode>(selected.get(1).getNodes());
406 Set<CyNode> third = new HashSet<CyNode>(selected.get(2).getNodes());
407 TernaryVennNode<CyNode> ternaryVennNode = new TernaryVennNode<CyNode>(firstLabel, first, secondLabel, second, thirdLabel, third);
408
409 JDialog dialog = new JDialog(windowForComponent(this), firstLabel + ", " + secondLabel + ", " + thirdLabel + " Venn Diagram");
410 dialog.setContentPane(new DiagramView(ternaryVennNode));
411 dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
412 installCloseKeyBinding(dialog);
413
414
415 dialog.setBounds(100, 100, 400, 400);
416 dialog.setVisible(true);
417 }
418
419
420
421
422 private void quaternaryDiagram()
423 {
424 String firstLabel = selected.get(0).getGroupName();
425 String secondLabel = selected.get(1).getGroupName();
426 String thirdLabel = selected.get(2).getGroupName();
427 String fourthLabel = selected.get(3).getGroupName();
428 Set<CyNode> first = new HashSet<CyNode>(selected.get(0).getNodes());
429 Set<CyNode> second = new HashSet<CyNode>(selected.get(1).getNodes());
430 Set<CyNode> third = new HashSet<CyNode>(selected.get(2).getNodes());
431 Set<CyNode> fourth = new HashSet<CyNode>(selected.get(3).getNodes());
432 QuaternaryVennNode<CyNode> quaternaryVennNode = new QuaternaryVennNode<CyNode>(firstLabel, first, secondLabel, second, thirdLabel, third, fourthLabel, fourth);
433
434 JDialog dialog = new JDialog(windowForComponent(this), firstLabel + ", " + secondLabel + ", " + thirdLabel + ", " + fourthLabel + " Venn Diagram");
435 dialog.setContentPane(new DiagramView(quaternaryVennNode));
436 dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
437 installCloseKeyBinding(dialog);
438
439
440 dialog.setBounds(100, 100, 600, 600);
441 dialog.setVisible(true);
442 }
443
444
445
446
447 private void binaryDetails()
448 {
449 String firstLabel = selected.get(0).getGroupName();
450 String secondLabel = selected.get(1).getGroupName();
451 Set<CyNode> first = new HashSet<CyNode>(selected.get(0).getNodes());
452 Set<CyNode> second = new HashSet<CyNode>(selected.get(1).getNodes());
453 final BinaryVennList<CyNode> binaryVennList = new BinaryVennList<CyNode>(firstLabel, first, secondLabel, second);
454
455 JDialog dialog = new JDialog(windowForComponent(this), firstLabel + ", " + secondLabel + " Details");
456 dialog.setContentPane(new DetailsView(binaryVennList));
457 dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
458 installCloseKeyBinding(dialog);
459
460
461 dialog.setBounds(100, 100, 600, 450);
462 dialog.setVisible(true);
463 }
464
465
466
467
468 private void ternaryDetails()
469 {
470 String firstLabel = selected.get(0).getGroupName();
471 String secondLabel = selected.get(1).getGroupName();
472 String thirdLabel = selected.get(2).getGroupName();
473 Set<CyNode> first = new HashSet<CyNode>(selected.get(0).getNodes());
474 Set<CyNode> second = new HashSet<CyNode>(selected.get(1).getNodes());
475 Set<CyNode> third = new HashSet<CyNode>(selected.get(2).getNodes());
476 final TernaryVennList<CyNode> ternaryVennList = new TernaryVennList<CyNode>(firstLabel, first, secondLabel, second, thirdLabel, third);
477
478 JDialog dialog = new JDialog(windowForComponent(this), firstLabel + ", " + secondLabel + ", " + thirdLabel + " Details");
479 dialog.setContentPane(new DetailsView(ternaryVennList));
480 dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
481 installCloseKeyBinding(dialog);
482
483
484 dialog.setBounds(100, 100, 747, 669);
485 dialog.setVisible(true);
486 }
487
488
489
490
491 private void quaternaryDetails()
492 {
493 String firstLabel = selected.get(0).getGroupName();
494 String secondLabel = selected.get(1).getGroupName();
495 String thirdLabel = selected.get(2).getGroupName();
496 String fourthLabel = selected.get(3).getGroupName();
497 Set<CyNode> first = new HashSet<CyNode>(selected.get(0).getNodes());
498 Set<CyNode> second = new HashSet<CyNode>(selected.get(1).getNodes());
499 Set<CyNode> third = new HashSet<CyNode>(selected.get(2).getNodes());
500 Set<CyNode> fourth = new HashSet<CyNode>(selected.get(3).getNodes());
501 final QuaternaryVennList<CyNode> quaternaryVennList = new QuaternaryVennList<CyNode>(firstLabel, first, secondLabel, second, thirdLabel, third, fourthLabel, fourth);
502
503 JDialog dialog = new JDialog(windowForComponent(this), firstLabel + ", " + secondLabel + ", " + thirdLabel + ", " + fourthLabel + " Details");
504 dialog.setContentPane(new DetailsView(quaternaryVennList));
505 dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
506 installCloseKeyBinding(dialog);
507
508
509 dialog.setBounds(100, 100, 894, 888);
510 dialog.setVisible(true);
511 }
512
513
514 public String getViewerName()
515 {
516 return "Venn/Euler Diagrams";
517 }
518
519
520 public void groupChanged(final CyGroup group, final CyNode changedNode, CyGroupViewer.ChangeType change)
521 {
522
523 }
524
525
526 public void groupCreated(final CyGroup group)
527 {
528 if (!groups.contains(group))
529 {
530 groups.add(group);
531 }
532 }
533
534
535 public void groupCreated(final CyGroup group, final CyNetworkView networkView)
536 {
537 if (!groups.contains(group))
538 {
539 groups.add(group);
540 }
541 }
542
543
544 public void groupWillBeRemoved(final CyGroup group)
545 {
546 if (groups.contains(group))
547 {
548 groups.remove(group);
549 }
550 }
551
552
553 public void groupChanged(final CyGroup group, final CyGroupChangeListener.ChangeType change)
554 {
555 switch (change)
556 {
557 case GROUP_CREATED:
558 if (!groups.contains(group))
559 {
560 groups.add(group);
561 }
562 break;
563 case GROUP_DELETED:
564 if (groups.contains(group))
565 {
566 groups.remove(group);
567 }
568 break;
569 case GROUP_MODIFIED:
570 default:
571 break;
572 }
573 }
574 }