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("label.colourScheme_",
125 final JRadioButtonMenuItem radioItem = new JRadioButtonMenuItem(
127 radioItem.setName(name);
128 radioItem.setEnabled(scheme.isApplicableTo(coll));
129 if (scheme instanceof UserColourScheme)
132 * user-defined colour scheme loaded on startup or during the
133 * Jalview session; right-click on this offers the option to
134 * remove it as a colour choice (unless currently selected)
136 radioItem.addMouseListener(new MouseAdapter()
139 public void mousePressed(MouseEvent evt)
141 if (evt.isPopupTrigger() && !radioItem.isSelected()) // Mac
148 public void mouseReleased(MouseEvent evt)
150 if (evt.isPopupTrigger() && !radioItem.isSelected()) // Windows
158 ActionListener al = radioItem.getActionListeners()[0];
159 radioItem.removeActionListener(al);
160 int option = JvOptionPane.showInternalConfirmDialog(
163 .getString("label.remove_from_default_list"),
165 .getString("label.remove_user_defined_colour"),
166 JvOptionPane.YES_NO_OPTION);
167 if (option == JvOptionPane.YES_OPTION)
169 ColourSchemes.getInstance()
170 .removeColourScheme(radioItem.getName());
171 colourMenu.remove(radioItem);
176 radioItem.addActionListener(al);
181 radioItem.addActionListener(new ActionListener()
184 public void actionPerformed(ActionEvent evt)
186 client.changeColour_actionPerformed(name);
189 colourMenu.add(radioItem);
190 colours.add(radioItem);
194 * only add the option to load/configure a user-defined colour
195 * to the AlignFrame colour menu
197 if (client instanceof AlignFrame)
199 final String label = MessageManager.getString("action.user_defined");
200 JRadioButtonMenuItem userDefinedColour = new JRadioButtonMenuItem(
202 userDefinedColour.setName(ResidueColourScheme.USER_DEFINED_MENU);
203 userDefinedColour.addActionListener(new ActionListener()
206 public void actionPerformed(ActionEvent e)
208 client.changeColour_actionPerformed(
209 ResidueColourScheme.USER_DEFINED_MENU);
212 colourMenu.add(userDefinedColour);
213 colours.add(userDefinedColour);
220 * Marks as selected the colour menu item matching the given colour scheme, or
221 * the first item ('None') if no match is found. If the colour scheme is a
222 * user defined scheme, but not in the menu (this arises if a new scheme is
223 * defined and applied but not saved to file), then menu option "User
224 * Defined.." is selected.
229 public static void setColourSelected(JMenu colourMenu, ColourSchemeI cs)
231 String colourName = cs == null ? ResidueColourScheme.NONE
232 : cs.getSchemeName();
234 JRadioButtonMenuItem none = null;
235 JRadioButtonMenuItem userDefined = null;
238 * select the radio button whose name matches the colour name
239 * (not the button text, as it may be internationalised)
241 for (Component menuItem : colourMenu.getMenuComponents())
243 if (menuItem instanceof JRadioButtonMenuItem)
245 JRadioButtonMenuItem radioButton = (JRadioButtonMenuItem) menuItem;
246 String buttonName = radioButton.getName();
247 if (buttonName.equals(colourName))
249 radioButton.setSelected(true);
252 if (ResidueColourScheme.NONE.equals(buttonName))
256 if (ResidueColourScheme.USER_DEFINED_MENU.equals(buttonName))
258 userDefined = radioButton;
264 * no match by name; select User Defined.. if current scheme is a
265 * user defined one, else select None
267 if (cs instanceof UserColourScheme && userDefined != null)
269 userDefined.setSelected(true);
271 else if (none != null)
273 none.setSelected(true);
278 * Updates the USER_DEFINE_COLOURS preference to remove any de-registered
281 static void updatePreferences()
283 StringBuilder coloursFound = new StringBuilder();
284 String[] files = Cache.getProperty("USER_DEFINED_COLOURS").split("\\|");
287 * the property does not include the scheme name, it is in the file;
288 * so just load the colour schemes and discard any whose name is not
291 for (String file : files)
295 UserColourScheme ucs = ColourSchemeLoader.loadColourScheme(file);
297 && ColourSchemes.getInstance().nameExists(ucs.getName()))
299 if (coloursFound.length() > 0)
301 coloursFound.append("|");
303 coloursFound.append(file);
305 } catch (Exception ex)
308 .outPrintln("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");