elementAt instead of get for 1.1 compatibility
[jalview.git] / src / jalview / appletgui / 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 \r
20 package jalview.appletgui;\r
21 \r
22 import java.awt.*;\r
23 \r
24 import jalview.datamodel.*;\r
25 \r
26 public class SeqCanvas\r
27     extends Panel\r
28 {\r
29   FeatureRenderer fr;\r
30   SequenceRenderer sr;\r
31   Image img;\r
32   Graphics gg;\r
33   int imgWidth;\r
34   int imgHeight;\r
35 \r
36   AlignViewport av;\r
37 \r
38   SearchResults searchResults = null;\r
39 \r
40   boolean fastPaint = false;\r
41 \r
42 \r
43   int cursorX = 0;\r
44   int cursorY = 0;\r
45 \r
46 \r
47   public SeqCanvas(AlignViewport av)\r
48   {\r
49     this.av = av;\r
50     fr = new FeatureRenderer(av);\r
51     sr = new SequenceRenderer(av);\r
52     PaintRefresher.Register(this, av.alignment);\r
53   }\r
54 \r
55   public AlignViewport getViewport()\r
56   {\r
57     return av;\r
58   }\r
59 \r
60   public FeatureRenderer getFeatureRenderer()\r
61   {\r
62     return fr;\r
63   }\r
64 \r
65   MCview.AppletPDBCanvas pdbCanvas;\r
66   public SequenceRenderer getSequenceRenderer()\r
67   {\r
68     return sr;\r
69   }\r
70 \r
71   public void setPDBCanvas(MCview.AppletPDBCanvas pc)\r
72   {\r
73     pdbCanvas = pc;\r
74   }\r
75 \r
76 \r
77   void drawNorthScale(Graphics g, int startx, int endx, int ypos)\r
78   {\r
79     int scalestartx = startx - startx % 10 + 10;\r
80 \r
81     g.setColor(Color.black);\r
82 \r
83     // NORTH SCALE\r
84     for (int i = scalestartx; i < endx; i += 10)\r
85     {\r
86       int value = i;\r
87       if(av.hasHiddenColumns)\r
88           value = av.getColumnSelection().adjustForHiddenColumns(value);\r
89 \r
90       g.drawString( String.valueOf(value), (i - startx - 1) * av.charWidth,\r
91           ypos - (av.charHeight / 2));\r
92 \r
93       g.drawLine(((i - startx - 1) * av.charWidth) + (av.charWidth / 2),\r
94           (ypos + 2) - (av.charHeight / 2),\r
95           ((i - startx - 1) * av.charWidth) + (av.charWidth / 2), ypos -\r
96                 2);\r
97     }\r
98   }\r
99 \r
100   void drawWestScale(Graphics g, int startx, int endx, int ypos)\r
101   {\r
102     FontMetrics fm = getFontMetrics(av.getFont());\r
103     ypos += av.charHeight;\r
104     if (av.hasHiddenColumns)\r
105     {\r
106       startx = av.getColumnSelection().adjustForHiddenColumns(startx);\r
107       endx = av.getColumnSelection().adjustForHiddenColumns(endx);\r
108     }\r
109 \r
110     int maxwidth = av.alignment.getWidth();\r
111     if (av.hasHiddenColumns)\r
112         maxwidth = av.getColumnSelection().findColumnPosition(maxwidth) - 1;\r
113 \r
114       // WEST SCALE\r
115       for (int i = 0; i < av.alignment.getHeight(); i++)\r
116       {\r
117         SequenceI seq = av.alignment.getSequenceAt(i);\r
118         int index = startx;\r
119         int value = -1;\r
120 \r
121         while (index < endx)\r
122         {\r
123           if (jalview.util.Comparison.isGap(seq.getCharAt(index)))\r
124           {\r
125             index++;\r
126 \r
127             continue;\r
128           }\r
129 \r
130           value = av.alignment.getSequenceAt(i).findPosition(index);\r
131 \r
132           break;\r
133         }\r
134 \r
135         if (value != -1)\r
136         {\r
137           int x = LABEL_WEST - fm.stringWidth(String.valueOf(value)) -\r
138               av.charWidth / 2;\r
139           g.drawString(value + "", x,\r
140                        (ypos + (i * av.charHeight)) - (av.charHeight / 5));\r
141         }\r
142       }\r
143     }\r
144   void drawEastScale(Graphics g, int startx, int endx, int ypos)\r
145   {\r
146         ypos += av.charHeight;\r
147 \r
148         if(av.hasHiddenColumns)\r
149                 endx = av.getColumnSelection().adjustForHiddenColumns(endx);\r
150 \r
151         SequenceI seq;\r
152         // EAST SCALE\r
153         for (int i = 0; i < av.alignment.getHeight(); i++)\r
154         {\r
155             seq = av.alignment.getSequenceAt(i);\r
156             int index = endx;\r
157             int value = -1;\r
158 \r
159             while (index > startx)\r
160             {\r
161                 if (jalview.util.Comparison.isGap(seq.getCharAt(index)))\r
162                 {\r
163                     index--;\r
164 \r
165                     continue;\r
166                 }\r
167 \r
168                 value = seq.findPosition(index);\r
169 \r
170                 break;\r
171             }\r
172 \r
173             if (value != -1)\r
174             {\r
175                 g.drawString(String.valueOf(value), 0,\r
176                     (ypos + (i * av.charHeight)) - (av.charHeight / 5));\r
177             }\r
178         }\r
179     }\r
180 \r
181   int lastsr=0;\r
182   void fastPaint(int horizontal, int vertical)\r
183   {\r
184     if ( fastPaint || gg == null)\r
185     {\r
186       return;\r
187     }\r
188 \r
189 \r
190     // Its possible on certain browsers that the call to fastpaint\r
191     // is faster than it can paint, so this check here catches\r
192     // this possibility\r
193     if(lastsr + horizontal != av.startRes)\r
194     {\r
195       horizontal = av.startRes - lastsr;\r
196     }\r
197 \r
198     lastsr = av.startRes;\r
199 \r
200     fastPaint = true;\r
201     gg.copyArea(horizontal * av.charWidth,\r
202                 vertical * av.charHeight,\r
203                 imgWidth - horizontal * av.charWidth,\r
204                 imgHeight - vertical * av.charHeight,\r
205                 -horizontal * av.charWidth,\r
206                 -vertical * av.charHeight);\r
207 \r
208 \r
209 \r
210     int sr = av.startRes, er = av.endRes, ss = av.startSeq, es = av.endSeq,\r
211         transX = 0, transY = 0;\r
212 \r
213     if (horizontal > 0) // scrollbar pulled right, image to the left\r
214     {\r
215       transX = (er - sr - horizontal) * av.charWidth;\r
216       sr = er - horizontal;\r
217     }\r
218     else if (horizontal < 0)\r
219     {\r
220       er = sr - horizontal;\r
221     }\r
222 \r
223     else if (vertical > 0) // scroll down\r
224     {\r
225       ss = es - vertical;\r
226       if (ss < av.startSeq) // ie scrolling too fast, more than a page at a time\r
227       {\r
228         ss = av.startSeq;\r
229       }\r
230       else\r
231       {\r
232         transY = imgHeight - vertical * av.charHeight;\r
233       }\r
234     }\r
235     else if (vertical < 0)\r
236     {\r
237       es = ss - vertical;\r
238       if (es > av.endSeq)\r
239       {\r
240         es = av.endSeq;\r
241       }\r
242     }\r
243 \r
244     gg.translate(transX, transY);\r
245 \r
246     drawPanel(gg, sr, er, ss, es, 0);\r
247     gg.translate( -transX, -transY);\r
248 \r
249     repaint();\r
250 \r
251   }\r
252 \r
253   /**\r
254    * Definitions of startx and endx (hopefully):\r
255    * SMJS This is what I'm working towards!\r
256    *   startx is the first residue (starting at 0) to display.\r
257    *   endx   is the last residue to display (starting at 0).\r
258    *   starty is the first sequence to display (starting at 0).\r
259    *   endy   is the last sequence to display (starting at 0).\r
260    * NOTE 1: The av limits are set in setFont in this class and\r
261    * in the adjustment listener in SeqPanel when the scrollbars move.\r
262    */\r
263   public void update(Graphics g)\r
264   {\r
265     paint(g);\r
266   }\r
267 \r
268   public void paint(Graphics g)\r
269   {\r
270 \r
271     if (img != null && (fastPaint\r
272                         || (getSize().width != g.getClipBounds().width)\r
273                         || (getSize().height != g.getClipBounds().height)))\r
274     {\r
275       g.drawImage(img, 0, 0, this);\r
276       fastPaint = false;\r
277       return;\r
278     }\r
279 \r
280     if (fastPaint)\r
281     {\r
282       g.drawImage(img, 0, 0, this);\r
283       fastPaint = false;\r
284       return;\r
285     }\r
286 \r
287     // this draws the whole of the alignment\r
288     imgWidth = this.getSize().width;\r
289     imgHeight = this.getSize().height;\r
290 \r
291     imgWidth -= imgWidth % av.charWidth;\r
292     imgHeight -= imgHeight % av.charHeight;\r
293 \r
294     if (imgWidth < 1 || imgHeight < 1)\r
295     {\r
296       return;\r
297     }\r
298 \r
299     if (img == null || imgWidth != img.getWidth(this) ||\r
300         imgHeight != img.getHeight(this))\r
301     {\r
302       img = createImage(imgWidth, imgHeight);\r
303       gg = img.getGraphics();\r
304       gg.setFont(av.getFont());\r
305     }\r
306 \r
307     gg.setColor(Color.white);\r
308     gg.fillRect(0, 0, imgWidth, imgHeight);\r
309 \r
310 \r
311     if (av.getWrapAlignment())\r
312     {\r
313       drawWrappedPanel(gg, imgWidth, imgHeight, av.startRes);\r
314     }\r
315     else\r
316     {\r
317       drawPanel(gg, av.startRes, av.endRes, av.startSeq, av.endSeq, 0);\r
318     }\r
319 \r
320     g.drawImage(img, 0, 0, this);\r
321 \r
322     if (pdbCanvas != null)\r
323     {\r
324       pdbCanvas.updateSeqColours();\r
325     }\r
326   }\r
327 \r
328   int LABEL_WEST, LABEL_EAST;\r
329   public int getWrappedCanvasWidth(int cwidth)\r
330   {\r
331       cwidth -= cwidth % av.charWidth;\r
332 \r
333       FontMetrics fm = getFontMetrics(av.getFont());\r
334 \r
335       LABEL_EAST = 0;\r
336       LABEL_WEST = 0;\r
337 \r
338       if (av.scaleRightWrapped)\r
339       {\r
340           LABEL_EAST = fm.stringWidth(getMask());\r
341       }\r
342 \r
343       if (av.scaleLeftWrapped)\r
344       {\r
345           LABEL_WEST = fm.stringWidth(getMask());\r
346       }\r
347 \r
348       return (cwidth - LABEL_EAST - LABEL_WEST) / av.charWidth;\r
349   }\r
350 \r
351 \r
352   /**\r
353    * Generates a string of zeroes.\r
354    * @return String\r
355    */\r
356   String getMask()\r
357   {\r
358     String mask = "00";\r
359     for (int i = av.alignment.getWidth(); i > 0; i /= 10)\r
360     {\r
361       mask += "0";\r
362     }\r
363     return mask;\r
364     }\r
365 \r
366   public void drawWrappedPanel(Graphics g, int canvasWidth, int canvasHeight,\r
367                                int startRes)\r
368   {\r
369     AlignmentI al = av.getAlignment();\r
370 \r
371     FontMetrics fm = getFontMetrics(av.getFont());\r
372 \r
373 \r
374     if (av.scaleRightWrapped)\r
375     {\r
376         LABEL_EAST = fm.stringWidth(getMask());\r
377     }\r
378 \r
379     if (av.scaleLeftWrapped)\r
380     {\r
381         LABEL_WEST = fm.stringWidth(getMask());\r
382     }\r
383 \r
384     int hgap = av.charHeight;\r
385     if(av.scaleAboveWrapped)\r
386       hgap += av.charHeight;\r
387 \r
388     int cWidth = (canvasWidth - LABEL_EAST - LABEL_WEST) / av.charWidth;\r
389     int cHeight = av.getAlignment().getHeight() * av.charHeight;\r
390 \r
391     av.setWrappedWidth(cWidth);\r
392 \r
393     av.endRes = av.startRes + cWidth;\r
394 \r
395 \r
396     int endx;\r
397     int ypos = hgap;\r
398 \r
399     int maxwidth = av.alignment.getWidth();\r
400 \r
401     if(av.hasHiddenColumns)\r
402           maxwidth = av.getColumnSelection().findColumnPosition(maxwidth)-1;\r
403 \r
404     while ((ypos <= canvasHeight) && (startRes < maxwidth))\r
405     {\r
406       endx = startRes + cWidth -1;\r
407 \r
408       if (endx > maxwidth)\r
409       {\r
410         endx = maxwidth;\r
411       }\r
412 \r
413         g.setColor(Color.black);\r
414 \r
415         if (av.scaleLeftWrapped)\r
416         {\r
417             drawWestScale(g, startRes, endx, ypos);\r
418         }\r
419 \r
420         if (av.scaleRightWrapped)\r
421         {\r
422             g.translate(canvasWidth - LABEL_EAST, 0);\r
423             drawEastScale(g, startRes, endx, ypos);\r
424             g.translate(-(canvasWidth - LABEL_EAST), 0);\r
425         }\r
426 \r
427         g.translate(LABEL_WEST, 0);\r
428 \r
429         if (av.scaleAboveWrapped)\r
430         {\r
431           drawNorthScale(g, startRes, endx, ypos);\r
432         }\r
433         if (av.hasHiddenColumns && av.showHiddenMarkers)\r
434         {\r
435           g.setColor(Color.blue);\r
436           int res;\r
437           for (int i = 0; i < av.getColumnSelection().getHiddenColumns().size();\r
438                i++)\r
439           {\r
440             res = av.getColumnSelection().findHiddenRegionPosition(i) -\r
441                 startRes;\r
442 \r
443             if (res < 0 || res > endx - startRes)\r
444               continue;\r
445 \r
446             gg.fillPolygon(new int[]\r
447                            {res * av.charWidth - av.charHeight / 4,\r
448                            res * av.charWidth + av.charHeight / 4,\r
449                            res * av.charWidth},\r
450                            new int[]\r
451                            {\r
452                            ypos - (av.charHeight / 2),\r
453                            ypos - (av.charHeight / 2),\r
454                            ypos - (av.charHeight / 2) + 8\r
455             }, 3);\r
456 \r
457           }\r
458         }\r
459 \r
460         if(g.getClip()==null)\r
461           g.setClip(0, 0, cWidth * av.charWidth, canvasHeight);\r
462 \r
463         drawPanel(g, startRes, endx, 0, al.getHeight(), ypos);\r
464          g.setClip(null);\r
465 \r
466 \r
467         if(av.showAnnotation)\r
468         {\r
469           g.translate(0, cHeight + ypos+4);\r
470           if(annotations==null)\r
471             annotations = new AnnotationPanel(av);\r
472 \r
473           annotations.drawComponent( g, startRes, endx+1 );\r
474           g.translate(0, -cHeight - ypos-4);\r
475         }\r
476         g.translate(-LABEL_WEST, 0);\r
477 \r
478         ypos += cHeight+getAnnotationHeight()+hgap;\r
479 \r
480 \r
481         startRes += cWidth;\r
482         }\r
483 \r
484   }\r
485 \r
486   AnnotationPanel annotations;\r
487   int getAnnotationHeight()\r
488   {\r
489     if(!av.showAnnotation)\r
490       return 0;\r
491 \r
492     if(annotations==null)\r
493       annotations = new AnnotationPanel(av);\r
494 \r
495     return annotations.adjustPanelHeight();\r
496     }\r
497 \r
498     void drawPanel(Graphics g1, int startRes, int endRes,\r
499                     int startSeq, int endSeq, int offset)\r
500     {\r
501       if(!av.hasHiddenColumns)\r
502       {\r
503         draw(g1, startRes, endRes, startSeq, endSeq, offset);\r
504       }\r
505       else\r
506       {\r
507         java.util.Vector regions = av.getColumnSelection().getHiddenColumns();\r
508 \r
509         int screenY = 0;\r
510         int blockStart = startRes;\r
511         int blockEnd = endRes;\r
512 \r
513         for (int i = 0; i < regions.size(); i++)\r
514         {\r
515           int[] region = (int[]) regions.elementAt(i);\r
516           int hideStart = region[0];\r
517           int hideEnd = region[1];\r
518 \r
519           if (hideStart <= blockStart)\r
520           {\r
521             blockStart += (hideEnd - hideStart) + 1;\r
522             continue;\r
523           }\r
524 \r
525           blockEnd = hideStart - 1;\r
526 \r
527           g1.translate(screenY * av.charWidth, 0);\r
528 \r
529           draw(g1, blockStart, blockEnd, startSeq, endSeq, offset);\r
530 \r
531           if(av.getShowHiddenMarkers())\r
532           {\r
533             g1.setColor(Color.blue);\r
534             g1.drawLine( (blockEnd - blockStart + 1) * av.charWidth - 1,\r
535                         startSeq + offset,\r
536                         (blockEnd - blockStart + 1) * av.charWidth - 1,\r
537                         startSeq + (endSeq - startSeq) * av.charHeight + offset);\r
538           }\r
539 \r
540           g1.translate( -screenY * av.charWidth, 0);\r
541           screenY += blockEnd - blockStart + 1;\r
542           blockStart = hideEnd + 1;\r
543         }\r
544 \r
545         if (screenY <= (endRes - startRes))\r
546         {\r
547           blockEnd = blockStart + (endRes - startRes) - screenY;\r
548           g1.translate(screenY * av.charWidth, 0);\r
549           draw(g1, blockStart, blockEnd, startSeq, endSeq, offset);\r
550 \r
551           g1.translate( -screenY * av.charWidth, 0);\r
552         }\r
553       }\r
554 \r
555     }\r
556 \r
557 \r
558 \r
559 \r
560     //int startRes, int endRes, int startSeq, int endSeq, int x, int y,\r
561     // int x1, int x2, int y1, int y2, int startx, int starty,\r
562     void draw(Graphics g,\r
563                    int startRes, int endRes,\r
564                    int startSeq, int endSeq,\r
565                    int offset)\r
566    {\r
567       g.setFont(av.getFont());\r
568       sr.prepare(g, av.renderGaps);\r
569 \r
570       SequenceI nextSeq;\r
571 \r
572         /// First draw the sequences\r
573         /////////////////////////////\r
574         for (int i = startSeq; i < endSeq; i++)\r
575         {\r
576             nextSeq = av.alignment.getSequenceAt(i);\r
577 \r
578             sr.drawSequence(nextSeq, av.alignment.findAllGroups(nextSeq),\r
579                             startRes, endRes,\r
580                             offset + ( (i - startSeq) * av.charHeight));\r
581 \r
582             if (av.showSequenceFeatures)\r
583             {\r
584                 fr.drawSequence(g, nextSeq, startRes, endRes,\r
585                     offset + ((i - startSeq) * av.charHeight));\r
586             }\r
587 \r
588             /// Highlight search Results once all sequences have been drawn\r
589             //////////////////////////////////////////////////////////\r
590             if (searchResults != null)\r
591             {\r
592               int[] visibleResults = searchResults.getResults(nextSeq, startRes, endRes);\r
593               if (visibleResults != null)\r
594                 for (int r = 0; r < visibleResults.length; r += 2)\r
595                 {\r
596                   sr.drawHighlightedText(nextSeq, visibleResults[r],\r
597                                          visibleResults[r + 1],\r
598                                          (visibleResults[r] - startRes) * av.charWidth,\r
599                                          offset + ( (i - startSeq) * av.charHeight));\r
600                 }\r
601             }\r
602 \r
603             if(av.cursorMode && cursorY==i\r
604                && cursorX>=startRes && cursorX<=endRes)\r
605             {\r
606               sr.drawCursor(nextSeq, cursorX, (cursorX - startRes) * av.charWidth,\r
607                             offset + ( (i - startSeq) * av.charHeight));\r
608             }\r
609           }\r
610 \r
611           if(av.getSelectionGroup()!=null || av.alignment.getGroups().size()>0)\r
612             drawGroupsBoundaries(g, startRes, endRes, startSeq, endSeq, offset);\r
613 \r
614    }\r
615 \r
616    void drawGroupsBoundaries(Graphics g,\r
617                    int startRes, int endRes,\r
618                    int startSeq, int endSeq,\r
619                    int offset)\r
620    {\r
621      //\r
622      /////////////////////////////////////\r
623      // Now outline any areas if necessary\r
624      /////////////////////////////////////\r
625      SequenceGroup group = av.getSelectionGroup();\r
626 \r
627      int sx = -1;\r
628      int sy = -1;\r
629      int ex = -1;\r
630      int groupIndex = -1;\r
631 \r
632      if ( (group == null) && (av.alignment.getGroups().size() > 0))\r
633      {\r
634        group = (SequenceGroup) av.alignment.getGroups().elementAt(0);\r
635        groupIndex = 0;\r
636      }\r
637 \r
638      if (group != null)\r
639      {\r
640        do\r
641        {\r
642          int oldY = -1;\r
643          int i = 0;\r
644          boolean inGroup = false;\r
645          int top = -1;\r
646          int bottom = -1;\r
647          int alHeight = av.alignment.getHeight()-1;\r
648 \r
649          for (i = startSeq; i < endSeq; i++)\r
650          {\r
651            sx = (group.getStartRes() - startRes) * av.charWidth;\r
652            sy = offset + ( (i - startSeq) * av.charHeight);\r
653            ex = ( ( (group.getEndRes() + 1) - group.getStartRes()) * av.charWidth) -\r
654                1;\r
655 \r
656            if (sx + ex < 0 || sx > imgWidth)\r
657            {\r
658              continue;\r
659            }\r
660 \r
661            if ( (sx <= (endRes - startRes) * av.charWidth) &&\r
662                group.getSequences(false).\r
663                contains(av.alignment.getSequenceAt(i)))\r
664            {\r
665              if ( (bottom == -1) &&\r
666              (i >= alHeight ||\r
667                  !group.getSequences(false).contains(\r
668                      av.alignment.getSequenceAt(i + 1))))\r
669              {\r
670                bottom = sy + av.charHeight;\r
671              }\r
672 \r
673              if (!inGroup)\r
674              {\r
675                if ( ( (top == -1) && (i == 0)) ||\r
676                    !group.getSequences(false).contains(\r
677                        av.alignment.getSequenceAt(i - 1)))\r
678                {\r
679                  top = sy;\r
680                }\r
681 \r
682                oldY = sy;\r
683                inGroup = true;\r
684 \r
685                if (group == av.getSelectionGroup())\r
686                {\r
687                  g.setColor(Color.red);\r
688                }\r
689                else\r
690                {\r
691                  g.setColor(group.getOutlineColour());\r
692                }\r
693              }\r
694            }\r
695            else\r
696            {\r
697              if (inGroup)\r
698              {\r
699                if (sx >= 0 && sx < imgWidth)\r
700                  g.drawLine(sx, oldY, sx, sy);\r
701 \r
702                if (sx + ex < imgWidth)\r
703                  g.drawLine(sx + ex, oldY, sx + ex, sy);\r
704 \r
705                if (sx < 0)\r
706                {\r
707                  ex += sx;\r
708                  sx = 0;\r
709                }\r
710 \r
711                if (sx + ex > imgWidth)\r
712                  ex = imgWidth;\r
713 \r
714                else if (sx + ex >= (endRes - startRes + 1) * av.charWidth)\r
715                  ex = (endRes - startRes + 1) * av.charWidth;\r
716 \r
717                if (top != -1)\r
718                {\r
719                  g.drawLine(sx, top, sx + ex, top);\r
720                  top = -1;\r
721                }\r
722 \r
723                if (bottom != -1)\r
724                {\r
725                  g.drawLine(sx, bottom, sx + ex, bottom);\r
726                  bottom = -1;\r
727                }\r
728 \r
729                inGroup = false;\r
730              }\r
731            }\r
732          }\r
733 \r
734          if (inGroup)\r
735          {\r
736            sy = offset + ( (i - startSeq) * av.charHeight);\r
737            if (sx >= 0 && sx < imgWidth)\r
738              g.drawLine(sx, oldY, sx, sy);\r
739 \r
740            if (sx + ex < imgWidth)\r
741              g.drawLine(sx + ex, oldY, sx + ex, sy);\r
742 \r
743            if (sx < 0)\r
744            {\r
745              ex += sx;\r
746              sx = 0;\r
747            }\r
748 \r
749            if (sx + ex > imgWidth)\r
750              ex = imgWidth;\r
751            else if (sx + ex >= (endRes - startRes + 1) * av.charWidth)\r
752              ex = (endRes - startRes + 1) * av.charWidth;\r
753 \r
754            if (top != -1)\r
755            {\r
756              g.drawLine(sx, top, sx + ex, top);\r
757              top = -1;\r
758            }\r
759 \r
760            if (bottom != -1)\r
761            {\r
762              g.drawLine(sx, bottom - 1, sx + ex, bottom - 1);\r
763              bottom = -1;\r
764            }\r
765 \r
766            inGroup = false;\r
767          }\r
768 \r
769          groupIndex++;\r
770 \r
771          if (groupIndex >= av.alignment.getGroups().size())\r
772          {\r
773            break;\r
774          }\r
775 \r
776          group = (SequenceGroup) av.alignment.getGroups().elementAt(groupIndex);\r
777        }\r
778        while (groupIndex < av.alignment.getGroups().size());\r
779 \r
780      }\r
781    }\r
782 \r
783   public void highlightSearchResults(SearchResults results)\r
784   {\r
785     searchResults = results;\r
786 \r
787     repaint();\r
788   }\r
789 \r
790 }\r