summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--client/src/main/java/com/vaadin/client/ui/VCheckBoxGroup.java16
-rw-r--r--client/src/main/java/com/vaadin/client/ui/VRadioButtonGroup.java24
-rw-r--r--client/src/main/java/com/vaadin/client/ui/optiongroup/CheckBoxGroupConnector.java19
-rw-r--r--client/src/main/java/com/vaadin/client/ui/optiongroup/RadioButtonGroupConnector.java19
-rw-r--r--server/src/main/java/com/vaadin/ui/AbstractMultiSelect.java2
-rw-r--r--server/src/main/java/com/vaadin/ui/CheckBoxGroup.java44
-rw-r--r--server/src/main/java/com/vaadin/ui/RadioButtonGroup.java39
-rw-r--r--shared/src/main/java/com/vaadin/shared/ui/ListingJsonConstants.java5
-rw-r--r--uitest/src/main/java/com/vaadin/tests/components/checkbox/CheckBoxGroupTestUI.java19
-rw-r--r--uitest/src/main/java/com/vaadin/tests/components/radiobutton/RadioButtonGroupTestUI.java17
-rw-r--r--uitest/src/test/java/com/vaadin/tests/components/checkboxgroup/CheckBoxGroupTest.java23
-rw-r--r--uitest/src/test/java/com/vaadin/tests/components/radiobuttongroup/RadioButtonGroupTest.java23
12 files changed, 249 insertions, 1 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
index ee1d83ee2c..8d38331af1 100644
--- a/client/src/main/java/com/vaadin/client/ui/VCheckBoxGroup.java
+++ b/client/src/main/java/com/vaadin/client/ui/VCheckBoxGroup.java
@@ -23,6 +23,7 @@ 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;
@@ -94,6 +95,21 @@ public class VCheckBoxGroup extends FocusableFlowPanelComposite
}
}
+ /**
+ * Returns the JsonObject used to populate the CheckBox widget that contains
+ * given Element.
+ *
+ * @since
+ * @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(e -> e.getKey().getElement().isOrHasChild(element))
+ .map(e -> e.getValue()).findFirst().orElse(null);
+ }
+
private void remove(Widget widget) {
getWidget().remove(widget);
optionsToItems.remove(widget);
diff --git a/client/src/main/java/com/vaadin/client/ui/VRadioButtonGroup.java b/client/src/main/java/com/vaadin/client/ui/VRadioButtonGroup.java
index 1386005351..1561cb9b8a 100644
--- a/client/src/main/java/com/vaadin/client/ui/VRadioButtonGroup.java
+++ b/client/src/main/java/com/vaadin/client/ui/VRadioButtonGroup.java
@@ -20,9 +20,11 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Optional;
import java.util.function.Consumer;
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.DOM;
@@ -101,6 +103,28 @@ public class VRadioButtonGroup extends FocusableFlowPanelComposite
}
}
+ /**
+ * Returns the JsonObject used to populate the RadioButton widget that
+ * contains given Element.
+ *
+ * @since
+ * @param element
+ * the element to search for
+ * @return the related JsonObject; {@code null} if not found
+ */
+ public JsonObject getItem(Element element) {
+ // The HTML populated in updateItem does not match RadioButton directly,
+ // which is why tryGetItem is also attempted on the parent element
+ return tryGetItem(element)
+ .orElse(tryGetItem(element.getParentElement()).orElse(null));
+ }
+
+ private Optional<JsonObject> tryGetItem(Element element) {
+ return optionsToItems.entrySet().stream()
+ .filter(e -> e.getKey().getElement().equals(element))
+ .map(e -> e.getValue()).findFirst();
+ }
+
private void remove(Widget widget) {
getWidget().remove(widget);
JsonObject item = optionsToItems.remove(widget);
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
index 1936aac79d..18d4019611 100644
--- a/client/src/main/java/com/vaadin/client/ui/optiongroup/CheckBoxGroupConnector.java
+++ b/client/src/main/java/com/vaadin/client/ui/optiongroup/CheckBoxGroupConnector.java
@@ -21,6 +21,8 @@ import java.util.Collections;
import java.util.HashSet;
import java.util.List;
+import com.google.gwt.dom.client.Element;
+import com.vaadin.client.TooltipInfo;
import com.vaadin.client.communication.StateChangeEvent;
import com.vaadin.client.connectors.AbstractFocusableListingConnector;
import com.vaadin.client.data.DataSource;
@@ -28,6 +30,7 @@ import com.vaadin.client.ui.HasRequiredIndicator;
import com.vaadin.client.ui.VCheckBoxGroup;
import com.vaadin.shared.data.selection.MultiSelectServerRpc;
import com.vaadin.shared.ui.Connect;
+import com.vaadin.shared.ui.ListingJsonConstants;
import com.vaadin.shared.ui.optiongroup.CheckBoxGroupState;
import com.vaadin.ui.CheckBoxGroup;
@@ -98,4 +101,20 @@ public class CheckBoxGroupConnector
public boolean isRequiredIndicatorVisible() {
return getState().required && !isReadOnly();
}
+
+ @Override
+ public TooltipInfo getTooltipInfo(Element element) {
+ JsonObject item = getWidget().getItem(element);
+ if (item != null
+ && item.hasKey(ListingJsonConstants.JSONKEY_ITEM_DESCRIPTION)) {
+ return new TooltipInfo(item
+ .getString(ListingJsonConstants.JSONKEY_ITEM_DESCRIPTION));
+ }
+ return super.getTooltipInfo(element);
+ }
+
+ @Override
+ public boolean hasTooltip() {
+ return true;
+ }
}
diff --git a/client/src/main/java/com/vaadin/client/ui/optiongroup/RadioButtonGroupConnector.java b/client/src/main/java/com/vaadin/client/ui/optiongroup/RadioButtonGroupConnector.java
index de92728712..882a91aa26 100644
--- a/client/src/main/java/com/vaadin/client/ui/optiongroup/RadioButtonGroupConnector.java
+++ b/client/src/main/java/com/vaadin/client/ui/optiongroup/RadioButtonGroupConnector.java
@@ -19,6 +19,8 @@ package com.vaadin.client.ui.optiongroup;
import java.util.ArrayList;
import java.util.List;
+import com.google.gwt.dom.client.Element;
+import com.vaadin.client.TooltipInfo;
import com.vaadin.client.annotations.OnStateChange;
import com.vaadin.client.communication.StateChangeEvent;
import com.vaadin.client.connectors.AbstractSingleSelectConnector;
@@ -28,6 +30,7 @@ import com.vaadin.shared.Range;
import com.vaadin.shared.Registration;
import com.vaadin.shared.data.selection.SelectionServerRpc;
import com.vaadin.shared.ui.Connect;
+import com.vaadin.shared.ui.ListingJsonConstants;
import com.vaadin.shared.ui.optiongroup.RadioButtonGroupState;
import com.vaadin.ui.RadioButtonGroup;
@@ -120,4 +123,20 @@ public class RadioButtonGroupConnector
select.buildOptions(options);
updateSelectedItem();
}
+
+ @Override
+ public TooltipInfo getTooltipInfo(Element element) {
+ JsonObject item = getWidget().getItem(element);
+ if (item != null
+ && item.hasKey(ListingJsonConstants.JSONKEY_ITEM_DESCRIPTION)) {
+ return new TooltipInfo(item
+ .getString(ListingJsonConstants.JSONKEY_ITEM_DESCRIPTION));
+ }
+ return super.getTooltipInfo(element);
+ }
+
+ @Override
+ public boolean hasTooltip() {
+ return true;
+ }
}
diff --git a/server/src/main/java/com/vaadin/ui/AbstractMultiSelect.java b/server/src/main/java/com/vaadin/ui/AbstractMultiSelect.java
index a0c8fd2225..93b0b35403 100644
--- a/server/src/main/java/com/vaadin/ui/AbstractMultiSelect.java
+++ b/server/src/main/java/com/vaadin/ui/AbstractMultiSelect.java
@@ -89,7 +89,7 @@ public abstract class AbstractMultiSelect<T> extends AbstractListing<T>
}
- private class MultiSelectDataGenerator implements DataGenerator<T> {
+ private final class MultiSelectDataGenerator implements DataGenerator<T> {
@Override
public void generateData(T data, JsonObject jsonObject) {
String caption = getItemCaptionGenerator().apply(data);
diff --git a/server/src/main/java/com/vaadin/ui/CheckBoxGroup.java b/server/src/main/java/com/vaadin/ui/CheckBoxGroup.java
index b6b6d69074..c257a1a0d0 100644
--- a/server/src/main/java/com/vaadin/ui/CheckBoxGroup.java
+++ b/server/src/main/java/com/vaadin/ui/CheckBoxGroup.java
@@ -17,6 +17,7 @@
package com.vaadin.ui;
import java.util.Collection;
+import java.util.Objects;
import java.util.Set;
import org.jsoup.nodes.Element;
@@ -32,7 +33,9 @@ import com.vaadin.event.FieldEvents.FocusListener;
import com.vaadin.event.FieldEvents.FocusNotifier;
import com.vaadin.server.SerializablePredicate;
import com.vaadin.shared.Registration;
+import com.vaadin.shared.ui.ListingJsonConstants;
import com.vaadin.shared.ui.optiongroup.CheckBoxGroupState;
+import com.vaadin.ui.components.grid.DescriptionGenerator;
import com.vaadin.ui.declarative.DesignContext;
import com.vaadin.ui.declarative.DesignFormatter;
@@ -48,6 +51,8 @@ import com.vaadin.ui.declarative.DesignFormatter;
public class CheckBoxGroup<T> extends AbstractMultiSelect<T>
implements FocusNotifier, BlurNotifier, HasDataProvider<T> {
+ private DescriptionGenerator<T> descriptionGenerator = item -> null;
+
/**
* Constructs a new CheckBoxGroup with caption.
*
@@ -92,6 +97,13 @@ public class CheckBoxGroup<T> extends AbstractMultiSelect<T>
*/
public CheckBoxGroup() {
registerRpc(new FocusAndBlurServerRpcDecorator(this, this::fireEvent));
+ addDataGenerator((item, jsonObject) -> {
+ String description = getItemDescriptionGenerator().apply(item);
+ if (description != null) {
+ jsonObject.put(ListingJsonConstants.JSONKEY_ITEM_DESCRIPTION,
+ description);
+ }
+ });
}
/**
@@ -162,6 +174,38 @@ public class CheckBoxGroup<T> extends AbstractMultiSelect<T>
BlurListener.blurMethod);
}
+ /**
+ * Sets the description generator that is used for generating descriptions
+ * for items. Description is shown as a tooltip when hovering on
+ * corresponding element. If the generator returns {@code null}, no tooltip
+ * is shown.
+ *
+ *
+ * @param descriptionGenerator
+ * the item description generator to set, not {@code null}
+ *
+ * @since
+ */
+ public void setItemDescriptionGenerator(
+ DescriptionGenerator<T> descriptionGenerator) {
+ Objects.requireNonNull(descriptionGenerator);
+ if (this.descriptionGenerator != descriptionGenerator) {
+ this.descriptionGenerator = descriptionGenerator;
+ getDataProvider().refreshAll();
+ }
+ }
+
+ /**
+ * Gets the item description generator.
+ *
+ * @return the item description generator
+ *
+ * @since
+ */
+ public DescriptionGenerator<T> getItemDescriptionGenerator() {
+ return descriptionGenerator;
+ }
+
@Override
protected void readItems(Element design, DesignContext context) {
setItemEnabledProvider(new DeclarativeItemEnabledProvider<>());
diff --git a/server/src/main/java/com/vaadin/ui/RadioButtonGroup.java b/server/src/main/java/com/vaadin/ui/RadioButtonGroup.java
index 35490c49d1..c6e4a66c65 100644
--- a/server/src/main/java/com/vaadin/ui/RadioButtonGroup.java
+++ b/server/src/main/java/com/vaadin/ui/RadioButtonGroup.java
@@ -38,6 +38,7 @@ import com.vaadin.server.SerializablePredicate;
import com.vaadin.shared.Registration;
import com.vaadin.shared.ui.ListingJsonConstants;
import com.vaadin.shared.ui.optiongroup.RadioButtonGroupState;
+import com.vaadin.ui.components.grid.DescriptionGenerator;
import com.vaadin.ui.declarative.DesignContext;
import com.vaadin.ui.declarative.DesignFormatter;
@@ -56,6 +57,7 @@ public class RadioButtonGroup<T> extends AbstractSingleSelect<T>
implements FocusNotifier, BlurNotifier, HasDataProvider<T> {
private SerializablePredicate<T> itemEnabledProvider = item -> true;
+ private DescriptionGenerator<T> descriptionGenerator = item -> null;
/**
* Constructs a new RadioButtonGroup with caption.
@@ -112,6 +114,12 @@ public class RadioButtonGroup<T> extends AbstractSingleSelect<T>
} else {
jsonObject.put(ListingJsonConstants.JSONKEY_ITEM_VALUE, "");
}
+ String description = getItemDescriptionGenerator().apply(data);
+ if (description != null) {
+ jsonObject.put(
+ ListingJsonConstants.JSONKEY_ITEM_DESCRIPTION,
+ description);
+ }
Resource icon = getItemIconGenerator().apply(data);
if (icon != null) {
String iconUrl = ResourceReference
@@ -219,6 +227,37 @@ public class RadioButtonGroup<T> extends AbstractSingleSelect<T>
this.itemEnabledProvider = itemEnabledProvider;
}
+ /**
+ * Sets the description generator that is used for generating descriptions
+ * for items. Description is shown as a tooltip when hovering on
+ * corresponding element. If the generator returns {@code null}, no tooltip
+ * is shown.
+ *
+ * @param descriptionGenerator
+ * the item description generator to set, not {@code null}
+ *
+ * @since
+ */
+ public void setItemDescriptionGenerator(
+ DescriptionGenerator<T> descriptionGenerator) {
+ Objects.requireNonNull(descriptionGenerator);
+ if (this.descriptionGenerator != descriptionGenerator) {
+ this.descriptionGenerator = descriptionGenerator;
+ getDataProvider().refreshAll();
+ }
+ }
+
+ /**
+ * Gets the item description generator.
+ *
+ * @return the item description generator
+ *
+ * @since
+ */
+ public DescriptionGenerator<T> getItemDescriptionGenerator() {
+ return descriptionGenerator;
+ }
+
@Override
public Registration addFocusListener(FocusListener listener) {
return addListener(FocusEvent.EVENT_ID, FocusEvent.class, listener,
diff --git a/shared/src/main/java/com/vaadin/shared/ui/ListingJsonConstants.java b/shared/src/main/java/com/vaadin/shared/ui/ListingJsonConstants.java
index 2ffd08ad7d..acdbcd097f 100644
--- a/shared/src/main/java/com/vaadin/shared/ui/ListingJsonConstants.java
+++ b/shared/src/main/java/com/vaadin/shared/ui/ListingJsonConstants.java
@@ -32,4 +32,9 @@ public class ListingJsonConstants implements Serializable {
public static final String JSONKEY_ITEM_VALUE = "v";
public static final String JSONKEY_ITEM_SELECTED = "s";
+
+ /**
+ * @since
+ */
+ public static final String JSONKEY_ITEM_DESCRIPTION = "dsc";
}
diff --git a/uitest/src/main/java/com/vaadin/tests/components/checkbox/CheckBoxGroupTestUI.java b/uitest/src/main/java/com/vaadin/tests/components/checkbox/CheckBoxGroupTestUI.java
index 88006fd68a..71c3a6147f 100644
--- a/uitest/src/main/java/com/vaadin/tests/components/checkbox/CheckBoxGroupTestUI.java
+++ b/uitest/src/main/java/com/vaadin/tests/components/checkbox/CheckBoxGroupTestUI.java
@@ -15,10 +15,13 @@
*/
package com.vaadin.tests.components.checkbox;
+import java.util.LinkedHashMap;
+
import com.vaadin.icons.VaadinIcons;
import com.vaadin.tests.components.abstractlisting.AbstractMultiSelectTestUI;
import com.vaadin.ui.CheckBoxGroup;
import com.vaadin.ui.IconGenerator;
+import com.vaadin.ui.components.grid.DescriptionGenerator;
/**
* Test UI for CheckBoxGroup component
@@ -49,6 +52,7 @@ public class CheckBoxGroupTestUI
protected void createActions() {
super.createActions();
createItemIconGenerator();
+ createItemDescriptionGeneratorMenu();
}
private void createItemIconGenerator() {
@@ -56,6 +60,21 @@ public class CheckBoxGroupTestUI
this::useItemIconProvider);
}
+ private void createItemDescriptionGeneratorMenu() {
+ LinkedHashMap<String, DescriptionGenerator<Object>> options = new LinkedHashMap<>();
+ options.put("Null Description Generator", item -> null);
+ options.put("Default Description Generator", item -> item.toString());
+ options.put("Custom Description Generator",
+ item -> item.toString() + " Description");
+
+ createSelectAction("Item Description Generator",
+ "Item Description Generator", options, "None",
+ (checkBoxGroup, generator, data) -> {
+ checkBoxGroup.setItemDescriptionGenerator(generator);
+ checkBoxGroup.getDataProvider().refreshAll();
+ }, true);
+ }
+
private void useItemIconProvider(CheckBoxGroup<Object> group,
boolean activate, Object data) {
if (activate) {
diff --git a/uitest/src/main/java/com/vaadin/tests/components/radiobutton/RadioButtonGroupTestUI.java b/uitest/src/main/java/com/vaadin/tests/components/radiobutton/RadioButtonGroupTestUI.java
index 20314fd347..d9161a6a46 100644
--- a/uitest/src/main/java/com/vaadin/tests/components/radiobutton/RadioButtonGroupTestUI.java
+++ b/uitest/src/main/java/com/vaadin/tests/components/radiobutton/RadioButtonGroupTestUI.java
@@ -22,6 +22,7 @@ import com.vaadin.icons.VaadinIcons;
import com.vaadin.tests.components.abstractlisting.AbstractListingTestUI;
import com.vaadin.ui.ItemCaptionGenerator;
import com.vaadin.ui.RadioButtonGroup;
+import com.vaadin.ui.components.grid.DescriptionGenerator;
/**
* Test UI for RadioButtonGroup component
@@ -46,6 +47,7 @@ public class RadioButtonGroupTestUI
createSelectionMenu();
createItemIconGeneratorMenu();
createItemCaptionGeneratorMenu();
+ createItemDescriptionGeneratorMenu();
}
protected void createSelectionMenu() {
@@ -92,6 +94,21 @@ public class RadioButtonGroupTestUI
}, true);
}
+ private void createItemDescriptionGeneratorMenu() {
+ LinkedHashMap<String, DescriptionGenerator<Object>> options = new LinkedHashMap<>();
+ options.put("Null Description Generator", item -> null);
+ options.put("Default Description Generator", item -> item.toString());
+ options.put("Custom Description Generator",
+ item -> item.toString() + " Description");
+
+ createSelectAction("Item Description Generator",
+ "Item Description Generator", options, "None",
+ (radioButtonGroup, generator, data) -> {
+ radioButtonGroup.setItemDescriptionGenerator(generator);
+ radioButtonGroup.getDataProvider().refreshAll();
+ }, true);
+ }
+
private void toggleSelection(String item) {
if (getComponent().isSelected(item)) {
getComponent().setValue(null);
diff --git a/uitest/src/test/java/com/vaadin/tests/components/checkboxgroup/CheckBoxGroupTest.java b/uitest/src/test/java/com/vaadin/tests/components/checkboxgroup/CheckBoxGroupTest.java
index 5d7c37c754..98d9cc03e5 100644
--- a/uitest/src/test/java/com/vaadin/tests/components/checkboxgroup/CheckBoxGroupTest.java
+++ b/uitest/src/test/java/com/vaadin/tests/components/checkboxgroup/CheckBoxGroupTest.java
@@ -33,6 +33,7 @@ import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;
import com.vaadin.icons.VaadinIcons;
+import com.vaadin.testbench.TestBenchElement;
import com.vaadin.testbench.elements.CheckBoxGroupElement;
import com.vaadin.tests.components.checkbox.CheckBoxGroupTestUI;
import com.vaadin.tests.tb3.MultiBrowserTest;
@@ -195,6 +196,28 @@ public class CheckBoxGroupTest extends MultiBrowserTest {
assertSelected("Item 1");
}
+ @Test
+ public void testItemDescriptionGenerators() {
+ TestBenchElement label;
+
+ selectMenuPath("Component", "Item Description Generator",
+ "Item Description Generator", "Default Description Generator");
+
+ label = (TestBenchElement) findElements(By.tagName("label")).get(5);
+ label.showTooltip();
+ Assert.assertEquals("Tooltip should contain the same text as caption",
+ label.getText(), getTooltipElement().getText());
+
+ selectMenuPath("Component", "Item Description Generator",
+ "Item Description Generator", "Custom Description Generator");
+
+ label = (TestBenchElement) findElements(By.tagName("label")).get(5);
+ label.showTooltip();
+ Assert.assertEquals("Tooltip should contain caption + ' Description'",
+ label.getText() + " Description",
+ getTooltipElement().getText());
+ }
+
private void assertSelected(String... expectedSelection) {
Assert.assertEquals(Arrays.asList(expectedSelection),
getSelect().getValue());
diff --git a/uitest/src/test/java/com/vaadin/tests/components/radiobuttongroup/RadioButtonGroupTest.java b/uitest/src/test/java/com/vaadin/tests/components/radiobuttongroup/RadioButtonGroupTest.java
index 2c53903d29..6c0b60be78 100644
--- a/uitest/src/test/java/com/vaadin/tests/components/radiobuttongroup/RadioButtonGroupTest.java
+++ b/uitest/src/test/java/com/vaadin/tests/components/radiobuttongroup/RadioButtonGroupTest.java
@@ -27,6 +27,7 @@ import org.openqa.selenium.WebElement;
import com.vaadin.icons.VaadinIcons;
import com.vaadin.testbench.By;
+import com.vaadin.testbench.TestBenchElement;
import com.vaadin.testbench.elements.RadioButtonGroupElement;
import com.vaadin.tests.components.radiobutton.RadioButtonGroupTestUI;
import com.vaadin.tests.tb3.MultiBrowserTest;
@@ -189,6 +190,28 @@ public class RadioButtonGroupTest extends MultiBrowserTest {
assertSelected("Item 5");
}
+ @Test
+ public void testItemDescriptionGenerators() {
+ TestBenchElement label;
+
+ selectMenuPath("Component", "Item Description Generator",
+ "Item Description Generator", "Default Description Generator");
+
+ label = (TestBenchElement) findElements(By.tagName("label")).get(5);
+ label.showTooltip();
+ Assert.assertEquals("Tooltip should contain the same text as caption",
+ label.getText(), getTooltipElement().getText());
+
+ selectMenuPath("Component", "Item Description Generator",
+ "Item Description Generator", "Custom Description Generator");
+
+ label = (TestBenchElement) findElements(By.tagName("label")).get(5);
+ label.showTooltip();
+ Assert.assertEquals("Tooltip should contain caption + ' Description'",
+ label.getText() + " Description",
+ getTooltipElement().getText());
+ }
+
private void assertSelected(String expectedSelection) {
Assert.assertEquals(expectedSelection, getSelect().getValue());
}