Faded anntotations when recalculating
[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         int res = (evt.getX() / av.getCharWidth()) + av.getStartRes();\r
513 \r
514         if(av.hasHiddenColumns)\r
515           res = av.getColumnSelection().adjustForHiddenColumns(res);\r
516 \r
517         if (row > -1 && res<aa[row].annotations.length)\r
518         {\r
519             if(aa[row].graphGroup>-1)\r
520             {\r
521               StringBuffer tip = new StringBuffer("<html>");\r
522               for (int gg = 0; gg < aa.length; gg++)\r
523               {\r
524                 if (aa[gg].graphGroup == aa[row].graphGroup && aa[gg].annotations[res]!=null)\r
525                   tip.append(aa[gg].label+" "+aa[gg].annotations[res].description+"<br>" );\r
526               }\r
527               if(tip.length()!=6)\r
528               {\r
529                 tip.setLength(tip.length() - 4);\r
530                 this.setToolTipText(tip.toString() + "</html>");\r
531               }\r
532             }\r
533             else if(aa[row].annotations[res] != null)\r
534               this.setToolTipText(aa[row].annotations[res].description);\r
535 \r
536             if(aa[row].annotations[res]!=null)\r
537             {\r
538               StringBuffer text = new StringBuffer("Sequence position " +\r
539                                                    (res + 1) + "  " +\r
540                                                    aa[row].annotations[res].description);\r
541 \r
542               ap.alignFrame.statusBar.setText(text.toString());\r
543             }\r
544         }\r
545     }\r
546 \r
547     /**\r
548      * DOCUMENT ME!\r
549      *\r
550      * @param evt DOCUMENT ME!\r
551      */\r
552     public void mouseClicked(MouseEvent evt)\r
553     {\r
554     }\r
555 \r
556     /**\r
557      * DOCUMENT ME!\r
558      *\r
559      * @param g DOCUMENT ME!\r
560      */\r
561     public void paintComponent(Graphics g)\r
562     {\r
563       g.setColor(Color.white);\r
564       g.fillRect(0, 0, getWidth(), getHeight());\r
565 \r
566       if(image!=null)\r
567       {if (fastPaint\r
568             || (getVisibleRect().width != g.getClipBounds().width)\r
569             || (getVisibleRect().height != g.getClipBounds().height))\r
570         {\r
571           g.drawImage(image, 0, 0, this);\r
572           fastPaint = false;\r
573           return;\r
574         }\r
575       }\r
576       imgWidth = (av.endRes - av.startRes + 1) * av.charWidth;\r
577 \r
578       if (image == null || imgWidth != image.getWidth()\r
579           || image.getHeight(this) != getHeight())\r
580       {\r
581         image = new BufferedImage(imgWidth, ap.annotationPanel.getHeight(),\r
582                                   BufferedImage.TYPE_INT_RGB);\r
583         gg = (Graphics2D) image.getGraphics();\r
584 \r
585         if(av.antiAlias)\r
586         gg.setRenderingHint(RenderingHints.KEY_ANTIALIASING,\r
587                             RenderingHints.VALUE_ANTIALIAS_ON);\r
588 \r
589         gg.setFont(av.getFont());\r
590         fm = gg.getFontMetrics();\r
591         gg.setColor(Color.white);\r
592         gg.fillRect(0, 0, imgWidth, image.getHeight());\r
593       }\r
594 \r
595 \r
596       drawComponent(gg, av.startRes, av.endRes + 1);\r
597       g.drawImage(image, 0, 0, this);\r
598     }\r
599 \r
600     /**\r
601      * DOCUMENT ME!\r
602      *\r
603      * @param horizontal DOCUMENT ME!\r
604      */\r
605     public void fastPaint(int horizontal)\r
606     {\r
607         if ((horizontal == 0)\r
608             || gg==null\r
609             || av.alignment.getAlignmentAnnotation()==null\r
610             || av.alignment.getAlignmentAnnotation().length < 1\r
611             || av.updatingConsensus\r
612             || av.updatingConservation)\r
613         {\r
614             repaint();\r
615             return;\r
616         }\r
617 \r
618         gg.copyArea(0, 0, imgWidth, getHeight(), -horizontal * av.charWidth, 0);\r
619 \r
620         int sr = av.startRes;\r
621         int er = av.endRes + 1;\r
622         int transX = 0;\r
623 \r
624         if (horizontal > 0) // scrollbar pulled right, image to the left\r
625         {\r
626             transX = (er - sr - horizontal) * av.charWidth;\r
627             sr = er - horizontal;\r
628         }\r
629         else if (horizontal < 0)\r
630         {\r
631             er = sr - horizontal;\r
632         }\r
633 \r
634         gg.translate(transX, 0);\r
635 \r
636         drawComponent(gg, sr, er);\r
637 \r
638         gg.translate(-transX, 0);\r
639 \r
640         fastPaint = true;\r
641 \r
642         repaint();\r
643 \r
644     }\r
645 \r
646     /**\r
647      * DOCUMENT ME!\r
648      *\r
649      * @param g DOCUMENT ME!\r
650      * @param startRes DOCUMENT ME!\r
651      * @param endRes DOCUMENT ME!\r
652      */\r
653     public void drawComponent(Graphics g, int startRes, int endRes)\r
654     {\r
655       if(av.updatingConsensus || av.updatingConservation)\r
656       {\r
657         //We'll keep a record of the old image,\r
658         //and draw a faded image until the calculation\r
659         //has completed\r
660         if(fadedImage==null\r
661            || fadedImage.getWidth()!=imgWidth\r
662         || fadedImage.getHeight()!=image.getHeight())\r
663         {\r
664           fadedImage = new BufferedImage(\r
665               imgWidth, image.getHeight(),\r
666               BufferedImage.TYPE_INT_RGB);\r
667 \r
668           Graphics2D fadedG = (Graphics2D) fadedImage.getGraphics();\r
669 \r
670           fadedG.setColor(Color.white);\r
671         fadedG.fillRect(0, 0, imgWidth, image.getHeight());\r
672 \r
673           fadedG.setComposite(\r
674               AlphaComposite.getInstance(\r
675                   AlphaComposite.SRC_OVER, .3f));\r
676           fadedG.drawImage(image, 0, 0, this);\r
677 \r
678         }\r
679 \r
680       }\r
681       else\r
682         fadedImage = null;\r
683 \r
684 \r
685       g.setColor(Color.white);\r
686       g.fillRect(0, 0, (endRes - startRes) * av.charWidth, getHeight());\r
687 \r
688       g.setFont(av.getFont());\r
689       if (fm == null)\r
690         fm = g.getFontMetrics();\r
691 \r
692 \r
693 \r
694 \r
695         if ( (av.alignment.getAlignmentAnnotation() == null) ||\r
696                 (av.alignment.getAlignmentAnnotation().length < 1))\r
697         {\r
698             g.setColor(Color.white);\r
699             g.fillRect(0, 0, getWidth(), getHeight());\r
700             g.setColor(Color.black);\r
701             if(av.validCharWidth)\r
702               g.drawString("Alignment has no annotations", 20, 15);\r
703 \r
704             return;\r
705         }\r
706 \r
707 \r
708         AlignmentAnnotation[] aa = av.alignment.getAlignmentAnnotation();\r
709 \r
710         int x = 0, y = 0;\r
711         int column=0;\r
712         char lastSS;\r
713         int lastSSX;\r
714         int iconOffset = av.charHeight / 2;\r
715         boolean validRes = false;\r
716 \r
717         boolean [] graphGroupDrawn = new boolean[aa.length];\r
718 \r
719 \r
720         //\u03B2 \u03B1\r
721         for (int i = 0; i < aa.length; i++)\r
722         {\r
723             AlignmentAnnotation row = aa[i];\r
724 \r
725             if (!row.visible)\r
726             {\r
727                 continue;\r
728             }\r
729 \r
730 \r
731             lastSS = ' ';\r
732             lastSSX = 0;\r
733 \r
734             if (row.graph>0)\r
735             {\r
736                 if(row.graphGroup>-1 && graphGroupDrawn[ row.graphGroup ] )\r
737                   continue;\r
738 \r
739                 // this is so that we draw the characters below the graph\r
740                 y += row.height;\r
741 \r
742                 if (row.hasText)\r
743                 {\r
744                     y -= av.charHeight;\r
745                 }\r
746             }\r
747 \r
748             if (av.updatingConsensus && aa[i].label.equals("Consensus"))\r
749             {\r
750               y += av.charHeight;\r
751 \r
752               g.drawImage(fadedImage,\r
753               0,y-row.height,imgWidth, y,\r
754               0,y-row.height,imgWidth, y, this);\r
755               g.setColor(Color.black);\r
756              // g.drawString("Calculating Consensus....",20, y-row.height/2);\r
757 \r
758               continue;\r
759             }\r
760             else if (av.updatingConservation && aa[i].label.equals("Conservation"))\r
761             {\r
762 \r
763               y += av.charHeight;\r
764               g.drawImage(fadedImage,\r
765                           0, y - row.height, imgWidth, y,\r
766                           0, y - row.height, imgWidth, y, this);\r
767 \r
768               g.setColor(Color.black);\r
769             //  g.drawString("Calculating Conservation.....",20, y-row.height/2);\r
770 \r
771               continue;\r
772             }\r
773             else if (av.updatingConservation && aa[i].label.equals("Quality"))\r
774             {\r
775 \r
776               y += av.charHeight;\r
777               g.drawImage(fadedImage,\r
778                           0, y - row.height, imgWidth, y,\r
779                           0, y - row.height, imgWidth, y, this);\r
780               g.setColor(Color.black);\r
781              /// g.drawString("Calculating Quality....",20, y-row.height/2);\r
782 \r
783               continue;\r
784             }\r
785 \r
786 \r
787             if (row.hasText)\r
788             {\r
789                 iconOffset = av.charHeight / 2 + 4;\r
790             }\r
791             else\r
792             {\r
793                 iconOffset = 0;\r
794             }\r
795 \r
796             x = 0;\r
797             while (x < endRes-startRes)\r
798             {\r
799               if (av.hasHiddenColumns)\r
800               {\r
801                 column = av.getColumnSelection().adjustForHiddenColumns(startRes+x);\r
802                 if (column > row.annotations.length-1)\r
803                 {\r
804                   break;\r
805                 }\r
806               }\r
807               else\r
808                 column = startRes+x;\r
809 \r
810 \r
811                 if ((row.annotations.length <= column) ||\r
812                         (row.annotations[column] == null))\r
813                 {\r
814                     validRes = false;\r
815                 }\r
816                 else\r
817                 {\r
818                     validRes = true;\r
819                 }\r
820 \r
821 \r
822                 if (activeRow == i)\r
823                 {\r
824                     g.setColor(Color.red);\r
825 \r
826                     if (av.getColumnSelection() != null)\r
827                     {\r
828                         for (int n = 0; n < av.getColumnSelection().size(); n++)\r
829                         {\r
830                             int v = av.getColumnSelection().columnAt(n);\r
831 \r
832                             if (v == column)\r
833                             {\r
834                                 g.fillRect(x * av.charWidth, y,\r
835                                     av.charWidth, av.charHeight);\r
836                             }\r
837                         }\r
838                     }\r
839                 }\r
840 \r
841                 if (av.validCharWidth && validRes &&\r
842                         (row.annotations[column].displayCharacter.length() > 0))\r
843                 {\r
844 \r
845                     int charOffset = (av.charWidth -\r
846                         fm.charWidth(row.annotations[column].displayCharacter.charAt(\r
847                                 0))) / 2;\r
848                     g.setColor(row.annotations[column].colour);\r
849 \r
850                     if (column == 0 || row.graph>0)\r
851                     {\r
852                         g.drawString(row.annotations[column].displayCharacter,\r
853                                      (x*av.charWidth)+charOffset,\r
854                             y + iconOffset );\r
855                     }\r
856                     else if (\r
857                         row.annotations[column - 1] == null\r
858                         ||(!row.annotations[column].displayCharacter.equals(\r
859                             row.annotations[column - 1].displayCharacter)\r
860                         ||\r
861                   (row.annotations[column].displayCharacter.length() <2 &&\r
862                    row.annotations[column].secondaryStructure==' ')))\r
863                     {\r
864                         g.drawString(row.annotations[column].displayCharacter,\r
865                                      x*av.charWidth+charOffset,\r
866                                      y + iconOffset );\r
867                     }\r
868                 }\r
869 \r
870                 if (row.hasIcons)\r
871                 {\r
872                     if (!validRes ||\r
873                             (row.annotations[column].secondaryStructure != lastSS))\r
874                     {\r
875                         switch (lastSS)\r
876                         {\r
877                         case 'H':\r
878                           g.setColor(HELIX_COLOUR);\r
879                           if (MAC)\r
880                           {\r
881                             //Off by 1 offset when drawing rects and ovals\r
882                             //to offscreen image on the MAC\r
883                             g.fillRoundRect(lastSSX, y + 4 + iconOffset,\r
884                                             (x*av.charWidth) - lastSSX, 7, 8, 8);\r
885                             break;\r
886                           }\r
887 \r
888                           int sCol = (lastSSX / av.charWidth) + startRes;\r
889                           int x1 = lastSSX;\r
890                           int x2 = (x*av.charWidth);\r
891 \r
892                          if(sCol==0 ||\r
893                             row.annotations[sCol-1]==null ||\r
894                             row.annotations[sCol-1].secondaryStructure!='H')\r
895                          {\r
896                            g.fillArc(lastSSX, y+4+iconOffset, av.charWidth, 8, 90,180) ;\r
897                            x1 += av.charWidth/2;\r
898                          }\r
899 \r
900                           if(row.annotations[column]==null ||\r
901                              row.annotations[column].secondaryStructure!='H')\r
902                           {\r
903                             g.fillArc((x*av.charWidth)-av.charWidth,\r
904                                       y+4+iconOffset, av.charWidth, 8, 270,180);\r
905                             x2 -= av.charWidth/2;\r
906                           }\r
907 \r
908                           g.fillRect(x1, y+4+iconOffset, x2-x1, 8);\r
909                               break;\r
910 \r
911                         case 'E':\r
912                             g.setColor(SHEET_COLOUR);\r
913                             g.fillRect(lastSSX, y + 4 + iconOffset,\r
914                                 (x*av.charWidth) - lastSSX - 4, 7);\r
915                             g.fillPolygon(new int[] { (x*av.charWidth) - 4,\r
916                                           (x*av.charWidth) - 4,\r
917                                           (x*av.charWidth) },\r
918                                 new int[]\r
919                                 {\r
920                                     y + iconOffset, y + 14 + iconOffset,\r
921                                     y + 8 + iconOffset\r
922                                 }, 3);\r
923 \r
924                             break;\r
925 \r
926 \r
927                         default:\r
928                             g.setColor(Color.gray);\r
929                             g.fillRect(lastSSX, y + 6 + iconOffset,\r
930                                 (x*av.charWidth) - lastSSX, 2);\r
931 \r
932                             break;\r
933                         }\r
934 \r
935                         if (validRes)\r
936                         {\r
937                             lastSS = row.annotations[column].secondaryStructure;\r
938                         }\r
939                         else\r
940                         {\r
941                             lastSS = ' ';\r
942                         }\r
943 \r
944                         lastSSX = (x*av.charWidth);\r
945                     }\r
946                 }\r
947 \r
948 \r
949             column++;\r
950             x++;\r
951             }\r
952 \r
953             if(column>=row.annotations.length)\r
954                 column = row.annotations.length-1;\r
955 \r
956           //  x ++;\r
957 \r
958             if (row.hasIcons)\r
959             {\r
960               switch (lastSS)\r
961               {\r
962                 case 'H':\r
963                   g.setColor(HELIX_COLOUR);\r
964                   if (MAC)\r
965                   {\r
966                     //Off by 1 offset when drawing rects and ovals\r
967                     //to offscreen image on the MAC\r
968                     g.fillRoundRect(lastSSX, y + 4 + iconOffset,\r
969                                     (x*av.charWidth) - lastSSX, 7, 8, 8);\r
970                     break;\r
971                   }\r
972 \r
973                   int sCol = (lastSSX / av.charWidth) + startRes;\r
974                   int x1 = lastSSX;\r
975                   int x2 = (x*av.charWidth);\r
976 \r
977                   if (sCol == 0 ||\r
978                       row.annotations[sCol - 1] == null ||\r
979                       row.annotations[sCol - 1].secondaryStructure != 'H')\r
980                   {\r
981                     g.fillArc(lastSSX, y + 4 + iconOffset, av.charWidth, 8, 90, 180);\r
982                     x1 += av.charWidth / 2;\r
983                   }\r
984 \r
985                   if (row.annotations[column] == null ||\r
986                       row.annotations[column].secondaryStructure != 'H')\r
987                   {\r
988                     g.fillArc((x*av.charWidth) - av.charWidth,\r
989                               y + 4 + iconOffset, av.charWidth, 8, 270,\r
990                               180);\r
991                     x2 -= av.charWidth / 2;\r
992                   }\r
993 \r
994                   g.fillRect(x1, y + 4 + iconOffset, x2 - x1, 8);\r
995 \r
996                   break;\r
997 \r
998                 case 'E':\r
999                   g.setColor(SHEET_COLOUR);\r
1000 \r
1001                   if (row.annotations[endRes] == null\r
1002                       || row.annotations[endRes].secondaryStructure != 'E')\r
1003                   {\r
1004                     g.fillRect(lastSSX, y + 4 + iconOffset,\r
1005                                (x*av.charWidth) - lastSSX - 4, 7);\r
1006                     g.fillPolygon(new int[]\r
1007                                   {(x*av.charWidth) - 4,\r
1008                                   (x*av.charWidth) - 4,\r
1009                                  (x*av.charWidth)},\r
1010                                   new int[]\r
1011                                   {\r
1012                                   y + iconOffset, y + 14 + iconOffset,\r
1013                                   y + 7 + iconOffset\r
1014                     }, 3);\r
1015                   }\r
1016                   else\r
1017                    {\r
1018                      g.fillRect(lastSSX, y + 4 + iconOffset,\r
1019                                 (x+1) * av.charWidth - lastSSX, 7);\r
1020                    }\r
1021                   break;\r
1022 \r
1023                 default:\r
1024                   g.setColor(Color.gray);\r
1025                   if(!av.wrapAlignment || endRes==av.endRes)\r
1026                   g.fillRect(lastSSX, y + 6 + iconOffset,\r
1027                              (x*av.charWidth) - lastSSX, 2);\r
1028 \r
1029                   break;\r
1030               }\r
1031           }\r
1032 \r
1033             if (row.graph>0 && row.graphHeight>0)\r
1034             {\r
1035                 if(row.graph == AlignmentAnnotation.LINE_GRAPH )\r
1036                 {\r
1037                   if(row.graphGroup>-1 && !graphGroupDrawn[row.graphGroup])\r
1038                    {\r
1039                      float groupmax=-999999, groupmin=9999999;\r
1040                      for(int gg=0; gg<aa.length; gg++)\r
1041                      {\r
1042                        if(aa[gg].graphGroup!=row.graphGroup)\r
1043                          continue;\r
1044 \r
1045                        if(aa[gg]!=row)\r
1046                          aa[gg].visible = false;\r
1047 \r
1048                        if(aa[gg].graphMax>groupmax)\r
1049                          groupmax = aa[gg].graphMax;\r
1050                        if(aa[gg].graphMin<groupmin)\r
1051                          groupmin = aa[gg].graphMin;\r
1052                      }\r
1053 \r
1054                      for (int gg = 0; gg < aa.length; gg++)\r
1055                      {\r
1056                        if (aa[gg].graphGroup == row.graphGroup)\r
1057                        {\r
1058                          drawLineGraph(g, aa[gg], startRes, endRes, y,\r
1059                                        groupmin, groupmax,\r
1060                                        row.graphHeight);\r
1061                        }\r
1062                      }\r
1063 \r
1064                      graphGroupDrawn[ row.graphGroup ] = true;\r
1065                    }\r
1066                    else\r
1067                      drawLineGraph(g, row, startRes, endRes,\r
1068                                    y, row.graphMin, row.graphMax, row.graphHeight  );\r
1069                 }\r
1070                 else if(row.graph == AlignmentAnnotation.BAR_GRAPH )\r
1071                    drawBarGraph(g, row, startRes, endRes,\r
1072                                 row.graphMin, row.graphMax, y);\r
1073             }\r
1074 \r
1075             if (row.graph>0 && row.hasText)\r
1076             {\r
1077                 y += av.charHeight;\r
1078             }\r
1079 \r
1080             if (row.graph==0)\r
1081             {\r
1082                 y += aa[i].height;\r
1083             }\r
1084         }\r
1085     }\r
1086 \r
1087     public void drawLineGraph(Graphics g, AlignmentAnnotation aa,\r
1088                               int sRes, int eRes,\r
1089                               int y,\r
1090                               float min, float max,\r
1091                               int graphHeight)\r
1092     {\r
1093       if(sRes>aa.annotations.length)\r
1094         return;\r
1095 \r
1096 \r
1097       int x = 0;\r
1098 \r
1099       //Adjustment for fastpaint to left\r
1100       if(eRes<av.endRes)\r
1101         eRes++;\r
1102 \r
1103       eRes = Math.min(eRes, aa.annotations.length);\r
1104 \r
1105       if(sRes==0)\r
1106       {\r
1107         x++;\r
1108       }\r
1109 \r
1110       int y1=y, y2=y;\r
1111       float range = max - min;\r
1112 \r
1113       ////Draw origin\r
1114       if(min<0)\r
1115         y2 = y - (int)((0-min / range)*graphHeight);\r
1116 \r
1117       g.setColor(Color.gray);\r
1118       g.drawLine(x-av.charWidth,y2,(eRes-sRes+1)*av.charWidth,y2);\r
1119 \r
1120       eRes = Math.min(eRes, aa.annotations.length);\r
1121 \r
1122       int column;\r
1123       int aaMax = aa.annotations.length-1;\r
1124 \r
1125       while( x < eRes - sRes )\r
1126       {\r
1127         column = sRes + x;\r
1128         if(av.hasHiddenColumns)\r
1129         {\r
1130           column = av.getColumnSelection().adjustForHiddenColumns(column);\r
1131         }\r
1132 \r
1133         if (column > aaMax)\r
1134         {\r
1135           break;\r
1136         }\r
1137 \r
1138         if(aa.annotations[column]==null || aa.annotations[column-1]==null)\r
1139         {\r
1140           x++;\r
1141           continue;\r
1142         }\r
1143 \r
1144 \r
1145           g.setColor(aa.annotations[column].colour);\r
1146           y1 = y - (int) (((aa.annotations[column-1].value-min) / range) * graphHeight);\r
1147           y2 = y - (int) (((aa.annotations[column].value-min) / range) * graphHeight);\r
1148 \r
1149           g.drawLine(x*av.charWidth-av.charWidth/2, y1, x*av.charWidth+av.charWidth/2, y2);\r
1150           x ++;\r
1151        }\r
1152 \r
1153        if(aa.threshold!=null)\r
1154        {\r
1155            g.setColor(aa.threshold.colour);\r
1156            Graphics2D g2 = (Graphics2D)g;\r
1157            g2.setStroke(new BasicStroke(1,\r
1158                                          BasicStroke.CAP_SQUARE,\r
1159                                          BasicStroke.JOIN_ROUND, 3f,\r
1160                                          new float[] { 5f, 3f }, 0f));\r
1161 \r
1162            y2 = (int)(y - ((aa.threshold.value-min) / range)*graphHeight);\r
1163            g.drawLine(0,y2,(eRes-sRes)*av.charWidth,y2);\r
1164            g2.setStroke(new BasicStroke());\r
1165       }\r
1166     }\r
1167 \r
1168     public void drawBarGraph(Graphics g, AlignmentAnnotation aa,\r
1169                              int sRes, int eRes,\r
1170                              float min, float max,\r
1171                              int y)\r
1172     {\r
1173       if(sRes>aa.annotations.length)\r
1174         return;\r
1175 \r
1176       eRes = Math.min(eRes, aa.annotations.length);\r
1177 \r
1178       int x=0, y1=y, y2=y;\r
1179 \r
1180       float range = max - min;\r
1181 \r
1182       if(min<0)\r
1183         y2 = y - (int)((0-min / (range))*aa.graphHeight);\r
1184 \r
1185       g.setColor(Color.gray);\r
1186 \r
1187       g.drawLine(x,y2,(eRes-sRes)*av.charWidth,y2);\r
1188 \r
1189       int column;\r
1190       int aaMax = aa.annotations.length-1;\r
1191 \r
1192       while( x < eRes-sRes )\r
1193       {\r
1194         column = sRes + x;\r
1195         if(av.hasHiddenColumns)\r
1196         {\r
1197           column = av.getColumnSelection().adjustForHiddenColumns(column);\r
1198         }\r
1199 \r
1200         if(column > aaMax)\r
1201         {\r
1202             break;\r
1203         }\r
1204 \r
1205         if (aa.annotations[column] == null)\r
1206         {\r
1207           x ++;\r
1208           continue;\r
1209         }\r
1210 \r
1211           g.setColor(aa.annotations[column].colour);\r
1212           y1 = y - (int) (((aa.annotations[column].value-min) / (range)) * aa.graphHeight);\r
1213 \r
1214           if(y1-y2>0)\r
1215             g.fillRect(x*av.charWidth, y2, av.charWidth, y1-y2 );\r
1216           else\r
1217             g.fillRect(x*av.charWidth, y1, av.charWidth, y2-y1 );\r
1218 \r
1219           x ++ ;\r
1220 \r
1221       }\r
1222       if(aa.threshold!=null)\r
1223       {\r
1224           g.setColor(aa.threshold.colour);\r
1225           Graphics2D g2 = (Graphics2D)g;\r
1226           g2.setStroke(new BasicStroke(1,\r
1227                                         BasicStroke.CAP_SQUARE,\r
1228                                         BasicStroke.JOIN_ROUND, 3f,\r
1229                                         new float[] { 5f, 3f }, 0f));\r
1230 \r
1231           y2 = (int)(y - ((aa.threshold.value-min) / range)*aa.graphHeight);\r
1232           g.drawLine(0,y2,(eRes-sRes)*av.charWidth,y2);\r
1233           g2.setStroke(new BasicStroke());\r
1234       }\r
1235     }\r
1236 \r
1237     // used by overview window\r
1238     public void drawGraph(Graphics g, AlignmentAnnotation aa, int width, int y, int sRes, int eRes)\r
1239     {\r
1240       eRes = Math.min(eRes, aa.annotations.length);\r
1241       g.setColor(Color.white);\r
1242       g.fillRect(0, 0, width, y);\r
1243       g.setColor(new Color(0, 0, 180));\r
1244 \r
1245       int x = 0, height;\r
1246 \r
1247       for (int j = sRes; j < eRes; j++)\r
1248       {\r
1249         if (aa.annotations[j] != null)\r
1250         {\r
1251           g.setColor(aa.annotations[j].colour);\r
1252 \r
1253           height = (int) ( (aa.annotations[j].value / aa.graphMax) * y);\r
1254           if (height > y)\r
1255             height = y;\r
1256 \r
1257           g.fillRect(x, y - height, av.charWidth, height);\r
1258         }\r
1259           x += av.charWidth;\r
1260       }\r
1261     }\r
1262 \r
1263 }\r