JAL-2016 FeatureSettingsI now FeatureSettingsModelI
[jalview.git] / src / jalview / gui / AlignViewport.java
index 579b476..7d8d4fe 100644 (file)
@@ -43,6 +43,9 @@ import jalview.analysis.AnnotationSorter.SequenceAnnotationOrder;
 import jalview.analysis.NJTree;
 import jalview.api.AlignViewportI;
 import jalview.api.AlignmentViewPanel;
+import jalview.api.FeatureColourI;
+import jalview.api.FeatureSettingsModelI;
+import jalview.api.FeaturesDisplayedI;
 import jalview.api.ViewStyleI;
 import jalview.bin.Cache;
 import jalview.commands.CommandI;
@@ -72,7 +75,6 @@ import java.awt.Rectangle;
 import java.util.ArrayList;
 import java.util.Hashtable;
 import java.util.List;
-import java.util.Set;
 import java.util.Vector;
 
 import javax.swing.JInternalFrame;
@@ -109,6 +111,7 @@ public class AlignViewport extends AlignmentViewport implements
   private boolean gatherViewsHere = false;
 
   private AnnotationColumnChooser annotationColumnSelectionState;
+
   /**
    * Creates a new AlignViewport object.
    * 
@@ -399,6 +402,7 @@ public class AlignViewport extends AlignmentViewport implements
             viewStyle.getFontSize()), false);
 
   }
+
   /**
    * DOCUMENT ME!
    * 
@@ -459,7 +463,7 @@ public class AlignViewport extends AlignmentViewport implements
     AlignmentI al = getAlignment();
     if (al != null)
     {
-      Set<AlignedCodonFrame> mappings = al.getCodonFrames();
+      List<AlignedCodonFrame> mappings = al.getCodonFrames();
       if (mappings != null)
       {
         StructureSelectionManager ssm = StructureSelectionManager
@@ -480,6 +484,7 @@ public class AlignViewport extends AlignmentViewport implements
    * 
    * @return DOCUMENT ME!
    */
+  @Override
   public char getGapCharacter()
   {
     return getAlignment().getGapCharacter();
@@ -504,6 +509,7 @@ public class AlignViewport extends AlignmentViewport implements
    * 
    * @return DOCUMENT ME!
    */
+  @Override
   public ColumnSelection getColumnSelection()
   {
     return colSel;
@@ -565,11 +571,9 @@ public class AlignViewport extends AlignmentViewport implements
     // TODO: JAL-1126
     if (historyList == null || redoList == null)
     {
-      return new long[]
-      { -1, -1 };
+      return new long[] { -1, -1 };
     }
-    return new long[]
-    { historyList.hashCode(), this.redoList.hashCode() };
+    return new long[] { historyList.hashCode(), this.redoList.hashCode() };
   }
 
   /**
@@ -617,6 +621,7 @@ public class AlignViewport extends AlignmentViewport implements
   /**
    * Send the current selection to be broadcast to any selection listeners.
    */
+  @Override
   public void sendSelection()
   {
     jalview.structure.StructureSelectionManager
@@ -714,8 +719,7 @@ public class AlignViewport extends AlignmentViewport implements
       List<SequenceI> seqs = new ArrayList<SequenceI>();
       for (SequenceI sq : alignment.getSequences())
       {
-        Vector<PDBEntry> pdbs = sq
-                .getDatasetSequence().getAllPDBEntries();
+        Vector<PDBEntry> pdbs = sq.getDatasetSequence().getAllPDBEntries();
         if (pdbs == null)
         {
           continue;
@@ -737,6 +741,7 @@ public class AlignViewport extends AlignmentViewport implements
     return seqvectors.toArray(new SequenceI[seqvectors.size()][]);
   }
 
+  @Override
   public boolean isNormaliseSequenceLogo()
   {
     return normaliseSequenceLogo;
@@ -751,6 +756,7 @@ public class AlignViewport extends AlignmentViewport implements
    * 
    * @return true if alignment characters should be displayed
    */
+  @Override
   public boolean isValidCharWidth()
   {
     return validCharWidth;
@@ -826,10 +832,10 @@ public class AlignViewport extends AlignmentViewport implements
    * may give the user the option to open a new frame, or split panel, with cDNA
    * and protein linked.
    * 
-   * @param al
+   * @param toAdd
    * @param title
    */
-  public void addAlignment(AlignmentI al, String title)
+  public void addAlignment(AlignmentI toAdd, String title)
   {
     // TODO: promote to AlignViewportI? applet CutAndPasteTransfer is different
 
@@ -842,25 +848,26 @@ public class AlignViewport extends AlignmentViewport implements
     // TODO: create undo object for this JAL-1101
 
     /*
-     * If any cDNA/protein mappings can be made between the alignments, offer to
-     * open a linked alignment with split frame option.
+     * Ensure datasets are created for the new alignment as
+     * mappings operate on dataset sequences
+     */
+    toAdd.setDataset(null);
+
+    /*
+     * Check if any added sequence could be the object of a mapping or
+     * cross-reference; if so, make the mapping explicit 
+     */
+    getAlignment().realiseMappings(toAdd.getSequences());
+
+    /*
+     * If any cDNA/protein mappings exist or can be made between the alignments, 
+     * offer to open a split frame with linked alignments
      */
     if (Cache.getDefault(Preferences.ENABLE_SPLIT_FRAME, true))
     {
-      if (al.getDataset() == null)
+      if (AlignmentUtils.isMappable(toAdd, getAlignment()))
       {
-        // need to create ds seqs
-        for (SequenceI sq : al.getSequences())
-        {
-          if (sq.getDatasetSequence() == null)
-          {
-            sq.createDatasetSequence();
-          }
-        }
-      }
-      if (AlignmentUtils.isMappable(al, getAlignment()))
-      {
-        if (openLinkedAlignment(al, title))
+        if (openLinkedAlignment(toAdd, title))
         {
           return;
         }
@@ -873,9 +880,22 @@ public class AlignViewport extends AlignmentViewport implements
     // TODO: JAL-407 regardless of above - identical sequences (based on ID and
     // provenance) should share the same dataset sequence
 
-    for (int i = 0; i < al.getHeight(); i++)
+    AlignmentI al = getAlignment();
+    String gap = String.valueOf(al.getGapCharacter());
+    for (int i = 0; i < toAdd.getHeight(); i++)
     {
-      getAlignment().addSequence(al.getSequenceAt(i));
+      SequenceI seq = toAdd.getSequenceAt(i);
+      /*
+       * experimental!
+       * - 'align' any mapped sequences as per existing 
+       *    e.g. cdna to genome, domain hit to protein sequence
+       * very experimental! (need a separate menu option for this)
+       * - only add mapped sequences ('select targets from a dataset')
+       */
+      if (true /*AlignmentUtils.alignSequenceAs(seq, al, gap, true, true)*/)
+      {
+        al.addSequence(seq);
+      }
     }
 
     setEndSeq(getAlignment().getHeight());
@@ -893,8 +913,8 @@ public class AlignViewport extends AlignmentViewport implements
    */
   protected boolean openLinkedAlignment(AlignmentI al, String title)
   {
-    String[] options = new String[]
-    { MessageManager.getString("action.no"),
+    String[] options = new String[] {
+        MessageManager.getString("action.no"),
         MessageManager.getString("label.split_window"),
         MessageManager.getString("label.new_window"), };
     final String question = JvSwingUtils.wrapTooltip(true,
@@ -927,7 +947,7 @@ public class AlignViewport extends AlignmentViewport implements
      * is a pre-requisite for building mappings.
      */
     al.setDataset(null);
-    AlignmentUtils.mapProteinToCdna(protein, cdna);
+    AlignmentUtils.mapProteinAlignmentToCdna(protein, cdna);
 
     /*
      * Create the AlignFrame for the added alignment. If it is protein, mappings
@@ -937,8 +957,7 @@ public class AlignViewport extends AlignmentViewport implements
             AlignFrame.DEFAULT_HEIGHT);
     newAlignFrame.setTitle(title);
     newAlignFrame.statusBar.setText(MessageManager.formatMessage(
-            "label.successfully_loaded_file", new Object[]
-            { title }));
+            "label.successfully_loaded_file", new Object[] { title }));
 
     // TODO if we want this (e.g. to enable reload of the alignment from file),
     // we will need to add parameters to the stack.
@@ -950,15 +969,13 @@ public class AlignViewport extends AlignmentViewport implements
     if (openInNewWindow)
     {
       Desktop.addInternalFrame(newAlignFrame, title,
-              AlignFrame.DEFAULT_WIDTH,
-              AlignFrame.DEFAULT_HEIGHT);
+              AlignFrame.DEFAULT_WIDTH, AlignFrame.DEFAULT_HEIGHT);
     }
 
     try
     {
       newAlignFrame.setMaximum(jalview.bin.Cache.getDefault(
-              "SHOW_FULLSCREEN",
-              false));
+              "SHOW_FULLSCREEN", false));
     } catch (java.beans.PropertyVetoException ex)
     {
     }
@@ -987,7 +1004,8 @@ public class AlignViewport extends AlignmentViewport implements
   {
     /*
      * Make a new frame with a copy of the alignment we are adding to. If this
-     * is protein, the mappings to cDNA will be registered with StructureSelectionManager as a side-effect.
+     * is protein, the mappings to cDNA will be registered with
+     * StructureSelectionManager as a side-effect.
      */
     AlignFrame copyMe = new AlignFrame(complement,
             AlignFrame.DEFAULT_WIDTH, AlignFrame.DEFAULT_HEIGHT);
@@ -996,8 +1014,7 @@ public class AlignViewport extends AlignmentViewport implements
     AlignmentI al = newAlignFrame.viewport.getAlignment();
     final AlignFrame proteinFrame = al.isNucleotide() ? copyMe
             : newAlignFrame;
-    final AlignFrame cdnaFrame = al.isNucleotide() ? newAlignFrame
-            : copyMe;
+    final AlignFrame cdnaFrame = al.isNucleotide() ? newAlignFrame : copyMe;
     cdnaFrame.setVisible(true);
     proteinFrame.setVisible(true);
     String linkedTitle = MessageManager
@@ -1074,8 +1091,9 @@ public class AlignViewport extends AlignmentViewport implements
     if (!sr.isEmpty())
     {
       // TODO would like next line without cast but needs more refactoring...
-      final AlignmentPanel complementPanel = ((AlignViewport) getCodingComplement()).getAlignPanel();
-      complementPanel.setFollowingComplementScroll(true);
+      final AlignmentPanel complementPanel = ((AlignViewport) getCodingComplement())
+              .getAlignPanel();
+      complementPanel.setDontScrollComplement(true);
       complementPanel.scrollToCentre(sr, verticalOffset);
     }
   }
@@ -1110,4 +1128,67 @@ public class AlignViewport extends AlignmentViewport implements
     return true;
   }
 
+  /**
+   * Applies the supplied feature settings descriptor to currently known
+   * features. This supports an 'initial configuration' of feature colouring
+   * based on a preset or user favourite. This may then be modified in the usual
+   * way using the Feature Settings dialogue.
+   * 
+   * @param featureSettings
+   */
+  public void applyFeaturesStyle(FeatureSettingsModelI featureSettings)
+  {
+    if (featureSettings == null)
+    {
+      return;
+    }
+
+    FeatureRenderer fr = getAlignPanel().getSeqPanel().seqCanvas
+            .getFeatureRenderer();
+    fr.findAllFeatures(true);
+    List<String> renderOrder = fr.getRenderOrder();
+    FeaturesDisplayedI displayed = fr.getFeaturesDisplayed();
+    displayed.clear();
+    // TODO this clears displayed.featuresRegistered - do we care?
+
+    /*
+     * set feature colour if specified by feature settings
+     * set visibility of all features
+     */
+    for (String type : renderOrder)
+    {
+      FeatureColourI preferredColour = featureSettings
+              .getFeatureColour(type);
+      if (preferredColour != null)
+      {
+        fr.setColour(type, preferredColour);
+      }
+      if (featureSettings.isFeatureDisplayed(type))
+      {
+        displayed.setVisible(type);
+      }
+    }
+
+    /*
+     * set visibility of feature groups
+     */
+    for (String group : fr.getFeatureGroups())
+    {
+      fr.setGroupVisibility(group, featureSettings.isGroupDisplayed(group));
+    }
+
+    /*
+     * order the features
+     */
+    if (featureSettings.optimiseOrder())
+    {
+      // TODO not supported (yet?)
+    }
+    else
+    {
+      fr.orderFeatures(featureSettings);
+    }
+    fr.setTransparency(featureSettings.getTransparency());
+  }
+
 }