View Javadoc

1   /*
2   
3       dsh-venn-cytoscape3-app  Cytoscape3 app for venn and euler diagrams.
4       Copyright (c) 2012-2013 held jointly by the individual authors.
5   
6       This library is free software; you can redistribute it and/or modify it
7       under the terms of the GNU Lesser General Public License as published
8       by the Free Software Foundation; either version 3 of the License, or (at
9       your option) any later version.
10  
11      This library is distributed in the hope that it will be useful, but WITHOUT
12      ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or
13      FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
14      License for more details.
15  
16      You should have received a copy of the GNU Lesser General Public License
17      along with this library;  if not, write to the Free Software Foundation,
18      Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA.
19  
20      > http://www.fsf.org/licensing/licenses/lgpl.html
21      > http://www.opensource.org/licenses/lgpl-license.php
22  
23  */
24  package org.dishevelled.venn.cytoscape3.internal;
25  
26  import java.awt.BorderLayout;
27  import java.awt.Toolkit;
28  
29  import java.awt.event.ActionEvent;
30  import java.awt.event.InputEvent;
31  import java.awt.event.KeyEvent;
32  
33  import javax.swing.AbstractAction;
34  import javax.swing.Action;
35  import javax.swing.InputMap;
36  import javax.swing.KeyStroke;
37  import javax.swing.JComponent;
38  import javax.swing.JMenuItem;
39  import javax.swing.JPanel;
40  import javax.swing.JPopupMenu;
41  
42  import javax.swing.border.EmptyBorder;
43  
44  import org.cytoscape.application.CyApplicationManager;
45  import org.cytoscape.model.CyNetwork;
46  import org.cytoscape.model.CyNode;
47  
48  import org.dishevelled.identify.ContextMenuListener;
49  import org.dishevelled.identify.IdToolBar;
50  
51  import org.dishevelled.observable.event.SetChangeEvent;
52  import org.dishevelled.observable.event.SetChangeListener;
53  
54  import org.dishevelled.venn.swing.BinaryVennList;
55  import org.dishevelled.venn.swing.TernaryVennList;
56  import org.dishevelled.venn.swing.QuaternaryVennList;
57  
58  /**
59   * Details view.
60   *
61   * @author  Michael Heuer
62   */
63  final class DetailsView
64      extends JPanel
65  {
66      /** Maximum number of nodes above which selection sync should be disabled for binary details views. */
67      private static final int BINARY_SELECTION_SYNC_MAXIMUM = Integer.MAX_VALUE;
68  
69      /** Maximum number of nodes above which selection sync should be disabled for ternary details views. */
70      private static final int TERNARY_SELECTION_SYNC_MAXIMUM = 2000000;
71  
72      /** Maximum number of nodes above which selection sync should be disabled for quaternary details views. */
73      private static final int QUATERNARY_SELECTION_SYNC_MAXIMUM = 20000;
74  
75      /** Binary venn list. */
76      private final BinaryVennList<CyNode> binaryVennList;
77  
78      /** Ternary venn list. */
79      private final TernaryVennList<CyNode> ternaryVennList;
80  
81      /** Quaternary venn list. */
82      private final QuaternaryVennList<CyNode> quaternaryVennList;
83  
84      /** Update Cytoscape selection. */
85      private final SetChangeListener<CyNode> updateCytoscapeSelection = new SetChangeListener<CyNode>()
86          {
87              /** {@inheritDoc} */
88              public void setChanged(final SetChangeEvent<CyNode> event)
89              {
90                  CyNetwork currentNetwork = applicationManager.getCurrentNetwork();
91                  for (CyNode node : currentNetwork.getNodeList())
92                  {
93                      currentNetwork.getRow(node).set(CyNetwork.SELECTED, event.getObservableSet().contains(node));
94                  }
95                  applicationManager.getCurrentNetworkView().updateView();
96              }
97          };
98  
99      // todo: use identifiable actions for these, if a clear selection icon can be found
100     //   ...there is EDIT_SELECT_ALL but 24x24 is not one of the tango icon sizes
101     /** Select all action. */
102     private final Action selectAll = new AbstractAction("Select all") // i18n
103         {
104             /** {@inheritDoc} */
105             public void actionPerformed(final ActionEvent event)
106             {
107                 if (binaryVennList != null)
108                 {
109                     binaryVennList.selectAll();
110                 }
111                 if (ternaryVennList != null)
112                 {
113                     ternaryVennList.selectAll();
114                 }
115                 if (quaternaryVennList != null)
116                 {
117                     quaternaryVennList.selectAll();
118                 }
119             }
120         };
121 
122     /** Clear selection action. */
123     private final Action clearSelection = new AbstractAction("Clear selection") // i18n
124         {
125             /** {@inheritDoc} */
126             public void actionPerformed(final ActionEvent event)
127             {
128                 if (binaryVennList != null)
129                 {
130                     binaryVennList.clearSelection();
131                 }
132                 if (ternaryVennList != null)
133                 {
134                     ternaryVennList.clearSelection();
135                 }
136                 if (quaternaryVennList != null)
137                 {
138                     quaternaryVennList.clearSelection();
139                 }
140             }
141         };
142 
143     /** Application manager. */
144     private final CyApplicationManager applicationManager;
145 
146 
147     /**
148      * Create a new details view.
149      *
150      * @param binaryVennList binary venn list
151      * @param ternaryVennList ternary venn list
152      * @param quaternaryVennList quaternary venn list
153      * @param applicationManager application manager, must not be null
154      */
155     private DetailsView(final BinaryVennList<CyNode> binaryVennList,
156                         final TernaryVennList<CyNode> ternaryVennList,
157                         final QuaternaryVennList<CyNode> quaternaryVennList,
158                         final CyApplicationManager applicationManager)
159     {
160         super();
161         if (applicationManager == null)
162         {
163             throw new IllegalArgumentException("applicationManager must not be null");
164         }
165 
166         this.binaryVennList = binaryVennList;
167         this.ternaryVennList = ternaryVennList;
168         this.quaternaryVennList = quaternaryVennList;
169         this.applicationManager = applicationManager;
170 
171         // suck.
172         if (this.binaryVennList != null)
173         {
174             this.binaryVennList.getFirst().setCellRenderer(new CyNodeListCellRenderer(applicationManager));
175             this.binaryVennList.getFirstOnly().setCellRenderer(new CyNodeListCellRenderer(applicationManager));
176             this.binaryVennList.getIntersection().setCellRenderer(new CyNodeListCellRenderer(applicationManager));
177             this.binaryVennList.getSecond().setCellRenderer(new CyNodeListCellRenderer(applicationManager));
178             this.binaryVennList.getSecondOnly().setCellRenderer(new CyNodeListCellRenderer(applicationManager));
179             this.binaryVennList.getUnion().setCellRenderer(new CyNodeListCellRenderer(applicationManager));
180         }
181         if (this.ternaryVennList != null)
182         {
183             this.ternaryVennList.getFirst().setCellRenderer(new CyNodeListCellRenderer(applicationManager));
184             this.ternaryVennList.getFirstOnly().setCellRenderer(new CyNodeListCellRenderer(applicationManager));
185             this.ternaryVennList.getFirstSecond().setCellRenderer(new CyNodeListCellRenderer(applicationManager));
186             this.ternaryVennList.getFirstThird().setCellRenderer(new CyNodeListCellRenderer(applicationManager));
187             this.ternaryVennList.getIntersection().setCellRenderer(new CyNodeListCellRenderer(applicationManager));
188             this.ternaryVennList.getSecond().setCellRenderer(new CyNodeListCellRenderer(applicationManager));
189             this.ternaryVennList.getSecondOnly().setCellRenderer(new CyNodeListCellRenderer(applicationManager));
190             this.ternaryVennList.getSecondThird().setCellRenderer(new CyNodeListCellRenderer(applicationManager));
191             this.ternaryVennList.getThird().setCellRenderer(new CyNodeListCellRenderer(applicationManager));
192             this.ternaryVennList.getThirdOnly().setCellRenderer(new CyNodeListCellRenderer(applicationManager));
193             this.ternaryVennList.getUnion().setCellRenderer(new CyNodeListCellRenderer(applicationManager));
194         }
195         if (this.quaternaryVennList != null)
196         {
197             this.quaternaryVennList.getFirst().setCellRenderer(new CyNodeListCellRenderer(applicationManager));
198             this.quaternaryVennList.getFirstFourth().setCellRenderer(new CyNodeListCellRenderer(applicationManager));
199             this.quaternaryVennList.getFirstOnly().setCellRenderer(new CyNodeListCellRenderer(applicationManager));
200             this.quaternaryVennList.getFirstSecond().setCellRenderer(new CyNodeListCellRenderer(applicationManager));
201             this.quaternaryVennList.getFirstSecondFourth().setCellRenderer(new CyNodeListCellRenderer(applicationManager));
202             this.quaternaryVennList.getFirstSecondThird().setCellRenderer(new CyNodeListCellRenderer(applicationManager));
203             this.quaternaryVennList.getFirstThird().setCellRenderer(new CyNodeListCellRenderer(applicationManager));
204             this.quaternaryVennList.getFirstThirdFourth().setCellRenderer(new CyNodeListCellRenderer(applicationManager));
205             this.quaternaryVennList.getFourth().setCellRenderer(new CyNodeListCellRenderer(applicationManager));
206             this.quaternaryVennList.getFourthOnly().setCellRenderer(new CyNodeListCellRenderer(applicationManager));
207             this.quaternaryVennList.getIntersection().setCellRenderer(new CyNodeListCellRenderer(applicationManager));
208             this.quaternaryVennList.getSecond().setCellRenderer(new CyNodeListCellRenderer(applicationManager));
209             this.quaternaryVennList.getSecondFourth().setCellRenderer(new CyNodeListCellRenderer(applicationManager));
210             this.quaternaryVennList.getSecondOnly().setCellRenderer(new CyNodeListCellRenderer(applicationManager));
211             this.quaternaryVennList.getSecondThird().setCellRenderer(new CyNodeListCellRenderer(applicationManager));
212             this.quaternaryVennList.getSecondThirdFourth().setCellRenderer(new CyNodeListCellRenderer(applicationManager));
213             this.quaternaryVennList.getThird().setCellRenderer(new CyNodeListCellRenderer(applicationManager));
214             this.quaternaryVennList.getThirdFourth().setCellRenderer(new CyNodeListCellRenderer(applicationManager));
215             this.quaternaryVennList.getThirdOnly().setCellRenderer(new CyNodeListCellRenderer(applicationManager));
216             this.quaternaryVennList.getUnion().setCellRenderer(new CyNodeListCellRenderer(applicationManager));
217         }
218 
219         InputMap inputMap = getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
220         int menuKeyMask = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
221         KeyStroke ctrlShiftA = KeyStroke.getKeyStroke(KeyEvent.VK_A, menuKeyMask | InputEvent.SHIFT_DOWN_MASK);
222         KeyStroke ctrlShiftC = KeyStroke.getKeyStroke(KeyEvent.VK_C, menuKeyMask | InputEvent.SHIFT_DOWN_MASK);
223         inputMap.put(ctrlShiftA, "selectAll");
224         inputMap.put(ctrlShiftC, "clearSelection");
225         getActionMap().put("selectAll", selectAll);
226         getActionMap().put("clearSelection", clearSelection);
227 
228         JMenuItem selectAllMenuItem = new JMenuItem(selectAll);
229         selectAllMenuItem.setAccelerator(ctrlShiftA);
230         JMenuItem clearSelectionMenuItem = new JMenuItem(clearSelection);
231         clearSelectionMenuItem.setAccelerator(ctrlShiftC);
232 
233         JPopupMenu contextMenu = new JPopupMenu();
234         contextMenu.add(selectAllMenuItem);
235         contextMenu.add(clearSelectionMenuItem);
236 
237         IdToolBar toolBar = new IdToolBar();
238         // todo:  odd border decorations on Win L&F
239         toolBar.add(selectAll);
240         toolBar.add(clearSelection);
241         toolBar.displayText();
242 
243         setLayout(new BorderLayout());
244         add("North", toolBar);
245         addMouseListener(new ContextMenuListener(contextMenu));
246     }
247 
248     /**
249      * Create a new details view with the specified binary venn list.
250      *
251      * @param binaryVennList binary venn list
252      * @param applicationManager application manager, must not be null
253      */
254     DetailsView(final BinaryVennList<CyNode> binaryVennList, final CyApplicationManager applicationManager)
255     {
256         this(binaryVennList, null, null, applicationManager);
257         binaryVennList.setBorder(new EmptyBorder(12, 12, 12, 12));
258         if (binaryVennList.getModel().union().size() > BINARY_SELECTION_SYNC_MAXIMUM)
259         {
260             selectAll.setEnabled(false);
261             clearSelection.setEnabled(false);
262         }
263         else
264         {
265             binaryVennList.getModel().selection().addSetChangeListener(updateCytoscapeSelection);
266         }
267         add("Center", binaryVennList);
268     }
269 
270     /**
271      * Create a new details view with the specified ternary venn list.
272      *
273      * @param ternaryVennList ternary venn list
274      * @param applicationManager application manager, must not be null
275      */
276     DetailsView(final TernaryVennList<CyNode> ternaryVennList, final CyApplicationManager applicationManager)
277     {
278         this(null, ternaryVennList, null, applicationManager);
279         ternaryVennList.setBorder(new EmptyBorder(12, 12, 12, 12));
280         if (ternaryVennList.getModel().union().size() > TERNARY_SELECTION_SYNC_MAXIMUM)
281         {
282             selectAll.setEnabled(false);
283             clearSelection.setEnabled(false);
284         }
285         else
286         {
287             ternaryVennList.getModel().selection().addSetChangeListener(updateCytoscapeSelection);
288         }
289         add("Center", ternaryVennList);
290     }
291 
292     /**
293      * Create a new details view with the specified quaternary venn list.
294      *
295      * @param quaternaryVennList quaternary venn list
296      * @param applicationManager application manager, must not be null
297      */
298     DetailsView(final QuaternaryVennList<CyNode> quaternaryVennList, final CyApplicationManager applicationManager)
299     {
300         this(null, null, quaternaryVennList, applicationManager);
301         quaternaryVennList.setBorder(new EmptyBorder(12, 12, 12, 12));
302         if (quaternaryVennList.getModel().union().size() > QUATERNARY_SELECTION_SYNC_MAXIMUM)
303         {
304             selectAll.setEnabled(false);
305             clearSelection.setEnabled(false);
306         }
307         else
308         {
309             quaternaryVennList.getModel().selection().addSetChangeListener(updateCytoscapeSelection);
310         }
311         add("Center", quaternaryVennList);
312     }
313 }