JAL-2360 structure viewers now using ColourMenuHelper, obsolete methods
[jalview.git] / src / jalview / gui / ColourMenuHelper.java
1 package jalview.gui;
2
3 import jalview.datamodel.AnnotatedCollectionI;
4 import jalview.schemes.ColourSchemeI;
5 import jalview.schemes.ColourSchemes;
6 import jalview.schemes.ResidueColourScheme;
7 import jalview.schemes.UserColourScheme;
8 import jalview.util.MessageManager;
9
10 import java.awt.Component;
11 import java.awt.event.ActionEvent;
12 import java.awt.event.ActionListener;
13 import java.awt.event.MouseAdapter;
14 import java.awt.event.MouseEvent;
15
16 import javax.swing.ButtonGroup;
17 import javax.swing.JMenu;
18 import javax.swing.JRadioButtonMenuItem;
19
20 public class ColourMenuHelper
21 {
22   public interface ColourChangeListener
23   {
24     void changeColour_actionPerformed(String name);
25   }
26
27   /**
28    * Adds items to the colour menu, as mutually exclusive members of a button
29    * group. The callback handler is responsible for the action on selecting any
30    * of these options. The callback method receives the name of the selected
31    * colour, or "None" or "User Defined". This method returns the ButtonGroup to
32    * which items were added.
33    * <ul>
34    * <li>None</li>
35    * <li>Clustal</li>
36    * <li>...other 'built-in' colours</li>
37    * <li>...any user-defined colours</li>
38    * <li>User Defined..</li>
39    * </ul>
40    * 
41    * @param colourMenu
42    *          the menu to attach items to
43    * @param client
44    *          a callback to handle menu selection
45    * @param coll
46    *          the data the menu is being built for
47    * @param simpleOnly
48    *          if true, only simple per-residue colour schemes are included
49    */
50   public static ButtonGroup addMenuItems(final JMenu colourMenu,
51           final ColourChangeListener client, AnnotatedCollectionI coll,
52           boolean simpleOnly)
53   {
54     /*
55      * ButtonGroup groups those items whose 
56      * selection is mutually exclusive
57      */
58     ButtonGroup colours = new ButtonGroup();
59
60     if (!simpleOnly)
61     {
62       JRadioButtonMenuItem noColourmenuItem = new JRadioButtonMenuItem(
63               MessageManager.getString("label.none"));
64       noColourmenuItem.setName(ResidueColourScheme.NONE);
65       noColourmenuItem.addActionListener(new ActionListener()
66       {
67         @Override
68         public void actionPerformed(ActionEvent e)
69         {
70           client.changeColour_actionPerformed(ResidueColourScheme.NONE);
71         }
72       });
73       colourMenu.add(noColourmenuItem);
74       colours.add(noColourmenuItem);
75     }
76
77     /*
78      * scan registered colour schemes (built-in or user-defined
79      * and add them to the menu (in the order they were added)
80      */
81     Iterable<ColourSchemeI> colourSchemes = ColourSchemes.getInstance()
82             .getColourSchemes();
83     for (ColourSchemeI scheme : colourSchemes)
84     {
85       if (simpleOnly && !scheme.isSimple())
86       {
87         continue;
88       }
89
90       /*
91        * button text is i18n'd but the name is the canonical name of
92        * the colour scheme (inspected in setColourSelected())
93        */
94       final String name = scheme.getSchemeName();
95       String label = MessageManager.getStringOrReturn("label.colourScheme_"
96               + name.toLowerCase().replace(" ", "_"), name);
97       final JRadioButtonMenuItem radioItem = new JRadioButtonMenuItem(label);
98       radioItem.setName(name);
99       radioItem.setEnabled(scheme.isApplicableTo(coll));
100       if (scheme instanceof UserColourScheme)
101       {
102         /*
103          * user-defined colour scheme loaded on startup or during the
104          * Jalview session; right-click on this offers the option to
105          * remove it as a colour choice
106          */
107         radioItem.addMouseListener(new MouseAdapter()
108         {
109           @Override
110           public void mousePressed(MouseEvent evt)
111           {
112             if (evt.isPopupTrigger()) // Mac
113             {
114               offerRemoval();
115             }
116           }
117
118           @Override
119           public void mouseReleased(MouseEvent evt)
120           {
121             if (evt.isPopupTrigger()) // Windows
122             {
123               offerRemoval();
124             }
125           }
126
127           void offerRemoval()
128           {
129             ActionListener al = radioItem.getActionListeners()[0];
130             radioItem.removeActionListener(al);
131             int option = JvOptionPane.showInternalConfirmDialog(
132                     Desktop.desktop, MessageManager
133                             .getString("label.remove_from_default_list"),
134                     MessageManager
135                             .getString("label.remove_user_defined_colour"),
136                     JvOptionPane.YES_NO_OPTION);
137             if (option == JvOptionPane.YES_OPTION)
138             {
139               UserDefinedColours.removeColourFromDefaults(radioItem
140                       .getName());
141               ColourSchemes.getInstance().removeColourScheme(
142                       radioItem.getName());
143               colourMenu.remove(radioItem);
144             }
145             else
146             {
147               radioItem.addActionListener(al);
148             }
149           }
150         });
151       }
152       radioItem.addActionListener(new ActionListener()
153       {
154         @Override
155         public void actionPerformed(ActionEvent evt)
156         {
157           client.changeColour_actionPerformed(name);
158         }
159       });
160       colourMenu.add(radioItem);
161       colours.add(radioItem);
162     }
163
164     /*
165      * only add the option to load/configure a user-defined colour
166      * to the AlignFrame colour menu
167      */
168     if (client instanceof AlignFrame)
169     {
170       final String label = MessageManager.getString("action.user_defined");
171       JRadioButtonMenuItem userDefinedColour = new JRadioButtonMenuItem(
172               label);
173       userDefinedColour.addActionListener(new ActionListener()
174       {
175         @Override
176         public void actionPerformed(ActionEvent e)
177         {
178           client.changeColour_actionPerformed(ResidueColourScheme.USER_DEFINED);
179         }
180       });
181       colourMenu.add(userDefinedColour);
182       colours.add(userDefinedColour);
183     }
184
185     return colours;
186   }
187
188   /**
189    * Marks as selected the colour menu item matching the given name, or the
190    * first item ('None') if no match is found
191    * 
192    * @param colourMenu
193    * @param colourName
194    */
195   public static void setColourSelected(JMenu colourMenu, String colourName)
196   {
197     if (colourName == null)
198     {
199       return;
200     }
201
202     JRadioButtonMenuItem none = null;
203
204     /*
205      * select the radio button whose name matches the colour name
206      * (not the button text, as it may be internationalised)
207      */
208     for (Component menuItem : colourMenu.getMenuComponents())
209     {
210       if (menuItem instanceof JRadioButtonMenuItem)
211       {
212         String buttonName = ((JRadioButtonMenuItem) menuItem).getName();
213         if (colourName.equals(buttonName))
214         {
215           ((JRadioButtonMenuItem) menuItem).setSelected(true);
216           return;
217         }
218         if (ResidueColourScheme.NONE.equals(buttonName))
219         {
220           none = (JRadioButtonMenuItem) menuItem;
221         }
222       }
223     }
224     if (none != null)
225     {
226       none.setSelected(true);
227     }
228   }
229
230   /**
231    * Marks as selected the colour menu item matching the given colour scheme, or
232    * the first item ('None') if no match is found
233    * 
234    * @param colourMenu
235    * @param cs
236    */
237   public static void setColourSelected(JMenu colourMenu, ColourSchemeI cs)
238   {
239     setColourSelected(colourMenu, cs == null ? ResidueColourScheme.NONE
240             : cs.getSchemeName());
241   }
242 }