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