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