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 }