view org.eclipse.jface.databinding/src/org/eclipse/jface/databinding/viewers/ObservableValueEditingSupport.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
 *******************************************************************************/

module org.eclipse.jface.databinding.viewers.ObservableValueEditingSupport;

import java.lang.all;

import org.eclipse.core.databinding.Binding;
import org.eclipse.core.databinding.DataBindingContext;
import org.eclipse.core.databinding.UpdateValueStrategy;
import org.eclipse.core.databinding.observable.value.IObservableValue;
import org.eclipse.core.runtime.Assert;
import org.eclipse.jface.viewers.CellEditor;
import org.eclipse.jface.viewers.ColumnViewer;
import org.eclipse.jface.viewers.ColumnViewerEditorActivationEvent;
import org.eclipse.jface.viewers.ColumnViewerEditorActivationListener;
import org.eclipse.jface.viewers.ColumnViewerEditorDeactivationEvent;
import org.eclipse.jface.viewers.EditingSupport;
import org.eclipse.jface.viewers.ViewerCell;

/**
 * {@link EditingSupport} using the JFace Data Binding concepts to handle the
 * updating of an element from a {@link CellEditor}.
 * 
 * @since 1.2
 */
public abstract class ObservableValueEditingSupport : EditingSupport {
    /**
     * Maintains references to the instances currently imployed while editing.
     * Will be <code>null</code> when not editing.
     */
    private EditingState editingState;

    private final ColumnViewerEditorActivationListenerHelper activationListener = new ColumnViewerEditorActivationListenerHelper();

    private ColumnViewer viewer;

    private DataBindingContext dbc;

    /**
     * Constructs a new instance with the provided <code>viewer</code> and
     * <code>dbc</code>.
     * 
     * @param viewer
     *            viewer to edit
     * @param dbc
     *            dbc to create <code>Bindings</code>
     */
    public this(ColumnViewer viewer,
            DataBindingContext dbc) {
        super(viewer);

        if (dbc is null) {
            throw new IllegalArgumentException("Parameter dbc was null."); //$NON-NLS-1$
        }

        this.viewer = viewer;
        this.dbc = dbc;
    }

    /**
     * Default implementation always returns <code>true</code>.
     * 
     * @see org.eclipse.jface.viewers.EditingSupport#canEdit(java.lang.Object)
     */
    protected bool canEdit(Object element) {
        return true;
    }

    /**
     * Default implementation always returns <code>null</code> as this will be
     * handled by the Binding.
     * 
     * @see org.eclipse.jface.viewers.EditingSupport#getValue(java.lang.Object)
     */
    protected Object getValue(Object element) {
        // no op
        return null;
    }

    /**
     * Default implementation does nothing as this will be handled by the
     * Binding.
     * 
     * @see org.eclipse.jface.viewers.EditingSupport#setValue(java.lang.Object,
     *      java.lang.Object)
     */
    protected void setValue(Object element, Object value) {
        // no op
    }

    /**
     * Creates a {@link Binding} between the editor and the element to be
     * edited. Invokes {@link #doCreateCellEditorObservable(CellEditor)},
     * {@link #doCreateElementObservable(Object, ViewerCell)}, and then
     * {@link #createBinding(IObservableValue, IObservableValue)}.
     */
    final protected void initializeCellEditorValue(CellEditor cellEditor,
            ViewerCell cell) {
        IObservableValue target = doCreateCellEditorObservable(cellEditor);
        Assert
                .isNotNull(target,
                        "doCreateCellEditorObservable(...) did not return an observable"); //$NON-NLS-1$

        IObservableValue model = doCreateElementObservable(cell.getElement(),
                cell);
        Assert.isNotNull(model,
                "doCreateElementObservable(...) did not return an observable"); //$NON-NLS-1$

        Binding binding = createBinding(target, model);
        Assert
                .isNotNull(binding,
                        "createBinding(...) did not return a binding"); //$NON-NLS-1$

        editingState = new EditingState(binding, target, model);

        getViewer().getColumnViewerEditor().addEditorActivationListener(
                activationListener);
    }

    /**
     * Creates the observable value for the CellEditor.
     * 
     * @param cellEditor
     * @return observable value
     */
    protected abstract IObservableValue doCreateCellEditorObservable(
            CellEditor cellEditor);

    /**
     * Creates the observable value for the element.
     * 
     * @param element
     * @param cell
     * @return observable value
     */
    protected abstract IObservableValue doCreateElementObservable(
            Object element, ViewerCell cell);

    /**
     * Creates a new binding for the provided <code>target</code> and
     * <code>model</code>. Default
     * {@link UpdateValueStrategy value update strategies} are used with the
     * target to model updating on {@link UpdateValueStrategy#POLICY_CONVERT}.
     * 
     * @param target
     * @param model
     * @return binding
     */
    protected Binding createBinding(IObservableValue target,
            IObservableValue model) {
        return dbc.bindValue(target, model, new UpdateValueStrategy(
                UpdateValueStrategy.POLICY_CONVERT), null);
    }

    /**
     * Updates the model from the target.
     */
    final protected void saveCellEditorValue(CellEditor cellEditor,
            ViewerCell cell) {
        editingState.binding.updateTargetToModel();
    }

    private class ColumnViewerEditorActivationListenerHelper :
            ColumnViewerEditorActivationListener {

        public void afterEditorActivated(ColumnViewerEditorActivationEvent event) {
            // do nothing
        }

        public void afterEditorDeactivated(
                ColumnViewerEditorDeactivationEvent event) {
            editingState.dispose();
            editingState = null;

            viewer.getColumnViewerEditor().removeEditorActivationListener(this);
        }

        public void beforeEditorActivated(
                ColumnViewerEditorActivationEvent event) {
            // do nothing
        }

        public void beforeEditorDeactivated(
                ColumnViewerEditorDeactivationEvent event) {
            // do nothing
        }
    }

    /**
     * Maintains references to objects that only live for the length of the edit
     * cycle.
     */
    private static class EditingState {
        IObservableValue target;

        IObservableValue model;

        Binding binding;

        this(Binding binding, IObservableValue target,
                IObservableValue model) {
            this.binding = binding;
            this.target = target;
            this.model = model;
        }

        void dispose() {
            target.dispose();
            model.dispose();
            binding.dispose();
        }
    }
}