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