import java.awt.event.InputEvent;
import java.awt.event.MouseEvent;
import java.util.HashSet;
+import java.util.List;
import java.util.Map;
import org.forester.archaeopteryx.MainFrame;
+import org.forester.phylogeny.PhylogenyMethods;
import org.forester.phylogeny.PhylogenyNode;
-public class JalviewAptxBinding implements JalviewTreeViewerBindingI
+/**
+ * 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 JalviewAptxBinding implements JalviewTreeViewerBindingI
{
- org.forester.archaeopteryx.TreePanel treeView;
+ private org.forester.archaeopteryx.TreePanel treeView;
- AlignmentViewport parentAvport;
+ private AlignmentViewport parentAvport;
- final StructureSelectionManager ssm;
+ private final StructureSelectionManager ssm;
- Map<SequenceI, PhylogenyNode> sequencesBoundToNodes;
+ private Map<SequenceI, PhylogenyNode> sequencesBoundToNodes;
- Map<PhylogenyNode, SequenceI> nodesBoundToSequences;
+ 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 JalviewAptxBinding(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;
ssm.addSelectionListener(this);
treeView.addMouseListener(this);
PaintRefresher.Register(treeView, parentAvport.getSequenceSetId());
+
}
@Override
/**
* If a node is selected in the tree panel this method highlights the
- * corresponding sequence in the Jalview alignment view.
+ * corresponding sequence in the Jalview alignment view. If an internal node
+ * is selected all child sequences get highlighted as well.
*/
@Override
public void showNodeSelectionOnAlign(final MouseEvent e)
final PhylogenyNode node = treeView.findNode(e.getX(), e.getY());
if (node != null)
{
- SequenceI matchingSequence = nodesBoundToSequences.get(node);
- if (matchingSequence != null)
+ if ((e.getModifiers() & InputEvent.SHIFT_MASK) == 0) // clear previous
+ // selection if shift
+ // IS NOT pressed
{
+ parentAvport.setSelectionGroup(null);
+ }
- if ((e.getModifiers() & InputEvent.SHIFT_MASK) != 0) // shift is pressed
- // (so multiple nodes
- // can be selected)
- {
- // something?
+ if (node.isInternal())
+ {
+ showMatchingChildSequences(node);
- }
- else
- {
- parentAvport.setSelectionGroup(null); // reset selection if shift
- // isn't
- // pressed
- }
+ }
+ else
+ {
+ showMatchingSequence(node);
- treeSelectionChanged(matchingSequence);
- parentAvport.sendSelection(); // not actually needed?
- PaintRefresher.Refresh(treeView, parentAvport.getSequenceSetId());
+ }
+ }
+ }
- }
+
+
+
+ public void showMatchingSequence(final PhylogenyNode nodeToMatch)
+ {
+ SequenceI matchingSequence = nodesBoundToSequences.get(nodeToMatch);
+ if (matchingSequence != null)
+ {
+ treeSelectionChanged(matchingSequence);
+ parentAvport.sendSelection();
+ PaintRefresher.Refresh(treeView, parentAvport.getSequenceSetId());
}
+ }
+ public void showMatchingChildSequences(final PhylogenyNode parentNode)
+ {
+ final List<PhylogenyNode> childNodes = PhylogenyMethods
+ .getAllDescendants(parentNode);
+ for (PhylogenyNode childNode : childNodes)
+ {
+ SequenceI matchingSequence = nodesBoundToSequences.get(childNode);
+ if (matchingSequence != null)
+ {
+ treeSelectionChanged(matchingSequence);
+ }
+ }
+
+ parentAvport.sendSelection();
+ PaintRefresher.Refresh(treeView, parentAvport.getSequenceSetId());
}
/**
- * Refactored from TreeCanvas
+ * Refactored from TreeCanvas.
*
* @param sequence
+ * of the node selected in the tree viewer.
*/
+ @Override
public void treeSelectionChanged(final SequenceI sequence)
{
SequenceGroup selected = parentAvport.getSelectionGroup();