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 public static ButtonGroup addMenuItems(final JMenu colourMenu,
77 final ColourChangeListener client, AnnotatedCollectionI coll)
80 * ButtonGroup groups those items whose
81 * selection is mutually exclusive
83 ButtonGroup colours = new ButtonGroup();
85 JRadioButtonMenuItem noColourmenuItem = new JRadioButtonMenuItem(MessageManager.getString("label.none"));
86 noColourmenuItem.setName(ResidueColourScheme.NONE);
87 noColourmenuItem.addActionListener(new ActionListener()
90 public void actionPerformed(ActionEvent e)
92 client.changeColour_actionPerformed(ResidueColourScheme.NONE);
95 colourMenu.add(noColourmenuItem);
96 colours.add(noColourmenuItem);
99 * scan registered colour schemes (built-in or user-defined)
100 * and add them to the menu (in the order they were registered)
102 Iterable<ColourSchemeI> colourSchemes = ColourSchemes.getInstance()
104 for (ColourSchemeI scheme : colourSchemes)
107 * button text is i18n'd but the name is the canonical name of
108 * the colour scheme (inspected in setColourSelected())
110 final String name = scheme.getSchemeName();
111 String label = MessageManager.getStringOrReturn(
112 "label.colourScheme_" + name.toLowerCase().replace(" ", "_"),
114 final JRadioButtonMenuItem radioItem = new JRadioButtonMenuItem(
116 radioItem.setName(name);
117 radioItem.setEnabled(scheme.isApplicableTo(coll));
118 if (scheme instanceof UserColourScheme)
121 * user-defined colour scheme loaded on startup or during the
122 * Jalview session; right-click on this offers the option to
123 * remove it as a colour choice (unless currently selected)
125 radioItem.addMouseListener(new MouseAdapter()
128 public void mousePressed(MouseEvent evt)
130 if (evt.isPopupTrigger() && !radioItem.isSelected()) // Mac
137 public void mouseReleased(MouseEvent evt)
139 if (evt.isPopupTrigger() && !radioItem.isSelected()) // Windows
147 ActionListener al = radioItem.getActionListeners()[0];
148 radioItem.removeActionListener(al);
149 int option = JvOptionPane.showInternalConfirmDialog(
152 .getString("label.remove_from_default_list"),
154 .getString("label.remove_user_defined_colour"),
155 JvOptionPane.YES_NO_OPTION);
156 if (option == JvOptionPane.YES_OPTION)
158 ColourSchemes.getInstance()
159 .removeColourScheme(radioItem.getName());
160 colourMenu.remove(radioItem);
165 radioItem.addActionListener(al);
170 radioItem.addActionListener(new ActionListener()
173 public void actionPerformed(ActionEvent evt)
175 client.changeColour_actionPerformed(name);
178 colourMenu.add(radioItem);
179 colours.add(radioItem);
183 * only add the option to load/configure a user-defined colour
184 * to the AlignFrame colour menu
186 if (client instanceof AlignFrame)
188 final String label = MessageManager.getString("action.user_defined");
189 JRadioButtonMenuItem userDefinedColour = new JRadioButtonMenuItem(
191 userDefinedColour.setName(ResidueColourScheme.USER_DEFINED_MENU);
192 userDefinedColour.addActionListener(new ActionListener()
195 public void actionPerformed(ActionEvent e)
197 client.changeColour_actionPerformed(
198 ResidueColourScheme.USER_DEFINED_MENU);
201 colourMenu.add(userDefinedColour);
202 colours.add(userDefinedColour);
209 * Marks as selected the colour menu item matching the given colour scheme, or
210 * the first item ('None') if no match is found. If the colour scheme is a
211 * user defined scheme, but not in the menu (this arises if a new scheme is
212 * defined and applied but not saved to file), then menu option "User
213 * Defined.." is selected.
218 public static void setColourSelected(JMenu colourMenu, ColourSchemeI cs)
220 String colourName = cs == null ? ResidueColourScheme.NONE
221 : cs.getSchemeName();
223 JRadioButtonMenuItem none = null;
224 JRadioButtonMenuItem userDefined = null;
227 * select the radio button whose name matches the colour name
228 * (not the button text, as it may be internationalised)
230 for (Component menuItem : colourMenu.getMenuComponents())
232 if (menuItem instanceof JRadioButtonMenuItem)
234 JRadioButtonMenuItem radioButton = (JRadioButtonMenuItem) menuItem;
235 String buttonName = radioButton.getName();
236 if (buttonName.equals(colourName))
238 radioButton.setSelected(true);
241 if (ResidueColourScheme.NONE.equals(buttonName))
245 if (ResidueColourScheme.USER_DEFINED_MENU.equals(buttonName))
247 userDefined = radioButton;
253 * no match by name; select User Defined.. if current scheme is a
254 * user defined one, else select None
256 if (cs instanceof UserColourScheme && userDefined != null)
258 userDefined.setSelected(true);
260 else if (none != null)
262 none.setSelected(true);
267 * Updates the USER_DEFINE_COLOURS preference to remove any de-registered
270 static void updatePreferences()
272 StringBuilder coloursFound = new StringBuilder();
273 String[] files = Cache.getProperty("USER_DEFINED_COLOURS").split("\\|");
276 * the property does not include the scheme name, it is in the file;
277 * so just load the colour schemes and discard any whose name is not
280 for (String file : files)
284 UserColourScheme ucs = ColourSchemeLoader.loadColourScheme(file);
286 && ColourSchemes.getInstance().nameExists(ucs.getName()))
288 if (coloursFound.length() > 0)
290 coloursFound.append("|");
292 coloursFound.append(file);
294 } catch (Exception ex)
296 System.out.println("Error loading User ColourFile\n" + ex);
300 if (coloursFound.toString().length() > 1)
302 Cache.setProperty("USER_DEFINED_COLOURS", coloursFound.toString());
306 Cache.applicationProperties.remove("USER_DEFINED_COLOURS");