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