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