JAL-641 patch
[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 selected, toggles whether a particular view is used to colour the alignment.");
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             if (e.getStateChange() == e.SELECTED)
205             {
206               _selectedviews.add(p);
207             }
208             else
209             {
210               _selectedviews.remove(p);
211             }
212             _handler.itemStateChanged(e);
213           }
214           else
215           {
216             // Deselect everything and select this item only
217             _selectedviews.clear();
218             _selectedviews.add(p);
219             enabled=false;
220             for (Component c : getMenuComponents())
221             {
222               if (c instanceof JCheckBoxMenuItem)
223               {
224                 ((JCheckBoxMenuItem) c).setSelected(a == c);
225               }
226             }
227             enabled=true;
228             // only fire event if we weren't selected before
229             _handler.itemStateChanged(e);
230           }
231           }
232         }
233       });
234       a.addMouseListener(new MouseListener()
235       {
236
237         @Override
238         public void mouseReleased(MouseEvent e)
239         {
240           // TODO Auto-generated method stub
241
242         }
243
244         @Override
245         public void mousePressed(MouseEvent e)
246         {
247           // TODO Auto-generated method stub
248
249         }
250
251         @Override
252         public void mouseExited(MouseEvent e)
253         {
254           try
255           {
256             p.setSelected(false);
257           } catch (Exception ex)
258           {
259           }
260           ;
261         }
262
263         @Override
264         public void mouseEntered(MouseEvent e)
265         {
266
267           try
268           {
269             p.setSelected(true);
270           } catch (Exception ex)
271           {
272           }
273           ;
274         }
275
276         @Override
277         public void mouseClicked(MouseEvent e)
278         {
279         }
280       });
281       add(a);
282     }
283   }
284
285 }