aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--client/src/main/java/com/vaadin/client/ui/VCustomField.java59
-rw-r--r--client/src/main/java/com/vaadin/client/ui/customfield/CustomFieldConnector.java45
-rw-r--r--compatibility-client/src/main/java/com/vaadin/v7/client/ui/VCustomField.java60
-rw-r--r--compatibility-client/src/main/java/com/vaadin/v7/client/ui/customfield/CustomFieldConnector.java35
-rw-r--r--compatibility-server/src/main/java/com/vaadin/v7/ui/CustomField.java51
-rw-r--r--compatibility-shared/src/main/java/com/vaadin/v7/shared/AbstractFieldState.java10
-rw-r--r--server/src/main/java/com/vaadin/ui/CustomField.java50
-rw-r--r--shared/src/main/java/com/vaadin/shared/ui/customfield/CustomFieldState.java9
-rw-r--r--uitest/src/main/java/com/vaadin/tests/components/grid/GridEditorCustomField.java144
-rw-r--r--uitest/src/main/java/com/vaadin/tests/fieldgroup/ComplexPerson.java20
-rw-r--r--uitest/src/main/java/com/vaadin/v7/tests/components/grid/GridEditorCustomField.java100
-rw-r--r--uitest/src/test/java/com/vaadin/tests/components/grid/GridEditorCustomFieldTest.java (renamed from uitest/src/test/java/com/vaadin/v7/tests/components/grid/GridEditorCustomFieldTest.java)19
12 files changed, 487 insertions, 115 deletions
diff --git a/client/src/main/java/com/vaadin/client/ui/VCustomField.java b/client/src/main/java/com/vaadin/client/ui/VCustomField.java
new file mode 100644
index 0000000000..2d5039fcd8
--- /dev/null
+++ b/client/src/main/java/com/vaadin/client/ui/VCustomField.java
@@ -0,0 +1,59 @@
+/*
+ * 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.vaadin.client.Focusable;
+
+public class VCustomField extends VCustomComponent implements Focusable {
+
+ private Focusable focusDelegate;
+
+ @Override
+ public void focus() {
+ if (focusDelegate != null) {
+ focusDelegate.focus();
+ }
+ }
+
+ /**
+ * Sets the focusable widget to focus instead of this custom field.
+ *
+ * @param focusDelegate
+ * the widget to delegate focus to
+ */
+ public void setFocusDelegate(Focusable focusDelegate) {
+ this.focusDelegate = focusDelegate;
+
+ }
+
+ /**
+ * Sets the focusable widget to focus instead of this custom field.
+ *
+ * @param focusDelegate
+ * the widget to delegate focus to
+ */
+ public void setFocusDelegate(
+ final com.google.gwt.user.client.ui.Focusable focusDelegate) {
+ this.focusDelegate = new Focusable() {
+ @Override
+ public void focus() {
+ focusDelegate.setFocus(true);
+ }
+ };
+
+ }
+
+}
diff --git a/client/src/main/java/com/vaadin/client/ui/customfield/CustomFieldConnector.java b/client/src/main/java/com/vaadin/client/ui/customfield/CustomFieldConnector.java
index c058522c4e..47c9da6732 100644
--- a/client/src/main/java/com/vaadin/client/ui/customfield/CustomFieldConnector.java
+++ b/client/src/main/java/com/vaadin/client/ui/customfield/CustomFieldConnector.java
@@ -17,15 +17,18 @@ package com.vaadin.client.ui.customfield;
import java.util.Collections;
import java.util.List;
+import java.util.logging.Logger;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.user.client.ui.Widget;
import com.vaadin.client.ComponentConnector;
import com.vaadin.client.ConnectorHierarchyChangeEvent;
import com.vaadin.client.ConnectorHierarchyChangeEvent.ConnectorHierarchyChangeHandler;
+import com.vaadin.client.Focusable;
import com.vaadin.client.HasComponentsConnector;
+import com.vaadin.client.communication.StateChangeEvent;
import com.vaadin.client.ui.AbstractFieldConnector;
-import com.vaadin.client.ui.VCustomComponent;
+import com.vaadin.client.ui.VCustomField;
import com.vaadin.shared.ui.Connect;
import com.vaadin.shared.ui.customfield.CustomFieldState;
import com.vaadin.ui.CustomField;
@@ -44,8 +47,13 @@ public class CustomFieldConnector extends AbstractFieldConnector
}
@Override
- public VCustomComponent getWidget() {
- return (VCustomComponent) super.getWidget();
+ public CustomFieldState getState() {
+ return (CustomFieldState) super.getState();
+ }
+
+ @Override
+ public VCustomField getWidget() {
+ return (VCustomField) super.getWidget();
}
@Override
@@ -54,6 +62,32 @@ public class CustomFieldConnector extends AbstractFieldConnector
}
@Override
+ public void onStateChanged(StateChangeEvent stateChangeEvent) {
+ super.onStateChanged(stateChangeEvent);
+ if (getState().focusDelegate != null) {
+ Widget widget = ((ComponentConnector) getState().focusDelegate)
+ .getWidget();
+ if (widget instanceof Focusable) {
+ getWidget().setFocusDelegate((Focusable) widget);
+ } else if (widget instanceof com.google.gwt.user.client.ui.Focusable) {
+ getWidget().setFocusDelegate(
+ (com.google.gwt.user.client.ui.Focusable) widget);
+ } else {
+ getLogger().warning(
+ "The given focus delegate does not implement Focusable: "
+ + widget.getClass().getName());
+ }
+ } else {
+ getWidget().setFocusDelegate((Focusable) null);
+ }
+
+ }
+
+ private static Logger getLogger() {
+ return Logger.getLogger(CustomFieldConnector.class.getName());
+ }
+
+ @Override
public void onConnectorHierarchyChange(
ConnectorHierarchyChangeEvent event) {
// We always have 1 child, unless the child is hidden
@@ -122,9 +156,4 @@ public class CustomFieldConnector extends AbstractFieldConnector
}
}
- @Override
- public CustomFieldState getState() {
- return (CustomFieldState) super.getState();
- }
-
}
diff --git a/compatibility-client/src/main/java/com/vaadin/v7/client/ui/VCustomField.java b/compatibility-client/src/main/java/com/vaadin/v7/client/ui/VCustomField.java
new file mode 100644
index 0000000000..f826e5d620
--- /dev/null
+++ b/compatibility-client/src/main/java/com/vaadin/v7/client/ui/VCustomField.java
@@ -0,0 +1,60 @@
+/*
+ * 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.v7.client.ui;
+
+import com.vaadin.client.Focusable;
+
+@Deprecated
+public class VCustomField extends VCustomComponent implements Focusable {
+
+ private Focusable focusDelegate;
+
+ @Override
+ public void focus() {
+ if (focusDelegate != null) {
+ focusDelegate.focus();
+ }
+ }
+
+ /**
+ * Sets the focusable widget to focus instead of this custom field.
+ *
+ * @param focusDelegate
+ * the widget to delegate focus to
+ */
+ public void setFocusDelegate(Focusable focusDelegate) {
+ this.focusDelegate = focusDelegate;
+
+ }
+
+ /**
+ * Sets the focusable widget to focus instead of this custom field.
+ *
+ * @param focusDelegate
+ * the widget to delegate focus to
+ */
+ public void setFocusDelegate(
+ final com.google.gwt.user.client.ui.Focusable focusDelegate) {
+ this.focusDelegate = new Focusable() {
+ @Override
+ public void focus() {
+ focusDelegate.setFocus(true);
+ }
+ };
+
+ }
+
+}
diff --git a/compatibility-client/src/main/java/com/vaadin/v7/client/ui/customfield/CustomFieldConnector.java b/compatibility-client/src/main/java/com/vaadin/v7/client/ui/customfield/CustomFieldConnector.java
index 2d26c7c040..f72672b43d 100644
--- a/compatibility-client/src/main/java/com/vaadin/v7/client/ui/customfield/CustomFieldConnector.java
+++ b/compatibility-client/src/main/java/com/vaadin/v7/client/ui/customfield/CustomFieldConnector.java
@@ -17,16 +17,19 @@ package com.vaadin.v7.client.ui.customfield;
import java.util.Collections;
import java.util.List;
+import java.util.logging.Logger;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.user.client.ui.Widget;
import com.vaadin.client.ComponentConnector;
import com.vaadin.client.ConnectorHierarchyChangeEvent;
import com.vaadin.client.ConnectorHierarchyChangeEvent.ConnectorHierarchyChangeHandler;
+import com.vaadin.client.Focusable;
import com.vaadin.client.HasComponentsConnector;
+import com.vaadin.client.communication.StateChangeEvent;
import com.vaadin.shared.ui.Connect;
import com.vaadin.v7.client.ui.AbstractFieldConnector;
-import com.vaadin.v7.client.ui.VCustomComponent;
+import com.vaadin.v7.client.ui.VCustomField;
import com.vaadin.v7.ui.CustomField;
@Connect(value = CustomField.class)
@@ -43,8 +46,8 @@ public class CustomFieldConnector extends AbstractFieldConnector
}
@Override
- public VCustomComponent getWidget() {
- return (VCustomComponent) super.getWidget();
+ public VCustomField getWidget() {
+ return (VCustomField) super.getWidget();
}
@Override
@@ -53,6 +56,32 @@ public class CustomFieldConnector extends AbstractFieldConnector
}
@Override
+ public void onStateChanged(StateChangeEvent stateChangeEvent) {
+ super.onStateChanged(stateChangeEvent);
+ if (getState().focusDelegate != null) {
+ Widget widget = ((ComponentConnector) getState().focusDelegate)
+ .getWidget();
+ if (widget instanceof Focusable) {
+ getWidget().setFocusDelegate((Focusable) widget);
+ } else if (widget instanceof com.google.gwt.user.client.ui.Focusable) {
+ getWidget().setFocusDelegate(
+ (com.google.gwt.user.client.ui.Focusable) widget);
+ } else {
+ getLogger().warning(
+ "The given focus delegate does not implement Focusable: "
+ + widget.getClass().getName());
+ }
+ } else {
+ getWidget().setFocusDelegate((Focusable) null);
+ }
+
+ }
+
+ private static Logger getLogger() {
+ return Logger.getLogger(CustomFieldConnector.class.getName());
+ }
+
+ @Override
public void onConnectorHierarchyChange(
ConnectorHierarchyChangeEvent event) {
// We always have 1 child, unless the child is hidden
diff --git a/compatibility-server/src/main/java/com/vaadin/v7/ui/CustomField.java b/compatibility-server/src/main/java/com/vaadin/v7/ui/CustomField.java
index 989bef22ec..c2e6c3f40f 100644
--- a/compatibility-server/src/main/java/com/vaadin/v7/ui/CustomField.java
+++ b/compatibility-server/src/main/java/com/vaadin/v7/ui/CustomField.java
@@ -130,7 +130,7 @@ public abstract class CustomField<T> extends AbstractField<T>
private class ComponentIterator
implements Iterator<Component>, Serializable {
- boolean first = (root != null);
+ boolean first = root != null;
@Override
public boolean hasNext() {
@@ -153,4 +153,53 @@ public abstract class CustomField<T> extends AbstractField<T>
public Iterator<Component> iterator() {
return new ComponentIterator();
}
+
+ /**
+ * Sets the component to which all methods from the {@link Focusable}
+ * interface should be delegated.
+ * <p>
+ * Set this to a wrapped field to include that field in the tabbing order,
+ * to make it receive focus when {@link #focus()} is called and to make it
+ * be correctly focused when used as a Grid editor component.
+ * <p>
+ * By default, {@link Focusable} events are handled by the super class and
+ * ultimately ignored.
+ *
+ * @param focusDelegate
+ * the focusable component to which focus events are redirected
+ */
+ public void setFocusDelegate(Focusable focusDelegate) {
+ getState().focusDelegate = focusDelegate;
+ }
+
+ private Focusable getFocusable() {
+ return (Focusable) getState(false).focusDelegate;
+ }
+
+ @Override
+ public void focus() {
+ if (getFocusable() != null) {
+ getFocusable().focus();
+ } else {
+ super.focus();
+ }
+ }
+
+ @Override
+ public int getTabIndex() {
+ if (getFocusable() != null) {
+ return getFocusable().getTabIndex();
+ } else {
+ return super.getTabIndex();
+ }
+ }
+
+ @Override
+ public void setTabIndex(int tabIndex) {
+ if (getFocusable() != null) {
+ getFocusable().setTabIndex(tabIndex);
+ } else {
+ super.setTabIndex(tabIndex);
+ }
+ }
}
diff --git a/compatibility-shared/src/main/java/com/vaadin/v7/shared/AbstractFieldState.java b/compatibility-shared/src/main/java/com/vaadin/v7/shared/AbstractFieldState.java
index 36e65acabe..8f69abc302 100644
--- a/compatibility-shared/src/main/java/com/vaadin/v7/shared/AbstractFieldState.java
+++ b/compatibility-shared/src/main/java/com/vaadin/v7/shared/AbstractFieldState.java
@@ -15,6 +15,7 @@
*/
package com.vaadin.v7.shared;
+import com.vaadin.shared.Connector;
import com.vaadin.shared.annotations.NoLayout;
/**
@@ -34,4 +35,13 @@ public class AbstractFieldState extends AbstractLegacyComponentState {
*/
@NoLayout
public int tabIndex = 0;
+
+ /**
+ * The component which should receive focus events instead of the custom
+ * field wrapper.
+ * <p>
+ * This is not used in all fields, but needs to be here for the time being
+ * (#20468).
+ */
+ public Connector focusDelegate;
}
diff --git a/server/src/main/java/com/vaadin/ui/CustomField.java b/server/src/main/java/com/vaadin/ui/CustomField.java
index 397346a8cb..8738bad2dc 100644
--- a/server/src/main/java/com/vaadin/ui/CustomField.java
+++ b/server/src/main/java/com/vaadin/ui/CustomField.java
@@ -155,4 +155,54 @@ public abstract class CustomField<T> extends AbstractField<T>
public Iterator<Component> iterator() {
return new ComponentIterator();
}
+
+ /**
+ * Sets the component to which all methods from the {@link Focusable}
+ * interface should be delegated.
+ * <p>
+ * Set this to a wrapped field to include that field in the tabbing order,
+ * to make it receive focus when {@link #focus()} is called and to make it
+ * be correctly focused when used as a Grid editor component.
+ * <p>
+ * By default, {@link Focusable} events are handled by the super class and
+ * ultimately ignored.
+ *
+ * @param focusDelegate
+ * the focusable component to which focus events are redirected
+ */
+ public void setFocusDelegate(Focusable focusDelegate) {
+ getState().focusDelegate = focusDelegate;
+ }
+
+ private Focusable getFocusable() {
+ return (Focusable) getState(false).focusDelegate;
+ }
+
+ @Override
+ public void focus() {
+ if (getFocusable() != null) {
+ getFocusable().focus();
+ } else {
+ super.focus();
+ }
+ }
+
+ @Override
+ public int getTabIndex() {
+ if (getFocusable() != null) {
+ return getFocusable().getTabIndex();
+ } else {
+ return super.getTabIndex();
+ }
+ }
+
+ @Override
+ public void setTabIndex(int tabIndex) {
+ if (getFocusable() != null) {
+ getFocusable().setTabIndex(tabIndex);
+ } else {
+ super.setTabIndex(tabIndex);
+ }
+ }
+
}
diff --git a/shared/src/main/java/com/vaadin/shared/ui/customfield/CustomFieldState.java b/shared/src/main/java/com/vaadin/shared/ui/customfield/CustomFieldState.java
index 467a5ebe99..2884f77d6b 100644
--- a/shared/src/main/java/com/vaadin/shared/ui/customfield/CustomFieldState.java
+++ b/shared/src/main/java/com/vaadin/shared/ui/customfield/CustomFieldState.java
@@ -16,14 +16,21 @@
package com.vaadin.shared.ui.customfield;
import com.vaadin.shared.AbstractFieldState;
+import com.vaadin.shared.Connector;
/**
* State class for CustomField.
- *
+ *
* @author Vaadin Ltd
* @since 8.0
*
*/
public class CustomFieldState extends AbstractFieldState {
+ /**
+ * The component which should receive focus events instead of the custom
+ * field wrapper.
+ */
+ public Connector focusDelegate;
+
}
diff --git a/uitest/src/main/java/com/vaadin/tests/components/grid/GridEditorCustomField.java b/uitest/src/main/java/com/vaadin/tests/components/grid/GridEditorCustomField.java
new file mode 100644
index 0000000000..409147ff9b
--- /dev/null
+++ b/uitest/src/main/java/com/vaadin/tests/components/grid/GridEditorCustomField.java
@@ -0,0 +1,144 @@
+/*
+ * 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.grid;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import com.vaadin.annotations.Theme;
+import com.vaadin.data.Binder;
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.server.data.ListDataProvider;
+import com.vaadin.server.data.Query;
+import com.vaadin.tests.components.AbstractTestUIWithLog;
+import com.vaadin.tests.fieldgroup.ComplexPerson;
+import com.vaadin.ui.Button;
+import com.vaadin.ui.ComboBox;
+import com.vaadin.ui.Component;
+import com.vaadin.ui.CustomField;
+import com.vaadin.ui.Grid;
+import com.vaadin.ui.HorizontalLayout;
+import com.vaadin.ui.TextField;
+
+@Theme("tests-valo-disabled-animations")
+public class GridEditorCustomField extends AbstractTestUIWithLog {
+
+ private static final String LAST_NAME_IDENTIFIER = "lastName";
+ private static final String FIRST_NAME_IDENTIFIER = "firstName";
+ private static final String ADDRESS_CITY_IDENTIFIER = "address.city";
+
+ @Override
+ protected void setup(VaadinRequest request) {
+ Grid<ComplexPerson> grid = createGrid();
+
+ ListDataProvider<ComplexPerson> dataProvider = ComplexPerson
+ .createDataProvider(100);
+
+ grid.setDataProvider(dataProvider);
+
+ Set<String> cities = new HashSet<>();
+ dataProvider.fetch(new Query<>()).forEach(person -> {
+ cities.add(person.getAddress().getCity());
+ });
+ CustomCitySelect cityEditor = new CustomCitySelect(
+ cities.toArray(new String[cities.size()]));
+
+ TextField firstNameField = new TextField();
+ TextField lastNameField = new TextField();
+ Binder<ComplexPerson> binder = new Binder<>();
+
+ binder.bind(firstNameField, ComplexPerson::getFirstName,
+ ComplexPerson::setFirstName);
+ binder.bind(lastNameField, ComplexPerson::getLastName,
+ ComplexPerson::setLastName);
+ binder.bind(cityEditor, person -> person.getAddress().getCity(),
+ (person, city) -> person.getAddress().setCity(city));
+
+ grid.getEditor().setBinder(binder);
+ grid.getColumn(ADDRESS_CITY_IDENTIFIER).setEditorComponent(cityEditor);
+ grid.getColumn(FIRST_NAME_IDENTIFIER)
+ .setEditorComponent(firstNameField);
+ grid.getColumn(LAST_NAME_IDENTIFIER).setEditorComponent(lastNameField);
+
+ addComponent(grid);
+ }
+
+ private Grid<ComplexPerson> createGrid() {
+ Grid<ComplexPerson> grid = new Grid<>();
+ grid.setWidth("800px");
+ grid.addColumn(FIRST_NAME_IDENTIFIER, person -> person.getFirstName())
+ .setCaption("First Name");
+ grid.addColumn(LAST_NAME_IDENTIFIER, person -> person.getLastName())
+ .setCaption("Last Name");
+ grid.addColumn(ADDRESS_CITY_IDENTIFIER,
+ person -> person.getAddress().getCity())
+ .setCaption("City Name");
+ grid.getEditor().setEnabled(true);
+
+ return grid;
+ }
+
+ public static class CustomCitySelect extends CustomField<String> {
+ private HorizontalLayout fieldLayout;
+ private String[] values;
+ private ComboBox<String> cityComboBox;
+ private String cachedValue;
+
+ public CustomCitySelect(String... values) {
+ this.values = values;
+ }
+
+ @Override
+ protected Component initContent() {
+ fieldLayout = new HorizontalLayout();
+ fieldLayout.setWidth("100%");
+
+ cityComboBox = new ComboBox<>();
+ cityComboBox.setItems(values);
+ if (cachedValue != null) {
+ cityComboBox.setValue(cachedValue);
+ cachedValue = null;
+ }
+
+ fieldLayout.addComponent(cityComboBox);
+ fieldLayout.setExpandRatio(cityComboBox, 1.0f);
+
+ Button addCountryButton = new Button("New");
+ fieldLayout.addComponent(addCountryButton);
+
+ setFocusDelegate(cityComboBox);
+
+ return fieldLayout;
+ }
+
+ @Override
+ public String getValue() {
+ if (cityComboBox == null) {
+ return null;
+ }
+ return cityComboBox.getValue();
+ }
+
+ @Override
+ protected void doSetValue(String value) {
+ if (cityComboBox == null) {
+ getContent();
+ }
+ cityComboBox.setValue(value);
+ }
+ }
+
+}
diff --git a/uitest/src/main/java/com/vaadin/tests/fieldgroup/ComplexPerson.java b/uitest/src/main/java/com/vaadin/tests/fieldgroup/ComplexPerson.java
index c2aeb51bab..8e355484b9 100644
--- a/uitest/src/main/java/com/vaadin/tests/fieldgroup/ComplexPerson.java
+++ b/uitest/src/main/java/com/vaadin/tests/fieldgroup/ComplexPerson.java
@@ -1,9 +1,13 @@
package com.vaadin.tests.fieldgroup;
import java.math.BigDecimal;
+import java.util.ArrayList;
import java.util.Date;
+import java.util.List;
import java.util.Random;
+import com.vaadin.server.data.DataProvider;
+import com.vaadin.server.data.ListDataProvider;
import com.vaadin.tests.util.TestDataGenerator;
import com.vaadin.v7.data.util.BeanItemContainer;
@@ -25,6 +29,10 @@ public class ComplexPerson {
this.firstName = firstName;
}
+ public void setLastName(String firstName) {
+ this.firstName = firstName;
+ }
+
public String getLastName() {
return lastName;
}
@@ -90,6 +98,18 @@ public class ComplexPerson {
return bic;
}
+ public static ListDataProvider<ComplexPerson> createDataProvider(int size) {
+ List<ComplexPerson> list = new ArrayList<>();
+ Random r = new Random(size);
+
+ for (int i = 0; i < size; i++) {
+ ComplexPerson cp = ComplexPerson.create(r);
+ list.add(cp);
+ }
+
+ return DataProvider.create(list);
+ }
+
public static ComplexPerson create(Random r) {
ComplexPerson cp = new ComplexPerson();
cp.setFirstName(TestDataGenerator.getFirstName(r));
diff --git a/uitest/src/main/java/com/vaadin/v7/tests/components/grid/GridEditorCustomField.java b/uitest/src/main/java/com/vaadin/v7/tests/components/grid/GridEditorCustomField.java
deleted file mode 100644
index 22efd2b6c6..0000000000
--- a/uitest/src/main/java/com/vaadin/v7/tests/components/grid/GridEditorCustomField.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * 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.v7.tests.components.grid;
-
-import java.util.HashSet;
-import java.util.Set;
-
-import com.vaadin.server.VaadinRequest;
-import com.vaadin.tests.components.AbstractTestUIWithLog;
-import com.vaadin.tests.fieldgroup.ComplexPerson;
-import com.vaadin.ui.Button;
-import com.vaadin.ui.Component;
-import com.vaadin.ui.HorizontalLayout;
-import com.vaadin.v7.ui.ComboBox;
-import com.vaadin.v7.ui.CustomField;
-import com.vaadin.v7.ui.Grid;
-
-public class GridEditorCustomField extends AbstractTestUIWithLog {
-
- @Override
- protected void setup(VaadinRequest request) {
- Grid grid = new PersonTestGrid(100);
- grid.setWidth("800px");
- grid.setColumns("firstName", "lastName", "address.city");
- grid.setEditorEnabled(true);
- Set<String> cities = new HashSet<>();
- for (Object o : grid.getContainerDataSource().getItemIds()) {
- ComplexPerson p = (ComplexPerson) o;
- cities.add(p.getAddress().getCity());
- }
- CustomCitySelect cityEditor = new CustomCitySelect(
- cities.toArray(new String[cities.size()]));
- grid.getColumn("address.city").setEditorField(cityEditor);
- addComponent(grid);
- }
-
- public static class CustomCitySelect extends CustomField<String> {
- private HorizontalLayout fieldLayout;
- private String[] values;
- private ComboBox cityComboBox;
-
- public CustomCitySelect(String... values) {
- this.values = values;
- }
-
- @Override
- protected Component initContent() {
- fieldLayout = new HorizontalLayout();
- fieldLayout.setWidth("100%");
-
- cityComboBox = new ComboBox();
- for (String value : values) {
- cityComboBox.addItem(value);
- }
- fieldLayout.addComponent(cityComboBox);
- fieldLayout.setExpandRatio(cityComboBox, 1.0f);
-
- Button addCountryButton = new Button("New");
- fieldLayout.addComponent(addCountryButton);
-
- return fieldLayout;
- }
-
- @Override
- public Class<String> getType() {
- return String.class;
- }
-
- @Override
- protected void setInternalValue(String newValue) {
- super.setInternalValue(newValue);
- if (cityComboBox == null) {
- return;
- }
- cityComboBox.setValue(newValue);
- }
-
- @Override
- public String getInternalValue() {
- if (cityComboBox == null) {
- return null;
- }
- return (String) cityComboBox.getValue();
- }
- }
-
-}
diff --git a/uitest/src/test/java/com/vaadin/v7/tests/components/grid/GridEditorCustomFieldTest.java b/uitest/src/test/java/com/vaadin/tests/components/grid/GridEditorCustomFieldTest.java
index f7b56f53d6..77d54dd93b 100644
--- a/uitest/src/test/java/com/vaadin/v7/tests/components/grid/GridEditorCustomFieldTest.java
+++ b/uitest/src/test/java/com/vaadin/tests/components/grid/GridEditorCustomFieldTest.java
@@ -13,17 +13,18 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.vaadin.v7.tests.components.grid;
+package com.vaadin.tests.components.grid;
import org.junit.Assert;
import org.junit.Test;
+import org.openqa.selenium.Keys;
import com.vaadin.testbench.TestBenchElement;
import com.vaadin.testbench.customelements.ComboBoxElement;
+import com.vaadin.testbench.customelements.GridElement;
import com.vaadin.testbench.elements.GridElement.GridEditorElement;
import com.vaadin.testbench.parallel.TestCategory;
import com.vaadin.tests.tb3.MultiBrowserTest;
-import com.vaadin.testbench.customelements.GridElement;
@TestCategory("grid")
public class GridEditorCustomFieldTest extends MultiBrowserTest {
@@ -43,4 +44,18 @@ public class GridEditorCustomFieldTest extends MultiBrowserTest {
Assert.assertEquals("Oslo", grid.getCell(0, 2).getText());
}
+
+ @Test
+ public void tabReachesCustomField() {
+ openTestURL();
+ GridElement grid = $(GridElement.class).first();
+ grid.getCell(0, 1).doubleClick();
+ GridEditorElement editor = grid.getEditor();
+ editor.getField(0).sendKeys(Keys.TAB, Keys.TAB);
+
+ ComboBoxElement comboBoxInCustomField = editor.getField(2)
+ .$(ComboBoxElement.class).first();
+ assertElementsEquals(comboBoxInCustomField.getInputField(),
+ getActiveElement());
+ }
}