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