You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

AbstractTextField.java 8.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  1. /*
  2. * Copyright 2000-2018 Vaadin Ltd.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License"); you may not
  5. * use this file except in compliance with the License. You may obtain a copy of
  6. * the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  12. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  13. * License for the specific language governing permissions and limitations under
  14. * the License.
  15. */
  16. package com.vaadin.ui;
  17. import java.util.Collection;
  18. import java.util.Objects;
  19. import org.jsoup.nodes.Attributes;
  20. import org.jsoup.nodes.Element;
  21. import com.vaadin.event.FieldEvents;
  22. import com.vaadin.event.FieldEvents.BlurEvent;
  23. import com.vaadin.event.FieldEvents.BlurListener;
  24. import com.vaadin.event.FieldEvents.FocusEvent;
  25. import com.vaadin.event.FieldEvents.FocusListener;
  26. import com.vaadin.shared.Registration;
  27. import com.vaadin.shared.communication.FieldRpc.FocusAndBlurServerRpc;
  28. import com.vaadin.shared.ui.ValueChangeMode;
  29. import com.vaadin.shared.ui.textfield.AbstractTextFieldClientRpc;
  30. import com.vaadin.shared.ui.textfield.AbstractTextFieldServerRpc;
  31. import com.vaadin.shared.ui.textfield.AbstractTextFieldState;
  32. import com.vaadin.ui.declarative.DesignAttributeHandler;
  33. import com.vaadin.ui.declarative.DesignContext;
  34. import elemental.json.Json;
  35. /**
  36. * Abstract base class for text input components.
  37. *
  38. * @author Vaadin Ltd.
  39. * @since 8.0
  40. */
  41. public abstract class AbstractTextField extends AbstractField<String>
  42. implements HasValueChangeMode, FieldEvents.FocusNotifier,
  43. FieldEvents.BlurNotifier {
  44. private final class AbstractTextFieldServerRpcImpl
  45. implements AbstractTextFieldServerRpc {
  46. @Override
  47. public void setText(String text, int cursorPosition) {
  48. updateDiffstate("text", Json.create(text));
  49. lastKnownCursorPosition = cursorPosition;
  50. setValue(text, true);
  51. }
  52. }
  53. private final class AbstractTextFieldFocusAndBlurRpcImpl
  54. implements FocusAndBlurServerRpc {
  55. @Override
  56. public void blur() {
  57. fireEvent(new BlurEvent(AbstractTextField.this));
  58. }
  59. @Override
  60. public void focus() {
  61. fireEvent(new FocusEvent(AbstractTextField.this));
  62. }
  63. }
  64. private int lastKnownCursorPosition = -1;
  65. /**
  66. * Creates a new instance.
  67. */
  68. protected AbstractTextField() {
  69. registerRpc(new AbstractTextFieldServerRpcImpl());
  70. registerRpc(new AbstractTextFieldFocusAndBlurRpcImpl());
  71. }
  72. /**
  73. * Sets the value of this text field. If the new value is not equal to
  74. * {@code getValue()}, fires a {@link ValueChangeEvent}. Throws
  75. * {@code NullPointerException} if the value is null.
  76. *
  77. * @param value
  78. * the new value, not {@code null}
  79. * @throws NullPointerException
  80. * if {@code value} is {@code null}
  81. */
  82. @Override
  83. public void setValue(String value) {
  84. Objects.requireNonNull(value, "value cannot be null");
  85. setValue(value, false);
  86. }
  87. /**
  88. * Returns the maximum number of characters in the field. Value -1 is
  89. * considered unlimited. Terminal may however have some technical limits.
  90. *
  91. * @return the maxLength
  92. */
  93. public int getMaxLength() {
  94. return getState(false).maxLength;
  95. }
  96. /**
  97. * Sets the maximum number of characters in the field. Value -1 is
  98. * considered unlimited. Terminal may however have some technical limits.
  99. *
  100. * @param maxLength
  101. * the maxLength to set
  102. */
  103. public void setMaxLength(int maxLength) {
  104. getState().maxLength = maxLength;
  105. }
  106. /**
  107. * Returns the current placeholder text.
  108. *
  109. * @see #setPlaceholder(String)
  110. * @return the placeholder text
  111. */
  112. public String getPlaceholder() {
  113. return getState(false).placeholder;
  114. }
  115. /**
  116. * Sets the placeholder text. The placeholder is text that is displayed when
  117. * the field would otherwise be empty, to prompt the user for input.
  118. *
  119. * @param placeholder
  120. * the placeholder text to set
  121. * @since 8.0
  122. */
  123. public void setPlaceholder(String placeholder) {
  124. getState().placeholder = placeholder;
  125. }
  126. @Override
  127. public String getValue() {
  128. return getState(false).text;
  129. }
  130. /**
  131. * Selects all text in the field.
  132. * <p>
  133. * As a side effect the field will become focused.
  134. */
  135. public void selectAll() {
  136. getRpcProxy(AbstractTextFieldClientRpc.class).selectAll();
  137. focus();
  138. }
  139. /**
  140. * Sets the range of text to be selected.
  141. * <p>
  142. * As a side effect the field will become focused.
  143. *
  144. * @param start
  145. * the position of the first character to be selected
  146. * @param length
  147. * the number of characters to be selected
  148. */
  149. public void setSelection(int start, int length) {
  150. getRpcProxy(AbstractTextFieldClientRpc.class).selectRange(start,
  151. length);
  152. focus();
  153. }
  154. /**
  155. * Sets the cursor position in the field. As a side effect the field will
  156. * become focused.
  157. *
  158. * @param pos
  159. * the position for the cursor
  160. */
  161. public void setCursorPosition(int pos) {
  162. setSelection(pos, 0);
  163. }
  164. /**
  165. * Returns the last known cursor position of the field.
  166. *
  167. * @return the last known cursor position
  168. */
  169. public int getCursorPosition() {
  170. return lastKnownCursorPosition;
  171. }
  172. /**
  173. * Adds a {@link FocusListener} to this component, which gets fired when
  174. * this component receives keyboard focus.
  175. *
  176. * @param listener
  177. * the focus listener
  178. * @return a registration for the listener
  179. *
  180. * @see Registration
  181. */
  182. @Override
  183. public Registration addFocusListener(FocusListener listener) {
  184. return addListener(FocusEvent.EVENT_ID, FocusEvent.class, listener,
  185. FocusListener.focusMethod);
  186. }
  187. /**
  188. * Adds a {@link BlurListener} to this component, which gets fired when this
  189. * component loses keyboard focus.
  190. *
  191. * @param listener
  192. * the blur listener
  193. * @return a registration for the listener
  194. *
  195. * @see Registration
  196. */
  197. @Override
  198. public Registration addBlurListener(BlurListener listener) {
  199. return addListener(BlurEvent.EVENT_ID, BlurEvent.class, listener,
  200. BlurListener.blurMethod);
  201. }
  202. @Override
  203. public void setValueChangeMode(ValueChangeMode mode) {
  204. getState().valueChangeMode = mode;
  205. }
  206. @Override
  207. public ValueChangeMode getValueChangeMode() {
  208. return getState(false).valueChangeMode;
  209. }
  210. @Override
  211. public void setValueChangeTimeout(int timeout) {
  212. if (timeout < 0) {
  213. throw new IllegalArgumentException(
  214. "Timeout must be greater than 0");
  215. }
  216. getState().valueChangeTimeout = timeout;
  217. }
  218. @Override
  219. public int getValueChangeTimeout() {
  220. return getState(false).valueChangeTimeout;
  221. }
  222. @Override
  223. public void readDesign(Element design, DesignContext designContext) {
  224. super.readDesign(design, designContext);
  225. Attributes attr = design.attributes();
  226. if (attr.hasKey("maxlength")) {
  227. setMaxLength(DesignAttributeHandler.readAttribute("maxlength", attr,
  228. Integer.class));
  229. }
  230. }
  231. @Override
  232. protected AbstractTextFieldState getState() {
  233. return (AbstractTextFieldState) super.getState();
  234. }
  235. @Override
  236. protected AbstractTextFieldState getState(boolean markAsDirty) {
  237. return (AbstractTextFieldState) super.getState(markAsDirty);
  238. }
  239. @Override
  240. protected void doSetValue(String value) {
  241. getState().text = value;
  242. }
  243. @Override
  244. public void writeDesign(Element design, DesignContext designContext) {
  245. super.writeDesign(design, designContext);
  246. AbstractTextField def = designContext.getDefaultInstance(this);
  247. Attributes attr = design.attributes();
  248. DesignAttributeHandler.writeAttribute("maxlength", attr, getMaxLength(),
  249. def.getMaxLength(), Integer.class, designContext);
  250. }
  251. @Override
  252. protected Collection<String> getCustomAttributes() {
  253. Collection<String> customAttributes = super.getCustomAttributes();
  254. customAttributes.add("maxlength");
  255. // to prevent this appearing in output
  256. customAttributes.add("max-length");
  257. customAttributes.add("cursor-position");
  258. return customAttributes;
  259. }
  260. @Override
  261. public String getEmptyValue() {
  262. return "";
  263. }
  264. }