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