diff options
4 files changed, 103 insertions, 18 deletions
diff --git a/server/src/main/java/com/vaadin/ui/ComboBox.java b/server/src/main/java/com/vaadin/ui/ComboBox.java index c8f6907866..ef1e7cfa84 100644 --- a/server/src/main/java/com/vaadin/ui/ComboBox.java +++ b/server/src/main/java/com/vaadin/ui/ComboBox.java @@ -35,6 +35,7 @@ import com.vaadin.data.HasValue; import com.vaadin.data.ValueProvider; import com.vaadin.data.provider.CallbackDataProvider; import com.vaadin.data.provider.DataCommunicator; +import com.vaadin.data.provider.DataGenerator; import com.vaadin.data.provider.DataKeyMapper; import com.vaadin.data.provider.DataProvider; import com.vaadin.data.provider.ListDataProvider; @@ -44,6 +45,7 @@ import com.vaadin.event.FieldEvents.BlurListener; import com.vaadin.event.FieldEvents.FocusAndBlurServerRpcDecorator; import com.vaadin.event.FieldEvents.FocusEvent; import com.vaadin.event.FieldEvents.FocusListener; +import com.vaadin.server.ConnectorResource; import com.vaadin.server.KeyMapper; import com.vaadin.server.Resource; import com.vaadin.server.ResourceReference; @@ -288,21 +290,56 @@ public class ComboBox<T> extends AbstractSingleSelect<T> registerRpc(rpc); registerRpc(new FocusAndBlurServerRpcDecorator(this, this::fireEvent)); - addDataGenerator((T data, JsonObject jsonObject) -> { - String caption = getItemCaptionGenerator().apply(data); - if (caption == null) { - caption = ""; + addDataGenerator(new DataGenerator<T>() { + + /** + * Map for storing names for icons. + */ + private Map<Object, String> resourceKeyMap = new HashMap<>(); + private int counter = 0; + + @Override + public void generateData(T item, JsonObject jsonObject) { + String caption = getItemCaptionGenerator().apply(item); + if (caption == null) { + caption = ""; + } + jsonObject.put(DataCommunicatorConstants.NAME, caption); + String style = itemStyleGenerator.apply(item); + if (style != null) { + jsonObject.put(ComboBoxConstants.STYLE, style); + } + Resource icon = getItemIcon(item); + if (icon != null) { + String iconKey = resourceKeyMap + .get(getDataProvider().getId(item)); + String iconUrl = ResourceReference + .create(icon, ComboBox.this, iconKey).getURL(); + jsonObject.put(ComboBoxConstants.ICON, iconUrl); + } } - jsonObject.put(DataCommunicatorConstants.NAME, caption); - String style = itemStyleGenerator.apply(data); - if (style != null) { - jsonObject.put(ComboBoxConstants.STYLE, style); + + @Override + public void destroyData(T item) { + Object itemId = getDataProvider().getId(item); + if (resourceKeyMap.containsKey(itemId)) { + setResource(resourceKeyMap.get(itemId), null); + resourceKeyMap.remove(itemId); + } } - Resource icon = getItemIconGenerator().apply(data); - if (icon != null) { - String iconUrl = ResourceReference - .create(icon, ComboBox.this, null).getURL(); - jsonObject.put(ComboBoxConstants.ICON, iconUrl); + + private Resource getItemIcon(T item) { + Resource icon = getItemIconGenerator().apply(item); + if (icon == null || !(icon instanceof ConnectorResource)) { + return icon; + } + + Object itemId = getDataProvider().getId(item); + if (!resourceKeyMap.containsKey(itemId)) { + resourceKeyMap.put(itemId, "icon" + (counter++)); + } + setResource(resourceKeyMap.get(itemId), icon); + return icon; } }); } @@ -804,8 +841,11 @@ public class ComboBox<T> extends AbstractSingleSelect<T> if (value != null) { Resource icon = getItemIconGenerator().apply(value); if (icon != null) { + if (icon instanceof ConnectorResource) { + setResource("selected", icon); + } selectedItemIcon = ResourceReference - .create(icon, ComboBox.this, null).getURL(); + .create(icon, ComboBox.this, "selected").getURL(); } } getState().selectedItemIcon = selectedItemIcon; diff --git a/tests/screenshots b/tests/screenshots -Subproject a70c038dcdf9b95d984d5fa7d54acf3f49c4513 +Subproject d7066ae2cb69bbea33017e89aa503ed2e4a4f09 diff --git a/uitest/src/main/java/com/vaadin/tests/components/combobox/ComboBoxItemIcon.java b/uitest/src/main/java/com/vaadin/tests/components/combobox/ComboBoxItemIcon.java index ad27e2b6ab..c12ef2878f 100644 --- a/uitest/src/main/java/com/vaadin/tests/components/combobox/ComboBoxItemIcon.java +++ b/uitest/src/main/java/com/vaadin/tests/components/combobox/ComboBoxItemIcon.java @@ -1,13 +1,40 @@ package com.vaadin.tests.components.combobox; +import java.net.URISyntaxException; +import java.nio.file.Paths; import java.util.Locale; +import java.util.stream.IntStream; +import com.vaadin.server.ClassResource; +import com.vaadin.server.FileResource; +import com.vaadin.server.StreamResource; import com.vaadin.server.ThemeResource; import com.vaadin.tests.components.TestBase; import com.vaadin.ui.ComboBox; +import com.vaadin.ui.IconGenerator; public class ComboBoxItemIcon extends TestBase { + private IconGenerator<Integer> iconGenerator = i -> { + switch (i % 3) { + case 0: + return new StreamResource(() -> getClass().getResourceAsStream( + "/com/vaadin/tests/integration/se.gif"), "se.gif"); + case 1: + try { + return new FileResource(Paths.get(getClass() + .getResource("/com/vaadin/tests/integration/fi.gif") + .toURI()).toFile()); + } catch (URISyntaxException e) { + return null; + } + case 2: + return new ClassResource("/com/vaadin/tests/m.gif"); + default: + return null; + } + }; + @Override protected Integer getTicketNumber() { return 2455; @@ -40,6 +67,15 @@ public class ComboBoxItemIcon extends TestBase { cb.setValue("Hungary"); addComponent(cb); } + { + ComboBox<Integer> cb = new ComboBox<>(); + cb.setItems(IntStream.range(0, 3).boxed()); + cb.setItemIconGenerator(iconGenerator); + + // FIXME: Selecting ConnectorResource on init does not work. + // cb.setValue(2); + addComponent(cb); + } } } diff --git a/uitest/src/test/java/com/vaadin/tests/components/combobox/ComboBoxItemIconTest.java b/uitest/src/test/java/com/vaadin/tests/components/combobox/ComboBoxItemIconTest.java index e5df4ad827..0c00220276 100644 --- a/uitest/src/test/java/com/vaadin/tests/components/combobox/ComboBoxItemIconTest.java +++ b/uitest/src/test/java/com/vaadin/tests/components/combobox/ComboBoxItemIconTest.java @@ -10,6 +10,7 @@ import com.vaadin.testbench.elements.ComboBoxElement; import com.vaadin.tests.tb3.MultiBrowserTest; public class ComboBoxItemIconTest extends MultiBrowserTest { + @Test public void testIconsInComboBox() throws Exception { openTestURL(); @@ -17,20 +18,28 @@ public class ComboBoxItemIconTest extends MultiBrowserTest { ComboBoxElement firstCombo = $(ComboBoxElement.class).first(); firstCombo.openPopup(); - compareScreen("first-combobox-open"); + compareScreen(firstCombo.getSuggestionPopup(), "first-combobox-open"); // null item not on the list, so use index 1 firstCombo.selectByText(firstCombo.getPopupSuggestions().get(1)); - compareScreen("fi-hu-selected"); + compareScreen(firstCombo, "fi-hu-selected"); ComboBoxElement secondCombo = $(ComboBoxElement.class).get(1); secondCombo.openPopup(); - compareScreen("second-combobox-open"); + compareScreen(secondCombo.getSuggestionPopup(), "second-combobox-open"); secondCombo.selectByText(secondCombo.getPopupSuggestions().get(2)); - compareScreen("fi-au-selected"); + compareScreen(secondCombo, "fi-au-selected"); + + ComboBoxElement thirdCombo = $(ComboBoxElement.class).get(2); + + thirdCombo.openPopup(); + compareScreen(thirdCombo.getSuggestionPopup(), "third-combobox-open"); + + thirdCombo.selectByText(thirdCombo.getPopupSuggestions().get(3)); + compareScreen(thirdCombo, "classresource"); } @Test |