summaryrefslogtreecommitdiffstats
path: root/server
diff options
context:
space:
mode:
authorHenrik Paul <henrik@vaadin.com>2015-03-31 14:44:23 +0300
committerHenrik Paul <henrik@vaadin.com>2015-03-31 14:44:23 +0300
commit844b2c6c41d57d4db1238eb6096f225c9fdb8314 (patch)
treeffdd57cd35da2df500fbfae5981de381439d1f5c /server
parent2080f86e03552c56d52f488e4dcd72282cd64f62 (diff)
parent3ab82ace45827365e87f9540fad3dffaed0679b5 (diff)
downloadvaadin-framework-844b2c6c41d57d4db1238eb6096f225c9fdb8314.tar.gz
vaadin-framework-844b2c6c41d57d4db1238eb6096f225c9fdb8314.zip
Merge remote-tracking branch 'origin/master' into grid-7.5
Change-Id: Ife8c6d2a5f6c134a6e28e862f524b6e687199cc8
Diffstat (limited to 'server')
-rw-r--r--server/src/com/vaadin/server/Constants.java3
-rw-r--r--server/src/com/vaadin/server/DefaultDeploymentConfiguration.java19
-rw-r--r--server/src/com/vaadin/server/DeploymentConfiguration.java10
-rw-r--r--server/src/com/vaadin/server/ExternalResource.java1
-rw-r--r--server/src/com/vaadin/server/FileResource.java1
-rw-r--r--server/src/com/vaadin/server/ServletPortletHelper.java3
-rw-r--r--server/src/com/vaadin/server/communication/UIInitHandler.java5
-rw-r--r--server/src/com/vaadin/ui/AbstractMedia.java52
-rw-r--r--server/src/com/vaadin/ui/AbstractSplitPanel.java77
-rw-r--r--server/src/com/vaadin/ui/Calendar.java71
-rw-r--r--server/src/com/vaadin/ui/CustomLayout.java36
-rw-r--r--server/src/com/vaadin/ui/DragAndDropWrapper.java37
-rw-r--r--server/src/com/vaadin/ui/MenuBar.java153
-rw-r--r--server/src/com/vaadin/ui/PushConfiguration.java47
-rw-r--r--server/src/com/vaadin/ui/Slider.java38
-rw-r--r--server/src/com/vaadin/ui/Video.java39
-rw-r--r--server/src/com/vaadin/ui/declarative/Design.java172
-rw-r--r--server/src/com/vaadin/ui/declarative/DesignAttributeHandler.java5
-rw-r--r--server/src/com/vaadin/ui/declarative/DesignContext.java170
-rw-r--r--server/src/com/vaadin/ui/declarative/converters/DesignResourceConverter.java3
-rw-r--r--server/tests/src/com/vaadin/server/AbstractDeploymentConfigurationTest.java4
-rw-r--r--server/tests/src/com/vaadin/tests/components/draganddropwrapper/DragAndDropWrapperDeclarativeTest.java66
-rw-r--r--server/tests/src/com/vaadin/tests/components/menubar/MenuBarDeclarativeTest.java139
-rw-r--r--server/tests/src/com/vaadin/tests/design/ComponentMapperTest.java129
-rw-r--r--server/tests/src/com/vaadin/tests/server/component/audio/AudioDeclarativeTest.java63
-rw-r--r--server/tests/src/com/vaadin/tests/server/component/audio/VideoDeclarativeTest.java59
-rw-r--r--server/tests/src/com/vaadin/tests/server/component/calendar/CalendarDeclarativeTest.java61
-rw-r--r--server/tests/src/com/vaadin/tests/server/component/customlayout/CustomLayoutDeclarativeTest.java96
-rw-r--r--server/tests/src/com/vaadin/tests/server/component/slider/SliderDeclarativeTest.java66
-rw-r--r--server/tests/src/com/vaadin/tests/util/MockDeploymentConfiguration.java6
-rw-r--r--server/tests/src/com/vaadin/ui/SplitPositionChangeListenerTest.java44
31 files changed, 1477 insertions, 198 deletions
diff --git a/server/src/com/vaadin/server/Constants.java b/server/src/com/vaadin/server/Constants.java
index b7c2a1ff3e..f3cdd48d58 100644
--- a/server/src/com/vaadin/server/Constants.java
+++ b/server/src/com/vaadin/server/Constants.java
@@ -132,12 +132,11 @@ public interface Constants {
static final String SERVLET_PARAMETER_RESOURCE_CACHE_TIME = "resourceCacheTime";
static final String SERVLET_PARAMETER_HEARTBEAT_INTERVAL = "heartbeatInterval";
static final String SERVLET_PARAMETER_CLOSE_IDLE_SESSIONS = "closeIdleSessions";
+ static final String SERVLET_PARAMETER_PUSH_MODE = "pushMode";
static final String SERVLET_PARAMETER_UI_PROVIDER = "UIProvider";
static final String SERVLET_PARAMETER_LEGACY_PROPERTY_TOSTRING = "legacyPropertyToString";
static final String SERVLET_PARAMETER_SYNC_ID_CHECK = "syncIdCheck";
static final String SERVLET_PARAMETER_SENDURLSASPARAMETERS = "sendUrlsAsParameters";
- static final String SERVLET_PARAMETER_PUSH_MODE = "pushMode";
- static final String SERVLET_PARAMETER_PUSH_PATH = "pushPath";
// Configurable parameter names
static final String PARAMETER_VAADIN_RESOURCES = "Resources";
diff --git a/server/src/com/vaadin/server/DefaultDeploymentConfiguration.java b/server/src/com/vaadin/server/DefaultDeploymentConfiguration.java
index 5402979be8..b26e048431 100644
--- a/server/src/com/vaadin/server/DefaultDeploymentConfiguration.java
+++ b/server/src/com/vaadin/server/DefaultDeploymentConfiguration.java
@@ -61,13 +61,6 @@ public class DefaultDeploymentConfiguration extends
public static final boolean DEFAULT_SEND_URLS_AS_PARAMETERS = true;
- /**
- * Default value for {@link #getPushPath()} = {@value} .
- *
- * @since 7.4.1
- */
- public static final String DEFAULT_PUSH_PATH = "PUSH";
-
private final Properties initParameters;
private boolean productionMode;
private boolean xsrfProtectionEnabled;
@@ -292,18 +285,6 @@ public class DefaultDeploymentConfiguration extends
}
/**
- * {@inheritDoc}
- * <p>
- * The default path {@link DEFAULT_PUSH_PATH} can be changed by using init
- * parameter {@link Constants.SERVLET_PARAMETER_PUSH_PATH}.
- */
- @Override
- public String getPushPath() {
- return getApplicationOrSystemProperty(
- Constants.SERVLET_PARAMETER_PUSH_PATH, DEFAULT_PUSH_PATH);
- }
-
- /**
* Log a warning if Vaadin is not running in production mode.
*/
private void checkProductionMode() {
diff --git a/server/src/com/vaadin/server/DeploymentConfiguration.java b/server/src/com/vaadin/server/DeploymentConfiguration.java
index 06556e28a7..968ec7c0c3 100644
--- a/server/src/com/vaadin/server/DeploymentConfiguration.java
+++ b/server/src/com/vaadin/server/DeploymentConfiguration.java
@@ -195,7 +195,7 @@ public interface DeploymentConfiguration extends Serializable {
*
* @since 7.4
*
- * @return the name of the widgetset
+ * @return UI class name
*/
public String getWidgetset(String defaultValue);
@@ -214,14 +214,6 @@ public interface DeploymentConfiguration extends Serializable {
public String getClassLoaderName();
/**
- * Returns the push path configuration option value. Should never be null.
- *
- * @since 7.4.1
- * @return the path used with server push
- */
- public String getPushPath();
-
- /**
* Returns to legacy Property.toString() mode used. See
* {@link AbstractProperty#isLegacyToStringEnabled()} for more information.
*
diff --git a/server/src/com/vaadin/server/ExternalResource.java b/server/src/com/vaadin/server/ExternalResource.java
index 0c724ae19f..e3b026dde8 100644
--- a/server/src/com/vaadin/server/ExternalResource.java
+++ b/server/src/com/vaadin/server/ExternalResource.java
@@ -124,5 +124,4 @@ public class ExternalResource implements Resource, Serializable {
public void setMIMEType(String mimeType) {
this.mimeType = mimeType;
}
-
}
diff --git a/server/src/com/vaadin/server/FileResource.java b/server/src/com/vaadin/server/FileResource.java
index b32905f972..28de124fe9 100644
--- a/server/src/com/vaadin/server/FileResource.java
+++ b/server/src/com/vaadin/server/FileResource.java
@@ -156,5 +156,4 @@ public class FileResource implements ConnectorResource {
public void setBufferSize(int bufferSize) {
this.bufferSize = bufferSize;
}
-
}
diff --git a/server/src/com/vaadin/server/ServletPortletHelper.java b/server/src/com/vaadin/server/ServletPortletHelper.java
index 1f0c7f02b9..197d9fe416 100644
--- a/server/src/com/vaadin/server/ServletPortletHelper.java
+++ b/server/src/com/vaadin/server/ServletPortletHelper.java
@@ -124,8 +124,7 @@ public class ServletPortletHelper implements Serializable {
}
public static boolean isPushRequest(VaadinRequest request) {
- return hasPathPrefix(request, request.getService()
- .getDeploymentConfiguration().getPushPath() + '/');
+ return hasPathPrefix(request, ApplicationConstants.PUSH_PATH + '/');
}
public static void initDefaultUIProvider(VaadinSession session,
diff --git a/server/src/com/vaadin/server/communication/UIInitHandler.java b/server/src/com/vaadin/server/communication/UIInitHandler.java
index 02b4e64159..3a6dc1e55f 100644
--- a/server/src/com/vaadin/server/communication/UIInitHandler.java
+++ b/server/src/com/vaadin/server/communication/UIInitHandler.java
@@ -198,11 +198,10 @@ public abstract class UIInitHandler extends SynchronizedRequestHandler {
PushMode pushMode = provider.getPushMode(event);
if (pushMode == null) {
- pushMode = session.getConfiguration().getPushMode();
+ pushMode = session.getService().getDeploymentConfiguration()
+ .getPushMode();
}
ui.getPushConfiguration().setPushMode(pushMode);
- ui.getPushConfiguration().setPushPath(
- session.getConfiguration().getPushPath());
Transport transport = provider.getPushTransport(event);
if (transport != null) {
diff --git a/server/src/com/vaadin/ui/AbstractMedia.java b/server/src/com/vaadin/ui/AbstractMedia.java
index 0bd8c3ea77..a0344624d7 100644
--- a/server/src/com/vaadin/ui/AbstractMedia.java
+++ b/server/src/com/vaadin/ui/AbstractMedia.java
@@ -18,12 +18,17 @@ package com.vaadin.ui;
import java.io.IOException;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
+import org.jsoup.nodes.Attributes;
+import org.jsoup.nodes.Element;
+import org.jsoup.nodes.Node;
+
import com.vaadin.server.ConnectorResource;
import com.vaadin.server.DownloadStream;
import com.vaadin.server.Resource;
@@ -34,6 +39,8 @@ import com.vaadin.server.VaadinSession;
import com.vaadin.shared.communication.URLReference;
import com.vaadin.shared.ui.AbstractMediaState;
import com.vaadin.shared.ui.MediaControl;
+import com.vaadin.ui.declarative.DesignAttributeHandler;
+import com.vaadin.ui.declarative.DesignContext;
/**
* Abstract base class for the HTML5 media components.
@@ -256,4 +263,49 @@ public abstract class AbstractMedia extends AbstractComponent {
getRpcProxy(MediaControl.class).play();
}
+ @Override
+ public void writeDesign(Element design, DesignContext designContext) {
+ super.writeDesign(design, designContext);
+
+ String altText = getAltText();
+ if (altText != null && !altText.isEmpty()) {
+ design.append(altText);
+ }
+
+ for (Resource r : getSources()) {
+ Attributes attr = design.appendElement("source").attributes();
+ DesignAttributeHandler.writeAttribute("href", attr, r, null,
+ Resource.class);
+ }
+ }
+
+ @Override
+ public void readDesign(Element design, DesignContext designContext) {
+ super.readDesign(design, designContext);
+
+ String altText = "";
+ for (Node child : design.childNodes()) {
+ if (child instanceof Element
+ && ((Element) child).tagName().equals("source")
+ && child.hasAttr("href")) {
+ addSource(DesignAttributeHandler.readAttribute("href",
+ child.attributes(), Resource.class));
+ } else {
+ altText += child.toString();
+ }
+ }
+
+ altText = altText.trim();
+ if (!altText.isEmpty()) {
+ setAltText(altText);
+ }
+ }
+
+ @Override
+ protected Collection<String> getCustomAttributes() {
+ Collection<String> result = super.getCustomAttributes();
+ result.add("alt-text");
+ return result;
+ }
+
}
diff --git a/server/src/com/vaadin/ui/AbstractSplitPanel.java b/server/src/com/vaadin/ui/AbstractSplitPanel.java
index af73fca6a8..8a7b9086c2 100644
--- a/server/src/com/vaadin/ui/AbstractSplitPanel.java
+++ b/server/src/com/vaadin/ui/AbstractSplitPanel.java
@@ -64,6 +64,8 @@ public abstract class AbstractSplitPanel extends AbstractComponentContainer {
@Override
public void setSplitterPosition(float position) {
getSplitterState().position = position;
+ fireEvent(new SplitPositionChangeEvent(AbstractSplitPanel.this,
+ position, getSplitPositionUnit()));
}
};
@@ -331,6 +333,8 @@ public abstract class AbstractSplitPanel extends AbstractComponentContainer {
splitterState.positionUnit = unit.getSymbol();
splitterState.positionReversed = reverse;
posUnit = unit;
+ fireEvent(new SplitPositionChangeEvent(AbstractSplitPanel.this, pos,
+ posUnit));
}
/**
@@ -520,6 +524,54 @@ public abstract class AbstractSplitPanel extends AbstractComponentContainer {
}
+ /**
+ * Interface for listening for {@link SplitPositionChangeEvent}s fired by a
+ * SplitPanel.
+ *
+ * @since
+ */
+ public interface SplitPositionChangeListener extends ConnectorEventListener {
+
+ public static final Method moveMethod = ReflectTools.findMethod(
+ SplitPositionChangeListener.class, "onSplitPositionChanged",
+ SplitPositionChangeEvent.class);
+
+ /**
+ * SplitPanel splitter position has been changed.
+ *
+ * @param event
+ * SplitPositionChangeEvent event.
+ */
+ public void onSplitPositionChanged(SplitPositionChangeEvent event);
+ }
+
+ /**
+ * Event that indicates a change in SplitPanel's splitter position.
+ *
+ * @since
+ */
+ public static class SplitPositionChangeEvent extends Component.Event {
+
+ private final float position;
+ private final Unit unit;
+
+ public SplitPositionChangeEvent(final Component source,
+ final float position, final Unit unit) {
+ super(source);
+ this.position = position;
+ this.unit = unit;
+ }
+
+ public float getSplitPosition() {
+ return position;
+ }
+
+ public Unit getSplitPositionUnit() {
+ return unit;
+ }
+
+ }
+
public void addSplitterClickListener(SplitterClickListener listener) {
addListener(EventId.CLICK_EVENT_IDENTIFIER, SplitterClickEvent.class,
listener, SplitterClickListener.clickMethod);
@@ -548,6 +600,31 @@ public abstract class AbstractSplitPanel extends AbstractComponentContainer {
removeSplitterClickListener(listener);
}
+ /**
+ * Register a listener to handle {@link SplitPositionChangeEvent}s.
+ *
+ * @since
+ * @param listener
+ * {@link SplitPositionChangeListener} to be registered.
+ */
+ public void addSplitPositionChangeListener(
+ SplitPositionChangeListener listener) {
+ addListener(SplitPositionChangeEvent.class, listener,
+ SplitPositionChangeListener.moveMethod);
+ }
+
+ /**
+ * Removes a {@link SplitPositionChangeListener}.
+ *
+ * @since
+ * @param listener
+ * SplitPositionChangeListener to be removed.
+ */
+ public void removeSplitPositionChangeListener(
+ SplitPositionChangeListener listener) {
+ removeListener(SplitPositionChangeEvent.class, listener);
+ }
+
@Override
protected AbstractSplitPanelState getState() {
return (AbstractSplitPanelState) super.getState();
diff --git a/server/src/com/vaadin/ui/Calendar.java b/server/src/com/vaadin/ui/Calendar.java
index 48c024026e..acddbe308b 100644
--- a/server/src/com/vaadin/ui/Calendar.java
+++ b/server/src/com/vaadin/ui/Calendar.java
@@ -22,6 +22,7 @@ import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collection;
import java.util.Date;
import java.util.EventListener;
import java.util.GregorianCalendar;
@@ -37,6 +38,9 @@ import java.util.TimeZone;
import java.util.logging.Level;
import java.util.logging.Logger;
+import org.jsoup.nodes.Attributes;
+import org.jsoup.nodes.Element;
+
import com.vaadin.data.Container;
import com.vaadin.data.util.BeanItemContainer;
import com.vaadin.event.Action;
@@ -84,6 +88,8 @@ import com.vaadin.ui.components.calendar.handler.BasicEventMoveHandler;
import com.vaadin.ui.components.calendar.handler.BasicEventResizeHandler;
import com.vaadin.ui.components.calendar.handler.BasicForwardHandler;
import com.vaadin.ui.components.calendar.handler.BasicWeekClickHandler;
+import com.vaadin.ui.declarative.DesignAttributeHandler;
+import com.vaadin.ui.declarative.DesignContext;
/**
* <p>
@@ -334,6 +340,10 @@ public class Calendar extends AbstractComponent implements
*/
public Date getStartDate() {
if (startDate == null) {
+ currentCalendar.set(java.util.Calendar.MILLISECOND, 0);
+ currentCalendar.set(java.util.Calendar.SECOND, 0);
+ currentCalendar.set(java.util.Calendar.MINUTE, 0);
+ currentCalendar.set(java.util.Calendar.HOUR_OF_DAY, 0);
currentCalendar.set(java.util.Calendar.DAY_OF_WEEK,
currentCalendar.getFirstDayOfWeek());
return currentCalendar.getTime();
@@ -363,6 +373,10 @@ public class Calendar extends AbstractComponent implements
*/
public Date getEndDate() {
if (endDate == null) {
+ currentCalendar.set(java.util.Calendar.MILLISECOND, 0);
+ currentCalendar.set(java.util.Calendar.SECOND, 59);
+ currentCalendar.set(java.util.Calendar.MINUTE, 59);
+ currentCalendar.set(java.util.Calendar.HOUR_OF_DAY, 23);
currentCalendar.set(java.util.Calendar.DAY_OF_WEEK,
currentCalendar.getFirstDayOfWeek() + 6);
return currentCalendar.getTime();
@@ -655,8 +669,14 @@ public class Calendar extends AbstractComponent implements
*/
public TimeFormat getTimeFormat() {
if (currentTimeFormat == null) {
- SimpleDateFormat f = (SimpleDateFormat) SimpleDateFormat
- .getTimeInstance(SimpleDateFormat.SHORT, getLocale());
+ SimpleDateFormat f;
+ if (getLocale() == null) {
+ f = (SimpleDateFormat) SimpleDateFormat
+ .getTimeInstance(SimpleDateFormat.SHORT);
+ } else {
+ f = (SimpleDateFormat) SimpleDateFormat.getTimeInstance(
+ SimpleDateFormat.SHORT, getLocale());
+ }
String p = f.toPattern();
if (p.indexOf("HH") != -1 || p.indexOf("H") != -1) {
return TimeFormat.Format24H;
@@ -1925,4 +1945,51 @@ public class Calendar extends AbstractComponent implements
return getState(false).eventCaptionAsHtml;
}
+ @Override
+ public void readDesign(Element design, DesignContext designContext) {
+ super.readDesign(design, designContext);
+
+ Attributes attr = design.attributes();
+ if (design.hasAttr("time-format")) {
+ setTimeFormat(TimeFormat.valueOf("Format"
+ + design.attr("time-format").toUpperCase()));
+ }
+
+ if (design.hasAttr("start-date")) {
+ setStartDate(DesignAttributeHandler.readAttribute("start-date",
+ attr, Date.class));
+ }
+ if (design.hasAttr("end-date")) {
+ setEndDate(DesignAttributeHandler.readAttribute("end-date", attr,
+ Date.class));
+ }
+ };
+
+ @Override
+ public void writeDesign(Element design, DesignContext designContext) {
+ super.writeDesign(design, designContext);
+
+ if (currentTimeFormat != null) {
+ design.attr("time-format",
+ (currentTimeFormat == TimeFormat.Format12H ? "12h" : "24h"));
+ }
+ if (startDate != null) {
+ design.attr("start-date", df_date.format(getStartDate()));
+ }
+ if (endDate != null) {
+ design.attr("end-date", df_date.format(getEndDate()));
+ }
+ if (!getTimeZone().equals(TimeZone.getDefault())) {
+ design.attr("time-zone", getTimeZone().getID());
+ }
+ }
+
+ @Override
+ protected Collection<String> getCustomAttributes() {
+ Collection<String> customAttributes = super.getCustomAttributes();
+ customAttributes.add("time-format");
+ customAttributes.add("start-date");
+ customAttributes.add("end-date");
+ return customAttributes;
+ }
}
diff --git a/server/src/com/vaadin/ui/CustomLayout.java b/server/src/com/vaadin/ui/CustomLayout.java
index a9c266b0b9..ceb47e1e7a 100644
--- a/server/src/com/vaadin/ui/CustomLayout.java
+++ b/server/src/com/vaadin/ui/CustomLayout.java
@@ -23,12 +23,16 @@ import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
+import java.util.Map.Entry;
import java.util.Set;
+import org.jsoup.nodes.Element;
+
import com.vaadin.server.JsonPaintTarget;
import com.vaadin.server.PaintException;
import com.vaadin.server.PaintTarget;
import com.vaadin.shared.ui.customlayout.CustomLayoutState;
+import com.vaadin.ui.declarative.DesignContext;
/**
* <p>
@@ -71,8 +75,8 @@ public class CustomLayout extends AbstractLayout implements LegacyComponent {
* {@link #setTemplateName(String)}, that makes layout fetch the template
* from theme, or {@link #setTemplateContents(String)}.
*/
- protected CustomLayout() {
- setWidth(100, UNITS_PERCENTAGE);
+ public CustomLayout() {
+ setWidth(100, Unit.PERCENTAGE);
}
/**
@@ -305,4 +309,32 @@ public class CustomLayout extends AbstractLayout implements LegacyComponent {
}
}
+ @Override
+ public void readDesign(Element design, DesignContext designContext) {
+ super.readDesign(design, designContext);
+
+ for (Element child : design.children()) {
+
+ Component childComponent = designContext.readDesign(child);
+
+ if (child.hasAttr(":location")) {
+ addComponent(childComponent, child.attr(":location"));
+ } else {
+ addComponent(childComponent);
+ }
+ }
+ }
+
+ @Override
+ public void writeDesign(Element design, DesignContext designContext) {
+ super.writeDesign(design, designContext);
+
+ for (Entry<String, Component> slot : slots.entrySet()) {
+ Element child = designContext.createElement(slot.getValue());
+ if (slots.size() > 1 || !"".equals(slot.getKey())) {
+ child.attr(":location", slot.getKey());
+ }
+ design.appendChild(child);
+ }
+ }
}
diff --git a/server/src/com/vaadin/ui/DragAndDropWrapper.java b/server/src/com/vaadin/ui/DragAndDropWrapper.java
index 6e4ec903d2..b813973861 100644
--- a/server/src/com/vaadin/ui/DragAndDropWrapper.java
+++ b/server/src/com/vaadin/ui/DragAndDropWrapper.java
@@ -24,6 +24,8 @@ import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
+import org.jsoup.nodes.Element;
+
import com.vaadin.event.Transferable;
import com.vaadin.event.TransferableImpl;
import com.vaadin.event.dd.DragSource;
@@ -38,6 +40,7 @@ import com.vaadin.shared.MouseEventDetails;
import com.vaadin.shared.ui.dd.HorizontalDropLocation;
import com.vaadin.shared.ui.dd.VerticalDropLocation;
import com.vaadin.shared.ui.draganddropwrapper.DragAndDropWrapperConstants;
+import com.vaadin.ui.declarative.DesignContext;
@SuppressWarnings("serial")
public class DragAndDropWrapper extends CustomComponent implements DropTarget,
@@ -185,7 +188,12 @@ public class DragAndDropWrapper extends CustomComponent implements DropTarget,
private Set<String> sentIds = new HashSet<String>();
- private DragAndDropWrapper() {
+ /**
+ * This is an internal constructor. Use
+ * {@link DragAndDropWrapper#DragAndDropWrapper(Component)} instead.
+ */
+ @Deprecated
+ public DragAndDropWrapper() {
super();
}
@@ -458,4 +466,31 @@ public class DragAndDropWrapper extends CustomComponent implements DropTarget,
}
+ @Override
+ public void readDesign(Element design, DesignContext designContext) {
+ super.readDesign(design, designContext);
+
+ for (Element child : design.children()) {
+ Component component = designContext.readDesign(child);
+ if (getDragStartMode() == DragStartMode.COMPONENT_OTHER
+ && child.hasAttr(":drag-image")) {
+ setDragImageComponent(component);
+ } else if (getCompositionRoot() == null) {
+ setCompositionRoot(component);
+ }
+ }
+ }
+
+ @Override
+ public void writeDesign(Element design, DesignContext designContext) {
+ super.writeDesign(design, designContext);
+
+ design.appendChild(designContext.createElement(getCompositionRoot()));
+ if (getDragStartMode() == DragStartMode.COMPONENT_OTHER) {
+ Element child = designContext
+ .createElement(getDragImageComponent());
+ child.attr(":drag-image", "");
+ design.appendChild(child);
+ }
+ }
}
diff --git a/server/src/com/vaadin/ui/MenuBar.java b/server/src/com/vaadin/ui/MenuBar.java
index 6b6555c0a2..747ce42727 100644
--- a/server/src/com/vaadin/ui/MenuBar.java
+++ b/server/src/com/vaadin/ui/MenuBar.java
@@ -17,17 +17,25 @@ package com.vaadin.ui;
import java.io.Serializable;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Stack;
+import org.jsoup.nodes.Attributes;
+import org.jsoup.nodes.Element;
+import org.jsoup.nodes.Node;
+import org.jsoup.parser.Tag;
+
import com.vaadin.server.PaintException;
import com.vaadin.server.PaintTarget;
import com.vaadin.server.Resource;
import com.vaadin.shared.ui.menubar.MenuBarConstants;
import com.vaadin.shared.ui.menubar.MenuBarState;
import com.vaadin.ui.Component.Focusable;
+import com.vaadin.ui.declarative.DesignAttributeHandler;
+import com.vaadin.ui.declarative.DesignContext;
/**
* <p>
@@ -932,7 +940,150 @@ public class MenuBar extends AbstractComponent implements LegacyComponent,
this.checked = checked;
markAsDirty();
}
-
}// class MenuItem
+ @Override
+ public void writeDesign(Element design, DesignContext designContext) {
+ super.writeDesign(design, designContext);
+ for (MenuItem item : getItems()) {
+ design.appendChild(createMenuElement(item));
+ }
+
+ // in many cases there seems to be an empty more menu item
+ if (getMoreMenuItem() != null && !getMoreMenuItem().getText().isEmpty()) {
+ Element moreMenu = createMenuElement(getMoreMenuItem());
+ moreMenu.attr("more", "");
+ design.appendChild(moreMenu);
+ }
+
+ if (!htmlContentAllowed) {
+ design.attr(DESIGN_ATTR_PLAIN_TEXT, "");
+ }
+ }
+
+ protected Element createMenuElement(MenuItem item) {
+ Element menuElement = new Element(Tag.valueOf("menu"), "");
+ // Defaults
+ MenuItem def = new MenuItem("", null, null);
+
+ Attributes attr = menuElement.attributes();
+ DesignAttributeHandler.writeAttribute("icon", attr, item.getIcon(),
+ def.getIcon(), Resource.class);
+ DesignAttributeHandler.writeAttribute("disabled", attr,
+ !item.isEnabled(), !def.isEnabled(), boolean.class);
+ DesignAttributeHandler.writeAttribute("visible", attr,
+ item.isVisible(), def.isVisible(), boolean.class);
+ DesignAttributeHandler.writeAttribute("separator", attr,
+ item.isSeparator(), def.isSeparator(), boolean.class);
+ DesignAttributeHandler.writeAttribute("checkable", attr,
+ item.isCheckable(), def.isCheckable(), boolean.class);
+ DesignAttributeHandler.writeAttribute("checked", attr,
+ item.isChecked(), def.isChecked(), boolean.class);
+ DesignAttributeHandler.writeAttribute("description", attr,
+ item.getDescription(), def.getDescription(), String.class);
+ DesignAttributeHandler.writeAttribute("style-name", attr,
+ item.getStyleName(), def.getStyleName(), String.class);
+
+ menuElement.append(item.getText());
+
+ if (item.hasChildren()) {
+ for (MenuItem subMenu : item.getChildren()) {
+ menuElement.appendChild(createMenuElement(subMenu));
+ }
+ }
+
+ return menuElement;
+ }
+
+ protected MenuItem readMenuElement(Element menuElement) {
+ Resource icon = null;
+ if (menuElement.hasAttr("icon")) {
+ icon = DesignAttributeHandler.getFormatter().parse(
+ menuElement.attr("icon"), Resource.class);
+ }
+
+ String caption = "";
+ List<Element> subMenus = new ArrayList<Element>();
+ for (Node node : menuElement.childNodes()) {
+ if (node instanceof Element
+ && ((Element) node).tagName().equals("menu")) {
+ subMenus.add((Element) node);
+ }
+ caption += node.toString();
+ }
+ MenuItem menu = new MenuItem(caption.trim(), icon, null);
+
+ Attributes attr = menuElement.attributes();
+ if (menuElement.hasAttr("icon")) {
+ menu.setIcon(DesignAttributeHandler.readAttribute("icon", attr,
+ Resource.class));
+ }
+ if (menuElement.hasAttr("disabled")) {
+ menu.setEnabled(!DesignAttributeHandler.readAttribute("disabled",
+ attr, boolean.class));
+ }
+ if (menuElement.hasAttr("visible")) {
+ menu.setVisible(DesignAttributeHandler.readAttribute("visible",
+ attr, boolean.class));
+ }
+ if (menuElement.hasAttr("separator")) {
+ menu.setSeparator(DesignAttributeHandler.readAttribute("separator",
+ attr, boolean.class));
+ }
+ if (menuElement.hasAttr("checkable")) {
+ menu.setCheckable(DesignAttributeHandler.readAttribute("checkable",
+ attr, boolean.class));
+ }
+ if (menuElement.hasAttr("checked")) {
+ menu.setChecked(DesignAttributeHandler.readAttribute("checked",
+ attr, boolean.class));
+ }
+ if (menuElement.hasAttr("description")) {
+ menu.setDescription(DesignAttributeHandler.readAttribute(
+ "description", attr, String.class));
+ }
+ if (menuElement.hasAttr("style-name")) {
+ menu.setStyleName(DesignAttributeHandler.readAttribute(
+ "style-name", attr, String.class));
+ }
+
+ if (!subMenus.isEmpty()) {
+ menu.itsChildren = new ArrayList<MenuItem>();
+ }
+
+ for (Element subMenu : subMenus) {
+ MenuItem newItem = readMenuElement(subMenu);
+
+ newItem.setParent(menu);
+ menu.itsChildren.add(newItem);
+ }
+
+ return menu;
+ }
+
+ @Override
+ public void readDesign(Element design, DesignContext designContext) {
+ super.readDesign(design, designContext);
+
+ for (Element itemElement : design.children()) {
+ if (itemElement.tagName().equals("menu")) {
+ MenuItem menuItem = readMenuElement(itemElement);
+ if (itemElement.hasAttr("more")) {
+ setMoreMenuItem(menuItem);
+ } else {
+ menuItems.add(menuItem);
+ }
+ }
+ }
+
+ setHtmlContentAllowed(!design.hasAttr(DESIGN_ATTR_PLAIN_TEXT));
+ }
+
+ @Override
+ protected Collection<String> getCustomAttributes() {
+ Collection<String> result = super.getCustomAttributes();
+ result.add(DESIGN_ATTR_PLAIN_TEXT);
+ result.add("html-content-allowed");
+ return result;
+ }
}// class MenuBar
diff --git a/server/src/com/vaadin/ui/PushConfiguration.java b/server/src/com/vaadin/ui/PushConfiguration.java
index d5e89b4b14..90ad28542c 100644
--- a/server/src/com/vaadin/ui/PushConfiguration.java
+++ b/server/src/com/vaadin/ui/PushConfiguration.java
@@ -105,26 +105,6 @@ public interface PushConfiguration extends Serializable {
public void setFallbackTransport(Transport fallbackTransport);
/**
- * Sets the path that is used with push.
- *
- * @since 7.4.1
- * @param pushPath
- * The path to be used with push
- *
- * @throws IllegalArgumentException
- * if the argument is null or empty.
- */
- public void setPushPath(String pushPath);
-
- /**
- * Returns the path used with push.
- *
- * @since 7.4.1
- * @return The path that is used with push
- */
- public String getPushPath();
-
- /**
* Returns the given parameter, if set.
* <p>
* This method provides low level access to push parameters and is typically
@@ -278,32 +258,6 @@ class PushConfigurationImpl implements PushConfiguration {
/*
* (non-Javadoc)
*
- * @see com.vaadin.ui.PushConfiguration#setPushPath(java.lang.String)
- */
- @Override
- public void setPushPath(String pushPath) {
- if (pushPath != null && !pushPath.isEmpty()) {
- getState().pushPath = pushPath;
- } else {
- throw new IllegalArgumentException(
- "Push path can't be empty or null");
- }
-
- }
-
- /*
- * (non-Javadoc)
- *
- * @see com.vaadin.ui.PushConfiguration#getPushPath()
- */
- @Override
- public String getPushPath() {
- return getState(false).pushPath;
- }
-
- /*
- * (non-Javadoc)
- *
* @see com.vaadin.ui.PushConfiguration#getParameter(java.lang.String)
*/
@Override
@@ -336,4 +290,5 @@ class PushConfigurationImpl implements PushConfiguration {
return Collections.unmodifiableCollection(getState(false).parameters
.keySet());
}
+
}
diff --git a/server/src/com/vaadin/ui/Slider.java b/server/src/com/vaadin/ui/Slider.java
index 99e1e8d5e9..40a4047d53 100644
--- a/server/src/com/vaadin/ui/Slider.java
+++ b/server/src/com/vaadin/ui/Slider.java
@@ -16,9 +16,16 @@
package com.vaadin.ui;
+import java.util.Collection;
+
+import org.jsoup.nodes.Attributes;
+import org.jsoup.nodes.Element;
+
import com.vaadin.shared.ui.slider.SliderOrientation;
import com.vaadin.shared.ui.slider.SliderServerRpc;
import com.vaadin.shared.ui.slider.SliderState;
+import com.vaadin.ui.declarative.DesignAttributeHandler;
+import com.vaadin.ui.declarative.DesignContext;
/**
* A component for selecting a numerical value within a range.
@@ -353,4 +360,35 @@ public class Slider extends AbstractField<Double> {
// Slider is never really "empty"
return false;
}
+
+ @Override
+ public void readDesign(Element design, DesignContext context) {
+ super.readDesign(design, context);
+ Attributes attr = design.attributes();
+ if (attr.hasKey("vertical")) {
+ setOrientation(SliderOrientation.VERTICAL);
+ }
+ if (!attr.get("value").isEmpty()) {
+ setValue(DesignAttributeHandler.readAttribute("value", attr,
+ Double.class));
+ }
+ }
+
+ @Override
+ public void writeDesign(Element design, DesignContext context) {
+ super.writeDesign(design, context);
+ if (getOrientation() == SliderOrientation.VERTICAL) {
+ design.attr("vertical", "");
+ }
+ Slider defaultSlider = context.getDefaultInstance(this);
+ DesignAttributeHandler.writeAttribute(this, "value",
+ design.attributes(), defaultSlider);
+ }
+
+ @Override
+ protected Collection<String> getCustomAttributes() {
+ Collection<String> result = super.getCustomAttributes();
+ result.add("orientation");
+ return result;
+ }
}
diff --git a/server/src/com/vaadin/ui/Video.java b/server/src/com/vaadin/ui/Video.java
index e690218e6f..46a4293b36 100644
--- a/server/src/com/vaadin/ui/Video.java
+++ b/server/src/com/vaadin/ui/Video.java
@@ -16,9 +16,17 @@
package com.vaadin.ui;
+import java.util.Collection;
+
+import org.jsoup.nodes.Attributes;
+import org.jsoup.nodes.Element;
+import org.jsoup.select.Elements;
+
import com.vaadin.server.Resource;
import com.vaadin.shared.ui.video.VideoConstants;
import com.vaadin.shared.ui.video.VideoState;
+import com.vaadin.ui.declarative.DesignAttributeHandler;
+import com.vaadin.ui.declarative.DesignContext;
/**
* The Video component translates into an HTML5 &lt;video&gt; element and as
@@ -89,4 +97,35 @@ public class Video extends AbstractMedia {
return getResource(VideoConstants.POSTER_RESOURCE);
}
+ @Override
+ public void readDesign(Element design, DesignContext designContext) {
+ Elements elems = design.getElementsByTag("poster");
+ for (Element poster : elems) {
+ if (getPoster() == null && poster.hasAttr("href")) {
+ setPoster(DesignAttributeHandler.readAttribute("href",
+ poster.attributes(), Resource.class));
+ }
+ poster.remove();
+ }
+
+ // Poster is extracted so AbstractMedia does not include it in alt text
+ super.readDesign(design, designContext);
+ }
+
+ @Override
+ public void writeDesign(Element design, DesignContext designContext) {
+ super.writeDesign(design, designContext);
+ if (getPoster() != null) {
+ Attributes attr = design.appendElement("poster").attributes();
+ DesignAttributeHandler.writeAttribute("href", attr, getPoster(),
+ null, Resource.class);
+ }
+ }
+
+ @Override
+ protected Collection<String> getCustomAttributes() {
+ Collection<String> result = super.getCustomAttributes();
+ result.add("poster");
+ return result;
+ }
}
diff --git a/server/src/com/vaadin/ui/declarative/Design.java b/server/src/com/vaadin/ui/declarative/Design.java
index 1b8585e6f6..6634e5248a 100644
--- a/server/src/com/vaadin/ui/declarative/Design.java
+++ b/server/src/com/vaadin/ui/declarative/Design.java
@@ -33,6 +33,7 @@ import org.jsoup.parser.Parser;
import org.jsoup.select.Elements;
import com.vaadin.annotations.DesignRoot;
+import com.vaadin.shared.util.SharedUtil;
import com.vaadin.ui.Component;
import com.vaadin.ui.declarative.DesignContext.ComponentCreatedEvent;
import com.vaadin.ui.declarative.DesignContext.ComponentCreationListener;
@@ -68,7 +69,6 @@ public class Design implements Serializable {
* Use {@link Design#setComponentFactory(ComponentFactory)} to configure
* Vaadin to use a custom component factory.
*
- *
* @since 7.4.1
*/
public interface ComponentFactory extends Serializable {
@@ -88,6 +88,50 @@ public class Design implements Serializable {
}
/**
+ * Delegate for handling the mapping between tag names and component
+ * instances.
+ * <p>
+ * Use {@link Design#setComponentMapper(ComponentMapper)} to configure
+ * Vaadin to use a custom component mapper.
+ *
+ * @since
+ * @author Vaadin Ltd
+ */
+ public interface ComponentMapper extends Serializable {
+ /**
+ * Resolves and creates a component using the provided component factory
+ * based on a tag name.
+ * <p>
+ * This method should be in sync with
+ * {@link #componentToTag(Component, DesignContext)} so that the
+ * resolved tag for a created component is the same as the tag for which
+ * the component was created.
+ *
+ * @param tag
+ * the tag name to create a component for
+ * @param componentFactory
+ * the component factory that actually creates a component
+ * based on a fully qualified class name
+ * @param context
+ * the design context for which the component is created
+ * @return a newly created component
+ */
+ public Component tagToComponent(String tag,
+ ComponentFactory componentFactory, DesignContext context);
+
+ /**
+ * Resolves a tag name from a component.
+ *
+ * @param component
+ * the component to get a tag name for
+ * @param context
+ * the design context for which the tag name is needed
+ * @return the tag name corresponding to the component
+ */
+ public String componentToTag(Component component, DesignContext context);
+ }
+
+ /**
* Default implementation of {@link ComponentFactory}, using
* <code>Class.forName(className).newInstance()</code> for finding the
* component class and creating a component instance.
@@ -135,7 +179,100 @@ public class Design implements Serializable {
}
+ /**
+ * Default implementation of {@link ComponentMapper},
+ *
+ * @since
+ */
+ public static class DefaultComponentMapper implements ComponentMapper {
+
+ @Override
+ public Component tagToComponent(String tagName,
+ ComponentFactory componentFactory, DesignContext context) {
+ // Extract the package and class names.
+ // Otherwise, get the full class name using the prefix to package
+ // mapping. Example: "v-vertical-layout" ->
+ // "com.vaadin.ui.VerticalLayout"
+ String[] parts = tagName.split("-", 2);
+ if (parts.length < 2) {
+ throw new DesignException("The tagname '" + tagName
+ + "' is invalid: missing prefix.");
+ }
+ String prefixName = parts[0];
+ String packageName = context.getPackage(prefixName);
+ if (packageName == null) {
+ throw new DesignException("Unknown tag: " + tagName);
+ }
+ String[] classNameParts = parts[1].split("-");
+ String className = "";
+ for (String classNamePart : classNameParts) {
+ // Split will ignore trailing and multiple dashes but that
+ // should be
+ // ok
+ // <v-button--> will be resolved to <v-button>
+ // <v--button> will be resolved to <v-button>
+ className += SharedUtil.capitalize(classNamePart);
+ }
+ String qualifiedClassName = packageName + "." + className;
+
+ Component component = componentFactory.createComponent(
+ qualifiedClassName, context);
+
+ if (component == null) {
+ throw new DesignException("Got unexpected null component from "
+ + componentFactory.getClass().getName() + " for class "
+ + qualifiedClassName);
+ }
+
+ return component;
+ }
+
+ @Override
+ public String componentToTag(Component component, DesignContext context) {
+ Class<?> componentClass = component.getClass();
+ String packageName = componentClass.getPackage().getName();
+ String prefix = context.getPackagePrefix(packageName);
+ if (prefix == null) {
+ prefix = packageName.replace('.', '_');
+ context.addPackagePrefix(prefix, packageName);
+ }
+ prefix = prefix + "-";
+ String className = classNameToElementName(componentClass
+ .getSimpleName());
+ String tagName = prefix + className;
+
+ return tagName;
+ }
+
+ /**
+ * Creates the name of the html tag corresponding to the given class
+ * name. The name is derived by converting each uppercase letter to
+ * lowercase and inserting a dash before the letter. No dash is inserted
+ * before the first letter of the class name.
+ *
+ * @param className
+ * the name of the class without a package name
+ * @return the html tag name corresponding to className
+ */
+ private String classNameToElementName(String className) {
+ StringBuilder result = new StringBuilder();
+ for (int i = 0; i < className.length(); i++) {
+ Character c = className.charAt(i);
+ if (Character.isUpperCase(c)) {
+ if (i > 0) {
+ result.append("-");
+ }
+ result.append(Character.toLowerCase(c));
+ } else {
+ result.append(c);
+ }
+ }
+ return result.toString();
+ }
+ }
+
private static volatile ComponentFactory componentFactory = new DefaultComponentFactory();
+ private static volatile ComponentMapper componentMapper = new DefaultComponentMapper();
/**
* Sets the component factory that is used for creating component instances
@@ -171,6 +308,39 @@ public class Design implements Serializable {
}
/**
+ * Sets the component mapper that is used for resolving between tag names
+ * and component instances.
+ * <p>
+ * Please note that this setting is global, so care should be taken to avoid
+ * conflicting changes.
+ *
+ * @param componentMapper
+ * the component mapper to set; not <code>null</code>
+ *
+ * @since
+ */
+ public static void setComponentMapper(ComponentMapper componentMapper) {
+ if (componentMapper == null) {
+ throw new IllegalArgumentException(
+ "Cannot set null component mapper");
+ }
+ Design.componentMapper = componentMapper;
+ }
+
+ /**
+ * Gets the currently used component mapper.
+ *
+ * @see #setComponentMapper(ComponentMapper)
+ *
+ * @return the component mapper
+ *
+ * @since
+ */
+ public static ComponentMapper getComponentMapper() {
+ return componentMapper;
+ }
+
+ /**
* Parses the given input stream into a jsoup document
*
* @param html
diff --git a/server/src/com/vaadin/ui/declarative/DesignAttributeHandler.java b/server/src/com/vaadin/ui/declarative/DesignAttributeHandler.java
index 215afd5041..2b446bda0e 100644
--- a/server/src/com/vaadin/ui/declarative/DesignAttributeHandler.java
+++ b/server/src/com/vaadin/ui/declarative/DesignAttributeHandler.java
@@ -38,7 +38,6 @@ import org.jsoup.nodes.Node;
import com.vaadin.data.util.converter.Converter;
import com.vaadin.shared.util.SharedUtil;
-import com.vaadin.ui.Component;
/**
* Default attribute handler implementation used when parsing designs to
@@ -192,8 +191,8 @@ public class DesignAttributeHandler implements Serializable {
* @param defaultInstance
* the default instance for comparing default values
*/
- public static void writeAttribute(Component component, String attribute,
- Attributes attr, Component defaultInstance) {
+ public static void writeAttribute(Object component, String attribute,
+ Attributes attr, Object defaultInstance) {
Method getter = findGetterForAttribute(component.getClass(), attribute);
if (getter == null) {
getLogger().warning(
diff --git a/server/src/com/vaadin/ui/declarative/DesignContext.java b/server/src/com/vaadin/ui/declarative/DesignContext.java
index 218774c72d..f991b3013a 100644
--- a/server/src/com/vaadin/ui/declarative/DesignContext.java
+++ b/server/src/com/vaadin/ui/declarative/DesignContext.java
@@ -17,6 +17,8 @@ package com.vaadin.ui.declarative;
import java.io.Serializable;
import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -28,10 +30,10 @@ import org.jsoup.nodes.Element;
import org.jsoup.nodes.Node;
import com.vaadin.annotations.DesignRoot;
-import com.vaadin.shared.util.SharedUtil;
import com.vaadin.ui.Component;
import com.vaadin.ui.HasComponents;
import com.vaadin.ui.declarative.Design.ComponentFactory;
+import com.vaadin.ui.declarative.Design.ComponentMapper;
/**
* This class contains contextual information that is collected when a component
@@ -79,7 +81,7 @@ public class DesignContext implements Serializable {
defaultPrefixes.put("v", "com.vaadin.ui");
for (String prefix : defaultPrefixes.keySet()) {
String packageName = defaultPrefixes.get(prefix);
- mapPrefixToPackage(prefix, packageName);
+ addPackagePrefix(prefix, packageName);
}
}
@@ -236,20 +238,65 @@ public class DesignContext implements Serializable {
}
/**
- * Creates a two-way mapping between a prefix and a package name. Return
- * true if prefix was already mapped to some package name or packageName to
- * some prefix.
+ * Creates a two-way mapping between a prefix and a package name.
*
* @param prefix
* the prefix name without an ending dash (for instance, "v" is
- * always used for "com.vaadin.ui")
+ * by default used for "com.vaadin.ui")
* @param packageName
* the name of the package corresponding to prefix
- * @return whether there was a mapping from prefix to some package name or
- * from packageName to some prefix.
+ *
+ * @see #getPackagePrefixes()
+ * @see #getPackagePrefix(String)
+ * @see #getPackage(String)
+ * @since
+ */
+ public void addPackagePrefix(String prefix, String packageName) {
+ twoWayMap(prefix, packageName, prefixToPackage, packageToPrefix);
+ }
+
+ /**
+ * Gets the prefix mapping for a given package, or <code>null</code> if
+ * there is no mapping for the package.
+ *
+ * @see #addPackagePrefix(String, String)
+ * @see #getPackagePrefixes()
+ *
+ * @since
+ * @param packageName
+ * the package name to get a prefix for
+ * @return the prefix for the package, or <code>null</code> if no prefix is
+ * registered
+ */
+ public String getPackagePrefix(String packageName) {
+ return packageToPrefix.get(packageName);
+ }
+
+ /**
+ * Gets all registered package prefixes.
+ *
+ *
+ * @since
+ * @see #getPackage(String)
+ * @return a collection of package prefixes
*/
- private boolean mapPrefixToPackage(String prefix, String packageName) {
- return twoWayMap(prefix, packageName, prefixToPackage, packageToPrefix);
+ public Collection<String> getPackagePrefixes() {
+ return Collections.unmodifiableCollection(prefixToPackage.keySet());
+ }
+
+ /**
+ * Gets the package corresponding to the give prefix, or <code>null</code>
+ * no package has been registered for the prefix
+ *
+ * @since
+ * @see #addPackagePrefix(String, String)
+ * @param prefix
+ * the prefix to find a package for
+ * @return the package prefix, or <code>null</code> if no package is
+ * registered for the provided prefix
+ */
+ public String getPackage(String prefix) {
+ return prefixToPackage.get(prefix);
}
/**
@@ -309,8 +356,7 @@ public class DesignContext implements Serializable {
}
String prefixName = parts[0];
String packageName = parts[1];
- twoWayMap(prefixName, packageName, prefixToPackage,
- packageToPrefix);
+ addPackagePrefix(prefixName, packageName);
}
}
}
@@ -328,14 +374,13 @@ public class DesignContext implements Serializable {
*/
public void writePackageMappings(Document doc) {
Element head = doc.head();
- for (String prefix : prefixToPackage.keySet()) {
+ for (String prefix : getPackagePrefixes()) {
// Only store the prefix-name mapping if it is not a default mapping
// (such as "v" -> "com.vaadin.ui")
if (defaultPrefixes.get(prefix) == null) {
Node newNode = doc.createElement("meta");
newNode.attr("name", "package-mapping");
- String prefixToPackageName = prefix + ":"
- + prefixToPackage.get(prefix);
+ String prefixToPackageName = prefix + ":" + getPackage(prefix);
newNode.attr("content", prefixToPackageName);
head.appendChild(newNode);
}
@@ -355,17 +400,11 @@ public class DesignContext implements Serializable {
* childComponent.
*/
public Element createElement(Component childComponent) {
- Class<?> componentClass = childComponent.getClass();
- String packageName = componentClass.getPackage().getName();
- String prefix = packageToPrefix.get(packageName);
- if (prefix == null) {
- prefix = packageName.replace('.', '_');
- twoWayMap(prefix, packageName, prefixToPackage, packageToPrefix);
- }
- prefix = prefix + "-";
- String className = classNameToElementName(componentClass
- .getSimpleName());
- Element newElement = doc.createElement(prefix + className);
+ ComponentMapper componentMapper = Design.getComponentMapper();
+
+ String tagName = componentMapper.componentToTag(childComponent, this);
+
+ Element newElement = doc.createElement(tagName);
childComponent.writeDesign(newElement, this);
// Handle the local id. Global id and caption should have been taken
// care of by writeDesign.
@@ -377,32 +416,6 @@ public class DesignContext implements Serializable {
}
/**
- * Creates the name of the html tag corresponding to the given class name.
- * The name is derived by converting each uppercase letter to lowercase and
- * inserting a dash before the letter. No dash is inserted before the first
- * letter of the class name.
- *
- * @param className
- * the name of the class without a package name
- * @return the html tag name corresponding to className
- */
- private String classNameToElementName(String className) {
- StringBuilder result = new StringBuilder();
- for (int i = 0; i < className.length(); i++) {
- Character c = className.charAt(i);
- if (Character.isUpperCase(c)) {
- if (i > 0) {
- result.append("-");
- }
- result.append(Character.toLowerCase(c));
- } else {
- result.append(c);
- }
- }
- return result.toString();
- }
-
- /**
* Reads the given design node and creates the corresponding component tree
*
* @param componentDesign
@@ -473,15 +486,22 @@ public class DesignContext implements Serializable {
* @return a Component corresponding to node, with no attributes set.
*/
private Component instantiateComponent(Node node) {
- // Extract the package and class names.
- String qualifiedClassName = tagNameToClassName(node);
+ String tag = node.nodeName();
+
+ ComponentMapper componentMapper = Design.getComponentMapper();
+ Component component = componentMapper.tagToComponent(tag,
+ Design.getComponentFactory(), this);
- return instantiateClass(qualifiedClassName);
+ assert tag.equals(componentMapper.componentToTag(component, this));
+
+ return component;
}
/**
* Instantiates given class via ComponentFactory.
- * @param qualifiedClassName class name to instantiate
+ *
+ * @param qualifiedClassName
+ * class name to instantiate
* @return instance of a given class
*/
private Component instantiateClass(String qualifiedClassName) {
@@ -498,44 +518,6 @@ public class DesignContext implements Serializable {
}
/**
- * Returns the qualified class name corresponding to the given html tree
- * node. The class name is extracted from the tag name of node.
- *
- * @param node
- * an html tree node
- * @return The qualified class name corresponding to the given node.
- */
- private String tagNameToClassName(Node node) {
- String tagName = node.nodeName();
- if (tagName.equals("v-addon")) {
- return node.attr("class");
- }
- // Otherwise, get the full class name using the prefix to package
- // mapping. Example: "v-vertical-layout" ->
- // "com.vaadin.ui.VerticalLayout"
- String[] parts = tagName.split("-", 2);
- if (parts.length < 2) {
- throw new DesignException("The tagname '" + tagName
- + "' is invalid: missing prefix.");
- }
- String prefixName = parts[0];
- String packageName = prefixToPackage.get(prefixName);
- if (packageName == null) {
- throw new DesignException("Unknown tag: " + tagName);
- }
- String[] classNameParts = parts[1].split("-");
- String className = "";
- for (String classNamePart : classNameParts) {
- // Split will ignore trailing and multiple dashes but that should be
- // ok
- // <v-button--> will be resolved to <v-button>
- // <v--button> will be resolved to <v-button>
- className += SharedUtil.capitalize(classNamePart);
- }
- return packageName + "." + className;
- }
-
- /**
* Returns the root component of a created component hierarchy.
*
* @return the root component of the hierarchy
diff --git a/server/src/com/vaadin/ui/declarative/converters/DesignResourceConverter.java b/server/src/com/vaadin/ui/declarative/converters/DesignResourceConverter.java
index 70e46b8e7f..21f20e6403 100644
--- a/server/src/com/vaadin/ui/declarative/converters/DesignResourceConverter.java
+++ b/server/src/com/vaadin/ui/declarative/converters/DesignResourceConverter.java
@@ -39,7 +39,8 @@ public class DesignResourceConverter implements Converter<String, Resource> {
public Resource convertToModel(String value,
Class<? extends Resource> targetType, Locale locale)
throws Converter.ConversionException {
- if (value.startsWith("http://")) {
+ if (value.startsWith("http://") || value.startsWith("https://")
+ || value.startsWith("ftp://") || value.startsWith("ftps://")) {
return new ExternalResource(value);
} else if (value.startsWith("theme://")) {
return new ThemeResource(value.substring(8));
diff --git a/server/tests/src/com/vaadin/server/AbstractDeploymentConfigurationTest.java b/server/tests/src/com/vaadin/server/AbstractDeploymentConfigurationTest.java
index ccdbfea150..0518bea650 100644
--- a/server/tests/src/com/vaadin/server/AbstractDeploymentConfigurationTest.java
+++ b/server/tests/src/com/vaadin/server/AbstractDeploymentConfigurationTest.java
@@ -158,9 +158,5 @@ public class AbstractDeploymentConfigurationTest {
return DefaultDeploymentConfiguration.DEFAULT_SEND_URLS_AS_PARAMETERS;
}
- @Override
- public String getPushPath() {
- return null;
- }
}
}
diff --git a/server/tests/src/com/vaadin/tests/components/draganddropwrapper/DragAndDropWrapperDeclarativeTest.java b/server/tests/src/com/vaadin/tests/components/draganddropwrapper/DragAndDropWrapperDeclarativeTest.java
new file mode 100644
index 0000000000..735216c474
--- /dev/null
+++ b/server/tests/src/com/vaadin/tests/components/draganddropwrapper/DragAndDropWrapperDeclarativeTest.java
@@ -0,0 +1,66 @@
+/*
+ * 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.draganddropwrapper;
+
+import org.junit.Test;
+
+import com.vaadin.tests.design.DeclarativeTestBase;
+import com.vaadin.ui.Button;
+import com.vaadin.ui.DragAndDropWrapper;
+import com.vaadin.ui.DragAndDropWrapper.DragStartMode;
+import com.vaadin.ui.declarative.DesignContext;
+
+public class DragAndDropWrapperDeclarativeTest extends
+ DeclarativeTestBase<DragAndDropWrapper> {
+
+ @Test
+ public void testDefaultDnDWrapper() {
+ Button okButton = new Button("OK");
+ String input = "<v-drag-and-drop-wrapper>"
+ + new DesignContext().createElement(okButton)
+ + "</v-drag-and-drop-wrapper>";
+ DragAndDropWrapper wrapper = new DragAndDropWrapper(okButton);
+ testWrite(input, wrapper);
+ testRead(input, wrapper);
+ }
+
+ @Test
+ public void testNoDragImage() {
+ Button okButton = new Button("OK");
+ String input = "<v-drag-and-drop-wrapper drag-start-mode='wrapper'>"
+ + new DesignContext().createElement(okButton)
+ + "</v-drag-and-drop-wrapper>";
+ DragAndDropWrapper wrapper = new DragAndDropWrapper(okButton);
+ wrapper.setDragStartMode(DragStartMode.WRAPPER);
+ testWrite(input, wrapper);
+ testRead(input, wrapper);
+ }
+
+ @Test
+ public void testWithDragImage() {
+ Button dragImage = new Button("Cancel");
+ Button okButton = new Button("OK");
+ String input = "<v-drag-and-drop-wrapper drag-start-mode='component_other'>"
+ + new DesignContext().createElement(okButton)
+ + new DesignContext().createElement(dragImage).attr(
+ ":drag-image", "") + "</v-drag-and-drop-wrapper>";
+ DragAndDropWrapper wrapper = new DragAndDropWrapper(okButton);
+ wrapper.setDragStartMode(DragStartMode.COMPONENT_OTHER);
+ wrapper.setDragImageComponent(dragImage);
+ testWrite(input, wrapper);
+ testRead(input, wrapper);
+ }
+}
diff --git a/server/tests/src/com/vaadin/tests/components/menubar/MenuBarDeclarativeTest.java b/server/tests/src/com/vaadin/tests/components/menubar/MenuBarDeclarativeTest.java
new file mode 100644
index 0000000000..e6dee44812
--- /dev/null
+++ b/server/tests/src/com/vaadin/tests/components/menubar/MenuBarDeclarativeTest.java
@@ -0,0 +1,139 @@
+/*
+ * 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.menubar;
+
+import java.io.IOException;
+
+import org.junit.Test;
+
+import com.vaadin.server.ExternalResource;
+import com.vaadin.server.ThemeResource;
+import com.vaadin.tests.design.DeclarativeTestBase;
+import com.vaadin.ui.MenuBar;
+import com.vaadin.ui.MenuBar.MenuItem;
+
+/**
+ * Tests declarative support for menu bars.
+ *
+ * @since 7.4
+ * @author Vaadin Ltd
+ */
+public class MenuBarDeclarativeTest extends DeclarativeTestBase<MenuBar> {
+
+ @Test
+ // #16328
+ public void testReadWrite() throws IOException {
+ String design = "<v-menu-bar auto-open='true' tabindex=5>"
+ + "<menu checkable='true'>Save</menu>"
+ + "<menu description='Open a file'>Open</menu>"
+ + "<menu disabled='true'>Close</menu>"
+ + "<menu icon='http://foo.bar/ico.png'>Help</menu>"
+ + "<menu visible='false'>About</menu>"
+ + "<menu>Sub<menu>Item</menu></menu>"
+ + "<menu more>WTF?!</menu>" + "</v-menu-bar>";
+ MenuBar bar = new MenuBar();
+ bar.setAutoOpen(true);
+ bar.setHtmlContentAllowed(true);
+ bar.setTabIndex(5);
+
+ bar.addItem("Save", null).setCheckable(true);
+ bar.addItem("Open", null).setDescription("Open a file");
+ bar.addItem("Close", null).setEnabled(false);
+ bar.addItem("Help", null).setIcon(
+ new ExternalResource("http://foo.bar/ico.png"));
+ bar.addItem("About", null).setVisible(false);
+
+ bar.addItem("Sub", null).addItem("Item", null);
+
+ bar.setMoreMenuItem(bar.new MenuItem("WTF?!", null, null));
+
+ testWrite(design, bar);
+ testRead(design, bar);
+ }
+
+ @Test
+ // #16328
+ public void testTicketSpec1() throws IOException {
+ String design = "<v-menu-bar auto-open='true' plain-text tabindex=5> "
+ + "<menu>File"
+ + "<menu>Save</menu>"
+ + "<menu icon=\"theme://../runo/icons/16/folder.png\">Open</menu>"
+ + "<menu separator='true' />"
+ + "<menu disabled='true'>Exit</menu>"
+ + "<menu visible='false'>Not for everybody</menu>"
+ + "</menu>"
+ + "<menu description=\"This contains many items in sub menus\">Other"
+ + "<menu style-name=\"fancy\">Sub"
+ + "<menu checkable='true' checked='true'>Option 1 - no <b>html</b></menu>"
+ + "<menu checkable='true'>Option 2</menu>"
+ + "<menu checkable='true'>Option 3</menu>" //
+ + "</menu>" //
+ + "</menu>" //
+ + "<menu more icon=\"theme://icon.png\">foo</menu>"
+ + "</v-menu-bar>";
+ // for one reason or another, no component has a correct .equals
+ // implementation, which makes tests a bit annoying
+ MenuBar menuBar = new MenuBar();
+ menuBar.setHtmlContentAllowed(false);
+ menuBar.setTabIndex(5);
+ menuBar.setAutoOpen(true);
+ // File menu
+ MenuItem fileMenu = menuBar.addItem("File", null);
+ fileMenu.addItem("Save", null);
+ fileMenu.addItem("Open", new ThemeResource(
+ "../runo/icons/16/folder.png"), null);
+ fileMenu.addSeparator();
+ fileMenu.addItem("Exit", null).setEnabled(false);
+ fileMenu.addItem("Not for everybody", null).setVisible(false);
+ MenuItem otherMenu = menuBar.addItem("Other", null);
+ otherMenu.setDescription("This contains many items in sub menus");
+ MenuItem subMenu = otherMenu.addItem("Sub", null);
+ subMenu.setStyleName("fancy");
+ MenuItem option1 = subMenu.addItem("Option 1 - no <b>html</b>", null);
+ option1.setCheckable(true);
+ option1.setChecked(true);
+ subMenu.addItem("Option 2", null).setCheckable(true);
+ subMenu.addItem("Option 3", null).setCheckable(true);
+ menuBar.setMoreMenuItem(null);
+ MenuItem moreMenu = menuBar.getMoreMenuItem();
+ moreMenu.setIcon(new ThemeResource("icon.png"));
+ moreMenu.setText("foo");
+ testRead(design, menuBar);
+ testWrite(design, menuBar);
+ }
+
+ @Test
+ // #16328
+ public void testTicketSpec2() throws IOException {
+ String design = "<v-menu-bar>"
+ + "<menu><b>File</b>"
+ + "<menu><font style=\"color: red\">Save</font></menu>"
+ + "<menu icon=\"theme://../runo/icons/16/folder.png\">Open</menu>"
+ + "<menu separator='true' />"
+ + "<menu disabled='true'>Exit</menu>" //
+ + "</menu></v-menu-bar>";
+ MenuBar menuBar = new MenuBar();
+ menuBar.setHtmlContentAllowed(true);
+ MenuItem fileMenu = menuBar.addItem("<b>File</b>", null);
+ fileMenu.addItem("<font style='color: red'>Save</font>", null);
+ fileMenu.addItem("Open", new ThemeResource(
+ "../runo/icons/16/folder.png"), null);
+ fileMenu.addSeparator();
+ fileMenu.addItem("Exit", null).setEnabled(false);
+ testRead(design, menuBar);
+ testWrite(design, menuBar);
+ }
+} \ No newline at end of file
diff --git a/server/tests/src/com/vaadin/tests/design/ComponentMapperTest.java b/server/tests/src/com/vaadin/tests/design/ComponentMapperTest.java
new file mode 100644
index 0000000000..c6e8c15109
--- /dev/null
+++ b/server/tests/src/com/vaadin/tests/design/ComponentMapperTest.java
@@ -0,0 +1,129 @@
+/*
+ * 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.design;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.vaadin.ui.Component;
+import com.vaadin.ui.Label;
+import com.vaadin.ui.declarative.Design;
+import com.vaadin.ui.declarative.Design.ComponentFactory;
+import com.vaadin.ui.declarative.Design.ComponentMapper;
+import com.vaadin.ui.declarative.DesignContext;
+
+public class ComponentMapperTest {
+ private static final ComponentMapper defaultMapper = Design
+ .getComponentMapper();
+
+ private static final ThreadLocal<ComponentMapper> currentMapper = new ThreadLocal<ComponentMapper>();
+
+ static {
+ Design.setComponentMapper(new ComponentMapper() {
+ @Override
+ public Component tagToComponent(String tag,
+ ComponentFactory componentFactory, DesignContext context) {
+ return getActualMapper().tagToComponent(tag, componentFactory,
+ context);
+ }
+
+ @Override
+ public String componentToTag(Component component,
+ DesignContext context) {
+ return getActualMapper().componentToTag(component, context);
+ }
+
+ private ComponentMapper getActualMapper() {
+ ComponentMapper mapper = currentMapper.get();
+ if (mapper == null) {
+ mapper = defaultMapper;
+ }
+ return mapper;
+ }
+ });
+ }
+
+ private final class CustomComponentMapper extends
+ Design.DefaultComponentMapper {
+ @Override
+ public Component tagToComponent(String tag,
+ ComponentFactory componentFactory, DesignContext context) {
+ if (tag.startsWith("custom-")) {
+ ComponentWithCustomTagName component = (ComponentWithCustomTagName) componentFactory
+ .createComponent(
+ ComponentWithCustomTagName.class.getName(),
+ context);
+ component.tagName = tag;
+ return component;
+ } else {
+ return super.tagToComponent(tag, componentFactory, context);
+ }
+ }
+
+ @Override
+ public String componentToTag(Component component, DesignContext context) {
+ if (component instanceof ComponentWithCustomTagName) {
+ ComponentWithCustomTagName withCustomTagName = (ComponentWithCustomTagName) component;
+ return withCustomTagName.tagName;
+ } else {
+ return super.componentToTag(component, context);
+ }
+ }
+ }
+
+ public static class ComponentWithCustomTagName extends Label {
+ private String tagName;
+ }
+
+ @Test
+ public void testCustomComponentMapperRead() {
+ currentMapper.set(new CustomComponentMapper());
+
+ Component component = Design.read(new ByteArrayInputStream(
+ "<custom-foobar />".getBytes()));
+
+ Assert.assertTrue("<custom-foobar> should resolve "
+ + ComponentWithCustomTagName.class.getSimpleName(),
+ component instanceof ComponentWithCustomTagName);
+ Assert.assertEquals("custom-foobar",
+ ((ComponentWithCustomTagName) component).tagName);
+ }
+
+ @Test
+ public void testCustomComponentMapperWrite() throws IOException {
+ currentMapper.set(new CustomComponentMapper());
+
+ ComponentWithCustomTagName component = new ComponentWithCustomTagName();
+ component.tagName = "custom-special";
+
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ Design.write(component, bos);
+ String writtenDesign = new String(bos.toByteArray());
+
+ Assert.assertTrue(
+ "Written design should contain \"<custom-special\", but instead got "
+ + writtenDesign,
+ writtenDesign.contains("<custom-special"));
+ }
+
+ public void cleanup() {
+ currentMapper.remove();
+ }
+}
diff --git a/server/tests/src/com/vaadin/tests/server/component/audio/AudioDeclarativeTest.java b/server/tests/src/com/vaadin/tests/server/component/audio/AudioDeclarativeTest.java
new file mode 100644
index 0000000000..4390499c4e
--- /dev/null
+++ b/server/tests/src/com/vaadin/tests/server/component/audio/AudioDeclarativeTest.java
@@ -0,0 +1,63 @@
+/*
+ * 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.server.component.audio;
+
+import java.io.File;
+
+import org.junit.Test;
+
+import com.vaadin.server.ExternalResource;
+import com.vaadin.server.FileResource;
+import com.vaadin.tests.design.DeclarativeTestBase;
+import com.vaadin.ui.Audio;
+
+/**
+ * Tests specs of declarative support for abstract media and its
+ * implementations.
+ *
+ * @since 7.4
+ * @author Vaadin Ltd
+ */
+public class AudioDeclarativeTest extends DeclarativeTestBase<Audio> {
+
+ @Test
+ public void testEmptyAudio() {
+ String design = "<v-audio />";
+ Audio audio = new Audio();
+ testRead(design, audio);
+ testWrite(design, audio);
+ }
+
+ @Test
+ public void testAudioMultipleSources() {
+ String design = "<v-audio muted='true' show-controls='false'>"
+ + "some <b>text</b>" //
+ + "<source href='http://foo.pl' />"
+ + "<source href='https://bar.pl' />" //
+ + "<source href='ohai' />" //
+ + "</v-audio>";
+ Audio audio = new Audio();
+ audio.setAltText("some <b>text</b>");
+ audio.setAutoplay(false);
+ audio.setMuted(true);
+ audio.setShowControls(false);
+ audio.setSources(new ExternalResource("http://foo.pl"),
+ new ExternalResource("https://bar.pl"), new FileResource(
+ new File("ohai")));
+ testRead(design, audio);
+ testWrite(design, audio);
+ }
+}
diff --git a/server/tests/src/com/vaadin/tests/server/component/audio/VideoDeclarativeTest.java b/server/tests/src/com/vaadin/tests/server/component/audio/VideoDeclarativeTest.java
new file mode 100644
index 0000000000..fc0b3d9512
--- /dev/null
+++ b/server/tests/src/com/vaadin/tests/server/component/audio/VideoDeclarativeTest.java
@@ -0,0 +1,59 @@
+/*
+ * 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.server.component.audio;
+
+import java.io.File;
+
+import org.junit.Test;
+
+import com.vaadin.server.ExternalResource;
+import com.vaadin.server.FileResource;
+import com.vaadin.tests.design.DeclarativeTestBase;
+import com.vaadin.ui.Video;
+
+public class VideoDeclarativeTest extends DeclarativeTestBase<Video> {
+
+ @Test
+ public void testEmptyVideo() {
+ String design = "<v-video />";
+ Video audio = new Video();
+ testRead(design, audio);
+ testWrite(design, audio);
+ }
+
+ @Test
+ public void testVideoMultipleSources() {
+ String design = "<v-video muted='true' show-controls='false'>"
+ + "some <b>text</b>" //
+ + "<source href='http://foo.pl' />"
+ + "<source href='https://bar.pl' />" //
+ + "<source href='ohai' />" //
+ + "<poster href='http://foo.pl/poster' />" //
+ + "</v-video>";
+ Video video = new Video();
+ video.setAltText("some <b>text</b>");
+ video.setAutoplay(false);
+ video.setMuted(true);
+ video.setShowControls(false);
+ video.setSources(new ExternalResource("http://foo.pl"),
+ new ExternalResource("https://bar.pl"), new FileResource(
+ new File("ohai")));
+ video.setPoster(new ExternalResource("http://foo.pl/poster"));
+ testRead(design, video);
+ testWrite(design, video);
+ }
+
+}
diff --git a/server/tests/src/com/vaadin/tests/server/component/calendar/CalendarDeclarativeTest.java b/server/tests/src/com/vaadin/tests/server/component/calendar/CalendarDeclarativeTest.java
new file mode 100644
index 0000000000..d866878fc7
--- /dev/null
+++ b/server/tests/src/com/vaadin/tests/server/component/calendar/CalendarDeclarativeTest.java
@@ -0,0 +1,61 @@
+/*
+ * 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.server.component.calendar;
+
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.TimeZone;
+
+import org.junit.Test;
+
+import com.vaadin.tests.design.DeclarativeTestBase;
+import com.vaadin.ui.Calendar;
+import com.vaadin.ui.Calendar.TimeFormat;
+
+public class CalendarDeclarativeTest extends DeclarativeTestBase<Calendar> {
+
+ @Test
+ public void testEmpty() {
+ verifyDeclarativeDesign("<v-calendar></v-calendar>", new Calendar());
+ }
+
+ @Test
+ public void testCalendarAllFeatures() throws ParseException {
+ String design = "<v-calendar start-date='2014-11-17' end-date='2014-11-23' "
+ + "first-visible-day-of-week=2 last-visible-day-of-week=5 "
+ + "time-zone='EST' time-format='12h' first-visible-hour-of-day=8 "
+ + "last-visible-hour-of-day=18 weekly-caption-format='mmm MM/dd' />";
+
+ DateFormat format = new SimpleDateFormat("yyyy-MM-dd");
+ Calendar calendar = new Calendar();
+ calendar.setStartDate(format.parse("2014-11-17"));
+ calendar.setEndDate(format.parse("2014-11-23"));
+ calendar.setFirstVisibleDayOfWeek(2);
+ calendar.setLastVisibleDayOfWeek(5);
+ calendar.setTimeZone(TimeZone.getTimeZone("EST"));
+ calendar.setTimeFormat(TimeFormat.Format12H);
+ calendar.setFirstVisibleHourOfDay(8);
+ calendar.setLastVisibleHourOfDay(18);
+ calendar.setWeeklyCaptionFormat("mmm MM/dd");
+ verifyDeclarativeDesign(design, calendar);
+ }
+
+ protected void verifyDeclarativeDesign(String design, Calendar expected) {
+ testRead(design, expected);
+ testWrite(design, expected);
+ }
+}
diff --git a/server/tests/src/com/vaadin/tests/server/component/customlayout/CustomLayoutDeclarativeTest.java b/server/tests/src/com/vaadin/tests/server/component/customlayout/CustomLayoutDeclarativeTest.java
new file mode 100644
index 0000000000..44261a61dc
--- /dev/null
+++ b/server/tests/src/com/vaadin/tests/server/component/customlayout/CustomLayoutDeclarativeTest.java
@@ -0,0 +1,96 @@
+/*
+ * 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.server.component.customlayout;
+
+import org.junit.Test;
+
+import com.vaadin.tests.design.DeclarativeTestBase;
+import com.vaadin.ui.Button;
+import com.vaadin.ui.CustomLayout;
+import com.vaadin.ui.Label;
+
+/**
+ * Tests declarative support for {@link CustomLayout}.
+ *
+ * @since
+ * @author Vaadin Ltd
+ */
+public class CustomLayoutDeclarativeTest extends
+ DeclarativeTestBase<CustomLayout> {
+
+ @Test
+ public void testEmpty() {
+ String design = "<v-custom-layout>";
+ CustomLayout expected = new CustomLayout();
+ test(design, expected);
+ }
+
+ @Test
+ public void testWithChildren() {
+ String design = "<v-custom-layout>" + //
+ "<v-button plain-text :location='b'></v-button>" + //
+ "<v-label plain-text :location='l'></v-label>" + //
+ "</v-custom-layout>";
+
+ CustomLayout expected = new CustomLayout();
+ expected.addComponent(new Button(), "b");
+ expected.addComponent(new Label(), "l");
+
+ test(design, expected);
+ }
+
+ @Test
+ public void testWithOneChild() {
+ String design = "<v-custom-layout><v-button plain-text></v-button></v-custom-layout>";
+
+ CustomLayout expected = new CustomLayout();
+ expected.addComponent(new Button());
+
+ test(design, expected);
+ }
+
+ @Test
+ public void testWithTemplate() {
+ String design = "<v-custom-layout template-name='template.html'></v-custom-layout>";
+ CustomLayout expected = new CustomLayout("template.html");
+ test(design, expected);
+ }
+
+ @Test
+ public void testWithDuplicateLocations() {
+ String design = "<v-custom-layout>" + //
+ "<v-button plain-text :location='foo'></v-button>" + //
+ "<v-label plain-text :location='foo'></v-label>" + //
+ "</v-custom-layout>";
+
+ CustomLayout expected = new CustomLayout();
+ expected.addComponent(new Button(), "foo");
+ expected.addComponent(new Label(), "foo");
+
+ testRead(design, expected);
+
+ String written = "<v-custom-layout>" + //
+ "<v-label plain-text :location='foo'></v-label>" + //
+ "</v-custom-layout>";
+
+ testWrite(written, expected);
+ }
+
+ protected void test(String design, CustomLayout expected) {
+ testRead(design, expected);
+ testWrite(design, expected);
+ }
+}
diff --git a/server/tests/src/com/vaadin/tests/server/component/slider/SliderDeclarativeTest.java b/server/tests/src/com/vaadin/tests/server/component/slider/SliderDeclarativeTest.java
new file mode 100644
index 0000000000..9ef28afb82
--- /dev/null
+++ b/server/tests/src/com/vaadin/tests/server/component/slider/SliderDeclarativeTest.java
@@ -0,0 +1,66 @@
+/*
+ * 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.server.component.slider;
+
+import org.junit.Test;
+
+import com.vaadin.shared.ui.slider.SliderOrientation;
+import com.vaadin.tests.design.DeclarativeTestBase;
+import com.vaadin.ui.Slider;
+
+/**
+ * Tests declarative support for implementations of {@link Slider}.
+ *
+ * @since
+ * @author Vaadin Ltd
+ */
+public class SliderDeclarativeTest extends DeclarativeTestBase<Slider> {
+
+ @Test
+ public void testDefault() {
+ String design = "<v-slider>";
+
+ Slider expected = new Slider();
+
+ testRead(design, expected);
+ testWrite(design, expected);
+ }
+
+ @Test
+ public void testHorizontal() {
+ String design = "<v-slider min=10 max=20 resolution=1 value=12.3>";
+
+ Slider expected = new Slider();
+ expected.setMin(10.0);
+ expected.setMax(20.0);
+ expected.setResolution(1);
+ expected.setValue(12.3);
+
+ testRead(design, expected);
+ testWrite(design, expected);
+ }
+
+ @Test
+ public void testVertical() {
+ String design = "<v-slider vertical>";
+
+ Slider expected = new Slider();
+ expected.setOrientation(SliderOrientation.VERTICAL);
+
+ testRead(design, expected);
+ testWrite(design, expected);
+ }
+}
diff --git a/server/tests/src/com/vaadin/tests/util/MockDeploymentConfiguration.java b/server/tests/src/com/vaadin/tests/util/MockDeploymentConfiguration.java
index 175dcb2b94..ddee23a9ec 100644
--- a/server/tests/src/com/vaadin/tests/util/MockDeploymentConfiguration.java
+++ b/server/tests/src/com/vaadin/tests/util/MockDeploymentConfiguration.java
@@ -22,7 +22,6 @@ public class MockDeploymentConfiguration extends
private LegacyProperyToStringMode legacyPropertyToStringMode = LegacyProperyToStringMode.DISABLED;
private boolean syncIdCheckEnabled = true;
private boolean sendUrlsAsParameters = true;
- private String pushPath = "PUSH";
@Override
public boolean isProductionMode() {
@@ -126,9 +125,4 @@ public class MockDeploymentConfiguration extends
return sendUrlsAsParameters;
}
- @Override
- public String getPushPath() {
- return pushPath;
- }
-
}
diff --git a/server/tests/src/com/vaadin/ui/SplitPositionChangeListenerTest.java b/server/tests/src/com/vaadin/ui/SplitPositionChangeListenerTest.java
new file mode 100644
index 0000000000..02dc412cd9
--- /dev/null
+++ b/server/tests/src/com/vaadin/ui/SplitPositionChangeListenerTest.java
@@ -0,0 +1,44 @@
+/*
+ * 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.ui;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+
+import org.junit.Test;
+
+import com.vaadin.server.Sizeable.Unit;
+import com.vaadin.ui.AbstractSplitPanel.SplitPositionChangeEvent;
+import com.vaadin.ui.AbstractSplitPanel.SplitPositionChangeListener;
+
+/**
+ * Test for {@link SplitPositionChangeListener}
+ *
+ * @author Vaadin Ltd
+ */
+public class SplitPositionChangeListenerTest {
+
+ @Test
+ public void testSplitPositionListenerIsTriggered() throws Exception {
+ final HorizontalSplitPanel splitPanel = new HorizontalSplitPanel();
+ SplitPositionChangeListener splitPositionChangeListener = mock(SplitPositionChangeListener.class);
+ splitPanel.addSplitPositionChangeListener(splitPositionChangeListener);
+ splitPanel.setSplitPosition(50, Unit.PERCENTAGE);
+ verify(splitPositionChangeListener).onSplitPositionChanged(
+ any(SplitPositionChangeEvent.class));
+ }
+}