JAL-2360 ColourSchemes holds configured schemes, AlignFrame colour menu
[jalview.git] / src / jalview / gui / AlignFrame.java
index 03e4534..4687913 100644 (file)
@@ -77,24 +77,13 @@ import jalview.io.JnetAnnotationMaker;
 import jalview.io.NewickFile;
 import jalview.io.TCoffeeScoreFile;
 import jalview.jbgui.GAlignFrame;
-import jalview.schemes.Blosum62ColourScheme;
-import jalview.schemes.BuriedColourScheme;
-import jalview.schemes.ClustalxColourScheme;
 import jalview.schemes.ColourSchemeI;
 import jalview.schemes.ColourSchemeProperty;
-import jalview.schemes.HelixColourScheme;
-import jalview.schemes.HydrophobicColourScheme;
-import jalview.schemes.NucleotideColourScheme;
-import jalview.schemes.PIDColourScheme;
-import jalview.schemes.PurinePyrimidineColourScheme;
-import jalview.schemes.RNAHelicesColourChooser;
+import jalview.schemes.ColourSchemes;
+import jalview.schemes.ResidueColourScheme;
 import jalview.schemes.ResidueProperties;
-import jalview.schemes.StrandColourScheme;
 import jalview.schemes.TCoffeeColourScheme;
-import jalview.schemes.TaylorColourScheme;
-import jalview.schemes.TurnColourScheme;
 import jalview.schemes.UserColourScheme;
-import jalview.schemes.ZappoColourScheme;
 import jalview.util.MessageManager;
 import jalview.viewmodel.AlignmentViewport;
 import jalview.ws.DBRefFetcher;
@@ -125,6 +114,7 @@ import java.awt.event.ItemEvent;
 import java.awt.event.ItemListener;
 import java.awt.event.KeyAdapter;
 import java.awt.event.KeyEvent;
+import java.awt.event.MouseAdapter;
 import java.awt.event.MouseEvent;
 import java.awt.print.PageFormat;
 import java.awt.print.PrinterJob;
@@ -139,12 +129,14 @@ import java.util.Hashtable;
 import java.util.List;
 import java.util.Vector;
 
+import javax.swing.ButtonGroup;
 import javax.swing.JCheckBoxMenuItem;
 import javax.swing.JEditorPane;
 import javax.swing.JInternalFrame;
 import javax.swing.JLayeredPane;
 import javax.swing.JMenu;
 import javax.swing.JMenuItem;
+import javax.swing.JRadioButtonMenuItem;
 import javax.swing.JScrollPane;
 import javax.swing.SwingUtilities;
 
@@ -344,7 +336,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
             alignPanel);
     if (viewport.getAlignmentConservationAnnotation() == null)
     {
-      BLOSUM62Colour.setEnabled(false);
+      // BLOSUM62Colour.setEnabled(false);
       conservationMenuItem.setEnabled(false);
       modifyConservation.setEnabled(false);
       // PIDColour.setEnabled(false);
@@ -364,19 +356,20 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
       sortPairwiseMenuItem_actionPerformed(null);
     }
 
-    if (Desktop.desktop != null)
-    {
-      this.setDropTarget(new java.awt.dnd.DropTarget(this, this));
-      addServiceListeners();
-      setGUINucleotide(viewport.getAlignment().isNucleotide());
-    }
-
     this.alignPanel.av
             .setShowAutocalculatedAbove(isShowAutoCalculatedAbove());
 
     setMenusFromViewport(viewport);
     buildSortByAnnotationScoresMenu();
     buildTreeMenu();
+    buildColourMenu();
+
+    if (Desktop.desktop != null)
+    {
+      this.setDropTarget(new java.awt.dnd.DropTarget(this, this));
+      addServiceListeners();
+      setGUINucleotide();
+    }
 
     if (viewport.getWrapAlignment())
     {
@@ -843,35 +836,48 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
   /**
    * Configure menu items that vary according to whether the alignment is
    * nucleotide or protein
-   * 
-   * @param nucleotide
    */
-  public void setGUINucleotide(boolean nucleotide)
+  public void setGUINucleotide()
   {
+    boolean nucleotide = viewport.getAlignment().isNucleotide();
+
     showTranslation.setVisible(nucleotide);
     showReverse.setVisible(nucleotide);
     showReverseComplement.setVisible(nucleotide);
     conservationMenuItem.setEnabled(!nucleotide);
     modifyConservation.setEnabled(!nucleotide);
     showGroupConservation.setEnabled(!nucleotide);
-    clustalColour.setEnabled(!nucleotide);
-    zappoColour.setEnabled(!nucleotide);
-    taylorColour.setEnabled(!nucleotide);
-    hydrophobicityColour.setEnabled(!nucleotide);
-    helixColour.setEnabled(!nucleotide);
-    strandColour.setEnabled(!nucleotide);
-    turnColour.setEnabled(!nucleotide);
-    buriedColour.setEnabled(!nucleotide);
-    rnahelicesColour.setEnabled(nucleotide);
-    nucleotideColour.setEnabled(nucleotide);
-    purinePyrimidineColour.setEnabled(nucleotide);
-    RNAInteractionColour.setEnabled(nucleotide);
+
+    AlignmentI al = getViewport().getAlignment();
+
+    /*
+     * enable / disable colour schemes by querying whether they
+     * are applicable to the alignment data (for example, peptide or
+     * nucleotide specific, or require certain annotation present)
+     */
+    for (Component menuItem : colourMenu.getMenuComponents())
+    {
+      if (menuItem instanceof JRadioButtonMenuItem)
+      {
+        String colourName = ((JRadioButtonMenuItem) menuItem).getName();
+        ColourSchemeI cs = ColourSchemes.getInstance().getColourScheme(
+                colourName, viewport);
+        if (cs != null)
+        {
+          ((JRadioButtonMenuItem) menuItem).setEnabled(cs
+                  .isApplicableTo(al));
+        }
+      }
+    }
+
     showComplementMenuItem.setText(nucleotide ? MessageManager
             .getString("label.protein") : MessageManager
             .getString("label.nucleotide"));
+
     String selectedColourScheme = Cache.getDefault(
             nucleotide ? Preferences.DEFAULT_COLOUR_NUC
-                    : Preferences.DEFAULT_COLOUR_PROT, "None");
+                    : Preferences.DEFAULT_COLOUR_PROT,
+            ResidueColourScheme.NONE);
     setColourSelected(selectedColourScheme);
   }
 
@@ -935,9 +941,6 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     autoCalculate.setSelected(av.autoCalculateConsensus);
     sortByTree.setSelected(av.sortByTree);
     listenToViewSelections.setSelected(av.followSelection);
-    rnahelicesColour.setEnabled(av.getAlignment().hasRNAStructure());
-    rnahelicesColour
-            .setSelected(av.getGlobalColourScheme() instanceof jalview.schemes.RNAHelicesColour);
 
     showProducts.setEnabled(canShowProducts());
     setGroovyEnabled(Desktop.getGroovyConsole() != null);
@@ -3324,121 +3327,6 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     changeColour(null);
   }
 
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  @Override
-  public void clustalColour_actionPerformed()
-  {
-    changeColour(new ClustalxColourScheme(viewport.getAlignment(),
-            viewport.getHiddenRepSequences()));
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  @Override
-  public void zappoColour_actionPerformed()
-  {
-    changeColour(new ZappoColourScheme());
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  @Override
-  public void taylorColour_actionPerformed()
-  {
-    changeColour(new TaylorColourScheme());
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  @Override
-  public void hydrophobicityColour_actionPerformed()
-  {
-    changeColour(new HydrophobicColourScheme());
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  @Override
-  public void helixColour_actionPerformed()
-  {
-    changeColour(new HelixColourScheme());
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  @Override
-  public void strandColour_actionPerformed()
-  {
-    changeColour(new StrandColourScheme());
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  @Override
-  public void turnColour_actionPerformed()
-  {
-    changeColour(new TurnColourScheme());
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  @Override
-  public void buriedColour_actionPerformed()
-  {
-    changeColour(new BuriedColourScheme());
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  @Override
-  public void nucleotideColour_actionPerformed()
-  {
-    changeColour(new NucleotideColourScheme());
-  }
-
-  @Override
-  public void purinePyrimidineColour_actionPerformed()
-  {
-    changeColour(new PurinePyrimidineColourScheme());
-  }
-
   /*
    * public void covariationColour_actionPerformed() {
    * changeColour(new
@@ -3457,35 +3345,43 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     new AnnotationColumnChooser(viewport, alignPanel);
   }
 
+  /**
+   * Action on the user checking or unchecking the option to apply the selected
+   * colour scheme to all groups. If unchecked, groups may have their own
+   * independent colour schemes.
+   * 
+   */
   @Override
-  public void rnahelicesColour_actionPerformed()
+  protected void applyToAllGroups_actionPerformed()
   {
-    new RNAHelicesColourChooser(viewport, alignPanel);
+    viewport.setColourAppliesToAllGroups(applyToAllGroups.isSelected());
   }
 
   /**
-   * DOCUMENT ME!
+   * Action on user selecting a colour from the colour menu
    * 
+   * @param name
+   *          the name (not the menu item label!) of the colour scheme
    */
-  @Override
-  protected void applyToAllGroups_actionPerformed()
+  public void changeColour_actionPerformed(String name)
   {
-    viewport.setColourAppliesToAllGroups(applyToAllGroups.isSelected());
+    ColourSchemeI cs = ColourSchemes.getInstance().getColourScheme(name,
+            viewport);
+    changeColour(cs);
   }
 
   /**
-   * DOCUMENT ME!
+   * Actions on setting or changing the alignment colour scheme
    * 
    * @param cs
-   *          DOCUMENT ME!
    */
   @Override
   public void changeColour(ColourSchemeI cs)
   {
     // TODO: pull up to controller method
-
     if (cs != null)
     {
+      setColourSelected(cs.getSchemeName());
       // Make sure viewport is up to date w.r.t. any sliders
       if (viewport.getAbovePIDThreshold())
       {
@@ -3499,11 +3395,6 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
         cs.setConservationInc(SliderPanel.setConservationSlider(alignPanel,
                 cs, "Background"));
       }
-      if (cs instanceof TCoffeeColourScheme)
-      {
-        tcoffeeColour.setEnabled(true);
-        tcoffeeColour.setSelected(true);
-      }
     }
 
     viewport.setGlobalColourScheme(cs);
@@ -3586,50 +3477,15 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
   }
 
   /**
-   * DOCUMENT ME!
+   * Action on the user selecting the option "User Defined" to create or load a
+   * new colour scheme
    * 
    * @param e
-   *          DOCUMENT ME!
    */
   @Override
   public void userDefinedColour_actionPerformed(ActionEvent e)
   {
-    if (e.getActionCommand().equals(
-            MessageManager.getString("action.user_defined")))
-    {
-      new UserDefinedColours(alignPanel, null);
-    }
-    else
-    {
-      UserColourScheme udc = UserDefinedColours
-              .getUserColourSchemes().get(e.getActionCommand());
-
-      changeColour(udc);
-    }
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  @Override
-  public void PIDColour_actionPerformed()
-  {
-    changeColour(new PIDColourScheme());
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  @Override
-  public void BLOSUM62Colour_actionPerformed()
-  {
-    changeColour(new Blosum62ColourScheme());
+    new UserDefinedColours(alignPanel, null);
   }
 
   /**
@@ -4266,12 +4122,6 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     }
   }
 
-  @Override
-  protected void tcoffeeColorScheme_actionPerformed()
-  {
-    changeColour(new TCoffeeColourScheme(alignPanel.getAlignment()));
-  }
-
   public TreePanel ShowNewickTree(NewickFile nf, String title)
   {
     return ShowNewickTree(nf, title, 600, 500, 4, 5);
@@ -4937,8 +4787,18 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
           {
             if (tcf.annotateAlignment(viewport.getAlignment(), true))
             {
-              tcoffeeColour.setEnabled(true);
-              tcoffeeColour.setSelected(true);
+              // tcoffeeColour.setEnabled(true);
+              // tcoffeeColour.setSelected(true);
+              for (Component menuItem : colourMenu.getMenuComponents())
+              {
+                if (menuItem instanceof JRadioButtonMenuItem
+                        && ((JRadioButtonMenuItem) menuItem).getText()
+                                .equals("T-Coffee Scores"))
+                {
+                  ((JRadioButtonMenuItem) menuItem).setSelected(true);
+                }
+              }
+              buildColourMenu();
               changeColour(new TCoffeeColourScheme(viewport.getAlignment()));
               isAnnotation = true;
               statusBar
@@ -5868,6 +5728,124 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
             true,
             (actionEvent.getModifiers() & (ActionEvent.META_MASK | ActionEvent.CTRL_MASK)) != 0);
   }
+
+  /**
+   * Rebuilds the Colour menu, including any user-defined colours which have
+   * been loaded either on startup or during the session
+   */
+  public void buildColourMenu()
+  {
+    colourMenu.removeAll();
+
+    /*
+     * ButtonGroup groups those items whose 
+     * selection is mutually exclusive
+     */
+    ButtonGroup colours = new ButtonGroup();
+
+    colourMenu.add(applyToAllGroups);
+    colourMenu.add(textColour);
+    colourMenu.addSeparator();
+    colourMenu.add(noColourmenuItem);
+    colours.add(noColourmenuItem);
+
+    /*
+     * scan registered colour schemes (built-in or user-defined
+     * and add them to the menu (in the order they were added)
+     */
+    Iterable<ColourSchemeI> colourSchemes = ColourSchemes.getInstance()
+            .getColourSchemes();
+    for (ColourSchemeI scheme : colourSchemes)
+    {
+      /*
+       * button text is i18n'd but the name is the canonical name of
+       * the colour scheme (inspected in changeColour_actionPerformed)
+       */
+      final String name = scheme.getSchemeName();
+      String label = MessageManager.getString("label.colourScheme_"
+              + name.toLowerCase().replace(" ", "_"));
+      final JRadioButtonMenuItem radioItem = new JRadioButtonMenuItem(label);
+      radioItem.setName(name);
+      if (scheme instanceof UserColourScheme)
+      {
+        /*
+         * user-defined colour scheme loaded on startup or during the
+         * Jalview session; right-click on this offers the option to
+         * remove it as a colour choice
+         */
+        radioItem.setText(((UserColourScheme) scheme).getName());
+        radioItem.addMouseListener(new MouseAdapter()
+        {
+          @Override
+          public void mousePressed(MouseEvent evt)
+          {
+            if (evt.isPopupTrigger()) // Mac
+            {
+              offerRemoval();
+            }
+          }
+
+          @Override
+          public void mouseReleased(MouseEvent evt)
+          {
+            if (evt.isPopupTrigger()) // Windows
+            {
+              offerRemoval();
+            }
+          }
+
+          void offerRemoval()
+          {
+            ActionListener al = radioItem.getActionListeners()[0];
+            radioItem.removeActionListener(al);
+            int option = JvOptionPane.showInternalConfirmDialog(
+                    Desktop.desktop, MessageManager
+                            .getString("label.remove_from_default_list"),
+                    MessageManager
+                            .getString("label.remove_user_defined_colour"),
+                    JvOptionPane.YES_NO_OPTION);
+            if (option == JvOptionPane.YES_OPTION)
+            {
+              UserDefinedColours.removeColourFromDefaults(radioItem
+                      .getName());
+              ColourSchemes.getInstance().removeColourScheme(
+                      radioItem.getName());
+              colourMenu.remove(radioItem);
+            }
+            else
+            {
+              radioItem.addActionListener(al);
+            }
+          }
+        });
+      }
+      radioItem.addActionListener(new ActionListener()
+      {
+        @Override
+        public void actionPerformed(ActionEvent evt)
+        {
+          changeColour_actionPerformed(name);
+        }
+      });
+      colourMenu.add(radioItem);
+      colours.add(radioItem);
+    }
+
+    colourMenu.add(userDefinedColour);
+    colours.add(userDefinedColour);
+
+    colourMenu.addSeparator();
+    colourMenu.add(conservationMenuItem);
+    colourMenu.add(modifyConservation);
+    colourMenu.add(abovePIDThreshold);
+    colourMenu.add(modifyPID);
+    colourMenu.add(annotationColour);
+
+    setColourSelected(Cache.getDefault(Preferences.DEFAULT_COLOUR,
+            ResidueColourScheme.NONE));
+
+    setGUINucleotide();
+  }
 }
 
 class PrintThread extends Thread