3 import jalview.bin.Cache;
4 import jalview.datamodel.AnnotatedCollectionI;
5 import jalview.schemes.ColourSchemeI;
6 import jalview.schemes.ColourSchemeLoader;
7 import jalview.schemes.ColourSchemes;
8 import jalview.schemes.ResidueColourScheme;
9 import jalview.schemes.UserColourScheme;
10 import jalview.util.MessageManager;
12 import java.awt.Component;
13 import java.awt.event.ActionEvent;
14 import java.awt.event.ActionListener;
15 import java.awt.event.MouseAdapter;
16 import java.awt.event.MouseEvent;
18 import javax.swing.ButtonGroup;
19 import javax.swing.JMenu;
20 import javax.swing.JRadioButtonMenuItem;
22 public class ColourMenuHelper
24 public interface ColourChangeListener
27 * Change colour scheme to the selected scheme
30 * the registered (unique) name of a colour scheme
32 void changeColour_actionPerformed(String name);
36 * Adds items to the colour menu, as mutually exclusive members of a button
37 * group. The callback handler is responsible for the action on selecting any
38 * of these options. The callback method receives the name of the selected
39 * colour, or "None" or "User Defined". This method returns the ButtonGroup to
40 * which items were added.
44 * <li>...other 'built-in' colours</li>
45 * <li>...any user-defined colours</li>
46 * <li>User Defined..(only for AlignFrame menu)</li>
50 * the menu to attach items to
52 * a callback to handle menu selection
54 * the data the menu is being built for
56 * if true, only simple per-residue colour schemes are included
58 public static ButtonGroup addMenuItems(final JMenu colourMenu,
59 final ColourChangeListener client, AnnotatedCollectionI coll,
63 * ButtonGroup groups those items whose
64 * selection is mutually exclusive
66 ButtonGroup colours = new ButtonGroup();
70 JRadioButtonMenuItem noColourmenuItem = new JRadioButtonMenuItem(
71 MessageManager.getString("label.none"));
72 noColourmenuItem.setName(ResidueColourScheme.NONE);
73 noColourmenuItem.addActionListener(new ActionListener()
76 public void actionPerformed(ActionEvent e)
78 client.changeColour_actionPerformed(ResidueColourScheme.NONE);
81 colourMenu.add(noColourmenuItem);
82 colours.add(noColourmenuItem);
86 * scan registered colour schemes (built-in or user-defined)
87 * and add them to the menu (in the order they were registered)
89 Iterable<ColourSchemeI> colourSchemes = ColourSchemes.getInstance()
91 for (ColourSchemeI scheme : colourSchemes)
93 if (simpleOnly && !scheme.isSimple())
99 * button text is i18n'd but the name is the canonical name of
100 * the colour scheme (inspected in setColourSelected())
102 final String name = scheme.getSchemeName();
103 String label = MessageManager.getStringOrReturn("label.colourScheme_"
104 + name.toLowerCase().replace(" ", "_"), name);
105 final JRadioButtonMenuItem radioItem = new JRadioButtonMenuItem(label);
106 radioItem.setName(name);
107 radioItem.setEnabled(scheme.isApplicableTo(coll));
108 if (scheme instanceof UserColourScheme)
111 * user-defined colour scheme loaded on startup or during the
112 * Jalview session; right-click on this offers the option to
113 * remove it as a colour choice (unless currently selected)
115 radioItem.addMouseListener(new MouseAdapter()
118 public void mousePressed(MouseEvent evt)
120 if (evt.isPopupTrigger() && !radioItem.isSelected()) // Mac
127 public void mouseReleased(MouseEvent evt)
129 if (evt.isPopupTrigger() && !radioItem.isSelected()) // Windows
137 ActionListener al = radioItem.getActionListeners()[0];
138 radioItem.removeActionListener(al);
139 int option = JvOptionPane.showInternalConfirmDialog(
140 Desktop.desktop, MessageManager
141 .getString("label.remove_from_default_list"),
143 .getString("label.remove_user_defined_colour"),
144 JvOptionPane.YES_NO_OPTION);
145 if (option == JvOptionPane.YES_OPTION)
147 ColourSchemes.getInstance().removeColourScheme(
148 radioItem.getName());
149 colourMenu.remove(radioItem);
154 radioItem.addActionListener(al);
159 radioItem.addActionListener(new ActionListener()
162 public void actionPerformed(ActionEvent evt)
164 client.changeColour_actionPerformed(name);
167 colourMenu.add(radioItem);
168 colours.add(radioItem);
172 * only add the option to load/configure a user-defined colour
173 * to the AlignFrame colour menu
175 if (client instanceof AlignFrame)
177 final String label = MessageManager.getString("action.user_defined");
178 JRadioButtonMenuItem userDefinedColour = new JRadioButtonMenuItem(
180 userDefinedColour.setName(ResidueColourScheme.USER_DEFINED);
181 userDefinedColour.addActionListener(new ActionListener()
184 public void actionPerformed(ActionEvent e)
186 client.changeColour_actionPerformed(ResidueColourScheme.USER_DEFINED);
189 colourMenu.add(userDefinedColour);
190 colours.add(userDefinedColour);
197 * Marks as selected the colour menu item matching the given colour scheme, or
198 * the first item ('None') if no match is found. If the colour scheme is a
199 * user defined scheme, but not in the menu (this arises if a new scheme is
200 * defined and applied but not saved to file), then menu option
201 * "User Defined.." is selected.
206 public static void setColourSelected(JMenu colourMenu, ColourSchemeI cs)
208 String colourName = cs == null ? ResidueColourScheme.NONE : cs
211 JRadioButtonMenuItem none = null;
212 JRadioButtonMenuItem userDefined = null;
215 * select the radio button whose name matches the colour name
216 * (not the button text, as it may be internationalised)
218 for (Component menuItem : colourMenu.getMenuComponents())
220 if (menuItem instanceof JRadioButtonMenuItem)
222 JRadioButtonMenuItem radioButton = (JRadioButtonMenuItem) menuItem;
223 String buttonName = radioButton.getName();
224 if (buttonName.equals(colourName))
226 radioButton.setSelected(true);
229 if (ResidueColourScheme.NONE.equals(buttonName))
233 if (ResidueColourScheme.USER_DEFINED.equals(buttonName))
235 userDefined = radioButton;
241 * no match by name; select User Defined.. if current scheme is a
242 * user defined one, else select None
244 if (cs instanceof UserColourScheme && userDefined != null)
246 userDefined.setSelected(true);
248 else if (none != null)
250 none.setSelected(true);
255 * Updates the USER_DEFINE_COLOURS preference to remove any de-registered
258 static void updatePreferences()
260 StringBuilder coloursFound = new StringBuilder();
261 String[] files = Cache.getProperty("USER_DEFINED_COLOURS").split("\\|");
264 * the property does not include the scheme name, it is in the file;
265 * so just load the colour schemes and discard any whose name is not
268 for (String file : files)
272 UserColourScheme ucs = ColourSchemeLoader.loadColourScheme(file);
274 && ColourSchemes.getInstance().nameExists(ucs.getName()))
276 if (coloursFound.length() > 0)
278 coloursFound.append("|");
280 coloursFound.append(file);
282 } catch (Exception ex)
284 System.out.println("Error loading User ColourFile\n" + ex);
288 if (coloursFound.toString().length() > 1)
290 Cache.setProperty("USER_DEFINED_COLOURS", coloursFound.toString());
294 Cache.applicationProperties.remove("USER_DEFINED_COLOURS");