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