/Users/richardallenbair/Documents/Source/Projects/nonsense/swingx/src/beaninfo/JXErrorPane_API.java
/*
 * $Id: JXErrorPane_API.html 1362 2006-08-24 20:06:25Z rbair $
 *
 * Copyright 2004 Sun Microsystems, Inc., 4150 Network Circle,
 * Santa Clara, California 95054, U.S.A. All rights reserved.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

import org.jdesktop.swingx.JXPanel;
import org.jdesktop.swingx.error.ErrorReporter;
import org.jdesktop.swingx.error.ErrorInfo;
import org.jdesktop.swingx.error.LogErrorReporter;

/**
 * <p>JXErrorPane is a common error component suitable for displaying errors,
 * warnings, and exceptional behavior to users. Typically, the <code>JXErrorPane</code>
 * is not created and displayed directly. Instead, one of the static showXXX methods
 * are called that create and display the <code>JXErrorPane</code> in a 
 * <code>JDialog</code>, <code>JFrame</code>, or <code>JInternalFrame</code>.</p>
 * 
 * <p>Data and application state associated with an error are encapsulated
 * in the {@link ErrorInfo} class. The <code>JXErrorPane</code> displays the
 * data contained in the <code>ErrorInfo</code>. In addition,
 * <code>ErrorInfo</code> is passed to the {@link ErrorReporter} if the user decides
 * to report the incident.</p>
 * 
 * <p>User interaction with the <code>JXErrorPane</code> includes the ability to
 * view details associated with the error. This is the primary feature that differentiates
 * <code>JXErrorPane</code> from <code>JOptionPane</code>. In addition,
 * <code>JXErrorPane</code> specializes in handling unrecoverable errors. If you
 * need an error dialog that allows the user to take some action to recover
 * from an error (such as "Repair Disk", "Replace All", etc) then you should
 * use <code>JOptionPane</code>.</p>
 * 
 * <p>Several static methods are included as part of the JXErrorPane API to
 * simplify showing errors. These methods are convenient to use from within
 * catch blocks. For example:
 * <pre><code>
 *              try {
 *                  //do stuff.... something throws an exception in here
 *              } catch (Exception e) {
 *                  JXErrorPane.showDialog(e);
 *              }
 * </code></pre>. Alternatively there are <code>showFrame</code> and
 * <code>showInternalFrame</code> variants of each of the <code>showDialog</code>
 * methods described in this API.</p>
 *
 * <p>While this is the simplest usage, it is not the recommended approach for
 * most errors since it yields the most difficult messages for users. Instead
 * it is recommended to provide a more useful message for users. For example:
 * <pre><code>
 *              URL url = null;
 *              try {
 *                  url = new URL(userSuppliedUrl);
 *              } catch (MalformedURLException e) {
 *                  String msg = "The web resource you entered is not formatted"
 *                              + " correctly.";
 *                  String details = "&lt;html&gt;Web resources should begin with \"http://\""
 *                              + " and cannot contain any spaces. Below are a few"
 *                              + " more guidelines.&lt;ul&gt;"
 *                              + getURLGuidelines()
 *                              + "&lt;/ul&gt;&lt;/html&gt;";
 *                  ErrorInfo 
 *                  JXErrorPane.showDialog(myWindow, "Unknown Resource", msg, details, e);
 *                  return false;
 *              }
 * </code></pre></p>
 * 
 * <p>Before showing the <code>JXErrorPane</code> in a frame or dialog, you may modify
 * the appearance and behavior of the JXErrorPane by setting one or more of its bean
 * properties. For example, to modify the icon shown with a particular
 * instance of a <code>JXErrorPane</code>, you might do the following:
 * <pre><code>
 *              JXErrorPane pane = new JXErrorPane();
 *              pane.setErrorIcon(myErrorIcon);
 *              pane.setErrorInfo(new ErrorInfo("Fatal Error", exception));
 *              JXErrorPane.showDialog(null, pane);
 * </code></pre></p>
 *
 * <p><code>JXErrorPane may also be configured with a "Report" button which allows
 * the user to send a bug report, typically through email. This is done through
 * the pluggable {@link ErrorReporter} class. Simply instantiate {@link LogErrorReporter},
 * {@link EmailErrorReporter}, {@link DeafultErrorReporter}, or some custom
 * subclass of <code>ErrorReporter</code> and pass the instance into the
 * {@link #setErrorReporter} method.</p>
 *
 * <p>By default, <code>JXErrorPane</code> is configured with an instance of
 * {@link DefaultErrorReporter}. <code>DefaultErrorReporter</code> simply inspects
 * the <code>ActionMap</code> of the <code>JXErrorPane</code> instance for an instance of
 * a <code>ReportAction</code>. If an instance exists, then a button will appear
 * in the <code>JXErrorPane</code> allowing the user to "Report" the error.</p>
 * 
 * <p><code>JXErrorPane</code> can also be used for displaying fatal error messages to
 * users. Fatal messages indicate a serious error in the application that cannot
 * be corrected and that must result in the termination of the application. 
 * After the close of a fatal error dialog, the application should
 * be automatically closed. Fatal messages are identified by the <code>Level</code>
 * of the <code>ErrorInfo</code> being {@link ErrorLevel}<code>.FATAL</code>.</p>
 * 
 * <p>By default, when Fatal error dialogs are closed the application exits with
 * a code of "1". In other words, <code>System.exit(1)</code>. If you wish to implement
 * custom handling, you can replace the default fatal action in the <code>ActionMap</code>
 * of the <code>JXErrorPane</code> instance. If you want to specify a different default
 * fatal <code>Action</code> (one that would be used by default by all new instances
 * of <code>JXErrorPane</code>, you can call the {@link setDefaultFatalAction}
 * method. If you specify a custom fatal action, then the default action of calling
 * System.exit will not occur. You are therefore responsible for shutting down
 * the application.</p>
 * 
 * @author Richard Bair
 * @author Alexander Zuev
 * @author Shai Almog
 */
public class JXErrorPane_API extends JXPanel {
    //---------------------------------------------------- static properties
    /**
     * Name of the Action used for reporting errors
     */
    public static final String REPORT_ACTION = "report-action";
    /**
     * Name of the Action used for fatal errors
     */
    public static final String FATAL_ACTION = "fatal-action";
    /**
     * UI Class ID
     */
    public final static String uiClassID = "ErrorPaneUI";
    
    //--------------------------------------------------------- constructors

    /**
     * Create a new <code>JXErrorPane</code>.
     */
    public JXErrorPane();
    
    //------------------------------------------------------------- UI Logic
    
    /**
     * @inheritDoc
     */
    public ErrorPaneUI getUI();

    /**
     * Returns the name of the L&F class that renders this component.
     *
     * @return the string {@link #uiClassID}
     * @see javax.swing.JComponent#getUIClassID
     * @see javax.swing.UIDefaults#getUI
     */
    public String getUIClassID();

    //-------------------------------------------- public methods/properties
    
    /**
     * Sets the ErrorInfo for this dialog
     *
     * @param info ErrorInfo that incorporates all the details about the error
     */
    public void setErrorInfo(ErrorInfo info);
    
    /**
     * Gets the <code>JXErrorPane</code>'s <code>ErrorInfo</code>
     *
     * @return <code>ErrorInfo</code> assigned to this dialog
     */
    public ErrorInfo getErrorInfo();
    
    /**
     * Sets the <code>ErrorReporter</code> to use with this instance of 
     * <code>JXErrorPane</code>.
     * If not specified, the default error reporter is used (as specified
     * by the setDefaultErrorReporter() static method) which by default is
     * null.
     *
     * <p>If null, then no "report" button will be shown.</p>
     *
     *
     * @param rep the error reporter to use. May be null.
     */
    public void setErrorReporter(ErrorReporter rep);
    
    /**
     * Returns the error reporter in use with this instance of <code>JXErrorPane.</code>
     *
     * @return the ErrorReporter in use. May be null
     */
    public ErrorReporter getErrorReporter();
    
    /**
     * Specifies the icon to use if the ErrorInfo is Level.SEVERE
     *
     * @param icon the Icon to use. May be null.
     */
    public void setErrorIcon(Icon icon);
    
    /**
     * Returns the Icon in use if the ErrorInfo is Level.SEVERE
     *
     * @return the Icon
     */
    public Icon getErrorIcon();
    
    /**
     * Specifies the icon to use if the ErrorInfo is not Level.SEVERE
     *
     * @param icon the Icon to use. May be null.
     */
    public void setWarningIcon(Icon icon);
    
    /**
     * Returns the Icon in use if the ErrorInfo is not Level.SEVERE
     *
     * @return the Icon
     */
    public Icon getWarningIcon();
    
    //------------------------------------------------------- static methods
    
    /**
     * <p>Constructs and shows the error dialog for the given exception.  The exceptions message will be the
     * errorMessage, and the stacktrace will be the details.</p>
     * 
     * <p>This method may be called from any thread. It will actually show the error
     * dialog on the AWT event dispatch thread.</p>
     * 
     * @param owner Owner of this error dialog. Determines the Window in which the dialog
     *          is displayed; if the <code>owner</code> has
     *          no <code>Window</code>, a default <code>Frame</code> is used
     * @param title Title of the error dialog
     * @param e Exception that contains information about the error cause and stack trace
     */
    public static void showDialog(Throwable e);
    
    /**
     * Constructs and shows the error dialog for the given exception.  The exceptions message will be the
     * errorMessage, and the stacktrace will be the details.
     * 
     * <p>This method may be called from any thread. It will actually show the error
     * dialog on the AWT event dispatch thread.</p>
     * 
     * @param owner Owner of this error dialog. Determines the Window in which the dialog
     *          is displayed; if the <code>owner</code> has
     *          no <code>Window</code>, a default <code>Frame</code> is used
     * @param title Title of the error dialog
     * @param e Exception that contains information about the error cause and stack trace
     */
    public static void showDialog(String category, Throwable e);
    
    /**
     * Constructs and shows the error dialog for the given exception.  The exceptions message is specified,
     * and the stacktrace will be the details.
     * 
     * <p>This method may be called from any thread. It will actually show the error
     * dialog on the AWT event dispatch thread.</p>
     * 
     * @param owner Owner of this error dialog. Determines the Window in which the dialog
     *          is displayed; if the <code>owner</code> has
     *          no <code>Window</code>, a default <code>Frame</code> is used
     * @param title Title of the error dialog
     * @param errorMessage Message for the error dialog
     * @param e Exception that contains information about the error cause and stack trace
     */
    public static void showDialog(Component owner, String title, String errorMessage, Throwable e);
    
    /**
     * Show the error dialog.
     * 
     * <p>This method may be called from any thread. It will actually show the error
     * dialog on the AWT event dispatch thread.</p>
     * 
     * @param owner Owner of this error dialog. Determines the Window in which the dialog
     *          is displayed; if the <code>owner</code> has
     *          no <code>Window</code>, a default <code>Frame</code> is used
     * @param info <code>ErrorInfo</code> that incorporates all the information about the error
     */
    public static void showDialog(Component owner, ErrorInfo info);
    
    /**
     * Show the error dialog.
     * @param info <code>ErrorInfo</code> that incorporates all the information about the error
     */
    public static void showDialog(ErrorInfo info);
    
    public static void showDialog(JXErrorPane pane);
    
    /**
     * 
     * <p>This method may be called from any thread. It will actually show the error
     * dialog on the AWT event dispatch thread.</p>
     * 
     */
    public static void showDialog(final Component owner, final JXErrorPane pane);
    
    /**
     * Constructs and shows the error dialog for the given exception.  The exceptions message will be the
     * errorMessage, and the stacktrace will be the details.
     * @param owner Owner of this error dialog. Determines the Window in which the dialog
     *          is displayed; if the <code>owner</code> has
     *          no <code>Window</code>, a default <code>Frame</code> is used
     * @param title Title of the error dialog
     * @param e Exception that contains information about the error cause and stack trace
     */
    public static void showFrame(Throwable e);
    
    /**
     * Constructs and shows the error dialog for the given exception.  The exceptions message will be the
     * errorMessage, and the stacktrace will be the details.
     * @param owner Owner of this error dialog. Determines the Window in which the dialog
     *          is displayed; if the <code>owner</code> has
     *          no <code>Window</code>, a default <code>Frame</code> is used
     * @param title Title of the error dialog
     * @param e Exception that contains information about the error cause and stack trace
     */
    public static void showFrame(String category, Throwable e);
    
    /**
     * Constructs and shows the error dialog for the given exception.  The exceptions message is specified,
     * and the stacktrace will be the details.
     * @param owner Owner of this error dialog. Determines the Window in which the dialog
     *          is displayed; if the <code>owner</code> has
     *          no <code>Window</code>, a default <code>Frame</code> is used
     * @param title Title of the error dialog
     * @param errorMessage Message for the error dialog
     * @param e Exception that contains information about the error cause and stack trace
     */
    public static void showFrame(Component owner, String title, String errorMessage, Throwable e);
    
    /**
     * Show the error dialog.
     * @param owner Owner of this error dialog. Determines the Window in which the dialog
     *          is displayed; if the <code>owner</code> has
     *          no <code>Window</code>, a default <code>Frame</code> is used
     * @param info <code>ErrorInfo</code> that incorporates all the information about the error
     */
    public static void showFrame(Component owner, ErrorInfo info);
    
    /**
     * Show the error dialog.
     * @param info <code>ErrorInfo</code> that incorporates all the information about the error
     */
    public static void showFrame(ErrorInfo info);
    
    public static void showFrame(JXErrorPane pane);
    
    public static void showFrame(final Component owner, final JXErrorPane pane);
    
    /**
     * Constructs and shows the error dialog for the given exception.  The exceptions message will be the
     * errorMessage, and the stacktrace will be the details.
     * @param owner Owner of this error dialog. Determines the Window in which the dialog
     *          is displayed; if the <code>owner</code> has
     *          no <code>Window</code>, a default <code>Frame</code> is used
     * @param title Title of the error dialog
     * @param e Exception that contains information about the error cause and stack trace
     */
    public static void showInternalFrame(Throwable e);
    
    /**
     * Constructs and shows the error dialog for the given exception.  The exceptions message will be the
     * errorMessage, and the stacktrace will be the details.
     * @param owner Owner of this error dialog. Determines the Window in which the dialog
     *          is displayed; if the <code>owner</code> has
     *          no <code>Window</code>, a default <code>Frame</code> is used
     * @param title Title of the error dialog
     * @param e Exception that contains information about the error cause and stack trace
     */
    public static void showInternalFrame(String category, Throwable e);
    
    /**
     * Constructs and shows the error dialog for the given exception.  The exceptions message is specified,
     * and the stacktrace will be the details.
     * @param owner Owner of this error dialog. Determines the Window in which the dialog
     *          is displayed; if the <code>owner</code> has
     *          no <code>Window</code>, a default <code>Frame</code> is used
     * @param title Title of the error dialog
     * @param errorMessage Message for the error dialog
     * @param e Exception that contains information about the error cause and stack trace
     */
    public static void showInternalFrame(Component owner, String title, String errorMessage, Throwable e);
    
    /**
     * Show the error dialog.
     * @param owner Owner of this error dialog. Determines the Window in which the dialog
     *          is displayed; if the <code>owner</code> has
     *          no <code>Window</code>, a default <code>Frame</code> is used
     * @param info <code>ErrorInfo</code> that incorporates all the information about the error
     */
    public static void showInternalFrame(Component owner, ErrorInfo info);
    
    /**
     * Show the error dialog.
     * @param info <code>ErrorInfo</code> that incorporates all the information about the error
     */
    public static void showInternalFrame(ErrorInfo info);
    
    public static void showInternalFrame(JXErrorPane pane);
    
    public static void showInternalFrame(final Component owner, final JXErrorPane pane);
    
    /**
     * Returns the current reporting engine that will be used to report a problem if
     * user clicks on 'Report' button or <code>null</code> if no default reporting 
     * engine set. If no default is set, a default will be created and used for the
     * <code>JXErrorPane</code> instance.
     *
     * @return reporting engine
     */
    public static ErrorReporter getDefaultErrorReporter();
    
    /**
     * Set reporting engine which will handle error reporting if user clicks 'report' button.
     *
     * @param rep <code>ErrorReporter</code> to be used or <code>null</code> to 
     * use a default reporter.
     */
    public static void setDefaultErrorReporter(ErrorReporter rep);
    
    /**
     * Returns the current default fatal <code>Action</code> used to handle fatal errors.
     *
     * @return default fatal action. May be null.
     */
    public static Action getDefaultFatalAction();
    
    /**
     * Sets the default fatal <code>Action</code> used to handle fatal errors for all
     * new JXErrorPane instances. If null, the UI delegate will create and handle
     * the action using a default implementation which simply calls System.exit(1).
     *
     * @param fatalAction <code>Action</code> to be used or <code>null</code> to 
     *        use the default behavior.
     */
    public static void setDefaultFatalAction(Action fatalAction);
    
    //------------------------------------------------ actions/inner classes
    
    /**
     * The default <code>ErrorReporter</code> used by JXErrorPane. This
     * <code>ErrorReporter</code> simply delegates to the <code>REPORT_ACTION</code>
     * in the <code>JXErrorPane</code>'s <code>ActionMap</code>, if there
     * is one. The <code>ErrorInfo</code> that is being reported will be put
     * into the <code>Action</code> prior to calling it with the name "errorInfo".
     * That is, <code>reportAction.putValue("errorInfo", errorInfo);</code>.
     */
    public static class DefaultErrorReporter implements ErrorReporter {
        private JXErrorPane pane;
        
        public DefaultErrorReporter(JXErrorPane pane) {
            if (pane == null) {
                throw new NullPointerException("the JXErrorPane parameter cannot be null");
            }
            this.pane = pane;
        }
        
        public void reportError(ErrorInfo info) {
            if (info == null) {
                throw new NullPointerException("Info cannot be null");
            }
            //This implementation detail is included in the API so I can confirm
            //its correctness. If it is not correct, some API may need to change.
            Action reportAction = pane.getActionMap().get(JXErrorPane.FATAL_ACTION);
            if (reportAction != null) {
                reportAction.putValue("errorInfo", info);
                ActionEvent ae = new ActionEvent(this, ActionEvent.ACTION_PERFORMED, "reportError");
                reportAction.actionPerformed(ae);
            }
        }
    }    
}