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