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