4
* (c) 2002-2005 BEAST Development Core Team
6
* This package may be distributed under the
7
* Lesser Gnu Public Licence (LGPL)
10
package figtree.treeviewer;
12
import jebl.evolution.graphs.Node;
13
import jebl.evolution.taxa.Taxon;
14
import jebl.evolution.trees.*;
15
import figtree.treeviewer.decorators.Decorator;
16
import figtree.treeviewer.painters.LabelPainter;
17
import figtree.treeviewer.painters.ScalePainter;
18
import figtree.treeviewer.painters.ScaleGridPainter;
19
import figtree.treeviewer.painters.NodeBarPainter;
20
import figtree.treeviewer.treelayouts.TreeLayout;
21
import jam.panels.StatusProvider;
25
import java.awt.print.PageFormat;
26
import java.awt.print.PrinterException;
28
import java.util.List;
29
import java.util.regex.PatternSyntaxException;
32
* @author Andrew Rambaut
33
* @version $Id: DefaultTreeViewer.java 822 2007-10-26 13:50:26Z rambaut $
35
public class DefaultTreeViewer extends TreeViewer {
36
private final static double MAX_ZOOM = 20;
37
private final static double MAX_VERTICAL_EXPANSION = 20;
40
* Creates new TreeViewer
42
public DefaultTreeViewer() {
43
setLayout(new BorderLayout());
45
this.treePane = new TreePane();
46
treePane.setAutoscrolls(true); //enable synthetic drag events
48
treePane.addTreePaneListener(new TreePaneListener() {
49
public void treePaneSettingsChanged() {
50
fireTreeSettingsChanged();
54
JScrollPane scrollPane = new JScrollPane(treePane, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
55
scrollPane.setMinimumSize(new Dimension(150, 150));
57
scrollPane.setBorder(null);
58
viewport = scrollPane.getViewport();
60
add(scrollPane, BorderLayout.CENTER);
62
// This overrides MouseListener and MouseMotionListener to allow selection in the TreePane -
63
// It installs itself within the constructor.
64
treePaneSelector = new TreePaneSelector(treePane);
66
treePaneRollOver = new TreePaneRollOver(treePane);
72
public void setTree(Tree tree) {
78
public void setTrees(Collection<? extends Tree> trees) {
80
for (Tree tree : trees) {
86
public void addTree(Tree tree) {
89
if (treePane.getTipLabelPainter() != null) {
90
treePane.getTipLabelPainter().setupAttributes(trees);
93
if (treePane.getBranchLabelPainter() != null) {
94
treePane.getBranchLabelPainter().setupAttributes(trees);
97
if (treePane.getNodeLabelPainter() != null) {
98
treePane.getNodeLabelPainter().setupAttributes(trees);
101
if (treePane.getNodeBarPainter() != null) {
102
treePane.getNodeBarPainter().setupAttributes(trees);
106
public void addTrees(Collection<? extends Tree> trees) {
107
int count = getTreeCount();
108
for (Tree tree : trees) {
114
public List<Tree> getTrees() {
118
public Tree getCurrentTree() {
119
return trees.get(currentTreeIndex);
122
public List<Tree> getTreesAsViewed() {
123
List<Tree> treeAsDisplayed = new ArrayList<Tree>();
124
for (Tree originalTree : trees) {
125
treeAsDisplayed.add(treePane.constructTransformedTree((RootedTree)originalTree));
127
return treeAsDisplayed;
130
public int getCurrentTreeIndex() {
131
return currentTreeIndex;
134
public int getTreeCount() {
135
if (trees == null) return 0;
139
public StatusProvider getStatusProvider() {
140
return treePaneRollOver;
143
public void showTree(int index) {
144
Tree tree = trees.get(index);
145
if (tree instanceof RootedTree) {
146
treePane.setTree((RootedTree)tree);
148
treePane.setTree(Utils.rootTheTree(tree));
151
currentTreeIndex = index;
155
public void showNextTree() {
156
if (currentTreeIndex < trees.size() - 1) {
157
showTree(currentTreeIndex + 1);
161
public void showPreviousTree() {
162
if (currentTreeIndex > 0) {
163
showTree(currentTreeIndex - 1);
167
public void setTreeLayout(TreeLayout treeLayout) {
168
treePane.setTreeLayout(treeLayout);
169
fireTreeSettingsChanged();
172
private boolean zoomPending = false;
173
private double zoom = 0.0, verticalExpansion = 0.0;
175
public void setZoom(double zoom) {
176
this.zoom = zoom * MAX_ZOOM;
180
public void setVerticalExpansion(double verticalExpansion) {
181
this.verticalExpansion = verticalExpansion * MAX_VERTICAL_EXPANSION;
185
public boolean verticalExpansionAllowed() {
186
return !treePane.maintainAspectRatio();
189
public void setTimeScale(TimeScale timeScale) {
190
treePane.setTimeScale(timeScale);
193
private void refreshZoom() {
194
setZoom(zoom, zoom + verticalExpansion);
197
private void setZoom(double xZoom, double yZoom) {
199
Dimension viewportSize = viewport.getViewSize();
200
Point position = viewport.getViewPosition();
202
Dimension extentSize = viewport.getExtentSize();
203
double w = extentSize.getWidth() * (1.0 + xZoom);
204
double h = extentSize.getHeight() * (1.0 + yZoom);
206
Dimension newSize = new Dimension((int) w, (int) h);
207
treePane.setPreferredSize(newSize);
209
double cx = position.getX() + (0.5 * extentSize.getWidth());
210
double cy = position.getY() + (0.5 * extentSize.getHeight());
212
double rx = ((double) newSize.getWidth()) / viewportSize.getWidth();
213
double ry = ((double) newSize.getHeight()) / viewportSize.getHeight();
215
double px = (cx * rx) - (extentSize.getWidth() / 2.0);
216
double py = (cy * ry) - (extentSize.getHeight() / 2.0);
218
Point newPosition = new Point((int) px, (int) py);
219
viewport.setViewPosition(newPosition);
220
treePane.revalidate();
223
public boolean hasSelection() {
224
return treePane.hasSelection();
227
public Set<Node> getSelectedNodes() {
228
return treePane.getSelectedNodes();
231
public Set<Node> getSelectedTips() {
232
return treePane.getSelectedTips();
235
public void selectTaxa(String attributeName, TextSearchType searchType, String searchString, boolean caseSensitive) {
236
if (treePane.getTree() == null) {
240
treePane.clearSelection();
242
String query = searchString;
244
if (searchType != TextSearchType.REG_EX) {
245
query = (caseSensitive ? searchString : searchString.toUpperCase());
246
query = query.trim();
249
Tree tree = treePane.getTree();
251
for (Node node : tree.getExternalNodes()) {
252
Taxon taxon = tree.getTaxon(node);
254
if (attributeName == null) {
255
Object target = taxon.getName();
256
if (matchesItem(searchType, target, query, caseSensitive)) {
257
treePane.addSelectedTip(node);
260
for (String name : taxon.getAttributeNames()) {
261
target = taxon.getAttribute(name);
262
if (matchesItem(searchType, target, query, caseSensitive)) {
263
treePane.addSelectedTip(node);
269
if (attributeName.equals("!name")) {
270
target = taxon.getName();
272
target = taxon.getAttribute(attributeName);
274
if (matchesItem(searchType, target, query, caseSensitive)) {
275
treePane.addSelectedTip(node);
281
public void selectNodes(String attributeName, TextSearchType searchType, String searchString, boolean caseSensitive) {
282
treePane.clearSelection();
284
String query = searchString;
286
if (searchType != TextSearchType.REG_EX) {
287
query = (caseSensitive ? searchString : searchString.toUpperCase());
288
query = query.trim();
291
Tree tree = treePane.getTree();
293
for (Node node : tree.getNodes()) {
294
if (attributeName == null) {
295
for (String name : node.getAttributeNames()) {
296
Object target = node.getAttribute(name);
297
if (matchesItem(searchType, target, query, caseSensitive)) {
298
treePane.addSelectedNode(node);
303
Object target = node.getAttribute(attributeName);
304
if (matchesItem(searchType, target, query, caseSensitive)) {
305
treePane.addSelectedNode(node);
311
private boolean matchesItem(TextSearchType searchType, Object object, String query, boolean caseSensitive) {
313
if (object != null) {
314
String target = (caseSensitive ? object.toString() : object.toString().toUpperCase());
315
switch (searchType) {
317
if (target.contains(query)) {
322
if (target.startsWith(query)) {
327
if (target.endsWith(query)) {
332
if (target.equals(query)) {
338
if (target.matches(query)) {
341
} catch (PatternSyntaxException pse) {
350
public void selectTaxa(String attributeName, NumberSearchType searchType, Number searchValue) {
351
treePane.clearSelection();
353
RootedTree tree = treePane.getTree();
355
for (Node node : tree.getExternalNodes()) {
357
if (attributeName.equals("!length")) {
358
value = tree.getLength(node);
359
} else if (attributeName.equals("!height")) {
360
value = tree.getHeight(node);
362
Taxon taxon = tree.getTaxon(node);
363
value = taxon.getAttribute(attributeName);
365
if (matchesItem(value, searchType, searchValue)) {
366
treePane.addSelectedTip(node);
371
public void selectNodes(String attributeName, NumberSearchType searchType, Number searchValue) {
372
treePane.clearSelection();
374
RootedTree tree = treePane.getTree();
376
for (Node node : tree.getNodes()) {
378
if (attributeName.equals("!length")) {
379
value = tree.getLength(node);
380
} else if (attributeName.equals("!height")) {
381
value = tree.getHeight(node);
383
value = node.getAttribute(attributeName);
385
if (matchesItem(value, searchType, searchValue)) {
386
treePane.addSelectedNode(node);
391
public void selectTaxa(Collection<String> taxonNames) {
392
treePane.clearSelection();
394
RootedTree tree = treePane.getTree();
396
for (Node node : tree.getExternalNodes()) {
398
if (taxonNames.contains(tree.getTaxon(node).getName())) {
399
treePane.addSelectedTip(node);
404
private boolean matchesItem(Object item, NumberSearchType searchType, Number searchValue) {
405
if (item != null && item instanceof Number) {
407
Number value = (Number)item;
409
switch (searchType) {
411
if (value.equals(searchValue)) {
415
case EQUALS_OR_GREATER_THAN:
416
if (value.doubleValue() >= searchValue.doubleValue()) {
420
case EQUALS_OR_LESS_THAN:
421
if (value.doubleValue() <= searchValue.doubleValue()) {
426
if (value.doubleValue() > searchValue.doubleValue()) {
431
if (value.doubleValue() < searchValue.doubleValue()) {
436
if (!searchValue.equals(value)) {
445
public void cartoonSelectedNodes() {
446
treePane.cartoonSelectedNodes();
447
fireTreeSettingsChanged();
450
public void collapseSelectedNodes() {
451
treePane.collapseSelectedNodes();
452
fireTreeSettingsChanged();
455
public void clearCollapsedNodes() {
456
treePane.clearCollapsedNodes();
457
fireTreeSettingsChanged();
460
public void hilightSelectedNodes(Color color) {
461
treePane.hilightSelectedNodes(color);
462
fireTreeSettingsChanged();
465
public void clearHilighting() {
466
treePane.clearHilightedNodes();
467
fireTreeSettingsChanged();
470
public void rerootOnSelectedBranch() {
471
treePane.rerootOnSelectedBranch();
472
fireTreeSettingsChanged();
475
public void clearRooting() {
476
treePane.clearRooting();
477
fireTreeSettingsChanged();
480
public void rotateSelectedNode() {
481
treePane.rotateSelectedNode();
482
fireTreeSettingsChanged();
485
public void clearRotations() {
486
treePane.clearSelectedNodeRotations();
487
fireTreeSettingsChanged();
490
public void annotateSelectedNodes(String name, Object value) {
491
treePane.annotateSelectedNodes(name, value);
492
fireTreeSettingsChanged();
495
public void annotateSelectedTips(String name, Object value) {
496
treePane.annotateSelectedTips(name, value);
497
fireTreeSettingsChanged();
500
public void clearAnnotation(String name) {
501
treePane.clearSelectedNodeAnnotation(name);
502
treePane.clearSelectedTipAnnotation(name);
503
fireTreeSettingsChanged();
506
public void clearColouring() {
507
treePane.clearSelectedNodeAnnotation("!color");
508
treePane.clearSelectedTipAnnotation("!color");
509
fireTreeSettingsChanged();
512
public void selectAll() {
513
if (treePaneSelector.getSelectionMode() == TreePaneSelector.SelectionMode.TAXA) {
514
treePane.selectAllTaxa();
516
treePane.selectAllNodes();
520
public void clearSelectedTaxa() {
521
treePane.clearSelection();
524
public void addTreeSelectionListener(TreeSelectionListener treeSelectionListener) {
525
treePane.addTreeSelectionListener(treeSelectionListener);
528
public void removeTreeSelectionListener(TreeSelectionListener treeSelectionListener) {
529
treePane.removeTreeSelectionListener(treeSelectionListener);
532
public void setSelectionMode(TreePaneSelector.SelectionMode selectionMode) {
533
TreePaneSelector.SelectionMode oldSelectionMode = treePaneSelector.getSelectionMode();
535
if (selectionMode == oldSelectionMode) {
539
if (oldSelectionMode == TreePaneSelector.SelectionMode.TAXA) {
540
treePane.selectNodesFromSelectedTips();
541
} else if (selectionMode == TreePaneSelector.SelectionMode.TAXA) {
542
treePane.selectTipsFromSelectedNodes();
543
} else if (selectionMode == TreePaneSelector.SelectionMode.CLADE) {
544
treePane.selectCladesFromSelectedNodes();
546
treePaneSelector.setSelectionMode(selectionMode);
549
public void setDragMode(TreePaneSelector.DragMode dragMode) {
550
treePaneSelector.setDragMode(dragMode);
553
// A load of deligated method calls through to treePane (which is now hidden outside the package).
554
public void setTipLabelPainter(LabelPainter<Node> tipLabelPainter) {
555
treePane.setTipLabelPainter(tipLabelPainter);
556
tipLabelPainter.setupAttributes(trees);
560
public void setNodeLabelPainter(LabelPainter<Node> nodeLabelPainter) {
561
treePane.setNodeLabelPainter(nodeLabelPainter);
562
nodeLabelPainter.setupAttributes(trees);
565
public void setNodeBarPainter(NodeBarPainter nodeBarPainter) {
566
treePane.setNodeBarPainter(nodeBarPainter);
567
nodeBarPainter.setupAttributes(trees);
570
public void setBranchLabelPainter(LabelPainter<Node> branchLabelPainter) {
571
treePane.setBranchLabelPainter(branchLabelPainter);
572
branchLabelPainter.setupAttributes(trees);
575
public void addScalePainter(ScalePainter scalePainter) {
576
treePane.addScalePainter(scalePainter);
579
public void removeScalePainter(ScalePainter scalePainter) {
580
treePane.removeScalePainter(scalePainter);
583
public void setScaleGridPainter(ScaleGridPainter scaleGridPainter) {
584
treePane.setScaleGridPainter(scaleGridPainter);
587
public void setBranchDecorator(Decorator branchDecorator) {
588
treePane.setBranchDecorator(branchDecorator);
591
public void setBranchColouringDecorator(String branchColouringAttribute, Decorator branchColouringDecorator) {
592
treePane.setBranchColouringDecorator(branchColouringAttribute, branchColouringDecorator);
595
public void setNodeBackgroundDecorator(Decorator nodeBackgroundDecorator) {
596
treePane.setNodeBackgroundDecorator(nodeBackgroundDecorator);
599
public void setSelectionColor(Color selectionColor) {
600
treePane.setSelectionColor(selectionColor);
603
public Paint getSelectionPaint() {
604
return treePane.getSelectionPaint();
607
public void setBranchStroke(BasicStroke branchStroke) {
608
treePane.setBranchStroke(branchStroke);
611
public boolean isTransformBranchesOn() {
612
return treePane.isTransformBranchesOn();
615
public TransformedRootedTree.Transform getBranchTransform() {
616
return treePane.getBranchTransform();
619
public void setTransformBranchesOn(boolean transformBranchesOn) {
620
treePane.setTransformBranchesOn(transformBranchesOn);
623
public void setBranchTransform(TransformedRootedTree.Transform transform) {
624
treePane.setBranchTransform(transform);
627
public boolean isOrderBranchesOn() {
628
return treePane.isOrderBranchesOn();
631
public SortedRootedTree.BranchOrdering getBranchOrdering() {
632
return treePane.getBranchOrdering();
635
public void setOrderBranchesOn(boolean orderBranchesOn) {
636
treePane.setOrderBranchesOn(orderBranchesOn);
639
public void setBranchOrdering(SortedRootedTree.BranchOrdering branchOrdering) {
640
treePane.setBranchOrdering(branchOrdering);
643
public boolean isRootingOn() {
644
return treePane.isRootingOn();
647
public TreePane.RootingType getRootingType() {
648
return treePane.getRootingType();
651
public void setRootingOn(boolean rootingOn) {
652
treePane.setRootingOn(rootingOn);
655
public void setRootingType(TreePane.RootingType rootingType) {
656
treePane.setRootingType(rootingType);
659
public void setToolMode(TreePaneSelector.ToolMode toolMode) {
660
treePaneSelector.setToolMode(toolMode);
663
public JComponent getContentPane() {
667
public void paint(Graphics g) {
675
public int print(Graphics g, PageFormat pageFormat, int pageIndex) throws PrinterException {
676
return treePane.print(g, pageFormat, pageIndex);
679
public void addTreeViewerListener(TreeViewerListener listener) {
680
listeners.add(listener);
683
public void removeTreeViewerListener(TreeViewerListener listener) {
684
listeners.remove(listener);
687
public void fireTreeChanged() {
688
for (TreeViewerListener listener : listeners) {
689
listener.treeChanged();
693
public void fireTreeSettingsChanged() {
694
for (TreeViewerListener listener : listeners) {
695
listener.treeSettingsChanged();
699
private java.util.List<TreeViewerListener> listeners = new ArrayList<TreeViewerListener>();
701
private List<Tree> trees = new ArrayList<Tree>();
702
private int currentTreeIndex = 0;
704
protected TreePane treePane;
705
protected TreePaneSelector treePaneSelector;
706
protected TreePaneRollOver treePaneRollOver;
708
protected JViewport viewport;
b'\\ No newline at end of file'