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

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610
  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.BlurEvent;
  9. import com.vaadin.event.FieldEvents.BlurListener;
  10. import com.vaadin.event.FieldEvents.FocusEvent;
  11. import com.vaadin.event.FieldEvents.FocusListener;
  12. import com.vaadin.terminal.PaintException;
  13. import com.vaadin.terminal.PaintTarget;
  14. import com.vaadin.terminal.gwt.client.ui.VTextField;
  15. /**
  16. * <p>
  17. * A text editor component that can be bound to any bindable Property. The text
  18. * editor supports both multiline and single line modes, default is one-line
  19. * mode.
  20. * </p>
  21. *
  22. * <p>
  23. * Since <code>TextField</code> extends <code>AbstractField</code> it implements
  24. * the {@link com.vaadin.data.Buffered} interface. A <code>TextField</code> is
  25. * in write-through mode by default, so
  26. * {@link com.vaadin.ui.AbstractField#setWriteThrough(boolean)} must be called
  27. * to enable buffering.
  28. * </p>
  29. *
  30. * @author IT Mill Ltd.
  31. * @version
  32. * @VERSION@
  33. * @since 3.0
  34. */
  35. @SuppressWarnings("serial")
  36. @ClientWidget(VTextField.class)
  37. public class TextField extends AbstractField {
  38. /* Private members */
  39. /**
  40. * Value formatter used to format the string contents.
  41. */
  42. private Format format;
  43. /**
  44. * Number of visible columns in the TextField.
  45. */
  46. private int columns = 0;
  47. /**
  48. * Number of visible rows in a multiline TextField. Value 0 implies a
  49. * single-line text-editor.
  50. */
  51. private int rows = 0;
  52. /**
  53. * Tells if word-wrapping should be used in multiline mode.
  54. */
  55. private boolean wordwrap = true;
  56. /**
  57. * Tells if input is used to enter sensitive information that is not echoed
  58. * to display. Typically passwords.
  59. */
  60. private boolean secret = false;
  61. /**
  62. * Null representation.
  63. */
  64. private String nullRepresentation = "null";
  65. /**
  66. * Is setting to null from non-null value allowed by setting with null
  67. * representation .
  68. */
  69. private boolean nullSettingAllowed = false;
  70. private String inputPrompt = null;
  71. /**
  72. * Maximum character count in text field.
  73. */
  74. private int maxLength = -1;
  75. private static final String BLUR_EVENT = VTextField.BLUR_EVENT_IDENTIFIER;
  76. private static final String FOCUS_EVENT = VTextField.FOCUS_EVENT_IDENTIFIER;
  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 c = getColumns();
  153. final int r = getRows();
  154. if (c != 0) {
  155. target.addAttribute("cols", String.valueOf(c));
  156. }
  157. if (r != 0) {
  158. target.addAttribute("rows", String.valueOf(r));
  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 variables) {
  217. super.changeVariables(source, variables);
  218. if (variables.containsKey(FOCUS_EVENT)) {
  219. fireFocus(variables.get(FOCUS_EVENT));
  220. }
  221. if (variables.containsKey(BLUR_EVENT)) {
  222. fireBlur(variables.get(BLUR_EVENT));
  223. }
  224. // Sets the text
  225. if (variables.containsKey("text") && !isReadOnly()) {
  226. // Only do the setting if the string representation of the value
  227. // has been updated
  228. String newValue = (String) variables.get("text");
  229. // server side check for max length
  230. if (getMaxLength() != -1 && newValue.length() > getMaxLength()) {
  231. newValue = newValue.substring(0, getMaxLength());
  232. }
  233. final String oldValue = getFormattedValue();
  234. if (newValue != null
  235. && (oldValue == null || isNullSettingAllowed())
  236. && newValue.equals(getNullRepresentation())) {
  237. newValue = null;
  238. }
  239. if (newValue != oldValue
  240. && (newValue == null || !newValue.equals(oldValue))) {
  241. boolean wasModified = isModified();
  242. setValue(newValue, true);
  243. // If the modified status changes, or if we have a formatter,
  244. // repaint is needed after all.
  245. if (format != null || wasModified != isModified()) {
  246. requestRepaint();
  247. }
  248. }
  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. If the number of rows is set to 0,
  289. * the actual number of displayed rows is determined implicitly by the
  290. * adapter.
  291. *
  292. * @param rows
  293. * the number of rows for this editor.
  294. */
  295. public void setRows(int rows) {
  296. if (rows < 0) {
  297. rows = 0;
  298. }
  299. this.rows = rows;
  300. requestRepaint();
  301. }
  302. /**
  303. * Tests if the editor is in word-wrap mode.
  304. *
  305. * @return <code>true</code> if the component is in the word-wrap mode,
  306. * <code>false</code> if not.
  307. */
  308. public boolean isWordwrap() {
  309. return wordwrap;
  310. }
  311. /**
  312. * Sets the editor's word-wrap mode on or off.
  313. *
  314. * @param wordwrap
  315. * the boolean value specifying if the editor should be in
  316. * word-wrap mode after the call or not.
  317. */
  318. public void setWordwrap(boolean wordwrap) {
  319. this.wordwrap = wordwrap;
  320. }
  321. /* Property features */
  322. /*
  323. * Gets the edited property's type. Don't add a JavaDoc comment here, we use
  324. * the default documentation from implemented interface.
  325. */
  326. @Override
  327. public Class getType() {
  328. return String.class;
  329. }
  330. /**
  331. * Gets the secret property on and off. If a field is used to enter
  332. * secretinformation the information is not echoed to display.
  333. *
  334. * @return <code>true</code> if the field is used to enter secret
  335. * information, <code>false</code> otherwise.
  336. */
  337. public boolean isSecret() {
  338. return secret;
  339. }
  340. /**
  341. * Sets the secret property on and off. If a field is used to enter
  342. * secretinformation the information is not echoed to display.
  343. *
  344. * @param secret
  345. * the value specifying if the field is used to enter secret
  346. * information.
  347. */
  348. public void setSecret(boolean secret) {
  349. this.secret = secret;
  350. requestRepaint();
  351. }
  352. /**
  353. * Gets the null-string representation.
  354. *
  355. * <p>
  356. * The null-valued strings are represented on the user interface by
  357. * replacing the null value with this string. If the null representation is
  358. * set null (not 'null' string), painting null value throws exception.
  359. * </p>
  360. *
  361. * <p>
  362. * The default value is string 'null'.
  363. * </p>
  364. *
  365. * @return the String Textual representation for null strings.
  366. * @see TextField#isNullSettingAllowed()
  367. */
  368. public String getNullRepresentation() {
  369. return nullRepresentation;
  370. }
  371. /**
  372. * Is setting nulls with null-string representation allowed.
  373. *
  374. * <p>
  375. * If this property is true, writing null-representation string to text
  376. * field always sets the field value to real null. If this property is
  377. * false, null setting is not made, but the null values are maintained.
  378. * Maintenance of null-values is made by only converting the textfield
  379. * contents to real null, if the text field matches the null-string
  380. * representation and the current value of the field is null.
  381. * </p>
  382. *
  383. * <p>
  384. * By default this setting is false
  385. * </p>
  386. *
  387. * @return boolean Should the null-string represenation be always converted
  388. * to null-values.
  389. * @see TextField#getNullRepresentation()
  390. */
  391. public boolean isNullSettingAllowed() {
  392. return nullSettingAllowed;
  393. }
  394. /**
  395. * Sets the null-string representation.
  396. *
  397. * <p>
  398. * The null-valued strings are represented on the user interface by
  399. * replacing the null value with this string. If the null representation is
  400. * set null (not 'null' string), painting null value throws exception.
  401. * </p>
  402. *
  403. * <p>
  404. * The default value is string 'null'
  405. * </p>
  406. *
  407. * @param nullRepresentation
  408. * Textual representation for null strings.
  409. * @see TextField#setNullSettingAllowed(boolean)
  410. */
  411. public void setNullRepresentation(String nullRepresentation) {
  412. this.nullRepresentation = nullRepresentation;
  413. }
  414. /**
  415. * Sets the null conversion mode.
  416. *
  417. * <p>
  418. * If this property is true, writing null-representation string to text
  419. * field always sets the field value to real null. If this property is
  420. * false, null setting is not made, but the null values are maintained.
  421. * Maintenance of null-values is made by only converting the textfield
  422. * contents to real null, if the text field matches the null-string
  423. * representation and the current value of the field is null.
  424. * </p>
  425. *
  426. * <p>
  427. * By default this setting is false.
  428. * </p>
  429. *
  430. * @param nullSettingAllowed
  431. * Should the null-string represenation be always converted to
  432. * null-values.
  433. * @see TextField#getNullRepresentation()
  434. */
  435. public void setNullSettingAllowed(boolean nullSettingAllowed) {
  436. this.nullSettingAllowed = nullSettingAllowed;
  437. }
  438. /**
  439. * Gets the current input prompt.
  440. *
  441. * @see #setInputPrompt(String)
  442. * @return the current input prompt, or null if not enabled
  443. */
  444. public String getInputPrompt() {
  445. return inputPrompt;
  446. }
  447. /**
  448. * Sets the input prompt - a textual prompt that is displayed when the field
  449. * would otherwise be empty, to prompt the user for input.
  450. *
  451. * @param inputPrompt
  452. */
  453. public void setInputPrompt(String inputPrompt) {
  454. this.inputPrompt = inputPrompt;
  455. }
  456. /**
  457. * Gets the value formatter of TextField.
  458. *
  459. * @return the Format used to format the value.
  460. * @deprecated replaced by {@link com.vaadin.data.util.PropertyFormatter}
  461. */
  462. @Deprecated
  463. public Format getFormat() {
  464. return format;
  465. }
  466. /**
  467. * Gets the value formatter of TextField.
  468. *
  469. * @param format
  470. * the Format used to format the value. Null disables the
  471. * formatting.
  472. * @deprecated replaced by {@link com.vaadin.data.util.PropertyFormatter}
  473. */
  474. @Deprecated
  475. public void setFormat(Format format) {
  476. this.format = format;
  477. requestRepaint();
  478. }
  479. @Override
  480. protected boolean isEmpty() {
  481. return super.isEmpty() || toString().length() == 0;
  482. }
  483. /**
  484. * Returns the maximum number of characters in the field. Value -1 is
  485. * considered unlimited. Terminal may however have some technical limits.
  486. *
  487. * @return the maxLength
  488. */
  489. public int getMaxLength() {
  490. return maxLength;
  491. }
  492. /**
  493. * Sets the maximum number of characters in the field. Value -1 is
  494. * considered unlimited. Terminal may however have some technical limits.
  495. *
  496. * @param maxLength
  497. * the maxLength to set
  498. */
  499. public void setMaxLength(int maxLength) {
  500. this.maxLength = maxLength;
  501. requestRepaint();
  502. }
  503. private void fireFocus(Object object) {
  504. fireEvent(new FocusEvent(this));
  505. }
  506. private void fireBlur(Object object) {
  507. fireEvent(new BlurEvent(this));
  508. }
  509. /**
  510. * TODO
  511. *
  512. * @param listener
  513. */
  514. public void addListener(FocusListener listener) {
  515. addListener(FOCUS_EVENT, FocusEvent.class, listener,
  516. FocusListener.focusMethod);
  517. }
  518. /**
  519. * TODO
  520. *
  521. * @param listener
  522. */
  523. public void removeListener(FocusListener listener) {
  524. removeListener(FOCUS_EVENT, FocusEvent.class, listener);
  525. }
  526. /**
  527. * TODO
  528. *
  529. * @param listener
  530. */
  531. public void addListener(BlurListener listener) {
  532. addListener(BLUR_EVENT, BlurEvent.class, listener,
  533. BlurListener.blurMethod);
  534. }
  535. /**
  536. * TODO
  537. *
  538. * @param listener
  539. */
  540. public void removeListener(BlurListener listener) {
  541. removeListener(BLUR_EVENT, BlurEvent.class, listener);
  542. }
  543. }