JAL-2388 Renamed viewport position props to viewport ranges
[jalview.git] / src / jalview / gui / AlignViewport.java
index 92c6355..11321eb 100644 (file)
  * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
  * The Jalview Authors are detailed in the 'AUTHORS' file.
  */
-/*
- * Jalview - A Sequence Alignment Editor and Viewer
- * Copyright (C) 2007 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
- */
 package jalview.gui;
 
 import jalview.analysis.AlignmentUtils;
@@ -43,6 +25,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;
@@ -52,17 +37,21 @@ import jalview.datamodel.AlignmentI;
 import jalview.datamodel.ColumnSelection;
 import jalview.datamodel.PDBEntry;
 import jalview.datamodel.SearchResults;
+import jalview.datamodel.SearchResultsI;
 import jalview.datamodel.Sequence;
 import jalview.datamodel.SequenceGroup;
 import jalview.datamodel.SequenceI;
+import jalview.renderer.ResidueShader;
+import jalview.schemes.ColourSchemeI;
 import jalview.schemes.ColourSchemeProperty;
+import jalview.schemes.ResidueColourScheme;
 import jalview.schemes.UserColourScheme;
-import jalview.structure.CommandListener;
 import jalview.structure.SelectionSource;
 import jalview.structure.StructureSelectionManager;
 import jalview.structure.VamsasSource;
 import jalview.util.MessageManager;
 import jalview.viewmodel.AlignmentViewport;
+import jalview.viewmodel.ViewportRanges;
 import jalview.ws.params.AutoCalcSetting;
 
 import java.awt.Container;
@@ -72,11 +61,9 @@ 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;
-import javax.swing.JOptionPane;
 
 /**
  * DOCUMENT ME!
@@ -85,7 +72,7 @@ import javax.swing.JOptionPane;
  * @version $Revision: 1.141 $
  */
 public class AlignViewport extends AlignmentViewport implements
-        SelectionSource, CommandListener
+        SelectionSource
 {
   Font font;
 
@@ -251,10 +238,7 @@ public class AlignViewport extends AlignmentViewport implements
 
   void init()
   {
-    this.startRes = 0;
-    this.endRes = alignment.getWidth() - 1;
-    this.startSeq = 0;
-    this.endSeq = alignment.getHeight() - 1;
+    ranges = new ViewportRanges(this.alignment);
     applyViewProperties();
 
     String fontName = Cache.getDefault("FONT_NAME", "SansSerif");
@@ -299,28 +283,27 @@ public class AlignViewport extends AlignmentViewport implements
     initAutoAnnotation();
     String colourProperty = alignment.isNucleotide() ? Preferences.DEFAULT_COLOUR_NUC
             : Preferences.DEFAULT_COLOUR_PROT;
-    String propertyValue = Cache.getProperty(colourProperty);
-    if (propertyValue == null)
+    String schemeName = Cache.getProperty(colourProperty);
+    if (schemeName == null)
     {
-      // fall back on this property for backwards compatibility
-      propertyValue = Cache.getProperty(Preferences.DEFAULT_COLOUR);
+      // only DEFAULT_COLOUR available in Jalview before 2.9
+      schemeName = Cache.getDefault(Preferences.DEFAULT_COLOUR,
+              ResidueColourScheme.NONE);
     }
-    if (propertyValue != null)
-    {
-      globalColourScheme = ColourSchemeProperty.getColour(alignment,
-              propertyValue);
+    ColourSchemeI colourScheme = ColourSchemeProperty.getColourScheme(
+            alignment, schemeName);
+    residueShading = new ResidueShader(colourScheme);
 
-      if (globalColourScheme instanceof UserColourScheme)
-      {
-        globalColourScheme = UserDefinedColours.loadDefaultColours();
-        ((UserColourScheme) globalColourScheme).setThreshold(0,
-                isIgnoreGapsConsensus());
-      }
+    if (colourScheme instanceof UserColourScheme)
+    {
+      residueShading = new ResidueShader(
+              UserDefinedColours.loadDefaultColours());
+      residueShading.setThreshold(0, isIgnoreGapsConsensus());
+    }
 
-      if (globalColourScheme != null)
-      {
-        globalColourScheme.setConsensus(hconsensus);
-      }
+    if (residueShading != null)
+    {
+      residueShading.setConsensus(hconsensus);
     }
   }
 
@@ -398,7 +381,6 @@ public class AlignViewport extends AlignmentViewport implements
     super.setViewStyle(settingsForView);
     setFont(new Font(viewStyle.getFontName(), viewStyle.getFontStyle(),
             viewStyle.getFontSize()), false);
-
   }
 
   /**
@@ -417,10 +399,11 @@ public class AlignViewport extends AlignmentViewport implements
    * @param align
    *          DOCUMENT ME!
    */
+  @Override
   public void setAlignment(AlignmentI align)
   {
     replaceMappings(align);
-    this.alignment = align;
+    super.setAlignment(align);
   }
 
   /**
@@ -461,7 +444,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
@@ -482,6 +465,7 @@ public class AlignViewport extends AlignmentViewport implements
    * 
    * @return DOCUMENT ME!
    */
+  @Override
   public char getGapCharacter()
   {
     return getAlignment().getGapCharacter();
@@ -504,16 +488,6 @@ public class AlignViewport extends AlignmentViewport implements
   /**
    * DOCUMENT ME!
    * 
-   * @return DOCUMENT ME!
-   */
-  public ColumnSelection getColumnSelection()
-  {
-    return colSel;
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
    * @param tree
    *          DOCUMENT ME!
    */
@@ -617,6 +591,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
@@ -658,39 +633,6 @@ public class AlignViewport extends AlignmentViewport implements
   }
 
   /**
-   * synthesize a column selection if none exists so it covers the given
-   * selection group. if wholewidth is false, no column selection is made if the
-   * selection group covers the whole alignment width.
-   * 
-   * @param sg
-   * @param wholewidth
-   */
-  public void expandColSelection(SequenceGroup sg, boolean wholewidth)
-  {
-    int sgs, sge;
-    if (sg != null
-            && (sgs = sg.getStartRes()) >= 0
-            && sg.getStartRes() <= (sge = sg.getEndRes())
-            && (colSel == null || colSel.getSelected() == null || colSel
-                    .getSelected().size() == 0))
-    {
-      if (!wholewidth && alignment.getWidth() == (1 + sge - sgs))
-      {
-        // do nothing
-        return;
-      }
-      if (colSel == null)
-      {
-        colSel = new ColumnSelection();
-      }
-      for (int cspos = sg.getStartRes(); cspos <= sg.getEndRes(); cspos++)
-      {
-        colSel.addElement(cspos);
-      }
-    }
-  }
-
-  /**
    * Returns the (Desktop) instance of the StructureSelectionManager
    */
   @Override
@@ -711,31 +653,49 @@ public class AlignViewport extends AlignmentViewport implements
     List<SequenceI[]> seqvectors = new ArrayList<SequenceI[]>();
     for (PDBEntry pdb : pdbEntries)
     {
-      List<SequenceI> seqs = new ArrayList<SequenceI>();
+      List<SequenceI> choosenSeqs = new ArrayList<SequenceI>();
       for (SequenceI sq : alignment.getSequences())
       {
-        Vector<PDBEntry> pdbs = sq.getDatasetSequence().getAllPDBEntries();
-        if (pdbs == null)
+        Vector<PDBEntry> pdbRefEntries = sq.getDatasetSequence()
+                .getAllPDBEntries();
+        if (pdbRefEntries == null)
         {
           continue;
         }
-        for (PDBEntry p1 : pdbs)
+        for (PDBEntry pdbRefEntry : pdbRefEntries)
         {
-          if (p1.getId().equals(pdb.getId()))
+          if (pdbRefEntry.getId().equals(pdb.getId()))
           {
-            if (!seqs.contains(sq))
+            if (pdbRefEntry.getChainCode() != null
+                    && pdb.getChainCode() != null)
             {
-              seqs.add(sq);
-              continue;
+              if (pdbRefEntry.getChainCode().equalsIgnoreCase(
+                      pdb.getChainCode())
+                      && !choosenSeqs.contains(sq))
+              {
+                choosenSeqs.add(sq);
+                continue;
+              }
             }
+            else
+            {
+              if (!choosenSeqs.contains(sq))
+              {
+                choosenSeqs.add(sq);
+                continue;
+              }
+            }
+
           }
         }
       }
-      seqvectors.add(seqs.toArray(new SequenceI[seqs.size()]));
+      seqvectors
+              .add(choosenSeqs.toArray(new SequenceI[choosenSeqs.size()]));
     }
     return seqvectors.toArray(new SequenceI[seqvectors.size()][]);
   }
 
+  @Override
   public boolean isNormaliseSequenceLogo()
   {
     return normaliseSequenceLogo;
@@ -750,6 +710,7 @@ public class AlignViewport extends AlignmentViewport implements
    * 
    * @return true if alignment characters should be displayed
    */
+  @Override
   public boolean isValidCharWidth()
   {
     return validCharWidth;
@@ -825,10 +786,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
 
@@ -841,25 +802,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)
-      {
-        // need to create ds seqs
-        for (SequenceI sq : al.getSequences())
-        {
-          if (sq.getDatasetSequence() == null)
-          {
-            sq.createDatasetSequence();
-          }
-        }
-      }
-      if (AlignmentUtils.isMappable(al, getAlignment()))
+      if (AlignmentUtils.isMappable(toAdd, getAlignment()))
       {
-        if (openLinkedAlignment(al, title))
+        if (openLinkedAlignment(toAdd, title))
         {
           return;
         }
@@ -872,9 +834,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());
@@ -898,9 +873,9 @@ public class AlignViewport extends AlignmentViewport implements
         MessageManager.getString("label.new_window"), };
     final String question = JvSwingUtils.wrapTooltip(true,
             MessageManager.getString("label.open_split_window?"));
-    int response = JOptionPane.showOptionDialog(Desktop.desktop, question,
+    int response = JvOptionPane.showOptionDialog(Desktop.desktop, question,
             MessageManager.getString("label.open_split_window"),
-            JOptionPane.DEFAULT_OPTION, JOptionPane.PLAIN_MESSAGE, null,
+            JvOptionPane.DEFAULT_OPTION, JvOptionPane.PLAIN_MESSAGE, null,
             options, options[0]);
 
     if (response != 1 && response != 2)
@@ -940,7 +915,7 @@ public class AlignViewport extends AlignmentViewport implements
 
     // TODO if we want this (e.g. to enable reload of the alignment from file),
     // we will need to add parameters to the stack.
-    // if (!protocol.equals(AppletFormatAdapter.PASTE))
+    // if (!protocol.equals(DataSourceType.PASTE))
     // {
     // alignFrame.setFileName(file, format);
     // }
@@ -1065,7 +1040,7 @@ public class AlignViewport extends AlignmentViewport implements
      * there is no complement, or it is not following highlights, or no mapping
      * is found, the result will be empty.
      */
-    SearchResults sr = new SearchResults();
+    SearchResultsI sr = new SearchResults();
     int verticalOffset = findComplementScrollTarget(sr);
     if (!sr.isEmpty())
     {
@@ -1107,4 +1082,68 @@ 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
+   */
+  @Override
+  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());
+  }
+
 }