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