Merge branch 'develop' into bug/JAL-2255_seq-fetcher-broken-on-linux
[jalview.git] / src / jalview / gui / PopupMenu.java
index 7ab6022..d91fa70 100644 (file)
@@ -38,23 +38,16 @@ import jalview.datamodel.Sequence;
 import jalview.datamodel.SequenceFeature;
 import jalview.datamodel.SequenceGroup;
 import jalview.datamodel.SequenceI;
+import jalview.gui.ColourMenuHelper.ColourChangeListener;
+import jalview.io.FileFormatI;
+import jalview.io.FileFormats;
 import jalview.io.FormatAdapter;
 import jalview.io.SequenceAnnotationReport;
-import jalview.schemes.AnnotationColourGradient;
 import jalview.schemes.Blosum62ColourScheme;
-import jalview.schemes.BuriedColourScheme;
-import jalview.schemes.ClustalxColourScheme;
-import jalview.schemes.HelixColourScheme;
-import jalview.schemes.HydrophobicColourScheme;
-import jalview.schemes.NucleotideColourScheme;
+import jalview.schemes.ColourSchemeI;
+import jalview.schemes.ColourSchemes;
 import jalview.schemes.PIDColourScheme;
-import jalview.schemes.PurinePyrimidineColourScheme;
-import jalview.schemes.StrandColourScheme;
-import jalview.schemes.TaylorColourScheme;
-import jalview.schemes.TurnColourScheme;
-import jalview.schemes.UserColourScheme;
-import jalview.schemes.ZappoColourScheme;
-import jalview.util.DBRefUtils;
+import jalview.schemes.ResidueColourScheme;
 import jalview.util.GroupUrlLink;
 import jalview.util.GroupUrlLink.UrlStringTooLongException;
 import jalview.util.MessageManager;
@@ -63,24 +56,22 @@ import jalview.util.UrlLink;
 import java.awt.Color;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
-import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.Hashtable;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.SortedMap;
 import java.util.TreeMap;
 import java.util.Vector;
 
-import javax.swing.ButtonGroup;
 import javax.swing.JCheckBoxMenuItem;
 import javax.swing.JColorChooser;
 import javax.swing.JMenu;
 import javax.swing.JMenuItem;
-import javax.swing.JOptionPane;
 import javax.swing.JPopupMenu;
-import javax.swing.JRadioButtonMenuItem;
 
 /**
  * DOCUMENT ME!
@@ -88,44 +79,20 @@ import javax.swing.JRadioButtonMenuItem;
  * @author $author$
  * @version $Revision: 1.118 $
  */
-public class PopupMenu extends JPopupMenu
+public class PopupMenu extends JPopupMenu implements ColourChangeListener
 {
   JMenu groupMenu = new JMenu();
 
   JMenuItem groupName = new JMenuItem();
 
-  protected JRadioButtonMenuItem clustalColour = new JRadioButtonMenuItem();
-
-  protected JRadioButtonMenuItem zappoColour = new JRadioButtonMenuItem();
-
-  protected JRadioButtonMenuItem taylorColour = new JRadioButtonMenuItem();
-
-  protected JRadioButtonMenuItem hydrophobicityColour = new JRadioButtonMenuItem();
-
-  protected JRadioButtonMenuItem helixColour = new JRadioButtonMenuItem();
-
-  protected JRadioButtonMenuItem strandColour = new JRadioButtonMenuItem();
-
-  protected JRadioButtonMenuItem turnColour = new JRadioButtonMenuItem();
-
-  protected JRadioButtonMenuItem buriedColour = new JRadioButtonMenuItem();
-
   protected JCheckBoxMenuItem abovePIDColour = new JCheckBoxMenuItem();
 
-  protected JRadioButtonMenuItem userDefinedColour = new JRadioButtonMenuItem();
-
-  protected JRadioButtonMenuItem PIDColour = new JRadioButtonMenuItem();
-
-  protected JRadioButtonMenuItem BLOSUM62Colour = new JRadioButtonMenuItem();
-
-  protected JRadioButtonMenuItem purinePyrimidineColour = new JRadioButtonMenuItem();
-
-  protected JRadioButtonMenuItem RNAInteractionColour = new JRadioButtonMenuItem();
-
-  JRadioButtonMenuItem noColourmenuItem = new JRadioButtonMenuItem();
+  protected JMenuItem modifyPID = new JMenuItem();
 
   protected JCheckBoxMenuItem conservationMenuItem = new JCheckBoxMenuItem();
 
+  protected JMenuItem modifyConservation = new JMenuItem();
+
   AlignmentPanel ap;
 
   JMenu sequenceMenu = new JMenu();
@@ -148,8 +115,6 @@ public class PopupMenu extends JPopupMenu
 
   JMenuItem outline = new JMenuItem();
 
-  JRadioButtonMenuItem nucleotideMenuItem = new JRadioButtonMenuItem();
-
   JMenu colourMenu = new JMenu();
 
   JCheckBoxMenuItem showBoxes = new JCheckBoxMenuItem();
@@ -238,29 +203,11 @@ public class PopupMenu extends JPopupMenu
     this.ap = ap;
     sequence = seq;
 
-    ButtonGroup colours = new ButtonGroup();
-    colours.add(noColourmenuItem);
-    colours.add(clustalColour);
-    colours.add(zappoColour);
-    colours.add(taylorColour);
-    colours.add(hydrophobicityColour);
-    colours.add(helixColour);
-    colours.add(strandColour);
-    colours.add(turnColour);
-    colours.add(buriedColour);
-    colours.add(abovePIDColour);
-    colours.add(userDefinedColour);
-    colours.add(PIDColour);
-    colours.add(BLOSUM62Colour);
-    colours.add(purinePyrimidineColour);
-    colours.add(RNAInteractionColour);
-
-    for (int i = 0; i < jalview.io.FormatAdapter.WRITEABLE_FORMATS.length; i++)
-    {
-      JMenuItem item = new JMenuItem(
-              jalview.io.FormatAdapter.WRITEABLE_FORMATS[i]);
-
-      item.addActionListener(new java.awt.event.ActionListener()
+    for (String ff : FileFormats.getInstance().getWritableFormats(true))
+    {
+      JMenuItem item = new JMenuItem(ff);
+
+      item.addActionListener(new ActionListener()
       {
         @Override
         public void actionPerformed(ActionEvent e)
@@ -344,7 +291,7 @@ public class PopupMenu extends JPopupMenu
               menuItem.setText(MessageManager.formatMessage(
                       "label.2d_rna_structure_line",
                       new Object[] { aa.label }));
-              menuItem.addActionListener(new java.awt.event.ActionListener()
+              menuItem.addActionListener(new ActionListener()
               {
                 @Override
                 public void actionPerformed(ActionEvent e)
@@ -372,7 +319,7 @@ public class PopupMenu extends JPopupMenu
               menuItem.setText(MessageManager.formatMessage(
                       "label.2d_rna_sequence_name",
                       new Object[] { seq.getName() }));
-              menuItem.addActionListener(new java.awt.event.ActionListener()
+              menuItem.addActionListener(new ActionListener()
               {
                 @Override
                 public void actionPerformed(ActionEvent e)
@@ -393,7 +340,7 @@ public class PopupMenu extends JPopupMenu
 
       menuItem = new JMenuItem(
               MessageManager.getString("action.hide_sequences"));
-      menuItem.addActionListener(new java.awt.event.ActionListener()
+      menuItem.addActionListener(new ActionListener()
       {
         @Override
         public void actionPerformed(ActionEvent e)
@@ -409,7 +356,7 @@ public class PopupMenu extends JPopupMenu
         menuItem = new JMenuItem(MessageManager.formatMessage(
                 "label.represent_group_with",
                 new Object[] { seq.getName() }));
-        menuItem.addActionListener(new java.awt.event.ActionListener()
+        menuItem.addActionListener(new ActionListener()
         {
           @Override
           public void actionPerformed(ActionEvent e)
@@ -466,7 +413,6 @@ public class PopupMenu extends JPopupMenu
 
         add(menuItem);
       }
-
     }
 
     SequenceGroup sg = ap.av.getSelectionGroup();
@@ -478,68 +424,23 @@ public class PopupMenu extends JPopupMenu
       groupName.setText(MessageManager
               .getString("label.edit_name_and_description_current_group"));
 
-      if (sg.cs instanceof ZappoColourScheme)
-      {
-        zappoColour.setSelected(true);
-      }
-      else if (sg.cs instanceof TaylorColourScheme)
-      {
-        taylorColour.setSelected(true);
-      }
-      else if (sg.cs instanceof PIDColourScheme)
-      {
-        PIDColour.setSelected(true);
-      }
-      else if (sg.cs instanceof Blosum62ColourScheme)
-      {
-        BLOSUM62Colour.setSelected(true);
-      }
-      else if (sg.cs instanceof UserColourScheme)
-      {
-        userDefinedColour.setSelected(true);
-      }
-      else if (sg.cs instanceof HydrophobicColourScheme)
-      {
-        hydrophobicityColour.setSelected(true);
-      }
-      else if (sg.cs instanceof HelixColourScheme)
-      {
-        helixColour.setSelected(true);
-      }
-      else if (sg.cs instanceof StrandColourScheme)
-      {
-        strandColour.setSelected(true);
-      }
-      else if (sg.cs instanceof TurnColourScheme)
-      {
-        turnColour.setSelected(true);
-      }
-      else if (sg.cs instanceof BuriedColourScheme)
-      {
-        buriedColour.setSelected(true);
-      }
-      else if (sg.cs instanceof ClustalxColourScheme)
-      {
-        clustalColour.setSelected(true);
-      }
-      else if (sg.cs instanceof PurinePyrimidineColourScheme)
-      {
-        purinePyrimidineColour.setSelected(true);
-      }
+      ColourMenuHelper.setColourSelected(colourMenu, sg.getColourScheme());
 
-      /*
-       * else if (sg.cs instanceof CovariationColourScheme) {
-       * covariationColour.setSelected(true); }
-       */
-      else
-      {
-        noColourmenuItem.setSelected(true);
-      }
+      conservationMenuItem.setEnabled(!sg.isNucleotide());
 
-      if (sg.cs != null && sg.cs.conservationApplied())
+      if (sg.cs != null)
       {
-        conservationMenuItem.setSelected(true);
+        if (sg.cs.conservationApplied())
+        {
+          conservationMenuItem.setSelected(true);
+        }
+        if (sg.cs.getThreshold() > 0)
+        {
+          abovePIDColour.setSelected(true);
+        }
       }
+      modifyConservation.setEnabled(conservationMenuItem.isSelected());
+      modifyPID.setEnabled(abovePIDColour.isSelected());
       displayNonconserved.setSelected(sg.getShowNonconserved());
       showText.setSelected(sg.getDisplayText());
       showColourText.setSelected(sg.getColourText());
@@ -617,7 +518,8 @@ public class PopupMenu extends JPopupMenu
   void addFeatureLinks(final SequenceI seq, List<String> links)
   {
     JMenu linkMenu = new JMenu(MessageManager.getString("action.link"));
-    List<String> linkset = new ArrayList<String>();
+    Map<String, List<String>> linkset = new LinkedHashMap<String, List<String>>();
+
     for (String link : links)
     {
       UrlLink urlLink = null;
@@ -629,97 +531,28 @@ public class PopupMenu extends JPopupMenu
         Cache.log.error("Exception for URLLink '" + link + "'", foo);
         continue;
       }
-      ;
+
       if (!urlLink.isValid())
       {
         Cache.log.error(urlLink.getInvalidMessage());
         continue;
       }
-      final String label = urlLink.getLabel();
-      if (seq != null && urlLink.isDynamic())
-      {
 
-        // collect matching db-refs
-        DBRefEntry[] dbr = DBRefUtils.selectRefs(seq.getDBRefs(),
-                new String[] { urlLink.getTarget() });
-        // collect id string too
-        String id = seq.getName();
-        String descr = seq.getDescription();
-        if (descr != null && descr.length() < 1)
-        {
-          descr = null;
-        }
+      urlLink.createLinksFromSeq(seq, linkset);
+    }
 
-        if (dbr != null)
-        {
-          for (int r = 0; r < dbr.length; r++)
-          {
-            if (id != null && dbr[r].getAccessionId().equals(id))
-            {
-              // suppress duplicate link creation for the bare sequence ID
-              // string with this link
-              id = null;
-            }
-            // create Bare ID link for this URL
-            String[] urls = urlLink.makeUrls(dbr[r].getAccessionId(), true);
-            if (urls != null)
-            {
-              for (int u = 0; u < urls.length; u += 2)
-              {
-                if (!linkset.contains(urls[u] + "|" + urls[u + 1]))
-                {
-                  linkset.add(urls[u] + "|" + urls[u + 1]);
-                  addshowLink(linkMenu, label + "|" + urls[u], urls[u + 1]);
-                }
-              }
-            }
-          }
-        }
-        if (id != null)
-        {
-          // create Bare ID link for this URL
-          String[] urls = urlLink.makeUrls(id, true);
-          if (urls != null)
-          {
-            for (int u = 0; u < urls.length; u += 2)
-            {
-              if (!linkset.contains(urls[u] + "|" + urls[u + 1]))
-              {
-                linkset.add(urls[u] + "|" + urls[u + 1]);
-                addshowLink(linkMenu, label, urls[u + 1]);
-              }
-            }
-          }
-        }
-        // Create urls from description but only for URL links which are regex
-        // links
-        if (descr != null && urlLink.getRegexReplace() != null)
-        {
-          // create link for this URL from description where regex matches
-          String[] urls = urlLink.makeUrls(descr, true);
-          if (urls != null)
-          {
-            for (int u = 0; u < urls.length; u += 2)
-            {
-              if (!linkset.contains(urls[u] + "|" + urls[u + 1]))
-              {
-                linkset.add(urls[u] + "|" + urls[u + 1]);
-                addshowLink(linkMenu, label, urls[u + 1]);
-              }
-            }
-          }
-        }
-      }
-      else
-      {
-        if (!linkset.contains(label + "|" + urlLink.getUrl_prefix()))
-        {
-          linkset.add(label + "|" + urlLink.getUrl_prefix());
-          // Add a non-dynamic link
-          addshowLink(linkMenu, label, urlLink.getUrl_prefix());
-        }
-      }
+    addshowLinks(linkMenu, linkset.values());
+
+    // disable link menu if there are no valid entries
+    if (linkMenu.getItemCount() > 0)
+    {
+      linkMenu.setEnabled(true);
     }
+    else
+    {
+      linkMenu.setEnabled(false);
+    }
+
     if (sequence != null)
     {
       sequenceMenu.add(linkMenu);
@@ -728,6 +561,7 @@ public class PopupMenu extends JPopupMenu
     {
       add(linkMenu);
     }
+
   }
 
   /**
@@ -845,7 +679,7 @@ public class PopupMenu extends JPopupMenu
     label = label.substring(1, label.length() - 1); // a, b, c
     final JMenuItem item = new JMenuItem(label);
     item.setToolTipText(calcId);
-    item.addActionListener(new java.awt.event.ActionListener()
+    item.addActionListener(new ActionListener()
     {
       @Override
       public void actionPerformed(ActionEvent e)
@@ -1004,6 +838,15 @@ public class PopupMenu extends JPopupMenu
     }
   }
 
+  private void addshowLinks(JMenu linkMenu, Collection<List<String>> linkset)
+  {
+    for (List<String> linkstrset : linkset)
+    {
+      // split linkstr into label and url
+      addshowLink(linkMenu, linkstrset.get(1), linkstrset.get(3));
+    }
+  }
+
   /**
    * add a show URL menu item to the given linkMenu
    * 
@@ -1018,7 +861,7 @@ public class PopupMenu extends JPopupMenu
     JMenuItem item = new JMenuItem(label);
     item.setToolTipText(MessageManager.formatMessage(
             "label.open_url_param", new Object[] { url }));
-    item.addActionListener(new java.awt.event.ActionListener()
+    item.addActionListener(new ActionListener()
     {
       @Override
       public void actionPerformed(ActionEvent e)
@@ -1095,7 +938,7 @@ public class PopupMenu extends JPopupMenu
   {
     groupMenu.setText(MessageManager.getString("label.selection"));
     groupName.setText(MessageManager.getString("label.name"));
-    groupName.addActionListener(new java.awt.event.ActionListener()
+    groupName.addActionListener(new ActionListener()
     {
       @Override
       public void actionPerformed(ActionEvent e)
@@ -1106,7 +949,7 @@ public class PopupMenu extends JPopupMenu
     sequenceMenu.setText(MessageManager.getString("label.sequence"));
     sequenceName.setText(MessageManager
             .getString("label.edit_name_description"));
-    sequenceName.addActionListener(new java.awt.event.ActionListener()
+    sequenceName.addActionListener(new ActionListener()
     {
       @Override
       public void actionPerformed(ActionEvent e)
@@ -1116,7 +959,7 @@ public class PopupMenu extends JPopupMenu
     });
     chooseAnnotations.setText(MessageManager
             .getString("action.choose_annotations"));
-    chooseAnnotations.addActionListener(new java.awt.event.ActionListener()
+    chooseAnnotations.addActionListener(new ActionListener()
     {
       @Override
       public void actionPerformed(ActionEvent e)
@@ -1126,7 +969,7 @@ public class PopupMenu extends JPopupMenu
     });
     sequenceDetails.setText(MessageManager
             .getString("label.sequence_details"));
-    sequenceDetails.addActionListener(new java.awt.event.ActionListener()
+    sequenceDetails.addActionListener(new ActionListener()
     {
       @Override
       public void actionPerformed(ActionEvent e)
@@ -1136,19 +979,18 @@ public class PopupMenu extends JPopupMenu
     });
     sequenceSelDetails.setText(MessageManager
             .getString("label.sequence_details"));
-    sequenceSelDetails
-            .addActionListener(new java.awt.event.ActionListener()
-            {
-              @Override
-              public void actionPerformed(ActionEvent e)
-              {
-                sequenceSelectionDetails_actionPerformed();
-              }
-            });
-    PIDColour.setFocusPainted(false);
+    sequenceSelDetails.addActionListener(new ActionListener()
+    {
+      @Override
+      public void actionPerformed(ActionEvent e)
+      {
+        sequenceSelectionDetails_actionPerformed();
+      }
+    });
+
     unGroupMenuItem
             .setText(MessageManager.getString("action.remove_group"));
-    unGroupMenuItem.addActionListener(new java.awt.event.ActionListener()
+    unGroupMenuItem.addActionListener(new ActionListener()
     {
       @Override
       public void actionPerformed(ActionEvent e)
@@ -1158,36 +1000,24 @@ public class PopupMenu extends JPopupMenu
     });
     createGroupMenuItem.setText(MessageManager
             .getString("action.create_group"));
-    createGroupMenuItem
-            .addActionListener(new java.awt.event.ActionListener()
-            {
-              @Override
-              public void actionPerformed(ActionEvent e)
-              {
-                createGroupMenuItem_actionPerformed();
-              }
-            });
-
-    outline.setText(MessageManager.getString("action.border_colour"));
-    outline.addActionListener(new java.awt.event.ActionListener()
+    createGroupMenuItem.addActionListener(new ActionListener()
     {
       @Override
       public void actionPerformed(ActionEvent e)
       {
-        outline_actionPerformed();
+        createGroupMenuItem_actionPerformed();
       }
     });
-    nucleotideMenuItem
-            .setText(MessageManager.getString("label.nucleotide"));
-    nucleotideMenuItem.addActionListener(new ActionListener()
+
+    outline.setText(MessageManager.getString("action.border_colour"));
+    outline.addActionListener(new ActionListener()
     {
       @Override
       public void actionPerformed(ActionEvent e)
       {
-        nucleotideMenuItem_actionPerformed();
+        outline_actionPerformed();
       }
     });
-    colourMenu.setText(MessageManager.getString("label.group_colour"));
     showBoxes.setText(MessageManager.getString("action.boxes"));
     showBoxes.setState(true);
     showBoxes.addActionListener(new ActionListener()
@@ -1218,7 +1048,7 @@ public class PopupMenu extends JPopupMenu
       }
     });
     displayNonconserved.setText(MessageManager
-            .getString("label.show_non_conversed"));
+            .getString("label.show_non_conserved"));
     displayNonconserved.setState(true);
     displayNonconserved.addActionListener(new ActionListener()
     {
@@ -1294,15 +1124,6 @@ public class PopupMenu extends JPopupMenu
         sequenceFeature_actionPerformed();
       }
     });
-    textColour.setText(MessageManager.getString("label.text_colour"));
-    textColour.addActionListener(new ActionListener()
-    {
-      @Override
-      public void actionPerformed(ActionEvent e)
-      {
-        textColour_actionPerformed();
-      }
-    });
     jMenu1.setText(MessageManager.getString("label.group"));
     pdbStructureDialog.setText(MessageManager
             .getString("label.show_pdbstruct_dialog"));
@@ -1357,12 +1178,7 @@ public class PopupMenu extends JPopupMenu
         hideInsertions_actionPerformed(e);
       }
     });
-    /*
-     * annotationMenuItem.setText("By Annotation");
-     * annotationMenuItem.addActionListener(new ActionListener() { public void
-     * actionPerformed(ActionEvent actionEvent) {
-     * annotationMenuItem_actionPerformed(actionEvent); } });
-     */
+
     groupMenu.add(sequenceSelDetails);
     add(groupMenu);
     add(sequenceMenu);
@@ -1394,49 +1210,10 @@ public class PopupMenu extends JPopupMenu
     sequenceMenu.add(sequenceName);
     sequenceMenu.add(sequenceDetails);
     sequenceMenu.add(makeReferenceSeq);
-    colourMenu.add(textColour);
-    colourMenu.add(noColourmenuItem);
-    colourMenu.add(clustalColour);
-    colourMenu.add(BLOSUM62Colour);
-    colourMenu.add(PIDColour);
-    colourMenu.add(zappoColour);
-    colourMenu.add(taylorColour);
-    colourMenu.add(hydrophobicityColour);
-    colourMenu.add(helixColour);
-    colourMenu.add(strandColour);
-    colourMenu.add(turnColour);
-    colourMenu.add(buriedColour);
-    colourMenu.add(nucleotideMenuItem);
-    if (ap.getAlignment().isNucleotide())
-    {
-      // JBPNote - commented since the colourscheme isn't functional
-      colourMenu.add(purinePyrimidineColour);
-    }
-    colourMenu.add(userDefinedColour);
 
-    if (jalview.gui.UserDefinedColours.getUserColourSchemes() != null)
-    {
-      java.util.Enumeration userColours = jalview.gui.UserDefinedColours
-              .getUserColourSchemes().keys();
-
-      while (userColours.hasMoreElements())
-      {
-        JMenuItem item = new JMenuItem(userColours.nextElement().toString());
-        item.addActionListener(new ActionListener()
-        {
-          @Override
-          public void actionPerformed(ActionEvent evt)
-          {
-            userDefinedColour_actionPerformed(evt);
-          }
-        });
-        colourMenu.add(item);
-      }
-    }
+    initColourMenu();
+    buildColourMenu();
 
-    colourMenu.addSeparator();
-    colourMenu.add(abovePIDColour);
-    colourMenu.add(conservationMenuItem);
     editMenu.add(copy);
     editMenu.add(cut);
     editMenu.add(editSequence);
@@ -1454,160 +1231,119 @@ public class PopupMenu extends JPopupMenu
     jMenu1.add(showColourText);
     jMenu1.add(outline);
     jMenu1.add(displayNonconserved);
-    noColourmenuItem.setText(MessageManager.getString("label.none"));
-    noColourmenuItem.addActionListener(new java.awt.event.ActionListener()
+  }
+  
+  /**
+   * Constructs the entries for the colour menu
+   */
+  protected void initColourMenu()
+  {
+    colourMenu.setText(MessageManager.getString("label.group_colour"));
+    textColour.setText(MessageManager.getString("label.text_colour"));
+    textColour.addActionListener(new ActionListener()
     {
       @Override
       public void actionPerformed(ActionEvent e)
       {
-        noColourmenuItem_actionPerformed();
+        textColour_actionPerformed();
       }
     });
 
-    clustalColour.setText(MessageManager
-            .getString("label.clustalx_colours"));
-    clustalColour.addActionListener(new java.awt.event.ActionListener()
-    {
-      @Override
-      public void actionPerformed(ActionEvent e)
-      {
-        clustalColour_actionPerformed();
-      }
-    });
-    zappoColour.setText(MessageManager.getString("label.zappo"));
-    zappoColour.addActionListener(new java.awt.event.ActionListener()
-    {
-      @Override
-      public void actionPerformed(ActionEvent e)
-      {
-        zappoColour_actionPerformed();
-      }
-    });
-    taylorColour.setText(MessageManager.getString("label.taylor"));
-    taylorColour.addActionListener(new java.awt.event.ActionListener()
-    {
-      @Override
-      public void actionPerformed(ActionEvent e)
-      {
-        taylorColour_actionPerformed();
-      }
-    });
-    hydrophobicityColour.setText(MessageManager
-            .getString("label.hydrophobicity"));
-    hydrophobicityColour
-            .addActionListener(new java.awt.event.ActionListener()
-            {
-              @Override
-              public void actionPerformed(ActionEvent e)
-              {
-                hydrophobicityColour_actionPerformed();
-              }
-            });
-    helixColour.setText(MessageManager.getString("label.helix_propensity"));
-    helixColour.addActionListener(new java.awt.event.ActionListener()
-    {
-      @Override
-      public void actionPerformed(ActionEvent e)
-      {
-        helixColour_actionPerformed();
-      }
-    });
-    strandColour.setText(MessageManager
-            .getString("label.strand_propensity"));
-    strandColour.addActionListener(new java.awt.event.ActionListener()
-    {
-      @Override
-      public void actionPerformed(ActionEvent e)
-      {
-        strandColour_actionPerformed();
-      }
-    });
-    turnColour.setText(MessageManager.getString("label.turn_propensity"));
-    turnColour.addActionListener(new java.awt.event.ActionListener()
-    {
-      @Override
-      public void actionPerformed(ActionEvent e)
-      {
-        turnColour_actionPerformed();
-      }
-    });
-    buriedColour.setText(MessageManager.getString("label.buried_index"));
-    buriedColour.addActionListener(new java.awt.event.ActionListener()
-    {
-      @Override
-      public void actionPerformed(ActionEvent e)
-      {
-        buriedColour_actionPerformed();
-      }
-    });
     abovePIDColour.setText(MessageManager
-            .getString("label.above_identity_percentage"));
-    abovePIDColour.addActionListener(new java.awt.event.ActionListener()
+            .getString("label.above_identity_threshold"));
+    abovePIDColour.addActionListener(new ActionListener()
     {
       @Override
       public void actionPerformed(ActionEvent e)
       {
-        abovePIDColour_actionPerformed();
+        abovePIDColour_actionPerformed(abovePIDColour.isSelected());
       }
     });
-    userDefinedColour.setText(MessageManager
-            .getString("action.user_defined"));
-    userDefinedColour.addActionListener(new java.awt.event.ActionListener()
+
+    modifyPID.setText(MessageManager
+            .getString("label.modify_identity_threshold"));
+    modifyPID.addActionListener(new ActionListener()
     {
       @Override
       public void actionPerformed(ActionEvent e)
       {
-        userDefinedColour_actionPerformed(e);
+        modifyPID_actionPerformed();
       }
     });
-    PIDColour
-            .setText(MessageManager.getString("label.percentage_identity"));
-    PIDColour.addActionListener(new java.awt.event.ActionListener()
+
+    conservationMenuItem.setText(MessageManager
+            .getString("action.by_conservation"));
+    conservationMenuItem.addActionListener(new ActionListener()
     {
       @Override
       public void actionPerformed(ActionEvent e)
       {
-        PIDColour_actionPerformed();
+        conservationMenuItem_actionPerformed(conservationMenuItem
+                .isSelected());
       }
     });
-    BLOSUM62Colour.setText(MessageManager.getString("label.blosum62"));
-    BLOSUM62Colour.addActionListener(new java.awt.event.ActionListener()
+
+    modifyConservation.setText(MessageManager
+            .getString("label.modify_conservation_threshold"));
+    modifyConservation.addActionListener(new ActionListener()
     {
       @Override
       public void actionPerformed(ActionEvent e)
       {
-        BLOSUM62Colour_actionPerformed();
+        modifyConservation_actionPerformed();
       }
     });
-    purinePyrimidineColour.setText(MessageManager
-            .getString("label.purine_pyrimidine"));
-    purinePyrimidineColour
-            .addActionListener(new java.awt.event.ActionListener()
-            {
-              @Override
-              public void actionPerformed(ActionEvent e)
-              {
-                purinePyrimidineColour_actionPerformed();
-              }
-            });
+  }
 
-    /*
-     * covariationColour.addActionListener(new java.awt.event.ActionListener() {
-     * public void actionPerformed(ActionEvent e) {
-     * covariationColour_actionPerformed(); } });
-     */
+  /**
+   * Builds the group colour sub-menu, including any user-defined colours which
+   * were loaded at startup or during the Jalview session
+   */
+  protected void buildColourMenu()
+  {
+    SequenceGroup sg = ap.av.getSelectionGroup();
+    if (sg == null)
+    {
+      /*
+       * popup menu with no sequence group scope
+       */
+      return;
+    }
+    colourMenu.removeAll();
+    colourMenu.add(textColour);
+    colourMenu.addSeparator();
 
-    conservationMenuItem.setText(MessageManager
-            .getString("label.conservation"));
-    conservationMenuItem
-            .addActionListener(new java.awt.event.ActionListener()
-            {
-              @Override
-              public void actionPerformed(ActionEvent e)
-              {
-                conservationMenuItem_actionPerformed();
-              }
-            });
+    ColourMenuHelper.addMenuItems(colourMenu, this, sg, false);
+
+    colourMenu.addSeparator();
+    colourMenu.add(conservationMenuItem);
+    colourMenu.add(modifyConservation);
+    colourMenu.add(abovePIDColour);
+    colourMenu.add(modifyPID);
+  }
+
+  protected void modifyConservation_actionPerformed()
+  {
+    SequenceGroup sg = getGroup();
+    if (sg.cs != null)
+    {
+      SliderPanel.setConservationSlider(ap, sg.cs, sg.getName());
+      SliderPanel.showConservationSlider();
+    }
+  }
+
+  protected void modifyPID_actionPerformed()
+  {
+    SequenceGroup sg = getGroup();
+    if (sg.cs != null)
+    {
+      // int threshold = SliderPanel.setPIDSliderSource(ap, sg.cs, getGroup()
+      // .getName());
+      // sg.cs.setThreshold(threshold, ap.av.isIgnoreGapsConsensus());
+      SliderPanel.setPIDSliderSource(ap, sg.cs, getGroup()
+              .getName());
+      SliderPanel.showPIDSlider();
+    }
   }
 
   /**
@@ -1632,7 +1368,7 @@ public class PopupMenu extends JPopupMenu
      * Temporary store to hold distinct calcId / type pairs for the tooltip.
      * Using TreeMap means calcIds are shown in alphabetical order.
      */
-    Map<String, String> tipEntries = new TreeMap<String, String>();
+    SortedMap<String, String> tipEntries = new TreeMap<String, String>();
     final Map<SequenceI, List<AlignmentAnnotation>> candidates = new LinkedHashMap<SequenceI, List<AlignmentAnnotation>>();
     AlignmentI al = this.ap.av.getAlignment();
     AlignmentUtils.findAddableReferenceAnnotations(forSequences,
@@ -1734,7 +1470,7 @@ public class PopupMenu extends JPopupMenu
   public void createSequenceDetailsReport(SequenceI[] sequences)
   {
     CutAndPasteHtmlTransfer cap = new CutAndPasteHtmlTransfer();
-    StringBuffer contents = new StringBuffer();
+    StringBuilder contents = new StringBuilder(128);
     for (SequenceI seq : sequences)
     {
       contents.append("<p><h2>"
@@ -1749,7 +1485,6 @@ public class PopupMenu extends JPopupMenu
                       seq,
                       true,
                       true,
-                      false,
                       (ap.getSeqPanel().seqCanvas.fr != null) ? ap
                               .getSeqPanel().seqCanvas.fr.getMinMax()
                               : null);
@@ -1782,121 +1517,6 @@ public class PopupMenu extends JPopupMenu
     PaintRefresher.Refresh(this, ap.av.getSequenceSetId());
   }
 
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  protected void clustalColour_actionPerformed()
-  {
-    SequenceGroup sg = getGroup();
-    sg.cs = new ClustalxColourScheme(sg, ap.av.getHiddenRepSequences());
-    refresh();
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  protected void zappoColour_actionPerformed()
-  {
-    getGroup().cs = new ZappoColourScheme();
-    refresh();
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  protected void taylorColour_actionPerformed()
-  {
-    getGroup().cs = new TaylorColourScheme();
-    refresh();
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  protected void hydrophobicityColour_actionPerformed()
-  {
-    getGroup().cs = new HydrophobicColourScheme();
-    refresh();
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  protected void helixColour_actionPerformed()
-  {
-    getGroup().cs = new HelixColourScheme();
-    refresh();
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  protected void strandColour_actionPerformed()
-  {
-    getGroup().cs = new StrandColourScheme();
-    refresh();
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  protected void turnColour_actionPerformed()
-  {
-    getGroup().cs = new TurnColourScheme();
-    refresh();
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  protected void buriedColour_actionPerformed()
-  {
-    getGroup().cs = new BuriedColourScheme();
-    refresh();
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  public void nucleotideMenuItem_actionPerformed()
-  {
-    getGroup().cs = new NucleotideColourScheme();
-    refresh();
-  }
-
-  protected void purinePyrimidineColour_actionPerformed()
-  {
-    getGroup().cs = new PurinePyrimidineColourScheme();
-    refresh();
-  }
-
   /*
    * protected void covariationColour_actionPerformed() { getGroup().cs = new
    * CovariationColourScheme(sequence.getAnnotation()[0]); refresh(); }
@@ -1904,10 +1524,12 @@ public class PopupMenu extends JPopupMenu
   /**
    * DOCUMENT ME!
    * 
+   * @param selected
+   * 
    * @param e
    *          DOCUMENT ME!
    */
-  protected void abovePIDColour_actionPerformed()
+  public void abovePIDColour_actionPerformed(boolean selected)
   {
     SequenceGroup sg = getGroup();
     if (sg.cs == null)
@@ -1915,13 +1537,14 @@ public class PopupMenu extends JPopupMenu
       return;
     }
 
-    if (abovePIDColour.isSelected())
+    if (selected)
     {
       sg.cs.setConsensus(AAFrequency.calculate(
               sg.getSequences(ap.av.getHiddenRepSequences()),
               sg.getStartRes(), sg.getEndRes() + 1));
 
-      int threshold = SliderPanel.setPIDSliderSource(ap, sg.cs, getGroup()
+      int threshold = SliderPanel.setPIDSliderSource(ap,
+              sg.getGroupColourScheme(), getGroup()
               .getName());
 
       sg.cs.setThreshold(threshold, ap.av.isIgnoreGapsConsensus());
@@ -1932,36 +1555,14 @@ public class PopupMenu extends JPopupMenu
     // remove PIDColouring
     {
       sg.cs.setThreshold(0, ap.av.isIgnoreGapsConsensus());
+      SliderPanel.hidePIDSlider();
     }
+    modifyPID.setEnabled(selected);
 
     refresh();
   }
 
   /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  protected void userDefinedColour_actionPerformed(ActionEvent e)
-  {
-    SequenceGroup sg = getGroup();
-
-    if (e.getSource().equals(userDefinedColour))
-    {
-      new UserDefinedColours(ap, sg);
-    }
-    else
-    {
-      UserColourScheme udc = (UserColourScheme) UserDefinedColours
-              .getUserColourSchemes().get(e.getActionCommand());
-
-      sg.cs = udc;
-    }
-    refresh();
-  }
-
-  /**
    * Open a panel where the user can choose which types of sequence annotation
    * to show or hide.
    * 
@@ -1979,54 +1580,7 @@ public class PopupMenu extends JPopupMenu
    * @param e
    *          DOCUMENT ME!
    */
-  protected void PIDColour_actionPerformed()
-  {
-    SequenceGroup sg = getGroup();
-    sg.cs = new PIDColourScheme();
-    sg.cs.setConsensus(AAFrequency.calculate(
-            sg.getSequences(ap.av.getHiddenRepSequences()),
-            sg.getStartRes(), sg.getEndRes() + 1));
-    refresh();
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  protected void BLOSUM62Colour_actionPerformed()
-  {
-    SequenceGroup sg = getGroup();
-
-    sg.cs = new Blosum62ColourScheme();
-
-    sg.cs.setConsensus(AAFrequency.calculate(
-            sg.getSequences(ap.av.getHiddenRepSequences()),
-            sg.getStartRes(), sg.getEndRes() + 1));
-
-    refresh();
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  protected void noColourmenuItem_actionPerformed()
-  {
-    getGroup().cs = null;
-    refresh();
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  protected void conservationMenuItem_actionPerformed()
+  public void conservationMenuItem_actionPerformed(boolean selected)
   {
     SequenceGroup sg = getGroup();
     if (sg.cs == null)
@@ -2034,44 +1588,28 @@ public class PopupMenu extends JPopupMenu
       return;
     }
 
-    if (conservationMenuItem.isSelected())
+    if (selected)
     {
       // JBPNote: Conservation name shouldn't be i18n translated
-      Conservation c = new Conservation("Group", 3, sg.getSequences(ap.av
+      Conservation c = new Conservation("Group", sg.getSequences(ap.av
               .getHiddenRepSequences()), sg.getStartRes(),
               sg.getEndRes() + 1);
 
       c.calculate();
       c.verdict(false, ap.av.getConsPercGaps());
-
       sg.cs.setConservation(c);
 
-      SliderPanel.setConservationSlider(ap, sg.cs, sg.getName());
+      SliderPanel.setConservationSlider(ap, sg.getGroupColourScheme(),
+              sg.getName());
       SliderPanel.showConservationSlider();
     }
     else
     // remove ConservationColouring
     {
       sg.cs.setConservation(null);
+      SliderPanel.hideConservationSlider();
     }
-
-    refresh();
-  }
-
-  public void annotationMenuItem_actionPerformed(ActionEvent actionEvent)
-  {
-    SequenceGroup sg = getGroup();
-    if (sg == null)
-    {
-      return;
-    }
-
-    AnnotationColourGradient acg = new AnnotationColourGradient(
-            sequence.getAnnotation()[0], null,
-            AnnotationColourGradient.NO_THRESHOLD);
-
-    acg.setPredefinedColours(true);
-    sg.cs = acg;
+    modifyConservation.setEnabled(selected);
 
     refresh();
   }
@@ -2146,14 +1684,14 @@ public class PopupMenu extends JPopupMenu
     {
       if (dialog.getName().indexOf(" ") > -1)
       {
-        JOptionPane
+        JvOptionPane
                 .showMessageDialog(
                         ap,
                         MessageManager
                                 .getString("label.spaces_converted_to_backslashes"),
                         MessageManager
                                 .getString("label.no_spaces_allowed_sequence_name"),
-                        JOptionPane.WARNING_MESSAGE);
+                        JvOptionPane.WARNING_MESSAGE);
       }
 
       sequence.setName(dialog.getName().replace(' ', '_'));
@@ -2252,10 +1790,10 @@ public class PopupMenu extends JPopupMenu
       jalview.util.BrowserLauncher.openURL(url);
     } catch (Exception ex)
     {
-      JOptionPane.showInternalMessageDialog(Desktop.desktop,
+      JvOptionPane.showInternalMessageDialog(Desktop.desktop,
               MessageManager.getString("label.web_browser_not_found_unix"),
               MessageManager.getString("label.web_browser_not_found"),
-              JOptionPane.WARNING_MESSAGE);
+              JvOptionPane.WARNING_MESSAGE);
 
       ex.printStackTrace();
     }
@@ -2331,8 +1869,8 @@ public class PopupMenu extends JPopupMenu
     // or we simply trust the user wants
     // wysiwig behaviour
 
-    cap.setText(new FormatAdapter(ap).formatSequences(e.getActionCommand(),
-            ap, true));
+    FileFormatI fileFormat = FileFormats.getInstance().forName(e.getActionCommand());
+    cap.setText(new FormatAdapter(ap).formatSequences(fileFormat, ap, true));
   }
 
   public void sequenceFeature_actionPerformed()
@@ -2436,4 +1974,41 @@ public class PopupMenu extends JPopupMenu
     }
   }
 
+  /**
+   * Action on user selecting an item from the colour menu (that does not have
+   * its bespoke action handler)
+   * 
+   * @return
+   */
+  @Override
+  public void changeColour_actionPerformed(String colourSchemeName)
+  {
+    SequenceGroup sg = getGroup();
+    if (ResidueColourScheme.USER_DEFINED.equals(colourSchemeName))
+    {
+      /*
+       * open a panel to load or configure a user-defined colour scheme
+       */
+      new UserDefinedColours(ap, sg);
+    }
+    else
+    {
+      /*
+       * switch to the chosen colour scheme (or null for None)
+       */
+      ColourSchemeI colourScheme = ColourSchemes.getInstance().getColourScheme(
+              colourSchemeName, sg, ap.av.getHiddenRepSequences());
+      sg.setColourScheme(colourScheme);
+      if (colourScheme instanceof Blosum62ColourScheme
+              || colourScheme instanceof PIDColourScheme)
+      {
+        sg.cs.setConsensus(AAFrequency.calculate(
+                sg.getSequences(ap.av.getHiddenRepSequences()),
+                sg.getStartRes(), sg.getEndRes() + 1));
+      }
+    }
+
+    refresh();
+  }
+
 }