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 26KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812
  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.v7.ui;
  17. import java.util.Collection;
  18. import java.util.Map;
  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.server.PaintException;
  26. import com.vaadin.server.PaintTarget;
  27. import com.vaadin.ui.LegacyComponent;
  28. import com.vaadin.ui.declarative.DesignAttributeHandler;
  29. import com.vaadin.ui.declarative.DesignContext;
  30. import com.vaadin.v7.event.FieldEvents.BlurNotifier;
  31. import com.vaadin.v7.event.FieldEvents.FocusNotifier;
  32. import com.vaadin.v7.event.FieldEvents.TextChangeEvent;
  33. import com.vaadin.v7.event.FieldEvents.TextChangeListener;
  34. import com.vaadin.v7.event.FieldEvents.TextChangeNotifier;
  35. import com.vaadin.v7.shared.ui.textfield.AbstractTextFieldState;
  36. import com.vaadin.v7.shared.ui.textfield.TextFieldConstants;
  37. @Deprecated
  38. public abstract class AbstractTextField extends AbstractField<String> implements
  39. BlurNotifier, FocusNotifier, TextChangeNotifier, LegacyComponent {
  40. /**
  41. * Null representation.
  42. */
  43. private String nullRepresentation = "null";
  44. /**
  45. * Is setting to null from non-null value allowed by setting with null
  46. * representation .
  47. */
  48. private boolean nullSettingAllowed = false;
  49. /**
  50. * The text content when the last messages to the server was sent. Cleared
  51. * when value is changed.
  52. */
  53. private String lastKnownTextContent;
  54. /**
  55. * The position of the cursor when the last message to the server was sent.
  56. */
  57. private int lastKnownCursorPosition;
  58. /**
  59. * Flag indicating that a text change event is pending to be triggered.
  60. * Cleared by {@link #setInternalValue(Object)} and when the event is fired.
  61. */
  62. private boolean textChangeEventPending;
  63. private boolean isFiringTextChangeEvent = false;
  64. private TextChangeEventMode textChangeEventMode = TextChangeEventMode.LAZY;
  65. private final int DEFAULT_TEXTCHANGE_TIMEOUT = 400;
  66. private int textChangeEventTimeout = DEFAULT_TEXTCHANGE_TIMEOUT;
  67. /**
  68. * Temporarily holds the new selection position. Cleared on paint.
  69. */
  70. private int selectionPosition = -1;
  71. /**
  72. * Temporarily holds the new selection length.
  73. */
  74. private int selectionLength;
  75. /**
  76. * Flag used to determine whether we are currently handling a state change
  77. * triggered by a user. Used to properly fire text change event before value
  78. * change event triggered by the client side.
  79. */
  80. private boolean changingVariables;
  81. protected AbstractTextField() {
  82. super();
  83. }
  84. @Override
  85. protected AbstractTextFieldState getState() {
  86. return (AbstractTextFieldState) super.getState();
  87. }
  88. @Override
  89. protected AbstractTextFieldState getState(boolean markAsDirty) {
  90. return (AbstractTextFieldState) super.getState(markAsDirty);
  91. }
  92. @Override
  93. public void beforeClientResponse(boolean initial) {
  94. super.beforeClientResponse(initial);
  95. String value = getValue();
  96. if (value == null) {
  97. value = getNullRepresentation();
  98. }
  99. getState().text = value;
  100. }
  101. @Override
  102. public void paintContent(PaintTarget target) throws PaintException {
  103. if (selectionPosition != -1) {
  104. target.addAttribute("selpos", selectionPosition);
  105. target.addAttribute("sellen", selectionLength);
  106. selectionPosition = -1;
  107. }
  108. if (hasListeners(TextChangeEvent.class)) {
  109. target.addAttribute(TextFieldConstants.ATTR_TEXTCHANGE_EVENTMODE,
  110. getTextChangeEventMode().toString());
  111. target.addAttribute(TextFieldConstants.ATTR_TEXTCHANGE_TIMEOUT,
  112. getTextChangeTimeout());
  113. if (lastKnownTextContent != null) {
  114. /*
  115. * The field has be repainted for some reason (e.g. caption,
  116. * size, stylename), but the value has not been changed since
  117. * the last text change event. Let the client side know about
  118. * the value the server side knows. Client side may then ignore
  119. * the actual value, depending on its state.
  120. */
  121. target.addAttribute(
  122. TextFieldConstants.ATTR_NO_VALUE_CHANGE_BETWEEN_PAINTS,
  123. true);
  124. }
  125. }
  126. }
  127. @Override
  128. public void changeVariables(Object source, Map<String, Object> variables) {
  129. changingVariables = true;
  130. try {
  131. // Sets the height set by the user when resize the <textarea>.
  132. String newHeight = (String) variables.get("height");
  133. if (newHeight != null) {
  134. setHeight(newHeight);
  135. }
  136. // Sets the width set by the user when resize the <textarea>.
  137. String newWidth = (String) variables.get("width");
  138. if (newWidth != null) {
  139. setWidth(newWidth);
  140. }
  141. if (variables.containsKey(TextFieldConstants.VAR_CURSOR)) {
  142. Integer object = (Integer) variables
  143. .get(TextFieldConstants.VAR_CURSOR);
  144. lastKnownCursorPosition = object.intValue();
  145. }
  146. if (variables.containsKey(TextFieldConstants.VAR_CUR_TEXT)) {
  147. /*
  148. * NOTE, we might want to develop this further so that on a
  149. * value change event the whole text content don't need to be
  150. * sent from the client to server. Just "commit" the value from
  151. * currentText to the value.
  152. */
  153. handleInputEventTextChange(variables);
  154. }
  155. // Sets the text
  156. if (variables.containsKey("text") && !isReadOnly()) {
  157. // Only do the setting if the string representation of the value
  158. // has been updated
  159. String newValue = (String) variables.get("text");
  160. // server side check for max length
  161. if (getMaxLength() != -1
  162. && newValue.length() > getMaxLength()) {
  163. newValue = newValue.substring(0, getMaxLength());
  164. }
  165. final String oldValue = getValue();
  166. if (newValue != null
  167. && (oldValue == null || isNullSettingAllowed())
  168. && newValue.equals(getNullRepresentation())) {
  169. newValue = null;
  170. }
  171. if (newValue != oldValue
  172. && (newValue == null || !newValue.equals(oldValue))) {
  173. boolean wasModified = isModified();
  174. setValue(newValue, true);
  175. // If the modified status changes, or if we have a
  176. // formatter, repaint is needed after all.
  177. if (wasModified != isModified()) {
  178. markAsDirty();
  179. }
  180. }
  181. }
  182. firePendingTextChangeEvent();
  183. if (variables.containsKey(FocusEvent.EVENT_ID)) {
  184. fireEvent(new FocusEvent(this));
  185. }
  186. if (variables.containsKey(BlurEvent.EVENT_ID)) {
  187. fireEvent(new BlurEvent(this));
  188. }
  189. } finally {
  190. changingVariables = false;
  191. }
  192. }
  193. @Override
  194. public Class<String> getType() {
  195. return String.class;
  196. }
  197. /**
  198. * Gets the null-string representation.
  199. *
  200. * <p>
  201. * The null-valued strings are represented on the user interface by
  202. * replacing the null value with this string. If the null representation is
  203. * set null (not 'null' string), painting null value throws exception.
  204. * </p>
  205. *
  206. * <p>
  207. * The default value is string 'null'.
  208. * </p>
  209. *
  210. * @return the String Textual representation for null strings.
  211. * @see TextField#isNullSettingAllowed()
  212. */
  213. public String getNullRepresentation() {
  214. return nullRepresentation;
  215. }
  216. /**
  217. * Is setting nulls with null-string representation allowed.
  218. *
  219. * <p>
  220. * If this property is true, writing null-representation string to text
  221. * field always sets the field value to real null. If this property is
  222. * false, null setting is not made, but the null values are maintained.
  223. * Maintenance of null-values is made by only converting the textfield
  224. * contents to real null, if the text field matches the null-string
  225. * representation and the current value of the field is null.
  226. * </p>
  227. *
  228. * <p>
  229. * By default this setting is false
  230. * </p>
  231. *
  232. * @return boolean Should the null-string represenation be always converted
  233. * to null-values.
  234. * @see TextField#getNullRepresentation()
  235. */
  236. public boolean isNullSettingAllowed() {
  237. return nullSettingAllowed;
  238. }
  239. /**
  240. * Sets the null-string representation.
  241. *
  242. * <p>
  243. * The null-valued strings are represented on the user interface by
  244. * replacing the null value with this string. If the null representation is
  245. * set null (not 'null' string), painting null value throws exception.
  246. * </p>
  247. *
  248. * <p>
  249. * The default value is string 'null'
  250. * </p>
  251. *
  252. * @param nullRepresentation
  253. * Textual representation for null strings.
  254. * @see TextField#setNullSettingAllowed(boolean)
  255. */
  256. public void setNullRepresentation(String nullRepresentation) {
  257. this.nullRepresentation = nullRepresentation;
  258. markAsDirty();
  259. }
  260. /**
  261. * Sets the null conversion mode.
  262. *
  263. * <p>
  264. * If this property is true, writing null-representation string to text
  265. * field always sets the field value to real null. If this property is
  266. * false, null setting is not made, but the null values are maintained.
  267. * Maintenance of null-values is made by only converting the textfield
  268. * contents to real null, if the text field matches the null-string
  269. * representation and the current value of the field is null.
  270. * </p>
  271. *
  272. * <p>
  273. * By default this setting is false.
  274. * </p>
  275. *
  276. * @param nullSettingAllowed
  277. * Should the null-string representation always be converted to
  278. * null-values.
  279. * @see TextField#getNullRepresentation()
  280. */
  281. public void setNullSettingAllowed(boolean nullSettingAllowed) {
  282. this.nullSettingAllowed = nullSettingAllowed;
  283. markAsDirty();
  284. }
  285. @Override
  286. public boolean isEmpty() {
  287. return super.isEmpty() || getValue().isEmpty();
  288. }
  289. /**
  290. * Returns the maximum number of characters in the field. Value -1 is
  291. * considered unlimited. Terminal may however have some technical limits.
  292. *
  293. * @return the maxLength
  294. */
  295. public int getMaxLength() {
  296. return getState(false).maxLength;
  297. }
  298. /**
  299. * Sets the maximum number of characters in the field. Value -1 is
  300. * considered unlimited. Terminal may however have some technical limits.
  301. *
  302. * @param maxLength
  303. * the maxLength to set
  304. */
  305. public void setMaxLength(int maxLength) {
  306. getState().maxLength = maxLength;
  307. }
  308. /**
  309. * Gets the number of columns in the editor. If the number of columns is set
  310. * 0, the actual number of displayed columns is determined implicitly by the
  311. * adapter.
  312. *
  313. * @return the number of columns in the editor.
  314. */
  315. public int getColumns() {
  316. return getState(false).columns;
  317. }
  318. /**
  319. * Sets the number of columns in the editor. If the number of columns is set
  320. * 0, the actual number of displayed columns is determined implicitly by the
  321. * adapter.
  322. *
  323. * @param columns
  324. * the number of columns to set.
  325. */
  326. public void setColumns(int columns) {
  327. if (columns < 0) {
  328. columns = 0;
  329. }
  330. getState().columns = columns;
  331. }
  332. /**
  333. * Gets the current input prompt.
  334. *
  335. * @see #setInputPrompt(String)
  336. * @return the current input prompt, or null if not enabled
  337. */
  338. public String getInputPrompt() {
  339. return getState(false).inputPrompt;
  340. }
  341. /**
  342. * Sets the input prompt - a textual prompt that is displayed when the field
  343. * would otherwise be empty, to prompt the user for input.
  344. *
  345. * @param inputPrompt
  346. */
  347. public void setInputPrompt(String inputPrompt) {
  348. getState().inputPrompt = inputPrompt;
  349. }
  350. /* ** Text Change Events ** */
  351. private void firePendingTextChangeEvent() {
  352. if (textChangeEventPending && !isFiringTextChangeEvent) {
  353. isFiringTextChangeEvent = true;
  354. textChangeEventPending = false;
  355. try {
  356. fireEvent(new TextChangeEventImpl(this));
  357. } finally {
  358. isFiringTextChangeEvent = false;
  359. }
  360. }
  361. }
  362. @Override
  363. protected void setInternalValue(String newValue) {
  364. if (changingVariables && !textChangeEventPending) {
  365. /*
  366. * TODO check for possible (minor?) issue (not tested)
  367. *
  368. * -field with e.g. PropertyFormatter.
  369. *
  370. * -TextChangeListener and it changes value.
  371. *
  372. * -if formatter again changes the value, do we get an extra
  373. * simulated text change event ?
  374. */
  375. /*
  376. * Fire a "simulated" text change event before value change event if
  377. * change is coming from the client side.
  378. *
  379. * Iff there is both value change and textChangeEvent in same
  380. * variable burst, it is a text field in non immediate mode and the
  381. * text change event "flushed" queued value change event. In this
  382. * case textChangeEventPending flag is already on and text change
  383. * event will be fired after the value change event.
  384. */
  385. if (newValue == null && lastKnownTextContent != null
  386. && !lastKnownTextContent.equals(getNullRepresentation())) {
  387. // Value was changed from something to null representation
  388. lastKnownTextContent = getNullRepresentation();
  389. textChangeEventPending = true;
  390. } else if (newValue != null
  391. && !newValue.toString().equals(lastKnownTextContent)) {
  392. // Value was changed to something else than null representation
  393. lastKnownTextContent = newValue.toString();
  394. textChangeEventPending = true;
  395. }
  396. firePendingTextChangeEvent();
  397. }
  398. super.setInternalValue(newValue);
  399. }
  400. @Override
  401. public void setValue(String newValue) throws ReadOnlyException {
  402. super.setValue(newValue);
  403. /*
  404. * Make sure w reset lastKnownTextContent field on value change. The
  405. * clearing must happen here as well because TextChangeListener can
  406. * revert the original value. Client must respect the value in this
  407. * case. AbstractField optimizes value change if the existing value is
  408. * reset. Also we need to force repaint if the flag is on.
  409. */
  410. if (lastKnownTextContent != null) {
  411. lastKnownTextContent = null;
  412. markAsDirty();
  413. }
  414. }
  415. private void handleInputEventTextChange(Map<String, Object> variables) {
  416. /*
  417. * TODO we could vastly optimize the communication of values by using
  418. * some sort of diffs instead of always sending the whole text content.
  419. * Also on value change events we could use the mechanism.
  420. */
  421. String object = (String) variables.get(TextFieldConstants.VAR_CUR_TEXT);
  422. lastKnownTextContent = object;
  423. textChangeEventPending = true;
  424. }
  425. /**
  426. * Sets the mode how the TextField triggers {@link TextChangeEvent}s.
  427. *
  428. * @param inputEventMode
  429. * the new mode
  430. *
  431. * @see TextChangeEventMode
  432. */
  433. public void setTextChangeEventMode(TextChangeEventMode inputEventMode) {
  434. textChangeEventMode = inputEventMode;
  435. markAsDirty();
  436. }
  437. /**
  438. * @return the mode used to trigger {@link TextChangeEvent}s.
  439. */
  440. public TextChangeEventMode getTextChangeEventMode() {
  441. return textChangeEventMode;
  442. }
  443. /**
  444. * Different modes how the TextField can trigger {@link TextChangeEvent}s.
  445. */
  446. @Deprecated
  447. public enum TextChangeEventMode {
  448. /**
  449. * An event is triggered on each text content change, most commonly key
  450. * press events.
  451. */
  452. EAGER,
  453. /**
  454. * Each text change event in the UI causes the event to be communicated
  455. * to the application after a timeout. The length of the timeout can be
  456. * controlled with {@link TextField#setTextChangeTimeout(int)}. Only the
  457. * last input event is reported to the server side if several text
  458. * change events happen during the timeout.
  459. * <p>
  460. * In case of a {@link ValueChangeEvent} the schedule is not kept
  461. * strictly. Before a {@link ValueChangeEvent} a {@link TextChangeEvent}
  462. * is triggered if the text content has changed since the previous
  463. * TextChangeEvent regardless of the schedule.
  464. */
  465. TIMEOUT,
  466. /**
  467. * An event is triggered when there is a pause of text modifications.
  468. * The length of the pause can be modified with
  469. * {@link TextField#setTextChangeTimeout(int)}. Like with the
  470. * {@link #TIMEOUT} mode, an event is forced before
  471. * {@link ValueChangeEvent}s, even if the user did not keep a pause
  472. * while entering the text.
  473. * <p>
  474. * This is the default mode.
  475. */
  476. LAZY
  477. }
  478. @Override
  479. public void addTextChangeListener(TextChangeListener listener) {
  480. addListener(TextChangeListener.EVENT_ID, TextChangeEvent.class,
  481. listener, TextChangeListener.EVENT_METHOD);
  482. }
  483. /**
  484. * @deprecated As of 7.0, replaced by
  485. * {@link #addTextChangeListener(TextChangeListener)}
  486. **/
  487. @Deprecated
  488. public void addListener(TextChangeListener listener) {
  489. addTextChangeListener(listener);
  490. }
  491. @Override
  492. public void removeTextChangeListener(TextChangeListener listener) {
  493. removeListener(TextChangeListener.EVENT_ID, TextChangeEvent.class,
  494. listener);
  495. }
  496. /**
  497. * @deprecated As of 7.0, replaced by
  498. * {@link #removeTextChangeListener(TextChangeListener)}
  499. **/
  500. @Deprecated
  501. public void removeListener(TextChangeListener listener) {
  502. removeTextChangeListener(listener);
  503. }
  504. /**
  505. * The text change timeout modifies how often text change events are
  506. * communicated to the application when {@link #getTextChangeEventMode()} is
  507. * {@link TextChangeEventMode#LAZY} or {@link TextChangeEventMode#TIMEOUT}.
  508. *
  509. *
  510. * @see #getTextChangeEventMode()
  511. *
  512. * @param timeout
  513. * the timeout in milliseconds
  514. */
  515. public void setTextChangeTimeout(int timeout) {
  516. textChangeEventTimeout = timeout;
  517. markAsDirty();
  518. }
  519. /**
  520. * Gets the timeout used to fire {@link TextChangeEvent}s when the
  521. * {@link #getTextChangeEventMode()} is {@link TextChangeEventMode#LAZY} or
  522. * {@link TextChangeEventMode#TIMEOUT}.
  523. *
  524. * @return the timeout value in milliseconds
  525. */
  526. public int getTextChangeTimeout() {
  527. return textChangeEventTimeout;
  528. }
  529. @Deprecated
  530. public static class TextChangeEventImpl extends TextChangeEvent {
  531. private String curText;
  532. private int cursorPosition;
  533. private TextChangeEventImpl(final AbstractTextField tf) {
  534. super(tf);
  535. curText = tf.getCurrentTextContent();
  536. cursorPosition = tf.getCursorPosition();
  537. }
  538. @Override
  539. public AbstractTextField getComponent() {
  540. return (AbstractTextField) super.getComponent();
  541. }
  542. @Override
  543. public String getText() {
  544. return curText;
  545. }
  546. @Override
  547. public int getCursorPosition() {
  548. return cursorPosition;
  549. }
  550. }
  551. /**
  552. * Gets the current (or the last known) text content in the field.
  553. * <p>
  554. * Note the text returned by this method is not necessary the same that is
  555. * returned by the {@link #getValue()} method. The value is updated when the
  556. * terminal fires a value change event via e.g. blurring the field or by
  557. * pressing enter. The value returned by this method is updated also on
  558. * {@link TextChangeEvent}s. Due to this high dependency to the terminal
  559. * implementation this method is (at least at this point) not published.
  560. *
  561. * @return the text which is currently displayed in the field.
  562. */
  563. private String getCurrentTextContent() {
  564. if (lastKnownTextContent != null) {
  565. return lastKnownTextContent;
  566. } else {
  567. Object text = getValue();
  568. if (text == null) {
  569. return getNullRepresentation();
  570. }
  571. return text.toString();
  572. }
  573. }
  574. /**
  575. * Selects all text in the field.
  576. *
  577. * @since 6.4
  578. */
  579. public void selectAll() {
  580. String text = getValue() == null ? "" : getValue().toString();
  581. setSelectionRange(0, text.length());
  582. }
  583. /**
  584. * Sets the range of text to be selected.
  585. *
  586. * As a side effect the field will become focused.
  587. *
  588. * @since 6.4
  589. *
  590. * @param pos
  591. * the position of the first character to be selected
  592. * @param length
  593. * the number of characters to be selected
  594. */
  595. public void setSelectionRange(int pos, int length) {
  596. selectionPosition = pos;
  597. selectionLength = length;
  598. focus();
  599. markAsDirty();
  600. }
  601. /**
  602. * Sets the cursor position in the field. As a side effect the field will
  603. * become focused.
  604. *
  605. * @since 6.4
  606. *
  607. * @param pos
  608. * the position for the cursor
  609. */
  610. public void setCursorPosition(int pos) {
  611. setSelectionRange(pos, 0);
  612. lastKnownCursorPosition = pos;
  613. }
  614. /**
  615. * Returns the last known cursor position of the field.
  616. *
  617. * <p>
  618. * Note that due to the client server nature or the GWT terminal, Vaadin
  619. * cannot provide the exact value of the cursor position in most situations.
  620. * The value is updated only when the client side terminal communicates to
  621. * TextField, like on {@link ValueChangeEvent}s and {@link TextChangeEvent}
  622. * s. This may change later if a deep push integration is built to Vaadin.
  623. *
  624. * @return the cursor position
  625. */
  626. public int getCursorPosition() {
  627. return lastKnownCursorPosition;
  628. }
  629. @Override
  630. public void addFocusListener(FocusListener listener) {
  631. addListener(FocusEvent.EVENT_ID, FocusEvent.class, listener,
  632. FocusListener.focusMethod);
  633. }
  634. /**
  635. * @deprecated As of 7.0, replaced by
  636. * {@link #addFocusListener(FocusListener)}
  637. **/
  638. @Deprecated
  639. public void addListener(FocusListener listener) {
  640. addFocusListener(listener);
  641. }
  642. @Override
  643. public void removeFocusListener(FocusListener listener) {
  644. removeListener(FocusEvent.EVENT_ID, FocusEvent.class, listener);
  645. }
  646. /**
  647. * @deprecated As of 7.0, replaced by
  648. * {@link #removeFocusListener(FocusListener)}
  649. **/
  650. @Deprecated
  651. public void removeListener(FocusListener listener) {
  652. removeFocusListener(listener);
  653. }
  654. @Override
  655. public void addBlurListener(BlurListener listener) {
  656. addListener(BlurEvent.EVENT_ID, BlurEvent.class, listener,
  657. BlurListener.blurMethod);
  658. }
  659. /**
  660. * @deprecated As of 7.0, replaced by {@link #addBlurListener(BlurListener)}
  661. **/
  662. @Deprecated
  663. public void addListener(BlurListener listener) {
  664. addBlurListener(listener);
  665. }
  666. @Override
  667. public void removeBlurListener(BlurListener listener) {
  668. removeListener(BlurEvent.EVENT_ID, BlurEvent.class, listener);
  669. }
  670. /**
  671. * @deprecated As of 7.0, replaced by
  672. * {@link #removeBlurListener(BlurListener)}
  673. **/
  674. @Deprecated
  675. public void removeListener(BlurListener listener) {
  676. removeBlurListener(listener);
  677. }
  678. /*
  679. * (non-Javadoc)
  680. *
  681. * @see com.vaadin.ui.AbstractField#readDesign(org.jsoup.nodes.Element ,
  682. * com.vaadin.ui.declarative.DesignContext)
  683. */
  684. @Override
  685. public void readDesign(Element design, DesignContext designContext) {
  686. super.readDesign(design, designContext);
  687. Attributes attr = design.attributes();
  688. if (attr.hasKey("maxlength")) {
  689. setMaxLength(DesignAttributeHandler.readAttribute("maxlength", attr,
  690. Integer.class));
  691. }
  692. }
  693. /*
  694. * (non-Javadoc)
  695. *
  696. * @see com.vaadin.ui.AbstractField#getCustomAttributes()
  697. */
  698. @Override
  699. protected Collection<String> getCustomAttributes() {
  700. Collection<String> customAttributes = super.getCustomAttributes();
  701. customAttributes.add("maxlength");
  702. customAttributes.add("max-length"); // to prevent this appearing in
  703. // output
  704. customAttributes.add("cursor-position");
  705. return customAttributes;
  706. }
  707. /*
  708. * (non-Javadoc)
  709. *
  710. * @see com.vaadin.ui.AbstractField#writeDesign(org.jsoup.nodes.Element,
  711. * com.vaadin.ui.declarative.DesignContext)
  712. */
  713. @Override
  714. public void writeDesign(Element design, DesignContext designContext) {
  715. super.writeDesign(design, designContext);
  716. AbstractTextField def = (AbstractTextField) designContext
  717. .getDefaultInstance(this);
  718. Attributes attr = design.attributes();
  719. DesignAttributeHandler.writeAttribute("maxlength", attr, getMaxLength(),
  720. def.getMaxLength(), Integer.class, designContext);
  721. }
  722. }