1 /* 2 * $Id$ 3 * 4 * Copyright (c) 2001, 2013, 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.CardLayout; 31 import java.awt.Component; 32 import java.awt.Dimension; 33 import java.awt.EventQueue; 34 import java.io.IOException; 35 import java.io.StringWriter; 36 import javax.swing.BorderFactory; 37 import javax.swing.DefaultListCellRenderer; 38 import javax.swing.DefaultListModel; 39 import javax.swing.Icon; 40 import javax.swing.ListSelectionModel; 41 import javax.swing.JEditorPane; 42 import javax.swing.JLabel; 43 import javax.swing.JList; 44 import javax.swing.JPanel; 45 import javax.swing.JScrollPane; 46 import javax.swing.JSplitPane; 47 import javax.swing.JTextArea; 48 import javax.swing.JTextField; 49 import javax.swing.event.HyperlinkEvent; 50 import javax.swing.event.HyperlinkListener; 51 import javax.swing.event.ListSelectionEvent; 52 import javax.swing.event.ListSelectionListener; 53 import javax.swing.text.html.HTMLDocument; 54 import javax.swing.text.html.HTMLEditorKit; 55 import javax.swing.text.html.StyleSheet; 56 57 import com.sun.javatest.JavaTestError; 58 import com.sun.javatest.Status; 59 import com.sun.javatest.TestResult; 60 import com.sun.javatest.tool.IconFactory; 61 import com.sun.javatest.tool.Preferences; 62 import com.sun.javatest.tool.UIFactory; 63 import com.sun.javatest.report.HTMLWriterEx; 64 import com.sun.javatest.util.StringArray; 65 import com.sun.javatest.tool.jthelp.ContextHelpManager; 66 67 /** 68 * Show the output sections for a particular test result. 69 * This panel will dynamically update data if the test is running. 70 */ 71 72 class TP_OutputSubpanel extends TP_Subpanel { 73 74 String currentTOCEntry = null; 75 76 TP_OutputSubpanel(UIFactory uif) { 77 super(uif, "out"); 78 initGUI(); 79 } 80 81 protected synchronized void updateSubpanel(TestResult newTest) { 82 if (subpanelTest != null) 83 subpanelTest.removeObserver(observer); 84 85 super.updateSubpanel(newTest); 86 updateTOC(); 87 88 // if it is mutable, track updates 89 if (subpanelTest.isMutable()) { 90 subpanelTest.addObserver(observer); 91 } 92 } 93 94 private void initGUI() { 95 setLayout(new BorderLayout()); 96 97 tocEntries = new DefaultListModel<>(); 98 toc = uif.createList("test.out.toc", tocEntries); 99 toc.setCellRenderer(new TOCRenderer()); 100 toc.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); 101 toc.setPrototypeCellValue("12345678901234567890"); 102 toc.setVisibleRowCount(10); 103 toc.addListSelectionListener(listener); 104 105 JScrollPane scrollableTOC = 106 uif.createScrollPane(toc, 107 JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, 108 JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); 109 110 main = new JPanel(new BorderLayout()); 111 titleField = uif.createOutputField("test.out.title"); 112 titleField.setBackground(UIFactory.Colors.PRIMARY_CONTROL_DARK_SHADOW.getValue()); 113 titleField.setForeground(UIFactory.Colors.WINDOW_BACKGROUND.getValue()); 114 main.add(titleField, BorderLayout.NORTH); 115 116 body = new JPanel(new CardLayout()) { 117 public Dimension getPreferredSize() { 118 int dpi = uif.getDotsPerInch(); 119 return new Dimension(3 * dpi, 3 * dpi); 120 } 121 }; 122 123 124 textArea = uif.createTextArea("test.out.textbody"); 125 textArea.setEditable(false); 126 textArea.setLineWrap(wrap); 127 textArea.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); 128 body.add(uif.createScrollPane(textArea, 129 JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, 130 JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED), 131 "text"); 132 133 htmlArea = new JEditorPane(); 134 htmlArea.setName("out_summ"); 135 htmlArea.getAccessibleContext().setAccessibleName(uif.getI18NString("test.out.summ.name")); 136 htmlArea.getAccessibleContext().setAccessibleDescription(uif.getI18NString("test.out.summ.name")); 137 //htmlArea.setContentType("text/html"); 138 139 // create and set a vacuous subtype of HTMLDocument, simply in order 140 // to have the right classloader associated with it, that can load 141 // any related OBJECT tags 142 htmlArea.setDocument(new HTMLDocument(getStyleSheet()) { }); 143 htmlArea.setEditable(false); 144 htmlArea.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); 145 htmlArea.addHyperlinkListener(listener); 146 body.add(uif.createScrollPane(htmlArea, 147 JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, 148 JScrollPane.HORIZONTAL_SCROLLBAR_NEVER), 149 "html"); 150 151 main.add(body, BorderLayout.CENTER); 152 153 JSplitPane sp = 154 new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, scrollableTOC, main); 155 sp.setBorder(BorderFactory.createLoweredBevelBorder()); 156 sp.setResizeWeight(0); // all excess space to right hand side 157 add(sp); 158 159 ContextHelpManager.setHelpIDString(this, "browse.outputTab.csh"); 160 initIcons(); 161 } 162 163 private void initIcons() { 164 streamIcon = uif.createIcon("test.out.sect.stream"); 165 } 166 167 private String getStatusKey(int i) { 168 String s; 169 switch (i) { 170 case Status.PASSED: return "passed"; 171 case Status.FAILED: return "failed"; 172 case Status.ERROR: return "error"; 173 case Status.NOT_RUN: return "notRun"; 174 default: return "unknown"; 175 } 176 } 177 178 private String createNotRunSummary() { 179 StringWriter sw = new StringWriter(); 180 try { 181 HTMLWriterEx out = new HTMLWriterEx(sw, uif.getI18NResourceBundle()); 182 out.startTag(HTMLWriterEx.HTML); 183 out.startTag(HTMLWriterEx.HEAD); 184 out.writeContentMeta(); 185 out.endTag(HTMLWriterEx.HEAD); 186 out.startTag(HTMLWriterEx.BODY); 187 //out.writeStyleAttr(bodyStyle); 188 out.writeI18N("test.out.smry.testNotRun"); 189 out.endTag(HTMLWriterEx.BODY); 190 out.endTag(HTMLWriterEx.HTML); 191 out.close(); 192 } 193 catch (IOException e) { 194 // should not happen, with StringWriter 195 } 196 return sw.toString(); 197 } 198 199 private String createSummary() { 200 StringWriter sw = new StringWriter(); 201 try { 202 HTMLWriterEx out = new HTMLWriterEx(sw, uif.getI18NResourceBundle()); 203 out.startTag(HTMLWriterEx.HTML); 204 out.startTag(HTMLWriterEx.HEAD); 205 out.writeContentMeta(); 206 out.endTag(HTMLWriterEx.HEAD); 207 out.startTag(HTMLWriterEx.BODY); 208 //out.writeStyleAttr(bodyStyle); 209 210 String[] scriptAndArgs; 211 try { 212 scriptAndArgs = StringArray.split(subpanelTest.getProperty(TestResult.SCRIPT)); 213 } 214 catch (TestResult.Fault e) { 215 scriptAndArgs = null; 216 } 217 218 String script = (scriptAndArgs == null || scriptAndArgs.length == 0 219 ? uif.getI18NString("test.out.smry.unknownScript") 220 : scriptAndArgs[0]); 221 out.writeI18N("test.out.script"); 222 out.startTag(HTMLWriterEx.TABLE); 223 out.writeAttr(HTMLWriterEx.BORDER, "0"); 224 //out.writeStyleAttr(tableStyle); 225 out.startTag(HTMLWriterEx.TR); 226 out.startTag(HTMLWriterEx.TD); 227 out.startTag(HTMLWriterEx.CODE); 228 out.write(script); 229 out.endTag(HTMLWriterEx.CODE); 230 out.endTag(HTMLWriterEx.TD); 231 out.endTag(HTMLWriterEx.TR); 232 out.endTag(HTMLWriterEx.TABLE); 233 if (scriptAndArgs != null && scriptAndArgs.length > 1) { 234 out.writeI18N("test.out.scriptArgs"); 235 out.startTag(HTMLWriterEx.TABLE); 236 out.writeAttr(HTMLWriterEx.BORDER, "0"); 237 //out.writeStyleAttr(tableStyle); 238 for (int i = 1; i < scriptAndArgs.length; i++) { 239 out.startTag(HTMLWriterEx.TR); 240 out.startTag(HTMLWriterEx.TD); 241 out.startTag(HTMLWriterEx.CODE); 242 out.write(scriptAndArgs[i]); 243 out.endTag(HTMLWriterEx.CODE); 244 out.endTag(HTMLWriterEx.TD); 245 out.endTag(HTMLWriterEx.TR); 246 } 247 out.endTag(HTMLWriterEx.TABLE); 248 } 249 250 if (subpanelTest.getSectionCount() > 0) { 251 TestResult.Section s = subpanelTest.getSection(0); 252 if (s.getTitle().equals(TestResult.MSG_SECTION_NAME)) { 253 out.writeI18N("test.out.smry.scriptLog.txt"); 254 out.startTag(HTMLWriterEx.TABLE); 255 out.writeAttr(HTMLWriterEx.BORDER, "0"); 256 //out.writeStyleAttr(tableStyle); 257 String[] names = s.getOutputNames(); 258 for (int i = 0; i < names.length; i++) { 259 String name = names[i]; 260 String text = s.getOutput(name); 261 out.startTag(HTMLWriterEx.TR); 262 out.startTag(HTMLWriterEx.TD); 263 out.writeLink("#" + name, name/*, linkStyle*/); 264 out.endTag(HTMLWriterEx.TD); 265 out.endTag(HTMLWriterEx.TR); 266 } 267 out.endTag(HTMLWriterEx.TABLE); 268 } 269 } 270 271 // generate a table showing the various sections 272 if (subpanelTest.getSectionCount() > 0) { 273 out.startTag(HTMLWriterEx.H3); 274 //out.writeStyleAttr(h3Style); 275 out.writeI18N("test.out.smry.sections.head"); 276 out.endTag(HTMLWriterEx.H3); 277 out.writeI18N("test.out.smry.sections.txt"); 278 out.startTag(HTMLWriterEx.TABLE); 279 out.writeAttr(HTMLWriterEx.BORDER, "0"); 280 //out.writeStyleAttr(tableStyle); 281 for (int i = 0; i < subpanelTest.getSectionCount(); i++) { 282 TestResult.Section s = subpanelTest.getSection(i); 283 if (s.getTitle().equals(TestResult.MSG_SECTION_NAME)) 284 continue; // already done, above 285 out.startTag(HTMLWriterEx.TR); 286 out.startTag(HTMLWriterEx.TD); 287 out.startTag(HTMLWriterEx.OBJECT); 288 out.writeAttr(HTMLWriterEx.CLASSID, "com.sun.javatest.tool.IconLabel"); 289 out.writeParam("type", "testSection"); 290 out.writeParam("state", getStatusKey(s.getStatus().getType())); 291 out.endTag(HTMLWriterEx.OBJECT); 292 out.writeLink(String.valueOf(i), s.getTitle()/*, linkStyle*/); 293 out.endTag(HTMLWriterEx.TD); 294 out.endTag(HTMLWriterEx.TR); 295 } 296 out.endTag(HTMLWriterEx.TABLE); 297 298 out.startTag(HTMLWriterEx.H3); 299 //out.writeStyleAttr(h3Style); 300 out.writeI18N("test.out.outcome.head"); 301 out.endTag(HTMLWriterEx.H3); 302 out.writeI18N("test.out.testResultForOutput.txt"); 303 } 304 else { 305 out.startTag(HTMLWriterEx.H3); 306 //out.writeStyleAttr(h3Style); 307 out.writeI18N("test.out.outcome.head"); 308 out.endTag(HTMLWriterEx.H3); 309 out.writeI18N("test.out.testResultNoOutput.txt"); 310 } 311 312 Status s = subpanelTest.getStatus(); 313 out.startTag(HTMLWriterEx.TABLE); 314 out.writeAttr(HTMLWriterEx.BORDER, "0"); 315 //out.writeStyleAttr(tableStyle); 316 out.startTag(HTMLWriterEx.TR); 317 out.startTag(HTMLWriterEx.TD); 318 out.startTag(HTMLWriterEx.OBJECT); 319 out.writeAttr(HTMLWriterEx.CLASSID, "com.sun.javatest.tool.IconLabel"); 320 out.writeParam("type", "test"); 321 out.writeParam("state", getStatusKey(s.getType())); 322 out.endTag(HTMLWriterEx.OBJECT); 323 out.endTag(HTMLWriterEx.TD); 324 out.startTag(HTMLWriterEx.TD); 325 out.write(s.toString()); 326 out.endTag(HTMLWriterEx.TD); 327 out.endTag(HTMLWriterEx.TR); 328 out.endTag(HTMLWriterEx.TABLE); 329 330 out.endTag(HTMLWriterEx.BODY); 331 out.endTag(HTMLWriterEx.HTML); 332 out.close(); 333 } 334 catch (IOException e) { 335 // should not happen, writing to StringWriter 336 } 337 catch (TestResult.ReloadFault e) { 338 throw new JavaTestError("Error loading result file for " + 339 subpanelTest.getTestName()); 340 } 341 342 return sw.toString(); 343 } 344 345 private String createSectionSummary(TestResult.Section section) { 346 StringWriter sw = new StringWriter(); 347 try { 348 HTMLWriterEx out = new HTMLWriterEx(sw, uif.getI18NResourceBundle()); 349 out.startTag(HTMLWriterEx.HTML); 350 out.startTag(HTMLWriterEx.HEAD); 351 out.writeContentMeta(); 352 out.endTag(HTMLWriterEx.HEAD); 353 out.startTag(HTMLWriterEx.BODY); 354 //out.writeStyleAttr(bodyStyle); 355 356 // generate a table showing the size of the various output streams 357 out.startTag(HTMLWriterEx.H3); 358 out.writeStyleAttr("margin-top: 0"); 359 out.writeI18N("test.out.outputSummary.head"); 360 out.endTag(HTMLWriterEx.H3); 361 out.writeI18N("test.out.outputSummary.txt"); 362 out.startTag(HTMLWriterEx.TABLE); 363 out.writeAttr(HTMLWriterEx.BORDER, "0"); 364 //out.writeStyleAttr(tableStyle); 365 out.startTag(HTMLWriterEx.TR); 366 out.startTag(HTMLWriterEx.TH); 367 out.writeAttr(HTMLWriterEx.STYLE, HTMLWriterEx.TEXT_LEFT); 368 out.writeI18N("test.out.outputName.txt"); 369 out.endTag(HTMLWriterEx.TH); 370 out.startTag(HTMLWriterEx.TH); 371 out.writeAttr(HTMLWriterEx.STYLE, HTMLWriterEx.TEXT_LEFT); 372 out.writeStyleAttr("margin-left:10"); 373 out.writeI18N("test.out.outputSize.txt"); 374 out.endTag(HTMLWriterEx.TH); 375 out.endTag(HTMLWriterEx.TR); 376 String[] names = section.getOutputNames(); 377 for (int i = 0; i < names.length; i++) { 378 String name = names[i]; 379 String text = section.getOutput(name); 380 out.startTag(HTMLWriterEx.TR); 381 out.startTag(HTMLWriterEx.TD); 382 if (text.length() == 0) 383 out.write(name); 384 else 385 out.writeLink("#" + name, name/*, linkStyle*/); 386 out.endTag(HTMLWriterEx.TD); 387 out.startTag(HTMLWriterEx.TD); 388 out.writeStyleAttr("margin-left:10"); 389 if (text.length() == 0) 390 out.writeI18N("test.out.empty.txt"); 391 else 392 out.write(String.valueOf(text.length())); 393 out.endTag(HTMLWriterEx.TD); 394 out.endTag(HTMLWriterEx.TR); 395 } 396 out.endTag(HTMLWriterEx.TABLE); 397 398 // if there is a status, show it 399 Status s = section.getStatus(); 400 if (s != null) { 401 out.startTag(HTMLWriterEx.H3); 402 //out.writeStyleAttr(h3Style); 403 out.writeI18N("test.out.outcome.head"); 404 out.endTag(HTMLWriterEx.H3); 405 out.writeI18N("test.out.sectionResult.txt"); 406 out.startTag(HTMLWriterEx.P); 407 out.writeStyleAttr("margin-left:30; margin-top:0; font-size: 12pt"); 408 out.startTag(HTMLWriterEx.OBJECT); 409 out.writeAttr(HTMLWriterEx.CLASSID, "com.sun.javatest.tool.IconLabel"); 410 out.writeParam("type", "testSection"); 411 out.writeParam("state", getStatusKey(s.getType())); 412 out.endTag(HTMLWriterEx.OBJECT); 413 out.write(s.toString()); 414 out.endTag(HTMLWriterEx.P); 415 } 416 417 out.endTag(HTMLWriterEx.BODY); 418 out.endTag(HTMLWriterEx.HTML); 419 out.close(); 420 } 421 catch (IOException e) { 422 // should not happen with StringWriter 423 } 424 return sw.toString(); 425 } 426 427 private String createStatusSummary() { 428 StringWriter sw = new StringWriter(); 429 try { 430 HTMLWriterEx out = new HTMLWriterEx(sw, uif.getI18NResourceBundle()); 431 out.startTag(HTMLWriterEx.HTML); 432 out.startTag(HTMLWriterEx.HEAD); 433 out.writeContentMeta(); 434 out.endTag(HTMLWriterEx.HEAD); 435 out.startTag(HTMLWriterEx.BODY); 436 //out.writeStyleAttr(bodyStyle); 437 438 if (subpanelTest.getSectionCount() > 0) 439 out.writeI18N("test.out.testResultForOutput.txt"); 440 else 441 out.writeI18N("test.out.testResultNoOutput.txt"); 442 443 Status s = subpanelTest.getStatus(); 444 out.startTag(HTMLWriterEx.TABLE); 445 out.writeAttr(HTMLWriterEx.BORDER, "0"); 446 //out.writeStyleAttr(tableStyle); 447 out.startTag(HTMLWriterEx.TR); 448 out.startTag(HTMLWriterEx.TD); 449 out.startTag(HTMLWriterEx.OBJECT); 450 out.writeAttr(HTMLWriterEx.CLASSID, "com.sun.javatest.tool.IconLabel"); 451 out.writeParam("type", "test"); 452 out.writeParam("state", getStatusKey(s.getType())); 453 out.endTag(HTMLWriterEx.OBJECT); 454 out.endTag(HTMLWriterEx.TD); 455 out.startTag(HTMLWriterEx.TD); 456 out.write(s.toString()); 457 out.endTag(HTMLWriterEx.TD); 458 out.endTag(HTMLWriterEx.TR); 459 out.endTag(HTMLWriterEx.TABLE); 460 out.endTag(HTMLWriterEx.BODY); 461 out.endTag(HTMLWriterEx.HTML); 462 out.close(); 463 } 464 catch (IOException e) { 465 // should not happen, for StringWriter 466 } 467 return sw.toString(); 468 } 469 470 void updateTOC() { 471 try { 472 TOCEntry newSelectedEntry = null; 473 tocEntries.setSize(0); 474 for (int i = 0; i < subpanelTest.getSectionCount(); i++) { 475 TestResult.Section s = subpanelTest.getSection(i); 476 TOCEntry e = new TOCEntry(s); 477 if (e.isScriptMessagesSection() && (currentTOCEntry == null) || 478 (e.getID().equals(currentTOCEntry))) 479 newSelectedEntry = e; 480 tocEntries.addElement(e); 481 String[] names = s.getOutputNames(); 482 for (int j = 0; j < names.length; j++) { 483 e = new TOCEntry(s, names[j]); 484 if (e.getID().equals(currentTOCEntry)) { 485 newSelectedEntry = e; 486 } 487 tocEntries.addElement(e); 488 } 489 } 490 491 TOCEntry e = new TOCEntry(); // for final status 492 if (newSelectedEntry == null) 493 newSelectedEntry = e; 494 tocEntries.addElement(e); 495 496 currentTOCEntry = newSelectedEntry.getID(); 497 toc.setSelectedValue(newSelectedEntry, true); 498 } 499 catch (TestResult.ReloadFault e) { 500 throw new JavaTestError("Error loading result file for " + 501 subpanelTest.getTestName()); 502 } 503 } 504 505 private void updateTOCLater() { 506 if (EventQueue.isDispatchThread()) 507 updateTOC(); 508 else { 509 EventQueue.invokeLater(new Runnable() { 510 public void run() { 511 updateTOC(); // will also update current entry 512 } 513 }); 514 } 515 } 516 517 /** 518 * @param tr Result being updated. 519 * @param section Section being updated. 520 * @param outputName Output in section being updated, may be null. 521 * @param start Start index from TestResult API 522 * @param end End index from TestResult API 523 * @param text New text. 524 * @see com.sun.javatest.TestResult 525 */ 526 private void updateOutput(final TestResult tr, final TestResult.Section section, 527 final String outputName, 528 final int start, final int end, final String text) { 529 //System.err.println("TPOS_TRO: written output[" + section.getTitle() + "/" + outputName + "]: " + tr.getWorkRelativePath()); 530 TOCEntry entry = findTOCEntry(section); 531 // should happen zero or one times per section 532 // primarily to catch observer messages that were missed before this 533 // panel attached to the TR. 534 if (entry == null) { 535 updateTOC(); 536 return; // return because it can't possibly be selected by user yet 537 } 538 539 // are we actually looking at the section being updated? 540 entry = (TOCEntry) (toc.getSelectedValue()); 541 if (entry.getSection() == section && outputName == entry.getOutputName()) { 542 addText(section, outputName, text); 543 } 544 } 545 546 547 private TOCEntry findTOCEntry(TestResult.Section section) { 548 if (tocEntries == null) 549 return null; 550 551 for (int i = 0; i < tocEntries.size(); i++) { 552 TOCEntry entry = tocEntries.get(i); 553 if (entry.getSection() == section) { 554 // found match, select this entry 555 return entry; 556 } 557 } 558 return null; 559 } 560 561 private void showHTML(String s) { 562 // high cost method call 563 htmlArea.setContentType("text/html"); 564 565 // try resetting doc to an empty doc before setting new text 566 567 // create and set a vacuous subtype of HTMLDocument, simply in order 568 // to have the right classloader associated with it, that can load 569 // any related OBJECT tags 570 HTMLDocument doc = new HTMLDocument(getStyleSheet()) { }; 571 htmlArea.setDocument(doc); 572 htmlArea.setText(s); 573 574 /* 575 StyleSheet styles = doc.getStyleSheet(); 576 Enumeration rules = styles.getStyleNames(); 577 while (rules.hasMoreElements()) { 578 String name = (String) rules.nextElement(); 579 System.out.println(styles.getStyle(name)); 580 } 581 */ 582 583 ((CardLayout)(body.getLayout())).show(body, "html"); 584 } 585 586 private void showText(String s) { 587 if (s.length() == 0) { 588 textArea.setText(uif.getI18NString("test.out.empty.txt")); 589 textArea.setEnabled(false); 590 } 591 else { 592 wrap = Boolean.parseBoolean(prefs.getPreference(LINE_WRAP_PREF, Boolean.toString(true))); 593 if (wrap) { 594 textArea.setLineWrap(true); 595 } else { 596 textArea.setLineWrap(false); 597 } 598 textArea.setText(s); 599 textArea.setCaretPosition(0); 600 textArea.setEnabled(true); 601 } 602 603 ((CardLayout)(body.getLayout())).show(body, "text"); 604 } 605 606 private void addText(TestResult.Section section, 607 String outputName, String s) { 608 if (s == null || s.length() == 0) 609 return; 610 611 if (!textArea.isEnabled()) { 612 textArea.setText(""); 613 textArea.append(s); 614 textArea.setEnabled(true); 615 } 616 else if (outputName != null) { 617 textArea.append(s); 618 } 619 } 620 621 private StyleSheet getStyleSheet() { 622 if (htmlEditorKit == null) 623 htmlEditorKit = new HTMLEditorKit(); 624 625 if (styleSheet == null) { 626 styleSheet = new StyleSheet(); 627 styleSheet.addStyleSheet(htmlEditorKit.getStyleSheet()); 628 styleSheet.addRule("body { font-family: SansSerif; font-size: 12pt }"); 629 styleSheet.addRule("h3 { margin-top:15 }"); 630 styleSheet.addRule("table { margin-left:30; margin-top:0 }"); 631 } 632 return styleSheet; 633 } 634 635 private boolean wrap = true; 636 private Preferences prefs = Preferences.access(); 637 public static final String LINE_WRAP_PREF = "testOutput.lineWrap"; 638 private Icon streamIcon; 639 private JList toc; 640 private JTextField titleField; 641 private JPanel body; 642 private JPanel main; 643 private JTextArea textArea; 644 645 private JEditorPane htmlArea; 646 647 private DefaultListModel<TOCEntry> tocEntries; 648 private Listener listener = new Listener(); 649 private TRObserver observer = new TRObserver(); 650 651 private StyleSheet styleSheet; 652 private HTMLEditorKit htmlEditorKit; 653 654 //------------------------------------------------------------------------------------ 655 656 private class Listener implements HyperlinkListener, ListSelectionListener 657 { 658 public void hyperlinkUpdate(HyperlinkEvent e) { 659 if (e.getEventType().equals(HyperlinkEvent.EventType.ACTIVATED)) { 660 String desc = e.getDescription(); 661 if (desc.startsWith("#")) { 662 String outputName = desc.substring(1); 663 // search for the output entry for the currently selected section 664 int index = toc.getSelectedIndex(); 665 if (index != -1) { 666 for (int i = index + 1; i < tocEntries.size(); i++) { 667 TOCEntry entry = tocEntries.get(i); 668 String entryOutputName = entry.getOutputName(); 669 if (entryOutputName == null) 670 // name not found, reached next section entry 671 break; 672 else if (entryOutputName.equals(outputName)) { 673 // found match, select this entry 674 toc.setSelectedIndex(i); 675 return; 676 } 677 } 678 } 679 } 680 else { 681 try { 682 int sectIndex = Integer.parseInt(desc); 683 TestResult.Section s = subpanelTest.getSection(sectIndex); 684 for (int i = 0; i < tocEntries.size(); i++) { 685 TOCEntry entry = tocEntries.get(i); 686 if (entry.getSection() == s) { 687 // found match, select this entry 688 toc.setSelectedIndex(i); 689 return; 690 } 691 } 692 693 } 694 catch (TestResult.ReloadFault f) { 695 throw new JavaTestError("Error loading result file for " + 696 subpanelTest.getTestName()); 697 } 698 } 699 } 700 } 701 702 public void valueChanged(ListSelectionEvent e) { 703 JList l = (JList) (e.getSource()); 704 TOCEntry entry = (TOCEntry) (l.getSelectedValue()); 705 if (entry == null) 706 return; 707 titleField.setText(entry.getTitle()); 708 currentTOCEntry = entry.getID(); 709 String outputName = entry.getOutputName(); 710 711 if (entry.section == null) { 712 if (subpanelTest.getStatus().getType() == Status.NOT_RUN) 713 showHTML(createNotRunSummary()); 714 else 715 showHTML(createStatusSummary()); 716 } 717 else if (outputName != null) 718 showText(entry.getSection().getOutput(outputName)); 719 else if (entry.isScriptMessagesSection()) 720 showHTML(createSummary()); 721 else 722 showHTML(createSectionSummary(entry.getSection())); 723 } 724 } 725 726 //------------------------------------------------------------------------------------ 727 728 private class TRObserver 729 implements TestResult.Observer 730 { 731 public void completed(TestResult tr) { 732 //System.err.println("TPOS_TRO: completed: " + tr.getWorkRelativePath()); 733 updateTOCLater(); 734 tr.removeObserver(this); 735 } 736 737 public void createdSection(TestResult tr, TestResult.Section section) { 738 //System.err.println("TPOS_TRO: created section[" + section.getTitle() + "]: " + tr.getWorkRelativePath()); 739 updateTOCLater(); 740 } 741 742 public void completedSection(TestResult tr, TestResult.Section section) { 743 //System.err.println("TPOS_TRO: completed section[" + section.getTitle() + "]: " + tr.getWorkRelativePath()); 744 updateTOCLater(); 745 } 746 747 public void createdOutput(TestResult tr, TestResult.Section section, 748 String outputName) { 749 //System.err.println("TPOS_TRO: created output[" + section.getTitle() + "/" + outputName + "]: " + tr.getWorkRelativePath()); 750 updateTOCLater(); 751 } 752 753 public void completedOutput(TestResult tr, TestResult.Section section, 754 String outputName) { 755 //System.err.println("TPOS_TRO: completed output[" + section.getTitle() + "/" + outputName + "]: " + tr.getWorkRelativePath()); 756 } 757 758 public void updatedOutput(final TestResult tr, final TestResult.Section section, 759 final String outputName, 760 final int start, final int end, final String text) { 761 //System.err.println("TPOS_TRO: written output[" + section.getTitle() + "/" + outputName + "]: " + tr.getWorkRelativePath()); 762 // this msg almost always on different thread - send it to the 763 // event thread 764 Runnable t = new Runnable() { 765 public void run() { 766 updateOutput(tr, section, outputName, start, end, text); 767 } 768 }; // Runnable 769 770 EventQueue.invokeLater(t); 771 } 772 773 public void updatedProperty(TestResult tr, String name, String value) { 774 // ignore 775 } 776 } 777 778 //------------------------------------------------------------------------------------ 779 780 private class TOCEntry { 781 // create an entry that will show the test result status 782 TOCEntry() { 783 section = null; 784 outputName = null; 785 } 786 787 // create an entry for a section summary 788 TOCEntry(TestResult.Section s) { 789 section = s; 790 outputName = null; 791 } 792 793 // create an entry for a block of section output 794 TOCEntry(TestResult.Section s, String n) { 795 section = s; 796 outputName = n; 797 } 798 799 boolean isScriptMessagesSection() { 800 return (section != null && section.getTitle().equals(TestResult.MSG_SECTION_NAME)); 801 } 802 803 TestResult.Section getSection() { 804 return section; 805 } 806 807 String getOutputName() { 808 return outputName; 809 } 810 811 String getTitle() { 812 if (section == null) { 813 if (subpanelTest.getStatus().getType() == Status.NOT_RUN) 814 return uif.getI18NString("test.out.notRunTitle"); 815 else 816 return uif.getI18NString("test.out.statusTitle"); 817 } 818 else if (isScriptMessagesSection()) { 819 if (outputName == null) 820 return uif.getI18NString("test.out.summary"); 821 else 822 return uif.getI18NString("test.out.scriptMessages"); 823 } 824 else { 825 if (outputName == null) 826 return uif.getI18NString("test.out.sectionTitle", section.getTitle()); 827 else 828 return uif.getI18NString("test.out.streamTitle", 829 new Object[] { section.getTitle(), outputName }); 830 } 831 } 832 833 String getText() { 834 if (section == null){ 835 if (subpanelTest.getStatus().getType() == Status.NOT_RUN) 836 return uif.getI18NString("test.out.notRunTitle"); 837 else 838 return uif.getI18NString("test.out.statusTitle"); 839 } 840 else if (isScriptMessagesSection()) { 841 if (outputName == null) 842 return uif.getI18NString("test.out.summary"); 843 else 844 return uif.getI18NString("test.out.scriptMessages"); 845 } 846 else { 847 if (outputName == null) 848 return section.getTitle(); 849 else 850 return outputName; 851 } 852 } 853 854 Icon getIcon() { 855 if (section == null) 856 return IconFactory.getTestIcon(subpanelTest.getStatus().getType(), false, true); 857 else if (outputName != null) 858 return streamIcon; 859 else { 860 Status s = section.getStatus(); 861 //return (s == null ? null : sectIcons[s.getType()]); 862 return (s == null ? null : IconFactory.getTestSectionIcon(s.getType())); 863 } 864 } 865 866 String getID() { 867 String s = ""; 868 if (section != null ) { 869 s = section.getTitle() + ":" + 870 (outputName == null ? "" : outputName); 871 } 872 return s; 873 } 874 875 private TestResult.Section section; 876 private String outputName; // null for section entry 877 } 878 879 private class TOCRenderer extends DefaultListCellRenderer { 880 public Component getListCellRendererComponent(JList list, 881 Object value, 882 int index, 883 boolean isSelected, 884 boolean cellHasFocus) { 885 JLabel l = (JLabel) super.getListCellRendererComponent(list, null, index, 886 isSelected, cellHasFocus); 887 if (value instanceof TOCEntry) { 888 TOCEntry e = (TOCEntry) value; 889 l.setText(e.getText()); 890 l.setIcon(e.getIcon()); 891 } 892 else 893 l.setText(value.toString()); 894 return l; 895 } 896 } 897 898 899 }