JXErrorDialog.java
上传用户:zhengdagz
上传日期:2014-03-06
资源大小:1956k
文件大小:14k
源码类别:

xml/soap/webservice

开发平台:

Java

  1. /*
  2.  * $Id: JXErrorDialog.java,v 1.6 2005/10/11 14:40:53 kizune Exp $
  3.  *
  4.  * Copyright 2004 Sun Microsystems, Inc., 4150 Network Circle,
  5.  * Santa Clara, California 95054, U.S.A. All rights reserved.
  6.  *
  7.  * This library is free software; you can redistribute it and/or
  8.  * modify it under the terms of the GNU Lesser General Public
  9.  * License as published by the Free Software Foundation; either
  10.  * version 2.1 of the License, or (at your option) any later version.
  11.  * 
  12.  * This library is distributed in the hope that it will be useful,
  13.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15.  * Lesser General Public License for more details.
  16.  * 
  17.  * You should have received a copy of the GNU Lesser General Public
  18.  * License along with this library; if not, write to the Free Software
  19.  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  20.  */
  21. package org.jdesktop.swingx;
  22. import java.awt.*;
  23. import java.awt.event.ActionEvent;
  24. import java.awt.event.ActionListener;
  25. import java.io.PrintWriter;
  26. import java.io.StringWriter;
  27. import javax.swing.*;
  28. /**
  29.  * Common Error Dialog, suitable for representing information about 
  30.  * errors and exceptions happened in application. The common usage of the 
  31.  * <code>JXErrorDialog</code> is to show collected data about the incident and 
  32.  * probably ask customer for a feedback. The data about the incident consists 
  33.  * from the title which will be displayed in the dialog header, short 
  34.  * description of the problem that will be immediately seen after dialog is 
  35.  * became visible, full description of the problem which will be visible after
  36.  * user clicks "Details" button and Throwable that contains stack trace and
  37.  * another usable information that may be displayed in the dialog.<p>
  38.  *
  39.  * To ask user for feedback extend abstract class <code>ErrorReporter</code> and
  40.  * set your reporter using <code>setReporter</code> method. Report button will 
  41.  * be added to the dialog automatically.<br>
  42.  * See {@link MailErrorReporter MailErrorReporter} documentation for the
  43.  * example of error reporting usage.<p>
  44.  * For example, to show simple <code>JXErrorDialog</code> call <br>
  45.  * <code>JXErrorDialog.showDialog(null, "Application Error", 
  46.  *   "The application encountered the unexpected error,
  47.  *    please contact developers")</code>
  48.  * @author Richard Bair
  49.  * @author Alexander Zuev
  50.  */
  51. public class JXErrorDialog extends JDialog {
  52.     /**
  53.      * Text representing expanding the details section of the dialog
  54.      */
  55.     private static final String DETAILS_EXPAND_TEXT = "Details >>";
  56.     /**
  57.      * Text representing contracting the details section of the dialog
  58.      */
  59.     private static final String DETAILS_CONTRACT_TEXT = "Details <<";
  60.     /**
  61.      * Text for the Ok button.
  62.      */
  63.     private static final String OK_BUTTON_TEXT = "Ok";
  64.     /**
  65.      * Icon for the error dialog (stop sign, etc)
  66.      */
  67.     private static final Icon icon = UIManager.getIcon("OptionPane.warningIcon");
  68.     /**
  69.      * Text for the reportError button
  70.      */
  71.     private static final String REPORT_BUTTON_TEXT = "Report...";
  72.     /**
  73.      * Error message label
  74.      */
  75.     private JLabel errorMessage;
  76.     /**
  77.      * details text area
  78.      */
  79.     private JTextArea details;
  80.     /**
  81.      * detail button
  82.      */
  83.     private JButton detailButton;
  84.     /**
  85.      * details scroll pane
  86.      */
  87.     private JScrollPane detailsScrollPane;
  88.     /**
  89.      * report an error button
  90.      */
  91.     private JButton reportButton;
  92.     /**
  93.      * Error reporting engine assigned for error reporting for all error dialogs
  94.      */
  95.     private static ErrorReporter reporter;
  96.     /**
  97.      * IncidentInfo that contains all the information prepared for
  98.      * reporting.
  99.      */
  100.     private IncidentInfo incidentInfo;
  101.     /**
  102.      * Create a new ErrorDialog with the given Frame as the owner
  103.      * @param owner Owner of this error dialog.
  104.      */
  105.     public JXErrorDialog(Frame owner) {
  106.         super(owner, true);
  107.         initGui();
  108.     }
  109.     /**
  110.      * Create a new ErrorDialog with the given Dialog as the owner
  111.      * @param owner Owner of this error dialog.
  112.      */
  113.     private JXErrorDialog(Dialog owner) {
  114.         super(owner, true);
  115.         initGui();
  116.     }
  117.     /**
  118.      * initialize the gui.
  119.      */
  120.     private void initGui() {
  121.         //initialize the gui
  122.         GridBagLayout layout = new GridBagLayout();
  123.         this.getContentPane().setLayout(layout);
  124.         GridBagConstraints gbc = new GridBagConstraints();
  125.         gbc.anchor = GridBagConstraints.CENTER;
  126.         gbc.fill = GridBagConstraints.NONE;
  127.         gbc.gridheight = 1;
  128.         gbc.insets = new Insets(22, 12, 11, 17);
  129.         this.getContentPane().add(new JLabel(icon), gbc);
  130.         errorMessage = new JLabel();
  131.         gbc.anchor = GridBagConstraints.WEST;
  132.         gbc.fill = GridBagConstraints.BOTH;
  133.         gbc.gridheight = 1;
  134.         gbc.gridwidth = 2;
  135.         gbc.gridx = 1;
  136.         gbc.weightx = 1.0;
  137.         gbc.insets = new Insets(12, 0, 0, 11);
  138.         this.getContentPane().add(errorMessage, gbc);
  139.         gbc.fill = GridBagConstraints.NONE;
  140.         gbc.gridx = 1;
  141.         gbc.gridy = 1;
  142.         gbc.gridwidth = 1;
  143.         gbc.weightx = 1.0;
  144.         gbc.weighty = 0.0;
  145.         gbc.anchor = GridBagConstraints.EAST;
  146.         gbc.insets = new Insets(12, 0, 11, 5);
  147.         JButton okButton = new JButton(OK_BUTTON_TEXT);
  148.         this.getContentPane().add(okButton, gbc);
  149.         reportButton = new JButton(new ReportAction());
  150.         gbc.gridx = 2;
  151.         gbc.weightx = 0.0;
  152.         gbc.insets = new Insets(12, 0, 11, 5);
  153.         this.getContentPane().add(reportButton, gbc);
  154.         reportButton.setVisible(false); // not visible by default
  155.         detailButton = new JButton(DETAILS_EXPAND_TEXT);
  156.         gbc.gridx = 3;
  157.         gbc.weightx = 0.0;
  158.         gbc.insets = new Insets(12, 0, 11, 11);
  159.         this.getContentPane().add(detailButton, gbc);
  160.         details = new JTextArea(7, 60);
  161.         detailsScrollPane = new JScrollPane(details);
  162.         detailsScrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
  163.         details.setEditable(false);
  164.         gbc.fill = GridBagConstraints.BOTH;
  165.         gbc.gridwidth = 4;
  166.         gbc.gridx = 0;
  167.         gbc.gridy = 2;
  168.         gbc.weighty = 1.0;
  169.         gbc.insets = new Insets(6, 11, 11, 11);
  170.         this.getContentPane().add(detailsScrollPane, gbc);
  171.         /*
  172.          * Here i'm going to add invisible empty container to the bottom of the
  173.          * content pane to fix minimal width of the dialog. It's quite a hack,
  174.          * but i have not found anything better.
  175.          */
  176.         Dimension spPredictedSize = detailsScrollPane.getPreferredSize();
  177.         Dimension newPanelSize =
  178.                 new Dimension(spPredictedSize.width+15, 0);
  179.         Container widthHolder = new Container();
  180.         widthHolder.setMinimumSize(newPanelSize);
  181.         widthHolder.setPreferredSize(newPanelSize);
  182.         widthHolder.setMaximumSize(newPanelSize);
  183.         gbc.gridy = 3;
  184.         gbc.insets = new Insets(0, 11, 11, 0);
  185.         this.getContentPane().add(widthHolder, gbc);
  186.         //make the buttons the same size
  187.         int buttonLength = detailButton.getPreferredSize().width;
  188.         int buttonHeight = detailButton.getPreferredSize().height;
  189.         Dimension buttonSize = new Dimension(buttonLength, buttonHeight);
  190.         okButton.setPreferredSize(buttonSize);
  191.         reportButton.setPreferredSize(buttonSize);
  192.         detailButton.setPreferredSize(buttonSize);
  193.         //set the event handling
  194.         okButton.addActionListener(new OkClickEvent());
  195.         detailButton.addActionListener(new DetailsClickEvent());
  196.     }
  197.     /**
  198.      * Set the details section of the error dialog.  If the details are either
  199.      * null or an empty string, then hide the details button and hide the detail
  200.      * scroll pane.  Otherwise, just set the details section.
  201.      * @param details  Details to be shown in the detail section of the dialog.  This can be null
  202.      * if you do not want to display the details section of the dialog.
  203.      */
  204.     private void setDetails(String details) {
  205.         if (details == null || details.equals("")) {
  206.             setDetailsVisible(false);
  207.             detailButton.setVisible(false);
  208.         } else {
  209.             this.details.setText(details);
  210.             setDetailsVisible(false);
  211.             detailButton.setVisible(true);
  212.         }
  213.     }
  214.     /**
  215.      * Set the details section to be either visible or invisible.  Set the
  216.      * text of the Details button accordingly.
  217.      * @param b if true details section will be visible
  218.      */
  219.     private void setDetailsVisible(boolean b) {
  220.         if (b) {
  221.             details.setCaretPosition(0);
  222.             detailsScrollPane.setVisible(true);
  223.             detailButton.setText(DETAILS_CONTRACT_TEXT);
  224.         } else {
  225.             detailsScrollPane.setVisible(false);
  226.             detailButton.setText(DETAILS_EXPAND_TEXT);
  227.         }
  228.         pack();
  229.     }
  230.     /**
  231.      * Set the error message for the dialog box
  232.      * @param errorMessage Message for the error dialog
  233.      */
  234.     private void setErrorMessage(String errorMessage) {
  235.         this.errorMessage.setText(errorMessage);
  236.     }
  237.     /**
  238.      * Sets the IncidentInfo for this dialog
  239.      *
  240.      * @param info IncidentInfo that incorporates all the details about the error
  241.      */
  242.     private void setIncidentInfo(IncidentInfo info) {
  243.         this.incidentInfo = info;
  244.         this.reportButton.setVisible(getReporter() != null);
  245.     }
  246.     /**
  247.      * Get curent dialog's IncidentInfo
  248.      *
  249.      * @return <code>IncidentInfo</code> assigned to this dialog
  250.      */
  251.     private IncidentInfo getIncidentInfo() {
  252.         return incidentInfo;
  253.     }
  254.     /**
  255.      * Listener for Ok button click events
  256.      * @author Richard Bair
  257.      */
  258.     private final class OkClickEvent implements ActionListener {
  259.         /* (non-Javadoc)
  260.         * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
  261.         */
  262.         public void actionPerformed(ActionEvent e) {
  263.             //close the window
  264.             setVisible(false);
  265.         }
  266.     }
  267.     /**
  268.      * Listener for Details click events.  Alternates whether the details section
  269.      * is visible or not.
  270.      * @author Richard Bair
  271.      */
  272.     private final class DetailsClickEvent implements ActionListener {
  273.         /* (non-Javadoc)
  274.         * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
  275.         */
  276.         public void actionPerformed(ActionEvent e) {
  277.             setDetailsVisible(!detailsScrollPane.isVisible());
  278.         }
  279.     }
  280.     /**
  281.      * Constructs and shows the error dialog for the given exception.  The exceptions message will be the
  282.      * errorMessage, and the stacktrace will be the details.
  283.      * @param owner Owner of this error dialog.
  284.      * @param title Title of the error dialog
  285.      * @param e Exception that contains information about the error cause and stack trace
  286.      */
  287.     public static void showDialog(Window owner, String title, Throwable e) {
  288.         IncidentInfo ii = new IncidentInfo(title, null, null, e);
  289.         showDialog(owner, ii);
  290.     }
  291.     /**
  292.      * Show the error dialog.
  293.      * @param owner Owner of this error dialog
  294.      * @param title Title of the error dialog
  295.      * @param errorMessage Message for the error dialog
  296.      * @param details Details to be shown in the detail section of the dialog.  This can be null
  297.      * if you do not want to display the details section of the dialog.
  298.      */
  299.     public static void showDialog(Window owner, String title, String errorMessage, String details) {
  300.         IncidentInfo ii = new IncidentInfo(title, errorMessage, details);
  301.         showDialog(owner, ii);
  302.     }
  303.     /**
  304.      * Show the error dialog.
  305.      * @param owner Owner of this error dialog.
  306.      * @param info <code>IncidentInfo</code> that incorporates all the information about the error
  307.      */
  308.     public static void showDialog(Window owner, IncidentInfo info) {
  309.         JXErrorDialog dlg;
  310.         if (owner instanceof Dialog) {
  311.             dlg = new JXErrorDialog((Dialog)owner);
  312.         } else {
  313.             dlg = new JXErrorDialog((Frame)owner);
  314.         }
  315.         dlg.setTitle(info.getHeader());
  316.         dlg.setErrorMessage(info.getBasicErrorMessage());
  317.         String details = info.getDetailedErrorMessage();
  318.         if(details == null) {
  319.             if(info.getErrorException() != null) {
  320.                 StringWriter sw = new StringWriter();
  321.                 PrintWriter pw = new PrintWriter(sw);
  322.                 info.getErrorException().printStackTrace(pw);
  323.                 details = sw.toString();
  324.             } else {
  325.                 details = "";
  326.             }
  327.         }
  328.         dlg.setDetails(details);
  329.         dlg.setIncidentInfo(info);
  330.         dlg.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
  331.         dlg.pack();
  332.         dlg.setLocationRelativeTo(owner);
  333.         dlg.setVisible(true);
  334.     }
  335.     /**
  336.      * Returns the current reporting engine that will be used to report a problem if
  337.      * user clicks on 'Report' button or <code>null</code> if no reporting engine set.
  338.      *
  339.      * @return reporting engine
  340.      */
  341.     public static ErrorReporter getReporter() {
  342.         return reporter;
  343.     }
  344.     /**
  345.      * Set reporting engine which will handle error reporting if user clicks 'report' button.
  346.      *
  347.      * @param rep <code>ErrorReporter</code> to be used or <code>null</code> to turn reporting facility off.
  348.      */
  349.     public static void setReporter(ErrorReporter rep) {
  350.         reporter = rep;
  351.     }
  352.     /**
  353.      * Action for report button
  354.      */
  355.     public class ReportAction extends AbstractAction {
  356.         public boolean isEnabled() {
  357.             return (getReporter() != null);
  358.         }
  359.         public void actionPerformed(ActionEvent e) {
  360.             getReporter().reportIncident(getIncidentInfo());
  361.         }
  362.         public Object getValue(String key) {
  363.             if(key == Action.NAME) {
  364.                 if(getReporter() != null && getReporter().getActionName() != null) {
  365.                     return getReporter().getActionName();
  366.                 } else {
  367.                     return REPORT_BUTTON_TEXT;
  368.                 }
  369.             }
  370.             return super.getValue(key);
  371.         }
  372.     }
  373. }