vamsasDemo new branch
[jalview.git] / src / jalview / gui / AlignmentPanel.java
1 /*\r
2  * Jalview - A Sequence Alignment Editor and Viewer\r
3  * Copyright (C) 2005 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle\r
4  *\r
5  * This program is free software; you can redistribute it and/or\r
6  * modify it under the terms of the GNU General Public License\r
7  * as published by the Free Software Foundation; either version 2\r
8  * of the License, or (at your option) any later version.\r
9  *\r
10  * This program is distributed in the hope that it will be useful,\r
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
13  * GNU General Public License for more details.\r
14  *\r
15  * You should have received a copy of the GNU General Public License\r
16  * along with this program; if not, write to the Free Software\r
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA\r
18  */\r
19 package jalview.gui;\r
20 \r
21 import jalview.datamodel.*;\r
22 \r
23 import jalview.jbgui.*;\r
24 \r
25 import jalview.schemes.*;\r
26 \r
27 import org.jibble.epsgraphics.*;\r
28 \r
29 import java.awt.*;\r
30 import java.awt.event.*;\r
31 import java.awt.image.*;\r
32 import java.awt.print.*;\r
33 \r
34 import java.io.*;\r
35 \r
36 import javax.imageio.*;\r
37 \r
38 import javax.swing.*;\r
39 \r
40 \r
41 /**\r
42  * DOCUMENT ME!\r
43  *\r
44  * @author $author$\r
45  * @version $Revision$\r
46  */\r
47 public class AlignmentPanel extends GAlignmentPanel\r
48     implements AdjustmentListener, Printable\r
49 {\r
50     public AlignViewport av;\r
51     OverviewPanel overviewPanel;\r
52     SeqPanel seqPanel;\r
53     IdPanel idPanel;\r
54     IdwidthAdjuster idwidthAdjuster;\r
55 \r
56     /** DOCUMENT ME!! */\r
57     public AlignFrame alignFrame;\r
58     ScalePanel scalePanel;\r
59     AnnotationPanel annotationPanel;\r
60     AnnotationLabels alabels;\r
61 \r
62     // this value is set false when selection area being dragged\r
63     boolean fastPaint = true;\r
64     int hextent = 0;\r
65     int vextent = 0;\r
66 \r
67     /**\r
68      * Creates a new AlignmentPanel object.\r
69      *\r
70      * @param af DOCUMENT ME!\r
71      * @param av DOCUMENT ME!\r
72      */\r
73     public AlignmentPanel(AlignFrame af, final AlignViewport av)\r
74     {\r
75         alignFrame = af;\r
76         this.av = av;\r
77         seqPanel = new SeqPanel(av, this);\r
78         idPanel = new IdPanel(av, this);\r
79 \r
80         scalePanel = new ScalePanel(av, this);\r
81 \r
82         idPanelHolder.add(idPanel, BorderLayout.CENTER);\r
83         idwidthAdjuster = new IdwidthAdjuster(this);\r
84         idSpaceFillerPanel1.add(idwidthAdjuster, BorderLayout.CENTER);\r
85 \r
86         annotationPanel = new AnnotationPanel(this);\r
87         alabels = new AnnotationLabels(this);\r
88 \r
89         annotationSpaceFillerHolder.setPreferredSize(annotationPanel.getPreferredSize());\r
90         annotationScroller.setPreferredSize(annotationPanel.getPreferredSize());\r
91         annotationScroller.setViewportView(annotationPanel);\r
92         annotationSpaceFillerHolder.add(alabels, BorderLayout.CENTER);\r
93 \r
94         fontChanged();\r
95 \r
96         scalePanelHolder.add(scalePanel, BorderLayout.CENTER);\r
97         seqPanelHolder.add(seqPanel, BorderLayout.CENTER);\r
98 \r
99         setScrollValues(0, 0);\r
100 \r
101         annotationPanel.adjustPanelHeight();\r
102         annotationSpaceFillerHolder.setPreferredSize(annotationPanel.getPreferredSize());\r
103         annotationScroller.setPreferredSize(annotationPanel.\r
104                                             getPreferredSize());\r
105         setAnnotationVisible(av.getShowAnnotation());\r
106 \r
107 \r
108         hscroll.addAdjustmentListener(this);\r
109         vscroll.addAdjustmentListener(this);\r
110 \r
111         af.addKeyListener(new KeyAdapter()\r
112             {\r
113                 public void keyPressed(KeyEvent evt)\r
114                 {\r
115                     switch (evt.getKeyCode())\r
116                     {\r
117                     case 27: // escape key\r
118                         av.setSelectionGroup(null);\r
119                         repaint();\r
120 \r
121                         break;\r
122 \r
123                     case KeyEvent.VK_DOWN:\r
124                         alignFrame.moveSelectedSequences(false);\r
125 \r
126                         break;\r
127 \r
128                     case KeyEvent.VK_UP:\r
129                         alignFrame.moveSelectedSequences(true);\r
130 \r
131                         break;\r
132 \r
133                     case KeyEvent.VK_BACK_SPACE:\r
134                     case KeyEvent.VK_DELETE:\r
135                       alignFrame.cut_actionPerformed(null);\r
136                       break;\r
137 \r
138                     case KeyEvent.VK_P:\r
139                       seqPanel.seqCanvas.increaseAARatio();\r
140                       break;\r
141                     case KeyEvent.VK_L:\r
142                       seqPanel.seqCanvas.decreaseAARation();\r
143                       break;\r
144                     }\r
145                 }\r
146             });\r
147     }\r
148 \r
149 \r
150     /**\r
151      * DOCUMENT ME!\r
152      */\r
153     public void fontChanged()\r
154     {\r
155         // set idCanvas bufferedImage to null\r
156         // to prevent drawing old image\r
157         FontMetrics fm = getFontMetrics(av.getFont());\r
158 \r
159         scalePanelHolder.setPreferredSize(new Dimension(10,\r
160                 av.charHeight + fm.getDescent()));\r
161         idSpaceFillerPanel1.setPreferredSize(new Dimension(10,\r
162                 av.charHeight + fm.getDescent()));\r
163 \r
164         idPanel.idCanvas.gg = null;\r
165         seqPanel.seqCanvas.img = null;\r
166         annotationPanel.adjustPanelHeight();\r
167 \r
168         Dimension d = calculateIdWidth();\r
169         d.setSize(d.width + 4, d.height);\r
170         idPanel.idCanvas.setPreferredSize(d);\r
171         hscrollFillerPanel.setPreferredSize(d);\r
172 \r
173         if (av.getWrapAlignment())\r
174         {\r
175           int max = av.alignment.getWidth() /\r
176               seqPanel.seqCanvas.getWrappedCanvasWidth(seqPanel.seqCanvas.getWidth());\r
177           vscroll.setMaximum(max);\r
178           vscroll.setUnitIncrement(1);\r
179           vscroll.setVisibleAmount(1);\r
180         }\r
181         else\r
182         {\r
183           setScrollValues(av.getStartRes(), av.getStartSeq());\r
184         }\r
185 \r
186         if(overviewPanel!=null)\r
187           overviewPanel.setBoxPosition();\r
188 \r
189         repaint();\r
190     }\r
191 \r
192     /**\r
193      * DOCUMENT ME!\r
194      *\r
195      * @return DOCUMENT ME!\r
196      */\r
197     public Dimension calculateIdWidth()\r
198     {\r
199       Container c = new Container();\r
200 \r
201         FontMetrics fm = c.getFontMetrics(av.font);\r
202         AlignmentI al = av.getAlignment();\r
203 \r
204         int i = 0;\r
205         int idWidth = 0;\r
206         String id;\r
207 \r
208         while ((i < al.getHeight()) && (al.getSequenceAt(i) != null))\r
209         {\r
210             SequenceI s = al.getSequenceAt(i);\r
211 \r
212             if (av.getShowFullId())\r
213             {\r
214                 id = s.getDisplayId();\r
215             }\r
216             else\r
217             {\r
218                 id = s.getName();\r
219             }\r
220 \r
221             if (fm.stringWidth(id) > idWidth)\r
222             {\r
223                 idWidth = fm.stringWidth(id);\r
224             }\r
225 \r
226             i++;\r
227         }\r
228 \r
229         // Also check annotation label widths\r
230         i = 0;\r
231 \r
232         if (al.getAlignmentAnnotation() != null)\r
233         {\r
234             fm = c.getFontMetrics(alabels.getFont());\r
235 \r
236             while (i < al.getAlignmentAnnotation().length)\r
237             {\r
238                 String label = al.getAlignmentAnnotation()[i].label;\r
239 \r
240                 if (fm.stringWidth(label) > idWidth)\r
241                 {\r
242                     idWidth = fm.stringWidth(label);\r
243                 }\r
244 \r
245                 i++;\r
246             }\r
247         }\r
248 \r
249         return new Dimension(idWidth, 12);\r
250     }\r
251 \r
252     /**\r
253      * DOCUMENT ME!\r
254      *\r
255      * @param results DOCUMENT ME!\r
256      */\r
257     public void highlightSearchResults(int[] results)\r
258     {\r
259         seqPanel.seqCanvas.highlightSearchResults(results);\r
260 \r
261         // do we need to scroll the panel?\r
262         if (results != null)\r
263         {\r
264             SequenceI seq = av.alignment.getSequenceAt(results[0]);\r
265             int start = seq.findIndex(results[1]) - 1;\r
266             int end = seq.findIndex(results[2]) - 1;\r
267 \r
268             if ((av.getStartRes() > start) || (av.getEndRes() < end) ||\r
269                     ((av.getStartSeq() > results[0]) ||\r
270                     (av.getEndSeq() < results[0])))\r
271             {\r
272                 setScrollValues(start, results[0]);\r
273             }\r
274         }\r
275     }\r
276 \r
277     /**\r
278      * DOCUMENT ME!\r
279      *\r
280      * @return DOCUMENT ME!\r
281      */\r
282     public OverviewPanel getOverviewPanel()\r
283     {\r
284         return overviewPanel;\r
285     }\r
286 \r
287     /**\r
288      * DOCUMENT ME!\r
289      *\r
290      * @param op DOCUMENT ME!\r
291      */\r
292     public void setOverviewPanel(OverviewPanel op)\r
293     {\r
294         overviewPanel = op;\r
295     }\r
296 \r
297     /**\r
298      * DOCUMENT ME!\r
299      *\r
300      * @param b DOCUMENT ME!\r
301      */\r
302     public void setAnnotationVisible(boolean b)\r
303     {\r
304       if (!av.wrapAlignment)\r
305       {\r
306         annotationSpaceFillerHolder.setVisible(b);\r
307         annotationScroller.setVisible(b);\r
308       }\r
309       repaint();\r
310     }\r
311 \r
312     /**\r
313      * DOCUMENT ME!\r
314      *\r
315      * @param wrap DOCUMENT ME!\r
316      */\r
317     public void setWrapAlignment(boolean wrap)\r
318     {\r
319         av.startSeq = 0;\r
320         scalePanelHolder.setVisible(!wrap);\r
321         hscroll.setVisible(!wrap);\r
322         idwidthAdjuster.setVisible(!wrap);\r
323 \r
324        if(wrap)\r
325        {\r
326          annotationScroller.setVisible(false);\r
327          annotationSpaceFillerHolder.setVisible(false);\r
328        }\r
329        else if(av.showAnnotation)\r
330        {\r
331          annotationScroller.setVisible(true);\r
332          annotationSpaceFillerHolder.setVisible(true);\r
333        }\r
334 \r
335        idSpaceFillerPanel1.setVisible(!wrap);\r
336 \r
337         repaint();\r
338     }\r
339 \r
340 \r
341     // return value is true if the scroll is valid\r
342     public boolean scrollUp(boolean up)\r
343     {\r
344         if (up)\r
345         {\r
346             if (vscroll.getValue() < 1)\r
347             {\r
348                 return false;\r
349             }\r
350 \r
351             fastPaint = false;\r
352             vscroll.setValue(vscroll.getValue() - 1);\r
353         }\r
354         else\r
355         {\r
356             if ((vextent + vscroll.getValue()) >= av.getAlignment().getHeight())\r
357             {\r
358                 return false;\r
359             }\r
360 \r
361             fastPaint = false;\r
362             vscroll.setValue(vscroll.getValue() + 1);\r
363         }\r
364 \r
365         fastPaint = true;\r
366 \r
367         return true;\r
368     }\r
369 \r
370     /**\r
371      * DOCUMENT ME!\r
372      *\r
373      * @param right DOCUMENT ME!\r
374      *\r
375      * @return DOCUMENT ME!\r
376      */\r
377     public boolean scrollRight(boolean right)\r
378     {\r
379         if (right)\r
380         {\r
381             if (hscroll.getValue() < 1)\r
382             {\r
383                 return false;\r
384             }\r
385 \r
386             fastPaint = false;\r
387             hscroll.setValue(hscroll.getValue() - 1);\r
388         }\r
389         else\r
390         {\r
391             if ((hextent + hscroll.getValue()) >= av.getAlignment().getWidth())\r
392             {\r
393                 return false;\r
394             }\r
395 \r
396             fastPaint = false;\r
397             hscroll.setValue(hscroll.getValue() + 1);\r
398         }\r
399 \r
400         fastPaint = true;\r
401 \r
402         return true;\r
403     }\r
404 \r
405     /**\r
406      * DOCUMENT ME!\r
407      *\r
408      * @param x DOCUMENT ME!\r
409      * @param y DOCUMENT ME!\r
410      */\r
411     public void setScrollValues(int x, int y)\r
412     {\r
413         av.setEndRes((x + (seqPanel.seqCanvas.getWidth() / av.getCharWidth())) -\r
414             1);\r
415 \r
416         hextent = seqPanel.seqCanvas.getWidth() / av.charWidth;\r
417         vextent = seqPanel.seqCanvas.getHeight() / av.charHeight;\r
418 \r
419         if (hextent > av.alignment.getWidth())\r
420         {\r
421             hextent = av.alignment.getWidth();\r
422         }\r
423 \r
424         if (vextent > av.alignment.getHeight())\r
425         {\r
426             vextent = av.alignment.getHeight();\r
427         }\r
428 \r
429         if ((hextent + x) > av.getAlignment().getWidth())\r
430         {\r
431             x = av.getAlignment().getWidth() - hextent;\r
432         }\r
433 \r
434         if ((vextent + y) > av.getAlignment().getHeight())\r
435         {\r
436             y = av.getAlignment().getHeight() - vextent;\r
437         }\r
438 \r
439         if (y < 0)\r
440         {\r
441             y = 0;\r
442         }\r
443 \r
444         if (x < 0)\r
445         {\r
446             x = 0;\r
447         }\r
448 \r
449         hscroll.setValues(x, hextent, 0, av.getAlignment().getWidth());\r
450         vscroll.setValues(y, vextent, 0, av.getAlignment().getHeight());\r
451     }\r
452 \r
453 \r
454     /**\r
455      * DOCUMENT ME!\r
456      *\r
457      * @param evt DOCUMENT ME!\r
458      */\r
459     public void adjustmentValueChanged(AdjustmentEvent evt)\r
460     {\r
461 \r
462         int oldX = av.getStartRes();\r
463         int oldY = av.getStartSeq();\r
464 \r
465         if (evt.getSource() == hscroll)\r
466         {\r
467             int x = hscroll.getValue();\r
468             av.setStartRes(x);\r
469             av.setEndRes((x +\r
470                 (seqPanel.seqCanvas.getWidth() / av.getCharWidth())) - 1);\r
471         }\r
472 \r
473         if (evt.getSource() == vscroll)\r
474         {\r
475             int offy = vscroll.getValue();\r
476 \r
477             if (av.getWrapAlignment())\r
478             {\r
479                 int rowSize = seqPanel.seqCanvas.getWrappedCanvasWidth(seqPanel.seqCanvas.getWidth());\r
480                 av.setStartRes(vscroll.getValue() * rowSize);\r
481                 av.setEndRes((vscroll.getValue() + 1) * rowSize);\r
482             }\r
483             else\r
484             {\r
485                 av.setStartSeq(offy);\r
486                 av.setEndSeq(offy +\r
487                     (seqPanel.seqCanvas.getHeight() / av.getCharHeight()));\r
488             }\r
489         }\r
490 \r
491         if (overviewPanel != null)\r
492         {\r
493             overviewPanel.setBoxPosition();\r
494         }\r
495 \r
496         int xShift = av.getStartRes() - oldX;\r
497         int yShift = av.getStartSeq() - oldY;\r
498 \r
499         if ( (xShift != 0 && yShift != 0) ||\r
500             (Math.abs(xShift) > av.getEndRes() - av.getStartRes()\r
501              || Math.abs(yShift) > av.getEndSeq() - av.getStartSeq())\r
502              || av.getWrapAlignment()\r
503              || !fastPaint)\r
504         {\r
505           // Either no shift at all, or shift greater than visible amount\r
506           repaint();\r
507         }\r
508         else\r
509         {\r
510             idPanel.idCanvas.fastPaint(yShift);\r
511             seqPanel.seqCanvas.fastPaint(xShift, yShift);\r
512 \r
513             scalePanel.repaint();\r
514 \r
515             if (av.getShowAnnotation())\r
516             {\r
517                 annotationPanel.fastPaint(xShift);\r
518             }\r
519         }\r
520     }\r
521 \r
522     /**\r
523      * DOCUMENT ME!\r
524      *\r
525      * @param g DOCUMENT ME!\r
526      */\r
527     public void paintComponent(Graphics g)\r
528     {\r
529         invalidate();\r
530 \r
531         Dimension d = idPanel.idCanvas.getPreferredSize();\r
532         idPanelHolder.setPreferredSize(d);\r
533         hscrollFillerPanel.setPreferredSize(new Dimension(d.width, 12));\r
534         validate();\r
535 \r
536         if (av.getWrapAlignment())\r
537         {\r
538             int max = av.alignment.getWidth() / seqPanel.seqCanvas.getWrappedCanvasWidth(seqPanel.seqCanvas.getWidth());\r
539             vscroll.setMaximum(max);\r
540             vscroll.setUnitIncrement(1);\r
541             vscroll.setVisibleAmount(1);\r
542         }\r
543         else\r
544         {\r
545             setScrollValues(av.getStartRes(), av.getStartSeq());\r
546         }\r
547     }\r
548 \r
549     /**\r
550      * DOCUMENT ME!\r
551      *\r
552      * @param pg DOCUMENT ME!\r
553      * @param pf DOCUMENT ME!\r
554      * @param pi DOCUMENT ME!\r
555      *\r
556      * @return DOCUMENT ME!\r
557      *\r
558      * @throws PrinterException DOCUMENT ME!\r
559      */\r
560     public int print(Graphics pg, PageFormat pf, int pi)\r
561         throws PrinterException\r
562     {\r
563         pg.translate((int) pf.getImageableX(), (int) pf.getImageableY());\r
564 \r
565         int pwidth = (int) pf.getImageableWidth();\r
566         int pheight = (int) pf.getImageableHeight();\r
567 \r
568         if (av.getWrapAlignment())\r
569         {\r
570             return printWrappedAlignment(pg, pwidth, pheight, pi);\r
571         }\r
572         else\r
573         {\r
574             return printUnwrapped(pg, pwidth, pheight, pi);\r
575         }\r
576     }\r
577 \r
578     /**\r
579      * DOCUMENT ME!\r
580      *\r
581      * @param pg DOCUMENT ME!\r
582      * @param pwidth DOCUMENT ME!\r
583      * @param pheight DOCUMENT ME!\r
584      * @param pi DOCUMENT ME!\r
585      *\r
586      * @return DOCUMENT ME!\r
587      *\r
588      * @throws PrinterException DOCUMENT ME!\r
589      */\r
590     public int printUnwrapped(Graphics pg, int pwidth, int pheight, int pi)\r
591         throws PrinterException\r
592     {\r
593         int idWidth = calculateIdWidth().width + 4;\r
594         FontMetrics fm = getFontMetrics(av.getFont());\r
595         int scaleHeight = av.charHeight + fm.getDescent();\r
596 \r
597         pg.setColor(Color.white);\r
598         pg.fillRect(0, 0, pwidth, pheight);\r
599         pg.setFont(av.getFont());\r
600 \r
601         ////////////////////////////////////\r
602         /// How many sequences and residues can we fit on a printable page?\r
603         int totalRes = (pwidth - idWidth) / av.getCharWidth();\r
604 \r
605         int totalSeq = (int) ((pheight - scaleHeight) / av.getCharHeight()) -\r
606             1;\r
607 \r
608         int pagesWide = (av.getAlignment().getWidth() / totalRes) + 1;\r
609 \r
610         /////////////////////////////\r
611         /// Only print these sequences and residues on this page\r
612         int startRes;\r
613 \r
614         /////////////////////////////\r
615         /// Only print these sequences and residues on this page\r
616         int endRes;\r
617 \r
618         /////////////////////////////\r
619         /// Only print these sequences and residues on this page\r
620         int startSeq;\r
621 \r
622         /////////////////////////////\r
623         /// Only print these sequences and residues on this page\r
624         int endSeq;\r
625         startRes = (pi % pagesWide) * totalRes;\r
626         endRes = (startRes + totalRes) - 1;\r
627 \r
628         if (endRes > (av.getAlignment().getWidth() - 1))\r
629         {\r
630             endRes = av.getAlignment().getWidth() - 1;\r
631         }\r
632 \r
633         startSeq = (pi / pagesWide) * totalSeq;\r
634         endSeq = startSeq + totalSeq;\r
635 \r
636         if (endSeq > av.getAlignment().getHeight())\r
637         {\r
638             endSeq = av.getAlignment().getHeight();\r
639         }\r
640 \r
641         int pagesHigh = ((av.alignment.getHeight() / totalSeq) + 1) * pheight;\r
642 \r
643         if (av.showAnnotation)\r
644         {\r
645             pagesHigh += annotationPanel.adjustPanelHeight()+3;\r
646         }\r
647 \r
648         pagesHigh /= pheight;\r
649 \r
650         if (pi >= (pagesWide * pagesHigh))\r
651         {\r
652             return Printable.NO_SUCH_PAGE;\r
653         }\r
654 \r
655         //draw Scale\r
656         pg.translate(idWidth, 0);\r
657         scalePanel.drawScale(pg, startRes, endRes, pwidth - idWidth, scaleHeight);\r
658         pg.translate(-idWidth, scaleHeight);\r
659 \r
660         ////////////////\r
661         // Draw the ids\r
662         Color currentColor = null;\r
663         Color currentTextColor = null;\r
664 \r
665         for (int i = startSeq; i < endSeq; i++)\r
666         {\r
667             if ((av.getSelectionGroup() != null) &&\r
668                     av.getSelectionGroup().sequences.contains(\r
669                         av.getAlignment().getSequenceAt(i)))\r
670             {\r
671                 currentColor = Color.gray;\r
672                 currentTextColor = Color.black;\r
673             }\r
674             else\r
675             {\r
676                 currentColor = av.getAlignment().getSequenceAt(i).getColor();\r
677                 currentTextColor = Color.black;\r
678             }\r
679 \r
680             pg.setColor(currentColor);\r
681             pg.fillRect(0, (i-startSeq) * av.charHeight, idWidth,\r
682                 av.getCharHeight());\r
683 \r
684             pg.setColor(currentTextColor);\r
685 \r
686             String string = av.getAlignment().getSequenceAt(i).getName();\r
687 \r
688             if (av.getShowFullId())\r
689             {\r
690                 string = av.getAlignment().getSequenceAt(i).getDisplayId();\r
691             }\r
692 \r
693             pg.drawString(string, 0,\r
694                 (((i-startSeq) * av.charHeight) + av.getCharHeight()) -\r
695                 (av.getCharHeight() / 5));\r
696         }\r
697 \r
698         // draw main sequence panel\r
699         pg.translate(idWidth, 0);\r
700         seqPanel.seqCanvas.drawPanel(pg, startRes, endRes, startSeq, endSeq,\r
701             startRes, startSeq, 0);\r
702 \r
703         if (av.showAnnotation && (endSeq == av.alignment.getHeight()))\r
704         {\r
705             pg.translate(-idWidth, (endSeq - startSeq) * av.charHeight +3);\r
706             alabels.drawComponent((Graphics2D) pg, idWidth);\r
707             pg.translate(idWidth, 0);\r
708             annotationPanel.drawComponent((Graphics2D) pg, startRes, endRes +\r
709                 1);\r
710         }\r
711 \r
712         return Printable.PAGE_EXISTS;\r
713     }\r
714 \r
715     /**\r
716      * DOCUMENT ME!\r
717      *\r
718      * @param pg DOCUMENT ME!\r
719      * @param pwidth DOCUMENT ME!\r
720      * @param pheight DOCUMENT ME!\r
721      * @param pi DOCUMENT ME!\r
722      *\r
723      * @return DOCUMENT ME!\r
724      *\r
725      * @throws PrinterException DOCUMENT ME!\r
726      */\r
727     public int printWrappedAlignment(Graphics pg, int pwidth, int pheight,\r
728         int pi) throws PrinterException\r
729     {\r
730 \r
731       int annotationHeight = 0;\r
732       AnnotationLabels labels = null;\r
733       if (av.showAnnotation)\r
734       {\r
735         annotationHeight = annotationPanel.adjustPanelHeight();\r
736         labels = new AnnotationLabels(av);\r
737       }\r
738 \r
739       int hgap = av.charHeight;\r
740       if (av.scaleAboveWrapped)\r
741         hgap += av.charHeight;\r
742 \r
743       int cHeight = av.getAlignment().getHeight() * av.charHeight\r
744           + hgap\r
745           + annotationHeight;\r
746 \r
747 \r
748       int idWidth = calculateIdWidth().width + 4;\r
749 \r
750         int resWidth = seqPanel.seqCanvas.getWrappedCanvasWidth(pwidth -\r
751                 idWidth);\r
752 \r
753         int totalHeight = cHeight * (av.alignment.getWidth() / resWidth +1);\r
754 \r
755         pg.setColor(Color.white);\r
756         pg.fillRect(0, 0, pwidth, pheight);\r
757         pg.setFont(av.getFont());\r
758 \r
759 \r
760         ////////////////\r
761         // Draw the ids\r
762         pg.setColor(Color.black);\r
763 \r
764         pg.translate(0, -pi * pheight);\r
765 \r
766         pg.setClip(0, pi * pheight, pwidth, pheight);\r
767 \r
768         int ypos = hgap;\r
769         Font italic = new Font(av.getFont().getName(), Font.ITALIC,\r
770                              av.getFont().getSize());\r
771         pg.setFont(italic);\r
772 \r
773 \r
774         do\r
775         {\r
776           for (int i = 0; i < av.alignment.getHeight(); i++)\r
777           {\r
778             SequenceI s = av.alignment.getSequenceAt(i);\r
779             String string = s.getName();\r
780 \r
781             if (av.getShowFullId())\r
782             {\r
783               string = s.getDisplayId();\r
784             }\r
785 \r
786             pg.drawString(string, 0,\r
787                           ( (i * av.charHeight) + ypos + av.charHeight) -\r
788                           (av.charHeight / 5));\r
789           }\r
790             if (labels != null)\r
791             {\r
792               pg.translate(0,\r
793                            ypos +\r
794                            (av.getAlignment().getHeight() * av.charHeight));\r
795 \r
796               pg.setFont(av.getFont());\r
797               labels.drawComponent( pg, idWidth );\r
798               pg.setFont(italic);\r
799               pg.translate(0,\r
800                            -ypos -\r
801                            (av.getAlignment().getHeight() * av.charHeight));\r
802             }\r
803 \r
804             ypos += cHeight;\r
805         }\r
806         while (ypos < totalHeight);\r
807 \r
808         pg.translate(idWidth, 0);\r
809 \r
810         seqPanel.seqCanvas.drawWrappedPanel(pg, pwidth - idWidth, totalHeight, 0);\r
811 \r
812         if ((pi * pheight) < totalHeight)\r
813         {\r
814             return Printable.PAGE_EXISTS;\r
815 \r
816         }\r
817      else\r
818         {\r
819             return Printable.NO_SUCH_PAGE;\r
820         }\r
821     }\r
822 \r
823     /**\r
824      * DOCUMENT ME!\r
825      */\r
826     public void makeEPS(File epsFile)\r
827     {\r
828       boolean accurateText = true;\r
829 \r
830       String renderStyle = jalview.bin.Cache.getDefault("EPS_RENDERING",\r
831           "Prompt each time");\r
832 \r
833       // If we need to prompt, and if the GUI is visible then\r
834       // Prompt for EPS rendering style\r
835       if (renderStyle.equalsIgnoreCase("Prompt each time")\r
836           && !\r
837           (System.getProperty("java.awt.headless") != null\r
838            && System.getProperty("java.awt.headless").equals("true")))\r
839       {\r
840         EPSOptions eps = new EPSOptions();\r
841         renderStyle = eps.getValue();\r
842 \r
843         if(eps.cancelled || renderStyle==null)\r
844           return;\r
845 \r
846         renderStyle = eps.getValue();\r
847       }\r
848 \r
849       if (renderStyle.equalsIgnoreCase("text"))\r
850       {\r
851         accurateText = false;\r
852       }\r
853 \r
854 \r
855         if(epsFile == null)\r
856         {\r
857           jalview.io.JalviewFileChooser chooser = new jalview.io.\r
858               JalviewFileChooser(jalview.bin.Cache.getProperty(\r
859                   "LAST_DIRECTORY"), new String[]\r
860                                  {"eps"},\r
861                                  new String[]\r
862                                  {"Encapsulated Postscript"},\r
863                                  "Encapsulated Postscript");\r
864           chooser.setFileView(new jalview.io.JalviewFileView());\r
865           chooser.setDialogTitle("Create EPS file from alignment");\r
866           chooser.setToolTipText("Save");\r
867 \r
868           int value = chooser.showSaveDialog(this);\r
869 \r
870           if (value != jalview.io.JalviewFileChooser.APPROVE_OPTION)\r
871           {\r
872             return;\r
873           }\r
874 \r
875           epsFile = chooser.getSelectedFile();\r
876 \r
877           jalview.bin.Cache.setProperty("LAST_DIRECTORY",\r
878                                         chooser.getSelectedFile().getParent());\r
879         }\r
880 \r
881 \r
882         int height = ( (av.alignment.getHeight() + 1) * av.charHeight) + 30;\r
883         int width = idPanel.getWidth() + (av.alignment.getWidth() * av.charWidth);\r
884 \r
885 \r
886         if (av.getWrapAlignment())\r
887         {\r
888           height = getWrappedHeight();\r
889           width = seqPanel.getWidth() + idPanel.getWidth();\r
890         }\r
891         else if (av.getShowAnnotation())\r
892         {\r
893           height += annotationPanel.adjustPanelHeight()+3;\r
894         }\r
895 \r
896 \r
897         try\r
898          {\r
899            FileOutputStream out = new FileOutputStream(epsFile);\r
900            EpsGraphics2D pg = new EpsGraphics2D("Example", out, 0, 0, width,\r
901                                                 height);\r
902 \r
903            pg.setAccurateTextMode(accurateText);\r
904 \r
905            if (av.getWrapAlignment())\r
906            {\r
907                 printWrappedAlignment(pg, width, height, 0);\r
908             }\r
909             else\r
910             {\r
911                 printUnwrapped(pg, width, height, 0);\r
912             }\r
913 \r
914             pg.flush();\r
915             pg.close();\r
916           }\r
917           catch (OutOfMemoryError err)\r
918           {\r
919             System.out.println("########################\n"\r
920                                + "OUT OF MEMORY " + epsFile + "\n"\r
921                                + "########################");\r
922 \r
923             JOptionPane.showInternalMessageDialog(Desktop.desktop,\r
924                                                   "Out of memory creating EPS file!!"\r
925                                                   +\r
926                                                   "\nSee help files for increasing Java Virtual Machine memory."\r
927                                                   , "Out of memory",\r
928                                                   JOptionPane.WARNING_MESSAGE);\r
929             System.out.println("Create EPS: " + err);\r
930             System.gc();\r
931           }\r
932         catch (Exception ex)\r
933         {\r
934             ex.printStackTrace();\r
935         }\r
936     }\r
937 \r
938 \r
939     public void makePNGImageMap(File imgMapFile, String imageName)\r
940     {\r
941       ///////ONLY WORKS WITH NONE WRAPPED ALIGNMENTS\r
942       //////////////////////////////////////////////\r
943       int idWidth = calculateIdWidth().width + 4;\r
944       FontMetrics fm = getFontMetrics(av.getFont());\r
945       int scaleHeight = av.charHeight + fm.getDescent();\r
946 \r
947         // Gen image map\r
948          //////////////////////////////////\r
949          if(imgMapFile!=null)\r
950          {\r
951            try\r
952            {\r
953              PrintWriter out = new PrintWriter(new FileWriter(imgMapFile));\r
954              out.println(jalview.io.HTMLOutput.getImageMapHTML());\r
955              out.println("<img src=\"" + imageName +\r
956                        "\" border=\"0\" usemap=\"#Map\" >"\r
957                        +"<map name=\"Map\">");\r
958 \r
959              for (int s = 0; s < av.alignment.getHeight(); s++)\r
960              {\r
961                SequenceI seq = av.alignment.getSequenceAt(s);\r
962                SequenceGroup[] groups = av.alignment.findAllGroups(seq);\r
963                for (int i = 0; i < groups.length; i++)\r
964                {\r
965                  int sy = s * av.charHeight + scaleHeight;\r
966                  for (int res = groups[i].getStartRes();\r
967                       res < groups[i].getEndRes() + 1; res++)\r
968                  {\r
969                    int alIndex = seq.findPosition(res);\r
970                    Object obj = ResidueProperties.aa2Triplet.get(\r
971                        seq.getCharAt(res) + "");\r
972                    if (obj == null)\r
973                      continue;\r
974 \r
975                    String triplet = obj.toString();\r
976 \r
977                    out.println(\r
978                        "<area shape=\"rect\" coords=\""\r
979                        + (idWidth + res * av.charWidth) + ","\r
980                        + sy + ","\r
981                        + (idWidth + (res + 1) * av.charWidth) + ","\r
982                        + (av.charHeight + sy) + "\""\r
983                        + " onMouseOver=\"toolTip('"\r
984                        + alIndex + " " + triplet +\r
985                        "<br><em>" + groups[i].getName() +\r
986                        "</em>')\"; onMouseOut=\"toolTip()\"; "\r
987                        + " href=\"#\">");\r
988                  }\r
989                }\r
990              }\r
991 \r
992              out.println("</map></body></html>");\r
993              out.close();\r
994 \r
995            }\r
996            catch (Exception ex)\r
997            {\r
998              ex.printStackTrace();\r
999            }\r
1000          }///////////END OF IMAGE MAP\r
1001 \r
1002     }\r
1003 \r
1004     int getWrappedHeight()\r
1005     {\r
1006 \r
1007       int chunkWidth = seqPanel.seqCanvas.getWrappedCanvasWidth(\r
1008         seqPanel.seqCanvas.getWidth());\r
1009 \r
1010       int hgap = av.charHeight;\r
1011       if (av.scaleAboveWrapped)\r
1012         hgap += av.charHeight;\r
1013 \r
1014       int annotationHeight = 0;\r
1015       if (av.showAnnotation)\r
1016       {\r
1017         annotationHeight = annotationPanel.adjustPanelHeight();\r
1018       }\r
1019 \r
1020       int cHeight = av.getAlignment().getHeight() * av.charHeight\r
1021           + hgap\r
1022           + annotationHeight;\r
1023 \r
1024 \r
1025       int height =  ( (av.alignment.getWidth() / chunkWidth) + 1) * cHeight;\r
1026 \r
1027       return height;\r
1028     }\r
1029 \r
1030     /**\r
1031      * DOCUMENT ME!\r
1032      */\r
1033     public void makePNG(File pngFile)\r
1034     {\r
1035       if(pngFile==null)\r
1036       {\r
1037         jalview.io.JalviewFileChooser chooser = new jalview.io.\r
1038             JalviewFileChooser(jalview.bin.Cache.getProperty(\r
1039                 "LAST_DIRECTORY"), new String[]\r
1040                                {"png"},\r
1041                                new String[]\r
1042                                {"Portable network graphics"},\r
1043                                "Portable network graphics");\r
1044         chooser.setFileView(new jalview.io.JalviewFileView());\r
1045         chooser.setDialogTitle("Create EPS file from alignment");\r
1046         chooser.setToolTipText("Save");\r
1047 \r
1048         int value = chooser.showSaveDialog(this);\r
1049 \r
1050         if (value != jalview.io.JalviewFileChooser.APPROVE_OPTION)\r
1051         {\r
1052           return;\r
1053         }\r
1054 \r
1055         pngFile = chooser.getSelectedFile();\r
1056 \r
1057         jalview.bin.Cache.setProperty("LAST_DIRECTORY",\r
1058                                       chooser.getSelectedFile().getParent());\r
1059       }\r
1060 \r
1061 \r
1062 \r
1063       int height = ( (av.alignment.getHeight() + 1) * av.charHeight) + 30;\r
1064       int width = idPanel.getWidth() + (av.alignment.getWidth() * av.charWidth);\r
1065 \r
1066       if (av.getWrapAlignment())\r
1067       {\r
1068         height = getWrappedHeight();\r
1069         width = seqPanel.getWidth() + idPanel.getWidth();\r
1070       }\r
1071       else if (av.getShowAnnotation())\r
1072         {\r
1073             height += annotationPanel.adjustPanelHeight()+3;\r
1074         }\r
1075 \r
1076         try\r
1077         {\r
1078 \r
1079             FileOutputStream out = new FileOutputStream(pngFile);\r
1080 \r
1081             BufferedImage bi = new BufferedImage(width, height,\r
1082                     BufferedImage.TYPE_INT_RGB);\r
1083             Graphics2D png = (Graphics2D) bi.getGraphics();\r
1084 \r
1085             png.setRenderingHint(RenderingHints.KEY_ANTIALIASING,\r
1086                 RenderingHints.VALUE_ANTIALIAS_ON);\r
1087 \r
1088             if (av.getWrapAlignment())\r
1089             {\r
1090                 printWrappedAlignment(png, width, height, 0);\r
1091             }\r
1092             else\r
1093             {\r
1094                 printUnwrapped(png, width, height, 0);\r
1095             }\r
1096 \r
1097             ImageIO.write(bi, "png", out);\r
1098             out.close();\r
1099         }\r
1100         catch (OutOfMemoryError err)\r
1101         {\r
1102           System.out.println("########################\n"\r
1103                              + "OUT OF MEMORY " + pngFile + "\n"\r
1104                              + "########################");\r
1105 \r
1106           JOptionPane.showInternalMessageDialog(Desktop.desktop,\r
1107                                                 "Out of memory creating PNG!!"\r
1108                                                 +\r
1109                                                 "\nSee help files for increasing Java Virtual Machine memory."\r
1110                                                 , "Out of memory",\r
1111                                                 JOptionPane.WARNING_MESSAGE);\r
1112           System.out.println("Create PNG: " + err);\r
1113           System.gc();\r
1114 \r
1115         }\r
1116         catch (Exception ex)\r
1117         {\r
1118             ex.printStackTrace();\r
1119         }\r
1120     }\r
1121 }\r
1122 \r
1123 \r
1124 /**\r
1125  * DOCUMENT ME!\r
1126  *\r
1127  * @author $author$\r
1128  * @version $Revision$\r
1129  */\r
1130 class Preview extends JFrame\r
1131 {\r
1132     /**\r
1133      * Creates a new Preview object.\r
1134      *\r
1135      * @param image DOCUMENT ME!\r
1136      */\r
1137     public Preview(Image image)\r
1138     {\r
1139         setResizable(true);\r
1140         setSize(image.getWidth(this), image.getHeight(this));\r
1141         setVisible(true);\r
1142         getContentPane().setLayout(new BorderLayout());\r
1143         getContentPane().add(new PreviewPanel(image), BorderLayout.CENTER);\r
1144         validate();\r
1145         repaint();\r
1146     }\r
1147 }\r
1148 \r
1149 \r
1150 /**\r
1151  * DOCUMENT ME!\r
1152  *\r
1153  * @author $author$\r
1154  * @version $Revision$\r
1155  */\r
1156 class PreviewPanel extends JPanel\r
1157 {\r
1158     Image image;\r
1159 \r
1160     /**\r
1161      * Creates a new PreviewPanel object.\r
1162      *\r
1163      * @param image DOCUMENT ME!\r
1164      */\r
1165     public PreviewPanel(Image image)\r
1166     {\r
1167         this.image = image;\r
1168     }\r
1169 \r
1170     /**\r
1171      * DOCUMENT ME!\r
1172      *\r
1173      * @param g DOCUMENT ME!\r
1174      */\r
1175     public void paintComponent(Graphics g)\r
1176     {\r
1177         if (image != null)\r
1178         {\r
1179             g.drawImage(image, 0, 0, this);\r
1180         }\r
1181         else\r
1182         {\r
1183             System.out.println("DEBUG:image is null");\r
1184         }\r
1185     }\r
1186 }\r