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