Formatting
[jalview.git] / src / jalview / appletgui / AnnotationPanel.java
1 /*\r
2  * Jalview - A Sequence Alignment Editor and Viewer\r
3  * Copyright (C) 2007 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.util.*;\r
23 \r
24 import java.awt.*;\r
25 import java.awt.event.*;\r
26 \r
27 import jalview.datamodel.*;\r
28 \r
29 public class AnnotationPanel\r
30     extends Panel implements AdjustmentListener\r
31 {\r
32   AlignViewport av;\r
33   AlignmentPanel ap;\r
34   int activeRow = -1;\r
35 \r
36   Vector activeRes;\r
37   static String HELIX = "Helix";\r
38   static String SHEET = "Sheet";\r
39   static String LABEL = "Label";\r
40   static String REMOVE = "Remove Annotation";\r
41   static String COLOUR = "Colour";\r
42   static Color HELIX_COLOUR = Color.red.darker();\r
43   static Color SHEET_COLOUR = Color.green.darker().darker();\r
44 \r
45   Image image;\r
46   Graphics gg;\r
47   FontMetrics fm;\r
48   int imgWidth = 0;\r
49 \r
50   boolean fastPaint = false;\r
51 \r
52   public static int GRAPH_HEIGHT = 40;\r
53 \r
54   boolean MAC = false;\r
55 \r
56   public AnnotationPanel(AlignmentPanel ap)\r
57   {\r
58     if (System.getProperty("os.name").startsWith("Mac"))\r
59     {\r
60       MAC = true;\r
61     }\r
62 \r
63     this.ap = ap;\r
64     av = ap.av;\r
65     setLayout(null);\r
66     adjustPanelHeight();\r
67 \r
68     addMouseMotionListener(new MouseMotionAdapter()\r
69     {\r
70       public void mouseMoved(MouseEvent evt)\r
71       {\r
72         doMouseMoved(evt);\r
73       }\r
74     });\r
75 \r
76     // ap.annotationScroller.getVAdjustable().addAdjustmentListener( this );\r
77   }\r
78 \r
79   public AnnotationPanel(AlignViewport av)\r
80   {\r
81     this.av = av;\r
82   }\r
83 \r
84   public void adjustmentValueChanged(AdjustmentEvent evt)\r
85   {\r
86     ap.alabels.setScrollOffset( -evt.getValue());\r
87   }\r
88 \r
89   public int adjustPanelHeight()\r
90   {\r
91     // setHeight of panels\r
92     AlignmentAnnotation[] aa = av.alignment.getAlignmentAnnotation();\r
93 \r
94     int height = 0;\r
95     if (aa != null)\r
96     {\r
97       for (int i = 0; i < aa.length; i++)\r
98       {\r
99         if (!aa[i].visible)\r
100         {\r
101           continue;\r
102         }\r
103 \r
104         aa[i].height = 0;\r
105 \r
106         if (aa[i].hasText)\r
107         {\r
108           aa[i].height += av.charHeight;\r
109         }\r
110         if (aa[i].hasIcons)\r
111         {\r
112           aa[i].height += 16;\r
113         }\r
114 \r
115         if (aa[i].graph > 0)\r
116         {\r
117           aa[i].height += GRAPH_HEIGHT;\r
118         }\r
119 \r
120         if (aa[i].height == 0)\r
121         {\r
122           aa[i].height = 20;\r
123         }\r
124         height += aa[i].height;\r
125       }\r
126     }\r
127     else\r
128     {\r
129       height = 20;\r
130     }\r
131 \r
132     this.setSize(getSize().width, height);\r
133 \r
134     repaint();\r
135 \r
136     return height;\r
137 \r
138   }\r
139 \r
140   public void addEditableColumn(int i)\r
141   {\r
142     if (activeRow == -1)\r
143     {\r
144       AlignmentAnnotation[] aa = av.alignment.getAlignmentAnnotation();\r
145       if (aa == null)\r
146       {\r
147         return;\r
148       }\r
149 \r
150       for (int j = 0; j < aa.length; j++)\r
151       {\r
152         if (aa[j].editable)\r
153         {\r
154           activeRow = j;\r
155           break;\r
156         }\r
157       }\r
158     }\r
159 \r
160     if (activeRes == null)\r
161     {\r
162       activeRes = new Vector();\r
163       activeRes.addElement(String.valueOf(i));\r
164       return;\r
165     }\r
166 \r
167     activeRes.addElement(String.valueOf(i));\r
168   }\r
169 \r
170   public void doMouseMoved(MouseEvent evt)\r
171   {\r
172     AlignmentAnnotation[] aa = av.alignment.getAlignmentAnnotation();\r
173     if (aa == null)\r
174     {\r
175       return;\r
176     }\r
177 \r
178     int row = -1;\r
179     int height = 0;\r
180     for (int i = 0; i < aa.length; i++)\r
181     {\r
182 \r
183       if (aa[i].visible)\r
184       {\r
185         height += aa[i].height;\r
186       }\r
187 \r
188       if (evt.getY() < height)\r
189       {\r
190         row = i;\r
191         break;\r
192       }\r
193     }\r
194 \r
195     int res = evt.getX() / av.getCharWidth() + av.getStartRes();\r
196 \r
197     if (av.hasHiddenColumns)\r
198     {\r
199       res = av.getColumnSelection().adjustForHiddenColumns(res);\r
200     }\r
201 \r
202     if (row > -1 && res < aa[row].annotations.length && aa[row].annotations[res] != null)\r
203     {\r
204       StringBuffer text = new StringBuffer("Sequence position " + (res + 1));\r
205       if (aa[row].annotations[res].description != null)\r
206       {\r
207         text.append("  " + aa[row].annotations[res].description);\r
208       }\r
209       ap.alignFrame.statusBar.setText(text.toString());\r
210     }\r
211   }\r
212 \r
213   public void update(Graphics g)\r
214   {\r
215     paint(g);\r
216   }\r
217 \r
218   public void paint(Graphics g)\r
219   {\r
220 \r
221     imgWidth = getSize().width;\r
222     //(av.endRes - av.startRes + 1) * av.charWidth;\r
223 \r
224     if (image == null || imgWidth != image.getWidth(this))\r
225     {\r
226       image = createImage(imgWidth, ap.annotationPanel.getSize().height);\r
227       gg = image.getGraphics();\r
228       gg.setFont(av.getFont());\r
229       fm = gg.getFontMetrics();\r
230       fastPaint = false;\r
231     }\r
232 \r
233     if (fastPaint)\r
234     {\r
235       g.drawImage(image, 0, 0, this);\r
236       fastPaint = false;\r
237       return;\r
238     }\r
239 \r
240     gg.setColor(Color.white);\r
241     gg.fillRect(0, 0, getSize().width, getSize().height);\r
242     drawComponent(gg, av.startRes, av.endRes + 1);\r
243 \r
244     g.drawImage(image, 0, 0, this);\r
245   }\r
246 \r
247   public void fastPaint(int horizontal)\r
248   {\r
249     if (horizontal == 0\r
250         || av.alignment.getAlignmentAnnotation() == null\r
251         || av.alignment.getAlignmentAnnotation().length < 1\r
252         )\r
253     {\r
254       repaint();\r
255       return;\r
256     }\r
257 \r
258     gg.copyArea(0, 0, imgWidth, getSize().height, -horizontal * av.charWidth, 0);\r
259     int sr = av.startRes, er = av.endRes + 1, transX = 0;\r
260 \r
261     if (horizontal > 0) // scrollbar pulled right, image to the left\r
262     {\r
263       transX = (er - sr - horizontal) * av.charWidth;\r
264       sr = er - horizontal;\r
265     }\r
266     else if (horizontal < 0)\r
267     {\r
268       er = sr - horizontal;\r
269     }\r
270 \r
271     gg.translate(transX, 0);\r
272 \r
273     drawComponent(gg, sr, er);\r
274 \r
275     gg.translate( -transX, 0);\r
276 \r
277     fastPaint = true;\r
278     repaint();\r
279   }\r
280 \r
281   /**\r
282    * DOCUMENT ME!\r
283    *\r
284    * @param g DOCUMENT ME!\r
285    * @param startRes DOCUMENT ME!\r
286    * @param endRes DOCUMENT ME!\r
287    */\r
288   public void drawComponent(Graphics g, int startRes, int endRes)\r
289   {\r
290     g.setFont(av.getFont());\r
291 \r
292     g.setColor(Color.white);\r
293     g.fillRect(0, 0, (endRes - startRes) * av.charWidth, getSize().height);\r
294 \r
295     if (fm == null)\r
296     {\r
297       fm = g.getFontMetrics();\r
298     }\r
299 \r
300     if ( (av.alignment.getAlignmentAnnotation() == null) ||\r
301         (av.alignment.getAlignmentAnnotation().length < 1))\r
302     {\r
303       g.setColor(Color.white);\r
304       g.fillRect(0, 0, getSize().width, getSize().height);\r
305       g.setColor(Color.black);\r
306       if (av.validCharWidth)\r
307       {\r
308         g.drawString("Alignment has no annotations", 20, 15);\r
309       }\r
310 \r
311       return;\r
312     }\r
313 \r
314     AlignmentAnnotation[] aa = av.alignment.getAlignmentAnnotation();\r
315 \r
316     int x = 0;\r
317     int y = 0;\r
318     int column = 0;\r
319     char lastSS;\r
320     int lastSSX;\r
321     int iconOffset = av.charHeight / 2;\r
322     boolean validRes = false;\r
323 \r
324     boolean[] graphGroupDrawn = new boolean[aa.length];\r
325 \r
326     //\u03B2 \u03B1\r
327     for (int i = 0; i < aa.length; i++)\r
328     {\r
329       AlignmentAnnotation row = aa[i];\r
330 \r
331       if (!row.visible)\r
332       {\r
333         continue;\r
334       }\r
335 \r
336       lastSS = ' ';\r
337       lastSSX = 0;\r
338 \r
339       if (row.graph > 0)\r
340       {\r
341         if (row.graphGroup > -1 && graphGroupDrawn[row.graphGroup])\r
342         {\r
343           continue;\r
344         }\r
345 \r
346         // this is so that we draw the characters below the graph\r
347         y += row.height;\r
348 \r
349         if (row.hasText)\r
350         {\r
351           y -= av.charHeight;\r
352         }\r
353       }\r
354 \r
355       if (row.hasText)\r
356       {\r
357         iconOffset = av.charHeight / 2;\r
358       }\r
359       else\r
360       {\r
361         iconOffset = 0;\r
362       }\r
363 \r
364       x = 0;\r
365       while (x < endRes - startRes)\r
366       {\r
367         if (av.hasHiddenColumns)\r
368         {\r
369           column = av.getColumnSelection().adjustForHiddenColumns(startRes + x);\r
370           if (column > row.annotations.length - 1)\r
371           {\r
372             break;\r
373           }\r
374         }\r
375         else\r
376         {\r
377           column = startRes + x;\r
378         }\r
379 \r
380         if ( (row.annotations.length <= column) ||\r
381             (row.annotations[column] == null))\r
382         {\r
383           validRes = false;\r
384         }\r
385         else\r
386         {\r
387           validRes = true;\r
388         }\r
389 \r
390         if (av.validCharWidth && validRes &&\r
391             (row.annotations[column].displayCharacter.length() > 0))\r
392         {\r
393           int charOffset = (av.charWidth -\r
394                             fm.charWidth(row.annotations[column].\r
395                                          displayCharacter.charAt(\r
396                                              0))) / 2;\r
397           g.setColor(row.annotations[column].colour);\r
398 \r
399           if (column == 0 || row.graph > 0)\r
400           {\r
401             g.drawString(row.annotations[column].displayCharacter,\r
402                          (x * av.charWidth) + charOffset,\r
403                          y + iconOffset + 3);\r
404           }\r
405           else if (\r
406               row.annotations[column - 1] == null\r
407               || (!row.annotations[column].displayCharacter.equals(\r
408                   row.annotations[column - 1].displayCharacter)\r
409                   ||\r
410                   (row.annotations[column].displayCharacter.length() < 2 &&\r
411                    row.annotations[column].secondaryStructure == ' ')))\r
412           {\r
413             g.drawString(row.annotations[column].displayCharacter,\r
414                          (x * av.charWidth) + charOffset,\r
415                          y + iconOffset + 3);\r
416           }\r
417         }\r
418 \r
419         if (row.hasIcons)\r
420         {\r
421           if (!validRes ||\r
422               (row.annotations[column].secondaryStructure != lastSS))\r
423           {\r
424             switch (lastSS)\r
425             {\r
426               case 'H':\r
427                 g.setColor(HELIX_COLOUR);\r
428                 if (MAC)\r
429                 {\r
430                   //Off by 1 offset when drawing rects and ovals\r
431                   //to offscreen image on the MAC\r
432                   g.fillRoundRect(lastSSX, y + 4 + iconOffset,\r
433                                   (x * av.charWidth) - lastSSX, 7, 8, 8);\r
434                   break;\r
435                 }\r
436 \r
437                 int sCol = (lastSSX / av.charWidth) + startRes;\r
438                 int x1 = lastSSX;\r
439                 int x2 = (x * av.charWidth);\r
440 \r
441                 if (sCol == 0 ||\r
442                     row.annotations[sCol - 1] == null ||\r
443                     row.annotations[sCol - 1].secondaryStructure != 'H')\r
444                 {\r
445                   g.fillArc(lastSSX, y + 4 + iconOffset, av.charWidth, 8, 90,\r
446                             180);\r
447                   x1 += av.charWidth / 2;\r
448                 }\r
449 \r
450                 if (row.annotations[column] == null ||\r
451                     row.annotations[column].secondaryStructure != 'H')\r
452                 {\r
453                   g.fillArc( (x * av.charWidth) - av.charWidth,\r
454                             y + 4 + iconOffset, av.charWidth, 8, 270, 180);\r
455                   x2 -= av.charWidth / 2;\r
456                 }\r
457 \r
458                 g.fillRect(x1, y + 4 + iconOffset, x2 - x1, 8);\r
459                 break;\r
460 \r
461               case 'E':\r
462                 g.setColor(SHEET_COLOUR);\r
463                 g.fillRect(lastSSX, y + 4 + iconOffset,\r
464                            (x * av.charWidth) - lastSSX - 4, 7);\r
465                 g.fillPolygon(new int[]\r
466                               { (x * av.charWidth) - 4,\r
467                               (x * av.charWidth) - 4,\r
468                               (x * av.charWidth)},\r
469                               new int[]\r
470                               {\r
471                               y + iconOffset, y + 14 + iconOffset,\r
472                               y + 8 + iconOffset\r
473                 }, 3);\r
474 \r
475                 break;\r
476 \r
477               default:\r
478                 g.setColor(Color.gray);\r
479                 g.fillRect(lastSSX, y + 6 + iconOffset,\r
480                            (x * av.charWidth) - lastSSX, 2);\r
481 \r
482                 break;\r
483             }\r
484 \r
485             if (validRes)\r
486             {\r
487               lastSS = row.annotations[column].secondaryStructure;\r
488             }\r
489             else\r
490             {\r
491               lastSS = ' ';\r
492             }\r
493 \r
494             lastSSX = (x * av.charWidth);\r
495           }\r
496         }\r
497 \r
498         column++;\r
499         x++;\r
500       }\r
501 \r
502       if (column >= row.annotations.length)\r
503       {\r
504         column = row.annotations.length - 1;\r
505       }\r
506 \r
507       //  x ++;\r
508 \r
509       if (row.hasIcons)\r
510       {\r
511         switch (lastSS)\r
512         {\r
513           case 'H':\r
514             g.setColor(HELIX_COLOUR);\r
515             if (MAC)\r
516             {\r
517               //Off by 1 offset when drawing rects and ovals\r
518               //to offscreen image on the MAC\r
519               g.fillRoundRect(lastSSX, y + 4 + iconOffset,\r
520                               (x * av.charWidth) - lastSSX, 7, 8, 8);\r
521               break;\r
522             }\r
523 \r
524             int sCol = (lastSSX / av.charWidth) + startRes;\r
525             int x1 = lastSSX;\r
526             int x2 = (x * av.charWidth);\r
527 \r
528             if (sCol == 0 ||\r
529                 row.annotations[sCol - 1] == null ||\r
530                 row.annotations[sCol - 1].secondaryStructure != 'H')\r
531             {\r
532               g.fillArc(lastSSX, y + 4 + iconOffset, av.charWidth, 8, 90, 180);\r
533               x1 += av.charWidth / 2;\r
534             }\r
535 \r
536             if (row.annotations[column] == null ||\r
537                 row.annotations[column].secondaryStructure != 'H')\r
538             {\r
539               g.fillArc( (x * av.charWidth) - av.charWidth,\r
540                         y + 4 + iconOffset, av.charWidth, 8, 270,\r
541                         180);\r
542               x2 -= av.charWidth / 2;\r
543             }\r
544 \r
545             g.fillRect(x1, y + 4 + iconOffset, x2 - x1, 8);\r
546 \r
547             break;\r
548 \r
549           case 'E':\r
550             g.setColor(SHEET_COLOUR);\r
551 \r
552             if (row.annotations[endRes] == null\r
553                 || row.annotations[endRes].secondaryStructure != 'E')\r
554             {\r
555               g.fillRect(lastSSX, y + 4 + iconOffset,\r
556                          (x * av.charWidth) - lastSSX - 4, 7);\r
557               g.fillPolygon(new int[]\r
558                             { (x * av.charWidth) - 4,\r
559                             (x * av.charWidth) - 4,\r
560                             (x * av.charWidth)},\r
561                             new int[]\r
562                             {\r
563                             y + iconOffset, y + 14 + iconOffset,\r
564                             y + 7 + iconOffset\r
565               }, 3);\r
566             }\r
567             else\r
568             {\r
569               g.fillRect(lastSSX, y + 4 + iconOffset,\r
570                          x * av.charWidth - lastSSX, 7);\r
571             }\r
572             break;\r
573 \r
574           default:\r
575             g.setColor(Color.gray);\r
576             if (!av.wrapAlignment || endRes == av.endRes)\r
577             {\r
578               g.fillRect(lastSSX, y + 6 + iconOffset,\r
579                          (x * av.charWidth) - lastSSX, 2);\r
580             }\r
581 \r
582             break;\r
583         }\r
584       }\r
585 \r
586       if (row.graph > 0)\r
587       {\r
588         if (row.graph == AlignmentAnnotation.LINE_GRAPH)\r
589         {\r
590           if (row.graphGroup > -1 && !graphGroupDrawn[row.graphGroup])\r
591           {\r
592             float groupmax = -999999, groupmin = 9999999;\r
593             for (int gg = 0; gg < aa.length; gg++)\r
594             {\r
595               if (aa[gg].graphGroup != row.graphGroup)\r
596               {\r
597                 continue;\r
598               }\r
599 \r
600               if (aa[gg] != row)\r
601               {\r
602                 aa[gg].visible = false;\r
603               }\r
604 \r
605               if (aa[gg].graphMax > groupmax)\r
606               {\r
607                 groupmax = aa[gg].graphMax;\r
608               }\r
609               if (aa[gg].graphMin < groupmin)\r
610               {\r
611                 groupmin = aa[gg].graphMin;\r
612               }\r
613             }\r
614 \r
615             for (int gg = 0; gg < aa.length; gg++)\r
616             {\r
617               if (aa[gg].graphGroup == row.graphGroup)\r
618               {\r
619                 drawLineGraph(g, aa[gg], startRes, endRes, y,\r
620                               groupmin, groupmax,\r
621                               row.graphHeight);\r
622               }\r
623             }\r
624 \r
625             graphGroupDrawn[row.graphGroup] = true;\r
626           }\r
627           else\r
628           {\r
629             drawLineGraph(g, row, startRes, endRes,\r
630                           y, row.graphMin, row.graphMax, row.graphHeight);\r
631           }\r
632         }\r
633         else if (row.graph == AlignmentAnnotation.BAR_GRAPH)\r
634         {\r
635           drawBarGraph(g, row, startRes, endRes,\r
636                        row.graphMin, row.graphMax, y);\r
637         }\r
638       }\r
639 \r
640       if (row.graph > 0 && row.hasText)\r
641       {\r
642         y += av.charHeight;\r
643       }\r
644 \r
645       if (row.graph == 0)\r
646       {\r
647         y += aa[i].height;\r
648       }\r
649     }\r
650   }\r
651 \r
652   public void drawLineGraph(Graphics g, AlignmentAnnotation aa,\r
653                             int sRes, int eRes,\r
654                             int y,\r
655                             float min, float max,\r
656                             int graphHeight)\r
657   {\r
658     if (sRes > aa.annotations.length)\r
659     {\r
660       return;\r
661     }\r
662 \r
663     int x = 0;\r
664 \r
665     //Adjustment for fastpaint to left\r
666     if (eRes < av.endRes)\r
667     {\r
668       eRes++;\r
669     }\r
670 \r
671     eRes = Math.min(eRes, aa.annotations.length);\r
672 \r
673     if (sRes == 0)\r
674     {\r
675       sRes++;\r
676       x += av.charWidth;\r
677     }\r
678 \r
679     int y1 = y, y2 = y;\r
680     float range = max - min;\r
681 \r
682     ////Draw origin\r
683     if (min < 0)\r
684     {\r
685       y2 = y - (int) ( (0 - min / range) * graphHeight);\r
686     }\r
687 \r
688     g.setColor(Color.gray);\r
689     g.drawLine(x - av.charWidth, y2, (eRes - sRes) * av.charWidth, y2);\r
690 \r
691     eRes = Math.min(eRes, aa.annotations.length);\r
692 \r
693     int column;\r
694     int aaMax = aa.annotations.length - 1;\r
695 \r
696     while (x < eRes - sRes)\r
697     {\r
698       column = sRes + x;\r
699       if (av.hasHiddenColumns)\r
700       {\r
701         column = av.getColumnSelection().adjustForHiddenColumns(column);\r
702       }\r
703 \r
704       if (column > aaMax)\r
705       {\r
706         break;\r
707       }\r
708 \r
709       if (aa.annotations[column] == null || aa.annotations[column - 1] == null)\r
710       {\r
711         x++;\r
712         continue;\r
713       }\r
714 \r
715       g.setColor(aa.annotations[column].colour);\r
716       y1 = y -\r
717           (int) ( ( (aa.annotations[column - 1].value - min) / range) * graphHeight);\r
718       y2 = y -\r
719           (int) ( ( (aa.annotations[column].value - min) / range) * graphHeight);\r
720 \r
721       g.drawLine(x * av.charWidth - av.charWidth / 2, y1,\r
722                  x * av.charWidth + av.charWidth / 2, y2);\r
723       x++;\r
724     }\r
725 \r
726     if (aa.threshold != null)\r
727     {\r
728       g.setColor(aa.threshold.colour);\r
729 \r
730       y2 = (int) (y - ( (aa.threshold.value - min) / range) * graphHeight);\r
731       g.drawLine(0, y2, (eRes - sRes) * av.charWidth, y2);\r
732     }\r
733   }\r
734 \r
735   public void drawBarGraph(Graphics g, AlignmentAnnotation aa,\r
736                            int sRes, int eRes,\r
737                            float min, float max,\r
738                            int y)\r
739   {\r
740     if (sRes > aa.annotations.length)\r
741     {\r
742       return;\r
743     }\r
744 \r
745     eRes = Math.min(eRes, aa.annotations.length);\r
746 \r
747     int x = 0, y1 = y, y2 = y;\r
748 \r
749     float range = max - min;\r
750 \r
751     if (min < 0)\r
752     {\r
753       y2 = y - (int) ( (0 - min / (range)) * aa.graphHeight);\r
754     }\r
755 \r
756     g.setColor(Color.gray);\r
757 \r
758     g.drawLine(x, y2, (eRes - sRes) * av.charWidth, y2);\r
759 \r
760     int column;\r
761     int aaMax = aa.annotations.length - 1;\r
762 \r
763     while (x < eRes - sRes)\r
764     {\r
765       column = sRes + x;\r
766       if (av.hasHiddenColumns)\r
767       {\r
768         column = av.getColumnSelection().adjustForHiddenColumns(column);\r
769       }\r
770 \r
771       if (column > aaMax)\r
772       {\r
773         break;\r
774       }\r
775 \r
776       if (aa.annotations[column] == null)\r
777       {\r
778         x++;\r
779         continue;\r
780       }\r
781 \r
782       g.setColor(aa.annotations[column].colour);\r
783       y1 = y -\r
784           (int) ( ( (aa.annotations[column].value - min) / (range)) * aa.graphHeight);\r
785 \r
786       if (y1 - y2 > 0)\r
787       {\r
788         g.fillRect(x * av.charWidth, y2, av.charWidth, y1 - y2);\r
789       }\r
790       else\r
791       {\r
792         g.fillRect(x * av.charWidth, y1, av.charWidth, y2 - y1);\r
793       }\r
794 \r
795       x++;\r
796 \r
797     }\r
798     if (aa.threshold != null)\r
799     {\r
800       g.setColor(aa.threshold.colour);\r
801       y2 = (int) (y - ( (aa.threshold.value - min) / range) * aa.graphHeight);\r
802       g.drawLine(0, y2, (eRes - sRes) * av.charWidth, y2);\r
803     }\r
804   }\r
805 \r
806   // used by overview window\r
807   public void drawGraph(Graphics g, AlignmentAnnotation aa, int width, int y,\r
808                         int sRes, int eRes)\r
809   {\r
810     g.setColor(Color.white);\r
811     g.fillRect(0, 0, width, y);\r
812     g.setColor(new Color(0, 0, 180));\r
813 \r
814     int x = 0, height;\r
815 \r
816     for (int j = sRes; j < eRes; j++)\r
817     {\r
818       g.setColor(aa.annotations[j].colour);\r
819 \r
820       height = (int) ( (aa.annotations[j].value / aa.graphMax) * GRAPH_HEIGHT);\r
821       if (height > y)\r
822       {\r
823         height = y;\r
824       }\r
825       g.fillRect(x, y - height, av.charWidth, height);\r
826       x += av.charWidth;\r
827     }\r
828   }\r
829 }\r