package org.eclipse.nebula.widgets.formattedtext; import org.eclipse.core.databinding.observable.Diffs; import org.eclipse.core.databinding.observable.Realm; import org.eclipse.core.databinding.observable.value.AbstractObservableValue; import org.eclipse.jface.databinding.swt.ISWTObservable; import org.eclipse.jface.databinding.swt.SWTObservables; import org.eclipse.swt.SWT; import org.eclipse.swt.events.DisposeEvent; import org.eclipse.swt.events.DisposeListener; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Widget; public class FormattedTextObservableValue extends AbstractObservableValue implements ISWTObservable{ /** * {@link FormattedText} FormattedText that this is being observed. */ protected final FormattedText formattedText; /** * SWT event that on firing this observable will fire change events to its * listeners. */ private final int updateEventType; /** * Flag to track when the model is updating the widget. When * <code>true</code> the handlers for the SWT events should not process * the event as this would cause an infinite loop. */ private boolean updating = false; /** * Previous value. */ private Object oldValue; private Listener updateListener = new Listener() { public void handleEvent(Event event) { if ( ! updating ) { Object newValue = formattedText.getValue(); if ( (newValue == null && oldValue != null) || (newValue != null && ! newValue.equals(oldValue)) ) { fireValueChange(Diffs.createValueDiff(oldValue, newValue)); oldValue = newValue; } } } }; /** * Valid types for the {@link #updateEventType}. */ private static final int[] validUpdateEventTypes = new int[] { SWT.Modify, SWT.FocusOut, SWT.None }; private DisposeListener disposeListener = new DisposeListener() { public void widgetDisposed(DisposeEvent e) { FormattedTextObservableValue.this.dispose(); } }; public FormattedTextObservableValue(final FormattedText formattedText) { this(SWTObservables.getRealm(formattedText.getControl().getDisplay()), formattedText, SWT.Modify); } public FormattedTextObservableValue(final FormattedText formattedText, int updateEventType) { this(SWTObservables.getRealm(formattedText.getControl().getDisplay()), formattedText, updateEventType); } public FormattedTextObservableValue(final Realm realm, final FormattedText formattedText, int updateEventType) { super(realm); boolean eventValid = false; for (int i = 0; !eventValid && i < validUpdateEventTypes.length; i++) { eventValid = (updateEventType == validUpdateEventTypes[i]); } if ( ! eventValid ) { throw new IllegalArgumentException( "UpdateEventType [" + updateEventType + "] is not supported."); //$NON-NLS-1$//$NON-NLS-2$ } this.formattedText = formattedText; this.updateEventType = updateEventType; if ( updateEventType != SWT.None ) { formattedText.getControl().addListener(updateEventType, updateListener); } formattedText.getControl().addDisposeListener(disposeListener); } public void dispose() { if ( formattedText.getControl() != null && ! formattedText.getControl().isDisposed() ) { if ( updateEventType != SWT.None ) { formattedText.getControl().removeListener(updateEventType, updateListener); } } super.dispose(); } protected Object doGetValue() { return oldValue = formattedText.getValue(); } /** * Sets the bound {@link DateChooser} date chooser to the passed <code>value</code>. * * @param value new value, Date expected * @see org.eclipse.core.databinding.observable.value.AbstractObservableValue#doSetValue(java.lang.Object) * @throws ClassCastException if the value is anything other than a Date */ protected void doSetValue(final Object value) { try { updating = true; formattedText.setValue(value); oldValue = formattedText.getValue(); } finally { updating = false; } } public Object getValueType() { return formattedText.getValueType(); } public Widget getWidget() { return formattedText.getControl(); } }