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.

AbstractField.java 7.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. /*
  2. * Copyright 2000-2018 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 org.jsoup.nodes.Attributes;
  20. import org.jsoup.nodes.Element;
  21. import com.vaadin.data.HasValue;
  22. import com.vaadin.shared.AbstractFieldState;
  23. import com.vaadin.shared.Registration;
  24. import com.vaadin.ui.Component.Focusable;
  25. import com.vaadin.ui.declarative.DesignAttributeHandler;
  26. import com.vaadin.ui.declarative.DesignContext;
  27. /**
  28. * An abstract implementation of a field, or a {@code Component} allowing user
  29. * input. Implements {@link HasValue} to represent the input value. Examples of
  30. * typical field components include text fields, date pickers, and check boxes.
  31. * <p>
  32. * This class replaces the Vaadin 7 {@code com.vaadin.ui.AbstractField} class.
  33. * The old {@code AbstractField} is retained, under the new name
  34. * {@link com.vaadin.v7.ui.AbstractField}, for compatibility and migration
  35. * purposes.
  36. *
  37. * @author Vaadin Ltd.
  38. * @since 8.0
  39. *
  40. * @param <T>
  41. * the input value type
  42. */
  43. public abstract class AbstractField<T> extends AbstractComponent
  44. implements HasValue<T>, Focusable {
  45. @Override
  46. public void setValue(T value) {
  47. setValue(value, false);
  48. }
  49. @Override
  50. public boolean isReadOnly() {
  51. return super.isReadOnly();
  52. }
  53. /**
  54. * {@inheritDoc}
  55. * <p>
  56. * The server ignores (potentially forged) value change requests from the
  57. * client to fields that are read-only. Programmatically changing the field
  58. * value via {@link #setValue(T)} is still possible.
  59. * <p>
  60. * The read-only mode is distinct from the
  61. * {@linkplain Component#setEnabled(boolean) disabled} state. When disabled,
  62. * a component cannot be interacted with at all, and its content should be
  63. * considered irrelevant or not applicable. In contrast, the user should
  64. * still be able to read the content and otherwise interact with a read-only
  65. * field even though changing the value is disallowed.
  66. *
  67. * @param readOnly
  68. * {@code true} to set read-only mode, {@code false} otherwise.
  69. */
  70. @Override
  71. public void setReadOnly(boolean readOnly) {
  72. super.setReadOnly(readOnly);
  73. }
  74. @Override
  75. public Registration addValueChangeListener(
  76. ValueChangeListener<T> listener) {
  77. return addListener(ValueChangeEvent.class, listener,
  78. ValueChangeListener.VALUE_CHANGE_METHOD);
  79. }
  80. @Override
  81. public void readDesign(Element design, DesignContext designContext) {
  82. super.readDesign(design, designContext);
  83. Attributes attr = design.attributes();
  84. if (attr.hasKey("readonly")) {
  85. setReadOnly(DesignAttributeHandler.readAttribute("readonly", attr,
  86. Boolean.class));
  87. }
  88. }
  89. @Override
  90. public void writeDesign(Element design, DesignContext designContext) {
  91. super.writeDesign(design, designContext);
  92. AbstractField<T> def = designContext.getDefaultInstance(this);
  93. Attributes attr = design.attributes();
  94. DesignAttributeHandler.writeAttribute("readonly", attr, isReadOnly(),
  95. def.isReadOnly(), Boolean.class, designContext);
  96. }
  97. @Override
  98. protected Collection<String> getCustomAttributes() {
  99. Collection<String> attributes = super.getCustomAttributes();
  100. attributes.add("readonly");
  101. // must be handled by subclasses
  102. attributes.add("value");
  103. return attributes;
  104. }
  105. /**
  106. * Sets the value of this field if it has changed and fires a value change
  107. * event. If the value originates from the client and this field is
  108. * read-only, does nothing. Invokes {@link #doSetValue(Object) doSetValue}
  109. * to actually store the value.
  110. *
  111. * @param value
  112. * the new value to set
  113. * @param userOriginated
  114. * {@code true} if this event originates from the client,
  115. * {@code false} otherwise.
  116. * @return <code>true</code> if the value was updated, <code>false</code>
  117. * otherwise
  118. */
  119. protected boolean setValue(T value, boolean userOriginated) {
  120. if (userOriginated && isReadOnly()) {
  121. return false;
  122. }
  123. if (!isDifferentValue(value)) {
  124. return false;
  125. }
  126. T oldValue = this.getValue();
  127. doSetValue(value);
  128. if (!userOriginated) {
  129. markAsDirty();
  130. }
  131. fireEvent(createValueChange(oldValue, userOriginated));
  132. return true;
  133. }
  134. /**
  135. * Called when a new value is set to determine whether the provided new
  136. * value is considered to be a change compared to the current value. This is
  137. * used to determine whether {@link #doSetValue(Object)} should be called
  138. * and a value change event fired.
  139. *
  140. * @param newValue
  141. * the new value candidate to check, may be <code>null</code>
  142. *
  143. * @return <code>true</code> if the provided value is considered to be
  144. * different and a value change event should be fired;
  145. * <code>false</code> if the values are considered to be the same
  146. * and no value change should be fired
  147. */
  148. protected boolean isDifferentValue(T newValue) {
  149. return !Objects.equals(newValue, getValue());
  150. }
  151. /**
  152. * Sets the value of this field. May do sanitization or throw
  153. * {@code IllegalArgumentException} if the value is invalid. Typically saves
  154. * the value to shared state.
  155. *
  156. * @param value
  157. * the new value of the field
  158. * @throws IllegalArgumentException
  159. * if the value is invalid
  160. */
  161. protected abstract void doSetValue(T value);
  162. /**
  163. * Returns a new value change event instance.
  164. *
  165. * @param oldValue
  166. * the value of this field before this value change event
  167. * @param userOriginated
  168. * {@code true} if this event originates from the client,
  169. * {@code false} otherwise.
  170. * @return the new event
  171. */
  172. protected ValueChangeEvent<T> createValueChange(T oldValue,
  173. boolean userOriginated) {
  174. return new ValueChangeEvent<>(this, oldValue, userOriginated);
  175. }
  176. @Override
  177. protected AbstractFieldState getState() {
  178. return (AbstractFieldState) super.getState();
  179. }
  180. @Override
  181. protected AbstractFieldState getState(boolean markAsDirty) {
  182. return (AbstractFieldState) super.getState(markAsDirty);
  183. }
  184. @Override
  185. public void focus() {
  186. super.focus();
  187. }
  188. @Override
  189. public int getTabIndex() {
  190. return getState(false).tabIndex;
  191. }
  192. @Override
  193. public void setTabIndex(int tabIndex) {
  194. getState().tabIndex = tabIndex;
  195. }
  196. @Override
  197. public void setRequiredIndicatorVisible(boolean visible) {
  198. super.setRequiredIndicatorVisible(visible);
  199. }
  200. @Override
  201. public boolean isRequiredIndicatorVisible() {
  202. return super.isRequiredIndicatorVisible();
  203. }
  204. }