X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fjalview%2Fgui%2FColourMenuHelper.java;fp=src%2Fjalview%2Fgui%2FColourMenuHelper.java;h=19ad9393cb9431fb5427634a9eabcc8207159ef8;hb=2595e9d4ee0dbbd3406a98c4e49a61ccde806479;hp=0000000000000000000000000000000000000000;hpb=e20075ba805d744d7cc4976e2b8d5e5840fb0a8d;p=jalview.git diff --git a/src/jalview/gui/ColourMenuHelper.java b/src/jalview/gui/ColourMenuHelper.java new file mode 100644 index 0000000..19ad939 --- /dev/null +++ b/src/jalview/gui/ColourMenuHelper.java @@ -0,0 +1,287 @@ +package jalview.gui; + +import jalview.bin.Cache; +import jalview.datamodel.AnnotatedCollectionI; +import jalview.schemes.ColourSchemeI; +import jalview.schemes.ColourSchemeLoader; +import jalview.schemes.ColourSchemes; +import jalview.schemes.ResidueColourScheme; +import jalview.schemes.UserColourScheme; +import jalview.util.MessageManager; + +import java.awt.Component; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; + +import javax.swing.ButtonGroup; +import javax.swing.JMenu; +import javax.swing.JRadioButtonMenuItem; + +public class ColourMenuHelper +{ + public interface ColourChangeListener + { + void changeColour_actionPerformed(String name); + } + + /** + * Adds items to the colour menu, as mutually exclusive members of a button + * group. The callback handler is responsible for the action on selecting any + * of these options. The callback method receives the name of the selected + * colour, or "None" or "User Defined". This method returns the ButtonGroup to + * which items were added. + * + * + * @param colourMenu + * the menu to attach items to + * @param client + * a callback to handle menu selection + * @param coll + * the data the menu is being built for + * @param simpleOnly + * if true, only simple per-residue colour schemes are included + */ + public static ButtonGroup addMenuItems(final JMenu colourMenu, + final ColourChangeListener client, AnnotatedCollectionI coll, + boolean simpleOnly) + { + /* + * ButtonGroup groups those items whose + * selection is mutually exclusive + */ + ButtonGroup colours = new ButtonGroup(); + + if (!simpleOnly) + { + JRadioButtonMenuItem noColourmenuItem = new JRadioButtonMenuItem( + MessageManager.getString("label.none")); + noColourmenuItem.setName(ResidueColourScheme.NONE); + noColourmenuItem.addActionListener(new ActionListener() + { + @Override + public void actionPerformed(ActionEvent e) + { + client.changeColour_actionPerformed(ResidueColourScheme.NONE); + } + }); + colourMenu.add(noColourmenuItem); + colours.add(noColourmenuItem); + } + + /* + * scan registered colour schemes (built-in or user-defined + * and add them to the menu (in the order they were registered) + */ + Iterable colourSchemes = ColourSchemes.getInstance() + .getColourSchemes(); + for (ColourSchemeI scheme : colourSchemes) + { + if (simpleOnly && !scheme.isSimple()) + { + continue; + } + + /* + * button text is i18n'd but the name is the canonical name of + * the colour scheme (inspected in setColourSelected()) + */ + final String name = scheme.getSchemeName(); + String label = MessageManager.getStringOrReturn("label.colourScheme_" + + name.toLowerCase().replace(" ", "_"), name); + final JRadioButtonMenuItem radioItem = new JRadioButtonMenuItem(label); + radioItem.setName(name); + radioItem.setEnabled(scheme.isApplicableTo(coll)); + if (scheme instanceof UserColourScheme) + { + /* + * user-defined colour scheme loaded on startup or during the + * Jalview session; right-click on this offers the option to + * remove it as a colour choice + */ + radioItem.addMouseListener(new MouseAdapter() + { + @Override + public void mousePressed(MouseEvent evt) + { + if (evt.isPopupTrigger()) // Mac + { + offerRemoval(); + } + } + + @Override + public void mouseReleased(MouseEvent evt) + { + if (evt.isPopupTrigger()) // Windows + { + offerRemoval(); + } + } + + void offerRemoval() + { + ActionListener al = radioItem.getActionListeners()[0]; + radioItem.removeActionListener(al); + int option = JvOptionPane.showInternalConfirmDialog( + Desktop.desktop, MessageManager + .getString("label.remove_from_default_list"), + MessageManager + .getString("label.remove_user_defined_colour"), + JvOptionPane.YES_NO_OPTION); + if (option == JvOptionPane.YES_OPTION) + { + ColourSchemes.getInstance().removeColourScheme( + radioItem.getName()); + colourMenu.remove(radioItem); + updatePreferences(); + } + else + { + radioItem.addActionListener(al); + } + } + }); + } + radioItem.addActionListener(new ActionListener() + { + @Override + public void actionPerformed(ActionEvent evt) + { + client.changeColour_actionPerformed(name); + } + }); + colourMenu.add(radioItem); + colours.add(radioItem); + } + + /* + * only add the option to load/configure a user-defined colour + * to the AlignFrame colour menu + */ + if (client instanceof AlignFrame) + { + final String label = MessageManager.getString("action.user_defined"); + JRadioButtonMenuItem userDefinedColour = new JRadioButtonMenuItem( + label); + userDefinedColour.addActionListener(new ActionListener() + { + @Override + public void actionPerformed(ActionEvent e) + { + client.changeColour_actionPerformed(ResidueColourScheme.USER_DEFINED); + } + }); + colourMenu.add(userDefinedColour); + colours.add(userDefinedColour); + } + + return colours; + } + + /** + * Marks as selected the colour menu item matching the given name, or the + * first item ('None') if no match is found + * + * @param colourMenu + * @param colourName + */ + public static void setColourSelected(JMenu colourMenu, String colourName) + { + if (colourName == null) + { + return; + } + + JRadioButtonMenuItem none = null; + + /* + * select the radio button whose name matches the colour name + * (not the button text, as it may be internationalised) + */ + for (Component menuItem : colourMenu.getMenuComponents()) + { + if (menuItem instanceof JRadioButtonMenuItem) + { + String buttonName = ((JRadioButtonMenuItem) menuItem).getName(); + if (colourName.equals(buttonName)) + { + ((JRadioButtonMenuItem) menuItem).setSelected(true); + return; + } + if (ResidueColourScheme.NONE.equals(buttonName)) + { + none = (JRadioButtonMenuItem) menuItem; + } + } + } + if (none != null) + { + none.setSelected(true); + } + } + + /** + * Marks as selected the colour menu item matching the given colour scheme, or + * the first item ('None') if no match is found + * + * @param colourMenu + * @param cs + */ + public static void setColourSelected(JMenu colourMenu, ColourSchemeI cs) + { + setColourSelected(colourMenu, cs == null ? ResidueColourScheme.NONE + : cs.getSchemeName()); + } + + /** + * Updates the USER_DEFINE_COLOURS preference to remove any de-registered + * colour scheme + */ + static void updatePreferences() + { + StringBuilder coloursFound = new StringBuilder(); + String[] files = Cache.getProperty("USER_DEFINED_COLOURS").split("\\|"); + + /* + * the property does not include the scheme name, it is in the file; + * so just load the colour schemes and discard any whose name is not + * registered + */ + for (String file : files) + { + try + { + UserColourScheme ucs = ColourSchemeLoader.loadColourScheme(file); + if (ucs != null + && ColourSchemes.getInstance().nameExists(ucs.getName())) + { + if (coloursFound.length() > 0) + { + coloursFound.append("|"); + } + coloursFound.append(file); + } + } catch (Exception ex) + { + System.out.println("Error loading User ColourFile\n" + ex); + } + } + + if (coloursFound.toString().length() > 1) + { + Cache.setProperty("USER_DEFINED_COLOURS", coloursFound.toString()); + } + else + { + Cache.applicationProperties.remove("USER_DEFINED_COLOURS"); + } + } +}