diff options
author | Denis Anisimov <denis@vaadin.com> | 2016-08-18 16:24:17 +0300 |
---|---|---|
committer | Vaadin Code Review <review@vaadin.com> | 2016-08-19 08:15:38 +0000 |
commit | 9b2b19366c77f164dbb54d057373713a02447984 (patch) | |
tree | 8e73e8f11047b033f5c71c7fa70d08078f2084ce | |
parent | e7b9db54a5aa172509b33746d270ac375009b4a6 (diff) | |
download | vaadin-framework-9b2b19366c77f164dbb54d057373713a02447984.tar.gz vaadin-framework-9b2b19366c77f164dbb54d057373713a02447984.zip |
CustomField migration to new AbstractField (#61).
Change-Id: I33dd7aa2cf91ba2606a602c8ba612bcc30b02622
6 files changed, 232 insertions, 51 deletions
diff --git a/client/src/main/java/com/vaadin/client/legacy/ui/LegacyCustomFieldConnector.java b/client/src/main/java/com/vaadin/client/legacy/ui/LegacyCustomFieldConnector.java new file mode 100644 index 0000000000..eca56612cb --- /dev/null +++ b/client/src/main/java/com/vaadin/client/legacy/ui/LegacyCustomFieldConnector.java @@ -0,0 +1,25 @@ +/* + * 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.legacy.ui; + +import com.vaadin.client.ui.customfield.CustomFieldConnector; +import com.vaadin.legacy.ui.LegacyCustomField; +import com.vaadin.shared.ui.Connect; + +@Connect(value = LegacyCustomField.class) +public class LegacyCustomFieldConnector extends CustomFieldConnector { + +} diff --git a/server/src/main/java/com/vaadin/legacy/ui/LegacyCustomField.java b/server/src/main/java/com/vaadin/legacy/ui/LegacyCustomField.java new file mode 100644 index 0000000000..4ef634e69b --- /dev/null +++ b/server/src/main/java/com/vaadin/legacy/ui/LegacyCustomField.java @@ -0,0 +1,158 @@ +/* + * 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.legacy.ui; + +import java.io.Serializable; +import java.util.Iterator; + +import com.vaadin.data.Property; +import com.vaadin.ui.Component; +import com.vaadin.ui.HasComponents; +import com.vaadin.v7.ui.LegacyAbstractField; +import com.vaadin.v7.ui.LegacyField; + +/** + * A {@link LegacyField} whose UI content can be constructed by the user, + * enabling the creation of e.g. form fields by composing Vaadin components. + * Customization of both the visual presentation and the logic of the field is + * possible. + * + * Subclasses must implement {@link #getType()} and {@link #initContent()}. + * + * Most custom fields can simply compose a user interface that calls the methods + * {@link #setInternalValue(Object)} and {@link #getInternalValue()} when + * necessary. + * + * It is also possible to override {@link #validate()}, + * {@link #setInternalValue(Object)}, {@link #commit()}, + * {@link #setPropertyDataSource(Property)}, {@link #isEmpty()} and other logic + * of the field. Methods overriding {@link #setInternalValue(Object)} should + * also call the corresponding superclass method. + * + * @param <T> + * field value type + * + * @since 7.0 + */ +public abstract class LegacyCustomField<T> extends LegacyAbstractField<T> + implements HasComponents { + + /** + * The root component implementing the custom component. + */ + private Component root = null; + + /** + * Constructs a new custom field. + * + * <p> + * The component is implemented by wrapping the methods of the composition + * root component given as parameter. The composition root must be set + * before the component can be used. + * </p> + */ + public LegacyCustomField() { + // expand horizontally by default + setWidth(100, Unit.PERCENTAGE); + } + + /** + * Constructs the content and notifies it that the {@link LegacyCustomField} + * is attached to a window. + * + * @see com.vaadin.ui.Component#attach() + */ + @Override + public void attach() { + // First call super attach to notify all children (none if content has + // not yet been created) + super.attach(); + + // If the content has not yet been created, create and attach it at + // this point by calling getContent() + getContent(); + } + + /** + * Returns the content (UI) of the custom component. + * + * @return Component + */ + protected Component getContent() { + if (null == root) { + root = initContent(); + root.setParent(this); + } + return root; + } + + /** + * Create the content component or layout for the field. Subclasses of + * {@link LegacyCustomField} should implement this method. + * + * Note that this method is called when the CustomField is attached to a + * layout or when {@link #getContent()} is called explicitly for the first + * time. It is only called once for a {@link LegacyCustomField}. + * + * @return {@link Component} representing the UI of the CustomField + */ + protected abstract Component initContent(); + + // Size related methods + // TODO might not be necessary to override but following the pattern from + // AbstractComponentContainer + + @Override + public void setHeight(float height, Unit unit) { + super.setHeight(height, unit); + markAsDirtyRecursive(); + } + + @Override + public void setWidth(float width, Unit unit) { + super.setWidth(width, unit); + markAsDirtyRecursive(); + } + + // ComponentContainer methods + + private class ComponentIterator + implements Iterator<Component>, Serializable { + boolean first = (root != null); + + @Override + public boolean hasNext() { + return first; + } + + @Override + public Component next() { + first = false; + return getContent(); + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + } + + @Override + public Iterator<Component> iterator() { + return new ComponentIterator(); + } +} diff --git a/server/src/main/java/com/vaadin/ui/CustomField.java b/server/src/main/java/com/vaadin/ui/CustomField.java index 4985560b3e..b36cb053a6 100644 --- a/server/src/main/java/com/vaadin/ui/CustomField.java +++ b/server/src/main/java/com/vaadin/ui/CustomField.java @@ -19,34 +19,25 @@ package com.vaadin.ui; import java.io.Serializable; import java.util.Iterator; -import com.vaadin.data.Property; -import com.vaadin.v7.ui.LegacyAbstractField; -import com.vaadin.v7.ui.LegacyField; +import com.vaadin.data.HasValue; /** - * A {@link LegacyField} whose UI content can be constructed by the user, - * enabling the creation of e.g. form fields by composing Vaadin components. + * A {@link HasValue} whose UI content can be constructed by the user, enabling + * the creation of e.g. form fields by composing Vaadin components. * Customization of both the visual presentation and the logic of the field is * possible. - * + * <p> * Subclasses must implement {@link #getType()} and {@link #initContent()}. - * + * <p> * Most custom fields can simply compose a user interface that calls the methods - * {@link #setInternalValue(Object)} and {@link #getInternalValue()} when - * necessary. - * - * It is also possible to override {@link #validate()}, - * {@link #setInternalValue(Object)}, {@link #commit()}, - * {@link #setPropertyDataSource(Property)}, {@link #isEmpty()} and other logic - * of the field. Methods overriding {@link #setInternalValue(Object)} should - * also call the corresponding superclass method. + * {@link #doSetValue(Object)} and {@link #getValue()} when necessary. * * @param <T> * field value type * - * @since 7.0 + * @since 8.0 */ -public abstract class CustomField<T> extends LegacyAbstractField<T> +public abstract class CustomField<T> extends AbstractField<T> implements HasComponents { /** diff --git a/uitest/src/main/java/com/vaadin/tests/components/customfield/BooleanField.java b/uitest/src/main/java/com/vaadin/tests/components/customfield/BooleanField.java index 20c004c068..355ba50143 100644 --- a/uitest/src/main/java/com/vaadin/tests/components/customfield/BooleanField.java +++ b/uitest/src/main/java/com/vaadin/tests/components/customfield/BooleanField.java @@ -1,8 +1,6 @@ package com.vaadin.tests.components.customfield; import com.vaadin.ui.Button; -import com.vaadin.ui.Button.ClickEvent; -import com.vaadin.ui.Button.ClickListener; import com.vaadin.ui.Component; import com.vaadin.ui.CustomField; import com.vaadin.ui.Label; @@ -13,7 +11,9 @@ import com.vaadin.ui.VerticalLayout; * composed of multiple components, and could also edit a more complex data * structures. Here, the commit etc. logic is not overridden. */ -public class BooleanField extends CustomField { +public class BooleanField extends CustomField<Boolean> { + + private boolean value; @Override protected Component initContent() { @@ -22,25 +22,23 @@ public class BooleanField extends CustomField { layout.addComponent(new Label("Please click the button")); final Button button = new Button("Click me"); - button.addListener(new ClickListener() { - @Override - public void buttonClick(ClickEvent event) { - Object value = getValue(); - boolean newValue = true; - if ((value instanceof Boolean) && ((Boolean) value)) { - newValue = false; - } - setValue(newValue); - button.setCaption(newValue ? "On" : "Off"); - } + button.addClickListener(event -> { + setValue(!getValue()); + button.setCaption(getValue() ? "On" : "Off"); }); layout.addComponent(button); return layout; + + } + + @Override + public Boolean getValue() { + return value; } @Override - public Class<?> getType() { - return Boolean.class; + protected void doSetValue(Boolean value) { + this.value = value; } } diff --git a/uitest/src/main/java/com/vaadin/tests/components/customfield/CustomFieldSize.java b/uitest/src/main/java/com/vaadin/tests/components/customfield/CustomFieldSize.java index efc842c767..b26f00b5a4 100644 --- a/uitest/src/main/java/com/vaadin/tests/components/customfield/CustomFieldSize.java +++ b/uitest/src/main/java/com/vaadin/tests/components/customfield/CustomFieldSize.java @@ -19,6 +19,7 @@ import com.vaadin.server.VaadinRequest; import com.vaadin.tests.components.AbstractTestUI; import com.vaadin.ui.Component; import com.vaadin.ui.CustomField; +import com.vaadin.ui.TextField; import com.vaadin.ui.VerticalLayout; import com.vaadin.v7.ui.LegacyTextField; @@ -35,21 +36,9 @@ public class CustomFieldSize extends AbstractTestUI { setContent(layout); layout.setWidth("50px"); - layout.addComponent(new LegacyTextField()); + layout.addComponent(new TextField()); - layout.addComponent(new CustomField<String>() { - - @Override - protected Component initContent() { - return new LegacyTextField(); - } - - @Override - public Class<? extends String> getType() { - return String.class; - } - - }); + layout.addComponent(new TestCustomField()); } @Override @@ -62,4 +51,24 @@ public class CustomFieldSize extends AbstractTestUI { return 12482; } + private static class TestCustomField extends CustomField<String> { + + private TextField field = new TextField(); + + @Override + protected Component initContent() { + return field; + } + + @Override + public String getValue() { + return field.getValue(); + } + + @Override + protected void doSetValue(String value) { + field.setValue(value); + } + } + } 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 index 7483e4e11c..40f4b81245 100644 --- a/uitest/src/main/java/com/vaadin/tests/components/grid/GridEditorCustomField.java +++ b/uitest/src/main/java/com/vaadin/tests/components/grid/GridEditorCustomField.java @@ -19,15 +19,15 @@ import java.util.HashSet; import java.util.Set; import com.vaadin.annotations.Theme; +import com.vaadin.legacy.ui.LegacyCustomField; 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.ComboBox; import com.vaadin.ui.Component; -import com.vaadin.ui.CustomField; -import com.vaadin.ui.LegacyGrid; import com.vaadin.ui.HorizontalLayout; +import com.vaadin.ui.LegacyGrid; @Theme("valo") public class GridEditorCustomField extends AbstractTestUIWithLog { @@ -38,7 +38,7 @@ public class GridEditorCustomField extends AbstractTestUIWithLog { grid.setWidth("800px"); grid.setColumns("firstName", "lastName", "address.city"); grid.setEditorEnabled(true); - Set<String> cities = new HashSet<String>(); + Set<String> cities = new HashSet<>(); for (Object o : grid.getContainerDataSource().getItemIds()) { ComplexPerson p = (ComplexPerson) o; cities.add(p.getAddress().getCity()); @@ -49,7 +49,7 @@ public class GridEditorCustomField extends AbstractTestUIWithLog { addComponent(grid); } - public static class CustomCitySelect extends CustomField<String> { + public static class CustomCitySelect extends LegacyCustomField<String> { private HorizontalLayout fieldLayout; private String[] values; private ComboBox cityComboBox; |