update author list in license for (JAL-826)
[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    * flag indicating if the itemStateChanged listener for view associated menu items is currently enabled 
126    */
127   private boolean enabled = true;
128   private JMenuItem selectAll, invertSel;
129   private JCheckBoxMenuItem toggleview=null;
130   private void rebuild()
131   {
132     removeAll();
133     AlignmentPanel[] allviews = _allviews.getAllAlignmentPanels();
134     if (allviews == null)
135     {
136       setVisible(false);
137       return;
138     }
139     if (allviews.length >= 2)
140     {
141       // ensure we update menu state to reflect external selection list state
142       append = append || _selectedviews.size()>1;
143       toggleview = new JCheckBoxMenuItem("Select many views",append);
144       toggleview.setToolTipText("When enabled, allows many views to be selected.");
145       toggleview.addItemListener(new ItemListener() {
146
147         @Override
148         public void itemStateChanged(ItemEvent arg0)
149         {
150           if (enabled)
151           {
152             append = !append;
153             selectAll.setEnabled(append);
154             invertSel.setEnabled(append);
155           }
156           
157         }
158         
159       });
160       add(toggleview);
161       add(selectAll= new JMenuItem("Select all views"));
162       selectAll.addActionListener(new ActionListener()
163       {
164
165         @Override
166         public void actionPerformed(ActionEvent e)
167         {
168           for (Component c : getMenuComponents())
169           {
170             boolean t=append;
171             append=true;
172             if (c instanceof JCheckBoxMenuItem)
173             {
174               if (toggleview!=c && !((JCheckBoxMenuItem) c).isSelected())
175               {
176                 ((JCheckBoxMenuItem) c).doClick();
177               }
178             }
179             append=t;
180           }
181         }
182       });
183       add(invertSel = new JMenuItem("Invert selection"));
184       invertSel.addActionListener(new ActionListener()
185       {
186
187         @Override
188         public void actionPerformed(ActionEvent e)
189         {
190           boolean t=append;
191           append=true;
192           for (Component c : getMenuComponents())
193           {
194             if (toggleview!=c && c instanceof JCheckBoxMenuItem)
195             {
196               ((JCheckBoxMenuItem) c).doClick();
197             }
198           }
199           append=t;
200         }
201       });
202       invertSel.setEnabled(append);
203       selectAll.setEnabled(append);
204     }
205     for (AlignmentPanel ap : allviews)
206     {
207       String nm = ((ap.getViewName() == null || ap.getViewName().length() == 0) ? ""
208               : ap.getViewName() + " for ")
209               + ap.alignFrame.getTitle();
210       final JCheckBoxMenuItem a = new JCheckBoxMenuItem(nm,
211               _selectedviews.contains(ap));
212       final AlignmentPanel p = ap;
213       a.addItemListener(new ItemListener()
214       {
215         @Override
216         public void itemStateChanged(ItemEvent e)
217         {
218           if (enabled)
219           {
220           if (append)
221           {
222             enabled=false;
223             // toggle the inclusion state
224             if (_selectedviews.indexOf(p)==-1)
225             {
226               _selectedviews.add(p);
227               a.setSelected(true);
228             }
229             else
230             {
231               _selectedviews.remove(p);
232               a.setSelected(false);
233             }
234             enabled=true;
235             _handler.itemStateChanged(e);
236           }
237           else
238           {
239             // Deselect everything and select this item only
240             _selectedviews.clear();
241             _selectedviews.add(p);
242             enabled=false;
243             for (Component c : getMenuComponents())
244             {
245               if (c instanceof JCheckBoxMenuItem)
246               {
247                 ((JCheckBoxMenuItem) c).setSelected(a == c);
248               }
249             }
250             enabled=true;
251             // only fire event if we weren't selected before
252             _handler.itemStateChanged(e);
253           }
254           }
255         }
256       });
257       a.addMouseListener(new MouseListener()
258       {
259
260         @Override
261         public void mouseReleased(MouseEvent e)
262         {
263           // TODO Auto-generated method stub
264
265         }
266
267         @Override
268         public void mousePressed(MouseEvent e)
269         {
270           // TODO Auto-generated method stub
271
272         }
273
274         @Override
275         public void mouseExited(MouseEvent e)
276         {
277           try
278           {
279             p.setSelected(false);
280           } catch (Exception ex)
281           {
282           }
283           ;
284         }
285
286         @Override
287         public void mouseEntered(MouseEvent e)
288         {
289
290           try
291           {
292             p.setSelected(true);
293           } catch (Exception ex)
294           {
295           }
296           ;
297         }
298
299         @Override
300         public void mouseClicked(MouseEvent e)
301         {
302         }
303       });
304       add(a);
305     }
306   }
307
308 }