Remove redundancy in Eclipse
[jalview.git] / src / jalview / gui / SeqCanvas.java
1 /*\r
2  * Jalview - A Sequence Alignment Editor and Viewer\r
3  * Copyright (C) 2005 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle\r
4  *\r
5  * This program is free software; you can redistribute it and/or\r
6  * modify it under the terms of the GNU General Public License\r
7  * as published by the Free Software Foundation; either version 2\r
8  * of the License, or (at your option) any later version.\r
9  *\r
10  * This program is distributed in the hope that it will be useful,\r
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
13  * GNU General Public License for more details.\r
14  *\r
15  * You should have received a copy of the GNU General Public License\r
16  * along with this program; if not, write to the Free Software\r
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA\r
18  */\r
19 package jalview.gui;\r
20 \r
21 import jalview.datamodel.*;\r
22 \r
23 import java.awt.*;\r
24 import java.awt.image.*;\r
25 \r
26 import javax.swing.*;\r
27 \r
28 \r
29 /**\r
30  * DOCUMENT ME!\r
31  *\r
32  * @author $author$\r
33  * @version $Revision$\r
34  */\r
35 public class SeqCanvas extends JComponent\r
36 {\r
37     FeatureRenderer fr;\r
38     SequenceRenderer sr;\r
39     BufferedImage img;\r
40     Graphics2D gg;\r
41     int imgWidth;\r
42     int imgHeight;\r
43     AlignViewport av;\r
44     boolean displaySearch = false;\r
45     int[] searchResults = null;\r
46     boolean fastPaint = false;\r
47     int LABEL_WEST;\r
48     int LABEL_EAST;\r
49 \r
50     boolean isOverview = false;\r
51 \r
52     /**\r
53      * Creates a new SeqCanvas object.\r
54      *\r
55      * @param av DOCUMENT ME!\r
56      */\r
57     public SeqCanvas(AlignViewport av)\r
58     {\r
59         this.av = av;\r
60         fr = new FeatureRenderer(av);\r
61         sr = new SequenceRenderer(av);\r
62         setLayout(new BorderLayout());\r
63         PaintRefresher.Register(this, av.alignment);\r
64         setBackground(Color.white);\r
65     }\r
66 \r
67     /**\r
68      * DOCUMENT ME!\r
69      *\r
70      * @param g DOCUMENT ME!\r
71      * @param startx DOCUMENT ME!\r
72      * @param endx DOCUMENT ME!\r
73      * @param ypos DOCUMENT ME!\r
74      */\r
75     void drawNorthScale(Graphics g, int startx, int endx, int ypos)\r
76     {\r
77         int scalestartx = startx - (startx % 10) + 10;\r
78 \r
79         g.setColor(Color.black);\r
80 \r
81         // NORTH SCALE\r
82         for (int i = scalestartx; i < endx; i += 10)\r
83         {\r
84             String string = String.valueOf(i);\r
85             g.drawString(string, (i - startx - 1) * av.charWidth,\r
86                 ypos - (av.charHeight / 2));\r
87 \r
88             g.drawLine(((i - startx - 1) * av.charWidth) + (av.charWidth / 2),\r
89                 (ypos + 2) - (av.charHeight / 2),\r
90                 ((i - startx - 1) * av.charWidth) + (av.charWidth / 2), ypos -\r
91                 2);\r
92         }\r
93     }\r
94 \r
95     /**\r
96      * DOCUMENT ME!\r
97      *\r
98      * @param g DOCUMENT ME!\r
99      * @param startx DOCUMENT ME!\r
100      * @param endx DOCUMENT ME!\r
101      * @param ypos DOCUMENT ME!\r
102      */\r
103     void drawWestScale(Graphics g, int startx, int endx, int ypos)\r
104     {\r
105         FontMetrics fm = getFontMetrics(av.getFont());\r
106         ypos += av.charHeight;\r
107 \r
108         // EAST SCALE\r
109         for (int i = 0; i < av.alignment.getHeight(); i++)\r
110         {\r
111             SequenceI seq = av.alignment.getSequenceAt(i);\r
112             int index = startx;\r
113             int value = -1;\r
114 \r
115             while (index < endx)\r
116             {\r
117                 if (jalview.util.Comparison.isGap(seq.getCharAt(index)))\r
118                 {\r
119                     index++;\r
120 \r
121                     continue;\r
122                 }\r
123 \r
124                 value = av.alignment.getSequenceAt(i).findPosition(index);\r
125 \r
126                 break;\r
127             }\r
128 \r
129             if (value != -1)\r
130             {\r
131                 int x = LABEL_WEST - fm.stringWidth(String.valueOf(value))-av.charWidth/2;\r
132                 g.drawString(value + "", x,\r
133                     (ypos + (i * av.charHeight)) - (av.charHeight / 5));\r
134             }\r
135         }\r
136     }\r
137 \r
138     /**\r
139      * DOCUMENT ME!\r
140      *\r
141      * @param g DOCUMENT ME!\r
142      * @param startx DOCUMENT ME!\r
143      * @param endx DOCUMENT ME!\r
144      * @param ypos DOCUMENT ME!\r
145      */\r
146     void drawEastScale(Graphics g, int startx, int endx, int ypos)\r
147     {\r
148         ypos += av.charHeight;\r
149 \r
150         // EAST SCALE\r
151         for (int i = 0; i < av.alignment.getHeight(); i++)\r
152         {\r
153             SequenceI seq = av.alignment.getSequenceAt(i);\r
154             int index = endx;\r
155             int value = -1;\r
156 \r
157             while (index > startx)\r
158             {\r
159                 if (jalview.util.Comparison.isGap(seq.getCharAt(index)))\r
160                 {\r
161                     index--;\r
162 \r
163                     continue;\r
164                 }\r
165 \r
166                 value = av.alignment.getSequenceAt(i).findPosition(index);\r
167 \r
168                 break;\r
169             }\r
170 \r
171             if (value != -1)\r
172             {\r
173                 g.drawString(String.valueOf(value), av.charWidth/2,\r
174                     (ypos + (i * av.charHeight)) - (av.charHeight / 5));\r
175             }\r
176         }\r
177     }\r
178 \r
179     /**\r
180      * DOCUMENT ME!\r
181      *\r
182      * @param horizontal DOCUMENT ME!\r
183      * @param vertical DOCUMENT ME!\r
184      */\r
185     public void fastPaint(int horizontal, int vertical)\r
186     {\r
187         if (gg == null)\r
188         {\r
189             return;\r
190         }\r
191 \r
192         gg.copyArea(horizontal * av.charWidth,\r
193                     vertical * av.charHeight,\r
194                     imgWidth,\r
195                     imgHeight,\r
196                     -horizontal * av.charWidth,\r
197                     -vertical * av.charHeight);\r
198 \r
199         int sr = av.startRes;\r
200         int er = av.endRes;\r
201         int ss = av.startSeq;\r
202         int es = av.endSeq;\r
203         int transX = 0;\r
204         int transY = 0;\r
205 \r
206         if (horizontal > 0) // scrollbar pulled right, image to the left\r
207         {\r
208             er ++;\r
209             transX = (er - sr - horizontal) * av.charWidth;\r
210             sr = er - horizontal;\r
211         }\r
212         else if (horizontal < 0)\r
213         {\r
214             er = sr - horizontal-1;\r
215         }\r
216         else if (vertical > 0) // scroll down\r
217         {\r
218             ss = es - vertical;\r
219 \r
220             if (ss < av.startSeq)\r
221             { // ie scrolling too fast, more than a page at a time\r
222                 ss = av.startSeq;\r
223             }\r
224             else\r
225             {\r
226                 transY = imgHeight - (vertical * av.charHeight);\r
227             }\r
228         }\r
229         else if (vertical < 0)\r
230         {\r
231             es = ss - vertical;\r
232 \r
233             if (es > av.endSeq)\r
234             {\r
235                 es = av.endSeq;\r
236             }\r
237         }\r
238 \r
239         gg.translate(transX, transY);\r
240         drawPanel(gg, sr, er, ss, es, sr, ss, 0);\r
241         gg.translate(-transX, -transY);\r
242 \r
243         fastPaint = true;\r
244         repaint();\r
245     }\r
246 \r
247     /**\r
248      * Definitions of startx and endx (hopefully):\r
249      * SMJS This is what I'm working towards!\r
250      *   startx is the first residue (starting at 0) to display.\r
251      *   endx   is the last residue to display (starting at 0).\r
252      *   starty is the first sequence to display (starting at 0).\r
253      *   endy   is the last sequence to display (starting at 0).\r
254      * NOTE 1: The av limits are set in setFont in this class and\r
255      * in the adjustment listener in SeqPanel when the scrollbars move.\r
256      */\r
257 \r
258     // Set this to false to force a full panel paint\r
259     public void paintComponent(Graphics g)\r
260     {\r
261         sr.renderGaps(av.renderGaps);\r
262 \r
263         if ((img != null) &&\r
264                 (fastPaint || (getWidth() != g.getClipBounds().width) ||\r
265                 (getHeight() != g.getClipBounds().height)))\r
266         {\r
267             g.drawImage(img, 0, 0, this);\r
268             fastPaint = false;\r
269 \r
270             return;\r
271         }\r
272 \r
273         // this draws the whole of the alignment\r
274         imgWidth = getWidth();\r
275         imgHeight = getHeight();\r
276 \r
277         imgWidth -= (imgWidth % av.charWidth);\r
278         imgHeight -= (imgHeight % av.charHeight);\r
279 \r
280         if ((imgWidth < 1) || (imgHeight < 1))\r
281         {\r
282             return;\r
283         }\r
284 \r
285 \r
286         img = new BufferedImage(imgWidth, imgHeight, BufferedImage.TYPE_INT_RGB);\r
287         gg = (Graphics2D) img.getGraphics();\r
288         gg.setFont(av.getFont());\r
289         gg.setRenderingHint(RenderingHints.KEY_ANTIALIASING,\r
290           RenderingHints.VALUE_ANTIALIAS_ON);\r
291 \r
292         gg.setColor(Color.white);\r
293         gg.fillRect(0, 0, imgWidth, imgHeight);\r
294 \r
295 \r
296         if (av.getWrapAlignment())\r
297         {\r
298             drawWrappedPanel(gg, getWidth(), getHeight(), av.startRes);\r
299         }\r
300         else\r
301         {\r
302             drawPanel(gg, av.startRes, av.endRes, av.startSeq, av.endSeq,\r
303                 av.startRes, av.startSeq, 0);\r
304         }\r
305 \r
306         g.drawImage(img, 0, 0, this);\r
307     }\r
308 \r
309     /**\r
310      * DOCUMENT ME!\r
311      *\r
312      * @param cwidth DOCUMENT ME!\r
313      *\r
314      * @return DOCUMENT ME!\r
315      */\r
316     public int getWrappedCanvasWidth(int cwidth)\r
317     {\r
318         FontMetrics fm = getFontMetrics(av.getFont());\r
319 \r
320         LABEL_EAST = 0;\r
321         LABEL_WEST = 0;\r
322 \r
323         if (av.scaleRightWrapped)\r
324         {\r
325             LABEL_EAST = fm.stringWidth(getMask()+"0");\r
326         }\r
327 \r
328         if (av.scaleLeftWrapped)\r
329         {\r
330             LABEL_WEST = fm.stringWidth(getMask());\r
331         }\r
332 \r
333         return (cwidth - LABEL_EAST - LABEL_WEST) / av.charWidth;\r
334     }\r
335 \r
336 \r
337     /**\r
338      * Generates a string of zeroes.\r
339      * @return String\r
340      */\r
341     String getMask()\r
342     {\r
343       String mask = "0";\r
344       for (int i = av.alignment.getWidth(); i > 0; i /= 10)\r
345       {\r
346         mask += "0";\r
347       }\r
348       return mask;\r
349     }\r
350 \r
351     /**\r
352      * DOCUMENT ME!\r
353      *\r
354      * @param g DOCUMENT ME!\r
355      * @param canvasWidth DOCUMENT ME!\r
356      * @param canvasHeight DOCUMENT ME!\r
357      * @param startRes DOCUMENT ME!\r
358      */\r
359     public void drawWrappedPanel(Graphics g, int canvasWidth, int canvasHeight,\r
360         int startRes)\r
361     {\r
362 \r
363         AlignmentI al = av.getAlignment();\r
364 \r
365         FontMetrics fm = getFontMetrics(av.getFont());\r
366 \r
367         int LABEL_EAST = 0;\r
368 \r
369         if (av.scaleRightWrapped)\r
370         {\r
371             LABEL_EAST = fm.stringWidth(getMask()+"0");\r
372         }\r
373 \r
374         int LABEL_WEST = 0;\r
375 \r
376         if (av.scaleLeftWrapped)\r
377         {\r
378             LABEL_WEST = fm.stringWidth(getMask());\r
379         }\r
380 \r
381         int hgap = av.charHeight;\r
382         if(av.scaleAboveWrapped)\r
383           hgap += av.charHeight;\r
384 \r
385         int cWidth = (canvasWidth - LABEL_EAST - LABEL_WEST) / av.charWidth;\r
386         int cHeight = av.getAlignment().getHeight() * av.charHeight;\r
387 \r
388         av.setWrappedWidth(cWidth);\r
389 \r
390         av.endRes = av.startRes + cWidth;\r
391 \r
392 \r
393         int endx = (startRes + cWidth) - 1;\r
394         int ypos = hgap;\r
395 \r
396 \r
397         while ((ypos <= canvasHeight) && (startRes < av.alignment.getWidth()))\r
398         {\r
399             g.setFont(av.getFont());\r
400             g.setColor(Color.black);\r
401 \r
402             if (av.scaleLeftWrapped)\r
403             {\r
404                 drawWestScale(g, startRes, endx, ypos);\r
405             }\r
406 \r
407             if (av.scaleRightWrapped)\r
408             {\r
409                 g.translate(canvasWidth - LABEL_EAST, 0);\r
410                 drawEastScale(g, startRes, endx, ypos);\r
411                 g.translate(-(canvasWidth - LABEL_EAST), 0);\r
412             }\r
413 \r
414             g.translate(LABEL_WEST, 0);\r
415 \r
416             if (av.scaleAboveWrapped)\r
417             {\r
418                 drawNorthScale(g, startRes, endx, ypos);\r
419             }\r
420 \r
421             // When printing we have an extra clipped region,\r
422             // the Printable page which we need to account for here\r
423             Shape clip = g.getClip();\r
424 \r
425             if (clip == null)\r
426             {\r
427                 g.setClip(0, 0, cWidth * av.charWidth, canvasHeight);\r
428             }\r
429             else\r
430             {\r
431                 g.setClip(0, (int) clip.getBounds().getY(),\r
432                     cWidth * av.charWidth, (int) clip.getBounds().getHeight());\r
433             }\r
434 \r
435             if (av.vconsensus!=null && av.alignment.getWidth() >= av.vconsensus.size())\r
436             {\r
437               endx = av.vconsensus.size() - 2;\r
438             }\r
439 \r
440 \r
441             drawPanel(g, startRes, endx, 0, al.getHeight(), startRes, 0, ypos);\r
442 \r
443             if(av.showAnnotation)\r
444             {\r
445               g.translate(0, cHeight + ypos + 3);\r
446               if(annotations==null)\r
447                 annotations = new AnnotationPanel(av);\r
448 \r
449               annotations.drawComponent( (Graphics2D) g, startRes, endx + 1);\r
450               g.translate(0, -cHeight - ypos);\r
451             }\r
452             g.setClip(clip);\r
453             g.translate(-LABEL_WEST, 0);\r
454 \r
455             ypos += cHeight+getAnnotationHeight()+hgap;\r
456             if(av.showAnnotation)\r
457               ypos -= 3;\r
458 \r
459             startRes += cWidth;\r
460             endx = (startRes + cWidth) - 1;\r
461 \r
462             if (endx > al.getWidth())\r
463             {\r
464                 endx = al.getWidth();\r
465             }\r
466         }\r
467     }\r
468 \r
469     AnnotationPanel annotations;\r
470     int getAnnotationHeight()\r
471     {\r
472       if(!av.showAnnotation)\r
473         return 0;\r
474 \r
475       if(annotations==null)\r
476         annotations = new AnnotationPanel(av);\r
477 \r
478       return annotations.adjustPanelHeight();\r
479     }\r
480 \r
481     /**\r
482      * DOCUMENT ME!\r
483      *\r
484      * @param g1 DOCUMENT ME!\r
485      * @param x1 DOCUMENT ME!\r
486      * @param x2 DOCUMENT ME!\r
487      * @param y1 DOCUMENT ME!\r
488      * @param y2 DOCUMENT ME!\r
489      * @param startx DOCUMENT ME!\r
490      * @param starty DOCUMENT ME!\r
491      * @param offset DOCUMENT ME!\r
492      */\r
493 \r
494     float aaRatio = 2f/3f;\r
495     public void increaseAARatio()\r
496     {\r
497       aaRatio += .025;\r
498       if(aaRatio>1)\r
499         aaRatio = 1;\r
500 \r
501       repaint();\r
502     }\r
503 \r
504     public void decreaseAARation()\r
505     {\r
506       aaRatio -= .025;\r
507       if(aaRatio<0)\r
508         aaRatio = 0;\r
509 \r
510       repaint();\r
511     }\r
512 \r
513     synchronized public void drawPanel(Graphics g1, int x1, int x2, int y1,\r
514         int y2, int startx, int starty, int offset)\r
515     {\r
516         Graphics2D g = (Graphics2D) g1;\r
517         g.setFont(av.getFont());\r
518 \r
519 \r
520   SequenceI nextSeq;\r
521 \r
522   SequenceI dna = null;\r
523 \r
524   int aaHeight = (int)(av.getCharHeight()*aaRatio);\r
525   int dnaHeight =(int)(av.getCharHeight() * (1-aaRatio));\r
526 \r
527 \r
528   java.awt.geom.AffineTransform transform = new java.awt.geom.AffineTransform();\r
529   transform.scale(1f/3f , 1);\r
530   Font dnafont = new Font(av.getFont().getName(), av.getFont().getStyle(),\r
531                               dnaHeight);\r
532   dnafont = dnafont.deriveFont(transform);\r
533 \r
534   Font aafont = new Font(av.getFont().getName(), av.getFont().getStyle(),\r
535                               aaHeight);\r
536   transform = new java.awt.geom.AffineTransform();\r
537   transform.scale(1/aaRatio, 1);\r
538   aafont = aafont.deriveFont(transform);\r
539 \r
540         /// First draw the sequences\r
541         /////////////////////////////\r
542         for (int i = y1; i < y2; i++)\r
543         {\r
544             nextSeq = av.alignment.getSequenceAt(i);\r
545             g.setFont(aafont);\r
546 /*\r
547             StringBuffer dnasb = new StringBuffer();\r
548             for (int j = 0; j < nextSeq.getLength(); j++)\r
549             {\r
550               java.util.Vector codons = jalview.schemes.ResidueProperties.getCodons(nextSeq.getSequence(j,\r
551                   j + 1));\r
552               if (codons != null && codons.size() > 0)\r
553                 dnasb.append(codons.elementAt(0).toString());\r
554             }\r
555 \r
556             dna = new Sequence("dna", dnasb.toString());*/\r
557 \r
558 \r
559             sr.drawSequence(g, nextSeq, av.alignment.findAllGroups(nextSeq),\r
560                             x1, x2, (x1 - startx) * av.charWidth,\r
561                             offset + ( (i - starty) * av.charHeight), av.charWidth,\r
562                             aaHeight);\r
563 \r
564 \r
565          /*   g.setFont(dnafont);\r
566 \r
567             sr.drawSequence(g, dna, null,\r
568                             x1, x2 * 3 +2, ( (x1 - startx) * av.charWidth) / 3,\r
569                             offset + ( (i - starty) * av.charHeight) + aaHeight, av.charWidth / 3,\r
570                             dnaHeight);*/\r
571 \r
572             if (av.showSequenceFeatures)\r
573             {\r
574                 fr.drawSequence(g, nextSeq,\r
575                     av.alignment.findAllGroups(nextSeq), x1, x2,\r
576                     (x1 - startx) * av.charWidth,\r
577                     offset + ((i - starty) * av.charHeight), av.charWidth,\r
578                     av.charHeight);\r
579             }\r
580         }\r
581 \r
582         //\r
583         /////////////////////////////////////\r
584         // Now outline any areas if necessary\r
585         /////////////////////////////////////\r
586         SequenceGroup group = av.getSelectionGroup();\r
587         java.util.Vector groups = av.alignment.getGroups();\r
588 \r
589         int sx = -1;\r
590         int sy = -1;\r
591         int ex = -1;\r
592         int groupIndex = -1;\r
593 \r
594         if ((group == null) && (groups.size() > 0))\r
595         {\r
596             group = (SequenceGroup) groups.elementAt(0);\r
597             groupIndex = 0;\r
598         }\r
599 \r
600 \r
601         if (group != null && !isOverview)\r
602         {\r
603             do\r
604             {\r
605                 int oldY = -1;\r
606                 int i = 0;\r
607                 boolean inGroup = false;\r
608                 int top = -1;\r
609                 int bottom = -1;\r
610 \r
611                 for (i = y1; i < y2; i++)\r
612                 {\r
613                     sx = (group.getStartRes() - startx) * av.charWidth;\r
614                     sy = offset + ((i - starty) * av.charHeight);\r
615                     ex = (((group.getEndRes() + 1) - group.getStartRes()) * av.charWidth) -\r
616                         1;\r
617 \r
618                     if(sx+ex<0 || sx>imgWidth)\r
619                     {\r
620                       continue;\r
621                     }\r
622 \r
623                     if ( (sx <= (x2-x1)*av.charWidth) &&\r
624                             group.sequences.contains(av.alignment.getSequenceAt(\r
625                                     i)))\r
626                     {\r
627                         if ((bottom == -1) &&\r
628                                 !group.sequences.contains(\r
629                                     av.alignment.getSequenceAt(i + 1)))\r
630                         {\r
631                             bottom = sy + av.charHeight;\r
632                         }\r
633 \r
634                         if (!inGroup)\r
635                         {\r
636                             if (((top == -1) && (i == 0)) ||\r
637                                     !group.sequences.contains(\r
638                                         av.alignment.getSequenceAt(i - 1)))\r
639                             {\r
640                                 top = sy;\r
641                             }\r
642 \r
643                             oldY = sy;\r
644                             inGroup = true;\r
645 \r
646                             if (group == av.getSelectionGroup())\r
647                             {\r
648                                 g.setStroke(new BasicStroke(1,\r
649                                         BasicStroke.CAP_BUTT,\r
650                                         BasicStroke.JOIN_ROUND, 3f,\r
651                                         new float[] { 5f, 3f }, 0f));\r
652                                 g.setColor(Color.RED);\r
653                             }\r
654                             else\r
655                             {\r
656                                 g.setStroke(new BasicStroke());\r
657                                 g.setColor(group.getOutlineColour());\r
658                             }\r
659                         }\r
660                     }\r
661                     else\r
662                     {\r
663                       if (inGroup)\r
664                       {\r
665                         if (sx >= 0 && sx < imgWidth)\r
666                           g.drawLine(sx, oldY, sx, sy);\r
667 \r
668                         if (sx + ex < imgWidth)\r
669                           g.drawLine(sx + ex, oldY, sx + ex, sy);\r
670 \r
671                         if (sx < 0)\r
672                         {\r
673                           ex += sx;\r
674                           sx = 0;\r
675                         }\r
676 \r
677                         if (sx + ex > imgWidth)\r
678                           ex = imgWidth;\r
679 \r
680                         else if (sx + ex >= (x2 - x1 + 1) * av.charWidth)\r
681                           ex = (x2 - x1 + 1) * av.charWidth;\r
682 \r
683                         if (top != -1)\r
684                         {\r
685                           g.drawLine(sx, top, sx + ex, top);\r
686                           top = -1;\r
687                         }\r
688 \r
689                         if (bottom != -1)\r
690                         {\r
691                           g.drawLine(sx, bottom, sx + ex, bottom);\r
692                           bottom = -1;\r
693                         }\r
694 \r
695                         inGroup = false;\r
696                         }\r
697                     }\r
698                 }\r
699 \r
700                 if (inGroup)\r
701                 {\r
702                   sy = offset + ( (i - starty) * av.charHeight);\r
703                   if (sx >= 0 && sx < imgWidth)\r
704                     g.drawLine(sx, oldY, sx, sy);\r
705 \r
706                   if (sx + ex < imgWidth)\r
707                     g.drawLine(sx + ex, oldY, sx + ex, sy);\r
708 \r
709                   if (sx < 0)\r
710                   {\r
711                     ex += sx;\r
712                     sx = 0;\r
713                   }\r
714 \r
715                   if (sx + ex > imgWidth)\r
716                     ex = imgWidth;\r
717                   else if (sx + ex >= (x2 - x1 + 1) * av.charWidth)\r
718                     ex = (x2 - x1 + 1) * av.charWidth;\r
719 \r
720                   if (top != -1)\r
721                   {\r
722                     g.drawLine(sx, top, sx + ex, top);\r
723                     top = -1;\r
724                   }\r
725 \r
726                   if (bottom != -1)\r
727                   {\r
728                     g.drawLine(sx, bottom - 1, sx + ex, bottom - 1);\r
729                     bottom = -1;\r
730                   }\r
731 \r
732                     inGroup = false;\r
733                 }\r
734 \r
735                 groupIndex++;\r
736 \r
737                 if (groupIndex >= groups.size())\r
738                 {\r
739                     break;\r
740                 }\r
741 \r
742                 group = (SequenceGroup) groups.elementAt(groupIndex);\r
743             }\r
744             while (groupIndex < groups.size());\r
745         }\r
746 \r
747         /// Highlight search Results once all sequences have been drawn\r
748         //////////////////////////////////////////////////////////\r
749         if (displaySearch)\r
750         {\r
751             for (int r = 0; r < searchResults.length; r += 3)\r
752             {\r
753                 int searchSeq = searchResults[r];\r
754 \r
755                 if ((searchSeq >= y1) && (searchSeq < y2))\r
756                 {\r
757                     SequenceI seq = av.getAlignment().getSequenceAt(searchSeq);\r
758 \r
759                     int searchStart = seq.findIndex(searchResults[r + 1]) - 1;\r
760                     int searchEnd = seq.findIndex(searchResults[r + 2]) - 1;\r
761 \r
762                     SequenceRenderer ssr = (SequenceRenderer) sr;\r
763 \r
764                     if (searchStart < x1)\r
765                     {\r
766                         searchStart = x1;\r
767                     }\r
768 \r
769                     if (searchEnd > x2)\r
770                     {\r
771                         searchEnd = x2;\r
772                     }\r
773 \r
774                     ssr.drawHighlightedText(seq, searchStart, searchEnd,\r
775                         (searchStart - startx) * av.charWidth,\r
776                         offset + ((searchSeq - starty) * av.charHeight),\r
777                         av.charWidth, av.charHeight);\r
778                 }\r
779             }\r
780         }\r
781     }\r
782 \r
783     /**\r
784      * DOCUMENT ME!\r
785      *\r
786      * @param results DOCUMENT ME!\r
787      */\r
788     public void highlightSearchResults(int[] results)\r
789     {\r
790         // results are in the order sequence, startRes, endRes\r
791         if (results == null)\r
792         {\r
793             displaySearch = false;\r
794         }\r
795         else\r
796         {\r
797             displaySearch = true;\r
798         }\r
799 \r
800         searchResults = results;\r
801 \r
802         repaint();\r
803     }\r
804 }\r