1 /* 2 * $Id$ 3 * 4 * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. 5 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 6 * 7 * This code is free software; you can redistribute it and/or modify it 8 * under the terms of the GNU General Public License version 2 only, as 9 * published by the Free Software Foundation. Oracle designates this 10 * particular file as subject to the "Classpath" exception as provided 11 * by Oracle in the LICENSE file that accompanied this code. 12 * 13 * This code is distributed in the hope that it will be useful, but WITHOUT 14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 15 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 16 * version 2 for more details (a copy is included in the LICENSE file that 17 * accompanied this code). 18 * 19 * You should have received a copy of the GNU General Public License version 20 * 2 along with this work; if not, write to the Free Software Foundation, 21 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 22 * 23 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 24 * or visit www.oracle.com if you need additional information or have any 25 * questions. 26 */ 27 package com.sun.javatest.exec; 28 29 import java.awt.BorderLayout; 30 import java.awt.Color; 31 import java.awt.Dimension; 32 import java.awt.EventQueue; 33 import java.awt.Font; 34 import java.awt.Rectangle; 35 import java.awt.event.ActionEvent; 36 import java.awt.event.ActionListener; 37 import java.awt.event.InputEvent; 38 import java.awt.event.KeyEvent; 39 import java.awt.event.MouseAdapter; 40 import java.awt.event.MouseEvent; 41 import java.util.ArrayList; 42 import java.util.Hashtable; 43 import java.util.List; 44 import java.util.Map; 45 import java.util.Vector; 46 47 import javax.swing.AbstractAction; 48 import javax.swing.Action; 49 import javax.swing.DefaultListModel; 50 import javax.swing.JComponent; 51 import javax.swing.JDialog; 52 import javax.swing.JList; 53 import javax.swing.JMenu; 54 import javax.swing.JMenuItem; 55 import javax.swing.JOptionPane; 56 import javax.swing.JPanel; 57 import javax.swing.JPopupMenu; 58 import javax.swing.JScrollPane; 59 import javax.swing.JSplitPane; 60 import javax.swing.JTextArea; 61 import javax.swing.JTextField; 62 import javax.swing.KeyStroke; 63 import javax.swing.ListModel; 64 import javax.swing.MenuElement; 65 import javax.swing.ScrollPaneConstants; 66 import javax.swing.Timer; 67 import javax.swing.event.*; 68 import javax.swing.tree.TreeModel; 69 import javax.swing.tree.TreeSelectionModel; 70 import javax.swing.tree.TreePath; 71 72 import com.sun.javatest.tool.Deck; 73 import com.sun.javatest.tool.UIFactory; 74 75 import com.sun.javatest.exec.Session.Event; 76 import com.sun.javatest.Harness; 77 import com.sun.javatest.JavaTestError; 78 import com.sun.javatest.Parameters; 79 import com.sun.javatest.TestResult; 80 import com.sun.javatest.TestResultTable; 81 import com.sun.javatest.TestResultTable.TreeNode; 82 import com.sun.javatest.TestSuite; 83 import com.sun.javatest.WorkDirectory; 84 import com.sun.javatest.tool.Preferences; 85 import com.sun.javatest.util.Debug; 86 import com.sun.javatest.util.DynamicArray; 87 import com.sun.javatest.util.I18NResourceBundle; 88 import com.sun.javatest.util.StringArray; 89 90 /** 91 * This panel is a split panel which has the testsuite tree on the left and a context 92 * sensitive panel on the right. 93 */ 94 class TestTreePanel extends JPanel implements ET_TestTreeControl, HarnessAware, Session.Observer { 95 96 /** 97 * Constructs TestTreePanel object, doesn't initialize GUI! 98 */ 99 public TestTreePanel(JComponent parent, ExecModel em, UIFactory uif) { 100 this.uif = uif; 101 this.execModel = em; 102 this.parent = parent; 103 uif.setAccessibleInfo(this, "treep"); 104 } 105 /** 106 * @param map Saved state map, may be null. 107 */ 108 public TestTreePanel(UIFactory uif, Harness h, ExecModel em, 109 FilterSelectionHandler fh, JComponent parent, 110 Map<String, String> map) { 111 this(parent, em, uif); 112 setHarness(h); 113 this.filterHandler = fh; 114 this.stateMap = map; 115 initialize(); 116 } 117 118 public void initialize() { 119 initGUI(); 120 } 121 122 /** 123 * Returns the current TRT, or null if no table is available. 124 */ 125 public synchronized TestResultTable getTestResultTable() { 126 /* 127 WorkDirectory wd = params.getWorkDirectory(); 128 if (wd == null) 129 return null; 130 else 131 return wd.getTestResultTable(); 132 */ 133 return initialized ? treeModel.getTestResultTable() : null; 134 } 135 136 /** 137 * Discover which parameters this panel is using. 138 */ 139 public Parameters getParameters() { 140 return params; 141 } 142 143 public synchronized TreePanelModel getTreePanelModel() { 144 return pm; 145 } 146 147 public synchronized void dispose() { 148 disposed = true; 149 150 // zap cache worker thread 151 if (treeModel != null) { 152 treeModel.dispose(); 153 treeModel = null; 154 } 155 156 // zap counter thread 157 if (brPanel != null) { 158 brPanel.dispose(); 159 brPanel = null; 160 } 161 162 // zap bg workers for purge or refresh 163 if (bgThread != null && bgThread.isAlive()) { 164 bgThread.interrupt(); 165 } 166 params = null; 167 newParams = null; 168 popup = null; 169 lastPopupPath = null; 170 testMenus = folderMenus = mixedMenus = customMenus = null; 171 } 172 173 // --------- private --------- 174 /** 175 * This method should only be called to indicate that a change has occurred 176 * which replaces the active TRT. In most cases, a call to this method 177 * should be followed by on to updateGUI(). Changes to the parameters 178 * (filters, initial URLs, etc... should propagate thru the FilterConfig 179 * system.<br> 180 * It does nothing but remembers passed object. The real work is done 181 * by applyParameters() method. 182 * 183 * 184 * @see #updateGUI 185 * @see #applyParameters 186 * @see com.sun.javatest.exec.FilterConfig 187 */ 188 public synchronized void setParameters(Parameters p) { 189 this.newParams = p; 190 newConfigAlreadyApplied = false; 191 } 192 193 /** 194 * Applies changed Parameters iff changed since last time. 195 * Method to be invoked from updateGUI(). 196 */ 197 synchronized void applyParameters(boolean force) { 198 if (!force) { 199 if (newParams == null) { 200 return; 201 } 202 if (newConfigAlreadyApplied) { 203 return; 204 } 205 newConfigAlreadyApplied = true; 206 } 207 208 String[] paths = null; 209 String[] selectedPaths = null; 210 211 // this is important because there are no params at construction 212 // time, so we need to make sure to make use of the preferences 213 if (params == null && stateMap != null) { 214 // trying to retrieve previous state 215 String tmp = stateMap.get(OPEN_PATHS_PREF); 216 if (tmp != null) { 217 paths = StringArray.split(tmp); 218 } 219 } else { 220 if (tree != null && !(treeModel instanceof EmptyTestTreeModel)) { 221 TreePath[] ps = tree.snapshotOpenPaths(); 222 paths = treeModel.pathsToStrings(ps); 223 224 ps = tree.snapshotSelectedPaths(); 225 selectedPaths = treeModel.pathsToStrings(ps); 226 } 227 } 228 229 this.params = newParams; 230 231 if (treeModel instanceof EmptyTestTreeModel) { 232 WorkDirectory wd = execModel.getWorkDirectory(); 233 ContextManager cm = execModel.getContextManager(); 234 EmptyTestTreeModel em = (EmptyTestTreeModel) treeModel; 235 236 if (wd != null && cm != null && cm.getFeatureManager().isEnabled(FeatureManager.NO_TREE_WITHOUT_WD)) { 237 cm.openTree(wd); 238 treeModel = new TestTreeModel(params, filterHandler, uif); 239 tree.setTreeModel(treeModel); 240 241 for (TreeModelListener l : em.getTreeModelListeners()) { 242 treeModel.addTreeModelListener(l); 243 } 244 for (TestResultTable.TreeNodeObserver o : em.getRootObservers()) { 245 ((TestResultTable.TreeNode) treeModel.getRoot()).addObserver(o); 246 } 247 harness.removeObserver(pm); 248 pm = new PanelModel(); 249 harness.addObserver(pm); 250 brPanel.dispose(); 251 brPanel.setTreeModel(treeModel); 252 253 em.dispose(); 254 } 255 } 256 257 if (treeModel != null) { 258 treeModel.setParameters(params); 259 } 260 261 if (tree != null) { 262 tree.setParameters(params); 263 treeRend.setParameters(params); 264 } 265 266 if (testPanel != null) { 267 testPanel.setTestSuite(params.getTestSuite()); 268 } 269 270 if (brPanel != null) { 271 brPanel.setParameters(params); 272 } 273 274 // restore onscreen open paths 275 if (tree != null && paths != null && paths.length > 0) { 276 tree.restorePaths(paths, true); 277 } 278 279 if (tree != null ) { 280 tree.restoreSelection(selectedPaths); 281 } 282 283 if (tree != null) { 284 ensureTreeSelection(); 285 } 286 287 } 288 289 private TreePath[] getTreePaths(String[] paths) { 290 if (paths != null) { 291 ArrayList<TreePath> translatedPaths = new ArrayList<>(paths.length); 292 293 for (int i = 0; i < paths.length; i++) { 294 // the paths need to be reconditioned because the JTree will not 295 // accept them if they refer to a different model/TRT. 296 //Object targetNode = trt.resolveUrl(paths[i]); 297 298 TreePath tp = treeModel.resolveUrl(paths[i]); 299 if (tp != null) { 300 translatedPaths.add(tp); 301 } 302 } // for (i) 303 304 TreePath[] result = new TreePath[translatedPaths.size()]; 305 translatedPaths.toArray(result); 306 return result; 307 } else { 308 return null; 309 } 310 } 311 312 313 @Override 314 public void saveTreeState(Map<String, String> m) { 315 String[] paths = getOpenPaths(); 316 m.put(OPEN_PATHS_PREF, StringArray.join(paths)); 317 } 318 319 @Override 320 public void restoreTreeState(Map<String, String> m) { 321 if (m != null) { 322 String tmp = m.get(OPEN_PATHS_PREF); 323 if (tree != null && tmp != null && tmp.length() > 0) { 324 tree.restorePaths(StringArray.split(tmp), true); 325 } 326 } 327 } 328 329 @Override 330 public void save(Map<String, String> m) { 331 // save the open paths 332 Preferences.access(); 333 saveTreeState(m); 334 } 335 336 @Override 337 public void restore(Map<String, String> m) { 338 stateMap = m; 339 restoreTreeState(stateMap); 340 } 341 342 /** 343 * Translates open tree paths into string URLs. 344 * @return null if no paths are open or the tree is not available. 345 */ 346 private String[] getOpenPaths() { 347 if (tree == null || tree.getModel() instanceof EmptyTestTreeModel) { 348 return null; 349 } 350 351 TreePath[] paths = tree.snapshotOpenPaths(); 352 Vector<String> urls = new Vector<>(); 353 354 if (paths != null) { 355 for (int i = 0; i < paths.length; i++) { 356 Object last = paths[i].getLastPathComponent(); 357 String url; 358 359 if (last instanceof TT_TestNode) { 360 // get url 361 url = ((TT_TestNode) last).getTestResult().getTestName(); 362 } 363 else if (last instanceof TT_BasicNode ) { // tree node 364 // get url 365 url = ((TT_BasicNode) last).getLongPath(); 366 } 367 else 368 return null; 369 370 urls.addElement(url); 371 } // for 372 } 373 374 if (urls == null || urls.size() == 0) { 375 return null; 376 } else { 377 String[] result = new String[urls.size()]; 378 urls.copyInto(result); 379 return result; 380 } 381 } 382 383 /* BK now unused 384 private TreePath nodeToPath(Object node, TestResultTable trt) { 385 if (node instanceof TestResult) { 386 TestResult tr = (TestResult)node; 387 388 } 389 else { // tree node 390 // trans url to path 391 Object[] ttp = TestResultTable.getObjectPath((TreeNode)node); 392 393 if (ttp != null && ttp.length > 0) 394 return new TreePath(ttp); 395 else 396 return null; 397 } 398 } 399 */ 400 private void setPopupItemsEnabled(boolean state) { 401 if (state) { 402 // enable all if possible 403 boolean haveWorkDir = (params != null && params.getWorkDirectory() != null); 404 purgeMI.setEnabled(haveWorkDir); 405 refreshMI.setEnabled(params != null && params.getTestSuite() != null); 406 407 // maybe should be based on whether the interview is complete 408 runMI.setEnabled(!execModel.isConfiguring()); 409 } else { 410 // disable all 411 purgeMI.setEnabled(false); 412 refreshMI.setEnabled(false); 413 runMI.setEnabled(false); 414 } 415 } 416 417 private void clearNodes(final TreePath[] what) { 418 final WorkDirectory wd = execModel.getWorkDirectory(); 419 420 if (wd == null) { 421 JOptionPane.showMessageDialog(parent, 422 uif.getI18NString("treep.cantPurgeNoWd.msg"), 423 uif.getI18NString("treep.cantPurgeNoWd.title"), 424 JOptionPane.WARNING_MESSAGE); 425 return; 426 } 427 428 if (harness.isRunning()) { 429 JOptionPane.showMessageDialog(parent, 430 uif.getI18NString("treep.cantPurgeRunning.msg"), 431 uif.getI18NString("treep.cantPurgeRunning.title"), 432 JOptionPane.WARNING_MESSAGE); 433 return; 434 } 435 436 boolean ack = false; 437 Object[] toPurge = new Object[what.length]; 438 439 if (what.length > 1) { 440 //int confirm = uif.showYesNoDialog("treep.purgeItemsSure", 441 //createNodeListString(createNodeList(what))); 442 443 String[] paths = createNodeList(what); 444 DefaultListModel<String> model = new DefaultListModel<>(); 445 for (int i = paths.length; i > 0; i--) { 446 model.add(model.getSize(), paths[model.getSize()]); 447 } 448 int confirm = showConfirmListDialog("treep.purgeItemsSure", null, model); 449 450 // user backs out 451 if (confirm != JOptionPane.YES_OPTION) { 452 return; 453 } else { 454 ack = true; 455 for (int i = 0; i < what.length; i++) { 456 Object item = what[i].getLastPathComponent(); 457 if (item instanceof TT_TestNode) { 458 toPurge[i] = ((TT_TestNode) item).getTestResult().getWorkRelativePath(); 459 } else if (item instanceof TT_BasicNode) { 460 TT_BasicNode tn = (TT_BasicNode) item; 461 if (tn.isRoot()) { 462 toPurge = new Object[1]; 463 toPurge[0] = ""; 464 break; // no need to process the rest of the list 465 } else { 466 toPurge[i] = tn.getLongPath(); 467 } 468 } else { 469 } 470 } // for 471 } 472 } // just one node 473 else if (what[0].getLastPathComponent() instanceof TT_TestNode) { 474 TestResult tr = ((TT_TestNode) (what[0].getLastPathComponent())).getTestResult(); 475 476 int confirm = uif.showYesNoDialog("treep.purgeTestSure", 477 tr.getTestName()); 478 479 // user backs out 480 if (confirm != JOptionPane.YES_OPTION) { 481 return; 482 } else { 483 //wd.purge(tr.getWorkRelativePath()); 484 ack = true; 485 toPurge[0] = tr.getWorkRelativePath(); 486 } 487 } else { 488 TT_BasicNode tn = (TT_BasicNode) (what[0].getLastPathComponent()); 489 490 int confirm = 0; 491 if (tn.isRoot()) { 492 confirm = uif.showYesNoDialog("treep.purgeRootSure"); 493 } else { 494 confirm = uif.showYesNoDialog("treep.purgeNodeSure", 495 tn.getLongPath()); // user backs out 496 } 497 if (confirm != JOptionPane.YES_OPTION) { 498 return; 499 } else { 500 ack = true; 501 toPurge[0] = tn; 502 } 503 } 504 505 // only go in here if user confirmed the operation 506 if (ack) { 507 // this block is intended to do the following: 508 // - disable menu items 509 // - start purge on background thread 510 // - show a wait dialog if the operation exceeds a min. time 511 // - hide dialog and re-enable menu item when thread finishes 512 final JDialog d = uif.createWaitDialog("treep.waitPurge", this); 513 final String[] finalList = createNodeList(toPurge); 514 515 // disable all menu items 516 setPopupItemsEnabled(false); 517 518 final Thread t = new Thread() { 519 520 @Override 521 public void run() { 522 for (int i = 0; i < what.length; i++) { 523 try { 524 // this may take a long while... 525 for (int j = 0; j < finalList.length; j++) { 526 wd.purge(finalList[j]); 527 } 528 } // try 529 catch (WorkDirectory.PurgeFault f) { 530 // print something in log... 531 I18NResourceBundle i18n = uif.getI18NResourceBundle(); 532 wd.log(i18n, "treep.purgeFail.err", f); 533 } // catch 534 finally { 535 // fixup GUI on GUI thread 536 try { 537 EventQueue.invokeAndWait(new Runnable() { 538 539 public void run() { 540 if (d.isShowing()) { 541 d.hide(); 542 // enable all menu items 543 } 544 setPopupItemsEnabled(true); 545 546 // reselect tree nodes 547 TreePath[] translatedPaths = getTreePaths(finalList); 548 if (translatedPaths != null && tree != null) { 549 tree.setSelectionPaths(translatedPaths); 550 } 551 } 552 }); 553 } catch (InterruptedException e) { 554 } catch (java.lang.reflect.InvocationTargetException e) { 555 } 556 } // outer try 557 } // for 558 } // run() 559 }; // thread 560 561 ActionListener al = new ActionListener() { 562 563 public void actionPerformed(ActionEvent evt) { 564 // show dialog if still processing 565 if (t == null) { 566 return; 567 } else if (t.isAlive() && !d.isVisible()) { 568 d.show(); 569 } else if (!t.isAlive() && d.isVisible()) { 570 // just in case...a watchdog type check 571 d.hide(); 572 } 573 } 574 }; 575 576 bgThread = t; 577 578 // show wait dialog if operation is still running after 579 // WAIT_DIALOG_DELAY 580 Timer timer = new Timer(WAIT_DIALOG_DELAY, al); 581 timer.setRepeats(false); 582 583 // do it! 584 // in this order to reduce race condition 585 timer.start(); 586 t.start(); 587 } // outer if 588 } 589 590 // XXX need to find a shared place for these two methods to live 591 static String createNodeListString(String[] items) { 592 StringBuffer sb = new StringBuffer(); 593 594 for (int i = 0; i < items.length; i++) { 595 sb.append(" "); 596 sb.append(items[i]); 597 598 if (i + 1 < items.length) { 599 sb.append("\n"); 600 } 601 } // for 602 603 return sb.toString(); 604 } 605 606 static String[] createNodeList(Object[] items) { 607 String[] result = new String[items.length]; 608 609 for (int i = 0; i < items.length; i++) { 610 Object item = items[i]; 611 612 if (item instanceof TreePath) { 613 item = ((TreePath) item).getLastPathComponent(); 614 } 615 if (item instanceof TT_TestNode) { 616 TestResult tr = ((TT_TestNode) item).getTestResult(); 617 result[i] = tr.getTestName(); 618 } else if (item instanceof TT_BasicNode) { 619 if (((TT_BasicNode) item).isRoot()) { 620 result = new String[1]; 621 result[0] = TestResultTable.getRootRelativePath(((TT_BasicNode)item).getTableNode()); 622 return result; 623 } else { 624 TestResultTable.TreeNode tn = ((TT_BasicNode) item).getTableNode(); 625 result[i] = TestResultTable.getRootRelativePath(tn); 626 } 627 } else if (item instanceof TestResult) { 628 // not used anymore, but left in case we decide to repopulate 629 // the list with actual TestResult objects 630 TestResult tr = (TestResult) item; 631 result[i] = tr.getTestName(); 632 } else if (item instanceof TestResultTable.TreeNode) { 633 TestResultTable.TreeNode tn = (TestResultTable.TreeNode) item; 634 result[i] = TestResultTable.getRootRelativePath(tn); 635 } else // should not happen 636 if (items[i] != null) { 637 result[i] = items[i].toString(); 638 } 639 } // for 640 641 return result; 642 } 643 644 private void showNodeInfoDialog(TreePath what) { 645 if (what.getLastPathComponent() instanceof TT_TreeNode) { 646 TT_TreeNode tn = (TT_TreeNode) (what.getLastPathComponent()); 647 Debug.println("info for this node not implemented" + 648 tn.getDisplayName() + " (" + tn + ")"); 649 } 650 } 651 652 private void runNodes(TreePath[] what) { 653 if (harness.isRunning()) { 654 JOptionPane.showMessageDialog(parent, 655 uif.getI18NString("treep.cantRunRunning.msg"), 656 uif.getI18NString("treep.cantRunRunning.title"), 657 JOptionPane.WARNING_MESSAGE); 658 return; 659 } 660 661 execModel.runTests(createNodeList(what)); 662 } 663 664 private static void restore(final TreePath[] paths, final TestTree targetTree) { 665 if (paths == null || targetTree == null) { 666 return; // we do it this way so that the tree updates itself, THEN we 667 // ask it to restore 668 } 669 Runnable restorer = new Runnable() { 670 671 public void run() { 672 //targetTree.restorePaths(paths); 673 } 674 }; // Runnable 675 676 EventQueue.invokeLater(restorer); 677 } 678 679 private void refreshNodes(TreePath[] what) { 680 // dialog to confirm wipe of results with refresh? 681 682 if (harness.isRunning()) { 683 JOptionPane.showMessageDialog(parent, 684 uif.getI18NString("treep.cantRefreshRunning.msg"), 685 uif.getI18NString("treep.cantRefreshRunning.title"), 686 JOptionPane.WARNING_MESSAGE); 687 return; 688 } 689 690 final TestResultTable trt = treeModel.getTestResultTable(); 691 boolean ack = false; 692 String[] ackTargets = new String[what.length]; 693 TT_TreeNode[] ackNodes = null; 694 695 if (what.length > 1) { 696 //int confirm = uif.showYesNoDialog("treep.refreshNodeSure", 697 // createNodeListString(createNodeList(what))); 698 699 String[] paths = createNodeList(what); 700 DefaultListModel<String> model = new DefaultListModel<>(); 701 for (int i = paths.length; i > 0; i--) { 702 model.add(model.getSize(), paths[model.getSize()]); 703 } 704 int confirm = showConfirmListDialog("treep.refreshNodeSure", paths, model); 705 706 if (confirm != JOptionPane.YES_OPTION) { 707 return; 708 } 709 else { 710 ack = true; 711 } 712 713 for (int i = 0; i < what.length; i++) { 714 Object item = what[i].getLastPathComponent(); 715 if (item instanceof TT_TestNode) { 716 ackTargets[i] = ((TT_TestNode) item).getLongPath(); 717 ackNodes = DynamicArray.append(ackNodes, (TT_TestNode)item, TT_TreeNode.class); 718 } else if (item instanceof TT_BasicNode) { 719 ackNodes = DynamicArray.append(ackNodes, (TT_BasicNode)item, TT_TreeNode.class); 720 TT_BasicNode tn = (TT_BasicNode) item; 721 if (tn.isRoot()) { 722 ackTargets = new String[1]; 723 ackTargets[0] = null; 724 break; // no other results needed 725 } else { 726 // does not happen 727 //ackTargets[i] = tn.getLongPath(); 728 } 729 } else { 730 } 731 } // for 732 733 } // BK deprecated, will never happen 734 else if (what[0].getLastPathComponent() instanceof TestResult) { 735 final TestResult tr = (TestResult) (what[0].getLastPathComponent()); 736 737 int confirm = uif.showYesNoDialog("treep.refreshTestSure", 738 tr.getTestName()); 739 740 // user backs out 741 if (confirm != JOptionPane.YES_OPTION) { 742 return; 743 } 744 ack = true; 745 ackTargets[0] = tr.getTestName(); 746 } // single node of any type is selected 747 else { 748 final TT_TreeNode tn = (TT_TreeNode) (what[0].getLastPathComponent()); 749 int confirm = JOptionPane.NO_OPTION; 750 ackTargets[0] = tn.getLongPath(); 751 if (tn.isRoot()) { 752 confirm = uif.showYesNoDialog("treep.refreshRootSure"); 753 } else { 754 confirm = uif.showYesNoDialog("treep.refreshNodeSure", 755 ackTargets[0]); // user backs out 756 } 757 if (confirm != JOptionPane.YES_OPTION) { 758 return; 759 } 760 else 761 ack = true; 762 763 if (tn instanceof TT_BasicNode) { 764 ackNodes = new TT_TreeNode[] {tn}; 765 } 766 } // else 767 768 // NOTES... 769 // if one node being refreshed, ackNodes is null 770 if (ack) { 771 final JDialog d = uif.createWaitDialog("treep.waitRef", this); 772 final String[] finalTargets = ackTargets; 773 final TT_TreeNode[] finalNodes = ackNodes; 774 TreePath[] tp = tree.snapshotOpenPaths(); 775 final String[] openUrls = treeModel.pathsToStrings(tp); 776 final String[] selectedUrls = treeModel.pathsToStrings(tree.snapshotSelectedPaths()); 777 778 779 // disable all menu items 780 setPopupItemsEnabled(false); 781 final Thread t = new Thread() { 782 783 { 784 setName("Tree refresh"); 785 } 786 787 public void run() { 788 if (trt == null) { 789 return; // empty tree model set 790 } 791 boolean changes = false; 792 try { 793 // avoid deadlocking while other things are going on 794 trt.waitUntilReady(); 795 treeModel.pauseWork(); 796 797 if (finalNodes == null) 798 for (int i = 0; i < finalTargets.length; i++) { 799 try { 800 // this may take a long while... 801 if (finalTargets[i] instanceof String) { 802 changes = trt.refreshIfNeeded(finalTargets[i]); 803 } 804 } // try 805 catch (TestResultTable.Fault f) { 806 // log the error 807 final WorkDirectory wd = execModel.getWorkDirectory(); 808 if (wd != null) { 809 I18NResourceBundle i18n = uif.getI18NResourceBundle(); 810 wd.log(i18n, "treep.refFail", 811 new String[]{ 812 finalTargets[i], 813 f.getMessage() 814 }); 815 } 816 } // catch 817 } // for 818 else { 819 for (int i = 0; i < finalNodes.length; i++) { 820 try { 821 if (finalNodes[i] instanceof TT_TestNode) 822 changes = trt.refreshIfNeeded(finalNodes[i].getLongPath()); 823 else { 824 changes = trt.refreshIfNeeded(((TT_BasicNode)finalNodes[i]).getTableNode()); 825 if (changes) trt.prune(((TT_BasicNode)finalNodes[i]).getTableNode()); 826 } 827 828 } 829 catch (TestResultTable.Fault f) { 830 // log the error 831 final WorkDirectory wd = execModel.getWorkDirectory(); 832 if (wd != null) { 833 I18NResourceBundle i18n = uif.getI18NResourceBundle(); 834 wd.log(i18n, "treep.refFail", 835 new String[]{ 836 finalTargets[i], 837 f.getMessage() 838 }); 839 } 840 } // catch 841 } // for 842 } 843 } finally { 844 treeModel.unpauseWork(); 845 final boolean updateTree = changes; 846 // fixup GUI on GUI thread 847 try { 848 EventQueue.invokeAndWait(new Runnable() { 849 850 public void run() { 851 if (d.isShowing()) { 852 d.hide(); 853 // enable all menu items 854 } 855 setPopupItemsEnabled(true); 856 if (updateTree) { 857 restoreOpenTreePaths(openUrls); 858 tree.restoreSelection(selectedUrls); 859 } 860 } 861 }); 862 } catch (InterruptedException e) { 863 } catch (java.lang.reflect.InvocationTargetException e) { 864 } // catch 865 } // finally 866 } // run() 867 }; // thread 868 869 ActionListener al = new ActionListener() { 870 871 public void actionPerformed(ActionEvent evt) { 872 // show dialog if still processing 873 if (t == null) { 874 return; 875 } else if (t.isAlive() && !d.isVisible()) { 876 d.show(); 877 } else if (!t.isAlive() && d.isVisible()) { 878 // just in case...a watchdog type check 879 d.hide(); 880 } 881 } 882 }; 883 884 bgThread = t; 885 886 // show wait dialog if operation is still running after 887 // WAIT_DIALOG_DELAY 888 Timer timer = new Timer(WAIT_DIALOG_DELAY, al); 889 timer.setRepeats(true); 890 891 // do it! 892 // in this order to reduce race condition 893 timer.start(); 894 t.start(); 895 } // outer if 896 } 897 898 private void refreshFilters() { 899 if (execModel instanceof ExecTool) { 900 ExecTool et = (ExecTool)execModel; 901 et.filterHandler.updateFilters(); 902 } 903 } 904 905 private void restoreOpenTreePaths(final String[] urls) { 906 //treeModel = (TestTreeModel)(tree.getModel()); 907 //treeModel.notifyFullStructure(); 908 //tree.restorePaths(treeModel.urlsToPaths(openUrls)); 909 tree.restorePaths(urls, true); 910 } 911 912 /** 913 * Call when it is likely that the Parameters have changed internally. 914 * A call to this method may should be made if setParameters() is called. 915 * This method should not be used to force updates when the filters have 916 * changed, that should be done through the View mechanism. 917 * 918 * @see #setParameters 919 */ 920 public synchronized void updateGUI() { 921 if (debug) { 922 Debug.println("TTP.updateGUI()"); 923 } 924 if (!initialized) { 925 return; 926 } 927 if (disposed) { 928 return; // enabled/disable popup menu items based on whether we have a 929 // workdir or testsuite 930 } 931 applyParameters(false); 932 if (popup != null && params != null) { 933 MenuElement[] elems = popup.getSubElements(); 934 if (elems != null) { 935 boolean haveWorkDir = (params.getWorkDirectory() != null); 936 purgeMI.setEnabled(haveWorkDir); 937 refreshMI.setEnabled(params.getTestSuite() != null); 938 939 // maybe should be based on whether the interview is complete 940 //runMI.setEnabled(haveWorkDir && params.isValid()); 941 runMI.setEnabled(!execModel.isConfiguring()); 942 } else { 943 } 944 } else { 945 } 946 tree.updateGUI(); 947 brPanel.updateGUI(); 948 startTreeUpdate(); 949 } 950 951 private synchronized void startTreeUpdate() { 952 final TestResultTable trt = getTestResultTable(); 953 if (trt != null && pm != null) { 954 trt.addObserver(pm); 955 } 956 if (trt != null) { 957 EventQueue.invokeLater(new Runnable() { 958 959 public void run() { 960 new Thread("Test tree updater") { 961 962 @Override 963 public void run() { 964 if (trt != null && trt.getWorkDirectory() != null 965 && treeModel != null && !disposed) { 966 try { 967 treeModel.pauseWork(); 968 trt.getLock().lock(); 969 trt.waitUntilReady(); 970 trt.refreshIfNeeded(trt.getRoot()); 971 972 TT_BasicNode root = (TT_BasicNode) (treeModel.getRoot()); 973 for (int i = 0; i >= 0 && i < root.getChildCount(); i++) { 974 Object c = root.getChildAt(i); 975 if (c instanceof TT_BasicNode) { 976 TT_BasicNode tn = (TT_BasicNode) c; 977 if (tn.getChildCount() == 0) { 978 trt.prune(tn.getTableNode()); 979 i--; 980 } 981 } 982 } 983 String[] openPaths = null; 984 String[] selectedPaths = null; 985 if (tree != null) { 986 TreePath[] p = tree.snapshotOpenPaths(); 987 openPaths = treeModel.pathsToStrings(p); 988 989 selectedPaths = treeModel.pathsToStrings(tree.snapshotSelectedPaths()); 990 991 } 992 993 if (pm != null) { 994 pm.refreshTree(); 995 } 996 997 if (tree != null) { 998 tree.invalidate(); 999 1000 if (openPaths != null && openPaths.length > 0) 1001 tree.restorePaths(openPaths, true); 1002 1003 tree.restoreSelection(selectedPaths); 1004 1005 } 1006 } catch (TestResultTable.Fault f) { 1007 } finally { 1008 trt.getLock().unlock(); 1009 1010 if (!disposed) 1011 treeModel.unpauseWork(); 1012 } 1013 } 1014 } 1015 }.start(); 1016 } 1017 }); 1018 } 1019 } 1020 1021 private synchronized void initGUI() { 1022 if (initialized) { 1023 return; 1024 } 1025 initialized = true; 1026 setName("treeAndDetails"); 1027 1028 JSplitPane splitPane = uif.createSplitPane(JSplitPane.HORIZONTAL_SPLIT); 1029 listener = new Listener(); 1030 // null params is okay 1031 1032 WorkDirectory wd = execModel.getWorkDirectory(); 1033 ContextManager cm = execModel.getContextManager(); 1034 if (wd == null && cm != null && cm.getFeatureManager().isEnabled(FeatureManager.NO_TREE_WITHOUT_WD)) { 1035 cm.openTree(null); 1036 treeModel = new EmptyTestTreeModel(params, filterHandler, uif); 1037 } else { 1038 cm.openTree(wd); 1039 treeModel = new TestTreeModel(params, filterHandler, uif); 1040 } 1041 treeRend = new TT_Renderer(uif, filterHandler, pm); 1042 1043 tree = new TestTree(uif, pm, filterHandler, treeModel); 1044 tree.setTreeModel(treeModel); 1045 tree.setCellRenderer(treeRend); 1046 tree.addTreeSelectionListener(listener); 1047 tree.addTreeExpansionListener(listener); 1048 tree.addMouseListener(listener); 1049 tree.getSelectionModel().setSelectionMode(TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION); 1050 tree.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put( 1051 KeyStroke.getKeyStroke(KeyEvent.VK_F10, 1052 InputEvent.SHIFT_MASK, 1053 false), 1054 "triggerPopup"); 1055 tree.getActionMap().put("triggerPopup", 1056 new TreePopupAction(uif.getI18NResourceBundle(), "treep.popup")); 1057 uif.setAccessibleInfo(tree, "treep.tree"); 1058 1059 JPanel left = uif.createPanel("tree", new BorderLayout(), false); 1060 1061 left.add(uif.createScrollPane(tree, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, 1062 JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED), 1063 BorderLayout.CENTER); 1064 splitPane.setLeftComponent(left); 1065 1066 deck = new Deck() { 1067 1068 public Dimension getPreferredSize() { 1069 int dpi = uif.getDotsPerInch(); 1070 return new Dimension(6 * dpi, 4 * dpi); 1071 } 1072 }; 1073 1074 testPanel = new TestPanel(uif, harness, execModel.getContextManager()); 1075 brPanel = new BranchPanel(uif, pm, harness, execModel, parent, filterHandler, treeModel); 1076 msPanel = new MultiSelectPanel(uif, pm, treeModel); 1077 deck.add(testPanel); 1078 deck.add(brPanel); 1079 deck.add(msPanel); 1080 1081 deckPanel = uif.createPanel("main", false); 1082 deckPanel.setLayout(new BorderLayout()); 1083 deckPanel.add(deck, BorderLayout.CENTER); 1084 1085 // title strip, above the tabs, not above the tree 1086 titleField = uif.createOutputField("treep.title"); 1087 titleField.setBorder(null); 1088 titleField.setText(uif.getI18NString("treep.title.noSelection.txt")); 1089 titleField.setBackground(UIFactory.Colors.MENU_BACKGROUND.getValue()); 1090 //titleField.setForeground(MetalLookAndFeel.getUserTextColor()); 1091 titleField.setForeground(new Color(102, 102, 102)); // #666666 1092 Font f = UIFactory.getBaseFont(); 1093 titleField.setFont(new Font("Ariel", Font.BOLD, f.getSize())); 1094 titleField.setEnabled(true); 1095 titleField.setEditable(false); 1096 1097 deckPanel.add(titleField, BorderLayout.NORTH); 1098 1099 splitPane.setRightComponent(deckPanel); 1100 testPanel.setVisible(false); 1101 brPanel.setVisible(false); 1102 deck.setVisible(true); 1103 deckPanel.setVisible(true); 1104 splitPane.setDividerLocation(0.3); 1105 splitPane.setResizeWeight(0.3); // 30% to left tree pane 1106 1107 ensureTreeSelection(); 1108 1109 popup = uif.createPopupMenu("treep.popup.mnu"); 1110 popup.add(runMI = uif.createMenuItem("treep.popup", "run", listener)); 1111 popup.addSeparator(); 1112 popup.add(refreshMI = uif.createMenuItem("treep.popup", "refresh", listener)); 1113 popup.add(purgeMI = uif.createMenuItem("treep.popup", "clear", listener)); 1114 1115 // get items from the test suite 1116 if (cm != null) { 1117 JavaTestContextMenu[] cms = cm.getContextMenus(); 1118 if (cms != null) { 1119 popup.addSeparator(); 1120 1121 for (int i = 0; i < cms.length; i++) { 1122 // filter out types of menus we don't want (not needed yet) 1123 // keep track of them for later 1124 switch (cms[i].getMenuApplication()) { 1125 case JavaTestContextMenu.TESTS_AND_FOLDERS: 1126 if (mixedMenus == null) { 1127 mixedMenus = new ArrayList<>(); 1128 } 1129 mixedMenus.add(cms[i]); 1130 break; 1131 case JavaTestContextMenu.TESTS_ONLY: 1132 if (testMenus == null) { 1133 testMenus = new ArrayList<>(); 1134 } 1135 testMenus.add(cms[i]); 1136 break; 1137 case JavaTestContextMenu.FOLDERS_ONLY: 1138 if (folderMenus == null) { 1139 folderMenus = new ArrayList<>(); 1140 } 1141 folderMenus.add(cms[i]); 1142 break; 1143 case JavaTestContextMenu.CUSTOM: 1144 if (customMenus == null) { 1145 customMenus = new ArrayList<>(); 1146 } 1147 customMenus.add(cms[i]); 1148 break; 1149 default: 1150 } 1151 popup.add(cms[i].getMenu()); 1152 } // for 1153 } 1154 } 1155 1156 // disabled by default 1157 // will immediately be reevaluated when setParameters() is called 1158 runMI.setEnabled(false); 1159 refreshMI.setEnabled(false); 1160 purgeMI.setEnabled(false); 1161 1162 // setup top toolbar 1163 /* 1164 JPanel topPanel = uif.createPanel("treeTb", new GridBagLayout(), false); 1165 // NOTE intentional space added below to defeat 1166 // i18n check in build while this is commented out 1167 JLabel lab = uif.createLabel ("treep.filter", true); 1168 1169 JComponent selector = filterHandler.getFilterSelector(); 1170 lab.setLabelFor(selector); 1171 1172 GridBagConstraints gbc = new GridBagConstraints(); 1173 gbc.gridy = 0; 1174 gbc.ipadx = 12; // JL&F 1175 gbc.fill = GridBagConstraints.HORIZONTAL; 1176 gbc.anchor = GridBagConstraints.CENTER; 1177 gbc.gridwidth = GridBagConstraints.REMAINDER; 1178 1179 gbc.gridy = 1; 1180 gbc.gridwidth = 1; 1181 gbc.fill = GridBagConstraints.NONE; 1182 gbc.anchor = GridBagConstraints.WEST; 1183 1184 topPanel.add(lab, gbc); 1185 topPanel.add(selector, gbc); 1186 1187 topPanel.add(uif.createHorizontalStrut(15), gbc); 1188 1189 gbc.anchor = GridBagConstraints.EAST; 1190 gbc.fill = GridBagConstraints.BOTH; 1191 gbc.weightx = 3; 1192 topPanel.add(uif.createMessageArea("treep.filter"), gbc); 1193 */ 1194 1195 setLayout(new BorderLayout()); 1196 1197 add(splitPane, BorderLayout.CENTER); 1198 //add(topPanel, BorderLayout.NORTH); 1199 applyParameters(false); 1200 TestResultTable trt = treeModel.getTestResultTable(); 1201 if (wd != null && trt != null) { 1202 try { 1203 wd.setTestResultTable(trt); 1204 } catch (Exception ignore) { 1205 } 1206 } 1207 1208 Preferences.access().addObserver("javatest.executionOrder", new Preferences.Observer() { 1209 @Override 1210 public void updated(String name, String newValue) { 1211 1212 treeModel.getTestResultTable().updateTestExecutionOrderOnTheFly(); 1213 1214 try { 1215 WorkDirectory wd = execModel.getWorkDirectory(); 1216 TestResultTable trt = getTestResultTable(); 1217 if(trt != null && !wd.isTRTSet()) { 1218 wd.setTestResultTable(trt); 1219 } 1220 applyParameters(true); 1221 } catch (Exception ee) { 1222 ee.printStackTrace(); 1223 } 1224 1225 } 1226 }); 1227 } 1228 1229 private void ensureTreeSelection() { 1230 // make sure some node is always selected 1231 if (tree.getSelectionPath() == null) { 1232 TreeModel tm = tree.getModel(); 1233 try { 1234 TT_BasicNode root = (TT_BasicNode) (tm.getRoot()); 1235 //selectBranch(root, new TreePath(root)); 1236 tree.setRootVisible(true); 1237 EventQueue.invokeLater(new Selector(root, new TreePath(root))); 1238 } catch (ClassCastException e) { 1239 // shouldn't happen really 1240 if (debug) { 1241 e.printStackTrace(Debug.getWriter()); 1242 } 1243 } 1244 } 1245 } 1246 1247 private void updatePopupMenu() { 1248 TreePath[] paths = tree.getSelectionPaths(); 1249 1250 // neither of these should be possible, since the tree should 1251 // always have something selected 1252 if (paths == null || paths.length == 0) { 1253 return; 1254 } 1255 1256 if (paths.length == 1) { 1257 Object item = paths[0]; 1258 1259 if (item instanceof TreePath) { 1260 item = ((TreePath) item).getLastPathComponent(); 1261 // determine leaf type 1262 } 1263 if (item instanceof TT_TestNode) { 1264 TestResult tr = ((TT_TestNode) item).getTestResult(); 1265 if (testMenus != null) { 1266 for (int i = 0; i < testMenus.size(); i++) { 1267 testMenus.get(i).getMenu().setEnabled(true); 1268 testMenus.get(i).updateState(tr); 1269 } // for 1270 } 1271 if (customMenus != null) { 1272 for (int i = 0; i < customMenus.size(); i++) { 1273 customMenus.get(i).updateState(tr); 1274 } // for 1275 } 1276 if (mixedMenus != null) { 1277 for (int i = 0; i < mixedMenus.size(); i++) { 1278 mixedMenus.get(i).getMenu().setEnabled(true); 1279 mixedMenus.get(i).updateState(tr); 1280 } // for 1281 } 1282 if (folderMenus != null) { 1283 for (int i = 0; i < folderMenus.size(); i++) { 1284 folderMenus.get(i).getMenu().setEnabled(false); 1285 } // for 1286 } 1287 } else if (item instanceof TT_BasicNode) { 1288 String url = ((TT_BasicNode) item).getLongPath(); 1289 if (url == null) 1290 url = ""; // this is just how we define it 1291 1292 if (testMenus != null) { 1293 for (int i = 0; i < testMenus.size(); i++) { 1294 testMenus.get(i).getMenu().setEnabled(false); 1295 } // for 1296 } 1297 if (customMenus != null) { 1298 for (int i = 0; i < customMenus.size(); i++) { 1299 customMenus.get(i).updateState(url); 1300 } // for 1301 } 1302 if (mixedMenus != null) { 1303 for (int i = 0; i < mixedMenus.size(); i++) { 1304 mixedMenus.get(i).getMenu().setEnabled(true); 1305 mixedMenus.get(i).updateState(url); 1306 } // for 1307 } 1308 if (folderMenus != null) { 1309 for (int i = 0; i < folderMenus.size(); i++) { 1310 folderMenus.get(i).getMenu().setEnabled(true); 1311 folderMenus.get(i).updateState(url); 1312 } // for 1313 } 1314 } else { // should not happen! 1315 if (testMenus != null) { 1316 for (int i = 0; i < testMenus.size(); i++) { 1317 testMenus.get(i).getMenu().setEnabled(false); 1318 } // for 1319 } 1320 if (customMenus != null) { 1321 for (int i = 0; i < customMenus.size(); i++) { 1322 customMenus.get(i).getMenu().setEnabled(false); 1323 } // for 1324 } 1325 if (mixedMenus != null) { 1326 for (int i = 0; i < mixedMenus.size(); i++) { 1327 mixedMenus.get(i).getMenu().setEnabled(false); 1328 } // for 1329 } 1330 if (folderMenus != null) { 1331 for (int i = 0; i < folderMenus.size(); i++) { 1332 folderMenus.get(i).getMenu().setEnabled(false); 1333 } // for 1334 } 1335 1336 if (!(tree.getModel() instanceof EmptyTestTreeModel)) 1337 throw new JavaTestError("Unknown node type from JTree!"); 1338 } 1339 } else { // multiple nodes selected 1340 ArrayList<TestResult> tests = new ArrayList<>(); 1341 ArrayList<String> folders = new ArrayList<>(); 1342 1343 for (int i = 0; i < paths.length; i++) { 1344 Object item = paths[i]; 1345 1346 if (item instanceof TreePath) { 1347 item = ((TreePath) item).getLastPathComponent(); 1348 } 1349 1350 if (item instanceof TT_TestNode) { 1351 tests.add(((TT_TestNode) item).getTestResult()); 1352 } else { 1353 TT_BasicNode bn = (TT_BasicNode)item; 1354 if (bn.isRoot()) 1355 folders.add(""); 1356 else 1357 folders.add(bn.getLongPath()); 1358 } 1359 } // for 1360 1361 TestResult[] t = null; 1362 if (tests.size() > 0) { 1363 t = tests.toArray(new TestResult[tests.size()]); 1364 } 1365 1366 String[] f = null; 1367 if (folders.size() > 0) { 1368 f = folders.toArray(new String[folders.size()]); 1369 // currently enable/disabled state is only determined by the menu's 1370 // ability to deal with multi selection 1371 } 1372 1373 if (testMenus != null) { 1374 for (int i = 0; i < testMenus.size(); i++) { 1375 JavaTestContextMenu m = testMenus.get(i); 1376 m.getMenu().setEnabled(m.isMultiSelectAllowed()); 1377 m.updateState(f, t); 1378 } // for 1379 } 1380 if (customMenus != null) { 1381 for (int i = 0; i < customMenus.size(); i++) { 1382 JavaTestContextMenu m = customMenus.get(i); 1383 m.getMenu().setEnabled(m.isMultiSelectAllowed()); 1384 m.updateState(f, t); 1385 } // for 1386 } 1387 if (mixedMenus != null) { 1388 for (int i = 0; i < mixedMenus.size(); i++) { 1389 JavaTestContextMenu m = mixedMenus.get(i); 1390 m.getMenu().setEnabled(m.isMultiSelectAllowed()); 1391 m.updateState(f, t); 1392 } // for 1393 } 1394 if (folderMenus != null) { 1395 for (int i = 0; i < folderMenus.size(); i++) { 1396 JavaTestContextMenu m = folderMenus.get(i); 1397 m.getMenu().setEnabled(m.isMultiSelectAllowed()); 1398 m.updateState(f, t); 1399 } // for 1400 } 1401 } 1402 } 1403 1404 1405 /** 1406 * This method should be called on the AWT event thread. 1407 */ 1408 private void selectTest(TestResult tr, TreePath path) { 1409 if (debug) { 1410 Debug.println("TTP showing: " + tr); 1411 Debug.println(" -> path provided is " + path.getPathCount() + " components long."); 1412 } 1413 1414 if (disposed) { 1415 if (debug) { 1416 Debug.println("TTP - selectTest() not running, panel is disposed."); 1417 } 1418 return; 1419 } 1420 1421 if (!isPopulated()) { 1422 if (debug) { 1423 Debug.println("TTP - no data, cannot display a leaf. No action."); 1424 } 1425 return; 1426 } 1427 1428 brPanel.setVisible(false); 1429 deck.show(testPanel); 1430 1431 // translate into path for display 1432 // could reoptimize to use path param 1433 // otherwise path param is mostly deprecated 1434 TreePath jtPath = treeModel.resolveUrl(tr.getTestName()); 1435 // setup the tree 1436 if (jtPath != null && !tree.isPathSelected(jtPath)) { 1437 tree.clearSelection(); 1438 tree.setSelectionPath(jtPath); 1439 } 1440 1441 if (!tree.isVisible(jtPath)) { 1442 tree.scrollPathToVisible(jtPath); // setup the test panel 1443 } 1444 1445 if (tr != testPanel.getTest()) { 1446 // select new node 1447 activeTest = tr.getTestName(); 1448 // special case: if the selected test is running, the TR object in 1449 // the tree may not be the active one. We want to see the running 1450 // test so we can provide real-time monitoring, so we check the 1451 // list of active TR objects. 1452 TestResult atr = pm.getActive(tr); 1453 testPanel.setTest((atr == null ? tr : atr)); 1454 } else { 1455 // should we ask for a refresh if == ? 1456 // XXX could force an update here, which is needed 1457 // if test panel does not have dynamic update 1458 // no way to force as of 9/18/2002 though 1459 // this is a problem if the user selects a test while 1460 // it is in the running state, because the TR object 1461 // does not change, but the status of that object does 1462 // change 1463 } 1464 1465 // configure the right side title 1466 titleField.setText(uif.getI18NString("treep.test", tr.getTestName())); 1467 1468 testPanel.setVisible(true); 1469 1470 tree.repaint(); 1471 deckPanel.repaint(); 1472 } 1473 1474 /** 1475 * This method should be called on the AWT event thread. 1476 */ 1477 private void selectBranch(TT_BasicNode tn, TreePath path) { 1478 if (debug) { 1479 Debug.println("TTP showing: " + tn.getShortName()); 1480 Debug.println(" -> " + tn); 1481 Debug.println(" -> path provided is " + path.getPathCount() + " components long."); 1482 } 1483 1484 if (disposed) { 1485 if (debug) { 1486 Debug.println("TTP - selectBranch() not running, panel is disposed."); 1487 } 1488 return; 1489 } 1490 1491 if (!isPopulated()) { 1492 if (debug) { 1493 Debug.println("TTP - no data, cannot display a branch. No action."); 1494 } 1495 return; 1496 } 1497 1498 // get rid of the test panel and show the branch panel 1499 if (deck.getCurrentCard() != brPanel) { 1500 deck.show(brPanel); 1501 testPanel.setVisible(false); 1502 activeTest = null; 1503 } 1504 1505 // setup the tree 1506 if (!tree.isPathSelected(path)) { 1507 tree.clearSelection(); 1508 tree.setSelectionPath(path); 1509 } 1510 1511 if (!tree.isVisible(path)) { 1512 tree.scrollPathToVisible(path); // setup the branch panel 1513 } 1514 if (tn != brPanel.getNode()) { 1515 // select new node 1516 brPanel.setNode(tn); 1517 treeModel.setActiveNode(tn); // hint to cache 1518 1519 } else { 1520 // should we ask for a refresh if == ? 1521 } 1522 1523 // configure the right side title 1524 if (tn.isRoot()) { // root node, has no name 1525 TestSuite ts = params.getTestSuite(); 1526 String tsn = ts.getName(); 1527 if (tsn != null) // use descriptive name of TestSuite 1528 { 1529 titleField.setText(uif.getI18NString("treep.ts", tsn)); 1530 } else // TestSuite has no name, use root path 1531 { 1532 titleField.setText(uif.getI18NString("treep.ts", ts.getPath())); 1533 } 1534 } else { 1535 String nName = tn.getLongPath(); 1536 titleField.setText(uif.getI18NString("treep.node", nName)); 1537 } 1538 1539 if (!brPanel.isVisible()) { 1540 brPanel.setVisible(true); 1541 } 1542 1543 deckPanel.repaint(); 1544 tree.repaint(); 1545 } 1546 1547 private void selectNodes(String[] paths) { 1548 } 1549 1550 /** 1551 * Called when multiple nodes in the tree have been selected. 1552 * This method is invoked repeatably as the user adds more nodes to 1553 * the selection. 1554 */ 1555 private void selectNodes(TreePath[] paths) { 1556 if (!isPopulated()) { 1557 if (debug) { 1558 Debug.println("TTP - no data, cannot display selections. No action."); 1559 } 1560 return; 1561 } 1562 1563 Object[] leaves = new Object[paths.length]; 1564 for (int i = 0; i < paths.length; i++) { 1565 leaves[i] = paths[i].getLastPathComponent(); 1566 } 1567 msPanel.setNodes(leaves); 1568 1569 // get rid of the test panel and show the branch panel 1570 if (deck.getCurrentCard() != msPanel) { 1571 deck.show(msPanel); 1572 activeTest = null; 1573 } 1574 1575 // configure the right side title 1576 titleField.setText(uif.getI18NString("treep.ms")); 1577 1578 msPanel.setVisible(true); 1579 deckPanel.repaint(); 1580 } 1581 1582 /** 1583 * @param prefix i18n bundle prefix 1584 * @param args Arguments for the user message string, which is prefix.txt. 1585 */ 1586 private int showConfirmListDialog(String prefix, Object[] args, ListModel<?> model) { 1587 // resources needed: 1588 // prefix.title 1589 JPanel p = uif.createPanel("ttp.confirmPanel", false); 1590 JTextArea msg = uif.createMessageArea(prefix, args); 1591 p.setLayout(new BorderLayout()); 1592 p.add(msg, BorderLayout.NORTH); 1593 1594 JList<?> list = uif.createList("treep.nodeList", model); 1595 p.add(uif.createScrollPane(list, 1596 ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, 1597 ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED), BorderLayout.CENTER); 1598 1599 return uif.showCustomYesNoDialog(prefix, p); 1600 } 1601 1602 /** 1603 * Does this panel currently have data to work from. 1604 */ 1605 private boolean isPopulated() { 1606 if (params == null || params.getTestSuite() == null) { 1607 return false; 1608 } else { 1609 return true; 1610 } 1611 } 1612 private UIFactory uif; 1613 private Harness harness; 1614 private FilterSelectionHandler filterHandler; 1615 private ExecModel execModel; 1616 private JComponent parent; 1617 private Thread bgThread; // in case disposal is required 1618 private Map<String, String> stateMap; // startup state, read-only 1619 private volatile boolean disposed; 1620 private PanelModel pm; 1621 private TestTree tree; 1622 private TT_Renderer treeRend; 1623 private TestPanel testPanel; 1624 private BranchPanel brPanel; 1625 private MultiSelectPanel msPanel; 1626 private JPopupMenu popup; 1627 private TreePath lastPopupPath; 1628 private JMenuItem refreshMI; 1629 private JMenuItem purgeMI; 1630 private JMenuItem runMI; 1631 private String activeTest; 1632 private ArrayList<JavaTestContextMenu> testMenus, folderMenus, mixedMenus, customMenus; 1633 private TestTreeModel treeModel; 1634 private Deck deck; 1635 private JPanel deckPanel; 1636 private JTextField titleField; 1637 private Listener listener; 1638 private TestSuite lastTs; // last recorded testsuite 1639 private Parameters params; 1640 private Parameters newParams; 1641 private boolean newConfigAlreadyApplied = false; 1642 private boolean initialized = false; 1643 private static final int WAIT_DIALOG_DELAY = 3000; // 3 second delay 1644 private static final String OPEN_PATHS_PREF = "openpaths"; 1645 static protected boolean debug = Boolean.getBoolean("debug." + TestTreePanel.class.getName()); 1646 1647 /** 1648 * ET_Config method 1649 * @return null - no menu required 1650 */ 1651 public JMenu getMenu() { 1652 return null; 1653 } 1654 1655 /** 1656 * ET_Config method 1657 * @return null - no tool bar actions 1658 */ 1659 public List<Action> getToolBarActionList() { 1660 return null; 1661 } 1662 1663 public void setHarness(Harness h) { 1664 this.harness = h; 1665 if (harness != null && pm == null) { 1666 pm = new PanelModel(); 1667 harness.addObserver(pm); 1668 } 1669 } 1670 1671 /** 1672 * @return this 1673 */ 1674 public JComponent getViewComponent() { 1675 return this; 1676 } 1677 1678 public void setFilterSelectionHandler(FilterSelectionHandler fh) { 1679 this.filterHandler = fh; 1680 } 1681 1682 /** 1683 * Session.Observer method. Invoked when parameters object has been changed. 1684 * @param ev 1685 */ 1686 public void updated(Event ev) { 1687 if (ev instanceof BasicSession.E_NewConfig) { 1688 setParameters(((BasicSession.E_NewConfig)ev).ip); 1689 } else if (ev instanceof BasicSession.E_NewWD) { 1690 WorkDirectory wd = ((BasicSession.E_NewWD)ev).wd; 1691 try { 1692 TestResultTable trt = getTestResultTable(); 1693 if(trt != null && !wd.isTRTSet()) { 1694 wd.setTestResultTable(trt); 1695 } 1696 applyParameters(true); 1697 } catch (Exception ee) { 1698 ee.printStackTrace(); 1699 } 1700 } else if (ev instanceof BasicSessionControl.E_EditorVisibility) { 1701 this.runMI.setEnabled(!execModel.isConfiguring()); 1702 } 1703 } 1704 1705 private class Listener extends MouseAdapter 1706 implements ActionListener, TreeSelectionListener, 1707 TreeExpansionListener { 1708 // --- TreeSelectionListener --- 1709 public void valueChanged(TreeSelectionEvent e) { 1710 // make sure source is our tree 1711 // ignore the message if we are unselecting a path or if 1712 // this is a deletion event 1713 if (e.isAddedPath() && e.getSource() == tree) { 1714 TreePath[] tp = e.getPaths(); 1715 TestTree source = (TestTree) (e.getSource()); 1716 dispatchSelection(source); 1717 } 1718 } 1719 1720 // --- TreeExpansionListener --- 1721 // the path indicates the path to the node which contains the 1722 // now-(in)visible nodes 1723 public void treeCollapsed(TreeExpansionEvent event) { 1724 if (disposed) { 1725 return; 1726 /* 1727 // send a hint to the model indicating that some nodes 1728 // are no longer visible 1729 TreePath tp = event.getPath(); 1730 //Debug.println("collapsed " + ((TreeNode)(tp.getLastPathComponent())).getName()); 1731 TreeNode tn = (TreeNode)(tp.getLastPathComponent()); 1732 1733 TreeNode[] childs = tn.getTreeNodes(); 1734 if (childs != null) 1735 for (int i = 0; i < childs.length; i++) 1736 treeModel.removeRelevantNode(childs[i]); 1737 1738 TestResult[] trs = tn.getTestResults(); 1739 if (trs != null) 1740 for (int i = 0; i < trs.length; i++) 1741 treeModel.removeRelevantTest(trs[i]); 1742 */ 1743 } 1744 } 1745 1746 public void treeExpanded(TreeExpansionEvent event) { 1747 if (disposed || treeModel instanceof EmptyTestTreeModel) { 1748 return; // basically send a hint to the model indicating that some nodes 1749 // are now visible 1750 } 1751 TreePath tp = event.getPath(); 1752 TT_BasicNode tn = (TT_BasicNode) (tp.getLastPathComponent()); 1753 //Debug.println("expanded " + ((TreeNode)(tp.getLastPathComponent())).getName()); 1754 1755 for (int i = 0; i < tn.getChildCount(); i++) { 1756 treeModel.addRelevantNode((TT_TreeNode) (tn.getChildAt(i))); 1757 /* 1758 TestResult[] trs = tn.getTestResults(); 1759 if (trs != null) 1760 for (int i = 0; i < trs.length; i++) 1761 treeModel.addRelevantTest(trs[i]); 1762 */ 1763 } 1764 } 1765 1766 private void dispatchSelection(TestTree source) { 1767 TreePath[] paths = source.getSelectionPaths(); 1768 1769 if (paths == null || paths.length == 0) { 1770 return; 1771 } else if (paths.length == 1) { 1772 Object target = paths[0].getLastPathComponent(); 1773 1774 // single selection 1775 if (target instanceof TT_TestNode) { 1776 //EventQueue.invokeLater(new Selector((TestResult)target, path)); 1777 selectTest(((TT_TestNode) target).getTestResult(), paths[0]); 1778 } else if (target instanceof TT_BasicNode) { 1779 //EventQueue.invokeLater(new Selector((TreeNode)target, path)); 1780 selectBranch((TT_BasicNode) target, paths[0]); 1781 } else { 1782 // unknown target, ignore it I guess 1783 if (debug) { 1784 Debug.println("Unknown node click target in TestTreePanel: "); 1785 Debug.println(" => " + target); 1786 } else { 1787 } 1788 } 1789 } // outer elseif 1790 else { 1791 // multiselection 1792 selectNodes(paths); 1793 } 1794 } 1795 1796 // MouseAdapter for tree popup 1797 public void mousePressed(MouseEvent e) { 1798 maybeShowPopup(e); 1799 } 1800 1801 public void mouseReleased(MouseEvent e) { 1802 maybeShowPopup(e); 1803 } 1804 1805 private void updateSelection(MouseEvent e) { 1806 TreePath pathClicked = tree.getPathForLocation(e.getX(), e.getY()); 1807 if(pathClicked != null && tree.getSelectionCount() <= 1 && tree.getSelectionPath() != pathClicked) { 1808 tree.setSelectionPath(pathClicked); 1809 } 1810 } 1811 1812 private void maybeShowPopup(MouseEvent e) { 1813 if (e.isPopupTrigger() && e.getComponent() == tree) { 1814 lastX = e.getX(); 1815 lastY = e.getY(); 1816 updateSelection(e); 1817 // filter out clicks which don't hit the tree 1818 /* 1819 TreePath target = tree.getPathForLocation(lastX, lastY); 1820 1821 if (target != null) { 1822 lastPopupPath = target; 1823 */ 1824 updatePopupMenu(); 1825 popup.show(e.getComponent(), lastX, lastY); 1826 1827 /* 1828 // select node which was clicked on 1829 if (tree.getSelectionPath() == null) 1830 tree.setSelectionPath(target); 1831 } 1832 */ 1833 } 1834 } 1835 1836 // ActionListener 1837 public void actionPerformed(ActionEvent e) { 1838 TreePath[] paths = tree.getSelectionPaths(); 1839 1840 if (e.getActionCommand().equals("clear")) { 1841 if (paths != null && paths.length > 0) { 1842 clearNodes(tree.getSelectionPaths()); 1843 } else { 1844 // XXX show error dialog 1845 } 1846 } /* 1847 else if (e.getActionCommand().equals("info")) { 1848 showNodeInfoDialog(tree.getSelectionPaths()); 1849 } 1850 */ 1851 else if (e.getActionCommand().equals("run")) { 1852 if (paths != null && paths.length > 0) { 1853 // special case check, remove all items if root 1854 // is selected 1855 for (int i = 0; i < paths.length; i++) { 1856 if (paths[i].getPathCount() > 1) { 1857 continue; 1858 } 1859 Object target = paths[i].getPathComponent(0); 1860 1861 if (target instanceof TT_TreeNode && 1862 ((TT_TreeNode) target).isRoot()) { 1863 paths = new TreePath[]{new TreePath(target)}; 1864 break; 1865 } 1866 } // for 1867 runNodes(paths); 1868 } else { 1869 // XXX show error dialog 1870 } 1871 } else if (e.getActionCommand().equals("refresh")) { 1872 if (paths != null && paths.length > 0) { 1873 refreshNodes(tree.getSelectionPaths()); 1874 } else { 1875 // XXX show error dialog 1876 } 1877 } 1878 } 1879 private int lastX; 1880 private int lastY; 1881 } 1882 1883 /** 1884 * Utility class for scheduling an update using the GUI thread. 1885 */ 1886 class Selector implements Runnable { 1887 1888 Selector(TestResult tr, TreePath path) { 1889 this.tr = tr; 1890 this.tp = path; 1891 } 1892 1893 Selector(TT_TreeNode tn, TreePath path) { 1894 this.tn = tn; 1895 this.tp = path; 1896 } 1897 1898 public void run() { 1899 if (tr != null) { 1900 selectTest(tr, tp); 1901 } else { 1902 selectBranch((TT_BasicNode) tn, tp); 1903 } 1904 } 1905 private TreePath tp; 1906 private TestResult tr; 1907 private TT_TreeNode tn; 1908 } 1909 1910 private class TreePopupAction extends AbstractAction { 1911 1912 TreePopupAction(I18NResourceBundle bund, String key) { 1913 desc = bund.getString(key + ".desc"); 1914 name = bund.getString(key + ".act"); 1915 } 1916 1917 public void actionPerformed(ActionEvent e) { 1918 if (disposed) { 1919 return; 1920 } 1921 lastPopupPath = tree.getSelectionPath(); 1922 Rectangle loc = tree.getPathBounds(lastPopupPath); 1923 if (loc == null) { 1924 return; 1925 } 1926 updatePopupMenu(); 1927 popup.show(tree, 1928 loc.x + (int) loc.getWidth(), 1929 loc.y + (int) loc.getHeight()); 1930 } 1931 1932 public Object getValue(String key) { 1933 if (key == null) { 1934 throw new NullPointerException(); 1935 } 1936 if (key.equals(NAME)) { 1937 return name; 1938 } else if (key.equals(SHORT_DESCRIPTION)) { 1939 return desc; 1940 } else { 1941 return null; 1942 } 1943 } 1944 private String name; 1945 private String desc; 1946 } 1947 1948 private class PanelModel implements TreePanelModel, Harness.Observer, TestResultTable.Observer { 1949 1950 PanelModel() { 1951 runningTests = new Hashtable<>(); 1952 activeNodes = new Hashtable<>(); 1953 } 1954 1955 public void pauseWork() { 1956 if (treeModel != null) { 1957 treeModel.pauseWork(); 1958 } 1959 } 1960 1961 public void unpauseWork() { 1962 if (treeModel != null) { 1963 treeModel.unpauseWork(); 1964 } 1965 } 1966 1967 public void refreshTree() { 1968 String[] openPaths = null; 1969 String[] selectedPaths = null; 1970 if (tree != null) { 1971 TreePath[] p = tree.snapshotOpenPaths(); 1972 openPaths = treeModel.pathsToStrings(p); 1973 1974 selectedPaths = treeModel.pathsToStrings(tree.snapshotSelectedPaths()); 1975 1976 } 1977 1978 if (treeModel != null) { 1979 treeModel.notifyFullStructure(); 1980 } 1981 1982 1983 if (openPaths != null && openPaths.length > 0) 1984 tree.restorePaths(openPaths, true); 1985 1986 if (tree != null) { 1987 tree.restoreSelection(selectedPaths); 1988 } 1989 } 1990 1991 public void nodeSelected(Object node, TreePath path) { 1992 } 1993 1994 public void testSelected(TestResult node, TreePath path) { 1995 } 1996 1997 public void nodeUnSelected(Object node, TreePath path) { 1998 } 1999 2000 public void testUnSelected(TestResult node, TreePath path) { 2001 } 2002 2003 public void showNode(Object node, TreePath path) { 2004 selectBranch((TT_BasicNode) (node), path); 2005 } 2006 2007 public void showNode(String url) { 2008 TreePath path = treeModel.resolveUrl(url); 2009 if (path != null && path.getLastPathComponent() instanceof TT_BasicNode) { 2010 selectBranch((TT_BasicNode) (path.getLastPathComponent()), path); 2011 } 2012 } 2013 2014 public void showTest(TestResult node, TreePath path) { 2015 selectTest(node, path); 2016 } 2017 2018 public void showTest(TestResult tr) { 2019 /* 2020 TreeNode[] path = TestResultTable.getObjectPath(tr); 2021 Object[] fp = new Object[path.length + 1]; 2022 System.arraycopy(path, 0, fp, 0, path.length); 2023 fp[fp.length-1] = tr; 2024 */ 2025 TreePath tp = treeModel.resolveUrl(tr.getTestName()); 2026 if (tp != null && tp.getLastPathComponent() instanceof TT_TreeNode) { 2027 showTest(tr, tp); 2028 } 2029 } 2030 2031 public void showTest(String url) { 2032 TestResultTable trt = getTestResultTable(); 2033 2034 if (trt == null) { 2035 return; 2036 } else { 2037 TestResult tr = trt.lookup(TestResult.getWorkRelativePath(url)); 2038 if (tr != null) { 2039 showTest(tr); 2040 } 2041 } 2042 } 2043 2044 public void hideNode(Object node, TreePath path) { 2045 } 2046 2047 public void hideTest(TestResult node, TreePath path) { 2048 } 2049 2050 public TestResultTable getTestResultTable() { 2051 return treeModel.getTestResultTable(); 2052 } 2053 2054 public String getSelectedTest() { 2055 return activeTest; 2056 } 2057 2058 public boolean isActive(TestResult tr) { 2059 if (runningTests.containsKey(tr.getTestName())) { 2060 return true; 2061 } else { 2062 return false; 2063 } 2064 } 2065 2066 public TestResult getActive(TestResult tr) { 2067 return runningTests.get(tr.getTestName()); 2068 } 2069 2070 public boolean isActive(TT_TreeNode node) { 2071 if (activeNodes.containsKey(node)) { 2072 return true; 2073 } else { 2074 return false; 2075 } 2076 } 2077 2078 // Harness.Observer 2079 public void startingTestRun(Parameters params) { 2080 runMI.setEnabled(false); 2081 purgeMI.setEnabled(false); 2082 refreshMI.setEnabled(false); 2083 } 2084 2085 public void startingTest(TestResult tr) { 2086 if (treeModel == null) // may occur during shutdown, see dispose() 2087 { 2088 return; // BK needed anymore? see renderer 2089 2090 //TestResult lookupTr = treeModel.getTestResultTable().lookup(tr.getWorkRelativePath()); 2091 //TreePath tp = treeModel.resolveUrl(tr.getWorkRelativePath()); 2092 } 2093 2094 runningTests.put(tr.getTestName(), tr); 2095 2096 /* 2097 TreeNode[] trtPath = TestResultTable.getObjectPath(tr); 2098 TT_TreeNode[] nodes = treeModel.translatePath(trtPath, false); 2099 if (nodes == null) { 2100 if (debug) { 2101 Debug.println("** " + tr.getTestName()); 2102 } 2103 return; 2104 }*/ 2105 2106 TreePath tp = treeModel.urlToPath(tr.getTestName()); 2107 if (tp != null) { 2108 Object[] nodes = tp.getPath(); 2109 2110 for (int i = 0; i < nodes.length; i++) { 2111 Integer hit = activeNodes.get(nodes[i]); 2112 if (hit == null) // not currently an active node 2113 { 2114 activeNodes.put(nodes[i], ONE); 2115 } else { 2116 activeNodes.put(nodes[i], 2117 new Integer(1 + hit)); 2118 } 2119 } 2120 } 2121 2122 tree.repaint(); // we're allowed to call this on any thread 2123 } 2124 2125 public void finishedTest(TestResult tr) { 2126 if (treeModel == null) // may occur during shutdown, see dispose() 2127 { 2128 return; //runningTests.remove(tr.getTestName()); 2129 // it's very important for items to be correctly removed 2130 // from the hashtables 2131 } 2132 2133 runningTests.remove(tr.getTestName()); 2134 2135 TreeNode[] trtPath = TestResultTable.getObjectPath(tr); 2136 TT_TreeNode[] nodes = treeModel.translatePath(trtPath, false); 2137 if (tr.getTestName().equals(activeTest)) { 2138 Object[] p = new Object[nodes.length + 1]; 2139 System.arraycopy(nodes, 0, p, 0, nodes.length); 2140 p[p.length - 1] = tr; 2141 EventQueue.invokeLater(new Selector(tr, new TreePath(p))); 2142 } 2143 2144 if (nodes != null) { 2145 for (int i = 0; i < nodes.length; i++) { 2146 Integer hit = activeNodes.get(nodes[i]); 2147 if (hit == null) { 2148 // should only really happen when test run finished, not 2149 // during the run 2150 continue; 2151 } 2152 if (hit == ONE) { 2153 activeNodes.remove(nodes[i]); 2154 } else { 2155 int currHits = hit.intValue(); 2156 activeNodes.put(nodes[i], 2157 (currHits == 2 ? ONE : new Integer(--currHits))); 2158 } 2159 } // for 2160 } 2161 tree.repaint(); // we're allowed to call this on any thread 2162 } 2163 2164 public void stoppingTestRun() { 2165 } 2166 2167 public void finishedTesting() { 2168 } 2169 2170 public void finishedTestRun(boolean allOK) { 2171 runningTests.clear(); 2172 activeNodes.clear(); 2173 2174 runMI.setEnabled(!execModel.isConfiguring()); 2175 purgeMI.setEnabled(true); 2176 refreshMI.setEnabled(true); 2177 2178 tree.repaint(); // we're allowed to call this on any thread 2179 } 2180 2181 public void error(String msg) { 2182 } 2183 2184 // TestResultTable.Observer 2185 public void update(TestResult oldValue, TestResult newValue) { 2186 /* BK reenable 2187 if (treeModel == null || treeModel.getTestResultTable() == null) 2188 return; 2189 2190 // this is primarily to ensure that the subpanel gets updated when 2191 // asynchronous (non-user GUI) events occur 2192 // example - if a "clear" operation is done, which includes the shown test 2193 // SWITCH ONTO EVENT THREAD 2194 if (newValue.getTestName().equals(activeTest)) { 2195 TestResult lookupTr = treeModel.getTestResultTable().lookup( 2196 newValue.getWorkRelativePath()); 2197 TreeNode[] nodes = TestResultTable.getObjectPath(lookupTr); 2198 2199 Object[] p = new Object[nodes.length + 1]; 2200 System.arraycopy(nodes, 0, p, 0, nodes.length); 2201 p[p.length-1] = newValue; 2202 EventQueue.invokeLater(new Selector(newValue, new TreePath(p))); 2203 } 2204 */ 2205 } 2206 2207 public void updated(TestResult whichTR) { 2208 // ignore 2209 } 2210 private Hashtable<String,TestResult> runningTests; 2211 private Hashtable<Object, Integer> activeNodes; 2212 private Integer ONE = Integer.valueOf(1); 2213 } 2214 }