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