]> source.dussan.org Git - vaadin-framework.git/commitdiff
Update NativeSelect to use DataSource, extend AbstractListing
authorJohannes Dahlström <johannesd@vaadin.com>
Thu, 8 Sep 2016 19:16:08 +0000 (22:16 +0300)
committerIlia Motornyi <elmot@vaadin.com>
Mon, 12 Sep 2016 09:05:41 +0000 (09:05 +0000)
Selection and focus/blur support not yet implemented.

Change-Id: I76752084442216e60055d93367475c1c0a612787

client/src/main/java/com/vaadin/client/ui/VNativeSelect.java [new file with mode: 0644]
client/src/main/java/com/vaadin/client/ui/nativeselect/NativeSelectConnector.java [new file with mode: 0644]
server/src/main/java/com/vaadin/ui/NativeSelect.java [new file with mode: 0644]
shared/src/main/java/com/vaadin/shared/ui/nativeselect/NativeSelectState.java [new file with mode: 0644]
uitest-common/src/main/java/com/vaadin/testbench/customelements/NativeSelectElement.java [new file with mode: 0644]
uitest/src/main/java/com/vaadin/tests/components/abstractlisting/AbstractListingTestUI.java
uitest/src/main/java/com/vaadin/tests/components/nativeselect/NativeSelects.java [new file with mode: 0644]
uitest/src/test/java/com/vaadin/tests/components/nativeselect/NativeSelectTest.java [new file with mode: 0644]

diff --git a/client/src/main/java/com/vaadin/client/ui/VNativeSelect.java b/client/src/main/java/com/vaadin/client/ui/VNativeSelect.java
new file mode 100644 (file)
index 0000000..4a3d95c
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * 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.user.client.ui.ListBox;
+import com.vaadin.shared.ui.nativeselect.NativeSelectState;
+
+/**
+ * The client-side widget for the {@code NativeSelect} component.
+ * 
+ * @author Vaadin Ltd.
+ */
+public class VNativeSelect extends ListBox {
+
+    /**
+     * Creates a new {@code VNativeSelect} instance.
+     */
+    public VNativeSelect() {
+        setStyleName(NativeSelectState.STYLE_NAME);
+    }
+}
diff --git a/client/src/main/java/com/vaadin/client/ui/nativeselect/NativeSelectConnector.java b/client/src/main/java/com/vaadin/client/ui/nativeselect/NativeSelectConnector.java
new file mode 100644 (file)
index 0000000..afa202e
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * 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.nativeselect;
+
+import com.vaadin.client.annotations.OnStateChange;
+import com.vaadin.client.connectors.AbstractListingConnector;
+import com.vaadin.client.data.DataSource;
+import com.vaadin.client.ui.VNativeSelect;
+import com.vaadin.shared.Range;
+import com.vaadin.shared.Registration;
+import com.vaadin.shared.data.selection.SelectionModel;
+import com.vaadin.shared.ui.Connect;
+
+import elemental.json.JsonObject;
+
+/**
+ * The client-side connector for the {@code NativeSelect} component.
+ * 
+ * @author Vaadin Ltd.
+ * 
+ * @see com.vaadin.ui.NativeSelect
+ * @see com.vaadin.client.ui.VNativeSelect
+ * 
+ * @since 8.0
+ */
+@Connect(com.vaadin.ui.NativeSelect.class)
+public class NativeSelectConnector extends
+        AbstractListingConnector<SelectionModel<?>> {
+
+    private Registration dataChangeRegistration;
+
+    @Override
+    public VNativeSelect getWidget() {
+        return (VNativeSelect) super.getWidget();
+    }
+
+    @Override
+    public void setDataSource(DataSource<JsonObject> dataSource) {
+        if (dataChangeRegistration != null) {
+            dataChangeRegistration.remove();
+        }
+        dataChangeRegistration = dataSource.addDataChangeHandler(
+                this::onDataChange);
+        super.setDataSource(dataSource);
+    }
+
+    @OnStateChange("readOnly")
+    @SuppressWarnings("deprecation")
+    void updateWidgetReadOnly() {
+        getWidget().setEnabled(isEnabled() && !isReadOnly());
+    }
+
+    /**
+     * A data change handler registered to the data source. Updates the data
+     * items and selection status when the data source notifies of new changes
+     * from the server side.
+     * 
+     * @param range
+     *            the new range of data items
+     */
+    private void onDataChange(Range range) {
+        assert range.getStart() == 0 && range.getEnd() == getDataSource()
+                .size() : "NativeSelect only supports full updates, but got range "
+                        + range;
+
+        final VNativeSelect select = getWidget();
+        final int itemCount = select.getItemCount();
+
+        for (int i = range.getStart(); i < range.getEnd(); i++) {
+
+            final JsonObject row = getDataSource().getRow(i);
+
+            if (i < itemCount) {
+                // Reuse and update an existing item
+                select.setItemText(i, getRowData(row).asString());
+                select.setValue(i, getRowKey(row));
+            } else {
+                // Add new items if the new dataset is larger than the old
+                select.addItem(getRowData(row).asString(), getRowKey(row));
+            }
+        }
+
+        for (int i = select.getItemCount() - 1; i >= range.getEnd(); i--) {
+            // Remove extra items if the new dataset is smaller than the old
+            select.removeItem(i);
+        }
+    }
+}
diff --git a/server/src/main/java/com/vaadin/ui/NativeSelect.java b/server/src/main/java/com/vaadin/ui/NativeSelect.java
new file mode 100644 (file)
index 0000000..9a400a1
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+ * 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.ui;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Set;
+
+import com.vaadin.server.data.DataSource;
+import com.vaadin.shared.data.DataCommunicatorConstants;
+import com.vaadin.shared.data.selection.SelectionModel;
+import com.vaadin.shared.ui.nativeselect.NativeSelectState;
+
+/**
+ * A simple drop-down select component. Represented on the client side by a
+ * "native" HTML {@code <select>} element. Lacks advanced features such as lazy
+ * loading, filtering, and adding new items.
+ * 
+ * @author Vaadin Ltd.
+ * 
+ * @param <T>
+ *            the data item type
+ * 
+ * @see com.vaadin.ui.ComboBox
+ */
+public class NativeSelect<T> extends AbstractListing<T, SelectionModel<T>> {
+
+    /**
+     * Creates a new {@code NativeSelect} with an empty caption and no items.
+     */
+    public NativeSelect() {
+        addDataGenerator((item, json) -> json.put(
+                DataCommunicatorConstants.DATA, String.valueOf(item)));
+
+        setSelectionModel(new SelectionModel<T>() {
+
+            @Override
+            public Set<T> getSelectedItems() {
+                return Collections.emptySet();
+            }
+
+            @Override
+            public void select(T item) {
+            }
+
+            @Override
+            public void deselect(T item) {
+            }
+        });
+    }
+
+    /**
+     * Creates a new {@code NativeSelect} with the given caption and no items.
+     * 
+     * @param caption
+     *            the component caption to set, null for no caption
+     */
+    public NativeSelect(String caption) {
+        this();
+        setCaption(caption);
+    }
+
+    /**
+     * Creates a new {@code NativeSelect} with the given caption, containing the
+     * data items in the given collection.
+     * 
+     * @param caption
+     *            the component caption to set, null for no caption
+     * @param items
+     *            the data items to use, not null
+     */
+    public NativeSelect(String caption, Collection<T> items) {
+        this(caption);
+        setItems(items);
+    }
+
+    /**
+     * Creates a new {@code NativeSelect} with the given caption, using the
+     * given {@code DataSource} as the source of data items.
+     * 
+     * @param caption
+     *            the component caption to set, null for no caption
+     * @param dataSource
+     *            the source of data items to use, not null
+     */
+    public NativeSelect(String caption, DataSource<T> dataSource) {
+        this(caption);
+        setDataSource(dataSource);
+    }
+
+    @Override
+    protected NativeSelectState getState() {
+        return getState(true);
+    }
+
+    @Override
+    protected NativeSelectState getState(boolean markAsDirty) {
+        return (NativeSelectState) super.getState(markAsDirty);
+    }
+}
diff --git a/shared/src/main/java/com/vaadin/shared/ui/nativeselect/NativeSelectState.java b/shared/src/main/java/com/vaadin/shared/ui/nativeselect/NativeSelectState.java
new file mode 100644 (file)
index 0000000..f5a6248
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * 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.shared.ui.nativeselect;
+
+import com.vaadin.shared.ui.AbstractSingleSelectState;
+
+/**
+ * Shared state for {@code NativeSelect}.
+ *
+ * @author Vaadin Ltd.
+ *
+ * @since 8.0
+ */
+public class NativeSelectState extends AbstractSingleSelectState {
+
+    /**
+     * The default primary style name for {@code NativeSelect}.
+     */
+    public static final String STYLE_NAME = "v-nativeselect";
+
+    {
+        primaryStyleName = STYLE_NAME;
+    }
+}
diff --git a/uitest-common/src/main/java/com/vaadin/testbench/customelements/NativeSelectElement.java b/uitest-common/src/main/java/com/vaadin/testbench/customelements/NativeSelectElement.java
new file mode 100644 (file)
index 0000000..e5d572e
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * 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.testbench.customelements;
+
+import java.util.List;
+
+import org.openqa.selenium.support.ui.Select;
+
+import com.vaadin.testbench.TestBenchElement;
+import com.vaadin.testbench.elements.AbstractSelectElement;
+import com.vaadin.testbench.elementsbase.ServerClass;
+
+@ServerClass("com.vaadin.ui.NativeSelect")
+public class NativeSelectElement extends AbstractSelectElement {
+    private Select selectElement;
+
+    @Override
+    protected void init() {
+        super.init();
+        selectElement = new Select(this);
+    }
+
+    public List<TestBenchElement> getOptions() {
+        return wrapElements(selectElement.getOptions(), getCommandExecutor());
+    }
+
+    public void selectByText(String text) throws ReadOnlyException {
+        if (isReadOnly()) {
+            throw new ReadOnlyException();
+        }
+        selectElement.selectByVisibleText(text);
+        waitForVaadin();
+    }
+
+    /**
+     * Clear operation is not supported for Native Select. This operation has no
+     * effect on Native Select element.
+     */
+    @Override
+    public void clear() {
+        super.clear();
+    }
+
+    /**
+     * Return value of the selected item in the native select element
+     *
+     * @return value of the selected item in the native select element
+     */
+    public String getValue() {
+        return selectElement.getFirstSelectedOption().getText();
+    }
+
+    /**
+     * Select item of the native select element with the specified value
+     *
+     * @param chars
+     *            value of the native select item will be selected
+     */
+    public void setValue(CharSequence chars) throws ReadOnlyException {
+        selectByText((String) chars);
+    }
+}
index e9fd2d0c36db7653b77f3435a915cc4376958368..6267890535b546aa1184015c6e8b8320265a197d 100644 (file)
@@ -3,20 +3,22 @@ package com.vaadin.tests.components.abstractlisting;
 import java.util.LinkedHashMap;
 import java.util.stream.IntStream;
 
+import com.vaadin.annotations.Widgetset;
 import com.vaadin.tests.components.AbstractComponentTest;
 import com.vaadin.ui.AbstractListing;
 
-public abstract class AbstractListingTestUI<T extends AbstractListing<Object, ?>, V>
+@Widgetset("com.vaadin.DefaultWidgetSet")
+public abstract class AbstractListingTestUI<T extends AbstractListing<Object, ?>>
         extends AbstractComponentTest<T> {
 
     @Override
     protected void createActions() {
         super.createActions();
-        createItemsSelect();
-        createSelectionSelect();
+        createItemsMenu();
+        createSelectionMenu();
     }
 
-    protected void createItemsSelect() {
+    protected void createItemsMenu() {
         LinkedHashMap<String, Integer> options = new LinkedHashMap<>();
         for (int i = 0; i <= 10; i++) {
             options.put(String.valueOf(i), i);
@@ -33,7 +35,7 @@ public abstract class AbstractListingTestUI<T extends AbstractListing<Object, ?>
                 });
     }
 
-    protected void createSelectionSelect() {
+    protected void createSelectionMenu() {
         LinkedHashMap<String, String> options = new LinkedHashMap<>();
         options.put("None", null);
         options.put("Item 0", "Item 0");
@@ -53,7 +55,7 @@ public abstract class AbstractListingTestUI<T extends AbstractListing<Object, ?>
     }
 
     protected Object[] createItems(int number) {
-        return IntStream.rangeClosed(0, number)
+        return IntStream.range(0, number)
                 .mapToObj(i -> "Item " + i)
                 .toArray();
     }
diff --git a/uitest/src/main/java/com/vaadin/tests/components/nativeselect/NativeSelects.java b/uitest/src/main/java/com/vaadin/tests/components/nativeselect/NativeSelects.java
new file mode 100644 (file)
index 0000000..3338f81
--- /dev/null
@@ -0,0 +1,14 @@
+package com.vaadin.tests.components.nativeselect;
+
+import com.vaadin.tests.components.abstractlisting.AbstractListingTestUI;
+import com.vaadin.ui.NativeSelect;
+
+public class NativeSelects extends
+        AbstractListingTestUI<NativeSelect<Object>> {
+
+    @Override
+    @SuppressWarnings({ "unchecked", "rawtypes" })
+    protected Class<NativeSelect<Object>> getTestClass() {
+        return (Class) NativeSelect.class;
+    }
+}
diff --git a/uitest/src/test/java/com/vaadin/tests/components/nativeselect/NativeSelectTest.java b/uitest/src/test/java/com/vaadin/tests/components/nativeselect/NativeSelectTest.java
new file mode 100644 (file)
index 0000000..ae97163
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * 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.tests.components.nativeselect;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import com.vaadin.testbench.TestBenchElement;
+import com.vaadin.testbench.customelements.NativeSelectElement;
+import com.vaadin.tests.tb3.MultiBrowserTest;
+
+public class NativeSelectTest extends MultiBrowserTest {
+
+    @Before
+    public void setUp() {
+        openTestURL();
+    }
+
+    @Test
+    public void initialLoad_containsCorrectItems() {
+        assertItems(20);
+    }
+
+    @Test
+    public void initialItems_reduceItemCount_containsCorrectItems() {
+        selectMenuPath("Component", "Data source", "Items", "5");
+        assertItems(5);
+    }
+
+    @Test
+    public void initialItems_increaseItemCount_containsCorrectItems() {
+        selectMenuPath("Component", "Data source", "Items", "100");
+        assertItems(100);
+    }
+
+    @Override
+    protected Class<?> getUIClass() {
+        return NativeSelects.class;
+    }
+
+    protected NativeSelectElement getSelect() {
+        return $(NativeSelectElement.class).first();
+    }
+
+    protected void assertItems(int count) {
+        int i = 0;
+        for (TestBenchElement e : getSelect().getOptions()) {
+            assertEquals("Item " + i, e.getText());
+            i++;
+        }
+        assertEquals("Number of items", count, i);
+    }
+}