Set black if colour null
[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\r
31     implements AdjustmentListener, ActionListener, MouseListener, MouseMotionListener\r
32 {\r
33   AlignViewport av;\r
34   AlignmentPanel ap;\r
35   int activeRow = -1;\r
36 \r
37   Vector activeRes;\r
38   static String HELIX = "Helix";\r
39   static String SHEET = "Sheet";\r
40   static String LABEL = "Label";\r
41   static String REMOVE = "Remove Annotation";\r
42   static String COLOUR = "Colour";\r
43   static Color HELIX_COLOUR = Color.red.darker();\r
44   static Color SHEET_COLOUR = Color.green.darker().darker();\r
45 \r
46   Image image;\r
47   Graphics gg;\r
48   FontMetrics fm;\r
49   int imgWidth = 0;\r
50 \r
51   boolean fastPaint = false;\r
52 \r
53   public static int GRAPH_HEIGHT = 40;\r
54 \r
55   boolean MAC = false;\r
56 \r
57   public AnnotationPanel(AlignmentPanel ap)\r
58   {\r
59     if (System.getProperty("os.name").startsWith("Mac"))\r
60     {\r
61       MAC = true;\r
62     }\r
63 \r
64     this.ap = ap;\r
65     av = ap.av;\r
66     setLayout(null);\r
67     adjustPanelHeight();\r
68 \r
69     addMouseMotionListener(this);\r
70 \r
71     addMouseListener(this);\r
72 \r
73 \r
74     // ap.annotationScroller.getVAdjustable().addAdjustmentListener( this );\r
75   }\r
76 \r
77   public AnnotationPanel(AlignViewport av)\r
78   {\r
79     this.av = av;\r
80   }\r
81 \r
82   public void adjustmentValueChanged(AdjustmentEvent evt)\r
83   {\r
84     ap.alabels.setScrollOffset( -evt.getValue());\r
85   }\r
86 \r
87   /**\r
88    * DOCUMENT ME!\r
89    *\r
90    * @param evt DOCUMENT ME!\r
91    */\r
92   public void actionPerformed(ActionEvent evt)\r
93   {\r
94     AlignmentAnnotation[] aa = av.alignment.getAlignmentAnnotation();\r
95     Annotation[] anot = aa[activeRow].annotations;\r
96 \r
97     if (anot.length < av.getColumnSelection().getMax())\r
98     {\r
99       Annotation[] temp = new Annotation[av.getColumnSelection().getMax() + 2];\r
100       System.arraycopy(anot, 0, temp, 0, anot.length);\r
101       anot = temp;\r
102       aa[activeRow].annotations = anot;\r
103     }\r
104 \r
105     String label = "";\r
106     if (av.colSel != null && av.colSel.size() > 0\r
107         && anot[av.colSel.getMin()] != null)\r
108       label = anot[av.getColumnSelection().getMin()].displayCharacter;\r
109 \r
110 \r
111     if (evt.getActionCommand().equals(REMOVE))\r
112     {\r
113       for (int i = 0; i < av.getColumnSelection().size(); i++)\r
114       {\r
115         anot[av.getColumnSelection().columnAt(i)] = null;\r
116       }\r
117     }\r
118     else if (evt.getActionCommand().equals(LABEL))\r
119     {\r
120       label = enterLabel(label, "Enter Label");\r
121 \r
122       if (label == null)\r
123       {\r
124         return;\r
125       }\r
126 \r
127       if ( (label.length() > 0) && !aa[activeRow].hasText)\r
128       {\r
129         aa[activeRow].hasText = true;\r
130       }\r
131 \r
132       for (int i = 0; i < av.getColumnSelection().size(); i++)\r
133       {\r
134         int index = av.getColumnSelection().columnAt(i);\r
135 \r
136         if(!av.colSel.isVisible(index))\r
137           continue;\r
138 \r
139         if (anot[index] == null)\r
140         {\r
141           anot[index] = new Annotation(label, "", ' ', 0);\r
142         }\r
143 \r
144         anot[index].displayCharacter = label;\r
145       }\r
146     }\r
147     else if (evt.getActionCommand().equals(COLOUR))\r
148     {\r
149       UserDefinedColours udc = new UserDefinedColours(\r
150           this,\r
151          Color.black, ap.alignFrame);\r
152 \r
153       Color col = udc.getColor();\r
154 \r
155       for (int i = 0; i < av.getColumnSelection().size(); i++)\r
156       {\r
157         int index = av.getColumnSelection().columnAt(i);\r
158 \r
159         if(!av.colSel.isVisible(index))\r
160           continue;\r
161 \r
162         if (anot[index] == null)\r
163         {\r
164           anot[index] = new Annotation("", "", ' ', 0);\r
165         }\r
166 \r
167         anot[index].colour = col;\r
168       }\r
169     }\r
170     else // HELIX OR SHEET\r
171     {\r
172       char type = 0;\r
173       String symbol = "\u03B1";\r
174 \r
175       if (evt.getActionCommand().equals(HELIX))\r
176       {\r
177         type = 'H';\r
178       }\r
179       else if (evt.getActionCommand().equals(SHEET))\r
180       {\r
181         type = 'E';\r
182         symbol = "\u03B2";\r
183       }\r
184 \r
185       if (!aa[activeRow].hasIcons)\r
186       {\r
187         aa[activeRow].hasIcons = true;\r
188       }\r
189 \r
190       label = enterLabel(symbol, "Enter Label");\r
191 \r
192       if (label == null)\r
193       {\r
194         return;\r
195       }\r
196 \r
197       if ( (label.length() > 0) && !aa[activeRow].hasText)\r
198       {\r
199         aa[activeRow].hasText = true;\r
200       }\r
201 \r
202       for (int i = 0; i < av.getColumnSelection().size(); i++)\r
203       {\r
204         int index = av.getColumnSelection().columnAt(i);\r
205 \r
206         if(!av.colSel.isVisible(index))\r
207           continue;\r
208 \r
209         if (anot[index] == null)\r
210         {\r
211           anot[index] = new Annotation(label, "", type, 0);\r
212         }\r
213 \r
214         anot[index].secondaryStructure = type;\r
215         anot[index].displayCharacter = label;\r
216       }\r
217     }\r
218 \r
219     adjustPanelHeight();\r
220     repaint();\r
221 \r
222     return;\r
223   }\r
224 \r
225   String enterLabel(String text, String label)\r
226   {\r
227     EditNameDialog dialog = new EditNameDialog(text,null,label,null,\r
228         ap.alignFrame,"Enter Label", 400,200);\r
229 \r
230     if(dialog.accept)\r
231       return dialog.getName();\r
232     else\r
233       return null;\r
234   }\r
235 \r
236   public void mousePressed(MouseEvent evt)\r
237   {\r
238       AlignmentAnnotation[] aa = av.alignment.getAlignmentAnnotation();\r
239       if (aa == null)\r
240       {\r
241         return;\r
242       }\r
243 \r
244       int height = 0;\r
245       activeRow = -1;\r
246 \r
247 \r
248       for (int i = 0; i < aa.length; i++)\r
249       {\r
250         if (aa[i].visible)\r
251         {\r
252           height += aa[i].height;\r
253         }\r
254 \r
255         if (evt.getY() < height)\r
256         {\r
257           if (aa[i].editable)\r
258           {\r
259             activeRow = i;\r
260           }\r
261 \r
262           break;\r
263         }\r
264       }\r
265 \r
266       if ( (evt.getModifiers() & InputEvent.BUTTON3_MASK) ==\r
267         InputEvent.BUTTON3_MASK  && activeRow != -1)\r
268       {\r
269         if (av.getColumnSelection() == null)\r
270         {\r
271           return;\r
272         }\r
273 \r
274         PopupMenu pop = new PopupMenu("Structure type");\r
275         MenuItem item = new MenuItem(HELIX);\r
276         item.addActionListener(this);\r
277         pop.add(item);\r
278         item = new MenuItem(SHEET);\r
279         item.addActionListener(this);\r
280         pop.add(item);\r
281         item = new MenuItem(LABEL);\r
282         item.addActionListener(this);\r
283         pop.add(item);\r
284         item = new MenuItem(COLOUR);\r
285         item.addActionListener(this);\r
286         pop.add(item);\r
287         item = new MenuItem(REMOVE);\r
288         item.addActionListener(this);\r
289         pop.add(item);\r
290         ap.alignFrame.add(pop);\r
291         pop.show(this, evt.getX(), evt.getY());\r
292 \r
293         return;\r
294       }\r
295 \r
296       if (aa == null)\r
297       {\r
298         return;\r
299       }\r
300 \r
301       ap.scalePanel.mousePressed(evt);\r
302   }\r
303 \r
304   public void mouseReleased(MouseEvent evt)\r
305   {\r
306     ap.scalePanel.mouseReleased(evt);\r
307   }\r
308 \r
309   public void mouseClicked(MouseEvent evt)\r
310   {}\r
311 \r
312   public void mouseDragged(MouseEvent evt)\r
313   {\r
314     ap.scalePanel.mouseDragged(evt);\r
315   }\r
316 \r
317   public void mouseMoved(MouseEvent evt)\r
318   {\r
319     AlignmentAnnotation[] aa = av.alignment.getAlignmentAnnotation();\r
320     if (aa == null)\r
321     {\r
322       return;\r
323     }\r
324 \r
325     int row = -1;\r
326     int height = 0;\r
327     for (int i = 0; i < aa.length; i++)\r
328     {\r
329 \r
330       if (aa[i].visible)\r
331       {\r
332         height += aa[i].height;\r
333       }\r
334 \r
335       if (evt.getY() < height)\r
336       {\r
337         row = i;\r
338         break;\r
339       }\r
340     }\r
341 \r
342     int res = evt.getX() / av.getCharWidth() + av.getStartRes();\r
343 \r
344     if (av.hasHiddenColumns)\r
345     {\r
346       res = av.getColumnSelection().adjustForHiddenColumns(res);\r
347     }\r
348 \r
349     if (row > -1 && res < aa[row].annotations.length && aa[row].annotations[res] != null)\r
350     {\r
351       StringBuffer text = new StringBuffer("Sequence position " + (res + 1));\r
352       if (aa[row].annotations[res].description != null)\r
353       {\r
354         text.append("  " + aa[row].annotations[res].description);\r
355       }\r
356       ap.alignFrame.statusBar.setText(text.toString());\r
357     }\r
358   }\r
359   public void mouseEntered(MouseEvent evt)\r
360   {\r
361     ap.scalePanel.mouseEntered(evt);\r
362   }\r
363   public void mouseExited(MouseEvent evt)\r
364   {\r
365     ap.scalePanel.mouseExited(evt);\r
366   }\r
367 \r
368 \r
369   public int adjustPanelHeight()\r
370   {\r
371     // setHeight of panels\r
372     AlignmentAnnotation[] aa = av.alignment.getAlignmentAnnotation();\r
373 \r
374     int height = 0;\r
375     if (aa != null)\r
376     {\r
377       for (int i = 0; i < aa.length; i++)\r
378       {\r
379         if (!aa[i].visible)\r
380         {\r
381           continue;\r
382         }\r
383 \r
384         aa[i].height = 0;\r
385 \r
386         if (aa[i].hasText)\r
387         {\r
388           aa[i].height += av.charHeight;\r
389         }\r
390         if (aa[i].hasIcons)\r
391         {\r
392           aa[i].height += 16;\r
393         }\r
394 \r
395         if (aa[i].graph > 0)\r
396         {\r
397           aa[i].height += GRAPH_HEIGHT;\r
398         }\r
399 \r
400         if (aa[i].height == 0)\r
401         {\r
402           aa[i].height = 20;\r
403         }\r
404         height += aa[i].height;\r
405       }\r
406     }\r
407     else\r
408     {\r
409       height = 20;\r
410     }\r
411 \r
412     this.setSize(getSize().width, height);\r
413 \r
414     repaint();\r
415 \r
416     return height;\r
417 \r
418   }\r
419 \r
420   public void addEditableColumn(int i)\r
421   {\r
422     if (activeRow == -1)\r
423     {\r
424       AlignmentAnnotation[] aa = av.alignment.getAlignmentAnnotation();\r
425       if (aa == null)\r
426       {\r
427         return;\r
428       }\r
429 \r
430       for (int j = 0; j < aa.length; j++)\r
431       {\r
432         if (aa[j].editable)\r
433         {\r
434           activeRow = j;\r
435           break;\r
436         }\r
437       }\r
438     }\r
439 \r
440     if (activeRes == null)\r
441     {\r
442       activeRes = new Vector();\r
443       activeRes.addElement(String.valueOf(i));\r
444       return;\r
445     }\r
446 \r
447     activeRes.addElement(String.valueOf(i));\r
448   }\r
449 \r
450 \r
451   public void update(Graphics g)\r
452   {\r
453     paint(g);\r
454   }\r
455 \r
456   public void paint(Graphics g)\r
457   {\r
458 \r
459     imgWidth = getSize().width;\r
460     //(av.endRes - av.startRes + 1) * av.charWidth;\r
461 \r
462     if (image == null || imgWidth != image.getWidth(this))\r
463     {\r
464       image = createImage(imgWidth, ap.annotationPanel.getSize().height);\r
465       gg = image.getGraphics();\r
466       gg.setFont(av.getFont());\r
467       fm = gg.getFontMetrics();\r
468       fastPaint = false;\r
469     }\r
470 \r
471     if (fastPaint)\r
472     {\r
473       g.drawImage(image, 0, 0, this);\r
474       fastPaint = false;\r
475       return;\r
476     }\r
477 \r
478     gg.setColor(Color.white);\r
479     gg.fillRect(0, 0, getSize().width, getSize().height);\r
480     drawComponent(gg, av.startRes, av.endRes + 1);\r
481 \r
482     g.drawImage(image, 0, 0, this);\r
483   }\r
484 \r
485   public void fastPaint(int horizontal)\r
486   {\r
487     if (horizontal == 0\r
488         || av.alignment.getAlignmentAnnotation() == null\r
489         || av.alignment.getAlignmentAnnotation().length < 1\r
490         )\r
491     {\r
492       repaint();\r
493       return;\r
494     }\r
495 \r
496     gg.copyArea(0, 0, imgWidth, getSize().height, -horizontal * av.charWidth, 0);\r
497     int sr = av.startRes, er = av.endRes + 1, transX = 0;\r
498 \r
499     if (horizontal > 0) // scrollbar pulled right, image to the left\r
500     {\r
501       transX = (er - sr - horizontal) * av.charWidth;\r
502       sr = er - horizontal;\r
503     }\r
504     else if (horizontal < 0)\r
505     {\r
506       er = sr - horizontal;\r
507     }\r
508 \r
509     gg.translate(transX, 0);\r
510 \r
511     drawComponent(gg, sr, er);\r
512 \r
513     gg.translate( -transX, 0);\r
514 \r
515     fastPaint = true;\r
516     repaint();\r
517   }\r
518 \r
519   /**\r
520    * DOCUMENT ME!\r
521    *\r
522    * @param g DOCUMENT ME!\r
523    * @param startRes DOCUMENT ME!\r
524    * @param endRes DOCUMENT ME!\r
525    */\r
526   public void drawComponent(Graphics g, int startRes, int endRes)\r
527   {\r
528     g.setFont(av.getFont());\r
529 \r
530     g.setColor(Color.white);\r
531     g.fillRect(0, 0, (endRes - startRes) * av.charWidth, getSize().height);\r
532 \r
533     if (fm == null)\r
534     {\r
535       fm = g.getFontMetrics();\r
536     }\r
537 \r
538     if ( (av.alignment.getAlignmentAnnotation() == null) ||\r
539         (av.alignment.getAlignmentAnnotation().length < 1))\r
540     {\r
541       g.setColor(Color.white);\r
542       g.fillRect(0, 0, getSize().width, getSize().height);\r
543       g.setColor(Color.black);\r
544       if (av.validCharWidth)\r
545       {\r
546         g.drawString("Alignment has no annotations", 20, 15);\r
547       }\r
548 \r
549       return;\r
550     }\r
551 \r
552     AlignmentAnnotation[] aa = av.alignment.getAlignmentAnnotation();\r
553 \r
554     int x = 0;\r
555     int y = 0;\r
556     int column = 0;\r
557     char lastSS;\r
558     int lastSSX;\r
559     int iconOffset = av.charHeight / 2;\r
560     boolean validRes = false;\r
561 \r
562     boolean[] graphGroupDrawn = new boolean[aa.length];\r
563 \r
564     //\u03B2 \u03B1\r
565     for (int i = 0; i < aa.length; i++)\r
566     {\r
567       AlignmentAnnotation row = aa[i];\r
568 \r
569       if (!row.visible)\r
570       {\r
571         continue;\r
572       }\r
573 \r
574       lastSS = ' ';\r
575       lastSSX = 0;\r
576 \r
577       if (row.graph > 0)\r
578       {\r
579         if (row.graphGroup > -1 && graphGroupDrawn[row.graphGroup])\r
580         {\r
581           continue;\r
582         }\r
583 \r
584         // this is so that we draw the characters below the graph\r
585         y += row.height;\r
586 \r
587         if (row.hasText)\r
588         {\r
589           y -= av.charHeight;\r
590         }\r
591       }\r
592 \r
593       if (row.hasText)\r
594       {\r
595         iconOffset = av.charHeight / 2;\r
596       }\r
597       else\r
598       {\r
599         iconOffset = 0;\r
600       }\r
601 \r
602       x = 0;\r
603       while (x < endRes - startRes)\r
604       {\r
605         if (av.hasHiddenColumns)\r
606         {\r
607           column = av.getColumnSelection().adjustForHiddenColumns(startRes + x);\r
608           if (column > row.annotations.length - 1)\r
609           {\r
610             break;\r
611           }\r
612         }\r
613         else\r
614         {\r
615           column = startRes + x;\r
616         }\r
617 \r
618         if ( (row.annotations.length <= column) ||\r
619             (row.annotations[column] == null))\r
620         {\r
621           validRes = false;\r
622         }\r
623         else\r
624         {\r
625           validRes = true;\r
626         }\r
627 \r
628         if (activeRow == i)\r
629         {\r
630           g.setColor(Color.red);\r
631 \r
632           if (av.getColumnSelection() != null)\r
633           {\r
634             for (int n = 0; n < av.getColumnSelection().size(); n++)\r
635             {\r
636               int v = av.getColumnSelection().columnAt(n);\r
637 \r
638               if (v == column)\r
639               {\r
640                 g.fillRect(x * av.charWidth, y,\r
641                            av.charWidth, av.charHeight);\r
642               }\r
643             }\r
644           }\r
645         }\r
646 \r
647 \r
648 \r
649         if (av.validCharWidth && validRes &&\r
650             (row.annotations[column].displayCharacter.length() > 0))\r
651         {\r
652           int charOffset = (av.charWidth -\r
653                             fm.charWidth(row.annotations[column].\r
654                                          displayCharacter.charAt(\r
655                                              0))) / 2;\r
656 \r
657           if (row.annotations[column].colour == null)\r
658             g.setColor(Color.black);\r
659           else\r
660             g.setColor(row.annotations[column].colour);\r
661 \r
662           if (column == 0 || row.graph > 0)\r
663           {\r
664             g.drawString(row.annotations[column].displayCharacter,\r
665                          (x * av.charWidth) + charOffset,\r
666                          y + iconOffset + 3);\r
667           }\r
668           else if (\r
669               row.annotations[column - 1] == null\r
670               || (!row.annotations[column].displayCharacter.equals(\r
671                   row.annotations[column - 1].displayCharacter)\r
672                   ||\r
673                   (row.annotations[column].displayCharacter.length() < 2 &&\r
674                    row.annotations[column].secondaryStructure == ' ')))\r
675           {\r
676             g.drawString(row.annotations[column].displayCharacter,\r
677                          (x * av.charWidth) + charOffset,\r
678                          y + iconOffset + 3);\r
679           }\r
680         }\r
681 \r
682         if (row.hasIcons)\r
683         {\r
684           if (!validRes ||\r
685               (row.annotations[column].secondaryStructure != lastSS))\r
686           {\r
687             switch (lastSS)\r
688             {\r
689               case 'H':\r
690                 g.setColor(HELIX_COLOUR);\r
691                 if (MAC)\r
692                 {\r
693                   //Off by 1 offset when drawing rects and ovals\r
694                   //to offscreen image on the MAC\r
695                   g.fillRoundRect(lastSSX, y + 4 + iconOffset,\r
696                                   (x * av.charWidth) - lastSSX, 7, 8, 8);\r
697                   break;\r
698                 }\r
699 \r
700                 int sCol = (lastSSX / av.charWidth) + startRes;\r
701                 int x1 = lastSSX;\r
702                 int x2 = (x * av.charWidth);\r
703 \r
704                 if (sCol == 0 ||\r
705                     row.annotations[sCol - 1] == null ||\r
706                     row.annotations[sCol - 1].secondaryStructure != 'H')\r
707                 {\r
708                   g.fillArc(lastSSX, y + 4 + iconOffset, av.charWidth, 8, 90,\r
709                             180);\r
710                   x1 += av.charWidth / 2;\r
711                 }\r
712 \r
713                 if (row.annotations[column] == null ||\r
714                     row.annotations[column].secondaryStructure != 'H')\r
715                 {\r
716                   g.fillArc( (x * av.charWidth) - av.charWidth,\r
717                             y + 4 + iconOffset, av.charWidth, 8, 270, 180);\r
718                   x2 -= av.charWidth / 2;\r
719                 }\r
720 \r
721                 g.fillRect(x1, y + 4 + iconOffset, x2 - x1, 8);\r
722                 break;\r
723 \r
724               case 'E':\r
725                 g.setColor(SHEET_COLOUR);\r
726                 g.fillRect(lastSSX, y + 4 + iconOffset,\r
727                            (x * av.charWidth) - lastSSX - 4, 7);\r
728                 g.fillPolygon(new int[]\r
729                               { (x * av.charWidth) - 4,\r
730                               (x * av.charWidth) - 4,\r
731                               (x * av.charWidth)},\r
732                               new int[]\r
733                               {\r
734                               y + iconOffset, y + 14 + iconOffset,\r
735                               y + 8 + iconOffset\r
736                 }, 3);\r
737 \r
738                 break;\r
739 \r
740               default:\r
741                 g.setColor(Color.gray);\r
742                 g.fillRect(lastSSX, y + 6 + iconOffset,\r
743                            (x * av.charWidth) - lastSSX, 2);\r
744 \r
745                 break;\r
746             }\r
747 \r
748             if (validRes)\r
749             {\r
750               lastSS = row.annotations[column].secondaryStructure;\r
751             }\r
752             else\r
753             {\r
754               lastSS = ' ';\r
755             }\r
756 \r
757             lastSSX = (x * av.charWidth);\r
758           }\r
759         }\r
760 \r
761         column++;\r
762         x++;\r
763       }\r
764 \r
765       if (column >= row.annotations.length)\r
766       {\r
767         column = row.annotations.length - 1;\r
768       }\r
769 \r
770       //  x ++;\r
771 \r
772       if (row.hasIcons)\r
773       {\r
774         switch (lastSS)\r
775         {\r
776           case 'H':\r
777             g.setColor(HELIX_COLOUR);\r
778             if (MAC)\r
779             {\r
780               //Off by 1 offset when drawing rects and ovals\r
781               //to offscreen image on the MAC\r
782               g.fillRoundRect(lastSSX, y + 4 + iconOffset,\r
783                               (x * av.charWidth) - lastSSX, 7, 8, 8);\r
784               break;\r
785             }\r
786 \r
787             int sCol = (lastSSX / av.charWidth) + startRes;\r
788             int x1 = lastSSX;\r
789             int x2 = (x * av.charWidth);\r
790 \r
791             if (sCol == 0 ||\r
792                 row.annotations[sCol - 1] == null ||\r
793                 row.annotations[sCol - 1].secondaryStructure != 'H')\r
794             {\r
795               g.fillArc(lastSSX, y + 4 + iconOffset, av.charWidth, 8, 90, 180);\r
796               x1 += av.charWidth / 2;\r
797             }\r
798 \r
799             if (row.annotations[column] == null ||\r
800                 row.annotations[column].secondaryStructure != 'H')\r
801             {\r
802               g.fillArc( (x * av.charWidth) - av.charWidth,\r
803                         y + 4 + iconOffset, av.charWidth, 8, 270,\r
804                         180);\r
805               x2 -= av.charWidth / 2;\r
806             }\r
807 \r
808             g.fillRect(x1, y + 4 + iconOffset, x2 - x1, 8);\r
809 \r
810             break;\r
811 \r
812           case 'E':\r
813             g.setColor(SHEET_COLOUR);\r
814 \r
815             if (row.annotations[endRes] == null\r
816                 || row.annotations[endRes].secondaryStructure != 'E')\r
817             {\r
818               g.fillRect(lastSSX, y + 4 + iconOffset,\r
819                          (x * av.charWidth) - lastSSX - 4, 7);\r
820               g.fillPolygon(new int[]\r
821                             { (x * av.charWidth) - 4,\r
822                             (x * av.charWidth) - 4,\r
823                             (x * av.charWidth)},\r
824                             new int[]\r
825                             {\r
826                             y + iconOffset, y + 14 + iconOffset,\r
827                             y + 7 + iconOffset\r
828               }, 3);\r
829             }\r
830             else\r
831             {\r
832               g.fillRect(lastSSX, y + 4 + iconOffset,\r
833                          x * av.charWidth - lastSSX, 7);\r
834             }\r
835             break;\r
836 \r
837           default:\r
838             g.setColor(Color.gray);\r
839             if (!av.wrapAlignment || endRes == av.endRes)\r
840             {\r
841               g.fillRect(lastSSX, y + 6 + iconOffset,\r
842                          (x * av.charWidth) - lastSSX, 2);\r
843             }\r
844 \r
845             break;\r
846         }\r
847       }\r
848 \r
849       if (row.graph > 0)\r
850       {\r
851         if (row.graph == AlignmentAnnotation.LINE_GRAPH)\r
852         {\r
853           if (row.graphGroup > -1 && !graphGroupDrawn[row.graphGroup])\r
854           {\r
855             float groupmax = -999999, groupmin = 9999999;\r
856             for (int gg = 0; gg < aa.length; gg++)\r
857             {\r
858               if (aa[gg].graphGroup != row.graphGroup)\r
859               {\r
860                 continue;\r
861               }\r
862 \r
863               if (aa[gg] != row)\r
864               {\r
865                 aa[gg].visible = false;\r
866               }\r
867 \r
868               if (aa[gg].graphMax > groupmax)\r
869               {\r
870                 groupmax = aa[gg].graphMax;\r
871               }\r
872               if (aa[gg].graphMin < groupmin)\r
873               {\r
874                 groupmin = aa[gg].graphMin;\r
875               }\r
876             }\r
877 \r
878             for (int gg = 0; gg < aa.length; gg++)\r
879             {\r
880               if (aa[gg].graphGroup == row.graphGroup)\r
881               {\r
882                 drawLineGraph(g, aa[gg], startRes, endRes, y,\r
883                               groupmin, groupmax,\r
884                               row.graphHeight);\r
885               }\r
886             }\r
887 \r
888             graphGroupDrawn[row.graphGroup] = true;\r
889           }\r
890           else\r
891           {\r
892             drawLineGraph(g, row, startRes, endRes,\r
893                           y, row.graphMin, row.graphMax, row.graphHeight);\r
894           }\r
895         }\r
896         else if (row.graph == AlignmentAnnotation.BAR_GRAPH)\r
897         {\r
898           drawBarGraph(g, row, startRes, endRes,\r
899                        row.graphMin, row.graphMax, y);\r
900         }\r
901       }\r
902 \r
903       if (row.graph > 0 && row.hasText)\r
904       {\r
905         y += av.charHeight;\r
906       }\r
907 \r
908       if (row.graph == 0)\r
909       {\r
910         y += aa[i].height;\r
911       }\r
912     }\r
913   }\r
914 \r
915   public void drawLineGraph(Graphics g, AlignmentAnnotation aa,\r
916                             int sRes, int eRes,\r
917                             int y,\r
918                             float min, float max,\r
919                             int graphHeight)\r
920   {\r
921     if (sRes > aa.annotations.length)\r
922     {\r
923       return;\r
924     }\r
925 \r
926     int x = 0;\r
927 \r
928     //Adjustment for fastpaint to left\r
929     if (eRes < av.endRes)\r
930     {\r
931       eRes++;\r
932     }\r
933 \r
934     eRes = Math.min(eRes, aa.annotations.length);\r
935 \r
936     if (sRes == 0)\r
937     {\r
938       sRes++;\r
939       x += av.charWidth;\r
940     }\r
941 \r
942     int y1 = y, y2 = y;\r
943     float range = max - min;\r
944 \r
945     ////Draw origin\r
946     if (min < 0)\r
947     {\r
948       y2 = y - (int) ( (0 - min / range) * graphHeight);\r
949     }\r
950 \r
951     g.setColor(Color.gray);\r
952     g.drawLine(x - av.charWidth, y2, (eRes - sRes) * av.charWidth, y2);\r
953 \r
954     eRes = Math.min(eRes, aa.annotations.length);\r
955 \r
956     int column;\r
957     int aaMax = aa.annotations.length - 1;\r
958 \r
959     while (x < eRes - sRes)\r
960     {\r
961       column = sRes + x;\r
962       if (av.hasHiddenColumns)\r
963       {\r
964         column = av.getColumnSelection().adjustForHiddenColumns(column);\r
965       }\r
966 \r
967       if (column > aaMax)\r
968       {\r
969         break;\r
970       }\r
971 \r
972       if (aa.annotations[column] == null || aa.annotations[column - 1] == null)\r
973       {\r
974         x++;\r
975         continue;\r
976       }\r
977 \r
978       if (aa.annotations[column].colour == null)\r
979         g.setColor(Color.black);\r
980       else\r
981         g.setColor(aa.annotations[column].colour);\r
982 \r
983       y1 = y -\r
984           (int) ( ( (aa.annotations[column - 1].value - min) / range) * graphHeight);\r
985       y2 = y -\r
986           (int) ( ( (aa.annotations[column].value - min) / range) * graphHeight);\r
987 \r
988       g.drawLine(x * av.charWidth - av.charWidth / 2, y1,\r
989                  x * av.charWidth + av.charWidth / 2, y2);\r
990       x++;\r
991     }\r
992 \r
993     if (aa.threshold != null)\r
994     {\r
995       g.setColor(aa.threshold.colour);\r
996 \r
997       y2 = (int) (y - ( (aa.threshold.value - min) / range) * graphHeight);\r
998       g.drawLine(0, y2, (eRes - sRes) * av.charWidth, y2);\r
999     }\r
1000   }\r
1001 \r
1002   public void drawBarGraph(Graphics g, AlignmentAnnotation aa,\r
1003                            int sRes, int eRes,\r
1004                            float min, float max,\r
1005                            int y)\r
1006   {\r
1007     if (sRes > aa.annotations.length)\r
1008     {\r
1009       return;\r
1010     }\r
1011 \r
1012     eRes = Math.min(eRes, aa.annotations.length);\r
1013 \r
1014     int x = 0, y1 = y, y2 = y;\r
1015 \r
1016     float range = max - min;\r
1017 \r
1018     if (min < 0)\r
1019     {\r
1020       y2 = y - (int) ( (0 - min / (range)) * aa.graphHeight);\r
1021     }\r
1022 \r
1023     g.setColor(Color.gray);\r
1024 \r
1025     g.drawLine(x, y2, (eRes - sRes) * av.charWidth, y2);\r
1026 \r
1027     int column;\r
1028     int aaMax = aa.annotations.length - 1;\r
1029 \r
1030     while (x < eRes - sRes)\r
1031     {\r
1032       column = sRes + x;\r
1033       if (av.hasHiddenColumns)\r
1034       {\r
1035         column = av.getColumnSelection().adjustForHiddenColumns(column);\r
1036       }\r
1037 \r
1038       if (column > aaMax)\r
1039       {\r
1040         break;\r
1041       }\r
1042 \r
1043       if (aa.annotations[column] == null)\r
1044       {\r
1045         x++;\r
1046         continue;\r
1047       }\r
1048 \r
1049       if (aa.annotations[column].colour == null)\r
1050         g.setColor(Color.black);\r
1051       else\r
1052         g.setColor(aa.annotations[column].colour);\r
1053 \r
1054       y1 = y -\r
1055           (int) ( ( (aa.annotations[column].value - min) / (range)) * aa.graphHeight);\r
1056 \r
1057       if (y1 - y2 > 0)\r
1058       {\r
1059         g.fillRect(x * av.charWidth, y2, av.charWidth, y1 - y2);\r
1060       }\r
1061       else\r
1062       {\r
1063         g.fillRect(x * av.charWidth, y1, av.charWidth, y2 - y1);\r
1064       }\r
1065 \r
1066       x++;\r
1067 \r
1068     }\r
1069     if (aa.threshold != null)\r
1070     {\r
1071       g.setColor(aa.threshold.colour);\r
1072       y2 = (int) (y - ( (aa.threshold.value - min) / range) * aa.graphHeight);\r
1073       g.drawLine(0, y2, (eRes - sRes) * av.charWidth, y2);\r
1074     }\r
1075   }\r
1076 \r
1077   // used by overview window\r
1078   public void drawGraph(Graphics g, AlignmentAnnotation aa, int width, int y,\r
1079                         int sRes, int eRes)\r
1080   {\r
1081     g.setColor(Color.white);\r
1082     g.fillRect(0, 0, width, y);\r
1083     g.setColor(new Color(0, 0, 180));\r
1084 \r
1085     int x = 0, height;\r
1086 \r
1087     for (int j = sRes; j < eRes; j++)\r
1088     {\r
1089       if (aa.annotations[j].colour == null)\r
1090         g.setColor(Color.black);\r
1091       else\r
1092         g.setColor(aa.annotations[j].colour);\r
1093 \r
1094       height = (int) ( (aa.annotations[j].value / aa.graphMax) * GRAPH_HEIGHT);\r
1095       if (height > y)\r
1096       {\r
1097         height = y;\r
1098       }\r
1099       g.fillRect(x, y - height, av.charWidth, height);\r
1100       x += av.charWidth;\r
1101     }\r
1102   }\r
1103 }\r