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;
}
}
+ /**
+ * 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);
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;
}
}
+ /**
+ * 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);
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;
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;
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;
+ }
}
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;
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;
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;
+ }
}
}
- 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);
package com.vaadin.ui;
import java.util.Collection;
+import java.util.Objects;
import java.util.Set;
import org.jsoup.nodes.Element;
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;
public class CheckBoxGroup<T> extends AbstractMultiSelect<T>
implements FocusNotifier, BlurNotifier, HasDataProvider<T> {
+ private DescriptionGenerator<T> descriptionGenerator = item -> null;
+
/**
* Constructs a new CheckBoxGroup with caption.
*
*/
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);
+ }
+ });
}
/**
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<>());
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;
implements FocusNotifier, BlurNotifier, HasDataProvider<T> {
private SerializablePredicate<T> itemEnabledProvider = item -> true;
+ private DescriptionGenerator<T> descriptionGenerator = item -> null;
/**
* Constructs a new RadioButtonGroup with caption.
} 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
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,
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";
}
*/
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
protected void createActions() {
super.createActions();
createItemIconGenerator();
+ createItemDescriptionGeneratorMenu();
}
private void createItemIconGenerator() {
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) {
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
createSelectionMenu();
createItemIconGeneratorMenu();
createItemCaptionGeneratorMenu();
+ createItemDescriptionGeneratorMenu();
}
protected void createSelectionMenu() {
}, 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);
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;
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());
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;
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());
}