com.vaadin.ui.AbstractTextField Maven / Gradle / Ivy
/*
* Copyright (C) 2000-2024 Vaadin Ltd
*
* This program is available under Vaadin Commercial License and Service Terms.
*
* See for the full
* license.
*/
package com.vaadin.ui;
import java.util.Collection;
import java.util.Objects;
import org.jsoup.nodes.Attributes;
import org.jsoup.nodes.Element;
import com.vaadin.event.FieldEvents;
import com.vaadin.event.FieldEvents.BlurEvent;
import com.vaadin.event.FieldEvents.BlurListener;
import com.vaadin.event.FieldEvents.FocusEvent;
import com.vaadin.event.FieldEvents.FocusListener;
import com.vaadin.shared.Registration;
import com.vaadin.shared.communication.FieldRpc.FocusAndBlurServerRpc;
import com.vaadin.shared.ui.ValueChangeMode;
import com.vaadin.shared.ui.textfield.AbstractTextFieldClientRpc;
import com.vaadin.shared.ui.textfield.AbstractTextFieldServerRpc;
import com.vaadin.shared.ui.textfield.AbstractTextFieldState;
import com.vaadin.ui.declarative.DesignAttributeHandler;
import com.vaadin.ui.declarative.DesignContext;
import elemental.json.Json;
/**
* Abstract base class for text input components.
*
* @author Vaadin Ltd.
* @since 8.0
*/
public abstract class AbstractTextField extends AbstractField
implements HasValueChangeMode, FieldEvents.FocusNotifier,
FieldEvents.BlurNotifier {
private final class AbstractTextFieldServerRpcImpl
implements AbstractTextFieldServerRpc {
@Override
public void setText(String text, int cursorPosition) {
updateDiffstate("text", Json.create(text));
lastKnownCursorPosition = cursorPosition;
setValue(text, true);
}
}
private final class AbstractTextFieldFocusAndBlurRpcImpl
implements FocusAndBlurServerRpc {
@Override
public void blur() {
fireEvent(new BlurEvent(AbstractTextField.this));
}
@Override
public void focus() {
fireEvent(new FocusEvent(AbstractTextField.this));
}
}
private int lastKnownCursorPosition = -1;
/**
* Creates a new instance.
*/
protected AbstractTextField() {
registerRpc(new AbstractTextFieldServerRpcImpl());
registerRpc(new AbstractTextFieldFocusAndBlurRpcImpl());
}
/**
* Sets the value of this text field. If the new value is not equal to
* {@code getValue()}, fires a {@link ValueChangeEvent}. Throws
* {@code NullPointerException} if the value is null.
*
* @param value
* the new value, not {@code null}
* @throws NullPointerException
* if {@code value} is {@code null}
*/
@Override
public void setValue(String value) {
Objects.requireNonNull(value, "value cannot be null");
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() {
return getState(false).maxLength;
}
/**
* 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
*/
public void setMaxLength(int maxLength) {
getState().maxLength = maxLength;
}
/**
* Returns the current placeholder text.
*
* @see #setPlaceholder(String)
* @return the placeholder text
*/
public String getPlaceholder() {
return getState(false).placeholder;
}
/**
* 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
* @since 8.0
*/
public void setPlaceholder(String placeholder) {
getState().placeholder = placeholder;
}
@Override
public String getValue() {
return getState(false).text;
}
/**
* Selects all text in the field.
*
* As a side effect the field will become focused.
*/
public void selectAll() {
getRpcProxy(AbstractTextFieldClientRpc.class).selectAll();
focus();
}
/**
* Sets the range of text to be selected.
*
* As a side effect the field will become focused.
*
* @param start
* the position of the first character to be selected
* @param length
* the number of characters to be selected
*/
public void setSelection(int start, int length) {
getRpcProxy(AbstractTextFieldClientRpc.class).selectRange(start,
length);
focus();
}
/**
* Sets the cursor position in the field. As a side effect the field will
* become focused.
*
* @param pos
* the position for the cursor
*/
public void setCursorPosition(int pos) {
setSelection(pos, 0);
}
/**
* Returns the last known cursor position of the field.
*
* @return the last known cursor position
*/
public int getCursorPosition() {
return lastKnownCursorPosition;
}
/**
* 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
*/
@Override
public Registration addFocusListener(FocusListener listener) {
return addListener(FocusEvent.EVENT_ID, FocusEvent.class, listener,
FocusListener.focusMethod);
}
/**
* 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
*/
@Override
public Registration addBlurListener(BlurListener listener) {
return addListener(BlurEvent.EVENT_ID, BlurEvent.class, listener,
BlurListener.blurMethod);
}
@Override
public void setValueChangeMode(ValueChangeMode mode) {
getState().valueChangeMode = mode;
}
@Override
public ValueChangeMode getValueChangeMode() {
return getState(false).valueChangeMode;
}
@Override
public void setValueChangeTimeout(int timeout) {
if (timeout < 0) {
throw new IllegalArgumentException(
"Timeout must be greater than 0");
}
getState().valueChangeTimeout = timeout;
}
@Override
public int getValueChangeTimeout() {
return getState(false).valueChangeTimeout;
}
@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));
}
}
@Override
protected AbstractTextFieldState getState() {
return (AbstractTextFieldState) super.getState();
}
@Override
protected AbstractTextFieldState getState(boolean markAsDirty) {
return (AbstractTextFieldState) super.getState(markAsDirty);
}
@Override
protected void doSetValue(String value) {
getState().text = value;
}
@Override
public void writeDesign(Element design, DesignContext designContext) {
super.writeDesign(design, designContext);
AbstractTextField def = designContext.getDefaultInstance(this);
Attributes attr = design.attributes();
DesignAttributeHandler.writeAttribute("maxlength", attr, getMaxLength(),
def.getMaxLength(), Integer.class, designContext);
}
@Override
protected Collection getCustomAttributes() {
Collection customAttributes = super.getCustomAttributes();
customAttributes.add("maxlength");
// to prevent this appearing in output
customAttributes.add("max-length");
customAttributes.add("cursor-position");
return customAttributes;
}
@Override
public String getEmptyValue() {
return "";
}
}