eu.geclipse.ui.dialogs.ProblemDialog.java Source code

Java tutorial

Introduction

Here is the source code for eu.geclipse.ui.dialogs.ProblemDialog.java

Source

/*****************************************************************************
 * Copyright (c) 2007-2008 g-Eclipse Consortium
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Initial development of the original code was made for the
 * g-Eclipse project founded by European Union
 * project number: FP6-IST-034327  http://www.geclipse.eu/
 *
 * Contributors:
 *    Mathias Stuempert - initial API and implementation
 *****************************************************************************/

package eu.geclipse.ui.dialogs;

import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.resource.ImageRegistry;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.ScrolledComposite;
import org.eclipse.swt.events.ControlAdapter;
import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Link;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;

import eu.geclipse.core.reporting.IProblem;
import eu.geclipse.core.reporting.ISolution;
import eu.geclipse.core.reporting.ProblemException;
import eu.geclipse.ui.internal.Activator;
import eu.geclipse.ui.internal.LogExceptionSolution;
import eu.geclipse.ui.internal.ReportProblemSolution;
import eu.geclipse.ui.internal.layout.PackData;
import eu.geclipse.ui.internal.layout.PackLayout;

/**
 * The ProblemDialog is the user-friendly way of g-Eclipse of reporting
 * problems to the user. It displays not only the description of the problem
 * but also the registered solutions that could potentially solve the problem.
 * The active solutions are clickable and perform some action, like generating
 * a problem report or logging the exception.
 */
public class ProblemDialog extends ErrorDialog {

    /**
     * Return code determining that a solution was chosen.
     */
    public static final int SOLVE = 2;

    private final Throwable exc;

    private ProblemDialog(final Shell parentShell, final String dialogTitle, final String message,
            final Throwable exc) {
        super(parentShell, dialogTitle, message, getStatus(exc),
                IStatus.OK | IStatus.INFO | IStatus.WARNING | IStatus.ERROR);
        this.message = message;
        this.exc = exc;
    }

    /**
     * Convenience static method for opening a {@link ProblemDialog}. This
     * method has to be called from the UI thread. The parent {@link Shell}
     * may be <code>null</code>. In this case a default {@link Shell} is
     * chosen. Nevertheless it is recommended to not call this method
     * without a valid {@link Shell}. 
     * 
     * @param parent The parent {@link Shell} of the dialog.
     * @param dialogTitle The dialog's title.
     * @param message A short message displayed as description of the problem.
     * @param exc An optional exception. If this is a {@link ProblemException}
     * the corresponding reasons and solutions are displayed.
     * @return The dialog's return status.
     */
    public static int openProblem(final Shell parent, final String dialogTitle, final String message,
            final Throwable exc) {

        Shell shell = parent;
        if (shell == null) {
            IWorkbench workbench = PlatformUI.getWorkbench();
            IWorkbenchWindow window = workbench.getActiveWorkbenchWindow();
            if (window != null) {
                shell = window.getShell();
            }
        }

        final ProblemDialog dialog = new ProblemDialog(shell, dialogTitle, message, exc);

        if (shell != null) {
            Display display = Display.getCurrent();
            if ((display == null) || (display.isDisposed())) {
                display = Display.getDefault();
            }
            display.syncExec(new Runnable() {
                public void run() {
                    dialog.open();
                }
            });
        }

        return dialog.getReturnCode();
    }

    /* (non-Javadoc)
     * @see org.eclipse.jface.dialogs.IconAndMessageDialog#createMessageArea(org.eclipse.swt.widgets.Composite)
     */
    @Override
    protected Control createMessageArea(final Composite parent) {

        Image image = getImage();
        if (image != null) {
            this.imageLabel = new Label(parent, SWT.NULL);
            image.setBackground(this.imageLabel.getBackground());
            this.imageLabel.setImage(image);
            // TODO mathias addAccessibleListeners missing
            this.imageLabel.setLayoutData(
                    new GridData(GridData.HORIZONTAL_ALIGN_CENTER | GridData.VERTICAL_ALIGN_BEGINNING));
        }

        Composite composite = new Composite(parent, SWT.NONE);
        composite.setLayoutData(new GridData(GridData.GRAB_HORIZONTAL | GridData.GRAB_VERTICAL
                | GridData.HORIZONTAL_ALIGN_FILL | GridData.VERTICAL_ALIGN_BEGINNING));
        composite.setLayout(new PackLayout(SWT.VERTICAL));

        createLabelArea(composite);
        createReasonArea(composite);
        createSolutionArea(composite);

        return composite;

    }

    protected void createLabelArea(final Composite parent) {

        if (this.message != null) {

            int wHint = convertHorizontalDLUsToPixels(IDialogConstants.MINIMUM_MESSAGE_AREA_WIDTH);

            final ScrolledComposite sComp = createListArea("Message:", parent, 100);

            final Composite comp = new Composite(sComp, SWT.NONE);
            sComp.setContent(comp);
            comp.setLayout(new GridLayout(1, false));

            Label label = new Label(comp, SWT.WRAP);
            label.setText(this.message);
            GridData gData = new GridData(GridData.FILL_HORIZONTAL);
            gData.grabExcessHorizontalSpace = true;
            gData.widthHint = wHint;
            label.setLayoutData(gData);

            Point size = comp.computeSize(wHint, SWT.DEFAULT);
            comp.setSize(size);

            sComp.addControlListener(new ControlAdapter() {
                @Override
                public void controlResized(final ControlEvent e) {
                    Rectangle r = sComp.getClientArea();
                    Point cSize = comp.computeSize(r.width, SWT.DEFAULT);
                    comp.setSize(cSize);
                }
            });

        }

    }

    protected void createReasonArea(final Composite parent) {

        String[] reasons = getReasons();

        if ((reasons != null) && (reasons.length > 0)) {

            ImageRegistry imgReg = Activator.getDefault().getImageRegistry();
            Image reasonImage = imgReg.get("reason"); //$NON-NLS-1$

            final ScrolledComposite sComp = createListArea("Reasons:", parent, 200);

            final Composite reasonList = new Composite(sComp, SWT.NONE);
            sComp.setContent(reasonList);
            reasonList.setLayout(new GridLayout(2, false));

            for (String reason : reasons) {

                Label imgLabel = new Label(reasonList, SWT.NONE);
                imgLabel.setImage(reasonImage);
                GridData gData = new GridData();
                gData.horizontalAlignment = GridData.CENTER;
                gData.verticalAlignment = GridData.BEGINNING;
                imgLabel.setLayoutData(gData);

                Label label = new Label(reasonList, SWT.WRAP);
                label.setText(reason);
                gData = new GridData(GridData.FILL_HORIZONTAL);
                gData.grabExcessHorizontalSpace = true;
                gData.horizontalAlignment = GridData.BEGINNING;
                label.setLayoutData(gData);

            }

            int wHint = convertHorizontalDLUsToPixels(IDialogConstants.MINIMUM_MESSAGE_AREA_WIDTH);
            reasonList.setSize(reasonList.computeSize(wHint, SWT.DEFAULT));

            sComp.addControlListener(new ControlAdapter() {
                @Override
                public void controlResized(final ControlEvent e) {
                    Rectangle r = sComp.getClientArea();
                    Point cSize = reasonList.computeSize(r.width, SWT.DEFAULT);
                    reasonList.setSize(cSize);
                }
            });

        }

    }

    protected void createSolutionArea(final Composite parent) {

        ISolution[] solutions = getSolutions();

        if ((solutions != null) && (solutions.length > 0)) {

            ImageRegistry imgReg = Activator.getDefault().getImageRegistry();
            Image solutionImage = imgReg.get("solution"); //$NON-NLS-1$

            final ScrolledComposite sComp = createListArea(Messages.getString("ProblemDialog.solutions_label"), //$NON-NLS-1$
                    parent, 200);

            final Composite solutionList = new Composite(sComp, SWT.NONE);
            sComp.setContent(solutionList);
            solutionList.setLayout(new GridLayout(2, false));

            for (final ISolution solution : solutions) {

                Label imgLabel = new Label(solutionList, SWT.NONE);
                imgLabel.setImage(solutionImage);
                GridData gData = new GridData();
                gData.horizontalAlignment = GridData.CENTER;
                gData.verticalAlignment = GridData.BEGINNING;
                imgLabel.setLayoutData(gData);

                Link link = new Link(solutionList, SWT.WRAP);
                String text = solution.getDescription();
                if (solution.isActive()) {
                    link.setText("<a>" + text + "</a>"); //$NON-NLS-1$ //$NON-NLS-2$
                } else {
                    link.setText(text);
                }
                gData = new GridData(GridData.FILL_HORIZONTAL);
                gData.grabExcessHorizontalSpace = true;
                gData.horizontalAlignment = GridData.BEGINNING;
                link.setLayoutData(gData);
                link.addSelectionListener(new SelectionAdapter() {
                    @SuppressWarnings("synthetic-access")
                    @Override
                    public void widgetSelected(final SelectionEvent e) {
                        setReturnCode(SOLVE);
                        close();
                        try {
                            solution.solve();
                        } catch (InvocationTargetException itExc) {
                            Throwable cause = itExc.getCause();
                            Activator.logException(cause);
                        }
                    }
                });
            }

            int wHint = convertHorizontalDLUsToPixels(IDialogConstants.MINIMUM_MESSAGE_AREA_WIDTH);
            solutionList.setSize(solutionList.computeSize(wHint, SWT.DEFAULT));

            sComp.addControlListener(new ControlAdapter() {
                @Override
                public void controlResized(final ControlEvent e) {
                    Rectangle r = sComp.getClientArea();
                    Point cSize = solutionList.computeSize(r.width, SWT.DEFAULT);
                    solutionList.setSize(cSize);
                }
            });

        }

    }

    protected IProblem getProblem() {

        IProblem result = null;

        if ((this.exc != null) && (this.exc instanceof ProblemException)) {
            result = ((ProblemException) this.exc).getProblem();
        }

        return result;

    }

    protected String[] getReasons() {

        List<String> resultList = new ArrayList<String>();

        IStatus status = getStatus();
        if (status != null) {
            resultList.add(status.getMessage());
        }

        IProblem problem = getProblem();
        if (problem != null) {
            String[] reasons = problem.getReasons();
            if (reasons != null) {
                for (String reason : reasons) {
                    resultList.add(reason);
                }
            }
        }

        return resultList.isEmpty() ? null : resultList.toArray(new String[resultList.size()]);

    }

    protected ISolution[] getSolutions() {

        List<ISolution> resultList = new ArrayList<ISolution>();

        IProblem problem = getProblem();
        if (problem != null) {
            List<ISolution> list = Arrays.asList(problem.getSolutions());
            resultList.addAll(list);
        }

        if (this.exc != null) {
            resultList.add(new LogExceptionSolution(this.exc));
            resultList.add(new ReportProblemSolution(this.exc));
        }

        return resultList.toArray(new ISolution[resultList.size()]);

    }

    protected IStatus getStatus() {
        return getStatus(this.exc);
    }

    private ScrolledComposite createListArea(final String title, final Composite parent,
            final int maxScrollableHeight) {

        Composite comp = new Composite(parent, SWT.NONE);
        PackLayout layout = new PackLayout(SWT.VERTICAL);
        comp.setLayout(layout);
        PackData pData = new PackData();
        comp.setLayoutData(pData);

        Label label = new Label(comp, SWT.NONE);
        label.setText(title);

        final ScrolledComposite sComp = new ScrolledComposite(comp, SWT.V_SCROLL);
        pData = new PackData();
        pData.minHeight = 10;
        pData.maxHeight = maxScrollableHeight;
        sComp.setLayoutData(pData);

        return sComp;

    }

    private static IStatus getStatus(final Throwable throwable) {

        IStatus result = null;

        if ((throwable != null) && (throwable instanceof CoreException)) {
            result = ((CoreException) throwable).getStatus();
        }

        else {
            String message = null;
            if (throwable != null) {
                message = throwable.getMessage();
            }
            if (message == null) {
                message = Messages.getString("ProblemDialog.no_further_info"); //$NON-NLS-1$
            }
            result = new Status(IStatus.ERROR, Activator.PLUGIN_ID, IStatus.OK, message, throwable);
        }

        return result;

    }

}