summaryrefslogtreecommitdiffstats
path: root/server/src/com/vaadin
diff options
context:
space:
mode:
authorJohannes Dahlström <johannesd@vaadin.com>2015-03-31 15:41:46 +0300
committerJohannes Dahlström <johannesd@vaadin.com>2015-04-07 15:21:50 +0300
commit8664c97c7bb6fb36b2ebbe3849b51ec00e052e24 (patch)
tree31451d8bf956cb2bfb686857f27f12e54703f67d /server/src/com/vaadin
parent0f1dcd23a0bffae76fc312d95d7b64bf7861df88 (diff)
downloadvaadin-framework-8664c97c7bb6fb36b2ebbe3849b51ec00e052e24.tar.gz
vaadin-framework-8664c97c7bb6fb36b2ebbe3849b51ec00e052e24.zip
Fix declarative support for Window (#17314)
Change-Id: If89a46a4c08ec1491eb00a2f2b8580fb3ef785fc
Diffstat (limited to 'server/src/com/vaadin')
-rw-r--r--server/src/com/vaadin/ui/AbstractSingleComponentContainer.java33
-rw-r--r--server/src/com/vaadin/ui/Window.java122
-rw-r--r--server/src/com/vaadin/ui/declarative/converters/DesignShortcutActionConverter.java49
3 files changed, 174 insertions, 30 deletions
diff --git a/server/src/com/vaadin/ui/AbstractSingleComponentContainer.java b/server/src/com/vaadin/ui/AbstractSingleComponentContainer.java
index 244feb3bb9..767ae66515 100644
--- a/server/src/com/vaadin/ui/AbstractSingleComponentContainer.java
+++ b/server/src/com/vaadin/ui/AbstractSingleComponentContainer.java
@@ -19,6 +19,7 @@ import java.util.Collections;
import java.util.Iterator;
import org.jsoup.nodes.Element;
+import org.jsoup.select.Elements;
import com.vaadin.server.ComponentSizeValidator;
import com.vaadin.server.VaadinService;
@@ -288,17 +289,33 @@ public abstract class AbstractSingleComponentContainer extends
public void readDesign(Element design, DesignContext designContext) {
// process default attributes
super.readDesign(design, designContext);
- // handle child element, checking that the design specifies at most one
- // child
- int childCount = design.children().size();
- if (childCount > 1) {
+ readDesignChildren(design.children(), designContext);
+ }
+
+ /**
+ * Reads the content component from the list of child elements of a design.
+ * The list must be empty or contain a single element; if the design
+ * contains multiple child elements, a DesignException is thrown. This
+ * method should be overridden by subclasses whose design may contain
+ * non-content child elements.
+ *
+ * @param children
+ * the child elements of the design that is being read
+ * @param context
+ * the DesignContext instance used to parse the design
+ *
+ * @throws DesignException
+ * if there are multiple child elements
+ * @throws DesignException
+ * if a child element could not be parsed as a Component
+ */
+ protected void readDesignChildren(Elements children, DesignContext context) {
+ if (children.size() > 1) {
throw new DesignException("The container of type "
+ getClass().toString()
+ " can have only one child component.");
- } else if (childCount == 1) {
- Element childElement = design.children().get(0);
- Component newChild = designContext.readDesign(childElement);
- setContent(newChild);
+ } else if (children.size() == 1) {
+ setContent(context.readDesign(children.first()));
}
}
diff --git a/server/src/com/vaadin/ui/Window.java b/server/src/com/vaadin/ui/Window.java
index 653b620746..e7764ffd8d 100644
--- a/server/src/com/vaadin/ui/Window.java
+++ b/server/src/com/vaadin/ui/Window.java
@@ -18,11 +18,18 @@ package com.vaadin.ui;
import java.io.Serializable;
import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
+import java.util.Iterator;
import java.util.LinkedHashSet;
+import java.util.List;
import java.util.Map;
+import org.jsoup.nodes.Element;
+import org.jsoup.select.Elements;
+
import com.vaadin.event.FieldEvents.BlurEvent;
import com.vaadin.event.FieldEvents.BlurListener;
import com.vaadin.event.FieldEvents.BlurNotifier;
@@ -42,6 +49,9 @@ import com.vaadin.shared.ui.window.WindowMode;
import com.vaadin.shared.ui.window.WindowRole;
import com.vaadin.shared.ui.window.WindowServerRpc;
import com.vaadin.shared.ui.window.WindowState;
+import com.vaadin.ui.declarative.DesignAttributeHandler;
+import com.vaadin.ui.declarative.DesignContext;
+import com.vaadin.ui.declarative.DesignException;
import com.vaadin.util.ReflectTools;
/**
@@ -1283,4 +1293,116 @@ public class Window extends Panel implements FocusNotifier, BlurNotifier,
public String getTabStopBottomAssistiveText() {
return getState(false).assistiveTabStopBottomText;
}
+
+ @Override
+ public void readDesign(Element design, DesignContext context) {
+ super.readDesign(design, context);
+
+ if (design.hasAttr("center")) {
+ center();
+ }
+ if (design.hasAttr("position")) {
+ String[] position = design.attr("position").split(",");
+ setPositionX(Integer.parseInt(position[0]));
+ setPositionY(Integer.parseInt(position[1]));
+ }
+ if (design.hasAttr("close-shortcut")) {
+ ShortcutAction shortcut = DesignAttributeHandler
+ .readAttribute("close-shortcut", design.attributes(),
+ ShortcutAction.class);
+ setCloseShortcut(shortcut.getKeyCode(), shortcut.getModifiers());
+ }
+ }
+
+ /**
+ * Reads the content and possible assistive descriptions from the list of
+ * child elements of a design. If an element has an
+ * {@code :assistive-description} attribute, adds the parsed component to
+ * the list of components used as the assistive description of this Window.
+ * Otherwise, sets the component as the content of this Window. If there are
+ * multiple non-description elements, throws a DesignException.
+ *
+ * @param children
+ * child elements in a design
+ * @param context
+ * the DesignContext instance used to parse the design
+ *
+ * @throws DesignException
+ * if there are multiple non-description child elements
+ * @throws DesignException
+ * if a child element could not be parsed as a Component
+ *
+ * @see #setContent(Component)
+ * @see #setAssistiveDescription(Component...)
+ */
+ @Override
+ protected void readDesignChildren(Elements children, DesignContext context) {
+ List<Component> descriptions = new ArrayList<Component>();
+ Elements content = new Elements();
+
+ for (Element child : children) {
+ if (child.hasAttr(":assistive-description")) {
+ descriptions.add(context.readDesign(child));
+ } else {
+ content.add(child);
+ }
+ }
+ super.readDesignChildren(content, context);
+ setAssistiveDescription(descriptions.toArray(new Component[0]));
+ }
+
+ @Override
+ public void writeDesign(Element design, DesignContext context) {
+ super.writeDesign(design, context);
+
+ Window def = context.getDefaultInstance(this);
+
+ if (getState().centered) {
+ design.attr("center", "");
+ }
+
+ DesignAttributeHandler.writeAttribute("position", design.attributes(),
+ getPosition(), def.getPosition(), String.class);
+
+ CloseShortcut shortcut = getCloseShortcut();
+ if (shortcut != null) {
+ // TODO What if several close shortcuts??
+
+ CloseShortcut defShortcut = def.getCloseShortcut();
+ if (defShortcut == null
+ || shortcut.getKeyCode() != defShortcut.getKeyCode()
+ || !Arrays.equals(shortcut.getModifiers(),
+ defShortcut.getModifiers())) {
+ DesignAttributeHandler.writeAttribute("close-shortcut",
+ design.attributes(), shortcut, null,
+ CloseShortcut.class);
+ }
+ }
+
+ for (Component c : getAssistiveDescription()) {
+ Element child = context.createElement(c).attr(
+ ":assistive-description", "");
+ design.appendChild(child);
+ }
+ }
+
+ private String getPosition() {
+ return getPositionX() + "," + getPositionY();
+ }
+
+ private CloseShortcut getCloseShortcut() {
+ Iterator<CloseShortcut> i = getCloseShortcuts().iterator();
+ return i.hasNext() ? i.next() : null;
+ }
+
+ @Override
+ protected Collection<String> getCustomAttributes() {
+ Collection<String> result = super.getCustomAttributes();
+ result.add("center");
+ result.add("position");
+ result.add("position-y");
+ result.add("position-x");
+ result.add("close-shortcut");
+ return result;
+ }
}
diff --git a/server/src/com/vaadin/ui/declarative/converters/DesignShortcutActionConverter.java b/server/src/com/vaadin/ui/declarative/converters/DesignShortcutActionConverter.java
index e2b6ed8e14..d6f2f65938 100644
--- a/server/src/com/vaadin/ui/declarative/converters/DesignShortcutActionConverter.java
+++ b/server/src/com/vaadin/ui/declarative/converters/DesignShortcutActionConverter.java
@@ -126,32 +126,37 @@ public class DesignShortcutActionConverter implements
if (value.length() == 0) {
return null;
}
- String[] data = value.split(" ", 2);
+ String[] data = value.split(" ", 2);
String[] parts = data[0].split("-");
- // handle keycode
- String keyCodePart = parts[parts.length - 1];
- int keyCode = getKeycodeForString(keyCodePart);
- if (keyCode < 0) {
- throw new IllegalArgumentException("Invalid shortcut definition "
- + value);
- }
- // handle modifiers
- int[] modifiers = null;
- if (parts.length > 1) {
- modifiers = new int[parts.length - 1];
- }
- for (int i = 0; i < parts.length - 1; i++) {
- int modifier = getKeycodeForString(parts[i]);
- if (modifier > 0) {
- modifiers[i] = modifier;
- } else {
- throw new IllegalArgumentException(
- "Invalid shortcut definition " + value);
+
+ try {
+ // handle keycode
+ String keyCodePart = parts[parts.length - 1];
+ int keyCode = getKeycodeForString(keyCodePart);
+ if (keyCode < 0) {
+ throw new IllegalArgumentException("Invalid key '"
+ + keyCodePart + "'");
+ }
+ // handle modifiers
+ int[] modifiers = null;
+ if (parts.length > 1) {
+ modifiers = new int[parts.length - 1];
+ }
+ for (int i = 0; i < parts.length - 1; i++) {
+ int modifier = getKeycodeForString(parts[i]);
+ if (modifier > 0) {
+ modifiers[i] = modifier;
+ } else {
+ throw new IllegalArgumentException("Invalid modifier '"
+ + parts[i] + "'");
+ }
}
+ return new ShortcutAction(data.length == 2 ? data[1] : null,
+ keyCode, modifiers);
+ } catch (Exception e) {
+ throw new ConversionException("Invalid shortcut '" + value + "'", e);
}
- return new ShortcutAction(data.length == 2 ? data[1] : null, keyCode,
- modifiers);
}
@Override