Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

VListSelect.java 7.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  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.client.ui;
  17. import java.util.ArrayList;
  18. import java.util.HashSet;
  19. import java.util.List;
  20. import java.util.Objects;
  21. import java.util.Set;
  22. import java.util.function.BiConsumer;
  23. import com.google.gwt.user.client.ui.Composite;
  24. import com.google.gwt.user.client.ui.FlowPanel;
  25. import com.google.gwt.user.client.ui.HasEnabled;
  26. import com.google.gwt.user.client.ui.ListBox;
  27. import com.vaadin.client.FastStringSet;
  28. import com.vaadin.client.Focusable;
  29. import com.vaadin.client.connectors.AbstractMultiSelectConnector.MultiSelectWidget;
  30. import com.vaadin.shared.Registration;
  31. import com.vaadin.shared.ui.listselect.ListSelectState;
  32. import elemental.json.JsonObject;
  33. /**
  34. * A simple list select for selecting multiple items.
  35. *
  36. * @author Vaadin Ltd
  37. */
  38. public class VListSelect extends Composite
  39. implements Field, Focusable, HasEnabled, MultiSelectWidget {
  40. private List<BiConsumer<Set<String>, Set<String>>> selectionChangeListeners = new ArrayList<>();
  41. /** Container for select. Kept for DOM backwards compatibility. */
  42. protected final FlowPanel container;
  43. /** The select component. */
  44. protected final ListBox select;
  45. private boolean enabled;
  46. private boolean readOnly;
  47. private FastStringSet selectedItemKeys = FastStringSet.create();
  48. /**
  49. * Constructs a simple ListSelect widget in multiselect mode.
  50. */
  51. public VListSelect() {
  52. container = new FlowPanel();
  53. initWidget(container);
  54. select = new ListBox();
  55. select.setMultipleSelect(true);
  56. // Add event handlers
  57. select.addClickHandler(
  58. clickEvent -> selectionEvent(clickEvent.getSource()));
  59. select.addChangeHandler(
  60. changeEvent -> selectionEvent(changeEvent.getSource()));
  61. container.add(select);
  62. updateEnabledState();
  63. setStylePrimaryName(ListSelectState.PRIMARY_STYLENAME);
  64. }
  65. @Override
  66. public void setStylePrimaryName(String style) {
  67. super.setStylePrimaryName(style);
  68. select.setStyleName(style + "-select");
  69. }
  70. /**
  71. * Sets the number of visible items for the list select.
  72. *
  73. * @param rows
  74. * the number of items to show
  75. * @see ListBox#setVisibleItemCount(int)
  76. */
  77. public void setRows(int rows) {
  78. if (select.getVisibleItemCount() != rows) {
  79. select.setVisibleItemCount(rows);
  80. }
  81. }
  82. /**
  83. * Returns the number of visible items for the list select.
  84. *
  85. * @return the number of items to show
  86. * @see ListBox#setVisibleItemCount(int)
  87. */
  88. public int getRows() {
  89. return select.getVisibleItemCount();
  90. }
  91. @Override
  92. public Registration addSelectionChangeListener(
  93. BiConsumer<Set<String>, Set<String>> listener) {
  94. Objects.nonNull(listener);
  95. selectionChangeListeners.add(listener);
  96. return (Registration) () -> selectionChangeListeners.remove(listener);
  97. }
  98. @Override
  99. public void setItems(List<JsonObject> items) {
  100. selectedItemKeys = FastStringSet.create();
  101. for (int i = 0; i < items.size(); i++) {
  102. final JsonObject item = items.get(i);
  103. // reuse existing option if possible
  104. final String key = MultiSelectWidget.getKey(item);
  105. if (i < select.getItemCount()) {
  106. select.setItemText(i, MultiSelectWidget.getCaption(item));
  107. select.setValue(i, key);
  108. } else {
  109. select.addItem(MultiSelectWidget.getCaption(item), key);
  110. }
  111. final boolean selected = MultiSelectWidget.isSelected(item);
  112. select.setItemSelected(i, selected);
  113. if (selected) {
  114. selectedItemKeys.add(key);
  115. }
  116. }
  117. // remove extra
  118. for (int i = select.getItemCount() - 1; i >= items.size(); i--) {
  119. select.removeItem(i);
  120. }
  121. }
  122. /**
  123. * Gets the currently selected item values.
  124. *
  125. * @return the currently selected item keys
  126. */
  127. protected FastStringSet getSelectedItems() {
  128. final FastStringSet selectedItemKeys = FastStringSet.create();
  129. for (int i = 0; i < select.getItemCount(); i++) {
  130. if (select.isItemSelected(i)) {
  131. selectedItemKeys.add(select.getValue(i));
  132. }
  133. }
  134. return selectedItemKeys;
  135. }
  136. private void selectionEvent(Object source) {
  137. if (source == select) {
  138. // selection can change by adding and at the same time removing
  139. // previous keys, or by just adding (e.g. when modifier keys are
  140. // pressed)
  141. final Set<String> newSelectedItemKeys = new HashSet<>();
  142. final Set<String> removedItemKeys = new HashSet<>();
  143. for (int i = 0; i < select.getItemCount(); i++) {
  144. String key = select.getValue(i);
  145. boolean selected = select.isItemSelected(i);
  146. boolean wasSelected = selectedItemKeys.contains(key);
  147. if (selected && !wasSelected) {
  148. newSelectedItemKeys.add(key);
  149. selectedItemKeys.add(key);
  150. } else if (!selected && wasSelected) {
  151. removedItemKeys.add(key);
  152. selectedItemKeys.remove(key);
  153. }
  154. }
  155. selectionChangeListeners.forEach(
  156. l -> l.accept(newSelectedItemKeys, removedItemKeys));
  157. }
  158. }
  159. @Override
  160. public void setHeight(String height) {
  161. select.setHeight(height);
  162. super.setHeight(height);
  163. }
  164. @Override
  165. public void setWidth(String width) {
  166. select.setWidth(width);
  167. super.setWidth(width);
  168. }
  169. /**
  170. * Sets the tab index.
  171. *
  172. * @param tabIndex
  173. * the tab index to set
  174. */
  175. public void setTabIndex(int tabIndex) {
  176. select.setTabIndex(tabIndex);
  177. }
  178. /**
  179. * Gets the tab index.
  180. *
  181. * @return the tab index
  182. */
  183. public int getTabIndex() {
  184. return select.getTabIndex();
  185. }
  186. /**
  187. * Sets this select as read only, meaning selection cannot be changed.
  188. *
  189. * @param readOnly
  190. * {@code true} for read only, {@code false} for not read only
  191. */
  192. public void setReadOnly(boolean readOnly) {
  193. if (this.readOnly != readOnly) {
  194. this.readOnly = readOnly;
  195. updateEnabledState();
  196. }
  197. }
  198. /**
  199. * Returns {@code true} if this select is in read only mode, {@code false}
  200. * if not.
  201. *
  202. * @return {@code true} for read only, {@code false} for not read only
  203. */
  204. public boolean isReadOnly() {
  205. return readOnly;
  206. }
  207. @Override
  208. public void setEnabled(boolean enabled) {
  209. if (this.enabled != enabled) {
  210. this.enabled = enabled;
  211. updateEnabledState();
  212. }
  213. }
  214. @Override
  215. public boolean isEnabled() {
  216. return enabled;
  217. }
  218. private void updateEnabledState() {
  219. select.setEnabled(isEnabled() && !isReadOnly());
  220. }
  221. @Override
  222. public void focus() {
  223. select.setFocus(true);
  224. }
  225. }