aboutsummaryrefslogtreecommitdiffstats
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
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
-rw-r--r--WebContent/WEB-INF/web.xml22
-rw-r--r--WebContent/statictestfiles/TableInIframeRowClickScrollJumpTest.html12
-rw-r--r--all/build.xml4
-rw-r--r--bom/build.xml46
-rw-r--r--bom/ivy.xml18
-rw-r--r--bom/vaadin-bom.pom103
-rw-r--r--build.xml2
-rw-r--r--client/src/com/vaadin/client/BrowserInfo.java5
-rw-r--r--client/src/com/vaadin/client/communication/AtmospherePushConnection.java15
-rw-r--r--client/src/com/vaadin/client/connectors/GridConnector.java31
-rw-r--r--client/src/com/vaadin/client/ui/FocusableScrollPanel.java8
-rw-r--r--client/src/com/vaadin/client/ui/VAccordion.java5
-rw-r--r--client/src/com/vaadin/client/ui/VScrollTable.java88
-rw-r--r--client/src/com/vaadin/client/ui/customlayout/CustomLayoutConnector.java22
-rw-r--r--client/src/com/vaadin/client/ui/dd/VDragAndDropManager.java47
-rw-r--r--client/src/com/vaadin/client/widget/grid/selection/MultiSelectionRenderer.java1
-rw-r--r--client/src/com/vaadin/client/widgets/Escalator.java109
-rw-r--r--client/src/com/vaadin/client/widgets/Grid.java32
-rw-r--r--common.xml3
-rw-r--r--ivysettings.xml2
-rw-r--r--pom-template.xml17
-rw-r--r--publish.xml64
-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
-rw-r--r--shared/src/com/vaadin/shared/ApplicationConstants.java12
-rw-r--r--shared/src/com/vaadin/shared/ui/ui/UIState.java1
-rw-r--r--uitest/src/com/vaadin/launcher/ApplicationRunnerServlet.java9
-rw-r--r--uitest/src/com/vaadin/tests/VerifyBrowserVersionTest.java17
-rw-r--r--uitest/src/com/vaadin/tests/components/accordion/AccordionRemoveComponent.java55
-rw-r--r--uitest/src/com/vaadin/tests/components/accordion/AccordionRemoveComponentTest.java (renamed from uitest/src/com/vaadin/tests/push/PushPathTest.java)30
-rw-r--r--uitest/src/com/vaadin/tests/components/customlayout/CustomLayoutWithNullTemplate.java44
-rw-r--r--uitest/src/com/vaadin/tests/components/customlayout/CustomLayoutWithNullTemplateTest.java43
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/GridColumnWidthsWithoutData.java21
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/GridColumnWidthsWithoutDataTest.java34
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/GridEditorMultiselect.java35
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/GridEditorMultiselectTest.java55
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/GridResizeTerror.java45
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/GridSwitchRenderers.java103
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/GridSwitchRenderersTest.java84
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridClientColumnPropertiesTest.java17
-rw-r--r--uitest/src/com/vaadin/tests/components/splitpanel/SplitPositionChange.java87
-rw-r--r--uitest/src/com/vaadin/tests/components/splitpanel/SplitPositionChangeTest.java82
-rw-r--r--uitest/src/com/vaadin/tests/components/table/TableBlurFocus.java153
-rw-r--r--uitest/src/com/vaadin/tests/components/table/TableBlurFocusTest.java64
-rw-r--r--uitest/src/com/vaadin/tests/components/table/TableInIframeRowClickScrollJumpTest.java127
-rw-r--r--uitest/src/com/vaadin/tests/components/table/TableSortingStopsWorkingOnChrome.java150
-rw-r--r--uitest/src/com/vaadin/tests/dd/DDInterrupt.java87
-rw-r--r--uitest/src/com/vaadin/tests/dd/DDInterruptTest.java97
-rw-r--r--uitest/src/com/vaadin/tests/dd/SpacebarPanner.java20
-rw-r--r--uitest/src/com/vaadin/tests/declarative/DeclarativeEditor.java4
-rw-r--r--uitest/src/com/vaadin/tests/push/PushPath.java77
-rw-r--r--uitest/src/com/vaadin/tests/util/ResizeTerrorizer.java51
-rw-r--r--uitest/src/com/vaadin/tests/widgetset/client/ResizeTerrorizerControlConnector.java157
-rw-r--r--uitest/src/com/vaadin/tests/widgetset/client/dd/SpacebarPannerConnector.java125
-rw-r--r--uitest/src/com/vaadin/tests/widgetset/rebind/TestWidgetRegistryGenerator.java3
84 files changed, 3728 insertions, 492 deletions
diff --git a/WebContent/WEB-INF/web.xml b/WebContent/WEB-INF/web.xml
index c1102f4682..ef60364202 100644
--- a/WebContent/WEB-INF/web.xml
+++ b/WebContent/WEB-INF/web.xml
@@ -87,9 +87,9 @@
</servlet>
<servlet>
- <!-- This servlet is a separate instance for the sole purpose of testing
- #12446 (com.vaadin.tests.components.ui.TimeoutRedirectResetsOnActivity) because
- it modifies the VaadinService timeout parameters -->
+ <!-- This servlet is a separate instance for the sole purpose of
+ testing #12446 (com.vaadin.tests.components.ui.TimeoutRedirectResetsOnActivity)
+ because it modifies the VaadinService timeout parameters -->
<servlet-name>VaadinApplicationRunnerWithTimeoutRedirect</servlet-name>
<servlet-class>com.vaadin.launcher.ApplicationRunnerServlet</servlet-class>
</servlet>
@@ -115,17 +115,6 @@
<async-supported>true</async-supported>
</servlet>
- <!-- For testing custom push path with, for example, Weblogic 12.1.2 -->
- <servlet>
- <servlet-name>VaadinApplicationRunnerWithPushPathTest</servlet-name>
- <servlet-class>com.vaadin.launcher.ApplicationRunnerServlet</servlet-class>
- <init-param>
- <param-name>pushPath</param-name>
- <param-value>ws</param-value>
- </init-param>
- <async-supported>true</async-supported>
- </servlet>
-
<servlet-mapping>
<servlet-name>Embed App 1</servlet-name>
<url-pattern>/embed1/*</url-pattern>
@@ -160,11 +149,6 @@
</servlet-mapping>
<servlet-mapping>
- <servlet-name>VaadinApplicationRunnerWithPushPathTest</servlet-name>
- <url-pattern>/run-pushpath/*</url-pattern>
- </servlet-mapping>
-
- <servlet-mapping>
<servlet-name>IntegrationTest</servlet-name>
<url-pattern>/integration/*</url-pattern>
</servlet-mapping>
diff --git a/WebContent/statictestfiles/TableInIframeRowClickScrollJumpTest.html b/WebContent/statictestfiles/TableInIframeRowClickScrollJumpTest.html
new file mode 100644
index 0000000000..dfddbdb7e5
--- /dev/null
+++ b/WebContent/statictestfiles/TableInIframeRowClickScrollJumpTest.html
@@ -0,0 +1,12 @@
+<html>
+<head>
+<title>IEJumpTest</title>
+</head>
+<!-- This is for testing Vaadin UI in iFrame (test class TableInIframeRowClickScrollJumpTest, for ticket #15294 -->
+<body>
+ <div style="font-size: 4px">test div</div>
+ <iframe id="test-iframe-0" src="/run/com.vaadin.tests.components.table.TableBlurFocus" width="100%" height="2000px" style="visibility: visible;">
+ </iframe>
+</body>
+
+</html> \ No newline at end of file
diff --git a/all/build.xml b/all/build.xml
index 37f728e529..c3672fc828 100644
--- a/all/build.xml
+++ b/all/build.xml
@@ -50,7 +50,7 @@
</then>
<else>
<!-- Unpack all source files to javadoc.temp.dir -->
- <antcontrib:foreach list="${modules.to.publish.to.maven}"
+ <antcontrib:foreach list="${modules.producing.jar}"
target="unzip.to.javadoctemp" param="module" />
<property name="javadoc.dir" location="${result.dir}/javadoc" />
@@ -88,7 +88,7 @@
<target name="copy-jars">
<delete dir="${temp.dir}" />
- <antcontrib:foreach list="${modules.to.publish.to.maven}"
+ <antcontrib:foreach list="${modules.producing.jar}"
target="fetch.module.and.dependencies" param="module" />
<!-- All jars are now in temp.dir. Still need to separate vaadin
and deps -->
diff --git a/bom/build.xml b/bom/build.xml
new file mode 100644
index 0000000000..42d7303b7b
--- /dev/null
+++ b/bom/build.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0"?>
+
+<project name="vaadin-bom" basedir="." default="publish-local"
+ xmlns:artifact="antlib:org.apache.maven.artifact.ant" xmlns:antcontrib="antlib:net.sf.antcontrib">
+ <description>
+ Compiles a BOM (Bill of Materials) Maven artifact
+ </description>
+ <include file="../common.xml" as="common" />
+ <include file="../build.xml" as="vaadin" />
+
+ <!-- global properties -->
+ <property name="module.name" value="vaadin-bom" />
+ <property name="result.dir" value="result" />
+
+ <target name="bom" description="Generates a BOM (Bill of Materials) pom.xml. Either for a snapshot or a release version">
+ <fail unless="result.dir" message="No result.dir parameter given" />
+ <condition property="vaadin.maven.version" value="${vaadin.version}">
+ <isset property="build.release" />
+ </condition>
+ <!-- if this wasn't already set by the condition, this is a snapshot -->
+ <property name="vaadin.maven.version" value="${vaadin.version.major}.${vaadin.version.minor}-SNAPSHOT" />
+
+ <property name="bom.xml" location="${result.dir}/lib/vaadin-bom-${vaadin.version}.pom" />
+
+ <copy file="vaadin-bom.pom" tofile="${bom.xml}" overwrite="true">
+ <filterchain>
+ <replacestring from="@vaadin.version@" to="${vaadin.maven.version}" />
+ </filterchain>
+ </copy>
+ </target>
+
+ <target name="publish-local" depends="bom">
+ <antcall target="common.publish-local" />
+ </target>
+
+ <target name="clean">
+ <antcall target="common.clean" />
+ </target>
+ <target name="checkstyle">
+ <!-- No code in this module -->
+ </target>
+ <target name="test" depends="checkstyle">
+ <!-- No tests for this BOM.. -->
+ </target>
+
+</project>
diff --git a/bom/ivy.xml b/bom/ivy.xml
new file mode 100644
index 0000000000..39abb30d80
--- /dev/null
+++ b/bom/ivy.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ivy-module version="2.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:noNamespaceSchemaLocation="http://ant.apache.org/ivy/schemas/ivy.xsd"
+ xmlns:m="http://ant.apache.org/ivy/maven">
+
+ <info organisation="com.vaadin" module="vaadin-bom" revision="${vaadin.version}" />
+
+ <configurations>
+ <conf name="build" />
+ </configurations>
+ <publications>
+ <artifact type="pom" ext="pom" />
+ </publications>
+ <dependencies defaultconf="build">
+ </dependencies>
+
+</ivy-module>
diff --git a/bom/vaadin-bom.pom b/bom/vaadin-bom.pom
new file mode 100644
index 0000000000..f2b482ad9b
--- /dev/null
+++ b/bom/vaadin-bom.pom
@@ -0,0 +1,103 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>com.vaadin</groupId>
+ <artifactId>vaadin-parent</artifactId>
+ <version>1.0.0</version>
+ </parent>
+ <groupId>com.vaadin</groupId>
+ <artifactId>vaadin-bom</artifactId>
+ <version>@vaadin.version@</version>
+ <packaging>pom</packaging>
+ <name>Vaadin Framework (Bill of Materials)</name>
+ <description>Vaadin Framework (Bill of Materials)</description>
+ <organization>
+ <name>Vaadin Ltd</name>
+ <url>http://vaadin.com</url>
+ </organization>
+ <url>http://vaadin.com</url>
+ <licenses>
+ <license>
+ <name>Apache License Version 2.0</name>
+ <distribution>repo</distribution>
+ <url>http://www.apache.org/licenses/LICENSE-2.0</url>
+ </license>
+ </licenses>
+ <scm>
+ <connection>scm:https:https://github.com/vaadin/vaadin.git</connection>
+ <developerConnection>scm:https:https://github.com/vaadin/vaadin.git</developerConnection>
+ <url>https://github.com/vaadin/vaadin</url>
+ </scm>
+ <developers>
+ <developer>
+ <id>artur</id>
+ <name>Artur Signell</name>
+ <email>artur.signell@vaadin.com</email>
+ <url>http://vaadin.com/web/artur</url>
+ <organization>Vaadin Ltd</organization>
+ <organizationUrl>http://vaadin.com/</organizationUrl>
+ <roles>
+ <role>architect</role>
+ <role>developer</role>
+ <role>team manager</role>
+ </roles>
+ <timezone>2</timezone>
+ </developer>
+ <developer>
+ <id>hesara</id>
+ <name>Henri Sara</name>
+ <email>hesara@vaadin.com</email>
+ <organization>Vaadin Ltd</organization>
+ <organizationUrl>http://vaadin.com/</organizationUrl>
+ <roles>
+ <role>developer</role>
+ </roles>
+ <timezone>2</timezone>
+ </developer>
+ </developers>
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>com.vaadin</groupId>
+ <artifactId>vaadin-shared</artifactId>
+ <version>@vaadin.version@</version>
+ </dependency>
+ <dependency>
+ <groupId>com.vaadin</groupId>
+ <artifactId>vaadin-server</artifactId>
+ <version>@vaadin.version@</version>
+ </dependency>
+ <dependency>
+ <groupId>com.vaadin</groupId>
+ <artifactId>vaadin-push</artifactId>
+ <version>@vaadin.version@</version>
+ </dependency>
+ <dependency>
+ <groupId>com.vaadin</groupId>
+ <artifactId>vaadin-widgets</artifactId>
+ <version>@vaadin.version@</version>
+ </dependency>
+ <dependency>
+ <groupId>com.vaadin</groupId>
+ <artifactId>vaadin-client</artifactId>
+ <version>@vaadin.version@</version>
+ </dependency>
+ <dependency>
+ <groupId>com.vaadin</groupId>
+ <artifactId>vaadin-client-compiler</artifactId>
+ <version>@vaadin.version@</version>
+ </dependency>
+ <dependency>
+ <groupId>com.vaadin</groupId>
+ <artifactId>vaadin-client-compiled</artifactId>
+ <version>@vaadin.version@</version>
+ </dependency>
+ <dependency>
+ <groupId>com.vaadin</groupId>
+ <artifactId>vaadin-themes</artifactId>
+ <version>@vaadin.version@</version>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+</project>
diff --git a/build.xml b/build.xml
index ee24c61529..a88892772e 100644
--- a/build.xml
+++ b/build.xml
@@ -21,11 +21,13 @@
<exclude name="build/**" />
<exclude name="bin/**" />
<exclude name="buildhelpers/**" />
+ <exclude name="all/**" />
</fileset>
</ivy:buildlist>
<path id="build-path">
<path location="buildhelpers/build.xml" />
<path refid="ivy.build.path" />
+ <path location="all/build.xml" />
</path>
</target>
<target name="clean" depends="buildorder">
diff --git a/client/src/com/vaadin/client/BrowserInfo.java b/client/src/com/vaadin/client/BrowserInfo.java
index 5ca79cb121..3bc75a9a9b 100644
--- a/client/src/com/vaadin/client/BrowserInfo.java
+++ b/client/src/com/vaadin/client/BrowserInfo.java
@@ -411,6 +411,11 @@ public class BrowserInfo {
if (isIOS() && isWebkit() && getOperatingSystemMajorVersion() >= 6) {
return false;
}
+
+ if (isIE()) {
+ return false;
+ }
+
return true;
}
diff --git a/client/src/com/vaadin/client/communication/AtmospherePushConnection.java b/client/src/com/vaadin/client/communication/AtmospherePushConnection.java
index 787da9bc6f..e544c91d0f 100644
--- a/client/src/com/vaadin/client/communication/AtmospherePushConnection.java
+++ b/client/src/com/vaadin/client/communication/AtmospherePushConnection.java
@@ -43,7 +43,7 @@ import elemental.json.JsonObject;
/**
* The default {@link PushConnection} implementation that uses Atmosphere for
* handling the communication channel.
- *
+ *
* @author Vaadin Ltd
* @since 7.1
*/
@@ -135,8 +135,6 @@ public class AtmospherePushConnection implements PushConnection {
*/
private Command pendingDisconnectCommand;
- private String pushPath;
-
public AtmospherePushConnection() {
}
@@ -183,9 +181,6 @@ public class AtmospherePushConnection implements PushConnection {
pushConfiguration.parameters.get(param));
}
- pushPath = pushConfiguration.pushPath;
- assert pushPath != null;
-
runWhenAtmosphereLoaded(new Command() {
@Override
public void execute() {
@@ -202,7 +197,7 @@ public class AtmospherePushConnection implements PushConnection {
private void connect() {
String baseUrl = connection
.translateVaadinUri(ApplicationConstants.APP_PROTOCOL_PREFIX
- + pushPath + '/');
+ + ApplicationConstants.PUSH_PATH + '/');
String extraParams = UIConstants.UI_ID_PARAMETER + "="
+ connection.getConfiguration().getUIId();
@@ -277,9 +272,9 @@ public class AtmospherePushConnection implements PushConnection {
/**
* Called whenever a server push connection is established (or
* re-established).
- *
+ *
* @param response
- *
+ *
* @since 7.2
*/
protected void onConnect(AtmosphereResponse response) {
@@ -360,7 +355,7 @@ public class AtmospherePushConnection implements PushConnection {
/**
* Called if the push connection fails. Atmosphere will automatically retry
* the connection until successful.
- *
+ *
*/
protected void onError(AtmosphereResponse response) {
state = State.DISCONNECTED;
diff --git a/client/src/com/vaadin/client/connectors/GridConnector.java b/client/src/com/vaadin/client/connectors/GridConnector.java
index d17f378611..0e2ee0046b 100644
--- a/client/src/com/vaadin/client/connectors/GridConnector.java
+++ b/client/src/com/vaadin/client/connectors/GridConnector.java
@@ -176,6 +176,18 @@ public class GridConnector extends AbstractHasComponentsConnector implements
this.id = id;
}
+ /**
+ * Sets a new renderer for this column object
+ *
+ * @param rendererConnector
+ * a renderer connector object
+ */
+ public void setRenderer(
+ AbstractRendererConnector<Object> rendererConnector) {
+ setRenderer(rendererConnector.getRenderer());
+ this.rendererConnector = rendererConnector;
+ }
+
@Override
public Object getValue(final JsonObject obj) {
final JsonObject rowData = obj.getObject(GridState.JSONKEY_DATA);
@@ -189,16 +201,6 @@ public class GridConnector extends AbstractHasComponentsConnector implements
return null;
}
- /*
- * Only used to check that the renderer connector will not change during
- * the column lifetime.
- *
- * TODO remove once support for changing renderers is implemented
- */
- private AbstractRendererConnector<Object> getRendererConnector() {
- return rendererConnector;
- }
-
private AbstractFieldConnector getEditorConnector() {
return editorConnector;
}
@@ -1137,11 +1139,6 @@ public class GridConnector extends AbstractHasComponentsConnector implements
columnsUpdatedFromState = true;
updateColumnFromState(column, columnState);
columnsUpdatedFromState = false;
-
- if (columnState.rendererConnector != column.getRendererConnector()) {
- throw new UnsupportedOperationException(
- "Changing column renderer after initialization is currently unsupported");
- }
}
/**
@@ -1185,6 +1182,7 @@ public class GridConnector extends AbstractHasComponentsConnector implements
* @param state
* The state to get the data from
*/
+ @SuppressWarnings("unchecked")
private static void updateColumnFromState(CustomGridColumn column,
GridColumnState state) {
column.setWidth(state.width);
@@ -1192,6 +1190,9 @@ public class GridConnector extends AbstractHasComponentsConnector implements
column.setMaximumWidth(state.maxWidth);
column.setExpandRatio(state.expandRatio);
+ assert state.rendererConnector instanceof AbstractRendererConnector : "GridColumnState.rendererConnector is invalid (not subclass of AbstractRendererConnector)";
+ column.setRenderer((AbstractRendererConnector<Object>) state.rendererConnector);
+
column.setSortable(state.sortable);
column.setHidden(state.hidden);
diff --git a/client/src/com/vaadin/client/ui/FocusableScrollPanel.java b/client/src/com/vaadin/client/ui/FocusableScrollPanel.java
index 475c8f8074..9dd9c17675 100644
--- a/client/src/com/vaadin/client/ui/FocusableScrollPanel.java
+++ b/client/src/com/vaadin/client/ui/FocusableScrollPanel.java
@@ -48,9 +48,11 @@ public class FocusableScrollPanel extends SimpleFocusablePanel implements
Style style = getElement().getStyle();
style.setProperty("zoom", "1");
style.setPosition(Position.RELATIVE);
+ browserInfo = BrowserInfo.get();
}
private DivElement focusElement;
+ private BrowserInfo browserInfo;
public FocusableScrollPanel(boolean useFakeFocusElement) {
this();
@@ -72,6 +74,12 @@ public class FocusableScrollPanel extends SimpleFocusablePanel implements
style.setPosition(Position.FIXED);
style.setTop(0, Unit.PX);
style.setLeft(0, Unit.PX);
+ if (browserInfo.isIE()) {
+ // for #15294: artificially hide little bit more the
+ // focusElement, otherwise IE will make the window to scroll
+ // into it when focused
+ style.setLeft(-999, Unit.PX);
+ }
getElement().appendChild(focusElement);
/* Sink from focusElemet too as focusa and blur don't bubble */
DOM.sinkEvents(focusElement, Event.FOCUSEVENTS);
diff --git a/client/src/com/vaadin/client/ui/VAccordion.java b/client/src/com/vaadin/client/ui/VAccordion.java
index 06eaecaf70..fc328dd56a 100644
--- a/client/src/com/vaadin/client/ui/VAccordion.java
+++ b/client/src/com/vaadin/client/ui/VAccordion.java
@@ -29,8 +29,8 @@ import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.ui.ComplexPanel;
import com.google.gwt.user.client.ui.Widget;
import com.vaadin.client.ComponentConnector;
-import com.vaadin.client.WidgetUtil;
import com.vaadin.client.VCaption;
+import com.vaadin.client.WidgetUtil;
import com.vaadin.client.ui.TouchScrollDelegate.TouchScrollHandler;
import com.vaadin.shared.ComponentConstants;
import com.vaadin.shared.ui.accordion.AccordionState;
@@ -417,6 +417,9 @@ public class VAccordion extends VTabsheetBase {
public void removeTab(int index) {
StackItem item = getStackItem(index);
remove(item);
+ if (selectedItemIndex == index) {
+ selectedItemIndex = -1;
+ }
touchScrollHandler.removeElement(item.getContainerElement());
}
diff --git a/client/src/com/vaadin/client/ui/VScrollTable.java b/client/src/com/vaadin/client/ui/VScrollTable.java
index 12de2724fc..13561dcd0f 100644
--- a/client/src/com/vaadin/client/ui/VScrollTable.java
+++ b/client/src/com/vaadin/client/ui/VScrollTable.java
@@ -2774,7 +2774,9 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
private boolean sortable = false;
private final String cid;
+
private boolean dragging;
+ private Integer currentDragX = null; // is used to resolve #14796
private int dragStartX;
private int colIndex;
@@ -3146,6 +3148,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
event.stopPropagation();
}
dragging = true;
+ currentDragX = WidgetUtil.getTouchOrMouseClientX(event);
moved = false;
colIndex = getColIndexByKey(cid);
DOM.setCapture(getElement());
@@ -3160,6 +3163,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
if (columnReordering
&& WidgetUtil.isTouchEventOrLeftMouseButton(event)) {
dragging = false;
+ currentDragX = null;
DOM.releaseCapture(getElement());
if (WidgetUtil.isTouchEvent(event)) {
@@ -3227,47 +3231,57 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
break;
case Event.ONTOUCHMOVE:
case Event.ONMOUSEMOVE:
- if (dragging && WidgetUtil.isTouchEventOrLeftMouseButton(event)) {
- if (event.getTypeInt() == Event.ONTOUCHMOVE) {
- /*
- * prevent using this event in e.g. scrolling
- */
- event.stopPropagation();
- }
- if (!moved) {
- createFloatingCopy();
- moved = true;
- }
+ // only start the drag if the mouse / touch has moved a minimum
+ // distance in x-axis (the same idea as in #13381)
+ int currentX = WidgetUtil.getTouchOrMouseClientX(event);
- final int clientX = WidgetUtil
- .getTouchOrMouseClientX(event);
- final int x = clientX + tHead.hTableWrapper.getScrollLeft();
- int slotX = headerX;
- closestSlot = colIndex;
- int closestDistance = -1;
- int start = 0;
- if (showRowHeaders) {
- start++;
- }
- final int visibleCellCount = tHead.getVisibleCellCount();
- for (int i = start; i <= visibleCellCount; i++) {
- if (i > 0) {
- final String colKey = getColKeyByIndex(i - 1);
- // getColWidth only returns the internal width
- // without padding, not the offset width of the
- // whole td (#10890)
- slotX += getColWidth(colKey)
- + scrollBody.getCellExtraWidth();
+ if (currentDragX == null
+ || Math.abs(currentDragX - currentX) > VDragAndDropManager.MINIMUM_DISTANCE_TO_START_DRAG) {
+ if (dragging
+ && WidgetUtil.isTouchEventOrLeftMouseButton(event)) {
+ if (event.getTypeInt() == Event.ONTOUCHMOVE) {
+ /*
+ * prevent using this event in e.g. scrolling
+ */
+ event.stopPropagation();
}
- final int dist = Math.abs(x - slotX);
- if (closestDistance == -1 || dist < closestDistance) {
- closestDistance = dist;
- closestSlot = i;
+ if (!moved) {
+ createFloatingCopy();
+ moved = true;
}
- }
- tHead.focusSlot(closestSlot);
- updateFloatingCopysPosition(clientX, -1);
+ final int clientX = WidgetUtil
+ .getTouchOrMouseClientX(event);
+ final int x = clientX
+ + tHead.hTableWrapper.getScrollLeft();
+ int slotX = headerX;
+ closestSlot = colIndex;
+ int closestDistance = -1;
+ int start = 0;
+ if (showRowHeaders) {
+ start++;
+ }
+ final int visibleCellCount = tHead
+ .getVisibleCellCount();
+ for (int i = start; i <= visibleCellCount; i++) {
+ if (i > 0) {
+ final String colKey = getColKeyByIndex(i - 1);
+ // getColWidth only returns the internal width
+ // without padding, not the offset width of the
+ // whole td (#10890)
+ slotX += getColWidth(colKey)
+ + scrollBody.getCellExtraWidth();
+ }
+ final int dist = Math.abs(x - slotX);
+ if (closestDistance == -1 || dist < closestDistance) {
+ closestDistance = dist;
+ closestSlot = i;
+ }
+ }
+ tHead.focusSlot(closestSlot);
+
+ updateFloatingCopysPosition(clientX, -1);
+ }
}
break;
default:
diff --git a/client/src/com/vaadin/client/ui/customlayout/CustomLayoutConnector.java b/client/src/com/vaadin/client/ui/customlayout/CustomLayoutConnector.java
index 80979587b9..cde1f1af0f 100644
--- a/client/src/com/vaadin/client/ui/customlayout/CustomLayoutConnector.java
+++ b/client/src/com/vaadin/client/ui/customlayout/CustomLayoutConnector.java
@@ -77,22 +77,24 @@ public class CustomLayoutConnector extends AbstractLayoutConnector implements
// (even though both can never be given at the same time)
templateContents = getConnection().getResource(
"layouts/" + templateName + ".html");
- if (templateContents == null) {
- // Template missing -> show debug notice and render components
- // in order.
- getWidget()
- .getElement()
- .setInnerHTML(
- "<em>Layout file layouts/"
- + templateName
- + ".html is missing. Components will be drawn for debug purposes.</em>");
- }
}
if (templateContents != null) {
// Template ok -> initialize.
getWidget().initializeHTML(templateContents,
getConnection().getThemeUri());
+ } else {
+ // Template missing -> show debug notice and render components in
+ // order.
+ String warning = templateName != null ? "Layout file layouts/"
+ + templateName + ".html is missing."
+ : "Layout file not specified.";
+ getWidget()
+ .getElement()
+ .setInnerHTML(
+ "<em>"
+ + warning
+ + " Components will be drawn for debug purposes.</em>");
}
templateUpdated = true;
}
diff --git a/client/src/com/vaadin/client/ui/dd/VDragAndDropManager.java b/client/src/com/vaadin/client/ui/dd/VDragAndDropManager.java
index 844f4c1b9c..47f8eb1b66 100644
--- a/client/src/com/vaadin/client/ui/dd/VDragAndDropManager.java
+++ b/client/src/com/vaadin/client/ui/dd/VDragAndDropManager.java
@@ -38,9 +38,9 @@ import com.vaadin.client.ComponentConnector;
import com.vaadin.client.MouseEventDetailsBuilder;
import com.vaadin.client.Profiler;
import com.vaadin.client.UIDL;
-import com.vaadin.client.WidgetUtil;
import com.vaadin.client.VConsole;
import com.vaadin.client.ValueMap;
+import com.vaadin.client.WidgetUtil;
import com.vaadin.client.ui.VOverlay;
import com.vaadin.shared.ApplicationConstants;
import com.vaadin.shared.MouseEventDetails;
@@ -240,6 +240,12 @@ public class VDragAndDropManager {
}
+ /*
+ * #13381, #14796. The drag only actually starts when the mouse move or
+ * touch move event is more than 3 pixel away.
+ */
+ public static final int MINIMUM_DISTANCE_TO_START_DRAG = 3;
+
private static VDragAndDropManager instance;
private HandlerRegistration handlerRegistration;
private VDragEvent currentDrag;
@@ -425,25 +431,16 @@ public class VDragAndDropManager {
int currentY = WidgetUtil
.getTouchOrMouseClientY(event
.getNativeEvent());
- if (Math.abs(startX - currentX) > 3
- || Math.abs(startY - currentY) > 3) {
- if (deferredStartRegistration != null) {
- deferredStartRegistration
- .removeHandler();
- deferredStartRegistration = null;
- }
+ if (Math.abs(startX - currentX) > MINIMUM_DISTANCE_TO_START_DRAG
+ || Math.abs(startY - currentY) > MINIMUM_DISTANCE_TO_START_DRAG) {
+ ensureDeferredRegistrationCleanup();
currentDrag.setCurrentGwtEvent(event
.getNativeEvent());
startDrag.execute();
}
break;
default:
- // on any other events, clean up the
- // deferred drag start
- if (deferredStartRegistration != null) {
- deferredStartRegistration.removeHandler();
- deferredStartRegistration = null;
- }
+ ensureDeferredRegistrationCleanup();
currentDrag = null;
clearDragElement();
break;
@@ -534,10 +531,10 @@ public class VDragAndDropManager {
}
private void endDrag(boolean doDrop) {
- if (handlerRegistration != null) {
- handlerRegistration.removeHandler();
- handlerRegistration = null;
- }
+
+ ensureDeferredRegistrationCleanup();
+ ensureHandlerRegistrationCleanup();
+
boolean sendTransferableToServer = false;
if (currentDropHandler != null) {
if (doDrop) {
@@ -595,6 +592,20 @@ public class VDragAndDropManager {
}
+ private void ensureHandlerRegistrationCleanup() {
+ if (handlerRegistration != null) {
+ handlerRegistration.removeHandler();
+ handlerRegistration = null;
+ }
+ }
+
+ private void ensureDeferredRegistrationCleanup() {
+ if (deferredStartRegistration != null) {
+ deferredStartRegistration.removeHandler();
+ deferredStartRegistration = null;
+ }
+ }
+
private void removeActiveDragSourceStyleName(ComponentConnector dragSource) {
dragSource.getWidget().removeStyleName(ACTIVE_DRAG_SOURCE_STYLENAME);
}
diff --git a/client/src/com/vaadin/client/widget/grid/selection/MultiSelectionRenderer.java b/client/src/com/vaadin/client/widget/grid/selection/MultiSelectionRenderer.java
index 5024c8bffa..ddbf690970 100644
--- a/client/src/com/vaadin/client/widget/grid/selection/MultiSelectionRenderer.java
+++ b/client/src/com/vaadin/client/widget/grid/selection/MultiSelectionRenderer.java
@@ -569,6 +569,7 @@ public class MultiSelectionRenderer<T> extends ComplexRenderer<Boolean> {
InputElement checkbox = InputElement.as(cell.getElement()
.getFirstChildElement());
checkbox.setChecked(data.booleanValue());
+ checkbox.setDisabled(grid.isEditorActive());
checkbox.setPropertyInt(LOGICAL_ROW_PROPERTY_INT, cell.getRowIndex());
}
diff --git a/client/src/com/vaadin/client/widgets/Escalator.java b/client/src/com/vaadin/client/widgets/Escalator.java
index 6d9b8ee70a..88ed9295e4 100644
--- a/client/src/com/vaadin/client/widgets/Escalator.java
+++ b/client/src/com/vaadin/client/widgets/Escalator.java
@@ -2031,9 +2031,8 @@ public class Escalator extends Widget implements RequiresResize,
return new Cell(domRowIndex, domColumnIndex, cellElement);
}
- double getMaxCellWidth(int colIndex) throws IllegalArgumentException {
- double maxCellWidth = -1;
-
+ void createAutoSizeElements(int colIndex,
+ Collection<TableCellElement> elements) {
assert isAttached() : "Can't measure max width of cell, since Escalator is not attached to the DOM.";
NodeList<TableRowElement> rows = root.getRows();
@@ -2062,24 +2061,9 @@ public class Escalator extends Widget implements RequiresResize,
cellClone.getStyle().clearWidth();
rowElement.insertBefore(cellClone, cellOriginal);
- double requiredWidth = WidgetUtil
- .getRequiredWidthBoundingClientRectDouble(cellClone);
-
- if (BrowserInfo.get().isIE()) {
- /*
- * IE browsers have some issues with subpixels. Occasionally
- * content is overflown even if not necessary. Increase the
- * counted required size by 0.01 just to be on the safe
- * side.
- */
- requiredWidth += 0.01;
- }
- maxCellWidth = Math.max(requiredWidth, maxCellWidth);
- cellClone.removeFromParent();
+ elements.add(cellClone);
}
-
- return maxCellWidth;
}
private boolean cellIsPartOfSpan(TableCellElement cell) {
@@ -3906,7 +3890,8 @@ public class Escalator extends Widget implements RequiresResize,
if (px < 0) {
if (isAttached()) {
- calculateWidth();
+ autosizeColumns(Collections.singletonList(columns
+ .indexOf(this)));
} else {
/*
* the column's width is calculated at Escalator.onLoad
@@ -3960,10 +3945,6 @@ public class Escalator extends Widget implements RequiresResize,
}
return false;
}
-
- private void calculateWidth() {
- calculatedWidth = getMaxCellWidth(columns.indexOf(this));
- }
}
private final List<Column> columns = new ArrayList<Column>();
@@ -4268,6 +4249,7 @@ public class Escalator extends Widget implements RequiresResize,
return;
}
+ List<Integer> autosizeColumns = new ArrayList<Integer>();
for (Entry<Integer, Double> entry : indexWidthMap.entrySet()) {
int index = entry.getKey().intValue();
double width = entry.getValue().doubleValue();
@@ -4277,10 +4259,15 @@ public class Escalator extends Widget implements RequiresResize,
}
checkValidColumnIndex(index);
- columns.get(index).setWidth(width);
-
+ if (width >= 0) {
+ columns.get(index).setWidth(width);
+ } else {
+ autosizeColumns.add(index);
+ }
}
+ autosizeColumns(autosizeColumns);
+
widthsArray = null;
header.reapplyColumnWidths();
body.reapplyColumnWidths();
@@ -4291,6 +4278,64 @@ public class Escalator extends Widget implements RequiresResize,
recalculateElementSizes();
}
+ private void autosizeColumns(List<Integer> columns) {
+ if (columns.isEmpty()) {
+ return;
+ }
+
+ // Must process columns in index order
+ Collections.sort(columns);
+
+ Map<Integer, List<TableCellElement>> autoSizeElements = new HashMap<Integer, List<TableCellElement>>();
+ try {
+ // Set up the entire DOM at once
+ for (int i = columns.size() - 1; i >= 0; i--) {
+ // Iterate backwards to not mess with the indexing
+ Integer colIndex = columns.get(i);
+
+ ArrayList<TableCellElement> elements = new ArrayList<TableCellElement>();
+ autoSizeElements.put(colIndex, elements);
+
+ header.createAutoSizeElements(colIndex, elements);
+ body.createAutoSizeElements(colIndex, elements);
+ footer.createAutoSizeElements(colIndex, elements);
+ }
+
+ // Extract all measurements & update values
+ for (Integer colIndex : columns) {
+ double maxWidth = Double.NEGATIVE_INFINITY;
+ List<TableCellElement> elements = autoSizeElements
+ .get(colIndex);
+ for (TableCellElement element : elements) {
+
+ double cellWidth = WidgetUtil
+ .getRequiredWidthBoundingClientRectDouble(element);
+
+ maxWidth = Math.max(maxWidth, cellWidth);
+ }
+ assert maxWidth >= 0 : "Got a negative max width for a column, which should be impossible.";
+
+ if (BrowserInfo.get().isIE()) {
+ /*
+ * IE browsers have some issues with subpixels.
+ * Occasionally content is overflown even if not
+ * necessary. Increase the counted required size by 0.01
+ * just to be on the safe side.
+ */
+ maxWidth += 0.01;
+ }
+
+ this.columns.get(colIndex).calculatedWidth = maxWidth;
+ }
+ } finally {
+ for (List<TableCellElement> list : autoSizeElements.values()) {
+ for (TableCellElement element : list) {
+ element.removeFromParent();
+ }
+ }
+ }
+ }
+
private void checkValidColumnIndex(int index)
throws IllegalArgumentException {
if (!Range.withLength(0, getColumnCount()).contains(index)) {
@@ -4310,18 +4355,6 @@ public class Escalator extends Widget implements RequiresResize,
return columns.get(index).getCalculatedWidth();
}
- private double getMaxCellWidth(int colIndex)
- throws IllegalArgumentException {
- double headerWidth = header.getMaxCellWidth(colIndex);
- double bodyWidth = body.getMaxCellWidth(colIndex);
- double footerWidth = footer.getMaxCellWidth(colIndex);
-
- double maxWidth = Math.max(headerWidth,
- Math.max(bodyWidth, footerWidth));
- assert maxWidth >= 0 : "Got a negative max width for a column, which should be impossible.";
- return maxWidth;
- }
-
/**
* Calculates the width of the columns in a given range.
*
diff --git a/client/src/com/vaadin/client/widgets/Grid.java b/client/src/com/vaadin/client/widgets/Grid.java
index dad6f0fcfc..20b8844623 100644
--- a/client/src/com/vaadin/client/widgets/Grid.java
+++ b/client/src/com/vaadin/client/widgets/Grid.java
@@ -1190,6 +1190,7 @@ public class Grid<T> extends ResizeComposite implements
+ "Grid editor");
grid.getEscalator().setScrollLocked(Direction.VERTICAL,
false);
+ updateSelectionCheckboxesAsNeeded(true);
}
}
};
@@ -1289,6 +1290,16 @@ public class Grid<T> extends ResizeComposite implements
null);
handler.cancel(request);
state = State.INACTIVE;
+ updateSelectionCheckboxesAsNeeded(true);
+ }
+
+ private void updateSelectionCheckboxesAsNeeded(boolean isEnabled) {
+ if (grid.getSelectionModel() instanceof Multi) {
+ grid.refreshBody();
+ CheckBox checkBox = (CheckBox) grid.getDefaultHeaderRow()
+ .getCell(grid.selectionColumn).getWidget();
+ checkBox.setEnabled(isEnabled);
+ }
}
/**
@@ -1315,6 +1326,7 @@ public class Grid<T> extends ResizeComposite implements
EditorRequest<T> request = new EditorRequestImpl<T>(grid, rowIndex,
saveRequestCallback);
handler.save(request);
+ updateSelectionCheckboxesAsNeeded(true);
}
/**
@@ -1379,6 +1391,7 @@ public class Grid<T> extends ResizeComposite implements
rowIndex, bindRequestCallback);
handler.bind(request);
grid.getEscalator().setScrollLocked(Direction.VERTICAL, true);
+ updateSelectionCheckboxesAsNeeded(false);
}
}
@@ -2577,7 +2590,7 @@ public class Grid<T> extends ResizeComposite implements
final double widthFixed = Math.max(widthAsIs,
column.getMinimumWidth());
defaultExpandRatios = defaultExpandRatios
- && column.getExpandRatio() == -1;
+ && (column.getExpandRatio() == -1 || column == selectionColumn);
if (isFixedWidth) {
columnSizes.put(visibleColumns.indexOf(column), widthFixed);
@@ -2595,7 +2608,8 @@ public class Grid<T> extends ResizeComposite implements
.getExpandRatio());
final double newWidth = column.getWidthActual();
final double maxWidth = getMaxWidth(column);
- boolean shouldExpand = newWidth < maxWidth && expandRatio > 0;
+ boolean shouldExpand = newWidth < maxWidth && expandRatio > 0
+ && column != selectionColumn;
if (shouldExpand) {
totalRatios += expandRatio;
columnsToExpand.add(column);
@@ -3923,12 +3937,14 @@ public class Grid<T> extends ResizeComposite implements
if (renderer == null) {
throw new IllegalArgumentException("Renderer cannot be null.");
}
- bodyRenderer = renderer;
- if (grid != null) {
- grid.refreshBody();
- }
+ if (renderer != bodyRenderer) {
+ bodyRenderer = renderer;
+ if (grid != null) {
+ grid.refreshBody();
+ }
+ }
return this;
}
@@ -5635,7 +5651,6 @@ public class Grid<T> extends ResizeComposite implements
escalator.getColumnConfiguration()
.setFrozenColumnCount(numberOfColumns);
-
}
/**
@@ -6975,6 +6990,9 @@ public class Grid<T> extends ResizeComposite implements
// Do ComplexRenderer.init and render new content
conf.insertColumns(0, visibleColumns.size());
+ // Number of frozen columns should be kept same #16901
+ updateFrozenColumns();
+
// Update column widths.
for (Column<?, T> column : columns) {
column.reapplyWidth();
diff --git a/common.xml b/common.xml
index 9487560051..075044bb5b 100644
--- a/common.xml
+++ b/common.xml
@@ -9,7 +9,8 @@
<property name="gwt.basedir" location="${vaadin.basedir}/../gwt" />
<property file="${vaadin.basedir}/build.properties" />
- <property name="modules.to.publish.to.maven" value="shared,server,client,client-compiler,client-compiled,themes,push,widgets" />
+ <property name="modules.producing.jar" value="shared,server,client,client-compiler,client-compiled,themes,push,widgets" />
+ <property name="modules.to.publish.to.maven" value="${modules.producing.jar},bom" />
<property name="modules.to.publish.to.download" value="${modules.to.publish.to.maven},all" />
<ivy:settings file="${vaadin.basedir}/ivysettings.xml" />
diff --git a/ivysettings.xml b/ivysettings.xml
index f1fc4d1c63..c97b6a3bfb 100644
--- a/ivysettings.xml
+++ b/ivysettings.xml
@@ -49,6 +49,8 @@
resolver="build-temp" />
<module organisation="com.vaadin" name="vaadin-widgets"
resolver="build-temp" />
+ <module organisation="com.vaadin" name="vaadin-bom"
+ resolver="build-temp" />
<module organisation="com.vaadin" name="vaadin-liferay"
resolver="build-temp" />
</modules>
diff --git a/pom-template.xml b/pom-template.xml
index 4f02482ceb..46b0a518ed 100644
--- a/pom-template.xml
+++ b/pom-template.xml
@@ -1,6 +1,11 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>com.vaadin</groupId>
+ <artifactId>vaadin-parent</artifactId>
+ <version>1.0.0</version>
+ </parent>
<groupId>com.vaadin</groupId>
<artifactId>${module.name}</artifactId>
<version>${vaadin.maven.version}</version>
@@ -62,18 +67,6 @@
<timezone>2</timezone>
</developer>
</developers>
- <distributionManagement>
- <repository>
- <id>vaadin-releases</id>
- <name>Vaadin release repository</name>
- <url>https://oss.sonatype.org/content/repositories/vaadin-releases/</url>
- </repository>
- <snapshotRepository>
- <id>vaadin-snapshots</id>
- <name>Vaadin snapshot repository</name>
- <url>https://oss.sonatype.org/content/repositories/vaadin-snapshots/</url>
- </snapshotRepository>
- </distributionManagement>
<repositories>
<repository>
<id>vaadin-snapshots</id>
diff --git a/publish.xml b/publish.xml
index 2fafb68246..3c14e86774 100644
--- a/publish.xml
+++ b/publish.xml
@@ -57,15 +57,33 @@
<property name="jar.file" location="result/artifacts/${vaadin.version}/vaadin-${module}/vaadin-${module}-${vaadin.version}.jar" />
<property name="pom.file" location="result/artifacts/${vaadin.version}/vaadin-${module}/vaadin-${module}-${vaadin.version}.pom" />
- <artifact:mvn failonerror="true">
- <arg value="gpg:sign-and-deploy-file" />
- <sysproperty key="file" value="${jar.file}" />
- <sysproperty key="pomFile" value="${pom.file}" />
- <sysproperty key="repositoryId" value="${maven.snapshot.repository.id}" />
- <sysproperty key="url" value="${maven.snapshot.repository.url}" />
- <sysproperty key="gpg.passphrase" value="${gpg.passphrase}" />
- <sysproperty key="retryFailedDeploymentCount" value="10" />
- </artifact:mvn>
+ <antcontrib:if>
+ <available file="${jar.file}"/>
+ <then>
+ <artifact:mvn failonerror="true">
+ <arg value="gpg:sign-and-deploy-file" />
+ <sysproperty key="file" value="${jar.file}" />
+ <sysproperty key="pomFile" value="${pom.file}" />
+ <sysproperty key="repositoryId" value="${maven.snapshot.repository.id}" />
+ <sysproperty key="url" value="${maven.snapshot.repository.url}" />
+ <sysproperty key="gpg.passphrase" value="${gpg.passphrase}" />
+ <sysproperty key="retryFailedDeploymentCount" value="10" />
+ </artifact:mvn>
+ </then>
+ <else>
+ <artifact:mvn failonerror="true">
+ <arg value="gpg:sign-and-deploy-file" />
+ <sysproperty key="file" value="${pom.file}" />
+ <sysproperty key="pomFile" value="${pom.file}" />
+ <sysproperty key="generatePom" value="false" />
+ <sysproperty key="packaging" value="pom" />
+ <sysproperty key="repositoryId" value="${maven.snapshot.repository.id}" />
+ <sysproperty key="url" value="${maven.snapshot.repository.url}" />
+ <sysproperty key="gpg.passphrase" value="${gpg.passphrase}" />
+ <sysproperty key="retryFailedDeploymentCount" value="10" />
+ </artifact:mvn>
+ </else>
+ </antcontrib:if>
</target>
<!-- Use this to publish to local Maven repo -->
@@ -87,12 +105,26 @@
<property name="sources.file" location="result/artifacts/${vaadin.version}/vaadin-${module}/vaadin-${module}-${vaadin.version}-sources.jar" />
<property name="pom.file" location="result/artifacts/${vaadin.version}/vaadin-${module}/vaadin-${module}-${vaadin.version}.pom" />
- <artifact:mvn failonerror="true">
- <arg value="install:install-file" />
- <sysproperty key="file" value="${jar.file}" />
- <sysproperty key="pomFile" value="${pom.file}" />
- <sysproperty key="javadoc" value="${javadoc.file}" />
- <sysproperty key="sources" value="${sources.file}" />
- </artifact:mvn>
+ <antcontrib:if>
+ <available file="${jar.file}"/>
+ <then>
+ <artifact:mvn failonerror="true">
+ <arg value="install:install-file" />
+ <sysproperty key="file" value="${jar.file}" />
+ <sysproperty key="pomFile" value="${pom.file}" />
+ <sysproperty key="javadoc" value="${javadoc.file}" />
+ <sysproperty key="sources" value="${sources.file}" />
+ </artifact:mvn>
+ </then>
+ <else>
+ <artifact:mvn failonerror="true">
+ <arg value="install:install-file" />
+ <sysproperty key="file" value="${pom.file}" />
+ <sysproperty key="pomFile" value="${pom.file}" />
+ <sysproperty key="generatePom" value="false" />
+ <sysproperty key="packaging" value="pom" />
+ </artifact:mvn>
+ </else>
+ </antcontrib:if>
</target>
</project>
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));
+ }
+}
diff --git a/shared/src/com/vaadin/shared/ApplicationConstants.java b/shared/src/com/vaadin/shared/ApplicationConstants.java
index 990564a6b8..d7aaee6267 100644
--- a/shared/src/com/vaadin/shared/ApplicationConstants.java
+++ b/shared/src/com/vaadin/shared/ApplicationConstants.java
@@ -28,6 +28,8 @@ public class ApplicationConstants implements Serializable {
public static final String HEARTBEAT_PATH = "HEARTBEAT";
+ public static final String PUSH_PATH = "PUSH";
+
public static final String PUBLISHED_FILE_PATH = APP_PATH + '/'
+ "PUBLISHED";
@@ -74,7 +76,7 @@ public class ApplicationConstants implements Serializable {
/**
* The name of the javascript containing the bootstrap code. The file is
* located in the VAADIN directory.
- *
+ *
* @since 7.3
*/
public static final String VAADIN_BOOTSTRAP_JS = "vaadinBootstrap.js";
@@ -88,7 +90,7 @@ public class ApplicationConstants implements Serializable {
/**
* The name of the debug version of the javascript containing push support.
* The file is located in the VAADIN directory.
- *
+ *
* @since 7.1.6
*/
public static final String VAADIN_PUSH_DEBUG_JS = "vaadinPush.debug.js";
@@ -100,14 +102,14 @@ public class ApplicationConstants implements Serializable {
/**
* The name of the parameter used to transmit RPC invocations
- *
+ *
* @since 7.2
*/
public static final String RPC_INVOCATIONS = "rpc";
/**
* The name of the parameter used to transmit the CSRF token
- *
+ *
* @since 7.2
*/
public static final String CSRF_TOKEN = "csrfToken";
@@ -116,7 +118,7 @@ public class ApplicationConstants implements Serializable {
* The name of the parameter used to transmit the sync id. The value can be
* set to -1 e.g. when testing with pre-recorded requests to make the
* framework ignore the sync id.
- *
+ *
* @see com.vaadin.ui.ConnectorTracker#getCurrentSyncId()
* @since 7.2
*/
diff --git a/shared/src/com/vaadin/shared/ui/ui/UIState.java b/shared/src/com/vaadin/shared/ui/ui/UIState.java
index 04e182c5d4..2f51fef6ee 100644
--- a/shared/src/com/vaadin/shared/ui/ui/UIState.java
+++ b/shared/src/com/vaadin/shared/ui/ui/UIState.java
@@ -110,7 +110,6 @@ public class UIState extends TabIndexState {
public static final String FALLBACK_TRANSPORT_PARAM = "fallbackTransport";
public PushMode mode = PushMode.DISABLED;
- public String pushPath;
public Map<String, String> parameters = new HashMap<String, String>();
{
parameters
diff --git a/uitest/src/com/vaadin/launcher/ApplicationRunnerServlet.java b/uitest/src/com/vaadin/launcher/ApplicationRunnerServlet.java
index 5c2e58d3a2..e2b93ab7d2 100644
--- a/uitest/src/com/vaadin/launcher/ApplicationRunnerServlet.java
+++ b/uitest/src/com/vaadin/launcher/ApplicationRunnerServlet.java
@@ -402,12 +402,9 @@ public class ApplicationRunnerServlet extends LegacyVaadinServlet {
try {
VaadinServletService service = (VaadinServletService) VaadinService
.getCurrent();
- if (service != null) {
- session = service
- .findVaadinSession(new VaadinServletRequest(
- currentRequest, service));
- }
-
+ session = service
+ .findVaadinSession(new VaadinServletRequest(
+ currentRequest, service));
} finally {
/*
* Clear some state set by findVaadinSession to
diff --git a/uitest/src/com/vaadin/tests/VerifyBrowserVersionTest.java b/uitest/src/com/vaadin/tests/VerifyBrowserVersionTest.java
index 5b4f4df788..8d0530204a 100644
--- a/uitest/src/com/vaadin/tests/VerifyBrowserVersionTest.java
+++ b/uitest/src/com/vaadin/tests/VerifyBrowserVersionTest.java
@@ -33,9 +33,20 @@ public class VerifyBrowserVersionTest extends MultiBrowserTest {
DesiredCapabilities desiredCapabilities = getDesiredCapabilities();
- assertThat(vaadinElementById("userAgent").getText(),
- containsString(getExpectedUserAgentString(desiredCapabilities)
- + desiredCapabilities.getVersion()));
+ String userAgent = vaadinElementById("userAgent").getText();
+ String browserIdentifier;
+
+ if (BrowserUtil.isChrome(getDesiredCapabilities())) {
+ // Chrome version does not necessarily match the desired version
+ // because of auto updates...
+ browserIdentifier = getExpectedUserAgentString(getDesiredCapabilities())
+ + "41";
+ } else {
+ browserIdentifier = getExpectedUserAgentString(desiredCapabilities)
+ + desiredCapabilities.getVersion();
+ }
+
+ assertThat(userAgent, containsString(browserIdentifier));
assertThat(vaadinElementById("touchDevice").getText(),
is("Touch device? No"));
diff --git a/uitest/src/com/vaadin/tests/components/accordion/AccordionRemoveComponent.java b/uitest/src/com/vaadin/tests/components/accordion/AccordionRemoveComponent.java
new file mode 100644
index 0000000000..80e0929f8d
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/accordion/AccordionRemoveComponent.java
@@ -0,0 +1,55 @@
+/*
+ * 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.accordion;
+
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.tests.components.AbstractTestUI;
+import com.vaadin.ui.Accordion;
+import com.vaadin.ui.Button;
+import com.vaadin.ui.Button.ClickEvent;
+
+/**
+ * Test for removing component from Accordion.
+ *
+ * @author Vaadin Ltd
+ */
+public class AccordionRemoveComponent extends AbstractTestUI {
+
+ @Override
+ protected void setup(VaadinRequest request) {
+ final Accordion accordion = new Accordion();
+ Button button = new Button("remove");
+ button.addClickListener(new Button.ClickListener() {
+
+ @Override
+ public void buttonClick(ClickEvent event) {
+ accordion.removeComponent(event.getButton());
+ }
+ });
+ accordion.addComponent(button);
+ addComponent(accordion);
+ }
+
+ @Override
+ protected String getTestDescription() {
+ return "Reset selected index when tab is removed";
+ }
+
+ @Override
+ protected Integer getTicketNumber() {
+ return 17248;
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/push/PushPathTest.java b/uitest/src/com/vaadin/tests/components/accordion/AccordionRemoveComponentTest.java
index 0af9c8d3a7..84f1734897 100644
--- a/uitest/src/com/vaadin/tests/push/PushPathTest.java
+++ b/uitest/src/com/vaadin/tests/components/accordion/AccordionRemoveComponentTest.java
@@ -13,27 +13,31 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.vaadin.tests.push;
+package com.vaadin.tests.components.accordion;
import org.junit.Assert;
import org.junit.Test;
+import org.openqa.selenium.By;
-import com.vaadin.tests.tb3.WebsocketTest;
+import com.vaadin.testbench.elements.ButtonElement;
+import com.vaadin.tests.tb3.MultiBrowserTest;
-public class PushPathTest extends WebsocketTest {
-
- private static final int TEN_SECONDS_IN_MS = 10 * 1000;
+/**
+ * Test for removing component from Accordion
+ *
+ * @author Vaadin Ltd
+ */
+public class AccordionRemoveComponentTest extends MultiBrowserTest {
@Test
- public void testCustomPushPath() throws InterruptedException {
+ public void removeComponent_noClientSideException() {
+ setDebug(true);
openTestURL();
- sleep(TEN_SECONDS_IN_MS);
- Assert.assertEquals(vaadinElementById(PushPath.PUSH_PATH_LABEL_ID)
- .getText(), PushPath.PUSH_PATH_LABEL_TEXT);
- }
- @Override
- protected String getDeploymentPath(Class<?> uiClass) {
- return "/run-pushpath/" + uiClass.getCanonicalName();
+ $(ButtonElement.class).first().click();
+
+ Assert.assertFalse(
+ "Error notification with client side exception is shown",
+ isElementPresent(By.className("v-Notification-error")));
}
}
diff --git a/uitest/src/com/vaadin/tests/components/customlayout/CustomLayoutWithNullTemplate.java b/uitest/src/com/vaadin/tests/components/customlayout/CustomLayoutWithNullTemplate.java
new file mode 100644
index 0000000000..de1caf86df
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/customlayout/CustomLayoutWithNullTemplate.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.tests.components.customlayout;
+
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.tests.components.AbstractTestUI;
+import com.vaadin.ui.Button;
+import com.vaadin.ui.CustomLayout;
+import com.vaadin.ui.Label;
+
+public class CustomLayoutWithNullTemplate extends AbstractTestUI {
+
+ @Override
+ protected void setup(VaadinRequest request) {
+ CustomLayout cl = new CustomLayout();
+ cl.addComponent(new Label("This Label should be visible."), "foo");
+ cl.addComponent(new Button("This Button too."), "bar");
+
+ addComponent(cl);
+ }
+
+ @Override
+ protected String getTestDescription() {
+ return "Verify that a default-constructed CustomLayout renders child components";
+ }
+
+ @Override
+ protected Integer getTicketNumber() {
+ return 17210;
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/customlayout/CustomLayoutWithNullTemplateTest.java b/uitest/src/com/vaadin/tests/components/customlayout/CustomLayoutWithNullTemplateTest.java
new file mode 100644
index 0000000000..668d43f18f
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/customlayout/CustomLayoutWithNullTemplateTest.java
@@ -0,0 +1,43 @@
+/*
+ * 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.customlayout;
+
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+
+import com.vaadin.testbench.ElementQuery;
+import com.vaadin.testbench.elements.ButtonElement;
+import com.vaadin.testbench.elements.CustomLayoutElement;
+import com.vaadin.testbench.elements.LabelElement;
+import com.vaadin.tests.tb3.SingleBrowserTest;
+
+public class CustomLayoutWithNullTemplateTest extends SingleBrowserTest {
+
+ @Test
+ public void testChildComponents() {
+ openTestURL();
+
+ ElementQuery<CustomLayoutElement> customLayout = $(CustomLayoutElement.class);
+
+ // Verify the Button and Label are rendered inside the CustomLayout.
+ assertTrue("Button was not rendered.",
+ customLayout.$(ButtonElement.class).exists());
+ assertTrue("Label was not rendered.", customLayout
+ .$(LabelElement.class).exists());
+ }
+
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/GridColumnWidthsWithoutData.java b/uitest/src/com/vaadin/tests/components/grid/GridColumnWidthsWithoutData.java
index 1dfc7bcf11..b04745f17a 100644
--- a/uitest/src/com/vaadin/tests/components/grid/GridColumnWidthsWithoutData.java
+++ b/uitest/src/com/vaadin/tests/components/grid/GridColumnWidthsWithoutData.java
@@ -15,21 +15,41 @@
*/
package com.vaadin.tests.components.grid;
+import java.util.EnumSet;
+
+import com.vaadin.data.Property.ValueChangeEvent;
+import com.vaadin.data.Property.ValueChangeListener;
import com.vaadin.server.VaadinRequest;
import com.vaadin.tests.components.AbstractTestUI;
import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.Grid;
+import com.vaadin.ui.Grid.SelectionMode;
+import com.vaadin.ui.NativeSelect;
import com.vaadin.ui.VerticalLayout;
public class GridColumnWidthsWithoutData extends AbstractTestUI {
+ private SelectionMode selectionMode = SelectionMode.NONE;
private Grid grid = createGrid(true);
@Override
protected void setup(VaadinRequest request) {
addComponent(grid);
+ NativeSelect selectionModeSelector = new NativeSelect("Selection mode",
+ EnumSet.allOf(SelectionMode.class));
+ selectionModeSelector.setValue(selectionMode);
+ selectionModeSelector.setNullSelectionAllowed(false);
+ selectionModeSelector.addValueChangeListener(new ValueChangeListener() {
+ @Override
+ public void valueChange(ValueChangeEvent event) {
+ selectionMode = (SelectionMode) event.getProperty().getValue();
+ grid.setSelectionMode(selectionMode);
+ }
+ });
+ addComponent(selectionModeSelector);
+
addComponent(new Button("Recreate without data",
new Button.ClickListener() {
@Override
@@ -72,6 +92,7 @@ public class GridColumnWidthsWithoutData extends AbstractTestUI {
grid.addColumn("foo");
grid.addColumn("bar");
grid.setWidth("300px");
+ grid.setSelectionMode(selectionMode);
if (withData) {
addDataToGrid(grid);
diff --git a/uitest/src/com/vaadin/tests/components/grid/GridColumnWidthsWithoutDataTest.java b/uitest/src/com/vaadin/tests/components/grid/GridColumnWidthsWithoutDataTest.java
index dd63d6abc9..c215fa0a59 100644
--- a/uitest/src/com/vaadin/tests/components/grid/GridColumnWidthsWithoutDataTest.java
+++ b/uitest/src/com/vaadin/tests/components/grid/GridColumnWidthsWithoutDataTest.java
@@ -23,6 +23,7 @@ import org.junit.Test;
import com.vaadin.testbench.elements.ButtonElement;
import com.vaadin.testbench.elements.GridElement;
import com.vaadin.testbench.elements.GridElement.GridCellElement;
+import com.vaadin.testbench.elements.NativeSelectElement;
import com.vaadin.testbench.elements.NotificationElement;
import com.vaadin.tests.tb3.SingleBrowserTest;
@@ -49,7 +50,7 @@ public class GridColumnWidthsWithoutDataTest extends SingleBrowserTest {
}
@Test
- public void restWidthsWhenInitiallyEmpty() {
+ public void testWidthsWhenInitiallyEmpty() {
setDebug(true);
openTestURL();
$(ButtonElement.class).caption("Recreate without data").first().click();
@@ -74,6 +75,37 @@ public class GridColumnWidthsWithoutDataTest extends SingleBrowserTest {
isElementPresent(NotificationElement.class));
}
+ @Test
+ public void testMultiSelectWidths() {
+ setDebug(true);
+ openTestURL();
+ $(NativeSelectElement.class).caption("Selection mode").first()
+ .selectByText("Multi");
+
+ GridElement grid = $(GridElement.class).first();
+
+ int sum = sumUsedWidths(grid);
+
+ // 295 instead of 300 to avoid rounding issues
+ Assert.assertTrue("Only " + sum + " out of 300px was used", sum > 295);
+
+ $(ButtonElement.class).caption("Recreate without data").first().click();
+
+ grid = $(GridElement.class).first();
+ sum = sumUsedWidths(grid);
+
+ // 295 instead of 300 to avoid rounding issues
+ Assert.assertTrue("Only " + sum + " out of 300px was used", sum > 295);
+ }
+
+ private int sumUsedWidths(GridElement grid) {
+ int sum = 0;
+ for (int i : getColWidths(grid)) {
+ sum += i;
+ }
+ return sum;
+ }
+
private static void assertSameWidths(int[] expected, int[] actual) {
Assert.assertEquals("Arrays have differing lengths", expected.length,
actual.length);
diff --git a/uitest/src/com/vaadin/tests/components/grid/GridEditorMultiselect.java b/uitest/src/com/vaadin/tests/components/grid/GridEditorMultiselect.java
new file mode 100644
index 0000000000..b80a9d1153
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/GridEditorMultiselect.java
@@ -0,0 +1,35 @@
+package com.vaadin.tests.components.grid;
+
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.tests.components.AbstractTestUI;
+import com.vaadin.ui.Grid;
+
+public class GridEditorMultiselect extends AbstractTestUI {
+
+ @Override
+ protected void setup(VaadinRequest request) {
+ Grid grid = new Grid();
+
+ grid.addColumn("name");
+ grid.addColumn("age", Integer.class);
+
+ for (int i = 0; i < 30; i++) {
+ grid.addRow("name " + i, i);
+ }
+
+ grid.setEditorEnabled(true);
+ grid.setSelectionMode(Grid.SelectionMode.MULTI);
+
+ addComponent(grid);
+ }
+
+ @Override
+ protected Integer getTicketNumber() {
+ return 17132;
+ }
+
+ @Override
+ public String getDescription() {
+ return "Grid Multiselect: Edit mode allows invalid selection";
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/GridEditorMultiselectTest.java b/uitest/src/com/vaadin/tests/components/grid/GridEditorMultiselectTest.java
new file mode 100644
index 0000000000..ba689fb5e1
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/GridEditorMultiselectTest.java
@@ -0,0 +1,55 @@
+package com.vaadin.tests.components.grid;
+
+import java.util.List;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.openqa.selenium.WebElement;
+
+import com.vaadin.testbench.By;
+import com.vaadin.testbench.elements.GridElement;
+import com.vaadin.tests.tb3.MultiBrowserTest;
+
+public class GridEditorMultiselectTest extends MultiBrowserTest {
+
+ @Test
+ public void testSelectCheckboxesDisabled() {
+ openTestURL();
+ GridElement grid = openEditor();
+ assertCheckboxesEnabled(grid, false);
+ }
+
+ @Test
+ public void testSelectCheckboxesEnabledBackOnSave() {
+ openTestURL();
+ GridElement grid = openEditor();
+ grid.getEditor().save();
+ assertCheckboxesEnabled(grid, true);
+ }
+
+ @Test
+ public void testSelectCheckboxesEnabledBackOnCancel() {
+ openTestURL();
+ GridElement grid = openEditor();
+ grid.getEditor().cancel();
+ assertCheckboxesEnabled(grid, true);
+ }
+
+ private GridElement openEditor() {
+ GridElement grid = $(GridElement.class).first();
+ grid.getRow(0).doubleClick();
+ Assert.assertTrue("Grid editor should be displayed.", grid.getEditor()
+ .isDisplayed());
+ return grid;
+ }
+
+ private void assertCheckboxesEnabled(GridElement grid, boolean isEnabled) {
+ List<WebElement> checkboxes = grid.findElements(By
+ .xpath("//input[@type='checkbox']"));
+ for (WebElement checkbox : checkboxes) {
+ Assert.assertEquals("Select checkboxes should be "
+ + (isEnabled ? "enabled" : "disabled"), isEnabled,
+ checkbox.isEnabled());
+ }
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/GridResizeTerror.java b/uitest/src/com/vaadin/tests/components/grid/GridResizeTerror.java
new file mode 100644
index 0000000000..365461caa9
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/GridResizeTerror.java
@@ -0,0 +1,45 @@
+/*
+ * 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.grid;
+
+import com.vaadin.annotations.Widgetset;
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.tests.util.ResizeTerrorizer;
+import com.vaadin.tests.widgetset.TestingWidgetSet;
+import com.vaadin.ui.Grid;
+import com.vaadin.ui.UI;
+
+@Widgetset(TestingWidgetSet.NAME)
+public class GridResizeTerror extends UI {
+ @Override
+ protected void init(VaadinRequest request) {
+ Grid grid = new Grid();
+
+ int cols = 10;
+ Object[] data = new Object[cols];
+
+ for (int i = 0; i < cols; i++) {
+ grid.addColumn("Col " + i);
+ data[i] = "Data " + i;
+ }
+
+ for (int i = 0; i < 500; i++) {
+ grid.addRow(data);
+ }
+
+ setContent(new ResizeTerrorizer(grid));
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/GridSwitchRenderers.java b/uitest/src/com/vaadin/tests/components/grid/GridSwitchRenderers.java
new file mode 100644
index 0000000000..e233edc5d0
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/GridSwitchRenderers.java
@@ -0,0 +1,103 @@
+package com.vaadin.tests.components.grid;
+
+import java.util.List;
+import java.util.Random;
+
+import com.vaadin.annotations.Theme;
+import com.vaadin.data.Item;
+import com.vaadin.data.Property.ValueChangeEvent;
+import com.vaadin.data.Property.ValueChangeListener;
+import com.vaadin.data.util.IndexedContainer;
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.tests.components.AbstractTestUIWithLog;
+import com.vaadin.ui.CheckBox;
+import com.vaadin.ui.Grid;
+import com.vaadin.ui.Grid.Column;
+import com.vaadin.ui.Grid.SelectionMode;
+import com.vaadin.ui.renderers.HtmlRenderer;
+import com.vaadin.ui.renderers.TextRenderer;
+
+@SuppressWarnings("serial")
+@Theme("valo")
+public class GridSwitchRenderers extends AbstractTestUIWithLog {
+ private static final int MANUALLY_FORMATTED_COLUMNS = 1;
+ private static final int COLUMNS = 3;
+ private static final int ROWS = 1000;
+ private static final String EXPANSION_COLUMN_ID = "Column 0";
+
+ private IndexedContainer ds;
+
+ @Override
+ protected void setup(VaadinRequest request) {
+ ds = new IndexedContainer() {
+ @Override
+ public List<Object> getItemIds(int startIndex, int numberOfIds) {
+ log("Requested items " + startIndex + " - "
+ + (startIndex + numberOfIds));
+ return super.getItemIds(startIndex, numberOfIds);
+ }
+ };
+
+ {
+ ds.addContainerProperty(EXPANSION_COLUMN_ID, String.class, "");
+
+ int col = MANUALLY_FORMATTED_COLUMNS;
+ for (; col < COLUMNS; col++) {
+ ds.addContainerProperty(getColumnProperty(col), String.class,
+ "");
+ }
+ }
+
+ Random rand = new Random();
+ rand.setSeed(13334);
+ for (int row = 0; row < ROWS; row++) {
+ Item item = ds.addItem(Integer.valueOf(row));
+ fillRow("" + row, item);
+ item.getItemProperty(getColumnProperty(1)).setReadOnly(true);
+ }
+
+ final Grid grid = new Grid(ds);
+ grid.setWidth("100%");
+
+ grid.getColumn(EXPANSION_COLUMN_ID).setWidth(50);
+ for (int col = MANUALLY_FORMATTED_COLUMNS; col < COLUMNS; col++) {
+ grid.getColumn(getColumnProperty(col)).setWidth(300);
+ grid.getColumn(getColumnProperty(col)).setRenderer(
+ new TextRenderer());
+ }
+
+ grid.setSelectionMode(SelectionMode.NONE);
+ addComponent(grid);
+
+ final CheckBox changeRenderer = new CheckBox(
+ "SetHtmlRenderer for Column 2", false);
+ changeRenderer.addValueChangeListener(new ValueChangeListener() {
+ @Override
+ public void valueChange(ValueChangeEvent event) {
+ Column column = grid.getColumn(getColumnProperty(1));
+ if (changeRenderer.getValue()) {
+ column.setRenderer(new HtmlRenderer());
+ } else {
+ column.setRenderer(new TextRenderer());
+ }
+ grid.markAsDirty();
+ }
+ });
+ addComponent(changeRenderer);
+ }
+
+ @SuppressWarnings("unchecked")
+ private void fillRow(String content, Item item) {
+ int col = MANUALLY_FORMATTED_COLUMNS;
+
+ for (; col < COLUMNS; col++) {
+ item.getItemProperty(getColumnProperty(col)).setValue(
+ "<b>(" + content + ", " + col + ")</b>");
+ }
+ }
+
+ private static String getColumnProperty(int c) {
+ return "Column " + c;
+ }
+
+} \ No newline at end of file
diff --git a/uitest/src/com/vaadin/tests/components/grid/GridSwitchRenderersTest.java b/uitest/src/com/vaadin/tests/components/grid/GridSwitchRenderersTest.java
new file mode 100644
index 0000000000..e3bab865c0
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/GridSwitchRenderersTest.java
@@ -0,0 +1,84 @@
+/*
+ * 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.grid;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.vaadin.testbench.elements.CheckBoxElement;
+import com.vaadin.testbench.elements.GridElement;
+import com.vaadin.tests.tb3.MultiBrowserTest;
+
+public class GridSwitchRenderersTest extends MultiBrowserTest {
+
+ @Test
+ public void testRendererSwitch() {
+
+ // The UI should start with TEXT rendering in the second column
+ // Clicking the checkbox will toggle rendering to HTML mode
+ // Clicking it again should return TEXT rendering mode.
+
+ openTestURL();
+
+ GridElement grid = $(GridElement.class).first();
+
+ Assert.assertTrue(
+ "Initial rendering of column 1 is not unformatted text",
+ cellTextIsUnformatted(grid.getCell(0, 1).getText()));
+
+ // NOTE: must click at 5,5 because of Valo and rendering in Chrome
+ // This is a TestBench bug that may be fixed sometime in the future
+ CheckBoxElement cb = $(CheckBoxElement.class).first();
+ cb.click(5, 5);
+
+ Assert.assertTrue(
+ "Column 1 data has not been rendered with HTMLRenderer after renderer swap",
+ cellTextIsHTMLFormatted(grid.getCell(0, 1).getText()));
+ cb.click(5, 5);
+
+ Assert.assertTrue(
+ "Column 1 data has not been re-rendered as text after renderer swap",
+ cellTextIsUnformatted(grid.getCell(0, 1).getText()));
+ }
+
+ /**
+ * Attempts to match a string to a string like {@code <b>(4, 1)</b>}.
+ *
+ * @param cellText
+ * input string
+ * @return true if input string is formatted like a raw HTML string
+ */
+ private boolean cellTextIsUnformatted(String cellText) {
+ String regex = "<b>\\(\\d+, \\d+\\)</b>";
+ return cellText.matches(regex);
+ }
+
+ /**
+ * Attempts to match a string to a string like {@code (4, 1)}, i.e. the HTML
+ * formatted version of the above (the bold tags should be consumed by the
+ * renderer).
+ *
+ * @param cellText
+ * input string
+ * @return true if input string is formatted like plain text (i.e. HTML bits
+ * have been consumed by renderer)
+ */
+ private boolean cellTextIsHTMLFormatted(String cellText) {
+ String regex = "\\(\\d+, \\d+\\)";
+ return cellText.matches(regex);
+ }
+
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridClientColumnPropertiesTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridClientColumnPropertiesTest.java
index 9e7256e0d3..2f5d0e7291 100644
--- a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridClientColumnPropertiesTest.java
+++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridClientColumnPropertiesTest.java
@@ -94,6 +94,23 @@ public class GridClientColumnPropertiesTest extends GridBasicClientFeaturesTest
}
@Test
+ public void testFrozenColumns_columnsReordered_frozenColumnsKept() {
+ openTestURL();
+
+ selectMenuPath("Component", "State", "Frozen column count", "2 columns");
+
+ assertTrue(cellIsFrozen(1, 0));
+ assertTrue(cellIsFrozen(1, 1));
+ assertFalse(cellIsFrozen(1, 2));
+
+ selectMenuPath("Component", "State", "Reverse grid columns");
+
+ assertTrue(cellIsFrozen(1, 0));
+ assertTrue(cellIsFrozen(1, 1));
+ assertFalse(cellIsFrozen(1, 2));
+ }
+
+ @Test
public void testBrokenRenderer() {
setDebug(true);
openTestURL();
diff --git a/uitest/src/com/vaadin/tests/components/splitpanel/SplitPositionChange.java b/uitest/src/com/vaadin/tests/components/splitpanel/SplitPositionChange.java
new file mode 100644
index 0000000000..81c449731c
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/splitpanel/SplitPositionChange.java
@@ -0,0 +1,87 @@
+/*
+ * 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.splitpanel;
+
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.tests.components.AbstractTestUIWithLog;
+import com.vaadin.ui.AbstractSplitPanel;
+import com.vaadin.ui.HorizontalSplitPanel;
+import com.vaadin.ui.Label;
+import com.vaadin.ui.Panel;
+import com.vaadin.ui.VerticalLayout;
+import com.vaadin.ui.VerticalSplitPanel;
+
+/**
+ * Test for {@link SplitPositionChangeListeners}.
+ *
+ * @author Vaadin Ltd
+ */
+public class SplitPositionChange extends AbstractTestUIWithLog {
+
+ @Override
+ protected void setup(VaadinRequest request) {
+ addSplitPanel(true, "Left", "Right");
+ addSplitPanel(false, "Top", "Bottom");
+ }
+
+ private void addSplitPanel(final boolean horizontal, String firstCaption,
+ String secondCaption) {
+ AbstractSplitPanel splitPanel;
+ if (horizontal) {
+ splitPanel = new HorizontalSplitPanel();
+ } else {
+ splitPanel = new VerticalSplitPanel();
+ }
+ splitPanel.setWidth("200px");
+ splitPanel.setHeight("200px");
+ splitPanel.addComponent(buildPanel(firstCaption));
+ splitPanel.addComponent(buildPanel(secondCaption));
+ splitPanel
+ .addSplitPositionChangeListener(new AbstractSplitPanel.SplitPositionChangeListener() {
+
+ @Override
+ public void onSplitPositionChanged(
+ AbstractSplitPanel.SplitPositionChangeEvent event) {
+ log(String.format(
+ "Split position changed: %s, position: %s %s",
+ (horizontal ? "horizontal" : "vertical"),
+ event.getSplitPosition(),
+ event.getSplitPositionUnit()));
+ }
+ });
+ addComponent(splitPanel);
+ }
+
+ private Panel buildPanel(String caption) {
+ VerticalLayout pl = new VerticalLayout();
+ pl.setMargin(true);
+ pl.addComponent(new Label("content"));
+ Panel panel = new Panel(caption, pl);
+ panel.setSizeFull();
+ return panel;
+ }
+
+ @Override
+ protected String getTestDescription() {
+ return "SplitPanel should have an event for the splitter being moved";
+ }
+
+ @Override
+ protected Integer getTicketNumber() {
+ return 3855;
+ }
+
+}
diff --git a/uitest/src/com/vaadin/tests/components/splitpanel/SplitPositionChangeTest.java b/uitest/src/com/vaadin/tests/components/splitpanel/SplitPositionChangeTest.java
new file mode 100644
index 0000000000..43edb56f3a
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/splitpanel/SplitPositionChangeTest.java
@@ -0,0 +1,82 @@
+/*
+ * 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.splitpanel;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.openqa.selenium.By;
+import org.openqa.selenium.WebElement;
+import org.openqa.selenium.interactions.Actions;
+
+import com.vaadin.testbench.elements.HorizontalSplitPanelElement;
+import com.vaadin.testbench.elements.VerticalSplitPanelElement;
+import com.vaadin.tests.tb3.MultiBrowserTest;
+
+/**
+ * Test for {@link SplitPositionChangeListeners}.
+ *
+ * @author Vaadin Ltd
+ */
+public class SplitPositionChangeTest extends MultiBrowserTest {
+
+ @Override
+ public void setup() throws Exception {
+ super.setup();
+ openTestURL();
+ waitForElementPresent(By.className("v-splitpanel-horizontal"));
+ }
+
+ @Test
+ public void testHorizontalSplit() {
+ HorizontalSplitPanelElement split = $(HorizontalSplitPanelElement.class)
+ .first();
+ WebElement splitter = split.findElement(By
+ .className("v-splitpanel-hsplitter"));
+ int position = splitter.getLocation().getX();
+ Actions actions = new Actions(driver);
+ actions.clickAndHold(splitter).moveByOffset(50, 0).release().perform();
+ assertPosition(position, splitter.getLocation().getX());
+ assertLogText(true);
+ }
+
+ @Test
+ public void testVerticalSplit() {
+ VerticalSplitPanelElement split = $(VerticalSplitPanelElement.class)
+ .first();
+ WebElement splitter = split.findElement(By
+ .className("v-splitpanel-vsplitter"));
+ int position = splitter.getLocation().getY();
+ Actions actions = new Actions(driver);
+ actions.clickAndHold(splitter).moveByOffset(0, 50).release().perform();
+ assertPosition(position, splitter.getLocation().getY());
+ assertLogText(false);
+ }
+
+ private void assertPosition(int original, int current) {
+ Assert.assertFalse("Position didn't change", original == current);
+ }
+
+ private void assertLogText(boolean horizontal) {
+ String expected = String.format(
+ "1. Split position changed: %s, position: .*",
+ horizontal ? "horizontal" : "vertical");
+ String actual = getLogRow(0);
+ Assert.assertTrue(
+ String.format(
+ "Log content didn't match the expected format.\nexpected: '%s'\nwas: '%s'",
+ expected, actual), actual.matches(expected));
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/table/TableBlurFocus.java b/uitest/src/com/vaadin/tests/components/table/TableBlurFocus.java
new file mode 100644
index 0000000000..d95b406c1a
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/table/TableBlurFocus.java
@@ -0,0 +1,153 @@
+/*
+ * 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.table;
+
+import java.util.Map;
+
+import com.vaadin.event.FieldEvents.BlurEvent;
+import com.vaadin.event.FieldEvents.BlurListener;
+import com.vaadin.event.FieldEvents.FocusEvent;
+import com.vaadin.event.FieldEvents.FocusListener;
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.tests.components.AbstractTestUIWithLog;
+import com.vaadin.ui.Button;
+import com.vaadin.ui.Button.ClickEvent;
+import com.vaadin.ui.Button.ClickListener;
+import com.vaadin.ui.Label;
+import com.vaadin.ui.Notification;
+import com.vaadin.ui.Table;
+
+/**
+ * Tests that previously focused component's blur event happens before any
+ * variable changes in the focused Table.
+ *
+ * @author Vaadin Ltd
+ */
+public class TableBlurFocus extends AbstractTestUIWithLog {
+
+ enum Columns {
+ COLUMN1, COLUMN2, COLUMN3, COLUMN4, COLUMN5
+ }
+
+ private int count = 0;
+ private Button focusButton;
+
+ @Override
+ protected void setup(VaadinRequest request) {
+ System.out
+ .println("TableBlurFocus/TableInIframeRowClickScrollJumpTest");
+ Button button = new Button("click to focus");
+ button.addFocusListener(new FocusListener() {
+
+ @Override
+ public void focus(FocusEvent event) {
+ log("focus");
+ }
+ });
+ button.addBlurListener(new BlurListener() {
+
+ @Override
+ public void blur(BlurEvent event) {
+ log("blur");
+ }
+ });
+ final Button scrollButton = new Button(
+ "focus lowest button to scroll down");
+ scrollButton.setId("scroll-button");
+ scrollButton.addClickListener(new ClickListener() {
+ @Override
+ public void buttonClick(ClickEvent event) {
+ focusButton.focus();
+ }
+ });
+
+ Label spacerLabel = new Label("spacer");
+ spacerLabel.setHeight("300px");
+
+ addComponent(button);
+ addComponent(scrollButton);
+ addComponent(createTable());
+ addComponent(spacerLabel);
+ addComponent(focusButton = new Button("for focus"));
+ focusButton.setId("focus-button");
+ focusButton.addFocusListener(new FocusListener() {
+ @Override
+ public void focus(FocusEvent event) {
+ focusButton.setCaption("focused");
+ }
+ });
+ }
+
+ private Table createTable() {
+ Table table = new Table() {
+ @Override
+ public void changeVariables(Object source,
+ Map<String, Object> variables) {
+ log("variable change");
+ super.changeVariables(source, variables);
+ }
+ };
+ table.setSelectable(true);
+ table.setImmediate(true);
+
+ table.addContainerProperty(Columns.COLUMN1, String.class, " ");
+ table.addContainerProperty(Columns.COLUMN2, Label.class, null);
+ table.addContainerProperty(Columns.COLUMN3, Button.class, null);
+ table.addContainerProperty(Columns.COLUMN4, String.class, " ");
+ table.setColumnCollapsingAllowed(true);
+ table.setColumnCollapsible(Columns.COLUMN4, true);
+ table.setColumnCollapsed(Columns.COLUMN4, true);
+ table.setSortEnabled(true);
+ table.setFooterVisible(true);
+ table.setPageLength(14);
+ table.addGeneratedColumn(Columns.COLUMN5, new Table.ColumnGenerator() {
+
+ @Override
+ public Object generateCell(Table source, Object itemId,
+ Object columnId) {
+ return "Generated";
+ }
+ });
+
+ table.setColumnHeader(Columns.COLUMN1, "Column");
+ for (int x = 0; x < 120; x++) {
+ final Label buttonLabel = new Label("Not clicked");
+ Button button = new Button("Click me?", new Button.ClickListener() {
+
+ @Override
+ public void buttonClick(Button.ClickEvent event) {
+ ++count;
+ buttonLabel.setValue("Clicked " + count + " times");
+ Notification.show("Clicked!");
+ }
+ });
+ table.addItem(new Object[] { "entryString" + x, buttonLabel,
+ button, " " }, "entryID" + x);
+ }
+ return table;
+ }
+
+ @Override
+ protected String getTestDescription() {
+ return "Click button to focus, then click Table header. Blur event should arrive before the next variable change.";
+ }
+
+ @Override
+ protected Integer getTicketNumber() {
+ return 15294;
+ }
+
+}
diff --git a/uitest/src/com/vaadin/tests/components/table/TableBlurFocusTest.java b/uitest/src/com/vaadin/tests/components/table/TableBlurFocusTest.java
new file mode 100644
index 0000000000..e5d07abc22
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/table/TableBlurFocusTest.java
@@ -0,0 +1,64 @@
+/*
+ * 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.table;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertEquals;
+
+import java.util.Arrays;
+
+import org.junit.Test;
+import org.openqa.selenium.By;
+
+import com.vaadin.testbench.elements.ButtonElement;
+import com.vaadin.testbench.elements.TableElement;
+import com.vaadin.tests.tb3.MultiBrowserTest;
+
+public class TableBlurFocusTest extends MultiBrowserTest {
+
+ @Test
+ public void testBlurAndFocus() throws InterruptedException {
+ openTestURL();
+ waitForElementPresent(By.className("v-button"));
+
+ assertAnyLogText("1. variable change");
+ assertEquals("Unexpected column header,", "COLUMN2",
+ $(TableElement.class).first().getHeaderCell(1).getCaption());
+ assertEquals("Unexpected button caption,", "click to focus",
+ $(ButtonElement.class).first().getCaption());
+
+ $(ButtonElement.class).first().click();
+ assertAnyLogText("2. focus", "3. focus");
+
+ $(TableElement.class).first().getHeaderCell(1).click();
+ assertAnyLogText("3. blur", "4. blur");
+ }
+
+ private void assertAnyLogText(String... texts) {
+ assertThat(String.format(
+ "Correct log text was not found, expected any of %s",
+ Arrays.asList(texts)), logContainsAnyText(texts));
+ }
+
+ private boolean logContainsAnyText(String... texts) {
+ for (String text : texts) {
+ if (logContainsText(text)) {
+ return true;
+ }
+ }
+ return false;
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/table/TableInIframeRowClickScrollJumpTest.java b/uitest/src/com/vaadin/tests/components/table/TableInIframeRowClickScrollJumpTest.java
new file mode 100644
index 0000000000..074958d671
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/table/TableInIframeRowClickScrollJumpTest.java
@@ -0,0 +1,127 @@
+/*
+ * 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.table;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+
+import java.util.List;
+
+import org.junit.Test;
+import org.openqa.selenium.JavascriptExecutor;
+import org.openqa.selenium.WebElement;
+
+import com.vaadin.testbench.By;
+import com.vaadin.testbench.elements.ButtonElement;
+import com.vaadin.testbench.elements.TableElement;
+import com.vaadin.tests.tb3.MultiBrowserTest;
+
+/**
+ * For testing that UI scroll does not jump back to up when: 1. UI is in iframe
+ * 2. the window scrolled down 3. and table is clicked
+ *
+ * @since
+ * @author Vaadin Ltd
+ */
+public class TableInIframeRowClickScrollJumpTest extends MultiBrowserTest {
+
+ private static final String TEST_URL = "statictestfiles/TableInIframeRowClickScrollJumpTest.html";
+
+ @Test
+ public void testRowClicking_WhenScrolledDown_shouldMaintainScrollPosition()
+ throws InterruptedException {
+ System.out.println(">>>" + getBaseURL() + TEST_URL);
+
+ driver.get(getUrl());
+
+ // using non-standard way because of iframe
+ sleep(4000);
+
+ // make sure we are in the "main content"
+ driver.switchTo().defaultContent();
+ sleep(2000);
+ switchIntoIframe();
+
+ // using non-standard way because of iframe
+ waitForElementVisible(By.id("scroll-button"));
+
+ ButtonElement scrollbutton = $(ButtonElement.class).id("scroll-button");
+ scrollbutton.click();
+
+ // using non-standard way because of iframe
+ sleep(1000);
+
+ Long scrollPosition = getWindowsScrollPosition();
+
+ assertThat("Scroll position should be greater than 100 (it was "
+ + scrollPosition + ")", scrollPosition > 100);
+
+ TableElement table = $(TableElement.class).first();
+ table.getRow(13).getCell(0).click();
+
+ // using non-standard way because of iframe
+ sleep(1000);
+
+ Long scrollPosition2 = getWindowsScrollPosition();
+
+ assertThat("Scroll position should stay about the same. Old was "
+ + scrollPosition + " and new one " + scrollPosition2,
+ Math.abs(scrollPosition - scrollPosition2) < 10);
+ }
+
+ private String getUrl() {
+ String url;
+ // using non-standard way because of iframe
+ if (getBaseURL().charAt(getBaseURL().length() - 1) == '/') {
+ url = getBaseURL() + TEST_URL;
+ } else {
+ // this one is for gerrit's teamcity :(
+ url = getBaseURL() + '/' + TEST_URL;
+ }
+ return url;
+ }
+
+ public void switchIntoIframe() {
+ List<WebElement> frames = driver.findElements(By.tagName("iframe"));
+ assertThat("No frames was found", frames.size() > 0);
+ driver.switchTo().frame(frames.get(0));
+ }
+
+ private Long getWindowsScrollPosition() {
+ // measure scroll pos in the main window
+ driver.switchTo().defaultContent();
+
+ JavascriptExecutor executor = (JavascriptExecutor) driver;
+ Long value = (Long) executor
+ .executeScript("if (window.pageYOffset) return window.pageYOffset;else if (window.document.documentElement.scrollTop) return window.document.documentElement.scrollTop;else return window.document.body.scrollTop;");
+
+ // back to the iframe
+ switchIntoIframe();
+
+ return value;
+ }
+
+ @Override
+ // using non-standard way because of iframe
+ protected void closeApplication() {
+ if (driver != null) {
+ try {
+ driver.get(getUrl() + "?closeApplication");
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/table/TableSortingStopsWorkingOnChrome.java b/uitest/src/com/vaadin/tests/components/table/TableSortingStopsWorkingOnChrome.java
new file mode 100644
index 0000000000..23d0581e5a
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/table/TableSortingStopsWorkingOnChrome.java
@@ -0,0 +1,150 @@
+package com.vaadin.tests.components.table;
+
+import java.io.Serializable;
+
+import com.vaadin.annotations.Theme;
+import com.vaadin.data.util.BeanItemContainer;
+import com.vaadin.event.dd.DragAndDropEvent;
+import com.vaadin.event.dd.DropHandler;
+import com.vaadin.event.dd.acceptcriteria.AcceptAll;
+import com.vaadin.event.dd.acceptcriteria.AcceptCriterion;
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.tests.components.AbstractTestUI;
+import com.vaadin.ui.Table;
+import com.vaadin.ui.Table.ColumnReorderEvent;
+import com.vaadin.ui.Table.ColumnReorderListener;
+import com.vaadin.ui.Table.HeaderClickEvent;
+import com.vaadin.ui.Table.HeaderClickListener;
+import com.vaadin.ui.VerticalLayout;
+
+@Theme("valo")
+@SuppressWarnings("serial")
+public class TableSortingStopsWorkingOnChrome extends AbstractTestUI {
+
+ protected static final int ROW_COUNT = 100;
+
+ @Override
+ protected void setup(VaadinRequest request) {
+ VerticalLayout layout = new VerticalLayout();
+ layout.setSizeFull();
+
+ final Table table = new Table();
+ table.setColumnReorderingAllowed(true);
+ table.setSizeFull();
+
+ BeanItemContainer<TestItem> cont = new BeanItemContainer<TestItem>(
+ TestItem.class);
+
+ for (int i = 0; i < ROW_COUNT; i++) {
+ TestItem ti = new TestItem();
+ ti.setValue1("Value1_" + i);
+ ti.setValue2("Value2_" + (ROW_COUNT - i));
+ ti.setValue3("Value3_" + i);
+ ti.setValue4("Value4_" + (ROW_COUNT - i));
+ ti.setValue5("Value5_" + i);
+ cont.addBean(ti);
+ }
+
+ table.setContainerDataSource(cont);
+ table.setImmediate(true);
+ table.setSelectable(true);
+ table.setMultiSelect(false);
+
+ table.setPageLength(10);
+ table.setDragMode(Table.TableDragMode.ROW);
+
+ table.setDropHandler(new DropHandler() {
+ @Override
+ public void drop(DragAndDropEvent dragAndDropEvent) {
+
+ }
+
+ @Override
+ public AcceptCriterion getAcceptCriterion() {
+ return AcceptAll.get();
+ }
+ });
+
+ table.addColumnReorderListener(new ColumnReorderListener() {
+
+ @Override
+ public void columnReorder(ColumnReorderEvent event) {
+ System.out.println("columnReorder");
+ }
+ });
+
+ table.addHeaderClickListener(new HeaderClickListener() {
+
+ @Override
+ public void headerClick(HeaderClickEvent event) {
+ System.out.println("Header was clicked");
+ }
+ });
+
+ layout.addComponent(table);
+
+ addComponent(layout);
+ }
+
+ public class TestItem implements Serializable {
+ private static final long serialVersionUID = -745849615488792221L;
+
+ private String value1;
+ private String value2;
+ private String value3;
+ private String value4;
+ private String value5;
+
+ public String getValue1() {
+ return value1;
+ }
+
+ public void setValue1(String value1) {
+ this.value1 = value1;
+ }
+
+ public String getValue2() {
+ return value2;
+ }
+
+ public void setValue2(String value2) {
+ this.value2 = value2;
+ }
+
+ public String getValue3() {
+ return value3;
+ }
+
+ public void setValue3(String value3) {
+ this.value3 = value3;
+ }
+
+ public String getValue4() {
+ return value4;
+ }
+
+ public void setValue4(String value4) {
+ this.value4 = value4;
+ }
+
+ public String getValue5() {
+ return value5;
+ }
+
+ public void setValue5(String value5) {
+ this.value5 = value5;
+ }
+
+ }
+
+ @Override
+ protected String getTestDescription() {
+ return "After an indeterminate period of time sorting tables via clicking on the column header should not stop working on Chrome";
+ }
+
+ @Override
+ protected Integer getTicketNumber() {
+ return 14796;
+ }
+
+}
diff --git a/uitest/src/com/vaadin/tests/dd/DDInterrupt.java b/uitest/src/com/vaadin/tests/dd/DDInterrupt.java
new file mode 100644
index 0000000000..1939bbbce5
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/dd/DDInterrupt.java
@@ -0,0 +1,87 @@
+package com.vaadin.tests.dd;
+
+import com.vaadin.annotations.Widgetset;
+import com.vaadin.event.dd.DragAndDropEvent;
+import com.vaadin.event.dd.DropHandler;
+import com.vaadin.event.dd.TargetDetailsImpl;
+import com.vaadin.event.dd.acceptcriteria.AcceptAll;
+import com.vaadin.event.dd.acceptcriteria.AcceptCriterion;
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.tests.components.AbstractTestUI;
+import com.vaadin.tests.widgetset.TestingWidgetSet;
+import com.vaadin.ui.Button;
+import com.vaadin.ui.Button.ClickEvent;
+import com.vaadin.ui.CssLayout;
+import com.vaadin.ui.DragAndDropWrapper;
+import com.vaadin.ui.DragAndDropWrapper.DragStartMode;
+import com.vaadin.ui.Label;
+
+/**
+ * Test for interrupting drag-and-drop.
+ *
+ * @author Vaadin Ltd
+ */
+@Widgetset(TestingWidgetSet.NAME)
+public class DDInterrupt extends AbstractTestUI {
+
+ private SpacebarPanner sp;
+
+ @Override
+ protected void setup(VaadinRequest vaadinRequest) {
+ final CssLayout layout = new CssLayout();
+ layout.setWidth("500px");
+ layout.setHeight("500px");
+
+ addButton("Click to interrupt next drag.", new Button.ClickListener() {
+
+ @Override
+ public void buttonClick(ClickEvent event) {
+ sp.interruptNext();
+ }
+ });
+
+ final Label draggableLabel = new Label("Drag me");
+ draggableLabel.setId("draggable");
+
+ DragAndDropWrapper dndLayoutWrapper = new DragAndDropWrapper(layout);
+ addComponent(dndLayoutWrapper);
+
+ DragAndDropWrapper labelWrapper = new DragAndDropWrapper(draggableLabel);
+ draggableLabel.setSizeUndefined();
+ labelWrapper.setDragStartMode(DragStartMode.COMPONENT);
+ labelWrapper.setSizeUndefined();
+
+ layout.addComponent(labelWrapper);
+
+ dndLayoutWrapper.setDropHandler(new DropHandler() {
+
+ @Override
+ public AcceptCriterion getAcceptCriterion() {
+ return AcceptAll.get();
+ }
+
+ @Override
+ public void drop(DragAndDropEvent event) {
+ TargetDetailsImpl targetDetails = (TargetDetailsImpl) event
+ .getTargetDetails();
+ int x = targetDetails.getMouseEvent().getRelativeX();
+ int y = targetDetails.getMouseEvent().getRelativeY();
+
+ draggableLabel.setWidth(x, Unit.PIXELS);
+ draggableLabel.setHeight(y, Unit.PIXELS);
+ }
+ });
+
+ sp = SpacebarPanner.wrap(this);
+ }
+
+ @Override
+ protected Integer getTicketNumber() {
+ return 17163;
+ }
+
+ @Override
+ protected String getTestDescription() {
+ return "Hold space while clicking and dragging the label, or click the button before draggin the label. There should be no client-side exception.";
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/dd/DDInterruptTest.java b/uitest/src/com/vaadin/tests/dd/DDInterruptTest.java
new file mode 100644
index 0000000000..e078bc4665
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/dd/DDInterruptTest.java
@@ -0,0 +1,97 @@
+/*
+ * 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.dd;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.openqa.selenium.By;
+import org.openqa.selenium.WebDriver;
+import org.openqa.selenium.interactions.Actions;
+import org.openqa.selenium.support.ui.ExpectedCondition;
+
+import com.vaadin.testbench.elements.ButtonElement;
+import com.vaadin.testbench.elements.LabelElement;
+import com.vaadin.testbench.elements.UIElement;
+import com.vaadin.tests.tb3.MultiBrowserTest;
+
+/**
+ * Test for interrupting drag-and-drop.
+ *
+ * @author Vaadin Ltd
+ */
+public class DDInterruptTest extends MultiBrowserTest {
+
+ private UIElement ui;
+
+ @Override
+ public void setup() throws Exception {
+ super.setup();
+ openTestURL("debug");
+ ui = $(UIElement.class).first();
+ }
+
+ @Test
+ public void testRegularDragging() {
+ dragElement();
+ assertNoNotifications();
+ assertDragged(true);
+ }
+
+ @Test
+ public void testTriggeredDragging() {
+ $(ButtonElement.class).first().click();
+ waitUntilTriggered(true);
+
+ dragElement();
+
+ waitUntilTriggered(false);
+ assertNoNotifications();
+ assertDragged(false);
+ }
+
+ private void dragElement() {
+ LabelElement label = $(LabelElement.class).id("draggable");
+ new Actions(driver).moveToElement(label).clickAndHold()
+ .moveByOffset(400, 400).perform();
+ }
+
+ private void assertNoNotifications() {
+ Assert.assertEquals(
+ "Notification found when there should have been none,", 0,
+ findElements(By.className("v-Notification")).size());
+ }
+
+ private void assertDragged(boolean dragged) {
+ Assert.assertEquals("Unexpected drag state,", dragged ? 1 : 0,
+ findElements(By.className("v-ddwrapper-over-bottom")).size());
+ }
+
+ private void waitUntilTriggered(final boolean triggered) {
+ waitUntil(new ExpectedCondition<Boolean>() {
+
+ @Override
+ public Boolean apply(WebDriver arg0) {
+ return triggered == hasCssClass(ui, "triggered");
+ }
+
+ @Override
+ public String toString() {
+ return String.format("UI to %s stylename 'triggered'",
+ (triggered ? "get" : "lose"));
+ }
+ });
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/dd/SpacebarPanner.java b/uitest/src/com/vaadin/tests/dd/SpacebarPanner.java
new file mode 100644
index 0000000000..d6179066fb
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/dd/SpacebarPanner.java
@@ -0,0 +1,20 @@
+package com.vaadin.tests.dd;
+
+import com.vaadin.server.AbstractExtension;
+import com.vaadin.ui.UI;
+
+public class SpacebarPanner extends AbstractExtension {
+
+ private static final long serialVersionUID = -7712258690917457123L;
+
+ public static SpacebarPanner wrap(UI ui) {
+ SpacebarPanner panner = new SpacebarPanner();
+ panner.extend(ui);
+ return panner;
+ }
+
+ public void interruptNext() {
+ getState().enabled = !getState().enabled;
+ }
+
+}
diff --git a/uitest/src/com/vaadin/tests/declarative/DeclarativeEditor.java b/uitest/src/com/vaadin/tests/declarative/DeclarativeEditor.java
index 17942ee201..d62f71b513 100644
--- a/uitest/src/com/vaadin/tests/declarative/DeclarativeEditor.java
+++ b/uitest/src/com/vaadin/tests/declarative/DeclarativeEditor.java
@@ -15,11 +15,11 @@
*/
package com.vaadin.tests.declarative;
+import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import org.apache.commons.io.IOUtils;
-import org.apache.tools.ant.filters.StringInputStream;
import com.vaadin.annotations.Theme;
import com.vaadin.data.Property.ReadOnlyException;
@@ -87,7 +87,7 @@ public class DeclarativeEditor extends UI {
return;
}
- dc = Design.read(new StringInputStream(string), null);
+ dc = Design.read(new ByteArrayInputStream(string.getBytes()), null);
treeHolder.removeAllComponents();
treeHolder.addComponent(dc.getRootComponent());
diff --git a/uitest/src/com/vaadin/tests/push/PushPath.java b/uitest/src/com/vaadin/tests/push/PushPath.java
deleted file mode 100644
index 20771bd84f..0000000000
--- a/uitest/src/com/vaadin/tests/push/PushPath.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * 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.push;
-
-import com.vaadin.annotations.Push;
-import com.vaadin.server.VaadinRequest;
-import com.vaadin.shared.ui.ui.Transport;
-import com.vaadin.tests.components.AbstractTestUI;
-import com.vaadin.ui.Label;
-
-@Push(transport = Transport.WEBSOCKET)
-public class PushPath extends AbstractTestUI {
-
- public static final String PUSH_PATH_LABEL_ID = "push-path-label-id";
- public static final String PUSH_PATH_LABEL_TEXT = "Label by push";
-
- @Override
- protected void setup(VaadinRequest request) {
- // use only websockets
- getPushConfiguration().setFallbackTransport(Transport.WEBSOCKET);
-
- String pushPath = request.getService().getDeploymentConfiguration()
- .getPushPath();
- String transport = getPushConfiguration().getTransport().name();
- Label pushPathLabel = new Label(String.format(
- "Waiting for push from path '%s' using %s in 3 seconds.",
- pushPath, transport));
- addComponent(pushPathLabel);
-
- new PushThread().start();
- }
-
- public class PushThread extends Thread {
-
- @Override
- public void run() {
- try {
- Thread.sleep(3000);
- } catch (InterruptedException e) {
- }
- access(new Runnable() {
-
- @Override
- public void run() {
- Label pushLabel = new Label(PUSH_PATH_LABEL_TEXT);
- pushLabel.setId(PUSH_PATH_LABEL_ID);
- addComponent(pushLabel);
- }
- });
-
- }
- }
-
- @Override
- public Integer getTicketNumber() {
- return 14432;
- }
-
- @Override
- public String getDescription() {
- return "Push path should be configurable since some servers can't serve both websockets and long polling from same URL.";
- }
-
-}
diff --git a/uitest/src/com/vaadin/tests/util/ResizeTerrorizer.java b/uitest/src/com/vaadin/tests/util/ResizeTerrorizer.java
new file mode 100644
index 0000000000..f124305d8a
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/util/ResizeTerrorizer.java
@@ -0,0 +1,51 @@
+/*
+ * 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.util;
+
+import com.vaadin.tests.widgetset.client.ResizeTerrorizerControlConnector.ResizeTerorrizerState;
+import com.vaadin.ui.AbstractComponent;
+import com.vaadin.ui.Component;
+import com.vaadin.ui.VerticalLayout;
+
+public class ResizeTerrorizer extends VerticalLayout {
+ private final ResizeTerrorizerControl control;
+
+ public class ResizeTerrorizerControl extends AbstractComponent implements
+ Component {
+
+ public ResizeTerrorizerControl(Component target) {
+ getState().target = target;
+ }
+
+ @Override
+ protected ResizeTerorrizerState getState() {
+ return (ResizeTerorrizerState) super.getState();
+ }
+ }
+
+ public ResizeTerrorizer(Component target) {
+ target.setWidth("700px");
+ setSizeFull();
+ addComponent(target);
+ setExpandRatio(target, 1);
+ control = new ResizeTerrorizerControl(target);
+ addComponent(control);
+ }
+
+ public void setDefaultWidthOffset(int px) {
+ control.getState().defaultWidthOffset = px;
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/widgetset/client/ResizeTerrorizerControlConnector.java b/uitest/src/com/vaadin/tests/widgetset/client/ResizeTerrorizerControlConnector.java
new file mode 100644
index 0000000000..9fe037706b
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/widgetset/client/ResizeTerrorizerControlConnector.java
@@ -0,0 +1,157 @@
+/*
+ * 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.widgetset.client;
+
+import com.google.gwt.animation.client.AnimationScheduler;
+import com.google.gwt.animation.client.AnimationScheduler.AnimationCallback;
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.ClickHandler;
+import com.google.gwt.user.client.ui.Button;
+import com.google.gwt.user.client.ui.FlowPanel;
+import com.google.gwt.user.client.ui.IntegerBox;
+import com.google.gwt.user.client.ui.Label;
+import com.google.gwt.user.client.ui.RequiresResize;
+import com.vaadin.client.ui.AbstractComponentConnector;
+import com.vaadin.client.ui.PostLayoutListener;
+import com.vaadin.shared.AbstractComponentState;
+import com.vaadin.shared.Connector;
+import com.vaadin.shared.ui.Connect;
+import com.vaadin.tests.util.ResizeTerrorizer;
+
+@Connect(ResizeTerrorizer.ResizeTerrorizerControl.class)
+public class ResizeTerrorizerControlConnector extends
+ AbstractComponentConnector implements PostLayoutListener {
+
+ public static class ResizeTerorrizerState extends AbstractComponentState {
+ public Connector target;
+ public int defaultWidthOffset = 200;
+ }
+
+ public class ResizeTerrorizerControlPanel extends FlowPanel {
+ private Label results = new Label("Results");
+ private IntegerBox startWidth = new IntegerBox();
+ private IntegerBox endWidth = new IntegerBox();
+ private final Button terrorizeButton = new Button("Terrorize",
+ new ClickHandler() {
+ @Override
+ public void onClick(ClickEvent event) {
+ terrorize(startWidth.getValue(), endWidth.getValue(),
+ 1000);
+ }
+ });
+
+ public ResizeTerrorizerControlPanel() {
+ add(new Label("Start width"));
+ add(startWidth);
+
+ add(new Label("End width"));
+ add(endWidth);
+
+ add(terrorizeButton);
+ add(results);
+
+ startWidth.getElement().setId("terror-start-width");
+ endWidth.getElement().setId("terror-end-width");
+ terrorizeButton.getElement().setId("terror-button");
+ results.getElement().setId("terror-results");
+ }
+
+ private void showResults(String results) {
+ Integer temp = startWidth.getValue();
+ startWidth.setValue(endWidth.getValue());
+ endWidth.setValue(temp);
+
+ this.results.setText(results);
+ }
+ }
+
+ private void terrorize(final double startWidth, final double endWidth,
+ final double duration) {
+ final AbstractComponentConnector target = getTarget();
+
+ final AnimationScheduler scheduler = AnimationScheduler.get();
+ AnimationCallback callback = new AnimationCallback() {
+ double startTime = -1;
+ int frameCount = 0;
+
+ @Override
+ public void execute(double timestamp) {
+ frameCount++;
+
+ boolean done = false;
+ if (startTime == -1) {
+ startTime = timestamp;
+ }
+
+ double time = timestamp - startTime;
+ if (time > duration) {
+ time = duration;
+ done = true;
+ }
+
+ double progress = time / duration;
+ double widthToSet = startWidth + (endWidth - startWidth)
+ * progress;
+
+ // TODO Optionally inform LayoutManager as well
+ target.getWidget().setWidth(widthToSet + "px");
+ if (target.getWidget() instanceof RequiresResize) {
+ ((RequiresResize) target.getWidget()).onResize();
+ }
+
+ if (!done) {
+ scheduler.requestAnimationFrame(this);
+ } else {
+ double fps = Math.round(frameCount / (duration / 1000));
+ String results = frameCount + " frames, " + fps + " fps";
+
+ getWidget().showResults(results);
+ }
+ }
+ };
+ scheduler.requestAnimationFrame(callback);
+ }
+
+ private AbstractComponentConnector getTarget() {
+ return (AbstractComponentConnector) getState().target;
+ }
+
+ @Override
+ public ResizeTerorrizerState getState() {
+ return (ResizeTerorrizerState) super.getState();
+ }
+
+ @Override
+ public ResizeTerrorizerControlPanel getWidget() {
+ return (ResizeTerrorizerControlPanel) super.getWidget();
+ }
+
+ @Override
+ protected ResizeTerrorizerControlPanel createWidget() {
+ return new ResizeTerrorizerControlPanel();
+ }
+
+ @Override
+ public void postLayout() {
+ if (getWidget().startWidth.getValue() == null) {
+ int width = getTarget().getWidget().getElement().getOffsetWidth();
+ getWidget().startWidth.setValue(width);
+ getWidget().endWidth
+ .setValue(width + getState().defaultWidthOffset);
+ }
+ }
+
+}
diff --git a/uitest/src/com/vaadin/tests/widgetset/client/dd/SpacebarPannerConnector.java b/uitest/src/com/vaadin/tests/widgetset/client/dd/SpacebarPannerConnector.java
new file mode 100644
index 0000000000..e13dd5030b
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/widgetset/client/dd/SpacebarPannerConnector.java
@@ -0,0 +1,125 @@
+package com.vaadin.tests.widgetset.client.dd;
+
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import com.google.gwt.dom.client.Element;
+import com.google.gwt.dom.client.NativeEvent;
+import com.google.gwt.event.dom.client.KeyCodes;
+import com.google.gwt.user.client.Event;
+import com.google.gwt.user.client.Event.NativePreviewEvent;
+import com.google.gwt.user.client.Event.NativePreviewHandler;
+import com.vaadin.client.ServerConnector;
+import com.vaadin.client.annotations.OnStateChange;
+import com.vaadin.client.extensions.AbstractExtensionConnector;
+import com.vaadin.client.ui.VUI;
+import com.vaadin.client.ui.dd.VDragAndDropManager;
+import com.vaadin.client.ui.ui.UIConnector;
+import com.vaadin.shared.ui.Connect;
+
+@Connect(com.vaadin.tests.dd.SpacebarPanner.class)
+public class SpacebarPannerConnector extends AbstractExtensionConnector {
+
+ Logger logger = Logger.getLogger(SpacebarPannerConnector.class
+ .getSimpleName());
+
+ private boolean trigger = false;
+ private VUI vui;
+ private boolean first = true;
+
+ @Override
+ protected void extend(ServerConnector target) {
+ UIConnector uic = (UIConnector) target;
+ vui = uic.getWidget();
+ Event.sinkEvents(vui.getElement(), Event.MOUSEEVENTS | Event.KEYEVENTS);
+ Event.addNativePreviewHandler(createNativePreviewHandler());
+ }
+
+ @OnStateChange("enabled")
+ private void trigger() {
+ if (first) {
+ // ignore initial state change
+ first = false;
+ } else {
+ trigger = true;
+ vui.addStyleName("triggered");
+ }
+ }
+
+ private NativePreviewHandler createNativePreviewHandler() {
+ return new NativePreviewHandler() {
+
+ private boolean spacebarDown = false;
+ private boolean shouldPan = false;
+ private boolean mouseDown = false;
+
+ private int lastMouseX;
+ private int lastMouseY;
+
+ @Override
+ public void onPreviewNativeEvent(NativePreviewEvent event) {
+ NativeEvent ne = event.getNativeEvent();
+ int type = event.getTypeInt();
+
+ switch (type) {
+ case Event.ONKEYDOWN:
+ if (ne.getKeyCode() == KeyCodes.KEY_SPACE) {
+ event.cancel();
+ ne.preventDefault();
+ ne.stopPropagation();
+ spacebarDown = true;
+ break;
+ }
+ case Event.ONKEYUP:
+ if (ne.getKeyCode() == KeyCodes.KEY_SPACE) {
+ spacebarDown = false;
+ }
+ break;
+ case Event.ONMOUSEDOWN:
+ logger.log(Level.INFO, "Drag started");
+ lastMouseX = ne.getClientX();
+ lastMouseY = ne.getClientY();
+
+ shouldPan = spacebarDown || trigger;
+ mouseDown = true;
+ break;
+
+ case Event.ONMOUSEUP:
+ shouldPan = false || trigger;
+ mouseDown = false;
+ break;
+
+ case Event.ONMOUSEMOVE:
+ if (mouseDown && shouldPan) {
+ logger.log(Level.INFO, "In mousemove: mouseDown:"
+ + mouseDown + ", shouldPan: " + shouldPan);
+ trigger = false;
+ vui.removeStyleName("triggered");
+
+ logger.log(Level.INFO, "Panning!");
+ int currentClientX = ne.getClientX();
+ int currentClientY = ne.getClientY();
+
+ int deltaX = lastMouseX - currentClientX;
+ int deltaY = lastMouseY - currentClientY;
+ lastMouseX = currentClientX;
+ lastMouseY = currentClientY;
+
+ // this causes #17163
+ VDragAndDropManager.get().interruptDrag();
+
+ Element uiElement = vui.getElement();
+ int top = uiElement.getScrollTop();
+ int left = uiElement.getScrollLeft();
+
+ uiElement.setScrollTop(top + deltaY);
+ uiElement.setScrollLeft(left + deltaX);
+ }
+
+ default:
+ break;
+ }
+ }
+ };
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/widgetset/rebind/TestWidgetRegistryGenerator.java b/uitest/src/com/vaadin/tests/widgetset/rebind/TestWidgetRegistryGenerator.java
index 1bdbba2c36..c7b29e271b 100644
--- a/uitest/src/com/vaadin/tests/widgetset/rebind/TestWidgetRegistryGenerator.java
+++ b/uitest/src/com/vaadin/tests/widgetset/rebind/TestWidgetRegistryGenerator.java
@@ -136,6 +136,9 @@ public class TestWidgetRegistryGenerator extends Generator {
} else if (!widgetType.getPackage().getName()
.startsWith(TestWidgetConnector.class.getPackage().getName())) {
return false;
+ } else if (widgetType.getEnclosingType() != null
+ && !widgetType.isStatic()) {
+ return false;
}
return true;