imported Vamsas bindings and alpha vamsas client code from VamJalview cvs branch...
[jalview.git] / src / jalview / gui / TreePanel.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer
3  * Copyright (C) 2006 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.gui;
20
21 import jalview.analysis.*;
22
23 import jalview.datamodel.*;
24
25 import jalview.io.*;
26
27 import jalview.jbgui.*;
28
29 import org.jibble.epsgraphics.*;
30
31 import java.awt.*;
32 import java.awt.event.*;
33 import java.awt.image.*;
34
35 import java.io.*;
36
37 import java.util.*;
38
39 import javax.imageio.*;
40
41 import java.beans.PropertyChangeEvent;
42
43
44 /**
45  * DOCUMENT ME!
46  *
47  * @author $author$
48  * @version $Revision$
49  */
50 public class TreePanel extends GTreePanel
51 {
52     String type;
53     String pwtype;
54     TreeCanvas treeCanvas;
55     NJTree tree;
56     AlignViewport av;
57
58     /**
59      * Creates a new TreePanel object.
60      *
61      * @param av DOCUMENT ME!
62      * @param seqVector DOCUMENT ME!
63      * @param type DOCUMENT ME!
64      * @param pwtype DOCUMENT ME!
65      * @param s DOCUMENT ME!
66      * @param e DOCUMENT ME!
67      */
68     public TreePanel(AlignmentPanel ap, String type, String pwtype)
69     {
70       super();
71       initTreePanel(ap, type, pwtype, null, null);
72
73       // We know this tree has distances. JBPNote TODO: prolly should add this as a userdefined default
74       // showDistances(true);
75     }
76
77     /**
78      * Creates a new TreePanel object.
79      *
80      * @param av DOCUMENT ME!
81      * @param seqVector DOCUMENT ME!
82      * @param newtree DOCUMENT ME!
83      * @param type DOCUMENT ME!
84      * @param pwtype DOCUMENT ME!
85      */
86     public TreePanel(AlignmentPanel ap,
87                      String type,
88                      String pwtype,
89                      NewickFile newtree)
90     {
91       super();
92       initTreePanel(ap, type, pwtype, newtree, null);
93     }
94     
95     public TreePanel(AlignmentPanel av,
96         String type,
97         String pwtype,
98         NewickFile newtree, AlignmentView inputData) {
99      super();
100      initTreePanel(av,type,pwtype,newtree,inputData);
101     }
102
103     public AlignmentI getAlignment()
104     {
105       return treeCanvas.av.getAlignment();
106     }
107     public AlignViewport getViewPort() {
108       return treeCanvas.av;
109     }
110
111     void initTreePanel(AlignmentPanel ap, String type,  String pwtype,
112                        NewickFile newTree, AlignmentView inputData)
113     {
114
115       av = ap.av;
116       this.type = type;
117       this.pwtype = pwtype;
118
119       treeCanvas = new TreeCanvas(ap, scrollPane);
120       scrollPane.setViewportView(treeCanvas);
121
122       av.addPropertyChangeListener(new java.beans.PropertyChangeListener()
123       {
124         public void propertyChange(PropertyChangeEvent evt)
125         {
126           if (evt.getPropertyName().equals("alignment"))
127           {
128             if(tree==null)
129               System.out.println("tree is null");
130             if(evt.getNewValue()==null)
131               System.out.println("new value is null");
132
133             tree.UpdatePlaceHolders( (Vector) evt.getNewValue());
134
135             repaint();
136           }
137         }
138       });
139
140       this.av = av;
141
142
143       TreeLoader tl = new TreeLoader(newTree);
144       if (inputData!=null) {
145         tl.odata=inputData;
146       }
147       tl.start();
148
149     }
150
151     class TreeLoader extends Thread
152     {
153       NewickFile newtree;
154       jalview.datamodel.AlignmentView odata=null;
155       public TreeLoader(NewickFile newtree)
156       {
157         this.newtree = newtree;
158         if (newtree != null)
159         {
160           // Must be outside run(), as Jalview2XML tries to
161           // update distance/bootstrap visibility at the same time
162           showBootstrap(newtree.HasBootstrap());
163           showDistances(newtree.HasDistances());
164         }
165       }
166
167       public void run()
168       {
169
170         if(newtree!=null)
171         {
172           if (odata==null) {
173             tree = new NJTree(av.alignment.getSequencesArray(),
174                               newtree);
175           } else {
176             tree = new NJTree(av.alignment.getSequencesArray(), odata, newtree);
177           }
178           if (!tree.hasOriginalSequenceData())
179             allowOriginalSeqData(false);
180         }
181         else
182         {
183           int start, end;
184           SequenceI [] seqs;
185           AlignmentView seqStrings = av.getAlignmentView(av.getSelectionGroup()!=null);
186           if(av.getSelectionGroup()==null)
187           {
188             start = 0;
189             end = av.alignment.getWidth();
190             seqs = av.alignment.getSequencesArray();
191           }
192           else
193           {
194             start = av.getSelectionGroup().getStartRes();
195             end = av.getSelectionGroup().getEndRes()+1;
196             seqs = av.getSelectionGroup().getSequencesInOrder(av.alignment);
197           }
198
199           tree = new NJTree(seqs, seqStrings, type, pwtype, start, end);
200           showDistances(true);
201         }
202
203
204         tree.reCount(tree.getTopNode());
205         tree.findHeight(tree.getTopNode());
206         treeCanvas.setTree(tree);
207         treeCanvas.repaint();
208         av.setCurrentTree(tree);
209
210       }
211     }
212
213     public void showDistances(boolean b)
214     {
215       treeCanvas.setShowDistances(b);
216       distanceMenu.setSelected(b);
217     }
218
219     public void showBootstrap(boolean b)
220     {
221       treeCanvas.setShowBootstrap(b);
222       bootstrapMenu.setSelected(b);
223     }
224
225     public void showPlaceholders(boolean b)
226     {
227       placeholdersMenu.setState(b);
228       treeCanvas.setMarkPlaceholders(b);
229     }
230
231     private void allowOriginalSeqData(boolean b) {
232       originalSeqData.setVisible(b);
233     }
234
235
236
237     /**
238      * DOCUMENT ME!
239      *
240      * @return DOCUMENT ME!
241      */
242     public NJTree getTree()
243     {
244         return tree;
245     }
246
247
248     /**
249      * DOCUMENT ME!
250      *
251      * @param e DOCUMENT ME!
252      */
253     public void textbox_actionPerformed(ActionEvent e)
254     {
255         CutAndPasteTransfer cap = new CutAndPasteTransfer();
256
257         StringBuffer buffer = new StringBuffer();
258
259         if (type.equals("AV"))
260         {
261             buffer.append("Average distance tree using ");
262         }
263         else
264         {
265             buffer.append("Neighbour joining tree using ");
266         }
267
268         if (pwtype.equals("BL"))
269         {
270             buffer.append("BLOSUM62");
271         }
272         else
273         {
274             buffer.append("PID");
275         }
276
277         Desktop.addInternalFrame(cap, buffer.toString(), 500, 100);
278
279         jalview.io.NewickFile fout = new jalview.io.NewickFile(tree.getTopNode());
280         cap.setText(fout.print(tree.isHasBootstrap(), tree.isHasDistances(), tree.isHasRootDistance()));
281     }
282
283     /**
284      * DOCUMENT ME!
285      *
286      * @param e DOCUMENT ME!
287      */
288     public void saveAsNewick_actionPerformed(ActionEvent e)
289     {
290         JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.getProperty(
291                     "LAST_DIRECTORY"));
292         chooser.setFileView(new JalviewFileView());
293         chooser.setDialogTitle("Save tree as newick file");
294         chooser.setToolTipText("Save");
295
296         int value = chooser.showSaveDialog(null);
297
298         if (value == JalviewFileChooser.APPROVE_OPTION)
299         {
300             String choice = chooser.getSelectedFile().getPath();
301             jalview.bin.Cache.setProperty("LAST_DIRECTORY",
302                 chooser.getSelectedFile().getParent());
303
304             try
305             {
306                 jalview.io.NewickFile fout = new jalview.io.NewickFile(tree.getTopNode());
307                 String output = fout.print(tree.isHasBootstrap(), tree.isHasDistances(), tree.isHasRootDistance());
308                 java.io.PrintWriter out = new java.io.PrintWriter(new java.io.FileWriter(
309                             choice));
310                 out.println(output);
311                 out.close();
312             }
313             catch (Exception ex)
314             {
315                 ex.printStackTrace();
316             }
317         }
318     }
319
320     /**
321      * DOCUMENT ME!
322      *
323      * @param e DOCUMENT ME!
324      */
325     public void printMenu_actionPerformed(ActionEvent e)
326     {
327         //Putting in a thread avoids Swing painting problems
328         treeCanvas.startPrinting();
329     }
330
331
332     public void originalSeqData_actionPerformed(ActionEvent e)
333     {
334       if (!tree.hasOriginalSequenceData())
335       {
336         jalview.bin.Cache.log.info("Unexpected call to originalSeqData_actionPerformed - should have hidden this menu action.");
337         return;
338       }
339       // decide if av alignment is sufficiently different to original data to warrant a new window to be created
340       // create new alignmnt window with hidden regions (unhiding hidden regions yields unaligned seqs)
341       // or create a selection box around columns in alignment view
342       // test Alignment(SeqCigar[])
343       Object[] alAndColsel = tree.seqData.getAlignmentAndColumnSelection(av.
344           getGapCharacter());
345
346
347       if (alAndColsel != null && alAndColsel[0]!=null)
348        {
349          // AlignmentOrder origorder = new AlignmentOrder(alAndColsel[0]);
350
351          Alignment al = new Alignment((SequenceI[]) alAndColsel[0]);
352          Alignment dataset = av.getAlignment().getDataset();
353          if (dataset != null)
354          {
355            al.setDataset(dataset);
356          }
357
358          if (true)
359          {
360            // make a new frame!
361            AlignFrame af = new AlignFrame(al, (ColumnSelection) alAndColsel[1],
362                                            AlignFrame.DEFAULT_WIDTH,
363                                            AlignFrame.DEFAULT_HEIGHT
364 );
365
366            //>>>This is a fix for the moment, until a better solution is found!!<<<
367            // af.getFeatureRenderer().transferSettings(alignFrame.getFeatureRenderer());
368
369        //           af.addSortByOrderMenuItem(ServiceName + " Ordering",
370        //                                     msaorder);
371
372            Desktop.addInternalFrame(af, "Original Data for " + this.title,
373                                     AlignFrame.DEFAULT_WIDTH,
374                                     AlignFrame.DEFAULT_HEIGHT);
375          }
376        }
377     }
378
379
380     /**
381      * DOCUMENT ME!
382      *
383      * @param e DOCUMENT ME!
384      */
385     public void fitToWindow_actionPerformed(ActionEvent e)
386     {
387         treeCanvas.fitToWindow = fitToWindow.isSelected();
388         repaint();
389     }
390
391     /**
392      * DOCUMENT ME!
393      *
394      * @param e DOCUMENT ME!
395      */
396     public void font_actionPerformed(ActionEvent e)
397     {
398         if (treeCanvas == null)
399         {
400             return;
401         }
402
403         new FontChooser(this);
404     }
405
406     public Font getTreeFont()
407     {
408         return treeCanvas.font;
409     }
410
411     public void setTreeFont(Font font)
412     {
413       if(treeCanvas!=null)
414       treeCanvas.setFont(font);
415     }
416
417     /**
418      * DOCUMENT ME!
419      *
420      * @param e DOCUMENT ME!
421      */
422     public void distanceMenu_actionPerformed(ActionEvent e)
423     {
424         treeCanvas.setShowDistances(distanceMenu.isSelected());
425     }
426
427     /**
428      * DOCUMENT ME!
429      *
430      * @param e DOCUMENT ME!
431      */
432     public void bootstrapMenu_actionPerformed(ActionEvent e)
433     {
434         treeCanvas.setShowBootstrap(bootstrapMenu.isSelected());
435     }
436
437     /**
438      * DOCUMENT ME!
439      *
440      * @param e DOCUMENT ME!
441      */
442     public void placeholdersMenu_actionPerformed(ActionEvent e)
443     {
444         treeCanvas.setMarkPlaceholders(placeholdersMenu.isSelected());
445     }
446
447     /**
448      * DOCUMENT ME!
449      *
450      * @param e DOCUMENT ME!
451      */
452     public void epsTree_actionPerformed(ActionEvent e)
453     {
454       boolean accurateText = true;
455
456       String renderStyle = jalview.bin.Cache.getDefault("EPS_RENDERING",
457           "Prompt each time");
458
459     // If we need to prompt, and if the GUI is visible then
460     // Prompt for EPS rendering style
461       if (renderStyle.equalsIgnoreCase("Prompt each time")
462           && !
463           (System.getProperty("java.awt.headless") != null
464            && System.getProperty("java.awt.headless").equals("true")))
465       {
466         EPSOptions eps = new EPSOptions();
467         renderStyle = eps.getValue();
468
469         if (renderStyle==null || eps.cancelled)
470           return;
471
472
473       }
474
475       if (renderStyle.equalsIgnoreCase("text"))
476       {
477         accurateText = false;
478       }
479
480         int width = treeCanvas.getWidth();
481         int height = treeCanvas.getHeight();
482
483         try
484         {
485             jalview.io.JalviewFileChooser chooser = new jalview.io.JalviewFileChooser(jalview.bin.Cache.getProperty(
486                         "LAST_DIRECTORY"), new String[] { "eps" },
487                     new String[] { "Encapsulated Postscript" },
488                     "Encapsulated Postscript");
489             chooser.setFileView(new jalview.io.JalviewFileView());
490             chooser.setDialogTitle("Create EPS file from tree");
491             chooser.setToolTipText("Save");
492
493             int value = chooser.showSaveDialog(this);
494
495             if (value != jalview.io.JalviewFileChooser.APPROVE_OPTION)
496             {
497                 return;
498             }
499
500             jalview.bin.Cache.setProperty("LAST_DIRECTORY",
501                                           chooser.getSelectedFile().getParent());
502
503             FileOutputStream out = new FileOutputStream(chooser.getSelectedFile());
504             EpsGraphics2D pg = new EpsGraphics2D("Tree", out, 0, 0, width,
505                                                  height);
506
507             pg.setAccurateTextMode(accurateText);
508
509             treeCanvas.draw(pg, width, height);
510
511             pg.flush();
512             pg.close();
513         }
514         catch (Exception ex)
515         {
516             ex.printStackTrace();
517         }
518     }
519
520     /**
521      * DOCUMENT ME!
522      *
523      * @param e DOCUMENT ME!
524      */
525     public void pngTree_actionPerformed(ActionEvent e)
526     {
527         int width = treeCanvas.getWidth();
528         int height = treeCanvas.getHeight();
529
530         try
531         {
532             jalview.io.JalviewFileChooser chooser = new jalview.io.JalviewFileChooser(jalview.bin.Cache.getProperty(
533                         "LAST_DIRECTORY"), new String[] { "png" },
534                     new String[] { "Portable network graphics" },
535                     "Portable network graphics");
536
537             chooser.setFileView(new jalview.io.JalviewFileView());
538             chooser.setDialogTitle("Create PNG image from tree");
539             chooser.setToolTipText("Save");
540
541             int value = chooser.showSaveDialog(this);
542
543             if (value != jalview.io.JalviewFileChooser.APPROVE_OPTION)
544             {
545                 return;
546             }
547
548             jalview.bin.Cache.setProperty("LAST_DIRECTORY",
549                 chooser.getSelectedFile().getParent());
550
551             FileOutputStream out = new FileOutputStream(chooser.getSelectedFile());
552
553             BufferedImage bi = new BufferedImage(width, height,
554                     BufferedImage.TYPE_INT_RGB);
555             Graphics png = bi.getGraphics();
556
557             treeCanvas.draw(png, width, height);
558
559             ImageIO.write(bi, "png", out);
560             out.close();
561         }
562         catch (Exception ex)
563         {
564             ex.printStackTrace();
565         }
566     }
567 }