diff options
author | Leif Åstrand <leif@vaadin.com> | 2011-11-22 12:14:22 +0200 |
---|---|---|
committer | Leif Åstrand <leif@vaadin.com> | 2011-11-22 12:14:22 +0200 |
commit | e578248b13275b94c9985aaadc1bf16b4c8b20e5 (patch) | |
tree | 0a5aba877d47d538869fc061ee941f264a84af8d | |
parent | 4b1d80a7b8906bd8ac72e762ea19e3cb55827f6b (diff) | |
parent | b23d8dfaa5c27cd4bed0df1a654e59b0464707b5 (diff) | |
download | vaadin-framework-e578248b13275b94c9985aaadc1bf16b4c8b20e5.tar.gz vaadin-framework-e578248b13275b94c9985aaadc1bf16b4c8b20e5.zip |
Merge remote branch 'origin/6.8'
Conflicts:
tests/integration_tests.xml
29 files changed, 1494 insertions, 195 deletions
diff --git a/WebContent/VAADIN/themes/base/dragwrapper/dragwrapper.css b/WebContent/VAADIN/themes/base/dragwrapper/dragwrapper.css index f7654a0296..2061fec8c3 100644 --- a/WebContent/VAADIN/themes/base/dragwrapper/dragwrapper.css +++ b/WebContent/VAADIN/themes/base/dragwrapper/dragwrapper.css @@ -3,6 +3,27 @@ -moz-border-radius: 4px; -webkit-border-radius: 4px; border-radius: 4px; + position: relative; +} +[draggable=true] { + -khtml-user-drag: element; + -webkit-user-drag: element; + -khtml-user-select: none; + -webkit-user-select: none; +} +.v-ie .v-ddwrapper a.drag-start { + display: block; + position: absolute; + top: 0; + bottom: 0; + left: 0; + right: 0; + width: 100%; + height: 100%; + opacity: 0; + /* Some color needed to make it draggable */ + background-color:cyan; + filter: alpha(opacity=0); } .v-ddwrapper-over { border: 2px solid #1d9dff; diff --git a/WebContent/release-notes.html b/WebContent/release-notes.html index b05a5e1548..574c3792ef 100644 --- a/WebContent/release-notes.html +++ b/WebContent/release-notes.html @@ -481,11 +481,11 @@ </p> <ul> - <li>Mozilla Firefox 3-6</li> + <li>Mozilla Firefox 3-8</li> <li>Internet Explorer 6-9</li> <li>Safari 4-5</li> <li>Opera 10-11</li> - <li>Google Chrome 13</li> + <li>Google Chrome 13-15</li> </ul> <h2 id="vaadinontheweb">Vaadin on the Web</h2> diff --git a/WebContent/statictestfiles/EmbedSizeHostPage.html b/WebContent/statictestfiles/EmbedSizeHostPage.html new file mode 100644 index 0000000000..06dfd5dfd7 --- /dev/null +++ b/WebContent/statictestfiles/EmbedSizeHostPage.html @@ -0,0 +1,43 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> +<style type="text/css">html, body {height:100%;margin:0;}</style><link rel="shortcut icon" type="image/vnd.microsoft.icon" href="/VAADIN/themes/reindeer/favicon.ico" /><link rel="icon" type="image/vnd.microsoft.icon" href="/VAADIN/themes/reindeer/favicon.ico" /><title>com.vaadin.tests.integration.EmbedSizeTest</title> +</head> +<body scroll="auto" class="v-generated-body"> +<script type="text/javascript"> +//<![CDATA[ +if(!vaadin || !vaadin.vaadinConfigurations) { + if(!vaadin) { var vaadin = {}} +vaadin.vaadinConfigurations = {}; +if (!vaadin.themesLoaded) { vaadin.themesLoaded = {}; } +vaadin.debug = true; +document.write('<iframe tabIndex="-1" id="__gwt_historyFrame" style="position:absolute;width:0;height:0;border:0;overflow:hidden;" src="javascript:false"></iframe>'); +document.write("<script language='javascript' src='/VAADIN/widgetsets/com.vaadin.terminal.gwt.DefaultWidgetSet/com.vaadin.terminal.gwt.DefaultWidgetSet.nocache.js?1321018813162'><\/script>"); +} +vaadin.vaadinConfigurations["runcomvaadintestsintegrationEmbedSizeTest-225840176"] = {appUri:'/run/com.vaadin.tests.integration.EmbedSizeTest', themeUri:"/VAADIN/themes/reindeer", versionInfo : {vaadinVersion:"9.9.9.INTERNAL-DEBUG-BUILD",applicationVersion:"NONVERSIONED"},"comErrMsg": {"caption":"Communication problem","message" : "Take note of any unsaved data, and <u>click here<\/u> to continue.","url" : null},"authErrMsg": {"caption":"Authentication problem","message" : "Take note of any unsaved data, and <u>click here<\/u> to continue.","url" : null}}; +//]]> +</script> +<script type="text/javascript"> +//<![CDATA[ +if(!vaadin.themesLoaded['reindeer']) { +var stylesheet = document.createElement('link'); +stylesheet.setAttribute('rel', 'stylesheet'); +stylesheet.setAttribute('type', 'text/css'); +stylesheet.setAttribute('href', '/VAADIN/themes/reindeer/styles.css'); +document.getElementsByTagName('head')[0].appendChild(stylesheet); +vaadin.themesLoaded['reindeer'] = true; +} +//]]> +</script> +<script type="text/javascript"> +//<![CDATA[ +setTimeout('if (typeof com_vaadin_terminal_gwt_DefaultWidgetSet == "undefined") {alert("Failed to load the widgetset: /VAADIN/widgetsets/com.vaadin.terminal.gwt.DefaultWidgetSet/com.vaadin.terminal.gwt.DefaultWidgetSet.nocache.js?1321018813162")};',15000); +//]]> +</script> +<div style="width: 80%; border: 1px solid black"> +<h1>Test page for resize events with embedded applications</h1> +<div id="runcomvaadintestsintegrationEmbedSizeTest-225840176" class="v-app v-theme-reindeer v-app-EmbedSizeTest" ><div class="v-app-loading"></div></div> +<noscript>You have to enable javascript in your browser to use an application built with Vaadin.</noscript></body> +</div> +</html> diff --git a/src/com/vaadin/terminal/gwt/DefaultWidgetSet.gwt.xml b/src/com/vaadin/terminal/gwt/DefaultWidgetSet.gwt.xml index 5884cdaceb..bdbcc75222 100644 --- a/src/com/vaadin/terminal/gwt/DefaultWidgetSet.gwt.xml +++ b/src/com/vaadin/terminal/gwt/DefaultWidgetSet.gwt.xml @@ -1,6 +1,6 @@ <module> - <!-- This GWT module defines the Vaadin DefaultWidgetSet. This is the module - you want to extend when creating an extended widget set, or when creating + <!-- This GWT module defines the Vaadin DefaultWidgetSet. This is the module + you want to extend when creating an extended widget set, or when creating a specialized widget set with a subset of the components. --> <!-- Hint for WidgetSetBuilder not to automatically update the file --> @@ -12,7 +12,7 @@ <source path="client" /> - <!-- Use own Scheduler implementation to be able to track if commands are + <!-- Use own Scheduler implementation to be able to track if commands are running --> <replace-with class="com.vaadin.terminal.gwt.client.VSchedulerImpl"> <when-type-is class="com.google.gwt.core.client.impl.SchedulerImpl" /> @@ -52,6 +52,16 @@ </any> </replace-with> + <replace-with + class="com.vaadin.terminal.gwt.client.ui.VDragAndDropWrapperIE"> + <when-type-is + class="com.vaadin.terminal.gwt.client.ui.VDragAndDropWrapper" /> + <any> + <when-property-is name="user.agent" value="ie6" /> + <when-property-is name="user.agent" value="ie8" /> + </any> + </replace-with> + <!-- Workaround for #6682. Remove when fixed in GWT. --> <replace-with class="com.google.gwt.dom.client.VaadinDOMImplSafari"> <when-type-is class="com.google.gwt.dom.client.DOMImpl" /> diff --git a/src/com/vaadin/terminal/gwt/client/ui/VDragAndDropWrapper.java b/src/com/vaadin/terminal/gwt/client/ui/VDragAndDropWrapper.java index 7fef345586..05d69d7dec 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VDragAndDropWrapper.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VDragAndDropWrapper.java @@ -25,14 +25,15 @@ import com.google.gwt.user.client.ui.Widget; import com.google.gwt.xhr.client.ReadyStateChangeHandler; import com.google.gwt.xhr.client.XMLHttpRequest; import com.vaadin.terminal.gwt.client.ApplicationConnection; -import com.vaadin.terminal.gwt.client.BrowserInfo; import com.vaadin.terminal.gwt.client.MouseEventDetails; import com.vaadin.terminal.gwt.client.Paintable; import com.vaadin.terminal.gwt.client.RenderInformation; import com.vaadin.terminal.gwt.client.RenderInformation.Size; import com.vaadin.terminal.gwt.client.UIDL; import com.vaadin.terminal.gwt.client.Util; +import com.vaadin.terminal.gwt.client.VConsole; import com.vaadin.terminal.gwt.client.VTooltip; +import com.vaadin.terminal.gwt.client.ValueMap; import com.vaadin.terminal.gwt.client.ui.dd.DDUtil; import com.vaadin.terminal.gwt.client.ui.dd.HorizontalDropLocation; import com.vaadin.terminal.gwt.client.ui.dd.VAbstractDropHandler; @@ -55,8 +56,11 @@ import com.vaadin.terminal.gwt.client.ui.dd.VerticalDropLocation; */ public class VDragAndDropWrapper extends VCustomComponent implements VHasDropHandler { + public static final String DRAG_START_MODE = "dragStartMode"; + public static final String HTML5_DATA_FLAVORS = "html5-data-flavors"; private static final String CLASSNAME = "v-ddwrapper"; + protected static final String DRAGGABLE = "draggable"; public VDragAndDropWrapper() { super(); @@ -82,6 +86,7 @@ public class VDragAndDropWrapper extends VCustomComponent implements } } }, TouchStartEvent.getType()); + sinkEvents(Event.TOUCHEVENTS); } @@ -102,7 +107,7 @@ public class VDragAndDropWrapper extends VCustomComponent implements * @return true if the event was handled as a drag start event */ private boolean startDrag(NativeEvent event) { - if (dragStarMode > 0) { + if (dragStartMode == WRAPPER || dragStartMode == COMPONENT) { VTransferable transferable = new VTransferable(); transferable.setDragSource(VDragAndDropWrapper.this); @@ -121,7 +126,7 @@ public class VDragAndDropWrapper extends VCustomComponent implements transferable.setData("mouseDown", new MouseEventDetails(event).serialize()); - if (dragStarMode == WRAPPER) { + if (dragStartMode == WRAPPER) { dragEvent.createDragImage(getElement(), true); } else { dragEvent.createDragImage(((Widget) paintable).getElement(), @@ -132,16 +137,21 @@ public class VDragAndDropWrapper extends VCustomComponent implements return false; } + protected final static int NONE = 0; + protected final static int COMPONENT = 1; + protected final static int WRAPPER = 2; + protected final static int HTML5 = 3; + + protected int dragStartMode; + private ApplicationConnection client; private VAbstractDropHandler dropHandler; private VDragEvent vaadinDragEvent; - private final static int NONE = 0; - private final static int COMPONENT = 1; - private final static int WRAPPER = 2; - private int dragStarMode; private int filecounter = 0; private Map<String, String> fileIdToReceiver; + private ValueMap html5DataFlavors; + private Element dragStartElement; @Override public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { @@ -180,10 +190,35 @@ public class VDragAndDropWrapper extends VCustomComponent implements } startNextUpload(); - dragStarMode = uidl.getIntAttribute("dragStartMode"); + dragStartMode = uidl.getIntAttribute(DRAG_START_MODE); + initDragStartMode(); + html5DataFlavors = uidl.getMapAttribute(HTML5_DATA_FLAVORS); + } + } + + protected void initDragStartMode() { + Element div = getElement(); + if (dragStartMode == HTML5) { + if (dragStartElement == null) { + dragStartElement = getDragStartElement(); + dragStartElement.setPropertyBoolean(DRAGGABLE, true); + VConsole.log("draggable = " + + dragStartElement.getPropertyBoolean(DRAGGABLE)); + hookHtml5DragStart(dragStartElement); + VConsole.log("drag start listeners hooked."); + } + } else { + dragStartElement = null; + if (div.hasAttribute(DRAGGABLE)) { + div.removeAttribute(DRAGGABLE); + } } } + protected Element getDragStartElement() { + return getElement(); + } + private boolean uploading; private ReadyStateChangeHandler readyStateChangeHandler = new ReadyStateChangeHandler() { @@ -227,6 +262,23 @@ public class VDragAndDropWrapper extends VCustomComponent implements } + public boolean html5DragStart(VHtml5DragEvent event) { + if (dragStartMode == HTML5) { + /* + * Populate html5 payload with dataflavors from the serverside + */ + JsArrayString flavors = html5DataFlavors.getKeyArray(); + for (int i = 0; i < flavors.length(); i++) { + String flavor = flavors.get(i); + event.setHtml5DataFlavor(flavor, + html5DataFlavors.getString(flavor)); + } + event.setEffectAllowed("copy"); + return true; + } + return false; + } + public boolean html5DragEnter(VHtml5DragEvent event) { if (dropHandler == null) { return true; @@ -246,8 +298,12 @@ public class VDragAndDropWrapper extends VCustomComponent implements VDragAndDropManager.get().setCurrentDropHandler( getDropHandler()); } - event.preventDefault(); - event.stopPropagation(); + try { + event.preventDefault(); + event.stopPropagation(); + } catch (Exception e) { + // VConsole.log("IE9 fails"); + } return false; } catch (Exception e) { GWT.getUncaughtExceptionHandler().onUncaughtException(e); @@ -277,8 +333,12 @@ public class VDragAndDropWrapper extends VCustomComponent implements } }; dragleavetimer.schedule(350); - event.preventDefault(); - event.stopPropagation(); + try { + event.preventDefault(); + event.stopPropagation(); + } catch (Exception e) { + // VConsole.log("IE9 fails"); + } return false; } catch (Exception e) { GWT.getUncaughtExceptionHandler().onUncaughtException(e); @@ -299,17 +359,20 @@ public class VDragAndDropWrapper extends VCustomComponent implements vaadinDragEvent.setCurrentGwtEvent(event); getDropHandler().dragOver(vaadinDragEvent); - // needed to be set for Safari, otherwise drop will not happen - if (BrowserInfo.get().isWebkit()) { - String s = event.getEffectAllowed(); - if ("all".equals(s) || s.contains("opy")) { - event.setDragEffect("copy"); - } else { - event.setDragEffect(s); - } + + String s = event.getEffectAllowed(); + if ("all".equals(s) || s.contains("opy")) { + event.setDropEffect("copy"); + } else { + event.setDropEffect(s); + } + + try { + event.preventDefault(); + event.stopPropagation(); + } catch (Exception e) { + // VConsole.log("IE9 fails"); } - event.preventDefault(); - event.stopPropagation(); return false; } @@ -349,9 +412,12 @@ public class VDragAndDropWrapper extends VCustomComponent implements VDragAndDropManager.get().endDrag(); vaadinDragEvent = null; - event.preventDefault(); - event.stopPropagation(); - + try { + event.preventDefault(); + event.stopPropagation(); + } catch (Exception e) { + // VConsole.log("IE9 fails"); + } return false; } catch (Exception e) { GWT.getUncaughtExceptionHandler().onUncaughtException(e); @@ -491,51 +557,38 @@ public class VDragAndDropWrapper extends VCustomComponent implements } + protected native void hookHtml5DragStart(Element el) + /*-{ + var me = this; + el.addEventListener("dragstart", function(ev) { + return me.@com.vaadin.terminal.gwt.client.ui.VDragAndDropWrapper::html5DragStart(Lcom/vaadin/terminal/gwt/client/ui/dd/VHtml5DragEvent;)(ev); + }, false); + }-*/; + /** * Prototype code, memory leak risk. * * @param el */ - private native void hookHtml5Events(Element el) + protected native void hookHtml5Events(Element el) /*-{ - var me = this; - - if(el.addEventListener) { - el.addEventListener("dragenter", function(ev) { - return me.@com.vaadin.terminal.gwt.client.ui.VDragAndDropWrapper::html5DragEnter(Lcom/vaadin/terminal/gwt/client/ui/dd/VHtml5DragEvent;)(ev); - }, false); - - el.addEventListener("dragleave", function(ev) { - return me.@com.vaadin.terminal.gwt.client.ui.VDragAndDropWrapper::html5DragLeave(Lcom/vaadin/terminal/gwt/client/ui/dd/VHtml5DragEvent;)(ev); - }, false); - - el.addEventListener("dragover", function(ev) { - return me.@com.vaadin.terminal.gwt.client.ui.VDragAndDropWrapper::html5DragOver(Lcom/vaadin/terminal/gwt/client/ui/dd/VHtml5DragEvent;)(ev); - }, false); - - el.addEventListener("drop", function(ev) { - return me.@com.vaadin.terminal.gwt.client.ui.VDragAndDropWrapper::html5DragDrop(Lcom/vaadin/terminal/gwt/client/ui/dd/VHtml5DragEvent;)(ev); - }, false); - - } else { - el.attachEvent("ondragenter", function(ev) { - return me.@com.vaadin.terminal.gwt.client.ui.VDragAndDropWrapper::html5DragEnter(Lcom/vaadin/terminal/gwt/client/ui/dd/VHtml5DragEvent;)(ev); - }); - - el.attachEvent("ondragleave", function(ev) { - return me.@com.vaadin.terminal.gwt.client.ui.VDragAndDropWrapper::html5DragLeave(Lcom/vaadin/terminal/gwt/client/ui/dd/VHtml5DragEvent;)(ev); - }); - - el.attachEvent("ondragover", function(ev) { - return me.@com.vaadin.terminal.gwt.client.ui.VDragAndDropWrapper::html5DragOver(Lcom/vaadin/terminal/gwt/client/ui/dd/VHtml5DragEvent;)(ev); - }); - - el.attachEvent("ondrop", function(ev) { - return me.@com.vaadin.terminal.gwt.client.ui.VDragAndDropWrapper::html5DragDrop(Lcom/vaadin/terminal/gwt/client/ui/dd/VHtml5DragEvent;)(ev); - }); - } - + + el.addEventListener("dragenter", function(ev) { + return me.@com.vaadin.terminal.gwt.client.ui.VDragAndDropWrapper::html5DragEnter(Lcom/vaadin/terminal/gwt/client/ui/dd/VHtml5DragEvent;)(ev); + }, false); + + el.addEventListener("dragleave", function(ev) { + return me.@com.vaadin.terminal.gwt.client.ui.VDragAndDropWrapper::html5DragLeave(Lcom/vaadin/terminal/gwt/client/ui/dd/VHtml5DragEvent;)(ev); + }, false); + + el.addEventListener("dragover", function(ev) { + return me.@com.vaadin.terminal.gwt.client.ui.VDragAndDropWrapper::html5DragOver(Lcom/vaadin/terminal/gwt/client/ui/dd/VHtml5DragEvent;)(ev); + }, false); + + el.addEventListener("drop", function(ev) { + return me.@com.vaadin.terminal.gwt.client.ui.VDragAndDropWrapper::html5DragDrop(Lcom/vaadin/terminal/gwt/client/ui/dd/VHtml5DragEvent;)(ev); + }, false); }-*/; public boolean updateDropDetails(VDragEvent drag) { diff --git a/src/com/vaadin/terminal/gwt/client/ui/VDragAndDropWrapperIE.java b/src/com/vaadin/terminal/gwt/client/ui/VDragAndDropWrapperIE.java new file mode 100644 index 0000000000..89f063eaf9 --- /dev/null +++ b/src/com/vaadin/terminal/gwt/client/ui/VDragAndDropWrapperIE.java @@ -0,0 +1,65 @@ +package com.vaadin.terminal.gwt.client.ui; + +import com.google.gwt.dom.client.AnchorElement; +import com.google.gwt.dom.client.Document; +import com.google.gwt.user.client.Element; +import com.vaadin.terminal.gwt.client.VConsole; + +public class VDragAndDropWrapperIE extends VDragAndDropWrapper { + private AnchorElement anchor = null; + + @Override + protected Element getDragStartElement() { + VConsole.log("IE get drag start element..."); + Element div = getElement(); + if (dragStartMode == HTML5) { + if (anchor == null) { + anchor = Document.get().createAnchorElement(); + anchor.setHref("#"); + anchor.setClassName("drag-start"); + div.appendChild(anchor); + } + VConsole.log("IE get drag start element..."); + return (Element) anchor.cast(); + } else { + if (anchor != null) { + div.removeChild(anchor); + anchor = null; + } + return div; + } + } + + @Override + protected native void hookHtml5DragStart(Element el) + /*-{ + var me = this; + + el.attachEvent("ondragstart", function(ev) { + return me.@com.vaadin.terminal.gwt.client.ui.VDragAndDropWrapper::html5DragStart(Lcom/vaadin/terminal/gwt/client/ui/dd/VHtml5DragEvent;)(ev); + }); + }-*/; + + @Override + protected native void hookHtml5Events(Element el) + /*-{ + var me = this; + + el.attachEvent("ondragenter", function(ev) { + return me.@com.vaadin.terminal.gwt.client.ui.VDragAndDropWrapper::html5DragEnter(Lcom/vaadin/terminal/gwt/client/ui/dd/VHtml5DragEvent;)(ev); + }); + + el.attachEvent("ondragleave", function(ev) { + return me.@com.vaadin.terminal.gwt.client.ui.VDragAndDropWrapper::html5DragLeave(Lcom/vaadin/terminal/gwt/client/ui/dd/VHtml5DragEvent;)(ev); + }); + + el.attachEvent("ondragover", function(ev) { + return me.@com.vaadin.terminal.gwt.client.ui.VDragAndDropWrapper::html5DragOver(Lcom/vaadin/terminal/gwt/client/ui/dd/VHtml5DragEvent;)(ev); + }); + + el.attachEvent("ondrop", function(ev) { + return me.@com.vaadin.terminal.gwt.client.ui.VDragAndDropWrapper::html5DragDrop(Lcom/vaadin/terminal/gwt/client/ui/dd/VHtml5DragEvent;)(ev); + }); + }-*/; + +} diff --git a/src/com/vaadin/terminal/gwt/client/ui/VFilterSelect.java b/src/com/vaadin/terminal/gwt/client/ui/VFilterSelect.java index 6f90a140e8..2af04cb97e 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VFilterSelect.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VFilterSelect.java @@ -7,8 +7,10 @@ package com.vaadin.terminal.gwt.client.ui; import java.util.ArrayList; import java.util.Collection; import java.util.Date; +import java.util.HashSet; import java.util.Iterator; import java.util.List; +import java.util.Set; import com.google.gwt.core.client.Scheduler; import com.google.gwt.core.client.Scheduler.ScheduledCommand; @@ -48,6 +50,7 @@ import com.vaadin.terminal.gwt.client.Focusable; import com.vaadin.terminal.gwt.client.Paintable; import com.vaadin.terminal.gwt.client.UIDL; import com.vaadin.terminal.gwt.client.Util; +import com.vaadin.terminal.gwt.client.VConsole; import com.vaadin.terminal.gwt.client.VTooltip; /** @@ -55,6 +58,7 @@ import com.vaadin.terminal.gwt.client.VTooltip; * * TODO needs major refactoring (to be extensible etc) */ +@SuppressWarnings("deprecation") public class VFilterSelect extends Composite implements Paintable, Field, KeyDownHandler, KeyUpHandler, ClickHandler, FocusHandler, BlurHandler, Focusable { @@ -95,7 +99,15 @@ public class VFilterSelect extends Composite implements Paintable, Field, sb.append(Util.escapeAttribute(iconUri)); sb.append("\" alt=\"\" class=\"v-icon\" />"); } - sb.append("<span>" + Util.escapeHTML(caption) + "</span>"); + String content; + if ("".equals(caption)) { + // Ensure that empty options use the same height as other + // options and are not collapsed (#7506) + content = " "; + } else { + content = Util.escapeHTML(caption); + } + sb.append("<span>" + content + "</span>"); return sb.toString(); } @@ -285,7 +297,7 @@ public class VFilterSelect extends Composite implements Paintable, Field, .getText().length() - lastFilter.length()); } else if (hasNextPage()) { - lastIndex = index - 1; // save for paging + selectPopupItemWhenResponseIsReceived = Select.FIRST; filterOptions(currentPage + 1, lastFilter); } } @@ -304,7 +316,7 @@ public class VFilterSelect extends Composite implements Paintable, Field, .getText().length() - lastFilter.length()); } else if (index == -1) { if (currentPage > 0) { - lastIndex = index + 1; // save for paging + selectPopupItemWhenResponseIsReceived = Select.LAST; filterOptions(currentPage - 1, lastFilter); } } else { @@ -329,7 +341,20 @@ public class VFilterSelect extends Composite implements Paintable, Field, @Override public void run() { if (pagesToScroll != 0) { - filterOptions(currentPage + pagesToScroll, lastFilter); + if (!waitingForFilteringResponse) { + /* + * Avoid scrolling while we are waiting for a response + * because otherwise the waiting flag will be reset in + * the first response and the second response will be + * ignored, causing an empty popup... + * + * As long as the scrolling delay is suitable + * double/triple clicks will work by scrolling two or + * three pages at a time and this should not be a + * problem. + */ + filterOptions(currentPage + pagesToScroll, lastFilter); + } pagesToScroll = 0; } } @@ -338,7 +363,7 @@ public class VFilterSelect extends Composite implements Paintable, Field, if (currentPage + pagesToScroll > 0) { pagesToScroll--; cancel(); - schedule(100); + schedule(200); } } @@ -347,7 +372,7 @@ public class VFilterSelect extends Composite implements Paintable, Field, * pageLength) { pagesToScroll++; cancel(); - schedule(100); + schedule(200); } } } @@ -537,6 +562,13 @@ public class VFilterSelect extends Composite implements Paintable, Field, public class SuggestionMenu extends MenuBar implements SubPartAware, LoadHandler { + /** + * Tracks the item that is currently selected using the keyboard. This + * is need only because mouseover changes the selection and we do not + * want to use that selection when pressing enter to select the item. + */ + private MenuItem keyboardSelectedItem; + private VLazyExecutor delayedImageLoadExecutioner = new VLazyExecutor( 100, new ScheduledCommand() { @@ -583,6 +615,10 @@ public class VFilterSelect extends Composite implements Paintable, Field, */ public void setSuggestions( Collection<FilterSelectSuggestion> suggestions) { + // Reset keyboard selection when contents is updated to avoid + // reusing old, invalid data + setKeyboardSelectedItem(null); + clearItems(); final Iterator<FilterSelectSuggestion> it = suggestions.iterator(); while (it.hasNext()) { @@ -622,8 +658,8 @@ public class VFilterSelect extends Composite implements Paintable, Field, return; } - selecting = filtering; - if (!filtering) { + updateSelectionWhenReponseIsReceived = waitingForFilteringResponse; + if (!waitingForFilteringResponse) { doPostFilterSelectedItemAction(); } } @@ -635,7 +671,7 @@ public class VFilterSelect extends Composite implements Paintable, Field, final MenuItem item = getSelectedItem(); final String enteredItemValue = tb.getText(); - selecting = false; + updateSelectionWhenReponseIsReceived = false; // check for exact match in menu int p = getItems().size(); @@ -730,6 +766,25 @@ public class VFilterSelect extends Composite implements Paintable, Field, delayedImageLoadExecutioner.trigger(); } + + public void selectFirstItem() { + MenuItem firstItem = getItems().get(0); + selectItem(firstItem); + } + + private MenuItem getKeyboardSelectedItem() { + return keyboardSelectedItem; + } + + private void setKeyboardSelectedItem(MenuItem firstItem) { + keyboardSelectedItem = firstItem; + } + + public void selectLastItem() { + List<MenuItem> items = getItems(); + MenuItem lastItem = items.get(items.size() - 1); + selectItem(lastItem); + } } public static final int FILTERINGMODE_OFF = 0; @@ -741,6 +796,8 @@ public class VFilterSelect extends Composite implements Paintable, Field, protected int pageLength = 10; + private boolean enableDebug = false; + private final FlowPanel panel = new FlowPanel(); /** @@ -814,19 +871,24 @@ public class VFilterSelect extends Composite implements Paintable, Field, * A collection of available suggestions (options) as received from the * server. */ - private final Collection<FilterSelectSuggestion> currentSuggestions = new ArrayList<FilterSelectSuggestion>(); + private final List<FilterSelectSuggestion> currentSuggestions = new ArrayList<FilterSelectSuggestion>(); private boolean immediate; private String selectedOptionKey; - private boolean filtering = false; - private boolean selecting = false; - private boolean tabPressed = false; + private boolean waitingForFilteringResponse = false; + private boolean updateSelectionWhenReponseIsReceived = false; + private boolean tabPressedWhenPopupOpen = false; private boolean initDone = false; private String lastFilter = ""; - private int lastIndex = -1; // last selected index when using arrows + + private enum Select { + NONE, FIRST, LAST + }; + + private Select selectPopupItemWhenResponseIsReceived = Select.NONE; /** * The current suggestion selected from the dropdown. This is one of the @@ -961,7 +1023,7 @@ public class VFilterSelect extends Composite implements Paintable, Field, } } - filtering = true; + waitingForFilteringResponse = true; client.updateVariable(paintableId, "filter", filter, false); client.updateVariable(paintableId, "page", page, true); lastFilter = filter; @@ -1025,14 +1087,13 @@ public class VFilterSelect extends Composite implements Paintable, Field, inputPrompt = ""; } - suggestionPopup.setPagingEnabled(true); suggestionPopup.updateStyleNames(uidl); allowNewItem = uidl.hasAttribute("allownewitem"); lastNewItemString = null; currentSuggestions.clear(); - if (!filtering) { + if (!waitingForFilteringResponse) { /* * Clear the current suggestions as the server response always * includes the new ones. Exception is when filtering, then we need @@ -1052,6 +1113,8 @@ public class VFilterSelect extends Composite implements Paintable, Field, final UIDL options = uidl.getChildUIDL(0); if (uidl.hasAttribute("totalMatches")) { totalMatches = uidl.getIntAttribute("totalMatches"); + } else { + totalMatches = 0; } // used only to calculate minimum popup width @@ -1063,7 +1126,7 @@ public class VFilterSelect extends Composite implements Paintable, Field, optionUidl); currentSuggestions.add(suggestion); if (optionUidl.hasAttribute("selected")) { - if (!filtering || popupOpenerClicked) { + if (!waitingForFilteringResponse || popupOpenerClicked) { String newSelectedOptionKey = Integer.toString(suggestion .getOptionKey()); if (!newSelectedOptionKey.equals(selectedOptionKey) @@ -1087,10 +1150,11 @@ public class VFilterSelect extends Composite implements Paintable, Field, captions += Util.escapeHTML(suggestion.getReplacementString()); } - if ((!filtering || popupOpenerClicked) && uidl.hasVariable("selected") + if ((!waitingForFilteringResponse || popupOpenerClicked) + && uidl.hasVariable("selected") && uidl.getStringArrayVariable("selected").length == 0) { // select nulled - if (!filtering || !popupOpenerClicked) { + if (!waitingForFilteringResponse || !popupOpenerClicked) { if (!focused) { /* * client.updateComponent overwrites all styles so we must @@ -1108,41 +1172,35 @@ public class VFilterSelect extends Composite implements Paintable, Field, selectedOptionKey = null; } - if (filtering + if (waitingForFilteringResponse && lastFilter.toLowerCase().equals( uidl.getStringVariable("filter"))) { suggestionPopup.showSuggestions(currentSuggestions, currentPage, totalMatches); - filtering = false; - if (!popupOpenerClicked && lastIndex != -1) { + waitingForFilteringResponse = false; + if (!popupOpenerClicked + && selectPopupItemWhenResponseIsReceived != Select.NONE) { // we're paging w/ arrows - MenuItem activeMenuItem; - if (lastIndex == 0) { - // going up, select last item - int lastItem = pageLength - 1; - List<MenuItem> items = suggestionPopup.menu.getItems(); - /* - * The first page can contain less than 10 items if the null - * selection item is filtered away - */ - if (lastItem >= items.size()) { - lastItem = items.size() - 1; - } - activeMenuItem = items.get(lastItem); - suggestionPopup.menu.selectItem(activeMenuItem); + if (selectPopupItemWhenResponseIsReceived == Select.LAST) { + suggestionPopup.menu.selectLastItem(); } else { - // going down, select first item - activeMenuItem = suggestionPopup.menu.getItems().get(0); - suggestionPopup.menu.selectItem(activeMenuItem); + suggestionPopup.menu.selectFirstItem(); } + // This is used for paging so we update the keyboard selection + // variable as well. + MenuItem activeMenuItem = suggestionPopup.menu + .getSelectedItem(); + suggestionPopup.menu.setKeyboardSelectedItem(activeMenuItem); + + // Update text field to contain the correct text setTextboxText(activeMenuItem.getText()); tb.setSelectionRange(lastFilter.length(), activeMenuItem .getText().length() - lastFilter.length()); - lastIndex = -1; // reset + selectPopupItemWhenResponseIsReceived = Select.NONE; // reset } - if (selecting) { + if (updateSelectionWhenReponseIsReceived) { suggestionPopup.menu.doPostFilterSelectedItemAction(); } } @@ -1254,7 +1312,7 @@ public class VFilterSelect extends Composite implements Paintable, Field, * The suggestion that just got selected. */ public void onSuggestionSelected(FilterSelectSuggestion suggestion) { - selecting = false; + updateSelectionWhenReponseIsReceived = false; currentSuggestion = suggestion; String newKey; @@ -1316,6 +1374,15 @@ public class VFilterSelect extends Composite implements Paintable, Field, marginTop + "px"); } + private static Set<Integer> navigationKeyCodes = new HashSet<Integer>(); + static { + navigationKeyCodes.add(KeyCodes.KEY_DOWN); + navigationKeyCodes.add(KeyCodes.KEY_UP); + navigationKeyCodes.add(KeyCodes.KEY_PAGEDOWN); + navigationKeyCodes.add(KeyCodes.KEY_PAGEUP); + navigationKeyCodes.add(KeyCodes.KEY_ENTER); + } + /* * (non-Javadoc) * @@ -1325,34 +1392,39 @@ public class VFilterSelect extends Composite implements Paintable, Field, */ public void onKeyDown(KeyDownEvent event) { if (enabled && !readonly) { - if (event.getNativeKeyCode() == KeyCodes.KEY_ENTER) { - // Same reaction to enter no matter on whether the popup is open - if (suggestionPopup.isAttached()) { - filterOptions(currentPage); - } else if (currentSuggestion != null - && tb.getText().equals( - currentSuggestion.getReplacementString())) { - // Retain behavior from #6686 by returning without stopping - // propagation if there's nothing to do - return; - } - if (currentSuggestions.size() == 1 && !allowNewItem) { - // If there is only one suggestion, select that - suggestionPopup.menu.selectItem(suggestionPopup.menu - .getItems().get(0)); - } - suggestionPopup.menu.doSelectedItemAction(); + int keyCode = event.getNativeKeyCode(); + debug("key down: " + keyCode); + if (waitingForFilteringResponse + && navigationKeyCodes.contains(keyCode)) { + /* + * Keyboard navigation events should not be handled while we are + * waiting for a response. This avoids flickering, disappearing + * items, wrongly interpreted responses and more. + */ + debug("Ignoring " + keyCode + + " because we are waiting for a filtering response"); + DOM.eventPreventDefault(DOM.eventGetCurrentEvent()); event.stopPropagation(); return; - } else if (suggestionPopup.isAttached()) { + } + + if (suggestionPopup.isAttached()) { + debug("Keycode " + keyCode + " target is popup"); popupKeyDown(event); } else { + debug("Keycode " + keyCode + " target is text field"); inputFieldKeyDown(event); } } } + private void debug(String string) { + if (enableDebug) { + VConsole.error(string); + } + } + /** * Triggered when a key is pressed in the text box * @@ -1365,17 +1437,31 @@ public class VFilterSelect extends Composite implements Paintable, Field, case KeyCodes.KEY_UP: case KeyCodes.KEY_PAGEDOWN: case KeyCodes.KEY_PAGEUP: - if (!suggestionPopup.isAttached()) { - // open popup as from gadget - filterOptions(-1, ""); - lastFilter = ""; - tb.selectAll(); - } + // open popup as from gadget + filterOptions(-1, ""); + lastFilter = ""; + tb.selectAll(); break; - case KeyCodes.KEY_TAB: - if (suggestionPopup.isAttached()) { - filterOptions(currentPage, tb.getText()); + case KeyCodes.KEY_ENTER: + /* + * This only handles the case when new items is allowed, a text is + * entered, the popup opener button is clicked to close the popup + * and enter is then pressed (see #7560). + */ + if (!allowNewItem) { + return; } + + if (currentSuggestion != null + && tb.getText().equals( + currentSuggestion.getReplacementString())) { + // Retain behavior from #6686 by returning without stopping + // propagation if there's nothing to do + return; + } + suggestionPopup.menu.doSelectedItemAction(); + + event.stopPropagation(); break; } @@ -1393,11 +1479,15 @@ public class VFilterSelect extends Composite implements Paintable, Field, switch (event.getNativeKeyCode()) { case KeyCodes.KEY_DOWN: suggestionPopup.selectNextItem(); + suggestionPopup.menu.setKeyboardSelectedItem(suggestionPopup.menu + .getSelectedItem()); DOM.eventPreventDefault(DOM.eventGetCurrentEvent()); event.stopPropagation(); break; case KeyCodes.KEY_UP: suggestionPopup.selectPrevItem(); + suggestionPopup.menu.setKeyboardSelectedItem(suggestionPopup.menu + .getSelectedItem()); DOM.eventPreventDefault(DOM.eventGetCurrentEvent()); event.stopPropagation(); break; @@ -1414,12 +1504,43 @@ public class VFilterSelect extends Composite implements Paintable, Field, event.stopPropagation(); break; case KeyCodes.KEY_TAB: - if (suggestionPopup.isAttached()) { - tabPressed = true; - filterOptions(currentPage); - } + tabPressedWhenPopupOpen = true; + filterOptions(currentPage); // onBlur() takes care of the rest break; + case KeyCodes.KEY_ESCAPE: + reset(); + event.stopPropagation(); + break; + case KeyCodes.KEY_ENTER: + if (suggestionPopup.menu.getKeyboardSelectedItem() == null) { + /* + * Nothing selected using up/down. Happens e.g. when entering a + * text (causes popup to open) and then pressing enter. + */ + if (!allowNewItem) { + /* + * New items are not allowed: If there is only one + * suggestion, select that. Otherwise do nothing. + */ + if (currentSuggestions.size() == 1) { + onSuggestionSelected(currentSuggestions.get(0)); + } + } else { + // Handle addition of new items. + suggestionPopup.menu.doSelectedItemAction(); + } + } else { + /* + * Get the suggestion that was navigated to using up/down. + */ + currentSuggestion = ((FilterSelectSuggestion) suggestionPopup.menu + .getKeyboardSelectedItem().getCommand()); + onSuggestionSelected(currentSuggestion); + } + + event.stopPropagation(); + break; } } @@ -1442,10 +1563,8 @@ public class VFilterSelect extends Composite implements Paintable, Field, case KeyCodes.KEY_UP: case KeyCodes.KEY_PAGEDOWN: case KeyCodes.KEY_PAGEUP: - ; // NOP - break; case KeyCodes.KEY_ESCAPE: - reset(); + ; // NOP break; default: if (textInputEnabled) { @@ -1604,8 +1723,8 @@ public class VFilterSelect extends Composite implements Paintable, Field, focused = false; if (!readonly) { // much of the TAB handling takes place here - if (tabPressed) { - tabPressed = false; + if (tabPressedWhenPopupOpen) { + tabPressedWhenPopupOpen = false; suggestionPopup.menu.doSelectedItemAction(); suggestionPopup.hide(); } else if (!suggestionPopup.isAttached() diff --git a/src/com/vaadin/terminal/gwt/client/ui/VView.java b/src/com/vaadin/terminal/gwt/client/ui/VView.java index af87610944..cd9f0c903c 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VView.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VView.java @@ -14,6 +14,7 @@ import com.google.gwt.core.client.Scheduler; import com.google.gwt.core.client.Scheduler.ScheduledCommand; import com.google.gwt.dom.client.DivElement; import com.google.gwt.dom.client.Document; +import com.google.gwt.dom.client.Element; import com.google.gwt.dom.client.Style; import com.google.gwt.dom.client.Style.Display; import com.google.gwt.event.dom.client.DomEvent.Type; @@ -23,7 +24,6 @@ import com.google.gwt.event.shared.EventHandler; import com.google.gwt.event.shared.HandlerRegistration; import com.google.gwt.user.client.Command; import com.google.gwt.user.client.DOM; -import com.google.gwt.user.client.Element; import com.google.gwt.user.client.Event; import com.google.gwt.user.client.Timer; import com.google.gwt.user.client.Window; @@ -109,7 +109,8 @@ public class VView extends SimplePanel implements Container, ResizeHandler, private VLazyExecutor delayedResizeExecutor = new VLazyExecutor(200, new ScheduledCommand() { public void execute() { - windowSizeMaybeChanged(getOffsetWidth(), getOffsetHeight()); + windowSizeMaybeChanged(Window.getClientWidth(), + Window.getClientHeight()); } }); @@ -576,25 +577,58 @@ public class VView extends SimplePanel implements Container, ResizeHandler, return getElement().getOffsetWidth() - getExcessWidth(); } - // If not running standalone, we might be inside elements that don't - // shrink with the browser window if our own components have + // If not running standalone, there might be multiple Vaadin apps + // that won't shrink with the browser window as the components have // calculated widths (#3125) - Element layoutElement = ((Widget) layout).getElement(); - Style layoutStyle = layoutElement.getStyle(); - // Set display:none to the entire application to get a width not - // influenced by the contents - String originalDisplay = layoutStyle.getDisplay(); - layoutStyle.setDisplay(Display.NONE); + // Find all Vaadin applications on the page + ArrayList<String> vaadinApps = new ArrayList<String>(); + loadAppIdListFromDOM(vaadinApps); + + // Store original styles here so they can be restored + ArrayList<String> originalDisplays = new ArrayList<String>( + vaadinApps.size()); + + String ownAppId = connection.getConfiguration().getRootPanelId(); + + // Set display: none for all Vaadin apps + for (int i = 0; i < vaadinApps.size(); i++) { + String appId = vaadinApps.get(i); + Element targetElement; + if (appId.equals(ownAppId)) { + // Only hide the contents of current application + targetElement = ((Widget) layout).getElement(); + } else { + // Hide everything for other applications + targetElement = Document.get().getElementById(appId); + } + Style layoutStyle = targetElement.getStyle(); + + originalDisplays.add(i, layoutStyle.getDisplay()); + layoutStyle.setDisplay(Display.NONE); + } int w = getElement().getOffsetWidth() - getExcessWidth(); // Then restore the old display style before returning - if (originalDisplay.length() == 0) { - layoutStyle.clearDisplay(); - } else { - layoutStyle.setDisplay(Display.valueOf(originalDisplay)); + for (int i = 0; i < vaadinApps.size(); i++) { + String appId = vaadinApps.get(i); + Element targetElement; + if (appId.equals(ownAppId)) { + targetElement = ((Widget) layout).getElement(); + } else { + targetElement = Document.get().getElementById(appId); + } + Style layoutStyle = targetElement.getStyle(); + String originalDisplay = originalDisplays.get(i); + + if (originalDisplay.length() == 0) { + layoutStyle.clearDisplay(); + } else { + layoutStyle.setProperty("display", originalDisplay); + } } + return w; } @@ -611,6 +645,14 @@ public class VView extends SimplePanel implements Container, ResizeHandler, } }; + private native static void loadAppIdListFromDOM(ArrayList<String> list) + /*-{ + var j; + for(j in $wnd.vaadin.vaadinConfigurations) { + list.@java.util.Collection::add(Ljava/lang/Object;)(j); + } + }-*/; + public RenderSpace getAllocatedSpace(Widget child) { return myRenderSpace; } diff --git a/src/com/vaadin/terminal/gwt/client/ui/dd/VHtml5DragEvent.java b/src/com/vaadin/terminal/gwt/client/ui/dd/VHtml5DragEvent.java index 3f3cf54e87..dd5852247a 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/dd/VHtml5DragEvent.java +++ b/src/com/vaadin/terminal/gwt/client/ui/dd/VHtml5DragEvent.java @@ -41,7 +41,15 @@ public class VHtml5DragEvent extends NativeEvent { return null; }-*/; - public final native void setDragEffect(String effect) + /** + * @deprecated As of Vaadin 6.8, replaced by {@link #setDropEffect(String)}. + */ + @Deprecated + public final void setDragEffect(String effect) { + setDropEffect(effect); + } + + public final native void setDropEffect(String effect) /*-{ try { this.dataTransfer.dropEffect = effect; @@ -53,6 +61,11 @@ public class VHtml5DragEvent extends NativeEvent { return this.dataTransfer.effectAllowed; }-*/; + public final native void setEffectAllowed(String effect) + /*-{ + this.dataTransfer.effectAllowed = effect; + }-*/; + public final native int getFileCount() /*-{ return this.dataTransfer.files ? this.dataTransfer.files.length : 0; @@ -63,4 +76,9 @@ public class VHtml5DragEvent extends NativeEvent { return this.dataTransfer.files[fileIndex]; }-*/; + public final native void setHtml5DataFlavor(String flavor, String data) + /*-{ + this.dataTransfer.setData(flavor, data); + }-*/; + } diff --git a/src/com/vaadin/terminal/gwt/client/ui/dd/VTransferable.java b/src/com/vaadin/terminal/gwt/client/ui/dd/VTransferable.java index 57b4d90e07..bb726586e2 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/dd/VTransferable.java +++ b/src/com/vaadin/terminal/gwt/client/ui/dd/VTransferable.java @@ -45,12 +45,12 @@ public class VTransferable { this.component = component; } - public Object getData(String dataFlawor) { - return variables.get(dataFlawor); + public Object getData(String dataFlavor) { + return variables.get(dataFlavor); } - public void setData(String dataFlawor, Object value) { - variables.put(dataFlawor, value); + public void setData(String dataFlavor, Object value) { + variables.put(dataFlavor, value); } public Collection<String> getDataFlavors() { diff --git a/src/com/vaadin/ui/DragAndDropWrapper.java b/src/com/vaadin/ui/DragAndDropWrapper.java index 83aa6314c8..9e06382eac 100644 --- a/src/com/vaadin/ui/DragAndDropWrapper.java +++ b/src/com/vaadin/ui/DragAndDropWrapper.java @@ -6,6 +6,7 @@ package com.vaadin.ui; import java.io.OutputStream; import java.util.HashMap; import java.util.Iterator; +import java.util.LinkedHashMap; import java.util.Map; import java.util.Map.Entry; @@ -54,7 +55,7 @@ public class DragAndDropWrapper extends CustomComponent implements DropTarget, /** * The component in wrapper that is being dragged or null if the - * transferrable is not a component (most likely an html5 drag). + * transferable is not a component (most likely an html5 drag). * * @return */ @@ -135,7 +136,8 @@ public class DragAndDropWrapper extends CustomComponent implements DropTarget, } /** - * @return a detail about the drags horizontal position over the wrapper. + * @return a detail about the drags horizontal position over the + * wrapper. */ public HorizontalDropLocation getHorizontalDropLocation() { return HorizontalDropLocation @@ -172,9 +174,18 @@ public class DragAndDropWrapper extends CustomComponent implements DropTarget, /** * The whole wrapper is used as a drag image when dragging. */ - WRAPPER + WRAPPER, + /** + * The whole wrapper is used to start an HTML5 drag. + * + * NOTE: In Internet Explorer 6 to 8, this prevents user interactions + * with the wrapper's contents. For example, clicking a button inside + * the wrapper will no longer work. + */ + HTML5, } + private final Map<String, Object> html5DataFlavors = new LinkedHashMap<String, Object>(); private DragStartMode dragStartMode = DragStartMode.NONE; /** @@ -187,10 +198,27 @@ public class DragAndDropWrapper extends CustomComponent implements DropTarget, super(root); } + /** + * Sets data flavors available in the DragAndDropWrapper is used to start an + * HTML5 style drags. Most commonly the "Text" flavor should be set. + * Multiple data types can be set. + * + * @param type + * the string identifier of the drag "payload". E.g. "Text" or + * "text/html" + * @param value + * the value + */ + public void setHTML5DataFlavor(String type, Object value) { + html5DataFlavors.put(type, value); + requestRepaint(); + } + @Override public void paintContent(PaintTarget target) throws PaintException { super.paintContent(target); - target.addAttribute("dragStartMode", dragStartMode.ordinal()); + target.addAttribute(VDragAndDropWrapper.DRAG_START_MODE, + dragStartMode.ordinal()); if (getDropHandler() != null) { getDropHandler().getAcceptCriterion().paint(target); } @@ -213,6 +241,8 @@ public class DragAndDropWrapper extends CustomComponent implements DropTarget, } } } + target.addAttribute(VDragAndDropWrapper.HTML5_DATA_FLAVORS, + html5DataFlavors); } private DropHandler dropHandler; diff --git a/src/com/vaadin/ui/Select.java b/src/com/vaadin/ui/Select.java index 7b6fc07e5b..439efdb864 100644 --- a/src/com/vaadin/ui/Select.java +++ b/src/com/vaadin/ui/Select.java @@ -148,7 +148,7 @@ public class Select extends AbstractSelect implements AbstractSelect.Filtering, } // Adds the required attribute - if (isRequired()) { + if (!isReadOnly() && isRequired()) { target.addAttribute("required", true); } diff --git a/src/com/vaadin/ui/TreeTable.java b/src/com/vaadin/ui/TreeTable.java index 9cba7362ac..fb12ffe323 100644 --- a/src/com/vaadin/ui/TreeTable.java +++ b/src/com/vaadin/ui/TreeTable.java @@ -333,6 +333,12 @@ public class TreeTable extends Table implements Hierarchical { private boolean animationsEnabled; private boolean clearFocusedRowPending; + /** + * If the container does not send item set change events, always do a full + * repaint instead of a partial update when expanding/collapsing nodes. + */ + private boolean containerSupportsPartialUpdates; + private ContainerStrategy getContainerStrategy() { if (cStrategy == null) { if (getContainerDataSource() instanceof Collapsible) { @@ -464,7 +470,7 @@ public class TreeTable extends Table implements Hierarchical { @Override protected boolean isPartialRowUpdate() { - return toggledItemId != null; + return toggledItemId != null && containerSupportsPartialUpdates; } @Override @@ -515,13 +521,20 @@ public class TreeTable extends Table implements Hierarchical { // ensure that page still has first item in page, DON'T clear the // caches. setCurrentPageFirstItemIndex(getCurrentPageFirstItemIndex(), false); - requestRepaint(); if (isCollapsed(itemId)) { fireCollapseEvent(itemId); } else { fireExpandEvent(itemId); } + + if (containerSupportsPartialUpdates) { + requestRepaint(); + } else { + // For containers that do not send item set change events, always do + // full repaint instead of partial row update. + refreshRowCache(); + } } @Override @@ -537,6 +550,9 @@ public class TreeTable extends Table implements Hierarchical { @Override public void setContainerDataSource(Container newDataSource) { cStrategy = null; + + containerSupportsPartialUpdates = (newDataSource instanceof ItemSetChangeNotifier); + if (!(newDataSource instanceof Hierarchical)) { newDataSource = new ContainerHierarchicalWrapper(newDataSource); } diff --git a/tests/integration_tests.xml b/tests/integration_tests.xml index 2a420553b7..2f10394ee0 100644 --- a/tests/integration_tests.xml +++ b/tests/integration_tests.xml @@ -9,7 +9,7 @@ <fail unless="test.integration.antfile" message="test.integration.antfile must be set for integration tests to run"/>
<!-- Test with these browsers -->
- <property name="test_browsers" value="winxp-safari5" />
+ <property name="test_browsers" value="winxp-firefox-latest" />
<!-- Path to key file. Default value -->
<property name="sshkey.file" value="id_dsa" />
@@ -217,6 +217,7 @@ <fileset dir="integration-testscripts" id="html-test-files" includes="GateIn-3/integration-test-GateIn-3.1.0-portlet2.html" />
<pathconvert pathsep=" " property="testfiles" refid="html-test-files" />
<antcall target="run-generic-integration-test">
+ <param name="test_browsers" value="winxp-firefox36" />
<param name="target-server" value="gatein3" />
</antcall>
</target>
@@ -225,6 +226,7 @@ <fileset dir="integration-testscripts" id="html-test-files" includes="eXo-3/integration-test-eXo-3.0.3-portlet2.html" />
<pathconvert pathsep=" " property="testfiles" refid="html-test-files" />
<antcall target="run-generic-integration-test">
+ <param name="test_browsers" value="winxp-firefox36" />
<param name="target-server" value="exo3" />
</antcall>
</target>
@@ -336,6 +338,7 @@ </fileset>
</scp>
+ <!-- trycatch probably not needed any more as it just fails with the original message and doesn't do anything in the finally block -->
<trycatch property="error_message">
<try>
<!-- timeout in one hour (remote end should timeout in 55 minutes) -->
@@ -378,18 +381,17 @@ </antcall>
</then>
</if>
- </try>
- <catch>
- <fail message="${error_message}" />
- </catch>
- <finally>
+
<!-- timeout in five minutes -->
<sshexec host="${target-host}" outputproperty="stop-output" timeout="300000" username="${user}" keyfile="${sshkey.file}" trust="yes" command="ant -f deploy.xml shutdown-and-cleanup" failonerror="false" />
<antcall target="echo-prefix">
<param name="prefix" value="${target-server}: " />
<param name="message" value="${stop-output}" />
</antcall>
- </finally>
+ </try>
+ <catch>
+ <fail message="${error_message}" />
+ </catch>
</trycatch>
</target>
diff --git a/tests/testbench/com/vaadin/tests/components/combobox/ComboBoxFiltering.html b/tests/testbench/com/vaadin/tests/components/combobox/ComboBoxFiltering.html new file mode 100644 index 0000000000..3de221871d --- /dev/null +++ b/tests/testbench/com/vaadin/tests/components/combobox/ComboBoxFiltering.html @@ -0,0 +1,62 @@ +<?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.combobox.ComboBoxSlow?restartApplication</td> + <td></td> +</tr> +<tr> + <td>mouseClick</td> + <td>vaadin=runcomvaadintestscomponentscomboboxComboBoxSlow::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[1]/VFilterSelect[0]/domChild[0]</td> + <td>92,19</td> +</tr> +<tr> + <td>enterCharacter</td> + <td>vaadin=runcomvaadintestscomponentscomboboxComboBoxSlow::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[1]/VFilterSelect[0]/domChild[0]</td> + <td>1</td> +</tr> +<tr> + <td>screenCapture</td> + <td></td> + <td>filter-no-match</td> +</tr> +<tr> + <td>enterCharacter</td> + <td>vaadin=runcomvaadintestscomponentscomboboxComboBoxSlow::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[1]/VFilterSelect[0]/domChild[0]</td> + <td>Item 12</td> +</tr> +<tr> + <td>screenCapture</td> + <td></td> + <td>filter-11-matches-paging</td> +</tr> +<tr> + <td>screenCapture</td> + <td></td> + <td>filter-11-matches-page-2</td> +</tr> +<tr> + <td>enterCharacter</td> + <td>vaadin=runcomvaadintestscomponentscomboboxComboBoxSlow::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[1]/VFilterSelect[0]/domChild[0]</td> + <td>Item 100</td> +</tr> +<tr> + <td>screenCapture</td> + <td></td> + <td>filter-2-matches-no-paging</td> +</tr> + +</tbody></table> +</body> +</html> diff --git a/tests/testbench/com/vaadin/tests/components/combobox/ComboBoxIdenticalItems.html b/tests/testbench/com/vaadin/tests/components/combobox/ComboBoxIdenticalItems.html new file mode 100644 index 0000000000..6d18c60038 --- /dev/null +++ b/tests/testbench/com/vaadin/tests/components/combobox/ComboBoxIdenticalItems.html @@ -0,0 +1,112 @@ +<?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.combobox.ComboBoxIdenticalItems?restartApplication</td> + <td></td> +</tr> +<tr> + <td>mouseClick</td> + <td>vaadin=runcomvaadintestscomponentscomboboxComboBoxIdenticalItems::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[1]/VFilterSelect[0]/domChild[0]</td> + <td>66,8</td> +</tr> +<tr> + <td>pressSpecialKey</td> + <td>vaadin=runcomvaadintestscomponentscomboboxComboBoxIdenticalItems::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[1]/VFilterSelect[0]/domChild[0]</td> + <td>down</td> +</tr> +<tr> + <td>pressSpecialKey</td> + <td>vaadin=runcomvaadintestscomponentscomboboxComboBoxIdenticalItems::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[1]/VFilterSelect[0]/domChild[0]</td> + <td>down</td> +</tr> +<tr> + <td>pressSpecialKey</td> + <td>vaadin=runcomvaadintestscomponentscomboboxComboBoxIdenticalItems::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[1]/VFilterSelect[0]/domChild[0]</td> + <td>enter</td> +</tr> +<tr> + <td>assertText</td> + <td>vaadin=runcomvaadintestscomponentscomboboxComboBoxIdenticalItems::PID_SLog_row_0</td> + <td>1. Item one-1 selected</td> +</tr> +<tr> + <td>pressSpecialKey</td> + <td>vaadin=runcomvaadintestscomponentscomboboxComboBoxIdenticalItems::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[1]/VFilterSelect[0]/domChild[0]</td> + <td>down</td> +</tr> +<tr> + <td>pressSpecialKey</td> + <td>vaadin=runcomvaadintestscomponentscomboboxComboBoxIdenticalItems::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[1]/VFilterSelect[0]/domChild[0]</td> + <td>down</td> +</tr> +<tr> + <td>pressSpecialKey</td> + <td>vaadin=runcomvaadintestscomponentscomboboxComboBoxIdenticalItems::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[1]/VFilterSelect[0]/domChild[0]</td> + <td>enter</td> +</tr> +<tr> + <td>assertText</td> + <td>vaadin=runcomvaadintestscomponentscomboboxComboBoxIdenticalItems::PID_SLog_row_0</td> + <td>2. Item one-2 selected</td> +</tr> +<tr> + <td>pressSpecialKey</td> + <td>vaadin=runcomvaadintestscomponentscomboboxComboBoxIdenticalItems::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[1]/VFilterSelect[0]/domChild[0]</td> + <td>down</td> +</tr> +<tr> + <td>pressSpecialKey</td> + <td>vaadin=runcomvaadintestscomponentscomboboxComboBoxIdenticalItems::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[1]/VFilterSelect[0]/domChild[0]</td> + <td>down</td> +</tr> +<tr> + <td>pressSpecialKey</td> + <td>vaadin=runcomvaadintestscomponentscomboboxComboBoxIdenticalItems::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[1]/VFilterSelect[0]/domChild[0]</td> + <td>enter</td> +</tr> +<tr> + <td>assertText</td> + <td>vaadin=runcomvaadintestscomponentscomboboxComboBoxIdenticalItems::PID_SLog_row_0</td> + <td>3. Item two selected</td> +</tr> +<tr> + <td>pressSpecialKey</td> + <td>vaadin=runcomvaadintestscomponentscomboboxComboBoxIdenticalItems::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[1]/VFilterSelect[0]/domChild[0]</td> + <td>up</td> +</tr> +<tr> + <td>pressSpecialKey</td> + <td>vaadin=runcomvaadintestscomponentscomboboxComboBoxIdenticalItems::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[1]/VFilterSelect[0]/domChild[0]</td> + <td>up</td> +</tr> +<tr> + <td>pressSpecialKey</td> + <td>vaadin=runcomvaadintestscomponentscomboboxComboBoxIdenticalItems::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[1]/VFilterSelect[0]/domChild[0]</td> + <td>up</td> +</tr> +<tr> + <td>pressSpecialKey</td> + <td>vaadin=runcomvaadintestscomponentscomboboxComboBoxIdenticalItems::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[1]/VFilterSelect[0]/domChild[0]</td> + <td>enter</td> +</tr> +<tr> + <td>assertText</td> + <td>vaadin=runcomvaadintestscomponentscomboboxComboBoxIdenticalItems::PID_SLog_row_0</td> + <td>4. Item one-1 selected</td> +</tr> + +</tbody></table> +</body> +</html> diff --git a/tests/testbench/com/vaadin/tests/components/combobox/ComboBoxIdenticalItems.java b/tests/testbench/com/vaadin/tests/components/combobox/ComboBoxIdenticalItems.java new file mode 100644 index 0000000000..dcd4af58ad --- /dev/null +++ b/tests/testbench/com/vaadin/tests/components/combobox/ComboBoxIdenticalItems.java @@ -0,0 +1,54 @@ +package com.vaadin.tests.components.combobox;
+
+import com.vaadin.data.Item;
+import com.vaadin.data.Property;
+import com.vaadin.data.Property.ValueChangeEvent;
+import com.vaadin.tests.components.TestBase;
+import com.vaadin.tests.util.Log;
+import com.vaadin.ui.ComboBox;
+
+public class ComboBoxIdenticalItems extends TestBase {
+
+ private Log log = new Log(5);
+
+ @Override
+ public void setup() {
+ final ComboBox select = new ComboBox("ComboBox");
+ select.addContainerProperty("caption", String.class, null);
+ Item item = select.addItem("one-1");
+ item.getItemProperty("caption").setValue("One");
+ item = select.addItem("one-2");
+ item.getItemProperty("caption").setValue("One");
+ item = select.addItem("two");
+ item.getItemProperty("caption").setValue("Two");
+ select.setItemCaptionPropertyId("caption");
+ select.setNullSelectionAllowed(false);
+ select.setImmediate(true);
+ select.addListener(new Property.ValueChangeListener() {
+ private static final long serialVersionUID = -7932700771673919620L;
+
+ public void valueChange(ValueChangeEvent event) {
+ log.log("Item " + select.getValue() + " selected");
+
+ }
+ });
+
+ addComponent(log);
+ addComponent(select);
+ }
+
+ @Override
+ protected String getDescription() {
+ return "Keyboard selecting of a value is broken in combobox if two "
+ + "items have the same caption. The first item's id is \"One-1\" "
+ + "while the second one is \"One-2\". Selecting with mouse works "
+ + "as expected but selecting with keyboard always returns the "
+ + "object \"One-1\".";
+ }
+
+ @Override
+ protected Integer getTicketNumber() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+}
diff --git a/tests/testbench/com/vaadin/tests/components/combobox/ComboBoxInPopup.htm b/tests/testbench/com/vaadin/tests/components/combobox/ComboBoxInPopup.htm new file mode 100644 index 0000000000..f943f912e4 --- /dev/null +++ b/tests/testbench/com/vaadin/tests/components/combobox/ComboBoxInPopup.htm @@ -0,0 +1,48 @@ +<?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.combobox.ComboBoxInPopup?restartApplication</td> + <td></td> +</tr> +<tr> + <td>mouseClick</td> + <td>vaadin=runcomvaadintestscomponentscomboboxComboBoxInPopup::/VWindow[0]/FocusableScrollPanel[0]/VVerticalLayout[0]/ChildComponentContainer[0]/VFilterSelect[0]/domChild[1]</td> + <td>12,13</td> +</tr> +<tr> + <td>assertText</td> + <td>vaadin=runcomvaadintestscomponentscomboboxComboBoxInPopup::Root/VFilterSelect$SuggestionPopup[0]/VFilterSelect$SuggestionMenu[0]#item1</td> + <td>Yes</td> +</tr> +<tr> + <td>pressSpecialKey</td> + <td>vaadin=runcomvaadintestscomponentscomboboxComboBoxInPopup::Root/VFilterSelect$SuggestionPopup[0]/VFilterSelect$SuggestionMenu[0]#item1</td> + <td>esc</td> +</tr> +<!--ensure the sub window is still open but the popup is not--> +<tr> + <td>assertText</td> + <td>vaadin=runcomvaadintestscomponentscomboboxComboBoxInPopup::/VWindow[0]/FocusableScrollPanel[0]/VVerticalLayout[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]</td> + <td>A combo box</td> +</tr> +<tr> + <td>assertElementNotPresent</td> + <td>vaadin=runcomvaadintestscomponentscomboboxComboBoxInPopup::Root/VFilterSelect$SuggestionPopup[0]/VFilterSelect$SuggestionMenu[0]#item1</td> + <td></td> +</tr> + +</tbody></table> +</body> +</html> diff --git a/tests/testbench/com/vaadin/tests/components/combobox/ComboBoxInPopup.java b/tests/testbench/com/vaadin/tests/components/combobox/ComboBoxInPopup.java new file mode 100644 index 0000000000..8160fb576e --- /dev/null +++ b/tests/testbench/com/vaadin/tests/components/combobox/ComboBoxInPopup.java @@ -0,0 +1,50 @@ +package com.vaadin.tests.components.combobox; + +import com.vaadin.event.ShortcutAction.KeyCode; +import com.vaadin.tests.components.TestBase; +import com.vaadin.ui.Button; +import com.vaadin.ui.Button.ClickEvent; +import com.vaadin.ui.ComboBox; +import com.vaadin.ui.Component; +import com.vaadin.ui.Window; + +public class ComboBoxInPopup extends TestBase { + + @Override + protected void setup() { + final Window w = new Window(); + w.getContent().setSizeUndefined(); + w.addComponent(createComboBox()); + Button close = new Button("Close window", new Button.ClickListener() { + + public void buttonClick(ClickEvent event) { + w.getParent().removeWindow(w); + } + }); + close.setClickShortcut(KeyCode.ESCAPE, null); + w.addComponent(close); + + getLayout().getWindow().addWindow(w); + + } + + private Component createComboBox() { + ComboBox cb = new ComboBox("A combo box"); + + cb.addItem("Yes"); + cb.addItem("No"); + cb.addItem("Maybe"); + return cb; + } + + @Override + protected String getDescription() { + return "Escape is a shortcut for the close button. Pressing escape when the popup is open should cause only the popup to close, not the window."; + } + + @Override + protected Integer getTicketNumber() { + return 6978; + } + +} diff --git a/tests/testbench/com/vaadin/tests/components/combobox/ComboBoxNullItem.html b/tests/testbench/com/vaadin/tests/components/combobox/ComboBoxNullItem.html new file mode 100644 index 0000000000..3dc31f4a98 --- /dev/null +++ b/tests/testbench/com/vaadin/tests/components/combobox/ComboBoxNullItem.html @@ -0,0 +1,62 @@ +<?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: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.components.combobox.ComboBoxNavigation?restartApplication&theme=chameleon</td> + <td></td> +</tr> +<tr> + <td>mouseClick</td> + <td>vaadin=runcomvaadintestscomponentscomboboxComboBoxNavigation::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VFilterSelect[0]/domChild[1]</td> + <td>5,9</td> +</tr> +<tr> + <td>screenCapture</td> + <td></td> + <td>combobox-with-null-item-chameleon</td> +</tr> +<tr> + <td>open</td> + <td>/run/com.vaadin.tests.components.combobox.ComboBoxNavigation?restartApplication&theme=runo</td> + <td></td> +</tr> +<tr> + <td>mouseClick</td> + <td>vaadin=runcomvaadintestscomponentscomboboxComboBoxNavigation::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VFilterSelect[0]/domChild[1]</td> + <td>5,9</td> +</tr> +<tr> + <td>screenCapture</td> + <td></td> + <td>combobox-with-null-item-runo</td> +</tr> +<tr> + <td>open</td> + <td>/run/com.vaadin.tests.components.combobox.ComboBoxNavigation?restartApplication&theme=reindeer</td> + <td></td> +</tr> +<tr> + <td>mouseClick</td> + <td>vaadin=runcomvaadintestscomponentscomboboxComboBoxNavigation::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VFilterSelect[0]/domChild[1]</td> + <td>5,9</td> +</tr> +<tr> + <td>screenCapture</td> + <td></td> + <td>combobox-with-null-item-reindeer</td> +</tr> + +</tbody></table> +</body> +</html> diff --git a/tests/testbench/com/vaadin/tests/components/combobox/ComboBoxSlow.java b/tests/testbench/com/vaadin/tests/components/combobox/ComboBoxSlow.java new file mode 100644 index 0000000000..15742cc783 --- /dev/null +++ b/tests/testbench/com/vaadin/tests/components/combobox/ComboBoxSlow.java @@ -0,0 +1,55 @@ +package com.vaadin.tests.components.combobox; + +import java.util.Map; + +import com.vaadin.data.Property.ValueChangeEvent; +import com.vaadin.data.Property.ValueChangeListener; +import com.vaadin.tests.components.TestBase; +import com.vaadin.tests.util.Log; +import com.vaadin.ui.ComboBox; + +public class ComboBoxSlow extends TestBase { + + private Log log = new Log(5); + + @Override + protected Integer getTicketNumber() { + return 7949; + } + + @Override + protected String getDescription() { + return "The ComboBox artificially introduces a server delay to more easily spot problems"; + } + + public class SlowComboBox extends ComboBox { + @Override + public void changeVariables(Object source, Map<String, Object> variables) { + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + super.changeVariables(source, variables); + } + } + + @Override + protected void setup() { + addComponent(log); + final SlowComboBox cb = new SlowComboBox(); + cb.setImmediate(true); + for (int i = 0; i <= 1000; i++) { + cb.addItem("Item " + i); + } + cb.addListener(new ValueChangeListener() { + + public void valueChange(ValueChangeEvent event) { + log.log("Value changed to " + cb.getValue()); + + } + }); + addComponent(cb); + } +} diff --git a/tests/testbench/com/vaadin/tests/components/combobox/Comboboxes.html b/tests/testbench/com/vaadin/tests/components/combobox/Comboboxes.html index 1affc9a8a9..4aa84a9453 100644 --- a/tests/testbench/com/vaadin/tests/components/combobox/Comboboxes.html +++ b/tests/testbench/com/vaadin/tests/components/combobox/Comboboxes.html @@ -250,30 +250,39 @@ </tr> <tr> <td>mouseClick</td> - <td>vaadin=runcomvaadintestscomponentscomboboxComboboxes::PID_Scheckboxaction-Readonly/domChild[0]</td> - <td>26,10</td> + <td>vaadin=runcomvaadintestscomponentscomboboxComboboxes::PID_Scheckboxaction-Required/domChild[0]</td> + <td>12,-8</td> </tr> <tr> - <td>waitForVaadin</td> - <td></td> - <td></td> + <td>mouseClick</td> + <td>vaadin=runcomvaadintestscomponentscomboboxComboboxes::PID_Scheckboxaction-Error indicators/domChild[0]</td> + <td>7,-8</td> </tr> <tr> <td>screenCapture</td> <td></td> - <td>error</td> + <td>readonly-required</td> +</tr> +<tr> + <td>mouseClick</td> + <td>vaadin=runcomvaadintestscomponentscomboboxComboboxes::PID_Scheckboxaction-Readonly/domChild[0]</td> + <td>26,10</td> +</tr> +<tr> + <td>mouseClick</td> + <td>vaadin=runcomvaadintestscomponentscomboboxComboboxes::PID_Scheckboxaction-Required/domChild[0]</td> + <td>3,-7</td> </tr> <tr> <td>mouseClick</td> <td>vaadin=runcomvaadintestscomponentscomboboxComboboxes::PID_Scheckboxaction-Error indicators/domChild[0]</td> - <td>67,8</td> + <td>7,-8</td> </tr> <tr> - <td>waitForVaadin</td> - <td></td> + <td>screenCapture</td> <td></td> + <td>error</td> </tr> - </tbody></table> </body> </html> diff --git a/tests/testbench/com/vaadin/tests/components/datefield/DateFieldTimezone.html b/tests/testbench/com/vaadin/tests/components/datefield/DateFieldTimezone.html index ca354dd240..2a67b16170 100644 --- a/tests/testbench/com/vaadin/tests/components/datefield/DateFieldTimezone.html +++ b/tests/testbench/com/vaadin/tests/components/datefield/DateFieldTimezone.html @@ -22,7 +22,7 @@ <td>6,10</td> </tr> <tr> - <td>type</td> + <td>enterCharacter</td> <td>vaadin=runcomvaadintestscomponentsdatefieldDateFieldTimezone::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VFilterSelect[0]/domChild[0]</td> <td>Europe/Helsinki (Eastern European Time)</td> </tr> @@ -51,7 +51,6 @@ <td>vaadin=runcomvaadintestscomponentsdatefieldDateFieldTimezone::PID_SLog_row_0</td> <td>2. Date changed to 12/31/09 11:00:00 PM UTC</td> </tr> - </tbody></table> </body> </html> diff --git a/tests/testbench/com/vaadin/tests/components/treetable/DisappearingComponents.java b/tests/testbench/com/vaadin/tests/components/treetable/DisappearingComponents.java index 0b972f07b2..becae955ab 100644 --- a/tests/testbench/com/vaadin/tests/components/treetable/DisappearingComponents.java +++ b/tests/testbench/com/vaadin/tests/components/treetable/DisappearingComponents.java @@ -1,15 +1,15 @@ package com.vaadin.tests.components.treetable; import com.vaadin.terminal.ExternalResource; -import com.vaadin.tests.components.TestBase; +import com.vaadin.tests.components.AbstractTestCase; import com.vaadin.ui.Link; import com.vaadin.ui.TreeTable; import com.vaadin.ui.Window; -public class DisappearingComponents extends TestBase { +public class DisappearingComponents extends AbstractTestCase { @Override - protected void setup() { + public void init() { Window mainWindow = new Window("Application"); final TreeTable tt = new TreeTable(); tt.setSizeUndefined(); diff --git a/tests/testbench/com/vaadin/tests/containers/filesystemcontainer/FileSystemContainerInTreeTable.html b/tests/testbench/com/vaadin/tests/containers/filesystemcontainer/FileSystemContainerInTreeTable.html new file mode 100644 index 0000000000..b5ccd53df0 --- /dev/null +++ b/tests/testbench/com/vaadin/tests/containers/filesystemcontainer/FileSystemContainerInTreeTable.html @@ -0,0 +1,117 @@ +<?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>FileSystemContainerInTreeTable</title> +</head> +<body> +<table cellpadding="1" cellspacing="1" border="1"> +<thead> +<tr><td rowspan="1" colspan="3">FileSystemContainerInTreeTable</td></tr> +</thead><tbody> +<tr> + <td>open</td> + <td>/run/com.vaadin.tests.containers.filesystemcontainer.FileSystemContainerInTreeTable?restartApplication</td> + <td></td> +</tr> +<tr> + <td>screenCapture</td> + <td></td> + <td>initial</td> +</tr> +<tr> + <td>click</td> + <td>vaadin=runcomvaadintestscontainersfilesystemcontainerFileSystemContainerInTreeTable::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[2]/VHorizontalLayout[0]/ChildComponentContainer[0]/VButton[0]/domChild[0]/domChild[0]</td> + <td></td> +</tr> +<tr> + <td>screenCapture</td> + <td></td> + <td>added_not_yet_visible</td> +</tr> +<tr> + <td>mouseClick</td> + <td>vaadin=runcomvaadintestscontainersfilesystemcontainerFileSystemContainerInTreeTable::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[1]/VTreeTable[0]/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[0]/domChild[0]</td> + <td>30,8</td> +</tr> +<tr> + <td>screenCapture</td> + <td></td> + <td>added_dir2_expanded</td> +</tr> +<tr> + <td>click</td> + <td>vaadin=runcomvaadintestscontainersfilesystemcontainerFileSystemContainerInTreeTable::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[2]/VHorizontalLayout[0]/ChildComponentContainer[1]/VButton[0]/domChild[0]/domChild[0]</td> + <td></td> +</tr> +<tr> + <td>mouseClick</td> + <td>vaadin=runcomvaadintestscontainersfilesystemcontainerFileSystemContainerInTreeTable::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[1]/VTreeTable[0]/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[2]/domChild[0]/domChild[0]/domChild[0]</td> + <td>32,6</td> +</tr> +<tr> + <td>screenCapture</td> + <td></td> + <td>deleted_dir2_collapsed</td> +</tr> +<tr> + <td>mouseClick</td> + <td>vaadin=runcomvaadintestscontainersfilesystemcontainerFileSystemContainerInTreeTable::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[1]/VTreeTable[0]/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[0]/domChild[0]</td> + <td>32,4</td> +</tr> +<tr> + <td>screenCapture</td> + <td></td> + <td>deleted_dir2_expanded</td> +</tr> +<tr> + <td>click</td> + <td>vaadin=runcomvaadintestscontainersfilesystemcontainerFileSystemContainerInTreeTable::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[2]/VHorizontalLayout[0]/ChildComponentContainer[0]/VButton[0]/domChild[0]</td> + <td></td> +</tr> +<tr> + <td>mouseClick</td> + <td>vaadin=runcomvaadintestscontainersfilesystemcontainerFileSystemContainerInTreeTable::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[1]/VTreeTable[0]/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[0]/domChild[0]</td> + <td>31,8</td> +</tr> +<tr> + <td>screenCapture</td> + <td></td> + <td>added_dir2_collapsed</td> +</tr> +<tr> + <td>mouseClick</td> + <td>vaadin=runcomvaadintestscontainersfilesystemcontainerFileSystemContainerInTreeTable::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[1]/VTreeTable[0]/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]</td> + <td>29,5</td> +</tr> +<tr> + <td>screenCapture</td> + <td></td> + <td>added_dir1_expanded</td> +</tr> +<tr> + <td>click</td> + <td>vaadin=runcomvaadintestscontainersfilesystemcontainerFileSystemContainerInTreeTable::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[2]/VHorizontalLayout[0]/ChildComponentContainer[1]/VButton[0]/domChild[0]/domChild[0]</td> + <td></td> +</tr> +<tr> + <td>mouseClick</td> + <td>vaadin=runcomvaadintestscontainersfilesystemcontainerFileSystemContainerInTreeTable::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[1]/VTreeTable[0]/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]</td> + <td>32,8</td> +</tr> +<tr> + <td>screenCapture</td> + <td></td> + <td>deleted_dir1_collapsed</td> +</tr> +<tr> + <td>click</td> + <td>vaadin=runcomvaadintestscontainersfilesystemcontainerFileSystemContainerInTreeTable::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[2]/VHorizontalLayout[0]/ChildComponentContainer[2]/VButton[0]/domChild[0]/domChild[0]</td> + <td></td> +</tr> + +</tbody></table> +</body> +</html> diff --git a/tests/testbench/com/vaadin/tests/containers/filesystemcontainer/FileSystemContainerInTreeTable.java b/tests/testbench/com/vaadin/tests/containers/filesystemcontainer/FileSystemContainerInTreeTable.java new file mode 100644 index 0000000000..b3b5185505 --- /dev/null +++ b/tests/testbench/com/vaadin/tests/containers/filesystemcontainer/FileSystemContainerInTreeTable.java @@ -0,0 +1,141 @@ +package com.vaadin.tests.containers.filesystemcontainer;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+
+import com.vaadin.data.Container;
+import com.vaadin.data.Container.Ordered;
+import com.vaadin.data.util.FilesystemContainer;
+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.HorizontalLayout;
+import com.vaadin.ui.Table;
+import com.vaadin.ui.Tree.CollapseEvent;
+import com.vaadin.ui.Tree.CollapseListener;
+import com.vaadin.ui.Tree.ExpandEvent;
+import com.vaadin.ui.Tree.ExpandListener;
+import com.vaadin.ui.TreeTable;
+
+public class FileSystemContainerInTreeTable extends TestBase {
+
+ private Log log = new Log(5);
+ private TreeTable treeTable;
+
+ @Override
+ protected void setup() {
+ setTheme("reindeer-tests");
+
+ final File folder;
+ try {
+ File tempFile = File.createTempFile("fsc-tt", "");
+ tempFile.delete();
+ folder = new File(tempFile.getParent(), tempFile.getName());
+ folder.mkdir();
+ System.out.println(folder.getPath());
+ folder.deleteOnExit();
+
+ populate(folder, 3, 10);
+
+ FilesystemContainer fsc = new FilesystemContainer(folder);
+
+ treeTable = new TreeTable();
+ treeTable.addStyleName("table-equal-rowheight");
+ treeTable.setWidth("450px");
+ treeTable.setHeight("550px");
+ treeTable.setContainerDataSource(fsc);
+ treeTable.setItemIconPropertyId(FilesystemContainer.PROPERTY_ICON);
+ treeTable.setVisibleColumns(new String[] { "Name" });
+ treeTable.setColumnWidth("Name", 400);
+ treeTable.addListener(new ExpandListener() {
+
+ public void nodeExpand(ExpandEvent event) {
+ logExpandCollapse(event.getItemId(), "expanded");
+
+ }
+ });
+ treeTable.addListener(new CollapseListener() {
+
+ public void nodeCollapse(CollapseEvent event) {
+ logExpandCollapse(event.getItemId(), "collapsed");
+
+ }
+ });
+
+ addComponent(log);
+ addComponent(treeTable);
+
+ HorizontalLayout buttonLayout = new HorizontalLayout();
+ buttonLayout.setSpacing(true);
+ buttonLayout.addComponent(new Button("Create dir11",
+ new Button.ClickListener() {
+ public void buttonClick(ClickEvent event) {
+ new File(folder, "dir11").mkdir();
+ log.log("Row dir11 created");
+ }
+ }));
+ buttonLayout.addComponent(new Button("Delete dir11",
+ new Button.ClickListener() {
+ public void buttonClick(ClickEvent event) {
+ new File(folder, "dir11").delete();
+ log.log("Row dir11 deleted");
+ }
+ }));
+ // to clean up explicitly before ending an automated test
+ buttonLayout.addComponent(new Button("Clean all files",
+ new Button.ClickListener() {
+ public void buttonClick(ClickEvent event) {
+ folder.delete();
+ }
+ }));
+ addComponent(buttonLayout);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ private void populate(File folder, int subDirectories, int files)
+ throws IOException {
+ for (int i = 1; i <= files; i++) {
+ File f = new File(folder, "file" + i + ".txt");
+ f.createNewFile();
+ }
+
+ for (int i = 1; i <= subDirectories; i++) {
+ File f = new File(folder, "dir" + i);
+ f.mkdir();
+ populate(f, 0, 2);
+ }
+ }
+
+ protected int indexOfId(Table source, Object itemId) {
+ Container.Ordered c = (Ordered) source.getContainerDataSource();
+ if (c instanceof Container.Indexed) {
+ return ((Container.Indexed) source).indexOfId(itemId);
+ } else {
+ ArrayList<Object> list = new ArrayList<Object>(source.getItemIds());
+ return list.indexOf(itemId);
+ }
+ }
+
+ protected void logExpandCollapse(Object itemId, String operation) {
+ File file = (File) itemId;
+ // do not use the variable part (path) of file name
+ log.log("Row " + file.getName() + " " + operation + ". Row index: "
+ + indexOfId(treeTable, itemId));
+
+ }
+
+ @Override
+ protected String getDescription() {
+ return "TreeTable partial updates can only be used with a container that notifies the TreeTable of item set changes";
+ }
+
+ @Override
+ protected Integer getTicketNumber() {
+ return 7837;
+ }
+
+}
\ No newline at end of file diff --git a/tests/testbench/com/vaadin/tests/dd/StartHtml5Drag.java b/tests/testbench/com/vaadin/tests/dd/StartHtml5Drag.java new file mode 100644 index 0000000000..2cdef65d31 --- /dev/null +++ b/tests/testbench/com/vaadin/tests/dd/StartHtml5Drag.java @@ -0,0 +1,65 @@ +package com.vaadin.tests.dd; + +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.terminal.ClassResource; +import com.vaadin.terminal.Sizeable; +import com.vaadin.tests.components.TestBase; +import com.vaadin.ui.DragAndDropWrapper; +import com.vaadin.ui.DragAndDropWrapper.DragStartMode; +import com.vaadin.ui.DragAndDropWrapper.WrapperTransferable; +import com.vaadin.ui.Embedded; +import com.vaadin.ui.Label; + +public class StartHtml5Drag extends TestBase { + + @Override + protected void setup() { + DragAndDropWrapper dragStart = new DragAndDropWrapper(new Label( + "Drag me")); + dragStart.setDragStartMode(DragStartMode.HTML5); + dragStart.setHTML5DataFlavor("Text", "HTML5!"); + addComponent(dragStart); + + DragAndDropWrapper dropTarget = new DragAndDropWrapper(new Label( + "over here")); + dropTarget.setDropHandler(new DropHandler() { + + public AcceptCriterion getAcceptCriterion() { + return AcceptAll.get(); + } + + public void drop(DragAndDropEvent event) { + getWindows() + .iterator() + .next() + .showNotification( + ((WrapperTransferable) event.getTransferable()) + .getText()); + } + }); + addComponent(dropTarget); + + Embedded iframe = new Embedded("", new ClassResource("html5drop.htm", + this)); + iframe.setType(Embedded.TYPE_BROWSER); + iframe.setWidth(400, Sizeable.UNITS_PIXELS); + iframe.setHeight(400, Sizeable.UNITS_PIXELS); + addComponent(iframe); + + } + + @Override + protected String getDescription() { + return "Should work. Try to e.g. drag the 'Hello Vaadin user' " + + "label to native text editor application. In text " + + "editor app 'HTML5!' text should appear."; + } + + @Override + protected Integer getTicketNumber() { + return 7833; + } +} diff --git a/tests/testbench/com/vaadin/tests/dd/html5drop.htm b/tests/testbench/com/vaadin/tests/dd/html5drop.htm new file mode 100644 index 0000000000..ed05fcedea --- /dev/null +++ b/tests/testbench/com/vaadin/tests/dd/html5drop.htm @@ -0,0 +1,51 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="UTF-8"> +<title>Insert title here</title> +<script type="text/javascript"> + if (window.addEventListener) { + window.addEventListener('load', init, false); //W3C + } else { + window.attachEvent('onload', init); //IE + } + + function init(event) { + var el = document.getElementById("drop"); + if (el.addEventListener) { + el.addEventListener("dragover", dragover, false); + el.addEventListener("dragenter", dragenter, false); + el.addEventListener("drop", drop, false); + } else if (el.attachEvent) { + el.attachEvent('ondragover', dragover); + el.attachEvent('ondragenter', dragenter); + el.attachEvent('ondrop', drop); + } + } + + function dragover(event) { + event.dataTransfer.dropEffect = 'copy'; + return cancel(event); + } + + function drop(event) { + document.getElementById("drop").innerHTML = event.dataTransfer.getData('Text'); + return cancel(event); + } + + function dragenter(event) { + return cancel(event); + } + + function cancel(event) { + if (event.preventDefault) { + event.preventDefault(); + } + return false; + } +</script> +</head> +<body> + <div id="drop">or over here</div> +</body> +</html>
\ No newline at end of file diff --git a/tests/testbench/com/vaadin/tests/integration/EmbedSizeTest.java b/tests/testbench/com/vaadin/tests/integration/EmbedSizeTest.java new file mode 100644 index 0000000000..479af4aa87 --- /dev/null +++ b/tests/testbench/com/vaadin/tests/integration/EmbedSizeTest.java @@ -0,0 +1,55 @@ +package com.vaadin.tests.integration; + +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.CheckBox; +import com.vaadin.ui.Window; +import com.vaadin.ui.Window.ResizeEvent; + +public class EmbedSizeTest extends TestBase { + + private Log log = new Log(10); + + @Override + protected void setup() { + Window mainWindow = getMainWindow(); + mainWindow.setSizeUndefined(); + mainWindow.getContent().setSizeUndefined(); + mainWindow.setImmediate(true); + + CheckBox lazyCheckBox = new CheckBox("Lazy resize", + new Button.ClickListener() { + public void buttonClick(ClickEvent event) { + boolean resizeLazy = Boolean.TRUE == event.getButton() + .getValue(); + getMainWindow().setResizeLazy(resizeLazy); + log.log("Resize lazy: " + resizeLazy); + } + }); + lazyCheckBox.setValue(Boolean.FALSE); + lazyCheckBox.setImmediate(true); + addComponent(lazyCheckBox); + + addComponent(log); + mainWindow.addListener(new Window.ResizeListener() { + public void windowResized(ResizeEvent e) { + Window window = e.getWindow(); + log.log("Resize event: " + window.getWidth() + " x " + + window.getHeight()); + } + }); + } + + @Override + protected String getDescription() { + return "Resizing the browser window should send consistent resize events to the server even when the application is embedded"; + } + + @Override + protected Integer getTicketNumber() { + return Integer.valueOf(7923); + } + +} |