2 * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3 * Copyright (C) $$Year-Rel$$ The Jalview Authors
5 * This file is part of Jalview.
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.
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.
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.
23 import jalview.bin.Cache;
24 import jalview.datamodel.AnnotatedCollectionI;
25 import jalview.schemes.ColourSchemeI;
26 import jalview.schemes.ColourSchemeLoader;
27 import jalview.schemes.ColourSchemes;
28 import jalview.schemes.ResidueColourScheme;
29 import jalview.schemes.UserColourScheme;
30 import jalview.util.MessageManager;
32 import java.awt.Component;
33 import java.awt.event.ActionEvent;
34 import java.awt.event.ActionListener;
35 import java.awt.event.MouseAdapter;
36 import java.awt.event.MouseEvent;
38 import javax.swing.ButtonGroup;
39 import javax.swing.JMenu;
40 import javax.swing.JRadioButtonMenuItem;
42 public class ColourMenuHelper
44 public interface ColourChangeListener
47 * Change colour scheme to the selected scheme
50 * the registered (unique) name of a colour scheme
52 void changeColour_actionPerformed(String name);
56 * Adds items to the colour menu, as mutually exclusive members of a button
57 * group. The callback handler is responsible for the action on selecting any
58 * of these options. The callback method receives the name of the selected
59 * colour, or "None" or "User Defined". This method returns the ButtonGroup to
60 * which items were added.
64 * <li>...other 'built-in' colours</li>
65 * <li>...any user-defined colours</li>
66 * <li>User Defined..(only for AlignFrame menu)</li>
70 * the menu to attach items to
72 * a callback to handle menu selection
74 * the data the menu is being built for
76 * if true, only simple per-residue colour schemes are included
78 public static ButtonGroup addMenuItems(final JMenu colourMenu,
79 final ColourChangeListener client, AnnotatedCollectionI coll,
83 * ButtonGroup groups those items whose
84 * selection is mutually exclusive
86 ButtonGroup colours = new ButtonGroup();
90 JRadioButtonMenuItem noColourmenuItem = new JRadioButtonMenuItem(
91 MessageManager.getString("label.none"));
92 noColourmenuItem.setName(ResidueColourScheme.NONE);
93 noColourmenuItem.addActionListener(new ActionListener()
96 public void actionPerformed(ActionEvent e)
98 client.changeColour_actionPerformed(ResidueColourScheme.NONE);
101 colourMenu.add(noColourmenuItem);
102 colours.add(noColourmenuItem);
106 * scan registered colour schemes (built-in or user-defined)
107 * and add them to the menu (in the order they were registered)
109 Iterable<ColourSchemeI> colourSchemes = ColourSchemes.getInstance()
111 for (ColourSchemeI scheme : colourSchemes)
113 if (simpleOnly && !scheme.isSimple())
119 * button text is i18n'd but the name is the canonical name of
120 * the colour scheme (inspected in setColourSelected())
122 final String name = scheme.getSchemeName();
123 String label = MessageManager.getStringOrReturn(
124 "label.colourScheme_" + name.toLowerCase().replace(" ", "_"),
126 final JRadioButtonMenuItem radioItem = new JRadioButtonMenuItem(
128 radioItem.setName(name);
129 radioItem.setEnabled(scheme.isApplicableTo(coll));
130 if (scheme instanceof UserColourScheme)
133 * user-defined colour scheme loaded on startup or during the
134 * Jalview session; right-click on this offers the option to
135 * remove it as a colour choice (unless currently selected)
137 radioItem.addMouseListener(new MouseAdapter()
140 public void mousePressed(MouseEvent evt)
142 if (evt.isPopupTrigger() && !radioItem.isSelected()) // Mac
149 public void mouseReleased(MouseEvent evt)
151 if (evt.isPopupTrigger() && !radioItem.isSelected()) // Windows
159 ActionListener al = radioItem.getActionListeners()[0];
160 radioItem.removeActionListener(al);
161 int option = JvOptionPane.showInternalConfirmDialog(
164 .getString("label.remove_from_default_list"),
166 .getString("label.remove_user_defined_colour"),
167 JvOptionPane.YES_NO_OPTION);
168 if (option == JvOptionPane.YES_OPTION)
170 ColourSchemes.getInstance()
171 .removeColourScheme(radioItem.getName());
172 colourMenu.remove(radioItem);
177 radioItem.addActionListener(al);
182 radioItem.addActionListener(new ActionListener()
185 public void actionPerformed(ActionEvent evt)
187 client.changeColour_actionPerformed(name);
190 colourMenu.add(radioItem);
191 colours.add(radioItem);
195 * only add the option to load/configure a user-defined colour
196 * to the AlignFrame colour menu
198 if (client instanceof AlignFrame)
200 final String label = MessageManager.getString("action.user_defined");
201 JRadioButtonMenuItem userDefinedColour = new JRadioButtonMenuItem(
203 userDefinedColour.setName(ResidueColourScheme.USER_DEFINED_MENU);
204 userDefinedColour.addActionListener(new ActionListener()
207 public void actionPerformed(ActionEvent e)
209 client.changeColour_actionPerformed(
210 ResidueColourScheme.USER_DEFINED_MENU);
213 colourMenu.add(userDefinedColour);
214 colours.add(userDefinedColour);
221 * Marks as selected the colour menu item matching the given colour scheme, or
222 * the first item ('None') if no match is found. If the colour scheme is a
223 * user defined scheme, but not in the menu (this arises if a new scheme is
224 * defined and applied but not saved to file), then menu option "User
225 * Defined.." is selected.
230 public static void setColourSelected(JMenu colourMenu, ColourSchemeI cs)
232 String colourName = cs == null ? ResidueColourScheme.NONE
233 : cs.getSchemeName();
235 JRadioButtonMenuItem none = null;
236 JRadioButtonMenuItem userDefined = null;
239 * select the radio button whose name matches the colour name
240 * (not the button text, as it may be internationalised)
242 for (Component menuItem : colourMenu.getMenuComponents())
244 if (menuItem instanceof JRadioButtonMenuItem)
246 JRadioButtonMenuItem radioButton = (JRadioButtonMenuItem) menuItem;
247 String buttonName = radioButton.getName();
248 if (buttonName.equals(colourName))
250 radioButton.setSelected(true);
253 if (ResidueColourScheme.NONE.equals(buttonName))
257 if (ResidueColourScheme.USER_DEFINED_MENU.equals(buttonName))
259 userDefined = radioButton;
265 * no match by name; select User Defined.. if current scheme is a
266 * user defined one, else select None
268 if (cs instanceof UserColourScheme && userDefined != null)
270 userDefined.setSelected(true);
272 else if (none != null)
274 none.setSelected(true);
279 * Updates the USER_DEFINE_COLOURS preference to remove any de-registered
282 static void updatePreferences()
284 StringBuilder coloursFound = new StringBuilder();
285 String[] files = Cache.getProperty("USER_DEFINED_COLOURS").split("\\|");
288 * the property does not include the scheme name, it is in the file;
289 * so just load the colour schemes and discard any whose name is not
292 for (String file : files)
296 UserColourScheme ucs = ColourSchemeLoader.loadColourScheme(file);
298 && ColourSchemes.getInstance().nameExists(ucs.getName()))
300 if (coloursFound.length() > 0)
302 coloursFound.append("|");
304 coloursFound.append(file);
306 } catch (Exception ex)
308 System.out.println("Error loading User ColourFile\n" + ex);
312 if (coloursFound.toString().length() > 1)
314 Cache.setProperty("USER_DEFINED_COLOURS", coloursFound.toString());
318 Cache.applicationProperties.remove("USER_DEFINED_COLOURS");