123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267 |
- /*
- * Copyright 2000-2018 Vaadin Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
- package com.vaadin.client.ui;
-
- import java.util.ArrayList;
- import java.util.HashSet;
- import java.util.List;
- import java.util.Objects;
- import java.util.Set;
- import java.util.function.BiConsumer;
-
- import com.google.gwt.user.client.ui.Composite;
- import com.google.gwt.user.client.ui.FlowPanel;
- import com.google.gwt.user.client.ui.HasEnabled;
- import com.google.gwt.user.client.ui.ListBox;
- import com.vaadin.client.BrowserInfo;
- import com.vaadin.client.FastStringSet;
- import com.vaadin.client.Focusable;
- import com.vaadin.client.connectors.AbstractMultiSelectConnector.MultiSelectWidget;
- import com.vaadin.shared.Registration;
- import com.vaadin.shared.ui.listselect.ListSelectState;
-
- import elemental.json.JsonObject;
-
- /**
- * A simple list select for selecting multiple items.
- *
- * @author Vaadin Ltd
- */
- public class VListSelect extends Composite
- implements Field, Focusable, HasEnabled, MultiSelectWidget {
-
- private List<BiConsumer<Set<String>, Set<String>>> selectionChangeListeners = new ArrayList<>();
-
- /** Container for select. Kept for DOM backwards compatibility. */
- protected final FlowPanel container;
- /** The select component. */
- protected final ListBox select;
-
- private boolean enabled;
- private boolean readOnly;
- private FastStringSet selectedItemKeys = FastStringSet.create();
-
- /**
- * Constructs a simple ListSelect widget in multiselect mode.
- */
- public VListSelect() {
- container = new FlowPanel();
-
- initWidget(container);
-
- select = new ListBox();
- select.setMultipleSelect(true);
-
- // Add event handlers
- select.addClickHandler(
- clickEvent -> selectionEvent(clickEvent.getSource()));
- select.addChangeHandler(
- changeEvent -> selectionEvent(changeEvent.getSource()));
-
- container.add(select);
-
- updateEnabledState();
- setStylePrimaryName(ListSelectState.PRIMARY_STYLENAME);
- }
-
- @Override
- public void setStylePrimaryName(String style) {
- super.setStylePrimaryName(style);
- select.setStyleName(style + "-select");
- }
-
- /**
- * Sets the number of visible items for the list select.
- *
- * @param rows
- * the number of items to show
- * @see ListBox#setVisibleItemCount(int)
- */
- public void setRows(int rows) {
- if (select.getVisibleItemCount() != rows) {
- select.setVisibleItemCount(rows);
- }
- }
-
- /**
- * Returns the number of visible items for the list select.
- *
- * @return the number of items to show
- * @see ListBox#setVisibleItemCount(int)
- */
- public int getRows() {
- return select.getVisibleItemCount();
- }
-
- @Override
- public Registration addSelectionChangeListener(
- BiConsumer<Set<String>, Set<String>> listener) {
- Objects.nonNull(listener);
- selectionChangeListeners.add(listener);
- return (Registration) () -> selectionChangeListeners.remove(listener);
- }
-
- @Override
- public void setItems(List<JsonObject> items) {
- selectedItemKeys = FastStringSet.create();
- for (int i = 0; i < items.size(); i++) {
- final JsonObject item = items.get(i);
- // reuse existing option if possible
- String key = MultiSelectWidget.getKey(item);
- if (BrowserInfo.get().isIE11() && key != null) {
- // IE11 doesn't handle numerical keys well on Win7,
- // prevent incorrect type handling with extra character
- key += " ";
- }
- if (i < select.getItemCount()) {
- select.setItemText(i, MultiSelectWidget.getCaption(item));
- select.setValue(i, key);
- } else {
- select.addItem(MultiSelectWidget.getCaption(item), key);
- }
- final boolean selected = MultiSelectWidget.isSelected(item);
- select.setItemSelected(i, selected);
- if (selected) {
- selectedItemKeys.add(key);
- }
- }
-
- // remove extra
- for (int i = select.getItemCount() - 1; i >= items.size(); i--) {
- select.removeItem(i);
- }
- }
-
- /**
- * Gets the currently selected item values.
- *
- * @return the currently selected item keys
- */
- protected FastStringSet getSelectedItems() {
- final FastStringSet selectedItemKeys = FastStringSet.create();
- for (int i = 0; i < select.getItemCount(); i++) {
- if (select.isItemSelected(i)) {
- String key = select.getValue(i);
- if (BrowserInfo.get().isIE11() && key != null) {
- // remove the IE11 workaround
- key = key.trim();
- }
- selectedItemKeys.add(key);
- }
- }
- return selectedItemKeys;
- }
-
- private void selectionEvent(Object source) {
- if (source == select) {
- // selection can change by adding and at the same time removing
- // previous keys, or by just adding (e.g. when modifier keys are
- // pressed)
- final Set<String> newSelectedItemKeys = new HashSet<>();
- final Set<String> removedItemKeys = new HashSet<>();
- for (int i = 0; i < select.getItemCount(); i++) {
- String key = select.getValue(i);
- boolean selected = select.isItemSelected(i);
- boolean wasSelected = selectedItemKeys.contains(key);
- if (selected && !wasSelected) {
- newSelectedItemKeys.add(key);
- selectedItemKeys.add(key);
- } else if (!selected && wasSelected) {
- removedItemKeys.add(key);
- selectedItemKeys.remove(key);
- }
- }
- selectionChangeListeners.forEach(
- l -> l.accept(newSelectedItemKeys, removedItemKeys));
- }
- }
-
- @Override
- public void setHeight(String height) {
- select.setHeight(height);
- super.setHeight(height);
- }
-
- @Override
- public void setWidth(String width) {
- select.setWidth(width);
- super.setWidth(width);
- }
-
- /**
- * Sets the tab index.
- *
- * @param tabIndex
- * the tab index to set
- */
- public void setTabIndex(int tabIndex) {
- select.setTabIndex(tabIndex);
- }
-
- /**
- * Gets the tab index.
- *
- * @return the tab index
- */
- public int getTabIndex() {
- return select.getTabIndex();
- }
-
- /**
- * Sets this select as read only, meaning selection cannot be changed.
- *
- * @param readOnly
- * {@code true} for read only, {@code false} for not read only
- */
- public void setReadOnly(boolean readOnly) {
- if (this.readOnly != readOnly) {
- this.readOnly = readOnly;
- updateEnabledState();
- }
- }
-
- /**
- * Returns {@code true} if this select is in read only mode, {@code false}
- * if not.
- *
- * @return {@code true} for read only, {@code false} for not read only
- */
- public boolean isReadOnly() {
- return readOnly;
- }
-
- @Override
- public void setEnabled(boolean enabled) {
- if (this.enabled != enabled) {
- this.enabled = enabled;
- updateEnabledState();
- }
- }
-
- @Override
- public boolean isEnabled() {
- return enabled;
- }
-
- private void updateEnabledState() {
- select.setEnabled(isEnabled() && !isReadOnly());
- }
-
- @Override
- public void focus() {
- select.setFocus(true);
- }
- }
|