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