GPL license added
[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 \r
20 package jalview.gui;\r
21 \r
22 import jalview.jbgui.GAlignmentPanel;\r
23 import jalview.schemes.*;\r
24 import jalview.analysis.*;\r
25 import jalview.datamodel.*;\r
26 import java.awt.*;\r
27 import java.awt.event.*;\r
28 import java.awt.print.*;\r
29 import java.io.*;\r
30 import java.awt.image.*;\r
31 import org.jibble.epsgraphics.*;\r
32 import javax.imageio.*;\r
33 import javax.swing.*;\r
34 \r
35 \r
36 \r
37 public class AlignmentPanel extends GAlignmentPanel implements AdjustmentListener, Printable\r
38 {\r
39 \r
40   AlignViewport     av;\r
41   OverviewPanel overviewPanel;\r
42   SeqPanel   seqPanel;\r
43   IdPanel    idPanel;\r
44   IdwidthAdjuster idwidthAdjuster;\r
45   public AlignFrame alignFrame;\r
46   ScalePanel scalePanel;\r
47   AnnotationPanel annotationPanel;\r
48   AnnotationLabels alabels;\r
49 \r
50   // this value is set false when selection area being dragged\r
51   boolean fastPaint = true;\r
52 \r
53   public AlignmentPanel(AlignFrame af, final AlignViewport av)\r
54   {\r
55     alignFrame = af;\r
56     this.av         = av;\r
57     seqPanel        = new SeqPanel  (av, this);\r
58     idPanel         = new IdPanel   (av, this);\r
59 \r
60     scalePanel = new ScalePanel(av, this);\r
61 \r
62     idPanelHolder.add(idPanel, BorderLayout.CENTER);\r
63     idwidthAdjuster = new IdwidthAdjuster(this);\r
64     idSpaceFillerPanel1.add(idwidthAdjuster, BorderLayout.CENTER);\r
65 \r
66     annotationPanel = new AnnotationPanel(this);\r
67     alabels = new AnnotationLabels(this);\r
68 \r
69     annotationSpaceFillerHolder.setPreferredSize(annotationPanel.getPreferredSize());\r
70     annotationScroller.setPreferredSize(annotationPanel.getPreferredSize());\r
71     annotationScroller.setViewportView(annotationPanel);\r
72     annotationSpaceFillerHolder.add(alabels, BorderLayout.CENTER);\r
73 \r
74     fontChanged();\r
75 \r
76     scalePanelHolder.add(scalePanel, BorderLayout.CENTER);\r
77     seqPanelHolder.add(seqPanel, BorderLayout.CENTER);\r
78 \r
79     setScrollValues(0, 0);\r
80 \r
81     hscroll.addAdjustmentListener(this);\r
82     vscroll.addAdjustmentListener(this);\r
83 \r
84    setFocusable(true);\r
85    addKeyListener(new KeyAdapter()\r
86    {\r
87      public void keyPressed(KeyEvent evt)\r
88      {\r
89        switch(evt.getKeyCode())\r
90        {\r
91          case  27: // escape key\r
92            av.setSelectionGroup(null);\r
93            repaint();\r
94            break;\r
95 \r
96         case KeyEvent.VK_DOWN:\r
97           alignFrame.moveSelectedSequences(false);\r
98           break;\r
99         case KeyEvent.VK_UP:\r
100           alignFrame.moveSelectedSequences(true);\r
101           break;\r
102        }\r
103      }\r
104    });\r
105   }\r
106 \r
107   public void fontChanged()\r
108   {\r
109     // set idCanvas bufferedImage to null\r
110     // to prevent drawing old image\r
111     FontMetrics fm = getFontMetrics(av.getFont());\r
112 \r
113     scalePanelHolder.setPreferredSize(new Dimension(10, av.charHeight+fm.getDescent()));\r
114     idSpaceFillerPanel1.setPreferredSize(new Dimension(10, av.charHeight+fm.getDescent()));\r
115 \r
116     idPanel.idCanvas.gg = null;\r
117     annotationPanel.adjustPanelHeight();\r
118     Dimension d = calculateIdWidth();\r
119     d.setSize(d.width + 4, d.height);\r
120     idPanel.idCanvas.setPreferredSize(d);\r
121     hscrollFillerPanel.setPreferredSize(d);\r
122     repaint();\r
123   }\r
124 \r
125 \r
126   Dimension calculateIdWidth()\r
127   {\r
128     Graphics g = this.getGraphics();\r
129     if(g==null)\r
130     {\r
131       javax.swing.JFrame f = new javax.swing.JFrame();\r
132       f.addNotify();\r
133       g = f.getGraphics();\r
134     }\r
135 \r
136     FontMetrics fm = g.getFontMetrics(av.font);\r
137     AlignmentI al = av.getAlignment();\r
138 \r
139        int i   = 0;\r
140        int idWidth = 0;\r
141        String id;\r
142        while (i < al.getHeight() && al.getSequenceAt(i) != null)\r
143        {\r
144          SequenceI s   = al.getSequenceAt(i);\r
145          if(av.getShowFullId())\r
146            id   = s.getDisplayId();\r
147          else\r
148            id = s.getName();\r
149 \r
150          if (fm.stringWidth(id) > idWidth)\r
151            idWidth = fm.stringWidth(id);\r
152          i++;\r
153        }\r
154 \r
155        // Also check annotation label widths\r
156        i=0;\r
157        if(al.getAlignmentAnnotation()!=null)\r
158        {\r
159          fm = g.getFontMetrics(alabels.getFont());\r
160          while (i < al.getAlignmentAnnotation().length)\r
161          {\r
162            String label = al.getAlignmentAnnotation()[i].label;\r
163            if (fm.stringWidth(label) > idWidth)\r
164              idWidth = fm.stringWidth(label);\r
165            i++;\r
166          }\r
167        }\r
168 \r
169        return new Dimension(idWidth, 12);\r
170   }\r
171 \r
172 \r
173  public void highlightSearchResults(int [] results)\r
174  {\r
175    seqPanel.seqCanvas.highlightSearchResults( results );\r
176 \r
177    // do we need to scroll the panel?\r
178    if(results!=null)\r
179     {\r
180       SequenceI seq = av.alignment.getSequenceAt(results[0]);\r
181       int start = seq.findIndex( results[1] )-1;\r
182       int end = seq.findIndex( results[2] )-1;\r
183       if( av.getStartRes() > start\r
184           || av.getEndRes() < end\r
185           || (av.getStartSeq() > results[0]\r
186           || av.getEndSeq() < results[0]))\r
187         setScrollValues(start, results[0]);\r
188     }\r
189 \r
190  }\r
191 \r
192 \r
193  public OverviewPanel getOverviewPanel()\r
194  {\r
195    return overviewPanel;\r
196  }\r
197 \r
198  public void setOverviewPanel(OverviewPanel op)\r
199  {\r
200    overviewPanel = op;\r
201  }\r
202 \r
203 \r
204   public void setAnnotationVisible(boolean b)\r
205   {\r
206     annotationSpaceFillerHolder.setVisible(b);\r
207     annotationScroller.setVisible(b);\r
208   }\r
209 \r
210 \r
211   public void setWrapAlignment(boolean wrap)\r
212   {\r
213     scalePanelHolder.setVisible(!wrap);\r
214     hscroll.setVisible(!wrap);\r
215     idwidthAdjuster.setVisible(!wrap);\r
216 \r
217     av.setShowAnnotation(!wrap);\r
218     annotationScroller.setVisible(!wrap);\r
219     annotationSpaceFillerHolder.setVisible(!wrap);\r
220     idSpaceFillerPanel1.setVisible(!wrap);\r
221 \r
222     repaint();\r
223 \r
224   }\r
225 \r
226 \r
227   public void setColourScheme()\r
228   {\r
229     ColourSchemeI cs = av.getGlobalColourScheme();\r
230 \r
231     if(av.getConservationSelected())\r
232     {\r
233 \r
234        Alignment al = (Alignment)av.getAlignment();\r
235        Conservation c = new Conservation("All",\r
236                             ResidueProperties.propHash, 3, al.getSequences(), 0,\r
237                             al.getWidth() );\r
238 \r
239        c.calculate();\r
240        c.verdict(false, av.ConsPercGaps);\r
241        ConservationColourScheme ccs = new ConservationColourScheme(c, cs);\r
242 \r
243        av.setGlobalColourScheme( ccs );\r
244 \r
245     }\r
246 \r
247     repaint();\r
248   }\r
249 \r
250 \r
251   int hextent = 0;\r
252   int vextent = 0;\r
253 \r
254   // return value is true if the scroll is valid\r
255   public boolean scrollUp(boolean up)\r
256   {\r
257     if(up)\r
258     {\r
259       if(vscroll.getValue()<1)\r
260         return false;\r
261       fastPaint  = false;\r
262       vscroll.setValue(vscroll.getValue() - 1);\r
263     }\r
264     else\r
265     {\r
266      if(vextent+vscroll.getValue() >= av.getAlignment().getHeight())\r
267        return false;\r
268       fastPaint  = false;\r
269       vscroll.setValue(vscroll.getValue() + 1);\r
270     }\r
271     fastPaint = true;\r
272     return true;\r
273   }\r
274 \r
275   public boolean scrollRight(boolean right)\r
276   {\r
277 \r
278     if (right)\r
279     {\r
280       if (hscroll.getValue() < 1)\r
281         return false;\r
282       fastPaint = false;\r
283       hscroll.setValue(hscroll.getValue() - 1);\r
284     }\r
285     else\r
286     {\r
287       if (hextent + hscroll.getValue() >= av.getAlignment().getWidth())\r
288         return false;\r
289       fastPaint = false;\r
290       hscroll.setValue(hscroll.getValue() + 1);\r
291     }\r
292     fastPaint = true;\r
293     return true;\r
294   }\r
295 \r
296 \r
297   public void setScrollValues(int x, int y)\r
298   {\r
299     av.setEndRes(x + seqPanel.seqCanvas.getWidth()/av.getCharWidth()-1);\r
300 \r
301     hextent = seqPanel.seqCanvas.getWidth()/av.charWidth;\r
302     vextent = seqPanel.seqCanvas.getHeight()/av.charHeight;\r
303 \r
304     if(hextent > av.alignment.getWidth())\r
305       hextent = av.alignment.getWidth();\r
306     if(vextent > av.alignment.getHeight())\r
307       vextent = av.alignment.getHeight();\r
308 \r
309     if(hextent+x  >  av.getAlignment().getWidth())\r
310       x =  av.getAlignment().getWidth()- hextent;\r
311 \r
312     if(vextent+y > av.getAlignment().getHeight())\r
313       y = av.getAlignment().getHeight() - vextent;\r
314 \r
315     if(y<0)\r
316       y = 0;\r
317 \r
318     if(x<0)\r
319       x=0;\r
320 \r
321     hscroll.setValues(x,hextent,0,av.getAlignment().getWidth());\r
322     vscroll.setValues(y,vextent,0,av.getAlignment().getHeight() );\r
323 \r
324 \r
325 \r
326   }\r
327 \r
328 \r
329   public void adjustmentValueChanged(AdjustmentEvent evt)\r
330   {\r
331     int oldX = av.getStartRes();\r
332     int oldY = av.getStartSeq();\r
333 \r
334     if (evt.getSource() == hscroll)\r
335     {\r
336       int x = hscroll.getValue();\r
337       av.setStartRes(x);\r
338       av.setEndRes(x + seqPanel.seqCanvas.getWidth()/av.getCharWidth()-1);\r
339     }\r
340 \r
341     if (evt.getSource() == vscroll)\r
342     {\r
343       int offy = vscroll.getValue();\r
344       if (av.getWrapAlignment())\r
345       {\r
346         int rowSize = seqPanel.seqCanvas.getWrappedCanvasWidth(seqPanel.seqCanvas.getWidth());\r
347         av.setStartRes( vscroll.getValue() * rowSize );\r
348         av.setEndRes( (vscroll.getValue()+1) * rowSize );\r
349       }\r
350       else\r
351       {\r
352         av.setStartSeq(offy);\r
353         av.setEndSeq(offy + seqPanel.seqCanvas.getHeight() / av.getCharHeight());\r
354       }\r
355     }\r
356 \r
357     if(overviewPanel!=null)\r
358       overviewPanel.setBoxPosition();\r
359 \r
360     if(av.getWrapAlignment() || !fastPaint)\r
361       repaint();\r
362     else\r
363     {\r
364       idPanel.idCanvas.fastPaint(av.getStartSeq() - oldY);\r
365       seqPanel.seqCanvas.fastPaint(av.getStartRes() - oldX,\r
366                                    av.getStartSeq() - oldY);\r
367 \r
368       scalePanel.repaint();\r
369       if (av.getShowAnnotation())\r
370         annotationPanel.fastPaint(av.getStartRes() - oldX);\r
371     }\r
372 \r
373   }\r
374 \r
375 \r
376   public void paintComponent(Graphics g)\r
377   {\r
378     invalidate();\r
379     Dimension d = idPanel.idCanvas.getPreferredSize();\r
380     idPanelHolder.setPreferredSize(d);\r
381     hscrollFillerPanel.setPreferredSize(new Dimension(d.width, 12));\r
382     validate();\r
383 \r
384     if (av.getWrapAlignment())\r
385     {\r
386       int max = av.alignment.getWidth() / seqPanel.seqCanvas.getWrappedCanvasWidth(seqPanel.seqCanvas.getWidth());\r
387       vscroll.setMaximum(max);\r
388       vscroll.setUnitIncrement(1);\r
389       vscroll.setVisibleAmount(1);\r
390     }\r
391     else\r
392     {\r
393       setScrollValues(av.getStartRes(), av.getStartSeq());\r
394     }\r
395 \r
396 \r
397 \r
398   }\r
399 \r
400   public int print(Graphics pg, PageFormat pf, int pi) throws PrinterException\r
401   {\r
402     pg.translate((int)pf.getImageableX(), (int)pf.getImageableY());\r
403 \r
404     int pwidth = (int) pf.getImageableWidth();\r
405     int pheight = (int) pf.getImageableHeight();\r
406 \r
407     if (av.getWrapAlignment())\r
408       return printWrappedAlignment(pg, pwidth,pheight, pi);\r
409     else\r
410       return printUnwrapped(pg,pwidth, pheight,pi);\r
411   }\r
412 \r
413   public int printUnwrapped(Graphics pg, int pwidth, int pheight, int pi) throws PrinterException\r
414   {\r
415 \r
416       int idWidth = calculateIdWidth().width + 4;\r
417       FontMetrics fm = getFontMetrics(av.getFont());\r
418       int scaleHeight = av.charHeight + fm.getDescent();\r
419 \r
420       pg.setColor(Color.white);\r
421       pg.fillRect(0, 0, pwidth, pheight);\r
422       pg.setFont(av.getFont());\r
423 \r
424       ////////////////////////////////////\r
425       /// How many sequences and residues can we fit on a printable page?\r
426       int totalRes = (pwidth - idWidth) / av.getCharWidth();\r
427 \r
428       int totalSeq = (int) ( (pheight - scaleHeight) / av.getCharHeight()) - 1;\r
429 \r
430       int pagesWide = av.getAlignment().getWidth() / totalRes + 1;\r
431 \r
432       /////////////////////////////\r
433       /// Only print these sequences and residues on this page\r
434       int startRes, endRes, startSeq, endSeq;\r
435       startRes = (pi % pagesWide) * totalRes;\r
436       endRes = startRes + totalRes - 1;\r
437       if (endRes > av.getAlignment().getWidth()-1)\r
438         endRes = av.getAlignment().getWidth()-1;\r
439 \r
440       startSeq = (pi / pagesWide) * totalSeq;\r
441       endSeq = startSeq + totalSeq;\r
442       if (endSeq > av.getAlignment().getHeight())\r
443         endSeq = av.getAlignment().getHeight();\r
444 \r
445       int pagesHigh = ( (av.alignment.getHeight() / totalSeq) + 1) * pheight;\r
446 \r
447       if (av.showAnnotation)\r
448         pagesHigh += annotationPanel.getHeight();\r
449 \r
450       pagesHigh /= pheight;\r
451 \r
452       if (pi >= pagesWide * pagesHigh)\r
453         return Printable.NO_SUCH_PAGE;\r
454 \r
455         //draw Scale\r
456       pg.translate(idWidth, 0);\r
457       scalePanel.drawScale(pg, startRes, endRes, pwidth - idWidth, scaleHeight);\r
458       pg.translate( -idWidth, scaleHeight);\r
459       ////////////////\r
460       // Draw the ids\r
461       Color currentColor = null;\r
462       Color currentTextColor = null;\r
463       for (int i = startSeq; i < endSeq; i++)\r
464       {\r
465         if (av.getSelectionGroup() != null &&\r
466             av.getSelectionGroup().sequences.\r
467             contains(av.getAlignment().getSequenceAt(i)))\r
468         {\r
469           currentColor = Color.gray;\r
470           currentTextColor = Color.black;\r
471         }\r
472         else\r
473         {\r
474           currentColor = av.getAlignment().getSequenceAt(i).getColor();\r
475           currentTextColor = Color.black;\r
476         }\r
477 \r
478         pg.setColor(currentColor);\r
479         pg.fillRect(0,\r
480                     jalview.analysis.AlignmentUtil.getPixelHeight(startSeq, i,\r
481             av.getCharHeight()),\r
482                     idWidth,\r
483                     av.getCharHeight());\r
484 \r
485         pg.setColor(currentTextColor);\r
486 \r
487         String string = av.getAlignment().getSequenceAt(i).getName();\r
488         if (av.getShowFullId())\r
489           string = av.getAlignment().getSequenceAt(i).getDisplayId();\r
490 \r
491         pg.drawString(string, 0, jalview.analysis.AlignmentUtil.getPixelHeight\r
492                       (startSeq, i, av.getCharHeight()) + av.getCharHeight() -\r
493                       (av.getCharHeight() / 5));\r
494       }\r
495 \r
496       // draw main sequence panel\r
497       pg.translate(idWidth, 0);\r
498       seqPanel.seqCanvas.drawPanel(pg, startRes, endRes, startSeq, endSeq,\r
499                                    startRes, startSeq, 0);\r
500 \r
501 \r
502       if (av.showAnnotation && endSeq == av.alignment.getHeight())\r
503       {\r
504         pg.translate( -idWidth, (endSeq - startSeq) * av.charHeight);\r
505         alabels.drawComponent( (Graphics2D) pg);\r
506         pg.translate(idWidth, 0);\r
507         annotationPanel.drawComponent( (Graphics2D) pg, startRes, endRes+1);\r
508       }\r
509 \r
510       return Printable.PAGE_EXISTS;\r
511 \r
512   }\r
513 \r
514 \r
515   public int printWrappedAlignment(Graphics pg, int pwidth, int pheight, int pi) throws PrinterException\r
516   {\r
517       int idWidth = calculateIdWidth().width + 4;\r
518 \r
519       int resWidth = seqPanel.seqCanvas.getWrappedCanvasWidth(pwidth - idWidth);\r
520       int totalHeight = totalHeight = (av.alignment.getHeight() + 2) *\r
521           ( (av.alignment.getWidth()\r
522              / resWidth) + 1) * av.charHeight;\r
523 \r
524 \r
525       pg.setColor(Color.white);\r
526       pg.fillRect(0, 0, pwidth, pheight);\r
527       pg.setFont(av.getFont());\r
528 \r
529       ////////////////\r
530       // Draw the ids\r
531       pg.setColor(Color.black);\r
532 \r
533       pg.translate(0, -pi * pheight);\r
534 \r
535       pg.setClip(0,pi*pheight,pwidth, pheight);\r
536 \r
537       int ypos = 2 * av.charHeight;\r
538       do\r
539       {\r
540         for (int i = 0; i < av.alignment.getHeight(); i++)\r
541         {\r
542           SequenceI s = av.alignment.getSequenceAt(i);\r
543           String string = s.getName();\r
544           if (av.getShowFullId())\r
545             string = s.getDisplayId();\r
546 \r
547           pg.drawString(string, 0,\r
548                         AlignmentUtil.getPixelHeight(0, i, av.charHeight) +\r
549                         ypos +\r
550                         av.charHeight - (av.charHeight / 5));\r
551 \r
552         }\r
553 \r
554         ypos += (av.alignment.getHeight() + 2) * av.charHeight;\r
555 \r
556       }\r
557       while (ypos < totalHeight);\r
558 \r
559       pg.translate(idWidth, 0);\r
560 \r
561       seqPanel.seqCanvas.drawWrappedPanel(pg, pwidth - idWidth, totalHeight, 0);\r
562 \r
563       if (pi * pheight < totalHeight)\r
564         return Printable.PAGE_EXISTS;\r
565       else\r
566         return Printable.NO_SUCH_PAGE;\r
567 \r
568 \r
569 \r
570   }\r
571 \r
572 \r
573   public void makeEPS()\r
574   {\r
575     int height = (av.alignment.getWidth() / av.getChunkWidth() +1) * av.chunkHeight;\r
576     int width = seqPanel.getWidth() + idPanel.getWidth();\r
577 \r
578     if (!av.getWrapAlignment())\r
579     {\r
580       height = (av.alignment.getHeight()+1) * av.charHeight + 30;\r
581       width = idPanel.getWidth() + av.alignment.getWidth() * av.charWidth;\r
582     }\r
583     if(av.getShowAnnotation())\r
584    {\r
585      height += annotationPanel.getPreferredSize().height;\r
586    }\r
587 \r
588     try\r
589     {\r
590       jalview.io.JalviewFileChooser chooser = new jalview.io.JalviewFileChooser(jalview.bin.Cache.getProperty(\r
591           "LAST_DIRECTORY"),\r
592               new String[]{"eps"},\r
593               new String[]{"Encapsulated Postscript"},\r
594               "Encapsulated Postscript");\r
595       chooser.setFileView(new jalview.io.JalviewFileView());\r
596       chooser.setDialogTitle("Create EPS file from alignment");\r
597       chooser.setToolTipText("Save");\r
598 \r
599       int value = chooser.showSaveDialog(this);\r
600       if (value != jalview.io.JalviewFileChooser.APPROVE_OPTION)\r
601         return;\r
602 \r
603       jalview.bin.Cache.setProperty("LAST_DIRECTORY",chooser.getSelectedFile().getParent());\r
604       FileOutputStream out = new FileOutputStream(chooser.getSelectedFile());\r
605       EpsGraphics2D pg = new EpsGraphics2D("Example", out, 0, 0, width, height);\r
606 \r
607         if (av.getWrapAlignment())\r
608           printWrappedAlignment(pg, width, height, 0);\r
609         else\r
610           printUnwrapped(pg, width, height, 0);\r
611 \r
612 \r
613         pg.flush();\r
614         pg.close();\r
615     }\r
616     catch (Exception ex)\r
617     {\r
618       ex.printStackTrace();\r
619     }\r
620   }\r
621 \r
622   public void makePNG()\r
623   {\r
624       int height = (av.alignment.getWidth() / av.getChunkWidth() +1) * av.chunkHeight;\r
625       int width = seqPanel.getWidth() + idPanel.getWidth();\r
626 \r
627       if (!av.getWrapAlignment())\r
628       {\r
629         height = (av.alignment.getHeight()+1) * av.charHeight + 30;\r
630         width = idPanel.getWidth() + av.alignment.getWidth() * av.charWidth;\r
631       }\r
632 \r
633       if(av.getShowAnnotation())\r
634       {\r
635         height += annotationPanel.getPreferredSize().height;\r
636       }\r
637 \r
638 \r
639 \r
640     try\r
641     {\r
642       jalview.io.JalviewFileChooser chooser = new jalview.io.JalviewFileChooser(jalview.bin.Cache.getProperty(\r
643           "LAST_DIRECTORY"),\r
644               new String[]{"png"},\r
645               new String[]{"Portable network graphics"},\r
646               "Portable network graphics");\r
647       chooser.setFileView(new jalview.io.JalviewFileView());\r
648       chooser.setDialogTitle("Create EPS file from alignment");\r
649       chooser.setToolTipText("Save");\r
650 \r
651       int value = chooser.showSaveDialog(this);\r
652       if (value != jalview.io.JalviewFileChooser.APPROVE_OPTION)\r
653         return;\r
654 \r
655       jalview.bin.Cache.setProperty("LAST_DIRECTORY",chooser.getSelectedFile().getParent());\r
656       FileOutputStream out = new FileOutputStream(chooser.getSelectedFile());\r
657 \r
658       BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);\r
659       Graphics2D png = (Graphics2D)bi.getGraphics();\r
660 \r
661       png.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);\r
662 \r
663         if (av.getWrapAlignment())\r
664           printWrappedAlignment(png, width, height, 0);\r
665         else\r
666           printUnwrapped(png, width, height, 0);\r
667 \r
668         ImageIO.write(bi, "png", out);\r
669         out.close();\r
670     }\r
671     catch (Exception ex)\r
672     {\r
673       ex.printStackTrace();\r
674     }\r
675   }\r
676 \r
677 }\r
678 \r
679 class Preview extends JFrame\r
680 {\r
681 \r
682   public Preview(Image image)\r
683   {\r
684     setResizable(true);\r
685     setSize(image.getWidth(this), image.getHeight(this));\r
686     setVisible(true);\r
687     getContentPane().setLayout(new BorderLayout());\r
688     getContentPane().add(new PreviewPanel(image), BorderLayout.CENTER);\r
689     validate();\r
690     repaint();\r
691   }\r
692 }\r
693 \r
694 class PreviewPanel extends JPanel\r
695 {\r
696   Image image;\r
697   public PreviewPanel(Image image)\r
698   {\r
699     this.image = image;\r
700   }\r
701   public void paintComponent(Graphics g)\r
702   {\r
703     if(image!=null)\r
704       g.drawImage(image,0,0,this);\r
705     else\r
706       System.out.println("DEBUG:image is null");\r
707   }\r
708 }\r
709 \r
710 \r
711 \r
712 \r