All Downloads are FREE. Search and download functionalities are using the official Maven repository.

cn.jhc.um.vaadin.js.UMEditorField Maven / Gradle / Ivy

package cn.jhc.um.vaadin.js;

import java.lang.reflect.Method;
import java.util.Collection;

import org.json.JSONArray;
import org.json.JSONException;

import com.vaadin.annotations.JavaScript;
import com.vaadin.data.Buffered;
import com.vaadin.data.Property;
import com.vaadin.data.Validatable;
import com.vaadin.data.Validator;
import com.vaadin.data.Buffered.SourceException;
import com.vaadin.data.Validator.InvalidValueException;
import com.vaadin.shared.util.SharedUtil;
import com.vaadin.ui.AbstractField;
import com.vaadin.ui.AbstractJavaScriptComponent;
import com.vaadin.ui.Field;
import com.vaadin.ui.JavaScriptFunction;

/**
 * UMEditor component in server side, some code is copyed from
 * {@link com.vaadin.ui.AbstractField}.
 * 
 * @author luyanfei
 * 
 */
@JavaScript({ "http://libs.baidu.com/jquery/1.10.2/jquery.min.js",
		"umeditor.config.js", "umeditor.js", "umeditor-connector.js" })
@SuppressWarnings("serial")
public class UMEditorField extends AbstractJavaScriptComponent implements
		Field {

	/**
	 * The error message for the exception that is thrown when the field is
	 * required but empty.
	 */
	private String requiredError = "";
	/**
	 * Connected data-source.
	 */
	private Property dataSource = null;
	/**
	 * True if field is in buffered mode, false otherwise
	 */
	private boolean buffered;
	/**
	 * Current source exception.
	 */
	private Buffered.SourceException currentBufferedSourceException = null;

	private boolean isListeningToPropertyEvents = false;
	private boolean valueWasModifiedByDataSourceDuringCommit;
	/**
	 * Flag to indicate that the field is currently committing its value to the
	 * datasource.
	 */
	private boolean committingValueToDataSource = false;
	
    /* Value change events */

    private static final Method VALUE_CHANGE_METHOD;

    static {
        try {
            VALUE_CHANGE_METHOD = Property.ValueChangeListener.class
                    .getDeclaredMethod("valueChange",
                            new Class[] { Property.ValueChangeEvent.class });
        } catch (final java.lang.NoSuchMethodException e) {
            // This should never happen
            throw new java.lang.RuntimeException(
                    "Internal error finding methods in AbstractField");
        }
    }

	public UMEditorField() {
		addFunction("onValueChange", new JavaScriptFunction() {

			@Override
			public void call(JSONArray arguments) throws JSONException {
				setValue(arguments.getString(0));
			}
		});
	}

	@Override
	protected UMEditorState getState() {
		return (UMEditorState) super.getState();
	}

	@Override
	protected UMEditorState getState(boolean markAsDirty) {
		return (UMEditorState) super.getState(markAsDirty);
	}

	public void setValue(String newValue) {
		setValue(newValue, false);
	}

	protected void setValue(String newValue, boolean repaintIsNotNeeded) {

		getState().value = newValue;
		setModified(dataSource != null);

		valueWasModifiedByDataSourceDuringCommit = false;
		// In not buffering, try to commit
		if (!isBuffered() && dataSource != null) {
			try {

				// Commits the value to datasource
				committingValueToDataSource = true;
				dataSource.setValue(newValue);

				// The buffer is now unmodified
				setModified(false);

			} catch (final Throwable e) {

				// Sets the buffering state
				currentBufferedSourceException = new Buffered.SourceException(
						this, e);
				markAsDirty();

				// Throws the source exception
				throw currentBufferedSourceException;
			} finally {
				committingValueToDataSource = false;
			}
		}

		// If successful, remove set the buffering state to be ok
		if (getCurrentBufferedSourceException() != null) {
			setCurrentBufferedSourceException(null);
		}

		if (valueWasModifiedByDataSourceDuringCommit) {
			/*
			 * Value was modified by datasource. Force repaint even if repaint
			 * was not requested.
			 */
			valueWasModifiedByDataSourceDuringCommit = repaintIsNotNeeded = false;
		}
		// Fires the value change
		fireValueChange(repaintIsNotNeeded);
	}

	public String getValue() {
		// Give the value from abstract buffers if the field if possible
		if (dataSource == null || isBuffered() || isModified()) {
			return getState().value;
		}
		return dataSource.getValue();
	}

	@Override
	public void focus() {
		super.focus();
	}

	@Override
	public boolean isInvalidCommitted() {
		return false;
	}

	@Override
	public void setInvalidCommitted(boolean isCommitted) {
	}

	@Override
	public void commit() throws SourceException, InvalidValueException {
		if (dataSource != null) {
			try {

				// Commits the value to datasource.
				valueWasModifiedByDataSourceDuringCommit = false;
				committingValueToDataSource = true;
				dataSource.setValue(getValue());
			} catch (final Throwable e) {

				// Sets the buffering state.
				SourceException sourceException = new Buffered.SourceException(
						this, e);
				setCurrentBufferedSourceException(sourceException);

				// Throws the source exception.
				throw sourceException;
			} finally {
				committingValueToDataSource = false;
			}

		}

		// The abstract field is not modified anymore
		if (isModified()) {
			setModified(false);
		}

		// If successful, remove set the buffering state to be ok
		if (getCurrentBufferedSourceException() != null) {
			setCurrentBufferedSourceException(null);
		}

		if (valueWasModifiedByDataSourceDuringCommit) {
			valueWasModifiedByDataSourceDuringCommit = false;
			fireValueChange(false);
		}
	}

	@Override
	public void discard() throws SourceException {
		updateValueFromDataSource();
	}

	/**
	 * Copyed from AbstractField. Sets the buffered mode of this Field.
	 * 

* When the field is in buffered mode, changes will not be committed to the * property data source until {@link #commit()} is called. *

*

* Setting buffered mode from true to false will commit any pending changes. *

*

* *

* * @since 7.0.0 * @param buffered * true if buffered mode should be turned on, false otherwise */ @Override public void setBuffered(boolean buffered) { if (this.buffered == buffered) { return; } this.buffered = buffered; if (!buffered) { commit(); } } @Override public boolean isBuffered() { return buffered; } @Override public boolean isModified() { return getState(false).modified; } private void setModified(boolean modified) { getState().modified = modified; } @Override public void addValidator(Validator validator) { } @Override public void removeValidator(Validator validator) { } @Override public void removeAllValidators() { } @Override public Collection getValidators() { return null; } @Override public boolean isValid() { return true; } @Override public void validate() throws InvalidValueException { } @Override public boolean isInvalidAllowed() { return false; } @Override public void setInvalidAllowed(boolean invalidValueAllowed) throws UnsupportedOperationException { } @Override public Class getType() { return String.class; } @Override public void addValueChangeListener( com.vaadin.data.Property.ValueChangeListener listener) { addListener(AbstractField.ValueChangeEvent.class, listener, VALUE_CHANGE_METHOD); } @Override public void addListener( com.vaadin.data.Property.ValueChangeListener listener) { addValueChangeListener(listener); } @Override public void removeValueChangeListener( com.vaadin.data.Property.ValueChangeListener listener) { removeListener(AbstractField.ValueChangeEvent.class, listener, VALUE_CHANGE_METHOD); } @Override public void removeListener( com.vaadin.data.Property.ValueChangeListener listener) { removeValueChangeListener(listener); } @Override public void valueChange(com.vaadin.data.Property.ValueChangeEvent event) { if (!isBuffered()) { if (committingValueToDataSource) { boolean propertyNotifiesOfTheBufferedValue = SharedUtil.equals( event.getProperty().getValue(), getValue()); if (!propertyNotifiesOfTheBufferedValue) { /* * Property (or chained property like PropertyFormatter) now * reports different value than the one the field has just * committed to it. In this case we respect the property * value. * * Still, we don't fire value change yet, but instead * postpone it until "commit" is done. See setValue(Object, * boolean) and commit(). */ readValueFromProperty(event); valueWasModifiedByDataSourceDuringCommit = true; } } else if (!isModified()) { readValueFromProperty(event); fireValueChange(false); } } } private void readValueFromProperty( com.vaadin.data.Property.ValueChangeEvent event) { setValue((String) event.getProperty().getValue()); } @SuppressWarnings("unchecked") @Override public void setPropertyDataSource(Property newDataSource) { final String oldValue = getValue(); removePropertyListeners(); dataSource = newDataSource; if (dataSource != null) { setValue(dataSource.getValue()); setModified(false); if (getCurrentBufferedSourceException() != null) { setCurrentBufferedSourceException(null); } } addPropertyListeners(); // Copy the validators from the data source if (dataSource instanceof Validatable) { final Collection validators = ((Validatable) dataSource) .getValidators(); if (validators != null) { for (Validator validator : validators) { addValidator(validator); } } } // Fires value change if the value has changed String value = getValue(); if ((value != oldValue) && ((value != null && !value.equals(oldValue)) || value == null)) { fireValueChange(false); } } @Override public Property getPropertyDataSource() { return dataSource; } /** * Emits the value change event. The value contained in the field is * validated before the event is created. */ protected void fireValueChange(boolean repaintIsNotNeeded) { fireEvent(new Field.ValueChangeEvent(this)); if (!repaintIsNotNeeded) { markAsDirty(); } } @Override public int getTabIndex() { return 0; } @Override public void setTabIndex(int tabIndex) { } @Override public boolean isRequired() { return getState().required; } @Override public void setRequired(boolean required) { getState().required = required; } @Override public void setRequiredError(String requiredMessage) { requiredError = requiredMessage; markAsDirty(); } @Override public String getRequiredError() { return requiredError; } @Override public void attach() { super.attach(); if (!isListeningToPropertyEvents) { addPropertyListeners(); if (!isModified() && !isBuffered()) { // Update value from data source updateValueFromDataSource(); } } } private void updateValueFromDataSource() { if (dataSource != null) { String newValue = dataSource.getValue(); // If successful, remove set the buffering state to be ok if (getCurrentBufferedSourceException() != null) { setCurrentBufferedSourceException(null); } final boolean wasModified = isModified(); setModified(false); // If the new value differs from the previous one if (!SharedUtil.equals(newValue, getValue())) { setValue(newValue); fireValueChange(false); } else if (wasModified) { // If the value did not change, but the modification status did markAsDirty(); } } } public void setCurrentBufferedSourceException( Buffered.SourceException sourceException) { this.currentBufferedSourceException = sourceException; markAsDirty(); } public Buffered.SourceException getCurrentBufferedSourceException() { return currentBufferedSourceException; } @Override public void detach() { super.detach(); removePropertyListeners(); } /** * Registers this as an event listener for events sent by the data source * (if any). Does nothing if * isListeningToPropertyEvents == true. */ private void addPropertyListeners() { if (!isListeningToPropertyEvents) { if (dataSource instanceof Property.ValueChangeNotifier) { ((Property.ValueChangeNotifier) dataSource) .addValueChangeListener(this); } isListeningToPropertyEvents = true; } } /** * Stops listening to events sent by the data source (if any). Does nothing * if isListeningToPropertyEvents == false. */ private void removePropertyListeners() { if (isListeningToPropertyEvents) { if (dataSource instanceof Property.ValueChangeNotifier) { ((Property.ValueChangeNotifier) dataSource) .removeValueChangeListener(this); } isListeningToPropertyEvents = false; } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy