org.eclipse.riena.internal.ui.ridgets.swt.DateTimeRidget.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.riena.internal.ui.ridgets.swt.DateTimeRidget.java

Source

/*******************************************************************************
 * Copyright (c) 2007, 2013 compeople AG 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:
 *    compeople AG - initial API and implementation
 *******************************************************************************/
package org.eclipse.riena.internal.ui.ridgets.swt;

import java.text.SimpleDateFormat;
import java.util.Date;

import org.eclipse.core.databinding.Binding;
import org.eclipse.core.databinding.DataBindingContext;
import org.eclipse.core.databinding.UpdateValueStrategy;
import org.eclipse.core.databinding.beans.BeansObservables;
import org.eclipse.core.databinding.beans.PojoObservables;
import org.eclipse.core.databinding.conversion.IConverter;
import org.eclipse.core.databinding.observable.value.DateAndTimeObservableValue;
import org.eclipse.core.databinding.observable.value.IObservableValue;
import org.eclipse.core.databinding.observable.value.WritableValue;
import org.eclipse.core.databinding.validation.IValidator;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.jface.databinding.swt.WidgetProperties;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.DateTime;

import org.eclipse.riena.ui.ridgets.IDateTimeRidget;
import org.eclipse.riena.ui.ridgets.swt.AbstractEditableRidget;
import org.eclipse.riena.ui.ridgets.swt.AbstractSWTRidget;

/**
 * Ridget for {@link DateTime} widgets.
 */
public class DateTimeRidget extends AbstractEditableRidget implements IDateTimeRidget {

    /**
     * This property is used by the databinding to sync ridget and model. It is
     * always fired before its sibling {@link IDateTimeRidget#PROPERTY_DATE} to
     * ensure that the model is updated before any listeners try accessing it.
     * <p>
     * This property is not API. Do not use in client code.
     */
    private static final String PROPERTY_DATE_INTERNAL = "dateInternal"; //$NON-NLS-1$

    private Date date;
    private DataBindingContext dbc;
    private Binding controlBinding;

    @Override
    protected void checkUIControl(final Object uiControl) {
        checkType(uiControl, DateTime.class);
    }

    @Override
    protected void bindUIControl() {
        final DateTime control = getUIControl();
        if (control != null) {
            dbc = new DataBindingContext();
            final IObservableValue timeObservable;
            final IObservableValue dateObservable;
            final Date nonNullDate = getNonNullDate(getDate());
            if (isTimeControl(control)) {
                // it is a time widget
                timeObservable = WidgetProperties.selection().observe(control);
                timeObservable.setValue(nonNullDate);
                dateObservable = new WritableValue(timeObservable.getRealm(), nonNullDate, Date.class);
            } else {
                // it is  date/calendar widget
                dateObservable = WidgetProperties.selection().observe(control);
                dateObservable.setValue(nonNullDate);
                timeObservable = new WritableValue(dateObservable.getRealm(), nonNullDate, Date.class);
            }
            controlBinding = dbc.bindValue(
                    new DateAndTimeObservableWithNullConversion(dateObservable, timeObservable),
                    getRidgetObservable(),
                    new UpdateValueStrategy(UpdateValueStrategy.POLICY_UPDATE)
                            .setAfterGetValidator(new EditRulesValidator()),
                    new UpdateValueStrategy(UpdateValueStrategy.POLICY_ON_REQUEST));
        }
    }

    @Override
    protected void unbindUIControl() {
        super.unbindUIControl();
        if (dbc != null) {
            dbc.dispose();
            dbc = null;
        }
    }

    @Override
    protected final IObservableValue getRidgetObservable() {
        return BeansObservables.observeValue(this, PROPERTY_DATE_INTERNAL);
    }

    @Override
    public DateTime getUIControl() {
        return (DateTime) super.getUIControl();
    }

    @Override
    public void bindToModel(final IObservableValue observableValue) {
        unbindUIControl();

        Assert.isNotNull(observableValue);
        super.bindToModel(observableValue);

        bindUIControl();
    }

    @Override
    public void bindToModel(final Object valueHolder, final String valuePropertyName) {
        if (AbstractSWTRidget.isBean(valueHolder.getClass())) {
            bindToModel(BeansObservables.observeValue(valueHolder, valuePropertyName));
        } else {
            bindToModel(PojoObservables.observeValue(valueHolder, valuePropertyName));
        }
    }

    public Date getDate() {
        return date;
    }

    /**
     * This method is not API. Do not use in client code.
     * 
     * @noreference This method is not intended to be referenced by clients.
     */
    public final Date getDateInternal() {
        return getDate();
    }

    public String getText() {
        final Date date = getDate();
        return date != null ? SimpleDateFormat.getInstance().format(date) : ""; //$NON-NLS-1$
    }

    public boolean isDirectWriting() {
        return true;
    }

    @Override
    public boolean isDisableMandatoryMarker() {
        return true;
    }

    @Override
    public boolean isEnabled() {
        return super.isEnabled() && !isOutputOnly();
    }

    public boolean revalidate() {
        final Date date = getDate();
        final IStatus onUpdate = checkOnUpdateRules(date, new ValidationCallback(false));
        if (onUpdate.isOK()) {
            getValueBindingSupport().updateFromTarget();
        }
        return !isErrorMarked();
    }

    /**
     * {@inheritDoc}
     * <p>
     * Implementation note: since the underlying DateTime widget cannot be
     * empty, a {@code null} date value will cause the widget to show the
     * 'empty' date, but getDate() will correctly return null.
     * <p>
     * Invoking this method will copy the given date into the ridget and the
     * widget regardless of the validation outcome. If the date does not pass
     * validation the error marker will be set and the date will <b>not</b> be
     * copied into the model. If validation passes the date will be copied into
     * the model as well.
     * <p>
     * Because of limitations of the underlying SWT {@link DateTime} widget, the
     * timestamp will be formatted according to the date/time format of the
     * operating system. See <a href="http://bugs.eclipse.org/248075">Bug
     * #248075</a>.
     */
    public void setDate(final Date date) {
        if (isChanged(this.date, date)) {
            final Object oldDate = this.date;
            // date is mutable, store / send out copies to be safe
            this.date = date == null ? null : new Date(date.getTime());
            final Date newDate = date == null ? null : new Date(date.getTime());
            firePropertyChange(PROPERTY_DATE_INTERNAL, oldDate, newDate);
            firePropertyChange(IDateTimeRidget.PROPERTY_DATE, oldDate, newDate);
            if (controlBinding != null) {
                controlBinding.updateModelToTarget(); // update widget
            }
            final IStatus status = checkAllRules(date, new ValidationCallback(false));
            if (status.isOK()) {
                getValueBindingSupport().updateFromTarget();
            }
        }
    }

    /**
     * This method is not API. Do not use in client code.
     * 
     * @noreference This method is not intended to be referenced by clients.
     */
    public final void setDateInternal(final Date date) {
        setDate(date);
    }

    /** Not supported. */
    public void setDirectWriting(final boolean directWriting) {
        throw new UnsupportedOperationException();
    }

    /** Not supported. */
    public void setInputToUIControlConverter(final IConverter converter) {
        throw new UnsupportedOperationException();
    }

    /** Not supported. */
    public void setText(final String text) {
        throw new UnsupportedOperationException();
    }

    @Override
    public void updateFromModel() {
        super.updateFromModel();
        if (controlBinding != null) {
            controlBinding.updateModelToTarget(); // updateWidget
        }
        checkAllRules(getDate(), new ValidationCallback(false));
    }

    // helping methods
    //////////////////

    /**
     * Return {@code date} if non-null, otherwise return the 'empty' date value.
     * 
     * @return {@code date} or new Date instance
     */
    private Date getNonNullDate(final Date date) {
        return date != null ? date : new Date(0);
    }

    private boolean isChanged(final Date date1, final Date date2) {
        if (date1 == date2) {
            return false;
        }
        return date1 != null ? !date1.equals(date2) : !date2.equals(date1);
    }

    private boolean isTimeControl(final DateTime control) {
        return (control.getStyle() & SWT.TIME) != 0;
    }

    // helping classes
    //////////////////

    /**
     * DateAndTimeObservable that handles doSetValue(null) gracefully.
     */
    private final class DateAndTimeObservableWithNullConversion extends DateAndTimeObservableValue {
        public DateAndTimeObservableWithNullConversion(final IObservableValue dateObservable,
                final IObservableValue timeObservable) {
            super(dateObservable, timeObservable);
        }

        @Override
        protected void doSetValue(final Object value) {
            super.doSetValue(getNonNullDate((Date) value));
        }
    }

    /**
     * Validator that delegates to the 'on edit' validators for this ridget.
     */
    private final class EditRulesValidator implements IValidator {
        public IStatus validate(final Object value) {
            return checkOnEditRules(value, new ValidationCallback(true));
        }
    }

}