Merge branch 'bug/JAL-2034contextchange' into develop
authorJim Procter <jprocter@issues.jalview.org>
Mon, 29 May 2017 16:38:34 +0000 (17:38 +0100)
committerJim Procter <jprocter@issues.jalview.org>
Mon, 29 May 2017 16:38:34 +0000 (17:38 +0100)
1  2 
src/jalview/appletgui/SeqPanel.java
src/jalview/gui/SeqPanel.java

@@@ -39,7 -39,6 +39,7 @@@ import jalview.structure.SelectionSourc
  import jalview.structure.SequenceListener;
  import jalview.structure.StructureSelectionManager;
  import jalview.structure.VamsasSource;
 +import jalview.util.Comparison;
  import jalview.util.MappingUtils;
  import jalview.util.MessageManager;
  import jalview.viewmodel.AlignmentViewport;
@@@ -228,7 -227,7 +228,7 @@@ public class SeqPanel extends Panel imp
      endEditing();
      if (av.getWrapAlignment())
      {
 -      ap.scrollToWrappedVisible(seqCanvas.cursorX);
 +      av.getRanges().scrollToWrappedVisible(seqCanvas.cursorX);
      }
      else
      {
        HiddenColumns hidden = av.getAlignment().getHiddenColumns();
        while (seqCanvas.cursorY < ranges.getStartSeq())
        {
 -        ap.scrollUp(true);
 +        ranges.scrollUp(true);
        }
        while (seqCanvas.cursorY > ranges.getEndSeq())
        {
 -        ap.scrollUp(false);
 +        ranges.scrollUp(false);
        }
        while (seqCanvas.cursorX < hidden.adjustForHiddenColumns(ranges
                .getStartRes()))
        {
  
 -        if (!ap.scrollRight(false))
 +        if (!ranges.scrollRight(false))
          {
            break;
          }
        while (seqCanvas.cursorX > hidden.adjustForHiddenColumns(ranges
                .getEndRes()))
        {
 -        if (!ap.scrollRight(true))
 +        if (!ranges.scrollRight(true))
          {
            break;
          }
     * 
     * @param sequence
     *          aligned sequence object
 -   * @param res
 +   * @param column
     *          alignment column
     * @param seq
     *          index of sequence in alignment
 -   * @return position of res in sequence
 +   * @return position of column in sequence or -1 if at gap
     */
 -  void setStatusMessage(SequenceI sequence, int res, int seq)
 +  void setStatusMessage(SequenceI sequence, int column, int seq)
    {
      // TODO remove duplication of identical gui method
      StringBuilder text = new StringBuilder(32);
      /*
       * 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);
      int pos = -1;
      if (residue != null)
      {
 -      pos = sequence.findPosition(res);
 +      pos = sequence.findPosition(column);
        text.append(" (").append(Integer.toString(pos)).append(")");
      }
  
    @Override
    public void mouseReleased(MouseEvent evt)
    {
+     boolean didDrag = mouseDragging; // did we come here after a drag
      mouseDragging = false;
      mouseWheelPressed = false;
  
      if (!editingSeqs)
      {
-       doMouseReleasedDefineMode(evt);
+       doMouseReleasedDefineMode(evt, didDrag);
        return;
      }
  
    {
      if (av.isFollowHighlight())
      {
 +      // don't allow highlight of protein/cDNA to also scroll a complementary
 +      // panel,as this sets up a feedback loop (scrolling panel 1 causes moused
 +      // over residue to change abruptly, causing highlighted residue in panel 2
 +      // to change, causing a scroll in panel 1 etc)
 +      ap.setToScrollComplementPanel(false);
        if (ap.scrollToPosition(results, true))
        {
          ap.alignFrame.repaint();
        }
 +      ap.setToScrollComplementPanel(true);
      }
      setStatusMessage(results);
      seqCanvas.highlightSearchResults(results);
    @Override
    public void mouseMoved(MouseEvent evt)
    {
 -    int res = findRes(evt);
 +    final int column = findRes(evt);
      int seq = findSeq(evt);
  
 -    if (seq >= av.getAlignment().getHeight() || seq < 0 || res < 0)
 +    if (seq >= av.getAlignment().getHeight() || seq < 0 || column < 0)
      {
        if (tooltip != null)
        {
      }
  
      SequenceI sequence = av.getAlignment().getSequenceAt(seq);
 -    if (res > sequence.getLength())
 +    if (column > sequence.getLength())
      {
        if (tooltip != null)
        {
        return;
      }
  
 -    int respos = sequence.findPosition(res);
 -    if (ssm != null)
 +    final char ch = sequence.getCharAt(column);
 +    int respos = Comparison.isGap(ch) ? -1 : sequence.findPosition(column);
 +
 +    if (ssm != null && respos != -1)
      {
 -      mouseOverSequence(sequence, res, respos);
 +      mouseOverSequence(sequence, column, respos);
      }
  
      StringBuilder text = new StringBuilder();
              .append(" ID: ").append(sequence.getName());
  
      String obj = null;
 -    final String ch = String.valueOf(sequence.getCharAt(res));
 -    if (av.getAlignment().isNucleotide())
 +    if (respos != -1)
      {
 -      obj = ResidueProperties.nucleotideName.get(ch);
 -      if (obj != null)
 +      if (av.getAlignment().isNucleotide())
        {
 -        text.append(" Nucleotide: ").append(obj);
 +        obj = ResidueProperties.nucleotideName.get(ch);
 +        if (obj != null)
 +        {
 +          text.append(" Nucleotide: ").append(obj);
 +        }
 +      }
 +      else
 +      {
 +        obj = (ch == 'x' || ch == 'X') ? "X" : ResidueProperties.aa2Triplet
 +                .get(String.valueOf(ch));
 +        if (obj != null)
 +        {
 +          text.append(" Residue: ").append(obj);
 +        }
        }
 -    }
 -    else
 -    {
 -      obj = "X".equalsIgnoreCase(ch) ? "X" : ResidueProperties.aa2Triplet
 -              .get(ch);
        if (obj != null)
        {
 -        text.append(" Residue: ").append(obj);
 +        text.append(" (").append(Integer.toString(respos)).append(")");
        }
      }
  
 -    if (obj != null)
 -    {
 -      text.append(" (").append(Integer.toString(respos)).append(")");
 -    }
 -
      ap.alignFrame.statusBar.setText(text.toString());
  
      StringBuilder tooltipText = new StringBuilder();
      {
        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"))
        }
      }
  
 -    // use aa to see if the mouse pointer is on a
 -    SequenceFeature[] allFeatures = findFeaturesAtRes(sequence,
 -            sequence.findPosition(res));
 -
 -    int index = 0;
 -    while (index < allFeatures.length)
 +    /*
 +     * add feature details to tooltip if over one or more features
 +     */
 +    if (respos != -1)
      {
 -      SequenceFeature sf = allFeatures[index];
 -
 -      tooltipText.append(sf.getType() + " " + sf.begin + ":" + sf.end);
 +      SequenceFeature[] allFeatures = findFeaturesAtRes(sequence,
 +              sequence.findPosition(column));
  
 -      if (sf.getDescription() != null)
 +      int index = 0;
 +      while (index < allFeatures.length)
        {
 -        tooltipText.append(" " + sf.getDescription());
 -      }
 +        SequenceFeature sf = allFeatures[index];
  
 -      if (sf.getValue("status") != null)
 -      {
 -        String status = sf.getValue("status").toString();
 -        if (status.length() > 0)
 +        tooltipText.append(sf.getType() + " " + sf.begin + ":" + sf.end);
 +
 +        if (sf.getDescription() != null)
          {
 -          tooltipText.append(" (" + sf.getValue("status") + ")");
 +          tooltipText.append(" " + sf.getDescription());
          }
 -      }
 -      tooltipText.append("\n");
  
 -      index++;
 +        if (sf.getValue("status") != null)
 +        {
 +          String status = sf.getValue("status").toString();
 +          if (status.length() > 0)
 +          {
 +            tooltipText.append(" (" + sf.getValue("status") + ")");
 +          }
 +        }
 +        tooltipText.append("\n");
 +
 +        index++;
 +      }
      }
  
      if (tooltip == null)
            {
              if (links == null)
              {
-               links = new Vector<String>();
+               links = new Vector<>();
              }
              for (int j = 0; j < allFeatures[i].links.size(); j++)
              {
      }
    }
  
-   public void doMouseReleasedDefineMode(MouseEvent evt)
+   public void doMouseReleasedDefineMode(MouseEvent evt, boolean afterDrag)
    {
      if (stretchGroup == null)
      {
      // but defer colourscheme update until hidden sequences are passed in
      boolean vischange = stretchGroup.recalcConservation(true);
      // here we rely on stretchGroup == av.getSelection()
-     needOverviewUpdate |= vischange && av.isSelectionDefinedGroup();
+     needOverviewUpdate |= vischange && av.isSelectionDefinedGroup()
+             && afterDrag;
      if (stretchGroup.cs != null)
      {
        stretchGroup.cs.alignmentChanged(stretchGroup,
            if (mouseDragging && evt.getY() < 0
                    && av.getRanges().getStartSeq() > 0)
            {
 -            running = ap.scrollUp(true);
 +            running = av.getRanges().scrollUp(true);
            }
  
            if (mouseDragging && evt.getY() >= getSize().height
                    && av.getAlignment().getHeight() > av.getRanges()
                            .getEndSeq())
            {
 -            running = ap.scrollUp(false);
 +            running = av.getRanges().scrollUp(false);
            }
  
            if (mouseDragging && evt.getX() < 0)
            {
 -            running = ap.scrollRight(false);
 +            running = av.getRanges().scrollRight(false);
            }
  
            else if (mouseDragging && evt.getX() >= getSize().width)
            {
 -            running = ap.scrollRight(true);
 +            running = av.getRanges().scrollRight(true);
            }
          }
  
@@@ -389,12 -389,38 +389,12 @@@ public class SeqPanel extends JPanel im
      endEditing();
      if (av.getWrapAlignment())
      {
 -      ap.scrollToWrappedVisible(seqCanvas.cursorX);
 +      av.getRanges().scrollToWrappedVisible(seqCanvas.cursorX);
      }
      else
      {
 -      while (seqCanvas.cursorY < av.getRanges().getStartSeq())
 -      {
 -        ap.scrollUp(true);
 -      }
 -      while (seqCanvas.cursorY > av.getRanges().getEndSeq())
 -      {
 -        ap.scrollUp(false);
 -      }
 -      if (!av.getWrapAlignment())
 -      {
 -        HiddenColumns hidden = av.getAlignment().getHiddenColumns();
 -        while (seqCanvas.cursorX < hidden.adjustForHiddenColumns(av
 -                .getRanges().getStartRes()))
 -        {
 -          if (!ap.scrollRight(false))
 -          {
 -            break;
 -          }
 -        }
 -        while (seqCanvas.cursorX > hidden.adjustForHiddenColumns(av
 -                .getRanges().getEndRes()))
 -        {
 -          if (!ap.scrollRight(true))
 -          {
 -            break;
 -          }
 -        }
 -      }
 +      av.getRanges().scrollToVisible(seqCanvas.cursorX, seqCanvas.cursorY,
 +              av);
      }
      setStatusMessage(av.getAlignment().getSequenceAt(seqCanvas.cursorY),
              seqCanvas.cursorX, seqCanvas.cursorY);
    @Override
    public void mouseReleased(MouseEvent evt)
    {
+     boolean didDrag = mouseDragging; // did we come here after a drag
      mouseDragging = false;
      mouseWheelPressed = false;
  
  
      if (!editingSeqs)
      {
-       doMouseReleasedDefineMode(evt);
+       doMouseReleasedDefineMode(evt, didDrag);
        return;
      }
  
  
      if (av.isFollowHighlight())
      {
 -      /*
 -       * if scrollToPosition requires a scroll adjustment, this flag prevents
 -       * another scroll event being propagated back to the originator
 -       * 
 -       * @see AlignmentPanel#adjustmentValueChanged
 -       */
 -      ap.setDontScrollComplement(true);
 +      // don't allow highlight of protein/cDNA to also scroll a complementary
 +      // panel,as this sets up a feedback loop (scrolling panel 1 causes moused
 +      // over residue to change abruptly, causing highlighted residue in panel 2
 +      // to change, causing a scroll in panel 1 etc)
 +      ap.setToScrollComplementPanel(false);
        if (ap.scrollToPosition(results, false))
        {
          seqCanvas.revalidate();
        }
 +      ap.setToScrollComplementPanel(true);
      }
      setStatusMessage(results);
      seqCanvas.highlightSearchResults(results);
        }
      }
  
 -    if (av.isShowSequenceFeatures())
 +    if (av.isShowSequenceFeatures() && pos != -1)
      {
        List<SequenceFeature> features = ap.getFeatureRenderer()
                .findFeaturesAtRes(sequence.getDatasetSequence(), pos);
    /**
     * 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.
 +   * column position. Returns the calculated residue position in the sequence,
 +   * or -1 for a gapped column position.
     * 
     * @param sequence
     *          aligned sequence object
     *          alignment column
     * @param seq
     *          index of sequence in alignment
 -   * @return position of res in sequence
 +   * @return position of column in sequence or -1 if at a gap
     */
    int setStatusMessage(SequenceI sequence, final int column, int seq)
    {
      }
  
      int pos = -1;
 -    pos = sequence.findPosition(column);
      if (residue != null)
      {
 +      pos = sequence.findPosition(column);
        text.append(" (").append(Integer.toString(pos)).append(")");
      }
      ap.alignFrame.statusBar.setText(text.toString());
      {
        if (e.isShiftDown())
        {
 -        ap.scrollRight(true);
 +        av.getRanges().scrollRight(true);
  
        }
        else
        {
 -        ap.scrollUp(false);
 +        av.getRanges().scrollUp(false);
        }
      }
      else
      {
        if (e.isShiftDown())
        {
 -        ap.scrollRight(false);
 +        av.getRanges().scrollRight(false);
        }
        else
        {
 -        ap.scrollUp(true);
 +        av.getRanges().scrollUp(true);
        }
      }
      // TODO Update tooltip for new position.
      List<SequenceFeature> allFeatures = ap.getFeatureRenderer()
              .findFeaturesAtRes(sequence.getDatasetSequence(),
                      sequence.findPosition(res));
-     List<String> links = new ArrayList<String>();
+     List<String> links = new ArrayList<>();
      for (SequenceFeature sf : allFeatures)
      {
        if (sf.links != null)
    }
  
    /**
-    * DOCUMENT ME!
+    * Update the display after mouse up on a selection or group
     * 
     * @param evt
-    *          DOCUMENT ME!
+    *          mouse released event details
+    * @param afterDrag
+    *          true if this event is happening after a mouse drag (rather than a
+    *          mouse down)
     */
-   public void doMouseReleasedDefineMode(MouseEvent evt)
+   public void doMouseReleasedDefineMode(MouseEvent evt, boolean afterDrag)
    {
      if (stretchGroup == null)
      {
      // always do this - annotation has own state
      // but defer colourscheme update until hidden sequences are passed in
      boolean vischange = stretchGroup.recalcConservation(true);
-     needOverviewUpdate |= vischange && av.isSelectionDefinedGroup();
+     needOverviewUpdate |= vischange && av.isSelectionDefinedGroup()
+             && afterDrag;
      if (stretchGroup.cs != null)
      {
        stretchGroup.cs.alignmentChanged(stretchGroup,
            if (mouseDragging && (evt.getY() < 0)
                    && (av.getRanges().getStartSeq() > 0))
            {
 -            running = ap.scrollUp(true);
 +            running = av.getRanges().scrollUp(true);
            }
  
            if (mouseDragging && (evt.getY() >= getHeight())
                    && (av.getAlignment().getHeight() > av.getRanges()
                            .getEndSeq()))
            {
 -            running = ap.scrollUp(false);
 +            running = av.getRanges().scrollUp(false);
            }
  
            if (mouseDragging && (evt.getX() < 0))
            {
 -            running = ap.scrollRight(false);
 +            running = av.getRanges().scrollRight(false);
            }
            else if (mouseDragging && (evt.getX() >= getWidth()))
            {
 -            running = ap.scrollRight(true);
 +            running = av.getRanges().scrollRight(true);
            }
          }
  
          ap.getCalculationDialog().validateCalcTypes();
        }
  
-       // process further ?
-       if (!av.followSelection)
-       {
-         return;
-       }
+       return;
+     }
+     // process further ?
+     if (!av.followSelection)
+     {
+       return;
      }
  
      /*