123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232 |
- /*
- * Copyright 2000-2016 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.HashMap;
- import java.util.List;
- import java.util.Map;
- import java.util.function.BiConsumer;
-
- import com.google.gwt.aria.client.Roles;
- import com.google.gwt.dom.client.Element;
- import com.google.gwt.event.dom.client.ClickEvent;
- import com.google.gwt.event.dom.client.ClickHandler;
- import com.google.gwt.user.client.ui.FocusWidget;
- import com.google.gwt.user.client.ui.HasEnabled;
- import com.google.gwt.user.client.ui.Widget;
- import com.vaadin.client.ApplicationConnection;
- import com.vaadin.client.BrowserInfo;
- import com.vaadin.client.WidgetUtil;
- import com.vaadin.client.widgets.FocusableFlowPanelComposite;
- import com.vaadin.shared.Registration;
- import com.vaadin.shared.ui.ListingJsonConstants;
-
- import elemental.json.JsonObject;
-
- /**
- * The client-side widget for the {@code CheckBoxGroup} component.
- *
- * @author Vaadin Ltd.
- * @since 8.0
- */
- public class VCheckBoxGroup extends FocusableFlowPanelComposite
- implements Field, ClickHandler, HasEnabled {
-
- public static final String CLASSNAME = "v-select-optiongroup";
- public static final String CLASSNAME_OPTION = "v-select-option";
-
- private final Map<VCheckBox, JsonObject> optionsToItems;
-
- /**
- * For internal use only. May be removed or replaced in the future.
- */
- public ApplicationConnection client;
-
- private boolean htmlContentAllowed = false;
-
- private boolean enabled;
- private boolean readonly;
- private List<BiConsumer<JsonObject, Boolean>> selectionChangeListeners;
-
- public VCheckBoxGroup() {
- getWidget().setStyleName(CLASSNAME);
- optionsToItems = new HashMap<>();
- selectionChangeListeners = new ArrayList<>();
- }
-
- /*
- * Build all the options
- */
- public void buildOptions(List<JsonObject> items) {
- Roles.getGroupRole().set(getElement());
- int i = 0;
- int widgetsToRemove = getWidget().getWidgetCount() - items.size();
- if (widgetsToRemove < 0) {
- widgetsToRemove = 0;
- }
- List<Widget> remove = new ArrayList<>(widgetsToRemove);
- for (Widget widget : getWidget()) {
- if (i < items.size()) {
- updateItem((VCheckBox) widget, items.get(i), false);
- i++;
- } else {
- remove.add(widget);
- }
- }
- remove.stream().forEach(this::remove);
- while (i < items.size()) {
- updateItem(new VCheckBox(), items.get(i), true);
- i++;
- }
- }
-
- /**
- * Returns the JsonObject used to populate the CheckBox widget that contains
- * given Element.
- *
- * @since 8.2
- * @param element
- * the element to search for
- * @return the related JsonObject; {@code null} if not found
- */
- public JsonObject getItem(Element element) {
- return optionsToItems.entrySet().stream()
- .filter(entry -> entry.getKey().getElement()
- .isOrHasChild(element))
- .map(entry -> entry.getValue()).findFirst().orElse(null);
- }
-
- private void remove(Widget widget) {
- getWidget().remove(widget);
- optionsToItems.remove(widget);
- }
-
- private void updateItem(VCheckBox widget, JsonObject item,
- boolean requireInitialization) {
- String itemHtml = item
- .getString(ListingJsonConstants.JSONKEY_ITEM_VALUE);
- if (!isHtmlContentAllowed()) {
- itemHtml = WidgetUtil.escapeHTML(itemHtml);
- }
-
- String iconUrl = item.getString(ListingJsonConstants.JSONKEY_ITEM_ICON);
- if (iconUrl != null && !iconUrl.isEmpty()) {
- Icon icon = client.getIcon(iconUrl);
- itemHtml = icon.getElement().getString() + itemHtml;
- }
-
- widget.setHTML(itemHtml);
- widget.setValue(
- item.getBoolean(ListingJsonConstants.JSONKEY_ITEM_SELECTED));
- setOptionEnabled(widget, item);
-
- if (requireInitialization) {
- widget.addStyleName(CLASSNAME_OPTION);
- widget.addClickHandler(this);
- getWidget().add(widget);
- }
- optionsToItems.put(widget, item);
- }
-
- @Override
- public void onClick(ClickEvent event) {
- if (event.getSource() instanceof VCheckBox) {
- VCheckBox source = (VCheckBox) event.getSource();
- if (!source.isEnabled()) {
- // Click events on the text are received even though the
- // checkbox is disabled
- return;
- }
- if (BrowserInfo.get().isWebkit() || BrowserInfo.get().isIE11()) {
- // Webkit does not focus non-text input elements on click
- // (#11854)
- source.setFocus(true);
- }
- Boolean selected = source.getValue();
-
- JsonObject item = optionsToItems.get(source);
- assert item != null;
-
- new ArrayList<>(selectionChangeListeners)
- .forEach(listener -> listener.accept(item, selected));
- }
- }
-
- public void setTabIndex(int tabIndex) {
- for (Widget anOptionsContainer : getWidget()) {
- FocusWidget widget = (FocusWidget) anOptionsContainer;
- widget.setTabIndex(tabIndex);
- }
- }
-
- /**
- * Updates the checkbox's enabled state according to the widget's enabled,
- * read only and the item's enabled.
- *
- * @param checkBox
- * the checkbox to update
- * @param item
- * the item for the checkbox
- */
- protected void setOptionEnabled(VCheckBox checkBox, JsonObject item) {
- boolean optionEnabled = !item
- .getBoolean(ListingJsonConstants.JSONKEY_ITEM_DISABLED);
- boolean enabled = optionEnabled && !isReadonly() && isEnabled();
- checkBox.setEnabled(enabled);
- }
-
- public boolean isHtmlContentAllowed() {
- return htmlContentAllowed;
- }
-
- public void setHtmlContentAllowed(boolean htmlContentAllowed) {
- this.htmlContentAllowed = htmlContentAllowed;
- }
-
- @Override
- public boolean isEnabled() {
- return enabled;
- }
-
- public boolean isReadonly() {
- return readonly;
- }
-
- public void setReadonly(boolean readonly) {
- if (this.readonly != readonly) {
- this.readonly = readonly;
- optionsToItems.forEach(this::setOptionEnabled);
- }
- }
-
- @Override
- public void setEnabled(boolean enabled) {
- if (this.enabled != enabled) {
- this.enabled = enabled;
- optionsToItems.forEach(this::setOptionEnabled);
- }
- }
-
- public Registration addSelectionChangeHandler(
- BiConsumer<JsonObject, Boolean> selectionChanged) {
- selectionChangeListeners.add(selectionChanged);
- return (Registration) () -> selectionChangeListeners
- .remove(selectionChanged);
- }
-
- }
|