Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

VListSelect.java 7.7KB

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