view org.eclipse.jface.databinding/src/org/eclipse/jface/databinding/wizard/WizardPageSupport.d @ 78:0a55d2d5a946

Added file for databinding
author Frank Benoit <benoit@tionex.de>
date Tue, 14 Apr 2009 11:35:29 +0200
parents
children 6be48cf9f95c
line wrap: on
line source

/*******************************************************************************
 * Copyright (c) 2007, 2008 IBM Corporation and others.
 * 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
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *     Boris Bokowski - bug 218269
 *     Matthew Hall - bug 218269
 *     Ashley Cambrell - bug 199179 
 *******************************************************************************/
module org.eclipse.jface.databinding.wizard.WizardPageSupport;

import java.lang.all;

import java.util.Iterator;

import org.eclipse.core.databinding.AggregateValidationStatus;
import org.eclipse.core.databinding.DataBindingContext;
import org.eclipse.core.databinding.ValidationStatusProvider;
import org.eclipse.core.databinding.observable.ChangeEvent;
import org.eclipse.core.databinding.observable.IChangeListener;
import org.eclipse.core.databinding.observable.IObservable;
import org.eclipse.core.databinding.observable.list.IListChangeListener;
import org.eclipse.core.databinding.observable.list.IObservableList;
import org.eclipse.core.databinding.observable.list.ListChangeEvent;
import org.eclipse.core.databinding.observable.list.ListDiff;
import org.eclipse.core.databinding.observable.list.ListDiffEntry;
import org.eclipse.core.databinding.observable.value.IValueChangeListener;
import org.eclipse.core.databinding.observable.value.ValueChangeEvent;
import org.eclipse.core.databinding.util.Policy;
import org.eclipse.core.runtime.AssertionFailedException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.MultiStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.dialogs.IMessageProvider;
import org.eclipse.jface.wizard.WizardPage;

/**
 * Connects the validation result from the given data binding context to the
 * given wizard page, updating the wizard page's completion state and its error
 * message accordingly.
 * 
 * @noextend This class is not intended to be subclassed by clients.
 *
 * @since 1.1
 */
public class WizardPageSupport {

    private WizardPage wizardPage;
    private DataBindingContext dbc;
    private AggregateValidationStatus aggregateStatus;
    private bool uiChanged = false;

    /**
     * Connect the validation result from the given data binding context to the
     * given wizard page. Upon creation, the wizard page support will use the
     * context's validation result to determine whether the page is complete.
     * The page's error message will not be set at this time ensuring that the
     * wizard page does not show an error right away. Upon any validation result
     * change, {@link WizardPage#setPageComplete(bool)} will be called
     * reflecting the new validation result, and the wizard page's error message
     * will be updated according to the current validation result.
     * 
     * @param wizardPage
     * @param dbc
     * @return an instance of WizardPageSupport
     */
    public static WizardPageSupport create(WizardPage wizardPage,
            DataBindingContext dbc) {
        return new WizardPageSupport(wizardPage, dbc);
    }

    private this(WizardPage wizardPage, DataBindingContext dbc) {
        this.wizardPage = wizardPage;
        this.dbc = dbc;
        init();
    }

    private IChangeListener uiChangeListener = new class() IChangeListener {
        public void handleChange(ChangeEvent event) {
            handleUIChanged();
        }
    };
    private IListChangeListener validationStatusProvidersListener = new class() IListChangeListener {
        public void handleListChange(ListChangeEvent event) {
            ListDiff diff = event.diff;
            ListDiffEntry[] differences = diff.getDifferences();
            for (int i = 0; i < differences.length; i++) {
                ListDiffEntry listDiffEntry = differences[i];
                ValidationStatusProvider validationStatusProvider = cast(ValidationStatusProvider) listDiffEntry
                        .getElement();
                IObservableList targets = validationStatusProvider.getTargets();
                if (listDiffEntry.isAddition()) {
                    targets
                            .addListChangeListener(validationStatusProviderTargetsListener);
                    for (Iterator it = targets.iterator(); it.hasNext();) {
                        (cast(IObservable) it.next())
                                .addChangeListener(uiChangeListener);
                    }
                } else {
                    targets
                            .removeListChangeListener(validationStatusProviderTargetsListener);
                    for (Iterator it = targets.iterator(); it.hasNext();) {
                        (cast(IObservable) it.next())
                                .removeChangeListener(uiChangeListener);
                    }
                }
            }
        }
    };
    private IListChangeListener validationStatusProviderTargetsListener = new class() IListChangeListener {
        public void handleListChange(ListChangeEvent event) {
            ListDiff diff = event.diff;
            ListDiffEntry[] differences = diff.getDifferences();
            for (int i = 0; i < differences.length; i++) {
                ListDiffEntry listDiffEntry = differences[i];
                IObservable target = cast(IObservable) listDiffEntry.getElement();
                if (listDiffEntry.isAddition()) {
                    target.addChangeListener(uiChangeListener);
                } else {
                    target.removeChangeListener(uiChangeListener);
                }
            }
        }
    };
    private IStatus currentStatus;

    protected void init() {
        aggregateStatus = new AggregateValidationStatus(dbc
                .getValidationStatusProviders(),
                AggregateValidationStatus.MAX_SEVERITY);
        aggregateStatus.addValueChangeListener(new class() IValueChangeListener {
            public void handleValueChange(ValueChangeEvent event) {

                currentStatus = cast(IStatus) event.diff.getNewValue();
                handleStatusChanged();
            }
        });
        currentStatus = cast(IStatus) aggregateStatus.getValue();
        handleStatusChanged();
        dbc.getValidationStatusProviders().addListChangeListener(
                validationStatusProvidersListener);
        for (Iterator it = dbc.getValidationStatusProviders().iterator(); it
                .hasNext();) {
            ValidationStatusProvider validationStatusProvider = cast(ValidationStatusProvider) it
                    .next();
            IObservableList targets = validationStatusProvider.getTargets();
            targets
                    .addListChangeListener(validationStatusProviderTargetsListener);
            for (Iterator iter = targets.iterator(); iter.hasNext();) {
                (cast(IObservable) iter.next()).addChangeListener(uiChangeListener);
            }
        }
    }

    protected void handleUIChanged() {
        uiChanged = true;
        if (currentStatus !is null) {
            handleStatusChanged();
        }
        dbc.getValidationStatusProviders().removeListChangeListener(
                validationStatusProvidersListener);
        for (Iterator it = dbc.getValidationStatusProviders().iterator(); it
                .hasNext();) {
            ValidationStatusProvider validationStatusProvider = cast(ValidationStatusProvider) it
                    .next();
            IObservableList targets = validationStatusProvider.getTargets();
            targets
                    .removeListChangeListener(validationStatusProviderTargetsListener);
            for (Iterator iter = targets.iterator(); iter.hasNext();) {
                (cast(IObservable) iter.next())
                        .removeChangeListener(uiChangeListener);
            }
        }
    }

    protected void handleStatusChanged() {
        if (currentStatus !is null
                && currentStatus.getSeverity() is IStatus.ERROR) {
            wizardPage.setPageComplete(false);
            wizardPage.setMessage(null);
            wizardPage.setErrorMessage(uiChanged ? currentStatus.getMessage()
                    : null);
            if (currentStatusHasException()) {
                handleStatusException();
            }
        } else if (currentStatus !is null
                && currentStatus.getSeverity() !is IStatus.OK) {
            int severity = currentStatus.getSeverity();
            wizardPage.setPageComplete((severity & IStatus.CANCEL) !is 0);
            int type;
            switch (severity) {
            case IStatus.OK:
                type = IMessageProvider.NONE;
                break;
            case IStatus.CANCEL:
                type = IMessageProvider.NONE;
                break;
            case IStatus.INFO:
                type = IMessageProvider.INFORMATION;
                break;
            case IStatus.WARNING:
                type = IMessageProvider.WARNING;
                break;
            case IStatus.ERROR:
                type = IMessageProvider.ERROR;
                break;
            default:
                throw new AssertionFailedException(
                        "incomplete switch statement"); //$NON-NLS-1$
            }
            wizardPage.setErrorMessage(null);
            wizardPage.setMessage(currentStatus.getMessage(), type);
        } else {
            wizardPage.setPageComplete(true);
            wizardPage.setMessage(null);
            wizardPage.setErrorMessage(null);
        }
    }

    private bool currentStatusHasException() {
        bool hasException = false;
        if (currentStatus.getException() !is null) {
            hasException = true;
        }
        if (null !is cast(MultiStatus)currentStatus) {
            MultiStatus multiStatus = cast(MultiStatus) currentStatus;

            for (int i = 0; i < multiStatus.getChildren().length; i++) {
                IStatus status = multiStatus.getChildren()[i];
                if (status.getException() !is null) {
                    hasException = true;
                    break;
                }
            }
        }
        return hasException;
    }

    /**
     * This is called when a Override to provide custom exception handling and
     * reporting.
     */
    protected void handleStatusException() {
        if (currentStatus.getException() !is null) {
            logThrowable(currentStatus.getException());
        } else if (null !is cast(MultiStatus)currentStatus) {
            MultiStatus multiStatus = cast(MultiStatus) currentStatus;
            for (int i = 0; i < multiStatus.getChildren().length; i++) {
                IStatus status = multiStatus.getChildren()[i];
                if (status.getException() !is null) {
                    logThrowable(status.getException());
                }
            }
        }
    }

    private void logThrowable(Throwable throwable) {
        Policy
                .getLog()
                .log(
                        new Status(
                                IStatus.ERROR,
                                Policy.JFACE_DATABINDING,
                                IStatus.OK,
                                "Unhandled exception: " + throwable.getMessage(), throwable)); //$NON-NLS-1$
    }

    /**
     * Disposes of this wizard page support object, removing any listeners it
     * may have attached.
     */
    public void dispose() {
        aggregateStatus.dispose();
        if (!uiChanged) {
            for (Iterator it = dbc.getValidationStatusProviders().iterator(); it
                    .hasNext();) {
                ValidationStatusProvider validationStatusProvider = cast(ValidationStatusProvider) it
                        .next();
                IObservableList targets = validationStatusProvider.getTargets();
                targets
                        .removeListChangeListener(validationStatusProviderTargetsListener);
                for (Iterator iter = targets.iterator(); iter.hasNext();) {
                    (cast(IObservable) iter.next())
                            .removeChangeListener(uiChangeListener);
                }
            }
            dbc.getValidationStatusProviders().removeListChangeListener(
                    validationStatusProvidersListener);
        }
        aggregateStatus = null;
        dbc = null;
        uiChangeListener = null;
        validationStatusProvidersListener = null;
        validationStatusProviderTargetsListener = null;
        wizardPage = null;
    }
}