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