org.openmicroscopy.shoola.util.ui.MessengerDialog.java Source code

Java tutorial

Introduction

Here is the source code for org.openmicroscopy.shoola.util.ui.MessengerDialog.java

Source

/*
 * org.openmicroscopy.shoola.util.ui.MessengerDialog 
 *
 *------------------------------------------------------------------------------
 *  Copyright (C) 2006 University of Dundee. All rights reserved.
 *
 *
 *    This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *  This program 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 General Public License for more details.
 *  
 *  You should have received a copy of the GNU General Public License along
 *  with this program; if not, write to the Free Software Foundation, Inc.,
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 *------------------------------------------------------------------------------
 */
package org.openmicroscopy.shoola.util.ui;

//Java imports
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.List;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.Icon;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JTextField;
import javax.swing.JTextPane;
import javax.swing.UIManager;
import javax.swing.WindowConstants;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.BadLocationException;
import javax.swing.text.Style;
import javax.swing.text.StyledDocument;

//Third-party libraries
import org.jdesktop.swingx.JXBusyLabel;
import info.clearthought.layout.TableLayout;
import org.apache.commons.collections.CollectionUtils;

//Application-internal dependencies
import org.openmicroscopy.shoola.util.file.ImportErrorObject;

/** 
 * A dialog used to collect and send comments or error messages.
 *
 * @author  Jean-Marie Burel     
 * <a href="mailto:j.burel@dundee.ac.uk">j.burel@dundee.ac.uk</a>
 * @author Donald MacDonald &nbsp;&nbsp;&nbsp;&nbsp;
 * <a href="mailto:donald@lifesci.dundee.ac.uk">donald@lifesci.dundee.ac.uk</a>
 * after code from 
 * @author Brian Loranger &nbsp;&nbsp;&nbsp;&nbsp;
 * <a href="mailto:brian.loranger@lifesci.dundee.ac.uk">
 * brian.loranger@lifesci.dundee.ac.uk</a>
 * 
 * @version 3.0
 * <small>
 * (<b>Internal version:</b> $Revision: $Date: $)
 * </small>
 * @since OME3.0
 */
public class MessengerDialog extends JDialog implements ActionListener, DocumentListener {

    /** Identifies the error dialog type. */
    public static final int ERROR_TYPE = 0;

    /** Identifies the error dialog type. */
    public static final int COMMENT_TYPE = 1;

    /** Identifies the error dialog type. */
    public static final int SUBMIT_ERROR_TYPE = 2;

    /** Bound property indicating to send the message. */
    public static final String SEND_PROPERTY = "send";

    /** Bound property indicating to close the window. */
    public static final String CLOSE_MESSENGER_PROPERTY = "closeMessenger";

    /** Action ID to close the dialog. */
    private static final int CANCEL = 0;

    /** Action ID to send comment and close the dialog. */
    private static final int SEND = 1;

    /** Action ID to copy on the clipboard. */
    private static final int COPY = 3;

    /** Action ID to indicate the consequence of not submitting files. */
    private static final int SUBMIT = 4;

    /** The default size of the window. */
    private static final Dimension DEFAULT_SIZE = new Dimension(700, 400);

    /** The tooltip of the {@link #cancelButton}. */
    private static final String CANCEL_TOOLTIP = "Cancel your message";

    /** The tooltip of the {@link #sendButton}. */
    private static final String SEND_TOOLTIP = "Send the information to " + "the development team";

    /** The tooltip of the {@link #copyButton}. */
    private static final String COPY_TOOLTIP = "Copy the Exception " + "Message to the clipboard";

    /** The default message displayed. */
    private static final String MESSAGE = "Thank you for taking the time " + "to send us your comments. \n\n"
            + "Your feedback will be used to further the development of "
            + "OMERO and improve our software. Any personal details you "
            + "provide are purely optional, and will only be used for " + "development purposes.\n";

    /** The default message displayed. */
    private static final String DEBUG_MESSAGE = "An error message has " + "been generated by the application.\n\n"
            + "To help us improve our software, please fill "
            + "out the following form. Your personal details are purely "
            + "optional, and will only be used for development purposes.\n\n"
            + "Please note that your application may need to be restarted " + "to work properly.\n";

    /** The default message displayed. */
    private static final String SUBMIT_MESSAGE = "Submit to the "
            + "development team the files that failed to import.\n\n"
            + "To help us improve our software, please fill "
            + "out the following form. Your personal details are purely "
            + "optional, and will only be used for development purposes.\n\n"
            + "Please note that your application may need to be restarted " + "to work properly.\n";

    /** The default message displayed when a non valid e-mail is entered. */
    private static final String EMAIL_MESSAGE = "The e-mail address "
            + "entered \n does not seem to be valid. \n Please enter a new " + "e-mail address.";

    /** 
     * The default message displayed if user decides not to submit the files. 
     */
    private static final String SUBMIT_FILES_MESSAGE = "Choosing not "
            + "to submit to the files will make it more difficult to "
            + "fix the problem you are experimenting.\nAre you sure " + "you do not want to submit the files?";

    /** Value of the  comment field. */
    private static final String COMMENT_FIELD = "Comment: ";

    /** Value of the comment field when an exception is specified. */
    private static final String DEBUG_COMMENT_FIELD = "What you were doing" + " when you crashed?";

    /** Value of the field. */
    private static final String EMAIL_FIELD = "Email: ";

    /** The default tool-tip of the e-mail area. */
    private static final String EMAIL_TOOLTIP = "Enter your email " + "address here.";

    /** The e-mail field's suffix. */
    private static final String EMAIL_SUFFIX = " (Optional)";

    /** Brief description of the error. */
    private static final String ERROR_BRIEF = "Brief Description:";

    /** 
     * One of the following constants: {@link #ERROR_TYPE} or 
     * {@link #COMMENT_TYPE}.
     */
    private int dialogType;

    /** Button to close and dispose of the window. */
    private JButton cancelButton;

    /** Button to post the message. */
    private JButton sendButton;

    /** The area displaying the <code>e-mail address</code>. */
    private JTextField emailArea;

    /** The comment Area. */
    private MultilineLabel commentArea;

    /** The e-mail address of the user submitting the message. */
    private String emailAddress;

    /** The exception to handle, <code>null</code> if no exception. */
    private Exception exception;

    /** The text pane displaying the error message. */
    private JTextPane debugArea;

    /** Button to copy the message on the clipBoard. */
    private JButton copyButton;

    /** The version of the server. */
    private String serverVersion;

    /** A brief description of the error. */
    private String errorDescription;

    /** The component displaying the files to send. */
    private FileTable table;

    /** Indicates the status of the files submission. */
    private JXBusyLabel submitStatus;

    /** Component indicating to submit the files or not. */
    private JCheckBox submitFile;

    /** Indicates the progress of the files submission.*/
    private JXBusyLabel progress;

    /** Indicates the progress of the files submission.*/
    private JLabel progressLabel;

    /** 
     * Displays the dialog indicating the consequence of not submitting
     * the files.
     */
    private void submitFilesControl() {
        if (!submitFile.isSelected()) {
            MessageBox dialog = new MessageBox(this, "Submit Files", SUBMIT_FILES_MESSAGE);
            dialog.setResizable(false);
            if (dialog.centerMsgBox() == MessageBox.NO_OPTION)
                submitFile.setSelected(true);
        }
    }

    /**
     * Formats the specified button.
     * 
     * @param b         The button to format.
     * @param mnemonic   The key-code that indicates a mnemonic key.
     * @param tooltip   The button's tooltip.
     * @param actionID   The action id associated to the passed button.
     */
    private void formatButton(JButton b, int mnemonic, String tooltip, int actionID) {
        b.setMnemonic(mnemonic);
        b.setOpaque(false);
        b.setToolTipText(tooltip);
        b.addActionListener(this);
        b.setActionCommand("" + actionID);
    }

    /** Hides the window and disposes. */
    private void close() {
        setVisible(false);
        dispose();
        firePropertyChange(CLOSE_MESSENGER_PROPERTY, Boolean.valueOf(false), Boolean.valueOf(true));
    }

    /** Copies the error message on the clipboard. */
    private void copy() {
        if (debugArea != null) {
            debugArea.selectAll();
            debugArea.copy();
        }
    }

    /**
     * Sends the error to the server.
     * 
     * @param propertyName The name of the property.
     */
    private void sendError(String propertyName) {
        String email = emailArea.getText().trim();
        String comment = commentArea.getText().trim();
        String error = null;
        if (debugArea != null)
            error = debugArea.getText().trim();
        MessengerDetails details = new MessengerDetails(email, comment);
        details.setExtra(serverVersion);
        details.setError(error);
        firePropertyChange(propertyName, null, details);
        close();
    }

    /** 
     * Sends the message. 
     * 
     * @param propertyName The name of the property to fire.
     */
    private void send(String propertyName) {
        if (dialogType == SUBMIT_ERROR_TYPE) {
            List<FileTableNode> files = null;
            if (table != null)
                files = table.getSelectedFiles();
            if (CollectionUtils.isEmpty(files)) {
                sendError(propertyName);
            } else {
                String email = emailArea.getText().trim();
                String comment = commentArea.getText().trim();
                MessengerDetails details = new MessengerDetails(email, comment);
                details.setExtra(serverVersion);
                details.setObjectToSubmit(files);
                submitStatus.setVisible(true);
                submitStatus.setBusy(true);
                details.setExceptionOnly(!submitFile.isSelected());
                firePropertyChange(propertyName, null, details);
            }
        } else {
            sendError(propertyName);
        }
        sendButton.setEnabled(false);
    }

    /** Initializes the various components. */
    private void initComponents() {
        progress = new JXBusyLabel(new Dimension(16, 16));
        progress.setVisible(false);
        progressLabel = new JLabel();
        setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
        addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent e) {
                close();
            }
        });
        cancelButton = new JButton("Cancel");
        formatButton(cancelButton, 'C', CANCEL_TOOLTIP, CANCEL);

        sendButton = new JButton("Send");
        formatButton(sendButton, 'S', SEND_TOOLTIP, SEND);

        emailArea = new JTextField(20);
        emailArea.setToolTipText(EMAIL_TOOLTIP);
        emailArea.setText(emailAddress);
        commentArea = new MultilineLabel();
        commentArea.setEditable(true);
        commentArea.setBackground(UIUtilities.BACKGROUND_COLOR);
        commentArea.setOpaque(true);
        if (exception != null) {
            debugArea = buildExceptionArea();
            copyButton = new JButton("Copy to Clipboard");
            formatButton(copyButton, 'C', COPY_TOOLTIP, COPY);
        }
        //getRootPane().setDefaultButton(sendButton);
        setAlwaysOnTop(true);
        if (dialogType == COMMENT_TYPE) {
            sendButton.setEnabled(false);
            commentArea.getDocument().addDocumentListener(this);
        }
        submitStatus = new JXBusyLabel(new Dimension(16, 16));
        submitStatus.setText("Uploading files");
        submitStatus.setVisible(false);
        submitFile = new JCheckBox("Files");
        submitFile.setSelected(true);
        submitFile.addActionListener(this);
        submitFile.setActionCommand("" + SUBMIT);
    }

    /**
     * Builds the UI component displaying the exception.
     * 
     * @return See above.
     */
    private JTextPane buildExceptionArea() {
        JTextPane pane = UIUtilities.buildExceptionArea();
        StyledDocument document = pane.getStyledDocument();
        Style style = pane.getLogicalStyle();
        //Get the full debug text
        StringWriter sw = new StringWriter();
        PrintWriter pw = new PrintWriter(sw);
        exception.printStackTrace(pw);
        try {
            document.insertString(document.getLength(), sw.toString(), style);
        } catch (BadLocationException e) {
        }

        return pane;
    }

    /**
     * Builds and lays out the panel hosting the <code>comment</code> details.
     * 
     * @param comment      The comment's text.
     * @param mnemonic       The key-code that indicates a mnemonic key.
     * @return See above.
     */
    private JPanel buildCommentAreaPanel(String comment, int mnemonic) {
        JPanel panel = new JPanel();
        panel.setOpaque(false);

        double size[][] = { { TableLayout.FILL }, { 20, TableLayout.FILL } };
        TableLayout layout = new TableLayout(size);
        panel.setLayout(layout);
        JScrollPane areaScrollPane = new JScrollPane(commentArea);
        areaScrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
        JLabel label = new JLabel(comment);
        label.setOpaque(false);
        label.setDisplayedMnemonic(mnemonic);
        panel.add(label, "0, 0, LEFT, CENTER");
        panel.add(areaScrollPane, "0, 1");
        return panel;
    }

    /**
     * Builds and lays out the panel hosting the <code>email</code> details.
     * 
     * @param mnemonic The key-code that indicates a mnemonic key.
     * @return See above.
     */
    private JPanel buildEmailAreaPanel(int mnemonic) {
        double[][] size = null;

        JPanel panel = new JPanel();
        panel.setOpaque(false);

        if (EMAIL_SUFFIX.length() == 0)
            size = new double[][] { { TableLayout.PREFERRED, TableLayout.FILL }, { 30 } };
        else
            size = new double[][] { { TableLayout.PREFERRED, TableLayout.FILL, TableLayout.PREFERRED }, { 30 } };

        TableLayout layout = new TableLayout(size);
        panel.setLayout(layout);

        JLabel label = new JLabel(EMAIL_FIELD);
        label.setDisplayedMnemonic(mnemonic);
        label.setLabelFor(emailArea);
        label.setOpaque(false);

        panel.add(label, "0, 0, RIGHT, CENTER");
        panel.add(emailArea, "1, 0, FULL, CENTER");

        if (EMAIL_SUFFIX.length() != 0)
            panel.add(new JLabel(EMAIL_SUFFIX), "2, 0, LEFT, CENTER");

        return panel;
    }

    /**
     * Builds and lays out the panel hosting the debug information.
     * 
     * @return See above.
     */
    private JPanel buildDebugPane() {
        JPanel panel = new JPanel();
        //panel.setBackground(UIUtilities.WINDOW_BACKGROUND_COLOR);
        panel.setOpaque(false);
        double tableSize[][] = { { TableLayout.FILL }, // columns
                { TableLayout.FILL, 32 } }; // rows
        TableLayout layout = new TableLayout(tableSize);
        panel.setLayout(layout);
        panel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
        JScrollPane pane = new JScrollPane(debugArea);
        //pane.setBackground(UIUtilities.WINDOW_BACKGROUND_COLOR);
        panel.add(pane, "0, 0");
        panel.add(copyButton, "0, 1, CENTER, BOTTOM");
        return panel;
    }

    /**
     * Builds and lays out the panel hosting the collection of files to submit.
     * 
     * @return See above.
     */
    private JPanel buildFilesToSubmitPane(List<ImportErrorObject> toSubmit) {
        JPanel panel = new JPanel();
        //panel.setBackground(UIUtilities.WINDOW_BACKGROUND_COLOR);
        panel.setOpaque(false);

        double tableSize[][] = { { TableLayout.FILL }, // columns
                { TableLayout.FILL } }; // rows
        TableLayout layout = new TableLayout(tableSize);
        panel.setLayout(layout);
        panel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
        table = new FileTable(toSubmit);
        JScrollPane pane = new JScrollPane(table);
        //pane.setBackground(UIUtilities.WINDOW_BACKGROUND_COLOR);
        panel.add(pane, "0, 0");
        return panel;
    }

    /**
     * Builds and lays out the panel hosting the comments.
     * 
     * @param comment      The comment's text.
     * @return See above.
     */
    private JPanel buildCommentPane(String comment) {
        JPanel commentPanel = new JPanel();
        //commentPanel.setBackground(UIUtilities.WINDOW_BACKGROUND_COLOR);
        int iconSpace = 0;
        double tableSize[][] = { { iconSpace, (160 - iconSpace), TableLayout.FILL }, // columns
                { 0, 0, 30, TableLayout.FILL } }; // rows
        TableLayout layout = new TableLayout(tableSize);
        commentPanel.setLayout(layout);
        commentPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
        commentPanel.add(buildEmailAreaPanel('E'), "0, 2, 2, 2");
        commentPanel.add(buildCommentAreaPanel(comment, 'W'), "0, 3, 2, 3");
        if (errorDescription != null && errorDescription.length() > 0) {
            layout.setRow(1, 30);
            JPanel p = new JPanel();
            p.add(UIUtilities.setTextFont(ERROR_BRIEF));
            p.add(new JLabel(errorDescription));
            commentPanel.add(UIUtilities.buildComponentPanel(p), "0, 1, 2, 1");
        }
        return commentPanel;
    }

    /** 
     * Builds the UI component hosting the debug information.
     * 
     * @param toSubmit The collection of files to send.
     * @return See above
     */
    private JTabbedPane buildExceptionPane(List<ImportErrorObject> toSubmit) {
        JTabbedPane tPane = new JTabbedPane();
        tPane.setOpaque(false);
        //tPane.setBackground(UIUtilities.WINDOW_BACKGROUND_COLOR);

        if (dialogType == SUBMIT_ERROR_TYPE) {
            tPane.addTab("Comments", null, buildCommentPane(COMMENT_FIELD), "Your comments go here.");
            tPane.addTab("Files to Send", null, buildFilesToSubmitPane(toSubmit),
                    "The files to send to the development team.");
        } else {
            tPane.addTab("Comments", null, buildCommentPane(DEBUG_COMMENT_FIELD), "Your comments go here.");
            tPane.addTab("Error Message", null, buildDebugPane(), "The Exception Message.");
        }
        return tPane;
    }

    /**
     * Builds and lays out the buttons.
     * 
     * @param submit Pass <code>true</code> to display the submit files option,
     *              <code>false</code> otherwise.
     * @return See above.
     */
    private JPanel buildToolBar(boolean submit) {
        JPanel bars = new JPanel();
        bars.setLayout(new BoxLayout(bars, BoxLayout.X_AXIS));
        if (submit) {
            JPanel row = new JPanel();
            row.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0));
            row.add(new JLabel("Submit Exceptions and: "));
            row.add(UIUtilities.buildComponentPanel(submitFile));
            JPanel p = new JPanel();
            p.setBorder(null);
            p.setLayout(new BoxLayout(p, BoxLayout.Y_AXIS));
            p.add(row);
            JPanel progressPane = new JPanel();
            progressPane.setLayout(new BoxLayout(progressPane, BoxLayout.X_AXIS));
            progressPane.add(progress);
            progressPane.add(Box.createHorizontalStrut(5));
            progressPane.add(progressLabel);
            p.add(UIUtilities.buildComponentPanel(progressPane));
            bars.add(UIUtilities.buildComponentPanel(p));
        }
        JPanel bar = new JPanel();
        bar.setLayout(new BoxLayout(bar, BoxLayout.X_AXIS));
        bar.add(cancelButton);
        bar.add(Box.createHorizontalStrut(5));
        bar.add(sendButton);
        bar.add(Box.createHorizontalStrut(10));
        bars.add(UIUtilities.buildComponentPanelRight(bar));
        return bars;
    }

    /** 
     * Builds and lays out the GUI. 
     * 
     * @param toSubmit The collection of files to send.
     */
    private void buildGUI(List<ImportErrorObject> toSubmit) {
        JComponent component;
        Icon icon;
        IconManager icons = IconManager.getInstance();
        String message;
        if (dialogType == SUBMIT_ERROR_TYPE) {
            message = SUBMIT_MESSAGE;
            component = buildExceptionPane(toSubmit);
            icon = icons.getIcon(IconManager.SUBMIT_ICON_64);
            if (icon == null)
                icon = UIManager.getIcon("OptionPane.errorIcon");
        } else if (exception == null) {
            message = MESSAGE;
            icon = icons.getIcon(IconManager.COMMENT_ICON_64);
            if (icon == null)
                icon = UIManager.getIcon("OptionPane.questionIcon");
            component = buildCommentPane(COMMENT_FIELD);
        } else {
            message = DEBUG_MESSAGE;
            component = buildExceptionPane(null);
            icon = icons.getIcon(IconManager.ERROR_ICON_64);
            if (icon == null)
                icon = UIManager.getIcon("OptionPane.errorIcon");
        }
        Container c = getContentPane();
        TitlePanel tp = new TitlePanel(getTitle(), message, icon);
        c.setLayout(new BorderLayout(0, 0));
        c.add(tp, BorderLayout.NORTH);
        c.add(component, BorderLayout.CENTER);
        c.add(buildToolBar(toSubmit != null && toSubmit.size() > 0), BorderLayout.SOUTH);
    }

    /** 
     * Initializes the dialog.
     * 
     *  @param title    The title of the dialog.
     *  @param toSubmit The collection of files to send.
     */
    private void initialize(String title, List<ImportErrorObject> toSubmit) {
        setTitle(title);
        initComponents();
        buildGUI(toSubmit);
        setSize(DEFAULT_SIZE);
    }

    /**
     * Creates a new instance.
     * 
     * @param parent      The parent of this dialog.
     * @param title         The dialog's title.
     * @param emailAddress   The e-mail address of the current user.
     */
    public MessengerDialog(JFrame parent, String title, String emailAddress) {
        super(parent);
        this.emailAddress = emailAddress;
        dialogType = COMMENT_TYPE;
        initialize(title, null);
    }

    /**
     * Creates a new instance.
     * 
     * @param parent      The parent of this dialog.
     * @param title         The dialog's title.
     * @param emailAddress   The e-mail address of the current user.
     * @param exception      The exception to handle.
     */
    public MessengerDialog(JFrame parent, String title, String emailAddress, Exception exception) {
        super(parent);
        dialogType = ERROR_TYPE;
        this.emailAddress = emailAddress;
        this.exception = exception;
        initialize(title, null);
    }

    /**
     * Creates a new instance.
     * 
     * @param parent      The parent of this dialog.
     * @param title         The dialog's title.
     * @param emailAddress   The e-mail address of the current user.
     * @param toSubmit      The object to submit.
     */
    public MessengerDialog(JFrame parent, String title, String emailAddress, List<ImportErrorObject> toSubmit) {
        super(parent);
        this.dialogType = SUBMIT_ERROR_TYPE;
        this.emailAddress = emailAddress;
        initialize(title, toSubmit);
    }

    /**
     * Sets a brief description of the error.
     * 
     * @param description The value to set.
     */
    public void setErrorDescription(String description) {
        errorDescription = description;
    }

    /**
     * Sets the comment to send.
     * 
     * @param comment The text to display.
     */
    public void setComment(String comment) {
        if (comment != null && comment.trim().length() > 0)
            commentArea.setText(comment);
    }

    /** 
     * Sets the version of the server.
     * 
     * @param serverVersion The value to set.
     */
    public void setServerVersion(String serverVersion) {
        this.serverVersion = serverVersion;
    }

    /**
     * Returns the type associated to this widget. 
     * 
     * @return See above.
     */
    public int getDialogType() {
        return dialogType;
    }

    /**
     * Sets the status of the file submission.
     * 
     * @param text The text to display.
     * @param hide Pass <code>true</code> to hide the progress,
     *             <code>false</code> otherwise.
     */
    public void setSubmitStatus(String text, boolean hide) {
        progressLabel.setText(text);
        progress.setVisible(!hide);
        progress.setBusy(!hide);
    }

    /**
     * Reacts to click on controls.
     * @see ActionListener#actionPerformed(ActionEvent)
     */
    public void actionPerformed(ActionEvent e) {
        int index = Integer.parseInt(e.getActionCommand());
        switch (index) {
        case CANCEL:
            close();
            break;
        case SEND:
            send(SEND_PROPERTY);
            break;
        case COPY:
            copy();
            break;
        case SUBMIT:
            submitFilesControl();
        }
    }

    /**
     * Sets the enabled flag of the {@link #sendButton} depending on the 
     * type of dialog we handle.
     * @see DocumentListener#insertUpdate(DocumentEvent)
     */
    public void insertUpdate(DocumentEvent e) {
        if (dialogType == COMMENT_TYPE) {
            String text = commentArea.getText();
            sendButton.setEnabled(text != null && text.trim().length() > 0);
        }
    }

    /**
     * Sets the enabled flag of the {@link #sendButton} depending on the 
     * type of dialog we handle.
     * @see DocumentListener#removeUpdate(DocumentEvent)
     */
    public void removeUpdate(DocumentEvent e) {
        if (dialogType == COMMENT_TYPE) {
            String text = commentArea.getText();
            sendButton.setEnabled(text != null && text.trim().length() > 0);
        }
    }

    /**
     * Required by the {@link DocumentListener} I/F but no-op implementation
     * in our case.
     * @see DocumentListener#changedUpdate(DocumentEvent)
     */
    public void changedUpdate(DocumentEvent e) {
    }

}