Recalc accelerated
[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 java.io.*;\r
22 import java.util.*;\r
23 import javax.imageio.*;\r
24 \r
25 import java.awt.*;\r
26 import java.awt.event.*;\r
27 import java.awt.image.*;\r
28 import javax.swing.*;\r
29 \r
30 import org.jibble.epsgraphics.*;\r
31 import jalview.analysis.*;\r
32 import jalview.datamodel.*;\r
33 import jalview.io.*;\r
34 import jalview.jbgui.*;\r
35 \r
36 public class TreePanel\r
37     extends GTreePanel\r
38 {\r
39   SequenceI[] seq;\r
40   String type;\r
41   String pwtype;\r
42   AlignViewport av;\r
43   int start;\r
44   int end;\r
45   TreeCanvas treeCanvas;\r
46   NJTree tree;\r
47 \r
48   public TreePanel(AlignViewport av, Vector seqVector, String type,\r
49                    String pwtype, int s, int e)\r
50   {\r
51     super();\r
52 \r
53     this.type = type;\r
54     this.pwtype = pwtype;\r
55 \r
56     start = s;\r
57     end = e;\r
58 \r
59     String longestName = "";\r
60     seq = new Sequence[seqVector.size()];\r
61 \r
62     for (int i = 0; i < seqVector.size(); i++)\r
63     {\r
64       seq[i] = (Sequence) seqVector.elementAt(i);\r
65 \r
66       if (seq[i].getName().length() > longestName.length())\r
67       {\r
68         longestName = seq[i].getName();\r
69       }\r
70     }\r
71 \r
72     tree = new NJTree(seq, type, pwtype, start, end);\r
73 \r
74     treeCanvas = new TreeCanvas(av, tree, scrollPane, longestName);\r
75     treeCanvas.setShowDistances(true); // We know this tree has distances. JBPNote TODO: prolly should add this as a userdefined default\r
76     setViewStateFromTreeCanvas(treeCanvas);\r
77     tree.reCount(tree.getTopNode());\r
78     tree.findHeight(tree.getTopNode());\r
79     scrollPane.setViewportView(treeCanvas);\r
80   }\r
81 \r
82   public TreePanel(AlignViewport av, Vector seqVector, NewickFile newtree,\r
83                    String type, String pwtype)\r
84   {\r
85     super();\r
86 \r
87     // These are probably only  arbitrary strings reflecting source of tree\r
88     this.type = type;\r
89     this.pwtype = pwtype;\r
90 \r
91     start = 0;\r
92     end = seqVector.size();\r
93 \r
94     String longestName = "";\r
95     seq = new Sequence[seqVector.size()];\r
96 \r
97     for (int i = 0; i < seqVector.size(); i++)\r
98     {\r
99       seq[i] = (Sequence) seqVector.elementAt(i);\r
100     }\r
101 \r
102     // This constructor matches sequence names to treenodes and sets up the tree layouts.\r
103     tree = new NJTree(seq, newtree);\r
104 \r
105     // Now have to calculate longest name based on the leaves\r
106     Vector leaves = tree.findLeaves(tree.getTopNode(), new Vector());\r
107     boolean has_placeholders = false;\r
108 \r
109     for (int i = 0; i < leaves.size(); i++)\r
110     {\r
111       SequenceNode lf = (SequenceNode) leaves.elementAt(i);\r
112 \r
113       if (lf.isPlaceholder())\r
114       {\r
115         has_placeholders = true;\r
116       }\r
117 \r
118       if (longestName.length() < ( (Sequence) lf.element()).getName()\r
119           .length())\r
120       {\r
121         longestName = TreeCanvas.PLACEHOLDER +\r
122             ( (Sequence) lf.element()).getName();\r
123       }\r
124     }\r
125 \r
126     tree.reCount(tree.getTopNode());\r
127     tree.findHeight(tree.getTopNode());\r
128 \r
129     treeCanvas = new TreeCanvas(av, tree, scrollPane, longestName);\r
130     treeCanvas.setShowBootstrap(newtree.HasBootstrap());\r
131     treeCanvas.setShowDistances(newtree.HasDistances());\r
132     scrollPane.setViewportView(treeCanvas);\r
133     treeCanvas.setMarkPlaceholders(has_placeholders);\r
134     setViewStateFromTreeCanvas(treeCanvas);\r
135 \r
136     // JBPNote TODO: preference for always marking placeholders in new associated tree\r
137   }\r
138 \r
139   public NJTree getTree()\r
140   {\r
141     return tree;\r
142   }\r
143 \r
144   private void setViewStateFromTreeCanvas(TreeCanvas tree)\r
145   {\r
146     // update view menu state from treeCanvas render state\r
147     distanceMenu.setSelected(tree.showDistances);\r
148     bootstrapMenu.setSelected(tree.showBootstrap);\r
149     placeholdersMenu.setSelected(tree.markPlaceholders);\r
150   }\r
151 \r
152   private void setTreeCanvasFromViewState(TreeCanvas tree)\r
153   {\r
154     // update view menu state from treeCanvas render state\r
155     tree.showDistances = distanceMenu.isSelected();\r
156     tree.showBootstrap = bootstrapMenu.isSelected();\r
157     tree.markPlaceholders = placeholdersMenu.isSelected();\r
158   }\r
159 \r
160   public void textbox_actionPerformed(ActionEvent e)\r
161   {\r
162     CutAndPasteTransfer cap = new CutAndPasteTransfer();\r
163 \r
164     StringBuffer buffer = new StringBuffer();\r
165 \r
166     if (type.equals("AV"))\r
167     {\r
168       buffer.append("Average distance tree using ");\r
169     }\r
170     else\r
171     {\r
172       buffer.append("Neighbour joining tree using ");\r
173     }\r
174 \r
175     if (pwtype.equals("BL"))\r
176     {\r
177       buffer.append("BLOSUM62");\r
178     }\r
179     else\r
180     {\r
181       buffer.append("PID");\r
182     }\r
183 \r
184     Desktop.addInternalFrame(cap, buffer.toString(), 500, 100);\r
185 \r
186     jalview.io.NewickFile fout = new jalview.io.NewickFile(tree.getTopNode());\r
187     cap.setText(fout.print(false, true));\r
188   }\r
189 \r
190   public void saveAsNewick_actionPerformed(ActionEvent e)\r
191   {\r
192     JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.\r
193         getProperty(\r
194             "LAST_DIRECTORY"));\r
195     chooser.setFileView(new JalviewFileView());\r
196     chooser.setDialogTitle("Save tree as newick file");\r
197     chooser.setToolTipText("Save");\r
198 \r
199     int value = chooser.showSaveDialog(null);\r
200 \r
201     if (value == JalviewFileChooser.APPROVE_OPTION)\r
202     {\r
203       String choice = chooser.getSelectedFile().getPath();\r
204       jalview.bin.Cache.setProperty("LAST_DIRECTORY",\r
205                                     chooser.getSelectedFile().getParent());\r
206 \r
207       try\r
208       {\r
209         jalview.io.NewickFile fout = new jalview.io.NewickFile(tree.getTopNode());\r
210         String output = fout.print(false, true); // distances only\r
211         java.io.PrintWriter out = new java.io.PrintWriter(new java.io.\r
212             FileWriter(\r
213                 choice));\r
214         out.println(output);\r
215         out.close();\r
216       }\r
217       catch (Exception ex)\r
218       {\r
219         ex.printStackTrace();\r
220       }\r
221     }\r
222   }\r
223 \r
224   protected void printMenu_actionPerformed(ActionEvent e)\r
225   {\r
226     //Putting in a thread avoids Swing painting problems\r
227     treeCanvas.startPrinting();\r
228   }\r
229 \r
230   protected void fitToWindow_actionPerformed(ActionEvent e)\r
231   {\r
232     treeCanvas.fitToWindow = fitToWindow.isSelected();\r
233     repaint();\r
234   }\r
235 \r
236   protected void fontSize_actionPerformed(ActionEvent e)\r
237   {\r
238     if (treeCanvas == null)\r
239     {\r
240       return;\r
241     }\r
242 \r
243     String size = fontSize.getText().substring(fontSize.getText().indexOf("-") +\r
244                                                1);\r
245 \r
246     Object selection = JOptionPane.showInternalInputDialog(Desktop.desktop,\r
247         "Select font size", "Font size", JOptionPane.QUESTION_MESSAGE,\r
248         null,\r
249         new String[]\r
250         {\r
251         "1", "2", "4", "6", "8", "10", "12", "14", "16", "18", "20"\r
252     }, "Font Size - " + size);\r
253 \r
254     if (selection != null)\r
255     {\r
256       fontSize.setText("Font Size - " + selection);\r
257 \r
258       int i = Integer.parseInt(selection.toString());\r
259       treeCanvas.setFontSize(i);\r
260     }\r
261 \r
262     scrollPane.setViewportView(treeCanvas);\r
263   }\r
264 \r
265   protected void distanceMenu_actionPerformed(ActionEvent e)\r
266   {\r
267     treeCanvas.setShowDistances(distanceMenu.isSelected());\r
268   }\r
269 \r
270   protected void bootstrapMenu_actionPerformed(ActionEvent e)\r
271   {\r
272     treeCanvas.setShowBootstrap(bootstrapMenu.isSelected());\r
273   }\r
274 \r
275   protected void placeholdersMenu_actionPerformed(ActionEvent e)\r
276   {\r
277     treeCanvas.setMarkPlaceholders(placeholdersMenu.isSelected());\r
278   }\r
279 \r
280   protected void epsTree_actionPerformed(ActionEvent e)\r
281   {\r
282     int width = treeCanvas.getWidth();\r
283     int height = treeCanvas.getHeight();\r
284 \r
285     try\r
286     {\r
287       jalview.io.JalviewFileChooser chooser = new jalview.io.JalviewFileChooser(\r
288           jalview.bin.Cache.getProperty(\r
289               "LAST_DIRECTORY"), new String[]\r
290           {"eps"},\r
291           new String[]\r
292           {"Encapsulated Postscript"},\r
293           "Encapsulated Postscript");\r
294       chooser.setFileView(new jalview.io.JalviewFileView());\r
295       chooser.setDialogTitle("Create EPS file from tree");\r
296       chooser.setToolTipText("Save");\r
297 \r
298       int value = chooser.showSaveDialog(this);\r
299 \r
300       if (value != jalview.io.JalviewFileChooser.APPROVE_OPTION)\r
301       {\r
302         return;\r
303       }\r
304 \r
305       jalview.bin.Cache.setProperty("LAST_DIRECTORY",\r
306                                     chooser.getSelectedFile().getParent());\r
307 \r
308       FileOutputStream out = new FileOutputStream(chooser.getSelectedFile());\r
309       EpsGraphics2D pg = new EpsGraphics2D("Tree", out, 0, 0, width,\r
310                                            height);\r
311 \r
312       treeCanvas.draw(pg, width, height);\r
313 \r
314       pg.flush();\r
315       pg.close();\r
316     }\r
317     catch (Exception ex)\r
318     {\r
319       ex.printStackTrace();\r
320     }\r
321   }\r
322 \r
323   protected void pngTree_actionPerformed(ActionEvent e)\r
324   {\r
325     int width = treeCanvas.getWidth();\r
326     int height = treeCanvas.getHeight();\r
327 \r
328     try\r
329     {\r
330       jalview.io.JalviewFileChooser chooser = new jalview.io.JalviewFileChooser(\r
331           jalview.bin.Cache.getProperty(\r
332               "LAST_DIRECTORY"), new String[]\r
333           {"png"},\r
334           new String[]\r
335           {"Portable network graphics"},\r
336           "Portable network graphics");\r
337 \r
338       chooser.setFileView(new jalview.io.JalviewFileView());\r
339       chooser.setDialogTitle("Create PNG image from tree");\r
340       chooser.setToolTipText("Save");\r
341 \r
342       int value = chooser.showSaveDialog(this);\r
343 \r
344       if (value != jalview.io.JalviewFileChooser.APPROVE_OPTION)\r
345       {\r
346         return;\r
347       }\r
348 \r
349       jalview.bin.Cache.setProperty("LAST_DIRECTORY",\r
350                                     chooser.getSelectedFile().getParent());\r
351 \r
352       FileOutputStream out = new FileOutputStream(chooser.getSelectedFile());\r
353 \r
354       BufferedImage bi = new BufferedImage(width, height,\r
355                                            BufferedImage.TYPE_INT_RGB);\r
356       Graphics png = bi.getGraphics();\r
357 \r
358       treeCanvas.draw(png, width, height);\r
359 \r
360       ImageIO.write(bi, "png", out);\r
361       out.close();\r
362     }\r
363     catch (Exception ex)\r
364     {\r
365       ex.printStackTrace();\r
366     }\r
367   }\r
368 }\r