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