JAL-2547 don't show features in tooltip over a gap
[jalview.git] / src / jalview / gui / SeqPanel.java
index 74ebb37..2884c50 100644 (file)
@@ -27,6 +27,7 @@ import jalview.commands.EditCommand.Action;
 import jalview.commands.EditCommand.Edit;
 import jalview.datamodel.AlignmentI;
 import jalview.datamodel.ColumnSelection;
+import jalview.datamodel.HiddenColumns;
 import jalview.datamodel.SearchResultMatchI;
 import jalview.datamodel.SearchResults;
 import jalview.datamodel.SearchResultsI;
@@ -182,7 +183,7 @@ public class SeqPanel extends JPanel implements MouseListener,
    * @param evt
    * @return
    */
-  int findRes(MouseEvent evt)
+  int findColumn(MouseEvent evt)
   {
     int res = 0;
     int x = evt.getX();
@@ -233,7 +234,8 @@ public class SeqPanel extends JPanel implements MouseListener,
 
     if (av.hasHiddenColumns())
     {
-      res = av.getColumnSelection().adjustForHiddenColumns(res);
+      res = av.getAlignment().getHiddenColumns()
+              .adjustForHiddenColumns(res);
     }
 
     return res;
@@ -339,20 +341,23 @@ public class SeqPanel extends JPanel implements MouseListener,
   {
     seqCanvas.cursorX += dx;
     seqCanvas.cursorY += dy;
+
+    HiddenColumns hidden = av.getAlignment().getHiddenColumns();
+
     if (av.hasHiddenColumns()
-            && !av.getColumnSelection().isVisible(seqCanvas.cursorX))
+ && !hidden.isVisible(seqCanvas.cursorX))
     {
       int original = seqCanvas.cursorX - dx;
       int maxWidth = av.getAlignment().getWidth();
 
-      while (!av.getColumnSelection().isVisible(seqCanvas.cursorX)
+      while (!hidden.isVisible(seqCanvas.cursorX)
               && seqCanvas.cursorX < maxWidth && seqCanvas.cursorX > 0)
       {
         seqCanvas.cursorX += dx;
       }
 
       if (seqCanvas.cursorX >= maxWidth
-              || !av.getColumnSelection().isVisible(seqCanvas.cursorX))
+              || !hidden.isVisible(seqCanvas.cursorX))
       {
         seqCanvas.cursorX = original;
       }
@@ -398,16 +403,17 @@ public class SeqPanel extends JPanel implements MouseListener,
       }
       if (!av.getWrapAlignment())
       {
-        while (seqCanvas.cursorX < av.getColumnSelection()
-                .adjustForHiddenColumns(av.getRanges().getStartRes()))
+        HiddenColumns hidden = av.getAlignment().getHiddenColumns();
+        while (seqCanvas.cursorX < hidden.adjustForHiddenColumns(av
+                .getRanges().getStartRes()))
         {
           if (!ap.scrollRight(false))
           {
             break;
           }
         }
-        while (seqCanvas.cursorX > av.getColumnSelection()
-                .adjustForHiddenColumns(av.getRanges().getEndRes()))
+        while (seqCanvas.cursorX > hidden.adjustForHiddenColumns(av
+                .getRanges().getEndRes()))
         {
           if (!ap.scrollRight(true))
           {
@@ -636,7 +642,7 @@ public class SeqPanel extends JPanel implements MouseListener,
     }
 
     int seq = findSeq(evt);
-    int res = findRes(evt);
+    int res = findColumn(evt);
 
     if (seq < 0 || res < 0)
     {
@@ -735,25 +741,27 @@ public class SeqPanel extends JPanel implements MouseListener,
       mouseDragged(evt);
     }
 
-    int res = findRes(evt);
+    final int column = findColumn(evt);
     int seq = findSeq(evt);
-    int pos;
-    if (res < 0 || seq < 0 || seq >= av.getAlignment().getHeight())
+    if (column < 0 || seq < 0 || seq >= av.getAlignment().getHeight())
     {
       return;
     }
 
     SequenceI sequence = av.getAlignment().getSequenceAt(seq);
 
-    if (res >= sequence.getLength())
+    if (column >= sequence.getLength())
     {
       return;
     }
 
-    pos = setStatusMessage(sequence, res, seq);
+    /*
+     * set status bar message, returning residue position in sequence
+     */
+    final int pos = setStatusMessage(sequence, column, seq);
     if (ssm != null && pos > -1)
     {
-      mouseOverSequence(sequence, res, pos);
+      mouseOverSequence(sequence, column, pos);
     }
 
     tooltipText.setLength(6); // Cuts the buffer back to <html>
@@ -763,7 +771,8 @@ public class SeqPanel extends JPanel implements MouseListener,
     {
       for (int g = 0; g < groups.length; g++)
       {
-        if (groups[g].getStartRes() <= res && groups[g].getEndRes() >= res)
+        if (groups[g].getStartRes() <= column
+                && groups[g].getEndRes() >= column)
         {
           if (!groups[g].getName().startsWith("JTreeGroup")
                   && !groups[g].getName().startsWith("JGroup"))
@@ -779,14 +788,11 @@ public class SeqPanel extends JPanel implements MouseListener,
       }
     }
 
-    // use aa to see if the mouse pointer is on a
-    if (av.isShowSequenceFeatures())
+    if (av.isShowSequenceFeatures() && pos != -1)
     {
-      int rpos;
       List<SequenceFeature> features = ap.getFeatureRenderer()
-              .findFeaturesAtRes(sequence.getDatasetSequence(),
-                      rpos = sequence.findPosition(res));
-      seqARep.appendFeatures(tooltipText, rpos, features,
+              .findFeaturesAtRes(sequence.getDatasetSequence(), pos);
+      seqARep.appendFeatures(tooltipText, pos, features,
               this.ap.getSeqPanel().seqCanvas.fr.getMinMax());
     }
     if (tooltipText.length() == 6) // <html>
@@ -853,17 +859,20 @@ public class SeqPanel extends JPanel implements MouseListener,
   // avcontroller or viewModel
 
   /**
-   * Set status message in alignment panel
+   * Sets the status message in alignment panel, showing the sequence number
+   * (index) and id, residue and residue position for the given sequence and
+   * column position. Returns the calculated residue position in the sequence,
+   * or -1 for a gapped column position.
    * 
    * @param sequence
    *          aligned sequence object
-   * @param res
+   * @param column
    *          alignment column
    * @param seq
    *          index of sequence in alignment
    * @return position of res in sequence
    */
-  int setStatusMessage(SequenceI sequence, int res, int seq)
+  int setStatusMessage(SequenceI sequence, final int column, int seq)
   {
     StringBuilder text = new StringBuilder(32);
 
@@ -878,7 +887,7 @@ public class SeqPanel extends JPanel implements MouseListener,
     /*
      * Try to translate the display character to residue name (null for gap).
      */
-    final String displayChar = String.valueOf(sequence.getCharAt(res));
+    final String displayChar = String.valueOf(sequence.getCharAt(column));
     if (av.getAlignment().isNucleotide())
     {
       residue = ResidueProperties.nucleotideName.get(displayChar);
@@ -901,7 +910,7 @@ public class SeqPanel extends JPanel implements MouseListener,
     int pos = -1;
     if (residue != null)
     {
-      pos = sequence.findPosition(res);
+      pos = sequence.findPosition(column);
       text.append(" (").append(Integer.toString(pos)).append(")");
     }
     ap.alignFrame.statusBar.setText(text.toString());
@@ -945,30 +954,36 @@ public class SeqPanel extends JPanel implements MouseListener,
   }
 
   /**
-   * DOCUMENT ME!
-   * 
-   * @param evt
-   *          DOCUMENT ME!
+   * {@inheritDoc}
    */
   @Override
   public void mouseDragged(MouseEvent evt)
   {
     if (mouseWheelPressed)
     {
+      boolean inSplitFrame = ap.av.getCodingComplement() != null;
+      boolean copyChanges = inSplitFrame && av.isProteinFontAsCdna();
+
       int oldWidth = av.getCharWidth();
 
       // Which is bigger, left-right or up-down?
       if (Math.abs(evt.getY() - lastMousePress.getY()) > Math.abs(evt
               .getX() - lastMousePress.getX()))
       {
+        /*
+         * on drag up or down, decrement or increment font size
+         */
         int fontSize = av.font.getSize();
+        boolean fontChanged = false;
 
         if (evt.getY() < lastMousePress.getY())
         {
+          fontChanged = true;
           fontSize--;
         }
         else if (evt.getY() > lastMousePress.getY())
         {
+          fontChanged = true;
           fontSize++;
         }
 
@@ -977,24 +992,56 @@ public class SeqPanel extends JPanel implements MouseListener,
           fontSize = 1;
         }
 
-        av.setFont(
-                new Font(av.font.getName(), av.font.getStyle(), fontSize),
-                true);
-        av.setCharWidth(oldWidth);
-        ap.fontChanged();
+        if (fontChanged)
+        {
+          Font newFont = new Font(av.font.getName(), av.font.getStyle(),
+                  fontSize);
+          av.setFont(newFont, true);
+          av.setCharWidth(oldWidth);
+          ap.fontChanged();
+          if (copyChanges)
+          {
+            ap.av.getCodingComplement().setFont(newFont, true);
+            SplitFrame splitFrame = (SplitFrame) ap.alignFrame
+                    .getSplitViewContainer();
+            splitFrame.adjustLayout();
+            splitFrame.repaint();
+          }
+        }
       }
       else
       {
+        /*
+         * on drag left or right, decrement or increment character width
+         */
+        int newWidth = 0;
         if (evt.getX() < lastMousePress.getX() && av.getCharWidth() > 1)
         {
-          av.setCharWidth(av.getCharWidth() - 1);
+          newWidth = av.getCharWidth() - 1;
+          av.setCharWidth(newWidth);
         }
         else if (evt.getX() > lastMousePress.getX())
         {
-          av.setCharWidth(av.getCharWidth() + 1);
+          newWidth = av.getCharWidth() + 1;
+          av.setCharWidth(newWidth);
+        }
+        if (newWidth > 0)
+        {
+          ap.paintAlignment(false);
+          if (copyChanges)
+          {
+            /*
+             * need to ensure newWidth is set on cdna, regardless of which
+             * panel the mouse drag happened in; protein will compute its 
+             * character width as 1:1 or 3:1
+             */
+            av.getCodingComplement().setCharWidth(newWidth);
+            SplitFrame splitFrame = (SplitFrame) ap.alignFrame
+                    .getSplitViewContainer();
+            splitFrame.adjustLayout();
+            splitFrame.repaint();
+          }
         }
-
-        ap.paintAlignment(false);
       }
 
       FontMetrics fm = getFontMetrics(av.getFont());
@@ -1011,7 +1058,7 @@ public class SeqPanel extends JPanel implements MouseListener,
       return;
     }
 
-    int res = findRes(evt);
+    int res = findColumn(evt);
 
     if (res < 0)
     {
@@ -1144,8 +1191,10 @@ public class SeqPanel extends JPanel implements MouseListener,
     if (av.hasHiddenColumns())
     {
       fixedColumns = true;
-      int y1 = av.getColumnSelection().getHiddenBoundaryLeft(startres);
-      int y2 = av.getColumnSelection().getHiddenBoundaryRight(startres);
+      int y1 = av.getAlignment().getHiddenColumns()
+              .getHiddenBoundaryLeft(startres);
+      int y2 = av.getAlignment().getHiddenColumns()
+              .getHiddenBoundaryRight(startres);
 
       if ((insertGap && startres > y1 && lastres < y1)
               || (!insertGap && startres < y2 && lastres > y2))
@@ -1220,8 +1269,8 @@ public class SeqPanel extends JPanel implements MouseListener,
         {
           if (sg.getSize() == av.getAlignment().getHeight())
           {
-            if ((av.hasHiddenColumns() && startres < av
-                    .getColumnSelection().getHiddenBoundaryRight(startres)))
+            if ((av.hasHiddenColumns() && startres < av.getAlignment()
+                    .getHiddenColumns().getHiddenBoundaryRight(startres)))
             {
               endEditing();
               return;
@@ -1506,7 +1555,7 @@ public class SeqPanel extends JPanel implements MouseListener,
 
       List<SequenceFeature> features = seqCanvas.getFeatureRenderer()
               .findFeaturesAtRes(sequence.getDatasetSequence(),
-                      sequence.findPosition(findRes(evt)));
+                      sequence.findPosition(findColumn(evt)));
 
       if (!features.isEmpty())
       {
@@ -1524,7 +1573,7 @@ public class SeqPanel extends JPanel implements MouseListener,
          */
         List<SequenceI> seqs = Collections.singletonList(sequence);
         seqCanvas.getFeatureRenderer().amendFeatures(seqs, features, false,
-                ap, null);
+                ap);
         seqCanvas.highlightSearchResults(null);
       }
     }
@@ -1568,7 +1617,7 @@ public class SeqPanel extends JPanel implements MouseListener,
    */
   public void doMousePressedDefineMode(MouseEvent evt)
   {
-    final int res = findRes(evt);
+    final int res = findColumn(evt);
     final int seq = findSeq(evt);
     oldSeq = seq;
     needOverviewUpdate = false;
@@ -1627,7 +1676,7 @@ public class SeqPanel extends JPanel implements MouseListener,
 
     if (av.cursorMode)
     {
-      seqCanvas.cursorX = findRes(evt);
+      seqCanvas.cursorX = findColumn(evt);
       seqCanvas.cursorY = findSeq(evt);
       seqCanvas.repaint();
       return;
@@ -1683,7 +1732,7 @@ public class SeqPanel extends JPanel implements MouseListener,
    */
   void showPopupMenu(MouseEvent evt)
   {
-    final int res = findRes(evt);
+    final int res = findColumn(evt);
     final int seq = findSeq(evt);
     SequenceI sequence = av.getAlignment().getSequenceAt(seq);
     List<SequenceFeature> allFeatures = ap.getFeatureRenderer()
@@ -1754,7 +1803,7 @@ public class SeqPanel extends JPanel implements MouseListener,
    */
   public void doMouseDraggedDefineMode(MouseEvent evt)
   {
-    int res = findRes(evt);
+    int res = findColumn(evt);
     int y = findSeq(evt);
 
     if (wrappedBlock != startWrapBlock)
@@ -1957,7 +2006,7 @@ public class SeqPanel extends JPanel implements MouseListener,
    */
   @Override
   public void selection(SequenceGroup seqsel, ColumnSelection colsel,
-          SelectionSource source)
+          HiddenColumns hidden, SelectionSource source)
   {
     // TODO: fix this hack - source of messages is align viewport, but SeqPanel
     // handles selection messages...
@@ -1993,7 +2042,7 @@ public class SeqPanel extends JPanel implements MouseListener,
      * Check for selection in a view of which this one is a dna/protein
      * complement.
      */
-    if (selectionFromTranslation(seqsel, colsel, source))
+    if (selectionFromTranslation(seqsel, colsel, hidden, source))
     {
       return;
     }
@@ -2056,7 +2105,8 @@ public class SeqPanel extends JPanel implements MouseListener,
         }
         else
         {
-          av.getColumnSelection().setElementsFrom(colsel);
+          av.getColumnSelection().setElementsFrom(colsel,
+                  av.getAlignment().getHiddenColumns());
         }
       }
       av.isColSelChanged(true);
@@ -2065,8 +2115,8 @@ public class SeqPanel extends JPanel implements MouseListener,
 
     if (copycolsel
             && av.hasHiddenColumns()
-            && (av.getColumnSelection() == null || av.getColumnSelection()
-                    .getHiddenColumns() == null))
+            && (av.getAlignment().getHiddenColumns() == null || av
+                    .getAlignment().getHiddenColumns().getHiddenRegions() == null))
     {
       System.err.println("Bad things");
     }
@@ -2095,7 +2145,8 @@ public class SeqPanel extends JPanel implements MouseListener,
    * @param source
    */
   protected boolean selectionFromTranslation(SequenceGroup seqsel,
-          ColumnSelection colsel, SelectionSource source)
+          ColumnSelection colsel, HiddenColumns hidden,
+          SelectionSource source)
   {
     if (!(source instanceof AlignViewportI))
     {
@@ -2118,9 +2169,13 @@ public class SeqPanel extends JPanel implements MouseListener,
     /*
      * Map column selection
      */
-    ColumnSelection cs = MappingUtils.mapColumnSelection(colsel, sourceAv,
-            av);
+    // ColumnSelection cs = MappingUtils.mapColumnSelection(colsel, sourceAv,
+    // av);
+    ColumnSelection cs = new ColumnSelection();
+    HiddenColumns hs = new HiddenColumns();
+    MappingUtils.mapColumnSelection(colsel, hidden, sourceAv, av, cs, hs);
     av.setColumnSelection(cs);
+    av.getAlignment().setHiddenColumns(hs);
 
     // lastly, update any dependent dialogs
     if (ap.getCalculationDialog() != null)