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.

CheckBoxGroup.java 8.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  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 java.util.Set;
  20. import org.jsoup.nodes.Element;
  21. import com.vaadin.data.HasDataProvider;
  22. import com.vaadin.data.provider.DataProvider;
  23. import com.vaadin.event.FieldEvents.BlurEvent;
  24. import com.vaadin.event.FieldEvents.BlurListener;
  25. import com.vaadin.event.FieldEvents.BlurNotifier;
  26. import com.vaadin.event.FieldEvents.FocusAndBlurServerRpcDecorator;
  27. import com.vaadin.event.FieldEvents.FocusEvent;
  28. import com.vaadin.event.FieldEvents.FocusListener;
  29. import com.vaadin.event.FieldEvents.FocusNotifier;
  30. import com.vaadin.server.SerializablePredicate;
  31. import com.vaadin.shared.Registration;
  32. import com.vaadin.shared.ui.ListingJsonConstants;
  33. import com.vaadin.shared.ui.optiongroup.CheckBoxGroupState;
  34. import com.vaadin.ui.declarative.DesignContext;
  35. import com.vaadin.ui.declarative.DesignFormatter;
  36. /**
  37. * A group of Checkboxes. Individual checkboxes are made from items supplied by
  38. * a {@link DataProvider}. Checkboxes may have captions and icons.
  39. *
  40. * @param <T>
  41. * item type
  42. * @author Vaadin Ltd
  43. * @since 8.0
  44. */
  45. public class CheckBoxGroup<T> extends AbstractMultiSelect<T>
  46. implements FocusNotifier, BlurNotifier, HasDataProvider<T> {
  47. private DescriptionGenerator<T> descriptionGenerator = item -> null;
  48. /**
  49. * Constructs a new CheckBoxGroup with caption.
  50. *
  51. * @param caption
  52. * caption text
  53. */
  54. public CheckBoxGroup(String caption) {
  55. this();
  56. setCaption(caption);
  57. }
  58. /**
  59. * Constructs a new CheckBoxGroup with caption and DataProvider.
  60. *
  61. * @param caption
  62. * the caption text
  63. * @param dataProvider
  64. * the data provider, not null
  65. * @see HasDataProvider#setDataProvider(DataProvider)
  66. */
  67. public CheckBoxGroup(String caption, DataProvider<T, ?> dataProvider) {
  68. this(caption);
  69. setDataProvider(dataProvider);
  70. }
  71. /**
  72. * Constructs a new CheckBoxGroup with caption and DataProvider containing
  73. * given items.
  74. *
  75. * @param caption
  76. * the caption text
  77. * @param items
  78. * the data items to use, not null
  79. * @see #setItems(Collection)
  80. */
  81. public CheckBoxGroup(String caption, Collection<T> items) {
  82. this(caption, DataProvider.ofCollection(items));
  83. }
  84. /**
  85. * Constructs a new CheckBoxGroup.
  86. */
  87. public CheckBoxGroup() {
  88. registerRpc(new FocusAndBlurServerRpcDecorator(this, this::fireEvent));
  89. addDataGenerator((item, jsonObject) -> {
  90. String description = getItemDescriptionGenerator().apply(item);
  91. if (description != null) {
  92. jsonObject.put(ListingJsonConstants.JSONKEY_ITEM_DESCRIPTION,
  93. description);
  94. }
  95. });
  96. }
  97. /**
  98. * Sets whether html is allowed in the item captions. If set to true, the
  99. * captions are passed to the browser as html and the developer is
  100. * responsible for ensuring no harmful html is used. If set to false, the
  101. * content is passed to the browser as plain text.
  102. *
  103. * @param htmlContentAllowed
  104. * true if the captions are used as html, false if used as plain
  105. * text
  106. */
  107. public void setHtmlContentAllowed(boolean htmlContentAllowed) {
  108. getState().htmlContentAllowed = htmlContentAllowed;
  109. }
  110. /**
  111. * Checks whether captions are interpreted as html or plain text.
  112. *
  113. * @return true if the captions are used as html, false if used as plain
  114. * text
  115. * @see #setHtmlContentAllowed(boolean)
  116. */
  117. public boolean isHtmlContentAllowed() {
  118. return getState(false).htmlContentAllowed;
  119. }
  120. @Override
  121. protected CheckBoxGroupState getState() {
  122. return (CheckBoxGroupState) super.getState();
  123. }
  124. @Override
  125. protected CheckBoxGroupState getState(boolean markAsDirty) {
  126. return (CheckBoxGroupState) super.getState(markAsDirty);
  127. }
  128. @Override
  129. public IconGenerator<T> getItemIconGenerator() {
  130. return super.getItemIconGenerator();
  131. }
  132. @Override
  133. public void setItemIconGenerator(IconGenerator<T> itemIconGenerator) {
  134. super.setItemIconGenerator(itemIconGenerator);
  135. }
  136. @Override
  137. public SerializablePredicate<T> getItemEnabledProvider() {
  138. return super.getItemEnabledProvider();
  139. }
  140. @Override
  141. public void setItemEnabledProvider(
  142. SerializablePredicate<T> itemEnabledProvider) {
  143. super.setItemEnabledProvider(itemEnabledProvider);
  144. }
  145. @Override
  146. public Registration addFocusListener(FocusListener listener) {
  147. return addListener(FocusEvent.EVENT_ID, FocusEvent.class, listener,
  148. FocusListener.focusMethod);
  149. }
  150. @Override
  151. public Registration addBlurListener(BlurListener listener) {
  152. return addListener(BlurEvent.EVENT_ID, BlurEvent.class, listener,
  153. BlurListener.blurMethod);
  154. }
  155. /**
  156. * Sets the description generator that is used for generating descriptions
  157. * for items. Description is shown as a tooltip when hovering on
  158. * corresponding element. If the generator returns {@code null}, no tooltip
  159. * is shown.
  160. *
  161. *
  162. * @param descriptionGenerator
  163. * the item description generator to set, not {@code null}
  164. *
  165. * @since 8.2
  166. */
  167. public void setItemDescriptionGenerator(
  168. DescriptionGenerator<T> descriptionGenerator) {
  169. Objects.requireNonNull(descriptionGenerator);
  170. if (this.descriptionGenerator != descriptionGenerator) {
  171. this.descriptionGenerator = descriptionGenerator;
  172. getDataProvider().refreshAll();
  173. }
  174. }
  175. /**
  176. * Gets the item description generator.
  177. *
  178. * @return the item description generator
  179. *
  180. * @since 8.2
  181. */
  182. public DescriptionGenerator<T> getItemDescriptionGenerator() {
  183. return descriptionGenerator;
  184. }
  185. @Override
  186. protected void readItems(Element design, DesignContext context) {
  187. setItemEnabledProvider(new DeclarativeItemEnabledProvider<>());
  188. super.readItems(design, context);
  189. }
  190. @SuppressWarnings({ "unchecked", "rawtypes" })
  191. @Override
  192. protected T readItem(Element child, Set<T> selected,
  193. DesignContext context) {
  194. T item = super.readItem(child, selected, context);
  195. SerializablePredicate<T> provider = getItemEnabledProvider();
  196. if (provider instanceof DeclarativeItemEnabledProvider) {
  197. if (child.hasAttr("disabled")) {
  198. ((DeclarativeItemEnabledProvider) provider).addDisabled(item);
  199. }
  200. } else {
  201. throw new IllegalStateException(String.format("Don't know how "
  202. + "to disable item using current item enabled provider '%s'",
  203. provider.getClass().getName()));
  204. }
  205. return item;
  206. }
  207. @Override
  208. protected Element writeItem(Element design, T item, DesignContext context) {
  209. Element elem = super.writeItem(design, item, context);
  210. if (!getItemEnabledProvider().test(item)) {
  211. elem.attr("disabled", true);
  212. }
  213. if (isHtmlContentAllowed()) {
  214. // need to unencode HTML entities. AbstractMultiSelect.writeDesign
  215. // can't check if HTML content is allowed, so it always encodes
  216. // entities like '>', '<' and '&'; in case HTML content is allowed
  217. // this is undesirable so we need to unencode entities. Entities
  218. // other than '<' and '>' will be taken care by Jsoup.
  219. elem.html(DesignFormatter.decodeFromTextNode(elem.html()));
  220. }
  221. return elem;
  222. }
  223. @Override
  224. public DataProvider<T, ?> getDataProvider() {
  225. return internalGetDataProvider();
  226. }
  227. @Override
  228. public void setDataProvider(DataProvider<T, ?> dataProvider) {
  229. internalSetDataProvider(dataProvider);
  230. }
  231. }