summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/com/vaadin/data/util/ContainerHierarchicalWrapper.java3
-rw-r--r--src/com/vaadin/event/dd/acceptcriteria/SourceIs.java27
-rw-r--r--src/com/vaadin/terminal/gwt/client/ApplicationConnection.java10
-rw-r--r--src/com/vaadin/terminal/gwt/client/BrowserInfo.java64
-rw-r--r--src/com/vaadin/terminal/gwt/client/CSSRule.java4
-rw-r--r--src/com/vaadin/terminal/gwt/client/ComponentDetailMap.java1
-rw-r--r--src/com/vaadin/terminal/gwt/client/ComputedStyle.java1
-rw-r--r--src/com/vaadin/terminal/gwt/client/Util.java13
-rw-r--r--src/com/vaadin/terminal/gwt/client/VBrowserDetails.java127
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/FocusableScrollPanel.java7
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/TouchScrollDelegate.java5
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/button/ButtonConnector.java6
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/button/ButtonState.java30
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/button/VButton.java4
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/datefield/VDateFieldCalendar.java7
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/nativebutton/NativeButtonConnector.java6
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/nativebutton/VNativeButton.java5
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/notification/VNotification.java7
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/root/VRoot.java1
-rw-r--r--src/com/vaadin/terminal/gwt/server/AbstractApplicationPortlet.java13
-rw-r--r--src/com/vaadin/terminal/gwt/server/AbstractApplicationServlet.java13
-rw-r--r--src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java15
-rw-r--r--src/com/vaadin/terminal/gwt/server/AbstractWebApplicationContext.java30
-rw-r--r--src/com/vaadin/terminal/gwt/server/RequestTimer.java55
-rw-r--r--src/com/vaadin/ui/Button.java29
-rw-r--r--src/com/vaadin/ui/Table.java2
-rw-r--r--tests/client-side/com/vaadin/terminal/gwt/client/TestVBrowserDetailsUserAgentParser.java120
-rw-r--r--tests/server-side/com/vaadin/tests/server/SourceFileChecker.java42
-rw-r--r--tests/server-side/com/vaadin/tests/server/component/tree/TestHasChildren.java25
-rw-r--r--tests/test.xml2
-rw-r--r--tests/testbench/com/vaadin/tests/components/TouchScrollables.java173
-rw-r--r--tests/testbench/com/vaadin/tests/components/button/ButtonHtml.html47
-rw-r--r--tests/testbench/com/vaadin/tests/components/button/ButtonHtml.java39
-rw-r--r--tests/testbench/com/vaadin/tests/components/combobox/GridLayoutComboBoxZoomOut.java62
-rw-r--r--tests/testbench/com/vaadin/tests/components/datefield/InlineDateFields.java4
-rw-r--r--tests/testbench/com/vaadin/tests/components/datefield/InlineDateFieldsHiddenOnStart.html26
-rw-r--r--tests/testbench/com/vaadin/tests/components/nativebutton/NativeButtonHtml.html47
-rw-r--r--tests/testbench/com/vaadin/tests/components/nativebutton/NativeButtonHtml.java41
-rw-r--r--tests/testbench/com/vaadin/tests/components/table/TableWithContainerRequiringEqualsForItemId.html97
-rw-r--r--tests/testbench/com/vaadin/tests/components/table/TableWithContainerRequiringEqualsForItemId.java128
-rw-r--r--tests/testbench/com/vaadin/tests/dd/NotPaintedAcceptSource.html71
-rw-r--r--tests/testbench/com/vaadin/tests/dd/NotPaintedAcceptSource.java91
-rw-r--r--tests/testbench/com/vaadin/tests/layouts/layouttester/LayoutTesterApplication.html2
43 files changed, 1335 insertions, 167 deletions
diff --git a/src/com/vaadin/data/util/ContainerHierarchicalWrapper.java b/src/com/vaadin/data/util/ContainerHierarchicalWrapper.java
index 91950f5d4f..9159fa358b 100644
--- a/src/com/vaadin/data/util/ContainerHierarchicalWrapper.java
+++ b/src/com/vaadin/data/util/ContainerHierarchicalWrapper.java
@@ -294,7 +294,8 @@ public class ContainerHierarchicalWrapper implements Container.Hierarchical,
return ((Container.Hierarchical) container).hasChildren(itemId);
}
- return children.get(itemId) != null;
+ LinkedList<Object> list = children.get(itemId);
+ return (list != null && !list.isEmpty());
}
/*
diff --git a/src/com/vaadin/event/dd/acceptcriteria/SourceIs.java b/src/com/vaadin/event/dd/acceptcriteria/SourceIs.java
index 8562bc70ec..0d29e9a327 100644
--- a/src/com/vaadin/event/dd/acceptcriteria/SourceIs.java
+++ b/src/com/vaadin/event/dd/acceptcriteria/SourceIs.java
@@ -6,6 +6,9 @@
*/
package com.vaadin.event.dd.acceptcriteria;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
import com.vaadin.event.TransferableImpl;
import com.vaadin.event.dd.DragAndDropEvent;
import com.vaadin.terminal.PaintException;
@@ -22,27 +25,39 @@ import com.vaadin.ui.Component;
@SuppressWarnings("serial")
@ClientCriterion(VDragSourceIs.class)
public class SourceIs extends ClientSideCriterion {
+ private static final Logger logger = Logger.getLogger(SourceIs.class
+ .getName());
- private Component[] component;
+ private Component[] components;
public SourceIs(Component... component) {
- this.component = component;
+ components = component;
}
@Override
public void paintContent(PaintTarget target) throws PaintException {
super.paintContent(target);
- target.addAttribute("c", component.length);
- for (int i = 0; i < component.length; i++) {
- target.addAttribute("component" + i, component[i]);
+ int paintedComponents = 0;
+ for (int i = 0; i < components.length; i++) {
+ Component c = components[i];
+ if (c.getApplication() != null) {
+ target.addAttribute("component" + paintedComponents++, c);
+ } else {
+ logger.log(
+ Level.WARNING,
+ "SourceIs component {0} at index {1} is not attached to the component hierachy and will thus be ignored",
+ new Object[] { c.getClass().getName(),
+ Integer.valueOf(i) });
+ }
}
+ target.addAttribute("c", paintedComponents);
}
public boolean accept(DragAndDropEvent dragEvent) {
if (dragEvent.getTransferable() instanceof TransferableImpl) {
Component sourceComponent = ((TransferableImpl) dragEvent
.getTransferable()).getSourceComponent();
- for (Component c : component) {
+ for (Component c : components) {
if (c == sourceComponent) {
return true;
}
diff --git a/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java b/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java
index be6d578112..739c232a72 100644
--- a/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java
+++ b/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java
@@ -272,7 +272,7 @@ public class ApplicationConnection {
ap.@com.vaadin.terminal.gwt.client.ApplicationConnection::lastProcessingTime,
ap.@com.vaadin.terminal.gwt.client.ApplicationConnection::totalProcessingTime
];
- pd = pd.concat(ap.@com.vaadin.terminal.gwt.client.ApplicationConnection::testBenchServerStatus);
+ pd = pd.concat(ap.@com.vaadin.terminal.gwt.client.ApplicationConnection::serverTimingInfo);
return pd;
});
@@ -698,7 +698,7 @@ public class ApplicationConnection {
* servicing the session so far. These values are always one request behind,
* since they cannot be measured before the request is finished.
*/
- private ValueMap testBenchServerStatus;
+ private ValueMap serverTimingInfo;
static final int MAX_CSS_WAITS = 100;
@@ -1037,10 +1037,10 @@ public class ApplicationConnection {
handleUIDLDuration.logDuration(
" * Handling type mappings from server completed", 10);
/*
- * Hook for TestBench to get details about server status
+ * Hook for e.g. TestBench to get details about server peformance
*/
- if (json.containsKey("tbss")) {
- testBenchServerStatus = json.getValueMap("tbss");
+ if (json.containsKey("timings")) {
+ serverTimingInfo = json.getValueMap("timings");
}
Command c = new Command() {
diff --git a/src/com/vaadin/terminal/gwt/client/BrowserInfo.java b/src/com/vaadin/terminal/gwt/client/BrowserInfo.java
index ef1dc481b1..064f175301 100644
--- a/src/com/vaadin/terminal/gwt/client/BrowserInfo.java
+++ b/src/com/vaadin/terminal/gwt/client/BrowserInfo.java
@@ -28,6 +28,8 @@ public class BrowserInfo {
private static final String OS_WINDOWS = "win";
private static final String OS_LINUX = "lin";
private static final String OS_MACOSX = "mac";
+ private static final String OS_ANDROID = "android";
+ private static final String OS_IOS = "ios";
private static BrowserInfo instance;
@@ -167,13 +169,18 @@ public class BrowserInfo {
if (osClass != null) {
cssClass = cssClass + " " + prefix + osClass;
}
+
}
return cssClass;
}
private String getOperatingSystemClass() {
- if (browserDetails.isWindows()) {
+ if (browserDetails.isAndroid()) {
+ return OS_ANDROID;
+ } else if (browserDetails.isIOS()) {
+ return OS_IOS;
+ } else if (browserDetails.isWindows()) {
return OS_WINDOWS;
} else if (browserDetails.isLinux()) {
return OS_LINUX;
@@ -312,4 +319,59 @@ public class BrowserInfo {
&& Util.getNativeScrollbarSize() > 0;
}
+ /**
+ * Checks if the browser is run on iOS
+ *
+ * @return true if the browser is run on iOS, false otherwise
+ */
+ public boolean isIOS() {
+ return browserDetails.isIOS();
+ }
+
+ /**
+ * Checks if the browser is run on Android
+ *
+ * @return true if the browser is run on Android, false otherwise
+ */
+ public boolean isAndroid() {
+ return browserDetails.isAndroid();
+ }
+
+ /**
+ * Checks if the browser is capable of handling scrolling natively or if a
+ * touch scroll helper is needed for scrolling.
+ *
+ * @return true if browser needs a touch scroll helper, false if the browser
+ * can handle scrolling natively
+ */
+ public boolean requiresTouchScrollDelegate() {
+ if (!isTouchDevice()) {
+ return false;
+ }
+
+ if (isAndroid() && isWebkit() && getWebkitVersion() < 534) {
+ return true;
+ }
+ // if (isIOS() && isWebkit() && getWebkitVersion() < ???) {
+ // return true;
+ // }
+
+ return false;
+ }
+
+ /**
+ * Tests if this is an Android devices with a broken scrollTop
+ * implementation
+ *
+ * @return true if scrollTop cannot be trusted on this device, false
+ * otherwise
+ */
+ public boolean isAndroidWithBrokenScrollTop() {
+ return isAndroid()
+ && (getOperatingSystemMajorVersion() == 3 || getOperatingSystemMajorVersion() == 4);
+ }
+
+ private int getOperatingSystemMajorVersion() {
+ return browserDetails.getOperatingSystemMajorVersion();
+ }
}
diff --git a/src/com/vaadin/terminal/gwt/client/CSSRule.java b/src/com/vaadin/terminal/gwt/client/CSSRule.java
index 4d9196c8d6..c36b0611e8 100644
--- a/src/com/vaadin/terminal/gwt/client/CSSRule.java
+++ b/src/com/vaadin/terminal/gwt/client/CSSRule.java
@@ -33,6 +33,7 @@ public class CSSRule {
for(var i = 0; i < sheets.length; i++) {
var sheet = sheets[i];
if(sheet.href && sheet.href.indexOf("VAADIN/themes")>-1) {
+ // $entry not needed as function is not exported
this.@com.vaadin.terminal.gwt.client.CSSRule::rules = @com.vaadin.terminal.gwt.client.CSSRule::searchForRule(Lcom/google/gwt/core/client/JavaScriptObject;Ljava/lang/String;Z)(sheet, selector, deep);
return;
}
@@ -58,6 +59,7 @@ public class CSSRule {
// IE handles imported sheet differently
if(deep && sheet.imports && sheet.imports.length > 0) {
for(var i=0; i < sheet.imports.length; i++) {
+ // $entry not needed as function is not exported
var imports = @com.vaadin.terminal.gwt.client.CSSRule::searchForRule(Lcom/google/gwt/core/client/JavaScriptObject;Ljava/lang/String;Z)(sheet.imports[i], selector, deep);
allMatches.concat(imports);
}
@@ -83,6 +85,7 @@ public class CSSRule {
}
} else if(deep && r.type == 3) {
// Search @import stylesheet
+ // $entry not needed as function is not exported
var imports = @com.vaadin.terminal.gwt.client.CSSRule::searchForRule(Lcom/google/gwt/core/client/JavaScriptObject;Ljava/lang/String;Z)(r.styleSheet, selector, deep);
allMatches = allMatches.concat(imports);
}
@@ -102,6 +105,7 @@ public class CSSRule {
/*-{
var j = this.@com.vaadin.terminal.gwt.client.CSSRule::rules.length;
for(var i=0; i<j; i++) {
+ // $entry not needed as function is not exported
var value = this.@com.vaadin.terminal.gwt.client.CSSRule::rules[i].style[propertyName];
if(value)
return value;
diff --git a/src/com/vaadin/terminal/gwt/client/ComponentDetailMap.java b/src/com/vaadin/terminal/gwt/client/ComponentDetailMap.java
index 3405d838a7..dfbcf9d38b 100644
--- a/src/com/vaadin/terminal/gwt/client/ComponentDetailMap.java
+++ b/src/com/vaadin/terminal/gwt/client/ComponentDetailMap.java
@@ -62,6 +62,7 @@ final class ComponentDetailMap extends JavaScriptObject {
private final native void fillWithValues(Collection<ComponentDetail> list)
/*-{
for(var key in this) {
+ // $entry not needed as function is not exported
list.@java.util.Collection::add(Ljava/lang/Object;)(this[key]);
}
}-*/;
diff --git a/src/com/vaadin/terminal/gwt/client/ComputedStyle.java b/src/com/vaadin/terminal/gwt/client/ComputedStyle.java
index bedb217c63..29b02b4dde 100644
--- a/src/com/vaadin/terminal/gwt/client/ComputedStyle.java
+++ b/src/com/vaadin/terminal/gwt/client/ComputedStyle.java
@@ -179,6 +179,7 @@ public class ComputedStyle {
if (isNaN(number))
return null;
else
+ // $entry not needed as function is not exported
return @java.lang.Integer::valueOf(I)(number);
}-*/;
diff --git a/src/com/vaadin/terminal/gwt/client/Util.java b/src/com/vaadin/terminal/gwt/client/Util.java
index bfe63caefd..c392a0ba9c 100644
--- a/src/com/vaadin/terminal/gwt/client/Util.java
+++ b/src/com/vaadin/terminal/gwt/client/Util.java
@@ -978,6 +978,19 @@ public class Util {
*/
final Element target = getElementFromPoint(touch.getClientX(),
touch.getClientY());
+
+ /*
+ * Fixes infocusable form fields in Safari of iOS 5.x and some Android
+ * browsers.
+ */
+ Widget targetWidget = findWidget(target, null);
+ if (targetWidget instanceof com.google.gwt.user.client.ui.Focusable) {
+ final com.google.gwt.user.client.ui.Focusable toBeFocusedWidget = (com.google.gwt.user.client.ui.Focusable) targetWidget;
+ toBeFocusedWidget.setFocus(true);
+ } else if (targetWidget instanceof Focusable) {
+ ((Focusable) targetWidget).focus();
+ }
+
Scheduler.get().scheduleDeferred(new ScheduledCommand() {
public void execute() {
try {
diff --git a/src/com/vaadin/terminal/gwt/client/VBrowserDetails.java b/src/com/vaadin/terminal/gwt/client/VBrowserDetails.java
index 89e106f063..6e0417149c 100644
--- a/src/com/vaadin/terminal/gwt/client/VBrowserDetails.java
+++ b/src/com/vaadin/terminal/gwt/client/VBrowserDetails.java
@@ -31,14 +31,19 @@ public class VBrowserDetails implements Serializable {
private boolean isOpera = false;
private boolean isIE = false;
- private boolean isWindows = false;
- private boolean isMacOSX = false;
- private boolean isLinux = false;
+ private OperatingSystem os = OperatingSystem.UNKNOWN;
+
+ public enum OperatingSystem {
+ UNKNOWN, WINDOWS, MACOSX, LINUX, IOS, ANDROID;
+ }
private float browserEngineVersion = -1;
private int browserMajorVersion = -1;
private int browserMinorVersion = -1;
+ private int osMajorVersion = -1;
+ private int osMinorVersion = -1;
+
/**
* Create an instance based on the given user agent.
*
@@ -122,14 +127,80 @@ public class VBrowserDetails implements Serializable {
// Operating system
if (userAgent.contains("windows ")) {
- isWindows = true;
+ os = OperatingSystem.WINDOWS;
} else if (userAgent.contains("linux")) {
- isLinux = true;
+ if (userAgent.contains("android")) {
+ os = OperatingSystem.ANDROID;
+ parseAndroidVersion(userAgent);
+ } else {
+ os = OperatingSystem.LINUX;
+
+ }
} else if (userAgent.contains("macintosh")
|| userAgent.contains("mac osx")
|| userAgent.contains("mac os x")) {
- isMacOSX = true;
+ if (userAgent.contains("ipad") || userAgent.contains("ipod")
+ || userAgent.contains("iphone")) {
+ os = OperatingSystem.IOS;
+ parseIOSVersion(userAgent);
+ } else {
+ os = OperatingSystem.MACOSX;
+ }
+ }
+ }
+
+ private void parseAndroidVersion(String userAgent) {
+ // Android 5.1;
+ if (!userAgent.contains("android")) {
+ return;
+ }
+
+ String osVersionString = safeSubstring(userAgent,
+ userAgent.indexOf("android ") + "android ".length(),
+ userAgent.length());
+ osVersionString = safeSubstring(osVersionString, 0,
+ osVersionString.indexOf(";"));
+ String[] parts = osVersionString.split("\\.");
+ parseOsVersion(parts);
+ }
+
+ private void parseIOSVersion(String userAgent) {
+ // OS 5_1 like Mac OS X
+ if (!userAgent.contains("os ") || !userAgent.contains(" like mac")) {
+ return;
+ }
+
+ String osVersionString = safeSubstring(userAgent,
+ userAgent.indexOf("os ") + 3, userAgent.indexOf(" like mac"));
+ String[] parts = osVersionString.split("_");
+ parseOsVersion(parts);
+ }
+
+ private void parseOsVersion(String[] parts) {
+ osMajorVersion = -1;
+ osMinorVersion = -1;
+
+ if (parts.length >= 1) {
+ try {
+ osMajorVersion = Integer.parseInt(parts[0]);
+ } catch (Exception e) {
+ }
+ }
+ if (parts.length >= 2) {
+ try {
+ osMinorVersion = Integer.parseInt(parts[1]);
+ } catch (Exception e) {
+ }
+ // Some Androids report version numbers as "2.1-update1"
+ if (osMinorVersion == -1 && parts[1].contains("-")) {
+ try {
+ osMinorVersion = Integer.parseInt(parts[1].substring(0,
+ parts[1].indexOf('-')));
+ } catch (Exception ee) {
+ }
+ }
}
+
}
private void parseVersionString(String versionString) {
@@ -306,7 +377,7 @@ public class VBrowserDetails implements Serializable {
* @return true if run on Windows, false otherwise
*/
public boolean isWindows() {
- return isWindows;
+ return os == OperatingSystem.WINDOWS;
}
/**
@@ -315,7 +386,7 @@ public class VBrowserDetails implements Serializable {
* @return true if run on Mac OSX, false otherwise
*/
public boolean isMacOSX() {
- return isMacOSX;
+ return os == OperatingSystem.MACOSX;
}
/**
@@ -324,7 +395,45 @@ public class VBrowserDetails implements Serializable {
* @return true if run on Linux, false otherwise
*/
public boolean isLinux() {
- return isLinux;
+ return os == OperatingSystem.LINUX;
+ }
+
+ /**
+ * Tests if the browser is run on Android.
+ *
+ * @return true if run on Android, false otherwise
+ */
+ public boolean isAndroid() {
+ return os == OperatingSystem.ANDROID;
+ }
+
+ /**
+ * Tests if the browser is run in iOS.
+ *
+ * @return true if run in iOS, false otherwise
+ */
+ public boolean isIOS() {
+ return os == OperatingSystem.IOS;
+ }
+
+ /**
+ * Returns the major version of the operating system. Currently only
+ * supported for mobile devices (iOS/Android)
+ *
+ * @return The major version or -1 if unknown
+ */
+ public int getOperatingSystemMajorVersion() {
+ return osMajorVersion;
+ }
+
+ /**
+ * Returns the minor version of the operating system. Currently only
+ * supported for mobile devices (iOS/Android)
+ *
+ * @return The minor version or -1 if unknown
+ */
+ public int getOperatingSystemMinorVersion() {
+ return osMinorVersion;
}
/**
diff --git a/src/com/vaadin/terminal/gwt/client/ui/FocusableScrollPanel.java b/src/com/vaadin/terminal/gwt/client/ui/FocusableScrollPanel.java
index 533d6a78ae..62697c4d98 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/FocusableScrollPanel.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/FocusableScrollPanel.java
@@ -153,7 +153,7 @@ public class FocusableScrollPanel extends SimpleFocusablePanel implements
* the new vertical scroll position, in pixels
*/
public void setScrollPosition(int position) {
- if (isAndroidWithBrokenScrollTop()) {
+ if (BrowserInfo.get().isAndroidWithBrokenScrollTop()) {
ArrayList<com.google.gwt.dom.client.Element> elements = TouchScrollDelegate
.getElements(getElement());
for (com.google.gwt.dom.client.Element el : elements) {
@@ -167,11 +167,6 @@ public class FocusableScrollPanel extends SimpleFocusablePanel implements
}
}
- private boolean isAndroidWithBrokenScrollTop() {
- return BrowserInfo.getBrowserString().contains("Android 3")
- || BrowserInfo.getBrowserString().contains("Android 4");
- }
-
public void onScroll(ScrollEvent event) {
Scheduler.get().scheduleDeferred(new ScheduledCommand() {
public void execute() {
diff --git a/src/com/vaadin/terminal/gwt/client/ui/TouchScrollDelegate.java b/src/com/vaadin/terminal/gwt/client/ui/TouchScrollDelegate.java
index d4b59ed23a..8b2248aff6 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/TouchScrollDelegate.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/TouchScrollDelegate.java
@@ -83,9 +83,8 @@ public class TouchScrollDelegate implements NativePreviewHandler {
private static TouchScrollDelegate activeScrollDelegate;
- private static final boolean androidWithBrokenScrollTop = BrowserInfo
- .getBrowserString().contains("Android 3")
- || BrowserInfo.getBrowserString().contains("Android 4");
+ private static final boolean androidWithBrokenScrollTop = BrowserInfo.get()
+ .isAndroidWithBrokenScrollTop();
public TouchScrollDelegate(Element... elements) {
scrollableElements = elements;
diff --git a/src/com/vaadin/terminal/gwt/client/ui/button/ButtonConnector.java b/src/com/vaadin/terminal/gwt/client/ui/button/ButtonConnector.java
index 62a5e8ac8b..a555ecd392 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/button/ButtonConnector.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/button/ButtonConnector.java
@@ -57,7 +57,11 @@ public class ButtonConnector extends AbstractComponentConnector implements
blurHandlerRegistration = EventHelper.updateBlurHandler(this,
blurHandlerRegistration);
// Set text
- getWidget().setText(getState().getCaption());
+ if (getState().isHtmlContentAllowed()) {
+ getWidget().setHtml(getState().getCaption());
+ } else {
+ getWidget().setText(getState().getCaption());
+ }
// handle error
if (null != getState().getErrorMessage()) {
diff --git a/src/com/vaadin/terminal/gwt/client/ui/button/ButtonState.java b/src/com/vaadin/terminal/gwt/client/ui/button/ButtonState.java
index f26cdae0c6..fdc053b3ae 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/button/ButtonState.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/button/ButtonState.java
@@ -17,6 +17,10 @@ import com.vaadin.ui.Button;
public class ButtonState extends ComponentState {
private boolean disableOnClick = false;
private int clickShortcutKeyCode = 0;
+ /**
+ * If caption should be rendered in HTML
+ */
+ private boolean htmlContentAllowed = false;
/**
* Checks whether the button should be disabled on the client side on next
@@ -62,4 +66,30 @@ public class ButtonState extends ComponentState {
this.clickShortcutKeyCode = clickShortcutKeyCode;
}
+ /**
+ * Set whether the caption text is rendered as HTML or not. You might need
+ * to retheme button to allow higher content than the original text style.
+ *
+ * If set to true, the captions are passed to the browser as html and the
+ * developer is responsible for ensuring no harmful html is used. If set to
+ * false, the content is passed to the browser as plain text.
+ *
+ * @param htmlContentAllowed
+ * <code>true</code> if caption is rendered as HTML,
+ * <code>false</code> otherwise
+ */
+ public void setHtmlContentAllowed(boolean htmlContentAllowed) {
+ this.htmlContentAllowed = htmlContentAllowed;
+ }
+
+ /**
+ * Return HTML rendering setting.
+ *
+ * @return <code>true</code> if the caption text is to be rendered as HTML,
+ * <code>false</code> otherwise
+ */
+ public boolean isHtmlContentAllowed() {
+ return htmlContentAllowed;
+ }
+
}
diff --git a/src/com/vaadin/terminal/gwt/client/ui/button/VButton.java b/src/com/vaadin/terminal/gwt/client/ui/button/VButton.java
index f7d73d3b5e..e5e7dbba8b 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/button/VButton.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/button/VButton.java
@@ -98,6 +98,10 @@ public class VButton extends FocusWidget implements ClickHandler {
captionElement.setInnerText(text);
}
+ public void setHtml(String html) {
+ captionElement.setInnerHTML(html);
+ }
+
@SuppressWarnings("deprecation")
@Override
/*
diff --git a/src/com/vaadin/terminal/gwt/client/ui/datefield/VDateFieldCalendar.java b/src/com/vaadin/terminal/gwt/client/ui/datefield/VDateFieldCalendar.java
index 21e0e0820d..84b3c678eb 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/datefield/VDateFieldCalendar.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/datefield/VDateFieldCalendar.java
@@ -45,6 +45,13 @@ public class VDateFieldCalendar extends VDateField {
*/
@SuppressWarnings("deprecation")
protected void updateValueFromPanel() {
+
+ // If field is invisible at the beginning, client can still be null when
+ // this function is called.
+ if (getClient() == null) {
+ return;
+ }
+
Date date2 = calendarPanel.getDate();
Date currentDate = getCurrentDate();
if (currentDate == null || date2.getTime() != currentDate.getTime()) {
diff --git a/src/com/vaadin/terminal/gwt/client/ui/nativebutton/NativeButtonConnector.java b/src/com/vaadin/terminal/gwt/client/ui/nativebutton/NativeButtonConnector.java
index 801c405826..84d3b73285 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/nativebutton/NativeButtonConnector.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/nativebutton/NativeButtonConnector.java
@@ -58,7 +58,11 @@ public class NativeButtonConnector extends AbstractComponentConnector implements
blurHandlerRegistration);
// Set text
- getWidget().setText(getState().getCaption());
+ if (getState().isHtmlContentAllowed()) {
+ getWidget().setHTML(getState().getCaption());
+ } else {
+ getWidget().setText(getState().getCaption());
+ }
// handle error
if (null != getState().getErrorMessage()) {
diff --git a/src/com/vaadin/terminal/gwt/client/ui/nativebutton/VNativeButton.java b/src/com/vaadin/terminal/gwt/client/ui/nativebutton/VNativeButton.java
index d0b8f73eb1..01ac4fab6a 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/nativebutton/VNativeButton.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/nativebutton/VNativeButton.java
@@ -65,6 +65,11 @@ public class VNativeButton extends Button implements ClickHandler {
}
@Override
+ public void setHTML(String html) {
+ captionElement.setInnerHTML(html);
+ }
+
+ @Override
public void onBrowserEvent(Event event) {
super.onBrowserEvent(event);
diff --git a/src/com/vaadin/terminal/gwt/client/ui/notification/VNotification.java b/src/com/vaadin/terminal/gwt/client/ui/notification/VNotification.java
index eb97160f52..0d222044ba 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/notification/VNotification.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/notification/VNotification.java
@@ -160,6 +160,13 @@ public class VNotification extends VOverlay {
}
super.show();
setPosition(position);
+ /**
+ * Android 4 fails to render notifications correctly without a little
+ * nudge (#8551)
+ */
+ if (BrowserInfo.get().isAndroid()) {
+ Util.setStyleTemporarily(getElement(), "display", "none");
+ }
}
@Override
diff --git a/src/com/vaadin/terminal/gwt/client/ui/root/VRoot.java b/src/com/vaadin/terminal/gwt/client/ui/root/VRoot.java
index 13fc55d7ea..12a69d5556 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/root/VRoot.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/root/VRoot.java
@@ -306,6 +306,7 @@ public class VRoot extends SimplePanel implements ResizeHandler,
/*-{
var j;
for(j in $wnd.vaadin.vaadinConfigurations) {
+ // $entry not needed as function is not exported
list.@java.util.Collection::add(Ljava/lang/Object;)(j);
}
}-*/;
diff --git a/src/com/vaadin/terminal/gwt/server/AbstractApplicationPortlet.java b/src/com/vaadin/terminal/gwt/server/AbstractApplicationPortlet.java
index 58d6a18592..77698805de 100644
--- a/src/com/vaadin/terminal/gwt/server/AbstractApplicationPortlet.java
+++ b/src/com/vaadin/terminal/gwt/server/AbstractApplicationPortlet.java
@@ -509,6 +509,9 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet
protected void handleRequest(PortletRequest request,
PortletResponse response) throws PortletException, IOException {
+ RequestTimer requestTimer = new RequestTimer();
+ requestTimer.start();
+
AbstractApplicationPortletWrapper portletWrapper = new AbstractApplicationPortletWrapper(
this);
@@ -530,9 +533,6 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet
WrappedPortletResponse wrappedResponse = new WrappedPortletResponse(
response, getDeploymentConfiguration());
- RequestTimer requestTimer = RequestTimer.get(wrappedRequest);
- requestTimer.start(wrappedRequest);
-
RequestType requestType = getRequestType(request);
if (requestType == RequestType.UNKNOWN) {
@@ -721,10 +721,11 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet
} finally {
Root.setCurrentRoot(null);
Application.setCurrentApplication(null);
- }
- requestTimer.stop();
- RequestTimer.set(wrappedRequest, requestTimer);
+ requestTimer
+ .stop((AbstractWebApplicationContext) application
+ .getContext());
+ }
}
}
}
diff --git a/src/com/vaadin/terminal/gwt/server/AbstractApplicationServlet.java b/src/com/vaadin/terminal/gwt/server/AbstractApplicationServlet.java
index 799271b979..6ab2748332 100644
--- a/src/com/vaadin/terminal/gwt/server/AbstractApplicationServlet.java
+++ b/src/com/vaadin/terminal/gwt/server/AbstractApplicationServlet.java
@@ -400,12 +400,12 @@ public abstract class AbstractApplicationServlet extends HttpServlet implements
private void service(WrappedHttpServletRequest request,
WrappedHttpServletResponse response) throws ServletException,
IOException {
+ RequestTimer requestTimer = new RequestTimer();
+ requestTimer.start();
+
AbstractApplicationServletWrapper servletWrapper = new AbstractApplicationServletWrapper(
this);
- RequestTimer requestTimer = RequestTimer.get(request);
- requestTimer.start(request);
-
RequestType requestType = getRequestType(request);
if (!ensureCookiesEnabled(requestType, request, response)) {
return;
@@ -540,10 +540,11 @@ public abstract class AbstractApplicationServlet extends HttpServlet implements
} finally {
Root.setCurrentRoot(null);
Application.setCurrentApplication(null);
- }
- requestTimer.stop();
- RequestTimer.set(request, requestTimer);
+ requestTimer
+ .stop((AbstractWebApplicationContext) application
+ .getContext());
+ }
}
}
diff --git a/src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java b/src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java
index b780f66a23..c57e7d8bc1 100644
--- a/src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java
+++ b/src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java
@@ -1097,19 +1097,18 @@ public abstract class AbstractCommunicationManager implements Serializable {
dragAndDropService.printJSONResponse(outWriter);
}
- writePerformanceDataForTestBench(request, outWriter);
+ writePerformanceData(outWriter);
}
/**
- * Adds the performance timing data used by TestBench 3 to the UIDL
+ * Adds the performance timing data (used by TestBench 3) to the UIDL
* response.
*/
- private void writePerformanceDataForTestBench(final WrappedRequest request,
- final PrintWriter outWriter) {
- Long totalTime = (Long) request.getAttribute("TOTAL");
- Long lastRequestTime = (Long) request.getAttribute("LASTREQUEST");
- outWriter.write(String.format(", \"tbss\":[%d, %d]", totalTime,
- lastRequestTime));
+ private void writePerformanceData(final PrintWriter outWriter) {
+ AbstractWebApplicationContext ctx = (AbstractWebApplicationContext) application
+ .getContext();
+ outWriter.write(String.format(", \"timings\":[%d, %d]",
+ ctx.getTotalSessionTime(), ctx.getLastRequestTime()));
}
private void legacyPaint(PaintTarget paintTarget,
diff --git a/src/com/vaadin/terminal/gwt/server/AbstractWebApplicationContext.java b/src/com/vaadin/terminal/gwt/server/AbstractWebApplicationContext.java
index c8335a8607..c0ae0afc26 100644
--- a/src/com/vaadin/terminal/gwt/server/AbstractWebApplicationContext.java
+++ b/src/com/vaadin/terminal/gwt/server/AbstractWebApplicationContext.java
@@ -44,6 +44,10 @@ public abstract class AbstractWebApplicationContext implements
protected HashMap<Application, AbstractCommunicationManager> applicationToAjaxAppMgrMap = new HashMap<Application, AbstractCommunicationManager>();
+ private long totalSessionTime = 0;
+
+ private long lastRequestTime = -1;
+
public void addTransactionListener(TransactionListener listener) {
if (listener != null) {
listeners.add(listener);
@@ -222,4 +226,30 @@ public abstract class AbstractWebApplicationContext implements
return relativeUri.substring(index + 1, next);
}
+ /**
+ * @return The total time spent servicing requests in this session.
+ */
+ public long getTotalSessionTime() {
+ return totalSessionTime;
+ }
+
+ /**
+ * Sets the time spent servicing the last request in the session and updates
+ * the total time spent servicing requests in this session.
+ *
+ * @param time
+ * the time spent in the last request.
+ */
+ public void setLastRequestTime(long time) {
+ lastRequestTime = time;
+ totalSessionTime += time;
+ }
+
+ /**
+ * @return the time spent servicing the last request in this session.
+ */
+ public long getLastRequestTime() {
+ return lastRequestTime;
+ }
+
} \ No newline at end of file
diff --git a/src/com/vaadin/terminal/gwt/server/RequestTimer.java b/src/com/vaadin/terminal/gwt/server/RequestTimer.java
index d47f444bef..6c0edec466 100644
--- a/src/com/vaadin/terminal/gwt/server/RequestTimer.java
+++ b/src/com/vaadin/terminal/gwt/server/RequestTimer.java
@@ -4,7 +4,7 @@
package com.vaadin.terminal.gwt.server;
-import com.vaadin.terminal.WrappedRequest;
+import java.io.Serializable;
/**
* Times the handling of requests and stores the information as an attribute in
@@ -14,67 +14,30 @@ import com.vaadin.terminal.WrappedRequest;
*
* @author Jonatan Kronqvist / Vaadin Ltd
*/
-public class RequestTimer {
- public static final String SESSION_ATTR_ID = "REQUESTTIMER";
-
+public class RequestTimer implements Serializable {
private long requestStartTime = 0;
- private long totalSessionTime = 0;
- private long lastRequestTime = -1;
/**
* Starts the timing of a request. This should be called before any
* processing of the request.
- *
- * @param request
- * the request.
*/
- public void start(WrappedRequest request) {
+ public void start() {
requestStartTime = System.nanoTime();
- request.setAttribute("TOTAL", totalSessionTime);
- request.setAttribute("LASTREQUEST", lastRequestTime);
}
/**
* Stops the timing of a request. This should be called when all processing
* of a request has finished.
+ *
+ * @param context
*/
- public void stop() {
+ public void stop(AbstractWebApplicationContext context) {
// Measure and store the total handling time. This data can be
// used in TestBench 3 tests.
long time = (System.nanoTime() - requestStartTime) / 1000000;
- lastRequestTime = time;
- totalSessionTime += time;
- }
-
- /**
- * Returns a valid request timer for the specified request. Timers are
- * session bound.
- *
- * @param request
- * the request for which to get a valid timer.
- * @return a valid timer.
- */
- public static RequestTimer get(WrappedRequest request) {
- RequestTimer timer = (RequestTimer) request
- .getSessionAttribute(SESSION_ATTR_ID);
- if (timer == null) {
- timer = new RequestTimer();
- }
- return timer;
- }
- /**
- * Associates the specified request timer with the specified request. Since
- * {@link #get(RequestWrapper)} will, at one point or another, return a new
- * instance, this method should be called to keep the request <-> timer
- * association updated.
- *
- * @param request
- * the request for which to set the timer.
- * @param requestTimer
- * the timer.
- */
- public static void set(WrappedRequest request, RequestTimer requestTimer) {
- request.setSessionAttribute(RequestTimer.SESSION_ATTR_ID, requestTimer);
+ // The timings must be stored in the context, since a new
+ // RequestTimer is created for every request.
+ context.setLastRequestTime(time);
}
}
diff --git a/src/com/vaadin/ui/Button.java b/src/com/vaadin/ui/Button.java
index f5e45ef3ef..876fe593e2 100644
--- a/src/com/vaadin/ui/Button.java
+++ b/src/com/vaadin/ui/Button.java
@@ -489,4 +489,33 @@ public class Button extends AbstractComponent implements
return (ButtonState) super.getState();
}
+ /**
+ * Set whether the caption text is rendered as HTML or not. You might need
+ * to retheme button to allow higher content than the original text style.
+ *
+ * If set to true, the captions are passed to the browser as html and the
+ * developer is responsible for ensuring no harmful html is used. If set to
+ * false, the content is passed to the browser as plain text.
+ *
+ * @param htmlContentAllowed
+ * <code>true</code> if caption is rendered as HTML,
+ * <code>false</code> otherwise
+ */
+ public void setHtmlContentAllowed(boolean htmlContentAllowed) {
+ if (getState().isHtmlContentAllowed() != htmlContentAllowed) {
+ getState().setHtmlContentAllowed(htmlContentAllowed);
+ requestRepaint();
+ }
+ }
+
+ /**
+ * Return HTML rendering setting
+ *
+ * @return <code>true</code> if the caption text is to be rendered as HTML,
+ * <code>false</code> otherwise
+ */
+ public boolean isHtmlContentAllowed() {
+ return getState().isHtmlContentAllowed();
+ }
+
}
diff --git a/src/com/vaadin/ui/Table.java b/src/com/vaadin/ui/Table.java
index 2fffedd9d6..ba4c6529c5 100644
--- a/src/com/vaadin/ui/Table.java
+++ b/src/com/vaadin/ui/Table.java
@@ -1930,7 +1930,7 @@ public class Table extends AbstractSelect implements Action.Container,
if (index < firstIndexNotInCache
&& index >= pageBufferFirstIndex
&& pageBuffer[CELL_GENERATED_ROW][indexInOldBuffer] == null
- && pageBuffer[CELL_ITEMID][indexInOldBuffer] == id) {
+ && id.equals(pageBuffer[CELL_ITEMID][indexInOldBuffer])) {
// we already have data in our cache,
// recycle it instead of fetching it via
// getValue/getPropertyValue
diff --git a/tests/client-side/com/vaadin/terminal/gwt/client/TestVBrowserDetailsUserAgentParser.java b/tests/client-side/com/vaadin/terminal/gwt/client/TestVBrowserDetailsUserAgentParser.java
index f661b6cf15..fedce98ecf 100644
--- a/tests/client-side/com/vaadin/terminal/gwt/client/TestVBrowserDetailsUserAgentParser.java
+++ b/tests/client-side/com/vaadin/terminal/gwt/client/TestVBrowserDetailsUserAgentParser.java
@@ -2,8 +2,6 @@ package com.vaadin.terminal.gwt.client;
import junit.framework.TestCase;
-import com.vaadin.terminal.gwt.client.VBrowserDetails;
-
public class TestVBrowserDetailsUserAgentParser extends TestCase {
private static final String FIREFOX30_WINDOWS = "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-GB; rv:1.9.0.6) Gecko/2009011913 Firefox/3.0.6";
@@ -37,6 +35,15 @@ public class TestVBrowserDetailsUserAgentParser extends TestCase {
private static final String SAFARI3_WINDOWS = "Mozilla/5.0 (Windows; U; Windows NT 5.1; cs-CZ) AppleWebKit/525.28.3 (KHTML, like Gecko) Version/3.2.3 Safari/525.29";
private static final String SAFARI4_MAC = "Mozilla/5.0 (Macintosh; U; PPC Mac OS X 10_5_8; en-us) AppleWebKit/531.22.7 (KHTML, like Gecko) Version/4.0.5 Safari/531.22.7";
+ private static final String IPHONE_IOS_5_1 = "Mozilla/5.0 (iPhone; CPU iPhone OS 5_1 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Version/5.1 Mobile/9B179 Safari/7534.48.3";
+ private static final String IPHONE_IOS_4_0 = "Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_0 like Mac OS X; en-us) AppleWebKit/532.9 (KHTML, like Gecko) Version/4.0.5 Mobile/8A293 Safari/6531.22.7";
+ private static final String IPAD_IOS_4_3_1 = "Mozilla/5.0 (iPad; U; CPU OS 4_3_1 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8G4 Safari/6533.18.5";
+
+ private static final String ANDROID_HTC_2_1 = "Mozilla/5.0 (Linux; U; Android 2.1-update1; en-us; ADR6300 Build/ERE27) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17";
+ private static final String ANDROID_GOOGLE_NEXUS_2_2 = "Mozilla/5.0 (Linux; U; Android 2.2; en-us; Nexus One Build/FRF91) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1";
+ private static final String ANDROID_MOTOROLA_3_0 = "Mozilla/5.0 (Linux; U; Android 3.0; en-us; Xoom Build/HRI39) AppleWebKit/534.13 (KHTML, like Gecko) Version/4.0 Safari/534.13";
+ private static final String ANDROID_GALAXY_NEXUS_4_0_4_CHROME = "Mozilla/5.0 (Linux; Android 4.0.4; Galaxy Nexus Build/IMM76B) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.133 Mobile Safari/535.19";
+
public void testSafari3() {
VBrowserDetails bd = new VBrowserDetails(SAFARI3_WINDOWS);
assertWebKit(bd);
@@ -57,6 +64,86 @@ public class TestVBrowserDetailsUserAgentParser extends TestCase {
assertMacOSX(bd);
}
+ public void testIPhoneIOS5() {
+ VBrowserDetails bd = new VBrowserDetails(IPHONE_IOS_5_1);
+ assertWebKit(bd);
+ assertSafari(bd);
+ assertBrowserMajorVersion(bd, 5);
+ assertBrowserMinorVersion(bd, 1);
+ assertEngineVersion(bd, 534f);
+ assertIOS(bd, 5, 1);
+ }
+
+ public void testIPhoneIOS4() {
+ VBrowserDetails bd = new VBrowserDetails(IPHONE_IOS_4_0);
+ assertWebKit(bd);
+ assertSafari(bd);
+ assertBrowserMajorVersion(bd, 4);
+ assertBrowserMinorVersion(bd, 0);
+ assertEngineVersion(bd, 532f);
+ assertIOS(bd, 4, 0);
+ }
+
+ public void testIPadIOS4() {
+ VBrowserDetails bd = new VBrowserDetails(IPAD_IOS_4_3_1);
+ assertWebKit(bd);
+ assertSafari(bd);
+ assertBrowserMajorVersion(bd, 5);
+ assertBrowserMinorVersion(bd, 0);
+ assertEngineVersion(bd, 533f);
+ assertIOS(bd, 4, 3);
+ }
+
+ public void testAndroid21() {
+ VBrowserDetails bd = new VBrowserDetails(ANDROID_HTC_2_1);
+ assertWebKit(bd);
+ assertSafari(bd);
+ assertBrowserMajorVersion(bd, 4);
+ assertBrowserMinorVersion(bd, 0);
+ assertEngineVersion(bd, 530f);
+ assertAndroid(bd, 2, 1);
+
+ }
+
+ public void testAndroid22() {
+ VBrowserDetails bd = new VBrowserDetails(ANDROID_GOOGLE_NEXUS_2_2);
+ assertWebKit(bd);
+ assertSafari(bd);
+ assertBrowserMajorVersion(bd, 4);
+ assertBrowserMinorVersion(bd, 0);
+ assertEngineVersion(bd, 533f);
+ assertAndroid(bd, 2, 2);
+ }
+
+ public void testAndroid30() {
+ VBrowserDetails bd = new VBrowserDetails(ANDROID_MOTOROLA_3_0);
+ assertWebKit(bd);
+ assertSafari(bd);
+ assertBrowserMajorVersion(bd, 4);
+ assertBrowserMinorVersion(bd, 0);
+ assertEngineVersion(bd, 534f);
+ assertAndroid(bd, 3, 0);
+ }
+
+ public void testAndroid40Chrome() {
+ VBrowserDetails bd = new VBrowserDetails(
+ ANDROID_GALAXY_NEXUS_4_0_4_CHROME);
+ assertWebKit(bd);
+ assertChrome(bd);
+ assertBrowserMajorVersion(bd, 18);
+ assertBrowserMinorVersion(bd, 0);
+ assertEngineVersion(bd, 535f);
+ assertAndroid(bd, 4, 0);
+ }
+
+ private void assertOSMajorVersion(VBrowserDetails bd, int i) {
+ assertEquals(i, bd.getOperatingSystemMajorVersion());
+ }
+
+ private void assertOSMinorVersion(VBrowserDetails bd, int i) {
+ assertEquals(i, bd.getOperatingSystemMinorVersion());
+ }
+
public void testChrome3() {
VBrowserDetails bd = new VBrowserDetails(CHROME3_MAC);
assertWebKit(bd);
@@ -352,18 +439,47 @@ public class TestVBrowserDetailsUserAgentParser extends TestCase {
assertFalse(browserDetails.isLinux());
assertFalse(browserDetails.isWindows());
assertTrue(browserDetails.isMacOSX());
+ assertFalse(browserDetails.isAndroid());
+ }
+
+ private void assertAndroid(VBrowserDetails browserDetails,
+ int majorVersion, int minorVersion) {
+ assertFalse(browserDetails.isLinux());
+ assertFalse(browserDetails.isWindows());
+ assertFalse(browserDetails.isMacOSX());
+ assertFalse(browserDetails.isIOS());
+ assertTrue(browserDetails.isAndroid());
+
+ assertOSMajorVersion(browserDetails, majorVersion);
+ assertOSMinorVersion(browserDetails, minorVersion);
+ }
+
+ private void assertIOS(VBrowserDetails browserDetails, int majorVersion,
+ int minorVersion) {
+ assertFalse(browserDetails.isLinux());
+ assertFalse(browserDetails.isWindows());
+ assertFalse(browserDetails.isMacOSX());
+ assertTrue(browserDetails.isIOS());
+ assertFalse(browserDetails.isAndroid());
+
+ assertOSMajorVersion(browserDetails, majorVersion);
+ assertOSMinorVersion(browserDetails, minorVersion);
}
private void assertWindows(VBrowserDetails browserDetails) {
assertFalse(browserDetails.isLinux());
assertTrue(browserDetails.isWindows());
assertFalse(browserDetails.isMacOSX());
+ assertFalse(browserDetails.isIOS());
+ assertFalse(browserDetails.isAndroid());
}
private void assertLinux(VBrowserDetails browserDetails) {
assertTrue(browserDetails.isLinux());
assertFalse(browserDetails.isWindows());
assertFalse(browserDetails.isMacOSX());
+ assertFalse(browserDetails.isIOS());
+ assertFalse(browserDetails.isAndroid());
}
}
diff --git a/tests/server-side/com/vaadin/tests/server/SourceFileChecker.java b/tests/server-side/com/vaadin/tests/server/SourceFileChecker.java
index 453aab5af8..9906990165 100644
--- a/tests/server-side/com/vaadin/tests/server/SourceFileChecker.java
+++ b/tests/server-side/com/vaadin/tests/server/SourceFileChecker.java
@@ -5,6 +5,8 @@ import java.io.FileInputStream;
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
import junit.framework.Assert;
import junit.framework.TestCase;
@@ -81,6 +83,17 @@ public class SourceFileChecker extends TestCase {
}
}
+ public void testGwtFilesUsingEntry() {
+ Set<String> ignore = new HashSet<String>(alwaysIgnore);
+ ignore.add(externalJavaFiles);
+ validateFiles(
+ SRC_DIR,
+ new GwtEntryChecker(),
+ ignore,
+ "The following files might export javscript callbacks without $entry:\n{0}",
+ ".java");
+ }
+
public interface FileValidator {
void validateFile(File f) throws Exception;
}
@@ -171,4 +184,33 @@ public class SourceFileChecker extends TestCase {
}
}
}
+
+ class GwtEntryChecker extends FileContentsValidator {
+ // Matches e.g.
+ // @com.vaadin.terminal.gwt.client.HistoryImplIEVaadin::escapeHtml(
+ private final Matcher matcher = Pattern.compile("@[\\w.]+::\\w+\\(")
+ .matcher("");
+
+ @Override
+ protected void validateContents(File f, String contents)
+ throws Exception {
+ matcher.reset(contents);
+ while (matcher.find()) {
+ int start = matcher.start();
+
+ // Search backwards to find index of native block start
+ int nativeBlockStart = contents.lastIndexOf("/*-{", start);
+
+ // Get contents between block start and our match
+ String beforeMatchInBlock = contents.substring(
+ nativeBlockStart, start);
+
+ // Fail if there's no $entry
+ if (!beforeMatchInBlock.contains("$entry")) {
+ throw new IllegalArgumentException();
+ }
+ }
+ }
+
+ }
}
diff --git a/tests/server-side/com/vaadin/tests/server/component/tree/TestHasChildren.java b/tests/server-side/com/vaadin/tests/server/component/tree/TestHasChildren.java
new file mode 100644
index 0000000000..66535d3ffb
--- /dev/null
+++ b/tests/server-side/com/vaadin/tests/server/component/tree/TestHasChildren.java
@@ -0,0 +1,25 @@
+package com.vaadin.tests.server.component.tree;
+
+import junit.framework.TestCase;
+
+import com.vaadin.ui.Tree;
+
+public class TestHasChildren extends TestCase {
+
+ private Tree tree;
+
+ @Override
+ protected void setUp() {
+ tree = new Tree();
+ tree.addItem("parent");
+ tree.addItem("child");
+ tree.setChildrenAllowed("parent", true);
+ tree.setParent("child", "parent");
+ }
+
+ public void testRemoveChildren() {
+ assertTrue(tree.hasChildren("parent"));
+ tree.removeItem("child");
+ assertFalse(tree.hasChildren("parent"));
+ }
+}
diff --git a/tests/test.xml b/tests/test.xml
index 28459c37e9..67e48ee137 100644
--- a/tests/test.xml
+++ b/tests/test.xml
@@ -11,7 +11,7 @@
<!-- Configuration -->
<!-- ================================================================== -->
<!-- Browsers to use for testing -->
- <property name="browsers-windows" value="winxp-ie8,win7-ie9,winxp-firefox11,winxp-safari5,winxp-googlechrome18,winxp-opera11" />
+ <property name="browsers-windows" value="winxp-ie8,win7-ie9,winxp-firefox12,winxp-safari5,winxp-googlechrome18,winxp-opera11" />
<property name="browsers-linux" value="linux-firefox3,linux-opera10,linux-googlechrome8" />
<property name="browsers-mac" value="osx-firefox3,osx-opera10,osx-googlechrome8,osx-safari4,osx-safari5" />
diff --git a/tests/testbench/com/vaadin/tests/components/TouchScrollables.java b/tests/testbench/com/vaadin/tests/components/TouchScrollables.java
index 636bddead8..053691e738 100644
--- a/tests/testbench/com/vaadin/tests/components/TouchScrollables.java
+++ b/tests/testbench/com/vaadin/tests/components/TouchScrollables.java
@@ -15,27 +15,102 @@ import com.vaadin.terminal.gwt.client.ui.dd.VerticalDropLocation;
import com.vaadin.tests.util.Person;
import com.vaadin.tests.util.PersonContainer;
import com.vaadin.tests.util.TestUtils;
-import com.vaadin.ui.AbstractComponent;
import com.vaadin.ui.AbstractSelect.AbstractSelectTargetDetails;
+import com.vaadin.ui.Accordion;
import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.Component;
import com.vaadin.ui.CssLayout;
-import com.vaadin.ui.HorizontalLayout;
+import com.vaadin.ui.HorizontalSplitPanel;
import com.vaadin.ui.Label;
+import com.vaadin.ui.Layout;
import com.vaadin.ui.Panel;
+import com.vaadin.ui.TabSheet;
import com.vaadin.ui.Table;
+import com.vaadin.ui.VerticalLayout;
+import com.vaadin.ui.Window;
public class TouchScrollables extends TestBase {
java.util.Random r = new java.util.Random(1);
- private HorizontalLayout testSelector;
+ private TabSheet testSelector = new TabSheet();
@Override
public void setup() {
- testSelector = new HorizontalLayout();
getLayout().addComponent(testSelector);
+ testSelector.setHeight("500px");
+ addTest(getPanelTest());
+ addTest(getSimpleTableTest());
+ addTest(getDDSortableTableTest());
+ addTest(getTabSheetTest());
+ addTest(getSplitPanelTest());
+ addTest(getAccordionTest());
+ addTest(getSubWindowTest());
+
+ TestUtils
+ .injectCSS(
+ getLayout().getRoot(),
+ "body * {-webkit-user-select: none;} .v-table-row-drag-middle .v-table-cell-content {"
+ + " background-color: inherit ; border-bottom: 1px solid cyan;"
+ + "}"
+ + ".v-table-row-drag-middle .v-table-cell-wrapper {"
+ + " margin-bottom: -1px;" + "}" + ""
+
+ );
+ }
+
+ private Component getPanelTest() {
+ Layout cssLayout = new CssLayout();
+ cssLayout.setCaption("Panel");
+
+ final Panel p = new Panel();
+ p.setHeight("400px");
+ Label l50 = null;
+ for (int i = 0; i < 100; i++) {
+ Label c = new Label("Label" + i);
+ p.addComponent(c);
+ if (i == 50) {
+ l50 = c;
+ }
+ }
+
+ final Label l = l50;
+ Button button = new Button("Scroll to label 50",
+ new Button.ClickListener() {
+ public void buttonClick(ClickEvent event) {
+ getLayout().getRoot().scrollIntoView(l);
+ }
+ });
+ cssLayout.addComponent(button);
+ button = new Button("Scroll to 100px", new Button.ClickListener() {
+ public void buttonClick(ClickEvent event) {
+ p.setScrollTop(100);
+ }
+ });
+ cssLayout.addComponent(button);
+ cssLayout.addComponent(p);
+ return cssLayout;
+ }
+
+ private Component getTabSheetTest() {
+ TabSheet ts = new TabSheet();
+ ts.setCaption("Tabsheet");
+ ts.setHeight("100%");
+ ts.addTab(getBigComponent(), "Tab 1");
+ ts.addTab(getBigComponent(), "Tab 2");
+ return ts;
+ }
+
+ private Component getSplitPanelTest() {
+ HorizontalSplitPanel sp = new HorizontalSplitPanel();
+ sp.setCaption("Splitpanel");
+ sp.addComponent(getBigComponent());
+ sp.addComponent(getBigComponent());
+ return sp;
+ }
+
+ private Component getSimpleTableTest() {
CssLayout cssLayout = new CssLayout();
final Table table = new Table();
@@ -68,57 +143,33 @@ public class TouchScrollables extends TestBase {
}
cssLayout.addComponent(table);
cssLayout.setCaption("Table");
+ return cssLayout;
+ }
- addTest(cssLayout);
-
- cssLayout = new CssLayout();
- cssLayout.setCaption("Panel");
-
- final Panel p = new Panel();
- p.setHeight("400px");
- p.setCaption("Panel");
- Label l50 = null;
- for (int i = 0; i < 100; i++) {
- Label c = new Label("Label" + i);
- p.addComponent(c);
- if (i == 50) {
- l50 = c;
- }
- }
+ private Component getAccordionTest() {
+ Accordion a = new Accordion();
+ a.setCaption("Accordion");
+ a.setHeight("100%");
+ a.addTab(getBigComponent(), "Tab 1");
+ a.addTab(getBigComponent(), "Tab 2");
+ a.addTab(getBigComponent(), "Tab 3");
+ return a;
+ }
- final Label l = l50;
- button = new Button("Scroll to label 50", new Button.ClickListener() {
+ private Component getSubWindowTest() {
+ Button b = new Button("Open subwindow", new Button.ClickListener() {
public void buttonClick(ClickEvent event) {
- getLayout().getRoot().scrollIntoView(l);
+ Window w = new Window("Subwindow");
+ w.center();
+ w.setHeight("200px");
+ w.addComponent(getBigComponent());
+ getMainWindow().addWindow(w);
}
});
- cssLayout.addComponent(button);
- button = new Button("Scroll to 100px", new Button.ClickListener() {
- public void buttonClick(ClickEvent event) {
- p.setScrollTop(100);
- }
- });
- cssLayout.addComponent(button);
- cssLayout.addComponent(p);
-
- addTest(cssLayout);
-
- TestUtils
- .injectCSS(
- getLayout().getRoot(),
- "body * {-webkit-user-select: none;} .v-table-row-drag-middle .v-table-cell-content {"
- + " background-color: inherit ; border-bottom: 1px solid cyan;"
- + "}"
- + ".v-table-row-drag-middle .v-table-cell-wrapper {"
- + " margin-bottom: -1px;" + "}" + ""
-
- );
-
- addDDSortableTable();
-
+ return b;
}
- private void addDDSortableTable() {
+ private Component getDDSortableTableTest() {
final Table table;
table = new Table();
table.setCaption("DD sortable table with context menus");
@@ -219,7 +270,7 @@ public class TouchScrollables extends TestBase {
}
});
- addTest(table);
+ return table;
}
private void populateTable(Table table) {
@@ -238,21 +289,17 @@ public class TouchScrollables extends TestBase {
}
- private Component testComponent;
-
- private void addTest(final AbstractComponent t) {
- Button button = new Button(t.getCaption());
- testSelector.addComponent(button);
- button.addListener(new Button.ClickListener() {
+ private void addTest(final Component t) {
+ testSelector.addComponent(t);
+ }
- public void buttonClick(ClickEvent event) {
- if (testComponent != null) {
- getLayout().removeComponent(testComponent);
- }
- testComponent = t;
- getLayout().addComponent(t);
- }
- });
+ private Component getBigComponent() {
+ Layout l = new VerticalLayout();
+ for (int i = 0; i < 100; i++) {
+ Label c = new Label("Label" + i);
+ l.addComponent(c);
+ }
+ return l;
}
@Override
diff --git a/tests/testbench/com/vaadin/tests/components/button/ButtonHtml.html b/tests/testbench/com/vaadin/tests/components/button/ButtonHtml.html
new file mode 100644
index 0000000000..2d58d0e2e1
--- /dev/null
+++ b/tests/testbench/com/vaadin/tests/components/button/ButtonHtml.html
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head profile="http://selenium-ide.openqa.org/profiles/test-case">
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<link rel="selenium.base" href="" />
+<title>ButtonHtml</title>
+</head>
+<body>
+<table cellpadding="1" cellspacing="1" border="1">
+<thead>
+<tr><td rowspan="1" colspan="3">ButtonHtml</td></tr>
+</thead><tbody>
+<tr>
+ <td>open</td>
+ <td>/run/com.vaadin.tests.components.button.ButtonHtml?restartApplication</td>
+ <td></td>
+</tr>
+<tr>
+ <td>screenCapture</td>
+ <td></td>
+ <td>initial</td>
+</tr>
+<tr>
+ <td>click</td>
+ <td>vaadin=runcomvaadintestscomponentsbuttonButtonHtml::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[2]/VButton[0]/domChild[0]/domChild[0]</td>
+ <td></td>
+</tr>
+<tr>
+ <td>screenCapture</td>
+ <td></td>
+ <td>after_1_click</td>
+</tr>
+<tr>
+ <td>click</td>
+ <td>vaadin=runcomvaadintestscomponentsbuttonButtonHtml::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[2]/VButton[0]/domChild[0]/domChild[0]/domChild[0]</td>
+ <td></td>
+</tr>
+<tr>
+ <td>screenCapture</td>
+ <td></td>
+ <td>after_2_clicks</td>
+</tr>
+
+</tbody></table>
+</body>
+</html>
diff --git a/tests/testbench/com/vaadin/tests/components/button/ButtonHtml.java b/tests/testbench/com/vaadin/tests/components/button/ButtonHtml.java
new file mode 100644
index 0000000000..253de5b43c
--- /dev/null
+++ b/tests/testbench/com/vaadin/tests/components/button/ButtonHtml.java
@@ -0,0 +1,39 @@
+package com.vaadin.tests.components.button;
+
+import com.vaadin.tests.components.TestBase;
+import com.vaadin.ui.Button;
+import com.vaadin.ui.Button.ClickEvent;
+
+public class ButtonHtml extends TestBase {
+
+ @Override
+ protected void setup() {
+ Button b = new Button("<b>Plain text button</b>");
+ addComponent(b);
+
+ b = new Button(
+ "<span style=\"color: red; font-weight: bold;\">HTML</span> button");
+ b.setHtmlContentAllowed(true);
+ addComponent(b);
+
+ final Button swapButton = new Button("<i>Swap button<i>");
+ swapButton.addListener(new Button.ClickListener() {
+
+ public void buttonClick(ClickEvent event) {
+ swapButton.setHtmlContentAllowed(!swapButton
+ .isHtmlContentAllowed());
+ }
+ });
+ addComponent(swapButton);
+ }
+
+ @Override
+ protected String getDescription() {
+ return "Verify that Button HTML rendering works";
+ }
+
+ @Override
+ protected Integer getTicketNumber() {
+ return 8663;
+ }
+}
diff --git a/tests/testbench/com/vaadin/tests/components/combobox/GridLayoutComboBoxZoomOut.java b/tests/testbench/com/vaadin/tests/components/combobox/GridLayoutComboBoxZoomOut.java
new file mode 100644
index 0000000000..37b0fe21a1
--- /dev/null
+++ b/tests/testbench/com/vaadin/tests/components/combobox/GridLayoutComboBoxZoomOut.java
@@ -0,0 +1,62 @@
+package com.vaadin.tests.components.combobox;
+
+import com.vaadin.tests.components.AbstractTestCase;
+import com.vaadin.ui.ComboBox;
+import com.vaadin.ui.GridLayout;
+import com.vaadin.ui.Label;
+import com.vaadin.ui.Layout;
+import com.vaadin.ui.Root;
+import com.vaadin.ui.Select;
+
+@SuppressWarnings("serial")
+public class GridLayoutComboBoxZoomOut extends AbstractTestCase {
+
+ @Override
+ public void init() {
+ Root.LegacyWindow mainWindow = new Root.LegacyWindow(
+ "Gridlayoutbug Application");
+ setMainWindow(mainWindow);
+
+ Label description = new Label(
+ "Open this application in Chrome, zoom out (cmd + \"-\") and "
+ + "open the ComboBox for weird behaviour.");
+ mainWindow.addComponent(description);
+
+ Layout formLayout = new GridLayout(2, 1);
+ // formLayout.setWidth("100%");
+ formLayout.setWidth("1000px");
+
+ Select countryField = new ComboBox();
+ countryField.addItem("Finland");
+ countryField.addItem("Sweden");
+ countryField.addItem("Canada");
+ countryField.addItem("USA");
+ countryField.setCaption("Country");
+ countryField.setWidth("100%");
+ formLayout.addComponent(countryField);
+
+ Select statusField = new ComboBox();
+ statusField.addItem("Available");
+ statusField.addItem("On vacation");
+ statusField.addItem("Busy");
+ statusField.addItem("Left the building");
+ statusField.setCaption("Status");
+ statusField.setWidth("100%");
+ formLayout.addComponent(statusField);
+
+ mainWindow.addComponent(formLayout);
+ }
+
+ @Override
+ protected String getDescription() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ protected Integer getTicketNumber() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+}
diff --git a/tests/testbench/com/vaadin/tests/components/datefield/InlineDateFields.java b/tests/testbench/com/vaadin/tests/components/datefield/InlineDateFields.java
index de08477dd3..b8c5be57bf 100644
--- a/tests/testbench/com/vaadin/tests/components/datefield/InlineDateFields.java
+++ b/tests/testbench/com/vaadin/tests/components/datefield/InlineDateFields.java
@@ -25,6 +25,10 @@ public class InlineDateFields extends ComponentTestCase<InlineDateField> {
@Override
protected void initializeComponents() {
+ InlineDateField hidden = new InlineDateField();
+ hidden.setVisible(false); // Used to break rest of layout #8693
+ addComponent(hidden);
+
Locale locale = LOCALES[0];
InlineDateField pd = createInlineDateField("Undefined width", "-1",
diff --git a/tests/testbench/com/vaadin/tests/components/datefield/InlineDateFieldsHiddenOnStart.html b/tests/testbench/com/vaadin/tests/components/datefield/InlineDateFieldsHiddenOnStart.html
new file mode 100644
index 0000000000..6b79ef419b
--- /dev/null
+++ b/tests/testbench/com/vaadin/tests/components/datefield/InlineDateFieldsHiddenOnStart.html
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head profile="http://selenium-ide.openqa.org/profiles/test-case">
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<link rel="selenium.base" href="" />
+<title>New Test</title>
+</head>
+<body>
+<table cellpadding="1" cellspacing="1" border="1">
+<thead>
+<tr><td rowspan="1" colspan="3">New Test</td></tr>
+</thead><tbody>
+<tr>
+ <td>open</td>
+ <td>/run/com.vaadin.tests.components.datefield.InlineDateFields?restartApplication</td>
+ <td></td>
+</tr>
+<tr>
+ <td>assertElementPresent</td>
+ <td>vaadin=runcomvaadintestscomponentsdatefieldInlineDateFields::PID_SLocale-en_US-undefined-wide/VCalendarPanel[0]#header</td>
+ <td></td>
+</tr>
+</tbody></table>
+</body>
+</html>
diff --git a/tests/testbench/com/vaadin/tests/components/nativebutton/NativeButtonHtml.html b/tests/testbench/com/vaadin/tests/components/nativebutton/NativeButtonHtml.html
new file mode 100644
index 0000000000..8a1b21c35d
--- /dev/null
+++ b/tests/testbench/com/vaadin/tests/components/nativebutton/NativeButtonHtml.html
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head profile="http://selenium-ide.openqa.org/profiles/test-case">
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<link rel="selenium.base" href="" />
+<title>NativeButtonHtml</title>
+</head>
+<body>
+<table cellpadding="1" cellspacing="1" border="1">
+<thead>
+<tr><td rowspan="1" colspan="3">NativeButtonHtml</td></tr>
+</thead><tbody>
+<tr>
+ <td>open</td>
+ <td>/run/com.vaadin.tests.components.nativebutton.NativeButtonHtml?restartApplication</td>
+ <td></td>
+</tr>
+<tr>
+ <td>screenCapture</td>
+ <td></td>
+ <td>initial</td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentsnativebuttonNativeButtonHtml::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[2]/VNativeButton[0]</td>
+ <td>116,9</td>
+</tr>
+<tr>
+ <td>screenCapture</td>
+ <td></td>
+ <td>after_1_click</td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentsnativebuttonNativeButtonHtml::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[2]/VNativeButton[0]</td>
+ <td>74,10</td>
+</tr>
+<tr>
+ <td>screenCapture</td>
+ <td></td>
+ <td>after_2_clicks</td>
+</tr>
+
+</tbody></table>
+</body>
+</html>
diff --git a/tests/testbench/com/vaadin/tests/components/nativebutton/NativeButtonHtml.java b/tests/testbench/com/vaadin/tests/components/nativebutton/NativeButtonHtml.java
new file mode 100644
index 0000000000..011439f810
--- /dev/null
+++ b/tests/testbench/com/vaadin/tests/components/nativebutton/NativeButtonHtml.java
@@ -0,0 +1,41 @@
+package com.vaadin.tests.components.nativebutton;
+
+import com.vaadin.tests.components.TestBase;
+import com.vaadin.ui.Button;
+import com.vaadin.ui.Button.ClickEvent;
+import com.vaadin.ui.NativeButton;
+
+public class NativeButtonHtml extends TestBase {
+
+ @Override
+ protected void setup() {
+ NativeButton b = new NativeButton("<b>Plain text button</b>");
+ addComponent(b);
+
+ b = new NativeButton(
+ "<span style=\"color: red; font-weight: bold;\">HTML</span> button");
+ b.setHtmlContentAllowed(true);
+ addComponent(b);
+
+ final NativeButton swapButton = new NativeButton("<i>Swap button<i>");
+ swapButton.addListener(new Button.ClickListener() {
+
+ public void buttonClick(ClickEvent event) {
+ swapButton.setHtmlContentAllowed(!swapButton
+ .isHtmlContentAllowed());
+ }
+ });
+ addComponent(swapButton);
+ }
+
+ @Override
+ protected String getDescription() {
+ return "Verify that NativeButton HTML rendering works";
+ }
+
+ @Override
+ protected Integer getTicketNumber() {
+ // 8663 was for normal button (see ButtonHtml test)
+ return null;
+ }
+}
diff --git a/tests/testbench/com/vaadin/tests/components/table/TableWithContainerRequiringEqualsForItemId.html b/tests/testbench/com/vaadin/tests/components/table/TableWithContainerRequiringEqualsForItemId.html
new file mode 100644
index 0000000000..5364b1cd1e
--- /dev/null
+++ b/tests/testbench/com/vaadin/tests/components/table/TableWithContainerRequiringEqualsForItemId.html
@@ -0,0 +1,97 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head profile="http://selenium-ide.openqa.org/profiles/test-case">
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<link rel="selenium.base" href="http://arturwin.office.itmill.com:9999/" />
+<title>New Test</title>
+</head>
+<body>
+<table cellpadding="1" cellspacing="1" border="1">
+<thead>
+<tr><td rowspan="1" colspan="3">New Test</td></tr>
+</thead><tbody>
+<tr>
+ <td>open</td>
+ <td>/run/com.vaadin.tests.components.table.TableWithContainerRequiringEqualsForItemId?debug&amp;restartApplication</td>
+ <td></td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentstableTableWithContainerRequiringEqualsForItemId::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/domChild[0]/domChild[0]</td>
+ <td>523,81</td>
+</tr>
+<tr>
+ <td>click</td>
+ <td>vaadin=runcomvaadintestscomponentstableTableWithContainerRequiringEqualsForItemId::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VScrollTable[0]/FocusableScrollPanel[0]/VScrollTable$VScrollTableBody[0]/VScrollTable$VScrollTableBody$VScrollTableRow[0]/VButton[0]/domChild[0]/domChild[0]</td>
+ <td></td>
+</tr>
+<tr>
+ <td>assertText</td>
+ <td>vaadin=runcomvaadintestscomponentstableTableWithContainerRequiringEqualsForItemId::PID_SLog_row_0</td>
+ <td>1. Button Button999 clicked</td>
+</tr>
+<tr>
+ <td>click</td>
+ <td>vaadin=runcomvaadintestscomponentstableTableWithContainerRequiringEqualsForItemId::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VScrollTable[0]/FocusableScrollPanel[0]/VScrollTable$VScrollTableBody[0]/VScrollTable$VScrollTableBody$VScrollTableRow[14]/VButton[0]/domChild[0]/domChild[0]</td>
+ <td></td>
+</tr>
+<tr>
+ <td>assertText</td>
+ <td>vaadin=runcomvaadintestscomponentstableTableWithContainerRequiringEqualsForItemId::PID_SLog_row_0</td>
+ <td>2. Button Button985 clicked</td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentstableTableWithContainerRequiringEqualsForItemId::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VScrollTable[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]/domChild[2]</td>
+ <td>19,7</td>
+</tr>
+<tr>
+ <td>contextmenu</td>
+ <td>vaadin=runcomvaadintestscomponentstableTableWithContainerRequiringEqualsForItemId::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VScrollTable[0]/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[0]/domChild[0]/domChild[0]</td>
+ <td></td>
+</tr>
+<tr>
+ <td>assertText</td>
+ <td>vaadin=runcomvaadintestscomponentstableTableWithContainerRequiringEqualsForItemId::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VScrollTable[0]/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[0]/domChild[0]/domChild[0]</td>
+ <td>0</td>
+</tr>
+<tr>
+ <td>click</td>
+ <td>vaadin=runcomvaadintestscomponentstableTableWithContainerRequiringEqualsForItemId::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VScrollTable[0]/FocusableScrollPanel[0]/VScrollTable$VScrollTableBody[0]/VScrollTable$VScrollTableBody$VScrollTableRow[0]/VButton[0]/domChild[0]/domChild[0]</td>
+ <td></td>
+</tr>
+<tr>
+ <td>assertText</td>
+ <td>vaadin=runcomvaadintestscomponentstableTableWithContainerRequiringEqualsForItemId::PID_SLog_row_0</td>
+ <td>3. Button Button0 clicked</td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentstableTableWithContainerRequiringEqualsForItemId::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VScrollTable[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]/domChild[2]</td>
+ <td>8,15</td>
+</tr>
+<tr>
+ <td>contextmenu</td>
+ <td>vaadin=runcomvaadintestscomponentstableTableWithContainerRequiringEqualsForItemId::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VScrollTable[0]/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[0]/domChild[0]/domChild[0]</td>
+ <td></td>
+</tr>
+<tr>
+ <td>assertText</td>
+ <td>vaadin=runcomvaadintestscomponentstableTableWithContainerRequiringEqualsForItemId::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VScrollTable[0]/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[0]/domChild[0]/domChild[0]</td>
+ <td>999</td>
+</tr>
+<tr>
+ <td>click</td>
+ <td>vaadin=runcomvaadintestscomponentstableTableWithContainerRequiringEqualsForItemId::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VScrollTable[0]/FocusableScrollPanel[0]/VScrollTable$VScrollTableBody[0]/VScrollTable$VScrollTableBody$VScrollTableRow[0]/VButton[0]/domChild[0]/domChild[0]</td>
+ <td></td>
+</tr>
+<tr>
+ <td>assertText</td>
+ <td>vaadin=runcomvaadintestscomponentstableTableWithContainerRequiringEqualsForItemId::PID_SLog_row_0</td>
+ <td>4. Button Button999 clicked</td>
+</tr>
+
+</tbody></table>
+</body>
+</html>
diff --git a/tests/testbench/com/vaadin/tests/components/table/TableWithContainerRequiringEqualsForItemId.java b/tests/testbench/com/vaadin/tests/components/table/TableWithContainerRequiringEqualsForItemId.java
new file mode 100644
index 0000000000..1b0335b673
--- /dev/null
+++ b/tests/testbench/com/vaadin/tests/components/table/TableWithContainerRequiringEqualsForItemId.java
@@ -0,0 +1,128 @@
+package com.vaadin.tests.components.table;
+
+import java.util.Date;
+
+import com.vaadin.data.util.BeanContainer;
+import com.vaadin.data.util.BeanItem;
+import com.vaadin.tests.components.TestBase;
+import com.vaadin.tests.util.Log;
+import com.vaadin.ui.Button;
+import com.vaadin.ui.Button.ClickEvent;
+import com.vaadin.ui.Component;
+import com.vaadin.ui.Table;
+import com.vaadin.ui.themes.Reindeer;
+
+public class TableWithContainerRequiringEqualsForItemId extends TestBase {
+
+ private MyEntityContainer container = new MyEntityContainer();
+ private Log log = new Log(10);
+
+ public static class MyEntityContainer extends BeanContainer<Long, MyEntity> {
+
+ public MyEntityContainer() {
+ super(MyEntity.class);
+ setBeanIdResolver(new BeanIdResolver<Long, TableWithContainerRequiringEqualsForItemId.MyEntity>() {
+
+ public Long getIdForBean(MyEntity bean) {
+ // Return a new instance every time to ensure Table can
+ // handle it
+ return new Long(bean.getId());
+ }
+ });
+
+ }
+
+ @Override
+ public Long getIdByIndex(int index) {
+ // Explicitly get the id using the resolver to make sure the
+ // instance does not stay the same
+ BeanItem<MyEntity> beanItem = getItem(super.getIdByIndex(index));
+ return getBeanIdResolver().getIdForBean(beanItem.getBean());
+ };
+
+ }
+
+ @Override
+ protected void setup() {
+ Table t = new Table("Table with 1000 item");
+ t.addGeneratedColumn("Actions", new Table.ColumnGenerator() {
+ public Component generateCell(final Table source,
+ final Object itemId, final Object columnId) {
+ Button tripFolderLink = new Button("Button" + itemId);
+ tripFolderLink.addListener(new Button.ClickListener() {
+ public void buttonClick(final ClickEvent event) {
+ log.log("Button " + event.getButton().getCaption()
+ + " clicked");
+ }
+ });
+ tripFolderLink.setStyleName(Reindeer.BUTTON_SMALL);
+ return tripFolderLink;
+ }
+ });
+
+ for (int i = 0; i < 1000; i++) {
+ MyEntity myEntity = new MyEntity(i + "st");
+ myEntity.setCreated(new Date(new Date().getTime() - 24 * 60 * 60
+ * 1000L));
+ myEntity.setId(i);
+ container.addBean(myEntity);
+ // entityProvider.addEntity(myEntity);
+ }
+
+ t.setContainerDataSource(container);
+ t.setVisibleColumns(new String[] { "id", "created", "name", "Actions" });
+
+ addComponent(t);
+ addComponent(log);
+
+ t.sort(new Object[] { "id" }, new boolean[] { false });
+
+ }
+
+ @Override
+ protected String getDescription() {
+ return "Test that verifies that Table works correctly with containers which do not return the same instance of the itemId object but instead requires an itemId.equals(otherItemId) check";
+ }
+
+ @Override
+ protected Integer getTicketNumber() {
+ return 8712;
+ }
+
+ public static class MyEntity {
+
+ private long id;
+
+ private String name;
+
+ private Date created;
+
+ public MyEntity() {
+ }
+
+ public MyEntity(String string) {
+ name = string;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public Date getCreated() {
+ return created;
+ }
+
+ public void setCreated(Date created) {
+ this.created = created;
+ }
+
+ public long getId() {
+ return id;
+ }
+
+ public void setId(long id) {
+ this.id = id;
+ }
+ }
+
+}
diff --git a/tests/testbench/com/vaadin/tests/dd/NotPaintedAcceptSource.html b/tests/testbench/com/vaadin/tests/dd/NotPaintedAcceptSource.html
new file mode 100644
index 0000000000..fd45e7284d
--- /dev/null
+++ b/tests/testbench/com/vaadin/tests/dd/NotPaintedAcceptSource.html
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head profile="http://selenium-ide.openqa.org/profiles/test-case">
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<link rel="selenium.base" href="http://localhost:8888/" />
+<title>New Test</title>
+</head>
+<body>
+<table cellpadding="1" cellspacing="1" border="1">
+<thead>
+<tr><td rowspan="1" colspan="3">New Test</td></tr>
+</thead><tbody>
+<tr>
+ <td>open</td>
+ <td>/run/com.vaadin.tests.dd.NotPaintedAcceptSource?restartApplication</td>
+ <td></td>
+</tr>
+<!--Drag value 0 to target-->
+<tr>
+ <td>drag</td>
+ <td>vaadin=runcomvaadintestsddNotPaintedAcceptSource::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VHorizontalLayout[0]/ChildComponentContainer[0]/VScrollTable[0]/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[0]/domChild[0]/domChild[0]</td>
+ <td>50,9</td>
+</tr>
+<tr>
+ <td>drop</td>
+ <td>vaadin=runcomvaadintestsddNotPaintedAcceptSource::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VHorizontalLayout[0]/ChildComponentContainer[1]/VScrollTable[0]/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[0]/domChild[0]/domChild[0]</td>
+ <td>124,20</td>
+</tr>
+<!--Assert drag was successful-->
+<tr>
+ <td>assertText</td>
+ <td>vaadin=runcomvaadintestsddNotPaintedAcceptSource::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VHorizontalLayout[0]/ChildComponentContainer[1]/VScrollTable[0]/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[0]</td>
+ <td>Source 1 value 0</td>
+</tr>
+<!--Swap source and verify it was properly painted-->
+<tr>
+ <td>click</td>
+ <td>vaadin=runcomvaadintestsddNotPaintedAcceptSource::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[1]/VButton[0]/domChild[0]/domChild[0]</td>
+ <td></td>
+</tr>
+<tr>
+ <td>assertText</td>
+ <td>vaadin=runcomvaadintestsddNotPaintedAcceptSource::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VHorizontalLayout[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]</td>
+ <td>Source 2</td>
+</tr>
+<!--Drag value 0 from source 2 and verify-->
+<tr>
+ <td>drag</td>
+ <td>vaadin=runcomvaadintestsddNotPaintedAcceptSource::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VHorizontalLayout[0]/ChildComponentContainer[0]/VScrollTable[0]/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[0]/domChild[0]/domChild[0]</td>
+ <td>19,8</td>
+</tr>
+<tr>
+ <td>drop</td>
+ <td>vaadin=runcomvaadintestsddNotPaintedAcceptSource::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VHorizontalLayout[0]/ChildComponentContainer[1]/VScrollTable[0]/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[2]/domChild[0]/domChild[0]</td>
+ <td>139,18</td>
+</tr>
+<tr>
+ <td>contextmenu</td>
+ <td>vaadin=runcomvaadintestsddNotPaintedAcceptSource::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VHorizontalLayout[0]/ChildComponentContainer[1]/VScrollTable[0]/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[3]/domChild[0]/domChild[0]</td>
+ <td></td>
+</tr>
+<tr>
+ <td>assertText</td>
+ <td>vaadin=runcomvaadintestsddNotPaintedAcceptSource::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VHorizontalLayout[0]/ChildComponentContainer[1]/VScrollTable[0]/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[3]/domChild[0]/domChild[0]</td>
+ <td>Source 2 value 0</td>
+</tr>
+
+</tbody></table>
+</body>
+</html>
diff --git a/tests/testbench/com/vaadin/tests/dd/NotPaintedAcceptSource.java b/tests/testbench/com/vaadin/tests/dd/NotPaintedAcceptSource.java
new file mode 100644
index 0000000000..74774f09ab
--- /dev/null
+++ b/tests/testbench/com/vaadin/tests/dd/NotPaintedAcceptSource.java
@@ -0,0 +1,91 @@
+package com.vaadin.tests.dd;
+
+import com.vaadin.data.Item;
+import com.vaadin.event.dd.DragAndDropEvent;
+import com.vaadin.event.dd.DropHandler;
+import com.vaadin.event.dd.acceptcriteria.AcceptCriterion;
+import com.vaadin.event.dd.acceptcriteria.SourceIs;
+import com.vaadin.tests.components.TestBase;
+import com.vaadin.ui.AbstractSelect.AbstractSelectTargetDetails;
+import com.vaadin.ui.Button;
+import com.vaadin.ui.Button.ClickEvent;
+import com.vaadin.ui.HorizontalLayout;
+import com.vaadin.ui.Table;
+import com.vaadin.ui.Table.TableDragMode;
+import com.vaadin.ui.Table.TableTransferable;
+
+public class NotPaintedAcceptSource extends TestBase {
+
+ @Override
+ protected void setup() {
+ final Table source1 = createTable("Source 1");
+ final Table source2 = createTable("Source 2");
+ final Table target = createTable("Target");
+
+ source1.setDragMode(TableDragMode.ROW);
+ source2.setDragMode(TableDragMode.ROW);
+
+ target.setDropHandler(new DropHandler() {
+ public AcceptCriterion getAcceptCriterion() {
+ return new SourceIs(source1, source2);
+ }
+
+ public void drop(DragAndDropEvent event) {
+ TableTransferable transferable = (TableTransferable) event
+ .getTransferable();
+ Item item = transferable.getSourceComponent().getItem(
+ transferable.getItemId());
+ Object value = item.getItemProperty("value").getValue();
+ AbstractSelectTargetDetails targetDetails = (AbstractSelectTargetDetails) event
+ .getTargetDetails();
+ Object targetItemId = targetDetails.getItemIdOver();
+ Object addItemAfter = target.addItemAfter(targetItemId);
+ target.getItem(addItemAfter).getItemProperty("value")
+ .setValue(value);
+ transferable.getSourceComponent().removeItem(
+ transferable.getItemId());
+ }
+ });
+
+ final HorizontalLayout horizontalLayout = new HorizontalLayout();
+ horizontalLayout.setSpacing(true);
+ horizontalLayout.addComponent(source1);
+ horizontalLayout.addComponent(target);
+
+ addComponent(horizontalLayout);
+
+ addComponent(new Button("Swap sources", new Button.ClickListener() {
+ public void buttonClick(ClickEvent event) {
+ if (source1.getParent() != null) {
+ horizontalLayout.replaceComponent(source1, source2);
+ } else {
+ horizontalLayout.replaceComponent(source2, source1);
+ }
+ target.requestRepaint();
+ }
+ }));
+
+ }
+
+ private Table createTable(String caption) {
+ Table table = new Table(caption);
+ table.addContainerProperty("value", String.class, "");
+ for (int i = 0; i < 10; i++) {
+ table.addItem(new Object[] { caption + " value " + i },
+ Integer.valueOf(i));
+ }
+ table.setWidth("300px");
+ return table;
+ }
+
+ @Override
+ protected String getDescription() {
+ return "Including a component in an accept criterion when the actual component is not included in a layout and thus not painted should still allow painting the component properly when it is added to a layout.";
+ }
+
+ @Override
+ protected Integer getTicketNumber() {
+ return Integer.valueOf(8730);
+ }
+
+}
diff --git a/tests/testbench/com/vaadin/tests/layouts/layouttester/LayoutTesterApplication.html b/tests/testbench/com/vaadin/tests/layouts/layouttester/LayoutTesterApplication.html
index 4bc409b881..8408aba9fd 100644
--- a/tests/testbench/com/vaadin/tests/layouts/layouttester/LayoutTesterApplication.html
+++ b/tests/testbench/com/vaadin/tests/layouts/layouttester/LayoutTesterApplication.html
@@ -13,7 +13,7 @@
</thead><tbody>
<tr>
<td>open</td>
- <td>/run/com.vaadin.tests.layouts.layouttester.LayoutTesterApplication</td>
+ <td>/run/com.vaadin.tests.layouts.layouttester.LayoutTesterApplication?restartApplication</td>
<td></td>
</tr>
<tr>