Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

PropertyFormatter.java 7.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. /*
  2. @VaadinApache2LicenseForJavaFiles@
  3. */
  4. package com.vaadin.data.util;
  5. import com.vaadin.data.Property;
  6. /**
  7. * Formatting proxy for a {@link Property}.
  8. *
  9. * <p>
  10. * This class can be used to implement formatting for any type of Property
  11. * datasources. The idea is to connect this as proxy between UI component and
  12. * the original datasource.
  13. * </p>
  14. *
  15. * <p>
  16. * For example <code>
  17. * <pre>textfield.setPropertyDataSource(new PropertyFormatter(property) {
  18. public String format(Object value) {
  19. return ((Double) value).toString() + "000000000";
  20. }
  21. public Object parse(String formattedValue) throws Exception {
  22. return Double.parseDouble(formattedValue);
  23. }
  24. });</pre></code> adds formatter for Double-typed property that extends
  25. * standard "1.0" notation with more zeroes.
  26. * </p>
  27. *
  28. * @author Vaadin Ltd.
  29. * @since 5.3.0
  30. */
  31. @SuppressWarnings("serial")
  32. public abstract class PropertyFormatter extends AbstractProperty implements
  33. Property.Viewer, Property.ValueChangeListener,
  34. Property.ReadOnlyStatusChangeListener {
  35. /** Datasource that stores the actual value. */
  36. Property dataSource;
  37. /**
  38. * Construct a new {@code PropertyFormatter} that is not connected to any
  39. * data source. Call {@link #setPropertyDataSource(Property)} later on to
  40. * attach it to a property.
  41. *
  42. */
  43. protected PropertyFormatter() {
  44. }
  45. /**
  46. * Construct a new formatter that is connected to given data source. Calls
  47. * {@link #format(Object)} which can be a problem if the formatter has not
  48. * yet been initialized.
  49. *
  50. * @param propertyDataSource
  51. * to connect this property to.
  52. */
  53. public PropertyFormatter(Property propertyDataSource) {
  54. setPropertyDataSource(propertyDataSource);
  55. }
  56. /**
  57. * Gets the current data source of the formatter, if any.
  58. *
  59. * @return the current data source as a Property, or <code>null</code> if
  60. * none defined.
  61. */
  62. public Property getPropertyDataSource() {
  63. return dataSource;
  64. }
  65. /**
  66. * Sets the specified Property as the data source for the formatter.
  67. *
  68. *
  69. * <p>
  70. * Remember that new data sources getValue() must return objects that are
  71. * compatible with parse() and format() methods.
  72. * </p>
  73. *
  74. * @param newDataSource
  75. * the new data source Property.
  76. */
  77. public void setPropertyDataSource(Property newDataSource) {
  78. boolean readOnly = false;
  79. String prevValue = null;
  80. if (dataSource != null) {
  81. if (dataSource instanceof Property.ValueChangeNotifier) {
  82. ((Property.ValueChangeNotifier) dataSource)
  83. .removeListener(this);
  84. }
  85. if (dataSource instanceof Property.ReadOnlyStatusChangeListener) {
  86. ((Property.ReadOnlyStatusChangeNotifier) dataSource)
  87. .removeListener(this);
  88. }
  89. readOnly = isReadOnly();
  90. prevValue = toString();
  91. }
  92. dataSource = newDataSource;
  93. if (dataSource != null) {
  94. if (dataSource instanceof Property.ValueChangeNotifier) {
  95. ((Property.ValueChangeNotifier) dataSource).addListener(this);
  96. }
  97. if (dataSource instanceof Property.ReadOnlyStatusChangeListener) {
  98. ((Property.ReadOnlyStatusChangeNotifier) dataSource)
  99. .addListener(this);
  100. }
  101. }
  102. if (isReadOnly() != readOnly) {
  103. fireReadOnlyStatusChange();
  104. }
  105. String newVal = toString();
  106. if ((prevValue == null && newVal != null)
  107. || (prevValue != null && !prevValue.equals(newVal))) {
  108. fireValueChange();
  109. }
  110. }
  111. /* Documented in the interface */
  112. public Class getType() {
  113. return String.class;
  114. }
  115. /**
  116. * Get the formatted value.
  117. *
  118. * @return If the datasource returns null, this is null. Otherwise this is
  119. * String given by format().
  120. */
  121. public Object getValue() {
  122. return toString();
  123. }
  124. /**
  125. * Get the formatted value.
  126. *
  127. * @return If the datasource returns null, this is null. Otherwise this is
  128. * String given by format().
  129. */
  130. @Override
  131. public String toString() {
  132. if (dataSource == null) {
  133. return null;
  134. }
  135. Object value = dataSource.getValue();
  136. if (value == null) {
  137. return null;
  138. }
  139. return format(value);
  140. }
  141. /** Reflects the read-only status of the datasource. */
  142. @Override
  143. public boolean isReadOnly() {
  144. return dataSource == null ? false : dataSource.isReadOnly();
  145. }
  146. /**
  147. * This method must be implemented to format the values received from
  148. * DataSource.
  149. *
  150. * @param value
  151. * Value object got from the datasource. This is guaranteed to be
  152. * non-null and of the type compatible with getType() of the
  153. * datasource.
  154. * @return
  155. */
  156. abstract public String format(Object value);
  157. /**
  158. * Parse string and convert it to format compatible with datasource.
  159. *
  160. * The method is required to assure that parse(format(x)) equals x.
  161. *
  162. * @param formattedValue
  163. * This is guaranteed to be non-null string.
  164. * @return Non-null value compatible with datasource.
  165. * @throws Exception
  166. * Any type of exception can be thrown to indicate that the
  167. * conversion was not succesful.
  168. */
  169. abstract public Object parse(String formattedValue) throws Exception;
  170. /**
  171. * Sets the Property's read-only mode to the specified status.
  172. *
  173. * @param newStatus
  174. * the new read-only status of the Property.
  175. */
  176. @Override
  177. public void setReadOnly(boolean newStatus) {
  178. if (dataSource != null) {
  179. dataSource.setReadOnly(newStatus);
  180. }
  181. }
  182. public void setValue(Object newValue) throws ReadOnlyException,
  183. ConversionException {
  184. if (dataSource == null) {
  185. return;
  186. }
  187. if (newValue == null) {
  188. if (dataSource.getValue() != null) {
  189. dataSource.setValue(null);
  190. fireValueChange();
  191. }
  192. } else {
  193. try {
  194. dataSource.setValue(parse(newValue.toString()));
  195. if (!newValue.equals(toString())) {
  196. fireValueChange();
  197. }
  198. } catch (ConversionException e) {
  199. throw e;
  200. } catch (Exception e) {
  201. throw new ConversionException(e);
  202. }
  203. }
  204. }
  205. /**
  206. * Listens for changes in the datasource.
  207. *
  208. * This should not be called directly.
  209. */
  210. public void valueChange(com.vaadin.data.Property.ValueChangeEvent event) {
  211. fireValueChange();
  212. }
  213. /**
  214. * Listens for changes in the datasource.
  215. *
  216. * This should not be called directly.
  217. */
  218. public void readOnlyStatusChange(
  219. com.vaadin.data.Property.ReadOnlyStatusChangeEvent event) {
  220. fireReadOnlyStatusChange();
  221. }
  222. }