correct eps png bug missing last 2 lines
[jalview.git] / src / jalview / gui / AlignmentPanel.java
1 package jalview.gui;\r
2 \r
3 import jalview.jbgui.GAlignmentPanel;\r
4 import jalview.schemes.*;\r
5 import jalview.analysis.*;\r
6 import jalview.datamodel.*;\r
7 import java.awt.*;\r
8 import java.awt.event.*;\r
9 import java.awt.print.*;\r
10 import java.io.*;\r
11 import java.awt.image.*;\r
12 import org.jibble.epsgraphics.*;\r
13 import javax.imageio.*;\r
14 \r
15 \r
16 \r
17 public class AlignmentPanel extends GAlignmentPanel implements AdjustmentListener, Printable\r
18 {\r
19 \r
20   AlignViewport     av;\r
21   OverviewPanel overviewPanel;\r
22   SeqPanel   seqPanel;\r
23   IdPanel    idPanel;\r
24   SecondaryStructurePanel ssPanel;\r
25   public AlignFrame alignFrame;\r
26   ScalePanel scalePanel;\r
27   ScorePanel scorePanel;\r
28 \r
29   public AlignmentPanel(AlignFrame af, final AlignViewport av)\r
30   {\r
31     alignFrame = af;\r
32     this.av         = av;\r
33     seqPanel        = new SeqPanel  (av, this);\r
34     idPanel         = new IdPanel   (av, this);\r
35 \r
36     scalePanel = new ScalePanel(av, this);\r
37     scorePanel = new ScorePanel(av);\r
38     ssPanel = new SecondaryStructurePanel(av);\r
39 \r
40     secondaryPanelHolder.add(ssPanel, BorderLayout.CENTER);\r
41 \r
42     idPanelHolder.add(idPanel, BorderLayout.CENTER);\r
43     IdwidthAdjuster iap = new IdwidthAdjuster(this);\r
44     idSpaceFillerPanel1.add(iap, BorderLayout.CENTER);\r
45 \r
46     Dimension d = calculateIdWidth();\r
47     d.setSize( d.width+4, d.height);\r
48     idPanel.idCanvas.setPreferredSize( d );\r
49     hscrollFillerPanel.setPreferredSize( d );\r
50 \r
51     scalePanelHolder.add(scalePanel, BorderLayout.CENTER);\r
52     scorePanelHolder.add(scorePanel, BorderLayout.CENTER);\r
53     seqPanelHolder.add(seqPanel, BorderLayout.CENTER);\r
54     setScrollValues(0,0);\r
55 \r
56     hscroll.addAdjustmentListener(this);\r
57     vscroll.addAdjustmentListener(this);\r
58 \r
59     addComponentListener(new ComponentAdapter()\r
60    {\r
61      public void componentResized(ComponentEvent evt)\r
62      {\r
63           RefreshPanels();\r
64      }\r
65    });\r
66 \r
67 \r
68   // hscroll.setFocusable(false);\r
69   // vscroll.setFocusable(false);\r
70    setFocusable(true);\r
71 \r
72    addKeyListener(new KeyAdapter()\r
73    {\r
74      public void keyPressed(KeyEvent evt)\r
75      {\r
76        switch(evt.getKeyCode())\r
77        {\r
78          case  27: // escape key\r
79            av.setSelectionGroup(null);\r
80            RefreshPanels();\r
81            break;\r
82          case KeyEvent.VK_X:\r
83            alignFrame.cut_actionPerformed(null);\r
84            break;\r
85          case KeyEvent.VK_C:\r
86            alignFrame.copy_actionPerformed(null);\r
87            break;\r
88          case KeyEvent.VK_V:\r
89            alignFrame.paste(true);\r
90            break;\r
91          case KeyEvent.VK_A:\r
92            alignFrame.selectAllSequenceMenuItem_actionPerformed(null);\r
93            break;\r
94         case KeyEvent.VK_DOWN:\r
95           alignFrame.moveSelectedSequences(false);\r
96           break;\r
97         case KeyEvent.VK_UP:\r
98           alignFrame.moveSelectedSequences(true);\r
99           break;\r
100         case KeyEvent.VK_F:\r
101           alignFrame.findMenuItem_actionPerformed(null);\r
102           break;\r
103        }\r
104      }\r
105    });\r
106   }\r
107 \r
108   Dimension calculateIdWidth()\r
109   {\r
110     Graphics g = this.getGraphics();\r
111     if(g==null)\r
112     {\r
113       javax.swing.JFrame f = new javax.swing.JFrame();\r
114       f.addNotify();\r
115       g = f.getGraphics();\r
116     }\r
117 \r
118     FontMetrics fm = g.getFontMetrics(av.font);\r
119     AlignmentI al = av.getAlignment();\r
120 \r
121        int i   = 0;\r
122        int idWidth = 0;\r
123        String id;\r
124        while (i < al.getHeight() && al.getSequenceAt(i) != null)\r
125        {\r
126          SequenceI s   = al.getSequenceAt(i);\r
127          if(av.getShowFullId())\r
128            id   = s.getDisplayId();\r
129          else\r
130            id = s.getName();\r
131 \r
132          if (fm.stringWidth(id) > idWidth)\r
133            idWidth = fm.stringWidth(id);\r
134          i++;\r
135        }\r
136 \r
137        return new Dimension(idWidth, 12);\r
138   }\r
139 \r
140 \r
141  public void highlightSearchResults(int [] results)\r
142  {\r
143    seqPanel.seqCanvas.highlightSearchResults( results );\r
144 \r
145    // do we need to scroll the panel?\r
146    if(results!=null && (av.getStartSeq()>results[0]\r
147                         || av.getEndSeq()<results[0]\r
148                         || av.getStartRes()>results[1]\r
149                         || av.getEndRes()<results[2]))\r
150        setScrollValues(results[1], results[0]);\r
151 \r
152 \r
153  }\r
154 \r
155 \r
156  public OverviewPanel getOverviewPanel()\r
157  {\r
158    return overviewPanel;\r
159  }\r
160 \r
161  public void setOverviewPanel(OverviewPanel op)\r
162  {\r
163    overviewPanel = op;\r
164  }\r
165 \r
166 \r
167   public void setGraphPanelVisible(boolean b)\r
168   {\r
169     idSpaceFillerPanel.setVisible(b);\r
170     scorePanelHolder.setVisible(b);\r
171 \r
172     RefreshPanels();\r
173     // bit annoying to call this twice, can you do better?\r
174     RefreshPanels();\r
175   }\r
176 \r
177   public void setSecondaryStructureVisible(boolean b)\r
178   {\r
179     secondaryPanelHolder.setVisible(b);\r
180     RefreshPanels();\r
181   }\r
182 \r
183   public void setWrapAlignment(boolean wrap)\r
184   {\r
185     scorePanelHolder.setVisible(!wrap);\r
186     scalePanelHolder.setVisible(!wrap);\r
187     secondaryPanelHolder.setVisible(!wrap);\r
188 \r
189     hscroll.setVisible(!wrap);\r
190 \r
191     idSpaceFillerPanel.setVisible(!wrap);\r
192     idSpaceFillerPanel1.setVisible(!wrap);\r
193 \r
194     RefreshPanels();\r
195 \r
196   }\r
197 \r
198 \r
199   public void setColourScheme()\r
200   {\r
201     ColourSchemeI cs = av.getGlobalColourScheme();\r
202 \r
203     if(av.getConservationSelected())\r
204     {\r
205 \r
206        Alignment al = (Alignment)av.getAlignment();\r
207        Conservation c = new Conservation("All",\r
208                             ResidueProperties.propHash, 3, al.getSequences(), 0,\r
209                             al.getWidth() );\r
210 \r
211        c.calculate();\r
212        c.verdict(false, 100);\r
213        ConservationColourScheme ccs = new ConservationColourScheme(c, cs);\r
214 \r
215        av.setGlobalColourScheme( ccs );\r
216 \r
217     }\r
218 \r
219     RefreshPanels();\r
220   }\r
221 \r
222   public void RefreshPanels()\r
223   {\r
224               requestFocus();\r
225               invalidate();\r
226               idPanelHolder.setPreferredSize(idPanel.idCanvas.getPreferredSize());\r
227               if(idPanel.idCanvas.getPreferredSize()!=null)\r
228                 hscrollFillerPanel.setPreferredSize(new Dimension(idPanel.idCanvas.getPreferredSize().width, 12));\r
229               idSpaceFillerPanel1.setPreferredSize(new Dimension(500,\r
230                   av.charHeight / 2 + 12));\r
231               scalePanelHolder.setPreferredSize(new Dimension(500,\r
232                   av.charHeight / 2 + 12));\r
233               if (av.getWrapAlignment())\r
234               {\r
235                 int max = av.alignment.getWidth() /\r
236                     (seqPanel.seqCanvas.getWidth() / av.charWidth) + 1;\r
237 \r
238                 int h = (av.alignment.getHeight() + 2) * av.charHeight;\r
239                 vextent = seqPanel.seqCanvas.getHeight() / h;\r
240                 vscroll.setValues(0, vextent, 0, max);\r
241               }\r
242               else\r
243 \r
244                 setScrollValues(av.getStartRes(), av.getStartSeq());\r
245               av.getConsensus(true);\r
246               if (overviewPanel != null)\r
247                 overviewPanel.updateOverviewImage();\r
248 \r
249           validate();\r
250           repaint();\r
251   }\r
252   int hextent = 0;\r
253   int vextent = 0;\r
254 \r
255 \r
256   // return value is true if the scroll is valid\r
257   public boolean scrollUp(boolean up)\r
258   {\r
259     if(up)\r
260     {\r
261       if(vscroll.getValue()<1)\r
262         return false;\r
263       vscroll.setValue(vscroll.getValue() - 1);\r
264     }\r
265     else\r
266     {\r
267      if(vextent+vscroll.getValue() >= av.getAlignment().getHeight())\r
268        return false;\r
269       vscroll.setValue(vscroll.getValue() + 1);\r
270     }\r
271 \r
272     return true;\r
273   }\r
274 \r
275   public boolean scrollRight(boolean right)\r
276   {\r
277     if(right)\r
278    {\r
279      if(hscroll.getValue()<1)\r
280        return false;\r
281      hscroll.setValue(hscroll.getValue() - 1);\r
282    }\r
283    else\r
284    {\r
285     if(hextent+hscroll.getValue() >= av.getAlignment().getWidth())\r
286       return false;\r
287      hscroll.setValue(hscroll.getValue() + 1);\r
288    }\r
289 \r
290    return true;\r
291  }\r
292 \r
293 \r
294   public void setScrollValues(int x, int y)\r
295   {\r
296     hextent = seqPanel.seqCanvas.getWidth()/av.getCharWidth();\r
297     vextent = seqPanel.seqCanvas.getHeight()/av.getCharHeight();\r
298 \r
299     if(hextent+x  >  av.getAlignment().getWidth())\r
300       x =  av.getAlignment().getWidth()- hextent;\r
301 \r
302     if(vextent+y > av.getAlignment().getHeight())\r
303       y = av.getAlignment().getHeight() - vextent;\r
304 \r
305     if(y<0)\r
306       y = 0;\r
307 \r
308     if(x<0)\r
309       x=0;\r
310 \r
311     hscroll.setValues(x,hextent,0,av.getAlignment().getWidth());\r
312     vscroll.setValues(y,vextent,0,av.getAlignment().getHeight() );\r
313 \r
314 \r
315     repaint();\r
316 \r
317   }\r
318 \r
319 \r
320   public void adjustmentValueChanged(AdjustmentEvent evt)\r
321   {\r
322 \r
323     if (evt.getSource() == hscroll)\r
324     {\r
325       int x = hscroll.getValue();\r
326       av.setStartRes(x);\r
327       av.setEndRes(x + seqPanel.seqCanvas.getWidth()/av.getCharWidth()-1);\r
328     }\r
329 \r
330     if (evt.getSource() == vscroll)\r
331     {\r
332       int offy = vscroll.getValue();\r
333       if (av.getWrapAlignment())\r
334       {\r
335         av.setStartRes( vscroll.getValue() * av.getChunkWidth());\r
336       }\r
337       else\r
338       {\r
339         av.setStartSeq(offy);\r
340         av.setEndSeq(offy + seqPanel.seqCanvas.getHeight() / av.getCharHeight());\r
341       }\r
342     }\r
343 \r
344 \r
345     if(overviewPanel!=null)\r
346       overviewPanel.setBoxPosition();\r
347 \r
348     repaint();\r
349   }\r
350 \r
351   public int print(Graphics pg, PageFormat pf, int pi) throws PrinterException\r
352   {\r
353     pg.translate((int)pf.getImageableX(), (int)pf.getImageableY());\r
354 \r
355     int pwidth = (int) pf.getImageableWidth();\r
356     int pheight = (int) pf.getImageableHeight();\r
357 \r
358     if (av.getWrapAlignment())\r
359       return printWrappedAlignment(pg, pwidth,pheight, pi);\r
360     else\r
361       return printUnwrapped(pg,pwidth, pheight,pi);\r
362   }\r
363 \r
364   public int printUnwrapped(Graphics pg, int pwidth, int pheight, int pi) throws PrinterException\r
365   {\r
366 \r
367     int idWidth = calculateIdWidth().width;\r
368 \r
369 \r
370     pg.setColor(Color.white);\r
371     pg.fillRect(0,0,pwidth, pheight);\r
372     pg.setFont( av.getFont() );\r
373 \r
374     ////////////////////////////////////\r
375     /// How many sequences and residues can we fit on a printable page?\r
376     int totalRes = (pwidth - idWidth)/av.getCharWidth();\r
377     int totalSeq = (int)((pheight - 30)/av.getCharHeight())-1;\r
378     int pagesWide = av.getAlignment().getWidth() / totalRes +1;\r
379     int pagesHigh = av.getAlignment().getHeight() / totalSeq +1;\r
380 \r
381     if (pi >= pagesWide*pagesHigh)\r
382      return Printable.NO_SUCH_PAGE;\r
383 \r
384     /////////////////////////////\r
385     /// Only print these sequences and residues on this page\r
386     int startRes, endRes, startSeq, endSeq;\r
387     startRes = (pi % pagesWide) * totalRes;\r
388     endRes = startRes + totalRes-1;\r
389     if(endRes>av.getAlignment().getWidth())\r
390       endRes = av.getAlignment().getWidth();\r
391 \r
392      startSeq = (pi / pagesWide) * totalSeq;\r
393      endSeq = startSeq + totalSeq;\r
394      if(endSeq > av.getAlignment().getHeight())\r
395        endSeq = av.getAlignment().getHeight();\r
396 \r
397 \r
398     ////////////////\r
399     //draw Scale\r
400     pg.translate(30,0);\r
401     scalePanel.drawScale(pg, startRes, endRes, pwidth-idWidth);\r
402 \r
403     pg.translate(-30, 30);\r
404     ////////////////\r
405     // Draw the ids\r
406     Color currentColor=null;\r
407     Color currentTextColor=null;\r
408     for(int i=startSeq; i<endSeq; i++)\r
409     {\r
410       if (av.getSelectionGroup()!=null && av.getSelectionGroup().sequences.contains(av.getAlignment().getSequenceAt(i)))\r
411       {\r
412         currentColor = Color.gray;\r
413         currentTextColor = Color.black;\r
414       }\r
415       else\r
416       {\r
417         currentColor = av.getAlignment().getSequenceAt(i).getColor();\r
418         currentTextColor = Color.black;\r
419       }\r
420 \r
421       pg.setColor(currentColor);\r
422       pg.fillRect(0,  jalview.analysis.AlignmentUtil.getPixelHeight(startSeq, i, av.getCharHeight()),\r
423                               idWidth,\r
424                               av.getCharHeight());\r
425 \r
426       pg.setColor(currentTextColor);\r
427 \r
428       String string = av.getAlignment().getSequenceAt(i).getName();\r
429       if(av.getShowFullId())\r
430         string = av.getAlignment().getSequenceAt(i).getDisplayId();\r
431 \r
432       pg.drawString(string, 0,  jalview.analysis.AlignmentUtil.getPixelHeight\r
433                     (startSeq, i, av.getCharHeight()) + av.getCharHeight() - (av.getCharHeight() / 5));\r
434     }\r
435 \r
436     // draw main sequence panel\r
437     pg.translate(idWidth+4,0);\r
438     pg.setClip(0,0,pwidth-idWidth, pheight);\r
439     seqPanel.seqCanvas.drawPanel(pg,startRes,endRes,startSeq,endSeq,startRes,startSeq,0);\r
440 \r
441     return Printable.PAGE_EXISTS;\r
442   }\r
443 \r
444 \r
445   public int printWrappedAlignment(Graphics pg, int pwidth, int pheight, int pi) throws PrinterException\r
446   {\r
447 \r
448     int idWidth = calculateIdWidth().width;\r
449 \r
450     if( seqPanel.seqCanvas.getWidth() < pwidth-idWidth)\r
451       pwidth = seqPanel.seqCanvas.getWidth() + idWidth;\r
452 \r
453 \r
454     pg.setColor(Color.white);\r
455     pg.fillRect(0,0,pwidth, pheight);\r
456     pg.setFont( av.getFont() );\r
457 \r
458     ////////////////////////////////////\r
459     /// How many sequences and residues can we fit on a printable page?\r
460     AlignmentI da = av.alignment;\r
461     int endy   = da.getHeight();\r
462     int chunkHeight =  (da.getHeight() + 2)*av.charHeight;\r
463     int chunkWidth  =   (pwidth-idWidth)/av.charWidth;\r
464 \r
465     int noChunksOnPage = pheight / chunkHeight;\r
466     int totalChunks = da.getWidth() / chunkWidth;\r
467 \r
468     if ( pi*noChunksOnPage > totalChunks )\r
469      return Printable.NO_SUCH_PAGE;\r
470 \r
471     ////////////////\r
472     // Draw the ids\r
473     pg.setClip(0,0,pwidth, noChunksOnPage*chunkHeight);\r
474 \r
475     int row = pi*noChunksOnPage;\r
476     pg.setColor(Color.black);\r
477     for(int ypos=2*av.charHeight;\r
478         ypos <= pheight && row*chunkWidth<da.getWidth();\r
479         ypos += chunkHeight, row++ )\r
480     {\r
481       for (int i = 0; i < endy; i++)\r
482       {\r
483         SequenceI s = da.getSequenceAt(i);\r
484         String string = s.getName();\r
485         if (av.getShowFullId())\r
486           string = s.getDisplayId();\r
487 \r
488         pg.drawString(string, 0,\r
489                       AlignmentUtil.getPixelHeight(0, i, av.charHeight) + ypos +\r
490                       av.charHeight - (av.charHeight / 5));\r
491       }\r
492     }\r
493 \r
494     // draw main sequence panel\r
495     pg.translate(idWidth+4,0);\r
496     seqPanel.seqCanvas.drawWrappedPanel(pg, pwidth-idWidth, pheight, pi*noChunksOnPage*chunkWidth);\r
497 \r
498 \r
499     return Printable.PAGE_EXISTS;\r
500 \r
501   }\r
502 \r
503 \r
504   public void makeEPS()\r
505   {\r
506     int height = (av.alignment.getWidth() / av.getChunkWidth() +1) * av.chunkHeight;\r
507     int width = seqPanel.getWidth() + idPanel.getWidth();\r
508 \r
509     if (!av.getWrapAlignment())\r
510     {\r
511       height = (av.alignment.getHeight()+1) * av.charHeight + 30;\r
512       width = idPanel.getWidth() + av.alignment.getWidth() * av.charWidth;\r
513     }\r
514 \r
515     try\r
516     {\r
517       jalview.io.JalviewFileChooser chooser = new jalview.io.JalviewFileChooser(jalview.bin.Cache.getProperty(\r
518           "LAST_DIRECTORY"), new String[]{"eps"}, "Encapsulated Postscript");\r
519       chooser.setFileView(new jalview.io.JalviewFileView());\r
520       chooser.setDialogTitle("Create EPS file from alignment");\r
521       chooser.setToolTipText("Save");\r
522 \r
523       int value = chooser.showSaveDialog(this);\r
524       if (value != jalview.io.JalviewFileChooser.APPROVE_OPTION)\r
525         return;\r
526 \r
527       jalview.bin.Cache.setProperty("LAST_DIRECTORY",chooser.getSelectedFile().getPath());\r
528       FileOutputStream out = new FileOutputStream(chooser.getSelectedFile());\r
529       EpsGraphics2D pg = new EpsGraphics2D("Example", out, 0, 0, width, height);\r
530 \r
531         if (av.getWrapAlignment())\r
532           printWrappedAlignment(pg, width, height, 0);\r
533         else\r
534           printUnwrapped(pg, width, height, 0);\r
535 \r
536 \r
537         pg.flush();\r
538         pg.close();\r
539     }\r
540     catch (Exception ex)\r
541     {\r
542       ex.printStackTrace();\r
543     }\r
544   }\r
545 \r
546   public void makePNG()\r
547   {\r
548       int height = (av.alignment.getWidth() / av.getChunkWidth() +1) * av.chunkHeight;\r
549       int width = seqPanel.getWidth() + idPanel.getWidth();\r
550 \r
551       if (!av.getWrapAlignment())\r
552       {\r
553         height = (av.alignment.getHeight()+1) * av.charHeight + 30;\r
554         width = idPanel.getWidth() + av.alignment.getWidth() * av.charWidth;\r
555       }\r
556 \r
557 \r
558 \r
559     try\r
560     {\r
561       jalview.io.JalviewFileChooser chooser = new jalview.io.JalviewFileChooser(jalview.bin.Cache.getProperty(\r
562           "LAST_DIRECTORY"), new String[]{"png"}, "Portable network graphics");\r
563       chooser.setFileView(new jalview.io.JalviewFileView());\r
564       chooser.setDialogTitle("Create EPS file from alignment");\r
565       chooser.setToolTipText("Save");\r
566 \r
567       int value = chooser.showSaveDialog(this);\r
568       if (value != jalview.io.JalviewFileChooser.APPROVE_OPTION)\r
569         return;\r
570 \r
571       jalview.bin.Cache.setProperty("LAST_DIRECTORY",chooser.getSelectedFile().getPath());\r
572       FileOutputStream out = new FileOutputStream(chooser.getSelectedFile());\r
573 \r
574       BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);\r
575       Graphics png = bi.getGraphics();\r
576 \r
577 \r
578         if (av.getWrapAlignment())\r
579           printWrappedAlignment(png, width, height, 0);\r
580         else\r
581           printUnwrapped(png, width, height, 0);\r
582 \r
583         ImageIO.write(bi, "png", out);\r
584         out.close();\r
585     }\r
586     catch (Exception ex)\r
587     {\r
588       ex.printStackTrace();\r
589     }\r
590   }\r
591 \r
592 }\r
593 \r
594 \r
595 \r
596 \r