diff 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 diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.jface.databinding/src/org/eclipse/jface/databinding/wizard/WizardPageSupport.d	Tue Apr 14 11:35:29 2009 +0200
@@ -0,0 +1,301 @@
+/*******************************************************************************
+ * 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;
+    }
+}