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(
104 "label.colourScheme_" + name.toLowerCase().replace(" ", "_"),
106 final JRadioButtonMenuItem radioItem = new JRadioButtonMenuItem(
108 radioItem.setName(name);
109 radioItem.setEnabled(scheme.isApplicableTo(coll));
110 if (scheme instanceof UserColourScheme)
113 * user-defined colour scheme loaded on startup or during the
114 * Jalview session; right-click on this offers the option to
115 * remove it as a colour choice (unless currently selected)
117 radioItem.addMouseListener(new MouseAdapter()
120 public void mousePressed(MouseEvent evt)
122 if (evt.isPopupTrigger() && !radioItem.isSelected()) // Mac
129 public void mouseReleased(MouseEvent evt)
131 if (evt.isPopupTrigger() && !radioItem.isSelected()) // Windows
139 ActionListener al = radioItem.getActionListeners()[0];
140 radioItem.removeActionListener(al);
141 int option = JvOptionPane.showInternalConfirmDialog(
144 .getString("label.remove_from_default_list"),
146 .getString("label.remove_user_defined_colour"),
147 JvOptionPane.YES_NO_OPTION);
148 if (option == JvOptionPane.YES_OPTION)
150 ColourSchemes.getInstance()
151 .removeColourScheme(radioItem.getName());
152 colourMenu.remove(radioItem);
157 radioItem.addActionListener(al);
162 radioItem.addActionListener(new ActionListener()
165 public void actionPerformed(ActionEvent evt)
167 client.changeColour_actionPerformed(name);
170 colourMenu.add(radioItem);
171 colours.add(radioItem);
175 * only add the option to load/configure a user-defined colour
176 * to the AlignFrame colour menu
178 if (client instanceof AlignFrame)
180 final String label = MessageManager.getString("action.user_defined");
181 JRadioButtonMenuItem userDefinedColour = new JRadioButtonMenuItem(
183 userDefinedColour.setName(ResidueColourScheme.USER_DEFINED_MENU);
184 userDefinedColour.addActionListener(new ActionListener()
187 public void actionPerformed(ActionEvent e)
189 client.changeColour_actionPerformed(
190 ResidueColourScheme.USER_DEFINED_MENU);
193 colourMenu.add(userDefinedColour);
194 colours.add(userDefinedColour);
201 * Marks as selected the colour menu item matching the given colour scheme, or
202 * the first item ('None') if no match is found. If the colour scheme is a
203 * user defined scheme, but not in the menu (this arises if a new scheme is
204 * defined and applied but not saved to file), then menu option "User
205 * Defined.." is selected.
210 public static void setColourSelected(JMenu colourMenu, ColourSchemeI cs)
212 String colourName = cs == null ? ResidueColourScheme.NONE
213 : cs.getSchemeName();
215 JRadioButtonMenuItem none = null;
216 JRadioButtonMenuItem userDefined = null;
219 * select the radio button whose name matches the colour name
220 * (not the button text, as it may be internationalised)
222 for (Component menuItem : colourMenu.getMenuComponents())
224 if (menuItem instanceof JRadioButtonMenuItem)
226 JRadioButtonMenuItem radioButton = (JRadioButtonMenuItem) menuItem;
227 String buttonName = radioButton.getName();
228 if (buttonName.equals(colourName))
230 radioButton.setSelected(true);
233 if (ResidueColourScheme.NONE.equals(buttonName))
237 if (ResidueColourScheme.USER_DEFINED_MENU.equals(buttonName))
239 userDefined = radioButton;
245 * no match by name; select User Defined.. if current scheme is a
246 * user defined one, else select None
248 if (cs instanceof UserColourScheme && userDefined != null)
250 userDefined.setSelected(true);
252 else if (none != null)
254 none.setSelected(true);
259 * Updates the USER_DEFINE_COLOURS preference to remove any de-registered
262 static void updatePreferences()
264 StringBuilder coloursFound = new StringBuilder();
265 String[] files = Cache.getProperty("USER_DEFINED_COLOURS").split("\\|");
268 * the property does not include the scheme name, it is in the file;
269 * so just load the colour schemes and discard any whose name is not
272 for (String file : files)
276 UserColourScheme ucs = ColourSchemeLoader.loadColourScheme(file);
278 && ColourSchemes.getInstance().nameExists(ucs.getName()))
280 if (coloursFound.length() > 0)
282 coloursFound.append("|");
284 coloursFound.append(file);
286 } catch (Exception ex)
288 System.out.println("Error loading User ColourFile\n" + ex);
292 if (coloursFound.toString().length() > 1)
294 Cache.setProperty("USER_DEFINED_COLOURS", coloursFound.toString());
298 Cache.applicationProperties.remove("USER_DEFINED_COLOURS");