SliderPanel removed
[jalview.git] / src / jalview / gui / AnnotationPanel.java
1 /*\r
2  * Jalview - A Sequence Alignment Editor and Viewer\r
3  * Copyright (C) 2005 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle\r
4  *\r
5  * This program is free software; you can redistribute it and/or\r
6  * modify it under the terms of the GNU General Public License\r
7  * as published by the Free Software Foundation; either version 2\r
8  * of the License, or (at your option) any later version.\r
9  *\r
10  * This program is distributed in the hope that it will be useful,\r
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
13  * GNU General Public License for more details.\r
14  *\r
15  * You should have received a copy of the GNU General Public License\r
16  * along with this program; if not, write to the Free Software\r
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA\r
18  */\r
19 package jalview.gui;\r
20 \r
21 import jalview.datamodel.*;\r
22 \r
23 import java.awt.*;\r
24 import java.awt.event.*;\r
25 import java.awt.image.*;\r
26 \r
27 import java.util.*;\r
28 \r
29 import javax.swing.*;\r
30 \r
31 \r
32 /**\r
33  * DOCUMENT ME!\r
34  *\r
35  * @author $author$\r
36  * @version $Revision$\r
37  */\r
38 public class AnnotationPanel extends JPanel implements MouseListener,\r
39     MouseMotionListener, ActionListener, AdjustmentListener\r
40 {\r
41     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                     //Stretch Graph\r
367                     graphStretch = i;\r
368                     graphStretchY = evt.getY();\r
369                     activeRes = null;\r
370                 }\r
371                 else\r
372                 {\r
373                     activeRes = null;\r
374                 }\r
375 \r
376                 break;\r
377             }\r
378         }\r
379 \r
380         if (SwingUtilities.isRightMouseButton(evt))\r
381         {\r
382             if (activeRes == null)\r
383             {\r
384                 return;\r
385             }\r
386 \r
387             JPopupMenu pop = new JPopupMenu("Structure type");\r
388             JMenuItem item = new JMenuItem(HELIX);\r
389             item.addActionListener(this);\r
390             pop.add(item);\r
391             item = new JMenuItem(SHEET);\r
392             item.addActionListener(this);\r
393             pop.add(item);\r
394             item = new JMenuItem(LABEL);\r
395             item.addActionListener(this);\r
396             pop.add(item);\r
397             item = new JMenuItem(COLOUR);\r
398             item.addActionListener(this);\r
399             pop.add(item);\r
400             item = new JMenuItem(REMOVE);\r
401             item.addActionListener(this);\r
402             pop.add(item);\r
403             pop.show(this, evt.getX(), evt.getY());\r
404 \r
405             return;\r
406         }\r
407 \r
408         if (aa == null)\r
409         {\r
410             return;\r
411         }\r
412 \r
413         int res = (evt.getX() / av.getCharWidth()) + av.getStartRes();\r
414 \r
415         if (evt.isControlDown() || evt.isAltDown())\r
416         {\r
417             addEditableColumn(res);\r
418         }\r
419         else if (evt.isShiftDown())\r
420         {\r
421             if (activeRes == null)\r
422             {\r
423                 activeRes = new Vector();\r
424             }\r
425             else\r
426             {\r
427                 int start = Integer.parseInt(activeRes.get(activeRes.size() -\r
428                             1).toString());\r
429                 int end = res;\r
430 \r
431                 if (end < start)\r
432                 {\r
433                     int temp = end;\r
434                     end = start;\r
435                     start = temp;\r
436                 }\r
437 \r
438                 for (int n = start; n <= end; n++)\r
439                 {\r
440                     addEditableColumn(n);\r
441                 }\r
442             }\r
443         }\r
444         else\r
445         {\r
446             activeRes = new Vector();\r
447             activeRes.addElement(String.valueOf(res));\r
448         }\r
449     }\r
450 \r
451     /**\r
452      * DOCUMENT ME!\r
453      *\r
454      * @param evt DOCUMENT ME!\r
455      */\r
456     public void mouseReleased(MouseEvent evt)\r
457     {\r
458       graphStretch = -1;\r
459       graphStretchY = -1;\r
460     }\r
461 \r
462     /**\r
463      * DOCUMENT ME!\r
464      *\r
465      * @param evt DOCUMENT ME!\r
466      */\r
467     public void mouseEntered(MouseEvent evt)\r
468     {\r
469     }\r
470 \r
471     /**\r
472      * DOCUMENT ME!\r
473      *\r
474      * @param evt DOCUMENT ME!\r
475      */\r
476     public void mouseExited(MouseEvent evt)\r
477     {\r
478     }\r
479 \r
480     /**\r
481      * DOCUMENT ME!\r
482      *\r
483      * @param evt DOCUMENT ME!\r
484      */\r
485     public void mouseDragged(MouseEvent evt)\r
486     {\r
487       if(graphStretch>-1)\r
488       {\r
489         av.alignment.getAlignmentAnnotation()[graphStretch].graphHeight += graphStretchY - evt.getY();\r
490         if(av.alignment.getAlignmentAnnotation()[graphStretch].graphHeight <10)\r
491           av.alignment.getAlignmentAnnotation()[graphStretch].graphHeight = 10;\r
492         graphStretchY = evt.getY();\r
493         adjustPanelHeight();\r
494         ap.repaint();\r
495       }\r
496     }\r
497 \r
498     /**\r
499      * DOCUMENT ME!\r
500      *\r
501      * @param evt DOCUMENT ME!\r
502      */\r
503     public void mouseMoved(MouseEvent evt)\r
504     {\r
505         AlignmentAnnotation[] aa = av.alignment.getAlignmentAnnotation();\r
506 \r
507         if (aa == null)\r
508         {\r
509             return;\r
510         }\r
511 \r
512         int row = -1;\r
513         int height = 0;\r
514 \r
515         for (int i = 0; i < aa.length; i++)\r
516         {\r
517             if (aa[i].visible)\r
518             {\r
519                 height += aa[i].height;\r
520             }\r
521 \r
522             if (evt.getY() < height)\r
523             {\r
524                 row = i;\r
525 \r
526                 break;\r
527             }\r
528         }\r
529 \r
530         int res = (evt.getX() / av.getCharWidth()) + av.getStartRes();\r
531 \r
532         if (row > -1 && res<aa[row].annotations.length)\r
533         {\r
534             if(aa[row].graphGroup>-1)\r
535             {\r
536               StringBuffer tip = new StringBuffer("<html>");\r
537               for (int gg = 0; gg < aa.length; gg++)\r
538               {\r
539                 if (aa[gg].graphGroup == aa[row].graphGroup && aa[gg].annotations[res]!=null)\r
540                   tip.append(aa[gg].label+" "+aa[gg].annotations[res].description+"<br>" );\r
541               }\r
542               if(tip.length()!=6)\r
543               {\r
544                 tip.setLength(tip.length() - 4);\r
545                 this.setToolTipText(tip.toString() + "</html>");\r
546               }\r
547             }\r
548             else if(aa[row].annotations[res] != null)\r
549               this.setToolTipText(aa[row].annotations[res].description);\r
550 \r
551             if(aa[row].annotations[res]!=null)\r
552             {\r
553               StringBuffer text = new StringBuffer("Sequence position " +\r
554                                                    (res + 1) + "  " +\r
555                                                    aa[row].annotations[res].description);\r
556 \r
557               ap.alignFrame.statusBar.setText(text.toString());\r
558             }\r
559         }\r
560     }\r
561 \r
562     /**\r
563      * DOCUMENT ME!\r
564      *\r
565      * @param evt DOCUMENT ME!\r
566      */\r
567     public void mouseClicked(MouseEvent evt)\r
568     {\r
569     }\r
570 \r
571     /**\r
572      * DOCUMENT ME!\r
573      *\r
574      * @param g DOCUMENT ME!\r
575      */\r
576     public void paintComponent(Graphics g)\r
577     {\r
578       g.setColor(Color.white);\r
579       g.fillRect(0, 0, getWidth(), getHeight());\r
580 \r
581       if(image!=null)\r
582       {if (fastPaint\r
583             || (getVisibleRect().width != g.getClipBounds().width)\r
584             || (getVisibleRect().height != g.getClipBounds().height))\r
585         {\r
586           g.drawImage(image, 0, 0, this);\r
587           fastPaint = false;\r
588           return;\r
589         }\r
590       }\r
591       imgWidth = (av.endRes - av.startRes + 1) * av.charWidth;\r
592 \r
593       if (image == null || imgWidth != image.getWidth()\r
594           || image.getHeight(this) != getHeight())\r
595       {\r
596         image = new BufferedImage(imgWidth, ap.annotationPanel.getHeight(),\r
597                                   BufferedImage.TYPE_INT_RGB);\r
598         gg = (Graphics2D) image.getGraphics();\r
599 \r
600         if(av.antiAlias)\r
601         gg.setRenderingHint(RenderingHints.KEY_ANTIALIASING,\r
602                             RenderingHints.VALUE_ANTIALIAS_ON);\r
603 \r
604         gg.setFont(av.getFont());\r
605         fm = gg.getFontMetrics();\r
606       }\r
607 \r
608 \r
609       drawComponent(gg, av.startRes, av.endRes + 1);\r
610       g.drawImage(image, 0, 0, this);\r
611     }\r
612 \r
613     /**\r
614      * DOCUMENT ME!\r
615      *\r
616      * @param horizontal DOCUMENT ME!\r
617      */\r
618     public void fastPaint(int horizontal)\r
619     {\r
620         if ((horizontal == 0) || gg==null ||\r
621                 (av.alignment.getAlignmentAnnotation() == null) ||\r
622                 (av.alignment.getAlignmentAnnotation().length < 1))\r
623         {\r
624             repaint();\r
625             return;\r
626         }\r
627 \r
628         gg.copyArea(0, 0, imgWidth, getHeight(), -horizontal * av.charWidth, 0);\r
629 \r
630         int sr = av.startRes;\r
631         int er = av.endRes + 1;\r
632         int transX = 0;\r
633 \r
634         if (horizontal > 0) // scrollbar pulled right, image to the left\r
635         {\r
636             transX = (er - sr - horizontal) * av.charWidth;\r
637             sr = er - horizontal;\r
638         }\r
639         else if (horizontal < 0)\r
640         {\r
641             er = sr - horizontal;\r
642         }\r
643 \r
644         gg.translate(transX, 0);\r
645 \r
646         drawComponent(gg, sr, er);\r
647 \r
648         gg.translate(-transX, 0);\r
649 \r
650         fastPaint = true;\r
651 \r
652         repaint();\r
653 \r
654     }\r
655 \r
656     /**\r
657      * DOCUMENT ME!\r
658      *\r
659      * @param g DOCUMENT ME!\r
660      * @param startRes DOCUMENT ME!\r
661      * @param endRes DOCUMENT ME!\r
662      */\r
663     public void drawComponent(Graphics g, int startRes, int endRes)\r
664     {\r
665       g.setFont(av.getFont());\r
666 \r
667       if (fm == null)\r
668         fm = g.getFontMetrics();\r
669 \r
670 \r
671         g.setColor(Color.white);\r
672         g.fillRect(0, 0, (endRes - startRes) * av.charWidth, getHeight());\r
673 \r
674         if ((av.alignment.getAlignmentAnnotation() == null) ||\r
675                 (av.alignment.getAlignmentAnnotation().length < 1))\r
676         {\r
677             g.setColor(Color.white);\r
678             g.fillRect(0, 0, getWidth(), getHeight());\r
679             g.setColor(Color.black);\r
680             g.drawString("Alignment has no annotations", 20, 15);\r
681 \r
682             return;\r
683         }\r
684 \r
685         AlignmentAnnotation[] aa = av.alignment.getAlignmentAnnotation();\r
686 \r
687         int j;\r
688         int x = 0;\r
689         int y = 0;\r
690         char[] lastSS = new char[aa.length];\r
691         int[] lastSSX = new int[aa.length];\r
692         int iconOffset = av.charHeight / 2;\r
693         boolean validRes = false;\r
694 \r
695         boolean [] graphGroupDrawn = new boolean[aa.length];\r
696 \r
697 \r
698         //\u03B2 \u03B1\r
699         for (int i = 0; i < aa.length; i++)\r
700         {\r
701             AlignmentAnnotation row = aa[i];\r
702 \r
703             if (!row.visible)\r
704             {\r
705                 continue;\r
706             }\r
707 \r
708 \r
709 \r
710             if (row.graph>0)\r
711             {\r
712                 if(row.graphGroup>-1 && graphGroupDrawn[ row.graphGroup ] )\r
713                   continue;\r
714 \r
715                 // this is so that we draw the characters below the graph\r
716                 y += row.height;\r
717 \r
718                 if (row.hasText)\r
719                 {\r
720                     y -= av.charHeight;\r
721                 }\r
722             }\r
723 \r
724             if (row.hasText)\r
725             {\r
726                 iconOffset = av.charHeight / 2;\r
727             }\r
728             else\r
729             {\r
730                 iconOffset = 0;\r
731             }\r
732 \r
733             for (j = startRes; j < endRes; j++)\r
734             {\r
735                 if ((row.annotations.length <= j) ||\r
736                         (row.annotations[j] == null))\r
737                 {\r
738                     validRes = false;\r
739                 }\r
740                 else\r
741                 {\r
742                     validRes = true;\r
743                 }\r
744 \r
745                 x = (j - startRes) * av.charWidth;\r
746 \r
747                 if (activeRow == i)\r
748                 {\r
749                     g.setColor(Color.red);\r
750 \r
751                     if (activeRes != null)\r
752                     {\r
753                         for (int n = 0; n < activeRes.size(); n++)\r
754                         {\r
755                             int v = Integer.parseInt(activeRes.get(n).toString());\r
756 \r
757                             if (v == j)\r
758                             {\r
759                                 g.fillRect((j - startRes) * av.charWidth, y,\r
760                                     av.charWidth, row.height);\r
761                             }\r
762                         }\r
763                     }\r
764                 }\r
765 \r
766                 if (validRes &&\r
767                         (row.annotations[j].displayCharacter.length() > 0))\r
768                 {\r
769 \r
770                     int charOffset = (av.charWidth -\r
771                         fm.charWidth(row.annotations[j].displayCharacter.charAt(\r
772                                 0))) / 2;\r
773                     g.setColor(row.annotations[j].colour);\r
774 \r
775                     if (j == 0 || row.graph>0)\r
776                     {\r
777                         g.drawString(row.annotations[j].displayCharacter, x+charOffset,\r
778                             y + iconOffset + 3);\r
779                     }\r
780                     else if (((row.annotations[j - 1] == null) ||\r
781                             (row.annotations[j].displayCharacter != row.annotations[j -\r
782                             1].displayCharacter)))\r
783                     {\r
784                         g.drawString(row.annotations[j].displayCharacter, x+charOffset,\r
785                             y + iconOffset + 3);\r
786                     }\r
787                 }\r
788 \r
789                 if (row.hasIcons)\r
790                 {\r
791                     if (!validRes ||\r
792                             (row.annotations[j].secondaryStructure != lastSS[i]))\r
793                     {\r
794                         switch (lastSS[i])\r
795                         {\r
796                         case 'H':\r
797                             g.setColor(HELIX_COLOUR);\r
798                             g.fillRoundRect(lastSSX[i], y + 4 + iconOffset,\r
799                                 x - lastSSX[i], 7, 8, 8);\r
800 \r
801                             break;\r
802 \r
803                         case 'E':\r
804                             g.setColor(SHEET_COLOUR);\r
805                             g.fillRect(lastSSX[i], y + 4 + iconOffset,\r
806                                 x - lastSSX[i] - 4, 7);\r
807                             g.fillPolygon(new int[] { x - 4, x - 4, x },\r
808                                 new int[]\r
809                                 {\r
810                                     y + iconOffset, y + 14 + iconOffset,\r
811                                     y + 8 + iconOffset\r
812                                 }, 3);\r
813 \r
814                             break;\r
815 \r
816 \r
817                         default:\r
818                             g.setColor(Color.gray);\r
819                             g.fillRect(lastSSX[i], y + 6 + iconOffset,\r
820                                 x - lastSSX[i], 2);\r
821 \r
822                             break;\r
823                         }\r
824 \r
825                         if (validRes)\r
826                         {\r
827                             lastSS[i] = row.annotations[j].secondaryStructure;\r
828                         }\r
829                         else\r
830                         {\r
831                             lastSS[i] = ' ';\r
832                         }\r
833 \r
834                         lastSSX[i] = x;\r
835                     }\r
836                 }\r
837             }\r
838 \r
839             x += av.charWidth;\r
840 \r
841             if (row.hasIcons)\r
842             {\r
843                 switch (lastSS[i])\r
844                 {\r
845                 case 'H':\r
846                     g.setColor(HELIX_COLOUR);\r
847                     g.fillRoundRect(lastSSX[i], y + 4 + iconOffset,\r
848                         x - lastSSX[i], 7, 8, 8);\r
849 \r
850                     break;\r
851 \r
852                 case 'E':\r
853                     g.setColor(SHEET_COLOUR);\r
854 \r
855                     if (row.annotations[endRes] !=null\r
856                         && row.annotations[endRes].secondaryStructure != 'E')\r
857                     {\r
858                       g.fillRect(lastSSX[i], y + 4 + iconOffset,\r
859                                  x - lastSSX[i] - 4, 7);\r
860                       g.fillPolygon(new int[]\r
861                                     {x - 4, x - 4, x},\r
862                                     new int[]\r
863                                     {\r
864                                     y + iconOffset, y + 14 + iconOffset,\r
865                                     y + 7 + iconOffset\r
866                       }, 3);\r
867                     }\r
868                     else\r
869                       g.fillRect(lastSSX[i], y + 4 + iconOffset,\r
870                                  x - lastSSX[i], 7);\r
871 \r
872                     break;\r
873 \r
874                 case 'C':\r
875                     break;\r
876 \r
877                 default:\r
878                     g.setColor(Color.gray);\r
879                     g.fillRect(lastSSX[i], y + 6 + iconOffset, x - lastSSX[i], 2);\r
880 \r
881                     break;\r
882                 }\r
883             }\r
884 \r
885             if (row.graph>0)\r
886             {\r
887                 if(row.graph == AlignmentAnnotation.LINE_GRAPH )\r
888                 {\r
889                   if(row.graphGroup>-1 && !graphGroupDrawn[row.graphGroup])\r
890                    {\r
891                      float groupmax=-999999, groupmin=9999999;\r
892                      for(int gg=0; gg<aa.length; gg++)\r
893                      {\r
894                        if(aa[gg].graphGroup!=row.graphGroup)\r
895                          continue;\r
896 \r
897                        if(aa[gg]!=row)\r
898                          aa[gg].visible = false;\r
899 \r
900                        if(aa[gg].graphMax>groupmax)\r
901                          groupmax = aa[gg].graphMax;\r
902                        if(aa[gg].graphMin<groupmin)\r
903                          groupmin = aa[gg].graphMin;\r
904                      }\r
905 \r
906                      for (int gg = 0; gg < aa.length; gg++)\r
907                      {\r
908                        if (aa[gg].graphGroup == row.graphGroup)\r
909                        {\r
910                          drawLineGraph(g, aa[gg], startRes, endRes, y,\r
911                                        groupmin, groupmax,\r
912                                        row.graphHeight);\r
913                        }\r
914                      }\r
915 \r
916                      graphGroupDrawn[ row.graphGroup ] = true;\r
917                    }\r
918                    else\r
919                      drawLineGraph(g, row, startRes, endRes,\r
920                                    y, row.graphMin, row.graphMax, row.graphHeight  );\r
921                 }\r
922                 else if(row.graph == AlignmentAnnotation.BAR_GRAPH )\r
923                    drawBarGraph(g, row, startRes, endRes,\r
924                                 row.graphMin, row.graphMax, y);\r
925             }\r
926 \r
927             if (row.graph>0 && row.hasText)\r
928             {\r
929                 y += av.charHeight;\r
930             }\r
931 \r
932             if (row.graph==0)\r
933             {\r
934                 y += aa[i].height;\r
935             }\r
936         }\r
937     }\r
938 \r
939     public void drawLineGraph(Graphics g, AlignmentAnnotation aa,\r
940                               int sRes, int eRes,\r
941                               int y,\r
942                               float min, float max,\r
943                               int graphHeight)\r
944     {\r
945       if(sRes>aa.annotations.length)\r
946         return;\r
947 \r
948       int x = 0;\r
949 \r
950       //Adjustment for fastpaint to left\r
951       if(eRes<av.endRes)\r
952         eRes++;\r
953 \r
954       if(sRes==0)\r
955       {\r
956         sRes++;\r
957         x+=av.charWidth;\r
958       }\r
959 \r
960       int y1=y, y2=y;\r
961       float range = max - min;\r
962 \r
963       ////Draw origin\r
964       if(min<0)\r
965         y2 = (int)(y - (0-min / range)*graphHeight);\r
966 \r
967       g.setColor(Color.gray);\r
968       g.drawLine(x-av.charWidth,y2,(eRes-sRes+1)*av.charWidth,y2);\r
969 \r
970 \r
971       if(aa.threshold!=null)\r
972       {\r
973           g.setColor(aa.threshold.colour);\r
974           Graphics2D g2 = (Graphics2D)g;\r
975           g2.setStroke(new BasicStroke(1,\r
976                                         BasicStroke.CAP_SQUARE,\r
977                                         BasicStroke.JOIN_ROUND, 3f,\r
978                                         new float[] { 5f, 3f }, 0f));\r
979 \r
980           y2 = (int)(y - ((aa.threshold.value-min) / range)*graphHeight);\r
981           g.drawLine(x-av.charWidth,y2,(eRes-sRes+1)*av.charWidth,y2);\r
982           g2.setStroke(new BasicStroke());\r
983       }\r
984 \r
985       eRes = Math.min(eRes, aa.annotations.length);\r
986       for (int j = sRes; j < eRes; j++)\r
987       {\r
988         if(aa.annotations[j]==null || aa.annotations[j-1]==null)\r
989         {\r
990           x+=av.charWidth;\r
991           continue;\r
992         }\r
993           g.setColor(aa.annotations[j].colour);\r
994           y1 = y - (int) (((aa.annotations[j-1].value-min) / range) * graphHeight);\r
995           y2 = y - (int) (((aa.annotations[j].value-min) / range) * graphHeight);\r
996           g.drawLine(x-av.charWidth/2, y1, x+av.charWidth/2, y2);\r
997           x += av.charWidth;\r
998        }\r
999     }\r
1000 \r
1001     public void drawBarGraph(Graphics g, AlignmentAnnotation aa,\r
1002                              int sRes, int eRes,\r
1003                              float min, float max,\r
1004                              int y)\r
1005     {\r
1006       if(sRes>aa.annotations.length)\r
1007         return;\r
1008 \r
1009       int x=0, y1, y2;\r
1010 \r
1011       float range = max - min;\r
1012 \r
1013       if(aa.threshold!=null)\r
1014       {\r
1015           g.setColor(aa.threshold.colour);\r
1016           Graphics2D g2 = (Graphics2D)g;\r
1017           g2.setStroke(new BasicStroke(1,\r
1018                                         BasicStroke.CAP_SQUARE,\r
1019                                         BasicStroke.JOIN_ROUND, 3f,\r
1020                                         new float[] { 5f, 3f }, 0f));\r
1021 \r
1022           y2 = (int)(y - ((aa.threshold.value-min) / range)*aa.graphHeight);\r
1023           g.drawLine(x-av.charWidth,y2,(eRes-sRes+1)*av.charWidth,y2);\r
1024           g2.setStroke(new BasicStroke());\r
1025       }\r
1026 \r
1027       y1 = y2 = y;\r
1028 \r
1029       if(min<0)\r
1030         y2 = (int)(y - (0-min / (range))*aa.graphHeight);\r
1031 \r
1032       g.setColor(Color.gray);\r
1033 \r
1034       g.drawLine(x,y2,(eRes-sRes+1)*av.charWidth,y2);\r
1035 \r
1036       eRes = Math.min(eRes, aa.annotations.length-1);\r
1037 \r
1038 \r
1039       for (int j = sRes; j < eRes; j++)\r
1040       {\r
1041 \r
1042         if (aa.annotations[j] == null)\r
1043         {\r
1044           x += av.charWidth;\r
1045           continue;\r
1046         }\r
1047 \r
1048           g.setColor(aa.annotations[j].colour);\r
1049           y1 = y - (int) (((aa.annotations[j].value-min) / (range)) * aa.graphHeight);\r
1050 \r
1051           if(y1-y2>0)\r
1052             g.fillRect(x, y2, av.charWidth, y1-y2 );\r
1053           else\r
1054             g.fillRect(x, y1, av.charWidth, y2-y1 );\r
1055 \r
1056           x += av.charWidth;\r
1057       }\r
1058 \r
1059     }\r
1060 \r
1061     // used by overview window\r
1062     public void drawGraph(Graphics g, AlignmentAnnotation aa, int width, int y, int sRes, int eRes)\r
1063     {\r
1064       g.setColor(Color.white);\r
1065       g.fillRect(0, 0, width, y);\r
1066       g.setColor(new Color(0, 0, 180));\r
1067 \r
1068       int x = 0, height;\r
1069 \r
1070       for (int j = sRes; j < eRes; j++)\r
1071       {\r
1072           g.setColor(aa.annotations[j].colour);\r
1073 \r
1074           height = (int) ((aa.annotations[j].value / aa.graphMax) * y);\r
1075           if(height>y)\r
1076             height = y;\r
1077 \r
1078           g.fillRect(x, y - height, av.charWidth, height);\r
1079           x += av.charWidth;\r
1080       }\r
1081     }\r
1082 \r
1083 }\r