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

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