nl.utwente.ce.imageexport.ExceptionErrorDialog.java Source code

Java tutorial

Introduction

Here is the source code for nl.utwente.ce.imageexport.ExceptionErrorDialog.java

Source

/*
 * This file is part of ImageExport.
 *
 * ImageExport 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 3 of the License, or
 * (at your option) any later version.
 *
 * ImageExport 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 ImageExport.  If not, see <http://www.gnu.org/licenses/>.
 */
package nl.utwente.ce.imageexport;

import java.io.PrintWriter;
import java.io.StringWriter;

import org.eclipse.core.runtime.IStatus;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.IconAndMessageDialog;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;

/**
 * <p>
 * Class that shows an exception in a Eclipse {@link IconAndMessageDialog}.
 * </p>
 * <p>
 * This class is loosely based on {@link org.eclipse.jface.dialogs.ErrorDialog ErrorDialog}
 * </p>
 */
public class ExceptionErrorDialog extends IconAndMessageDialog {
    /** The Details button. */
    private Button detailsButton;

    /** The title of the dialog. */
    private String title;

    /** The SWT list control that displays the error details. */
    private Text text;

    /** Indicates whether the error details viewer is currently created. */
    private boolean listCreated = false;

    /** The status object. */
    private IStatus status;

    /**
     * @param parentShell the shell under which to create this dialog
     * @param dialogTitle the title to use for this dialog, or <code>null</code> to indicate that the default title
     *            should be used
     * @param message the message to show in this dialog, or <code>null</code> to indicate that the error's message
     *            should be shown as the primary message
     * @param status the error to show to the user
     */
    public ExceptionErrorDialog(Shell parentShell, String dialogTitle, String message, IStatus status) {
        super(parentShell);
        this.title = dialogTitle == null ? JFaceResources.getString("Problem_Occurred") : //$NON-NLS-1$
                dialogTitle;
        this.message = message == null ? status.getMessage()
                : JFaceResources.format("Reason", new Object[] { message, status.getMessage() }); //$NON-NLS-1$
        this.status = status;
    }

    @Override
    protected void buttonPressed(int id) {
        if (id == IDialogConstants.DETAILS_ID) {
            // Details button got pressed
            toggleDetailsArea();
        } else {
            super.buttonPressed(id);
        }
    }

    @Override
    protected void configureShell(Shell shell) {
        super.configureShell(shell);
        shell.setText(title);
    }

    @Override
    protected void createButtonsForButtonBar(Composite parent) {
        // create OK and Details buttons
        createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true);
        detailsButton = createButton(parent, IDialogConstants.DETAILS_ID, IDialogConstants.SHOW_DETAILS_LABEL,
                false);
    }

    /** Create the area for extra error support information. */
    private void createSupportArea(Composite parent) {
        Composite supportArea = new Composite(parent, SWT.NONE);
        GridData supportData = new GridData(SWT.FILL, SWT.FILL, true, true);
        supportData.verticalSpan = 3;
        supportArea.setLayoutData(supportData);
        if (supportArea.getLayout() == null) {
            GridLayout layout = new GridLayout();
            layout.marginWidth = 0;
            layout.marginHeight = 0;
            supportArea.setLayout(layout); // Give it a default layout if one isn't set
        }
    }

    @Override
    protected Control createDialogArea(Composite parent) {
        Composite composite = new Composite(parent, SWT.NONE);
        createMessageArea(composite);
        createSupportArea(parent);
        GridLayout layout = new GridLayout();
        layout.marginHeight = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_MARGIN);
        layout.marginWidth = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_MARGIN);
        layout.verticalSpacing = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_SPACING);
        layout.horizontalSpacing = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_SPACING);
        layout.numColumns = 2;
        composite.setLayout(layout);
        GridData childData = new GridData(GridData.FILL_BOTH);
        childData.horizontalSpan = 2;
        childData.grabExcessVerticalSpace = false;
        composite.setLayoutData(childData);
        composite.setFont(parent.getFont());

        return composite;
    }

    @Override
    protected void createDialogAndButtonArea(Composite parent) {
        super.createDialogAndButtonArea(parent);
        if (this.dialogArea instanceof Composite) {
            // Create a label if there are no children to force a smaller layout
            Composite dialogComposite = (Composite) dialogArea;
            if (dialogComposite.getChildren().length == 0) {
                new Label(dialogComposite, SWT.NULL);
            }
        }
    }

    @Override
    protected Image getImage() {
        if (status != null) {
            if (status.getSeverity() == IStatus.WARNING) {
                return getWarningImage();
            }
            if (status.getSeverity() == IStatus.INFO) {
                return getInfoImage();
            }
        }
        // If it was not a warning or an info then return the error image
        return getErrorImage();
    }

    /**
     * Create this dialog's drop-down text component. The text is displayed after the user presses details button. It is
     * developer responsibility to display details button if and only if there is some content on drop down list. The
     * visibility of the details button is controlled by {@link #shouldShowDetailsButton()}, which should also be
     * overridden together with this method.
     * 
     * @param parent the parent composite
     * @return the drop-down list component
     */
    protected Text createDropDownText(Composite parent) {
        text = new Text(parent, SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL | SWT.MULTI);
        // fill the list
        populateList(text, status);
        GridData data = new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL
                | GridData.VERTICAL_ALIGN_FILL | GridData.GRAB_VERTICAL);
        data.horizontalSpan = 2;
        text.setLayoutData(data);
        text.setFont(parent.getFont());
        text.setEditable(false);
        listCreated = true;
        return text;
    }

    /**
     * Opens an error dialog to display the given error.
     * 
     * @param parentShell the parent shell of the dialog, or <code>null</code> if none
     * @param title the title to use for this dialog, or <code>null</code> to indicate that the default title should be
     *            used
     * @param message the message to show in this dialog, or <code>null</code> to indicate that the error's message
     *            should be shown as the primary message
     * @param status the error to show to the user
     */
    public static void openError(Shell parentShell, String title, String message, IStatus status) {
        ExceptionErrorDialog dialog = new ExceptionErrorDialog(parentShell, title, message, status);
        dialog.open();
    }

    /**
     * Populate the list with the messages from the given status. Traverse the children of the status deeply and also
     * traverse CoreExceptions that appear in the status.
     * 
     * @param listToPopulate the list to populate
     * @param buildingStatus the status being displayed
     */
    private void populateList(Text listToPopulate, IStatus buildingStatus) {
        Throwable t = buildingStatus.getException();
        // Include low-level exception message
        StringWriter sw = new StringWriter();
        PrintWriter pw = new PrintWriter(sw);
        t.printStackTrace(pw);
        String message = sw.getBuffer().toString();
        if (message == null) {
            message = t.toString();
        }
        listToPopulate.append(message);
    }

    /** Toggles the unfolding of the details area. This is triggered by the user pressing the details button. */
    private void toggleDetailsArea() {
        Point windowSize = getShell().getSize();
        Point oldSize = getShell().computeSize(SWT.DEFAULT, SWT.DEFAULT);
        if (listCreated) {
            text.dispose();
            listCreated = false;
            detailsButton.setText(IDialogConstants.SHOW_DETAILS_LABEL);
        } else {
            text = createDropDownText((Composite) getContents());
            detailsButton.setText(IDialogConstants.HIDE_DETAILS_LABEL);
            getContents().getShell().layout();
        }
        Point newSize = getShell().computeSize(SWT.DEFAULT, SWT.DEFAULT);
        getShell().setSize(new Point(windowSize.x, windowSize.y + (newSize.y - oldSize.y)));
    }

    /**
     * Show the details portion of the dialog if it is not already visible. This method will only work when it is
     * invoked after the control of the dialog has been set. In other words, after the <code>createContents</code>
     * method has been invoked and has returned the control for the content area of the dialog. Invoking the method
     * before the content area has been set or after the dialog has been disposed will have no effect.
     * 
     * @since 3.1
     */
    protected final void showDetailsArea() {
        if (!listCreated) {
            Control control = getContents();
            if (control != null && !control.isDisposed()) {
                toggleDetailsArea();
            }
        }
    }

    protected boolean isResizable() {
        return true;
    }
}