JAL-1858 'fastPaint' of minimal region for highlights; todo: hidden
authorgmungoc <g.m.carstairs@dundee.ac.uk>
Fri, 23 Jun 2017 12:13:02 +0000 (13:13 +0100)
committergmungoc <g.m.carstairs@dundee.ac.uk>
Fri, 23 Jun 2017 12:13:02 +0000 (13:13 +0100)
columns

src/jalview/gui/SeqCanvas.java

index a74db48..ca1c64a 100755 (executable)
@@ -290,29 +290,29 @@ public class SeqCanvas extends JComponent implements ViewportListenerI
             imgHeight, -horizontal * charWidth, -vertical * charHeight);
 
     ViewportRanges ranges = av.getRanges();
-    int sr = ranges.getStartRes();
-    int er = ranges.getEndRes();
-    int ss = ranges.getStartSeq();
-    int es = ranges.getEndSeq();
+    int startRes = ranges.getStartRes();
+    int endRes = ranges.getEndRes();
+    int startSeq = ranges.getStartSeq();
+    int endSeq = ranges.getEndSeq();
     int transX = 0;
     int transY = 0;
 
     if (horizontal > 0) // scrollbar pulled right, image to the left
     {
-      transX = (er - sr - horizontal) * charWidth;
-      sr = er - horizontal;
+      transX = (endRes - startRes - horizontal) * charWidth;
+      startRes = endRes - horizontal;
     }
     else if (horizontal < 0)
     {
-      er = sr - horizontal;
+      endRes = startRes - horizontal;
     }
     else if (vertical > 0) // scroll down
     {
-      ss = es - vertical;
+      startSeq = endSeq - vertical;
 
-      if (ss < ranges.getStartSeq())
+      if (startSeq < ranges.getStartSeq())
       { // ie scrolling too fast, more than a page at a time
-        ss = ranges.getStartSeq();
+        startSeq = ranges.getStartSeq();
       }
       else
       {
@@ -321,32 +321,22 @@ public class SeqCanvas extends JComponent implements ViewportListenerI
     }
     else if (vertical < 0)
     {
-      es = ss - vertical;
+      endSeq = startSeq - vertical;
 
-      if (es > ranges.getEndSeq())
+      if (endSeq > ranges.getEndSeq())
       {
-        es = ranges.getEndSeq();
+        endSeq = ranges.getEndSeq();
       }
     }
 
     gg.translate(transX, transY);
-    drawPanel(gg, sr, er, ss, es, 0);
+    drawPanel(gg, startRes, endRes, startSeq, endSeq, 0);
     gg.translate(-transX, -transY);
 
     repaint();
     fastpainting = false;
   }
 
-  /**
-   * Definitions of startx and endx (hopefully): SMJS This is what I'm working
-   * towards! startx is the first residue (starting at 0) to display. endx is
-   * the last residue to display (starting at 0). starty is the first sequence
-   * to display (starting at 0). endy is the last sequence to display (starting
-   * at 0). NOTE 1: The av limits are set in setFont in this class and in the
-   * adjustment listener in SeqPanel when the scrollbars move.
-   */
-
-  // Set this to false to force a full panel paint
   @Override
   public void paintComponent(Graphics g)
   {
@@ -774,11 +764,13 @@ public class SeqCanvas extends JComponent implements ViewportListenerI
                 + ((i - startSeq) * charHeight), false);
       }
 
-      // / Highlight search Results once all sequences have been drawn
-      // ////////////////////////////////////////////////////////
+      /*
+       * highlight search Results once sequence has been drawn
+       */
       if (av.hasSearchResults())
       {
-        int[] visibleResults = av.getSearchResults().getResults(nextSeq,
+        SearchResultsI searchResults = av.getSearchResults();
+        int[] visibleResults = searchResults.getResults(nextSeq,
                 startRes, endRes);
         if (visibleResults != null)
         {
@@ -996,18 +988,104 @@ public class SeqCanvas extends JComponent implements ViewportListenerI
   }
 
   /**
-   * DOCUMENT ME!
+   * Highlights search results in the visible region by rendering as white text
+   * on a black background. Any previous highlighting is removed.
    * 
    * @param results
-   *          DOCUMENT ME!
    */
   public void highlightSearchResults(SearchResultsI results)
   {
-    img = null;
+    updateViewport();
+    fastpainting = true;
+    fastPaint = true;
+
+    /*
+     * calculate the minimal rectangle to draw that includes 
+     * both the new and any existing search results
+     */
+    SearchResultsI previous = av.getSearchResults();
+    int firstSeq = Integer.MAX_VALUE;
+    int lastSeq = -1;
+    int firstCol = Integer.MAX_VALUE;
+    int lastCol = -1;
+    boolean matchFound = false;
+
+    ViewportRanges ranges = av.getRanges();
+    for (int seqNo = ranges.getStartSeq(); seqNo <= ranges
+            .getEndSeq(); seqNo++)
+    {
+      SequenceI seq = av.getAlignment().getSequenceAt(seqNo);
+      if (previous != null)
+      {
+        /*
+         * find the bounding rectangle enclosing last search results
+         */
+        int[] visibleResults = previous.getResults(seq,
+                ranges.getStartRes(), ranges.getEndRes());
+        if (visibleResults != null)
+        {
+          int firstMatchedColumn = visibleResults[0];
+          int lastMatchedColumn = visibleResults[visibleResults.length - 1];
+          if (firstMatchedColumn <= ranges.getEndRes()
+                  && lastMatchedColumn >= ranges.getStartRes())
+          {
+            /*
+             * a previous search results match in the visible region
+             * remember the first and last sequence matched, and the first
+             * and last visible columns in the matched positions
+             */
+            matchFound = true;
+            firstSeq = Math.min(firstSeq, seqNo);
+            lastSeq = Math.max(lastSeq, seqNo);
+            firstMatchedColumn = Math.max(firstMatchedColumn,
+                    ranges.getStartRes());
+            lastMatchedColumn = Math.min(lastMatchedColumn,
+                    ranges.getEndRes());
+            firstCol = Math.min(firstCol, firstMatchedColumn);
+            lastCol = Math.max(lastCol, lastMatchedColumn);
+          }
+        }
+      }
+
+      /*
+       * and repeat for the new search results
+       */
+      int[] visibleResults = results.getResults(seq, ranges.getStartRes(),
+              ranges.getEndRes());
+      if (visibleResults != null)
+      {
+        int firstMatchedColumn = visibleResults[0];
+        int lastMatchedColumn = visibleResults[visibleResults.length - 1];
+        if (firstMatchedColumn <= ranges.getEndRes()
+                && lastMatchedColumn >= ranges.getStartRes())
+        {
+          matchFound = true;
+          firstSeq = Math.min(firstSeq, seqNo);
+          lastSeq = Math.max(lastSeq, seqNo);
+          firstMatchedColumn = Math.max(firstMatchedColumn,
+                  ranges.getStartRes());
+          lastMatchedColumn = Math.min(lastMatchedColumn,
+                  ranges.getEndRes());
+          firstCol = Math.min(firstCol, firstMatchedColumn);
+          lastCol = Math.max(lastCol, lastMatchedColumn);
+        }
+      }
+    }
 
     av.setSearchResults(results);
 
-    repaint();
+    if (matchFound)
+    {
+      int transX = (firstCol - ranges.getStartRes()) * av.getCharWidth();
+      int transY = (firstSeq - ranges.getStartSeq()) * av.getCharHeight();
+      gg.translate(transX, transY);
+      drawPanel(gg, firstCol, lastCol, firstSeq, lastSeq, 0);
+      gg.translate(-transX, -transY);
+
+      repaint();
+    }
+
+    fastpainting = false; // todo in finally block?
   }
 
   @Override