Merge branch 'bug/JAL-2750' into develop
authorJim Procter <jprocter@issues.jalview.org>
Mon, 17 Dec 2018 17:04:56 +0000 (17:04 +0000)
committerJim Procter <jprocter@issues.jalview.org>
Mon, 17 Dec 2018 17:04:56 +0000 (17:04 +0000)
1  2 
src/jalview/datamodel/SequenceGroup.java
src/jalview/gui/ScalePanel.java

@@@ -30,7 -30,6 +30,7 @@@ import java.awt.Color
  import java.beans.PropertyChangeListener;
  import java.beans.PropertyChangeSupport;
  import java.util.ArrayList;
 +import java.util.Arrays;
  import java.util.List;
  import java.util.Map;
  
@@@ -102,11 -101,15 +102,15 @@@ public class SequenceGroup implements A
     */
    public ResidueShaderI cs;
  
-   // start column (base 0)
-   int startRes = 0;
+   /**
+    * start column (base 0)
+    */
+   private int startRes = 0;
  
-   // end column (base 0)
-   int endRes = 0;
+   /**
+    *  end column (base 0)
+    */
+   private int endRes = 0;
  
    public Color outlineColour = Color.black;
  
        displayBoxes = seqsel.displayBoxes;
        displayText = seqsel.displayText;
        colourText = seqsel.colourText;
+       
        startRes = seqsel.startRes;
        endRes = seqsel.endRes;
        cs = new ResidueShader((ResidueShader) seqsel.cs);
    /**
     * Set the first column selected by this group. Runs from 0<=i<N_cols
     * 
-    * @param i
+    * @param newStart
     */
-   public void setStartRes(int i)
+   public void setStartRes(int newStart)
    {
      int before = startRes;
-     startRes = i;
-     changeSupport.firePropertyChange(SEQ_GROUP_CHANGED, before, startRes);
+    startRes= Math.max(0,newStart); // sanity check for negative start column positions
+    changeSupport.firePropertyChange(SEQ_GROUP_CHANGED, before, startRes);
+     
    }
  
    /**
      {
        if (consensus.annotations[i] != null)
        {
 -        if (consensus.annotations[i].description.charAt(0) == '[')
 +        String desc = consensus.annotations[i].description;
 +        if (desc.length() > 1 && desc.charAt(0) == '[')
          {
 -          seqs.append(consensus.annotations[i].description.charAt(1));
 +          seqs.append(desc.charAt(1));
          }
          else
          {
    @Override
    public Iterable<AlignmentAnnotation> findAnnotation(String calcId)
    {
 -    List<AlignmentAnnotation> aa = new ArrayList<>();
 -    if (calcId == null)
 -    {
 -      return aa;
 -    }
 -    for (AlignmentAnnotation a : getAlignmentAnnotation())
 -    {
 -      if (calcId.equals(a.getCalcId()))
 -      {
 -        aa.add(a);
 -      }
 -    }
 -    return aa;
 +    return AlignmentAnnotation.findAnnotation(
 +            Arrays.asList(getAlignmentAnnotation()), calcId);
    }
  
    @Override
    public Iterable<AlignmentAnnotation> findAnnotations(SequenceI seq,
            String calcId, String label)
    {
 -    ArrayList<AlignmentAnnotation> aa = new ArrayList<>();
 -    for (AlignmentAnnotation ann : getAlignmentAnnotation())
 -    {
 -      if ((calcId == null || (ann.getCalcId() != null
 -              && ann.getCalcId().equals(calcId)))
 -              && (seq == null || (ann.sequenceRef != null
 -                      && ann.sequenceRef == seq))
 -              && (label == null
 -                      || (ann.label != null && ann.label.equals(label))))
 -      {
 -        aa.add(ann);
 -      }
 -    }
 -    return aa;
 +    return AlignmentAnnotation.findAnnotations(
 +            Arrays.asList(getAlignmentAnnotation()), seq, calcId, label);
    }
  
    /**
     */
    public boolean hasAnnotation(String calcId)
    {
 -    if (calcId != null && !"".equals(calcId))
 -    {
 -      for (AlignmentAnnotation a : getAlignmentAnnotation())
 -      {
 -        if (a.getCalcId() == calcId)
 -        {
 -          return true;
 -        }
 -      }
 -    }
 -    return false;
 +    return AlignmentAnnotation
 +            .hasAnnotation(Arrays.asList(getAlignmentAnnotation()), calcId);
    }
  
    /**
@@@ -42,7 -42,6 +42,7 @@@ import java.awt.event.MouseEvent
  import java.awt.event.MouseListener;
  import java.awt.event.MouseMotionListener;
  import java.beans.PropertyChangeEvent;
 +import java.util.Iterator;
  import java.util.List;
  
  import javax.swing.JMenuItem;
@@@ -113,7 -112,7 +113,7 @@@ public class ScalePanel extends JPane
  
      if (av.hasHiddenColumns())
      {
 -      x = av.getAlignment().getHiddenColumns().adjustForHiddenColumns(x);
 +      x = av.getAlignment().getHiddenColumns().visibleToAbsoluteColumn(x);
      }
  
      if (x >= av.getAlignment().getWidth())
          {
            av.showColumn(reveal[0]);
            reveal = null;
 -          ap.paintAlignment(true);
 +          ap.paintAlignment(true, true);
            av.sendSelection();
          }
        });
        pop.add(item);
  
 -      if (av.getAlignment().getHiddenColumns().hasHiddenColumns())
 +      if (av.getAlignment().getHiddenColumns().hasMultiHiddenColumnRegions())
        {
          item = new JMenuItem(MessageManager.getString("action.reveal_all"));
          item.addActionListener(new ActionListener()
            {
              av.showAllHiddenColumns();
              reveal = null;
 -            ap.paintAlignment(true);
 +            ap.paintAlignment(true, true);
              av.sendSelection();
            }
          });
              av.setSelectionGroup(null);
            }
  
 -          ap.paintAlignment(true);
 +          ap.paintAlignment(true, true);
            av.sendSelection();
          }
        });
        sg.setEndRes(max);
      }
      av.setSelectionGroup(sg);
 -    ap.paintAlignment(false);
 +    ap.paintAlignment(false, false);
      av.sendSelection();
    }
  
    {
      mouseDragging = false;
  
-     int res = (evt.getX() / av.getCharWidth())
+     int xCords = Math.max(0, evt.getX()); // prevent negative X coordinates
+     int res = (xCords / av.getCharWidth())
              + av.getRanges().getStartRes();
  
      if (av.hasHiddenColumns())
      {
        res = av.getAlignment().getHiddenColumns()
 -              .adjustForHiddenColumns(res);
 +              .visibleToAbsoluteColumn(res);
      }
  
      if (res >= av.getAlignment().getWidth())
        }
        else
        {
 -        ap.paintAlignment(false);
 +        ap.paintAlignment(false, false);
        }
        return;
      }
        }
      }
      stretchingGroup = false;
 -    ap.paintAlignment(false);
 +    ap.paintAlignment(false, false);
      av.sendSelection();
    }
  
      int res = (evt.getX() / av.getCharWidth())
              + av.getRanges().getStartRes();
      res = Math.max(0, res);
 -    res = hidden.adjustForHiddenColumns(res);
 +    res = hidden.visibleToAbsoluteColumn(res);
      res = Math.min(res, av.getAlignment().getWidth() - 1);
      min = Math.min(res, min);
      max = Math.max(res, max);
      {
        stretchingGroup = true;
        cs.stretchGroup(res, sg, min, max);
 -      ap.paintAlignment(false);
 +      ap.paintAlignment(false, false);
      }
    }
  
      reveal = av.getAlignment().getHiddenColumns()
              .getRegionWithEdgeAtRes(res);
  
 -    res = av.getAlignment().getHiddenColumns().adjustForHiddenColumns(res);
 +    res = av.getAlignment().getHiddenColumns().visibleToAbsoluteColumn(res);
  
      ToolTipManager.sharedInstance().registerComponent(this);
      this.setToolTipText(
    @Override
    public void paintComponent(Graphics g)
    {
 +    super.paintComponent(g);
 +
      /*
       * shouldn't get called in wrapped mode as the scale above is
       * drawn instead by SeqCanvas.drawNorthScale
          {
            if (hidden.isVisible(sel))
            {
 -            sel = hidden.findColumnPosition(sel);
 +            sel = hidden.absoluteToVisibleColumn(sel);
            }
            else
            {
  
        if (av.getShowHiddenMarkers())
        {
 -        List<Integer> positions = hidden.findHiddenRegionPositions();
 -        for (int pos : positions)
 +        Iterator<Integer> it = hidden.getStartRegionIterator(startx,
 +                startx + widthx + 1);
 +        while (it.hasNext())
          {
 -          res = pos - startx;
 -
 -          if (res < 0 || res > widthx)
 -          {
 -            continue;
 -          }
 +          res = it.next() - startx;
  
            gg.fillPolygon(
                    new int[]
 -                  { -1 + res * avCharWidth - avCharHeight / 4,
 -                      -1 + res * avCharWidth + avCharHeight / 4,
 -                      -1 + res * avCharWidth },
 -                  new int[]
 -                  { y, y, y + 2 * yOf }, 3);
 +          { -1 + res * avCharWidth - avCharHeight / 4,
 +              -1 + res * avCharWidth + avCharHeight / 4,
 +              -1 + res * avCharWidth }, new int[]
 +          { y, y, y + 2 * yOf }, 3);
          }
        }
      }
      // Here we only want to fastpaint on a scroll, with resize using a normal
      // paint, so scroll events are identified as changes to the horizontal or
      // vertical start value.
 -    if (evt.getPropertyName().equals(ViewportRanges.STARTRES))
 +    if (evt.getPropertyName().equals(ViewportRanges.STARTRES)
 +            || evt.getPropertyName().equals(ViewportRanges.STARTRESANDSEQ)
 +            || evt.getPropertyName().equals(ViewportRanges.MOVE_VIEWPORT))
      {
        // scroll event, repaint panel
 -      repaint();
 +      
 +      // Call repaint on alignment panel so that repaints from other alignment
 +    // panel components can be aggregated. Otherwise performance of the overview
 +    // window and others may be adversely affected.
 +      av.getAlignPanel().repaint();
      }
    }