JAL-1953 2.11.2 with Archeopteryx!
authorJim Procter <j.procter@dundee.ac.uk>
Fri, 3 Jun 2022 10:37:14 +0000 (11:37 +0100)
committerJim Procter <j.procter@dundee.ac.uk>
Fri, 3 Jun 2022 11:24:33 +0000 (12:24 +0100)
Minimal patches and Merge branch 'kjvdh/features/PhylogenyViewer' into merge/2_11_2/PhylogenyViewer
also restored last kjvdh build of forester to j8 and j11lib directories
 Conflicts:
.classpath
j8lib/forester.jar
resources/lang/Messages.properties
src/jalview/ext/rbvi/chimera/JalviewChimeraBinding.java
src/jalview/fts/core/GFTSPanel.java
src/jalview/fts/service/pdb/PDBFTSPanel.java
src/jalview/gui/AlignFrame.java
src/jalview/gui/DasSourceBrowser.java
src/jalview/gui/Desktop.java
src/jalview/gui/PopupMenu.java
src/jalview/gui/SplashScreen.java
src/jalview/gui/StructureViewerBase.java
src/jalview/io/BioJsHTMLOutput.java
src/jalview/io/FileLoader.java
src/jalview/io/HtmlSvgOutput.java
src/jalview/project/Jalview2XML.java
src/jalview/schemabinding/version2/JalviewModelSequence.java
src/jalview/util/DBRefUtils.java
src/jalview/viewmodel/AlignmentViewport.java
src/jalview/ws/DBRefFetcher.java
src/jalview/ws/DasSequenceFeatureFetcher.java
src/jalview/ws/jws2/Jws2Discoverer.java
utils/jalviewjs/buildxml/build.xml

83 files changed:
.gitmodules
forester [deleted submodule]
j11lib/forester.jar
j8lib/forester.jar
resources/_aptx_jalview_configuration_file.txt [moved from _aptx_jalview_configuration_file.txt with 99% similarity]
resources/lang/Messages.properties
src/jalview/analysis/AlignmentSorter.java
src/jalview/appletgui/OverviewPanel.java
src/jalview/appletgui/PCAPanel.java
src/jalview/appletgui/RedundancyPanel.java
src/jalview/bin/Jalview.java
src/jalview/ext/archaeopteryx/Aptx.java [deleted file]
src/jalview/ext/archaeopteryx/AptxControlPanel.java [new file with mode: 0644]
src/jalview/ext/archaeopteryx/AptxFrame.java [new file with mode: 0644]
src/jalview/ext/archaeopteryx/AptxInit.java
src/jalview/ext/archaeopteryx/AptxTreeBuilder.java
src/jalview/ext/archaeopteryx/AptxTreePanel.java
src/jalview/ext/archaeopteryx/JalviewBinding.java [deleted file]
src/jalview/ext/archaeopteryx/LoadedTreeAssociation.java [deleted file]
src/jalview/ext/archaeopteryx/Tree.java
src/jalview/ext/archaeopteryx/TreeIterator.java [new file with mode: 0644]
src/jalview/ext/archaeopteryx/TreeNode.java
src/jalview/ext/forester/DataConversions.java
src/jalview/ext/forester/io/ForesterParser.java [new file with mode: 0644]
src/jalview/ext/forester/io/NexusFile.java [new file with mode: 0644]
src/jalview/ext/forester/io/PhyloXmlFile.java [new file with mode: 0644]
src/jalview/ext/forester/io/TreeDatabaseMenuBuilder.java
src/jalview/ext/forester/io/TreeParser.java [deleted file]
src/jalview/ext/forester/io/UtilityMethods.java [new file with mode: 0644]
src/jalview/ext/treeviewer/ExternalLoadedTreeAssociationI.java [deleted file]
src/jalview/ext/treeviewer/ExternalTreeBuilderI.java [deleted file]
src/jalview/ext/treeviewer/ExternalTreeI.java [deleted file]
src/jalview/ext/treeviewer/ExternalTreeNodeI.java [deleted file]
src/jalview/ext/treeviewer/ExternalTreePanelI.java [deleted file]
src/jalview/ext/treeviewer/ExternalTreeParserI.java [deleted file]
src/jalview/ext/treeviewer/ExternalTreeViewerBindingI.java [deleted file]
src/jalview/ext/treeviewer/ExternalTreeViewerI.java [deleted file]
src/jalview/ext/treeviewer/JalviewBinding.java [new file with mode: 0644]
src/jalview/ext/treeviewer/LoadedTreeAssociationI.java [new file with mode: 0644]
src/jalview/ext/treeviewer/LoadedTreeSequenceAssociation.java [new file with mode: 0644]
src/jalview/ext/treeviewer/TreeBuilderI.java [new file with mode: 0644]
src/jalview/ext/treeviewer/TreeControlsI.java [new file with mode: 0644]
src/jalview/ext/treeviewer/TreeFrameI.java [new file with mode: 0644]
src/jalview/ext/treeviewer/TreeI.java [new file with mode: 0644]
src/jalview/ext/treeviewer/TreeNodeI.java [new file with mode: 0644]
src/jalview/ext/treeviewer/TreePanelI.java [new file with mode: 0644]
src/jalview/ext/treeviewer/TreeParserI.java [new file with mode: 0644]
src/jalview/ext/treeviewer/TreeViewerBindingI.java [new file with mode: 0644]
src/jalview/ext/treeviewer/TreeViewerUtils.java [new file with mode: 0644]
src/jalview/fts/core/GFTSPanel.java
src/jalview/fts/service/pdb/PDBFTSPanel.java
src/jalview/gui/AlignFrame.java
src/jalview/gui/AlignViewport.java
src/jalview/gui/AppJmol.java
src/jalview/gui/CalculationChooser.java
src/jalview/gui/ChimeraViewFrame.java
src/jalview/gui/Console.java
src/jalview/gui/Desktop.java
src/jalview/gui/JalviewDialog.java
src/jalview/gui/OverviewPanel.java
src/jalview/gui/RedundancyPanel.java
src/jalview/gui/StructureViewerBase.java
src/jalview/gui/TreeCanvas.java
src/jalview/gui/VamsasApplication.java
src/jalview/gui/WebserviceInfo.java
src/jalview/gui/WsPreferences.java
src/jalview/io/FileFormat.java
src/jalview/io/FileFormatI.java
src/jalview/io/FileLoader.java
src/jalview/io/IdentifyFile.java
src/jalview/javascript/JSFunctionExec.java
src/jalview/jbgui/GAlignFrame.java
src/jalview/project/Jalview2XML.java
src/jalview/util/AWTConsole.java
src/jalview/util/DBRefUtils.java
src/jalview/util/MappingUtils.java
src/jalview/viewmodel/AlignmentViewport.java
src/jalview/ws/DBRefFetcher.java
src/jalview/ws/jws2/Jws2Discoverer.java
test/jalview/ext/archaeopteryx/AptxJalviewSequenceTreeTest.java
test/jalview/ext/archaeopteryx/AptxPhylogenyTreeTest.java
test/jalview/ext/archaeopteryx/TreeViewTest.java
test/jalview/gui/FreeUpMemoryTest.java

index e9167c0..e69de29 100644 (file)
@@ -1,3 +0,0 @@
-[submodule "forester"]
-       path = forester
-       url = file:////Users/kjvanderheide/Documents/Archae/forester
diff --git a/forester b/forester
deleted file mode 160000 (submodule)
index 642ccb7..0000000
--- a/forester
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit 642ccb75fc1e4cb7def346cb2f56191907f82a34
index afe77b2..534564c 100644 (file)
Binary files a/j11lib/forester.jar and b/j11lib/forester.jar differ
index afe77b2..534564c 100644 (file)
Binary files a/j8lib/forester.jar and b/j8lib/forester.jar differ
similarity index 99%
rename from _aptx_jalview_configuration_file.txt
rename to resources/_aptx_jalview_configuration_file.txt
index 447f9a4..b5b75b7 100644 (file)
@@ -157,7 +157,7 @@ font_size_min:                             2
 font_size_max:                             20
 antialias_screen:                          yes
 show_scale:                                yes
-cladogram_type:                            lined_up
+cladogram_type:                            non_lined_up
 phylogeny_graphics_type:                   rectangular
 node_label_direction:                      horizontal
 show_default_node_shapes_internal:         yes
@@ -224,7 +224,7 @@ show_annotations:               display   no
 write_confidence_values:        display   ?
 write_branch_length_values:     display   yes
 write_events:                   display   ?
-use_visual_styles:              display   no
+use_visual_styles:              display   yes
 width_branches:                 display   no
 show_domain_architectures:      display   no
 show_msa:                       display   no
index 291052a..c5d566f 100644 (file)
@@ -174,6 +174,9 @@ label.average_distance_identity = Average Distance Using % Identity
 label.neighbour_joining_identity = Neighbour Joining Using % Identity
 label.choose_calculation = Choose Calculation
 label.calc_title = {0} Using {1}
+label.treecalc_title = {0} Using {1}
+label.aptx_title = Archaeopteryx Tree View 
+label.of_x = of {0}
 label.tree_calc_av = Average Distance
 label.tree_calc_nj = Neighbour Joining
 label.score_model_pid = % Identity
@@ -303,6 +306,10 @@ label.mark_unassociated_leaves = Mark Unassociated Leaves
 label.fit_to_window = Fit To Window
 label.newick_format = Newick Format
 label.select_tree_file = Select a tree file
+label.treebase_study = TreeBASE Study
+label.treebase = TreeBASE
+label.treefam = TreeFam
+label.tree_of_life = Tree of Life
 label.colours = Colours
 label.view_mapping = View Mapping
 label.wireframe = Wireframe
@@ -386,7 +393,9 @@ label.not_enough_sequences = Not enough sequences
 label.selected_region_to_tree_may_only_contain_residues_or_gaps =  The selected region to create a tree may\nonly contain residues or gaps.\nTry using the Pad function in the edit menu,\nor one of the multiple sequence alignment web services.
 label.sequences_selection_not_aligned = Sequences in selection are not aligned
 label.problem_reading_tree_file =  Problem reading tree file
+label.tabs_detected_archaeopteryx = Warning, multiple trees detected in a single tree viewer instance. This will cause problems!
 label.possible_problem_with_tree_file = Possible problem with tree file
+label.aptx_config_not_found = Warning: tree viewer configuration file not found, continue anyway? (this WILL cause the viewer to look different)
 label.tree_url_example = Please enter a complete URL, for example \"http://www.jalview.org/examples/ferredoxin.nw\"
 label.from_database = From Database...
 label.load_tree_url = Tree from URL
@@ -901,6 +910,8 @@ label.webservice_job_title_on = {0} using {1} on {2}
 label.loading_file = Loading File: {0}
 label.edit_params = Edit {0}
 label.as_percentage = As Percentage
+error.database_id_has_letters = Database identifier ({0}) should contain only digits
+error.phyloxml_validation = phyloXML XSD-based validation is turned off (enable with line 'validate_against_phyloxml_xsd_schem: true' in configuration file)
 error.not_implemented = Not implemented
 error.no_such_method_as_clone1_for = No such method as clone1 for {0}
 error.null_from_clone1 = Null from clone1!
index 81bddc2..6005208 100755 (executable)
@@ -29,12 +29,15 @@ import jalview.datamodel.SequenceFeature;
 import jalview.datamodel.SequenceGroup;
 import jalview.datamodel.SequenceI;
 import jalview.datamodel.SequenceNode;
+import jalview.ext.treeviewer.TreeI;
+import jalview.ext.treeviewer.TreeNodeI;
 import jalview.util.QuickSort;
 
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Map;
 
 /**
  * Routines for manipulating the order of a multiple sequence alignment TODO:
@@ -69,6 +72,8 @@ public class AlignmentSorter
 
   static TreeModel lastTree = null;
 
+  static TreeI lastExternalTree = null;
+
   static boolean sortTreeAscending = true;
 
   /*
@@ -438,7 +443,7 @@ public class AlignmentSorter
 
     List<SequenceI> tmp = new ArrayList<>();
 
-    tmp = _sortByTree(tree.getTopNode(), tmp, align.getSequences());
+    tmp = _sortByTree(tree.getTopNode(), tmp);
 
     if (tmp.size() != nSeq)
     {
@@ -461,6 +466,27 @@ public class AlignmentSorter
     return tmp;
   }
 
+
+
+  private static List<SequenceI> getOrderByTree(TreeI aptxTree,
+          Map<TreeNodeI, SequenceI> nodesWithBoundSeqs)
+  {
+    List<SequenceI> seqsByTreeOrder = new ArrayList<>();
+    if (!aptxTree.isEmpty())
+    {
+      for (final Iterator<TreeNodeI> iter = aptxTree
+              .iterateInPreOrder(); iter.hasNext();)
+      {
+        TreeNodeI treeNode = iter.next();
+        seqsByTreeOrder.add(nodesWithBoundSeqs.get(treeNode));
+      }
+
+    }
+    return seqsByTreeOrder;
+
+
+  }
+
   /**
    * Sorts the alignment by a given tree
    * 
@@ -496,6 +522,48 @@ public class AlignmentSorter
   }
 
   /**
+   * Sorts the alignment by a given tree from Archaeopteryx
+   * 
+   * @param align
+   *          alignment to order
+   * @param tree
+   *          tree which has
+   */
+  public static void sortByTree(AlignmentI align,
+          Map<TreeNodeI, SequenceI> nodesBoundToSequences,
+          TreeI treeI) throws IllegalArgumentException
+  {
+    List<SequenceI> tmp = getOrderByTree(treeI, nodesBoundToSequences);
+
+    if (!tmp.isEmpty())
+    {
+      if (lastExternalTree != treeI)
+      {
+        sortTreeAscending = true;
+        lastExternalTree = treeI;
+      }
+      else
+      {
+        sortTreeAscending = !sortTreeAscending;
+      }
+
+      if (sortTreeAscending)
+      {
+        setOrder(align, tmp);
+      }
+      else
+      {
+        setReverseOrder(align,
+                vectorSubsetToArray(tmp, align.getSequences()));
+      }
+    }
+    else
+    {
+      throw new IllegalArgumentException();
+    }
+  }
+
+  /**
    * DOCUMENT ME!
    * 
    * @param align
@@ -535,7 +603,7 @@ public class AlignmentSorter
    * @return DOCUMENT ME!
    */
   private static List<SequenceI> _sortByTree(SequenceNode node,
-          List<SequenceI> tmp, List<SequenceI> seqset)
+          List<SequenceI> tmp)
   {
     if (node == null)
     {
@@ -564,13 +632,15 @@ public class AlignmentSorter
     }
     else
     {
-      _sortByTree(left, tmp, seqset);
-      _sortByTree(right, tmp, seqset);
+      _sortByTree(left, tmp);
+      _sortByTree(right, tmp);
     }
 
     return tmp;
   }
 
+
+
   // Ordering Objects
   // Alignment.sortBy(OrderObj) - sequence of sequence pointer refs in
   // appropriate order
index 09e54e7..685b8c9 100755 (executable)
@@ -244,7 +244,7 @@ public class OverviewPanel extends Panel implements Runnable,
 
       updateRunning = true;
     }
-    Thread thread = new Thread(this, "OverviewUpdateThread");
+    Thread thread = new Thread(this, "OverviewUpdate");
     thread.start();
     repaint();
     updateRunning = false;
index fe9d69b..0a4e1c5 100644 (file)
@@ -117,7 +117,7 @@ public class PCAPanel extends EmbmenuFrame
             MessageManager.getString("label.principal_component_analysis"),
             475, 400);
 
-    Thread worker = new Thread(this, "PCACalcThread");
+    Thread worker = new Thread(this, "PCACalc");
     worker.start();
   }
 
@@ -218,7 +218,7 @@ public class PCAPanel extends EmbmenuFrame
         ScoreModelI scoreModel = ScoreModels.getInstance()
                 .getDefaultModel(false);
         pcaModel.setScoreModel(scoreModel);
-        new Thread(this, "PCARecalcThread").start();
+        new Thread(this, "PCARecalc").start();
       }
     }
     else if (evt.getSource() == protSetting)
@@ -229,7 +229,7 @@ public class PCAPanel extends EmbmenuFrame
         ScoreModelI scoreModel = ScoreModels.getInstance()
                 .getDefaultModel(true);
         pcaModel.setScoreModel(scoreModel);
-        new Thread(this, "PCARecalcThread").start();
+        new Thread(this, "PCARecalc").start();
       }
     }
   }
index c7d8157..41bba33 100644 (file)
@@ -89,7 +89,7 @@ public class RedundancyPanel extends SliderPanel
 
     frame.addWindowListener(this);
 
-    Thread worker = new Thread(this, "RedundancyCalcThread");
+    Thread worker = new Thread(this, "RedundancyCalc");
     worker.start();
   }
 
index efa5d6f..ea61024 100755 (executable)
@@ -191,7 +191,7 @@ public class Jalview
             running--;
           }
         }
-      }, "FeatureFetcherThread").start();
+      }, "FeatureFetcher").start();
     }
 
     public synchronized boolean allFinished()
diff --git a/src/jalview/ext/archaeopteryx/Aptx.java b/src/jalview/ext/archaeopteryx/Aptx.java
deleted file mode 100644 (file)
index 640dd31..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-package jalview.ext.archaeopteryx;
-
-import jalview.ext.treeviewer.ExternalTreeViewerI;
-
-import org.forester.archaeopteryx.MainFrame;
-
-public class Aptx implements ExternalTreeViewerI
-{
-  private final MainFrame aptxApp;
-
-  public Aptx(MainFrame aptx)
-  {
-    aptxApp = aptx;
-
-
-  }
-}
diff --git a/src/jalview/ext/archaeopteryx/AptxControlPanel.java b/src/jalview/ext/archaeopteryx/AptxControlPanel.java
new file mode 100644 (file)
index 0000000..aa0ffc6
--- /dev/null
@@ -0,0 +1,37 @@
+package jalview.ext.archaeopteryx;
+
+import jalview.ext.treeviewer.TreeControlsI;
+
+import org.forester.archaeopteryx.ControlPanel;
+
+/**
+ * Wrapper for the Archaeopteryx control panel (left side panel) Currently just
+ * used for refreshing Aptx upon initialisation.
+ * 
+ * @author kjvanderheide
+ *
+ */
+public class AptxControlPanel implements TreeControlsI
+{
+  ControlPanel aptxCp;
+
+  /**
+   * Note that this control panel MUST be part of an Archaeopteryx frame
+   * 
+   * @param aptxControlPanel
+   *          the original Control Panel from Archaeopteryx
+   */
+  protected AptxControlPanel(ControlPanel aptxControlPanel)
+  {
+    aptxCp = aptxControlPanel;
+
+  }
+
+  @Override
+  public void displayEntireTree()
+  {
+    aptxCp.showWhole();
+
+  }
+
+}
diff --git a/src/jalview/ext/archaeopteryx/AptxFrame.java b/src/jalview/ext/archaeopteryx/AptxFrame.java
new file mode 100644 (file)
index 0000000..fca6e49
--- /dev/null
@@ -0,0 +1,510 @@
+package jalview.ext.archaeopteryx;
+
+import jalview.bin.Cache;
+import jalview.ext.treeviewer.TreeControlsI;
+import jalview.ext.treeviewer.TreeFrameI;
+import jalview.ext.treeviewer.TreeI;
+import jalview.ext.treeviewer.TreePanelI;
+import jalview.ext.treeviewer.TreeViewerBindingI;
+import jalview.ext.treeviewer.TreeViewerUtils;
+import jalview.gui.Desktop;
+import jalview.gui.LineartOptions;
+import jalview.io.JalviewFileChooser;
+import jalview.io.JalviewFileView;
+import jalview.util.ImageMaker;
+import jalview.util.MessageManager;
+import jalview.util.Platform;
+import jalview.util.ImageMaker.TYPE;
+
+import java.awt.Component;
+import java.awt.Container;
+import java.awt.Dimension;
+import java.awt.Event;
+import java.awt.Font;
+import java.awt.Image;
+import java.awt.MenuComponent;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.FileOutputStream;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import javax.accessibility.AccessibleContext;
+import javax.swing.JLayeredPane;
+import javax.swing.JMenu;
+import javax.swing.JMenuBar;
+import javax.swing.JMenuItem;
+import javax.swing.JRootPane;
+import javax.swing.JSeparator;
+import javax.swing.event.InternalFrameListener;
+
+import org.forester.archaeopteryx.Archaeopteryx;
+import org.forester.archaeopteryx.Configuration;
+import org.forester.archaeopteryx.MainFrame;
+import org.forester.phylogeny.Phylogeny;
+import org.jibble.epsgraphics.EpsGraphics2D;
+
+public class AptxFrame implements TreeFrameI
+{
+  private final MainFrame aptxFrame;
+
+  private TreeViewerBindingI viewBinding;
+
+  private TreePanelI aptxPanel;
+
+  private TreeControlsI aptxControls;
+
+
+  public AptxFrame(Phylogeny tree, Configuration aptxConfig,
+          String treeTitle)
+  {
+    this(Archaeopteryx.createApplication(tree,
+            aptxConfig,
+            treeTitle));
+
+  }
+
+
+  public AptxFrame(MainFrame aptx)
+  {
+
+    aptxFrame = aptx;
+    aptxPanel = new AptxTreePanel(
+            aptxFrame.getMainPanel().getCurrentTreePanel());
+    aptxControls = new AptxControlPanel(
+            aptxFrame.getMainPanel().getControlPanel());
+    adaptAptxGui(aptxFrame);
+
+  }
+  
+  /**
+   * Hides certain redundant Archaeopteryx GUI elements such as the menu items
+   * for reading in trees and adds extra items related to Jalview such as the
+   * tree sorting menu item.
+   * 
+   * 
+   * @param aptxFrame
+   */
+  protected void adaptAptxGui(MainFrame aptxFrame)
+  {
+    JMenuBar frameBar = aptxFrame.getJMenuBar();
+    boolean epsAdded = false;
+    for (int i = 0; i < frameBar.getMenuCount();i++) {
+      JMenu menu = frameBar.getMenu(i);
+      int menuCount = menu.getMenuComponentCount();
+
+      if (menu.getText().contains("File"))
+      {
+        // hide all "Read from ..." and "New" menu items and any Separators that
+        // come directly after them
+        Component previousComp = null;
+        for (int x = 0; x < menuCount; x++)
+        {
+          Component menuItem = menu.getMenuComponent(x);
+          if (previousComp instanceof JMenuItem)
+          {
+            JMenuItem previousMenuItem = (JMenuItem) previousComp;
+            if (previousMenuItem.getText().startsWith("Read")
+                    || previousMenuItem.getText()
+                            .startsWith("New")
+                    || previousMenuItem.getText()
+                            .startsWith("Close Tab"))
+            {
+              previousComp.setVisible(false);
+
+              if (menuItem instanceof JSeparator)
+              {
+                menuItem.setVisible(false);
+              }
+
+            }
+
+            if ((!epsAdded) && previousMenuItem.getText()
+                    .startsWith("Export to"))
+            {
+              JMenuItem exportEps = new JMenuItem("Export to EPS file...");
+              menu.add(exportEps, x);
+              exportEps.addActionListener(new ActionListener()
+              {
+
+                @Override
+                public void actionPerformed(ActionEvent e)
+                {
+                  epsTree_actionPerformed(e);
+
+                }
+                
+              });
+              epsAdded = true;
+
+            }
+          }
+          previousComp = menuItem;
+        }
+      }
+      else if (menu.getText().contains("Inference"))
+      {
+        menu.setVisible(false);
+      }
+      else if (menu.getText().contains("View"))
+      {
+        menu.addSeparator();
+
+        JMenuItem sortByTree = new JMenuItem("Sort alignment by tree");
+        JMenuItem refreshJalview = new JMenuItem(
+                "Filter alignment to show only currently visible sequences");
+        JMenuItem hideCollapsed = new JMenuItem(
+                "Hide sequences of collapsed nodes");
+
+        refreshJalview.setFont(menu.getFont());
+        refreshJalview.addActionListener(new ActionListener() {
+          
+          @Override
+          public void actionPerformed(ActionEvent e) {
+            TreeViewerBindingI bindingManager = TreeViewerUtils
+                    .getActiveTreeViews().get(AptxFrame.this);
+            bindingManager.actionPerformed(e);
+          }
+        });
+                
+        sortByTree.addActionListener(new ActionListener()
+        {
+
+          @Override
+          public void actionPerformed(ActionEvent e)
+          {
+            TreeViewerBindingI bindingManager = TreeViewerUtils
+                    .getActiveTreeViews().get(AptxFrame.this);
+            bindingManager.sortByTree_actionPerformed();
+
+          }
+
+        });
+
+        hideCollapsed.addActionListener(new ActionListener()
+        {
+
+          @Override
+          public void actionPerformed(ActionEvent e)
+          {
+            TreeViewerBindingI bindingManager = TreeViewerUtils
+                    .getActiveTreeViews().get(AptxFrame.this);
+            bindingManager.hideCollapsedSequences_actionPerformed();
+            
+          }
+
+        });
+
+        menu.add(sortByTree);
+        menu.add(refreshJalview);
+        menu.add(hideCollapsed);
+
+        sortByTree.setFont(menu.getFont());
+
+
+
+      }
+
+    }
+    // aptxFrame.validate();
+  }
+
+  public void epsTree_actionPerformed(ActionEvent e)
+  {
+    boolean accurateText = true;
+    final long messageId = System.currentTimeMillis();
+
+    String renderStyle = jalview.bin.Cache.getDefault("EPS_RENDERING",
+            "Prompt each time");
+    if (Platform.isJS())
+    {
+      renderStyle = "Text";
+    }
+
+    AtomicBoolean textSelected = new AtomicBoolean(
+            !"Lineart".equals(renderStyle));
+
+    // If we need to prompt, and if the GUI is visible then
+    // Prompt for EPS rendering style
+    if (renderStyle.equalsIgnoreCase("Prompt each time")
+            && !Platform.isHeadless())
+    // && !(System.getProperty("java.awt.headless") != null && System
+    // .getProperty("java.awt.headless").equals("true")))
+    {
+      LineartOptions epsOption = new LineartOptions(TYPE.EPS.getName(),
+              textSelected);
+      epsOption.setResponseAction(1, new Runnable()
+      {
+        @Override
+        public void run()
+        {
+          // report canceled
+          // setStatus(MessageManager.formatMessage(
+          // "status.cancelled_image_export_operation",
+          // TYPE.EPS.getName()), messageId);
+        }
+      });
+      epsOption.setResponseAction(0, new Runnable()
+      {
+        @Override
+        public void run()
+        {
+          // TODO Auto-generated method stub
+
+          String renderStyle = epsOption.getValue();
+
+          if (renderStyle == null)
+          {
+            return;
+          }
+
+          boolean accurateText = true;
+          if (renderStyle.equalsIgnoreCase("text"))
+          {
+            accurateText = false;
+          }
+          doExport(accurateText);
+
+        }
+
+      });
+      epsOption.showDialog();
+    }
+    else
+    {
+      doExport(accurateText);
+    }
+  }
+
+  protected void doExport(boolean accurateText)
+  {
+    int width = getTreePanel().getWidth();
+    int height = getTreePanel().getHeight();
+
+    try
+    {
+      JalviewFileChooser chooser = new JalviewFileChooser(
+              ImageMaker.EPS_EXTENSION, ImageMaker.EPS_EXTENSION);
+      chooser.setFileView(new JalviewFileView());
+      chooser.setDialogTitle(
+              MessageManager.getString("label.create_eps_from_tree"));
+      chooser.setToolTipText(MessageManager.getString("action.save"));
+
+      int value = chooser.showSaveDialog(aptxFrame);
+
+      if (value != JalviewFileChooser.APPROVE_OPTION)
+      {
+        return;
+      }
+
+      Cache.setProperty("LAST_DIRECTORY",
+              chooser.getSelectedFile().getParent());
+
+      FileOutputStream out = new FileOutputStream(
+              chooser.getSelectedFile());
+      EpsGraphics2D pg = new EpsGraphics2D("Tree", out, 0, 0, width,
+              height);
+
+      pg.setAccurateTextMode(accurateText);
+
+      getTreePanel().paintToFile(pg, width, height);
+
+      pg.flush();
+      pg.close();
+    } catch (Exception ex)
+    {
+      ex.printStackTrace();
+    }
+  }
+  @Override
+  public TreePanelI getTreePanel()
+  {
+    return aptxPanel;
+  }
+
+  @Override
+  public TreeI getTree()
+  {
+    return aptxPanel.getTree();
+  }
+
+  @Override
+  public void enableMultipleTrees()
+  {
+    aptxFrame.activateSaveAllIfNeeded();
+
+  }
+
+  @Override
+  public int getNumberOfTrees()
+  {
+    return aptxFrame.getMainPanel().getTabbedPane().getTabCount();
+  }
+
+  @Override
+  public TreeControlsI getTreeControls()
+  {
+    return aptxControls;
+  }
+
+  @Override
+  public AccessibleContext getAccessibleContext()
+  {
+    return aptxFrame.getAccessibleContext();
+  }
+
+  @Override
+  public JRootPane getRootPane()
+  {
+    return aptxFrame.getRootPane();
+  }
+
+  @Override
+  public void setContentPane(Container contentPane)
+  {
+    aptxFrame.setContentPane(contentPane);
+
+  }
+
+  @Override
+  public Container getContentPane()
+  {
+    return aptxFrame.getContentPane();
+  }
+
+  @Override
+  public void setLayeredPane(JLayeredPane layeredPane)
+  {
+    aptxFrame.setLayeredPane(layeredPane);
+
+  }
+
+  @Override
+  public JLayeredPane getLayeredPane()
+  {
+    return aptxFrame.getLayeredPane();
+  }
+
+  @Override
+  public void setGlassPane(Component glassPane)
+  {
+    aptxFrame.setGlassPane(glassPane);
+
+  }
+
+  @Override
+  public Component getGlassPane()
+  {
+    return aptxFrame.getGlassPane();
+  }
+
+  @Override
+  public boolean imageUpdate(Image img, int infoflags, int x, int y,
+          int width, int height)
+  {
+    return aptxFrame.imageUpdate(img, infoflags, x, y, width, height);
+  }
+
+  @Override
+  public Font getFont()
+  {
+    return aptxFrame.getFont();
+  }
+
+  @Override
+  public void remove(MenuComponent comp)
+  {
+    aptxFrame.remove(comp);
+
+  }
+
+  @Deprecated
+  @Override
+  public boolean postEvent(Event evt)
+  {
+    return aptxFrame.postEvent(evt);
+  }
+
+  @Override
+  public void addFrameListener(InternalFrameListener listener)
+  {
+    aptxFrame.addInternalFrameListener(listener);
+
+  }
+
+  @Override
+  public void removeFrameListener(InternalFrameListener listener)
+  {
+    aptxFrame.removeInternalFrameListener(listener);
+
+  }
+
+  @Override
+  public InternalFrameListener[] getFrameListeners()
+  {
+    return aptxFrame.getInternalFrameListeners();
+
+  }
+
+  @Override
+  public void repaint()
+  {
+    aptxFrame.repaint();
+
+  }
+
+  @Override
+  public void setMinimumSize(Dimension dimension)
+  {
+    aptxFrame.setMinimumSize(dimension);
+
+  }
+
+  @Override
+  public boolean isShowing()
+  {
+    return aptxFrame.isShowing();
+  }
+
+  @Override
+  public Container getTopLevelAncestor()
+  {
+    return aptxFrame.getTopLevelAncestor();
+  }
+
+  @Override
+  public void addFrameToJalview(String title, boolean makeVisible,
+          int width, int height, boolean resizable, boolean ignoreMinSize)
+  {
+    Desktop.addInternalFrame(aptxFrame, title, makeVisible, width, height,
+            resizable, ignoreMinSize);
+
+  }
+
+  @Override
+  public TreeViewerBindingI getViewBinding()
+  {
+    return viewBinding;
+  }
+
+  @Override
+  public void setViewBinding(TreeViewerBindingI alignmentBinding)
+  {
+    viewBinding = alignmentBinding;
+  }
+
+
+  @Override
+  public void setMaximumSize(Dimension maximumSize)
+  {
+    aptxFrame.setMaximumSize(maximumSize);
+
+  }
+
+  @Override
+  public void setPreferredSize(Dimension preferredSize)
+  {
+    aptxFrame.setPreferredSize(preferredSize);
+
+  }
+
+}
\ No newline at end of file
index e58a38d..f06deb3 100644 (file)
@@ -1,25 +1,38 @@
 package jalview.ext.archaeopteryx;
 
-import jalview.analysis.TreeBuilder;
-import jalview.datamodel.SequenceI;
-import jalview.ext.treeviewer.ExternalTreeBuilderI;
-import jalview.ext.treeviewer.ExternalTreeViewerBindingI;
+import jalview.ext.forester.io.UtilityMethods;
+import jalview.ext.treeviewer.LoadedTreeAssociationI;
+import jalview.ext.treeviewer.LoadedTreeSequenceAssociation;
+import jalview.ext.treeviewer.TreeFrameI;
+import jalview.ext.treeviewer.TreeI;
+import jalview.ext.treeviewer.TreeViewerUtils;
 import jalview.gui.Desktop;
+import jalview.gui.JvOptionPane;
+import jalview.util.MessageManager;
 import jalview.viewmodel.AlignmentViewport;
 
-import java.awt.Dimension;
+import java.io.File;
 import java.io.FileNotFoundException;
 import java.io.IOException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
 import java.net.URL;
-import java.util.Map;
 
 import org.forester.archaeopteryx.AptxUtil;
-import org.forester.archaeopteryx.Archaeopteryx;
 import org.forester.archaeopteryx.Configuration;
-import org.forester.archaeopteryx.MainFrame;
+import org.forester.archaeopteryx.webservices.PhylogeniesWebserviceClient;
+import org.forester.archaeopteryx.webservices.WebserviceUtil;
+import org.forester.io.parsers.PhylogenyParser;
+import org.forester.io.parsers.nexus.NexusPhylogeniesParser;
 import org.forester.io.parsers.nhx.NHXParser;
+import org.forester.io.parsers.phyloxml.PhyloXmlDataFormatException;
+import org.forester.io.parsers.phyloxml.PhyloXmlParser;
+import org.forester.io.parsers.tol.TolParser;
+import org.forester.io.parsers.util.ParserUtils;
 import org.forester.phylogeny.Phylogeny;
-import org.forester.phylogeny.PhylogenyNode;
+import org.forester.phylogeny.PhylogenyMethods;
+import org.forester.phylogeny.data.Identifier;
+import org.forester.util.ForesterUtil;
 
 /**
  * Static class for creating Archaeopteryx tree viewer instances from calculated
@@ -30,9 +43,19 @@ import org.forester.phylogeny.PhylogenyNode;
  */
 public final class AptxInit
 {
+  public final static InputStream CONFIG_LOC = AptxInit.class
 
-  private final static Configuration APTX_CONFIG = new Configuration(
-          "_aptx_jalview_configuration_file", false, false, false);
+          .getResourceAsStream("/_aptx_jalview_configuration_file.txt");
+
+  public final static Configuration APTX_CONFIG = new Configuration(
+          CONFIG_LOC,
+          false, false);
+  static
+  {
+    APTX_CONFIG.setBaseFontSize(Desktop.instance.getFont().getSize());
+    APTX_CONFIG
+            .setBaseFontFamilyName(Desktop.instance.getFont().getFamily());
+  }
 
   private final static boolean VALIDATE_PHYLOXML_XSD = APTX_CONFIG
           .isValidatePhyloXmlAgainstSchema();
@@ -49,151 +72,491 @@ public final class AptxInit
   private final static NHXParser.TAXONOMY_EXTRACTION TAXONOMY_EXTRACTION = APTX_CONFIG
           .getTaxonomyExtraction();
 
-  /**
-   * Test method, should generally not be used as it does not bind the tree to
-   * its alignment
-   * 
-   * @param aptxTrees
-   * @return
-   */
-  public static MainFrame createUnboundInstance(final Phylogeny aptxTree)
-  {
-    Phylogeny[] aptxTrees = { aptxTree };
-    return createAptxFrame(aptxTrees);
-  }
 
-  // public static MainFrame createInstance(final Phylogeny[] aptxTrees,
-  // AlignmentViewport jalviewAlignmentView)
-  // {
-  // return createAptxFrameInJalview(aptxTrees);
-  //
-  // }
-  //
-  // public static MainFrame createInstance(final Phylogeny aptxTree,
-  // final AlignmentViewport jalviewAlignmentView)
-  // {
-  // Phylogeny[] aptxTrees = { aptxTree }; // future possibility to load in
-  // // several trees simultaneously
-  // return createAptxFrameInJalview(aptxTrees);
-  //
-  // }
-
-  public static MainFrame createInstance(
-          final TreeBuilder calculatedTree) // very dense method, to be split up
+  public static TreeFrameI createInstanceFromNhx(String treeTitle,
+          String nhxString, AlignmentViewport viewport)
+          throws IOException
   {
-    ExternalTreeBuilderI<Phylogeny, PhylogenyNode> aptxTreeBuilder = new AptxTreeBuilder(
-            calculatedTree);
+    if (Desktop.instance != null)
+    {
+      Desktop.instance.startLoading(treeTitle);
+    }
+
+
+    Phylogeny aptxPhylogeny = Phylogeny
+            .createInstanceFromNhxString(nhxString);
+    aptxPhylogeny.setName(treeTitle);
 
-    Phylogeny aptxTree = aptxTreeBuilder.buildTree();
-    Phylogeny[] aptxTrees = { aptxTree }; // future possibility to load in
-                                          // several trees simultaneously
+    TreeFrameI aptxFrame = createAptxFrame(aptxPhylogeny, viewport,
+            treeTitle);
 
-    MainFrame aptxApp = createAptxFrame(aptxTrees);
-            
-    bindNodesToJalviewSequences(aptxApp, calculatedTree.getAvport(),
-            aptxTreeBuilder.getAlignmentBoundNodes(),
-            aptxTreeBuilder.getNodesBoundAlignment());
+    if (Desktop.instance != null)
+    {
+      Desktop.instance.stopLoading();
+    }
 
-    return bindFrameToJalview(aptxApp);
+    return aptxFrame;
 
   }
 
-  public static MainFrame createInstanceFromFile(String filePath,
+  /**
+   * Refactored from Archaeopteryx.main
+   * 
+   * @param filePath
+   * @param viewport
+   * @return
+   * @throws IOException
+   * @throws FileNotFoundException
+   */
+  public static TreeFrameI[] createInstancesFromFile(File treeFile,
           AlignmentViewport viewport)
+          throws FileNotFoundException, IOException
   {
-    String[] AptxArgs = new String[] { "-c",
-        APTX_CONFIG.getConfigFilename(), filePath };
-    MainFrame aptxApp = Archaeopteryx.main(AptxArgs);
-
-    int tabCount = aptxApp.getMainPanel().getTabbedPane().getTabCount();
-
-    for (int i = 0; i < tabCount; i++)
+    TreeFrameI[] aptxFrames = null;
+    if (UtilityMethods.canForesterReadFile(treeFile))
     {
-      // roundabout way to select each tree because getComponentAt(i) requires
-      // casting to TreePanel which doesn't work
-      aptxApp.getMainPanel().getTabbedPane().setSelectedIndex(i);
-      Phylogeny tree = aptxApp.getMainPanel().getCurrentTreePanel()
-              .getPhylogeny();
 
-    LoadedTreeAssociation bindAptxNodes = new LoadedTreeAssociation(
-            viewport.getAlignment().getSequencesArray(),
-              tree);
+      if (Desktop.instance != null)
+      {
+        Desktop.instance.startLoading(treeFile.getCanonicalPath());
+      }
+      boolean nhx_or_nexus = false;
+      final PhylogenyParser parser = ParserUtils
+              .createParserDependingOnFileType(treeFile,
+                      VALIDATE_PHYLOXML_XSD);
+      if (parser instanceof NHXParser)
+      {
+        nhx_or_nexus = true;
+        final NHXParser nhx = (NHXParser) parser;
+        nhx.setReplaceUnderscores(REPLACE_NHX_UNDERSCORES);
+        nhx.setIgnoreQuotes(false);
+        nhx.setTaxonomyExtraction(TAXONOMY_EXTRACTION);
+      }
+      else if (parser instanceof NexusPhylogeniesParser)
+      {
+        nhx_or_nexus = true;
+        final NexusPhylogeniesParser nex = (NexusPhylogeniesParser) parser;
+        nex.setReplaceUnderscores(REPLACE_NHX_UNDERSCORES);
+        nex.setIgnoreQuotes(false);
+      }
+      else if (parser instanceof PhyloXmlParser)
+      {
+        if (VALIDATE_PHYLOXML_XSD == false)
+        {
+          JvOptionPane.showInternalMessageDialog(Desktop.desktop,
+                  MessageManager.getString("error.phyloxml_validation"),
+                  MessageManager.getString("label.file_open_error"),
+                  JvOptionPane.WARNING_MESSAGE);
+        }
+      }
+      Phylogeny[] trees = PhylogenyMethods.readPhylogenies(parser,
+              treeFile);
+      aptxFrames = new TreeFrameI[trees.length];
+
+      for (int i = 0; i < trees.length; i++)
+      {
+        Phylogeny aptxPhylogeny = trees[i];
+
+        if (nhx_or_nexus && INTERNAL_NUMBERS_AS_CONFIDENCE)
+        {
+          PhylogenyMethods
+                  .transferInternalNodeNamesToConfidence(aptxPhylogeny, "");
+        }
+        String treeTitle = treeFile.getName() + "[" + i + "]";
+        aptxPhylogeny.setName(treeTitle);
+        aptxFrames[i] = createAptxFrame(aptxPhylogeny, viewport, treeTitle);
+
+      }
+      if (Desktop.instance != null)
+      {
+        Desktop.instance.stopLoading();
+      }
+    }
+    return aptxFrames;
+  }
 
-    bindAptxNodes.associateLeavesToSequences();
 
-    bindNodesToJalviewSequences(aptxApp, viewport,
-            bindAptxNodes.getAlignmentWithNodes(),
-            bindAptxNodes.getNodesWithAlignment());
+  public static TreeFrameI[] createInstancesFromFile(
+          String filePath,
+          AlignmentViewport viewport)
+          throws FileNotFoundException, IOException
+  {
+    File treeFile = new File(filePath);
+    return createInstancesFromFile(treeFile, viewport);
+
     }
-    return bindFrameToJalview(aptxApp);
-  }
 
-  public static MainFrame createInstanceFromUrl(URL treeUrl,
+  public static TreeFrameI[] createInstancesFromUrl(URL treeUrl,
           AlignmentViewport viewport)
           throws FileNotFoundException, IOException, RuntimeException
   {
+    
     String treeTitle = treeUrl.getFile();
+    if (Desktop.instance != null)
+    {
+      Desktop.instance.startLoading(treeTitle);
+    }
     Phylogeny[] trees = AptxUtil.readPhylogeniesFromUrl(treeUrl,
             VALIDATE_PHYLOXML_XSD,
              REPLACE_NHX_UNDERSCORES, INTERNAL_NUMBERS_AS_CONFIDENCE,
             TAXONOMY_EXTRACTION, MIDPOINT_REROOT);
-    MainFrame aptxApp = Archaeopteryx.createApplication(trees, APTX_CONFIG,
-            treeTitle);
 
-    for (Phylogeny tree : trees)
+    TreeFrameI[] aptxFrames = new TreeFrameI[trees.length];
+    for (int i = 0; i < trees.length; i++)
     {
-      LoadedTreeAssociation bindAptxNodes = new LoadedTreeAssociation(
-              viewport.getAlignment().getSequencesArray(), tree);
-
-      bindAptxNodes.associateLeavesToSequences();
-      bindNodesToJalviewSequences(aptxApp, viewport,
-              bindAptxNodes.getAlignmentWithNodes(),
-              bindAptxNodes.getNodesWithAlignment());
+      Phylogeny aptxTree = trees[i];
+      aptxFrames[i] = createAptxFrame(aptxTree, viewport, treeTitle);
+    }
 
+    if (Desktop.instance != null)
+    {
+      Desktop.instance.stopLoading();
     }
 
-    return bindFrameToJalview(aptxApp);
+    return aptxFrames;
 
   }
 
+  /**
+   * Refactored from Forester's UrlTreeReader, this can be more efficient
+   * 
+   * @param databaseIndex
+   * @param viewport
+   * @return
+   */
+  public static TreeFrameI[] createInstancesFromDb(
+          PhylogeniesWebserviceClient treeDbClient, String identifier,
+          AlignmentViewport viewport)
+  {
 
+    URL url = null;
+    Phylogeny[] trees = null;
+    TreeFrameI[] aptxFrames = null;
+
+    if ((identifier != null) && (identifier.trim().length() > 0))
+    {
+      if (Desktop.instance != null)
+      {
+        Desktop.instance.startLoading(identifier);
+      }
+
+      identifier = identifier.trim();
+      if (treeDbClient.isQueryInteger())
+      {
+        identifier = identifier.replaceAll("^\\D+", "");
+
+        int id;
+        try
+        {
+          id = Integer.parseInt(identifier);
+        } catch (final NumberFormatException e)
+        {
+          JvOptionPane.showInternalMessageDialog(Desktop.desktop,
+                  MessageManager.formatMessage(
+                          "error.database_id_has_letters", new String[]
+                          { identifier }),
+                  MessageManager.getString("label.invalid_url"),
+                  JvOptionPane.ERROR_MESSAGE);
+          return new TreeFrameI[0];
+        }
+        identifier = id + "";
+      }
+      boolean exception = false;
+      try
+      {
+        String url_str = treeDbClient.getUrl();
+        url_str = url_str.replaceFirst(
+                PhylogeniesWebserviceClient.QUERY_PLACEHOLDER, identifier);
+        url = new URL(url_str);
+        PhylogenyParser parser = null;
+        switch (treeDbClient.getReturnFormat())
+        {
+        case TOL_XML_RESPONSE:
+          parser = new TolParser();
+          break;
+        case NEXUS:
+          parser = new NexusPhylogeniesParser();
+          ((NexusPhylogeniesParser) parser).setReplaceUnderscores(true);
+          break;
+        case TREEBASE_TREE:
+          parser = new NexusPhylogeniesParser();
+          ((NexusPhylogeniesParser) parser).setReplaceUnderscores(true);
+          ((NexusPhylogeniesParser) parser)
+                  .setTaxonomyExtraction(NHXParser.TAXONOMY_EXTRACTION.NO);
+          break;
+        case TREEBASE_STUDY:
+          parser = new NexusPhylogeniesParser();
+          ((NexusPhylogeniesParser) parser).setReplaceUnderscores(true);
+          ((NexusPhylogeniesParser) parser)
+                  .setTaxonomyExtraction(NHXParser.TAXONOMY_EXTRACTION.NO);
+          break;
+        case NH:
+          parser = new NHXParser();
+          ((NHXParser) parser)
+                  .setTaxonomyExtraction(NHXParser.TAXONOMY_EXTRACTION.NO);
+          ((NHXParser) parser).setReplaceUnderscores(true);
+          ((NHXParser) parser).setGuessRootedness(true);
+          break;
+        case NH_EXTRACT_TAXONOMY:
+          parser = new NHXParser();
+          ((NHXParser) parser).setTaxonomyExtraction(
+                  NHXParser.TAXONOMY_EXTRACTION.AGGRESSIVE);
+          ((NHXParser) parser).setReplaceUnderscores(false);
+          ((NHXParser) parser).setGuessRootedness(true);
+          break;
+        case PFAM:
+          parser = new NHXParser();
+          ((NHXParser) parser).setTaxonomyExtraction(
+                  NHXParser.TAXONOMY_EXTRACTION.PFAM_STYLE_STRICT);
+          ((NHXParser) parser).setReplaceUnderscores(false);
+          ((NHXParser) parser).setGuessRootedness(true);
+          break;
+        case NHX:
+          parser = new NHXParser();
+          ((NHXParser) parser)
+                  .setTaxonomyExtraction(NHXParser.TAXONOMY_EXTRACTION.NO);
+          ((NHXParser) parser).setReplaceUnderscores(false);
+          ((NHXParser) parser).setGuessRootedness(true);
+          break;
+        case PHYLOXML:
+          parser = PhyloXmlParser.createPhyloXmlParserXsdValidating();
+          break;
+        default:
+          throw new IllegalArgumentException(
+                  "unknown format: " + treeDbClient.getReturnFormat());
+        }
+        //
+        // if (_main_frame.getMainPanel().getCurrentTreePanel() != null)
+        // {
+        // _main_frame.getMainPanel().getCurrentTreePanel().setWaitCursor();
+        // }
+        // else
+        // {
+        // _main_frame.getMainPanel().setWaitCursor();
+        // }
+        trees = ForesterUtil.readPhylogeniesFromUrl(url, parser);
+        aptxFrames = new TreeFrameI[trees.length];
+      } catch (final MalformedURLException e)
+      {
+        exception = true;
+        JvOptionPane.showInternalMessageDialog(Desktop.desktop,
+                MessageManager.formatMessage(
+                        "exception.unable_to_launch_url", new String[]
+                        { url.toString() }),
+                MessageManager.getString("label.invalid_url"),
+                JvOptionPane.ERROR_MESSAGE);
+        System.err.println(e.getLocalizedMessage());
+      } catch (final IOException e)
+      {
+        exception = true;
+        JvOptionPane.showInternalMessageDialog(Desktop.desktop,
+                "Could not read from " + url + "\n"
+                        + e.getLocalizedMessage(),
+                "Failed to read tree from " + treeDbClient.getName() + " for "
+                        + identifier,
+                JvOptionPane.ERROR_MESSAGE);
+        System.err.println(e.getLocalizedMessage());
+      } catch (final NumberFormatException e)
+      {
+        exception = true;
+        JvOptionPane.showInternalMessageDialog(Desktop.desktop,
+                "Could not read from " + url + "\n"
+                        + e.getLocalizedMessage(),
+                "Failed to read tree from " + treeDbClient.getName() + " for "
+                        + identifier,
+                JvOptionPane.ERROR_MESSAGE);
+        System.err.println(e.getLocalizedMessage());
+      } catch (final Exception e)
+      {
+        exception = true;
+        e.printStackTrace();
+        JvOptionPane.showInternalMessageDialog(Desktop.desktop,
+                e.getLocalizedMessage(), "Unexpected Exception",
+                JvOptionPane.ERROR_MESSAGE);
+        System.err.println(e.getLocalizedMessage());
+      }
+      if ((trees != null) && (trees.length > 0))
+      {
+        int i = 0;
+        for (final Phylogeny aptxTree : trees)
+        {
+          if (!aptxTree.isEmpty())
+          {
+            if (treeDbClient.getName().equals(WebserviceUtil.TREE_FAM_NAME))
+            {
+              aptxTree.setRerootable(false);
+              aptxTree.setRooted(true);
+            }
+            if (treeDbClient.getProcessingInstructions() != null)
+            {
+              try
+              {
+                WebserviceUtil.processInstructions(treeDbClient,
+                        aptxTree);
+              } catch (final PhyloXmlDataFormatException e)
+              {
+                JvOptionPane.showInternalMessageDialog(Desktop.desktop,
+                        "Error:\n" + e.getLocalizedMessage(), "Error",
+                        JvOptionPane.ERROR_MESSAGE);
+              }
+            }
+            if (treeDbClient.getNodeField() != null)
+            {
+              try
+              {
+                PhylogenyMethods.transferNodeNameToField(aptxTree,
+                        treeDbClient.getNodeField(), false);
+              } catch (final PhyloXmlDataFormatException e)
+              {
+                JvOptionPane.showInternalMessageDialog(Desktop.desktop,
+                        "Error:\n" + e.getLocalizedMessage(), "Error",
+                        JvOptionPane.ERROR_MESSAGE);
+              }
+            }
+            aptxTree.setIdentifier(
+                    new Identifier(identifier, treeDbClient.getName()));
+            // _main_frame.getJMenuBar().remove(_main_frame.getHelpMenu());
+            // _main_frame.getMenuBarOfExternalTreeFrameI()
+            // .add(_main_frame.getHelpMenu());
+            // _main_frame.getMainPanel().addExternalTreeIInNewTab(ExternalTreeI,
+            // _main_frame.getConfiguration(),
+            // new File(url.getFile()).getName(), url.toString());
+
+
+            TreeFrameI aptxApp = createAptxFrame(aptxTree,
+                    viewport,
+                    url.getFile());
+            String my_name_for_file = "";
+            if (!ForesterUtil.isEmpty(aptxTree.getName()))
+            {
+              my_name_for_file = new String(aptxTree.getName())
+                      .replaceAll(" ", "_");
+            }
+            else if (aptxTree.getIdentifier() != null)
+            {
+              final StringBuffer sb = new StringBuffer();
+              if (!ForesterUtil
+                      .isEmpty(aptxTree.getIdentifier().getProvider()))
+              {
+                sb.append(aptxTree.getIdentifier().getProvider());
+                sb.append("_");
+              }
+              sb.append(aptxTree.getIdentifier().getValue());
+              my_name_for_file = new String(
+                      sb.toString().replaceAll(" ", "_"));
+            }
+            aptxApp.getTreePanel()
+                    .setTreeFile(new File(my_name_for_file));
+            // AptxUtil.lookAtSomeTreePropertiesForAptxControlSettings(
+            // aptxTree, aptxApp.getMainPanel().getControlPanel(),
+            // APTX_CONFIG);
+            aptxApp.getTreeControls().displayEntireTree();
+
+            aptxApp.enableMultipleTrees();
+            aptxFrames[i++] = aptxApp;
+          }
+        }
+      }
+      else if (!exception) // ..what?
+      {
+        JvOptionPane.showMessageDialog(null,
+                ForesterUtil.wordWrap(
+                        "Failed to read in tree(s) from [" + url + "]", 80),
+                "Error", JvOptionPane.ERROR_MESSAGE);
+      }
+      if ((trees != null) && (trees.length > 0))
+      {
+        try
+        {
+          JvOptionPane.showMessageDialog(null,
+                  ForesterUtil.wordWrap("Successfully read in "
+                          + trees.length + " tree(s) from [" + url + "]",
+                          80),
+                  "Success", JvOptionPane.INFORMATION_MESSAGE);
+        } catch (final Exception e)
+        {
+          // Not important if this fails, do nothing.
+        }
+      }
+    }
+
+
+    if (Desktop.instance != null)
+    {
+      Desktop.instance.stopLoading();
+    }
+    return aptxFrames;
 
 
-  public static MainFrame createAptxFrame(
-          final Phylogeny[] aptxTrees)
-  {
-    MainFrame aptxApp = Archaeopteryx.createApplication(aptxTrees,
-            APTX_CONFIG, null);
-    return aptxApp;
   }
 
 
-  public static ExternalTreeViewerBindingI<?> bindNodesToJalviewSequences(
-          final MainFrame aptxApp,
-          final AlignmentViewport jalviewAlignViewport,
-          final Map<SequenceI, PhylogenyNode> alignMappedToNodes,
-          final Map<PhylogenyNode, SequenceI> nodesMappedToAlign)
+
+  public static TreeFrameI createAptxFrame(TreeI aptxTree,
+          AlignmentViewport jalviewAlignport, String treeTitle)
   {
-    return new JalviewBinding(aptxApp, jalviewAlignViewport,
-            alignMappedToNodes, nodesMappedToAlign);
+    validateConfig(APTX_CONFIG);
+    TreeFrameI aptxApp = aptxTree
+            .createTreeViewerFromTree(treeTitle);
+    TreeI jalviewTree = aptxApp.getTree();
+    LoadedTreeAssociationI bindAptxNodes = new LoadedTreeSequenceAssociation(
+            jalviewAlignport.getAlignment().getSequencesArray(),
+            jalviewTree);
+    bindAptxNodes.associateNodesToSequences();
+
+    TreeViewerUtils.associateNodesWithJalviewSequences(aptxApp, jalviewAlignport,
+            bindAptxNodes.getAlignmentWithNodes(),
+            bindAptxNodes.getNodesWithAlignment());
+    TreeViewerUtils.addTreeViewFrameToJalview(aptxApp, 400, 500);
+
+    // adaptAptxGui(aptxApp); //moved to AptxFrame
+    return aptxApp;
   }
 
 
-  public static MainFrame bindFrameToJalview(final MainFrame aptxApp)
+  protected static TreeFrameI createAptxFrame(
+          final Phylogeny aptxTree,
+          final AlignmentViewport jalviewAlignport, String treeTitle)
   {
-    int width = 400;
-    int height = 550;
-    aptxApp.setMinimumSize(new Dimension(width, height));
-    // aptxApp.setFont(Desktop.instance.getFont());
-    // aptxApp.getMainPanel().setFont(Desktop.instance.getFont());
+    validateConfig(APTX_CONFIG);
+    TreeFrameI aptxApp = new AptxFrame(aptxTree, APTX_CONFIG,
+            treeTitle);
+    TreeI jalviewTree = aptxApp.getTree();
+    LoadedTreeAssociationI bindAptxNodes = new LoadedTreeSequenceAssociation(
+            jalviewAlignport.getAlignment().getSequencesArray(),
+            jalviewTree);
+    bindAptxNodes.associateNodesToSequences();
 
-    Desktop.addInternalFrame(aptxApp, "Archaeopteryx Tree View", true,
-            width, height, true, true);
+    TreeViewerUtils.associateNodesWithJalviewSequences(aptxApp, jalviewAlignport,
+            bindAptxNodes.getAlignmentWithNodes(),
+            bindAptxNodes.getNodesWithAlignment());
+    TreeViewerUtils.addTreeViewFrameToJalview(aptxApp, 400, 500);
 
     return aptxApp;
-
   }
 
 
+  private static boolean validateConfig(Configuration aptxConfig)
+  {
+    if (aptxConfig == null || aptxConfig.isCouldReadConfigFile() == false)
+    {
+      int keepGoing = JvOptionPane.showConfirmDialog(Desktop.desktop,
+              MessageManager.getString("label.aptx_config_not_found"),
+              MessageManager.formatMessage("label.couldnt_locate",
+                      new String[]
+                      { "_aptx_jalview_configuration_file" }),
+              JvOptionPane.YES_NO_CANCEL_OPTION);
+
+      if (keepGoing == JvOptionPane.CANCEL_OPTION
+              || keepGoing == JvOptionPane.CLOSED_OPTION
+              || keepGoing == JvOptionPane.NO_OPTION)
+      {
+        return false;
+      }
+
+    }
+    return true;
+  }
+
 
 }
index 74d89d2..1be7da3 100644 (file)
-package jalview.ext.archaeopteryx;
-
-import jalview.analysis.TreeBuilder;
-import jalview.datamodel.SequenceI;
-import jalview.ext.forester.DataConversions;
-import jalview.ext.forester.ForesterMatrix;
-import jalview.ext.treeviewer.ExternalTreeBuilderI;
-import jalview.util.MappingUtils;
-import jalview.util.MessageManager;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import org.forester.evoinference.matrix.distance.DistanceMatrix;
-import org.forester.phylogeny.Phylogeny;
-import org.forester.phylogeny.PhylogenyNode;
-import org.forester.phylogeny.data.NodeData;
-import org.forester.phylogeny.data.Sequence;
-
-/**
- * Class for converting trees made in Jalview (through TreeBuilder) to trees
- * compatible with Forester (Phylogeny objects).
- * 
- * Note that this currently demands a 1:1 relationship between tree nodes and
- * the sequences used for generating them.
- * 
- * @author kjvanderheide
- *
- */
-public class AptxTreeBuilder
-        implements ExternalTreeBuilderI<Phylogeny, PhylogenyNode>
-{
-  protected final SequenceI[] sequences;
-
-  protected final DistanceMatrix distances;
-  
-  protected final TreeBuilder jalviewTree;
-  
-  public String treeTitle;
-
-  private final Phylogeny aptxTree;
-
-  private PhylogenyNode rootNode;
-
-  private final Map<SequenceI, PhylogenyNode> alignmentWithNodes;
-
-  private final Map<PhylogenyNode, SequenceI> nodesWithAlignment;
-
-  public AptxTreeBuilder(final TreeBuilder calculatedTree)
-  {
-    jalviewTree = calculatedTree;
-    sequences = jalviewTree.getSequences();
-    distances = ForesterMatrix.convertJalviewToForester(
-            jalviewTree.getDistances(), sequences);
-
-    aptxTree = new Phylogeny();
-    rootNode = new PhylogenyNode();
-
-    int amountOfSequences = distances.getSize();
-    alignmentWithNodes = new HashMap<>(amountOfSequences);
-    nodesWithAlignment = new HashMap<>(amountOfSequences);
-
-
-  }
-
-  @Override
-  public Phylogeny buildTree(final PhylogenyNode treeRoot)
-  {
-
-    if (treeRoot != null)
-    {
-      rootNode = treeRoot;
-    }
-
-    buildTree();
-
-    return aptxTree;
-
-  }
-
-
-  @Override
-  public Phylogeny buildTree()
-  {
-
-    for (SequenceI sequence : sequences)
-    {
-      Sequence seq = DataConversions
-              .createForesterSequence(sequence, true);
-      PhylogenyNode sequenceNode = new PhylogenyNode(sequence.getName());
-
-      NodeData nodeData = sequenceNode.getNodeData();
-      nodeData.setSequence(seq);
-
-      MappingUtils.putWithDuplicationCheck(nodesWithAlignment,
-              sequenceNode, sequence);
-      MappingUtils.putWithDuplicationCheck(alignmentWithNodes,
-              sequence, sequenceNode);
-      rootNode.addAsChild(sequenceNode);
-    }
-
-
-    aptxTree.setRoot(rootNode);
-
-    treeTitle = generateTreeName();
-    aptxTree.setName(treeTitle);
-
-    return aptxTree;
-
-  }
-
-  @Override
-  public Map<SequenceI, PhylogenyNode> getAlignmentBoundNodes()
-  {
-    return alignmentWithNodes;
-  }
-
-  @Override
-  public Map<PhylogenyNode, SequenceI> getNodesBoundAlignment()
-  {
-    return nodesWithAlignment;
-  }
-
-  private Phylogeny clusterNodes()
-  {
-    return aptxTree;
-
-  }
-  /**
-   * Formats a localised title for the tree panel, like
-   * <p>
-   * Neighbour Joining Using BLOSUM62
-   * <p>
-   * For a tree loaded from file, just uses the file name
-   * 
-   * @return
-   */
-  @Override
-  public String generateTreeName() // Move this and add selection region to the
-                                   // title when applicable
-  {
-    if (treeTitle != null) // will currently never happen, loaded tree file will
-                           // take a different path
-    {
-      return treeTitle;
-    }
-    else
-    {
-      /*
-      * i18n description of Neighbour Joining or Average Distance method
-      */
-      String treecalcnm = MessageManager
-              .getString("label.tree_calc_" + jalviewTree.getClass()
-                      .getSimpleName().substring(0, 2).toLowerCase());
-      /*
-      * short score model name (long description can be too long)
-      */
-      String smn = jalviewTree.getScoreModel().getName();
-
-      /*
-      * put them together as <method> Using <model>
-      */
-      final String ttl = MessageManager
-              .formatMessage("label.treecalc_title", treecalcnm, smn);
-      return ttl;
-    }
-  }
-  
-
-}
+// package jalview.ext.archaeopteryx;
+//
+// import jalview.analysis.TreeBuilder;
+// import jalview.datamodel.SequenceI;
+// import jalview.ext.forester.ForesterMatrix;
+// import jalview.ext.treeviewer.TreeBuilderI;
+// import jalview.ext.treeviewer.TreeI;
+// import jalview.ext.treeviewer.TreeNodeI;
+// import jalview.util.MappingUtils;
+// import jalview.util.MessageManager;
+//
+// import java.util.HashMap;
+// import java.util.Map;
+//
+// import org.forester.evoinference.matrix.distance.DistanceMatrix;
+// import org.forester.phylogeny.Phylogeny;
+// import org.forester.phylogeny.PhylogenyNode;
+//
+/// **
+// * Class for converting trees made in Jalview (through TreeBuilder) to trees
+// * compatible with Forester (Phylogeny objects).
+// *
+// * Note that this currently demands a 1:1 relationship between tree nodes and
+// * the sequences used for generating them.
+// *
+// * @author kjvanderheide
+// *
+// */
+// public class AptxTreeBuilder
+// implements TreeBuilderI
+// {
+// protected final SequenceI[] sequences;
+//
+// protected final DistanceMatrix distances;
+//
+// protected final TreeBuilder jalviewTree;
+//
+// public String treeTitle;
+//
+// private final TreeI aptxTree;
+//
+// private TreeNodeI rootNode;
+//
+// private final Map<SequenceI, TreeNodeI> alignmentWithNodes;
+//
+// private final Map<TreeNodeI, SequenceI> nodesWithAlignment;
+//
+// public AptxTreeBuilder(final TreeBuilder calculatedTree)
+// {
+// jalviewTree = calculatedTree;
+// sequences = jalviewTree.getSequences();
+// distances = ForesterMatrix.convertJalviewToForester(
+// jalviewTree.getDistances(), sequences);
+//
+// aptxTree = new Tree(new Phylogeny());
+// rootNode = TreeNode.getUniqueWrapper(new PhylogenyNode());
+//
+// int amountOfSequences = distances.getSize();
+// alignmentWithNodes = new HashMap<>(amountOfSequences);
+// nodesWithAlignment = new HashMap<>(amountOfSequences);
+//
+//
+// }
+//
+// @Override
+// public TreeI buildTree(final TreeNodeI treeRoot)
+// {
+//
+// if (treeRoot != null)
+// {
+// rootNode = treeRoot;
+// }
+//
+// buildTree();
+//
+// return aptxTree;
+//
+// }
+//
+//
+// @Override
+// public TreeI buildTree()
+// {
+//
+// for (SequenceI sequence : sequences)
+// {
+//
+// TreeNodeI sequenceNode = TreeNode
+// .getUniqueWrapper(
+// new PhylogenyNode(sequence.getName()));
+//
+// sequenceNode.setSequence(sequence);
+//
+// MappingUtils.putWithDuplicationCheck(nodesWithAlignment,
+// sequenceNode, sequence);
+// MappingUtils.putWithDuplicationCheck(alignmentWithNodes,
+// sequence, sequenceNode);
+// rootNode.addAsChild(sequenceNode);
+// }
+//
+//
+// aptxTree.setRoot(rootNode);
+//
+// treeTitle = generateTreeName();
+// aptxTree.setTreeName(treeTitle);
+//
+// return aptxTree;
+//
+// }
+//
+// @Override
+// public Map<SequenceI, TreeNodeI> getAlignmentBoundNodes()
+// {
+// return alignmentWithNodes;
+// }
+//
+// @Override
+// public Map<TreeNodeI, SequenceI> getNodesBoundAlignment()
+// {
+// return nodesWithAlignment;
+// }
+//
+//
+// /**
+// * Formats a localised title for the tree panel, like
+// * <p>
+// * Neighbour Joining Using BLOSUM62
+// * <p>
+// * For a tree loaded from file, just uses the file name
+// *
+// * @return
+// */
+// @Override
+// public String generateTreeName() // Move this and add selection region to the
+// // title when applicable
+// {
+// if (treeTitle != null) // will currently never happen, loaded tree file will
+// // take a different path
+// {
+// return treeTitle;
+// }
+// else
+// {
+// /*
+// * i18n description of Neighbour Joining or Average Distance method
+// */
+// String treecalcnm = MessageManager
+// .getString("label.tree_calc_" + jalviewTree.getClass()
+// .getSimpleName().substring(0, 2).toLowerCase());
+// /*
+// * short score model name (long description can be too long)
+// */
+// String smn = jalviewTree.getScoreModel().getName();
+//
+// /*
+// * put them together as <method> Using <model>
+// */
+// final String ttl = MessageManager
+// .formatMessage("label.treecalc_title", treecalcnm, smn);
+// return ttl;
+// }
+// }
+//
+//
+//
+//
+// }
index 631ff15..05c5cab 100644 (file)
 package jalview.ext.archaeopteryx;
 
-import jalview.ext.treeviewer.ExternalTreePanelI;
+import jalview.ext.treeviewer.TreeI;
+import jalview.ext.treeviewer.TreeNodeI;
+import jalview.ext.treeviewer.TreePanelI;
+import jalview.gui.PaintRefresher;
 
-public class AptxTreePanel implements ExternalTreePanelI
+import java.awt.Dimension;
+import java.awt.Event;
+import java.awt.Font;
+import java.awt.Graphics2D;
+import java.awt.MenuComponent;
+import java.awt.Rectangle;
+import java.awt.event.MouseListener;
+import java.io.File;
+import java.util.Set;
+
+import javax.accessibility.AccessibleContext;
+
+public class AptxTreePanel implements TreePanelI
 {
   private final org.forester.archaeopteryx.TreePanel treeView;
 
-  public AptxTreePanel(org.forester.archaeopteryx.TreePanel aptxTreePanel)
+  private final TreeI tree;
+
+  private String sequenceSetId;
+
+  protected AptxTreePanel(
+          org.forester.archaeopteryx.TreePanel aptxTreePanel)
   {
     treeView = aptxTreePanel;
+    tree = new Tree(treeView.getPhylogeny());
+  }
+
+  protected AptxTreePanel(
+          org.forester.archaeopteryx.TreePanel aptxTreePanel,
+          TreeI aptxTree)
+  {
+    treeView = aptxTreePanel;
+    tree = aptxTree;
+
+  }
+
+  @Override
+  public void setTreeFile(File file)
+  {
+    treeView.setTreeFile(file);
+  }
+
+  @Override
+  public TreeI getTree()
+  {
+    return tree;
+  }
+
+  @Override
+  public File getTreeFile()
+  {
+    return treeView.getTreeFile();
+  }
+
+  @Override
+  public TreeNodeI findNode(int x, int y)
+  {
+    return TreeNode.getUniqueWrapper(treeView.findNode(x, y));
+  }
+
+  @Override
+  public void setMatchingNodes(Set<Long> hashSet)
+  {
+    treeView.setFoundNodes0(hashSet);
+
+  }
+
+  @Override
+  public Set<Long> getMatchingNodesIds()
+  {
+    return treeView.getFoundNodes0();
+  }
+
+  @Override
+  public AccessibleContext getAccessibleContext()
+  {
+    return treeView.getAccessibleContext();
+  }
+
+  @Override
+  public Font getFont()
+  {
+    return treeView.getFont();
+  }
+
+  @Override
+  public void remove(MenuComponent comp)
+  {
+    treeView.remove(comp);
+
+  }
+
+  @Deprecated
+  @Override
+  public boolean postEvent(Event evt)
+  {
+    return treeView.postEvent(evt);
+  }
+
+  @Override
+  public void addMouseListener(MouseListener listener)
+  {
+    treeView.addMouseListener(listener);
+  }
+
+  @Override
+  public void removeMouseListener(MouseListener listener)
+  {
+    treeView.removeMouseListener(listener);
+
+  }
+
+  @Override
+  public MouseListener[] getMouseListeners()
+  {
+    return treeView.getMouseListeners();
+  }
+
+  @Override
+  public void repaint()
+  {
+    treeView.repaint();
+
+  }
+
+  @Override
+  public void registerWithPaintRefresher(String sequenceSetIdentifier)
+  {
+    sequenceSetId = sequenceSetIdentifier;
+    PaintRefresher.Register(treeView, sequenceSetIdentifier);
+
+  }
+
+  @Override
+  public void notifyPaintRefresher(String sequenceSetIdentifier,
+          boolean alignmentChanged, boolean validateSequences)
+  {
+    PaintRefresher.Refresh(treeView, sequenceSetIdentifier,
+            alignmentChanged, validateSequences);
+
+  }
+
+  @Override
+  public void notifyPaintRefresher(boolean alignmentChanged,
+          boolean validateSequences)
+  {
+    if (sequenceSetId != null)
+    {
+    PaintRefresher.Refresh(treeView, sequenceSetId, alignmentChanged,
+              validateSequences);
+    }
+    else
+    {
+      // throw some kind of exception
+    }
+
+  }
+
+  @Override
+  public int getWidth()
+  {
+    return treeView.getWidth();
+  }
+
+  @Override
+  public int getHeight()
+  {
+    return treeView.getHeight();
+  }
+
+  @Override
+  public void paintToFile(Graphics2D pg, int width, int height)
+  {
+    treeView.paintFile(pg, false, width, height, 0, 0);
+
+  }
+
+  @Override
+  public boolean showingSubTree()
+  {
+    return treeView.isCurrentTreeIsSubtree();
+  }
+
+  @Override
+  public Rectangle getVisibleArea()
+  {
+    return treeView.getVisibleRect();
+  }
+
+  @Override
+  public float getPartitionThreshold()
+  {
+    return treeView.getThreshold();
+  }
+
+  @Override
+  public void setMinimumSize(Dimension minimumSize)
+  {
+    treeView.setMinimumSize(minimumSize);
+
+  }
+
+  @Override
+  public void setMaximumSize(Dimension maximumSize)
+  {
+    treeView.setMaximumSize(maximumSize);
+
+  }
+
+  @Override
+  public void setPreferredSize(Dimension preferredSize)
+  {
+    treeView.setPreferredSize(preferredSize);
+
+  }
+
+  @Override
+  public void addToMatchingNodes(TreeNodeI matchedNode)
+  {
+    treeView.getFoundNodes0().add(matchedNode.getId());
 
   }
 }
diff --git a/src/jalview/ext/archaeopteryx/JalviewBinding.java b/src/jalview/ext/archaeopteryx/JalviewBinding.java
deleted file mode 100644 (file)
index dae01f1..0000000
+++ /dev/null
@@ -1,434 +0,0 @@
-package jalview.ext.archaeopteryx;
-
-import jalview.datamodel.ColumnSelection;
-import jalview.datamodel.HiddenColumns;
-import jalview.datamodel.SequenceGroup;
-import jalview.datamodel.SequenceI;
-import jalview.ext.treeviewer.ExternalTreeViewerBindingI;
-import jalview.gui.PaintRefresher;
-import jalview.structure.SelectionSource;
-import jalview.structure.StructureSelectionManager;
-import jalview.viewmodel.AlignmentViewport;
-
-import java.awt.event.ActionEvent;
-import java.awt.event.InputEvent;
-import java.awt.event.MouseEvent;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import javax.swing.JTabbedPane;
-import javax.swing.SwingUtilities;
-import javax.swing.event.ChangeEvent;
-import javax.swing.event.ChangeListener;
-
-import org.forester.archaeopteryx.MainFrame;
-import org.forester.phylogeny.Phylogeny;
-import org.forester.phylogeny.PhylogenyMethods;
-import org.forester.phylogeny.PhylogenyNode;
-
-/**
- * Class for binding the Archaeopteryx tree viewer to the Jalview alignment that
- * it originates from, meaning that selecting sequences in the tree viewer also
- * selects them in the alignment view and vice versa.
- * 
- * @author kjvanderheide
- *
- */
-public final class JalviewBinding
-        implements ExternalTreeViewerBindingI<PhylogenyNode>
-{
-  private org.forester.archaeopteryx.TreePanel treeView;
-
-  private AlignmentViewport parentAvport;
-
-  private JTabbedPane treeTabs;
-
-  private final StructureSelectionManager ssm;
-
-  private Map<SequenceI, PhylogenyNode> sequencesBoundToNodes;
-
-  private Map<PhylogenyNode, SequenceI> nodesBoundToSequences;
-
-  /**
-   * 
-   * @param archaeopteryx
-   * 
-   * @param jalviewAlignmentViewport
-   *          alignment viewport from which the tree was calculated.
-   * 
-   * @param alignMappedToNodes
-   *          map with sequences used to calculate the tree and matching tree
-   *          nodes as key, value pair respectively.
-   * 
-   * @param nodesMappedToAlign
-   *          map with tree nodes and matching sequences used to calculate the
-   *          tree as key, value pair respectively.
-   */
-  public JalviewBinding(final MainFrame archaeopteryx,
-          final AlignmentViewport jalviewAlignmentViewport,
-          final Map<SequenceI, PhylogenyNode> alignMappedToNodes,
-          final Map<PhylogenyNode, SequenceI> nodesMappedToAlign)
-  {
-    // deal with/prohibit null values here as that will cause problems
-    parentAvport = jalviewAlignmentViewport;
-    sequencesBoundToNodes = alignMappedToNodes;
-    nodesBoundToSequences = nodesMappedToAlign;
-
-    treeView = archaeopteryx.getMainPanel().getCurrentTreePanel();
-    treeTabs = archaeopteryx.getMainPanel().getTabbedPane();
-    ssm = parentAvport.getStructureSelectionManager();
-
-    // archaeopteryx.getMainPanel().getControlPanel().setColorBranches(true);
-    
-    ssm.addSelectionListener(this);
-    treeView.addMouseListener(this);
-    PaintRefresher.Register(treeView, parentAvport.getSequenceSetId());
-
-
-    treeTabs.addChangeListener(new ChangeListener()
-    {
-
-      @Override
-      public void stateChanged(ChangeEvent e)
-      {
-
-        SwingUtilities.invokeLater(new Runnable()
-        {
-
-          @Override
-          /**
-           * Resend the selection to the tree view when tabs get switched, this
-           * has to be buried in invokeLater as Forester first resets the tree
-           * view on switching tabs, without invokeLater this would get called
-           * before Forester resets which would nullify the selection.
-           */
-          public void run()
-          {
-            parentAvport.sendSelection();
-            // PaintRefresher.Refresh(treeView,
-            // parentAvport.getSequenceSetId());
-
-          }
-        });
-
-      }
-      
-    });
-
-  }
-
-  @Override
-  public void actionPerformed(ActionEvent e)
-  {
-  }
-
-  @Override
-  public void mouseClicked(MouseEvent e)
-  {
-    SwingUtilities.invokeLater(new Runnable() {
-
-      @Override
-      /**
-       * invokeLater so that this always runs after Forester's mouseClicked
-       */
-      public void run()
-      {
-        final PhylogenyNode node = treeView.findNode(e.getX(), e.getY());
-        if (node != null)
-        {
-          if ((e.getModifiers() & InputEvent.SHIFT_MASK) == 0) // clear previous
-          // selection if shift
-          // IS NOT pressed
-          {
-            parentAvport.setSelectionGroup(null);
-
-          }
-          showNodeSelectionOnAlign(node);
-        }
-        else
-        {
-          partitionTree(e);
-        
-        
-      }
-      
-      }
-    });
-
-
-  }
-
-  @Override
-  public void mousePressed(final MouseEvent e)
-  {
-
-  }
-  @Override
-  public void mouseReleased(MouseEvent e)
-  {
-  }
-
-  @Override
-  public void mouseEntered(MouseEvent e)
-  {
-  }
-
-  @Override
-  public void mouseExited(MouseEvent e)
-  {
-  }
-
-
-  @Override
-  public void selection(final SequenceGroup seqsel,
-          final ColumnSelection colsel, final HiddenColumns hidden,
-          final SelectionSource source)
-  {
-    if (source == parentAvport) // check if source is alignment from where the
-    // tree originates
-    {
-      treeView.setFoundNodes0(
-              new HashSet<Long>(seqsel.getSequences().size()));
-
-      for (SequenceI selectedSequence : seqsel.getSequences())
-      {
-        PhylogenyNode matchingNode = sequencesBoundToNodes.get(selectedSequence);
-        if (matchingNode != null)
-        {
-          treeView.getFoundNodes0().add(matchingNode.getId());
-        }
-
-      }
-      treeView.repaint();
-
-    }
-
-
-  }
-
-  /**
-   * Partially refactored from TreeCanvas
-   */
-  public void partitionTree(final MouseEvent e)
-  {
-    int x = e.getX();
-    int lineLength = treeView.getHeight();
-
-    Phylogeny tree = treeView.getPhylogeny();
-    double treeHeight = tree.calculateHeight(true);
-
-
-
-    if (treeHeight != 0)
-    {
-      int viewWidth = treeView.getWidth();
-
-      // treeView.validate();
-
-      // System.out.println("selection");
-      // System.out.println(x);
-      // System.out.println("-------------");
-      // System.out.println("width");
-      // System.out.println(viewWidth);
-
-    }
-
-
-  }
-  
-
-
-  @Override
-  public void showNodeSelectionOnAlign(final PhylogenyNode node)
-  {
-
-      if (node.isInternal())
-      {
-        showMatchingChildSequences(node);
-      }
-
-      else
-      {
-        showMatchingSequence(node);
-      }
-
-    }
-
-
-
-
-
-  @Override
-  public void showMatchingSequence(final PhylogenyNode nodeToMatch)
-  {
-    SequenceI matchingSequence = nodesBoundToSequences.get(nodeToMatch);
-    if (matchingSequence != null)
-    {
-      long nodeId = nodeToMatch.getId();
-      addOrRemoveInSet(treeView.getFoundNodes0(), nodeId);
-      treeSelectionChanged(matchingSequence);
-      parentAvport.sendSelection();
-
-    }
-  }
-
-  @Override
-  public void showMatchingChildSequences(final PhylogenyNode parentNode)
-  {
-    List<PhylogenyNode> childNodes = PhylogenyMethods
-            .getAllDescendants(parentNode);
-
-
-    for (PhylogenyNode childNode : childNodes)
-    {
-      // childNode.getBranchData().setBranchColor(new BranchColor(Color.BLUE));
-
-      SequenceI matchingSequence = nodesBoundToSequences.get(childNode);
-      if (matchingSequence != null)
-      {
-        long nodeId = childNode.getId();
-        addOrRemoveInSet(treeView.getFoundNodes0(), nodeId);
-
-        treeSelectionChanged(matchingSequence);
-
-      }
-
-    }
-    parentAvport.sendSelection();
-
-
-  }
-
-  /**
-   * Refactored from TreeCanvas.
-   * 
-   * @param sequence
-   *          of the node selected in the tree viewer.
-   */
-  @Override
-  public void treeSelectionChanged(final SequenceI sequence)
-  {
-    if (!parentAvport.isClosed()) // alignment view could be closed
-    {
-      SequenceGroup selected = parentAvport.getSelectionGroup();
-
-      if (selected == null)
-      {
-        selected = new SequenceGroup();
-        parentAvport.setSelectionGroup(selected);
-      }
-
-      selected.setEndRes(parentAvport.getAlignment().getWidth() - 1);
-        selected.addOrRemove(sequence, true);
-    }
-
-  }
-  public void sortByTree_actionPerformed() {
-    // parentAvport.mirrorCommand(command, undo, ssm, source);
-
-    // alignFrame
-    // .addHistoryItem(sortAlignmentIn(treeCanvas.ap));
-    
-  }
-  
-
-  /**
-   * sort the associated alignment view by the current tree.
-   * 
-   * @param e
-   */
-  // @Override
-  // public void sortByTree_actionPerformed()// modify for Aptx
-  // {
-  //
-  // // if (treeCanvas.applyToAllViews)
-  //
-  // final ArrayList<CommandI> commands = new ArrayList<>();
-  // for (AlignmentPanel ap : PaintRefresher
-  // .getAssociatedPanels(parentAvport.getSequenceSetId()))
-  // {
-  // commands.add(sortAlignmentIn(ap.av.getAlignPanel()));
-  // }
-  // av.getAlignPanel().alignFrame.addHistoryItem(new CommandI()
-  // {
-  //
-  // @Override
-  // public void undoCommand(AlignmentI[] views)
-  // {
-  // for (CommandI tsort : commands)
-  // {
-  // tsort.undoCommand(views);
-  // }
-  // }
-  //
-  // @Override
-  // public int getSize()
-  // {
-  // return commands.size();
-  // }
-  //
-  // @Override
-  // public String getDescription()
-  // {
-  // return "Tree Sort (many views)";
-  // }
-  //
-  // @Override
-  // public void doCommand(AlignmentI[] views)
-  // {
-  //
-  // for (CommandI tsort : commands)
-  // {
-  // tsort.doCommand(views);
-  // }
-  // }
-  // });
-  // for (AlignmentPanel ap : PaintRefresher
-  // .getAssociatedPanels(av.getSequenceSetId()))
-  // {
-  // // ensure all the alignFrames refresh their GI after adding an undo item
-  // ap.alignFrame.updateEditMenuBar();
-  // }
-  // }
-  // else
-  // {
-  // treeCanvas.ap.alignFrame
-  // .addHistoryItem(sortAlignmentIn(treeCanvas.ap));
-  // }
-
-
-
-  /**
-   * TO BE MOVED
-   * 
-   * @param set
-   * @param objectToCheck
-   */
-  public static <E> void addOrRemoveInSet(Set<E> set, E objectToCheck)
-  {
-    if (set.contains(objectToCheck))
-    {
-      set.remove(objectToCheck);
-    }
-    else
-    {
-      set.add(objectToCheck);
-    }
-
-  }
-
-  public AlignmentViewport getParentAvport()
-  {
-    return parentAvport;
-  }
-
-  public void setParentAvport(final AlignmentViewport parentAvport)
-  {
-    this.parentAvport = parentAvport;
-  }
-}
-
-
-
diff --git a/src/jalview/ext/archaeopteryx/LoadedTreeAssociation.java b/src/jalview/ext/archaeopteryx/LoadedTreeAssociation.java
deleted file mode 100644 (file)
index c869cd5..0000000
+++ /dev/null
@@ -1,163 +0,0 @@
-package jalview.ext.archaeopteryx;
-
-import jalview.analysis.SequenceIdMatcher;
-import jalview.datamodel.SequenceI;
-import jalview.ext.forester.DataConversions;
-import jalview.ext.treeviewer.ExternalLoadedTreeAssociationI;
-import jalview.util.MappingUtils;
-
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.forester.phylogeny.Phylogeny;
-import org.forester.phylogeny.PhylogenyNode;
-
-public class LoadedTreeAssociation
-        implements ExternalLoadedTreeAssociationI
-{
-  SequenceI[] alignSequences;
-
-  Phylogeny tree;
-
-  Map<SequenceI, PhylogenyNode> alignmentWithNodes;
-
-  Map<PhylogenyNode, SequenceI> nodesWithAlignment;
-
-  public LoadedTreeAssociation(SequenceI[] alignmentSequences,
-          Phylogeny aptxTree)
-  {
-    alignSequences = alignmentSequences;
-    tree = aptxTree;
-    alignmentWithNodes = new HashMap<>(alignSequences.length);
-    nodesWithAlignment = new HashMap<>(alignSequences.length);
-
-  }
-
-
-
-  /**
-   * Tries to match sequences from Jalview with tree nodes in Archaeopteryx and
-   * fills in the tree node with sequence data if a match is found.
-   * 
-   * Partially refactored from the old Jalview TreeModel
-   * associateLeavesToSequences method.
-   *
-   * @param seqs
-   * @param aptxTree
-   */
-  @Override
-  public void associateLeavesToSequences()
-
-  {
-    SequenceIdMatcher algnIds = new SequenceIdMatcher(alignSequences);
-
-    List<PhylogenyNode> leaves = tree.getExternalNodes();
-    SequenceI nodeSequence;
-    String nodeSequenceName;
-
-    for (PhylogenyNode treeNode : leaves)
-    {
-      nodeSequenceName = treeNode.getName();
-
-      nodeSequence = algnIds.findIdMatch(nodeSequenceName);
-      if (nodeSequence != null)
-      {
-        org.forester.phylogeny.data.Sequence foresterNodeSeq = DataConversions
-                .createForesterSequence(nodeSequence, true);
-        treeNode.getNodeData().setSequence(foresterNodeSeq);
-
-        MappingUtils.putWithDuplicationCheck(alignmentWithNodes,
-                nodeSequence, treeNode);
-        MappingUtils.putWithDuplicationCheck(nodesWithAlignment,
-                treeNode, nodeSequence);
-
-
-      }
-
-    }
-
-  }
-
-
-
-  public Map<SequenceI, PhylogenyNode> getAlignmentWithNodes()
-  {
-    return alignmentWithNodes;
-  }
-
-  public Map<PhylogenyNode, SequenceI> getNodesWithAlignment()
-  {
-    return nodesWithAlignment;
-  }
-
-  // {
-  // SequenceIdMatcher algnIds = new SequenceIdMatcher(seqs);
-  //
-  // List<PhylogenyNode> leaves = aptxTree.getExternalNodes();
-  //
-  // int namesleft = seqs.length;
-  // SequenceI nodeSequence;
-  // String nodeSequenceName;
-  // List<SequenceI> one2many = new ArrayList<>();
-  // int countOne2Many = 0;
-  //
-  // for (PhylogenyNode treeNode : leaves)
-  // {
-  // nodeSequenceName = treeNode.getName();
-  // nodeSequence = null;
-  //
-  // if (namesleft > -1)
-  // {
-  // nodeSequence = algnIds.findIdMatch(nodeSequenceName);
-  // }
-  //
-  // if (nodeSequence != null)
-  // {
-  // org.forester.phylogeny.data.Sequence foresterNodeSeq =
-  // ForesterDataConversions.createForesterSequence(nodeSequence, true);
-  //
-  // treeNode.getNodeData().setSequence(foresterNodeSeq);
-  // if (one2many.contains(nodeSequence))
-  // {
-  // countOne2Many++;
-  // if (jalview.bin.Cache.log.isDebugEnabled())
-  // {
-  // jalview.bin.Cache.log.debug("One 2 many relationship for"
-  // +nodeSequence.getName());
-  // }
-  // }
-  // else
-  // {
-  // one2many.add(nodeSequence);
-  // namesleft--;
-  // }
-  // }
-  // else
-  // {
-  // treeNode.setCollapse(true); // collapse nodes that couldn't be connected
-  // // to a sequence
-  //
-  //
-  // // treeNode.setElement( new Sequence(nodeSequenceName,
-  // "THISISAPLACEHOLDER"));
-  // // treeNode.setPlaceholder(true);
-  // }
-  // }
-  // if (jalview.bin.Cache.log.isDebugEnabled() && countOne2Many > 0)
-  // {
-  // jalview.bin.Cache.log.debug("There were " + countOne2Many
-  // + "alignment sequence ids (out of" + one2many.size()
-  // + " unique ids) linked to two or more leaves.");
-  // }
-  // one2many.clear();
-  //
-  // }
-
-}
-
-
-
-
-
-
index 884a359..616ea4b 100644 (file)
@@ -1,30 +1,55 @@
 package jalview.ext.archaeopteryx;
 
-import jalview.ext.treeviewer.ExternalTreeI;
-import jalview.ext.treeviewer.ExternalTreeNodeI;
+import jalview.datamodel.SequenceI;
+import jalview.ext.treeviewer.TreeFrameI;
+import jalview.ext.treeviewer.TreeI;
+import jalview.ext.treeviewer.TreeNodeI;
 
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.forester.archaeopteryx.Archaeopteryx;
+import org.forester.io.writers.PhylogenyWriter;
 import org.forester.phylogeny.Phylogeny;
+import org.forester.phylogeny.PhylogenyMethods;
+import org.forester.phylogeny.PhylogenyNode;
 
-public class Tree implements ExternalTreeI
+public class Tree implements TreeI
 {
   private final Phylogeny tree;
 
+
+  public Tree()
+  {
+    tree = new Phylogeny();
+  }
+
   public Tree(Phylogeny aptxTree)
   {
     tree = aptxTree;
+    wrapAllTreeNodes();
+
   }
 
-  @Override
-  public Phylogeny getOriginalTree()
+  private void wrapAllTreeNodes()
   {
-    return tree;
+    for (Iterator<PhylogenyNode> iterator = tree
+            .iteratorPostorder(); iterator.hasNext();)
+    {
+      PhylogenyNode foresterNode = iterator.next();
+      TreeNodeI treeNode = TreeNode
+              .getUniqueWrapper(foresterNode);
 
+    }
   }
 
   @Override
-  public ExternalTreeNodeI getRoot()
+  public TreeNodeI getRoot()
   {
-    ExternalTreeNodeI root = new TreeNode(tree.getRoot());
+    TreeNodeI root = TreeNode.getUniqueWrapper(tree.getRoot());
     return root;
   }
 
@@ -36,9 +61,9 @@ public class Tree implements ExternalTreeI
   }
 
   @Override
-  public ExternalTreeNodeI getNodeWithName(String name)
+  public TreeNodeI getNodeWithName(String name)
   {
-    return new TreeNode(tree.getNode(name));
+    return TreeNode.getUniqueWrapper(tree.getNode(name));
 
   }
 
@@ -47,4 +72,125 @@ public class Tree implements ExternalTreeI
   {
     return tree.getAllExternalNodeNames();
   }
+
+  @Override
+  public void setRerootable(boolean b)
+  {
+    tree.setRerootable(b);
+
+  }
+
+  @Override
+  public void setRooted(boolean b)
+  {
+    tree.setRooted(b);
+
+  }
+
+  @Override
+  public boolean isEmpty()
+  {
+    return tree.isEmpty();
+  }
+
+  @Override
+  public String getTreeName()
+  {
+    return tree.getName();
+  }
+
+  @Override
+  public void setRoot(TreeNodeI rootNode)
+  {
+    PhylogenyNode treeRoot = TreeNode.unwrapNode(rootNode);
+    tree.setRoot(treeRoot);
+    wrapAllTreeNodes();
+
+  }
+
+  @Override
+  public double getMaximumLength(boolean adjustForCollapsedSubtrees)
+  {
+    return tree.calculateHeight(adjustForCollapsedSubtrees);
+  }
+
+  @Override
+  public Iterator<TreeNodeI> iterateInPreOrder()
+  {
+    Iterator<TreeNodeI> iter = new TreeIterator(
+            tree.iteratorPreorder());
+    return iter;
+  }
+
+  @Override
+  public Iterator<TreeNodeI> iterateInLevelOrder()
+  {
+    Iterator<TreeNodeI> iter = new TreeIterator(
+            tree.iteratorLevelOrder());
+    return iter;
+  }
+
+  @Override
+  public Iterator<TreeNodeI> iterateInPostOrder()
+  {
+    Iterator<TreeNodeI> iter = new TreeIterator(
+            tree.iteratorPostorder());
+    return iter;
+  }
+
+  @Override
+  public TreeNodeI getFurthestNode()
+  {
+    PhylogenyNode furthestNode = PhylogenyMethods
+            .calculateNodeWithMaxDistanceToRoot(tree);
+    return TreeNode.getUniqueWrapper(furthestNode);
+  }
+
+  @Override
+  public TreeFrameI createTreeViewerFromTree(String instanceTitle)
+  {
+    return new AptxFrame(Archaeopteryx.createApplication(tree,
+            AptxInit.APTX_CONFIG,
+            instanceTitle));
+  }
+
+  @Override
+  public List<SequenceI> getNodeSequences()
+  {
+    List<SequenceI> treeSeqs = new ArrayList<>();
+    Iterator<TreeNodeI> iter = iterateInPreOrder();
+    while (iter.hasNext())
+    {
+
+      SequenceI nodeSeq = iter.next().getSequence();
+      if (nodeSeq != null)
+      {
+        treeSeqs.add(nodeSeq);
+      }
+    }
+    return treeSeqs;
+  }
+
+  @Override
+  public TreeNodeI[] getAllNodes()
+  {
+    TreeNodeI[] treeNodes = new TreeNodeI[tree.getNodeCount()];
+    Iterator<TreeNodeI> iter = iterateInPreOrder();
+    int i = 0;
+    while (iter.hasNext())
+    {
+      treeNodes[i++] = iter.next();
+    }
+    return treeNodes;
+  }
+
+  @Override
+  public void outputAsFile(File outputFile) throws IOException
+  {
+    PhylogenyWriter treeWriter = new PhylogenyWriter();
+    treeWriter.toPhyloXML(tree, 0, outputFile);
+
+
+  }
+
 }
diff --git a/src/jalview/ext/archaeopteryx/TreeIterator.java b/src/jalview/ext/archaeopteryx/TreeIterator.java
new file mode 100644 (file)
index 0000000..20c8fc8
--- /dev/null
@@ -0,0 +1,31 @@
+package jalview.ext.archaeopteryx;
+
+import jalview.ext.treeviewer.TreeNodeI;
+
+import java.util.Iterator;
+
+import org.forester.phylogeny.iterators.PhylogenyNodeIterator;
+
+public class TreeIterator implements Iterator<TreeNodeI>
+{
+  private final PhylogenyNodeIterator iter;
+
+  public TreeIterator(PhylogenyNodeIterator aptxIterator)
+  {
+    iter = aptxIterator;
+  }
+
+  @Override
+  public boolean hasNext()
+  {
+    return iter.hasNext();
+  }
+
+  @Override
+  public TreeNodeI next()
+  {
+    TreeNodeI node = TreeNode.getUniqueWrapper(iter.next());
+    return node;
+  }
+
+}
index 8e06d6c..0844171 100644 (file)
 package jalview.ext.archaeopteryx;
 
-import jalview.ext.treeviewer.ExternalTreeNodeI;
+import jalview.datamodel.SequenceI;
+import jalview.ext.forester.DataConversions;
+import jalview.ext.treeviewer.TreeNodeI;
 
+import java.awt.Color;
+import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
+import org.forester.phylogeny.PhylogenyMethods;
 import org.forester.phylogeny.PhylogenyNode;
 
-public class TreeNode implements ExternalTreeNodeI
+public class TreeNode implements TreeNodeI
 {
   private final PhylogenyNode node;
 
-  public TreeNode(PhylogenyNode aptxNode)
+  private SequenceI nodeSeq;
+
+  private static Map<PhylogenyNode, TreeNodeI> originalNodes = new HashMap<>(
+          500); // prolly make this size dynamic?
+
+  private static Map<TreeNodeI, PhylogenyNode> wrappedNodes = new HashMap<>(
+          500);
+
+  /**
+   * Please don't use me directly.
+   * 
+   * @param aptxNode
+   */
+  private TreeNode(PhylogenyNode aptxNode)
   {
     node = aptxNode;
+    if (aptxNode.getNodeData().getSequence() != null)
+    {
+    nodeSeq = DataConversions
+              .createJalviewSequence(aptxNode);
+    }
+    originalNodes.put(aptxNode, this);
+    wrappedNodes.put(this, aptxNode);
+
   }
 
+
   @Override
-  public PhylogenyNode getOriginalNode()
+  public String getNodeName()
   {
-    return node;
+    return node.getName();
   }
 
+
   @Override
-  public String getNodeName()
+  public List<TreeNodeI> getAllDescendants()
   {
-    return node.getName();
+
+    List<PhylogenyNode> descNodes = PhylogenyMethods
+            .getAllDescendants(node);
+    return getUniqueWrappers(descNodes);
+    
+
+  }
+
+  @Override
+  public List<TreeNodeI> getExternalDescendants()
+  {
+    List<PhylogenyNode> extDescNodes = node.getAllExternalDescendants();
+    return getUniqueWrappers(extDescNodes);
+  }
+
+
+  @Override
+  public List<TreeNodeI> getDirectChildren()
+  {
+    List<PhylogenyNode> childNodes = node.getDescendants();
+    return getUniqueWrappers(childNodes);
+    
+
+  }
+
+
+
+  @Override
+  public void setSequence(SequenceI seq)
+  {
+    nodeSeq = seq;
+    org.forester.phylogeny.data.Sequence foresterFormatSeq = DataConversions
+            .createForesterSequence(seq, true);
+    node.getNodeData().setSequence(foresterFormatSeq);
+
+  }
+
+  @Override
+  public SequenceI getSequence()
+  {
+    return nodeSeq;
+  }
+
+  @Override
+  public void addAsChild(TreeNodeI childNode)
+  {
+    PhylogenyNode aptxNode = unwrapNode(childNode);
+
+    node.addAsChild(aptxNode);
+
+  }
+
+  @Override
+  public long getId()
+  {
+    return node.getId();
+  }
+
+  @Override
+  public float getXcoord()
+  {
+    return node.getXcoord();
+  }
+
+  @Override
+  public void setBranchColor(Color branchColor)
+  {
+    PhylogenyMethods.setBranchColorValue(node, branchColor);
+
   }
 
   @Override
-  public List<ExternalTreeNodeI> getChildren()
+  public boolean isInternal()
   {
-    // return node.getDescendants();
-    return null;
+    return node.isInternal();
   }
 
+  public static List<TreeNodeI> getUniqueWrappers(
+          List<PhylogenyNode> aptxNodes)
+  {
+    List<TreeNodeI> wrappedNodes = new ArrayList<>(
+            aptxNodes.size());
+
+    for (PhylogenyNode aptxNode : aptxNodes)
+    {
+      wrappedNodes.add(getUniqueWrapper(aptxNode));
+    }
+    return wrappedNodes;
+  }
+
+  /**
+   * This method should be used to create new wrappers as there is a possibility
+   * the Archaeopteryx node was already introduced to Jalview previously so this
+   * avoids giving one node duplicate wrappers
+   * 
+   * @param aptxNode
+   * @return
+   */
+  public static TreeNodeI getUniqueWrapper(
+          PhylogenyNode aptxNode)
+  {
+    if (aptxNode == null)
+    {
+      return null;
+    }
+    TreeNodeI wrappedNode = originalNodes.get(aptxNode);
+    if (wrappedNode == null)
+    {
+      wrappedNode = new TreeNode(aptxNode);
+    }
+    return wrappedNode;
+  }
+
+  /**
+   * Attempts to unwrap the given node, if the unwrapped node already exists it
+   * is simply returned as is. If it is not however, the wrapper will be used to
+   * create a new Archaeopteryx node. This way it becomes possible to construct
+   * new Archaeopteryx nodes from different tree viewers, as long as they
+   * implement the interface.
+   * 
+   * @param wrappedNode
+   * @return
+   */
+  protected static PhylogenyNode unwrapNode(TreeNodeI wrappedNode)
+  {
+    if (wrappedNode == null)
+    {
+      return null;
+    }
+    PhylogenyNode aptxNode = wrappedNodes.get(wrappedNode);
+    if (aptxNode == null)
+    {
+      // expand this
+      aptxNode = new PhylogenyNode(wrappedNode.getNodeName());
+
+    }
+    return aptxNode;
+
+  }
+
+
+  @Override
+  public int hashCode()
+  {
+    final int prime = 31;
+    int result = 1;
+    result = (int) (prime * result
+            + ((node == null) ? 0 : (node.hashCode() * getId())));
+    return result;
+  }
+
+  @Override
+  public boolean equals(Object obj)
+  {
+    if (this == obj)
+    {
+      return true;
+    }
+    if (obj == null)
+    {
+      return false;
+    }
+    if (getClass() != obj.getClass())
+    {
+      return false;
+    }
+    TreeNode other = (TreeNode) obj;
+    if (node == null)
+    {
+      if (other.node != null)
+      {
+        return false;
+      }
+    }
+    if (getId() != other.getId())
+    {
+      return false;
+    }
+
+    if (!node.equals(other.node))
+    {
+      return false;
+    }
+    return true;
+  }
+
+
+  @Override
+  public float getYcoord()
+  {
+    return node.getYcoord();
+  }
+
+  @Override
+  public boolean isCollapsed()
+  {
+    return node.isCollapse();
+  }
 
 }
index be97e0e..a6ed3d9 100644 (file)
@@ -1,10 +1,12 @@
 package jalview.ext.forester;
 
+import jalview.datamodel.Sequence;
 import jalview.datamodel.SequenceI;
 import jalview.math.MatrixI;
 
 import org.forester.evoinference.matrix.distance.DistanceMatrix;
 import org.forester.io.parsers.phyloxml.PhyloXmlDataFormatException;
+import org.forester.phylogeny.PhylogenyNode;
 
 public final class DataConversions
 {
@@ -17,14 +19,14 @@ public final class DataConversions
     {
       foresterSeq.setName(jalviewSequence.getDescription());
     }
-    foresterSeq.setMolecularSequenceAligned(sequenceIsAligned); // all tree
-                                                                // sequences
-                                                                // should
-                                                                // be aligned
-                                                                // already
+
+    // all tree sequences should be aligned already
+    foresterSeq.setMolecularSequenceAligned(sequenceIsAligned);
+
     foresterSeq.setMolecularSequence(jalviewSequence.getSequenceAsString());
-    if (jalviewSequence.isProtein()) // add checks for DNA or RNA (infer from
-                                     // forester itself?)
+    
+    // add checks for DNA or RNA (infer from forester itself?)
+    if (jalviewSequence.isProtein())
     {
       try
       {
@@ -40,6 +42,20 @@ public final class DataConversions
 
   }
 
+  public static SequenceI createJalviewSequence(
+          PhylogenyNode foresterNode)
+  {
+    String seq = foresterNode.getNodeData().getSequence()
+            .getMolecularSequence();
+    String seqName = foresterNode.getName();
+
+    SequenceI jalviewSeq = new Sequence(seqName, seq, 1,
+            seq.length() + 1);
+    return jalviewSeq.deriveSequence();
+
+
+  }
+
 
   // public static org.forester.phylogeny.data.Accession
   // createForesterAccession(
@@ -73,4 +89,6 @@ public final class DataConversions
     return foresterMatrix;
 
   }
+
+
 }
diff --git a/src/jalview/ext/forester/io/ForesterParser.java b/src/jalview/ext/forester/io/ForesterParser.java
new file mode 100644 (file)
index 0000000..b0c2bdb
--- /dev/null
@@ -0,0 +1,90 @@
+package jalview.ext.forester.io;
+
+import jalview.ext.archaeopteryx.AptxInit;
+import jalview.ext.archaeopteryx.Tree;
+import jalview.ext.treeviewer.TreeI;
+import jalview.ext.treeviewer.TreeParserI;
+
+import java.io.File;
+import java.io.IOException;
+
+import org.forester.io.parsers.PhylogenyParser;
+import org.forester.io.parsers.nexus.NexusPhylogeniesParser;
+import org.forester.io.parsers.phyloxml.PhyloXmlParser;
+import org.forester.io.parsers.util.PhylogenyParserException;
+import org.forester.phylogeny.Phylogeny;
+
+public class ForesterParser
+        implements TreeParserI
+{
+  private final PhylogenyParser parser;
+
+  private TreeI[] parsedTrees;
+
+  protected ForesterParser(PhylogenyParser foresterParser, File file)
+          throws PhylogenyParserException, IOException
+  {
+    parser = foresterParser;
+    parser.setSource(file);
+  }
+
+  public static ForesterParser createNexusParser(File file)
+          throws PhylogenyParserException, IOException
+  {
+    NexusPhylogeniesParser nxParser = new NexusPhylogeniesParser();
+    nxParser.setReplaceUnderscores(
+            AptxInit.APTX_CONFIG.isReplaceUnderscoresInNhParsing());
+    nxParser.setIgnoreQuotes(false);
+    return new ForesterParser(nxParser, file);
+  }
+
+  public static ForesterParser createPhyloXmlParser(File file)
+          throws PhylogenyParserException, IOException
+  {
+    if (AptxInit.APTX_CONFIG.isValidatePhyloXmlAgainstSchema())
+    {
+    return new ForesterParser(
+              PhyloXmlParser.createPhyloXmlParserXsdValidating(), file);
+    }
+    else
+    {
+      return new ForesterParser(PhyloXmlParser.createPhyloXmlParser(),
+              file);
+    }
+  }
+
+  // ParserBasedPhylogenyFactory.getInstance().create(foresterParser, source)
+  @Override
+  public TreeI[] parse() throws IOException
+  {
+    Phylogeny[] foresterTrees = parser.parse();
+    parsedTrees = new TreeI[foresterTrees.length];
+
+    for (int i = 0; i < foresterTrees.length; i++)
+    {
+      parsedTrees[i] = new Tree(foresterTrees[i]);
+    }
+    return parsedTrees;
+
+  }
+
+  @Override
+  public void setSource(Object source) throws IOException
+  {
+    parser.setSource(source);
+
+  }
+
+  @Override
+  public String getName()
+  {
+    return parser.getName();
+  }
+
+
+  @Override
+  public TreeI[] getParsedTrees()
+  {
+    return parsedTrees;
+  }
+}
\ No newline at end of file
diff --git a/src/jalview/ext/forester/io/NexusFile.java b/src/jalview/ext/forester/io/NexusFile.java
new file mode 100644 (file)
index 0000000..7050f27
--- /dev/null
@@ -0,0 +1,47 @@
+package jalview.ext.forester.io;
+
+import jalview.datamodel.SequenceI;
+import jalview.ext.treeviewer.TreeI;
+import jalview.ext.treeviewer.TreeParserI;
+import jalview.io.AlignFile;
+import jalview.io.FileParse;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.List;
+
+public class NexusFile extends AlignFile
+{
+
+  public NexusFile(FileParse source) throws IOException
+  {
+    super(source);
+  }
+
+  @Override
+  public String print(SequenceI[] seqs, boolean jvsuffix)
+  {
+    // TODO Auto-generated method stub
+    return null;
+  }
+
+  /**
+   * This does not properly work for Nexus yet as Forester's parser doesn't
+   * parse the actual sequences to the tree.
+   */
+  @Override
+  public void parse() throws IOException
+  {
+    TreeParserI parser = ForesterParser
+            .createNexusParser(new File(getDataName()));
+    TreeI[] trees = parser.parse();
+    List<SequenceI> treeSeqs = trees[0].getNodeSequences();
+    for (SequenceI seq : treeSeqs)
+    {
+        seqs.add(seq);
+      }
+    }
+
+  }
+
+
diff --git a/src/jalview/ext/forester/io/PhyloXmlFile.java b/src/jalview/ext/forester/io/PhyloXmlFile.java
new file mode 100644 (file)
index 0000000..3cb3223
--- /dev/null
@@ -0,0 +1,42 @@
+package jalview.ext.forester.io;
+
+import jalview.datamodel.SequenceI;
+import jalview.ext.treeviewer.TreeI;
+import jalview.ext.treeviewer.TreeParserI;
+import jalview.io.AlignFile;
+import jalview.io.FileParse;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.List;
+
+public class PhyloXmlFile extends AlignFile
+{
+
+  public PhyloXmlFile(FileParse source) throws IOException
+  {
+    super(source);
+  }
+
+  @Override
+  public String print(SequenceI[] seqs, boolean jvsuffix)
+  {
+    // TODO Auto-generated method stub
+    return null;
+  }
+
+  @Override
+  public void parse() throws IOException
+  {
+    TreeParserI parser = ForesterParser
+            .createPhyloXmlParser(new File(getDataName()));
+    TreeI[] trees = parser.parse();
+    List<SequenceI> treeSeqs = trees[0].getNodeSequences();
+    for (SequenceI seq : treeSeqs)
+      {
+        seqs.add(seq);
+      }
+
+  }
+
+}
index 45415d1..3d11c8d 100644 (file)
@@ -1,5 +1,7 @@
 package jalview.ext.forester.io;
 
+import java.util.List;
+
 import javax.swing.JMenu;
 import javax.swing.JMenuItem;
 
@@ -10,7 +12,6 @@ public class TreeDatabaseMenuBuilder
 {
   final WebservicesManager webservicesManager;
 
-  JMenuItem[] treeDatabaseMenuItems;
 
   public TreeDatabaseMenuBuilder()
 
@@ -20,8 +21,10 @@ public class TreeDatabaseMenuBuilder
 
   }
 
-  public JMenu fillMenu(JMenu treeDbMenu) {
-    treeDatabaseMenuItems = new JMenuItem[webservicesManager
+  public JMenu createDbMenu()
+  {
+    JMenu treeDbMenu = new JMenu();
+    JMenuItem[] treeDatabaseMenuItems = new JMenuItem[webservicesManager
                                           .getAvailablePhylogeniesWebserviceClients().size()];
     
     for (int i = 0; i < treeDatabaseMenuItems.length; ++i)
@@ -37,4 +40,9 @@ public class TreeDatabaseMenuBuilder
     
   }
 
+  public List<PhylogeniesWebserviceClient> getTreeDatabases()
+  {
+    return webservicesManager.getAvailablePhylogeniesWebserviceClients();
+  }
+
 }
diff --git a/src/jalview/ext/forester/io/TreeParser.java b/src/jalview/ext/forester/io/TreeParser.java
deleted file mode 100644 (file)
index 43fd1fa..0000000
+++ /dev/null
@@ -1,198 +0,0 @@
-package jalview.ext.forester.io;
-
-import jalview.ext.archaeopteryx.AptxInit;
-import jalview.gui.AlignViewport;
-//import jalview.ext.treeviewer.ExternalTreeParserI;
-import jalview.gui.Desktop;
-import jalview.gui.JvOptionPane;
-import jalview.io.DataSourceType;
-import jalview.io.NewickFile;
-import jalview.util.MessageManager;
-
-import java.io.File;
-import java.io.IOException;
-
-import org.forester.util.ForesterUtil;
-
-public class TreeParser // implements ExternalTreeParserI<MainFrame>
-{
-  private final String filePath;
-
-  private final File file;
-
-  public TreeParser(final String treeFilePath)
-  {
-    final String possibleError = ForesterUtil.isReadableFile(treeFilePath);
-    if (possibleError != null)
-    {
-      JvOptionPane.showMessageDialog(Desktop.desktop, possibleError,
-              MessageManager.getString("label.problem_reading_tree_file"),
-              JvOptionPane.WARNING_MESSAGE);
-
-    }
-    filePath = treeFilePath;
-    file = new File(filePath);
-
-  }
-
-  public TreeParser(final File treeFile) throws IOException
-  {
-    final String possibleError = ForesterUtil.isReadableFile(treeFile);
-    if (possibleError != null)
-    {
-      JvOptionPane.showMessageDialog(Desktop.desktop, possibleError,
-              MessageManager.getString("label.problem_reading_tree_file"),
-              JvOptionPane.WARNING_MESSAGE);
-
-    }
-    file = treeFile;
-    filePath = file.getCanonicalPath();
-  }
-
-  public void loadTree(AlignViewport viewport)
-  {
-
-    NewickFile fin = null; // old tree
-      try
-      {
-        AptxInit.createInstanceFromFile(filePath, viewport);
-
-        fin = new NewickFile(filePath, DataSourceType.FILE);
-        viewport.setCurrentTree(viewport.getAlignPanel().alignFrame
-                .showNewickTree(fin, filePath).getTree());
-
-      } catch (Exception ex)
-      {
-        JvOptionPane.showMessageDialog(Desktop.desktop, ex.getMessage(),
-                MessageManager.getString("label.problem_reading_tree_file"),
-                JvOptionPane.WARNING_MESSAGE);
-        ex.printStackTrace();
-      }
-      if (fin != null && fin.hasWarningMessage())
-      {
-        JvOptionPane.showMessageDialog(Desktop.desktop,
-                fin.getWarningMessage(),
-                MessageManager
-                        .getString("label.possible_problem_with_tree_file"),
-                JvOptionPane.WARNING_MESSAGE);
-      }
-    }
-  }
-
-
-//
-// @Override
-// public MainFrame loadTreeFile(AlignmentViewport viewport)
-// {
-// String[] AptxArgs = new String[] { "-c",
-// "_aptx_jalview_configuration_file", filePath };
-// MainFrame aptx = Archaeopteryx.main(AptxArgs);
-//
-// LoadedTreeAssociation bindAptxNodes = new LoadedTreeAssociation(
-// viewport.getAlignment().getSequencesArray(),
-// aptx.getMainPanel().getCurrentTreePanel().getPhylogeny());
-//
-// bindAptxNodes.associateLeavesToSequences();
-//
-// new JalviewBinding(aptx, viewport, bindAptxNodes.getAlignmentWithNodes(),
-// bindAptxNodes.getNodesWithAlignment());
-//
-// AptxInit.bindFrameToJalview(aptx);
-//
-// return aptx;
-//
-//
-// }
-// //
-// void readPhylogeniesFromURL() {
-// URL url = null;
-// Phylogeny[] phys = null;
-// final String message = "Please enter a complete URL, for example
-// \"http://purl.org/phylo/treebase/phylows/study/TB2:S15480?format=nexus\"";
-// final String url_string = JOptionPane
-// .showInputDialog( this,
-// message,
-// "Use URL/webservice to obtain a phylogeny",
-// JOptionPane.QUESTION_MESSAGE );
-// boolean nhx_or_nexus = false;
-// if ( ( url_string != null ) && ( url_string.length() > 0 ) ) {
-// try {
-// url = new URL( url_string );
-// PhylogenyParser parser = null;
-// if ( url.getHost().toLowerCase().indexOf( "tolweb" ) >= 0 ) {
-// parser = new TolParser();
-// }
-// else {
-// parser = ParserUtils
-// .createParserDependingOnUrlContents( url,
-// getConfiguration().isValidatePhyloXmlAgainstSchema() );
-// }
-// if ( parser instanceof NexusPhylogeniesParser ) {
-// nhx_or_nexus = true;
-// }
-// else if ( parser instanceof NHXParser ) {
-// nhx_or_nexus = true;
-// }
-// if ( _mainpanel.getCurrentTreePanel() != null ) {
-// _mainpanel.getCurrentTreePanel().setWaitCursor();
-// }
-// else {
-// _mainpanel.setWaitCursor();
-// }
-// final PhylogenyFactory factory =
-// ParserBasedPhylogenyFactory.getInstance();
-// phys = factory.create( url.openStream(), parser );
-// }
-// catch ( final MalformedURLException e ) {
-// JOptionPane.showMessageDialog( this,
-// "Malformed URL: " + url + "\n" + e.getLocalizedMessage(),
-// "Malformed URL",
-// JOptionPane.ERROR_MESSAGE );
-// }
-// catch ( final IOException e ) {
-// JOptionPane.showMessageDialog( this,
-// "Could not read from " + url + "\n"
-// + ForesterUtil.wordWrap( e.getLocalizedMessage(), 80 ),
-// "Failed to read URL",
-// JOptionPane.ERROR_MESSAGE );
-// }
-// catch ( final Exception e ) {
-// JOptionPane.showMessageDialog( this,
-// ForesterUtil.wordWrap( e.getLocalizedMessage(), 80 ),
-// "Unexpected Exception",
-// JOptionPane.ERROR_MESSAGE );
-// }
-// finally {
-// if ( _mainpanel.getCurrentTreePanel() != null ) {
-// _mainpanel.getCurrentTreePanel().setArrowCursor();
-// }
-// else {
-// _mainpanel.setArrowCursor();
-// }
-// }
-// if ( ( phys != null ) && ( phys.length > 0 ) ) {
-// if ( nhx_or_nexus &&
-// getOptions().isInternalNumberAreConfidenceForNhParsing() ) {
-// for( final Phylogeny phy : phys ) {
-// PhylogenyMethods.transferInternalNodeNamesToConfidence( phy, "" );
-// }
-// }
-// AptxUtil.addPhylogeniesToTabs( phys,
-// new File( url.getFile() ).getName(),
-// new File( url.getFile() ).toString(),
-// getConfiguration(),
-// getMainPanel() );
-// _mainpanel.getControlPanel().showWhole();
-// }
-// }
-// activateSaveAllIfNeeded();
-// System.gc();
-// }
-//
-// }
-//
-//
-//
-//
-//
-//
diff --git a/src/jalview/ext/forester/io/UtilityMethods.java b/src/jalview/ext/forester/io/UtilityMethods.java
new file mode 100644 (file)
index 0000000..3d7be38
--- /dev/null
@@ -0,0 +1,25 @@
+package jalview.ext.forester.io;
+
+import jalview.gui.Desktop;
+import jalview.gui.JvOptionPane;
+import jalview.util.MessageManager;
+
+import java.io.File;
+
+import org.forester.util.ForesterUtil;
+
+public class UtilityMethods
+{
+  public static boolean canForesterReadFile(File treeFile)
+  {
+    final String err = ForesterUtil.isReadableFile(treeFile);
+    if (!ForesterUtil.isEmpty(err))
+    {
+      JvOptionPane.showInternalMessageDialog(Desktop.desktop, err,
+              MessageManager.getString("label.problem_reading_tree_file"),
+              JvOptionPane.WARNING_MESSAGE);
+      return false;
+    }
+    return true;
+  }
+}
diff --git a/src/jalview/ext/treeviewer/ExternalLoadedTreeAssociationI.java b/src/jalview/ext/treeviewer/ExternalLoadedTreeAssociationI.java
deleted file mode 100644 (file)
index 83ffac6..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-package jalview.ext.treeviewer;
-
-/**
- * Interface for associating the leaves of a loaded in (not calculated) tree to
- * the alignment sequences in Jalview.
- * 
- * @author kjvanderheide
- *
- * 
- */
-public interface ExternalLoadedTreeAssociationI
-{
-  public void associateLeavesToSequences();
-}
diff --git a/src/jalview/ext/treeviewer/ExternalTreeBuilderI.java b/src/jalview/ext/treeviewer/ExternalTreeBuilderI.java
deleted file mode 100644 (file)
index 8fd1d1d..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-package jalview.ext.treeviewer;
-
-import jalview.datamodel.SequenceI;
-
-import java.util.Map;
-
-/**
- * Note that this will take anything as a Tree or TreeNode object as no
- * assumptions can be made about the inheritance structure of Tree or TreeNode
- * (besides being Objects).
- * 
- * @author kjvanderheide
- *
- * @param <T>
- *          Tree object that the tree viewer requires.
- * @param <N>
- *          Tree node object that the tree viewer requires.
- */
-public interface ExternalTreeBuilderI<T, N>
-{
-  public T buildTree(N treeRoot);
-
-  public T buildTree();
-
-  public Map<SequenceI, N> getAlignmentBoundNodes();
-
-  public Map<N, SequenceI> getNodesBoundAlignment();
-
-  public String generateTreeName();
-
-}
diff --git a/src/jalview/ext/treeviewer/ExternalTreeI.java b/src/jalview/ext/treeviewer/ExternalTreeI.java
deleted file mode 100644 (file)
index 0184227..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-package jalview.ext.treeviewer;
-
-public interface ExternalTreeI
-{
-  public void setTreeName(String name);
-
-  public <T> T getOriginalTree();
-
-  public ExternalTreeNodeI getRoot();
-
-  public ExternalTreeNodeI getNodeWithName(String name);
-
-  public String[] getAllLeafNames();
-
-}
diff --git a/src/jalview/ext/treeviewer/ExternalTreeNodeI.java b/src/jalview/ext/treeviewer/ExternalTreeNodeI.java
deleted file mode 100644 (file)
index 34f45bd..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-package jalview.ext.treeviewer;
-
-import java.util.List;
-
-public interface ExternalTreeNodeI
-{
-  public <N> N getOriginalNode();
-
-  public String getNodeName();
-
-  public List<ExternalTreeNodeI> getChildren();
-}
diff --git a/src/jalview/ext/treeviewer/ExternalTreePanelI.java b/src/jalview/ext/treeviewer/ExternalTreePanelI.java
deleted file mode 100644 (file)
index c488683..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-package jalview.ext.treeviewer;
-
-public interface ExternalTreePanelI
-{
-
-}
diff --git a/src/jalview/ext/treeviewer/ExternalTreeParserI.java b/src/jalview/ext/treeviewer/ExternalTreeParserI.java
deleted file mode 100644 (file)
index 47960f9..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-// package jalview.ext.treeviewer;
-//
-// import jalview.viewmodel.AlignmentViewport;
-//
-/// **
-// *
-// * Interface for loading in existing trees to an external tree viewer.
-// *
-// * @author kjvanderheide
-// *
-// */
-// public interface ExternalTreeParserI
-// {
-// public ExternalTreeI loadTreeFile(AlignmentViewport viewport);
-//
-// public ExternalTreeI loadTreeUrl(AlignmentViewport viewport);
-//
-// }
diff --git a/src/jalview/ext/treeviewer/ExternalTreeViewerBindingI.java b/src/jalview/ext/treeviewer/ExternalTreeViewerBindingI.java
deleted file mode 100644 (file)
index a4ec9b2..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
- * Copyright (C) $$Year-Rel$$ The Jalview Authors
- * 
- * This file is part of Jalview.
- * 
- * Jalview is free software: you can redistribute it and/or
- * modify it under the terms of the GNU General Public License 
- * as published by the Free Software Foundation, either version 3
- * of the License, or (at your option) any later version.
- *  
- * Jalview is distributed in the hope that it will be useful, but 
- * WITHOUT ANY WARRANTY; without even the implied warranty 
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
- * PURPOSE.  See the GNU General Public License for more details.
- * 
- * You should have received a copy of the GNU General Public License
- * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
- * The Jalview Authors are detailed in the 'AUTHORS' file.
- */
-package jalview.ext.treeviewer;
-
-import jalview.datamodel.SequenceI;
-import jalview.structure.SelectionListener;
-import jalview.structure.SelectionSource;
-
-import java.awt.event.ActionListener;
-import java.awt.event.MouseListener;
-
-/**
- * 
- * Interface for binding a tree viewer to Jalview alignments. Assumes a tree
- * viewer will both want to receive and send selection events. Note that this
- * will take anything as a TreeNode object as no assumptions can be made about
- * the inheritance structure of the TreeNode (besides being an Object).
- * 
- * @author kjvanderheide
- *
- * @param <N>
- *          Tree node object.
- */
-public interface ExternalTreeViewerBindingI<N>
-        extends ActionListener, MouseListener, SelectionListener,
-        SelectionSource
-{
-  /**
-   * If a node is selected in the tree panel this method highlights the
-   * corresponding sequence in the Jalview alignment view. If an internal node
-   * is selected all child sequences get highlighted as well.
-   */
-  public void showNodeSelectionOnAlign(N node);
-
-  public void treeSelectionChanged(SequenceI sequence);
-
-  public void showMatchingSequence(N nodeToMatch);
-
-  public void showMatchingChildSequences(N parentNode);
-
-}
diff --git a/src/jalview/ext/treeviewer/ExternalTreeViewerI.java b/src/jalview/ext/treeviewer/ExternalTreeViewerI.java
deleted file mode 100644 (file)
index 20c47f6..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-package jalview.ext.treeviewer;
-
-public interface ExternalTreeViewerI
-{
-
-}
diff --git a/src/jalview/ext/treeviewer/JalviewBinding.java b/src/jalview/ext/treeviewer/JalviewBinding.java
new file mode 100644 (file)
index 0000000..fd1735e
--- /dev/null
@@ -0,0 +1,763 @@
+package jalview.ext.treeviewer;
+
+import jalview.analysis.AlignmentSorter;
+import jalview.analysis.Conservation;
+import jalview.api.AlignViewportI;
+import jalview.commands.CommandI;
+import jalview.commands.OrderCommand;
+import jalview.datamodel.AlignmentI;
+import jalview.datamodel.ColumnSelection;
+import jalview.datamodel.HiddenColumns;
+import jalview.datamodel.SequenceGroup;
+import jalview.datamodel.SequenceI;
+import jalview.gui.AlignViewport;
+import jalview.gui.AlignmentPanel;
+import jalview.gui.Desktop;
+import jalview.gui.JvOptionPane;
+import jalview.gui.PaintRefresher;
+import jalview.schemes.ColourSchemeI;
+import jalview.schemes.ColourSchemeProperty;
+import jalview.schemes.UserColourScheme;
+import jalview.structure.SelectionSource;
+import jalview.structure.StructureSelectionManager;
+import jalview.util.MappingUtils;
+import jalview.util.MessageManager;
+import jalview.viewmodel.AlignmentViewport;
+
+import java.awt.Color;
+import java.awt.Rectangle;
+import java.awt.event.ActionEvent;
+import java.awt.event.InputEvent;
+import java.awt.event.MouseEvent;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+
+import javax.swing.SwingUtilities;
+import javax.swing.event.InternalFrameAdapter;
+import javax.swing.event.InternalFrameEvent;
+
+/**
+ * Class for binding the tree viewer to the Jalview alignment that it originates
+ * from, meaning that selecting sequences in the tree viewer also selects them
+ * in the alignment view and vice versa.
+ * 
+ * @author kjvanderheide
+ *
+ */
+public final class JalviewBinding
+        implements TreeViewerBindingI
+{
+  private final TreeFrameI aptxFrame;
+
+  private TreePanelI treeView;
+
+  private AlignmentViewport parentAvport;
+
+  private final StructureSelectionManager ssm;
+
+  private Map<SequenceI, TreeNodeI> sequencesBoundToNodes;
+
+  private Map<TreeNodeI, SequenceI> nodesBoundToSequences;
+
+  private float rootX;
+
+  private float furthestNodeX;
+
+  private int nrTreeGroups = 0;
+
+  private boolean applyToAllViews = false;
+
+  /**
+   * 
+   * @param archaeopteryx
+   * 
+   * @param jalviewAlignmentViewport
+   *          alignment viewport from which the tree was calculated.
+   * 
+   * @param alignMappedToNodes
+   *          map with sequences used to calculate the tree and matching tree
+   *          nodes as key, value pair respectively.
+   * 
+   * @param nodesMappedToAlign
+   *          map with tree nodes and matching sequences used to calculate the
+   *          tree as key, value pair respectively.
+   */
+  public JalviewBinding(final TreeFrameI archaeopteryx,
+          final AlignmentViewport jalviewAlignmentViewport,
+          final Map<SequenceI, TreeNodeI> alignMappedToNodes,
+          final Map<TreeNodeI, SequenceI> nodesMappedToAlign)
+  {
+
+    if (archaeopteryx.getNumberOfTrees() > 1)
+    {
+      JvOptionPane.showMessageDialog(Desktop.desktop,
+              MessageManager.getString("label.tabs_detected_archaeopteryx"),
+              MessageManager.getString("label.problem_reading_tree_file"),
+              JvOptionPane.WARNING_MESSAGE);
+
+    }
+
+    // deal with/prohibit null values here as that will cause problems
+    aptxFrame = archaeopteryx;
+    parentAvport = jalviewAlignmentViewport;
+    sequencesBoundToNodes = alignMappedToNodes;
+    nodesBoundToSequences = nodesMappedToAlign;
+
+    treeView = archaeopteryx.getTreePanel();
+    ssm = parentAvport.getStructureSelectionManager();
+    
+    aptxFrame.setViewBinding(this);
+    ssm.addSelectionListener(this);
+    treeView.addMouseListener(this);
+    treeView.registerWithPaintRefresher(
+            parentAvport.getSequenceSetId());
+
+    aptxFrame.addFrameListener(new InternalFrameAdapter()
+    {
+
+      @Override
+      public void internalFrameClosed(InternalFrameEvent e)
+      {
+        TreeViewerUtils.getActiveTreeViews().remove(aptxFrame);
+        ssm.removeSelectionListener(JalviewBinding.this);
+      }
+
+    });
+
+    // treeTabs.addChangeListener(new ChangeListener()
+    // {
+    //
+    // @Override
+    // public void stateChanged(ChangeEvent e)
+    // {
+    //
+    // SwingUtilities.invokeLater(new Runnable()
+    // {
+    //
+    // @Override
+    // /**
+    // * Resend the selection to the tree view when tabs get switched, this
+    // * has to be buried in invokeLater as Forester first resets the tree
+    // * view on switching tabs, without invokeLater this would get called
+    // * before Forester resets which would nullify the selection.
+    // */
+    // public void run()
+    // {
+    // treeView = archaeopteryx.getMainPanel().getCurrentTreePanel();
+    // parentAvport.sendSelection();
+    // // PaintRefresher.Refresh(treeView,
+    // // parentAvport.getSequenceSetId());
+    //
+    // }
+    // });
+    //
+    // }
+    //
+    // });
+
+  }
+
+  @Override
+  public void actionPerformed(ActionEvent e)
+  {
+    // reset hidden sequences first
+    parentAvport.showAllHiddenSeqs();
+
+    if (treeView.showingSubTree())
+    {
+      LoadedTreeSequenceAssociation bindAptxNodes = new LoadedTreeSequenceAssociation(
+              parentAvport.getAlignment().getSequencesArray(),
+              treeView.getTree());
+      bindAptxNodes.associateNodesToSequences();
+      sequencesBoundToNodes = bindAptxNodes.getAlignmentWithNodes();
+      nodesBoundToSequences = bindAptxNodes.getNodesWithAlignment();
+      TreeViewerUtils.associateNodesWithJalviewSequences(aptxFrame,
+              parentAvport, sequencesBoundToNodes, nodesBoundToSequences);
+
+
+      for (SequenceI seq : parentAvport.getAlignment().getSequencesArray())
+      {
+        if (!sequencesBoundToNodes.containsKey(seq))
+        {
+          parentAvport.hideSequence(new SequenceI[] { seq });
+
+        }
+      }
+    }
+
+    else
+    {
+
+      Rectangle visibleView = treeView.getVisibleArea();
+
+      for (TreeNodeI node : treeView.getTree().getRoot()
+              .getAllDescendants())
+      {
+        if (!(node.getXcoord() > visibleView.getMinX()
+                && node.getXcoord() < visibleView.getMaxX()
+                && node.getYcoord() > visibleView.getMinY()
+                && node.getYcoord() < visibleView.getMaxY()))
+        {
+          parentAvport
+                  .hideSequence(new SequenceI[]
+                  { nodesBoundToSequences.get(node) });
+        }
+      }
+
+    }
+
+
+
+  }
+
+  @Override
+  public void mouseClicked(MouseEvent e)
+  {
+    SwingUtilities.invokeLater(new Runnable() {
+
+      @Override
+      /**
+       * invokeLater so that this always runs after Forester's mouseClicked
+       */
+      public void run()
+      {
+        final TreeNodeI node = treeView.findNode(e.getX(),
+                e.getY());
+        if (node != null)
+        {
+          if ((e.getModifiers() & InputEvent.SHIFT_MASK) == 0) // clear previous
+          // selection if shift
+          // IS NOT pressed
+          {
+            parentAvport.setSelectionGroup(null);
+
+          }
+          showNodeSelectionOnAlign(node);
+        }
+        else
+        {
+
+          partitionTree(e.getX());
+      }
+        treeView.notifyPaintRefresher(parentAvport.getSequenceSetId(),
+                false, false);
+        treeView.repaint();
+
+
+
+      }
+    });
+
+
+  }
+
+  @Override
+  public void mousePressed(final MouseEvent e)
+  {
+
+  }
+  @Override
+  public void mouseReleased(MouseEvent e)
+  {
+  }
+
+  @Override
+  public void mouseEntered(MouseEvent e)
+  {
+  }
+
+  @Override
+  public void mouseExited(MouseEvent e)
+  {
+  }
+
+
+  @Override
+  public void selection(final SequenceGroup seqsel,
+          final ColumnSelection colsel, final HiddenColumns hidden,
+          final SelectionSource source)
+  {
+    if (source == parentAvport) // check if source is alignment from where the
+    // tree originates
+    {
+      treeView.setMatchingNodes(
+              new HashSet<Long>(seqsel.getSequences().size()));
+
+
+      for (SequenceI selectedSequence : seqsel.getSequences())
+      {
+        TreeNodeI matchingNode = sequencesBoundToNodes
+                .get(selectedSequence);
+        if (matchingNode != null)
+        {
+          treeView.addToMatchingNodes(matchingNode);
+
+
+          // if (!matchingNode.getBranchData().isHasBranchColor())
+          // {
+          // // Color foundNodesColour = treeView.getTreeColorSet()
+          // // .getFoundColor0();
+          // // matchingNode.getBranchData()
+          // // .setBranchColor(new BranchColor(foundNodesColour));
+          //
+          // }
+
+        }
+
+      }
+
+      treeView.repaint();
+    }
+
+
+  }
+
+  /**
+   * Partially refactored from TreeCanvas
+   */
+  @Override
+  public void partitionTree(final int x)
+  {
+    TreeI tree = treeView.getTree();
+
+    if (!tree.isEmpty())
+    {
+      // should be calculated on each partition as the tree can theoretically
+      // change in the meantime
+      TreeNodeI furthestNode = tree.getFurthestNode();
+      furthestNodeX = furthestNode.getXcoord();
+      rootX = tree.getRoot().getXcoord();
+
+      // don't bother if 0 distance tree or clicked x lies outside of tree
+      // if (furthestNodeX != rootX && !(x > furthestNodeX))
+
+        float threshold = (x - rootX) / (furthestNodeX - rootX);
+        List<TreeNodeI> foundNodes = getNodesAboveThreshold(
+                threshold,
+                tree.getRoot());
+
+
+    }
+
+
+  }
+
+  public List<TreeNodeI> getNodesAboveThreshold(float threshold,
+          TreeNodeI node)
+  {
+
+    List<TreeNodeI> nodesAboveThreshold = new ArrayList<>();
+
+    parentAvport.setSelectionGroup(null);
+    parentAvport.getAlignment().deleteAllGroups();
+    parentAvport.clearSequenceColours();
+    if (parentAvport.getCodingComplement() != null)
+    {
+      parentAvport.getCodingComplement().setSelectionGroup(null);
+      parentAvport.getCodingComplement().getAlignment().deleteAllGroups();
+      parentAvport.getCodingComplement().clearSequenceColours();
+    }
+
+
+    colourNodesAboveThreshold(nodesAboveThreshold, threshold,
+            node);
+    return nodesAboveThreshold;
+
+  }
+
+  /**
+   * Partially refactored from TreeCanvas colourGroups (can be made nicer).
+   * 
+   * @param nodeList
+   * @param threshold
+   * @param treeLength
+   * @param node
+   * @return
+   */
+  private List<TreeNodeI> colourNodesAboveThreshold(
+          List<TreeNodeI> nodeList, float threshold,
+          TreeNodeI node)
+  {
+
+    for (TreeNodeI childNode : node.getDirectChildren())
+    {
+      childNode.setBranchColor(Color.black);
+      float nodeCutoff = (childNode.getXcoord() - rootX)
+              / (furthestNodeX - rootX);
+
+      if (nodeCutoff > threshold)
+      {
+        nodeList.add(childNode);
+
+        Color randomColour = new Color((int) (Math.random() * 255),
+                (int) (Math.random() * 255), (int) (Math.random() * 255));
+        childNode.setBranchColor(randomColour);
+
+        List<SequenceI> groupSeqs = new ArrayList<>();
+        SequenceI seq = nodesBoundToSequences.get(childNode);
+        if (seq != null)
+        {
+          groupSeqs.add(seq);
+          parentAvport.setSequenceColour(seq, randomColour);
+        }
+
+        List<TreeNodeI> descendantNodes = childNode
+                .getAllDescendants();
+        // .forEach instead?
+        for (TreeNodeI descNode : descendantNodes)
+        {
+          seq = nodesBoundToSequences.get(descNode);
+          if (seq != null)
+          {
+            groupSeqs.add(seq);
+            parentAvport.setSequenceColour(seq, randomColour);
+          }
+
+          descNode.setBranchColor(randomColour);
+        }
+
+        if (groupSeqs != null)
+        {
+          nrTreeGroups++;
+          groupThresholdSequences(groupSeqs, randomColour);
+        }}
+
+      else
+      {
+        colourNodesAboveThreshold(nodeList, threshold, childNode);
+      }
+    }
+
+    for (AlignmentPanel associatedPanel : getAssociatedPanels())
+    {
+
+        associatedPanel.updateAnnotation();
+
+        final AlignViewportI codingComplement = associatedPanel.getAlignViewport()
+                .getCodingComplement();
+        if (codingComplement != null)
+        {
+          // GROSS
+          ((AlignViewport) codingComplement).getAlignPanel()
+                  .updateAnnotation();
+        }
+      }
+
+
+    return nodeList;
+  }
+
+  public void groupThresholdSequences(List<SequenceI> groupedSeqs,
+          Color groupColour)
+  {
+    SequenceGroup treeGroup = new SequenceGroup(groupedSeqs, null, null,
+            true, true, false, 0,
+            parentAvport.getAlignment().getWidth() - 1);
+
+    ColourSchemeI cs = null;
+    if (parentAvport.getGlobalColourScheme() != null)
+    {
+      if (parentAvport.getGlobalColourScheme() instanceof UserColourScheme)
+      {
+        cs = new UserColourScheme(
+                ((UserColourScheme) parentAvport.getGlobalColourScheme())
+                        .getColours());
+      }
+      else
+      {
+        cs = ColourSchemeProperty.getColourScheme(parentAvport,treeGroup,
+                ColourSchemeProperty.getColourName(
+                        parentAvport.getGlobalColourScheme()));
+      }
+
+    }
+    treeGroup.setColourScheme(cs);
+    treeGroup.getGroupColourScheme().setThreshold(
+            parentAvport.getResidueShading().getThreshold(),
+            parentAvport.isIgnoreGapsConsensus());
+
+    treeGroup.setName("Tree Group " + nrTreeGroups);
+    treeGroup.setIdColour(groupColour);
+
+    for (AlignmentPanel associatedPanel : getAssociatedPanels())
+    {
+      AlignViewportI altViewport = associatedPanel
+              .getAlignViewport();
+
+      if (altViewport.getGlobalColourScheme() != null
+              && altViewport.getResidueShading()
+                      .conservationApplied())
+      {
+        Conservation conserv = new Conservation(treeGroup.getName(),
+                treeGroup.getSequences(null), treeGroup.getStartRes(),
+                treeGroup.getEndRes());
+        conserv.calculate();
+        conserv.verdict(false, altViewport.getConsPercGaps());
+        treeGroup.getGroupColourScheme().setConservation(conserv);
+      }
+
+      altViewport.getAlignment().addGroup(treeGroup);
+      // TODO can we push all of the below into AlignViewportI?
+      final AlignViewportI codingComplement = altViewport
+              .getCodingComplement();
+      if (codingComplement != null)
+      {
+        SequenceGroup mappedGroup = MappingUtils.mapSequenceGroup(treeGroup,
+                parentAvport, codingComplement);
+        if (mappedGroup.getSequences().size() > 0)
+        {
+          codingComplement.getAlignment().addGroup(mappedGroup);
+          for (SequenceI seq : mappedGroup.getSequences())
+          {
+            codingComplement.setSequenceColour(seq, groupColour.brighter());
+          }
+        }
+      }
+
+    }
+
+  }
+
+
+  @Override
+  public void showNodeSelectionOnAlign(final TreeNodeI node)
+  {
+
+      if (node.isInternal())
+      {
+        showMatchingChildSequences(node);
+      }
+
+      else
+      {
+        showMatchingSequence(node);
+      }
+
+
+    }
+
+
+
+
+
+  @Override
+  public void showMatchingSequence(final TreeNodeI nodeToMatch)
+  {
+    SequenceI matchingSequence = nodesBoundToSequences.get(nodeToMatch);
+    if (matchingSequence != null)
+    {
+      long nodeId = nodeToMatch.getId();
+      addOrRemoveInCollection(treeView.getMatchingNodesIds(), nodeId);
+      treeSelectionChanged(matchingSequence);
+      parentAvport.sendSelection();
+
+    }
+  }
+
+  @Override
+  public void showMatchingChildSequences(final TreeNodeI parentNode)
+  {
+    // redundancy here, Forester already iterates through tree to get all
+    // descendants
+    List<TreeNodeI> childNodes = parentNode.getAllDescendants();
+
+
+    for (TreeNodeI childNode : childNodes)
+    {
+      SequenceI matchingSequence = nodesBoundToSequences.get(childNode);
+      if (matchingSequence != null)
+      {
+        long nodeId = childNode.getId();
+        addOrRemoveInCollection(treeView.getMatchingNodesIds(), nodeId);
+
+        treeSelectionChanged(matchingSequence);
+
+      }
+
+    }
+    parentAvport.sendSelection();
+
+
+  }
+
+
+  @Override
+  public void treeSelectionChanged(final SequenceI sequence)
+  {
+    if (!parentAvport.isClosed()) // alignment view could be closed
+    {
+      SequenceGroup selected = parentAvport.getSelectionGroup();
+
+      if (selected == null)
+      {
+        selected = new SequenceGroup();
+        parentAvport.setSelectionGroup(selected);
+      }
+
+      selected.setEndRes(parentAvport.getAlignment().getWidth() - 1);
+        selected.addOrRemove(sequence, true);
+    }
+
+  }
+
+  @Override
+  public void sortByTree_actionPerformed()
+  {
+
+    // if (applyToAllViews)
+
+      final ArrayList<CommandI> commands = new ArrayList<>();
+      for (AlignmentPanel ap : PaintRefresher
+              .getAssociatedPanels(parentAvport.getSequenceSetId()))
+      {
+        commands.add(sortAlignmentIn(ap.av.getAlignPanel()));
+        ap.alignFrame.addHistoryItem(new CommandI()
+        {
+
+          @Override
+          public void undoCommand(AlignmentI[] views)
+          {
+            for (CommandI tsort : commands)
+            {
+              tsort.undoCommand(views);
+            }
+          }
+
+          @Override
+          public int getSize()
+          {
+            return commands.size();
+          }
+
+          @Override
+          public String getDescription()
+          {
+            return "Tree Sort (many views)";
+          }
+
+          @Override
+          public void doCommand(AlignmentI[] views)
+          {
+
+            for (CommandI tsort : commands)
+            {
+              tsort.doCommand(views);
+            }
+          }
+        });
+
+        ap.alignFrame.updateEditMenuBar();
+      }
+    }
+  // else
+  // {
+  // alignPanel.alignFrame.addHistoryItem(sortAlignmentIn(alignPanel));
+  // }
+
+
+
+  @Override
+  public CommandI sortAlignmentIn(AlignmentPanel ap)
+  {
+    AlignmentViewport viewport = ap.av;
+    SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
+    try
+    {
+    AlignmentSorter.sortByTree(viewport.getAlignment(),
+            nodesBoundToSequences,
+              treeView.getTree());
+      CommandI undo;
+      undo = new OrderCommand("Tree Sort", oldOrder,
+              viewport.getAlignment());
+
+      ap.paintAlignment(true, false);
+      return undo;
+
+    } catch (Exception e)
+    {
+      System.err.println(e.getMessage());
+    }
+    return null;
+
+  }
+  
+
+
+  /**
+   * TO BE MOVED
+   * 
+   * @param collection
+   * @param nodeId
+   */
+  public static <E> void addOrRemoveInCollection(Collection<Long> collection,
+          long nodeId)
+  {
+    if (collection.contains(nodeId))
+    {
+      collection.remove(nodeId);
+    }
+    else
+    {
+      collection.add(nodeId);
+    }
+
+  }
+
+  public AlignmentViewport getParentAvport()
+  {
+    return parentAvport;
+  }
+
+  public void setParentAvport(final AlignmentViewport parentAvport)
+  {
+    this.parentAvport = parentAvport;
+  }
+
+  public AlignmentPanel[] getAssociatedPanels()
+  {
+    return PaintRefresher
+            .getAssociatedPanels(parentAvport.getSequenceSetId());
+  }
+
+  @Override
+  public Map<SequenceI, TreeNodeI> getAlignmentWithNodes()
+  {
+    return sequencesBoundToNodes;
+  }
+
+  @Override
+  public Map<TreeNodeI, SequenceI> getNodesWithAlignment()
+  {
+    return nodesBoundToSequences;
+  }
+
+  @Override
+  public void hideCollapsedSequences_actionPerformed()
+  {
+    parentAvport.showAllHiddenSeqs();
+
+    for (TreeNodeI node : treeView.getTree().getAllNodes())
+    {
+      if (node.isCollapsed())
+      {
+        SequenceI seqToHide = nodesBoundToSequences.get(node);
+        if (seqToHide != null)
+        {
+          parentAvport.hideSequence(new SequenceI[] { seqToHide });
+
+
+        }
+
+      }
+    }
+
+
+  }
+
+}
+
+
+
diff --git a/src/jalview/ext/treeviewer/LoadedTreeAssociationI.java b/src/jalview/ext/treeviewer/LoadedTreeAssociationI.java
new file mode 100644 (file)
index 0000000..34367e9
--- /dev/null
@@ -0,0 +1,39 @@
+package jalview.ext.treeviewer;
+
+import jalview.datamodel.SequenceI;
+
+import java.util.Map;
+
+/**
+ * Interface for associating the nodes of a loaded in (instead of calculated)
+ * tree to the sequences of an alignment in Jalview.
+ * 
+ * @author kjvanderheide
+ *
+ */
+public interface LoadedTreeAssociationI
+{
+  /**
+   * Tries to match the loaded in tree nodes as best as possible with Jalview
+   * sequences
+   * 
+   * Partially refactored from the old Jalview TreeModel
+   * associateLeavesToSequences method.
+   */
+  public void associateNodesToSequences();
+
+  /**
+   * @see jalview.ext.treeviewer.TreeViewerBindingI#getAlignmentWithNodes()
+   * 
+   * 
+   */
+  public Map<SequenceI, TreeNodeI> getAlignmentWithNodes();
+
+  /**
+   * @see jalview.ext.treeviewer.TreeViewerBindingI#getNodesWithAlignment()
+   * 
+   * 
+   * 
+   */
+  public Map<TreeNodeI, SequenceI> getNodesWithAlignment();
+}
diff --git a/src/jalview/ext/treeviewer/LoadedTreeSequenceAssociation.java b/src/jalview/ext/treeviewer/LoadedTreeSequenceAssociation.java
new file mode 100644 (file)
index 0000000..c05a57c
--- /dev/null
@@ -0,0 +1,113 @@
+package jalview.ext.treeviewer;
+
+import jalview.analysis.SequenceIdMatcher;
+import jalview.datamodel.SequenceI;
+import jalview.util.MappingUtils;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+/**
+ * Generic implementation of {@link LoadedTreeAssociationI } that tries to
+ * associate tree nodes based on comparing Jalview's sequence IDs to tree node
+ * names.
+ * 
+ * @author kjvanderheide
+ *
+ */
+public class LoadedTreeSequenceAssociation
+        implements LoadedTreeAssociationI
+{
+  SequenceI[] alignSequences;
+
+  TreeI tree;
+
+  Map<SequenceI, TreeNodeI> alignmentWithNodes;
+
+  Map<TreeNodeI, SequenceI> nodesWithAlignment;
+
+  public LoadedTreeSequenceAssociation(SequenceI[] alignmentSequences,
+          TreeI extTree)
+  {
+    alignSequences = alignmentSequences;
+    tree = extTree;
+    alignmentWithNodes = new HashMap<>(alignSequences.length);
+    nodesWithAlignment = new HashMap<>(alignSequences.length);
+
+  }
+
+  @Override
+  public void associateNodesToSequences()
+
+  {
+    SequenceIdMatcher algnIds = new SequenceIdMatcher(alignSequences);
+    SequenceI nodeSequence;
+    String nodeSequenceName;
+
+    if (!tree.isEmpty())
+    {
+      for (final Iterator<TreeNodeI> iter = tree
+              .iterateInPreOrder(); iter
+              .hasNext();)
+      {
+        TreeNodeI treeNode = iter.next();
+        nodeSequenceName = treeNode.getNodeName();
+
+        nodeSequence = algnIds.findIdMatch(nodeSequenceName);
+        if (nodeSequence != null)
+        {
+          // is there already a sequence present for the node?
+          // If so, does it actually match Jalview's sequence?
+          if (treeNode.getSequence() != null)
+          {
+            if (!(treeNode.getSequence().getSequenceAsString()
+                    .equals(nodeSequence.getSequenceAsString())))
+            {
+              System.err.println(
+                      "Sequence detected in tree node that does not match corresponding Jalview sequence:"
+                              + nodeSequenceName);
+              // which sequence gets precedence?
+
+            }
+
+          }
+          else
+          {
+          treeNode.setSequence(nodeSequence);
+          }
+          MappingUtils.putWithDuplicationCheck(alignmentWithNodes,
+                  nodeSequence, treeNode);
+          MappingUtils.putWithDuplicationCheck(nodesWithAlignment, treeNode,
+                  nodeSequence);
+
+
+        }
+
+    }
+
+    }
+  }
+
+
+
+  @Override
+  public Map<SequenceI, TreeNodeI> getAlignmentWithNodes()
+  {
+    return alignmentWithNodes;
+  }
+
+  @Override
+  public Map<TreeNodeI, SequenceI> getNodesWithAlignment()
+  {
+    return nodesWithAlignment;
+  }
+
+
+}
+
+
+
+
+
+
diff --git a/src/jalview/ext/treeviewer/TreeBuilderI.java b/src/jalview/ext/treeviewer/TreeBuilderI.java
new file mode 100644 (file)
index 0000000..066caae
--- /dev/null
@@ -0,0 +1,23 @@
+package jalview.ext.treeviewer;
+
+import jalview.datamodel.SequenceI;
+
+import java.util.Map;
+
+/**
+ * @author kjvanderheide
+ *
+ */
+public interface TreeBuilderI
+{
+  public TreeI buildTree();
+
+  public TreeI buildTree(TreeNodeI treeRoot);
+
+  public String generateTreeName();
+
+  public Map<SequenceI, TreeNodeI> getAlignmentBoundNodes();
+
+  public Map<TreeNodeI, SequenceI> getNodesBoundAlignment();
+
+}
diff --git a/src/jalview/ext/treeviewer/TreeControlsI.java b/src/jalview/ext/treeviewer/TreeControlsI.java
new file mode 100644 (file)
index 0000000..d33c73b
--- /dev/null
@@ -0,0 +1,18 @@
+package jalview.ext.treeviewer;
+
+/**
+ * Interface for visually manipulating the tree with methods that might be user
+ * triggered.
+ * 
+ * @author kjvanderheide
+ *
+ */
+public interface TreeControlsI
+{
+  /**
+   * Resets the current view so that it shows the tree in its entirety (in case
+   * it was previously zoomed in etc.)
+   */
+  public void displayEntireTree();
+
+}
diff --git a/src/jalview/ext/treeviewer/TreeFrameI.java b/src/jalview/ext/treeviewer/TreeFrameI.java
new file mode 100644 (file)
index 0000000..26f74c2
--- /dev/null
@@ -0,0 +1,82 @@
+package jalview.ext.treeviewer;
+
+import java.awt.Container;
+import java.awt.Dimension;
+import java.awt.MenuContainer;
+import java.awt.image.ImageObserver;
+
+import javax.accessibility.Accessible;
+import javax.swing.RootPaneContainer;
+import javax.swing.WindowConstants;
+import javax.swing.event.InternalFrameListener;
+
+/**
+ * Interface for implementing the (probably) top level frame of an external tree
+ * viewer. Note that this extends many interfaces shared with Swing frames but
+ * doesn't demand that an implementation actually is a Swing frame.
+ * 
+ * Frames should be added to Jalview's desktop via
+ * {@link TreeViewerUtils#addTreeViewFrameToJalview(TreeFrameI)} to ensure that
+ * they are registered as an active tree view.
+ * 
+ * @author kjvanderheide
+ *
+ */
+public interface TreeFrameI
+        extends Accessible, WindowConstants, RootPaneContainer,
+        ImageObserver, MenuContainer
+{
+  public void addFrameListener(InternalFrameListener listener);
+
+  /**
+   * Method for adding the actual frame to Jalview, probably by calling
+   * {@link jalview.gui.Desktop#addInternalFrame(javax.swing.JInternalFrame, String, boolean, int, int, boolean, boolean)}
+   * 
+   * @param title
+   * @param makeVisible
+   * @param width
+   * @param height
+   * @param resizable
+   * @param ignoreMinSize
+   */
+  public void addFrameToJalview(String title, boolean makeVisible,
+          int width, int height, boolean resizable, boolean ignoreMinSize);
+
+  /**
+   * If the tree viewer used supports multiple trees in one frame this method
+   * should perform the needed adaptations.
+   */
+  public abstract void enableMultipleTrees();
+
+  public InternalFrameListener[] getFrameListeners();
+
+  public abstract int getNumberOfTrees();
+
+  public Container getTopLevelAncestor();
+
+  public abstract TreeI getTree();
+
+  public TreeControlsI getTreeControls();
+
+  public abstract TreePanelI getTreePanel();
+
+  public TreeViewerBindingI getViewBinding();
+
+  public boolean isShowing();
+
+  public void removeFrameListener(InternalFrameListener listener);
+
+  /**
+   * @see java.awt.Component#repaint()
+   */
+  public void repaint();
+
+  public void setMaximumSize(Dimension maximumSize);
+
+  public void setMinimumSize(Dimension minimumSize);
+
+  public void setPreferredSize(Dimension preferredSize);
+
+  public void setViewBinding(TreeViewerBindingI alignmentBinding);
+
+}
diff --git a/src/jalview/ext/treeviewer/TreeI.java b/src/jalview/ext/treeviewer/TreeI.java
new file mode 100644 (file)
index 0000000..08c3d04
--- /dev/null
@@ -0,0 +1,89 @@
+package jalview.ext.treeviewer;
+
+import jalview.datamodel.SequenceI;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * Interface for implementing a phylogenetic tree.
+ * 
+ * @author kjvanderheide
+ *
+ */
+public interface TreeI
+{
+  /**
+   * Uses this tree as the basis for a new tree frame.
+   * 
+   * @param instanceTitle
+   *          name of the new tree frame.
+   * @return
+   */
+  TreeFrameI createTreeViewerFromTree(String instanceTitle);
+
+  public String[] getAllLeafNames();
+
+  public TreeNodeI[] getAllNodes();
+
+  /**
+   * Gets the node that has the maximum branch length from the root (or top
+   * level node if tree is unrooted).
+   * 
+   * @return
+   */
+  public TreeNodeI getFurthestNode();
+
+  /**
+   * Returns the longest total branch length from the root to a leaf node.
+   * 
+   * @param adjustForCollapsedSubtrees
+   *          true if nodes part of a collapsed (hidden) subtree should be
+   *          considered.
+   * @return
+   */
+  public double getMaximumLength(boolean adjustForCollapsedSubtrees);
+
+  public List<SequenceI> getNodeSequences();
+
+  public TreeNodeI getNodeWithName(String name);
+
+  public TreeNodeI getRoot();
+
+  public String getTreeName();
+
+  /**
+   * Check if the tree actually contains any nodes.
+   * 
+   * @return true if tree has no nodes (or is deleted), false otherwise.
+   */
+  public boolean isEmpty();
+
+  public Iterator<TreeNodeI> iterateInLevelOrder();
+
+  public Iterator<TreeNodeI> iterateInPostOrder();
+
+  public Iterator<TreeNodeI> iterateInPreOrder();
+
+  /**
+   * This should write the tree to the richest file format available for
+   * compatibility reasons as this is the method used when Jalview saves a tree
+   * to its project.
+   * 
+   * @param outputFile
+   *          File that tree should be written to
+   * @throws IOException
+   */
+  public void outputAsFile(File outputFile) throws IOException;
+
+  public void setRerootable(boolean b);
+
+  public void setRoot(TreeNodeI rootNode);
+
+  public void setRooted(boolean b);
+
+  public void setTreeName(String treeTitle);
+
+}
diff --git a/src/jalview/ext/treeviewer/TreeNodeI.java b/src/jalview/ext/treeviewer/TreeNodeI.java
new file mode 100644 (file)
index 0000000..33cb080
--- /dev/null
@@ -0,0 +1,59 @@
+package jalview.ext.treeviewer;
+
+import jalview.datamodel.SequenceI;
+
+import java.awt.Color;
+import java.util.List;
+
+/**
+ * Interface for implementing a tree node, these nodes might -but do not have
+ * to- be part of a {@link TreeI}.
+ * 
+ * @author kjvanderheide
+ *
+ */
+public interface TreeNodeI
+{
+
+  public void addAsChild(TreeNodeI childNode);
+
+  public List<TreeNodeI> getAllDescendants();
+
+  /**
+   * Returns only the immediate descendants of this node, so any nodes whose
+   * parent is this node.
+   * 
+   * @return
+   */
+  public List<TreeNodeI> getDirectChildren();
+
+  /**
+   * Gets just the nodes downwards from this node that are external/leafs.
+   * 
+   * @return
+   */
+  public List<TreeNodeI> getExternalDescendants();
+
+  public long getId();
+
+  public String getNodeName();
+
+  public SequenceI getSequence();
+
+  public float getXcoord();
+
+  public float getYcoord();
+
+  /**
+   * 
+   * @return True if the node is internal, false if it's external (a leaf).
+   */
+  public boolean isInternal();
+
+  public boolean isCollapsed();
+
+  public void setBranchColor(Color branchColor);
+
+  public void setSequence(SequenceI seq);
+
+}
diff --git a/src/jalview/ext/treeviewer/TreePanelI.java b/src/jalview/ext/treeviewer/TreePanelI.java
new file mode 100644 (file)
index 0000000..6871105
--- /dev/null
@@ -0,0 +1,133 @@
+package jalview.ext.treeviewer;
+
+import java.awt.Dimension;
+import java.awt.Graphics2D;
+import java.awt.MenuContainer;
+import java.awt.Rectangle;
+import java.awt.event.MouseListener;
+import java.io.File;
+import java.util.Set;
+
+import javax.accessibility.Accessible;
+
+/**
+ * Interface for a panel that supports viewing a phylogenetic tree, should
+ * probably be part of a {@link TreeFrameI}. Does not necessarily have to be a
+ * Swing JPanel.
+ * 
+ * Implementations must always contain a {@link TreeI}.
+ * 
+ * @author kjvanderheide
+ *
+ */
+public interface TreePanelI extends Accessible, MenuContainer
+{
+  public void addMouseListener(MouseListener listener);
+
+  /**
+   * Look for a tree node at the specified coordinates inside the panel.
+   * 
+   * @param x
+   *          X coordinate on the panel to look at.
+   * @param y
+   *          Y coordinate on the panel to look at.
+   * @return The tree node if one was found, otherwise null.
+   */
+  public abstract TreeNodeI findNode(int x, int y);
+
+  public int getHeight();
+
+  /**
+   * Method for adding a tree node to the Set of nodes that are associated with
+   * some operation outside of the tree, such as nodes belonging to currently
+   * selected Jalview alignment sequences.
+   * 
+   * @param matchedNode
+   */
+  public void addToMatchingNodes(TreeNodeI matchedNode);
+
+  public abstract Set<Long> getMatchingNodesIds();
+
+  public MouseListener[] getMouseListeners();
+
+  /**
+   * Gets the current partitioning threshold which is the ratio of the
+   * partitioning x coordinate to the total panel width.
+   * 
+   * @return The partition threshold.
+   */
+  public float getPartitionThreshold();
+
+  public abstract TreeI getTree();
+
+  /**
+   * Gets the File from where the Tree originates.
+   * 
+   * @return
+   */
+  public abstract File getTreeFile();
+
+  public abstract Rectangle getVisibleArea();
+
+  public int getWidth();
+
+  /**
+   * Method for triggering PaintRefresher refreshes with the actual tree panel
+   * using the sequence set id the panel was registered with.
+   * 
+   * @see jalview.gui.PaintRefresher#Refresh(java.awt.Component, String,
+   *      boolean, boolean)
+   * @param alignmentChanged
+   * @param validateSequences
+   */
+  public void notifyPaintRefresher(boolean alignmentChanged,
+          boolean validateSequences);
+
+  /**
+   * Method for triggering PaintRefresher refreshes with the actual tree panel
+   * using a new sequence set id.
+   * 
+   * @see jalview.gui.PaintRefresher#Refresh(java.awt.Component, String,
+   *      boolean, boolean)
+   * @param newSeqSetIdentifier
+   * @param alignmentChanged
+   * @param validateSequences
+   */
+  public void notifyPaintRefresher(String newSeqSetIdentifier,
+          boolean alignmentChanged, boolean validateSequences);
+
+  public abstract void paintToFile(Graphics2D pg, int width, int height);
+
+  /**
+   * Registers the actual tree viewing panel used with PaintRefresher, this
+   * method is necessary as panels cannot be registered at this interface level
+   * because there is no guarantee an implementation will be a Component.
+   * 
+   * @see jalview.gui.PaintRefresher#Register(java.awt.Component, String)
+   * @param sequenceSetIdentifier
+   */
+  public void registerWithPaintRefresher(String sequenceSetIdentifier);
+
+  public void removeMouseListener(MouseListener listener);
+
+  public void repaint();
+
+  public abstract void setMatchingNodes(Set<Long> matchingNodes);
+
+  public void setMaximumSize(Dimension maximumSize);
+
+  public void setMinimumSize(Dimension minimumSize);
+
+  public void setPreferredSize(Dimension preferredSize);
+
+  public abstract void setTreeFile(File file);
+
+  /**
+   * Checks if the tree has been cut to display just a sub tree.
+   * 
+   * @return True if the panel is currently showing only a subtree, otherwise
+   *         false.
+   */
+  public boolean showingSubTree();
+
+}
diff --git a/src/jalview/ext/treeviewer/TreeParserI.java b/src/jalview/ext/treeviewer/TreeParserI.java
new file mode 100644 (file)
index 0000000..97db111
--- /dev/null
@@ -0,0 +1,26 @@
+package jalview.ext.treeviewer;
+
+import java.io.IOException;
+
+/**
+ * Interface for reading in trees from a given source.
+ * 
+ * @author kjvanderheide
+ *
+ */
+public interface TreeParserI
+ {
+  public String getName();
+
+  public TreeI[] getParsedTrees();
+
+  /**
+   * 
+   * @return Trees that were successfully parsed.
+   * @throws IOException
+   */
+  public TreeI[] parse() throws IOException;
+
+  public void setSource(Object source) throws IOException;
+
+ }
diff --git a/src/jalview/ext/treeviewer/TreeViewerBindingI.java b/src/jalview/ext/treeviewer/TreeViewerBindingI.java
new file mode 100644 (file)
index 0000000..0c0af6f
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License 
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *  
+ * Jalview is distributed in the hope that it will be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty 
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ * PURPOSE.  See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
+package jalview.ext.treeviewer;
+
+import jalview.commands.CommandI;
+import jalview.datamodel.SequenceI;
+import jalview.gui.AlignmentPanel;
+import jalview.structure.SelectionListener;
+import jalview.structure.SelectionSource;
+
+import java.awt.event.ActionListener;
+import java.awt.event.MouseListener;
+import java.util.Map;
+
+/**
+ * 
+ * Interface for associating the nodes of a tree viewer with Jalview alignment
+ * sequences and communicating between the two. Assumes a tree viewer will both
+ * want to receive and send selection events.
+ * 
+ * @author kjvanderheide
+ *
+ * 
+ */
+public interface TreeViewerBindingI
+        extends ActionListener, MouseListener, SelectionListener,
+        SelectionSource
+{
+  /**
+   * Gets the mapping for sequences with their associated tree nodes
+   * 
+   * @return
+   */
+  public Map<SequenceI, TreeNodeI> getAlignmentWithNodes();
+
+  /**
+   * Gets the mapping for tree nodes with their associated sequences
+   * 
+   * @return
+   */
+  public Map<TreeNodeI, SequenceI> getNodesWithAlignment();
+
+  /**
+   * Triggers a tree partition from the specified x coordinate.
+   * 
+   * @param x
+   * 
+   */
+  public void partitionTree(final int x);
+
+  /**
+   * Looks up the given TreeNodeI in the tree and highlights Jalview sequences
+   * that belong to it or its descendants.
+   * 
+   * @param parentNode
+   *          node from where the descendants should get matched, this node
+   *          should be internal.
+   */
+  public void showMatchingChildSequences(TreeNodeI parentNode);
+
+  /**
+   * Highlights the Jalview sequence belonging to the given TreeNodeI (if
+   * possible).
+   * 
+   * @param nodeToMatch
+   */
+  public void showMatchingSequence(TreeNodeI nodeToMatch);
+
+  /**
+   * If a node is selected in the tree panel this method highlights the
+   * corresponding sequence in the Jalview alignment view. If an internal node
+   * is selected all child sequences get highlighted as well.
+   */
+  public void showNodeSelectionOnAlign(TreeNodeI node);
+
+  /**
+   * Sorts the given alignment by the order in which the sequences appear in the
+   * tree.
+   * 
+   * @param alignPanel
+   *          panel containing the alignment to be sorted.
+   * @return the sorting Command
+   */
+  public CommandI sortAlignmentIn(AlignmentPanel alignPanel);
+
+  /**
+   * Is triggered when the user wants to sort the Jalview alignment by the
+   * sequence order of the tree.
+   */
+  public void sortByTree_actionPerformed();
+
+  /**
+   * Is triggered when the users wants to hide sequences in the Jalview
+   * alignment view that are part of a currently collapsed sub tree.
+   */
+  public void hideCollapsedSequences_actionPerformed();
+
+  /**
+   * If the nodes that should be matched have changed (different one selected by
+   * the user), this method notifies the Jalview alignment view that the
+   * matching sequences have changed as well.
+   * 
+   * @param sequence
+   *          the new SequenceI that should be matched.
+   */
+  public void treeSelectionChanged(SequenceI sequence);
+
+}
diff --git a/src/jalview/ext/treeviewer/TreeViewerUtils.java b/src/jalview/ext/treeviewer/TreeViewerUtils.java
new file mode 100644 (file)
index 0000000..7e1a4e9
--- /dev/null
@@ -0,0 +1,90 @@
+package jalview.ext.treeviewer;
+
+import jalview.datamodel.SequenceI;
+import jalview.util.MessageManager;
+import jalview.viewmodel.AlignmentViewport;
+
+import java.awt.Dimension;
+import java.io.File;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Static class containing generic methods for communicating between the tree
+ * viewer frame and Jalview, currently includes adding the frame to the Jalview
+ * Desktop and triggering an association between an {@link AlignmentViewport}
+ * and {@link TreeFrameI}.
+ * 
+ * @author kjvanderheide
+ *
+ */
+public final class TreeViewerUtils
+{
+  /**
+   * All tree viewers should be added to this map so that Jalview saves them to
+   * its project.
+   */
+  private static Map<TreeFrameI, TreeViewerBindingI> activeViews = new HashMap<>();
+
+  /**
+   * Adds the given tree frame to the Jalview {@link Desktop}.
+   * 
+   * @param treeFrame
+   * @return the same tree frame but now as part of Jalview.
+   */
+  public static TreeFrameI addTreeViewFrameToJalview(
+          final TreeFrameI treeFrame, int width, int height)
+  {
+    treeFrame.setMinimumSize(new Dimension(width, height));
+    // aptxApp.setFont(Desktop.instance.getFont());
+    // aptxApp.getMainPanel().setFont(Desktop.instance.getFont());
+    String frameTitle = MessageManager.getString("label.aptx_title");
+    File treeFile = treeFrame.getTreePanel().getTreeFile();
+    if (treeFile != null)
+    {
+      frameTitle += MessageManager.formatMessage("label.of_x",
+              new String[]
+              { treeFile.getAbsolutePath() });
+    }
+    // Usually redundant as this is done when associating nodes as well but that
+    // step could be bypassed
+    activeViews.put(treeFrame, treeFrame.getViewBinding());
+
+    treeFrame.addFrameToJalview(frameTitle, true, width, height, true,
+            false);
+    treeFrame.getTreeControls().displayEntireTree();
+    return treeFrame;
+  
+  }
+
+  /**
+   * Convience method for building the association between Jalview's alignment
+   * and the tree frame.
+   * 
+   * @param treeFrame
+   * @param jalviewAlignViewport
+   * @param alignMappedToNodes
+   * @param nodesMappedToAlign
+   * @return
+   */
+  public static TreeViewerBindingI associateNodesWithJalviewSequences(
+          final TreeFrameI treeFrame,
+          final AlignmentViewport jalviewAlignViewport,
+          final Map<SequenceI, TreeNodeI> alignMappedToNodes,
+          final Map<TreeNodeI, SequenceI> nodesMappedToAlign)
+  {
+    TreeViewerBindingI treeBinding = new JalviewBinding(treeFrame,
+            jalviewAlignViewport,
+            alignMappedToNodes, nodesMappedToAlign);
+    jalviewAlignViewport.setCurrentExtTree(treeFrame.getTree());
+    activeViews.put(treeFrame, treeFrame.getViewBinding());
+
+    return treeBinding;
+  }
+
+  public static Map<TreeFrameI, TreeViewerBindingI> getActiveTreeViews()
+  {
+    return activeViews;
+  }
+
+}
index ea206e9..62262d5 100644 (file)
@@ -917,7 +917,7 @@ public abstract class GFTSPanel extends JPanel implements GFTSPanelI
   public void transferToSequenceFetcher(String ids)
   {
     seqFetcher.setQuery(ids);
-    Thread worker = new Thread(seqFetcher);
+    Thread worker = new Thread(seqFetcher, "GFTSSeqFetcher");
     worker.start();
   }
 
index 15a68e6..0083971 100644 (file)
@@ -224,7 +224,7 @@ public class PDBFTSPanel extends GFTSPanel
 
     String ids = selectedIds.toString();
     seqFetcher.setQuery(ids);
-    Thread worker = new Thread(seqFetcher, "PDBFTSSeqFetcherThread");
+    Thread worker = new Thread(seqFetcher, "PDBFTSSeqFetcher");
     worker.start();
     delayAndEnableActionButtons();
   }
index 89f4036..f8bce9d 100644 (file)
@@ -60,6 +60,8 @@ import java.util.Enumeration;
 import java.util.Hashtable;
 import java.util.List;
 import java.util.Locale;
+import java.util.Map;
+import java.util.Map.Entry;
 import java.util.StringTokenizer;
 import java.util.Vector;
 
@@ -77,6 +79,9 @@ import javax.swing.JPanel;
 import javax.swing.JScrollPane;
 import javax.swing.SwingUtilities;
 
+import org.forester.archaeopteryx.webservices.PhylogeniesWebserviceClient;
+import org.forester.archaeopteryx.webservices.WebservicesManager;
+
 import ext.vamsas.ServiceHandle;
 import jalview.analysis.AlignmentSorter;
 import jalview.analysis.AlignmentUtils;
@@ -115,6 +120,7 @@ import jalview.datamodel.AlignmentI;
 import jalview.datamodel.AlignmentOrder;
 import jalview.datamodel.AlignmentView;
 import jalview.datamodel.ColumnSelection;
+import jalview.datamodel.DBRefEntry;
 import jalview.datamodel.HiddenColumns;
 import jalview.datamodel.PDBEntry;
 import jalview.datamodel.SeqCigar;
@@ -123,7 +129,9 @@ import jalview.datamodel.SequenceGroup;
 import jalview.datamodel.SequenceI;
 import jalview.ext.archaeopteryx.AptxInit;
 import jalview.ext.forester.io.SupportedTreeFileFilter;
-import jalview.ext.forester.io.TreeParser;
+import jalview.ext.treeviewer.TreeFrameI;
+import jalview.ext.treeviewer.TreeViewerBindingI;
+import jalview.ext.treeviewer.TreeViewerUtils;
 import jalview.gui.ColourMenuHelper.ColourChangeListener;
 import jalview.gui.ViewSelectionMenu.ViewSetProvider;
 import jalview.io.AlignmentProperties;
@@ -153,6 +161,7 @@ import jalview.schemes.ColourSchemeI;
 import jalview.schemes.ColourSchemes;
 import jalview.schemes.ResidueColourScheme;
 import jalview.schemes.TCoffeeColourScheme;
+import jalview.util.DBRefUtils;
 import jalview.util.HttpUtils;
 import jalview.util.ImageMaker.TYPE;
 import jalview.util.MessageManager;
@@ -1643,7 +1652,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
   /**
    * DOCUMENT ME!
    */
-  void updateEditMenuBar()
+  public void updateEditMenuBar()
   {
 
     if (viewport.getHistoryList().size() > 0)
@@ -3925,6 +3934,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     }
   }
 
+
   /**
    * Maintain the Order by->Displayed Tree menu. Creates a new menu item for a
    * TreePanel with an appropriate <code>jalview.analysis.AlignmentSorter</code>
@@ -3940,15 +3950,21 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     List<Component> comps = PaintRefresher.components
             .get(viewport.getSequenceSetId());
     List<TreePanel> treePanels = new ArrayList<>();
+
+    Map<TreeFrameI, TreeViewerBindingI> aptxFrames = TreeViewerUtils
+            .getActiveTreeViews();
+
     for (Component comp : comps)
     {
+      // old treepanels
       if (comp instanceof TreePanel)
       {
         treePanels.add((TreePanel) comp);
       }
+
     }
 
-    if (treePanels.size() < 1)
+    if (treePanels.isEmpty() && aptxFrames.isEmpty())
     {
       sortByTreeMenu.setVisible(false);
       return;
@@ -3956,6 +3972,42 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
 
     sortByTreeMenu.setVisible(true);
 
+    for (Entry<TreeFrameI, TreeViewerBindingI> aptxFrameWithBinding : aptxFrames
+            .entrySet())
+    {
+      TreeFrameI aptxFrame = aptxFrameWithBinding.getKey();
+      TreeViewerBindingI binding = aptxFrameWithBinding.getValue();
+
+      // future support for multiple tabs
+      // for (org.forester.archaeopteryx.TreePanel aptxTree : aptxFrame
+      // .getMainPanel().getTreePanels())
+      {
+        final JMenuItem item = new JMenuItem(
+                aptxFrame.getTree().getTreeName());
+
+          item.addActionListener(new ActionListener()
+          {
+
+            @Override
+            public void actionPerformed(ActionEvent e)
+            {
+            binding.sortByTree_actionPerformed(); // redundant here??
+            addHistoryItem(binding.sortAlignmentIn(alignPanel));
+            }
+
+          });
+        sortByTreeMenu.add(item);
+      }
+
+
+
+      }
+       
+
+           
+
+
+    // old treepanels
     for (final TreePanel tp : treePanels)
     {
       final JMenuItem item = new JMenuItem(tp.getTitle());
@@ -3964,7 +4016,6 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
         @Override
         public void actionPerformed(ActionEvent e)
         {
-          // adapt to Aptx
           tp.sortByTree_actionPerformed();
           addHistoryItem(tp.sortAlignmentIn(alignPanel));
 
@@ -4086,39 +4137,54 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
   @Override
   protected void loadTreeBaseStudy_actionPerformed(ActionEvent e)
   {
-    chooseTreeDb();
+    chooseTreeDb(0, null);
 
   }
 
   @Override
-  protected void loadTreeOfLife_actionPerformed(ActionEvent e)
+  protected void loadTreeBase_actionPerformed(ActionEvent e)
   {
-    chooseTreeDb();
+    chooseTreeDb(1, null);
 
   }
-
   @Override
-  protected void loadTreeFam_actionPerformed(ActionEvent e)
+  protected void loadTreePfam_actionPerformed(ActionEvent e)
   {
-    chooseTreeDb();
 
-  }
+    // only DBRefs of first sequence are checked for matching DB for now,
+    // iterating through them all seems excessive
+    SequenceI seq = viewport.getAlignment().getSequenceAt(0);
+    String dbId = null;
+    for (DBRefEntry pfamRef : DBRefUtils
+            .searchRefsForSource(seq.getDBRefs(), "pfam"))
+    {
+      if (pfamRef.getAccessionId().startsWith("PF"))
+      {
+        dbId = pfamRef.getAccessionId().replaceAll("[A-Za-z]", "");
+      }
+
+    }
+    chooseTreeDb(2, dbId);
 
+  }
   @Override
-  protected void loadTreePfam_actionPerformed(ActionEvent e)
+  protected void loadTreeFam_actionPerformed(ActionEvent e)
   {
-    chooseTreeDb();
+    chooseTreeDb(3, null);
 
   }
 
   @Override
-  protected void loadTreeBase_actionPerformed(ActionEvent e)
+  protected void loadTreeOfLife_actionPerformed(ActionEvent e)
   {
-    chooseTreeDb();
+    chooseTreeDb(4, null);
 
   }
 
 
+
+
+
   public void chooseTreeFile()
   {
     // Pick the tree file
@@ -4134,35 +4200,32 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     {
       chooser.setFileFilter(treeFormat.getTreeFilter());
     }
-
+    final AlignFrame us=this;
     chooser.setResponseHandler(0, new Runnable()
     {
       @Override
       public void run()
       {
-        String filePath = chooser.getSelectedFile().getPath();
-        Cache.setProperty("LAST_DIRECTORY", filePath);
-       TreeParser treeParser = null;
-       try {
-         treeParser = new TreeParser(filePath);
-         treeParser.loadTree(viewport);        
-        } catch (Exception ex)
-        {
-          JvOptionPane.showMessageDialog(Desktop.desktop, ex.getMessage(),
-                  MessageManager
-                          .getString("label.problem_reading_tree_file"),
-                  JvOptionPane.WARNING_MESSAGE);
-          ex.printStackTrace();
-        }
-// TODO: handle any other warnings from treeParser ?
-       //        if (treeParser != null && treeParser.fin.hasWarningMessage())
-//        {
-//          JvOptionPane.showMessageDialog(Desktop.desktop,
-//                  fin.getWarningMessage(),
-//                  MessageManager.getString(
-//                          "label.possible_problem_with_tree_file"),
-//                  JvOptionPane.WARNING_MESSAGE);
-//        }
+      String filePath = chooser.getSelectedFile().getPath();
+      Cache.setProperty("LAST_DIRECTORY", filePath);
+      
+      
+      NewickFile fin = null; // old tree
+      try
+      {
+        AptxInit.createInstancesFromFile(filePath, viewport);
+
+        // fin = new NewickFile(filePath, DataSourceType.FILE);
+        // viewport.setCurrentTree(viewport.getAlignPanel().alignFrame
+        // .showNewickTree(fin, filePath).getTree());
+
+      } catch (Exception ex)
+      {
+        JvOptionPane.showMessageDialog(us, ex.getMessage(),
+                MessageManager.getString("label.problem_reading_tree_file"),
+                JvOptionPane.WARNING_MESSAGE);
+        ex.printStackTrace();
+      }
       }
     });
     chooser.showOpenDialog(this);
@@ -4217,7 +4280,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
         format = new IdentifyFile().identify(urlString, DataSourceType.URL);
         // add actual use for the format identification (jalview .jar files)
         treeUrl = new URL(urlString);
-        AptxInit.createInstanceFromUrl(treeUrl, viewport);
+        AptxInit.createInstancesFromUrl(treeUrl, viewport);
 
       } catch (IOException | RuntimeException e)
       {
@@ -4235,8 +4298,26 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     }
   }
 
-  public void chooseTreeDb()
+  /**
+   * Disgustingly hardcoded atm.
+   * 
+   * @param databaseIndex
+   */
+  public void chooseTreeDb(int databaseIndex, String defaultIdentifier)
   {
+    final WebservicesManager webservices_manager = WebservicesManager
+            .getInstance();
+    final PhylogeniesWebserviceClient client = webservices_manager
+            .getAvailablePhylogeniesWebserviceClient(databaseIndex);
+    String identifier = JvOptionPane
+            .showInternalInputDialog(Desktop.desktop,
+                    client.getInstructions() + "\n(Reference: "
+                            + client.getReference() + ")",
+                    client.getDescription(), JvOptionPane.QUESTION_MESSAGE,
+                    null, null, defaultIdentifier)
+            .toString();
+
+    AptxInit.createInstancesFromDb(client, identifier, viewport);
   }
 
   public TreePanel showNewickTree(NewickFile nf, String treeTitle)
@@ -4302,6 +4383,10 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
 
   private boolean buildingMenu = false;
 
+  public void BuildTreeDbMenu()
+  {
+
+  }
   /**
    * Generates menu items and listener event actions for web service clients
    * 
@@ -4503,7 +4588,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
         }
         buildingMenu = false;
       }
-    }, "BuildWebServiceThread").start();
+    }, "BuildWebService").start();
 
   }
 
@@ -4612,7 +4697,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
           final String source)
   {
     new Thread(CrossRefAction.getHandlerFor(sel, _odna, source, this),
-            "CrossReferencesThread")
+            "CrossReferences")
             .start();
   }
 
@@ -4921,7 +5006,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
             ex.printStackTrace();
           }
         }
-      }, "DropFileThread").start();
+      }, "DropFile").start();
     }
   }
 
@@ -5320,7 +5405,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
             });
             dbRefFetcher.fetchDBRefs(false);
           }
-        }, "BuildFetchDBMenuThread").start();
+        }, "BuildFetchDBMenu").start();
 
       }
 
index 30ccdbe..ac295a1 100644 (file)
@@ -520,7 +520,6 @@ public class AlignViewport extends AlignmentViewport
    * return the alignPanel containing the given viewport. Use this to get the
    * components currently handling the given viewport.
    * 
-   * @param av
    * @return null or an alignPanel guaranteed to have non-null alignFrame
    *         reference
    */
index 8447faf..64ea4dc 100644 (file)
@@ -202,7 +202,7 @@ public class AppJmol extends StructureViewerBase
     setSize(400, 400); // probably should be a configurable/dynamic default here
     initMenus();
     addingStructures = false;
-    worker = new Thread(this, "OpenJmolThread");
+    worker = new Thread(this, "OpenJmol");
     worker.start();
 
     this.addInternalFrameListener(new InternalFrameAdapter()
index c43d59b..ae92168 100644 (file)
@@ -47,6 +47,7 @@ import java.awt.event.FocusListener;
 import java.awt.event.MouseAdapter;
 import java.awt.event.MouseEvent;
 import java.beans.PropertyVetoException;
+import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -512,6 +513,8 @@ public class CalculationChooser extends JPanel
 
   /**
    * Open and calculate the selected tree or PCA on 'OK'
+   * 
+   * @throws IOException
    */
   protected void calculate_actionPerformed()
   {
@@ -525,7 +528,14 @@ public class CalculationChooser extends JPanel
     }
     else
     {
-      createTree(substitutionMatrix, params);
+      try
+      {
+        createTree(substitutionMatrix, params);
+      } catch (IOException e)
+      {
+        // TODO Auto-generated catch block
+        e.printStackTrace();
+      }
 
 
 
@@ -538,17 +548,23 @@ public class CalculationChooser extends JPanel
   }
 
   protected void createTree(String substitutionMatrix,
-          SimilarityParamsI params)
+          SimilarityParamsI params) throws IOException
   {
     String treeAlgo = determineTreeAlgo();
     TreeCalculator treeCalculator = new TreeCalculator(treeAlgo,
             substitutionMatrix, params);
     TreeBuilder calculatedTree = treeCalculator.makeTree(af.getViewport());
 
-    AptxInit.createInstance(calculatedTree);
+    // AptxInit.createInstanceFromCalculation(calculatedTree);
 
     TreeModel tree = new TreeModel(calculatedTree);
-    openTreePanel(tree, treeAlgo, substitutionMatrix);
+    jalview.io.NewickFile newick = new jalview.io.NewickFile(
+            tree.getTopNode());
+    String output = newick.print(tree.hasBootstrap(), tree.hasDistances(),
+            tree.hasRootDistance());
+    AptxInit.createInstanceFromNhx(af.getTitle(), output, 
+            af.getViewport());
+    // openTreePanel(tree, treeAlgo, substitutionMatrix);
   }
 
 
index 367ca7f..e78938a 100644 (file)
@@ -216,7 +216,7 @@ public class ChimeraViewFrame extends StructureViewerBase
     initMenus();
 
     addingStructures = false;
-    worker = new Thread(this, "OpenChimeraThread");
+    worker = new Thread(this, "OpenChimera");
     worker.start();
 
     this.addInternalFrameListener(new InternalFrameAdapter()
index 592f666..140f6cc 100644 (file)
@@ -279,15 +279,15 @@ public class Console extends WindowAdapter
 
     // Starting two seperate threads to read from the PipedInputStreams
     //
-    reader = new Thread(this, "ConsoleReader1Thread");
+    reader = new Thread(this, "ConsoleReader1");
     reader.setDaemon(true);
     reader.start();
     //
-    reader2 = new Thread(this, "ConsoleReader2Thread");
+    reader2 = new Thread(this, "ConsoleReader2");
     reader2.setDaemon(true);
     reader2.start();
     // and a thread to append text to the textarea
-    textAppender = new Thread(this, "ConsoleTextAppendThread");
+    textAppender = new Thread(this, "ConsoleTextAppend");
     textAppender.setDaemon(true);
     textAppender.start();
 
@@ -446,7 +446,7 @@ public class Console extends WindowAdapter
     // We do it with a seperate Thread becasue we don't wan't to break a Thread
     // used by the Console.
     System.out.println("\nLets throw an error on this console");
-    errorThrower = new Thread(this, "ConsoleErrorLogThread");
+    errorThrower = new Thread(this, "ConsoleErrorLog");
     errorThrower.setDaemon(true);
     errorThrower.start();
   }
index 1a42f58..92cc153 100644 (file)
@@ -1429,7 +1429,7 @@ public class Desktop extends jalview.jbgui.GDesktop
       {
         new SplashScreen(false);
       }
-    }, "ShowAboutMenuThread").start();
+    }, "ShowAboutMenu").start();
   }
 
   /**
@@ -1797,7 +1797,7 @@ public class Desktop extends jalview.jbgui.GDesktop
           }
           setProgressBar(null, chosenFile.hashCode());
         }
-      }, "SaveJalviewProjectThread").start();
+      }, "SaveJalviewProject").start();
     }
   }
 
@@ -1842,13 +1842,17 @@ public class Desktop extends jalview.jbgui.GDesktop
       {
         File selectedFile = chooser.getSelectedFile();
         setProjectFile(selectedFile);
-        String choice = selectedFile.getAbsolutePath();
+        final String choice = selectedFile.getAbsolutePath();
         Cache.setProperty("LAST_DIRECTORY", selectedFile.getParent());
         new Thread(new Runnable()
         {
           @Override
           public void run()
           {
+          setProgressBar(MessageManager.formatMessage(
+                "label.loading_jalview_project", new Object[]
+                 { choice }), choice.hashCode());
+
             try
             {
               new Jalview2XML().loadJalviewAlign(selectedFile);
@@ -1868,6 +1872,7 @@ public class Desktop extends jalview.jbgui.GDesktop
                               .getString("label.couldnt_load_project"),
                       JvOptionPane.WARNING_MESSAGE);
             }
+          setProgressBar(null, choice.hashCode());
           }
         }, "Project Loader").start();
       }
@@ -2187,7 +2192,7 @@ public class Desktop extends jalview.jbgui.GDesktop
   {
     UserQuestionnaireCheck jvq = new UserQuestionnaireCheck(url);
     // javax.swing.SwingUtilities.invokeLater(jvq);
-    new Thread(jvq, "CheckQuestionnaireThread").start();
+    new Thread(jvq, "CheckQuestionnaire").start();
   }
 
   public void checkURLLinks()
@@ -2299,7 +2304,7 @@ public class Desktop extends jalview.jbgui.GDesktop
       this.showMemoryUsage = showMemory;
       if (showMemory)
       {
-        Thread worker = new Thread(this, "ShowMemoryUsageThread");
+        Thread worker = new Thread(this, "ShowMemoryUsage");
         worker.start();
       }
       repaint();
@@ -2753,7 +2758,7 @@ public class Desktop extends jalview.jbgui.GDesktop
       }
       // JAL-940 - disabled JWS1 service configuration - always start discoverer
       // until we phase out completely
-      (t0 = new Thread(discoverer, "DiscovererThread")).start();
+      (t0 = new Thread(discoverer, "Discoverer")).start();
     }
 
     if (ignore_SHOW_JWS2_SERVICES_preference
@@ -2905,7 +2910,7 @@ public class Desktop extends jalview.jbgui.GDesktop
           progress.setProgressBar(null, this.hashCode());
         }
       }
-    }, "OpenURLThread").start();
+    }, "OpenURL").start();
   }
 
   public static WsParamSetManager wsparamManager = null;
index b1f868e..4237ee6 100644 (file)
@@ -66,7 +66,7 @@ public abstract class JalviewDialog extends JPanel
           frame.setVisible(true);
         }
 
-      }, "UnblockedDialogThread").start();
+      }, "UnblockedDialog").start();
     }
     else
     {
index d7ef76a..b3e3e66 100755 (executable)
@@ -333,7 +333,7 @@ public class OverviewPanel extends JPanel
       return;
     }
 
-    Thread thread = new Thread(this, "UpdateOverviewThread");
+    Thread thread = new Thread(this, "UpdateOverview");
     thread.start();
     repaint();
 
index b248ec4..ad07497 100755 (executable)
@@ -96,7 +96,7 @@ public class RedundancyPanel extends GSliderPanel implements Runnable
     slider.setMaximum(100);
     slider.setValue(100);
 
-    Thread worker = new Thread(this, "CreateRedundancyPanelThread");
+    Thread worker = new Thread(this, "CreateRedundancyPanel");
     worker.start();
 
     frame = new JInternalFrame();
index 474b63c..4de11dd 100644 (file)
@@ -403,7 +403,7 @@ public abstract class StructureViewerBase extends GStructureViewer
             // and call ourselves again.
             addStructure(pdbentry, seqs, chains, alignFrame);
           }
-        }, "Adding3DStructureQueueThread").start();
+        }, "Adding3DStructureQueue").start();
         return;
       }
     }
@@ -413,7 +413,7 @@ public abstract class StructureViewerBase extends GStructureViewer
             { seqs }, new String[][] { chains });
     addingStructures = true;
     _started = false;
-    worker = new Thread(this, "Adding3DStructureThread");
+    worker = new Thread(this, "Adding3DStructure");
     worker.start();
     return;
   }
index 06b06fa..6617277 100755 (executable)
@@ -525,7 +525,7 @@ public class TreeCanvas extends JPanel implements MouseListener, Runnable,
    */
   void startPrinting()
   {
-    Thread thread = new Thread(this, "PrintTreeCanvasThread");
+    Thread thread = new Thread(this, "PrintTreeCanvas");
     thread.start();
   }
 
index df63be1..dabec6d 100644 (file)
@@ -325,7 +325,7 @@ public class VamsasApplication implements SelectionSource, VamsasSource
         Console.info("Jalview finished updating to the Vamsas Session.");
       }
 
-    }, "UpdateVamsasThread");
+    }, "UpdateVamsas");
     udthread.start();
   }
 
index 034cbad..7a5d693 100644 (file)
@@ -351,7 +351,7 @@ public class WebserviceInfo extends GWebserviceInfo
     titlePanel.add(titleText, BorderLayout.CENTER);
     setStatus(currentStatus);
 
-    Thread thread = new Thread(ap, "AnimatedPanelThread");
+    Thread thread = new Thread(ap, "AnimatedPanel");
     thread.start();
     final WebserviceInfo thisinfo = this;
     frame.addInternalFrameListener(new InternalFrameAdapter()
index 7b8bc51..64ea1b1 100644 (file)
@@ -567,7 +567,7 @@ public class WsPreferences extends GWsPreferences
         updateWsMenuConfig(false);
         refreshWsMenu(true);
       }
-    }, "RefreshWebServicesThread").start();
+    }, "RefreshWebServices").start();
 
   }
 
@@ -603,7 +603,7 @@ public class WsPreferences extends GWsPreferences
           progressBar.setVisible(false);
           validate();
         }
-      }, "RefreshWebServicesMenuProgressBarThread").start();
+      }, "RefreshWebServicesMenuProgressBar").start();
 
     }
     else
@@ -626,7 +626,7 @@ public class WsPreferences extends GWsPreferences
           Desktop.instance.setProgressBar(null, ct);
         }
 
-      }, "RefreshWebServicesMenuThread").start();
+      }, "RefreshWebServicesMenu").start();
     }
   }
 
@@ -677,7 +677,7 @@ public class WsPreferences extends GWsPreferences
         updateWsMenuConfig(false);
         refreshWsMenu(showProgressInDialog);
       }
-    }, "UpdateAndRefreshWebServicesMenuThread").start();
+    }, "UpdateAndRefreshWebServicesMenu").start();
 
   }
 }
index b701963..361d699 100644 (file)
@@ -25,6 +25,7 @@ import java.io.IOException;
 import jalview.datamodel.AlignmentI;
 import jalview.datamodel.DBRefSource;
 import jalview.datamodel.PDBEntry;
+import jalview.ext.forester.io.PhyloXmlFile;
 import jalview.ext.jmol.JmolParser;
 import jalview.structure.StructureImportSettings;
 
@@ -405,8 +406,67 @@ public enum FileFormat implements FileFormatI
     {
       return true;
     }
-  };
+  },
+  // Nexus("Nexus", "nex,nexus,nx,tre", true, true)
+  // {
+  //
+  // @Override
+  // public AlignmentFileReaderI getReader(FileParse source)
+  // throws IOException
+  // {
+  // return new NexusFile(source);
+  // }
+  //
+  // @Override
+  // public AlignmentFileWriterI getWriter(AlignmentI al)
+  // {
+  // // handle within Aptx?
+  // return null;
+  // }
+  //
+  // @Override
+  // public boolean isTextFormat()
+  // {
+  // return true;
+  // }
+  //
+  // @Override
+  // public boolean isTreeFile()
+  // {
+  // return true;
+  // }
+  //
+  // },
+  PhyloXML("PhyloXML", "phyloxml,phylo.xml,pxml", true, true)
+  {
+
+    @Override
+    public AlignmentFileReaderI getReader(FileParse source)
+            throws IOException
+    {
+      return new PhyloXmlFile(source);
+    }
+
+    @Override
+    public AlignmentFileWriterI getWriter(AlignmentI al)
+    {
+      // handle within Aptx?
+      return null;
+    }
+
+    @Override
+    public boolean isTextFormat()
+    {
+      return true;
+    }
+
+    @Override
+    public boolean isTreeFile()
+    {
+      return true;
+    }
 
+  };
   private boolean writable;
 
   private boolean readable;
@@ -482,6 +542,12 @@ public enum FileFormat implements FileFormatI
     return false;
   }
 
+  @Override
+  public boolean isTreeFile()
+  {
+    return false;
+  }
+
   /**
    * By default, answers true, indicating the format is one that can be
    * identified by IdentifyFile. Formats that cannot be identified should
index f7b6076..1e8ab1d 100644 (file)
@@ -80,4 +80,11 @@ public interface FileFormatI
    * @return
    */
   boolean isStructureFile();
+
+  /**
+   * Answers true if the file format can contain a phylogenetic tree.
+   * 
+   * @return
+   */
+  boolean isTreeFile();
 }
index fec0b3a..4cf77de 100755 (executable)
@@ -37,6 +37,7 @@ import jalview.datamodel.AlignmentI;
 import jalview.datamodel.HiddenColumns;
 import jalview.datamodel.PDBEntry;
 import jalview.datamodel.SequenceI;
+import jalview.ext.archaeopteryx.AptxInit;
 import jalview.gui.AlignFrame;
 import jalview.gui.AlignViewport;
 import jalview.gui.Desktop;
@@ -111,7 +112,7 @@ public class FileLoader implements Runnable
     this.protocol = protocol;
     this.format = format;
 
-    final Thread loader = new Thread(this, "LoadFileThread");
+    final Thread loader = new Thread(this, "LoadFile");
 
     SwingUtilities.invokeLater(new Runnable()
     {
@@ -212,6 +213,7 @@ public class FileLoader implements Runnable
     return alignFrame;
   }
 
+  // add support for recently opened Aptx trees
   public void updateRecentlyOpened()
   {
     Vector<String> recent = new Vector<>();
@@ -470,6 +472,13 @@ public class FileLoader implements Runnable
               alignFrame.getViewport()
                       .applyFeaturesStyle(proxyColourScheme);
             }
+            if (format.isTreeFile())
+            {
+              // make generic instead of Aptx specific?
+              AptxInit.createInstancesFromFile(file,
+                      alignFrame.getViewport());
+
+            }
             alignFrame.setStatus(MessageManager.formatMessage(
                     "label.successfully_loaded_file", new String[]
                     { title }));
@@ -485,6 +494,7 @@ public class FileLoader implements Runnable
                       AlignFrame.DEFAULT_WIDTH, AlignFrame.DEFAULT_HEIGHT);
             }
 
+
             try
             {
               alignFrame.setMaximum(
index c21127e..d2c586a 100755 (executable)
@@ -386,15 +386,33 @@ public class IdentifyFile
           reply = FileFormat.Phylip;
           break;
         }
-        else
+        else if (!lineswereskipped && looksLikeJnetData(data))
         {
-          if (!lineswereskipped && looksLikeJnetData(data))
-          {
             reply = FileFormat.Jnet;
             break;
-          }
+
         }
+        else // phylogenetic file
+        {
+          String identifier = data.toLowerCase();
+          String secondLine = source.nextLine().toLowerCase();
+          if (identifier.startsWith("<phyloxml")
+                  || secondLine.startsWith("<phyloxml"))
+          {
+            reply = FileFormat.PhyloXML;
+            break;
+          }
+          // commented out, nexus parser is troublesome
 
+          // else if (((identifier.startsWith("nexus"))
+          // || (identifier.startsWith("#nexus"))
+          // || (identifier.startsWith("# nexus"))
+          // || (identifier.startsWith("begin"))))
+          // {
+          // reply = FileFormat.Nexus;
+          // break;
+          // }
+        }
         lineswereskipped = true; // this means there was some junk before any
         // key file signature
       }
index 33da111..cfde4ae 100644 (file)
@@ -249,7 +249,7 @@ public class JSFunctionExec implements Runnable
       if (executor == null)
       {
         executor = new Thread(new JSFunctionExec(jvlite),
-                "JavaScriptThread");
+                "JavaScript");
         executor.start();
       }
       synchronized (jsExecQueue)
index 4d2850b..870aa89 100755 (executable)
@@ -1150,7 +1150,7 @@ public class GAlignFrame extends JInternalFrame
 
 
     JMenuItem loadTreeBaseStudy = new JMenuItem(
-            MessageManager.getString("treebase study"));
+            MessageManager.getString("label.treebase_study"));
     loadTreeBaseStudy.addActionListener(new ActionListener()
     {
 
@@ -1164,7 +1164,7 @@ public class GAlignFrame extends JInternalFrame
 
 
     JMenuItem loadTreeBase = new JMenuItem(
-            MessageManager.getString("treebase"));
+            MessageManager.getString("label.treebase"));
     loadTreeBase.addActionListener(new ActionListener()
     {
 
@@ -1178,7 +1178,7 @@ public class GAlignFrame extends JInternalFrame
 
     });
     JMenuItem loadTreePfam = new JMenuItem(
-            MessageManager.getString("pfam"));
+            MessageManager.getString("label.pfam"));
     loadTreePfam.addActionListener(new ActionListener()
     {
 
@@ -1191,7 +1191,7 @@ public class GAlignFrame extends JInternalFrame
 
     });
     JMenuItem loadTreeFam = new JMenuItem(
-            MessageManager.getString("treefam"));
+            MessageManager.getString("label.treefam"));
     loadTreeFam.addActionListener(new ActionListener()
     {
 
@@ -1205,7 +1205,7 @@ public class GAlignFrame extends JInternalFrame
     });
 
     JMenuItem loadTreeOfLife = new JMenuItem(
-            MessageManager.getString("tree_of_life"));
+            MessageManager.getString("label.tree_of_life"));
     loadTreeOfLife.addActionListener(new ActionListener()
     {
 
index d4b2c04..1a48a16 100644 (file)
@@ -104,6 +104,10 @@ import jalview.datamodel.features.FeatureMatcher;
 import jalview.datamodel.features.FeatureMatcherI;
 import jalview.datamodel.features.FeatureMatcherSet;
 import jalview.datamodel.features.FeatureMatcherSetI;
+import jalview.ext.archaeopteryx.AptxInit;
+import jalview.ext.treeviewer.TreeFrameI;
+import jalview.ext.treeviewer.TreeI;
+import jalview.ext.treeviewer.TreeViewerUtils;
 import jalview.ext.varna.RnaModel;
 import jalview.gui.AlignFrame;
 import jalview.gui.AlignViewport;
@@ -1276,9 +1280,35 @@ public class Jalview2XML
               object.getTree().add(tree);
             }
           }
+
         }
       }
     }
+    if (!storeDS && av.getCurrentExtTree() != null)
+    {
+      Set<TreeFrameI> externalTreeViews = TreeViewerUtils
+              .getActiveTreeViews()
+              .keySet();
+      for (TreeFrameI treeView : externalTreeViews)
+      {
+        TreeI tree = treeView.getTree();
+        try
+        {
+          tree.outputAsFile(new File("word"));
+          copyFileToJar(jout, "word", "aptx-test","Archeopteryx Tree Session");
+
+
+        } catch (IOException e)
+        {
+          // TODO Auto-generated catch block
+          e.printStackTrace();
+        }
+
+      }
+
+    }
+
+
 
     /*
      * save PCA viewers
@@ -4055,6 +4085,7 @@ public class Jalview2XML
     if (loadTreesAndStructures)
     {
       loadTrees(jalviewModel, view, af, av, ap);
+      loadExternalTrees(jprovider, jalviewModel, av);
       loadPCAViewers(jalviewModel, ap);
       loadPDBStructures(jprovider, jseqs, af, ap);
       loadRnaViewers(jprovider, jseqs, ap);
@@ -4062,6 +4093,27 @@ public class Jalview2XML
     // and finally return.
     return af;
   }
+    
+  private void loadExternalTrees(jarInputStreamProvider jprovider,
+          JalviewModel jms, AlignViewport av)
+  {
+    // TODO: allow more than one archeopteryx session per project
+    String treeFile = copyJarEntry(jprovider, "aptx-test", "aptx", null);
+    if (treeFile != null)
+    {
+    try
+    {
+      AptxInit.createInstancesFromFile(treeFile, av);
+    } catch (IOException e)
+    {
+      // TODO Auto-generated catch block
+      e.printStackTrace();
+      }
+    }
+    
+  }
+
+
 
   /**
    * Instantiate and link any saved RNA (Varna) viewers. The state of the Varna
@@ -4179,6 +4231,10 @@ public class Jalview2XML
 
         Tree tree = jm.getTree().get(t);
 
+        TreeFrameI externalViewer = AptxInit.createInstanceFromNhx(
+                tree.getTitle(), tree.getNewick(),
+                av);
+
         TreePanel tp = (TreePanel) retrieveExistingObj(tree.getId());
         if (tp == null)
         {
index 64c8e89..751f940 100644 (file)
@@ -125,11 +125,11 @@ public class AWTConsole extends WindowAdapter
 
     // Starting two seperate threads to read from the PipedInputStreams
     //
-    reader = new Thread(this, "AWTConsoleReader1Thread");
+    reader = new Thread(this, "AWTConsoleReader1");
     reader.setDaemon(true);
     reader.start();
     //
-    reader2 = new Thread(this, "AWTConsoleReader2Thread");
+    reader2 = new Thread(this, "AWTConsoleReader2");
     reader2.setDaemon(true);
     reader2.start();
 
@@ -150,7 +150,7 @@ public class AWTConsole extends WindowAdapter
     // We do it with a seperate Thread becasue we don't wan't to break a Thread
     // used by the Console.
     System.out.println("\nLets throw an error on this console");
-    errorThrower = new Thread(this, "AWTConsoleErrorLogThread");
+    errorThrower = new Thread(this, "AWTConsoleErrorLog");
     errorThrower.setDaemon(true);
     errorThrower.start();
   }
index 5337852..77a64e8 100755 (executable)
@@ -78,6 +78,9 @@ public class DBRefUtils
     canonicalSourceNameLookup.put("ensembl-tr", DBRefSource.ENSEMBL);
     canonicalSourceNameLookup.put("ensembl-gn", DBRefSource.ENSEMBL);
 
+    // TODO keep ? (in phyloviewer branch only)
+    canonicalSourceNameLookup.put("pfam", DBRefSource.PFAM);
+
     // guarantee we always have lowercase entries for canonical string lookups
     for (String k : canonicalSourceNameLookup.keySet())
     {
@@ -273,7 +276,7 @@ public class DBRefUtils
   static List<DBRefEntry> searchRefs(List<DBRefEntry> refs,
           DBRefEntry entry, DbRefComp comparator, int mode)
   {
-    List<DBRefEntry> rfs = new ArrayList<DBRefEntry>();
+    List<DBRefEntry> rfs = new ArrayList<>();
     if (refs == null || entry == null)
     {
       return rfs;
@@ -664,7 +667,7 @@ public class DBRefUtils
   public static List<DBRefEntry> searchRefsForSource(
           List<DBRefEntry> dbRefs, String source)
   {
-    List<DBRefEntry> matches = new ArrayList<DBRefEntry>();
+    List<DBRefEntry> matches = new ArrayList<>();
     if (dbRefs != null && source != null)
     {
       for (DBRefEntry dbref : dbRefs)
index 05fc1c6..dbbf8a0 100644 (file)
@@ -1119,7 +1119,7 @@ public final class MappingUtils
     }
     else
     {
-      jalview.bin.Cache.log.warn(
+      Console.warn(
               "Attempt to add duplicate entry detected for map with key: "
                       + key.toString() + " and value: " + value.toString());
     }
index d7ba417..b4e33c8 100644 (file)
@@ -45,6 +45,7 @@ import jalview.datamodel.Sequence;
 import jalview.datamodel.SequenceCollectionI;
 import jalview.datamodel.SequenceGroup;
 import jalview.datamodel.SequenceI;
+import jalview.ext.treeviewer.TreeI;
 import jalview.renderer.ResidueShader;
 import jalview.renderer.ResidueShaderI;
 import jalview.schemes.ColourSchemeI;
@@ -961,6 +962,7 @@ public abstract class AlignmentViewport
     changeSupport = null;
     ranges = null;
     currentTree = null;
+    currentExtTree = null;
     selectionGroup = null;
     colSel = null;
     setAlignment(null);
@@ -2913,6 +2915,8 @@ public abstract class AlignmentViewport
 
   protected TreeModel currentTree = null;
 
+  protected TreeI currentExtTree = null;
+
   @Override
   public boolean hasSearchResults()
   {
@@ -3096,4 +3100,14 @@ public abstract class AlignmentViewport
     return (alignment.getHiddenColumns().getVisContigsIterator(start, end,
             false));
   }
+  public TreeI getCurrentExtTree()
+  {
+    return currentExtTree;
+  }
+
+  public void setCurrentExtTree(TreeI externalTree)
+  {
+    currentExtTree = externalTree;
+  }
+
 }
index eb66016..00bd074 100644 (file)
@@ -233,7 +233,7 @@ public class DBRefFetcher implements Runnable
     }
     else
     {
-      new Thread(this).start();
+      new Thread(this,"FetchDBRef").start();
     }
   }
 
index 7bf5a97..1fe9495 100644 (file)
@@ -238,7 +238,7 @@ public class Jws2Discoverer implements Runnable, WSMenuEntryProviderI
 
       }
       qrys.add(squery);
-      new Thread(squery, "JabaQueryThread").start();
+      new Thread(squery, "JabaQuery").start();
     }
     boolean finished = true;
     do
@@ -458,7 +458,7 @@ public class Jws2Discoverer implements Runnable, WSMenuEntryProviderI
                   changeSupport.firePropertyChange("services",
                           new Vector<Jws2Instance>(), services);
                 };
-              }, "LoadPreferredServiceThread").start();
+              }, "LoadPreferredService").start();
             }
           });
         }
index e7324eb..eb92df9 100644 (file)
-package jalview.ext.archaeopteryx;
-
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertTrue;
-
-import jalview.analysis.NJTree;
-import jalview.analysis.TreeBuilder;
-import jalview.analysis.scoremodels.ScoreModels;
-import jalview.analysis.scoremodels.SimilarityParams;
-import jalview.api.analysis.ScoreModelI;
-import jalview.api.analysis.SimilarityParamsI;
-import jalview.bin.Jalview;
-import jalview.datamodel.Alignment;
-import jalview.datamodel.AlignmentI;
-import jalview.datamodel.Sequence;
-import jalview.datamodel.SequenceI;
-import jalview.gui.AlignViewport;
-
-import org.forester.archaeopteryx.MainFrame;
-import org.forester.archaeopteryx.TreePanel;
-import org.forester.phylogeny.Phylogeny;
-import org.testng.annotations.BeforeClass;
-import org.testng.annotations.Test;
-
-public class AptxJalviewSequenceTreeTest extends TreeViewTest
-{
-  TreeBuilder jalviewTree;
-
-  TreePanel treePanel;
-
-  Phylogeny tree;
-
-  MainFrame aptx;
-
-  Jalview jalview;
-  
-  @Override
-  @BeforeClass(alwaysRun = true)
-  public void setUpTree()
-  {
-    SequenceI seq1 = new Sequence("Seq1", "ABCDEFGHIJ");
-    SequenceI seq2 = new Sequence("Seq2", "ABCDEFTHIJ");
-    SequenceI seq3 = new Sequence("Seq3", "BCFWDHIJ");
-    SequenceI seq4 = new Sequence("Seq4", "WTHISTHIS");
-
-    AlignmentI al = new Alignment(
-            new SequenceI[]
-            { seq1, seq2, seq3, seq4 });
-    AlignViewport alignViewport = new AlignViewport(al);
-
-    ScoreModelI scoreModel = ScoreModels.getInstance().getBlosum62();
-    SimilarityParamsI similarityParams = new SimilarityParams(true, true,
-            true, false);
-
-    jalviewTree = new NJTree(alignViewport, scoreModel,
-            similarityParams);
-  }
-
-  @Override
-  @BeforeClass(dependsOnMethods = { "setUpTree" })
-  public void createTreeView()
-  {
-    treeView = AptxInit.createInstance(jalviewTree);
-    aptx = (MainFrame) treeView; // still pretty ugly
-
-    treePanel = aptx.getMainPanel().getCurrentTreePanel();
-    tree = treePanel.getPhylogeny();
-
-  }
-
-  @Override
-  public void testTreeLoaded()
-  {
-    assertTrue(tree != null);
-
-  }
-
-  @Override
-  public void testTreeTitle()
-  {
-    assertTrue(tree.getName().contains("Neighbour Joining Using BLOSUM62"));
-
-  }
-
-  @Override
-  public void testChildNodesCount()
-  {
-    assertEquals(
-            tree.getNode("Seq2").getParent().getNumberOfExternalNodes(), 2);
-
-  }
-
-  @Override
-  public void testExistingBranchName()
-  {
-    tree.getNode("Seq4");
-
-  }
-
-  @Override
-  public void testChildToParentBranchLength()
-  {
-    assertEquals(tree.getNode("Seq1").getDistanceToParent(), 5.25);
-
-  }
-
-  @Test(
-    groups = "Functional",
-    expectedExceptions = IllegalArgumentException.class)
-  public void testInvalidBranchName()
-  {
-    tree.getNode("I shouldn't exist");
-
-  }
-
-  @Override
-  public void testNodeToRootBranchLength()
-  {
-    assertEquals(tree.getNode("Seq3").calculateDistanceToRoot(), 19.13);
-
-  }
-
-  @Override
-  public void testDistantNodeToRootBranchLength()
-  {
-    assertEquals(tree.getNode("Seq2").calculateDistanceToRoot(),
-            3.75 + 35.75 + 19.13);
-
-  }
-
-
-
-
-}
+// package jalview.ext.archaeopteryx;
+//
+// import static org.testng.Assert.assertEquals;
+// import static org.testng.Assert.assertTrue;
+//
+// import jalview.analysis.NJTree;
+// import jalview.analysis.TreeBuilder;
+// import jalview.analysis.scoremodels.ScoreModels;
+// import jalview.analysis.scoremodels.SimilarityParams;
+// import jalview.api.analysis.ScoreModelI;
+// import jalview.api.analysis.SimilarityParamsI;
+// import jalview.bin.Jalview;
+// import jalview.datamodel.Alignment;
+// import jalview.datamodel.AlignmentI;
+// import jalview.datamodel.Sequence;
+// import jalview.datamodel.SequenceI;
+// import jalview.gui.AlignViewport;
+//
+// import org.forester.archaeopteryx.MainFrame;
+// import org.forester.archaeopteryx.TreePanel;
+// import org.forester.phylogeny.Phylogeny;
+// import org.testng.annotations.BeforeClass;
+// import org.testng.annotations.Test;
+//
+// public class AptxJalviewSequenceTreeTest extends TreeViewTest
+// {
+// TreeBuilder jalviewTree;
+//
+// TreePanel treePanel;
+//
+// Phylogeny tree;
+//
+// MainFrame aptx;
+//
+// Jalview jalview;
+//
+// @Override
+// @BeforeClass(alwaysRun = true)
+// public void setUpTree()
+// {
+// SequenceI seq1 = new Sequence("Seq1", "ABCDEFGHIJ");
+// SequenceI seq2 = new Sequence("Seq2", "ABCDEFTHIJ");
+// SequenceI seq3 = new Sequence("Seq3", "BCFWDHIJ");
+// SequenceI seq4 = new Sequence("Seq4", "WTHISTHIS");
+//
+// AlignmentI al = new Alignment(
+// new SequenceI[]
+// { seq1, seq2, seq3, seq4 });
+// AlignViewport alignViewport = new AlignViewport(al);
+//
+// ScoreModelI scoreModel = ScoreModels.getInstance().getBlosum62();
+// SimilarityParamsI similarityParams = new SimilarityParams(true, true,
+// true, false);
+//
+// jalviewTree = new NJTree(alignViewport, scoreModel,
+// similarityParams);
+// }
+//
+// @Override
+// @BeforeClass(dependsOnMethods = { "setUpTree" })
+// public void createTreeView()
+// {
+// treeView = AptxInit.createInstanceFromCalculation(jalviewTree);
+// aptx = (MainFrame) treeView; // still pretty ugly
+//
+// treePanel = aptx.getMainPanel().getCurrentTreePanel();
+// tree = treePanel.getPhylogeny();
+//
+// }
+//
+// @Override
+// public void testTreeLoaded()
+// {
+// assertTrue(tree != null);
+//
+// }
+//
+// @Override
+// public void testTreeTitle()
+// {
+// assertTrue(tree.getName().contains("Neighbour Joining Using BLOSUM62"));
+//
+// }
+//
+// @Override
+// public void testChildNodesCount()
+// {
+// assertEquals(
+// tree.getNode("Seq2").getParent().getNumberOfExternalNodes(), 2);
+//
+// }
+//
+// @Override
+// public void testExistingBranchName()
+// {
+// tree.getNode("Seq4");
+//
+// }
+//
+// @Override
+// public void testChildToParentBranchLength()
+// {
+// assertEquals(tree.getNode("Seq1").getDistanceToParent(), 5.25);
+//
+// }
+//
+// @Test(
+// groups = "Functional",
+// expectedExceptions = IllegalArgumentException.class)
+// public void testInvalidBranchName()
+// {
+// tree.getNode("I shouldn't exist");
+//
+// }
+//
+// @Override
+// public void testNodeToRootBranchLength()
+// {
+// assertEquals(tree.getNode("Seq3").calculateDistanceToRoot(), 19.13);
+//
+// }
+//
+// @Override
+// public void testDistantNodeToRootBranchLength()
+// {
+// assertEquals(tree.getNode("Seq2").calculateDistanceToRoot(),
+// 3.75 + 35.75 + 19.13);
+//
+// }
+//
+//
+//
+//
+// }
index 9d62eb1..4163e3d 100644 (file)
-package jalview.ext.archaeopteryx;
-
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertTrue;
-
-import org.forester.archaeopteryx.MainFrame;
-import org.forester.archaeopteryx.TreePanel;
-import org.forester.phylogeny.Phylogeny;
-import org.forester.phylogeny.PhylogenyNode;
-import org.testng.annotations.BeforeClass;
-import org.testng.annotations.Test;
-
-public class AptxPhylogenyTreeTest extends TreeViewTest
-{
-  final Phylogeny inputTree = new Phylogeny();
-
-  final PhylogenyNode rootNode = new PhylogenyNode("root");
-
-  final PhylogenyNode ancestor1Node = new PhylogenyNode("ancestor 1");
-
-  final PhylogenyNode ancestor2Node = new PhylogenyNode("leaf 2");
-
-  final PhylogenyNode leaf1aNode = new PhylogenyNode("leaf 1a");
-
-  final PhylogenyNode leaf1bNode = new PhylogenyNode("leaf 1b");
-
-  final PhylogenyNode leaf1cNode = new PhylogenyNode("leaf 1c");
-
-  Phylogeny tree;
-
-  TreePanel treePanel;
-
-  MainFrame aptx;
-
-
-  @Override
-  @BeforeClass(alwaysRun = true)
-  public void setUpTree()
-  {
-    ancestor1Node.addAsChild(leaf1aNode);
-    ancestor1Node.addAsChild(leaf1bNode);
-    ancestor1Node.addAsChild(leaf1cNode);
-
-    rootNode.addAsChild(ancestor1Node);
-    rootNode.addAsChild(ancestor2Node);
-
-    leaf1aNode.setDistanceToParent(2);
-    leaf1bNode.setDistanceToParent(3);
-    leaf1cNode.setDistanceToParent(4);
-
-    ancestor1Node.setDistanceToParent(36);
-    ancestor2Node.setDistanceToParent(42);
-
-    inputTree.setName("test");
-    inputTree.setRoot(rootNode);
-    inputTree.setRooted(true);
-
-  }
-
-  @Override
-  @BeforeClass(dependsOnMethods = { "setUpJalview", "setUpTree" })
-  public void createTreeView()
-  {
-    treeView = AptxInit.createUnboundInstance(inputTree);
-    aptx = (MainFrame) treeView; // pretty ugly
-    treePanel = aptx.getMainPanel().getCurrentTreePanel();
-    tree = treePanel.getPhylogeny();
-  }
-
-
-
-  @Test(groups = "Functional")
-  public void testMainPanelExists()
-  {
-    assertTrue(aptx.getMainPanel() != null);
-  }
-
-  @Test(groups = "Functional")
-  public void testTreePanelExists()
-  {
-    assertTrue(treePanel != null);
-  }
-
-  @Override
-  public void testTreeTitle()
-  {
-    assertTrue(tree.getName().equals("test"));
-
-  }
-
-  @Test(
-    groups = "Functional",
-    expectedExceptions = IllegalArgumentException.class)
-  public void testInvalidBranchName()
-  {
-    tree.getNode("I shouldn't exist");
-
-  }
-
-  @Override
-  public void testExistingBranchName()
-  {
-    tree.getNode("leaf 2");
-
-  }
-
-  @Override
-  public void testTreeLoaded()
-  {
-    assertTrue(tree != null);
-  }
-
-  @Override
-  public void testChildNodesCount()
-  {
-    assertEquals(tree.getNode("ancestor 1").getNumberOfExternalNodes(), 3);
-
-  }
-
-  @Override
-  public void testChildToParentBranchLength()
-  {
-    assertEquals(tree.getNode("leaf 1a").getDistanceToParent(), 2.0);
-
-  }
-
-  @Override
-  public void testNodeToRootBranchLength()
-  {
-    assertEquals(tree.getNode("leaf 2").getDistanceToParent(), 42.0);
-
-  }
-
-  @Override
-  public void testDistantNodeToRootBranchLength()
-  {
-    assertEquals(tree.getNode("leaf 1c").calculateDistanceToRoot(),
-            4.0 + 36.0);
-
-  }
-
-
-
-
-
-
-
-}
+// package jalview.ext.archaeopteryx;
+//
+// import static org.testng.Assert.assertEquals;
+// import static org.testng.Assert.assertTrue;
+//
+// import jalview.gui.Desktop;
+//
+// import org.forester.archaeopteryx.Archaeopteryx;
+// import org.forester.archaeopteryx.MainFrame;
+// import org.forester.archaeopteryx.TreePanel;
+// import org.forester.phylogeny.Phylogeny;
+// import org.forester.phylogeny.PhylogenyNode;
+// import org.testng.annotations.BeforeClass;
+// import org.testng.annotations.Test;
+//
+// public class AptxPhylogenyTreeTest extends TreeViewTest
+// {
+// final Phylogeny inputTree = new Phylogeny();
+//
+// final PhylogenyNode rootNode = new PhylogenyNode("root");
+//
+// final PhylogenyNode ancestor1Node = new PhylogenyNode("ancestor 1");
+//
+// final PhylogenyNode ancestor2Node = new PhylogenyNode("leaf 2");
+//
+// final PhylogenyNode leaf1aNode = new PhylogenyNode("leaf 1a");
+//
+// final PhylogenyNode leaf1bNode = new PhylogenyNode("leaf 1b");
+//
+// final PhylogenyNode leaf1cNode = new PhylogenyNode("leaf 1c");
+//
+// Phylogeny tree;
+//
+// TreePanel treePanel;
+//
+// MainFrame aptx;
+//
+//
+// @Override
+// @BeforeClass(alwaysRun = true)
+// public void setUpTree()
+// {
+// ancestor1Node.addAsChild(leaf1aNode);
+// ancestor1Node.addAsChild(leaf1bNode);
+// ancestor1Node.addAsChild(leaf1cNode);
+//
+// rootNode.addAsChild(ancestor1Node);
+// rootNode.addAsChild(ancestor2Node);
+//
+// leaf1aNode.setDistanceToParent(2);
+// leaf1bNode.setDistanceToParent(3);
+// leaf1cNode.setDistanceToParent(4);
+//
+// ancestor1Node.setDistanceToParent(36);
+// ancestor2Node.setDistanceToParent(42);
+//
+// inputTree.setName("test");
+// inputTree.setRoot(rootNode);
+// inputTree.setRooted(true);
+//
+// }
+//
+// @Override
+// @BeforeClass(dependsOnMethods = { "setUpJalview", "setUpTree" })
+// public void createTreeView()
+// {
+// treeView = Archaeopteryx.createApplication(inputTree);
+// aptx = (MainFrame) treeView; // pretty ugly
+// treePanel = aptx.getMainPanel().getCurrentTreePanel();
+// tree = treePanel.getPhylogeny();
+//
+// Desktop.addInternalFrame(aptx, "Archaeopteryx", 500, 500);
+//
+// }
+//
+//
+//
+// @Test(groups = "Functional")
+// public void testMainPanelExists()
+// {
+// assertTrue(aptx.getMainPanel() != null);
+// }
+//
+// @Test(groups = "Functional")
+// public void testTreePanelExists()
+// {
+// assertTrue(treePanel != null);
+// }
+//
+// @Override
+// public void testTreeTitle()
+// {
+// assertTrue(tree.getName().equals("test"));
+//
+// }
+//
+// @Test(
+// groups = "Functional",
+// expectedExceptions = IllegalArgumentException.class)
+// public void testInvalidBranchName()
+// {
+// tree.getNode("I shouldn't exist");
+//
+// }
+//
+// @Override
+// public void testExistingBranchName()
+// {
+// tree.getNode("leaf 2");
+//
+// }
+//
+// @Override
+// public void testTreeLoaded()
+// {
+// assertTrue(tree != null);
+// }
+//
+// @Override
+// public void testChildNodesCount()
+// {
+// assertEquals(tree.getNode("ancestor 1").getNumberOfExternalNodes(), 3);
+//
+// }
+//
+// @Override
+// public void testChildToParentBranchLength()
+// {
+// assertEquals(tree.getNode("leaf 1a").getDistanceToParent(), 2.0);
+//
+// }
+//
+// @Override
+// public void testNodeToRootBranchLength()
+// {
+// assertEquals(tree.getNode("leaf 2").getDistanceToParent(), 42.0);
+//
+// }
+//
+// @Override
+// public void testDistantNodeToRootBranchLength()
+// {
+// assertEquals(tree.getNode("leaf 1c").calculateDistanceToRoot(),
+// 4.0 + 36.0);
+//
+// }
+//
+//
+//
+//
+//
+//
+//
+// }
index 4bbe140..87c32e4 100644 (file)
@@ -3,11 +3,10 @@ package jalview.ext.archaeopteryx;
 import static org.testng.Assert.assertTrue;
 
 import jalview.bin.Jalview;
+import jalview.ext.treeviewer.TreeFrameI;
 import jalview.gui.Desktop;
 import jalview.gui.JvOptionPane;
 
-import javax.swing.JInternalFrame;
-
 import org.testng.annotations.BeforeClass;
 import org.testng.annotations.Test;
 
@@ -15,7 +14,7 @@ public abstract class TreeViewTest
 {
   Jalview jalview;
 
-  JInternalFrame treeView;
+  TreeFrameI treeView;
 
   @BeforeClass(alwaysRun = true)
   public void setUpJvOptionPane()
index 8a6d688..56f8652 100644 (file)
@@ -255,7 +255,14 @@ public class FreeUpMemoryTest
     af.openTreePcaDialog();
     CalculationChooser dialog = af.alignPanel.getCalculationDialog();
     dialog.openPcaPanel("BLOSUM62", dialog.getSimilarityParameters(true));
-    dialog.createTree("BLOSUM62",dialog.getSimilarityParameters(false));
+    try
+    {
+      dialog.createTree("BLOSUM62", dialog.getSimilarityParameters(false));
+    } catch (IOException e)
+    {
+      // TODO Auto-generated catch block
+      e.printStackTrace();
+    }
 
     /*
      * wait until Tree and PCA have been computed