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