001/* 002 * $Id: JXErrorPane.java 4158 2012-02-03 18:29:40Z kschaefe $ 003 * 004 * Copyright 2004 Sun Microsystems, Inc., 4150 Network Circle, 005 * Santa Clara, California 95054, U.S.A. All rights reserved. 006 * 007 * This library is free software; you can redistribute it and/or 008 * modify it under the terms of the GNU Lesser General Public 009 * License as published by the Free Software Foundation; either 010 * version 2.1 of the License, or (at your option) any later version. 011 * 012 * This library is distributed in the hope that it will be useful, 013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 015 * Lesser General Public License for more details. 016 * 017 * You should have received a copy of the GNU Lesser General Public 018 * License along with this library; if not, write to the Free Software 019 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 020 */ 021package org.jdesktop.swingx; 022 023import java.awt.Component; 024import java.lang.reflect.InvocationTargetException; 025 026import javax.swing.Icon; 027import javax.swing.JComponent; 028import javax.swing.JDialog; 029import javax.swing.JFrame; 030import javax.swing.JInternalFrame; 031import javax.swing.SwingUtilities; 032 033import org.jdesktop.beans.JavaBean; 034import org.jdesktop.swingx.error.ErrorInfo; 035import org.jdesktop.swingx.error.ErrorReporter; 036import org.jdesktop.swingx.plaf.ErrorPaneAddon; 037import org.jdesktop.swingx.plaf.ErrorPaneUI; 038import org.jdesktop.swingx.plaf.LookAndFeelAddons; 039 040/** 041 * <p>JXErrorPane is a common error component suitable for displaying errors, 042 * warnings, and exceptional application behavior to users.</p> 043 * 044 * <p>User interaction with the <code>JXErrorPane</code> includes the ability to 045 * view details associated with the error. This is the primary feature that differentiates 046 * <code>JXErrorPane</code> from <code>JOptionPane</code>. In addition, 047 * <code>JXErrorPane</code> specializes in handling unrecoverable errors. If you 048 * need an error dialog that allows the user to take some action to recover 049 * from an error (such as "Repair Disk", "Replace All", etc) then you should 050 * use <code>JOptionPane</code>.</p> 051 * 052 * <p>Data and application state associated with an error are encapsulated 053 * in the {@link org.jdesktop.swingx.error.ErrorInfo} class. The 054 * {@code JXErrorPane} displays the data contained in the {@code ErrorInfo}. 055 * In addition, {@code ErrorInfo} is passed to the 056 * {@link org.jdesktop.swingx.error.ErrorReporter} if the user decides to report 057 * the incident.</p> 058 * 059 * <h2>Basic Usage</h2> 060 * <p>Typically, the <code>JXErrorPane</code> 061 * is not created and displayed directly. Instead, one of the static showXXX methods 062 * are called that create and display the <code>JXErrorPane</code> in a 063 * <code>JDialog</code>, <code>JFrame</code>, or <code>JInternalFrame</code>.</p> 064 * 065 * <p>These static showXXX methods all follow the same pattern, namely ( 066 * where XXX could be one of Dialog, Frame, or InternalFrame): 067 * <ul> 068 * <li><b>showXXX(Throwable e)</b>: This usage allows you to show a default error 069 * window, detailing the error</li> 070 * <li><b>showXXX(Component owner, ErrorInfo info)</b>: This usage shows an 071 * error dialog based on the given <code>ErrorInfo</code>. The component 072 * argument is the component over which the dialog should be centered.</li> 073 * <li><b>showXXX(Component owner, JXErrorPane pane)</b>: This usage shows 074 * an error dialog using the given error pane. This allows you to completely 075 * modify the pane (perhaps installing a custom UI delegate, etc) to present 076 * to the user</li> 077 * <li><b>createXXX(Component owner, JXErrorPane pane)</b>: Creates and returns 078 * a dialog for presenting the given <code>JXErrorPane</code>, but does not 079 * show it. This allows the developer to modify properties of the dialog 080 * prior to display</li> 081 * </ul></p> 082 * 083 * <p>Following are some examples and further discussion regarding some of these 084 * static methods. Example of the most basic usage: 085 * <pre><code> 086 * try { 087 * //do stuff.... something throws an exception in here 088 * } catch (Exception e) { 089 * JXErrorPane.showDialog(e); 090 * } 091 * </code></pre>. Alternatively there are <code>showFrame</code> and 092 * <code>showInternalFrame</code> variants of each of the <code>showDialog</code> 093 * methods described in this API.</p> 094 * 095 * <p>While this is the simplest usage, it is not the recommended approach for 096 * most errors since it yields the most difficult messages for users to understand. 097 * Instead it is recommended to provide a more useful message for users. For example: 098 * <pre><code> 099 * URL url = null; 100 * try { 101 * url = new URL(userSuppliedUrl); 102 * } catch (MalformedURLException e) { 103 * String msg = "The web resource you entered is not formatted" 104 * + " correctly."; 105 * String details = "<html>Web resources should begin with \"http://\"" 106 * + " and cannot contain any spaces. Below are a few" 107 * + " more guidelines.<ul>" 108 * + getURLGuidelines() 109 * + "</ul></html>"; 110 * JXErrorPane.showDialog(myWindow, "Unknown Resource", msg, details, e); 111 * return false; 112 * } 113 * </code></pre></p> 114 * 115 * <p>Before showing the <code>JXErrorPane</code> in a frame or dialog, you may modify 116 * the appearance and behavior of the <code>JXErrorPane</code> by setting one or more of its bean 117 * properties. For example, to modify the icon shown with a particular 118 * instance of a <code>JXErrorPane</code>, you might do the following: 119 * <pre><code> 120 * JXErrorPane pane = new JXErrorPane(); 121 * pane.setErrorIcon(myErrorIcon); 122 * pane.setErrorInfo(new ErrorInfo("Fatal Error", exception)); 123 * JXErrorPane.showDialog(null, pane); 124 * </code></pre></p> 125 * 126 * <p><code>JXErrorPane</code> may also be configured with a "Report" button which allows 127 * the user to send a bug report, typically through email. This is done through 128 * the pluggable {@link org.jdesktop.swingx.error.ErrorReporter} class. Simply instantiate 129 * some custom subclass of <code>ErrorReporter</code> and pass the instance into the 130 * {@link #setErrorReporter} method.</p> 131 * 132 * <p><code>JXErrorPane</code> can also be used for displaying fatal error messages to 133 * users. Fatal messages indicate a serious error in the application that cannot 134 * be corrected and that must result in the termination of the application. 135 * After the close of a fatal error dialog, the application should 136 * automatically exit. Fatal messages are identified by the <code>Level</code> 137 * of the <code>ErrorInfo</code> being 138 * {@link org.jdesktop.swingx.error.ErrorLevel}<code>.FATAL</code>.</p> 139 * 140 * <p>By default, when Fatal error dialogs are closed the application exits with 141 * a code of "1". In other words, <code>System.exit(1)</code>. If you wish to implement 142 * custom handling, you can replace the default fatal action in the <code>ActionMap</code> 143 * of the <code>JXErrorPane</code> instance. If you specify a custom fatal 144 * action, then the default action of calling 145 * System.exit will not occur. You are therefore responsible for shutting down 146 * the application.</p> 147 * 148 * <h2>UI Default Keys</h2> 149 * <p>TODO</p> 150 * JXErrorPane.errorIcon 151 * or, if not specified, JOptionPane.errorIcon 152 * JXErrorPane.warningIcon 153 * or, if not specified, JOptionPane.warningIcon 154 * JXErrorPane.details_contract_text (ignored on Mac OS X) 155 * JXErrorPane.details_expand_text (ignored on Mac OS X) 156 * JXErrorPane.mac.details_contract_text 157 * JXErrorPane.mac.details_expand_text 158 * Tree.expandedIcon (on Mac OS X) 159 * Tree.collapsedIcon (on Mac OS X) 160 * 161 * <h2>Customizing the Look and Feel</h2> 162 * <p>TODO</p> 163 * 164 * 165 * @status REVIEWED 166 * 167 * @author Richard Bair 168 * @author Alexander Zuev 169 * @author Shai Almog 170 * @author rah003 171 */ 172@JavaBean 173public class JXErrorPane extends JComponent { 174 //---------------------------------------------------- static properties 175 /** 176 * Name of the Action used for reporting errors 177 */ 178 public static final String REPORT_ACTION_KEY = "report-action"; 179 /** 180 * Name of the Action used for fatal errors 181 */ 182 public static final String FATAL_ACTION_KEY = "fatal-action"; 183 /** 184 * UI Class ID 185 */ 186 public final static String uiClassID = "ErrorPaneUI"; 187 188 /** 189 */ 190 static { 191 LookAndFeelAddons.contribute(new ErrorPaneAddon()); 192 } 193 194 //-------------------------------------------------- instance properties 195 196 /** 197 * ErrorInfo that contains all the information prepared for 198 * reporting. 199 */ 200 private ErrorInfo errorInfo = new ErrorInfo("Error", "Normally this place contains problem description.\n You see this text because one of the following reasons:\n * Either it is a test\n * Developer have not provided error details\n * This error message was invoked unexpectedly and there are no more details available", null, null, null, null, null); 201 /** 202 * The Icon to use, regardless of the error message. The UI delegate is 203 * responsible for setting this icon, if the developer has not specified 204 * the icon. 205 */ 206 private Icon icon; 207 /** 208 * The delegate to use for reporting errors. 209 */ 210 private ErrorReporter reporter; 211 212 //--------------------------------------------------------- constructors 213 214 /** 215 * Create a new <code>JXErrorPane</code>. 216 */ 217 public JXErrorPane() { 218 super(); 219 updateUI(); 220 } 221 222 //------------------------------------------------------------- UI Logic 223 224 /** 225 * Returns the look and feel (L&F) object that renders this component. 226 * 227 * @return the {@link ErrorPaneUI} object that renders this component 228 */ 229 public ErrorPaneUI getUI() { 230 return (ErrorPaneUI)ui; 231 } 232 233 /** 234 * Sets the look and feel (L&F) object that renders this component. 235 * 236 * @param ui 237 * the ErrorPaneUI L&F object 238 * @see javax.swing.UIDefaults#getUI 239 * @beaninfo bound: true hidden: true attribute: visualUpdate true 240 * description: The UI object that implements the Component's 241 * LookAndFeel. 242 */ 243 public void setUI(ErrorPaneUI ui) { 244 super.setUI(ui); 245 } 246 247 /** 248 * Returns the name of the L&F class that renders this component. 249 * 250 * @return the string {@link #uiClassID} 251 * @see javax.swing.JComponent#getUIClassID 252 * @see javax.swing.UIDefaults#getUI 253 */ 254 @Override 255 public String getUIClassID() { 256 return uiClassID; 257 } 258 259 /** 260 * Notification from the <code>UIManager</code> that the L&F has changed. 261 * Replaces the current UI object with the latest version from the 262 * <code>UIManager</code>. 263 * 264 * @see javax.swing.JComponent#updateUI 265 */ 266 @Override 267 public void updateUI() { 268 setUI((ErrorPaneUI) LookAndFeelAddons 269 .getUI(this, ErrorPaneUI.class)); 270 } 271 272 //-------------------------------------------- public methods/properties 273 274 /** 275 * Sets the ErrorInfo for this dialog. ErrorInfo can't be null. 276 * 277 * @param info ErrorInfo that incorporates all the details about the error. Null value is not supported. 278 */ 279 public void setErrorInfo(ErrorInfo info) { 280 if (info == null) { 281 throw new NullPointerException("ErrorInfo can't be null. Provide valid ErrorInfo object."); 282 } 283 ErrorInfo old = this.errorInfo; 284 this.errorInfo = info; 285 firePropertyChange("errorInfo", old, this.errorInfo); 286 } 287 288 /** 289 * Gets the <code>JXErrorPane</code>'s <code>ErrorInfo</code> 290 * 291 * @return <code>ErrorInfo</code> assigned to this dialog 292 */ 293 public ErrorInfo getErrorInfo() { 294 return errorInfo; 295 } 296 297 /** 298 * Specifies the icon to use 299 * 300 * @param icon the Icon to use. May be null. 301 */ 302 public void setIcon(Icon icon) { 303 Icon old = this.icon; 304 this.icon = icon; 305 firePropertyChange("icon", old, this.icon); 306 } 307 308 /** 309 * Returns the Icon used 310 * 311 * @return the Icon 312 */ 313 public Icon getIcon() { 314 return icon; 315 } 316 317 /** 318 * Sets the {@link ErrorReporter} delegate to use. This delegate is called 319 * automatically when the report action is fired. 320 * 321 * @param reporter the ErrorReporter to use. If null, the report button will 322 * not be shown in the error dialog. 323 */ 324 public void setErrorReporter(ErrorReporter reporter) { 325 ErrorReporter old = getErrorReporter(); 326 this.reporter = reporter; 327 firePropertyChange("errorReporter", old, getErrorReporter()); 328 } 329 330 /** 331 * Gets the {@link ErrorReporter} delegate in use. 332 * 333 * @return the ErrorReporter. May be null. 334 */ 335 public ErrorReporter getErrorReporter() { 336 return reporter; 337 } 338 339 //------------------------------------------------------- static methods 340 341 /** 342 * <p>Constructs and shows the error dialog for the given exception. The 343 * exceptions message will be the errorMessage, and the stacktrace will form 344 * the details for the error dialog.</p> 345 * 346 * <p>This method may be called from any thread. It will actually show the error 347 * dialog on the AWT event dispatch thread. This method blocks. If called 348 * on the EDT, the dialog shown will be modal. Otherwise, this thread will 349 * block until the error dialog has been shown and hidden on the EDT.</p> 350 * 351 * @param e Exception that contains information about the error cause and stack trace 352 */ 353 public static void showDialog(Throwable e) { 354 ErrorInfo ii = new ErrorInfo(null, null, null, null, e, null, null); 355 showDialog(null, ii); 356 } 357 358 /** 359 * <p>Constructs and shows the error dialog, using the given 360 * <code>ErrorInfo</code> to initialize the view.</p> 361 * 362 * <p>This method may be called from any thread. It will actually show the error 363 * dialog on the AWT event dispatch thread. This method blocks. If called 364 * on the EDT, the dialog shown will be modal. Otherwise, this thread will 365 * block until the error dialog has been shown and hidden on the EDT.</p> 366 * 367 * @param owner Owner of this error dialog. Determines the Window in which the dialog 368 * is displayed; if the <code>owner</code> has 369 * no <code>Window</code>, a default <code>Frame</code> is used 370 * @param info <code>ErrorInfo</code> that incorporates all the information about the error 371 */ 372 public static void showDialog(Component owner, ErrorInfo info) { 373 JXErrorPane pane = new JXErrorPane(); 374 pane.setErrorInfo(info); 375 showDialog(owner, pane); 376 } 377 378 /** 379 * <p>Constructs and shows the error dialog, using the given 380 * <code>JXErrorPane</code> for the view portion of the dialog.</p> 381 * 382 * <p>This method may be called from any thread. It will actually show the error 383 * dialog on the AWT event dispatch thread. This method blocks. If called 384 * on the EDT, the dialog shown will be modal. Otherwise, this thread will 385 * block until the error dialog has been shown and hidden on the EDT.</p> 386 * 387 * @param owner Owner of this error dialog. Determines the Window in which the dialog 388 * is displayed; if the <code>owner</code> has 389 * no <code>Window</code>, a default <code>Frame</code> is used 390 * @param pane <code>JXErrorPane</code> which will form the content area 391 * of the dialog. 392 */ 393 public static void showDialog(final Component owner, final JXErrorPane pane) { 394 Runnable r = new Runnable() { 395 @Override 396 public void run() { 397 JDialog dlg = createDialog(owner, pane); 398 dlg.setVisible(true); 399 } 400 }; 401 402 if (!SwingUtilities.isEventDispatchThread()) { 403 try { 404 SwingUtilities.invokeAndWait(r); 405 } catch (InvocationTargetException ex) { 406 ex.printStackTrace(); 407 } catch (InterruptedException ex) { 408 ex.printStackTrace(); 409 } 410 } else { 411 r.run(); 412 } 413 } 414 415 /** 416 * <p>Constructs and returns an error dialog, using the given 417 * <code>JXErrorPane</code> for the view portion of the dialog.</p> 418 * 419 * <p>This method may be called from any thread. It does not block. The 420 * caller is responsible for ensuring that the dialog is shown and manipulated 421 * on the AWT event dispatch thread. A common way to do this is to use 422 * <code>SwingUtilities.invokeAndWait</code> or 423 * <code>SwingUtilities.invokeLater()</code>.</p> 424 * 425 * @param owner Owner of this error dialog. Determines the Window in which the dialog 426 * is displayed; if the <code>owner</code> has 427 * no <code>Window</code>, a default <code>Frame</code> is used 428 * @param pane <code>JXErrorPane</code> which will form the content area 429 * of the dialog. 430 * @return a <code>JDialog</code> configured to display the error. 431 */ 432 public static JDialog createDialog(Component owner, JXErrorPane pane) { 433 JDialog window = pane.getUI().getErrorDialog(owner); 434 // If the owner is null applies orientation of the shared 435 // hidden window used as owner. 436 if(owner != null) { 437 pane.applyComponentOrientation(owner.getComponentOrientation()); 438 } else { 439 pane.applyComponentOrientation(window.getComponentOrientation()); 440 } 441 window.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); 442 window.pack(); 443 window.setLocationRelativeTo(owner); 444 return window; 445 } 446 447 /** 448 * <p>Constructs and shows the error frame for the given exception. The 449 * exceptions message will be the errorMessage, and the stacktrace will form 450 * the details for the error dialog.</p> 451 * 452 * <p>This method may be called from any thread. It will actually show the error 453 * dialog on the AWT event dispatch thread. This method blocks. If called 454 * on the EDT, the frame shown will be modal. Otherwise, this thread will 455 * block until the error frame has been shown and hidden on the EDT.</p> 456 * 457 * @param e Exception that contains information about the error cause and stack trace 458 */ 459 public static void showFrame(Throwable e) { 460 ErrorInfo ii = new ErrorInfo(null, null, null, null, e, null, null); 461 showFrame(null, ii); 462 } 463 464 /** 465 * <p>Constructs and shows the error frame, using the given 466 * <code>ErrorInfo</code> to initialize the view.</p> 467 * 468 * <p>This method may be called from any thread. It will actually show the error 469 * dialog on the AWT event dispatch thread. This method blocks. If called 470 * on the EDT, the frame shown will be modal. Otherwise, this thread will 471 * block until the error frame has been shown and hidden on the EDT.</p> 472 * 473 * @param owner Owner of this error frame. Determines the Window in which the frame 474 * is displayed; if the <code>owner</code> has 475 * no <code>Window</code>, a default <code>Frame</code> is used 476 * @param info <code>ErrorInfo</code> that incorporates all the information about the error 477 */ 478 public static void showFrame(Component owner, ErrorInfo info) { 479 JXErrorPane pane = new JXErrorPane(); 480 pane.setErrorInfo(info); 481 showFrame(owner, pane); 482 } 483 484 /** 485 * <p>Constructs and shows the error frame, using the given 486 * <code>JXErrorPane</code> for the view portion of the frame.</p> 487 * 488 * <p>This method may be called from any thread. It will actually show the error 489 * dialog on the AWT event dispatch thread. This method blocks. If called 490 * on the EDT, the frame shown will be modal. Otherwise, this thread will 491 * block until the error frame has been shown and hidden on the EDT.</p> 492 * 493 * @param owner Owner of this error frame. Determines the Window in which the dialog 494 * is displayed; if the <code>owner</code> has 495 * no <code>Window</code>, a default <code>Frame</code> is used 496 * @param pane <code>JXErrorPane</code> which will form the content area 497 * of the frame. 498 */ 499 public static void showFrame(final Component owner, final JXErrorPane pane) { 500 Runnable r = new Runnable() { 501 @Override 502 public void run() { 503 JFrame window = createFrame(owner, pane); 504 window.setVisible(true); 505 } 506 }; 507 508 if (!SwingUtilities.isEventDispatchThread()) { 509 try { 510 SwingUtilities.invokeAndWait(r); 511 } catch (InvocationTargetException ex) { 512 ex.printStackTrace(); 513 } catch (InterruptedException ex) { 514 ex.printStackTrace(); 515 } 516 } else { 517 r.run(); 518 } 519 } 520 521 /** 522 * <p>Constructs and returns an error frame, using the given 523 * <code>JXErrorPane</code> for the view portion of the frame.</p> 524 * 525 * <p>This method may be called from any thread. It does not block. The 526 * caller is responsible for ensuring that the frame is shown and manipulated 527 * on the AWT event dispatch thread. A common way to do this is to use 528 * <code>SwingUtilities.invokeAndWait</code> or 529 * <code>SwingUtilities.invokeLater()</code>.</p> 530 * 531 * @param owner Owner of this error frame. Determines the Window in which the frame 532 * is displayed; if the <code>owner</code> has 533 * no <code>Window</code>, a default <code>Frame</code> is used 534 * @param pane <code>JXErrorPane</code> which will form the content area 535 * of the frame. 536 * @return a <code>JFrame</code> configured to display the error. 537 */ 538 public static JFrame createFrame(Component owner, JXErrorPane pane) { 539 JFrame window = pane.getUI().getErrorFrame(owner); 540 // If the owner is null applies orientation of the shared 541 // hidden window used as owner. 542 if(owner != null) { 543 pane.applyComponentOrientation(owner.getComponentOrientation()); 544 } else { 545 pane.applyComponentOrientation(window.getComponentOrientation()); 546 } 547 window.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); 548 window.pack(); 549// window.setLocationRelativeTo(owner); 550 return window; 551 } 552 553 /** 554 * <p>Constructs and shows the error frame for the given exception. The 555 * exceptions message will be the errorMessage, and the stacktrace will form 556 * the details for the error dialog.</p> 557 * 558 * <p>This method may be called from any thread. It will actually show the error 559 * dialog on the AWT event dispatch thread. This method blocks. If called 560 * on the EDT, the frame shown will be modal. Otherwise, this thread will 561 * block until the error frame has been shown and hidden on the EDT.</p> 562 * 563 * @param e Exception that contains information about the error cause and stack trace 564 */ 565 public static void showInternalFrame(Throwable e) { 566 ErrorInfo ii = new ErrorInfo(null, null, null, null, e, null, null); 567 showInternalFrame(null, ii); 568 } 569 570 /** 571 * <p>Constructs and shows the error frame, using the given 572 * <code>ErrorInfo</code> to initialize the view.</p> 573 * 574 * <p>This method may be called from any thread. It will actually show the error 575 * dialog on the AWT event dispatch thread. This method blocks. If called 576 * on the EDT, the frame shown will be modal. Otherwise, this thread will 577 * block until the error frame has been shown and hidden on the EDT.</p> 578 * 579 * @param owner Owner of this error frame. Determines the Window in which the frame 580 * is displayed; if the <code>owner</code> has 581 * no <code>Window</code>, a default <code>Frame</code> is used 582 * @param info <code>ErrorInfo</code> that incorporates all the information about the error 583 */ 584 public static void showInternalFrame(Component owner, ErrorInfo info) { 585 JXErrorPane pane = new JXErrorPane(); 586 pane.setErrorInfo(info); 587 showInternalFrame(owner, pane); 588 } 589 590 /** 591 * <p>Constructs and shows the error frame, using the given 592 * <code>JXErrorPane</code> for the view portion of the frame.</p> 593 * 594 * <p>This method may be called from any thread. It will actually show the error 595 * dialog on the AWT event dispatch thread. This method blocks. If called 596 * on the EDT, the frame shown will be modal. Otherwise, this thread will 597 * block until the error frame has been shown and hidden on the EDT.</p> 598 * 599 * @param owner Owner of this error frame. Determines the Window in which the dialog 600 * is displayed; if the <code>owner</code> has 601 * no <code>Window</code>, a default <code>Frame</code> is used 602 * @param pane <code>JXErrorPane</code> which will form the content area 603 * of the frame. 604 */ 605 public static void showInternalFrame(final Component owner, final JXErrorPane pane) { 606 Runnable r = new Runnable() { 607 @Override 608 public void run() { 609 JInternalFrame window = createInternalFrame(owner, pane); 610 window.setVisible(true); 611 } 612 }; 613 614 if (!SwingUtilities.isEventDispatchThread()) { 615 try { 616 SwingUtilities.invokeAndWait(r); 617 } catch (InvocationTargetException ex) { 618 ex.printStackTrace(); 619 } catch (InterruptedException ex) { 620 ex.printStackTrace(); 621 } 622 } else { 623 r.run(); 624 } 625 } 626 627 /** 628 * <p>Constructs and returns an error frame, using the given 629 * <code>JXErrorPane</code> for the view portion of the frame.</p> 630 * 631 * <p>This method may be called from any thread. It does not block. The 632 * caller is responsible for ensuring that the frame is shown and manipulated 633 * on the AWT event dispatch thread. A common way to do this is to use 634 * <code>SwingUtilities.invokeAndWait</code> or 635 * <code>SwingUtilities.invokeLater()</code>.</p> 636 * 637 * @param owner Owner of this error frame. Determines the Window in which the frame 638 * is displayed; if the <code>owner</code> has 639 * no <code>Window</code>, a default <code>Frame</code> is used 640 * @param pane <code>JXErrorPane</code> which will form the content area 641 * of the frame. 642 * @return a <code>JInternalFrame</code> configured to display the error. 643 */ 644 public static JInternalFrame createInternalFrame(Component owner, JXErrorPane pane) { 645 JInternalFrame window = pane.getUI().getErrorInternalFrame(owner); 646 // If the owner is null applies orientation of the shared 647 // hidden window used as owner. 648 if(owner != null) { 649 pane.applyComponentOrientation(owner.getComponentOrientation()); 650 } else { 651 pane.applyComponentOrientation(window.getComponentOrientation()); 652 } 653 window.setDefaultCloseOperation(JInternalFrame.DISPOSE_ON_CLOSE); 654 window.pack(); 655 //TODO! 656// window.setLocationRelativeTo(owner); 657 return window; 658 } 659 660}