moved to org.biojava
[jalview.git] / src / jalview / gui / TreePanel.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 package jalview.gui;\r
20 \r
21 import jalview.analysis.*;\r
22 \r
23 import jalview.datamodel.*;\r
24 \r
25 import jalview.io.*;\r
26 \r
27 import jalview.jbgui.*;\r
28 \r
29 import org.jibble.epsgraphics.*;\r
30 \r
31 import java.awt.*;\r
32 import java.awt.event.*;\r
33 import java.awt.image.*;\r
34 \r
35 import java.io.*;\r
36 \r
37 import java.util.*;\r
38 \r
39 import javax.imageio.*;\r
40 \r
41 import java.beans.PropertyChangeEvent;\r
42 \r
43 \r
44 /**\r
45  * DOCUMENT ME!\r
46  *\r
47  * @author $author$\r
48  * @version $Revision$\r
49  */\r
50 public class TreePanel extends GTreePanel\r
51 {\r
52     String type;\r
53     String pwtype;\r
54     TreeCanvas treeCanvas;\r
55     NJTree tree;\r
56     AlignViewport av;\r
57 \r
58     /**\r
59      * Creates a new TreePanel object.\r
60      *\r
61      * @param av DOCUMENT ME!\r
62      * @param seqVector DOCUMENT ME!\r
63      * @param type DOCUMENT ME!\r
64      * @param pwtype DOCUMENT ME!\r
65      * @param s DOCUMENT ME!\r
66      * @param e DOCUMENT ME!\r
67      */\r
68     public TreePanel(AlignViewport av, String type, String pwtype)\r
69     {\r
70       super();\r
71       initTreePanel(av, type, pwtype, null);\r
72 \r
73       // We know this tree has distances. JBPNote TODO: prolly should add this as a userdefined default\r
74       showDistances(true);\r
75     }\r
76 \r
77     /**\r
78      * Creates a new TreePanel object.\r
79      *\r
80      * @param av DOCUMENT ME!\r
81      * @param seqVector DOCUMENT ME!\r
82      * @param newtree DOCUMENT ME!\r
83      * @param type DOCUMENT ME!\r
84      * @param pwtype DOCUMENT ME!\r
85      */\r
86     public TreePanel(AlignViewport av,\r
87                      String type,\r
88                      String pwtype,\r
89                      NewickFile newtree)\r
90     {\r
91       super();\r
92       initTreePanel(av, type, pwtype, newtree);\r
93     }\r
94 \r
95     public AlignmentI getAlignment()\r
96     {\r
97       return treeCanvas.av.getAlignment();\r
98     }\r
99 \r
100 \r
101     void initTreePanel(AlignViewport av, String type,  String pwtype,\r
102                        NewickFile newTree)\r
103     {\r
104 \r
105       this.type = type;\r
106       this.pwtype = pwtype;\r
107 \r
108       treeCanvas = new TreeCanvas(av, scrollPane);\r
109       scrollPane.setViewportView(treeCanvas);\r
110 \r
111       av.addPropertyChangeListener(new java.beans.PropertyChangeListener()\r
112       {\r
113         public void propertyChange(PropertyChangeEvent evt)\r
114         {\r
115           if (evt.getPropertyName().equals("alignment"))\r
116           {\r
117             if(tree==null)\r
118               System.out.println("tree is null");\r
119             if(evt.getNewValue()==null)\r
120               System.out.println("new value is null");\r
121 \r
122             tree.UpdatePlaceHolders( (Vector) evt.getNewValue());\r
123 \r
124             repaint();\r
125           }\r
126         }\r
127       });\r
128 \r
129       this.av = av;\r
130 \r
131 \r
132       TreeLoader tl = new TreeLoader(newTree);\r
133       tl.start();\r
134 \r
135     }\r
136 \r
137     class TreeLoader extends Thread\r
138     {\r
139       NewickFile newtree;\r
140 \r
141       public TreeLoader(NewickFile newtree)\r
142       {\r
143         this.newtree = newtree;\r
144         if (newtree != null)\r
145         {\r
146           // Must be outside run(), as Jalview2XML tries to\r
147           // update distance/bootstrap visibility at the same time\r
148           showBootstrap(newtree.HasBootstrap());\r
149           showDistances(newtree.HasDistances());\r
150         }\r
151       }\r
152 \r
153       public void run()\r
154       {\r
155 \r
156         if(newtree!=null)\r
157           tree = new NJTree(av.alignment.getSequencesArray(),\r
158                             newtree);\r
159         else\r
160         {\r
161           int start, end;\r
162           SequenceI [] seqs;\r
163           String [] seqStrings = null;\r
164           if (av.hasHiddenColumns)\r
165           {\r
166             seqStrings = av.getViewAsString(true);\r
167           }\r
168 \r
169           if(av.getSelectionGroup()==null)\r
170           {\r
171             start = 0;\r
172             end = av.alignment.getWidth();\r
173             seqs = av.alignment.getSequencesArray();\r
174           }\r
175           else\r
176           {\r
177             start = av.getSelectionGroup().getStartRes();\r
178             end = av.getSelectionGroup().getEndRes()+1;\r
179             seqs = av.getSelectionGroup().getSequencesInOrder(av.alignment);\r
180           }\r
181 \r
182           tree = new NJTree(seqs, seqStrings, type, pwtype, start, end);\r
183         }\r
184 \r
185 \r
186         tree.reCount(tree.getTopNode());\r
187         tree.findHeight(tree.getTopNode());\r
188         treeCanvas.setTree(tree);\r
189 \r
190         treeCanvas.repaint();\r
191 \r
192         av.setCurrentTree(tree);\r
193 \r
194       }\r
195     }\r
196 \r
197     public void showDistances(boolean b)\r
198     {\r
199       treeCanvas.setShowDistances(b);\r
200       distanceMenu.setSelected(b);\r
201     }\r
202 \r
203     public void showBootstrap(boolean b)\r
204     {\r
205       treeCanvas.setShowBootstrap(b);\r
206       bootstrapMenu.setSelected(b);\r
207     }\r
208 \r
209     public void showPlaceholders(boolean b)\r
210     {\r
211       placeholdersMenu.setState(b);\r
212       treeCanvas.setMarkPlaceholders(b);\r
213     }\r
214 \r
215 \r
216 \r
217 \r
218     /**\r
219      * DOCUMENT ME!\r
220      *\r
221      * @return DOCUMENT ME!\r
222      */\r
223     public NJTree getTree()\r
224     {\r
225         return tree;\r
226     }\r
227 \r
228 \r
229     /**\r
230      * DOCUMENT ME!\r
231      *\r
232      * @param e DOCUMENT ME!\r
233      */\r
234     public void textbox_actionPerformed(ActionEvent e)\r
235     {\r
236         CutAndPasteTransfer cap = new CutAndPasteTransfer();\r
237 \r
238         StringBuffer buffer = new StringBuffer();\r
239 \r
240         if (type.equals("AV"))\r
241         {\r
242             buffer.append("Average distance tree using ");\r
243         }\r
244         else\r
245         {\r
246             buffer.append("Neighbour joining tree using ");\r
247         }\r
248 \r
249         if (pwtype.equals("BL"))\r
250         {\r
251             buffer.append("BLOSUM62");\r
252         }\r
253         else\r
254         {\r
255             buffer.append("PID");\r
256         }\r
257 \r
258         Desktop.addInternalFrame(cap, buffer.toString(), 500, 100);\r
259 \r
260         jalview.io.NewickFile fout = new jalview.io.NewickFile(tree.getTopNode());\r
261         cap.setText(fout.print(tree.isHasBootstrap(), tree.isHasDistances(), tree.isHasRootDistance()));\r
262     }\r
263 \r
264     /**\r
265      * DOCUMENT ME!\r
266      *\r
267      * @param e DOCUMENT ME!\r
268      */\r
269     public void saveAsNewick_actionPerformed(ActionEvent e)\r
270     {\r
271         JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.getProperty(\r
272                     "LAST_DIRECTORY"));\r
273         chooser.setFileView(new JalviewFileView());\r
274         chooser.setDialogTitle("Save tree as newick file");\r
275         chooser.setToolTipText("Save");\r
276 \r
277         int value = chooser.showSaveDialog(null);\r
278 \r
279         if (value == JalviewFileChooser.APPROVE_OPTION)\r
280         {\r
281             String choice = chooser.getSelectedFile().getPath();\r
282             jalview.bin.Cache.setProperty("LAST_DIRECTORY",\r
283                 chooser.getSelectedFile().getParent());\r
284 \r
285             try\r
286             {\r
287                 jalview.io.NewickFile fout = new jalview.io.NewickFile(tree.getTopNode());\r
288                 String output = fout.print(tree.isHasBootstrap(), tree.isHasDistances(), tree.isHasRootDistance());\r
289                 java.io.PrintWriter out = new java.io.PrintWriter(new java.io.FileWriter(\r
290                             choice));\r
291                 out.println(output);\r
292                 out.close();\r
293             }\r
294             catch (Exception ex)\r
295             {\r
296                 ex.printStackTrace();\r
297             }\r
298         }\r
299     }\r
300 \r
301     /**\r
302      * DOCUMENT ME!\r
303      *\r
304      * @param e DOCUMENT ME!\r
305      */\r
306     public void printMenu_actionPerformed(ActionEvent e)\r
307     {\r
308         //Putting in a thread avoids Swing painting problems\r
309         treeCanvas.startPrinting();\r
310     }\r
311 \r
312 \r
313     public void originalSeqData_actionPerformed(ActionEvent e)\r
314     {\r
315       CutAndPasteTransfer cap = new CutAndPasteTransfer();\r
316       cap.setText(tree.printOriginalSequenceData());\r
317       Desktop.addInternalFrame(cap, "Original Data",\r
318           400, 400);\r
319     }\r
320 \r
321 \r
322     /**\r
323      * DOCUMENT ME!\r
324      *\r
325      * @param e DOCUMENT ME!\r
326      */\r
327     public void fitToWindow_actionPerformed(ActionEvent e)\r
328     {\r
329         treeCanvas.fitToWindow = fitToWindow.isSelected();\r
330         repaint();\r
331     }\r
332 \r
333     /**\r
334      * DOCUMENT ME!\r
335      *\r
336      * @param e DOCUMENT ME!\r
337      */\r
338     public void font_actionPerformed(ActionEvent e)\r
339     {\r
340         if (treeCanvas == null)\r
341         {\r
342             return;\r
343         }\r
344 \r
345         new FontChooser(this);\r
346     }\r
347 \r
348     public Font getTreeFont()\r
349     {\r
350         return treeCanvas.font;\r
351     }\r
352 \r
353     public void setTreeFont(Font font)\r
354     {\r
355       if(treeCanvas!=null)\r
356       treeCanvas.setFont(font);\r
357     }\r
358 \r
359     /**\r
360      * DOCUMENT ME!\r
361      *\r
362      * @param e DOCUMENT ME!\r
363      */\r
364     public void distanceMenu_actionPerformed(ActionEvent e)\r
365     {\r
366         treeCanvas.setShowDistances(distanceMenu.isSelected());\r
367     }\r
368 \r
369     /**\r
370      * DOCUMENT ME!\r
371      *\r
372      * @param e DOCUMENT ME!\r
373      */\r
374     public void bootstrapMenu_actionPerformed(ActionEvent e)\r
375     {\r
376         treeCanvas.setShowBootstrap(bootstrapMenu.isSelected());\r
377     }\r
378 \r
379     /**\r
380      * DOCUMENT ME!\r
381      *\r
382      * @param e DOCUMENT ME!\r
383      */\r
384     public void placeholdersMenu_actionPerformed(ActionEvent e)\r
385     {\r
386         treeCanvas.setMarkPlaceholders(placeholdersMenu.isSelected());\r
387     }\r
388 \r
389     /**\r
390      * DOCUMENT ME!\r
391      *\r
392      * @param e DOCUMENT ME!\r
393      */\r
394     public void epsTree_actionPerformed(ActionEvent e)\r
395     {\r
396       boolean accurateText = true;\r
397 \r
398       String renderStyle = jalview.bin.Cache.getDefault("EPS_RENDERING",\r
399           "Prompt each time");\r
400 \r
401     // If we need to prompt, and if the GUI is visible then\r
402     // Prompt for EPS rendering style\r
403       if (renderStyle.equalsIgnoreCase("Prompt each time")\r
404           && !\r
405           (System.getProperty("java.awt.headless") != null\r
406            && System.getProperty("java.awt.headless").equals("true")))\r
407       {\r
408         EPSOptions eps = new EPSOptions();\r
409         renderStyle = eps.getValue();\r
410 \r
411         if (renderStyle==null || eps.cancelled)\r
412           return;\r
413 \r
414 \r
415       }\r
416 \r
417       if (renderStyle.equalsIgnoreCase("text"))\r
418       {\r
419         accurateText = false;\r
420       }\r
421 \r
422         int width = treeCanvas.getWidth();\r
423         int height = treeCanvas.getHeight();\r
424 \r
425         try\r
426         {\r
427             jalview.io.JalviewFileChooser chooser = new jalview.io.JalviewFileChooser(jalview.bin.Cache.getProperty(\r
428                         "LAST_DIRECTORY"), new String[] { "eps" },\r
429                     new String[] { "Encapsulated Postscript" },\r
430                     "Encapsulated Postscript");\r
431             chooser.setFileView(new jalview.io.JalviewFileView());\r
432             chooser.setDialogTitle("Create EPS file from tree");\r
433             chooser.setToolTipText("Save");\r
434 \r
435             int value = chooser.showSaveDialog(this);\r
436 \r
437             if (value != jalview.io.JalviewFileChooser.APPROVE_OPTION)\r
438             {\r
439                 return;\r
440             }\r
441 \r
442             jalview.bin.Cache.setProperty("LAST_DIRECTORY",\r
443                                           chooser.getSelectedFile().getParent());\r
444 \r
445             FileOutputStream out = new FileOutputStream(chooser.getSelectedFile());\r
446             EpsGraphics2D pg = new EpsGraphics2D("Tree", out, 0, 0, width,\r
447                                                  height);\r
448 \r
449             pg.setAccurateTextMode(accurateText);\r
450 \r
451             treeCanvas.draw(pg, width, height);\r
452 \r
453             pg.flush();\r
454             pg.close();\r
455         }\r
456         catch (Exception ex)\r
457         {\r
458             ex.printStackTrace();\r
459         }\r
460     }\r
461 \r
462     /**\r
463      * DOCUMENT ME!\r
464      *\r
465      * @param e DOCUMENT ME!\r
466      */\r
467     public void pngTree_actionPerformed(ActionEvent e)\r
468     {\r
469         int width = treeCanvas.getWidth();\r
470         int height = treeCanvas.getHeight();\r
471 \r
472         try\r
473         {\r
474             jalview.io.JalviewFileChooser chooser = new jalview.io.JalviewFileChooser(jalview.bin.Cache.getProperty(\r
475                         "LAST_DIRECTORY"), new String[] { "png" },\r
476                     new String[] { "Portable network graphics" },\r
477                     "Portable network graphics");\r
478 \r
479             chooser.setFileView(new jalview.io.JalviewFileView());\r
480             chooser.setDialogTitle("Create PNG image from tree");\r
481             chooser.setToolTipText("Save");\r
482 \r
483             int value = chooser.showSaveDialog(this);\r
484 \r
485             if (value != jalview.io.JalviewFileChooser.APPROVE_OPTION)\r
486             {\r
487                 return;\r
488             }\r
489 \r
490             jalview.bin.Cache.setProperty("LAST_DIRECTORY",\r
491                 chooser.getSelectedFile().getParent());\r
492 \r
493             FileOutputStream out = new FileOutputStream(chooser.getSelectedFile());\r
494 \r
495             BufferedImage bi = new BufferedImage(width, height,\r
496                     BufferedImage.TYPE_INT_RGB);\r
497             Graphics png = bi.getGraphics();\r
498 \r
499             treeCanvas.draw(png, width, height);\r
500 \r
501             ImageIO.write(bi, "png", out);\r
502             out.close();\r
503         }\r
504         catch (Exception ex)\r
505         {\r
506             ex.printStackTrace();\r
507         }\r
508     }\r
509 }\r