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.8KB

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