/* * Copyright 2000-2014 Vaadin Ltd. * * 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 com.vaadin.ui; import java.util.Collection; import java.util.Map; import org.jsoup.nodes.Attributes; import org.jsoup.nodes.Element; import com.vaadin.event.FieldEvents.BlurEvent; import com.vaadin.event.FieldEvents.BlurListener; import com.vaadin.event.FieldEvents.BlurNotifier; import com.vaadin.event.FieldEvents.FocusEvent; import com.vaadin.event.FieldEvents.FocusListener; import com.vaadin.event.FieldEvents.FocusNotifier; import com.vaadin.event.FieldEvents.TextChangeEvent; import com.vaadin.event.FieldEvents.TextChangeListener; import com.vaadin.event.FieldEvents.TextChangeNotifier; import com.vaadin.server.PaintException; import com.vaadin.server.PaintTarget; import com.vaadin.shared.ui.textfield.AbstractTextFieldState; import com.vaadin.shared.ui.textfield.TextFieldConstants; import com.vaadin.ui.declarative.DesignAttributeHandler; import com.vaadin.ui.declarative.DesignContext; public abstract class AbstractTextField extends AbstractField implements BlurNotifier, FocusNotifier, TextChangeNotifier, LegacyComponent { /** * Null representation. */ private String nullRepresentation = "null"; /** * Is setting to null from non-null value allowed by setting with null * representation . */ private boolean nullSettingAllowed = false; /** * The text content when the last messages to the server was sent. Cleared * when value is changed. */ private String lastKnownTextContent; /** * The position of the cursor when the last message to the server was sent. */ private int lastKnownCursorPosition; /** * Flag indicating that a text change event is pending to be triggered. * Cleared by {@link #setInternalValue(Object)} and when the event is fired. */ private boolean textChangeEventPending; private boolean isFiringTextChangeEvent = false; private TextChangeEventMode textChangeEventMode = TextChangeEventMode.LAZY; private final int DEFAULT_TEXTCHANGE_TIMEOUT = 400; private int textChangeEventTimeout = DEFAULT_TEXTCHANGE_TIMEOUT; /** * Temporarily holds the new selection position. Cleared on paint. */ private int selectionPosition = -1; /** * Temporarily holds the new selection length. */ private int selectionLength; /** * Flag used to determine whether we are currently handling a state change * triggered by a user. Used to properly fire text change event before value * change event triggered by the client side. */ private boolean changingVariables; protected AbstractTextField() { super(); } @Override protected AbstractTextFieldState getState() { return (AbstractTextFieldState) super.getState(); } @Override protected AbstractTextFieldState getState(boolean markAsDirty) { return (AbstractTextFieldState) super.getState(markAsDirty); } @Override public void beforeClientResponse(boolean initial) { super.beforeClientResponse(initial); String value = getValue(); if (value == null) { value = getNullRepresentation(); } getState().text = value; } @Override public void paintContent(PaintTarget target) throws PaintException { if (selectionPosition != -1) { target.addAttribute("selpos", selectionPosition); target.addAttribute("sellen", selectionLength); selectionPosition = -1; } if (hasListeners(TextChangeEvent.class)) { target.addAttribute(TextFieldConstants.ATTR_TEXTCHANGE_EVENTMODE, getTextChangeEventMode().toString()); target.addAttribute(TextFieldConstants.ATTR_TEXTCHANGE_TIMEOUT, getTextChangeTimeout()); if (lastKnownTextContent != null) { /* * The field has be repainted for some reason (e.g. caption, * size, stylename), but the value has not been changed since * the last text change event. Let the client side know about * the value the server side knows. Client side may then ignore * the actual value, depending on its state. */ target.addAttribute( TextFieldConstants.ATTR_NO_VALUE_CHANGE_BETWEEN_PAINTS, true); } } } @Override public void changeVariables(Object source, Map variables) { changingVariables = true; try { // Sets the height set by the user when resize the