fix for bug #8333
[jalview.git] / src / jalview / appletgui / TreePanel.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer (Development Version 2.4.1)
3  * Copyright (C) 2009 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle
4  * 
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  * 
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  * 
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
18  */
19 package jalview.appletgui;
20
21 import java.awt.*;
22 import java.awt.event.*;
23 import java.util.Hashtable;
24
25 import jalview.analysis.*;
26 import jalview.datamodel.*;
27 import jalview.io.*;
28
29 public class TreePanel extends EmbmenuFrame implements ActionListener,
30         ItemListener
31 {
32   SequenceI[] seq;
33
34   String type;
35
36   String pwtype;
37
38   int start;
39
40   int end;
41
42   TreeCanvas treeCanvas;
43
44   NJTree tree;
45
46   AlignViewport av;
47
48   public NJTree getTree()
49   {
50     return tree;
51   }
52
53   /**
54    * Creates a new TreePanel object.
55    * 
56    * @param av
57    *                DOCUMENT ME!
58    * @param seqVector
59    *                DOCUMENT ME!
60    * @param type
61    *                DOCUMENT ME!
62    * @param pwtype
63    *                DOCUMENT ME!
64    * @param s
65    *                DOCUMENT ME!
66    * @param e
67    *                DOCUMENT ME!
68    */
69   public TreePanel(AlignViewport av, String type, String pwtype)
70   {
71     try
72     {
73       jbInit();
74       this.setMenuBar(jMenuBar1);
75     } catch (Exception ex)
76     {
77       ex.printStackTrace();
78     }
79
80     initTreePanel(av, type, pwtype, null);
81   }
82
83   /**
84    * Creates a new TreePanel object.
85    * 
86    * @param av
87    *                DOCUMENT ME!
88    * @param seqVector
89    *                DOCUMENT ME!
90    * @param newtree
91    *                DOCUMENT ME!
92    * @param type
93    *                DOCUMENT ME!
94    * @param pwtype
95    *                DOCUMENT ME!
96    */
97   public TreePanel(AlignViewport av, String type, String pwtype,
98           NewickFile newtree)
99   {
100     try
101     {
102       jbInit();
103       this.setMenuBar(jMenuBar1);
104     } catch (Exception e)
105     {
106       e.printStackTrace();
107     }
108
109     initTreePanel(av, type, pwtype, newtree);
110   }
111
112   void initTreePanel(AlignViewport av, String type, String pwtype,
113           NewickFile newTree)
114   {
115
116     this.av = av;
117     this.type = type;
118     this.pwtype = pwtype;
119
120     treeCanvas = new TreeCanvas(av, scrollPane);
121     TreeLoader tl = new TreeLoader(newTree);
122     tl.start();
123     embedMenuIfNeeded(treeCanvas);
124     scrollPane.add(treeCanvas, BorderLayout.CENTER);
125   }
126
127   void showOriginalData()
128   {
129     // decide if av alignment is sufficiently different to original data to
130     // warrant a new window to be created
131     // create new alignmnt window with hidden regions (unhiding hidden regions
132     // yields unaligned seqs)
133     // or create a selection box around columns in alignment view
134     // test Alignment(SeqCigar[])
135     if (tree.seqData != null)
136     {
137       char gc = '-';
138       try
139       {
140         // we try to get the associated view's gap character
141         // but this may fail if the view was closed...
142         gc = av.getGapCharacter();
143       } catch (Exception ex)
144       {
145       }
146       ;
147       Object[] alAndColsel = tree.seqData
148               .getAlignmentAndColumnSelection(gc);
149
150       if (alAndColsel != null && alAndColsel[0] != null)
151       {
152         Alignment al = new Alignment((SequenceI[]) alAndColsel[0]);
153         AlignFrame af = new AlignFrame(al, av.applet,
154                 "Original Data for Tree", false);
155
156         af.viewport.setHiddenColumns((ColumnSelection) alAndColsel[1]);
157       }
158     }
159     else
160     {
161       System.out.println("Original Tree Data not available");
162     }
163   }
164
165   class TreeLoader extends Thread
166   {
167     NewickFile newtree;
168
169     jalview.datamodel.AlignmentView odata = null;
170
171     public TreeLoader(NewickFile newtree)
172     {
173       this.newtree = newtree;
174     }
175
176     public void run()
177     {
178       if (newtree != null)
179       {
180         if (odata == null)
181         {
182           tree = new NJTree(av.alignment.getSequencesArray(), newtree);
183         }
184         else
185         {
186           tree = new NJTree(av.alignment.getSequencesArray(), odata,
187                   newtree);
188         }
189
190       }
191       else
192       {
193         int start, end;
194         SequenceI[] seqs;
195         AlignmentView seqStrings = av.getAlignmentView(av
196                 .getSelectionGroup() != null);
197         if (av.getSelectionGroup() == null)
198         {
199           start = 0;
200           end = av.alignment.getWidth();
201           seqs = av.alignment.getSequencesArray();
202         }
203         else
204         {
205           start = av.getSelectionGroup().getStartRes();
206           end = av.getSelectionGroup().getEndRes() + 1;
207           seqs = av.getSelectionGroup().getSequencesInOrder(av.alignment);
208         }
209
210         tree = new NJTree(seqs, seqStrings, type, pwtype, start, end);
211       }
212
213       tree.reCount(tree.getTopNode());
214       tree.findHeight(tree.getTopNode());
215       treeCanvas.setTree(tree);
216       if (newtree != null)
217       {
218         // Set default view, paying lip service to any overriding tree view parameter settings
219         boolean showDist = newtree.HasDistances() && av.applet.getDefaultParameter("showTreeDistances", newtree.HasDistances());
220         boolean showBoots = newtree.HasBootstrap() && av.applet.getDefaultParameter("showTreeBootstraps", newtree.HasBootstrap());
221         distanceMenu.setState(showDist);
222         bootstrapMenu.setState(showBoots);
223         treeCanvas.setShowBootstrap(showBoots);
224         treeCanvas.setShowDistances(showDist);
225         treeCanvas.setMarkPlaceholders(av.applet.getDefaultParameter("showUnlinkedTreeNodes", false));
226       }
227
228       treeCanvas.repaint();
229
230       av.setCurrentTree(tree);
231
232     }
233   }
234
235   public void actionPerformed(ActionEvent evt)
236   {
237     if (evt.getSource() == newickOutput)
238     {
239       newickOutput_actionPerformed();
240     }
241     else if (evt.getSource() == fontSize)
242     {
243       fontSize_actionPerformed();
244     }
245     else if (evt.getSource() == inputData)
246     {
247       showOriginalData();
248     }
249   }
250
251   public void itemStateChanged(ItemEvent evt)
252   {
253     if (evt.getSource() == fitToWindow)
254     {
255       treeCanvas.fitToWindow = fitToWindow.getState();
256     }
257
258     else if (evt.getSource() == distanceMenu)
259     {
260       treeCanvas.setShowDistances(distanceMenu.getState());
261     }
262
263     else if (evt.getSource() == bootstrapMenu)
264     {
265       treeCanvas.setShowBootstrap(bootstrapMenu.getState());
266     }
267
268     else if (evt.getSource() == placeholdersMenu)
269     {
270       treeCanvas.setMarkPlaceholders(placeholdersMenu.getState());
271     }
272
273     treeCanvas.repaint();
274   }
275
276   public void newickOutput_actionPerformed()
277   {
278     jalview.io.NewickFile fout = new jalview.io.NewickFile(tree
279             .getTopNode());
280     String output = fout.print(false, true);
281     CutAndPasteTransfer cap = new CutAndPasteTransfer(false, null);
282     cap.setText(output);
283     java.awt.Frame frame = new java.awt.Frame();
284     frame.add(cap);
285     jalview.bin.JalviewLite.addFrame(frame, type + " " + pwtype, 500, 100);
286   }
287
288   public java.awt.Font getTreeFont()
289   {
290     return treeCanvas.font;
291   }
292
293   public void setTreeFont(java.awt.Font font)
294   {
295     treeCanvas.font = font;
296     treeCanvas.repaint();
297   }
298
299   protected void fontSize_actionPerformed()
300   {
301     if (treeCanvas == null)
302     {
303       return;
304     }
305
306     new FontChooser(this);
307   }
308
309   BorderLayout borderLayout1 = new BorderLayout();
310
311   protected ScrollPane scrollPane = new ScrollPane();
312
313   MenuBar jMenuBar1 = new MenuBar();
314
315   Menu jMenu2 = new Menu();
316
317   protected MenuItem fontSize = new MenuItem();
318
319   protected CheckboxMenuItem bootstrapMenu = new CheckboxMenuItem();
320
321   protected CheckboxMenuItem distanceMenu = new CheckboxMenuItem();
322
323   protected CheckboxMenuItem placeholdersMenu = new CheckboxMenuItem();
324
325   protected CheckboxMenuItem fitToWindow = new CheckboxMenuItem();
326
327   Menu fileMenu = new Menu();
328
329   MenuItem newickOutput = new MenuItem();
330
331   MenuItem inputData = new MenuItem();
332
333   private void jbInit() throws Exception
334   {
335     setLayout(borderLayout1);
336     this.setBackground(Color.white);
337     this.setFont(new java.awt.Font("Verdana", 0, 12));
338     jMenu2.setLabel("View");
339     fontSize.setLabel("Font...");
340     fontSize.addActionListener(this);
341     bootstrapMenu.setLabel("Show Bootstrap Values");
342     bootstrapMenu.addItemListener(this);
343     distanceMenu.setLabel("Show Distances");
344     distanceMenu.addItemListener(this);
345     placeholdersMenu.setLabel("Mark Unassociated Leaves");
346     placeholdersMenu.addItemListener(this);
347     fitToWindow.setState(true);
348     fitToWindow.setLabel("Fit To Window");
349     fitToWindow.addItemListener(this);
350     fileMenu.setLabel("File");
351     newickOutput.setLabel("Newick Format");
352     newickOutput.addActionListener(this);
353     inputData.setLabel("Input Data...");
354
355     add(scrollPane, BorderLayout.CENTER);
356     jMenuBar1.add(fileMenu);
357     jMenuBar1.add(jMenu2);
358     jMenu2.add(fitToWindow);
359     jMenu2.add(fontSize);
360     jMenu2.add(distanceMenu);
361     jMenu2.add(bootstrapMenu);
362     jMenu2.add(placeholdersMenu);
363     fileMenu.add(newickOutput);
364     fileMenu.add(inputData);
365     inputData.addActionListener(this);
366   }
367
368 }