formatting
[jalview.git] / src / jalview / gui / ViewSelectionMenu.java
1 /*******************************************************************************
2  * Jalview - A Sequence Alignment Editor and Viewer (Version 2.7)
3  * Copyright (C) 2011 J Procter, AM Waterhouse, J Engelhardt, LM Lui, G Barton, M Clamp, S Searle
4  *
5  * This file is part of Jalview.
6  *
7  * Jalview is free software: you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License 
9  * as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
10  *
11  * Jalview is distributed in the hope that it will be useful, but 
12  * WITHOUT ANY WARRANTY; without even the implied warranty 
13  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
14  * PURPOSE.  See the GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
17  *******************************************************************************/
18 package jalview.gui;
19
20 import java.awt.Component;
21 import java.awt.event.ActionEvent;
22 import java.awt.event.ActionListener;
23 import java.awt.event.ItemEvent;
24 import java.awt.event.ItemListener;
25 import java.awt.event.MouseEvent;
26 import java.awt.event.MouseListener;
27 import java.util.List;
28
29 import javax.swing.JCheckBoxMenuItem;
30 import javax.swing.JMenu;
31 import javax.swing.JMenuItem;
32 import javax.swing.event.MenuEvent;
33 import javax.swing.event.MenuListener;
34
35 /**
36  * this is an implementation of an abstract Jalview GUI class that provides a
37  * dialog/menu which allows the user to select/deselect specific views from a
38  * list of associated views.
39  * 
40  * Includes patches related to JAL-641
41  * 
42  * @author JimP
43  * 
44  */
45 public class ViewSelectionMenu extends JMenu
46 {
47   public interface ViewSetProvider
48   {
49     public AlignmentPanel[] getAllAlignmentPanels();
50   }
51
52   private ViewSetProvider _allviews;
53
54   private List<AlignmentPanel> _selectedviews;
55
56   private ItemListener _handler;
57
58   @Override
59   protected void finalize() throws Throwable
60   {
61     _selectedviews = null;
62     _handler = null;
63     _allviews = null;
64     super.finalize();
65   }
66
67   /**
68    * create a new view selection menu. This menu has some standard entries
69    * (select all, invert selection), and a checkbox for every view. Mousing over
70    * a view entry will cause it to be raised/selected in the Desktop, allowing
71    * the user to easily identify which view is being referred to.
72    * 
73    * @param title
74    *          Name of menu
75    * @param allviews
76    *          all the views that might be selected
77    * @param selectedviews
78    *          the list of selected views which will be updated when
79    *          selection/deselections occur
80    * @param handler
81    *          a handler called for each selection/deselection - use this to
82    *          update any gui elements which need to reflect current
83    *          selection/deselection state
84    */
85   public ViewSelectionMenu(String title, final ViewSetProvider allviews,
86           final List<AlignmentPanel> selectedviews,
87           final ItemListener handler)
88   {
89     super(title);
90     this._allviews = allviews;
91     this._selectedviews = selectedviews;
92     this._handler = handler;
93     addMenuListener(new MenuListener()
94     {
95
96       @Override
97       public void menuSelected(MenuEvent e)
98       {
99         rebuild();
100
101       }
102
103       @Override
104       public void menuDeselected(MenuEvent e)
105       {
106         // TODO Auto-generated method stub
107
108       }
109
110       @Override
111       public void menuCanceled(MenuEvent e)
112       {
113         // TODO Auto-generated method stub
114
115       }
116     });
117   }
118
119   /**
120    * view selection modifier flag - indicates if an action key is pressed when
121    * menu selection event occurred.
122    */
123   private boolean append = false;
124
125   /**
126    * flag indicating if the itemStateChanged listener for view associated menu
127    * items is currently enabled
128    */
129   private boolean enabled = true;
130
131   private JMenuItem selectAll, invertSel;
132
133   private JCheckBoxMenuItem toggleview = null;
134
135   private void rebuild()
136   {
137     removeAll();
138     AlignmentPanel[] allviews = _allviews.getAllAlignmentPanels();
139     if (allviews == null)
140     {
141       setVisible(false);
142       return;
143     }
144     if (allviews.length >= 2)
145     {
146       // ensure we update menu state to reflect external selection list state
147       append = append || _selectedviews.size() > 1;
148       toggleview = new JCheckBoxMenuItem("Select many views", append);
149       toggleview
150               .setToolTipText("When enabled, allows many views to be selected.");
151       toggleview.addItemListener(new ItemListener()
152       {
153
154         @Override
155         public void itemStateChanged(ItemEvent arg0)
156         {
157           if (enabled)
158           {
159             append = !append;
160             selectAll.setEnabled(append);
161             invertSel.setEnabled(append);
162           }
163
164         }
165
166       });
167       add(toggleview);
168       add(selectAll = new JMenuItem("Select all views"));
169       selectAll.addActionListener(new ActionListener()
170       {
171
172         @Override
173         public void actionPerformed(ActionEvent e)
174         {
175           for (Component c : getMenuComponents())
176           {
177             boolean t = append;
178             append = true;
179             if (c instanceof JCheckBoxMenuItem)
180             {
181               if (toggleview != c && !((JCheckBoxMenuItem) c).isSelected())
182               {
183                 ((JCheckBoxMenuItem) c).doClick();
184               }
185             }
186             append = t;
187           }
188         }
189       });
190       add(invertSel = new JMenuItem("Invert selection"));
191       invertSel.addActionListener(new ActionListener()
192       {
193
194         @Override
195         public void actionPerformed(ActionEvent e)
196         {
197           boolean t = append;
198           append = true;
199           for (Component c : getMenuComponents())
200           {
201             if (toggleview != c && c instanceof JCheckBoxMenuItem)
202             {
203               ((JCheckBoxMenuItem) c).doClick();
204             }
205           }
206           append = t;
207         }
208       });
209       invertSel.setEnabled(append);
210       selectAll.setEnabled(append);
211     }
212     for (AlignmentPanel ap : allviews)
213     {
214       String nm = ((ap.getViewName() == null || ap.getViewName().length() == 0) ? ""
215               : ap.getViewName() + " for ")
216               + ap.alignFrame.getTitle();
217       final JCheckBoxMenuItem a = new JCheckBoxMenuItem(nm,
218               _selectedviews.contains(ap));
219       final AlignmentPanel p = ap;
220       a.addItemListener(new ItemListener()
221       {
222         @Override
223         public void itemStateChanged(ItemEvent e)
224         {
225           if (enabled)
226           {
227             if (append)
228             {
229               enabled = false;
230               // toggle the inclusion state
231               if (_selectedviews.indexOf(p) == -1)
232               {
233                 _selectedviews.add(p);
234                 a.setSelected(true);
235               }
236               else
237               {
238                 _selectedviews.remove(p);
239                 a.setSelected(false);
240               }
241               enabled = true;
242               _handler.itemStateChanged(e);
243             }
244             else
245             {
246               // Deselect everything and select this item only
247               _selectedviews.clear();
248               _selectedviews.add(p);
249               enabled = false;
250               for (Component c : getMenuComponents())
251               {
252                 if (c instanceof JCheckBoxMenuItem)
253                 {
254                   ((JCheckBoxMenuItem) c).setSelected(a == c);
255                 }
256               }
257               enabled = true;
258               // only fire event if we weren't selected before
259               _handler.itemStateChanged(e);
260             }
261           }
262         }
263       });
264       a.addMouseListener(new MouseListener()
265       {
266
267         @Override
268         public void mouseReleased(MouseEvent e)
269         {
270           // TODO Auto-generated method stub
271
272         }
273
274         @Override
275         public void mousePressed(MouseEvent e)
276         {
277           // TODO Auto-generated method stub
278
279         }
280
281         @Override
282         public void mouseExited(MouseEvent e)
283         {
284           try
285           {
286             p.setSelected(false);
287           } catch (Exception ex)
288           {
289           }
290           ;
291         }
292
293         @Override
294         public void mouseEntered(MouseEvent e)
295         {
296
297           try
298           {
299             p.setSelected(true);
300           } catch (Exception ex)
301           {
302           }
303           ;
304         }
305
306         @Override
307         public void mouseClicked(MouseEvent e)
308         {
309         }
310       });
311       add(a);
312     }
313   }
314
315 }