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