summaryrefslogtreecommitdiffstats
path: root/client
diff options
context:
space:
mode:
authorelmot <elmot@vaadin.com>2016-09-12 17:58:38 +0300
committerVaadin Code Review <review@vaadin.com>2016-09-13 18:06:18 +0000
commit37e488d86b0bc59bf085a64eda3e258a01c496f0 (patch)
treea287284353b4d2c7068c0126ef773c56e0d8700e /client
parentd0435d5f02f93e3f5123ae54216d0062054cbe90 (diff)
downloadvaadin-framework-37e488d86b0bc59bf085a64eda3e258a01c496f0.tar.gz
vaadin-framework-37e488d86b0bc59bf085a64eda3e258a01c496f0.zip
Create a CheckBoxGroup that replaces the multi select case of OptionGroup
Change-Id: I250c60741bc65443b66498a8d0b17541edb77bf1
Diffstat (limited to 'client')
-rw-r--r--client/src/main/java/com/vaadin/client/ui/VCheckBoxGroup.java223
-rw-r--r--client/src/main/java/com/vaadin/client/ui/checkbox/CheckBoxConnector.java6
-rw-r--r--client/src/main/java/com/vaadin/client/ui/optiongroup/CheckBoxGroupConnector.java83
3 files changed, 312 insertions, 0 deletions
diff --git a/client/src/main/java/com/vaadin/client/ui/VCheckBoxGroup.java b/client/src/main/java/com/vaadin/client/ui/VCheckBoxGroup.java
new file mode 100644
index 0000000000..3b6c73950c
--- /dev/null
+++ b/client/src/main/java/com/vaadin/client/ui/VCheckBoxGroup.java
@@ -0,0 +1,223 @@
+/*
+ * 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 com.google.gwt.aria.client.Roles;
+import com.google.gwt.event.dom.client.ChangeEvent;
+import com.google.gwt.event.dom.client.ChangeHandler;
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.ClickHandler;
+import com.google.gwt.user.client.ui.Composite;
+import com.google.gwt.user.client.ui.FlowPanel;
+import com.google.gwt.user.client.ui.FocusWidget;
+import com.google.gwt.user.client.ui.Focusable;
+import com.google.gwt.user.client.ui.HasEnabled;
+import com.google.gwt.user.client.ui.Panel;
+import com.google.gwt.user.client.ui.Widget;
+import com.vaadin.client.ApplicationConnection;
+import com.vaadin.client.WidgetUtil;
+import com.vaadin.shared.Registration;
+import com.vaadin.shared.ui.optiongroup.CheckBoxGroupConstants;
+import elemental.json.JsonObject;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Consumer;
+
+import static com.vaadin.shared.ui.optiongroup.CheckBoxGroupConstants.JSONKEY_ITEM_DISABLED;
+
+/**
+ * The client-side widget for the {@code CheckBoxGroup} component.
+ *
+ * @author Vaadin Ltd.
+ * @since 8.0
+ */
+public class VCheckBoxGroup extends Composite
+ implements Field, ClickHandler, ChangeHandler,
+ com.vaadin.client.Focusable, 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;
+ /**
+ * For internal use only. May be removed or replaced in the future.
+ */
+ public JsonObject selected; //TODO replace with SelectionModel
+ /**
+ * Widget holding the different options (e.g. ListBox or Panel for radio
+ * buttons) (optional, fallbacks to container Panel)
+ * <p>
+ * For internal use only. May be removed or replaced in the future.
+ */
+ public Panel optionsContainer;
+
+ private boolean htmlContentAllowed = false;
+
+ private boolean enabled;
+ private boolean readonly;
+ private List<Consumer<JsonObject>> selectionChangeListeners;
+
+ public VCheckBoxGroup() {
+ optionsContainer = new FlowPanel();
+ initWidget(this.optionsContainer);
+ optionsContainer.setStyleName(CLASSNAME);
+ optionsToItems = new HashMap<>();
+ selectionChangeListeners = new ArrayList<>();
+ }
+
+ /*
+ * Build all the options
+ */
+ public void buildOptions(List<JsonObject> items) {
+ /*
+ * In order to retain focus, we need to update values rather than
+ * recreate panel from scratch (#10451). However, the panel will be
+ * rebuilt (losing focus) if number of elements or their order is
+ * changed.
+ */
+
+ Roles.getRadiogroupRole().set(getElement());
+ optionsContainer.clear();
+ for (JsonObject item : items) {
+ String itemHtml =
+ item.getString(CheckBoxGroupConstants.JSONKEY_ITEM_VALUE);
+ if (!isHtmlContentAllowed()) {
+ itemHtml = WidgetUtil.escapeHTML(itemHtml);
+ }
+ VCheckBox checkBox = new VCheckBox();
+
+ String iconUrl =
+ item.getString(CheckBoxGroupConstants.JSONKEY_ITEM_ICON);
+ if (iconUrl != null && iconUrl.length() != 0) {
+ checkBox.icon = client.getIcon(iconUrl);
+ }
+
+ checkBox.addStyleName(CLASSNAME_OPTION);
+ checkBox.addClickHandler(this);
+ checkBox.setHTML(itemHtml);
+ checkBox.setValue(true);//TODO selection model here
+ boolean optionEnabled = !item.getBoolean(JSONKEY_ITEM_DISABLED);
+ boolean enabled = optionEnabled && !isReadonly() && isEnabled();
+ checkBox.setEnabled(enabled);
+
+ optionsContainer.add(checkBox);
+ optionsToItems.put(checkBox, 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;
+ }
+
+ final boolean selected = source.getValue();
+ JsonObject item = optionsToItems.get(source); //TODO SelectionModel
+ if (selected) {
+ this.selected = item;
+ } else {
+ this.selected = null;
+ }
+ }
+ }
+
+ public void setTabIndex(int tabIndex) {
+ for (Widget anOptionsContainer : optionsContainer) {
+ FocusWidget widget = (FocusWidget) anOptionsContainer;
+ widget.setTabIndex(tabIndex);
+ }
+ }
+
+ protected void updateEnabledState() {
+ boolean optionGroupEnabled = isEnabled() && !isReadonly();
+ // sets options enabled according to the widget's enabled,
+ // readonly and each options own enabled
+ for (Map.Entry<VCheckBox, JsonObject> entry : optionsToItems
+ .entrySet()) {
+ VCheckBox checkBox = entry.getKey();
+ JsonObject value = entry.getValue();
+ Boolean isOptionEnabled = !value.getBoolean(
+ CheckBoxGroupConstants.JSONKEY_ITEM_DISABLED);
+ checkBox.setEnabled(optionGroupEnabled && isOptionEnabled);
+ }
+ }
+
+ @Override
+ public void focus() {
+ Iterator<Widget> iterator = optionsContainer.iterator();
+ if (iterator.hasNext()) {
+ ((Focusable) iterator.next()).setFocus(true);
+ }
+ }
+
+ public boolean isHtmlContentAllowed() {
+ return htmlContentAllowed;
+ }
+
+ public void setHtmlContentAllowed(boolean htmlContentAllowed) {
+ this.htmlContentAllowed = htmlContentAllowed;
+ }
+
+ @Override
+ public boolean isEnabled() {
+ return enabled;
+ }
+
+ public boolean isReadonly() {
+ return readonly;
+ }
+
+ @Override
+ public void onChange(ChangeEvent event) {
+ //TODO selectionModel
+ }
+
+ public void setReadonly(boolean readonly) {
+ if (this.readonly != readonly) {
+ this.readonly = readonly;
+ updateEnabledState();
+ }
+ }
+
+ @Override
+ public void setEnabled(boolean enabled) {
+ if (this.enabled != enabled) {
+ this.enabled = enabled;
+ updateEnabledState();
+ }
+ }
+
+ public Registration addNotifyHandler(
+ Consumer<JsonObject> selectionChanged) {
+ selectionChangeListeners.add(selectionChanged);
+ return (Registration) () -> selectionChangeListeners
+ .remove(selectionChanged);
+ }
+}
diff --git a/client/src/main/java/com/vaadin/client/ui/checkbox/CheckBoxConnector.java b/client/src/main/java/com/vaadin/client/ui/checkbox/CheckBoxConnector.java
index 598280cf5c..3c36ffd4fe 100644
--- a/client/src/main/java/com/vaadin/client/ui/checkbox/CheckBoxConnector.java
+++ b/client/src/main/java/com/vaadin/client/ui/checkbox/CheckBoxConnector.java
@@ -36,6 +36,12 @@ import com.vaadin.shared.ui.checkbox.CheckBoxServerRpc;
import com.vaadin.shared.ui.checkbox.CheckBoxState;
import com.vaadin.ui.CheckBox;
+/**
+ * The client-side connector for the {@code CheckBoxGroup} component.
+ *
+ * @author Vaadin Ltd.
+ * @since 8.0
+ */
@Connect(CheckBox.class)
public class CheckBoxConnector extends AbstractFieldConnector
implements ClickHandler {
diff --git a/client/src/main/java/com/vaadin/client/ui/optiongroup/CheckBoxGroupConnector.java b/client/src/main/java/com/vaadin/client/ui/optiongroup/CheckBoxGroupConnector.java
new file mode 100644
index 0000000000..dbd531382d
--- /dev/null
+++ b/client/src/main/java/com/vaadin/client/ui/optiongroup/CheckBoxGroupConnector.java
@@ -0,0 +1,83 @@
+/*
+ * 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.optiongroup;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.vaadin.client.communication.StateChangeEvent;
+import com.vaadin.client.connectors.AbstractListingConnector;
+import com.vaadin.client.data.DataSource;
+import com.vaadin.client.ui.VCheckBoxGroup;
+import com.vaadin.shared.Registration;
+import com.vaadin.shared.data.selection.SelectionModel;
+import com.vaadin.shared.ui.Connect;
+import com.vaadin.shared.ui.optiongroup.CheckBoxGroupState;
+import com.vaadin.ui.CheckBoxGroup;
+
+import elemental.json.JsonObject;
+
+@Connect(CheckBoxGroup.class)
+public class CheckBoxGroupConnector
+ extends AbstractListingConnector<SelectionModel.Multi<JsonObject>> {
+
+ private Registration selectionChangeRegistration;
+
+ @Override
+ protected void init() {
+ super.init();
+ selectionChangeRegistration =
+ getWidget().addNotifyHandler(this::selectionChanged);
+ }
+
+ private void selectionChanged(JsonObject newSelection) {
+ getSelectionModel().select(newSelection);
+ }
+
+ @Override
+ public void onStateChanged(StateChangeEvent stateChangeEvent) {
+ super.onStateChanged(stateChangeEvent);
+ getWidget().setTabIndex(getState().tabIndex);
+ getWidget().setReadonly(isReadOnly());
+ getWidget().client = getConnection();
+ }
+
+ @Override
+ public void setDataSource(DataSource<JsonObject> dataSource) {
+ dataSource.addDataChangeHandler(range -> updateOptionGroup());
+ super.setDataSource(dataSource);
+ }
+
+ private void updateOptionGroup() {
+ List<JsonObject> items = new ArrayList<>(getDataSource().size());
+ for (int i = 0; i < getDataSource().size(); ++i) {
+ JsonObject item = getDataSource().getRow(i);
+ items.add(item);
+ }
+ getWidget().buildOptions(items);
+ }
+
+ @Override
+ public VCheckBoxGroup getWidget() {
+ return (VCheckBoxGroup) super.getWidget();
+ }
+
+ @Override
+ public CheckBoxGroupState getState() {
+ return (CheckBoxGroupState) super.getState();
+ }
+}