JAL-3093 'read-only' annotations when in wrapped mode
authorgmungoc <g.m.carstairs@dundee.ac.uk>
Mon, 1 Oct 2018 16:22:33 +0000 (17:22 +0100)
committergmungoc <g.m.carstairs@dundee.ac.uk>
Mon, 1 Oct 2018 16:22:33 +0000 (17:22 +0100)
src/jalview/gui/IdPanel.java
src/jalview/gui/SeqPanel.java

index a183144..94eab76 100755 (executable)
  */
 package jalview.gui;
 
+import jalview.datamodel.AlignmentAnnotation;
 import jalview.datamodel.Sequence;
 import jalview.datamodel.SequenceFeature;
 import jalview.datamodel.SequenceGroup;
 import jalview.datamodel.SequenceI;
+import jalview.gui.SeqPanel.MousePos;
 import jalview.io.SequenceAnnotationReport;
 import jalview.util.MessageManager;
 import jalview.util.Platform;
@@ -102,15 +104,28 @@ public class IdPanel extends JPanel
   public void mouseMoved(MouseEvent e)
   {
     SeqPanel sp = alignPanel.getSeqPanel();
-    int seq = Math.max(0, sp.findSeq(e));
-    if (seq > -1 && seq < av.getAlignment().getHeight())
+    MousePos pos = sp.findMousePosition(e);
+    if (pos.annotationIndex != -1)
     {
-      SequenceI sequence = av.getAlignment().getSequenceAt(seq);
-      StringBuilder tip = new StringBuilder(64);
-      seqAnnotReport.createTooltipAnnotationReport(tip, sequence,
-              av.isShowDBRefs(), av.isShowNPFeats(), sp.seqCanvas.fr);
-      setToolTipText(JvSwingUtils.wrapTooltip(true,
-              sequence.getDisplayId(true) + " " + tip.toString()));
+      /*
+       * mouse is over an annotation label in wrapped mode
+       */
+      AlignmentAnnotation annotation = av.getAlignment()
+              .getAlignmentAnnotation()[pos.annotationIndex];
+      setToolTipText(AnnotationLabels.getTooltip(annotation));
+    }
+    else
+    {
+      int seq = Math.max(0, pos.seqIndex);
+      if (seq < av.getAlignment().getHeight())
+      {
+        SequenceI sequence = av.getAlignment().getSequenceAt(seq);
+        StringBuilder tip = new StringBuilder(64);
+        seqAnnotReport.createTooltipAnnotationReport(tip, sequence,
+                av.isShowDBRefs(), av.isShowNPFeats(), sp.seqCanvas.fr);
+        setToolTipText(JvSwingUtils.wrapTooltip(true,
+                sequence.getDisplayId(true) + " " + tip.toString()));
+      }
     }
   }
 
@@ -125,7 +140,14 @@ public class IdPanel extends JPanel
   {
     mouseDragging = true;
 
-    int seq = Math.max(0, alignPanel.getSeqPanel().findSeq(e));
+    MousePos pos = alignPanel.getSeqPanel().findMousePosition(e);
+    if (pos.annotationIndex != -1)
+    {
+      // mouse is over annotation label in wrapped mode
+      return;
+    }
+
+    int seq = Math.max(0, pos.seqIndex);
 
     if (seq < lastid)
     {
@@ -196,7 +218,14 @@ public class IdPanel extends JPanel
       return;
     }
 
-    int seq = alignPanel.getSeqPanel().findSeq(e);
+    MousePos pos = alignPanel.getSeqPanel().findMousePosition(e);
+    if (pos.annotationIndex != -1)
+    {
+      // mouse is over annotation label in wrapped mode
+      return;
+    }
+
+    int seq = pos.seqIndex;
     String id = av.getAlignment().getSequenceAt(seq).getName();
     String url = Preferences.sequenceUrlLinks.getPrimaryUrl(id);
 
@@ -276,9 +305,16 @@ public class IdPanel extends JPanel
       return;
     }
 
+    MousePos pos = alignPanel.getSeqPanel().findMousePosition(e);
+    if (pos.annotationIndex != -1)
+    {
+      // mouse is over an annotation label in wrapped mode
+      return;
+    }
+    
     if (e.isPopupTrigger()) // Mac reports this in mousePressed
     {
-      showPopupMenu(e);
+      showPopupMenu(e, pos);
       return;
     }
 
@@ -301,14 +337,13 @@ public class IdPanel extends JPanel
       av.getSelectionGroup().setEndRes(av.getAlignment().getWidth() - 1);
     }
 
-    int seq = alignPanel.getSeqPanel().findSeq(e);
     if (e.isShiftDown() && (lastid != -1))
     {
-      selectSeqs(lastid, seq);
+      selectSeqs(lastid, pos.seqIndex);
     }
     else
     {
-      selectSeq(seq);
+      selectSeq(pos.seqIndex);
     }
 
     av.isSelectionGroupChanged(true);
@@ -321,10 +356,9 @@ public class IdPanel extends JPanel
    * 
    * @param e
    */
-  void showPopupMenu(MouseEvent e)
+  void showPopupMenu(MouseEvent e, MousePos pos)
   {
-    int seq2 = alignPanel.getSeqPanel().findSeq(e);
-    Sequence sq = (Sequence) av.getAlignment().getSequenceAt(seq2);
+    Sequence sq = (Sequence) av.getAlignment().getSequenceAt(pos.seqIndex);
 
     /*
      *  build a new links menu based on the current links
@@ -336,10 +370,7 @@ public class IdPanel extends JPanel
     {
       if (sf.links != null)
       {
-        for (String link : sf.links)
-        {
-          nlinks.add(link);
-        }
+        nlinks.addAll(sf.links);
       }
     }
 
@@ -410,6 +441,12 @@ public class IdPanel extends JPanel
     {
       scrollThread.running = false;
     }
+    MousePos pos = alignPanel.getSeqPanel().findMousePosition(e);
+    if (pos.annotationIndex != -1)
+    {
+      // mouse is over an annotation label in wrapped mode
+      return;
+    }
 
     mouseDragging = false;
     PaintRefresher.Refresh(this, av.getSequenceSetId());
@@ -418,7 +455,7 @@ public class IdPanel extends JPanel
 
     if (e.isPopupTrigger()) // Windows reports this in mouseReleased
     {
-      showPopupMenu(e);
+      showPopupMenu(e, pos);
     }
   }
 
index 14ec6e9..e678738 100644 (file)
@@ -287,6 +287,8 @@ public class SeqPanel extends JPanel
                 .getAlignmentAnnotation();
         int rowOffsetPx = yOffsetPx - alignmentHeightPixels;
         annIndex = AnnotationPanel.getRowIndex(rowOffsetPx, anns);
+        // also last sequence in alignment (for backwards compatible behaviour)
+        seq = alignmentHeight - 1;
       }
       else
       {
@@ -353,18 +355,13 @@ public class SeqPanel extends JPanel
     }
     else
     {
-      if (x > seqCanvas.getX() + seqCanvas.getWidth())
-      {
-        // make sure we calculate relative to visible alignment, rather than
-        // right-hand gutter
-        x = seqCanvas.getX() + seqCanvas.getWidth();
-      }
+      /*
+       * make sure we calculate relative to visible alignment, 
+       * rather than right-hand gutter
+       */
+      x = Math.min(x, seqCanvas.getX() + seqCanvas.getWidth());
       res = (x / av.getCharWidth()) + startRes;
-      if (res > av.getRanges().getEndRes())
-      {
-        // moused off right
-        res = av.getRanges().getEndRes();
-      }
+      res = Math.min(res, av.getRanges().getEndRes());
     }
 
     if (av.hasHiddenColumns())
@@ -374,55 +371,6 @@ public class SeqPanel extends JPanel
     }
 
     return res;
-
-  }
-
-  /**
-   * Answers the index in the alignment (0...) of the sequence under the mouse
-   * position. If the mouse is below the alignment (say, over annotations),
-   * answers the index of the last sequence.
-   * 
-   * @param evt
-   * @return
-   */
-  int findSeq(MouseEvent evt)
-  {
-    int seq = 0;
-    int y = evt.getY();
-
-    int charHeight = av.getCharHeight();
-    int alignmentHeight = av.getAlignment().getHeight();
-    if (av.getWrapAlignment())
-    {
-      int hgap = charHeight;
-      if (av.getScaleAboveWrapped())
-      {
-        hgap += charHeight;
-      }
-
-      int alignmentHeightPixels = alignmentHeight * charHeight;
-      int cHeight = alignmentHeightPixels + hgap
-              + seqCanvas.getAnnotationHeight();
-
-      y -= hgap;
-
-      int yOffsetPx = y % cHeight; // yPos below repeating width(s)
-//      if (yOffsetPx > alignmentHeightPixels)
-//      {
-//        seq = -1; // cursor is over annotation or below alignment entirely
-//      }
-//      else
-      // {
-        seq = Math.min(yOffsetPx / charHeight, alignmentHeight - 1);
-//      }
-    }
-    else
-    {
-      seq = Math.min((y / charHeight) + av.getRanges().getStartSeq(),
-              alignmentHeight - 1);
-    }
-
-    return seq;
   }
 
   /**
@@ -758,13 +706,20 @@ public class SeqPanel extends JPanel
   @Override
   public void mouseReleased(MouseEvent evt)
   {
+    MousePos pos = findMousePosition(evt);
+    if (pos.annotationIndex != -1)
+    {
+      // mouse is over annotation row in wrapped mode
+      return;
+    }
+
     boolean didDrag = mouseDragging; // did we come here after a drag
     mouseDragging = false;
     mouseWheelPressed = false;
 
     if (evt.isPopupTrigger()) // Windows: mouseReleased
     {
-      showPopupMenu(evt);
+      showPopupMenu(evt, pos);
       evt.consume();
       return;
     }
@@ -788,6 +743,12 @@ public class SeqPanel extends JPanel
   public void mousePressed(MouseEvent evt)
   {
     lastMousePress = evt.getPoint();
+    MousePos pos = findMousePosition(evt);
+    if (pos.annotationIndex != -1)
+    {
+      // mouse is over an annotation row in wrapped mode
+      return;
+    }
 
     if (SwingUtilities.isMiddleMouseButton(evt))
     {
@@ -806,12 +767,12 @@ public class SeqPanel extends JPanel
     }
     else
     {
-      doMousePressedDefineMode(evt);
+      doMousePressedDefineMode(evt, pos);
       return;
     }
 
-    int seq = findSeq(evt);
-    int res = findColumn(evt);
+    int seq = pos.seqIndex;
+    int res = pos.column;
 
     if (seq < 0 || res < 0)
     {
@@ -933,7 +894,7 @@ public class SeqPanel extends JPanel
       mouseMovedOverAnnotation(mousePos);
       return;
     }
-    final int seq = mousePos.seqIndex;// findSeq(evt);
+    final int seq = mousePos.seqIndex;
 
     final int column = mousePos.column;
     if (column < 0 || seq < 0 || seq >= av.getAlignment().getHeight())
@@ -1216,6 +1177,13 @@ public class SeqPanel extends JPanel
   @Override
   public void mouseDragged(MouseEvent evt)
   {
+    MousePos pos = findMousePosition(evt);
+    if (pos.annotationIndex != -1)
+    {
+      // mouse is over annotation row in wrapped mode
+      return;
+    }
+
     if (mouseWheelPressed)
     {
       boolean inSplitFrame = ap.av.getCodingComplement() != null;
@@ -1315,7 +1283,7 @@ public class SeqPanel extends JPanel
       return;
     }
 
-    int res = findColumn(evt);
+    int res = pos.column;
 
     if (res < 0)
     {
@@ -1801,7 +1769,13 @@ public class SeqPanel extends JPanel
   public void mouseClicked(MouseEvent evt)
   {
     SequenceGroup sg = null;
-    SequenceI sequence = av.getAlignment().getSequenceAt(findSeq(evt));
+    MousePos pos = findMousePosition(evt);
+    if (pos.annotationIndex != -1)
+    {
+      // mouse is over annotation label in wrapped mode
+      return;
+    }
+
     if (evt.getClickCount() > 1)
     {
       sg = av.getSelectionGroup();
@@ -1811,12 +1785,13 @@ public class SeqPanel extends JPanel
         av.setSelectionGroup(null);
       }
 
-      int column = findColumn(evt);
+      int column = pos.column;
 
       /*
        * find features at the position (if not gapped), or straddling
        * the position (if at a gap)
        */
+      SequenceI sequence = av.getAlignment().getSequenceAt(pos.seqIndex);// findSeq(evt));
       List<SequenceFeature> features = seqCanvas.getFeatureRenderer()
               .findFeaturesAtColumn(sequence, column + 1);
 
@@ -1883,28 +1858,28 @@ public class SeqPanel extends JPanel
   /**
    * DOCUMENT ME!
    * 
-   * @param evt
+   * @param pos
    *          DOCUMENT ME!
    */
-  public void doMousePressedDefineMode(MouseEvent evt)
+  protected void doMousePressedDefineMode(MouseEvent evt, MousePos pos)
   {
-    final int res = findColumn(evt);
-    final int seq = findSeq(evt);
+    if (pos.annotationIndex != -1)
+    {
+      // JvOptionPane.showInternalMessageDialog(Desktop.desktop,
+      // MessageManager.getString(
+      // "label.cannot_edit_annotations_in_wrapped_view"),
+      // MessageManager.getString("label.wrapped_view_no_edit"),
+      // JvOptionPane.WARNING_MESSAGE);
+      return;
+    }
+
+    final int res = pos.column;
+    final int seq = pos.seqIndex;
     oldSeq = seq;
     updateOverviewAndStructs = false;
 
     startWrapBlock = wrappedBlock;
 
-    if (av.getWrapAlignment() && seq > av.getAlignment().getHeight())
-    {
-      JvOptionPane.showInternalMessageDialog(Desktop.desktop,
-              MessageManager.getString(
-                      "label.cannot_edit_annotations_in_wrapped_view"),
-              MessageManager.getString("label.wrapped_view_no_edit"),
-              JvOptionPane.WARNING_MESSAGE);
-      return;
-    }
-
     if (seq < 0 || res < 0)
     {
       return;
@@ -1932,7 +1907,7 @@ public class SeqPanel extends JPanel
 
     if (evt.isPopupTrigger()) // Mac: mousePressed
     {
-      showPopupMenu(evt);
+      showPopupMenu(evt, pos);
       return;
     }
 
@@ -1948,8 +1923,8 @@ public class SeqPanel extends JPanel
 
     if (av.cursorMode)
     {
-      seqCanvas.cursorX = findColumn(evt);
-      seqCanvas.cursorY = findSeq(evt);
+      seqCanvas.cursorX = res;
+      seqCanvas.cursorY = seq;
       seqCanvas.repaint();
       return;
     }
@@ -2007,15 +1982,14 @@ public class SeqPanel extends JPanel
 
   /**
    * Build and show a pop-up menu at the right-click mouse position
-   * 
+   *
    * @param evt
-   * @param res
-   * @param sequences
+   * @param pos
    */
-  void showPopupMenu(MouseEvent evt)
+  void showPopupMenu(MouseEvent evt, MousePos pos)
   {
-    final int column = findColumn(evt);
-    final int seq = findSeq(evt);
+    final int column = pos.column;
+    final int seq = pos.seqIndex;
     SequenceI sequence = av.getAlignment().getSequenceAt(seq);
     List<SequenceFeature> features = ap.getFeatureRenderer()
             .findFeaturesAtColumn(sequence, column + 1);
@@ -2083,8 +2057,15 @@ public class SeqPanel extends JPanel
    */
   public void doMouseDraggedDefineMode(MouseEvent evt)
   {
-    int res = findColumn(evt);
-    int y = findSeq(evt);
+    MousePos pos = findMousePosition(evt);
+    if (pos.annotationIndex != -1)
+    {
+      // mouse is over annotation in wrapped mode
+      return;
+    }
+
+    int res = pos.column;
+    int y = pos.seqIndex;
 
     if (wrappedBlock != startWrapBlock)
     {