1 package jalview.ext.archaeopteryx;
3 import jalview.datamodel.ColumnSelection;
4 import jalview.datamodel.HiddenColumns;
5 import jalview.datamodel.SequenceGroup;
6 import jalview.datamodel.SequenceI;
7 import jalview.ext.treeviewer.ExternalTreeViewerBindingI;
8 import jalview.gui.PaintRefresher;
9 import jalview.structure.SelectionSource;
10 import jalview.structure.StructureSelectionManager;
11 import jalview.viewmodel.AlignmentViewport;
13 import java.awt.event.ActionEvent;
14 import java.awt.event.InputEvent;
15 import java.awt.event.MouseEvent;
16 import java.util.HashSet;
17 import java.util.List;
20 import javax.swing.JTabbedPane;
21 import javax.swing.SwingUtilities;
22 import javax.swing.event.ChangeEvent;
23 import javax.swing.event.ChangeListener;
25 import org.forester.archaeopteryx.MainFrame;
26 import org.forester.phylogeny.PhylogenyMethods;
27 import org.forester.phylogeny.PhylogenyNode;
30 * Class for binding the Archaeopteryx tree viewer to the Jalview alignment that
31 * it originates from, meaning that selecting sequences in the tree viewer also
32 * selects them in the alignment view and vice versa.
34 * @author kjvanderheide
37 public final class JalviewBinding
38 implements ExternalTreeViewerBindingI<PhylogenyNode>
40 private org.forester.archaeopteryx.TreePanel treeView;
42 private AlignmentViewport parentAvport;
44 private JTabbedPane treeTabs;
46 private final StructureSelectionManager ssm;
48 private Map<SequenceI, PhylogenyNode> sequencesBoundToNodes;
50 private Map<PhylogenyNode, SequenceI> nodesBoundToSequences;
54 * @param archaeopteryx
56 * @param jalviewAlignmentViewport
57 * alignment viewport from which the tree was calculated.
59 * @param alignMappedToNodes
60 * map with sequences used to calculate the tree and matching tree
61 * nodes as key, value pair respectively.
63 * @param nodesMappedToAlign
64 * map with tree nodes and matching sequences used to calculate the
65 * tree as key, value pair respectively.
67 public JalviewBinding(final MainFrame archaeopteryx,
68 final AlignmentViewport jalviewAlignmentViewport,
69 final Map<SequenceI, PhylogenyNode> alignMappedToNodes,
70 final Map<PhylogenyNode, SequenceI> nodesMappedToAlign)
72 // deal with/prohibit null values here as that will cause problems
73 parentAvport = jalviewAlignmentViewport;
74 sequencesBoundToNodes = alignMappedToNodes;
75 nodesBoundToSequences = nodesMappedToAlign;
77 treeView = archaeopteryx.getMainPanel().getCurrentTreePanel();
78 treeTabs = archaeopteryx.getMainPanel().getTabbedPane();
79 ssm = parentAvport.getStructureSelectionManager();
81 // archaeopteryx.getMainPanel().getControlPanel().setColorBranches(true);
83 ssm.addSelectionListener(this);
84 treeView.addMouseListener(this);
85 PaintRefresher.Register(treeView, parentAvport.getSequenceSetId());
88 treeTabs.addChangeListener(new ChangeListener()
92 public void stateChanged(ChangeEvent e)
95 SwingUtilities.invokeLater(new Runnable()
100 * Resend the selection to the tree view when tabs get switched, this
101 * has to be buried in invokeLater as Forester first resets the tree
102 * view on switching tabs, without invokeLater this would get called
103 * before Forester resets which would nullify the selection
107 parentAvport.sendSelection();
119 public void actionPerformed(ActionEvent e)
124 public void mouseClicked(MouseEvent e)
129 public void mousePressed(final MouseEvent e)
131 showNodeSelectionOnAlign(e);
135 public void mouseReleased(MouseEvent e)
140 public void mouseEntered(MouseEvent e)
145 public void mouseExited(MouseEvent e)
151 public void selection(final SequenceGroup seqsel,
152 final ColumnSelection colsel, final HiddenColumns hidden,
153 final SelectionSource source)
155 if (source == parentAvport) // check if source is alignment from where the
158 treeView.setFoundNodes0(
159 new HashSet<Long>(seqsel.getSequences().size()));
161 for (SequenceI selectedSequence : seqsel.getSequences())
163 PhylogenyNode matchingNode = sequencesBoundToNodes.get(selectedSequence);
164 if (matchingNode != null)
166 treeView.getFoundNodes0().add(matchingNode.getId());
170 PaintRefresher.Refresh(treeView, parentAvport.getSequenceSetId());
179 public void showNodeSelectionOnAlign(final MouseEvent e)
181 final PhylogenyNode node = treeView.findNode(e.getX(), e.getY());
184 if ((e.getModifiers() & InputEvent.SHIFT_MASK) == 0) // clear previous
185 // selection if shift
188 parentAvport.setSelectionGroup(null);
191 if (node.isInternal())
193 showMatchingChildSequences(node);
198 showMatchingSequence(node);
208 public void showMatchingSequence(final PhylogenyNode nodeToMatch)
210 SequenceI matchingSequence = nodesBoundToSequences.get(nodeToMatch);
211 if (matchingSequence != null)
213 treeSelectionChanged(matchingSequence);
214 parentAvport.sendSelection();
215 PaintRefresher.Refresh(treeView, parentAvport.getSequenceSetId());
220 public void showMatchingChildSequences(final PhylogenyNode parentNode)
222 List<PhylogenyNode> childNodes = PhylogenyMethods
223 .getAllDescendants(parentNode);
225 for (PhylogenyNode childNode : childNodes)
227 // childNode.getBranchData().setBranchColor(new BranchColor(Color.BLUE));
229 SequenceI matchingSequence = nodesBoundToSequences.get(childNode);
230 if (matchingSequence != null)
232 treeSelectionChanged(matchingSequence);
236 parentAvport.sendSelection();
237 PaintRefresher.Refresh(treeView, parentAvport.getSequenceSetId());
241 * Refactored from TreeCanvas.
244 * of the node selected in the tree viewer.
247 public void treeSelectionChanged(final SequenceI sequence)
249 SequenceGroup selected = parentAvport.getSelectionGroup();
251 if (selected == null)
253 selected = new SequenceGroup();
254 parentAvport.setSelectionGroup(selected);
257 selected.setEndRes(parentAvport.getAlignment().getWidth() - 1);
258 selected.addOrRemove(sequence, true);
262 public AlignmentViewport getParentAvport()
267 public void setParentAvport(final AlignmentViewport parentAvport)
269 this.parentAvport = parentAvport;