*/
package com.vaadin.ui;
+import java.util.ArrayList;
+import java.util.List;
import java.util.Objects;
+import org.jsoup.nodes.Attributes;
+import org.jsoup.nodes.Element;
+
import com.vaadin.data.Listing;
import com.vaadin.data.SelectionModel;
import com.vaadin.server.AbstractExtension;
+import com.vaadin.server.Resource;
import com.vaadin.server.data.DataCommunicator;
import com.vaadin.server.data.DataGenerator;
import com.vaadin.server.data.DataProvider;
+import com.vaadin.server.data.Query;
+import com.vaadin.ui.declarative.DesignAttributeHandler;
+import com.vaadin.ui.declarative.DesignContext;
+import com.vaadin.ui.declarative.DesignException;
+import com.vaadin.ui.declarative.DesignFormatter;
/**
* A base class for listing components. Provides common handling for fetching
*/
public abstract class AbstractListing<T> extends AbstractComponent
implements Listing<T> {
+ /**
+ * The item icon caption provider.
+ */
+ private ItemCaptionGenerator<T> itemCaptionGenerator = String::valueOf;
+
+ /**
+ * The item icon provider. It is up to the implementing class to support
+ * this or not.
+ */
+ private IconGenerator<T> itemIconGenerator = item -> null;
/**
* A helper base class for creating extensions for Listing components. This
return getDataCommunicator().getDataProvider();
}
+ /**
+ * Gets the item caption generator that is used to produce the strings shown
+ * in the combo box for each item.
+ *
+ * @return the item caption generator used, not null
+ */
+ protected ItemCaptionGenerator<T> getItemCaptionGenerator() {
+ return itemCaptionGenerator;
+ }
+
+ /**
+ * Sets the item caption generator that is used to produce the strings shown
+ * in the combo box for each item. By default,
+ * {@link String#valueOf(Object)} is used.
+ *
+ * @param itemCaptionGenerator
+ * the item caption provider to use, not null
+ */
+ protected void setItemCaptionGenerator(
+ ItemCaptionGenerator<T> itemCaptionGenerator) {
+ Objects.requireNonNull(itemCaptionGenerator,
+ "Item caption generators must not be null");
+ this.itemCaptionGenerator = itemCaptionGenerator;
+ getDataCommunicator().reset();
+ }
+
+ /**
+ * Sets the item icon generator that is used to produce custom icons for
+ * showing items in the popup. The generator can return null for items with
+ * no icon.
+ *
+ * @see IconGenerator
+ *
+ * @param itemIconGenerator
+ * the item icon generator to set, not null
+ * @throws NullPointerException
+ * if {@code itemIconGenerator} is {@code null}
+ */
+ protected void setItemIconGenerator(IconGenerator<T> itemIconGenerator) {
+ Objects.requireNonNull(itemIconGenerator,
+ "Item icon generator must not be null");
+ this.itemIconGenerator = itemIconGenerator;
+ getDataCommunicator().reset();
+ }
+
+ /**
+ * Gets the currently used item icon generator. The default item icon
+ * provider returns null for all items, resulting in no icons being used.
+ *
+ * @see IconGenerator
+ * @see #setItemIconGenerator(IconGenerator)
+ *
+ * @return the currently used item icon generator, not null
+ */
+ protected IconGenerator<T> getItemIconGenerator() {
+ return itemIconGenerator;
+ }
+
/**
* Adds the given data generator to this listing. If the generator was
* already added, does nothing.
public DataCommunicator<T> getDataCommunicator() {
return dataCommunicator;
}
+
+ @Override
+ public void writeDesign(Element design, DesignContext designContext) {
+ super.writeDesign(design, designContext);
+
+ // Write options if warranted
+ if (designContext.shouldWriteData(this)) {
+ writeItems(design, designContext);
+ }
+
+ AbstractListing<T> select = designContext.getDefaultInstance(this);
+ Attributes attr = design.attributes();
+ DesignAttributeHandler.writeAttribute("readonly", attr, isReadOnly(),
+ select.isReadOnly(), Boolean.class, designContext);
+ }
+
+ /**
+ * Writes the data source items to a design. Hierarchical select components
+ * should override this method to only write the root items.
+ *
+ * @param design
+ * the element into which to insert the items
+ * @param context
+ * the DesignContext instance used in writing
+ */
+ protected void writeItems(Element design, DesignContext context) {
+ getDataProvider().fetch(new Query<>())
+ .forEach(item -> writeItem(design, item, context));
+ }
+
+ /**
+ * Writes a data source Item to a design. Hierarchical select components
+ * should override this method to recursively write any child items as well.
+ *
+ * @param design
+ * the element into which to insert the item
+ * @param item
+ * the item to write
+ * @param context
+ * the DesignContext instance used in writing
+ * @return a JSOUP element representing the {@code item}
+ */
+ protected Element writeItem(Element design, T item, DesignContext context) {
+ Element element = design.appendElement("option");
+
+ String caption = getItemCaptionGenerator().apply(item);
+ if (caption != null) {
+ element.html(DesignFormatter.encodeForTextNode(caption));
+ } else {
+ element.html(DesignFormatter.encodeForTextNode(item.toString()));
+ }
+ element.attr("item", serializeDeclarativeRepresentation(item));
+
+ Resource icon = getItemIconGenerator().apply(item);
+ if (icon != null) {
+ DesignAttributeHandler.writeAttribute("icon", element.attributes(),
+ icon, null, Resource.class, context);
+ }
+
+ return element;
+ }
+
+ @Override
+ public void readDesign(Element design, DesignContext context) {
+ super.readDesign(design, context);
+ Attributes attr = design.attributes();
+ if (attr.hasKey("readonly")) {
+ setReadOnly(DesignAttributeHandler.readAttribute("readonly", attr,
+ Boolean.class));
+ }
+ readItems(design, context);
+ }
+
+ /**
+ * Reads the data source items from the {@code design}.
+ *
+ * @param design
+ * The element to obtain the state from
+ * @param context
+ * The DesignContext instance used for parsing the design
+ */
+ protected void readItems(Element design, DesignContext context) {
+ setItemCaptionGenerator(new DeclarativeCaptionGenerator<>());
+ setItemIconGenerator(new DeclarativeIconGenerator<>());
+ }
+
+ /**
+ * Reads an Item from a design and inserts it into the data source.
+ * <p>
+ * Doesn't care about selection/value (if any).
+ *
+ * @param child
+ * a child element representing the item
+ * @param context
+ * the DesignContext instance used in parsing
+ * @return the item id of the new item
+ *
+ * @throws DesignException
+ * if the tag name of the {@code child} element is not
+ * {@code option}.
+ */
+ @SuppressWarnings({ "rawtypes", "unchecked" })
+ protected T readItem(Element child, DesignContext context) {
+ if (!"option".equals(child.tagName())) {
+ throw new DesignException("Unrecognized child element in "
+ + getClass().getSimpleName() + ": " + child.tagName());
+ }
+
+ String serializedItem = "";
+ String caption = DesignFormatter.decodeFromTextNode(child.html());
+ List<T> items = new ArrayList<>();
+ if (child.hasAttr("item")) {
+ serializedItem = child.attr("item");
+ }
+
+ T item = deserializeDeclarativeRepresentation(serializedItem);
+ items.add(item);
+
+ ItemCaptionGenerator<T> captionGenerator = getItemCaptionGenerator();
+ if (captionGenerator instanceof DeclarativeCaptionGenerator) {
+ ((DeclarativeCaptionGenerator) captionGenerator).setCaption(item,
+ caption);
+ } else {
+ throw new IllegalStateException(String.format(
+ "Don't know how "
+ + "to set caption using current caption generator '%s'",
+ captionGenerator.getClass().getName()));
+ }
+
+ IconGenerator<T> iconGenerator = getItemIconGenerator();
+ if (child.hasAttr("icon")) {
+ if (iconGenerator instanceof DeclarativeIconGenerator) {
+ ((DeclarativeIconGenerator) iconGenerator).setIcon(item,
+ DesignAttributeHandler.readAttribute("icon",
+ child.attributes(), Resource.class));
+ } else {
+ throw new IllegalStateException(String.format(
+ "Don't know how "
+ + "to set icon using current caption generator '%s'",
+ iconGenerator.getClass().getName()));
+ }
+ }
+
+ return item;
+ }
+
+ /**
+ * Deserializes a string to a data item.
+ * <p>
+ * Default implementation is able to handle only {@link String} as an item
+ * type. There will be a {@link ClassCastException} if {@code T } is not a
+ * {@link String}.
+ *
+ * @see #serializeDeclarativeRepresentation(Object)
+ *
+ * @param item
+ * string to deserialize
+ * @throws ClassCastException
+ * if type {@code T} is not a {@link String}
+ * @return deserialized item
+ */
+ protected T deserializeDeclarativeRepresentation(String item) {
+ return (T) item;
+ }
+
+ /**
+ * Serializes an {@code item} to a string for saving declarative format.
+ * <p>
+ * Default implementation delegates a call to {@code item.toString()}.
+ *
+ * @see #serializeDeclarativeRepresentation(Object)
+ *
+ * @param item
+ * a data item
+ * @return string representation of the {@code item}.
+ */
+ protected String serializeDeclarativeRepresentation(T item) {
+ return item.toString();
+ }
}
package com.vaadin.ui;
import java.lang.reflect.Method;
+import java.util.Collection;
import java.util.Collections;
+import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Predicate;
import java.util.stream.Collectors;
+import org.jsoup.nodes.Element;
+
import com.vaadin.data.HasValue;
import com.vaadin.data.SelectionModel;
import com.vaadin.data.SelectionModel.Multi;
import com.vaadin.shared.Registration;
import com.vaadin.shared.data.selection.MultiSelectServerRpc;
import com.vaadin.shared.ui.ListingJsonConstants;
+import com.vaadin.ui.declarative.DesignContext;
+import com.vaadin.ui.declarative.DesignException;
import com.vaadin.util.ReflectTools;
import elemental.json.JsonObject;
.findMethod(MultiSelectionListener.class, "accept",
MultiSelectionEvent.class);
- /**
- * The item icon caption provider.
- */
- private ItemCaptionGenerator<T> itemCaptionGenerator = String::valueOf;
-
- /**
- * The item icon provider. It is up to the implementing class to support
- * this or not.
- */
- private IconGenerator<T> itemIconGenerator = item -> null;
-
/**
* The item enabled status provider. It is up to the implementing class to
* support this or not.
SELECTION_CHANGE_METHOD);
}
- /**
- * Gets the item caption generator that is used to produce the strings shown
- * in the select for each item.
- *
- * @return the item caption generator used, not {@code null}
- * @see #setItemCaptionGenerator(ItemCaptionGenerator)
- */
+ @Override
public ItemCaptionGenerator<T> getItemCaptionGenerator() {
- return itemCaptionGenerator;
+ return super.getItemCaptionGenerator();
}
- /**
- * Sets the item caption generator that is used to produce the strings shown
- * in the select for each item. By default, {@link String#valueOf(Object)}
- * is used.
- *
- * @param itemCaptionGenerator
- * the item caption generator to use, not {@code null}
- */
+ @Override
public void setItemCaptionGenerator(
ItemCaptionGenerator<T> itemCaptionGenerator) {
- Objects.requireNonNull(itemCaptionGenerator);
- this.itemCaptionGenerator = itemCaptionGenerator;
- getDataCommunicator().reset();
+ super.setItemCaptionGenerator(itemCaptionGenerator);
}
/**
new ValueChangeEvent<>(this, event.isUserOriginated())));
}
- /**
- * Returns the item icon generator for this multiselect.
- * <p>
- * <em>Implementation note:</em> Override this method and
- * {@link #setItemIconGenerator(IconGenerator)} as {@code public} and invoke
- * {@code super} methods to support this feature in the multiselect
- * component.
- *
- * @return the item icon generator, not {@code null}
- * @see #setItemIconGenerator(IconGenerator)
- */
- protected IconGenerator<T> getItemIconGenerator() {
- return itemIconGenerator;
- }
-
- /**
- * Sets the item icon generator for this multiselect. The icon generator is
- * queried for each item to optionally display an icon next to the item
- * caption. If the generator returns null for an item, no icon is displayed.
- * The default provider always returns null (no icons).
- * <p>
- * <em>Implementation note:</em> Override this method and
- * {@link #getItemIconGenerator()} as {@code public} and invoke
- * {@code super} methods to support this feature in the multiselect
- * component.
- *
- * @param itemIconGenerator
- * the item icon generator to set, not {@code null}
- */
- protected void setItemIconGenerator(IconGenerator<T> itemIconGenerator) {
- Objects.requireNonNull(itemIconGenerator);
- this.itemIconGenerator = itemIconGenerator;
- }
-
/**
* Returns the item enabled provider for this multiselect.
* <p>
updateSelection(set -> set.add(item), userOriginated);
}
+ @Override
+ protected Collection<String> getCustomAttributes() {
+ Collection<String> attributes = super.getCustomAttributes();
+ // "value" is not an attribute for the component. "selected" attribute
+ // is used in "option"'s tag to mark selection which implies value for
+ // multiselect component
+ attributes.add("value");
+ return attributes;
+ }
+
+ @Override
+ protected Element writeItem(Element design, T item, DesignContext context) {
+ Element element = super.writeItem(design, item, context);
+
+ if (isSelected(item)) {
+ element.attr("selected", "");
+ }
+
+ return element;
+ }
+
+ @Override
+ protected void readItems(Element design, DesignContext context) {
+ super.readItems(design, context);
+ Set<T> selected = new HashSet<>();
+ design.children().stream()
+ .forEach(child -> readItem(child, selected, context));
+ deselectAll();
+ selected.forEach(this::select);
+ }
+
+ /**
+ * Reads an Item from a design and inserts it into the data source.
+ * Hierarchical select components should override this method to recursively
+ * recursively read any child items as well.
+ *
+ * @param child
+ * a child element representing the item
+ * @param selected
+ * A set accumulating selected items. If the item that is read is
+ * marked as selected, its item id should be added to this set.
+ * @param context
+ * the DesignContext instance used in parsing
+ * @return the item id of the new item
+ *
+ * @throws DesignException
+ * if the tag name of the {@code child} element is not
+ * {@code option}.
+ */
+ protected T readItem(Element child, Set<T> selected,
+ DesignContext context) {
+ T item = readItem(child, context);
+
+ if (child.hasAttr("selected")) {
+ selected.add(item);
+ }
+
+ return item;
+ }
+
private void updateSelection(Consumer<Set<T>> handler,
boolean userOriginated) {
LinkedHashSet<T> oldSelection = new LinkedHashSet<>(selection);
package com.vaadin.ui;
import java.lang.reflect.Method;
+import java.util.Collection;
+import java.util.HashSet;
import java.util.Objects;
import java.util.Optional;
+import java.util.Set;
+
+import org.jsoup.nodes.Element;
import com.vaadin.data.HasValue;
import com.vaadin.data.SelectionModel;
import com.vaadin.shared.Registration;
import com.vaadin.shared.data.selection.SelectionServerRpc;
import com.vaadin.shared.ui.AbstractSingleSelectState;
+import com.vaadin.ui.declarative.DesignContext;
+import com.vaadin.ui.declarative.DesignException;
import com.vaadin.util.ReflectTools;
/**
return Objects.equals(getValue(), item);
}
+ @Override
+ protected Element writeItem(Element design, T item, DesignContext context) {
+ Element element = super.writeItem(design, item, context);
+
+ if (isSelected(item)) {
+ element.attr("selected", "");
+ }
+
+ return element;
+ }
+
+ @Override
+ protected void readItems(Element design, DesignContext context) {
+ super.readItems(design, context);
+ Set<T> selected = new HashSet<>();
+ design.children().stream()
+ .forEach(child -> readItem(child, selected, context));
+ selected.forEach(this::setValue);
+ }
+
+ /**
+ * Reads an Item from a design and inserts it into the data source.
+ * Hierarchical select components should override this method to recursively
+ * recursively read any child items as well.
+ *
+ * @param child
+ * a child element representing the item
+ * @param selected
+ * A set accumulating selected items. If the item that is read is
+ * marked as selected, its item id should be added to this set.
+ * @param context
+ * the DesignContext instance used in parsing
+ * @return the item id of the new item
+ *
+ * @throws DesignException
+ * if the tag name of the {@code child} element is not
+ * {@code option}.
+ */
+ protected T readItem(Element child, Set<T> selected,
+ DesignContext context) {
+ T item = readItem(child, context);
+
+ if (child.hasAttr("selected")) {
+ selected.add(item);
+ }
+
+ return item;
+ }
+
+ @Override
+ protected Collection<String> getCustomAttributes() {
+ Collection<String> attributes = super.getCustomAttributes();
+ // "value" is not an attribute for the component. "selected" attribute
+ // is used in "option"'s tag to mark selection which implies value for
+ // single select component
+ attributes.add("value");
+ return attributes;
+ }
+
private void init() {
registerRpc(new SelectionServerRpc() {
package com.vaadin.ui;
import java.util.Collection;
+import java.util.Set;
+
+import org.jsoup.nodes.Element;
import com.vaadin.data.Listing;
import com.vaadin.event.FieldEvents.BlurEvent;
import com.vaadin.server.data.DataProvider;
import com.vaadin.shared.Registration;
import com.vaadin.shared.ui.optiongroup.CheckBoxGroupState;
+import com.vaadin.ui.declarative.DesignContext;
+import com.vaadin.ui.declarative.DesignFormatter;
/**
* A group of Checkboxes. Individual checkboxes are made from items supplied by
public void removeBlurListener(BlurListener listener) {
removeListener(BlurEvent.EVENT_ID, BlurEvent.class, listener);
}
+
+ @Override
+ protected void readItems(Element design, DesignContext context) {
+ setItemEnabledProvider(new DeclarativeItemEnabledProvider<>());
+ super.readItems(design, context);
+ }
+
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ @Override
+ protected T readItem(Element child, Set<T> selected,
+ DesignContext context) {
+ T item = super.readItem(child, selected, context);
+
+ SerializablePredicate<T> provider = getItemEnabledProvider();
+ if (provider instanceof DeclarativeItemEnabledProvider) {
+ if (child.hasAttr("disabled")) {
+ ((DeclarativeItemEnabledProvider) provider).addDisabled(item);
+ }
+ } else {
+ throw new IllegalStateException(String.format(
+ "Don't know how "
+ + "to disable item using current item enabled provider '%s'",
+ provider.getClass().getName()));
+ }
+ return item;
+ }
+
+ @Override
+ protected Element writeItem(Element design, T item, DesignContext context) {
+ Element elem = super.writeItem(design, item, context);
+
+ if (!getItemEnabledProvider().test(item)) {
+ elem.attr("disabled", "");
+ }
+
+ if (isHtmlContentAllowed()) {
+ // need to unencode HTML entities. AbstractMultiSelect.writeDesign
+ // can't check if HTML content is allowed, so it always encodes
+ // entities like '>', '<' and '&'; in case HTML content is allowed
+ // this is undesirable so we need to unencode entities. Entities
+ // other than '<' and '>' will be taken care by Jsoup.
+ elem.html(DesignFormatter.decodeFromTextNode(elem.html()));
+ }
+
+ return elem;
+ }
}
import java.io.Serializable;
import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
import java.util.Objects;
+import java.util.Set;
import java.util.function.BiFunction;
import java.util.function.Consumer;
+import org.jsoup.nodes.Element;
+
import com.vaadin.data.HasValue;
import com.vaadin.event.FieldEvents;
import com.vaadin.event.FieldEvents.BlurEvent;
import com.vaadin.shared.ui.combobox.ComboBoxConstants;
import com.vaadin.shared.ui.combobox.ComboBoxServerRpc;
import com.vaadin.shared.ui.combobox.ComboBoxState;
+import com.vaadin.ui.declarative.DesignAttributeHandler;
+import com.vaadin.ui.declarative.DesignContext;
+import com.vaadin.ui.declarative.DesignFormatter;
import elemental.json.JsonObject;
public interface NewItemHandler extends Consumer<String>, Serializable {
}
+ /**
+ * Item style generator class for declarative support.
+ * <p>
+ * Provides a straightforward mapping between an item and its style.
+ *
+ * @param <T>
+ * item type
+ */
+ protected static class DeclarativeStyleGenerator<T>
+ implements StyleGenerator<T> {
+ private Map<T, String> styles = new HashMap<>();
+
+ @Override
+ public String apply(T item) {
+ return styles.get(item);
+ }
+
+ /**
+ * Sets a {@code style} for the {@code item}.
+ *
+ * @param item
+ * a data item
+ * @param style
+ * a style for the {@code item}
+ */
+ protected void setStyle(T item, String style) {
+ styles.put(item, style);
+ }
+ }
+
/**
* Filter can be used to customize the filtering of items based on user
* input.
*/
private NewItemHandler newItemHandler;
- private ItemCaptionGenerator<T> itemCaptionGenerator = String::valueOf;
-
private StyleGenerator<T> itemStyleGenerator = item -> null;
- private IconGenerator<T> itemIconGenerator = item -> null;
private ItemFilter<T> filter = (filterText, item) -> {
if (filterText == null) {
if (style != null) {
jsonObject.put(ComboBoxConstants.STYLE, style);
}
- Resource icon = itemIconGenerator.apply(data);
+ Resource icon = getItemIconGenerator().apply(data);
if (icon != null) {
String iconUrl = ResourceReference
.create(icon, ComboBox.this, null).getURL();
return getState(false).scrollToSelectedItem;
}
- /**
- * Gets the item caption generator that is used to produce the strings shown
- * in the combo box for each item.
- *
- * @return the item caption generator used, not null
- */
+ @Override
public ItemCaptionGenerator<T> getItemCaptionGenerator() {
- return itemCaptionGenerator;
+ return super.getItemCaptionGenerator();
}
- /**
- * Sets the item caption generator that is used to produce the strings shown
- * in the combo box for each item. By default,
- * {@link String#valueOf(Object)} is used.
- *
- * @param itemCaptionGenerator
- * the item caption provider to use, not null
- */
+ @Override
public void setItemCaptionGenerator(
ItemCaptionGenerator<T> itemCaptionGenerator) {
- Objects.requireNonNull(itemCaptionGenerator,
- "Item caption generators must not be null");
- this.itemCaptionGenerator = itemCaptionGenerator;
- getDataCommunicator().reset();
+ super.setItemCaptionGenerator(itemCaptionGenerator);
}
/**
return itemStyleGenerator;
}
- /**
- * Sets the item icon generator that is used to produce custom icons for
- * showing items in the popup. The generator can return null for items with
- * no icon.
- *
- * @see IconGenerator
- *
- * @param itemIconGenerator
- * the item icon generator to set, not null
- * @throws NullPointerException
- * if {@code itemIconGenerator} is {@code null}
- */
+ @Override
public void setItemIconGenerator(IconGenerator<T> itemIconGenerator) {
- Objects.requireNonNull(itemIconGenerator,
- "Item icon generator must not be null");
- this.itemIconGenerator = itemIconGenerator;
- getDataCommunicator().reset();
+ super.setItemIconGenerator(itemIconGenerator);
}
- /**
- * Gets the currently used item icon generator. The default item icon
- * provider returns null for all items, resulting in no icons being used.
- *
- * @see IconGenerator
- * @see #setItemIconGenerator(IconGenerator)
- *
- * @return the currently used item icon generator, not null
- */
+ @Override
public IconGenerator<T> getItemIconGenerator() {
- return itemIconGenerator;
+ return super.getItemIconGenerator();
}
/**
getState().selectedItemCaption = selectedCaption;
}
+ @Override
+ protected Element writeItem(Element design, T item, DesignContext context) {
+ Element element = design.appendElement("option");
+
+ String caption = getItemCaptionGenerator().apply(item);
+ if (caption != null) {
+ element.html(DesignFormatter.encodeForTextNode(caption));
+ } else {
+ element.html(DesignFormatter.encodeForTextNode(item.toString()));
+ }
+ element.attr("item", item.toString());
+
+ Resource icon = getItemIconGenerator().apply(item);
+ if (icon != null) {
+ DesignAttributeHandler.writeAttribute("icon", element.attributes(),
+ icon, null, Resource.class, context);
+ }
+
+ String style = getStyleGenerator().apply(item);
+ if (style != null) {
+ element.attr("style", style);
+ }
+
+ if (isSelected(item)) {
+ element.attr("selected", "");
+ }
+
+ return element;
+ }
+
+ @Override
+ protected void readItems(Element design, DesignContext context) {
+ setStyleGenerator(new DeclarativeStyleGenerator<>());
+ super.readItems(design, context);
+ }
+
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ @Override
+ protected T readItem(Element child, Set<T> selected,
+ DesignContext context) {
+ T item = super.readItem(child, selected, context);
+
+ if (child.hasAttr("style")) {
+ StyleGenerator<T> styleGenerator = getStyleGenerator();
+ if (styleGenerator instanceof DeclarativeStyleGenerator) {
+ ((DeclarativeStyleGenerator) styleGenerator).setStyle(item,
+ child.attr("style"));
+ } else {
+ throw new IllegalStateException(String.format(
+ "Don't know how "
+ + "to set style using current style generator '%s'",
+ styleGenerator.getClass().getName()));
+ }
+ }
+ return item;
+ }
+
}
--- /dev/null
+/*
+ * 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.HashMap;
+import java.util.Map;
+
+/**
+ * Item caption generator class for declarative support.
+ * <p>
+ * Provides a straightforward mapping between an item and its caption.
+ *
+ * @param <T>
+ * item type
+ */
+class DeclarativeCaptionGenerator<T> implements ItemCaptionGenerator<T> {
+
+ private Map<T, String> captions = new HashMap<>();
+
+ @Override
+ public String apply(T item) {
+ return captions.get(item);
+ }
+
+ /**
+ * Sets a {@code caption} for the {@code item}.
+ *
+ * @param item
+ * a data item
+ * @param caption
+ * a caption for the {@code item}
+ */
+ protected void setCaption(T item, String caption) {
+ captions.put(item, caption);
+ }
+
+}
--- /dev/null
+/*
+ * 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.HashMap;
+import java.util.Map;
+
+import com.vaadin.server.Resource;
+
+/**
+ * Icon generator class for declarative support.
+ * <p>
+ * Provides a straightforward mapping between an item and its icon.
+ *
+ * @param <T>
+ * item type
+ */
+class DeclarativeIconGenerator<T> implements IconGenerator<T> {
+
+ private Map<T, Resource> captions = new HashMap<>();
+
+ @Override
+ public Resource apply(T item) {
+ return captions.get(item);
+ }
+
+ /**
+ * Sets an {@code icon} for the {@code item}.
+ *
+ * @param item
+ * a data item
+ * @param icon
+ * an icon for the {@code item}
+ */
+ protected void setIcon(T item, Resource icon) {
+ captions.put(item, icon);
+ }
+
+}
--- /dev/null
+/*
+ * 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.HashSet;
+import java.util.Set;
+
+import com.vaadin.server.SerializablePredicate;
+
+/**
+ * Item enabled provider class for declarative support.
+ * <p>
+ * Provides a straightforward mapping between an item and its enable state.
+ *
+ * @param <T>
+ * item type
+ */
+class DeclarativeItemEnabledProvider<T> implements SerializablePredicate<T> {
+
+ private Set<T> disabled = new HashSet<>();
+
+ @Override
+ public boolean test(T item) {
+ return !disabled.contains(item);
+ }
+
+ /**
+ * Adds the {@code item} to disabled items list.
+ *
+ * @param item
+ * a data item
+ * @param caption
+ * a caption for the {@code item}
+ */
+ protected void addDisabled(T item) {
+ disabled.add(item);
+ }
+
+}
import java.util.stream.Collectors;
import java.util.stream.Stream;
+import org.jsoup.nodes.Element;
+
import com.vaadin.data.Binder;
import com.vaadin.data.SelectionModel;
import com.vaadin.event.ConnectorEvent;
import com.vaadin.ui.components.grid.Header;
import com.vaadin.ui.components.grid.Header.Row;
import com.vaadin.ui.components.grid.SingleSelectionModel;
+import com.vaadin.ui.declarative.DesignContext;
import com.vaadin.ui.renderers.AbstractRenderer;
import com.vaadin.ui.renderers.Renderer;
import com.vaadin.ui.renderers.TextRenderer;
fireEvent(new ColumnResizeEvent(this, column, userOriginated));
}
+ @Override
+ protected Element writeItem(Element design, T item, DesignContext context) {
+ // TODO see vaadin/framework8-issues#390
+ return null;
+ }
+
+ @Override
+ protected void readItems(Element design, DesignContext context) {
+ // TODO see vaadin/framework8-issues#390
+ }
+
}
import java.util.Collection;
import java.util.Objects;
+import java.util.Set;
+
+import org.jsoup.nodes.Element;
import com.vaadin.data.Listing;
import com.vaadin.event.FieldEvents.BlurEvent;
import com.vaadin.shared.Registration;
import com.vaadin.shared.ui.ListingJsonConstants;
import com.vaadin.shared.ui.optiongroup.RadioButtonGroupState;
+import com.vaadin.ui.declarative.DesignContext;
+import com.vaadin.ui.declarative.DesignFormatter;
import elemental.json.JsonObject;
public class RadioButtonGroup<T> extends AbstractSingleSelect<T>
implements FocusNotifier, BlurNotifier {
- private IconGenerator<T> itemIconGenerator = item -> null;
-
- private ItemCaptionGenerator<T> itemCaptionGenerator = String::valueOf;
-
private SerializablePredicate<T> itemEnabledProvider = item -> true;
/**
return (RadioButtonGroupState) super.getState(markAsDirty);
}
- /**
- * Returns the item icon generator.
- *
- * @return the currently set icon generator
- * @see #setItemIconGenerator
- * @see IconGenerator
- */
+ @Override
public IconGenerator<T> getItemIconGenerator() {
- return itemIconGenerator;
+ return super.getItemIconGenerator();
}
- /**
- * Sets the item icon generator for this radiobutton group. The icon
- * generator is queried for each item to optionally display an icon next to
- * the item caption. If the generator returns null for an item, no icon is
- * displayed. The default generator always returns null (no icons).
- *
- * @param itemIconGenerator
- * the icon generator, not null
- * @see IconGenerator
- */
+ @Override
public void setItemIconGenerator(IconGenerator<T> itemIconGenerator) {
- Objects.requireNonNull(itemIconGenerator,
- "Item icon generator cannot be null.");
- this.itemIconGenerator = itemIconGenerator;
+ super.setItemIconGenerator(itemIconGenerator);
}
- /**
- * Returns the currently set item caption generator.
- *
- * @return the currently set caption generator
- * @see #setItemCaptionGenerator
- * @see ItemCaptionGenerator
- */
+ @Override
public ItemCaptionGenerator<T> getItemCaptionGenerator() {
- return itemCaptionGenerator;
+ return super.getItemCaptionGenerator();
}
- /**
- * Sets the item caption generator for this radiobutton group. The caption
- * generator is queried for each item to optionally display an item textual
- * representation. The default generator returns
- * {@code String.valueOf(item)}.
- *
- * @param itemCaptionGenerator
- * the item caption generator, not null
- * @see ItemCaptionGenerator
- */
+ @Override
public void setItemCaptionGenerator(
ItemCaptionGenerator<T> itemCaptionGenerator) {
- Objects.requireNonNull(itemCaptionGenerator,
- "Item caption generator cannot be null.");
- this.itemCaptionGenerator = itemCaptionGenerator;
+ super.setItemCaptionGenerator(itemCaptionGenerator);
}
/**
public void removeBlurListener(BlurListener listener) {
removeListener(BlurEvent.EVENT_ID, BlurEvent.class, listener);
}
+
+ @Override
+ protected void readItems(Element design, DesignContext context) {
+ setItemEnabledProvider(new DeclarativeItemEnabledProvider<>());
+ super.readItems(design, context);
+ }
+
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ @Override
+ protected T readItem(Element child, Set<T> selected,
+ DesignContext context) {
+ T item = super.readItem(child, selected, context);
+
+ SerializablePredicate<T> provider = getItemEnabledProvider();
+ if (provider instanceof DeclarativeItemEnabledProvider) {
+ if (child.hasAttr("disabled")) {
+ ((DeclarativeItemEnabledProvider) provider).addDisabled(item);
+ }
+ } else {
+ throw new IllegalStateException(String.format(
+ "Don't know how "
+ + "to disable item using current item enabled provider '%s'",
+ provider.getClass().getName()));
+ }
+ return item;
+ }
+
+ @Override
+ protected Element writeItem(Element design, T item, DesignContext context) {
+ Element elem = super.writeItem(design, item, context);
+
+ if (!getItemEnabledProvider().test(item)) {
+ elem.attr("disabled", "");
+ }
+
+ if (isHtmlContentAllowed()) {
+ // need to unencode HTML entities. AbstractMultiSelect.writeDesign
+ // can't check if HTML content is allowed, so it always encodes
+ // entities like '>', '<' and '&'; in case HTML content is allowed
+ // this is undesirable so we need to unencode entities. Entities
+ // other than '<' and '>' will be taken care by Jsoup.
+ elem.html(DesignFormatter.decodeFromTextNode(elem.html()));
+ }
+
+ return elem;
+ }
}
public class IntrospectorEqualsAsserter<C> implements EqualsAsserter<C> {
- private final Class<C> c;
+ private final Class<C> clazz;
- public IntrospectorEqualsAsserter(Class<C> c) {
- this.c = c;
+ public IntrospectorEqualsAsserter(Class<C> clazz) {
+ this.clazz = clazz;
}
@Override
- public void assertObjectEquals(C o1, C o2) {
+ public void assertObjectEquals(C object1, C object2) {
try {
- BeanInfo bi = Introspector.getBeanInfo(c);
+ BeanInfo bi = Introspector.getBeanInfo(clazz);
for (PropertyDescriptor pd : bi.getPropertyDescriptors()) {
Method readMethod = pd.getReadMethod();
Method writeMethod = pd.getWriteMethod();
- if (readMethod == null || writeMethod == null) {
- continue;
- }
- // Needed to access public properties inherited from a
- // nonpublic superclass, see #17425
- readMethod.setAccessible(true);
- writeMethod.setAccessible(true);
- if (Connector.class.isAssignableFrom(c)
- && readMethod.getName().equals("getParent")) {
- // Hack to break cycles in the connector hierarchy
- continue;
- }
- try {
- c.getDeclaredMethod(readMethod.getName());
- } catch (Exception e) {
- // Not declared in this class, will be tested by parent
- // class tester
- if (debug) {
- System.out.println("Skipped " + c.getSimpleName()
- + "." + readMethod.getName());
- }
- continue;
- }
- if (debug) {
- System.out.println("Testing " + c.getSimpleName() + "."
- + readMethod.getName());
+ if (acceptProperty(clazz, readMethod, writeMethod)) {
+ Object property1 = readMethod.invoke(object1);
+ Object property2 = readMethod.invoke(object2);
+ assertEquals(pd.getDisplayName(), property1, property2);
}
- Object v1 = readMethod.invoke(o1);
- Object v2 = readMethod.invoke(o2);
- assertEquals(pd.getDisplayName(), v1, v2);
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
+
}
{
});
}
+ protected boolean acceptProperty(Class<?> clazz, Method readMethod,
+ Method writeMethod) {
+ if (readMethod == null || writeMethod == null) {
+ return false;
+ }
+ // Needed to access public properties inherited from a
+ // nonpublic superclass, see #17425
+ readMethod.setAccessible(true);
+ writeMethod.setAccessible(true);
+ if (Connector.class.isAssignableFrom(clazz)
+ && readMethod.getName().equals("getParent")) {
+ // Hack to break cycles in the connector hierarchy
+ return false;
+ }
+ try {
+ clazz.getDeclaredMethod(readMethod.getName());
+ } catch (Exception e) {
+ // Not declared in this class, will be tested by parent
+ // class tester
+ if (debug) {
+ System.out.println("Skipped " + clazz.getSimpleName() + "."
+ + readMethod.getName());
+ }
+ return false;
+ }
+
+ if (debug) {
+ System.out.println("Testing " + clazz.getSimpleName() + "."
+ + readMethod.getName());
+ }
+ return true;
+ }
+
@Override
protected EqualsAsserter getComparator(Class c) {
com.vaadin.tests.design.DeclarativeTestBaseBase.EqualsAsserter<?> comp = comparators
}
return comp;
}
+
}
Assert.assertEquals("", l.getMessages());
}
- public void testWrite(String design, T expected, boolean writeData) {
- String written = write(expected, writeData);
+ public void testWrite(String expectedDesign, T component,
+ boolean writeData) {
+ String written = write(component, writeData);
Element producedElem = Jsoup.parse(written).body().child(0);
- Element comparableElem = Jsoup.parse(design).body().child(0);
+ Element comparableElem = Jsoup.parse(expectedDesign).body().child(0);
String produced = elementToHtml(producedElem);
String comparable = elementToHtml(comparableElem);
import static org.junit.Assert.assertTrue;
import java.io.File;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
import java.util.Locale;
import org.junit.Test;
@Test
public void abstractComponentAttributesDeserialization()
- throws InstantiationException, IllegalAccessException {
+ throws InstantiationException, IllegalAccessException,
+ IllegalArgumentException, InvocationTargetException {
String id = "testId";
String caption = "testCaption";
boolean captionAsHtml = true;
boolean responsive = true;
String styleName = "testStyleName";
boolean visible = false;
+ boolean requiredIndicator = true;
String design = String.format(
"<%s id='%s' caption='%s' caption-as-html description='%s' "
+ "error='%s' enabled='false' width='%s' height='%s' "
+ "icon='%s' locale='%s' primary-style-name='%s' "
- + "readonly responsive style-name='%s' visible='false'/>",
+ + "readonly responsive style-name='%s' visible='false' "
+ + "required-indicator-visible/>",
getComponentTag(), id, caption, description, error, width,
height, icon, locale.toString(), primaryStyle, styleName);
component.setIcon(new FileResource(new File(icon)));
component.setLocale(locale);
component.setPrimaryStyleName(primaryStyle);
- try {
- component.getClass()
- .getMethod("setReadOnly", new Class[] { boolean.class })
- .invoke(component, readOnly);
- } catch (Exception e) {
- // Ignore
- }
+ callBooleanSetter(readOnly, "setReadOnly", component);
+ callBooleanSetter(requiredIndicator, "setRequiredIndicatorVisible",
+ component);
component.setResponsive(responsive);
component.setStyleName(styleName);
component.setVisible(visible);
testWrite(design, component);
}
+ private void callBooleanSetter(boolean value, String setterName,
+ T component)
+ throws IllegalAccessException, InvocationTargetException {
+ try {
+ Method method = component.getClass().getMethod(setterName,
+ new Class[] { boolean.class });
+ method.invoke(component, value);
+ } catch (NoSuchMethodException ignore) {
+ // ignore if there is no such method
+ }
+ }
+
@Test
public void externalIcon()
throws InstantiationException, IllegalAccessException {
--- /dev/null
+/*
+ * 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.server.component.abstractlisting;
+
+import java.io.File;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.List;
+
+import org.junit.Test;
+
+import com.vaadin.server.ExternalResource;
+import com.vaadin.server.FileResource;
+import com.vaadin.server.Resource;
+import com.vaadin.server.SerializablePredicate;
+import com.vaadin.server.ThemeResource;
+import com.vaadin.tests.server.component.abstractcomponent.AbstractComponentDeclarativeTestBase;
+import com.vaadin.ui.AbstractComponent;
+import com.vaadin.ui.AbstractListing;
+import com.vaadin.ui.IconGenerator;
+import com.vaadin.ui.ItemCaptionGenerator;
+
+/**
+ * {@link AbstractListing} component declarative test.
+ * <p>
+ * Test ignores comparison for {@link ItemCaptionGenerator},
+ * {@link IconGenerator} and {@link SerializablePredicate} "properties" since
+ * they are functions and it doesn't matter which implementation is chosen. But
+ * test checks generated item captions, item icon generation and enabled items
+ * generations if they are available in the component as public methods.
+ * <p>
+ * Common {@link AbstractComponent} properties are tested in
+ * {@link AbstractComponentDeclarativeTestBase}
+ *
+ * @see AbstractComponentDeclarativeTestBase
+ *
+ * @author Vaadin Ltd
+ *
+ *
+ * @param <T>
+ * a component type
+ */
+@SuppressWarnings({ "unchecked", "rawtypes" })
+public abstract class AbstractListingDeclarativeTest<T extends AbstractListing>
+ extends AbstractComponentDeclarativeTestBase<T> {
+
+ private static final String EXTERNAL_URL = "http://example.com/example.gif";
+
+ private static final String FILE_PATH = "img/example.gif";
+
+ private static final String THEME_PATH = "example.gif";
+
+ @Test
+ public abstract void dataSerialization() throws InstantiationException,
+ IllegalAccessException, InvocationTargetException;
+
+ @Test
+ public abstract void valueSerialization() throws InstantiationException,
+ IllegalAccessException, InvocationTargetException;
+
+ @Test
+ public void itemIconsSerialization() throws InstantiationException,
+ IllegalAccessException, InvocationTargetException {
+ T component = getComponentClass().newInstance();
+ Method setIconGenerator = getIconGeneratorMethod(component);
+ if (setIconGenerator == null) {
+ return;
+ }
+
+ List<String> items = Arrays.asList("foo", "bar", "foobar", "barfoo");
+
+ String design = String.format(
+ "<%s>\n" + "<option item='foo' icon='%s'>foo</option>\n"
+ + "<option item='bar' icon='%s'>bar</option>"
+ + "<option item='foobar' icon='theme://%s'>foobar</option>"
+ + "<option item='barfoo'>barfoo</option>" + "</%s>",
+ getComponentTag(), EXTERNAL_URL, FILE_PATH, THEME_PATH,
+ getComponentTag());
+
+ component.setItems(items);
+ IconGenerator generator = item -> generateIcons(item, items);
+ setIconGenerator.invoke(component, generator);
+
+ testRead(design, component);
+ testWrite(design, component, true);
+ }
+
+ @Test
+ public void enabledItemsSerialization() throws InstantiationException,
+ IllegalAccessException, InvocationTargetException {
+ T component = getComponentClass().newInstance();
+ Method setEnabledITemsGenerator = getEnabledItemsProviderMethod(
+ component);
+ if (setEnabledITemsGenerator == null) {
+ return;
+ }
+
+ List<String> items = Arrays.asList("foo", "bar", "foobar");
+
+ String design = String.format(
+ "<%s>\n" + "<option item='foo'>foo</option>\n"
+ + "<option item='bar' disabled>bar</option>"
+ + "<option item='foobar'>foobar</option>",
+ getComponentTag(), getComponentTag());
+
+ component.setItems(items);
+ SerializablePredicate predicate = item -> !item.equals("bar");
+ setEnabledITemsGenerator.invoke(component, predicate);
+
+ testRead(design, component);
+ testWrite(design, component, true);
+ }
+
+ @Test
+ public abstract void readOnlySelection() throws InstantiationException,
+ IllegalAccessException, InvocationTargetException;
+
+ @Override
+ protected boolean acceptProperty(Class<?> clazz, Method readMethod,
+ Method writeMethod) {
+ if (readMethod != null) {
+ Class<?> returnType = readMethod.getReturnType();
+ if (ItemCaptionGenerator.class.equals(returnType)
+ || IconGenerator.class.equals(returnType)
+ || SerializablePredicate.class.equals(returnType)) {
+ return false;
+ }
+ }
+ return super.acceptProperty(clazz, readMethod, writeMethod);
+ }
+
+ private Method getIconGeneratorMethod(T component)
+ throws IllegalAccessException, InvocationTargetException {
+ try {
+ return component.getClass().getMethod("setItemIconGenerator",
+ new Class[] { IconGenerator.class });
+ } catch (NoSuchMethodException ignore) {
+ // ignore if there is no such method
+ return null;
+ }
+ }
+
+ private Method getEnabledItemsProviderMethod(T component)
+ throws IllegalAccessException, InvocationTargetException {
+ try {
+ return component.getClass().getMethod("setItemEnabledProvider",
+ new Class[] { SerializablePredicate.class });
+ } catch (NoSuchMethodException ignore) {
+ // ignore if there is no such method
+ return null;
+ }
+ }
+
+ private Resource generateIcons(Object item, List<String> items) {
+ int index = items.indexOf(item);
+ switch (index) {
+ case 0:
+ return new ExternalResource(EXTERNAL_URL);
+ case 1:
+ return new FileResource(new File(FILE_PATH));
+ case 2:
+ return new ThemeResource(THEME_PATH);
+ }
+ return null;
+ }
+
+}
--- /dev/null
+/*
+ * 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.server.component.abstractmultiselect;
+
+import java.lang.reflect.InvocationTargetException;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+
+import org.junit.Test;
+
+import com.vaadin.tests.server.component.abstractlisting.AbstractListingDeclarativeTest;
+import com.vaadin.ui.AbstractMultiSelect;
+
+/**
+ * {@link AbstractMultiSelect} component declarative test.
+ * <p>
+ * Test inherits test methods from a {@link AbstractListingDeclarativeTest}
+ * class providing here only common cases for {@link AbstractMultiSelect}s.
+ *
+ * @see AbstractListingDeclarativeTest
+ *
+ * @author Vaadin Ltd
+ *
+ *
+ * @param <T>
+ * a component type
+ */
+@SuppressWarnings({ "unchecked", "rawtypes" })
+public abstract class AbstractMultiSelectDeclarativeTest<T extends AbstractMultiSelect>
+ extends AbstractListingDeclarativeTest<T> {
+
+ @Override
+ @Test
+ public void dataSerialization() throws InstantiationException,
+ IllegalAccessException, InvocationTargetException {
+ List<String> items = Arrays.asList("foo", "bar", "foobar");
+
+ String design = String.format(
+ "<%s>\n" + "<option item='foo' selected>foo1</option>\n"
+ + "<option item='bar'>bar1</option>"
+ + "<option item='foobar' selected>foobar1</option></%s>",
+ getComponentTag(), getComponentTag());
+ T component = getComponentClass().newInstance();
+ component.setItems(items);
+ component.select("foo");
+ component.select("foobar");
+ component.setItemCaptionGenerator(item -> item + "1");
+
+ testRead(design, component);
+ testWrite(design, component, true);
+ }
+
+ @Override
+ @Test
+ public void valueSerialization() throws InstantiationException,
+ IllegalAccessException, InvocationTargetException {
+ List<String> items = Arrays.asList("foo", "bar", "foobar");
+
+ String design = String.format(
+ "<%s>\n" + "<option item='foo' selected>foo1</option>\n"
+ + "<option item='bar'>bar1</option>"
+ + "<option item='foobar' selected>foobar1</option></%s>",
+ getComponentTag(), getComponentTag());
+ T component = getComponentClass().newInstance();
+ component.setItems(items);
+ component.setValue(new HashSet<>(Arrays.asList("foo", "foobar")));
+ component.setItemCaptionGenerator(item -> item + "1");
+
+ testRead(design, component);
+ testWrite(design, component, true);
+ }
+
+ @Override
+ @Test
+ public void readOnlySelection() throws InstantiationException,
+ IllegalAccessException, InvocationTargetException {
+ T component = getComponentClass().newInstance();
+
+ List<String> items = Arrays.asList("foo", "bar", "foobar");
+
+ String design = String.format(
+ "<%s readonly>\n" + "<option item='foo'>foo</option>\n"
+ + "<option item='bar'>bar</option>"
+ + "<option item='foobar'>foobar</option>",
+ getComponentTag(), getComponentTag());
+
+ component.setItems(items);
+ component.setReadOnly(true);
+
+ testRead(design, component);
+ testWrite(design, component, true);
+ }
+
+}
--- /dev/null
+/*
+ * 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.server.component.abstractsingleselect;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.List;
+
+import org.junit.Test;
+
+import com.vaadin.tests.server.component.abstractlisting.AbstractListingDeclarativeTest;
+import com.vaadin.ui.AbstractSingleSelect;
+import com.vaadin.ui.ItemCaptionGenerator;
+
+/**
+ * {@link AbstractSingleSelect} component declarative test.
+ * <p>
+ * Test inherits test methods from a {@link AbstractListingDeclarativeTest}
+ * class providing here only common cases for {@link AbstractSingleSelect}s.
+ *
+ * @author Vaadin Ltd
+ *
+ *
+ * @param <T>
+ * a component type
+ */
+@SuppressWarnings({ "unchecked", "rawtypes" })
+public abstract class AbstractSingleSelectDeclarativeTest<T extends AbstractSingleSelect>
+ extends AbstractListingDeclarativeTest<T> {
+
+ @Override
+ @Test
+ public void dataSerialization() throws InstantiationException,
+ IllegalAccessException, InvocationTargetException {
+ List<String> items = Arrays.asList("foo", "bar", "foobar");
+
+ String design = String.format(
+ "<%s>\n" + "<option item='foo'>foo</option>\n"
+ + "<option item='bar' selected>bar</option>"
+ + "<option item='foobar'>foobar</option></%s>",
+ getComponentTag(), getComponentTag());
+ T component = getComponentClass().newInstance();
+ component.setItems(items);
+ component.setSelectedItem("bar");
+
+ testRead(design, component);
+ testWrite(design, component, true);
+ }
+
+ @Override
+ @Test
+ public void valueSerialization() throws InstantiationException,
+ IllegalAccessException, InvocationTargetException {
+ List<String> items = Arrays.asList("foo", "bar", "foobar");
+
+ String design = String.format(
+ "<%s>\n" + "<option item='foo'>foo</option>\n"
+ + "<option item='bar' selected>bar</option>"
+ + "<option item='foobar'>foobar</option></%s>",
+ getComponentTag(), getComponentTag());
+ T component = getComponentClass().newInstance();
+ component.setItems(items);
+ component.setValue("bar");
+
+ testRead(design, component);
+ testWrite(design, component, true);
+ }
+
+ @Test
+ public void dataWithCaptionGeneratorSerialization()
+ throws InstantiationException, IllegalAccessException,
+ InvocationTargetException {
+ List<String> items = Arrays.asList("foo", "bar", "foobar");
+ T component = getComponentClass().newInstance();
+ Method setItemCaptionGenerator = getItemCaptionGeneratorMethod(
+ component);
+ if (setItemCaptionGenerator == null) {
+ return;
+ }
+ String design = String.format(
+ "<%s>\n" + "<option item='foo'>foo1</option>\n"
+ + "<option item='bar' selected>bar1</option>"
+ + "<option item='foobar'>foobar1</option></%s>",
+ getComponentTag(), getComponentTag());
+ component.setItems(items);
+ component.setValue("bar");
+ ItemCaptionGenerator generator = item -> item + "1";
+ setItemCaptionGenerator.invoke(component, generator);
+
+ testRead(design, component);
+ testWrite(design, component, true);
+ }
+
+ @Override
+ @Test
+ public void readOnlySelection() throws InstantiationException,
+ IllegalAccessException, InvocationTargetException {
+ T component = getComponentClass().newInstance();
+
+ List<String> items = Arrays.asList("foo", "bar", "foobar");
+
+ String design = String.format(
+ "<%s readonly>\n" + "<option item='foo'>foo</option>\n"
+ + "<option item='bar'>bar</option>"
+ + "<option item='foobar'>foobar</option>",
+ getComponentTag(), getComponentTag());
+
+ component.setItems(items);
+ component.setReadOnly(true);
+
+ testRead(design, component);
+ testWrite(design, component, true);
+ }
+
+ private Method getItemCaptionGeneratorMethod(T component)
+ throws IllegalAccessException, InvocationTargetException {
+ try {
+ return component.getClass().getMethod("setItemCaptionGenerator",
+ new Class[] { ItemCaptionGenerator.class });
+ } catch (NoSuchMethodException ignore) {
+ // ignore if there is no such method
+ return null;
+ }
+ }
+
+}
--- /dev/null
+/*
+ * 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.server.component.checkboxgroup;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.junit.Test;
+
+import com.vaadin.tests.server.component.abstractmultiselect.AbstractMultiSelectDeclarativeTest;
+import com.vaadin.ui.CheckBoxGroup;
+
+/**
+ * Declarative support test for CheckBoxGroup.
+ * <p>
+ * Only {@link CheckBoxGroup#setHtmlContentAllowed(boolean)} is tested here
+ * explicitly. All other tests are in the super class (
+ * {@link AbstractMultiSelectDeclarativeTest}).
+ *
+ * @see AbstractMultiSelectDeclarativeTest
+ *
+ * @author Vaadin Ltd
+ *
+ */
+@SuppressWarnings("rawtypes")
+public class CheckBoxGroupDeclarativeTest
+ extends AbstractMultiSelectDeclarativeTest<CheckBoxGroup> {
+
+ private static final String SIMPLE_HTML = "<span>foo</span>";
+
+ private static final String HTML = "<div class='wrapper'><div>bar</div></div>";
+
+ private static final String HTML_ENTITIES = "<b>a & b</b>";
+
+ @Test
+ public void serializeDataWithHtmlContentAllowed() {
+ CheckBoxGroup<String> group = new CheckBoxGroup<>();
+
+ List<String> items = Arrays.asList("foo", "bar", "foobar");
+
+ String design = String.format(
+ "<%s html-content-allowed>\n"
+ + "<option item='foo'>%s</option>\n"
+ + "<option item='bar'>%s</option>"
+ + "<option item='foobar'>%s</option>",
+ getComponentTag(), SIMPLE_HTML, HTML,
+ HTML_ENTITIES.replace("&", "&"), getComponentTag());
+
+ group.setItems(items);
+ group.setHtmlContentAllowed(true);
+ group.setItemCaptionGenerator(item -> generateCaption(item, items));
+
+ testRead(design, group);
+ testWrite(design, group, true);
+ }
+
+ @Override
+ protected String getComponentTag() {
+ return "vaadin-check-box-group";
+ }
+
+ @Override
+ protected Class<CheckBoxGroup> getComponentClass() {
+ return CheckBoxGroup.class;
+ }
+
+ private String generateCaption(String item, List<String> items) {
+ int index = items.indexOf(item);
+ switch (index) {
+ case 0:
+ return SIMPLE_HTML;
+ case 1:
+ return HTML;
+ case 2:
+ return HTML_ENTITIES;
+ }
+ return null;
+ }
+
+}
\ No newline at end of file
--- /dev/null
+/*
+ * 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.server.component.combobox;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.List;
+
+import org.junit.Test;
+
+import com.vaadin.tests.server.component.abstractsingleselect.AbstractSingleSelectDeclarativeTest;
+import com.vaadin.ui.ComboBox;
+import com.vaadin.ui.StyleGenerator;
+
+/**
+ * Declarative support test for ComboBox.
+ * <p>
+ * There are only ComboBox specific properties explicit tests. All other tests
+ * are in the super class ( {@link AbstractSingleSelectDeclarativeTest}).
+ *
+ * @see AbstractSingleSelectDeclarativeTest
+ *
+ * @author Vaadin Ltd
+ *
+ */
+@SuppressWarnings("rawtypes")
+public class ComboBoxDeclarativeTest
+ extends AbstractSingleSelectDeclarativeTest<ComboBox> {
+
+ @Test
+ public void comboBoxSpecificPropertiesSerialize() {
+ String placeholder = "testPlaceholder";
+ boolean textInputAllowed = false;
+ int pageLength = 7;
+ String popupWidth = "11%";
+ boolean emptySelectionAllowed = false;
+
+ String design = String.format(
+ "<%s placeholder='%s' text-input-allowed='%s' page-length='%d' "
+ + "popup-width='%s' empty-selection-allowed='%s' scroll-to-selected-item/>",
+ getComponentTag(), placeholder, textInputAllowed, pageLength,
+ popupWidth, emptySelectionAllowed);
+
+ ComboBox<String> comboBox = new ComboBox<>();
+ comboBox.setPlaceholder(placeholder);
+ comboBox.setTextInputAllowed(textInputAllowed);
+ comboBox.setPageLength(pageLength);
+ comboBox.setPopupWidth(popupWidth);
+ comboBox.setScrollToSelectedItem(true);
+ comboBox.setEmptySelectionAllowed(emptySelectionAllowed);
+
+ testRead(design, comboBox);
+ testWrite(design, comboBox);
+ }
+
+ @Test
+ public void optionStylesSerialization() throws InstantiationException,
+ IllegalAccessException, InvocationTargetException {
+ List<String> items = Arrays.asList("foo", "bar", "foobar");
+
+ String design = String.format(
+ "<%s>\n" + "<option item='foo' style='foo-style'>foo</option>\n"
+ + "<option item='bar' style='bar-style'>bar</option>"
+ + "<option item='foobar' style='foobar-style'>foobar</option></%s>",
+ getComponentTag(), getComponentTag());
+ ComboBox<String> comboBox = new ComboBox<>();
+ comboBox.setItems(items);
+ comboBox.setStyleGenerator(item -> item + "-style");
+
+ testRead(design, comboBox);
+ testWrite(design, comboBox, true);
+ }
+
+ @Override
+ protected String getComponentTag() {
+ return "vaadin-combo-box";
+ }
+
+ @Override
+ protected Class<? extends ComboBox> getComponentClass() {
+ return ComboBox.class;
+ }
+
+ @Override
+ protected boolean acceptProperty(Class<?> clazz, Method readMethod,
+ Method writeMethod) {
+ if (readMethod != null) {
+ Class<?> returnType = readMethod.getReturnType();
+ if (StyleGenerator.class.equals(returnType))
+ return false;
+ }
+ return super.acceptProperty(clazz, readMethod, writeMethod);
+ }
+
+}
*/
package com.vaadin.tests.server.component.listselect;
-import java.util.Arrays;
-
import org.junit.Test;
-import com.vaadin.tests.design.DeclarativeTestBase;
+import com.vaadin.tests.server.component.abstractmultiselect.AbstractMultiSelectDeclarativeTest;
import com.vaadin.ui.ListSelect;
+/**
+ * List select declarative test.
+ * <p>
+ * There is only {@link ListSelect#setRows(int)}/{@link ListSelect#getRows()}
+ * explicit test. All other tests are in the super class (
+ * {@link AbstractMultiSelectDeclarativeTest}).
+ *
+ * @see AbstractMultiSelectDeclarativeTest
+ *
+ * @author Vaadin Ltd
+ *
+ */
+@SuppressWarnings("rawtypes")
public class ListSelectDeclarativeTest
- extends DeclarativeTestBase<ListSelect<String>> {
-
- private ListSelect<String> getWithOptionsExpected() {
- ListSelect<String> ls = new ListSelect<>(null,
- Arrays.asList("Male", "Female"));
- ls.setRows(9); // 10 is default
- return ls;
- }
-
- private String getWithOptionsDesign() {
- return "<vaadin-list-select rows=9>\n"
- + " <option>Male</option>\n"
- + " <option>Female</option>\n"
- + "</vaadin-list-select>\n" + "";
- }
+ extends AbstractMultiSelectDeclarativeTest<ListSelect> {
@Test
- public void testReadWithOptions() {
- testRead(getWithOptionsDesign(), getWithOptionsExpected());
- }
+ public void rowsPropertySerialization() {
+ int rows = 7;
+ String design = String.format("<%s rows='%s'/>", getComponentTag(),
+ rows);
- @Test
- public void testWriteWithOptions() {
- testWrite(stripOptionTags(getWithOptionsDesign()),
- getWithOptionsExpected());
- }
+ ListSelect<String> select = new ListSelect<>();
+ select.setRows(rows);
- private ListSelect<String> getBasicExpected() {
- ListSelect<String> ls = new ListSelect<>();
- ls.setCaption("Hello");
- return ls;
+ testRead(design, select);
+ testWrite(design, select);
}
- private String getBasicDesign() {
- return "<vaadin-list-select caption='Hello' />";
+ @Override
+ protected String getComponentTag() {
+ return "vaadin-list-select";
}
- @Test
- public void testReadBasic() {
- testRead(getBasicDesign(), getBasicExpected());
- }
-
- @Test
- public void testWriteBasic() {
- testWrite(getBasicDesign(), getBasicExpected());
+ @Override
+ protected Class<? extends ListSelect> getComponentClass() {
+ return ListSelect.class;
}
}
--- /dev/null
+/*
+ * 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.server.component.nativeselect;
+
+import com.vaadin.tests.server.component.abstractsingleselect.AbstractSingleSelectDeclarativeTest;
+import com.vaadin.ui.NativeSelect;
+
+/**
+ * Declarative support tests for {@link NativeSelect}. All tests are in the
+ * super class ({@link AbstractSingleSelectDeclarativeTest}). This class
+ * declares only tag name and native select class (test parameters).
+ *
+ * @author Vaadin Ltd
+ *
+ */
+public class NativeSelectDeclarativeTest
+ extends AbstractSingleSelectDeclarativeTest<NativeSelect> {
+
+ @Override
+ protected String getComponentTag() {
+ return "vaadin-native-select";
+ }
+
+ @Override
+ protected Class<NativeSelect> getComponentClass() {
+ return NativeSelect.class;
+ }
+
+}
--- /dev/null
+/*
+ * 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.server.component.radiobuttongroup;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.junit.Test;
+
+import com.vaadin.tests.server.component.abstractsingleselect.AbstractSingleSelectDeclarativeTest;
+import com.vaadin.ui.RadioButtonGroup;
+
+/**
+ * Declarative support test for RadioButtonGroup.
+ * <p>
+ * Only {@link RadioButtonGroup#setHtmlContentAllowed(boolean)} is tested here
+ * explicitly. All other tests are in the super class (
+ * {@link AbstractSingleSelectDeclarativeTest}).
+ *
+ * @see AbstractSingleSelectDeclarativeTest
+ *
+ * @author Vaadin Ltd
+ *
+ */
+@SuppressWarnings("rawtypes")
+public class RadioButtonGroupDeclarativeTest
+ extends AbstractSingleSelectDeclarativeTest<RadioButtonGroup> {
+
+ private static final String SIMPLE_HTML = "<span>foo</span>";
+
+ private static final String HTML = "<div class='wrapper'><div>bar</div></div>";
+
+ private static final String HTML_ENTITIES = "<b>a & b</b>";
+
+ @Test
+ public void serializeDataWithHtmlContentAllowed() {
+ RadioButtonGroup<String> group = new RadioButtonGroup<>();
+
+ List<String> items = Arrays.asList("foo", "bar", "foobar");
+
+ String design = String.format(
+ "<%s html-content-allowed>\n"
+ + "<option item='foo'>%s</option>\n"
+ + "<option item='bar'>%s</option>"
+ + "<option item='foobar'>%s</option>",
+ getComponentTag(), SIMPLE_HTML, HTML,
+ HTML_ENTITIES.replace("&", "&"), getComponentTag());
+
+ group.setItems(items);
+ group.setHtmlContentAllowed(true);
+ group.setItemCaptionGenerator(item -> generateCaption(item, items));
+
+ testRead(design, group);
+ testWrite(design, group, true);
+ }
+
+ @Override
+ protected String getComponentTag() {
+ return "vaadin-radio-button-group";
+ }
+
+ @Override
+ protected Class<RadioButtonGroup> getComponentClass() {
+ return RadioButtonGroup.class;
+ }
+
+ private String generateCaption(String item, List<String> items) {
+ int index = items.indexOf(item);
+ switch (index) {
+ case 0:
+ return SIMPLE_HTML;
+ case 1:
+ return HTML;
+ case 2:
+ return HTML_ENTITIES;
+ }
+ return null;
+ }
+
+}
\ No newline at end of file
import org.junit.Test;
-import com.vaadin.tests.design.DeclarativeTestBase;
+import com.vaadin.tests.server.component.abstractmultiselect.AbstractMultiSelectDeclarativeTest;
import com.vaadin.ui.TwinColSelect;
/**
- * Test cases for reading the properties of selection components.
- *
+ * TwinColSelectt declarative test.
+ * <p>
+ * There are only TwinColSelect specific properties explicit tests. All other
+ * tests are in the super class ( {@link AbstractMultiSelectDeclarativeTest}).
+ *
+ * @see AbstractMultiSelectDeclarativeTest
+ *
* @author Vaadin Ltd
+ *
*/
public class TwinColSelectDeclarativeTest
- extends DeclarativeTestBase<TwinColSelect<String>> {
+ extends AbstractMultiSelectDeclarativeTest<TwinColSelect> {
- public String getBasicDesign() {
- return "<vaadin-twin-col-select rows=5 right-column-caption='Selected values' left-column-caption='Unselected values'>\n"
- + " <option>First item</option>\n"
- + " <option selected>Second item</option>\n"
- + " <option selected>Third item</option>\n"
- + "</vaadin-twin-col-select>";
+ @Test
+ public void rowsPropertySerialization() {
+ int rows = 7;
+ String design = String.format("<%s rows='%s'/>", getComponentTag(),
+ rows);
- }
+ TwinColSelect<String> select = new TwinColSelect<>();
+ select.setRows(rows);
- public TwinColSelect<String> getBasicExpected() {
- TwinColSelect<String> s = new TwinColSelect<>();
- s.setRightColumnCaption("Selected values");
- s.setLeftColumnCaption("Unselected values");
- /*
- * This is broken for now : declarative doesn't read data and doesn't
- * set value/selection. See #388
- *
- * s.setItems("First item", "Second item", "Third item");
- * s.getSelectionModel().select("Second item");
- * s.getSelectionModel().select("Third item");
- *
- */
- s.setRows(5);
- return s;
+ testRead(design, select);
+ testWrite(design, select);
}
@Test
- public void testReadBasic() {
- testRead(getBasicDesign(), getBasicExpected());
+ public void rightColumnCaptionPropertySerialization() {
+ String rightColumnCaption = "foo";
+ String design = String.format("<%s right-column-caption='%s'/>",
+ getComponentTag(), rightColumnCaption);
+
+ TwinColSelect<String> select = new TwinColSelect<>();
+ select.setRightColumnCaption(rightColumnCaption);
+
+ testRead(design, select);
+ testWrite(design, select);
}
@Test
- public void testWriteBasic() {
- testWrite(stripOptionTags(getBasicDesign()), getBasicExpected());
+ public void leftColumnCaptionPropertySerialization() {
+ String leftColumnCaption = "foo";
+ String design = String.format("<%s left-column-caption='%s'/>",
+ getComponentTag(), leftColumnCaption);
+
+ TwinColSelect<String> select = new TwinColSelect<>();
+ select.setLeftColumnCaption(leftColumnCaption);
+
+ testRead(design, select);
+ testWrite(design, select);
}
- @Test
- public void testReadEmpty() {
- testRead("<vaadin-twin-col-select />", new TwinColSelect());
+ @Override
+ protected String getComponentTag() {
+ return "vaadin-twin-col-select";
}
- @Test
- public void testWriteEmpty() {
- testWrite("<vaadin-twin-col-select />", new TwinColSelect());
+ @Override
+ protected Class<? extends TwinColSelect> getComponentClass() {
+ return TwinColSelect.class;
}
}
\ No newline at end of file
import java.util.List;
import java.util.stream.Stream;
-import com.vaadin.server.data.BackEndDataProvider;
+import org.jsoup.nodes.Element;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
+import com.vaadin.server.data.BackEndDataProvider;
import com.vaadin.server.data.DataProvider;
import com.vaadin.server.data.ListDataProvider;
import com.vaadin.server.data.Query;
import com.vaadin.ui.AbstractListing.AbstractListingExtension;
+import com.vaadin.ui.declarative.DesignContext;
import elemental.json.JsonObject;
public void runDataGeneration() {
super.getDataCommunicator().beforeClientResponse(true);
}
+
+ @Override
+ protected Element writeItem(Element design, String item,
+ DesignContext context) {
+ return null;
+ }
+
+ @Override
+ protected void readItems(Element design, DesignContext context) {
+ }
}
private final class CountGenerator
public void testSetDataProvider() {
ListDataProvider<String> dataProvider = DataProvider.create(items);
listing.setDataProvider(dataProvider);
- Assert.assertEquals("setDataProvider did not set data provider", dataProvider,
- listing.getDataProvider());
- listing.setDataProvider(new BackEndDataProvider<>(q -> Stream.of(ITEM_ARRAY)
- .skip(q.getOffset()).limit(q.getLimit()),
+ Assert.assertEquals("setDataProvider did not set data provider",
+ dataProvider, listing.getDataProvider());
+ listing.setDataProvider(new BackEndDataProvider<>(q -> Stream
+ .of(ITEM_ARRAY).skip(q.getOffset()).limit(q.getLimit()),
q -> ITEM_ARRAY.length));
Assert.assertNotEquals("setDataProvider did not replace data provider",
dataProvider, listing.getDataProvider());
import java.util.Optional;
import java.util.concurrent.atomic.AtomicReference;
+import org.jsoup.nodes.Element;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import com.vaadin.server.data.provider.bov.Person;
import com.vaadin.shared.Registration;
import com.vaadin.shared.data.DataCommunicatorClientRpc;
+import com.vaadin.ui.declarative.DesignContext;
/**
* Test for {@link AbstractSingleSelect} and {@link AbstractSingleSelection}
private List<Person> selectionChanges;
private static class PersonListing extends AbstractSingleSelect<Person> {
+
+ @Override
+ protected Element writeItem(Element design, Person item,
+ DesignContext context) {
+ return null;
+ }
+
+ @Override
+ protected void readItems(Element design, DesignContext context) {
+ }
}
@Before
public String getValue() {
return value;
}
+
+ @Override
+ protected Element writeItem(Element design, String item,
+ DesignContext context) {
+ return null;
+ }
+
+ @Override
+ protected void readItems(Element design, DesignContext context) {
+ }
};
AtomicReference<ValueChangeEvent<?>> event = new AtomicReference<>();
+++ /dev/null
-/*
- * Copyright 2000-2014 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.radiobutton;
-
-import com.vaadin.server.FontAwesome;
-import com.vaadin.testbench.By;
-import com.vaadin.testbench.customelements.RadioButtonGroupElement;
-import com.vaadin.tests.tb3.MultiBrowserTest;
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
-import org.openqa.selenium.WebElement;
-
-import java.util.Arrays;
-import java.util.List;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
-/**
- * Test for RadioButtonGroup
- *
- * @author Vaadin Ltd
- * @since 8.0
- */
-public class RadioButtonGroupTest extends MultiBrowserTest {
-
- @Before
- public void setUp() throws Exception {
- openTestURL();
- }
-
- @Test
- public void initialLoad_containsCorrectItems() {
- assertItems(20);
- }
-
- @Test
- public void initialItems_reduceItemCount_containsCorrectItems() {
- selectMenuPath("Component", "Data provider", "Items", "5");
- assertItems(5);
- }
-
- @Test
- public void initialItems_increaseItemCount_containsCorrectItems() {
- selectMenuPath("Component", "Data provider", "Items", "100");
- assertItems(100);
- }
-
- @Test
- public void clickToSelect() {
- selectMenuPath("Component", "Listeners", "Selection listener");
-
- getSelect().selectByText("Item 4");
- Assert.assertEquals("1. Selected: Optional[Item 4]", getLogRow(0));
-
- getSelect().selectByText("Item 2");
- Assert.assertEquals("2. Selected: Optional[Item 2]", getLogRow(0));
-
- getSelect().selectByText("Item 4");
- Assert.assertEquals("3. Selected: Optional[Item 4]", getLogRow(0));
- }
-
- @Test
- public void disabled_clickToSelect() {
- selectMenuPath("Component", "State", "Enabled");
-
- Assert.assertTrue(getSelect().findElements(By.tagName("input")).stream()
- .allMatch(element -> element.getAttribute("disabled") != null));
-
- selectMenuPath("Component", "Listeners", "Selection listener");
-
- String lastLogRow = getLogRow(0);
-
- getSelect().selectByText("Item 4");
- Assert.assertEquals(lastLogRow, getLogRow(0));
-
- getSelect().selectByText("Item 2");
- Assert.assertEquals(lastLogRow, getLogRow(0));
-
- getSelect().selectByText("Item 4");
- Assert.assertEquals(lastLogRow, getLogRow(0));
- }
-
- @Test
- public void itemIconGenerator() {
- selectMenuPath("Component", "Item Icon Generator", "Use Item Icon Generator");
- assertItemsSuffices(20);
-
- List<WebElement> icons = getSelect().findElements(By.
- cssSelector(".v-select-optiongroup .v-icon"));
-
- assertEquals(20,icons.size());
-
- for (int i = 0; i < icons.size(); i++) {
- Assert.assertEquals(FontAwesome.values()[i + 1].getCodepoint(),
- icons.get(i).getText().charAt(0));
- }
- }
-
-
- @Test
- public void clickToSelect_reenable() {
- selectMenuPath("Component", "State", "Enabled");
- selectMenuPath("Component", "Listeners", "Selection listener");
-
- getSelect().selectByText("Item 4");
-
- selectMenuPath("Component", "State", "Enabled");
-
- getSelect().selectByText("Item 5");
- Assert.assertEquals("3. Selected: Optional[Item 5]", getLogRow(0));
-
- getSelect().selectByText("Item 2");
- Assert.assertEquals("4. Selected: Optional[Item 2]", getLogRow(0));
-
- getSelect().selectByText("Item 4");
- Assert.assertEquals("5. Selected: Optional[Item 4]", getLogRow(0));
- }
-
- @Test
- public void itemCaptionGenerator() {
- selectMenuPath("Component", "Item Caption Generator", "Item Caption Generator",
- "Custom Caption Generator");
- assertItems(20, " Caption");
- }
-
- @Test
- public void nullItemCaptionGenerator() {
- selectMenuPath("Component", "Item Caption Generator", "Item Caption Generator",
- "Null Caption Generator");
- for (String text : getSelect().getOptions()) {
- Assert.assertEquals("", text);
- }
- }
-
- @Test
- public void selectProgramatically() {
- selectMenuPath("Component", "Listeners", "Selection listener");
-
- selectMenuPath("Component", "Selection", "Toggle Item 5");
- Assert.assertEquals("2. Selected: Optional[Item 5]", getLogRow(0));
- assertSelected("Item 5");
-
- selectMenuPath("Component", "Selection", "Toggle Item 1");
- Assert.assertEquals("4. Selected: Optional[Item 1]", getLogRow(0));
- // DOM order
- assertSelected("Item 1");
-
- selectMenuPath("Component", "Selection", "Toggle Item 5");
- Assert.assertEquals("6. Selected: Optional[Item 5]", getLogRow(0));
- assertSelected("Item 5");
- }
-
- private void assertSelected(String... expectedSelection) {
- Assert.assertEquals(Arrays.asList(expectedSelection),
- getSelect().getSelection());
- }
-
- @Override
- protected Class<?> getUIClass() {
- return RadioButtonGroupTestUI.class;
- }
-
- protected RadioButtonGroupElement getSelect() {
- return $(RadioButtonGroupElement.class).first();
- }
-
- protected void assertItems(int count) {
- assertItems(count, "");
- }
-
- protected void assertItems(int count, String suffix) {
- int i = 0;
- for (String text : getSelect().getOptions()) {
- assertEquals("Item " + i + suffix, text);
- i++;
- }
- assertEquals("Number of items", count, i);
- }
-
- protected void assertItemsSuffices(int count) {
- int i = 0;
- for (String text : getSelect().getOptions()) {
- assertTrue(text.endsWith("Item " + i));
- i++;
- }
- assertEquals("Number of items", count, i);
- }
-}
--- /dev/null
+/*
+ * Copyright 2000-2014 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.radiobuttongroup;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.openqa.selenium.WebElement;
+
+import com.vaadin.server.FontAwesome;
+import com.vaadin.testbench.By;
+import com.vaadin.testbench.customelements.RadioButtonGroupElement;
+import com.vaadin.tests.components.radiobutton.RadioButtonGroupTestUI;
+import com.vaadin.tests.tb3.MultiBrowserTest;
+
+/**
+ * Test for RadioButtonGroup
+ *
+ * @author Vaadin Ltd
+ * @since 8.0
+ */
+public class RadioButtonGroupTest extends MultiBrowserTest {
+
+ @Before
+ public void setUp() throws Exception {
+ openTestURL();
+ }
+
+ @Test
+ public void initialLoad_containsCorrectItems() {
+ assertItems(20);
+ }
+
+ @Test
+ public void initialItems_reduceItemCount_containsCorrectItems() {
+ selectMenuPath("Component", "Data provider", "Items", "5");
+ assertItems(5);
+ }
+
+ @Test
+ public void initialItems_increaseItemCount_containsCorrectItems() {
+ selectMenuPath("Component", "Data provider", "Items", "100");
+ assertItems(100);
+ }
+
+ @Test
+ public void clickToSelect() {
+ selectMenuPath("Component", "Listeners", "Selection listener");
+
+ getSelect().selectByText("Item 4");
+ Assert.assertEquals("1. Selected: Optional[Item 4]", getLogRow(0));
+
+ getSelect().selectByText("Item 2");
+ Assert.assertEquals("2. Selected: Optional[Item 2]", getLogRow(0));
+
+ getSelect().selectByText("Item 4");
+ Assert.assertEquals("3. Selected: Optional[Item 4]", getLogRow(0));
+ }
+
+ @Test
+ public void disabled_clickToSelect() {
+ selectMenuPath("Component", "State", "Enabled");
+
+ Assert.assertTrue(getSelect().findElements(By.tagName("input")).stream()
+ .allMatch(element -> element.getAttribute("disabled") != null));
+
+ selectMenuPath("Component", "Listeners", "Selection listener");
+
+ String lastLogRow = getLogRow(0);
+
+ getSelect().selectByText("Item 4");
+ Assert.assertEquals(lastLogRow, getLogRow(0));
+
+ getSelect().selectByText("Item 2");
+ Assert.assertEquals(lastLogRow, getLogRow(0));
+
+ getSelect().selectByText("Item 4");
+ Assert.assertEquals(lastLogRow, getLogRow(0));
+ }
+
+ @Test
+ public void itemIconGenerator() {
+ selectMenuPath("Component", "Item Icon Generator",
+ "Use Item Icon Generator");
+ assertItemsSuffices(20);
+
+ List<WebElement> icons = getSelect()
+ .findElements(By.cssSelector(".v-select-optiongroup .v-icon"));
+
+ assertEquals(20, icons.size());
+
+ for (int i = 0; i < icons.size(); i++) {
+ Assert.assertEquals(FontAwesome.values()[i + 1].getCodepoint(),
+ icons.get(i).getText().charAt(0));
+ }
+ }
+
+ @Test
+ public void clickToSelect_reenable() {
+ selectMenuPath("Component", "State", "Enabled");
+ selectMenuPath("Component", "Listeners", "Selection listener");
+
+ getSelect().selectByText("Item 4");
+
+ selectMenuPath("Component", "State", "Enabled");
+
+ getSelect().selectByText("Item 5");
+ Assert.assertEquals("3. Selected: Optional[Item 5]", getLogRow(0));
+
+ getSelect().selectByText("Item 2");
+ Assert.assertEquals("4. Selected: Optional[Item 2]", getLogRow(0));
+
+ getSelect().selectByText("Item 4");
+ Assert.assertEquals("5. Selected: Optional[Item 4]", getLogRow(0));
+ }
+
+ @Test
+ public void itemCaptionGenerator() {
+ selectMenuPath("Component", "Item Caption Generator",
+ "Item Caption Generator", "Custom Caption Generator");
+ assertItems(20, " Caption");
+ }
+
+ @Test
+ public void nullItemCaptionGenerator() {
+ selectMenuPath("Component", "Item Caption Generator",
+ "Item Caption Generator", "Null Caption Generator");
+ for (String text : getSelect().getOptions()) {
+ Assert.assertEquals("", text);
+ }
+ }
+
+ @Test
+ public void selectProgramatically() {
+ selectMenuPath("Component", "Listeners", "Selection listener");
+
+ selectMenuPath("Component", "Selection", "Toggle Item 5");
+ Assert.assertEquals("2. Selected: Optional[Item 5]", getLogRow(0));
+ assertSelected("Item 5");
+
+ selectMenuPath("Component", "Selection", "Toggle Item 1");
+ Assert.assertEquals("4. Selected: Optional[Item 1]", getLogRow(0));
+ // DOM order
+ assertSelected("Item 1");
+
+ selectMenuPath("Component", "Selection", "Toggle Item 5");
+ Assert.assertEquals("6. Selected: Optional[Item 5]", getLogRow(0));
+ assertSelected("Item 5");
+ }
+
+ private void assertSelected(String... expectedSelection) {
+ Assert.assertEquals(Arrays.asList(expectedSelection),
+ getSelect().getSelection());
+ }
+
+ @Override
+ protected Class<?> getUIClass() {
+ return RadioButtonGroupTestUI.class;
+ }
+
+ protected RadioButtonGroupElement getSelect() {
+ return $(RadioButtonGroupElement.class).first();
+ }
+
+ protected void assertItems(int count) {
+ assertItems(count, "");
+ }
+
+ protected void assertItems(int count, String suffix) {
+ int i = 0;
+ for (String text : getSelect().getOptions()) {
+ assertEquals("Item " + i + suffix, text);
+ i++;
+ }
+ assertEquals("Number of items", count, i);
+ }
+
+ protected void assertItemsSuffices(int count) {
+ int i = 0;
+ for (String text : getSelect().getOptions()) {
+ assertTrue(text.endsWith("Item " + i));
+ i++;
+ }
+ assertEquals("Number of items", count, i);
+ }
+}