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