org.vaadin.viritin.fields.MTextField.java Source code

Java tutorial

Introduction

Here is the source code for org.vaadin.viritin.fields.MTextField.java

Source

/*
 * Copyright 2014 mattitahvonenitmill.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.vaadin.viritin.fields;

import com.vaadin.data.Property;
import com.vaadin.data.Validator;
import com.vaadin.data.util.converter.Converter;
import com.vaadin.data.util.converter.ConverterUtil;
import com.vaadin.event.FieldEvents;
import com.vaadin.event.FieldEvents.TextChangeEvent;
import com.vaadin.server.AbstractErrorMessage;
import com.vaadin.server.CompositeErrorMessage;
import com.vaadin.server.ErrorMessage;
import com.vaadin.server.Resource;
import com.vaadin.ui.TextField;
import org.vaadin.viritin.util.HtmlElementPropertySetter;

import java.util.EventObject;

/**
 * A an extension to basic Vaadin TextField. Uses the only sane default for
 * "nullRepresentation" (""), adds support for "eager validation" (~ validate
 * while typing) and adds some fluent APIs.
 */
public class MTextField extends TextField implements EagerValidateable {

    private boolean eagerValidation = false;
    private boolean eagerValidationStatus;
    private String lastKnownTextChangeValue;
    private Validator.InvalidValueException eagerValidationError;
    private AutoComplete autocomplete;
    private AutoCapitalize autocapitalize;
    private AutoCorrect autocorrect;
    private Boolean spellcheck;

    public MTextField() {
        configureMaddonStuff();
    }

    private void configureMaddonStuff() {
        setNullRepresentation("");
    }

    public MTextField(String caption) {
        super(caption);
        configureMaddonStuff();
    }

    public MTextField(Property dataSource) {
        super(dataSource);
        configureMaddonStuff();
    }

    public MTextField(String caption, Property dataSource) {
        super(caption, dataSource);
        configureMaddonStuff();
    }

    public MTextField(String caption, String value) {
        super(caption, value);
    }

    public MTextField withCaption(String caption) {
        setCaption(caption);
        return this;
    }

    @Override
    protected void setValue(String newFieldValue, boolean repaintIsNotNeeded)
            throws ReadOnlyException, Converter.ConversionException, Validator.InvalidValueException {
        lastKnownTextChangeValue = null;
        eagerValidationError = null;
        super.setValue(newFieldValue, repaintIsNotNeeded);
    }

    @Override
    public boolean isEagerValidation() {
        return eagerValidation;
    }

    @Override
    public void setEagerValidation(boolean eagerValidation) {
        this.eagerValidation = eagerValidation;
    }

    @Override
    protected void fireEvent(EventObject event) {
        if (isEagerValidation() && event instanceof TextChangeEvent) {
            lastKnownTextChangeValue = ((TextChangeEvent) event).getText();
            doEagerValidation();
        }
        super.fireEvent(event);
    }

    /**
     *
     * @return the value of the field or if a text change event have sent a
     * value to the server since last value changes, then that.
     */
    public String getLastKnownTextContent() {
        return lastKnownTextChangeValue;
    }

    public MTextField withConversionError(String message) {
        setConversionError(message);
        return this;
    }

    public MTextField withConverter(Converter<String, ?> converter) {
        setConverter(converter);
        return this;
    }

    public MTextField withFullWidth() {
        setWidth("100%");
        return this;
    }

    public MTextField withValue(String value) {
        setValue(value);
        return this;
    }

    public MTextField withInputPrompt(String inputPrompt) {
        setInputPrompt(inputPrompt);
        return this;
    }

    public MTextField withReadOnly(boolean readOnly) {
        setReadOnly(readOnly);
        return this;
    }

    public MTextField withValidator(Validator validator) {
        setImmediate(true);
        addValidator(validator);
        return this;
    }

    public MTextField withWidth(float width, Unit unit) {
        setWidth(width, unit);
        return this;
    }

    public MTextField withWidth(String width) {
        setWidth(width);
        return this;
    }

    public MTextField withNullRepresentation(String nullRepresentation) {
        setNullRepresentation(nullRepresentation);
        return this;
    }

    public MTextField withStyleName(String... styleNames) {
        for (String styleName : styleNames) {
            addStyleName(styleName);
        }
        return this;
    }

    public MTextField withIcon(Resource icon) {
        setIcon(icon);
        return this;
    }

    public MTextField withRequired(boolean required) {
        setRequired(required);
        return this;
    }

    public MTextField withRequiredError(String requiredError) {
        setRequiredError(requiredError);
        return this;
    }

    public MTextField withVisible(boolean visible) {
        setVisible(visible);
        return this;
    }

    public MTextField withTextChangeListener(FieldEvents.TextChangeListener listener) {
        addTextChangeListener(listener);
        return this;
    }

    public MTextField withValueChangeListener(Property.ValueChangeListener listener) {
        addValueChangeListener(listener);
        return this;
    }

    public MTextField withBlurListener(FieldEvents.BlurListener listener) {
        addBlurListener(listener);
        return this;
    }

    public void setSpellcheck(Boolean spellcheck) {
        this.spellcheck = spellcheck;
    }

    public Boolean getSpellcheck() {
        return spellcheck;
    }

    public MTextField withSpellCheckOff() {
        setSpellcheck(false);
        return this;
    }

    public MTextField withId(String id) {
        setId(id);
        return this;
    }

    public enum AutoComplete {
        on, off
    }

    public enum AutoCorrect {
        on, off
    }

    public enum AutoCapitalize {
        on, off
    }

    public MTextField withAutocompleteOff() {
        return setAutocomplete(AutoComplete.off);
    }

    public MTextField setAutocomplete(AutoComplete autocomplete) {
        this.autocomplete = autocomplete;
        return this;
    }

    public AutoComplete getAutocomplete() {
        return autocomplete;
    }

    public MTextField withAutoCapitalizeOff() {
        return setAutoCapitalize(AutoCapitalize.off);
    }

    public MTextField setAutoCapitalize(AutoCapitalize autoCapitalize) {
        this.autocapitalize = autoCapitalize;
        return this;
    }

    public AutoCapitalize getAutoCapitalize() {
        return autocapitalize;
    }

    public MTextField withAutoCorrectOff() {
        return setAutoCorrect(AutoCorrect.off);
    }

    public MTextField setAutoCorrect(AutoCorrect autoCorrect) {
        this.autocorrect = autoCorrect;
        return this;
    }

    public AutoCorrect getAutoCorrect() {
        return autocorrect;
    }

    private HtmlElementPropertySetter heps;

    protected HtmlElementPropertySetter getHtmlElementPropertySetter() {
        if (heps == null) {
            heps = new HtmlElementPropertySetter(this);
        }
        return heps;
    }

    @Override
    public void beforeClientResponse(boolean initial) {
        super.beforeClientResponse(initial);
        if (initial) {
            if (spellcheck != null) {
                getHtmlElementPropertySetter().setProperty("spellcheck", spellcheck);
            }
            if (autocomplete != null) {
                // sending here to keep value if toggling visibility
                getHtmlElementPropertySetter().setProperty("autocomplete", autocomplete.toString());
            }
            if (autocorrect != null) {
                // sending here to keep value if toggling visibility
                getHtmlElementPropertySetter().setProperty("autocorrect", autocorrect.toString());
            }
            if (autocapitalize != null) {
                // sending here to keep value if toggling visibility
                getHtmlElementPropertySetter().setProperty("autocapitalize", autocapitalize.toString());
            }
        }
    }

    @Override
    public ErrorMessage getErrorMessage() {

        Validator.InvalidValueException validationError = getValidationError();

        final ErrorMessage superError = getComponentError();

        if (superError == null && validationError == null && getCurrentBufferedSourceException() == null) {
            return null;
        }
        // Throw combination of the error types
        return new CompositeErrorMessage(
                new ErrorMessage[] { superError, AbstractErrorMessage.getErrorMessageForException(validationError),
                        AbstractErrorMessage.getErrorMessageForException(getCurrentBufferedSourceException()) });
    }

    protected Validator.InvalidValueException getValidationError() {
        if (isEagerValidation() && lastKnownTextChangeValue != null) {
            return eagerValidationError;
        }
        /*
         * Check validation errors only if automatic validation is enabled.
         * Empty, required fields will generate a validation error containing
         * the requiredError string. For these fields the exclamation mark will
         * be hidden but the error must still be sent to the client.
         */
        Validator.InvalidValueException validationError = null;
        if (isValidationVisible()) {
            try {
                validate();
            } catch (Validator.InvalidValueException e) {
                if (!e.isInvisible()) {
                    validationError = e;
                }
            }
        }
        return validationError;
    }

    protected void doEagerValidation() {
        final boolean wasvalid = eagerValidationStatus;
        eagerValidationStatus = true;
        eagerValidationError = null;
        try {
            if (isRequired() && getLastKnownTextContent().isEmpty()) {
                throw new Validator.EmptyValueException(getRequiredError());
            }
            validate(getLastKnownTextContent());
            if (!wasvalid) {
                markAsDirty();
            }
            // Also eagerly pass content to backing bean to make top level
            // validation eager, but do not listen the value back in value change
            // event
            if (getPropertyDataSource() != null) {
                skipValueChangeEvent = true;
                Object convertedValue = ConverterUtil.convertToModel(getLastKnownTextContent(),
                        getPropertyDataSource().getType(), getConverter(), getLocale());
                getPropertyDataSource().setValue(convertedValue);
                skipValueChangeEvent = false;
            }
        } catch (Validator.InvalidValueException e) {
            eagerValidationError = e;
            eagerValidationStatus = false;
            markAsDirty();
        }
    }

    private boolean skipValueChangeEvent = false;

    @Override
    public void valueChange(Property.ValueChangeEvent event) {
        if (!skipValueChangeEvent) {
            super.valueChange(event);
        } else {
            skipValueChangeEvent = false;
        }
    }

    @Override
    public boolean isValid() {
        if (isEagerValidation() && lastKnownTextChangeValue != null) {
            return eagerValidationStatus;
        } else {
            return super.isValid();
        }
    }

    @Override
    public void validate() throws Validator.InvalidValueException {
        if (isEagerValidation() && lastKnownTextChangeValue != null) {
            // This is most likely not executed, unless someone, for some weird
            // reason calls this explicitly
            if (isRequired() && getLastKnownTextContent().isEmpty()) {
                throw new Validator.EmptyValueException(getRequiredError());
            }
            validate(getLastKnownTextContent());
        } else {
            super.validate();
        }
    }

}