From 9b17bc12f8116e33468e81d3b397ca81d8fea530 Mon Sep 17 00:00:00 2001 From: Johannes Dahlström Date: Thu, 3 May 2012 15:02:57 +0000 Subject: New helper class handling touch scrolling either natively or with TouchScrollDelegate, depending on platform capabilities svn changeset:23671/svn branch:6.8 --- .../gwt/client/ui/TouchScrollDelegate.java | 47 +++++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) diff --git a/src/com/vaadin/terminal/gwt/client/ui/TouchScrollDelegate.java b/src/com/vaadin/terminal/gwt/client/ui/TouchScrollDelegate.java index 8b2248aff6..a2a94489e4 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/TouchScrollDelegate.java +++ b/src/com/vaadin/terminal/gwt/client/ui/TouchScrollDelegate.java @@ -15,10 +15,12 @@ import com.google.gwt.dom.client.Style; import com.google.gwt.dom.client.Touch; import com.google.gwt.event.dom.client.ScrollHandler; import com.google.gwt.event.dom.client.TouchStartEvent; +import com.google.gwt.event.dom.client.TouchStartHandler; import com.google.gwt.event.shared.HandlerRegistration; import com.google.gwt.user.client.Event; import com.google.gwt.user.client.Event.NativePreviewEvent; import com.google.gwt.user.client.Event.NativePreviewHandler; +import com.google.gwt.user.client.ui.Widget; import com.vaadin.terminal.gwt.client.BrowserInfo; import com.vaadin.terminal.gwt.client.VConsole; @@ -86,6 +88,49 @@ public class TouchScrollDelegate implements NativePreviewHandler { private static final boolean androidWithBrokenScrollTop = BrowserInfo.get() .isAndroidWithBrokenScrollTop(); + public static class TouchScrollHandler implements TouchStartHandler { + + private final TouchScrollDelegate delegate; + private final boolean requiresDelegate = BrowserInfo.get() + .requiresTouchScrollDelegate(); + + public TouchScrollHandler(Widget widget, Element... scrollables) { + if (requiresDelegate) { + delegate = new TouchScrollDelegate(); + widget.addDomHandler(this, TouchStartEvent.getType()); + } else { + delegate = null; + widget.addDomHandler(new TouchStartHandler() { + + public void onTouchStart(TouchStartEvent event) { + // TODO Auto-generated method stub + + } + }, TouchStartEvent.getType()); + } + setElements(scrollables); + } + + public void onTouchStart(TouchStartEvent event) { + VConsole.log("TouchScrollHandler onTouchStart"); + assert delegate != null; + delegate.onTouchStart(event); + } + + public void setElements(Element... scrollables) { + if (requiresDelegate) { + delegate.setElements(scrollables); + } else if (BrowserInfo.get().isTouchDevice()) { + for (Element e : scrollables) { + e.getStyle().setProperty("overflow", "auto"); + e.getStyle().setProperty("-webkit-overflow-scrolling", + "touch"); + e.getStyle().setProperty("-webkit-user-select", "none"); + } + } + } + } + public TouchScrollDelegate(Element... elements) { scrollableElements = elements; } @@ -535,7 +580,7 @@ public class TouchScrollDelegate implements NativePreviewHandler { } } - public void setElements(com.google.gwt.user.client.Element[] elements) { + public void setElements(Element[] elements) { scrollableElements = elements; } -- cgit v1.2.3 From 16d1f5b07ee217c5e30656796357ed8ee1c316d4 Mon Sep 17 00:00:00 2001 From: Automerge Date: Thu, 3 May 2012 17:06:26 +0000 Subject: [merge from 6.7] Fixed #8589: Permit XHTML content in UserError svn changeset:23673/svn branch:6.8 --- src/com/vaadin/terminal/UserError.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/com/vaadin/terminal/UserError.java b/src/com/vaadin/terminal/UserError.java index 170d76610b..678e936dec 100644 --- a/src/com/vaadin/terminal/UserError.java +++ b/src/com/vaadin/terminal/UserError.java @@ -77,7 +77,7 @@ public class UserError implements ErrorMessage { public UserError(String message, int contentMode, int errorLevel) { // Check the parameters - if (contentMode < 0 || contentMode > 2) { + if (contentMode < 0 || contentMode > 3) { throw new java.lang.IllegalArgumentException( "Unsupported content mode: " + contentMode); } -- cgit v1.2.3 From 2a72a1db5f3698c4fe040b96043f9fea3f31d308 Mon Sep 17 00:00:00 2001 From: Automerge Date: Fri, 4 May 2012 09:55:44 +0000 Subject: [merge from 6.7] Blur the combo box before swapping data source to avoid random issue in Safari related to Testbench blur emulation svn changeset:23675/svn branch:6.8 --- .../tests/components/combobox/ComboBoxInvalidNullSelection.html | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/testbench/com/vaadin/tests/components/combobox/ComboBoxInvalidNullSelection.html b/tests/testbench/com/vaadin/tests/components/combobox/ComboBoxInvalidNullSelection.html index bbe5d5d717..1459a30985 100644 --- a/tests/testbench/com/vaadin/tests/components/combobox/ComboBoxInvalidNullSelection.html +++ b/tests/testbench/com/vaadin/tests/components/combobox/ComboBoxInvalidNullSelection.html @@ -31,6 +31,11 @@ vaadin=runcomvaadintestscomponentscomboboxComboBoxInvalidNullSelection::Root/VFilterSelect$SuggestionPopup[0]/VFilterSelect$SuggestionMenu[0]#item3 101,11 + + click + vaadin=runcomvaadintestscomponentscomboboxComboBoxInvalidNullSelection::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[3]/VButton[0]/domChild[0]/domChild[0] + + click vaadin=runcomvaadintestscomponentscomboboxComboBoxInvalidNullSelection::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[1]/VButton[0]/domChild[0]/domChild[0] -- cgit v1.2.3 From 63dc030e321b05faf02248ca266a90dec2aff067 Mon Sep 17 00:00:00 2001 From: Johannes Dahlström Date: Fri, 4 May 2012 13:13:11 +0000 Subject: Add new CSS class to the base theme enabling (touch) scrolling of the element (#8716 #8720 #8721 #8722 #8723 #8724 #8725) svn changeset:23677/svn branch:6.8 --- WebContent/VAADIN/themes/base/common/common.css | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/WebContent/VAADIN/themes/base/common/common.css b/WebContent/VAADIN/themes/base/common/common.css index 27bc57dd00..adf84ac3b7 100644 --- a/WebContent/VAADIN/themes/base/common/common.css +++ b/WebContent/VAADIN/themes/base/common/common.css @@ -229,4 +229,9 @@ div.v-app-loading { opacity: 0.5; filter: alpha(opacity=50); cursor: default; +} + +.v-scrollable { + overflow: auto; + -webkit-overflow-scrolling: touch; } \ No newline at end of file -- cgit v1.2.3 From 295e0f391131d5a9fa9d2f2b08dcc6418e42d484 Mon Sep 17 00:00:00 2001 From: Automerge Date: Fri, 4 May 2012 13:19:50 +0000 Subject: [merge from 6.7] Fix #7136: Opening a modal subwindow when there are visible notifications prevented the notifications from fading svn changeset:23678/svn branch:6.8 --- .../terminal/gwt/client/ui/VNotification.java | 19 ++++++++++ src/com/vaadin/terminal/gwt/client/ui/VWindow.java | 1 + .../notification/NotificationsAndModalWindow.html | 42 ++++++++++++++++++++++ .../notification/NotificationsAndModalWindow.java | 42 ++++++++++++++++++++++ 4 files changed, 104 insertions(+) create mode 100644 tests/testbench/com/vaadin/tests/components/notification/NotificationsAndModalWindow.html create mode 100644 tests/testbench/com/vaadin/tests/components/notification/NotificationsAndModalWindow.java diff --git a/src/com/vaadin/terminal/gwt/client/ui/VNotification.java b/src/com/vaadin/terminal/gwt/client/ui/VNotification.java index 2ee66d01ca..4166148a25 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VNotification.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VNotification.java @@ -41,6 +41,8 @@ public class VNotification extends VOverlay { public static final String STYLE_SYSTEM = "system"; private static final int FADE_ANIMATION_INTERVAL = 50; // == 20 fps + private static final ArrayList notifications = new ArrayList(); + private int startOpacity = 90; private int fadeMsec = 400; private int delayMsec = 1000; @@ -150,6 +152,7 @@ public class VNotification extends VOverlay { addStyleDependentName(style); } super.show(); + notifications.add(this); setPosition(position); /** * Android 4 fails to render notifications correctly without a little @@ -171,6 +174,7 @@ public class VNotification extends VOverlay { temporaryStyle = null; } super.hide(); + notifications.remove(this); fireEvent(new HideEvent(this)); } @@ -421,4 +425,19 @@ public class VNotification extends VOverlay { public interface EventListener extends java.util.EventListener { public void notificationHidden(HideEvent event); } + + /** + * Moves currently visible notifications to the top of the event preview + * stack. Can be called when opening other overlays such as subwindows to + * ensure the notifications receive the events they need and don't linger + * indefinitely. See #7136. + * + * TODO Should this be a generic Overlay feature instead? + */ + public static void bringNotificationsToFront() { + for (VNotification notification : notifications) { + DOM.removeEventPreview(notification); + DOM.addEventPreview(notification); + } + } } diff --git a/src/com/vaadin/terminal/gwt/client/ui/VWindow.java b/src/com/vaadin/terminal/gwt/client/ui/VWindow.java index 103979927a..2355a9c65a 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VWindow.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VWindow.java @@ -520,6 +520,7 @@ public class VWindow extends VOverlay implements Container, Scheduler.get().scheduleFinally(new Command() { public void execute() { doServerSideOrdering(); + VNotification.bringNotificationsToFront(); } }); } diff --git a/tests/testbench/com/vaadin/tests/components/notification/NotificationsAndModalWindow.html b/tests/testbench/com/vaadin/tests/components/notification/NotificationsAndModalWindow.html new file mode 100644 index 0000000000..35d22da46e --- /dev/null +++ b/tests/testbench/com/vaadin/tests/components/notification/NotificationsAndModalWindow.html @@ -0,0 +1,42 @@ + + + + + + +NotificationsAndModalWindow + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NotificationsAndModalWindow
open/run/com.vaadin.tests.components.notification.NotificationsAndModalWindow?restartApplication
clickvaadin=runcomvaadintestscomponentsnotificationNotificationsAndModalWindow::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VButton[0]/domChild[0]/domChild[0]
closeNotificationvaadin=runcomvaadintestscomponentsnotificationNotificationsAndModalWindow::Root/VNotification[1]0,0
closeNotificationvaadin=runcomvaadintestscomponentsnotificationNotificationsAndModalWindow::Root/VNotification[0]0,0
assertElementNotPresentvaadin=runcomvaadintestscomponentsnotificationNotificationsAndModalWindow::Root/VNotification[0]
+ + diff --git a/tests/testbench/com/vaadin/tests/components/notification/NotificationsAndModalWindow.java b/tests/testbench/com/vaadin/tests/components/notification/NotificationsAndModalWindow.java new file mode 100644 index 0000000000..562e8095f2 --- /dev/null +++ b/tests/testbench/com/vaadin/tests/components/notification/NotificationsAndModalWindow.java @@ -0,0 +1,42 @@ +package com.vaadin.tests.components.notification; + +import com.vaadin.tests.components.TestBase; +import com.vaadin.ui.Button; +import com.vaadin.ui.Button.ClickEvent; +import com.vaadin.ui.Window; +import com.vaadin.ui.Window.Notification; + +public class NotificationsAndModalWindow extends TestBase { + + @Override + protected void setup() { + getMainWindow().showNotification("Notification 1", + Notification.TYPE_WARNING_MESSAGE); + getMainWindow().showNotification("Notification 2", + Notification.TYPE_WARNING_MESSAGE); + + Button b = new Button("Button"); + b.addListener(new Button.ClickListener() { + + public void buttonClick(ClickEvent event) { + + Window w = new Window("This is a window"); + w.setModal(true); + getMainWindow().addWindow(w); + } + + }); + addComponent(b); + } + + @Override + protected String getDescription() { + return "Press the button when both two notifications are visible to add a modal window to the app. When the modal window is visible, the notifications should disappear normally."; + } + + @Override + protected Integer getTicketNumber() { + return 7136; + } + +} -- cgit v1.2.3 From 4599ecaf627974d225380dddeb6baa92a549df8e Mon Sep 17 00:00:00 2001 From: Johannes Dahlström Date: Fri, 4 May 2012 13:41:04 +0000 Subject: Improved TouchScrollHandler helper svn changeset:23679/svn branch:6.8 --- .../gwt/client/ui/TouchScrollDelegate.java | 23 ++++++++-------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/src/com/vaadin/terminal/gwt/client/ui/TouchScrollDelegate.java b/src/com/vaadin/terminal/gwt/client/ui/TouchScrollDelegate.java index a2a94489e4..ac9527e3ef 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/TouchScrollDelegate.java +++ b/src/com/vaadin/terminal/gwt/client/ui/TouchScrollDelegate.java @@ -100,37 +100,30 @@ public class TouchScrollDelegate implements NativePreviewHandler { widget.addDomHandler(this, TouchStartEvent.getType()); } else { delegate = null; - widget.addDomHandler(new TouchStartHandler() { - - public void onTouchStart(TouchStartEvent event) { - // TODO Auto-generated method stub - - } - }, TouchStartEvent.getType()); } setElements(scrollables); } public void onTouchStart(TouchStartEvent event) { - VConsole.log("TouchScrollHandler onTouchStart"); assert delegate != null; delegate.onTouchStart(event); } public void setElements(Element... scrollables) { + for (Element scrollable : scrollables) { + scrollable.addClassName("v-scrollable"); + } if (requiresDelegate) { delegate.setElements(scrollables); - } else if (BrowserInfo.get().isTouchDevice()) { - for (Element e : scrollables) { - e.getStyle().setProperty("overflow", "auto"); - e.getStyle().setProperty("-webkit-overflow-scrolling", - "touch"); - e.getStyle().setProperty("-webkit-user-select", "none"); - } } } } + public static TouchScrollHandler enableTouchScrolling(Widget widget, + Element... scrollables) { + return new TouchScrollHandler(widget, scrollables); + } + public TouchScrollDelegate(Element... elements) { scrollableElements = elements; } -- cgit v1.2.3 From 33e3dc600c990bf8e93f0ac88af26e5e95b79965 Mon Sep 17 00:00:00 2001 From: Johannes Dahlström Date: Fri, 4 May 2012 13:51:15 +0000 Subject: #8716 Use TouchScrollDelegate.enableTouchScrolling() instead of a TouchScrollDelegate instance directly svn changeset:23680/svn branch:6.8 --- src/com/vaadin/terminal/gwt/client/ui/VPanel.java | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/src/com/vaadin/terminal/gwt/client/ui/VPanel.java b/src/com/vaadin/terminal/gwt/client/ui/VPanel.java index 036f4f0600..f754addcf3 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VPanel.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VPanel.java @@ -9,8 +9,6 @@ import java.util.Set; import com.google.gwt.dom.client.DivElement; import com.google.gwt.dom.client.Document; import com.google.gwt.event.dom.client.DomEvent.Type; -import com.google.gwt.event.dom.client.TouchStartEvent; -import com.google.gwt.event.dom.client.TouchStartHandler; import com.google.gwt.event.shared.EventHandler; import com.google.gwt.event.shared.HandlerRegistration; import com.google.gwt.user.client.DOM; @@ -90,7 +88,6 @@ public class VPanel extends SimplePanel implements Container, return addDomHandler(handler, type); } }; - private TouchScrollDelegate touchScrollDelegate; public VPanel() { super(); @@ -120,11 +117,8 @@ public class VPanel extends SimplePanel implements Container, DOM.sinkEvents(contentNode, Event.ONSCROLL | Event.TOUCHEVENTS); contentNode.getStyle().setProperty("position", "relative"); getElement().getStyle().setProperty("overflow", "hidden"); - addHandler(new TouchStartHandler() { - public void onTouchStart(TouchStartEvent event) { - getTouchScrollDelegate().onTouchStart(event); - } - }, TouchStartEvent.getType()); + + TouchScrollDelegate.enableTouchScrolling(this, contentNode); } /** @@ -438,14 +432,6 @@ public class VPanel extends SimplePanel implements Container, } } - protected TouchScrollDelegate getTouchScrollDelegate() { - if (touchScrollDelegate == null) { - touchScrollDelegate = new TouchScrollDelegate(contentNode); - } - return touchScrollDelegate; - - } - @Override public void setHeight(String height) { this.height = height; -- cgit v1.2.3 From c3bba747205792447d67b3ac0c1ecf91ec6f87ca Mon Sep 17 00:00:00 2001 From: Johannes Dahlström Date: Fri, 4 May 2012 14:44:22 +0000 Subject: #8720 Use TouchScrollDelegate.enableTouchScrolling() instead of a TouchScrollDelegate instance directly svn changeset:23681/svn branch:6.8 --- .../terminal/gwt/client/ui/VTabsheetPanel.java | 36 ++++------------------ 1 file changed, 6 insertions(+), 30 deletions(-) diff --git a/src/com/vaadin/terminal/gwt/client/ui/VTabsheetPanel.java b/src/com/vaadin/terminal/gwt/client/ui/VTabsheetPanel.java index 126b0ebea1..f1dbea18b2 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VTabsheetPanel.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VTabsheetPanel.java @@ -4,16 +4,13 @@ package com.vaadin.terminal.gwt.client.ui; -import com.google.gwt.dom.client.Node; -import com.google.gwt.dom.client.NodeList; -import com.google.gwt.event.dom.client.TouchStartEvent; -import com.google.gwt.event.dom.client.TouchStartHandler; 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.ui.ComplexPanel; import com.google.gwt.user.client.ui.Widget; import com.vaadin.terminal.gwt.client.Util; +import com.vaadin.terminal.gwt.client.ui.TouchScrollDelegate.TouchScrollHandler; /** * A panel that displays all of its child widgets in a 'deck', where only one @@ -27,7 +24,8 @@ import com.vaadin.terminal.gwt.client.Util; public class VTabsheetPanel extends ComplexPanel { private Widget visibleWidget; - private TouchScrollDelegate touchScrollDelegate; + + private TouchScrollHandler touchScrollHandler; /** * Creates an empty tabsheet panel. @@ -35,30 +33,8 @@ public class VTabsheetPanel extends ComplexPanel { public VTabsheetPanel() { setElement(DOM.createDiv()); sinkEvents(Event.TOUCHEVENTS); - addDomHandler(new TouchStartHandler() { - public void onTouchStart(TouchStartEvent event) { - /* - * All container elements needs to be scrollable by one finger. - * Update the scrollable element list of touch delegate on each - * touch start. - */ - NodeList childNodes = getElement().getChildNodes(); - Element[] elements = new Element[childNodes.getLength()]; - for (int i = 0; i < elements.length; i++) { - elements[i] = (Element) childNodes.getItem(i); - } - getTouchScrollDelegate().setElements(elements); - getTouchScrollDelegate().onTouchStart(event); - } - }, TouchStartEvent.getType()); - } - - protected TouchScrollDelegate getTouchScrollDelegate() { - if (touchScrollDelegate == null) { - touchScrollDelegate = new TouchScrollDelegate(); - } - return touchScrollDelegate; + touchScrollHandler = TouchScrollDelegate.enableTouchScrolling(this); } /** @@ -77,7 +53,6 @@ public class VTabsheetPanel extends ComplexPanel { private Element createContainerElement() { Element el = DOM.createDiv(); DOM.setStyleAttribute(el, "position", "absolute"); - DOM.setStyleAttribute(el, "overflow", "auto"); hide(el); return el; } @@ -142,6 +117,8 @@ public class VTabsheetPanel extends ComplexPanel { } visibleWidget = newVisible; unHide(DOM.getParent(visibleWidget.getElement())); + touchScrollHandler.setElements(visibleWidget.getElement() + .getParentElement()); } } @@ -199,7 +176,6 @@ public class VTabsheetPanel extends ComplexPanel { Util.runWebkitOverflowAutoFix(DOM.getParent(visibleWidget .getElement())); } - } public void replaceComponent(Widget oldComponent, Widget newComponent) { -- cgit v1.2.3 From 03b6110d94b65d0767d1519fac572630538cf314 Mon Sep 17 00:00:00 2001 From: Automerge Date: Mon, 7 May 2012 13:06:50 +0000 Subject: [merge from 6.7] Test that a sensible message is displayed if no application is found svn changeset:23683/svn branch:6.8 --- .../applicationservlet/NoApplicationClass.html | 26 ++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 tests/testbench/com/vaadin/tests/applicationservlet/NoApplicationClass.html diff --git a/tests/testbench/com/vaadin/tests/applicationservlet/NoApplicationClass.html b/tests/testbench/com/vaadin/tests/applicationservlet/NoApplicationClass.html new file mode 100644 index 0000000000..70bb8cc8f3 --- /dev/null +++ b/tests/testbench/com/vaadin/tests/applicationservlet/NoApplicationClass.html @@ -0,0 +1,26 @@ + + + + + + +New Test + + + + + + + + + + + + + + + + +
New Test
open/run/ClassThatIsNotPresent?restartApplication
assertText//pre[1]java.lang.InstantiationException: Failed to load application class: ClassThatIsNotPresent
+ + -- cgit v1.2.3 From a810ce9ce0bafce6d9b437582e706175f4c8827a Mon Sep 17 00:00:00 2001 From: Leif Åstrand Date: Mon, 7 May 2012 13:16:13 +0000 Subject: Don't assume there's always an application (#8694) svn changeset:23684/svn branch:6.8 --- .../vaadin/terminal/gwt/server/AbstractApplicationPortlet.java | 8 +++++--- .../vaadin/terminal/gwt/server/AbstractApplicationServlet.java | 7 ++++--- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/com/vaadin/terminal/gwt/server/AbstractApplicationPortlet.java b/src/com/vaadin/terminal/gwt/server/AbstractApplicationPortlet.java index 1741ec5e7f..2ac574c2de 100644 --- a/src/com/vaadin/terminal/gwt/server/AbstractApplicationPortlet.java +++ b/src/com/vaadin/terminal/gwt/server/AbstractApplicationPortlet.java @@ -495,9 +495,11 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet } } finally { - requestTimer - .stop((AbstractWebApplicationContext) application - .getContext()); + PortletSession session = request + .getPortletSession(false); + if (session != null) { + requestTimer.stop(getApplicationContext(session)); + } } } } diff --git a/src/com/vaadin/terminal/gwt/server/AbstractApplicationServlet.java b/src/com/vaadin/terminal/gwt/server/AbstractApplicationServlet.java index d42b2142fe..68089e18e0 100644 --- a/src/com/vaadin/terminal/gwt/server/AbstractApplicationServlet.java +++ b/src/com/vaadin/terminal/gwt/server/AbstractApplicationServlet.java @@ -552,9 +552,10 @@ public abstract class AbstractApplicationServlet extends HttpServlet implements .onRequestEnd(request, response); } } finally { - requestTimer - .stop((AbstractWebApplicationContext) application - .getContext()); + HttpSession session = request.getSession(false); + if (session != null) { + requestTimer.stop(getApplicationContext(session)); + } } } -- cgit v1.2.3 From 257d49fc06f152df292704e8ae6c3bc9a5541a8f Mon Sep 17 00:00:00 2001 From: Leif Åstrand Date: Mon, 7 May 2012 13:20:18 +0000 Subject: Prevent setting mainWindow from a TestBase svn changeset:23685/svn branch:6.8 --- .../com/vaadin/tests/application/PaintableIdsShouldBeUnique.java | 6 +++--- tests/testbench/com/vaadin/tests/components/TestBase.java | 9 +++++++++ .../vaadin/tests/components/table/ScrollCausesRequestLoop.java | 6 +++--- .../tests/components/table/ScrollDetachSynchronization.java | 6 +++--- .../tests/components/table/TableClickValueChangeInteraction.java | 6 +++--- .../components/window/ReplacingComponentsInHandleParameters.java | 6 +++--- .../vaadin/tests/containers/TableWithFileSystemContainer.java | 6 +++--- tests/testbench/com/vaadin/tests/layouts/GridLayoutCaptions.java | 6 +++--- .../vaadin/tests/layouts/GridLayoutExpandRatioModification.java | 8 ++++---- .../tests/layouts/VerticalLayoutExpandRatioModification.java | 8 ++++---- tests/testbench/com/vaadin/tests/tickets/Ticket6002.java | 6 +++--- .../com/vaadin/tests/validation/RequiredErrorMessage.java | 6 +++--- 12 files changed, 44 insertions(+), 35 deletions(-) diff --git a/tests/testbench/com/vaadin/tests/application/PaintableIdsShouldBeUnique.java b/tests/testbench/com/vaadin/tests/application/PaintableIdsShouldBeUnique.java index 95760c11a8..a7c9fe4a4f 100644 --- a/tests/testbench/com/vaadin/tests/application/PaintableIdsShouldBeUnique.java +++ b/tests/testbench/com/vaadin/tests/application/PaintableIdsShouldBeUnique.java @@ -1,16 +1,16 @@ package com.vaadin.tests.application; import com.vaadin.terminal.ExternalResource; -import com.vaadin.tests.components.TestBase; +import com.vaadin.tests.components.AbstractTestCase; import com.vaadin.ui.Button; import com.vaadin.ui.Button.ClickEvent; import com.vaadin.ui.Label; import com.vaadin.ui.Window; -public class PaintableIdsShouldBeUnique extends TestBase { +public class PaintableIdsShouldBeUnique extends AbstractTestCase { @Override - protected void setup() { + public void init() { setMainWindow(new MyWindow()); } diff --git a/tests/testbench/com/vaadin/tests/components/TestBase.java b/tests/testbench/com/vaadin/tests/components/TestBase.java index c7380d3d7c..4d34fb2c8d 100644 --- a/tests/testbench/com/vaadin/tests/components/TestBase.java +++ b/tests/testbench/com/vaadin/tests/components/TestBase.java @@ -24,6 +24,15 @@ public abstract class TestBase extends AbstractTestCase { setup(); } + @Override + public void setMainWindow(Window mainWindow) { + if (mainWindow != window) { + throw new IllegalStateException( + "You should not set your own main window when using TestBase. If you need to use a custom Window as the main window, use AbstractTestCase instead."); + } + super.setMainWindow(mainWindow); + } + private Window window; private VerticalLayout layout; diff --git a/tests/testbench/com/vaadin/tests/components/table/ScrollCausesRequestLoop.java b/tests/testbench/com/vaadin/tests/components/table/ScrollCausesRequestLoop.java index 1916dcd0d7..b4c46a2ca6 100644 --- a/tests/testbench/com/vaadin/tests/components/table/ScrollCausesRequestLoop.java +++ b/tests/testbench/com/vaadin/tests/components/table/ScrollCausesRequestLoop.java @@ -4,16 +4,16 @@ import java.util.ArrayList; import java.util.List; import com.vaadin.data.util.BeanItemContainer; -import com.vaadin.tests.components.TestBase; +import com.vaadin.tests.components.AbstractTestCase; import com.vaadin.tests.util.Person; import com.vaadin.ui.HorizontalLayout; import com.vaadin.ui.Table; import com.vaadin.ui.Window; -public class ScrollCausesRequestLoop extends TestBase { +public class ScrollCausesRequestLoop extends AbstractTestCase { @Override - protected void setup() { + public void init() { setMainWindow(new Window("", new TestView())); } diff --git a/tests/testbench/com/vaadin/tests/components/table/ScrollDetachSynchronization.java b/tests/testbench/com/vaadin/tests/components/table/ScrollDetachSynchronization.java index fe99cfaf2a..07a2974052 100644 --- a/tests/testbench/com/vaadin/tests/components/table/ScrollDetachSynchronization.java +++ b/tests/testbench/com/vaadin/tests/components/table/ScrollDetachSynchronization.java @@ -1,6 +1,6 @@ package com.vaadin.tests.components.table; -import com.vaadin.tests.components.TestBase; +import com.vaadin.tests.components.AbstractTestCase; import com.vaadin.ui.Button; import com.vaadin.ui.Button.ClickEvent; import com.vaadin.ui.HorizontalLayout; @@ -9,10 +9,10 @@ import com.vaadin.ui.Table; import com.vaadin.ui.VerticalLayout; import com.vaadin.ui.Window; -public class ScrollDetachSynchronization extends TestBase { +public class ScrollDetachSynchronization extends AbstractTestCase { @Override - public void setup() { + public void init() { Window mainWindow = new Window("Synctest Application"); mainWindow.setContent(buildLayout()); setMainWindow(mainWindow); diff --git a/tests/testbench/com/vaadin/tests/components/table/TableClickValueChangeInteraction.java b/tests/testbench/com/vaadin/tests/components/table/TableClickValueChangeInteraction.java index 47216033e9..63c6c753ca 100644 --- a/tests/testbench/com/vaadin/tests/components/table/TableClickValueChangeInteraction.java +++ b/tests/testbench/com/vaadin/tests/components/table/TableClickValueChangeInteraction.java @@ -4,7 +4,7 @@ import com.vaadin.data.Property.ValueChangeEvent; import com.vaadin.data.Property.ValueChangeListener; import com.vaadin.event.ItemClickEvent; import com.vaadin.event.ItemClickEvent.ItemClickListener; -import com.vaadin.tests.components.TestBase; +import com.vaadin.tests.components.AbstractTestCase; import com.vaadin.ui.Component; import com.vaadin.ui.GridLayout; import com.vaadin.ui.Label; @@ -13,12 +13,12 @@ import com.vaadin.ui.Table; import com.vaadin.ui.VerticalLayout; import com.vaadin.ui.Window; -public class TableClickValueChangeInteraction extends TestBase { +public class TableClickValueChangeInteraction extends AbstractTestCase { final Window mainWindow = new Window(); @Override - public void setup() { + public void init() { setMainWindow(mainWindow); GridLayout layout = new GridLayout(4, 4); diff --git a/tests/testbench/com/vaadin/tests/components/window/ReplacingComponentsInHandleParameters.java b/tests/testbench/com/vaadin/tests/components/window/ReplacingComponentsInHandleParameters.java index d6fe10601f..1f87c3c563 100644 --- a/tests/testbench/com/vaadin/tests/components/window/ReplacingComponentsInHandleParameters.java +++ b/tests/testbench/com/vaadin/tests/components/window/ReplacingComponentsInHandleParameters.java @@ -2,14 +2,14 @@ package com.vaadin.tests.components.window; import java.util.Map; -import com.vaadin.tests.components.TestBase; +import com.vaadin.tests.components.AbstractTestCase; import com.vaadin.ui.Button; import com.vaadin.ui.Button.ClickEvent; import com.vaadin.ui.Button.ClickListener; import com.vaadin.ui.Label; import com.vaadin.ui.Window; -public class ReplacingComponentsInHandleParameters extends TestBase { +public class ReplacingComponentsInHandleParameters extends AbstractTestCase { @Override protected String getDescription() { @@ -22,7 +22,7 @@ public class ReplacingComponentsInHandleParameters extends TestBase { } @Override - protected void setup() { + public void init() { final ClickListener clickListener = new ClickListener() { public void buttonClick(ClickEvent event) { event.getButton().setCaption("Clicked!"); diff --git a/tests/testbench/com/vaadin/tests/containers/TableWithFileSystemContainer.java b/tests/testbench/com/vaadin/tests/containers/TableWithFileSystemContainer.java index 20567e70af..bedb2a735e 100644 --- a/tests/testbench/com/vaadin/tests/containers/TableWithFileSystemContainer.java +++ b/tests/testbench/com/vaadin/tests/containers/TableWithFileSystemContainer.java @@ -3,16 +3,16 @@ package com.vaadin.tests.containers; import java.io.File; import com.vaadin.data.util.FilesystemContainer; -import com.vaadin.tests.components.TestBase; +import com.vaadin.tests.components.AbstractTestCase; import com.vaadin.ui.Table; import com.vaadin.ui.Window; -public class TableWithFileSystemContainer extends TestBase { +public class TableWithFileSystemContainer extends AbstractTestCase { private String testPath = "C:/temp/img"; @Override - public void setup() { + public void init() { setMainWindow(new Window("")); Table table = new Table("Documents", new FilesystemContainer(new File( testPath))); diff --git a/tests/testbench/com/vaadin/tests/layouts/GridLayoutCaptions.java b/tests/testbench/com/vaadin/tests/layouts/GridLayoutCaptions.java index 08df953e66..d851e9326f 100644 --- a/tests/testbench/com/vaadin/tests/layouts/GridLayoutCaptions.java +++ b/tests/testbench/com/vaadin/tests/layouts/GridLayoutCaptions.java @@ -3,7 +3,7 @@ package com.vaadin.tests.layouts; import com.vaadin.data.Item; import com.vaadin.data.Validator; import com.vaadin.data.util.BeanItem; -import com.vaadin.tests.components.TestBase; +import com.vaadin.tests.components.AbstractTestCase; import com.vaadin.ui.Button; import com.vaadin.ui.Button.ClickEvent; import com.vaadin.ui.Component; @@ -18,7 +18,7 @@ import com.vaadin.ui.TextField; import com.vaadin.ui.VerticalLayout; import com.vaadin.ui.Window; -public class GridLayoutCaptions extends TestBase { +public class GridLayoutCaptions extends AbstractTestCase { class CustomForm extends Form { private com.vaadin.ui.GridLayout layout; @@ -173,7 +173,7 @@ public class GridLayoutCaptions extends TestBase { } @Override - protected void setup() { + public void init() { Window mainWindow = new Window("Formlayoutcaptionboom Application"); Label label = new Label("Hello Vaadin user"); mainWindow.addComponent(label); diff --git a/tests/testbench/com/vaadin/tests/layouts/GridLayoutExpandRatioModification.java b/tests/testbench/com/vaadin/tests/layouts/GridLayoutExpandRatioModification.java index e9d206009a..fa44345dfe 100644 --- a/tests/testbench/com/vaadin/tests/layouts/GridLayoutExpandRatioModification.java +++ b/tests/testbench/com/vaadin/tests/layouts/GridLayoutExpandRatioModification.java @@ -1,6 +1,6 @@ package com.vaadin.tests.layouts; -import com.vaadin.tests.components.TestBase; +import com.vaadin.tests.components.AbstractTestCase; import com.vaadin.ui.Button; import com.vaadin.ui.Button.ClickEvent; import com.vaadin.ui.Button.ClickListener; @@ -10,8 +10,8 @@ import com.vaadin.ui.TextField; import com.vaadin.ui.VerticalLayout; import com.vaadin.ui.Window; -public class GridLayoutExpandRatioModification extends TestBase implements - ClickListener { +public class GridLayoutExpandRatioModification extends AbstractTestCase + implements ClickListener { private boolean isVisible = false; private GridLayout mainLayout; @@ -20,7 +20,7 @@ public class GridLayoutExpandRatioModification extends TestBase implements private Button button; @Override - public void setup() { + public void init() { Window main = new Window("The Main Window"); mainLayout = new GridLayout(3, 3); main.setContent(mainLayout); diff --git a/tests/testbench/com/vaadin/tests/layouts/VerticalLayoutExpandRatioModification.java b/tests/testbench/com/vaadin/tests/layouts/VerticalLayoutExpandRatioModification.java index e2c02a629b..5b1c7a5888 100644 --- a/tests/testbench/com/vaadin/tests/layouts/VerticalLayoutExpandRatioModification.java +++ b/tests/testbench/com/vaadin/tests/layouts/VerticalLayoutExpandRatioModification.java @@ -1,6 +1,6 @@ package com.vaadin.tests.layouts; -import com.vaadin.tests.components.TestBase; +import com.vaadin.tests.components.AbstractTestCase; import com.vaadin.ui.Button; import com.vaadin.ui.Button.ClickEvent; import com.vaadin.ui.Button.ClickListener; @@ -9,8 +9,8 @@ import com.vaadin.ui.TextField; import com.vaadin.ui.VerticalLayout; import com.vaadin.ui.Window; -public class VerticalLayoutExpandRatioModification extends TestBase implements - ClickListener { +public class VerticalLayoutExpandRatioModification extends AbstractTestCase + implements ClickListener { private boolean isVisible = false; private VerticalLayout mainLayout; @@ -19,7 +19,7 @@ public class VerticalLayoutExpandRatioModification extends TestBase implements private Button button; @Override - public void setup() { + public void init() { Window main = new Window("The Main Window"); mainLayout = new VerticalLayout(); main.setContent(mainLayout); diff --git a/tests/testbench/com/vaadin/tests/tickets/Ticket6002.java b/tests/testbench/com/vaadin/tests/tickets/Ticket6002.java index bd6a8e2b7c..ad3b01ae78 100644 --- a/tests/testbench/com/vaadin/tests/tickets/Ticket6002.java +++ b/tests/testbench/com/vaadin/tests/tickets/Ticket6002.java @@ -3,16 +3,16 @@ package com.vaadin.tests.tickets; import com.vaadin.data.Property; import com.vaadin.data.Property.ValueChangeEvent; import com.vaadin.data.util.ObjectProperty; -import com.vaadin.tests.components.TestBase; +import com.vaadin.tests.components.AbstractTestCase; import com.vaadin.ui.Label; import com.vaadin.ui.TextField; import com.vaadin.ui.VerticalLayout; import com.vaadin.ui.Window; -public class Ticket6002 extends TestBase { +public class Ticket6002 extends AbstractTestCase { @Override - public void setup() { + public void init() { Window main = new Window("The Main Window"); setMainWindow(main); diff --git a/tests/testbench/com/vaadin/tests/validation/RequiredErrorMessage.java b/tests/testbench/com/vaadin/tests/validation/RequiredErrorMessage.java index 7f5048bd80..81c737cd17 100644 --- a/tests/testbench/com/vaadin/tests/validation/RequiredErrorMessage.java +++ b/tests/testbench/com/vaadin/tests/validation/RequiredErrorMessage.java @@ -1,12 +1,12 @@ package com.vaadin.tests.validation; -import com.vaadin.tests.components.TestBase; +import com.vaadin.tests.components.AbstractTestCase; import com.vaadin.ui.Form; import com.vaadin.ui.TextField; import com.vaadin.ui.VerticalLayout; import com.vaadin.ui.Window; -public class RequiredErrorMessage extends TestBase { +public class RequiredErrorMessage extends AbstractTestCase { @Override protected Integer getTicketNumber() { @@ -19,7 +19,7 @@ public class RequiredErrorMessage extends TestBase { } @Override - public void setup() { + public void init() { final Window main = new Window(getClass().getName()); setMainWindow(main); -- cgit v1.2.3 From 97df7ebc178ae8aa5f6105822cfa10340b232867 Mon Sep 17 00:00:00 2001 From: Johannes Dahlström Date: Mon, 7 May 2012 13:20:37 +0000 Subject: #8763 requiresTouchScrollDelegate now returns false for iOS5; the default return value is now true instead of false. svn changeset:23686/svn branch:6.8 --- src/com/vaadin/terminal/gwt/client/BrowserInfo.java | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/com/vaadin/terminal/gwt/client/BrowserInfo.java b/src/com/vaadin/terminal/gwt/client/BrowserInfo.java index 8ec610c089..5e496bd05d 100644 --- a/src/com/vaadin/terminal/gwt/client/BrowserInfo.java +++ b/src/com/vaadin/terminal/gwt/client/BrowserInfo.java @@ -445,15 +445,13 @@ public class BrowserInfo { if (!isTouchDevice()) { return false; } - - if (isAndroid() && isWebkit() && getWebkitVersion() < 534) { - return true; + if (isAndroid() && isWebkit() && getWebkitVersion() >= 534) { + return false; } - // if (isIOS() && isWebkit() && getWebkitVersion() < ???) { - // return true; - // } - - return false; + if (isIOS() && isWebkit() && getWebkitVersion() >= 534) { + return false; + } + return true; } /** -- cgit v1.2.3 From 62c36174ce0d63aca7bab3936226d01734bb9b12 Mon Sep 17 00:00:00 2001 From: Johannes Dahlström Date: Mon, 7 May 2012 13:22:39 +0000 Subject: #8763 Use Set instead of an array in TouchScrollDelegate to allow dynamic adding and removing scrollable elements svn changeset:23687/svn branch:6.8 --- .../gwt/client/ui/TouchScrollDelegate.java | 27 +++++++++++++--------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/src/com/vaadin/terminal/gwt/client/ui/TouchScrollDelegate.java b/src/com/vaadin/terminal/gwt/client/ui/TouchScrollDelegate.java index ac9527e3ef..65d8029593 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/TouchScrollDelegate.java +++ b/src/com/vaadin/terminal/gwt/client/ui/TouchScrollDelegate.java @@ -4,6 +4,8 @@ package com.vaadin.terminal.gwt.client.ui; import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; import com.google.gwt.animation.client.Animation; import com.google.gwt.core.client.Duration; @@ -70,7 +72,7 @@ public class TouchScrollDelegate implements NativePreviewHandler { private static final double DECELERATION = 0.002; private static final int MAX_DURATION = 1500; private int origY; - private Element[] scrollableElements; + private HashSet scrollableElements; private Element scrolledElement; private int origScrollTop; private HandlerRegistration handlerRegistration; @@ -101,7 +103,9 @@ public class TouchScrollDelegate implements NativePreviewHandler { } else { delegate = null; } - setElements(scrollables); + for (Element scrollable : scrollables) { + addElement(scrollable); + } } public void onTouchStart(TouchStartEvent event) { @@ -109,12 +113,17 @@ public class TouchScrollDelegate implements NativePreviewHandler { delegate.onTouchStart(event); } - public void setElements(Element... scrollables) { - for (Element scrollable : scrollables) { - scrollable.addClassName("v-scrollable"); + public void addElement(Element scrollable) { + scrollable.addClassName("v-scrollable"); + if (requiresDelegate) { + delegate.scrollableElements.add(scrollable); } + } + + public void removeElement(Element scrollable) { + scrollable.removeClassName("v-scrollable"); if (requiresDelegate) { - delegate.setElements(scrollables); + delegate.scrollableElements.remove(scrollable); } } } @@ -125,7 +134,7 @@ public class TouchScrollDelegate implements NativePreviewHandler { } public TouchScrollDelegate(Element... elements) { - scrollableElements = elements; + scrollableElements = new HashSet(Arrays.asList(elements)); } public void setScrollHandler(ScrollHandler scrollHandler) { @@ -573,10 +582,6 @@ public class TouchScrollDelegate implements NativePreviewHandler { } } - public void setElements(Element[] elements) { - scrollableElements = elements; - } - /** * long calcucation are not very efficient in GWT, so this helper method * returns timestamp in double. -- cgit v1.2.3 From ff05bab8e8d21a9fa13295f05e5cd1f9fbe60bda Mon Sep 17 00:00:00 2001 From: Johannes Dahlström Date: Mon, 7 May 2012 13:24:18 +0000 Subject: #8722 Make subwindows touch scrollable svn changeset:23688/svn branch:6.8 --- src/com/vaadin/terminal/gwt/client/ui/VWindow.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/com/vaadin/terminal/gwt/client/ui/VWindow.java b/src/com/vaadin/terminal/gwt/client/ui/VWindow.java index 2355a9c65a..d756eaf8b0 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VWindow.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VWindow.java @@ -205,6 +205,9 @@ public class VWindow extends VOverlay implements Container, contentPanel.addKeyDownHandler(this); contentPanel.addFocusHandler(this); contentPanel.addBlurHandler(this); + + TouchScrollDelegate.enableTouchScrolling(this, getContainerElement() + .getFirstChildElement()); } public void bringToFront() { -- cgit v1.2.3 From 8cfb84d9ec1570f7b14890edadebdf43a474be8c Mon Sep 17 00:00:00 2001 From: Automerge Date: Tue, 8 May 2012 09:06:50 +0000 Subject: [merge from 6.7] Don't activate tab when clicking close element (#7686) svn changeset:23690/svn branch:6.8 --- .../vaadin/terminal/gwt/client/ui/VTabsheet.java | 13 +++++++- .../tabsheet/TabSheetWithDisappearingContent.html | 36 ++++++++++++++++++++++ .../tabsheet/TabSheetWithDisappearingContent.java | 34 ++++++++++++++++++++ 3 files changed, 82 insertions(+), 1 deletion(-) create mode 100644 tests/testbench/com/vaadin/tests/components/tabsheet/TabSheetWithDisappearingContent.html create mode 100644 tests/testbench/com/vaadin/tests/components/tabsheet/TabSheetWithDisappearingContent.java diff --git a/src/com/vaadin/terminal/gwt/client/ui/VTabsheet.java b/src/com/vaadin/terminal/gwt/client/ui/VTabsheet.java index f1a5b31379..d3836bb177 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VTabsheet.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VTabsheet.java @@ -350,6 +350,10 @@ public class VTabsheet extends VTabsheetBase implements Focusable, } return width; } + public Element getCloseButton() { + return closeButton; + } + } static class TabBar extends ComplexPanel implements ClickHandler, @@ -412,7 +416,14 @@ public class VTabsheet extends VTabsheetBase implements Focusable, } public void onClick(ClickEvent event) { - Widget caption = (Widget) event.getSource(); + TabCaption caption = (TabCaption) event.getSource(); + Element targetElement = event.getNativeEvent().getEventTarget() + .cast(); + // the tab should not be focused if the close button was clicked + if (targetElement == caption.getCloseButton()) { + return; + } + int index = getWidgetIndex(caption.getParent()); // IE needs explicit focus() if (BrowserInfo.get().isIE()) { diff --git a/tests/testbench/com/vaadin/tests/components/tabsheet/TabSheetWithDisappearingContent.html b/tests/testbench/com/vaadin/tests/components/tabsheet/TabSheetWithDisappearingContent.html new file mode 100644 index 0000000000..b01a4a16ae --- /dev/null +++ b/tests/testbench/com/vaadin/tests/components/tabsheet/TabSheetWithDisappearingContent.html @@ -0,0 +1,36 @@ + + + + + + +TabSheetWithDisappearingContent + + + + + + + + + + + + + + + + + + + + + + + + + + +
TabSheetWithDisappearingContent
open/run/com.vaadin.tests.components.tabsheet.TabSheetWithDisappearingContent?restartApplication
mouseClickvaadin=runcomvaadintestscomponentstabsheetTabSheetWithDisappearingContent::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VTabsheet[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]/domChild[2]/domChild[0]/domChild[0]/domChild[1]14,7
assertTextvaadin=runcomvaadintestscomponentstabsheetTabSheetWithDisappearingContent::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VTabsheet[0]/VTabsheetPanel[0]/VVerticalLayout[0]/ChildComponentContainer[0]/VLabel[0]Content 1
assertVisiblevaadin=runcomvaadintestscomponentstabsheetTabSheetWithDisappearingContent::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VTabsheet[0]/VTabsheetPanel[0]/VVerticalLayout[0]/ChildComponentContainer[0]/VLabel[0]
+ + diff --git a/tests/testbench/com/vaadin/tests/components/tabsheet/TabSheetWithDisappearingContent.java b/tests/testbench/com/vaadin/tests/components/tabsheet/TabSheetWithDisappearingContent.java new file mode 100644 index 0000000000..aed273dd64 --- /dev/null +++ b/tests/testbench/com/vaadin/tests/components/tabsheet/TabSheetWithDisappearingContent.java @@ -0,0 +1,34 @@ +package com.vaadin.tests.components.tabsheet; + +import com.vaadin.tests.components.TestBase; +import com.vaadin.ui.Label; +import com.vaadin.ui.TabSheet; +import com.vaadin.ui.TabSheet.Tab; +import com.vaadin.ui.VerticalLayout; + +public class TabSheetWithDisappearingContent extends TestBase { + + @Override + protected void setup() { + final TabSheet t = new TabSheet(); + + for (int i = 1; i < 4; i++) { + VerticalLayout v = new VerticalLayout(); + v.addComponent(new Label("Content " + i)); + Tab tab = t.addTab(v, "Tab " + i); + tab.setClosable(true); + } + addComponent(t); + } + + @Override + protected String getDescription() { + return "In some browsers, when trying to close the last tab of a tabsheet an IndexOutOfBoundException happens. After that, although an other tab is visually active, no contents are shown."; + } + + @Override + protected Integer getTicketNumber() { + return 7686; + } + +} -- cgit v1.2.3 From af19523dd55e1a81acabade6b8ade096ffa7d785 Mon Sep 17 00:00:00 2001 From: Automerge Date: Wed, 9 May 2012 09:07:00 +0000 Subject: [merge from 6.7] Test case for #8778 svn changeset:23696/svn branch:6.8 --- .../application/TerminalErrorNotification.html | 36 ++++++++++++++ .../application/TerminalErrorNotification.java | 57 ++++++++++++++++++++++ 2 files changed, 93 insertions(+) create mode 100644 tests/testbench/com/vaadin/tests/application/TerminalErrorNotification.html create mode 100644 tests/testbench/com/vaadin/tests/application/TerminalErrorNotification.java diff --git a/tests/testbench/com/vaadin/tests/application/TerminalErrorNotification.html b/tests/testbench/com/vaadin/tests/application/TerminalErrorNotification.html new file mode 100644 index 0000000000..f20967c8de --- /dev/null +++ b/tests/testbench/com/vaadin/tests/application/TerminalErrorNotification.html @@ -0,0 +1,36 @@ + + + + + + +TabSheetWithDisappearingContent + + + + + + + + + + + + + + + + + + + + + + + + + + +
TabSheetWithDisappearingContent
open/run/com.vaadin.tests.application.TerminalErrorNotification?restartApplication&debug
clickvaadin=runcomvaadintestsapplicationTerminalErrorNotification::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VButton[0]/domChild[0]/domChild[0]
assertElementPresentvaadin=runcomvaadintestsapplicationTerminalErrorNotification::Root/VNotification[0]
assertTextvaadin=runcomvaadintestsapplicationTerminalErrorNotification::Root/VNotification[0]/HTML[0]/domChild[0]Got an exception: You asked for it
+ + diff --git a/tests/testbench/com/vaadin/tests/application/TerminalErrorNotification.java b/tests/testbench/com/vaadin/tests/application/TerminalErrorNotification.java new file mode 100644 index 0000000000..93e38bac5b --- /dev/null +++ b/tests/testbench/com/vaadin/tests/application/TerminalErrorNotification.java @@ -0,0 +1,57 @@ +/* +@VaadinApache2LicenseForJavaFiles@ + */ +package com.vaadin.tests.application; + +import com.vaadin.tests.components.TestBase; +import com.vaadin.ui.Button; +import com.vaadin.ui.Button.ClickEvent; +import com.vaadin.ui.Window; +import com.vaadin.ui.Window.Notification; + +public class TerminalErrorNotification extends TestBase { + + @Override + protected void setup() { + Button button = new Button("Throw exception", + new Button.ClickListener() { + public void buttonClick(ClickEvent event) { + throw new RuntimeException("You asked for it"); + } + }); + + addComponent(button); + } + + @Override + public void terminalError(com.vaadin.terminal.Terminal.ErrorEvent event) { + event.getThrowable().printStackTrace(); + + Window mainWindow = getMainWindow(); + if (mainWindow != null) { + Throwable throwable = event.getThrowable(); + + // Find the root cause + while (throwable.getCause() != null) { + throwable = throwable.getCause(); + } + + mainWindow.showNotification( + "Got an exception: " + throwable.getMessage(), + Notification.TYPE_ERROR_MESSAGE); + } else { + System.out.println("No main window found"); + } + } + + @Override + protected String getDescription() { + return "Showing a notification in the terminalError method should make the notification appear in the browser."; + } + + @Override + protected Integer getTicketNumber() { + return Integer.valueOf(8778); + } + +} -- cgit v1.2.3 From 2f9e56f46e59152d9bed498eb72586fb3f9e15dd Mon Sep 17 00:00:00 2001 From: Johannes Dahlström Date: Wed, 9 May 2012 11:44:20 +0000 Subject: TouchScrollHandler: added debug info, restored setElements() svn changeset:23697/svn branch:6.8 --- .../gwt/client/ui/TouchScrollDelegate.java | 29 ++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/src/com/vaadin/terminal/gwt/client/ui/TouchScrollDelegate.java b/src/com/vaadin/terminal/gwt/client/ui/TouchScrollDelegate.java index 65d8029593..580313f433 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/TouchScrollDelegate.java +++ b/src/com/vaadin/terminal/gwt/client/ui/TouchScrollDelegate.java @@ -98,11 +98,20 @@ public class TouchScrollDelegate implements NativePreviewHandler { public TouchScrollHandler(Widget widget, Element... scrollables) { if (requiresDelegate) { + VConsole.log("REQUIRES DELEGATE"); delegate = new TouchScrollDelegate(); widget.addDomHandler(this, TouchStartEvent.getType()); } else { + VConsole.log("DOES NOT REQUIRE DELEGATE"); delegate = null; } + VConsole.log(BrowserInfo.getBrowserString()); + BrowserInfo bi = BrowserInfo.get(); + VConsole.log("Is Android: " + bi.isAndroid()); + VConsole.log("Is Android with broken scrolltop: " + + bi.isAndroidWithBrokenScrollTop()); + VConsole.log("Is IOS: " + bi.isIOS()); + VConsole.log("Is Webkit: " + bi.isWebkit()); for (Element scrollable : scrollables) { addElement(scrollable); } @@ -113,11 +122,22 @@ public class TouchScrollDelegate implements NativePreviewHandler { delegate.onTouchStart(event); } + public void debug(Element e) { + VConsole.log("Classes: " + e.getClassName() + " overflow: " + + e.getStyle().getProperty("overflow") + " w-o-s: " + + e.getStyle().getProperty("-webkit-overflow-scrolling")); + } + public void addElement(Element scrollable) { scrollable.addClassName("v-scrollable"); + scrollable.getStyle().setProperty("-webkit-overflow-scrolling", + "touch"); + scrollable.getStyle().setProperty("overflow-y", "auto"); + scrollable.getStyle().setProperty("overflow-x", "hidden"); if (requiresDelegate) { delegate.scrollableElements.add(scrollable); } + VConsole.log("Added scrollable: " + scrollable.getClassName()); } public void removeElement(Element scrollable) { @@ -126,6 +146,15 @@ public class TouchScrollDelegate implements NativePreviewHandler { delegate.scrollableElements.remove(scrollable); } } + + public void setElements(Element... scrollables) { + if (requiresDelegate) { + delegate.scrollableElements.clear(); + } + for (Element e : scrollables) { + addElement(e); + } + } } public static TouchScrollHandler enableTouchScrolling(Widget widget, -- cgit v1.2.3 From 0bcee7fad275880d2acf5ed4cca34ace42c7481b Mon Sep 17 00:00:00 2001 From: Automerge Date: Wed, 9 May 2012 17:06:15 +0000 Subject: [merge from 6.7] Test case for #8781 svn changeset:23699/svn branch:6.8 --- WebContent/statictestfiles/dummy.zip | Bin 0 -> 138 bytes .../tests/components/window/DownloadAndUpdate.java | 45 +++++++++++++++++++++ 2 files changed, 45 insertions(+) create mode 100644 WebContent/statictestfiles/dummy.zip create mode 100644 tests/testbench/com/vaadin/tests/components/window/DownloadAndUpdate.java diff --git a/WebContent/statictestfiles/dummy.zip b/WebContent/statictestfiles/dummy.zip new file mode 100644 index 0000000000..e6e34282fe Binary files /dev/null and b/WebContent/statictestfiles/dummy.zip differ diff --git a/tests/testbench/com/vaadin/tests/components/window/DownloadAndUpdate.java b/tests/testbench/com/vaadin/tests/components/window/DownloadAndUpdate.java new file mode 100644 index 0000000000..ca9c31513f --- /dev/null +++ b/tests/testbench/com/vaadin/tests/components/window/DownloadAndUpdate.java @@ -0,0 +1,45 @@ +package com.vaadin.tests.components.window; + +import com.vaadin.terminal.ExternalResource; +import com.vaadin.tests.components.TestBase; +import com.vaadin.ui.Button; +import com.vaadin.ui.Button.ClickEvent; +import com.vaadin.ui.Table; + +public class DownloadAndUpdate extends TestBase { + + @Override + protected void setup() { + addComponent(new Button("Download and update", + new Button.ClickListener() { + public void buttonClick(ClickEvent event) { + downloadAndUpdate(); + } + })); + } + + protected void downloadAndUpdate() { + getMainWindow().open( + new ExternalResource("/statictestfiles/dummy.zip", "_new")); + + // Any component sending an UIDL request when rendered will likely do + Table table = new Table(); + table.addContainerProperty("A", String.class, ""); + for (int i = 0; i < 100; i++) { + table.addItem(new Object[] { Integer.toString(i) }, + Integer.valueOf(i)); + } + addComponent(table); + } + + @Override + protected String getDescription() { + return "There should be no problems downloading a file from the same request that triggers another request, even in webkit browsers."; + } + + @Override + protected Integer getTicketNumber() { + return Integer.valueOf(8781); + } + +} -- cgit v1.2.3 From d53b654e2539a4c0728aba77b77efa01aa4a2c7d Mon Sep 17 00:00:00 2001 From: Leif Åstrand Date: Thu, 10 May 2012 08:33:27 +0000 Subject: Use   in empty table footers to make them render properly (#7718) svn changeset:23701/svn branch:6.8 --- src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java b/src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java index a022a2bd83..f0874a5d18 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java @@ -3425,6 +3425,10 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler, * The text in the footer */ public void setText(String footerText) { + if (footerText == null || footerText.equals("")) { + footerText = " "; + } + DOM.setInnerHTML(captionContainer, footerText); } -- cgit v1.2.3 From f6bfd75b703aa199d2ef7e956d5ec7422a507d85 Mon Sep 17 00:00:00 2001 From: Automerge Date: Thu, 10 May 2012 09:10:01 +0000 Subject: [merge from 6.7] Send VView size instead of window size (#7931) svn changeset:23703/svn branch:6.8 --- src/com/vaadin/terminal/gwt/client/ui/VView.java | 33 +++++++++++++++--------- 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/src/com/vaadin/terminal/gwt/client/ui/VView.java b/src/com/vaadin/terminal/gwt/client/ui/VView.java index c03652f259..8f8a6ab4b3 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VView.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VView.java @@ -61,11 +61,12 @@ public class VView extends SimplePanel implements Container, ResizeHandler, private ShortcutActionHandler actionHandler; - /** stored width for IE resize optimization */ - private int width; + /** stored size for IE resize optimization */ + private int windowWidth; + private int windowHeight; - /** stored height for IE resize optimization */ - private int height; + private int viewWidth; + private int viewHeight; private ApplicationConnection connection; @@ -134,15 +135,15 @@ public class VView extends SimplePanel implements Container, ResizeHandler, */ protected void windowSizeMaybeChanged(int newWidth, int newHeight) { boolean changed = false; - if (width != newWidth) { - width = newWidth; + if (windowWidth != newWidth) { + windowWidth = newWidth; changed = true; - VConsole.log("New window width: " + width); + VConsole.log("New window width: " + windowWidth); } - if (height != newHeight) { - height = newHeight; + if (windowHeight != newHeight) { + windowHeight = newHeight; changed = true; - VConsole.log("New window height: " + height); + VConsole.log("New window height: " + windowHeight); } if (changed) { VConsole.log("Running layout functions due to window resize"); @@ -492,8 +493,16 @@ public class VView extends SimplePanel implements Container, ResizeHandler, * Send new dimensions to the server. */ private void sendClientResized() { - connection.updateVariable(id, "height", height, false); - connection.updateVariable(id, "width", width, immediate); + int newViewHeight = getElement().getClientHeight(); + int newViewWidth = getElement().getClientWidth(); + + // Send the view dimensions if they have changed + if (newViewHeight != viewHeight || newViewWidth != viewWidth) { + viewHeight = newViewHeight; + viewWidth = newViewWidth; + connection.updateVariable(id, "height", newViewHeight, false); + connection.updateVariable(id, "width", newViewWidth, immediate); + } } public native static void goTo(String url) -- cgit v1.2.3 From c8a4ca73ac23373683cab03cb8aa46ca5ea6fa7c Mon Sep 17 00:00:00 2001 From: Automerge Date: Thu, 10 May 2012 13:07:21 +0000 Subject: [merge from 6.7] Tweaks to #7931 based on review. svn changeset:23708/svn branch:6.8 --- src/com/vaadin/terminal/gwt/client/ui/VView.java | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/src/com/vaadin/terminal/gwt/client/ui/VView.java b/src/com/vaadin/terminal/gwt/client/ui/VView.java index 8f8a6ab4b3..d500c56e52 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VView.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VView.java @@ -61,10 +61,18 @@ public class VView extends SimplePanel implements Container, ResizeHandler, private ShortcutActionHandler actionHandler; - /** stored size for IE resize optimization */ + /* + * Last known window size used to detect whether VView should be layouted + * again. Detection must be based on window size, because the VView size + * might be fixed and thus not automatically adapt to changed window sizes. + */ private int windowWidth; private int windowHeight; + /* + * Last know view size used to detect whether new dimensions should be sent + * to the server. + */ private int viewWidth; private int viewHeight; @@ -146,6 +154,13 @@ public class VView extends SimplePanel implements Container, ResizeHandler, VConsole.log("New window height: " + windowHeight); } if (changed) { + /* + * If the window size has changed, layout the VView again and send + * new size to the server if the size changed. (Just checking VView + * size would cause us to ignore cases when a relatively sized VView + * should shrink as the content's size is fixed and would thus not + * automatically shrink.) + */ VConsole.log("Running layout functions due to window resize"); connection.runDescendentsLayout(VView.this); Util.runWebkitOverflowAutoFix(getElement()); @@ -493,8 +508,9 @@ public class VView extends SimplePanel implements Container, ResizeHandler, * Send new dimensions to the server. */ private void sendClientResized() { - int newViewHeight = getElement().getClientHeight(); - int newViewWidth = getElement().getClientWidth(); + Element parentElement = getElement().getParentElement(); + int newViewHeight = parentElement.getClientHeight(); + int newViewWidth = parentElement.getClientWidth(); // Send the view dimensions if they have changed if (newViewHeight != viewHeight || newViewWidth != viewWidth) { -- cgit v1.2.3 From 33371699c7d3984c199e3d9ccbda3aedf883102e Mon Sep 17 00:00:00 2001 From: Automerge Date: Thu, 10 May 2012 17:06:37 +0000 Subject: [merge from 6.7] Increase granularity of some assertions to better detect exactly where the random issue in Safari occurs. svn changeset:23710/svn branch:6.8 --- .../treetable/TreeTableCacheOnPartialUpdate.html | 25 +++++++++++++--------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/tests/testbench/com/vaadin/tests/components/treetable/TreeTableCacheOnPartialUpdate.html b/tests/testbench/com/vaadin/tests/components/treetable/TreeTableCacheOnPartialUpdate.html index b22d77a94c..340d3bead5 100644 --- a/tests/testbench/com/vaadin/tests/components/treetable/TreeTableCacheOnPartialUpdate.html +++ b/tests/testbench/com/vaadin/tests/components/treetable/TreeTableCacheOnPartialUpdate.html @@ -287,30 +287,35 @@ vaadin=runcomvaadintestscomponentstreetableTreeTableCacheOnPartialUpdates::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[3]/VTreeTable[0]/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[34]/domChild[0]/domChild[0]/domChild[0] 9,-998 + + assertText + vaadin=runcomvaadintestscomponentstreetableTreeTableCacheOnPartialUpdates::PID_SLog_row_0 + 25. Row Item TestBean [col1=40 (children), col2=AN] collapsed. Row index: 39 + mouseClick vaadin=runcomvaadintestscomponentstreetableTreeTableCacheOnPartialUpdates::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[3]/VTreeTable[0]/FocusableScrollPanel[0]/VTreeTable$VTreeTableScrollBody[0]/VTreeTable$VTreeTableScrollBody$VTreeTableRow[34]/VNativeButton[0] 42,-990 - mouseClick - vaadin=runcomvaadintestscomponentstreetableTreeTableCacheOnPartialUpdates::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[3]/VTreeTable[0]/FocusableScrollPanel[0]/VTreeTable$VTreeTableScrollBody[0]/VTreeTable$VTreeTableScrollBody$VTreeTableRow[29]/VNativeButton[0] - 84,-990 + assertText + vaadin=runcomvaadintestscomponentstreetableTreeTableCacheOnPartialUpdates::PID_SLog_row_0 + 26. Button Item TestBean [col1=40 (children), col2=AN]/col3 clicked. Row index: 39 mouseClick - vaadin=runcomvaadintestscomponentstreetableTreeTableCacheOnPartialUpdates::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[3]/VTreeTable[0]/FocusableScrollPanel[0]/VTreeTable$VTreeTableScrollBody[0]/VTreeTable$VTreeTableScrollBody$VTreeTableRow[42]/VNativeButton[0] - 98,-998 + vaadin=runcomvaadintestscomponentstreetableTreeTableCacheOnPartialUpdates::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[3]/VTreeTable[0]/FocusableScrollPanel[0]/VTreeTable$VTreeTableScrollBody[0]/VTreeTable$VTreeTableScrollBody$VTreeTableRow[29]/VNativeButton[0] + 84,-990 assertText - vaadin=runcomvaadintestscomponentstreetableTreeTableCacheOnPartialUpdates::PID_SLog_row_2 - 26. Button Item TestBean [col1=40 (children), col2=AN]/col3 clicked. Row index: 39 + vaadin=runcomvaadintestscomponentstreetableTreeTableCacheOnPartialUpdates::PID_SLog_row_0 + 27. Button Item TestBean [col1=35, col2=AI]/col3 clicked. Row index: 34 - assertText - vaadin=runcomvaadintestscomponentstreetableTreeTableCacheOnPartialUpdates::PID_SLog_row_1 - 27. Button Item TestBean [col1=35, col2=AI]/col3 clicked. Row index: 34 + mouseClick + vaadin=runcomvaadintestscomponentstreetableTreeTableCacheOnPartialUpdates::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[3]/VTreeTable[0]/FocusableScrollPanel[0]/VTreeTable$VTreeTableScrollBody[0]/VTreeTable$VTreeTableScrollBody$VTreeTableRow[42]/VNativeButton[0] + 98,-998 assertText -- cgit v1.2.3 From 0c403456cadcae75575f56fc69002893faed07f6 Mon Sep 17 00:00:00 2001 From: Automerge Date: Fri, 11 May 2012 09:06:57 +0000 Subject: [merge from 6.7] Further increase granularity of some assertions to better detect exactly where the random issue in Safari occurs. svn changeset:23713/svn branch:6.8 --- .../treetable/TreeTableCacheOnPartialUpdate.html | 40 +++++++++++----------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/tests/testbench/com/vaadin/tests/components/treetable/TreeTableCacheOnPartialUpdate.html b/tests/testbench/com/vaadin/tests/components/treetable/TreeTableCacheOnPartialUpdate.html index 340d3bead5..ac20598ccd 100644 --- a/tests/testbench/com/vaadin/tests/components/treetable/TreeTableCacheOnPartialUpdate.html +++ b/tests/testbench/com/vaadin/tests/components/treetable/TreeTableCacheOnPartialUpdate.html @@ -238,44 +238,44 @@ 9,-995 - mouseClick - vaadin=runcomvaadintestscomponentstreetableTreeTableCacheOnPartialUpdates::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[3]/VTreeTable[0]/FocusableScrollPanel[0]/VTreeTable$VTreeTableScrollBody[0]/VTreeTable$VTreeTableScrollBody$VTreeTableRow[34]/VNativeButton[0] - 93,-991 + assertText + vaadin=runcomvaadintestscomponentstreetableTreeTableCacheOnPartialUpdates::PID_SLog_row_0 + 20. Row Item TestBean [col1=40 (children), col2=AN] expanded. Row index: 39 mouseClick - vaadin=runcomvaadintestscomponentstreetableTreeTableCacheOnPartialUpdates::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[3]/VTreeTable[0]/FocusableScrollPanel[0]/VTreeTable$VTreeTableScrollBody[0]/VTreeTable$VTreeTableScrollBody$VTreeTableRow[35]/VNativeButton[0] - 123,-991 + vaadin=runcomvaadintestscomponentstreetableTreeTableCacheOnPartialUpdates::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[3]/VTreeTable[0]/FocusableScrollPanel[0]/VTreeTable$VTreeTableScrollBody[0]/VTreeTable$VTreeTableScrollBody$VTreeTableRow[34]/VNativeButton[0] + 93,-991 - mouseClick - vaadin=runcomvaadintestscomponentstreetableTreeTableCacheOnPartialUpdates::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[3]/VTreeTable[0]/FocusableScrollPanel[0]/VTreeTable$VTreeTableScrollBody[0]/VTreeTable$VTreeTableScrollBody$VTreeTableRow[44]/VNativeButton[0] - 114,-1000 + assertText + vaadin=runcomvaadintestscomponentstreetableTreeTableCacheOnPartialUpdates::PID_SLog_row_0 + 21. Button Item TestBean [col1=40 (children), col2=AN]/col3 clicked. Row index: 39 mouseClick - vaadin=runcomvaadintestscomponentstreetableTreeTableCacheOnPartialUpdates::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[3]/VTreeTable[0]/FocusableScrollPanel[0]/VTreeTable$VTreeTableScrollBody[0]/VTreeTable$VTreeTableScrollBody$VTreeTableRow[34]/VNativeButton[0] - 118,-993 + vaadin=runcomvaadintestscomponentstreetableTreeTableCacheOnPartialUpdates::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[3]/VTreeTable[0]/FocusableScrollPanel[0]/VTreeTable$VTreeTableScrollBody[0]/VTreeTable$VTreeTableScrollBody$VTreeTableRow[35]/VNativeButton[0] + 123,-991 assertText - vaadin=runcomvaadintestscomponentstreetableTreeTableCacheOnPartialUpdates::PID_SLog_row_4 - 20. Row Item TestBean [col1=40 (children), col2=AN] expanded. Row index: 39 + vaadin=runcomvaadintestscomponentstreetableTreeTableCacheOnPartialUpdates::PID_SLog_row_0 + 22. Button Item TestBean [col1=40.1, col2=AN.A]/col3 clicked. Row index: 40 - assertText - vaadin=runcomvaadintestscomponentstreetableTreeTableCacheOnPartialUpdates::PID_SLog_row_3 - 21. Button Item TestBean [col1=40 (children), col2=AN]/col3 clicked. Row index: 39 + mouseClick + vaadin=runcomvaadintestscomponentstreetableTreeTableCacheOnPartialUpdates::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[3]/VTreeTable[0]/FocusableScrollPanel[0]/VTreeTable$VTreeTableScrollBody[0]/VTreeTable$VTreeTableScrollBody$VTreeTableRow[44]/VNativeButton[0] + 114,-1000 assertText - vaadin=runcomvaadintestscomponentstreetableTreeTableCacheOnPartialUpdates::PID_SLog_row_2 - 22. Button Item TestBean [col1=40.1, col2=AN.A]/col3 clicked. Row index: 40 + vaadin=runcomvaadintestscomponentstreetableTreeTableCacheOnPartialUpdates::PID_SLog_row_0 + 23. Button Item TestBean [col1=40.10, col2=AN.J]/col3 clicked. Row index: 49 - assertText - vaadin=runcomvaadintestscomponentstreetableTreeTableCacheOnPartialUpdates::PID_SLog_row_1 - 23. Button Item TestBean [col1=40.10, col2=AN.J]/col3 clicked. Row index: 49 + mouseClick + vaadin=runcomvaadintestscomponentstreetableTreeTableCacheOnPartialUpdates::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[3]/VTreeTable[0]/FocusableScrollPanel[0]/VTreeTable$VTreeTableScrollBody[0]/VTreeTable$VTreeTableScrollBody$VTreeTableRow[34]/VNativeButton[0] + 118,-993 assertText -- cgit v1.2.3 From 8383bddc03cc07bd0ae682af182784ca3415d505 Mon Sep 17 00:00:00 2001 From: Johannes Dahlström Date: Fri, 11 May 2012 10:56:06 +0000 Subject: camelCasify CSS property names svn changeset:23715/svn branch:6.8 --- src/com/vaadin/terminal/gwt/client/ui/TouchScrollDelegate.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/com/vaadin/terminal/gwt/client/ui/TouchScrollDelegate.java b/src/com/vaadin/terminal/gwt/client/ui/TouchScrollDelegate.java index 580313f433..171ec2838d 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/TouchScrollDelegate.java +++ b/src/com/vaadin/terminal/gwt/client/ui/TouchScrollDelegate.java @@ -125,15 +125,15 @@ public class TouchScrollDelegate implements NativePreviewHandler { public void debug(Element e) { VConsole.log("Classes: " + e.getClassName() + " overflow: " + e.getStyle().getProperty("overflow") + " w-o-s: " - + e.getStyle().getProperty("-webkit-overflow-scrolling")); + + e.getStyle().getProperty("WebkitOverflowScrolling")); } public void addElement(Element scrollable) { scrollable.addClassName("v-scrollable"); - scrollable.getStyle().setProperty("-webkit-overflow-scrolling", + scrollable.getStyle().setProperty("WebkitOverflowScrolling", "touch"); - scrollable.getStyle().setProperty("overflow-y", "auto"); - scrollable.getStyle().setProperty("overflow-x", "hidden"); + scrollable.getStyle().setProperty("overflowY", "auto"); + scrollable.getStyle().setProperty("overflowX", "auto"); if (requiresDelegate) { delegate.scrollableElements.add(scrollable); } -- cgit v1.2.3 From bb486ff26ad6f43197aba42d5af53508bf2c5235 Mon Sep 17 00:00:00 2001 From: Johannes Dahlström Date: Fri, 11 May 2012 12:42:04 +0000 Subject: #8723 Add touch scrolling support to Accordion svn changeset:23716/svn branch:6.8 --- .../vaadin/terminal/gwt/client/ui/VAccordion.java | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/src/com/vaadin/terminal/gwt/client/ui/VAccordion.java b/src/com/vaadin/terminal/gwt/client/ui/VAccordion.java index 4d0776a5f9..73d7eba2d6 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VAccordion.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VAccordion.java @@ -24,6 +24,7 @@ import com.vaadin.terminal.gwt.client.RenderSpace; import com.vaadin.terminal.gwt.client.UIDL; import com.vaadin.terminal.gwt.client.Util; import com.vaadin.terminal.gwt.client.VCaption; +import com.vaadin.terminal.gwt.client.ui.TouchScrollDelegate.TouchScrollHandler; public class VAccordion extends VTabsheetBase implements ContainerResizedListener { @@ -48,12 +49,16 @@ public class VAccordion extends VTabsheetBase implements private RenderInformation renderInformation = new RenderInformation(); + private final TouchScrollHandler touchScrollHandler; + public VAccordion() { super(CLASSNAME); // IE6 needs this to calculate offsetHeight correctly if (BrowserInfo.get().isIE6()) { DOM.setStyleAttribute(getElement(), "zoom", "1"); } + + touchScrollHandler = TouchScrollDelegate.enableTouchScrolling(this); } @Override @@ -198,7 +203,6 @@ public class VAccordion extends VTabsheetBase implements } } } - if (!alreadyOpen) { item.open(); activeTabIndex = itemIndex; @@ -442,11 +446,15 @@ public class VAccordion extends VTabsheetBase implements DOM.appendChild(captionNode, caption.getElement()); DOM.appendChild(getElement(), captionNode); DOM.appendChild(getElement(), content); - setStyleName(CLASSNAME + "-item"); - DOM.setElementProperty(content, "className", CLASSNAME - + "-item-content"); - DOM.setElementProperty(captionNode, "className", CLASSNAME - + "-item-caption"); + + getElement().addClassName(CLASSNAME + "-item"); + captionNode.addClassName(CLASSNAME + "-item-caption"); + content.addClassName(CLASSNAME + "-item-content"); + + touchScrollHandler.addElement(getContainerElement()); + + sinkEvents(Event.TOUCHEVENTS | Event.MOUSEEVENTS); + close(); } @@ -640,6 +648,8 @@ public class VAccordion extends VTabsheetBase implements protected void removeTab(int index) { StackItem item = getStackItem(index); remove(item); + + touchScrollHandler.addElement(item.getContainerElement()); } @Override -- cgit v1.2.3 From 239aad4885931b6e7913ca4c86409b7b6997642f Mon Sep 17 00:00:00 2001 From: Johannes Dahlström Date: Fri, 11 May 2012 14:04:26 +0000 Subject: #8763 Removed overflow: auto from v-panel-content, v-accordion-item-content, and v-view classes; use v-scrollable class in elements that should scroll instead svn changeset:23718/svn branch:6.8 --- WebContent/VAADIN/themes/base/accordion/accordion.css | 1 - WebContent/VAADIN/themes/base/common/common.css | 1 - WebContent/VAADIN/themes/base/panel/panel.css | 1 - 3 files changed, 3 deletions(-) diff --git a/WebContent/VAADIN/themes/base/accordion/accordion.css b/WebContent/VAADIN/themes/base/accordion/accordion.css index 10c205ae24..ad762ee0ac 100644 --- a/WebContent/VAADIN/themes/base/accordion/accordion.css +++ b/WebContent/VAADIN/themes/base/accordion/accordion.css @@ -22,6 +22,5 @@ } .v-accordion-item-content { position: absolute; - overflow: auto; width: 100%; } \ No newline at end of file diff --git a/WebContent/VAADIN/themes/base/common/common.css b/WebContent/VAADIN/themes/base/common/common.css index adf84ac3b7..f0b0f8e7be 100644 --- a/WebContent/VAADIN/themes/base/common/common.css +++ b/WebContent/VAADIN/themes/base/common/common.css @@ -29,7 +29,6 @@ div.v-app-loading { .v-view { height: 100%; width: 100%; - overflow: auto; /* avoid scrollbars with margins in root layout */ outline: none; margin-top: -1px; diff --git a/WebContent/VAADIN/themes/base/panel/panel.css b/WebContent/VAADIN/themes/base/panel/panel.css index 126d3da91c..74d7b67a35 100644 --- a/WebContent/VAADIN/themes/base/panel/panel.css +++ b/WebContent/VAADIN/themes/base/panel/panel.css @@ -29,7 +29,6 @@ overflow: hidden; } .v-panel-content { - overflow: auto; } .v-panel-deco { } \ No newline at end of file -- cgit v1.2.3 From f560e8e20bdcc8035d17c494d31d961d440a60c2 Mon Sep 17 00:00:00 2001 From: Johannes Dahlström Date: Fri, 11 May 2012 14:26:52 +0000 Subject: #8725 Use TouchScrollDelegate.enableTouchScrolling() instead of TouchScrollDelegate instance directly; rewrite CSS class handling a bit to prevent overwriting v-scrollable svn changeset:23719/svn branch:6.8 --- .../vaadin/terminal/gwt/client/ui/VSplitPanel.java | 72 +++++++--------------- 1 file changed, 23 insertions(+), 49 deletions(-) diff --git a/src/com/vaadin/terminal/gwt/client/ui/VSplitPanel.java b/src/com/vaadin/terminal/gwt/client/ui/VSplitPanel.java index 51e378cc0c..173bd02151 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VSplitPanel.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VSplitPanel.java @@ -122,7 +122,7 @@ public class VSplitPanel extends ComplexPanel implements Container, private boolean positionReversed = false; - private String[] componentStyleNames; + private String[] componentStyleNames = new String[0]; private Element draggingCurtain; @@ -150,8 +150,6 @@ public class VSplitPanel extends ComplexPanel implements Container, protected int origScrollTop; - private TouchScrollDelegate touchScrollDelegate; - public VSplitPanel() { this(ORIENTATION_HORIZONTAL); } @@ -175,6 +173,9 @@ public class VSplitPanel extends ComplexPanel implements Container, setOrientation(orientation); sinkEvents(Event.MOUSEEVENTS); + TouchScrollDelegate.enableTouchScrolling(this, firstContainer, + secondContainer); + addDomHandler(new TouchCancelHandler() { public void onTouchCancel(TouchCancelEvent event) { // TODO When does this actually happen?? @@ -186,11 +187,8 @@ public class VSplitPanel extends ComplexPanel implements Container, Node target = event.getTouches().get(0).getTarget().cast(); if (splitter.isOrHasChild(target)) { onMouseDown(Event.as(event.getNativeEvent())); - } else { - getTouchScrollDelegate().onTouchStart(event); } } - }, TouchStartEvent.getType()); addDomHandler(new TouchMoveHandler() { public void onTouchMove(TouchMoveEvent event) { @@ -209,14 +207,6 @@ public class VSplitPanel extends ComplexPanel implements Container, } - private TouchScrollDelegate getTouchScrollDelegate() { - if (touchScrollDelegate == null) { - touchScrollDelegate = new TouchScrollDelegate(firstContainer, - secondContainer); - } - return touchScrollDelegate; - } - protected void constructDom() { DOM.appendChild(splitter, DOM.createDiv()); // for styling DOM.appendChild(getElement(), wrapper); @@ -231,9 +221,7 @@ public class VSplitPanel extends ComplexPanel implements Container, DOM.setStyleAttribute(splitter, "position", "absolute"); DOM.setStyleAttribute(secondContainer, "position", "absolute"); - DOM.setStyleAttribute(firstContainer, "overflow", "auto"); - DOM.setStyleAttribute(secondContainer, "overflow", "auto"); - + setStylenames(); } private void setOrientation(int orientation) { @@ -249,11 +237,6 @@ public class VSplitPanel extends ComplexPanel implements Container, DOM.setStyleAttribute(firstContainer, "width", "100%"); DOM.setStyleAttribute(secondContainer, "width", "100%"); } - - DOM.setElementProperty(firstContainer, "className", CLASSNAME - + "-first-container"); - DOM.setElementProperty(secondContainer, "className", CLASSNAME - + "-second-container"); } public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { @@ -320,7 +303,6 @@ public class VSplitPanel extends ComplexPanel implements Container, client.runDescendentsLayout(this); rendering = false; - } @Override @@ -475,7 +457,6 @@ public class VSplitPanel extends ComplexPanel implements Container, // fixes scrollbars issues on webkit based browsers Util.runWebkitOverflowAutoFix(secondContainer); Util.runWebkitOverflowAutoFix(firstContainer); - } private void setFirstWidget(Widget w) { @@ -815,31 +796,24 @@ public class VSplitPanel extends ComplexPanel implements Container, } private void setStylenames() { - final String splitterSuffix = (orientation == ORIENTATION_HORIZONTAL ? "-hsplitter" - : "-vsplitter"); - final String firstContainerSuffix = "-first-container"; - final String secondContainerSuffix = "-second-container"; - String lockedSuffix = ""; - - String splitterStyle = CLASSNAME + splitterSuffix; - String firstStyle = CLASSNAME + firstContainerSuffix; - String secondStyle = CLASSNAME + secondContainerSuffix; - - if (locked) { - splitterStyle = CLASSNAME + splitterSuffix + "-locked"; - lockedSuffix = "-locked"; - } - for (int i = 0; i < componentStyleNames.length; i++) { - splitterStyle += " " + CLASSNAME + splitterSuffix + "-" - + componentStyleNames[i] + lockedSuffix; - firstStyle += " " + CLASSNAME + firstContainerSuffix + "-" - + componentStyleNames[i]; - secondStyle += " " + CLASSNAME + secondContainerSuffix + "-" - + componentStyleNames[i]; - } - DOM.setElementProperty(splitter, "className", splitterStyle); - DOM.setElementProperty(firstContainer, "className", firstStyle); - DOM.setElementProperty(secondContainer, "className", secondStyle); + final String splitterClass = CLASSNAME + + (orientation == ORIENTATION_HORIZONTAL ? "-hsplitter" + : "-vsplitter"); + final String firstContainerClass = CLASSNAME + "-first-container"; + final String secondContainerClass = CLASSNAME + "-second-container"; + final String lockedSuffix = locked ? "-locked" : ""; + + splitter.addClassName(splitterClass); + firstContainer.addClassName(firstContainerClass); + secondContainer.addClassName(secondContainerClass); + + for (String styleName : componentStyleNames) { + splitter.addClassName(splitterClass + "-" + styleName + + lockedSuffix); + firstContainer.addClassName(firstContainerClass + "-" + styleName); + secondContainer + .addClassName(secondContainerClass + "-" + styleName); + } } public void setEnabled(boolean enabled) { -- cgit v1.2.3 From 16c9142f252110d732fd74a3f0d8cd82217d8b33 Mon Sep 17 00:00:00 2001 From: Johannes Dahlström Date: Fri, 11 May 2012 14:29:48 +0000 Subject: #8723 Oops, call removeElement(), not addElement(), in removeTab() svn changeset:23720/svn branch:6.8 --- src/com/vaadin/terminal/gwt/client/ui/VAccordion.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/com/vaadin/terminal/gwt/client/ui/VAccordion.java b/src/com/vaadin/terminal/gwt/client/ui/VAccordion.java index 73d7eba2d6..1b089af931 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VAccordion.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VAccordion.java @@ -648,8 +648,7 @@ public class VAccordion extends VTabsheetBase implements protected void removeTab(int index) { StackItem item = getStackItem(index); remove(item); - - touchScrollHandler.addElement(item.getContainerElement()); + touchScrollHandler.removeElement(item.getContainerElement()); } @Override -- cgit v1.2.3 From b50dcc33d6dcf16d562953ae21c194b1f3775d02 Mon Sep 17 00:00:00 2001 From: Johannes Dahlström Date: Fri, 11 May 2012 15:08:46 +0000 Subject: #8720 Improve handling of tab container scrolling svn changeset:23721/svn branch:6.8 --- src/com/vaadin/terminal/gwt/client/ui/VTabsheetPanel.java | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/com/vaadin/terminal/gwt/client/ui/VTabsheetPanel.java b/src/com/vaadin/terminal/gwt/client/ui/VTabsheetPanel.java index f1dbea18b2..d8ab30a1e1 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VTabsheetPanel.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VTabsheetPanel.java @@ -6,7 +6,6 @@ package com.vaadin.terminal.gwt.client.ui; 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.ui.ComplexPanel; import com.google.gwt.user.client.ui.Widget; import com.vaadin.terminal.gwt.client.Util; @@ -25,15 +24,13 @@ public class VTabsheetPanel extends ComplexPanel { private Widget visibleWidget; - private TouchScrollHandler touchScrollHandler; + private final TouchScrollHandler touchScrollHandler; /** * Creates an empty tabsheet panel. */ public VTabsheetPanel() { setElement(DOM.createDiv()); - sinkEvents(Event.TOUCHEVENTS); - touchScrollHandler = TouchScrollDelegate.enableTouchScrolling(this); } @@ -54,6 +51,7 @@ public class VTabsheetPanel extends ComplexPanel { Element el = DOM.createDiv(); DOM.setStyleAttribute(el, "position", "absolute"); hide(el); + touchScrollHandler.addElement(el); return el; } @@ -97,6 +95,7 @@ public class VTabsheetPanel extends ComplexPanel { if (parent != null) { DOM.removeChild(getElement(), parent); } + touchScrollHandler.removeElement(parent); } return removed; } @@ -117,8 +116,6 @@ public class VTabsheetPanel extends ComplexPanel { } visibleWidget = newVisible; unHide(DOM.getParent(visibleWidget.getElement())); - touchScrollHandler.setElements(visibleWidget.getElement() - .getParentElement()); } } -- cgit v1.2.3 From 95e0de3166a1cfcf832ab708e5449ffce48cefed Mon Sep 17 00:00:00 2001 From: Johannes Dahlström Date: Fri, 11 May 2012 15:09:50 +0000 Subject: #8721 Make VView touch scrollable svn changeset:23722/svn branch:6.8 --- src/com/vaadin/terminal/gwt/client/ui/VView.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/com/vaadin/terminal/gwt/client/ui/VView.java b/src/com/vaadin/terminal/gwt/client/ui/VView.java index d500c56e52..597d40cf29 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VView.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VView.java @@ -131,6 +131,7 @@ public class VView extends SimplePanel implements Container, ResizeHandler, // Allow focusing the view by using the focus() method, the view // should not be in the document focus flow getElement().setTabIndex(-1); + TouchScrollDelegate.enableTouchScrolling(this, getElement()); } /** -- cgit v1.2.3 From 716de2f65ea070ffc2335b07af6fa793b4a948f9 Mon Sep 17 00:00:00 2001 From: Johannes Dahlström Date: Fri, 11 May 2012 15:31:16 +0000 Subject: #8722 Move handling of scrolling from VWindow to FocusableScrollPanel svn changeset:23723/svn branch:6.8 --- src/com/vaadin/terminal/gwt/client/ui/FocusableScrollPanel.java | 5 +++-- src/com/vaadin/terminal/gwt/client/ui/VWindow.java | 3 --- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/com/vaadin/terminal/gwt/client/ui/FocusableScrollPanel.java b/src/com/vaadin/terminal/gwt/client/ui/FocusableScrollPanel.java index 460c474e66..60f58fb37e 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/FocusableScrollPanel.java +++ b/src/com/vaadin/terminal/gwt/client/ui/FocusableScrollPanel.java @@ -34,8 +34,8 @@ public class FocusableScrollPanel extends SimpleFocusablePanel implements public FocusableScrollPanel() { // Prevent IE standard mode bug when a AbsolutePanel is contained. + TouchScrollDelegate.enableTouchScrolling(this, getElement()); Style style = getElement().getStyle(); - style.setOverflow(Overflow.AUTO); style.setProperty("zoom", "1"); style.setPosition(Position.RELATIVE); } @@ -162,7 +162,8 @@ public class FocusableScrollPanel extends SimpleFocusablePanel implements * the new vertical scroll position, in pixels */ public void setScrollPosition(int position) { - if (BrowserInfo.get().isAndroidWithBrokenScrollTop()) { + if (BrowserInfo.get().isAndroidWithBrokenScrollTop() + && BrowserInfo.get().requiresTouchScrollDelegate()) { ArrayList elements = TouchScrollDelegate .getElements(getElement()); for (com.google.gwt.dom.client.Element el : elements) { diff --git a/src/com/vaadin/terminal/gwt/client/ui/VWindow.java b/src/com/vaadin/terminal/gwt/client/ui/VWindow.java index d756eaf8b0..2355a9c65a 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VWindow.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VWindow.java @@ -205,9 +205,6 @@ public class VWindow extends VOverlay implements Container, contentPanel.addKeyDownHandler(this); contentPanel.addFocusHandler(this); contentPanel.addBlurHandler(this); - - TouchScrollDelegate.enableTouchScrolling(this, getContainerElement() - .getFirstChildElement()); } public void bringToFront() { -- cgit v1.2.3 From ac20081a91417ad45c6770ffdac6f4c1ae903058 Mon Sep 17 00:00:00 2001 From: Johannes Dahlström Date: Fri, 11 May 2012 15:38:58 +0000 Subject: #8724 Preliminary native touch scroll support for Table svn changeset:23724/svn branch:6.8 --- .../terminal/gwt/client/ui/VScrollTable.java | 214 +++++++++++++++++++-- 1 file changed, 194 insertions(+), 20 deletions(-) diff --git a/src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java b/src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java index f0874a5d18..0ab200ccf4 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java @@ -44,8 +44,6 @@ import com.google.gwt.event.dom.client.KeyUpEvent; import com.google.gwt.event.dom.client.KeyUpHandler; import com.google.gwt.event.dom.client.ScrollEvent; import com.google.gwt.event.dom.client.ScrollHandler; -import com.google.gwt.event.dom.client.TouchStartEvent; -import com.google.gwt.event.dom.client.TouchStartHandler; import com.google.gwt.event.logical.shared.CloseEvent; import com.google.gwt.event.logical.shared.CloseHandler; import com.google.gwt.user.client.Command; @@ -212,6 +210,9 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler, private boolean enableDebug = false; + private final static boolean requiresTouchScrollDelegate = BrowserInfo + .get().requiresTouchScrollDelegate(); + /** * Represents a select range of rows */ @@ -467,12 +468,12 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler, public VScrollTable() { setMultiSelectMode(MULTISELECT_MODE_DEFAULT); - scrollBodyPanel.setStyleName(CLASSNAME + "-body-wrapper"); + scrollBodyPanel.addStyleName(CLASSNAME + "-body-wrapper"); scrollBodyPanel.addFocusHandler(this); scrollBodyPanel.addBlurHandler(this); scrollBodyPanel.addScrollHandler(this); - scrollBodyPanel.setStyleName(CLASSNAME + "-body"); + scrollBodyPanel.addStyleName(CLASSNAME + "-body"); /* * Firefox auto-repeat works correctly only if we use a key press @@ -487,11 +488,6 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler, scrollBodyPanel.addKeyUpHandler(navKeyUpHandler); scrollBodyPanel.sinkEvents(Event.TOUCHEVENTS); - scrollBodyPanel.addDomHandler(new TouchStartHandler() { - public void onTouchStart(TouchStartEvent event) { - getTouchScrollDelegate().onTouchStart(event); - } - }, TouchStartEvent.getType()); scrollBodyPanel.sinkEvents(Event.ONCONTEXTMENU); scrollBodyPanel.addDomHandler(new ContextMenuHandler() { @@ -509,16 +505,6 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler, rowRequestHandler = new RowRequestHandler(); } - protected TouchScrollDelegate getTouchScrollDelegate() { - if (touchScrollDelegate == null) { - touchScrollDelegate = new TouchScrollDelegate( - scrollBodyPanel.getElement()); - touchScrollDelegate.setScrollHandler(this); - } - return touchScrollDelegate; - - } - private void handleBodyContextMenu(ContextMenuEvent event) { if (enabled && bodyActionKeys != null) { int left = Util.getTouchOrMouseClientX(event.getNativeEvent()); @@ -4068,7 +4054,7 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler, DOM.appendChild(container, preSpacer); DOM.appendChild(container, table); DOM.appendChild(container, postSpacer); - if (BrowserInfo.get().isTouchDevice()) { + if (BrowserInfo.get().requiresTouchScrollDelegate()) { NodeList childNodes = container.getChildNodes(); for (int i = 0; i < childNodes.getLength(); i++) { Element item = (Element) childNodes.getItem(i); @@ -4638,6 +4624,7 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler, + "-row-odd"; private static final int TOUCH_CONTEXT_MENU_TIMEOUT = 500; private Timer contextTouchTimeout; + private Timer dragTouchTimeout; private int touchStartY; private int touchStartX; @@ -5050,11 +5037,198 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler, } } + private boolean wasSignificantMove = false; + private boolean isDragging = false; + + /** + * Special handler for touch devices + * + * @param event + */ + public void onTouchBrowserEvent(final Event event) { + VConsole.log("-- START ONTOUCHBROWSEREVENT"); + if (enabled) { + final Element targetTdOrTr = getEventTargetTdOrTr(event); + final int type = event.getTypeInt(); + + switch (type) { + case Event.ONCONTEXTMENU: + showContextMenu(event); + if (enabled + && (actionKeys != null || client + .hasEventListeners(VScrollTable.this, + ITEM_CLICK_EVENT_ID))) { + /* + * Prevent browser context menu only if there are + * action handlers or item click listeners + * registered + */ + event.stopPropagation(); + event.preventDefault(); + } + break; + case Event.ONTOUCHSTART: + touchStart = event; + isDragging = false; + wasSignificantMove = false; + Touch touch = event.getChangedTouches().get(0); + // save position to fields, touches in events are same + // instance during the operation. + touchStartX = touch.getClientX(); + touchStartY = touch.getClientY(); + + if (dragmode != 0) { + if (dragTouchTimeout == null) { + dragTouchTimeout = new Timer() { + @Override + public void run() { + if (touchStart != null) { + VConsole.log("DRAGGING"); + isDragging = true; + } + } + }; + VConsole.log("START DRAG TIMEOUT"); + dragTouchTimeout.schedule(TOUCHSCROLL_TIMEOUT); + } + } + + if (actionKeys != null) { + if (contextTouchTimeout == null) { + contextTouchTimeout = new Timer() { + @Override + public void run() { + if (touchStart != null) { + VConsole.log("SHOW CONTEXT"); + showContextMenu(touchStart); + event.preventDefault(); + touchStart = null; + + } + } + }; + VConsole.log("START CONTEXT TIMEOUT"); + + contextTouchTimeout.cancel(); + contextTouchTimeout + .schedule(TOUCH_CONTEXT_MENU_TIMEOUT); + } + } + break; + case Event.ONTOUCHMOVE: + if (isSignificantMove(event)) { + wasSignificantMove = true; + if (contextTouchTimeout != null) { + contextTouchTimeout.cancel(); + } + if (!isDragging && dragTouchTimeout != null) { + VConsole.log("CANCEL DRAG TIMEOUT"); + dragTouchTimeout.cancel(); + dragTouchTimeout = null; + } + if (isDragging) { + if (dragmode != 0 && touchStart != null) { + event.preventDefault(); + event.stopPropagation(); + VConsole.log("START DRAG"); + startRowDrag(touchStart, type, targetTdOrTr); + } + isDragging = false; + } + touchStart = null; + } + break; + case Event.ONTOUCHEND: + case Event.ONTOUCHCANCEL: + VConsole.log("ONTOUCHEND"); + if (contextTouchTimeout != null) { + VConsole.log("CANCEL CONTEXT TIMEOUT"); + contextTouchTimeout.cancel(); + } + if (dragTouchTimeout != null) { + VConsole.log("CANCEL DRAG TIMEOUT"); + dragTouchTimeout.cancel(); + } + if (touchStart != null) { + event.preventDefault(); + event.stopPropagation(); + touchStart = null; + } + isDragging = false; + VConsole.log("END ONTOUCHEND"); + break; + case Event.ONMOUSEDOWN: + VConsole.log("ONMOUSEDOWN"); + if (targetTdOrTr != null) { + setRowFocus(this); + ensureFocus(); + if (dragmode != 0 + && (event.getButton() == NativeEvent.BUTTON_LEFT)) { + startRowDrag(event, event.getTypeInt(), + targetTdOrTr); + } else { + event.stopPropagation(); + } + + event.preventDefault(); + } + break; + case Event.ONMOUSEOUT: + VConsole.log("ONMOUSEOUT"); + break; + case Event.ONMOUSEUP: + VConsole.log("ONMOUSEUP"); + if (targetTdOrTr != null) { + if (isSelectable()) { + boolean currentlyJustThisRowSelected = selectedRowKeys + .size() == 1 + && selectedRowKeys.contains(getKey()); + + if (!currentlyJustThisRowSelected) { + if (isSingleSelectMode() + || isMultiSelectModeDefault()) { + deselectAll(); + } + toggleSelection(); + } else if ((isSingleSelectMode() || isMultiSelectModeSimple()) + && nullSelectionAllowed) { + toggleSelection(); + } + + selectionRangeStart = this; + setRowFocus(this); + + event.preventDefault(); + event.stopPropagation(); + } + } + + break; + case Event.ONDBLCLICK: + if (targetTdOrTr != null) { + handleClickEvent(event, targetTdOrTr, true); + } + break; + default: + } + } + VConsole.log("-- SUPER ONBROWSEREVENT"); + + super.onBrowserEvent(event); + VConsole.log("-- END ONTOUCHBROWSEREVENT"); + } + /* * React on click that occur on content cells only */ @Override public void onBrowserEvent(final Event event) { + + if (!requiresTouchScrollDelegate) { + onTouchBrowserEvent(event); + return; + } + if (enabled) { final int type = event.getTypeInt(); final Element targetTdOrTr = getEventTargetTdOrTr(event); -- cgit v1.2.3 From 3826313b3485dc944e2ab40867936331374fa93d Mon Sep 17 00:00:00 2001 From: Johannes Dahlström Date: Mon, 14 May 2012 08:57:13 +0000 Subject: #8716 Rewrite some CSS classname handling code to prevent overwriting v-scrollable svn changeset:23728/svn branch:6.8 --- src/com/vaadin/terminal/gwt/client/ui/VPanel.java | 55 ++++++++++------------- 1 file changed, 23 insertions(+), 32 deletions(-) diff --git a/src/com/vaadin/terminal/gwt/client/ui/VPanel.java b/src/com/vaadin/terminal/gwt/client/ui/VPanel.java index f754addcf3..1b5c48283b 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VPanel.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VPanel.java @@ -8,6 +8,7 @@ import java.util.Set; import com.google.gwt.dom.client.DivElement; import com.google.gwt.dom.client.Document; +import com.google.gwt.dom.client.Style; import com.google.gwt.event.dom.client.DomEvent.Type; import com.google.gwt.event.shared.EventHandler; import com.google.gwt.event.shared.HandlerRegistration; @@ -159,44 +160,33 @@ public class VPanel extends SimplePanel implements Container, if (!uidl.hasAttribute("cached")) { // Handle caption displaying and style names, prior generics. - // Affects size - // calculations + // Affects size calculations + + final boolean hasCaption = uidl.hasAttribute("caption") + && !uidl.getStringAttribute("caption").equals(""); + + setCaption(hasCaption ? uidl.getStringAttribute("caption") : ""); // Restore default stylenames - contentNode.setClassName(CLASSNAME + "-content"); - bottomDecoration.setClassName(CLASSNAME + "-deco"); - captionNode.setClassName(CLASSNAME + "-caption"); - boolean hasCaption = false; - if (uidl.hasAttribute("caption") - && !uidl.getStringAttribute("caption").equals("")) { - setCaption(uidl.getStringAttribute("caption")); - hasCaption = true; - } else { - setCaption(""); - captionNode.setClassName(CLASSNAME + "-nocaption"); - } + final String captionBaseClass = CLASSNAME + + (hasCaption ? "-caption" : "-nocaption"); + final String contentBaseClass = CLASSNAME + "-content"; + final String decoBaseClass = CLASSNAME + "-deco"; + + captionNode.addClassName(captionBaseClass); + contentNode.addClassName(contentBaseClass); + bottomDecoration.addClassName(decoBaseClass); // Add proper stylenames for all elements. This way we can prevent // unwanted CSS selector inheritance. if (uidl.hasAttribute("style")) { final String[] styles = uidl.getStringAttribute("style").split( " "); - final String captionBaseClass = CLASSNAME - + (hasCaption ? "-caption" : "-nocaption"); - final String contentBaseClass = CLASSNAME + "-content"; - final String decoBaseClass = CLASSNAME + "-deco"; - String captionClass = captionBaseClass; - String contentClass = contentBaseClass; - String decoClass = decoBaseClass; - for (int i = 0; i < styles.length; i++) { - captionClass += " " + captionBaseClass + "-" + styles[i]; - contentClass += " " + contentBaseClass + "-" + styles[i]; - decoClass += " " + decoBaseClass + "-" + styles[i]; + for (String style : styles) { + captionNode.addClassName(captionBaseClass + "-" + style); + contentNode.addClassName(contentBaseClass + "-" + style); + bottomDecoration.addClassName(decoBaseClass + "-" + style); } - captionNode.setClassName(captionClass); - contentNode.setClassName(contentClass); - bottomDecoration.setClassName(decoClass); - } } // Ensure correct implementation @@ -509,12 +499,13 @@ public class VPanel extends SimplePanel implements Container, } private void detectContainerBorders() { - DOM.setStyleAttribute(contentNode, "overflow", "hidden"); + Style contentStyle = contentNode.getStyle(); + String overflow = contentStyle.getProperty("overflow"); + contentStyle.setProperty("overflow", "hidden"); borderPaddingHorizontal = Util.measureHorizontalBorder(contentNode); borderPaddingVertical = Util.measureVerticalBorder(contentNode); - - DOM.setStyleAttribute(contentNode, "overflow", "auto"); + contentStyle.setProperty("overflow", overflow); captionPaddingHorizontal = Util.measureHorizontalPaddingAndBorder( captionNode, 26); -- cgit v1.2.3 From 321b403c95ce067db25b67b91c531a5e082c38eb Mon Sep 17 00:00:00 2001 From: Automerge Date: Mon, 14 May 2012 09:11:31 +0000 Subject: [merge from 6.7] #5521 portlet body should fill portlet content e.g. in Liferay freeform layout, related manual test application svn changeset:23729/svn branch:6.8 --- src/com/vaadin/terminal/gwt/client/ui/VView.java | 38 +++++++++++++++++++++- ...tletSizeInLiferayFreeformLayoutApplication.java | 30 +++++++++++++++++ 2 files changed, 67 insertions(+), 1 deletion(-) create mode 100644 tests/testbench/com/vaadin/tests/integration/PortletSizeInLiferayFreeformLayoutApplication.java diff --git a/src/com/vaadin/terminal/gwt/client/ui/VView.java b/src/com/vaadin/terminal/gwt/client/ui/VView.java index 597d40cf29..abebf0ea4a 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VView.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VView.java @@ -318,8 +318,15 @@ public class VView extends SimplePanel implements Container, ResizeHandler, layout = lo; } + boolean childLayoutCached = childUidl.getBooleanAttribute("cached"); + + if (!childLayoutCached) { + // Liferay #5521: update portlet-body element size + updateLiferayPortletBodySize(childUidl); + } + layout.updateFromUIDL(childUidl, client); - if (!childUidl.getBooleanAttribute("cached")) { + if (!childLayoutCached) { updateParentFrameSize(); } @@ -420,6 +427,35 @@ public class VView extends SimplePanel implements Container, ResizeHandler, rendering = false; } + private void updateLiferayPortletBodySize(UIDL childUidl) { + // Liferay #5521: update portlet-body element size + Element parentOfVApp = getElement().getParentElement() + .getParentElement(); + if (parentOfVApp != null + && parentOfVApp.getClassName().contains("portlet-body")) { + // portlet-body needs to get size 100% if e.g. in a freeform + // layout or otherwise in a situation where the application + // layout size is specified as a percentage + for (String direction : new String[] { "height", "width" }) { + if (childUidl.hasAttribute(direction) + && childUidl.getStringAttribute(direction) + .contains("%")) { + // if layout has a percentual size, set portlet body size + // as percentual + if ("".equals(parentOfVApp.getStyle() + .getProperty(direction))) { + parentOfVApp.getStyle().setProperty(direction, "100%"); + } + } else if (parentOfVApp.getStyle().getHeight().contains("%")) { + // if layout size is undefined or fixed and we have set a + // percentual size for portlet-body, remove size setting on + // portlet body + parentOfVApp.getStyle().setProperty(direction, ""); + } + } + } + } + /** * Tries to scroll paintable referenced from given UIDL snippet to be * visible. diff --git a/tests/testbench/com/vaadin/tests/integration/PortletSizeInLiferayFreeformLayoutApplication.java b/tests/testbench/com/vaadin/tests/integration/PortletSizeInLiferayFreeformLayoutApplication.java new file mode 100644 index 0000000000..1687bd588a --- /dev/null +++ b/tests/testbench/com/vaadin/tests/integration/PortletSizeInLiferayFreeformLayoutApplication.java @@ -0,0 +1,30 @@ +package com.vaadin.tests.integration; + +import com.vaadin.Application; +import com.vaadin.ui.Label; +import com.vaadin.ui.VerticalLayout; +import com.vaadin.ui.Window; + +/** + * On Liferay in a freeform layout, this application should get its height from + * the height of the portlet container in the Liferay layout. + * + * See ticket #5521. + */ +public class PortletSizeInLiferayFreeformLayoutApplication extends Application { + @Override + public void init() { + Window mainWindow = new Window("Portlet5521 Application"); + ((VerticalLayout) mainWindow.getContent()).setMargin(false); + ((VerticalLayout) mainWindow.getContent()).setSizeFull(); + // ((VerticalLayout) mainWindow.getContent()).setHeight("200px"); + Label label = new Label("Hello Vaadin user"); + mainWindow.addComponent(label); + for (int i = 0; i < 50; ++i) { + mainWindow.addComponent(new Label("Label " + i)); + } + mainWindow.setSizeFull(); + setMainWindow(mainWindow); + } + +} -- cgit v1.2.3 From 9ae6ce60f0965a17886b532d52de6ecdc42a173e Mon Sep 17 00:00:00 2001 From: Johannes Dahlström Date: Mon, 14 May 2012 09:19:52 +0000 Subject: #8763 Disable native touch scrolling on iOS 5 devices until #8792 is resolved svn changeset:23730/svn branch:6.8 --- src/com/vaadin/terminal/gwt/client/BrowserInfo.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/com/vaadin/terminal/gwt/client/BrowserInfo.java b/src/com/vaadin/terminal/gwt/client/BrowserInfo.java index 5e496bd05d..c8caab6829 100644 --- a/src/com/vaadin/terminal/gwt/client/BrowserInfo.java +++ b/src/com/vaadin/terminal/gwt/client/BrowserInfo.java @@ -448,9 +448,10 @@ public class BrowserInfo { if (isAndroid() && isWebkit() && getWebkitVersion() >= 534) { return false; } - if (isIOS() && isWebkit() && getWebkitVersion() >= 534) { - return false; - } + // Cannot enable native touch scrolling on iOS 5 until #8792 is resolved + // if (isIOS() && isWebkit() && getWebkitVersion() >= 534) { + // return false; + // } return true; } -- cgit v1.2.3 From 22652ba707768ab4955f1632d0d98d1f35fe6256 Mon Sep 17 00:00:00 2001 From: Johannes Dahlström Date: Mon, 14 May 2012 09:57:39 +0000 Subject: #8763 Removed debug messages, added Javadoc to TouchScrollHandler svn changeset:23731/svn branch:6.8 --- .../gwt/client/ui/TouchScrollDelegate.java | 61 ++++++++++++++++------ 1 file changed, 45 insertions(+), 16 deletions(-) diff --git a/src/com/vaadin/terminal/gwt/client/ui/TouchScrollDelegate.java b/src/com/vaadin/terminal/gwt/client/ui/TouchScrollDelegate.java index 171ec2838d..4e19f66b14 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/TouchScrollDelegate.java +++ b/src/com/vaadin/terminal/gwt/client/ui/TouchScrollDelegate.java @@ -90,28 +90,34 @@ public class TouchScrollDelegate implements NativePreviewHandler { private static final boolean androidWithBrokenScrollTop = BrowserInfo.get() .isAndroidWithBrokenScrollTop(); + /** + * A helper class for making a widget scrollable. Uses native scrolling if + * supported by the browser, otherwise registers a touch start handler + * delegating to a TouchScrollDelegate instance. + */ public static class TouchScrollHandler implements TouchStartHandler { + private static final String SCROLLABLE_CLASSNAME = "v-scrollable"; + private final TouchScrollDelegate delegate; private final boolean requiresDelegate = BrowserInfo.get() .requiresTouchScrollDelegate(); + /** + * Constructs a scroll handler for the given widget. + * + * @param widget + * The widget that contains scrollable elements + * @param scrollables + * The elements of the widget that should be scrollable. + */ public TouchScrollHandler(Widget widget, Element... scrollables) { if (requiresDelegate) { - VConsole.log("REQUIRES DELEGATE"); delegate = new TouchScrollDelegate(); widget.addDomHandler(this, TouchStartEvent.getType()); } else { - VConsole.log("DOES NOT REQUIRE DELEGATE"); delegate = null; } - VConsole.log(BrowserInfo.getBrowserString()); - BrowserInfo bi = BrowserInfo.get(); - VConsole.log("Is Android: " + bi.isAndroid()); - VConsole.log("Is Android with broken scrolltop: " - + bi.isAndroidWithBrokenScrollTop()); - VConsole.log("Is IOS: " + bi.isIOS()); - VConsole.log("Is Webkit: " + bi.isWebkit()); for (Element scrollable : scrollables) { addElement(scrollable); } @@ -128,27 +134,40 @@ public class TouchScrollDelegate implements NativePreviewHandler { + e.getStyle().getProperty("WebkitOverflowScrolling")); } + /** + * Registers the given element as scrollable. + */ public void addElement(Element scrollable) { - scrollable.addClassName("v-scrollable"); - scrollable.getStyle().setProperty("WebkitOverflowScrolling", - "touch"); - scrollable.getStyle().setProperty("overflowY", "auto"); - scrollable.getStyle().setProperty("overflowX", "auto"); + scrollable.addClassName(SCROLLABLE_CLASSNAME); if (requiresDelegate) { delegate.scrollableElements.add(scrollable); } - VConsole.log("Added scrollable: " + scrollable.getClassName()); } + /** + * Unregisters the given element as scrollable. Should be called when a + * previously-registered element is removed from the DOM to prevent + * memory leaks. + */ public void removeElement(Element scrollable) { - scrollable.removeClassName("v-scrollable"); + scrollable.removeClassName(SCROLLABLE_CLASSNAME); if (requiresDelegate) { delegate.scrollableElements.remove(scrollable); } } + /** + * Registers the given elements as scrollable, removing previously + * registered scrollables from this handler. + * + * @param scrollables + * The elements that should be scrollable + */ public void setElements(Element... scrollables) { if (requiresDelegate) { + for (Element e : delegate.scrollableElements) { + e.removeClassName(SCROLLABLE_CLASSNAME); + } delegate.scrollableElements.clear(); } for (Element e : scrollables) { @@ -157,6 +176,16 @@ public class TouchScrollDelegate implements NativePreviewHandler { } } + /** + * Makes the given elements scrollable, either natively or by using a + * TouchScrollDelegate, depending on platform capabilities. + * + * @param widget + * The widget that contains scrollable elements + * @param scrollables + * The elements inside the widget that should be scrollable + * @return A scroll handler for the given widget. + */ public static TouchScrollHandler enableTouchScrolling(Widget widget, Element... scrollables) { return new TouchScrollHandler(widget, scrollables); -- cgit v1.2.3 From c03c497eeb4f1f368e36ee2dfa72d33ef4b22a23 Mon Sep 17 00:00:00 2001 From: Johannes Dahlström Date: Mon, 14 May 2012 10:32:48 +0000 Subject: #8724 Erroneously called onTouchBrowserEvent with non-touch platforms svn changeset:23732/svn branch:6.8 --- src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java b/src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java index 0ab200ccf4..bcd66c13f8 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java @@ -210,8 +210,9 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler, private boolean enableDebug = false; - private final static boolean requiresTouchScrollDelegate = BrowserInfo - .get().requiresTouchScrollDelegate(); + private static final boolean hasNativeTouchScrolling = BrowserInfo.get() + .isTouchDevice() + && !BrowserInfo.get().requiresTouchScrollDelegate(); /** * Represents a select range of rows @@ -5224,7 +5225,7 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler, @Override public void onBrowserEvent(final Event event) { - if (!requiresTouchScrollDelegate) { + if (hasNativeTouchScrolling) { onTouchBrowserEvent(event); return; } -- cgit v1.2.3 From 0ec34926cc165bba52fd52526f2b99bba6b9d603 Mon Sep 17 00:00:00 2001 From: Johannes Dahlström Date: Mon, 14 May 2012 11:50:40 +0000 Subject: #8723 Do not sink touch events in Accordion svn changeset:23733/svn branch:6.8 --- src/com/vaadin/terminal/gwt/client/ui/VAccordion.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/com/vaadin/terminal/gwt/client/ui/VAccordion.java b/src/com/vaadin/terminal/gwt/client/ui/VAccordion.java index 1b089af931..4ff70d1668 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VAccordion.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VAccordion.java @@ -453,7 +453,7 @@ public class VAccordion extends VTabsheetBase implements touchScrollHandler.addElement(getContainerElement()); - sinkEvents(Event.TOUCHEVENTS | Event.MOUSEEVENTS); + sinkEvents(Event.MOUSEEVENTS); close(); } -- cgit v1.2.3 From 8b064167bbf42f1e0788e854bd7450a87fc480a2 Mon Sep 17 00:00:00 2001 From: Johannes Dahlström Date: Tue, 15 May 2012 07:48:46 +0000 Subject: #8716 #8725 Fix regressions introduced by CSS class handling changes svn changeset:23736/svn branch:6.8 --- src/com/vaadin/terminal/gwt/client/ui/VPanel.java | 15 +++++++++++---- src/com/vaadin/terminal/gwt/client/ui/VSplitPanel.java | 16 +++++++++++----- 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/src/com/vaadin/terminal/gwt/client/ui/VPanel.java b/src/com/vaadin/terminal/gwt/client/ui/VPanel.java index 1b5c48283b..56bc779fbc 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VPanel.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VPanel.java @@ -27,6 +27,7 @@ import com.vaadin.terminal.gwt.client.RenderSpace; import com.vaadin.terminal.gwt.client.UIDL; import com.vaadin.terminal.gwt.client.Util; import com.vaadin.terminal.gwt.client.ui.ShortcutActionHandler.ShortcutActionHandlerOwner; +import com.vaadin.terminal.gwt.client.ui.TouchScrollDelegate.TouchScrollHandler; public class VPanel extends SimplePanel implements Container, ShortcutActionHandlerOwner, Focusable { @@ -80,6 +81,8 @@ public class VPanel extends SimplePanel implements Container, private String previousStyleName; + private final TouchScrollHandler touchScrollHandler; + private ClickEventHandler clickEventHandler = new ClickEventHandler(this, CLICK_EVENT_IDENTIFIER) { @@ -119,7 +122,8 @@ public class VPanel extends SimplePanel implements Container, contentNode.getStyle().setProperty("position", "relative"); getElement().getStyle().setProperty("overflow", "hidden"); - TouchScrollDelegate.enableTouchScrolling(this, contentNode); + touchScrollHandler = TouchScrollDelegate.enableTouchScrolling(this, + contentNode); } /** @@ -173,9 +177,9 @@ public class VPanel extends SimplePanel implements Container, final String contentBaseClass = CLASSNAME + "-content"; final String decoBaseClass = CLASSNAME + "-deco"; - captionNode.addClassName(captionBaseClass); - contentNode.addClassName(contentBaseClass); - bottomDecoration.addClassName(decoBaseClass); + captionNode.setClassName(captionBaseClass); + contentNode.setClassName(contentBaseClass); + bottomDecoration.setClassName(decoBaseClass); // Add proper stylenames for all elements. This way we can prevent // unwanted CSS selector inheritance. @@ -188,6 +192,9 @@ public class VPanel extends SimplePanel implements Container, bottomDecoration.addClassName(decoBaseClass + "-" + style); } } + + // Ensure panel is still scrollable + touchScrollHandler.addElement(contentNode); } // Ensure correct implementation if (client.updateComponent(this, uidl, false)) { diff --git a/src/com/vaadin/terminal/gwt/client/ui/VSplitPanel.java b/src/com/vaadin/terminal/gwt/client/ui/VSplitPanel.java index 173bd02151..5a996954a0 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VSplitPanel.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VSplitPanel.java @@ -36,6 +36,7 @@ import com.vaadin.terminal.gwt.client.RenderSpace; 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.ui.TouchScrollDelegate.TouchScrollHandler; public class VSplitPanel extends ComplexPanel implements Container, ContainerResizedListener { @@ -146,6 +147,8 @@ public class VSplitPanel extends ComplexPanel implements Container, /* The current position of the split handle in either percentages or pixels */ private String position; + private final TouchScrollHandler touchScrollHandler; + protected Element scrolledContainer; protected int origScrollTop; @@ -173,8 +176,8 @@ public class VSplitPanel extends ComplexPanel implements Container, setOrientation(orientation); sinkEvents(Event.MOUSEEVENTS); - TouchScrollDelegate.enableTouchScrolling(this, firstContainer, - secondContainer); + touchScrollHandler = TouchScrollDelegate.enableTouchScrolling(this, + firstContainer, secondContainer); addDomHandler(new TouchCancelHandler() { public void onTouchCancel(TouchCancelEvent event) { @@ -265,6 +268,9 @@ public class VSplitPanel extends ComplexPanel implements Container, setStylenames(); + // Ensure panels are still scrollable + touchScrollHandler.setElements(firstContainer, secondContainer); + position = uidl.getStringAttribute("position"); setSplitPosition(position); @@ -803,9 +809,9 @@ public class VSplitPanel extends ComplexPanel implements Container, final String secondContainerClass = CLASSNAME + "-second-container"; final String lockedSuffix = locked ? "-locked" : ""; - splitter.addClassName(splitterClass); - firstContainer.addClassName(firstContainerClass); - secondContainer.addClassName(secondContainerClass); + splitter.setClassName(splitterClass + lockedSuffix); + firstContainer.setClassName(firstContainerClass); + secondContainer.setClassName(secondContainerClass); for (String styleName : componentStyleNames) { splitter.addClassName(splitterClass + "-" + styleName -- cgit v1.2.3 From a21464620881742f28b233864bf8c35f74728ad0 Mon Sep 17 00:00:00 2001 From: Johannes Dahlström Date: Tue, 15 May 2012 08:14:45 +0000 Subject: #8763 Re-added TouchScrollDelegate#setElements() svn changeset:23737/svn branch:6.8 --- src/com/vaadin/terminal/gwt/client/ui/TouchScrollDelegate.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/com/vaadin/terminal/gwt/client/ui/TouchScrollDelegate.java b/src/com/vaadin/terminal/gwt/client/ui/TouchScrollDelegate.java index 4e19f66b14..7302f9f2ac 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/TouchScrollDelegate.java +++ b/src/com/vaadin/terminal/gwt/client/ui/TouchScrollDelegate.java @@ -118,9 +118,7 @@ public class TouchScrollDelegate implements NativePreviewHandler { } else { delegate = null; } - for (Element scrollable : scrollables) { - addElement(scrollable); - } + setElements(scrollables); } public void onTouchStart(TouchStartEvent event) { @@ -192,7 +190,7 @@ public class TouchScrollDelegate implements NativePreviewHandler { } public TouchScrollDelegate(Element... elements) { - scrollableElements = new HashSet(Arrays.asList(elements)); + setElements(elements); } public void setScrollHandler(ScrollHandler scrollHandler) { @@ -640,6 +638,10 @@ public class TouchScrollDelegate implements NativePreviewHandler { } } + public void setElements(Element[] elements) { + scrollableElements = new HashSet(Arrays.asList(elements)); + } + /** * long calcucation are not very efficient in GWT, so this helper method * returns timestamp in double. -- cgit v1.2.3 From adf89bd4dbd637ff4641efe3c544f8d9d3c560d7 Mon Sep 17 00:00:00 2001 From: Automerge Date: Tue, 15 May 2012 09:09:04 +0000 Subject: [merge from 6.7] Avoid random failures by not clicking button outside viewport svn changeset:23739/svn branch:6.8 --- .../tests/components/treetable/TreeTableCacheOnPartialUpdate.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/testbench/com/vaadin/tests/components/treetable/TreeTableCacheOnPartialUpdate.html b/tests/testbench/com/vaadin/tests/components/treetable/TreeTableCacheOnPartialUpdate.html index ac20598ccd..499c30c86a 100644 --- a/tests/testbench/com/vaadin/tests/components/treetable/TreeTableCacheOnPartialUpdate.html +++ b/tests/testbench/com/vaadin/tests/components/treetable/TreeTableCacheOnPartialUpdate.html @@ -264,13 +264,13 @@ mouseClick - vaadin=runcomvaadintestscomponentstreetableTreeTableCacheOnPartialUpdates::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[3]/VTreeTable[0]/FocusableScrollPanel[0]/VTreeTable$VTreeTableScrollBody[0]/VTreeTable$VTreeTableScrollBody$VTreeTableRow[44]/VNativeButton[0] + vaadin=runcomvaadintestscomponentstreetableTreeTableCacheOnPartialUpdates::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[3]/VTreeTable[0]/FocusableScrollPanel[0]/VTreeTable$VTreeTableScrollBody[0]/VTreeTable$VTreeTableScrollBody$VTreeTableRow[40]/VNativeButton[0] 114,-1000 assertText vaadin=runcomvaadintestscomponentstreetableTreeTableCacheOnPartialUpdates::PID_SLog_row_0 - 23. Button Item TestBean [col1=40.10, col2=AN.J]/col3 clicked. Row index: 49 + 23. Button Item TestBean [col1=40.6, col2=AN.F]/col3 clicked. Row index: 45 mouseClick -- cgit v1.2.3 From b5486bce95d754a3fd1ff169679c4714c42154ee Mon Sep 17 00:00:00 2001 From: Automerge Date: Tue, 15 May 2012 09:09:09 +0000 Subject: [merge from 6.7] #5521 fixed condition that was always checking for height, not width svn changeset:23740/svn branch:6.8 --- src/com/vaadin/terminal/gwt/client/ui/VView.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/com/vaadin/terminal/gwt/client/ui/VView.java b/src/com/vaadin/terminal/gwt/client/ui/VView.java index abebf0ea4a..ec4c5d9cba 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VView.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VView.java @@ -446,7 +446,8 @@ public class VView extends SimplePanel implements Container, ResizeHandler, .getProperty(direction))) { parentOfVApp.getStyle().setProperty(direction, "100%"); } - } else if (parentOfVApp.getStyle().getHeight().contains("%")) { + } else if (parentOfVApp.getStyle().getProperty(direction) + .contains("%")) { // if layout size is undefined or fixed and we have set a // percentual size for portlet-body, remove size setting on // portlet body -- cgit v1.2.3 From 531e592760c2f2fe065ff203b120cba3f6950da3 Mon Sep 17 00:00:00 2001 From: Automerge Date: Tue, 15 May 2012 13:06:42 +0000 Subject: [merge from 6.7] Remove invalid import used by javadocs svn changeset:23745/svn branch:6.8 --- src/com/vaadin/ui/TreeTable.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/com/vaadin/ui/TreeTable.java b/src/com/vaadin/ui/TreeTable.java index 43bc7a80fe..19ca27133b 100644 --- a/src/com/vaadin/ui/TreeTable.java +++ b/src/com/vaadin/ui/TreeTable.java @@ -13,7 +13,6 @@ import java.util.List; import java.util.Map; import java.util.logging.Logger; -import com.google.gwt.user.client.ui.Tree; import com.vaadin.data.Container; import com.vaadin.data.Container.Hierarchical; import com.vaadin.data.Container.ItemSetChangeEvent; -- cgit v1.2.3 From 41f5328ef5600ce61bb323814f605cc6e77cbca2 Mon Sep 17 00:00:00 2001 From: Automerge Date: Tue, 15 May 2012 17:11:36 +0000 Subject: [merge from 6.7] Take viewport scrolling into account when calculating drop position (#6021) svn changeset:23749/svn branch:6.8 --- .../vaadin/terminal/gwt/client/ui/dd/DDUtil.java | 17 ++++-- .../tests/dd/ScrolledDropTarget.html.disabled | 0 .../com/vaadin/tests/dd/ScrolledDropTarget.java | 67 ++++++++++++++++++++++ 3 files changed, 79 insertions(+), 5 deletions(-) create mode 100644 tests/testbench/com/vaadin/tests/dd/ScrolledDropTarget.html.disabled create mode 100644 tests/testbench/com/vaadin/tests/dd/ScrolledDropTarget.java diff --git a/src/com/vaadin/terminal/gwt/client/ui/dd/DDUtil.java b/src/com/vaadin/terminal/gwt/client/ui/dd/DDUtil.java index 02c1fe5061..225770b62b 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/dd/DDUtil.java +++ b/src/com/vaadin/terminal/gwt/client/ui/dd/DDUtil.java @@ -5,6 +5,7 @@ package com.vaadin.terminal.gwt.client.ui.dd; import com.google.gwt.dom.client.NativeEvent; import com.google.gwt.user.client.Element; +import com.google.gwt.user.client.Window; import com.vaadin.terminal.gwt.client.Util; public class DDUtil { @@ -43,8 +44,11 @@ public class DDUtil { public static VerticalDropLocation getVerticalDropLocation(Element element, int offsetHeight, int clientY, double topBottomRatio) { - int absoluteTop = element.getAbsoluteTop(); - int fromTop = clientY - absoluteTop; + // Event coordinates are relative to the viewport, element absolute + // position is relative to the document. Make element position relative + // to viewport by adjusting for viewport scrolling. See #6021 + int elementTop = element.getAbsoluteTop() - Window.getScrollTop(); + int fromTop = clientY - elementTop; float percentageFromTop = (fromTop / (float) offsetHeight); if (percentageFromTop < topBottomRatio) { @@ -74,11 +78,14 @@ public class DDUtil { public static HorizontalDropLocation getHorizontalDropLocation( Element element, int clientX, double leftRightRatio) { - int absoluteLeft = element.getAbsoluteLeft(); + // Event coordinates are relative to the viewport, element absolute + // position is relative to the document. Make element position relative + // to viewport by adjusting for viewport scrolling. See #6021 + int elementLeft = element.getAbsoluteLeft() - Window.getScrollLeft(); int offsetWidth = element.getOffsetWidth(); - int fromTop = clientX - absoluteLeft; + int fromLeft = clientX - elementLeft; - float percentageFromTop = (fromTop / (float) offsetWidth); + float percentageFromTop = (fromLeft / (float) offsetWidth); if (percentageFromTop < leftRightRatio) { return HorizontalDropLocation.LEFT; } else if (percentageFromTop > 1 - leftRightRatio) { diff --git a/tests/testbench/com/vaadin/tests/dd/ScrolledDropTarget.html.disabled b/tests/testbench/com/vaadin/tests/dd/ScrolledDropTarget.html.disabled new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/testbench/com/vaadin/tests/dd/ScrolledDropTarget.java b/tests/testbench/com/vaadin/tests/dd/ScrolledDropTarget.java new file mode 100644 index 0000000000..093e12f84a --- /dev/null +++ b/tests/testbench/com/vaadin/tests/dd/ScrolledDropTarget.java @@ -0,0 +1,67 @@ +package com.vaadin.tests.dd; + +import com.vaadin.event.dd.DragAndDropEvent; +import com.vaadin.event.dd.DropHandler; +import com.vaadin.event.dd.acceptcriteria.AcceptCriterion; +import com.vaadin.terminal.gwt.client.ui.dd.VerticalDropLocation; +import com.vaadin.tests.components.TestBase; +import com.vaadin.tests.util.Log; +import com.vaadin.ui.AbstractSelect.AbstractSelectTargetDetails; +import com.vaadin.ui.AbstractSelect.VerticalLocationIs; +import com.vaadin.ui.Button; +import com.vaadin.ui.Button.ClickEvent; +import com.vaadin.ui.Table; +import com.vaadin.ui.Table.TableDragMode; + +public class ScrolledDropTarget extends TestBase { + private final Log log = new Log(5); + + @Override + protected void setup() { + + Table table = new Table(); + table.addContainerProperty("A", String.class, ""); + for (int i = 0; i < 100; i++) { + table.addItem(new Object[] { Integer.toString(i) }, + Integer.valueOf(i)); + } + + table.setDragMode(TableDragMode.ROW); + table.setDropHandler(new DropHandler() { + public AcceptCriterion getAcceptCriterion() { + return VerticalLocationIs.MIDDLE; + } + + public void drop(DragAndDropEvent event) { + AbstractSelectTargetDetails targetDetails = (AbstractSelectTargetDetails) event + .getTargetDetails(); + VerticalDropLocation dropLocation = targetDetails + .getDropLocation(); + log.log("Drop at " + dropLocation + " relative to " + + targetDetails.getItemIdOver()); + } + }); + + addComponent(table); + addComponent(new Button("Scroll body", new Button.ClickListener() { + public void buttonClick(ClickEvent event) { + getMainWindow().executeJavaScript( + "document.body.style.overflow = 'auto';" + + "document.body.style.height = '200%';" + + "window.scrollTo(0,18)"); + } + })); + addComponent(log); + } + + @Override + protected String getDescription() { + return "Vertical location for drags should work even when the browser window is scrolled"; + } + + @Override + protected Integer getTicketNumber() { + return Integer.valueOf(6021); + } + +} -- cgit v1.2.3 From d0e524428add4a5685a67ddcdccb6260e9b330f6 Mon Sep 17 00:00:00 2001 From: Automerge Date: Tue, 15 May 2012 17:11:42 +0000 Subject: [merge from 6.7] Test case for #7387 svn changeset:23750/svn branch:6.8 --- .../treetable/ComponentsInTreeTable.java | 50 ++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 tests/testbench/com/vaadin/tests/components/treetable/ComponentsInTreeTable.java diff --git a/tests/testbench/com/vaadin/tests/components/treetable/ComponentsInTreeTable.java b/tests/testbench/com/vaadin/tests/components/treetable/ComponentsInTreeTable.java new file mode 100644 index 0000000000..5b7700bc6e --- /dev/null +++ b/tests/testbench/com/vaadin/tests/components/treetable/ComponentsInTreeTable.java @@ -0,0 +1,50 @@ +package com.vaadin.tests.components.treetable; + +import com.vaadin.tests.components.TestBase; +import com.vaadin.ui.Button; +import com.vaadin.ui.Component; +import com.vaadin.ui.HorizontalLayout; +import com.vaadin.ui.Label; +import com.vaadin.ui.Layout; +import com.vaadin.ui.TreeTable; + +public class ComponentsInTreeTable extends TestBase { + + @Override + protected void setup() { + TreeTable tt = new TreeTable(); + tt.setWidth("300px"); + addComponent(tt); + + Object id, id2; + + tt.addContainerProperty("foo", Component.class, ""); + tt.addContainerProperty("bar", String.class, "bar"); + tt.addContainerProperty("baz", String.class, "baz"); + + id = tt.addItem(); + Layout l = new HorizontalLayout(); + l.addComponent(new Label("bar")); + l.addComponent(new Label("bar")); + tt.getContainerProperty(id, "foo").setValue(l); + + id = tt.addItem(); + Label lbl = new Label("foo
bar"); + lbl.setContentMode(Label.CONTENT_XHTML); + tt.getContainerProperty(id, "foo").setValue(lbl); + + id2 = tt.addItem(); + tt.setParent(id2, id); + tt.getContainerProperty(id2, "foo").setValue(new Button("Test")); + } + + @Override + protected String getDescription() { + return "Components in TreeTable cells should be rendered inline with the expand/collapse arrow"; + } + + @Override + protected Integer getTicketNumber() { + return 7387; + } +} -- cgit v1.2.3 From a9aeab18b267ea1bc8e454d01ce5adeea94f917d Mon Sep 17 00:00:00 2001 From: Automerge Date: Wed, 16 May 2012 09:07:19 +0000 Subject: [merge from 6.7] Rename illogical local variable svn changeset:23752/svn branch:6.8 --- src/com/vaadin/terminal/gwt/client/ui/dd/DDUtil.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/com/vaadin/terminal/gwt/client/ui/dd/DDUtil.java b/src/com/vaadin/terminal/gwt/client/ui/dd/DDUtil.java index 225770b62b..97f5eb86fd 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/dd/DDUtil.java +++ b/src/com/vaadin/terminal/gwt/client/ui/dd/DDUtil.java @@ -85,10 +85,10 @@ public class DDUtil { int offsetWidth = element.getOffsetWidth(); int fromLeft = clientX - elementLeft; - float percentageFromTop = (fromLeft / (float) offsetWidth); - if (percentageFromTop < leftRightRatio) { + float percentageFromLeft = (fromLeft / (float) offsetWidth); + if (percentageFromLeft < leftRightRatio) { return HorizontalDropLocation.LEFT; - } else if (percentageFromTop > 1 - leftRightRatio) { + } else if (percentageFromLeft > 1 - leftRightRatio) { return HorizontalDropLocation.RIGHT; } else { return HorizontalDropLocation.CENTER; -- cgit v1.2.3 From ecd02651e7a27b964515cfd41b956a82f2886f43 Mon Sep 17 00:00:00 2001 From: Johannes Dahlström Date: Fri, 18 May 2012 07:34:03 +0000 Subject: [merge from 6.7] #8793 Add unit test for TabSheet.replaceComponent() svn changeset:23758/svn branch:6.8 --- .../server/component/tabsheet/TestTabSheet.java | 63 ++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/tests/server-side/com/vaadin/tests/server/component/tabsheet/TestTabSheet.java b/tests/server-side/com/vaadin/tests/server/component/tabsheet/TestTabSheet.java index 69de33f3af..c74a3fadf1 100644 --- a/tests/server-side/com/vaadin/tests/server/component/tabsheet/TestTabSheet.java +++ b/tests/server-side/com/vaadin/tests/server/component/tabsheet/TestTabSheet.java @@ -2,6 +2,8 @@ package com.vaadin.tests.server.component.tabsheet; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertSame; import java.util.Iterator; @@ -158,4 +160,65 @@ public class TestTabSheet { tabSheet.setSelectedTab(123); assertEquals(tab1.getComponent(), tabSheet.getSelectedTab()); } + + @Test + public void replaceComponent() { + TabSheet tabSheet = new TabSheet(); + Label lbl1 = new Label("aaa"); + Label lbl2 = new Label("bbb"); + Label lbl3 = new Label("ccc"); + Label lbl4 = new Label("ddd"); + + Tab tab1 = tabSheet.addTab(lbl1); + tab1.setCaption("tab1"); + tab1.setClosable(true); + Tab tab2 = tabSheet.addTab(lbl2); + tab2.setDescription("description"); + tab2.setEnabled(false); + + // Replace component not in tabsheet with one already in tabsheet - + // should be no-op + tabSheet.replaceComponent(lbl3, lbl2); + assertEquals(2, tabSheet.getComponentCount()); + assertSame(tab1, tabSheet.getTab(lbl1)); + assertSame(tab2, tabSheet.getTab(lbl2)); + assertNull(tabSheet.getTab(lbl3)); + + // Replace component not in tabsheet with one not in tabsheet either + // should add lbl4 as last tab + tabSheet.replaceComponent(lbl3, lbl4); + assertEquals(3, tabSheet.getComponentCount()); + assertSame(tab1, tabSheet.getTab(lbl1)); + assertSame(tab2, tabSheet.getTab(lbl2)); + assertEquals(2, tabSheet.getTabPosition(tabSheet.getTab(lbl4))); + + // Replace component in tabsheet with another + // should swap places, tab association should stay the same but tabs + // should swap metadata + tabSheet.replaceComponent(lbl1, lbl2); + assertSame(tab1, tabSheet.getTab(lbl1)); + assertSame(tab2, tabSheet.getTab(lbl2)); + assertEquals(false, tab1.isClosable()); + assertEquals(true, tab2.isClosable()); + assertEquals(false, tab1.isEnabled()); + assertEquals(true, tab2.isEnabled()); + assertEquals("description", tab1.getDescription()); + assertEquals(null, tab2.getDescription()); + assertEquals(3, tabSheet.getComponentCount()); + assertEquals(1, tabSheet.getTabPosition(tabSheet.getTab(lbl1))); + assertEquals(0, tabSheet.getTabPosition(tabSheet.getTab(lbl2))); + + // Replace component in tabsheet with one not in tabsheet + // should create a new tab instance for the new component, old tab + // instance should become unattached + // tab metadata should be copied from old to new + tabSheet.replaceComponent(lbl1, lbl3); + assertEquals(3, tabSheet.getComponentCount()); + assertNull(tabSheet.getTab(lbl1)); + assertNull(tab1.getComponent()); + assertNotNull(tabSheet.getTab(lbl3)); + assertEquals(false, tabSheet.getTab(lbl3).isEnabled()); + assertEquals("description", tab1.getDescription()); + assertEquals(1, tabSheet.getTabPosition(tabSheet.getTab(lbl3))); + } } -- cgit v1.2.3 From 55f69ec8a203137d6bc1acfdb385da96a2f09b47 Mon Sep 17 00:00:00 2001 From: Johannes Dahlström Date: Fri, 18 May 2012 07:52:44 +0000 Subject: [merge from 6.7] #8793 Retain all tab metadata, not just caption and icon, in TabSheet.replaceComponent() svn changeset:23761/svn branch:6.8 --- src/com/vaadin/ui/TabSheet.java | 78 +++++++++++++++++------------------------ 1 file changed, 32 insertions(+), 46 deletions(-) diff --git a/src/com/vaadin/ui/TabSheet.java b/src/com/vaadin/ui/TabSheet.java index 09d1002b48..6ada797570 100644 --- a/src/com/vaadin/ui/TabSheet.java +++ b/src/com/vaadin/ui/TabSheet.java @@ -725,25 +725,6 @@ public class TabSheet extends AbstractComponentContainer implements Focusable, Tab newTab = tabs.get(newComponent); Tab oldTab = tabs.get(oldComponent); - // Gets the captions - String oldCaption = null; - Resource oldIcon = null; - String newCaption = null; - Resource newIcon = null; - - if (oldTab != null) { - oldCaption = oldTab.getCaption(); - oldIcon = oldTab.getIcon(); - } - - if (newTab != null) { - newCaption = newTab.getCaption(); - newIcon = newTab.getIcon(); - } else { - newCaption = newComponent.getCaption(); - newIcon = newComponent.getIcon(); - } - // Gets the locations int oldLocation = -1; int newLocation = -1; @@ -765,35 +746,21 @@ public class TabSheet extends AbstractComponentContainer implements Focusable, addComponent(newComponent); } else if (newLocation == -1) { removeComponent(oldComponent); - keyMapper.remove(oldComponent); - newTab = addTab(newComponent); - components.remove(newComponent); - components.add(oldLocation, newComponent); - newTab.setCaption(oldCaption); - newTab.setIcon(oldIcon); + newTab = addTab(newComponent, oldLocation); + // Copy all relevant metadata to the new tab (#8793) + // TODO Should reuse the old tab instance instead? + copyTabMetadata(oldTab, newTab); } else { - if (oldLocation > newLocation) { - components.remove(oldComponent); - components.add(newLocation, oldComponent); - components.remove(newComponent); - components.add(oldLocation, newComponent); - } else { - components.remove(newComponent); - components.add(oldLocation, newComponent); - components.remove(oldComponent); - components.add(newLocation, oldComponent); - } + components.set(oldLocation, newComponent); + components.set(newLocation, oldComponent); - if (newTab != null) { - // This should always be true - newTab.setCaption(oldCaption); - newTab.setIcon(oldIcon); - } - if (oldTab != null) { - // This should always be true - oldTab.setCaption(newCaption); - oldTab.setIcon(newIcon); - } + // Tab associations are not changed, but metadata is swapped between + // the instances + // TODO Should reassociate the instances instead? + Tab tmp = new TabSheetTabImpl(null, null); + copyTabMetadata(newTab, tmp); + copyTabMetadata(oldTab, newTab); + copyTabMetadata(tmp, oldTab); requestRepaint(); } @@ -1303,4 +1270,23 @@ public class TabSheet extends AbstractComponentContainer implements Focusable, removeListener(FocusEvent.EVENT_ID, FocusEvent.class, listener); } + + /** + * Copies properties from one Tab to another. + * + * @param from + * The tab whose data to copy. + * @param to + * The tab to which copy the data. + */ + private static void copyTabMetadata(Tab from, Tab to) { + to.setCaption(from.getCaption()); + to.setIcon(from.getIcon()); + to.setDescription(from.getDescription()); + to.setVisible(from.isVisible()); + to.setEnabled(from.isEnabled()); + to.setClosable(from.isClosable()); + to.setStyleName(from.getStyleName()); + to.setComponentError(from.getComponentError()); + } } -- cgit v1.2.3 From b4eb8571aba35b90df5cf70ad1f4a8ca3f67556d Mon Sep 17 00:00:00 2001 From: Automerge Date: Fri, 18 May 2012 08:44:57 +0000 Subject: [merge from 6.7] #8805 fix flickering of partial first row in table, related manual test svn changeset:23762/svn branch:6.8 --- src/com/vaadin/ui/Table.java | 7 ++ .../components/table/TableFirstRowFlicker.java | 85 ++++++++++++++++++++++ 2 files changed, 92 insertions(+) create mode 100644 tests/testbench/com/vaadin/tests/components/table/TableFirstRowFlicker.java diff --git a/src/com/vaadin/ui/Table.java b/src/com/vaadin/ui/Table.java index 7828fdb734..db0809fbd5 100644 --- a/src/com/vaadin/ui/Table.java +++ b/src/com/vaadin/ui/Table.java @@ -1458,6 +1458,13 @@ public class Table extends AbstractSelect implements Action.Container, } } else { // initial load + + // #8805 send one extra row in the beginning in case a partial + // row is shown on the UI + if (firstIndex > 0) { + firstIndex = firstIndex - 1; + rows = rows + 1; + } firstToBeRenderedInClient = firstIndex; } if (totalRows > 0) { diff --git a/tests/testbench/com/vaadin/tests/components/table/TableFirstRowFlicker.java b/tests/testbench/com/vaadin/tests/components/table/TableFirstRowFlicker.java new file mode 100644 index 0000000000..776e7956bf --- /dev/null +++ b/tests/testbench/com/vaadin/tests/components/table/TableFirstRowFlicker.java @@ -0,0 +1,85 @@ +package com.vaadin.tests.components.table; + +import com.vaadin.Application; +import com.vaadin.data.Container; +import com.vaadin.data.util.IndexedContainer; +import com.vaadin.ui.Label; +import com.vaadin.ui.ProgressIndicator; +import com.vaadin.ui.Table; +import com.vaadin.ui.VerticalLayout; +import com.vaadin.ui.Window; + +public class TableFirstRowFlicker extends Application { + + Table t; + + @Override + public void init() { + Window mainWindow = new Window("Table Row Flicker"); + mainWindow.getContent().setSizeFull(); + setMainWindow(mainWindow); + + t = new Table(); + t.setSizeFull(); + t.setSelectable(true); + t.setContainerDataSource(buildContainer()); + mainWindow.addComponent(t); + ((VerticalLayout) mainWindow.getContent()).setExpandRatio(t, 1); + + // Button button = new Button("Refresh"); + // button.addListener(new Button.ClickListener() { + // public void buttonClick(ClickEvent event) { + // t.refreshRowCache(); + // } + // }); + // mainWindow.addComponent(button); + + ProgressIndicator pi = new ProgressIndicator(); + pi.setPollingInterval(1000); + pi.setIndeterminate(true); + mainWindow.addComponent(pi); + + Thread r = new Thread() { + @Override + public void run() { + while (t != null) { + synchronized (t.getApplication()) { + int firstId = t.getCurrentPageFirstItemIndex(); + Object selected = t.getValue(); + t.setContainerDataSource(buildContainer()); + t.setValue(selected); + t.setCurrentPageFirstItemIndex(firstId); + // lighter alternative for all of above + // t.refreshRowCache(); + } + try { + Thread.sleep(500); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + System.out.println("Table update thread stopped"); + } + }; + r.start(); + } + + @Override + public void close() { + t = null; + super.close(); + } + + private Container buildContainer() { + IndexedContainer cont = new IndexedContainer(); + cont.addContainerProperty("name", Label.class, null); + for (int i = 0; i < 10000; i++) { + cont.addItem(i); + Label l = new Label("Item " + i); + l.setHeight("50px"); + cont.getContainerProperty(i, "name").setValue(l); + } + return cont; + } + +} \ No newline at end of file -- cgit v1.2.3 From 7f8bcc2638e5fe97e3a362e86a3b7953c0663e8e Mon Sep 17 00:00:00 2001 From: Automerge Date: Fri, 18 May 2012 08:45:02 +0000 Subject: [merge from 6.7] Fix #8810 - only animate row expansion if there are child rows to animate svn changeset:23763/svn branch:6.8 --- .../vaadin/terminal/gwt/client/ui/VTreeTable.java | 11 +++- .../tests/components/treetable/RowAnimation.html | 77 ++++++++++++++++++++++ 2 files changed, 86 insertions(+), 2 deletions(-) create mode 100644 tests/testbench/com/vaadin/tests/components/treetable/RowAnimation.html diff --git a/src/com/vaadin/terminal/gwt/client/ui/VTreeTable.java b/src/com/vaadin/terminal/gwt/client/ui/VTreeTable.java index 8e55400f31..13a60c74b9 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VTreeTable.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VTreeTable.java @@ -496,8 +496,11 @@ public class VTreeTable extends VScrollTable { int firstIndex, int rows) { List insertedRows = insertAndReindexRows(rowData, firstIndex, rows); - RowExpandAnimation anim = new RowExpandAnimation(insertedRows); - anim.run(150); + if (!insertedRows.isEmpty()) { + // Only animate if there's something to animate (#8810) + RowExpandAnimation anim = new RowExpandAnimation(insertedRows); + anim.run(150); + } return insertedRows; } @@ -620,6 +623,10 @@ public class VTreeTable extends VScrollTable { private Element cloneTable; private AnimationPreparator preparator; + /** + * @param rows + * List of rows to animate. Must not be empty. + */ public RowExpandAnimation(List rows) { this.rows = rows; buildAndInsertAnimatingDiv(); diff --git a/tests/testbench/com/vaadin/tests/components/treetable/RowAnimation.html b/tests/testbench/com/vaadin/tests/components/treetable/RowAnimation.html new file mode 100644 index 0000000000..64ff061c13 --- /dev/null +++ b/tests/testbench/com/vaadin/tests/components/treetable/RowAnimation.html @@ -0,0 +1,77 @@ + + + + + + +TestAnimatedExpandCollapse + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
TestAnimatedExpandCollapse
open/run/com.vaadin.tests.components.treetable.TreeTableTest?restartApplication
mouseClickvaadin=runcomvaadintestscomponentstreetableTreeTableTest::PID_Smenu#item038,10
mouseClickvaadin=runcomvaadintestscomponentstreetableTreeTableTest::Root/VOverlay[0]/VMenuBar[0]#item035,5
mouseClickvaadin=runcomvaadintestscomponentstreetableTreeTableTest::Root/VOverlay[1]/VMenuBar[0]#item730,12
mouseClickvaadin=runcomvaadintestscomponentstreetableTreeTableTest::PID_StestComponent/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]12,7
mouseClickvaadin=runcomvaadintestscomponentstreetableTreeTableTest::PID_StestComponent/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[0]/domChild[0]31,7
mouseClickvaadin=runcomvaadintestscomponentstreetableTreeTableTest::PID_StestComponent/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[2]/domChild[0]/domChild[0]/domChild[0]29,8
mouseClickvaadin=runcomvaadintestscomponentstreetableTreeTableTest::PID_StestComponent/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[3]/domChild[0]/domChild[0]/domChild[0]30,6
assertTextvaadin=runcomvaadintestscomponentstreetableTreeTableTest::PID_StestComponent/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[0]Item 4,1
assertTextvaadin=runcomvaadintestscomponentstreetableTreeTableTest::PID_StestComponent/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[2]/domChild[0]/domChild[0]Item 5,1
assertTextvaadin=runcomvaadintestscomponentstreetableTreeTableTest::PID_StestComponent/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[3]/domChild[0]/domChild[0]Item 6,1
assertTextvaadin=runcomvaadintestscomponentstreetableTreeTableTest::PID_StestComponent/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[4]/domChild[0]/domChild[0]Item 7,1
+ + -- cgit v1.2.3 From 2041e6273e0dfb2e4e38b00ec1470e691ea115b8 Mon Sep 17 00:00:00 2001 From: Automerge Date: Fri, 18 May 2012 08:45:07 +0000 Subject: [merge from 6.7] #8810 Fix row collapse animation as well svn changeset:23764/svn branch:6.8 --- .../vaadin/terminal/gwt/client/ui/VTreeTable.java | 33 ++++++++++++++-------- 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/src/com/vaadin/terminal/gwt/client/ui/VTreeTable.java b/src/com/vaadin/terminal/gwt/client/ui/VTreeTable.java index 13a60c74b9..324efcb67d 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VTreeTable.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VTreeTable.java @@ -478,18 +478,23 @@ public class VTreeTable extends VScrollTable { rowsToDelete.add(row); } } - RowCollapseAnimation anim = new RowCollapseAnimation(rowsToDelete) { - @Override - protected void onComplete() { - super.onComplete(); - // Actually unlink the rows and update the cache after the - // animation is done. - unlinkAndReindexRows(firstIndex, rows); - discardRowsOutsideCacheWindow(); - ensureCacheFilled(); - } - }; - anim.run(150); + if (!rowsToDelete.isEmpty()) { + // #8810 Only animate if there's something to animate + RowCollapseAnimation anim = new RowCollapseAnimation( + rowsToDelete) { + @Override + protected void onComplete() { + super.onComplete(); + // Actually unlink the rows and update the cache after + // the + // animation is done. + unlinkAndReindexRows(firstIndex, rows); + discardRowsOutsideCacheWindow(); + ensureCacheFilled(); + } + }; + anim.run(150); + } } protected List insertRowsAnimated(UIDL rowData, @@ -747,6 +752,10 @@ public class VTreeTable extends VScrollTable { private final List rows; + /** + * @param rows + * List of rows to animate. Must not be empty. + */ public RowCollapseAnimation(List rows) { super(rows); this.rows = rows; -- cgit v1.2.3 From 99786aecc49f538dbae3a856009baefc05666a34 Mon Sep 17 00:00:00 2001 From: Automerge Date: Fri, 18 May 2012 13:06:38 +0000 Subject: [merge from 6.7] Test application for #8813 svn changeset:23766/svn branch:6.8 --- .../tests/dd/NotPaintedAcceptSourceInTabSheet.java | 77 ++++++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 tests/testbench/com/vaadin/tests/dd/NotPaintedAcceptSourceInTabSheet.java diff --git a/tests/testbench/com/vaadin/tests/dd/NotPaintedAcceptSourceInTabSheet.java b/tests/testbench/com/vaadin/tests/dd/NotPaintedAcceptSourceInTabSheet.java new file mode 100644 index 0000000000..ac92193764 --- /dev/null +++ b/tests/testbench/com/vaadin/tests/dd/NotPaintedAcceptSourceInTabSheet.java @@ -0,0 +1,77 @@ +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.TabSheet; +import com.vaadin.ui.Table; +import com.vaadin.ui.Table.TableDragMode; +import com.vaadin.ui.Table.TableTransferable; + +public class NotPaintedAcceptSourceInTabSheet 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()); + } + }); + + TabSheet tabSheet = new TabSheet(); + tabSheet.addComponent(source1); + tabSheet.addComponent(source2); + + addComponent(tabSheet); + addComponent(target); + } + + 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 in a TabSheet and has not yet been painted should still allow painting the component properly when the tab is opened."; + } + + @Override + protected Integer getTicketNumber() { + return Integer.valueOf(8730); + } + +} -- cgit v1.2.3 From e716b16b6162a90946a926eff3bfd2593f092b69 Mon Sep 17 00:00:00 2001 From: Johannes Dahlström Date: Mon, 21 May 2012 12:26:20 +0000 Subject: Remove -webkit-overflow-scrolling from .v-scrollable for now - caused a weird iOS 5 bug in Accordion touch support (#8723 #8792) svn changeset:23770/svn branch:6.8 --- WebContent/VAADIN/themes/base/common/common.css | 1 - 1 file changed, 1 deletion(-) diff --git a/WebContent/VAADIN/themes/base/common/common.css b/WebContent/VAADIN/themes/base/common/common.css index f0b0f8e7be..8734aee63f 100644 --- a/WebContent/VAADIN/themes/base/common/common.css +++ b/WebContent/VAADIN/themes/base/common/common.css @@ -232,5 +232,4 @@ div.v-app-loading { .v-scrollable { overflow: auto; - -webkit-overflow-scrolling: touch; } \ No newline at end of file -- cgit v1.2.3 From 879e9aef4d6374ce89565460e0a979731f5da71f Mon Sep 17 00:00:00 2001 From: Johannes Dahlström Date: Mon, 21 May 2012 13:10:49 +0000 Subject: #8723 Remove superfluous sinkEvents() call svn changeset:23772/svn branch:6.8 --- src/com/vaadin/terminal/gwt/client/ui/VAccordion.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/com/vaadin/terminal/gwt/client/ui/VAccordion.java b/src/com/vaadin/terminal/gwt/client/ui/VAccordion.java index 4ff70d1668..20030d2d46 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VAccordion.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VAccordion.java @@ -453,8 +453,6 @@ public class VAccordion extends VTabsheetBase implements touchScrollHandler.addElement(getContainerElement()); - sinkEvents(Event.MOUSEEVENTS); - close(); } -- cgit v1.2.3 From 9b52497261f0063b5a2d0431b8d7d61930a46161 Mon Sep 17 00:00:00 2001 From: Automerge Date: Mon, 21 May 2012 13:19:35 +0000 Subject: [merge from 6.7] Don't trigger actions if space or enter is pressed with Button focused (#7191) svn changeset:23774/svn branch:6.8 --- src/com/vaadin/terminal/gwt/client/ui/VButton.java | 37 +++++-------- src/com/vaadin/ui/Button.java | 3 -- .../button/ButtonEnterWithWindowShortcut.html | 62 ++++++++++++++++++++++ .../button/ButtonEnterWithWindowShortcut.java | 55 +++++++++++++++++++ 4 files changed, 129 insertions(+), 28 deletions(-) create mode 100644 tests/testbench/com/vaadin/tests/components/button/ButtonEnterWithWindowShortcut.html create mode 100644 tests/testbench/com/vaadin/tests/components/button/ButtonEnterWithWindowShortcut.java diff --git a/src/com/vaadin/terminal/gwt/client/ui/VButton.java b/src/com/vaadin/terminal/gwt/client/ui/VButton.java index 98103dc41e..e77ad710b1 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VButton.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VButton.java @@ -77,7 +77,9 @@ public class VButton extends FocusWidget implements Paintable, ClickHandler, private boolean isCapturing; /** - * If true, this widget has focus with the space bar down. + * If true, this widget has focus with the space bar down. This + * means that we will get events when the button is released, but we should + * trigger the button only if the button is still focused at that point. */ private boolean isFocusing; @@ -91,8 +93,6 @@ public class VButton extends FocusWidget implements Paintable, ClickHandler, private HandlerRegistration focusHandlerRegistration; private HandlerRegistration blurHandlerRegistration; - private int clickShortcut = 0; - /** * If caption should be rendered in HTML */ @@ -174,10 +174,6 @@ public class VButton extends FocusWidget implements Paintable, ClickHandler, icon = null; } } - - if (uidl.hasAttribute("keycode")) { - clickShortcut = uidl.getIntAttribute("keycode"); - } } public void setText(String text) { @@ -316,37 +312,28 @@ public class VButton extends FocusWidget implements Paintable, ClickHandler, if ((event.getTypeInt() & Event.KEYEVENTS) != 0) { switch (type) { case Event.ONKEYDOWN: + // Stop propagation when the user starts pressing a button that + // we are handling to prevent actions from getting triggered if (event.getKeyCode() == 32 /* space */) { isFocusing = true; event.preventDefault(); + event.stopPropagation(); + } else if (event.getKeyCode() == KeyCodes.KEY_ENTER) { + event.stopPropagation(); } break; case Event.ONKEYUP: if (isFocusing && event.getKeyCode() == 32 /* space */) { isFocusing = false; - - /* - * If click shortcut is space then the shortcut handler will - * take care of the click. - */ - if (clickShortcut != 32 /* space */) { - onClick(); - } - + onClick(); + event.stopPropagation(); event.preventDefault(); } break; case Event.ONKEYPRESS: if (event.getKeyCode() == KeyCodes.KEY_ENTER) { - - /* - * If click shortcut is enter then the shortcut handler will - * take care of the click. - */ - if (clickShortcut != KeyCodes.KEY_ENTER) { - onClick(); - } - + onClick(); + event.stopPropagation(); event.preventDefault(); } break; diff --git a/src/com/vaadin/ui/Button.java b/src/com/vaadin/ui/Button.java index fdaef046e5..0032db1752 100644 --- a/src/com/vaadin/ui/Button.java +++ b/src/com/vaadin/ui/Button.java @@ -158,9 +158,6 @@ public class Button extends AbstractField implements FieldEvents.BlurNotifier, if (isDisableOnClick()) { target.addAttribute(VButton.ATTR_DISABLE_ON_CLICK, true); } - if (clickShortcut != null) { - target.addAttribute("keycode", clickShortcut.getKeyCode()); - } if (isHtmlContentAllowed()) { target.addAttribute("html-caption", true); diff --git a/tests/testbench/com/vaadin/tests/components/button/ButtonEnterWithWindowShortcut.html b/tests/testbench/com/vaadin/tests/components/button/ButtonEnterWithWindowShortcut.html new file mode 100644 index 0000000000..5ec33f09fa --- /dev/null +++ b/tests/testbench/com/vaadin/tests/components/button/ButtonEnterWithWindowShortcut.html @@ -0,0 +1,62 @@ + + + + + + +New Test + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
New Test
open/run/com.vaadin.tests.components.button.ButtonEnterWithWindowShortcut?restartApplication
pressSpecialKeyvaadin=runcomvaadintestscomponentsbuttonButtonEnterWithWindowShortcut::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[1]/VButton[0]enter
assertTextvaadin=runcomvaadintestscomponentsbuttonButtonEnterWithWindowShortcut::PID_SLog_row_01. button click listener fired
pressSpecialKeyvaadin=runcomvaadintestscomponentsbuttonButtonEnterWithWindowShortcut::enter
assertTextvaadin=runcomvaadintestscomponentsbuttonButtonEnterWithWindowShortcut::PID_SLog_row_02. enter pressed in window
+ + diff --git a/tests/testbench/com/vaadin/tests/components/button/ButtonEnterWithWindowShortcut.java b/tests/testbench/com/vaadin/tests/components/button/ButtonEnterWithWindowShortcut.java new file mode 100644 index 0000000000..7efd40ca5d --- /dev/null +++ b/tests/testbench/com/vaadin/tests/components/button/ButtonEnterWithWindowShortcut.java @@ -0,0 +1,55 @@ +package com.vaadin.tests.components.button; + +import com.vaadin.event.Action; +import com.vaadin.event.Action.Handler; +import com.vaadin.event.ShortcutAction; +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.Button.ClickListener; + +public class ButtonEnterWithWindowShortcut extends TestBase { + Log log = new Log(5); + + @Override + protected void setup() { + getMainWindow().addActionHandler(new Handler() { + private static final long serialVersionUID = -4976129418325394913L; + + public void handleAction(Action action, Object sender, Object target) { + log.log(action.getCaption() + " pressed in window"); + } + + public Action[] getActions(Object target, Object sender) { + ShortcutAction enter = new ShortcutAction("enter", + ShortcutAction.KeyCode.ENTER, null); + ShortcutAction space = new ShortcutAction("space", + ShortcutAction.KeyCode.SPACEBAR, null); + return new Action[] { enter, space }; + } + }); + + Button button = new Button("Focus me and press enter", + new ClickListener() { + public void buttonClick(ClickEvent event) { + log.log("button click listener fired"); + } + }); + button.focus(); + + addComponent(log); + addComponent(button); + } + + @Override + protected String getDescription() { + return "Pressing enter or space with the button focused should trigger the button click listener and not the shortcut action on the window."; + } + + @Override + protected Integer getTicketNumber() { + return Integer.valueOf(5433); + } + +} -- cgit v1.2.3 From 233afce911a8f3c80ce86d9f46254a9c03c305d8 Mon Sep 17 00:00:00 2001 From: Johannes Dahlström Date: Mon, 21 May 2012 13:53:47 +0000 Subject: #8724 Factored away duplicate code in native/non-native touch handling, removed unused variables, removed debug messages, added comments svn changeset:23775/svn branch:6.8 --- .../terminal/gwt/client/ui/VScrollTable.java | 148 +++++---------------- 1 file changed, 33 insertions(+), 115 deletions(-) diff --git a/src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java b/src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java index bcd66c13f8..9e65889f44 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java @@ -4617,7 +4617,6 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler, private String[] actionKeys = null; private final TableRowElement rowElement; - private boolean mDown; private int index; private Event touchStart; private static final String ROW_CLASSNAME_EVEN = CLASSNAME + "-row"; @@ -4628,6 +4627,7 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler, private Timer dragTouchTimeout; private int touchStartY; private int touchStartX; + private boolean isDragging = false; private VScrollTableRow(int rowKey) { this.rowKey = rowKey; @@ -5038,40 +5038,24 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler, } } - private boolean wasSignificantMove = false; - private boolean isDragging = false; - /** - * Special handler for touch devices + * Special handler for touch devices that support native scrolling * - * @param event + * @return Whether the event was handled by this method. */ - public void onTouchBrowserEvent(final Event event) { - VConsole.log("-- START ONTOUCHBROWSEREVENT"); - if (enabled) { + private boolean handleTouchEvent(final Event event) { + + boolean touchEventHandled = false; + + if (enabled && hasNativeTouchScrolling) { final Element targetTdOrTr = getEventTargetTdOrTr(event); final int type = event.getTypeInt(); switch (type) { - case Event.ONCONTEXTMENU: - showContextMenu(event); - if (enabled - && (actionKeys != null || client - .hasEventListeners(VScrollTable.this, - ITEM_CLICK_EVENT_ID))) { - /* - * Prevent browser context menu only if there are - * action handlers or item click listeners - * registered - */ - event.stopPropagation(); - event.preventDefault(); - } - break; case Event.ONTOUCHSTART: + touchEventHandled = true; touchStart = event; isDragging = false; - wasSignificantMove = false; Touch touch = event.getChangedTouches().get(0); // save position to fields, touches in events are same // instance during the operation. @@ -5084,14 +5068,14 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler, @Override public void run() { if (touchStart != null) { - VConsole.log("DRAGGING"); + // Start a drag if a finger is held + // in place long enough, then moved isDragging = true; } } }; - VConsole.log("START DRAG TIMEOUT"); - dragTouchTimeout.schedule(TOUCHSCROLL_TIMEOUT); } + dragTouchTimeout.schedule(TOUCHSCROLL_TIMEOUT); } if (actionKeys != null) { @@ -5100,54 +5084,51 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler, @Override public void run() { if (touchStart != null) { - VConsole.log("SHOW CONTEXT"); + // Open the context menu if finger + // is held in place long enough. showContextMenu(touchStart); event.preventDefault(); - touchStart = null; - } } }; - VConsole.log("START CONTEXT TIMEOUT"); - - contextTouchTimeout.cancel(); - contextTouchTimeout - .schedule(TOUCH_CONTEXT_MENU_TIMEOUT); } + contextTouchTimeout + .schedule(TOUCH_CONTEXT_MENU_TIMEOUT); } break; case Event.ONTOUCHMOVE: + touchEventHandled = true; if (isSignificantMove(event)) { - wasSignificantMove = true; if (contextTouchTimeout != null) { + // Moved finger before the context menu timer + // expired, so let the browser handle this as a + // scroll. contextTouchTimeout.cancel(); + contextTouchTimeout = null; } if (!isDragging && dragTouchTimeout != null) { - VConsole.log("CANCEL DRAG TIMEOUT"); + // Moved finger before the drag timer expired, + // so let the browser handle this as a scroll. dragTouchTimeout.cancel(); dragTouchTimeout = null; } - if (isDragging) { - if (dragmode != 0 && touchStart != null) { - event.preventDefault(); - event.stopPropagation(); - VConsole.log("START DRAG"); - startRowDrag(touchStart, type, targetTdOrTr); - } - isDragging = false; + + if (dragmode != 0 && touchStart != null + && isDragging) { + event.preventDefault(); + event.stopPropagation(); + startRowDrag(touchStart, type, targetTdOrTr); } touchStart = null; } break; case Event.ONTOUCHEND: case Event.ONTOUCHCANCEL: - VConsole.log("ONTOUCHEND"); + touchEventHandled = true; if (contextTouchTimeout != null) { - VConsole.log("CANCEL CONTEXT TIMEOUT"); contextTouchTimeout.cancel(); } if (dragTouchTimeout != null) { - VConsole.log("CANCEL DRAG TIMEOUT"); dragTouchTimeout.cancel(); } if (touchStart != null) { @@ -5156,67 +5137,10 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler, touchStart = null; } isDragging = false; - VConsole.log("END ONTOUCHEND"); break; - case Event.ONMOUSEDOWN: - VConsole.log("ONMOUSEDOWN"); - if (targetTdOrTr != null) { - setRowFocus(this); - ensureFocus(); - if (dragmode != 0 - && (event.getButton() == NativeEvent.BUTTON_LEFT)) { - startRowDrag(event, event.getTypeInt(), - targetTdOrTr); - } else { - event.stopPropagation(); - } - - event.preventDefault(); - } - break; - case Event.ONMOUSEOUT: - VConsole.log("ONMOUSEOUT"); - break; - case Event.ONMOUSEUP: - VConsole.log("ONMOUSEUP"); - if (targetTdOrTr != null) { - if (isSelectable()) { - boolean currentlyJustThisRowSelected = selectedRowKeys - .size() == 1 - && selectedRowKeys.contains(getKey()); - - if (!currentlyJustThisRowSelected) { - if (isSingleSelectMode() - || isMultiSelectModeDefault()) { - deselectAll(); - } - toggleSelection(); - } else if ((isSingleSelectMode() || isMultiSelectModeSimple()) - && nullSelectionAllowed) { - toggleSelection(); - } - - selectionRangeStart = this; - setRowFocus(this); - - event.preventDefault(); - event.stopPropagation(); - } - } - - break; - case Event.ONDBLCLICK: - if (targetTdOrTr != null) { - handleClickEvent(event, targetTdOrTr, true); - } - break; - default: } } - VConsole.log("-- SUPER ONBROWSEREVENT"); - - super.onBrowserEvent(event); - VConsole.log("-- END ONTOUCHBROWSEREVENT"); + return touchEventHandled; } /* @@ -5225,12 +5149,9 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler, @Override public void onBrowserEvent(final Event event) { - if (hasNativeTouchScrolling) { - onTouchBrowserEvent(event); - return; - } + final boolean touchEventHandled = handleTouchEvent(event); - if (enabled) { + if (enabled && !touchEventHandled) { final int type = event.getTypeInt(); final Element targetTdOrTr = getEventTargetTdOrTr(event); if (type == Event.ONCONTEXTMENU) { @@ -5263,7 +5184,6 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler, break; case Event.ONMOUSEUP: if (targetCellOrRowFound) { - mDown = false; /* * Queue here, send at the same time as the * corresponding value change event - see #7127 @@ -5507,7 +5427,6 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler, break; case Event.ONMOUSEOUT: if (targetCellOrRowFound) { - mDown = false; } break; default: @@ -5538,7 +5457,6 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler, protected void startRowDrag(Event event, final int type, Element targetTdOrTr) { - mDown = true; VTransferable transferable = new VTransferable(); transferable.setDragSource(VScrollTable.this); transferable.setData("itemId", "" + rowKey); -- cgit v1.2.3 From ac7031059125b41aef98d7920670022befeb55a6 Mon Sep 17 00:00:00 2001 From: Johannes Dahlström Date: Mon, 21 May 2012 13:55:39 +0000 Subject: Removed an empty if() {} MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit svn changeset:23776/svn branch:6.8 --- src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java b/src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java index 9e65889f44..9aeeffe1f0 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java @@ -5426,8 +5426,6 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler, } break; case Event.ONMOUSEOUT: - if (targetCellOrRowFound) { - } break; default: break; -- cgit v1.2.3 From 12e35f034db98f5351c58c03b5277d4657e2ab28 Mon Sep 17 00:00:00 2001 From: Automerge Date: Mon, 21 May 2012 17:06:20 +0000 Subject: [merge from 6.7] Remove duplicate code in constructor svn changeset:23779/svn branch:6.8 --- src/com/vaadin/terminal/ClassResource.java | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/com/vaadin/terminal/ClassResource.java b/src/com/vaadin/terminal/ClassResource.java index fa196e90d9..e7419576f1 100644 --- a/src/com/vaadin/terminal/ClassResource.java +++ b/src/com/vaadin/terminal/ClassResource.java @@ -60,13 +60,7 @@ public class ClassResource implements ApplicationResource, Serializable { * the application this resource will be added to. */ public ClassResource(String resourceName, Application application) { - associatedClass = application.getClass(); - this.resourceName = resourceName; - this.application = application; - if (resourceName == null) { - throw new NullPointerException(); - } - application.addResource(this); + this(application.getClass(), resourceName, application); } /** -- cgit v1.2.3 From bec62403a7b56f093f5ee9829fea20ba3dee4628 Mon Sep 17 00:00:00 2001 From: Johannes Dahlström Date: Tue, 22 May 2012 11:24:41 +0000 Subject: #8724 Properly generate simulated click events from touch events on iOS 5 svn changeset:23784/svn branch:6.8 --- src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java b/src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java index 9aeeffe1f0..38c0ccce11 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java @@ -5088,6 +5088,7 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler, // is held in place long enough. showContextMenu(touchStart); event.preventDefault(); + touchStart = null; } } }; @@ -5134,6 +5135,10 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler, if (touchStart != null) { event.preventDefault(); event.stopPropagation(); + if (!BrowserInfo.get().isAndroid()) { + Util.simulateClickFromTouchEvent(touchStart, + this); + } touchStart = null; } isDragging = false; -- cgit v1.2.3 From e085efa41793fc68d455fa5d718bbfc1309296b9 Mon Sep 17 00:00:00 2001 From: Leif Åstrand Date: Tue, 22 May 2012 12:53:06 +0000 Subject: Make browser window size available in Window (#5655) svn changeset:23790/svn branch:6.8 --- src/com/vaadin/terminal/gwt/client/ui/VView.java | 31 +++++++------- src/com/vaadin/ui/Window.java | 49 ++++++++++++++++++++++ .../vaadin/tests/integration/EmbedSizeTest.java | 6 ++- 3 files changed, 68 insertions(+), 18 deletions(-) diff --git a/src/com/vaadin/terminal/gwt/client/ui/VView.java b/src/com/vaadin/terminal/gwt/client/ui/VView.java index ec4c5d9cba..e544a56190 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VView.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VView.java @@ -47,6 +47,10 @@ import com.vaadin.terminal.gwt.client.ui.ShortcutActionHandler.ShortcutActionHan public class VView extends SimplePanel implements Container, ResizeHandler, Window.ClosingHandler, ShortcutActionHandlerOwner, Focusable { + public static final String BROWSER_HEIGHT_VAR = "browserHeight"; + + public static final String BROWSER_WIDTH_VAR = "browserWidth"; + private static final String CLASSNAME = "v-view"; public static final String NOTIFICATION_HTML_CONTENT_NOT_ALLOWED = "useplain"; @@ -69,13 +73,6 @@ public class VView extends SimplePanel implements Container, ResizeHandler, private int windowWidth; private int windowHeight; - /* - * Last know view size used to detect whether new dimensions should be sent - * to the server. - */ - private int viewWidth; - private int viewHeight; - private ApplicationConnection connection; /** @@ -547,16 +544,18 @@ public class VView extends SimplePanel implements Container, ResizeHandler, */ private void sendClientResized() { Element parentElement = getElement().getParentElement(); - int newViewHeight = parentElement.getClientHeight(); - int newViewWidth = parentElement.getClientWidth(); + int viewHeight = parentElement.getClientHeight(); + int viewWidth = parentElement.getClientWidth(); - // Send the view dimensions if they have changed - if (newViewHeight != viewHeight || newViewWidth != viewWidth) { - viewHeight = newViewHeight; - viewWidth = newViewWidth; - connection.updateVariable(id, "height", newViewHeight, false); - connection.updateVariable(id, "width", newViewWidth, immediate); - } + connection.updateVariable(id, "height", viewHeight, false); + connection.updateVariable(id, "width", viewWidth, false); + + int windowWidth = Window.getClientWidth(); + int windowHeight = Window.getClientHeight(); + + connection.updateVariable(id, BROWSER_WIDTH_VAR, windowWidth, false); + connection.updateVariable(id, BROWSER_HEIGHT_VAR, windowHeight, + immediate); } public native static void goTo(String url) diff --git a/src/com/vaadin/ui/Window.java b/src/com/vaadin/ui/Window.java index 5f6c29f182..f20090fead 100644 --- a/src/com/vaadin/ui/Window.java +++ b/src/com/vaadin/ui/Window.java @@ -223,6 +223,10 @@ public class Window extends Panel implements URIHandler, ParameterHandler, */ private Component scrollIntoView; + private int browserWindowWidth = -1; + + private int browserWindowHeight = -1; + /** * Creates a new unnamed window with a default layout. */ @@ -1081,6 +1085,20 @@ public class Window extends Panel implements URIHandler, ParameterHandler, .get("width") != getWidth())) { sizeHasChanged = true; } + Integer browserHeightVar = (Integer) variables + .get(VView.BROWSER_HEIGHT_VAR); + if (browserHeightVar != null + && browserHeightVar.intValue() != browserWindowHeight) { + browserWindowHeight = browserHeightVar.intValue(); + sizeHasChanged = true; + } + Integer browserWidthVar = (Integer) variables + .get(VView.BROWSER_WIDTH_VAR); + if (browserWidthVar != null + && browserWidthVar.intValue() != browserWindowWidth) { + browserWindowWidth = browserWidthVar.intValue(); + sizeHasChanged = true; + } super.changeVariables(source, variables); @@ -2380,4 +2398,35 @@ public class Window extends Panel implements URIHandler, ParameterHandler, } } + /** + * Gets the height of the viewport area of the browser window where this + * window is displayed. + * + * @return the browser viewport height in pixels + */ + public int getBrowserWindowHeight() { + // Size only reported by VView -> data only available from application + // level window + if (getParent() != null) { + return (getParent()).getBrowserWindowHeight(); + } + + return browserWindowHeight; + } + + /** + * Gets the width of the viewport area of the browser window where this + * window is displayed. + * + * @return the browser viewport width in pixels + */ + public int getBrowserWindowWidth() { + // Size only reported by VView -> data only available from application + // level window + if (getParent() != null) { + return (getParent()).getBrowserWindowWidth(); + } + + return browserWindowWidth; + } } diff --git a/tests/testbench/com/vaadin/tests/integration/EmbedSizeTest.java b/tests/testbench/com/vaadin/tests/integration/EmbedSizeTest.java index 479af4aa87..3524b3fce3 100644 --- a/tests/testbench/com/vaadin/tests/integration/EmbedSizeTest.java +++ b/tests/testbench/com/vaadin/tests/integration/EmbedSizeTest.java @@ -36,8 +36,10 @@ public class EmbedSizeTest extends TestBase { mainWindow.addListener(new Window.ResizeListener() { public void windowResized(ResizeEvent e) { Window window = e.getWindow(); - log.log("Resize event: " + window.getWidth() + " x " - + window.getHeight()); + log.log("App: " + window.getWidth() + " x " + + window.getHeight() + ", Browser window: " + + window.getBrowserWindowWidth() + " x " + + window.getBrowserWindowHeight()); } }); } -- cgit v1.2.3 From e1d2b8f1797e9e373161cfc7658b1e5386f98125 Mon Sep 17 00:00:00 2001 From: Artur Signell Date: Tue, 22 May 2012 16:03:50 +0300 Subject: Made it possible to override the type of wrapped request used in portals --- .../gwt/server/AbstractApplicationPortlet.java | 47 +++++++++++++--------- 1 file changed, 29 insertions(+), 18 deletions(-) diff --git a/src/com/vaadin/terminal/gwt/server/AbstractApplicationPortlet.java b/src/com/vaadin/terminal/gwt/server/AbstractApplicationPortlet.java index 1acc9d128a..5b2be308a3 100644 --- a/src/com/vaadin/terminal/gwt/server/AbstractApplicationPortlet.java +++ b/src/com/vaadin/terminal/gwt/server/AbstractApplicationPortlet.java @@ -67,7 +67,7 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet private static final Logger logger = Logger .getLogger(AbstractApplicationPortlet.class.getName()); - private static class WrappedHttpAndPortletRequest extends + public static class WrappedHttpAndPortletRequest extends WrappedPortletRequest { public WrappedHttpAndPortletRequest(PortletRequest request, @@ -112,7 +112,7 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet } } - private static class WrappedGateinRequest extends + public static class WrappedGateinRequest extends WrappedHttpAndPortletRequest { public WrappedGateinRequest(PortletRequest request, DeploymentConfiguration deploymentConfiguration) { @@ -134,7 +134,7 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet } } - private static class WrappedLiferayRequest extends + public static class WrappedLiferayRequest extends WrappedHttpAndPortletRequest { public WrappedLiferayRequest(PortletRequest request, @@ -169,7 +169,7 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet } - private static class AbstractApplicationPortletWrapper implements Callback { + public static class AbstractApplicationPortletWrapper implements Callback { private final AbstractApplicationPortlet portlet; @@ -500,20 +500,7 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet AbstractApplicationPortletWrapper portletWrapper = new AbstractApplicationPortletWrapper( this); - WrappedPortletRequest wrappedRequest; - - String portalInfo = request.getPortalContext().getPortalInfo() - .toLowerCase(); - if (portalInfo.contains("liferay")) { - wrappedRequest = new WrappedLiferayRequest(request, - getDeploymentConfiguration()); - } else if (portalInfo.contains("gatein")) { - wrappedRequest = new WrappedGateinRequest(request, - getDeploymentConfiguration()); - } else { - wrappedRequest = new WrappedPortletRequest(request, - getDeploymentConfiguration()); - } + WrappedPortletRequest wrappedRequest = createWrappedRequest(request); WrappedPortletResponse wrappedResponse = new WrappedPortletResponse( response, getDeploymentConfiguration()); @@ -712,6 +699,30 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet } } + /** + * Wraps the request in a (possibly portal specific) wrapped portlet + * request. + * + * @param request + * The original PortletRequest + * @return A wrapped version of the PorletRequest + */ + protected WrappedPortletRequest createWrappedRequest(PortletRequest request) { + String portalInfo = request.getPortalContext().getPortalInfo() + .toLowerCase(); + if (portalInfo.contains("liferay")) { + return new WrappedLiferayRequest(request, + getDeploymentConfiguration()); + } else if (portalInfo.contains("gatein")) { + return new WrappedGateinRequest(request, + getDeploymentConfiguration()); + } else { + return new WrappedPortletRequest(request, + getDeploymentConfiguration()); + } + + } + private DeploymentConfiguration getDeploymentConfiguration() { return deploymentConfiguration; } -- cgit v1.2.3 From e7f31596e7a13c297988ec5c687e1b681420b243 Mon Sep 17 00:00:00 2001 From: Leif Åstrand Date: Tue, 22 May 2012 13:07:32 +0000 Subject: Remove clientHeight/Width from WebBrowser (#5655) svn changeset:23792/svn branch:6.8 --- .../gwt/server/AbstractApplicationPortlet.java | 2 - .../gwt/server/AbstractApplicationServlet.java | 3 +- src/com/vaadin/terminal/gwt/server/WebBrowser.java | 44 ++-------------------- .../tests/application/WebBrowserSizeTest.java | 6 ++- 4 files changed, 8 insertions(+), 47 deletions(-) diff --git a/src/com/vaadin/terminal/gwt/server/AbstractApplicationPortlet.java b/src/com/vaadin/terminal/gwt/server/AbstractApplicationPortlet.java index 2ac574c2de..0a8e9530f0 100644 --- a/src/com/vaadin/terminal/gwt/server/AbstractApplicationPortlet.java +++ b/src/com/vaadin/terminal/gwt/server/AbstractApplicationPortlet.java @@ -578,8 +578,6 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet browser.updateClientSideDetails( getHTTPRequestParameter(request, "sw"), getHTTPRequestParameter(request, "sh"), - getHTTPRequestParameter(request, "cw"), - getHTTPRequestParameter(request, "ch"), getHTTPRequestParameter(request, "tzo"), getHTTPRequestParameter(request, "rtzo"), getHTTPRequestParameter(request, "dstd"), diff --git a/src/com/vaadin/terminal/gwt/server/AbstractApplicationServlet.java b/src/com/vaadin/terminal/gwt/server/AbstractApplicationServlet.java index 68089e18e0..54ea4a94ed 100644 --- a/src/com/vaadin/terminal/gwt/server/AbstractApplicationServlet.java +++ b/src/com/vaadin/terminal/gwt/server/AbstractApplicationServlet.java @@ -603,8 +603,7 @@ public abstract class AbstractApplicationServlet extends HttpServlet implements request.getHeader("user-agent")); if (request.getParameter("repaintAll") != null) { browser.updateClientSideDetails(request.getParameter("sw"), - request.getParameter("sh"), request.getParameter("cw"), - request.getParameter("ch"), request.getParameter("tzo"), + request.getParameter("sh"), request.getParameter("tzo"), request.getParameter("rtzo"), request.getParameter("dstd"), request.getParameter("dston"), request.getParameter("curdate"), diff --git a/src/com/vaadin/terminal/gwt/server/WebBrowser.java b/src/com/vaadin/terminal/gwt/server/WebBrowser.java index a57a4c65d2..9182ebdc03 100644 --- a/src/com/vaadin/terminal/gwt/server/WebBrowser.java +++ b/src/com/vaadin/terminal/gwt/server/WebBrowser.java @@ -22,8 +22,6 @@ public class WebBrowser implements Terminal { private int screenHeight = 0; private int screenWidth = 0; - private int clientHeight = 0; - private int clientWidth = 0; private String browserApplication = null; private Locale locale; private String address; @@ -64,30 +62,6 @@ public class WebBrowser implements Terminal { return screenWidth; } - /** - * Gets the height of the client (browser window). - *

- * Note that the client size is only updated on a full repaint, not when the - * browser window size changes - * - * @return The height of the client or 0 if unknown. - */ - public int getClientHeight() { - return clientHeight; - } - - /** - * Gets the width of the client (browser window) - *

- * Note that the client size is only updated on a full repaint, not when the - * browser window size changes - * - * @return The width of the client or 0 if unknown. - */ - public int getClientWidth() { - return clientWidth; - } - /** * Get the browser user-agent string. * @@ -338,10 +312,6 @@ public class WebBrowser implements Terminal { * Screen width * @param sh * Screen height - * @param cw - * Client width - * @param ch - * Client height * @param tzo * TimeZone offset in minutes from GMT * @param rtzo @@ -354,9 +324,9 @@ public class WebBrowser implements Terminal { * the current date in milliseconds since the epoch * @param touchDevice */ - void updateClientSideDetails(String sw, String sh, String cw, String ch, - String tzo, String rtzo, String dstSavings, String dstInEffect, - String curDate, boolean touchDevice) { + void updateClientSideDetails(String sw, String sh, String tzo, String rtzo, + String dstSavings, String dstInEffect, String curDate, + boolean touchDevice) { if (sw != null) { try { screenHeight = Integer.parseInt(sh); @@ -365,14 +335,6 @@ public class WebBrowser implements Terminal { screenHeight = screenWidth = 0; } } - if (cw != null) { - try { - clientHeight = Integer.parseInt(ch); - clientWidth = Integer.parseInt(cw); - } catch (final NumberFormatException e) { - clientHeight = clientWidth = 0; - } - } if (tzo != null) { try { // browser->java conversion: min->ms, reverse sign diff --git a/tests/testbench/com/vaadin/tests/application/WebBrowserSizeTest.java b/tests/testbench/com/vaadin/tests/application/WebBrowserSizeTest.java index eacf2a0e53..a3f11f2cd3 100644 --- a/tests/testbench/com/vaadin/tests/application/WebBrowserSizeTest.java +++ b/tests/testbench/com/vaadin/tests/application/WebBrowserSizeTest.java @@ -21,8 +21,10 @@ public class WebBrowserSizeTest extends TestBase { public void buttonClick(ClickEvent event) { screenSizeLabel.setValue(getBrowser().getScreenWidth() + " x " + getBrowser().getScreenHeight()); - browserSizeLabel.setValue(getBrowser().getClientWidth() + " x " - + getBrowser().getClientHeight()); + browserSizeLabel.setValue(getMainWindow() + .getBrowserWindowWidth() + + " x " + + getMainWindow().getBrowserWindowHeight()); } }); -- cgit v1.2.3 From 375f737133f4852559bf9b841fd27bc31795975e Mon Sep 17 00:00:00 2001 From: Artur Signell Date: Tue, 22 May 2012 13:57:52 +0000 Subject: [merge from 6.7] Chrome 18 -> 19 (#8835) svn changeset:23800/svn branch:6.8 --- tests/test.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test.xml b/tests/test.xml index acbbe672ef..7b2b283fc6 100644 --- a/tests/test.xml +++ b/tests/test.xml @@ -5,7 +5,7 @@ - + -- cgit v1.2.3 From 35b979139f4fbb6e6bbc19728951277adce394b7 Mon Sep 17 00:00:00 2001 From: Automerge Date: Tue, 22 May 2012 17:07:33 +0000 Subject: [merge from 6.7] #8305 extend Liferay session when the user interacts with a Vaadin portlet svn changeset:23802/svn branch:6.8 --- .../terminal/gwt/client/ApplicationConnection.java | 27 ++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java b/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java index dcf52827ed..4448c047c2 100644 --- a/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java +++ b/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java @@ -330,6 +330,25 @@ public class ApplicationConnection { } }-*/; + /** + * If on Liferay and logged in, ask the client side session management + * JavaScript to extend the session duration. + * + * Otherwise, Liferay client side JavaScript will explicitly expire the + * session even though the server side considers the session to be active. + * See ticket #8305 for more information. + */ + protected native void extendLiferaySession() + /*-{ + if ($wnd.Liferay && $wnd.Liferay.Session) { + $wnd.Liferay.Session.extend(); + // if the extend banner is visible, hide it + if ($wnd.Liferay.Session.banner) { + $wnd.Liferay.Session.banner.remove(); + } + } + }-*/; + /** * Get the active Console for writing debug messages. May return an actual * logging console, or the NullConsole if debugging is not turned on. @@ -819,6 +838,14 @@ public class ApplicationConnection { public void execute() { if (!hasActiveRequest()) { hideLoadingIndicator(); + + // If on Liferay and session expiration management is in + // use, extend session duration on each request. + // Doing it here rather than before the request to improve + // responsiveness. + // Postponed until the end of the next request if other + // requests still pending. + extendLiferaySession(); } } }); -- cgit v1.2.3 From 9fc49aeb7640a4a63183c08b8c406da4839ec414 Mon Sep 17 00:00:00 2001 From: Automerge Date: Tue, 22 May 2012 17:07:38 +0000 Subject: [merge from 6.7] Removed book tagging. svn changeset:23803/svn branch:6.8 --- build/bin/tagrelease.py | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/build/bin/tagrelease.py b/build/bin/tagrelease.py index 0101ecdbd6..871d34515e 100644 --- a/build/bin/tagrelease.py +++ b/build/bin/tagrelease.py @@ -42,7 +42,7 @@ def readProperties(filename): def helpAndExit(): print "Usage: build/bin/tagrelease [parameters...]" print "Commands:" - print "\ttag " + print "\ttag " sys.exit(1) ############################################################################### @@ -77,7 +77,7 @@ def tag(product, srcUrl, trgUrl, version, changeset, dryrun = 1): ############################################################################### # Tag command ############################################################################### -def tagCommand(version, changeset, bookRepo): +def tagCommand(version, changeset): # Check parameters m = re.match(r'^[0-9]+\.[0-9]+\.[0-9]+(\.\w+)?$', version) if not m: @@ -94,19 +94,11 @@ def tagCommand(version, changeset, bookRepo): repoRoot = svnInfo["Repository Root"] tagUrl = repoRoot+"/releases/"+version - # Book tag parameters - if (not re.search(r'branches/[0-9\.]+$', bookRepo)) and (not re.search(r'doc/trunk$', bookRepo)): - print "Bad documentation branch '%s' for release." % (bookRepo) - sys.exit(1) - bookTagUrl = repoRoot+"/doc/tags/"+version - # Check that neither tag exists checkNotTagged(tagUrl) - checkNotTagged(bookTagUrl) # Do the tagging tag("Vaadin", url, tagUrl, version, changeset) - tag("Book of Vaadin", bookRepo, bookTagUrl, version, changeset) ############################################################################### # Verify command @@ -132,8 +124,8 @@ def verifyCommand(version, changeset): if len(sys.argv) < 2: helpAndExit() -if sys.argv[1] == "tag" and len(sys.argv) == 5: - tagCommand(sys.argv[2], sys.argv[3], sys.argv[4]) +if sys.argv[1] == "tag" and len(sys.argv) == 4: + tagCommand(sys.argv[2], sys.argv[3]) elif sys.argv[1] == "verify" and len(sys.argv) == 4: verifyCommand(sys.argv[2], sys.argv[3]) else: -- cgit v1.2.3 From e8844544fcf3f62e9b8a9226e235b90a7106d881 Mon Sep 17 00:00:00 2001 From: Automerge Date: Tue, 22 May 2012 17:07:43 +0000 Subject: [merge from 6.7] Recalculate column widths if scrollbar has changed (#6039) svn changeset:23804/svn branch:6.8 --- src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java b/src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java index 38c0ccce11..39492d8731 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java @@ -2112,6 +2112,9 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler, return true; } } else { + if (scrollBody == null) { + return false; + } int fakeheight = (int) Math.round(scrollBody.getRowHeight() * totalRows); int availableHeight = scrollBodyPanel.getElement().getPropertyInt( @@ -6213,10 +6216,15 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler, @Override public void setHeight(String height) { + boolean hadScrollbars = willHaveScrollbars(); this.height = height; super.setHeight(height); setContainerHeight(); + if (hadScrollbars != willHaveScrollbars()) { + triggerLazyColumnAdjustment(true); + } + if (initializedAndAttached) { updatePageLength(); } -- cgit v1.2.3 From e8a652c91e9e02079180a854789afd5accffce7b Mon Sep 17 00:00:00 2001 From: Leif Åstrand Date: Wed, 23 May 2012 08:06:06 +0000 Subject: Table: Make some columns uncollapsable (#7495) svn changeset:23811/svn branch:6.8 --- .../terminal/gwt/client/ui/VScrollTable.java | 27 ++++++- src/com/vaadin/ui/Table.java | 46 ++++++++++++ .../table/TableWithNoncollapsibleColumns.html | 82 +++++++++++++++++++++ .../table/TableWithNoncollapsibleColumns.java | 83 ++++++++++++++++++++++ .../com/vaadin/tests/components/table/Tables.java | 11 +++ 5 files changed, 247 insertions(+), 2 deletions(-) create mode 100644 tests/testbench/com/vaadin/tests/components/table/TableWithNoncollapsibleColumns.html create mode 100644 tests/testbench/com/vaadin/tests/components/table/TableWithNoncollapsibleColumns.java diff --git a/src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java b/src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java index 39492d8731..c5ca16925b 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java @@ -214,6 +214,8 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler, .isTouchDevice() && !BrowserInfo.get().requiresTouchScrollDelegate(); + private Set noncollapsibleColumns; + /** * Represents a select range of rows */ @@ -1086,6 +1088,10 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler, updateHeader(uidl.getStringArrayAttribute("vcolorder")); updateFooter(uidl.getStringArrayAttribute("vcolorder")); + if (uidl.hasVariable("noncollapsiblecolumns")) { + noncollapsibleColumns = uidl + .getStringArrayVariableAsSet("noncollapsiblecolumns"); + } } private void updateCollapsedColumns(UIDL uidl) { @@ -3244,6 +3250,7 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler, String colKey; private boolean collapsed; + private boolean noncollapsible = false; private VScrollTableRow currentlyFocusedRow; public VisibleColumnAction(String colKey) { @@ -3255,6 +3262,9 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler, @Override public void execute() { + if (noncollapsible) { + return; + } client.getContextMenu().hide(); // toggle selected column if (collapsedColumns.contains(colKey)) { @@ -3278,17 +3288,27 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler, collapsed = b; } + public void setNoncollapsible(boolean b) { + noncollapsible = b; + } + /** * Override default method to distinguish on/off columns */ @Override public String getHTML() { final StringBuffer buf = new StringBuffer(); + buf.append(""); + buf.append("v-off"); } else { - buf.append(""); + buf.append("v-on"); + } + if (noncollapsible) { + buf.append(" v-disabled"); } + buf.append("\">"); + buf.append(super.getHTML()); buf.append(""); @@ -3330,6 +3350,9 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler, if (!c.isEnabled()) { a.setCollapsed(true); } + if (noncollapsibleColumns.contains(cid)) { + a.setNoncollapsible(true); + } actions[i] = a; } return actions; diff --git a/src/com/vaadin/ui/Table.java b/src/com/vaadin/ui/Table.java index db0809fbd5..a2db89cabb 100644 --- a/src/com/vaadin/ui/Table.java +++ b/src/com/vaadin/ui/Table.java @@ -229,6 +229,11 @@ public class Table extends AbstractSelect implements Action.Container, */ private LinkedList visibleColumns = new LinkedList(); + /** + * Holds noncollapsible columns. + */ + private HashSet noncollapsibleColumns = new HashSet(); + /** * Holds propertyIds of currently collapsed columns. */ @@ -1139,6 +1144,9 @@ public class Table extends AbstractSelect implements Action.Container, if (!isColumnCollapsingAllowed()) { throw new IllegalStateException("Column collapsing not allowed!"); } + if (collapsed && noncollapsibleColumns.contains(propertyId)) { + throw new IllegalStateException("The column is noncollapsible!"); + } if (collapsed) { collapsedColumns.add(propertyId); @@ -1177,6 +1185,34 @@ public class Table extends AbstractSelect implements Action.Container, refreshRenderedCells(); } + /** + * Sets whether a column can be collapsed or not. + * + * @param propertyId + * the propertyID identifying the column. + * @param collapsible + * the desired collapsibleness + */ + public void setColumnNoncollapsible(Object propertyId, + boolean noncollapsible) { + if (noncollapsible) { + noncollapsibleColumns.add(propertyId); + collapsedColumns.remove(propertyId); + } else { + noncollapsibleColumns.remove(propertyId); + } + refreshRowCache(); + } + + /** + * Checks if the column can be collapsed. + * + * @return true if the column can be collapsed; false otherwise. + */ + public boolean isColumnNoncollapsible(Object propertyId) { + return noncollapsibleColumns.contains(propertyId); + } + /** * Checks if column reordering is allowed. * @@ -2996,7 +3032,17 @@ public class Table extends AbstractSelect implements Action.Container, } } target.addVariable(this, "collapsedcolumns", collapsedKeys); + + final String[] noncollapsibleKeys = new String[noncollapsibleColumns + .size()]; + nextColumn = 0; + for (Object colId : noncollapsibleColumns) { + noncollapsibleKeys[nextColumn++] = columnIdMap.key(colId); + } + target.addVariable(this, "noncollapsiblecolumns", + noncollapsibleKeys); } + } private void paintActions(PaintTarget target, final Set actionSet) diff --git a/tests/testbench/com/vaadin/tests/components/table/TableWithNoncollapsibleColumns.html b/tests/testbench/com/vaadin/tests/components/table/TableWithNoncollapsibleColumns.html new file mode 100644 index 0000000000..e3c9a8423b --- /dev/null +++ b/tests/testbench/com/vaadin/tests/components/table/TableWithNoncollapsibleColumns.html @@ -0,0 +1,82 @@ + + + + + + +TableWithNoncollapsibleColumns + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
TableWithNoncollapsibleColumns
open/run/com.vaadin.tests.components.table.TableWithNoncollapsibleColumns?restartApplication
clickvaadin=runcomvaadintestscomponentstableTableWithNoncollapsibleColumns::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VVerticalLayout[0]/ChildComponentContainer[3]/VButton[0]/domChild[0]/domChild[0]
screenCapturecolumn-3-collapsed
clickvaadin=runcomvaadintestscomponentstableTableWithNoncollapsibleColumns::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VVerticalLayout[0]/ChildComponentContainer[4]/VButton[0]/domChild[0]/domChild[0]
screenCapturecolumn-3-noncollapsible
clickvaadin=runcomvaadintestscomponentstableTableWithNoncollapsibleColumns::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VVerticalLayout[0]/ChildComponentContainer[1]/VButton[0]/domChild[0]/domChild[0]
clickvaadin=runcomvaadintestscomponentstableTableWithNoncollapsibleColumns::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VVerticalLayout[0]/ChildComponentContainer[2]/VButton[0]/domChild[0]/domChild[0]
clickvaadin=runcomvaadintestscomponentstableTableWithNoncollapsibleColumns::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VVerticalLayout[0]/ChildComponentContainer[3]/VButton[0]/domChild[0]/domChild[0]
mouseClickvaadin=runcomvaadintestscomponentstableTableWithNoncollapsibleColumns::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VVerticalLayout[0]/ChildComponentContainer[0]/VScrollTable[0]/domChild[0]/domChild[1]9,7
screenCapturecolumn-menu-after-collapsing-all-columns
mouseClickvaadin=runcomvaadintestscomponentstableTableWithNoncollapsibleColumns::Root/VContextMenu[0]#option293,4
mouseClickvaadin=runcomvaadintestscomponentstableTableWithNoncollapsibleColumns::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VVerticalLayout[0]/ChildComponentContainer[0]/VScrollTable[0]/domChild[0]/domChild[1]7,10
screenCapturecolumn-menu-after-expanding-column-2
+ + diff --git a/tests/testbench/com/vaadin/tests/components/table/TableWithNoncollapsibleColumns.java b/tests/testbench/com/vaadin/tests/components/table/TableWithNoncollapsibleColumns.java new file mode 100644 index 0000000000..9e8c201452 --- /dev/null +++ b/tests/testbench/com/vaadin/tests/components/table/TableWithNoncollapsibleColumns.java @@ -0,0 +1,83 @@ +package com.vaadin.tests.components.table; + +import com.vaadin.tests.components.TestBase; +import com.vaadin.ui.Button; +import com.vaadin.ui.Button.ClickEvent; +import com.vaadin.ui.Table; +import com.vaadin.ui.VerticalLayout; + +public class TableWithNoncollapsibleColumns extends TestBase { + + @Override + protected void setup() { + VerticalLayout layout = new VerticalLayout(); + layout.setSizeFull(); + addComponent(layout); + + final Table table = new Table(); + table.setWidth("100%"); + table.setHeight("300px"); + table.setColumnCollapsingAllowed(true); + + table.addContainerProperty("Column 1 - noncollapsible", String.class, + null); + table.addContainerProperty("Column 2 - collapsible", String.class, null); + table.addContainerProperty("Column 3 - toggle collapsing", + String.class, null); + + table.setColumnNoncollapsible("Column 1 - noncollapsible", true); + layout.addComponent(table); + + final Button button1 = new Button("Column 1: collapse/show", + new Button.ClickListener() { + public void buttonClick(ClickEvent event) { + table.setColumnCollapsed( + "Column 1 - noncollapsible", + !table.isColumnCollapsed("Column 1 - noncollapsible")); + } + }); + final Button button2 = new Button("Column 2: collapse/show", + new Button.ClickListener() { + public void buttonClick(ClickEvent event) { + table.setColumnCollapsed( + "Column 2 - collapsible", + !table.isColumnCollapsed("Column 2 - collapsible")); + } + }); + + final Button button3 = new Button("Column 3: collapse/show", + new Button.ClickListener() { + public void buttonClick(ClickEvent event) { + table.setColumnCollapsed( + "Column 3 - toggle collapsing", + !table.isColumnCollapsed("Column 3 - toggle collapsing")); + } + }); + final Button button4 = new Button( + "Column 3: make noncollapsible/collapsible", + new Button.ClickListener() { + public void buttonClick(ClickEvent event) { + table.setColumnNoncollapsible( + "Column 3 - toggle collapsing", + !table.isColumnNoncollapsible("Column 3 - toggle collapsing")); + } + }); + + layout.addComponent(button1); + layout.addComponent(button2); + layout.addComponent(button3); + layout.addComponent(button4); + + } + + @Override + protected String getDescription() { + return "Often a table has one column that identifies the row better than any other and it would not make sense to collapse that one. Make it possible from the server side api to disable collapsing for some properties. These properties could appear as grayed out in the collapse drop down menu."; + } + + @Override + protected Integer getTicketNumber() { + return 7495; + } + +} diff --git a/tests/testbench/com/vaadin/tests/components/table/Tables.java b/tests/testbench/com/vaadin/tests/components/table/Tables.java index 3f37a178b6..5c55ea87b2 100644 --- a/tests/testbench/com/vaadin/tests/components/table/Tables.java +++ b/tests/testbench/com/vaadin/tests/components/table/Tables.java @@ -73,6 +73,14 @@ public class Tables extends AbstractSelectTestCase } }; + private Command columnNonCollapsibleCommand = new Command() { + + public void execute(T c, Boolean noncollapsible, Object propertyId) { + c.setColumnNoncollapsible(propertyId, noncollapsible); + + } + }; + protected Command columnResizeListenerCommand = new Command() { public void execute(Table c, Boolean value, Object data) { @@ -644,6 +652,9 @@ public class Tables extends AbstractSelectTestCase createSelectAction("Expand ratio", category, expandOptions, "- remove -", columnExpandRatioCommand, propertyId); t.log("Expand"); + createBooleanAction("Noncollapsible", category, false, + columnNonCollapsibleCommand, propertyId); + // Footer text (move) // Header text (move) -- cgit v1.2.3 From edf451f67f4d50d5baeb4ae9ceaa6746eb6fa10c Mon Sep 17 00:00:00 2001 From: Tapio Aali Date: Wed, 23 May 2012 09:01:22 +0000 Subject: Fixed styles that were left lingering while changing the orientation of a slider (#7002). svn changeset:23813/svn branch:6.8 --- src/com/vaadin/terminal/gwt/client/ui/VSlider.java | 11 +++- .../tests/components/slider/SliderOrientation.html | 72 ++++++++++++++++++++++ 2 files changed, 82 insertions(+), 1 deletion(-) create mode 100644 tests/testbench/com/vaadin/tests/components/slider/SliderOrientation.html diff --git a/src/com/vaadin/terminal/gwt/client/ui/VSlider.java b/src/com/vaadin/terminal/gwt/client/ui/VSlider.java index 4a46346613..e605c6fe12 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VSlider.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VSlider.java @@ -200,8 +200,12 @@ public class VSlider extends SimpleFocusablePanel implements Paintable, Field, private void buildBase() { final String styleAttribute = vertical ? "height" : "width"; + final String oppositeStyleAttribute = vertical ? "width" : "height"; final String domProperty = vertical ? "offsetHeight" : "offsetWidth"; + // clear unnecessary opposite style attribute + DOM.setStyleAttribute(base, oppositeStyleAttribute, ""); + final Element p = DOM.getParent(getElement()); if (DOM.getElementPropertyInt(p, domProperty) > 50) { if (vertical) { @@ -235,10 +239,15 @@ public class VSlider extends SimpleFocusablePanel implements Paintable, Field, private void buildHandle() { final String styleAttribute = vertical ? "height" : "width"; final String handleAttribute = vertical ? "marginTop" : "marginLeft"; + final String oppositeHandleAttribute = vertical ? "marginLeft" + : "marginTop"; final String domProperty = vertical ? "offsetHeight" : "offsetWidth"; DOM.setStyleAttribute(handle, handleAttribute, "0"); + // clear unnecessary opposite handle attribute + DOM.setStyleAttribute(handle, oppositeHandleAttribute, ""); + if (scrollbarStyle) { // Only stretch the handle if scrollbar style is set. int s = (int) (Double.parseDouble(DOM.getElementProperty(base, @@ -356,7 +365,7 @@ public class VSlider extends SimpleFocusablePanel implements Paintable, Field, } else if (DOM.eventGetType(event) == Event.ONMOUSEDOWN) { feedbackPopup.show(); } - if(Util.isTouchEvent(event)) { + if (Util.isTouchEvent(event)) { event.preventDefault(); // avoid simulated events event.stopPropagation(); } diff --git a/tests/testbench/com/vaadin/tests/components/slider/SliderOrientation.html b/tests/testbench/com/vaadin/tests/components/slider/SliderOrientation.html new file mode 100644 index 0000000000..174ddca016 --- /dev/null +++ b/tests/testbench/com/vaadin/tests/components/slider/SliderOrientation.html @@ -0,0 +1,72 @@ + + + + + + +SliderOrientation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
SliderOrientation
open/run/com.vaadin.tests.components.slider.SliderTest?restartApplication
mouseClickvaadin=runcomvaadintestscomponentssliderSliderTest::PID_Smenu#item05,6
mouseClickvaadin=runcomvaadintestscomponentssliderSliderTest::Root/VOverlay[0]/VMenuBar[0]#item441,7
mouseClickvaadin=runcomvaadintestscomponentssliderSliderTest::Root/VOverlay[1]/VMenuBar[0]#item337,3
mouseClickvaadin=runcomvaadintestscomponentssliderSliderTest::Root/VOverlay[2]/VMenuBar[0]#item119,7
screenCapturechange-orientation-to-vertical
mouseClickvaadin=runcomvaadintestscomponentssliderSliderTest::PID_Smenu#item033,1
mouseClickvaadin=runcomvaadintestscomponentssliderSliderTest::Root/VOverlay[0]/VMenuBar[0]#item463,11
mouseClickvaadin=runcomvaadintestscomponentssliderSliderTest::Root/VOverlay[1]/VMenuBar[0]#item330,1
mouseClickvaadin=runcomvaadintestscomponentssliderSliderTest::Root/VOverlay[2]/VMenuBar[0]#item010,10
screenCapturechange-orientation-to-horizontal
+ + -- cgit v1.2.3 From 4c5e0b8043c682c0a3d552e0ecaa39c7c52b44fa Mon Sep 17 00:00:00 2001 From: Automerge Date: Wed, 23 May 2012 13:08:48 +0000 Subject: [merge from 6.7] Print more debug info when running testbench tests svn changeset:23816/svn branch:6.8 --- tests/test.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/test.xml b/tests/test.xml index 7b2b283fc6..3964573d89 100644 --- a/tests/test.xml +++ b/tests/test.xml @@ -148,6 +148,8 @@ + + -- cgit v1.2.3 From b02102fe98227562f986d421abc999049dfa405d Mon Sep 17 00:00:00 2001 From: Automerge Date: Wed, 23 May 2012 17:07:08 +0000 Subject: [merge from 6.7] Test application for #8855 svn changeset:23818/svn branch:6.8 --- .../components/gridlayout/GridLayoutInForm.java | 78 ++++++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 tests/testbench/com/vaadin/tests/components/gridlayout/GridLayoutInForm.java diff --git a/tests/testbench/com/vaadin/tests/components/gridlayout/GridLayoutInForm.java b/tests/testbench/com/vaadin/tests/components/gridlayout/GridLayoutInForm.java new file mode 100644 index 0000000000..648bbd2d52 --- /dev/null +++ b/tests/testbench/com/vaadin/tests/components/gridlayout/GridLayoutInForm.java @@ -0,0 +1,78 @@ +package com.vaadin.tests.components.gridlayout; + +import java.util.ArrayList; +import java.util.List; + +import com.vaadin.data.util.ObjectProperty; +import com.vaadin.data.util.PropertysetItem; +import com.vaadin.tests.components.TestBase; +import com.vaadin.ui.Button; +import com.vaadin.ui.Button.ClickEvent; +import com.vaadin.ui.Form; +import com.vaadin.ui.GridLayout; +import com.vaadin.ui.Panel; + +public class GridLayoutInForm extends TestBase { + + @Override + protected void setup() { + final List propertyIds = new ArrayList(); + for (int i = 0; i < 50; i++) { + propertyIds.add("property " + i); + } + + GridLayout gridLayout = new GridLayout(); + gridLayout.setSizeUndefined(); + gridLayout.setColumns(2); + gridLayout.setSpacing(true); + + PropertysetItem item = new PropertysetItem(); + for (String propertyId : propertyIds) { + item.addItemProperty(propertyId, new ObjectProperty( + propertyId)); + } + + final Form form = new Form(gridLayout); + form.setItemDataSource(item); + + form.setSizeUndefined(); + + Panel panel = new Panel(); + panel.addComponent(form); + panel.setHeight("500px"); + + addComponent(panel); + + addComponent(new Button("Use 15 first fields", + new Button.ClickListener() { + public void buttonClick(ClickEvent event) { + form.setVisibleItemProperties(propertyIds + .subList(0, 15)); + } + })); + addComponent(new Button("Use 15 last fields", + new Button.ClickListener() { + public void buttonClick(ClickEvent event) { + form.setVisibleItemProperties(propertyIds.subList(35, + 50)); + } + })); + + addComponent(new Button("Use all fields", new Button.ClickListener() { + public void buttonClick(ClickEvent event) { + form.setVisibleItemProperties(propertyIds); + } + })); + } + + @Override + protected String getDescription() { + return "Changing the number of visible fields in a Form using a GridLayout with spacing should not cause additional empty space in the end of the GridLayout"; + } + + @Override + protected Integer getTicketNumber() { + return Integer.valueOf(8855); + } + +} -- cgit v1.2.3 From cb20a6b202937c4b2fa96cc23db6cf4301097203 Mon Sep 17 00:00:00 2001 From: Henri Sara Date: Thu, 24 May 2012 09:53:02 +0000 Subject: Merged VView changes to 6.8 (#8799). svn changeset:23820/svn branch:6.8 --- src/com/vaadin/terminal/gwt/client/ui/VView.java | 121 ++++++++++++++++++----- 1 file changed, 99 insertions(+), 22 deletions(-) diff --git a/src/com/vaadin/terminal/gwt/client/ui/VView.java b/src/com/vaadin/terminal/gwt/client/ui/VView.java index e544a56190..350c4b206b 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VView.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VView.java @@ -55,6 +55,8 @@ public class VView extends SimplePanel implements Container, ResizeHandler, public static final String NOTIFICATION_HTML_CONTENT_NOT_ALLOWED = "useplain"; + private static int MONITOR_PARENT_TIMER_INTERVAL = 1000; + private String theme; private Paintable layout; @@ -67,8 +69,8 @@ public class VView extends SimplePanel implements Container, ResizeHandler, /* * Last known window size used to detect whether VView should be layouted - * again. Detection must be based on window size, because the VView size - * might be fixed and thus not automatically adapt to changed window sizes. + * again. Detection must check window size, because the VView size might be + * fixed and thus not automatically adapt to changed window sizes. */ private int windowWidth; private int windowHeight; @@ -76,13 +78,19 @@ public class VView extends SimplePanel implements Container, ResizeHandler, private ApplicationConnection connection; /** - * We are postponing resize process with IE. IE bugs with scrollbars in some - * situations, that causes false onWindowResized calls. With Timer we will - * give IE some time to decide if it really wants to keep current size - * (scrollbars). + * Keep track of possible parent size changes when an embedded application. + * + * Uses {@link #parentWidth} and {@link #parentHeight} as an optimization to + * keep track of when there is a real change. */ private Timer resizeTimer; + /** stored width of parent for embedded application auto-resize */ + private int parentWidth; + + /** stored height of parent for embedded application auto-resize */ + private int parentHeight; + private int scrollTop; private int scrollLeft; @@ -115,8 +123,7 @@ public class VView extends SimplePanel implements Container, ResizeHandler, private VLazyExecutor delayedResizeExecutor = new VLazyExecutor(200, new ScheduledCommand() { public void execute() { - windowSizeMaybeChanged(Window.getClientWidth(), - Window.getClientHeight()); + performSizeCheck(); } }); @@ -129,28 +136,75 @@ public class VView extends SimplePanel implements Container, ResizeHandler, // should not be in the document focus flow getElement().setTabIndex(-1); TouchScrollDelegate.enableTouchScrolling(this, getElement()); + + if (isMonitoringParentSize()) { + resizeTimer = new Timer() { + @Override + public void run() { + // trigger check to see if parent size has changed, + // recalculate layouts + performSizeCheck(); + resizeTimer.schedule(MONITOR_PARENT_TIMER_INTERVAL); + } + }; + resizeTimer.schedule(MONITOR_PARENT_TIMER_INTERVAL); + } } /** - * Called when the window might have been resized. + * Called when the window or parent div might have been resized. * - * @param newWidth + * This immediately checks the sizes of the window and the parent div (if + * monitoring it) and triggers layout recalculation if they have changed. + */ + protected void performSizeCheck() { + windowSizeMaybeChanged(Window.getClientWidth(), + Window.getClientHeight()); + } + + /** + * Called when the window or parent div might have been resized. + * + * This immediately checks the sizes of the window and the parent div (if + * monitoring it) and triggers layout recalculation if they have changed. + * + * @param newWindowWidth * The new width of the window - * @param newHeight + * @param newWindowHeight * The new height of the window + * + * @deprecated use {@link #performSizeCheck()} */ - protected void windowSizeMaybeChanged(int newWidth, int newHeight) { + @Deprecated + protected void windowSizeMaybeChanged(int newWindowWidth, + int newWindowHeight) { boolean changed = false; - if (windowWidth != newWidth) { - windowWidth = newWidth; + if (windowWidth != newWindowWidth) { + windowWidth = newWindowWidth; changed = true; VConsole.log("New window width: " + windowWidth); } - if (windowHeight != newHeight) { - windowHeight = newHeight; + if (windowHeight != newWindowHeight) { + windowHeight = newWindowHeight; changed = true; VConsole.log("New window height: " + windowHeight); } + Element parentElement = getElement().getParentElement(); + if (isMonitoringParentSize() && parentElement != null) { + // check also for parent size changes + int newParentWidth = parentElement.getClientWidth(); + int newParentHeight = parentElement.getClientHeight(); + if (parentWidth != newParentWidth) { + parentWidth = newParentWidth; + changed = true; + VConsole.log("New parent width: " + parentWidth); + } + if (parentHeight != newParentHeight) { + parentHeight = newParentHeight; + changed = true; + VConsole.log("New parent height: " + parentHeight); + } + } if (changed) { /* * If the window size has changed, layout the VView again and send @@ -159,10 +213,19 @@ public class VView extends SimplePanel implements Container, ResizeHandler, * should shrink as the content's size is fixed and would thus not * automatically shrink.) */ - VConsole.log("Running layout functions due to window resize"); + VConsole.log("Running layout functions due to window or parent resize"); + connection.runDescendentsLayout(VView.this); Util.runWebkitOverflowAutoFix(getElement()); + // update size to avoid (most) redundant re-layout passes + // there can still be an extra layout recalculation if webkit + // overflow fix updates the size in a deferred block + if (isMonitoringParentSize() && parentElement != null) { + parentWidth = parentElement.getClientWidth(); + parentHeight = parentElement.getClientHeight(); + } + sendClientResized(); } } @@ -206,6 +269,17 @@ public class VView extends SimplePanel implements Container, ResizeHandler, .contains(ApplicationConnection.GENERATED_BODY_CLASSNAME); } + /** + * Returns true if the size of the parent should be checked periodically and + * the application should react to its changes. + * + * @return true if size of parent should be tracked + */ + protected boolean isMonitoringParentSize() { + // could also perform a more specific check (Liferay portlet) + return isEmbedded(); + } + public void updateFromUIDL(final UIDL uidl, ApplicationConnection client) { rendering = true; @@ -400,7 +474,7 @@ public class VView extends SimplePanel implements Container, ResizeHandler, Window.addResizeHandler(this); } - onResize(); + triggerSizeChangeCheck(); // finally set scroll position from UIDL if (uidl.hasVariable("scrollTop")) { @@ -510,13 +584,17 @@ public class VView extends SimplePanel implements Container, ResizeHandler, * .gwt.event.logical.shared.ResizeEvent) */ public void onResize(ResizeEvent event) { - onResize(); + triggerSizeChangeCheck(); } /** * Called when a resize event is received. + * + * This may trigger a lazy refresh or perform the size check immediately + * depending on the browser used and whether the server side requests + * resizes to be lazy. */ - private void onResize() { + private void triggerSizeChangeCheck() { /* * IE (pre IE9 at least) will give us some false resize events due to * problems with scrollbars. Firefox 3 might also produce some extra @@ -534,8 +612,7 @@ public class VView extends SimplePanel implements Container, ResizeHandler, if (lazy) { delayedResizeExecutor.trigger(); } else { - windowSizeMaybeChanged(Window.getClientWidth(), - Window.getClientHeight()); + performSizeCheck(); } } -- cgit v1.2.3 From 338563e4d772c395da863d8764bca4a4b759cbe3 Mon Sep 17 00:00:00 2001 From: Henri Sara Date: Thu, 24 May 2012 13:07:19 +0300 Subject: Implement first version of view and navigation APIs (#8859). --- src/com/vaadin/navigator/FragmentManager.java | 38 ++ src/com/vaadin/navigator/Navigator.java | 582 +++++++++++++++++++++ src/com/vaadin/navigator/View.java | 50 ++ src/com/vaadin/navigator/ViewChangeListener.java | 62 +++ src/com/vaadin/navigator/ViewDisplay.java | 29 + src/com/vaadin/navigator/ViewProvider.java | 44 ++ .../navigator/ClassBasedViewProviderTest.java | 208 ++++++++ .../tests/server/navigator/NavigatorTest.java | 252 +++++++++ .../server/navigator/UriFragmentManagerTest.java | 51 ++ 9 files changed, 1316 insertions(+) create mode 100644 src/com/vaadin/navigator/FragmentManager.java create mode 100644 src/com/vaadin/navigator/Navigator.java create mode 100644 src/com/vaadin/navigator/View.java create mode 100644 src/com/vaadin/navigator/ViewChangeListener.java create mode 100644 src/com/vaadin/navigator/ViewDisplay.java create mode 100644 src/com/vaadin/navigator/ViewProvider.java create mode 100644 tests/server-side/com/vaadin/tests/server/navigator/ClassBasedViewProviderTest.java create mode 100644 tests/server-side/com/vaadin/tests/server/navigator/NavigatorTest.java create mode 100644 tests/server-side/com/vaadin/tests/server/navigator/UriFragmentManagerTest.java diff --git a/src/com/vaadin/navigator/FragmentManager.java b/src/com/vaadin/navigator/FragmentManager.java new file mode 100644 index 0000000000..f1fd90e569 --- /dev/null +++ b/src/com/vaadin/navigator/FragmentManager.java @@ -0,0 +1,38 @@ +/* +@VaadinApache2LicenseForJavaFiles@ + */ + +package com.vaadin.navigator; + +import java.io.Serializable; + +/** + * Fragment manager that handles interaction between Navigator and URI fragments + * or other similar view identification and bookmarking system. + * + * Alternative implementations can be created for HTML5 pushState, for portlet + * URL navigation and other similar systems. + * + * This interface is mostly for internal use by {@link Navigator}. + * + * @author Vaadin Ltd + * @since 7.0 + */ +public interface FragmentManager extends Serializable { + /** + * Return the current fragment (location string) including view name and any + * optional parameters. + * + * @return current view and parameter string, not null + */ + public String getFragment(); + + /** + * Set the current fragment (location string) in the application URL or + * similar location, including view name and any optional parameters. + * + * @param fragment + * new view and parameter string, not null + */ + public void setFragment(String fragment); +} \ No newline at end of file diff --git a/src/com/vaadin/navigator/Navigator.java b/src/com/vaadin/navigator/Navigator.java new file mode 100644 index 0000000000..d0bba584f1 --- /dev/null +++ b/src/com/vaadin/navigator/Navigator.java @@ -0,0 +1,582 @@ +/* +@VaadinApache2LicenseForJavaFiles@ + */ + +package com.vaadin.navigator; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; + +import com.vaadin.ui.Component; +import com.vaadin.ui.CssLayout; +import com.vaadin.ui.CustomComponent; +import com.vaadin.ui.Root; +import com.vaadin.ui.Root.FragmentChangedEvent; +import com.vaadin.ui.Root.FragmentChangedListener; + +/** + * Navigator utility that allows switching of views in a part of an application. + * + * The view switching can be based e.g. on URI fragments containing the view + * name and parameters to the view. There are two types of parameters for views: + * an optional parameter string that is included in the fragment (may be + * bookmarkable) and optional internal parameters that are not. + * + * Views can be explicitly registered or dynamically generated and listening to + * view changes is possible. + * + * Note that {@link Navigator} is not a component itself but comes with + * {@link SimpleViewDisplay} which is a component that displays the selected + * view as its contents. + * + * @author Vaadin Ltd + * @since 7.0 + */ +public class Navigator implements Serializable { + + // TODO divert navigation e.g. if no permissions? Or just show another view + // but keep URL? how best to intercept + // TODO investigate relationship to TouchKit navigation support + + /** + * Empty view component. + */ + public static class EmptyView extends CssLayout implements View { + public void init() { + setWidth("0px"); + setHeight("0px"); + } + + public void navigateTo(String fragmentParameters, + Object... internalParameters) { + // nothing to do + } + } + + /** + * Fragment manager using URI fragments of a Root to track views and enable + * listening to view changes. + * + * This class is mostly for internal use by Navigator, and is only public + * and static to enable testing. + */ + public static class UriFragmentManager implements FragmentManager, + FragmentChangedListener { + private final Root root; + private final Navigator navigator; + + /** + * Create a new URIFragmentManager and attach it to listen to URI + * fragment changes of a {@link Root}. + * + * @param root + * root whose URI fragment to get and modify + * @param navigator + * {@link Navigator} to notify of fragment changes (using + * {@link Navigator#navigateTo(String, Object...)} + */ + public UriFragmentManager(Root root, Navigator navigator) { + this.root = root; + this.navigator = navigator; + + root.addListener(this); + } + + public String getFragment() { + return root.getFragment(); + } + + public void setFragment(String fragment) { + // TODO ", false" ??? + root.setFragment(fragment); + } + + public void fragmentChanged(FragmentChangedEvent event) { + UriFragmentManager.this.navigator.navigateTo(getFragment()); + } + } + + /** + * View display that is a component itself and replaces its contents with + * the view. + * + * This display only supports views that are {@link Component}s themselves. + * Attempting to display a view that is not a component causes an exception + * to be thrown. + * + * By default, the view display has full size. + */ + public static class SimpleViewDisplay extends CustomComponent implements + ViewDisplay { + + /** + * Create new {@link ViewDisplay} that is itself a component displaying + * the view. + */ + public SimpleViewDisplay() { + setSizeFull(); + } + + public void showView(View view) { + if (view instanceof Component) { + setCompositionRoot((Component) view); + } else { + throw new IllegalArgumentException("View is not a component: " + + view); + } + } + } + + /** + * View provider which uses a map from view name to pre-created and + * registered view instances. + */ + public static class RegisteredViewProvider implements ViewProvider { + + private HashMap viewNameToView = new HashMap(); + + public String getViewName(String viewAndParameters) { + if (null == viewAndParameters) { + return null; + } + for (String viewName : viewNameToView.keySet()) { + if (viewAndParameters.equals(viewName) + || viewAndParameters.startsWith(viewName + "/")) { + return viewName; + } + } + return null; + } + + public View getView(String viewName) { + return viewNameToView.get(viewName); + } + + /** + * Register a view for a view name. + * + * Registering another view with a name that is already registered + * overwrites the old registration. + * + * @param viewName + * String that identifies a view (not null nor empty string) + * @param view + * {@link View} instance (not null) + */ + public void addView(String viewName, View view) { + + // Check parameters + if (viewName == null || view == null || viewName.length() == 0) { + throw new IllegalArgumentException( + "view and viewName must be non-null and not empty"); + } + + viewNameToView.put(viewName, view); + } + + /** + * Remove view from navigator. + * + * @param viewName + * name of the view to remove + */ + public void removeView(String viewName) { + viewNameToView.remove(viewName); + } + } + + /** + * View provider which uses a map from view name to the class to instantiate + * for the view. + * + * Views that have been created are cached and reused when the same view + * name is requested again. + * + * Note that the view class must be accessible by the class loader used by + * the provider. This may require its visibility to be public. + */ + public static class ClassBasedViewProvider implements ViewProvider { + + private HashMap> viewNameToClass = new HashMap>(); + private HashMap, String> classToViewName = new HashMap, String>(); + /** + * Already opened (cached) views that can be reopened or reused with new + * parameters. + */ + private HashMap, View> classToView = new HashMap, View>(); + + public String getViewName(String viewAndParameters) { + if (null == viewAndParameters) { + return null; + } + for (String viewName : viewNameToClass.keySet()) { + if (viewAndParameters.equals(viewName) + || viewAndParameters.startsWith(viewName + "/")) { + return viewName; + } + } + return null; + } + + public View getView(String viewName) { + Class newViewClass = viewNameToClass.get(viewName); + if (null == newViewClass) { + return null; + } + if (!classToView.containsKey(newViewClass)) { + try { + View view = newViewClass.newInstance(); + view.init(); + classToView.put(newViewClass, view); + } catch (InstantiationException e) { + // TODO error handling + throw new RuntimeException(e); + } catch (IllegalAccessException e) { + // TODO error handling + throw new RuntimeException(e); + } + } + // return already cached view + final View v = classToView.get(newViewClass); + return v; + } + + /** + * Register a view class for a view name. + * + * @param viewName + * String that identifies a view (not null nor empty string) + * @param viewClass + * Component class that implements Navigator.View interface + * (not null) + */ + public void addView(String viewName, Class viewClass) { + + // Check parameters + if (viewName == null || viewClass == null || viewName.length() == 0) { + throw new IllegalArgumentException( + "viewClass and viewName must be non-null and not empty"); + } + + if (!View.class.isAssignableFrom(viewClass)) { + throw new IllegalArgumentException( + "viewClass must implement Navigator.View"); + } + + if (viewNameToClass.containsKey(viewName)) { + if (viewNameToClass.get(viewName) == viewClass) { + return; + } + + throw new IllegalArgumentException(viewNameToClass + .get(viewName).getName() + + " is already mapped to '" + + viewName + "'"); + } + + if (classToViewName.containsKey(viewClass)) { + throw new IllegalArgumentException( + "Each view class can only be added to Navigator with one view name"); + } + + viewNameToClass.put(viewName, viewClass); + classToViewName.put(viewClass, viewName); + } + + /** + * Remove view from navigator. + * + * @param viewName + * name of the view to remove + */ + public void removeView(String viewName) { + Class c = viewNameToClass.get(viewName); + if (c != null) { + viewNameToClass.remove(viewName); + classToViewName.remove(c); + classToView.remove(c); + } + } + + /** + * Get the view name for given view implementation class. + * + * @param viewClass + * Class that implements the view. + * @return view name for which the view class is registered, null if + * none + */ + public String getViewName(Class viewClass) { + return classToViewName.get(viewClass); + } + + /** + * Get the view class for given view name. + * + * @param viewName + * view name to get view for + * @return View that corresponds to the name + */ + public Class getViewClass(String viewName) { + return viewNameToClass.get(viewName); + } + } + + private final FragmentManager fragmentManager; + private final ViewDisplay display; + private String mainViewName = null; + private View currentView = null; + private List listeners = new LinkedList(); + private List providers = new LinkedList(); + + /** + * Create a navigator that is tracking the active view using URI fragments. + * + * @param root + * whose URI fragments are used + * @param display + * where to display the views + */ + public Navigator(Root root, ViewDisplay display) { + this.display = display; + fragmentManager = new UriFragmentManager(root, this); + } + + /** + * Create a navigator. + * + * When a custom fragment manager is not needed, use the constructor + * {@link #Navigator(Root, ViewDisplay)} which uses a URI fragment based + * fragment manager. + * + * @param fragmentManager + * fragment manager keeping track of the active view and enabling + * bookmarking and direct navigation + * @param display + * where to display the views + */ + public Navigator(FragmentManager fragmentManager, ViewDisplay display) { + this.display = display; + this.fragmentManager = fragmentManager; + } + + /** + * Navigate to a view and initialize the view with given parameters. + * + * The view string consists of a view name optionally followed by a slash + * and (fragment) parameters. ViewProviders are used to find and create the + * correct type of view. + * + * If the view being left indicates it wants a confirmation for the + * navigation operation, the user is asked for the confirmation. + * + * @param viewAndParameters + * view name and parameters + * @param internalParameters + * parameters that are only passed when switching views + * explicitly on the server side, not bookmarkable + */ + public void navigateTo(String viewAndParameters, + Object... internalParameters) { + if ("".equals(viewAndParameters)) { + viewAndParameters = mainViewName; + } + for (ViewProvider provider : providers) { + String viewName = provider.getViewName(viewAndParameters); + if (null != viewName) { + String parameters = null; + if (viewAndParameters.length() > viewName.length() + 1) { + parameters = viewAndParameters + .substring(viewName.length() + 1); + } + View view = provider.getView(viewName); + if (null != view) { + navigateTo(view, viewName, parameters, internalParameters); + // stop after a view is found + return; + } + } + } + // TODO if no view is found, use main view or do nothing? + } + + /** + * Internal method activating a view, setting its parameters and calling + * listeners. + * + * This method also verifies that the user is allowed to perform the + * navigation operation. + * + * @param view + * view to activate + * @param viewName + * (optional) name of the view or null not to set the fragment + * @param fragmentParameters + * parameters passed in the fragment for the view + * @param internalParameters + * parameters that are only passed when switching views + * explicitly on the server side, not bookmarkable + */ + protected void navigateTo(View view, String viewName, + String fragmentParameters, Object... internalParameters) { + if (!isViewChangeAllowed(currentView, view, viewName, + fragmentParameters, internalParameters)) { + return; + } + + if (null != viewName && getFragmentManager() != null) { + String currentFragment = viewName; + if (fragmentParameters != null) { + currentFragment += "/" + fragmentParameters; + } + if (!currentFragment.equals(getFragmentManager().getFragment())) { + getFragmentManager().setFragment(currentFragment); + } + } + + view.navigateTo(fragmentParameters, internalParameters); + View previousView = currentView; + currentView = view; + + if (display != null) { + display.showView(view); + } + + fireViewChange(previousView); + } + + /** + * Check whether view change is allowed. + * + * All related listeners are called. The view change is blocked if any of + * them wants to block the navigation operation. + * + * The view change listeners may also e.g. open a warning or question dialog + * and save the parameters to re-initiate the navigation operation upon user + * action. + * + * @param previous + * the view being deactivated + * @param next + * the view being activated + * @param viewName + * name of the view being activated + * @param fragmentParameters + * parameters passed in the fragment for the view + * @param internalParameters + * parameters that are only passed on the server side, not + * bookmarkable + * @return true if the view change should be allowed, false to silently + * block the navigation operation + */ + protected boolean isViewChangeAllowed(View previous, View next, + String viewName, String fragmentParameters, + Object[] internalParameters) { + for (ViewChangeListener l : listeners) { + if (!l.isViewChangeAllowed(previous, next, viewName, + fragmentParameters, internalParameters)) { + return false; + } + } + return true; + } + + /** + * Return the fragment manager that is used to get, listen to and manipulate + * the URI fragment or other source of navigation information. + * + * @return fragment manager in use + */ + protected FragmentManager getFragmentManager() { + return fragmentManager; + } + + /** + * Get the main view. + * + * Main view is the default view shown to user when he opens application + * without specifying view name. + * + * @return name of the main view. + */ + public String getMainView() { + return mainViewName; + } + + /** + * Set the main view. + * + * Main view is the default view shown to user when he opens application + * without specifying view name. If the {@link Navigator} does not have a + * current view, the main view is automatically selected when set. + * + * @param mainViewName + * name of the main view. + */ + public void setMainView(String mainViewName) { + this.mainViewName = mainViewName; + // TODO should this be done? + if (currentView == null) { + navigateTo(mainViewName); + } + } + + /** + * Fire an event when the current view has changed. + * + * @param previousView + */ + protected void fireViewChange(View previousView) { + for (ViewChangeListener l : listeners) { + l.navigatorViewChanged(previousView, currentView); + } + } + + /** + * Register a view provider (factory). + * + * Providers are called in order of registration until one that can handle + * the requested view name is found. + * + * @param provider + * provider to register + */ + public void registerProvider(ViewProvider provider) { + providers.add(provider); + } + + /** + * Unregister a view provider (factory). + * + * @param provider + * provider to unregister + */ + public void unregisterProvider(ViewProvider provider) { + providers.remove(provider); + } + + /** + * Listen to changes of the active view. + * + * The listener will get notified after the view has changed. + * + * @param listener + * Listener to invoke after view changes. + */ + public void addListener(ViewChangeListener listener) { + listeners.add(listener); + } + + /** + * Remove a view change listener. + * + * @param listener + * Listener to remove. + */ + public void removeListener(ViewChangeListener listener) { + listeners.remove(listener); + } + +} diff --git a/src/com/vaadin/navigator/View.java b/src/com/vaadin/navigator/View.java new file mode 100644 index 0000000000..efa13fbac2 --- /dev/null +++ b/src/com/vaadin/navigator/View.java @@ -0,0 +1,50 @@ +/* +@VaadinApache2LicenseForJavaFiles@ + */ + +package com.vaadin.navigator; + +import java.io.Serializable; + +import com.vaadin.ui.Component; + +/** + * Interface for all views controlled by the navigator. + * + * Each view added to the navigator must implement this interface. Typically, a + * view is a {@link Component}. + * + * @author Vaadin Ltd + * @since 7.0 + */ +public interface View extends Serializable { + + /** + * Init view. + * + * Convenience method which navigator calls just before the view is rendered + * for the first time. This is called only once in the lifetime of each view + * instance. + */ + public void init(); + + /** + * This view is navigated to. + * + * This method is always called before the view is shown on screen. If there + * is any additional id to data what should be shown in the view, it is also + * optionally passed as parameter. + * + * TODO fragmentParameters null if no parameters or empty string? + * + * @param fragmentParameters + * parameters to the view or null if none given. This is the + * string that appears e.g. in URI after "viewname/" + * @param internalParameters + * parameters given directly to + * {@link Navigator#navigateTo(String, Object...)}, not passed + * via the fragment and not preserved in bookmarks + */ + public void navigateTo(String fragmentParameters, + Object... internalParameters); +} \ No newline at end of file diff --git a/src/com/vaadin/navigator/ViewChangeListener.java b/src/com/vaadin/navigator/ViewChangeListener.java new file mode 100644 index 0000000000..9ac48e27cc --- /dev/null +++ b/src/com/vaadin/navigator/ViewChangeListener.java @@ -0,0 +1,62 @@ +/* +@VaadinApache2LicenseForJavaFiles@ + */ + +package com.vaadin.navigator; + +import java.io.Serializable; + +/** + * Interface for listening to View changes before and after they occur. + * + * Implementations of this interface can also block navigation between views + * before it is performed. + * + * @author Vaadin Ltd + * @since 7.0 + */ +public interface ViewChangeListener extends Serializable { + + /** + * Check whether changing the view is permissible. + * + * This method may also e.g. open a "save" dialog or question about the + * change, which may re-initiate the navigation operation after user action. + * + * If this listener does not want to block the view change (e.g. does not + * know the view in question), it should return true. If any listener + * returns false, the view change is not allowed. + * + * TODO move to separate interface? + * + * @param previous + * view that is being deactivated + * @param next + * view that is being activated + * @param viewName + * name of the new view that is being activated + * @param fragmentParameters + * fragment parameters (potentially bookmarkable) for the new + * view + * @param internalParameters + * internal parameters for the new view, not visible in the + * browser + * @return true if the view change should be allowed or this listener does + * not care about the view change, false to block the change + */ + public boolean isViewChangeAllowed(View previous, View next, + String viewName, String fragmentParameters, + Object... internalParameters); + + /** + * Invoked after the view has changed. Be careful for deadlocks if you + * decide to change the view again in the listener. + * + * @param previous + * Preview view before the change. + * @param current + * New view after the change. + */ + public void navigatorViewChanged(View previous, View current); + +} \ No newline at end of file diff --git a/src/com/vaadin/navigator/ViewDisplay.java b/src/com/vaadin/navigator/ViewDisplay.java new file mode 100644 index 0000000000..6016951394 --- /dev/null +++ b/src/com/vaadin/navigator/ViewDisplay.java @@ -0,0 +1,29 @@ +/* +@VaadinApache2LicenseForJavaFiles@ + */ + +package com.vaadin.navigator; + +import java.io.Serializable; + +/** + * Interface for displaying a view in an appropriate location. + * + * The view display can be a component/layout itself or can modify a separate + * layout. + * + * @author Vaadin Ltd + * @since 7.0 + */ +public interface ViewDisplay extends Serializable { + /** + * Remove previously shown view and show the newly selected view in its + * place. + * + * The parameters for the view have been set before this method is called. + * + * @param view + * new view to show + */ + public void showView(View view); +} \ No newline at end of file diff --git a/src/com/vaadin/navigator/ViewProvider.java b/src/com/vaadin/navigator/ViewProvider.java new file mode 100644 index 0000000000..4d9d22acab --- /dev/null +++ b/src/com/vaadin/navigator/ViewProvider.java @@ -0,0 +1,44 @@ +/* +@VaadinApache2LicenseForJavaFiles@ + */ + +package com.vaadin.navigator; + +import java.io.Serializable; + +/** + * A provider for view instances that can return pre-registered views or + * dynamically create new views. + * + * If multiple providers are used, {@link #getViewName(String)} of each is + * called (in registration order) until one of them returns a non-null value. + * The {@link #getView(String)} method of that provider is then used. + * + * @author Vaadin Ltd + * @since 7.0 + */ +public interface ViewProvider extends Serializable { + /** + * Extract the view name from a combined view name and parameter string. + * This method should return a view name if and only if this provider + * handles creation of such views. + * + * @param viewAndParameters + * string with view name and its fragment parameters (if given), + * not null + * @return view name if the view is handled by this provider, null otherwise + */ + public String getViewName(String viewAndParameters); + + /** + * Create or return a pre-created instance of a view. + * + * The parameters for the view are set separately by the navigator when the + * view is activated. + * + * @param viewName + * name of the view, not null + * @return newly created view (null if none available for the view name) + */ + public View getView(String viewName); +} \ No newline at end of file diff --git a/tests/server-side/com/vaadin/tests/server/navigator/ClassBasedViewProviderTest.java b/tests/server-side/com/vaadin/tests/server/navigator/ClassBasedViewProviderTest.java new file mode 100644 index 0000000000..818229ab2f --- /dev/null +++ b/tests/server-side/com/vaadin/tests/server/navigator/ClassBasedViewProviderTest.java @@ -0,0 +1,208 @@ +/* +@VaadinApache2LicenseForJavaFiles@ + */ + +package com.vaadin.tests.server.navigator; + +import junit.framework.TestCase; + +import com.vaadin.navigator.Navigator.ClassBasedViewProvider; +import com.vaadin.navigator.View; +import com.vaadin.ui.Label; + +public class ClassBasedViewProviderTest extends TestCase { + + private ClassBasedViewProvider provider; + + public static class TestView extends Label implements View { + public boolean initialized = false; + public String parameters = null; + + public void init() { + initialized = true; + } + + public void navigateTo(String parameters, Object... internalParameters) { + this.parameters = parameters; + } + + } + + public static class TestView2 extends TestView { + + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + provider = new ClassBasedViewProvider(); + } + + public void testAddViewWithNullName() throws Exception { + try { + provider.addView(null, TestView.class); + fail("Should not be able to add view with null name"); + } catch (IllegalArgumentException e) { + } + } + + public void testAddViewWithEmptyStringName() throws Exception { + try { + provider.addView("", TestView.class); + fail("Should not be able to add view with empty name"); + } catch (IllegalArgumentException e) { + } + } + + public void testAddViewNull() throws Exception { + try { + provider.addView("test", null); + fail("Should not be able to add null view"); + } catch (IllegalArgumentException e) { + } + } + + public void testAddViewSameName() throws Exception { + try { + provider.addView("test", TestView.class); + provider.addView("test", TestView2.class); + fail("Should not be able to add two views with same name"); + } catch (IllegalArgumentException e) { + } + } + + public void testAddViewSameClass() throws Exception { + try { + provider.addView("test", TestView.class); + provider.addView("test2", TestView.class); + fail("Should not be able to add same view class with two different names"); + } catch (IllegalArgumentException e) { + } + } + + public void testGetViewNameForNullString() throws Exception { + assertNull( + "Found view name for null view string in an empty view provider", + provider.getViewName((String) null)); + + provider.addView("test", TestView.class); + assertNull("Found view name for null view string", + provider.getViewName((String) null)); + } + + public void testGetViewNameForNullClass() throws Exception { + assertNull("Found view name for null class", + provider.getViewName((Class) null)); + } + + public void testGetViewNameForEmptyString() throws Exception { + assertNull( + "Found view name for empty view string in an empty provider", + provider.getViewName("")); + provider.addView("test", TestView.class); + assertNull("Found view name for empty view string", + provider.getViewName("")); + } + + public void testGetViewNameForClass() throws Exception { + provider.addView("test", TestView.class); + assertEquals("No view name found for view class", "test", + provider.getViewName(TestView.class)); + } + + public void testGetViewNameWithParameters() throws Exception { + provider.addView("test", TestView.class); + assertEquals("Incorrect view name found for view string", "test", + provider.getViewName("test")); + assertEquals( + "Incorrect view name found for view string ending with slash", + "test", provider.getViewName("test/")); + assertEquals( + "Incorrect view name found for view string with parameters", + "test", provider.getViewName("test/params/are/here")); + } + + public void testGetViewNameMultipleRegisteredWithParameters() + throws Exception { + provider.addView("test", TestView.class); + provider.addView("test2", TestView2.class); + assertEquals("Incorrect view name found for view string", "test", + provider.getViewName("test/test2/params")); + } + + public void testGetViewNameNestedNames() throws Exception { + provider.addView("test/subview", TestView2.class); + provider.addView("test", TestView.class); + assertEquals("Incorrect view name found for subview string", + "test/subview", provider.getViewName("test/subview")); + assertEquals( + "Incorrect view name found for subview string with empty parameters", + "test/subview", provider.getViewName("test/subview/")); + assertEquals( + "Incorrect view name found for subview string with parameters", + "test/subview", provider.getViewName("test/subview/parameters")); + assertEquals("Incorrect view name found for top level view string", + "test", provider.getViewName("test")); + assertEquals( + "Incorrect view name found for top level view string with empty parameters", + "test", provider.getViewName("test/")); + assertEquals( + "Incorrect view name found for top level view string with parameters starting like subview name", + "test", provider.getViewName("test/subviewnothere")); + } + + public void testGetViewClass() throws Exception { + assertNull("View class found for empty view provider", + provider.getViewClass("test")); + provider.addView("test", TestView.class); + assertEquals("View class not found", TestView.class, + provider.getViewClass("test")); + assertNull("View class found for unregistered view name", + provider.getViewClass("test2")); + } + + public void testGetViewSimple() throws Exception { + assertNull("Found view in an empty view provider", + provider.getViewName("test")); + + provider.addView("test", TestView.class); + View view = provider.getView("test"); + assertNotNull("Did not get view from a provider", view); + assertEquals("Incorrect view type", TestView.class, view.getClass()); + assertTrue("View not initialized", ((TestView) view).initialized); + } + + public void testGetViewMultipleRegistered() throws Exception { + provider.addView("test", TestView.class); + provider.addView("test2", TestView2.class); + assertEquals("Incorrect view type", TestView.class, + provider.getView("test").getClass()); + assertEquals("Incorrect view type", TestView2.class, + provider.getView("test2").getClass()); + assertEquals("Incorrect view type", TestView.class, + provider.getView("test").getClass()); + } + + public void testRemoveView() throws Exception { + provider.addView("test", TestView.class); + assertNotNull("Did not get view from a provider", + provider.getView("test")); + provider.removeView("test"); + assertNull("View class found for removed view name", + provider.getViewClass("test")); + assertNull("View name found for removed view", + provider.getViewName(TestView.class)); + // cached view? + assertNull( + "Received view instance from a provider after removing view type", + provider.getView("test")); + } + + public void testGetViewCached() throws Exception { + provider.addView("test", TestView.class); + View view1 = provider.getView("test"); + View view2 = provider.getView("test"); + assertSame("View instance not cached", view1, view2); + } + +} diff --git a/tests/server-side/com/vaadin/tests/server/navigator/NavigatorTest.java b/tests/server-side/com/vaadin/tests/server/navigator/NavigatorTest.java new file mode 100644 index 0000000000..d6a7cc68c7 --- /dev/null +++ b/tests/server-side/com/vaadin/tests/server/navigator/NavigatorTest.java @@ -0,0 +1,252 @@ +/* +@VaadinApache2LicenseForJavaFiles@ + */ + +package com.vaadin.tests.server.navigator; + +import junit.framework.TestCase; + +import org.easymock.EasyMock; +import org.easymock.IMocksControl; + +import com.vaadin.navigator.FragmentManager; +import com.vaadin.navigator.Navigator; +import com.vaadin.navigator.View; +import com.vaadin.navigator.ViewChangeListener; +import com.vaadin.navigator.ViewDisplay; +import com.vaadin.navigator.ViewProvider; + +public class NavigatorTest extends TestCase { + + // TODO test internal parameters (and absence of them) + // TODO test listeners blocking navigation, multiple listeners + + public void testBasicNavigation() { + IMocksControl control = EasyMock.createControl(); + FragmentManager manager = control.createMock(FragmentManager.class); + ViewDisplay display = control.createMock(ViewDisplay.class); + ViewProvider provider = control.createMock(ViewProvider.class); + View view1 = control.createMock(View.class); + View view2 = control.createMock(View.class); + + // prepare mocks: what to expect + EasyMock.expect(provider.getViewName("test1")).andReturn("test1"); + EasyMock.expect(provider.getView("test1")).andReturn(view1); + view1.init(); + EasyMock.expect(manager.getFragment()).andReturn(""); + view1.navigateTo(null); + display.showView(view1); + manager.setFragment("test1"); + + EasyMock.expect(provider.getViewName("test2/")).andReturn("test2"); + EasyMock.expect(provider.getView("test2")).andReturn(view2); + view2.init(); + EasyMock.expect(manager.getFragment()).andReturn("view1"); + view2.navigateTo(null); + display.showView(view2); + manager.setFragment("test2"); + + EasyMock.expect(provider.getViewName("test1/params")) + .andReturn("test1"); + EasyMock.expect(provider.getView("test1")).andReturn(view1); + view1.init(); + EasyMock.expect(manager.getFragment()).andReturn("view2"); + view1.navigateTo("params"); + display.showView(view1); + manager.setFragment("test1/params"); + + control.replay(); + + // create and test navigator + Navigator navigator = new Navigator(manager, display); + navigator.registerProvider(provider); + + navigator.navigateTo("test1"); + navigator.navigateTo("test2/"); + navigator.navigateTo("test1/params"); + } + + public void testMainView() { + IMocksControl control = EasyMock.createControl(); + FragmentManager manager = control.createMock(FragmentManager.class); + ViewDisplay display = control.createMock(ViewDisplay.class); + ViewProvider provider = control.createMock(ViewProvider.class); + View view1 = control.createMock(View.class); + View view2 = control.createMock(View.class); + + // prepare mocks: what to expect + EasyMock.expect(provider.getViewName("test1")).andReturn("test1"); + EasyMock.expect(provider.getView("test1")).andReturn(view1); + view1.init(); + EasyMock.expect(manager.getFragment()).andReturn(""); + view1.navigateTo(null); + display.showView(view1); + manager.setFragment("test1"); + + EasyMock.expect(provider.getViewName("test2")).andReturn("test2"); + EasyMock.expect(provider.getView("test2")).andReturn(view2); + view2.init(); + EasyMock.expect(manager.getFragment()).andReturn("view1"); + view2.navigateTo(null); + display.showView(view2); + manager.setFragment("test2"); + + EasyMock.expect(provider.getViewName("test1")).andReturn("test1"); + EasyMock.expect(provider.getView("test1")).andReturn(view1); + view1.init(); + EasyMock.expect(manager.getFragment()).andReturn(""); + view1.navigateTo(null); + display.showView(view1); + manager.setFragment("test1"); + + EasyMock.expect(provider.getViewName("test1/params")) + .andReturn("test1"); + EasyMock.expect(provider.getView("test1")).andReturn(view1); + view1.init(); + EasyMock.expect(manager.getFragment()).andReturn("view2"); + view1.navigateTo("params"); + display.showView(view1); + manager.setFragment("test1/params"); + + control.replay(); + + // create and test navigator + Navigator navigator = new Navigator(manager, display); + navigator.registerProvider(provider); + // this also triggers navigation + navigator.setMainView("test1"); + + navigator.navigateTo("test2"); + navigator.navigateTo(""); + navigator.navigateTo("test1/params"); + } + + public void testListeners() { + IMocksControl control = EasyMock.createControl(); + FragmentManager manager = control.createMock(FragmentManager.class); + ViewDisplay display = control.createMock(ViewDisplay.class); + ViewProvider provider = control.createMock(ViewProvider.class); + View view1 = control.createMock(View.class); + View view2 = control.createMock(View.class); + ViewChangeListener listener = control + .createMock(ViewChangeListener.class); + + // prepare mocks: what to expect + EasyMock.expect(provider.getViewName("test1")).andReturn("test1"); + EasyMock.expect(provider.getView("test1")).andReturn(view1); + view1.init(); + EasyMock.expect(manager.getFragment()).andReturn(""); + EasyMock.expect( + listener.isViewChangeAllowed(null, view1, "test1", null, + new Object[0])).andReturn(true); + view1.navigateTo(null); + display.showView(view1); + manager.setFragment("test1"); + listener.navigatorViewChanged(null, view1); + + EasyMock.expect(provider.getViewName("test2")).andReturn("test2"); + EasyMock.expect(provider.getView("test2")).andReturn(view2); + view2.init(); + EasyMock.expect(manager.getFragment()).andReturn("view1"); + EasyMock.expect( + listener.isViewChangeAllowed(view1, view2, "test2", null, + new Object[0])).andReturn(true); + view2.navigateTo(null); + display.showView(view2); + manager.setFragment("test2"); + listener.navigatorViewChanged(view1, view2); + + control.replay(); + + // create and test navigator + Navigator navigator = new Navigator(manager, display); + navigator.registerProvider(provider); + navigator.addListener(listener); + + navigator.navigateTo("test1"); + navigator.navigateTo("test2"); + } + + public void testBlockNavigation() { + IMocksControl control = EasyMock.createControl(); + FragmentManager manager = control.createMock(FragmentManager.class); + ViewDisplay display = control.createMock(ViewDisplay.class); + ViewProvider provider = control.createMock(ViewProvider.class); + View view1 = control.createMock(View.class); + View view2 = control.createMock(View.class); + ViewChangeListener listener1 = control + .createMock(ViewChangeListener.class); + ViewChangeListener listener2 = control + .createMock(ViewChangeListener.class); + + // prepare mocks: what to expect + // first listener blocks first view change + EasyMock.expect(provider.getViewName("test1")).andReturn("test1"); + EasyMock.expect(provider.getView("test1")).andReturn(view1); + view1.init(); + EasyMock.expect(manager.getFragment()).andReturn(""); + EasyMock.expect( + listener1.isViewChangeAllowed(null, view1, "test1", null, + new Object[0])).andReturn(false); + + // second listener blocks second view change + EasyMock.expect(provider.getViewName("test1/test")).andReturn("test1"); + EasyMock.expect(provider.getView("test1")).andReturn(view1); + view1.init(); + EasyMock.expect(manager.getFragment()).andReturn(""); + EasyMock.expect( + listener1.isViewChangeAllowed(null, view1, "test1", "test", + new Object[0])).andReturn(true); + EasyMock.expect( + listener2.isViewChangeAllowed(null, view1, "test1", "test", + new Object[0])).andReturn(false); + + // both listeners allow view change + EasyMock.expect(provider.getViewName("test1/bar")).andReturn("test1"); + EasyMock.expect(provider.getView("test1")).andReturn(view1); + view1.init(); + EasyMock.expect(manager.getFragment()).andReturn(""); + EasyMock.expect( + listener1.isViewChangeAllowed(null, view1, "test1", "bar", + new Object[0])).andReturn(true); + EasyMock.expect( + listener2.isViewChangeAllowed(null, view1, "test1", "bar", + new Object[0])).andReturn(true); + view1.navigateTo("bar"); + display.showView(view1); + manager.setFragment("test1/bar"); + listener1.navigatorViewChanged(null, view1); + listener2.navigatorViewChanged(null, view1); + + // both listeners allow view change from non-null view + EasyMock.expect(provider.getViewName("test2")).andReturn("test2"); + EasyMock.expect(provider.getView("test2")).andReturn(view2); + view2.init(); + EasyMock.expect(manager.getFragment()).andReturn("view1"); + EasyMock.expect( + listener1.isViewChangeAllowed(view1, view2, "test2", null, + new Object[0])).andReturn(true); + EasyMock.expect( + listener2.isViewChangeAllowed(view1, view2, "test2", null, + new Object[0])).andReturn(true); + view2.navigateTo(null); + display.showView(view2); + manager.setFragment("test2"); + listener1.navigatorViewChanged(view1, view2); + listener2.navigatorViewChanged(view1, view2); + + control.replay(); + + // create and test navigator + Navigator navigator = new Navigator(manager, display); + navigator.registerProvider(provider); + navigator.addListener(listener1); + navigator.addListener(listener2); + + navigator.navigateTo("test1"); + navigator.navigateTo("test1/test"); + navigator.navigateTo("test1/bar"); + navigator.navigateTo("test2"); + } + +} diff --git a/tests/server-side/com/vaadin/tests/server/navigator/UriFragmentManagerTest.java b/tests/server-side/com/vaadin/tests/server/navigator/UriFragmentManagerTest.java new file mode 100644 index 0000000000..cfbf50f256 --- /dev/null +++ b/tests/server-side/com/vaadin/tests/server/navigator/UriFragmentManagerTest.java @@ -0,0 +1,51 @@ +/* +@VaadinApache2LicenseForJavaFiles@ + */ + +package com.vaadin.tests.server.navigator; + +import junit.framework.TestCase; + +import org.easymock.EasyMock; +import org.easymock.IMocksControl; + +import com.vaadin.navigator.Navigator; +import com.vaadin.navigator.Navigator.UriFragmentManager; +import com.vaadin.ui.Root; +import com.vaadin.ui.Root.FragmentChangedEvent; + +public class UriFragmentManagerTest extends TestCase { + + public void testGetSetFragment() { + Root root = EasyMock.createMock(Root.class); + UriFragmentManager manager = new UriFragmentManager(root, null); + + // prepare mock + EasyMock.expect(root.getFragment()).andReturn(""); + root.setFragment("test"); + EasyMock.expect(root.getFragment()).andReturn("test"); + EasyMock.replay(root); + + // test manager using the mock + assertEquals("Incorrect fragment value", "", manager.getFragment()); + manager.setFragment("test"); + assertEquals("Incorrect fragment value", "test", manager.getFragment()); + } + + public void testListener() { + // create mocks + IMocksControl control = EasyMock.createControl(); + Navigator navigator = control.createMock(Navigator.class); + Root root = control.createMock(Root.class); + + UriFragmentManager manager = new UriFragmentManager(root, navigator); + + EasyMock.expect(root.getFragment()).andReturn("test"); + navigator.navigateTo("test"); + control.replay(); + + FragmentChangedEvent event = root.new FragmentChangedEvent(root, + "oldtest"); + manager.fragmentChanged(event); + } +} -- cgit v1.2.3 From ce78aaeb78cf7e48e91a8e76ecb5f48531baea6c Mon Sep 17 00:00:00 2001 From: Automerge Date: Thu, 24 May 2012 11:06:04 +0000 Subject: [merge from 6.7] #8801 Recompute VFilterSelect textbox width if popup opener width has changed eg. due to a style/theme change svn changeset:23823/svn branch:6.8 --- src/com/vaadin/terminal/gwt/client/ui/VFilterSelect.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/com/vaadin/terminal/gwt/client/ui/VFilterSelect.java b/src/com/vaadin/terminal/gwt/client/ui/VFilterSelect.java index 8362d6fbec..4ecb42d920 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VFilterSelect.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VFilterSelect.java @@ -1237,6 +1237,12 @@ public class VFilterSelect extends Composite implements Paintable, Field, updateRootWidth(); } + // Popup opener width may have changed due to a style change (#8801) + if (!readonly && popupWidth != Util.getRequiredWidth(popupOpener)) { + popupWidth = Util.getRequiredWidth(popupOpener); + updateRootWidth(); + } + // Focus dependent style names are lost during the update, so we add // them here back again if (focused) { -- cgit v1.2.3 From 20ba0f58a0649702cfa5442d7c192c74d03b6a36 Mon Sep 17 00:00:00 2001 From: Henri Sara Date: Thu, 24 May 2012 13:16:02 +0000 Subject: Manual merge from 6.7 to 6.8 for #8799 timer unregistration. svn changeset:23825/svn branch:6.8 --- src/com/vaadin/terminal/gwt/client/ui/VView.java | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/com/vaadin/terminal/gwt/client/ui/VView.java b/src/com/vaadin/terminal/gwt/client/ui/VView.java index 350c4b206b..6fdacc9607 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VView.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VView.java @@ -136,7 +136,14 @@ public class VView extends SimplePanel implements Container, ResizeHandler, // should not be in the document focus flow getElement().setTabIndex(-1); TouchScrollDelegate.enableTouchScrolling(this, getElement()); + } + /** + * Start to periodically monitor for parent element resizes if embedded + * application (e.g. portlet). + */ + protected void onLoad() { + super.onLoad(); if (isMonitoringParentSize()) { resizeTimer = new Timer() { @Override @@ -151,6 +158,18 @@ public class VView extends SimplePanel implements Container, ResizeHandler, } } + /** + * Stop monitoring for parent element resizes. + */ + @Override + protected void onUnload() { + if (resizeTimer != null) { + resizeTimer.cancel(); + resizeTimer = null; + } + super.onUnload(); + } + /** * Called when the window or parent div might have been resized. * -- cgit v1.2.3 From cac340e3dda0c4ec68af5294df84d428ffd5d30d Mon Sep 17 00:00:00 2001 From: Johannes Dahlström Date: Fri, 25 May 2012 12:35:28 +0000 Subject: #7911 Added a common CSS class "v-touch" for all touch devices svn changeset:23828/svn branch:6.8 --- src/com/vaadin/terminal/gwt/client/BrowserInfo.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/com/vaadin/terminal/gwt/client/BrowserInfo.java b/src/com/vaadin/terminal/gwt/client/BrowserInfo.java index c8caab6829..4b9f3eacab 100644 --- a/src/com/vaadin/terminal/gwt/client/BrowserInfo.java +++ b/src/com/vaadin/terminal/gwt/client/BrowserInfo.java @@ -33,6 +33,9 @@ public class BrowserInfo { private static final String OS_ANDROID = "android"; private static final String OS_IOS = "ios"; + // Common CSS class for all touch devices + private static final String UI_TOUCH = "touch"; + private static BrowserInfo instance; private static String cssClass = null; @@ -171,7 +174,9 @@ public class BrowserInfo { if (osClass != null) { cssClass = cssClass + " " + prefix + osClass; } - + if (isTouchDevice()) { + cssClass = cssClass + " " + prefix + UI_TOUCH; + } } return cssClass; -- cgit v1.2.3 From bb48c7e56e9ae66ef7b74e5c055c91b7c309b60c Mon Sep 17 00:00:00 2001 From: Automerge Date: Fri, 25 May 2012 13:06:27 +0000 Subject: [merge from 6.7] Try to fix a sporadic test failure on IE svn changeset:23831/svn branch:6.8 --- .../tests/components/table/RowUpdateShouldRetainContextMenu.html | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/testbench/com/vaadin/tests/components/table/RowUpdateShouldRetainContextMenu.html b/tests/testbench/com/vaadin/tests/components/table/RowUpdateShouldRetainContextMenu.html index e13aa5a3e5..65487d8fa8 100644 --- a/tests/testbench/com/vaadin/tests/components/table/RowUpdateShouldRetainContextMenu.html +++ b/tests/testbench/com/vaadin/tests/components/table/RowUpdateShouldRetainContextMenu.html @@ -21,6 +21,11 @@ vaadin=runRowUpdateShouldRetainContextMenu::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[1]/VScrollTable[0]/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[3]/domChild[0]/domChild[0] 10,10 + + pause + 1000 + + assertText vaadin=runRowUpdateShouldRetainContextMenu::Root/VContextMenu[0]#option0 -- cgit v1.2.3 From 60c1b8b4c379a5d526c660eb3931e38ece859eb0 Mon Sep 17 00:00:00 2001 From: Johannes Dahlström Date: Fri, 25 May 2012 14:00:45 +0000 Subject: #8625 Fixed a regression caused by #8720 changes (touch scroll support) svn changeset:23832/svn branch:6.8 --- src/com/vaadin/terminal/gwt/client/ui/VTabsheet.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/com/vaadin/terminal/gwt/client/ui/VTabsheet.java b/src/com/vaadin/terminal/gwt/client/ui/VTabsheet.java index d3836bb177..9161cb798d 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VTabsheet.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VTabsheet.java @@ -350,6 +350,7 @@ public class VTabsheet extends VTabsheetBase implements Focusable, } return width; } + public Element getCloseButton() { return closeButton; } @@ -1274,7 +1275,7 @@ public class VTabsheet extends VTabsheetBase implements Focusable, */ if (BrowserInfo.get().isFirefox() || BrowserInfo.get().isIE9()) { Util.setStyleTemporarily((Element) tp.getElement() - .getFirstChildElement(), "overflow", ""); + .getFirstChildElement(), "overflow", "hidden"); } return false; } else { -- cgit v1.2.3 From 74ca8ce87118ca4b028968c68b4106edd2daa2d0 Mon Sep 17 00:00:00 2001 From: Leif Åstrand Date: Tue, 29 May 2012 13:48:23 +0300 Subject: Add support for building TestingWidgetSet (#8469) --- build/build.xml | 34 ++++++++++++++++------ .../tests/widgetset/TestingWidgetSet.gwt.xml | 6 ++++ 2 files changed, 31 insertions(+), 9 deletions(-) create mode 100644 tests/testbench/com/vaadin/tests/widgetset/TestingWidgetSet.gwt.xml diff --git a/build/build.xml b/build/build.xml index 573c799f7d..801be1b846 100644 --- a/build/build.xml +++ b/build/build.xml @@ -38,7 +38,7 @@ - + @@ -55,6 +55,12 @@ + + + + + + @@ -492,12 +498,7 @@ Compiling widgetset ${widgetset}. Output directory: ${widgetsets-output-dir} - - - - - - + @@ -519,14 +520,27 @@ - + + + + + + + + + + + + + + - + @@ -538,6 +552,7 @@ Compiling widget sets in parallel. + @@ -556,6 +571,7 @@ + diff --git a/tests/testbench/com/vaadin/tests/widgetset/TestingWidgetSet.gwt.xml b/tests/testbench/com/vaadin/tests/widgetset/TestingWidgetSet.gwt.xml new file mode 100644 index 0000000000..bd91d05b02 --- /dev/null +++ b/tests/testbench/com/vaadin/tests/widgetset/TestingWidgetSet.gwt.xml @@ -0,0 +1,6 @@ + + + + + + -- cgit v1.2.3 From 6cc33ff6167da0d18dd9a5ff0f15ba544c40aef8 Mon Sep 17 00:00:00 2001 From: Leif Åstrand Date: Tue, 29 May 2012 13:49:17 +0300 Subject: Verify that @Widgetset loads the right widgetset (#7885) This is testable now that we have a separate widgetset for testing. --- .../tests/components/root/TestRootWidgetset.html | 0 .../tests/components/root/TestRootWidgetset.java | 7 +++--- .../tests/components/root/TestRootWidgetset2.java | 24 ++++++++++++++++++++ .../MissingFromDefaultWidgetsetConnector.java | 26 ++++++++++++++++++++++ .../MissingFromDefaultWidgetsetComponent.java | 10 +++++++++ 5 files changed, 64 insertions(+), 3 deletions(-) create mode 100644 tests/testbench/com/vaadin/tests/components/root/TestRootWidgetset.html create mode 100644 tests/testbench/com/vaadin/tests/components/root/TestRootWidgetset2.java create mode 100644 tests/testbench/com/vaadin/tests/widgetset/client/MissingFromDefaultWidgetsetConnector.java create mode 100644 tests/testbench/com/vaadin/tests/widgetset/server/MissingFromDefaultWidgetsetComponent.java diff --git a/tests/testbench/com/vaadin/tests/components/root/TestRootWidgetset.html b/tests/testbench/com/vaadin/tests/components/root/TestRootWidgetset.html new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/testbench/com/vaadin/tests/components/root/TestRootWidgetset.java b/tests/testbench/com/vaadin/tests/components/root/TestRootWidgetset.java index c9c001deb6..b92815eeed 100644 --- a/tests/testbench/com/vaadin/tests/components/root/TestRootWidgetset.java +++ b/tests/testbench/com/vaadin/tests/components/root/TestRootWidgetset.java @@ -3,18 +3,19 @@ package com.vaadin.tests.components.root; import com.vaadin.annotations.Widgetset; import com.vaadin.terminal.WrappedRequest; import com.vaadin.tests.components.AbstractTestRoot; +import com.vaadin.tests.widgetset.server.MissingFromDefaultWidgetsetComponent; -@Widgetset("invalid") +@Widgetset("com.vaadin.tests.widgetset.TestingWidgetSet") public class TestRootWidgetset extends AbstractTestRoot { @Override protected void setup(WrappedRequest request) { - // Nothing here + addComponent(new MissingFromDefaultWidgetsetComponent()); } @Override public String getTestDescription() { - return "This root should never load, as the widgetset can not be loaded"; + return "This contents if this root should work as the component is present in TestingWidgetSet"; } @Override diff --git a/tests/testbench/com/vaadin/tests/components/root/TestRootWidgetset2.java b/tests/testbench/com/vaadin/tests/components/root/TestRootWidgetset2.java new file mode 100644 index 0000000000..d3be29215e --- /dev/null +++ b/tests/testbench/com/vaadin/tests/components/root/TestRootWidgetset2.java @@ -0,0 +1,24 @@ +package com.vaadin.tests.components.root; + +import com.vaadin.terminal.WrappedRequest; +import com.vaadin.tests.components.AbstractTestRoot; +import com.vaadin.tests.widgetset.server.MissingFromDefaultWidgetsetComponent; + +public class TestRootWidgetset2 extends AbstractTestRoot { + + @Override + protected void setup(WrappedRequest request) { + addComponent(new MissingFromDefaultWidgetsetComponent()); + } + + @Override + public String getTestDescription() { + return "This contents if this root should not work as the component is not present in DefaultWidgetSet"; + } + + @Override + protected Integer getTicketNumber() { + return Integer.valueOf(7885); + } + +} diff --git a/tests/testbench/com/vaadin/tests/widgetset/client/MissingFromDefaultWidgetsetConnector.java b/tests/testbench/com/vaadin/tests/widgetset/client/MissingFromDefaultWidgetsetConnector.java new file mode 100644 index 0000000000..5b7c6d8712 --- /dev/null +++ b/tests/testbench/com/vaadin/tests/widgetset/client/MissingFromDefaultWidgetsetConnector.java @@ -0,0 +1,26 @@ +/* +@VaadinApache2LicenseForJavaFiles@ + */ +package com.vaadin.tests.widgetset.client; + +import com.vaadin.terminal.gwt.client.ui.AbstractComponentConnector; +import com.vaadin.terminal.gwt.client.ui.Connect; +import com.vaadin.terminal.gwt.client.ui.label.VLabel; +import com.vaadin.tests.widgetset.server.MissingFromDefaultWidgetsetComponent; + +@Connect(MissingFromDefaultWidgetsetComponent.class) +public class MissingFromDefaultWidgetsetConnector extends + AbstractComponentConnector { + @Override + public VLabel getWidget() { + return (VLabel) super.getWidget(); + } + + @Override + protected void init() { + getWidget() + .setText( + "This component is available in TestingWidgetset, but not in DefaultWidgetset"); + super.init(); + } +} diff --git a/tests/testbench/com/vaadin/tests/widgetset/server/MissingFromDefaultWidgetsetComponent.java b/tests/testbench/com/vaadin/tests/widgetset/server/MissingFromDefaultWidgetsetComponent.java new file mode 100644 index 0000000000..44f91538b6 --- /dev/null +++ b/tests/testbench/com/vaadin/tests/widgetset/server/MissingFromDefaultWidgetsetComponent.java @@ -0,0 +1,10 @@ +/* +@VaadinApache2LicenseForJavaFiles@ + */ +package com.vaadin.tests.widgetset.server; + +import com.vaadin.ui.AbstractComponent; + +public class MissingFromDefaultWidgetsetComponent extends AbstractComponent { + +} -- cgit v1.2.3 From 8e5b52a1bd24de51f9a08ebbe6618094400078d2 Mon Sep 17 00:00:00 2001 From: Artur Signell Date: Tue, 29 May 2012 10:57:48 +0000 Subject: Made Table serializable when using column width for row header (#8428) svn changeset:23834/svn branch:6.8 --- src/com/vaadin/ui/Table.java | 3 +- src/com/vaadin/ui/UniqueSerializable.java | 35 ++++++++++++++++++++++ .../server/component/table/TableSerialization.java | 24 +++++++++++++++ .../vaadin/tests/util/UniqueSerializableTest.java | 33 ++++++++++++++++++++ 4 files changed, 94 insertions(+), 1 deletion(-) create mode 100644 src/com/vaadin/ui/UniqueSerializable.java create mode 100644 tests/server-side/com/vaadin/tests/server/component/table/TableSerialization.java create mode 100644 tests/server-side/com/vaadin/tests/util/UniqueSerializableTest.java diff --git a/src/com/vaadin/ui/Table.java b/src/com/vaadin/ui/Table.java index a2db89cabb..564aa24991 100644 --- a/src/com/vaadin/ui/Table.java +++ b/src/com/vaadin/ui/Table.java @@ -205,7 +205,8 @@ public class Table extends AbstractSelect implements Action.Container, private static final double CACHE_RATE_DEFAULT = 2; private static final String ROW_HEADER_COLUMN_KEY = "0"; - private static final Object ROW_HEADER_FAKE_PROPERTY_ID = new Object(); + private static final Object ROW_HEADER_FAKE_PROPERTY_ID = new UniqueSerializable() { + }; /* Private table extensions to Select */ diff --git a/src/com/vaadin/ui/UniqueSerializable.java b/src/com/vaadin/ui/UniqueSerializable.java new file mode 100644 index 0000000000..f6f354ef58 --- /dev/null +++ b/src/com/vaadin/ui/UniqueSerializable.java @@ -0,0 +1,35 @@ +/* +@VaadinApache2LicenseForJavaFiles@ + */ +package com.vaadin.ui; + +import java.io.Serializable; + +/** + * A base class for generating an unique object that is serializable. + *

+ * This class is abstract but has no abstract methods to force users to create + * an anonymous inner class. Otherwise each instance will not be unique. + * + * @author Vaadin Ltd + * @version @VERSION@ + * @since 7.0 + * + */ +public abstract class UniqueSerializable implements Serializable { + + public static UniqueSerializable create() { + return new UniqueSerializable() { + }; + } + + @Override + public int hashCode() { + return getClass().hashCode(); + } + + @Override + public boolean equals(Object obj) { + return getClass() == obj.getClass(); + } +} diff --git a/tests/server-side/com/vaadin/tests/server/component/table/TableSerialization.java b/tests/server-side/com/vaadin/tests/server/component/table/TableSerialization.java new file mode 100644 index 0000000000..44dcd60fa5 --- /dev/null +++ b/tests/server-side/com/vaadin/tests/server/component/table/TableSerialization.java @@ -0,0 +1,24 @@ +package com.vaadin.tests.server.component.table; + +import junit.framework.TestCase; + +import org.apache.commons.lang.SerializationUtils; + +import com.vaadin.ui.Table; + +public class TableSerialization extends TestCase { + + public void testSerialization() { + Table t = new Table(); + byte[] ser = SerializationUtils.serialize(t); + Table t2 = (Table) SerializationUtils.deserialize(ser); + + } + public void testSerializationWithRowHeaders() { + Table t = new Table(); + t.setRowHeaderMode(Table.ROW_HEADER_MODE_EXPLICIT); + t.setColumnWidth(null, 100); + byte[] ser = SerializationUtils.serialize(t); + Table t2 = (Table) SerializationUtils.deserialize(ser); + } +} diff --git a/tests/server-side/com/vaadin/tests/util/UniqueSerializableTest.java b/tests/server-side/com/vaadin/tests/util/UniqueSerializableTest.java new file mode 100644 index 0000000000..578d983c4d --- /dev/null +++ b/tests/server-side/com/vaadin/tests/util/UniqueSerializableTest.java @@ -0,0 +1,33 @@ +/* +@VaadinApache2LicenseForJavaFiles@ + */ +package com.vaadin.tests.util; + +import java.io.Serializable; + +import junit.framework.TestCase; + +import org.apache.commons.lang.SerializationUtils; + +import com.vaadin.ui.UniqueSerializable; + +public class UniqueSerializableTest extends TestCase implements Serializable { + + public void testUniqueness() { + UniqueSerializable o1 = new UniqueSerializable() { + }; + UniqueSerializable o2 = new UniqueSerializable() { + }; + assertFalse(o1 == o2); + assertFalse(o1.equals(o2)); + } + + public void testSerialization() { + UniqueSerializable o1 = new UniqueSerializable() { + }; + UniqueSerializable d1 = (UniqueSerializable) SerializationUtils + .deserialize(SerializationUtils.serialize(o1)); + assertTrue(d1.equals(o1)); + } + +} -- cgit v1.2.3 From 16554478a54c556bc11f1c7f43800c69685772ca Mon Sep 17 00:00:00 2001 From: Artur Signell Date: Tue, 29 May 2012 11:05:39 +0000 Subject: Removed non-working/unneeded code (#8428) svn changeset:23835/svn branch:6.8 --- src/com/vaadin/ui/UniqueSerializable.java | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/com/vaadin/ui/UniqueSerializable.java b/src/com/vaadin/ui/UniqueSerializable.java index f6f354ef58..828b285538 100644 --- a/src/com/vaadin/ui/UniqueSerializable.java +++ b/src/com/vaadin/ui/UniqueSerializable.java @@ -18,11 +18,6 @@ import java.io.Serializable; */ public abstract class UniqueSerializable implements Serializable { - public static UniqueSerializable create() { - return new UniqueSerializable() { - }; - } - @Override public int hashCode() { return getClass().hashCode(); -- cgit v1.2.3 From bc630f6f294a24f5224c053634aa0ec3a6ccc7d5 Mon Sep 17 00:00:00 2001 From: Automerge Date: Tue, 29 May 2012 13:09:19 +0000 Subject: [merge from 6.7] Revert last attempt of fix for (#6039) as it doesn't fix all problems svn changeset:23839/svn branch:6.8 --- src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java b/src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java index c5ca16925b..9bfd013603 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java @@ -2118,9 +2118,6 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler, return true; } } else { - if (scrollBody == null) { - return false; - } int fakeheight = (int) Math.round(scrollBody.getRowHeight() * totalRows); int availableHeight = scrollBodyPanel.getElement().getPropertyInt( @@ -6239,15 +6236,10 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler, @Override public void setHeight(String height) { - boolean hadScrollbars = willHaveScrollbars(); this.height = height; super.setHeight(height); setContainerHeight(); - if (hadScrollbars != willHaveScrollbars()) { - triggerLazyColumnAdjustment(true); - } - if (initializedAndAttached) { updatePageLength(); } -- cgit v1.2.3 From 6d07c324f8a6268c52fe3c4eb969450622d9a985 Mon Sep 17 00:00:00 2001 From: Automerge Date: Tue, 29 May 2012 13:09:24 +0000 Subject: [merge from 6.7] #8801 TestBench test svn changeset:23840/svn branch:6.8 --- .../components/select/StylingPopupOpener.html | 32 ++++++++++++++++++ .../components/select/StylingPopupOpener.java | 38 ++++++++++++++++++++++ 2 files changed, 70 insertions(+) create mode 100644 tests/testbench/com/vaadin/tests/components/select/StylingPopupOpener.html create mode 100644 tests/testbench/com/vaadin/tests/components/select/StylingPopupOpener.java diff --git a/tests/testbench/com/vaadin/tests/components/select/StylingPopupOpener.html b/tests/testbench/com/vaadin/tests/components/select/StylingPopupOpener.html new file mode 100644 index 0000000000..48adf2edfe --- /dev/null +++ b/tests/testbench/com/vaadin/tests/components/select/StylingPopupOpener.html @@ -0,0 +1,32 @@ + + + + + + +StylingPopupOpener + + + + + + + + + + + + + + + + + + + + + + +
StylingPopupOpener
open/run/com.vaadin.tests.components.select.StylingPopupOpener?restartApplication
clickvaadin=runcomvaadintestscomponentsselectStylingPopupOpener::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[1]/VButton[0]/domChild[0]/domChild[0]
screenCapture
+ + diff --git a/tests/testbench/com/vaadin/tests/components/select/StylingPopupOpener.java b/tests/testbench/com/vaadin/tests/components/select/StylingPopupOpener.java new file mode 100644 index 0000000000..b3911f19c7 --- /dev/null +++ b/tests/testbench/com/vaadin/tests/components/select/StylingPopupOpener.java @@ -0,0 +1,38 @@ +package com.vaadin.tests.components.select; + +import com.vaadin.tests.components.TestBase; +import com.vaadin.tests.util.TestUtils; +import com.vaadin.ui.Button; +import com.vaadin.ui.Button.ClickEvent; +import com.vaadin.ui.Select; + +public class StylingPopupOpener extends TestBase { + + @Override + protected void setup() { + TestUtils + .injectCSS( + getMainWindow(), + ".v-filterselect-mystyle .v-filterselect-button { width: 50px; background-color: red; } "); + + final Select select = new Select(); + addComponent(select); + + addComponent(new Button("Update style", new Button.ClickListener() { + public void buttonClick(ClickEvent event) { + select.setStyleName("mystyle"); + } + })); + } + + @Override + protected String getDescription() { + return "VFilterSelect popup opener width is not updated when the style or theme changes"; + } + + @Override + protected Integer getTicketNumber() { + return 8801; + } + +} -- cgit v1.2.3 From 658e2255f459208ae18d79bb0e426d6c58b04c03 Mon Sep 17 00:00:00 2001 From: Leif Åstrand Date: Tue, 29 May 2012 16:22:30 +0300 Subject: Test Vaadin 7 using Chrome 19 --- tests/test.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test.xml b/tests/test.xml index 67e48ee137..090e5129f6 100644 --- a/tests/test.xml +++ b/tests/test.xml @@ -11,7 +11,7 @@ - + -- cgit v1.2.3 From 929a76b832fdbeee20dcd35668a8ed1372ff71f8 Mon Sep 17 00:00:00 2001 From: Leif Åstrand Date: Wed, 30 May 2012 09:26:26 +0300 Subject: Move dependency to the target that is not run in parallel --- build/build.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/build/build.xml b/build/build.xml index 801be1b846..4f654310c0 100644 --- a/build/build.xml +++ b/build/build.xml @@ -525,7 +525,7 @@ - + @@ -548,7 +548,7 @@ - + Compiling widget sets in parallel. @@ -571,7 +571,7 @@ - + -- cgit v1.2.3 From c4e3055fce1519471869784b55d06ada8870ac31 Mon Sep 17 00:00:00 2001 From: Leif Åstrand Date: Wed, 30 May 2012 09:35:19 +0300 Subject: Make clean-all remove screenshot errors --- build/build.xml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/build/build.xml b/build/build.xml index 4f654310c0..7771100c6b 100644 --- a/build/build.xml +++ b/build/build.xml @@ -63,6 +63,11 @@ + + + + + -- cgit v1.2.3 From 7c007b1ea84b3e671fd974c615de4e5e5b59ebc3 Mon Sep 17 00:00:00 2001 From: Leif Åstrand Date: Wed, 30 May 2012 09:37:44 +0300 Subject: Remove Table.setLazyLoading (#6010) --- src/com/vaadin/ui/Table.java | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/src/com/vaadin/ui/Table.java b/src/com/vaadin/ui/Table.java index ba4c6529c5..299eace16d 100644 --- a/src/com/vaadin/ui/Table.java +++ b/src/com/vaadin/ui/Table.java @@ -4359,19 +4359,6 @@ public class Table extends AbstractSelect implements Action.Container, } } - /** - * Table does not support lazy options loading mode. Setting this true will - * throw UnsupportedOperationException. - * - * @see com.vaadin.ui.Select#setLazyLoading(boolean) - */ - public void setLazyLoading(boolean useLazyLoading) { - if (useLazyLoading) { - throw new UnsupportedOperationException( - "Lazy options loading is not supported by Table."); - } - } - /** * Used to create "generated columns"; columns that exist only in the Table, * not in the underlying Container. Implement this interface and pass it to -- cgit v1.2.3 From f7692ee48e5436a7de67bb1539b1ea5682e3ccd7 Mon Sep 17 00:00:00 2001 From: Leif Åstrand Date: Wed, 30 May 2012 09:42:09 +0300 Subject: Missing test script contents (#7885) --- .../tests/components/root/TestRootWidgetset.html | 36 ++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/tests/testbench/com/vaadin/tests/components/root/TestRootWidgetset.html b/tests/testbench/com/vaadin/tests/components/root/TestRootWidgetset.html index e69de29bb2..c91d742581 100644 --- a/tests/testbench/com/vaadin/tests/components/root/TestRootWidgetset.html +++ b/tests/testbench/com/vaadin/tests/components/root/TestRootWidgetset.html @@ -0,0 +1,36 @@ + + + + + + +Ticket4607 + + + + + + + + + + + + + + + + + + + + + + + + + + +
Ticket4607
open/run/com.vaadin.tests.components.root.TestRootWidgetset
assertTextvaadin=runcomvaadintestscomponentsrootTestRootWidgetset::/VVerticalLayout[0]/VVerticalLayout[0]/VLabel[0]This component is available in TestingWidgetset, but not in DefaultWidgetset
open/run/com.vaadin.tests.components.root.TestRootWidgetset2
assertTextvaadin=runcomvaadintestscomponentsrootTestRootWidgetset2::/VVerticalLayout[0]/VVerticalLayout[0]/VUnknownComponent[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]Widgetset does not contain implementation for com.vaadin.tests.widgetset.server.MissingFromDefaultWidgetsetComponent. Check its component connector's @Connect mapping, widgetsets GWT module description file and re-compile your widgetset. In case you have downloaded a vaadin add-on package, you might want to refer to add-on instructions.
+ + -- cgit v1.2.3 From 1ee17867e98f1fda0b205ae06820ebb0182c9415 Mon Sep 17 00:00:00 2001 From: Leif Åstrand Date: Wed, 30 May 2012 09:44:43 +0300 Subject: Ignore some temp files created when running TestBench tests locally --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 42a4e9cc07..999a655caf 100644 --- a/.gitignore +++ b/.gitignore @@ -51,6 +51,9 @@ /build/integration-test-output /build/buildhelpers/com/vaadin/buildhelpers/*.class +# /tests/ +/tests/junit*.properties + # /bin/ /bin -- cgit v1.2.3 From 2b03c7b53cca18e4aaebd2832b9a6cd4b8699076 Mon Sep 17 00:00:00 2001 From: Leif Åstrand Date: Wed, 30 May 2012 10:29:08 +0300 Subject: Reduce number of local workers to avoid synchronization problems --- build/build.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/build.xml b/build/build.xml index 7771100c6b..b0cdea39e5 100644 --- a/build/build.xml +++ b/build/build.xml @@ -499,7 +499,7 @@ - + Compiling widgetset ${widgetset}. Output directory: ${widgetsets-output-dir} -- cgit v1.2.3 From 616387587d1377d0088a87d6831d984667f8eb3a Mon Sep 17 00:00:00 2001 From: Automerge Date: Wed, 30 May 2012 09:09:06 +0000 Subject: [merge from 6.7] Make ClickEventHandler fire clicks only if mousedown and mouseup match (#4120) svn changeset:23846/svn branch:6.8 --- src/com/vaadin/terminal/gwt/client/Util.java | 16 +++ .../terminal/gwt/client/ui/ClickEventHandler.java | 79 ++++++++++++- .../orderedlayout/LayoutClickListenerTest.html | 29 +++-- .../PanelClickListenerRelativeCoordinates.html | 6 +- .../tests/layouts/TestLayoutClickListeners.html | 128 ++++++++++++++++++++- 5 files changed, 233 insertions(+), 25 deletions(-) diff --git a/src/com/vaadin/terminal/gwt/client/Util.java b/src/com/vaadin/terminal/gwt/client/Util.java index cb2539daa5..1a9991bb80 100644 --- a/src/com/vaadin/terminal/gwt/client/Util.java +++ b/src/com/vaadin/terminal/gwt/client/Util.java @@ -1156,6 +1156,22 @@ public class Util { } } + /** + * Find the element corresponding to the coordinates in the passed mouse + * event. Please note that this is not always the same as the target of the + * element e.g. if event capture is used. + * + * @param event + * the mouse event to get coordinates from + * @return the element at the coordinates of the event + */ + public static Element getElementUnderMouse(NativeEvent event) { + int pageX = getTouchOrMouseClientX(event); + int pageY = getTouchOrMouseClientY(event); + + return getElementFromPoint(pageX, pageY); + } + /** * A helper method to return the client position from an event. Returns * position from either first changed touch (if touch event) or from the diff --git a/src/com/vaadin/terminal/gwt/client/ui/ClickEventHandler.java b/src/com/vaadin/terminal/gwt/client/ui/ClickEventHandler.java index 3deb140d30..79ae5167fc 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/ClickEventHandler.java +++ b/src/com/vaadin/terminal/gwt/client/ui/ClickEventHandler.java @@ -6,33 +6,79 @@ package com.vaadin.terminal.gwt.client.ui; import java.util.HashMap; import java.util.Map; +import com.google.gwt.core.client.JavaScriptObject; import com.google.gwt.dom.client.NativeEvent; import com.google.gwt.event.dom.client.ContextMenuEvent; import com.google.gwt.event.dom.client.ContextMenuHandler; import com.google.gwt.event.dom.client.DomEvent; import com.google.gwt.event.dom.client.DoubleClickEvent; import com.google.gwt.event.dom.client.DoubleClickHandler; +import com.google.gwt.event.dom.client.MouseDownEvent; +import com.google.gwt.event.dom.client.MouseDownHandler; import com.google.gwt.event.dom.client.MouseUpEvent; import com.google.gwt.event.dom.client.MouseUpHandler; import com.google.gwt.event.shared.EventHandler; import com.google.gwt.event.shared.HandlerRegistration; import com.google.gwt.user.client.Element; +import com.google.gwt.user.client.Event; +import com.google.gwt.user.client.Event.NativePreviewEvent; +import com.google.gwt.user.client.Event.NativePreviewHandler; import com.google.gwt.user.client.ui.Widget; import com.vaadin.terminal.gwt.client.ApplicationConnection; import com.vaadin.terminal.gwt.client.MouseEventDetails; import com.vaadin.terminal.gwt.client.Paintable; +import com.vaadin.terminal.gwt.client.Util; public abstract class ClickEventHandler implements DoubleClickHandler, - ContextMenuHandler, MouseUpHandler { + ContextMenuHandler, MouseUpHandler, MouseDownHandler { private HandlerRegistration doubleClickHandlerRegistration; private HandlerRegistration mouseUpHandlerRegistration; + private HandlerRegistration mouseDownHandlerRegistration; private HandlerRegistration contextMenuHandlerRegistration; protected String clickEventIdentifier; protected Paintable paintable; private ApplicationConnection client; + /** + * The element where the last mouse down event was registered. + */ + private JavaScriptObject lastMouseDownTarget; + + /** + * Set to true by {@link #mouseUpPreviewHandler} if it gets a mouseup at the + * same element as {@link #lastMouseDownTarget}. + */ + private boolean mouseUpPreviewMatched = false; + + private HandlerRegistration mouseUpEventPreviewRegistration; + + /** + * Previews events after a mousedown to detect where the following mouseup + * hits. + */ + private final NativePreviewHandler mouseUpPreviewHandler = new NativePreviewHandler() { + public void onPreviewNativeEvent(NativePreviewEvent event) { + if (event.getTypeInt() == Event.ONMOUSEUP) { + mouseUpEventPreviewRegistration.removeHandler(); + + // Event's reported target not always correct if event + // capture is in use + Element elementUnderMouse = Util.getElementUnderMouse(event + .getNativeEvent()); + if (lastMouseDownTarget != null + && elementUnderMouse.cast() == lastMouseDownTarget) { + mouseUpPreviewMatched = true; + } else { + System.out.println("Ignoring mouseup from " + + elementUnderMouse + " when mousedown was on " + + lastMouseDownTarget); + } + } + } + }; + public ClickEventHandler(Paintable paintable, String clickEventIdentifier) { this.paintable = paintable; this.clickEventIdentifier = clickEventIdentifier; @@ -46,6 +92,8 @@ public abstract class ClickEventHandler implements DoubleClickHandler, if (mouseUpHandlerRegistration == null) { mouseUpHandlerRegistration = registerHandler(this, MouseUpEvent.getType()); + mouseDownHandlerRegistration = registerHandler(this, + MouseDownEvent.getType()); contextMenuHandlerRegistration = registerHandler(this, ContextMenuEvent.getType()); doubleClickHandlerRegistration = registerHandler(this, @@ -56,10 +104,12 @@ public abstract class ClickEventHandler implements DoubleClickHandler, // Remove existing handlers doubleClickHandlerRegistration.removeHandler(); mouseUpHandlerRegistration.removeHandler(); + mouseDownHandlerRegistration.removeHandler(); contextMenuHandlerRegistration.removeHandler(); contextMenuHandlerRegistration = null; mouseUpHandlerRegistration = null; + mouseDownHandlerRegistration = null; doubleClickHandlerRegistration = null; } @@ -101,14 +151,33 @@ public abstract class ClickEventHandler implements DoubleClickHandler, } + public void onMouseDown(MouseDownEvent event) { + /* + * When getting a mousedown event, we must detect where the + * corresponding mouseup event if it's on a different part of the page. + */ + lastMouseDownTarget = event.getNativeEvent().getEventTarget(); + mouseUpPreviewMatched = false; + mouseUpEventPreviewRegistration = Event + .addNativePreviewHandler(mouseUpPreviewHandler); + } + public void onMouseUp(MouseUpEvent event) { - // TODO For perfect accuracy we should check that a mousedown has - // occured on this element before this mouseup and that no mouseup - // has occured anywhere after that. - if (hasEventListener()) { + /* + * Only fire a click if the mouseup hits the same element as the + * corresponding mousedown. This is first checked in the event preview + * but we can't fire the even there as the event might get canceled + * before it gets here. + */ + if (hasEventListener() + && mouseUpPreviewMatched + && lastMouseDownTarget != null + && Util.getElementUnderMouse(event.getNativeEvent()) == lastMouseDownTarget) { // "Click" with left, right or middle button fireClick(event.getNativeEvent()); } + mouseUpPreviewMatched = false; + lastMouseDownTarget = null; } public void onDoubleClick(DoubleClickEvent event) { diff --git a/tests/testbench/com/vaadin/tests/components/orderedlayout/LayoutClickListenerTest.html b/tests/testbench/com/vaadin/tests/components/orderedlayout/LayoutClickListenerTest.html index 6b850fb52a..4d33294dca 100644 --- a/tests/testbench/com/vaadin/tests/components/orderedlayout/LayoutClickListenerTest.html +++ b/tests/testbench/com/vaadin/tests/components/orderedlayout/LayoutClickListenerTest.html @@ -19,74 +19,73 @@ mouseClick vaadin=runcomvaadintestscomponentsorderedlayoutLayoutClickListenerTest::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VGridLayout[0]/AbsolutePanel[0]/ChildComponentContainer[0]/VTextField[0] - + 5,5 mouseClick vaadin=runcomvaadintestscomponentsorderedlayoutLayoutClickListenerTest::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VGridLayout[0]/AbsolutePanel[0]/ChildComponentContainer[1]/VLink[0]/domChild[0]/domChild[0] - + 5,5 mouseClick vaadin=runcomvaadintestscomponentsorderedlayoutLayoutClickListenerTest::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VGridLayout[0]/AbsolutePanel[0]/ChildComponentContainer[2]/VFilterSelect[0]/domChild[0] - + 5,5 mouseClick vaadin=runcomvaadintestscomponentsorderedlayoutLayoutClickListenerTest::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VGridLayout[0]/AbsolutePanel[0]/ChildComponentContainer[3]/VTabsheet[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]/domChild[1]/domChild[0] - + 5,5 mouseClick vaadin=runcomvaadintestscomponentsorderedlayoutLayoutClickListenerTest::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VGridLayout[0]/AbsolutePanel[0]/ChildComponentContainer[3]/VTabsheet[0]/VTabsheetPanel[0]/VVerticalLayout[0]/ChildComponentContainer[0]/VLabel[0] - + 5,5 mouseClick vaadin=runcomvaadintestscomponentsorderedlayoutLayoutClickListenerTest::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VGridLayout[0]/AbsolutePanel[0]/ChildComponentContainer[3]/VTabsheet[0]/VTabsheetPanel[0]/VVerticalLayout[0]/ChildComponentContainer[1]/VTextField[0] - + 5,5 mouseClick vaadin=runcomvaadintestscomponentsorderedlayoutLayoutClickListenerTest::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VGridLayout[0]/AbsolutePanel[0]/ChildComponentContainer[3]/VTabsheet[0]/VTabsheetPanel[0]/VVerticalLayout[0]/ChildComponentContainer[2]/VLink[0]/domChild[0]/domChild[0] - + 5,5 mouseClick - vaadin=runcomvaadintestscomponentsorderedlayoutLayoutClickListenerTest::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VGridLayout[0]/AbsolutePanel[0]/ChildComponentContainer[3]/VTabsheet[0]/VTabsheetPanel[0]/VVerticalLayout[0]/domChild[0]/domChild[1] - + vaadin=runcomvaadintestscomponentsorderedlayoutLayoutClickListenerTest::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VGridLayout[0]/AbsolutePanel[0]/ChildComponentContainer[3]/VTabsheet[0]/VTabsheetPanel[0]/VVerticalLayout[0] + 396,87 mouseClick vaadin=runcomvaadintestscomponentsorderedlayoutLayoutClickListenerTest::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VGridLayout[0]/AbsolutePanel[0]/ChildComponentContainer[4]/VVerticalLayout[0]/ChildComponentContainer[0]/VLabel[0] - + 5,5 mouseClick vaadin=runcomvaadintestscomponentsorderedlayoutLayoutClickListenerTest::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VGridLayout[0]/AbsolutePanel[0]/ChildComponentContainer[4]/VVerticalLayout[0]/ChildComponentContainer[1]/VTextField[0] - + 5,5 mouseClick vaadin=runcomvaadintestscomponentsorderedlayoutLayoutClickListenerTest::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VGridLayout[0]/AbsolutePanel[0]/ChildComponentContainer[4]/VVerticalLayout[0]/ChildComponentContainer[2]/VLink[0]/domChild[0]/domChild[0] - + 5,5 mouseClick vaadin=runcomvaadintestscomponentsorderedlayoutLayoutClickListenerTest::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VGridLayout[0]/AbsolutePanel[0]/ChildComponentContainer[4]/VVerticalLayout[0]/ChildComponentContainer[3]/VHorizontalLayout[0]/ChildComponentContainer[0]/VLabel[0] - + 5,5 mouseClick vaadin=runcomvaadintestscomponentsorderedlayoutLayoutClickListenerTest::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VGridLayout[0]/domChild[0]/domChild[0] - + 1135,146 screenCapture everything_clicked - diff --git a/tests/testbench/com/vaadin/tests/components/panel/PanelClickListenerRelativeCoordinates.html b/tests/testbench/com/vaadin/tests/components/panel/PanelClickListenerRelativeCoordinates.html index eb40765d03..4b71c5a9a9 100644 --- a/tests/testbench/com/vaadin/tests/components/panel/PanelClickListenerRelativeCoordinates.html +++ b/tests/testbench/com/vaadin/tests/components/panel/PanelClickListenerRelativeCoordinates.html @@ -28,10 +28,10 @@ mouseClick - vaadin=runcomvaadintestscomponentspanelPanelClickListenerRelativeCoordinates::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VPanel[0] - 287,25 + vaadin=runcomvaadintestscomponentspanelPanelClickListenerRelativeCoordinates::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VPanel[0]/VVerticalLayout[0] + 287,6 - + + drag + vaadin=runcomvaadintestslayoutsTestLayoutClickListeners::/VVerticalLayout[0]/ChildComponentContainer[1]/VHorizontalLayout[0]/ChildComponentContainer[0]/VVerticalLayout[0]/ChildComponentContainer[1]/VGridLayout[0]/AbsolutePanel[0]/ChildComponentContainer[0]/VLabel[0] + 40,8 + + + drop + vaadin=runcomvaadintestslayoutsTestLayoutClickListeners::/VVerticalLayout[0]/ChildComponentContainer[1]/VHorizontalLayout[0]/ChildComponentContainer[0]/VVerticalLayout[0]/ChildComponentContainer[1]/VGridLayout[0]/AbsolutePanel[0]/ChildComponentContainer[0]/VLabel[0] + 40,8 + + + assertText + vaadin=runcomvaadintestslayoutsTestLayoutClickListeners::PID_SLog_row_0 + exact:GridLayout: left click on This is label 1 + + + drag + vaadin=runcomvaadintestslayoutsTestLayoutClickListeners::/VVerticalLayout[0]/ChildComponentContainer[1]/VHorizontalLayout[0]/ChildComponentContainer[0]/VVerticalLayout[0]/ChildComponentContainer[1]/VGridLayout[0]/AbsolutePanel[0]/ChildComponentContainer[0]/VLabel[0] + 24,7 + + + drop + vaadin=runcomvaadintestslayoutsTestLayoutClickListeners::/VVerticalLayout[0]/ChildComponentContainer[1]/VHorizontalLayout[0]/ChildComponentContainer[0]/VVerticalLayout[0]/ChildComponentContainer[1]/VGridLayout[0]/AbsolutePanel[0]/ChildComponentContainer[4]/VTextField[0] + 46,13 + + + assertText + vaadin=runcomvaadintestslayoutsTestLayoutClickListeners::PID_SLog_row_0 + exact:GridLayout: left click on This is label 1 + + + + drag + vaadin=runcomvaadintestslayoutsTestLayoutClickListeners::/VVerticalLayout[0]/ChildComponentContainer[1]/VHorizontalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[4]/VTextField[0] + 25,9 + + + drop + vaadin=runcomvaadintestslayoutsTestLayoutClickListeners::/VVerticalLayout[0]/ChildComponentContainer[1]/VHorizontalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[4]/VTextField[0] + 25,9 + + + assertText + vaadin=runcomvaadintestslayoutsTestLayoutClickListeners::PID_SLog_row_0 + exact:VerticalLayout: left click on This is tf5 + + + drag + vaadin=runcomvaadintestslayoutsTestLayoutClickListeners::/VVerticalLayout[0]/ChildComponentContainer[1]/VHorizontalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/domChild[0]/domChild[8]/domChild[0]/domChild[0] + 28,11 + + + drop + vaadin=runcomvaadintestslayoutsTestLayoutClickListeners::/VVerticalLayout[0]/ChildComponentContainer[1]/VHorizontalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[8]/VTextField[0] + 39,7 + + + assertText + vaadin=runcomvaadintestslayoutsTestLayoutClickListeners::PID_SLog_row_0 + exact:VerticalLayout: left click on This is tf5 + + + + drag + vaadin=runcomvaadintestslayoutsTestLayoutClickListeners::/VVerticalLayout[0]/ChildComponentContainer[1]/VHorizontalLayout[0]/ChildComponentContainer[2]/VAbsoluteLayout[0]/domChild[0]/domChild[0]/domChild[1]/domChild[0] + 21,9 + + + drop + vaadin=runcomvaadintestslayoutsTestLayoutClickListeners::/VVerticalLayout[0]/ChildComponentContainer[1]/VHorizontalLayout[0]/ChildComponentContainer[2]/VAbsoluteLayout[0]/domChild[0]/domChild[0]/domChild[1]/domChild[0] + 21,9 + + + assertText + vaadin=runcomvaadintestslayoutsTestLayoutClickListeners::PID_SLog_row_0 + exact:AbsoluteLayout: left click on This is its caption + + + drag + vaadin=runcomvaadintestslayoutsTestLayoutClickListeners::/VVerticalLayout[0]/ChildComponentContainer[1]/VHorizontalLayout[0]/ChildComponentContainer[2]/VAbsoluteLayout[0]/VAbsoluteLayout$AbsoluteWrapper[0]/VTextField[0] + 54,7 + + + drop + vaadin=runcomvaadintestslayoutsTestLayoutClickListeners::/VVerticalLayout[0]/ChildComponentContainer[1]/VHorizontalLayout[0]/ChildComponentContainer[2]/VAbsoluteLayout[0]/VAbsoluteLayout$AbsoluteWrapper[1]/VTextField[0] + 52,10 + + + assertText + vaadin=runcomvaadintestslayoutsTestLayoutClickListeners::PID_SLog_row_0 + exact:AbsoluteLayout: left click on This is its caption + + + + drag + vaadin=runcomvaadintestslayoutsTestLayoutClickListeners::/VVerticalLayout[0]/ChildComponentContainer[1]/VHorizontalLayout[0]/ChildComponentContainer[3]/VCssLayout[0]/VCssLayout$FlowPane[0]/VTextField[0] + 51,7 + + + drop + vaadin=runcomvaadintestslayoutsTestLayoutClickListeners::/VVerticalLayout[0]/ChildComponentContainer[1]/VHorizontalLayout[0]/ChildComponentContainer[3]/VCssLayout[0]/VCssLayout$FlowPane[0]/VTextField[0] + 51,7 + + + assertText + vaadin=runcomvaadintestslayoutsTestLayoutClickListeners::PID_SLog_row_0 + exact:CSSLayout: left click on This is its caption + + + drag + vaadin=runcomvaadintestslayoutsTestLayoutClickListeners::/VVerticalLayout[0]/ChildComponentContainer[1]/VHorizontalLayout[0]/ChildComponentContainer[3]/VCssLayout[0]/domChild[0]/domChild[0]/domChild[2]/domChild[0] + 31,7 + + + drop + vaadin=runcomvaadintestslayoutsTestLayoutClickListeners::/VVerticalLayout[0]/ChildComponentContainer[1]/VHorizontalLayout[0]/ChildComponentContainer[3]/VCssLayout[0]/VCssLayout$FlowPane[0]/VTextField[1] + 33,7 + + + assertText + vaadin=runcomvaadintestslayoutsTestLayoutClickListeners::PID_SLog_row_0 + exact:CSSLayout: left click on This is its caption + -- cgit v1.2.3 From e3c2e2efbed6452a365483aadfc147c4ae6ffdad Mon Sep 17 00:00:00 2001 From: Tapio Aali Date: Wed, 30 May 2012 10:02:29 +0000 Subject: Added options for setting maximum and minimum split positions to SplitPanel (#1744). svn changeset:23850/svn branch:6.8 --- .../vaadin/terminal/gwt/client/ui/VSplitPanel.java | 119 +++++++-- src/com/vaadin/ui/AbstractSplitPanel.java | 110 +++++++- .../SplitPanelWithMinimumAndMaximum.html | 207 ++++++++++++++++ .../SplitPanelWithMinimumAndMaximum.java | 276 +++++++++++++++++++++ 4 files changed, 691 insertions(+), 21 deletions(-) create mode 100644 tests/testbench/com/vaadin/tests/components/splitpanel/SplitPanelWithMinimumAndMaximum.html create mode 100644 tests/testbench/com/vaadin/tests/components/splitpanel/SplitPanelWithMinimumAndMaximum.java diff --git a/src/com/vaadin/terminal/gwt/client/ui/VSplitPanel.java b/src/com/vaadin/terminal/gwt/client/ui/VSplitPanel.java index 5a996954a0..4cb183917f 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VSplitPanel.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VSplitPanel.java @@ -147,6 +147,10 @@ public class VSplitPanel extends ComplexPanel implements Container, /* The current position of the split handle in either percentages or pixels */ private String position; + private String maximumPosition; + + private String minimumPosition; + private final TouchScrollHandler touchScrollHandler; protected Element scrolledContainer; @@ -272,6 +276,10 @@ public class VSplitPanel extends ComplexPanel implements Container, touchScrollHandler.setElements(firstContainer, secondContainer); position = uidl.getStringAttribute("position"); + + minimumPosition = uidl.getStringAttribute("minimumPosition"); + maximumPosition = uidl.getStringAttribute("maximumPosition"); + setSplitPosition(position); final Paintable newFirstChild = client.getPaintable(uidl @@ -346,11 +354,100 @@ public class VSplitPanel extends ComplexPanel implements Container, } } + /** + * Converts given split position string (in pixels or percentage) to a + * floating point pixel value. + * + * @param pos + * @return + */ + private float convertToPixels(String pos) { + float posAsFloat; + if (pos.indexOf("%") > 0) { + posAsFloat = Math.round(Float.parseFloat(pos.substring(0, + pos.length() - 1)) + / 100 + * (orientation == ORIENTATION_HORIZONTAL ? getOffsetWidth() + : getOffsetHeight())); + } else { + posAsFloat = Float.parseFloat(pos.substring(0, pos.length() - 2)); + } + return posAsFloat; + } + + /** + * Converts given split position string (in pixels or percentage) to a float + * percentage value. + * + * @param pos + * @return + */ + private float convertToPercentage(String pos) { + float posAsFloat = 0; + + if (pos.indexOf("px") > 0) { + int posAsInt = Integer.parseInt(pos.substring(0, pos.length() - 2)); + int offsetLength = orientation == ORIENTATION_HORIZONTAL ? getOffsetWidth() + : getOffsetHeight(); + + // 100% needs special handling + if (posAsInt + getSplitterSize() >= offsetLength) { + posAsInt = offsetLength; + } + // Reversed position + if (positionReversed) { + posAsInt = offsetLength - posAsInt - getSplitterSize(); + } + posAsFloat = ((float) posAsInt / (float) getOffsetWidth() * 100); + + } else { + posAsFloat = Float.parseFloat(pos.substring(0, pos.length() - 1)); + } + return posAsFloat; + } + + private String checkSplitPositionLimits(String pos) { + float positionAsFloat = convertToPixels(pos); + float maximumAsFloat = convertToPixels(maximumPosition); + float minimumAsFloat = convertToPixels(minimumPosition); + + if (maximumAsFloat < positionAsFloat) { + pos = maximumPosition; + } else if (minimumAsFloat > positionAsFloat) { + pos = minimumPosition; + } + return pos; + } + + /** + * Converts given string to the same units as the split position is. + * + * @param pos + * position to be converted + * @return converted position string + */ + private String convertToPositionUnits(String pos) { + if (position.indexOf("%") != -1 && pos.indexOf("%") == -1) { + // position is in percentage, pos in pixels + pos = convertToPercentage(pos) + "%"; + } else if (position.indexOf("px") > 0 && pos.indexOf("px") == -1) { + // position is in pixels and pos in percentage + pos = convertToPixels(pos) + "px"; + } + + return pos; + } + private void setSplitPosition(String pos) { if (pos == null) { return; } + pos = checkSplitPositionLimits(pos); + if (!pos.equals(position)) { + position = convertToPositionUnits(pos); + } + // Convert percentage values to pixels if (pos.indexOf("%") > 0) { pos = Float.parseFloat(pos.substring(0, pos.length() - 1)) @@ -564,16 +661,7 @@ public class VSplitPanel extends ComplexPanel implements Container, } if (position.indexOf("%") > 0) { - float pos = newX; - // 100% needs special handling - if (newX + getSplitterSize() >= getOffsetWidth()) { - pos = getOffsetWidth(); - } - // Reversed position - if (positionReversed) { - pos = getOffsetWidth() - pos - getSplitterSize(); - } - position = (pos / getOffsetWidth() * 100) + "%"; + position = convertToPositionUnits(newX + "px"); } else { // Reversed position if (positionReversed) { @@ -606,16 +694,7 @@ public class VSplitPanel extends ComplexPanel implements Container, } if (position.indexOf("%") > 0) { - float pos = newY; - // 100% needs special handling - if (newY + getSplitterSize() >= getOffsetHeight()) { - pos = getOffsetHeight(); - } - // Reversed position - if (positionReversed) { - pos = getOffsetHeight() - pos - getSplitterSize(); - } - position = pos / getOffsetHeight() * 100 + "%"; + position = convertToPositionUnits(newY + "px"); } else { // Reversed position if (positionReversed) { diff --git a/src/com/vaadin/ui/AbstractSplitPanel.java b/src/com/vaadin/ui/AbstractSplitPanel.java index b507b88478..ebdee17de2 100644 --- a/src/com/vaadin/ui/AbstractSplitPanel.java +++ b/src/com/vaadin/ui/AbstractSplitPanel.java @@ -22,7 +22,7 @@ import com.vaadin.tools.ReflectTools; * AbstractSplitPanel. * * AbstractSplitPanel is base class for a component container that - * can contain two components. The comopnents are split by a divider element. + * can contain two components. The components are split by a divider element. * * @author Vaadin Ltd. * @version @@ -41,6 +41,14 @@ public abstract class AbstractSplitPanel extends AbstractLayout { private boolean posReversed = false; + private int posMin = 0; + + private int posMinUnit = UNITS_PERCENTAGE; + + private int posMax = 100; + + private int posMaxUnit = UNITS_PERCENTAGE; + private boolean locked = false; private static final String SPLITTER_CLICK_EVENT = VSplitPanel.SPLITTER_CLICK_EVENT_IDENTIFIER; @@ -210,8 +218,12 @@ public abstract class AbstractSplitPanel extends AbstractLayout { super.paintContent(target); final String position = pos + UNIT_SYMBOLS[posUnit]; + final String minimumPosition = posMin + UNIT_SYMBOLS[posMinUnit]; + final String maximumPosition = posMax + UNIT_SYMBOLS[posMaxUnit]; target.addAttribute("position", position); + target.addAttribute("minimumPosition", minimumPosition); + target.addAttribute("maximumPosition", maximumPosition); if (isLocked()) { target.addAttribute("locked", true); @@ -322,6 +334,102 @@ public abstract class AbstractSplitPanel extends AbstractLayout { return posUnit; } + /** + * Sets the minimum split position to the given position and unit. If the + * split position is reversed, maximum and minimum are also reversed. + * + * @param pos + * the minimum position of the split + * @param unit + * the unit (from {@link Sizeable}) in which the size is given. + * Allowed units are UNITS_PERCENTAGE and UNITS_PIXELS + */ + public void setMinimumSplitPosition(int pos, int unit) { + setSplitPositionLimits(pos, unit, posMax, posMaxUnit); + } + + /** + * Returns the current minimum position of the splitter, in + * {@link #getMinSplitPositionUnit()} units. + * + * @return the minimum position of the splitter + */ + public int getMinSplitPosition() { + return posMin; + } + + /** + * Returns the unit of the minimum position of the splitter. + * + * @return the unit of the minimum position of the splitter + */ + public int getMinSplitPositionUnit() { + return posMinUnit; + } + + /** + * Sets the maximum split position to the given position and unit. If the + * split position is reversed, maximum and minimum are also reversed. + * + * @param pos + * the maximum position of the split + * @param unit + * the unit (from {@link Sizeable}) in which the size is given. + * Allowed units are UNITS_PERCENTAGE and UNITS_PIXELS + */ + public void setMaxSplitPosition(int pos, int unit) { + setSplitPositionLimits(posMin, posMinUnit, pos, unit); + } + + /** + * Returns the current maximum position of the splitter, in + * {@link #getMaxSplitPositionUnit()} units. + * + * @return the maximum position of the splitter + */ + public int getMaxSplitPosition() { + return posMax; + } + + /** + * Returns the unit of the maximum position of the splitter + * + * @return the unit of the maximum position of the splitter + */ + public int getMaxSplitPositionUnit() { + return posMaxUnit; + } + + /** + * Sets the maximum and minimum position of the splitter. If the split + * position is reversed, maximum and minimum are also reversed. + * + * @param minPos + * the new minimum position + * @param minPosUnit + * the unit (from {@link Sizeable}) in which the minimum position + * is given. + * @param maxPos + * the new maximum position + * @param maxPosUnit + * the unit (from {@link Sizeable}) in which the maximum position + * is given. + */ + private void setSplitPositionLimits(int minPos, int minPosUnit, int maxPos, + int maxPosUnit) { + if ((minPosUnit != UNITS_PERCENTAGE && minPosUnit != UNITS_PIXELS) + || (maxPosUnit != UNITS_PERCENTAGE && maxPosUnit != UNITS_PIXELS)) { + throw new IllegalArgumentException( + "Only percentage and pixel units are allowed"); + } + + posMin = minPos; + posMinUnit = minPosUnit; + posMax = maxPos; + posMaxUnit = maxPosUnit; + requestRepaint(); + } + /** * Moves the position of the splitter. * diff --git a/tests/testbench/com/vaadin/tests/components/splitpanel/SplitPanelWithMinimumAndMaximum.html b/tests/testbench/com/vaadin/tests/components/splitpanel/SplitPanelWithMinimumAndMaximum.html new file mode 100644 index 0000000000..3aefedeff3 --- /dev/null +++ b/tests/testbench/com/vaadin/tests/components/splitpanel/SplitPanelWithMinimumAndMaximum.html @@ -0,0 +1,207 @@ + + + + + + +SplitPanelWithMinimumAndMaximum + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
SplitPanelWithMinimumAndMaximum
open/run/com.vaadin.tests.components.splitpanel.SplitPanelWithMinimumAndMaximum?restartApplication
dragAndDropvaadin=runcomvaadintestscomponentssplitpanelSplitPanelWithMinimumAndMaximum::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VTabsheet[0]/VTabsheetPanel[0]/VVerticalLayout[0]/ChildComponentContainer[0]/VSplitPanelHorizontal[0]/domChild[0]/domChild[2]/domChild[0]-239,0
dragAndDropvaadin=runcomvaadintestscomponentssplitpanelSplitPanelWithMinimumAndMaximum::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VTabsheet[0]/VTabsheetPanel[0]/VVerticalLayout[0]/ChildComponentContainer[1]/VSplitPanelHorizontal[0]/domChild[0]/domChild[2]/domChild[0]-340,0
dragAndDropvaadin=runcomvaadintestscomponentssplitpanelSplitPanelWithMinimumAndMaximum::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VTabsheet[0]/VTabsheetPanel[0]/VVerticalLayout[0]/ChildComponentContainer[2]/VSplitPanelHorizontal[0]/domChild[0]/domChild[2]/domChild[0]-300,0
dragAndDropvaadin=runcomvaadintestscomponentssplitpanelSplitPanelWithMinimumAndMaximum::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VTabsheet[0]/VTabsheetPanel[0]/VVerticalLayout[0]/ChildComponentContainer[3]/VSplitPanelHorizontal[0]/domChild[0]/domChild[2]/domChild[0]-79,0
dragAndDropvaadin=runcomvaadintestscomponentssplitpanelSplitPanelWithMinimumAndMaximum::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VTabsheet[0]/VTabsheetPanel[0]/VVerticalLayout[0]/ChildComponentContainer[4]/VSplitPanelHorizontal[0]/domChild[0]/domChild[2]/domChild[0]-179,0
dragAndDropvaadin=runcomvaadintestscomponentssplitpanelSplitPanelWithMinimumAndMaximum::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VTabsheet[0]/VTabsheetPanel[0]/VVerticalLayout[0]/ChildComponentContainer[5]/VSplitPanelHorizontal[0]/domChild[0]/domChild[2]/domChild[0]-78,0
dragAndDropvaadin=runcomvaadintestscomponentssplitpanelSplitPanelWithMinimumAndMaximum::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VTabsheet[0]/VTabsheetPanel[0]/VVerticalLayout[0]/ChildComponentContainer[6]/VSplitPanelHorizontal[0]/domChild[0]/domChild[2]/domChild[0]-150,0
dragAndDropvaadin=runcomvaadintestscomponentssplitpanelSplitPanelWithMinimumAndMaximum::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VTabsheet[0]/VTabsheetPanel[0]/VVerticalLayout[0]/ChildComponentContainer[7]/VSplitPanelHorizontal[0]/domChild[0]/domChild[2]/domChild[0]-371,0
screenCapturehorizontal-splits-left
dragAndDropvaadin=runcomvaadintestscomponentssplitpanelSplitPanelWithMinimumAndMaximum::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VTabsheet[0]/VTabsheetPanel[0]/VVerticalLayout[0]/ChildComponentContainer[0]/VSplitPanelHorizontal[0]/domChild[0]/domChild[2]/domChild[0]418,0
dragAndDropvaadin=runcomvaadintestscomponentssplitpanelSplitPanelWithMinimumAndMaximum::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VTabsheet[0]/VTabsheetPanel[0]/VVerticalLayout[0]/ChildComponentContainer[1]/VSplitPanelHorizontal[0]/domChild[0]/domChild[2]/domChild[0]418,0
dragAndDropvaadin=runcomvaadintestscomponentssplitpanelSplitPanelWithMinimumAndMaximum::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VTabsheet[0]/VTabsheetPanel[0]/VVerticalLayout[0]/ChildComponentContainer[2]/VSplitPanelHorizontal[0]/domChild[0]/domChild[2]/domChild[0]450,0
dragAndDropvaadin=runcomvaadintestscomponentssplitpanelSplitPanelWithMinimumAndMaximum::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VTabsheet[0]/VTabsheetPanel[0]/VVerticalLayout[0]/ChildComponentContainer[3]/VSplitPanelHorizontal[0]/domChild[0]/domChild[2]/domChild[0]450,0
dragAndDropvaadin=runcomvaadintestscomponentssplitpanelSplitPanelWithMinimumAndMaximum::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VTabsheet[0]/VTabsheetPanel[0]/VVerticalLayout[0]/ChildComponentContainer[4]/VSplitPanelHorizontal[0]/domChild[0]/domChild[2]/domChild[0]418,0
dragAndDropvaadin=runcomvaadintestscomponentssplitpanelSplitPanelWithMinimumAndMaximum::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VTabsheet[0]/VTabsheetPanel[0]/VVerticalLayout[0]/ChildComponentContainer[5]/VSplitPanelHorizontal[0]/domChild[0]/domChild[2]/domChild[0]418,0
dragAndDropvaadin=runcomvaadintestscomponentssplitpanelSplitPanelWithMinimumAndMaximum::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VTabsheet[0]/VTabsheetPanel[0]/VVerticalLayout[0]/ChildComponentContainer[6]/VSplitPanelHorizontal[0]/domChild[0]/domChild[2]/domChild[0]450,0
dragAndDropvaadin=runcomvaadintestscomponentssplitpanelSplitPanelWithMinimumAndMaximum::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VTabsheet[0]/VTabsheetPanel[0]/VVerticalLayout[0]/ChildComponentContainer[7]/VSplitPanelHorizontal[0]/domChild[0]/domChild[2]/domChild[0]450,0
screenCapturehorizontal-splits-right
mouseClickvaadin=runcomvaadintestscomponentssplitpanelSplitPanelWithMinimumAndMaximum::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VTabsheet[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]/domChild[1]/domChild[0]/domChild[0]/domChild[0]44,2
dragAndDropvaadin=runcomvaadintestscomponentssplitpanelSplitPanelWithMinimumAndMaximum::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VTabsheet[0]/VTabsheetPanel[0]/VHorizontalLayout[0]/ChildComponentContainer[0]/VSplitPanelVertical[0]/domChild[0]/domChild[2]/domChild[0]0,-206
dragAndDropvaadin=runcomvaadintestscomponentssplitpanelSplitPanelWithMinimumAndMaximum::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VTabsheet[0]/VTabsheetPanel[0]/VHorizontalLayout[0]/ChildComponentContainer[1]/VSplitPanelVertical[0]/domChild[0]/domChild[2]/domChild[0]0,-348
dragAndDropvaadin=runcomvaadintestscomponentssplitpanelSplitPanelWithMinimumAndMaximum::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VTabsheet[0]/VTabsheetPanel[0]/VHorizontalLayout[0]/ChildComponentContainer[2]/VSplitPanelVertical[0]/domChild[0]/domChild[2]/domChild[0]0,-300
dragAndDropvaadin=runcomvaadintestscomponentssplitpanelSplitPanelWithMinimumAndMaximum::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VTabsheet[0]/VTabsheetPanel[0]/VHorizontalLayout[0]/ChildComponentContainer[3]/VSplitPanelVertical[0]/domChild[0]/domChild[2]/domChild[0]0,-55
dragAndDropvaadin=runcomvaadintestscomponentssplitpanelSplitPanelWithMinimumAndMaximum::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VTabsheet[0]/VTabsheetPanel[0]/VHorizontalLayout[0]/ChildComponentContainer[4]/VSplitPanelVertical[0]/domChild[0]/domChild[2]/domChild[0]0,-155
dragAndDropvaadin=runcomvaadintestscomponentssplitpanelSplitPanelWithMinimumAndMaximum::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VTabsheet[0]/VTabsheetPanel[0]/VHorizontalLayout[0]/ChildComponentContainer[5]/VSplitPanelVertical[0]/domChild[0]/domChild[2]/domChild[0]0,-13
dragAndDropvaadin=runcomvaadintestscomponentssplitpanelSplitPanelWithMinimumAndMaximum::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VTabsheet[0]/VTabsheetPanel[0]/VHorizontalLayout[0]/ChildComponentContainer[7]/VSplitPanelVertical[0]/domChild[0]/domChild[2]/domChild[0]0,-300
dragAndDropvaadin=runcomvaadintestscomponentssplitpanelSplitPanelWithMinimumAndMaximum::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VTabsheet[0]/VTabsheetPanel[0]/VHorizontalLayout[0]/ChildComponentContainer[6]/VSplitPanelVertical[0]/domChild[0]/domChild[2]/domChild[0]0,-300
screenCapturevertical-splits-up
dragAndDropvaadin=runcomvaadintestscomponentssplitpanelSplitPanelWithMinimumAndMaximum::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VTabsheet[0]/VTabsheetPanel[0]/VHorizontalLayout[0]/ChildComponentContainer[0]/VSplitPanelVertical[0]/domChild[0]/domChild[2]/domChild[0]0,361
dragAndDropvaadin=runcomvaadintestscomponentssplitpanelSplitPanelWithMinimumAndMaximum::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VTabsheet[0]/VTabsheetPanel[0]/VHorizontalLayout[0]/ChildComponentContainer[1]/VSplitPanelVertical[0]/domChild[0]/domChild[2]/domChild[0]0,361
dragAndDropvaadin=runcomvaadintestscomponentssplitpanelSplitPanelWithMinimumAndMaximum::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VTabsheet[0]/VTabsheetPanel[0]/VHorizontalLayout[0]/ChildComponentContainer[2]/VSplitPanelVertical[0]/domChild[0]/domChild[2]/domChild[0]0,350
dragAndDropvaadin=runcomvaadintestscomponentssplitpanelSplitPanelWithMinimumAndMaximum::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VTabsheet[0]/VTabsheetPanel[0]/VHorizontalLayout[0]/ChildComponentContainer[3]/VSplitPanelVertical[0]/domChild[0]/domChild[2]/domChild[0]0,350
dragAndDropvaadin=runcomvaadintestscomponentssplitpanelSplitPanelWithMinimumAndMaximum::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VTabsheet[0]/VTabsheetPanel[0]/VHorizontalLayout[0]/ChildComponentContainer[4]/VSplitPanelVertical[0]/domChild[0]/domChild[2]/domChild[0]0,361
dragAndDropvaadin=runcomvaadintestscomponentssplitpanelSplitPanelWithMinimumAndMaximum::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VTabsheet[0]/VTabsheetPanel[0]/VHorizontalLayout[0]/ChildComponentContainer[5]/VSplitPanelVertical[0]/domChild[0]/domChild[2]/domChild[0]0,361
dragAndDropvaadin=runcomvaadintestscomponentssplitpanelSplitPanelWithMinimumAndMaximum::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VTabsheet[0]/VTabsheetPanel[0]/VHorizontalLayout[0]/ChildComponentContainer[6]/VSplitPanelVertical[0]/domChild[0]/domChild[2]/domChild[0]0,300
dragAndDropvaadin=runcomvaadintestscomponentssplitpanelSplitPanelWithMinimumAndMaximum::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VTabsheet[0]/VTabsheetPanel[0]/VHorizontalLayout[0]/ChildComponentContainer[7]/VSplitPanelVertical[0]/domChild[0]/domChild[2]/domChild[0]0,300
screenCapturevertical-splits-down
+ + diff --git a/tests/testbench/com/vaadin/tests/components/splitpanel/SplitPanelWithMinimumAndMaximum.java b/tests/testbench/com/vaadin/tests/components/splitpanel/SplitPanelWithMinimumAndMaximum.java new file mode 100644 index 0000000000..9fa6fc18a3 --- /dev/null +++ b/tests/testbench/com/vaadin/tests/components/splitpanel/SplitPanelWithMinimumAndMaximum.java @@ -0,0 +1,276 @@ +package com.vaadin.tests.components.splitpanel; + +import com.vaadin.terminal.Sizeable; +import com.vaadin.tests.components.TestBase; +import com.vaadin.ui.HorizontalLayout; +import com.vaadin.ui.HorizontalSplitPanel; +import com.vaadin.ui.Label; +import com.vaadin.ui.TabSheet; +import com.vaadin.ui.VerticalLayout; +import com.vaadin.ui.VerticalSplitPanel; + +public class SplitPanelWithMinimumAndMaximum extends TestBase { + + @Override + protected void setup() { + TabSheet tabs = new TabSheet(); + + VerticalLayout horizontalSplitsLayout = new VerticalLayout(); + horizontalSplitsLayout.setCaption("Horizontal splits"); + + HorizontalSplitPanel percentagePositionWithPercentageLimitsHorizontal = new HorizontalSplitPanel(); + percentagePositionWithPercentageLimitsHorizontal + .setMinimumSplitPosition(10, Sizeable.UNITS_PERCENTAGE); + percentagePositionWithPercentageLimitsHorizontal.setMaxSplitPosition( + 80, Sizeable.UNITS_PERCENTAGE); + percentagePositionWithPercentageLimitsHorizontal + .setFirstComponent(new Label("Min 10 % - 50 % position")); + percentagePositionWithPercentageLimitsHorizontal + .setSecondComponent(new Label("Max 80 %")); + percentagePositionWithPercentageLimitsHorizontal.setSplitPosition(50, + Sizeable.UNITS_PERCENTAGE); + horizontalSplitsLayout + .addComponent(percentagePositionWithPercentageLimitsHorizontal); + + HorizontalSplitPanel pixelPositionWithPercentageLimitsHorizontal = new HorizontalSplitPanel(); + pixelPositionWithPercentageLimitsHorizontal.setMinimumSplitPosition(10, + Sizeable.UNITS_PERCENTAGE); + pixelPositionWithPercentageLimitsHorizontal.setMaxSplitPosition(80, + Sizeable.UNITS_PERCENTAGE); + pixelPositionWithPercentageLimitsHorizontal + .setFirstComponent(new Label("Min 10 % - 400 px position")); + pixelPositionWithPercentageLimitsHorizontal + .setSecondComponent(new Label("Max 80 %")); + pixelPositionWithPercentageLimitsHorizontal.setSplitPosition(400, + Sizeable.UNITS_PIXELS); + horizontalSplitsLayout + .addComponent(pixelPositionWithPercentageLimitsHorizontal); + + HorizontalSplitPanel pixelPositionWithPixelLimitsHorizontal = new HorizontalSplitPanel(); + pixelPositionWithPixelLimitsHorizontal.setMinimumSplitPosition(100, + Sizeable.UNITS_PIXELS); + pixelPositionWithPixelLimitsHorizontal.setMaxSplitPosition(550, + Sizeable.UNITS_PIXELS); + pixelPositionWithPixelLimitsHorizontal.setFirstComponent(new Label( + "Min 100 px - 400 px position")); + pixelPositionWithPixelLimitsHorizontal.setSecondComponent(new Label( + "Max 550 px")); + pixelPositionWithPixelLimitsHorizontal.setSplitPosition(400, + Sizeable.UNITS_PIXELS); + horizontalSplitsLayout + .addComponent(pixelPositionWithPixelLimitsHorizontal); + + HorizontalSplitPanel percentagePositionWithPixelLimitsHorizontal = new HorizontalSplitPanel(); + percentagePositionWithPixelLimitsHorizontal.setMinimumSplitPosition( + 100, Sizeable.UNITS_PIXELS); + percentagePositionWithPixelLimitsHorizontal.setMaxSplitPosition(550, + Sizeable.UNITS_PIXELS); + percentagePositionWithPixelLimitsHorizontal + .setFirstComponent(new Label("Min 100 px - 30 % position")); + percentagePositionWithPixelLimitsHorizontal + .setSecondComponent(new Label("Max 550 px")); + percentagePositionWithPixelLimitsHorizontal.setSplitPosition(30, + Sizeable.UNITS_PERCENTAGE); + horizontalSplitsLayout + .addComponent(percentagePositionWithPixelLimitsHorizontal); + + HorizontalSplitPanel percentagePositionWithPercentageLimitsHorizontalResersed = new HorizontalSplitPanel(); + percentagePositionWithPercentageLimitsHorizontalResersed + .setMinimumSplitPosition(10, Sizeable.UNITS_PERCENTAGE); + percentagePositionWithPercentageLimitsHorizontalResersed + .setMaxSplitPosition(80, Sizeable.UNITS_PERCENTAGE); + percentagePositionWithPercentageLimitsHorizontalResersed + .setFirstComponent(new Label( + "Max 80 % - Reversed 50 % position")); + percentagePositionWithPercentageLimitsHorizontalResersed + .setSecondComponent(new Label("Min 10 %")); + percentagePositionWithPercentageLimitsHorizontalResersed + .setSplitPosition(50, Sizeable.UNITS_PERCENTAGE, true); + horizontalSplitsLayout + .addComponent(percentagePositionWithPercentageLimitsHorizontalResersed); + + HorizontalSplitPanel pixelPositionWithPercentageLimitsHorizontalResersed = new HorizontalSplitPanel(); + pixelPositionWithPercentageLimitsHorizontalResersed + .setMinimumSplitPosition(10, Sizeable.UNITS_PERCENTAGE); + pixelPositionWithPercentageLimitsHorizontalResersed + .setMaxSplitPosition(80, Sizeable.UNITS_PERCENTAGE); + pixelPositionWithPercentageLimitsHorizontalResersed + .setFirstComponent(new Label( + "Max 80 % - Reversed 400 px position")); + pixelPositionWithPercentageLimitsHorizontalResersed + .setSecondComponent(new Label("Min 10 %")); + pixelPositionWithPercentageLimitsHorizontalResersed.setSplitPosition( + 400, Sizeable.UNITS_PIXELS, true); + horizontalSplitsLayout + .addComponent(pixelPositionWithPercentageLimitsHorizontalResersed); + + HorizontalSplitPanel pixelPositionWithPixelLimitsHorizontalResersed = new HorizontalSplitPanel(); + pixelPositionWithPixelLimitsHorizontalResersed.setMinimumSplitPosition( + 100, Sizeable.UNITS_PIXELS); + pixelPositionWithPixelLimitsHorizontalResersed.setMaxSplitPosition(550, + Sizeable.UNITS_PIXELS); + pixelPositionWithPixelLimitsHorizontalResersed + .setFirstComponent(new Label( + "Max 550 px - Reversed 400 px position")); + pixelPositionWithPixelLimitsHorizontalResersed + .setSecondComponent(new Label("Min 100 px")); + pixelPositionWithPixelLimitsHorizontalResersed.setSplitPosition(400, + Sizeable.UNITS_PIXELS, true); + horizontalSplitsLayout + .addComponent(pixelPositionWithPixelLimitsHorizontalResersed); + + HorizontalSplitPanel percentagePositionWithPixelLimitsHorizontalResersed = new HorizontalSplitPanel(); + percentagePositionWithPixelLimitsHorizontalResersed + .setMinimumSplitPosition(100, Sizeable.UNITS_PIXELS); + percentagePositionWithPixelLimitsHorizontalResersed + .setMaxSplitPosition(550, Sizeable.UNITS_PIXELS); + percentagePositionWithPixelLimitsHorizontalResersed + .setFirstComponent(new Label( + "Max 550 px - Reversed 30 % position")); + percentagePositionWithPixelLimitsHorizontalResersed + .setSecondComponent(new Label("Min 100 px")); + percentagePositionWithPixelLimitsHorizontalResersed.setSplitPosition( + 30, Sizeable.UNITS_PERCENTAGE, true); + horizontalSplitsLayout + .addComponent(percentagePositionWithPixelLimitsHorizontalResersed); + + horizontalSplitsLayout.setSizeFull(); + tabs.addComponent(horizontalSplitsLayout); + + HorizontalLayout verticalSplitsLayout = new HorizontalLayout(); + verticalSplitsLayout.setCaption("Vertical splits"); + + VerticalSplitPanel percentagePositionWithPercentageLimitsVertical = new VerticalSplitPanel(); + percentagePositionWithPercentageLimitsVertical.setMinimumSplitPosition( + 10, Sizeable.UNITS_PERCENTAGE); + percentagePositionWithPercentageLimitsVertical.setMaxSplitPosition(80, + Sizeable.UNITS_PERCENTAGE); + percentagePositionWithPercentageLimitsVertical + .setFirstComponent(new Label("Min 10 % - 50 % position")); + percentagePositionWithPercentageLimitsVertical + .setSecondComponent(new Label("Max 80 %")); + percentagePositionWithPercentageLimitsVertical.setSplitPosition(50, + Sizeable.UNITS_PERCENTAGE); + verticalSplitsLayout + .addComponent(percentagePositionWithPercentageLimitsVertical); + + VerticalSplitPanel pixelPositionWithPercentageLimitsVertical = new VerticalSplitPanel(); + pixelPositionWithPercentageLimitsVertical.setMinimumSplitPosition(10, + Sizeable.UNITS_PERCENTAGE); + pixelPositionWithPercentageLimitsVertical.setMaxSplitPosition(80, + Sizeable.UNITS_PERCENTAGE); + pixelPositionWithPercentageLimitsVertical.setFirstComponent(new Label( + "Min 10 % - 400 px position")); + pixelPositionWithPercentageLimitsVertical.setSecondComponent(new Label( + "Max 80 %")); + pixelPositionWithPercentageLimitsVertical.setSplitPosition(400, + Sizeable.UNITS_PIXELS); + verticalSplitsLayout + .addComponent(pixelPositionWithPercentageLimitsVertical); + + VerticalSplitPanel pixelPositionWithPixelLimitsVertical = new VerticalSplitPanel(); + pixelPositionWithPixelLimitsVertical.setMinimumSplitPosition(100, + Sizeable.UNITS_PIXELS); + pixelPositionWithPixelLimitsVertical.setMaxSplitPosition(450, + Sizeable.UNITS_PIXELS); + pixelPositionWithPixelLimitsVertical.setFirstComponent(new Label( + "Min 100 px - 400 px position")); + pixelPositionWithPixelLimitsVertical.setSecondComponent(new Label( + "Max 450 px")); + pixelPositionWithPixelLimitsVertical.setSplitPosition(400, + Sizeable.UNITS_PIXELS); + verticalSplitsLayout.addComponent(pixelPositionWithPixelLimitsVertical); + + VerticalSplitPanel percentagePositionWithPixelLimitsVertical = new VerticalSplitPanel(); + percentagePositionWithPixelLimitsVertical.setMinimumSplitPosition(100, + Sizeable.UNITS_PIXELS); + percentagePositionWithPixelLimitsVertical.setMaxSplitPosition(450, + Sizeable.UNITS_PIXELS); + percentagePositionWithPixelLimitsVertical.setFirstComponent(new Label( + "Min 100 px - 30 % position")); + percentagePositionWithPixelLimitsVertical.setSecondComponent(new Label( + "Max 450 px")); + percentagePositionWithPixelLimitsVertical.setSplitPosition(30, + Sizeable.UNITS_PERCENTAGE); + verticalSplitsLayout + .addComponent(percentagePositionWithPixelLimitsVertical); + + VerticalSplitPanel percentagePositionWithPercentageLimitsVerticalReversed = new VerticalSplitPanel(); + percentagePositionWithPercentageLimitsVerticalReversed + .setMinimumSplitPosition(10, Sizeable.UNITS_PERCENTAGE); + percentagePositionWithPercentageLimitsVerticalReversed + .setMaxSplitPosition(80, Sizeable.UNITS_PERCENTAGE); + percentagePositionWithPercentageLimitsVerticalReversed + .setFirstComponent(new Label( + "Max 80 % - Reversed 50 % position")); + percentagePositionWithPercentageLimitsVerticalReversed + .setSecondComponent(new Label("Min 10 %")); + percentagePositionWithPercentageLimitsVerticalReversed + .setSplitPosition(50, Sizeable.UNITS_PERCENTAGE, true); + verticalSplitsLayout + .addComponent(percentagePositionWithPercentageLimitsVerticalReversed); + + VerticalSplitPanel pixelPositionWithPercentageLimitsVerticalReversed = new VerticalSplitPanel(); + pixelPositionWithPercentageLimitsVerticalReversed + .setMinimumSplitPosition(10, Sizeable.UNITS_PERCENTAGE); + pixelPositionWithPercentageLimitsVerticalReversed.setMaxSplitPosition( + 80, Sizeable.UNITS_PERCENTAGE); + pixelPositionWithPercentageLimitsVerticalReversed + .setFirstComponent(new Label( + "Max 80 % - Reversed 400 px position")); + pixelPositionWithPercentageLimitsVerticalReversed + .setSecondComponent(new Label("Min 10 %")); + pixelPositionWithPercentageLimitsVerticalReversed.setSplitPosition(400, + Sizeable.UNITS_PIXELS, true); + verticalSplitsLayout + .addComponent(pixelPositionWithPercentageLimitsVerticalReversed); + + VerticalSplitPanel pixelPositionWithPixelLimitsVerticalReversed = new VerticalSplitPanel(); + pixelPositionWithPixelLimitsVerticalReversed.setMinimumSplitPosition( + 100, Sizeable.UNITS_PIXELS); + pixelPositionWithPixelLimitsVerticalReversed.setMaxSplitPosition(400, + Sizeable.UNITS_PIXELS); + pixelPositionWithPixelLimitsVerticalReversed + .setFirstComponent(new Label( + "Max 400 px - Reversed 300 px position")); + pixelPositionWithPixelLimitsVerticalReversed + .setSecondComponent(new Label("Min 100 px")); + pixelPositionWithPixelLimitsVerticalReversed.setSplitPosition(300, + Sizeable.UNITS_PIXELS, true); + verticalSplitsLayout + .addComponent(pixelPositionWithPixelLimitsVerticalReversed); + + VerticalSplitPanel percentagePositionWithPixelLimitsVerticalReversed = new VerticalSplitPanel(); + percentagePositionWithPixelLimitsVerticalReversed + .setMinimumSplitPosition(100, Sizeable.UNITS_PIXELS); + percentagePositionWithPixelLimitsVerticalReversed.setMaxSplitPosition( + 400, Sizeable.UNITS_PIXELS); + percentagePositionWithPixelLimitsVerticalReversed + .setFirstComponent(new Label( + "Max 400 px - Reversed 30 % position")); + percentagePositionWithPixelLimitsVerticalReversed + .setSecondComponent(new Label("Min 100 px")); + percentagePositionWithPixelLimitsVerticalReversed.setSplitPosition(30, + Sizeable.UNITS_PERCENTAGE, true); + verticalSplitsLayout + .addComponent(percentagePositionWithPixelLimitsVerticalReversed); + + tabs.addComponent(verticalSplitsLayout); + verticalSplitsLayout.setSizeFull(); + + addComponent(tabs); + tabs.setHeight("550px"); + tabs.setWidth("600px"); + getLayout().setSizeFull(); + } + + @Override + protected String getDescription() { + return "SplitPanel could have setMaxSplitPosition and setMinSplitPosition methods as a way to set maximum and minimum limits for the split position. This is not a very critical feature but could be useful in some situations."; + } + + @Override + protected Integer getTicketNumber() { + return 1744; + } +} -- cgit v1.2.3 From 6b3151d68e954ba219f577ee8ab261f4033c3265 Mon Sep 17 00:00:00 2001 From: Henri Sara Date: Wed, 30 May 2012 15:39:06 +0300 Subject: Support for additional build time non-Ivy JARs in build.xml . --- build/build.xml | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/build/build.xml b/build/build.xml index b0cdea39e5..97f7c1c274 100644 --- a/build/build.xml +++ b/build/build.xml @@ -26,9 +26,26 @@ - - - + + + + + + + + + + + + + + + + + + + + -- cgit v1.2.3 From f900ad7732663d06960caa10df4a53c51965be87 Mon Sep 17 00:00:00 2001 From: Jonatan Kronqvist Date: Wed, 30 May 2012 12:47:06 +0000 Subject: VFilterSelect implements SubPartAware #8878 svn changeset:23851/svn branch:6.8 --- .../terminal/gwt/client/ui/VFilterSelect.java | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/src/com/vaadin/terminal/gwt/client/ui/VFilterSelect.java b/src/com/vaadin/terminal/gwt/client/ui/VFilterSelect.java index 4ecb42d920..8bb2cd5b5f 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VFilterSelect.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VFilterSelect.java @@ -62,7 +62,7 @@ import com.vaadin.terminal.gwt.client.VTooltip; @SuppressWarnings("deprecation") public class VFilterSelect extends Composite implements Paintable, Field, KeyDownHandler, KeyUpHandler, ClickHandler, FocusHandler, BlurHandler, - Focusable { + Focusable, SubPartAware { /** * Represents a suggestion in the suggestion popup box @@ -2008,4 +2008,24 @@ public class VFilterSelect extends Composite implements Paintable, Field, super.onDetach(); suggestionPopup.hide(); } + + @Override + public Element getSubPartElement(String subPart) { + if ("textbox".equals(subPart)) { + return this.tb.getElement(); + } else if ("button".equals(subPart)) { + return this.popupOpener.getElement(); + } + return null; + } + + @Override + public String getSubPartName(Element subElement) { + if (tb.getElement().isOrHasChild(subElement)) { + return "textbox"; + } else if (popupOpener.getElement().isOrHasChild(subElement)) { + return "button"; + } + return null; + } } -- cgit v1.2.3 From 56d0c039f888b59179bef114cb43ce32ea4da30e Mon Sep 17 00:00:00 2001 From: Automerge Date: Wed, 30 May 2012 13:08:20 +0000 Subject: [merge from 6.7] Small tweaks to #4120 based on review svn changeset:23852/svn branch:6.8 --- src/com/vaadin/terminal/gwt/client/Util.java | 2 +- src/com/vaadin/terminal/gwt/client/ui/ClickEventHandler.java | 4 ---- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/src/com/vaadin/terminal/gwt/client/Util.java b/src/com/vaadin/terminal/gwt/client/Util.java index 1a9991bb80..4b25e6ec9e 100644 --- a/src/com/vaadin/terminal/gwt/client/Util.java +++ b/src/com/vaadin/terminal/gwt/client/Util.java @@ -1159,7 +1159,7 @@ public class Util { /** * Find the element corresponding to the coordinates in the passed mouse * event. Please note that this is not always the same as the target of the - * element e.g. if event capture is used. + * event e.g. if event capture is used. * * @param event * the mouse event to get coordinates from diff --git a/src/com/vaadin/terminal/gwt/client/ui/ClickEventHandler.java b/src/com/vaadin/terminal/gwt/client/ui/ClickEventHandler.java index 79ae5167fc..5617c94a27 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/ClickEventHandler.java +++ b/src/com/vaadin/terminal/gwt/client/ui/ClickEventHandler.java @@ -70,10 +70,6 @@ public abstract class ClickEventHandler implements DoubleClickHandler, if (lastMouseDownTarget != null && elementUnderMouse.cast() == lastMouseDownTarget) { mouseUpPreviewMatched = true; - } else { - System.out.println("Ignoring mouseup from " - + elementUnderMouse + " when mousedown was on " - + lastMouseDownTarget); } } } -- cgit v1.2.3 From 6e960199f98fda0745dd846e786e0e3b625cfcbb Mon Sep 17 00:00:00 2001 From: Marko Grönroos Date: Wed, 30 May 2012 13:30:53 +0000 Subject: Updated Release Notes for Vaadin 6.8 RC1. Cleanup of the invalid HTML formatting. svn changeset:23853/svn branch:6.8 --- WebContent/release-notes.html | 756 ++++++++++++++++++++++++------------------ 1 file changed, 437 insertions(+), 319 deletions(-) diff --git a/WebContent/release-notes.html b/WebContent/release-notes.html index 4574766ea9..3f3cc30a3d 100644 --- a/WebContent/release-notes.html +++ b/WebContent/release-notes.html @@ -1,14 +1,14 @@ - - -Vaadin Framework @version@ - + + + Vaadin Framework @version@ + - - - - - -

- + + -
+ -

Version @version@ built on @builddate@.

- -

Release Notes for Vaadin Framework - @version@

- -

Package Contents

-

- Vaadin is a Java framework for building modern web - applications that look great, perform well and make you and your - users happy. Vaadin is available under the Apache 2 license - (see license.html). -

-

- Vaadin is distributed as a single JAR file. Inside the JAR you - will find: -

    -
  • Vaadin server and client side classes (/com)
  • -
  • Vaadin server and client side sources (/com)
  • -
  • The default widget set (/VAADIN/widgetsets)
  • -
  • Themes: Runo, Reindeer and Chameleon (/VAADIN/themes)
  • -
  • Release notes (/release-notes.html)
  • -
  • Licensing information (/license.html)
  • -
-

+ - - -

Enhancements in Vaadin @version-minor@

-

- TODO: Enhancements -

-

TOdO: Enhancements.

-

Fixes in Vaadin @version@

- -

- TODO: Ticket list -

-

- The full - details of the defects can be found at dev.vaadin.com. -

- -

Backwards incompatible - changes in Vaadin @version-minor@

-

VerticalSplitPanel and HorizontalSplitPanel position is now a float instead of an int to enable defining an exact position when using percentages.

+
-

Vaadin @version@ dependencies

+

Version @version@ built on @builddate@.

+ + +

Release Notes for Vaadin Framework @version@

+ + + +

Overview of Vaadin @version-minor@ Release

+ +

+ Vaadin is a Java application development framework for building modern web + applications that look great, perform well and make you and your users + happy. Vaadin is available under the Apache 2 license (see + license.html in the JAR). +

+ +

+ This release @version-minor@ includes a number of significant enhancements in + addition to many bug fixes. +

+ + +

Enhancements in Vaadin @version-minor@

+ +
    +
  • +

    Native scrolling support for Android and iOS (#8763)

    +
      +
    • +

      Non-native scrolling implementation used in iOS 5 because of an iOS bug (see #8792)

      +
    • +
    +
  • +
  • +

    Possibility to fire Button click events on the server-side (#8209)

    +
  • +
  • +

    Possibility to use HTML inside a Button caption (#8663)

    +
  • +
  • +

    Possibility to set "alternative text" (alt attribute) for the Embedded component (#6085)

    +
  • +
  • +

    Keyboard navigation in TabSheet (#5100)

    +
  • + +
  • +

    Max/min limits for splitter position in SplitPanel (#1744)

    +
  • +
  • +

    Extended day range in month view to six full weeks in DateField (#6718)

    +
  • +
  • +

    Uncollapseable Table columns (#7495)

    +
  • +
  • +

    Debug IDs unique to a window (#5109)

    +
  • +
+ +

+ Also note: +

+ +
    +
  • +

    A separate add-on will be released for handling broken classloaders (#8447)

    +
  • +
+ + + + + + + +

Changes in Vaadin @version@

+ +

+ This release includes the following changes: +

+ +
    +
  • #1744: SplitPanel could have setMaxSplitPosition and setMinSplitPosition methods
  • +
  • #3789: Create integration test for WebSphere Application Server 8
  • +
  • #4296: SplitPanel percentage position rounding error after splitter drag
  • +
  • #5100: TabSheet keyboard navigation
  • +
  • #5109: DebugId should be window unique, not application unique
  • +
  • #5655: Add getClientWidth() and getClientHeight() to WebBrowser
  • +
  • #6085: It should be possible to set the alternate text for embedded images
  • +
  • #6155: Memory leak in AbstractField when PropertyDataSources are used
  • +
  • #6718: PopupDateField: extend its range
  • +
  • #7002: Changing Slider orientation breaks it completely
  • +
  • #7495: Table: Make some columns uncollapsable
  • +
  • #7614: Add getComponentIndex(Component) and getComponent(int) to CssLayout
  • +
  • #7718: Table footers are visible in IE6/IE7 even though footers have been turned off (Chameleon)
  • +
  • #7772: Create build configurations for Vaadin 6.8
  • +
  • #7773: Create branch for Vaadin 6.8
  • +
  • #7816: Ensure an application that uses injection works on IBM WebSphere v8
  • +
  • #7833: Make DragAndDropWrapper capable of starting an HTML5 drag
  • +
  • #7911: Touch device identifiers to div.v-app
  • +
  • #7931: Invalid top level window size for embedded applications
  • +
  • #7975: Remove non-core classes from main source directory
  • +
  • #8203: Add setSelectedTab(TabSheet.Tab) to TabSheet API
  • +
  • #8209: Button: add public click() method
  • +
  • #8216: Warning when compiling the widgetset
  • +
  • #8307: Add Field.removeAllValidators
  • +
  • #8428: Field ROW_HEADER_FAKE_PROPERTY_ID in com.vaadin.ui.Table does not implement Serializable
  • +
  • #8523: Change the default size for the debug window
  • +
  • #8551: Notifications are displayed in parts on an Asus TF101
  • +
  • #8600: Tree.hasChildren() works incorrectly after all children were removed
  • +
  • #8637: Nightly builds are not deployed to Maven
  • +
  • #8638: Build should fail with an error if Maven deployment fails
  • +
  • #8653: TabSheet#getTab(int) unintentionally throws if index out of bounds
  • +
  • #8659: Not possible to have editable cell in a table on IPad with IOS 5.x
  • +
  • #8663: html in buttons is not possible
  • +
  • #8693: setVisibile() in InlineDateSelect doesn't work correctly
  • +
  • #8694: Provide profiling data for TestBench
  • +
  • #8699: Wrap javascript callback entry points in $entry
  • +
  • #8716: Implement native scrolling support for Panel (Android 3+ & iOS 5+)
  • +
  • #8720: Implement native scrolling support for Tabsheet (Android 3+ & iOS 5+)
  • +
  • #8721: Implement native scrolling support for Window/root (Android 3+ & iOS 5+)
  • +
  • #8722: Implement native scrolling support for sub windows (Android 3+ & iOS 5+)
  • +
  • #8723: Implement native scrolling support for Accordion (Android 3+ & iOS 5+)
  • +
  • #8724: Implement native scrolling support for Table (Android 3+ & iOS 5+)
  • +
  • #8725: Implement native scrolling support for SplitPanel (Android 3+ & iOS 5+)
  • +
  • #8739: Test using Firefox 12
  • +
  • #8763: Do some groundwork to make implementing touch scrolling in various components easier
  • +
+ +

+ The full + list of the changes can be found at dev.vaadin.com. +

+ + +

Package Contents

+ +

+ Vaadin Framework is distributed as a single JAR file. Inside the JAR you will + find: +

+ +
    +
  • Vaadin server and client side classes (/com)
  • +
  • Vaadin server and client side sources (/com)
  • +
  • The default widget set (/VAADIN/widgetsets)
  • +
  • Themes: Runo, Reindeer and Chameleon (/VAADIN/themes)
  • +
  • Release notes (/release-notes.html)
  • +
  • Licensing information (/license.html)
  • +
+ + +

Vaadin @version@ dependencies

+ +

Vaadin uses GWT @gwt-version@ for widget set compilation. GWT can be downloaded from http://code.google.com/webtoolkit/. GWT can also be automatically downloaded by the Vaadin Plug-in for Eclipse. Please note that GWT @gwt-version@ requires the validation-api-1.0.0.GA.jar and validation-api-1.0.0.GA-sources.jar files in addition to gwt-dev.jar and gwt-user.jar for widget set compilation. - -

Upgrading to Vaadin @version-minor@

-

- When upgrading from an earlier Vaadin version, you must -

    -
  • Recompile your classes using the new Vaadin JAR. Binary - compatibility is only guaranteed for maintenance releases of - Vaadin.
  • -
  • Recompile any add-ons you have created using the new Vaadin - JAR.
  • -
  • Recompile your widget set using the new Vaadin JAR and the - newly compiled add-ons.
  • -
  • If you have extracted a theme from the Vaadin JAR, you need - to update it with the theme provided in the new Vaadin JAR.
  • -
-

-

Remember also to refresh the project in your IDE to ensure that - the new version of everything is in use.

-

Using the "?debug" URL parameter you can verify that the - version of the servlet (JAR), the theme and the widgetset all match.

-

- Eclipse users should always check if there is a new version of - the Eclipse Plug-in available. The Eclipse Plug-in can be used to - update the Vaadin version in the project (Project properties » - Vaadin). -

- -

- Maven users should update the Vaadin dependency version in the - pom.xml - unless it is defined as - LATEST - . You must also ensure that the GWT dependency uses the correct - version and recompile your project and your widget set. - +

+ + +

Upgrading to Vaadin @version-minor@

+ +

+ When upgrading from an earlier Vaadin version, you must: +

+ +
    +
  • Recompile your classes using the new Vaadin JAR. Binary + compatibility is only guaranteed for maintenance releases of + Vaadin.
  • +
  • Recompile any add-ons you have created using the new Vaadin + JAR.
  • +
  • Recompile your widget set using the new Vaadin JAR and the + newly compiled add-ons.
  • +
  • If you have extracted a theme from the Vaadin JAR, you need + to update it with the theme provided in the new Vaadin JAR.
  • +
+ +

Remember also to refresh the project in your IDE to ensure that the new version + of everything is in use.

+ +

Using the "?debug" URL parameter you can verify that the + version of the servlet (JAR), the theme and the widgetset all match.

+ +

+ Eclipse users should always check if there is a new version of the Eclipse + Plug-in available. The Eclipse Plug-in can be used to update the Vaadin version in + the project (Project properties » Vaadin). +

+ +

+ Maven users should update the Vaadin dependency version in the + pom.xml unless it is defined as LATEST . You must also ensure + that the GWT dependency uses the correct version and recompile your project and + your widget set.

+

Liferay and other portal users must install the new vaadin-@version@.jar as - ROOT/WEB-INF/lib/vaadin.jar in the portal. Additionally the + ROOT/WEB-INF/lib/vaadin.jar in the portal. Additionally the contents of the VAADIN folder from the JAR must be extracted to the ROOT/html/VAADIN directory in the Liferay installation. If your portal uses custom widgets, install the latest version of Vaadin Control Panel for Liferay for easy widget set compilation. +

-

Upgrading from Vaadin 6.5 or earlier

+

Upgrading from Vaadin 6.5 or earlier

+ +

If you are upgrading from 6.5.x or earlier, notice that Vaadin @version@ uses GWT @gwt-version@. Upgrade your dependencies as necessary. See the dependencies section for more information. -

+

-

Upgrading from Vaadin 6.1 or earlier

+

Upgrading from Vaadin 6.1 or earlier

-

- The way widget sets are created was completely changed in Vaadin 6.2. - Existing projects, where custom widgets (a custom widget set) are - used, must be migrated when upgrading to Vaadin 6.2 or later. - Projects where the default widget set is used do not need migration. - See Vaadin - 6.2.0 release notes for more details. -

+

+ The way widget sets are created was completely changed in Vaadin 6.2. Existing + projects, where custom widgets (a custom widget set) are used, must be migrated + when upgrading to Vaadin 6.2 or later. Projects where the default widget set is + used do not need migration. See Vaadin + 6.2.0 release notes for more details. +

-

Notes and Limitations for Google App Engine

+

Notes and Limitations for Google App Engine

-

The following instructions and limitations apply when you run a - Vaadin application under the Google App Engine.

+

+ The following instructions and limitations apply when you run a Vaadin application + under the Google App Engine. +

-
- - + + +
  • Avoid using the session for storage, usual App Engine + limitations apply (no synchronization, i.e, unreliable).

    +
  • + +
  • + Vaadin uses memcache for mutex, the key is of the form + _vmutex<sessionid>. +

    +
  • + +
  • +

    The Vaadin WebApplicationContext class is serialized separately into + memcache and datastore; the memcache key is _vac<sessionid> and + the datastore entity kind is _vac with identifiers of the type + _vac<sessionid>.

    +
  • + +
  • +

    DO NOT update application state when serving an ApplicationResource + (e.g ClassResource.getStream()).

    +
  • + +
  • +

    + AVOID (or be very careful when) updating application state in a + TransactionListener or a HttpServletRequestListener - they are + called even when the application is not locked and won't be serialized (e.g + ApplicationResource), and changes can thus go missing (it should be + safe to update things that can be safely discarded later - i.e valid only for + the current request) +

    +
  • + +
  • +

    + The application remains locked during uploads - a progress bar is not + possible +

    +
  • + + +

    + For other known problems, see open tickets at developer site dev.vaadin.com. +

    + + +

    Supported technologies

    + +

    + Vaadin is based on Java 5 and it is also compatible with most other + operating system supporting Java 5 or newer. Vaadin is supported on the following + operating systems: +

    + +
      +
    • Windows
    • +
    • Linux
    • +
    • Mac OS X
    • +
    + +

    + Vaadin requires Java Servlet API 2.3 but also supports later versions and + should work with any Java application server that conforms to the standard. The + following application servers are supported: +

    + +
      +
    • Apache Tomcat, version 4.1-7.0
    • +
    • Oracle WebLogic® Server, version 9.2-10.3.5(11gR1)
    • +
    • IBM WebSphere® Application Server, version 6.1-8.0
    • +
    • JBoss Application Server, 3.2.8-7.0
    • +
    • Jetty, version 5.0-7.0
    • +
    • Glassfish, version 2.0-3.1
    • +
    + +

    + Vaadin supports JSR-168 and JSR-286 Portlet specifications. All portals that + implement either of the portlet specifications should work. The following + portals are supported: +

    + +
      +
    • Liferay Portal 5.2-6.0
    • +
    • GateIn Portal 3.1
    • +
    • eXo Platform 3
    • +
    • Oracle WebLogic® Portal 10gR3
    • +
    • WebSphere Portal 6.1-7.0
    • +
    + +

    + Vaadin also supports Google App Engine. +

    + +

    + Vaadin supports the following browsers: +

    + +
      +
    • Mozilla Firefox 3-11
    • +
    • Internet Explorer 6-9
    • +
    • Safari 4-5
    • +
    • Opera 10-11
    • +
    • Google Chrome 13-19
    • +
    + +

    + Vaadin supports the built-in browsers in the following mobile operating + systems: +

    + +
      +
    • iOS 4-5
    • +
    • Android 2-3
    • +
    + + +

    Vaadin on the Web

    + + +
    - - - - \ No newline at end of file + vaadin }> thinking of U and I + ↑ Back to top + + + + + + -- cgit v1.2.3 From 42dff513d801eecb011ad245bb6274e1396da66b Mon Sep 17 00:00:00 2001 From: Johannes Dahlström Date: Wed, 30 May 2012 14:02:35 +0000 Subject: #1744 Fixed a regression svn changeset:23854/svn branch:6.8 --- src/com/vaadin/terminal/gwt/client/ui/VSplitPanel.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/com/vaadin/terminal/gwt/client/ui/VSplitPanel.java b/src/com/vaadin/terminal/gwt/client/ui/VSplitPanel.java index 4cb183917f..d998c3e5b4 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VSplitPanel.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VSplitPanel.java @@ -398,7 +398,7 @@ public class VSplitPanel extends ComplexPanel implements Container, if (positionReversed) { posAsInt = offsetLength - posAsInt - getSplitterSize(); } - posAsFloat = ((float) posAsInt / (float) getOffsetWidth() * 100); + posAsFloat = ((float) posAsInt / (float) offsetLength * 100); } else { posAsFloat = Float.parseFloat(pos.substring(0, pos.length() - 1)); -- cgit v1.2.3 From 113228df952c43aecd1ec13b9d24f8cb6954ddd3 Mon Sep 17 00:00:00 2001 From: Johannes Dahlström Date: Wed, 30 May 2012 14:56:51 +0000 Subject: #1744 Should not check for reversed position here svn changeset:23855/svn branch:6.8 --- src/com/vaadin/terminal/gwt/client/ui/VSplitPanel.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/com/vaadin/terminal/gwt/client/ui/VSplitPanel.java b/src/com/vaadin/terminal/gwt/client/ui/VSplitPanel.java index d998c3e5b4..613ec47f57 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VSplitPanel.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VSplitPanel.java @@ -394,10 +394,6 @@ public class VSplitPanel extends ComplexPanel implements Container, if (posAsInt + getSplitterSize() >= offsetLength) { posAsInt = offsetLength; } - // Reversed position - if (positionReversed) { - posAsInt = offsetLength - posAsInt - getSplitterSize(); - } posAsFloat = ((float) posAsInt / (float) offsetLength * 100); } else { -- cgit v1.2.3 From e978b997047573b1497a07f77f730195e3ea467a Mon Sep 17 00:00:00 2001 From: Johannes Dahlström Date: Wed, 30 May 2012 15:39:50 +0000 Subject: #8878 Cannot use @Override when implementing interface methods in Java 1.5 svn changeset:23856/svn branch:6.8 --- src/com/vaadin/terminal/gwt/client/ui/VFilterSelect.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/com/vaadin/terminal/gwt/client/ui/VFilterSelect.java b/src/com/vaadin/terminal/gwt/client/ui/VFilterSelect.java index 8bb2cd5b5f..ce254a7bc6 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VFilterSelect.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VFilterSelect.java @@ -2009,7 +2009,6 @@ public class VFilterSelect extends Composite implements Paintable, Field, suggestionPopup.hide(); } - @Override public Element getSubPartElement(String subPart) { if ("textbox".equals(subPart)) { return this.tb.getElement(); @@ -2019,7 +2018,6 @@ public class VFilterSelect extends Composite implements Paintable, Field, return null; } - @Override public String getSubPartName(Element subElement) { if (tb.getElement().isOrHasChild(subElement)) { return "textbox"; -- cgit v1.2.3 From 2e581760d056ad7038bfa5c04c6fd17c883a7d32 Mon Sep 17 00:00:00 2001 From: Tapio Aali Date: Thu, 31 May 2012 05:30:06 +0000 Subject: Optimized network usage of the split position limits of the SplitPanel (#8880). svn changeset:23857/svn branch:6.8 --- .../vaadin/terminal/gwt/client/ui/VSplitPanel.java | 22 ++++++++++++---------- src/com/vaadin/ui/AbstractSplitPanel.java | 8 ++++++-- 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/src/com/vaadin/terminal/gwt/client/ui/VSplitPanel.java b/src/com/vaadin/terminal/gwt/client/ui/VSplitPanel.java index 613ec47f57..00d76e3a45 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VSplitPanel.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VSplitPanel.java @@ -147,9 +147,9 @@ public class VSplitPanel extends ComplexPanel implements Container, /* The current position of the split handle in either percentages or pixels */ private String position; - private String maximumPosition; + private String maximumPosition = null; - private String minimumPosition; + private String minimumPosition = null; private final TouchScrollHandler touchScrollHandler; @@ -277,8 +277,10 @@ public class VSplitPanel extends ComplexPanel implements Container, position = uidl.getStringAttribute("position"); - minimumPosition = uidl.getStringAttribute("minimumPosition"); - maximumPosition = uidl.getStringAttribute("maximumPosition"); + minimumPosition = uidl.hasAttribute("minimumPosition") ? uidl + .getStringAttribute("minimumPosition") : null; + maximumPosition = uidl.hasAttribute("maximumPosition") ? uidl + .getStringAttribute("maximumPosition") : null; setSplitPosition(position); @@ -404,12 +406,12 @@ public class VSplitPanel extends ComplexPanel implements Container, private String checkSplitPositionLimits(String pos) { float positionAsFloat = convertToPixels(pos); - float maximumAsFloat = convertToPixels(maximumPosition); - float minimumAsFloat = convertToPixels(minimumPosition); - if (maximumAsFloat < positionAsFloat) { + if (maximumPosition != null + && convertToPixels(maximumPosition) < positionAsFloat) { pos = maximumPosition; - } else if (minimumAsFloat > positionAsFloat) { + } else if (minimumPosition != null + && convertToPixels(minimumPosition) > positionAsFloat) { pos = minimumPosition; } return pos; @@ -870,8 +872,8 @@ public class VSplitPanel extends ComplexPanel implements Container, if (position.indexOf("%") > 0) { pos = Float.valueOf(position.substring(0, position.length() - 1)); } else { - pos = Integer - .parseInt(position.substring(0, position.length() - 2)); + pos = Math.round(Float.parseFloat(position.substring(0, + position.length() - 2))); } client.updateVariable(id, "position", pos, immediate); } diff --git a/src/com/vaadin/ui/AbstractSplitPanel.java b/src/com/vaadin/ui/AbstractSplitPanel.java index ebdee17de2..586dbc81fe 100644 --- a/src/com/vaadin/ui/AbstractSplitPanel.java +++ b/src/com/vaadin/ui/AbstractSplitPanel.java @@ -222,8 +222,12 @@ public abstract class AbstractSplitPanel extends AbstractLayout { final String maximumPosition = posMax + UNIT_SYMBOLS[posMaxUnit]; target.addAttribute("position", position); - target.addAttribute("minimumPosition", minimumPosition); - target.addAttribute("maximumPosition", maximumPosition); + if (minimumPosition != "0%") { + target.addAttribute("minimumPosition", minimumPosition); + } + if (maximumPosition != "100%") { + target.addAttribute("maximumPosition", maximumPosition); + } if (isLocked()) { target.addAttribute("locked", true); -- cgit v1.2.3 From 052feb7be25e3f18bd751877b306d8247098d7f3 Mon Sep 17 00:00:00 2001 From: Artur Signell Date: Tue, 15 May 2012 05:17:49 +0300 Subject: Fixed header height by taking padding into account (box sizing change) --- WebContent/VAADIN/themes/liferay/window/window.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WebContent/VAADIN/themes/liferay/window/window.css b/WebContent/VAADIN/themes/liferay/window/window.css index 5ac7c02175..f034d7503f 100644 --- a/WebContent/VAADIN/themes/liferay/window/window.css +++ b/WebContent/VAADIN/themes/liferay/window/window.css @@ -11,7 +11,7 @@ } .v-window-outerheader { - height: 16px; + height: 38px; margin-left: 9px; padding: 10px 40px 12px 2px; background: transparent url(top-right.png) no-repeat right top; -- cgit v1.2.3 From 42c86ae274b041650b0745755167cb668ba4ae8d Mon Sep 17 00:00:00 2001 From: Artur Signell Date: Mon, 21 May 2012 16:19:24 +0300 Subject: Added generic test for FormLayout --- .../vaadin/tests/components/formlayout/FormLayouts.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100755 tests/testbench/com/vaadin/tests/components/formlayout/FormLayouts.java diff --git a/tests/testbench/com/vaadin/tests/components/formlayout/FormLayouts.java b/tests/testbench/com/vaadin/tests/components/formlayout/FormLayouts.java new file mode 100755 index 0000000000..e247ce95f7 --- /dev/null +++ b/tests/testbench/com/vaadin/tests/components/formlayout/FormLayouts.java @@ -0,0 +1,16 @@ +/* +@VaadinApache2LicenseForJavaFiles@ + */ +package com.vaadin.tests.components.formlayout; + +import com.vaadin.tests.components.AbstractOrderedLayoutTest; +import com.vaadin.ui.FormLayout; + +public class FormLayouts extends AbstractOrderedLayoutTest { + + @Override + protected Class getTestClass() { + return FormLayout.class; + } + +} -- cgit v1.2.3 From 8725ab419ad084ff5d04987406054333947d3232 Mon Sep 17 00:00:00 2001 From: Artur Signell Date: Mon, 21 May 2012 16:16:28 +0300 Subject: Updated to be Root-based and added debug ids to ease testing --- .../integration/JSR286PortletApplication.java | 183 -------------------- .../tests/integration/JSR286PortletRoot.java | 188 +++++++++++++++++++++ 2 files changed, 188 insertions(+), 183 deletions(-) delete mode 100644 tests/testbench/com/vaadin/tests/integration/JSR286PortletApplication.java create mode 100644 tests/testbench/com/vaadin/tests/integration/JSR286PortletRoot.java diff --git a/tests/testbench/com/vaadin/tests/integration/JSR286PortletApplication.java b/tests/testbench/com/vaadin/tests/integration/JSR286PortletApplication.java deleted file mode 100644 index 7ba6f2c0c0..0000000000 --- a/tests/testbench/com/vaadin/tests/integration/JSR286PortletApplication.java +++ /dev/null @@ -1,183 +0,0 @@ -package com.vaadin.tests.integration; - -import java.io.ByteArrayOutputStream; -import java.io.OutputStream; -import java.util.Iterator; -import java.util.Map; - -import javax.portlet.ActionRequest; -import javax.portlet.ActionResponse; -import javax.portlet.EventRequest; -import javax.portlet.EventResponse; -import javax.portlet.PortletMode; -import javax.portlet.PortletRequest; -import javax.portlet.PortletURL; -import javax.portlet.RenderRequest; -import javax.portlet.RenderResponse; -import javax.portlet.ResourceRequest; -import javax.portlet.ResourceResponse; -import javax.portlet.WindowState; - -import com.vaadin.Application; -import com.vaadin.terminal.ExternalResource; -import com.vaadin.terminal.gwt.client.ui.label.ContentMode; -import com.vaadin.terminal.gwt.server.PortletApplicationContext2; -import com.vaadin.terminal.gwt.server.PortletApplicationContext2.PortletListener; -import com.vaadin.ui.Embedded; -import com.vaadin.ui.Label; -import com.vaadin.ui.Link; -import com.vaadin.ui.Notification; -import com.vaadin.ui.Root; -import com.vaadin.ui.Root.LegacyWindow; -import com.vaadin.ui.TextField; -import com.vaadin.ui.Upload; -import com.vaadin.ui.Upload.Receiver; - -/** - * Adapted from old PortletDemo to support integration testing. - */ -public class JSR286PortletApplication extends Application.LegacyApplication { - - LegacyWindow main = new LegacyWindow(); - TextField tf = new TextField("Some value"); - Label userInfo = new Label(); - Link portletEdit = new Link(); - Link portletMax = new Link(); - Link someAction = null; - - @Override - public void init() { - setMainWindow(main); - - Embedded appResourceTest = new Embedded( - "Test of ApplicationResources with full path", - new FlagSeResource(this)); - main.addComponent(appResourceTest); - Embedded specialNameResourceTest = new Embedded( - "Test ApplicationResources with special names", - new SpecialNameResource(this)); - main.addComponent(specialNameResourceTest); - - userInfo.setCaption("User info"); - userInfo.setContentMode(ContentMode.PREFORMATTED); - main.addComponent(userInfo); - - tf.setEnabled(false); - tf.setImmediate(true); - main.addComponent(tf); - - portletEdit.setEnabled(false); - main.addComponent(portletEdit); - portletMax.setEnabled(false); - main.addComponent(portletMax); - - Upload upload = new Upload("Upload a file", new Receiver() { - - public OutputStream receiveUpload(String filename, String mimeType) { - return new ByteArrayOutputStream(); - } - }); - main.addComponent(upload); - - if (getContext() instanceof PortletApplicationContext2) { - PortletApplicationContext2 ctx = (PortletApplicationContext2) getContext(); - ctx.addPortletListener(this, new DemoPortletListener()); - } else { - getMainWindow().showNotification("Not inited via Portal!", - Notification.TYPE_ERROR_MESSAGE); - } - - } - - private class DemoPortletListener implements PortletListener { - - public void handleActionRequest(ActionRequest request, - ActionResponse response, Root window) { - main.addComponent(new Label("Action received")); - } - - public void handleRenderRequest(RenderRequest request, - RenderResponse response, Root window) { - // Portlet up-and-running, enable stuff - portletEdit.setEnabled(true); - portletMax.setEnabled(true); - - // Editable if we're in editmode - tf.setEnabled((request.getPortletMode() == PortletMode.EDIT)); - - // Show notification about current mode and state - getMainWindow().showNotification( - "Portlet status", - "Mode: " + request.getPortletMode() + " State: " - + request.getWindowState(), - Notification.TYPE_WARNING_MESSAGE); - - // Display current user info - Map uinfo = (Map) request - .getAttribute(PortletRequest.USER_INFO); - if (uinfo != null) { - String s = ""; - for (Iterator it = uinfo.keySet().iterator(); it.hasNext();) { - Object key = it.next(); - Object val = uinfo.get(key); - s += key + ": " + val + "\n"; - } - if (request.isUserInRole("administrator")) { - s += "(administrator)"; - } - userInfo.setValue(s); - } else { - userInfo.setValue("-"); - } - - // Create Edit/Done link (actionUrl) - PortletURL url = response.createActionURL(); - try { - url.setPortletMode((request.getPortletMode() == PortletMode.VIEW ? PortletMode.EDIT - : PortletMode.VIEW)); - portletEdit.setResource(new ExternalResource(url.toString())); - portletEdit - .setCaption((request.getPortletMode() == PortletMode.VIEW ? "Edit" - : "Done")); - } catch (Exception e) { - portletEdit.setEnabled(false); - } - // Create Maximize/Normal link (actionUrl) - url = response.createActionURL(); - try { - url.setWindowState((request.getWindowState() == WindowState.NORMAL ? WindowState.MAXIMIZED - : WindowState.NORMAL)); - portletMax.setResource(new ExternalResource(url.toString())); - portletMax - .setCaption((request.getWindowState() == WindowState.NORMAL ? "Maximize" - : "Back to normal")); - } catch (Exception e) { - portletMax.setEnabled(false); - } - - if (someAction == null) { - url = response.createActionURL(); - try { - someAction = new Link("An action", new ExternalResource( - url.toString())); - main.addComponent(someAction); - } catch (Exception e) { - // Oops - System.err.println("Could not create someAction: " + e); - } - - } - } - - public void handleEventRequest(EventRequest request, - EventResponse response, Root window) { - // events not used by this test - } - - public void handleResourceRequest(ResourceRequest request, - ResourceResponse response, Root window) { - // nothing special to do here - } - } - -} diff --git a/tests/testbench/com/vaadin/tests/integration/JSR286PortletRoot.java b/tests/testbench/com/vaadin/tests/integration/JSR286PortletRoot.java new file mode 100644 index 0000000000..e022a8bf30 --- /dev/null +++ b/tests/testbench/com/vaadin/tests/integration/JSR286PortletRoot.java @@ -0,0 +1,188 @@ +package com.vaadin.tests.integration; + +import java.io.ByteArrayOutputStream; +import java.io.OutputStream; +import java.util.Iterator; +import java.util.Map; + +import javax.portlet.ActionRequest; +import javax.portlet.ActionResponse; +import javax.portlet.EventRequest; +import javax.portlet.EventResponse; +import javax.portlet.PortletMode; +import javax.portlet.PortletRequest; +import javax.portlet.PortletURL; +import javax.portlet.RenderRequest; +import javax.portlet.RenderResponse; +import javax.portlet.ResourceRequest; +import javax.portlet.ResourceResponse; +import javax.portlet.WindowState; + +import com.vaadin.terminal.ExternalResource; +import com.vaadin.terminal.WrappedRequest; +import com.vaadin.terminal.gwt.client.ui.label.ContentMode; +import com.vaadin.terminal.gwt.server.PortletApplicationContext2; +import com.vaadin.terminal.gwt.server.PortletApplicationContext2.PortletListener; +import com.vaadin.ui.Embedded; +import com.vaadin.ui.Label; +import com.vaadin.ui.Link; +import com.vaadin.ui.Notification; +import com.vaadin.ui.Root; +import com.vaadin.ui.TextField; +import com.vaadin.ui.Upload; +import com.vaadin.ui.Upload.Receiver; +import com.vaadin.ui.VerticalLayout; + +/** + * Adapted from old PortletDemo to support integration testing. + */ +public class JSR286PortletRoot extends Root { + + TextField tf = new TextField("Some value"); + Label userInfo = new Label(); + Link portletEdit = new Link(); + Link portletMax = new Link(); + Link someAction = null; + + @Override + protected void init(WrappedRequest request) { + VerticalLayout main = new VerticalLayout(); + tf.setDebugId("tf"); + userInfo.setDebugId("userInfo"); + portletEdit.setDebugId("portletEdit"); + portletMax.setDebugId("portletMax"); + Embedded appResourceTest = new Embedded( + "Test of ApplicationResources with full path", + new FlagSeResource(getApplication())); + main.addComponent(appResourceTest); + Embedded specialNameResourceTest = new Embedded( + "Test ApplicationResources with special names", + new SpecialNameResource(getApplication())); + main.addComponent(specialNameResourceTest); + + userInfo.setCaption("User info"); + userInfo.setContentMode(ContentMode.PREFORMATTED); + main.addComponent(userInfo); + + tf.setEnabled(false); + tf.setImmediate(true); + main.addComponent(tf); + + portletEdit.setEnabled(false); + main.addComponent(portletEdit); + portletMax.setEnabled(false); + main.addComponent(portletMax); + + Upload upload = new Upload("Upload a file", new Receiver() { + + public OutputStream receiveUpload(String filename, String mimeType) { + return new ByteArrayOutputStream(); + } + }); + main.addComponent(upload); + + if (getApplication().getContext() instanceof PortletApplicationContext2) { + PortletApplicationContext2 ctx = (PortletApplicationContext2) getApplication() + .getContext(); + ctx.addPortletListener(getApplication(), new DemoPortletListener()); + } else { + showNotification("Not inited via Portal!", + Notification.TYPE_ERROR_MESSAGE); + } + + } + + private class DemoPortletListener implements PortletListener { + + public void handleActionRequest(ActionRequest request, + ActionResponse response, Root window) { + getContent().addComponent(new Label("Action received")); + } + + public void handleRenderRequest(RenderRequest request, + RenderResponse response, Root window) { + // Portlet up-and-running, enable stuff + portletEdit.setEnabled(true); + portletMax.setEnabled(true); + + // Editable if we're in editmode + tf.setEnabled((request.getPortletMode() == PortletMode.EDIT)); + + // Show notification about current mode and state + showNotification( + "Portlet status", + "Mode: " + request.getPortletMode() + " State: " + + request.getWindowState(), + Notification.TYPE_WARNING_MESSAGE); + + // Display current user info + Map uinfo = (Map) request + .getAttribute(PortletRequest.USER_INFO); + if (uinfo != null) { + String s = ""; + for (Iterator it = uinfo.keySet().iterator(); it.hasNext();) { + Object key = it.next(); + Object val = uinfo.get(key); + s += key + ": " + val + "\n"; + } + if (request.isUserInRole("administrator")) { + s += "(administrator)"; + } + userInfo.setValue(s); + } else { + userInfo.setValue("-"); + } + + // Create Edit/Done link (actionUrl) + PortletURL url = response.createActionURL(); + try { + url.setPortletMode((request.getPortletMode() == PortletMode.VIEW ? PortletMode.EDIT + : PortletMode.VIEW)); + portletEdit.setResource(new ExternalResource(url.toString())); + portletEdit + .setCaption((request.getPortletMode() == PortletMode.VIEW ? "Edit" + : "Done")); + } catch (Exception e) { + portletEdit.setEnabled(false); + } + // Create Maximize/Normal link (actionUrl) + url = response.createActionURL(); + try { + url.setWindowState((request.getWindowState() == WindowState.NORMAL ? WindowState.MAXIMIZED + : WindowState.NORMAL)); + portletMax.setResource(new ExternalResource(url.toString())); + portletMax + .setCaption((request.getWindowState() == WindowState.NORMAL ? "Maximize" + : "Back to normal")); + } catch (Exception e) { + portletMax.setEnabled(false); + } + + if (someAction == null) { + url = response.createActionURL(); + try { + someAction = new Link("An action", new ExternalResource( + url.toString())); + someAction.setDebugId("someAction"); + + addComponent(someAction); + } catch (Exception e) { + // Oops + System.err.println("Could not create someAction: " + e); + } + + } + } + + public void handleEventRequest(EventRequest request, + EventResponse response, Root window) { + // events not used by this test + } + + public void handleResourceRequest(ResourceRequest request, + ResourceResponse response, Root window) { + // nothing special to do here + } + } + +} -- cgit v1.2.3 From ee7526e0876fbe5e418331e3883ad5b9a1d7a828 Mon Sep 17 00:00:00 2001 From: Tapio Aali Date: Thu, 31 May 2012 08:34:34 +0000 Subject: Created a test for disabling and enabling max/min split position of SplitPanel. Also fixed some inconsistenties from the AbstractSplitPanel class. svn changeset:23859/svn branch:6.8 --- src/com/vaadin/ui/AbstractSplitPanel.java | 20 ++-- .../SplitPanelWithMinimumAndMaximum.html | 55 +++++++++++ .../SplitPanelWithMinimumAndMaximum.java | 102 ++++++++++++++++----- 3 files changed, 144 insertions(+), 33 deletions(-) diff --git a/src/com/vaadin/ui/AbstractSplitPanel.java b/src/com/vaadin/ui/AbstractSplitPanel.java index 586dbc81fe..0588e44d40 100644 --- a/src/com/vaadin/ui/AbstractSplitPanel.java +++ b/src/com/vaadin/ui/AbstractSplitPanel.java @@ -41,11 +41,11 @@ public abstract class AbstractSplitPanel extends AbstractLayout { private boolean posReversed = false; - private int posMin = 0; + private float posMin = 0; private int posMinUnit = UNITS_PERCENTAGE; - private int posMax = 100; + private float posMax = 100; private int posMaxUnit = UNITS_PERCENTAGE; @@ -222,10 +222,10 @@ public abstract class AbstractSplitPanel extends AbstractLayout { final String maximumPosition = posMax + UNIT_SYMBOLS[posMaxUnit]; target.addAttribute("position", position); - if (minimumPosition != "0%") { + if (!minimumPosition.equals("0%")) { target.addAttribute("minimumPosition", minimumPosition); } - if (maximumPosition != "100%") { + if (!maximumPosition.equals("100%")) { target.addAttribute("maximumPosition", maximumPosition); } @@ -348,7 +348,7 @@ public abstract class AbstractSplitPanel extends AbstractLayout { * the unit (from {@link Sizeable}) in which the size is given. * Allowed units are UNITS_PERCENTAGE and UNITS_PIXELS */ - public void setMinimumSplitPosition(int pos, int unit) { + public void setMinSplitPosition(float pos, int unit) { setSplitPositionLimits(pos, unit, posMax, posMaxUnit); } @@ -358,7 +358,7 @@ public abstract class AbstractSplitPanel extends AbstractLayout { * * @return the minimum position of the splitter */ - public int getMinSplitPosition() { + public float getMinSplitPosition() { return posMin; } @@ -381,7 +381,7 @@ public abstract class AbstractSplitPanel extends AbstractLayout { * the unit (from {@link Sizeable}) in which the size is given. * Allowed units are UNITS_PERCENTAGE and UNITS_PIXELS */ - public void setMaxSplitPosition(int pos, int unit) { + public void setMaxSplitPosition(float pos, int unit) { setSplitPositionLimits(posMin, posMinUnit, pos, unit); } @@ -391,7 +391,7 @@ public abstract class AbstractSplitPanel extends AbstractLayout { * * @return the maximum position of the splitter */ - public int getMaxSplitPosition() { + public float getMaxSplitPosition() { return posMax; } @@ -419,8 +419,8 @@ public abstract class AbstractSplitPanel extends AbstractLayout { * the unit (from {@link Sizeable}) in which the maximum position * is given. */ - private void setSplitPositionLimits(int minPos, int minPosUnit, int maxPos, - int maxPosUnit) { + private void setSplitPositionLimits(float minPos, int minPosUnit, + float maxPos, int maxPosUnit) { if ((minPosUnit != UNITS_PERCENTAGE && minPosUnit != UNITS_PIXELS) || (maxPosUnit != UNITS_PERCENTAGE && maxPosUnit != UNITS_PIXELS)) { throw new IllegalArgumentException( diff --git a/tests/testbench/com/vaadin/tests/components/splitpanel/SplitPanelWithMinimumAndMaximum.html b/tests/testbench/com/vaadin/tests/components/splitpanel/SplitPanelWithMinimumAndMaximum.html index 3aefedeff3..70d619edac 100644 --- a/tests/testbench/com/vaadin/tests/components/splitpanel/SplitPanelWithMinimumAndMaximum.html +++ b/tests/testbench/com/vaadin/tests/components/splitpanel/SplitPanelWithMinimumAndMaximum.html @@ -201,6 +201,61 @@ vertical-splits-down + + mouseClick + vaadin=runcomvaadintestscomponentssplitpanelSplitPanelWithMinimumAndMaximum::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VTabsheet[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]/domChild[2]/domChild[0]/domChild[0]/domChild[0] + 25,5 + + + dragAndDrop + vaadin=runcomvaadintestscomponentssplitpanelSplitPanelWithMinimumAndMaximum::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VTabsheet[0]/VTabsheetPanel[0]/VVerticalLayout[1]/ChildComponentContainer[0]/VSplitPanelHorizontal[0]/domChild[0]/domChild[2]/domChild[0] + -239,0 + + + screenCapture + + togglable-to-min-with-limit-enabled + + + click + vaadin=runcomvaadintestscomponentssplitpanelSplitPanelWithMinimumAndMaximum::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VTabsheet[0]/VTabsheetPanel[0]/VVerticalLayout[1]/ChildComponentContainer[1]/VHorizontalLayout[0]/ChildComponentContainer[0]/VButton[0]/domChild[0]/domChild[0] + + + + dragAndDrop + vaadin=runcomvaadintestscomponentssplitpanelSplitPanelWithMinimumAndMaximum::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VTabsheet[0]/VTabsheetPanel[0]/VVerticalLayout[1]/ChildComponentContainer[0]/VSplitPanelHorizontal[0]/domChild[0]/domChild[2]/domChild[0] + -60,0 + + + screenCapture + + togglable-to-min-with-limit-disabled + + + dragAndDrop + vaadin=runcomvaadintestscomponentssplitpanelSplitPanelWithMinimumAndMaximum::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VTabsheet[0]/VTabsheetPanel[0]/VVerticalLayout[1]/ChildComponentContainer[0]/VSplitPanelHorizontal[0]/domChild[0]/domChild[2]/domChild[0] + 478,0 + + + screenCapture + + togglable-to-max-with-limit-enabled + + + click + vaadin=runcomvaadintestscomponentssplitpanelSplitPanelWithMinimumAndMaximum::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VTabsheet[0]/VTabsheetPanel[0]/VVerticalLayout[1]/ChildComponentContainer[1]/VHorizontalLayout[0]/ChildComponentContainer[2]/VButton[0]/domChild[0]/domChild[0] + + + + dragAndDrop + vaadin=runcomvaadintestscomponentssplitpanelSplitPanelWithMinimumAndMaximum::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VTabsheet[0]/VTabsheetPanel[0]/VVerticalLayout[1]/ChildComponentContainer[0]/VSplitPanelHorizontal[0]/domChild[0]/domChild[2]/domChild[0] + 113,0 + + + screenCapture + + togglable-to-max-with-limit-disabled + diff --git a/tests/testbench/com/vaadin/tests/components/splitpanel/SplitPanelWithMinimumAndMaximum.java b/tests/testbench/com/vaadin/tests/components/splitpanel/SplitPanelWithMinimumAndMaximum.java index 9fa6fc18a3..f7c3dd84e4 100644 --- a/tests/testbench/com/vaadin/tests/components/splitpanel/SplitPanelWithMinimumAndMaximum.java +++ b/tests/testbench/com/vaadin/tests/components/splitpanel/SplitPanelWithMinimumAndMaximum.java @@ -2,6 +2,7 @@ package com.vaadin.tests.components.splitpanel; import com.vaadin.terminal.Sizeable; import com.vaadin.tests.components.TestBase; +import com.vaadin.ui.Button; import com.vaadin.ui.HorizontalLayout; import com.vaadin.ui.HorizontalSplitPanel; import com.vaadin.ui.Label; @@ -19,8 +20,8 @@ public class SplitPanelWithMinimumAndMaximum extends TestBase { horizontalSplitsLayout.setCaption("Horizontal splits"); HorizontalSplitPanel percentagePositionWithPercentageLimitsHorizontal = new HorizontalSplitPanel(); - percentagePositionWithPercentageLimitsHorizontal - .setMinimumSplitPosition(10, Sizeable.UNITS_PERCENTAGE); + percentagePositionWithPercentageLimitsHorizontal.setMinSplitPosition( + 10, Sizeable.UNITS_PERCENTAGE); percentagePositionWithPercentageLimitsHorizontal.setMaxSplitPosition( 80, Sizeable.UNITS_PERCENTAGE); percentagePositionWithPercentageLimitsHorizontal @@ -33,7 +34,7 @@ public class SplitPanelWithMinimumAndMaximum extends TestBase { .addComponent(percentagePositionWithPercentageLimitsHorizontal); HorizontalSplitPanel pixelPositionWithPercentageLimitsHorizontal = new HorizontalSplitPanel(); - pixelPositionWithPercentageLimitsHorizontal.setMinimumSplitPosition(10, + pixelPositionWithPercentageLimitsHorizontal.setMinSplitPosition(10, Sizeable.UNITS_PERCENTAGE); pixelPositionWithPercentageLimitsHorizontal.setMaxSplitPosition(80, Sizeable.UNITS_PERCENTAGE); @@ -47,7 +48,7 @@ public class SplitPanelWithMinimumAndMaximum extends TestBase { .addComponent(pixelPositionWithPercentageLimitsHorizontal); HorizontalSplitPanel pixelPositionWithPixelLimitsHorizontal = new HorizontalSplitPanel(); - pixelPositionWithPixelLimitsHorizontal.setMinimumSplitPosition(100, + pixelPositionWithPixelLimitsHorizontal.setMinSplitPosition(100, Sizeable.UNITS_PIXELS); pixelPositionWithPixelLimitsHorizontal.setMaxSplitPosition(550, Sizeable.UNITS_PIXELS); @@ -61,8 +62,8 @@ public class SplitPanelWithMinimumAndMaximum extends TestBase { .addComponent(pixelPositionWithPixelLimitsHorizontal); HorizontalSplitPanel percentagePositionWithPixelLimitsHorizontal = new HorizontalSplitPanel(); - percentagePositionWithPixelLimitsHorizontal.setMinimumSplitPosition( - 100, Sizeable.UNITS_PIXELS); + percentagePositionWithPixelLimitsHorizontal.setMinSplitPosition(100, + Sizeable.UNITS_PIXELS); percentagePositionWithPixelLimitsHorizontal.setMaxSplitPosition(550, Sizeable.UNITS_PIXELS); percentagePositionWithPixelLimitsHorizontal @@ -76,7 +77,7 @@ public class SplitPanelWithMinimumAndMaximum extends TestBase { HorizontalSplitPanel percentagePositionWithPercentageLimitsHorizontalResersed = new HorizontalSplitPanel(); percentagePositionWithPercentageLimitsHorizontalResersed - .setMinimumSplitPosition(10, Sizeable.UNITS_PERCENTAGE); + .setMinSplitPosition(10, Sizeable.UNITS_PERCENTAGE); percentagePositionWithPercentageLimitsHorizontalResersed .setMaxSplitPosition(80, Sizeable.UNITS_PERCENTAGE); percentagePositionWithPercentageLimitsHorizontalResersed @@ -91,7 +92,7 @@ public class SplitPanelWithMinimumAndMaximum extends TestBase { HorizontalSplitPanel pixelPositionWithPercentageLimitsHorizontalResersed = new HorizontalSplitPanel(); pixelPositionWithPercentageLimitsHorizontalResersed - .setMinimumSplitPosition(10, Sizeable.UNITS_PERCENTAGE); + .setMinSplitPosition(10, Sizeable.UNITS_PERCENTAGE); pixelPositionWithPercentageLimitsHorizontalResersed .setMaxSplitPosition(80, Sizeable.UNITS_PERCENTAGE); pixelPositionWithPercentageLimitsHorizontalResersed @@ -105,8 +106,8 @@ public class SplitPanelWithMinimumAndMaximum extends TestBase { .addComponent(pixelPositionWithPercentageLimitsHorizontalResersed); HorizontalSplitPanel pixelPositionWithPixelLimitsHorizontalResersed = new HorizontalSplitPanel(); - pixelPositionWithPixelLimitsHorizontalResersed.setMinimumSplitPosition( - 100, Sizeable.UNITS_PIXELS); + pixelPositionWithPixelLimitsHorizontalResersed.setMinSplitPosition(100, + Sizeable.UNITS_PIXELS); pixelPositionWithPixelLimitsHorizontalResersed.setMaxSplitPosition(550, Sizeable.UNITS_PIXELS); pixelPositionWithPixelLimitsHorizontalResersed @@ -121,7 +122,7 @@ public class SplitPanelWithMinimumAndMaximum extends TestBase { HorizontalSplitPanel percentagePositionWithPixelLimitsHorizontalResersed = new HorizontalSplitPanel(); percentagePositionWithPixelLimitsHorizontalResersed - .setMinimumSplitPosition(100, Sizeable.UNITS_PIXELS); + .setMinSplitPosition(100, Sizeable.UNITS_PIXELS); percentagePositionWithPixelLimitsHorizontalResersed .setMaxSplitPosition(550, Sizeable.UNITS_PIXELS); percentagePositionWithPixelLimitsHorizontalResersed @@ -141,8 +142,8 @@ public class SplitPanelWithMinimumAndMaximum extends TestBase { verticalSplitsLayout.setCaption("Vertical splits"); VerticalSplitPanel percentagePositionWithPercentageLimitsVertical = new VerticalSplitPanel(); - percentagePositionWithPercentageLimitsVertical.setMinimumSplitPosition( - 10, Sizeable.UNITS_PERCENTAGE); + percentagePositionWithPercentageLimitsVertical.setMinSplitPosition(10, + Sizeable.UNITS_PERCENTAGE); percentagePositionWithPercentageLimitsVertical.setMaxSplitPosition(80, Sizeable.UNITS_PERCENTAGE); percentagePositionWithPercentageLimitsVertical @@ -155,7 +156,7 @@ public class SplitPanelWithMinimumAndMaximum extends TestBase { .addComponent(percentagePositionWithPercentageLimitsVertical); VerticalSplitPanel pixelPositionWithPercentageLimitsVertical = new VerticalSplitPanel(); - pixelPositionWithPercentageLimitsVertical.setMinimumSplitPosition(10, + pixelPositionWithPercentageLimitsVertical.setMinSplitPosition(10, Sizeable.UNITS_PERCENTAGE); pixelPositionWithPercentageLimitsVertical.setMaxSplitPosition(80, Sizeable.UNITS_PERCENTAGE); @@ -169,7 +170,7 @@ public class SplitPanelWithMinimumAndMaximum extends TestBase { .addComponent(pixelPositionWithPercentageLimitsVertical); VerticalSplitPanel pixelPositionWithPixelLimitsVertical = new VerticalSplitPanel(); - pixelPositionWithPixelLimitsVertical.setMinimumSplitPosition(100, + pixelPositionWithPixelLimitsVertical.setMinSplitPosition(100, Sizeable.UNITS_PIXELS); pixelPositionWithPixelLimitsVertical.setMaxSplitPosition(450, Sizeable.UNITS_PIXELS); @@ -182,7 +183,7 @@ public class SplitPanelWithMinimumAndMaximum extends TestBase { verticalSplitsLayout.addComponent(pixelPositionWithPixelLimitsVertical); VerticalSplitPanel percentagePositionWithPixelLimitsVertical = new VerticalSplitPanel(); - percentagePositionWithPixelLimitsVertical.setMinimumSplitPosition(100, + percentagePositionWithPixelLimitsVertical.setMinSplitPosition(100, Sizeable.UNITS_PIXELS); percentagePositionWithPixelLimitsVertical.setMaxSplitPosition(450, Sizeable.UNITS_PIXELS); @@ -197,7 +198,7 @@ public class SplitPanelWithMinimumAndMaximum extends TestBase { VerticalSplitPanel percentagePositionWithPercentageLimitsVerticalReversed = new VerticalSplitPanel(); percentagePositionWithPercentageLimitsVerticalReversed - .setMinimumSplitPosition(10, Sizeable.UNITS_PERCENTAGE); + .setMinSplitPosition(10, Sizeable.UNITS_PERCENTAGE); percentagePositionWithPercentageLimitsVerticalReversed .setMaxSplitPosition(80, Sizeable.UNITS_PERCENTAGE); percentagePositionWithPercentageLimitsVerticalReversed @@ -211,8 +212,8 @@ public class SplitPanelWithMinimumAndMaximum extends TestBase { .addComponent(percentagePositionWithPercentageLimitsVerticalReversed); VerticalSplitPanel pixelPositionWithPercentageLimitsVerticalReversed = new VerticalSplitPanel(); - pixelPositionWithPercentageLimitsVerticalReversed - .setMinimumSplitPosition(10, Sizeable.UNITS_PERCENTAGE); + pixelPositionWithPercentageLimitsVerticalReversed.setMinSplitPosition( + 10, Sizeable.UNITS_PERCENTAGE); pixelPositionWithPercentageLimitsVerticalReversed.setMaxSplitPosition( 80, Sizeable.UNITS_PERCENTAGE); pixelPositionWithPercentageLimitsVerticalReversed @@ -226,8 +227,8 @@ public class SplitPanelWithMinimumAndMaximum extends TestBase { .addComponent(pixelPositionWithPercentageLimitsVerticalReversed); VerticalSplitPanel pixelPositionWithPixelLimitsVerticalReversed = new VerticalSplitPanel(); - pixelPositionWithPixelLimitsVerticalReversed.setMinimumSplitPosition( - 100, Sizeable.UNITS_PIXELS); + pixelPositionWithPixelLimitsVerticalReversed.setMinSplitPosition(100, + Sizeable.UNITS_PIXELS); pixelPositionWithPixelLimitsVerticalReversed.setMaxSplitPosition(400, Sizeable.UNITS_PIXELS); pixelPositionWithPixelLimitsVerticalReversed @@ -241,8 +242,8 @@ public class SplitPanelWithMinimumAndMaximum extends TestBase { .addComponent(pixelPositionWithPixelLimitsVerticalReversed); VerticalSplitPanel percentagePositionWithPixelLimitsVerticalReversed = new VerticalSplitPanel(); - percentagePositionWithPixelLimitsVerticalReversed - .setMinimumSplitPosition(100, Sizeable.UNITS_PIXELS); + percentagePositionWithPixelLimitsVerticalReversed.setMinSplitPosition( + 100, Sizeable.UNITS_PIXELS); percentagePositionWithPixelLimitsVerticalReversed.setMaxSplitPosition( 400, Sizeable.UNITS_PIXELS); percentagePositionWithPixelLimitsVerticalReversed @@ -258,6 +259,61 @@ public class SplitPanelWithMinimumAndMaximum extends TestBase { tabs.addComponent(verticalSplitsLayout); verticalSplitsLayout.setSizeFull(); + final VerticalLayout togglableSplitPanelLayout = new VerticalLayout(); + togglableSplitPanelLayout.setCaption("Togglable minimum/maximum"); + + final HorizontalSplitPanel togglableSplitPanel = new HorizontalSplitPanel(); + togglableSplitPanel.setMinSplitPosition(10, Sizeable.UNITS_PERCENTAGE); + togglableSplitPanel.setMaxSplitPosition(80, Sizeable.UNITS_PERCENTAGE); + togglableSplitPanel.setFirstComponent(new Label( + "Min 10 % - 50 % position")); + togglableSplitPanel.setSecondComponent(new Label("Max 80 %")); + togglableSplitPanel.setSplitPosition(50, Sizeable.UNITS_PERCENTAGE); + togglableSplitPanel.setHeight("250px"); + togglableSplitPanelLayout.addComponent(togglableSplitPanel); + + final HorizontalLayout buttonLayout = new HorizontalLayout(); + + Button disableMinimum = new Button("Disable min limit", + new Button.ClickListener() { + public void buttonClick(Button.ClickEvent event) { + togglableSplitPanel.setMinSplitPosition(0, + Sizeable.UNITS_PERCENTAGE); + + } + }); + Button enableMinimum = new Button("Enable min limit", + new Button.ClickListener() { + public void buttonClick(Button.ClickEvent event) { + togglableSplitPanel.setMinSplitPosition(10, + Sizeable.UNITS_PERCENTAGE); + + } + }); + Button disableMaximum = new Button("Disable max limit", + new Button.ClickListener() { + public void buttonClick(Button.ClickEvent event) { + togglableSplitPanel.setMaxSplitPosition(100, + Sizeable.UNITS_PERCENTAGE); + + } + }); + Button enableMaximum = new Button("Enable max limit", + new Button.ClickListener() { + public void buttonClick(Button.ClickEvent event) { + togglableSplitPanel.setMaxSplitPosition(80, + Sizeable.UNITS_PERCENTAGE); + + } + }); + buttonLayout.addComponent(disableMinimum); + buttonLayout.addComponent(enableMinimum); + buttonLayout.addComponent(disableMaximum); + buttonLayout.addComponent(enableMaximum); + + togglableSplitPanelLayout.addComponent(buttonLayout); + tabs.addComponent(togglableSplitPanelLayout); + addComponent(tabs); tabs.setHeight("550px"); tabs.setWidth("600px"); -- cgit v1.2.3 From 35973ebe675b8914f35e672b95b07be988fdc9e5 Mon Sep 17 00:00:00 2001 From: Johannes Dahlström Date: Thu, 31 May 2012 09:15:27 +0000 Subject: #7495 Inverted the server-side API naming (eg. setColumnNoncollapsible -> setColumnCollapsible). No other change in semantics. svn changeset:23861/svn branch:6.8 --- src/com/vaadin/ui/Table.java | 27 ++++++++++++++-------- .../table/TableWithNoncollapsibleColumns.java | 6 ++--- 2 files changed, 20 insertions(+), 13 deletions(-) diff --git a/src/com/vaadin/ui/Table.java b/src/com/vaadin/ui/Table.java index 564aa24991..73fe9679d5 100644 --- a/src/com/vaadin/ui/Table.java +++ b/src/com/vaadin/ui/Table.java @@ -1187,31 +1187,38 @@ public class Table extends AbstractSelect implements Action.Container, } /** - * Sets whether a column can be collapsed or not. + * Sets whether the given column is collapsible. Note that collapsible + * columns can only be actually collapsed (via UI or with + * {@link #setColumnCollapsed(Object, boolean) setColumnCollapsed()}) if + * {@link #isColumnCollapsingAllowed()} is true. By default all columns are + * collapsible. * * @param propertyId * the propertyID identifying the column. * @param collapsible - * the desired collapsibleness + * true if the column should be collapsible, false otherwise. */ - public void setColumnNoncollapsible(Object propertyId, - boolean noncollapsible) { - if (noncollapsible) { + public void setColumnCollapsible(Object propertyId, boolean collapsible) { + if (collapsible) { + noncollapsibleColumns.remove(propertyId); + } else { noncollapsibleColumns.add(propertyId); collapsedColumns.remove(propertyId); - } else { - noncollapsibleColumns.remove(propertyId); } refreshRowCache(); } /** - * Checks if the column can be collapsed. + * Checks if the given column is collapsible. Note that even if this method + * returns true, the column can only be actually collapsed (via + * UI or with {@link #setColumnCollapsed(Object, boolean) + * setColumnCollapsed()}) if {@link #isColumnCollapsingAllowed()} is also + * true. * * @return true if the column can be collapsed; false otherwise. */ - public boolean isColumnNoncollapsible(Object propertyId) { - return noncollapsibleColumns.contains(propertyId); + public boolean isColumnCollapsible(Object propertyId) { + return !noncollapsibleColumns.contains(propertyId); } /** diff --git a/tests/testbench/com/vaadin/tests/components/table/TableWithNoncollapsibleColumns.java b/tests/testbench/com/vaadin/tests/components/table/TableWithNoncollapsibleColumns.java index 9e8c201452..404ba5d779 100644 --- a/tests/testbench/com/vaadin/tests/components/table/TableWithNoncollapsibleColumns.java +++ b/tests/testbench/com/vaadin/tests/components/table/TableWithNoncollapsibleColumns.java @@ -25,7 +25,7 @@ public class TableWithNoncollapsibleColumns extends TestBase { table.addContainerProperty("Column 3 - toggle collapsing", String.class, null); - table.setColumnNoncollapsible("Column 1 - noncollapsible", true); + table.setColumnCollapsible("Column 1 - noncollapsible", false); layout.addComponent(table); final Button button1 = new Button("Column 1: collapse/show", @@ -57,9 +57,9 @@ public class TableWithNoncollapsibleColumns extends TestBase { "Column 3: make noncollapsible/collapsible", new Button.ClickListener() { public void buttonClick(ClickEvent event) { - table.setColumnNoncollapsible( + table.setColumnCollapsible( "Column 3 - toggle collapsing", - !table.isColumnNoncollapsible("Column 3 - toggle collapsing")); + !table.isColumnCollapsible("Column 3 - toggle collapsing")); } }); -- cgit v1.2.3 From 6f729f5d55cdfb719e8de835d4c713225bfd7ef2 Mon Sep 17 00:00:00 2001 From: Johannes Dahlström Date: Thu, 31 May 2012 09:47:53 +0000 Subject: #7495 Fixed Tables test to use the inverted API naming svn changeset:23862/svn branch:6.8 --- tests/testbench/com/vaadin/tests/components/table/Tables.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/testbench/com/vaadin/tests/components/table/Tables.java b/tests/testbench/com/vaadin/tests/components/table/Tables.java index 5c55ea87b2..9d409c5df8 100644 --- a/tests/testbench/com/vaadin/tests/components/table/Tables.java +++ b/tests/testbench/com/vaadin/tests/components/table/Tables.java @@ -73,10 +73,10 @@ public class Tables extends AbstractSelectTestCase } }; - private Command columnNonCollapsibleCommand = new Command() { + private Command columnCollapsibleCommand = new Command() { - public void execute(T c, Boolean noncollapsible, Object propertyId) { - c.setColumnNoncollapsible(propertyId, noncollapsible); + public void execute(T c, Boolean collapsible, Object propertyId) { + c.setColumnCollapsible(propertyId, collapsible); } }; @@ -652,8 +652,8 @@ public class Tables extends AbstractSelectTestCase createSelectAction("Expand ratio", category, expandOptions, "- remove -", columnExpandRatioCommand, propertyId); t.log("Expand"); - createBooleanAction("Noncollapsible", category, false, - columnNonCollapsibleCommand, propertyId); + createBooleanAction("Collapsible", category, true, + columnCollapsibleCommand, propertyId); // Footer text (move) // Header text (move) -- cgit v1.2.3 From d1b21ae7f7a52542ee56a150a5495bf52b1d0b25 Mon Sep 17 00:00:00 2001 From: Automerge Date: Fri, 1 Jun 2012 09:07:29 +0000 Subject: [merge from 6.7] Made tooltips work for Slider (#8863) svn changeset:23873/svn branch:6.8 --- src/com/vaadin/terminal/gwt/client/ui/VSlider.java | 6 ++ .../tests/components/slider/SliderTooltip.html | 67 ++++++++++++++++++++++ 2 files changed, 73 insertions(+) create mode 100644 tests/testbench/com/vaadin/tests/components/slider/SliderTooltip.html diff --git a/src/com/vaadin/terminal/gwt/client/ui/VSlider.java b/src/com/vaadin/terminal/gwt/client/ui/VSlider.java index e605c6fe12..84a7284944 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VSlider.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VSlider.java @@ -20,6 +20,7 @@ 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; public class VSlider extends SimpleFocusablePanel implements Paintable, Field, ContainerResizedListener { @@ -113,6 +114,8 @@ public class VSlider extends SimpleFocusablePanel implements Paintable, Field, feedbackPopup.addStyleName(CLASSNAME + "-feedback"); feedbackPopup.setWidget(feedback); + + sinkEvents(VTooltip.TOOLTIP_EVENTS); } public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { @@ -369,6 +372,9 @@ public class VSlider extends SimpleFocusablePanel implements Paintable, Field, event.preventDefault(); // avoid simulated events event.stopPropagation(); } + if (client != null) { + client.handleTooltipEvent(event, this); + } } private void processMouseWheelEvent(final Event event) { diff --git a/tests/testbench/com/vaadin/tests/components/slider/SliderTooltip.html b/tests/testbench/com/vaadin/tests/components/slider/SliderTooltip.html new file mode 100644 index 0000000000..4e8296050f --- /dev/null +++ b/tests/testbench/com/vaadin/tests/components/slider/SliderTooltip.html @@ -0,0 +1,67 @@ + + + + + + +New Test + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    New Test
    open/run/com.vaadin.tests.components.slider.SliderTest?debug&restartApplication
    mouseClickvaadin=runcomvaadintestscomponentssliderSliderTest::PID_Smenu#item024,2
    mouseClickvaadin=runcomvaadintestscomponentssliderSliderTest::Root/VOverlay[0]/VMenuBar[0]#item135,12
    mouseClickvaadin=runcomvaadintestscomponentssliderSliderTest::Root/VOverlay[1]/VMenuBar[0]#item174,3
    mouseClickvaadin=runcomvaadintestscomponentssliderSliderTest::Root/VOverlay[2]/VMenuBar[0]#item230,6
    showTooltipvaadin=runcomvaadintestscomponentssliderSliderTest::PID_StestComponent/domChild[2]/domChild[0]0,0
    waitForElementPresentvaadin=runcomvaadintestscomponentssliderSliderTest::Root/VTooltip[0]/FlowPanel[0]/domChild[1]
    assertTextvaadin=runcomvaadintestscomponentssliderSliderTest::Root/VTooltip[0]/FlowPanel[0]/domChild[1]This is a semi-long text that might wrap.
    mouseClickvaadin=runcomvaadintestscomponentssliderSliderTest::/VVerticalLayout[0]/ChildComponentContainer[0]/VLabel[0]40,16
    waitForElementNotPresentvaadin=runcomvaadintestscomponentssliderSliderTest::Root/VTooltip[0]/FlowPanel[0]/domChild[1]
    + + -- cgit v1.2.3 From abdc1ee5c270658b9f361cace015ff27cc448a68 Mon Sep 17 00:00:00 2001 From: Johannes Dahlström Date: Fri, 1 Jun 2012 12:19:05 +0000 Subject: Update supported platforms to include Firefox 12, Android 4 svn changeset:23874/svn branch:6.8 --- WebContent/release-notes.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/WebContent/release-notes.html b/WebContent/release-notes.html index 3f3cc30a3d..ef27d8de8c 100644 --- a/WebContent/release-notes.html +++ b/WebContent/release-notes.html @@ -406,7 +406,7 @@

      -
    • Mozilla Firefox 3-11
    • +
    • Mozilla Firefox 3-12
    • Internet Explorer 6-9
    • Safari 4-5
    • Opera 10-11
    • @@ -420,7 +420,7 @@
      • iOS 4-5
      • -
      • Android 2-3
      • +
      • Android 2-4
      -- cgit v1.2.3 From c0e3309e9bef20d34dd3e573bfd99540e29a291b Mon Sep 17 00:00:00 2001 From: Artur Signell Date: Fri, 1 Jun 2012 15:38:05 +0300 Subject: Repaint when contents changes (#8832) --- src/com/vaadin/ui/Root.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/com/vaadin/ui/Root.java b/src/com/vaadin/ui/Root.java index 93b98693c2..9c3aef4152 100644 --- a/src/com/vaadin/ui/Root.java +++ b/src/com/vaadin/ui/Root.java @@ -1072,6 +1072,8 @@ public abstract class Root extends AbstractComponentContainer implements if (content != null) { super.addComponent(content); } + + requestRepaint(); } /** -- cgit v1.2.3 From 33b1c7c40077304dc6f17f10896bbee6e37e95c1 Mon Sep 17 00:00:00 2001 From: Artur Signell Date: Fri, 1 Jun 2012 15:38:54 +0300 Subject: Repaint when contents changes (#8735) --- src/com/vaadin/ui/Panel.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/com/vaadin/ui/Panel.java b/src/com/vaadin/ui/Panel.java index b2916f78c7..a0fd84bbef 100644 --- a/src/com/vaadin/ui/Panel.java +++ b/src/com/vaadin/ui/Panel.java @@ -164,6 +164,7 @@ public class Panel extends AbstractComponentContainer implements Scrollable, .addListener((ComponentContainer.ComponentDetachListener) this); content = newContent; + requestRepaint(); } /** -- cgit v1.2.3 From 17c14316649b191bedc5cf2c0cc58cd49ad74a03 Mon Sep 17 00:00:00 2001 From: Henri Sara Date: Tue, 5 Jun 2012 07:44:15 +0000 Subject: #8297 Do not use static logger instances svn changeset:23882/svn branch:6.8 --- src/com/vaadin/Application.java | 14 ++-- src/com/vaadin/data/util/MethodProperty.java | 9 +- .../vaadin/data/util/MethodPropertyDescriptor.java | 11 +-- .../data/util/sqlcontainer/SQLContainer.java | 98 ++++++++++++---------- .../connection/J2EEConnectionPool.java | 5 +- .../data/util/sqlcontainer/query/TableQuery.java | 29 +++---- src/com/vaadin/event/ListenerMethod.java | 16 ++-- .../vaadin/event/dd/acceptcriteria/SourceIs.java | 12 ++- .../gwt/server/AbstractApplicationPortlet.java | 33 ++++---- .../gwt/server/AbstractApplicationServlet.java | 67 ++++++++------- .../gwt/server/AbstractCommunicationManager.java | 39 +++++---- .../gwt/server/AbstractWebApplicationContext.java | 9 +- .../gwt/server/ApplicationRunnerServlet.java | 15 ++-- .../gwt/server/ComponentSizeValidator.java | 13 +-- .../terminal/gwt/server/DragAndDropService.java | 17 ++-- .../terminal/gwt/server/GAEApplicationServlet.java | 36 ++++---- .../terminal/gwt/server/JsonPaintTarget.java | 34 ++++---- .../gwt/server/PortletApplicationContext2.java | 17 ++-- .../gwt/widgetsetutils/ClassPathExplorer.java | 42 ++++++---- src/com/vaadin/tools/WidgetsetCompiler.java | 11 +-- src/com/vaadin/ui/Table.java | 69 +++++++++------ src/com/vaadin/ui/TreeTable.java | 11 +-- 22 files changed, 341 insertions(+), 266 deletions(-) diff --git a/src/com/vaadin/Application.java b/src/com/vaadin/Application.java index 9fb4cfe7fa..a41cff36cb 100644 --- a/src/com/vaadin/Application.java +++ b/src/com/vaadin/Application.java @@ -92,9 +92,6 @@ import com.vaadin.ui.Window; public abstract class Application implements URIHandler, Terminal.ErrorListener, Serializable { - private final static Logger logger = Logger.getLogger(Application.class - .getName()); - /** * Id use for the next window that is opened. Access to this must be * synchronized. @@ -1191,8 +1188,9 @@ public abstract class Application implements URIHandler, final Throwable t = event.getThrowable(); if (t instanceof SocketException) { // Most likely client browser closed socket - logger.info("SocketException in CommunicationManager." - + " Most likely client (browser) closed socket."); + getLogger().info( + "SocketException in CommunicationManager." + + " Most likely client (browser) closed socket."); return; } @@ -1219,7 +1217,7 @@ public abstract class Application implements URIHandler, } // also print the error on console - logger.log(Level.SEVERE, "Terminal error:", t); + getLogger().log(Level.SEVERE, "Terminal error:", t); } /** @@ -1906,4 +1904,8 @@ public abstract class Application implements URIHandler, } } + + private static final Logger getLogger() { + return Logger.getLogger(Application.class.getName()); + } } \ No newline at end of file diff --git a/src/com/vaadin/data/util/MethodProperty.java b/src/com/vaadin/data/util/MethodProperty.java index ff258d3e0f..777ce68790 100644 --- a/src/com/vaadin/data/util/MethodProperty.java +++ b/src/com/vaadin/data/util/MethodProperty.java @@ -49,8 +49,6 @@ import com.vaadin.util.SerializerHelper; @SuppressWarnings("serial") public class MethodProperty extends AbstractProperty { - private static final Logger logger = Logger.getLogger(MethodProperty.class - .getName()); /** * The object that includes the property the MethodProperty is bound to. */ @@ -131,9 +129,9 @@ public class MethodProperty extends AbstractProperty { getMethod = null; } } catch (SecurityException e) { - logger.log(Level.SEVERE, "Internal deserialization error", e); + getLogger().log(Level.SEVERE, "Internal deserialization error", e); } catch (NoSuchMethodException e) { - logger.log(Level.SEVERE, "Internal deserialization error", e); + getLogger().log(Level.SEVERE, "Internal deserialization error", e); } }; @@ -805,4 +803,7 @@ public class MethodProperty extends AbstractProperty { super.fireValueChange(); } + private static final Logger getLogger() { + return Logger.getLogger(MethodProperty.class.getName()); + } } diff --git a/src/com/vaadin/data/util/MethodPropertyDescriptor.java b/src/com/vaadin/data/util/MethodPropertyDescriptor.java index f0c879766b..c4ec515917 100644 --- a/src/com/vaadin/data/util/MethodPropertyDescriptor.java +++ b/src/com/vaadin/data/util/MethodPropertyDescriptor.java @@ -23,9 +23,6 @@ import com.vaadin.util.SerializerHelper; public class MethodPropertyDescriptor implements VaadinPropertyDescriptor { - private static final Logger logger = Logger - .getLogger(MethodPropertyDescriptor.class.getName()); - private final String name; private Class propertyType; private transient Method readMethod; @@ -109,9 +106,9 @@ public class MethodPropertyDescriptor implements readMethod = null; } } catch (SecurityException e) { - logger.log(Level.SEVERE, "Internal deserialization error", e); + getLogger().log(Level.SEVERE, "Internal deserialization error", e); } catch (NoSuchMethodException e) { - logger.log(Level.SEVERE, "Internal deserialization error", e); + getLogger().log(Level.SEVERE, "Internal deserialization error", e); } }; @@ -128,4 +125,8 @@ public class MethodPropertyDescriptor implements writeMethod); } + private static final Logger getLogger() { + return Logger.getLogger(MethodPropertyDescriptor.class.getName()); + } + } \ No newline at end of file diff --git a/src/com/vaadin/data/util/sqlcontainer/SQLContainer.java b/src/com/vaadin/data/util/sqlcontainer/SQLContainer.java index 7eb67437e0..242a977614 100644 --- a/src/com/vaadin/data/util/sqlcontainer/SQLContainer.java +++ b/src/com/vaadin/data/util/sqlcontainer/SQLContainer.java @@ -36,9 +36,6 @@ import com.vaadin.data.util.sqlcontainer.query.generator.OracleGenerator; public class SQLContainer implements Container, Container.Filterable, Container.Indexed, Container.Sortable, Container.ItemSetChangeNotifier { - private static final Logger logger = Logger.getLogger(SQLContainer.class - .getName()); - /** Query delegate */ private QueryDelegate delegate; /** Auto commit mode, default = false */ @@ -162,15 +159,15 @@ public class SQLContainer implements Container, Container.Filterable, if (notificationsEnabled) { CacheFlushNotifier.notifyOfCacheFlush(this); } - logger.log(Level.FINER, "Row added to DB..."); + getLogger().log(Level.FINER, "Row added to DB..."); return itemId; } catch (SQLException e) { - logger.log(Level.WARNING, + getLogger().log(Level.WARNING, "Failed to add row to DB. Rolling back.", e); try { delegate.rollback(); } catch (SQLException ee) { - logger.log(Level.SEVERE, + getLogger().log(Level.SEVERE, "Failed to roll back row addition", e); } return null; @@ -215,7 +212,7 @@ public class SQLContainer implements Container, Container.Filterable, return delegate.containsRowWithKey(((RowId) itemId).getId()); } catch (Exception e) { /* Query failed, just return false. */ - logger.log(Level.WARNING, "containsId query failed", e); + getLogger().log(Level.WARNING, "containsId query failed", e); } } return false; @@ -325,17 +322,18 @@ public class SQLContainer implements Container, Container.Filterable, rs.close(); delegate.commit(); } catch (SQLException e) { - logger.log(Level.WARNING, "getItemIds() failed, rolling back.", e); + getLogger().log(Level.WARNING, + "getItemIds() failed, rolling back.", e); try { delegate.rollback(); } catch (SQLException e1) { - logger.log(Level.SEVERE, "Failed to roll back state", e1); + getLogger().log(Level.SEVERE, "Failed to roll back state", e1); } try { rs.getStatement().close(); rs.close(); } catch (SQLException e1) { - logger.log(Level.WARNING, "Closing session failed", e1); + getLogger().log(Level.WARNING, "Closing session failed", e1); } throw new RuntimeException("Failed to fetch item indexes.", e); } @@ -400,29 +398,29 @@ public class SQLContainer implements Container, Container.Filterable, CacheFlushNotifier.notifyOfCacheFlush(this); } if (success) { - logger.log(Level.FINER, "Row removed from DB..."); + getLogger().log(Level.FINER, "Row removed from DB..."); } return success; } catch (SQLException e) { - logger.log(Level.WARNING, "Failed to remove row, rolling back", - e); + getLogger().log(Level.WARNING, + "Failed to remove row, rolling back", e); try { delegate.rollback(); } catch (SQLException ee) { /* Nothing can be done here */ - logger.log(Level.SEVERE, "Failed to rollback row removal", - ee); + getLogger().log(Level.SEVERE, + "Failed to rollback row removal", ee); } return false; } catch (OptimisticLockException e) { - logger.log(Level.WARNING, "Failed to remove row, rolling back", - e); + getLogger().log(Level.WARNING, + "Failed to remove row, rolling back", e); try { delegate.rollback(); } catch (SQLException ee) { /* Nothing can be done here */ - logger.log(Level.SEVERE, "Failed to rollback row removal", - ee); + getLogger().log(Level.SEVERE, + "Failed to rollback row removal", ee); } throw e; } @@ -452,7 +450,7 @@ public class SQLContainer implements Container, Container.Filterable, } if (success) { delegate.commit(); - logger.log(Level.FINER, "All rows removed from DB..."); + getLogger().log(Level.FINER, "All rows removed from DB..."); refresh(); if (notificationsEnabled) { CacheFlushNotifier.notifyOfCacheFlush(this); @@ -462,23 +460,23 @@ public class SQLContainer implements Container, Container.Filterable, } return success; } catch (SQLException e) { - logger.log(Level.WARNING, + getLogger().log(Level.WARNING, "removeAllItems() failed, rolling back", e); try { delegate.rollback(); } catch (SQLException ee) { /* Nothing can be done here */ - logger.log(Level.SEVERE, "Failed to roll back", ee); + getLogger().log(Level.SEVERE, "Failed to roll back", ee); } return false; } catch (OptimisticLockException e) { - logger.log(Level.WARNING, + getLogger().log(Level.WARNING, "removeAllItems() failed, rolling back", e); try { delegate.rollback(); } catch (SQLException ee) { /* Nothing can be done here */ - logger.log(Level.SEVERE, "Failed to roll back", ee); + getLogger().log(Level.SEVERE, "Failed to roll back", ee); } throw e; } @@ -743,7 +741,7 @@ public class SQLContainer implements Container, Container.Filterable, try { asc = ascending[i]; } catch (Exception e) { - logger.log(Level.WARNING, "", e); + getLogger().log(Level.WARNING, "", e); } sorters.add(new OrderBy((String) propertyId[i], asc)); } @@ -872,7 +870,8 @@ public class SQLContainer implements Container, Container.Filterable, */ public void commit() throws UnsupportedOperationException, SQLException { try { - logger.log(Level.FINER, "Commiting changes through delegate..."); + getLogger().log(Level.FINER, + "Commiting changes through delegate..."); delegate.beginTransaction(); /* Perform buffered deletions */ for (RowItem item : removedItems.values()) { @@ -926,7 +925,7 @@ public class SQLContainer implements Container, Container.Filterable, * @throws SQLException */ public void rollback() throws UnsupportedOperationException, SQLException { - logger.log(Level.FINE, "Rolling back changes..."); + getLogger().log(Level.FINE, "Rolling back changes..."); removedItems.clear(); addedItems.clear(); modifiedItems.clear(); @@ -956,15 +955,15 @@ public class SQLContainer implements Container, Container.Filterable, if (notificationsEnabled) { CacheFlushNotifier.notifyOfCacheFlush(this); } - logger.log(Level.FINER, "Row updated to DB..."); + getLogger().log(Level.FINER, "Row updated to DB..."); } catch (SQLException e) { - logger.log(Level.WARNING, + getLogger().log(Level.WARNING, "itemChangeNotification failed, rolling back...", e); try { delegate.rollback(); } catch (SQLException ee) { /* Nothing can be done here */ - logger.log(Level.SEVERE, "Rollback failed", e); + getLogger().log(Level.SEVERE, "Rollback failed", e); } throw new RuntimeException(e); } @@ -1009,13 +1008,13 @@ public class SQLContainer implements Container, Container.Filterable, try { delegate.setFilters(filters); } catch (UnsupportedOperationException e) { - logger.log(Level.FINE, + getLogger().log(Level.FINE, "The query delegate doesn't support filtering", e); } try { delegate.setOrderBy(sorters); } catch (UnsupportedOperationException e) { - logger.log(Level.FINE, + getLogger().log(Level.FINE, "The query delegate doesn't support filtering", e); } int newSize = delegate.getCount(); @@ -1025,7 +1024,8 @@ public class SQLContainer implements Container, Container.Filterable, } sizeUpdated = new Date(); sizeDirty = false; - logger.log(Level.FINER, "Updated row count. New count is: " + size); + getLogger().log(Level.FINER, + "Updated row count. New count is: " + size); } catch (SQLException e) { throw new RuntimeException("Failed to update item set size.", e); } @@ -1069,7 +1069,7 @@ public class SQLContainer implements Container, Container.Filterable, try { type = Class.forName(rsmd.getColumnClassName(i)); } catch (Exception e) { - logger.log(Level.WARNING, "Class not found", e); + getLogger().log(Level.WARNING, "Class not found", e); /* On failure revert to Object and hope for the best. */ type = Object.class; } @@ -1095,14 +1095,14 @@ public class SQLContainer implements Container, Container.Filterable, rs.getStatement().close(); rs.close(); delegate.commit(); - logger.log(Level.FINER, "Property IDs fetched."); + getLogger().log(Level.FINER, "Property IDs fetched."); } catch (SQLException e) { - logger.log(Level.WARNING, + getLogger().log(Level.WARNING, "Failed to fetch property ids, rolling back", e); try { delegate.rollback(); } catch (SQLException e1) { - logger.log(Level.SEVERE, "Failed to roll back", e1); + getLogger().log(Level.SEVERE, "Failed to roll back", e1); } try { if (rs != null) { @@ -1112,7 +1112,7 @@ public class SQLContainer implements Container, Container.Filterable, rs.close(); } } catch (SQLException e1) { - logger.log(Level.WARNING, "Failed to close session", e1); + getLogger().log(Level.WARNING, "Failed to close session", e1); } throw e; } @@ -1135,7 +1135,7 @@ public class SQLContainer implements Container, Container.Filterable, } catch (UnsupportedOperationException e) { /* The query delegate doesn't support sorting. */ /* No need to do anything. */ - logger.log(Level.FINE, + getLogger().log(Level.FINE, "The query delegate doesn't support sorting", e); } delegate.beginTransaction(); @@ -1217,14 +1217,17 @@ public class SQLContainer implements Container, Container.Filterable, rs.getStatement().close(); rs.close(); delegate.commit(); - logger.log(Level.FINER, "Fetched " + pageLength * CACHE_RATIO - + " rows starting from " + currentOffset); + getLogger().log( + Level.FINER, + "Fetched " + pageLength * CACHE_RATIO + + " rows starting from " + currentOffset); } catch (SQLException e) { - logger.log(Level.WARNING, "Failed to fetch rows, rolling back", e); + getLogger().log(Level.WARNING, + "Failed to fetch rows, rolling back", e); try { delegate.rollback(); } catch (SQLException e1) { - logger.log(Level.SEVERE, "Failed to roll back", e1); + getLogger().log(Level.SEVERE, "Failed to roll back", e1); } try { if (rs != null) { @@ -1234,7 +1237,7 @@ public class SQLContainer implements Container, Container.Filterable, } } } catch (SQLException e1) { - logger.log(Level.WARNING, "Failed to close session", e1); + getLogger().log(Level.WARNING, "Failed to close session", e1); } throw new RuntimeException("Failed to fetch page.", e); } @@ -1577,7 +1580,8 @@ public class SQLContainer implements Container, Container.Filterable, r.getReferencedColumn())); return true; } catch (Exception e) { - logger.log(Level.WARNING, "Setting referenced item failed.", e); + getLogger() + .log(Level.WARNING, "Setting referenced item failed.", e); return false; } } @@ -1640,4 +1644,8 @@ public class SQLContainer implements Container, Container.Filterable, } } + private static final Logger getLogger() { + return Logger.getLogger(SQLContainer.class.getName()); + } + } \ No newline at end of file diff --git a/src/com/vaadin/data/util/sqlcontainer/connection/J2EEConnectionPool.java b/src/com/vaadin/data/util/sqlcontainer/connection/J2EEConnectionPool.java index 9e4bb772f5..40d0d0426f 100644 --- a/src/com/vaadin/data/util/sqlcontainer/connection/J2EEConnectionPool.java +++ b/src/com/vaadin/data/util/sqlcontainer/connection/J2EEConnectionPool.java @@ -13,8 +13,6 @@ import javax.naming.NamingException; import javax.sql.DataSource; public class J2EEConnectionPool implements JDBCConnectionPool { - private static final Logger logger = Logger - .getLogger(J2EEConnectionPool.class.getName()); private String dataSourceJndiName; @@ -58,7 +56,8 @@ public class J2EEConnectionPool implements JDBCConnectionPool { try { conn.close(); } catch (SQLException e) { - logger.log(Level.FINE, "Could not release SQL connection", e); + Logger.getLogger(J2EEConnectionPool.class.getName()).log( + Level.FINE, "Could not release SQL connection", e); } } } diff --git a/src/com/vaadin/data/util/sqlcontainer/query/TableQuery.java b/src/com/vaadin/data/util/sqlcontainer/query/TableQuery.java index 7e546309f6..22ca30cc32 100644 --- a/src/com/vaadin/data/util/sqlcontainer/query/TableQuery.java +++ b/src/com/vaadin/data/util/sqlcontainer/query/TableQuery.java @@ -38,9 +38,6 @@ import com.vaadin.data.util.sqlcontainer.query.generator.StatementHelper; public class TableQuery implements QueryDelegate, QueryDelegate.RowIdChangeNotifier { - private static final Logger logger = Logger.getLogger(TableQuery.class - .getName()); - /** Table name, primary key column name(s) and version column name */ private String tableName; private List primaryKeyColumns; @@ -115,7 +112,7 @@ public class TableQuery implements QueryDelegate, * @see com.vaadin.addon.sqlcontainer.query.QueryDelegate#getCount() */ public int getCount() throws SQLException { - logger.log(Level.FINE, "Fetching count..."); + getLogger().log(Level.FINE, "Fetching count..."); StatementHelper sh = sqlGenerator.generateSelectQuery(tableName, filters, null, 0, 0, "COUNT(*)"); boolean shouldCloseTransaction = false; @@ -228,7 +225,7 @@ public class TableQuery implements QueryDelegate, PreparedStatement pstmt = activeConnection.prepareStatement( sh.getQueryString(), primaryKeyColumns.toArray(new String[0])); sh.setParameterValuesToStatement(pstmt); - logger.log(Level.FINE, "DB -> " + sh.getQueryString()); + getLogger().log(Level.FINE, "DB -> " + sh.getQueryString()); int result = pstmt.executeUpdate(); if (result > 0) { /* @@ -293,7 +290,7 @@ public class TableQuery implements QueryDelegate, throw new IllegalStateException(); } - logger.log(Level.FINE, "DB -> begin transaction"); + getLogger().log(Level.FINE, "DB -> begin transaction"); activeConnection = connectionPool.reserveConnection(); activeConnection.setAutoCommit(false); transactionOpen = true; @@ -306,7 +303,7 @@ public class TableQuery implements QueryDelegate, */ public void commit() throws UnsupportedOperationException, SQLException { if (transactionOpen && activeConnection != null) { - logger.log(Level.FINE, "DB -> commit"); + getLogger().log(Level.FINE, "DB -> commit"); activeConnection.commit(); connectionPool.releaseConnection(activeConnection); } else { @@ -334,7 +331,7 @@ public class TableQuery implements QueryDelegate, */ public void rollback() throws UnsupportedOperationException, SQLException { if (transactionOpen && activeConnection != null) { - logger.log(Level.FINE, "DB -> rollback"); + getLogger().log(Level.FINE, "DB -> rollback"); activeConnection.rollback(); connectionPool.releaseConnection(activeConnection); } else { @@ -389,7 +386,7 @@ public class TableQuery implements QueryDelegate, } PreparedStatement pstmt = c.prepareStatement(sh.getQueryString()); sh.setParameterValuesToStatement(pstmt); - logger.log(Level.FINE, "DB -> " + sh.getQueryString()); + getLogger().log(Level.FINE, "DB -> " + sh.getQueryString()); return pstmt.executeQuery(); } @@ -415,7 +412,7 @@ public class TableQuery implements QueryDelegate, } pstmt = c.prepareStatement(sh.getQueryString()); sh.setParameterValuesToStatement(pstmt); - logger.log(Level.FINE, "DB -> " + sh.getQueryString()); + getLogger().log(Level.FINE, "DB -> " + sh.getQueryString()); int retval = pstmt.executeUpdate(); return retval; } finally { @@ -458,7 +455,7 @@ public class TableQuery implements QueryDelegate, pstmt = c.prepareStatement(sh.getQueryString(), primaryKeyColumns.toArray(new String[0])); sh.setParameterValuesToStatement(pstmt); - logger.log(Level.FINE, "DB -> " + sh.getQueryString()); + getLogger().log(Level.FINE, "DB -> " + sh.getQueryString()); int result = pstmt.executeUpdate(); genKeys = pstmt.getGeneratedKeys(); RowId newId = getNewRowId(row, genKeys); @@ -571,7 +568,7 @@ public class TableQuery implements QueryDelegate, } return new RowId(newRowId.toArray()); } catch (Exception e) { - logger.log(Level.FINE, + getLogger().log(Level.FINE, "Failed to fetch key values on insert: " + e.getMessage()); return null; } @@ -586,8 +583,8 @@ public class TableQuery implements QueryDelegate, */ public boolean removeRow(RowItem row) throws UnsupportedOperationException, SQLException { - logger.log(Level.FINE, "Removing row with id: " - + row.getId().getId()[0].toString()); + getLogger().log(Level.FINE, + "Removing row with id: " + row.getId().getId()[0].toString()); if (executeUpdate(sqlGenerator.generateDeleteQuery(getTableName(), primaryKeyColumns, versionColumn, row)) == 1) { return true; @@ -695,4 +692,8 @@ public class TableQuery implements QueryDelegate, rowIdChangeListeners.remove(listener); } } + + private static final Logger getLogger() { + return Logger.getLogger(TableQuery.class.getName()); + } } diff --git a/src/com/vaadin/event/ListenerMethod.java b/src/com/vaadin/event/ListenerMethod.java index 1f1305fa69..f7dc8a7f13 100644 --- a/src/com/vaadin/event/ListenerMethod.java +++ b/src/com/vaadin/event/ListenerMethod.java @@ -43,9 +43,6 @@ import java.util.logging.Logger; @SuppressWarnings("serial") public class ListenerMethod implements EventListener, Serializable { - private static final Logger logger = Logger.getLogger(ListenerMethod.class - .getName()); - /** * Type of the event that should trigger this listener. Also the subclasses * of this class are accepted to trigger the listener. @@ -84,9 +81,10 @@ public class ListenerMethod implements EventListener, Serializable { out.writeObject(name); out.writeObject(paramTypes); } catch (NotSerializableException e) { - logger.warning("Error in serialization of the application: Class " - + target.getClass().getName() - + " must implement serialization."); + getLogger().warning( + "Error in serialization of the application: Class " + + target.getClass().getName() + + " must implement serialization."); throw e; } @@ -103,7 +101,7 @@ public class ListenerMethod implements EventListener, Serializable { // inner classes method = findHighestMethod(target.getClass(), name, paramTypes); } catch (SecurityException e) { - logger.log(Level.SEVERE, "Internal deserialization error", e); + getLogger().log(Level.SEVERE, "Internal deserialization error", e); } }; @@ -658,4 +656,8 @@ public class ListenerMethod implements EventListener, Serializable { return target; } + private static final Logger getLogger() { + return Logger.getLogger(ListenerMethod.class.getName()); + } + } diff --git a/src/com/vaadin/event/dd/acceptcriteria/SourceIs.java b/src/com/vaadin/event/dd/acceptcriteria/SourceIs.java index 0d29e9a327..62bf64f76c 100644 --- a/src/com/vaadin/event/dd/acceptcriteria/SourceIs.java +++ b/src/com/vaadin/event/dd/acceptcriteria/SourceIs.java @@ -25,8 +25,6 @@ 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[] components; @@ -43,11 +41,11 @@ public class SourceIs extends ClientSideCriterion { 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) }); + Logger.getLogger(SourceIs.class.getName()) + .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); diff --git a/src/com/vaadin/terminal/gwt/server/AbstractApplicationPortlet.java b/src/com/vaadin/terminal/gwt/server/AbstractApplicationPortlet.java index 0a8e9530f0..9f1bd4e9ee 100644 --- a/src/com/vaadin/terminal/gwt/server/AbstractApplicationPortlet.java +++ b/src/com/vaadin/terminal/gwt/server/AbstractApplicationPortlet.java @@ -68,9 +68,6 @@ import com.vaadin.ui.Window; public abstract class AbstractApplicationPortlet extends GenericPortlet implements Constants { - private static final Logger logger = Logger - .getLogger(AbstractApplicationPortlet.class.getName()); - /** * This portlet parameter is used to add styles to the main element. E.g * "height:500px" generates a style="height:500px" to the main element. @@ -123,7 +120,7 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet * Print an information/warning message about running with xsrf * protection disabled */ - logger.warning(WARNING_XSRF_PROTECTION_DISABLED); + getLogger().warning(WARNING_XSRF_PROTECTION_DISABLED); } } @@ -136,9 +133,10 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet private void checkWidgetsetVersion(PortletRequest request) { if (!AbstractApplicationServlet.VERSION.equals(getHTTPRequestParameter( request, "wsver"))) { - logger.warning(String.format(WIDGETSET_MISMATCH_INFO, - AbstractApplicationServlet.VERSION, - getHTTPRequestParameter(request, "wsver"))); + getLogger().warning( + String.format(WIDGETSET_MISMATCH_INFO, + AbstractApplicationServlet.VERSION, + getHTTPRequestParameter(request, "wsver"))); } } @@ -158,7 +156,7 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet if (!productionMode) { /* Print an information/warning message about running in debug mode */ // TODO Maybe we need a different message for portlets? - logger.warning(NOT_PRODUCTION_MODE_INFO); + getLogger().warning(NOT_PRODUCTION_MODE_INFO); } } @@ -473,11 +471,12 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet } catch (final SessionExpiredException e) { // TODO Figure out a better way to deal with // SessionExpiredExceptions - logger.finest("A user session has expired"); + getLogger().finest("A user session has expired"); } catch (final GeneralSecurityException e) { // TODO Figure out a better way to deal with // GeneralSecurityExceptions - logger.fine("General security exception, the security key was probably incorrect."); + getLogger() + .fine("General security exception, the security key was probably incorrect."); } catch (final Throwable e) { handleServiceException(request, response, application, e); } finally { @@ -508,7 +507,7 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet private void handleUnknownRequest(PortletRequest request, PortletResponse response) { - logger.warning("Unknown request type"); + getLogger().warning("Unknown request type"); } /** @@ -705,8 +704,9 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet os.write(buffer, 0, bytes); } } else { - logger.info("Requested resource [" + resourceID - + "] could not be found"); + getLogger().info( + "Requested resource [" + resourceID + + "] could not be found"); response.setProperty(ResourceResponse.HTTP_STATUS_CODE, Integer.toString(HttpServletResponse.SC_NOT_FOUND)); } @@ -963,7 +963,8 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet appClass += getApplicationClass().getSimpleName(); } catch (ClassNotFoundException e) { appClass += "unknown"; - logger.log(Level.SEVERE, "Could not find application class", e); + getLogger() + .log(Level.SEVERE, "Could not find application class", e); } String themeClass = "v-theme-" + themeName.replaceAll("[^a-zA-Z0-9]", ""); @@ -1633,4 +1634,8 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet return PortletApplicationContext2.getApplicationContext(portletSession); } + private static final Logger getLogger() { + return Logger.getLogger(AbstractApplicationPortlet.class.getName()); + } + } diff --git a/src/com/vaadin/terminal/gwt/server/AbstractApplicationServlet.java b/src/com/vaadin/terminal/gwt/server/AbstractApplicationServlet.java index 54ea4a94ed..c6d286ed03 100644 --- a/src/com/vaadin/terminal/gwt/server/AbstractApplicationServlet.java +++ b/src/com/vaadin/terminal/gwt/server/AbstractApplicationServlet.java @@ -67,9 +67,6 @@ public abstract class AbstractApplicationServlet extends HttpServlet implements // TODO Move some (all?) of the constants to a separate interface (shared // with portlet) - private static final Logger logger = Logger - .getLogger(AbstractApplicationServlet.class.getName()); - /** * The version number of this release. For example "6.2.0". Always in the * format "major.minor.revision[.build]". The build part is optional. All of @@ -232,7 +229,7 @@ public abstract class AbstractApplicationServlet extends HttpServlet implements * Print an information/warning message about running with xsrf * protection disabled */ - logger.warning(WARNING_XSRF_PROTECTION_DISABLED); + getLogger().warning(WARNING_XSRF_PROTECTION_DISABLED); } } @@ -244,8 +241,9 @@ public abstract class AbstractApplicationServlet extends HttpServlet implements */ private void checkWidgetsetVersion(HttpServletRequest request) { if (!VERSION.equals(request.getParameter("wsver"))) { - logger.warning(String.format(WIDGETSET_MISMATCH_INFO, VERSION, - request.getParameter("wsver"))); + getLogger().warning( + String.format(WIDGETSET_MISMATCH_INFO, VERSION, + request.getParameter("wsver"))); } } @@ -264,7 +262,7 @@ public abstract class AbstractApplicationServlet extends HttpServlet implements if (!productionMode) { /* Print an information/warning message about running in debug mode */ - logger.warning(NOT_PRODUCTION_MODE_INFO); + getLogger().warning(NOT_PRODUCTION_MODE_INFO); } } @@ -278,7 +276,7 @@ public abstract class AbstractApplicationServlet extends HttpServlet implements } catch (NumberFormatException nfe) { // Default is 1h resourceCacheTime = 3600; - logger.warning(WARNING_RESOURCE_CACHING_TIME_NOT_NUMERIC); + getLogger().warning(WARNING_RESOURCE_CACHING_TIME_NOT_NUMERIC); } } @@ -857,8 +855,8 @@ public abstract class AbstractApplicationServlet extends HttpServlet implements resultPath = url.getFile(); } catch (final Exception e) { // FIXME: Handle exception - logger.log(Level.INFO, "Could not find resource path " + path, - e); + getLogger().log(Level.INFO, + "Could not find resource path " + path, e); } } return resultPath; @@ -1273,10 +1271,11 @@ public abstract class AbstractApplicationServlet extends HttpServlet implements if (resourceUrl == null) { // cannot serve requested file - logger.info("Requested resource [" - + filename - + "] not found from filesystem or through class loader." - + " Add widgetset and/or theme JAR to your classpath or add files to WebContent/VAADIN folder."); + getLogger() + .info("Requested resource [" + + filename + + "] not found from filesystem or through class loader." + + " Add widgetset and/or theme JAR to your classpath or add files to WebContent/VAADIN folder."); response.setStatus(HttpServletResponse.SC_NOT_FOUND); return; } @@ -1284,9 +1283,10 @@ public abstract class AbstractApplicationServlet extends HttpServlet implements // security check: do not permit navigation out of the VAADIN // directory if (!isAllowedVAADINResourceUrl(request, resourceUrl)) { - logger.info("Requested resource [" - + filename - + "] not accessible in the VAADIN directory or access to it is forbidden."); + getLogger() + .info("Requested resource [" + + filename + + "] not accessible in the VAADIN directory or access to it is forbidden."); response.setStatus(HttpServletResponse.SC_FORBIDDEN); return; } @@ -1307,10 +1307,10 @@ public abstract class AbstractApplicationServlet extends HttpServlet implements } } catch (Exception e) { // Failed to find out last modified timestamp. Continue without it. - logger.log( - Level.FINEST, - "Failed to find out last modified timestamp. Continuing without it.", - e); + getLogger() + .log(Level.FINEST, + "Failed to find out last modified timestamp. Continuing without it.", + e); } // Set type mime type if we can determine it based on the filename @@ -1375,12 +1375,14 @@ public abstract class AbstractApplicationServlet extends HttpServlet implements // loader sees it. if (!resourceUrl.getPath().contains("!/VAADIN/")) { - logger.info("Blocked attempt to access a JAR entry not starting with /VAADIN/: " - + resourceUrl); + getLogger().info( + "Blocked attempt to access a JAR entry not starting with /VAADIN/: " + + resourceUrl); return false; } - logger.fine("Accepted access to a JAR entry using a class loader: " - + resourceUrl); + getLogger().fine( + "Accepted access to a JAR entry using a class loader: " + + resourceUrl); return true; } else { // Some servers such as GlassFish extract files from JARs (file:) @@ -1390,11 +1392,13 @@ public abstract class AbstractApplicationServlet extends HttpServlet implements // "/../" if (!resourceUrl.getPath().contains("/VAADIN/") || resourceUrl.getPath().contains("/../")) { - logger.info("Blocked attempt to access file: " + resourceUrl); + getLogger().info( + "Blocked attempt to access file: " + resourceUrl); return false; } - logger.fine("Accepted access to a file using a class loader: " - + resourceUrl); + getLogger().fine( + "Accepted access to a file using a class loader: " + + resourceUrl); return true; } } @@ -1796,7 +1800,8 @@ public abstract class AbstractApplicationServlet extends HttpServlet implements try { return getApplicationClass().getSimpleName(); } catch (ClassNotFoundException e) { - logger.log(Level.WARNING, "getApplicationCSSClassName failed", e); + getLogger().log(Level.WARNING, "getApplicationCSSClassName failed", + e); return "unknown"; } } @@ -2518,4 +2523,8 @@ public abstract class AbstractApplicationServlet extends HttpServlet implements c > 96 && c < 123 // a-z ; } + + private static final Logger getLogger() { + return Logger.getLogger(AbstractApplicationServlet.class.getName()); + } } diff --git a/src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java b/src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java index cb570f88e7..b001b52918 100644 --- a/src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java +++ b/src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java @@ -91,9 +91,6 @@ public abstract class AbstractCommunicationManager implements private static final String DASHDASH = "--"; - private static final Logger logger = Logger - .getLogger(AbstractCommunicationManager.class.getName()); - /** * Generic interface of a (HTTP or Portlet) request to the application. * @@ -737,8 +734,9 @@ public abstract class AbstractCommunicationManager implements if (window == null) { // This should not happen, no windows exists but // application is still open. - logger.warning("Could not get window for application with request ID " - + request.getRequestID()); + getLogger().warning( + "Could not get window for application with request ID " + + request.getRequestID()); return; } } else { @@ -762,7 +760,7 @@ public abstract class AbstractCommunicationManager implements // FIXME: Handle exception // Not critical, but something is still wrong; print // stacktrace - logger.log(Level.WARNING, + getLogger().log(Level.WARNING, "getSystemMessages() failed - continuing", e2); } if (ci != null) { @@ -808,7 +806,7 @@ public abstract class AbstractCommunicationManager implements printHighlightedComponentHierarchy(sb, component); } - logger.info(sb.toString()); + getLogger().info(sb.toString()); } protected void printHighlightedComponentHierarchy(StringBuilder sb, @@ -1095,16 +1093,16 @@ public abstract class AbstractCommunicationManager implements (Class[]) null); ci = (Application.SystemMessages) m.invoke(null, (Object[]) null); } catch (NoSuchMethodException e) { - logger.log(Level.WARNING, + getLogger().log(Level.WARNING, "getSystemMessages() failed - continuing", e); } catch (IllegalArgumentException e) { - logger.log(Level.WARNING, + getLogger().log(Level.WARNING, "getSystemMessages() failed - continuing", e); } catch (IllegalAccessException e) { - logger.log(Level.WARNING, + getLogger().log(Level.WARNING, "getSystemMessages() failed - continuing", e); } catch (InvocationTargetException e) { - logger.log(Level.WARNING, + getLogger().log(Level.WARNING, "getSystemMessages() failed - continuing", e); } @@ -1144,8 +1142,8 @@ public abstract class AbstractCommunicationManager implements resource); } catch (final Exception e) { // FIXME: Handle exception - logger.log(Level.FINER, "Failed to get theme resource stream.", - e); + getLogger().log(Level.FINER, + "Failed to get theme resource stream.", e); } if (is != null) { @@ -1164,13 +1162,13 @@ public abstract class AbstractCommunicationManager implements r.close(); } catch (final java.io.IOException e) { // FIXME: Handle exception - logger.log(Level.INFO, "Resource transfer failed", e); + getLogger().log(Level.INFO, "Resource transfer failed", e); } outWriter.print("\"" + JsonPaintTarget.escapeJSON(layout.toString()) + "\""); } else { // FIXME: Handle exception - logger.severe("CustomLayout not found: " + resource); + getLogger().severe("CustomLayout not found: " + resource); } } outWriter.print("}"); @@ -1444,7 +1442,7 @@ public abstract class AbstractCommunicationManager implements + variable[VAR_PID]; success = false; } - logger.warning(msg); + getLogger().warning(msg); continue; } } @@ -1779,8 +1777,9 @@ public abstract class AbstractCommunicationManager implements DateFormat dateFormat = DateFormat.getDateTimeInstance( DateFormat.SHORT, DateFormat.SHORT, l); if (!(dateFormat instanceof SimpleDateFormat)) { - logger.warning("Unable to get default date pattern for locale " - + l.toString()); + getLogger().warning( + "Unable to get default date pattern for locale " + + l.toString()); dateFormat = new SimpleDateFormat(); } final String df = ((SimpleDateFormat) dateFormat).toPattern(); @@ -2483,4 +2482,8 @@ public abstract class AbstractCommunicationManager implements return b; } } + + private static final Logger getLogger() { + return Logger.getLogger(AbstractCommunicationManager.class.getName()); + } } diff --git a/src/com/vaadin/terminal/gwt/server/AbstractWebApplicationContext.java b/src/com/vaadin/terminal/gwt/server/AbstractWebApplicationContext.java index c0ae0afc26..bf4ea860a8 100644 --- a/src/com/vaadin/terminal/gwt/server/AbstractWebApplicationContext.java +++ b/src/com/vaadin/terminal/gwt/server/AbstractWebApplicationContext.java @@ -32,9 +32,6 @@ import com.vaadin.terminal.ApplicationResource; public abstract class AbstractWebApplicationContext implements ApplicationContext, HttpSessionBindingListener, Serializable { - private static final Logger logger = Logger - .getLogger(AbstractWebApplicationContext.class.getName()); - protected Collection listeners = Collections .synchronizedList(new LinkedList()); @@ -145,7 +142,7 @@ public abstract class AbstractWebApplicationContext implements // remove same application here. Possible if you got e.g. session // lifetime 1 min but socket write may take longer than 1 min. // FIXME: Handle exception - logger.log(Level.SEVERE, + getLogger().log(Level.SEVERE, "Could not remove application, leaking memory.", e); } } @@ -252,4 +249,8 @@ public abstract class AbstractWebApplicationContext implements return lastRequestTime; } + private Logger getLogger() { + return Logger.getLogger(AbstractWebApplicationContext.class.getName()); + } + } \ No newline at end of file diff --git a/src/com/vaadin/terminal/gwt/server/ApplicationRunnerServlet.java b/src/com/vaadin/terminal/gwt/server/ApplicationRunnerServlet.java index a9eaa1bb82..38b36a0cbf 100644 --- a/src/com/vaadin/terminal/gwt/server/ApplicationRunnerServlet.java +++ b/src/com/vaadin/terminal/gwt/server/ApplicationRunnerServlet.java @@ -19,9 +19,6 @@ import com.vaadin.Application; @SuppressWarnings("serial") public class ApplicationRunnerServlet extends AbstractApplicationServlet { - private static final Logger logger = Logger - .getLogger(ApplicationRunnerServlet.class.getName()); - /** * The name of the application class currently used. Only valid within one * request. @@ -176,10 +173,10 @@ public class ApplicationRunnerServlet extends AbstractApplicationServlet { // Ignore as this is expected for many packages } catch (Exception e2) { // TODO: handle exception - logger.log( - Level.FINE, - "Failed to find application class in the default package.", - e2); + getLogger() + .log(Level.FINE, + "Failed to find application class in the default package.", + e2); } if (appClass != null) { return appClass; @@ -215,4 +212,8 @@ public class ApplicationRunnerServlet extends AbstractApplicationServlet { return staticFilesPath; } + private Logger getLogger() { + return Logger.getLogger(ApplicationRunnerServlet.class.getName()); + } + } diff --git a/src/com/vaadin/terminal/gwt/server/ComponentSizeValidator.java b/src/com/vaadin/terminal/gwt/server/ComponentSizeValidator.java index 7889968e63..2c48d03b10 100644 --- a/src/com/vaadin/terminal/gwt/server/ComponentSizeValidator.java +++ b/src/com/vaadin/terminal/gwt/server/ComponentSizeValidator.java @@ -35,9 +35,6 @@ import com.vaadin.ui.Window; @SuppressWarnings({ "serial", "deprecation" }) public class ComponentSizeValidator implements Serializable { - private final static Logger logger = Logger - .getLogger(ComponentSizeValidator.class.getName()); - private final static int LAYERS_SHOWN = 4; /** @@ -135,7 +132,7 @@ public class ComponentSizeValidator implements Serializable { return parentCanDefineHeight(component); } catch (Exception e) { - logger.log(Level.FINER, + getLogger().log(Level.FINER, "An exception occurred while validating sizes.", e); return true; } @@ -155,7 +152,7 @@ public class ComponentSizeValidator implements Serializable { return parentCanDefineWidth(component); } catch (Exception e) { - logger.log(Level.FINER, + getLogger().log(Level.FINER, "An exception occurred while validating sizes.", e); return true; } @@ -675,11 +672,15 @@ public class ComponentSizeValidator implements Serializable { return; } catch (Exception e) { // TODO Auto-generated catch block - logger.log(Level.FINER, + getLogger().log(Level.FINER, "An exception occurred while validating sizes.", e); } } } + private static Logger getLogger() { + return Logger.getLogger(ComponentSizeValidator.class.getName()); + } + } diff --git a/src/com/vaadin/terminal/gwt/server/DragAndDropService.java b/src/com/vaadin/terminal/gwt/server/DragAndDropService.java index 3a923c1840..0653754c39 100644 --- a/src/com/vaadin/terminal/gwt/server/DragAndDropService.java +++ b/src/com/vaadin/terminal/gwt/server/DragAndDropService.java @@ -23,9 +23,6 @@ import com.vaadin.ui.Component; public class DragAndDropService implements VariableOwner { - private static final Logger logger = Logger - .getLogger(DragAndDropService.class.getName()); - private int lastVisitId; private boolean lastVisitAccepted = false; @@ -45,8 +42,9 @@ public class DragAndDropService implements VariableOwner { // Validate drop handler owner if (!(owner instanceof DropTarget)) { - logger.severe("DropHandler owner " + owner - + " must implement DropTarget"); + getLogger() + .severe("DropHandler owner " + owner + + " must implement DropTarget"); return; } // owner cannot be null here @@ -76,8 +74,9 @@ public class DragAndDropService implements VariableOwner { DropHandler dropHandler = (dropTarget).getDropHandler(); if (dropHandler == null) { // No dropHandler returned so no drop can be performed. - logger.fine("DropTarget.getDropHandler() returned null for owner: " - + dropTarget); + getLogger().fine( + "DropTarget.getDropHandler() returned null for owner: " + + dropTarget); return; } @@ -212,4 +211,8 @@ public class DragAndDropService implements VariableOwner { } return false; } + + private Logger getLogger() { + return Logger.getLogger(DragAndDropService.class.getName()); + } } diff --git a/src/com/vaadin/terminal/gwt/server/GAEApplicationServlet.java b/src/com/vaadin/terminal/gwt/server/GAEApplicationServlet.java index 485c98f036..a6032fa98d 100644 --- a/src/com/vaadin/terminal/gwt/server/GAEApplicationServlet.java +++ b/src/com/vaadin/terminal/gwt/server/GAEApplicationServlet.java @@ -94,9 +94,6 @@ import com.vaadin.service.ApplicationContext; */ public class GAEApplicationServlet extends ApplicationServlet { - private static final Logger logger = Logger - .getLogger(GAEApplicationServlet.class.getName()); - // memcache mutex is MUTEX_BASE + sessio id private static final String MUTEX_BASE = "_vmutex"; @@ -209,8 +206,9 @@ public class GAEApplicationServlet extends ApplicationServlet { try { Thread.sleep(RETRY_AFTER_MILLISECONDS); } catch (InterruptedException e) { - logger.finer("Thread.sleep() interrupted while waiting for lock. Trying again. " - + e); + getLogger().finer( + "Thread.sleep() interrupted while waiting for lock. Trying again. " + + e); } } @@ -252,16 +250,16 @@ public class GAEApplicationServlet extends ApplicationServlet { ds.put(entity); } catch (DeadlineExceededException e) { - logger.warning("DeadlineExceeded for " + session.getId()); + getLogger().warning("DeadlineExceeded for " + session.getId()); sendDeadlineExceededNotification(request, response); } catch (NotSerializableException e) { - logger.log(Level.SEVERE, "Not serializable!", e); + getLogger().log(Level.SEVERE, "Not serializable!", e); // TODO this notification is usually not shown - should we redirect // in some other way - can we? sendNotSerializableNotification(request, response); } catch (Exception e) { - logger.log(Level.WARNING, + getLogger().log(Level.WARNING, "An exception occurred while servicing request.", e); sendCriticalErrorNotification(request, response); @@ -308,12 +306,14 @@ public class GAEApplicationServlet extends ApplicationServlet { session.setAttribute(WebApplicationContext.class.getName(), applicationContext); } catch (IOException e) { - logger.log(Level.WARNING, + getLogger().log( + Level.WARNING, "Could not de-serialize ApplicationContext for " + session.getId() + " A new one will be created. ", e); } catch (ClassNotFoundException e) { - logger.log(Level.WARNING, + getLogger().log( + Level.WARNING, "Could not de-serialize ApplicationContext for " + session.getId() + " A new one will be created. ", e); @@ -368,8 +368,9 @@ public class GAEApplicationServlet extends ApplicationServlet { List entities = pq.asList(Builder .withLimit(CLEANUP_LIMIT)); if (entities != null) { - logger.info("Vaadin cleanup deleting " + entities.size() - + " expired Vaadin sessions."); + getLogger().info( + "Vaadin cleanup deleting " + entities.size() + + " expired Vaadin sessions."); List keys = new ArrayList(); for (Entity e : entities) { keys.add(e.getKey()); @@ -387,8 +388,9 @@ public class GAEApplicationServlet extends ApplicationServlet { List entities = pq.asList(Builder .withLimit(CLEANUP_LIMIT)); if (entities != null) { - logger.info("Vaadin cleanup deleting " + entities.size() - + " expired appengine sessions."); + getLogger().info( + "Vaadin cleanup deleting " + entities.size() + + " expired appengine sessions."); List keys = new ArrayList(); for (Entity e : entities) { keys.add(e.getKey()); @@ -397,7 +399,11 @@ public class GAEApplicationServlet extends ApplicationServlet { } } } catch (Exception e) { - logger.log(Level.WARNING, "Exception while cleaning.", e); + getLogger().log(Level.WARNING, "Exception while cleaning.", e); } } + + private static final Logger getLogger() { + return Logger.getLogger(GAEApplicationServlet.class.getName()); + } } diff --git a/src/com/vaadin/terminal/gwt/server/JsonPaintTarget.java b/src/com/vaadin/terminal/gwt/server/JsonPaintTarget.java index 97c5139296..9292ae2506 100644 --- a/src/com/vaadin/terminal/gwt/server/JsonPaintTarget.java +++ b/src/com/vaadin/terminal/gwt/server/JsonPaintTarget.java @@ -52,9 +52,6 @@ import com.vaadin.ui.CustomLayout; @SuppressWarnings("serial") public class JsonPaintTarget implements PaintTarget { - private static final Logger logger = Logger.getLogger(JsonPaintTarget.class - .getName()); - /* Document type declarations */ private final static String UIDL_ARG_NAME = "name"; @@ -700,11 +697,11 @@ public class JsonPaintTarget implements PaintTarget { if (!manager.hasPaintableId(paintable)) { if (paintable instanceof Component && ((Component) paintable).getApplication() == null) { - logger.log( - Level.WARNING, - "Painting reference to orphan " - + paintable.getClass().getName() - + ", the component will not be accessible on the client side."); + getLogger() + .log(Level.WARNING, + "Painting reference to orphan " + + paintable.getClass().getName() + + ", the component will not be accessible on the client side."); return "Orphan"; } if (identifiersCreatedDueRefPaint == null) { @@ -1029,10 +1026,12 @@ public class JsonPaintTarget implements PaintTarget { && Paintable.class.isAssignableFrom(superclass)) { class1 = (Class) superclass; } else { - logger.warning("No superclass of " - + paintable.getClass().getName() - + " has a @ClientWidget" - + " annotation. Component will not be mapped correctly on client side."); + getLogger() + .warning( + "No superclass of " + + paintable.getClass().getName() + + " has a @ClientWidget" + + " annotation. Component will not be mapped correctly on client side."); break; } } @@ -1136,18 +1135,19 @@ public class JsonPaintTarget implements PaintTarget { // TODO could optimize to quit at the end attribute } } catch (IOException e1) { - logger.log(Level.SEVERE, + getLogger().log(Level.SEVERE, "An error occurred while finding widget mapping.", e1); } finally { try { bufferedReader.close(); } catch (IOException e1) { - logger.log(Level.SEVERE, "Could not close reader.", e1); + getLogger() + .log(Level.SEVERE, "Could not close reader.", e1); } } } catch (Throwable t) { - logger.log(Level.SEVERE, + getLogger().log(Level.SEVERE, "An error occurred while finding widget mapping.", t); } @@ -1176,4 +1176,8 @@ public class JsonPaintTarget implements PaintTarget { return !cacheEnabled; } + private static final Logger getLogger() { + return Logger.getLogger(JsonPaintTarget.class.getName()); + } + } diff --git a/src/com/vaadin/terminal/gwt/server/PortletApplicationContext2.java b/src/com/vaadin/terminal/gwt/server/PortletApplicationContext2.java index dce1a1a78c..1875103652 100644 --- a/src/com/vaadin/terminal/gwt/server/PortletApplicationContext2.java +++ b/src/com/vaadin/terminal/gwt/server/PortletApplicationContext2.java @@ -49,9 +49,6 @@ import com.vaadin.ui.Window; @SuppressWarnings("serial") public class PortletApplicationContext2 extends AbstractWebApplicationContext { - private static final Logger logger = Logger - .getLogger(PortletApplicationContext2.class.getName()); - protected Map> portletListeners = new HashMap>(); protected transient PortletSession session; @@ -77,11 +74,11 @@ public class PortletApplicationContext2 extends AbstractWebApplicationContext { return new File(url.getFile()); } catch (final Exception e) { // FIXME: Handle exception - logger.log( - Level.INFO, - "Cannot access base directory, possible security issue " - + "with Application Server or Servlet Container", - e); + getLogger() + .log(Level.INFO, + "Cannot access base directory, possible security issue " + + "with Application Server or Servlet Container", + e); } } return null; @@ -415,4 +412,8 @@ public class PortletApplicationContext2 extends AbstractWebApplicationContext { "Portlet mode can only be changed from a portlet request"); } } + + private Logger getLogger() { + return Logger.getLogger(PortletApplicationContext2.class.getName()); + } } diff --git a/src/com/vaadin/terminal/gwt/widgetsetutils/ClassPathExplorer.java b/src/com/vaadin/terminal/gwt/widgetsetutils/ClassPathExplorer.java index 2e4ce39513..8d7e370aaa 100644 --- a/src/com/vaadin/terminal/gwt/widgetsetutils/ClassPathExplorer.java +++ b/src/com/vaadin/terminal/gwt/widgetsetutils/ClassPathExplorer.java @@ -54,9 +54,6 @@ import com.vaadin.ui.ClientWidget; */ public class ClassPathExplorer { - private static Logger logger = Logger.getLogger(ClassPathExplorer.class - .getName()); - private static final String VAADIN_ADDON_VERSION_ATTRIBUTE = "Vaadin-Package-Version"; /** @@ -103,6 +100,7 @@ public class ClassPathExplorer { * @return a collection of {@link Paintable} classes */ public static Collection> getPaintablesHavingWidgetAnnotation() { + final Logger logger = getLogger(); logger.info("Searching for paintables.."); long start = System.currentTimeMillis(); Collection> paintables = new HashSet>(); @@ -157,6 +155,7 @@ public class ClassPathExplorer { sb.append(widgetsets.get(ws)); sb.append("\n"); } + final Logger logger = getLogger(); logger.info(sb.toString()); logger.info("Search took " + (end - start) + "ms"); return widgetsets; @@ -217,7 +216,7 @@ public class ClassPathExplorer { } catch (MalformedURLException e) { // should never happen as based on an existing URL, // only changing end of file name/path part - logger.log(Level.SEVERE, + getLogger().log(Level.SEVERE, "Error locating the widgetset " + classname, e); } } @@ -253,7 +252,7 @@ public class ClassPathExplorer { } } } catch (IOException e) { - logger.log(Level.WARNING, "Error parsing jar file", e); + getLogger().log(Level.WARNING, "Error parsing jar file", e); } } @@ -281,7 +280,7 @@ public class ClassPathExplorer { classpath = classpath.substring(0, classpath.length() - 1); } - logger.fine("Classpath: " + classpath); + getLogger().fine("Classpath: " + classpath); String[] split = classpath.split(pathSep); for (int i = 0; i < split.length; i++) { @@ -315,6 +314,7 @@ public class ClassPathExplorer { include(null, file, locations); } long end = System.currentTimeMillis(); + Logger logger = getLogger(); if (logger.isLoggable(Level.FINE)) { logger.fine("getClassPathLocations took " + (end - start) + "ms"); } @@ -355,7 +355,7 @@ public class ClassPathExplorer { url = new URL("jar:" + url.toExternalForm() + "!/"); JarURLConnection conn = (JarURLConnection) url .openConnection(); - logger.fine(url.toString()); + getLogger().fine(url.toString()); JarFile jarFile = conn.getJarFile(); Manifest manifest = jarFile.getManifest(); if (manifest != null) { @@ -366,9 +366,11 @@ public class ClassPathExplorer { } } } catch (MalformedURLException e) { - logger.log(Level.FINEST, "Failed to inspect JAR file", e); + getLogger().log(Level.FINEST, "Failed to inspect JAR file", + e); } catch (IOException e) { - logger.log(Level.FINEST, "Failed to inspect JAR file", e); + getLogger().log(Level.FINEST, "Failed to inspect JAR file", + e); } return false; @@ -515,7 +517,7 @@ public class ClassPathExplorer { } } } catch (IOException e) { - logger.warning(e.toString()); + getLogger().warning(e.toString()); } } @@ -594,7 +596,8 @@ public class ClassPathExplorer { // Must be done here after stderr and stdout have been reset. if (errorToShow != null && logLevel != null) { - logger.log(logLevel, + getLogger().log( + logLevel, "Failed to load class " + fullclassName + ". " + errorToShow.getClass().getName() + ": " + errorToShow.getMessage()); @@ -613,6 +616,9 @@ public class ClassPathExplorer { * @return URL */ public static URL getDefaultSourceDirectory() { + + final Logger logger = getLogger(); + if (logger.isLoggable(Level.FINE)) { logger.fine("classpathLocations values:"); ArrayList locations = new ArrayList( @@ -669,20 +675,24 @@ public class ClassPathExplorer { public static void main(String[] args) { Collection> paintables = ClassPathExplorer .getPaintablesHavingWidgetAnnotation(); - logger.info("Found annotated paintables:"); + getLogger().info("Found annotated paintables:"); for (Class cls : paintables) { - logger.info(cls.getCanonicalName()); + getLogger().info(cls.getCanonicalName()); } - logger.info(""); - logger.info("Searching available widgetsets..."); + getLogger().info(""); + getLogger().info("Searching available widgetsets..."); Map availableWidgetSets = ClassPathExplorer .getAvailableWidgetSets(); for (String string : availableWidgetSets.keySet()) { - logger.info(string + " in " + availableWidgetSets.get(string)); + getLogger().info(string + " in " + availableWidgetSets.get(string)); } } + private static final Logger getLogger() { + return Logger.getLogger(ClassPathExplorer.class.getName()); + } + } diff --git a/src/com/vaadin/tools/WidgetsetCompiler.java b/src/com/vaadin/tools/WidgetsetCompiler.java index 323fb17e32..9bb76022ae 100644 --- a/src/com/vaadin/tools/WidgetsetCompiler.java +++ b/src/com/vaadin/tools/WidgetsetCompiler.java @@ -33,9 +33,6 @@ import com.vaadin.terminal.gwt.widgetsetutils.WidgetSetBuilder; */ public class WidgetsetCompiler { - private static final Logger logger = Logger - .getLogger(WidgetsetCompiler.class.getName()); - /** * @param args * same arguments as for com.google.gwt.dev.Compiler @@ -72,7 +69,7 @@ public class WidgetsetCompiler { String[].class); method.invoke(null, new Object[] { args }); } catch (Throwable thr) { - logger.log(Level.SEVERE, + getLogger().log(Level.SEVERE, "Widgetset compilation failed", thr); } } @@ -82,7 +79,11 @@ public class WidgetsetCompiler { runThread.join(); System.out.println("Widgetset compilation finished"); } catch (Throwable thr) { - logger.log(Level.SEVERE, "Widgetset compilation failed", thr); + getLogger().log(Level.SEVERE, "Widgetset compilation failed", thr); } } + + private static final Logger getLogger() { + return Logger.getLogger(WidgetsetCompiler.class.getName()); + } } diff --git a/src/com/vaadin/ui/Table.java b/src/com/vaadin/ui/Table.java index 73fe9679d5..55f3f27507 100644 --- a/src/com/vaadin/ui/Table.java +++ b/src/com/vaadin/ui/Table.java @@ -76,8 +76,7 @@ public class Table extends AbstractSelect implements Action.Container, Container.Ordered, Container.Sortable, ItemClickSource, ItemClickNotifier, DragSource, DropTarget { - private static final Logger logger = Logger - .getLogger(Table.class.getName()); + private transient Logger logger = null; /** * Modes that Table support as drag sourse. @@ -1646,8 +1645,9 @@ public class Table extends AbstractSelect implements Action.Container, * @return */ private Object[][] getVisibleCellsInsertIntoCache(int firstIndex, int rows) { - logger.finest("Insert " + rows + " rows at index " + firstIndex - + " to existing page buffer requested"); + getLogger().finest( + "Insert " + rows + " rows at index " + firstIndex + + " to existing page buffer requested"); // Page buffer must not become larger than pageLength*cacheRate before // or after the current page @@ -1750,11 +1750,14 @@ public class Table extends AbstractSelect implements Action.Container, } } pageBuffer = newPageBuffer; - logger.finest("Page Buffer now contains " - + pageBuffer[CELL_ITEMID].length + " rows (" - + pageBufferFirstIndex + "-" - + (pageBufferFirstIndex + pageBuffer[CELL_ITEMID].length - 1) - + ")"); + getLogger().finest( + "Page Buffer now contains " + + pageBuffer[CELL_ITEMID].length + + " rows (" + + pageBufferFirstIndex + + "-" + + (pageBufferFirstIndex + + pageBuffer[CELL_ITEMID].length - 1) + ")"); return cells; } @@ -1771,8 +1774,9 @@ public class Table extends AbstractSelect implements Action.Container, */ private Object[][] getVisibleCellsNoCache(int firstIndex, int rows, boolean replaceListeners) { - logger.finest("Render visible cells for rows " + firstIndex + "-" - + (firstIndex + rows - 1)); + getLogger().finest( + "Render visible cells for rows " + firstIndex + "-" + + (firstIndex + rows - 1)); final Object[] colids = getVisibleColumns(); final int cols = colids.length; @@ -1954,8 +1958,9 @@ public class Table extends AbstractSelect implements Action.Container, } protected void registerComponent(Component component) { - logger.finest("Registered " + component.getClass().getSimpleName() - + ": " + component.getCaption()); + getLogger().finest( + "Registered " + component.getClass().getSimpleName() + ": " + + component.getCaption()); if (component.getParent() != this) { component.setParent(this); } @@ -1986,8 +1991,9 @@ public class Table extends AbstractSelect implements Action.Container, * @param count */ private void unregisterComponentsAndPropertiesInRows(int firstIx, int count) { - logger.finest("Unregistering components in rows " + firstIx + "-" - + (firstIx + count - 1)); + getLogger().finest( + "Unregistering components in rows " + firstIx + "-" + + (firstIx + count - 1)); Object[] colids = getVisibleColumns(); if (pageBuffer != null && pageBuffer[CELL_ITEMID].length > 0) { int bufSize = pageBuffer[CELL_ITEMID].length; @@ -2067,8 +2073,9 @@ public class Table extends AbstractSelect implements Action.Container, * a set of components that should be unregistered. */ protected void unregisterComponent(Component component) { - logger.finest("Unregistered " + component.getClass().getSimpleName() - + ": " + component.getCaption()); + getLogger().finest( + "Unregistered " + component.getClass().getSimpleName() + ": " + + component.getCaption()); component.setParent(null); /* * Also remove property data sources to unregister listeners keeping the @@ -2438,7 +2445,7 @@ public class Table extends AbstractSelect implements Action.Container, .get("lastToBeRendered")).intValue(); } catch (Exception e) { // FIXME: Handle exception - logger.log(Level.FINER, + getLogger().log(Level.FINER, "Could not parse the first and/or last rows.", e); } @@ -2458,8 +2465,9 @@ public class Table extends AbstractSelect implements Action.Container, } } } - logger.finest("Client wants rows " + reqFirstRowToPaint + "-" - + (reqFirstRowToPaint + reqRowsToPaint - 1)); + getLogger().finest( + "Client wants rows " + reqFirstRowToPaint + "-" + + (reqFirstRowToPaint + reqRowsToPaint - 1)); clientNeedsContentRefresh = true; } @@ -2505,7 +2513,7 @@ public class Table extends AbstractSelect implements Action.Container, } } catch (final Exception e) { // FIXME: Handle exception - logger.log(Level.FINER, + getLogger().log(Level.FINER, "Could not determine column collapsing state", e); } clientNeedsContentRefresh = true; @@ -2527,7 +2535,7 @@ public class Table extends AbstractSelect implements Action.Container, } } catch (final Exception e) { // FIXME: Handle exception - logger.log(Level.FINER, + getLogger().log(Level.FINER, "Could not determine column reordering state", e); } clientNeedsContentRefresh = true; @@ -2817,8 +2825,9 @@ public class Table extends AbstractSelect implements Action.Container, target.startTag("prows"); if (!shouldHideAddedRows()) { - logger.finest("Paint rows for add. Index: " + firstIx + ", count: " - + count + "."); + getLogger().finest( + "Paint rows for add. Index: " + firstIx + ", count: " + + count + "."); // Partial row additions bypass the normal caching mechanism. Object[][] cells = getVisibleCellsInsertIntoCache(firstIx, count); @@ -2841,8 +2850,9 @@ public class Table extends AbstractSelect implements Action.Container, indexInRowbuffer, itemId); } } else { - logger.finest("Paint rows for remove. Index: " + firstIx - + ", count: " + count + "."); + getLogger().finest( + "Paint rows for remove. Index: " + firstIx + ", count: " + + count + "."); removeRowsFromCacheAndFillBottom(firstIx, count); target.addAttribute("hide", true); } @@ -5217,4 +5227,11 @@ public class Table extends AbstractSelect implements Action.Container, } super.setVisible(visible); } + + private final Logger getLogger() { + if (logger == null) { + logger = Logger.getLogger(Table.class.getName()); + } + return logger; + } } diff --git a/src/com/vaadin/ui/TreeTable.java b/src/com/vaadin/ui/TreeTable.java index 19ca27133b..ffdb25b041 100644 --- a/src/com/vaadin/ui/TreeTable.java +++ b/src/com/vaadin/ui/TreeTable.java @@ -50,9 +50,6 @@ import com.vaadin.ui.treetable.HierarchicalContainerOrderedWrapper; @ClientWidget(VTreeTable.class) public class TreeTable extends Table implements Hierarchical { - private static final Logger logger = Logger.getLogger(TreeTable.class - .getName()); - private interface ContainerStrategy extends Serializable { public int size(); @@ -223,9 +220,9 @@ public class TreeTable extends Table implements Hierarchical { boolean removed = openItems.remove(itemId); if (!removed) { openItems.add(itemId); - logger.finest("Item " + itemId + " is now expanded"); + getLogger().finest("Item " + itemId + " is now expanded"); } else { - logger.finest("Item " + itemId + " is now collapsed"); + getLogger().finest("Item " + itemId + " is now collapsed"); } clearPreorderCache(); } @@ -787,4 +784,8 @@ public class TreeTable extends Table implements Hierarchical { requestRepaint(); } + private static final Logger getLogger() { + return Logger.getLogger(TreeTable.class.getName()); + } + } -- cgit v1.2.3 From 564f67f77b535f490fb7c7783d89bf83a55c8cab Mon Sep 17 00:00:00 2001 From: Henri Sara Date: Tue, 5 Jun 2012 11:41:42 +0300 Subject: Deprecate WidgetSetCompiler, not needed with Java6 (but used in Eclipse) --- src/com/vaadin/tools/WidgetsetCompiler.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/com/vaadin/tools/WidgetsetCompiler.java b/src/com/vaadin/tools/WidgetsetCompiler.java index 323fb17e32..618313a8d8 100644 --- a/src/com/vaadin/tools/WidgetsetCompiler.java +++ b/src/com/vaadin/tools/WidgetsetCompiler.java @@ -30,7 +30,10 @@ import com.vaadin.terminal.gwt.widgetsetutils.WidgetSetBuilder; * The source directory containing widgetset and related classes must be * included in the classpath, as well as the gwt-dev-[platform].jar and other * relevant JARs. + * + * @deprecated with Java 6, can use com.google.gwt.dev.Compiler directly (also in Eclipse plug-in etc.) */ +@Deprecated public class WidgetsetCompiler { private static final Logger logger = Logger -- cgit v1.2.3 From f7da26697a01cfda4334557fe94579abffee09bb Mon Sep 17 00:00:00 2001 From: Leif Åstrand Date: Fri, 25 May 2012 16:09:54 +0300 Subject: Initial extension support (#6690) --- .../vaadin/terminal/AbstractClientConnector.java | 452 +++++++++++++++++++++ src/com/vaadin/terminal/AbstractExtension.java | 25 ++ src/com/vaadin/terminal/Extension.java | 7 + src/com/vaadin/terminal/PaintTarget.java | 26 +- .../gwt/client/ApplicationConfiguration.java | 16 +- .../terminal/gwt/client/ApplicationConnection.java | 119 +++--- .../terminal/gwt/client/ComponentConnector.java | 23 -- .../gwt/client/ComponentContainerConnector.java | 12 +- .../terminal/gwt/client/ComponentLocator.java | 29 +- .../vaadin/terminal/gwt/client/ComponentState.java | 24 -- src/com/vaadin/terminal/gwt/client/Connector.java | 8 + .../vaadin/terminal/gwt/client/ConnectorMap.java | 21 +- .../vaadin/terminal/gwt/client/LayoutManager.java | 12 +- .../terminal/gwt/client/ServerConnector.java | 29 ++ src/com/vaadin/terminal/gwt/client/Util.java | 15 +- .../vaadin/terminal/gwt/client/VDebugConsole.java | 47 +-- .../vaadin/terminal/gwt/client/VUIDLBrowser.java | 4 +- .../terminal/gwt/client/WidgetInstantiator.java | 2 +- src/com/vaadin/terminal/gwt/client/WidgetMap.java | 12 +- src/com/vaadin/terminal/gwt/client/WidgetSet.java | 35 +- .../gwt/client/communication/SharedState.java | 26 ++ .../gwt/client/ui/AbstractComponentConnector.java | 67 +-- .../ui/AbstractComponentContainerConnector.java | 41 +- .../terminal/gwt/client/ui/AbstractConnector.java | 66 ++- .../ui/absolutelayout/AbsoluteLayoutConnector.java | 8 +- .../client/ui/csslayout/CssLayoutConnector.java | 4 +- .../customcomponent/CustomComponentConnector.java | 4 +- .../ui/customlayout/CustomLayoutConnector.java | 2 +- .../client/ui/formlayout/FormLayoutConnector.java | 4 +- .../client/ui/gridlayout/GridLayoutConnector.java | 4 +- .../client/ui/helloworldfeature/GreetAgainRpc.java | 12 + .../HelloWorldExtensionConnector.java | 48 +++ .../client/ui/helloworldfeature/HelloWorldRpc.java | 10 + .../ui/helloworldfeature/HelloWorldState.java | 18 + .../gwt/client/ui/layout/LayoutDependencyTree.java | 23 +- .../AbstractOrderedLayoutConnector.java | 6 +- .../gwt/client/ui/panel/PanelConnector.java | 4 +- .../terminal/gwt/client/ui/root/RootConnector.java | 6 +- .../ui/splitpanel/AbstractSplitPanelConnector.java | 2 +- .../gwt/client/ui/table/TableConnector.java | 8 +- .../gwt/client/ui/window/WindowConnector.java | 4 +- .../gwt/server/AbstractApplicationPortlet.java | 47 +-- .../gwt/server/AbstractCommunicationManager.java | 100 +++-- .../terminal/gwt/server/ClientConnector.java | 96 +++++ .../terminal/gwt/server/DragAndDropService.java | 42 ++ .../terminal/gwt/server/JsonPaintTarget.java | 9 +- .../widgetsetutils/CustomWidgetMapGenerator.java | 4 +- .../widgetsetutils/EagerWidgetMapGenerator.java | 5 +- .../gwt/widgetsetutils/LazyWidgetMapGenerator.java | 5 +- .../gwt/widgetsetutils/SerializerMapGenerator.java | 1 + .../gwt/widgetsetutils/WidgetMapGenerator.java | 62 ++- src/com/vaadin/ui/AbsoluteLayout.java | 3 +- src/com/vaadin/ui/AbstractComponent.java | 395 ++---------------- src/com/vaadin/ui/AbstractComponentContainer.java | 70 ---- src/com/vaadin/ui/Component.java | 138 +------ src/com/vaadin/ui/CssLayout.java | 5 +- src/com/vaadin/ui/CustomField.java | 9 +- src/com/vaadin/ui/DirtyConnectorTracker.java | 84 ++-- src/com/vaadin/ui/Form.java | 4 - src/com/vaadin/ui/HasComponents.java | 11 +- src/com/vaadin/ui/HelloWorldExtension.java | 38 ++ src/com/vaadin/ui/Panel.java | 38 -- src/com/vaadin/ui/Root.java | 8 - src/com/vaadin/ui/Table.java | 18 - .../TestAbstractComponentStyleNames.java | 1 - .../textfield/TextFieldWithPropertyFormatter.java | 15 +- .../tests/features/HelloWorldFeatureTest.java | 38 ++ 67 files changed, 1352 insertions(+), 1179 deletions(-) create mode 100644 src/com/vaadin/terminal/AbstractClientConnector.java create mode 100644 src/com/vaadin/terminal/AbstractExtension.java create mode 100644 src/com/vaadin/terminal/Extension.java create mode 100644 src/com/vaadin/terminal/gwt/client/ui/helloworldfeature/GreetAgainRpc.java create mode 100644 src/com/vaadin/terminal/gwt/client/ui/helloworldfeature/HelloWorldExtensionConnector.java create mode 100644 src/com/vaadin/terminal/gwt/client/ui/helloworldfeature/HelloWorldRpc.java create mode 100644 src/com/vaadin/terminal/gwt/client/ui/helloworldfeature/HelloWorldState.java create mode 100644 src/com/vaadin/ui/HelloWorldExtension.java create mode 100644 tests/testbench/com/vaadin/tests/features/HelloWorldFeatureTest.java diff --git a/src/com/vaadin/terminal/AbstractClientConnector.java b/src/com/vaadin/terminal/AbstractClientConnector.java new file mode 100644 index 0000000000..ad7c98b7e1 --- /dev/null +++ b/src/com/vaadin/terminal/AbstractClientConnector.java @@ -0,0 +1,452 @@ +package com.vaadin.terminal; + +import java.io.Serializable; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.NoSuchElementException; +import java.util.logging.Logger; + +import com.vaadin.Application; +import com.vaadin.terminal.gwt.client.communication.ClientRpc; +import com.vaadin.terminal.gwt.client.communication.ServerRpc; +import com.vaadin.terminal.gwt.client.communication.SharedState; +import com.vaadin.terminal.gwt.server.ClientConnector; +import com.vaadin.terminal.gwt.server.ClientMethodInvocation; +import com.vaadin.terminal.gwt.server.RpcManager; +import com.vaadin.terminal.gwt.server.RpcTarget; +import com.vaadin.terminal.gwt.server.ServerRpcManager; +import com.vaadin.ui.HasComponents; +import com.vaadin.ui.Root; + +/** + * + */ +public abstract class AbstractClientConnector implements ClientConnector { + /** + * A map from client to server RPC interface class to the RPC call manager + * that handles incoming RPC calls for that interface. + */ + private Map, RpcManager> rpcManagerMap = new HashMap, RpcManager>(); + + /** + * A map from server to client RPC interface class to the RPC proxy that + * sends ourgoing RPC calls for that interface. + */ + private Map, ClientRpc> rpcProxyMap = new HashMap, ClientRpc>(); + + /** + * Shared state object to be communicated from the server to the client when + * modified. + */ + private SharedState sharedState; + + /** + * Pending RPC method invocations to be sent. + */ + private ArrayList pendingInvocations = new ArrayList(); + + private String connectorId; + + private ArrayList extensions = new ArrayList(); + + private ClientConnector parent; + + /* Documentation copied from interface */ + public void requestRepaint() { + Root root = getRoot(); + if (root != null) { + root.getDirtyConnectorTracker().markDirty(this); + } + } + + /** + * Registers an RPC interface implementation for this component. + * + * A component can listen to multiple RPC interfaces, and subclasses can + * register additional implementations. + * + * @since 7.0 + * + * @param implementation + * RPC interface implementation + * @param rpcInterfaceType + * RPC interface class for which the implementation should be + * registered + */ + protected void registerRpc(T implementation, Class rpcInterfaceType) { + rpcManagerMap.put(rpcInterfaceType, new ServerRpcManager( + implementation, rpcInterfaceType)); + } + + /** + * Registers an RPC interface implementation for this component. + * + * A component can listen to multiple RPC interfaces, and subclasses can + * register additional implementations. + * + * @since 7.0 + * + * @param implementation + * RPC interface implementation. Also used to deduce the type. + */ + protected void registerRpc(T implementation) { + Class cls = implementation.getClass(); + Class[] interfaces = cls.getInterfaces(); + while (interfaces.length == 0) { + // Search upwards until an interface is found. It must be found as T + // extends ServerRpc + cls = cls.getSuperclass(); + interfaces = cls.getInterfaces(); + } + if (interfaces.length != 1 + || !(ServerRpc.class.isAssignableFrom(interfaces[0]))) { + throw new RuntimeException( + "Use registerRpc(T implementation, Class rpcInterfaceType) if the Rpc implementation implements more than one interface"); + } + Class type = (Class) interfaces[0]; + registerRpc(implementation, type); + } + + public SharedState getState() { + if (null == sharedState) { + sharedState = createState(); + } + return sharedState; + } + + /** + * Creates the shared state bean to be used in server to client + * communication. + *

      + * By default a state object of the defined return type of + * {@link #getState()} is created. Subclasses can override this method and + * return a new instance of the correct state class but this should rarely + * be necessary. + *

      + *

      + * No configuration of the values of the state should be performed in + * {@link #createState()}. + * + * @since 7.0 + * + * @return new shared state object + */ + protected SharedState createState() { + try { + return getStateType().newInstance(); + } catch (Exception e) { + throw new RuntimeException( + "Error creating state of type " + getStateType().getName() + + " for " + getClass().getName(), e); + } + } + + /* + * (non-Javadoc) + * + * @see com.vaadin.terminal.gwt.server.ClientConnector#getStateType() + */ + public Class getStateType() { + try { + Method m = getClass().getMethod("getState", (Class[]) null); + Class type = m.getReturnType(); + return type.asSubclass(SharedState.class); + } catch (Exception e) { + throw new RuntimeException("Error finding state type for " + + getClass().getName(), e); + } + } + + /** + * Returns an RPC proxy for a given server to client RPC interface for this + * component. + * + * TODO more javadoc, subclasses, ... + * + * @param rpcInterface + * RPC interface type + * + * @since 7.0 + */ + public T getRpcProxy(final Class rpcInterface) { + // create, initialize and return a dynamic proxy for RPC + try { + if (!rpcProxyMap.containsKey(rpcInterface)) { + Class proxyClass = Proxy.getProxyClass( + rpcInterface.getClassLoader(), rpcInterface); + Constructor constructor = proxyClass + .getConstructor(InvocationHandler.class); + T rpcProxy = rpcInterface.cast(constructor + .newInstance(new RpcInvoicationHandler(rpcInterface))); + // cache the proxy + rpcProxyMap.put(rpcInterface, rpcProxy); + } + return (T) rpcProxyMap.get(rpcInterface); + } catch (Exception e) { + // TODO exception handling? + throw new RuntimeException(e); + } + } + + private class RpcInvoicationHandler implements InvocationHandler, + Serializable { + + private String rpcInterfaceName; + + public RpcInvoicationHandler(Class rpcInterface) { + rpcInterfaceName = rpcInterface.getName().replaceAll("\\$", "."); + } + + public Object invoke(Object proxy, Method method, Object[] args) + throws Throwable { + addMethodInvocationToQueue(rpcInterfaceName, method, args); + // TODO no need to do full repaint if only RPC calls + requestRepaint(); + return null; + } + + } + + /** + * For internal use: adds a method invocation to the pending RPC call queue. + * + * @param interfaceName + * RPC interface name + * @param method + * RPC method + * @param parameters + * RPC all parameters + * + * @since 7.0 + */ + protected void addMethodInvocationToQueue(String interfaceName, + Method method, Object[] parameters) { + // add to queue + pendingInvocations.add(new ClientMethodInvocation(this, interfaceName, + method, parameters)); + } + + /** + * @see RpcTarget#getRpcManager(Class) + * + * @param rpcInterface + * RPC interface for which a call was made + * @return RPC Manager handling calls for the interface + * + * @since 7.0 + */ + public RpcManager getRpcManager(Class rpcInterface) { + return rpcManagerMap.get(rpcInterface); + } + + public List retrievePendingRpcCalls() { + if (pendingInvocations.isEmpty()) { + return Collections.emptyList(); + } else { + List result = pendingInvocations; + pendingInvocations = new ArrayList(); + return Collections.unmodifiableList(result); + } + } + + public String getConnectorId() { + if (connectorId == null) { + if (getApplication() == null) { + throw new RuntimeException( + "Component must be attached to an application when getConnectorId() is called for the first time"); + } + connectorId = getApplication().createConnectorId(this); + } + return connectorId; + } + + /** + * Finds the Application to which this connector belongs. If the connector + * has not been attached, null is returned. + * + * @return The connector's application, or null if not attached + */ + protected Application getApplication() { + Root root = getRoot(); + if (root == null) { + return null; + } else { + return root.getApplication(); + } + } + + /** + * Finds a Root ancestor of this connector. null is returned if + * no Root ancestor is found (typically because the connector is not + * attached to a proper hierarchy). + * + * @return the Root ancestor of this connector, or null if none + * is found. + */ + protected Root getRoot() { + ClientConnector connector = this; + while (connector != null) { + if (connector instanceof Root) { + return (Root) connector; + } + connector = connector.getParent(); + } + return null; + } + + private static Logger getLogger() { + return Logger.getLogger(AbstractClientConnector.class.getName()); + } + + public void requestRepaintAll() { + requestRepaint(); + + for (ClientConnector connector : getAllChildrenIteratable(this)) { + connector.requestRepaintAll(); + } + } + + private static final class CombinedIterator implements Iterator, + Serializable { + + private final Collection> iterators = new ArrayList>(); + + public void addIterator(Iterator iterator) { + iterators.add(iterator); + } + + public boolean hasNext() { + for (Iterator i : iterators) { + if (i.hasNext()) { + return true; + } + } + return false; + } + + public T next() { + for (Iterator i : iterators) { + if (i.hasNext()) { + return i.next(); + } + } + throw new NoSuchElementException(); + } + + public void remove() { + throw new UnsupportedOperationException(); + } + } + + public static Iterable getAllChildrenIteratable( + final ClientConnector connector) { + return new Iterable() { + public Iterator iterator() { + CombinedIterator iterator = new CombinedIterator(); + iterator.addIterator(connector.getExtensionIterator()); + + if (connector instanceof HasComponents) { + HasComponents hasComponents = (HasComponents) connector; + iterator.addIterator(hasComponents.iterator()); + } + + return iterator; + } + }; + } + + public Iterator getExtensionIterator() { + return Collections.unmodifiableList(extensions).iterator(); + } + + protected void addExtension(Extension extension) { + addExtensionAtIndex(extension, extensions.size()); + } + + protected void addExtensionAtIndex(Extension extension, int index) { + ClientConnector previousParent = extension.getParent(); + if (previousParent == this) { + int oldIndex = extensions.indexOf(extension); + if (oldIndex < index) { + index--; + } + extensions.remove(oldIndex); + extensions.add(index, extension); + } else { + if (previousParent != null) { + previousParent.removeExtension(extension); + } + extensions.add(index, extension); + extension.setParent(this); + } + requestRepaint(); + } + + public void removeExtension(Extension extension) { + extension.setParent(null); + extensions.remove(extension); + requestRepaint(); + } + + public void setParent(ClientConnector parent) { + + // If the parent is not changed, don't do anything + if (parent == this.parent) { + return; + } + + if (parent != null && this.parent != null) { + throw new IllegalStateException(getClass().getName() + + " already has a parent."); + } + + // Send detach event if the component have been connected to a window + if (getApplication() != null) { + detach(); + } + + // Connect to new parent + this.parent = parent; + + // Send attach event if connected to an application + if (getApplication() != null) { + attach(); + } + } + + public ClientConnector getParent() { + return parent; + } + + public void attach() { + requestRepaint(); + + for (ClientConnector connector : getAllChildrenIteratable(this)) { + connector.attach(); + } + } + + public void detach() { + for (ClientConnector connector : getAllChildrenIteratable(this)) { + connector.detach(); + } + } + + public boolean isConnectorEnabled() { + if (getParent() == null) { + // No parent -> the component cannot receive updates from the client + return false; + } else { + return getParent().isConnectorEnabled(); + } + } +} diff --git a/src/com/vaadin/terminal/AbstractExtension.java b/src/com/vaadin/terminal/AbstractExtension.java new file mode 100644 index 0000000000..d01f7544c5 --- /dev/null +++ b/src/com/vaadin/terminal/AbstractExtension.java @@ -0,0 +1,25 @@ +package com.vaadin.terminal; + +import com.vaadin.terminal.gwt.server.ClientConnector; + +public abstract class AbstractExtension extends AbstractClientConnector implements + Extension { + + protected Class getAcceptedParentType() { + return ClientConnector.class; + } + + @Override + public void setParent(ClientConnector parent) { + Class acceptedParentType = getAcceptedParentType(); + if (parent == null || acceptedParentType.isInstance(parent)) { + super.setParent(parent); + } else { + throw new IllegalArgumentException(getClass().getName() + + " can only be attached to parents of type " + + acceptedParentType.getName() + " but attach to " + + parent.getClass().getName() + " was attempted."); + } + } + +} diff --git a/src/com/vaadin/terminal/Extension.java b/src/com/vaadin/terminal/Extension.java new file mode 100644 index 0000000000..7e4b92811d --- /dev/null +++ b/src/com/vaadin/terminal/Extension.java @@ -0,0 +1,7 @@ +package com.vaadin.terminal; + +import com.vaadin.terminal.gwt.server.ClientConnector; + +public interface Extension extends ClientConnector { + +} diff --git a/src/com/vaadin/terminal/PaintTarget.java b/src/com/vaadin/terminal/PaintTarget.java index 9cfa324133..b658c9f4a3 100644 --- a/src/com/vaadin/terminal/PaintTarget.java +++ b/src/com/vaadin/terminal/PaintTarget.java @@ -9,7 +9,9 @@ import java.util.Map; import com.vaadin.terminal.StreamVariable.StreamingStartEvent; import com.vaadin.terminal.gwt.client.ApplicationConnection; +import com.vaadin.terminal.gwt.client.Paintable; import com.vaadin.terminal.gwt.server.ClientConnector; +import com.vaadin.ui.Component; /** * This interface defines the methods for painting XML to the UIDL stream. @@ -39,7 +41,7 @@ public interface PaintTarget extends Serializable { /** * Result of starting to paint a Paintable ( - * {@link PaintTarget#startPaintable(ClientConnector, String)}). + * {@link PaintTarget#startPaintable(Component, String)}). * * @since 7.0 */ @@ -55,7 +57,7 @@ public interface PaintTarget extends Serializable { * changes. */ CACHED - }; + } /** * Prints element start tag of a paintable section. Starts a paintable @@ -73,8 +75,8 @@ public interface PaintTarget extends Serializable { *

      *

      * Each paintable being painted should be closed by a matching - * {@link #endPaintable(ClientConnector)} regardless of the - * {@link PaintStatus} returned. + * {@link #endPaintable(Component)} regardless of the {@link PaintStatus} + * returned. *

      * * @param paintable @@ -89,15 +91,15 @@ public interface PaintTarget extends Serializable { * @see #startTag(String) * @since 7.0 (previously using startTag(Paintable, String)) */ - public PaintStatus startPaintable(ClientConnector paintable, String tag) + public PaintStatus startPaintable(Component paintable, String tag) throws PaintException; /** * Prints paintable element end tag. * - * Calls to {@link #startPaintable(ClientConnector, String)}should be - * matched by {@link #endPaintable(ClientConnector)}. If the parent tag is - * closed before every child tag is closed a PaintException is raised. + * Calls to {@link #startPaintable(Component, String)}should be matched by + * {@link #endPaintable(Component)}. If the parent tag is closed before + * every child tag is closed a PaintException is raised. * * @param paintable * the paintable to close. @@ -105,7 +107,7 @@ public interface PaintTarget extends Serializable { * if the paint operation failed. * @since 7.0 (previously using engTag(String)) */ - public void endPaintable(ClientConnector paintable) throws PaintException; + public void endPaintable(Component paintable) throws PaintException; /** * Prints element start tag. @@ -289,7 +291,7 @@ public interface PaintTarget extends Serializable { * the Paintable to be referenced on client side * @throws PaintException */ - public void addAttribute(String name, ClientConnector value) + public void addAttribute(String name, Component value) throws PaintException; /** @@ -421,8 +423,8 @@ public interface PaintTarget extends Serializable { * @throws PaintException * if the paint oparation fails */ - public void addVariable(VariableOwner owner, String name, - ClientConnector value) throws PaintException; + public void addVariable(VariableOwner owner, String name, Component value) + throws PaintException; /** * Adds a upload stream type variable. diff --git a/src/com/vaadin/terminal/gwt/client/ApplicationConfiguration.java b/src/com/vaadin/terminal/gwt/client/ApplicationConfiguration.java index 8eeccb828d..244f310c1a 100644 --- a/src/com/vaadin/terminal/gwt/client/ApplicationConfiguration.java +++ b/src/com/vaadin/terminal/gwt/client/ApplicationConfiguration.java @@ -209,7 +209,7 @@ public class ApplicationConfiguration implements EntryPoint { private HashMap unknownComponents; - private Class[] classes = new Class[1024]; + private Class[] classes = new Class[1024]; private boolean browserDetailsSent = false; private boolean widgetsetVersionSent = false; @@ -393,7 +393,7 @@ public class ApplicationConfiguration implements EntryPoint { return useDebugIdInDom; } - public Class getWidgetClassByEncodedTag( + public Class getConnectorClassByEncodedTag( int tag) { try { return classes[tag]; @@ -508,7 +508,7 @@ public class ApplicationConfiguration implements EntryPoint { public void run() { pending = false; if (!isBusy()) { - Class nextType = getNextType(); + Class nextType = getNextType(); if (nextType == null) { // ensured that all widgets are loaded deferredWidgetLoader = null; @@ -521,13 +521,13 @@ public class ApplicationConfiguration implements EntryPoint { } } - private Class getNextType() { - Class[] deferredLoadedWidgets = widgetSet - .getDeferredLoadedWidgets(); - if (deferredLoadedWidgets.length <= nextWidgetIndex) { + private Class getNextType() { + Class[] deferredLoadedConnectors = widgetSet + .getDeferredLoadedConnectors(); + if (deferredLoadedConnectors.length <= nextWidgetIndex) { return null; } else { - return deferredLoadedWidgets[nextWidgetIndex++]; + return deferredLoadedConnectors[nextWidgetIndex++]; } } diff --git a/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java b/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java index 51a0ec3f02..4e7213e777 100644 --- a/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java +++ b/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java @@ -1271,27 +1271,24 @@ public class ApplicationConnection { List currentConnectors = new ArrayList( connectorMap.getConnectors()); for (ServerConnector c : currentConnectors) { - if (c instanceof ComponentConnector) { - ComponentConnector cc = (ComponentConnector) c; - if (cc.getParent() != null) { - if (!cc.getParent().getChildren().contains(cc)) { - VConsole.error("ERROR: Connector is connected to a parent but the parent does not contain the connector"); - } - } else if ((cc instanceof RootConnector && cc == getRootConnector())) { - // RootConnector for this connection, leave as-is - } else if (cc instanceof WindowConnector - && getRootConnector().hasSubWindow( - (WindowConnector) cc)) { - // Sub window attached to this RootConnector, leave - // as-is - } else { - // The connector has been detached from the - // hierarchy, unregister it and any possible - // children. The RootConnector should never be - // unregistered even though it has no parent. - connectorMap.unregisterConnector(cc); - unregistered++; + if (c.getParent() != null) { + if (!c.getParent().getChildren().contains(c)) { + VConsole.error("ERROR: Connector is connected to a parent but the parent does not contain the connector"); } + } else if ((c instanceof RootConnector && c == getRootConnector())) { + // RootConnector for this connection, leave as-is + } else if (c instanceof WindowConnector + && getRootConnector().hasSubWindow( + (WindowConnector) c)) { + // Sub window attached to this RootConnector, leave + // as-is + } else { + // The connector has been detached from the + // hierarchy, unregister it and any possible + // children. The RootConnector should never be + // unregistered even though it has no parent. + connectorMap.unregisterConnector(c); + unregistered++; } } @@ -1319,8 +1316,8 @@ public class ApplicationConnection { continue; } - Class connectorClass = configuration - .getWidgetClassByEncodedTag(connectorType); + Class connectorClass = configuration + .getConnectorClassByEncodedTag(connectorType); // Connector does not exist so we must create it if (connectorClass != RootConnector.class) { @@ -1454,47 +1451,44 @@ public class ApplicationConnection { for (int i = 0; i < hierarchyKeys.length(); i++) { try { String connectorId = hierarchyKeys.get(i); - ServerConnector connector = connectorMap + ServerConnector parentConnector = connectorMap .getConnector(connectorId); - if (!(connector instanceof ComponentContainerConnector)) { - VConsole.error("Retrieved a hierarchy update for a connector (" - + connectorId - + ") that is not a ComponentContainerConnector"); - continue; - } - ComponentContainerConnector ccc = (ComponentContainerConnector) connector; - JsArrayString childConnectorIds = hierarchies .getJSStringArray(connectorId); int childConnectorSize = childConnectorIds.length(); List newChildren = new ArrayList(); + List newComponents = new ArrayList(); for (int connectorIndex = 0; connectorIndex < childConnectorSize; connectorIndex++) { String childConnectorId = childConnectorIds .get(connectorIndex); - ComponentConnector childConnector = (ComponentConnector) connectorMap + ServerConnector childConnector = connectorMap .getConnector(childConnectorId); if (childConnector == null) { VConsole.error("Hierarchy claims that " + childConnectorId + " is a child for " + connectorId + " (" - + connector.getClass().getName() + + parentConnector.getClass().getName() + ") but no connector with id " + childConnectorId + " has been registered"); continue; } newChildren.add(childConnector); - if (childConnector.getParent() != ccc) { + if (childConnector instanceof ComponentConnector) { + newComponents + .add((ComponentConnector) childConnector); + } + if (childConnector.getParent() != parentConnector) { // Avoid extra calls to setParent - childConnector.setParent(ccc); + childConnector.setParent(parentConnector); } } // TODO This check should be done on the server side in // the future so the hierarchy update is only sent when // something actually has changed - List oldChildren = ccc + List oldChildren = parentConnector .getChildren(); boolean actuallyChanged = !Util.collectionsEquals( oldChildren, newChildren); @@ -1503,19 +1497,34 @@ public class ApplicationConnection { continue; } - // Fire change event if the hierarchy has changed - ConnectorHierarchyChangeEvent event = GWT - .create(ConnectorHierarchyChangeEvent.class); - event.setOldChildren(oldChildren); - event.setConnector(ccc); - ccc.setChildren((List) newChildren); - events.add(event); + if (parentConnector instanceof ComponentContainerConnector) { + ComponentContainerConnector ccc = (ComponentContainerConnector) parentConnector; + List oldComponents = ccc + .getChildComponents(); + if (!Util.collectionsEquals(oldComponents, + newComponents)) { + // Fire change event if the hierarchy has + // changed + ConnectorHierarchyChangeEvent event = GWT + .create(ConnectorHierarchyChangeEvent.class); + event.setOldChildren(oldComponents); + event.setConnector(parentConnector); + ccc.setChildComponents(newComponents); + events.add(event); + } + } else if (!newComponents.isEmpty()) { + VConsole.error("Hierachy claims " + + Util.getConnectorString(parentConnector) + + " has component children even though it isn't a ComponentContainerConnector"); + } + + parentConnector.setChildren(newChildren); // Remove parent for children that are no longer // attached to this (avoid updating children if they // have already been assigned to a new parent) - for (ComponentConnector oldChild : oldChildren) { - if (oldChild.getParent() != ccc) { + for (ServerConnector oldChild : oldChildren) { + if (oldChild.getParent() != parentConnector) { continue; } @@ -2079,7 +2088,9 @@ public class ApplicationConnection { @Deprecated public ComponentConnector getPaintable(UIDL uidl) { - return getConnector(uidl.getId(), Integer.parseInt(uidl.getTag())); + // Non-component connectors shouldn't be painted from legacy connectors + return (ComponentConnector) getConnector(uidl.getId(), + Integer.parseInt(uidl.getTag())); } /** @@ -2098,17 +2109,17 @@ public class ApplicationConnection { * @return Either an existing ComponentConnector or a new ComponentConnector * of the given type */ - public ComponentConnector getConnector(String connectorId, int connectorType) { + public ServerConnector getConnector(String connectorId, int connectorType) { if (!connectorMap.hasConnector(connectorId)) { return createAndRegisterConnector(connectorId, connectorType); } - return (ComponentConnector) connectorMap.getConnector(connectorId); + return connectorMap.getConnector(connectorId); } /** - * Creates a new ComponentConnector with the given type and id. + * Creates a new ServerConnector with the given type and id. * - * Creates and registers a new ComponentConnector of the given type. Should + * Creates and registers a new ServerConnector of the given type. Should * never be called with the connector id of an existing connector. * * @param connectorId @@ -2116,13 +2127,13 @@ public class ApplicationConnection { * @param connectorType * Type of the connector, as passed from the server side * - * @return A new ComponentConnector of the given type + * @return A new ServerConnector of the given type */ - private ComponentConnector createAndRegisterConnector(String connectorId, + private ServerConnector createAndRegisterConnector(String connectorId, int connectorType) { // Create and register a new connector with the given type - ComponentConnector p = widgetSet.createWidget(connectorType, - configuration); + ServerConnector p = widgetSet + .createWidget(connectorType, configuration); connectorMap.registerConnector(connectorId, p); p.doInit(connectorId, this); diff --git a/src/com/vaadin/terminal/gwt/client/ComponentConnector.java b/src/com/vaadin/terminal/gwt/client/ComponentConnector.java index 5f9171084e..4e6a690a3c 100644 --- a/src/com/vaadin/terminal/gwt/client/ComponentConnector.java +++ b/src/com/vaadin/terminal/gwt/client/ComponentConnector.java @@ -70,29 +70,6 @@ public interface ComponentConnector extends ServerConnector { */ public boolean isRelativeHeight(); - /** - * Returns the parent of this connector. Can be null for only the root - * connector. - * - * @return The parent of this connector, as set by - * {@link #setParent(ComponentContainerConnector)}. - */ - public ComponentContainerConnector getParent(); - - /** - * Sets the parent for this connector. This method should only be called by - * the framework to ensure that the connector hierarchy on the client side - * and the server side are in sync. - *

      - * Note that calling this method does not fire a - * {@link ConnectorHierarchyChangeEvent}. The event is fired only when the - * whole hierarchy has been updated. - * - * @param parent - * The new parent of the connector - */ - public void setParent(ComponentContainerConnector parent); - /** * Checks if the connector is read only. * diff --git a/src/com/vaadin/terminal/gwt/client/ComponentContainerConnector.java b/src/com/vaadin/terminal/gwt/client/ComponentContainerConnector.java index 05334e8049..08ce3d31dc 100644 --- a/src/com/vaadin/terminal/gwt/client/ComponentContainerConnector.java +++ b/src/com/vaadin/terminal/gwt/client/ComponentContainerConnector.java @@ -14,7 +14,7 @@ import com.vaadin.terminal.gwt.client.ConnectorHierarchyChangeEvent.ConnectorHie * An interface used by client-side connectors whose widget is a component * container (implements {@link HasWidgets}). */ -public interface ComponentContainerConnector extends ComponentConnector { +public interface ComponentContainerConnector extends ServerConnector { /** * Update child components caption, description and error message. @@ -42,7 +42,7 @@ public interface ComponentContainerConnector extends ComponentConnector { * @return A collection of children for this connector. An empty collection * if there are no children. Never returns null. */ - public List getChildren(); + public List getChildComponents(); /** * Sets the children for this connector. This method should only be called @@ -50,14 +50,14 @@ public interface ComponentContainerConnector extends ComponentConnector { * side and the server side are in sync. *

      * Note that calling this method does not call - * {@link #connectorHierarchyChanged(ConnectorHierarchyChangeEvent)}. The - * event method is called only when the hierarchy has been updated for all - * connectors. + * {@link ConnectorHierarchyChangeHandler#onConnectorHierarchyChange(ConnectorHierarchyChangeEvent)} + * . The event method is called only when the hierarchy has been updated for + * all connectors. * * @param children * The new child connectors */ - public void setChildren(List children); + public void setChildComponents(List children); /** * Adds a handler that is called whenever the child hierarchy of this diff --git a/src/com/vaadin/terminal/gwt/client/ComponentLocator.java b/src/com/vaadin/terminal/gwt/client/ComponentLocator.java index d847d49e6f..205317542f 100644 --- a/src/com/vaadin/terminal/gwt/client/ComponentLocator.java +++ b/src/com/vaadin/terminal/gwt/client/ComponentLocator.java @@ -11,7 +11,9 @@ import com.google.gwt.user.client.DOM; import com.google.gwt.user.client.Element; import com.google.gwt.user.client.ui.HasWidgets; import com.google.gwt.user.client.ui.RootPanel; +import com.google.gwt.user.client.ui.SimplePanel; import com.google.gwt.user.client.ui.Widget; +import com.vaadin.terminal.gwt.client.communication.SharedState; import com.vaadin.terminal.gwt.client.ui.SubPartAware; import com.vaadin.terminal.gwt.client.ui.gridlayout.VGridLayout; import com.vaadin.terminal.gwt.client.ui.orderedlayout.VMeasuringOrderedLayout; @@ -440,8 +442,8 @@ public class ComponentLocator { } else if (w == null) { String id = part; // Must be old static pid (PID_S*) - ComponentConnector connector = (ComponentConnector) ConnectorMap - .get(client).getConnector(id); + ServerConnector connector = ConnectorMap.get(client) + .getConnector(id); if (connector == null) { // Lookup by debugId // TODO Optimize this @@ -449,8 +451,8 @@ public class ComponentLocator { id.substring(5)); } - if (connector != null) { - w = connector.getWidget(); + if (connector instanceof ComponentConnector) { + w = ((SimplePanel) connector).getWidget(); } else { // Not found return null; @@ -588,19 +590,16 @@ public class ComponentLocator { return w; } - private ComponentConnector findConnectorById(ComponentConnector root, - String id) { - if (root instanceof ComponentConnector - && id.equals(root.getState().getDebugId())) { + private ServerConnector findConnectorById(ServerConnector root, String id) { + SharedState state = root.getState(); + if (state instanceof ComponentState + && id.equals(((ComponentState) state).getDebugId())) { return root; } - if (root instanceof ComponentContainerConnector) { - ComponentContainerConnector ccc = (ComponentContainerConnector) root; - for (ComponentConnector child : ccc.getChildren()) { - ComponentConnector found = findConnectorById(child, id); - if (found != null) { - return found; - } + for (ServerConnector child : root.getChildren()) { + ServerConnector found = findConnectorById(child, id); + if (found != null) { + return found; } } diff --git a/src/com/vaadin/terminal/gwt/client/ComponentState.java b/src/com/vaadin/terminal/gwt/client/ComponentState.java index 10cd14251b..9cd5c6f668 100644 --- a/src/com/vaadin/terminal/gwt/client/ComponentState.java +++ b/src/com/vaadin/terminal/gwt/client/ComponentState.java @@ -24,7 +24,6 @@ public class ComponentState extends SharedState { private String width = ""; private boolean readOnly = false; private boolean immediate = false; - private boolean enabled = true; private String description = ""; // Note: for the caption, there is a difference between null and an empty // string! @@ -174,29 +173,6 @@ public class ComponentState extends SharedState { return styles != null && !styles.isEmpty(); } - /** - * Returns true if the component is enabled. - * - * @see com.vaadin.ui.Component#isEnabled() - * - * @return true if the component is enabled - */ - public boolean isEnabled() { - return enabled; - } - - /** - * Enables or disables the component. - * - * @see com.vaadin.ui.Component#setEnabled(boolean) - * - * @param enabled - * new mode for the component - */ - public void setEnabled(boolean enabled) { - this.enabled = enabled; - } - /** * Gets the description of the component (typically shown as tooltip). * diff --git a/src/com/vaadin/terminal/gwt/client/Connector.java b/src/com/vaadin/terminal/gwt/client/Connector.java index 1c61052735..9b2fcf61f1 100644 --- a/src/com/vaadin/terminal/gwt/client/Connector.java +++ b/src/com/vaadin/terminal/gwt/client/Connector.java @@ -46,4 +46,12 @@ public interface Connector extends Serializable { */ public String getConnectorId(); + /** + * Gets the parent connector of this connector, or null if the + * connector is not attached to any parent. + * + * @return the parent connector, or null if there is no parent. + */ + public Connector getParent(); + } diff --git a/src/com/vaadin/terminal/gwt/client/ConnectorMap.java b/src/com/vaadin/terminal/gwt/client/ConnectorMap.java index e57776cf1c..816c4f62e3 100644 --- a/src/com/vaadin/terminal/gwt/client/ConnectorMap.java +++ b/src/com/vaadin/terminal/gwt/client/ConnectorMap.java @@ -159,17 +159,16 @@ public class ConnectorMap { idToConnector.remove(connectorId); connector.onUnregister(); - if (connector instanceof ComponentContainerConnector) { - for (ComponentConnector child : ((ComponentContainerConnector) connector) - .getChildren()) { - if (child.getParent() == connector) { - // Only unregister children that are actually connected to - // this parent. For instance when moving connectors from one - // layout to another and removing the first layout it will - // still contain references to its old children, which are - // now attached to another connector. - unregisterConnector(child); - } + for (ServerConnector child : connector.getChildren()) { + if (child.getParent() == connector) { + /* + * Only unregister children that are actually connected to this + * parent. For instance when moving connectors from one layout + * to another and removing the first layout it will still + * contain references to its old children, which are now + * attached to another connector. + */ + unregisterConnector(child); } } } diff --git a/src/com/vaadin/terminal/gwt/client/LayoutManager.java b/src/com/vaadin/terminal/gwt/client/LayoutManager.java index 9390c719fc..2281b4ab9c 100644 --- a/src/com/vaadin/terminal/gwt/client/LayoutManager.java +++ b/src/com/vaadin/terminal/gwt/client/LayoutManager.java @@ -416,11 +416,13 @@ public class LayoutManager { for (ComponentConnector componentConnector : pendingOverflowFixes) { // Delay the overflow fix if the involved connectors might still // change - if (!currentDependencyTree - .noMoreChangesExpected(componentConnector) - || !currentDependencyTree - .noMoreChangesExpected(componentConnector - .getParent())) { + boolean connectorChangesExpected = !currentDependencyTree + .noMoreChangesExpected(componentConnector); + boolean parentChangesExcpected = componentConnector.getParent() instanceof ComponentConnector + && !currentDependencyTree + .noMoreChangesExpected((ComponentConnector) componentConnector + .getParent()); + if (connectorChangesExpected || parentChangesExcpected) { delayedOverflowFixes.add(componentConnector); continue; } diff --git a/src/com/vaadin/terminal/gwt/client/ServerConnector.java b/src/com/vaadin/terminal/gwt/client/ServerConnector.java index 44f65fc6a7..3809073076 100644 --- a/src/com/vaadin/terminal/gwt/client/ServerConnector.java +++ b/src/com/vaadin/terminal/gwt/client/ServerConnector.java @@ -4,6 +4,7 @@ package com.vaadin.terminal.gwt.client; import java.util.Collection; +import java.util.List; import com.google.gwt.event.shared.GwtEvent; import com.google.web.bindery.event.shared.HandlerRegistration; @@ -85,4 +86,32 @@ public interface ServerConnector extends Connector { */ public void onUnregister(); + /** + * Returns the parent of this connector. Can be null for only the root + * connector. + * + * @return The parent of this connector, as set by + * {@link #setParent(ServerConnector)}. + */ + public ServerConnector getParent(); + + /** + * Sets the parent for this connector. This method should only be called by + * the framework to ensure that the connector hierarchy on the client side + * and the server side are in sync. + *

      + * Note that calling this method does not fire a + * {@link ConnectorHierarchyChangeEvent}. The event is fired only when the + * whole hierarchy has been updated. + * + * @param parent + * The new parent of the connector + */ + public void setParent(ServerConnector parent); + + public void updateEnabledState(boolean enabledState); + + public void setChildren(List children); + + public List getChildren(); } diff --git a/src/com/vaadin/terminal/gwt/client/Util.java b/src/com/vaadin/terminal/gwt/client/Util.java index c392a0ba9c..87bf27fc27 100644 --- a/src/com/vaadin/terminal/gwt/client/Util.java +++ b/src/com/vaadin/terminal/gwt/client/Util.java @@ -812,13 +812,12 @@ public class Util { return idx; } - private static void printPaintablesInvocations( + private static void printConnectorInvocations( ArrayList invocations, String id, ApplicationConnection c) { - ComponentConnector paintable = (ComponentConnector) ConnectorMap.get(c) - .getConnector(id); - if (paintable != null) { - VConsole.log("\t" + id + " (" + paintable.getClass() + ") :"); + ServerConnector connector = ConnectorMap.get(c).getConnector(id); + if (connector != null) { + VConsole.log("\t" + id + " (" + connector.getClass() + ") :"); for (MethodInvocation invocation : invocations) { Object[] parameters = invocation.getParameters(); String formattedParams = null; @@ -842,7 +841,7 @@ public class Util { + ")"); } } else { - VConsole.log("\t" + id + ": Warning: no corresponding paintable!"); + VConsole.log("\t" + id + ": Warning: no corresponding connector!"); } } @@ -858,14 +857,14 @@ public class Util { if (curId == null) { curId = id; } else if (!curId.equals(id)) { - printPaintablesInvocations(invocations, curId, c); + printConnectorInvocations(invocations, curId, c); invocations.clear(); curId = id; } invocations.add(loggedBurst.get(i)); } if (!invocations.isEmpty()) { - printPaintablesInvocations(invocations, curId, c); + printConnectorInvocations(invocations, curId, c); } } catch (Exception e) { VConsole.error(e); diff --git a/src/com/vaadin/terminal/gwt/client/VDebugConsole.java b/src/com/vaadin/terminal/gwt/client/VDebugConsole.java index 5eaf78f255..09e939336e 100644 --- a/src/com/vaadin/terminal/gwt/client/VDebugConsole.java +++ b/src/com/vaadin/terminal/gwt/client/VDebugConsole.java @@ -560,23 +560,27 @@ public class VDebugConsole extends VOverlay implements Console { Set zeroHeightComponents, ApplicationConnection ac) { for (final ComponentConnector paintable : zeroHeightComponents) { - final Widget layout = paintable.getParent().getWidget(); + final ServerConnector parent = paintable.getParent(); VerticalPanel errorDetails = new VerticalPanel(); errorDetails.add(new Label("" + Util.getSimpleName(paintable) - + " inside " + Util.getSimpleName(layout))); - final CheckBox emphasisInUi = new CheckBox( - "Emphasize components parent in UI (the actual component is not visible)"); - emphasisInUi.addClickHandler(new ClickHandler() { - public void onClick(ClickEvent event) { - if (paintable != null) { + + " inside " + Util.getSimpleName(parent))); + if (parent instanceof ComponentConnector) { + ComponentConnector parentComponent = (ComponentConnector) parent; + final Widget layout = parentComponent.getWidget(); + + final CheckBox emphasisInUi = new CheckBox( + "Emphasize components parent in UI (the actual component is not visible)"); + emphasisInUi.addClickHandler(new ClickHandler() { + public void onClick(ClickEvent event) { Element element2 = layout.getElement(); Widget.setStyleName(element2, "invalidlayout", - emphasisInUi.getValue()); + emphasisInUi.getValue().booleanValue()); } - } - }); - errorDetails.add(emphasisInUi); + }); + + errorDetails.add(emphasisInUi); + } panel.add(errorDetails); } } @@ -862,7 +866,7 @@ public class VDebugConsole extends VOverlay implements Console { log("================"); log("Connector hierarchy for Root: " + root.getState().getCaption() + " (" + root.getConnectorId() + ")"); - Set connectorsInHierarchy = new HashSet(); + Set connectorsInHierarchy = new HashSet(); SimpleTree rootHierachy = dumpConnectorHierarchy(root, "", connectorsInHierarchy); if (panel.isAttached()) { @@ -874,7 +878,7 @@ public class VDebugConsole extends VOverlay implements Console { Collection registeredConnectors = connectorMap .getConnectors(); log("Sub windows:"); - Set subWindowHierarchyConnectors = new HashSet(); + Set subWindowHierarchyConnectors = new HashSet(); for (WindowConnector wc : root.getSubWindows()) { SimpleTree windowHierachy = dumpConnectorHierarchy(wc, "", subWindowHierarchyConnectors); @@ -908,14 +912,15 @@ public class VDebugConsole extends VOverlay implements Console { } - private SimpleTree dumpConnectorHierarchy( - final ComponentConnector connector, String indent, - Set connectors) { + private SimpleTree dumpConnectorHierarchy(final ServerConnector connector, + String indent, Set connectors) { SimpleTree simpleTree = new SimpleTree(getConnectorString(connector)) { @Override protected void select(ClickEvent event) { super.select(event); - VUIDLBrowser.highlight(connector); + if (connector instanceof ComponentConnector) { + VUIDLBrowser.highlight((ComponentConnector) connector); + } } }; simpleTree.addDomHandler(new MouseOutHandler() { @@ -930,12 +935,8 @@ public class VDebugConsole extends VOverlay implements Console { consoleLog(msg); System.out.println(msg); - if (connector instanceof ComponentContainerConnector) { - for (ComponentConnector c : ((ComponentContainerConnector) connector) - .getChildren()) { - simpleTree.add(dumpConnectorHierarchy(c, indent + " ", - connectors)); - } + for (ServerConnector c : connector.getChildren()) { + simpleTree.add(dumpConnectorHierarchy(c, indent + " ", connectors)); } return simpleTree; } diff --git a/src/com/vaadin/terminal/gwt/client/VUIDLBrowser.java b/src/com/vaadin/terminal/gwt/client/VUIDLBrowser.java index 9fa973dc29..4230eda298 100644 --- a/src/com/vaadin/terminal/gwt/client/VUIDLBrowser.java +++ b/src/com/vaadin/terminal/gwt/client/VUIDLBrowser.java @@ -98,8 +98,8 @@ public class VUIDLBrowser extends SimpleTree { private String getNodeName(UIDL uidl, ApplicationConfiguration conf, int tag) { - Class widgetClassByDecodedTag = conf - .getWidgetClassByEncodedTag(tag); + Class widgetClassByDecodedTag = conf + .getConnectorClassByEncodedTag(tag); if (widgetClassByDecodedTag == UnknownComponentConnector.class) { return conf.getUnknownServerClassNameByTag(tag) + "(NO CLIENT IMPLEMENTATION FOUND)"; diff --git a/src/com/vaadin/terminal/gwt/client/WidgetInstantiator.java b/src/com/vaadin/terminal/gwt/client/WidgetInstantiator.java index dd69883d58..0a4f92bc79 100644 --- a/src/com/vaadin/terminal/gwt/client/WidgetInstantiator.java +++ b/src/com/vaadin/terminal/gwt/client/WidgetInstantiator.java @@ -7,5 +7,5 @@ package com.vaadin.terminal.gwt.client; * A helper class used by WidgetMap implementation. Used by the generated code. */ interface WidgetInstantiator { - public ComponentConnector get(); + public ServerConnector get(); } diff --git a/src/com/vaadin/terminal/gwt/client/WidgetMap.java b/src/com/vaadin/terminal/gwt/client/WidgetMap.java index af84a11ced..b770414457 100644 --- a/src/com/vaadin/terminal/gwt/client/WidgetMap.java +++ b/src/com/vaadin/terminal/gwt/client/WidgetMap.java @@ -17,7 +17,7 @@ import com.vaadin.terminal.gwt.widgetsetutils.WidgetMapGenerator; */ abstract class WidgetMap { - protected static HashMap instmap = new HashMap(); + protected static HashMap, WidgetInstantiator> instmap = new HashMap, WidgetInstantiator>(); /** * Create a new instance of a connector based on its type. @@ -26,8 +26,8 @@ abstract class WidgetMap { * {@link ComponentConnector} class to instantiate * @return new instance of the connector */ - public ComponentConnector instantiate( - Class classType) { + public ServerConnector instantiate( + Class classType) { return instmap.get(classType).get(); } @@ -39,7 +39,7 @@ abstract class WidgetMap { * fully qualified name of the server side component class * @return component connector class to use */ - public abstract Class getConnectorClassForServerSideClassName( + public abstract Class getConnectorClassForServerSideClassName( String fullyqualifiedName); /** @@ -49,7 +49,7 @@ abstract class WidgetMap { * @return component connector class to load after the initial widgetset * loading */ - public abstract Class[] getDeferredLoadedWidgets(); + public abstract Class[] getDeferredLoadedConnectors(); /** * Make sure the code for a (deferred or lazy) component connector type has @@ -60,6 +60,6 @@ abstract class WidgetMap { * component connector class */ public abstract void ensureInstantiator( - Class classType); + Class classType); } diff --git a/src/com/vaadin/terminal/gwt/client/WidgetSet.java b/src/com/vaadin/terminal/gwt/client/WidgetSet.java index e47837296d..a973c4fd05 100644 --- a/src/com/vaadin/terminal/gwt/client/WidgetSet.java +++ b/src/com/vaadin/terminal/gwt/client/WidgetSet.java @@ -18,20 +18,19 @@ public class WidgetSet { private WidgetMap widgetMap = GWT.create(WidgetMap.class); /** - * Create an uninitialized component that best matches given UIDL. The - * component must be a {@link Widget} that implements - * {@link ComponentConnector}. + * Create an uninitialized connector that best matches given UIDL. The + * connector must be a {@link Widget} that implements + * {@link ServerConnector}. * * @param tag - * component type tag for the component to create + * connector type tag for the connector to create * @param client * the application connection that whishes to instantiate widget * - * @return New uninitialized and unregistered component that can paint given + * @return New uninitialized and unregistered connector that can paint given * UIDL. */ - public ComponentConnector createWidget(int tag, - ApplicationConfiguration conf) { + public ServerConnector createWidget(int tag, ApplicationConfiguration conf) { /* * Yes, this (including the generated code in WidgetMap) may look very * odd code, but due the nature of GWT, we cannot do this any cleaner. @@ -40,7 +39,7 @@ public class WidgetSet { * has no "native" counterpart on client side. */ - Class classType = resolveInheritedWidgetType( + Class classType = resolveInheritedWidgetType( conf, tag); if (classType == null || classType == UnknownComponentConnector.class) { @@ -57,9 +56,9 @@ public class WidgetSet { } } - private Class resolveInheritedWidgetType( + private Class resolveInheritedWidgetType( ApplicationConfiguration conf, int tag) { - Class classType = null; + Class classType = null; Integer t = tag; do { classType = resolveWidgetType(t, conf); @@ -68,10 +67,10 @@ public class WidgetSet { return classType; } - protected Class resolveWidgetType(int tag, + protected Class resolveWidgetType(int tag, ApplicationConfiguration conf) { - Class widgetClass = conf - .getWidgetClassByEncodedTag(tag); + Class widgetClass = conf + .getConnectorClassByEncodedTag(tag); return widgetClass; } @@ -85,9 +84,9 @@ public class WidgetSet { * @param applicationConfiguration * @return */ - public Class getConnectorClassByTag(int tag, + public Class getConnectorClassByTag(int tag, ApplicationConfiguration conf) { - Class connectorClass = null; + Class connectorClass = null; Integer t = tag; do { String serverSideClassName = conf.getServerSideClassNameForTag(t); @@ -99,11 +98,11 @@ public class WidgetSet { return connectorClass; } - public Class[] getDeferredLoadedWidgets() { - return widgetMap.getDeferredLoadedWidgets(); + public Class[] getDeferredLoadedConnectors() { + return widgetMap.getDeferredLoadedConnectors(); } - public void loadImplementation(Class nextType) { + public void loadImplementation(Class nextType) { widgetMap.ensureInstantiator(nextType); } diff --git a/src/com/vaadin/terminal/gwt/client/communication/SharedState.java b/src/com/vaadin/terminal/gwt/client/communication/SharedState.java index 266d6bcbf2..b087907f9e 100644 --- a/src/com/vaadin/terminal/gwt/client/communication/SharedState.java +++ b/src/com/vaadin/terminal/gwt/client/communication/SharedState.java @@ -38,4 +38,30 @@ import com.vaadin.terminal.gwt.client.ui.AbstractComponentConnector; * @since 7.0 */ public class SharedState implements Serializable { + + private boolean enabled = true; + + /** + * Returns true if the component is enabled. + * + * @see com.vaadin.ui.Component#isEnabled() + * + * @return true if the component is enabled + */ + public boolean isEnabled() { + return enabled; + } + + /** + * Enables or disables the component. + * + * @see com.vaadin.ui.Component#setEnabled(boolean) + * + * @param enabled + * new mode for the component + */ + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } + } diff --git a/src/com/vaadin/terminal/gwt/client/ui/AbstractComponentConnector.java b/src/com/vaadin/terminal/gwt/client/ui/AbstractComponentConnector.java index d690bdded1..67dbd2d9d9 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/AbstractComponentConnector.java +++ b/src/com/vaadin/terminal/gwt/client/ui/AbstractComponentConnector.java @@ -12,8 +12,10 @@ import com.vaadin.terminal.gwt.client.ApplicationConnection; import com.vaadin.terminal.gwt.client.ComponentConnector; import com.vaadin.terminal.gwt.client.ComponentContainerConnector; import com.vaadin.terminal.gwt.client.ComponentState; +import com.vaadin.terminal.gwt.client.Connector; import com.vaadin.terminal.gwt.client.ConnectorMap; import com.vaadin.terminal.gwt.client.LayoutManager; +import com.vaadin.terminal.gwt.client.ServerConnector; import com.vaadin.terminal.gwt.client.TooltipInfo; import com.vaadin.terminal.gwt.client.UIDL; import com.vaadin.terminal.gwt.client.Util; @@ -24,8 +26,6 @@ import com.vaadin.terminal.gwt.client.ui.root.RootConnector; public abstract class AbstractComponentConnector extends AbstractConnector implements ComponentConnector { - private ComponentContainerConnector parent; - private Widget widget; private String lastKnownWidth = ""; @@ -73,8 +73,6 @@ public abstract class AbstractComponentConnector extends AbstractConnector @Override public void onStateChanged(StateChangeEvent stateChangeEvent) { - super.onStateChanged(stateChangeEvent); - ConnectorMap paintableMap = ConnectorMap.get(getConnection()); if (getState().getDebugId() != null) { @@ -86,7 +84,8 @@ public abstract class AbstractComponentConnector extends AbstractConnector /* * Disabled state may affect (override) tabindex so the order must be - * first setting tabindex, then enabled state. + * first setting tabindex, then enabled state (through super + * implementation). */ if (getState() instanceof TabIndexState && getWidget() instanceof Focusable) { @@ -94,7 +93,7 @@ public abstract class AbstractComponentConnector extends AbstractConnector .getTabIndex()); } - setWidgetEnabled(isEnabled()); + super.onStateChanged(stateChangeEvent); // Style names String styleName = getStyleNames(getWidget().getStylePrimaryName()); @@ -112,10 +111,10 @@ public abstract class AbstractComponentConnector extends AbstractConnector // Set captions if (delegateCaptionHandling()) { - ComponentContainerConnector parent = getParent(); - if (parent != null) { - parent.updateCaption(this); - } else if (!(this instanceof RootConnector)) { + ServerConnector parent = getParent(); + if (parent instanceof ComponentContainerConnector) { + ((ComponentContainerConnector) parent).updateCaption(this); + } else if (parent == null && !(this instanceof RootConnector)) { VConsole.error("Parent of connector " + Util.getConnectorString(this) + " is null. This is typically an indication of a broken component hierarchy"); @@ -143,7 +142,7 @@ public abstract class AbstractComponentConnector extends AbstractConnector // Parent should be updated if either dimension changed between relative // and non-relative if (newWidth.endsWith("%") != lastKnownWidth.endsWith("%")) { - ComponentContainerConnector parent = getParent(); + Connector parent = getParent(); if (parent instanceof ManagedLayout) { getLayoutManager().setNeedsHorizontalLayout( (ManagedLayout) parent); @@ -151,7 +150,7 @@ public abstract class AbstractComponentConnector extends AbstractConnector } if (newHeight.endsWith("%") != lastKnownHeight.endsWith("%")) { - ComponentContainerConnector parent = getParent(); + Connector parent = getParent(); if (parent instanceof ManagedLayout) { getLayoutManager().setNeedsVerticalLayout( (ManagedLayout) parent); @@ -187,23 +186,6 @@ public abstract class AbstractComponentConnector extends AbstractConnector return getState().getWidth().length() == 0; } - /* - * (non-Javadoc) - * - * @see com.vaadin.terminal.gwt.client.Connector#isEnabled() - */ - public boolean isEnabled() { - if (!getState().isEnabled()) { - return false; - } - - if (getParent() == null) { - return true; - } else { - return getParent().isEnabled(); - } - } - /* * (non-Javadoc) * @@ -284,26 +266,6 @@ public abstract class AbstractComponentConnector extends AbstractConnector return LayoutManager.get(getConnection()); } - /* - * (non-Javadoc) - * - * @see com.vaadin.terminal.gwt.client.Connector#getParent() - */ - public ComponentContainerConnector getParent() { - return parent; - } - - /* - * (non-Javadoc) - * - * @see - * com.vaadin.terminal.gwt.client.Connector#setParent(com.vaadin.terminal - * .gwt.client.ComponentContainerConnector) - */ - public void setParent(ComponentContainerConnector parent) { - this.parent = parent; - } - /** * Checks if there is a registered server side listener for the given event * identifier. @@ -318,6 +280,13 @@ public abstract class AbstractComponentConnector extends AbstractConnector return (reg != null && reg.contains(eventIdentifier)); } + @Override + public void updateEnabledState(boolean enabledState) { + super.updateEnabledState(enabledState); + + setWidgetEnabled(isEnabled()); + } + @Override public void onUnregister() { super.onUnregister(); diff --git a/src/com/vaadin/terminal/gwt/client/ui/AbstractComponentContainerConnector.java b/src/com/vaadin/terminal/gwt/client/ui/AbstractComponentContainerConnector.java index 526631e4b2..c6bfba5023 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/AbstractComponentContainerConnector.java +++ b/src/com/vaadin/terminal/gwt/client/ui/AbstractComponentContainerConnector.java @@ -3,7 +3,7 @@ */ package com.vaadin.terminal.gwt.client.ui; -import java.util.LinkedList; +import java.util.Collections; import java.util.List; import com.google.gwt.event.shared.HandlerRegistration; @@ -18,18 +18,10 @@ public abstract class AbstractComponentContainerConnector extends AbstractComponentConnector implements ComponentContainerConnector, ConnectorHierarchyChangeHandler { - List children; + List childComponents; private final boolean debugLogging = false; - /** - * Temporary storage for last enabled state to be able to see if it has - * changed. Can be removed once we are able to listen specifically for - * enabled changes in the state. Widget.isEnabled() cannot be used as all - * Widgets do not implement HasEnabled - */ - private boolean lastWidgetEnabledState = true; - /** * Default constructor */ @@ -43,12 +35,12 @@ public abstract class AbstractComponentContainerConnector extends * @see * com.vaadin.terminal.gwt.client.ComponentContainerConnector#getChildren() */ - public List getChildren() { - if (children == null) { - return new LinkedList(); + public List getChildComponents() { + if (childComponents == null) { + return Collections.emptyList(); } - return children; + return childComponents; } /* @@ -58,8 +50,8 @@ public abstract class AbstractComponentContainerConnector extends * com.vaadin.terminal.gwt.client.ComponentContainerConnector#setChildren * (java.util.Collection) */ - public void setChildren(List children) { - this.children = children; + public void setChildComponents(List childComponents) { + this.childComponents = childComponents; } /* @@ -80,7 +72,7 @@ public abstract class AbstractComponentContainerConnector extends VConsole.log(oldChildren); String newChildren = "* New children: "; - for (ComponentConnector child : getChildren()) { + for (ComponentConnector child : getChildComponents()) { newChildren += Util.getConnectorString(child) + " "; } VConsole.log(newChildren); @@ -92,19 +84,4 @@ public abstract class AbstractComponentContainerConnector extends return ensureHandlerManager().addHandler( ConnectorHierarchyChangeEvent.TYPE, handler); } - - @Override - public void setWidgetEnabled(boolean widgetEnabled) { - if (lastWidgetEnabledState == widgetEnabled) { - return; - } - lastWidgetEnabledState = widgetEnabled; - - super.setWidgetEnabled(widgetEnabled); - for (ComponentConnector c : getChildren()) { - // Update children as they might be affected by the enabled state of - // their parent - c.setWidgetEnabled(c.isEnabled()); - } - } } diff --git a/src/com/vaadin/terminal/gwt/client/ui/AbstractConnector.java b/src/com/vaadin/terminal/gwt/client/ui/AbstractConnector.java index dc960f90a5..bee9c75165 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/AbstractConnector.java +++ b/src/com/vaadin/terminal/gwt/client/ui/AbstractConnector.java @@ -7,6 +7,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; +import java.util.List; import java.util.Map; import com.google.gwt.event.shared.GwtEvent; @@ -40,6 +41,16 @@ public abstract class AbstractConnector implements ServerConnector, private final boolean debugLogging = false; private SharedState state; + private ServerConnector parent; + + /** + * Temporary storage for last enabled state to be able to see if it has + * changed. Can be removed once we are able to listen specifically for + * enabled changes in the state. Widget.isEnabled() cannot be used as all + * Widgets do not implement HasEnabled + */ + private boolean lastEnabledState = true; + private List children; /* * (non-Javadoc) @@ -137,16 +148,6 @@ public abstract class AbstractConnector implements ServerConnector, return (Collection) rpcImplementations.get(rpcInterfaceId); } - /* - * (non-Javadoc) - * - * @see com.vaadin.terminal.gwt.client.Connector#isConnectorEnabled() - */ - public boolean isConnectorEnabled() { - // Client side can always receive message from the server - return true; - } - public void fireEvent(GwtEvent event) { if (handlerManager != null) { handlerManager.fireEvent(event); @@ -172,6 +173,8 @@ public abstract class AbstractConnector implements ServerConnector, + Util.getConnectorString(stateChangeEvent.getConnector()) + " received by " + Util.getConnectorString(this)); } + + updateEnabledState(isEnabled()); } /* @@ -214,4 +217,47 @@ public abstract class AbstractConnector implements ServerConnector, return ConnectorStateFactory.createState(getClass()); } + public ServerConnector getParent() { + return parent; + } + + public void setParent(ServerConnector parent) { + this.parent = parent; + } + + public List getChildren() { + if (children == null) { + return Collections.emptyList(); + } + return children; + } + + public void setChildren(List children) { + this.children = children; + } + + public boolean isEnabled() { + if (!getState().isEnabled()) { + return false; + } + + if (getParent() == null) { + return true; + } else { + return getParent().isEnabled(); + } + } + + public void updateEnabledState(boolean enabledState) { + if (lastEnabledState == enabledState) { + return; + } + lastEnabledState = enabledState; + + for (ServerConnector c : getChildren()) { + // Update children as they might be affected by the enabled state of + // their parent + c.updateEnabledState(c.isEnabled()); + } + } } diff --git a/src/com/vaadin/terminal/gwt/client/ui/absolutelayout/AbsoluteLayoutConnector.java b/src/com/vaadin/terminal/gwt/client/ui/absolutelayout/AbsoluteLayoutConnector.java index b42c0acea7..91436f5353 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/absolutelayout/AbsoluteLayoutConnector.java +++ b/src/com/vaadin/terminal/gwt/client/ui/absolutelayout/AbsoluteLayoutConnector.java @@ -109,7 +109,7 @@ public class AbsoluteLayoutConnector extends // TODO Margin handling - for (ComponentConnector child : getChildren()) { + for (ComponentConnector child : getChildComponents()) { getWrapper(child).setPosition( getState().getConnectorPosition(child)); } @@ -133,7 +133,7 @@ public class AbsoluteLayoutConnector extends public void onConnectorHierarchyChange(ConnectorHierarchyChangeEvent event) { super.onConnectorHierarchyChange(event); - for (ComponentConnector child : getChildren()) { + for (ComponentConnector child : getChildComponents()) { getWrapper(child); } @@ -149,7 +149,7 @@ public class AbsoluteLayoutConnector extends public void layoutVertically() { VAbsoluteLayout layout = getWidget(); - for (ComponentConnector paintable : getChildren()) { + for (ComponentConnector paintable : getChildComponents()) { Widget widget = paintable.getWidget(); AbsoluteWrapper wrapper = (AbsoluteWrapper) widget.getParent(); Style wrapperStyle = wrapper.getElement().getStyle(); @@ -181,7 +181,7 @@ public class AbsoluteLayoutConnector extends public void layoutHorizontally() { VAbsoluteLayout layout = getWidget(); - for (ComponentConnector paintable : getChildren()) { + for (ComponentConnector paintable : getChildComponents()) { AbsoluteWrapper wrapper = getWrapper(paintable); Style wrapperStyle = wrapper.getElement().getStyle(); diff --git a/src/com/vaadin/terminal/gwt/client/ui/csslayout/CssLayoutConnector.java b/src/com/vaadin/terminal/gwt/client/ui/csslayout/CssLayoutConnector.java index 71d670fe9d..4d341bddfc 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/csslayout/CssLayoutConnector.java +++ b/src/com/vaadin/terminal/gwt/client/ui/csslayout/CssLayoutConnector.java @@ -64,7 +64,7 @@ public class CssLayoutConnector extends AbstractLayoutConnector { getWidget().setMarginStyles( new VMarginInfo(getState().getMarginsBitmask())); - for (ComponentConnector child : getChildren()) { + for (ComponentConnector child : getChildComponents()) { if (!getState().getChildCss().containsKey(child)) { continue; } @@ -92,7 +92,7 @@ public class CssLayoutConnector extends AbstractLayoutConnector { int index = 0; FlowPane cssLayoutWidgetContainer = getWidget().panel; - for (ComponentConnector child : getChildren()) { + for (ComponentConnector child : getChildComponents()) { VCaption childCaption = childToCaption.get(child); if (childCaption != null) { cssLayoutWidgetContainer.addOrMove(childCaption, index++); diff --git a/src/com/vaadin/terminal/gwt/client/ui/customcomponent/CustomComponentConnector.java b/src/com/vaadin/terminal/gwt/client/ui/customcomponent/CustomComponentConnector.java index 981818fc69..5001711d6c 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/customcomponent/CustomComponentConnector.java +++ b/src/com/vaadin/terminal/gwt/client/ui/customcomponent/CustomComponentConnector.java @@ -28,8 +28,8 @@ public class CustomComponentConnector extends super.onConnectorHierarchyChange(event); ComponentConnector newChild = null; - if (getChildren().size() == 1) { - newChild = getChildren().get(0); + if (getChildComponents().size() == 1) { + newChild = getChildComponents().get(0); } VCustomComponent customComponent = getWidget(); diff --git a/src/com/vaadin/terminal/gwt/client/ui/customlayout/CustomLayoutConnector.java b/src/com/vaadin/terminal/gwt/client/ui/customlayout/CustomLayoutConnector.java index ca24cfc91a..f8861caf92 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/customlayout/CustomLayoutConnector.java +++ b/src/com/vaadin/terminal/gwt/client/ui/customlayout/CustomLayoutConnector.java @@ -75,7 +75,7 @@ public class CustomLayoutConnector extends AbstractLayoutConnector implements updateHtmlTemplate(); // For all contained widgets - for (ComponentConnector child : getChildren()) { + for (ComponentConnector child : getChildComponents()) { String location = getState().getChildLocations().get(child); try { getWidget().setWidget(child.getWidget(), location); diff --git a/src/com/vaadin/terminal/gwt/client/ui/formlayout/FormLayoutConnector.java b/src/com/vaadin/terminal/gwt/client/ui/formlayout/FormLayoutConnector.java index cdac73a771..ca21947a6c 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/formlayout/FormLayoutConnector.java +++ b/src/com/vaadin/terminal/gwt/client/ui/formlayout/FormLayoutConnector.java @@ -46,9 +46,9 @@ public class FormLayoutConnector extends AbstractLayoutConnector { int childId = 0; - formLayoutTable.setRowCount(getChildren().size()); + formLayoutTable.setRowCount(getChildComponents().size()); - for (ComponentConnector child : getChildren()) { + for (ComponentConnector child : getChildComponents()) { Widget childWidget = child.getWidget(); Caption caption = formLayoutTable.getCaption(childWidget); diff --git a/src/com/vaadin/terminal/gwt/client/ui/gridlayout/GridLayoutConnector.java b/src/com/vaadin/terminal/gwt/client/ui/gridlayout/GridLayoutConnector.java index 50afbc5913..2cd82313c2 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/gridlayout/GridLayoutConnector.java +++ b/src/com/vaadin/terminal/gwt/client/ui/gridlayout/GridLayoutConnector.java @@ -63,7 +63,7 @@ public class GridLayoutConnector extends AbstractComponentContainerConnector layout.spacingMeasureElement); // Unregister caption size dependencies - for (ComponentConnector child : getChildren()) { + for (ComponentConnector child : getChildComponents()) { Cell cell = layout.widgetToCell.get(child.getWidget()); cell.slot.setCaption(null); } @@ -155,7 +155,7 @@ public class GridLayoutConnector extends AbstractComponentContainerConnector if (needCaptionUpdate) { needCaptionUpdate = false; - for (ComponentConnector child : getChildren()) { + for (ComponentConnector child : getChildComponents()) { updateCaption(child); } } diff --git a/src/com/vaadin/terminal/gwt/client/ui/helloworldfeature/GreetAgainRpc.java b/src/com/vaadin/terminal/gwt/client/ui/helloworldfeature/GreetAgainRpc.java new file mode 100644 index 0000000000..0bfb8f3c32 --- /dev/null +++ b/src/com/vaadin/terminal/gwt/client/ui/helloworldfeature/GreetAgainRpc.java @@ -0,0 +1,12 @@ +/* +@VaadinApache2LicenseForJavaFiles@ + */ +package com.vaadin.terminal.gwt.client.ui.helloworldfeature; + +import com.vaadin.terminal.gwt.client.communication.ClientRpc; + +public interface GreetAgainRpc extends ClientRpc { + + public void greetAgain(); + +} diff --git a/src/com/vaadin/terminal/gwt/client/ui/helloworldfeature/HelloWorldExtensionConnector.java b/src/com/vaadin/terminal/gwt/client/ui/helloworldfeature/HelloWorldExtensionConnector.java new file mode 100644 index 0000000000..ff444fece5 --- /dev/null +++ b/src/com/vaadin/terminal/gwt/client/ui/helloworldfeature/HelloWorldExtensionConnector.java @@ -0,0 +1,48 @@ +/* +@VaadinApache2LicenseForJavaFiles@ + */ +package com.vaadin.terminal.gwt.client.ui.helloworldfeature; + +import com.google.gwt.user.client.Window; +import com.vaadin.terminal.gwt.client.ServerConnector; +import com.vaadin.terminal.gwt.client.Util; +import com.vaadin.terminal.gwt.client.VConsole; +import com.vaadin.terminal.gwt.client.communication.RpcProxy; +import com.vaadin.terminal.gwt.client.ui.AbstractConnector; +import com.vaadin.terminal.gwt.client.ui.Connect; +import com.vaadin.ui.HelloWorldExtension; + +@Connect(HelloWorldExtension.class) +public class HelloWorldExtensionConnector extends AbstractConnector { + HelloWorldRpc rpc = RpcProxy.create(HelloWorldRpc.class, this); + + @Override + public HelloWorldState getState() { + return (HelloWorldState) super.getState(); + } + + @Override + protected void init() { + registerRpc(GreetAgainRpc.class, new GreetAgainRpc() { + public void greetAgain() { + greet(); + } + }); + } + + @Override + public void setParent(ServerConnector parent) { + super.setParent(parent); + greet(); + } + + private void greet() { + String msg = getState().getGreeting() + " from " + + Util.getConnectorString(this) + " attached to " + + Util.getConnectorString(getParent()); + VConsole.log(msg); + + String response = Window.prompt(msg, ""); + rpc.onMessageSent(response); + } +} diff --git a/src/com/vaadin/terminal/gwt/client/ui/helloworldfeature/HelloWorldRpc.java b/src/com/vaadin/terminal/gwt/client/ui/helloworldfeature/HelloWorldRpc.java new file mode 100644 index 0000000000..0289713390 --- /dev/null +++ b/src/com/vaadin/terminal/gwt/client/ui/helloworldfeature/HelloWorldRpc.java @@ -0,0 +1,10 @@ +/* +@VaadinApache2LicenseForJavaFiles@ + */ +package com.vaadin.terminal.gwt.client.ui.helloworldfeature; + +import com.vaadin.terminal.gwt.client.communication.ServerRpc; + +public interface HelloWorldRpc extends ServerRpc { + public void onMessageSent(String message); +} diff --git a/src/com/vaadin/terminal/gwt/client/ui/helloworldfeature/HelloWorldState.java b/src/com/vaadin/terminal/gwt/client/ui/helloworldfeature/HelloWorldState.java new file mode 100644 index 0000000000..9524a5e9aa --- /dev/null +++ b/src/com/vaadin/terminal/gwt/client/ui/helloworldfeature/HelloWorldState.java @@ -0,0 +1,18 @@ +/* +@VaadinApache2LicenseForJavaFiles@ + */ +package com.vaadin.terminal.gwt.client.ui.helloworldfeature; + +import com.vaadin.terminal.gwt.client.communication.SharedState; + +public class HelloWorldState extends SharedState { + private String greeting = "Hello world"; + + public String getGreeting() { + return greeting; + } + + public void setGreeting(String greeting) { + this.greeting = greeting; + } +} diff --git a/src/com/vaadin/terminal/gwt/client/ui/layout/LayoutDependencyTree.java b/src/com/vaadin/terminal/gwt/client/ui/layout/LayoutDependencyTree.java index 1ca8933ff2..18843057f3 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/layout/LayoutDependencyTree.java +++ b/src/com/vaadin/terminal/gwt/client/ui/layout/LayoutDependencyTree.java @@ -13,6 +13,7 @@ import java.util.Set; import com.vaadin.terminal.gwt.client.ComponentConnector; import com.vaadin.terminal.gwt.client.ComponentContainerConnector; import com.vaadin.terminal.gwt.client.ComponentState; +import com.vaadin.terminal.gwt.client.ServerConnector; import com.vaadin.terminal.gwt.client.Util; import com.vaadin.terminal.gwt.client.VConsole; import com.vaadin.terminal.gwt.client.ui.ManagedLayout; @@ -154,9 +155,9 @@ public class LayoutDependencyTree { needsSize.add(connector); } if (!isRelativeInDirection(connector, direction)) { - ComponentConnector parent = connector.getParent(); - if (parent != null) { - needsSize.add(parent); + ServerConnector parent = connector.getParent(); + if (parent instanceof ComponentConnector) { + needsSize.add((ComponentConnector) parent); } } @@ -193,7 +194,7 @@ public class LayoutDependencyTree { if (connector instanceof ComponentContainerConnector) { ComponentContainerConnector container = (ComponentContainerConnector) connector; - for (ComponentConnector child : container.getChildren()) { + for (ComponentConnector child : container.getChildComponents()) { if (isRelativeInDirection(child, direction)) { resized.add(child); } @@ -246,16 +247,15 @@ public class LayoutDependencyTree { private LayoutDependency findPotentiallyChangedScrollbar() { ComponentConnector currentConnector = connector; while (true) { - ComponentContainerConnector parent = currentConnector - .getParent(); - if (parent == null) { + ServerConnector parent = currentConnector.getParent(); + if (!(parent instanceof ComponentConnector)) { return null; } if (parent instanceof MayScrollChildren) { return getDependency(currentConnector, getOppositeDirection()); } - currentConnector = parent; + currentConnector = (ComponentConnector) parent; } } @@ -504,12 +504,11 @@ public class LayoutDependencyTree { public ComponentConnector getScrollingBoundary(ComponentConnector connector) { LayoutDependency dependency = getDependency(connector, HORIZONTAL); if (!dependency.scrollingParentCached) { - ComponentContainerConnector parent = dependency.connector - .getParent(); + ServerConnector parent = dependency.connector.getParent(); if (parent instanceof MayScrollChildren) { dependency.scrollingBoundary = connector; - } else if (parent != null) { - dependency.scrollingBoundary = getScrollingBoundary(parent); + } else if (parent instanceof ComponentConnector) { + dependency.scrollingBoundary = getScrollingBoundary((ComponentConnector) parent); } else { // No scrolling parent } diff --git a/src/com/vaadin/terminal/gwt/client/ui/orderedlayout/AbstractOrderedLayoutConnector.java b/src/com/vaadin/terminal/gwt/client/ui/orderedlayout/AbstractOrderedLayoutConnector.java index d15766db21..9a89553fd2 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/orderedlayout/AbstractOrderedLayoutConnector.java +++ b/src/com/vaadin/terminal/gwt/client/ui/orderedlayout/AbstractOrderedLayoutConnector.java @@ -61,7 +61,7 @@ public abstract class AbstractOrderedLayoutConnector extends lm.unregisterDependency(this, layout.spacingMeasureElement); // Unregister child caption listeners - for (ComponentConnector child : getChildren()) { + for (ComponentConnector child : getChildComponents()) { VLayoutSlot slot = layout.getSlotForChild(child.getWidget()); slot.setCaption(null); } @@ -105,7 +105,7 @@ public abstract class AbstractOrderedLayoutConnector extends VMeasuringOrderedLayout layout = getWidget(); - for (ComponentConnector child : getChildren()) { + for (ComponentConnector child : getChildComponents()) { VLayoutSlot slot = layout.getSlotForChild(child.getWidget()); AlignmentInfo alignment = new AlignmentInfo(getState() @@ -285,7 +285,7 @@ public abstract class AbstractOrderedLayoutConnector extends int currentIndex = 0; VMeasuringOrderedLayout layout = getWidget(); - for (ComponentConnector child : getChildren()) { + for (ComponentConnector child : getChildComponents()) { Widget childWidget = child.getWidget(); VLayoutSlot slot = layout.getSlotForChild(childWidget); diff --git a/src/com/vaadin/terminal/gwt/client/ui/panel/PanelConnector.java b/src/com/vaadin/terminal/gwt/client/ui/panel/PanelConnector.java index 35a0ede390..5b97fc110f 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/panel/PanelConnector.java +++ b/src/com/vaadin/terminal/gwt/client/ui/panel/PanelConnector.java @@ -226,8 +226,8 @@ public class PanelConnector extends AbstractComponentContainerConnector super.onConnectorHierarchyChange(event); // We always have 1 child, unless the child is hidden Widget newChildWidget = null; - if (getChildren().size() == 1) { - ComponentConnector newChild = getChildren().get(0); + if (getChildComponents().size() == 1) { + ComponentConnector newChild = getChildComponents().get(0); newChildWidget = newChild.getWidget(); } diff --git a/src/com/vaadin/terminal/gwt/client/ui/root/RootConnector.java b/src/com/vaadin/terminal/gwt/client/ui/root/RootConnector.java index e02bcc9330..9be41a9623 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/root/RootConnector.java +++ b/src/com/vaadin/terminal/gwt/client/ui/root/RootConnector.java @@ -329,7 +329,7 @@ public class RootConnector extends AbstractComponentContainerConnector */ @Deprecated public boolean hasSubWindow(WindowConnector wc) { - return getChildren().contains(wc); + return getChildComponents().contains(wc); } /** @@ -340,7 +340,7 @@ public class RootConnector extends AbstractComponentContainerConnector */ public List getSubWindows() { ArrayList windows = new ArrayList(); - for (ComponentConnector child : getChildren()) { + for (ComponentConnector child : getChildComponents()) { if (child instanceof WindowConnector) { windows.add((WindowConnector) child); } @@ -380,7 +380,7 @@ public class RootConnector extends AbstractComponentContainerConnector onChildSizeChange(); } - for (ComponentConnector c : getChildren()) { + for (ComponentConnector c : getChildComponents()) { if (c instanceof WindowConnector) { WindowConnector wc = (WindowConnector) c; wc.setWindowOrderAndPosition(); diff --git a/src/com/vaadin/terminal/gwt/client/ui/splitpanel/AbstractSplitPanelConnector.java b/src/com/vaadin/terminal/gwt/client/ui/splitpanel/AbstractSplitPanelConnector.java index a2f1f26c15..10e5dbe37a 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/splitpanel/AbstractSplitPanelConnector.java +++ b/src/com/vaadin/terminal/gwt/client/ui/splitpanel/AbstractSplitPanelConnector.java @@ -143,7 +143,7 @@ public abstract class AbstractSplitPanelConnector extends splitPanel.setSplitPosition(splitPanel.position); splitPanel.updateSizes(); // Report relative sizes in other direction for quicker propagation - List children = getChildren(); + List children = getChildComponents(); for (ComponentConnector child : children) { reportOtherDimension(child); } diff --git a/src/com/vaadin/terminal/gwt/client/ui/table/TableConnector.java b/src/com/vaadin/terminal/gwt/client/ui/table/TableConnector.java index 73bc5da83f..ada0f2424f 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/table/TableConnector.java +++ b/src/com/vaadin/terminal/gwt/client/ui/table/TableConnector.java @@ -16,6 +16,7 @@ import com.vaadin.terminal.gwt.client.BrowserInfo; import com.vaadin.terminal.gwt.client.ComponentConnector; import com.vaadin.terminal.gwt.client.DirectionalManagedLayout; import com.vaadin.terminal.gwt.client.Paintable; +import com.vaadin.terminal.gwt.client.ServerConnector; import com.vaadin.terminal.gwt.client.UIDL; import com.vaadin.terminal.gwt.client.Util; import com.vaadin.terminal.gwt.client.ui.AbstractComponentContainerConnector; @@ -283,8 +284,11 @@ public class TableConnector extends AbstractComponentContainerConnector Scheduler.get().scheduleFinally(new ScheduledCommand() { public void execute() { getLayoutManager().setNeedsMeasure(TableConnector.this); - getLayoutManager().setNeedsMeasure( - TableConnector.this.getParent()); + ServerConnector parent = getParent(); + if (parent instanceof ComponentConnector) { + getLayoutManager().setNeedsMeasure( + (ComponentConnector) parent); + } getLayoutManager().setNeedsVerticalLayout( TableConnector.this); getLayoutManager().layoutNow(); diff --git a/src/com/vaadin/terminal/gwt/client/ui/window/WindowConnector.java b/src/com/vaadin/terminal/gwt/client/ui/window/WindowConnector.java index 3a37baafbb..83de039f0b 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/window/WindowConnector.java +++ b/src/com/vaadin/terminal/gwt/client/ui/window/WindowConnector.java @@ -201,8 +201,8 @@ public class WindowConnector extends AbstractComponentContainerConnector // We always have 1 child, unless the child is hidden Widget newChildWidget = null; ComponentConnector newChild = null; - if (getChildren().size() == 1) { - newChild = getChildren().get(0); + if (getChildComponents().size() == 1) { + newChild = getChildComponents().get(0); newChildWidget = newChild.getWidget(); } diff --git a/src/com/vaadin/terminal/gwt/server/AbstractApplicationPortlet.java b/src/com/vaadin/terminal/gwt/server/AbstractApplicationPortlet.java index 5b2be308a3..1acc9d128a 100644 --- a/src/com/vaadin/terminal/gwt/server/AbstractApplicationPortlet.java +++ b/src/com/vaadin/terminal/gwt/server/AbstractApplicationPortlet.java @@ -67,7 +67,7 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet private static final Logger logger = Logger .getLogger(AbstractApplicationPortlet.class.getName()); - public static class WrappedHttpAndPortletRequest extends + private static class WrappedHttpAndPortletRequest extends WrappedPortletRequest { public WrappedHttpAndPortletRequest(PortletRequest request, @@ -112,7 +112,7 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet } } - public static class WrappedGateinRequest extends + private static class WrappedGateinRequest extends WrappedHttpAndPortletRequest { public WrappedGateinRequest(PortletRequest request, DeploymentConfiguration deploymentConfiguration) { @@ -134,7 +134,7 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet } } - public static class WrappedLiferayRequest extends + private static class WrappedLiferayRequest extends WrappedHttpAndPortletRequest { public WrappedLiferayRequest(PortletRequest request, @@ -169,7 +169,7 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet } - public static class AbstractApplicationPortletWrapper implements Callback { + private static class AbstractApplicationPortletWrapper implements Callback { private final AbstractApplicationPortlet portlet; @@ -500,7 +500,20 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet AbstractApplicationPortletWrapper portletWrapper = new AbstractApplicationPortletWrapper( this); - WrappedPortletRequest wrappedRequest = createWrappedRequest(request); + WrappedPortletRequest wrappedRequest; + + String portalInfo = request.getPortalContext().getPortalInfo() + .toLowerCase(); + if (portalInfo.contains("liferay")) { + wrappedRequest = new WrappedLiferayRequest(request, + getDeploymentConfiguration()); + } else if (portalInfo.contains("gatein")) { + wrappedRequest = new WrappedGateinRequest(request, + getDeploymentConfiguration()); + } else { + wrappedRequest = new WrappedPortletRequest(request, + getDeploymentConfiguration()); + } WrappedPortletResponse wrappedResponse = new WrappedPortletResponse( response, getDeploymentConfiguration()); @@ -699,30 +712,6 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet } } - /** - * Wraps the request in a (possibly portal specific) wrapped portlet - * request. - * - * @param request - * The original PortletRequest - * @return A wrapped version of the PorletRequest - */ - protected WrappedPortletRequest createWrappedRequest(PortletRequest request) { - String portalInfo = request.getPortalContext().getPortalInfo() - .toLowerCase(); - if (portalInfo.contains("liferay")) { - return new WrappedLiferayRequest(request, - getDeploymentConfiguration()); - } else if (portalInfo.contains("gatein")) { - return new WrappedGateinRequest(request, - getDeploymentConfiguration()); - } else { - return new WrappedPortletRequest(request, - getDeploymentConfiguration()); - } - - } - private DeploymentConfiguration getDeploymentConfiguration() { return deploymentConfiguration; } diff --git a/src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java b/src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java index c08d70aa37..186126c9c6 100644 --- a/src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java +++ b/src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java @@ -49,6 +49,7 @@ import com.vaadin.Version; import com.vaadin.external.json.JSONArray; import com.vaadin.external.json.JSONException; import com.vaadin.external.json.JSONObject; +import com.vaadin.terminal.AbstractClientConnector; import com.vaadin.terminal.CombinedRequest; import com.vaadin.terminal.LegacyPaint; import com.vaadin.terminal.PaintException; @@ -74,7 +75,6 @@ import com.vaadin.ui.AbstractField; import com.vaadin.ui.Component; import com.vaadin.ui.DirtyConnectorTracker; import com.vaadin.ui.HasComponents; -import com.vaadin.ui.Panel; import com.vaadin.ui.Root; import com.vaadin.ui.Window; @@ -769,7 +769,7 @@ public abstract class AbstractCommunicationManager implements Serializable { logger.log(Level.FINE, "* Creating response to client"); if (repaintAll) { getClientCache(root).clear(); - rootConnectorTracker.markAllComponentsDirty(); + rootConnectorTracker.markAllConnectorsDirty(); // Reset sent locales locales = null; @@ -777,7 +777,7 @@ public abstract class AbstractCommunicationManager implements Serializable { } dirtyVisibleConnectors - .addAll(getDirtyVisibleComponents(rootConnectorTracker)); + .addAll(getDirtyVisibleConnectors(rootConnectorTracker)); logger.log(Level.FINE, "Found " + dirtyVisibleConnectors.size() + " dirty connectors to paint"); @@ -786,7 +786,7 @@ public abstract class AbstractCommunicationManager implements Serializable { ((Component) connector).updateState(); } } - rootConnectorTracker.markAllComponentsClean(); + rootConnectorTracker.markAllConnectorsClean(); outWriter.print("\"changes\":["); @@ -893,26 +893,24 @@ public abstract class AbstractCommunicationManager implements Serializable { outWriter.print("\"hierarchy\":"); JSONObject hierarchyInfo = new JSONObject(); - for (Connector connector : dirtyVisibleConnectors) { - if (connector instanceof HasComponents) { - HasComponents parent = (HasComponents) connector; - String parentConnectorId = parent.getConnectorId(); - JSONArray children = new JSONArray(); - - for (Component child : getChildComponents(parent)) { - if (isVisible(child)) { - children.put(child.getConnectorId()); - } - } - try { - hierarchyInfo.put(parentConnectorId, children); - } catch (JSONException e) { - throw new PaintException( - "Failed to send hierarchy information about " - + parentConnectorId + " to the client: " - + e.getMessage(), e); + for (ClientConnector connector : dirtyVisibleConnectors) { + String connectorId = connector.getConnectorId(); + JSONArray children = new JSONArray(); + + for (ClientConnector child : AbstractClientConnector + .getAllChildrenIteratable(connector)) { + if (isVisible(child)) { + children.put(child.getConnectorId()); } } + try { + hierarchyInfo.put(connectorId, children); + } catch (JSONException e) { + throw new PaintException( + "Failed to send hierarchy information about " + + connectorId + " to the client: " + + e.getMessage(), e); + } } outWriter.append(hierarchyInfo.toString()); outWriter.print(", "); // close hierarchy @@ -1222,6 +1220,30 @@ public abstract class AbstractCommunicationManager implements Serializable { return cache; } + /** + * Checks if the connector is visible in context. For Components, + * {@link #isVisible(Component)} is used. For other types of connectors, the + * contextual visibility of its first Component ancestor is used. If no + * Component ancestor is found, the connector is not visible. + * + * @param connector + * The connector to check + * @return true if the connector is visible to the client, + * false otherwise + */ + static boolean isVisible(ClientConnector connector) { + if (connector instanceof Component) { + return isVisible((Component) connector); + } else { + ClientConnector parent = connector.getParent(); + if (parent == null) { + return false; + } else { + return isVisible(parent); + } + } + } + /** * Checks if the component is visible in context, i.e. returns false if the * child is hidden, the parent is hidden or the parent says the child should @@ -1256,30 +1278,6 @@ public abstract class AbstractCommunicationManager implements Serializable { } - public static Iterable getChildComponents(HasComponents cc) { - // TODO This must be moved to Root/Panel - if (cc instanceof Root) { - Root root = (Root) cc; - List children = new ArrayList(); - if (root.getContent() != null) { - children.add(root.getContent()); - } - for (Window w : root.getWindows()) { - children.add(w); - } - return children; - } else if (cc instanceof Panel) { - // This is so wrong.. (#2924) - if (((Panel) cc).getContent() == null) { - return Collections.emptyList(); - } else { - return Collections.singleton((Component) ((Panel) cc) - .getContent()); - } - } - return cc; - } - /** * Collects all pending RPC calls from listed {@link ClientConnector}s and * clears their RPC queues. @@ -2016,16 +2014,16 @@ public abstract class AbstractCommunicationManager implements Serializable { * root window for which dirty components is to be fetched * @return */ - private ArrayList getDirtyVisibleComponents( + private ArrayList getDirtyVisibleConnectors( DirtyConnectorTracker dirtyConnectorTracker) { - ArrayList dirtyComponents = new ArrayList(); - for (Component c : dirtyConnectorTracker.getDirtyComponents()) { + ArrayList dirtyConnectors = new ArrayList(); + for (ClientConnector c : dirtyConnectorTracker.getDirtyConnectors()) { if (isVisible(c)) { - dirtyComponents.add(c); + dirtyConnectors.add(c); } } - return dirtyComponents; + return dirtyConnectors; } /** diff --git a/src/com/vaadin/terminal/gwt/server/ClientConnector.java b/src/com/vaadin/terminal/gwt/server/ClientConnector.java index 7e74c26fb1..6830aa8e14 100644 --- a/src/com/vaadin/terminal/gwt/server/ClientConnector.java +++ b/src/com/vaadin/terminal/gwt/server/ClientConnector.java @@ -3,10 +3,16 @@ */ package com.vaadin.terminal.gwt.server; +import java.util.Iterator; import java.util.List; +import com.vaadin.terminal.AbstractClientConnector; +import com.vaadin.terminal.Extension; import com.vaadin.terminal.gwt.client.Connector; import com.vaadin.terminal.gwt.client.communication.SharedState; +import com.vaadin.ui.Component; +import com.vaadin.ui.ComponentContainer; +import com.vaadin.ui.Root; /** * Interface implemented by all connectors that are capable of communicating @@ -44,4 +50,94 @@ public interface ClientConnector extends Connector, RpcTarget { */ public Class getStateType(); + public ClientConnector getParent(); + + /** + * Requests that the connector should be repainted as soon as possible. + */ + public void requestRepaint(); + + /** + * Causes a repaint of this connector, and all connectors below it. + * + * This should only be used in special cases, e.g when the state of a + * descendant depends on the state of a ancestor. + */ + public void requestRepaintAll(); + + /** + * Sets the parent connector of the connector. + * + *

      + * This method automatically calls {@link #attach()} if the parent becomes + * attached to the application, regardless of whether it was attached + * previously. Conversely, if the parent is {@code null} and the connector + * is attached to the application, {@link #detach()} is called for the + * connector. + *

      + *

      + * This method is rarely called directly. One of the + * {@link ComponentContainer#addComponent(Component)} or + * {@link AbstractClientConnector#addFeature(Feature)} methods is normally + * used for adding connectors to a container and it will call this method + * implicitly. + *

      + * + *

      + * It is not possible to change the parent without first setting the parent + * to {@code null}. + *

      + * + * @param parent + * the parent connector + * @throws IllegalStateException + * if a parent is given even though the connector already has a + * parent + */ + public void setParent(ClientConnector parent); + + /** + * Notifies the connector that it is connected to an application. + * + *

      + * The caller of this method is {@link #setParent(ClientConnector)} if the + * parent is itself already attached to the application. If not, the parent + * will call the {@link #attach()} for all its children when it is attached + * to the application. This method is always called before the connector is + * painted for the first time. + *

      + * + *

      + * The attachment logic is implemented in {@link AbstractClientConnector}. + *

      + * + * @see #getApplication() + */ + public void attach(); + + /** + * Notifies the component that it is detached from the application. + * + *

      + * The {@link #getApplication()} and {@link #getRoot()} methods might return + * null after this method is called. + *

      + * + *

      + * This method must call {@link Root#componentDetached(Component)} to let + * the Root know that a new Component has been attached. + *

      + * * + *

      + * The caller of this method is {@link #setParent(Component)} if the parent + * is in the application. When the parent is detached from the application + * it is its response to call {@link #detach()} for all the children and to + * detach itself from the terminal. + *

      + */ + public void detach(); + + public Iterator getExtensionIterator(); + + public void removeExtension(Extension feature); } diff --git a/src/com/vaadin/terminal/gwt/server/DragAndDropService.java b/src/com/vaadin/terminal/gwt/server/DragAndDropService.java index f6c96557ea..e2358bcbb9 100644 --- a/src/com/vaadin/terminal/gwt/server/DragAndDropService.java +++ b/src/com/vaadin/terminal/gwt/server/DragAndDropService.java @@ -4,6 +4,7 @@ package com.vaadin.terminal.gwt.server; import java.io.PrintWriter; +import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.logging.Logger; @@ -17,6 +18,7 @@ import com.vaadin.event.dd.DropTarget; import com.vaadin.event.dd.TargetDetails; import com.vaadin.event.dd.TargetDetailsImpl; import com.vaadin.event.dd.acceptcriteria.AcceptCriterion; +import com.vaadin.terminal.Extension; import com.vaadin.terminal.PaintException; import com.vaadin.terminal.VariableOwner; import com.vaadin.terminal.gwt.client.communication.SharedState; @@ -242,4 +244,44 @@ public class DragAndDropService implements VariableOwner, ClientConnector { public Class getStateType() { return SharedState.class; } + + public void requestRepaint() { + // TODO Auto-generated method stub + + } + + public ClientConnector getParent() { + // TODO Auto-generated method stub + return null; + } + + public void requestRepaintAll() { + // TODO Auto-generated method stub + + } + + public void setParent(ClientConnector parent) { + // TODO Auto-generated method stub + + } + + public void attach() { + // TODO Auto-generated method stub + + } + + public void detach() { + // TODO Auto-generated method stub + + } + + public Iterator getExtensionIterator() { + // TODO Auto-generated method stub + return null; + } + + public void removeExtension(Extension feature) { + // TODO Auto-generated method stub + + } } diff --git a/src/com/vaadin/terminal/gwt/server/JsonPaintTarget.java b/src/com/vaadin/terminal/gwt/server/JsonPaintTarget.java index def334290e..1cde164618 100644 --- a/src/com/vaadin/terminal/gwt/server/JsonPaintTarget.java +++ b/src/com/vaadin/terminal/gwt/server/JsonPaintTarget.java @@ -26,6 +26,7 @@ import com.vaadin.terminal.ThemeResource; import com.vaadin.terminal.VariableOwner; import com.vaadin.terminal.gwt.client.Connector; import com.vaadin.ui.Alignment; +import com.vaadin.ui.Component; import com.vaadin.ui.CustomLayout; /** @@ -399,7 +400,7 @@ public class JsonPaintTarget implements PaintTarget { } - public void addAttribute(String name, ClientConnector value) + public void addAttribute(String name, Component value) throws PaintException { final String id = value.getConnectorId(); addAttribute(name, id); @@ -468,7 +469,7 @@ public class JsonPaintTarget implements PaintTarget { } public void addVariable(VariableOwner owner, String name, - ClientConnector value) throws PaintException { + Component value) throws PaintException { tag.addVariable(new StringVariable(owner, name, value.getConnectorId())); } @@ -645,7 +646,7 @@ public class JsonPaintTarget implements PaintTarget { * @see com.vaadin.terminal.PaintTarget#startPaintable(com.vaadin.terminal * .Paintable, java.lang.String) */ - public PaintStatus startPaintable(ClientConnector connector, String tagName) + public PaintStatus startPaintable(Component connector, String tagName) throws PaintException { boolean topLevelPaintable = openPaintables.isEmpty(); @@ -670,7 +671,7 @@ public class JsonPaintTarget implements PaintTarget { return PaintStatus.PAINTING; } - public void endPaintable(ClientConnector paintable) throws PaintException { + public void endPaintable(Component paintable) throws PaintException { logger.fine("endPaintable for " + paintable.getClass().getName() + "@" + Integer.toHexString(paintable.hashCode())); diff --git a/src/com/vaadin/terminal/gwt/widgetsetutils/CustomWidgetMapGenerator.java b/src/com/vaadin/terminal/gwt/widgetsetutils/CustomWidgetMapGenerator.java index f0d6f0453b..f0f3df20b0 100644 --- a/src/com/vaadin/terminal/gwt/widgetsetutils/CustomWidgetMapGenerator.java +++ b/src/com/vaadin/terminal/gwt/widgetsetutils/CustomWidgetMapGenerator.java @@ -7,6 +7,7 @@ import java.util.Collection; import java.util.HashSet; import com.vaadin.terminal.gwt.client.ComponentConnector; +import com.vaadin.terminal.gwt.client.ServerConnector; import com.vaadin.terminal.gwt.client.ui.Connect; import com.vaadin.terminal.gwt.client.ui.Connect.LoadStyle; @@ -25,8 +26,7 @@ public abstract class CustomWidgetMapGenerator extends WidgetMapGenerator { private Collection> deferredPaintables = new HashSet>(); @Override - protected LoadStyle getLoadStyle( - Class connector) { + protected LoadStyle getLoadStyle(Class connector) { if (eagerPaintables == null) { init(); } diff --git a/src/com/vaadin/terminal/gwt/widgetsetutils/EagerWidgetMapGenerator.java b/src/com/vaadin/terminal/gwt/widgetsetutils/EagerWidgetMapGenerator.java index 8a1dfee3b5..084e1c3857 100644 --- a/src/com/vaadin/terminal/gwt/widgetsetutils/EagerWidgetMapGenerator.java +++ b/src/com/vaadin/terminal/gwt/widgetsetutils/EagerWidgetMapGenerator.java @@ -3,7 +3,7 @@ */ package com.vaadin.terminal.gwt.widgetsetutils; -import com.vaadin.terminal.gwt.client.ComponentConnector; +import com.vaadin.terminal.gwt.client.ServerConnector; import com.vaadin.terminal.gwt.client.ui.Connect.LoadStyle; /** @@ -23,8 +23,7 @@ import com.vaadin.terminal.gwt.client.ui.Connect.LoadStyle; public class EagerWidgetMapGenerator extends WidgetMapGenerator { @Override - protected LoadStyle getLoadStyle( - Class connector) { + protected LoadStyle getLoadStyle(Class connector) { return LoadStyle.EAGER; } } diff --git a/src/com/vaadin/terminal/gwt/widgetsetutils/LazyWidgetMapGenerator.java b/src/com/vaadin/terminal/gwt/widgetsetutils/LazyWidgetMapGenerator.java index 729a999a21..f8366beb46 100644 --- a/src/com/vaadin/terminal/gwt/widgetsetutils/LazyWidgetMapGenerator.java +++ b/src/com/vaadin/terminal/gwt/widgetsetutils/LazyWidgetMapGenerator.java @@ -3,7 +3,7 @@ */ package com.vaadin.terminal.gwt.widgetsetutils; -import com.vaadin.terminal.gwt.client.ComponentConnector; +import com.vaadin.terminal.gwt.client.ServerConnector; import com.vaadin.terminal.gwt.client.ui.Connect.LoadStyle; /** @@ -16,8 +16,7 @@ import com.vaadin.terminal.gwt.client.ui.Connect.LoadStyle; */ public class LazyWidgetMapGenerator extends WidgetMapGenerator { @Override - protected LoadStyle getLoadStyle( - Class connector) { + protected LoadStyle getLoadStyle(Class connector) { return LoadStyle.LAZY; } diff --git a/src/com/vaadin/terminal/gwt/widgetsetutils/SerializerMapGenerator.java b/src/com/vaadin/terminal/gwt/widgetsetutils/SerializerMapGenerator.java index 07efcda91b..2688775435 100644 --- a/src/com/vaadin/terminal/gwt/widgetsetutils/SerializerMapGenerator.java +++ b/src/com/vaadin/terminal/gwt/widgetsetutils/SerializerMapGenerator.java @@ -203,6 +203,7 @@ public class SerializerMapGenerator extends Generator { // Generate serializer classes for each subclass of SharedState JClassType serializerType = typeOracle.findType(SharedState.class .getName()); + types.add(serializerType); JClassType[] serializerSubtypes = serializerType.getSubtypes(); for (JClassType type : serializerSubtypes) { types.add(type); diff --git a/src/com/vaadin/terminal/gwt/widgetsetutils/WidgetMapGenerator.java b/src/com/vaadin/terminal/gwt/widgetsetutils/WidgetMapGenerator.java index 6d4289b173..b264a9c7fe 100644 --- a/src/com/vaadin/terminal/gwt/widgetsetutils/WidgetMapGenerator.java +++ b/src/com/vaadin/terminal/gwt/widgetsetutils/WidgetMapGenerator.java @@ -22,8 +22,8 @@ import com.google.gwt.core.ext.typeinfo.JClassType; import com.google.gwt.core.ext.typeinfo.TypeOracle; import com.google.gwt.user.rebind.ClassSourceFileComposerFactory; import com.google.gwt.user.rebind.SourceWriter; -import com.vaadin.terminal.gwt.client.ComponentConnector; import com.vaadin.terminal.gwt.client.Connector; +import com.vaadin.terminal.gwt.client.ServerConnector; import com.vaadin.terminal.gwt.client.ui.Connect; import com.vaadin.terminal.gwt.client.ui.Connect.LoadStyle; import com.vaadin.terminal.gwt.client.ui.UnknownComponentConnector; @@ -71,7 +71,7 @@ import com.vaadin.terminal.gwt.server.ClientConnector; */ public class WidgetMapGenerator extends Generator { - private static String componentConnectorClassName = ComponentConnector.class + private static String serverConnectorClassName = ServerConnector.class .getName(); private String packageName; @@ -115,7 +115,7 @@ public class WidgetMapGenerator extends Generator { return; } logger.log(Type.INFO, - "Detecting Vaadin components in classpath to generate WidgetMapImpl.java ..."); + "Detecting Vaadin connectors in classpath to generate WidgetMapImpl.java ..."); Date date = new Date(); // init composer, set class properties, create source writer @@ -128,7 +128,7 @@ public class WidgetMapGenerator extends Generator { SourceWriter sourceWriter = composer.createSourceWriter(context, printWriter); - Collection> connectors = getUsedConnectors(context + Collection> connectors = getUsedConnectors(context .getTypeOracle()); validateConnectors(logger, connectors); @@ -149,12 +149,11 @@ public class WidgetMapGenerator extends Generator { } private void validateConnectors(TreeLogger logger, - Collection> connectors) { + Collection> connectors) { - Iterator> iter = connectors - .iterator(); + Iterator> iter = connectors.iterator(); while (iter.hasNext()) { - Class connectorClass = iter.next(); + Class connectorClass = iter.next(); Connect annotation = connectorClass.getAnnotation(Connect.class); if (!ClientConnector.class.isAssignableFrom(annotation.value())) { logger.log( @@ -173,13 +172,13 @@ public class WidgetMapGenerator extends Generator { } private void logConnectors(TreeLogger logger, GeneratorContext context, - Collection> connectors) { + Collection> connectors) { logger.log(Type.INFO, "Widget set will contain implementations for following component connectors: "); TreeSet classNames = new TreeSet(); HashMap loadStyle = new HashMap(); - for (Class connectorClass : connectors) { + for (Class connectorClass : connectors) { String className = connectorClass.getCanonicalName(); classNames.add(className); if (getLoadStyle(connectorClass) == LoadStyle.DEFERRED) { @@ -208,16 +207,16 @@ public class WidgetMapGenerator extends Generator { * widgetset */ @SuppressWarnings("unchecked") - private Collection> getUsedConnectors( + private Collection> getUsedConnectors( TypeOracle typeOracle) { JClassType connectorType = typeOracle.findType(Connector.class .getName()); - Collection> connectors = new HashSet>(); + Collection> connectors = new HashSet>(); for (JClassType jClassType : connectorType.getSubtypes()) { Connect annotation = jClassType.getAnnotation(Connect.class); if (annotation != null) { try { - Class clazz = (Class) Class + Class clazz = (Class) Class .forName(jClassType.getQualifiedSourceName()); connectors.add(clazz); } catch (ClassNotFoundException e) { @@ -242,15 +241,14 @@ public class WidgetMapGenerator extends Generator { * @return true iff the widget for given component should be lazy loaded by * the client side engine */ - protected LoadStyle getLoadStyle( - Class connector) { + protected LoadStyle getLoadStyle(Class connector) { Connect annotation = connector.getAnnotation(Connect.class); return annotation.loadStyle(); } private void generateInstantiatorMethod( SourceWriter sourceWriter, - Collection> connectorsHavingComponentAnnotation) { + Collection> connectorsHavingComponentAnnotation) { Collection> deferredWidgets = new LinkedList>(); @@ -258,16 +256,16 @@ public class WidgetMapGenerator extends Generator { // lookup with index than with the hashmap sourceWriter.println("public void ensureInstantiator(Class classType) {"); + + serverConnectorClassName + "> classType) {"); sourceWriter.println("if(!instmap.containsKey(classType)){"); boolean first = true; - ArrayList> lazyLoadedWidgets = new ArrayList>(); + ArrayList> lazyLoadedConnectors = new ArrayList>(); - HashSet> connectorsWithInstantiator = new HashSet>(); + HashSet> connectorsWithInstantiator = new HashSet>(); - for (Class class1 : connectorsHavingComponentAnnotation) { - Class clientClass = class1; + for (Class class1 : connectorsHavingComponentAnnotation) { + Class clientClass = class1; if (connectorsWithInstantiator.contains(clientClass)) { continue; } @@ -284,7 +282,7 @@ public class WidgetMapGenerator extends Generator { + ".class) {"); String instantiator = "new WidgetInstantiator() {\n public " - + componentConnectorClassName + + serverConnectorClassName + " get() {\n return GWT.create(" + clientClass.getName() + ".class );\n}\n}\n"; @@ -298,7 +296,7 @@ public class WidgetMapGenerator extends Generator { + clientClass.getName() + ".class," + instantiator + ");}});\n"); - lazyLoadedWidgets.add(class1); + lazyLoadedConnectors.add(class1); if (loadStyle == LoadStyle.DEFERRED) { deferredWidgets.add(class1); @@ -321,8 +319,8 @@ public class WidgetMapGenerator extends Generator { sourceWriter.println("}"); sourceWriter.println("public Class[] getDeferredLoadedWidgets() {"); + + serverConnectorClassName + + ">[] getDeferredLoadedConnectors() {"); sourceWriter.println("return new Class[] {"); first = true; @@ -344,11 +342,11 @@ public class WidgetMapGenerator extends Generator { // TODO an index of last ensured widget in array - sourceWriter.println("public " + componentConnectorClassName - + " instantiate(Class classType) {"); sourceWriter.indent(); - sourceWriter.println(componentConnectorClassName + sourceWriter.println(serverConnectorClassName + " p = super.instantiate(classType); if(p!= null) return p;"); sourceWriter.println("return instmap.get(classType).get();"); @@ -365,17 +363,17 @@ public class WidgetMapGenerator extends Generator { */ private void generateImplementationDetector( SourceWriter sourceWriter, - Collection> paintablesHavingWidgetAnnotation) { + Collection> paintablesHavingWidgetAnnotation) { sourceWriter .println("public Class " + "getConnectorClassForServerSideClassName(String fullyQualifiedName) {"); sourceWriter.indent(); sourceWriter .println("fullyQualifiedName = fullyQualifiedName.intern();"); - for (Class connectorClass : paintablesHavingWidgetAnnotation) { + for (Class connectorClass : paintablesHavingWidgetAnnotation) { Class clientConnectorClass = getClientConnectorClass(connectorClass); sourceWriter.print("if ( fullyQualifiedName == \""); sourceWriter.print(clientConnectorClass.getName()); @@ -393,7 +391,7 @@ public class WidgetMapGenerator extends Generator { } private static Class getClientConnectorClass( - Class connectorClass) { + Class connectorClass) { Connect annotation = connectorClass.getAnnotation(Connect.class); return (Class) annotation.value(); } diff --git a/src/com/vaadin/ui/AbsoluteLayout.java b/src/com/vaadin/ui/AbsoluteLayout.java index 9ba005f75a..7d8c402fc9 100644 --- a/src/com/vaadin/ui/AbsoluteLayout.java +++ b/src/com/vaadin/ui/AbsoluteLayout.java @@ -161,7 +161,8 @@ public class AbsoluteLayout extends AbstractLayout implements // connectorId unless the component is attached to the application so // the String->String map cannot be populated in internal* either. Map connectorToPosition = new HashMap(); - for (Component c : this) { + for (Iterator ci = getComponentIterator(); ci.hasNext();) { + Component c = ci.next(); connectorToPosition.put(c.getConnectorId(), getPosition(c) .getCSSString()); } diff --git a/src/com/vaadin/ui/AbstractComponent.java b/src/com/vaadin/ui/AbstractComponent.java index 554d7806f9..25695e3c0c 100644 --- a/src/com/vaadin/ui/AbstractComponent.java +++ b/src/com/vaadin/ui/AbstractComponent.java @@ -5,20 +5,13 @@ package com.vaadin.ui; import java.io.Serializable; -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; -import java.lang.reflect.Proxy; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; -import java.util.HashMap; import java.util.Iterator; -import java.util.LinkedList; import java.util.List; import java.util.Locale; -import java.util.Map; -import java.util.logging.Logger; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -27,18 +20,14 @@ import com.vaadin.event.ActionManager; import com.vaadin.event.EventRouter; import com.vaadin.event.MethodEventSource; import com.vaadin.event.ShortcutListener; +import com.vaadin.terminal.AbstractClientConnector; import com.vaadin.terminal.ErrorMessage; import com.vaadin.terminal.Resource; import com.vaadin.terminal.Terminal; import com.vaadin.terminal.gwt.client.ComponentState; -import com.vaadin.terminal.gwt.client.communication.ClientRpc; -import com.vaadin.terminal.gwt.client.communication.ServerRpc; -import com.vaadin.terminal.gwt.server.ClientMethodInvocation; +import com.vaadin.terminal.gwt.server.ClientConnector; import com.vaadin.terminal.gwt.server.ComponentSizeValidator; import com.vaadin.terminal.gwt.server.ResourceReference; -import com.vaadin.terminal.gwt.server.RpcManager; -import com.vaadin.terminal.gwt.server.RpcTarget; -import com.vaadin.terminal.gwt.server.ServerRpcManager; import com.vaadin.tools.ReflectTools; /** @@ -53,7 +42,8 @@ import com.vaadin.tools.ReflectTools; * @since 3.0 */ @SuppressWarnings("serial") -public abstract class AbstractComponent implements Component, MethodEventSource { +public abstract class AbstractComponent extends AbstractClientConnector + implements Component, MethodEventSource { /* Private members */ @@ -63,11 +53,6 @@ public abstract class AbstractComponent implements Component, MethodEventSource */ private Object applicationData; - /** - * The container this component resides in. - */ - private HasComponents parent = null; - /** * The EventRouter used for the event model. */ @@ -88,11 +73,6 @@ public abstract class AbstractComponent implements Component, MethodEventSource */ private boolean delayedFocus; - /** - * List of repaint request listeners or null if not listened at all. - */ - private LinkedList repaintRequestListeners = null; - /* Sizeable fields */ private float width = SIZE_UNDEFINED; @@ -110,31 +90,6 @@ public abstract class AbstractComponent implements Component, MethodEventSource */ private ActionManager actionManager; - /** - * A map from client to server RPC interface class to the RPC call manager - * that handles incoming RPC calls for that interface. - */ - private Map, RpcManager> rpcManagerMap = new HashMap, RpcManager>(); - - /** - * A map from server to client RPC interface class to the RPC proxy that - * sends ourgoing RPC calls for that interface. - */ - private Map, ClientRpc> rpcProxyMap = new HashMap, ClientRpc>(); - - /** - * Shared state object to be communicated from the server to the client when - * modified. - */ - private ComponentState sharedState; - - /** - * Pending RPC method invocations to be sent. - */ - private ArrayList pendingInvocations = new ArrayList(); - - private String connectorId; - /* Constructor */ /** @@ -287,6 +242,7 @@ public abstract class AbstractComponent implements Component, MethodEventSource if (locale != null) { return locale; } + HasComponents parent = getParent(); if (parent != null) { return parent.getLocale(); } @@ -378,21 +334,18 @@ public abstract class AbstractComponent implements Component, MethodEventSource * * @see com.vaadin.terminal.gwt.client.Connector#isConnectorEnabled() */ + @Override public boolean isConnectorEnabled() { - if (getParent() == null) { - // No parent -> the component cannot receive updates from the client + if (!isVisible()) { + return false; + } else if (!isEnabled()) { + return false; + } else if (!super.isConnectorEnabled()) { + return false; + } else if (!getParent().isComponentVisible(this)) { return false; } else { - boolean thisEnabledAndVisible = isEnabled() && isVisible(); - if (!thisEnabledAndVisible) { - return false; - } - - if (!getParent().isConnectorEnabled()) { - return false; - } - - return getParent().isComponentVisible(this); + return true; } } @@ -529,8 +482,20 @@ public abstract class AbstractComponent implements Component, MethodEventSource * Gets the component's parent component. Don't add a JavaDoc comment here, * we use the default documentation from implemented interface. */ + @Override public HasComponents getParent() { - return parent; + return (HasComponents) super.getParent(); + } + + @Override + public void setParent(ClientConnector parent) { + if (parent == null || parent instanceof HasComponents) { + super.setParent(parent); + } else { + throw new IllegalArgumentException( + "The parent of a Component must implement HasComponents, which " + + parent.getClass() + " doesn't do."); + } } /** @@ -558,36 +523,6 @@ public abstract class AbstractComponent implements Component, MethodEventSource return null; } - /* - * Sets the parent component. Don't add a JavaDoc comment here, we use the - * default documentation from implemented interface. - */ - public void setParent(HasComponents parent) { - - // If the parent is not changed, don't do anything - if (parent == this.parent) { - return; - } - - if (parent != null && this.parent != null) { - throw new IllegalStateException(getClass().getName() - + " already has a parent."); - } - - // Send detach event if the component have been connected to a window - if (getApplication() != null) { - detach(); - } - - // Connect to new parent - this.parent = parent; - - // Send attach event if connected to a window - if (getApplication() != null) { - attach(); - } - } - /** * Gets the error message for this component. * @@ -648,12 +583,10 @@ public abstract class AbstractComponent implements Component, MethodEventSource * Gets the parent window of the component. Don't add a JavaDoc comment * here, we use the default documentation from implemented interface. */ + @Override public Root getRoot() { - if (parent == null) { - return null; - } else { - return parent.getRoot(); - } + // Just make method from implemented Component interface public + return super.getRoot(); } /* @@ -661,9 +594,9 @@ public abstract class AbstractComponent implements Component, MethodEventSource * comment here, we use the default documentation from implemented * interface. */ + @Override public void attach() { - getRoot().componentAttached(this); - requestRepaint(); + super.attach(); if (delayedFocus) { focus(); } @@ -674,13 +607,13 @@ public abstract class AbstractComponent implements Component, MethodEventSource * Detach the component from application. Don't add a JavaDoc comment here, * we use the default documentation from implemented interface. */ + @Override public void detach() { if (actionManager != null) { // Remove any existing viewer. Root cast is just to make the // compiler happy actionManager.setViewer((Root) null); } - getRoot().componentDetached(this); } /** @@ -717,12 +650,10 @@ public abstract class AbstractComponent implements Component, MethodEventSource * @return the parent application of the component or null. * @see #attach() */ + @Override public Application getApplication() { - if (parent == null) { - return null; - } else { - return parent.getApplication(); - } + // Just make method inherited from Component interface public + return super.getApplication(); } /** @@ -762,11 +693,9 @@ public abstract class AbstractComponent implements Component, MethodEventSource * * @return updated component shared state */ + @Override public ComponentState getState() { - if (null == sharedState) { - sharedState = createState(); - } - return sharedState; + return (ComponentState) super.getState(); } /* @@ -801,95 +730,15 @@ public abstract class AbstractComponent implements Component, MethodEventSource } } - /** - * Creates the shared state bean to be used in server to client - * communication. - *

      - * By default a state object of the defined return type of - * {@link #getState()} is created. Subclasses can override this method and - * return a new instance of the correct state class but this should rarely - * be necessary. - *

      - *

      - * No configuration of the values of the state should be performed in - * {@link #createState()}. - * - * @since 7.0 - * - * @return new shared state object - */ - protected ComponentState createState() { - try { - return getStateType().newInstance(); - } catch (Exception e) { - throw new RuntimeException( - "Error creating state of type " + getStateType().getName() - + " for " + getClass().getName(), e); - } - } - - /* (non-Javadoc) - * @see com.vaadin.terminal.gwt.server.ClientConnector#getStateType() - */ - public Class getStateType() { - try { - Method m = getClass().getMethod("getState", (Class[]) null); - Class type = (Class) m - .getReturnType(); - return type; - } catch (Exception e) { - throw new RuntimeException("Error finding state type for " - + getClass().getName(), e); - } - } - /* Documentation copied from interface */ + @Override public void requestRepaint() { // Invisible components (by flag in this particular component) do not // need repaints if (!getState().isVisible()) { return; } - - fireRequestRepaintEvent(); - } - - /** - * Fires the repaint request event. - * - * @param alreadyNotified - */ - // Notify listeners only once - private void fireRequestRepaintEvent() { - // Notify the listeners - if (repaintRequestListeners != null - && !repaintRequestListeners.isEmpty()) { - final Object[] listeners = repaintRequestListeners.toArray(); - final RepaintRequestEvent event = new RepaintRequestEvent(this); - for (int i = 0; i < listeners.length; i++) { - ((RepaintRequestListener) listeners[i]).repaintRequested(event); - } - } - } - - /* Documentation copied from interface */ - public void addListener(RepaintRequestListener listener) { - if (repaintRequestListeners == null) { - repaintRequestListeners = new LinkedList(); - } - if (!repaintRequestListeners.contains(listener)) { - repaintRequestListeners.add(listener); - } - } - - /* Documentation copied from interface */ - public void removeListener(RepaintRequestListener listener) { - if (repaintRequestListeners != null) { - repaintRequestListeners.remove(listener); - if (repaintRequestListeners.isEmpty()) { - repaintRequestListeners = null; - } - } + super.requestRepaint(); } /* General event framework */ @@ -1155,15 +1004,6 @@ public abstract class AbstractComponent implements Component, MethodEventSource * are found. */ public Collection getListeners(Class eventType) { - if (eventType.isAssignableFrom(RepaintRequestEvent.class)) { - // RepaintRequestListeners are not stored in eventRouter - if (repaintRequestListeners == null) { - return Collections.EMPTY_LIST; - } else { - return Collections - .unmodifiableCollection(repaintRequestListeners); - } - } if (eventRouter == null) { return Collections.EMPTY_LIST; } @@ -1512,159 +1352,4 @@ public abstract class AbstractComponent implements Component, MethodEventSource actionManager.removeAction(shortcut); } } - - /** - * Registers an RPC interface implementation for this component. - * - * A component can listen to multiple RPC interfaces, and subclasses can - * register additional implementations. - * - * @since 7.0 - * - * @param implementation - * RPC interface implementation - * @param rpcInterfaceType - * RPC interface class for which the implementation should be - * registered - */ - protected void registerRpc(T implementation, Class rpcInterfaceType) { - rpcManagerMap.put(rpcInterfaceType, new ServerRpcManager( - implementation, rpcInterfaceType)); - } - - /** - * Registers an RPC interface implementation for this component. - * - * A component can listen to multiple RPC interfaces, and subclasses can - * register additional implementations. - * - * @since 7.0 - * - * @param implementation - * RPC interface implementation. Also used to deduce the type. - */ - protected void registerRpc(T implementation) { - Class cls = implementation.getClass(); - Class[] interfaces = cls.getInterfaces(); - while (interfaces.length == 0) { - // Search upwards until an interface is found. It must be found as T - // extends ServerRpc - cls = cls.getSuperclass(); - interfaces = cls.getInterfaces(); - } - if (interfaces.length != 1 - || !(ServerRpc.class.isAssignableFrom(interfaces[0]))) { - throw new RuntimeException( - "Use registerRpc(T implementation, Class rpcInterfaceType) if the Rpc implementation implements more than one interface"); - } - Class type = (Class) interfaces[0]; - registerRpc(implementation, type); - } - - /** - * Returns an RPC proxy for a given server to client RPC interface for this - * component. - * - * TODO more javadoc, subclasses, ... - * - * @param rpcInterface - * RPC interface type - * - * @since 7.0 - */ - public T getRpcProxy(final Class rpcInterface) { - // create, initialize and return a dynamic proxy for RPC - try { - if (!rpcProxyMap.containsKey(rpcInterface)) { - Class proxyClass = (Class) Proxy.getProxyClass( - rpcInterface.getClassLoader(), rpcInterface); - Constructor constructor = proxyClass - .getConstructor(InvocationHandler.class); - T rpcProxy = constructor.newInstance(new RpcInvoicationHandler( - rpcInterface)); - // cache the proxy - rpcProxyMap.put(rpcInterface, rpcProxy); - } - return (T) rpcProxyMap.get(rpcInterface); - } catch (Exception e) { - // TODO exception handling? - throw new RuntimeException(e); - } - } - - private class RpcInvoicationHandler implements InvocationHandler, - Serializable { - - private String rpcInterfaceName; - - public RpcInvoicationHandler(Class rpcInterface) { - rpcInterfaceName = rpcInterface.getName().replaceAll("\\$", "."); - } - - public Object invoke(Object proxy, Method method, Object[] args) - throws Throwable { - addMethodInvocationToQueue(rpcInterfaceName, method, args); - // TODO no need to do full repaint if only RPC calls - requestRepaint(); - return null; - } - - } - - /** - * For internal use: adds a method invocation to the pending RPC call queue. - * - * @param interfaceName - * RPC interface name - * @param methodName - * RPC method name - * @param parameters - * RPC vall parameters - * - * @since 7.0 - */ - protected void addMethodInvocationToQueue(String interfaceName, - Method method, Object[] parameters) { - // add to queue - pendingInvocations.add(new ClientMethodInvocation(this, interfaceName, - method, parameters)); - } - - /** - * @see RpcTarget#getRpcManager(Class) - * - * @param rpcInterface - * RPC interface for which a call was made - * @return RPC Manager handling calls for the interface - * - * @since 7.0 - */ - public RpcManager getRpcManager(Class rpcInterface) { - return rpcManagerMap.get(rpcInterface); - } - - public List retrievePendingRpcCalls() { - if (pendingInvocations.isEmpty()) { - return Collections.emptyList(); - } else { - List result = pendingInvocations; - pendingInvocations = new ArrayList(); - return Collections.unmodifiableList(result); - } - } - - public String getConnectorId() { - if (connectorId == null) { - if (getApplication() == null) { - throw new RuntimeException( - "Component must be attached to an application when getConnectorId() is called for the first time"); - } - connectorId = getApplication().createConnectorId(this); - } - return connectorId; - } - - private Logger getLogger() { - return Logger.getLogger(AbstractComponent.class.getName()); - } } diff --git a/src/com/vaadin/ui/AbstractComponentContainer.java b/src/com/vaadin/ui/AbstractComponentContainer.java index 1c857a03cd..8ef458b704 100644 --- a/src/com/vaadin/ui/AbstractComponentContainer.java +++ b/src/com/vaadin/ui/AbstractComponentContainer.java @@ -71,36 +71,6 @@ public abstract class AbstractComponentContainer extends AbstractComponent } } - /** - * Notifies all contained components that the container is attached to a - * window. - * - * @see com.vaadin.ui.Component#attach() - */ - @Override - public void attach() { - super.attach(); - - for (final Iterator i = getComponentIterator(); i.hasNext();) { - (i.next()).attach(); - } - } - - /** - * Notifies all contained components that the container is detached from a - * window. - * - * @see com.vaadin.ui.Component#detach() - */ - @Override - public void detach() { - super.detach(); - - for (final Iterator i = getComponentIterator(); i.hasNext();) { - (i.next()).detach(); - } - } - /* Events */ private static final Method COMPONENT_ATTACHED_METHOD; @@ -355,46 +325,6 @@ public abstract class AbstractComponentContainer extends AbstractComponent true); } - public void requestRepaintAll() { - requestRepaintAll(this); - } - - /** - * Helper that implements the logic needed by requestRepaintAll. Calls - * requestRepaintAll/requestRepaint for the component container and all its - * children recursively. - * - * @param container - */ - public static void requestRepaintAll(HasComponents container) { - container.requestRepaint(); - if (container instanceof Panel) { - Panel p = (Panel) container; - // #2924 Panel is invalid, really invalid. - // Panel.getComponentIterator returns the children of content, not - // of Panel... - if (p.getContent() != null) { - p.getContent().requestRepaint(); - } - } - for (Iterator childIterator = container - .getComponentIterator(); childIterator.hasNext();) { - Component c = childIterator.next(); - if (c instanceof HasComponents) { - requestRepaintAll((HasComponents) c); - } else { - c.requestRepaint(); - } - } - } - - /** - * Returns an iterator for the child components. - * - * @return An iterator for the child components. - * @see #getComponentIterator() - * @since 7.0.0 - */ public Iterator iterator() { return getComponentIterator(); } diff --git a/src/com/vaadin/ui/Component.java b/src/com/vaadin/ui/Component.java index 3632c4ca5e..ce6df9854f 100644 --- a/src/com/vaadin/ui/Component.java +++ b/src/com/vaadin/ui/Component.java @@ -304,40 +304,9 @@ public interface Component extends ClientConnector, Sizeable, Serializable { *

      * * @return the parent component - * @see #setParent(Component) */ public HasComponents getParent(); - /** - * Sets the parent component of the component. - * - *

      - * This method automatically calls {@link #attach()} if the parent becomes - * attached to the application, regardless of whether it was attached - * previously. Conversely, if the parent is {@code null} and the component - * is attached to the application, {@link #detach()} is called for the - * component. - *

      - *

      - * This method is rarely called directly. The - * {@link ComponentContainer#addComponent(Component)} method is normally - * used for adding components to a container and it will call this method - * implicitly. - *

      - * - *

      - * It is not possible to change the parent without first setting the parent - * to {@code null}. - *

      - * - * @param parent - * the parent component - * @throws IllegalStateException - * if a parent is given even though the component already has a - * parent - */ - public void setParent(HasComponents parent); - /** * Tests whether the component is in the read-only mode. The user can not * change the value of a read-only component. As only {@link Field} @@ -564,15 +533,7 @@ public interface Component extends ClientConnector, Sizeable, Serializable { public Application getApplication(); /** - * Notifies the component that it is connected to an application. - * - *

      - * The caller of this method is {@link #setParent(Component)} if the parent - * is itself already attached to the application. If not, the parent will - * call the {@link #attach()} for all its children when it is attached to - * the application. This method is always called before the component is - * painted for the first time. - *

      + * {@inheritDoc} * *

      * Reimplementing the {@code attach()} method is useful for tasks that need @@ -624,37 +585,9 @@ public interface Component extends ClientConnector, Sizeable, Serializable { * } * } * - * - *

      - * The attachment logic is implemented in {@link AbstractComponent}. - *

      - * - * @see #getApplication() */ public void attach(); - /** - * Notifies the component that it is detached from the application. - * - *

      - * The {@link #getApplication()} and {@link #getRoot()} methods might return - * null after this method is called. - *

      - * - *

      - * This method must call {@link Root#componentDetached(Component)} to let - * the Root know that a new Component has been attached. - *

      - * * - *

      - * The caller of this method is {@link #setParent(Component)} if the parent - * is in the application. When the parent is detached from the application - * it is its response to call {@link #detach()} for all the children and to - * detach itself from the terminal. - *

      - */ - public void detach(); - /** * Gets the locale of the component. * @@ -719,75 +652,6 @@ public interface Component extends ClientConnector, Sizeable, Serializable { */ public String getDebugId(); - /** - * Requests that the component should be repainted as soon as possible. - */ - public void requestRepaint(); - - /** - * Repaint request event is thrown when the connector needs to be repainted. - * This is typically done when the paint method would return - * dissimilar UIDL from the previous call of the method. - */ - @SuppressWarnings("serial") - public static class RepaintRequestEvent extends EventObject { - - /** - * Constructs a new event. - * - * @param source - * the paintable needing repaint. - */ - public RepaintRequestEvent(ClientConnector source) { - super(source); - } - - /** - * Gets the connector needing repainting. - * - * @return Paintable for which the paint method will return - * dissimilar UIDL from the previous call of the method. - */ - public ClientConnector getConnector() { - return (ClientConnector) getSource(); - } - } - - /** - * Listens repaint requests. The repaintRequested method is - * called when the paintable needs to be repainted. This is typically done - * when the paint method would return dissimilar UIDL from the - * previous call of the method. - */ - public interface RepaintRequestListener extends Serializable { - - /** - * Receives repaint request events. - * - * @param event - * the repaint request event specifying the paintable source. - */ - public void repaintRequested(RepaintRequestEvent event); - } - - /** - * Adds repaint request listener. In order to assure that no repaint - * requests are missed, the new repaint listener should paint the paintable - * right after adding itself as listener. - * - * @param listener - * the listener to be added. - */ - public void addListener(RepaintRequestListener listener); - - /** - * Removes repaint request listener. - * - * @param listener - * the listener to be removed. - */ - public void removeListener(RepaintRequestListener listener); - /* Component event framework */ /** diff --git a/src/com/vaadin/ui/CssLayout.java b/src/com/vaadin/ui/CssLayout.java index 0a2656af31..e8ec6bd041 100644 --- a/src/com/vaadin/ui/CssLayout.java +++ b/src/com/vaadin/ui/CssLayout.java @@ -11,9 +11,9 @@ import com.vaadin.event.LayoutEvents.LayoutClickListener; import com.vaadin.event.LayoutEvents.LayoutClickNotifier; import com.vaadin.terminal.gwt.client.Connector; import com.vaadin.terminal.gwt.client.MouseEventDetails; +import com.vaadin.terminal.gwt.client.ui.LayoutClickEventHandler; import com.vaadin.terminal.gwt.client.ui.csslayout.CssLayoutServerRpc; import com.vaadin.terminal.gwt.client.ui.csslayout.CssLayoutState; -import com.vaadin.terminal.gwt.client.ui.LayoutClickEventHandler; /** * CssLayout is a layout component that can be used in browser environment only. @@ -185,7 +185,8 @@ public class CssLayout extends AbstractLayout implements LayoutClickNotifier { public void updateState() { super.updateState(); getState().getChildCss().clear(); - for (Component child : this) { + for (Iterator ci = getComponentIterator(); ci.hasNext();) { + Component child = ci.next(); String componentCssString = getCss(child); if (componentCssString != null) { getState().getChildCss().put(child, componentCssString); diff --git a/src/com/vaadin/ui/CustomField.java b/src/com/vaadin/ui/CustomField.java index 806ee91335..269f24fb2c 100644 --- a/src/com/vaadin/ui/CustomField.java +++ b/src/com/vaadin/ui/CustomField.java @@ -63,11 +63,9 @@ public abstract class CustomField extends AbstractField implements @Override public void attach() { root = getContent(); - super.attach(); getContent().setParent(this); - getContent().attach(); - fireComponentAttachEvent(getContent()); + super.attach(); } /** @@ -79,7 +77,6 @@ public abstract class CustomField extends AbstractField implements @Override public void detach() { super.detach(); - getContent().detach(); } /** @@ -154,10 +151,6 @@ public abstract class CustomField extends AbstractField implements return (null != getContent()) ? 1 : 0; } - public void requestRepaintAll() { - AbstractComponentContainer.requestRepaintAll(this); - } - /** * Fires the component attached event. This should be called by the * addComponent methods after the component have been added to this diff --git a/src/com/vaadin/ui/DirtyConnectorTracker.java b/src/com/vaadin/ui/DirtyConnectorTracker.java index 84df7e7c7c..a4e509422c 100644 --- a/src/com/vaadin/ui/DirtyConnectorTracker.java +++ b/src/com/vaadin/ui/DirtyConnectorTracker.java @@ -9,10 +9,8 @@ import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; -import com.vaadin.terminal.gwt.server.AbstractCommunicationManager; +import com.vaadin.terminal.AbstractClientConnector; import com.vaadin.terminal.gwt.server.ClientConnector; -import com.vaadin.ui.Component.RepaintRequestEvent; -import com.vaadin.ui.Component.RepaintRequestListener; /** * A class that tracks dirty {@link ClientConnector}s. A {@link ClientConnector} @@ -25,8 +23,8 @@ import com.vaadin.ui.Component.RepaintRequestListener; * @since 7.0.0 * */ -public class DirtyConnectorTracker implements RepaintRequestListener { - private Set dirtyComponents = new HashSet(); +public class DirtyConnectorTracker { + private Set dirtyConnectors = new HashSet(); private Root root; /** @@ -43,90 +41,72 @@ public class DirtyConnectorTracker implements RepaintRequestListener { this.root = root; } - public void repaintRequested(RepaintRequestEvent event) { - markDirty((Component) event.getConnector()); - } - - public void componentAttached(Component component) { - component.addListener(this); - markDirty(component); - } - - private void markDirty(Component component) { + public void markDirty(ClientConnector connector) { if (getLogger().isLoggable(Level.FINE)) { - if (!dirtyComponents.contains(component)) { + if (!dirtyConnectors.contains(connector)) { getLogger() - .fine(getDebugInfo(component) + " " + "is now dirty"); + .fine(getDebugInfo(connector) + " " + "is now dirty"); } } - dirtyComponents.add(component); + dirtyConnectors.add(connector); } - private void markClean(Component component) { + public void markClean(ClientConnector connector) { if (getLogger().isLoggable(Level.FINE)) { - if (dirtyComponents.contains(component)) { + if (dirtyConnectors.contains(connector)) { getLogger().fine( - getDebugInfo(component) + " " + "is no longer dirty"); + getDebugInfo(connector) + " " + "is no longer dirty"); } } - dirtyComponents.remove(component); + dirtyConnectors.remove(connector); } - private String getDebugInfo(Component component) { - String message = getObjectString(component); - if (component.getParent() != null) { - message += " (parent: " + getObjectString(component.getParent()) + private String getDebugInfo(ClientConnector connector) { + String message = getObjectString(connector); + if (connector.getParent() != null) { + message += " (parent: " + getObjectString(connector.getParent()) + ")"; } return message; } - private String getObjectString(Object component) { - return component.getClass().getName() + "@" - + Integer.toHexString(component.hashCode()); + private String getObjectString(Object connector) { + return connector.getClass().getName() + "@" + + Integer.toHexString(connector.hashCode()); } - public void componentDetached(Component component) { - component.removeListener(this); - markClean(component); + public void markAllConnectorsDirty() { + markConnectorsDirtyRecursively(root); + getLogger().fine("All connectors are now dirty"); } - public void markAllComponentsDirty() { - markComponentsDirtyRecursively(root); - getLogger().fine("All components are now dirty"); - } - - public void markAllComponentsClean() { - dirtyComponents.clear(); - getLogger().fine("All components are now clean"); + public void markAllConnectorsClean() { + dirtyConnectors.clear(); + getLogger().fine("All connectors are now clean"); } /** - * Marks all visible components dirty, starting from the given component and + * Marks all visible connectors dirty, starting from the given connector and * going downwards in the hierarchy. * * @param c * The component to start iterating downwards from */ - private void markComponentsDirtyRecursively(Component c) { - if (!c.isVisible()) { + private void markConnectorsDirtyRecursively(ClientConnector c) { + if (c instanceof Component && !((Component) c).isVisible()) { return; } markDirty(c); - if (c instanceof HasComponents) { - HasComponents container = (HasComponents) c; - for (Component child : AbstractCommunicationManager - .getChildComponents(container)) { - markComponentsDirtyRecursively(child); - } + for (ClientConnector child : AbstractClientConnector + .getAllChildrenIteratable(c)) { + markConnectorsDirtyRecursively(child); } - } - public Collection getDirtyComponents() { - return dirtyComponents; + public Collection getDirtyConnectors() { + return dirtyConnectors; } } diff --git a/src/com/vaadin/ui/Form.java b/src/com/vaadin/ui/Form.java index 5f5516b21f..39b12e67e2 100644 --- a/src/com/vaadin/ui/Form.java +++ b/src/com/vaadin/ui/Form.java @@ -1411,10 +1411,6 @@ public class Form extends AbstractField implements Item.Editor, return new ComponentIterator(); } - public void requestRepaintAll() { - AbstractComponentContainer.requestRepaintAll(this); - } - public int getComponentCount() { int count = 0; if (getLayout() != null) { diff --git a/src/com/vaadin/ui/HasComponents.java b/src/com/vaadin/ui/HasComponents.java index eca89ddcd2..3ebd63bff2 100644 --- a/src/com/vaadin/ui/HasComponents.java +++ b/src/com/vaadin/ui/HasComponents.java @@ -21,7 +21,10 @@ public interface HasComponents extends Component, Iterable { * container. * * @return the component iterator. + * + * @deprecated Use {@link #iterator()} instead. */ + @Deprecated public Iterator getComponentIterator(); /** @@ -43,12 +46,4 @@ public interface HasComponents extends Component, Iterable { */ public boolean isComponentVisible(Component childComponent); - /** - * Causes a repaint of this component, and all components below it. - * - * This should only be used in special cases, e.g when the state of a - * descendant depends on the state of a ancestor. - */ - public void requestRepaintAll(); - } diff --git a/src/com/vaadin/ui/HelloWorldExtension.java b/src/com/vaadin/ui/HelloWorldExtension.java new file mode 100644 index 0000000000..6d9ce9bcf1 --- /dev/null +++ b/src/com/vaadin/ui/HelloWorldExtension.java @@ -0,0 +1,38 @@ +/* +@VaadinApache2LicenseForJavaFiles@ + */ +package com.vaadin.ui; + +import com.vaadin.terminal.AbstractExtension; +import com.vaadin.terminal.gwt.client.ui.helloworldfeature.GreetAgainRpc; +import com.vaadin.terminal.gwt.client.ui.helloworldfeature.HelloWorldRpc; +import com.vaadin.terminal.gwt.client.ui.helloworldfeature.HelloWorldState; + +public class HelloWorldExtension extends AbstractExtension { + + public HelloWorldExtension() { + registerRpc(new HelloWorldRpc() { + public void onMessageSent(String message) { + getRoot().showNotification(message); + } + }); + } + + @Override + public HelloWorldState getState() { + return (HelloWorldState) super.getState(); + } + + public void setGreeting(String greeting) { + getState().setGreeting(greeting); + requestRepaint(); + } + + public String getGreeting() { + return getState().getGreeting(); + } + + public void greetAgain() { + getRpcProxy(GreetAgainRpc.class).greetAgain(); + } +} diff --git a/src/com/vaadin/ui/Panel.java b/src/com/vaadin/ui/Panel.java index a0fd84bbef..37e03ffb37 100644 --- a/src/com/vaadin/ui/Panel.java +++ b/src/com/vaadin/ui/Panel.java @@ -193,15 +193,6 @@ public class Panel extends AbstractComponentContainer implements Scrollable, } } - @Override - public void requestRepaintAll() { - // Panel has odd structure, delegate to layout - requestRepaint(); - if (getContent() != null) { - getContent().requestRepaintAll(); - } - } - /** * Adds the component into this container. * @@ -354,35 +345,6 @@ public class Panel extends AbstractComponentContainer implements Scrollable, } } - /** - * Notifies the component that it is connected to an application. - * - * @see com.vaadin.ui.Component#attach() - */ - @Override - public void attach() { - getRoot().componentAttached(this); - // can't call parent here as this is Panels hierarchy is a hack - requestRepaint(); - if (content != null) { - content.attach(); - } - } - - /** - * Notifies the component that it is detached from the application. - * - * @see com.vaadin.ui.Component#detach() - */ - @Override - public void detach() { - // can't call parent here as this is Panels hierarchy is a hack - if (content != null) { - content.detach(); - } - getRoot().componentDetached(this); - } - /** * Removes all components from this container. * diff --git a/src/com/vaadin/ui/Root.java b/src/com/vaadin/ui/Root.java index 9c3aef4152..0ba8ef27fb 100644 --- a/src/com/vaadin/ui/Root.java +++ b/src/com/vaadin/ui/Root.java @@ -1584,12 +1584,4 @@ public abstract class Root extends AbstractComponentContainer implements return dirtyConnectorTracker; } - public void componentAttached(Component component) { - getDirtyConnectorTracker().componentAttached(component); - } - - public void componentDetached(Component component) { - getDirtyConnectorTracker().componentDetached(component); - } - } diff --git a/src/com/vaadin/ui/Table.java b/src/com/vaadin/ui/Table.java index 299eace16d..e41c3d2a42 100644 --- a/src/com/vaadin/ui/Table.java +++ b/src/com/vaadin/ui/Table.java @@ -3705,13 +3705,6 @@ public class Table extends AbstractSelect implements Action.Container, super.attach(); refreshRenderedCells(); - - if (visibleComponents != null) { - for (final Iterator i = visibleComponents.iterator(); i - .hasNext();) { - i.next().attach(); - } - } } /** @@ -3722,13 +3715,6 @@ public class Table extends AbstractSelect implements Action.Container, @Override public void detach() { super.detach(); - - if (visibleComponents != null) { - for (final Iterator i = visibleComponents.iterator(); i - .hasNext();) { - i.next().detach(); - } - } } /** @@ -4453,10 +4439,6 @@ public class Table extends AbstractSelect implements Action.Container, } } - public void requestRepaintAll() { - AbstractComponentContainer.requestRepaintAll(this); - } - /** * Sets the drag start mode of the Table. Drag start mode controls how Table * behaves as a drag source. diff --git a/tests/server-side/com/vaadin/tests/server/component/abstractcomponent/TestAbstractComponentStyleNames.java b/tests/server-side/com/vaadin/tests/server/component/abstractcomponent/TestAbstractComponentStyleNames.java index b1c4a8f4be..1903e66f92 100644 --- a/tests/server-side/com/vaadin/tests/server/component/abstractcomponent/TestAbstractComponentStyleNames.java +++ b/tests/server-side/com/vaadin/tests/server/component/abstractcomponent/TestAbstractComponentStyleNames.java @@ -58,5 +58,4 @@ public class TestAbstractComponentStyleNames extends TestCase { return new AbstractComponent() { }; } - } diff --git a/tests/server-side/com/vaadin/tests/server/component/textfield/TextFieldWithPropertyFormatter.java b/tests/server-side/com/vaadin/tests/server/component/textfield/TextFieldWithPropertyFormatter.java index 0749dc299e..c6af98a873 100644 --- a/tests/server-side/com/vaadin/tests/server/component/textfield/TextFieldWithPropertyFormatter.java +++ b/tests/server-side/com/vaadin/tests/server/component/textfield/TextFieldWithPropertyFormatter.java @@ -9,8 +9,6 @@ import com.vaadin.data.Property.ValueChangeEvent; import com.vaadin.data.Property.ValueChangeListener; import com.vaadin.data.util.ObjectProperty; import com.vaadin.data.util.PropertyFormatter; -import com.vaadin.ui.Component.RepaintRequestEvent; -import com.vaadin.ui.Component.RepaintRequestListener; import com.vaadin.ui.TextField; public class TextFieldWithPropertyFormatter extends TestCase { @@ -30,7 +28,13 @@ public class TextFieldWithPropertyFormatter extends TestCase { protected void setUp() throws Exception { super.setUp(); - field = new TextField(); + field = new TextField() { + @Override + public void requestRepaint() { + repainted++; + super.requestRepaint(); + } + }; formatter = new PropertyFormatter() { @@ -61,11 +65,6 @@ public class TextFieldWithPropertyFormatter extends TestCase { }; field.addListener(listener); - field.addListener(new RepaintRequestListener() { - public void repaintRequested(RepaintRequestEvent event) { - repainted++; - } - }); listenerCalled = 0; repainted = 0; } diff --git a/tests/testbench/com/vaadin/tests/features/HelloWorldFeatureTest.java b/tests/testbench/com/vaadin/tests/features/HelloWorldFeatureTest.java new file mode 100644 index 0000000000..3d26b92648 --- /dev/null +++ b/tests/testbench/com/vaadin/tests/features/HelloWorldFeatureTest.java @@ -0,0 +1,38 @@ +/* +@VaadinApache2LicenseForJavaFiles@ + */ +package com.vaadin.tests.features; + +import com.vaadin.terminal.WrappedRequest; +import com.vaadin.tests.components.AbstractTestRoot; +import com.vaadin.ui.Button; +import com.vaadin.ui.Button.ClickEvent; +import com.vaadin.ui.HelloWorldExtension; + +public class HelloWorldFeatureTest extends AbstractTestRoot { + + @Override + protected void setup(WrappedRequest request) { + final HelloWorldExtension extension = new HelloWorldExtension(); + extension.setGreeting("Kind words"); + addExtension(extension); + + addComponent(new Button("Greet again", new Button.ClickListener() { + public void buttonClick(ClickEvent event) { + extension.greetAgain(); + } + })); + } + + @Override + protected String getTestDescription() { + return "Testing basic Feature"; + } + + @Override + protected Integer getTicketNumber() { + // TODO Auto-generated method stub + return null; + } + +} -- cgit v1.2.3 From 2e2020cb9b3a3f3353d7a56de7b1e0ab2b5186e1 Mon Sep 17 00:00:00 2001 From: Leif Åstrand Date: Mon, 28 May 2012 16:05:55 +0300 Subject: Fix accidental invalid cast (#6690) --- src/com/vaadin/terminal/gwt/client/ComponentLocator.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/com/vaadin/terminal/gwt/client/ComponentLocator.java b/src/com/vaadin/terminal/gwt/client/ComponentLocator.java index 205317542f..f88cd6b143 100644 --- a/src/com/vaadin/terminal/gwt/client/ComponentLocator.java +++ b/src/com/vaadin/terminal/gwt/client/ComponentLocator.java @@ -11,7 +11,6 @@ import com.google.gwt.user.client.DOM; import com.google.gwt.user.client.Element; import com.google.gwt.user.client.ui.HasWidgets; import com.google.gwt.user.client.ui.RootPanel; -import com.google.gwt.user.client.ui.SimplePanel; import com.google.gwt.user.client.ui.Widget; import com.vaadin.terminal.gwt.client.communication.SharedState; import com.vaadin.terminal.gwt.client.ui.SubPartAware; @@ -452,7 +451,7 @@ public class ComponentLocator { } if (connector instanceof ComponentConnector) { - w = ((SimplePanel) connector).getWidget(); + w = ((ComponentConnector) connector).getWidget(); } else { // Not found return null; -- cgit v1.2.3 From f77f121d0dd47ffc23c8f07e034fd6a115d0c2b0 Mon Sep 17 00:00:00 2001 From: Leif Åstrand Date: Tue, 29 May 2012 14:23:39 +0300 Subject: Fix some broken hierarchies (#6690) --- src/com/vaadin/ui/Panel.java | 3 ++- src/com/vaadin/ui/Root.java | 14 ++++++++++---- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/com/vaadin/ui/Panel.java b/src/com/vaadin/ui/Panel.java index 37e03ffb37..c339100cda 100644 --- a/src/com/vaadin/ui/Panel.java +++ b/src/com/vaadin/ui/Panel.java @@ -4,6 +4,7 @@ package com.vaadin.ui; +import java.util.Collections; import java.util.Iterator; import java.util.Map; @@ -229,7 +230,7 @@ public class Panel extends AbstractComponentContainer implements Scrollable, * @see com.vaadin.ui.ComponentContainer#getComponentIterator() */ public Iterator getComponentIterator() { - return content.getComponentIterator(); + return Collections.singleton((Component) content).iterator(); } /** diff --git a/src/com/vaadin/ui/Root.java b/src/com/vaadin/ui/Root.java index 0ba8ef27fb..8792bf1912 100644 --- a/src/com/vaadin/ui/Root.java +++ b/src/com/vaadin/ui/Root.java @@ -643,11 +643,17 @@ public abstract class Root extends AbstractComponentContainer implements * @see com.vaadin.ui.ComponentContainer#getComponentIterator() */ public Iterator getComponentIterator() { - if (getContent() == null) { - return Collections.EMPTY_LIST.iterator(); + // TODO could directly create some kind of combined iterator instead of + // creating a new ArrayList + ArrayList components = new ArrayList(); + + if (getContent() != null) { + components.add(getContent()); } - return Collections.singleton((Component) getContent()).iterator(); + components.addAll(windows); + + return components.iterator(); } /* @@ -656,7 +662,7 @@ public abstract class Root extends AbstractComponentContainer implements * @see com.vaadin.ui.ComponentContainer#getComponentCount() */ public int getComponentCount() { - return getContent() == null ? 0 : 1; + return windows.size() + (getContent() == null ? 0 : 1); } /** -- cgit v1.2.3 From 1e6e833666cdae5bff04a4c835baf117a8aba0b5 Mon Sep 17 00:00:00 2001 From: Leif Åstrand Date: Tue, 29 May 2012 16:47:04 +0300 Subject: Redefine isVisible to not paint dirty detached component (#6690) --- .../terminal/gwt/server/AbstractCommunicationManager.java | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java b/src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java index 186126c9c6..15b148ce7f 100644 --- a/src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java +++ b/src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java @@ -1255,9 +1255,17 @@ public abstract class AbstractCommunicationManager implements Serializable { * @return true if the child is visible to the client, false otherwise */ static boolean isVisible(Component child) { + if (!child.isVisible()) { + return false; + } + HasComponents parent = child.getParent(); - if (parent == null || !child.isVisible()) { - return child.isVisible(); + if (parent == null) { + if (child instanceof Root) { + return child.isVisible(); + } else { + return false; + } } return parent.isComponentVisible(child) && isVisible(parent); -- cgit v1.2.3 From d1a48a703a1947e2ad220e9608da726f0df3ee85 Mon Sep 17 00:00:00 2001 From: Leif Åstrand Date: Wed, 30 May 2012 11:34:52 +0300 Subject: Fix missing licenses and Serializable (#6690) --- .../vaadin/terminal/AbstractClientConnector.java | 38 ++++++++++++++-------- src/com/vaadin/terminal/AbstractExtension.java | 8 +++-- src/com/vaadin/terminal/Extension.java | 4 +++ src/com/vaadin/ui/DirtyConnectorTracker.java | 3 +- 4 files changed, 37 insertions(+), 16 deletions(-) diff --git a/src/com/vaadin/terminal/AbstractClientConnector.java b/src/com/vaadin/terminal/AbstractClientConnector.java index ad7c98b7e1..136ed702fc 100644 --- a/src/com/vaadin/terminal/AbstractClientConnector.java +++ b/src/com/vaadin/terminal/AbstractClientConnector.java @@ -1,3 +1,6 @@ +/* +@VaadinApache2LicenseForJavaFiles@ + */ package com.vaadin.terminal; import java.io.Serializable; @@ -197,6 +200,27 @@ public abstract class AbstractClientConnector implements ClientConnector { } } + private static final class AllChildrenIterable implements + Iterable, Serializable { + private final ClientConnector connector; + + private AllChildrenIterable(ClientConnector connector) { + this.connector = connector; + } + + public Iterator iterator() { + CombinedIterator iterator = new CombinedIterator(); + iterator.addIterator(connector.getExtensionIterator()); + + if (connector instanceof HasComponents) { + HasComponents hasComponents = (HasComponents) connector; + iterator.addIterator(hasComponents.iterator()); + } + + return iterator; + } + } + private class RpcInvoicationHandler implements InvocationHandler, Serializable { @@ -349,19 +373,7 @@ public abstract class AbstractClientConnector implements ClientConnector { public static Iterable getAllChildrenIteratable( final ClientConnector connector) { - return new Iterable() { - public Iterator iterator() { - CombinedIterator iterator = new CombinedIterator(); - iterator.addIterator(connector.getExtensionIterator()); - - if (connector instanceof HasComponents) { - HasComponents hasComponents = (HasComponents) connector; - iterator.addIterator(hasComponents.iterator()); - } - - return iterator; - } - }; + return new AllChildrenIterable(connector); } public Iterator getExtensionIterator() { diff --git a/src/com/vaadin/terminal/AbstractExtension.java b/src/com/vaadin/terminal/AbstractExtension.java index d01f7544c5..35123bc488 100644 --- a/src/com/vaadin/terminal/AbstractExtension.java +++ b/src/com/vaadin/terminal/AbstractExtension.java @@ -1,9 +1,13 @@ +/* +@VaadinApache2LicenseForJavaFiles@ + */ + package com.vaadin.terminal; import com.vaadin.terminal.gwt.server.ClientConnector; -public abstract class AbstractExtension extends AbstractClientConnector implements - Extension { +public abstract class AbstractExtension extends AbstractClientConnector + implements Extension { protected Class getAcceptedParentType() { return ClientConnector.class; diff --git a/src/com/vaadin/terminal/Extension.java b/src/com/vaadin/terminal/Extension.java index 7e4b92811d..7769423f0d 100644 --- a/src/com/vaadin/terminal/Extension.java +++ b/src/com/vaadin/terminal/Extension.java @@ -1,3 +1,7 @@ +/* +@VaadinApache2LicenseForJavaFiles@ + */ + package com.vaadin.terminal; import com.vaadin.terminal.gwt.server.ClientConnector; diff --git a/src/com/vaadin/ui/DirtyConnectorTracker.java b/src/com/vaadin/ui/DirtyConnectorTracker.java index a4e509422c..dae334fe4c 100644 --- a/src/com/vaadin/ui/DirtyConnectorTracker.java +++ b/src/com/vaadin/ui/DirtyConnectorTracker.java @@ -3,6 +3,7 @@ */ package com.vaadin.ui; +import java.io.Serializable; import java.util.Collection; import java.util.HashSet; import java.util.Set; @@ -23,7 +24,7 @@ import com.vaadin.terminal.gwt.server.ClientConnector; * @since 7.0.0 * */ -public class DirtyConnectorTracker { +public class DirtyConnectorTracker implements Serializable { private Set dirtyConnectors = new HashSet(); private Root root; -- cgit v1.2.3 From 9ae1a99ca3f4bcff88a576fddee6644ceeaa9d7e Mon Sep 17 00:00:00 2001 From: Leif Åstrand Date: Wed, 6 Jun 2012 09:59:22 +0300 Subject: Change widget -> connector in some places --- .../terminal/gwt/client/ApplicationConnection.java | 2 +- src/com/vaadin/terminal/gwt/client/WidgetSet.java | 28 +++++++++++----------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java b/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java index 4e7213e777..c3bdc405aa 100644 --- a/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java +++ b/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java @@ -2133,7 +2133,7 @@ public class ApplicationConnection { int connectorType) { // Create and register a new connector with the given type ServerConnector p = widgetSet - .createWidget(connectorType, configuration); + .createConnector(connectorType, configuration); connectorMap.registerConnector(connectorId, p); p.doInit(connectorId, this); diff --git a/src/com/vaadin/terminal/gwt/client/WidgetSet.java b/src/com/vaadin/terminal/gwt/client/WidgetSet.java index a973c4fd05..d7cc2df00d 100644 --- a/src/com/vaadin/terminal/gwt/client/WidgetSet.java +++ b/src/com/vaadin/terminal/gwt/client/WidgetSet.java @@ -5,7 +5,6 @@ package com.vaadin.terminal.gwt.client; import com.google.gwt.core.client.GWT; -import com.google.gwt.user.client.ui.Widget; import com.vaadin.terminal.gwt.client.ui.UnknownComponentConnector; public class WidgetSet { @@ -19,27 +18,28 @@ public class WidgetSet { /** * Create an uninitialized connector that best matches given UIDL. The - * connector must be a {@link Widget} that implements - * {@link ServerConnector}. + * connector must implement {@link ServerConnector}. * * @param tag * connector type tag for the connector to create - * @param client - * the application connection that whishes to instantiate widget + * @param conf + * the application configuration to use when creating the + * connector * * @return New uninitialized and unregistered connector that can paint given * UIDL. */ - public ServerConnector createWidget(int tag, ApplicationConfiguration conf) { + public ServerConnector createConnector(int tag, + ApplicationConfiguration conf) { /* * Yes, this (including the generated code in WidgetMap) may look very * odd code, but due the nature of GWT, we cannot do this any cleaner. * Luckily this is mostly written by WidgetSetGenerator, here are just - * some hacks. Extra instantiation code is needed if client side widget - * has no "native" counterpart on client side. + * some hacks. Extra instantiation code is needed if client side + * connector has no "native" counterpart on client side. */ - Class classType = resolveInheritedWidgetType( + Class classType = resolveInheritedConnectorType( conf, tag); if (classType == null || classType == UnknownComponentConnector.class) { @@ -56,23 +56,23 @@ public class WidgetSet { } } - private Class resolveInheritedWidgetType( + private Class resolveInheritedConnectorType( ApplicationConfiguration conf, int tag) { Class classType = null; Integer t = tag; do { - classType = resolveWidgetType(t, conf); + classType = resolveConnectorType(t, conf); t = conf.getParentTag(t); } while (classType == null && t != null); return classType; } - protected Class resolveWidgetType(int tag, + protected Class resolveConnectorType(int tag, ApplicationConfiguration conf) { - Class widgetClass = conf + Class connectorClass = conf .getConnectorClassByEncodedTag(tag); - return widgetClass; + return connectorClass; } /** -- cgit v1.2.3 From f8cb0b8eefb3e3f173b4168782324c9e8887d8a7 Mon Sep 17 00:00:00 2001 From: Leif Åstrand Date: Wed, 6 Jun 2012 07:42:00 +0000 Subject: Show better error message when variable change decoding fails (#8914) svn changeset:23888/svn branch:6.8 --- .../gwt/server/AbstractCommunicationManager.java | 27 ++++++++++++++-------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java b/src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java index b001b52918..fe848e50f2 100644 --- a/src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java +++ b/src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java @@ -1369,15 +1369,11 @@ public abstract class AbstractCommunicationManager implements // we have more than one value changes in row for // one variable owner, collect them in HashMap m = new HashMap(); - m.put(variable[VAR_NAME], - convertVariableValue(variable[VAR_TYPE].charAt(0), - variable[VAR_VALUE])); + m.put(variable[VAR_NAME], decodeVariable(variable)); } else { // use optimized single value map - m = Collections.singletonMap( - variable[VAR_NAME], - convertVariableValue(variable[VAR_TYPE].charAt(0), - variable[VAR_VALUE])); + m = Collections.singletonMap(variable[VAR_NAME], + decodeVariable(variable)); } // collect following variable changes for this owner @@ -1390,9 +1386,7 @@ public abstract class AbstractCommunicationManager implements } else { nextVariable = null; } - m.put(variable[VAR_NAME], - convertVariableValue(variable[VAR_TYPE].charAt(0), - variable[VAR_VALUE])); + m.put(variable[VAR_NAME], decodeVariable(variable)); } try { changeVariables(source, owner, m); @@ -1560,6 +1554,19 @@ public abstract class AbstractCommunicationManager implements } + private Object decodeVariable(String[] variable) { + try { + return convertVariableValue(variable[VAR_TYPE].charAt(0), + variable[VAR_VALUE]); + } catch (Exception e) { + String pid = variable[VAR_PID]; + VariableOwner variableOwner = getVariableOwner(pid); + throw new RuntimeException("Could not convert variable \"" + + variable[VAR_NAME] + "\" for " + + variableOwner.getClass().getName() + " (" + pid + ")", e); + } + } + private Object convertVariableValue(char variableType, String strValue) { Object val = null; switch (variableType) { -- cgit v1.2.3 From 948b55f86a4a7981ca576f6304820c644f418e61 Mon Sep 17 00:00:00 2001 From: Leif Åstrand Date: Wed, 6 Jun 2012 08:12:01 +0000 Subject: Avoid potential NPE discovered in review (#8914) svn changeset:23889/svn branch:6.8 --- .../vaadin/terminal/gwt/server/AbstractCommunicationManager.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java b/src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java index fe848e50f2..ae2cacdd38 100644 --- a/src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java +++ b/src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java @@ -1561,9 +1561,11 @@ public abstract class AbstractCommunicationManager implements } catch (Exception e) { String pid = variable[VAR_PID]; VariableOwner variableOwner = getVariableOwner(pid); + String targetType = variableOwner == null ? "unknown VariableOwner" + : variableOwner.getClass().getName(); throw new RuntimeException("Could not convert variable \"" - + variable[VAR_NAME] + "\" for " - + variableOwner.getClass().getName() + " (" + pid + ")", e); + + variable[VAR_NAME] + "\" for " + targetType + " (" + pid + + ")", e); } } -- cgit v1.2.3 From 1115e1f8bbc39c70005214b2a0e713cb3a17f5e4 Mon Sep 17 00:00:00 2001 From: Leif Åstrand Date: Wed, 6 Jun 2012 13:16:35 +0300 Subject: Add missing call to super.detach() (#6690) --- src/com/vaadin/ui/AbstractComponent.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/com/vaadin/ui/AbstractComponent.java b/src/com/vaadin/ui/AbstractComponent.java index 25695e3c0c..ba0e5db89c 100644 --- a/src/com/vaadin/ui/AbstractComponent.java +++ b/src/com/vaadin/ui/AbstractComponent.java @@ -609,6 +609,7 @@ public abstract class AbstractComponent extends AbstractClientConnector */ @Override public void detach() { + super.detach(); if (actionManager != null) { // Remove any existing viewer. Root cast is just to make the // compiler happy -- cgit v1.2.3 From f633581ab653be38bef09d1f68b361409cdea108 Mon Sep 17 00:00:00 2001 From: Leif Åstrand Date: Wed, 30 May 2012 15:13:26 +0300 Subject: Wrap variable change data in UidlValue wrapper with type info (#8878) This is the first step towards dropping type info from the sent data for everything except changeVariables data --- .../terminal/gwt/client/ApplicationConnection.java | 3 ++- .../gwt/client/communication/JsonEncoder.java | 17 +++++++++++++++ .../gwt/client/communication/UidlValue.java | 25 ++++++++++++++++++++++ .../gwt/server/AbstractCommunicationManager.java | 5 ++++- src/com/vaadin/terminal/gwt/server/JsonCodec.java | 21 ++++++++++++++++++ 5 files changed, 69 insertions(+), 2 deletions(-) create mode 100644 src/com/vaadin/terminal/gwt/client/communication/UidlValue.java diff --git a/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java b/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java index c3bdc405aa..530fd546db 100644 --- a/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java +++ b/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java @@ -45,6 +45,7 @@ import com.vaadin.terminal.gwt.client.communication.MethodInvocation; import com.vaadin.terminal.gwt.client.communication.RpcManager; import com.vaadin.terminal.gwt.client.communication.SerializerMap; import com.vaadin.terminal.gwt.client.communication.StateChangeEvent; +import com.vaadin.terminal.gwt.client.communication.UidlValue; import com.vaadin.terminal.gwt.client.ui.AbstractComponentConnector; import com.vaadin.terminal.gwt.client.ui.VContextMenu; import com.vaadin.terminal.gwt.client.ui.dd.VDragAndDropManager; @@ -1600,7 +1601,7 @@ public class ApplicationConnection { // TODO could eliminate invocations of same shared variable setter addMethodInvocationToQueue(new MethodInvocation(connectorId, UPDATE_VARIABLE_INTERFACE, UPDATE_VARIABLE_METHOD, - new Object[] { variableName, value }), immediate); + new Object[] { variableName, new UidlValue(value) }), immediate); } /** diff --git a/src/com/vaadin/terminal/gwt/client/communication/JsonEncoder.java b/src/com/vaadin/terminal/gwt/client/communication/JsonEncoder.java index f09536a9f7..edd900174a 100644 --- a/src/com/vaadin/terminal/gwt/client/communication/JsonEncoder.java +++ b/src/com/vaadin/terminal/gwt/client/communication/JsonEncoder.java @@ -46,6 +46,12 @@ public class JsonEncoder { public static final String VTYPE_SET = "q"; public static final String VTYPE_NULL = "n"; + /** + * Temporary hack to get variable changes decoded as internal types in + * JsonCodec. + */ + public static final String VTYPE_UIDL_VALUE = "v"; + /** * Encode a value to a JSON representation for transport from the client to * the server. @@ -98,6 +104,9 @@ public class JsonEncoder { } else if (value instanceof Collection) { return encodeCollection((Collection) value, restrictToInternalTypes, connectorMap, connection); + } else if (value instanceof UidlValue) { + return encodeVariableChange((UidlValue) value, connectorMap, + connection); } else { String transportType = getTransportType(value); if (transportType != null) { @@ -117,6 +126,14 @@ public class JsonEncoder { } } + private static JSONValue encodeVariableChange(UidlValue value, + ConnectorMap connectorMap, ApplicationConnection connection) { + JSONArray encodedValue = encode(value.getValue(), true, connectorMap, + connection).isArray(); + + return combineTypeAndValue(VTYPE_UIDL_VALUE, encodedValue); + } + private static JSONValue encodeMap(Map map, boolean restrictToInternalTypes, ConnectorMap connectorMap, ApplicationConnection connection) { diff --git a/src/com/vaadin/terminal/gwt/client/communication/UidlValue.java b/src/com/vaadin/terminal/gwt/client/communication/UidlValue.java new file mode 100644 index 0000000000..2a21074037 --- /dev/null +++ b/src/com/vaadin/terminal/gwt/client/communication/UidlValue.java @@ -0,0 +1,25 @@ +/* +@VaadinApache2LicenseForJavaFiles@ + */ + +package com.vaadin.terminal.gwt.client.communication; + +import java.io.Serializable; + +public class UidlValue implements Serializable { + private Object value; + + public UidlValue(Object value) { + this.value = value; + } + + public Object getValue() { + return value; + } + + @Override + public String toString() { + return "" + value; + } + +} diff --git a/src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java b/src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java index 15b148ce7f..5ead96c42e 100644 --- a/src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java +++ b/src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java @@ -68,6 +68,7 @@ import com.vaadin.terminal.gwt.client.ApplicationConnection; import com.vaadin.terminal.gwt.client.Connector; import com.vaadin.terminal.gwt.client.communication.MethodInvocation; import com.vaadin.terminal.gwt.client.communication.SharedState; +import com.vaadin.terminal.gwt.client.communication.UidlValue; import com.vaadin.terminal.gwt.server.BootstrapHandler.BootstrapContext; import com.vaadin.terminal.gwt.server.ComponentSizeValidator.InvalidLayout; import com.vaadin.ui.AbstractComponent; @@ -1630,9 +1631,11 @@ public abstract class AbstractCommunicationManager implements Serializable { String variableName = (String) JsonCodec .decodeInternalType(String.class, true, parametersJson.getJSONArray(0), application); - Object value = JsonCodec.decodeInternalType( + UidlValue uidlValue = (UidlValue) JsonCodec.decodeInternalType( parametersJson.getJSONArray(1), application); + Object value = uidlValue.getValue(); + if (previousInvocation != null && previousInvocation.getConnectorId().equals(connectorId)) { previousInvocation.setVariableChange(variableName, value); diff --git a/src/com/vaadin/terminal/gwt/server/JsonCodec.java b/src/com/vaadin/terminal/gwt/server/JsonCodec.java index e082eca47e..9c7abc53b4 100644 --- a/src/com/vaadin/terminal/gwt/server/JsonCodec.java +++ b/src/com/vaadin/terminal/gwt/server/JsonCodec.java @@ -13,6 +13,7 @@ import java.lang.reflect.Method; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; @@ -27,6 +28,7 @@ import com.vaadin.external.json.JSONException; import com.vaadin.external.json.JSONObject; import com.vaadin.terminal.gwt.client.Connector; import com.vaadin.terminal.gwt.client.communication.JsonEncoder; +import com.vaadin.terminal.gwt.client.communication.UidlValue; import com.vaadin.ui.Component; /** @@ -64,6 +66,7 @@ public class JsonCodec implements Serializable { registerType(HashMap.class, JsonEncoder.VTYPE_MAP); registerType(List.class, JsonEncoder.VTYPE_LIST); registerType(Set.class, JsonEncoder.VTYPE_SET); + registerType(UidlValue.class, JsonEncoder.VTYPE_UIDL_VALUE); } private static void registerType(Class type, String transportType) { @@ -195,6 +198,13 @@ public class JsonCodec implements Serializable { if (JsonEncoder.VTYPE_NULL.equals(encodedTransportType)) { return null; } + + // VariableChange + if (JsonEncoder.VTYPE_UIDL_VALUE.contentEquals(transportType)) { + return decodeVariableChange((JSONArray) encodedJsonValue, + application); + } + // Collections if (JsonEncoder.VTYPE_LIST.equals(transportType)) { return decodeList(targetType, restrictToInternalTypes, @@ -244,6 +254,17 @@ public class JsonCodec implements Serializable { throw new JSONException("Unknown type " + transportType); } + private static UidlValue decodeVariableChange(JSONArray encodedJsonValue, + Application application) throws JSONException { + String type = encodedJsonValue.getString(0); + + // Fake format used by decode method + JSONArray valueAndType = new JSONArray(Arrays.asList(type, + encodedJsonValue.get(1))); + Object decodedValue = decodeInternalType(valueAndType, application); + return new UidlValue(decodedValue); + } + private static boolean transportTypesCompatible( String encodedTransportType, String transportType) { if (encodedTransportType == null) { -- cgit v1.2.3 From 4d8a33b2ad876e607fb6b24b52e3d5dddc5309dd Mon Sep 17 00:00:00 2001 From: Leif Åstrand Date: Wed, 30 May 2012 16:23:49 +0300 Subject: Use UidlValue for sending legacy maps and arrays (#8878) --- .../gwt/client/communication/JsonEncoder.java | 19 +++++++++++-- .../gwt/server/AbstractCommunicationManager.java | 3 +- src/com/vaadin/terminal/gwt/server/JsonCodec.java | 33 +++++----------------- 3 files changed, 25 insertions(+), 30 deletions(-) diff --git a/src/com/vaadin/terminal/gwt/client/communication/JsonEncoder.java b/src/com/vaadin/terminal/gwt/client/communication/JsonEncoder.java index edd900174a..20ed319253 100644 --- a/src/com/vaadin/terminal/gwt/client/communication/JsonEncoder.java +++ b/src/com/vaadin/terminal/gwt/client/communication/JsonEncoder.java @@ -88,8 +88,8 @@ public class JsonEncoder { if (restrictToInternalTypes) { // Enums are encoded as strings in Vaadin 6 so we still do that // for backwards copmatibility. - return encode(value.toString(), restrictToInternalTypes, - connectorMap, connection); + return encode(new UidlValue(value.toString()), + restrictToInternalTypes, connectorMap, connection); } else { Enum e = (Enum) value; return encodeEnum(e, connectorMap, connection); @@ -140,6 +140,15 @@ public class JsonEncoder { JSONObject jsonMap = new JSONObject(); for (Object mapKey : map.keySet()) { Object mapValue = map.get(mapKey); + if (restrictToInternalTypes) { + if (!(mapKey instanceof String)) { + throw new IllegalStateException( + "Only string keys supported for legacy maps"); + } + // Wrap in UidlValue to send explicit type info + mapKey = new UidlValue(mapKey); + mapValue = new UidlValue(mapValue); + } JSONValue encodedKey = encode(mapKey, restrictToInternalTypes, connectorMap, connection); JSONValue encodedValue = encode(mapValue, restrictToInternalTypes, @@ -161,9 +170,13 @@ public class JsonEncoder { JSONArray jsonArray = new JSONArray(); for (int i = 0; i < array.length; ++i) { // TODO handle object graph loops? + Object value = array[i]; + if (restrictToInternalTypes) { + value = new UidlValue(value); + } jsonArray.set( i, - encode(array[i], restrictToInternalTypes, connectorMap, + encode(value, restrictToInternalTypes, connectorMap, connection)); } return combineTypeAndValue(VTYPE_ARRAY, jsonArray); diff --git a/src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java b/src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java index 5ead96c42e..11e86b99fc 100644 --- a/src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java +++ b/src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java @@ -1632,7 +1632,8 @@ public abstract class AbstractCommunicationManager implements Serializable { .decodeInternalType(String.class, true, parametersJson.getJSONArray(0), application); UidlValue uidlValue = (UidlValue) JsonCodec.decodeInternalType( - parametersJson.getJSONArray(1), application); + UidlValue.class, true, parametersJson.getJSONArray(1), + application); Object value = uidlValue.getValue(); diff --git a/src/com/vaadin/terminal/gwt/server/JsonCodec.java b/src/com/vaadin/terminal/gwt/server/JsonCodec.java index 9c7abc53b4..a7515c7135 100644 --- a/src/com/vaadin/terminal/gwt/server/JsonCodec.java +++ b/src/com/vaadin/terminal/gwt/server/JsonCodec.java @@ -96,31 +96,10 @@ public class JsonCodec implements Serializable { } } - public static String getTransportType(JSONArray encodedValue) - throws JSONException { - return encodedValue.getString(0); - } - private static Class getType(String transportType) { return transportTypeToType.get(transportType); } - /** - * Decodes the given value and type, restricted to using only internal - * types. - * - * @param valueAndType - * @param application - * @throws JSONException - */ - @Deprecated - public static Object decodeInternalType(JSONArray valueAndType, - Application application) throws JSONException { - String transportType = getTransportType(valueAndType); - return decodeInternalType(getType(transportType), true, valueAndType, - application); - } - public static Object decodeInternalOrCustomType(Type targetType, JSONArray valueAndType, Application application) throws JSONException { @@ -258,10 +237,10 @@ public class JsonCodec implements Serializable { Application application) throws JSONException { String type = encodedJsonValue.getString(0); - // Fake format used by decode method JSONArray valueAndType = new JSONArray(Arrays.asList(type, encodedJsonValue.get(1))); - Object decodedValue = decodeInternalType(valueAndType, application); + Object decodedValue = decodeInternalType(getType(type), true, + valueAndType, application); return new UidlValue(decodedValue); } @@ -322,9 +301,11 @@ public class JsonCodec implements Serializable { return decodeInternalOrCustomType(childType, encodedValueAndType, application); } else { - // Only internal types when not enforcing a given type to avoid - // security issues - return decodeInternalType(encodedValueAndType, application); + // Only UidlValue when not enforcing a given type to avoid security + // issues + UidlValue decodeInternalType = (UidlValue) decodeInternalType( + UidlValue.class, true, encodedValueAndType, application); + return decodeInternalType.getValue(); } } -- cgit v1.2.3 From e2990637d5b7602f8ee9a6f503c5c17b20e896f8 Mon Sep 17 00:00:00 2001 From: Leif Åstrand Date: Wed, 30 May 2012 17:35:22 +0300 Subject: Drop explicit type info from client -> server communication (#8879) --- .../gwt/client/communication/JsonEncoder.java | 54 ++++++----------- .../gwt/server/AbstractCommunicationManager.java | 11 ++-- src/com/vaadin/terminal/gwt/server/JsonCodec.java | 68 ++++++++-------------- 3 files changed, 47 insertions(+), 86 deletions(-) diff --git a/src/com/vaadin/terminal/gwt/client/communication/JsonEncoder.java b/src/com/vaadin/terminal/gwt/client/communication/JsonEncoder.java index 20ed319253..541dc631c6 100644 --- a/src/com/vaadin/terminal/gwt/client/communication/JsonEncoder.java +++ b/src/com/vaadin/terminal/gwt/client/communication/JsonEncoder.java @@ -46,12 +46,6 @@ public class JsonEncoder { public static final String VTYPE_SET = "q"; public static final String VTYPE_NULL = "n"; - /** - * Temporary hack to get variable changes decoded as internal types in - * JsonCodec. - */ - public static final String VTYPE_UIDL_VALUE = "v"; - /** * Encode a value to a JSON representation for transport from the client to * the server. @@ -67,20 +61,18 @@ public class JsonEncoder { boolean restrictToInternalTypes, ConnectorMap connectorMap, ApplicationConnection connection) { if (null == value) { - return combineTypeAndValue(VTYPE_NULL, JSONNull.getInstance()); + return JSONNull.getInstance(); } else if (value instanceof String[]) { String[] array = (String[]) value; JSONArray jsonArray = new JSONArray(); for (int i = 0; i < array.length; ++i) { jsonArray.set(i, new JSONString(array[i])); } - return combineTypeAndValue(VTYPE_STRINGARRAY, jsonArray); + return jsonArray; } else if (value instanceof String) { - return combineTypeAndValue(VTYPE_STRING, new JSONString( - (String) value)); + return new JSONString((String) value); } else if (value instanceof Boolean) { - return combineTypeAndValue(VTYPE_BOOLEAN, - JSONBoolean.getInstance((Boolean) value)); + return JSONBoolean.getInstance((Boolean) value); } else if (value instanceof Object[]) { return encodeObjectArray((Object[]) value, restrictToInternalTypes, connectorMap, connection); @@ -99,8 +91,7 @@ public class JsonEncoder { connectorMap, connection); } else if (value instanceof Connector) { Connector connector = (Connector) value; - return combineTypeAndValue(VTYPE_CONNECTOR, new JSONString( - connector.getConnectorId())); + return new JSONString(connector.getConnectorId()); } else if (value instanceof Collection) { return encodeCollection((Collection) value, restrictToInternalTypes, connectorMap, connection); @@ -110,8 +101,7 @@ public class JsonEncoder { } else { String transportType = getTransportType(value); if (transportType != null) { - return combineTypeAndValue(transportType, - new JSONString(String.valueOf(value))); + return new JSONString(String.valueOf(value)); } else { // Try to find a generated serializer object, class name is the // type @@ -120,18 +110,20 @@ public class JsonEncoder { .getSerializer(transportType); // TODO handle case with no serializer found - return combineTypeAndValue(transportType, - serializer.serialize(value, connectorMap, connection)); + return serializer.serialize(value, connectorMap, connection); } } } - private static JSONValue encodeVariableChange(UidlValue value, + private static JSONValue encodeVariableChange(UidlValue uidlValue, ConnectorMap connectorMap, ApplicationConnection connection) { - JSONArray encodedValue = encode(value.getValue(), true, connectorMap, - connection).isArray(); + Object value = uidlValue.getValue(); - return combineTypeAndValue(VTYPE_UIDL_VALUE, encodedValue); + JSONArray jsonArray = new JSONArray(); + jsonArray.set(0, new JSONString(getTransportType(value))); + jsonArray.set(1, encode(value, true, connectorMap, connection)); + + return jsonArray; } private static JSONValue encodeMap(Map map, @@ -155,13 +147,12 @@ public class JsonEncoder { connectorMap, connection); jsonMap.put(encodedKey.toString(), encodedValue); } - return combineTypeAndValue(VTYPE_MAP, jsonMap); + return jsonMap; } private static JSONValue encodeEnum(Enum e, ConnectorMap connectorMap, ApplicationConnection connection) { - return combineTypeAndValue(e.getClass().getName(), - new JSONString(e.toString())); + return new JSONString(e.toString()); } private static JSONValue encodeObjectArray(Object[] array, @@ -179,7 +170,7 @@ public class JsonEncoder { encode(value, restrictToInternalTypes, connectorMap, connection)); } - return combineTypeAndValue(VTYPE_ARRAY, jsonArray); + return jsonArray; } private static JSONValue encodeCollection(Collection collection, @@ -193,9 +184,9 @@ public class JsonEncoder { jsonArray.set(idx++, encodedObject); } if (collection instanceof Set) { - return combineTypeAndValue(VTYPE_SET, jsonArray); + return jsonArray; } else if (collection instanceof List) { - return combineTypeAndValue(VTYPE_LIST, jsonArray); + return jsonArray; } else { throw new RuntimeException("Unsupport collection type: " + collection.getClass().getName()); @@ -203,13 +194,6 @@ public class JsonEncoder { } - private static JSONValue combineTypeAndValue(String type, JSONValue value) { - JSONArray outerArray = new JSONArray(); - outerArray.set(0, new JSONString(type)); - outerArray.set(1, value); - return outerArray; - } - /** * Returns the transport type for the given value. Only returns a transport * type for internally handled values. diff --git a/src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java b/src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java index 11e86b99fc..b32525a703 100644 --- a/src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java +++ b/src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java @@ -1628,12 +1628,9 @@ public abstract class AbstractCommunicationManager implements Serializable { "Invalid parameters in legacy change variables call. Expected 2, was " + parametersJson.length()); } - String variableName = (String) JsonCodec - .decodeInternalType(String.class, true, - parametersJson.getJSONArray(0), application); + String variableName = parametersJson.getString(0); UidlValue uidlValue = (UidlValue) JsonCodec.decodeInternalType( - UidlValue.class, true, parametersJson.getJSONArray(1), - application); + UidlValue.class, true, parametersJson.get(1), application); Object value = uidlValue.getValue(); @@ -1658,10 +1655,10 @@ public abstract class AbstractCommunicationManager implements Serializable { .getGenericParameterTypes(); for (int j = 0; j < parametersJson.length(); ++j) { - JSONArray parameterJson = parametersJson.getJSONArray(j); + Object parameterValue = parametersJson.get(j); Type parameterType = declaredRpcMethodParameterTypes[j]; parameters[j] = JsonCodec.decodeInternalOrCustomType(parameterType, - parameterJson, application); + parameterValue, application); } invocation.setParameters(parameters); return invocation; diff --git a/src/com/vaadin/terminal/gwt/server/JsonCodec.java b/src/com/vaadin/terminal/gwt/server/JsonCodec.java index a7515c7135..b853c90a3b 100644 --- a/src/com/vaadin/terminal/gwt/server/JsonCodec.java +++ b/src/com/vaadin/terminal/gwt/server/JsonCodec.java @@ -13,7 +13,6 @@ import java.lang.reflect.Method; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; @@ -26,6 +25,7 @@ import com.vaadin.Application; import com.vaadin.external.json.JSONArray; import com.vaadin.external.json.JSONException; import com.vaadin.external.json.JSONObject; +import com.vaadin.external.json.JSONTokener; import com.vaadin.terminal.gwt.client.Connector; import com.vaadin.terminal.gwt.client.communication.JsonEncoder; import com.vaadin.terminal.gwt.client.communication.UidlValue; @@ -66,7 +66,6 @@ public class JsonCodec implements Serializable { registerType(HashMap.class, JsonEncoder.VTYPE_MAP); registerType(List.class, JsonEncoder.VTYPE_LIST); registerType(Set.class, JsonEncoder.VTYPE_SET); - registerType(UidlValue.class, JsonEncoder.VTYPE_UIDL_VALUE); } private static void registerType(Class type, String transportType) { @@ -84,6 +83,10 @@ public class JsonCodec implements Serializable { if (type instanceof Class && ((Class) type).isPrimitive()) { // All primitive types are handled internally return true; + } else if (type == UidlValue.class) { + // UidlValue is a special internal type wrapping type info and a + // value + return true; } return typeToTransportType.containsKey(getClassForType(type)); } @@ -101,32 +104,22 @@ public class JsonCodec implements Serializable { } public static Object decodeInternalOrCustomType(Type targetType, - JSONArray valueAndType, Application application) - throws JSONException { + Object value, Application application) throws JSONException { if (isInternalType(targetType)) { - return decodeInternalType(targetType, false, valueAndType, - application); + return decodeInternalType(targetType, false, value, application); } else { - return decodeCustomType(targetType, valueAndType, application); + return decodeCustomType(targetType, value, application); } } - public static Object decodeCustomType(Type targetType, - JSONArray valueAndType, Application application) - throws JSONException { + public static Object decodeCustomType(Type targetType, Object value, + Application application) throws JSONException { if (isInternalType(targetType)) { throw new JSONException("decodeCustomType cannot be used for " + targetType + ", which is an internal type"); } - String transportType = getCustomTransportType(getClassForType(targetType)); - String encodedTransportType = valueAndType.getString(0); - if (!transportTypesCompatible(encodedTransportType, transportType)) { - throw new JSONException("Expected a value of type " + transportType - + ", received " + encodedTransportType); - } // Try to decode object using fields - Object value = valueAndType.get(1); if (value == JSONObject.NULL) { return null; } else { @@ -159,29 +152,21 @@ public class JsonCodec implements Serializable { * @throws JSONException */ public static Object decodeInternalType(Type targetType, - boolean restrictToInternalTypes, JSONArray valueAndType, + boolean restrictToInternalTypes, Object encodedJsonValue, Application application) throws JSONException { - String encodedTransportType = valueAndType.getString(0); if (!isInternalType(targetType)) { throw new JSONException("Type " + targetType + " is not a supported internal type."); } String transportType = getInternalTransportType(targetType); - if (!transportTypesCompatible(encodedTransportType, transportType)) { - throw new JSONException("Expected a value of type " + targetType - + ", received " + getType(encodedTransportType)); - } - - Object encodedJsonValue = valueAndType.get(1); - if (JsonEncoder.VTYPE_NULL.equals(encodedTransportType)) { + if (encodedJsonValue == JSONObject.NULL) { return null; } - // VariableChange - if (JsonEncoder.VTYPE_UIDL_VALUE.contentEquals(transportType)) { - return decodeVariableChange((JSONArray) encodedJsonValue, - application); + // UidlValue + if (targetType == UidlValue.class) { + return decodeUidlValue((JSONArray) encodedJsonValue, application); } // Collections @@ -233,14 +218,12 @@ public class JsonCodec implements Serializable { throw new JSONException("Unknown type " + transportType); } - private static UidlValue decodeVariableChange(JSONArray encodedJsonValue, + private static UidlValue decodeUidlValue(JSONArray encodedJsonValue, Application application) throws JSONException { String type = encodedJsonValue.getString(0); - JSONArray valueAndType = new JSONArray(Arrays.asList(type, - encodedJsonValue.get(1))); Object decodedValue = decodeInternalType(getType(type), true, - valueAndType, application); + encodedJsonValue.get(1), application); return new UidlValue(decodedValue); } @@ -267,8 +250,8 @@ public class JsonCodec implements Serializable { Iterator it = jsonMap.keys(); while (it.hasNext()) { String key = it.next(); - JSONArray encodedKey = new JSONArray(key); - JSONArray encodedValue = jsonMap.getJSONArray(key); + Object encodedKey = new JSONTokener(key).nextValue(); + Object encodedValue = jsonMap.get(key); Object decodedKey = decodeParametrizedType(targetType, restrictToInternalTypes, 0, encodedKey, application); @@ -291,20 +274,18 @@ public class JsonCodec implements Serializable { * @throws JSONException */ private static Object decodeParametrizedType(Type targetType, - boolean restrictToInternalTypes, int typeIndex, - JSONArray encodedValueAndType, Application application) - throws JSONException { + boolean restrictToInternalTypes, int typeIndex, Object value, + Application application) throws JSONException { if (!restrictToInternalTypes && targetType instanceof ParameterizedType) { Type childType = ((ParameterizedType) targetType) .getActualTypeArguments()[typeIndex]; // Only decode the given type - return decodeInternalOrCustomType(childType, encodedValueAndType, - application); + return decodeInternalOrCustomType(childType, value, application); } else { // Only UidlValue when not enforcing a given type to avoid security // issues UidlValue decodeInternalType = (UidlValue) decodeInternalType( - UidlValue.class, true, encodedValueAndType, application); + UidlValue.class, true, value, application); return decodeInternalType.getValue(); } } @@ -391,8 +372,7 @@ public class JsonCodec implements Serializable { if (fieldName == null) { continue; } - JSONArray encodedFieldValue = serializedObject - .getJSONArray(fieldName); + Object encodedFieldValue = serializedObject.get(fieldName); Type fieldType = pd.getReadMethod().getGenericReturnType(); Object decodedFieldValue = decodeInternalOrCustomType( fieldType, encodedFieldValue, application); -- cgit v1.2.3 From 6526c870a3b5d8fbb22c8c80cb06fa25ab62ed97 Mon Sep 17 00:00:00 2001 From: Leif Åstrand Date: Wed, 30 May 2012 17:57:48 +0300 Subject: Extract duplicated code for decoding collections --- .../terminal/gwt/client/communication/JsonDecoder.java | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/com/vaadin/terminal/gwt/client/communication/JsonDecoder.java b/src/com/vaadin/terminal/gwt/client/communication/JsonDecoder.java index 9ed20b6c79..8df92a141e 100644 --- a/src/com/vaadin/terminal/gwt/client/communication/JsonDecoder.java +++ b/src/com/vaadin/terminal/gwt/client/communication/JsonDecoder.java @@ -5,6 +5,7 @@ package com.vaadin.terminal.gwt.client.communication; import java.util.ArrayList; +import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; @@ -144,22 +145,24 @@ public class JsonDecoder { private static List decodeList(JSONArray jsonArray, ConnectorMap idMapper, ApplicationConnection connection) { List tokens = new ArrayList(); - for (int i = 0; i < jsonArray.size(); ++i) { - // each entry always has two elements: type and value - JSONArray entryArray = (JSONArray) jsonArray.get(i); - tokens.add(decodeValue(entryArray, null, idMapper, connection)); - } + decodeIntoCollection(jsonArray, idMapper, connection, tokens); return tokens; } private static Set decodeSet(JSONArray jsonArray, ConnectorMap idMapper, ApplicationConnection connection) { Set tokens = new HashSet(); + decodeIntoCollection(jsonArray, idMapper, connection, tokens); + return tokens; + } + + private static void decodeIntoCollection(JSONArray jsonArray, + ConnectorMap idMapper, ApplicationConnection connection, + Collection tokens) { for (int i = 0; i < jsonArray.size(); ++i) { // each entry always has two elements: type and value JSONArray entryArray = (JSONArray) jsonArray.get(i); tokens.add(decodeValue(entryArray, null, idMapper, connection)); } - return tokens; } } -- cgit v1.2.3 From dc7e238f2dc9ec6c9faad5ab6dcfdab8f2eaae46 Mon Sep 17 00:00:00 2001 From: Leif Åstrand Date: Thu, 31 May 2012 16:31:26 +0300 Subject: Refactor RpcManager to provide info about parameter types (#8879) This is an intermediate step towards decoding everything received from the server based on its declared type. --- .../vaadin/terminal/gwt/DefaultWidgetSet.gwt.xml | 4 +- .../communication/GeneratedRpcMethodProvider.java | 20 ++ .../gwt/client/communication/RpcManager.java | 59 +++++- .../gwt/client/communication/RpcMethod.java | 32 ++++ .../terminal/gwt/client/communication/Type.java | 40 ++++ .../GeneratedRpcMethodProviderGenerator.java | 202 +++++++++++++++++++++ .../gwt/widgetsetutils/RpcManagerGenerator.java | 197 -------------------- 7 files changed, 352 insertions(+), 202 deletions(-) create mode 100644 src/com/vaadin/terminal/gwt/client/communication/GeneratedRpcMethodProvider.java create mode 100644 src/com/vaadin/terminal/gwt/client/communication/RpcMethod.java create mode 100644 src/com/vaadin/terminal/gwt/client/communication/Type.java create mode 100644 src/com/vaadin/terminal/gwt/widgetsetutils/GeneratedRpcMethodProviderGenerator.java delete mode 100644 src/com/vaadin/terminal/gwt/widgetsetutils/RpcManagerGenerator.java diff --git a/src/com/vaadin/terminal/gwt/DefaultWidgetSet.gwt.xml b/src/com/vaadin/terminal/gwt/DefaultWidgetSet.gwt.xml index 74dc78d9b8..daa5e9f24d 100644 --- a/src/com/vaadin/terminal/gwt/DefaultWidgetSet.gwt.xml +++ b/src/com/vaadin/terminal/gwt/DefaultWidgetSet.gwt.xml @@ -63,9 +63,9 @@ + class="com.vaadin.terminal.gwt.widgetsetutils.GeneratedRpcMethodProviderGenerator"> + class="com.vaadin.terminal.gwt.client.communication.GeneratedRpcMethodProvider" /> getGeneratedRpcMethods(); +} diff --git a/src/com/vaadin/terminal/gwt/client/communication/RpcManager.java b/src/com/vaadin/terminal/gwt/client/communication/RpcManager.java index 302e6eaa55..1d3447687d 100644 --- a/src/com/vaadin/terminal/gwt/client/communication/RpcManager.java +++ b/src/com/vaadin/terminal/gwt/client/communication/RpcManager.java @@ -4,9 +4,13 @@ package com.vaadin.terminal.gwt.client.communication; -import java.io.Serializable; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import com.google.gwt.core.client.GWT; import com.vaadin.terminal.gwt.client.ConnectorMap; +import com.vaadin.terminal.gwt.client.ServerConnector; /** * Client side RPC manager that can invoke methods based on RPC calls received @@ -17,7 +21,21 @@ import com.vaadin.terminal.gwt.client.ConnectorMap; * * @since 7.0 */ -public interface RpcManager extends Serializable { +public class RpcManager { + + private final Map methodMap = new HashMap(); + + public RpcManager() { + GeneratedRpcMethodProvider provider = GWT + .create(GeneratedRpcMethodProvider.class); + Collection methods = provider.getGeneratedRpcMethods(); + for (RpcMethod rpcMethod : methods) { + methodMap.put( + rpcMethod.getInterfaceName() + "." + + rpcMethod.getMethodName(), rpcMethod); + } + } + /** * Perform server to client RPC invocation. * @@ -28,5 +46,40 @@ public interface RpcManager extends Serializable { * connectors referenced in parameters */ public void applyInvocation(MethodInvocation invocation, - ConnectorMap connectorMap); + ConnectorMap connectorMap) { + ServerConnector connector = connectorMap.getConnector(invocation + .getConnectorId()); + String signature = getSignature(invocation); + if (connector == null) { + throw new IllegalStateException("Target connector (" + + invocation.getConnectorId() + ") not found for RCC to " + + signature); + } + + RpcMethod rpcMethod = getRpcMethod(signature); + Collection implementations = connector + .getRpcImplementations(invocation.getInterfaceName()); + for (ClientRpc clientRpc : implementations) { + rpcMethod.applyInvocation(clientRpc, invocation.getParameters()); + } + } + + private RpcMethod getRpcMethod(String signature) { + RpcMethod rpcMethod = methodMap.get(signature); + if (rpcMethod == null) { + throw new IllegalStateException("There is no information about " + + signature + + ". Did you remember to compile the right widgetset?"); + } + return rpcMethod; + } + + private static String getSignature(MethodInvocation invocation) { + return invocation.getInterfaceName() + "." + invocation.getMethodName(); + } + + public Type[] getParameterTypes(MethodInvocation invocation) { + return getRpcMethod(getSignature(invocation)).getParameterTypes(); + } + } diff --git a/src/com/vaadin/terminal/gwt/client/communication/RpcMethod.java b/src/com/vaadin/terminal/gwt/client/communication/RpcMethod.java new file mode 100644 index 0000000000..abdcf73e2c --- /dev/null +++ b/src/com/vaadin/terminal/gwt/client/communication/RpcMethod.java @@ -0,0 +1,32 @@ +/* +@VaadinApache2LicenseForJavaFiles@ + */ +package com.vaadin.terminal.gwt.client.communication; + +public abstract class RpcMethod { + private String interfaceName; + private String methodName; + private Type[] parameterTypes; + + public RpcMethod(String interfaceName, String methodName, + Type... parameterTypes) { + this.interfaceName = interfaceName; + this.methodName = methodName; + this.parameterTypes = parameterTypes; + } + + public String getInterfaceName() { + return interfaceName; + } + + public String getMethodName() { + return methodName; + } + + public Type[] getParameterTypes() { + return parameterTypes; + } + + public abstract void applyInvocation(ClientRpc target, Object... parameters); + +} diff --git a/src/com/vaadin/terminal/gwt/client/communication/Type.java b/src/com/vaadin/terminal/gwt/client/communication/Type.java new file mode 100644 index 0000000000..dc33f760ff --- /dev/null +++ b/src/com/vaadin/terminal/gwt/client/communication/Type.java @@ -0,0 +1,40 @@ +/* +@VaadinApache2LicenseForJavaFiles@ + */ +package com.vaadin.terminal.gwt.client.communication; + +public class Type { + private final String baseTypeName; + private final Type[] parameterTypes; + + public Type(String baseTypeName, Type[] parameterTypes) { + this.baseTypeName = baseTypeName; + this.parameterTypes = parameterTypes; + } + + public String getBaseTypeName() { + return baseTypeName; + } + + public Type[] getParameterTypes() { + return parameterTypes; + } + + @Override + public String toString() { + String string = baseTypeName; + if (parameterTypes != null) { + string += '<'; + for (int i = 0; i < parameterTypes.length; i++) { + if (i != 0) { + string += ','; + } + string += parameterTypes[i].toString(); + } + string += '>'; + } + + return string; + } + +} diff --git a/src/com/vaadin/terminal/gwt/widgetsetutils/GeneratedRpcMethodProviderGenerator.java b/src/com/vaadin/terminal/gwt/widgetsetutils/GeneratedRpcMethodProviderGenerator.java new file mode 100644 index 0000000000..f0db4886e4 --- /dev/null +++ b/src/com/vaadin/terminal/gwt/widgetsetutils/GeneratedRpcMethodProviderGenerator.java @@ -0,0 +1,202 @@ +/* +@VaadinApache2LicenseForJavaFiles@ + */ + +package com.vaadin.terminal.gwt.widgetsetutils; + +import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +import com.google.gwt.core.ext.Generator; +import com.google.gwt.core.ext.GeneratorContext; +import com.google.gwt.core.ext.TreeLogger; +import com.google.gwt.core.ext.TreeLogger.Type; +import com.google.gwt.core.ext.UnableToCompleteException; +import com.google.gwt.core.ext.typeinfo.JClassType; +import com.google.gwt.core.ext.typeinfo.JMethod; +import com.google.gwt.core.ext.typeinfo.JParameterizedType; +import com.google.gwt.core.ext.typeinfo.JType; +import com.google.gwt.core.ext.typeinfo.TypeOracle; +import com.google.gwt.user.rebind.ClassSourceFileComposerFactory; +import com.google.gwt.user.rebind.SourceWriter; +import com.vaadin.terminal.gwt.client.communication.ClientRpc; +import com.vaadin.terminal.gwt.client.communication.GeneratedRpcMethodProvider; +import com.vaadin.terminal.gwt.client.communication.RpcManager; +import com.vaadin.terminal.gwt.client.communication.RpcMethod; + +/** + * GWT generator that creates an implementation for {@link RpcManager} on the + * client side classes for executing RPC calls received from the the server. + * + * @since 7.0 + */ +public class GeneratedRpcMethodProviderGenerator extends Generator { + + @Override + public String generate(TreeLogger logger, GeneratorContext context, + String typeName) throws UnableToCompleteException { + + String packageName = null; + String className = null; + try { + TypeOracle typeOracle = context.getTypeOracle(); + + // get classType and save instance variables + JClassType classType = typeOracle.getType(typeName); + packageName = classType.getPackage().getName(); + className = classType.getSimpleSourceName() + "Impl"; + // Generate class source code for SerializerMapImpl + generateClass(logger, context, packageName, className); + } catch (Exception e) { + logger.log(TreeLogger.ERROR, + "SerializerMapGenerator creation failed", e); + } + // return the fully qualifed name of the class generated + return packageName + "." + className; + } + + /** + * Generate source code for RpcManagerImpl + * + * @param logger + * Logger object + * @param context + * Generator context + * @param packageName + * package name for the class to generate + * @param className + * class name for the class to generate + */ + private void generateClass(TreeLogger logger, GeneratorContext context, + String packageName, String className) { + // get print writer that receives the source code + PrintWriter printWriter = null; + printWriter = context.tryCreate(logger, packageName, className); + // print writer if null, source code has ALREADY been generated + if (printWriter == null) { + return; + } + logger.log(Type.INFO, + "Detecting server to client RPC interface types..."); + Date date = new Date(); + TypeOracle typeOracle = context.getTypeOracle(); + JClassType serverToClientRpcType = typeOracle.findType(ClientRpc.class + .getName()); + JClassType[] rpcInterfaceSubtypes = serverToClientRpcType.getSubtypes(); + + // init composer, set class properties, create source writer + ClassSourceFileComposerFactory composer = null; + composer = new ClassSourceFileComposerFactory(packageName, className); + composer.addImport("com.google.gwt.core.client.GWT"); + composer.addImport(RpcMethod.class.getName()); + composer.addImport(ClientRpc.class.getName()); + composer.addImport(com.vaadin.terminal.gwt.client.communication.Type.class + .getName()); + composer.addImplementedInterface(GeneratedRpcMethodProvider.class + .getName()); + SourceWriter sourceWriter = composer.createSourceWriter(context, + printWriter); + sourceWriter.indent(); + + List rpcMethods = new ArrayList(); + + sourceWriter + .println("public java.util.Collection getGeneratedRpcMethods() {"); + sourceWriter.indent(); + + sourceWriter + .println("java.util.ArrayList list = new java.util.ArrayList();"); + + // iterate over RPC interfaces and create helper methods for each + // interface + for (JClassType type : rpcInterfaceSubtypes) { + if (null == type.isInterface()) { + // only interested in interfaces here, not implementations + continue; + } + + // loop over the methods of the interface and its superinterfaces + // methods + for (JClassType currentType : type.getFlattenedSupertypeHierarchy()) { + for (JMethod method : currentType.getMethods()) { + + // RpcMethod(String interfaceName, String methodName, + // Type... parameterTypes) + sourceWriter.print("list.add(new RpcMethod(\"" + + type.getQualifiedSourceName() + "\", \"" + + method.getName() + "\""); + JType[] parameterTypes = method.getParameterTypes(); + for (JType parameter : parameterTypes) { + sourceWriter.print(", "); + writeTypeCreator(sourceWriter, parameter); + } + sourceWriter.println(") {"); + sourceWriter.indent(); + + sourceWriter + .println("public void applyInvocation(ClientRpc target, Object... parameters) {"); + sourceWriter.indent(); + + sourceWriter.print("((" + type.getQualifiedSourceName() + + ")target)." + method.getName() + "("); + for (int i = 0; i < parameterTypes.length; i++) { + JType parameterType = parameterTypes[i]; + if (i != 0) { + sourceWriter.print(", "); + } + sourceWriter.print("(" + + parameterType.getQualifiedSourceName() + + ") parameters[" + i + "]"); + } + sourceWriter.println(");"); + + sourceWriter.outdent(); + sourceWriter.println("}"); + + sourceWriter.outdent(); + sourceWriter.println("});"); + } + } + } + + sourceWriter.println("return list;"); + + sourceWriter.outdent(); + sourceWriter.println("}"); + sourceWriter.println(); + + // close generated class + sourceWriter.outdent(); + sourceWriter.println("}"); + // commit generated class + context.commit(logger, printWriter); + logger.log(Type.INFO, + "Done. (" + (new Date().getTime() - date.getTime()) / 1000 + + "seconds)"); + + } + + private void writeTypeCreator(SourceWriter sourceWriter, JType type) { + sourceWriter.print("new Type(\"" + + type.getErasedType().getQualifiedSourceName() + "\", "); + JParameterizedType parameterized = type.isParameterized(); + if (parameterized != null) { + sourceWriter.print("new Type[] {"); + JClassType[] typeArgs = parameterized.getTypeArgs(); + for (JClassType jClassType : typeArgs) { + writeTypeCreator(sourceWriter, jClassType); + sourceWriter.print(", "); + } + sourceWriter.print("}"); + } else { + sourceWriter.print("null"); + } + sourceWriter.print(")"); + } + + private String getInvokeMethodName(JClassType type) { + return "invoke" + type.getQualifiedSourceName().replaceAll("\\.", "_"); + } +} diff --git a/src/com/vaadin/terminal/gwt/widgetsetutils/RpcManagerGenerator.java b/src/com/vaadin/terminal/gwt/widgetsetutils/RpcManagerGenerator.java deleted file mode 100644 index 2899061204..0000000000 --- a/src/com/vaadin/terminal/gwt/widgetsetutils/RpcManagerGenerator.java +++ /dev/null @@ -1,197 +0,0 @@ -/* -@VaadinApache2LicenseForJavaFiles@ - */ - -package com.vaadin.terminal.gwt.widgetsetutils; - -import java.io.PrintWriter; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; - -import com.google.gwt.core.ext.Generator; -import com.google.gwt.core.ext.GeneratorContext; -import com.google.gwt.core.ext.TreeLogger; -import com.google.gwt.core.ext.TreeLogger.Type; -import com.google.gwt.core.ext.UnableToCompleteException; -import com.google.gwt.core.ext.typeinfo.JClassType; -import com.google.gwt.core.ext.typeinfo.JMethod; -import com.google.gwt.core.ext.typeinfo.JType; -import com.google.gwt.core.ext.typeinfo.TypeOracle; -import com.google.gwt.user.rebind.ClassSourceFileComposerFactory; -import com.google.gwt.user.rebind.SourceWriter; -import com.vaadin.terminal.gwt.client.ServerConnector; -import com.vaadin.terminal.gwt.client.ConnectorMap; -import com.vaadin.terminal.gwt.client.communication.ClientRpc; -import com.vaadin.terminal.gwt.client.communication.MethodInvocation; -import com.vaadin.terminal.gwt.client.communication.RpcManager; - -/** - * GWT generator that creates an implementation for {@link RpcManager} on the - * client side classes for executing RPC calls received from the the server. - * - * @since 7.0 - */ -public class RpcManagerGenerator extends Generator { - - @Override - public String generate(TreeLogger logger, GeneratorContext context, - String typeName) throws UnableToCompleteException { - - String packageName = null; - String className = null; - try { - TypeOracle typeOracle = context.getTypeOracle(); - - // get classType and save instance variables - JClassType classType = typeOracle.getType(typeName); - packageName = classType.getPackage().getName(); - className = classType.getSimpleSourceName() + "Impl"; - // Generate class source code for SerializerMapImpl - generateClass(logger, context, packageName, className); - } catch (Exception e) { - logger.log(TreeLogger.ERROR, - "SerializerMapGenerator creation failed", e); - } - // return the fully qualifed name of the class generated - return packageName + "." + className; - } - - /** - * Generate source code for RpcManagerImpl - * - * @param logger - * Logger object - * @param context - * Generator context - * @param packageName - * package name for the class to generate - * @param className - * class name for the class to generate - */ - private void generateClass(TreeLogger logger, GeneratorContext context, - String packageName, String className) { - // get print writer that receives the source code - PrintWriter printWriter = null; - printWriter = context.tryCreate(logger, packageName, className); - // print writer if null, source code has ALREADY been generated - if (printWriter == null) { - return; - } - logger.log(Type.INFO, - "Detecting server to client RPC interface types..."); - Date date = new Date(); - TypeOracle typeOracle = context.getTypeOracle(); - JClassType serverToClientRpcType = typeOracle.findType(ClientRpc.class - .getName()); - JClassType[] rpcInterfaceSubtypes = serverToClientRpcType.getSubtypes(); - - // init composer, set class properties, create source writer - ClassSourceFileComposerFactory composer = null; - composer = new ClassSourceFileComposerFactory(packageName, className); - composer.addImport("com.google.gwt.core.client.GWT"); - composer.addImplementedInterface(RpcManager.class.getName()); - SourceWriter sourceWriter = composer.createSourceWriter(context, - printWriter); - sourceWriter.indent(); - - List rpcInterfaces = new ArrayList(); - - // iterate over RPC interfaces and create helper methods for each - // interface - for (JClassType type : rpcInterfaceSubtypes) { - if (null == type.isInterface()) { - // only interested in interfaces here, not implementations - continue; - } - rpcInterfaces.add(type); - // generate method to call methods of an RPC interface - sourceWriter.println("private void " + getInvokeMethodName(type) - + "(" + MethodInvocation.class.getName() + " invocation, " - + ConnectorMap.class.getName() + " connectorMap) {"); - sourceWriter.indent(); - - // loop over the methods of the interface and its superinterfaces - // methods - for (JClassType currentType : type.getFlattenedSupertypeHierarchy()) { - for (JMethod method : currentType.getMethods()) { - sourceWriter.println("if (\"" + method.getName() - + "\".equals(invocation.getMethodName())) {"); - sourceWriter.indent(); - // construct parameter string with appropriate casts - String paramString = ""; - JType[] parameterTypes = method.getParameterTypes(); - for (int i = 0; i < parameterTypes.length; ++i) { - paramString = paramString + "(" - + parameterTypes[i].getQualifiedSourceName() - + ") invocation.getParameters()[" + i + "]"; - if (i < parameterTypes.length - 1) { - paramString = paramString + ", "; - } - } - sourceWriter - .println(ServerConnector.class.getName() - + " connector = connectorMap.getConnector(invocation.getConnectorId());"); - sourceWriter - .println("for (" - + ClientRpc.class.getName() - + " rpcImplementation : connector.getRpcImplementations(\"" - + type.getQualifiedSourceName() + "\")) {"); - sourceWriter.indent(); - sourceWriter.println("((" + type.getQualifiedSourceName() - + ") rpcImplementation)." + method.getName() + "(" - + paramString + ");"); - sourceWriter.outdent(); - sourceWriter.println("}"); - sourceWriter.println("return;"); - sourceWriter.outdent(); - sourceWriter.println("}"); - } - } - - sourceWriter.outdent(); - sourceWriter.println("}"); - - logger.log(Type.DEBUG, - "Constructed helper method for server to client RPC for " - + type.getName()); - } - - // generate top-level "switch-case" method to select the correct - // previously generated method based on the RPC interface - sourceWriter.println("public void applyInvocation(" - + MethodInvocation.class.getName() + " invocation, " - + ConnectorMap.class.getName() + " connectorMap) {"); - sourceWriter.indent(); - - for (JClassType type : rpcInterfaces) { - sourceWriter.println("if (\"" + type.getQualifiedSourceName() - + "\".equals(invocation.getInterfaceName())) {"); - sourceWriter.indent(); - sourceWriter.println(getInvokeMethodName(type) - + "(invocation, connectorMap);"); - sourceWriter.println("return;"); - sourceWriter.outdent(); - sourceWriter.println("}"); - - logger.log(Type.INFO, - "Configured server to client RPC for " + type.getName()); - } - sourceWriter.outdent(); - sourceWriter.println("}"); - - // close generated class - sourceWriter.outdent(); - sourceWriter.println("}"); - // commit generated class - context.commit(logger, printWriter); - logger.log(Type.INFO, - "Done. (" + (new Date().getTime() - date.getTime()) / 1000 - + "seconds)"); - - } - - private String getInvokeMethodName(JClassType type) { - return "invoke" + type.getQualifiedSourceName().replaceAll("\\.", "_"); - } -} -- cgit v1.2.3 From 694a588f94785431d012daa8d001f2f931aec852 Mon Sep 17 00:00:00 2001 From: Leif Åstrand Date: Thu, 31 May 2012 23:12:57 +0300 Subject: Add DiffJSONSerializer for updating existing objects (#8879) This is work in progress towards using declared types for data received from the server. --- .../terminal/gwt/client/ApplicationConnection.java | 5 +- .../client/communication/DiffJSONSerializer.java | 19 +++++ .../gwt/client/communication/JSONSerializer.java | 7 +- .../gwt/client/communication/JsonDecoder.java | 65 +++++++++-------- .../communication/URLReference_Serializer.java | 6 +- .../gwt/widgetsetutils/SerializerGenerator.java | 84 ++++++++++++---------- 6 files changed, 107 insertions(+), 79 deletions(-) create mode 100644 src/com/vaadin/terminal/gwt/client/communication/DiffJSONSerializer.java diff --git a/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java b/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java index 530fd546db..c7ec5236b0 100644 --- a/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java +++ b/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java @@ -1412,7 +1412,7 @@ public class ApplicationConnection { states.getJavaScriptObject(connectorId)); JsonDecoder.decodeValue(stateDataAndType, - connector.getState(), connectorMap, + connector.getState(), ApplicationConnection.this); StateChangeEvent event = GWT @@ -1578,8 +1578,7 @@ public class ApplicationConnection { Object[] parameters = new Object[parametersJson.size()]; for (int j = 0; j < parametersJson.size(); ++j) { parameters[j] = JsonDecoder.decodeValue( - (JSONArray) parametersJson.get(j), null, getConnectorMap(), - this); + (JSONArray) parametersJson.get(j), null, this); } return new MethodInvocation(connectorId, interfaceName, methodName, parameters); diff --git a/src/com/vaadin/terminal/gwt/client/communication/DiffJSONSerializer.java b/src/com/vaadin/terminal/gwt/client/communication/DiffJSONSerializer.java new file mode 100644 index 0000000000..29cb714828 --- /dev/null +++ b/src/com/vaadin/terminal/gwt/client/communication/DiffJSONSerializer.java @@ -0,0 +1,19 @@ +/* +@VaadinApache2LicenseForJavaFiles@ + */ +package com.vaadin.terminal.gwt.client.communication; + +import com.google.gwt.json.client.JSONValue; +import com.vaadin.terminal.gwt.client.ApplicationConnection; + +public interface DiffJSONSerializer extends JSONSerializer { + /** + * Update the target object in place based on the passed JSON data. + * + * @param target + * @param jsonValue + * @param connection + */ + public void update(T target, Type type, JSONValue jsonValue, + ApplicationConnection connection); +} diff --git a/src/com/vaadin/terminal/gwt/client/communication/JSONSerializer.java b/src/com/vaadin/terminal/gwt/client/communication/JSONSerializer.java index f7b3df6b05..fe879b2fa7 100644 --- a/src/com/vaadin/terminal/gwt/client/communication/JSONSerializer.java +++ b/src/com/vaadin/terminal/gwt/client/communication/JSONSerializer.java @@ -34,14 +34,9 @@ public interface JSONSerializer { * * @param jsonValue * JSON map from property name to property value - * @param target - * The object to write the deserialized values to - * @param idMapper - * mapper from paintable id to paintable, used to decode - * references to paintables * @return A deserialized object */ - T deserialize(JSONValue jsonValue, T target, ConnectorMap idMapper, + T deserialize(Type type, JSONValue jsonValue, ApplicationConnection connection); /** diff --git a/src/com/vaadin/terminal/gwt/client/communication/JsonDecoder.java b/src/com/vaadin/terminal/gwt/client/communication/JsonDecoder.java index 8df92a141e..8d22481783 100644 --- a/src/com/vaadin/terminal/gwt/client/communication/JsonDecoder.java +++ b/src/com/vaadin/terminal/gwt/client/communication/JsonDecoder.java @@ -49,26 +49,25 @@ public class JsonDecoder { * @return decoded value (does not contain JSON types) */ public static Object decodeValue(JSONArray jsonArray, Object target, - ConnectorMap idMapper, ApplicationConnection connection) { + ApplicationConnection connection) { String type = ((JSONString) jsonArray.get(0)).stringValue(); - return decodeValue(type, jsonArray.get(1), target, idMapper, connection); + return decodeValue(type, jsonArray.get(1), target, connection); } private static Object decodeValue(String variableType, JSONValue value, - Object target, ConnectorMap idMapper, - ApplicationConnection connection) { + Object target, ApplicationConnection connection) { Object val = null; // TODO type checks etc. if (JsonEncoder.VTYPE_NULL.equals(variableType)) { val = null; } else if (JsonEncoder.VTYPE_ARRAY.equals(variableType)) { - val = decodeArray((JSONArray) value, idMapper, connection); + val = decodeArray((JSONArray) value, connection); } else if (JsonEncoder.VTYPE_MAP.equals(variableType)) { - val = decodeMap((JSONObject) value, idMapper, connection); + val = decodeMap((JSONObject) value, connection); } else if (JsonEncoder.VTYPE_LIST.equals(variableType)) { - val = decodeList((JSONArray) value, idMapper, connection); + val = decodeList((JSONArray) value, connection); } else if (JsonEncoder.VTYPE_SET.equals(variableType)) { - val = decodeSet((JSONArray) value, idMapper, connection); + val = decodeSet((JSONArray) value, connection); } else if (JsonEncoder.VTYPE_STRINGARRAY.equals(variableType)) { val = decodeStringArray((JSONArray) value); } else if (JsonEncoder.VTYPE_STRING.equals(variableType)) { @@ -89,39 +88,44 @@ public class JsonDecoder { // TODO handle properly val = Boolean.valueOf(String.valueOf(value)); } else if (JsonEncoder.VTYPE_CONNECTOR.equals(variableType)) { - val = idMapper.getConnector(((JSONString) value).stringValue()); + val = ConnectorMap.get(connection).getConnector( + ((JSONString) value).stringValue()); } else { - return decodeObject(variableType, value, target, idMapper, + return decodeObject(new Type(variableType, null), value, target, connection); } return val; } - private static Object decodeObject(String variableType, - JSONValue encodedValue, Object target, ConnectorMap idMapper, - ApplicationConnection connection) { + private static Object decodeObject(Type type, JSONValue encodedValue, + Object target, ApplicationConnection connection) { // object, class name as type JSONSerializer serializer = connection.getSerializerMap() - .getSerializer(variableType); + .getSerializer(type.getBaseTypeName()); // TODO handle case with no serializer found - Object object = serializer.deserialize(encodedValue, target, idMapper, - connection); - return object; + + if (target != null && serializer instanceof DiffJSONSerializer) { + DiffJSONSerializer diffSerializer = (DiffJSONSerializer) serializer; + diffSerializer.update(target, type, encodedValue, connection); + return target; + } else { + Object object = serializer.deserialize(type, encodedValue, + connection); + return object; + } } private static Map decodeMap(JSONObject jsonMap, - ConnectorMap idMapper, ApplicationConnection connection) { + ApplicationConnection connection) { HashMap map = new HashMap(); Iterator it = jsonMap.keySet().iterator(); while (it.hasNext()) { String key = it.next(); JSONArray encodedKey = (JSONArray) JSONParser.parseStrict(key); JSONArray encodedValue = (JSONArray) jsonMap.get(key); - Object decodedKey = decodeValue(encodedKey, null, idMapper, - connection); - Object decodedValue = decodeValue(encodedValue, null, idMapper, - connection); + Object decodedKey = decodeValue(encodedKey, null, connection); + Object decodedValue = decodeValue(encodedValue, null, connection); map.put(decodedKey, decodedValue); } return map; @@ -137,32 +141,31 @@ public class JsonDecoder { } private static Object[] decodeArray(JSONArray jsonArray, - ConnectorMap idMapper, ApplicationConnection connection) { - List list = decodeList(jsonArray, idMapper, connection); + ApplicationConnection connection) { + List list = decodeList(jsonArray, connection); return list.toArray(new Object[list.size()]); } private static List decodeList(JSONArray jsonArray, - ConnectorMap idMapper, ApplicationConnection connection) { + ApplicationConnection connection) { List tokens = new ArrayList(); - decodeIntoCollection(jsonArray, idMapper, connection, tokens); + decodeIntoCollection(jsonArray, connection, tokens); return tokens; } private static Set decodeSet(JSONArray jsonArray, - ConnectorMap idMapper, ApplicationConnection connection) { + ApplicationConnection connection) { Set tokens = new HashSet(); - decodeIntoCollection(jsonArray, idMapper, connection, tokens); + decodeIntoCollection(jsonArray, connection, tokens); return tokens; } private static void decodeIntoCollection(JSONArray jsonArray, - ConnectorMap idMapper, ApplicationConnection connection, - Collection tokens) { + ApplicationConnection connection, Collection tokens) { for (int i = 0; i < jsonArray.size(); ++i) { // each entry always has two elements: type and value JSONArray entryArray = (JSONArray) jsonArray.get(i); - tokens.add(decodeValue(entryArray, null, idMapper, connection)); + tokens.add(decodeValue(entryArray, null, connection)); } } } diff --git a/src/com/vaadin/terminal/gwt/client/communication/URLReference_Serializer.java b/src/com/vaadin/terminal/gwt/client/communication/URLReference_Serializer.java index 2ee7df7f6d..1ae8cc4755 100644 --- a/src/com/vaadin/terminal/gwt/client/communication/URLReference_Serializer.java +++ b/src/com/vaadin/terminal/gwt/client/communication/URLReference_Serializer.java @@ -12,14 +12,14 @@ import com.vaadin.terminal.gwt.client.ConnectorMap; public class URLReference_Serializer implements JSONSerializer { - public URLReference deserialize(JSONValue jsonValue, URLReference target, - ConnectorMap idMapper, ApplicationConnection connection) { + public URLReference deserialize(Type type, JSONValue jsonValue, + ApplicationConnection connection) { URLReference reference = GWT.create(URLReference.class); JSONObject json = (JSONObject) jsonValue; if (json.containsKey("URL")) { JSONArray jsonURL = (JSONArray) json.get("URL"); String URL = (String) JsonDecoder.decodeValue(jsonURL, null, - idMapper, connection); + connection); reference.setURL(connection.translateVaadinUri(URL)); } return reference; diff --git a/src/com/vaadin/terminal/gwt/widgetsetutils/SerializerGenerator.java b/src/com/vaadin/terminal/gwt/widgetsetutils/SerializerGenerator.java index bc031f4bdb..6aa6b073ee 100644 --- a/src/com/vaadin/terminal/gwt/widgetsetutils/SerializerGenerator.java +++ b/src/com/vaadin/terminal/gwt/widgetsetutils/SerializerGenerator.java @@ -30,6 +30,7 @@ import com.google.gwt.user.rebind.ClassSourceFileComposerFactory; import com.google.gwt.user.rebind.SourceWriter; import com.vaadin.terminal.gwt.client.ApplicationConnection; import com.vaadin.terminal.gwt.client.ConnectorMap; +import com.vaadin.terminal.gwt.client.communication.DiffJSONSerializer; import com.vaadin.terminal.gwt.client.communication.JSONSerializer; import com.vaadin.terminal.gwt.client.communication.JsonDecoder; import com.vaadin.terminal.gwt.client.communication.JsonEncoder; @@ -107,13 +108,20 @@ public class SerializerGenerator extends Generator { serializerClassName); composer.addImport(GWT.class.getName()); composer.addImport(JSONArray.class.getName()); + composer.addImport(com.vaadin.terminal.gwt.client.communication.Type.class + .getName()); // composer.addImport(JSONObject.class.getName()); // composer.addImport(VPaintableMap.class.getName()); composer.addImport(JsonDecoder.class.getName()); // composer.addImport(VaadinSerializer.class.getName()); - composer.addImplementedInterface(JSONSerializer.class.getName() + "<" - + beanQualifiedSourceName + ">"); + if (isEnum) { + composer.addImplementedInterface(JSONSerializer.class.getName() + + "<" + beanQualifiedSourceName + ">"); + } else { + composer.addImplementedInterface(DiffJSONSerializer.class.getName() + + "<" + beanQualifiedSourceName + ">"); + } SourceWriter sourceWriter = composer.createSourceWriter(context, printWriter); @@ -138,20 +146,39 @@ public class SerializerGenerator extends Generator { writeBeanSerializer(logger, sourceWriter, beanType); } // } + sourceWriter.outdent(); sourceWriter.println("}"); + sourceWriter.println(); + + // Updater + // public void update(T target, Type type, JSONValue jsonValue, + // ApplicationConnection connection); + if (!isEnum) { + sourceWriter.println("public void update(" + + beanQualifiedSourceName + " target, Type type, " + + JSONValue.class.getName() + " jsonValue, " + + ApplicationConnection.class.getName() + " connection) {"); + sourceWriter.indent(); + + writeBeanDeserializer(logger, sourceWriter, beanType, true); + + sourceWriter.outdent(); + sourceWriter.println("}"); + } // Deserializer + // T deserialize(Type type, JSONValue jsonValue, ApplicationConnection + // connection); sourceWriter.println("public " + beanQualifiedSourceName - + " deserialize(" + JSONValue.class.getName() + " jsonValue, " - + beanQualifiedSourceName + " target, " - + ConnectorMap.class.getName() + " idMapper, " - + ApplicationConnection.class.getName() + " connection) {"); + + " deserialize(Type type, " + JSONValue.class.getName() + + " jsonValue, " + ApplicationConnection.class.getName() + + " connection) {"); sourceWriter.indent(); if (isEnum) { writeEnumDeserializer(logger, sourceWriter, beanType.isEnum()); } else { - writeBeanDeserializer(logger, sourceWriter, beanType); + writeBeanDeserializer(logger, sourceWriter, beanType, false); } sourceWriter.println("}"); sourceWriter.outdent(); @@ -183,18 +210,14 @@ public class SerializerGenerator extends Generator { } private void writeBeanDeserializer(TreeLogger logger, - SourceWriter sourceWriter, JClassType beanType) { + SourceWriter sourceWriter, JClassType beanType, boolean update) { String beanQualifiedSourceName = beanType.getQualifiedSourceName(); - // if (target == null) { - sourceWriter.println("if (target == null) {"); - sourceWriter.indent(); - - // target = GWT.create(VButtonState.class); - sourceWriter.println("target = GWT.create(" + beanQualifiedSourceName - + ".class);"); - sourceWriter.outdent(); - sourceWriter.println("}"); + if (!update) { + sourceWriter.println(beanQualifiedSourceName + + " target = GWT.create(" + beanQualifiedSourceName + + ".class);"); + } // JSONOBject json = (JSONObject)jsonValue; sourceWriter.println(JSONObject.class.getName() + " json = (" @@ -230,37 +253,26 @@ public class SerializerGenerator extends Generator { fieldType = setterParameterType.getQualifiedSourceName(); } - // String referenceValue; - sourceWriter.println(fieldType + " referenceValue;"); - // if (target == null) { - sourceWriter.println("if (target == null) {"); - sourceWriter.indent(); - // referenceValue = null; - sourceWriter.println("referenceValue = null;"); - // } else { - sourceWriter.println("} else {"); - // referenceValue = target.getHeight(); - sourceWriter.println("referenceValue = target." + getterName - + "();"); - // } - sourceWriter.outdent(); - sourceWriter.println("}"); + // String referenceValue = target.getHeight(); + sourceWriter.println(fieldType + " referenceValue = target." + + getterName + "();"); // target.setHeight((String) // JsonDecoder.decodeValue(jsonFieldValue,referenceValue, idMapper, // connection)); sourceWriter.println("target." + setterName + "((" + fieldType + ") " + JsonDecoder.class.getName() + ".decodeValue(" - + jsonFieldName - + ", referenceValue, idMapper, connection));"); + + jsonFieldName + ", referenceValue, connection));"); // } ... end of if contains sourceWriter.println("}"); sourceWriter.outdent(); } - // return target; - sourceWriter.println("return target;"); + if (!update) { + // return target; + sourceWriter.println("return target;"); + } } -- cgit v1.2.3 From 3702e37192c36203b74cb2694ba90a62266be079 Mon Sep 17 00:00:00 2001 From: Leif Åstrand Date: Fri, 1 Jun 2012 16:51:42 +0300 Subject: Pass declared types to JsonDecoder and use them (#8677) --- .../terminal/gwt/client/ApplicationConnection.java | 19 +++- .../gwt/client/communication/JsonDecoder.java | 126 ++++++++++----------- .../communication/URLReference_Serializer.java | 5 +- .../GeneratedRpcMethodProviderGenerator.java | 12 +- .../gwt/widgetsetutils/SerializerGenerator.java | 11 +- 5 files changed, 95 insertions(+), 78 deletions(-) diff --git a/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java b/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java index c7ec5236b0..bf5c34f3f3 100644 --- a/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java +++ b/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java @@ -44,7 +44,9 @@ import com.vaadin.terminal.gwt.client.communication.JsonEncoder; import com.vaadin.terminal.gwt.client.communication.MethodInvocation; import com.vaadin.terminal.gwt.client.communication.RpcManager; import com.vaadin.terminal.gwt.client.communication.SerializerMap; +import com.vaadin.terminal.gwt.client.communication.SharedState; import com.vaadin.terminal.gwt.client.communication.StateChangeEvent; +import com.vaadin.terminal.gwt.client.communication.Type; import com.vaadin.terminal.gwt.client.communication.UidlValue; import com.vaadin.terminal.gwt.client.ui.AbstractComponentConnector; import com.vaadin.terminal.gwt.client.ui.VContextMenu; @@ -1411,8 +1413,9 @@ public class ApplicationConnection { JSONArray stateDataAndType = new JSONArray( states.getJavaScriptObject(connectorId)); - JsonDecoder.decodeValue(stateDataAndType, - connector.getState(), + SharedState state = connector.getState(); + JsonDecoder.decodeValue(new Type(state.getClass() + .getName(), null), stateDataAndType, state, ApplicationConnection.this); StateChangeEvent event = GWT @@ -1575,13 +1578,19 @@ public class ApplicationConnection { String interfaceName = ((JSONString) rpcCall.get(1)).stringValue(); String methodName = ((JSONString) rpcCall.get(2)).stringValue(); JSONArray parametersJson = (JSONArray) rpcCall.get(3); + + MethodInvocation methodInvocation = new MethodInvocation(connectorId, + interfaceName, methodName); + Type[] parameterTypes = rpcManager.getParameterTypes(methodInvocation); + Object[] parameters = new Object[parametersJson.size()]; for (int j = 0; j < parametersJson.size(); ++j) { - parameters[j] = JsonDecoder.decodeValue( + parameters[j] = JsonDecoder.decodeValue(parameterTypes[j], (JSONArray) parametersJson.get(j), null, this); } - return new MethodInvocation(connectorId, interfaceName, methodName, - parameters); + + methodInvocation.setParameters(parameters); + return methodInvocation; } // Redirect browser, null reloads current page diff --git a/src/com/vaadin/terminal/gwt/client/communication/JsonDecoder.java b/src/com/vaadin/terminal/gwt/client/communication/JsonDecoder.java index 8d22481783..cd255ada95 100644 --- a/src/com/vaadin/terminal/gwt/client/communication/JsonDecoder.java +++ b/src/com/vaadin/terminal/gwt/client/communication/JsonDecoder.java @@ -19,6 +19,7 @@ import com.google.gwt.json.client.JSONParser; import com.google.gwt.json.client.JSONString; import com.google.gwt.json.client.JSONValue; import com.vaadin.terminal.gwt.client.ApplicationConnection; +import com.vaadin.terminal.gwt.client.Connector; import com.vaadin.terminal.gwt.client.ConnectorMap; import com.vaadin.terminal.gwt.client.ServerConnector; @@ -48,75 +49,72 @@ public class JsonDecoder { * reference to the current ApplicationConnection * @return decoded value (does not contain JSON types) */ - public static Object decodeValue(JSONArray jsonArray, Object target, - ApplicationConnection connection) { - String type = ((JSONString) jsonArray.get(0)).stringValue(); + public static Object decodeValue(Type type, JSONArray jsonArray, + Object target, ApplicationConnection connection) { return decodeValue(type, jsonArray.get(1), target, connection); } - private static Object decodeValue(String variableType, JSONValue value, + private static Object decodeValue(Type type, JSONValue jsonValue, Object target, ApplicationConnection connection) { - Object val = null; - // TODO type checks etc. - if (JsonEncoder.VTYPE_NULL.equals(variableType)) { - val = null; - } else if (JsonEncoder.VTYPE_ARRAY.equals(variableType)) { - val = decodeArray((JSONArray) value, connection); - } else if (JsonEncoder.VTYPE_MAP.equals(variableType)) { - val = decodeMap((JSONObject) value, connection); - } else if (JsonEncoder.VTYPE_LIST.equals(variableType)) { - val = decodeList((JSONArray) value, connection); - } else if (JsonEncoder.VTYPE_SET.equals(variableType)) { - val = decodeSet((JSONArray) value, connection); - } else if (JsonEncoder.VTYPE_STRINGARRAY.equals(variableType)) { - val = decodeStringArray((JSONArray) value); - } else if (JsonEncoder.VTYPE_STRING.equals(variableType)) { - val = ((JSONString) value).stringValue(); - } else if (JsonEncoder.VTYPE_INTEGER.equals(variableType)) { - // TODO handle properly - val = Integer.valueOf(String.valueOf(value)); - } else if (JsonEncoder.VTYPE_LONG.equals(variableType)) { + + // Null is null, regardless of type + if (jsonValue.isNull() != null) { + return null; + } + + String baseTypeName = type.getBaseTypeName(); + if (baseTypeName.endsWith("[]")) { + return decodeArray(type, (JSONArray) jsonValue, connection); + } else if (Map.class.getName().equals(baseTypeName) + || HashMap.class.getName().equals(baseTypeName)) { + return decodeMap(type, (JSONObject) jsonValue, connection); + } else if (List.class.getName().equals(baseTypeName) + || ArrayList.class.getName().equals(baseTypeName)) { + return decodeList(type, (JSONArray) jsonValue, connection); + } else if (Set.class.getName().equals(baseTypeName)) { + return decodeSet(type, (JSONArray) jsonValue, connection); + } else if (String.class.getName().equals(baseTypeName)) { + return ((JSONString) jsonValue).stringValue(); + } else if (Integer.class.getName().equals(baseTypeName)) { + return Integer.valueOf(String.valueOf(jsonValue)); + } else if (Long.class.getName().equals(baseTypeName)) { // TODO handle properly - val = Long.valueOf(String.valueOf(value)); - } else if (JsonEncoder.VTYPE_FLOAT.equals(variableType)) { + return Long.valueOf(String.valueOf(jsonValue)); + } else if (Float.class.getName().equals(baseTypeName)) { // TODO handle properly - val = Float.valueOf(String.valueOf(value)); - } else if (JsonEncoder.VTYPE_DOUBLE.equals(variableType)) { + return Float.valueOf(String.valueOf(jsonValue)); + } else if (Double.class.getName().equals(baseTypeName)) { // TODO handle properly - val = Double.valueOf(String.valueOf(value)); - } else if (JsonEncoder.VTYPE_BOOLEAN.equals(variableType)) { + return Double.valueOf(String.valueOf(jsonValue)); + } else if (Boolean.class.getName().equals(baseTypeName)) { // TODO handle properly - val = Boolean.valueOf(String.valueOf(value)); - } else if (JsonEncoder.VTYPE_CONNECTOR.equals(variableType)) { - val = ConnectorMap.get(connection).getConnector( - ((JSONString) value).stringValue()); + return Boolean.valueOf(String.valueOf(jsonValue)); + } else if (Connector.class.getName().equals(baseTypeName)) { + return ConnectorMap.get(connection).getConnector( + ((JSONString) jsonValue).stringValue()); } else { - return decodeObject(new Type(variableType, null), value, target, - connection); + return decodeObject(type, jsonValue, target, connection); } - - return val; } - private static Object decodeObject(Type type, JSONValue encodedValue, + private static Object decodeObject(Type type, JSONValue jsonValue, Object target, ApplicationConnection connection) { - // object, class name as type JSONSerializer serializer = connection.getSerializerMap() .getSerializer(type.getBaseTypeName()); // TODO handle case with no serializer found + // Currently getSerializer throws exception if not found if (target != null && serializer instanceof DiffJSONSerializer) { DiffJSONSerializer diffSerializer = (DiffJSONSerializer) serializer; - diffSerializer.update(target, type, encodedValue, connection); + diffSerializer.update(target, type, jsonValue, connection); return target; } else { - Object object = serializer.deserialize(type, encodedValue, - connection); + Object object = serializer.deserialize(type, jsonValue, connection); return object; } } - private static Map decodeMap(JSONObject jsonMap, + private static Map decodeMap(Type type, JSONObject jsonMap, ApplicationConnection connection) { HashMap map = new HashMap(); Iterator it = jsonMap.keySet().iterator(); @@ -124,48 +122,48 @@ public class JsonDecoder { String key = it.next(); JSONArray encodedKey = (JSONArray) JSONParser.parseStrict(key); JSONArray encodedValue = (JSONArray) jsonMap.get(key); - Object decodedKey = decodeValue(encodedKey, null, connection); - Object decodedValue = decodeValue(encodedValue, null, connection); + Object decodedKey = decodeValue(type.getParameterTypes()[0], + encodedKey, null, connection); + Object decodedValue = decodeValue(type.getParameterTypes()[1], + encodedValue, null, connection); map.put(decodedKey, decodedValue); } return map; } - private static String[] decodeStringArray(JSONArray jsonArray) { - int size = jsonArray.size(); - List tokens = new ArrayList(size); - for (int i = 0; i < size; ++i) { - tokens.add(String.valueOf(jsonArray.get(i))); - } - return tokens.toArray(new String[tokens.size()]); - } - - private static Object[] decodeArray(JSONArray jsonArray, + private static Object[] decodeArray(Type type, JSONArray jsonArray, ApplicationConnection connection) { - List list = decodeList(jsonArray, connection); + String arrayTypeName = type.getBaseTypeName(); + String chldTypeName = arrayTypeName.substring(0, + arrayTypeName.length() - 2); + List list = decodeList(new Type(chldTypeName, null), jsonArray, + connection); return list.toArray(new Object[list.size()]); } - private static List decodeList(JSONArray jsonArray, + private static List decodeList(Type type, JSONArray jsonArray, ApplicationConnection connection) { List tokens = new ArrayList(); - decodeIntoCollection(jsonArray, connection, tokens); + decodeIntoCollection(type.getParameterTypes()[0], jsonArray, + connection, tokens); return tokens; } - private static Set decodeSet(JSONArray jsonArray, + private static Set decodeSet(Type type, JSONArray jsonArray, ApplicationConnection connection) { Set tokens = new HashSet(); - decodeIntoCollection(jsonArray, connection, tokens); + decodeIntoCollection(type.getParameterTypes()[0], jsonArray, + connection, tokens); return tokens; } - private static void decodeIntoCollection(JSONArray jsonArray, - ApplicationConnection connection, Collection tokens) { + private static void decodeIntoCollection(Type childType, + JSONArray jsonArray, ApplicationConnection connection, + Collection tokens) { for (int i = 0; i < jsonArray.size(); ++i) { // each entry always has two elements: type and value JSONArray entryArray = (JSONArray) jsonArray.get(i); - tokens.add(decodeValue(entryArray, null, connection)); + tokens.add(decodeValue(childType, entryArray, null, connection)); } } } diff --git a/src/com/vaadin/terminal/gwt/client/communication/URLReference_Serializer.java b/src/com/vaadin/terminal/gwt/client/communication/URLReference_Serializer.java index 1ae8cc4755..5db487d867 100644 --- a/src/com/vaadin/terminal/gwt/client/communication/URLReference_Serializer.java +++ b/src/com/vaadin/terminal/gwt/client/communication/URLReference_Serializer.java @@ -18,8 +18,9 @@ public class URLReference_Serializer implements JSONSerializer { JSONObject json = (JSONObject) jsonValue; if (json.containsKey("URL")) { JSONArray jsonURL = (JSONArray) json.get("URL"); - String URL = (String) JsonDecoder.decodeValue(jsonURL, null, - connection); + String URL = (String) JsonDecoder.decodeValue( + new Type(String.class.getCanonicalName(), null), jsonURL, + null, connection); reference.setURL(connection.translateVaadinUri(URL)); } return reference; diff --git a/src/com/vaadin/terminal/gwt/widgetsetutils/GeneratedRpcMethodProviderGenerator.java b/src/com/vaadin/terminal/gwt/widgetsetutils/GeneratedRpcMethodProviderGenerator.java index f0db4886e4..ba3dcd85b9 100644 --- a/src/com/vaadin/terminal/gwt/widgetsetutils/GeneratedRpcMethodProviderGenerator.java +++ b/src/com/vaadin/terminal/gwt/widgetsetutils/GeneratedRpcMethodProviderGenerator.java @@ -178,9 +178,15 @@ public class GeneratedRpcMethodProviderGenerator extends Generator { } - private void writeTypeCreator(SourceWriter sourceWriter, JType type) { - sourceWriter.print("new Type(\"" - + type.getErasedType().getQualifiedSourceName() + "\", "); + public static void writeTypeCreator(SourceWriter sourceWriter, JType type) { + String typeName; + if (type.isPrimitive() != null) { + // Used boxed types for primitives + typeName = type.isPrimitive().getQualifiedBoxedSourceName(); + } else { + typeName = type.getErasedType().getQualifiedBinaryName(); + } + sourceWriter.print("new Type(\"" + typeName + "\", "); JParameterizedType parameterized = type.isParameterized(); if (parameterized != null) { sourceWriter.print("new Type[] {"); diff --git a/src/com/vaadin/terminal/gwt/widgetsetutils/SerializerGenerator.java b/src/com/vaadin/terminal/gwt/widgetsetutils/SerializerGenerator.java index 6aa6b073ee..8e34e28999 100644 --- a/src/com/vaadin/terminal/gwt/widgetsetutils/SerializerGenerator.java +++ b/src/com/vaadin/terminal/gwt/widgetsetutils/SerializerGenerator.java @@ -260,13 +260,16 @@ public class SerializerGenerator extends Generator { // target.setHeight((String) // JsonDecoder.decodeValue(jsonFieldValue,referenceValue, idMapper, // connection)); - sourceWriter.println("target." + setterName + "((" + fieldType - + ") " + JsonDecoder.class.getName() + ".decodeValue(" - + jsonFieldName + ", referenceValue, connection));"); + sourceWriter.print("target." + setterName + "((" + fieldType + ") " + + JsonDecoder.class.getName() + ".decodeValue("); + GeneratedRpcMethodProviderGenerator.writeTypeCreator(sourceWriter, + setterParameterType); + sourceWriter.println(", " + jsonFieldName + + ", referenceValue, connection));"); // } ... end of if contains - sourceWriter.println("}"); sourceWriter.outdent(); + sourceWriter.println("}"); } if (!update) { -- cgit v1.2.3 From 7468c8261d186fbfb35586571c3a0728d31116e5 Mon Sep 17 00:00:00 2001 From: Leif Åstrand Date: Tue, 5 Jun 2012 11:21:20 +0300 Subject: Don't send type info from server to client (#8879) --- .../terminal/gwt/client/ApplicationConnection.java | 5 +- .../gwt/client/communication/JsonDecoder.java | 23 ++---- .../communication/URLReference_Serializer.java | 7 +- .../gwt/server/AbstractCommunicationManager.java | 7 +- src/com/vaadin/terminal/gwt/server/JsonCodec.java | 84 +++++++--------------- .../gwt/widgetsetutils/SerializerGenerator.java | 9 ++- .../terminal/gwt/server/JSONSerializerTest.java | 11 ++- 7 files changed, 52 insertions(+), 94 deletions(-) diff --git a/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java b/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java index bf5c34f3f3..1b902e8e40 100644 --- a/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java +++ b/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java @@ -28,6 +28,7 @@ import com.google.gwt.http.client.RequestCallback; import com.google.gwt.http.client.RequestException; import com.google.gwt.http.client.Response; import com.google.gwt.json.client.JSONArray; +import com.google.gwt.json.client.JSONObject; import com.google.gwt.json.client.JSONString; import com.google.gwt.regexp.shared.MatchResult; import com.google.gwt.regexp.shared.RegExp; @@ -1410,7 +1411,7 @@ public class ApplicationConnection { .getConnector(connectorId); if (null != connector) { - JSONArray stateDataAndType = new JSONArray( + JSONObject stateDataAndType = new JSONObject( states.getJavaScriptObject(connectorId)); SharedState state = connector.getState(); @@ -1586,7 +1587,7 @@ public class ApplicationConnection { Object[] parameters = new Object[parametersJson.size()]; for (int j = 0; j < parametersJson.size(); ++j) { parameters[j] = JsonDecoder.decodeValue(parameterTypes[j], - (JSONArray) parametersJson.get(j), null, this); + parametersJson.get(j), null, this); } methodInvocation.setParameters(parameters); diff --git a/src/com/vaadin/terminal/gwt/client/communication/JsonDecoder.java b/src/com/vaadin/terminal/gwt/client/communication/JsonDecoder.java index cd255ada95..c7b33a70db 100644 --- a/src/com/vaadin/terminal/gwt/client/communication/JsonDecoder.java +++ b/src/com/vaadin/terminal/gwt/client/communication/JsonDecoder.java @@ -21,7 +21,6 @@ import com.google.gwt.json.client.JSONValue; import com.vaadin.terminal.gwt.client.ApplicationConnection; import com.vaadin.terminal.gwt.client.Connector; import com.vaadin.terminal.gwt.client.ConnectorMap; -import com.vaadin.terminal.gwt.client.ServerConnector; /** * Client side decoder for decodeing shared state and other values from JSON @@ -40,21 +39,13 @@ public class JsonDecoder { * Decode a JSON array with two elements (type and value) into a client-side * type, recursively if necessary. * - * @param jsonArray - * JSON array with two elements - * @param idMapper - * mapper between connector ID and {@link ServerConnector} - * objects + * @param jsonValue + * JSON value with encoded data * @param connection * reference to the current ApplicationConnection * @return decoded value (does not contain JSON types) */ - public static Object decodeValue(Type type, JSONArray jsonArray, - Object target, ApplicationConnection connection) { - return decodeValue(type, jsonArray.get(1), target, connection); - } - - private static Object decodeValue(Type type, JSONValue jsonValue, + public static Object decodeValue(Type type, JSONValue jsonValue, Object target, ApplicationConnection connection) { // Null is null, regardless of type @@ -120,8 +111,8 @@ public class JsonDecoder { Iterator it = jsonMap.keySet().iterator(); while (it.hasNext()) { String key = it.next(); - JSONArray encodedKey = (JSONArray) JSONParser.parseStrict(key); - JSONArray encodedValue = (JSONArray) jsonMap.get(key); + JSONValue encodedKey = JSONParser.parseStrict(key); + JSONValue encodedValue = jsonMap.get(key); Object decodedKey = decodeValue(type.getParameterTypes()[0], encodedKey, null, connection); Object decodedValue = decodeValue(type.getParameterTypes()[1], @@ -162,8 +153,8 @@ public class JsonDecoder { Collection tokens) { for (int i = 0; i < jsonArray.size(); ++i) { // each entry always has two elements: type and value - JSONArray entryArray = (JSONArray) jsonArray.get(i); - tokens.add(decodeValue(childType, entryArray, null, connection)); + JSONValue entryValue = jsonArray.get(i); + tokens.add(decodeValue(childType, entryValue, null, connection)); } } } diff --git a/src/com/vaadin/terminal/gwt/client/communication/URLReference_Serializer.java b/src/com/vaadin/terminal/gwt/client/communication/URLReference_Serializer.java index 5db487d867..f6108bbfa8 100644 --- a/src/com/vaadin/terminal/gwt/client/communication/URLReference_Serializer.java +++ b/src/com/vaadin/terminal/gwt/client/communication/URLReference_Serializer.java @@ -4,7 +4,6 @@ package com.vaadin.terminal.gwt.client.communication; import com.google.gwt.core.client.GWT; -import com.google.gwt.json.client.JSONArray; import com.google.gwt.json.client.JSONObject; import com.google.gwt.json.client.JSONValue; import com.vaadin.terminal.gwt.client.ApplicationConnection; @@ -17,10 +16,10 @@ public class URLReference_Serializer implements JSONSerializer { URLReference reference = GWT.create(URLReference.class); JSONObject json = (JSONObject) jsonValue; if (json.containsKey("URL")) { - JSONArray jsonURL = (JSONArray) json.get("URL"); + JSONValue jsonURL = json.get("URL"); String URL = (String) JsonDecoder.decodeValue( - new Type(String.class.getCanonicalName(), null), jsonURL, - null, connection); + new Type(String.class.getName(), null), jsonURL, null, + connection); reference.setURL(connection.translateVaadinUri(URL)); } return reference; diff --git a/src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java b/src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java index b32525a703..d6feba9dc0 100644 --- a/src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java +++ b/src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java @@ -846,11 +846,10 @@ public abstract class AbstractCommunicationManager implements Serializable { + stateType.getName()); } } - JSONArray stateJsonArray = JsonCodec.encode(state, - referenceState, stateType, application); + Object stateJson = JsonCodec.encode(state, referenceState, + stateType, application); - sharedStates - .put(connector.getConnectorId(), stateJsonArray); + sharedStates.put(connector.getConnectorId(), stateJson); } catch (JSONException e) { throw new PaintException( "Failed to serialize shared state for connector " diff --git a/src/com/vaadin/terminal/gwt/server/JsonCodec.java b/src/com/vaadin/terminal/gwt/server/JsonCodec.java index b853c90a3b..e76a3d3f3a 100644 --- a/src/com/vaadin/terminal/gwt/server/JsonCodec.java +++ b/src/com/vaadin/terminal/gwt/server/JsonCodec.java @@ -250,7 +250,8 @@ public class JsonCodec implements Serializable { Iterator it = jsonMap.keys(); while (it.hasNext()) { String key = it.next(); - Object encodedKey = new JSONTokener(key).nextValue(); + String keyString = (String) new JSONTokener(key).nextValue(); + Object encodedKey = new JSONTokener(keyString).nextValue(); Object encodedValue = jsonMap.get(key); Object decodedKey = decodeParametrizedType(targetType, @@ -394,55 +395,43 @@ public class JsonCodec implements Serializable { } } - @Deprecated - private static JSONArray encode(Object value, Application application) - throws JSONException { - return encode(value, null, null, application); - } - - public static JSONArray encode(Object value, Object referenceValue, + public static Object encode(Object value, Object referenceValue, Type valueType, Application application) throws JSONException { - if (null == value) { - return encodeNull(); + if (valueType == null) { + throw new IllegalArgumentException("type must be defined"); } - if (valueType == null) { - valueType = value.getClass(); + if (null == value) { + return encodeNull(); } - String internalTransportType = getInternalTransportType(valueType); if (value instanceof String[]) { String[] array = (String[]) value; JSONArray jsonArray = new JSONArray(); for (int i = 0; i < array.length; ++i) { jsonArray.put(array[i]); } - return combineTypeAndValue(JsonEncoder.VTYPE_STRINGARRAY, jsonArray); + return jsonArray; } else if (value instanceof String) { - return combineTypeAndValue(JsonEncoder.VTYPE_STRING, value); + return value; } else if (value instanceof Boolean) { - return combineTypeAndValue(JsonEncoder.VTYPE_BOOLEAN, value); + return value; } else if (value instanceof Number) { - return combineTypeAndValue(internalTransportType, value); + return value; } else if (value instanceof Collection) { - if (internalTransportType == null) { - throw new RuntimeException( - "Unable to serialize unsupported type: " + valueType); - } Collection collection = (Collection) value; JSONArray jsonArray = encodeCollection(valueType, collection, application); - - return combineTypeAndValue(internalTransportType, jsonArray); + return jsonArray; } else if (value instanceof Object[]) { Object[] array = (Object[]) value; JSONArray jsonArray = encodeArrayContents(array, application); - return combineTypeAndValue(JsonEncoder.VTYPE_ARRAY, jsonArray); + return jsonArray; } else if (value instanceof Map) { JSONObject jsonMap = encodeMap(valueType, (Map) value, application); - return combineTypeAndValue(JsonEncoder.VTYPE_MAP, jsonMap); + return jsonMap; } else if (value instanceof Connector) { Connector connector = (Connector) value; if (value instanceof Component @@ -450,24 +439,18 @@ public class JsonCodec implements Serializable { .isVisible((Component) value))) { return encodeNull(); } - return combineTypeAndValue(JsonEncoder.VTYPE_CONNECTOR, - connector.getConnectorId()); - } else if (internalTransportType != null) { - return combineTypeAndValue(internalTransportType, - String.valueOf(value)); + return connector.getConnectorId(); } else if (value instanceof Enum) { - return encodeEnum((Enum) value, application); + return encodeEnum((Enum) value, application); } else { // Any object that we do not know how to encode we encode by looping // through fields - return combineTypeAndValue( - getCustomTransportType((Class) valueType), - encodeObject(value, referenceValue, application)); + return encodeObject(value, referenceValue, application); } } - private static JSONArray encodeNull() { - return combineTypeAndValue(JsonEncoder.VTYPE_NULL, JSONObject.NULL); + private static Object encodeNull() { + return JSONObject.NULL; } private static Object encodeObject(Object value, Object referenceValue, @@ -531,10 +514,9 @@ public class JsonCodec implements Serializable { return false; } - private static JSONArray encodeEnum(Enum e, Application application) + private static String encodeEnum(Enum e, Application application) throws JSONException { - String enumIdentifier = e.name(); - return combineTypeAndValue(e.getClass().getName(), enumIdentifier); + return e.name(); } private static JSONArray encodeArrayContents(Object[] array, @@ -556,15 +538,15 @@ public class JsonCodec implements Serializable { return jsonArray; } - private static JSONArray encodeChild(Type targetType, int typeIndex, - Object o, Application application) throws JSONException { + private static Object encodeChild(Type targetType, int typeIndex, Object o, + Application application) throws JSONException { if (targetType instanceof ParameterizedType) { Type childType = ((ParameterizedType) targetType) .getActualTypeArguments()[typeIndex]; // Encode using the given type return encode(o, null, childType, application); } else { - return encode(o, application); + throw new JSONException("Collection is missing generics"); } } @@ -582,25 +564,13 @@ public class JsonCodec implements Serializable { JSONObject jsonMap = new JSONObject(); for (Object mapKey : map.keySet()) { Object mapValue = map.get(mapKey); - JSONArray encodedKey = encode(mapKey, null, keyType, application); - JSONArray encodedValue = encode(mapValue, null, valueType, - application); - jsonMap.put(encodedKey.toString(), encodedValue); + Object encodedKey = encode(mapKey, null, keyType, application); + Object encodedValue = encode(mapValue, null, valueType, application); + jsonMap.put(JSONObject.quote(encodedKey.toString()), encodedValue); } return jsonMap; } - private static JSONArray combineTypeAndValue(String type, Object value) { - if (type == null) { - throw new RuntimeException("Type for value " + value - + " cannot be null!"); - } - JSONArray outerArray = new JSONArray(); - outerArray.put(type); - outerArray.put(value); - return outerArray; - } - /** * Gets the transport type for the given class. Returns null if no transport * type can be found. diff --git a/src/com/vaadin/terminal/gwt/widgetsetutils/SerializerGenerator.java b/src/com/vaadin/terminal/gwt/widgetsetutils/SerializerGenerator.java index 8e34e28999..6e99089434 100644 --- a/src/com/vaadin/terminal/gwt/widgetsetutils/SerializerGenerator.java +++ b/src/com/vaadin/terminal/gwt/widgetsetutils/SerializerGenerator.java @@ -22,7 +22,6 @@ import com.google.gwt.core.ext.typeinfo.JMethod; import com.google.gwt.core.ext.typeinfo.JPrimitiveType; import com.google.gwt.core.ext.typeinfo.JType; import com.google.gwt.core.ext.typeinfo.TypeOracle; -import com.google.gwt.json.client.JSONArray; import com.google.gwt.json.client.JSONObject; import com.google.gwt.json.client.JSONString; import com.google.gwt.json.client.JSONValue; @@ -107,7 +106,7 @@ public class SerializerGenerator extends Generator { composer = new ClassSourceFileComposerFactory(serializerPackageName, serializerClassName); composer.addImport(GWT.class.getName()); - composer.addImport(JSONArray.class.getName()); + composer.addImport(JSONValue.class.getName()); composer.addImport(com.vaadin.terminal.gwt.client.communication.Type.class .getName()); // composer.addImport(JSONObject.class.getName()); @@ -236,9 +235,9 @@ public class SerializerGenerator extends Generator { + "\")) {"); sourceWriter.indent(); String jsonFieldName = "json_" + fieldName; - // JSONArray json_Height = (JSONArray) json.get("height"); - sourceWriter.println("JSONArray " + jsonFieldName - + " = (JSONArray) json.get(\"" + fieldName + "\");"); + // JSONValue json_Height = json.get("height"); + sourceWriter.println("JSONValue " + jsonFieldName + + " = json.get(\"" + fieldName + "\");"); String fieldType; String getterName = "get" + fieldName; diff --git a/tests/client-side/com/vaadin/terminal/gwt/server/JSONSerializerTest.java b/tests/client-side/com/vaadin/terminal/gwt/server/JSONSerializerTest.java index 926f026b40..fefc2d927c 100644 --- a/tests/client-side/com/vaadin/terminal/gwt/server/JSONSerializerTest.java +++ b/tests/client-side/com/vaadin/terminal/gwt/server/JSONSerializerTest.java @@ -13,7 +13,6 @@ import java.util.Map; import junit.framework.TestCase; -import com.vaadin.external.json.JSONArray; import com.vaadin.terminal.gwt.client.communication.JsonDecoder; import com.vaadin.terminal.gwt.client.communication.JsonEncoder; import com.vaadin.terminal.gwt.client.ui.splitpanel.AbstractSplitPanelState; @@ -43,8 +42,8 @@ public class JSONSerializerTest extends TestCase { stringToStateMap.put("string - state 1", s); stringToStateMap.put("String - state 2", s2); - JSONArray encodedMap = JsonCodec.encode(stringToStateMap, null, - mapType, null); + Object encodedMap = JsonCodec.encode(stringToStateMap, null, mapType, + null); ensureDecodedCorrectly(stringToStateMap, encodedMap, mapType); } @@ -60,13 +59,13 @@ public class JSONSerializerTest extends TestCase { stateToStringMap.put(s, "string - state 1"); stateToStringMap.put(s2, "String - state 2"); - JSONArray encodedMap = JsonCodec.encode(stateToStringMap, null, - mapType, null); + Object encodedMap = JsonCodec.encode(stateToStringMap, null, mapType, + null); ensureDecodedCorrectly(stateToStringMap, encodedMap, mapType); } - private void ensureDecodedCorrectly(Object original, JSONArray encoded, + private void ensureDecodedCorrectly(Object original, Object encoded, Type type) throws Exception { Object serverSideDecoded = JsonCodec.decodeInternalOrCustomType(type, encoded, null); -- cgit v1.2.3 From 351e04dd8e07d41b23231783910ba41852c62145 Mon Sep 17 00:00:00 2001 From: Leif Åstrand Date: Tue, 5 Jun 2012 15:10:57 +0300 Subject: Change map serialization to use same scheme as GWT AutoBean (#8602) --- .../gwt/client/communication/JsonDecoder.java | 86 +++++++++-- .../gwt/client/communication/JsonEncoder.java | 88 +++++++++-- src/com/vaadin/terminal/gwt/server/JsonCodec.java | 165 ++++++++++++++++++--- 3 files changed, 290 insertions(+), 49 deletions(-) diff --git a/src/com/vaadin/terminal/gwt/client/communication/JsonDecoder.java b/src/com/vaadin/terminal/gwt/client/communication/JsonDecoder.java index c7b33a70db..1459d8ee7d 100644 --- a/src/com/vaadin/terminal/gwt/client/communication/JsonDecoder.java +++ b/src/com/vaadin/terminal/gwt/client/communication/JsonDecoder.java @@ -8,14 +8,12 @@ import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; -import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import com.google.gwt.json.client.JSONArray; import com.google.gwt.json.client.JSONObject; -import com.google.gwt.json.client.JSONParser; import com.google.gwt.json.client.JSONString; import com.google.gwt.json.client.JSONValue; import com.vaadin.terminal.gwt.client.ApplicationConnection; @@ -58,7 +56,7 @@ public class JsonDecoder { return decodeArray(type, (JSONArray) jsonValue, connection); } else if (Map.class.getName().equals(baseTypeName) || HashMap.class.getName().equals(baseTypeName)) { - return decodeMap(type, (JSONObject) jsonValue, connection); + return decodeMap(type, jsonValue, connection); } else if (List.class.getName().equals(baseTypeName) || ArrayList.class.getName().equals(baseTypeName)) { return decodeList(type, (JSONArray) jsonValue, connection); @@ -105,20 +103,80 @@ public class JsonDecoder { } } - private static Map decodeMap(Type type, JSONObject jsonMap, + private static Map decodeMap(Type type, JSONValue jsonMap, ApplicationConnection connection) { - HashMap map = new HashMap(); - Iterator it = jsonMap.keySet().iterator(); - while (it.hasNext()) { - String key = it.next(); - JSONValue encodedKey = JSONParser.parseStrict(key); - JSONValue encodedValue = jsonMap.get(key); - Object decodedKey = decodeValue(type.getParameterTypes()[0], - encodedKey, null, connection); - Object decodedValue = decodeValue(type.getParameterTypes()[1], - encodedValue, null, connection); + // Client -> server encodes empty map as an empty array because of + // #8906. Do the same for server -> client to maintain symmetry. + if (jsonMap instanceof JSONArray) { + JSONArray array = (JSONArray) jsonMap; + if (array.size() == 0) { + return new HashMap(); + } + } + + Type keyType = type.getParameterTypes()[0]; + Type valueType = type.getParameterTypes()[1]; + + if (keyType.getBaseTypeName().equals(String.class.getName())) { + return decodeStringMap(valueType, jsonMap, connection); + } else if (keyType.getBaseTypeName().equals(Connector.class.getName())) { + return decodeConnectorMap(valueType, jsonMap, connection); + } else { + return decodeObjectMap(keyType, valueType, jsonMap, connection); + } + } + + private static Map decodeObjectMap(Type keyType, + Type valueType, JSONValue jsonValue, + ApplicationConnection connection) { + Map map = new HashMap(); + + JSONArray mapArray = (JSONArray) jsonValue; + JSONArray keys = (JSONArray) mapArray.get(0); + JSONArray values = (JSONArray) mapArray.get(1); + + assert (keys.size() == values.size()); + + for (int i = 0; i < keys.size(); i++) { + Object decodedKey = decodeValue(keyType, keys.get(i), null, + connection); + Object decodedValue = decodeValue(valueType, values.get(i), null, + connection); + map.put(decodedKey, decodedValue); } + + return map; + } + + private static Map decodeConnectorMap(Type valueType, + JSONValue jsonValue, ApplicationConnection connection) { + Map map = new HashMap(); + + JSONObject jsonMap = (JSONObject) jsonValue; + ConnectorMap connectorMap = ConnectorMap.get(connection); + + for (String connectorId : jsonMap.keySet()) { + Object value = decodeValue(valueType, jsonMap.get(connectorId), + null, connection); + map.put(connectorMap.getConnector(connectorId), value); + } + + return map; + } + + private static Map decodeStringMap(Type valueType, + JSONValue jsonValue, ApplicationConnection connection) { + Map map = new HashMap(); + + JSONObject jsonMap = (JSONObject) jsonValue; + + for (String key : jsonMap.keySet()) { + Object value = decodeValue(valueType, jsonMap.get(key), null, + connection); + map.put(key, value); + } + return map; } diff --git a/src/com/vaadin/terminal/gwt/client/communication/JsonEncoder.java b/src/com/vaadin/terminal/gwt/client/communication/JsonEncoder.java index 541dc631c6..df095833dc 100644 --- a/src/com/vaadin/terminal/gwt/client/communication/JsonEncoder.java +++ b/src/com/vaadin/terminal/gwt/client/communication/JsonEncoder.java @@ -7,6 +7,7 @@ package com.vaadin.terminal.gwt.client.communication; import java.util.Collection; import java.util.List; import java.util.Map; +import java.util.Map.Entry; import java.util.Set; import com.google.gwt.json.client.JSONArray; @@ -129,24 +130,85 @@ public class JsonEncoder { private static JSONValue encodeMap(Map map, boolean restrictToInternalTypes, ConnectorMap connectorMap, ApplicationConnection connection) { + /* + * As we have no info about declared types, we instead select encoding + * scheme based on actual type of first key. We can't do this if there's + * no first key, so instead we send some special value that the + * server-side decoding must check for. (see #8906) + */ + if (map.isEmpty()) { + return new JSONArray(); + } + + Object firstKey = map.keySet().iterator().next(); + if (firstKey instanceof String) { + return encodeStringMap(map, restrictToInternalTypes, connectorMap, + connection); + } else if (restrictToInternalTypes) { + throw new IllegalStateException( + "Only string keys supported for legacy maps"); + } else if (firstKey instanceof Connector) { + return encodeConenctorMap(map, connectorMap, connection); + } else { + return encodeObjectMap(map, connectorMap, connection); + } + } + + private static JSONValue encodeObjectMap(Map map, + ConnectorMap connectorMap, ApplicationConnection connection) { + JSONArray keys = new JSONArray(); + JSONArray values = new JSONArray(); + for (Entry entry : map.entrySet()) { + // restrictToInternalTypes always false if we end up here + keys.set(keys.size(), + encode(entry.getKey(), false, connectorMap, connection)); + values.set(values.size(), + encode(entry.getValue(), false, connectorMap, connection)); + } + + JSONArray keysAndValues = new JSONArray(); + keysAndValues.set(0, keys); + keysAndValues.set(1, values); + + return keysAndValues; + } + + private static JSONValue encodeConenctorMap(Map map, + ConnectorMap connectorMap, ApplicationConnection connection) { JSONObject jsonMap = new JSONObject(); - for (Object mapKey : map.keySet()) { - Object mapValue = map.get(mapKey); + + for (Entry entry : map.entrySet()) { + Connector connector = (Connector) entry.getKey(); + + // restrictToInternalTypes always false if we end up here + JSONValue encodedValue = encode(entry.getValue(), false, + connectorMap, connection); + + jsonMap.put(connector.getConnectorId(), encodedValue); + } + + return jsonMap; + } + + private static JSONValue encodeStringMap(Map map, + boolean restrictToInternalTypes, ConnectorMap connectorMap, + ApplicationConnection connection) { + JSONObject jsonMap = new JSONObject(); + + for (Entry entry : map.entrySet()) { + String key = (String) entry.getKey(); + Object value = entry.getValue(); + if (restrictToInternalTypes) { - if (!(mapKey instanceof String)) { - throw new IllegalStateException( - "Only string keys supported for legacy maps"); - } - // Wrap in UidlValue to send explicit type info - mapKey = new UidlValue(mapKey); - mapValue = new UidlValue(mapValue); + value = new UidlValue(value); } - JSONValue encodedKey = encode(mapKey, restrictToInternalTypes, - connectorMap, connection); - JSONValue encodedValue = encode(mapValue, restrictToInternalTypes, + + JSONValue encodedValue = encode(value, restrictToInternalTypes, connectorMap, connection); - jsonMap.put(encodedKey.toString(), encodedValue); + + jsonMap.put(key, encodedValue); } + return jsonMap; } diff --git a/src/com/vaadin/terminal/gwt/server/JsonCodec.java b/src/com/vaadin/terminal/gwt/server/JsonCodec.java index e76a3d3f3a..feaf78d2e8 100644 --- a/src/com/vaadin/terminal/gwt/server/JsonCodec.java +++ b/src/com/vaadin/terminal/gwt/server/JsonCodec.java @@ -13,19 +13,20 @@ import java.lang.reflect.Method; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Map.Entry; import java.util.Set; import com.vaadin.Application; import com.vaadin.external.json.JSONArray; import com.vaadin.external.json.JSONException; import com.vaadin.external.json.JSONObject; -import com.vaadin.external.json.JSONTokener; import com.vaadin.terminal.gwt.client.Connector; import com.vaadin.terminal.gwt.client.communication.JsonEncoder; import com.vaadin.terminal.gwt.client.communication.UidlValue; @@ -178,7 +179,7 @@ public class JsonCodec implements Serializable { (JSONArray) encodedJsonValue, application); } else if (JsonEncoder.VTYPE_MAP.equals(transportType)) { return decodeMap(targetType, restrictToInternalTypes, - (JSONObject) encodedJsonValue, application); + encodedJsonValue, application); } // Arrays @@ -243,23 +244,92 @@ public class JsonCodec implements Serializable { } private static Map decodeMap(Type targetType, - boolean restrictToInternalTypes, JSONObject jsonMap, + boolean restrictToInternalTypes, Object jsonMap, Application application) throws JSONException { - HashMap map = new HashMap(); + if (jsonMap instanceof JSONArray) { + // Client-side has no declared type information to determine + // encoding method for empty maps, so these are handled separately. + // See #8906. + JSONArray jsonArray = (JSONArray) jsonMap; + if (jsonArray.length() == 0) { + return new HashMap(); + } + } - Iterator it = jsonMap.keys(); - while (it.hasNext()) { - String key = it.next(); - String keyString = (String) new JSONTokener(key).nextValue(); - Object encodedKey = new JSONTokener(keyString).nextValue(); - Object encodedValue = jsonMap.get(key); + if (!restrictToInternalTypes && targetType instanceof ParameterizedType) { + Type keyType = ((ParameterizedType) targetType) + .getActualTypeArguments()[0]; + Type valueType = ((ParameterizedType) targetType) + .getActualTypeArguments()[1]; + if (keyType == String.class) { + return decodeStringMap(valueType, (JSONObject) jsonMap, + application); + } else if (keyType == Connector.class) { + return decodeConnectorMap(valueType, (JSONObject) jsonMap, + application); + } else { + return decodeObjectMap(keyType, valueType, (JSONArray) jsonMap, + application); + } + } else { + return decodeStringMap(UidlValue.class, (JSONObject) jsonMap, + application); + } + } + + private static Map decodeObjectMap(Type keyType, + Type valueType, JSONArray jsonMap, Application application) + throws JSONException { + Map map = new HashMap(); + + JSONArray keys = jsonMap.getJSONArray(0); + JSONArray values = jsonMap.getJSONArray(1); + + assert (keys.length() == values.length()); + + for (int i = 0; i < keys.length(); i++) { + Object key = decodeInternalOrCustomType(keyType, keys.get(i), + application); + Object value = decodeInternalOrCustomType(valueType, values.get(i), + application); - Object decodedKey = decodeParametrizedType(targetType, - restrictToInternalTypes, 0, encodedKey, application); - Object decodedValue = decodeParametrizedType(targetType, - restrictToInternalTypes, 1, encodedValue, application); - map.put(decodedKey, decodedValue); + map.put(key, value); } + + return map; + } + + private static Map decodeConnectorMap(Type valueType, + JSONObject jsonMap, Application application) throws JSONException { + Map map = new HashMap(); + + for (Iterator iter = jsonMap.keys(); iter.hasNext();) { + String key = (String) iter.next(); + Object value = decodeInternalOrCustomType(valueType, + jsonMap.get(key), application); + if (valueType == UidlValue.class) { + value = ((UidlValue) value).getValue(); + } + map.put(application.getConnector(key), value); + } + + return map; + } + + private static Map decodeStringMap(Type valueType, + JSONObject jsonMap, Application application) throws JSONException { + Map map = new HashMap(); + + for (Iterator iter = jsonMap.keys(); iter.hasNext();) { + String key = (String) iter.next(); + Object value = decodeInternalOrCustomType(valueType, + jsonMap.get(key), application); + if (valueType == UidlValue.class) { + value = ((UidlValue) value).getValue(); + } + map.put(key, value); + } + return map; } @@ -429,7 +499,7 @@ public class JsonCodec implements Serializable { JSONArray jsonArray = encodeArrayContents(array, application); return jsonArray; } else if (value instanceof Map) { - JSONObject jsonMap = encodeMap(valueType, (Map) value, + Object jsonMap = encodeMap(valueType, (Map) value, application); return jsonMap; } else if (value instanceof Connector) { @@ -550,7 +620,7 @@ public class JsonCodec implements Serializable { } } - private static JSONObject encodeMap(Type mapType, Map map, + private static Object encodeMap(Type mapType, Map map, Application application) throws JSONException { Type keyType, valueType; @@ -561,13 +631,64 @@ public class JsonCodec implements Serializable { throw new JSONException("Map is missing generics"); } + if (map.isEmpty()) { + // Client -> server encodes empty map as an empty array because of + // #8906. Do the same for server -> client to maintain symmetry. + return new JSONArray(); + } + + if (keyType == String.class) { + return encodeStringMap(valueType, map, application); + } else if (keyType == Connector.class) { + return encodeConnectorMap(valueType, map, application); + } else { + return encodeObjectMap(keyType, valueType, map, application); + } + } + + private static JSONArray encodeObjectMap(Type keyType, Type valueType, + Map map, Application application) throws JSONException { + JSONArray keys = new JSONArray(); + JSONArray values = new JSONArray(); + + for (Entry entry : map.entrySet()) { + Object encodedKey = encode(entry.getKey(), null, keyType, + application); + Object encodedValue = encode(entry.getValue(), null, valueType, + application); + + keys.put(encodedKey); + values.put(encodedValue); + } + + return new JSONArray(Arrays.asList(keys, values)); + } + + private static JSONObject encodeConnectorMap(Type valueType, Map map, + Application application) throws JSONException { + JSONObject jsonMap = new JSONObject(); + + for (Entry entry : map.entrySet()) { + Connector key = (Connector) entry.getKey(); + Object encodedValue = encode(entry.getValue(), null, valueType, + application); + jsonMap.put(key.getConnectorId(), encodedValue); + } + + return jsonMap; + } + + private static JSONObject encodeStringMap(Type valueType, Map map, + Application application) throws JSONException { JSONObject jsonMap = new JSONObject(); - for (Object mapKey : map.keySet()) { - Object mapValue = map.get(mapKey); - Object encodedKey = encode(mapKey, null, keyType, application); - Object encodedValue = encode(mapValue, null, valueType, application); - jsonMap.put(JSONObject.quote(encodedKey.toString()), encodedValue); + + for (Entry entry : map.entrySet()) { + String key = (String) entry.getKey(); + Object encodedValue = encode(entry.getValue(), null, valueType, + application); + jsonMap.put(key, encodedValue); } + return jsonMap; } -- cgit v1.2.3 From e88a49764e1a797089f65566e77482c6cc585c91 Mon Sep 17 00:00:00 2001 From: Leif Åstrand Date: Tue, 5 Jun 2012 15:18:03 +0300 Subject: Remove redundant ConnectorMap from JsonEncoder.encode --- .../terminal/gwt/client/ApplicationConnection.java | 2 +- .../gwt/client/communication/JSONSerializer.java | 6 +- .../gwt/client/communication/JsonEncoder.java | 69 +++++++++------------- .../communication/URLReference_Serializer.java | 6 +- .../gwt/widgetsetutils/SerializerGenerator.java | 6 +- 5 files changed, 33 insertions(+), 56 deletions(-) diff --git a/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java b/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java index 1b902e8e40..0a954f530b 100644 --- a/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java +++ b/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java @@ -1711,7 +1711,7 @@ public class ApplicationConnection { // TODO non-static encoder? type registration? paramJson.set(i, JsonEncoder.encode( invocation.getParameters()[i], - restrictToInternalTypes, getConnectorMap(), this)); + restrictToInternalTypes, this)); } invocationJson.set(3, paramJson); reqJson.set(reqJson.size(), invocationJson); diff --git a/src/com/vaadin/terminal/gwt/client/communication/JSONSerializer.java b/src/com/vaadin/terminal/gwt/client/communication/JSONSerializer.java index fe879b2fa7..9820b6a895 100644 --- a/src/com/vaadin/terminal/gwt/client/communication/JSONSerializer.java +++ b/src/com/vaadin/terminal/gwt/client/communication/JSONSerializer.java @@ -47,12 +47,8 @@ public interface JSONSerializer { * * @param value * The object to serialize - * @param idMapper - * mapper from paintable id to paintable, used to decode - * references to paintables * @return A JSON serialized version of the object */ - JSONValue serialize(T value, ConnectorMap idMapper, - ApplicationConnection connection); + JSONValue serialize(T value, ApplicationConnection connection); } diff --git a/src/com/vaadin/terminal/gwt/client/communication/JsonEncoder.java b/src/com/vaadin/terminal/gwt/client/communication/JsonEncoder.java index df095833dc..9b0b690ed4 100644 --- a/src/com/vaadin/terminal/gwt/client/communication/JsonEncoder.java +++ b/src/com/vaadin/terminal/gwt/client/communication/JsonEncoder.java @@ -18,7 +18,6 @@ import com.google.gwt.json.client.JSONString; import com.google.gwt.json.client.JSONValue; import com.vaadin.terminal.gwt.client.ApplicationConnection; import com.vaadin.terminal.gwt.client.Connector; -import com.vaadin.terminal.gwt.client.ConnectorMap; /** * Encoder for converting RPC parameters and other values to JSON for transfer @@ -53,14 +52,11 @@ public class JsonEncoder { * * @param value * value to convert - * @param connectorMap - * mapper from connectors to connector IDs * @param connection * @return JSON representation of the value */ public static JSONValue encode(Object value, - boolean restrictToInternalTypes, ConnectorMap connectorMap, - ApplicationConnection connection) { + boolean restrictToInternalTypes, ApplicationConnection connection) { if (null == value) { return JSONNull.getInstance(); } else if (value instanceof String[]) { @@ -76,29 +72,27 @@ public class JsonEncoder { return JSONBoolean.getInstance((Boolean) value); } else if (value instanceof Object[]) { return encodeObjectArray((Object[]) value, restrictToInternalTypes, - connectorMap, connection); + connection); } else if (value instanceof Enum) { if (restrictToInternalTypes) { // Enums are encoded as strings in Vaadin 6 so we still do that // for backwards copmatibility. return encode(new UidlValue(value.toString()), - restrictToInternalTypes, connectorMap, connection); + restrictToInternalTypes, connection); } else { Enum e = (Enum) value; - return encodeEnum(e, connectorMap, connection); + return encodeEnum(e, connection); } } else if (value instanceof Map) { - return encodeMap((Map) value, restrictToInternalTypes, - connectorMap, connection); + return encodeMap((Map) value, restrictToInternalTypes, connection); } else if (value instanceof Connector) { Connector connector = (Connector) value; return new JSONString(connector.getConnectorId()); } else if (value instanceof Collection) { return encodeCollection((Collection) value, - restrictToInternalTypes, connectorMap, connection); + restrictToInternalTypes, connection); } else if (value instanceof UidlValue) { - return encodeVariableChange((UidlValue) value, connectorMap, - connection); + return encodeVariableChange((UidlValue) value, connection); } else { String transportType = getTransportType(value); if (transportType != null) { @@ -111,25 +105,24 @@ public class JsonEncoder { .getSerializer(transportType); // TODO handle case with no serializer found - return serializer.serialize(value, connectorMap, connection); + return serializer.serialize(value, connection); } } } private static JSONValue encodeVariableChange(UidlValue uidlValue, - ConnectorMap connectorMap, ApplicationConnection connection) { + ApplicationConnection connection) { Object value = uidlValue.getValue(); JSONArray jsonArray = new JSONArray(); jsonArray.set(0, new JSONString(getTransportType(value))); - jsonArray.set(1, encode(value, true, connectorMap, connection)); + jsonArray.set(1, encode(value, true, connection)); return jsonArray; } private static JSONValue encodeMap(Map map, - boolean restrictToInternalTypes, ConnectorMap connectorMap, - ApplicationConnection connection) { + boolean restrictToInternalTypes, ApplicationConnection connection) { /* * As we have no info about declared types, we instead select encoding * scheme based on actual type of first key. We can't do this if there's @@ -142,28 +135,26 @@ public class JsonEncoder { Object firstKey = map.keySet().iterator().next(); if (firstKey instanceof String) { - return encodeStringMap(map, restrictToInternalTypes, connectorMap, - connection); + return encodeStringMap(map, restrictToInternalTypes, connection); } else if (restrictToInternalTypes) { throw new IllegalStateException( "Only string keys supported for legacy maps"); } else if (firstKey instanceof Connector) { - return encodeConenctorMap(map, connectorMap, connection); + return encodeConenctorMap(map, connection); } else { - return encodeObjectMap(map, connectorMap, connection); + return encodeObjectMap(map, connection); } } private static JSONValue encodeObjectMap(Map map, - ConnectorMap connectorMap, ApplicationConnection connection) { + ApplicationConnection connection) { JSONArray keys = new JSONArray(); JSONArray values = new JSONArray(); for (Entry entry : map.entrySet()) { // restrictToInternalTypes always false if we end up here - keys.set(keys.size(), - encode(entry.getKey(), false, connectorMap, connection)); + keys.set(keys.size(), encode(entry.getKey(), false, connection)); values.set(values.size(), - encode(entry.getValue(), false, connectorMap, connection)); + encode(entry.getValue(), false, connection)); } JSONArray keysAndValues = new JSONArray(); @@ -174,15 +165,14 @@ public class JsonEncoder { } private static JSONValue encodeConenctorMap(Map map, - ConnectorMap connectorMap, ApplicationConnection connection) { + ApplicationConnection connection) { JSONObject jsonMap = new JSONObject(); for (Entry entry : map.entrySet()) { Connector connector = (Connector) entry.getKey(); // restrictToInternalTypes always false if we end up here - JSONValue encodedValue = encode(entry.getValue(), false, - connectorMap, connection); + JSONValue encodedValue = encode(entry.getValue(), false, connection); jsonMap.put(connector.getConnectorId(), encodedValue); } @@ -191,8 +181,7 @@ public class JsonEncoder { } private static JSONValue encodeStringMap(Map map, - boolean restrictToInternalTypes, ConnectorMap connectorMap, - ApplicationConnection connection) { + boolean restrictToInternalTypes, ApplicationConnection connection) { JSONObject jsonMap = new JSONObject(); for (Entry entry : map.entrySet()) { @@ -204,7 +193,7 @@ public class JsonEncoder { } JSONValue encodedValue = encode(value, restrictToInternalTypes, - connectorMap, connection); + connection); jsonMap.put(key, encodedValue); } @@ -212,14 +201,13 @@ public class JsonEncoder { return jsonMap; } - private static JSONValue encodeEnum(Enum e, ConnectorMap connectorMap, + private static JSONValue encodeEnum(Enum e, ApplicationConnection connection) { return new JSONString(e.toString()); } private static JSONValue encodeObjectArray(Object[] array, - boolean restrictToInternalTypes, ConnectorMap connectorMap, - ApplicationConnection connection) { + boolean restrictToInternalTypes, ApplicationConnection connection) { JSONArray jsonArray = new JSONArray(); for (int i = 0; i < array.length; ++i) { // TODO handle object graph loops? @@ -227,22 +215,19 @@ public class JsonEncoder { if (restrictToInternalTypes) { value = new UidlValue(value); } - jsonArray.set( - i, - encode(value, restrictToInternalTypes, connectorMap, - connection)); + jsonArray + .set(i, encode(value, restrictToInternalTypes, connection)); } return jsonArray; } private static JSONValue encodeCollection(Collection collection, - boolean restrictToInternalTypes, ConnectorMap connectorMap, - ApplicationConnection connection) { + boolean restrictToInternalTypes, ApplicationConnection connection) { JSONArray jsonArray = new JSONArray(); int idx = 0; for (Object o : collection) { JSONValue encodedObject = encode(o, restrictToInternalTypes, - connectorMap, connection); + connection); jsonArray.set(idx++, encodedObject); } if (collection instanceof Set) { diff --git a/src/com/vaadin/terminal/gwt/client/communication/URLReference_Serializer.java b/src/com/vaadin/terminal/gwt/client/communication/URLReference_Serializer.java index f6108bbfa8..56c4bb9623 100644 --- a/src/com/vaadin/terminal/gwt/client/communication/URLReference_Serializer.java +++ b/src/com/vaadin/terminal/gwt/client/communication/URLReference_Serializer.java @@ -7,7 +7,6 @@ import com.google.gwt.core.client.GWT; import com.google.gwt.json.client.JSONObject; import com.google.gwt.json.client.JSONValue; import com.vaadin.terminal.gwt.client.ApplicationConnection; -import com.vaadin.terminal.gwt.client.ConnectorMap; public class URLReference_Serializer implements JSONSerializer { @@ -25,11 +24,10 @@ public class URLReference_Serializer implements JSONSerializer { return reference; } - public JSONValue serialize(URLReference value, ConnectorMap idMapper, - ApplicationConnection connection) { + public JSONValue serialize(URLReference value, ApplicationConnection connection) { JSONObject json = new JSONObject(); json.put("URL", - JsonEncoder.encode(value.getURL(), true, idMapper, connection)); + JsonEncoder.encode(value.getURL(), true, connection)); return json; } diff --git a/src/com/vaadin/terminal/gwt/widgetsetutils/SerializerGenerator.java b/src/com/vaadin/terminal/gwt/widgetsetutils/SerializerGenerator.java index 6e99089434..6e1ebdfc7f 100644 --- a/src/com/vaadin/terminal/gwt/widgetsetutils/SerializerGenerator.java +++ b/src/com/vaadin/terminal/gwt/widgetsetutils/SerializerGenerator.java @@ -28,7 +28,6 @@ import com.google.gwt.json.client.JSONValue; import com.google.gwt.user.rebind.ClassSourceFileComposerFactory; import com.google.gwt.user.rebind.SourceWriter; import com.vaadin.terminal.gwt.client.ApplicationConnection; -import com.vaadin.terminal.gwt.client.ConnectorMap; import com.vaadin.terminal.gwt.client.communication.DiffJSONSerializer; import com.vaadin.terminal.gwt.client.communication.JSONSerializer; import com.vaadin.terminal.gwt.client.communication.JsonDecoder; @@ -128,11 +127,10 @@ public class SerializerGenerator extends Generator { // Serializer - // public JSONValue serialize(Object value, ConnectorMap idMapper, + // public JSONValue serialize(Object value, // ApplicationConnection connection) { sourceWriter.println("public " + JSONValue.class.getName() + " serialize(" + beanQualifiedSourceName + " value, " - + ConnectorMap.class.getName() + " idMapper, " + ApplicationConnection.class.getName() + " connection) {"); sourceWriter.indent(); // MouseEventDetails castedValue = (MouseEventDetails) value; @@ -306,7 +304,7 @@ public class SerializerGenerator extends Generator { // connection)); sourceWriter.println("json.put(\"" + fieldName + "\", " + JsonEncoder.class.getName() + ".encode(castedValue." - + getterName + "(), false, idMapper, connection));"); + + getterName + "(), false, connection));"); } // return json; sourceWriter.println("return json;"); -- cgit v1.2.3 From c284b3c3881b23cd0275a5adad055dd2aa3c3252 Mon Sep 17 00:00:00 2001 From: Leif Åstrand Date: Tue, 5 Jun 2012 15:56:53 +0300 Subject: Use update from deserialize instead of generating the same code again Also slightly improve indenting in generated code --- .../gwt/widgetsetutils/SerializerGenerator.java | 28 +++++++++------------- 1 file changed, 11 insertions(+), 17 deletions(-) diff --git a/src/com/vaadin/terminal/gwt/widgetsetutils/SerializerGenerator.java b/src/com/vaadin/terminal/gwt/widgetsetutils/SerializerGenerator.java index 6e1ebdfc7f..060d0fa96a 100644 --- a/src/com/vaadin/terminal/gwt/widgetsetutils/SerializerGenerator.java +++ b/src/com/vaadin/terminal/gwt/widgetsetutils/SerializerGenerator.java @@ -157,7 +157,7 @@ public class SerializerGenerator extends Generator { + ApplicationConnection.class.getName() + " connection) {"); sourceWriter.indent(); - writeBeanDeserializer(logger, sourceWriter, beanType, true); + writeBeanDeserializer(logger, sourceWriter, beanType); sourceWriter.outdent(); sourceWriter.println("}"); @@ -175,14 +175,20 @@ public class SerializerGenerator extends Generator { if (isEnum) { writeEnumDeserializer(logger, sourceWriter, beanType.isEnum()); } else { - writeBeanDeserializer(logger, sourceWriter, beanType, false); + sourceWriter.println(beanQualifiedSourceName + + " target = GWT.create(" + beanQualifiedSourceName + + ".class);"); + sourceWriter + .println("update(target, type, jsonValue, connection);"); + // return target; + sourceWriter.println("return target;"); } - sourceWriter.println("}"); sourceWriter.outdent(); + sourceWriter.println("}"); // End of class - sourceWriter.println("}"); sourceWriter.outdent(); + sourceWriter.println("}"); // commit generated class context.commit(logger, printWriter); @@ -207,15 +213,9 @@ public class SerializerGenerator extends Generator { } private void writeBeanDeserializer(TreeLogger logger, - SourceWriter sourceWriter, JClassType beanType, boolean update) { + SourceWriter sourceWriter, JClassType beanType) { String beanQualifiedSourceName = beanType.getQualifiedSourceName(); - if (!update) { - sourceWriter.println(beanQualifiedSourceName - + " target = GWT.create(" + beanQualifiedSourceName - + ".class);"); - } - // JSONOBject json = (JSONObject)jsonValue; sourceWriter.println(JSONObject.class.getName() + " json = (" + JSONObject.class.getName() + ")jsonValue;"); @@ -268,12 +268,6 @@ public class SerializerGenerator extends Generator { sourceWriter.outdent(); sourceWriter.println("}"); } - - if (!update) { - // return target; - sourceWriter.println("return target;"); - } - } private void writeEnumSerializer(TreeLogger logger, -- cgit v1.2.3 From 8eae5a4313ea8ddba38bd42c93043a9a6fa9ce03 Mon Sep 17 00:00:00 2001 From: Automerge Date: Wed, 6 Jun 2012 13:07:21 +0000 Subject: [merge from 6.7] #7606 Run a Webkit overflow fix as deferred to keep table scroll position accurate svn changeset:23896/svn branch:6.8 --- src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java b/src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java index 9bfd013603..8d0414a235 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java @@ -6247,7 +6247,14 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler, // Webkit may sometimes get an odd rendering bug (white space // between header and body), see bug #3875. Running // overflow hack here to shake body element a bit. - Util.runWebkitOverflowAutoFix(scrollBodyPanel.getElement()); + // We must run the fix as a deferred command to prevent it from + // overwriting the scroll position with an outdated value, see + // #7606. + Scheduler.get().scheduleDeferred(new Command() { + public void execute() { + Util.runWebkitOverflowAutoFix(scrollBodyPanel.getElement()); + } + }); } /* -- cgit v1.2.3 From a53d9263b7aaeddd0c7601acba8397a6983c26b3 Mon Sep 17 00:00:00 2001 From: Leif Åstrand Date: Thu, 7 Jun 2012 10:26:17 +0300 Subject: Use camelCase field names -> JSON more suitable for javascript (#8888) --- .../communication/URLReference_Serializer.java | 12 +++++--- src/com/vaadin/terminal/gwt/server/JsonCodec.java | 15 ++++++++-- .../gwt/widgetsetutils/SerializerGenerator.java | 35 ++++++++++++++++++---- 3 files changed, 50 insertions(+), 12 deletions(-) diff --git a/src/com/vaadin/terminal/gwt/client/communication/URLReference_Serializer.java b/src/com/vaadin/terminal/gwt/client/communication/URLReference_Serializer.java index 56c4bb9623..bab0f385ed 100644 --- a/src/com/vaadin/terminal/gwt/client/communication/URLReference_Serializer.java +++ b/src/com/vaadin/terminal/gwt/client/communication/URLReference_Serializer.java @@ -10,12 +10,15 @@ import com.vaadin.terminal.gwt.client.ApplicationConnection; public class URLReference_Serializer implements JSONSerializer { + // setURL() -> uRL as first char becomes lower case... + private static final String URL_FIELD = "uRL"; + public URLReference deserialize(Type type, JSONValue jsonValue, ApplicationConnection connection) { URLReference reference = GWT.create(URLReference.class); JSONObject json = (JSONObject) jsonValue; - if (json.containsKey("URL")) { - JSONValue jsonURL = json.get("URL"); + if (json.containsKey(URL_FIELD)) { + JSONValue jsonURL = json.get(URL_FIELD); String URL = (String) JsonDecoder.decodeValue( new Type(String.class.getName(), null), jsonURL, null, connection); @@ -24,9 +27,10 @@ public class URLReference_Serializer implements JSONSerializer { return reference; } - public JSONValue serialize(URLReference value, ApplicationConnection connection) { + public JSONValue serialize(URLReference value, + ApplicationConnection connection) { JSONObject json = new JSONObject(); - json.put("URL", + json.put(URL_FIELD, JsonEncoder.encode(value.getURL(), true, connection)); return json; } diff --git a/src/com/vaadin/terminal/gwt/server/JsonCodec.java b/src/com/vaadin/terminal/gwt/server/JsonCodec.java index feaf78d2e8..f4892bd905 100644 --- a/src/com/vaadin/terminal/gwt/server/JsonCodec.java +++ b/src/com/vaadin/terminal/gwt/server/JsonCodec.java @@ -410,7 +410,7 @@ public class JsonCodec implements Serializable { * Returns the name that should be used as field name in the JSON. We strip * "set" from the setter, keeping the result - this is easy to do on both * server and client, avoiding some issues with cASE. E.g setZIndex() - * becomes "ZIndex". Also ensures that both getter and setter are present, + * becomes "zIndex". Also ensures that both getter and setter are present, * returning null otherwise. * * @param pd @@ -421,7 +421,10 @@ public class JsonCodec implements Serializable { if (pd.getReadMethod() == null || pd.getWriteMethod() == null) { return null; } - return pd.getWriteMethod().getName().substring(3); + String fieldName = pd.getWriteMethod().getName().substring(3); + fieldName = Character.toLowerCase(fieldName.charAt(0)) + + fieldName.substring(1); + return fieldName; } private static Object decodeObject(Type targetType, @@ -547,6 +550,14 @@ public class JsonCodec implements Serializable { equals = equals(fieldValue, referenceFieldValue); } if (!equals) { + if (jsonMap.has(fieldName)) { + throw new RuntimeException( + "Can't encode " + + value.getClass().getName() + + " as it has multiple fields with the name " + + fieldName.toLowerCase() + + ". This can happen if only casing distinguishes one property name from another."); + } jsonMap.put( fieldName, encode(fieldValue, referenceFieldValue, fieldType, diff --git a/src/com/vaadin/terminal/gwt/widgetsetutils/SerializerGenerator.java b/src/com/vaadin/terminal/gwt/widgetsetutils/SerializerGenerator.java index 060d0fa96a..c32b54ff1c 100644 --- a/src/com/vaadin/terminal/gwt/widgetsetutils/SerializerGenerator.java +++ b/src/com/vaadin/terminal/gwt/widgetsetutils/SerializerGenerator.java @@ -7,6 +7,7 @@ package com.vaadin.terminal.gwt.widgetsetutils; import java.io.PrintWriter; import java.util.ArrayList; import java.util.Date; +import java.util.HashSet; import java.util.List; import com.google.gwt.core.client.GWT; @@ -79,10 +80,11 @@ public class SerializerGenerator extends Generator { * bean type for which the serializer is to be generated * @param beanSerializerTypeName * name of the serializer class to generate + * @throws UnableToCompleteException */ private void generateClass(TreeLogger logger, GeneratorContext context, JClassType beanType, String serializerPackageName, - String serializerClassName) { + String serializerClassName) throws UnableToCompleteException { // get print writer that receives the source code PrintWriter printWriter = null; printWriter = context.tryCreate(logger, serializerPackageName, @@ -222,7 +224,9 @@ public class SerializerGenerator extends Generator { for (JMethod method : getSetters(beanType)) { String setterName = method.getName(); - String fieldName = setterName.substring(3); // setZIndex() -> ZIndex + String baseName = setterName.substring(3); + String fieldName = getTransportFieldName(baseName); // setZIndex() + // -> zIndex JType setterParameterType = method.getParameterTypes()[0]; logger.log(Type.DEBUG, "* Processing field " + fieldName + " in " @@ -238,13 +242,13 @@ public class SerializerGenerator extends Generator { + " = json.get(\"" + fieldName + "\");"); String fieldType; - String getterName = "get" + fieldName; + String getterName = "get" + baseName; JPrimitiveType primitiveType = setterParameterType.isPrimitive(); if (primitiveType != null) { // This is a primitive type -> must used the boxed type fieldType = primitiveType.getQualifiedBoxedSourceName(); if (primitiveType == JPrimitiveType.BOOLEAN) { - getterName = "is" + fieldName; + getterName = "is" + baseName; } } else { fieldType = setterParameterType.getQualifiedSourceName(); @@ -278,15 +282,29 @@ public class SerializerGenerator extends Generator { } private void writeBeanSerializer(TreeLogger logger, - SourceWriter sourceWriter, JClassType beanType) { + SourceWriter sourceWriter, JClassType beanType) + throws UnableToCompleteException { // JSONObject json = new JSONObject(); sourceWriter.println(JSONObject.class.getName() + " json = new " + JSONObject.class.getName() + "();"); + HashSet usedFieldNames = new HashSet(); + for (JMethod setterMethod : getSetters(beanType)) { String setterName = setterMethod.getName(); - String fieldName = setterName.substring(3); // setZIndex() -> ZIndex + String fieldName = getTransportFieldName(setterName.substring(3)); // setZIndex() + // -> zIndex + if (!usedFieldNames.add(fieldName)) { + logger.log( + TreeLogger.ERROR, + "Can't encode " + + beanType.getQualifiedSourceName() + + " as it has multiple fields with the name " + + fieldName.toLowerCase() + + ". This can happen if only casing distinguishes one property name from another."); + throw new UnableToCompleteException(); + } String getterName = findGetter(beanType, setterMethod); if (getterName == null) { @@ -305,6 +323,11 @@ public class SerializerGenerator extends Generator { } + private static String getTransportFieldName(String baseName) { + return Character.toLowerCase(baseName.charAt(0)) + + baseName.substring(1); + } + private String findGetter(JClassType beanType, JMethod setterMethod) { JType setterParameterType = setterMethod.getParameterTypes()[0]; String fieldName = setterMethod.getName().substring(3); -- cgit v1.2.3 From 5c31c4150d273e087514776cefe19561cc66d5fd Mon Sep 17 00:00:00 2001 From: Leif Åstrand Date: Thu, 7 Jun 2012 11:41:50 +0300 Subject: Fix broken enums in UIDL message (#8878) --- .../terminal/gwt/client/communication/JsonEncoder.java | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/src/com/vaadin/terminal/gwt/client/communication/JsonEncoder.java b/src/com/vaadin/terminal/gwt/client/communication/JsonEncoder.java index 9b0b690ed4..657f44896d 100644 --- a/src/com/vaadin/terminal/gwt/client/communication/JsonEncoder.java +++ b/src/com/vaadin/terminal/gwt/client/communication/JsonEncoder.java @@ -74,15 +74,7 @@ public class JsonEncoder { return encodeObjectArray((Object[]) value, restrictToInternalTypes, connection); } else if (value instanceof Enum) { - if (restrictToInternalTypes) { - // Enums are encoded as strings in Vaadin 6 so we still do that - // for backwards copmatibility. - return encode(new UidlValue(value.toString()), - restrictToInternalTypes, connection); - } else { - Enum e = (Enum) value; - return encodeEnum(e, connection); - } + return encodeEnum((Enum) value, connection); } else if (value instanceof Map) { return encodeMap((Map) value, restrictToInternalTypes, connection); } else if (value instanceof Connector) { @@ -277,6 +269,9 @@ public class JsonEncoder { return VTYPE_ARRAY; } else if (value instanceof Map) { return VTYPE_MAP; + } else if (value instanceof Enum) { + // Enum value is processed as a string + return VTYPE_STRING; } return null; } -- cgit v1.2.3 From b18d9f7bb2419c947c8e0401fc7ee1b4f29e92cb Mon Sep 17 00:00:00 2001 From: Leif Åstrand Date: Thu, 7 Jun 2012 10:58:10 +0000 Subject: Refactor ?debug detection (#8923) This fixes #8923 by not looking at the uri fragment at all. Also prevents e.g. ?nodebugwindow or ?mode=debug from opening the debug window. svn changeset:23898/svn branch:6.8 --- .../gwt/client/ApplicationConfiguration.java | 23 ++++--- .../com/vaadin/tests/debug/DebugWindowPresent.html | 72 +++++++++++++++++++++- 2 files changed, 84 insertions(+), 11 deletions(-) diff --git a/src/com/vaadin/terminal/gwt/client/ApplicationConfiguration.java b/src/com/vaadin/terminal/gwt/client/ApplicationConfiguration.java index 21ecfe2776..c6d6bae80a 100644 --- a/src/com/vaadin/terminal/gwt/client/ApplicationConfiguration.java +++ b/src/com/vaadin/terminal/gwt/client/ApplicationConfiguration.java @@ -16,6 +16,7 @@ import com.google.gwt.core.client.JavaScriptObject; import com.google.gwt.core.client.JsArrayString; import com.google.gwt.user.client.Command; import com.google.gwt.user.client.Timer; +import com.google.gwt.user.client.Window; import com.vaadin.terminal.gwt.client.ui.VUnknownComponent; public class ApplicationConfiguration implements EntryPoint { @@ -496,12 +497,15 @@ public class ApplicationConfiguration implements EntryPoint { * * @return true if client side is currently been debugged */ - public native static boolean isDebugMode() + public static boolean isDebugMode() { + return isDebugAvailable() + && Window.Location.getParameter("debug") != null; + } + + private native static boolean isDebugAvailable() /*-{ if($wnd.vaadin.debug) { - var parameters = $wnd.location.search; - var re = /debug[^\/]*$/; - return re.test(parameters); + return true; } else { return false; } @@ -512,11 +516,10 @@ public class ApplicationConfiguration implements EntryPoint { * * @return true if debug logging should be quiet */ - public native static boolean isQuietDebugMode() - /*-{ - var uri = $wnd.location; - var re = /debug=q[^\/]*$/; - return re.test(uri); - }-*/; + public static boolean isQuietDebugMode() { + String debugParameter = Window.Location.getParameter("debug"); + return isDebugAvailable() && debugParameter != null + && debugParameter.startsWith("q"); + } } diff --git a/tests/testbench/com/vaadin/tests/debug/DebugWindowPresent.html b/tests/testbench/com/vaadin/tests/debug/DebugWindowPresent.html index d396c1778e..11640ef6c3 100644 --- a/tests/testbench/com/vaadin/tests/debug/DebugWindowPresent.html +++ b/tests/testbench/com/vaadin/tests/debug/DebugWindowPresent.html @@ -13,7 +13,17 @@ open - /run/com.vaadin.tests.debug.DebugWindowPresent?restartApplication&debug + /run/com.vaadin.tests.debug.DebugWindowPresent?restartApplication&debug&otherparam + + + + assertElementPresent + vaadin=runcomvaadintestsdebugDebugWindowPresent::Root/VDebugConsole[0] + + + + open + /run/com.vaadin.tests.debug.DebugWindowPresent?debug&restartApplication @@ -31,6 +41,66 @@ vaadin=runcomvaadintestsdebugDebugWindowPresent::Root/VDebugConsole[0] + + open + /run/com.vaadin.tests.debug.DebugWindowPresent?restartApplication&mode=debug + + + + assertElementNotPresent + vaadin=runcomvaadintestsdebugDebugWindowPresent::Root/VDebugConsole[0] + + + + open + /run/com.vaadin.tests.debug.DebugWindowPresent?nodebug&restartApplication + + + + assertElementNotPresent + vaadin=runcomvaadintestsdebugDebugWindowPresent::Root/VDebugConsole[0] + + + + open + /run/com.vaadin.tests.debug.DebugWindowPresent?restartApplication&nodebug + + + + assertElementNotPresent + vaadin=runcomvaadintestsdebugDebugWindowPresent::Root/VDebugConsole[0] + + + + open + /run/com.vaadin.tests.debug.DebugWindowPresent?restartApplication&debug=quiet + + + + assertElementNotPresent + vaadin=runcomvaadintestsdebugDebugWindowPresent::Root/VDebugConsole[0] + + + + open + /run/com.vaadin.tests.debug.DebugWindowPresent?debug=quiet&restartApplication + + + + assertElementNotPresent + vaadin=runcomvaadintestsdebugDebugWindowPresent::Root/VDebugConsole[0] + + + + open + /run/com.vaadin.tests.debug.DebugWindowPresent?restartApplication&debug=quiet#/asdf + + + + assertElementNotPresent + vaadin=runcomvaadintestsdebugDebugWindowPresent::Root/VDebugConsole[0] + + -- cgit v1.2.3 From 0a7f33f1ff4611b738c5f96b0ec21b5c444e70ca Mon Sep 17 00:00:00 2001 From: Automerge Date: Thu, 7 Jun 2012 11:42:25 +0000 Subject: [merge from 6.7] #7607 updated test svn changeset:23902/svn branch:6.8 --- .../components/table/TestCurrentPageFirstItem.html | 37 +++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/tests/testbench/com/vaadin/tests/components/table/TestCurrentPageFirstItem.html b/tests/testbench/com/vaadin/tests/components/table/TestCurrentPageFirstItem.html index ac06706aa5..451e9b9c8d 100644 --- a/tests/testbench/com/vaadin/tests/components/table/TestCurrentPageFirstItem.html +++ b/tests/testbench/com/vaadin/tests/components/table/TestCurrentPageFirstItem.html @@ -3,7 +3,7 @@ - + TestCurrentPageFirstItem @@ -36,6 +36,41 @@ + + click + vaadin=runTestCurrentPageFirstItem::/VHorizontalLayout[0]/ChildComponentContainer[4]/VButton[0]/domChild[0]/domChild[0] + + + + click + vaadin=runTestCurrentPageFirstItem::/VHorizontalLayout[0]/ChildComponentContainer[5]/VButton[0]/domChild[0]/domChild[0] + + + + click + vaadin=runTestCurrentPageFirstItem::/VHorizontalLayout[0]/ChildComponentContainer[4]/VButton[0]/domChild[0]/domChild[0] + + + + click + vaadin=runTestCurrentPageFirstItem::/VHorizontalLayout[0]/ChildComponentContainer[5]/VButton[0]/domChild[0]/domChild[0] + + + + click + vaadin=runTestCurrentPageFirstItem::/VHorizontalLayout[0]/ChildComponentContainer[4]/VButton[0]/domChild[0]/domChild[0] + + + + click + vaadin=runTestCurrentPageFirstItem::/VHorizontalLayout[0]/ChildComponentContainer[5]/VButton[0]/domChild[0]/domChild[0] + + + + screenCapture + + + -- cgit v1.2.3 From d2c12c2e5ffb9ce8336eac53ef14faaf3499ae82 Mon Sep 17 00:00:00 2001 From: Automerge Date: Thu, 7 Jun 2012 11:42:29 +0000 Subject: [merge from 6.7] #7067 Update a comment, fix typoed ticket reference svn changeset:23903/svn branch:6.8 --- src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java b/src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java index 8d0414a235..d88d0d31e5 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java @@ -2060,11 +2060,7 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler, isNewBody = false; if (firstvisible > 0) { - // FIXME #7607 - // Originally deferred due to Firefox oddities which should not - // occur any more. Currently deferring breaks Webkit scrolling with - // relative-height tables, but not deferring instead breaks tables - // with explicit page length. + // Deferred due to some Firefox oddities Scheduler.get().scheduleDeferred(new Command() { public void execute() { scrollBodyPanel @@ -6249,7 +6245,7 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler, // overflow hack here to shake body element a bit. // We must run the fix as a deferred command to prevent it from // overwriting the scroll position with an outdated value, see - // #7606. + // #7607. Scheduler.get().scheduleDeferred(new Command() { public void execute() { Util.runWebkitOverflowAutoFix(scrollBodyPanel.getElement()); -- cgit v1.2.3 From ac9c7f065645874a6cf7f78bfb7068703b171418 Mon Sep 17 00:00:00 2001 From: Artur Signell Date: Thu, 7 Jun 2012 14:44:54 +0300 Subject: Made it possible to override the type of wrapped request used in portals Accidentally removed change restored by this commit. --- .../gwt/server/AbstractApplicationPortlet.java | 47 +++++++++++++--------- 1 file changed, 29 insertions(+), 18 deletions(-) diff --git a/src/com/vaadin/terminal/gwt/server/AbstractApplicationPortlet.java b/src/com/vaadin/terminal/gwt/server/AbstractApplicationPortlet.java index 1acc9d128a..5b2be308a3 100644 --- a/src/com/vaadin/terminal/gwt/server/AbstractApplicationPortlet.java +++ b/src/com/vaadin/terminal/gwt/server/AbstractApplicationPortlet.java @@ -67,7 +67,7 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet private static final Logger logger = Logger .getLogger(AbstractApplicationPortlet.class.getName()); - private static class WrappedHttpAndPortletRequest extends + public static class WrappedHttpAndPortletRequest extends WrappedPortletRequest { public WrappedHttpAndPortletRequest(PortletRequest request, @@ -112,7 +112,7 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet } } - private static class WrappedGateinRequest extends + public static class WrappedGateinRequest extends WrappedHttpAndPortletRequest { public WrappedGateinRequest(PortletRequest request, DeploymentConfiguration deploymentConfiguration) { @@ -134,7 +134,7 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet } } - private static class WrappedLiferayRequest extends + public static class WrappedLiferayRequest extends WrappedHttpAndPortletRequest { public WrappedLiferayRequest(PortletRequest request, @@ -169,7 +169,7 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet } - private static class AbstractApplicationPortletWrapper implements Callback { + public static class AbstractApplicationPortletWrapper implements Callback { private final AbstractApplicationPortlet portlet; @@ -500,20 +500,7 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet AbstractApplicationPortletWrapper portletWrapper = new AbstractApplicationPortletWrapper( this); - WrappedPortletRequest wrappedRequest; - - String portalInfo = request.getPortalContext().getPortalInfo() - .toLowerCase(); - if (portalInfo.contains("liferay")) { - wrappedRequest = new WrappedLiferayRequest(request, - getDeploymentConfiguration()); - } else if (portalInfo.contains("gatein")) { - wrappedRequest = new WrappedGateinRequest(request, - getDeploymentConfiguration()); - } else { - wrappedRequest = new WrappedPortletRequest(request, - getDeploymentConfiguration()); - } + WrappedPortletRequest wrappedRequest = createWrappedRequest(request); WrappedPortletResponse wrappedResponse = new WrappedPortletResponse( response, getDeploymentConfiguration()); @@ -712,6 +699,30 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet } } + /** + * Wraps the request in a (possibly portal specific) wrapped portlet + * request. + * + * @param request + * The original PortletRequest + * @return A wrapped version of the PorletRequest + */ + protected WrappedPortletRequest createWrappedRequest(PortletRequest request) { + String portalInfo = request.getPortalContext().getPortalInfo() + .toLowerCase(); + if (portalInfo.contains("liferay")) { + return new WrappedLiferayRequest(request, + getDeploymentConfiguration()); + } else if (portalInfo.contains("gatein")) { + return new WrappedGateinRequest(request, + getDeploymentConfiguration()); + } else { + return new WrappedPortletRequest(request, + getDeploymentConfiguration()); + } + + } + private DeploymentConfiguration getDeploymentConfiguration() { return deploymentConfiguration; } -- cgit v1.2.3 From cece22a1d1919d8da459b6dab18c19e53c6e7f04 Mon Sep 17 00:00:00 2001 From: Leif Åstrand Date: Thu, 7 Jun 2012 12:07:16 +0000 Subject: Remove document.write from bootstrap (#8924) svn changeset:23905/svn branch:6.8 --- .../gwt/server/AbstractApplicationPortlet.java | 70 ++++++++++++++++------ .../gwt/server/AbstractApplicationServlet.java | 12 ++-- 2 files changed, 59 insertions(+), 23 deletions(-) diff --git a/src/com/vaadin/terminal/gwt/server/AbstractApplicationPortlet.java b/src/com/vaadin/terminal/gwt/server/AbstractApplicationPortlet.java index 9f1bd4e9ee..26b0d3df1d 100644 --- a/src/com/vaadin/terminal/gwt/server/AbstractApplicationPortlet.java +++ b/src/com/vaadin/terminal/gwt/server/AbstractApplicationPortlet.java @@ -879,6 +879,30 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet return null; } + /** + * Returns the URL from which the widgetset is served on the portal. + * + * @param request + * @return + */ + protected String getWidgetsetURL(RenderRequest request) { + String requestWidgetset = getApplicationOrSystemProperty( + PARAMETER_WIDGETSET, null); + String sharedWidgetset = getPortalProperty( + PORTAL_PARAMETER_VAADIN_WIDGETSET, request.getPortalContext()); + + String widgetset; + if (requestWidgetset != null) { + widgetset = requestWidgetset; + } else if (sharedWidgetset != null) { + widgetset = sharedWidgetset; + } else { + widgetset = DEFAULT_WIDGETSET; + } + String widgetsetURL = getWidgetsetURL(widgetset, request); + return widgetsetURL; + } + /** * Returns the URL from which the widgetset is served on the portal. * @@ -1037,12 +1061,32 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet writer.write("\n"); + writeAjaxPageWidgetset(request, writer); + writeAjaxPageHtmlTheme(request, writer, themeName, themeURI, portalTheme); // TODO Warn if widgetset has not been loaded after 15 seconds } + /** + * Writes the script to load the widgetset on the HTML fragment created by + * the portlet. + * + * @param request + * @param writer + * @throws IOException + */ + protected void writeAjaxPageWidgetset(RenderRequest request, + BufferedWriter writer) throws IOException { + String widgetsetURL = getWidgetsetURL(request); + writer.write("'\n"); + writer.write("\n"); + } + /** * Writes the script to load the widgetset on the HTML fragment created by * the portlet. @@ -1051,29 +1095,19 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet * @param response * @param writer * @throws IOException + * + * @Deprecated As of 6.8, use + * {@link #writeAjaxPageWidgetset(RenderRequest, BufferedWriter)} + * instead to avoid using document.write */ + @Deprecated protected void writeAjaxPageScriptWidgetset(RenderRequest request, RenderResponse response, final BufferedWriter writer) throws IOException { - String requestWidgetset = getApplicationOrSystemProperty( - PARAMETER_WIDGETSET, null); - String sharedWidgetset = getPortalProperty( - PORTAL_PARAMETER_VAADIN_WIDGETSET, request.getPortalContext()); + // No longer used as of #8924, but retained to maintain compatibility - String widgetset; - if (requestWidgetset != null) { - widgetset = requestWidgetset; - } else if (sharedWidgetset != null) { - widgetset = sharedWidgetset; - } else { - widgetset = DEFAULT_WIDGETSET; - } - String widgetsetURL = getWidgetsetURL(widgetset, request); - writer.write("document.write('');\n"); - writer.write("document.write(\"\n"); + page.write("\n"); + page.write("\n"); + if (themeName != null) { // Custom theme's stylesheet, load only once, in different // script -- cgit v1.2.3 From 45b2a35ec9789bd1c6ef9cd46de3ba6695279547 Mon Sep 17 00:00:00 2001 From: Leif Åstrand Date: Thu, 7 Jun 2012 13:40:30 +0000 Subject: Fix some typos in Portlet init javascript and html (#8924) svn changeset:23910/svn branch:6.8 --- src/com/vaadin/terminal/gwt/server/AbstractApplicationPortlet.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/com/vaadin/terminal/gwt/server/AbstractApplicationPortlet.java b/src/com/vaadin/terminal/gwt/server/AbstractApplicationPortlet.java index 26b0d3df1d..898bd2856c 100644 --- a/src/com/vaadin/terminal/gwt/server/AbstractApplicationPortlet.java +++ b/src/com/vaadin/terminal/gwt/server/AbstractApplicationPortlet.java @@ -1082,7 +1082,7 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet String widgetsetURL = getWidgetsetURL(request); writer.write("'\n"); + + "hidden;opacity:0;top:-100px;left:-100px;\" src=\"javascript:false\">\n"); writer.write("\n"); } @@ -1107,7 +1107,7 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet // No longer used as of #8924, but retained to maintain compatibility // But we still need to close this one block, for compatibility - writer.append("\\n}\\n"); + writer.append("\n}\n"); } /** -- cgit v1.2.3 From 07b20a1cd3118b744e361d02ca4a5607cccf124f Mon Sep 17 00:00:00 2001 From: Leif Åstrand Date: Thu, 7 Jun 2012 14:02:38 +0000 Subject: Prevent double iframe and script tags if writeAjaxPageScriptWidgetset is overridden (#8924) svn changeset:23911/svn branch:6.8 --- .../gwt/server/AbstractApplicationPortlet.java | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/src/com/vaadin/terminal/gwt/server/AbstractApplicationPortlet.java b/src/com/vaadin/terminal/gwt/server/AbstractApplicationPortlet.java index 898bd2856c..edc151f22d 100644 --- a/src/com/vaadin/terminal/gwt/server/AbstractApplicationPortlet.java +++ b/src/com/vaadin/terminal/gwt/server/AbstractApplicationPortlet.java @@ -76,6 +76,8 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet private static final String PORTAL_PARAMETER_VAADIN_THEME = "vaadin.theme"; + public static final String WRITE_AJAX_PAGE_SCRIPT_WIDGETSET_SHOULD_WRITE = "writeAjaxPageScriptWidgetsetShouldWrite"; + // TODO some parts could be shared with AbstractApplicationServlet // TODO Can we close the application when the portlet is removed? Do we know @@ -1071,7 +1073,8 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet /** * Writes the script to load the widgetset on the HTML fragment created by - * the portlet. + * the portlet if the request attribute + * WRITE_AJAX_PAGE_SCRIPT_WIDGETSET_SHOULD_WRITE is set to Boolean.TRUE. * * @param request * @param writer @@ -1079,6 +1082,14 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet */ protected void writeAjaxPageWidgetset(RenderRequest request, BufferedWriter writer) throws IOException { + /* + * If the old method that used to add this code using document.write has + * been overridden, we shouldn't do anything here because then the + * iframe and script tag have already been added. + */ + if (request.getAttribute(WRITE_AJAX_PAGE_SCRIPT_WIDGETSET_SHOULD_WRITE) != Boolean.TRUE) { + return; + } String widgetsetURL = getWidgetsetURL(request); writer.write("