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