JAL-1953 first pass of adding javadoc, some methods renamed
[jalview.git] / src / jalview / ext / archaeopteryx / JalviewBinding.java
index 2bacfd5..f0c2866 100644 (file)
@@ -1,13 +1,24 @@
 package jalview.ext.archaeopteryx;
 
+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.ext.treeviewer.ExternalTreeViewerBindingI;
+import jalview.ext.treeviewer.LoadedTreeSequenceAssociation;
+import jalview.ext.treeviewer.TreeFrameI;
+import jalview.ext.treeviewer.TreeI;
+import jalview.ext.treeviewer.TreeNodeI;
+import jalview.ext.treeviewer.TreePanelI;
+import jalview.ext.treeviewer.TreeViewerBindingI;
+import jalview.ext.treeviewer.TreeViewerUtils;
 import jalview.gui.AlignViewport;
+import jalview.gui.AlignmentPanel;
 import jalview.gui.Desktop;
 import jalview.gui.JvOptionPane;
 import jalview.gui.PaintRefresher;
@@ -21,7 +32,7 @@ import jalview.util.MessageManager;
 import jalview.viewmodel.AlignmentViewport;
 
 import java.awt.Color;
-import java.awt.Graphics;
+import java.awt.Rectangle;
 import java.awt.event.ActionEvent;
 import java.awt.event.InputEvent;
 import java.awt.event.MouseEvent;
@@ -31,17 +42,9 @@ 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.archaeopteryx.TreePanelUtil;
-import org.forester.phylogeny.Phylogeny;
-import org.forester.phylogeny.PhylogenyMethods;
-import org.forester.phylogeny.PhylogenyNode;
-import org.forester.phylogeny.data.BranchColor;
+import javax.swing.event.InternalFrameAdapter;
+import javax.swing.event.InternalFrameEvent;
 
 /**
  * Class for binding the Archaeopteryx tree viewer to the Jalview alignment that
@@ -52,19 +55,27 @@ import org.forester.phylogeny.data.BranchColor;
  *
  */
 public final class JalviewBinding
-        implements ExternalTreeViewerBindingI<PhylogenyNode>
+        implements TreeViewerBindingI
 {
-  private org.forester.archaeopteryx.TreePanel treeView;
+  private final TreeFrameI aptxFrame;
 
-  private AlignmentViewport parentAvport;
+  private TreePanelI treeView;
 
-  private final JTabbedPane treeTabs;
+  private AlignmentViewport parentAvport;
 
   private final StructureSelectionManager ssm;
 
-  private Map<SequenceI, PhylogenyNode> sequencesBoundToNodes;
+  private Map<SequenceI, TreeNodeI> sequencesBoundToNodes;
+
+  private Map<TreeNodeI, SequenceI> nodesBoundToSequences;
+
+  private float rootX;
+
+  private float furthestNodeX;
+
+  private int nrTreeGroups = 0;
 
-  private Map<PhylogenyNode, SequenceI> nodesBoundToSequences;
+  private boolean applyToAllViews = false;
 
   /**
    * 
@@ -81,71 +92,130 @@ public final class JalviewBinding
    *          map with tree nodes and matching sequences used to calculate the
    *          tree as key, value pair respectively.
    */
-  public JalviewBinding(final MainFrame archaeopteryx,
+  public JalviewBinding(final TreeFrameI archaeopteryx,
           final AlignmentViewport jalviewAlignmentViewport,
-          final Map<SequenceI, PhylogenyNode> alignMappedToNodes,
-          final Map<PhylogenyNode, SequenceI> nodesMappedToAlign)
+          final Map<SequenceI, TreeNodeI> alignMappedToNodes,
+          final Map<TreeNodeI, SequenceI> nodesMappedToAlign)
   {
 
-    if (archaeopteryx.getMainPanel().getTabbedPane().getTabCount() > 1)
+    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.getMainPanel().getCurrentTreePanel();
-    treeTabs = archaeopteryx.getMainPanel().getTabbedPane();
+    treeView = archaeopteryx.getTreePanel();
     ssm = parentAvport.getStructureSelectionManager();
     
+    aptxFrame.setViewBinding(this);
     ssm.addSelectionListener(this);
     treeView.addMouseListener(this);
-    PaintRefresher.Register(treeView, parentAvport.getSequenceSetId());
-
+    treeView.registerWithPaintRefresher(
+            parentAvport.getSequenceSetId());
 
-    treeTabs.addChangeListener(new ChangeListener()
+    aptxFrame.addFrameListener(new InternalFrameAdapter()
     {
 
       @Override
-      public void stateChanged(ChangeEvent e)
+      public void internalFrameClosed(InternalFrameEvent 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());
-
-          }
-        });
-
+        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
@@ -159,7 +229,8 @@ public final class JalviewBinding
        */
       public void run()
       {
-        final PhylogenyNode node = treeView.findNode(e.getX(), e.getY());
+        final TreeNodeI node = treeView.findNode(e.getX(),
+                e.getY());
         if (node != null)
         {
           if ((e.getModifiers() & InputEvent.SHIFT_MASK) == 0) // clear previous
@@ -176,7 +247,9 @@ public final class JalviewBinding
 
           partitionTree(e.getX());
       }
-        PaintRefresher.Refresh(treeView, parentAvport.getSequenceSetId());
+        treeView.notifyPaintRefresher(parentAvport.getSequenceSetId(),
+                false, false);
+        treeView.repaint();
 
 
 
@@ -215,20 +288,32 @@ public final class JalviewBinding
     if (source == parentAvport) // check if source is alignment from where the
     // tree originates
     {
-      treeView.setFoundNodes0(
+      treeView.setMatchingNodes(
               new HashSet<Long>(seqsel.getSequences().size()));
 
+
       for (SequenceI selectedSequence : seqsel.getSequences())
       {
-        PhylogenyNode matchingNode = sequencesBoundToNodes.get(selectedSequence);
+        TreeNodeI matchingNode = sequencesBoundToNodes
+                .get(selectedSequence);
         if (matchingNode != null)
         {
-          treeView.getFoundNodes0().add(matchingNode.getId());
+          treeView.getMatchingNodes().add(matchingNode.getId());
+
+
+          // if (!matchingNode.getBranchData().isHasBranchColor())
+          // {
+          // // Color foundNodesColour = treeView.getTreeColorSet()
+          // // .getFoundColor0();
+          // // matchingNode.getBranchData()
+          // // .setBranchColor(new BranchColor(foundNodesColour));
+          //
+          // }
+
         }
 
       }
 
-
       treeView.repaint();
     }
 
@@ -240,36 +325,35 @@ public final class JalviewBinding
    */
   public void partitionTree(final int x)
   {
-    Phylogeny tree = treeView.getPhylogeny();
+    TreeI tree = treeView.getTree();
 
     if (!tree.isEmpty())
     {
-      double longestBranch = tree.calculateHeight(true);
-      if (longestBranch != 0)
-      {
+      // 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();
 
-        // double relativeTreeWidth = longestBranch / viewWidth;
-        // MOVE
-        Graphics g = treeView.getGraphics();
-        int panelHeight = treeView.getHeight();
-        g.drawLine(x, 0, x, panelHeight);
+      // 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());
 
-        float rootX = tree.getRoot().getXcoord();
-        double threshold = ((double) x - rootX) / longestBranch;
-        List<PhylogenyNode> foundNodes = getNodesAboveThreshold(threshold,
-                longestBranch, tree.getRoot());
 
-      }
     }
 
 
   }
 
-  public List<PhylogenyNode> getNodesAboveThreshold(double threshold,
-          double treeLength, PhylogenyNode node)
+  public List<TreeNodeI> getNodesAboveThreshold(float threshold,
+          TreeNodeI node)
   {
 
-    List<PhylogenyNode> nodesAboveThreshold = new ArrayList<>();
+    List<TreeNodeI> nodesAboveThreshold = new ArrayList<>();
 
     parentAvport.setSelectionGroup(null);
     parentAvport.getAlignment().deleteAllGroups();
@@ -282,7 +366,7 @@ public final class JalviewBinding
     }
 
 
-    colourNodesAboveThreshold(nodesAboveThreshold, threshold, treeLength,
+    colourNodesAboveThreshold(nodesAboveThreshold, threshold,
             node);
     return nodesAboveThreshold;
 
@@ -297,157 +381,153 @@ public final class JalviewBinding
    * @param node
    * @return
    */
-  private List<PhylogenyNode> colourNodesAboveThreshold(
-          List<PhylogenyNode> nodeList, double threshold,
-          double treeLength, PhylogenyNode node)
+  private List<TreeNodeI> colourNodesAboveThreshold(
+          List<TreeNodeI> nodeList, float threshold,
+          TreeNodeI node)
   {
-    // could also use PhylogenyMethods.getAllDescendants
-    for (PhylogenyNode childNode : node.getDescendants())
+
+    for (TreeNodeI childNode : node.getDirectChildren())
     {
-      childNode.getBranchData()
-              .setBranchColor(new BranchColor(Color.black));
-      double nodeCutoff = childNode.calculateDistanceToRoot() / treeLength;
+      childNode.setBranchColor(Color.black);
+      float nodeCutoff = (childNode.getXcoord() - rootX)
+              / (furthestNodeX - rootX);
 
       if (nodeCutoff > threshold)
       {
         nodeList.add(childNode);
 
-        Color randomColor = new Color((int) (Math.random() * 255),
+        Color randomColour = new Color((int) (Math.random() * 255),
                 (int) (Math.random() * 255), (int) (Math.random() * 255));
-        TreePanelUtil.colorizeSubtree(childNode,
-                new BranchColor(randomColor));
+        childNode.setBranchColor(randomColour);
 
-        List<PhylogenyNode> descendantNodes = childNode
-                .getAllExternalDescendants();
-        List<SequenceI> descendantSeqs = new ArrayList<>();
-        for (PhylogenyNode descNode : descendantNodes)
+        List<SequenceI> groupSeqs = new ArrayList<>();
+        SequenceI seq = nodesBoundToSequences.get(childNode);
+        if (seq != null)
         {
-          descendantSeqs.add(nodesBoundToSequences.get(descNode));
+          groupSeqs.add(seq);
+          parentAvport.setSequenceColour(seq, randomColour);
         }
 
-
-        SequenceGroup sg = new SequenceGroup(descendantSeqs, null, null,
-                true, true, false, 0,
-                parentAvport.getAlignment().getWidth() - 1);
-
-        ColourSchemeI cs = null;
-        if (parentAvport.getGlobalColourScheme() != null)
+        List<TreeNodeI> descendantNodes = childNode
+                .getAllDescendants();
+        // .forEach instead?
+        for (TreeNodeI descNode : descendantNodes)
         {
-          if (parentAvport.getGlobalColourScheme() instanceof UserColourScheme)
-          {
-            cs = new UserColourScheme(
-                    ((UserColourScheme) parentAvport.getGlobalColourScheme())
-                            .getColours());
-
-          }
-          else
+          seq = nodesBoundToSequences.get(descNode);
+          if (seq != null)
           {
-            cs = ColourSchemeProperty.getColourScheme(sg, ColourSchemeProperty
-                    .getColourName(parentAvport.getGlobalColourScheme()));
+            groupSeqs.add(seq);
+            parentAvport.setSequenceColour(seq, randomColour);
           }
+
+          descNode.setBranchColor(randomColour);
         }
-        sg.setColourScheme(cs);
-        sg.getGroupColourScheme().setThreshold(
-                parentAvport.getResidueShading().getThreshold(),
-                parentAvport.isIgnoreGapsConsensus());
-        // sg.recalcConservation();
-        sg.setName("Tree Group:" + sg.hashCode());
-        sg.setIdColour(randomColor);
-
-        if (parentAvport.getGlobalColourScheme() != null
-                && parentAvport.getResidueShading().conservationApplied())
+
+        if (groupSeqs != null)
         {
-          Conservation c = new Conservation("Group", sg.getSequences(null),
-                  sg.getStartRes(), sg.getEndRes());
-          c.calculate();
-          c.verdict(false, parentAvport.getConsPercGaps());
-          sg.cs.setConservation(c);
-        }
+          nrTreeGroups++;
+          groupThresholdSequences(groupSeqs, randomColour);
+        }}
+
+      else
+      {
+        colourNodesAboveThreshold(nodeList, threshold, childNode);
+      }
+    }
+
+    for (AlignmentPanel associatedPanel : getAssociatedPanels())
+    {
 
-        parentAvport.getAlignment().addGroup(new SequenceGroup(sg));
-        // TODO can we push all of the below into AlignViewportI?
-        final AlignViewportI codingComplement = parentAvport
+        associatedPanel.updateAnnotation();
+
+        final AlignViewportI codingComplement = associatedPanel.getAlignViewport()
                 .getCodingComplement();
         if (codingComplement != null)
         {
-          SequenceGroup mappedGroup = MappingUtils.mapSequenceGroup(sg,
-                  parentAvport,
-                  codingComplement);
-          if (mappedGroup.getSequences().size() > 0)
-          {
-            codingComplement.getAlignment().addGroup(mappedGroup);
-            for (SequenceI seq : mappedGroup.getSequences())
-            {
-              codingComplement.setSequenceColour(seq,
-                      randomColor.brighter());
-            }
-          }
+          // 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
       {
-      colourNodesAboveThreshold(nodeList, threshold, treeLength,
-                childNode);
+        cs = ColourSchemeProperty.getColourScheme(treeGroup,
+                ColourSchemeProperty.getColourName(
+                        parentAvport.getGlobalColourScheme()));
       }
 
     }
-    // GROSS
-    ((AlignViewport) parentAvport).getAlignPanel().updateAnnotation();
-
-    final AlignViewportI codingComplement = parentAvport
-            .getCodingComplement();
-    if (codingComplement != null)
-    {
-      ((AlignViewport) codingComplement).getAlignPanel().updateAnnotation();
-    }
+    treeGroup.setColourScheme(cs);
+    treeGroup.getGroupColourScheme().setThreshold(
+            parentAvport.getResidueShading().getThreshold(),
+            parentAvport.isIgnoreGapsConsensus());
 
+    treeGroup.setName("Tree Group " + nrTreeGroups);
+    treeGroup.setIdColour(groupColour);
 
-    return nodeList;
-  }
+    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());
+          }
+        }
+      }
 
+    }
 
-  // public List<PhylogenyNode> groupNodes(float threshold, PhylogenyNode root,
-  // double treeHeight)
-  // {
-  // List<PhylogenyNode> groups = new ArrayList<>();
-  // _groupNodes(groups, root, threshold, treeHeight);
-  // System.out.println(groups);
-  // return groups;
-  // }
-  //
-  // protected void _groupNodes(List<PhylogenyNode> groups, PhylogenyNode nd,
-  // float threshold, double treeHeight)
-  // {
-  // if (nd == null)
-  // {
-  // return;
-  // }
-  //
-  // if ((nd.calculateDistanceToRoot() / treeHeight) > threshold)
-  // {
-  // groups.add(nd);
-  // }
-  // else
-  // {
-  // for (PhylogenyNode childNode : nd.getDescendants())
-  // {
-  // _groupNodes(groups, childNode, threshold, treeHeight);
-  // }
-  // }
-  // }
-  //
+  }
 
 
-  /**
-   * may or may not need an extra repaint on the alignment view (check what kira
-   * does)
-   */
   @Override
-  public void showNodeSelectionOnAlign(final PhylogenyNode node)
+  public void showNodeSelectionOnAlign(final TreeNodeI node)
   {
 
       if (node.isInternal())
@@ -468,13 +548,13 @@ public final class JalviewBinding
 
 
   @Override
-  public void showMatchingSequence(final PhylogenyNode nodeToMatch)
+  public void showMatchingSequence(final TreeNodeI nodeToMatch)
   {
     SequenceI matchingSequence = nodesBoundToSequences.get(nodeToMatch);
     if (matchingSequence != null)
     {
       long nodeId = nodeToMatch.getId();
-      addOrRemoveInSet(treeView.getFoundNodes0(), nodeId);
+      addOrRemoveInSet(treeView.getMatchingNodes(), nodeId);
       treeSelectionChanged(matchingSequence);
       parentAvport.sendSelection();
 
@@ -482,21 +562,20 @@ public final class JalviewBinding
   }
 
   @Override
-  public void showMatchingChildSequences(final PhylogenyNode parentNode)
+  public void showMatchingChildSequences(final TreeNodeI parentNode)
   {
-    List<PhylogenyNode> childNodes = PhylogenyMethods
-            .getAllDescendants(parentNode);
+    // redundancy here, Forester already iterates through tree to get all
+    // descendants
+    List<TreeNodeI> childNodes = parentNode.getAllDescendants();
 
 
-    for (PhylogenyNode childNode : childNodes)
+    for (TreeNodeI 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);
+        addOrRemoveInSet(treeView.getMatchingNodes(), nodeId);
 
         treeSelectionChanged(matchingSequence);
 
@@ -508,12 +587,7 @@ public final class JalviewBinding
 
   }
 
-  /**
-   * Refactored from TreeCanvas.
-   * 
-   * @param sequence
-   *          of the node selected in the tree viewer.
-   */
+
   @Override
   public void treeSelectionChanged(final SequenceI sequence)
   {
@@ -532,81 +606,90 @@ public final class JalviewBinding
     }
 
   }
-  public void sortByTree_actionPerformed() {
-    // parentAvport.mirrorCommand(command, undo, ssm, source);
 
-    // alignFrame
-    // .addHistoryItem(sortAlignmentIn(treeCanvas.ap));
-    
-  }
-  
+  @Override
+  public void sortByTree_actionPerformed()
+  {
 
-  /**
-   * 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.parentAvport.getAlignPanel()));
-  // }
-  // parentAvport.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(parentAvport.getSequenceSetId()))
-  // {
-  // // ensure all the alignFrames refresh their GI after adding an undo item
-  // ap.alignFrame.updateEditMenuBar();
-  // }
-  // }
+    // 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
   // {
-  // treeCanvas.ap.alignFrame
-  // .addHistoryItem(sortAlignmentIn(treeCanvas.ap));
+  // 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
    * 
@@ -635,6 +718,26 @@ public final class JalviewBinding
   {
     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;
+  }
+
+
 }