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