Merge branch 'feature/JAL-2587' into documentation/JAL-2675_release2102b1
[jalview.git] / src / jalview / gui / PopupMenu.java
index e86b2c5..2ef71cc 100644 (file)
@@ -24,36 +24,29 @@ import jalview.analysis.AAFrequency;
 import jalview.analysis.AlignmentAnnotationUtils;
 import jalview.analysis.AlignmentUtils;
 import jalview.analysis.Conservation;
+import jalview.bin.Cache;
 import jalview.commands.ChangeCaseCommand;
 import jalview.commands.EditCommand;
 import jalview.commands.EditCommand.Action;
 import jalview.datamodel.AlignmentAnnotation;
 import jalview.datamodel.AlignmentI;
 import jalview.datamodel.Annotation;
-import jalview.datamodel.ColumnSelection;
 import jalview.datamodel.DBRefEntry;
+import jalview.datamodel.HiddenColumns;
 import jalview.datamodel.PDBEntry;
 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.ResidueProperties;
-import jalview.schemes.StrandColourScheme;
-import jalview.schemes.TaylorColourScheme;
-import jalview.schemes.TurnColourScheme;
-import jalview.schemes.UserColourScheme;
-import jalview.schemes.ZappoColourScheme;
 import jalview.util.GroupUrlLink;
 import jalview.util.GroupUrlLink.UrlStringTooLongException;
 import jalview.util.MessageManager;
@@ -62,23 +55,24 @@ 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.BitSet;
+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!
@@ -86,48 +80,20 @@ import javax.swing.JRadioButtonMenuItem;
  * @author $author$
  * @version $Revision: 1.118 $
  */
-public class PopupMenu extends JPopupMenu
+public class PopupMenu extends JPopupMenu implements ColourChangeListener
 {
-  private static final String ALL_ANNOTATIONS = "All";
-
-  private static final String COMMA = ",";
-
   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();
@@ -150,8 +116,6 @@ public class PopupMenu extends JPopupMenu
 
   JMenuItem outline = new JMenuItem();
 
-  JRadioButtonMenuItem nucleotideMenuItem = new JRadioButtonMenuItem();
-
   JMenu colourMenu = new JMenu();
 
   JCheckBoxMenuItem showBoxes = new JCheckBoxMenuItem();
@@ -176,12 +140,6 @@ public class PopupMenu extends JPopupMenu
 
   JMenu pdbMenu = new JMenu();
 
-  JMenuItem pdbFromFile = new JMenuItem();
-
-  JMenuItem enterPDB = new JMenuItem();
-
-  JMenuItem discoverPDB = new JMenuItem();
-
   JMenu outputMenu = new JMenu();
 
   JMenu seqShowAnnotationsMenu = new JMenu();
@@ -222,7 +180,8 @@ public class PopupMenu extends JPopupMenu
    * @param seq
    *          DOCUMENT ME!
    */
-  public PopupMenu(final AlignmentPanel ap, Sequence seq, Vector links)
+  public PopupMenu(final AlignmentPanel ap, Sequence seq,
+          List<String> links)
   {
     this(ap, seq, links, null);
   }
@@ -235,7 +194,7 @@ public class PopupMenu extends JPopupMenu
    * @param groupLinks
    */
   public PopupMenu(final AlignmentPanel ap, final SequenceI seq,
-          Vector links, Vector groupLinks)
+          List<String> links, List<String> groupLinks)
   {
     // /////////////////////////////////////////////////////////
     // If this is activated from the sequence panel, the user may want to
@@ -246,29 +205,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)
@@ -285,8 +226,9 @@ public class PopupMenu extends JPopupMenu
      * 'reference annotations' that may be added to the alignment. First for the
      * currently selected sequence (if there is one):
      */
-    final List<SequenceI> selectedSequence = (seq == null ? Collections
-            .<SequenceI> emptyList() : Arrays.asList(seq));
+    final List<SequenceI> selectedSequence = (seq == null
+            ? Collections.<SequenceI> emptyList()
+            : Arrays.asList(seq));
     buildAnnotationTypesMenus(seqShowAnnotationsMenu,
             seqHideAnnotationsMenu, selectedSequence);
     configureReferenceAnnotationsMenu(seqAddReferenceAnnotations,
@@ -295,9 +237,9 @@ public class PopupMenu extends JPopupMenu
     /*
      * And repeat for the current selection group (if there is one):
      */
-    final List<SequenceI> selectedGroup = (ap.av.getSelectionGroup() == null ? Collections
-            .<SequenceI> emptyList() : ap.av.getSelectionGroup()
-            .getSequences());
+    final List<SequenceI> selectedGroup = (ap.av.getSelectionGroup() == null
+            ? Collections.<SequenceI> emptyList()
+            : ap.av.getSelectionGroup().getSequences());
     buildAnnotationTypesMenus(groupShowAnnotationsMenu,
             groupHideAnnotationsMenu, selectedGroup);
     configureReferenceAnnotationsMenu(groupAddReferenceAnnotations,
@@ -317,13 +259,13 @@ public class PopupMenu extends JPopupMenu
       sequenceMenu.setText(sequence.getName());
       if (seq == ap.av.getAlignment().getSeqrep())
       {
-        makeReferenceSeq.setText(MessageManager
-                .getString("action.unmark_as_reference"));
+        makeReferenceSeq.setText(
+                MessageManager.getString("action.unmark_as_reference"));
       }
       else
       {
-        makeReferenceSeq.setText(MessageManager
-                .getString("action.set_as_reference"));
+        makeReferenceSeq.setText(
+                MessageManager.getString("action.set_as_reference"));
       }
 
       if (!ap.av.getAlignment().isNucleotide())
@@ -350,9 +292,9 @@ public class PopupMenu extends JPopupMenu
                */
               menuItem = new JMenuItem();
               menuItem.setText(MessageManager.formatMessage(
-                      "label.2d_rna_structure_line",
-                      new Object[] { aa.label }));
-              menuItem.addActionListener(new java.awt.event.ActionListener()
+                      "label.2d_rna_structure_line", new Object[]
+                      { aa.label }));
+              menuItem.addActionListener(new ActionListener()
               {
                 @Override
                 public void actionPerformed(ActionEvent e)
@@ -378,9 +320,9 @@ public class PopupMenu extends JPopupMenu
               // TODO: make rnastrucF a bit more nice
               menuItem = new JMenuItem();
               menuItem.setText(MessageManager.formatMessage(
-                      "label.2d_rna_sequence_name",
-                      new Object[] { seq.getName() }));
-              menuItem.addActionListener(new java.awt.event.ActionListener()
+                      "label.2d_rna_sequence_name", new Object[]
+                      { seq.getName() }));
+              menuItem.addActionListener(new ActionListener()
               {
                 @Override
                 public void actionPerformed(ActionEvent e)
@@ -401,7 +343,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)
@@ -414,10 +356,10 @@ public class PopupMenu extends JPopupMenu
       if (ap.av.getSelectionGroup() != null
               && ap.av.getSelectionGroup().getSize() > 1)
       {
-        menuItem = new JMenuItem(MessageManager.formatMessage(
-                "label.represent_group_with",
-                new Object[] { seq.getName() }));
-        menuItem.addActionListener(new java.awt.event.ActionListener()
+        menuItem = new JMenuItem(MessageManager
+                .formatMessage("label.represent_group_with", new Object[]
+                { seq.getName() }));
+        menuItem.addActionListener(new ActionListener()
         {
           @Override
           public void actionPerformed(ActionEvent e)
@@ -474,82 +416,35 @@ public class PopupMenu extends JPopupMenu
 
         add(menuItem);
       }
-
     }
 
     SequenceGroup sg = ap.av.getSelectionGroup();
-    boolean isDefinedGroup = (sg != null) ? ap.av.getAlignment()
-            .getGroups().contains(sg) : false;
+    boolean isDefinedGroup = (sg != null)
+            ? ap.av.getAlignment().getGroups().contains(sg)
+            : false;
 
     if (sg != null && sg.getSize() > 0)
     {
-      groupName.setText(MessageManager.formatMessage("label.name_param",
-              new Object[] { sg.getName() }));
       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());
@@ -560,7 +455,8 @@ public class PopupMenu extends JPopupMenu
         buildGroupURLMenu(sg, groupLinks);
       }
       // Add a 'show all structures' for the current selection
-      Hashtable<String, PDBEntry> pdbe = new Hashtable<String, PDBEntry>(), reppdb = new Hashtable<String, PDBEntry>();
+      Hashtable<String, PDBEntry> pdbe = new Hashtable<>(), reppdb = new Hashtable<>();
+
       SequenceI sqass = null;
       for (SequenceI sq : ap.av.getSequenceSelection())
       {
@@ -580,9 +476,9 @@ public class PopupMenu extends JPopupMenu
       }
       if (pdbe.size() > 0)
       {
-        final PDBEntry[] pe = pdbe.values().toArray(
-                new PDBEntry[pdbe.size()]), pr = reppdb.values().toArray(
-                new PDBEntry[reppdb.size()]);
+        final PDBEntry[] pe = pdbe.values()
+                .toArray(new PDBEntry[pdbe.size()]),
+                pr = reppdb.values().toArray(new PDBEntry[reppdb.size()]);
         final JMenuItem gpdbview, rpdbview;
       }
     }
@@ -614,124 +510,63 @@ public class PopupMenu extends JPopupMenu
 
     if (links != null && links.size() > 0)
     {
+      addFeatureLinks(seq, links);
+    }
+  }
 
-      JMenu linkMenu = new JMenu(MessageManager.getString("action.link"));
-      Vector linkset = new Vector();
-      for (int i = 0; i < links.size(); i++)
-      {
-        String link = links.elementAt(i).toString();
-        UrlLink urlLink = null;
-        try
-        {
-          urlLink = new UrlLink(link);
-        } catch (Exception foo)
-        {
-          jalview.bin.Cache.log.error("Exception for URLLink '" + link
-                  + "'", foo);
-          continue;
-        }
-        ;
-        if (!urlLink.isValid())
-        {
-          jalview.bin.Cache.log.error(urlLink.getInvalidMessage());
-          continue;
-        }
-        final String label = urlLink.getLabel();
-        if (seq != null && urlLink.isDynamic())
-        {
-
-          // collect matching db-refs
-          DBRefEntry[] dbr = jalview.util.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;
-          }
+  /**
+   * Adds a 'Link' menu item with a sub-menu item for each hyperlink provided.
+   * 
+   * @param seq
+   * @param links
+   */
+  void addFeatureLinks(final SequenceI seq, List<String> links)
+  {
+    JMenu linkMenu = new JMenu(MessageManager.getString("action.link"));
+    Map<String, List<String>> linkset = new LinkedHashMap<>();
 
-          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 RUL
-              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.addElement(urls[u] + "|" + urls[u + 1]);
-                    addshowLink(linkMenu, label + "|" + urls[u],
-                            urls[u + 1]);
-                  }
-                }
-              }
-            }
-          }
-          if (id != null)
-          {
-            // create Bare ID link for this RUL
-            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.addElement(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.addElement(urls[u] + "|" + urls[u + 1]);
-                  addshowLink(linkMenu, label, urls[u + 1]);
-                }
-              }
-            }
-          }
-        }
-        else
-        {
-          if (!linkset.contains(label + "|" + urlLink.getUrl_prefix()))
-          {
-            linkset.addElement(label + "|" + urlLink.getUrl_prefix());
-            // Add a non-dynamic link
-            addshowLink(linkMenu, label, urlLink.getUrl_prefix());
-          }
-        }
-      }
-      if (sequence != null)
+    for (String link : links)
+    {
+      UrlLink urlLink = null;
+      try
+      {
+        urlLink = new UrlLink(link);
+      } catch (Exception foo)
       {
-        sequenceMenu.add(linkMenu);
+        Cache.log.error("Exception for URLLink '" + link + "'", foo);
+        continue;
       }
-      else
+
+      if (!urlLink.isValid())
       {
-        add(linkMenu);
+        Cache.log.error(urlLink.getInvalidMessage());
+        continue;
       }
+
+      urlLink.createLinksFromSeq(seq, linkset);
+    }
+
+    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);
+    }
+    else
+    {
+      add(linkMenu);
     }
+
   }
 
   /**
@@ -755,8 +590,11 @@ public class PopupMenu extends JPopupMenu
     showMenu.removeAll();
     hideMenu.removeAll();
 
-    final List<String> all = Arrays.asList(ALL_ANNOTATIONS);
-    addAnnotationTypeToShowHide(showMenu, forSequences, "", all, true, true);
+    final List<String> all = Arrays
+            .asList(new String[]
+            { MessageManager.getString("label.all") });
+    addAnnotationTypeToShowHide(showMenu, forSequences, "", all, true,
+            true);
     addAnnotationTypeToShowHide(hideMenu, forSequences, "", all, true,
             false);
     showMenu.addSeparator();
@@ -771,8 +609,8 @@ public class PopupMenu extends JPopupMenu
      * the insertion order, which is the order of the annotations on the
      * alignment.
      */
-    Map<String, List<List<String>>> shownTypes = new LinkedHashMap<String, List<List<String>>>();
-    Map<String, List<List<String>>> hiddenTypes = new LinkedHashMap<String, List<List<String>>>();
+    Map<String, List<List<String>>> shownTypes = new LinkedHashMap<>();
+    Map<String, List<List<String>>> hiddenTypes = new LinkedHashMap<>();
     AlignmentAnnotationUtils.getShownHiddenTypes(shownTypes, hiddenTypes,
             AlignmentAnnotationUtils.asList(annotations), forSequences);
 
@@ -848,7 +686,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)
@@ -861,7 +699,7 @@ public class PopupMenu extends JPopupMenu
     showOrHideMenu.add(item);
   }
 
-  private void buildGroupURLMenu(SequenceGroup sg, Vector groupLinks)
+  private void buildGroupURLMenu(SequenceGroup sg, List<String> groupLinks)
   {
 
     // TODO: usability: thread off the generation of group url content so root
@@ -870,24 +708,20 @@ public class PopupMenu extends JPopupMenu
     // ID/regex match URLs
     groupLinksMenu = new JMenu(
             MessageManager.getString("action.group_link"));
+    // three types of url that might be created.
     JMenu[] linkMenus = new JMenu[] { null,
         new JMenu(MessageManager.getString("action.ids")),
         new JMenu(MessageManager.getString("action.sequences")),
-        new JMenu(MessageManager.getString("action.ids_sequences")) }; // three
-                                                                       // types
-                                                                       // of url
-                                                                       // that
-                                                                       // might
-                                                                       // be
-    // created.
+        new JMenu(MessageManager.getString("action.ids_sequences")) };
+
     SequenceI[] seqs = ap.av.getSelectionAsNewSequence();
     String[][] idandseqs = GroupUrlLink.formStrings(seqs);
-    Hashtable commonDbrefs = new Hashtable();
+    Hashtable<String, Object[]> commonDbrefs = new Hashtable<>();
     for (int sq = 0; sq < seqs.length; sq++)
     {
 
-      int start = seqs[sq].findPosition(sg.getStartRes()), end = seqs[sq]
-              .findPosition(sg.getEndRes());
+      int start = seqs[sq].findPosition(sg.getStartRes()),
+              end = seqs[sq].findPosition(sg.getEndRes());
       // just collect ids from dataset sequence
       // TODO: check if IDs collected from selecton group intersects with the
       // current selection, too
@@ -902,7 +736,7 @@ public class PopupMenu extends JPopupMenu
         for (int d = 0; d < dbr.length; d++)
         {
           String src = dbr[d].getSource(); // jalview.util.DBRefUtils.getCanonicalName(dbr[d].getSource()).toUpperCase();
-          Object[] sarray = (Object[]) commonDbrefs.get(src);
+          Object[] sarray = commonDbrefs.get(src);
           if (sarray == null)
           {
             sarray = new Object[2];
@@ -914,8 +748,8 @@ public class PopupMenu extends JPopupMenu
 
           if (((String[]) sarray[1])[sq] == null)
           {
-            if (!dbr[d].hasMap()
-                    || (dbr[d].getMap().locateMappedRange(start, end) != null))
+            if (!dbr[d].hasMap() || (dbr[d].getMap()
+                    .locateMappedRange(start, end) != null))
             {
               ((String[]) sarray[1])[sq] = dbr[d].getAccessionId();
               ((int[]) sarray[0])[0]++;
@@ -927,30 +761,28 @@ public class PopupMenu extends JPopupMenu
     // now create group links for all distinct ID/sequence sets.
     boolean addMenu = false; // indicates if there are any group links to give
                              // to user
-    for (int i = 0; i < groupLinks.size(); i++)
+    for (String link : groupLinks)
     {
-      String link = groupLinks.elementAt(i).toString();
       GroupUrlLink urlLink = null;
       try
       {
         urlLink = new GroupUrlLink(link);
       } catch (Exception foo)
       {
-        jalview.bin.Cache.log.error("Exception for GroupURLLink '" + link
-                + "'", foo);
+        Cache.log.error("Exception for GroupURLLink '" + link + "'", foo);
         continue;
       }
       ;
       if (!urlLink.isValid())
       {
-        jalview.bin.Cache.log.error(urlLink.getInvalidMessage());
+        Cache.log.error(urlLink.getInvalidMessage());
         continue;
       }
       final String label = urlLink.getLabel();
       boolean usingNames = false;
       // Now see which parts of the group apply for this URL
       String ltarget = urlLink.getTarget(); // jalview.util.DBRefUtils.getCanonicalName(urlLink.getTarget());
-      Object[] idset = (Object[]) commonDbrefs.get(ltarget.toUpperCase());
+      Object[] idset = commonDbrefs.get(ltarget.toUpperCase());
       String[] seqstr, ids; // input to makeUrl
       if (idset != null)
       {
@@ -989,9 +821,10 @@ public class PopupMenu extends JPopupMenu
         int type = urlLink.getGroupURLType() & 3;
         // first two bits ofurlLink type bitfield are sequenceids and sequences
         // TODO: FUTURE: ensure the groupURL menu structure can be generalised
-        addshowLink(linkMenus[type], label
-                + (((type & 1) == 1) ? ("("
-                        + (usingNames ? "Names" : ltarget) + ")") : ""),
+        addshowLink(linkMenus[type],
+                label + (((type & 1) == 1)
+                        ? ("(" + (usingNames ? "Names" : ltarget) + ")")
+                        : ""),
                 urlLink, urlset);
         addMenu = true;
       }
@@ -1013,6 +846,16 @@ 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
    * 
@@ -1025,9 +868,10 @@ public class PopupMenu extends JPopupMenu
   private void addshowLink(JMenu linkMenu, String label, final String url)
   {
     JMenuItem item = new JMenuItem(label);
-    item.setToolTipText(MessageManager.formatMessage(
-            "label.open_url_param", new Object[] { url }));
-    item.addActionListener(new java.awt.event.ActionListener()
+    item.setToolTipText(MessageManager.formatMessage("label.open_url_param",
+            new Object[]
+            { url }));
+    item.addActionListener(new ActionListener()
     {
       @Override
       public void actionPerformed(ActionEvent e)
@@ -1063,12 +907,12 @@ public class PopupMenu extends JPopupMenu
           final GroupUrlLink urlgenerator, final Object[] urlstub)
   {
     JMenuItem item = new JMenuItem(label);
-    item.setToolTipText(MessageManager.formatMessage(
-            "label.open_url_seqs_param",
-            new Object[] { urlgenerator.getUrl_prefix(),
+    item.setToolTipText(MessageManager
+            .formatMessage("label.open_url_seqs_param", new Object[]
+            { urlgenerator.getUrl_prefix(),
                 urlgenerator.getNumberInvolved(urlstub) }));
     // TODO: put in info about what is being sent.
-    item.addActionListener(new java.awt.event.ActionListener()
+    item.addActionListener(new ActionListener()
     {
       @Override
       public void actionPerformed(ActionEvent e)
@@ -1082,7 +926,7 @@ public class PopupMenu extends JPopupMenu
             try
             {
               showLink(urlgenerator.constructFrom(urlstub));
-            } catch (UrlStringTooLongException e)
+            } catch (UrlStringTooLongException e2)
             {
             }
           }
@@ -1102,10 +946,9 @@ public class PopupMenu extends JPopupMenu
    */
   private void jbInit() throws Exception
   {
-    groupMenu.setText(MessageManager.getString("label.group"));
     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)
@@ -1114,9 +957,9 @@ 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.setText(
+            MessageManager.getString("label.edit_name_description"));
+    sequenceName.addActionListener(new ActionListener()
     {
       @Override
       public void actionPerformed(ActionEvent e)
@@ -1124,9 +967,9 @@ public class PopupMenu extends JPopupMenu
         sequenceName_actionPerformed();
       }
     });
-    chooseAnnotations.setText(MessageManager
-            .getString("action.choose_annotations"));
-    chooseAnnotations.addActionListener(new java.awt.event.ActionListener()
+    chooseAnnotations
+            .setText(MessageManager.getString("action.choose_annotations"));
+    chooseAnnotations.addActionListener(new ActionListener()
     {
       @Override
       public void actionPerformed(ActionEvent e)
@@ -1134,9 +977,9 @@ public class PopupMenu extends JPopupMenu
         chooseAnnotations_actionPerformed(e);
       }
     });
-    sequenceDetails.setText(MessageManager
-            .getString("label.sequence_details"));
-    sequenceDetails.addActionListener(new java.awt.event.ActionListener()
+    sequenceDetails
+            .setText(MessageManager.getString("label.sequence_details"));
+    sequenceDetails.addActionListener(new ActionListener()
     {
       @Override
       public void actionPerformed(ActionEvent e)
@@ -1144,21 +987,20 @@ public class PopupMenu extends JPopupMenu
         sequenceDetails_actionPerformed();
       }
     });
-    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);
+            .setText(MessageManager.getString("label.sequence_details"));
+    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)
@@ -1166,38 +1008,26 @@ public class PopupMenu extends JPopupMenu
         unGroupMenuItem_actionPerformed();
       }
     });
-    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()
+            .setText(MessageManager.getString("action.create_group"));
+    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()
@@ -1227,8 +1057,8 @@ public class PopupMenu extends JPopupMenu
         showColourText_actionPerformed();
       }
     });
-    displayNonconserved.setText(MessageManager
-            .getString("label.show_non_conversed"));
+    displayNonconserved
+            .setText(MessageManager.getString("label.show_non_conserved"));
     displayNonconserved.setState(true);
     displayNonconserved.addActionListener(new ActionListener()
     {
@@ -1284,48 +1114,18 @@ public class PopupMenu extends JPopupMenu
         changeCase(e);
       }
     });
-    pdbMenu.setText(MessageManager
-            .getString("label.associate_structure_with_sequence"));
-    pdbFromFile.setText(MessageManager.getString("label.from_file"));
-    pdbFromFile.addActionListener(new ActionListener()
-    {
-      @Override
-      public void actionPerformed(ActionEvent e)
-      {
-        pdbFromFile_actionPerformed();
-      }
-    });
-
-    enterPDB.setText(MessageManager.getString("label.enter_pdb_id"));
-    enterPDB.addActionListener(new ActionListener()
-    {
-      @Override
-      public void actionPerformed(ActionEvent e)
-      {
-        enterPDB_actionPerformed();
-      }
-    });
-    discoverPDB.setText(MessageManager.getString("label.discover_pdb_ids"));
-    discoverPDB.addActionListener(new ActionListener()
-    {
-      @Override
-      public void actionPerformed(ActionEvent e)
-      {
-        discoverPDB_actionPerformed();
-      }
-    });
-    outputMenu.setText(MessageManager.getString("label.out_to_textbox")
-            + "...");
-    seqShowAnnotationsMenu.setText(MessageManager
-            .getString("label.show_annotations"));
-    seqHideAnnotationsMenu.setText(MessageManager
-            .getString("label.hide_annotations"));
-    groupShowAnnotationsMenu.setText(MessageManager
-            .getString("label.show_annotations"));
-    groupHideAnnotationsMenu.setText(MessageManager
-            .getString("label.hide_annotations"));
-    sequenceFeature.setText(MessageManager
-            .getString("label.create_sequence_feature"));
+    outputMenu.setText(
+            MessageManager.getString("label.out_to_textbox") + "...");
+    seqShowAnnotationsMenu
+            .setText(MessageManager.getString("label.show_annotations"));
+    seqHideAnnotationsMenu
+            .setText(MessageManager.getString("label.hide_annotations"));
+    groupShowAnnotationsMenu
+            .setText(MessageManager.getString("label.show_annotations"));
+    groupHideAnnotationsMenu
+            .setText(MessageManager.getString("label.hide_annotations"));
+    sequenceFeature.setText(
+            MessageManager.getString("label.create_sequence_feature"));
     sequenceFeature.addActionListener(new ActionListener()
     {
       @Override
@@ -1334,18 +1134,9 @@ 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"));
+    pdbStructureDialog.setText(
+            MessageManager.getString("label.show_pdbstruct_dialog"));
     pdbStructureDialog.addActionListener(new ActionListener()
     {
       @Override
@@ -1360,12 +1151,12 @@ public class PopupMenu extends JPopupMenu
       }
     });
 
-    rnaStructureMenu.setText(MessageManager
-            .getString("label.view_rna_structure"));
+    rnaStructureMenu
+            .setText(MessageManager.getString("label.view_rna_structure"));
 
     // colStructureMenu.setText("Colour By Structure");
-    editSequence.setText(MessageManager.getString("label.edit_sequence")
-            + "...");
+    editSequence.setText(
+            MessageManager.getString("label.edit_sequence") + "...");
     editSequence.addActionListener(new ActionListener()
     {
       @Override
@@ -1374,8 +1165,8 @@ public class PopupMenu extends JPopupMenu
         editSequence_actionPerformed(actionEvent);
       }
     });
-    makeReferenceSeq.setText(MessageManager
-            .getString("label.mark_as_representative"));
+    makeReferenceSeq.setText(
+            MessageManager.getString("label.mark_as_representative"));
     makeReferenceSeq.addActionListener(new ActionListener()
     {
 
@@ -1386,8 +1177,8 @@ public class PopupMenu extends JPopupMenu
 
       }
     });
-    hideInsertions.setText(MessageManager
-            .getString("label.hide_insertions"));
+    hideInsertions
+            .setText(MessageManager.getString("label.hide_insertions"));
     hideInsertions.addActionListener(new ActionListener()
     {
 
@@ -1397,12 +1188,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);
@@ -1434,62 +1220,20 @@ 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);
     editMenu.add(upperCase);
     editMenu.add(lowerCase);
     editMenu.add(toggle);
-    pdbMenu.add(pdbFromFile);
     // JBPNote: These shouldn't be added here - should appear in a generic
     // 'apply web service to this sequence menu'
     // pdbMenu.add(RNAFold);
     // pdbMenu.add(ContraFold);
-    pdbMenu.add(enterPDB);
-    pdbMenu.add(discoverPDB);
     jMenu1.add(groupName);
     jMenu1.add(colourMenu);
     jMenu1.add(showBoxes);
@@ -1497,160 +1241,118 @@ 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()
-    {
-      @Override
-      public void actionPerformed(ActionEvent e)
-      {
-        noColourmenuItem_actionPerformed();
-      }
-    });
+  }
 
-    clustalColour.setText(MessageManager
-            .getString("label.clustalx_colours"));
-    clustalColour.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)
       {
-        clustalColour_actionPerformed();
+        textColour_actionPerformed();
       }
     });
-    zappoColour.setText(MessageManager.getString("label.zappo"));
-    zappoColour.addActionListener(new java.awt.event.ActionListener()
+
+    abovePIDColour.setText(
+            MessageManager.getString("label.above_identity_threshold"));
+    abovePIDColour.addActionListener(new ActionListener()
     {
       @Override
       public void actionPerformed(ActionEvent e)
       {
-        zappoColour_actionPerformed();
+        abovePIDColour_actionPerformed(abovePIDColour.isSelected());
       }
     });
-    taylorColour.setText(MessageManager.getString("label.taylor"));
-    taylorColour.addActionListener(new java.awt.event.ActionListener()
+
+    modifyPID.setText(
+            MessageManager.getString("label.modify_identity_threshold"));
+    modifyPID.addActionListener(new ActionListener()
     {
       @Override
       public void actionPerformed(ActionEvent e)
       {
-        taylorColour_actionPerformed();
+        modifyPID_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()
+
+    conservationMenuItem
+            .setText(MessageManager.getString("action.by_conservation"));
+    conservationMenuItem.addActionListener(new ActionListener()
     {
       @Override
       public void actionPerformed(ActionEvent e)
       {
-        helixColour_actionPerformed();
+        conservationMenuItem_actionPerformed(
+                conservationMenuItem.isSelected());
       }
     });
-    strandColour.setText(MessageManager
-            .getString("label.strand_propensity"));
-    strandColour.addActionListener(new java.awt.event.ActionListener()
+
+    modifyConservation.setText(MessageManager
+            .getString("label.modify_conservation_threshold"));
+    modifyConservation.addActionListener(new ActionListener()
     {
       @Override
       public void actionPerformed(ActionEvent e)
       {
-        strandColour_actionPerformed();
+        modifyConservation_actionPerformed();
       }
     });
-    turnColour.setText(MessageManager.getString("label.turn_propensity"));
-    turnColour.addActionListener(new java.awt.event.ActionListener()
+  }
+
+  /**
+   * 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)
     {
-      @Override
-      public void actionPerformed(ActionEvent e)
-      {
-        turnColour_actionPerformed();
-      }
-    });
-    buriedColour.setText(MessageManager.getString("label.buried_index"));
-    buriedColour.addActionListener(new java.awt.event.ActionListener()
+      /*
+       * popup menu with no sequence group scope
+       */
+      return;
+    }
+    colourMenu.removeAll();
+    colourMenu.add(textColour);
+    colourMenu.addSeparator();
+
+    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)
     {
-      @Override
-      public void actionPerformed(ActionEvent e)
-      {
-        buriedColour_actionPerformed();
-      }
-    });
-    abovePIDColour.setText(MessageManager
-            .getString("label.above_identity_percentage"));
-    abovePIDColour.addActionListener(new java.awt.event.ActionListener()
-    {
-      @Override
-      public void actionPerformed(ActionEvent e)
-      {
-        abovePIDColour_actionPerformed();
-      }
-    });
-    userDefinedColour.setText(MessageManager
-            .getString("action.user_defined"));
-    userDefinedColour.addActionListener(new java.awt.event.ActionListener()
-    {
-      @Override
-      public void actionPerformed(ActionEvent e)
-      {
-        userDefinedColour_actionPerformed(e);
-      }
-    });
-    PIDColour
-            .setText(MessageManager.getString("label.percentage_identity"));
-    PIDColour.addActionListener(new java.awt.event.ActionListener()
-    {
-      @Override
-      public void actionPerformed(ActionEvent e)
-      {
-        PIDColour_actionPerformed();
-      }
-    });
-    BLOSUM62Colour.setText(MessageManager.getString("label.blosum62"));
-    BLOSUM62Colour.addActionListener(new java.awt.event.ActionListener()
-    {
-      @Override
-      public void actionPerformed(ActionEvent e)
-      {
-        BLOSUM62Colour_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(); } });
-     */
+      SliderPanel.setConservationSlider(ap, sg.cs, sg.getName());
+      SliderPanel.showConservationSlider();
+    }
+  }
 
-    conservationMenuItem.setText(MessageManager
-            .getString("label.conservation"));
-    conservationMenuItem
-            .addActionListener(new java.awt.event.ActionListener()
-            {
-              @Override
-              public void actionPerformed(ActionEvent e)
-              {
-                conservationMenuItem_actionPerformed();
-              }
-            });
+  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();
+    }
   }
 
   /**
@@ -1675,11 +1377,11 @@ 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>();
-    final Map<SequenceI, List<AlignmentAnnotation>> candidates = new LinkedHashMap<SequenceI, List<AlignmentAnnotation>>();
+    SortedMap<String, String> tipEntries = new TreeMap<>();
+    final Map<SequenceI, List<AlignmentAnnotation>> candidates = new LinkedHashMap<>();
     AlignmentI al = this.ap.av.getAlignment();
-    AlignmentUtils.findAddableReferenceAnnotations(forSequences,
-            tipEntries, candidates, al);
+    AlignmentUtils.findAddableReferenceAnnotations(forSequences, tipEntries,
+            candidates, al);
     if (!candidates.isEmpty())
     {
       StringBuilder tooltip = new StringBuilder(64);
@@ -1751,16 +1453,59 @@ public class PopupMenu extends JPopupMenu
 
   protected void hideInsertions_actionPerformed(ActionEvent actionEvent)
   {
-    if (sequence != null)
+
+    HiddenColumns hidden = new HiddenColumns();
+    BitSet inserts = new BitSet(), mask = new BitSet();
+
+    // set mask to preserve existing hidden columns outside selected group
+    if (ap.av.hasHiddenColumns())
     {
-      ColumnSelection cs = ap.av.getColumnSelection();
-      if (cs == null)
+      ap.av.getAlignment().getHiddenColumns().markHiddenRegions(mask);
+    }
+
+    boolean markedPopup = false;
+    // mark inserts in current selection
+    if (ap.av.getSelectionGroup() != null)
+    {
+      // mark just the columns in the selection group to be hidden
+      inserts.set(ap.av.getSelectionGroup().getStartRes(),
+              ap.av.getSelectionGroup().getEndRes() + 1);
+
+      // and clear that part of the mask
+      mask.andNot(inserts);
+
+      // now clear columns without gaps
+      for (SequenceI sq : ap.av.getSelectionGroup().getSequences())
       {
-        cs = new ColumnSelection();
+        if (sq == sequence)
+        {
+          markedPopup = true;
+        }
+        inserts.and(sq.getInsertionsAsBits());
       }
-      cs.hideInsertionsFor(sequence);
-      ap.av.setColumnSelection(cs);
     }
+    else
+    {
+      // initially, mark all columns to be hidden
+      inserts.set(0, ap.av.getAlignment().getWidth());
+
+      // and clear out old hidden regions completely
+      mask.clear();
+    }
+
+    // now mark for sequence under popup if we haven't already done it
+    if (!markedPopup && sequence != null)
+    {
+      inserts.and(sequence.getInsertionsAsBits());
+    }
+
+    // finally, preserve hidden regions outside selection
+    inserts.or(mask);
+
+    // and set hidden columns accordingly
+    hidden.hideMarkedBits(inserts);
+
+    ap.av.getAlignment().setHiddenColumns(hidden);
     refresh();
   }
 
@@ -1777,34 +1522,30 @@ 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>"
-              + MessageManager
-                      .formatMessage(
-                              "label.create_sequence_details_report_annotation_for",
-                              new Object[] { seq.getDisplayId(true) })
-              + "</h2></p><p>");
-      new SequenceAnnotationReport(null)
-              .createSequenceAnnotationReport(
-                      contents,
-                      seq,
-                      true,
-                      true,
-                      false,
-                      (ap.getSeqPanel().seqCanvas.fr != null) ? ap
-                              .getSeqPanel().seqCanvas.fr.getMinMax()
-                              : null);
+      contents.append("<p><h2>" + MessageManager.formatMessage(
+              "label.create_sequence_details_report_annotation_for",
+              new Object[]
+              { seq.getDisplayId(true) }) + "</h2></p><p>");
+      new SequenceAnnotationReport(null).createSequenceAnnotationReport(
+              contents, seq, true, true,
+              (ap.getSeqPanel().seqCanvas.fr != null)
+                      ? ap.getSeqPanel().seqCanvas.fr.getMinMax()
+                      : null);
       contents.append("</p>");
     }
     cap.setText("<html>" + contents.toString() + "</html>");
 
-    Desktop.addInternalFrame(cap, MessageManager.formatMessage(
-            "label.sequence_details_for",
-            (sequences.length == 1 ? new Object[] { sequences[0]
-                    .getDisplayId(true) } : new Object[] { MessageManager
-                    .getString("label.selection") })), 500, 400);
+    Desktop.addInternalFrame(cap,
+            MessageManager.formatMessage("label.sequence_details_for",
+                    (sequences.length == 1 ? new Object[]
+                    { sequences[0].getDisplayId(true) }
+                            : new Object[]
+                            { MessageManager
+                                    .getString("label.selection") })),
+            500, 400);
 
   }
 
@@ -1820,126 +1561,13 @@ public class PopupMenu extends JPopupMenu
   void refresh()
   {
     ap.updateAnnotation();
-    ap.paintAlignment(true);
+    // removed paintAlignment(true) here:
+    // updateAnnotation calls paintAlignment already, so don't need to call
+    // again
 
     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(); }
@@ -1947,10 +1575,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)
@@ -1958,14 +1588,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()
-              .getName());
+      int threshold = SliderPanel.setPIDSliderSource(ap,
+              sg.getGroupColourScheme(), getGroup().getName());
 
       sg.cs.setThreshold(threshold, ap.av.isIgnoreGapsConsensus());
 
@@ -1975,36 +1605,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.
    * 
@@ -2022,54 +1630,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)
@@ -2077,45 +1638,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",
-              ResidueProperties.propHash, 3, sg.getSequences(ap.av
-                      .getHiddenRepSequences()), sg.getStartRes(),
-              sg.getEndRes() + 1);
+              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();
   }
@@ -2131,8 +1675,8 @@ public class PopupMenu extends JPopupMenu
 
     SequenceGroup sg = getGroup();
     EditNameDialog dialog = new EditNameDialog(sg.getName(),
-            sg.getDescription(), "       "
-                    + MessageManager.getString("label.group_name") + " ",
+            sg.getDescription(),
+            "       " + MessageManager.getString("label.group_name") + " ",
             MessageManager.getString("label.group_description") + " ",
             MessageManager.getString("label.edit_group_name_description"),
             ap.alignFrame);
@@ -2177,8 +1721,8 @@ public class PopupMenu extends JPopupMenu
             "       " + MessageManager.getString("label.sequence_name")
                     + " ",
             MessageManager.getString("label.sequence_description") + " ",
-            MessageManager
-                    .getString("label.edit_sequence_name_description"),
+            MessageManager.getString(
+                    "label.edit_sequence_name_description"),
             ap.alignFrame);
 
     if (!dialog.accept)
@@ -2190,14 +1734,12 @@ public class PopupMenu extends JPopupMenu
     {
       if (dialog.getName().indexOf(" ") > -1)
       {
-        JOptionPane
-                .showMessageDialog(
-                        ap,
-                        MessageManager
-                                .getString("label.spaces_converted_to_backslashes"),
-                        MessageManager
-                                .getString("label.no_spaces_allowed_sequence_name"),
-                        JOptionPane.WARNING_MESSAGE);
+        JvOptionPane.showMessageDialog(ap,
+                MessageManager
+                        .getString("label.spaces_converted_to_backslashes"),
+                MessageManager
+                        .getString("label.no_spaces_allowed_sequence_name"),
+                JvOptionPane.WARNING_MESSAGE);
       }
 
       sequence.setName(dialog.getName().replace(' ', '_'));
@@ -2206,8 +1748,8 @@ public class PopupMenu extends JPopupMenu
 
     sequence.setDescription(dialog.getDescription());
 
-    ap.av.firePropertyChange("alignment", null, ap.av.getAlignment()
-            .getSequences());
+    ap.av.firePropertyChange("alignment", null,
+            ap.av.getAlignment().getSequences());
 
   }
 
@@ -2296,10 +1838,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();
     }
@@ -2307,28 +1849,7 @@ public class PopupMenu extends JPopupMenu
 
   void hideSequences(boolean representGroup)
   {
-    SequenceGroup sg = ap.av.getSelectionGroup();
-    if (sg == null || sg.getSize() < 1)
-    {
-      ap.av.hideSequence(new SequenceI[] { sequence });
-      return;
-    }
-
-    ap.av.setSelectionGroup(null);
-
-    if (representGroup)
-    {
-      ap.av.hideRepSequences(sequence, sg);
-
-      return;
-    }
-
-    int gsize = sg.getSize();
-    SequenceI[] hseqs = sg.getSequences().toArray(new SequenceI[gsize]);
-
-    ap.av.hideSequence(hseqs);
-    // refresh(); TODO: ? needed ?
-    ap.av.sendSelection();
+    ap.av.hideSequences(sequence, representGroup);
   }
 
   public void copy_actionPerformed()
@@ -2376,8 +1897,8 @@ public class PopupMenu extends JPopupMenu
 
       ap.alignFrame.addHistoryItem(caseCommand);
 
-      ap.av.firePropertyChange("alignment", null, ap.av.getAlignment()
-              .getSequences());
+      ap.av.firePropertyChange("alignment", null,
+              ap.av.getAlignment().getSequences());
 
     }
   }
@@ -2386,9 +1907,9 @@ public class PopupMenu extends JPopupMenu
   {
     CutAndPasteTransfer cap = new CutAndPasteTransfer();
     cap.setForInput(null);
-    Desktop.addInternalFrame(cap, MessageManager.formatMessage(
-            "label.alignment_output_command",
-            new Object[] { e.getActionCommand() }), 600, 500);
+    Desktop.addInternalFrame(cap, MessageManager
+            .formatMessage("label.alignment_output_command", new Object[]
+            { e.getActionCommand() }), 600, 500);
 
     String[] omitHidden = null;
 
@@ -2396,72 +1917,10 @@ public class PopupMenu extends JPopupMenu
     // or we simply trust the user wants
     // wysiwig behaviour
 
-    cap.setText(new FormatAdapter(ap).formatSequences(e.getActionCommand(),
-            ap, true));
-  }
-
-  public void pdbFromFile_actionPerformed()
-  {
-    jalview.io.JalviewFileChooser chooser = new jalview.io.JalviewFileChooser(
-            jalview.bin.Cache.getProperty("LAST_DIRECTORY"));
-    chooser.setFileView(new jalview.io.JalviewFileView());
-    chooser.setDialogTitle(MessageManager.formatMessage(
-            "label.select_pdb_file_for",
-            new Object[] { sequence.getDisplayId(false) }));
-    chooser.setToolTipText(MessageManager.formatMessage(
-            "label.load_pdb_file_associate_with_sequence",
-            new Object[] { sequence.getDisplayId(false) }));
-
-    int value = chooser.showOpenDialog(null);
-
-    if (value == jalview.io.JalviewFileChooser.APPROVE_OPTION)
-    {
-      String choice = chooser.getSelectedFile().getPath();
-      jalview.bin.Cache.setProperty("LAST_DIRECTORY", choice);
-      new AssociatePdbFileWithSeq().associatePdbWithSeq(choice,
-              jalview.io.AppletFormatAdapter.FILE, sequence, true,
-              Desktop.instance);
-    }
-
-  }
-
-  public void enterPDB_actionPerformed()
-  {
-    String id = JOptionPane.showInternalInputDialog(Desktop.desktop,
-            MessageManager.getString("label.enter_pdb_id"),
-            MessageManager.getString("label.enter_pdb_id"),
-            JOptionPane.QUESTION_MESSAGE);
-
-    if (id != null && id.length() > 0)
-    {
-      PDBEntry entry = new PDBEntry();
-      entry.setId(id.toUpperCase());
-      sequence.getDatasetSequence().addPDBId(entry);
-    }
-  }
-
-  public void discoverPDB_actionPerformed()
-  {
-
-    final SequenceI[] sequences = ((ap.av.getSelectionGroup() == null) ? new SequenceI[]
-    { sequence }
-            : ap.av.getSequenceSelection());
-    Thread discpdb = new Thread(new Runnable()
-    {
-      @Override
-      public void run()
-      {
-        boolean isNuclueotide = ap.alignFrame.getViewport().getAlignment()
-                .isNucleotide();
-
-        new jalview.ws.DBRefFetcher(sequences, ap.alignFrame, null,
-                ap.alignFrame.featureSettings, isNuclueotide)
-                .fetchDBRefs(false);
-
-      }
-
-    });
-    discpdb.start();
+    FileFormatI fileFormat = FileFormats.getInstance()
+            .forName(e.getActionCommand());
+    cap.setText(
+            new FormatAdapter(ap).formatSequences(fileFormat, ap, true));
   }
 
   public void sequenceFeature_actionPerformed()
@@ -2472,33 +1931,37 @@ public class PopupMenu extends JPopupMenu
       return;
     }
 
-    int rsize = 0, gSize = sg.getSize();
-    SequenceI[] rseqs, seqs = new SequenceI[gSize];
-    SequenceFeature[] tfeatures, features = new SequenceFeature[gSize];
+    List<SequenceI> seqs = new ArrayList<>();
+    List<SequenceFeature> features = new ArrayList<>();
 
+    /*
+     * assemble dataset sequences, and template new sequence features,
+     * for the amend features dialog
+     */
+    int gSize = sg.getSize();
     for (int i = 0; i < gSize; i++)
     {
       int start = sg.getSequenceAt(i).findPosition(sg.getStartRes());
       int end = sg.findEndRes(sg.getSequenceAt(i));
       if (start <= end)
       {
-        seqs[rsize] = sg.getSequenceAt(i).getDatasetSequence();
-        features[rsize] = new SequenceFeature(null, null, null, start, end,
-                "Jalview");
-        rsize++;
+        seqs.add(sg.getSequenceAt(i).getDatasetSequence());
+        features.add(
+                new SequenceFeature(null, null, null, start, end, null));
       }
     }
-    rseqs = new SequenceI[rsize];
-    tfeatures = new SequenceFeature[rsize];
-    System.arraycopy(seqs, 0, rseqs, 0, rsize);
-    System.arraycopy(features, 0, tfeatures, 0, rsize);
-    features = tfeatures;
-    seqs = rseqs;
-    if (ap.getSeqPanel().seqCanvas.getFeatureRenderer().amendFeatures(seqs,
-            features, true, ap))
-    {
-      ap.alignFrame.setShowSeqFeatures(true);
-      ap.highlightSearchResults(null);
+
+    /*
+     * an entirely gapped region will generate empty lists of sequence / features
+     */
+    if (!seqs.isEmpty())
+    {
+      if (ap.getSeqPanel().seqCanvas.getFeatureRenderer()
+              .amendFeatures(seqs, features, true, ap))
+      {
+        ap.alignFrame.setShowSeqFeatures(true);
+        ap.highlightSearchResults(null);
+      }
     }
   }
 
@@ -2543,8 +2006,8 @@ public class PopupMenu extends JPopupMenu
 
       EditNameDialog dialog = new EditNameDialog(
               sequence.getSequenceAsString(sg.getStartRes(),
-                      sg.getEndRes() + 1), null,
-              MessageManager.getString("label.edit_sequence"), null,
+                      sg.getEndRes() + 1),
+              null, MessageManager.getString("label.edit_sequence"), null,
               MessageManager.getString("label.edit_sequence"),
               ap.alignFrame);
 
@@ -2552,17 +2015,45 @@ public class PopupMenu extends JPopupMenu
       {
         EditCommand editCommand = new EditCommand(
                 MessageManager.getString("label.edit_sequences"),
-                Action.REPLACE, dialog.getName().replace(' ',
-                        ap.av.getGapCharacter()),
+                Action.REPLACE,
+                dialog.getName().replace(' ', ap.av.getGapCharacter()),
                 sg.getSequencesAsArray(ap.av.getHiddenRepSequences()),
                 sg.getStartRes(), sg.getEndRes() + 1, ap.av.getAlignment());
 
         ap.alignFrame.addHistoryItem(editCommand);
 
-        ap.av.firePropertyChange("alignment", null, ap.av.getAlignment()
-                .getSequences());
+        ap.av.firePropertyChange("alignment", null,
+                ap.av.getAlignment().getSequences());
       }
     }
   }
 
+  /**
+   * 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();
+    /*
+     * 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();
+  }
+
 }