1 /* 2 * DefaultTreeViewer.java 3 * 4 * Copyright (C) 2006-2014 Andrew Rambaut 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License 8 * as published by the Free Software Foundation; either version 2 9 * of the License, or (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19 */ 20 21 package figtree.treeviewer; 22 23 import figtree.treeviewer.painters.*; 24 import jebl.evolution.graphs.Node; 25 import jebl.evolution.taxa.Taxon; 26 import jebl.evolution.trees.*; 27 import figtree.treeviewer.decorators.Decorator; 28 import figtree.treeviewer.treelayouts.TreeLayout; 29 import jam.panels.StatusProvider; 30 31 import javax.swing.*; 32 import java.awt.*; 33 import java.awt.print.PageFormat; 34 import java.awt.print.PrinterException; 35 import java.util.*; 36 import java.util.List; 37 import java.util.regex.PatternSyntaxException; 38 39 /** 40 * @author Andrew Rambaut 41 * @version $Id$ 42 * 43 * $HeadURL$ 44 * 45 * $LastChangedBy$ 46 * $LastChangedDate$ 47 * $LastChangedRevision$ 48 */ 49 public class DefaultTreeViewer extends TreeViewer { 50 private final static double ZOOM_SCALE = 0.02; 51 private final static double VERTICAL_EXPANSION_SCALE = 0.02; 52 private final static double ZOOM_POWER = 1.2; 53 DefaultTreeViewer()54 public DefaultTreeViewer() { 55 this(null); 56 } 57 58 /** 59 * Creates new TreeViewer 60 */ DefaultTreeViewer(JFrame frame)61 public DefaultTreeViewer(JFrame frame) { 62 this.frame = frame; 63 64 setLayout(new BorderLayout()); 65 66 this.treePane = new TreePane(); 67 treePane.setAutoscrolls(true); //enable synthetic drag events 68 69 treePane.addTreePaneListener(new TreePaneListener() { 70 public void treePaneSettingsChanged() { 71 fireTreeSettingsChanged(); 72 } 73 }); 74 75 JScrollPane scrollPane = new JScrollPane(treePane, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS); 76 scrollPane.setMinimumSize(new Dimension(150, 150)); 77 78 scrollPane.setBorder(null); 79 viewport = scrollPane.getViewport(); 80 81 add(scrollPane, BorderLayout.CENTER); 82 83 // This overrides MouseListener and MouseMotionListener to allow selection in the TreePane - 84 // It installs itself within the constructor. 85 treePaneSelector = new TreePaneSelector(treePane); 86 treePaneRollOver = new TreePaneRollOver(treePane); 87 88 setFocusable(true); 89 90 } 91 setTree(Tree tree)92 public void setTree(Tree tree) { 93 trees.clear(); 94 addTree(tree); 95 showTree(0); 96 } 97 setTrees(Collection<? extends Tree> trees)98 public void setTrees(Collection<? extends Tree> trees) { 99 this.trees.clear(); 100 for (Tree tree : trees) { 101 addTree(tree); 102 } 103 showTree(0); 104 } 105 addTree(Tree tree)106 public void addTree(Tree tree) { 107 this.trees.add(tree); 108 109 // if (treePane.getTipLabelPainter() != null) { 110 // treePane.getTipLabelPainter().setupAttributes(trees); 111 // } 112 // 113 // if (treePane.getBranchLabelPainter() != null) { 114 // treePane.getBranchLabelPainter().setupAttributes(trees); 115 // } 116 // 117 // if (treePane.getNodeLabelPainter() != null) { 118 // treePane.getNodeLabelPainter().setupAttributes(trees); 119 // } 120 // 121 // if (treePane.getNodeBarPainter() != null) { 122 // treePane.getNodeBarPainter().setupAttributes(trees); 123 // } 124 // 125 // if (treePane.getLegendPainter() != null) { 126 // treePane.getLegendPainter().setupAttributes(trees); 127 // } 128 } 129 addTrees(Collection<? extends Tree> trees)130 public void addTrees(Collection<? extends Tree> trees) { 131 int count = getTreeCount(); 132 for (Tree tree : trees) { 133 addTree(tree); 134 } 135 showTree(count); 136 } 137 getTrees()138 public List<Tree> getTrees() { 139 return trees; 140 } 141 getCurrentTree()142 public Tree getCurrentTree() { 143 // return trees.get(currentTreeIndex); 144 return treePane.getTree(); 145 } 146 getTreesAsViewed()147 public List<Tree> getTreesAsViewed() { 148 List<Tree> treeAsDisplayed = new ArrayList<Tree>(); 149 for (Tree originalTree : trees) { 150 treeAsDisplayed.add(treePane.constructTransformedTree((RootedTree)originalTree)); 151 } 152 return treeAsDisplayed; 153 } 154 getSelectedSubtree()155 public RootedTree getSelectedSubtree() { 156 return treePane.getSelectedSubtree(); 157 } 158 getCurrentTreeIndex()159 public int getCurrentTreeIndex() { 160 return currentTreeIndex; 161 } 162 getTreeCount()163 public int getTreeCount() { 164 if (trees == null) return 0; 165 return trees.size(); 166 } 167 getStatusProvider()168 public StatusProvider getStatusProvider() { 169 return treePaneRollOver; 170 } 171 showTree(int index)172 public void showTree(int index) { 173 if (isRootingOn() && getRootingType() == TreePane.RootingType.USER_ROOTING) { 174 JOptionPane.showMessageDialog(frame, "Cannot switch trees when user rooting option is on.\n" + 175 "Turn this option off to switch trees", 176 "Unable to switch trees", 177 JOptionPane.ERROR_MESSAGE); 178 return; 179 } 180 181 Tree tree = trees.get(index); 182 if (tree instanceof RootedTree) { 183 treePane.setTree((RootedTree)tree); 184 } else { 185 treePane.setTree(Utils.rootTheTree(tree)); 186 } 187 188 currentTreeIndex = index; 189 fireTreeChanged(); 190 } 191 showNextTree()192 public void showNextTree() { 193 if (currentTreeIndex < trees.size() - 1) { 194 showTree(currentTreeIndex + 1); 195 } 196 } 197 showPreviousTree()198 public void showPreviousTree() { 199 if (currentTreeIndex > 0) { 200 showTree(currentTreeIndex - 1); 201 } 202 } 203 setTreeLayout(TreeLayout treeLayout)204 public void setTreeLayout(TreeLayout treeLayout) { 205 treePane.setTreeLayout(treeLayout); 206 fireTreeSettingsChanged(); 207 } 208 209 private boolean zoomPending = false; 210 private double zoom = 0.0; 211 private double verticalExpansion = 0.0; 212 setZoom(double zoom)213 public void setZoom(double zoom) { 214 double n = Math.max(treePane.getTree().getTaxa().size(), 50); 215 this.zoom = Math.pow(zoom * n * ZOOM_SCALE, ZOOM_POWER); 216 // this.zoom = zoom * MAX_ZOOM; 217 refreshZoom(); 218 } 219 setVerticalExpansion(double verticalExpansion)220 public void setVerticalExpansion(double verticalExpansion) { 221 double n = Math.max(treePane.getTree().getTaxa().size(), 50); 222 this.verticalExpansion = Math.pow(verticalExpansion * n * VERTICAL_EXPANSION_SCALE, ZOOM_POWER); 223 // this.verticalExpansion = verticalExpansion * MAX_VERTICAL_EXPANSION; 224 refreshZoom(); 225 } 226 verticalExpansionAllowed()227 public boolean verticalExpansionAllowed() { 228 return !treePane.maintainAspectRatio(); 229 } 230 setTimeScale(TimeScale timeScale)231 public void setTimeScale(TimeScale timeScale) { 232 treePane.setTimeScale(timeScale); 233 } 234 refreshZoom()235 private void refreshZoom() { 236 setZoom(zoom, zoom + verticalExpansion); 237 } 238 setZoom(double xZoom, double yZoom)239 private void setZoom(double xZoom, double yZoom) { 240 241 Dimension viewportSize = viewport.getViewSize(); 242 Point position = viewport.getViewPosition(); 243 244 Dimension extentSize = viewport.getExtentSize(); 245 double w = extentSize.getWidth() * (1.0 + xZoom); 246 double h = extentSize.getHeight() * (1.0 + yZoom); 247 248 Dimension newSize = new Dimension((int) w, (int) h); 249 treePane.setPreferredSize(newSize); 250 251 double cx = position.getX() + (0.5 * extentSize.getWidth()); 252 double cy = position.getY() + (0.5 * extentSize.getHeight()); 253 254 double rx = ((double) newSize.getWidth()) / viewportSize.getWidth(); 255 double ry = ((double) newSize.getHeight()) / viewportSize.getHeight(); 256 257 double px = (cx * rx) - (extentSize.getWidth() / 2.0); 258 double py = (cy * ry) - (extentSize.getHeight() / 2.0); 259 260 Point newPosition = new Point((int) px, (int) py); 261 viewport.setViewPosition(newPosition); 262 treePane.revalidate(); 263 } 264 hasSelection()265 public boolean hasSelection() { 266 return treePane.hasSelection(); 267 } 268 getSelectedNodes()269 public Set<Node> getSelectedNodes() { 270 return treePane.getSelectedNodes(); 271 } 272 getSelectedTips()273 public Set<Node> getSelectedTips() { 274 return treePane.getSelectedTips(); 275 } 276 getSelectedTaxa()277 public Set<Taxon> getSelectedTaxa() { 278 return treePane.getSelectedTaxa(); 279 } 280 281 /** 282 * Select taxa with a search string matching the currently displayed attribute 283 * @param searchType 284 * @param searchString 285 * @param caseSensitive 286 */ selectTaxa(TextSearchType searchType, String searchString, boolean caseSensitive)287 public void selectTaxa(TextSearchType searchType, String searchString, boolean caseSensitive) { 288 String attributeName = "!name"; 289 LabelPainter lp = treePane.getTipLabelPainter(); 290 if (lp != null && lp.isVisible() && lp.getDisplayAttribute() != null) { 291 attributeName = lp.getDisplayAttribute(); 292 } 293 294 selectTaxa(attributeName, searchType, searchString, caseSensitive); 295 296 scrollToSelectedTips(); 297 } 298 selectTaxa(String attributeName, TextSearchType searchType, String searchString, boolean caseSensitive)299 public void selectTaxa(String attributeName, TextSearchType searchType, String searchString, boolean caseSensitive) { 300 if (treePane.getTree() == null) { 301 return; 302 } 303 304 treePane.clearSelection(); 305 306 String query = searchString; 307 308 if (searchType != TextSearchType.REG_EX) { 309 query = (caseSensitive ? searchString : searchString.toUpperCase()); 310 query = query.trim(); 311 } 312 313 Tree tree = treePane.getTree(); 314 315 for (Node node : tree.getExternalNodes()) { 316 Taxon taxon = tree.getTaxon(node); 317 318 if (attributeName == null) { 319 Object target = taxon.getName(); 320 if (matchesItem(searchType, target, query, caseSensitive)) { 321 treePane.addSelectedTip(node); 322 break; 323 } 324 for (String name : taxon.getAttributeNames()) { 325 target = taxon.getAttribute(name); 326 if (matchesItem(searchType, target, query, caseSensitive)) { 327 treePane.addSelectedTip(node); 328 break; 329 } 330 } 331 } else { 332 Object target; 333 if (attributeName.equals("!name")) { 334 target = taxon.getName(); 335 } else { 336 target = taxon.getAttribute(attributeName); 337 if (target == null) { 338 // if we can't find the attribute on the taxon, try the node 339 target = node.getAttribute(attributeName); 340 } 341 } 342 if (matchesItem(searchType, target, query, caseSensitive)) { 343 treePane.addSelectedTip(node); 344 } 345 } 346 } 347 } 348 selectNodes(String attributeName, TextSearchType searchType, String searchString, boolean caseSensitive)349 public void selectNodes(String attributeName, TextSearchType searchType, String searchString, boolean caseSensitive) { 350 treePane.clearSelection(); 351 352 String query = searchString; 353 354 if (searchType != TextSearchType.REG_EX) { 355 query = (caseSensitive ? searchString : searchString.toUpperCase()); 356 query = query.trim(); 357 } 358 359 Tree tree = treePane.getTree(); 360 361 for (Node node : tree.getNodes()) { 362 if (attributeName == null) { 363 for (String name : node.getAttributeNames()) { 364 Object target = node.getAttribute(name); 365 if (matchesItem(searchType, target, query, caseSensitive)) { 366 treePane.addSelectedNode(node); 367 break; 368 } 369 } 370 } else { 371 Object target = node.getAttribute(attributeName); 372 if (matchesItem(searchType, target, query, caseSensitive)) { 373 treePane.addSelectedNode(node); 374 } 375 } 376 } 377 } 378 matchesItem(TextSearchType searchType, Object object, String query, boolean caseSensitive)379 private boolean matchesItem(TextSearchType searchType, Object object, String query, boolean caseSensitive) { 380 381 if (object != null) { 382 String target = (caseSensitive ? object.toString() : object.toString().toUpperCase()); 383 switch (searchType) { 384 case CONTAINS: 385 if (target.contains(query)) { 386 return true; 387 } 388 break; 389 case STARTS_WITH: 390 if (target.startsWith(query)) { 391 return true; 392 } 393 break; 394 case ENDS_WITH: 395 if (target.endsWith(query)) { 396 return true; 397 } 398 break; 399 case MATCHES: 400 if (target.equals(query)) { 401 return true; 402 } 403 break; 404 case REG_EX: 405 try { 406 if (target.matches(query)) { 407 return true; 408 } 409 } catch (PatternSyntaxException pse) { 410 // ignore 411 } 412 break; 413 } 414 } 415 return false; 416 } 417 selectTaxa(String attributeName, NumberSearchType searchType, Number searchValue)418 public void selectTaxa(String attributeName, NumberSearchType searchType, Number searchValue) { 419 treePane.clearSelection(); 420 421 RootedTree tree = treePane.getTree(); 422 423 for (Node node : tree.getExternalNodes()) { 424 Object value = null; 425 if (attributeName.equals("!length")) { 426 value = tree.getLength(node); 427 } else if (attributeName.equals("!height")) { 428 value = tree.getHeight(node); 429 } else { 430 Taxon taxon = tree.getTaxon(node); 431 value = taxon.getAttribute(attributeName); 432 } 433 if (matchesItem(value, searchType, searchValue)) { 434 treePane.addSelectedTip(node); 435 } 436 } 437 } 438 selectNodes(String attributeName, NumberSearchType searchType, Number searchValue)439 public void selectNodes(String attributeName, NumberSearchType searchType, Number searchValue) { 440 treePane.clearSelection(); 441 442 RootedTree tree = treePane.getTree(); 443 444 for (Node node : tree.getNodes()) { 445 Object value = null; 446 if (attributeName.equals("!length")) { 447 value = tree.getLength(node); 448 } else if (attributeName.equals("!height")) { 449 value = tree.getHeight(node); 450 } else { 451 value = node.getAttribute(attributeName); 452 } 453 if (matchesItem(value, searchType, searchValue)) { 454 treePane.addSelectedNode(node); 455 } 456 } 457 } 458 selectTaxa(Collection<String> taxonNames)459 public void selectTaxa(Collection<String> taxonNames) { 460 treePane.clearSelection(); 461 462 RootedTree tree = treePane.getTree(); 463 464 for (Node node : tree.getExternalNodes()) { 465 Object value = null; 466 if (taxonNames.contains(tree.getTaxon(node).getName())) { 467 treePane.addSelectedTip(node); 468 } 469 } 470 } 471 matchesItem(Object item, NumberSearchType searchType, Number searchValue)472 private boolean matchesItem(Object item, NumberSearchType searchType, Number searchValue) { 473 if (item != null && item instanceof Number) { 474 475 Number value = (Number)item; 476 477 switch (searchType) { 478 case EQUALS: 479 if (value.equals(searchValue)) { 480 return true; 481 } 482 break; 483 case EQUALS_OR_GREATER_THAN: 484 if (value.doubleValue() >= searchValue.doubleValue()) { 485 return true; 486 } 487 break; 488 case EQUALS_OR_LESS_THAN: 489 if (value.doubleValue() <= searchValue.doubleValue()) { 490 return true; 491 } 492 break; 493 case GREATER_THAN: 494 if (value.doubleValue() > searchValue.doubleValue()) { 495 return true; 496 } 497 break; 498 case LESS_THAN: 499 if (value.doubleValue() < searchValue.doubleValue()) { 500 return true; 501 } 502 break; 503 case NOT_EQUALS: 504 if (!searchValue.equals(value)) { 505 return true; 506 } 507 break; 508 } 509 } 510 return false; 511 } 512 scrollToSelectedTips()513 public void scrollToSelectedTips() { 514 Set<Node> selectedTips = treePane.getSelectedTips(); 515 if (selectedTips.size() > 0) { 516 Point point = treePane.getLocationOfTip(selectedTips.iterator().next()); 517 treePane.scrollPointToVisible(point); 518 } 519 } 520 cartoonSelectedNodes()521 public void cartoonSelectedNodes() { 522 treePane.cartoonSelectedNodes(); 523 fireTreeSettingsChanged(); 524 } 525 collapseSelectedNodes()526 public void collapseSelectedNodes() { 527 treePane.collapseSelectedNodes(); 528 fireTreeSettingsChanged(); 529 } 530 clearCollapsedNodes()531 public void clearCollapsedNodes() { 532 treePane.clearCollapsedNodes(); 533 fireTreeSettingsChanged(); 534 } 535 hilightSelectedNodes(Color color)536 public void hilightSelectedNodes(Color color) { 537 treePane.hilightSelectedNodes(color); 538 fireTreeSettingsChanged(); 539 } 540 clearHilighting()541 public void clearHilighting() { 542 treePane.clearHilightedNodes(); 543 fireTreeSettingsChanged(); 544 } 545 rerootOnSelectedBranch()546 public void rerootOnSelectedBranch() { 547 treePane.rerootOnSelectedBranch(); 548 fireTreeSettingsChanged(); 549 } 550 clearRooting()551 public void clearRooting() { 552 treePane.clearRooting(); 553 fireTreeSettingsChanged(); 554 } 555 rotateSelectedNode()556 public void rotateSelectedNode() { 557 treePane.rotateSelectedNode(); 558 fireTreeSettingsChanged(); 559 } 560 clearRotations()561 public void clearRotations() { 562 treePane.clearSelectedNodeRotations(); 563 fireTreeSettingsChanged(); 564 } 565 annotateSelectedNodes(String name, Object value)566 public void annotateSelectedNodes(String name, Object value) { 567 treePane.annotateSelectedNodes(name, value); 568 fireTreeSettingsChanged(); 569 } 570 annotateSelectedTips(String name, Object value)571 public void annotateSelectedTips(String name, Object value) { 572 treePane.annotateSelectedTips(name, value); 573 fireTreeSettingsChanged(); 574 } 575 clearAnnotation(String name)576 public void clearAnnotation(String name) { 577 treePane.clearSelectedNodeAnnotation(name); 578 treePane.clearSelectedTipAnnotation(name); 579 fireTreeSettingsChanged(); 580 } 581 clearColouring()582 public void clearColouring() { 583 treePane.clearSelectedNodeAnnotation("!color"); 584 treePane.clearSelectedTipAnnotation("!color"); 585 fireTreeSettingsChanged(); 586 } 587 selectAll()588 public void selectAll() { 589 if (treePaneSelector.getSelectionMode() == TreePaneSelector.SelectionMode.TAXA) { 590 treePane.selectAllTaxa(); 591 } else { 592 treePane.selectAllNodes(); 593 } 594 } 595 clearSelectedTaxa()596 public void clearSelectedTaxa() { 597 treePane.clearSelection(); 598 } 599 addTreeSelectionListener(TreeSelectionListener treeSelectionListener)600 public void addTreeSelectionListener(TreeSelectionListener treeSelectionListener) { 601 treePane.addTreeSelectionListener(treeSelectionListener); 602 } 603 removeTreeSelectionListener(TreeSelectionListener treeSelectionListener)604 public void removeTreeSelectionListener(TreeSelectionListener treeSelectionListener) { 605 treePane.removeTreeSelectionListener(treeSelectionListener); 606 } 607 getSelectionMode()608 public TreePaneSelector.SelectionMode getSelectionMode() { 609 return treePaneSelector.getSelectionMode(); 610 } 611 612 setSelectionMode(TreePaneSelector.SelectionMode selectionMode)613 public void setSelectionMode(TreePaneSelector.SelectionMode selectionMode) { 614 TreePaneSelector.SelectionMode oldSelectionMode = treePaneSelector.getSelectionMode(); 615 616 if (selectionMode == oldSelectionMode) { 617 return; 618 } 619 620 if (oldSelectionMode == TreePaneSelector.SelectionMode.TAXA) { 621 treePane.selectNodesFromSelectedTips(); 622 } else if (selectionMode == TreePaneSelector.SelectionMode.TAXA) { 623 treePane.selectTipsFromSelectedNodes(); 624 } else if (selectionMode == TreePaneSelector.SelectionMode.CLADE) { 625 treePane.selectCladesFromSelectedNodes(); 626 } 627 treePaneSelector.setSelectionMode(selectionMode); 628 } 629 setDragMode(TreePaneSelector.DragMode dragMode)630 public void setDragMode(TreePaneSelector.DragMode dragMode) { 631 treePaneSelector.setDragMode(dragMode); 632 } 633 634 // A load of delegated method calls through to treePane (which is now hidden outside the package). setTipLabelPainter(LabelPainter<Node> tipLabelPainter)635 public void setTipLabelPainter(LabelPainter<Node> tipLabelPainter) { 636 treePane.setTipLabelPainter(tipLabelPainter); 637 // tipLabelPainter.setupAttributes(trees); 638 639 } 640 setNodeLabelPainter(LabelPainter<Node> nodeLabelPainter)641 public void setNodeLabelPainter(LabelPainter<Node> nodeLabelPainter) { 642 treePane.setNodeLabelPainter(nodeLabelPainter); 643 // nodeLabelPainter.setupAttributes(trees); 644 } 645 setNodeBarPainter(NodeBarPainter nodeBarPainter)646 public void setNodeBarPainter(NodeBarPainter nodeBarPainter) { 647 treePane.setNodeBarPainter(nodeBarPainter); 648 // nodeBarPainter.setupAttributes(trees); 649 } 650 setTipShapePainter(NodeShapePainter tipShapePainter)651 public void setTipShapePainter(NodeShapePainter tipShapePainter) { 652 treePane.setTipShapePainter(tipShapePainter); 653 } 654 setNodeShapePainter(NodeShapePainter nodeShapePainter)655 public void setNodeShapePainter(NodeShapePainter nodeShapePainter) { 656 treePane.setNodeShapePainter(nodeShapePainter); 657 } 658 setBranchLabelPainter(LabelPainter<Node> branchLabelPainter)659 public void setBranchLabelPainter(LabelPainter<Node> branchLabelPainter) { 660 treePane.setBranchLabelPainter(branchLabelPainter); 661 // branchLabelPainter.setupAttributes(trees); 662 } 663 addScalePainter(ScalePainter scalePainter)664 public void addScalePainter(ScalePainter scalePainter) { 665 treePane.addScalePainter(scalePainter); 666 } 667 removeScalePainter(ScalePainter scalePainter)668 public void removeScalePainter(ScalePainter scalePainter) { 669 treePane.removeScalePainter(scalePainter); 670 } 671 setScaleGridPainter(ScaleGridPainter scaleGridPainter)672 public void setScaleGridPainter(ScaleGridPainter scaleGridPainter) { 673 treePane.setScaleGridPainter(scaleGridPainter); 674 } 675 setLegendPainter(LegendPainter legendPainter)676 public void setLegendPainter(LegendPainter legendPainter) { 677 treePane.setLegendPainter(legendPainter); 678 // legendPainter.setupAttributes(trees); 679 } 680 setBranchDecorator(Decorator branchDecorator, boolean isGradient)681 public void setBranchDecorator(Decorator branchDecorator, boolean isGradient) { 682 treePane.setBranchDecorator(branchDecorator, isGradient); 683 } 684 setBranchColouringDecorator(String branchColouringAttribute, Decorator branchColouringDecorator)685 public void setBranchColouringDecorator(String branchColouringAttribute, Decorator branchColouringDecorator) { 686 treePane.setBranchColouringDecorator(branchColouringAttribute, branchColouringDecorator); 687 } 688 setNodeBackgroundDecorator(Decorator nodeBackgroundDecorator)689 public void setNodeBackgroundDecorator(Decorator nodeBackgroundDecorator) { 690 treePane.setNodeBackgroundDecorator(nodeBackgroundDecorator); 691 } 692 setHilightingGradient(boolean hilightingGradient)693 public void setHilightingGradient(boolean hilightingGradient) { 694 treePane.setHilightingGradient(hilightingGradient); 695 } 696 setSelectionColor(Color selectionColor)697 public void setSelectionColor(Color selectionColor) { 698 treePane.setSelectionColor(selectionColor); 699 } 700 getSelectionPaint()701 public Paint getSelectionPaint() { 702 return treePane.getSelectionPaint(); 703 } 704 setBranchStroke(BasicStroke branchStroke)705 public void setBranchStroke(BasicStroke branchStroke) { 706 treePane.setBranchStroke(branchStroke); 707 } 708 isTransformBranchesOn()709 public boolean isTransformBranchesOn() { 710 return treePane.isTransformBranchesOn(); 711 } 712 getBranchTransform()713 public TransformedRootedTree.Transform getBranchTransform() { 714 return treePane.getBranchTransform(); 715 } 716 setTransformBranchesOn(boolean transformBranchesOn)717 public void setTransformBranchesOn(boolean transformBranchesOn) { 718 treePane.setTransformBranchesOn(transformBranchesOn); 719 } 720 setBranchTransform(TransformedRootedTree.Transform transform)721 public void setBranchTransform(TransformedRootedTree.Transform transform) { 722 treePane.setBranchTransform(transform); 723 } 724 isOrderBranchesOn()725 public boolean isOrderBranchesOn() { 726 return treePane.isOrderBranchesOn(); 727 } 728 getBranchOrdering()729 public SortedRootedTree.BranchOrdering getBranchOrdering() { 730 return treePane.getBranchOrdering(); 731 } 732 setOrderBranchesOn(boolean orderBranchesOn)733 public void setOrderBranchesOn(boolean orderBranchesOn) { 734 treePane.setOrderBranchesOn(orderBranchesOn); 735 } 736 setBranchOrdering(SortedRootedTree.BranchOrdering branchOrdering)737 public void setBranchOrdering(SortedRootedTree.BranchOrdering branchOrdering) { 738 treePane.setBranchOrdering(branchOrdering); 739 } 740 isRootingOn()741 public boolean isRootingOn() { 742 return treePane.isRootingOn(); 743 } 744 getRootingType()745 public TreePane.RootingType getRootingType() { 746 return treePane.getRootingType(); 747 } 748 setRootingOn(boolean rootingOn)749 public void setRootingOn(boolean rootingOn) { 750 treePane.setRootingOn(rootingOn); 751 } 752 setRootingType(TreePane.RootingType rootingType)753 public void setRootingType(TreePane.RootingType rootingType) { 754 treePane.setRootingType(rootingType); 755 } 756 setToolMode(TreePaneSelector.ToolMode toolMode)757 public void setToolMode(TreePaneSelector.ToolMode toolMode) { 758 treePaneSelector.setToolMode(toolMode); 759 } 760 getContentPane()761 public JComponent getContentPane() { 762 return treePane; 763 } 764 paint(Graphics g)765 public void paint(Graphics g) { 766 if( zoomPending ) { 767 refreshZoom(); 768 zoomPending = false; 769 } 770 super.paint(g); 771 } 772 print(Graphics g, PageFormat pageFormat, int pageIndex)773 public int print(Graphics g, PageFormat pageFormat, int pageIndex) throws PrinterException { 774 return treePane.print(g, pageFormat, pageIndex); 775 } 776 addTreeViewerListener(TreeViewerListener listener)777 public void addTreeViewerListener(TreeViewerListener listener) { 778 listeners.add(listener); 779 } 780 removeTreeViewerListener(TreeViewerListener listener)781 public void removeTreeViewerListener(TreeViewerListener listener) { 782 listeners.remove(listener); 783 } 784 fireTreeChanged()785 public void fireTreeChanged() { 786 for (TreeViewerListener listener : listeners) { 787 listener.treeChanged(); 788 } 789 } 790 fireTreeSettingsChanged()791 public void fireTreeSettingsChanged() { 792 for (TreeViewerListener listener : listeners) { 793 listener.treeSettingsChanged(); 794 } 795 } 796 797 private java.util.List<TreeViewerListener> listeners = new ArrayList<TreeViewerListener>(); 798 799 private List<Tree> trees = new ArrayList<Tree>(); 800 private int currentTreeIndex = 0; 801 802 protected TreePane treePane; 803 protected TreePaneSelector treePaneSelector; 804 protected TreePaneRollOver treePaneRollOver; 805 806 protected JViewport viewport; 807 808 private final JFrame frame; 809 }