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.

TextField.java 19KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637
  1. /*
  2. @ITMillApache2LicenseForJavaFiles@
  3. */
  4. package com.vaadin.ui;
  5. import java.text.Format;
  6. import java.util.Map;
  7. import com.vaadin.data.Property;
  8. import com.vaadin.event.FieldEvents;
  9. import com.vaadin.event.FieldEvents.BlurEvent;
  10. import com.vaadin.event.FieldEvents.BlurListener;
  11. import com.vaadin.event.FieldEvents.FocusEvent;
  12. import com.vaadin.event.FieldEvents.FocusListener;
  13. import com.vaadin.terminal.PaintException;
  14. import com.vaadin.terminal.PaintTarget;
  15. import com.vaadin.terminal.gwt.client.ui.VTextField;
  16. /**
  17. * <p>
  18. * A text editor component that can be bound to any bindable Property. The text
  19. * editor supports both multiline and single line modes, default is one-line
  20. * mode.
  21. * </p>
  22. *
  23. * <p>
  24. * Since <code>TextField</code> extends <code>AbstractField</code> it implements
  25. * the {@link com.vaadin.data.Buffered} interface. A <code>TextField</code> is
  26. * in write-through mode by default, so
  27. * {@link com.vaadin.ui.AbstractField#setWriteThrough(boolean)} must be called
  28. * to enable buffering.
  29. * </p>
  30. *
  31. * @author IT Mill Ltd.
  32. * @version
  33. * @VERSION@
  34. * @since 3.0
  35. */
  36. @SuppressWarnings("serial")
  37. @ClientWidget(value = VTextField.class, lazyLoad = false)
  38. public class TextField extends AbstractField implements
  39. FieldEvents.BlurNotifier, FieldEvents.FocusNotifier {
  40. /* Private members */
  41. /**
  42. * Value formatter used to format the string contents.
  43. */
  44. private Format format;
  45. /**
  46. * Number of visible columns in the TextField.
  47. */
  48. private int columns = 0;
  49. /**
  50. * Number of visible rows in a multiline TextField. Value 0 implies a
  51. * single-line text-editor.
  52. */
  53. private int rows = 0;
  54. /**
  55. * Tells if word-wrapping should be used in multiline mode.
  56. */
  57. private boolean wordwrap = true;
  58. /**
  59. * Tells if input is used to enter sensitive information that is not echoed
  60. * to display. Typically passwords.
  61. */
  62. private boolean secret = false;
  63. /**
  64. * Null representation.
  65. */
  66. private String nullRepresentation = "null";
  67. /**
  68. * Is setting to null from non-null value allowed by setting with null
  69. * representation .
  70. */
  71. private boolean nullSettingAllowed = false;
  72. private String inputPrompt = null;
  73. /**
  74. * Maximum character count in text field.
  75. */
  76. private int maxLength = -1;
  77. /* Constructors */
  78. /**
  79. * Constructs an empty <code>TextField</code> with no caption.
  80. */
  81. public TextField() {
  82. setValue("");
  83. }
  84. /**
  85. * Constructs an empty <code>TextField</code> with given caption.
  86. *
  87. * @param caption
  88. * the caption <code>String</code> for the editor.
  89. */
  90. public TextField(String caption) {
  91. setValue("");
  92. setCaption(caption);
  93. }
  94. /**
  95. * Constructs a new <code>TextField</code> that's bound to the specified
  96. * <code>Property</code> and has no caption.
  97. *
  98. * @param dataSource
  99. * the Property to be edited with this editor.
  100. */
  101. public TextField(Property dataSource) {
  102. setPropertyDataSource(dataSource);
  103. }
  104. /**
  105. * Constructs a new <code>TextField</code> that's bound to the specified
  106. * <code>Property</code> and has the given caption <code>String</code>.
  107. *
  108. * @param caption
  109. * the caption <code>String</code> for the editor.
  110. * @param dataSource
  111. * the Property to be edited with this editor.
  112. */
  113. public TextField(String caption, Property dataSource) {
  114. this(dataSource);
  115. setCaption(caption);
  116. }
  117. /**
  118. * Constructs a new <code>TextField</code> with the given caption and
  119. * initial text contents. The editor constructed this way will not be bound
  120. * to a Property unless
  121. * {@link com.vaadin.data.Property.Viewer#setPropertyDataSource(Property)}
  122. * is called to bind it.
  123. *
  124. * @param caption
  125. * the caption <code>String</code> for the editor.
  126. * @param text
  127. * the initial text content of the editor.
  128. */
  129. public TextField(String caption, String value) {
  130. setValue(value);
  131. setCaption(caption);
  132. }
  133. /* Component basic features */
  134. /*
  135. * Paints this component. Don't add a JavaDoc comment here, we use the
  136. * default documentation from implemented interface.
  137. */
  138. @Override
  139. public void paintContent(PaintTarget target) throws PaintException {
  140. super.paintContent(target);
  141. // Sets the secret attribute
  142. if (isSecret()) {
  143. target.addAttribute("secret", true);
  144. }
  145. if (getMaxLength() >= 0) {
  146. target.addAttribute("maxLength", getMaxLength());
  147. }
  148. if (inputPrompt != null) {
  149. target.addAttribute("prompt", inputPrompt);
  150. }
  151. // Adds the number of column and rows
  152. final int columns = getColumns();
  153. final int rows = getRows();
  154. if (columns != 0) {
  155. target.addAttribute("cols", String.valueOf(columns));
  156. }
  157. if (rows != 0) {
  158. target.addAttribute("rows", String.valueOf(rows));
  159. target.addAttribute("multiline", true);
  160. if (!wordwrap) {
  161. target.addAttribute("wordwrap", false);
  162. }
  163. }
  164. // Adds the content as variable
  165. String value = getFormattedValue();
  166. if (value == null) {
  167. value = getNullRepresentation();
  168. }
  169. if (value == null) {
  170. throw new IllegalStateException(
  171. "Null values are not allowed if the null-representation is null");
  172. }
  173. target.addVariable(this, "text", value);
  174. }
  175. /**
  176. * Gets the formatted string value. Sets the field value by using the
  177. * assigned Format.
  178. *
  179. * @return the Formatted value.
  180. * @see #setFormat(Format)
  181. * @see Format
  182. * @deprecated
  183. */
  184. @Deprecated
  185. protected String getFormattedValue() {
  186. Object v = getValue();
  187. if (v == null) {
  188. return null;
  189. }
  190. return v.toString();
  191. }
  192. /*
  193. * Gets the value of the field, but uses formatter is given. Don't add a
  194. * JavaDoc comment here, we use the default documentation from implemented
  195. * interface.
  196. */
  197. @Override
  198. public Object getValue() {
  199. Object v = super.getValue();
  200. if (format == null || v == null) {
  201. return v;
  202. }
  203. try {
  204. return format.format(v);
  205. } catch (final IllegalArgumentException e) {
  206. return v;
  207. }
  208. }
  209. /*
  210. * (non-Javadoc)
  211. *
  212. * @see com.vaadin.ui.AbstractField#changeVariables(java.lang.Object,
  213. * java.util.Map)
  214. */
  215. @Override
  216. public void changeVariables(Object source, Map<String, Object> variables) {
  217. super.changeVariables(source, variables);
  218. // Sets the text
  219. if (variables.containsKey("text") && !isReadOnly()) {
  220. // Only do the setting if the string representation of the value
  221. // has been updated
  222. String newValue = (String) variables.get("text");
  223. // server side check for max length
  224. if (getMaxLength() != -1 && newValue.length() > getMaxLength()) {
  225. newValue = newValue.substring(0, getMaxLength());
  226. }
  227. final String oldValue = getFormattedValue();
  228. if (newValue != null
  229. && (oldValue == null || isNullSettingAllowed())
  230. && newValue.equals(getNullRepresentation())) {
  231. newValue = null;
  232. }
  233. if (newValue != oldValue
  234. && (newValue == null || !newValue.equals(oldValue))) {
  235. boolean wasModified = isModified();
  236. setValue(newValue, true);
  237. // If the modified status changes, or if we have a formatter,
  238. // repaint is needed after all.
  239. if (format != null || wasModified != isModified()) {
  240. requestRepaint();
  241. }
  242. }
  243. }
  244. if (variables.containsKey(FocusEvent.EVENT_ID)) {
  245. fireEvent(new FocusEvent(this));
  246. }
  247. if (variables.containsKey(BlurEvent.EVENT_ID)) {
  248. fireEvent(new BlurEvent(this));
  249. }
  250. }
  251. /* Text field configuration */
  252. /**
  253. * Gets the number of columns in the editor. If the number of columns is set
  254. * 0, the actual number of displayed columns is determined implicitly by the
  255. * adapter.
  256. *
  257. * @return the number of columns in the editor.
  258. */
  259. public int getColumns() {
  260. return columns;
  261. }
  262. /**
  263. * Sets the number of columns in the editor. If the number of columns is set
  264. * 0, the actual number of displayed columns is determined implicitly by the
  265. * adapter.
  266. *
  267. * @param columns
  268. * the number of columns to set.
  269. */
  270. public void setColumns(int columns) {
  271. if (columns < 0) {
  272. columns = 0;
  273. }
  274. this.columns = columns;
  275. requestRepaint();
  276. }
  277. /**
  278. * Gets the number of rows in the editor. If the number of rows is set to 0,
  279. * the actual number of displayed rows is determined implicitly by the
  280. * adapter.
  281. *
  282. * @return number of explicitly set rows.
  283. */
  284. public int getRows() {
  285. return rows;
  286. }
  287. /**
  288. * Sets the number of rows in the editor.
  289. *
  290. * @param rows
  291. * the number of rows for this editor.
  292. */
  293. public void setRows(int rows) {
  294. if (rows < 0) {
  295. rows = 0;
  296. }
  297. if (this.rows != rows) {
  298. this.rows = rows;
  299. requestRepaint();
  300. }
  301. }
  302. /**
  303. * Sets the height of the {@link TextField} instance.
  304. *
  305. * <p>
  306. * Setting height for {@link TextField} also has a side-effect that puts
  307. * {@link TextField} into multiline mode (aka "textarea"). Multiline mode
  308. * can also be achieved by calling {@link #setRows(int)}. The height value
  309. * overrides the number of rows set by {@link #setRows(int)}.
  310. * <p>
  311. * If you want to set height of single line {@link TextField}, call
  312. * {@link #setRows(int)} with value 0 after setting the height. Setting rows
  313. * to 0 resets the side-effect.
  314. *
  315. * @see com.vaadin.ui.AbstractComponent#setHeight(float, int)
  316. */
  317. @Override
  318. public void setHeight(float height, int unit) {
  319. super.setHeight(height, unit);
  320. if (height > 1) {
  321. /*
  322. * In html based terminals we most commonly want to make component
  323. * to be textarea if height is defined. Setting row field above 0
  324. * will render component as textarea.
  325. */
  326. rows = 2;
  327. }
  328. }
  329. /**
  330. * Sets the height of the {@link TextField} instance.
  331. *
  332. * <p>
  333. * Setting height for {@link TextField} also has a side-effect that puts
  334. * {@link TextField} into multiline mode (aka "textarea"). Multiline mode
  335. * can also be achieved by calling {@link #setRows(int)}. The height value
  336. * overrides the number of rows set by {@link #setRows(int)}.
  337. * <p>
  338. * If you want to set height of single line {@link TextField}, call
  339. * {@link #setRows(int)} with value 0 after setting the height. Setting rows
  340. * to 0 resets the side-effect.
  341. *
  342. * @see com.vaadin.ui.AbstractComponent#setHeight(java.lang.String)
  343. */
  344. @Override
  345. public void setHeight(String height) {
  346. // will call setHeight(float, int) the actually does the magic. Method
  347. // is overridden just to document side-effects.
  348. super.setHeight(height);
  349. }
  350. /**
  351. * Tests if the editor is in word-wrap mode.
  352. *
  353. * @return <code>true</code> if the component is in the word-wrap mode,
  354. * <code>false</code> if not.
  355. */
  356. public boolean isWordwrap() {
  357. return wordwrap;
  358. }
  359. /**
  360. * Sets the editor's word-wrap mode on or off.
  361. *
  362. * @param wordwrap
  363. * the boolean value specifying if the editor should be in
  364. * word-wrap mode after the call or not.
  365. */
  366. public void setWordwrap(boolean wordwrap) {
  367. if (this.wordwrap != wordwrap) {
  368. this.wordwrap = wordwrap;
  369. requestRepaint();
  370. }
  371. }
  372. /* Property features */
  373. /*
  374. * Gets the edited property's type. Don't add a JavaDoc comment here, we use
  375. * the default documentation from implemented interface.
  376. */
  377. @Override
  378. public Class getType() {
  379. return String.class;
  380. }
  381. /**
  382. * Gets the secret property on and off. If a field is used to enter
  383. * secretinformation the information is not echoed to display.
  384. *
  385. * @return <code>true</code> if the field is used to enter secret
  386. * information, <code>false</code> otherwise.
  387. */
  388. public boolean isSecret() {
  389. return secret;
  390. }
  391. /**
  392. * Sets the secret property on and off. If a field is used to enter
  393. * secretinformation the information is not echoed to display.
  394. *
  395. * @param secret
  396. * the value specifying if the field is used to enter secret
  397. * information.
  398. */
  399. public void setSecret(boolean secret) {
  400. if (this.secret != secret) {
  401. this.secret = secret;
  402. requestRepaint();
  403. }
  404. }
  405. /**
  406. * Gets the null-string representation.
  407. *
  408. * <p>
  409. * The null-valued strings are represented on the user interface by
  410. * replacing the null value with this string. If the null representation is
  411. * set null (not 'null' string), painting null value throws exception.
  412. * </p>
  413. *
  414. * <p>
  415. * The default value is string 'null'.
  416. * </p>
  417. *
  418. * @return the String Textual representation for null strings.
  419. * @see TextField#isNullSettingAllowed()
  420. */
  421. public String getNullRepresentation() {
  422. return nullRepresentation;
  423. }
  424. /**
  425. * Is setting nulls with null-string representation allowed.
  426. *
  427. * <p>
  428. * If this property is true, writing null-representation string to text
  429. * field always sets the field value to real null. If this property is
  430. * false, null setting is not made, but the null values are maintained.
  431. * Maintenance of null-values is made by only converting the textfield
  432. * contents to real null, if the text field matches the null-string
  433. * representation and the current value of the field is null.
  434. * </p>
  435. *
  436. * <p>
  437. * By default this setting is false
  438. * </p>
  439. *
  440. * @return boolean Should the null-string represenation be always converted
  441. * to null-values.
  442. * @see TextField#getNullRepresentation()
  443. */
  444. public boolean isNullSettingAllowed() {
  445. return nullSettingAllowed;
  446. }
  447. /**
  448. * Sets the null-string representation.
  449. *
  450. * <p>
  451. * The null-valued strings are represented on the user interface by
  452. * replacing the null value with this string. If the null representation is
  453. * set null (not 'null' string), painting null value throws exception.
  454. * </p>
  455. *
  456. * <p>
  457. * The default value is string 'null'
  458. * </p>
  459. *
  460. * @param nullRepresentation
  461. * Textual representation for null strings.
  462. * @see TextField#setNullSettingAllowed(boolean)
  463. */
  464. public void setNullRepresentation(String nullRepresentation) {
  465. this.nullRepresentation = nullRepresentation;
  466. }
  467. /**
  468. * Sets the null conversion mode.
  469. *
  470. * <p>
  471. * If this property is true, writing null-representation string to text
  472. * field always sets the field value to real null. If this property is
  473. * false, null setting is not made, but the null values are maintained.
  474. * Maintenance of null-values is made by only converting the textfield
  475. * contents to real null, if the text field matches the null-string
  476. * representation and the current value of the field is null.
  477. * </p>
  478. *
  479. * <p>
  480. * By default this setting is false.
  481. * </p>
  482. *
  483. * @param nullSettingAllowed
  484. * Should the null-string represenation be always converted to
  485. * null-values.
  486. * @see TextField#getNullRepresentation()
  487. */
  488. public void setNullSettingAllowed(boolean nullSettingAllowed) {
  489. this.nullSettingAllowed = nullSettingAllowed;
  490. }
  491. /**
  492. * Gets the current input prompt.
  493. *
  494. * @see #setInputPrompt(String)
  495. * @return the current input prompt, or null if not enabled
  496. */
  497. public String getInputPrompt() {
  498. return inputPrompt;
  499. }
  500. /**
  501. * Sets the input prompt - a textual prompt that is displayed when the field
  502. * would otherwise be empty, to prompt the user for input.
  503. *
  504. * @param inputPrompt
  505. */
  506. public void setInputPrompt(String inputPrompt) {
  507. this.inputPrompt = inputPrompt;
  508. requestRepaint();
  509. }
  510. /**
  511. * Gets the value formatter of TextField.
  512. *
  513. * @return the Format used to format the value.
  514. * @deprecated replaced by {@link com.vaadin.data.util.PropertyFormatter}
  515. */
  516. @Deprecated
  517. public Format getFormat() {
  518. return format;
  519. }
  520. /**
  521. * Gets the value formatter of TextField.
  522. *
  523. * @param format
  524. * the Format used to format the value. Null disables the
  525. * formatting.
  526. * @deprecated replaced by {@link com.vaadin.data.util.PropertyFormatter}
  527. */
  528. @Deprecated
  529. public void setFormat(Format format) {
  530. this.format = format;
  531. requestRepaint();
  532. }
  533. @Override
  534. protected boolean isEmpty() {
  535. return super.isEmpty() || toString().length() == 0;
  536. }
  537. /**
  538. * Returns the maximum number of characters in the field. Value -1 is
  539. * considered unlimited. Terminal may however have some technical limits.
  540. *
  541. * @return the maxLength
  542. */
  543. public int getMaxLength() {
  544. return maxLength;
  545. }
  546. /**
  547. * Sets the maximum number of characters in the field. Value -1 is
  548. * considered unlimited. Terminal may however have some technical limits.
  549. *
  550. * @param maxLength
  551. * the maxLength to set
  552. */
  553. public void setMaxLength(int maxLength) {
  554. this.maxLength = maxLength;
  555. requestRepaint();
  556. }
  557. public void addListener(FocusListener listener) {
  558. addListener(FocusEvent.EVENT_ID, FocusEvent.class, listener,
  559. FocusListener.focusMethod);
  560. }
  561. public void removeListener(FocusListener listener) {
  562. removeListener(FocusEvent.EVENT_ID, FocusEvent.class, listener);
  563. }
  564. public void addListener(BlurListener listener) {
  565. addListener(BlurEvent.EVENT_ID, BlurEvent.class, listener,
  566. BlurListener.blurMethod);
  567. }
  568. public void removeListener(BlurListener listener) {
  569. removeListener(BlurEvent.EVENT_ID, BlurEvent.class, listener);
  570. }
  571. }