aboutsummaryrefslogtreecommitdiffstats
path: root/server/src/main/java/com/vaadin/ui/AbstractTextField.java
diff options
context:
space:
mode:
authorAleksi Hietanen <aleksi@vaadin.com>2016-08-08 13:41:56 +0300
committerVaadin Code Review <review@vaadin.com>2016-08-17 07:31:03 +0000
commita5575a9252f4e502624079c65c7080e741846692 (patch)
tree739061425eef0a9ce3e1de714b5590300b1eb4fd /server/src/main/java/com/vaadin/ui/AbstractTextField.java
parent93d7a0d962d100ee807089a76d57d0621a238108 (diff)
downloadvaadin-framework-a5575a9252f4e502624079c65c7080e741846692.tar.gz
vaadin-framework-a5575a9252f4e502624079c65c7080e741846692.zip
Update TextField to extend AbstractFieldNew (#51)
- Changes input prompt to be based on the placeholder attribute. - Unifies TextChangeEvents with ValueChangeEvents. - add*Listener methods now return Registration objects, remove*Listener methods removed. Change-Id: Ie92506ae9db205bb0010ae9126c608c62ad023ff
Diffstat (limited to 'server/src/main/java/com/vaadin/ui/AbstractTextField.java')
-rw-r--r--server/src/main/java/com/vaadin/ui/AbstractTextField.java802
1 files changed, 194 insertions, 608 deletions
diff --git a/server/src/main/java/com/vaadin/ui/AbstractTextField.java b/server/src/main/java/com/vaadin/ui/AbstractTextField.java
index ba53d546c2..a52ff79760 100644
--- a/server/src/main/java/com/vaadin/ui/AbstractTextField.java
+++ b/server/src/main/java/com/vaadin/ui/AbstractTextField.java
@@ -1,12 +1,12 @@
/*
* 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
@@ -17,323 +17,68 @@
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.legacy.ui.LegacyAbstractField;
-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.event.Registration;
+import com.vaadin.shared.ui.textfield.TextFieldServerRpc;
+import com.vaadin.shared.ui.textfield.TextFieldState;
+import com.vaadin.shared.ui.textfield.ValueChangeMode;
import com.vaadin.ui.declarative.DesignAttributeHandler;
import com.vaadin.ui.declarative.DesignContext;
-public abstract class AbstractTextField extends LegacyAbstractField<String>
- 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;
+/**
+ * Abstract base class for text input components.
+ *
+ * @author Vaadin Ltd.
+ * @since 8.0
+ */
+public abstract class AbstractTextField extends AbstractField<String> {
protected AbstractTextField() {
- super();
- }
-
- @Override
- protected AbstractTextFieldState getState() {
- return (AbstractTextFieldState) super.getState();
- }
+ registerRpc(new TextFieldServerRpc() {
- @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<String, Object> variables) {
- changingVariables = true;
-
- try {
-
- // Sets the height set by the user when resize the <textarea>.
- String newHeight = (String) variables.get("height");
- if (newHeight != null) {
- setHeight(newHeight);
- }
-
- // Sets the width set by the user when resize the <textarea>.
- String newWidth = (String) variables.get("width");
- if (newWidth != null) {
- setWidth(newWidth);
- }
-
- if (variables.containsKey(TextFieldConstants.VAR_CURSOR)) {
- Integer object = (Integer) variables
- .get(TextFieldConstants.VAR_CURSOR);
- lastKnownCursorPosition = object.intValue();
+ @Override
+ public void blur() {
+ fireEvent(new BlurEvent(AbstractTextField.this));
}
- if (variables.containsKey(TextFieldConstants.VAR_CUR_TEXT)) {
- /*
- * NOTE, we might want to develop this further so that on a
- * value change event the whole text content don't need to be
- * sent from the client to server. Just "commit" the value from
- * currentText to the value.
- */
- handleInputEventTextChange(variables);
+ @Override
+ public void focus() {
+ fireEvent(new FocusEvent(AbstractTextField.this));
}
- // Sets the text
- if (variables.containsKey("text") && !isReadOnly()) {
-
- // Only do the setting if the string representation of the value
- // has been updated
- String newValue = (String) variables.get("text");
-
- // server side check for max length
- if (getMaxLength() != -1
- && newValue.length() > getMaxLength()) {
- newValue = newValue.substring(0, getMaxLength());
- }
- final String oldValue = getValue();
- if (newValue != null
- && (oldValue == null || isNullSettingAllowed())
- && newValue.equals(getNullRepresentation())) {
- newValue = null;
- }
- if (newValue != oldValue
- && (newValue == null || !newValue.equals(oldValue))) {
- boolean wasModified = isModified();
- setValue(newValue, true);
-
- // If the modified status changes, or if we have a
- // formatter, repaint is needed after all.
- if (wasModified != isModified()) {
- markAsDirty();
- }
- }
+ @Override
+ public void setText(String text, int cursorPosition) {
+ getUI().getConnectorTracker()
+ .getDiffState(AbstractTextField.this).put("text", text);
+ getUI().getConnectorTracker()
+ .getDiffState(AbstractTextField.this)
+ .put("cursorPosition", cursorPosition);
+ getState(false).cursorPosition = cursorPosition;
+ setValue(text, true);
}
- firePendingTextChangeEvent();
-
- if (variables.containsKey(FocusEvent.EVENT_ID)) {
- fireEvent(new FocusEvent(this));
- }
- if (variables.containsKey(BlurEvent.EVENT_ID)) {
- fireEvent(new BlurEvent(this));
- }
- } finally {
- changingVariables = false;
-
- }
-
+ });
}
@Override
- public Class<String> getType() {
- return String.class;
- }
-
- /**
- * Gets the null-string representation.
- *
- * <p>
- * The null-valued strings are represented on the user interface by
- * replacing the null value with this string. If the null representation is
- * set null (not 'null' string), painting null value throws exception.
- * </p>
- *
- * <p>
- * The default value is string 'null'.
- * </p>
- *
- * @return the String Textual representation for null strings.
- * @see TextField#isNullSettingAllowed()
- */
- public String getNullRepresentation() {
- return nullRepresentation;
- }
-
- /**
- * Is setting nulls with null-string representation allowed.
- *
- * <p>
- * If this property is true, writing null-representation string to text
- * field always sets the field value to real null. If this property is
- * false, null setting is not made, but the null values are maintained.
- * Maintenance of null-values is made by only converting the textfield
- * contents to real null, if the text field matches the null-string
- * representation and the current value of the field is null.
- * </p>
- *
- * <p>
- * By default this setting is false
- * </p>
- *
- * @return boolean Should the null-string represenation be always converted
- * to null-values.
- * @see TextField#getNullRepresentation()
- */
- public boolean isNullSettingAllowed() {
- return nullSettingAllowed;
- }
-
- /**
- * Sets the null-string representation.
- *
- * <p>
- * The null-valued strings are represented on the user interface by
- * replacing the null value with this string. If the null representation is
- * set null (not 'null' string), painting null value throws exception.
- * </p>
- *
- * <p>
- * The default value is string 'null'
- * </p>
- *
- * @param nullRepresentation
- * Textual representation for null strings.
- * @see TextField#setNullSettingAllowed(boolean)
- */
- public void setNullRepresentation(String nullRepresentation) {
- this.nullRepresentation = nullRepresentation;
- markAsDirty();
- }
-
- /**
- * Sets the null conversion mode.
- *
- * <p>
- * If this property is true, writing null-representation string to text
- * field always sets the field value to real null. If this property is
- * false, null setting is not made, but the null values are maintained.
- * Maintenance of null-values is made by only converting the textfield
- * contents to real null, if the text field matches the null-string
- * representation and the current value of the field is null.
- * </p>
- *
- * <p>
- * By default this setting is false.
- * </p>
- *
- * @param nullSettingAllowed
- * Should the null-string representation always be converted to
- * null-values.
- * @see TextField#getNullRepresentation()
- */
- public void setNullSettingAllowed(boolean nullSettingAllowed) {
- this.nullSettingAllowed = nullSettingAllowed;
- markAsDirty();
- }
-
- @Override
- public boolean isEmpty() {
- return super.isEmpty() || getValue().length() == 0;
+ public void setValue(String value) {
+ if (value == null) {
+ setValue("", false);
+ } else {
+ setValue(value, false);
+ }
}
/**
* Returns the maximum number of characters in the field. Value -1 is
* considered unlimited. Terminal may however have some technical limits.
- *
+ *
* @return the maxLength
*/
public int getMaxLength() {
@@ -343,7 +88,7 @@ public abstract class AbstractTextField extends LegacyAbstractField<String>
/**
* Sets the maximum number of characters in the field. Value -1 is
* considered unlimited. Terminal may however have some technical limits.
- *
+ *
* @param maxLength
* the maxLength to set
*/
@@ -352,398 +97,230 @@ public abstract class AbstractTextField extends LegacyAbstractField<String>
}
/**
- * Gets the number of columns in the editor. If the number of columns is set
- * 0, the actual number of displayed columns is determined implicitly by the
- * adapter.
- *
- * @return the number of columns in the editor.
+ * Returns the current placeholder text.
+ *
+ * @see #setPlaceholder(String)
+ * @return the placeholder text
*/
- public int getColumns() {
- return getState(false).columns;
+ public String getPlaceholder() {
+ return getState(false).placeholder;
}
/**
- * Sets the number of columns in the editor. If the number of columns is set
- * 0, the actual number of displayed columns is determined implicitly by the
- * adapter.
- *
- * @param columns
- * the number of columns to set.
+ * Sets the placeholder text. The placeholder is text that is displayed when
+ * the field would otherwise be empty, to prompt the user for input.
+ *
+ * @param placeholder
+ * the placeholder text to set
*/
- public void setColumns(int columns) {
- if (columns < 0) {
- columns = 0;
- }
- getState().columns = columns;
+ public void setPlaceholder(String placeholder) {
+ getState().placeholder = placeholder;
}
- /**
- * Gets the current input prompt.
- *
- * @see #setInputPrompt(String)
- * @return the current input prompt, or null if not enabled
- */
- public String getInputPrompt() {
- return getState(false).inputPrompt;
+ @Override
+ public String getValue() {
+ return getState(false).text;
}
/**
- * Sets the input prompt - a textual prompt that is displayed when the field
- * would otherwise be empty, to prompt the user for input.
- *
- * @param inputPrompt
+ * Selects all text in the field.
*/
- public void setInputPrompt(String inputPrompt) {
- getState().inputPrompt = inputPrompt;
- }
-
- /* ** Text Change Events ** */
-
- private void firePendingTextChangeEvent() {
- if (textChangeEventPending && !isFiringTextChangeEvent) {
- isFiringTextChangeEvent = true;
- textChangeEventPending = false;
- try {
- fireEvent(new TextChangeEventImpl(this));
- } finally {
- isFiringTextChangeEvent = false;
- }
- }
- }
-
- @Override
- protected void setInternalValue(String newValue) {
- if (changingVariables && !textChangeEventPending) {
-
- /*
- * TODO check for possible (minor?) issue (not tested)
- *
- * -field with e.g. PropertyFormatter.
- *
- * -TextChangeListener and it changes value.
- *
- * -if formatter again changes the value, do we get an extra
- * simulated text change event ?
- */
-
- /*
- * Fire a "simulated" text change event before value change event if
- * change is coming from the client side.
- *
- * Iff there is both value change and textChangeEvent in same
- * variable burst, it is a text field in non immediate mode and the
- * text change event "flushed" queued value change event. In this
- * case textChangeEventPending flag is already on and text change
- * event will be fired after the value change event.
- */
- if (newValue == null && lastKnownTextContent != null
- && !lastKnownTextContent.equals(getNullRepresentation())) {
- // Value was changed from something to null representation
- lastKnownTextContent = getNullRepresentation();
- textChangeEventPending = true;
- } else if (newValue != null
- && !newValue.toString().equals(lastKnownTextContent)) {
- // Value was changed to something else than null representation
- lastKnownTextContent = newValue.toString();
- textChangeEventPending = true;
- }
- firePendingTextChangeEvent();
- }
-
- super.setInternalValue(newValue);
- }
-
- @Override
- public void setValue(String newValue) throws ReadOnlyException {
- super.setValue(newValue);
- /*
- * Make sure w reset lastKnownTextContent field on value change. The
- * clearing must happen here as well because TextChangeListener can
- * revert the original value. Client must respect the value in this
- * case. LegacyAbstractField optimizes value change if the existing
- * value is reset. Also we need to force repaint if the flag is on.
- */
- if (lastKnownTextContent != null) {
- lastKnownTextContent = null;
- markAsDirty();
- }
- }
-
- private void handleInputEventTextChange(Map<String, Object> variables) {
- /*
- * TODO we could vastly optimize the communication of values by using
- * some sort of diffs instead of always sending the whole text content.
- * Also on value change events we could use the mechanism.
- */
- String object = (String) variables.get(TextFieldConstants.VAR_CUR_TEXT);
- lastKnownTextContent = object;
- textChangeEventPending = true;
+ public void selectAll() {
+ setSelection(0, getValue().length());
}
/**
- * Sets the mode how the TextField triggers {@link TextChangeEvent}s.
- *
- * @param inputEventMode
- * the new mode
- *
- * @see TextChangeEventMode
+ * Sets the range of text to be selected.
+ *
+ * As a side effect the field will become focused.
+ *
+ * @param pos
+ * the position of the first character to be selected
+ * @param length
+ * the number of characters to be selected
*/
- public void setTextChangeEventMode(TextChangeEventMode inputEventMode) {
- textChangeEventMode = inputEventMode;
- markAsDirty();
+ public void setSelection(int start, int length) {
+ getState().selectionStart = start;
+ getState().selectionLength = length;
+ focus();
}
/**
- * @return the mode used to trigger {@link TextChangeEvent}s.
+ * Sets the cursor position in the field. As a side effect the field will
+ * become focused.
+ *
+ * @param pos
+ * the position for the cursor
*/
- public TextChangeEventMode getTextChangeEventMode() {
- return textChangeEventMode;
+ public void setCursorPosition(int pos) {
+ getState().cursorPosition = pos;
+ focus();
}
/**
- * Different modes how the TextField can trigger {@link TextChangeEvent}s.
+ * Returns the last known cursor position of the field.
+ *
*/
- public enum TextChangeEventMode {
-
- /**
- * An event is triggered on each text content change, most commonly key
- * press events.
- */
- EAGER,
- /**
- * Each text change event in the UI causes the event to be communicated
- * to the application after a timeout. The length of the timeout can be
- * controlled with {@link TextField#setTextChangeTimeout(int)}. Only the
- * last input event is reported to the server side if several text
- * change events happen during the timeout.
- * <p>
- * In case of a {@link ValueChangeEvent} the schedule is not kept
- * strictly. Before a {@link ValueChangeEvent} a {@link TextChangeEvent}
- * is triggered if the text content has changed since the previous
- * TextChangeEvent regardless of the schedule.
- */
- TIMEOUT,
- /**
- * An event is triggered when there is a pause of text modifications.
- * The length of the pause can be modified with
- * {@link TextField#setTextChangeTimeout(int)}. Like with the
- * {@link #TIMEOUT} mode, an event is forced before
- * {@link ValueChangeEvent}s, even if the user did not keep a pause
- * while entering the text.
- * <p>
- * This is the default mode.
- */
- LAZY
- }
-
- @Override
- public void addTextChangeListener(TextChangeListener listener) {
- addListener(TextChangeListener.EVENT_ID, TextChangeEvent.class,
- listener, TextChangeListener.EVENT_METHOD);
+ public int getCursorPosition() {
+ return getState(false).cursorPosition;
}
- @Override
- public void removeTextChangeListener(TextChangeListener listener) {
- removeListener(TextChangeListener.EVENT_ID, TextChangeEvent.class,
+ /**
+ * Adds a {@link FocusListener} to this component, which gets fired when
+ * this component receives keyboard focus.
+ *
+ * @param listener
+ * the focus listener
+ * @return a registration for the listener
+ *
+ * @see Registration
+ */
+ public Registration addFocusListener(FocusListener listener) {
+ addListener(FocusEvent.EVENT_ID, FocusEvent.class, listener,
+ FocusListener.focusMethod);
+ return () -> removeListener(FocusEvent.EVENT_ID, FocusEvent.class,
listener);
}
/**
- * The text change timeout modifies how often text change events are
- * communicated to the application when {@link #getTextChangeEventMode()} is
- * {@link TextChangeEventMode#LAZY} or {@link TextChangeEventMode#TIMEOUT}.
- *
- *
- * @see #getTextChangeEventMode()
- *
- * @param timeout
- * the timeout in milliseconds
+ * Adds a {@link BlurListener} to this component, which gets fired when this
+ * component loses keyboard focus.
+ *
+ * @param listener
+ * the blur listener
+ * @return a registration for the listener
+ *
+ * @see Registration
*/
- public void setTextChangeTimeout(int timeout) {
- textChangeEventTimeout = timeout;
- markAsDirty();
+ public Registration addBlurListener(BlurListener listener) {
+ addListener(BlurEvent.EVENT_ID, BlurEvent.class, listener,
+ BlurListener.blurMethod);
+ return () -> removeListener(BlurEvent.EVENT_ID, BlurEvent.class,
+ listener);
}
/**
- * Gets the timeout used to fire {@link TextChangeEvent}s when the
- * {@link #getTextChangeEventMode()} is {@link TextChangeEventMode#LAZY} or
- * {@link TextChangeEventMode#TIMEOUT}.
- *
- * @return the timeout value in milliseconds
+ * Gets the number of columns in the editor. If the number of columns is set
+ * 0, the actual number of displayed columns is determined implicitly by the
+ * adapter.
+ *
+ * @return the number of columns in the editor.
*/
- public int getTextChangeTimeout() {
- return textChangeEventTimeout;
- }
-
- public static class TextChangeEventImpl extends TextChangeEvent {
- private String curText;
- private int cursorPosition;
-
- private TextChangeEventImpl(final AbstractTextField tf) {
- super(tf);
- curText = tf.getCurrentTextContent();
- cursorPosition = tf.getCursorPosition();
- }
-
- @Override
- public AbstractTextField getComponent() {
- return (AbstractTextField) super.getComponent();
- }
-
- @Override
- public String getText() {
- return curText;
- }
-
- @Override
- public int getCursorPosition() {
- return cursorPosition;
- }
-
+ public int getColumns() {
+ return getState(false).columns;
}
/**
- * Gets the current (or the last known) text content in the field.
- * <p>
- * Note the text returned by this method is not necessary the same that is
- * returned by the {@link #getValue()} method. The value is updated when the
- * terminal fires a value change event via e.g. blurring the field or by
- * pressing enter. The value returned by this method is updated also on
- * {@link TextChangeEvent}s. Due to this high dependency to the terminal
- * implementation this method is (at least at this point) not published.
- *
- * @return the text which is currently displayed in the field.
+ * Sets the number of columns in the editor. If the number of columns is set
+ * 0, the actual number of displayed columns is determined implicitly by the
+ * adapter.
+ *
+ * @param columns
+ * the number of columns to set.
*/
- private String getCurrentTextContent() {
- if (lastKnownTextContent != null) {
- return lastKnownTextContent;
- } else {
- Object text = getValue();
- if (text == null) {
- return getNullRepresentation();
- }
- return text.toString();
+ public void setColumns(int columns) {
+ if (columns < 0) {
+ columns = 0;
}
+ getState().columns = columns;
}
/**
- * Selects all text in the field.
+ * Sets the mode how the TextField triggers {@link ValueChange}s.
+ *
+ * @param mode
+ * the new mode
*
- * @since 6.4
+ * @see ValueChangeMode
*/
- public void selectAll() {
- String text = getValue() == null ? "" : getValue().toString();
- setSelectionRange(0, text.length());
+ public void setValueChangeMode(ValueChangeMode mode) {
+ getState().valueChangeMode = mode;
}
/**
- * Sets the range of text to be selected.
- *
- * As a side effect the field will become focused.
- *
- * @since 6.4
- *
- * @param pos
- * the position of the first character to be selected
- * @param length
- * the number of characters to be selected
+ * Returns the currently set {@link ValueChangeMode}.
+ *
+ * @return the mode used to trigger {@link ValueChange}s.
+ *
+ * @see ValueChangeMode
*/
- public void setSelectionRange(int pos, int length) {
- selectionPosition = pos;
- selectionLength = length;
- focus();
- markAsDirty();
+ public ValueChangeMode getValueChangeMode() {
+ return getState(false).valueChangeMode;
}
/**
- * Sets the cursor position in the field. As a side effect the field will
- * become focused.
+ * Sets how often {@link ValueChange}s are triggered when the
+ * {@link ValueChangeMode} is set to either {@link ValueChangeMode#LAZY} or
+ * {@link ValueChangeMode#TIMEOUT}.
*
- * @since 6.4
+ * @param timeout
+ * timeout in milliseconds, must be greater or equal to 0
+ * @throws IllegalArgumentException
+ * if given timeout is smaller than 0
*
- * @param pos
- * the position for the cursor
+ * @see ValueChangeMode
*/
- public void setCursorPosition(int pos) {
- setSelectionRange(pos, 0);
- lastKnownCursorPosition = pos;
+ public void setValueChangeTimeout(int timeout) {
+ if (timeout < 0)
+ throw new IllegalArgumentException(
+ "Timeout must be greater than 0");
+ getState().valueChangeTimeout = timeout;
}
/**
- * Returns the last known cursor position of the field.
- *
- * <p>
- * Note that due to the client server nature or the GWT terminal, Vaadin
- * cannot provide the exact value of the cursor position in most situations.
- * The value is updated only when the client side terminal communicates to
- * TextField, like on {@link ValueChangeEvent}s and {@link TextChangeEvent}
- * s. This may change later if a deep push integration is built to Vaadin.
- *
- * @return the cursor position
+ * Returns the currently set timeout, in milliseconds, for how often
+ * {@link ValueChange}s are triggered if the current {@link ValueChangeMode}
+ * is set to either {@link ValueChangeMode#LAZY} or
+ * {@link ValueChangeMode#TIMEOUT}.
+ *
+ * @return the timeout in milliseconds of how often {@link ValueChange}s are
+ * triggered.
*/
- public int getCursorPosition() {
- return lastKnownCursorPosition;
+ public int getValueChangeTimeout() {
+ return getState(false).valueChangeTimeout;
}
@Override
- public void addFocusListener(FocusListener listener) {
- addListener(FocusEvent.EVENT_ID, FocusEvent.class, listener,
- FocusListener.focusMethod);
+ public void readDesign(Element design, DesignContext designContext) {
+ super.readDesign(design, designContext);
+ Attributes attr = design.attributes();
+ if (attr.hasKey("maxlength")) {
+ setMaxLength(DesignAttributeHandler.readAttribute("maxlength", attr,
+ Integer.class));
+ }
}
@Override
- public void removeFocusListener(FocusListener listener) {
- removeListener(FocusEvent.EVENT_ID, FocusEvent.class, listener);
+ protected TextFieldState getState() {
+ return (TextFieldState) super.getState();
}
@Override
- public void addBlurListener(BlurListener listener) {
- addListener(BlurEvent.EVENT_ID, BlurEvent.class, listener,
- BlurListener.blurMethod);
+ protected TextFieldState getState(boolean markAsDirty) {
+ return (TextFieldState) super.getState(markAsDirty);
}
@Override
- public void removeBlurListener(BlurListener listener) {
- removeListener(BlurEvent.EVENT_ID, BlurEvent.class, listener);
+ protected void doSetValue(String value) {
+ getState().text = value;
}
- /*
- * (non-Javadoc)
- *
- * @see com.vaadin.ui.AbstractField#readDesign(org.jsoup.nodes.Element ,
- * com.vaadin.ui.declarative.DesignContext)
+ /**
+ * Clears the value of this field.
*/
- @Override
- public void readDesign(Element design, DesignContext designContext) {
- super.readDesign(design, designContext);
- Attributes attr = design.attributes();
- if (attr.hasKey("maxlength")) {
- setMaxLength(DesignAttributeHandler.readAttribute("maxlength", attr,
- Integer.class));
- }
+ public void clear() {
+ setValue("");
}
- /*
- * (non-Javadoc)
- *
- * @see com.vaadin.ui.AbstractField#getCustomAttributes()
+ /**
+ * Checks if the field is empty.
+ *
+ * @return true if the field value is an empty string, false otherwise
*/
- @Override
- protected Collection<String> getCustomAttributes() {
- Collection<String> customAttributes = super.getCustomAttributes();
- customAttributes.add("maxlength");
- customAttributes.add("max-length"); // to prevent this appearing in
- // output
- customAttributes.add("cursor-position");
- return customAttributes;
+ public boolean isEmpty() {
+ return "".equals(getValue());
}
- /*
- * (non-Javadoc)
- *
- * @see com.vaadin.ui.AbstractField#writeDesign(org.jsoup.nodes.Element,
- * com.vaadin.ui.declarative.DesignContext)
- */
@Override
public void writeDesign(Element design, DesignContext designContext) {
super.writeDesign(design, designContext);
@@ -754,4 +331,13 @@ public abstract class AbstractTextField extends LegacyAbstractField<String>
def.getMaxLength(), Integer.class);
}
+ @Override
+ protected Collection<String> getCustomAttributes() {
+ Collection<String> customAttributes = super.getCustomAttributes();
+ customAttributes.add("maxlength");
+ customAttributes.add("max-length"); // to prevent this appearing in
+ // output
+ customAttributes.add("cursor-position");
+ return customAttributes;
+ }
}