summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore3
-rw-r--r--WebContent/VAADIN/themes/base/accordion/accordion.css1
-rw-r--r--WebContent/VAADIN/themes/base/common/common.css16
-rw-r--r--WebContent/VAADIN/themes/base/panel/panel.css1
-rw-r--r--WebContent/VAADIN/themes/liferay/window/window.css2
-rw-r--r--WebContent/release-notes.html18
-rw-r--r--WebContent/statictestfiles/dummy.zipbin0 -> 138 bytes
-rw-r--r--WebContent/statictestfiles/jsconnector.js13
-rw-r--r--WebContent/statictestfiles/jsextension.js24
-rw-r--r--build/bin/tagrelease.py16
-rw-r--r--build/build.xml66
-rw-r--r--src/com/vaadin/Application.java75
-rw-r--r--src/com/vaadin/annotations/LoadScripts.java24
-rw-r--r--src/com/vaadin/data/util/AbstractBeanContainer.java5
-rw-r--r--src/com/vaadin/data/util/AbstractInMemoryContainer.java4
-rw-r--r--src/com/vaadin/data/util/MethodProperty.java9
-rw-r--r--src/com/vaadin/data/util/MethodPropertyDescriptor.java12
-rw-r--r--src/com/vaadin/data/util/converter/ConverterUtil.java168
-rw-r--r--src/com/vaadin/data/util/sqlcontainer/SQLContainer.java129
-rw-r--r--src/com/vaadin/data/util/sqlcontainer/connection/J2EEConnectionPool.java5
-rw-r--r--src/com/vaadin/data/util/sqlcontainer/query/TableQuery.java29
-rw-r--r--src/com/vaadin/event/ListenerMethod.java16
-rw-r--r--src/com/vaadin/event/dd/acceptcriteria/AcceptAll.java2
-rw-r--r--src/com/vaadin/event/dd/acceptcriteria/And.java1
-rw-r--r--src/com/vaadin/event/dd/acceptcriteria/ClientCriterion.java29
-rw-r--r--src/com/vaadin/event/dd/acceptcriteria/ContainsDataFlavor.java2
-rw-r--r--src/com/vaadin/event/dd/acceptcriteria/Not.java2
-rw-r--r--src/com/vaadin/event/dd/acceptcriteria/Or.java2
-rw-r--r--src/com/vaadin/event/dd/acceptcriteria/ServerSideCriterion.java2
-rw-r--r--src/com/vaadin/event/dd/acceptcriteria/SourceIs.java14
-rw-r--r--src/com/vaadin/event/dd/acceptcriteria/SourceIsTarget.java2
-rw-r--r--src/com/vaadin/event/dd/acceptcriteria/TargetDetailIs.java2
-rw-r--r--src/com/vaadin/navigator/FragmentManager.java38
-rw-r--r--src/com/vaadin/navigator/Navigator.java586
-rw-r--r--src/com/vaadin/navigator/View.java36
-rw-r--r--src/com/vaadin/navigator/ViewChangeListener.java118
-rw-r--r--src/com/vaadin/navigator/ViewDisplay.java29
-rw-r--r--src/com/vaadin/navigator/ViewProvider.java44
-rw-r--r--src/com/vaadin/terminal/AbstractClientConnector.java490
-rw-r--r--src/com/vaadin/terminal/AbstractErrorMessage.java7
-rw-r--r--src/com/vaadin/terminal/AbstractExtension.java76
-rw-r--r--src/com/vaadin/terminal/AbstractJavaScriptExtension.java158
-rw-r--r--src/com/vaadin/terminal/ClassResource.java8
-rw-r--r--src/com/vaadin/terminal/CombinedRequest.java2
-rw-r--r--src/com/vaadin/terminal/Extension.java27
-rw-r--r--src/com/vaadin/terminal/JavaScriptCallbackHelper.java115
-rw-r--r--src/com/vaadin/terminal/Page.java646
-rw-r--r--src/com/vaadin/terminal/PaintTarget.java26
-rw-r--r--src/com/vaadin/terminal/UserError.java10
-rw-r--r--src/com/vaadin/terminal/gwt/DefaultWidgetSet.gwt.xml4
-rw-r--r--src/com/vaadin/terminal/gwt/client/ApplicationConfiguration.java41
-rw-r--r--src/com/vaadin/terminal/gwt/client/ApplicationConnection.java194
-rw-r--r--src/com/vaadin/terminal/gwt/client/BrowserInfo.java20
-rw-r--r--src/com/vaadin/terminal/gwt/client/ComponentConnector.java23
-rw-r--r--src/com/vaadin/terminal/gwt/client/ComponentContainerConnector.java12
-rw-r--r--src/com/vaadin/terminal/gwt/client/ComponentLocator.java28
-rw-r--r--src/com/vaadin/terminal/gwt/client/ComponentState.java24
-rw-r--r--src/com/vaadin/terminal/gwt/client/Connector.java8
-rw-r--r--src/com/vaadin/terminal/gwt/client/ConnectorMap.java33
-rw-r--r--src/com/vaadin/terminal/gwt/client/JavaScriptConnectorHelper.java372
-rw-r--r--src/com/vaadin/terminal/gwt/client/JavaScriptExtension.java32
-rw-r--r--src/com/vaadin/terminal/gwt/client/JavaScriptExtensionState.java36
-rw-r--r--src/com/vaadin/terminal/gwt/client/LayoutManager.java111
-rw-r--r--src/com/vaadin/terminal/gwt/client/LayoutManagerIE8.java44
-rw-r--r--src/com/vaadin/terminal/gwt/client/ServerConnector.java29
-rw-r--r--src/com/vaadin/terminal/gwt/client/Util.java31
-rw-r--r--src/com/vaadin/terminal/gwt/client/VDebugConsole.java47
-rw-r--r--src/com/vaadin/terminal/gwt/client/VUIDLBrowser.java4
-rw-r--r--src/com/vaadin/terminal/gwt/client/WidgetInstantiator.java2
-rw-r--r--src/com/vaadin/terminal/gwt/client/WidgetMap.java12
-rw-r--r--src/com/vaadin/terminal/gwt/client/WidgetSet.java55
-rw-r--r--src/com/vaadin/terminal/gwt/client/communication/DiffJSONSerializer.java19
-rw-r--r--src/com/vaadin/terminal/gwt/client/communication/GeneratedRpcMethodProvider.java20
-rw-r--r--src/com/vaadin/terminal/gwt/client/communication/HasJavaScriptConnectorHelper.java11
-rw-r--r--src/com/vaadin/terminal/gwt/client/communication/JSONSerializer.java13
-rw-r--r--src/com/vaadin/terminal/gwt/client/communication/JsonDecoder.java224
-rw-r--r--src/com/vaadin/terminal/gwt/client/communication/JsonEncoder.java185
-rw-r--r--src/com/vaadin/terminal/gwt/client/communication/RpcManager.java102
-rw-r--r--src/com/vaadin/terminal/gwt/client/communication/RpcMethod.java32
-rw-r--r--src/com/vaadin/terminal/gwt/client/communication/SharedState.java26
-rw-r--r--src/com/vaadin/terminal/gwt/client/communication/Type.java40
-rw-r--r--src/com/vaadin/terminal/gwt/client/communication/URLReference_Serializer.java24
-rw-r--r--src/com/vaadin/terminal/gwt/client/communication/UidlValue.java25
-rw-r--r--src/com/vaadin/terminal/gwt/client/extensions/AbstractExtensionConnector.java27
-rw-r--r--src/com/vaadin/terminal/gwt/client/extensions/javascriptmanager/ExecuteJavaScriptRpc.java11
-rw-r--r--src/com/vaadin/terminal/gwt/client/extensions/javascriptmanager/JavaScriptManagerConnector.java119
-rw-r--r--src/com/vaadin/terminal/gwt/client/extensions/javascriptmanager/JavaScriptManagerState.java22
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/AbstractBoxLayoutConnector.java18
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/AbstractClickEventHandler.java104
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/AbstractComponentConnector.java82
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/AbstractComponentContainerConnector.java41
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/AbstractConnector.java66
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/ClickEventHandler.java1
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/FocusableScrollPanel.java5
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/JavaScriptComponentConnector.java42
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/JavaScriptComponentState.java37
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/JavaScriptWidget.java25
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/TouchScrollDelegate.java111
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/absolutelayout/AbsoluteLayoutConnector.java8
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/accordion/VAccordion.java19
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/button/ButtonState.java25
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/button/VButton.java42
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/combobox/VFilterSelect.java37
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/csslayout/CssLayoutConnector.java4
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/customcomponent/CustomComponentConnector.java4
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/customlayout/CustomLayoutConnector.java2
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/dd/AcceptCriterion.java33
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/dd/DDUtil.java21
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/dd/VAcceptAll.java2
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/dd/VAnd.java2
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/dd/VContainsDataFlavor.java2
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/dd/VDragSourceIs.java2
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/dd/VIsOverId.java2
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/dd/VItemIdIs.java2
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/dd/VLazyInitItemIdentifiers.java16
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/dd/VNot.java2
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/dd/VOr.java2
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/dd/VServerAccept.java2
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/dd/VSourceIsTarget.java2
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/dd/VTargetDetailIs.java2
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/dd/VTargetInSubtree.java2
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/draganddropwrapper/DragAndDropWrapperConnector.java3
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/draganddropwrapper/VDragAndDropWrapper.java10
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/form/VForm.java5
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/formlayout/FormLayoutConnector.java4
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/formlayout/VFormLayout.java3
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/gridlayout/GridLayoutConnector.java4
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/helloworldfeature/GreetAgainRpc.java12
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/helloworldfeature/HelloWorldExtensionConnector.java48
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/helloworldfeature/HelloWorldRpc.java10
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/helloworldfeature/HelloWorldState.java18
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/label/ContentMode.java2
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/layout/LayoutDependencyTree.java23
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/nativebutton/VNativeButton.java7
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/notification/VNotification.java19
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/orderedlayout/AbstractOrderedLayoutConnector.java6
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/panel/PanelConnector.java6
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/panel/VPanel.java33
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/root/PageClientRpc.java13
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/root/RootConnector.java21
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/root/VRoot.java223
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/slider/VSlider.java17
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/splitpanel/AbstractSplitPanelConnector.java9
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/splitpanel/AbstractSplitPanelState.java36
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/splitpanel/VAbstractSplitPanel.java207
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/table/TableConnector.java8
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/table/VScrollTable.java242
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/tabsheet/VTabsheet.java15
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/tabsheet/VTabsheetPanel.java40
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/treetable/VTreeTable.java44
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/window/VWindow.java4
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/window/WindowConnector.java4
-rw-r--r--src/com/vaadin/terminal/gwt/server/AbstractApplicationPortlet.java90
-rw-r--r--src/com/vaadin/terminal/gwt/server/AbstractApplicationServlet.java94
-rw-r--r--src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java304
-rw-r--r--src/com/vaadin/terminal/gwt/server/AbstractWebApplicationContext.java9
-rw-r--r--src/com/vaadin/terminal/gwt/server/BootstrapHandler.java59
-rw-r--r--src/com/vaadin/terminal/gwt/server/ClientConnector.java96
-rw-r--r--src/com/vaadin/terminal/gwt/server/ClientMethodInvocation.java7
-rw-r--r--src/com/vaadin/terminal/gwt/server/CommunicationManager.java18
-rw-r--r--src/com/vaadin/terminal/gwt/server/ComponentSizeValidator.java13
-rw-r--r--src/com/vaadin/terminal/gwt/server/Constants.java2
-rw-r--r--src/com/vaadin/terminal/gwt/server/DragAndDropService.java59
-rw-r--r--src/com/vaadin/terminal/gwt/server/GAEApplicationServlet.java36
-rw-r--r--src/com/vaadin/terminal/gwt/server/JsonCodec.java456
-rw-r--r--src/com/vaadin/terminal/gwt/server/JsonPaintTarget.java37
-rw-r--r--src/com/vaadin/terminal/gwt/server/PortletApplicationContext2.java17
-rw-r--r--src/com/vaadin/terminal/gwt/server/PortletCommunicationManager.java6
-rw-r--r--src/com/vaadin/terminal/gwt/server/RpcManager.java33
-rw-r--r--src/com/vaadin/terminal/gwt/server/ServerRpcManager.java9
-rw-r--r--src/com/vaadin/terminal/gwt/server/ServerRpcMethodInvocation.java6
-rw-r--r--src/com/vaadin/terminal/gwt/server/WebBrowser.java50
-rw-r--r--src/com/vaadin/terminal/gwt/server/WrappedHttpServletRequest.java2
-rw-r--r--src/com/vaadin/terminal/gwt/server/WrappedPortletRequest.java2
-rw-r--r--src/com/vaadin/terminal/gwt/widgetsetutils/AcceptCriteriaFactoryGenerator.java40
-rw-r--r--src/com/vaadin/terminal/gwt/widgetsetutils/ClassPathExplorer.java252
-rw-r--r--src/com/vaadin/terminal/gwt/widgetsetutils/CustomWidgetMapGenerator.java4
-rw-r--r--src/com/vaadin/terminal/gwt/widgetsetutils/EagerWidgetMapGenerator.java5
-rw-r--r--src/com/vaadin/terminal/gwt/widgetsetutils/GeneratedRpcMethodProviderGenerator.java (renamed from src/com/vaadin/terminal/gwt/widgetsetutils/RpcManagerGenerator.java)138
-rw-r--r--src/com/vaadin/terminal/gwt/widgetsetutils/LazyWidgetMapGenerator.java5
-rw-r--r--src/com/vaadin/terminal/gwt/widgetsetutils/RpcProxyGenerator.java2
-rw-r--r--src/com/vaadin/terminal/gwt/widgetsetutils/SerializerGenerator.java266
-rw-r--r--src/com/vaadin/terminal/gwt/widgetsetutils/SerializerMapGenerator.java30
-rw-r--r--src/com/vaadin/terminal/gwt/widgetsetutils/WidgetMapGenerator.java62
-rw-r--r--src/com/vaadin/tools/WidgetsetCompiler.java14
-rw-r--r--src/com/vaadin/ui/AbsoluteLayout.java3
-rw-r--r--src/com/vaadin/ui/AbstractComponent.java396
-rw-r--r--src/com/vaadin/ui/AbstractComponentContainer.java70
-rw-r--r--src/com/vaadin/ui/AbstractField.java92
-rw-r--r--src/com/vaadin/ui/AbstractJavaScriptComponent.java161
-rw-r--r--src/com/vaadin/ui/AbstractSelect.java5
-rw-r--r--src/com/vaadin/ui/AbstractSplitPanel.java128
-rw-r--r--src/com/vaadin/ui/Button.java20
-rw-r--r--src/com/vaadin/ui/Component.java167
-rw-r--r--src/com/vaadin/ui/ConnectorTracker.java229
-rw-r--r--src/com/vaadin/ui/CssLayout.java5
-rw-r--r--src/com/vaadin/ui/CustomField.java31
-rw-r--r--src/com/vaadin/ui/DirtyConnectorTracker.java132
-rw-r--r--src/com/vaadin/ui/Form.java32
-rw-r--r--src/com/vaadin/ui/HasComponents.java11
-rw-r--r--src/com/vaadin/ui/HelloWorldExtension.java38
-rw-r--r--src/com/vaadin/ui/JavaScript.java146
-rw-r--r--src/com/vaadin/ui/JavaScriptCallback.java41
-rw-r--r--src/com/vaadin/ui/Label.java159
-rw-r--r--src/com/vaadin/ui/Link.java7
-rw-r--r--src/com/vaadin/ui/Notification.java50
-rw-r--r--src/com/vaadin/ui/Panel.java42
-rw-r--r--src/com/vaadin/ui/Root.java1057
-rw-r--r--src/com/vaadin/ui/TabSheet.java88
-rw-r--r--src/com/vaadin/ui/Table.java257
-rw-r--r--src/com/vaadin/ui/Tree.java5
-rw-r--r--src/com/vaadin/ui/TreeTable.java12
-rw-r--r--src/com/vaadin/ui/UniqueSerializable.java30
-rw-r--r--src/com/vaadin/ui/Window.java82
-rw-r--r--src/com/vaadin/ui/themes/ChameleonTheme.java2
-rw-r--r--tests/client-side/com/vaadin/terminal/gwt/server/JSONSerializerTest.java11
-rw-r--r--tests/server-side/com/vaadin/tests/VaadinClasses.java14
-rw-r--r--tests/server-side/com/vaadin/tests/data/bean/Person.java10
-rw-r--r--tests/server-side/com/vaadin/tests/data/converter/ConverterFactory.java100
-rw-r--r--tests/server-side/com/vaadin/tests/server/TestThemeNames.java38
-rw-r--r--tests/server-side/com/vaadin/tests/server/component/abstractcomponent/TestAbstractComponentStyleNames.java1
-rw-r--r--tests/server-side/com/vaadin/tests/server/component/abstractfield/AbstractFieldValueConversions.java42
-rw-r--r--tests/server-side/com/vaadin/tests/server/component/abstractfield/DefaultConverterFactory.java2
-rw-r--r--tests/server-side/com/vaadin/tests/server/component/abstractfield/RemoveListenersOnDetach.java13
-rw-r--r--tests/server-side/com/vaadin/tests/server/component/label/LabelConverters.java59
-rw-r--r--tests/server-side/com/vaadin/tests/server/component/table/TableSerialization.java24
-rw-r--r--tests/server-side/com/vaadin/tests/server/component/tabsheet/TestTabSheet.java63
-rw-r--r--tests/server-side/com/vaadin/tests/server/component/textfield/TextFieldWithPropertyFormatter.java15
-rw-r--r--tests/server-side/com/vaadin/tests/server/navigator/ClassBasedViewProviderTest.java117
-rw-r--r--tests/server-side/com/vaadin/tests/server/navigator/NavigatorTest.java569
-rw-r--r--tests/server-side/com/vaadin/tests/server/navigator/UriFragmentManagerTest.java51
-rw-r--r--tests/server-side/com/vaadin/tests/util/UniqueSerializableTest.java33
-rw-r--r--tests/test.xml4
-rw-r--r--tests/testbench/com/vaadin/launcher/ApplicationRunnerServlet.java14
-rw-r--r--tests/testbench/com/vaadin/tests/TestBench.java6
-rw-r--r--tests/testbench/com/vaadin/tests/TestComponentAddAndRecursion.java26
-rw-r--r--tests/testbench/com/vaadin/tests/TestForWindowOpen.java6
-rw-r--r--tests/testbench/com/vaadin/tests/TestForWindowing.java2
-rw-r--r--tests/testbench/com/vaadin/tests/appengine/GAESyncTest.java3
-rw-r--r--tests/testbench/com/vaadin/tests/application/TerminalErrorNotification.html36
-rw-r--r--tests/testbench/com/vaadin/tests/application/TerminalErrorNotification.java57
-rw-r--r--tests/testbench/com/vaadin/tests/application/ThreadLocalInstances.java8
-rw-r--r--tests/testbench/com/vaadin/tests/application/WebBrowserSizeTest.java6
-rw-r--r--tests/testbench/com/vaadin/tests/applicationservlet/NoApplicationClass.html26
-rw-r--r--tests/testbench/com/vaadin/tests/components/AbstractTestRoot.java4
-rw-r--r--tests/testbench/com/vaadin/tests/components/DisableEnableCascadeStyles.html250
-rw-r--r--tests/testbench/com/vaadin/tests/components/DisableEnableCascadeStyles.java142
-rw-r--r--tests/testbench/com/vaadin/tests/components/TestBase.java10
-rw-r--r--tests/testbench/com/vaadin/tests/components/TouchScrollables.java3
-rw-r--r--tests/testbench/com/vaadin/tests/components/beanitemcontainer/BeanItemContainerNullValues.java8
-rw-r--r--tests/testbench/com/vaadin/tests/components/button/ButtonEnterWithWindowShortcut.html62
-rw-r--r--tests/testbench/com/vaadin/tests/components/button/ButtonEnterWithWindowShortcut.java55
-rw-r--r--tests/testbench/com/vaadin/tests/components/button/ButtonTabIndex.java53
-rw-r--r--tests/testbench/com/vaadin/tests/components/combobox/ComboBoxInvalidNullSelection.html5
-rw-r--r--tests/testbench/com/vaadin/tests/components/customfield/AddressFormExample.java8
-rw-r--r--tests/testbench/com/vaadin/tests/components/customfield/BooleanFieldExample.java12
-rw-r--r--tests/testbench/com/vaadin/tests/components/draganddropwrapper/DragStartModes.html62
-rw-r--r--tests/testbench/com/vaadin/tests/components/draganddropwrapper/DragStartModes.java46
-rw-r--r--tests/testbench/com/vaadin/tests/components/draganddropwrapper/TooltipHandlingWhenNotDefined.html37
-rw-r--r--tests/testbench/com/vaadin/tests/components/draganddropwrapper/TooltipHandlingWhenNotDefined.java41
-rw-r--r--tests/testbench/com/vaadin/tests/components/formlayout/FormLayoutErrorHover.html47
-rw-r--r--tests/testbench/com/vaadin/tests/components/formlayout/FormLayoutErrorHover.java33
-rw-r--r--tests/testbench/com/vaadin/tests/components/formlayout/FormLayouts.java16
-rw-r--r--tests/testbench/com/vaadin/tests/components/gridlayout/GridLayoutInForm.java78
-rw-r--r--tests/testbench/com/vaadin/tests/components/javascriptcomponent/BasicJavaScriptComponent.java81
-rw-r--r--tests/testbench/com/vaadin/tests/components/notification/Notifications.java5
-rw-r--r--tests/testbench/com/vaadin/tests/components/notification/NotificationsAndModalWindow.html42
-rw-r--r--tests/testbench/com/vaadin/tests/components/notification/NotificationsAndModalWindow.java39
-rw-r--r--tests/testbench/com/vaadin/tests/components/notification/NotificationsHtmlAllowed.java12
-rw-r--r--tests/testbench/com/vaadin/tests/components/orderedlayout/LayoutClickListenerTest.html32
-rw-r--r--tests/testbench/com/vaadin/tests/components/panel/PanelChangeContents.html77
-rw-r--r--tests/testbench/com/vaadin/tests/components/panel/PanelChangeContents.java73
-rw-r--r--tests/testbench/com/vaadin/tests/components/panel/PanelClickListenerRelativeCoordinates.html6
-rw-r--r--tests/testbench/com/vaadin/tests/components/richtextarea/RichTextAreaWithKeyboardShortcuts.java3
-rw-r--r--tests/testbench/com/vaadin/tests/components/root/TestRootWidgetset.html36
-rw-r--r--tests/testbench/com/vaadin/tests/components/root/TestRootWidgetset.java7
-rw-r--r--tests/testbench/com/vaadin/tests/components/root/TestRootWidgetset2.java24
-rw-r--r--tests/testbench/com/vaadin/tests/components/root/UriFragmentTest.java8
-rw-r--r--tests/testbench/com/vaadin/tests/components/select/StylingPopupOpener.html32
-rw-r--r--tests/testbench/com/vaadin/tests/components/select/StylingPopupOpener.java38
-rw-r--r--tests/testbench/com/vaadin/tests/components/slider/SliderOrientation.html72
-rw-r--r--tests/testbench/com/vaadin/tests/components/slider/SliderTooltip.html67
-rw-r--r--tests/testbench/com/vaadin/tests/components/splitpanel/HorizontalSplitPanelSplitterClick.html5
-rw-r--r--tests/testbench/com/vaadin/tests/components/splitpanel/SplitPanelWithMinimumAndMaximum.html262
-rw-r--r--tests/testbench/com/vaadin/tests/components/splitpanel/SplitPanelWithMinimumAndMaximum.java332
-rw-r--r--tests/testbench/com/vaadin/tests/components/splitpanel/VerticalSplitPanelSplitterClick.html5
-rw-r--r--tests/testbench/com/vaadin/tests/components/table/HeaderClick.java2
-rw-r--r--tests/testbench/com/vaadin/tests/components/table/HeaderFooterClickLeftRightMiddle.java4
-rw-r--r--tests/testbench/com/vaadin/tests/components/table/MultiSelectWithNotIdentityEqualIds.java4
-rw-r--r--tests/testbench/com/vaadin/tests/components/table/RowUpdateShouldRetainContextMenu.html5
-rw-r--r--tests/testbench/com/vaadin/tests/components/table/ScrollCausesRequestLoop.java6
-rw-r--r--tests/testbench/com/vaadin/tests/components/table/ScrollDetachSynchronization.java2
-rw-r--r--tests/testbench/com/vaadin/tests/components/table/SortLabelsInTable.html192
-rw-r--r--tests/testbench/com/vaadin/tests/components/table/SortLabelsInTable.java38
-rw-r--r--tests/testbench/com/vaadin/tests/components/table/TableClickValueChangeInteraction.java2
-rw-r--r--tests/testbench/com/vaadin/tests/components/table/TableContextMenu.java3
-rw-r--r--tests/testbench/com/vaadin/tests/components/table/TableFirstRowFlicker.java85
-rw-r--r--tests/testbench/com/vaadin/tests/components/table/TableInTabsheet.java114
-rw-r--r--tests/testbench/com/vaadin/tests/components/table/TableShouldNotEatValueChanges.java4
-rw-r--r--tests/testbench/com/vaadin/tests/components/table/TableWithNoncollapsibleColumns.html82
-rw-r--r--tests/testbench/com/vaadin/tests/components/table/TableWithNoncollapsibleColumns.java83
-rw-r--r--tests/testbench/com/vaadin/tests/components/table/Tables.java11
-rw-r--r--tests/testbench/com/vaadin/tests/components/table/TestCurrentPageFirstItem.html37
-rw-r--r--tests/testbench/com/vaadin/tests/components/tabsheet/TabSheetWithDisappearingContent.html37
-rw-r--r--tests/testbench/com/vaadin/tests/components/tabsheet/TabSheetWithDisappearingContent.java34
-rw-r--r--tests/testbench/com/vaadin/tests/components/treetable/ComponentsInTreeTable.java50
-rw-r--r--tests/testbench/com/vaadin/tests/components/treetable/ProgrammaticCollapse.java10
-rw-r--r--tests/testbench/com/vaadin/tests/components/treetable/RowAnimation.html77
-rw-r--r--tests/testbench/com/vaadin/tests/components/treetable/TreeTableCacheOnPartialUpdate.html65
-rw-r--r--tests/testbench/com/vaadin/tests/components/window/DownloadAndUpdate.java45
-rw-r--r--tests/testbench/com/vaadin/tests/components/window/LazyWindowResize.java4
-rw-r--r--tests/testbench/com/vaadin/tests/components/window/RepaintWindowContents.html57
-rw-r--r--tests/testbench/com/vaadin/tests/components/window/RepaintWindowContents.java56
-rw-r--r--tests/testbench/com/vaadin/tests/components/window/SubWindowFocusAndBlurListeners.java9
-rw-r--r--tests/testbench/com/vaadin/tests/components/window/UndefinedHeightSubWindowAndContent.html57
-rw-r--r--tests/testbench/com/vaadin/tests/components/window/UndefinedHeightSubWindowAndContent.java58
-rw-r--r--tests/testbench/com/vaadin/tests/components/window/WindowClickEvents.html11
-rw-r--r--tests/testbench/com/vaadin/tests/components/window/WindowResizeListener.java6
-rw-r--r--tests/testbench/com/vaadin/tests/containers/TableWithFileSystemContainer.java2
-rw-r--r--tests/testbench/com/vaadin/tests/dd/NotPaintedAcceptSourceInTabSheet.java77
-rw-r--r--tests/testbench/com/vaadin/tests/dd/ScrolledDropTarget.html.disabled0
-rw-r--r--tests/testbench/com/vaadin/tests/dd/ScrolledDropTarget.java67
-rw-r--r--tests/testbench/com/vaadin/tests/debug/DebugWindowPresent.html72
-rw-r--r--tests/testbench/com/vaadin/tests/extensions/HelloWorldExtensionTest.java38
-rw-r--r--tests/testbench/com/vaadin/tests/extensions/JavascriptManagerTest.html47
-rw-r--r--tests/testbench/com/vaadin/tests/extensions/JavascriptManagerTest.java50
-rw-r--r--tests/testbench/com/vaadin/tests/extensions/SimpleJavaScriptExtensionTest.java116
-rw-r--r--tests/testbench/com/vaadin/tests/fieldgroup/AbstractBeanFieldGroupTest.java4
-rw-r--r--tests/testbench/com/vaadin/tests/fieldgroup/BasicPersonForm.java4
-rw-r--r--tests/testbench/com/vaadin/tests/fieldgroup/FieldBinderWithBeanValidation.java4
-rw-r--r--tests/testbench/com/vaadin/tests/integration/EmbedSizeTest.java11
-rw-r--r--tests/testbench/com/vaadin/tests/integration/JSR286PortletRoot.java (renamed from tests/testbench/com/vaadin/tests/integration/JSR286PortletApplication.java)44
-rw-r--r--tests/testbench/com/vaadin/tests/integration/LiferayThemeDemo.java28
-rw-r--r--tests/testbench/com/vaadin/tests/integration/PortletSizeInLiferayFreeformLayoutApplication.java31
-rw-r--r--tests/testbench/com/vaadin/tests/layouts/GridLayoutCaptions.java8
-rw-r--r--tests/testbench/com/vaadin/tests/layouts/GridLayoutExpandRatioModification.java4
-rw-r--r--tests/testbench/com/vaadin/tests/layouts/TestLayoutClickListeners.html128
-rw-r--r--tests/testbench/com/vaadin/tests/layouts/VerticalLayoutExpandRatioModification.java4
-rw-r--r--tests/testbench/com/vaadin/tests/minitutorials/v7a1/AutoGeneratingForm.java77
-rw-r--r--tests/testbench/com/vaadin/tests/minitutorials/v7a1/BasicApplication.java28
-rw-r--r--tests/testbench/com/vaadin/tests/minitutorials/v7a1/CreatingPreserveState.java31
-rw-r--r--tests/testbench/com/vaadin/tests/minitutorials/v7a1/CustomConverterFactoryRoot.java (renamed from tests/testbench/com/vaadin/tests/minitutorials/CustomConverterFactoryRoot.java)2
-rw-r--r--tests/testbench/com/vaadin/tests/minitutorials/v7a1/DefineRootTheme.java31
-rw-r--r--tests/testbench/com/vaadin/tests/minitutorials/v7a1/DifferentFeaturesForDifferentClients.java63
-rw-r--r--tests/testbench/com/vaadin/tests/minitutorials/v7a1/DynamicImageRoot.java (renamed from tests/testbench/com/vaadin/tests/minitutorials/DynamicImageRoot.java)2
-rw-r--r--tests/testbench/com/vaadin/tests/minitutorials/v7a1/FindCurrentRootAndApplication.java44
-rw-r--r--tests/testbench/com/vaadin/tests/minitutorials/v7a1/FormUsingExistingLayout.java (renamed from tests/testbench/com/vaadin/tests/minitutorials/FormUsingExistingLayout.java)2
-rw-r--r--tests/testbench/com/vaadin/tests/minitutorials/v7a1/FormatTableValue.java (renamed from tests/testbench/com/vaadin/tests/minitutorials/FormatTableValue.java)2
-rw-r--r--tests/testbench/com/vaadin/tests/minitutorials/v7a1/IntegerTextFieldDataSource.java (renamed from tests/testbench/com/vaadin/tests/minitutorials/IntegerTextFieldDataSource.java)13
-rw-r--r--tests/testbench/com/vaadin/tests/minitutorials/v7a1/IntegerTextFieldStandalone.java (renamed from tests/testbench/com/vaadin/tests/minitutorials/IntegerTextFieldStandalone.java)14
-rw-r--r--tests/testbench/com/vaadin/tests/minitutorials/v7a1/MultiTabApplication.java51
-rw-r--r--tests/testbench/com/vaadin/tests/minitutorials/v7a1/MyConverterFactory.java (renamed from tests/testbench/com/vaadin/tests/minitutorials/MyConverterFactory.java)2
-rw-r--r--tests/testbench/com/vaadin/tests/minitutorials/v7a1/MyStringToDoubleConverter.java (renamed from tests/testbench/com/vaadin/tests/minitutorials/MyStringToDoubleConverter.java)2
-rw-r--r--tests/testbench/com/vaadin/tests/minitutorials/v7a1/StringMyTypeConverter.java (renamed from tests/testbench/com/vaadin/tests/minitutorials/StringMyTypeConverter.java)10
-rw-r--r--tests/testbench/com/vaadin/tests/minitutorials/v7a1/UsingBeanValidation.java74
-rw-r--r--tests/testbench/com/vaadin/tests/minitutorials/v7a1/UsingUriFragments.java54
-rw-r--r--tests/testbench/com/vaadin/tests/minitutorials/v7a1/UsingXyzWhenInitializing.java52
-rw-r--r--tests/testbench/com/vaadin/tests/minitutorials/v7a2/ComponentInStateComponent.java26
-rw-r--r--tests/testbench/com/vaadin/tests/minitutorials/v7a2/ComponentInStateRoot.java27
-rw-r--r--tests/testbench/com/vaadin/tests/minitutorials/v7a2/MyComponent.java47
-rw-r--r--tests/testbench/com/vaadin/tests/minitutorials/v7a2/MyComponentRoot.java36
-rw-r--r--tests/testbench/com/vaadin/tests/minitutorials/v7a2/MyPickerConnector.java61
-rw-r--r--tests/testbench/com/vaadin/tests/minitutorials/v7a2/MyPickerWidget.java51
-rw-r--r--tests/testbench/com/vaadin/tests/minitutorials/v7a2/ResourceInStateComponent.java30
-rw-r--r--tests/testbench/com/vaadin/tests/minitutorials/v7a2/ResourceInStateRoot.java32
-rw-r--r--tests/testbench/com/vaadin/tests/minitutorials/v7a2/WidgetContainer.java46
-rw-r--r--tests/testbench/com/vaadin/tests/minitutorials/v7a2/WidgetcontainerRoot.java44
-rw-r--r--tests/testbench/com/vaadin/tests/serialization/SerializerTest.java273
-rw-r--r--tests/testbench/com/vaadin/tests/tickets/Ticket1465ModalNotification.java7
-rw-r--r--tests/testbench/com/vaadin/tests/tickets/Ticket2998.java4
-rw-r--r--tests/testbench/com/vaadin/tests/tickets/Ticket34.java8
-rw-r--r--tests/testbench/com/vaadin/tests/tickets/Ticket6002.java5
-rw-r--r--tests/testbench/com/vaadin/tests/util/TestUtils.java2
-rw-r--r--tests/testbench/com/vaadin/tests/validation/RequiredErrorMessage.java6
-rw-r--r--tests/testbench/com/vaadin/tests/widgetset/TestingWidgetSet.gwt.xml6
-rw-r--r--tests/testbench/com/vaadin/tests/widgetset/client/ComplexTestBean.java70
-rw-r--r--tests/testbench/com/vaadin/tests/widgetset/client/MissingFromDefaultWidgetsetConnector.java26
-rw-r--r--tests/testbench/com/vaadin/tests/widgetset/client/SerializerTestConnector.java227
-rw-r--r--tests/testbench/com/vaadin/tests/widgetset/client/SerializerTestRpc.java64
-rw-r--r--tests/testbench/com/vaadin/tests/widgetset/client/SimpleTestBean.java38
-rw-r--r--tests/testbench/com/vaadin/tests/widgetset/client/minitutorials/v7a2/ComponentInStateState.java20
-rw-r--r--tests/testbench/com/vaadin/tests/widgetset/client/minitutorials/v7a2/ComponentInStateStateConnector.java38
-rw-r--r--tests/testbench/com/vaadin/tests/widgetset/client/minitutorials/v7a2/MyComponentClientRpc.java9
-rw-r--r--tests/testbench/com/vaadin/tests/widgetset/client/minitutorials/v7a2/MyComponentConnector.java56
-rw-r--r--tests/testbench/com/vaadin/tests/widgetset/client/minitutorials/v7a2/MyComponentServerRpc.java10
-rw-r--r--tests/testbench/com/vaadin/tests/widgetset/client/minitutorials/v7a2/MyComponentState.java17
-rw-r--r--tests/testbench/com/vaadin/tests/widgetset/client/minitutorials/v7a2/MyComponentWidget.java16
-rw-r--r--tests/testbench/com/vaadin/tests/widgetset/client/minitutorials/v7a2/ResourceInStateConnector.java38
-rw-r--r--tests/testbench/com/vaadin/tests/widgetset/client/minitutorials/v7a2/ResourceInStateState.java17
-rw-r--r--tests/testbench/com/vaadin/tests/widgetset/client/minitutorials/v7a2/VWidgetContainer.java12
-rw-r--r--tests/testbench/com/vaadin/tests/widgetset/client/minitutorials/v7a2/WidgetContainerConnector.java35
-rw-r--r--tests/testbench/com/vaadin/tests/widgetset/server/MissingFromDefaultWidgetsetComponent.java10
-rw-r--r--tests/testbench/com/vaadin/tests/widgetset/server/SerializerTestExtension.java22
393 files changed, 16050 insertions, 4271 deletions
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
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 3c08a9d584..d2695a8015 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;
position: relative;
@@ -236,12 +235,17 @@ div.v-app-loading {
.v-drag-element {
z-index: 60000;
- position: absolute;
- opacity: 0.5;
- filter: alpha(opacity=50);
- cursor: default;
+ /* override any other position: properties */
+ position: absolute !important;
+ opacity: 0.5;
+ filter: alpha(opacity=50);
+ cursor: default;
}
.v-clip {
overflow: hidden;
-} \ No newline at end of file
+}
+
+.v-scrollable {
+ overflow: auto;
+}
diff --git a/WebContent/VAADIN/themes/base/panel/panel.css b/WebContent/VAADIN/themes/base/panel/panel.css
index 489d6bc015..d5a9915490 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;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
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;
diff --git a/WebContent/release-notes.html b/WebContent/release-notes.html
index 1b56b7fb9c..6f2eb8c2cc 100644
--- a/WebContent/release-notes.html
+++ b/WebContent/release-notes.html
@@ -76,7 +76,7 @@
purpose of receiving feedback about the changes.
</p>
- <p>The major changes in this second alpha phase are:
+ <p>The major changes in this second alpha phase are:</p>
<ul>
<li>Complete overhaul of the client-server communication architecture
@@ -354,15 +354,25 @@
</p>
<p>
- Vaadin supports the following <b>browsers</b>:
+ Vaadin supports the following <b>desktop browsers</b>:
</p>
<ul>
- <li>Mozilla Firefox 11</li>
+ <li>Mozilla Firefox 12</li>
<li>Internet Explorer 8-9</li>
<li>Safari 5</li>
<li>Opera 11</li>
- <li>Google Chrome 18</li>
+ <li>Google Chrome 19</li>
+ </ul>
+
+ <p>
+ Additionally, Vaadin supports the built-in browsers in the following
+ <b>mobile operating systems</b>:
+ </p>
+
+ <ul>
+ <li>iOS 4-5</li>
+ <li>Android 2-4</li>
</ul>
<h2 id="vaadinontheweb">Vaadin on the Web</h2>
diff --git a/WebContent/statictestfiles/dummy.zip b/WebContent/statictestfiles/dummy.zip
new file mode 100644
index 0000000000..e6e34282fe
--- /dev/null
+++ b/WebContent/statictestfiles/dummy.zip
Binary files differ
diff --git a/WebContent/statictestfiles/jsconnector.js b/WebContent/statictestfiles/jsconnector.js
new file mode 100644
index 0000000000..d7f697dbf5
--- /dev/null
+++ b/WebContent/statictestfiles/jsconnector.js
@@ -0,0 +1,13 @@
+window.com_vaadin_tests_components_javascriptcomponent_BasicJavaScriptComponent_ExampleWidget = function() {
+ var connector = this;
+
+ var rootElement = connector.getWidgetElement();
+ rootElement.innerHTML = 'Hello world!';
+ rootElement.onclick = function() {
+ connector.getRpcProxy().onClick("message");
+ connector.onclick("another message");
+ }
+ connector.onStateChange = function() {
+ console.log('state change:', this.getState());
+ }
+} \ No newline at end of file
diff --git a/WebContent/statictestfiles/jsextension.js b/WebContent/statictestfiles/jsextension.js
new file mode 100644
index 0000000000..1a46300e45
--- /dev/null
+++ b/WebContent/statictestfiles/jsextension.js
@@ -0,0 +1,24 @@
+window.com_vaadin_tests_extensions_SimpleJavaScriptExtensionTest_SimpleJavascriptExtension = function() {
+ var self = this;
+ var state = this.getState();
+
+ //var rpc = this.getRpcProxy("com.vaadin.tests.extensions.SimpleJavaScriptExtensionTest.SimpleJavaScriptExtensionServerRpc");
+ var rpc = this.getRpcProxy();
+
+// this.registerRpc("com.vaadin.tests.extensions.SimpleJavaScriptExtensionTest.SimpleJavaScriptExtensionClientRpc", {
+ this.registerRpc({
+ 'greet': function(greeting) {
+ var response = window.prompt(state.prefix + greeting);
+ if (response !== null) {
+ rpc.greet(response);
+ }
+ }
+ });
+
+ this.greetToClient = function(greeting) {
+ var response = window.prompt(state.prefix + greeting);
+ if (response !== null) {
+ self.greetToServer(response);
+ }
+ }
+} \ No newline at end of file
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 <command> [parameters...]"
print "Commands:"
- print "\ttag <version> <changeset> <manual-repository>"
+ print "\ttag <version> <changeset>"
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:
diff --git a/build/build.xml b/build/build.xml
index 573c799f7d..97f7c1c274 100644
--- a/build/build.xml
+++ b/build/build.xml
@@ -26,9 +26,26 @@
<target name="init-deps" depends="common.init-deps" >
<property name="ivy.resolved" value="1" />
<ivy:resolve file="build/ivy/ivy.xml" resolveid="common" conf="ss.compile, cs.compile, ss.test.compile"/>
- <ivy:cachepath pathid="compile.classpath.server-side" conf="ss.compile"/>
- <ivy:cachepath pathid="compile.classpath.client-side" conf="cs.compile"/>
- <ivy:cachepath pathid="compile.classpath.server-side-tests" conf="ss.test.compile"/>
+ <ivy:cachepath pathid="ivy.compile.classpath.server-side" conf="ss.compile"/>
+ <ivy:cachepath pathid="ivy.compile.classpath.client-side" conf="cs.compile"/>
+ <ivy:cachepath pathid="ivy.compile.classpath.server-side-tests" conf="ss.test.compile"/>
+ <!-- Extra JARs for custom builds - taken into account before JARs from Ivy. -->
+ <!-- Note that this should not be used for permanent build dependencies. -->
+ <path id="additional.jar.path">
+ <fileset dir="build" includes="lib/**/*.jar" ></fileset>
+ </path>
+ <path id="compile.classpath.server-side">
+ <path refid="additional.jar.path" />
+ <path refid="ivy.compile.classpath.server-side" />
+ </path>
+ <path id="compile.classpath.client-side">
+ <path refid="additional.jar.path" />
+ <path refid="ivy.compile.classpath.client-side" />
+ </path>
+ <path id="compile.classpath.server-side-tests">
+ <path refid="additional.jar.path" />
+ <path refid="ivy.compile.classpath.server-side-tests" />
+ </path>
</target>
<!-- Clean results - - - - - - - - - - - - - - - - - - - - - - - - - -->
@@ -38,7 +55,7 @@
<delete dir="${result-path}" includes="**/*" followsymlinks="false" defaultexcludes="false" includeemptydirs="true" failonerror="false"/>
</target>
- <target name="build.properties">
+ <target name="build.properties" depends="init-deps">
<property file="build/build.properties" />
<property file="build/VERSION.properties" />
@@ -55,8 +72,19 @@
<property name="result-classes-core-for-emma-war" value="${result-path}/classes/emma-war"/>
<property name="result-classes-core-for-emma-junit" value="${result-path}/classes/emma-junit"/>
+ <!-- Default classpath for building widgetsets, overridden for testing widgetset -->
+ <path id="compile.classpath.widgetset">
+ <path refid="compile.classpath.client-side" />
+ <pathelement location="${result-classes-core}" />
+ <pathelement location="${result-src-core}" />
+ </path>
</target>
<target name="clean-all" depends="clean-result">
+ <delete failonerror="false">
+ <fileset dir="${com.vaadin.testbench.screenshot.directory}/errors">
+ <include name="*.png" />
+ </fileset>
+ </delete>
</target>
<!-- ================================================================== -->
@@ -488,16 +516,11 @@
<target name="compile-widgetset" depends="init-deps">
<fail unless="widgetset" message="No widgetset parameter set"/>
<property name="widgetset-style" value="OBF" />
- <property name="widgetset-localWorkers" value="4" />
+ <property name="widgetset-localWorkers" value="2" />
<property name="widgetset-extraParams" value="" />
<echo>Compiling widgetset ${widgetset}. Output directory: ${widgetsets-output-dir}</echo>
<mkdir dir="${widgetsets-output-dir}"/>
- <java classname="com.google.gwt.dev.Compiler" failonerror="yes" fork="yes" maxmemory="512m">
- <classpath>
- <path refid="compile.classpath.client-side" />
- <pathelement location="${result-classes-core}" />
- <pathelement location="${result-src-core}" />
- </classpath>
+ <java classname="com.google.gwt.dev.Compiler" classpathref="compile.classpath.widgetset" failonerror="yes" fork="yes" maxmemory="512m">
<arg value="-war" />
<arg value="${widgetsets-output-dir}" />
<arg value="-style" />
@@ -519,14 +542,27 @@
<target name="compile-widgetset-default">
<antcall target="compile-widgetset">
- <reference refid="compile.classpath.client-side" />
+ <reference refid="compile.classpath.widgetset" />
<param name="widgetset" value="com.vaadin.terminal.gwt.DefaultWidgetSet"/>
</antcall>
</target>
+ <target name="compile-widgetset-testing">
+ <!-- Crate a path reference containing default widgetset classpath + testbench files -->
+ <path id="compile.classpath.testingwidgetset">
+ <path refid="compile.classpath.widgetset" />
+ <pathelement location="${result-classes-testbench}" />
+ <pathelement location="${result-src-testbench}" />
+ </path>
+ <antcall target="compile-widgetset">
+ <reference refid="compile.classpath.testingwidgetset" torefid="compile.classpath.widgetset" />
+ <param name="widgetset" value="com.vaadin.tests.widgetset.TestingWidgetSet"/>
+ </antcall>
+ </target>
+
<target name="compile-widgetset-portal-default" unless="compile.only.default-widgetset">
<antcall target="compile-widgetset">
- <reference refid="compile.classpath.client-side" />
+ <reference refid="compile.classpath.widgetset" />
<param name="widgetset" value="com.vaadin.portal.gwt.PortalDefaultWidgetSet"/>
</antcall>
</target>
@@ -534,10 +570,11 @@
<!-- Compiles all widgetsets. -->
<!-- This is called when building packages and when compiling all -->
<!-- widgetsets, but not when compiling individual widgetsets. -->
- <target name="compile-client-side" depends="compile-server-side">
+ <target name="compile-client-side" depends="compile-server-side, compile-tests">
<echo>Compiling widget sets in parallel.</echo>
<parallel threadsperprocessor="1">
<antcall inheritrefs="true" target="compile-widgetset-default"/>
+ <antcall inheritrefs="true" target="compile-widgetset-testing"/>
<antcall inheritrefs="true" target="compile-widgetset-portal-default"/>
</parallel>
</target>
@@ -556,6 +593,7 @@
<!-- Build each widgetset locally, i.e., not for an installation package. -->
<target name="widgetset-default" depends="init-nonpackage, init, compile-widgetset-generator, compile-widgetset-default" description="Compile the DefaultWidgetSet"/>
+ <target name="widgetset-testing" depends="init-nonpackage, init, compile-tests, compile-widgetset-generator, compile-widgetset-testing"/>
<target name="widgetset-portal-default" depends="init-nonpackage, init, compile-widgetset-generator, compile-widgetset-portal-default"/>
<!-- ================================================================== -->
diff --git a/src/com/vaadin/Application.java b/src/com/vaadin/Application.java
index 4da1d52c00..84a8df5053 100644
--- a/src/com/vaadin/Application.java
+++ b/src/com/vaadin/Application.java
@@ -18,7 +18,6 @@ import java.util.EventObject;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
-import java.util.Iterator;
import java.util.LinkedList;
import java.util.Locale;
import java.util.Map;
@@ -48,14 +47,12 @@ import com.vaadin.terminal.WrappedRequest;
import com.vaadin.terminal.WrappedRequest.BrowserDetails;
import com.vaadin.terminal.WrappedResponse;
import com.vaadin.terminal.gwt.client.ApplicationConnection;
-import com.vaadin.terminal.gwt.client.Connector;
import com.vaadin.terminal.gwt.server.AbstractApplicationServlet;
import com.vaadin.terminal.gwt.server.ChangeVariablesErrorEvent;
import com.vaadin.terminal.gwt.server.ClientConnector;
import com.vaadin.terminal.gwt.server.WebApplicationContext;
import com.vaadin.ui.AbstractComponent;
import com.vaadin.ui.AbstractField;
-import com.vaadin.ui.Component;
import com.vaadin.ui.Root;
import com.vaadin.ui.Table;
import com.vaadin.ui.Window;
@@ -194,6 +191,7 @@ public class Application implements Terminal.ErrorListener, Serializable {
* @see #getWindow(String)
* @see Application#getRoot(WrappedRequest)
*/
+
@Override
public Root.LegacyWindow getRoot(WrappedRequest request) {
String pathInfo = request.getRequestPathInfo();
@@ -246,6 +244,7 @@ public class Application implements Terminal.ErrorListener, Serializable {
* <p>
* {@inheritDoc}
*/
+
@Override
public String getThemeForRoot(Root root) {
return theme;
@@ -1066,12 +1065,14 @@ public class Application implements Terminal.ErrorListener, Serializable {
* the change event.
* @see com.vaadin.terminal.Terminal.ErrorListener#terminalError(com.vaadin.terminal.Terminal.ErrorEvent)
*/
+
public void terminalError(Terminal.ErrorEvent event) {
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;
}
@@ -1090,7 +1091,7 @@ public class Application implements Terminal.ErrorListener, Serializable {
}
// also print the error on console
- logger.log(Level.SEVERE, "Terminal error:", t);
+ getLogger().log(Level.SEVERE, "Terminal error:", t);
}
/**
@@ -2118,11 +2119,11 @@ public class Application implements Terminal.ErrorListener, Serializable {
* @return the current application instance if available, otherwise
* <code>null</code>
*
- * @see #setCurrentApplication(Application)
+ * @see #setCurrent(Application)
*
* @since 7.0
*/
- public static Application getCurrentApplication() {
+ public static Application getCurrent() {
return currentApplication.get();
}
@@ -2138,12 +2139,12 @@ public class Application implements Terminal.ErrorListener, Serializable {
*
* @param application
*
- * @see #getCurrentApplication()
+ * @see #getCurrent()
* @see ThreadLocal
*
* @since 7.0
*/
- public static void setCurrentApplication(Application application) {
+ public static void setCurrent(Application application) {
currentApplication.set(application);
}
@@ -2187,7 +2188,7 @@ public class Application implements Terminal.ErrorListener, Serializable {
*/
public Root getRootForRequest(WrappedRequest request)
throws RootRequiresMoreInformationException {
- Root root = Root.getCurrentRoot();
+ Root root = Root.getCurrent();
if (root != null) {
return root;
}
@@ -2239,7 +2240,7 @@ public class Application implements Terminal.ErrorListener, Serializable {
}
// Set thread local here so it is available in init
- Root.setCurrentRoot(root);
+ Root.setCurrent(root);
if (!initedRoots.contains(rootId)) {
boolean initRequiresBrowserDetails = isRootPreserved()
@@ -2355,8 +2356,6 @@ public class Application implements Terminal.ErrorListener, Serializable {
return Collections.unmodifiableCollection(roots.values());
}
- private final HashMap<String, ClientConnector> connectorIdToConnector = new HashMap<String, ClientConnector>();
-
private int connectorIdSequence = 0;
/**
@@ -2368,52 +2367,10 @@ public class Application implements Terminal.ErrorListener, Serializable {
* @return A new id for the connector
*/
public String createConnectorId(ClientConnector connector) {
- String connectorId = String.valueOf(connectorIdSequence++);
- Connector oldReference = connectorIdToConnector.put(connectorId,
- connector);
- if (oldReference != null) {
- throw new RuntimeException(
- "An error occured while generating connector ids. A connector with id "
- + connectorId + " was already found!");
- }
- return connectorId;
- }
-
- /**
- * Gets a connector by its id.
- *
- * @param connectorId
- * The connector id to look for
- * @return The connector with the given id or null if no connector has the
- * given id
- */
- public ClientConnector getConnector(String connectorId) {
- return connectorIdToConnector.get(connectorId);
+ return String.valueOf(connectorIdSequence++);
}
- /**
- * Cleans the connector map from all connectors that are no longer attached
- * to the application. This should only be called by the framework.
- */
- public void cleanConnectorMap() {
- // remove detached components from paintableIdMap so they
- // can be GC'ed
- Iterator<String> iterator = connectorIdToConnector.keySet().iterator();
-
- while (iterator.hasNext()) {
- String connectorId = iterator.next();
- Connector connector = connectorIdToConnector.get(connectorId);
- if (connector instanceof Component) {
- Component component = (Component) connector;
- if (component.getApplication() != this) {
- // If component is no longer part of this application,
- // remove it from the map. If it is re-attached to the
- // application at some point it will be re-added to this
- // collection when sent to the client.
- iterator.remove();
- }
- }
- }
-
+ private static final Logger getLogger() {
+ return Logger.getLogger(Application.class.getName());
}
}
diff --git a/src/com/vaadin/annotations/LoadScripts.java b/src/com/vaadin/annotations/LoadScripts.java
new file mode 100644
index 0000000000..84ac2d2fb7
--- /dev/null
+++ b/src/com/vaadin/annotations/LoadScripts.java
@@ -0,0 +1,24 @@
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+package com.vaadin.annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Temporary hack used for ensuring external javascript libraries are included.
+ * To add a javascript, add this annotation to your Root class.
+ *
+ * @deprecated Will be removed in favor of a more robust solution before version
+ * 7.0.0
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.TYPE)
+@Deprecated
+public @interface LoadScripts {
+ public String[] value();
+
+}
diff --git a/src/com/vaadin/data/util/AbstractBeanContainer.java b/src/com/vaadin/data/util/AbstractBeanContainer.java
index bed3ca0450..300f92ea3a 100644
--- a/src/com/vaadin/data/util/AbstractBeanContainer.java
+++ b/src/com/vaadin/data/util/AbstractBeanContainer.java
@@ -8,6 +8,7 @@ import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
+import java.util.List;
import java.util.Map;
import com.vaadin.data.Container;
@@ -247,8 +248,8 @@ public abstract class AbstractBeanContainer<IDTYPE, BEANTYPE> extends
*/
@Override
@SuppressWarnings("unchecked")
- public Collection<IDTYPE> getItemIds() {
- return (Collection<IDTYPE>) super.getItemIds();
+ public List<IDTYPE> getItemIds() {
+ return (List<IDTYPE>) super.getItemIds();
}
/*
diff --git a/src/com/vaadin/data/util/AbstractInMemoryContainer.java b/src/com/vaadin/data/util/AbstractInMemoryContainer.java
index cc7f469c0c..795aabb419 100644
--- a/src/com/vaadin/data/util/AbstractInMemoryContainer.java
+++ b/src/com/vaadin/data/util/AbstractInMemoryContainer.java
@@ -165,8 +165,8 @@ public abstract class AbstractInMemoryContainer<ITEMIDTYPE, PROPERTYIDCLASS, ITE
}
}
- public Collection<?> getItemIds() {
- return Collections.unmodifiableCollection(getVisibleItemIds());
+ public List<?> getItemIds() {
+ return Collections.unmodifiableList(getVisibleItemIds());
}
// Container.Ordered
diff --git a/src/com/vaadin/data/util/MethodProperty.java b/src/com/vaadin/data/util/MethodProperty.java
index 4fc5531320..7df45e04ab 100644
--- a/src/com/vaadin/data/util/MethodProperty.java
+++ b/src/com/vaadin/data/util/MethodProperty.java
@@ -48,8 +48,6 @@ import com.vaadin.util.SerializerHelper;
@SuppressWarnings("serial")
public class MethodProperty<T> extends AbstractProperty<T> {
- private static final Logger logger = Logger.getLogger(MethodProperty.class
- .getName());
/**
* The object that includes the property the MethodProperty is bound to.
*/
@@ -130,9 +128,9 @@ public class MethodProperty<T> extends AbstractProperty<T> {
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);
}
};
@@ -777,4 +775,7 @@ public class MethodProperty<T> extends AbstractProperty<T> {
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 10faa7a0f3..5fdb982b9e 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<BT> implements
VaadinPropertyDescriptor<BT> {
- 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<BT> 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,7 @@ public class MethodPropertyDescriptor<BT> 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/converter/ConverterUtil.java b/src/com/vaadin/data/util/converter/ConverterUtil.java
new file mode 100644
index 0000000000..7011496ed7
--- /dev/null
+++ b/src/com/vaadin/data/util/converter/ConverterUtil.java
@@ -0,0 +1,168 @@
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+package com.vaadin.data.util.converter;
+
+import java.io.Serializable;
+import java.util.Locale;
+
+import com.vaadin.Application;
+
+public class ConverterUtil implements Serializable {
+
+ /**
+ * Finds a converter that can convert from the given presentation type to
+ * the given model type and back. Uses the given application to find a
+ * {@link ConverterFactory} or, if application is null, uses the
+ * {@link Application#getCurrent()}.
+ *
+ * @param <PRESENTATIONTYPE>
+ * The presentation type
+ * @param <MODELTYPE>
+ * The model type
+ * @param presentationType
+ * The presentation type
+ * @param modelType
+ * The model type
+ * @param application
+ * The application to use to find a ConverterFactory or null to
+ * use the current application
+ * @return A Converter capable of converting between the given types or null
+ * if no converter was found
+ */
+ public static <PRESENTATIONTYPE, MODELTYPE> Converter<PRESENTATIONTYPE, MODELTYPE> getConverter(
+ Class<PRESENTATIONTYPE> presentationType,
+ Class<MODELTYPE> modelType, Application application) {
+ Converter<PRESENTATIONTYPE, MODELTYPE> converter = null;
+ if (application == null) {
+ application = Application.getCurrent();
+ }
+
+ if (application != null) {
+ ConverterFactory factory = application.getConverterFactory();
+ converter = factory.createConverter(presentationType, modelType);
+ }
+ return converter;
+
+ }
+
+ /**
+ * Convert the given value from the data source type to the UI type.
+ *
+ * @param modelValue
+ * The model value to convert
+ * @param presentationType
+ * The type of the presentation value
+ * @param converter
+ * The converter to (try to) use
+ * @param locale
+ * The locale to use for conversion
+ * @param <PRESENTATIONTYPE>
+ * Presentation type
+ *
+ * @return The converted value, compatible with the presentation type, or
+ * the original value if its type is compatible and no converter is
+ * set.
+ * @throws Converter.ConversionException
+ * if there is no converter and the type is not compatible with
+ * the model type.
+ */
+ @SuppressWarnings("unchecked")
+ public static <PRESENTATIONTYPE, MODELTYPE> PRESENTATIONTYPE convertFromModel(
+ MODELTYPE modelValue,
+ Class<? extends PRESENTATIONTYPE> presentationType,
+ Converter<PRESENTATIONTYPE, MODELTYPE> converter, Locale locale)
+ throws Converter.ConversionException {
+ if (converter != null) {
+ return converter.convertToPresentation(modelValue, locale);
+ }
+ if (modelValue == null) {
+ return null;
+ }
+
+ if (presentationType.isAssignableFrom(modelValue.getClass())) {
+ return (PRESENTATIONTYPE) modelValue;
+ } else {
+ throw new Converter.ConversionException(
+ "Unable to convert value of type "
+ + modelValue.getClass().getName()
+ + " to presentation type "
+ + presentationType
+ + ". No converter is set and the types are not compatible.");
+ }
+ }
+
+ /**
+ * @param <MODELTYPE>
+ * @param <PRESENTATIONTYPE>
+ * @param presentationValue
+ * @param modelType
+ * @param converter
+ * @param locale
+ * @return
+ * @throws Converter.ConversionException
+ */
+ public static <MODELTYPE, PRESENTATIONTYPE> MODELTYPE convertToModel(
+ PRESENTATIONTYPE presentationValue, Class<MODELTYPE> modelType,
+ Converter<PRESENTATIONTYPE, MODELTYPE> converter, Locale locale)
+ throws Converter.ConversionException {
+ if (converter != null) {
+ /*
+ * If there is a converter, always use it. It must convert or throw
+ * an exception.
+ */
+ return converter.convertToModel(presentationValue, locale);
+ }
+
+ if (presentationValue == null) {
+ // Null should always be passed through the converter but if there
+ // is no converter we can safely return null
+ return null;
+ }
+
+ if (modelType == null) {
+ // No model type, return original value
+ return (MODELTYPE) presentationValue;
+ } else if (modelType.isAssignableFrom(presentationValue.getClass())) {
+ // presentation type directly compatible with model type
+ return modelType.cast(presentationValue);
+ } else {
+ throw new Converter.ConversionException(
+ "Unable to convert value of type "
+ + presentationValue.getClass().getName()
+ + " to model type "
+ + modelType
+ + ". No converter is set and the types are not compatible.");
+ }
+
+ }
+
+ /**
+ * Checks if the given converter can handle conversion between the given
+ * presentation and model type
+ *
+ * @param converter
+ * The converter to check
+ * @param presentationType
+ * The presentation type
+ * @param modelType
+ * The model type
+ * @return true if the converter supports conversion between the given
+ * presentation and model type, false otherwise
+ */
+ public static boolean canConverterHandle(Converter<?, ?> converter,
+ Class<?> presentationType, Class<?> modelType) {
+ if (converter == null) {
+ return false;
+ }
+
+ if (!modelType.isAssignableFrom(converter.getModelType())) {
+ return false;
+ }
+ if (!presentationType.isAssignableFrom(converter.getPresentationType())) {
+ return false;
+ }
+
+ return true;
+ }
+}
diff --git a/src/com/vaadin/data/util/sqlcontainer/SQLContainer.java b/src/com/vaadin/data/util/sqlcontainer/SQLContainer.java
index 3bf33defd5..e9b5b4fea3 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 */
@@ -132,6 +129,7 @@ public class SQLContainer implements Container, Container.Filterable,
*
* {@inheritDoc}
*/
+
public Object addItem() throws UnsupportedOperationException {
Object emptyKey[] = new Object[delegate.getPrimaryKeyColumns().size()];
RowId itemId = new TemporaryRowId(emptyKey);
@@ -162,15 +160,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;
@@ -187,6 +185,7 @@ public class SQLContainer implements Container, Container.Filterable,
*
* @see com.vaadin.data.Container#containsId(java.lang.Object)
*/
+
public boolean containsId(Object itemId) {
if (itemId == null) {
return false;
@@ -215,7 +214,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;
@@ -227,6 +226,7 @@ public class SQLContainer implements Container, Container.Filterable,
* @see com.vaadin.data.Container#getContainerProperty(java.lang.Object,
* java.lang.Object)
*/
+
public Property<?> getContainerProperty(Object itemId, Object propertyId) {
Item item = getItem(itemId);
if (item == null) {
@@ -240,6 +240,7 @@ public class SQLContainer implements Container, Container.Filterable,
*
* @see com.vaadin.data.Container#getContainerPropertyIds()
*/
+
public Collection<?> getContainerPropertyIds() {
return Collections.unmodifiableCollection(propertyIds);
}
@@ -249,6 +250,7 @@ public class SQLContainer implements Container, Container.Filterable,
*
* @see com.vaadin.data.Container#getItem(java.lang.Object)
*/
+
public Item getItem(Object itemId) {
if (!cachedItems.containsKey(itemId)) {
int index = indexOfId(itemId);
@@ -295,6 +297,7 @@ public class SQLContainer implements Container, Container.Filterable,
*
* {@inheritDoc}
*/
+
public Collection<?> getItemIds() {
updateCount();
ArrayList<RowId> ids = new ArrayList<RowId>();
@@ -325,17 +328,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);
}
@@ -350,6 +354,7 @@ public class SQLContainer implements Container, Container.Filterable,
*
* @see com.vaadin.data.Container#getType(java.lang.Object)
*/
+
public Class<?> getType(Object propertyId) {
if (!propertyIds.contains(propertyId)) {
return null;
@@ -362,6 +367,7 @@ public class SQLContainer implements Container, Container.Filterable,
*
* @see com.vaadin.data.Container#size()
*/
+
public int size() {
updateCount();
return size + sizeOfAddedItems() - removedItems.size();
@@ -372,6 +378,7 @@ public class SQLContainer implements Container, Container.Filterable,
*
* @see com.vaadin.data.Container#removeItem(java.lang.Object)
*/
+
public boolean removeItem(Object itemId)
throws UnsupportedOperationException {
if (!containsId(itemId)) {
@@ -400,29 +407,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;
}
@@ -439,6 +446,7 @@ public class SQLContainer implements Container, Container.Filterable,
*
* @see com.vaadin.data.Container#removeAllItems()
*/
+
public boolean removeAllItems() throws UnsupportedOperationException {
if (autoCommit) {
/* Remove and commit instantly. */
@@ -452,7 +460,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 +470,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;
}
@@ -499,6 +507,7 @@ public class SQLContainer implements Container, Container.Filterable,
/**
* {@inheritDoc}
*/
+
public void addContainerFilter(Filter filter)
throws UnsupportedFilterException {
// filter.setCaseSensitive(!ignoreCase);
@@ -510,6 +519,7 @@ public class SQLContainer implements Container, Container.Filterable,
/**
* {@inheritDoc}
*/
+
public void removeContainerFilter(Filter filter) {
filters.remove(filter);
}
@@ -549,6 +559,7 @@ public class SQLContainer implements Container, Container.Filterable,
/**
* {@inheritDoc}
*/
+
public void removeAllContainerFilters() {
filters.clear();
refresh();
@@ -563,6 +574,7 @@ public class SQLContainer implements Container, Container.Filterable,
*
* @see com.vaadin.data.Container.Indexed#indexOfId(java.lang.Object)
*/
+
public int indexOfId(Object itemId) {
// First check if the id is in the added items
for (int ix = 0; ix < addedItems.size(); ix++) {
@@ -609,6 +621,7 @@ public class SQLContainer implements Container, Container.Filterable,
*
* @see com.vaadin.data.Container.Indexed#getIdByIndex(int)
*/
+
public Object getIdByIndex(int index) {
if (index < 0 || index > size() - 1) {
return null;
@@ -635,6 +648,7 @@ public class SQLContainer implements Container, Container.Filterable,
*
* @see com.vaadin.data.Container.Ordered#nextItemId(java.lang.Object)
*/
+
public Object nextItemId(Object itemId) {
return getIdByIndex(indexOfId(itemId) + 1);
}
@@ -644,6 +658,7 @@ public class SQLContainer implements Container, Container.Filterable,
*
* @see com.vaadin.data.Container.Ordered#prevItemId(java.lang.Object)
*/
+
public Object prevItemId(Object itemId) {
return getIdByIndex(indexOfId(itemId) - 1);
}
@@ -653,6 +668,7 @@ public class SQLContainer implements Container, Container.Filterable,
*
* @see com.vaadin.data.Container.Ordered#firstItemId()
*/
+
public Object firstItemId() {
updateCount();
if (size == 0) {
@@ -680,6 +696,7 @@ public class SQLContainer implements Container, Container.Filterable,
*
* @see com.vaadin.data.Container.Ordered#lastItemId()
*/
+
public Object lastItemId() {
if (addedItems.isEmpty()) {
int lastIx = size() - 1;
@@ -705,6 +722,7 @@ public class SQLContainer implements Container, Container.Filterable,
*
* @see com.vaadin.data.Container.Ordered#isFirstId(java.lang.Object)
*/
+
public boolean isFirstId(Object itemId) {
return firstItemId().equals(itemId);
}
@@ -714,6 +732,7 @@ public class SQLContainer implements Container, Container.Filterable,
*
* @see com.vaadin.data.Container.Ordered#isLastId(java.lang.Object)
*/
+
public boolean isLastId(Object itemId) {
return lastItemId().equals(itemId);
}
@@ -728,6 +747,7 @@ public class SQLContainer implements Container, Container.Filterable,
* @see com.vaadin.data.Container.Sortable#sort(java.lang.Object[],
* boolean[])
*/
+
public void sort(Object[] propertyId, boolean[] ascending) {
sorters.clear();
if (propertyId == null || propertyId.length == 0) {
@@ -743,7 +763,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));
}
@@ -756,6 +776,7 @@ public class SQLContainer implements Container, Container.Filterable,
*
* @see com.vaadin.data.Container.Sortable#getSortableContainerPropertyIds()
*/
+
public Collection<?> getSortableContainerPropertyIds() {
return getContainerPropertyIds();
}
@@ -872,7 +893,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 +948,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 +978,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 +1031,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 +1047,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 +1092,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 +1118,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 +1135,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 +1158,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 +1240,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 +1260,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);
}
@@ -1324,6 +1350,7 @@ public class SQLContainer implements Container, Container.Filterable,
* @see com.vaadin.data.Container#addContainerProperty(java.lang.Object,
* java.lang.Class, java.lang.Object)
*/
+
public boolean addContainerProperty(Object propertyId, Class<?> type,
Object defaultValue) throws UnsupportedOperationException {
throw new UnsupportedOperationException();
@@ -1334,6 +1361,7 @@ public class SQLContainer implements Container, Container.Filterable,
*
* @see com.vaadin.data.Container#removeContainerProperty(java.lang.Object)
*/
+
public boolean removeContainerProperty(Object propertyId)
throws UnsupportedOperationException {
throw new UnsupportedOperationException();
@@ -1344,6 +1372,7 @@ public class SQLContainer implements Container, Container.Filterable,
*
* @see com.vaadin.data.Container#addItem(java.lang.Object)
*/
+
public Item addItem(Object itemId) throws UnsupportedOperationException {
throw new UnsupportedOperationException();
}
@@ -1354,6 +1383,7 @@ public class SQLContainer implements Container, Container.Filterable,
* @see com.vaadin.data.Container.Ordered#addItemAfter(java.lang.Object,
* java.lang.Object)
*/
+
public Item addItemAfter(Object previousItemId, Object newItemId)
throws UnsupportedOperationException {
throw new UnsupportedOperationException();
@@ -1364,6 +1394,7 @@ public class SQLContainer implements Container, Container.Filterable,
*
* @see com.vaadin.data.Container.Indexed#addItemAt(int, java.lang.Object)
*/
+
public Item addItemAt(int index, Object newItemId)
throws UnsupportedOperationException {
throw new UnsupportedOperationException();
@@ -1374,6 +1405,7 @@ public class SQLContainer implements Container, Container.Filterable,
*
* @see com.vaadin.data.Container.Indexed#addItemAt(int)
*/
+
public Object addItemAt(int index) throws UnsupportedOperationException {
throw new UnsupportedOperationException();
}
@@ -1383,6 +1415,7 @@ public class SQLContainer implements Container, Container.Filterable,
*
* @see com.vaadin.data.Container.Ordered#addItemAfter(java.lang.Object)
*/
+
public Object addItemAfter(Object previousItemId)
throws UnsupportedOperationException {
throw new UnsupportedOperationException();
@@ -1399,6 +1432,7 @@ public class SQLContainer implements Container, Container.Filterable,
* com.vaadin.data.Container.ItemSetChangeNotifier#addListener(com.vaadin
* .data.Container.ItemSetChangeListener)
*/
+
public void addListener(Container.ItemSetChangeListener listener) {
if (itemSetChangeListeners == null) {
itemSetChangeListeners = new LinkedList<Container.ItemSetChangeListener>();
@@ -1413,6 +1447,7 @@ public class SQLContainer implements Container, Container.Filterable,
* com.vaadin.data.Container.ItemSetChangeNotifier#removeListener(com.vaadin
* .data.Container.ItemSetChangeListener)
*/
+
public void removeListener(Container.ItemSetChangeListener listener) {
if (itemSetChangeListeners != null) {
itemSetChangeListeners.remove(listener);
@@ -1577,7 +1612,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 +1676,7 @@ public class SQLContainer implements Container, Container.Filterable,
}
}
+ private static final Logger getLogger() {
+ return Logger.getLogger(SQLContainer.class.getName());
+ }
}
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<String> 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/AcceptAll.java b/src/com/vaadin/event/dd/acceptcriteria/AcceptAll.java
index 87193e8b3e..52ffab9263 100644
--- a/src/com/vaadin/event/dd/acceptcriteria/AcceptAll.java
+++ b/src/com/vaadin/event/dd/acceptcriteria/AcceptAll.java
@@ -7,7 +7,6 @@
package com.vaadin.event.dd.acceptcriteria;
import com.vaadin.event.dd.DragAndDropEvent;
-import com.vaadin.terminal.gwt.client.ui.dd.VAcceptAll;
/**
* Criterion that accepts all drops anywhere on the component.
@@ -18,7 +17,6 @@ import com.vaadin.terminal.gwt.client.ui.dd.VAcceptAll;
* @since 6.3
*
*/
-@ClientCriterion(VAcceptAll.class)
public final class AcceptAll extends ClientSideCriterion {
private static final long serialVersionUID = 7406683402153141461L;
diff --git a/src/com/vaadin/event/dd/acceptcriteria/And.java b/src/com/vaadin/event/dd/acceptcriteria/And.java
index 89c8cb377b..a0340a9cdb 100644
--- a/src/com/vaadin/event/dd/acceptcriteria/And.java
+++ b/src/com/vaadin/event/dd/acceptcriteria/And.java
@@ -19,7 +19,6 @@ import com.vaadin.terminal.PaintTarget;
* @since 6.3
*
*/
-@ClientCriterion(com.vaadin.terminal.gwt.client.ui.dd.VAnd.class)
public class And extends ClientSideCriterion {
private static final long serialVersionUID = -5242574480825471748L;
diff --git a/src/com/vaadin/event/dd/acceptcriteria/ClientCriterion.java b/src/com/vaadin/event/dd/acceptcriteria/ClientCriterion.java
deleted file mode 100644
index 8b64106be7..0000000000
--- a/src/com/vaadin/event/dd/acceptcriteria/ClientCriterion.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-package com.vaadin.event.dd.acceptcriteria;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-import com.vaadin.terminal.gwt.client.ui.dd.VAcceptCriterion;
-
-/**
- * An annotation type used to point the client side counterpart for server side
- * a {@link AcceptCriterion} class.
- * <p>
- * Annotations are used at GWT compilation phase, so remember to rebuild your
- * widgetset if you do changes for {@link ClientCriterion} mappings.
- *
- * @since 6.3
- */
-@Retention(RetentionPolicy.RUNTIME)
-@Target(ElementType.TYPE)
-public @interface ClientCriterion {
- /**
- * @return the client side counterpart for the annotated criterion
- */
- Class<? extends VAcceptCriterion> value();
-}
diff --git a/src/com/vaadin/event/dd/acceptcriteria/ContainsDataFlavor.java b/src/com/vaadin/event/dd/acceptcriteria/ContainsDataFlavor.java
index 298a50a1d5..7eb04d9647 100644
--- a/src/com/vaadin/event/dd/acceptcriteria/ContainsDataFlavor.java
+++ b/src/com/vaadin/event/dd/acceptcriteria/ContainsDataFlavor.java
@@ -10,7 +10,6 @@ import com.vaadin.event.Transferable;
import com.vaadin.event.dd.DragAndDropEvent;
import com.vaadin.terminal.PaintException;
import com.vaadin.terminal.PaintTarget;
-import com.vaadin.terminal.gwt.client.ui.dd.VContainsDataFlavor;
/**
* A Criterion that checks whether {@link Transferable} contains given data
@@ -19,7 +18,6 @@ import com.vaadin.terminal.gwt.client.ui.dd.VContainsDataFlavor;
*
* @since 6.3
*/
-@ClientCriterion(VContainsDataFlavor.class)
public class ContainsDataFlavor extends ClientSideCriterion {
private String dataFlavorId;
diff --git a/src/com/vaadin/event/dd/acceptcriteria/Not.java b/src/com/vaadin/event/dd/acceptcriteria/Not.java
index 774dcc642e..85ff7e9bc9 100644
--- a/src/com/vaadin/event/dd/acceptcriteria/Not.java
+++ b/src/com/vaadin/event/dd/acceptcriteria/Not.java
@@ -9,7 +9,6 @@ package com.vaadin.event.dd.acceptcriteria;
import com.vaadin.event.dd.DragAndDropEvent;
import com.vaadin.terminal.PaintException;
import com.vaadin.terminal.PaintTarget;
-import com.vaadin.terminal.gwt.client.ui.dd.VNot;
/**
* Criterion that wraps another criterion and inverts its return value.
@@ -17,7 +16,6 @@ import com.vaadin.terminal.gwt.client.ui.dd.VNot;
* @since 6.3
*
*/
-@ClientCriterion(VNot.class)
public class Not extends ClientSideCriterion {
private static final long serialVersionUID = 1131422338558613244L;
diff --git a/src/com/vaadin/event/dd/acceptcriteria/Or.java b/src/com/vaadin/event/dd/acceptcriteria/Or.java
index 2e7cdf45a3..077e9114d8 100644
--- a/src/com/vaadin/event/dd/acceptcriteria/Or.java
+++ b/src/com/vaadin/event/dd/acceptcriteria/Or.java
@@ -9,7 +9,6 @@ package com.vaadin.event.dd.acceptcriteria;
import com.vaadin.event.dd.DragAndDropEvent;
import com.vaadin.terminal.PaintException;
import com.vaadin.terminal.PaintTarget;
-import com.vaadin.terminal.gwt.client.ui.dd.VOr;
/**
* A compound criterion that accepts the drag if any of its criterion accepts
@@ -20,7 +19,6 @@ import com.vaadin.terminal.gwt.client.ui.dd.VOr;
* @since 6.3
*
*/
-@ClientCriterion(VOr.class)
public class Or extends ClientSideCriterion {
private static final long serialVersionUID = 1L;
private AcceptCriterion criteria[];
diff --git a/src/com/vaadin/event/dd/acceptcriteria/ServerSideCriterion.java b/src/com/vaadin/event/dd/acceptcriteria/ServerSideCriterion.java
index b3f4702c51..77840bc94f 100644
--- a/src/com/vaadin/event/dd/acceptcriteria/ServerSideCriterion.java
+++ b/src/com/vaadin/event/dd/acceptcriteria/ServerSideCriterion.java
@@ -8,7 +8,6 @@ import java.io.Serializable;
import com.vaadin.event.Transferable;
import com.vaadin.terminal.PaintException;
import com.vaadin.terminal.PaintTarget;
-import com.vaadin.terminal.gwt.client.ui.dd.VServerAccept;
/**
* Parent class for criteria which are verified on the server side during a drag
@@ -27,7 +26,6 @@ import com.vaadin.terminal.gwt.client.ui.dd.VServerAccept;
*
* @since 6.3
*/
-@ClientCriterion(VServerAccept.class)
public abstract class ServerSideCriterion implements Serializable,
AcceptCriterion {
diff --git a/src/com/vaadin/event/dd/acceptcriteria/SourceIs.java b/src/com/vaadin/event/dd/acceptcriteria/SourceIs.java
index 0d29e9a327..d7c47dc915 100644
--- a/src/com/vaadin/event/dd/acceptcriteria/SourceIs.java
+++ b/src/com/vaadin/event/dd/acceptcriteria/SourceIs.java
@@ -13,7 +13,6 @@ import com.vaadin.event.TransferableImpl;
import com.vaadin.event.dd.DragAndDropEvent;
import com.vaadin.terminal.PaintException;
import com.vaadin.terminal.PaintTarget;
-import com.vaadin.terminal.gwt.client.ui.dd.VDragSourceIs;
import com.vaadin.ui.Component;
/**
@@ -23,10 +22,7 @@ import com.vaadin.ui.Component;
* @since 6.3
*/
@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 +39,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/event/dd/acceptcriteria/SourceIsTarget.java b/src/com/vaadin/event/dd/acceptcriteria/SourceIsTarget.java
index 8303809140..454159b3da 100644
--- a/src/com/vaadin/event/dd/acceptcriteria/SourceIsTarget.java
+++ b/src/com/vaadin/event/dd/acceptcriteria/SourceIsTarget.java
@@ -10,7 +10,6 @@ import com.vaadin.event.Transferable;
import com.vaadin.event.TransferableImpl;
import com.vaadin.event.dd.DragAndDropEvent;
import com.vaadin.event.dd.DropTarget;
-import com.vaadin.terminal.gwt.client.ui.dd.VSourceIsTarget;
import com.vaadin.ui.Component;
import com.vaadin.ui.Table;
import com.vaadin.ui.Tree;
@@ -26,7 +25,6 @@ import com.vaadin.ui.Tree;
* @since 6.3
*
*/
-@ClientCriterion(VSourceIsTarget.class)
public class SourceIsTarget extends ClientSideCriterion {
private static final long serialVersionUID = -451399314705532584L;
diff --git a/src/com/vaadin/event/dd/acceptcriteria/TargetDetailIs.java b/src/com/vaadin/event/dd/acceptcriteria/TargetDetailIs.java
index 25371938d2..641fddc3ea 100644
--- a/src/com/vaadin/event/dd/acceptcriteria/TargetDetailIs.java
+++ b/src/com/vaadin/event/dd/acceptcriteria/TargetDetailIs.java
@@ -10,7 +10,6 @@ import com.vaadin.event.dd.DragAndDropEvent;
import com.vaadin.event.dd.TargetDetails;
import com.vaadin.terminal.PaintException;
import com.vaadin.terminal.PaintTarget;
-import com.vaadin.terminal.gwt.client.ui.dd.VTargetDetailIs;
/**
* Criterion for checking if drop target details contains the specific property
@@ -21,7 +20,6 @@ import com.vaadin.terminal.gwt.client.ui.dd.VTargetDetailIs;
* TODO add support for other basic data types that we support in UIDL.
*
*/
-@ClientCriterion(VTargetDetailIs.class)
public class TargetDetailIs extends ClientSideCriterion {
private static final long serialVersionUID = 763165450054331246L;
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..3ff727b504
--- /dev/null
+++ b/src/com/vaadin/navigator/Navigator.java
@@ -0,0 +1,586 @@
+package com.vaadin.navigator;
+
+/*
+ @VaadinApache2LicenseForJavaFiles@
+ */
+
+import java.io.Serializable;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+
+import com.vaadin.navigator.ViewChangeListener.ViewChangeEvent;
+import com.vaadin.terminal.Page;
+import com.vaadin.terminal.Page.FragmentChangedEvent;
+import com.vaadin.terminal.Page.FragmentChangedListener;
+import com.vaadin.ui.Component;
+import com.vaadin.ui.CssLayout;
+import com.vaadin.ui.CustomComponent;
+
+/**
+ * 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).
+ *
+ * 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 with TouchKit navigation support
+
+ /**
+ * Empty view component.
+ */
+ public static class EmptyView extends CssLayout implements View {
+ /**
+ * Create minimally sized empty view.
+ */
+ public EmptyView() {
+ setWidth("0px");
+ setHeight("0px");
+ }
+
+ public void navigateTo(String fragmentParameters) {
+ // nothing to do
+ }
+ }
+
+ /**
+ * Fragment manager using URI fragments of a Page 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 Page page;
+ private final Navigator navigator;
+
+ /**
+ * Create a new URIFragmentManager and attach it to listen to URI
+ * fragment changes of a {@link Page}.
+ *
+ * @param page
+ * page whose URI fragment to get and modify
+ * @param navigator
+ * {@link Navigator} to notify of fragment changes (using
+ * {@link Navigator#navigateTo(String)}
+ */
+ public UriFragmentManager(Page page, Navigator navigator) {
+ this.page = page;
+ this.navigator = navigator;
+
+ page.addListener(this);
+ }
+
+ public String getFragment() {
+ return page.getFragment();
+ }
+
+ public void setFragment(String fragment) {
+ page.setFragment(fragment, false);
+ }
+
+ 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 supports mapping a single view name to a single
+ * pre-initialized view instance.
+ *
+ * For most cases, ClassBasedViewProvider should be used instead of this.
+ */
+ public static class StaticViewProvider implements ViewProvider {
+ private final String viewName;
+ private final View view;
+
+ /**
+ * Create a new view provider which returns a pre-created view instance.
+ *
+ * @param viewName
+ * name of the view (not null)
+ * @param view
+ * view instance to return (not null), reused on every
+ * request
+ */
+ public StaticViewProvider(String viewName, View view) {
+ this.viewName = viewName;
+ this.view = view;
+ }
+
+ public String getViewName(String viewAndParameters) {
+ if (null == viewAndParameters) {
+ return null;
+ }
+ if (viewAndParameters.startsWith(viewName)) {
+ return viewName;
+ }
+ return null;
+ }
+
+ public View getView(String viewName) {
+ if (this.viewName.equals(viewName)) {
+ return view;
+ }
+ return null;
+ }
+
+ /**
+ * Get the view name for this provider.
+ *
+ * @return view name for this provider
+ */
+ public String getViewName() {
+ return viewName;
+ }
+ }
+
+ /**
+ * View provider which maps a single view name to a class to instantiate for
+ * the view.
+ *
+ * Note that the view class must be accessible by the class loader used by
+ * the provider. This may require its visibility to be public.
+ *
+ * This class is primarily for internal use by {@link Navigator}.
+ */
+ public static class ClassBasedViewProvider implements ViewProvider {
+
+ private final String viewName;
+ private final Class<? extends View> viewClass;
+
+ /**
+ * Create a new view provider which creates new view instances based on
+ * a view class.
+ *
+ * @param viewName
+ * name of the views to create (not null)
+ * @param viewClass
+ * class to instantiate when a view is requested (not null)
+ */
+ public ClassBasedViewProvider(String viewName,
+ Class<? extends View> viewClass) {
+ if (null == viewName || null == viewClass) {
+ throw new IllegalArgumentException(
+ "View name and class should not be null");
+ }
+ this.viewName = viewName;
+ this.viewClass = viewClass;
+ }
+
+ public String getViewName(String viewAndParameters) {
+ if (null == viewAndParameters) {
+ return null;
+ }
+ if (viewAndParameters.equals(viewName)
+ || viewAndParameters.startsWith(viewName + "/")) {
+ return viewName;
+ }
+ return null;
+ }
+
+ public View getView(String viewName) {
+ if (this.viewName.equals(viewName)) {
+ try {
+ View view = viewClass.newInstance();
+ return view;
+ } catch (InstantiationException e) {
+ // TODO error handling
+ throw new RuntimeException(e);
+ } catch (IllegalAccessException e) {
+ // TODO error handling
+ throw new RuntimeException(e);
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Get the view name for this provider.
+ *
+ * @return view name for this provider
+ */
+ public String getViewName() {
+ return viewName;
+ }
+
+ /**
+ * Get the view class for this provider.
+ *
+ * @return {@link View} class
+ */
+ public Class<? extends View> getViewClass() {
+ return viewClass;
+ }
+ }
+
+ private final FragmentManager fragmentManager;
+ private final ViewDisplay display;
+ private View currentView = null;
+ private List<ViewChangeListener> listeners = new LinkedList<ViewChangeListener>();
+ private List<ViewProvider> providers = new LinkedList<ViewProvider>();
+
+ /**
+ * Create a navigator that is tracking the active view using URI fragments.
+ *
+ * @param page
+ * whose URI fragments are used
+ * @param display
+ * where to display the views
+ */
+ public Navigator(Page page, ViewDisplay display) {
+ this.display = display;
+ fragmentManager = new UriFragmentManager(page, this);
+ navigateTo(page.getFragment());
+ }
+
+ /**
+ * Create a navigator that is tracking the active view using URI fragments.
+ * By default, a {@link SimpleViewDisplay} is used and can be obtained using
+ * {@link #getDisplay()}.
+ *
+ * @param page
+ * whose URI fragments are used
+ */
+ public Navigator(Page page) {
+ display = new SimpleViewDisplay();
+ fragmentManager = new UriFragmentManager(page, this);
+ navigateTo(page.getFragment());
+ }
+
+ /**
+ * Create a navigator.
+ *
+ * When a custom fragment manager is not needed, use the constructor
+ * {@link #Navigator(Page, ViewDisplay)} which uses a URI fragment based
+ * fragment manager.
+ *
+ * Note that navigation to the initial view must be performed explicitly by
+ * the application after creating a Navigator using this constructor.
+ *
+ * @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 multiple providers return a matching view, the view with the longest
+ * name is selected. This way, e.g. hierarchies of subviews can be
+ * registered like "admin/", "admin/users", "admin/settings" and the longest
+ * match is used.
+ *
+ * If the view being deactivated indicates it wants a confirmation for the
+ * navigation operation, the user is asked for the confirmation.
+ *
+ * Registered {@link ViewChangeListener}s are called upon successful view
+ * change.
+ *
+ * @param viewAndParameters
+ * view name and parameters
+ */
+ public void navigateTo(String viewAndParameters) {
+ String longestViewName = null;
+ View viewWithLongestName = null;
+ for (ViewProvider provider : providers) {
+ String viewName = provider.getViewName(viewAndParameters);
+ if (null != viewName
+ && (longestViewName == null || viewName.length() > longestViewName
+ .length())) {
+ View view = provider.getView(viewName);
+ if (null != view) {
+ longestViewName = viewName;
+ viewWithLongestName = view;
+ }
+ }
+ }
+ if (viewWithLongestName != null) {
+ String parameters = null;
+ if (viewAndParameters.length() > longestViewName.length() + 1) {
+ parameters = viewAndParameters.substring(longestViewName
+ .length() + 1);
+ }
+ navigateTo(viewWithLongestName, longestViewName, parameters);
+ }
+ // TODO if no view is found, what to do?
+ }
+
+ /**
+ * 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
+ */
+ protected void navigateTo(View view, String viewName,
+ String fragmentParameters) {
+ ViewChangeEvent event = new ViewChangeEvent(this, currentView, view,
+ viewName, fragmentParameters);
+ if (!isViewChangeAllowed(event)) {
+ 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);
+ currentView = view;
+
+ if (display != null) {
+ display.showView(view);
+ }
+
+ fireViewChange(event);
+ }
+
+ /**
+ * 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 event
+ * view change event (not null, view change not yet performed)
+ * @return true if the view change should be allowed, false to silently
+ * block the navigation operation
+ */
+ protected boolean isViewChangeAllowed(ViewChangeEvent event) {
+ for (ViewChangeListener l : listeners) {
+ if (!l.isViewChangeAllowed(event)) {
+ 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;
+ }
+
+ /**
+ * Returns the ViewDisplay used by the navigator. Unless another display is
+ * specified, a {@link SimpleViewDisplay} (which is a {@link Component}) is
+ * used by default.
+ *
+ * @return current ViewDisplay
+ */
+ public ViewDisplay getDisplay() {
+ return display;
+ }
+
+ /**
+ * Fire an event when the current view has changed.
+ *
+ * @param event
+ * view change event (not null)
+ */
+ protected void fireViewChange(ViewChangeEvent event) {
+ for (ViewChangeListener l : listeners) {
+ l.navigatorViewChanged(event);
+ }
+ }
+
+ /**
+ * Register a static, pre-initialized view instance for a view name.
+ *
+ * Registering another view with a name that is already registered
+ * overwrites the old registration of the same type.
+ *
+ * @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) {
+ throw new IllegalArgumentException(
+ "view and viewName must be non-null");
+ }
+
+ removeView(viewName);
+ registerProvider(new StaticViewProvider(viewName, view));
+ }
+
+ /**
+ * Register for a view name a view class.
+ *
+ * Registering another view with a name that is already registered
+ * overwrites the old registration of the same type.
+ *
+ * A new view instance is created every time a view is requested.
+ *
+ * @param viewName
+ * String that identifies a view (not null nor empty string)
+ * @param viewClass
+ * {@link View} class to instantiate when a view is requested
+ * (not null)
+ */
+ public void addView(String viewName, Class<? extends View> viewClass) {
+
+ // Check parameters
+ if (viewName == null || viewClass == null) {
+ throw new IllegalArgumentException(
+ "view and viewClass must be non-null");
+ }
+
+ removeView(viewName);
+ registerProvider(new ClassBasedViewProvider(viewName, viewClass));
+ }
+
+ /**
+ * Remove view from navigator.
+ *
+ * This method only applies to views registered using
+ * {@link #addView(String, View)} or {@link #addView(String, Class)}.
+ *
+ * @param viewName
+ * name of the view to remove
+ */
+ public void removeView(String viewName) {
+ Iterator<ViewProvider> it = providers.iterator();
+ while (it.hasNext()) {
+ ViewProvider provider = it.next();
+ if (provider instanceof StaticViewProvider) {
+ StaticViewProvider staticProvider = (StaticViewProvider) provider;
+ if (staticProvider.getViewName().equals(viewName)) {
+ it.remove();
+ }
+ } else if (provider instanceof ClassBasedViewProvider) {
+ ClassBasedViewProvider classBasedProvider = (ClassBasedViewProvider) provider;
+ if (classBasedProvider.getViewName().equals(viewName)) {
+ it.remove();
+ }
+ }
+ }
+ }
+
+ /**
+ * 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..4d135b4c0b
--- /dev/null
+++ b/src/com/vaadin/navigator/View.java
@@ -0,0 +1,36 @@
+/*
+@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 {
+
+ /**
+ * 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/"
+ */
+ public void navigateTo(String fragmentParameters);
+} \ 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..2eb34e6fcf
--- /dev/null
+++ b/src/com/vaadin/navigator/ViewChangeListener.java
@@ -0,0 +1,118 @@
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+
+package com.vaadin.navigator;
+
+import java.io.Serializable;
+import java.util.EventObject;
+
+/**
+ * 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 {
+
+ /**
+ * Event received by the listener for attempted and executed view changes.
+ */
+ public static class ViewChangeEvent extends EventObject {
+ private final View oldView;
+ private final View newView;
+ private final String viewName;
+ private final String fragmentParameters;
+
+ /**
+ * Create a new view change event.
+ *
+ * @param navigator
+ * Navigator that triggered the event, not null
+ */
+ public ViewChangeEvent(Navigator navigator, View oldView, View newView,
+ String viewName, String fragmentParameters) {
+ super(navigator);
+ this.oldView = oldView;
+ this.newView = newView;
+ this.viewName = viewName;
+ this.fragmentParameters = fragmentParameters;
+ }
+
+ /**
+ * Returns the navigator that triggered this event.
+ *
+ * @return Navigator (not null)
+ */
+ public Navigator getNavigator() {
+ return (Navigator) getSource();
+ }
+
+ /**
+ * Returns the view being deactivated.
+ *
+ * @return old View
+ */
+ public View getOldView() {
+ return oldView;
+ }
+
+ /**
+ * Returns the view being activated.
+ *
+ * @return new View
+ */
+ public View getNewView() {
+ return newView;
+ }
+
+ /**
+ * Returns the view name of the view being activated.
+ *
+ * @return view name of the new View
+ */
+ public String getViewName() {
+ return viewName;
+ }
+
+ /**
+ * Returns the parameters for the view being activated.
+ *
+ * @return fragment parameters (potentially bookmarkable) for the new
+ * view
+ */
+ public String getFragmentParameters() {
+ return fragmentParameters;
+ }
+ }
+
+ /**
+ * 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.
+ *
+ * @param event
+ * view change event
+ * @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(ViewChangeEvent event);
+
+ /**
+ * Invoked after the view has changed. Be careful for deadlocks if you
+ * decide to change the view again in the listener.
+ *
+ * @param event
+ * view change event
+ */
+ public void navigatorViewChanged(ViewChangeEvent event);
+
+} \ 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/src/com/vaadin/terminal/AbstractClientConnector.java b/src/com/vaadin/terminal/AbstractClientConnector.java
new file mode 100644
index 0000000000..9de444d70e
--- /dev/null
+++ b/src/com/vaadin/terminal/AbstractClientConnector.java
@@ -0,0 +1,490 @@
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+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;
+
+/**
+ * An abstract base class for ClientConnector implementations. This class
+ * provides all the basic functionality required for connectors.
+ *
+ * @author Vaadin Ltd
+ * @version @VERSION@
+ * @since 7.0.0
+ */
+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<Class<?>, RpcManager> rpcManagerMap = new HashMap<Class<?>, RpcManager>();
+
+ /**
+ * A map from server to client RPC interface class to the RPC proxy that
+ * sends ourgoing RPC calls for that interface.
+ */
+ private Map<Class<?>, ClientRpc> rpcProxyMap = new HashMap<Class<?>, 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<ClientMethodInvocation> pendingInvocations = new ArrayList<ClientMethodInvocation>();
+
+ private String connectorId;
+
+ private ArrayList<Extension> extensions = new ArrayList<Extension>();
+
+ private ClientConnector parent;
+
+ /* Documentation copied from interface */
+ public void requestRepaint() {
+ Root root = getRoot();
+ if (root != null) {
+ root.getConnectorTracker().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 <T> void registerRpc(T implementation, Class<T> rpcInterfaceType) {
+ rpcManagerMap.put(rpcInterfaceType, new ServerRpcManager<T>(
+ 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 <T extends ServerRpc> 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<T> rpcInterfaceType) if the Rpc implementation implements more than one interface");
+ }
+ @SuppressWarnings("unchecked")
+ Class<T> type = (Class<T>) 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.
+ * <p>
+ * 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.
+ * </p>
+ * <p>
+ * 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<? extends SharedState> 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 extends ClientRpc> T getRpcProxy(final Class<T> 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 static final class AllChildrenIterable implements
+ Iterable<ClientConnector>, Serializable {
+ private final ClientConnector connector;
+
+ private AllChildrenIterable(ClientConnector connector) {
+ this.connector = connector;
+ }
+
+ public Iterator<ClientConnector> iterator() {
+ CombinedIterator<ClientConnector> iterator = new CombinedIterator<ClientConnector>();
+ iterator.addIterator(connector.getExtensions().iterator());
+
+ if (connector instanceof HasComponents) {
+ HasComponents hasComponents = (HasComponents) connector;
+ iterator.addIterator(hasComponents.iterator());
+ }
+
+ return iterator;
+ }
+ }
+
+ 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<ClientMethodInvocation> retrievePendingRpcCalls() {
+ if (pendingInvocations.isEmpty()) {
+ return Collections.emptyList();
+ } else {
+ List<ClientMethodInvocation> result = pendingInvocations;
+ pendingInvocations = new ArrayList<ClientMethodInvocation>();
+ 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, <code>null</code> is returned.
+ *
+ * @return The connector's application, or <code>null</code> 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. <code>null</code> 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 <code>null</code> 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 : getAllChildrenIterable(this)) {
+ connector.requestRepaintAll();
+ }
+ }
+
+ private static final class CombinedIterator<T> implements Iterator<T>,
+ Serializable {
+
+ private final Collection<Iterator<? extends T>> iterators = new ArrayList<Iterator<? extends T>>();
+
+ public void addIterator(Iterator<? extends T> iterator) {
+ iterators.add(iterator);
+ }
+
+ public boolean hasNext() {
+ for (Iterator<? extends T> i : iterators) {
+ if (i.hasNext()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public T next() {
+ for (Iterator<? extends T> i : iterators) {
+ if (i.hasNext()) {
+ return i.next();
+ }
+ }
+ throw new NoSuchElementException();
+ }
+
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+ /**
+ * Get an Iterable for iterating over all child connectors, including both
+ * extensions and child components.
+ *
+ * @param connector
+ * the connector to get children for
+ * @return an Iterable giving all child connectors.
+ */
+ public static Iterable<ClientConnector> getAllChildrenIterable(
+ final ClientConnector connector) {
+ return new AllChildrenIterable(connector);
+ }
+
+ public Collection<Extension> getExtensions() {
+ return Collections.unmodifiableCollection(extensions);
+ }
+
+ /**
+ * Add an extension to this connector. This method is protected to allow
+ * extensions to select which targets they can extend.
+ *
+ * @param extension
+ * the extension to add
+ */
+ protected void addExtension(Extension extension) {
+ ClientConnector previousParent = extension.getParent();
+ if (previousParent == this) {
+ // Nothing to do, already attached
+ return;
+ } else if (previousParent != null) {
+ throw new IllegalStateException(
+ "Moving an extension from one parent to another is not supported");
+ }
+
+ extensions.add(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();
+
+ getRoot().getConnectorTracker().registerConnector(this);
+
+ for (ClientConnector connector : getAllChildrenIterable(this)) {
+ connector.attach();
+ }
+
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * <p>
+ * The {@link #getApplication()} and {@link #getRoot()} methods might return
+ * <code>null</code> after this method is called.
+ * </p>
+ */
+ public void detach() {
+ for (ClientConnector connector : getAllChildrenIterable(this)) {
+ connector.detach();
+ }
+
+ getRoot().getConnectorTracker().unregisterConnector(this);
+ }
+
+ 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/AbstractErrorMessage.java b/src/com/vaadin/terminal/AbstractErrorMessage.java
index 1a625fc0e6..3f526f7339 100644
--- a/src/com/vaadin/terminal/AbstractErrorMessage.java
+++ b/src/com/vaadin/terminal/AbstractErrorMessage.java
@@ -4,6 +4,8 @@
package com.vaadin.terminal;
+import java.io.PrintWriter;
+import java.io.StringWriter;
import java.util.ArrayList;
import java.util.List;
@@ -156,7 +158,10 @@ public abstract class AbstractErrorMessage implements ErrorMessage {
}
return error;
} else {
- return new SystemError(t);
+ StringWriter sw = new StringWriter();
+ PrintWriter pw = new PrintWriter(sw);
+ t.printStackTrace(pw);
+ return new SystemError(sw.toString());
}
}
diff --git a/src/com/vaadin/terminal/AbstractExtension.java b/src/com/vaadin/terminal/AbstractExtension.java
new file mode 100644
index 0000000000..33a60e39ef
--- /dev/null
+++ b/src/com/vaadin/terminal/AbstractExtension.java
@@ -0,0 +1,76 @@
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+
+package com.vaadin.terminal;
+
+import com.vaadin.terminal.gwt.server.ClientConnector;
+
+/**
+ * An extension is an entity that is attached to a Component or another
+ * Extension and independently communicates between client and server.
+ * <p>
+ * Extensions can use shared state and RPC in the same way as components.
+ * <p>
+ * AbstractExtension adds a mechanism for adding the extension to any Connector
+ * (extend). To let the Extension determine what kind target it can be added to,
+ * the extend method is declared as protected.
+ *
+ * @author Vaadin Ltd
+ * @version @VERSION@
+ * @since 7.0.0
+ */
+public abstract class AbstractExtension extends AbstractClientConnector
+ implements Extension {
+ private boolean previouslyAttached = false;
+
+ /**
+ * Gets a type that the parent must be an instance of. Override this if the
+ * extension only support certain targets, e.g. if only TextFields can be
+ * extended.
+ *
+ * @return a type that the parent must be an instance of
+ */
+ protected Class<? extends ClientConnector> getSupportedParentType() {
+ return ClientConnector.class;
+ }
+
+ /**
+ * Add this extension to the target connector. This method is protected to
+ * allow subclasses to require a more specific type of target.
+ *
+ * @param target
+ * the connector to attach this extension to
+ */
+ protected void extend(AbstractClientConnector target) {
+ target.addExtension(this);
+ }
+
+ /**
+ * Remove this extension from its target. After an extension has been
+ * removed, it can not be attached again.
+ */
+ public void removeFromTarget() {
+ getParent().removeExtension(this);
+ }
+
+ @Override
+ public void setParent(ClientConnector parent) {
+ if (previouslyAttached && parent != null) {
+ throw new IllegalStateException(
+ "An extension can not be set to extend a new target after getting detached from the previous.");
+ }
+
+ Class<? extends ClientConnector> supportedParentType = getSupportedParentType();
+ if (parent == null || supportedParentType.isInstance(parent)) {
+ super.setParent(parent);
+ previouslyAttached = true;
+ } else {
+ throw new IllegalArgumentException(getClass().getName()
+ + " can only be attached to targets of type "
+ + supportedParentType.getName() + " but attach to "
+ + parent.getClass().getName() + " was attempted.");
+ }
+ }
+
+}
diff --git a/src/com/vaadin/terminal/AbstractJavaScriptExtension.java b/src/com/vaadin/terminal/AbstractJavaScriptExtension.java
new file mode 100644
index 0000000000..bdcd948c74
--- /dev/null
+++ b/src/com/vaadin/terminal/AbstractJavaScriptExtension.java
@@ -0,0 +1,158 @@
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+
+package com.vaadin.terminal;
+
+import com.vaadin.terminal.gwt.client.JavaScriptExtensionState;
+import com.vaadin.ui.JavaScriptCallback;
+
+/**
+ * Base class for Extensions with all client-side logic implemented using
+ * JavaScript.
+ * <p>
+ * When a new JavaScript extension is initialized in the browser, the framework
+ * will look for a globally defined JavaScript function that will initialize the
+ * extension. The name of the initialization function is formed by replacing .
+ * with _ in the name of the server-side class. If no such function is defined,
+ * each super class is used in turn until a match is found. The framework will
+ * thus first attempt with <code>com_example_MyExtension</code> for the
+ * server-side
+ * <code>com.example.MyExtension extends AbstractJavaScriptExtension</code>
+ * class. If MyExtension instead extends <code>com.example.SuperExtension</code>
+ * , then <code>com_example_SuperExtension</code> will also be attempted if
+ * <code>com_example_MyExtension</code> has not been defined.
+ * <p>
+ *
+ * The initialization function will be called with <code>this</code> pointing to
+ * a connector wrapper object providing integration to Vaadin with the following
+ * functions:
+ * <ul>
+ * <li><code>getConnectorId()</code> - returns a string with the id of the
+ * connector.</li>
+ * <li><code>getParentId([connectorId])</code> - returns a string with the id of
+ * the connector's parent. If <code>connectorId</code> is provided, the id of
+ * the parent of the corresponding connector with the passed id is returned
+ * instead.</li>
+ * <li><code>getWidgetElement([connectorId])</code> - returns the DOM Element
+ * that is the root of a connector's widget. <code>null</code> is returned if
+ * the connector can not be found or if the connector doesn't have a widget. If
+ * <code>connectorId</code> is not provided, the connector id of the current
+ * connector will be used.</li>
+ * <li><code>getState()</code> - returns an object corresponding to the shared
+ * state defined on the server. The scheme for conversion between Java and
+ * JavaScript types is described bellow.</li>
+ * <li><code>registerRpc([name, ] rpcObject)</code> - registers the
+ * <code>rpcObject</code> as a RPC handler. <code>rpcObject</code> should be an
+ * object with field containing functions for all eligible RPC functions. If
+ * <code>name</code> is provided, the RPC handler will only used for RPC calls
+ * for the RPC interface with the same fully qualified Java name. If no
+ * <code>name</code> is provided, the RPC handler will be used for all incoming
+ * RPC invocations where the RPC method name is defined as a function field in
+ * the handler. The scheme for conversion between Java types in the RPC
+ * interface definition and the JavaScript values passed as arguments to the
+ * handler functions is described bellow.</li>
+ * <li><code>getRpcProxy([name])</code> - returns an RPC proxy object. If
+ * <code>name</code> is provided, the proxy object will contain functions for
+ * all methods in the RPC interface with the same fully qualified name, provided
+ * a RPC handler has been registered by the server-side code. If no
+ * <code>name</code> is provided, the returned RPC proxy object will contain
+ * functions for all methods in all RPC interfaces registered for the connector
+ * on the server. If the same method name is present in multiple registered RPC
+ * interfaces, the corresponding function in the RPC proxy object will throw an
+ * exception when called. The scheme for conversion between Java types in the
+ * RPC interface and the JavaScript values that should be passed to the
+ * functions is described bellow.</li>
+ * </ul>
+ * The connector wrapper also supports these special functions:
+ * <ul>
+ * <li><code>onStateChange</code> - If the JavaScript code assigns a function to
+ * the field, that function is called whenever the contents of the shared state
+ * is changed.</li>
+ * <li>Any field name corresponding to a call to
+ * {@link #registerCallback(String, JavaScriptCallback)} on the server will
+ * automatically be present as a function that triggers the registered callback
+ * on the server.</li>
+ * <li>Any field name referred to using
+ * {@link #invokeCallback(String, Object...)} on the server will be called if a
+ * function has been assigned to the field.</li>
+ * </ul>
+ * <p>
+ *
+ * Values in the Shared State and in RPC calls are converted between Java and
+ * JavaScript using the following conventions:
+ * <ul>
+ * <li>Primitive Java numbers (byte, char, int, long, float, double) and their
+ * boxed types (Byte, Character, Integer, Long, Float, Double) are represented
+ * by JavaScript numbers.</li>
+ * <li>The primitive Java boolean and the boxed Boolean are represented by
+ * JavaScript booleans.</li>
+ * <li>Java Strings are represented by JavaScript strings.</li>
+ * <li>List, Set and all arrays in Java are represented by JavaScript arrays.</li>
+ * <li>Map<String, ?> in Java is represented by JavaScript object with fields
+ * corresponding to the map keys.</li>
+ * <li>Any other Java Map is represented by a JavaScript array containing two
+ * arrays, the first contains the keys and the second contains the values in the
+ * same order.</li>
+ * <li>A Java Bean is represented by a JavaScript object with fields
+ * corresponding to the bean's properties.</li>
+ * <li>A Java Connector is represented by a JavaScript string containing the
+ * connector's id.</li>
+ * <li>A pluggable serialization mechanism is provided for types not described
+ * here. Please refer to the documentation for specific types for serialization
+ * information.</li>
+ * </ul>
+ *
+ * @author Vaadin Ltd
+ * @version @VERSION@
+ * @since 7.0.0
+ */
+public abstract class AbstractJavaScriptExtension extends AbstractExtension {
+ private JavaScriptCallbackHelper callbackHelper = new JavaScriptCallbackHelper(
+ this);
+
+ @Override
+ protected <T> void registerRpc(T implementation, Class<T> rpcInterfaceType) {
+ super.registerRpc(implementation, rpcInterfaceType);
+ callbackHelper.registerRpc(rpcInterfaceType);
+ }
+
+ /**
+ * Register a {@link JavaScriptCallback} that can be called from the
+ * JavaScript using the provided name. A JavaScript function with the
+ * provided name will be added to the connector wrapper object (initially
+ * available as <code>this</code>). Calling that JavaScript function will
+ * cause the call method in the registered {@link JavaScriptCallback} to be
+ * invoked with the same arguments.
+ *
+ * @param functionName
+ * the name that should be used for client-side callback
+ * @param javaScriptCallback
+ * the callback object that will be invoked when the JavaScript
+ * function is called
+ */
+ protected void registerCallback(String functionName,
+ JavaScriptCallback javaScriptCallback) {
+ callbackHelper.registerCallback(functionName, javaScriptCallback);
+ }
+
+ /**
+ * Invoke a named function that the connector JavaScript has added to the
+ * JavaScript connector wrapper object. The arguments should only contain
+ * data types that can be represented in JavaScript, including primitive
+ * boxing types, arrays, String, List, Set, Map, Connector and JavaBeans.
+ *
+ * @param name
+ * the name of the function
+ * @param arguments
+ * function arguments
+ */
+ protected void invokeCallback(String name, Object... arguments) {
+ callbackHelper.invokeCallback(name, arguments);
+ }
+
+ @Override
+ public JavaScriptExtensionState getState() {
+ return (JavaScriptExtensionState) super.getState();
+ }
+}
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);
}
/**
diff --git a/src/com/vaadin/terminal/CombinedRequest.java b/src/com/vaadin/terminal/CombinedRequest.java
index ccef6d8963..abf5e0412a 100644
--- a/src/com/vaadin/terminal/CombinedRequest.java
+++ b/src/com/vaadin/terminal/CombinedRequest.java
@@ -129,7 +129,7 @@ public class CombinedRequest implements WrappedRequest {
public WebBrowser getWebBrowser() {
WebApplicationContext context = (WebApplicationContext) Application
- .getCurrentApplication().getContext();
+ .getCurrent().getContext();
return context.getBrowser();
}
};
diff --git a/src/com/vaadin/terminal/Extension.java b/src/com/vaadin/terminal/Extension.java
new file mode 100644
index 0000000000..ef5bb4cf8d
--- /dev/null
+++ b/src/com/vaadin/terminal/Extension.java
@@ -0,0 +1,27 @@
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+
+package com.vaadin.terminal;
+
+import com.vaadin.terminal.gwt.server.ClientConnector;
+
+/**
+ * An extension is an entity that is attached to a Component or another
+ * Extension and independently communicates between client and server.
+ * <p>
+ * An extension can only be attached once. It is not supported to move an
+ * extension from one target to another.
+ * <p>
+ * Extensions can use shared state and RPC in the same way as components.
+ *
+ * @author Vaadin Ltd
+ * @version @VERSION@
+ * @since 7.0.0
+ */
+public interface Extension extends ClientConnector {
+ /*
+ * Currently just an empty marker interface to distinguish between
+ * extensions and other connectors, e.g. components
+ */
+}
diff --git a/src/com/vaadin/terminal/JavaScriptCallbackHelper.java b/src/com/vaadin/terminal/JavaScriptCallbackHelper.java
new file mode 100644
index 0000000000..01db0267d9
--- /dev/null
+++ b/src/com/vaadin/terminal/JavaScriptCallbackHelper.java
@@ -0,0 +1,115 @@
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+
+package com.vaadin.terminal;
+
+import java.io.Serializable;
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import com.vaadin.external.json.JSONArray;
+import com.vaadin.external.json.JSONException;
+import com.vaadin.terminal.gwt.client.JavaScriptConnectorHelper;
+import com.vaadin.terminal.gwt.client.JavaScriptConnectorHelper.JavaScriptConnectorState;
+import com.vaadin.tools.ReflectTools;
+import com.vaadin.ui.AbstractJavaScriptComponent;
+import com.vaadin.ui.JavaScript.JavaScriptCallbackRpc;
+import com.vaadin.ui.JavaScriptCallback;
+
+/**
+ * Internal helper class used to implement functionality common to
+ * {@link AbstractJavaScriptComponent} and {@link AbstractJavaScriptExtension}.
+ * Corresponding support in client-side code is in
+ * {@link JavaScriptConnectorHelper}.
+ * <p>
+ * You should most likely no use this class directly.
+ *
+ * @author Vaadin Ltd
+ * @version @VERSION@
+ * @since 7.0.0
+ */
+public class JavaScriptCallbackHelper implements Serializable {
+
+ private static final Method CALL_METHOD = ReflectTools.findMethod(
+ JavaScriptCallbackRpc.class, "call", String.class, JSONArray.class);
+ private AbstractClientConnector connector;
+
+ private Map<String, JavaScriptCallback> callbacks = new HashMap<String, JavaScriptCallback>();
+ private JavaScriptCallbackRpc javascriptCallbackRpc;
+
+ public JavaScriptCallbackHelper(AbstractClientConnector connector) {
+ this.connector = connector;
+ }
+
+ public void registerCallback(String functionName,
+ JavaScriptCallback javaScriptCallback) {
+ callbacks.put(functionName, javaScriptCallback);
+ JavaScriptConnectorState state = getConnectorState();
+ if (state.getCallbackNames().add(functionName)) {
+ connector.requestRepaint();
+ }
+ ensureRpc();
+ }
+
+ private JavaScriptConnectorState getConnectorState() {
+ JavaScriptConnectorState state = (JavaScriptConnectorState) connector
+ .getState();
+ return state;
+ }
+
+ private void ensureRpc() {
+ if (javascriptCallbackRpc == null) {
+ javascriptCallbackRpc = new JavaScriptCallbackRpc() {
+ public void call(String name, JSONArray arguments) {
+ JavaScriptCallback callback = callbacks.get(name);
+ try {
+ callback.call(arguments);
+ } catch (JSONException e) {
+ throw new IllegalArgumentException(e);
+ }
+ }
+ };
+ connector.registerRpc(javascriptCallbackRpc);
+ }
+ }
+
+ public void invokeCallback(String name, Object... arguments) {
+ if (callbacks.containsKey(name)) {
+ throw new IllegalStateException(
+ "Can't call callback "
+ + name
+ + " on the client because a callback with the same name is registered on the server.");
+ }
+ JSONArray args = new JSONArray(Arrays.asList(arguments));
+ connector.addMethodInvocationToQueue(
+ JavaScriptCallbackRpc.class.getName(), CALL_METHOD,
+ new Object[] { name, args });
+ connector.requestRepaint();
+ }
+
+ public void registerRpc(Class<?> rpcInterfaceType) {
+ if (rpcInterfaceType == JavaScriptCallbackRpc.class) {
+ // Ignore
+ return;
+ }
+ Map<String, Set<String>> rpcInterfaces = getConnectorState()
+ .getRpcInterfaces();
+ String interfaceName = rpcInterfaceType.getName();
+ if (!rpcInterfaces.containsKey(interfaceName)) {
+ Set<String> methodNames = new HashSet<String>();
+
+ for (Method method : rpcInterfaceType.getMethods()) {
+ methodNames.add(method.getName());
+ }
+
+ rpcInterfaces.put(interfaceName, methodNames);
+ connector.requestRepaint();
+ }
+ }
+
+}
diff --git a/src/com/vaadin/terminal/Page.java b/src/com/vaadin/terminal/Page.java
new file mode 100644
index 0000000000..8ccb243a1e
--- /dev/null
+++ b/src/com/vaadin/terminal/Page.java
@@ -0,0 +1,646 @@
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+
+package com.vaadin.terminal;
+
+import java.io.Serializable;
+import java.lang.reflect.Method;
+import java.util.EventObject;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+
+import com.vaadin.event.EventRouter;
+import com.vaadin.terminal.WrappedRequest.BrowserDetails;
+import com.vaadin.terminal.gwt.client.ui.notification.VNotification;
+import com.vaadin.terminal.gwt.client.ui.root.PageClientRpc;
+import com.vaadin.terminal.gwt.client.ui.root.VRoot;
+import com.vaadin.terminal.gwt.server.WebApplicationContext;
+import com.vaadin.terminal.gwt.server.WebBrowser;
+import com.vaadin.tools.ReflectTools;
+import com.vaadin.ui.JavaScript;
+import com.vaadin.ui.Notification;
+import com.vaadin.ui.Root;
+
+public class Page implements Serializable {
+
+ /**
+ * Listener that gets notified when the size of the browser window
+ * containing the root has changed.
+ *
+ * @see Root#addListener(BrowserWindowResizeListener)
+ */
+ public interface BrowserWindowResizeListener extends Serializable {
+ /**
+ * Invoked when the browser window containing a Root has been resized.
+ *
+ * @param event
+ * a browser window resize event
+ */
+ public void browserWindowResized(BrowserWindowResizeEvent event);
+ }
+
+ /**
+ * Event that is fired when a browser window containing a root is resized.
+ */
+ public class BrowserWindowResizeEvent extends EventObject {
+
+ private final int width;
+ private final int height;
+
+ /**
+ * Creates a new event
+ *
+ * @param source
+ * the root for which the browser window has been resized
+ * @param width
+ * the new width of the browser window
+ * @param height
+ * the new height of the browser window
+ */
+ public BrowserWindowResizeEvent(Page source, int width, int height) {
+ super(source);
+ this.width = width;
+ this.height = height;
+ }
+
+ @Override
+ public Page getSource() {
+ return (Page) super.getSource();
+ }
+
+ /**
+ * Gets the new browser window height
+ *
+ * @return an integer with the new pixel height of the browser window
+ */
+ public int getHeight() {
+ return height;
+ }
+
+ /**
+ * Gets the new browser window width
+ *
+ * @return an integer with the new pixel width of the browser window
+ */
+ public int getWidth() {
+ return width;
+ }
+ }
+
+ /**
+ * Private class for storing properties related to opening resources.
+ */
+ private class OpenResource implements Serializable {
+
+ /**
+ * The resource to open
+ */
+ private final Resource resource;
+
+ /**
+ * The name of the target window
+ */
+ private final String name;
+
+ /**
+ * The width of the target window
+ */
+ private final int width;
+
+ /**
+ * The height of the target window
+ */
+ private final int height;
+
+ /**
+ * The border style of the target window
+ */
+ private final int border;
+
+ /**
+ * Creates a new open resource.
+ *
+ * @param resource
+ * The resource to open
+ * @param name
+ * The name of the target window
+ * @param width
+ * The width of the target window
+ * @param height
+ * The height of the target window
+ * @param border
+ * The border style of the target window
+ */
+ private OpenResource(Resource resource, String name, int width,
+ int height, int border) {
+ this.resource = resource;
+ this.name = name;
+ this.width = width;
+ this.height = height;
+ this.border = border;
+ }
+
+ /**
+ * Paints the open request. Should be painted inside the window.
+ *
+ * @param target
+ * the paint target
+ * @throws PaintException
+ * if the paint operation fails
+ */
+ private void paintContent(PaintTarget target) throws PaintException {
+ target.startTag("open");
+ target.addAttribute("src", resource);
+ if (name != null && name.length() > 0) {
+ target.addAttribute("name", name);
+ }
+ if (width >= 0) {
+ target.addAttribute("width", width);
+ }
+ if (height >= 0) {
+ target.addAttribute("height", height);
+ }
+ switch (border) {
+ case BORDER_MINIMAL:
+ target.addAttribute("border", "minimal");
+ break;
+ case BORDER_NONE:
+ target.addAttribute("border", "none");
+ break;
+ }
+
+ target.endTag("open");
+ }
+ }
+
+ private static final Method BROWSWER_RESIZE_METHOD = ReflectTools
+ .findMethod(BrowserWindowResizeListener.class,
+ "browserWindowResized", BrowserWindowResizeEvent.class);
+
+ /**
+ * A border style used for opening resources in a window without a border.
+ */
+ public static final int BORDER_NONE = 0;
+
+ /**
+ * A border style used for opening resources in a window with a minimal
+ * border.
+ */
+ public static final int BORDER_MINIMAL = 1;
+
+ /**
+ * A border style that indicates that the default border style should be
+ * used when opening resources.
+ */
+ public static final int BORDER_DEFAULT = 2;
+
+ /**
+ * Listener that listens changes in URI fragment.
+ */
+ public interface FragmentChangedListener extends Serializable {
+ public void fragmentChanged(FragmentChangedEvent event);
+ }
+
+ private static final Method FRAGMENT_CHANGED_METHOD = ReflectTools
+ .findMethod(Page.FragmentChangedListener.class, "fragmentChanged",
+ FragmentChangedEvent.class);
+
+ /**
+ * Resources to be opened automatically on next repaint. The list is
+ * automatically cleared when it has been sent to the client.
+ */
+ private final LinkedList<OpenResource> openList = new LinkedList<OpenResource>();
+
+ /**
+ * A list of notifications that are waiting to be sent to the client.
+ * Cleared (set to null) when the notifications have been sent.
+ */
+ private List<Notification> notifications;
+
+ /**
+ * Event fired when uri fragment changes.
+ */
+ public class FragmentChangedEvent extends EventObject {
+
+ /**
+ * The new uri fragment
+ */
+ private final String fragment;
+
+ /**
+ * Creates a new instance of UriFragmentReader change event.
+ *
+ * @param source
+ * the Source of the event.
+ */
+ public FragmentChangedEvent(Page source, String fragment) {
+ super(source);
+ this.fragment = fragment;
+ }
+
+ /**
+ * Gets the root in which the fragment has changed.
+ *
+ * @return the root in which the fragment has changed
+ */
+ public Page getPage() {
+ return (Page) getSource();
+ }
+
+ /**
+ * Get the new fragment
+ *
+ * @return the new fragment
+ */
+ public String getFragment() {
+ return fragment;
+ }
+ }
+
+ private EventRouter eventRouter;
+
+ /**
+ * The current URI fragment.
+ */
+ private String fragment;
+
+ private final Root root;
+
+ private int browserWindowWidth = -1;
+ private int browserWindowHeight = -1;
+
+ private JavaScript javaScript;
+
+ public Page(Root root) {
+ this.root = root;
+ }
+
+ private void addListener(Class<?> eventType, Object target, Method method) {
+ if (eventRouter == null) {
+ eventRouter = new EventRouter();
+ }
+ eventRouter.addListener(eventType, target, method);
+ }
+
+ private void removeListener(Class<?> eventType, Object target, Method method) {
+ if (eventRouter != null) {
+ eventRouter.removeListener(eventType, target, method);
+ }
+ }
+
+ public void addListener(Page.FragmentChangedListener listener) {
+ addListener(FragmentChangedEvent.class, listener,
+ FRAGMENT_CHANGED_METHOD);
+ }
+
+ public void removeListener(Page.FragmentChangedListener listener) {
+ removeListener(FragmentChangedEvent.class, listener,
+ FRAGMENT_CHANGED_METHOD);
+ }
+
+ /**
+ * Sets URI fragment. Optionally fires a {@link FragmentChangedEvent}
+ *
+ * @param newFragment
+ * id of the new fragment
+ * @param fireEvent
+ * true to fire event
+ * @see FragmentChangedEvent
+ * @see Page.FragmentChangedListener
+ */
+ public void setFragment(String newFragment, boolean fireEvents) {
+ if (newFragment == null) {
+ throw new NullPointerException("The fragment may not be null");
+ }
+ if (!newFragment.equals(fragment)) {
+ fragment = newFragment;
+ if (fireEvents) {
+ fireEvent(new FragmentChangedEvent(this, newFragment));
+ }
+ root.requestRepaint();
+ }
+ }
+
+ private void fireEvent(EventObject event) {
+ if (eventRouter != null) {
+ eventRouter.fireEvent(event);
+ }
+ }
+
+ /**
+ * Sets URI fragment. This method fires a {@link FragmentChangedEvent}
+ *
+ * @param newFragment
+ * id of the new fragment
+ * @see FragmentChangedEvent
+ * @see Page.FragmentChangedListener
+ */
+ public void setFragment(String newFragment) {
+ setFragment(newFragment, true);
+ }
+
+ /**
+ * Gets currently set URI fragment.
+ * <p>
+ * To listen changes in fragment, hook a
+ * {@link Page.FragmentChangedListener}.
+ *
+ * @return the current fragment in browser uri or null if not known
+ */
+ public String getFragment() {
+ return fragment;
+ }
+
+ public void init(WrappedRequest request) {
+ BrowserDetails browserDetails = request.getBrowserDetails();
+ if (browserDetails != null) {
+ fragment = browserDetails.getUriFragment();
+ }
+ }
+
+ public WebBrowser getWebBrowser() {
+ return ((WebApplicationContext) root.getApplication().getContext())
+ .getBrowser();
+ }
+
+ public void setBrowserWindowSize(Integer width, Integer height) {
+ boolean fireEvent = false;
+
+ if (width != null) {
+ int newWidth = width.intValue();
+ if (newWidth != browserWindowWidth) {
+ browserWindowWidth = newWidth;
+ fireEvent = true;
+ }
+ }
+
+ if (height != null) {
+ int newHeight = height.intValue();
+ if (newHeight != browserWindowHeight) {
+ browserWindowHeight = newHeight;
+ fireEvent = true;
+ }
+ }
+
+ if (fireEvent) {
+ fireEvent(new BrowserWindowResizeEvent(this, browserWindowWidth,
+ browserWindowHeight));
+ }
+
+ }
+
+ /**
+ * Adds a new {@link BrowserWindowResizeListener} to this root. The listener
+ * will be notified whenever the browser window within which this root
+ * resides is resized.
+ *
+ * @param resizeListener
+ * the listener to add
+ *
+ * @see BrowserWindowResizeListener#browserWindowResized(BrowserWindowResizeEvent)
+ * @see #setResizeLazy(boolean)
+ */
+ public void addListener(BrowserWindowResizeListener resizeListener) {
+ addListener(BrowserWindowResizeEvent.class, resizeListener,
+ BROWSWER_RESIZE_METHOD);
+ }
+
+ /**
+ * Removes a {@link BrowserWindowResizeListener} from this root. The
+ * listener will no longer be notified when the browser window is resized.
+ *
+ * @param resizeListener
+ * the listener to remove
+ */
+ public void removeListener(BrowserWindowResizeListener resizeListener) {
+ removeListener(BrowserWindowResizeEvent.class, resizeListener,
+ BROWSWER_RESIZE_METHOD);
+ }
+
+ /**
+ * Gets the last known height of the browser window in which this root
+ * resides.
+ *
+ * @return the browser window height in pixels
+ */
+ public int getBrowserWindowHeight() {
+ return browserWindowHeight;
+ }
+
+ /**
+ * Gets the last known width of the browser window in which this root
+ * resides.
+ *
+ * @return the browser window width in pixels
+ */
+ public int getBrowserWindowWidth() {
+ return browserWindowWidth;
+ }
+
+ public JavaScript getJavaScript() {
+ if (javaScript == null) {
+ // Create and attach on first use
+ javaScript = new JavaScript();
+ javaScript.extend(root);
+ }
+
+ return javaScript;
+ }
+
+ public void paintContent(PaintTarget target) throws PaintException {
+ if (!openList.isEmpty()) {
+ for (final Iterator<OpenResource> i = openList.iterator(); i
+ .hasNext();) {
+ (i.next()).paintContent(target);
+ }
+ openList.clear();
+ }
+
+ // Paint notifications
+ if (notifications != null) {
+ target.startTag("notifications");
+ for (final Iterator<Notification> it = notifications.iterator(); it
+ .hasNext();) {
+ final Notification n = it.next();
+ target.startTag("notification");
+ if (n.getCaption() != null) {
+ target.addAttribute(
+ VNotification.ATTRIBUTE_NOTIFICATION_CAPTION,
+ n.getCaption());
+ }
+ if (n.getDescription() != null) {
+ target.addAttribute(
+ VNotification.ATTRIBUTE_NOTIFICATION_MESSAGE,
+ n.getDescription());
+ }
+ if (n.getIcon() != null) {
+ target.addAttribute(
+ VNotification.ATTRIBUTE_NOTIFICATION_ICON,
+ n.getIcon());
+ }
+ if (!n.isHtmlContentAllowed()) {
+ target.addAttribute(
+ VRoot.NOTIFICATION_HTML_CONTENT_NOT_ALLOWED, true);
+ }
+ target.addAttribute(
+ VNotification.ATTRIBUTE_NOTIFICATION_POSITION,
+ n.getPosition());
+ target.addAttribute(VNotification.ATTRIBUTE_NOTIFICATION_DELAY,
+ n.getDelayMsec());
+ if (n.getStyleName() != null) {
+ target.addAttribute(
+ VNotification.ATTRIBUTE_NOTIFICATION_STYLE,
+ n.getStyleName());
+ }
+ target.endTag("notification");
+ }
+ target.endTag("notifications");
+ notifications = null;
+ }
+
+ if (fragment != null) {
+ target.addAttribute(VRoot.FRAGMENT_VARIABLE, fragment);
+ }
+
+ }
+
+ /**
+ * Opens the given resource in this root. The contents of this Root is
+ * replaced by the {@code Resource}.
+ *
+ * @param resource
+ * the resource to show in this root
+ */
+ public void open(Resource resource) {
+ openList.add(new OpenResource(resource, null, -1, -1, BORDER_DEFAULT));
+ root.requestRepaint();
+ }
+
+ /**
+ * Opens the given resource in a window with the given name.
+ * <p>
+ * The supplied {@code windowName} is used as the target name in a
+ * window.open call in the client. This means that special values such as
+ * "_blank", "_self", "_top", "_parent" have special meaning. An empty or
+ * <code>null</code> window name is also a special case.
+ * </p>
+ * <p>
+ * "", null and "_self" as {@code windowName} all causes the resource to be
+ * opened in the current window, replacing any old contents. For
+ * downloadable content you should avoid "_self" as "_self" causes the
+ * client to skip rendering of any other changes as it considers them
+ * irrelevant (the page will be replaced by the resource). This can speed up
+ * the opening of a resource, but it might also put the client side into an
+ * inconsistent state if the window content is not completely replaced e.g.,
+ * if the resource is downloaded instead of displayed in the browser.
+ * </p>
+ * <p>
+ * "_blank" as {@code windowName} causes the resource to always be opened in
+ * a new window or tab (depends on the browser and browser settings).
+ * </p>
+ * <p>
+ * "_top" and "_parent" as {@code windowName} works as specified by the HTML
+ * standard.
+ * </p>
+ * <p>
+ * Any other {@code windowName} will open the resource in a window with that
+ * name, either by opening a new window/tab in the browser or by replacing
+ * the contents of an existing window with that name.
+ * </p>
+ *
+ * @param resource
+ * the resource.
+ * @param windowName
+ * the name of the window.
+ */
+ public void open(Resource resource, String windowName) {
+ openList.add(new OpenResource(resource, windowName, -1, -1,
+ BORDER_DEFAULT));
+ root.requestRepaint();
+ }
+
+ /**
+ * Opens the given resource in a window with the given size, border and
+ * name. For more information on the meaning of {@code windowName}, see
+ * {@link #open(Resource, String)}.
+ *
+ * @param resource
+ * the resource.
+ * @param windowName
+ * the name of the window.
+ * @param width
+ * the width of the window in pixels
+ * @param height
+ * the height of the window in pixels
+ * @param border
+ * the border style of the window. See {@link #BORDER_NONE
+ * Window.BORDER_* constants}
+ */
+ public void open(Resource resource, String windowName, int width,
+ int height, int border) {
+ openList.add(new OpenResource(resource, windowName, width, height,
+ border));
+ root.requestRepaint();
+ }
+
+ /**
+ * Internal helper method to actually add a notification.
+ *
+ * @param notification
+ * the notification to add
+ */
+ private void addNotification(Notification notification) {
+ if (notifications == null) {
+ notifications = new LinkedList<Notification>();
+ }
+ notifications.add(notification);
+ root.requestRepaint();
+ }
+
+ /**
+ * Shows a notification message.
+ *
+ * @see Notification
+ *
+ * @param notification
+ * The notification message to show
+ *
+ * @deprecated Use Notification.show(Page) instead.
+ */
+ @Deprecated
+ public void showNotification(Notification notification) {
+ addNotification(notification);
+ }
+
+ /**
+ * Gets the Page to which the current root belongs. This is automatically
+ * defined when processing requests to the server. In other cases, (e.g.
+ * from background threads), the current root is not automatically defined.
+ *
+ * @see Root#getCurrent()
+ *
+ * @return the current page instance if available, otherwise
+ * <code>null</code>
+ */
+ public static Page getCurrent() {
+ Root currentRoot = Root.getCurrent();
+ if (currentRoot == null) {
+ return null;
+ }
+ return currentRoot.getPage();
+ }
+
+ /**
+ * Sets the page title. The page title is displayed by the browser e.g. as
+ * the title of the browser window or as the title of the tab.
+ *
+ * @param title
+ * the new page title to set
+ */
+ public void setTitle(String title) {
+ root.getRpcProxy(PageClientRpc.class).setTitle(title);
+ }
+
+}
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 {
* </p>
* <p>
* 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.
* </p>
*
* @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/UserError.java b/src/com/vaadin/terminal/UserError.java
index baaf331fa0..a7a4fd89e2 100644
--- a/src/com/vaadin/terminal/UserError.java
+++ b/src/com/vaadin/terminal/UserError.java
@@ -44,6 +44,16 @@ public class UserError extends AbstractErrorMessage {
super(textErrorMessage);
}
+ /**
+ * Creates an error message with level and content mode.
+ *
+ * @param message
+ * the error message.
+ * @param contentMode
+ * the content Mode.
+ * @param errorLevel
+ * the level of error.
+ */
public UserError(String message, ContentMode contentMode,
ErrorLevel errorLevel) {
super(message);
diff --git a/src/com/vaadin/terminal/gwt/DefaultWidgetSet.gwt.xml b/src/com/vaadin/terminal/gwt/DefaultWidgetSet.gwt.xml
index 3487a655e5..77e3127745 100644
--- a/src/com/vaadin/terminal/gwt/DefaultWidgetSet.gwt.xml
+++ b/src/com/vaadin/terminal/gwt/DefaultWidgetSet.gwt.xml
@@ -71,9 +71,9 @@
<!-- Generate client side RPC manager for server to client RPC -->
<generate-with
- class="com.vaadin.terminal.gwt.widgetsetutils.RpcManagerGenerator">
+ class="com.vaadin.terminal.gwt.widgetsetutils.GeneratedRpcMethodProviderGenerator">
<when-type-assignable
- class="com.vaadin.terminal.gwt.client.communication.RpcManager" />
+ class="com.vaadin.terminal.gwt.client.communication.GeneratedRpcMethodProvider" />
</generate-with>
<generate-with
diff --git a/src/com/vaadin/terminal/gwt/client/ApplicationConfiguration.java b/src/com/vaadin/terminal/gwt/client/ApplicationConfiguration.java
index 8eeccb828d..960b0a8b0e 100644
--- a/src/com/vaadin/terminal/gwt/client/ApplicationConfiguration.java
+++ b/src/com/vaadin/terminal/gwt/client/ApplicationConfiguration.java
@@ -18,6 +18,7 @@ import com.google.gwt.core.client.Scheduler;
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
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.UnknownComponentConnector;
public class ApplicationConfiguration implements EntryPoint {
@@ -209,7 +210,7 @@ public class ApplicationConfiguration implements EntryPoint {
private HashMap<Integer, String> unknownComponents;
- private Class<? extends ComponentConnector>[] classes = new Class[1024];
+ private Class<? extends ServerConnector>[] classes = new Class[1024];
private boolean browserDetailsSent = false;
private boolean widgetsetVersionSent = false;
@@ -346,6 +347,7 @@ public class ApplicationConfiguration implements EntryPoint {
*/
public static void startApplication(final String applicationId) {
Scheduler.get().scheduleDeferred(new ScheduledCommand() {
+
public void execute() {
ApplicationConfiguration appConf = getConfigFromDOM(applicationId);
ApplicationConnection a = GWT
@@ -393,7 +395,7 @@ public class ApplicationConfiguration implements EntryPoint {
return useDebugIdInDom;
}
- public Class<? extends ComponentConnector> getWidgetClassByEncodedTag(
+ public Class<? extends ServerConnector> getConnectorClassByEncodedTag(
int tag) {
try {
return classes[tag];
@@ -508,7 +510,7 @@ public class ApplicationConfiguration implements EntryPoint {
public void run() {
pending = false;
if (!isBusy()) {
- Class<? extends ComponentConnector> nextType = getNextType();
+ Class<? extends ServerConnector> nextType = getNextType();
if (nextType == null) {
// ensured that all widgets are loaded
deferredWidgetLoader = null;
@@ -521,13 +523,13 @@ public class ApplicationConfiguration implements EntryPoint {
}
}
- private Class<? extends ComponentConnector> getNextType() {
- Class<? extends ComponentConnector>[] deferredLoadedWidgets = widgetSet
- .getDeferredLoadedWidgets();
- if (deferredLoadedWidgets.length <= nextWidgetIndex) {
+ private Class<? extends ServerConnector> getNextType() {
+ Class<? extends ServerConnector>[] deferredLoadedConnectors = widgetSet
+ .getDeferredLoadedConnectors();
+ if (deferredLoadedConnectors.length <= nextWidgetIndex) {
return null;
} else {
- return deferredLoadedWidgets[nextWidgetIndex++];
+ return deferredLoadedConnectors[nextWidgetIndex++];
}
}
@@ -568,6 +570,7 @@ public class ApplicationConfiguration implements EntryPoint {
* GWT hosted mode.
*/
GWT.setUncaughtExceptionHandler(new UncaughtExceptionHandler() {
+
public void onUncaughtException(Throwable e) {
/*
* Note in case of null console (without ?debug) we eat
@@ -602,12 +605,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;
}
@@ -618,12 +624,11 @@ public class ApplicationConfiguration implements EntryPoint {
*
* @return <code>true</code> 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");
+ }
/**
* Checks whether information from the web browser (e.g. uri fragment and
diff --git a/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java b/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java
index 51a0ec3f02..f0470c8ee8 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;
@@ -39,12 +40,17 @@ import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.Widget;
import com.vaadin.terminal.gwt.client.ApplicationConfiguration.ErrorMessage;
+import com.vaadin.terminal.gwt.client.communication.HasJavaScriptConnectorHelper;
import com.vaadin.terminal.gwt.client.communication.JsonDecoder;
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.extensions.AbstractExtensionConnector;
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;
@@ -365,6 +371,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.
*
@@ -846,6 +871,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();
}
}
});
@@ -1271,27 +1304,24 @@ public class ApplicationConnection {
List<ServerConnector> currentConnectors = new ArrayList<ServerConnector>(
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 +1349,8 @@ public class ApplicationConnection {
continue;
}
- Class<? extends ComponentConnector> connectorClass = configuration
- .getWidgetClassByEncodedTag(connectorType);
+ Class<? extends ServerConnector> connectorClass = configuration
+ .getConnectorClassByEncodedTag(connectorType);
// Connector does not exist so we must create it
if (connectorClass != RootConnector.class) {
@@ -1410,11 +1440,19 @@ public class ApplicationConnection {
.getConnector(connectorId);
if (null != connector) {
- JSONArray stateDataAndType = new JSONArray(
+ JSONObject stateJson = new JSONObject(
states.getJavaScriptObject(connectorId));
- JsonDecoder.decodeValue(stateDataAndType,
- connector.getState(), connectorMap,
+ if (connector instanceof HasJavaScriptConnectorHelper) {
+ ((HasJavaScriptConnectorHelper) connector)
+ .getJavascriptConnectorHelper()
+ .setNativeState(
+ stateJson.getJavaScriptObject());
+ }
+
+ SharedState state = connector.getState();
+ JsonDecoder.decodeValue(new Type(state.getClass()
+ .getName(), null), stateJson, state,
ApplicationConnection.this);
StateChangeEvent event = GWT
@@ -1454,47 +1492,48 @@ 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<ServerConnector> newChildren = new ArrayList<ServerConnector>();
+ List<ComponentConnector> newComponents = new ArrayList<ComponentConnector>();
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);
+ } else if (!(childConnector instanceof AbstractExtensionConnector)) {
+ throw new IllegalStateException(
+ Util.getConnectorString(childConnector)
+ + " is not a ComponentConnector nor an AbstractExtensionConnector");
+ }
+ 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<ComponentConnector> oldChildren = ccc
+ List<ServerConnector> oldChildren = parentConnector
.getChildren();
boolean actuallyChanged = !Util.collectionsEquals(
oldChildren, newChildren);
@@ -1503,19 +1542,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<ComponentConnector> 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;
}
@@ -1543,11 +1597,8 @@ public class ApplicationConnection {
for (int i = 0; i < rpcLength; i++) {
try {
JSONArray rpcCall = (JSONArray) rpcCalls.get(i);
- MethodInvocation invocation = parseMethodInvocation(rpcCall);
- VConsole.log("Server to client RPC call: "
- + invocation);
- rpcManager.applyInvocation(invocation,
- getConnectorMap());
+ rpcManager.parseAndApplyInvocation(rpcCall,
+ ApplicationConnection.this);
} catch (final Throwable e) {
VConsole.error(e);
}
@@ -1560,21 +1611,6 @@ public class ApplicationConnection {
ApplicationConfiguration.runWhenWidgetsLoaded(c);
}
- private MethodInvocation parseMethodInvocation(JSONArray rpcCall) {
- String connectorId = ((JSONString) rpcCall.get(0)).stringValue();
- String interfaceName = ((JSONString) rpcCall.get(1)).stringValue();
- String methodName = ((JSONString) rpcCall.get(2)).stringValue();
- JSONArray parametersJson = (JSONArray) rpcCall.get(3);
- 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);
- }
- return new MethodInvocation(connectorId, interfaceName, methodName,
- parameters);
- }
-
// Redirect browser, null reloads current page
private static native void redirect(String url)
/*-{
@@ -1591,7 +1627,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);
}
/**
@@ -1692,7 +1728,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);
@@ -2079,7 +2115,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 +2136,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,12 +2154,12 @@ 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,
+ ServerConnector p = widgetSet.createConnector(connectorType,
configuration);
connectorMap.registerConnector(connectorId, p);
p.doInit(connectorId, this);
diff --git a/src/com/vaadin/terminal/gwt/client/BrowserInfo.java b/src/com/vaadin/terminal/gwt/client/BrowserInfo.java
index e12c002930..82cf925ec1 100644
--- a/src/com/vaadin/terminal/gwt/client/BrowserInfo.java
+++ b/src/com/vaadin/terminal/gwt/client/BrowserInfo.java
@@ -31,6 +31,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;
@@ -169,7 +172,9 @@ public class BrowserInfo {
if (osClass != null) {
cssClass = cssClass + " " + prefix + osClass;
}
-
+ if (isTouchDevice()) {
+ cssClass = cssClass + " " + prefix + UI_TOUCH;
+ }
}
return cssClass;
@@ -344,15 +349,14 @@ 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;
+ // Cannot enable native touch scrolling on iOS 5 until #8792 is resolved
+ // if (isIOS() && isWebkit() && getWebkitVersion() >= 534) {
+ // return false;
// }
-
- return false;
+ return true;
}
/**
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
@@ -71,29 +71,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.
- * <p>
- * 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.
*
* @deprecated This belongs in AbstractFieldConnector, see #8514
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<ComponentConnector> getChildren();
+ public List<ComponentConnector> 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.
* <p>
* 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<ComponentConnector> children);
+ public void setChildComponents(List<ComponentConnector> 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 a4df6c6cc4..0e7a0c1d1c 100644
--- a/src/com/vaadin/terminal/gwt/client/ComponentLocator.java
+++ b/src/com/vaadin/terminal/gwt/client/ComponentLocator.java
@@ -12,6 +12,7 @@ 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.Widget;
+import com.vaadin.terminal.gwt.client.communication.SharedState;
import com.vaadin.terminal.gwt.client.ui.SubPartAware;
import com.vaadin.terminal.gwt.client.ui.VBoxLayout;
import com.vaadin.terminal.gwt.client.ui.gridlayout.VGridLayout;
@@ -441,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
@@ -450,8 +451,8 @@ public class ComponentLocator {
id.substring(5));
}
- if (connector != null) {
- w = connector.getWidget();
+ if (connector instanceof ComponentConnector) {
+ w = ((ComponentConnector) connector).getWidget();
} else {
// Not found
return null;
@@ -597,19 +598,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 7f01300d68..a603368f44 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!
@@ -195,29 +194,6 @@ public class ComponentState extends SharedState {
}
/**
- * 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).
*
* @see com.vaadin.ui.AbstractComponent#getDescription()
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 <code>null</code> if the
+ * connector is not attached to any parent.
+ *
+ * @return the parent connector, or <code>null</code> 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..efb50b5e00 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);
}
}
}
@@ -209,12 +208,20 @@ public class ConnectorMap {
*/
@Deprecated
public TooltipInfo getTooltipInfo(ComponentConnector paintable, Object key) {
- return getComponentDetail(paintable).getTooltipInfo(key);
+ ComponentDetail componentDetail = getComponentDetail(paintable);
+ if (componentDetail == null) {
+ return null;
+ }
+ return componentDetail.getTooltipInfo(key);
}
@Deprecated
public TooltipInfo getWidgetTooltipInfo(Widget widget, Object key) {
- return getTooltipInfo(getConnector(widget), key);
+ ComponentConnector connector = getConnector(widget);
+ if (connector == null) {
+ return null;
+ }
+ return getTooltipInfo(connector, key);
}
public Collection<? extends ServerConnector> getConnectors() {
diff --git a/src/com/vaadin/terminal/gwt/client/JavaScriptConnectorHelper.java b/src/com/vaadin/terminal/gwt/client/JavaScriptConnectorHelper.java
new file mode 100644
index 0000000000..bd62a759cb
--- /dev/null
+++ b/src/com/vaadin/terminal/gwt/client/JavaScriptConnectorHelper.java
@@ -0,0 +1,372 @@
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+
+package com.vaadin.terminal.gwt.client;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import com.google.gwt.core.client.JavaScriptObject;
+import com.google.gwt.core.client.JsArray;
+import com.google.gwt.json.client.JSONArray;
+import com.google.gwt.user.client.Element;
+import com.vaadin.terminal.gwt.client.communication.MethodInvocation;
+import com.vaadin.terminal.gwt.client.communication.StateChangeEvent;
+import com.vaadin.terminal.gwt.client.communication.StateChangeEvent.StateChangeHandler;
+
+public class JavaScriptConnectorHelper {
+
+ public interface JavaScriptConnectorState {
+ public Set<String> getCallbackNames();
+
+ public Map<String, Set<String>> getRpcInterfaces();
+ }
+
+ private final ServerConnector connector;
+ private final JavaScriptObject nativeState = JavaScriptObject
+ .createObject();
+ private final JavaScriptObject rpcMap = JavaScriptObject.createObject();
+
+ private final Map<String, JavaScriptObject> rpcObjects = new HashMap<String, JavaScriptObject>();
+ private final Map<String, Set<String>> rpcMethods = new HashMap<String, Set<String>>();
+
+ private JavaScriptObject connectorWrapper;
+ private int tag;
+
+ private boolean inited = false;
+
+ public JavaScriptConnectorHelper(ServerConnector connector) {
+ this.connector = connector;
+
+ // Wildcard rpc object
+ rpcObjects.put("", JavaScriptObject.createObject());
+ }
+
+ public void init() {
+ connector.addStateChangeHandler(new StateChangeHandler() {
+ public void onStateChanged(StateChangeEvent stateChangeEvent) {
+ JavaScriptObject wrapper = getConnectorWrapper();
+ JavaScriptConnectorState state = getConnectorState();
+
+ for (String callback : state.getCallbackNames()) {
+ ensureCallback(JavaScriptConnectorHelper.this, wrapper,
+ callback);
+ }
+
+ for (Entry<String, Set<String>> entry : state
+ .getRpcInterfaces().entrySet()) {
+ String rpcName = entry.getKey();
+ String jsName = getJsInterfaceName(rpcName);
+ if (!rpcObjects.containsKey(jsName)) {
+ Set<String> methods = entry.getValue();
+ rpcObjects.put(jsName,
+ createRpcObject(rpcName, methods));
+
+ // Init all methods for wildcard rpc
+ for (String method : methods) {
+ JavaScriptObject wildcardRpcObject = rpcObjects
+ .get("");
+ Set<String> interfaces = rpcMethods.get(method);
+ if (interfaces == null) {
+ interfaces = new HashSet<String>();
+ rpcMethods.put(method, interfaces);
+ attachRpcMethod(wildcardRpcObject, null, method);
+ }
+ interfaces.add(rpcName);
+ }
+ }
+ }
+
+ // Init after setting up callbacks & rpc
+ if (!inited) {
+ initJavaScript();
+ inited = true;
+ }
+
+ fireNativeStateChange(wrapper);
+ }
+ });
+ }
+
+ private static String getJsInterfaceName(String rpcName) {
+ return rpcName.replace('$', '.');
+ }
+
+ protected JavaScriptObject createRpcObject(String iface, Set<String> methods) {
+ JavaScriptObject object = JavaScriptObject.createObject();
+
+ for (String method : methods) {
+ attachRpcMethod(object, iface, method);
+ }
+
+ return object;
+ }
+
+ private boolean initJavaScript() {
+ ApplicationConfiguration conf = connector.getConnection()
+ .getConfiguration();
+ ArrayList<String> attemptedNames = new ArrayList<String>();
+ Integer tag = Integer.valueOf(this.tag);
+ while (tag != null) {
+ String serverSideClassName = conf.getServerSideClassNameForTag(tag);
+ String initFunctionName = serverSideClassName
+ .replaceAll("\\.", "_");
+ if (tryInitJs(initFunctionName, getConnectorWrapper())) {
+ VConsole.log("JavaScript connector initialized using "
+ + initFunctionName);
+ return true;
+ } else {
+ VConsole.log("No JavaScript function " + initFunctionName
+ + " found");
+ attemptedNames.add(initFunctionName);
+ tag = conf.getParentTag(tag.intValue());
+ }
+ }
+ VConsole.log("No JavaScript init for connector not found");
+ showInitProblem(attemptedNames);
+ return false;
+ }
+
+ protected void showInitProblem(ArrayList<String> attemptedNames) {
+ // Default does nothing
+ }
+
+ private static native boolean tryInitJs(String initFunctionName,
+ JavaScriptObject connectorWrapper)
+ /*-{
+ if (typeof $wnd[initFunctionName] == 'function') {
+ $wnd[initFunctionName].apply(connectorWrapper);
+ return true;
+ } else {
+ return false;
+ }
+ }-*/;
+
+ private JavaScriptObject getConnectorWrapper() {
+ if (connectorWrapper == null) {
+ connectorWrapper = createConnectorWrapper(this, nativeState,
+ rpcMap, connector.getConnectorId(), rpcObjects);
+ }
+
+ return connectorWrapper;
+ }
+
+ private static native void fireNativeStateChange(
+ JavaScriptObject connectorWrapper)
+ /*-{
+ if (typeof connectorWrapper.onStateChange == 'function') {
+ connectorWrapper.onStateChange();
+ }
+ }-*/;
+
+ private static native JavaScriptObject createConnectorWrapper(
+ JavaScriptConnectorHelper h, JavaScriptObject nativeState,
+ JavaScriptObject registeredRpc, String connectorId,
+ Map<String, JavaScriptObject> rpcObjects)
+ /*-{
+ return {
+ 'getConnectorId': function() {
+ return connectorId;
+ },
+ 'getParentId': $entry(function(connectorId) {
+ return h.@com.vaadin.terminal.gwt.client.JavaScriptConnectorHelper::getParentId(Ljava/lang/String;)(connectorId);
+ }),
+ 'getState': function() {
+ return nativeState;
+ },
+ 'getRpcProxy': $entry(function(iface) {
+ if (!iface) {
+ iface = '';
+ }
+ return rpcObjects.@java.util.Map::get(Ljava/lang/Object;)(iface);
+ }),
+ 'getWidgetElement': $entry(function(connectorId) {
+ return h.@com.vaadin.terminal.gwt.client.JavaScriptConnectorHelper::getWidgetElement(Ljava/lang/String;)(connectorId);
+ }),
+ 'registerRpc': function(iface, rpcHandler) {
+ //registerRpc(handler) -> registerRpc('', handler);
+ if (!rpcHandler) {
+ rpcHandler = iface;
+ iface = '';
+ }
+ if (!registeredRpc[iface]) {
+ registeredRpc[iface] = [];
+ }
+ registeredRpc[iface].push(rpcHandler);
+ },
+ };
+ }-*/;
+
+ private native void attachRpcMethod(JavaScriptObject rpc, String iface,
+ String method)
+ /*-{
+ var self = this;
+ rpc[method] = $entry(function() {
+ self.@com.vaadin.terminal.gwt.client.JavaScriptConnectorHelper::fireRpc(Ljava/lang/String;Ljava/lang/String;Lcom/google/gwt/core/client/JsArray;)(iface, method, arguments);
+ });
+ }-*/;
+
+ private String getParentId(String connectorId) {
+ ServerConnector target = getConnector(connectorId);
+ if (target == null) {
+ return null;
+ }
+ ServerConnector parent = target.getParent();
+ if (parent == null) {
+ return null;
+ } else {
+ return parent.getConnectorId();
+ }
+ }
+
+ private Element getWidgetElement(String connectorId) {
+ ServerConnector target = getConnector(connectorId);
+ if (target instanceof ComponentConnector) {
+ return ((ComponentConnector) target).getWidget().getElement();
+ } else {
+ return null;
+ }
+ }
+
+ private ServerConnector getConnector(String connectorId) {
+ if (connectorId == null || connectorId.length() == 0) {
+ return connector;
+ }
+
+ return ConnectorMap.get(connector.getConnection())
+ .getConnector(connectorId);
+ }
+
+ private void fireRpc(String iface, String method,
+ JsArray<JavaScriptObject> arguments) {
+ if (iface == null) {
+ iface = findWildcardInterface(method);
+ }
+
+ JSONArray argumentsArray = new JSONArray(arguments);
+ Object[] parameters = new Object[arguments.length()];
+ for (int i = 0; i < parameters.length; i++) {
+ parameters[i] = argumentsArray.get(i);
+ }
+ connector.getConnection().addMethodInvocationToQueue(
+ new MethodInvocation(connector.getConnectorId(), iface, method,
+ parameters), true);
+ }
+
+ private String findWildcardInterface(String method) {
+ Set<String> interfaces = rpcMethods.get(method);
+ if (interfaces.size() == 1) {
+ return interfaces.iterator().next();
+ } else {
+ // TODO Resolve conflicts using argument count and types
+ String interfaceList = "";
+ for (String iface : interfaces) {
+ if (interfaceList.length() != 0) {
+ interfaceList += ", ";
+ }
+ interfaceList += getJsInterfaceName(iface);
+ }
+
+ throw new IllegalStateException(
+ "Can not call method "
+ + method
+ + " for wildcard rpc proxy because the function is defined for multiple rpc interfaces: "
+ + interfaceList
+ + ". Retrieve a rpc proxy for a specific interface using getRpcProxy(interfaceName) to use the function.");
+ }
+ }
+
+ private void fireCallback(String name, JsArray<JavaScriptObject> arguments) {
+ MethodInvocation invocation = new MethodInvocation(
+ connector.getConnectorId(),
+ "com.vaadin.ui.JavaScript$JavaScriptCallbackRpc", "call",
+ new Object[] { name, new JSONArray(arguments) });
+ connector.getConnection().addMethodInvocationToQueue(invocation, true);
+ }
+
+ public void setNativeState(JavaScriptObject state) {
+ updateNativeState(nativeState, state);
+ }
+
+ private static native void updateNativeState(JavaScriptObject state,
+ JavaScriptObject input)
+ /*-{
+ // Copy all fields to existing state object
+ for(var key in state) {
+ if (state.hasOwnProperty(key)) {
+ delete state[key];
+ }
+ }
+
+ for(var key in input) {
+ if (input.hasOwnProperty(key)) {
+ state[key] = input[key];
+ }
+ }
+ }-*/;
+
+ public Object[] decodeRpcParameters(JSONArray parametersJson) {
+ return new Object[] { parametersJson.getJavaScriptObject() };
+ }
+
+ public void setTag(int tag) {
+ this.tag = tag;
+ }
+
+ public void invokeJsRpc(MethodInvocation invocation,
+ JSONArray parametersJson) {
+ String iface = invocation.getInterfaceName();
+ String method = invocation.getMethodName();
+ if ("com.vaadin.ui.JavaScript$JavaScriptCallbackRpc".equals(iface)
+ && "call".equals(method)) {
+ String callbackName = parametersJson.get(0).isString()
+ .stringValue();
+ JavaScriptObject arguments = parametersJson.get(1).isArray()
+ .getJavaScriptObject();
+ invokeCallback(getConnectorWrapper(), callbackName, arguments);
+ } else {
+ JavaScriptObject arguments = parametersJson.getJavaScriptObject();
+ invokeJsRpc(rpcMap, iface, method, arguments);
+ // Also invoke wildcard interface
+ invokeJsRpc(rpcMap, "", method, arguments);
+ }
+ }
+
+ private static native void invokeCallback(JavaScriptObject connector,
+ String name, JavaScriptObject arguments)
+ /*-{
+ connector[name].apply(connector, arguments);
+ }-*/;
+
+ private static native void invokeJsRpc(JavaScriptObject rpcMap,
+ String interfaceName, String methodName, JavaScriptObject parameters)
+ /*-{
+ var targets = rpcMap[interfaceName];
+ if (!targets) {
+ return;
+ }
+ for(var i = 0; i < targets.length; i++) {
+ var target = targets[i];
+ target[methodName].apply(target, parameters);
+ }
+ }-*/;
+
+ private static native void ensureCallback(JavaScriptConnectorHelper h,
+ JavaScriptObject connector, String name)
+ /*-{
+ connector[name] = $entry(function() {
+ var args = Array.prototype.slice.call(arguments, 0);
+ h.@com.vaadin.terminal.gwt.client.JavaScriptConnectorHelper::fireCallback(Ljava/lang/String;Lcom/google/gwt/core/client/JsArray;)(name, args);
+ });
+ }-*/;
+
+ private JavaScriptConnectorState getConnectorState() {
+ return (JavaScriptConnectorState) connector.getState();
+ }
+
+}
diff --git a/src/com/vaadin/terminal/gwt/client/JavaScriptExtension.java b/src/com/vaadin/terminal/gwt/client/JavaScriptExtension.java
new file mode 100644
index 0000000000..2a97e4a770
--- /dev/null
+++ b/src/com/vaadin/terminal/gwt/client/JavaScriptExtension.java
@@ -0,0 +1,32 @@
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+
+package com.vaadin.terminal.gwt.client;
+
+import com.vaadin.terminal.AbstractJavaScriptExtension;
+import com.vaadin.terminal.gwt.client.communication.HasJavaScriptConnectorHelper;
+import com.vaadin.terminal.gwt.client.extensions.AbstractExtensionConnector;
+import com.vaadin.terminal.gwt.client.ui.Connect;
+
+@Connect(AbstractJavaScriptExtension.class)
+public final class JavaScriptExtension extends AbstractExtensionConnector
+ implements HasJavaScriptConnectorHelper {
+ private final JavaScriptConnectorHelper helper = new JavaScriptConnectorHelper(
+ this);
+
+ @Override
+ protected void init() {
+ super.init();
+ helper.init();
+ }
+
+ public JavaScriptConnectorHelper getJavascriptConnectorHelper() {
+ return helper;
+ }
+
+ @Override
+ public JavaScriptExtensionState getState() {
+ return (JavaScriptExtensionState) super.getState();
+ }
+}
diff --git a/src/com/vaadin/terminal/gwt/client/JavaScriptExtensionState.java b/src/com/vaadin/terminal/gwt/client/JavaScriptExtensionState.java
new file mode 100644
index 0000000000..e7bfbc4bb2
--- /dev/null
+++ b/src/com/vaadin/terminal/gwt/client/JavaScriptExtensionState.java
@@ -0,0 +1,36 @@
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+
+package com.vaadin.terminal.gwt.client;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import com.vaadin.terminal.gwt.client.JavaScriptConnectorHelper.JavaScriptConnectorState;
+import com.vaadin.terminal.gwt.client.communication.SharedState;
+
+public class JavaScriptExtensionState extends SharedState implements
+ JavaScriptConnectorState {
+
+ private Set<String> callbackNames = new HashSet<String>();
+ private Map<String, Set<String>> rpcInterfaces = new HashMap<String, Set<String>>();
+
+ public Set<String> getCallbackNames() {
+ return callbackNames;
+ }
+
+ public void setCallbackNames(Set<String> callbackNames) {
+ this.callbackNames = callbackNames;
+ }
+
+ public Map<String, Set<String>> getRpcInterfaces() {
+ return rpcInterfaces;
+ }
+
+ public void setRpcInterfaces(Map<String, Set<String>> rpcInterfaces) {
+ this.rpcInterfaces = rpcInterfaces;
+ }
+}
diff --git a/src/com/vaadin/terminal/gwt/client/LayoutManager.java b/src/com/vaadin/terminal/gwt/client/LayoutManager.java
index 239a948a10..41ad0e9f47 100644
--- a/src/com/vaadin/terminal/gwt/client/LayoutManager.java
+++ b/src/com/vaadin/terminal/gwt/client/LayoutManager.java
@@ -120,7 +120,7 @@ public class LayoutManager {
/**
* Assigns a measured size to an element. Method defined as protected to
- * allow separate implementation for IE8 in which delete not always works.
+ * allow separate implementation for IE8.
*
* @param element
* the dom element to attach the measured size to
@@ -139,18 +139,14 @@ public class LayoutManager {
}-*/;
/**
- * Get the measured size of the given element. If no size is set, use the
- * default size instead.
- *
- * Method defined as protected to allow separate implementation for IE8
- * (performance reason: storing any data in the DOM causes a reflow).
+ * Gets the measured size for an element. Method defined as protected to
+ * allow separate implementation for IE8.
*
* @param element
- * the dom element whose measured size to get
+ * The element to get measured size for
* @param defaultSize
- * a fallback size if the element doesn't have a measured size
- * stored
- * @return
+ * The size to return if no measured size could be found
+ * @return The measured size for the element or {@literal defaultSize}
*/
protected native MeasuredSize getMeasuredSize(Element element,
MeasuredSize defaultSize)
@@ -185,7 +181,7 @@ public class LayoutManager {
return;
}
measuredSize.removeDependent(owner.getConnectorId());
- stopMeasuringIfUnnecessary(element);
+ stopMeasuringIfUnecessary(element);
}
public boolean isLayoutRunning() {
@@ -270,16 +266,10 @@ public class LayoutManager {
VConsole.log(" Measured " + measuredConnectorCount
+ " elements in " + measureTime + " ms");
- VConsole.log(" Total of " + measureCount
- + " measurement operations");
-
if (!listenersToFire.isEmpty()) {
for (Element element : listenersToFire) {
Collection<ElementResizeListener> listeners = elementResizeListeners
.get(element);
- if (listeners == null) {
- continue;
- }
ElementResizeListener[] array = listeners
.toArray(new ElementResizeListener[listeners.size()]);
ElementResizeEvent event = new ElementResizeEvent(this,
@@ -409,8 +399,13 @@ public class LayoutManager {
((PostLayoutListener) connector).postLayout();
}
}
- VConsole.log("Invoke post layout listeners in "
- + (totalDuration.elapsedMillis() - postLayoutStart) + " ms");
+ int postLayoutDone = (totalDuration.elapsedMillis() - postLayoutStart);
+ VConsole.log("Invoke post layout listeners in " + postLayoutDone
+ + " ms");
+
+ cleanMeasuredSizes();
+ int cleaningDone = (totalDuration.elapsedMillis() - postLayoutDone);
+ VConsole.log("Cleaned old measured sizes in " + cleaningDone + "ms");
VConsole.log("Total layout phase time: "
+ totalDuration.elapsedMillis() + "ms");
@@ -436,11 +431,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;
}
@@ -521,15 +518,8 @@ public class LayoutManager {
}
private void measureConnector(ComponentConnector connector) {
- MeasuredSize measuredSize = getMeasuredSize(connector);
- if (!isManagedLayout(connector)
- && !isManagedLayout(connector.getParent())
- && elementResizeListeners.get(connector.getWidget()
- .getElement()) == null && !measuredSize.hasDependents()) {
- return;
- }
-
Element element = connector.getWidget().getElement();
+ MeasuredSize measuredSize = getMeasuredSize(connector);
MeasureResult measureResult = measuredAndUpdate(element, measuredSize);
if (measureResult.isChanged()) {
@@ -569,11 +559,8 @@ public class LayoutManager {
+ " non connector elements");
}
- int measureCount = 0;
-
private MeasureResult measuredAndUpdate(Element element,
MeasuredSize measuredSize) {
- measureCount++;
MeasureResult measureResult = measuredSize.measure(element);
if (measureResult.isChanged()) {
notifyListenersAndDepdendents(element,
@@ -1032,12 +1019,48 @@ public class LayoutManager {
return getMeasuredSize(element, nullSize).getMarginLeft();
}
- public int getMarginWidth(Element element) {
- return getMeasuredSize(element, nullSize).getMarginWidth();
+ /**
+ * Gets the combined top & bottom margin of the given element, provided that
+ * they have been measured. These elements are guaranteed to be measured:
+ * <ul>
+ * <li>ManagedLayotus and their child Connectors
+ * <li>Elements for which there is at least one ElementResizeListener
+ * <li>Elements for which at least one ManagedLayout has registered a
+ * dependency
+ * </ul>
+ *
+ * A negative number is returned if the element has not been measured. If 0
+ * is returned, it might indicate that the element is not attached to the
+ * DOM.
+ *
+ * @param element
+ * the element to get the measured margin for
+ * @return the measured top+bottom margin of the element in pixels.
+ */
+ public int getMarginHeight(Element element) {
+ return getMarginTop(element) + getMarginBottom(element);
}
- public int getMarginHeight(Element element) {
- return getMeasuredSize(element, nullSize).getMarginHeight();
+ /**
+ * Gets the combined left & right margin of the given element, provided that
+ * they have been measured. These elements are guaranteed to be measured:
+ * <ul>
+ * <li>ManagedLayotus and their child Connectors
+ * <li>Elements for which there is at least one ElementResizeListener
+ * <li>Elements for which at least one ManagedLayout has registered a
+ * dependency
+ * </ul>
+ *
+ * A negative number is returned if the element has not been measured. If 0
+ * is returned, it might indicate that the element is not attached to the
+ * DOM.
+ *
+ * @param element
+ * the element to get the measured margin for
+ * @return the measured left+right margin of the element in pixels.
+ */
+ public int getMarginWidth(Element element) {
+ return getMarginLeft(element) + getMarginRight(element);
}
/**
@@ -1192,12 +1215,12 @@ public class LayoutManager {
listeners.remove(listener);
if (listeners.isEmpty()) {
elementResizeListeners.remove(element);
- stopMeasuringIfUnnecessary(element);
+ stopMeasuringIfUnecessary(element);
}
}
}
- private void stopMeasuringIfUnnecessary(Element element) {
+ private void stopMeasuringIfUnecessary(Element element) {
if (!needsMeasure(element)) {
measuredNonConnectorElements.remove(element);
setMeasuredSize(element, null);
@@ -1227,4 +1250,10 @@ public class LayoutManager {
everythingNeedsMeasure = true;
}
+ /**
+ * Clean measured sizes which are no longer needed. Only for IE8.
+ */
+ protected void cleanMeasuredSizes() {
+ }
+
}
diff --git a/src/com/vaadin/terminal/gwt/client/LayoutManagerIE8.java b/src/com/vaadin/terminal/gwt/client/LayoutManagerIE8.java
index fc55007969..ea130779ea 100644
--- a/src/com/vaadin/terminal/gwt/client/LayoutManagerIE8.java
+++ b/src/com/vaadin/terminal/gwt/client/LayoutManagerIE8.java
@@ -4,43 +4,47 @@
package com.vaadin.terminal.gwt.client;
import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.Element;
+import com.google.gwt.user.client.ui.RootPanel;
public class LayoutManagerIE8 extends LayoutManager {
- protected HashMap<Element, MeasuredSize> sizes = new HashMap<Element, MeasuredSize>();
+ private Map<Element, MeasuredSize> measuredSizes = new HashMap<Element, MeasuredSize>();
@Override
protected void setMeasuredSize(Element element, MeasuredSize measuredSize) {
if (measuredSize != null) {
- sizes.put(element, measuredSize);
+ measuredSizes.put(element, measuredSize);
} else {
- sizes.remove(element);
+ measuredSizes.remove(element);
}
}
- // @Override
- // protected native void setMeasuredSize(Element element,
- // MeasuredSize measuredSize)
- // IE8 cannot do delete element.vMeasuredSize, at least in the case when
- // element is not attached to the document (e.g. when a caption is removed)
- /*-{
- if (measuredSize) {
- element.vMeasuredSize = measuredSize;
- } else {
- element.vMeasuredSize = undefined;
- }
- // }-*/;
-
@Override
protected MeasuredSize getMeasuredSize(Element element,
MeasuredSize defaultSize) {
- MeasuredSize size = sizes.get(element);
- if (size != null) {
- return size;
+ MeasuredSize measured = measuredSizes.get(element);
+ if (measured != null) {
+ return measured;
+ } else {
+ return defaultSize;
}
- return defaultSize;
}
+ @Override
+ protected void cleanMeasuredSizes() {
+ Document document = RootPanel.get().getElement().getOwnerDocument();
+
+ Iterator<Element> i = measuredSizes.keySet().iterator();
+ while (i.hasNext()) {
+ Element e = i.next();
+ if (e.getOwnerDocument() != document) {
+ i.remove();
+ }
+ }
+ }
}
diff --git a/src/com/vaadin/terminal/gwt/client/ServerConnector.java b/src/com/vaadin/terminal/gwt/client/ServerConnector.java
index 02b894e831..fcf5100c8e 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;
@@ -94,4 +95,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.
+ * <p>
+ * 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<ServerConnector> children);
+
+ public List<ServerConnector> getChildren();
}
diff --git a/src/com/vaadin/terminal/gwt/client/Util.java b/src/com/vaadin/terminal/gwt/client/Util.java
index c392a0ba9c..d3cb54160d 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<MethodInvocation> 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);
@@ -912,6 +911,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
+ * event 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
* event itself.
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<ComponentConnector> 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<ComponentConnector> connectorsInHierarchy = new HashSet<ComponentConnector>();
+ Set<ServerConnector> connectorsInHierarchy = new HashSet<ServerConnector>();
SimpleTree rootHierachy = dumpConnectorHierarchy(root, "",
connectorsInHierarchy);
if (panel.isAttached()) {
@@ -874,7 +878,7 @@ public class VDebugConsole extends VOverlay implements Console {
Collection<? extends ServerConnector> registeredConnectors = connectorMap
.getConnectors();
log("Sub windows:");
- Set<ComponentConnector> subWindowHierarchyConnectors = new HashSet<ComponentConnector>();
+ Set<ServerConnector> subWindowHierarchyConnectors = new HashSet<ServerConnector>();
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<ComponentConnector> connectors) {
+ private SimpleTree dumpConnectorHierarchy(final ServerConnector connector,
+ String indent, Set<ServerConnector> 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<? extends ComponentConnector> widgetClassByDecodedTag = conf
- .getWidgetClassByEncodedTag(tag);
+ Class<? extends ServerConnector> 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<Class, WidgetInstantiator> instmap = new HashMap<Class, WidgetInstantiator>();
+ protected static HashMap<Class<? extends ServerConnector>, WidgetInstantiator> instmap = new HashMap<Class<? extends ServerConnector>, 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<? extends ComponentConnector> classType) {
+ public ServerConnector instantiate(
+ Class<? extends ServerConnector> 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<? extends ComponentConnector> getConnectorClassForServerSideClassName(
+ public abstract Class<? extends ServerConnector> getConnectorClassForServerSideClassName(
String fullyqualifiedName);
/**
@@ -49,7 +49,7 @@ abstract class WidgetMap {
* @return component connector class to load after the initial widgetset
* loading
*/
- public abstract Class<? extends ComponentConnector>[] getDeferredLoadedWidgets();
+ public abstract Class<? extends ServerConnector>[] 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<? extends ComponentConnector> classType);
+ Class<? extends ServerConnector> classType);
}
diff --git a/src/com/vaadin/terminal/gwt/client/WidgetSet.java b/src/com/vaadin/terminal/gwt/client/WidgetSet.java
index e47837296d..3d7e838c62 100644
--- a/src/com/vaadin/terminal/gwt/client/WidgetSet.java
+++ b/src/com/vaadin/terminal/gwt/client/WidgetSet.java
@@ -5,7 +5,7 @@
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.communication.HasJavaScriptConnectorHelper;
import com.vaadin.terminal.gwt.client.ui.UnknownComponentConnector;
public class WidgetSet {
@@ -18,29 +18,29 @@ 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 implement {@link ServerConnector}.
*
* @param tag
- * component type tag for the component to create
- * @param client
- * the application connection that whishes to instantiate widget
+ * connector type tag for the connector to create
+ * @param conf
+ * the application configuration to use when creating the
+ * connector
*
- * @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,
+ 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<? extends ComponentConnector> classType = resolveInheritedWidgetType(
+ Class<? extends ServerConnector> classType = resolveInheritedConnectorType(
conf, tag);
if (classType == null || classType == UnknownComponentConnector.class) {
@@ -53,27 +53,32 @@ public class WidgetSet {
/*
* let the auto generated code instantiate this type
*/
- return widgetMap.instantiate(classType);
+ ServerConnector connector = widgetMap.instantiate(classType);
+ if (connector instanceof HasJavaScriptConnectorHelper) {
+ ((HasJavaScriptConnectorHelper) connector)
+ .getJavascriptConnectorHelper().setTag(tag);
+ }
+ return connector;
}
}
- private Class<? extends ComponentConnector> resolveInheritedWidgetType(
+ private Class<? extends ServerConnector> resolveInheritedConnectorType(
ApplicationConfiguration conf, int tag) {
- Class<? extends ComponentConnector> classType = null;
+ Class<? extends ServerConnector> 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<? extends ComponentConnector> resolveWidgetType(int tag,
+ protected Class<? extends ServerConnector> resolveConnectorType(int tag,
ApplicationConfiguration conf) {
- Class<? extends ComponentConnector> widgetClass = conf
- .getWidgetClassByEncodedTag(tag);
+ Class<? extends ServerConnector> connectorClass = conf
+ .getConnectorClassByEncodedTag(tag);
- return widgetClass;
+ return connectorClass;
}
/**
@@ -85,9 +90,9 @@ public class WidgetSet {
* @param applicationConfiguration
* @return
*/
- public Class<? extends ComponentConnector> getConnectorClassByTag(int tag,
+ public Class<? extends ServerConnector> getConnectorClassByTag(int tag,
ApplicationConfiguration conf) {
- Class<? extends ComponentConnector> connectorClass = null;
+ Class<? extends ServerConnector> connectorClass = null;
Integer t = tag;
do {
String serverSideClassName = conf.getServerSideClassNameForTag(t);
@@ -99,11 +104,11 @@ public class WidgetSet {
return connectorClass;
}
- public Class<? extends ComponentConnector>[] getDeferredLoadedWidgets() {
- return widgetMap.getDeferredLoadedWidgets();
+ public Class<? extends ServerConnector>[] getDeferredLoadedConnectors() {
+ return widgetMap.getDeferredLoadedConnectors();
}
- public void loadImplementation(Class<? extends ComponentConnector> nextType) {
+ public void loadImplementation(Class<? extends ServerConnector> nextType) {
widgetMap.ensureInstantiator(nextType);
}
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<T> extends JSONSerializer<T> {
+ /**
+ * 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/GeneratedRpcMethodProvider.java b/src/com/vaadin/terminal/gwt/client/communication/GeneratedRpcMethodProvider.java
new file mode 100644
index 0000000000..c92466084c
--- /dev/null
+++ b/src/com/vaadin/terminal/gwt/client/communication/GeneratedRpcMethodProvider.java
@@ -0,0 +1,20 @@
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+package com.vaadin.terminal.gwt.client.communication;
+
+import java.util.Collection;
+
+/**
+ * Provides runtime data about client side RPC calls received from the server to
+ * the client-side code.
+ *
+ * A GWT generator is used to create an implementation of this class at
+ * run-time.
+ *
+ * @since 7.0
+ */
+public interface GeneratedRpcMethodProvider {
+
+ public Collection<RpcMethod> getGeneratedRpcMethods();
+}
diff --git a/src/com/vaadin/terminal/gwt/client/communication/HasJavaScriptConnectorHelper.java b/src/com/vaadin/terminal/gwt/client/communication/HasJavaScriptConnectorHelper.java
new file mode 100644
index 0000000000..a5191a5fed
--- /dev/null
+++ b/src/com/vaadin/terminal/gwt/client/communication/HasJavaScriptConnectorHelper.java
@@ -0,0 +1,11 @@
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+
+package com.vaadin.terminal.gwt.client.communication;
+
+import com.vaadin.terminal.gwt.client.JavaScriptConnectorHelper;
+
+public interface HasJavaScriptConnectorHelper {
+ public JavaScriptConnectorHelper getJavascriptConnectorHelper();
+}
diff --git a/src/com/vaadin/terminal/gwt/client/communication/JSONSerializer.java b/src/com/vaadin/terminal/gwt/client/communication/JSONSerializer.java
index f7b3df6b05..9820b6a895 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<T> {
*
* @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);
/**
@@ -52,12 +47,8 @@ public interface JSONSerializer<T> {
*
* @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/JsonDecoder.java b/src/com/vaadin/terminal/gwt/client/communication/JsonDecoder.java
index 9ed20b6c79..23a2c30cd0 100644
--- a/src/com/vaadin/terminal/gwt/client/communication/JsonDecoder.java
+++ b/src/com/vaadin/terminal/gwt/client/communication/JsonDecoder.java
@@ -5,21 +5,20 @@
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;
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;
+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
@@ -38,128 +37,177 @@ 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(JSONArray jsonArray, Object target,
- ConnectorMap idMapper, ApplicationConnection connection) {
- String type = ((JSONString) jsonArray.get(0)).stringValue();
- return decodeValue(type, jsonArray.get(1), target, idMapper, connection);
- }
+ public static Object decodeValue(Type type, JSONValue jsonValue,
+ Object target, ApplicationConnection connection) {
- private static Object decodeValue(String variableType, JSONValue value,
- Object target, ConnectorMap idMapper,
- 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);
- } else if (JsonEncoder.VTYPE_MAP.equals(variableType)) {
- val = decodeMap((JSONObject) value, idMapper, connection);
- } else if (JsonEncoder.VTYPE_LIST.equals(variableType)) {
- val = decodeList((JSONArray) value, idMapper, connection);
- } else if (JsonEncoder.VTYPE_SET.equals(variableType)) {
- val = decodeSet((JSONArray) value, idMapper, 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)) {
+ // Null is null, regardless of type
+ if (jsonValue.isNull() != null) {
+ return null;
+ }
+
+ String baseTypeName = type.getBaseTypeName();
+ if (Map.class.getName().equals(baseTypeName)
+ || HashMap.class.getName().equals(baseTypeName)) {
+ return decodeMap(type, 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
+ return Long.valueOf(String.valueOf(jsonValue));
+ } else if (Float.class.getName().equals(baseTypeName)) {
// TODO handle properly
- val = Integer.valueOf(String.valueOf(value));
- } else if (JsonEncoder.VTYPE_LONG.equals(variableType)) {
+ return Float.valueOf(String.valueOf(jsonValue));
+ } else if (Double.class.getName().equals(baseTypeName)) {
// TODO handle properly
- val = Long.valueOf(String.valueOf(value));
- } else if (JsonEncoder.VTYPE_FLOAT.equals(variableType)) {
+ return Double.valueOf(String.valueOf(jsonValue));
+ } else if (Boolean.class.getName().equals(baseTypeName)) {
// TODO handle properly
- val = Float.valueOf(String.valueOf(value));
- } else if (JsonEncoder.VTYPE_DOUBLE.equals(variableType)) {
+ return Boolean.valueOf(String.valueOf(jsonValue));
+ } else if (Byte.class.getName().equals(baseTypeName)) {
// TODO handle properly
- val = Double.valueOf(String.valueOf(value));
- } else if (JsonEncoder.VTYPE_BOOLEAN.equals(variableType)) {
+ return Byte.valueOf(String.valueOf(jsonValue));
+ } else if (Character.class.getName().equals(baseTypeName)) {
// TODO handle properly
- val = Boolean.valueOf(String.valueOf(value));
- } else if (JsonEncoder.VTYPE_CONNECTOR.equals(variableType)) {
- val = idMapper.getConnector(((JSONString) value).stringValue());
+ return Character.valueOf(((JSONString) jsonValue).stringValue()
+ .charAt(0));
+ } else if (Connector.class.getName().equals(baseTypeName)) {
+ return ConnectorMap.get(connection).getConnector(
+ ((JSONString) jsonValue).stringValue());
} else {
- return decodeObject(variableType, value, target, idMapper,
- connection);
+ return decodeObject(type, jsonValue, target, connection);
}
-
- return val;
}
- private static Object decodeObject(String variableType,
- JSONValue encodedValue, Object target, ConnectorMap idMapper,
- ApplicationConnection connection) {
- // object, class name as type
+ private static Object decodeObject(Type type, JSONValue jsonValue,
+ Object target, ApplicationConnection connection) {
JSONSerializer<Object> 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;
+ // Currently getSerializer throws exception if not found
+
+ if (target != null && serializer instanceof DiffJSONSerializer<?>) {
+ DiffJSONSerializer<Object> diffSerializer = (DiffJSONSerializer<Object>) serializer;
+ diffSerializer.update(target, type, jsonValue, connection);
+ return target;
+ } else {
+ Object object = serializer.deserialize(type, jsonValue, connection);
+ return object;
+ }
}
- private static Map<Object, Object> decodeMap(JSONObject jsonMap,
- ConnectorMap idMapper, ApplicationConnection connection) {
- HashMap<Object, Object> map = new HashMap<Object, Object>();
- Iterator<String> 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,
+ private static Map<Object, Object> decodeMap(Type type, JSONValue jsonMap,
+ ApplicationConnection 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<Object, Object>();
+ }
+ }
+
+ 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<Object, Object> decodeObjectMap(Type keyType,
+ Type valueType, JSONValue jsonValue,
+ ApplicationConnection connection) {
+ Map<Object, Object> map = new HashMap<Object, Object>();
+
+ 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(encodedValue, null, idMapper,
+ Object decodedValue = decodeValue(valueType, values.get(i), null,
connection);
+
map.put(decodedKey, decodedValue);
}
+
return map;
}
- private static String[] decodeStringArray(JSONArray jsonArray) {
- int size = jsonArray.size();
- List<String> tokens = new ArrayList<String>(size);
- for (int i = 0; i < size; ++i) {
- tokens.add(String.valueOf(jsonArray.get(i)));
+ private static Map<Object, Object> decodeConnectorMap(Type valueType,
+ JSONValue jsonValue, ApplicationConnection connection) {
+ Map<Object, Object> map = new HashMap<Object, Object>();
+
+ 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 tokens.toArray(new String[tokens.size()]);
+
+ return map;
}
- private static Object[] decodeArray(JSONArray jsonArray,
- ConnectorMap idMapper, ApplicationConnection connection) {
- List<Object> list = decodeList(jsonArray, idMapper, connection);
- return list.toArray(new Object[list.size()]);
+ private static Map<Object, Object> decodeStringMap(Type valueType,
+ JSONValue jsonValue, ApplicationConnection connection) {
+ Map<Object, Object> map = new HashMap<Object, Object>();
+
+ JSONObject jsonMap = (JSONObject) jsonValue;
+
+ for (String key : jsonMap.keySet()) {
+ Object value = decodeValue(valueType, jsonMap.get(key), null,
+ connection);
+ map.put(key, value);
+ }
+
+ return map;
}
- private static List<Object> decodeList(JSONArray jsonArray,
- ConnectorMap idMapper, ApplicationConnection connection) {
+ private static List<Object> decodeList(Type type, JSONArray jsonArray,
+ ApplicationConnection connection) {
List<Object> tokens = new ArrayList<Object>();
- 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(type.getParameterTypes()[0], jsonArray,
+ connection, tokens);
return tokens;
}
- private static Set<Object> decodeSet(JSONArray jsonArray,
- ConnectorMap idMapper, ApplicationConnection connection) {
+ private static Set<Object> decodeSet(Type type, JSONArray jsonArray,
+ ApplicationConnection connection) {
Set<Object> tokens = new HashSet<Object>();
+ decodeIntoCollection(type.getParameterTypes()[0], jsonArray,
+ connection, tokens);
+ return tokens;
+ }
+
+ private static void decodeIntoCollection(Type childType,
+ JSONArray jsonArray, ApplicationConnection connection,
+ Collection<Object> 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));
+ JSONValue entryValue = jsonArray.get(i);
+ tokens.add(decodeValue(childType, entryValue, null, connection));
}
- return tokens;
}
}
diff --git a/src/com/vaadin/terminal/gwt/client/communication/JsonEncoder.java b/src/com/vaadin/terminal/gwt/client/communication/JsonEncoder.java
index f09536a9f7..925f0b6272 100644
--- a/src/com/vaadin/terminal/gwt/client/communication/JsonEncoder.java
+++ b/src/com/vaadin/terminal/gwt/client/communication/JsonEncoder.java
@@ -7,17 +7,18 @@ 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;
import com.google.gwt.json.client.JSONBoolean;
import com.google.gwt.json.client.JSONNull;
+import com.google.gwt.json.client.JSONNumber;
import com.google.gwt.json.client.JSONObject;
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
@@ -52,57 +53,49 @@ 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 combineTypeAndValue(VTYPE_NULL, JSONNull.getInstance());
+ return JSONNull.getInstance();
+ } else if (value instanceof JSONValue) {
+ return (JSONValue) value;
} 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 Byte) {
+ return new JSONNumber((Byte) value);
+ } else if (value instanceof Character) {
+ return new JSONString(String.valueOf(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(value.toString(), restrictToInternalTypes,
- connectorMap, connection);
- } else {
- Enum e = (Enum) value;
- return encodeEnum(e, connectorMap, connection);
- }
+ return encodeEnum((Enum<?>) value, 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 combineTypeAndValue(VTYPE_CONNECTOR, new JSONString(
- connector.getConnectorId()));
+ 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, connection);
} 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
@@ -111,61 +104,135 @@ public class JsonEncoder {
.getSerializer(transportType);
// TODO handle case with no serializer found
- return combineTypeAndValue(transportType,
- serializer.serialize(value, connectorMap, connection));
+ return serializer.serialize(value, connection);
}
}
}
+ private static JSONValue encodeVariableChange(UidlValue uidlValue,
+ ApplicationConnection connection) {
+ Object value = uidlValue.getValue();
+
+ JSONArray jsonArray = new JSONArray();
+ jsonArray.set(0, new JSONString(getTransportType(value)));
+ jsonArray.set(1, encode(value, true, connection));
+
+ return jsonArray;
+ }
+
private static JSONValue encodeMap(Map<Object, Object> map,
- boolean restrictToInternalTypes, ConnectorMap connectorMap,
+ 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
+ * 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, connection);
+ } else if (restrictToInternalTypes) {
+ throw new IllegalStateException(
+ "Only string keys supported for legacy maps");
+ } else if (firstKey instanceof Connector) {
+ return encodeConenctorMap(map, connection);
+ } else {
+ return encodeObjectMap(map, connection);
+ }
+ }
+
+ private static JSONValue encodeObjectMap(Map<Object, Object> map,
+ 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, connection));
+ values.set(values.size(),
+ encode(entry.getValue(), false, connection));
+ }
+
+ JSONArray keysAndValues = new JSONArray();
+ keysAndValues.set(0, keys);
+ keysAndValues.set(1, values);
+
+ return keysAndValues;
+ }
+
+ private static JSONValue encodeConenctorMap(Map<Object, Object> map,
ApplicationConnection connection) {
JSONObject jsonMap = new JSONObject();
- for (Object mapKey : map.keySet()) {
- Object mapValue = map.get(mapKey);
- JSONValue encodedKey = encode(mapKey, restrictToInternalTypes,
- connectorMap, connection);
- JSONValue encodedValue = encode(mapValue, restrictToInternalTypes,
- connectorMap, connection);
- jsonMap.put(encodedKey.toString(), encodedValue);
+
+ for (Entry<?, ?> entry : map.entrySet()) {
+ Connector connector = (Connector) entry.getKey();
+
+ // restrictToInternalTypes always false if we end up here
+ JSONValue encodedValue = encode(entry.getValue(), false, connection);
+
+ jsonMap.put(connector.getConnectorId(), encodedValue);
+ }
+
+ return jsonMap;
+ }
+
+ private static JSONValue encodeStringMap(Map<Object, Object> map,
+ boolean restrictToInternalTypes, ApplicationConnection connection) {
+ JSONObject jsonMap = new JSONObject();
+
+ for (Entry<?, ?> entry : map.entrySet()) {
+ String key = (String) entry.getKey();
+ Object value = entry.getValue();
+
+ if (restrictToInternalTypes) {
+ value = new UidlValue(value);
+ }
+
+ JSONValue encodedValue = encode(value, restrictToInternalTypes,
+ connection);
+
+ jsonMap.put(key, encodedValue);
}
- return combineTypeAndValue(VTYPE_MAP, jsonMap);
+
+ return jsonMap;
}
- private static JSONValue encodeEnum(Enum e, ConnectorMap connectorMap,
+ private static JSONValue encodeEnum(Enum<?> e,
ApplicationConnection connection) {
- return combineTypeAndValue(e.getClass().getName(),
- new JSONString(e.toString()));
+ 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?
- jsonArray.set(
- i,
- encode(array[i], restrictToInternalTypes, connectorMap,
- connection));
+ Object value = array[i];
+ if (restrictToInternalTypes) {
+ value = new UidlValue(value);
+ }
+ jsonArray
+ .set(i, encode(value, restrictToInternalTypes, connection));
}
- return combineTypeAndValue(VTYPE_ARRAY, jsonArray);
+ 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) {
- 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());
@@ -173,13 +240,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.
@@ -216,6 +276,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;
}
diff --git a/src/com/vaadin/terminal/gwt/client/communication/RpcManager.java b/src/com/vaadin/terminal/gwt/client/communication/RpcManager.java
index 302e6eaa55..07d6292ce2 100644
--- a/src/com/vaadin/terminal/gwt/client/communication/RpcManager.java
+++ b/src/com/vaadin/terminal/gwt/client/communication/RpcManager.java
@@ -4,9 +4,17 @@
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.google.gwt.json.client.JSONArray;
+import com.google.gwt.json.client.JSONString;
+import com.vaadin.terminal.gwt.client.ApplicationConnection;
import com.vaadin.terminal.gwt.client.ConnectorMap;
+import com.vaadin.terminal.gwt.client.ServerConnector;
+import com.vaadin.terminal.gwt.client.VConsole;
/**
* Client side RPC manager that can invoke methods based on RPC calls received
@@ -17,16 +25,98 @@ import com.vaadin.terminal.gwt.client.ConnectorMap;
*
* @since 7.0
*/
-public interface RpcManager extends Serializable {
+public class RpcManager {
+
+ private final Map<String, RpcMethod> methodMap = new HashMap<String, RpcMethod>();
+
+ public RpcManager() {
+ GeneratedRpcMethodProvider provider = GWT
+ .create(GeneratedRpcMethodProvider.class);
+ Collection<RpcMethod> methods = provider.getGeneratedRpcMethods();
+ for (RpcMethod rpcMethod : methods) {
+ methodMap.put(
+ rpcMethod.getInterfaceName() + "."
+ + rpcMethod.getMethodName(), rpcMethod);
+ }
+ }
+
/**
* Perform server to client RPC invocation.
*
* @param invocation
* method to invoke
- * @param connectorMap
- * mapper used to find Connector for the method call and any
- * connectors referenced in parameters
*/
public void applyInvocation(MethodInvocation invocation,
- ConnectorMap connectorMap);
+ ServerConnector connector) {
+ String signature = getSignature(invocation);
+
+ RpcMethod rpcMethod = getRpcMethod(signature);
+ Collection<ClientRpc> 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();
+ }
+
+ public void parseAndApplyInvocation(JSONArray rpcCall,
+ ApplicationConnection connection) {
+ ConnectorMap connectorMap = ConnectorMap.get(connection);
+
+ String connectorId = ((JSONString) rpcCall.get(0)).stringValue();
+ String interfaceName = ((JSONString) rpcCall.get(1)).stringValue();
+ String methodName = ((JSONString) rpcCall.get(2)).stringValue();
+ JSONArray parametersJson = (JSONArray) rpcCall.get(3);
+
+ ServerConnector connector = connectorMap.getConnector(connectorId);
+
+ MethodInvocation invocation = new MethodInvocation(connectorId,
+ interfaceName, methodName);
+ if (connector instanceof HasJavaScriptConnectorHelper) {
+ ((HasJavaScriptConnectorHelper) connector)
+ .getJavascriptConnectorHelper().invokeJsRpc(invocation,
+ parametersJson);
+ } else {
+ if (connector == null) {
+ throw new IllegalStateException("Target connector ("
+ + connector + ") not found for RCC to "
+ + getSignature(invocation));
+ }
+
+ parseMethodParameters(invocation, parametersJson, connection);
+ VConsole.log("Server to client RPC call: " + invocation);
+ applyInvocation(invocation, connector);
+ }
+ }
+
+ private void parseMethodParameters(MethodInvocation methodInvocation,
+ JSONArray parametersJson, ApplicationConnection connection) {
+ Type[] parameterTypes = getParameterTypes(methodInvocation);
+
+ Object[] parameters = new Object[parametersJson.size()];
+ for (int j = 0; j < parametersJson.size(); ++j) {
+ parameters[j] = JsonDecoder.decodeValue(parameterTypes[j],
+ parametersJson.get(j), null, connection);
+ }
+
+ methodInvocation.setParameters(parameters);
+ }
+
}
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/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/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/client/communication/URLReference_Serializer.java b/src/com/vaadin/terminal/gwt/client/communication/URLReference_Serializer.java
index 2ee7df7f6d..bab0f385ed 100644
--- a/src/com/vaadin/terminal/gwt/client/communication/URLReference_Serializer.java
+++ b/src/com/vaadin/terminal/gwt/client/communication/URLReference_Serializer.java
@@ -4,32 +4,34 @@
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;
-import com.vaadin.terminal.gwt.client.ConnectorMap;
public class URLReference_Serializer implements JSONSerializer<URLReference> {
- public URLReference deserialize(JSONValue jsonValue, URLReference target,
- ConnectorMap idMapper, ApplicationConnection connection) {
+ // 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")) {
- JSONArray jsonURL = (JSONArray) json.get("URL");
- String URL = (String) JsonDecoder.decodeValue(jsonURL, null,
- idMapper, connection);
+ 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);
reference.setURL(connection.translateVaadinUri(URL));
}
return reference;
}
- public JSONValue serialize(URLReference value, ConnectorMap idMapper,
+ public JSONValue serialize(URLReference value,
ApplicationConnection connection) {
JSONObject json = new JSONObject();
- json.put("URL",
- JsonEncoder.encode(value.getURL(), true, idMapper, connection));
+ json.put(URL_FIELD,
+ JsonEncoder.encode(value.getURL(), true, connection));
return json;
}
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/client/extensions/AbstractExtensionConnector.java b/src/com/vaadin/terminal/gwt/client/extensions/AbstractExtensionConnector.java
new file mode 100644
index 0000000000..bcefcf05cb
--- /dev/null
+++ b/src/com/vaadin/terminal/gwt/client/extensions/AbstractExtensionConnector.java
@@ -0,0 +1,27 @@
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+
+package com.vaadin.terminal.gwt.client.extensions;
+
+import com.vaadin.terminal.gwt.client.ServerConnector;
+import com.vaadin.terminal.gwt.client.ui.AbstractConnector;
+
+public abstract class AbstractExtensionConnector extends AbstractConnector {
+ @Override
+ public void setParent(ServerConnector parent) {
+ ServerConnector oldParent = getParent();
+ if (oldParent != null && oldParent != parent) {
+ throw new IllegalStateException(
+ "An extension can not be moved from one parent to another.");
+ }
+
+ super.setParent(parent);
+
+ extend(parent);
+ }
+
+ protected void extend(ServerConnector target) {
+ // Default does nothing
+ }
+}
diff --git a/src/com/vaadin/terminal/gwt/client/extensions/javascriptmanager/ExecuteJavaScriptRpc.java b/src/com/vaadin/terminal/gwt/client/extensions/javascriptmanager/ExecuteJavaScriptRpc.java
new file mode 100644
index 0000000000..f1185586d5
--- /dev/null
+++ b/src/com/vaadin/terminal/gwt/client/extensions/javascriptmanager/ExecuteJavaScriptRpc.java
@@ -0,0 +1,11 @@
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+
+package com.vaadin.terminal.gwt.client.extensions.javascriptmanager;
+
+import com.vaadin.terminal.gwt.client.communication.ClientRpc;
+
+public interface ExecuteJavaScriptRpc extends ClientRpc {
+ public void executeJavaScript(String script);
+}
diff --git a/src/com/vaadin/terminal/gwt/client/extensions/javascriptmanager/JavaScriptManagerConnector.java b/src/com/vaadin/terminal/gwt/client/extensions/javascriptmanager/JavaScriptManagerConnector.java
new file mode 100644
index 0000000000..8656783a86
--- /dev/null
+++ b/src/com/vaadin/terminal/gwt/client/extensions/javascriptmanager/JavaScriptManagerConnector.java
@@ -0,0 +1,119 @@
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+
+package com.vaadin.terminal.gwt.client.extensions.javascriptmanager;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import com.google.gwt.core.client.JavaScriptObject;
+import com.google.gwt.core.client.JsArray;
+import com.google.gwt.json.client.JSONArray;
+import com.vaadin.terminal.gwt.client.communication.MethodInvocation;
+import com.vaadin.terminal.gwt.client.communication.StateChangeEvent;
+import com.vaadin.terminal.gwt.client.extensions.AbstractExtensionConnector;
+import com.vaadin.terminal.gwt.client.ui.Connect;
+import com.vaadin.ui.JavaScript;
+
+@Connect(JavaScript.class)
+public class JavaScriptManagerConnector extends AbstractExtensionConnector {
+ private Set<String> currentNames = new HashSet<String>();
+
+ @Override
+ protected void init() {
+ registerRpc(ExecuteJavaScriptRpc.class, new ExecuteJavaScriptRpc() {
+ public void executeJavaScript(String Script) {
+ eval(Script);
+ }
+ });
+ }
+
+ @Override
+ public void onStateChanged(StateChangeEvent stateChangeEvent) {
+ super.onStateChanged(stateChangeEvent);
+
+ Set<String> newNames = getState().getNames();
+
+ // Current names now only contains orphan callbacks
+ currentNames.removeAll(newNames);
+
+ for (String name : currentNames) {
+ removeCallback(name);
+ }
+
+ currentNames = new HashSet<String>(newNames);
+ for (String name : newNames) {
+ addCallback(name);
+ }
+ }
+
+ // TODO Ensure we don't overwrite anything (important) in $wnd
+ private native void addCallback(String name)
+ /*-{
+ var m = this;
+ var target = $wnd;
+ var parts = name.split('.');
+
+ for(var i = 0; i < parts.length - 1; i++) {
+ var part = parts[i];
+ if (target[part] === undefined) {
+ target[part] = {};
+ }
+ target = target[part];
+ }
+
+ target[parts[parts.length - 1]] = $entry(function() {
+ //Must make a copy because arguments is an array-like object (not instanceof Array), causing suboptimal JSON encoding
+ var args = Array.prototype.slice.call(arguments, 0);
+ m.@com.vaadin.terminal.gwt.client.extensions.javascriptmanager.JavaScriptManagerConnector::sendRpc(Ljava/lang/String;Lcom/google/gwt/core/client/JsArray;)(name, args);
+ });
+ }-*/;
+
+ // TODO only remove what we actually added
+ // TODO We might leave empty objects behind, but there's no good way of
+ // knowing whether they are unused
+ private native void removeCallback(String name)
+ /*-{
+ var target = $wnd;
+ var parts = name.split('.');
+
+ for(var i = 0; i < parts.length - 1; i++) {
+ var part = parts[i];
+ if (target[part] === undefined) {
+ $wnd.console.log(part,'not defined in',target);
+ // No longer attached -> nothing more to do
+ return;
+ }
+ target = target[part];
+ }
+
+ $wnd.console.log('removing',parts[parts.length - 1],'from',target);
+ delete target[parts[parts.length - 1]];
+ }-*/;
+
+ private static native void eval(String script)
+ /*-{
+ if(script) {
+ (new $wnd.Function(script)).apply($wnd);
+ }
+ }-*/;
+
+ public void sendRpc(String name, JsArray<JavaScriptObject> arguments) {
+ Object[] parameters = new Object[] { name, new JSONArray(arguments) };
+
+ /*
+ * Must invoke manually as the RPC interface can't be used in GWT
+ * because of the JSONArray parameter
+ */
+ getConnection().addMethodInvocationToQueue(
+ new MethodInvocation(getConnectorId(),
+ "com.vaadin.ui.JavaScript$JavaScriptCallbackRpc",
+ "call", parameters), true);
+ }
+
+ @Override
+ public JavaScriptManagerState getState() {
+ return (JavaScriptManagerState) super.getState();
+ }
+}
diff --git a/src/com/vaadin/terminal/gwt/client/extensions/javascriptmanager/JavaScriptManagerState.java b/src/com/vaadin/terminal/gwt/client/extensions/javascriptmanager/JavaScriptManagerState.java
new file mode 100644
index 0000000000..fc246aff04
--- /dev/null
+++ b/src/com/vaadin/terminal/gwt/client/extensions/javascriptmanager/JavaScriptManagerState.java
@@ -0,0 +1,22 @@
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+
+package com.vaadin.terminal.gwt.client.extensions.javascriptmanager;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import com.vaadin.terminal.gwt.client.communication.SharedState;
+
+public class JavaScriptManagerState extends SharedState {
+ private Set<String> names = new HashSet<String>();
+
+ public Set<String> getNames() {
+ return names;
+ }
+
+ public void setNames(Set<String> names) {
+ this.names = names;
+ }
+}
diff --git a/src/com/vaadin/terminal/gwt/client/ui/AbstractBoxLayoutConnector.java b/src/com/vaadin/terminal/gwt/client/ui/AbstractBoxLayoutConnector.java
index 854b02018f..413c605a88 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/AbstractBoxLayoutConnector.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/AbstractBoxLayoutConnector.java
@@ -7,10 +7,8 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
-import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.user.client.Element;
-import com.google.gwt.user.client.ui.Widget;
import com.vaadin.terminal.gwt.client.AbstractFieldState;
import com.vaadin.terminal.gwt.client.ComponentConnector;
import com.vaadin.terminal.gwt.client.ConnectorHierarchyChangeEvent;
@@ -58,11 +56,6 @@ public abstract class AbstractBoxLayoutConnector extends
}
@Override
- protected Widget createWidget() {
- return GWT.create(VBoxLayout.class);
- }
-
- @Override
public VBoxLayout getWidget() {
return (VBoxLayout) super.getWidget();
}
@@ -119,7 +112,6 @@ public abstract class AbstractBoxLayoutConnector extends
required = ((AbstractFieldConnector) child).isRequired();
}
boolean enabled = child.getState().isEnabled();
- // TODO Description is handled from somewhere else?
slot.setCaption(caption, iconUrl, styles, error, showError, required,
enabled);
@@ -157,7 +149,7 @@ public abstract class AbstractBoxLayoutConnector extends
int currentIndex = 0;
VBoxLayout layout = getWidget();
- for (ComponentConnector child : getChildren()) {
+ for (ComponentConnector child : getChildComponents()) {
Slot slot = layout.getSlot(child);
if (slot.getParent() != layout) {
child.addStateChangeHandler(childStateChangeHandler);
@@ -218,7 +210,7 @@ public abstract class AbstractBoxLayoutConnector extends
boolean equalExpandRatio = getWidget().vertical ? !isUndefinedHeight()
: !isUndefinedWidth();
- for (ComponentConnector child : getChildren()) {
+ for (ComponentConnector child : getChildComponents()) {
double expandRatio = getState().getChildData().get(child)
.getExpandRatio();
if (expandRatio > 0) {
@@ -227,7 +219,7 @@ public abstract class AbstractBoxLayoutConnector extends
}
}
- for (ComponentConnector child : getChildren()) {
+ for (ComponentConnector child : getChildComponents()) {
Slot slot = getWidget().getSlot(child);
AlignmentInfo alignment = new AlignmentInfo(getState()
@@ -313,7 +305,7 @@ public abstract class AbstractBoxLayoutConnector extends
}
private void updateAllSlotListeners() {
- for (ComponentConnector child : getChildren()) {
+ for (ComponentConnector child : getChildComponents()) {
updateSlotListeners(child);
}
// if (needsFixedHeight()) {
@@ -553,7 +545,7 @@ public abstract class AbstractBoxLayoutConnector extends
// dontListen(getWidget().getElement(), layoutResizeListener);
- for (ComponentConnector child : getChildren()) {
+ for (ComponentConnector child : getChildComponents()) {
Slot slot = getWidget().getSlot(child);
if (slot.hasCaption()) {
dontListen(slot.getCaptionElement(), slotCaptionResizeListener);
diff --git a/src/com/vaadin/terminal/gwt/client/ui/AbstractClickEventHandler.java b/src/com/vaadin/terminal/gwt/client/ui/AbstractClickEventHandler.java
index 31204aa0c6..e0ca798682 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/AbstractClickEventHandler.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/AbstractClickEventHandler.java
@@ -3,29 +3,76 @@
*/
package com.vaadin.terminal.gwt.client.ui;
+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.vaadin.terminal.gwt.client.ComponentConnector;
+import com.vaadin.terminal.gwt.client.Util;
-public abstract class AbstractClickEventHandler implements DoubleClickHandler,
- ContextMenuHandler, MouseUpHandler {
+public abstract class AbstractClickEventHandler implements MouseDownHandler,
+ MouseUpHandler, DoubleClickHandler, ContextMenuHandler {
- private HandlerRegistration doubleClickHandlerRegistration;
+ private HandlerRegistration mouseDownHandlerRegistration;
private HandlerRegistration mouseUpHandlerRegistration;
+ private HandlerRegistration doubleClickHandlerRegistration;
private HandlerRegistration contextMenuHandlerRegistration;
protected ComponentConnector connector;
private String clickEventIdentifier;
+ /**
+ * 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 AbstractClickEventHandler(ComponentConnector connector,
String clickEventIdentifier) {
this.connector = connector;
@@ -36,25 +83,28 @@ public abstract class AbstractClickEventHandler implements DoubleClickHandler,
// Handle registering/unregistering of click handler depending on if
// server side listeners have been added or removed.
if (hasEventListener()) {
- if (mouseUpHandlerRegistration == null) {
+ if (mouseDownHandlerRegistration == null) {
+ mouseDownHandlerRegistration = registerHandler(this,
+ MouseDownEvent.getType());
mouseUpHandlerRegistration = registerHandler(this,
MouseUpEvent.getType());
- contextMenuHandlerRegistration = registerHandler(this,
- ContextMenuEvent.getType());
doubleClickHandlerRegistration = registerHandler(this,
DoubleClickEvent.getType());
+ contextMenuHandlerRegistration = registerHandler(this,
+ ContextMenuEvent.getType());
}
} else {
- if (mouseUpHandlerRegistration != null) {
+ if (mouseDownHandlerRegistration != null) {
// Remove existing handlers
- doubleClickHandlerRegistration.removeHandler();
+ mouseDownHandlerRegistration.removeHandler();
mouseUpHandlerRegistration.removeHandler();
+ doubleClickHandlerRegistration.removeHandler();
contextMenuHandlerRegistration.removeHandler();
- contextMenuHandlerRegistration = null;
+ mouseDownHandlerRegistration = null;
mouseUpHandlerRegistration = null;
doubleClickHandlerRegistration = null;
-
+ contextMenuHandlerRegistration = null;
}
}
@@ -93,6 +143,7 @@ public abstract class AbstractClickEventHandler implements DoubleClickHandler,
* Event handler for context menu. Prevents the browser context menu from
* popping up if there is a listener for right clicks.
*/
+
public void onContextMenu(ContextMenuEvent event) {
if (hasEventListener() && shouldFireEvent(event)) {
// Prevent showing the browser's context menu when there is a right
@@ -101,18 +152,34 @@ public abstract class AbstractClickEventHandler implements DoubleClickHandler,
}
}
- /**
- * Event handler for mouse up. This is used to detect all single click
- * events.
- */
+ 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() && shouldFireEvent(event)) {
+ /*
+ * 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
+ && shouldFireEvent(event)) {
// "Click" with left, right or middle button
fireClick(event.getNativeEvent());
}
+ mouseUpPreviewMatched = false;
+ lastMouseDownTarget = null;
}
/**
@@ -140,6 +207,7 @@ public abstract class AbstractClickEventHandler implements DoubleClickHandler,
* that browsers typically fail to prevent the second click event so a
* double click will result in two click events and one double click event.
*/
+
public void onDoubleClick(DoubleClickEvent event) {
if (hasEventListener() && shouldFireEvent(event)) {
fireClick(event.getNativeEvent());
diff --git a/src/com/vaadin/terminal/gwt/client/ui/AbstractComponentConnector.java b/src/com/vaadin/terminal/gwt/client/ui/AbstractComponentConnector.java
index 1caec0428e..a621c488be 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/AbstractComponentConnector.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/AbstractComponentConnector.java
@@ -14,8 +14,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;
@@ -26,8 +28,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 = "";
@@ -77,8 +77,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) {
@@ -90,7 +88,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) {
@@ -98,7 +97,7 @@ public abstract class AbstractComponentConnector extends AbstractConnector
.getTabIndex());
}
- setWidgetEnabled(isEnabled());
+ super.onStateChanged(stateChangeEvent);
// Style names
// String styleName = getStyleNames(getWidget().getStylePrimaryName());
@@ -117,10 +116,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");
@@ -137,7 +136,22 @@ public abstract class AbstractComponentConnector extends AbstractConnector
public void setWidgetEnabled(boolean widgetEnabled) {
if (getWidget() instanceof HasEnabled) {
+ // set widget specific enabled state
((HasEnabled) getWidget()).setEnabled(widgetEnabled);
+ // add or remove v-disabled style name from the widget
+ getWidget().setStyleName(ApplicationConnection.DISABLED_CLASSNAME,
+ !widgetEnabled);
+ // make sure the caption has or has not v-disabled style
+ if (delegateCaptionHandling()) {
+ 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");
+ }
+ }
}
}
@@ -148,7 +162,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);
@@ -156,7 +170,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);
@@ -195,23 +209,6 @@ public abstract class AbstractComponentConnector extends AbstractConnector
/*
* (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)
- *
* @see
* com.vaadin.terminal.gwt.client.ComponentConnector#delegateCaptionHandling
* ()
@@ -337,26 +334,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.
@@ -372,6 +349,13 @@ public abstract class AbstractComponentConnector extends AbstractConnector
}
@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,19 +18,11 @@ public abstract class AbstractComponentContainerConnector extends
AbstractComponentConnector implements ComponentContainerConnector,
ConnectorHierarchyChangeHandler {
- List<ComponentConnector> children;
+ List<ComponentConnector> 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
*/
public AbstractComponentContainerConnector() {
@@ -43,12 +35,12 @@ public abstract class AbstractComponentContainerConnector extends
* @see
* com.vaadin.terminal.gwt.client.ComponentContainerConnector#getChildren()
*/
- public List<ComponentConnector> getChildren() {
- if (children == null) {
- return new LinkedList<ComponentConnector>();
+ public List<ComponentConnector> 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<ComponentConnector> children) {
- this.children = children;
+ public void setChildComponents(List<ComponentConnector> 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 54812a7a42..d34529ee4e 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<ServerConnector> children;
/*
* (non-Javadoc)
@@ -137,16 +148,6 @@ public abstract class AbstractConnector implements ServerConnector,
return (Collection<T>) 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);
@@ -176,6 +177,8 @@ public abstract class AbstractConnector implements ServerConnector,
+ Util.getConnectorString(stateChangeEvent.getConnector())
+ " received by " + Util.getConnectorString(this));
}
+
+ updateEnabledState(isEnabled());
}
/*
@@ -218,4 +221,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<ServerConnector> getChildren() {
+ if (children == null) {
+ return Collections.emptyList();
+ }
+ return children;
+ }
+
+ public void setChildren(List<ServerConnector> 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/ClickEventHandler.java b/src/com/vaadin/terminal/gwt/client/ui/ClickEventHandler.java
index cffdb1e68a..758f798ef2 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/ClickEventHandler.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/ClickEventHandler.java
@@ -28,6 +28,7 @@ public abstract class ClickEventHandler extends AbstractClickEventHandler {
* @param event
* The native event that caused this click event
*/
+ @Override
protected void fireClick(NativeEvent event) {
MouseEventDetails mouseDetails = MouseEventDetailsBuilder
.buildMouseEventDetails(event, getRelativeToElement());
diff --git a/src/com/vaadin/terminal/gwt/client/ui/FocusableScrollPanel.java b/src/com/vaadin/terminal/gwt/client/ui/FocusableScrollPanel.java
index 62697c4d98..ef1ea8521b 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);
}
@@ -153,7 +153,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<com.google.gwt.dom.client.Element> elements = TouchScrollDelegate
.getElements(getElement());
for (com.google.gwt.dom.client.Element el : elements) {
diff --git a/src/com/vaadin/terminal/gwt/client/ui/JavaScriptComponentConnector.java b/src/com/vaadin/terminal/gwt/client/ui/JavaScriptComponentConnector.java
new file mode 100644
index 0000000000..bb062a6677
--- /dev/null
+++ b/src/com/vaadin/terminal/gwt/client/ui/JavaScriptComponentConnector.java
@@ -0,0 +1,42 @@
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+package com.vaadin.terminal.gwt.client.ui;
+
+import com.vaadin.terminal.gwt.client.JavaScriptConnectorHelper;
+import com.vaadin.terminal.gwt.client.communication.HasJavaScriptConnectorHelper;
+import com.vaadin.ui.AbstractJavaScriptComponent;
+
+@Connect(AbstractJavaScriptComponent.class)
+public final class JavaScriptComponentConnector extends
+ AbstractComponentConnector implements HasJavaScriptConnectorHelper {
+
+ private final JavaScriptConnectorHelper helper = new JavaScriptConnectorHelper(
+ this) {
+ @Override
+ protected void showInitProblem(
+ java.util.ArrayList<String> attemptedNames) {
+ getWidget().showNoInitFound(attemptedNames);
+ }
+ };
+
+ @Override
+ public JavaScriptWidget getWidget() {
+ return (JavaScriptWidget) super.getWidget();
+ }
+
+ @Override
+ protected void init() {
+ super.init();
+ helper.init();
+ }
+
+ public JavaScriptConnectorHelper getJavascriptConnectorHelper() {
+ return helper;
+ }
+
+ @Override
+ public JavaScriptComponentState getState() {
+ return (JavaScriptComponentState) super.getState();
+ }
+}
diff --git a/src/com/vaadin/terminal/gwt/client/ui/JavaScriptComponentState.java b/src/com/vaadin/terminal/gwt/client/ui/JavaScriptComponentState.java
new file mode 100644
index 0000000000..6728f85ec9
--- /dev/null
+++ b/src/com/vaadin/terminal/gwt/client/ui/JavaScriptComponentState.java
@@ -0,0 +1,37 @@
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+
+package com.vaadin.terminal.gwt.client.ui;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import com.vaadin.terminal.gwt.client.ComponentState;
+import com.vaadin.terminal.gwt.client.JavaScriptConnectorHelper.JavaScriptConnectorState;
+
+public class JavaScriptComponentState extends ComponentState implements
+ JavaScriptConnectorState {
+
+ private Set<String> callbackNames = new HashSet<String>();
+ private Map<String, Set<String>> rpcInterfaces = new HashMap<String, Set<String>>();
+
+ public Set<String> getCallbackNames() {
+ return callbackNames;
+ }
+
+ public void setCallbackNames(Set<String> callbackNames) {
+ this.callbackNames = callbackNames;
+ }
+
+ public Map<String, Set<String>> getRpcInterfaces() {
+ return rpcInterfaces;
+ }
+
+ public void setRpcInterfaces(Map<String, Set<String>> rpcInterfaces) {
+ this.rpcInterfaces = rpcInterfaces;
+ }
+
+}
diff --git a/src/com/vaadin/terminal/gwt/client/ui/JavaScriptWidget.java b/src/com/vaadin/terminal/gwt/client/ui/JavaScriptWidget.java
new file mode 100644
index 0000000000..e6c3323893
--- /dev/null
+++ b/src/com/vaadin/terminal/gwt/client/ui/JavaScriptWidget.java
@@ -0,0 +1,25 @@
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+package com.vaadin.terminal.gwt.client.ui;
+
+import java.util.ArrayList;
+
+import com.google.gwt.dom.client.Document;
+import com.google.gwt.user.client.ui.Widget;
+
+public class JavaScriptWidget extends Widget {
+ public JavaScriptWidget() {
+ setElement(Document.get().createDivElement());
+ }
+
+ public void showNoInitFound(ArrayList<String> attemptedNames) {
+ String message = "Could not initialize JavaScriptConnector because no JavaScript init function was found. Make sure one of these functions are defined: <ul>";
+ for (String name : attemptedNames) {
+ message += "<li>" + name + "</li>";
+ }
+ message += "</ul>";
+
+ getElement().setInnerHTML(message);
+ }
+}
diff --git a/src/com/vaadin/terminal/gwt/client/ui/TouchScrollDelegate.java b/src/com/vaadin/terminal/gwt/client/ui/TouchScrollDelegate.java
index 8b2248aff6..7302f9f2ac 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;
@@ -15,10 +17,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;
@@ -68,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<Element> scrollableElements;
private Element scrolledElement;
private int origScrollTop;
private HandlerRegistration handlerRegistration;
@@ -86,8 +90,107 @@ 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) {
+ delegate = new TouchScrollDelegate();
+ widget.addDomHandler(this, TouchStartEvent.getType());
+ } else {
+ delegate = null;
+ }
+ setElements(scrollables);
+ }
+
+ public void onTouchStart(TouchStartEvent event) {
+ assert delegate != null;
+ delegate.onTouchStart(event);
+ }
+
+ public void debug(Element e) {
+ VConsole.log("Classes: " + e.getClassName() + " overflow: "
+ + e.getStyle().getProperty("overflow") + " w-o-s: "
+ + e.getStyle().getProperty("WebkitOverflowScrolling"));
+ }
+
+ /**
+ * Registers the given element as scrollable.
+ */
+ public void addElement(Element scrollable) {
+ scrollable.addClassName(SCROLLABLE_CLASSNAME);
+ if (requiresDelegate) {
+ delegate.scrollableElements.add(scrollable);
+ }
+ }
+
+ /**
+ * 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(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) {
+ addElement(e);
+ }
+ }
+ }
+
+ /**
+ * 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);
+ }
+
public TouchScrollDelegate(Element... elements) {
- scrollableElements = elements;
+ setElements(elements);
}
public void setScrollHandler(ScrollHandler scrollHandler) {
@@ -535,8 +638,8 @@ public class TouchScrollDelegate implements NativePreviewHandler {
}
}
- public void setElements(com.google.gwt.user.client.Element[] elements) {
- scrollableElements = elements;
+ public void setElements(Element[] elements) {
+ scrollableElements = new HashSet<Element>(Arrays.asList(elements));
}
/**
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/accordion/VAccordion.java b/src/com/vaadin/terminal/gwt/client/ui/accordion/VAccordion.java
index dcd520bbb3..b83d5afb00 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/accordion/VAccordion.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/accordion/VAccordion.java
@@ -20,6 +20,8 @@ import com.vaadin.terminal.gwt.client.ConnectorMap;
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;
+import com.vaadin.terminal.gwt.client.ui.TouchScrollDelegate.TouchScrollHandler;
import com.vaadin.terminal.gwt.client.ui.tabsheet.TabsheetBaseConnector;
import com.vaadin.terminal.gwt.client.ui.tabsheet.VTabsheetBase;
@@ -35,8 +37,11 @@ public class VAccordion extends VTabsheetBase {
int selectedUIDLItemIndex = -1;
+ private final TouchScrollHandler touchScrollHandler;
+
public VAccordion() {
super(CLASSNAME);
+ touchScrollHandler = TouchScrollDelegate.enableTouchScrolling(this);
}
@Override
@@ -145,7 +150,6 @@ public class VAccordion extends VTabsheetBase {
}
}
}
-
if (!alreadyOpen) {
item.open();
activeTabIndex = itemIndex;
@@ -342,11 +346,13 @@ public class VAccordion extends VTabsheetBase {
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());
+
close();
}
@@ -488,6 +494,7 @@ public class VAccordion extends VTabsheetBase {
protected void removeTab(int index) {
StackItem item = getStackItem(index);
remove(item);
+ touchScrollHandler.removeElement(item.getContainerElement());
}
@Override
diff --git a/src/com/vaadin/terminal/gwt/client/ui/button/ButtonState.java b/src/com/vaadin/terminal/gwt/client/ui/button/ButtonState.java
index fdc053b3ae..2daceea0e8 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/button/ButtonState.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/button/ButtonState.java
@@ -5,6 +5,7 @@
package com.vaadin.terminal.gwt.client.ui.button;
import com.vaadin.terminal.gwt.client.ComponentState;
+import com.vaadin.terminal.gwt.client.ui.TabIndexState;
import com.vaadin.ui.Button;
/**
@@ -14,10 +15,14 @@ import com.vaadin.ui.Button;
*
* @since 7.0
*/
-public class ButtonState extends ComponentState {
+public class ButtonState extends ComponentState implements TabIndexState {
private boolean disableOnClick = false;
private int clickShortcutKeyCode = 0;
/**
+ * The tab order number of this field.
+ */
+ private int tabIndex = 0;
+ /**
* If caption should be rendered in HTML
*/
private boolean htmlContentAllowed = false;
@@ -92,4 +97,22 @@ public class ButtonState extends ComponentState {
return htmlContentAllowed;
}
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.vaadin.terminal.gwt.client.ui.TabIndexState#getTabIndex()
+ */
+ public int getTabIndex() {
+ return tabIndex;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.vaadin.terminal.gwt.client.ui.TabIndexState#setTabIndex(int)
+ */
+ public void setTabIndex(int tabIndex) {
+ this.tabIndex = tabIndex;
+ }
+
}
diff --git a/src/com/vaadin/terminal/gwt/client/ui/button/VButton.java b/src/com/vaadin/terminal/gwt/client/ui/button/VButton.java
index e5e7dbba8b..0cd8bc54f4 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/button/VButton.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/button/VButton.java
@@ -10,6 +10,7 @@ import com.google.gwt.dom.client.NativeEvent;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.KeyCodes;
+import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.ui.Accessibility;
@@ -61,7 +62,9 @@ public class VButton extends FocusWidget implements ClickHandler {
private boolean isCapturing;
/**
- * If <code>true</code>, this widget has focus with the space bar down.
+ * If <code>true</code>, 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;
@@ -74,6 +77,14 @@ public class VButton extends FocusWidget implements ClickHandler {
protected int clickShortcut = 0;
+ private HandlerRegistration focusHandlerRegistration;
+ private HandlerRegistration blurHandlerRegistration;
+
+ /**
+ * If caption should be rendered in HTML
+ */
+ protected boolean htmlCaption = false;
+
public VButton() {
super(DOM.createDiv());
setTabIndex(0);
@@ -229,37 +240,28 @@ public class VButton extends FocusWidget implements 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;
@@ -336,12 +338,10 @@ public class VButton extends FocusWidget implements ClickHandler {
Accessibility.removeState(getElement(),
Accessibility.STATE_PRESSED);
super.setTabIndex(-1);
- addStyleName(ApplicationConnection.DISABLED_CLASSNAME);
} else {
Accessibility.setState(getElement(),
Accessibility.STATE_PRESSED, "false");
super.setTabIndex(tabIndex);
- removeStyleName(ApplicationConnection.DISABLED_CLASSNAME);
}
}
}
diff --git a/src/com/vaadin/terminal/gwt/client/ui/combobox/VFilterSelect.java b/src/com/vaadin/terminal/gwt/client/ui/combobox/VFilterSelect.java
index d29eda0d6a..8c5d521445 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/combobox/VFilterSelect.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/combobox/VFilterSelect.java
@@ -69,7 +69,8 @@ import com.vaadin.terminal.gwt.client.ui.menubar.MenuItem;
*/
@SuppressWarnings("deprecation")
public class VFilterSelect extends Composite implements Field, KeyDownHandler,
- KeyUpHandler, ClickHandler, FocusHandler, BlurHandler, Focusable {
+ KeyUpHandler, ClickHandler, FocusHandler, BlurHandler, Focusable,
+ SubPartAware {
/**
* Represents a suggestion in the suggestion popup box
@@ -100,6 +101,7 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler,
* contains an image tag with the rows icon (if an icon has been
* specified) and the caption of the item
*/
+
public String getDisplayString() {
final StringBuffer sb = new StringBuffer();
if (iconUri != null) {
@@ -122,6 +124,7 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler,
/**
* Get a string that represents this item. This is used in the text box.
*/
+
public String getReplacementString() {
return caption;
}
@@ -147,6 +150,7 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler,
/**
* Executes a selection of this item.
*/
+
public void execute() {
onSuggestionSelected(this);
}
@@ -392,6 +396,7 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler,
* com.google.gwt.user.client.ui.Widget#onBrowserEvent(com.google.gwt
* .user.client.Event)
*/
+
@Override
public void onBrowserEvent(Event event) {
if (event.getTypeInt() == Event.ONCLICK) {
@@ -449,6 +454,7 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler,
* com.google.gwt.user.client.ui.PopupPanel$PositionCallback#setPosition
* (int, int)
*/
+
public void setPosition(int offsetWidth, int offsetHeight) {
int top = -1;
@@ -541,6 +547,7 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler,
* com.google.gwt.event.logical.shared.CloseHandler#onClose(com.google
* .gwt.event.logical.shared.CloseEvent)
*/
+
@Override
public void onClose(CloseEvent<PopupPanel> event) {
if (event.isAutoClosed()) {
@@ -824,6 +831,7 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler,
* com.google.gwt.user.client.ui.TextBoxBase#onBrowserEvent(com.google
* .gwt.user.client.Event)
*/
+
@Override
public void onBrowserEvent(Event event) {
super.onBrowserEvent(event);
@@ -832,8 +840,8 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler,
}
}
- @Override
// Overridden to avoid selecting text when text input is disabled
+ @Override
public void setSelectionRange(int pos, int length) {
if (textInputEnabled) {
super.setSelectionRange(pos, length);
@@ -857,6 +865,7 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler,
* com.google.gwt.user.client.ui.Widget#onBrowserEvent(com.google.gwt
* .user.client.Event)
*/
+
@Override
public void onBrowserEvent(Event event) {
super.onBrowserEvent(event);
@@ -951,6 +960,7 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler,
public VFilterSelect() {
selectedItemIcon.setStyleName("v-icon");
selectedItemIcon.addLoadHandler(new LoadHandler() {
+
public void onLoad(LoadEvent event) {
if (BrowserInfo.get().isIE8()) {
// IE8 needs some help to discover it should reposition the
@@ -1203,6 +1213,7 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler,
* com.google.gwt.event.dom.client.KeyDownHandler#onKeyDown(com.google.gwt
* .event.dom.client.KeyDownEvent)
*/
+
public void onKeyDown(KeyDownEvent event) {
if (enabled && !readonly) {
int keyCode = event.getNativeKeyCode();
@@ -1364,6 +1375,7 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler,
* @param event
* The KeyUpEvent of the key depressed
*/
+
public void onKeyUp(KeyUpEvent event) {
if (enabled && !readonly) {
switch (event.getNativeKeyCode()) {
@@ -1411,6 +1423,7 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler,
/**
* Listener for popupopener
*/
+
public void onClick(ClickEvent event) {
if (textInputEnabled
&& event.getNativeEvent().getEventTarget().cast() == tb
@@ -1474,6 +1487,7 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler,
* com.google.gwt.event.dom.client.FocusHandler#onFocus(com.google.gwt.event
* .dom.client.FocusEvent)
*/
+
public void onFocus(FocusEvent event) {
/*
@@ -1567,6 +1581,7 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler,
*
* @see com.vaadin.terminal.gwt.client.Focusable#focus()
*/
+
public void focus() {
focused = true;
if (prompting && !readonly) {
@@ -1674,4 +1689,22 @@ public class VFilterSelect extends Composite implements Field, KeyDownHandler,
super.onDetach();
suggestionPopup.hide();
}
+
+ public Element getSubPartElement(String subPart) {
+ if ("textbox".equals(subPart)) {
+ return this.tb.getElement();
+ } else if ("button".equals(subPart)) {
+ return this.popupOpener.getElement();
+ }
+ return null;
+ }
+
+ public String getSubPartName(Element subElement) {
+ if (tb.getElement().isOrHasChild(subElement)) {
+ return "textbox";
+ } else if (popupOpener.getElement().isOrHasChild(subElement)) {
+ return "button";
+ }
+ return null;
+ }
}
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/dd/AcceptCriterion.java b/src/com/vaadin/terminal/gwt/client/ui/dd/AcceptCriterion.java
new file mode 100644
index 0000000000..8a026e4d2e
--- /dev/null
+++ b/src/com/vaadin/terminal/gwt/client/ui/dd/AcceptCriterion.java
@@ -0,0 +1,33 @@
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+
+package com.vaadin.terminal.gwt.client.ui.dd;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * An annotation type used to point the server side counterpart for client side
+ * a {@link VAcceptCriterion} class.
+ * <p>
+ * Annotations are used at GWT compilation phase, so remember to rebuild your
+ * widgetset if you do changes for {@link AcceptCriterion} mappings.
+ *
+ * Prior to Vaadin 7, the mapping was done with an annotation on server side
+ * classes.
+ *
+ * @since 7.0
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.TYPE)
+public @interface AcceptCriterion {
+ /**
+ * @return the class of the server side counterpart for the annotated
+ * criterion
+ */
+ Class<?> value();
+
+}
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..97f5eb86fd 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,14 +78,17 @@ 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);
- 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;
diff --git a/src/com/vaadin/terminal/gwt/client/ui/dd/VAcceptAll.java b/src/com/vaadin/terminal/gwt/client/ui/dd/VAcceptAll.java
index 51782c002d..a864a93c2a 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/dd/VAcceptAll.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/dd/VAcceptAll.java
@@ -6,8 +6,10 @@
*/
package com.vaadin.terminal.gwt.client.ui.dd;
+import com.vaadin.event.dd.acceptcriteria.AcceptAll;
import com.vaadin.terminal.gwt.client.UIDL;
+@AcceptCriterion(AcceptAll.class)
final public class VAcceptAll extends VAcceptCriterion {
@Override
diff --git a/src/com/vaadin/terminal/gwt/client/ui/dd/VAnd.java b/src/com/vaadin/terminal/gwt/client/ui/dd/VAnd.java
index 65c67e6b8a..19399d7d4a 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/dd/VAnd.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/dd/VAnd.java
@@ -6,8 +6,10 @@
*/
package com.vaadin.terminal.gwt.client.ui.dd;
+import com.vaadin.event.dd.acceptcriteria.And;
import com.vaadin.terminal.gwt.client.UIDL;
+@AcceptCriterion(And.class)
final public class VAnd extends VAcceptCriterion implements VAcceptCallback {
private boolean b1;
diff --git a/src/com/vaadin/terminal/gwt/client/ui/dd/VContainsDataFlavor.java b/src/com/vaadin/terminal/gwt/client/ui/dd/VContainsDataFlavor.java
index 4a95034d4a..3cd341eefd 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/dd/VContainsDataFlavor.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/dd/VContainsDataFlavor.java
@@ -6,8 +6,10 @@
*/
package com.vaadin.terminal.gwt.client.ui.dd;
+import com.vaadin.event.dd.acceptcriteria.ContainsDataFlavor;
import com.vaadin.terminal.gwt.client.UIDL;
+@AcceptCriterion(ContainsDataFlavor.class)
final public class VContainsDataFlavor extends VAcceptCriterion {
@Override
diff --git a/src/com/vaadin/terminal/gwt/client/ui/dd/VDragSourceIs.java b/src/com/vaadin/terminal/gwt/client/ui/dd/VDragSourceIs.java
index aabbf58b24..b6af81085f 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/dd/VDragSourceIs.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/dd/VDragSourceIs.java
@@ -3,6 +3,7 @@
*/
package com.vaadin.terminal.gwt.client.ui.dd;
+import com.vaadin.event.dd.acceptcriteria.SourceIs;
import com.vaadin.terminal.gwt.client.ComponentConnector;
import com.vaadin.terminal.gwt.client.ConnectorMap;
import com.vaadin.terminal.gwt.client.UIDL;
@@ -12,6 +13,7 @@ import com.vaadin.terminal.gwt.client.UIDL;
*
* @since 6.3
*/
+@AcceptCriterion(SourceIs.class)
final public class VDragSourceIs extends VAcceptCriterion {
@Override
diff --git a/src/com/vaadin/terminal/gwt/client/ui/dd/VIsOverId.java b/src/com/vaadin/terminal/gwt/client/ui/dd/VIsOverId.java
index 90e2b033c9..5dad4873ea 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/dd/VIsOverId.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/dd/VIsOverId.java
@@ -9,7 +9,9 @@ package com.vaadin.terminal.gwt.client.ui.dd;
import com.vaadin.terminal.gwt.client.ComponentConnector;
import com.vaadin.terminal.gwt.client.ConnectorMap;
import com.vaadin.terminal.gwt.client.UIDL;
+import com.vaadin.ui.AbstractSelect;
+@AcceptCriterion(AbstractSelect.TargetItemIs.class)
final public class VIsOverId extends VAcceptCriterion {
@Override
diff --git a/src/com/vaadin/terminal/gwt/client/ui/dd/VItemIdIs.java b/src/com/vaadin/terminal/gwt/client/ui/dd/VItemIdIs.java
index eb55c1a91c..ca4d0e900d 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/dd/VItemIdIs.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/dd/VItemIdIs.java
@@ -8,7 +8,9 @@ package com.vaadin.terminal.gwt.client.ui.dd;
import com.vaadin.terminal.gwt.client.ComponentConnector;
import com.vaadin.terminal.gwt.client.UIDL;
+import com.vaadin.ui.AbstractSelect;
+@AcceptCriterion(AbstractSelect.AcceptItem.class)
final public class VItemIdIs extends VAcceptCriterion {
@Override
diff --git a/src/com/vaadin/terminal/gwt/client/ui/dd/VLazyInitItemIdentifiers.java b/src/com/vaadin/terminal/gwt/client/ui/dd/VLazyInitItemIdentifiers.java
index b824c1cb65..e3bed02642 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/dd/VLazyInitItemIdentifiers.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/dd/VLazyInitItemIdentifiers.java
@@ -9,15 +9,29 @@ package com.vaadin.terminal.gwt.client.ui.dd;
import java.util.HashSet;
import com.vaadin.terminal.gwt.client.UIDL;
+import com.vaadin.ui.Table;
+import com.vaadin.ui.Tree;
/**
*
*/
-final public class VLazyInitItemIdentifiers extends VAcceptCriterion {
+public class VLazyInitItemIdentifiers extends VAcceptCriterion {
private boolean loaded = false;
private HashSet<String> hashSet;
private VDragEvent lastDragEvent;
+ @AcceptCriterion(Table.TableDropCriterion.class)
+ final public static class VTableLazyInitItemIdentifiers extends
+ VLazyInitItemIdentifiers {
+ // all logic in superclass
+ }
+
+ @AcceptCriterion(Tree.TreeDropCriterion.class)
+ final public static class VTreeLazyInitItemIdentifiers extends
+ VLazyInitItemIdentifiers {
+ // all logic in superclass
+ }
+
@Override
public void accept(final VDragEvent drag, UIDL configuration,
final VAcceptCallback callback) {
diff --git a/src/com/vaadin/terminal/gwt/client/ui/dd/VNot.java b/src/com/vaadin/terminal/gwt/client/ui/dd/VNot.java
index f4ba868497..e4d2dff606 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/dd/VNot.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/dd/VNot.java
@@ -6,6 +6,7 @@
*/
package com.vaadin.terminal.gwt.client.ui.dd;
+import com.vaadin.event.dd.acceptcriteria.Not;
import com.vaadin.terminal.gwt.client.UIDL;
import com.vaadin.terminal.gwt.client.VConsole;
@@ -13,6 +14,7 @@ import com.vaadin.terminal.gwt.client.VConsole;
* TODO implementation could now be simplified/optimized
*
*/
+@AcceptCriterion(Not.class)
final public class VNot extends VAcceptCriterion {
private boolean b1;
private VAcceptCriterion crit1;
diff --git a/src/com/vaadin/terminal/gwt/client/ui/dd/VOr.java b/src/com/vaadin/terminal/gwt/client/ui/dd/VOr.java
index e47447b7fc..91ba4bf0c4 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/dd/VOr.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/dd/VOr.java
@@ -6,11 +6,13 @@
*/
package com.vaadin.terminal.gwt.client.ui.dd;
+import com.vaadin.event.dd.acceptcriteria.Or;
import com.vaadin.terminal.gwt.client.UIDL;
/**
*
*/
+@AcceptCriterion(Or.class)
final public class VOr extends VAcceptCriterion implements VAcceptCallback {
private boolean accepted;
diff --git a/src/com/vaadin/terminal/gwt/client/ui/dd/VServerAccept.java b/src/com/vaadin/terminal/gwt/client/ui/dd/VServerAccept.java
index bccb6656aa..64c2da5320 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/dd/VServerAccept.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/dd/VServerAccept.java
@@ -6,8 +6,10 @@
*/
package com.vaadin.terminal.gwt.client.ui.dd;
+import com.vaadin.event.dd.acceptcriteria.ServerSideCriterion;
import com.vaadin.terminal.gwt.client.UIDL;
+@AcceptCriterion(ServerSideCriterion.class)
final public class VServerAccept extends VAcceptCriterion {
@Override
public void accept(final VDragEvent drag, UIDL configuration,
diff --git a/src/com/vaadin/terminal/gwt/client/ui/dd/VSourceIsTarget.java b/src/com/vaadin/terminal/gwt/client/ui/dd/VSourceIsTarget.java
index 430b422b34..2365eabe22 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/dd/VSourceIsTarget.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/dd/VSourceIsTarget.java
@@ -6,9 +6,11 @@
*/
package com.vaadin.terminal.gwt.client.ui.dd;
+import com.vaadin.event.dd.acceptcriteria.SourceIsTarget;
import com.vaadin.terminal.gwt.client.ComponentConnector;
import com.vaadin.terminal.gwt.client.UIDL;
+@AcceptCriterion(SourceIsTarget.class)
final public class VSourceIsTarget extends VAcceptCriterion {
@Override
diff --git a/src/com/vaadin/terminal/gwt/client/ui/dd/VTargetDetailIs.java b/src/com/vaadin/terminal/gwt/client/ui/dd/VTargetDetailIs.java
index 713a0d6646..610d555745 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/dd/VTargetDetailIs.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/dd/VTargetDetailIs.java
@@ -6,8 +6,10 @@
*/
package com.vaadin.terminal.gwt.client.ui.dd;
+import com.vaadin.event.dd.acceptcriteria.TargetDetailIs;
import com.vaadin.terminal.gwt.client.UIDL;
+@AcceptCriterion(TargetDetailIs.class)
final public class VTargetDetailIs extends VAcceptCriterion {
@Override
diff --git a/src/com/vaadin/terminal/gwt/client/ui/dd/VTargetInSubtree.java b/src/com/vaadin/terminal/gwt/client/ui/dd/VTargetInSubtree.java
index f69fa85290..56478b2b95 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/dd/VTargetInSubtree.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/dd/VTargetInSubtree.java
@@ -10,7 +10,9 @@ import com.google.gwt.user.client.ui.Widget;
import com.vaadin.terminal.gwt.client.UIDL;
import com.vaadin.terminal.gwt.client.ui.tree.VTree;
import com.vaadin.terminal.gwt.client.ui.tree.VTree.TreeNode;
+import com.vaadin.ui.Tree;
+@AcceptCriterion(Tree.TargetInSubtree.class)
final public class VTargetInSubtree extends VAcceptCriterion {
@Override
diff --git a/src/com/vaadin/terminal/gwt/client/ui/draganddropwrapper/DragAndDropWrapperConnector.java b/src/com/vaadin/terminal/gwt/client/ui/draganddropwrapper/DragAndDropWrapperConnector.java
index 57f6835bcc..2a78cc4433 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/draganddropwrapper/DragAndDropWrapperConnector.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/draganddropwrapper/DragAndDropWrapperConnector.java
@@ -57,6 +57,9 @@ public class DragAndDropWrapperConnector extends CustomComponentConnector
getWidget().initDragStartMode();
getWidget().html5DataFlavors = uidl
.getMapAttribute(VDragAndDropWrapper.HTML5_DATA_FLAVORS);
+
+ // Used to prevent wrapper from stealing tooltips when not defined
+ getWidget().hasTooltip = getState().hasDescription();
}
}
diff --git a/src/com/vaadin/terminal/gwt/client/ui/draganddropwrapper/VDragAndDropWrapper.java b/src/com/vaadin/terminal/gwt/client/ui/draganddropwrapper/VDragAndDropWrapper.java
index d09b81e1e1..4c36e92bbb 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/draganddropwrapper/VDragAndDropWrapper.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/draganddropwrapper/VDragAndDropWrapper.java
@@ -60,6 +60,8 @@ public class VDragAndDropWrapper extends VCustomComponent implements
private static final String CLASSNAME = "v-ddwrapper";
protected static final String DRAGGABLE = "draggable";
+ boolean hasTooltip = false;
+
public VDragAndDropWrapper() {
super();
sinkEvents(VTooltip.TOOLTIP_EVENTS);
@@ -67,6 +69,7 @@ public class VDragAndDropWrapper extends VCustomComponent implements
hookHtml5Events(getElement());
setStyleName(CLASSNAME);
addDomHandler(new MouseDownHandler() {
+
public void onMouseDown(MouseDownEvent event) {
if (startDrag(event.getNativeEvent())) {
event.preventDefault(); // prevent text selection
@@ -75,6 +78,7 @@ public class VDragAndDropWrapper extends VCustomComponent implements
}, MouseDownEvent.getType());
addDomHandler(new TouchStartHandler() {
+
public void onTouchStart(TouchStartEvent event) {
if (startDrag(event.getNativeEvent())) {
/*
@@ -92,7 +96,8 @@ public class VDragAndDropWrapper extends VCustomComponent implements
public void onBrowserEvent(Event event) {
super.onBrowserEvent(event);
- if (client != null) {
+ if (hasTooltip && client != null) {
+ // Override child tooltips if the wrapper has a tooltip defined
client.handleTooltipEvent(event, this);
}
}
@@ -172,6 +177,7 @@ public class VDragAndDropWrapper extends VCustomComponent implements
private boolean uploading;
private ReadyStateChangeHandler readyStateChangeHandler = new ReadyStateChangeHandler() {
+
public void onReadyStateChange(XMLHttpRequest xhr) {
if (xhr.getReadyState() == XMLHttpRequest.DONE) {
// visit server for possible
@@ -269,6 +275,7 @@ public class VDragAndDropWrapper extends VCustomComponent implements
try {
dragleavetimer = new Timer() {
+
@Override
public void run() {
// Yes, dragleave happens before drop. Makes no sense to me.
@@ -455,6 +462,7 @@ public class VDragAndDropWrapper extends VCustomComponent implements
if (detailsChanged) {
currentlyValid = false;
validate(new VAcceptCallback() {
+
public void accepted(VDragEvent event) {
dragAccepted(drag);
}
diff --git a/src/com/vaadin/terminal/gwt/client/ui/form/VForm.java b/src/com/vaadin/terminal/gwt/client/ui/form/VForm.java
index e3a0c9b321..81f24a8e7e 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/form/VForm.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/form/VForm.java
@@ -4,7 +4,6 @@
package com.vaadin.terminal.gwt.client.ui.form;
-import com.google.gwt.dom.client.Style.Display;
import com.google.gwt.event.dom.client.KeyDownEvent;
import com.google.gwt.event.dom.client.KeyDownHandler;
import com.google.gwt.event.shared.HandlerRegistration;
@@ -27,7 +26,6 @@ public class VForm extends ComplexPanel implements KeyDownHandler {
Widget lo;
Element legend = DOM.createLegend();
Element caption = DOM.createSpan();
- private Element errorIndicatorElement = DOM.createDiv();
Element desc = DOM.createDiv();
Icon icon;
VErrorMessage errorMessage = new VErrorMessage();
@@ -52,9 +50,6 @@ public class VForm extends ComplexPanel implements KeyDownHandler {
setStyleName(CLASSNAME);
fieldSet.appendChild(legend);
legend.appendChild(caption);
- errorIndicatorElement.setClassName("v-errorindicator");
- errorIndicatorElement.getStyle().setDisplay(Display.NONE);
- errorIndicatorElement.setInnerText(" "); // needed for IE
desc.setClassName("v-form-description");
fieldSet.appendChild(desc); // Adding description for initial padding
// measurements, removed later if no
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/formlayout/VFormLayout.java b/src/com/vaadin/terminal/gwt/client/ui/formlayout/VFormLayout.java
index 85584755a6..8a859c409c 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/formlayout/VFormLayout.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/formlayout/VFormLayout.java
@@ -35,7 +35,6 @@ public class VFormLayout extends SimplePanel {
private final static String CLASSNAME = "v-formlayout";
- ApplicationConnection client;
VFormLayoutTable table;
public VFormLayout() {
@@ -371,7 +370,7 @@ public class VFormLayout extends SimplePanel {
public void onBrowserEvent(Event event) {
super.onBrowserEvent(event);
if (owner != null) {
- client.handleTooltipEvent(event, owner);
+ owner.getConnection().handleTooltipEvent(event, owner);
}
}
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/label/ContentMode.java b/src/com/vaadin/terminal/gwt/client/ui/label/ContentMode.java
index 2c232c9c38..4892c7e6bd 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/label/ContentMode.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/label/ContentMode.java
@@ -6,7 +6,7 @@ package com.vaadin.terminal.gwt.client.ui.label;
/**
* Content modes defining how the client should interpret a Label's value.
*
- * @sine 7.0
+ * @since 7.0.0
*/
public enum ContentMode {
/**
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/nativebutton/VNativeButton.java b/src/com/vaadin/terminal/gwt/client/ui/nativebutton/VNativeButton.java
index 01ac4fab6a..dd6e741126 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/nativebutton/VNativeButton.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/nativebutton/VNativeButton.java
@@ -127,11 +127,4 @@ public class VNativeButton extends Button implements ClickHandler {
clickPending = false;
}
- @Override
- public void setEnabled(boolean enabled) {
- if (isEnabled() != enabled) {
- super.setEnabled(enabled);
- setStyleName(ApplicationConnection.DISABLED_CLASSNAME, !enabled);
- }
- }
}
diff --git a/src/com/vaadin/terminal/gwt/client/ui/notification/VNotification.java b/src/com/vaadin/terminal/gwt/client/ui/notification/VNotification.java
index 0d222044ba..fb853b8a55 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/notification/VNotification.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/notification/VNotification.java
@@ -43,6 +43,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<VNotification> notifications = new ArrayList<VNotification>();
+
private int startOpacity = 90;
private int fadeMsec = 400;
private int delayMsec = 1000;
@@ -159,6 +161,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
@@ -180,6 +183,7 @@ public class VNotification extends VOverlay {
temporaryStyle = null;
}
super.hide();
+ notifications.remove(this);
fireEvent(new HideEvent(this));
}
@@ -435,4 +439,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/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..d9096526f3 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/panel/PanelConnector.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/panel/PanelConnector.java
@@ -111,6 +111,8 @@ public class PanelConnector extends AbstractComponentContainerConnector
getWidget().captionNode.setClassName(captionClass);
getWidget().contentNode.setClassName(contentClass);
getWidget().bottomDecoration.setClassName(decoClass);
+
+ getWidget().makeScrollable();
}
if (!isRealUpdate(uidl)) {
@@ -226,8 +228,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/panel/VPanel.java b/src/com/vaadin/terminal/gwt/client/ui/panel/VPanel.java
index e2d3d443a0..6a06367acd 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/panel/VPanel.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/panel/VPanel.java
@@ -6,8 +6,6 @@ package com.vaadin.terminal.gwt.client.ui.panel;
import com.google.gwt.dom.client.DivElement;
import com.google.gwt.dom.client.Document;
-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;
@@ -18,6 +16,7 @@ import com.vaadin.terminal.gwt.client.ui.Icon;
import com.vaadin.terminal.gwt.client.ui.ShortcutActionHandler;
import com.vaadin.terminal.gwt.client.ui.ShortcutActionHandler.ShortcutActionHandlerOwner;
import com.vaadin.terminal.gwt.client.ui.TouchScrollDelegate;
+import com.vaadin.terminal.gwt.client.ui.TouchScrollDelegate.TouchScrollHandler;
public class VPanel extends SimplePanel implements ShortcutActionHandlerOwner,
Focusable {
@@ -46,7 +45,7 @@ public class VPanel extends SimplePanel implements ShortcutActionHandlerOwner,
int scrollLeft;
- private TouchScrollDelegate touchScrollDelegate;
+ private TouchScrollHandler touchScrollHandler;
public VPanel() {
super();
@@ -74,11 +73,11 @@ public class VPanel extends SimplePanel implements ShortcutActionHandlerOwner,
setStyleName(CLASSNAME);
DOM.sinkEvents(getElement(), Event.ONKEYDOWN);
DOM.sinkEvents(contentNode, Event.ONSCROLL | Event.TOUCHEVENTS);
- addHandler(new TouchStartHandler() {
- public void onTouchStart(TouchStartEvent event) {
- getTouchScrollDelegate().onTouchStart(event);
- }
- }, TouchStartEvent.getType());
+
+ contentNode.getStyle().setProperty("position", "relative");
+ getElement().getStyle().setProperty("overflow", "hidden");
+
+ makeScrollable();
}
/**
@@ -100,6 +99,7 @@ public class VPanel extends SimplePanel implements ShortcutActionHandlerOwner,
*
* @see com.vaadin.terminal.gwt.client.Focusable#focus()
*/
+
public void focus() {
setFocus(true);
@@ -174,16 +174,17 @@ public class VPanel extends SimplePanel implements ShortcutActionHandlerOwner,
}
}
- protected TouchScrollDelegate getTouchScrollDelegate() {
- if (touchScrollDelegate == null) {
- touchScrollDelegate = new TouchScrollDelegate(contentNode);
- }
- return touchScrollDelegate;
-
- }
-
public ShortcutActionHandler getShortcutActionHandler() {
return shortcutHandler;
}
+ /**
+ * Ensures the panel is scrollable eg. after style name changes
+ */
+ void makeScrollable() {
+ if (touchScrollHandler == null) {
+ touchScrollHandler = TouchScrollDelegate.enableTouchScrolling(this);
+ }
+ touchScrollHandler.addElement(contentNode);
+ }
}
diff --git a/src/com/vaadin/terminal/gwt/client/ui/root/PageClientRpc.java b/src/com/vaadin/terminal/gwt/client/ui/root/PageClientRpc.java
new file mode 100644
index 0000000000..a02ecc8ded
--- /dev/null
+++ b/src/com/vaadin/terminal/gwt/client/ui/root/PageClientRpc.java
@@ -0,0 +1,13 @@
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+
+package com.vaadin.terminal.gwt.client.ui.root;
+
+import com.vaadin.terminal.gwt.client.communication.ClientRpc;
+
+public interface PageClientRpc extends ClientRpc {
+
+ public void setTitle(String title);
+
+}
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..1a62e566ad 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/root/RootConnector.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/root/RootConnector.java
@@ -61,6 +61,11 @@ public class RootConnector extends AbstractComponentContainerConnector
@Override
protected void init() {
super.init();
+ registerRpc(PageClientRpc.class, new PageClientRpc() {
+ public void setTitle(String title) {
+ com.google.gwt.user.client.Window.setTitle(title);
+ }
+ });
}
public void updateFromUIDL(final UIDL uidl, ApplicationConnection client) {
@@ -93,12 +98,9 @@ public class RootConnector extends AbstractComponentContainerConnector
}
getWidget().setStyleName(styles.trim());
- clickEventHandler.handleEventHandlerRegistration();
+ getWidget().makeScrollable();
- if (!getWidget().isEmbedded() && getState().getCaption() != null) {
- // only change window title if we're in charge of the whole page
- com.google.gwt.user.client.Window.setTitle(getState().getCaption());
- }
+ clickEventHandler.handleEventHandlerRegistration();
// Process children
int childIndex = 0;
@@ -168,9 +170,6 @@ public class RootConnector extends AbstractComponentContainerConnector
getWidget().id, client);
}
getWidget().actionHandler.updateActionMap(childUidl);
- } else if (tag == "execJS") {
- String script = childUidl.getStringAttribute("script");
- VRoot.eval(script);
} else if (tag == "notifications") {
for (final Iterator<?> it = childUidl.getChildIterator(); it
.hasNext();) {
@@ -329,7 +328,7 @@ public class RootConnector extends AbstractComponentContainerConnector
*/
@Deprecated
public boolean hasSubWindow(WindowConnector wc) {
- return getChildren().contains(wc);
+ return getChildComponents().contains(wc);
}
/**
@@ -340,7 +339,7 @@ public class RootConnector extends AbstractComponentContainerConnector
*/
public List<WindowConnector> getSubWindows() {
ArrayList<WindowConnector> windows = new ArrayList<WindowConnector>();
- for (ComponentConnector child : getChildren()) {
+ for (ComponentConnector child : getChildComponents()) {
if (child instanceof WindowConnector) {
windows.add((WindowConnector) child);
}
@@ -380,7 +379,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/root/VRoot.java b/src/com/vaadin/terminal/gwt/client/ui/root/VRoot.java
index 12a69d5556..0af8919280 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/root/VRoot.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/root/VRoot.java
@@ -7,6 +7,7 @@ package com.vaadin.terminal.gwt.client.ui.root;
import java.util.ArrayList;
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
+import com.google.gwt.dom.client.Element;
import com.google.gwt.event.logical.shared.ResizeEvent;
import com.google.gwt.event.logical.shared.ResizeHandler;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
@@ -26,6 +27,8 @@ import com.vaadin.terminal.gwt.client.Focusable;
import com.vaadin.terminal.gwt.client.VConsole;
import com.vaadin.terminal.gwt.client.ui.ShortcutActionHandler;
import com.vaadin.terminal.gwt.client.ui.ShortcutActionHandler.ShortcutActionHandlerOwner;
+import com.vaadin.terminal.gwt.client.ui.TouchScrollDelegate;
+import com.vaadin.terminal.gwt.client.ui.TouchScrollDelegate.TouchScrollHandler;
import com.vaadin.terminal.gwt.client.ui.VLazyExecutor;
import com.vaadin.terminal.gwt.client.ui.textfield.VTextField;
@@ -37,21 +40,36 @@ public class VRoot extends SimplePanel implements ResizeHandler,
public static final String FRAGMENT_VARIABLE = "fragment";
+ 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";
+ private static int MONITOR_PARENT_TIMER_INTERVAL = 1000;
+
String theme;
String id;
ShortcutActionHandler actionHandler;
- /** stored width for IE resize optimization */
- private int width;
+ /*
+ * Last known window size used to detect whether VView should be layouted
+ * 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;
- /** stored height for IE resize optimization */
- private int height;
+ /*
+ * Last know view size used to detect whether new dimensions should be sent
+ * to the server.
+ */
+ private int viewWidth;
+ private int viewHeight;
ApplicationConnection connection;
@@ -59,13 +77,19 @@ public class VRoot extends SimplePanel implements ResizeHandler,
public static final String CLICK_EVENT_ID = "click";
/**
- * 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;
+
int scrollTop;
int scrollLeft;
@@ -85,6 +109,8 @@ public class VRoot extends SimplePanel implements ResizeHandler,
private HandlerRegistration historyHandlerRegistration;
+ private TouchScrollHandler touchScrollHandler;
+
/**
* The current URI fragment, used to avoid sending updates if nothing has
* changed.
@@ -96,6 +122,7 @@ public class VRoot extends SimplePanel implements ResizeHandler,
* whenever the value changes.
*/
private final ValueChangeHandler<String> historyChangeHandler = new ValueChangeHandler<String>() {
+
public void onValueChange(ValueChangeEvent<String> event) {
String newFragment = event.getValue();
@@ -110,9 +137,9 @@ public class VRoot extends SimplePanel implements ResizeHandler,
private VLazyExecutor delayedResizeExecutor = new VLazyExecutor(200,
new ScheduledCommand() {
+
public void execute() {
- windowSizeMaybeChanged(Window.getClientWidth(),
- Window.getClientHeight());
+ performSizeCheck();
}
});
@@ -124,6 +151,29 @@ public class VRoot extends SimplePanel implements ResizeHandler,
// Allow focusing the view by using the focus() method, the view
// should not be in the document focus flow
getElement().setTabIndex(-1);
+ makeScrollable();
+ }
+
+ /**
+ * Start to periodically monitor for parent element resizes if embedded
+ * application (e.g. portlet).
+ */
+ @Override
+ protected void onLoad() {
+ super.onLoad();
+ 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);
+ }
}
@Override
@@ -142,32 +192,95 @@ public class VRoot extends SimplePanel implements ResizeHandler,
}
/**
- * Called when the window might have been resized.
+ * 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.
*
- * @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;
ComponentConnector connector = ConnectorMap.get(connection)
.getConnector(this);
- if (width != newWidth) {
- width = newWidth;
+ if (windowWidth != newWindowWidth) {
+ windowWidth = newWindowWidth;
changed = true;
- connector.getLayoutManager().reportOuterWidth(connector, newWidth);
- VConsole.log("New window width: " + width);
+ connector.getLayoutManager().reportOuterWidth(connector,
+ newWindowWidth);
+ VConsole.log("New window width: " + windowWidth);
}
- if (height != newHeight) {
- height = newHeight;
+ if (windowHeight != newWindowHeight) {
+ windowHeight = newWindowHeight;
changed = true;
- connector.getLayoutManager()
- .reportOuterHeight(connector, newHeight);
- VConsole.log("New window height: " + height);
+ connector.getLayoutManager().reportOuterHeight(connector,
+ newWindowHeight);
+ 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) {
- VConsole.log("Running layout functions due to window resize");
+ /*
+ * 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 or parent resize");
+
+ // 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();
@@ -188,21 +301,6 @@ public class VRoot extends SimplePanel implements ResizeHandler,
}-*/;
/**
- * Evaluate the given script in the browser document.
- *
- * @param script
- * Script to be executed.
- */
- static native void eval(String script)
- /*-{
- try {
- if (script == null) return;
- $wnd.eval(script);
- } catch (e) {
- }
- }-*/;
-
- /**
* Returns true if the body is NOT generated, i.e if someone else has made
* the page that we're running in. Otherwise we're in charge of the whole
* page.
@@ -214,6 +312,17 @@ public class VRoot extends SimplePanel implements 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();
+ }
+
@Override
public void onBrowserEvent(Event event) {
super.onBrowserEvent(event);
@@ -251,14 +360,19 @@ public class VRoot extends SimplePanel implements ResizeHandler,
* com.google.gwt.event.logical.shared.ResizeHandler#onResize(com.google
* .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.
*/
- 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
@@ -274,8 +388,7 @@ public class VRoot extends SimplePanel implements ResizeHandler,
if (lazy) {
delayedResizeExecutor.trigger();
} else {
- windowSizeMaybeChanged(Window.getClientWidth(),
- Window.getClientHeight());
+ performSizeCheck();
}
}
@@ -283,8 +396,19 @@ public class VRoot extends SimplePanel implements ResizeHandler,
* Send new dimensions to the server.
*/
private void sendClientResized() {
- connection.updateVariable(id, "height", height, false);
- connection.updateVariable(id, "width", width, immediate);
+ Element parentElement = getElement().getParentElement();
+ int viewHeight = parentElement.getClientHeight();
+ int viewWidth = parentElement.getClientWidth();
+
+ 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)
@@ -319,4 +443,13 @@ public class VRoot extends SimplePanel implements ResizeHandler,
getElement().focus();
}
+ /**
+ * Ensures the root is scrollable eg. after style name changes.
+ */
+ void makeScrollable() {
+ if (touchScrollHandler == null) {
+ touchScrollHandler = TouchScrollDelegate.enableTouchScrolling(this);
+ }
+ touchScrollHandler.addElement(getElement());
+ }
}
diff --git a/src/com/vaadin/terminal/gwt/client/ui/slider/VSlider.java b/src/com/vaadin/terminal/gwt/client/ui/slider/VSlider.java
index 9ff614252d..5c7ee7a784 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/slider/VSlider.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/slider/VSlider.java
@@ -18,6 +18,7 @@ import com.vaadin.terminal.gwt.client.BrowserInfo;
import com.vaadin.terminal.gwt.client.ContainerResizedListener;
import com.vaadin.terminal.gwt.client.Util;
import com.vaadin.terminal.gwt.client.VConsole;
+import com.vaadin.terminal.gwt.client.VTooltip;
import com.vaadin.terminal.gwt.client.ui.Field;
import com.vaadin.terminal.gwt.client.ui.SimpleFocusablePanel;
import com.vaadin.terminal.gwt.client.ui.VLazyExecutor;
@@ -51,6 +52,7 @@ public class VSlider extends SimpleFocusablePanel implements Field,
private final HTML feedback = new HTML("", false);
private final VOverlay feedbackPopup = new VOverlay(true, false, true) {
+
@Override
public void show() {
super.show();
@@ -112,6 +114,8 @@ public class VSlider extends SimpleFocusablePanel implements Field,
feedbackPopup.addStyleName(CLASSNAME + "-feedback");
feedbackPopup.setWidget(feedback);
+
+ sinkEvents(VTooltip.TOOLTIP_EVENTS);
}
void setFeedbackValue(double value) {
@@ -139,8 +143,12 @@ public class VSlider extends SimpleFocusablePanel implements Field,
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) {
@@ -153,6 +161,7 @@ public class VSlider extends SimpleFocusablePanel implements Field,
// (supposedly) been drawn completely.
DOM.setStyleAttribute(base, styleAttribute, MIN_SIZE + "px");
Scheduler.get().scheduleDeferred(new Command() {
+
public void execute() {
final Element p = DOM.getParent(getElement());
if (DOM.getElementPropertyInt(p, domProperty) > (MIN_SIZE + 5)) {
@@ -173,9 +182,14 @@ public class VSlider extends SimpleFocusablePanel implements Field,
void buildHandle() {
final String handleAttribute = vertical ? "marginTop" : "marginLeft";
+ final String oppositeHandleAttribute = vertical ? "marginLeft"
+ : "marginTop";
DOM.setStyleAttribute(handle, handleAttribute, "0");
+ // clear unnecessary opposite handle attribute
+ DOM.setStyleAttribute(handle, oppositeHandleAttribute, "");
+
// Restore visibility
DOM.setStyleAttribute(handle, "visibility", "visible");
@@ -277,6 +291,9 @@ public class VSlider extends SimpleFocusablePanel implements Field,
event.preventDefault(); // avoid simulated events
event.stopPropagation();
}
+ if (client != null) {
+ client.handleTooltipEvent(event, this);
+ }
}
private void processMouseWheelEvent(final Event event) {
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..e33755bc9b 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/splitpanel/AbstractSplitPanelConnector.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/splitpanel/AbstractSplitPanelConnector.java
@@ -127,6 +127,12 @@ public abstract class AbstractSplitPanelConnector extends
getWidget().setStylenames();
+ getWidget().minimumPosition = splitterState.getMinPosition()
+ + splitterState.getMinPositionUnit();
+
+ getWidget().maximumPosition = splitterState.getMaxPosition()
+ + splitterState.getMaxPositionUnit();
+
getWidget().position = splitterState.getPosition()
+ splitterState.getPositionUnit();
@@ -136,6 +142,7 @@ public abstract class AbstractSplitPanelConnector extends
getLayoutManager().setNeedsLayout(this);
+ getWidget().makeScrollable();
}
public void layout() {
@@ -143,7 +150,7 @@ public abstract class AbstractSplitPanelConnector extends
splitPanel.setSplitPosition(splitPanel.position);
splitPanel.updateSizes();
// Report relative sizes in other direction for quicker propagation
- List<ComponentConnector> children = getChildren();
+ List<ComponentConnector> children = getChildComponents();
for (ComponentConnector child : children) {
reportOtherDimension(child);
}
diff --git a/src/com/vaadin/terminal/gwt/client/ui/splitpanel/AbstractSplitPanelState.java b/src/com/vaadin/terminal/gwt/client/ui/splitpanel/AbstractSplitPanelState.java
index 8b80eed840..db3a39d3a5 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/splitpanel/AbstractSplitPanelState.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/splitpanel/AbstractSplitPanelState.java
@@ -49,6 +49,10 @@ public class AbstractSplitPanelState extends ComponentState {
public static class SplitterState implements Serializable {
private float position;
private String positionUnit;
+ private float minPosition;
+ private String minPositionUnit;
+ private float maxPosition;
+ private String maxPositionUnit;
private boolean positionReversed = false;
private boolean locked = false;
@@ -68,6 +72,38 @@ public class AbstractSplitPanelState extends ComponentState {
this.positionUnit = positionUnit;
}
+ public float getMinPosition() {
+ return minPosition;
+ }
+
+ public void setMinPosition(float minPosition) {
+ this.minPosition = minPosition;
+ }
+
+ public String getMinPositionUnit() {
+ return minPositionUnit;
+ }
+
+ public void setMinPositionUnit(String minPositionUnit) {
+ this.minPositionUnit = minPositionUnit;
+ }
+
+ public float getMaxPosition() {
+ return maxPosition;
+ }
+
+ public void setMaxPosition(float maxPosition) {
+ this.maxPosition = maxPosition;
+ }
+
+ public String getMaxPositionUnit() {
+ return maxPositionUnit;
+ }
+
+ public void setMaxPositionUnit(String maxPositionUnit) {
+ this.maxPositionUnit = maxPositionUnit;
+ }
+
public boolean isPositionReversed() {
return positionReversed;
}
diff --git a/src/com/vaadin/terminal/gwt/client/ui/splitpanel/VAbstractSplitPanel.java b/src/com/vaadin/terminal/gwt/client/ui/splitpanel/VAbstractSplitPanel.java
index 166e79e92e..e2f30c6676 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/splitpanel/VAbstractSplitPanel.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/splitpanel/VAbstractSplitPanel.java
@@ -4,6 +4,7 @@
package com.vaadin.terminal.gwt.client.ui.splitpanel;
+import java.util.Collections;
import java.util.List;
import com.google.gwt.dom.client.Node;
@@ -31,6 +32,7 @@ import com.vaadin.terminal.gwt.client.LayoutManager;
import com.vaadin.terminal.gwt.client.Util;
import com.vaadin.terminal.gwt.client.VConsole;
import com.vaadin.terminal.gwt.client.ui.TouchScrollDelegate;
+import com.vaadin.terminal.gwt.client.ui.TouchScrollDelegate.TouchScrollHandler;
import com.vaadin.terminal.gwt.client.ui.VOverlay;
import com.vaadin.terminal.gwt.client.ui.splitpanel.VAbstractSplitPanel.SplitterMoveHandler.SplitterMoveEvent;
@@ -76,7 +78,7 @@ public class VAbstractSplitPanel extends ComplexPanel {
private boolean positionReversed = false;
- List<String> componentStyleNames;
+ List<String> componentStyleNames = Collections.emptyList();
private Element draggingCurtain;
@@ -87,12 +89,16 @@ public class VAbstractSplitPanel extends ComplexPanel {
/* The current position of the split handle in either percentages or pixels */
String position;
+ String maximumPosition;
+
+ String minimumPosition;
+
+ private TouchScrollHandler touchScrollHandler;
+
protected Element scrolledContainer;
protected int origScrollTop;
- private TouchScrollDelegate touchScrollDelegate;
-
public VAbstractSplitPanel() {
this(ORIENTATION_HORIZONTAL);
}
@@ -116,6 +122,8 @@ public class VAbstractSplitPanel extends ComplexPanel {
setOrientation(orientation);
sinkEvents(Event.MOUSEEVENTS);
+ makeScrollable();
+
addDomHandler(new TouchCancelHandler() {
public void onTouchCancel(TouchCancelEvent event) {
// TODO When does this actually happen??
@@ -127,11 +135,8 @@ public class VAbstractSplitPanel extends ComplexPanel {
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) {
@@ -150,14 +155,6 @@ public class VAbstractSplitPanel extends ComplexPanel {
}
- 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);
@@ -172,9 +169,7 @@ public class VAbstractSplitPanel extends ComplexPanel {
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) {
@@ -190,11 +185,6 @@ public class VAbstractSplitPanel extends ComplexPanel {
DOM.setStyleAttribute(firstContainer, "width", "100%");
DOM.setStyleAttribute(secondContainer, "width", "100%");
}
-
- DOM.setElementProperty(firstContainer, "className", CLASSNAME
- + "-first-container");
- DOM.setElementProperty(secondContainer, "className", CLASSNAME
- + "-second-container");
}
@Override
@@ -232,11 +222,109 @@ public class VAbstractSplitPanel extends ComplexPanel {
}
}
+ /**
+ * 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;
+ }
+ posAsFloat = ((float) posAsInt / (float) offsetLength * 100);
+
+ } else {
+ posAsFloat = Float.parseFloat(pos.substring(0, pos.length() - 1));
+ }
+ return posAsFloat;
+ }
+
+ /**
+ * Returns the given position clamped to the range between current minimum
+ * and maximum positions.
+ *
+ * TODO Should this be in the connector?
+ *
+ * @param pos
+ * Position of the splitter as a CSS string, either pixels or a
+ * percentage.
+ * @return minimumPosition if pos is less than minimumPosition;
+ * maximumPosition if pos is greater than maximumPosition; pos
+ * otherwise.
+ */
+ private String checkSplitPositionLimits(String pos) {
+ float positionAsFloat = convertToPixels(pos);
+
+ if (maximumPosition != null
+ && convertToPixels(maximumPosition) < positionAsFloat) {
+ pos = maximumPosition;
+ } else if (minimumPosition != null
+ && convertToPixels(minimumPosition) > 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;
+ }
+
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) {
int size = orientation == ORIENTATION_HORIZONTAL ? getOffsetWidth()
@@ -375,7 +463,6 @@ public class VAbstractSplitPanel extends ComplexPanel {
}
break;
}
-
}
void setFirstWidget(Widget w) {
@@ -481,16 +568,7 @@ public class VAbstractSplitPanel extends ComplexPanel {
}
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) {
@@ -523,16 +601,7 @@ public class VAbstractSplitPanel extends ComplexPanel {
}
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) {
@@ -659,30 +728,24 @@ public class VAbstractSplitPanel extends ComplexPanel {
}
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 (String style : componentStyleNames) {
- splitterStyle += " " + CLASSNAME + splitterSuffix + "-" + style
- + lockedSuffix;
- firstStyle += " " + CLASSNAME + firstContainerSuffix + "-" + style;
- secondStyle += " " + CLASSNAME + secondContainerSuffix + "-"
- + style;
- }
- 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.setClassName(splitterClass + lockedSuffix);
+ firstContainer.setClassName(firstContainerClass);
+ secondContainer.setClassName(secondContainerClass);
+
+ for (String styleName : componentStyleNames) {
+ splitter.addClassName(splitterClass + "-" + styleName
+ + lockedSuffix);
+ firstContainer.addClassName(firstContainerClass + "-" + styleName);
+ secondContainer
+ .addClassName(secondContainerClass + "-" + styleName);
+ }
}
public void setEnabled(boolean enabled) {
@@ -693,4 +756,14 @@ public class VAbstractSplitPanel extends ComplexPanel {
return enabled;
}
+ /**
+ * Ensures the panels are scrollable eg. after style name changes
+ */
+ void makeScrollable() {
+ if (touchScrollHandler == null) {
+ touchScrollHandler = TouchScrollDelegate.enableTouchScrolling(this);
+ }
+ touchScrollHandler.addElement(firstContainer);
+ touchScrollHandler.addElement(secondContainer);
+ }
}
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/table/VScrollTable.java b/src/com/vaadin/terminal/gwt/client/ui/table/VScrollTable.java
index c45c26c4ac..c4a57f5c8b 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/table/VScrollTable.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/table/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;
@@ -236,6 +234,12 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
private boolean enableDebug = false;
+ private static final boolean hasNativeTouchScrolling = BrowserInfo.get()
+ .isTouchDevice()
+ && !BrowserInfo.get().requiresTouchScrollDelegate();
+
+ private Set<String> noncollapsibleColumns;
+
/**
* Represents a select range of rows
*/
@@ -268,6 +272,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
*
* @see java.lang.Object#toString()
*/
+
@Override
public String toString() {
return startRow.getKey() + "-" + length;
@@ -321,6 +326,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
final FocusableScrollPanel scrollBodyPanel = new FocusableScrollPanel(true);
private KeyPressHandler navKeyPressHandler = new KeyPressHandler() {
+
public void onKeyPress(KeyPressEvent keyPressEvent) {
// This is used for Firefox only, since Firefox auto-repeat
// works correctly only if we use a key press handler, other
@@ -489,12 +495,12 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
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
@@ -509,14 +515,10 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
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() {
+
public void onContextMenu(ContextMenuEvent event) {
handleBodyContextMenu(event);
}
@@ -536,22 +538,13 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
// Add a handler to clear saved context menu details when the menu
// closes. See #8526.
client.getContextMenu().addCloseHandler(new CloseHandler<PopupPanel>() {
+
public void onClose(CloseEvent<PopupPanel> event) {
contextMenu = null;
}
});
}
- 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());
@@ -896,6 +889,10 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
updateHeader(uidl.getStringArrayAttribute("vcolorder"));
updateFooter(uidl.getStringArrayAttribute("vcolorder"));
+ if (uidl.hasVariable("noncollapsiblecolumns")) {
+ noncollapsibleColumns = uidl
+ .getStringArrayVariableAsSet("noncollapsiblecolumns");
+ }
}
private void updateCollapsedColumns(UIDL uidl) {
@@ -1848,12 +1845,9 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
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
.setScrollPosition(measureRowHeightOffset(firstvisible));
@@ -1888,6 +1882,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
*/
scrollBody.reLayoutComponents();
Scheduler.get().scheduleDeferred(new Command() {
+
public void execute() {
Util.runWebkitOverflowAutoFix(scrollBodyPanel.getElement());
}
@@ -2218,6 +2213,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
setWidth(tdWidth + "px");
} else {
Scheduler.get().scheduleDeferred(new Command() {
+
public void execute() {
int tdWidth = width
+ scrollBody.getCellExtraWidth();
@@ -2271,6 +2267,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
/**
* Handle column reordering.
*/
+
@Override
public void onBrowserEvent(Event event) {
if (enabled && event != null) {
@@ -2814,6 +2811,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
final int newWidth = width;
Scheduler.get().scheduleDeferred(
new ScheduledCommand() {
+
public void execute() {
setColWidth(colIx, newWidth, true);
}
@@ -2841,6 +2839,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
if (refreshContentWidths) {
// Recalculate the column sizings if any column has changed
Scheduler.get().scheduleDeferred(new ScheduledCommand() {
+
public void execute() {
triggerLazyColumnAdjustment(true);
}
@@ -3029,6 +3028,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
String colKey;
private boolean collapsed;
+ private boolean noncollapsible = false;
private VScrollTableRow currentlyFocusedRow;
public VisibleColumnAction(String colKey) {
@@ -3040,6 +3040,9 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
@Override
public void execute() {
+ if (noncollapsible) {
+ return;
+ }
client.getContextMenu().hide();
// toggle selected column
if (collapsedColumns.contains(colKey)) {
@@ -3063,17 +3066,28 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
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("<span class=\"");
if (collapsed) {
- buf.append("<span class=\"v-off\">");
+ buf.append("v-off");
} else {
- buf.append("<span class=\"v-on\">");
+ buf.append("v-on");
+ }
+ if (noncollapsible) {
+ buf.append(" v-disabled");
}
+ buf.append("\">");
+
buf.append(super.getHTML());
buf.append("</span>");
@@ -3085,6 +3099,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
/*
* Returns columns as Action array for column select popup
*/
+
public Action[] getActions() {
Object[] cols;
if (columnReordering && columnOrder != null) {
@@ -3115,6 +3130,9 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
if (!c.isEnabled()) {
a.setCollapsed(true);
}
+ if (noncollapsibleColumns.contains(cid)) {
+ a.setNoncollapsible(true);
+ }
actions[i] = a;
}
return actions;
@@ -3200,6 +3218,10 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
* The text in the footer
*/
public void setText(String footerText) {
+ if (footerText == null || footerText.equals("")) {
+ footerText = "&nbsp;";
+ }
+
DOM.setInnerHTML(captionContainer, footerText);
}
@@ -3295,6 +3317,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
setWidth(tdWidth + "px");
} else {
Scheduler.get().scheduleDeferred(new Command() {
+
public void execute() {
int borderWidths = 1;
int tdWidth = width
@@ -3541,6 +3564,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
* com.google.gwt.user.client.ui.Panel#remove(com.google.gwt.user.client
* .ui.Widget)
*/
+
@Override
public boolean remove(Widget w) {
if (visibleCells.contains(w)) {
@@ -3557,6 +3581,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
*
* @see com.google.gwt.user.client.ui.HasWidgets#iterator()
*/
+
public Iterator<Widget> iterator() {
return visibleCells.iterator();
}
@@ -3835,7 +3860,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
DOM.appendChild(container, preSpacer);
DOM.appendChild(container, table);
DOM.appendChild(container, postSpacer);
- if (BrowserInfo.get().isTouchDevice()) {
+ if (BrowserInfo.get().requiresTouchScrollDelegate()) {
NodeList<Node> childNodes = container.getChildNodes();
for (int i = 0; i < childNodes.getLength(); i++) {
Element item = (Element) childNodes.getItem(i);
@@ -4388,7 +4413,6 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
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";
@@ -4396,8 +4420,10 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
+ "-row-odd";
private static final int TOUCH_CONTEXT_MENU_TIMEOUT = 500;
private Timer contextTouchTimeout;
+ private Timer dragTouchTimeout;
private int touchStartY;
private int touchStartX;
+ private boolean isDragging = false;
private VScrollTableRow(int rowKey) {
this.rowKey = rowKey;
@@ -4785,12 +4811,128 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
}
}
+ /**
+ * Special handler for touch devices that support native scrolling
+ *
+ * @return Whether the event was handled by this method.
+ */
+ 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.ONTOUCHSTART:
+ touchEventHandled = true;
+ touchStart = event;
+ isDragging = 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) {
+ // Start a drag if a finger is held
+ // in place long enough, then moved
+ isDragging = true;
+ }
+ }
+ };
+ }
+ dragTouchTimeout.schedule(TOUCHSCROLL_TIMEOUT);
+ }
+
+ if (actionKeys != null) {
+ if (contextTouchTimeout == null) {
+ contextTouchTimeout = new Timer() {
+
+ @Override
+ public void run() {
+ if (touchStart != null) {
+ // Open the context menu if finger
+ // is held in place long enough.
+ showContextMenu(touchStart);
+ event.preventDefault();
+ touchStart = null;
+ }
+ }
+ };
+ }
+ contextTouchTimeout
+ .schedule(TOUCH_CONTEXT_MENU_TIMEOUT);
+ }
+ break;
+ case Event.ONTOUCHMOVE:
+ touchEventHandled = true;
+ if (isSignificantMove(event)) {
+ 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) {
+ // Moved finger before the drag timer expired,
+ // so let the browser handle this as a scroll.
+ dragTouchTimeout.cancel();
+ dragTouchTimeout = null;
+ }
+
+ if (dragmode != 0 && touchStart != null
+ && isDragging) {
+ event.preventDefault();
+ event.stopPropagation();
+ startRowDrag(touchStart, type, targetTdOrTr);
+ }
+ touchStart = null;
+ }
+ break;
+ case Event.ONTOUCHEND:
+ case Event.ONTOUCHCANCEL:
+ touchEventHandled = true;
+ if (contextTouchTimeout != null) {
+ contextTouchTimeout.cancel();
+ }
+ if (dragTouchTimeout != null) {
+ dragTouchTimeout.cancel();
+ }
+ if (touchStart != null) {
+ event.preventDefault();
+ event.stopPropagation();
+ if (!BrowserInfo.get().isAndroid()) {
+ Util.simulateClickFromTouchEvent(touchStart,
+ this);
+ }
+ touchStart = null;
+ }
+ isDragging = false;
+ break;
+ }
+ }
+ return touchEventHandled;
+ }
+
/*
* React on click that occur on content cells only
*/
+
@Override
public void onBrowserEvent(final Event event) {
- if (enabled) {
+
+ final boolean touchEventHandled = handleTouchEvent(event);
+
+ if (enabled && !touchEventHandled) {
final int type = event.getTypeInt();
final Element targetTdOrTr = getEventTargetTdOrTr(event);
if (type == Event.ONCONTEXTMENU) {
@@ -4823,7 +4965,6 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
break;
case Event.ONMOUSEUP:
if (targetCellOrRowFound) {
- mDown = false;
/*
* Queue here, send at the same time as the
* corresponding value change event - see #7127
@@ -4983,6 +5124,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
touchStart.preventDefault();
if (dragmode != 0 || actionKeys != null) {
new Timer() {
+
@Override
public void run() {
TouchScrollDelegate activeScrollDelegate = TouchScrollDelegate
@@ -5021,6 +5163,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
if (contextTouchTimeout == null
&& actionKeys != null) {
contextTouchTimeout = new Timer() {
+
@Override
public void run() {
if (touchStart != null) {
@@ -5066,9 +5209,6 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
}
break;
case Event.ONMOUSEOUT:
- if (targetCellOrRowFound) {
- mDown = false;
- }
break;
default:
break;
@@ -5098,7 +5238,6 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
protected void startRowDrag(Event event, final int type,
Element targetTdOrTr) {
- mDown = true;
VTransferable transferable = new VTransferable();
transferable.setDragSource(ConnectorMap.get(client)
.getConnector(VScrollTable.this));
@@ -5290,6 +5429,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
*
* @see com.vaadin.terminal.gwt.client.ui.IActionOwner#getActions ()
*/
+
public Action[] getActions() {
if (actionKeys == null) {
return new Action[] {};
@@ -5299,6 +5439,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
final String actionKey = actionKeys[i];
final TreeAction a = new TreeAction(this,
String.valueOf(rowKey), actionKey) {
+
@Override
public void execute() {
super.execute();
@@ -5586,6 +5727,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
* column widths "optimally". Doing this lazily to avoid expensive
* calculation when resizing is not yet finished.
*/
+
@Override
public void run() {
if (scrollBody == null) {
@@ -5682,7 +5824,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
if (isDynamicHeight() && totalRows == pageLength) {
// fix body height (may vary if lazy loading is offhorizontal
// scrollbar appears/disappears)
- int bodyHeight = scrollBody.getRequiredHeight();
+ int bodyHeight = Util.getRequiredHeight(scrollBody);
boolean needsSpaceForHorizontalScrollbar = (availW < usedMinimumWidth);
if (needsSpaceForHorizontalScrollbar) {
bodyHeight += Util.getNativeScrollbarSize();
@@ -5695,6 +5837,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
}
scrollBody.reLayoutComponents();
Scheduler.get().scheduleDeferred(new Command() {
+
public void execute() {
Util.runWebkitOverflowAutoFix(scrollBodyPanel.getElement());
}
@@ -5804,15 +5947,26 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
void updateHeight() {
setContainerHeight();
- updatePageLength();
-
+ if (initializedAndAttached) {
+ updatePageLength();
+ }
if (!rendering) {
// 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
+ // #7607.
+ Scheduler.get().scheduleDeferred(new Command() {
+
+ public void execute() {
+ Util.runWebkitOverflowAutoFix(scrollBodyPanel.getElement());
+ }
+ });
}
+ triggerLazyColumnAdjustment(false);
+
/*
* setting height may affect wheter the component has scrollbars ->
* needs scrolling or not
@@ -5826,6 +5980,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
* lost). Example ITabPanel just set contained components invisible and back
* when changing tabs.
*/
+
@Override
public void setVisible(boolean visible) {
if (isVisible() != visible) {
@@ -5833,6 +5988,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
if (initializedAndAttached) {
if (visible) {
Scheduler.get().scheduleDeferred(new Command() {
+
public void execute() {
scrollBodyPanel
.setScrollPosition(measureRowHeightOffset(firstRowInViewPort));
@@ -5866,6 +6022,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
* This method has logic which rows needs to be requested from server when
* user scrolls
*/
+
public void onScroll(ScrollEvent event) {
scrollLeft = scrollBodyPanel.getElement().getScrollLeft();
scrollTop = scrollBodyPanel.getScrollPosition();
@@ -5894,6 +6051,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
// correct
// value available soon.
Scheduler.get().scheduleDeferred(new Command() {
+
public void execute() {
onScroll(null);
}
@@ -5994,7 +6152,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
return false;
}
- // @Override
+ //
// public int hashCode() {
// return overkey;
// }
@@ -6053,6 +6211,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
deEmphasis();
final TableDDDetails newDetails = dropDetails;
VAcceptCallback cb = new VAcceptCallback() {
+
public void accepted(VDragEvent event) {
if (newDetails.equals(dropDetails)) {
dragAccepted(event);
@@ -6459,6 +6618,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
* com.google.gwt.event.dom.client.FocusHandler#onFocus(com.google.gwt.event
* .dom.client.FocusEvent)
*/
+
public void onFocus(FocusEvent event) {
if (isFocusable()) {
hasFocus = true;
@@ -6479,6 +6639,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
* com.google.gwt.event.dom.client.BlurHandler#onBlur(com.google.gwt.event
* .dom.client.BlurEvent)
*/
+
public void onBlur(BlurEvent event) {
hasFocus = false;
navKeyDown = false;
@@ -6551,6 +6712,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
*
* @see com.vaadin.terminal.gwt.client.Focusable#focus()
*/
+
public void focus() {
if (isFocusable()) {
scrollBodyPanel.focus();
@@ -6594,6 +6756,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
public void startScrollingVelocityTimer() {
if (scrollingVelocityTimer == null) {
scrollingVelocityTimer = new Timer() {
+
@Override
public void run() {
scrollingVelocity++;
@@ -6630,6 +6793,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
public void lazyRevertFocusToRow(final VScrollTableRow currentlyFocusedRow) {
Scheduler.get().scheduleFinally(new ScheduledCommand() {
+
public void execute() {
if (currentlyFocusedRow != null) {
setRowFocus(currentlyFocusedRow);
diff --git a/src/com/vaadin/terminal/gwt/client/ui/tabsheet/VTabsheet.java b/src/com/vaadin/terminal/gwt/client/ui/tabsheet/VTabsheet.java
index c97ede1252..aba5a41f9a 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/tabsheet/VTabsheet.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/tabsheet/VTabsheet.java
@@ -331,6 +331,11 @@ public class VTabsheet extends VTabsheetBase implements Focusable,
}
return width;
}
+
+ public Element getCloseButton() {
+ return closeButton;
+ }
+
}
static class TabBar extends ComplexPanel implements ClickHandler,
@@ -393,7 +398,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()) {
@@ -1021,6 +1033,7 @@ public class VTabsheet extends VTabsheetBase implements Focusable,
final Style style = scroller.getStyle();
style.setProperty("whiteSpace", "normal");
Scheduler.get().scheduleDeferred(new Command() {
+
public void execute() {
style.setProperty("whiteSpace", "");
}
diff --git a/src/com/vaadin/terminal/gwt/client/ui/tabsheet/VTabsheetPanel.java b/src/com/vaadin/terminal/gwt/client/ui/tabsheet/VTabsheetPanel.java
index f2b37c3a1c..bd6cddb682 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/tabsheet/VTabsheetPanel.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/tabsheet/VTabsheetPanel.java
@@ -4,16 +4,12 @@
package com.vaadin.terminal.gwt.client.ui.tabsheet;
-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.ui.TouchScrollDelegate;
+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,38 +23,15 @@ import com.vaadin.terminal.gwt.client.ui.TouchScrollDelegate;
public class VTabsheetPanel extends ComplexPanel {
private Widget visibleWidget;
- private TouchScrollDelegate touchScrollDelegate;
+
+ private final TouchScrollHandler touchScrollHandler;
/**
* Creates an empty tabsheet panel.
*/
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<Node> 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,8 +50,8 @@ public class VTabsheetPanel extends ComplexPanel {
private Element createContainerElement() {
Element el = DOM.createDiv();
DOM.setStyleAttribute(el, "position", "absolute");
- DOM.setStyleAttribute(el, "overflow", "auto");
hide(el);
+ touchScrollHandler.addElement(el);
return el;
}
@@ -122,6 +95,7 @@ public class VTabsheetPanel extends ComplexPanel {
if (parent != null) {
DOM.removeChild(getElement(), parent);
}
+ touchScrollHandler.removeElement(parent);
}
return removed;
}
@@ -141,6 +115,8 @@ public class VTabsheetPanel extends ComplexPanel {
hide(DOM.getParent(visibleWidget.getElement()));
}
visibleWidget = newVisible;
+ touchScrollHandler.setElements(visibleWidget.getElement()
+ .getParentElement());
}
// Always ensure the selected tab is visible. If server prevents a tab
// change we might end up here with visibleWidget == newVisible but its
diff --git a/src/com/vaadin/terminal/gwt/client/ui/treetable/VTreeTable.java b/src/com/vaadin/terminal/gwt/client/ui/treetable/VTreeTable.java
index f7cd9d133e..9a8e0e9ce1 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/treetable/VTreeTable.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/treetable/VTreeTable.java
@@ -379,26 +379,34 @@ 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<VScrollTableRow> insertRowsAnimated(UIDL rowData,
int firstIndex, int rows) {
List<VScrollTableRow> 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;
}
@@ -521,6 +529,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<VScrollTableRow> rows) {
this.rows = rows;
buildAndInsertAnimatingDiv();
@@ -641,6 +653,10 @@ public class VTreeTable extends VScrollTable {
private final List<VScrollTableRow> rows;
+ /**
+ * @param rows
+ * List of rows to animate. Must not be empty.
+ */
public RowCollapseAnimation(List<VScrollTableRow> rows) {
super(rows);
this.rows = rows;
diff --git a/src/com/vaadin/terminal/gwt/client/ui/window/VWindow.java b/src/com/vaadin/terminal/gwt/client/ui/window/VWindow.java
index d08387fc6d..8fd84a9ea6 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/window/VWindow.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/window/VWindow.java
@@ -40,6 +40,7 @@ import com.vaadin.terminal.gwt.client.ui.ShortcutActionHandler;
import com.vaadin.terminal.gwt.client.ui.ShortcutActionHandler.ShortcutActionHandlerOwner;
import com.vaadin.terminal.gwt.client.ui.VLazyExecutor;
import com.vaadin.terminal.gwt.client.ui.VOverlay;
+import com.vaadin.terminal.gwt.client.ui.notification.VNotification;
/**
* "Sub window" component.
@@ -264,8 +265,10 @@ public class VWindow extends VOverlay implements ShortcutActionHandlerOwner,
if (!orderingDefered) {
orderingDefered = true;
Scheduler.get().scheduleFinally(new Command() {
+
public void execute() {
doServerSideOrdering();
+ VNotification.bringNotificationsToFront();
}
});
}
@@ -275,6 +278,7 @@ public class VWindow extends VOverlay implements ShortcutActionHandlerOwner,
orderingDefered = false;
VWindow[] array = windowOrder.toArray(new VWindow[windowOrder.size()]);
Arrays.sort(array, new Comparator<VWindow>() {
+
public int compare(VWindow o1, VWindow o2) {
/*
* Order by modality, then by bringtofront sequence.
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 1acc9d128a..c2f887674a 100644
--- a/src/com/vaadin/terminal/gwt/server/AbstractApplicationPortlet.java
+++ b/src/com/vaadin/terminal/gwt/server/AbstractApplicationPortlet.java
@@ -64,10 +64,7 @@ import com.vaadin.ui.Root;
public abstract class AbstractApplicationPortlet extends GenericPortlet
implements Constants {
- 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 +109,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 +131,7 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet
}
}
- private static class WrappedLiferayRequest extends
+ public static class WrappedLiferayRequest extends
WrappedHttpAndPortletRequest {
public WrappedLiferayRequest(PortletRequest request,
@@ -169,7 +166,7 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet
}
- private static class AbstractApplicationPortletWrapper implements Callback {
+ public static class AbstractApplicationPortletWrapper implements Callback {
private final AbstractApplicationPortlet portlet;
@@ -203,6 +200,8 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet
*/
public 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
@@ -213,6 +212,7 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet
private boolean productionMode = false;
private DeploymentConfiguration deploymentConfiguration = new DeploymentConfiguration() {
+
public String getConfiguredWidgetset(WrappedRequest request) {
String widgetset = getApplicationOrSystemProperty(
@@ -271,6 +271,7 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet
* @return The location of static resources (inside which there should
* be a VAADIN directory). Does not end with a slash (/).
*/
+
public String getStaticFileLocation(WrappedRequest request) {
String staticFileLocation = WrappedPortletRequest.cast(request)
.getPortalProperty(
@@ -329,7 +330,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);
}
}
@@ -345,7 +346,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);
}
}
@@ -500,20 +501,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());
@@ -552,7 +540,7 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet
if (application == null) {
return;
}
- Application.setCurrentApplication(application);
+ Application.setCurrent(application);
/*
* Get or create an application context and an application
@@ -650,7 +638,7 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet
/* Handle the request */
if (requestType == RequestType.FILE_UPLOAD) {
- applicationManager.handleFileUpload(wrappedRequest,
+ applicationManager.handleFileUpload(root, wrappedRequest,
wrappedResponse);
return;
} else if (requestType == RequestType.BROWSER_DETAILS) {
@@ -678,11 +666,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 {
@@ -700,25 +689,51 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet
}
} finally {
- Root.setCurrentRoot(null);
- Application.setCurrentApplication(null);
+ Root.setCurrent(null);
+ Application.setCurrent(null);
- requestTimer
- .stop((AbstractWebApplicationContext) application
- .getContext());
+ PortletSession session = request
+ .getPortletSession(false);
+ if (session != null) {
+ requestTimer.stop(getApplicationContext(session));
+ }
}
}
}
}
}
+ /**
+ * 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;
}
private void handleUnknownRequest(PortletRequest request,
PortletResponse response) {
- logger.warning("Unknown request type");
+ getLogger().warning("Unknown request type");
}
/**
@@ -784,8 +799,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));
}
@@ -1130,4 +1146,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 905cfe7e3c..f7e46a7ca9 100644
--- a/src/com/vaadin/terminal/gwt/server/AbstractApplicationServlet.java
+++ b/src/com/vaadin/terminal/gwt/server/AbstractApplicationServlet.java
@@ -87,9 +87,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());
-
private Properties applicationProperties;
private boolean productionMode = false;
@@ -99,6 +96,7 @@ public abstract class AbstractApplicationServlet extends HttpServlet implements
private int resourceCacheTime = 3600;
private DeploymentConfiguration deploymentConfiguration = new DeploymentConfiguration() {
+
public String getStaticFileLocation(WrappedRequest request) {
HttpServletRequest servletRequest = WrappedHttpServletRequest
.cast(request);
@@ -149,8 +147,8 @@ public abstract class AbstractApplicationServlet extends HttpServlet implements
* if an exception has occurred that interferes with the
* servlet's normal operation.
*/
- @SuppressWarnings("unchecked")
@Override
+ @SuppressWarnings("unchecked")
public void init(javax.servlet.ServletConfig servletConfig)
throws javax.servlet.ServletException {
super.init(servletConfig);
@@ -186,7 +184,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);
}
}
@@ -200,7 +198,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);
}
}
@@ -214,7 +212,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);
}
}
@@ -333,6 +331,7 @@ public abstract class AbstractApplicationServlet extends HttpServlet implements
* @throws IOException
* if the request for the TRACE cannot be handled.
*/
+
@Override
protected void service(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
@@ -386,7 +385,7 @@ public abstract class AbstractApplicationServlet extends HttpServlet implements
if (application == null) {
return;
}
- Application.setCurrentApplication(application);
+ Application.setCurrent(application);
/*
* Get or create a WebApplicationContext and an ApplicationManager
@@ -422,25 +421,29 @@ public abstract class AbstractApplicationServlet extends HttpServlet implements
/* Handle the request */
if (requestType == RequestType.FILE_UPLOAD) {
- applicationManager.handleFileUpload(application, request,
- response);
+ Root root = application.getRootForRequest(request);
+ if (root == null) {
+ throw new ServletException(ERROR_NO_ROOT_FOUND);
+ }
+ applicationManager.handleFileUpload(root, request, response);
return;
} else if (requestType == RequestType.UIDL) {
- // Handles AJAX UIDL requests
Root root = application.getRootForRequest(request);
if (root == null) {
- throw new ServletException(ERROR_NO_WINDOW_FOUND);
+ throw new ServletException(ERROR_NO_ROOT_FOUND);
}
+ // Handles AJAX UIDL requests
applicationManager.handleUidlRequest(request, response,
servletWrapper, root);
return;
} else if (requestType == RequestType.BROWSER_DETAILS) {
+ // Browser details - not related to a specific root
applicationManager.handleBrowserDetailsRequest(request,
response, application);
return;
}
- // Removes application if it has stopped (mayby by thread or
+ // Removes application if it has stopped (maybe by thread or
// transactionlistener)
if (!application.isRunning()) {
endApplication(request, response, application);
@@ -475,12 +478,13 @@ public abstract class AbstractApplicationServlet extends HttpServlet implements
.onRequestEnd(request, response);
}
} finally {
- Root.setCurrentRoot(null);
- Application.setCurrentApplication(null);
+ Root.setCurrent(null);
+ Application.setCurrent(null);
- requestTimer
- .stop((AbstractWebApplicationContext) application
- .getContext());
+ HttpSession session = request.getSession(false);
+ if (session != null) {
+ requestTimer.stop(getApplicationContext(session));
+ }
}
}
@@ -796,8 +800,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;
@@ -1054,10 +1058,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;
}
@@ -1065,9 +1070,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;
}
@@ -1090,10 +1096,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);
} finally {
if (connection instanceof URLConnection) {
try {
@@ -1105,7 +1111,7 @@ public abstract class AbstractApplicationServlet extends HttpServlet implements
is.close();
}
} catch (IOException e) {
- logger.log(Level.INFO,
+ getLogger().log(Level.INFO,
"Error closing URLConnection input stream", e);
}
}
@@ -1130,7 +1136,7 @@ public abstract class AbstractApplicationServlet extends HttpServlet implements
* parameter in web.xml
*/
response.setHeader("Cache-Control",
- "max-age: " + String.valueOf(resourceCacheTime));
+ "max-age= " + String.valueOf(resourceCacheTime));
}
// Write the resource to the client.
@@ -1173,12 +1179,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:)
@@ -1188,11 +1196,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;
}
}
@@ -1733,4 +1743,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 c08d70aa37..7cad8e3a33 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;
@@ -67,14 +68,15 @@ 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.terminal.gwt.server.RpcManager.RpcInvocationException;
import com.vaadin.ui.AbstractComponent;
import com.vaadin.ui.AbstractField;
import com.vaadin.ui.Component;
-import com.vaadin.ui.DirtyConnectorTracker;
+import com.vaadin.ui.ConnectorTracker;
import com.vaadin.ui.HasComponents;
-import com.vaadin.ui.Panel;
import com.vaadin.ui.Root;
import com.vaadin.ui.Window;
@@ -91,9 +93,6 @@ public abstract class AbstractCommunicationManager implements Serializable {
private static final String DASHDASH = "--";
- private static final Logger logger = Logger
- .getLogger(AbstractCommunicationManager.class.getName());
-
private static final RequestHandler APP_RESOURCE_HANDLER = new ApplicationResourceHandler();
private static final RequestHandler UNSUPPORTED_BROWSER_HANDLER = new UnsupportedBrowserHandler();
@@ -136,6 +135,9 @@ public abstract class AbstractCommunicationManager implements Serializable {
private static final String GET_PARAM_ANALYZE_LAYOUTS = "analyzeLayouts";
+ /**
+ * The application this communication manager is used for
+ */
private final Application application;
private List<String> locales;
@@ -519,7 +521,8 @@ public abstract class AbstractCommunicationManager implements Serializable {
if (request.getParameter(GET_PARAM_HIGHLIGHT_COMPONENT) != null) {
String pid = request
.getParameter(GET_PARAM_HIGHLIGHT_COMPONENT);
- highlightedConnector = root.getApplication().getConnector(pid);
+ highlightedConnector = root.getConnectorTracker().getConnector(
+ pid);
highlightConnector(highlightedConnector);
}
}
@@ -538,7 +541,7 @@ public abstract class AbstractCommunicationManager implements Serializable {
if (root == null) {
// This should not happen, no windows exists but
// application is still open.
- logger.warning("Could not get root for application");
+ getLogger().warning("Could not get root for application");
return;
}
} else {
@@ -561,7 +564,7 @@ public abstract class AbstractCommunicationManager implements Serializable {
// 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) {
@@ -603,8 +606,9 @@ public abstract class AbstractCommunicationManager implements Serializable {
}
if (!Version.getFullVersion().equals(widgetsetVersion)) {
- logger.warning(String.format(Constants.WIDGETSET_MISMATCH_INFO,
- Version.getFullVersion(), widgetsetVersion));
+ getLogger().warning(
+ String.format(Constants.WIDGETSET_MISMATCH_INFO,
+ Version.getFullVersion(), widgetsetVersion));
}
}
@@ -618,7 +622,7 @@ public abstract class AbstractCommunicationManager implements Serializable {
protected void postPaint(Root root) {
// Remove connectors that have been detached from the application during
// handling of the request
- root.getApplication().cleanConnectorMap();
+ root.getConnectorTracker().cleanConnectorMap();
}
protected void highlightConnector(Connector highlightedConnector) {
@@ -637,7 +641,7 @@ public abstract class AbstractCommunicationManager implements Serializable {
printHighlightedComponentHierarchy(sb, component);
}
- logger.info(sb.toString());
+ getLogger().info(sb.toString());
}
protected void printHighlightedComponentHierarchy(StringBuilder sb,
@@ -764,12 +768,11 @@ public abstract class AbstractCommunicationManager implements Serializable {
ArrayList<ClientConnector> dirtyVisibleConnectors = new ArrayList<ClientConnector>();
Application application = root.getApplication();
// Paints components
- DirtyConnectorTracker rootConnectorTracker = root
- .getDirtyConnectorTracker();
- logger.log(Level.FINE, "* Creating response to client");
+ ConnectorTracker rootConnectorTracker = root.getConnectorTracker();
+ getLogger().log(Level.FINE, "* Creating response to client");
if (repaintAll) {
getClientCache(root).clear();
- rootConnectorTracker.markAllComponentsDirty();
+ rootConnectorTracker.markAllConnectorsDirty();
// Reset sent locales
locales = null;
@@ -777,16 +780,18 @@ public abstract class AbstractCommunicationManager implements Serializable {
}
dirtyVisibleConnectors
- .addAll(getDirtyVisibleComponents(rootConnectorTracker));
+ .addAll(getDirtyVisibleConnectors(rootConnectorTracker));
- logger.log(Level.FINE, "Found " + dirtyVisibleConnectors.size()
- + " dirty connectors to paint");
+ getLogger().log(
+ Level.FINE,
+ "Found " + dirtyVisibleConnectors.size()
+ + " dirty connectors to paint");
for (ClientConnector connector : dirtyVisibleConnectors) {
if (connector instanceof Component) {
((Component) connector).updateState();
}
}
- rootConnectorTracker.markAllComponentsClean();
+ rootConnectorTracker.markAllConnectorsClean();
outWriter.print("\"changes\":[");
@@ -840,16 +845,16 @@ public abstract class AbstractCommunicationManager implements Serializable {
try {
referenceState = stateType.newInstance();
} catch (Exception e) {
- logger.log(Level.WARNING,
+ getLogger().log(
+ Level.WARNING,
"Error creating reference object for state of type "
+ stateType.getName());
}
}
- JSONArray stateJsonArray = JsonCodec.encode(state,
- referenceState, stateType, application);
+ Object stateJson = JsonCodec.encode(state, referenceState,
+ stateType, root.getConnectorTracker());
- sharedStates
- .put(connector.getConnectorId(), stateJsonArray);
+ sharedStates.put(connector.getConnectorId(), stateJson);
} catch (JSONException e) {
throw new PaintException(
"Failed to serialize shared state for connector "
@@ -893,26 +898,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
+ .getAllChildrenIterable(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
@@ -937,7 +940,7 @@ public abstract class AbstractCommunicationManager implements Serializable {
invocationJson.put(invocation.getMethodName());
JSONArray paramJson = new JSONArray();
for (int i = 0; i < invocation.getParameterTypes().length; ++i) {
- Class<?> parameterType = invocation.getParameterTypes()[i];
+ Type parameterType = invocation.getParameterTypes()[i];
Object referenceParameter = null;
// TODO Use default values for RPC parameter types
// if (!JsonCodec.isInternalType(parameterType)) {
@@ -951,7 +954,7 @@ public abstract class AbstractCommunicationManager implements Serializable {
// }
paramJson.put(JsonCodec.encode(
invocation.getParameters()[i], referenceParameter,
- parameterType, application));
+ parameterType, root.getConnectorTracker()));
}
invocationJson.put(paramJson);
rpcCalls.put(invocationJson);
@@ -1008,16 +1011,16 @@ public abstract class AbstractCommunicationManager implements Serializable {
(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);
}
@@ -1056,8 +1059,8 @@ public abstract class AbstractCommunicationManager implements Serializable {
is = getThemeResourceAsStream(root, getTheme(root), 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) {
@@ -1076,13 +1079,13 @@ public abstract class AbstractCommunicationManager implements Serializable {
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("}");
@@ -1173,8 +1176,9 @@ public abstract class AbstractCommunicationManager implements Serializable {
}
sortByHierarchy((List) legacyComponents);
for (Vaadin6Component c : legacyComponents) {
- logger.fine("Painting Vaadin6Component " + c.getClass().getName()
- + "@" + Integer.toHexString(c.hashCode()));
+ getLogger().fine(
+ "Painting Vaadin6Component " + c.getClass().getName() + "@"
+ + Integer.toHexString(c.hashCode()));
paintTarget.startTag("change");
final String pid = c.getConnectorId();
paintTarget.addAttribute("pid", pid);
@@ -1189,6 +1193,7 @@ public abstract class AbstractCommunicationManager implements Serializable {
// containers rely on that their updateFromUIDL method has been called
// before children start calling e.g. updateCaption
Collections.sort(paintables, new Comparator<Component>() {
+
public int compare(Component c1, Component c2) {
int depth1 = 0;
while (c1.getParent() != null) {
@@ -1223,6 +1228,30 @@ public abstract class AbstractCommunicationManager implements Serializable {
}
/**
+ * 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 <code>true</code> if the connector is visible to the client,
+ * <code>false</code> 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
* not be rendered (using
@@ -1233,9 +1262,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);
@@ -1256,30 +1293,6 @@ public abstract class AbstractCommunicationManager implements Serializable {
}
- public static Iterable<Component> getChildComponents(HasComponents cc) {
- // TODO This must be moved to Root/Panel
- if (cc instanceof Root) {
- Root root = (Root) cc;
- List<Component> children = new ArrayList<Component>();
- 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.
@@ -1402,7 +1415,7 @@ public abstract class AbstractCommunicationManager implements Serializable {
for (int bi = 1; bi < bursts.length; bi++) {
// unescape any encoded separator characters in the burst
final String burst = unescapeBurst(bursts[bi]);
- success &= handleBurst(request, application2, burst);
+ success &= handleBurst(request, root, burst);
// In case that there were multiple bursts, we know that this is
// a special synchronous case for closing window. Thus we are
@@ -1444,36 +1457,38 @@ public abstract class AbstractCommunicationManager implements Serializable {
* directly.
*
* @param source
- * @param app
- * application receiving the burst
+ * @param root
+ * the root receiving the burst
* @param burst
* the content of the burst as a String to be parsed
* @return true if the processing of the burst was successful and there were
* no messages to non-existent components
*/
- public boolean handleBurst(Object source, Application app,
+ public boolean handleBurst(WrappedRequest source, Root root,
final String burst) {
boolean success = true;
try {
Set<Connector> enabledConnectors = new HashSet<Connector>();
- List<MethodInvocation> invocations = parseInvocations(burst);
+ List<MethodInvocation> invocations = parseInvocations(
+ root.getConnectorTracker(), burst);
for (MethodInvocation invocation : invocations) {
- final ClientConnector connector = getConnector(app,
+ final ClientConnector connector = getConnector(root,
invocation.getConnectorId());
if (connector != null && connector.isConnectorEnabled()) {
enabledConnectors.add(connector);
}
}
+
for (int i = 0; i < invocations.size(); i++) {
MethodInvocation invocation = invocations.get(i);
- final ClientConnector connector = getConnector(app,
+ final ClientConnector connector = getConnector(root,
invocation.getConnectorId());
if (connector == null) {
- logger.log(
+ getLogger().log(
Level.WARNING,
"RPC call to " + invocation.getInterfaceName()
+ "." + invocation.getMethodName()
@@ -1511,13 +1526,23 @@ public abstract class AbstractCommunicationManager implements Serializable {
msg += ", caption=" + caption;
}
}
- logger.warning(msg);
+ getLogger().warning(msg);
continue;
}
if (invocation instanceof ServerRpcMethodInvocation) {
- ServerRpcManager.applyInvocation(connector,
- (ServerRpcMethodInvocation) invocation);
+ try {
+ ServerRpcManager.applyInvocation(connector,
+ (ServerRpcMethodInvocation) invocation);
+ } catch (RpcInvocationException e) {
+ Throwable realException = e.getCause();
+ Component errorComponent = null;
+ if (connector instanceof Component) {
+ errorComponent = (Component) connector;
+ }
+ handleChangeVariablesError(root.getApplication(),
+ errorComponent, realException, null);
+ }
} else {
// All code below is for legacy variable changes
@@ -1525,8 +1550,18 @@ public abstract class AbstractCommunicationManager implements Serializable {
Map<String, Object> changes = legacyInvocation
.getVariableChanges();
try {
- changeVariables(source, (VariableOwner) connector,
- changes);
+ if (connector instanceof VariableOwner) {
+ changeVariables(source, (VariableOwner) connector,
+ changes);
+ } else {
+ throw new IllegalStateException(
+ "Received legacy variable change for "
+ + connector.getClass().getName()
+ + " ("
+ + connector.getConnectorId()
+ + ") which is not a VariableOwner. The client-side connector sent these legacy varaibles: "
+ + changes.keySet());
+ }
} catch (Exception e) {
Component errorComponent = null;
if (connector instanceof Component) {
@@ -1537,16 +1572,15 @@ public abstract class AbstractCommunicationManager implements Serializable {
errorComponent = (Component) dropHandlerOwner;
}
}
- handleChangeVariablesError(app, errorComponent, e,
- changes);
-
+ handleChangeVariablesError(root.getApplication(),
+ errorComponent, e, changes);
}
}
}
-
} catch (JSONException e) {
- logger.warning("Unable to parse RPC call from the client: "
- + e.getMessage());
+ getLogger().warning(
+ "Unable to parse RPC call from the client: "
+ + e.getMessage());
// TODO or return success = false?
throw new RuntimeException(e);
}
@@ -1558,12 +1592,15 @@ public abstract class AbstractCommunicationManager implements Serializable {
* Parse a message burst from the client into a list of MethodInvocation
* instances.
*
+ * @param connectorTracker
+ * The ConnectorTracker used to lookup connectors
* @param burst
* message string (JSON)
* @return list of MethodInvocation to perform
* @throws JSONException
*/
- private List<MethodInvocation> parseInvocations(final String burst)
+ private List<MethodInvocation> parseInvocations(
+ ConnectorTracker connectorTracker, final String burst)
throws JSONException {
JSONArray invocationsJson = new JSONArray(burst);
@@ -1576,7 +1613,7 @@ public abstract class AbstractCommunicationManager implements Serializable {
JSONArray invocationJson = invocationsJson.getJSONArray(i);
MethodInvocation invocation = parseInvocation(invocationJson,
- previousInvocation);
+ previousInvocation, connectorTracker);
if (invocation != null) {
// Can be null iff the invocation was a legacy invocation and it
// was merged with the previous one
@@ -1588,7 +1625,8 @@ public abstract class AbstractCommunicationManager implements Serializable {
}
private MethodInvocation parseInvocation(JSONArray invocationJson,
- MethodInvocation previousInvocation) throws JSONException {
+ MethodInvocation previousInvocation,
+ ConnectorTracker connectorTracker) throws JSONException {
String connectorId = invocationJson.getString(0);
String interfaceName = invocationJson.getString(1);
String methodName = invocationJson.getString(2);
@@ -1604,10 +1642,10 @@ public abstract class AbstractCommunicationManager implements Serializable {
return parseLegacyChangeVariablesInvocation(connectorId,
interfaceName, methodName,
(LegacyChangeVariablesInvocation) previousInvocation,
- parametersJson);
+ parametersJson, connectorTracker);
} else {
return parseServerRpcInvocation(connectorId, interfaceName,
- methodName, parametersJson);
+ methodName, parametersJson, connectorTracker);
}
}
@@ -1615,17 +1653,18 @@ public abstract class AbstractCommunicationManager implements Serializable {
private LegacyChangeVariablesInvocation parseLegacyChangeVariablesInvocation(
String connectorId, String interfaceName, String methodName,
LegacyChangeVariablesInvocation previousInvocation,
- JSONArray parametersJson) throws JSONException {
+ JSONArray parametersJson, ConnectorTracker connectorTracker)
+ throws JSONException {
if (parametersJson.length() != 2) {
throw new JSONException(
"Invalid parameters in legacy change variables call. Expected 2, was "
+ parametersJson.length());
}
- String variableName = (String) JsonCodec
- .decodeInternalType(String.class, true,
- parametersJson.getJSONArray(0), application);
- Object value = JsonCodec.decodeInternalType(
- parametersJson.getJSONArray(1), application);
+ String variableName = parametersJson.getString(0);
+ UidlValue uidlValue = (UidlValue) JsonCodec.decodeInternalType(
+ UidlValue.class, true, parametersJson.get(1), connectorTracker);
+
+ Object value = uidlValue.getValue();
if (previousInvocation != null
&& previousInvocation.getConnectorId().equals(connectorId)) {
@@ -1639,7 +1678,8 @@ public abstract class AbstractCommunicationManager implements Serializable {
private ServerRpcMethodInvocation parseServerRpcInvocation(
String connectorId, String interfaceName, String methodName,
- JSONArray parametersJson) throws JSONException {
+ JSONArray parametersJson, ConnectorTracker connectorTracker)
+ throws JSONException {
ServerRpcMethodInvocation invocation = new ServerRpcMethodInvocation(
connectorId, interfaceName, methodName, parametersJson.length());
@@ -1648,10 +1688,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, connectorTracker);
}
invocation.setParameters(parameters);
return invocation;
@@ -1662,8 +1702,9 @@ public abstract class AbstractCommunicationManager implements Serializable {
owner.changeVariables(source, m);
}
- protected ClientConnector getConnector(Application app, String connectorId) {
- ClientConnector c = app.getConnector(connectorId);
+ protected ClientConnector getConnector(Root root, String connectorId) {
+ ClientConnector c = root.getConnectorTracker()
+ .getConnector(connectorId);
if (c == null
&& connectorId.equals(getDragAndDropService().getConnectorId())) {
return getDragAndDropService();
@@ -1745,10 +1786,10 @@ public abstract class AbstractCommunicationManager implements Serializable {
* map from variable names to values
*/
private void handleChangeVariablesError(Application application,
- Component owner, Exception e, Map<String, Object> m) {
+ Component owner, Throwable t, Map<String, Object> m) {
boolean handled = false;
ChangeVariablesErrorEvent errorEvent = new ChangeVariablesErrorEvent(
- owner, e, m);
+ owner, t, m);
if (owner instanceof AbstractField) {
try {
@@ -1889,8 +1930,9 @@ public abstract class AbstractCommunicationManager implements Serializable {
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();
@@ -2016,16 +2058,16 @@ public abstract class AbstractCommunicationManager implements Serializable {
* root window for which dirty components is to be fetched
* @return
*/
- private ArrayList<Component> getDirtyVisibleComponents(
- DirtyConnectorTracker dirtyConnectorTracker) {
- ArrayList<Component> dirtyComponents = new ArrayList<Component>();
- for (Component c : dirtyConnectorTracker.getDirtyComponents()) {
+ private ArrayList<ClientConnector> getDirtyVisibleConnectors(
+ ConnectorTracker connectorTracker) {
+ ArrayList<ClientConnector> dirtyConnectors = new ArrayList<ClientConnector>();
+ for (ClientConnector c : connectorTracker.getDirtyConnectors()) {
if (isVisible(c)) {
- dirtyComponents.add(c);
+ dirtyConnectors.add(c);
}
}
- return dirtyComponents;
+ return dirtyConnectors;
}
/**
@@ -2089,7 +2131,8 @@ public abstract class AbstractCommunicationManager implements Serializable {
if (id == null) {
id = nextTypeKey++;
typeToKey.put(class1, id);
- logger.log(Level.FINE, "Mapping " + class1.getName() + " to " + id);
+ getLogger().log(Level.FINE,
+ "Mapping " + class1.getName() + " to " + id);
}
return id.toString();
}
@@ -2151,7 +2194,7 @@ public abstract class AbstractCommunicationManager implements Serializable {
// if we do not yet have a currentRoot, it should be initialized
// shortly, and we should send the initial UIDL
- boolean sendUIDL = Root.getCurrentRoot() == null;
+ boolean sendUIDL = Root.getCurrent() == null;
try {
CombinedRequest combinedRequest = new CombinedRequest(request);
@@ -2226,7 +2269,7 @@ public abstract class AbstractCommunicationManager implements Serializable {
writeUidlResponse(request, true, pWriter, root, false);
pWriter.print("}");
String initialUIDL = sWriter.toString();
- logger.log(Level.FINE, "Initial UIDL:" + initialUIDL);
+ getLogger().log(Level.FINE, "Initial UIDL:" + initialUIDL);
return initialUIDL;
}
@@ -2380,4 +2423,7 @@ public abstract class AbstractCommunicationManager implements Serializable {
}
}
+ 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<TransactionListener> listeners = Collections
.synchronizedList(new LinkedList<TransactionListener>());
@@ -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/BootstrapHandler.java b/src/com/vaadin/terminal/gwt/server/BootstrapHandler.java
index 8a0c700121..69f033c8cd 100644
--- a/src/com/vaadin/terminal/gwt/server/BootstrapHandler.java
+++ b/src/com/vaadin/terminal/gwt/server/BootstrapHandler.java
@@ -9,6 +9,10 @@ import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Serializable;
import java.io.Writer;
+import java.lang.annotation.Annotation;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletResponse;
@@ -16,6 +20,7 @@ import javax.servlet.http.HttpServletResponse;
import com.vaadin.Application;
import com.vaadin.RootRequiresMoreInformationException;
import com.vaadin.Version;
+import com.vaadin.annotations.LoadScripts;
import com.vaadin.external.json.JSONException;
import com.vaadin.external.json.JSONObject;
import com.vaadin.terminal.DeploymentConfiguration;
@@ -78,7 +83,7 @@ public abstract class BootstrapHandler implements RequestHandler {
public Root getRoot() {
if (!rootFetched) {
- root = Root.getCurrentRoot();
+ root = Root.getCurrent();
rootFetched = true;
}
return root;
@@ -467,15 +472,15 @@ public abstract class BootstrapHandler implements RequestHandler {
page.write("<meta http-equiv=\"X-UA-Compatible\" content=\"chrome=1\"/>\n");
page.write("<style type=\"text/css\">"
- + "html, body {height:100%;margin:0;}</style>");
+ + "html, body {height:100%;margin:0;}</style>\n");
// Add favicon links
if (themeName != null) {
String themeUri = getThemeUri(context, themeName);
page.write("<link rel=\"shortcut icon\" type=\"image/vnd.microsoft.icon\" href=\""
- + themeUri + "/favicon.ico\" />");
+ + themeUri + "/favicon.ico\" />\n");
page.write("<link rel=\"icon\" type=\"image/vnd.microsoft.icon\" href=\""
- + themeUri + "/favicon.ico\" />");
+ + themeUri + "/favicon.ico\" />\n");
}
Root root = context.getRoot();
@@ -484,7 +489,51 @@ public abstract class BootstrapHandler implements RequestHandler {
page.write("<title>"
+ AbstractApplicationServlet.safeEscapeForHtml(title)
- + "</title>");
+ + "</title>\n");
+
+ if (root != null) {
+ List<LoadScripts> loadScriptsAnnotations = getAnnotationsFor(
+ root.getClass(), LoadScripts.class);
+ Collections.reverse(loadScriptsAnnotations);
+ // Begin from the end as a class might requests scripts that depend
+ // on script loaded by a super class
+ for (int i = loadScriptsAnnotations.size() - 1; i >= 0; i--) {
+ LoadScripts loadScripts = loadScriptsAnnotations.get(i);
+ String[] value = loadScripts.value();
+ if (value != null) {
+ for (String script : value) {
+ page.write("<script type='text/javascript' src='");
+ page.write(script);
+ page.write("'></script>\n");
+ }
+ }
+ }
+
+ }
+ }
+
+ private static <T extends Annotation> List<T> getAnnotationsFor(
+ Class<?> type, Class<T> annotationType) {
+ List<T> list = new ArrayList<T>();
+ // Find from the class hierarchy
+ Class<?> currentType = type;
+ while (currentType != Object.class) {
+ T annotation = currentType.getAnnotation(annotationType);
+ if (annotation != null) {
+ list.add(annotation);
+ }
+ currentType = currentType.getSuperclass();
+ }
+
+ // Find from an implemented interface
+ for (Class<?> iface : type.getInterfaces()) {
+ T annotation = iface.getAnnotation(annotationType);
+ if (annotation != null) {
+ list.add(annotation);
+ }
+ }
+
+ return list;
}
/**
diff --git a/src/com/vaadin/terminal/gwt/server/ClientConnector.java b/src/com/vaadin/terminal/gwt/server/ClientConnector.java
index 7e74c26fb1..dfdd58879d 100644
--- a/src/com/vaadin/terminal/gwt/server/ClientConnector.java
+++ b/src/com/vaadin/terminal/gwt/server/ClientConnector.java
@@ -3,10 +3,15 @@
*/
package com.vaadin.terminal.gwt.server;
+import java.util.Collection;
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;
/**
* Interface implemented by all connectors that are capable of communicating
@@ -24,8 +29,6 @@ public interface ClientConnector extends Connector, RpcTarget {
*
* @return an unmodifiable ordered list of pending server to client method
* calls (not null)
- *
- * @since 7.0
*/
public List<ClientMethodInvocation> retrievePendingRpcCalls();
@@ -44,4 +47,93 @@ public interface ClientConnector extends Connector, RpcTarget {
*/
public Class<? extends SharedState> 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 an ancestor.
+ */
+ public void requestRepaintAll();
+
+ /**
+ * Sets the parent connector of the connector.
+ *
+ * <p>
+ * This method automatically calls {@link #attach()} if the connector
+ * 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.
+ * </p>
+ * <p>
+ * This method is rarely called directly. One of the
+ * {@link ComponentContainer#addComponent(Component)} or
+ * {@link AbstractClientConnector#addExtension(Extension)} methods are
+ * normally used for adding connectors to a parent and they will call this
+ * method implicitly.
+ * </p>
+ *
+ * <p>
+ * It is not possible to change the parent without first setting the parent
+ * to {@code null}.
+ * </p>
+ *
+ * @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.
+ *
+ * <p>
+ * 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's
+ * data is sent to the client-side for the first time.
+ * </p>
+ *
+ * <p>
+ * The attachment logic is implemented in {@link AbstractClientConnector}.
+ * </p>
+ */
+ public void attach();
+
+ /**
+ * Notifies the component that it is detached from the application.
+ *
+ * <p>
+ * The caller of this method is {@link #setParent(ClientConnector)} 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.
+ * </p>
+ */
+ public void detach();
+
+ /**
+ * Get a read-only collection of all extensions attached to this connector.
+ *
+ * @return a collection of extensions
+ */
+ public Collection<Extension> getExtensions();
+
+ /**
+ * Remove an extension from this connector.
+ *
+ * @param extension
+ * the extension to remove.
+ */
+ public void removeExtension(Extension extension);
}
diff --git a/src/com/vaadin/terminal/gwt/server/ClientMethodInvocation.java b/src/com/vaadin/terminal/gwt/server/ClientMethodInvocation.java
index 99633a13d6..ad9484723b 100644
--- a/src/com/vaadin/terminal/gwt/server/ClientMethodInvocation.java
+++ b/src/com/vaadin/terminal/gwt/server/ClientMethodInvocation.java
@@ -6,6 +6,7 @@ package com.vaadin.terminal.gwt.server;
import java.io.Serializable;
import java.lang.reflect.Method;
+import java.lang.reflect.Type;
/**
* Internal class for keeping track of pending server to client method
@@ -19,7 +20,7 @@ public class ClientMethodInvocation implements Serializable,
private final String interfaceName;
private final String methodName;
private final Object[] parameters;
- private Class<?>[] parameterTypes;
+ private Type[] parameterTypes;
// used for sorting calls between different connectors in the same Root
private final long sequenceNumber;
@@ -31,12 +32,12 @@ public class ClientMethodInvocation implements Serializable,
this.connector = connector;
this.interfaceName = interfaceName;
methodName = method.getName();
- parameterTypes = method.getParameterTypes();
+ parameterTypes = method.getGenericParameterTypes();
this.parameters = (null != parameters) ? parameters : new Object[0];
sequenceNumber = ++counter;
}
- public Class<?>[] getParameterTypes() {
+ public Type[] getParameterTypes() {
return parameterTypes;
}
diff --git a/src/com/vaadin/terminal/gwt/server/CommunicationManager.java b/src/com/vaadin/terminal/gwt/server/CommunicationManager.java
index 3dd2eb97fd..cc2981dc45 100644
--- a/src/com/vaadin/terminal/gwt/server/CommunicationManager.java
+++ b/src/com/vaadin/terminal/gwt/server/CommunicationManager.java
@@ -61,7 +61,8 @@ public class CommunicationManager extends AbstractCommunicationManager {
/**
* Handles file upload request submitted via Upload component.
*
- * @param application
+ * @param root
+ * The root for this request
*
* @see #getStreamVariableTargetUrl(ReceiverOwner, String, StreamVariable)
*
@@ -70,9 +71,9 @@ public class CommunicationManager extends AbstractCommunicationManager {
* @throws IOException
* @throws InvalidUIDLSecurityKeyException
*/
- public void handleFileUpload(Application application,
- WrappedRequest request, WrappedResponse response)
- throws IOException, InvalidUIDLSecurityKeyException {
+ public void handleFileUpload(Root root, WrappedRequest request,
+ WrappedResponse response) throws IOException,
+ InvalidUIDLSecurityKeyException {
/*
* URI pattern: APP/UPLOAD/[PID]/[NAME]/[SECKEY] See #createReceiverUrl
@@ -86,14 +87,14 @@ public class CommunicationManager extends AbstractCommunicationManager {
String uppUri = pathInfo.substring(startOfData);
String[] parts = uppUri.split("/", 3); // 0 = pid, 1= name, 2 = sec key
String variableName = parts[1];
- String paintableId = parts[0];
+ String connectorId = parts[0];
StreamVariable streamVariable = pidToNameToStreamVariable.get(
- paintableId).get(variableName);
+ connectorId).get(variableName);
String secKey = streamVariableToSeckey.get(streamVariable);
if (secKey.equals(parts[2])) {
- Connector source = getConnector(application, paintableId);
+ Connector source = getConnector(root, connectorId);
String contentType = request.getContentType();
if (contentType.contains("boundary")) {
// Multipart requests contain boundary string
@@ -117,13 +118,12 @@ public class CommunicationManager extends AbstractCommunicationManager {
protected void postPaint(Root root) {
super.postPaint(root);
- Application application = root.getApplication();
if (pidToNameToStreamVariable != null) {
Iterator<String> iterator = pidToNameToStreamVariable.keySet()
.iterator();
while (iterator.hasNext()) {
String connectorId = iterator.next();
- if (application.getConnector(connectorId) == null) {
+ if (root.getConnectorTracker().getConnector(connectorId) == null) {
// Owner is no longer attached to the application
Map<String, StreamVariable> removed = pidToNameToStreamVariable
.get(connectorId);
diff --git a/src/com/vaadin/terminal/gwt/server/ComponentSizeValidator.java b/src/com/vaadin/terminal/gwt/server/ComponentSizeValidator.java
index 335067ca7a..171d440796 100644
--- a/src/com/vaadin/terminal/gwt/server/ComponentSizeValidator.java
+++ b/src/com/vaadin/terminal/gwt/server/ComponentSizeValidator.java
@@ -34,9 +34,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;
/**
@@ -134,7 +131,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;
}
@@ -154,7 +151,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;
}
@@ -653,11 +650,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/Constants.java b/src/com/vaadin/terminal/gwt/server/Constants.java
index 7c467aa7f4..9e6b2c775b 100644
--- a/src/com/vaadin/terminal/gwt/server/Constants.java
+++ b/src/com/vaadin/terminal/gwt/server/Constants.java
@@ -68,7 +68,7 @@ public interface Constants {
// Widget set parameter name
static final String PARAMETER_WIDGETSET = "widgetset";
- static final String ERROR_NO_WINDOW_FOUND = "No window found. Did you remember to setMainWindow()?";
+ static final String ERROR_NO_ROOT_FOUND = "Application did not return a root for the request and did not request extra information either. Something is wrong.";
static final String DEFAULT_THEME_NAME = "reindeer";
diff --git a/src/com/vaadin/terminal/gwt/server/DragAndDropService.java b/src/com/vaadin/terminal/gwt/server/DragAndDropService.java
index f6c96557ea..0e8d1c0152 100644
--- a/src/com/vaadin/terminal/gwt/server/DragAndDropService.java
+++ b/src/com/vaadin/terminal/gwt/server/DragAndDropService.java
@@ -4,6 +4,8 @@
package com.vaadin.terminal.gwt.server;
import java.io.PrintWriter;
+import java.util.Collection;
+import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
@@ -17,6 +19,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;
@@ -26,9 +29,6 @@ import com.vaadin.ui.Component;
public class DragAndDropService implements VariableOwner, ClientConnector {
- private static final Logger logger = Logger
- .getLogger(DragAndDropService.class.getName());
-
private int lastVisitId;
private boolean lastVisitAccepted = false;
@@ -48,8 +48,9 @@ public class DragAndDropService implements VariableOwner, ClientConnector {
// 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
@@ -79,8 +80,9 @@ public class DragAndDropService implements VariableOwner, ClientConnector {
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;
}
@@ -242,4 +244,47 @@ public class DragAndDropService implements VariableOwner, ClientConnector {
public Class<? extends SharedState> 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 Collection<Extension> getExtensions() {
+ // TODO Auto-generated method stub
+ return Collections.emptySet();
+ }
+
+ public void removeExtension(Extension extension) {
+ // TODO Auto-generated method stub
+ }
+
+ 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<Entity> 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<Key> keys = new ArrayList<Key>();
for (Entity e : entities) {
keys.add(e.getKey());
@@ -387,8 +388,9 @@ public class GAEApplicationServlet extends ApplicationServlet {
List<Entity> 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<Key> keys = new ArrayList<Key>();
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/JsonCodec.java b/src/com/vaadin/terminal/gwt/server/JsonCodec.java
index e082eca47e..d3a2ef56f8 100644
--- a/src/com/vaadin/terminal/gwt/server/JsonCodec.java
+++ b/src/com/vaadin/terminal/gwt/server/JsonCodec.java
@@ -8,26 +8,30 @@ import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.Serializable;
+import java.lang.reflect.Array;
import java.lang.reflect.InvocationTargetException;
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.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;
+import com.vaadin.ui.ConnectorTracker;
/**
* Decoder for converting RPC parameters and other values from JSON in transfer
@@ -79,8 +83,16 @@ public class JsonCodec implements Serializable {
public static boolean isInternalType(Type type) {
if (type instanceof Class && ((Class<?>) type).isPrimitive()) {
+ if (type == byte.class || type == char.class) {
+ // Almost all primitive types are handled internally
+ return false;
+ }
// 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));
}
@@ -93,65 +105,62 @@ 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)
+ Object value, ConnectorTracker connectorTracker)
throws JSONException {
if (isInternalType(targetType)) {
- return decodeInternalType(targetType, false, valueAndType,
- application);
+ return decodeInternalType(targetType, false, value,
+ connectorTracker);
} else {
- return decodeCustomType(targetType, valueAndType, application);
+ return decodeCustomType(targetType, value, connectorTracker);
}
}
- public static Object decodeCustomType(Type targetType,
- JSONArray valueAndType, Application application)
- throws JSONException {
+ public static Object decodeCustomType(Type targetType, Object value,
+ ConnectorTracker connectorTracker) 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 if (targetType == byte.class || targetType == Byte.class) {
+ return Byte.valueOf(String.valueOf(value));
+ } else if (targetType == char.class || targetType == Character.class) {
+ return Character.valueOf(String.valueOf(value).charAt(0));
+ } else if (targetType instanceof Class<?>
+ && ((Class<?>) targetType).isArray()) {
+ // Legacy Object[] and String[] handled elsewhere, this takes care
+ // of generic arrays
+ return decodeArray((Class<?>) targetType, (JSONArray) value,
+ connectorTracker);
+ } else if (targetType == JSONObject.class
+ || targetType == JSONArray.class) {
+ return value;
} else {
- return decodeObject(targetType, (JSONObject) value, application);
+ return decodeObject(targetType, (JSONObject) value,
+ connectorTracker);
}
}
+ private static Object decodeArray(Class<?> targetType, JSONArray value,
+ ConnectorTracker connectorTracker) throws JSONException {
+ Class<?> componentType = targetType.getComponentType();
+ Object array = Array.newInstance(componentType, value.length());
+ for (int i = 0; i < value.length(); i++) {
+ Object decodedValue = decodeInternalOrCustomType(componentType,
+ value.get(i), connectorTracker);
+ Array.set(array, i, decodedValue);
+ }
+ return array;
+ }
+
/**
* Decodes a value that is of an internal type.
* <p>
@@ -177,41 +186,41 @@ public class JsonCodec implements Serializable {
* @throws JSONException
*/
public static Object decodeInternalType(Type targetType,
- boolean restrictToInternalTypes, JSONArray valueAndType,
- Application application) throws JSONException {
- String encodedTransportType = valueAndType.getString(0);
+ boolean restrictToInternalTypes, Object encodedJsonValue,
+ ConnectorTracker connectorTracker) throws JSONException {
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;
}
+
+ // UidlValue
+ if (targetType == UidlValue.class) {
+ return decodeUidlValue((JSONArray) encodedJsonValue,
+ connectorTracker);
+ }
+
// Collections
if (JsonEncoder.VTYPE_LIST.equals(transportType)) {
return decodeList(targetType, restrictToInternalTypes,
- (JSONArray) encodedJsonValue, application);
+ (JSONArray) encodedJsonValue, connectorTracker);
} else if (JsonEncoder.VTYPE_SET.equals(transportType)) {
return decodeSet(targetType, restrictToInternalTypes,
- (JSONArray) encodedJsonValue, application);
+ (JSONArray) encodedJsonValue, connectorTracker);
} else if (JsonEncoder.VTYPE_MAP.equals(transportType)) {
return decodeMap(targetType, restrictToInternalTypes,
- (JSONObject) encodedJsonValue, application);
+ encodedJsonValue, connectorTracker);
}
// Arrays
if (JsonEncoder.VTYPE_ARRAY.equals(transportType)) {
return decodeObjectArray(targetType, (JSONArray) encodedJsonValue,
- application);
+ connectorTracker);
} else if (JsonEncoder.VTYPE_STRINGARRAY.equals(transportType)) {
return decodeStringArray((JSONArray) encodedJsonValue);
@@ -222,10 +231,10 @@ public class JsonCodec implements Serializable {
String stringValue = String.valueOf(encodedJsonValue);
if (JsonEncoder.VTYPE_CONNECTOR.equals(transportType)) {
- return application.getConnector(stringValue);
+ return connectorTracker.getConnector(stringValue);
}
- // Standard Java types
+ // Legacy types
if (JsonEncoder.VTYPE_STRING.equals(transportType)) {
return stringValue;
@@ -244,6 +253,15 @@ public class JsonCodec implements Serializable {
throw new JSONException("Unknown type " + transportType);
}
+ private static UidlValue decodeUidlValue(JSONArray encodedJsonValue,
+ ConnectorTracker connectorTracker) throws JSONException {
+ String type = encodedJsonValue.getString(0);
+
+ Object decodedValue = decodeInternalType(getType(type), true,
+ encodedJsonValue.get(1), connectorTracker);
+ return new UidlValue(decodedValue);
+ }
+
private static boolean transportTypesCompatible(
String encodedTransportType, String transportType) {
if (encodedTransportType == null) {
@@ -260,22 +278,94 @@ public class JsonCodec implements Serializable {
}
private static Map<Object, Object> decodeMap(Type targetType,
- boolean restrictToInternalTypes, JSONObject jsonMap,
- Application application) throws JSONException {
- HashMap<Object, Object> map = new HashMap<Object, Object>();
-
- Iterator<String> it = jsonMap.keys();
- while (it.hasNext()) {
- String key = it.next();
- JSONArray encodedKey = new JSONArray(key);
- JSONArray encodedValue = jsonMap.getJSONArray(key);
-
- Object decodedKey = decodeParametrizedType(targetType,
- restrictToInternalTypes, 0, encodedKey, application);
- Object decodedValue = decodeParametrizedType(targetType,
- restrictToInternalTypes, 1, encodedValue, application);
- map.put(decodedKey, decodedValue);
+ boolean restrictToInternalTypes, Object jsonMap,
+ ConnectorTracker connectorTracker) throws JSONException {
+ 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<Object, Object>();
+ }
}
+
+ 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,
+ connectorTracker);
+ } else if (keyType == Connector.class) {
+ return decodeConnectorMap(valueType, (JSONObject) jsonMap,
+ connectorTracker);
+ } else {
+ return decodeObjectMap(keyType, valueType, (JSONArray) jsonMap,
+ connectorTracker);
+ }
+ } else {
+ return decodeStringMap(UidlValue.class, (JSONObject) jsonMap,
+ connectorTracker);
+ }
+ }
+
+ private static Map<Object, Object> decodeObjectMap(Type keyType,
+ Type valueType, JSONArray jsonMap, ConnectorTracker connectorTracker)
+ throws JSONException {
+ Map<Object, Object> map = new HashMap<Object, Object>();
+
+ 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),
+ connectorTracker);
+ Object value = decodeInternalOrCustomType(valueType, values.get(i),
+ connectorTracker);
+
+ map.put(key, value);
+ }
+
+ return map;
+ }
+
+ private static Map<Object, Object> decodeConnectorMap(Type valueType,
+ JSONObject jsonMap, ConnectorTracker connectorTracker)
+ throws JSONException {
+ Map<Object, Object> map = new HashMap<Object, Object>();
+
+ for (Iterator<?> iter = jsonMap.keys(); iter.hasNext();) {
+ String key = (String) iter.next();
+ Object value = decodeInternalOrCustomType(valueType,
+ jsonMap.get(key), connectorTracker);
+ if (valueType == UidlValue.class) {
+ value = ((UidlValue) value).getValue();
+ }
+ map.put(connectorTracker.getConnector(key), value);
+ }
+
+ return map;
+ }
+
+ private static Map<Object, Object> decodeStringMap(Type valueType,
+ JSONObject jsonMap, ConnectorTracker connectorTracker)
+ throws JSONException {
+ Map<Object, Object> map = new HashMap<Object, Object>();
+
+ for (Iterator<?> iter = jsonMap.keys(); iter.hasNext();) {
+ String key = (String) iter.next();
+ Object value = decodeInternalOrCustomType(valueType,
+ jsonMap.get(key), connectorTracker);
+ if (valueType == UidlValue.class) {
+ value = ((UidlValue) value).getValue();
+ }
+ map.put(key, value);
+ }
+
return map;
}
@@ -291,19 +381,20 @@ 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,
+ ConnectorTracker connectorTracker) 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,
+ connectorTracker);
} 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, value, connectorTracker);
+ return decodeInternalType.getValue();
}
}
@@ -323,21 +414,21 @@ public class JsonCodec implements Serializable {
}
private static Object[] decodeObjectArray(Type targetType,
- JSONArray jsonArray, Application application) throws JSONException {
- List list = decodeList(List.class, true, jsonArray, application);
+ JSONArray jsonArray, ConnectorTracker connectorTracker)
+ throws JSONException {
+ List list = decodeList(List.class, true, jsonArray, connectorTracker);
return list.toArray(new Object[list.size()]);
}
private static List<Object> decodeList(Type targetType,
boolean restrictToInternalTypes, JSONArray jsonArray,
- Application application) throws JSONException {
+ ConnectorTracker connectorTracker) throws JSONException {
List<Object> list = new ArrayList<Object>();
for (int i = 0; i < jsonArray.length(); ++i) {
// each entry always has two elements: type and value
- JSONArray encodedValueAndType = jsonArray.getJSONArray(i);
+ Object encodedValue = jsonArray.get(i);
Object decodedChild = decodeParametrizedType(targetType,
- restrictToInternalTypes, 0, encodedValueAndType,
- application);
+ restrictToInternalTypes, 0, encodedValue, connectorTracker);
list.add(decodedChild);
}
return list;
@@ -345,10 +436,10 @@ public class JsonCodec implements Serializable {
private static Set<Object> decodeSet(Type targetType,
boolean restrictToInternalTypes, JSONArray jsonArray,
- Application application) throws JSONException {
+ ConnectorTracker connectorTracker) throws JSONException {
HashSet<Object> set = new HashSet<Object>();
- set.addAll(decodeList(List.class, restrictToInternalTypes, jsonArray,
- application));
+ set.addAll(decodeList(targetType, restrictToInternalTypes, jsonArray,
+ connectorTracker));
return set;
}
@@ -356,7 +447,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
@@ -367,11 +458,14 @@ 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,
- JSONObject serializedObject, Application application)
+ JSONObject serializedObject, ConnectorTracker connectorTracker)
throws JSONException {
Class<?> targetClass = getClassForType(targetType);
@@ -389,11 +483,10 @@ 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);
+ fieldType, encodedFieldValue, connectorTracker);
pd.getWriteMethod().invoke(decodedObject, decodedFieldValue);
}
@@ -412,55 +505,47 @@ public class JsonCodec implements Serializable {
}
}
- @Deprecated
- private static JSONArray encode(Object value, Application application)
+ public static Object encode(Object value, Object referenceValue,
+ Type valueType, ConnectorTracker connectorTracker)
throws JSONException {
- return encode(value, null, null, application);
- }
- public static JSONArray encode(Object value, Object referenceValue,
- Type valueType, Application application) throws JSONException {
+ if (valueType == null) {
+ throw new IllegalArgumentException("type must be defined");
+ }
if (null == value) {
return encodeNull();
}
- if (valueType == null) {
- valueType = value.getClass();
- }
-
- 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 Character) {
+ // Character is not a Number
+ 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);
- } else if (value instanceof Object[]) {
- Object[] array = (Object[]) value;
- JSONArray jsonArray = encodeArrayContents(array, application);
- return combineTypeAndValue(JsonEncoder.VTYPE_ARRAY, jsonArray);
+ connectorTracker);
+ return jsonArray;
+ } else if (valueType instanceof Class<?>
+ && ((Class<?>) valueType).isArray()) {
+ JSONArray jsonArray = encodeArrayContents(value, connectorTracker);
+ return jsonArray;
} else if (value instanceof Map) {
- JSONObject jsonMap = encodeMap(valueType, (Map<?, ?>) value,
- application);
- return combineTypeAndValue(JsonEncoder.VTYPE_MAP, jsonMap);
+ Object jsonMap = encodeMap(valueType, (Map<?, ?>) value,
+ connectorTracker);
+ return jsonMap;
} else if (value instanceof Connector) {
Connector connector = (Connector) value;
if (value instanceof Component
@@ -468,28 +553,24 @@ 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, connectorTracker);
+ } else if (value instanceof JSONArray || value instanceof JSONObject) {
+ return value;
} 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, connectorTracker);
}
}
- 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,
- Application application) throws JSONException {
+ ConnectorTracker connectorTracker) throws JSONException {
JSONObject jsonMap = new JSONObject();
try {
@@ -512,10 +593,18 @@ 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,
- application));
+ connectorTracker));
// } else {
// System.out.println("Skipping field " + fieldName
// + " of type " + fieldType.getName()
@@ -549,45 +638,46 @@ public class JsonCodec implements Serializable {
return false;
}
- private static JSONArray encodeEnum(Enum e, Application application)
- throws JSONException {
- String enumIdentifier = e.name();
- return combineTypeAndValue(e.getClass().getName(), enumIdentifier);
+ private static String encodeEnum(Enum<?> e,
+ ConnectorTracker connectorTracker) throws JSONException {
+ return e.name();
}
- private static JSONArray encodeArrayContents(Object[] array,
- Application application) throws JSONException {
+ private static JSONArray encodeArrayContents(Object array,
+ ConnectorTracker connectorTracker) throws JSONException {
JSONArray jsonArray = new JSONArray();
- for (Object o : array) {
- jsonArray.put(encode(o, null, null, application));
+ Class<?> componentType = array.getClass().getComponentType();
+ for (int i = 0; i < Array.getLength(array); i++) {
+ jsonArray.put(encode(Array.get(array, i), null, componentType,
+ connectorTracker));
}
return jsonArray;
}
private static JSONArray encodeCollection(Type targetType,
- Collection collection, Application application)
+ Collection collection, ConnectorTracker connectorTracker)
throws JSONException {
JSONArray jsonArray = new JSONArray();
for (Object o : collection) {
- jsonArray.put(encodeChild(targetType, 0, o, application));
+ jsonArray.put(encodeChild(targetType, 0, o, connectorTracker));
}
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,
+ ConnectorTracker connectorTracker) throws JSONException {
if (targetType instanceof ParameterizedType) {
Type childType = ((ParameterizedType) targetType)
.getActualTypeArguments()[typeIndex];
// Encode using the given type
- return encode(o, null, childType, application);
+ return encode(o, null, childType, connectorTracker);
} else {
- return encode(o, application);
+ throw new JSONException("Collection is missing generics");
}
}
- private static JSONObject encodeMap(Type mapType, Map<?, ?> map,
- Application application) throws JSONException {
+ private static Object encodeMap(Type mapType, Map<?, ?> map,
+ ConnectorTracker connectorTracker) throws JSONException {
Type keyType, valueType;
if (mapType instanceof ParameterizedType) {
@@ -597,26 +687,66 @@ 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, connectorTracker);
+ } else if (keyType == Connector.class) {
+ return encodeConnectorMap(valueType, map, connectorTracker);
+ } else {
+ return encodeObjectMap(keyType, valueType, map, connectorTracker);
+ }
+ }
+
+ private static JSONArray encodeObjectMap(Type keyType, Type valueType,
+ Map<?, ?> map, ConnectorTracker connectorTracker)
+ throws JSONException {
+ JSONArray keys = new JSONArray();
+ JSONArray values = new JSONArray();
+
+ for (Entry<?, ?> entry : map.entrySet()) {
+ Object encodedKey = encode(entry.getKey(), null, keyType,
+ connectorTracker);
+ Object encodedValue = encode(entry.getValue(), null, valueType,
+ connectorTracker);
+
+ keys.put(encodedKey);
+ values.put(encodedValue);
+ }
+
+ return new JSONArray(Arrays.asList(keys, values));
+ }
+
+ private static JSONObject encodeConnectorMap(Type valueType, Map<?, ?> map,
+ ConnectorTracker connectorTracker) throws JSONException {
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);
+
+ for (Entry<?, ?> entry : map.entrySet()) {
+ Connector key = (Connector) entry.getKey();
+ Object encodedValue = encode(entry.getValue(), null, valueType,
+ connectorTracker);
+ jsonMap.put(key.getConnectorId(), encodedValue);
}
+
return jsonMap;
}
- private static JSONArray combineTypeAndValue(String type, Object value) {
- if (type == null) {
- throw new RuntimeException("Type for value " + value
- + " cannot be null!");
+ private static JSONObject encodeStringMap(Type valueType, Map<?, ?> map,
+ ConnectorTracker connectorTracker) throws JSONException {
+ JSONObject jsonMap = new JSONObject();
+
+ for (Entry<?, ?> entry : map.entrySet()) {
+ String key = (String) entry.getKey();
+ Object encodedValue = encode(entry.getValue(), null, valueType,
+ connectorTracker);
+ jsonMap.put(key, encodedValue);
}
- JSONArray outerArray = new JSONArray();
- outerArray.put(type);
- outerArray.put(value);
- return outerArray;
+
+ return jsonMap;
}
/**
diff --git a/src/com/vaadin/terminal/gwt/server/JsonPaintTarget.java b/src/com/vaadin/terminal/gwt/server/JsonPaintTarget.java
index def334290e..70ab452e4e 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;
/**
@@ -42,9 +43,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";
@@ -161,6 +159,7 @@ public class JsonPaintTarget implements PaintTarget {
* @throws Paintexception
* if the paint operation failed.
*/
+
public void endTag(String tagName) throws PaintException {
// In case of null data output nothing:
if (tagName == null) {
@@ -327,6 +326,7 @@ public class JsonPaintTarget implements PaintTarget {
* if the paint operation failed.
*
*/
+
public void addText(String str) throws PaintException {
tag.addData("\"" + escapeJSON(str) + "\"");
}
@@ -399,7 +399,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);
@@ -467,8 +467,8 @@ public class JsonPaintTarget implements PaintTarget {
tag.addVariable(new StringVariable(owner, name, escapeJSON(value)));
}
- public void addVariable(VariableOwner owner, String name,
- ClientConnector value) throws PaintException {
+ public void addVariable(VariableOwner owner, String name, Component value)
+ throws PaintException {
tag.addVariable(new StringVariable(owner, name, value.getConnectorId()));
}
@@ -515,6 +515,7 @@ public class JsonPaintTarget implements PaintTarget {
* @throws PaintException
* if the paint operation failed.
*/
+
public void addUploadStreamVariable(VariableOwner owner, String name)
throws PaintException {
startTag("uploadstream");
@@ -534,6 +535,7 @@ public class JsonPaintTarget implements PaintTarget {
* @throws PaintException
* if the paint operation failed.
*/
+
public void addSection(String sectionTagName, String sectionData)
throws PaintException {
tag.addData("{\"" + sectionTagName + "\":\"" + escapeJSON(sectionData)
@@ -548,6 +550,7 @@ public class JsonPaintTarget implements PaintTarget {
* @throws PaintException
* if the paint operation failed.
*/
+
public void addUIDL(String xml) throws PaintException {
// Ensure that the target is open
@@ -581,6 +584,7 @@ public class JsonPaintTarget implements PaintTarget {
* @see com.vaadin.terminal.PaintTarget#addXMLSection(String, String,
* String)
*/
+
public void addXMLSection(String sectionTagName, String sectionData,
String namespace) throws PaintException {
@@ -645,12 +649,14 @@ 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();
- logger.fine("startPaintable for " + connector.getClass().getName()
- + "@" + Integer.toHexString(connector.hashCode()));
+ getLogger().fine(
+ "startPaintable for " + connector.getClass().getName() + "@"
+ + Integer.toHexString(connector.hashCode()));
startTag(tagName, true);
openPaintables.push(connector);
@@ -670,9 +676,10 @@ public class JsonPaintTarget implements PaintTarget {
return PaintStatus.PAINTING;
}
- public void endPaintable(ClientConnector paintable) throws PaintException {
- logger.fine("endPaintable for " + paintable.getClass().getName() + "@"
- + Integer.toHexString(paintable.hashCode()));
+ public void endPaintable(Component paintable) throws PaintException {
+ getLogger().fine(
+ "endPaintable for " + paintable.getClass().getName() + "@"
+ + Integer.toHexString(paintable.hashCode()));
ClientConnector openPaintable = openPaintables.peek();
if (paintable != openPaintable) {
@@ -691,6 +698,7 @@ public class JsonPaintTarget implements PaintTarget {
*
* @see com.vaadin.terminal.PaintTarget#addCharacterData(java.lang.String )
*/
+
public void addCharacterData(String text) throws PaintException {
if (text != null) {
tag.addData(text);
@@ -997,8 +1005,13 @@ public class JsonPaintTarget implements PaintTarget {
*
* @see com.vaadin.terminal.PaintTarget#isFullRepaint()
*/
+
public boolean isFullRepaint() {
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 661da57af6..de4f918b75 100644
--- a/src/com/vaadin/terminal/gwt/server/PortletApplicationContext2.java
+++ b/src/com/vaadin/terminal/gwt/server/PortletApplicationContext2.java
@@ -48,9 +48,6 @@ import com.vaadin.ui.Root;
@SuppressWarnings("serial")
public class PortletApplicationContext2 extends AbstractWebApplicationContext {
- private static final Logger logger = Logger
- .getLogger(PortletApplicationContext2.class.getName());
-
protected Map<Application, Set<PortletListener>> portletListeners = new HashMap<Application, Set<PortletListener>>();
protected transient PortletSession session;
@@ -76,11 +73,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;
@@ -419,4 +416,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/server/PortletCommunicationManager.java b/src/com/vaadin/terminal/gwt/server/PortletCommunicationManager.java
index 55f15da3d9..d3fbf4d988 100644
--- a/src/com/vaadin/terminal/gwt/server/PortletCommunicationManager.java
+++ b/src/com/vaadin/terminal/gwt/server/PortletCommunicationManager.java
@@ -43,12 +43,12 @@ public class PortletCommunicationManager extends AbstractCommunicationManager {
super(application);
}
- public void handleFileUpload(WrappedRequest request,
+ public void handleFileUpload(Root root, WrappedRequest request,
WrappedResponse response) throws IOException {
String contentType = request.getContentType();
String name = request.getParameter("name");
String ownerId = request.getParameter("rec-owner");
- Connector owner = getConnector(getApplication(), ownerId);
+ Connector owner = getConnector(root, ownerId);
StreamVariable streamVariable = ownerToNameToStreamVariable.get(owner)
.get(name);
@@ -73,7 +73,7 @@ public class PortletCommunicationManager extends AbstractCommunicationManager {
.iterator();
while (iterator.hasNext()) {
Connector owner = iterator.next();
- if (application.getConnector(owner.getConnectorId()) == null) {
+ if (getConnector(root, owner.getConnectorId()) == null) {
// Owner is no longer attached to the application
iterator.remove();
}
diff --git a/src/com/vaadin/terminal/gwt/server/RpcManager.java b/src/com/vaadin/terminal/gwt/server/RpcManager.java
index d240ab8467..026c847e2b 100644
--- a/src/com/vaadin/terminal/gwt/server/RpcManager.java
+++ b/src/com/vaadin/terminal/gwt/server/RpcManager.java
@@ -13,5 +13,36 @@ import java.io.Serializable;
* @since 7.0
*/
public interface RpcManager extends Serializable {
- public void applyInvocation(ServerRpcMethodInvocation invocation);
+ public void applyInvocation(ServerRpcMethodInvocation invocation)
+ throws RpcInvocationException;
+
+ /**
+ * Wrapper exception for exceptions which occur during invocation of an RPC
+ * call
+ *
+ * @author Vaadin Ltd
+ * @version @VERSION@
+ * @since 7.0
+ *
+ */
+ public static class RpcInvocationException extends Exception {
+
+ public RpcInvocationException() {
+ super();
+ }
+
+ public RpcInvocationException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public RpcInvocationException(String message) {
+ super(message);
+ }
+
+ public RpcInvocationException(Throwable cause) {
+ super(cause);
+ }
+
+ }
+
}
diff --git a/src/com/vaadin/terminal/gwt/server/ServerRpcManager.java b/src/com/vaadin/terminal/gwt/server/ServerRpcManager.java
index 07f83864c2..d9931a9610 100644
--- a/src/com/vaadin/terminal/gwt/server/ServerRpcManager.java
+++ b/src/com/vaadin/terminal/gwt/server/ServerRpcManager.java
@@ -5,6 +5,7 @@
package com.vaadin.terminal.gwt.server;
import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
@@ -66,9 +67,10 @@ public class ServerRpcManager<T> implements RpcManager {
* non-null target of the RPC call
* @param invocation
* method invocation to perform
+ * @throws RpcInvocationException
*/
public static void applyInvocation(RpcTarget target,
- ServerRpcMethodInvocation invocation) {
+ ServerRpcMethodInvocation invocation) throws RpcInvocationException {
RpcManager manager = target.getRpcManager(invocation
.getInterfaceClass());
if (manager != null) {
@@ -109,7 +111,8 @@ public class ServerRpcManager<T> implements RpcManager {
* @param invocation
* method invocation to perform
*/
- public void applyInvocation(ServerRpcMethodInvocation invocation) {
+ public void applyInvocation(ServerRpcMethodInvocation invocation)
+ throws RpcInvocationException {
Method method = invocation.getMethod();
Class<?>[] parameterTypes = method.getParameterTypes();
Object[] args = new Object[parameterTypes.length];
@@ -125,7 +128,7 @@ public class ServerRpcManager<T> implements RpcManager {
try {
method.invoke(implementation, args);
} catch (Exception e) {
- throw new RuntimeException("Unable to invoke method "
+ throw new RpcInvocationException("Unable to invoke method "
+ invocation.getMethodName() + " in "
+ invocation.getInterfaceName(), e);
}
diff --git a/src/com/vaadin/terminal/gwt/server/ServerRpcMethodInvocation.java b/src/com/vaadin/terminal/gwt/server/ServerRpcMethodInvocation.java
index 6f278f7797..95565c4379 100644
--- a/src/com/vaadin/terminal/gwt/server/ServerRpcMethodInvocation.java
+++ b/src/com/vaadin/terminal/gwt/server/ServerRpcMethodInvocation.java
@@ -79,6 +79,12 @@ public class ServerRpcMethodInvocation extends MethodInvocation {
}
}
+ if (invocationMethod == null) {
+ throw new IllegalStateException("Can't find method " + methodName
+ + " with " + parameterCount + " parameters in "
+ + targetType.getName());
+ }
+
return invocationMethod;
}
diff --git a/src/com/vaadin/terminal/gwt/server/WebBrowser.java b/src/com/vaadin/terminal/gwt/server/WebBrowser.java
index 358f6f38fb..38b5409594 100644
--- a/src/com/vaadin/terminal/gwt/server/WebBrowser.java
+++ b/src/com/vaadin/terminal/gwt/server/WebBrowser.java
@@ -23,8 +23,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;
@@ -43,6 +41,7 @@ public class WebBrowser implements Terminal {
*
* @return Always returns null.
*/
+
public String getDefaultTheme() {
return null;
}
@@ -52,6 +51,7 @@ public class WebBrowser implements Terminal {
*
* @see com.vaadin.terminal.Terminal#getScreenHeight()
*/
+
public int getScreenHeight() {
return screenHeight;
}
@@ -61,35 +61,12 @@ public class WebBrowser implements Terminal {
*
* @see com.vaadin.terminal.Terminal#getScreenWidth()
*/
+
public int getScreenWidth() {
return screenWidth;
}
/**
- * Gets the height of the client (browser window).
- * <p>
- * 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)
- * <p>
- * 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.
*
* @return The raw browser userAgent string
@@ -367,10 +344,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
@@ -383,9 +356,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);
@@ -394,14 +367,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
@@ -462,8 +427,7 @@ public class WebBrowser implements Terminal {
if (request.getParameter("sw") != null) {
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/WrappedHttpServletRequest.java b/src/com/vaadin/terminal/gwt/server/WrappedHttpServletRequest.java
index b6f1a192cb..0774a79990 100644
--- a/src/com/vaadin/terminal/gwt/server/WrappedHttpServletRequest.java
+++ b/src/com/vaadin/terminal/gwt/server/WrappedHttpServletRequest.java
@@ -82,7 +82,7 @@ public class WrappedHttpServletRequest extends HttpServletRequestWrapper
public WebBrowser getWebBrowser() {
WebApplicationContext context = (WebApplicationContext) Application
- .getCurrentApplication().getContext();
+ .getCurrent().getContext();
return context.getBrowser();
}
};
diff --git a/src/com/vaadin/terminal/gwt/server/WrappedPortletRequest.java b/src/com/vaadin/terminal/gwt/server/WrappedPortletRequest.java
index 3838695aa3..85d8d5c69c 100644
--- a/src/com/vaadin/terminal/gwt/server/WrappedPortletRequest.java
+++ b/src/com/vaadin/terminal/gwt/server/WrappedPortletRequest.java
@@ -130,7 +130,7 @@ public class WrappedPortletRequest implements WrappedRequest {
public WebBrowser getWebBrowser() {
PortletApplicationContext2 context = (PortletApplicationContext2) Application
- .getCurrentApplication().getContext();
+ .getCurrent().getContext();
return context.getBrowser();
}
};
diff --git a/src/com/vaadin/terminal/gwt/widgetsetutils/AcceptCriteriaFactoryGenerator.java b/src/com/vaadin/terminal/gwt/widgetsetutils/AcceptCriteriaFactoryGenerator.java
index d8d3c23e0c..6d90a51761 100644
--- a/src/com/vaadin/terminal/gwt/widgetsetutils/AcceptCriteriaFactoryGenerator.java
+++ b/src/com/vaadin/terminal/gwt/widgetsetutils/AcceptCriteriaFactoryGenerator.java
@@ -4,7 +4,6 @@
package com.vaadin.terminal.gwt.widgetsetutils;
import java.io.PrintWriter;
-import java.util.Collection;
import java.util.Date;
import com.google.gwt.core.ext.Generator;
@@ -16,14 +15,13 @@ 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.event.dd.acceptcriteria.AcceptCriterion;
-import com.vaadin.event.dd.acceptcriteria.ClientCriterion;
+import com.vaadin.terminal.gwt.client.ui.dd.AcceptCriterion;
import com.vaadin.terminal.gwt.client.ui.dd.VAcceptCriterion;
import com.vaadin.terminal.gwt.client.ui.dd.VAcceptCriterionFactory;
/**
* GWT generator to build {@link VAcceptCriterionFactory} implementation
- * dynamically based on {@link ClientCriterion} annotations available in
+ * dynamically based on {@link AcceptCriterion} annotations available in
* classpath.
*
*/
@@ -102,26 +100,28 @@ public class AcceptCriteriaFactoryGenerator extends Generator {
sourceWriter.println("name = name.intern();");
- Collection<Class<? extends AcceptCriterion>> clientSideVerifiableCriterion = ClassPathExplorer
- .getCriterion();
-
- for (Class<? extends AcceptCriterion> class1 : clientSideVerifiableCriterion) {
- logger.log(Type.INFO,
- "creating mapping for " + class1.getCanonicalName());
- String canonicalName = class1.getCanonicalName();
- Class<? extends VAcceptCriterion> clientClass = class1
- .getAnnotation(ClientCriterion.class).value();
- sourceWriter.print("if (\"");
- sourceWriter.print(canonicalName);
- sourceWriter.print("\" == name) return GWT.create(");
- sourceWriter.print(clientClass.getCanonicalName());
- sourceWriter.println(".class );");
- sourceWriter.print("else ");
+ JClassType criteriaType = context.getTypeOracle().findType(
+ VAcceptCriterion.class.getName());
+ for (JClassType clientClass : criteriaType.getSubtypes()) {
+ AcceptCriterion annotation = clientClass
+ .getAnnotation(AcceptCriterion.class);
+ if (annotation != null) {
+ String clientClassName = clientClass.getQualifiedSourceName();
+ Class<?> serverClass = clientClass.getAnnotation(
+ AcceptCriterion.class).value();
+ String serverClassName = serverClass.getCanonicalName();
+ logger.log(Type.INFO, "creating mapping for " + serverClassName);
+ sourceWriter.print("if (\"");
+ sourceWriter.print(serverClassName);
+ sourceWriter.print("\" == name) return GWT.create(");
+ sourceWriter.print(clientClassName);
+ sourceWriter.println(".class );");
+ sourceWriter.print("else ");
+ }
}
sourceWriter.println("return null;");
sourceWriter.outdent();
sourceWriter.println("}");
}
-
}
diff --git a/src/com/vaadin/terminal/gwt/widgetsetutils/ClassPathExplorer.java b/src/com/vaadin/terminal/gwt/widgetsetutils/ClassPathExplorer.java
index 6a0aa0f4c2..1c5b736492 100644
--- a/src/com/vaadin/terminal/gwt/widgetsetutils/ClassPathExplorer.java
+++ b/src/com/vaadin/terminal/gwt/widgetsetutils/ClassPathExplorer.java
@@ -6,33 +6,23 @@ package com.vaadin.terminal.gwt.widgetsetutils;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
-import java.io.OutputStream;
-import java.io.PrintStream;
import java.net.JarURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Enumeration;
import java.util.HashMap;
-import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.jar.Attributes;
-import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.Manifest;
import java.util.logging.Level;
import java.util.logging.Logger;
-import com.vaadin.event.dd.acceptcriteria.AcceptCriterion;
-import com.vaadin.event.dd.acceptcriteria.ClientCriterion;
-import com.vaadin.terminal.gwt.server.ClientConnector;
-
/**
* Utility class to collect widgetset related information from classpath.
* Utility will seek all directories from classpaths, and jar files having
@@ -53,9 +43,6 @@ import com.vaadin.terminal.gwt.server.ClientConnector;
*/
public class ClassPathExplorer {
- private static Logger logger = Logger.getLogger(ClassPathExplorer.class
- .getName());
-
private static final String VAADIN_ADDON_VERSION_ATTRIBUTE = "Vaadin-Package-Version";
/**
@@ -92,46 +79,6 @@ public class ClassPathExplorer {
}
/**
- * Finds server side widgets with ClientWidget annotation on the class path
- * (entries that can contain widgets/widgetsets - see
- * getRawClasspathEntries()).
- *
- * As a side effect, also accept criteria are searched under the same class
- * path entries and added into the acceptCriterion collection.
- *
- * @return a collection of {@link ClientConnector} classes
- */
- public static void findAcceptCriteria() {
- logger.info("Searching for accept criteria..");
- long start = System.currentTimeMillis();
- Set<String> keySet = classpathLocations.keySet();
- for (String url : keySet) {
- logger.fine("Searching for accept criteria in "
- + classpathLocations.get(url));
- searchForPaintables(classpathLocations.get(url), url);
- }
- long end = System.currentTimeMillis();
-
- logger.info("Search took " + (end - start) + "ms");
-
- }
-
- /**
- * Finds all accept criteria having client side counterparts (classes with
- * the {@link ClientCriterion} annotation).
- *
- * @return Collection of AcceptCriterion classes
- */
- public static Collection<Class<? extends AcceptCriterion>> getCriterion() {
- if (acceptCriterion.isEmpty()) {
- // accept criterion are searched as a side effect, normally after
- // paintable detection
- findAcceptCriteria();
- }
- return acceptCriterion;
- }
-
- /**
* Finds the names and locations of widgetsets available on the class path.
*
* @return map from widgetset classname to widgetset location URL
@@ -154,6 +101,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;
@@ -214,7 +162,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);
}
}
@@ -250,7 +198,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);
}
}
@@ -278,7 +226,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++) {
@@ -312,6 +260,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");
}
@@ -352,7 +301,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) {
@@ -363,9 +312,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;
@@ -445,151 +396,6 @@ public class ClassPathExplorer {
}
/**
- * Searches for all paintable classes and accept criteria under a location
- * based on {@link ClientCriterion} annotations.
- *
- * Note that client criteria are updated directly to the
- * {@link #acceptCriterion} field, whereas paintables are added to the
- * paintables map given as a parameter.
- *
- * @param location
- * @param locationString
- */
- private final static void searchForPaintables(URL location,
- String locationString) {
-
- // Get a File object for the package
- File directory = new File(location.getFile());
-
- if (directory.exists() && !directory.isHidden()) {
- // Get the list of the files contained in the directory
- String[] files = directory.list();
- for (int i = 0; i < files.length; i++) {
- // we are only interested in .class files
- if (files[i].endsWith(".class")) {
- // remove the .class extension
- String classname = files[i].substring(0,
- files[i].length() - 6);
- String packageName = locationString
- .substring(locationString.lastIndexOf("/") + 1);
- classname = packageName + "." + classname;
- tryToAdd(classname);
- }
- }
- } else {
- try {
- // check files in jar file, entries will list all directories
- // and files in jar
-
- URLConnection openConnection = location.openConnection();
-
- if (openConnection instanceof JarURLConnection) {
- JarURLConnection conn = (JarURLConnection) openConnection;
-
- JarFile jarFile = conn.getJarFile();
-
- // Only scan for paintables in Vaadin add-ons
- if (!isVaadinAddon(jarFile)) {
- return;
- }
-
- Enumeration<JarEntry> e = jarFile.entries();
- while (e.hasMoreElements()) {
- JarEntry entry = e.nextElement();
- String entryname = entry.getName();
- if (!entry.isDirectory()
- && entryname.endsWith(".class")) {
- String classname = entryname.substring(0,
- entryname.length() - 6);
- if (classname.startsWith("/")) {
- classname = classname.substring(1);
- }
- classname = classname.replace('/', '.');
- tryToAdd(classname);
- }
- }
- }
- } catch (IOException e) {
- logger.warning(e.toString());
- }
- }
-
- }
-
- /**
- * A print stream that ignores all output.
- *
- * This is used to hide error messages from static initializers of classes
- * being inspected.
- */
- private static PrintStream devnull = new PrintStream(new OutputStream() {
- @Override
- public void write(int b) throws IOException {
- // NOP
- }
- });
-
- /**
- * Collection of all {@link AcceptCriterion} classes, updated as a side
- * effect of {@link #searchForPaintables(URL, String, Collection)} based on
- * {@link ClientCriterion} annotations.
- */
- private static Set<Class<? extends AcceptCriterion>> acceptCriterion = new HashSet<Class<? extends AcceptCriterion>>();
-
- /**
- * Checks a class for the {@link ClientCriterion} annotations, and adds it
- * to the appropriate collection.
- *
- * @param fullclassName
- */
- @SuppressWarnings("unchecked")
- private static void tryToAdd(final String fullclassName) {
- PrintStream out = System.out;
- PrintStream err = System.err;
- Throwable errorToShow = null;
- Level logLevel = null;
- try {
- System.setErr(devnull);
- System.setOut(devnull);
-
- Class<?> c = Class.forName(fullclassName);
-
- if (c.getAnnotation(ClientCriterion.class) != null) {
- acceptCriterion.add((Class<? extends AcceptCriterion>) c);
- }
- } catch (UnsupportedClassVersionError e) {
- // Inform the user about this as the class might contain a Paintable
- // Typically happens when using an add-on that is compiled using a
- // newer Java version.
- logLevel = Level.INFO;
- errorToShow = e;
- } catch (ClassNotFoundException e) {
- // Don't show to avoid flooding the user with irrelevant messages
- logLevel = Level.FINE;
- errorToShow = e;
- } catch (LinkageError e) {
- // Don't show to avoid flooding the user with irrelevant messages
- logLevel = Level.FINE;
- errorToShow = e;
- } catch (Exception e) {
- // Don't show to avoid flooding the user with irrelevant messages
- logLevel = Level.FINE;
- errorToShow = e;
- } finally {
- System.setErr(err);
- System.setOut(out);
- }
-
- // Must be done here after stderr and stdout have been reset.
- if (errorToShow != null && logLevel != null) {
- logger.log(logLevel,
- "Failed to load class " + fullclassName + ". "
- + errorToShow.getClass().getName() + ": "
- + errorToShow.getMessage());
- }
- }
-
- /**
* Find and return the default source directory where to create new
* widgetsets.
*
@@ -601,6 +407,9 @@ public class ClassPathExplorer {
* @return URL
*/
public static URL getDefaultSourceDirectory() {
+
+ final Logger logger = getLogger();
+
if (logger.isLoggable(Level.FINE)) {
logger.fine("classpathLocations values:");
ArrayList<String> locations = new ArrayList<String>(
@@ -632,44 +441,21 @@ public class ClassPathExplorer {
}
/**
- * Checks if the given jarFile is a Vaadin add-on.
- *
- * @param jarFile
- * @return true if the file is an add-on, false otherwise
- * @throws IOException
- */
- private static boolean isVaadinAddon(JarFile jarFile) throws IOException {
- Manifest manifest = jarFile.getManifest();
- if (manifest == null) {
- return false;
- }
- Attributes mainAttributes = manifest.getMainAttributes();
- if (mainAttributes == null) {
- return false;
- }
-
- return (mainAttributes.getValue(VAADIN_ADDON_VERSION_ATTRIBUTE) != null);
- }
-
- /**
* Test method for helper tool
*/
public static void main(String[] args) {
- ClassPathExplorer.findAcceptCriteria();
- logger.info("Found client criteria:");
- for (Class<? extends AcceptCriterion> cls : acceptCriterion) {
- logger.info(cls.getCanonicalName());
- }
-
- logger.info("");
- logger.info("Searching available widgetsets...");
+ getLogger().info("Searching available widgetsets...");
Map<String, URL> 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/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<Class<? extends ComponentConnector>> deferredPaintables = new HashSet<Class<? extends ComponentConnector>>();
@Override
- protected LoadStyle getLoadStyle(
- Class<? extends ComponentConnector> connector) {
+ protected LoadStyle getLoadStyle(Class<? extends ServerConnector> 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<? extends ComponentConnector> connector) {
+ protected LoadStyle getLoadStyle(Class<? extends ServerConnector> connector) {
return LoadStyle.EAGER;
}
}
diff --git a/src/com/vaadin/terminal/gwt/widgetsetutils/RpcManagerGenerator.java b/src/com/vaadin/terminal/gwt/widgetsetutils/GeneratedRpcMethodProviderGenerator.java
index 2899061204..b1d69b178b 100644
--- a/src/com/vaadin/terminal/gwt/widgetsetutils/RpcManagerGenerator.java
+++ b/src/com/vaadin/terminal/gwt/widgetsetutils/GeneratedRpcMethodProviderGenerator.java
@@ -16,15 +16,15 @@ 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.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.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
@@ -32,7 +32,7 @@ import com.vaadin.terminal.gwt.client.communication.RpcManager;
*
* @since 7.0
*/
-public class RpcManagerGenerator extends Generator {
+public class GeneratedRpcMethodProviderGenerator extends Generator {
@Override
public String generate(TreeLogger logger, GeneratorContext context,
@@ -90,12 +90,24 @@ public class RpcManagerGenerator extends Generator {
ClassSourceFileComposerFactory composer = null;
composer = new ClassSourceFileComposerFactory(packageName, className);
composer.addImport("com.google.gwt.core.client.GWT");
- composer.addImplementedInterface(RpcManager.class.getName());
+ 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<JClassType> rpcInterfaces = new ArrayList<JClassType>();
+ List<JMethod> rpcMethods = new ArrayList<JMethod>();
+
+ sourceWriter
+ .println("public java.util.Collection<RpcMethod> getGeneratedRpcMethods() {");
+ sourceWriter.indent();
+
+ sourceWriter
+ .println("java.util.ArrayList<RpcMethod> list = new java.util.ArrayList<RpcMethod>();");
// iterate over RPC interfaces and create helper methods for each
// interface
@@ -104,81 +116,56 @@ public class RpcManagerGenerator extends Generator {
// 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 = "";
+
+ // RpcMethod(String interfaceName, String methodName,
+ // Type... parameterTypes)
+ sourceWriter.print("list.add(new RpcMethod(\""
+ + type.getQualifiedSourceName() + "\", \""
+ + method.getName() + "\"");
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 + ", ";
- }
+ for (JType parameter : parameterTypes) {
+ sourceWriter.print(", ");
+ writeTypeCreator(sourceWriter, parameter);
}
+ sourceWriter.println(") {");
+ sourceWriter.indent();
+
sourceWriter
- .println(ServerConnector.class.getName()
- + " connector = connectorMap.getConnector(invocation.getConnectorId());");
- sourceWriter
- .println("for ("
- + ClientRpc.class.getName()
- + " rpcImplementation : connector.getRpcImplementations(\""
- + type.getQualifiedSourceName() + "\")) {");
+ .println("public void applyInvocation(ClientRpc target, Object... parameters) {");
sourceWriter.indent();
- sourceWriter.println("((" + type.getQualifiedSourceName()
- + ") rpcImplementation)." + method.getName() + "("
- + paramString + ");");
+
+ sourceWriter.print("((" + type.getQualifiedSourceName()
+ + ")target)." + method.getName() + "(");
+ for (int i = 0; i < parameterTypes.length; i++) {
+ JType parameterType = parameterTypes[i];
+ if (i != 0) {
+ sourceWriter.print(", ");
+ }
+ String parameterTypeName = getBoxedTypeName(parameterType);
+ sourceWriter.print("(" + parameterTypeName
+ + ") parameters[" + i + "]");
+ }
+ sourceWriter.println(");");
+
sourceWriter.outdent();
sourceWriter.println("}");
- sourceWriter.println("return;");
+
sourceWriter.outdent();
- sourceWriter.println("}");
+ 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();
+ sourceWriter.println("return list;");
- 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("}");
+ sourceWriter.println();
// close generated class
sourceWriter.outdent();
@@ -191,6 +178,33 @@ public class RpcManagerGenerator extends Generator {
}
+ public static void writeTypeCreator(SourceWriter sourceWriter, JType type) {
+ String typeName = getBoxedTypeName(type);
+ sourceWriter.print("new Type(\"" + typeName + "\", ");
+ 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(")");
+ }
+
+ public static String getBoxedTypeName(JType type) {
+ if (type.isPrimitive() != null) {
+ // Used boxed types for primitives
+ return type.isPrimitive().getQualifiedBoxedSourceName();
+ } else {
+ return type.getErasedType().getQualifiedSourceName();
+ }
+ }
+
private String getInvokeMethodName(JClassType type) {
return "invoke" + type.getQualifiedSourceName().replaceAll("\\.", "_");
}
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<? extends ComponentConnector> connector) {
+ protected LoadStyle getLoadStyle(Class<? extends ServerConnector> connector) {
return LoadStyle.LAZY;
}
diff --git a/src/com/vaadin/terminal/gwt/widgetsetutils/RpcProxyGenerator.java b/src/com/vaadin/terminal/gwt/widgetsetutils/RpcProxyGenerator.java
index ad4e513049..d9bc8bc832 100644
--- a/src/com/vaadin/terminal/gwt/widgetsetutils/RpcProxyGenerator.java
+++ b/src/com/vaadin/terminal/gwt/widgetsetutils/RpcProxyGenerator.java
@@ -117,7 +117,7 @@ public class RpcProxyGenerator extends Generator {
writer.println(" {");
writer.indent();
- writer.print("connector.getConnection().addMethodInvocationToQueue(new MethodInvocation(connector.getConnectorId(), \""
+ writer.print("this.connector.getConnection().addMethodInvocationToQueue(new MethodInvocation(this.connector.getConnectorId(), \""
+ requestedType.getQualifiedBinaryName() + "\", \"");
writer.print(m.getName());
writer.print("\", new Object[] {");
diff --git a/src/com/vaadin/terminal/gwt/widgetsetutils/SerializerGenerator.java b/src/com/vaadin/terminal/gwt/widgetsetutils/SerializerGenerator.java
index bc031f4bdb..1951f8ba40 100644
--- a/src/com/vaadin/terminal/gwt/widgetsetutils/SerializerGenerator.java
+++ b/src/com/vaadin/terminal/gwt/widgetsetutils/SerializerGenerator.java
@@ -6,7 +6,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;
@@ -15,13 +15,14 @@ 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.JArrayType;
import com.google.gwt.core.ext.typeinfo.JClassType;
import com.google.gwt.core.ext.typeinfo.JEnumConstant;
import com.google.gwt.core.ext.typeinfo.JEnumType;
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.core.ext.typeinfo.TypeOracleException;
import com.google.gwt.json.client.JSONArray;
import com.google.gwt.json.client.JSONObject;
import com.google.gwt.json.client.JSONString;
@@ -29,7 +30,7 @@ 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;
import com.vaadin.terminal.gwt.client.communication.JsonEncoder;
@@ -46,26 +47,32 @@ import com.vaadin.terminal.gwt.client.communication.SerializerMap;
public class SerializerGenerator extends Generator {
private static final String SUBTYPE_SEPARATOR = "___";
- private static String beanSerializerPackageName = SerializerMap.class
+ private static String serializerPackageName = SerializerMap.class
.getPackage().getName();
@Override
public String generate(TreeLogger logger, GeneratorContext context,
- String beanTypeName) throws UnableToCompleteException {
- JClassType beanType = context.getTypeOracle().findType(beanTypeName);
- String beanSerializerClassName = getSerializerSimpleClassName(beanType);
+ String typeName) throws UnableToCompleteException {
+ JClassType type;
+ try {
+ type = (JClassType) context.getTypeOracle().parse(typeName);
+ } catch (TypeOracleException e1) {
+ logger.log(Type.ERROR, "Could not find type " + typeName, e1);
+ throw new UnableToCompleteException();
+ }
+ String serializerClassName = getSerializerSimpleClassName(type);
try {
// Generate class source code
- generateClass(logger, context, beanType, beanSerializerPackageName,
- beanSerializerClassName);
+ generateClass(logger, context, type, serializerPackageName,
+ serializerClassName);
} catch (Exception e) {
logger.log(TreeLogger.ERROR, "SerializerGenerator failed for "
- + beanType.getQualifiedSourceName(), e);
+ + type.getQualifiedSourceName(), e);
throw new UnableToCompleteException();
}
// return the fully qualifed name of the class generated
- return getFullyQualifiedSerializerClassName(beanType);
+ return getFullyQualifiedSerializerClassName(type);
}
/**
@@ -75,15 +82,16 @@ public class SerializerGenerator extends Generator {
* Logger object
* @param context
* Generator context
- * @param beanType
+ * @param type
* @param beanTypeName
* 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) {
+ JClassType type, String serializerPackageName,
+ String serializerClassName) throws UnableToCompleteException {
// get print writer that receives the source code
PrintWriter printWriter = null;
printWriter = context.tryCreate(logger, serializerPackageName,
@@ -93,27 +101,33 @@ public class SerializerGenerator extends Generator {
if (printWriter == null) {
return;
}
- boolean isEnum = (beanType.isEnum() != null);
+ boolean isEnum = (type.isEnum() != null);
+ boolean isArray = (type.isArray() != null);
- Date date = new Date();
- TypeOracle typeOracle = context.getTypeOracle();
- String beanQualifiedSourceName = beanType.getQualifiedSourceName();
+ String qualifiedSourceName = type.getQualifiedSourceName();
logger.log(Type.DEBUG, "Processing serializable type "
- + beanQualifiedSourceName + "...");
+ + qualifiedSourceName + "...");
// init composer, set class properties, create source writer
ClassSourceFileComposerFactory composer = null;
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());
// composer.addImport(VPaintableMap.class.getName());
composer.addImport(JsonDecoder.class.getName());
// composer.addImport(VaadinSerializer.class.getName());
- composer.addImplementedInterface(JSONSerializer.class.getName() + "<"
- + beanQualifiedSourceName + ">");
+ if (isEnum || isArray) {
+ composer.addImplementedInterface(JSONSerializer.class.getName()
+ + "<" + qualifiedSourceName + ">");
+ } else {
+ composer.addImplementedInterface(DiffJSONSerializer.class.getName()
+ + "<" + qualifiedSourceName + ">");
+ }
SourceWriter sourceWriter = composer.createSourceWriter(context,
printWriter);
@@ -121,49 +135,76 @@ 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, "
+ + " serialize(" + qualifiedSourceName + " value, "
+ ApplicationConnection.class.getName() + " connection) {");
sourceWriter.indent();
// MouseEventDetails castedValue = (MouseEventDetails) value;
- sourceWriter.println(beanQualifiedSourceName + " castedValue = ("
- + beanQualifiedSourceName + ") value;");
+ sourceWriter.println(qualifiedSourceName + " castedValue = ("
+ + qualifiedSourceName + ") value;");
if (isEnum) {
- writeEnumSerializer(logger, sourceWriter, beanType);
+ writeEnumSerializer(logger, sourceWriter, type);
+ } else if (isArray) {
+ writeArraySerializer(logger, sourceWriter, type.isArray());
} else {
- writeBeanSerializer(logger, sourceWriter, beanType);
+ writeBeanSerializer(logger, sourceWriter, type);
}
// }
+ sourceWriter.outdent();
sourceWriter.println("}");
+ sourceWriter.println();
+
+ // Updater
+ // public void update(T target, Type type, JSONValue jsonValue,
+ // ApplicationConnection connection);
+ if (!isEnum && !isArray) {
+ sourceWriter.println("public void update(" + qualifiedSourceName
+ + " target, Type type, " + JSONValue.class.getName()
+ + " jsonValue, " + ApplicationConnection.class.getName()
+ + " connection) {");
+ sourceWriter.indent();
+
+ writeBeanDeserializer(logger, sourceWriter, type);
+
+ sourceWriter.outdent();
+ sourceWriter.println("}");
+ }
// Deserializer
- sourceWriter.println("public " + beanQualifiedSourceName
- + " deserialize(" + JSONValue.class.getName() + " jsonValue, "
- + beanQualifiedSourceName + " target, "
- + ConnectorMap.class.getName() + " idMapper, "
- + ApplicationConnection.class.getName() + " connection) {");
+ // T deserialize(Type type, JSONValue jsonValue, ApplicationConnection
+ // connection);
+ sourceWriter.println("public " + qualifiedSourceName
+ + " deserialize(Type type, " + JSONValue.class.getName()
+ + " jsonValue, " + ApplicationConnection.class.getName()
+ + " connection) {");
sourceWriter.indent();
if (isEnum) {
- writeEnumDeserializer(logger, sourceWriter, beanType.isEnum());
+ writeEnumDeserializer(logger, sourceWriter, type.isEnum());
+ } else if (isArray) {
+ writeArrayDeserializer(logger, sourceWriter, type.isArray());
} else {
- writeBeanDeserializer(logger, sourceWriter, beanType);
+ sourceWriter.println(qualifiedSourceName + " target = GWT.create("
+ + qualifiedSourceName + ".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);
logger.log(TreeLogger.INFO, "Generated Serializer class "
- + getFullyQualifiedSerializerClassName(beanType));
+ + getFullyQualifiedSerializerClassName(type));
}
private void writeEnumDeserializer(TreeLogger logger,
@@ -182,27 +223,56 @@ public class SerializerGenerator extends Generator {
sourceWriter.println("return null;");
}
- private void writeBeanDeserializer(TreeLogger logger,
- SourceWriter sourceWriter, JClassType beanType) {
- String beanQualifiedSourceName = beanType.getQualifiedSourceName();
+ private void writeArrayDeserializer(TreeLogger logger,
+ SourceWriter sourceWriter, JArrayType type) {
+ JType leafType = type.getLeafType();
+ int rank = type.getRank();
+
+ sourceWriter.println(JSONArray.class.getName()
+ + " jsonArray = jsonValue.isArray();");
- // if (target == null) {
- sourceWriter.println("if (target == null) {");
+ // Type value = new Type[jsonArray.size()][][];
+ sourceWriter.print(type.getQualifiedSourceName() + " value = new "
+ + leafType.getQualifiedSourceName() + "[jsonArray.size()]");
+ for (int i = 1; i < rank; i++) {
+ sourceWriter.print("[]");
+ }
+ sourceWriter.println(";");
+
+ sourceWriter.println("for(int i = 0 ; i < value.length; i++) {");
sourceWriter.indent();
- // target = GWT.create(VButtonState.class);
- sourceWriter.println("target = GWT.create(" + beanQualifiedSourceName
- + ".class);");
+ JType componentType = type.getComponentType();
+
+ sourceWriter.print("value[i] = ("
+ + GeneratedRpcMethodProviderGenerator
+ .getBoxedTypeName(componentType) + ") "
+ + JsonDecoder.class.getName() + ".decodeValue(");
+ GeneratedRpcMethodProviderGenerator.writeTypeCreator(sourceWriter,
+ componentType);
+ sourceWriter.print(", jsonArray.get(i), null, connection)");
+
+ sourceWriter.println(";");
+
sourceWriter.outdent();
sourceWriter.println("}");
+ sourceWriter.println("return value;");
+ }
+
+ private void writeBeanDeserializer(TreeLogger logger,
+ SourceWriter sourceWriter, JClassType beanType) {
+ String beanQualifiedSourceName = beanType.getQualifiedSourceName();
+
// JSONOBject json = (JSONObject)jsonValue;
sourceWriter.println(JSONObject.class.getName() + " json = ("
+ JSONObject.class.getName() + ")jsonValue;");
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 "
@@ -213,55 +283,41 @@ 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;
+ 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();
}
- // 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));");
+ 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("}");
}
-
- // return target;
- sourceWriter.println("return target;");
-
}
private void writeEnumSerializer(TreeLogger logger,
@@ -271,16 +327,47 @@ public class SerializerGenerator extends Generator {
+ "(castedValue.name());");
}
+ private void writeArraySerializer(TreeLogger logger,
+ SourceWriter sourceWriter, JArrayType array) {
+ sourceWriter.println(JSONArray.class.getName() + " values = new "
+ + JSONArray.class.getName() + "();");
+ JType componentType = array.getComponentType();
+ // JPrimitiveType primitive = componentType.isPrimitive();
+ sourceWriter.println("for (int i = 0; i < castedValue.length; i++) {");
+ sourceWriter.indent();
+ sourceWriter.print("values.set(i, ");
+ sourceWriter.print(JsonEncoder.class.getName()
+ + ".encode(castedValue[i], false, connection)");
+ sourceWriter.println(");");
+ sourceWriter.outdent();
+ sourceWriter.println("}");
+ sourceWriter.println("return values;");
+ }
+
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<String> usedFieldNames = new HashSet<String>();
+
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) {
@@ -292,13 +379,18 @@ 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;");
}
+ 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);
@@ -344,10 +436,15 @@ public class SerializerGenerator extends Generator {
return getSimpleClassName(beanType) + "_Serializer";
}
- private static String getSimpleClassName(JClassType type) {
- if (type.isMemberType()) {
+ private static String getSimpleClassName(JType type) {
+ JArrayType arrayType = type.isArray();
+ if (arrayType != null) {
+ return "Array" + getSimpleClassName(arrayType.getComponentType());
+ }
+ JClassType classType = type.isClass();
+ if (classType != null && classType.isMemberType()) {
// Assumed to be static sub class
- String baseName = getSimpleClassName(type.getEnclosingType());
+ String baseName = getSimpleClassName(classType.getEnclosingType());
String name = baseName + SUBTYPE_SEPARATOR
+ type.getSimpleSourceName();
return name;
@@ -356,7 +453,6 @@ public class SerializerGenerator extends Generator {
}
public static String getFullyQualifiedSerializerClassName(JClassType type) {
- return beanSerializerPackageName + "."
- + getSerializerSimpleClassName(type);
+ return serializerPackageName + "." + getSerializerSimpleClassName(type);
}
}
diff --git a/src/com/vaadin/terminal/gwt/widgetsetutils/SerializerMapGenerator.java b/src/com/vaadin/terminal/gwt/widgetsetutils/SerializerMapGenerator.java
index 07efcda91b..5e151323a0 100644
--- a/src/com/vaadin/terminal/gwt/widgetsetutils/SerializerMapGenerator.java
+++ b/src/com/vaadin/terminal/gwt/widgetsetutils/SerializerMapGenerator.java
@@ -17,6 +17,7 @@ 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.JArrayType;
import com.google.gwt.core.ext.typeinfo.JClassType;
import com.google.gwt.core.ext.typeinfo.JMethod;
import com.google.gwt.core.ext.typeinfo.JParameterizedType;
@@ -96,6 +97,10 @@ public class SerializerMapGenerator extends Generator {
JClassType javaSerializable = typeOracle.findType(Serializable.class
.getName());
for (JClassType type : typesNeedingSerializers) {
+ if (type.isArray() != null) {
+ // Don't check for arrays
+ continue;
+ }
boolean serializable = type.isAssignableTo(javaSerializable);
if (!serializable) {
logger.log(
@@ -166,8 +171,15 @@ public class SerializerMapGenerator extends Generator {
// TODO cache serializer instances in a map
for (JClassType type : typesNeedingSerializers) {
- sourceWriter.println("if (type.equals(\""
- + type.getQualifiedBinaryName() + "\")) {");
+ sourceWriter.print("if (type.equals(\""
+ + type.getQualifiedSourceName() + "\")");
+ if (type instanceof JArrayType) {
+ // Also add binary name to support encoding based on
+ // object.getClass().getName()
+ sourceWriter.print("||type.equals(\"" + type.getJNISignature()
+ + "\")");
+ }
+ sourceWriter.println(") {");
sourceWriter.indent();
String serializerName = SerializerGenerator
.getFullyQualifiedSerializerClassName(type);
@@ -203,6 +215,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);
@@ -276,6 +289,14 @@ public class SerializerMapGenerator extends Generator {
serializableTypes.add(typeClass);
findSubTypesNeedingSerializers(typeClass, serializableTypes);
}
+
+ // Generate (n-1)-dimensional array serializer for n-dimensional array
+ JArrayType arrayType = type.isArray();
+ if (arrayType != null) {
+ serializableTypes.add(arrayType);
+ addTypeIfNeeded(serializableTypes, arrayType.getComponentType());
+ }
+
}
Set<Class<?>> frameworkHandledTypes = new HashSet<Class<?>>();
@@ -292,15 +313,14 @@ public class SerializerMapGenerator extends Generator {
frameworkHandledTypes.add(Map.class);
frameworkHandledTypes.add(List.class);
frameworkHandledTypes.add(Set.class);
+ frameworkHandledTypes.add(Byte.class);
+ frameworkHandledTypes.add(Character.class);
}
private boolean serializationHandledByFramework(JType setterType) {
// Some types are handled by the framework at the moment. See #8449
// This method should be removed at some point.
- if (setterType.isArray() != null) {
- return true;
- }
if (setterType.isPrimitive() != null) {
return true;
}
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<Class<? extends ComponentConnector>> connectors = getUsedConnectors(context
+ Collection<Class<? extends ServerConnector>> connectors = getUsedConnectors(context
.getTypeOracle());
validateConnectors(logger, connectors);
@@ -149,12 +149,11 @@ public class WidgetMapGenerator extends Generator {
}
private void validateConnectors(TreeLogger logger,
- Collection<Class<? extends ComponentConnector>> connectors) {
+ Collection<Class<? extends ServerConnector>> connectors) {
- Iterator<Class<? extends ComponentConnector>> iter = connectors
- .iterator();
+ Iterator<Class<? extends ServerConnector>> iter = connectors.iterator();
while (iter.hasNext()) {
- Class<? extends ComponentConnector> connectorClass = iter.next();
+ Class<? extends ServerConnector> 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<Class<? extends ComponentConnector>> connectors) {
+ Collection<Class<? extends ServerConnector>> connectors) {
logger.log(Type.INFO,
"Widget set will contain implementations for following component connectors: ");
TreeSet<String> classNames = new TreeSet<String>();
HashMap<String, String> loadStyle = new HashMap<String, String>();
- for (Class<? extends ComponentConnector> connectorClass : connectors) {
+ for (Class<? extends ServerConnector> 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<Class<? extends ComponentConnector>> getUsedConnectors(
+ private Collection<Class<? extends ServerConnector>> getUsedConnectors(
TypeOracle typeOracle) {
JClassType connectorType = typeOracle.findType(Connector.class
.getName());
- Collection<Class<? extends ComponentConnector>> connectors = new HashSet<Class<? extends ComponentConnector>>();
+ Collection<Class<? extends ServerConnector>> connectors = new HashSet<Class<? extends ServerConnector>>();
for (JClassType jClassType : connectorType.getSubtypes()) {
Connect annotation = jClassType.getAnnotation(Connect.class);
if (annotation != null) {
try {
- Class<? extends ComponentConnector> clazz = (Class<? extends ComponentConnector>) Class
+ Class<? extends ServerConnector> clazz = (Class<? extends ServerConnector>) 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<? extends ComponentConnector> connector) {
+ protected LoadStyle getLoadStyle(Class<? extends ServerConnector> connector) {
Connect annotation = connector.getAnnotation(Connect.class);
return annotation.loadStyle();
}
private void generateInstantiatorMethod(
SourceWriter sourceWriter,
- Collection<Class<? extends ComponentConnector>> connectorsHavingComponentAnnotation) {
+ Collection<Class<? extends ServerConnector>> connectorsHavingComponentAnnotation) {
Collection<Class<?>> deferredWidgets = new LinkedList<Class<?>>();
@@ -258,16 +256,16 @@ public class WidgetMapGenerator extends Generator {
// lookup with index than with the hashmap
sourceWriter.println("public void ensureInstantiator(Class<? extends "
- + componentConnectorClassName + "> classType) {");
+ + serverConnectorClassName + "> classType) {");
sourceWriter.println("if(!instmap.containsKey(classType)){");
boolean first = true;
- ArrayList<Class<? extends ComponentConnector>> lazyLoadedWidgets = new ArrayList<Class<? extends ComponentConnector>>();
+ ArrayList<Class<? extends ServerConnector>> lazyLoadedConnectors = new ArrayList<Class<? extends ServerConnector>>();
- HashSet<Class<? extends com.vaadin.terminal.gwt.client.ComponentConnector>> connectorsWithInstantiator = new HashSet<Class<? extends com.vaadin.terminal.gwt.client.ComponentConnector>>();
+ HashSet<Class<? extends ServerConnector>> connectorsWithInstantiator = new HashSet<Class<? extends ServerConnector>>();
- for (Class<? extends ComponentConnector> class1 : connectorsHavingComponentAnnotation) {
- Class<? extends ComponentConnector> clientClass = class1;
+ for (Class<? extends ServerConnector> class1 : connectorsHavingComponentAnnotation) {
+ Class<? extends ServerConnector> 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<? extends "
- + componentConnectorClassName
- + ">[] 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<? extends " + componentConnectorClassName
+ sourceWriter.println("public " + serverConnectorClassName
+ + " instantiate(Class<? extends " + serverConnectorClassName
+ "> 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<Class<? extends ComponentConnector>> paintablesHavingWidgetAnnotation) {
+ Collection<Class<? extends ServerConnector>> paintablesHavingWidgetAnnotation) {
sourceWriter
.println("public Class<? extends "
- + componentConnectorClassName
+ + serverConnectorClassName
+ "> "
+ "getConnectorClassForServerSideClassName(String fullyQualifiedName) {");
sourceWriter.indent();
sourceWriter
.println("fullyQualifiedName = fullyQualifiedName.intern();");
- for (Class<? extends ComponentConnector> connectorClass : paintablesHavingWidgetAnnotation) {
+ for (Class<? extends ServerConnector> connectorClass : paintablesHavingWidgetAnnotation) {
Class<? extends ClientConnector> clientConnectorClass = getClientConnectorClass(connectorClass);
sourceWriter.print("if ( fullyQualifiedName == \"");
sourceWriter.print(clientConnectorClass.getName());
@@ -393,7 +391,7 @@ public class WidgetMapGenerator extends Generator {
}
private static Class<? extends ClientConnector> getClientConnectorClass(
- Class<? extends ComponentConnector> connectorClass) {
+ Class<? extends ServerConnector> connectorClass) {
Connect annotation = connectorClass.getAnnotation(Connect.class);
return (Class<? extends ClientConnector>) annotation.value();
}
diff --git a/src/com/vaadin/tools/WidgetsetCompiler.java b/src/com/vaadin/tools/WidgetsetCompiler.java
index 323fb17e32..407f0e2387 100644
--- a/src/com/vaadin/tools/WidgetsetCompiler.java
+++ b/src/com/vaadin/tools/WidgetsetCompiler.java
@@ -30,12 +30,12 @@ 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
- .getLogger(WidgetsetCompiler.class.getName());
-
/**
* @param args
* same arguments as for com.google.gwt.dev.Compiler
@@ -72,7 +72,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 +82,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/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<String, String> connectorToPosition = new HashMap<String, String>();
- for (Component c : this) {
+ for (Iterator<Component> 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..ba0e5db89c 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 */
@@ -64,11 +54,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.
*/
private EventRouter eventRouter = null;
@@ -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<RepaintRequestListener> 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<Class<?>, RpcManager> rpcManagerMap = new HashMap<Class<?>, RpcManager>();
-
- /**
- * A map from server to client RPC interface class to the RPC proxy that
- * sends ourgoing RPC calls for that interface.
- */
- private Map<Class<?>, ClientRpc> rpcProxyMap = new HashMap<Class<?>, 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<ClientMethodInvocation> pendingInvocations = new ArrayList<ClientMethodInvocation>();
-
- 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,14 @@ 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() {
+ super.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 +651,10 @@ public abstract class AbstractComponent implements Component, MethodEventSource
* @return the parent application of the component or <code>null</code>.
* @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 +694,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 +731,15 @@ public abstract class AbstractComponent implements Component, MethodEventSource
}
}
- /**
- * Creates the shared state bean to be used in server to client
- * communication.
- * <p>
- * 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.
- * </p>
- * <p>
- * 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<? extends ComponentState> getStateType() {
- try {
- Method m = getClass().getMethod("getState", (Class[]) null);
- Class<? extends ComponentState> type = (Class<? extends ComponentState>) 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<RepaintRequestListener>();
- }
- 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 +1005,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 +1353,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 <T> void registerRpc(T implementation, Class<T> rpcInterfaceType) {
- rpcManagerMap.put(rpcInterfaceType, new ServerRpcManager<T>(
- 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 <T extends ServerRpc> 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<T> rpcInterfaceType) if the Rpc implementation implements more than one interface");
- }
- Class<T> type = (Class<T>) 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 extends ClientRpc> T getRpcProxy(final Class<T> rpcInterface) {
- // create, initialize and return a dynamic proxy for RPC
- try {
- if (!rpcProxyMap.containsKey(rpcInterface)) {
- Class<T> proxyClass = (Class) Proxy.getProxyClass(
- rpcInterface.getClassLoader(), rpcInterface);
- Constructor<T> 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<ClientMethodInvocation> retrievePendingRpcCalls() {
- if (pendingInvocations.isEmpty()) {
- return Collections.emptyList();
- } else {
- List<ClientMethodInvocation> result = pendingInvocations;
- pendingInvocations = new ArrayList<ClientMethodInvocation>();
- 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<Component> 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<Component> 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<Component> 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<Component> iterator() {
return getComponentIterator();
}
diff --git a/src/com/vaadin/ui/AbstractField.java b/src/com/vaadin/ui/AbstractField.java
index 4efed11e2c..ce62fb43ed 100644
--- a/src/com/vaadin/ui/AbstractField.java
+++ b/src/com/vaadin/ui/AbstractField.java
@@ -14,14 +14,14 @@ import java.util.LinkedList;
import java.util.List;
import java.util.logging.Logger;
-import com.vaadin.Application;
import com.vaadin.data.Buffered;
import com.vaadin.data.Property;
import com.vaadin.data.Validatable;
import com.vaadin.data.Validator;
import com.vaadin.data.Validator.InvalidValueException;
import com.vaadin.data.util.converter.Converter;
-import com.vaadin.data.util.converter.ConverterFactory;
+import com.vaadin.data.util.converter.Converter.ConversionException;
+import com.vaadin.data.util.converter.ConverterUtil;
import com.vaadin.event.Action;
import com.vaadin.event.ShortcutAction;
import com.vaadin.event.ShortcutListener;
@@ -591,7 +591,7 @@ public abstract class AbstractField<T> extends AbstractComponent implements
// Commits the value to datasource
committingValueToDataSource = true;
getPropertyDataSource().setValue(
- convertToDataSource(newFieldValue));
+ convertToModel(newFieldValue));
// The buffer is now unmodified
setModified(false);
@@ -701,8 +701,8 @@ public abstract class AbstractField<T> extends AbstractComponent implements
// Check if the current converter is compatible.
if (newDataSource != null
- && (getConverter() == null || !newDataSource.getType()
- .isAssignableFrom(getConverter().getModelType()))) {
+ && !ConverterUtil.canConverterHandle(getConverter(), getType(),
+ newDataSource.getType())) {
// Changing from e.g. Number -> Double should set a new converter,
// changing from Double -> Number can keep the old one (Property
// accepts Number)
@@ -760,15 +760,9 @@ public abstract class AbstractField<T> extends AbstractComponent implements
* from
*/
public void setConverter(Class<?> datamodelType) {
- Converter<T, ?> converter = null;
-
- Application app = Application.getCurrentApplication();
- if (app != null) {
- ConverterFactory factory = app.getConverterFactory();
- converter = (Converter<T, ?>) factory.createConverter(getType(),
- datamodelType);
- }
- setConverter(converter);
+ Converter<T, ?> c = (Converter<T, ?>) ConverterUtil.getConverter(
+ getType(), datamodelType, getApplication());
+ setConverter(c);
}
/**
@@ -782,26 +776,9 @@ public abstract class AbstractField<T> extends AbstractComponent implements
* if there is no converter and the type is not compatible with
* the data source type.
*/
- @SuppressWarnings("unchecked")
- private T convertFromDataSource(Object newValue)
- throws Converter.ConversionException {
- if (converter != null) {
- return converter.convertToPresentation(newValue, getLocale());
- }
- if (newValue == null) {
- return null;
- }
-
- if (getType().isAssignableFrom(newValue.getClass())) {
- return (T) newValue;
- } else {
- throw new Converter.ConversionException(
- "Unable to convert value of type "
- + newValue.getClass().getName()
- + " to "
- + getType()
- + ". No converter is set and the types are not compatible.");
- }
+ private T convertFromDataSource(Object newValue) {
+ return ConverterUtil.convertFromModel(newValue, getType(),
+ getConverter(), getLocale());
}
/**
@@ -815,40 +792,21 @@ public abstract class AbstractField<T> extends AbstractComponent implements
* if there is no converter and the type is not compatible with
* the data source type.
*/
- private Object convertToDataSource(T fieldValue)
+ private Object convertToModel(T fieldValue)
throws Converter.ConversionException {
- if (converter != null) {
- /*
- * If there is a converter, always use it. It must convert or throw
- * an exception.
- */
- try {
- return converter.convertToModel(fieldValue, getLocale());
- } catch (com.vaadin.data.util.converter.Converter.ConversionException e) {
- throw new Converter.ConversionException(
- getConversionError(converter.getModelType()), e);
+ try {
+ Class<?> modelType = null;
+ Property pd = getPropertyDataSource();
+ if (pd != null) {
+ modelType = pd.getType();
+ } else if (getConverter() != null) {
+ modelType = getConverter().getModelType();
}
- }
-
- if (fieldValue == null) {
- // Null should always be passed through the converter but if there
- // is no converter we can safely return null
- return null;
- }
-
- // check that the value class is compatible with the data source type
- // (if data source set) or field type
- Class<?> type;
- if (getPropertyDataSource() != null) {
- type = getPropertyDataSource().getType();
- } else {
- type = getType();
- }
-
- if (type.isAssignableFrom(fieldValue.getClass())) {
- return fieldValue;
- } else {
- throw new Converter.ConversionException(getConversionError(type));
+ return ConverterUtil.convertToModel(fieldValue,
+ (Class<Object>) modelType, getConverter(), getLocale());
+ } catch (ConversionException e) {
+ throw new ConversionException(
+ getConversionError(converter.getModelType()), e);
}
}
@@ -880,7 +838,7 @@ public abstract class AbstractField<T> extends AbstractComponent implements
* @return The converted value that is compatible with the data source type
*/
public Object getConvertedValue() {
- return convertToDataSource(getFieldValue());
+ return convertToModel(getFieldValue());
}
/**
diff --git a/src/com/vaadin/ui/AbstractJavaScriptComponent.java b/src/com/vaadin/ui/AbstractJavaScriptComponent.java
new file mode 100644
index 0000000000..95c45f55f9
--- /dev/null
+++ b/src/com/vaadin/ui/AbstractJavaScriptComponent.java
@@ -0,0 +1,161 @@
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+package com.vaadin.ui;
+
+import com.vaadin.terminal.JavaScriptCallbackHelper;
+import com.vaadin.terminal.gwt.client.ui.JavaScriptComponentState;
+import com.vaadin.terminal.gwt.client.ui.JavaScriptWidget;
+
+/**
+ * Base class for Components with all client-side logic implemented using
+ * JavaScript.
+ * <p>
+ * When a new JavaScript component is initialized in the browser, the framework
+ * will look for a globally defined JavaScript function that will initialize the
+ * component. The name of the initialization function is formed by replacing .
+ * with _ in the name of the server-side class. If no such function is defined,
+ * each super class is used in turn until a match is found. The framework will
+ * thus first attempt with <code>com_example_MyComponent</code> for the
+ * server-side
+ * <code>com.example.MyComponent extends AbstractJavaScriptComponent</code>
+ * class. If MyComponent instead extends <code>com.example.SuperComponent</code>
+ * , then <code>com_example_SuperComponent</code> will also be attempted if
+ * <code>com_example_MyComponent</code> has not been defined.
+ * <p>
+ * JavaScript components have a very simple GWT widget ({@link JavaScriptWidget}
+ * ) just consisting of a <code>div</code> element to which the JavaScript code
+ * should initialize its own user interface.
+ * <p>
+ * The initialization function will be called with <code>this</code> pointing to
+ * a connector wrapper object providing integration to Vaadin with the following
+ * functions:
+ * <ul>
+ * <li><code>getConnectorId()</code> - returns a string with the id of the
+ * connector.</li>
+ * <li><code>getParentId([connectorId])</code> - returns a string with the id of
+ * the connector's parent. If <code>connectorId</code> is provided, the id of
+ * the parent of the corresponding connector with the passed id is returned
+ * instead.</li>
+ * <li><code>getWidgetElement([connectorId])</code> - returns the DOM Element
+ * that is the root of a connector's widget. <code>null</code> is returned if
+ * the connector can not be found or if the connector doesn't have a widget. If
+ * <code>connectorId</code> is not provided, the connector id of the current
+ * connector will be used.</li>
+ * <li><code>getState()</code> - returns an object corresponding to the shared
+ * state defined on the server. The scheme for conversion between Java and
+ * JavaScript types is described bellow.</li>
+ * <li><code>registerRpc([name, ] rpcObject)</code> - registers the
+ * <code>rpcObject</code> as a RPC handler. <code>rpcObject</code> should be an
+ * object with field containing functions for all eligible RPC functions. If
+ * <code>name</code> is provided, the RPC handler will only used for RPC calls
+ * for the RPC interface with the same fully qualified Java name. If no
+ * <code>name</code> is provided, the RPC handler will be used for all incoming
+ * RPC invocations where the RPC method name is defined as a function field in
+ * the handler. The scheme for conversion between Java types in the RPC
+ * interface definition and the JavaScript values passed as arguments to the
+ * handler functions is described bellow.</li>
+ * <li><code>getRpcProxy([name])</code> - returns an RPC proxy object. If
+ * <code>name</code> is provided, the proxy object will contain functions for
+ * all methods in the RPC interface with the same fully qualified name, provided
+ * a RPC handler has been registered by the server-side code. If no
+ * <code>name</code> is provided, the returned RPC proxy object will contain
+ * functions for all methods in all RPC interfaces registered for the connector
+ * on the server. If the same method name is present in multiple registered RPC
+ * interfaces, the corresponding function in the RPC proxy object will throw an
+ * exception when called. The scheme for conversion between Java types in the
+ * RPC interface and the JavaScript values that should be passed to the
+ * functions is described bellow.</li>
+ * </ul>
+ * The connector wrapper also supports these special functions:
+ * <ul>
+ * <li><code>onStateChange</code> - If the JavaScript code assigns a function to
+ * the field, that function is called whenever the contents of the shared state
+ * is changed.</li>
+ * <li>Any field name corresponding to a call to
+ * {@link #registerCallback(String, JavaScriptCallback)} on the server will
+ * automatically be present as a function that triggers the registered callback
+ * on the server.</li>
+ * <li>Any field name referred to using
+ * {@link #invokeCallback(String, Object...)} on the server will be called if a
+ * function has been assigned to the field.</li>
+ * </ul>
+ * <p>
+ *
+ * Values in the Shared State and in RPC calls are converted between Java and
+ * JavaScript using the following conventions:
+ * <ul>
+ * <li>Primitive Java numbers (byte, char, int, long, float, double) and their
+ * boxed types (Byte, Character, Integer, Long, Float, Double) are represented
+ * by JavaScript numbers.</li>
+ * <li>The primitive Java boolean and the boxed Boolean are represented by
+ * JavaScript booleans.</li>
+ * <li>Java Strings are represented by JavaScript strings.</li>
+ * <li>List, Set and all arrays in Java are represented by JavaScript arrays.</li>
+ * <li>Map<String, ?> in Java is represented by JavaScript object with fields
+ * corresponding to the map keys.</li>
+ * <li>Any other Java Map is represented by a JavaScript array containing two
+ * arrays, the first contains the keys and the second contains the values in the
+ * same order.</li>
+ * <li>A Java Bean is represented by a JavaScript object with fields
+ * corresponding to the bean's properties.</li>
+ * <li>A Java Connector is represented by a JavaScript string containing the
+ * connector's id.</li>
+ * <li>A pluggable serialization mechanism is provided for types not described
+ * here. Please refer to the documentation for specific types for serialization
+ * information.</li>
+ * </ul>
+ *
+ * @author Vaadin Ltd
+ * @version @VERSION@
+ * @since 7.0.0
+ */
+public class AbstractJavaScriptComponent extends AbstractComponent {
+ private JavaScriptCallbackHelper callbackHelper = new JavaScriptCallbackHelper(
+ this);
+
+ @Override
+ protected <T> void registerRpc(T implementation, Class<T> rpcInterfaceType) {
+ super.registerRpc(implementation, rpcInterfaceType);
+ callbackHelper.registerRpc(rpcInterfaceType);
+ }
+
+ /**
+ * Register a {@link JavaScriptCallback} that can be called from the
+ * JavaScript using the provided name. A JavaScript function with the
+ * provided name will be added to the connector wrapper object (initially
+ * available as <code>this</code>). Calling that JavaScript function will
+ * cause the call method in the registered {@link JavaScriptCallback} to be
+ * invoked with the same arguments.
+ *
+ * @param functionName
+ * the name that should be used for client-side callback
+ * @param javaScriptCallback
+ * the callback object that will be invoked when the JavaScript
+ * function is called
+ */
+ protected void registerCallback(String functionName,
+ JavaScriptCallback javaScriptCallback) {
+ callbackHelper.registerCallback(functionName, javaScriptCallback);
+ }
+
+ /**
+ * Invoke a named function that the connector JavaScript has added to the
+ * JavaScript connector wrapper object. The arguments should only contain
+ * data types that can be represented in JavaScript, including primitive
+ * boxing types, arrays, String, List, Set, Map, Connector and JavaBeans.
+ *
+ * @param name
+ * the name of the function
+ * @param arguments
+ * function arguments
+ */
+ protected void invokeCallback(String name, Object... arguments) {
+ callbackHelper.invokeCallback(name, arguments);
+ }
+
+ @Override
+ public JavaScriptComponentState getState() {
+ return (JavaScriptComponentState) super.getState();
+ }
+}
diff --git a/src/com/vaadin/ui/AbstractSelect.java b/src/com/vaadin/ui/AbstractSelect.java
index e586810b2d..6a927251af 100644
--- a/src/com/vaadin/ui/AbstractSelect.java
+++ b/src/com/vaadin/ui/AbstractSelect.java
@@ -24,7 +24,6 @@ import com.vaadin.event.Transferable;
import com.vaadin.event.dd.DragAndDropEvent;
import com.vaadin.event.dd.DropTarget;
import com.vaadin.event.dd.TargetDetailsImpl;
-import com.vaadin.event.dd.acceptcriteria.ClientCriterion;
import com.vaadin.event.dd.acceptcriteria.ClientSideCriterion;
import com.vaadin.event.dd.acceptcriteria.ContainsDataFlavor;
import com.vaadin.event.dd.acceptcriteria.TargetDetailIs;
@@ -33,8 +32,6 @@ import com.vaadin.terminal.PaintException;
import com.vaadin.terminal.PaintTarget;
import com.vaadin.terminal.Resource;
import com.vaadin.terminal.Vaadin6Component;
-import com.vaadin.terminal.gwt.client.ui.dd.VIsOverId;
-import com.vaadin.terminal.gwt.client.ui.dd.VItemIdIs;
import com.vaadin.terminal.gwt.client.ui.dd.VerticalDropLocation;
import com.vaadin.ui.AbstractSelect.ItemCaptionMode;
@@ -1800,7 +1797,6 @@ public abstract class AbstractSelect extends AbstractField<Object> implements
*
* @since 6.3
*/
- @ClientCriterion(VIsOverId.class)
public static class TargetItemIs extends AbstractItemSetCriterion {
/**
@@ -1867,7 +1863,6 @@ public abstract class AbstractSelect extends AbstractField<Object> implements
*
* @since 6.3
*/
- @ClientCriterion(VItemIdIs.class)
public static class AcceptItem extends AbstractItemSetCriterion {
/**
diff --git a/src/com/vaadin/ui/AbstractSplitPanel.java b/src/com/vaadin/ui/AbstractSplitPanel.java
index 5205952621..876d39f2ae 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.
*
* <code>AbstractSplitPanel</code> 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
@@ -31,7 +31,10 @@ import com.vaadin.tools.ReflectTools;
*/
public abstract class AbstractSplitPanel extends AbstractComponentContainer {
+ // TODO use Unit in AbstractSplitPanelState and remove these
private Unit posUnit;
+ private Unit posMinUnit;
+ private Unit posMaxUnit;
private AbstractSplitPanelRpc rpc = new AbstractSplitPanelRpc() {
@@ -41,13 +44,14 @@ public abstract class AbstractSplitPanel extends AbstractComponentContainer {
}
public void setSplitterPosition(float position) {
- getState().getSplitterState().setPosition(position);
+ getSplitterState().setPosition(position);
}
};
public AbstractSplitPanel() {
registerRpc(rpc);
setSplitPosition(50, Unit.PERCENTAGE, false);
+ setSplitPositionLimits(0, Unit.PERCENTAGE, 100, Unit.PERCENTAGE);
}
/**
@@ -101,6 +105,7 @@ public abstract class AbstractSplitPanel extends AbstractComponentContainer {
* @param c
* the component to be added.
*/
+
@Override
public void addComponent(Component c) {
if (getFirstComponent() == null) {
@@ -188,6 +193,7 @@ public abstract class AbstractSplitPanel extends AbstractComponentContainer {
* @param c
* the component to be removed.
*/
+
@Override
public void removeComponent(Component c) {
super.removeComponent(c);
@@ -204,6 +210,7 @@ public abstract class AbstractSplitPanel extends AbstractComponentContainer {
*
* @see com.vaadin.ui.ComponentContainer#getComponentIterator()
*/
+
public Iterator<Component> getComponentIterator() {
return new ComponentIterator();
}
@@ -214,6 +221,7 @@ public abstract class AbstractSplitPanel extends AbstractComponentContainer {
*
* @return the number of contained components (zero, one or two)
*/
+
public int getComponentCount() {
int count = 0;
if (getFirstComponent() != null) {
@@ -226,6 +234,7 @@ public abstract class AbstractSplitPanel extends AbstractComponentContainer {
}
/* Documented in superclass */
+
public void replaceComponent(Component oldComponent, Component newComponent) {
if (oldComponent == getFirstComponent()) {
setFirstComponent(newComponent);
@@ -297,7 +306,7 @@ public abstract class AbstractSplitPanel extends AbstractComponentContainer {
if (unit != Unit.PERCENTAGE) {
pos = Math.round(pos);
}
- SplitterState splitterState = getState().getSplitterState();
+ SplitterState splitterState = getSplitterState();
splitterState.setPosition(pos);
splitterState.setPositionUnit(unit.getSymbol());
splitterState.setPositionReversed(reverse);
@@ -313,7 +322,7 @@ public abstract class AbstractSplitPanel extends AbstractComponentContainer {
* @return position of the splitter
*/
public float getSplitPosition() {
- return getState().getSplitterState().getPosition();
+ return getSplitterState().getPosition();
}
/**
@@ -326,6 +335,110 @@ public abstract class AbstractSplitPanel extends AbstractComponentContainer {
}
/**
+ * 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 setMinSplitPosition(int pos, Unit unit) {
+ setSplitPositionLimits(pos, unit, getSplitterState().getMaxPosition(),
+ posMaxUnit);
+ }
+
+ /**
+ * Returns the current minimum position of the splitter, in
+ * {@link #getMinSplitPositionUnit()} units.
+ *
+ * @return the minimum position of the splitter
+ */
+ public float getMinSplitPosition() {
+ return getSplitterState().getMinPosition();
+ }
+
+ /**
+ * Returns the unit of the minimum position of the splitter.
+ *
+ * @return the unit of the minimum position of the splitter
+ */
+ public Unit 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(float pos, Unit unit) {
+ setSplitPositionLimits(getSplitterState().getMinPosition(), posMinUnit,
+ pos, unit);
+ }
+
+ /**
+ * Returns the current maximum position of the splitter, in
+ * {@link #getMaxSplitPositionUnit()} units.
+ *
+ * @return the maximum position of the splitter
+ */
+ public float getMaxSplitPosition() {
+ return getSplitterState().getMaxPosition();
+ }
+
+ /**
+ * Returns the unit of the maximum position of the splitter
+ *
+ * @return the unit of the maximum position of the splitter
+ */
+ public Unit 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(float minPos, Unit minPosUnit,
+ float maxPos, Unit maxPosUnit) {
+ if ((minPosUnit != Unit.PERCENTAGE && minPosUnit != Unit.PIXELS)
+ || (maxPosUnit != Unit.PERCENTAGE && maxPosUnit != Unit.PIXELS)) {
+ throw new IllegalArgumentException(
+ "Only percentage and pixel units are allowed");
+ }
+
+ SplitterState state = getSplitterState();
+
+ state.setMinPosition(minPos);
+ state.setMinPositionUnit(minPosUnit.getSymbol());
+ posMinUnit = minPosUnit;
+
+ state.setMaxPosition(maxPos);
+ state.setMaxPositionUnit(maxPosUnit.getSymbol());
+ posMaxUnit = maxPosUnit;
+
+ requestRepaint();
+ }
+
+ /**
* Lock the SplitPanels position, disabling the user from dragging the split
* handle.
*
@@ -333,7 +446,7 @@ public abstract class AbstractSplitPanel extends AbstractComponentContainer {
* Set <code>true</code> if locked, <code>false</code> otherwise.
*/
public void setLocked(boolean locked) {
- getState().getSplitterState().setLocked(locked);
+ getSplitterState().setLocked(locked);
requestRepaint();
}
@@ -344,7 +457,7 @@ public abstract class AbstractSplitPanel extends AbstractComponentContainer {
* @return <code>true</code> if locked, <code>false</code> otherwise.
*/
public boolean isLocked() {
- return getState().getSplitterState().isLocked();
+ return getSplitterState().isLocked();
}
/**
@@ -394,4 +507,7 @@ public abstract class AbstractSplitPanel extends AbstractComponentContainer {
return (AbstractSplitPanelState) super.getState();
}
+ private SplitterState getSplitterState() {
+ return getState().getSplitterState();
+ }
}
diff --git a/src/com/vaadin/ui/Button.java b/src/com/vaadin/ui/Button.java
index 876fe593e2..0abc50f26f 100644
--- a/src/com/vaadin/ui/Button.java
+++ b/src/com/vaadin/ui/Button.java
@@ -38,6 +38,7 @@ public class Button extends AbstractComponent implements
Action.ShortcutNotifier {
private ButtonServerRpc rpc = new ButtonServerRpc() {
+
public void click(MouseEventDetails mouseEventDetails) {
fireClick(mouseEventDetails);
}
@@ -50,6 +51,7 @@ public class Button extends AbstractComponent implements
};
FocusAndBlurServerRpcImpl focusBlurRpc = new FocusAndBlurServerRpcImpl(this) {
+
@Override
protected void fireEvent(Event event) {
Button.this.fireEvent(event);
@@ -355,8 +357,6 @@ public class Button extends AbstractComponent implements
protected ClickShortcut clickShortcut;
- private int tabIndex = 0;
-
/**
* Makes it possible to invoke a click on this button by pressing the given
* {@link KeyCode} and (optional) {@link ModifierKey}s.<br/>
@@ -469,13 +469,23 @@ public class Button extends AbstractComponent implements
requestRepaint();
}
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.vaadin.ui.Component.Focusable#getTabIndex()
+ */
public int getTabIndex() {
- return tabIndex;
+ return getState().getTabIndex();
}
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.vaadin.ui.Component.Focusable#setTabIndex(int)
+ */
public void setTabIndex(int tabIndex) {
- this.tabIndex = tabIndex;
-
+ getState().setTabIndex(tabIndex);
+ requestRepaint();
}
@Override
diff --git a/src/com/vaadin/ui/Component.java b/src/com/vaadin/ui/Component.java
index 3632c4ca5e..81e0319880 100644
--- a/src/com/vaadin/ui/Component.java
+++ b/src/com/vaadin/ui/Component.java
@@ -304,41 +304,10 @@ public interface Component extends ClientConnector, Sizeable, Serializable {
* </p>
*
* @return the parent component
- * @see #setParent(Component)
*/
public HasComponents getParent();
/**
- * Sets the parent component of the component.
- *
- * <p>
- * 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.
- * </p>
- * <p>
- * 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.
- * </p>
- *
- * <p>
- * It is not possible to change the parent without first setting the parent
- * to {@code null}.
- * </p>
- *
- * @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}
* components normally have a value that can be input or changed by the
@@ -528,21 +497,15 @@ public interface Component extends ClientConnector, Sizeable, Serializable {
public void setIcon(Resource icon);
/**
- * Gets the parent window of the component.
+ * Gets the Root the component is attached to.
*
* <p>
- * If the component is not attached to a window through a component
+ * If the component is not attached to a Root through a component
* containment hierarchy, <code>null</code> is returned.
* </p>
*
- * <p>
- * The window can be either an application-level window or a sub-window. If
- * the component is itself a window, it returns a reference to itself, not
- * to its containing window (of a sub-window).
- * </p>
- *
- * @return the parent window of the component or <code>null</code> if it is
- * not attached to a window or is itself a window
+ * @return the Root of the component or <code>null</code> if it is not
+ * attached to a Root
*/
public Root getRoot();
@@ -551,11 +514,16 @@ public interface Component extends ClientConnector, Sizeable, Serializable {
*
* <p>
* The method will return {@code null} if the component is not currently
- * attached to an application. This is often a problem in constructors of
- * regular components and in the initializers of custom composite
- * components. A standard workaround is to move the problematic
- * initialization to {@link #attach()}, as described in the documentation of
- * the method.
+ * attached to an application.
+ * </p>
+ *
+ * <p>
+ * Getting a null value is often a problem in constructors of regular
+ * components and in the initializers of custom composite components. A
+ * standard workaround is to use {@link Application#getCurrent()}
+ * to retrieve the application instance that the current request relates to.
+ * Another way is to move the problematic initialization to
+ * {@link #attach()}, as described in the documentation of the method.
* </p>
*
* @return the parent application of the component or <code>null</code>.
@@ -564,15 +532,7 @@ public interface Component extends ClientConnector, Sizeable, Serializable {
public Application getApplication();
/**
- * Notifies the component that it is connected to an application.
- *
- * <p>
- * 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.
- * </p>
+ * {@inheritDoc}
*
* <p>
* Reimplementing the {@code attach()} method is useful for tasks that need
@@ -624,38 +584,10 @@ public interface Component extends ClientConnector, Sizeable, Serializable {
* }
* }
* </pre>
- *
- * <p>
- * The attachment logic is implemented in {@link AbstractComponent}.
- * </p>
- *
- * @see #getApplication()
*/
public void attach();
/**
- * Notifies the component that it is detached from the application.
- *
- * <p>
- * The {@link #getApplication()} and {@link #getRoot()} methods might return
- * <code>null</code> after this method is called.
- * </p>
- *
- * <p>
- * This method must call {@link Root#componentDetached(Component)} to let
- * the Root know that a new Component has been attached.
- * </p>
- * *
- * <p>
- * 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.
- * </p>
- */
- public void detach();
-
- /**
* Gets the locale of the component.
*
* <p>
@@ -719,75 +651,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 <code>paint</code> 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 <code>paint</code> method will return
- * dissimilar UIDL from the previous call of the method.
- */
- public ClientConnector getConnector() {
- return (ClientConnector) getSource();
- }
- }
-
- /**
- * Listens repaint requests. The <code>repaintRequested</code> method is
- * called when the paintable needs to be repainted. This is typically done
- * when the <code>paint</code> 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/ConnectorTracker.java b/src/com/vaadin/ui/ConnectorTracker.java
new file mode 100644
index 0000000000..75a75ad22a
--- /dev/null
+++ b/src/com/vaadin/ui/ConnectorTracker.java
@@ -0,0 +1,229 @@
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+package com.vaadin.ui;
+
+import java.io.Serializable;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import com.vaadin.terminal.AbstractClientConnector;
+import com.vaadin.terminal.gwt.client.ServerConnector;
+import com.vaadin.terminal.gwt.server.ClientConnector;
+
+/**
+ * A class which takes care of book keeping of {@link ClientConnector}s for one
+ * Root.
+ * <p>
+ * Provides {@link #getConnector(String)} which can be used to lookup a
+ * connector from its id. This is for framework use only and should not be
+ * needed in applications.
+ * </p>
+ * <p>
+ * Tracks which {@link ClientConnector}s are dirty so they can be updated to the
+ * client when the following response is sent. A connector is dirty when an
+ * operation has been performed on it on the server and as a result of this
+ * operation new information needs to be sent to its {@link ServerConnector}.
+ * </p>
+ *
+ * @author Vaadin Ltd
+ * @version @VERSION@
+ * @since 7.0.0
+ *
+ */
+public class ConnectorTracker implements Serializable {
+
+ private final HashMap<String, ClientConnector> connectorIdToConnector = new HashMap<String, ClientConnector>();
+ private Set<ClientConnector> dirtyConnectors = new HashSet<ClientConnector>();
+
+ private Root root;
+
+ /**
+ * Gets a logger for this class
+ *
+ * @return A logger instance for logging within this class
+ *
+ */
+ public static Logger getLogger() {
+ return Logger.getLogger(ConnectorTracker.class.getName());
+ }
+
+ public ConnectorTracker(Root root) {
+ this.root = root;
+ }
+
+ /**
+ * Register the given connector.
+ * <p>
+ * The lookup method {@link #getConnector(String)} only returns registered
+ * connectors.
+ * </p>
+ *
+ * @param connector
+ * The connector to register.
+ */
+ public void registerConnector(ClientConnector connector) {
+ String connectorId = connector.getConnectorId();
+ ClientConnector previouslyRegistered = connectorIdToConnector
+ .get(connectorId);
+ if (previouslyRegistered == null) {
+ connectorIdToConnector.put(connectorId, connector);
+ getLogger().fine(
+ "Registered " + connector.getClass().getSimpleName() + " ("
+ + connectorId + ")");
+ } else if (previouslyRegistered != connector) {
+ throw new RuntimeException("A connector with id " + connectorId
+ + " is already registered!");
+ } else {
+ getLogger().warning(
+ "An already registered connector was registered again: "
+ + connector.getClass().getSimpleName() + " ("
+ + connectorId + ")");
+ }
+
+ }
+
+ /**
+ * Unregister the given connector.
+ *
+ * <p>
+ * The lookup method {@link #getConnector(String)} only returns registered
+ * connectors.
+ * </p>
+ *
+ * @param connector
+ * The connector to unregister
+ */
+ public void unregisterConnector(ClientConnector connector) {
+ String connectorId = connector.getConnectorId();
+ if (!connectorIdToConnector.containsKey(connectorId)) {
+ getLogger().warning(
+ "Tried to unregister "
+ + connector.getClass().getSimpleName() + " ("
+ + connectorId + ") which is not registered");
+ return;
+ }
+ if (connectorIdToConnector.get(connectorId) != connector) {
+ throw new RuntimeException("The given connector with id "
+ + connectorId
+ + " is not the one that was registered for that id");
+ }
+
+ getLogger().fine(
+ "Unregistered " + connector.getClass().getSimpleName() + " ("
+ + connectorId + ")");
+ connectorIdToConnector.remove(connectorId);
+ }
+
+ /**
+ * Gets a connector by its id.
+ *
+ * @param connectorId
+ * The connector id to look for
+ * @return The connector with the given id or null if no connector has the
+ * given id
+ */
+ public ClientConnector getConnector(String connectorId) {
+ return connectorIdToConnector.get(connectorId);
+ }
+
+ /**
+ * Cleans the connector map from all connectors that are no longer attached
+ * to the application. This should only be called by the framework.
+ */
+ public void cleanConnectorMap() {
+ // remove detached components from paintableIdMap so they
+ // can be GC'ed
+ Iterator<String> iterator = connectorIdToConnector.keySet().iterator();
+
+ while (iterator.hasNext()) {
+ String connectorId = iterator.next();
+ ClientConnector connector = connectorIdToConnector.get(connectorId);
+ if (connector instanceof Component) {
+ Component component = (Component) connector;
+ if (component.getRoot() != root) {
+ // If component is no longer part of this application,
+ // remove it from the map. If it is re-attached to the
+ // application at some point it will be re-added through
+ // registerConnector(connector)
+ iterator.remove();
+ }
+ }
+ }
+
+ }
+
+ public void markDirty(ClientConnector connector) {
+ if (getLogger().isLoggable(Level.FINE)) {
+ if (!dirtyConnectors.contains(connector)) {
+ getLogger()
+ .fine(getDebugInfo(connector) + " " + "is now dirty");
+ }
+ }
+
+ dirtyConnectors.add(connector);
+ }
+
+ public void markClean(ClientConnector connector) {
+ if (getLogger().isLoggable(Level.FINE)) {
+ if (dirtyConnectors.contains(connector)) {
+ getLogger().fine(
+ getDebugInfo(connector) + " " + "is no longer dirty");
+ }
+ }
+
+ dirtyConnectors.remove(connector);
+ }
+
+ private String getDebugInfo(ClientConnector connector) {
+ String message = getObjectString(connector);
+ if (connector.getParent() != null) {
+ message += " (parent: " + getObjectString(connector.getParent())
+ + ")";
+ }
+ return message;
+ }
+
+ private String getObjectString(Object connector) {
+ return connector.getClass().getName() + "@"
+ + Integer.toHexString(connector.hashCode());
+ }
+
+ public void markAllConnectorsDirty() {
+ markConnectorsDirtyRecursively(root);
+ getLogger().fine("All connectors are now dirty");
+ }
+
+ public void markAllConnectorsClean() {
+ dirtyConnectors.clear();
+ getLogger().fine("All connectors are now clean");
+ }
+
+ /**
+ * 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 markConnectorsDirtyRecursively(ClientConnector c) {
+ if (c instanceof Component && !((Component) c).isVisible()) {
+ return;
+ }
+ markDirty(c);
+ for (ClientConnector child : AbstractClientConnector
+ .getAllChildrenIterable(c)) {
+ markConnectorsDirtyRecursively(child);
+ }
+ }
+
+ public Collection<ClientConnector> getDirtyConnectors() {
+ return dirtyConnectors;
+ }
+
+}
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<Component> 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..0998c11612 100644
--- a/src/com/vaadin/ui/CustomField.java
+++ b/src/com/vaadin/ui/CustomField.java
@@ -62,24 +62,18 @@ public abstract class CustomField<T> extends AbstractField<T> implements
*/
@Override
public void attach() {
- root = getContent();
+ // First call super attach to notify all children (none if content has
+ // not yet been created)
super.attach();
- getContent().setParent(this);
- getContent().attach();
- fireComponentAttachEvent(getContent());
- }
-
- /**
- * Notifies the content that the {@link CustomField} is detached from a
- * window.
- *
- * @see com.vaadin.ui.Component#detach()
- */
- @Override
- public void detach() {
- super.detach();
- getContent().detach();
+ // If the content has not yet been created, we create and attach it at
+ // this point.
+ if (root == null) {
+ // Ensure content is created and its parent is set.
+ // The getContent() call creates the content and attaches the
+ // content
+ fireComponentAttachEvent(getContent());
+ }
}
/**
@@ -90,6 +84,7 @@ public abstract class CustomField<T> extends AbstractField<T> implements
protected Component getContent() {
if (null == root) {
root = initContent();
+ root.setParent(this);
}
return root;
}
@@ -154,10 +149,6 @@ public abstract class CustomField<T> extends AbstractField<T> 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
deleted file mode 100644
index 84df7e7c7c..0000000000
--- a/src/com/vaadin/ui/DirtyConnectorTracker.java
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-package com.vaadin.ui;
-
-import java.util.Collection;
-import java.util.HashSet;
-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.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}
- * is dirty when an operation has been performed on it on the server and as a
- * result of this operation new information needs to be sent to its client side
- * counterpart.
- *
- * @author Vaadin Ltd
- * @version @VERSION@
- * @since 7.0.0
- *
- */
-public class DirtyConnectorTracker implements RepaintRequestListener {
- private Set<Component> dirtyComponents = new HashSet<Component>();
- private Root root;
-
- /**
- * Gets a logger for this class
- *
- * @return A logger instance for logging within this class
- *
- */
- public static Logger getLogger() {
- return Logger.getLogger(DirtyConnectorTracker.class.getName());
- }
-
- public DirtyConnectorTracker(Root root) {
- 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) {
- if (getLogger().isLoggable(Level.FINE)) {
- if (!dirtyComponents.contains(component)) {
- getLogger()
- .fine(getDebugInfo(component) + " " + "is now dirty");
- }
- }
-
- dirtyComponents.add(component);
- }
-
- private void markClean(Component component) {
- if (getLogger().isLoggable(Level.FINE)) {
- if (dirtyComponents.contains(component)) {
- getLogger().fine(
- getDebugInfo(component) + " " + "is no longer dirty");
- }
- }
-
- dirtyComponents.remove(component);
- }
-
- private String getDebugInfo(Component component) {
- String message = getObjectString(component);
- if (component.getParent() != null) {
- message += " (parent: " + getObjectString(component.getParent())
- + ")";
- }
- return message;
- }
-
- private String getObjectString(Object component) {
- return component.getClass().getName() + "@"
- + Integer.toHexString(component.hashCode());
- }
-
- public void componentDetached(Component component) {
- component.removeListener(this);
- markClean(component);
- }
-
- public void markAllComponentsDirty() {
- markComponentsDirtyRecursively(root);
- getLogger().fine("All components are now dirty");
- }
-
- public void markAllComponentsClean() {
- dirtyComponents.clear();
- getLogger().fine("All components are now clean");
- }
-
- /**
- * Marks all visible components dirty, starting from the given component and
- * going downwards in the hierarchy.
- *
- * @param c
- * The component to start iterating downwards from
- */
- private void markComponentsDirtyRecursively(Component c) {
- if (!c.isVisible()) {
- return;
- }
- markDirty(c);
- if (c instanceof HasComponents) {
- HasComponents container = (HasComponents) c;
- for (Component child : AbstractCommunicationManager
- .getChildComponents(container)) {
- markComponentsDirtyRecursively(child);
- }
- }
-
- }
-
- public Collection<Component> getDirtyComponents() {
- return dirtyComponents;
- }
-
-}
diff --git a/src/com/vaadin/ui/Form.java b/src/com/vaadin/ui/Form.java
index 5f5516b21f..796ad17448 100644
--- a/src/com/vaadin/ui/Form.java
+++ b/src/com/vaadin/ui/Form.java
@@ -968,34 +968,6 @@ public class Form extends AbstractField<Object> implements Item.Editor,
}
/**
- * Notifies the component that it is connected to an application
- *
- * @see com.vaadin.ui.Component#attach()
- */
- @Override
- public void attach() {
- super.attach();
- getLayout().attach();
- if (getFooter() != null) {
- getFooter().attach();
- }
- }
-
- /**
- * Notifies the component that it is detached from the application.
- *
- * @see com.vaadin.ui.Component#detach()
- */
- @Override
- public void detach() {
- super.detach();
- getLayout().detach();
- if (getFooter() != null) {
- getFooter().detach();
- }
- }
-
- /**
* Checks the validity of the Form and all of its fields.
*
* @see com.vaadin.data.Validatable#validate()
@@ -1411,10 +1383,6 @@ public class Form extends AbstractField<Object> 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<Component> {
* container.
*
* @return the component iterator.
+ *
+ * @deprecated Use {@link #iterator()} instead.
*/
+ @Deprecated
public Iterator<Component> getComponentIterator();
/**
@@ -43,12 +46,4 @@ public interface HasComponents extends Component, Iterable<Component> {
*/
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..e705954f2e
--- /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) {
+ Notification.show(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/JavaScript.java b/src/com/vaadin/ui/JavaScript.java
new file mode 100644
index 0000000000..d256717711
--- /dev/null
+++ b/src/com/vaadin/ui/JavaScript.java
@@ -0,0 +1,146 @@
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+
+package com.vaadin.ui;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import com.vaadin.external.json.JSONArray;
+import com.vaadin.external.json.JSONException;
+import com.vaadin.terminal.AbstractExtension;
+import com.vaadin.terminal.Page;
+import com.vaadin.terminal.gwt.client.communication.ServerRpc;
+import com.vaadin.terminal.gwt.client.extensions.javascriptmanager.ExecuteJavaScriptRpc;
+import com.vaadin.terminal.gwt.client.extensions.javascriptmanager.JavaScriptManagerState;
+
+/**
+ * Provides access to JavaScript functionality in the web browser. To get an
+ * instance of JavaScript, either use Page.getJavaScript() or
+ * JavaScript.getCurrent() as a shorthand for getting the JavaScript object
+ * corresponding to the current Page.
+ *
+ * @author Vaadin Ltd
+ * @version @VERSION@
+ * @since 7.0.0
+ */
+public class JavaScript extends AbstractExtension {
+ private Map<String, JavaScriptCallback> callbacks = new HashMap<String, JavaScriptCallback>();
+
+ // Can not be defined in client package as this JSONArray is not available
+ // in GWT
+ public interface JavaScriptCallbackRpc extends ServerRpc {
+ public void call(String name, JSONArray arguments);
+ }
+
+ /**
+ * Creates a new JavaScript object. You should typically not this, but
+ * instead use the JavaScript object already associated with your Page
+ * object.
+ */
+ public JavaScript() {
+ registerRpc(new JavaScriptCallbackRpc() {
+ public void call(String name, JSONArray arguments) {
+ JavaScriptCallback callback = callbacks.get(name);
+ // TODO handle situation if name is not registered
+ try {
+ callback.call(arguments);
+ } catch (JSONException e) {
+ throw new IllegalArgumentException(e);
+ }
+ }
+ });
+ }
+
+ @Override
+ public JavaScriptManagerState getState() {
+ return (JavaScriptManagerState) super.getState();
+ }
+
+ /**
+ * Add a new function to the global JavaScript namespace (i.e. the window
+ * object). The <code>call</code> method in the passed
+ * {@link JavaScriptCallback} object will be invoked with the same
+ * parameters whenever the JavaScript function is called in the browser.
+ *
+ * A callback added with the name <code>"myCallback"</code> can thus be
+ * invoked with the following JavaScript code:
+ * <code>window.myCallback(argument1, argument2)</code>.
+ *
+ * If the name parameter contains dots, simple objects are created on demand
+ * to allow calling the function using the same name (e.g.
+ * <code>window.myObject.myFunction</code>).
+ *
+ * @param name
+ * the name that the callback function should get in the global
+ * JavaScript namespace.
+ * @param callback
+ * the JavaScriptCallback that will be invoked if the JavaScript
+ * function is called.
+ */
+ public void addCallback(String name, JavaScriptCallback callback) {
+ callbacks.put(name, callback);
+ if (getState().getNames().add(name)) {
+ requestRepaint();
+ }
+ }
+
+ /**
+ * Removes a JavaScripCallback from the browser's global JavaScript
+ * namespace.
+ *
+ * If the name contains dots and intermediate were created by
+ * {@link #addCallback(String, JavaScriptCallback)}addCallback, these
+ * objects will not be removed when the callback is removed.
+ *
+ * @param name
+ * the name of the callback to remove
+ */
+ public void removeCallback(String name) {
+ callbacks.remove(name);
+ if (getState().getNames().remove(name)) {
+ requestRepaint();
+ }
+ }
+
+ /**
+ * Executes the given JavaScript code in the browser.
+ *
+ * @param script
+ * The JavaScript code to run.
+ */
+ public void execute(String script) {
+ getRpcProxy(ExecuteJavaScriptRpc.class).executeJavaScript(script);
+ }
+
+ /**
+ * Get the JavaScript object for the current Page, or null if there is no
+ * current page.
+ *
+ * @see Page#getCurrent()
+ *
+ * @return the JavaScript object corresponding to the current Page, or
+ * <code>null</code> if there is no current page.
+ */
+ public static JavaScript getCurrent() {
+ Page page = Page.getCurrent();
+ if (page == null) {
+ return null;
+ }
+ return page.getJavaScript();
+ }
+
+ /**
+ * JavaScript is not designed to be removed.
+ *
+ * @throws UnsupportedOperationException
+ * when invoked
+ */
+ @Override
+ public void removeFromTarget() {
+ throw new UnsupportedOperationException(
+ "JavaScript is not designed to be removed.");
+ }
+
+}
diff --git a/src/com/vaadin/ui/JavaScriptCallback.java b/src/com/vaadin/ui/JavaScriptCallback.java
new file mode 100644
index 0000000000..49f7695e89
--- /dev/null
+++ b/src/com/vaadin/ui/JavaScriptCallback.java
@@ -0,0 +1,41 @@
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+
+package com.vaadin.ui;
+
+import java.io.Serializable;
+
+import com.vaadin.external.json.JSONArray;
+import com.vaadin.external.json.JSONException;
+import com.vaadin.terminal.AbstractJavaScriptExtension;
+
+/**
+ * Defines a method that is called by a client-side JavaScript function. When
+ * the corresponding JavaScript function is called, the {@link #call(JSONArray)}
+ * method is invoked.
+ *
+ * @see JavaScript#addCallback(String, JavaScriptCallback)
+ * @see AbstractJavaScriptComponent#registerCallback(String, JavaScriptCallback)
+ * @see AbstractJavaScriptExtension#registerCallback(String, JavaScriptCallback)
+ *
+ * @author Vaadin Ltd
+ * @version @VERSION@
+ * @since 7.0.0
+ */
+public interface JavaScriptCallback extends Serializable {
+ /**
+ * Invoked whenever the corresponding JavaScript function is called in the
+ * browser.
+ * <p>
+ * Because of the asynchronous nature of the communication between client
+ * and server, no return value can be sent back to the browser.
+ *
+ * @param arguments
+ * an array with JSON representations of the arguments with which
+ * the JavaScript function was called.
+ * @throws JSONException
+ * if the arguments can not be interpreted
+ */
+ public void call(JSONArray arguments) throws JSONException;
+}
diff --git a/src/com/vaadin/ui/Label.java b/src/com/vaadin/ui/Label.java
index 99a0f89e5c..e1c64605d7 100644
--- a/src/com/vaadin/ui/Label.java
+++ b/src/com/vaadin/ui/Label.java
@@ -7,7 +7,8 @@ package com.vaadin.ui;
import java.lang.reflect.Method;
import com.vaadin.data.Property;
-import com.vaadin.data.util.ObjectProperty;
+import com.vaadin.data.util.converter.Converter;
+import com.vaadin.data.util.converter.ConverterUtil;
import com.vaadin.terminal.gwt.client.ui.label.ContentMode;
import com.vaadin.terminal.gwt.client.ui.label.LabelState;
@@ -36,10 +37,9 @@ import com.vaadin.terminal.gwt.client.ui.label.LabelState;
* @since 3.0
*/
@SuppressWarnings("serial")
-// TODO generics for interface Property
-public class Label extends AbstractComponent implements Property,
+public class Label extends AbstractComponent implements Property<String>,
Property.Viewer, Property.ValueChangeListener,
- Property.ValueChangeNotifier, Comparable<Object> {
+ Property.ValueChangeNotifier, Comparable<Label> {
/**
* @deprecated From 7.0, use {@link ContentMode#TEXT} instead
@@ -77,9 +77,13 @@ public class Label extends AbstractComponent implements Property,
@Deprecated
public static final ContentMode CONTENT_DEFAULT = ContentMode.TEXT;
- private static final String DATASOURCE_MUST_BE_SET = "Datasource must be set";
+ /**
+ * A converter used to convert from the data model type to the field type
+ * and vice versa. Label type is always String.
+ */
+ private Converter<String, Object> converter = null;
- private Property dataSource;
+ private Property<String> dataSource = null;
/**
* Creates an empty Label.
@@ -114,7 +118,9 @@ public class Label extends AbstractComponent implements Property,
* @param contentMode
*/
public Label(String content, ContentMode contentMode) {
- this(new ObjectProperty<String>(content, String.class), contentMode);
+ setValue(content);
+ setContentMode(contentMode);
+ setWidth(100, Unit.PERCENTAGE);
}
/**
@@ -127,15 +133,7 @@ public class Label extends AbstractComponent implements Property,
public Label(Property contentSource, ContentMode contentMode) {
setPropertyDataSource(contentSource);
setContentMode(contentMode);
- setWidth(100, UNITS_PERCENTAGE);
- }
-
- @Override
- public void updateState() {
- super.updateState();
- // We don't know when the text is updated so update it here before
- // sending the state to the client
- getState().setText(getStringValue());
+ setWidth(100, Unit.PERCENTAGE);
}
@Override
@@ -149,25 +147,35 @@ public class Label extends AbstractComponent implements Property,
*
* @return the Value of the label.
*/
- public Object getValue() {
- if (dataSource == null) {
- throw new IllegalStateException(DATASOURCE_MUST_BE_SET);
+ public String getValue() {
+ if (getPropertyDataSource() == null) {
+ // Use internal value if we are running without a data source
+ return getState().getText();
}
- return dataSource.getValue();
+ return ConverterUtil.convertFromModel(getPropertyDataSource()
+ .getValue(), String.class, getConverter(), getLocale());
}
/**
* Set the value of the label. Value of the label is the XML contents of the
* label.
*
- * @param newValue
+ * @param newStringValue
* the New value of the label.
*/
- public void setValue(Object newValue) {
- if (dataSource == null) {
- throw new IllegalStateException(DATASOURCE_MUST_BE_SET);
+ public void setValue(Object newStringValue) {
+ if (newStringValue != null && newStringValue.getClass() != String.class) {
+ throw new Converter.ConversionException("Value of type "
+ + newStringValue.getClass() + " cannot be assigned to "
+ + String.class.getName());
+ }
+ if (getPropertyDataSource() == null) {
+ getState().setText((String) newStringValue);
+ requestRepaint();
+ } else {
+ throw new IllegalStateException(
+ "Label is only a Property.Viewer and cannot update its data source");
}
- dataSource.setValue(newValue);
}
/**
@@ -179,26 +187,7 @@ public class Label extends AbstractComponent implements Property,
@Override
public String toString() {
throw new UnsupportedOperationException(
- "Use Property.getValue() instead of Label.toString()");
- }
-
- /**
- * Returns the value of the <code>Property</code> in human readable textual
- * format.
- *
- * This method exists to help migration from previous Vaadin versions by
- * providing a simple replacement for {@link #toString()}. However, it is
- * normally better to use the value of the label directly.
- *
- * @return String representation of the value stored in the Property
- * @since 7.0
- */
- public String getStringValue() {
- if (dataSource == null) {
- throw new IllegalStateException(DATASOURCE_MUST_BE_SET);
- }
- Object value = dataSource.getValue();
- return (null != value) ? value.toString() : null;
+ "Use getValue() instead of Label.toString()");
}
/**
@@ -206,11 +195,8 @@ public class Label extends AbstractComponent implements Property,
*
* @see com.vaadin.data.Property#getType()
*/
- public Class getType() {
- if (dataSource == null) {
- throw new IllegalStateException(DATASOURCE_MUST_BE_SET);
- }
- return dataSource.getType();
+ public Class<String> getType() {
+ return String.class;
}
/**
@@ -238,7 +224,13 @@ public class Label extends AbstractComponent implements Property,
((Property.ValueChangeNotifier) dataSource).removeListener(this);
}
- // Sets the new data source
+ if (!ConverterUtil.canConverterHandle(getConverter(), String.class,
+ newDataSource.getType())) {
+ // Try to find a converter
+ Converter<String, ?> c = ConverterUtil.getConverter(String.class,
+ newDataSource.getType(), getApplication());
+ setConverter(c);
+ }
dataSource = newDataSource;
// Listens the new data source if possible
@@ -354,7 +346,6 @@ public class Label extends AbstractComponent implements Property,
protected void fireValueChange() {
// Set the error message
fireEvent(new Label.ValueChangeEvent(this));
- requestRepaint();
}
/**
@@ -363,9 +354,28 @@ public class Label extends AbstractComponent implements Property,
* @see com.vaadin.data.Property.ValueChangeListener#valueChange(Property.ValueChangeEvent)
*/
public void valueChange(Property.ValueChangeEvent event) {
+ // Update the internal value from the data source
+ getState().setText(getValue());
+ requestRepaint();
+
fireValueChange();
}
+ private String getComparableValue() {
+ String stringValue = getValue();
+ if (stringValue == null) {
+ stringValue = "";
+ }
+
+ if (getContentMode() == ContentMode.XHTML
+ || getContentMode() == ContentMode.XML) {
+ return stripTags(stringValue);
+ } else {
+ return stringValue;
+ }
+
+ }
+
/**
* Compares the Label to other objects.
*
@@ -387,27 +397,10 @@ public class Label extends AbstractComponent implements Property,
* less than, equal to, or greater than the specified object.
* @see java.lang.Comparable#compareTo(java.lang.Object)
*/
- public int compareTo(Object other) {
-
- String thisValue;
- String otherValue;
+ public int compareTo(Label other) {
- if (getContentMode() == ContentMode.XML
- || getContentMode() == ContentMode.XHTML) {
- thisValue = stripTags(getStringValue());
- } else {
- thisValue = getStringValue();
- }
-
- if (other instanceof Label
- && (((Label) other).getContentMode() == ContentMode.XML || ((Label) other)
- .getContentMode() == ContentMode.XHTML)) {
- otherValue = stripTags(((Label) other).getStringValue());
- } else {
- // TODO not a good idea - and might assume that Field.toString()
- // returns a string representation of the value
- otherValue = other.toString();
- }
+ String thisValue = getComparableValue();
+ String otherValue = other.getComparableValue();
return thisValue.compareTo(otherValue);
}
@@ -443,4 +436,26 @@ public class Label extends AbstractComponent implements Property,
return res.toString();
}
+ /**
+ * Gets the converter used to convert the property data source value to the
+ * label value.
+ *
+ * @return The converter or null if none is set.
+ */
+ public Converter<String, Object> getConverter() {
+ return converter;
+ }
+
+ /**
+ * Sets the converter used to convert the label value to the property data
+ * source type. The converter must have a presentation type of String.
+ *
+ * @param converter
+ * The new converter to use.
+ */
+ public void setConverter(Converter<String, ?> converter) {
+ this.converter = (Converter<String, Object>) converter;
+ requestRepaint();
+ }
+
}
diff --git a/src/com/vaadin/ui/Link.java b/src/com/vaadin/ui/Link.java
index ed5ffbba3a..db0dc58e6b 100644
--- a/src/com/vaadin/ui/Link.java
+++ b/src/com/vaadin/ui/Link.java
@@ -6,6 +6,7 @@ package com.vaadin.ui;
import java.util.Map;
+import com.vaadin.terminal.Page;
import com.vaadin.terminal.PaintException;
import com.vaadin.terminal.PaintTarget;
import com.vaadin.terminal.Resource;
@@ -23,13 +24,13 @@ import com.vaadin.terminal.Vaadin6Component;
public class Link extends AbstractComponent implements Vaadin6Component {
/* Target window border type constant: No window border */
- public static final int TARGET_BORDER_NONE = Root.BORDER_NONE;
+ public static final int TARGET_BORDER_NONE = Page.BORDER_NONE;
/* Target window border type constant: Minimal window border */
- public static final int TARGET_BORDER_MINIMAL = Root.BORDER_MINIMAL;
+ public static final int TARGET_BORDER_MINIMAL = Page.BORDER_MINIMAL;
/* Target window border type constant: Default window border */
- public static final int TARGET_BORDER_DEFAULT = Root.BORDER_DEFAULT;
+ public static final int TARGET_BORDER_DEFAULT = Page.BORDER_DEFAULT;
private Resource resource = null;
diff --git a/src/com/vaadin/ui/Notification.java b/src/com/vaadin/ui/Notification.java
index bb1f874635..0358283cb4 100644
--- a/src/com/vaadin/ui/Notification.java
+++ b/src/com/vaadin/ui/Notification.java
@@ -6,6 +6,7 @@ package com.vaadin.ui;
import java.io.Serializable;
+import com.vaadin.terminal.Page;
import com.vaadin.terminal.Resource;
/**
@@ -318,4 +319,53 @@ public class Notification implements Serializable {
public boolean isHtmlContentAllowed() {
return htmlContentAllowed;
}
+
+ /**
+ * Shows this notification on a Page.
+ *
+ * @param page
+ * The page on which the notification should be shown
+ */
+ public void show(Page page) {
+ // TODO Can avoid deprecated API when Notification extends Extension
+ page.showNotification(this);
+ }
+
+ /**
+ * Shows a notification message on the middle of the current page. The
+ * message automatically disappears ("humanized message").
+ *
+ * Care should be taken to to avoid XSS vulnerabilities as the caption is
+ * rendered as html.
+ *
+ * @see #Notification(String)
+ * @see #show(Page)
+ *
+ * @param caption
+ * The message
+ */
+ public static void show(String caption) {
+ new Notification(caption).show(Page.getCurrent());
+ }
+
+ /**
+ * Shows a notification message the current page. The position and behavior
+ * of the message depends on the type, which is one of the basic types
+ * defined in {@link Notification}, for instance
+ * Notification.TYPE_WARNING_MESSAGE.
+ *
+ * Care should be taken to to avoid XSS vulnerabilities as the caption is
+ * rendered as html.
+ *
+ * @see #Notification(String, int)
+ * @see #show(Page)
+ *
+ * @param caption
+ * The message
+ * @param type
+ * The message type
+ */
+ public static void show(String caption, int type) {
+ new Notification(caption, type).show(Page.getCurrent());
+ }
} \ No newline at end of file
diff --git a/src/com/vaadin/ui/Panel.java b/src/com/vaadin/ui/Panel.java
index b2916f78c7..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;
@@ -164,6 +165,7 @@ public class Panel extends AbstractComponentContainer implements Scrollable,
.addListener((ComponentContainer.ComponentDetachListener) this);
content = newContent;
+ requestRepaint();
}
/**
@@ -192,15 +194,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.
*
@@ -237,7 +230,7 @@ public class Panel extends AbstractComponentContainer implements Scrollable,
* @see com.vaadin.ui.ComponentContainer#getComponentIterator()
*/
public Iterator<Component> getComponentIterator() {
- return content.getComponentIterator();
+ return Collections.singleton((Component) content).iterator();
}
/**
@@ -354,35 +347,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.
*
* @see com.vaadin.ui.ComponentContainer#removeAllComponents()
diff --git a/src/com/vaadin/ui/Root.java b/src/com/vaadin/ui/Root.java
index 93b98693c2..7ae687be79 100644
--- a/src/com/vaadin/ui/Root.java
+++ b/src/com/vaadin/ui/Root.java
@@ -4,8 +4,6 @@
package com.vaadin.ui;
-import java.io.Serializable;
-import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
@@ -13,8 +11,6 @@ import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashSet;
-import java.util.LinkedList;
-import java.util.List;
import java.util.Map;
import com.vaadin.Application;
@@ -24,6 +20,9 @@ import com.vaadin.event.Action.Handler;
import com.vaadin.event.ActionManager;
import com.vaadin.event.MouseEvents.ClickEvent;
import com.vaadin.event.MouseEvents.ClickListener;
+import com.vaadin.terminal.Page;
+import com.vaadin.terminal.Page.BrowserWindowResizeEvent;
+import com.vaadin.terminal.Page.BrowserWindowResizeListener;
import com.vaadin.terminal.PaintException;
import com.vaadin.terminal.PaintTarget;
import com.vaadin.terminal.Resource;
@@ -31,11 +30,9 @@ import com.vaadin.terminal.Vaadin6Component;
import com.vaadin.terminal.WrappedRequest;
import com.vaadin.terminal.WrappedRequest.BrowserDetails;
import com.vaadin.terminal.gwt.client.MouseEventDetails;
-import com.vaadin.terminal.gwt.client.ui.notification.VNotification;
import com.vaadin.terminal.gwt.client.ui.root.RootServerRpc;
import com.vaadin.terminal.gwt.client.ui.root.RootState;
import com.vaadin.terminal.gwt.client.ui.root.VRoot;
-import com.vaadin.tools.ReflectTools;
import com.vaadin.ui.Window.CloseListener;
/**
@@ -79,121 +76,6 @@ public abstract class Root extends AbstractComponentContainer implements
Action.Container, Action.Notifier, Vaadin6Component {
/**
- * Listener that gets notified when the size of the browser window
- * containing the root has changed.
- *
- * @see Root#addListener(BrowserWindowResizeListener)
- */
- public interface BrowserWindowResizeListener extends Serializable {
- /**
- * Invoked when the browser window containing a Root has been resized.
- *
- * @param event
- * a browser window resize event
- */
- public void browserWindowResized(BrowserWindowResizeEvent event);
- }
-
- /**
- * Event that is fired when a browser window containing a root is resized.
- */
- public class BrowserWindowResizeEvent extends Component.Event {
-
- private final int width;
- private final int height;
-
- /**
- * Creates a new event
- *
- * @param source
- * the root for which the browser window has been resized
- * @param width
- * the new width of the browser window
- * @param height
- * the new height of the browser window
- */
- public BrowserWindowResizeEvent(Root source, int width, int height) {
- super(source);
- this.width = width;
- this.height = height;
- }
-
- @Override
- public Root getSource() {
- return (Root) super.getSource();
- }
-
- /**
- * Gets the new browser window height
- *
- * @return an integer with the new pixel height of the browser window
- */
- public int getHeight() {
- return height;
- }
-
- /**
- * Gets the new browser window width
- *
- * @return an integer with the new pixel width of the browser window
- */
- public int getWidth() {
- return width;
- }
- }
-
- private static final Method BROWSWER_RESIZE_METHOD = ReflectTools
- .findMethod(BrowserWindowResizeListener.class,
- "browserWindowResized", BrowserWindowResizeEvent.class);
-
- /**
- * Listener that listens changes in URI fragment.
- */
- public interface FragmentChangedListener extends Serializable {
- public void fragmentChanged(FragmentChangedEvent event);
- }
-
- /**
- * Event fired when uri fragment changes.
- */
- public class FragmentChangedEvent extends Component.Event {
-
- /**
- * The new uri fragment
- */
- private final String fragment;
-
- /**
- * Creates a new instance of UriFragmentReader change event.
- *
- * @param source
- * the Source of the event.
- */
- public FragmentChangedEvent(Root source, String fragment) {
- super(source);
- this.fragment = fragment;
- }
-
- /**
- * Gets the root in which the fragment has changed.
- *
- * @return the root in which the fragment has changed
- */
- public Root getRoot() {
- return (Root) getComponent();
- }
-
- /**
- * Get the new fragment
- *
- * @return the new fragment
- */
- public String getFragment() {
- return fragment;
- }
- }
-
- /**
* Helper class to emulate the main window from Vaadin 6 using roots. This
* class should be used in the same way as Window used as a browser level
* window in Vaadin 6 with {@link com.vaadin.Application.LegacyApplication}
@@ -312,55 +194,191 @@ public abstract class Root extends AbstractComponentContainer implements
"Internal problem getting window URL, please report");
}
}
- }
- private static final Method FRAGMENT_CHANGED_METHOD;
-
- static {
- try {
- FRAGMENT_CHANGED_METHOD = FragmentChangedListener.class
- .getDeclaredMethod("fragmentChanged",
- new Class[] { FragmentChangedEvent.class });
- } catch (final java.lang.NoSuchMethodException e) {
- // This should never happen
- throw new java.lang.RuntimeException(
- "Internal error finding methods in FragmentChangedListener");
+ /**
+ * Opens the given resource in this root. The contents of this Root is
+ * replaced by the {@code Resource}.
+ *
+ * @param resource
+ * the resource to show in this root
+ *
+ * @deprecated As of 7.0, use getPage().open instead
+ */
+ @Deprecated
+ public void open(Resource resource) {
+ getPage().open(resource);
+ }
+
+ /* ********************************************************************* */
+
+ /**
+ * Opens the given resource in a window with the given name.
+ * <p>
+ * The supplied {@code windowName} is used as the target name in a
+ * window.open call in the client. This means that special values such
+ * as "_blank", "_self", "_top", "_parent" have special meaning. An
+ * empty or <code>null</code> window name is also a special case.
+ * </p>
+ * <p>
+ * "", null and "_self" as {@code windowName} all causes the resource to
+ * be opened in the current window, replacing any old contents. For
+ * downloadable content you should avoid "_self" as "_self" causes the
+ * client to skip rendering of any other changes as it considers them
+ * irrelevant (the page will be replaced by the resource). This can
+ * speed up the opening of a resource, but it might also put the client
+ * side into an inconsistent state if the window content is not
+ * completely replaced e.g., if the resource is downloaded instead of
+ * displayed in the browser.
+ * </p>
+ * <p>
+ * "_blank" as {@code windowName} causes the resource to always be
+ * opened in a new window or tab (depends on the browser and browser
+ * settings).
+ * </p>
+ * <p>
+ * "_top" and "_parent" as {@code windowName} works as specified by the
+ * HTML standard.
+ * </p>
+ * <p>
+ * Any other {@code windowName} will open the resource in a window with
+ * that name, either by opening a new window/tab in the browser or by
+ * replacing the contents of an existing window with that name.
+ * </p>
+ *
+ * @param resource
+ * the resource.
+ * @param windowName
+ * the name of the window.
+ * @deprecated As of 7.0, use getPage().open instead
+ */
+ @Deprecated
+ public void open(Resource resource, String windowName) {
+ getPage().open(resource, windowName);
}
- }
- /**
- * A border style used for opening resources in a window without a border.
- */
- public static final int BORDER_NONE = 0;
+ /**
+ * Opens the given resource in a window with the given size, border and
+ * name. For more information on the meaning of {@code windowName}, see
+ * {@link #open(Resource, String)}.
+ *
+ * @param resource
+ * the resource.
+ * @param windowName
+ * the name of the window.
+ * @param width
+ * the width of the window in pixels
+ * @param height
+ * the height of the window in pixels
+ * @param border
+ * the border style of the window. See {@link #BORDER_NONE
+ * Window.BORDER_* constants}
+ * @deprecated As of 7.0, use getPage().open instead
+ */
+ @Deprecated
+ public void open(Resource resource, String windowName, int width,
+ int height, int border) {
+ getPage().open(resource, windowName, width, height, border);
+ }
- /**
- * A border style used for opening resources in a window with a minimal
- * border.
- */
- public static final int BORDER_MINIMAL = 1;
+ /**
+ * Adds a new {@link BrowserWindowResizeListener} to this root. The
+ * listener will be notified whenever the browser window within which
+ * this root resides is resized.
+ *
+ * @param resizeListener
+ * the listener to add
+ *
+ * @see BrowserWindowResizeListener#browserWindowResized(BrowserWindowResizeEvent)
+ * @see #setResizeLazy(boolean)
+ *
+ * @deprecated As of 7.0, use the similarly named api in Page instead
+ */
+ @Deprecated
+ public void addListener(BrowserWindowResizeListener resizeListener) {
+ getPage().addListener(resizeListener);
+ }
- /**
- * A border style that indicates that the default border style should be
- * used when opening resources.
- */
- public static final int BORDER_DEFAULT = 2;
+ /**
+ * Removes a {@link BrowserWindowResizeListener} from this root. The
+ * listener will no longer be notified when the browser window is
+ * resized.
+ *
+ * @param resizeListener
+ * the listener to remove
+ * @deprecated As of 7.0, use the similarly named api in Page instead
+ */
+ @Deprecated
+ public void removeListener(BrowserWindowResizeListener resizeListener) {
+ getPage().removeListener(resizeListener);
+ }
- /**
- * The application to which this root belongs
- */
- private Application application;
+ /**
+ * Gets the last known height of the browser window in which this root
+ * resides.
+ *
+ * @return the browser window height in pixels
+ * @deprecated As of 7.0, use the similarly named api in Page instead
+ */
+ @Deprecated
+ public int getBrowserWindowHeight() {
+ return getPage().getBrowserWindowHeight();
+ }
- /**
- * A list of notifications that are waiting to be sent to the client.
- * Cleared (set to null) when the notifications have been sent.
- */
- private List<Notification> notifications;
+ /**
+ * Gets the last known width of the browser window in which this root
+ * resides.
+ *
+ * @return the browser window width in pixels
+ *
+ * @deprecated As of 7.0, use the similarly named api in Page instead
+ */
+ @Deprecated
+ public int getBrowserWindowWidth() {
+ return getPage().getBrowserWindowWidth();
+ }
+
+ /**
+ * Executes JavaScript in this window.
+ *
+ * <p>
+ * This method allows one to inject javascript from the server to
+ * client. A client implementation is not required to implement this
+ * functionality, but currently all web-based clients do implement this.
+ * </p>
+ *
+ * <p>
+ * Executing javascript this way often leads to cross-browser
+ * compatibility issues and regressions that are hard to resolve. Use of
+ * this method should be avoided and instead it is recommended to create
+ * new widgets with GWT. For more info on creating own, reusable
+ * client-side widgets in Java, read the corresponding chapter in Book
+ * of Vaadin.
+ * </p>
+ *
+ * @param script
+ * JavaScript snippet that will be executed.
+ *
+ * @deprecated as of 7.0, use JavaScript.getCurrent().execute(String)
+ * instead
+ */
+ @Deprecated
+ public void executeJavaScript(String script) {
+ getPage().getJavaScript().execute(script);
+ }
+
+ @Override
+ public void setCaption(String caption) {
+ // Override to provide backwards compatibility
+ getState().setCaption(caption);
+ getPage().setTitle(caption);
+ }
+
+ }
/**
- * A list of javascript commands that are waiting to be sent to the client.
- * Cleared (set to null) when the commands have been sent.
+ * The application to which this root belongs
*/
- private List<String> jsExecQueue = null;
+ private Application application;
/**
* List of windows in this root.
@@ -368,12 +386,6 @@ public abstract class Root extends AbstractComponentContainer implements
private final LinkedHashSet<Window> windows = new LinkedHashSet<Window>();
/**
- * Resources to be opened automatically on next repaint. The list is
- * automatically cleared when it has been sent to the client.
- */
- private final LinkedList<OpenResource> openList = new LinkedList<OpenResource>();
-
- /**
* The component that should be scrolled into view after the next repaint.
* Null if nothing should be scrolled into view.
*/
@@ -399,14 +411,12 @@ public abstract class Root extends AbstractComponentContainer implements
*/
private static final ThreadLocal<Root> currentRoot = new ThreadLocal<Root>();
- private int browserWindowWidth = -1;
- private int browserWindowHeight = -1;
-
/** Identifies the click event */
private static final String CLICK_EVENT_ID = VRoot.CLICK_EVENT_ID;
- private DirtyConnectorTracker dirtyConnectorTracker = new DirtyConnectorTracker(
- this);
+ private ConnectorTracker connectorTracker = new ConnectorTracker(this);
+
+ private Page page = new Page(this);
private RootServerRpc rpc = new RootServerRpc() {
public void click(MouseEventDetails mouseDetails) {
@@ -502,68 +512,7 @@ public abstract class Root extends AbstractComponentContainer implements
}
public void paintContent(PaintTarget target) throws PaintException {
- // Open requested resource
- synchronized (openList) {
- if (!openList.isEmpty()) {
- for (final Iterator<OpenResource> i = openList.iterator(); i
- .hasNext();) {
- (i.next()).paintContent(target);
- }
- openList.clear();
- }
- }
-
- // Paint notifications
- if (notifications != null) {
- target.startTag("notifications");
- for (final Iterator<Notification> it = notifications.iterator(); it
- .hasNext();) {
- final Notification n = it.next();
- target.startTag("notification");
- if (n.getCaption() != null) {
- target.addAttribute(
- VNotification.ATTRIBUTE_NOTIFICATION_CAPTION,
- n.getCaption());
- }
- if (n.getDescription() != null) {
- target.addAttribute(
- VNotification.ATTRIBUTE_NOTIFICATION_MESSAGE,
- n.getDescription());
- }
- if (n.getIcon() != null) {
- target.addAttribute(
- VNotification.ATTRIBUTE_NOTIFICATION_ICON,
- n.getIcon());
- }
- if (!n.isHtmlContentAllowed()) {
- target.addAttribute(
- VRoot.NOTIFICATION_HTML_CONTENT_NOT_ALLOWED, true);
- }
- target.addAttribute(
- VNotification.ATTRIBUTE_NOTIFICATION_POSITION,
- n.getPosition());
- target.addAttribute(VNotification.ATTRIBUTE_NOTIFICATION_DELAY,
- n.getDelayMsec());
- if (n.getStyleName() != null) {
- target.addAttribute(
- VNotification.ATTRIBUTE_NOTIFICATION_STYLE,
- n.getStyleName());
- }
- target.endTag("notification");
- }
- target.endTag("notifications");
- notifications = null;
- }
-
- // Add executable javascripts if needed
- if (jsExecQueue != null) {
- for (String script : jsExecQueue) {
- target.startTag("execJS");
- target.addAttribute("script", script);
- target.endTag("execJS");
- }
- jsExecQueue = null;
- }
+ page.paintContent(target);
if (scrollIntoView != null) {
target.addAttribute("scrollTo", scrollIntoView);
@@ -584,10 +533,6 @@ public abstract class Root extends AbstractComponentContainer implements
actionManager.paintActions(null, target);
}
- if (fragment != null) {
- target.addAttribute(VRoot.FRAGMENT_VARIABLE, fragment);
- }
-
if (isResizeLazy()) {
target.addAttribute(VRoot.RESIZE_LAZY, true);
}
@@ -618,23 +563,14 @@ public abstract class Root extends AbstractComponentContainer implements
if (variables.containsKey(VRoot.FRAGMENT_VARIABLE)) {
String fragment = (String) variables.get(VRoot.FRAGMENT_VARIABLE);
- setFragment(fragment, true);
+ getPage().setFragment(fragment, true);
}
- boolean sendResizeEvent = false;
- if (variables.containsKey("height")) {
- browserWindowHeight = ((Integer) variables.get("height"))
- .intValue();
- sendResizeEvent = true;
- }
- if (variables.containsKey("width")) {
- browserWindowWidth = ((Integer) variables.get("width")).intValue();
- sendResizeEvent = true;
- }
- if (sendResizeEvent) {
- fireEvent(new BrowserWindowResizeEvent(this, browserWindowWidth,
- browserWindowHeight));
+ if (variables.containsKey("height") || variables.containsKey("width")) {
+ getPage().setBrowserWindowSize((Integer) variables.get("width"),
+ (Integer) variables.get("height"));
}
+
}
/*
@@ -643,11 +579,17 @@ public abstract class Root extends AbstractComponentContainer implements
* @see com.vaadin.ui.ComponentContainer#getComponentIterator()
*/
public Iterator<Component> 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<Component> components = new ArrayList<Component>();
+
+ if (getContent() != null) {
+ components.add(getContent());
}
- return Collections.singleton((Component) getContent()).iterator();
+ components.addAll(windows);
+
+ return components.iterator();
}
/*
@@ -656,7 +598,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);
}
/**
@@ -809,11 +751,6 @@ public abstract class Root extends AbstractComponentContainer implements
*/
private Focusable pendingFocus;
- /**
- * The current URI fragment.
- */
- private String fragment;
-
private boolean resizeLazy = false;
/**
@@ -835,175 +772,6 @@ public abstract class Root extends AbstractComponentContainer implements
}
/**
- * Shows a notification message on the middle of the root. The message
- * automatically disappears ("humanized message").
- *
- * Care should be taken to to avoid XSS vulnerabilities as the caption is
- * rendered as html.
- *
- * @see #showNotification(Notification)
- * @see Notification
- *
- * @param caption
- * The message
- */
- public void showNotification(String caption) {
- addNotification(new Notification(caption));
- }
-
- /**
- * Shows a notification message the root. The position and behavior of the
- * message depends on the type, which is one of the basic types defined in
- * {@link Notification}, for instance Notification.TYPE_WARNING_MESSAGE.
- *
- * Care should be taken to to avoid XSS vulnerabilities as the caption is
- * rendered as html.
- *
- * @see #showNotification(Notification)
- * @see Notification
- *
- * @param caption
- * The message
- * @param type
- * The message type
- */
- public void showNotification(String caption, int type) {
- addNotification(new Notification(caption, type));
- }
-
- /**
- * Shows a notification consisting of a bigger caption and a smaller
- * description on the middle of the root. The message automatically
- * disappears ("humanized message").
- *
- * Care should be taken to to avoid XSS vulnerabilities as the caption and
- * description are rendered as html.
- *
- * @see #showNotification(Notification)
- * @see Notification
- *
- * @param caption
- * The caption of the message
- * @param description
- * The message description
- *
- */
- public void showNotification(String caption, String description) {
- addNotification(new Notification(caption, description));
- }
-
- /**
- * Shows a notification consisting of a bigger caption and a smaller
- * description. The position and behavior of the message depends on the
- * type, which is one of the basic types defined in {@link Notification},
- * for instance Notification.TYPE_WARNING_MESSAGE.
- *
- * Care should be taken to to avoid XSS vulnerabilities as the caption and
- * description are rendered as html.
- *
- * @see #showNotification(Notification)
- * @see Notification
- *
- * @param caption
- * The caption of the message
- * @param description
- * The message description
- * @param type
- * The message type
- */
- public void showNotification(String caption, String description, int type) {
- addNotification(new Notification(caption, description, type));
- }
-
- /**
- * Shows a notification consisting of a bigger caption and a smaller
- * description. The position and behavior of the message depends on the
- * type, which is one of the basic types defined in {@link Notification},
- * for instance Notification.TYPE_WARNING_MESSAGE.
- *
- * Care should be taken to avoid XSS vulnerabilities if html content is
- * allowed.
- *
- * @see #showNotification(Notification)
- * @see Notification
- *
- * @param caption
- * The message caption
- * @param description
- * The message description
- * @param type
- * The type of message
- * @param htmlContentAllowed
- * Whether html in the caption and description should be
- * displayed as html or as plain text
- */
- public void showNotification(String caption, String description, int type,
- boolean htmlContentAllowed) {
- addNotification(new Notification(caption, description, type,
- htmlContentAllowed));
- }
-
- /**
- * Shows a notification message.
- *
- * @see Notification
- * @see #showNotification(String)
- * @see #showNotification(String, int)
- * @see #showNotification(String, String)
- * @see #showNotification(String, String, int)
- *
- * @param notification
- * The notification message to show
- */
- public void showNotification(Notification notification) {
- addNotification(notification);
- }
-
- /**
- * Internal helper method to actually add a notification.
- *
- * @param notification
- * the notification to add
- */
- private void addNotification(Notification notification) {
- if (notifications == null) {
- notifications = new LinkedList<Notification>();
- }
- notifications.add(notification);
- requestRepaint();
- }
-
- /**
- * Executes JavaScript in this root.
- *
- * <p>
- * This method allows one to inject javascript from the server to client. A
- * client implementation is not required to implement this functionality,
- * but currently all web-based clients do implement this.
- * </p>
- *
- * <p>
- * Executing javascript this way often leads to cross-browser compatibility
- * issues and regressions that are hard to resolve. Use of this method
- * should be avoided and instead it is recommended to create new widgets
- * with GWT. For more info on creating own, reusable client-side widgets in
- * Java, read the corresponding chapter in Book of Vaadin.
- * </p>
- *
- * @param script
- * JavaScript snippet that will be executed.
- */
- public void executeJavaScript(String script) {
- if (jsExecQueue == null) {
- jsExecQueue = new ArrayList<String>();
- }
-
- jsExecQueue.add(script);
-
- requestRepaint();
- }
-
- /**
* Scrolls any component between the component and root to a suitable
* position so the component is visible to the user. The given component
* must belong to this root.
@@ -1072,6 +840,8 @@ public abstract class Root extends AbstractComponentContainer implements
if (content != null) {
super.addComponent(content);
}
+
+ requestRepaint();
}
/**
@@ -1115,10 +885,7 @@ public abstract class Root extends AbstractComponentContainer implements
* the initialization request
*/
public void doInit(WrappedRequest request) {
- BrowserDetails browserDetails = request.getBrowserDetails();
- if (browserDetails != null) {
- fragment = browserDetails.getUriFragment();
- }
+ getPage().init(request);
// Call the init overridden by the application developer
init(request);
@@ -1156,10 +923,10 @@ public abstract class Root extends AbstractComponentContainer implements
* @param root
* the root to register as the current root
*
- * @see #getCurrentRoot()
+ * @see #getCurrent()
* @see ThreadLocal
*/
- public static void setCurrentRoot(Root root) {
+ public static void setCurrent(Root root) {
currentRoot.set(root);
}
@@ -1171,192 +938,12 @@ public abstract class Root extends AbstractComponentContainer implements
* @return the current root instance if available, otherwise
* <code>null</code>
*
- * @see #setCurrentRoot(Root)
+ * @see #setCurrent(Root)
*/
- public static Root getCurrentRoot() {
+ public static Root getCurrent() {
return currentRoot.get();
}
- /**
- * Opens the given resource in this root. The contents of this Root is
- * replaced by the {@code Resource}.
- *
- * @param resource
- * the resource to show in this root
- */
- public void open(Resource resource) {
- synchronized (openList) {
- if (!openList.contains(resource)) {
- openList.add(new OpenResource(resource, null, -1, -1,
- BORDER_DEFAULT));
- }
- }
- requestRepaint();
- }
-
- /* ********************************************************************* */
-
- /**
- * Opens the given resource in a window with the given name.
- * <p>
- * The supplied {@code windowName} is used as the target name in a
- * window.open call in the client. This means that special values such as
- * "_blank", "_self", "_top", "_parent" have special meaning. An empty or
- * <code>null</code> window name is also a special case.
- * </p>
- * <p>
- * "", null and "_self" as {@code windowName} all causes the resource to be
- * opened in the current window, replacing any old contents. For
- * downloadable content you should avoid "_self" as "_self" causes the
- * client to skip rendering of any other changes as it considers them
- * irrelevant (the page will be replaced by the resource). This can speed up
- * the opening of a resource, but it might also put the client side into an
- * inconsistent state if the window content is not completely replaced e.g.,
- * if the resource is downloaded instead of displayed in the browser.
- * </p>
- * <p>
- * "_blank" as {@code windowName} causes the resource to always be opened in
- * a new window or tab (depends on the browser and browser settings).
- * </p>
- * <p>
- * "_top" and "_parent" as {@code windowName} works as specified by the HTML
- * standard.
- * </p>
- * <p>
- * Any other {@code windowName} will open the resource in a window with that
- * name, either by opening a new window/tab in the browser or by replacing
- * the contents of an existing window with that name.
- * </p>
- *
- * @param resource
- * the resource.
- * @param windowName
- * the name of the window.
- */
- public void open(Resource resource, String windowName) {
- synchronized (openList) {
- if (!openList.contains(resource)) {
- openList.add(new OpenResource(resource, windowName, -1, -1,
- BORDER_DEFAULT));
- }
- }
- requestRepaint();
- }
-
- /**
- * Opens the given resource in a window with the given size, border and
- * name. For more information on the meaning of {@code windowName}, see
- * {@link #open(Resource, String)}.
- *
- * @param resource
- * the resource.
- * @param windowName
- * the name of the window.
- * @param width
- * the width of the window in pixels
- * @param height
- * the height of the window in pixels
- * @param border
- * the border style of the window. See {@link #BORDER_NONE
- * Window.BORDER_* constants}
- */
- public void open(Resource resource, String windowName, int width,
- int height, int border) {
- synchronized (openList) {
- if (!openList.contains(resource)) {
- openList.add(new OpenResource(resource, windowName, width,
- height, border));
- }
- }
- requestRepaint();
- }
-
- /**
- * Private class for storing properties related to opening resources.
- */
- private class OpenResource implements Serializable {
-
- /**
- * The resource to open
- */
- private final Resource resource;
-
- /**
- * The name of the target window
- */
- private final String name;
-
- /**
- * The width of the target window
- */
- private final int width;
-
- /**
- * The height of the target window
- */
- private final int height;
-
- /**
- * The border style of the target window
- */
- private final int border;
-
- /**
- * Creates a new open resource.
- *
- * @param resource
- * The resource to open
- * @param name
- * The name of the target window
- * @param width
- * The width of the target window
- * @param height
- * The height of the target window
- * @param border
- * The border style of the target window
- */
- private OpenResource(Resource resource, String name, int width,
- int height, int border) {
- this.resource = resource;
- this.name = name;
- this.width = width;
- this.height = height;
- this.border = border;
- }
-
- /**
- * Paints the open request. Should be painted inside the window.
- *
- * @param target
- * the paint target
- * @throws PaintException
- * if the paint operation fails
- */
- private void paintContent(PaintTarget target) throws PaintException {
- target.startTag("open");
- target.addAttribute("src", resource);
- if (name != null && name.length() > 0) {
- target.addAttribute("name", name);
- }
- if (width >= 0) {
- target.addAttribute("width", width);
- }
- if (height >= 0) {
- target.addAttribute("height", height);
- }
- switch (border) {
- case BORDER_MINIMAL:
- target.addAttribute("border", "minimal");
- break;
- case BORDER_NONE:
- target.addAttribute("border", "none");
- break;
- }
-
- target.endTag("open");
- }
- }
-
public void setScrollTop(int scrollTop) {
throw new RuntimeException("Not yet implemented");
}
@@ -1444,150 +1031,176 @@ public abstract class Root extends AbstractComponentContainer implements
removeListener(CLICK_EVENT_ID, ClickEvent.class, listener);
}
- public void addListener(FragmentChangedListener listener) {
- addListener(FragmentChangedEvent.class, listener,
- FRAGMENT_CHANGED_METHOD);
+ @Override
+ public boolean isConnectorEnabled() {
+ // TODO How can a Root be invisible? What does it mean?
+ return isVisible() && isEnabled();
}
- public void removeListener(FragmentChangedListener listener) {
- removeListener(FragmentChangedEvent.class, listener,
- FRAGMENT_CHANGED_METHOD);
+ public ConnectorTracker getConnectorTracker() {
+ return connectorTracker;
}
- /**
- * Sets URI fragment. Optionally fires a {@link FragmentChangedEvent}
- *
- * @param newFragment
- * id of the new fragment
- * @param fireEvent
- * true to fire event
- * @see FragmentChangedEvent
- * @see FragmentChangedListener
- */
- public void setFragment(String newFragment, boolean fireEvents) {
- if (newFragment == null) {
- throw new NullPointerException("The fragment may not be null");
- }
- if (!newFragment.equals(fragment)) {
- fragment = newFragment;
- if (fireEvents) {
- fireEvent(new FragmentChangedEvent(this, newFragment));
- }
- requestRepaint();
- }
+ public Page getPage() {
+ return page;
}
/**
- * Sets URI fragment. This method fires a {@link FragmentChangedEvent}
+ * Setting the caption of a Root is not supported. To set the title of the
+ * HTML page, use Page.setTitle
*
- * @param newFragment
- * id of the new fragment
- * @see FragmentChangedEvent
- * @see FragmentChangedListener
+ * @deprecated as of 7.0.0, use {@link Page#setTitle(String)}
*/
- public void setFragment(String newFragment) {
- setFragment(newFragment, true);
+ @Override
+ @Deprecated
+ public void setCaption(String caption) {
+ throw new IllegalStateException(
+ "You can not set the title of a Root. To set the title of the HTML page, use Page.setTitle");
}
/**
- * Gets currently set URI fragment.
- * <p>
- * To listen changes in fragment, hook a {@link FragmentChangedListener}.
+ * Shows a notification message on the middle of the root. The message
+ * automatically disappears ("humanized message").
*
- * @return the current fragment in browser uri or null if not known
- */
- public String getFragment() {
- return fragment;
- }
-
- /**
- * Adds a new {@link BrowserWindowResizeListener} to this root. The listener
- * will be notified whenever the browser window within which this root
- * resides is resized.
+ * Care should be taken to to avoid XSS vulnerabilities as the caption is
+ * rendered as html.
+ *
+ * @see #showNotification(Notification)
+ * @see Notification
*
- * @param resizeListener
- * the listener to add
+ * @param caption
+ * The message
*
- * @see BrowserWindowResizeListener#browserWindowResized(BrowserWindowResizeEvent)
- * @see #setResizeLazy(boolean)
+ * @deprecated As of 7.0, use Notification.show instead
*/
- public void addListener(BrowserWindowResizeListener resizeListener) {
- addListener(BrowserWindowResizeEvent.class, resizeListener,
- BROWSWER_RESIZE_METHOD);
+ @Deprecated
+ public void showNotification(String caption) {
+ getPage().showNotification(new Notification(caption));
}
/**
- * Removes a {@link BrowserWindowResizeListener} from this root. The
- * listener will no longer be notified when the browser window is resized.
+ * Shows a notification message the root. The position and behavior of the
+ * message depends on the type, which is one of the basic types defined in
+ * {@link Notification}, for instance Notification.TYPE_WARNING_MESSAGE.
+ *
+ * Care should be taken to to avoid XSS vulnerabilities as the caption is
+ * rendered as html.
*
- * @param resizeListener
- * the listener to remove
+ * @see #showNotification(Notification)
+ * @see Notification
+ *
+ * @param caption
+ * The message
+ * @param type
+ * The message type
+ *
+ * @deprecated As of 7.0, use Notification.show instead
*/
- public void removeListener(BrowserWindowResizeListener resizeListener) {
- removeListener(BrowserWindowResizeEvent.class, resizeListener,
- BROWSWER_RESIZE_METHOD);
+ @Deprecated
+ public void showNotification(String caption, int type) {
+ getPage().showNotification(new Notification(caption, type));
}
/**
- * Gets the last known height of the browser window in which this root
- * resides.
+ * Shows a notification consisting of a bigger caption and a smaller
+ * description on the middle of the root. The message automatically
+ * disappears ("humanized message").
+ *
+ * Care should be taken to to avoid XSS vulnerabilities as the caption and
+ * description are rendered as html.
*
- * @return the browser window height in pixels
+ * @see #showNotification(Notification)
+ * @see Notification
+ *
+ * @param caption
+ * The caption of the message
+ * @param description
+ * The message description
+ *
+ * @deprecated As of 7.0, use Notification.show instead
*/
- public int getBrowserWindowHeight() {
- return browserWindowHeight;
+ @Deprecated
+ public void showNotification(String caption, String description) {
+ getPage().showNotification(new Notification(caption, description));
}
/**
- * Gets the last known width of the browser window in which this root
- * resides.
+ * Shows a notification consisting of a bigger caption and a smaller
+ * description. The position and behavior of the message depends on the
+ * type, which is one of the basic types defined in {@link Notification} ,
+ * for instance Notification.TYPE_WARNING_MESSAGE.
+ *
+ * Care should be taken to to avoid XSS vulnerabilities as the caption and
+ * description are rendered as html.
*
- * @return the browser window width in pixels
+ * @see #showNotification(Notification)
+ * @see Notification
+ *
+ * @param caption
+ * The caption of the message
+ * @param description
+ * The message description
+ * @param type
+ * The message type
+ *
+ * @deprecated As of 7.0, use Notification.show instead
*/
- public int getBrowserWindowWidth() {
- return browserWindowWidth;
+ @Deprecated
+ public void showNotification(String caption, String description, int type) {
+ getPage()
+ .showNotification(new Notification(caption, description, type));
}
/**
- * Notifies the child components and windows that the root is attached to
- * the application.
+ * Shows a notification consisting of a bigger caption and a smaller
+ * description. The position and behavior of the message depends on the
+ * type, which is one of the basic types defined in {@link Notification} ,
+ * for instance Notification.TYPE_WARNING_MESSAGE.
+ *
+ * Care should be taken to avoid XSS vulnerabilities if html content is
+ * allowed.
+ *
+ * @see #showNotification(Notification)
+ * @see Notification
+ *
+ * @param caption
+ * The message caption
+ * @param description
+ * The message description
+ * @param type
+ * The type of message
+ * @param htmlContentAllowed
+ * Whether html in the caption and description should be
+ * displayed as html or as plain text
+ *
+ * @deprecated As of 7.0, use Notification.show instead
*/
- @Override
- public void attach() {
- super.attach();
- for (Window w : windows) {
- w.attach();
- }
+ @Deprecated
+ public void showNotification(String caption, String description, int type,
+ boolean htmlContentAllowed) {
+ getPage()
+ .showNotification(
+ new Notification(caption, description, type,
+ htmlContentAllowed));
}
/**
- * Notifies the child components and windows that the root is detached from
- * the application.
+ * Shows a notification message.
+ *
+ * @see Notification
+ * @see #showNotification(String)
+ * @see #showNotification(String, int)
+ * @see #showNotification(String, String)
+ * @see #showNotification(String, String, int)
+ *
+ * @param notification
+ * The notification message to show
+ *
+ * @deprecated As of 7.0, use Notification.show instead
*/
- @Override
- public void detach() {
- super.detach();
- for (Window w : windows) {
- w.detach();
- }
- }
-
- @Override
- public boolean isConnectorEnabled() {
- // TODO How can a Root be invisible? What does it mean?
- return isVisible() && isEnabled();
- }
-
- public DirtyConnectorTracker getDirtyConnectorTracker() {
- return dirtyConnectorTracker;
- }
-
- public void componentAttached(Component component) {
- getDirtyConnectorTracker().componentAttached(component);
- }
-
- public void componentDetached(Component component) {
- getDirtyConnectorTracker().componentDetached(component);
+ @Deprecated
+ public void showNotification(Notification notification) {
+ getPage().showNotification(notification);
}
}
diff --git a/src/com/vaadin/ui/TabSheet.java b/src/com/vaadin/ui/TabSheet.java
index 23dee15359..061809de67 100644
--- a/src/com/vaadin/ui/TabSheet.java
+++ b/src/com/vaadin/ui/TabSheet.java
@@ -108,6 +108,7 @@ public class TabSheet extends AbstractComponentContainer implements Focusable,
setWidth(100, UNITS_PERCENTAGE);
setImmediate(true);
setCloseHandler(new CloseHandler() {
+
public void onTabClose(TabSheet tabsheet, Component c) {
tabsheet.removeComponent(c);
}
@@ -120,6 +121,7 @@ public class TabSheet extends AbstractComponentContainer implements Focusable,
*
* @return the unmodifiable Iterator of the tab content components
*/
+
public Iterator<Component> getComponentIterator() {
return Collections.unmodifiableList(components).iterator();
}
@@ -130,6 +132,7 @@ public class TabSheet extends AbstractComponentContainer implements Focusable,
*
* @return the number of contained components
*/
+
public int getComponentCount() {
return components.size();
}
@@ -143,6 +146,7 @@ public class TabSheet extends AbstractComponentContainer implements Focusable,
* @param c
* the component to be removed.
*/
+
@Override
public void removeComponent(Component c) {
if (c != null && components.contains(c)) {
@@ -193,6 +197,7 @@ public class TabSheet extends AbstractComponentContainer implements Focusable,
* @param c
* the component to be added.
*/
+
@Override
public void addComponent(Component c) {
addTab(c);
@@ -334,6 +339,7 @@ public class TabSheet extends AbstractComponentContainer implements Focusable,
* @param source
* the container components are removed from.
*/
+
@Override
public void moveComponentsFrom(ComponentContainer source) {
for (final Iterator<Component> i = source.getComponentIterator(); i
@@ -359,6 +365,7 @@ public class TabSheet extends AbstractComponentContainer implements Focusable,
* @throws PaintException
* if the paint operation failed.
*/
+
public void paintContent(PaintTarget target) throws PaintException {
if (areTabsHidden()) {
@@ -683,6 +690,7 @@ public class TabSheet extends AbstractComponentContainer implements Focusable,
}
// inherits javadoc
+
public void changeVariables(Object source, Map<String, Object> variables) {
if (variables.containsKey("selected")) {
setSelectedTab(keyMapper.get((String) variables.get("selected")));
@@ -719,6 +727,7 @@ public class TabSheet extends AbstractComponentContainer implements Focusable,
*
* {@inheritDoc}
*/
+
public void replaceComponent(Component oldComponent, Component newComponent) {
if (selected == oldComponent) {
@@ -729,25 +738,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;
@@ -769,35 +759,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();
}
@@ -1106,6 +1082,7 @@ public class TabSheet extends AbstractComponentContainer implements Focusable,
/**
* Returns the tab caption. Can never be null.
*/
+
public String getCaption() {
return caption;
}
@@ -1300,4 +1277,23 @@ public class TabSheet extends AbstractComponentContainer implements Focusable,
public boolean isComponentVisible(Component childComponent) {
return childComponent == getSelectedTab();
}
+
+ /**
+ * 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());
+ }
}
diff --git a/src/com/vaadin/ui/Table.java b/src/com/vaadin/ui/Table.java
index ba4c6529c5..a1cc4f95fe 100644
--- a/src/com/vaadin/ui/Table.java
+++ b/src/com/vaadin/ui/Table.java
@@ -21,13 +21,13 @@ import java.util.StringTokenizer;
import java.util.logging.Level;
import java.util.logging.Logger;
-import com.vaadin.Application;
import com.vaadin.data.Container;
import com.vaadin.data.Item;
import com.vaadin.data.Property;
import com.vaadin.data.util.ContainerOrderedWrapper;
import com.vaadin.data.util.IndexedContainer;
import com.vaadin.data.util.converter.Converter;
+import com.vaadin.data.util.converter.ConverterUtil;
import com.vaadin.event.Action;
import com.vaadin.event.Action.Handler;
import com.vaadin.event.DataBoundTransferable;
@@ -39,7 +39,6 @@ import com.vaadin.event.dd.DragAndDropEvent;
import com.vaadin.event.dd.DragSource;
import com.vaadin.event.dd.DropHandler;
import com.vaadin.event.dd.DropTarget;
-import com.vaadin.event.dd.acceptcriteria.ClientCriterion;
import com.vaadin.event.dd.acceptcriteria.ServerSideCriterion;
import com.vaadin.terminal.KeyMapper;
import com.vaadin.terminal.LegacyPaint;
@@ -47,7 +46,6 @@ import com.vaadin.terminal.PaintException;
import com.vaadin.terminal.PaintTarget;
import com.vaadin.terminal.Resource;
import com.vaadin.terminal.gwt.client.MouseEventDetails;
-import com.vaadin.terminal.gwt.client.ui.dd.VLazyInitItemIdentifiers;
import com.vaadin.terminal.gwt.client.ui.table.VScrollTable;
/**
@@ -78,8 +76,7 @@ public class Table extends AbstractSelect implements Action.Container,
Container.Ordered, Container.Sortable, ItemClickNotifier, DragSource,
DropTarget, HasComponents {
- private static final Logger logger = Logger
- .getLogger(Table.class.getName());
+ private transient Logger logger = null;
/**
* Modes that Table support as drag sourse.
@@ -331,7 +328,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 */
@@ -356,6 +354,11 @@ public class Table extends AbstractSelect implements Action.Container,
private LinkedList<Object> visibleColumns = new LinkedList<Object>();
/**
+ * Holds noncollapsible columns.
+ */
+ private HashSet<Object> noncollapsibleColumns = new HashSet<Object>();
+
+ /**
* Holds propertyIds of currently collapsed columns.
*/
private final HashSet<Object> collapsedColumns = new HashSet<Object>();
@@ -473,10 +476,9 @@ public class Table extends AbstractSelect implements Action.Container,
private Object sortContainerPropertyId = null;
/**
- * Is table sorting disabled alltogether; even if some of the properties
- * would be sortable.
+ * Is table sorting by the user enabled.
*/
- private boolean sortDisabled = false;
+ private boolean sortEnabled = true;
/**
* Number of rows explicitly requested by the client to be painted on next
@@ -1248,6 +1250,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);
@@ -1287,6 +1292,41 @@ public class Table extends AbstractSelect implements Action.Container,
}
/**
+ * 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
+ * true if the column should be collapsible, false otherwise.
+ */
+ public void setColumnCollapsible(Object propertyId, boolean collapsible) {
+ if (collapsible) {
+ noncollapsibleColumns.remove(propertyId);
+ } else {
+ noncollapsibleColumns.add(propertyId);
+ collapsedColumns.remove(propertyId);
+ }
+ refreshRowCache();
+ }
+
+ /**
+ * Checks if the given column is collapsible. Note that even if this method
+ * returns <code>true</code>, 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 isColumnCollapsible(Object propertyId) {
+ return !noncollapsibleColumns.contains(propertyId);
+ }
+
+ /**
* Checks if column reordering is allowed.
*
* @return true if columns can be reordered; false otherwise.
@@ -1569,6 +1609,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) {
@@ -1597,12 +1644,21 @@ public class Table extends AbstractSelect implements Action.Container,
* this method has been called. See {@link #refreshRowCache()} for forcing
* an update of the contents.
*/
+
@Override
public void requestRepaint() {
// Overridden only for javadoc
super.requestRepaint();
}
+ @Override
+ public void requestRepaintAll() {
+ super.requestRepaintAll();
+
+ // Avoid sending a partial repaint (#8714)
+ refreshRowCache();
+ }
+
private void removeRowsFromCacheAndFillBottom(int firstIndex, int rows) {
int totalCachedRows = pageBuffer[CELL_ITEMID].length;
int totalRows = size();
@@ -1706,8 +1762,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
@@ -1810,11 +1867,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;
}
@@ -1831,8 +1891,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;
@@ -2014,8 +2075,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);
}
@@ -2046,8 +2108,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;
@@ -2127,8 +2190,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,6 +2502,7 @@ public class Table extends AbstractSelect implements Action.Container,
* @see com.vaadin.ui.Select#changeVariables(java.lang.Object,
* java.util.Map)
*/
+
@Override
public void changeVariables(Object source, Map<String, Object> variables) {
@@ -2497,7 +2562,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);
}
@@ -2517,12 +2582,13 @@ 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;
}
- if (!sortDisabled) {
+ if (isSortEnabled()) {
// Sorting
boolean doSort = false;
if (variables.containsKey("sortcolumn")) {
@@ -2564,7 +2630,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;
@@ -2586,7 +2652,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;
@@ -2759,6 +2825,7 @@ public class Table extends AbstractSelect implements Action.Container,
* @see com.vaadin.ui.AbstractSelect#paintContent(com.vaadin.
* terminal.PaintTarget)
*/
+
@Override
public void paintContent(PaintTarget target) throws PaintException {
/*
@@ -2876,8 +2943,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);
@@ -2900,8 +2968,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);
}
@@ -3100,7 +3169,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<Action> actionSet)
@@ -3584,12 +3663,8 @@ public class Table extends AbstractSelect implements Action.Container,
if (hasConverter(colId)) {
converter = getConverter(colId);
} else {
- Application app = Application.getCurrentApplication();
- if (app != null) {
- converter = (Converter<String, Object>) app
- .getConverterFactory().createConverter(String.class,
- property.getType());
- }
+ ConverterUtil.getConverter(String.class, property.getType(),
+ getApplication());
}
Object value = property.getValue();
if (converter != null) {
@@ -3605,6 +3680,7 @@ public class Table extends AbstractSelect implements Action.Container,
*
* @see com.vaadin.event.Action.Container#addActionHandler(Action.Handler)
*/
+
public void addActionHandler(Action.Handler actionHandler) {
if (actionHandler != null) {
@@ -3631,6 +3707,7 @@ public class Table extends AbstractSelect implements Action.Container,
*
* @see com.vaadin.event.Action.Container#removeActionHandler(Action.Handler)
*/
+
public void removeActionHandler(Action.Handler actionHandler) {
if (actionHandlers != null && actionHandlers.contains(actionHandler)) {
@@ -3670,6 +3747,7 @@ public class Table extends AbstractSelect implements Action.Container,
*
* @see com.vaadin.data.Property.ValueChangeListener#valueChange(Property.ValueChangeEvent)
*/
+
@Override
public void valueChange(Property.ValueChangeEvent event) {
if (event.getProperty() == this
@@ -3700,18 +3778,12 @@ public class Table extends AbstractSelect implements Action.Container,
*
* @see com.vaadin.ui.Component#attach()
*/
+
@Override
public void attach() {
super.attach();
refreshRenderedCells();
-
- if (visibleComponents != null) {
- for (final Iterator<Component> i = visibleComponents.iterator(); i
- .hasNext();) {
- i.next().attach();
- }
- }
}
/**
@@ -3719,16 +3791,10 @@ public class Table extends AbstractSelect implements Action.Container,
*
* @see com.vaadin.ui.Component#detach()
*/
+
@Override
public void detach() {
super.detach();
-
- if (visibleComponents != null) {
- for (final Iterator<Component> i = visibleComponents.iterator(); i
- .hasNext();) {
- i.next().detach();
- }
- }
}
/**
@@ -3736,6 +3802,7 @@ public class Table extends AbstractSelect implements Action.Container,
*
* @see com.vaadin.data.Container#removeAllItems()
*/
+
@Override
public boolean removeAllItems() {
currentPageFirstItemId = null;
@@ -3748,6 +3815,7 @@ public class Table extends AbstractSelect implements Action.Container,
*
* @see com.vaadin.data.Container#removeItem(Object)
*/
+
@Override
public boolean removeItem(Object itemId) {
final Object nextItemId = nextItemId(itemId);
@@ -3766,6 +3834,7 @@ public class Table extends AbstractSelect implements Action.Container,
*
* @see com.vaadin.data.Container#removeContainerProperty(Object)
*/
+
@Override
public boolean removeContainerProperty(Object propertyId)
throws UnsupportedOperationException {
@@ -3792,6 +3861,7 @@ public class Table extends AbstractSelect implements Action.Container,
* @see com.vaadin.data.Container#addContainerProperty(Object, Class,
* Object)
*/
+
@Override
public boolean addContainerProperty(Object propertyId, Class<?> type,
Object defaultValue) throws UnsupportedOperationException {
@@ -3947,6 +4017,7 @@ public class Table extends AbstractSelect implements Action.Container,
*
* @see com.vaadin.ui.Select#getVisibleItemIds()
*/
+
@Override
public Collection<?> getVisibleItemIds() {
@@ -3970,6 +4041,7 @@ public class Table extends AbstractSelect implements Action.Container,
*
* @see com.vaadin.data.Container.ItemSetChangeListener#containerItemSetChange(com.vaadin.data.Container.ItemSetChangeEvent)
*/
+
@Override
public void containerItemSetChange(Container.ItemSetChangeEvent event) {
super.containerItemSetChange(event);
@@ -3986,6 +4058,7 @@ public class Table extends AbstractSelect implements Action.Container,
*
* @see com.vaadin.data.Container.PropertySetChangeListener#containerPropertySetChange(com.vaadin.data.Container.PropertySetChangeEvent)
*/
+
@Override
public void containerPropertySetChange(
Container.PropertySetChangeEvent event) {
@@ -4029,6 +4102,7 @@ public class Table extends AbstractSelect implements Action.Container,
* if set to true.
* @see com.vaadin.ui.Select#setNewItemsAllowed(boolean)
*/
+
@Override
public void setNewItemsAllowed(boolean allowNewOptions)
throws UnsupportedOperationException {
@@ -4042,6 +4116,7 @@ public class Table extends AbstractSelect implements Action.Container,
*
* @see com.vaadin.data.Container.Ordered#nextItemId(java.lang.Object)
*/
+
public Object nextItemId(Object itemId) {
return ((Container.Ordered) items).nextItemId(itemId);
}
@@ -4052,6 +4127,7 @@ public class Table extends AbstractSelect implements Action.Container,
*
* @see com.vaadin.data.Container.Ordered#prevItemId(java.lang.Object)
*/
+
public Object prevItemId(Object itemId) {
return ((Container.Ordered) items).prevItemId(itemId);
}
@@ -4061,6 +4137,7 @@ public class Table extends AbstractSelect implements Action.Container,
*
* @see com.vaadin.data.Container.Ordered#firstItemId()
*/
+
public Object firstItemId() {
return ((Container.Ordered) items).firstItemId();
}
@@ -4070,6 +4147,7 @@ public class Table extends AbstractSelect implements Action.Container,
*
* @see com.vaadin.data.Container.Ordered#lastItemId()
*/
+
public Object lastItemId() {
return ((Container.Ordered) items).lastItemId();
}
@@ -4080,6 +4158,7 @@ public class Table extends AbstractSelect implements Action.Container,
*
* @see com.vaadin.data.Container.Ordered#isFirstId(java.lang.Object)
*/
+
public boolean isFirstId(Object itemId) {
return ((Container.Ordered) items).isFirstId(itemId);
}
@@ -4090,6 +4169,7 @@ public class Table extends AbstractSelect implements Action.Container,
*
* @see com.vaadin.data.Container.Ordered#isLastId(java.lang.Object)
*/
+
public boolean isLastId(Object itemId) {
return ((Container.Ordered) items).isLastId(itemId);
}
@@ -4099,6 +4179,7 @@ public class Table extends AbstractSelect implements Action.Container,
*
* @see com.vaadin.data.Container.Ordered#addItemAfter(java.lang.Object)
*/
+
public Object addItemAfter(Object previousItemId)
throws UnsupportedOperationException {
Object itemId = ((Container.Ordered) items)
@@ -4115,6 +4196,7 @@ public class Table extends AbstractSelect implements Action.Container,
* @see com.vaadin.data.Container.Ordered#addItemAfter(java.lang.Object,
* java.lang.Object)
*/
+
public Item addItemAfter(Object previousItemId, Object newItemId)
throws UnsupportedOperationException {
Item item = ((Container.Ordered) items).addItemAfter(previousItemId,
@@ -4207,6 +4289,7 @@ public class Table extends AbstractSelect implements Action.Container,
* boolean[])
*
*/
+
public void sort(Object[] propertyId, boolean[] ascending)
throws UnsupportedOperationException {
final Container c = getContainerDataSource();
@@ -4239,15 +4322,21 @@ public class Table extends AbstractSelect implements Action.Container,
/**
* Gets the container property IDs, which can be used to sort the item.
+ * <p>
+ * Note that the {@link #isSortEnabled()} state affects what this method
+ * returns. Disabling sorting causes this method to always return an empty
+ * collection.
+ * </p>
*
* @see com.vaadin.data.Container.Sortable#getSortableContainerPropertyIds()
*/
+
public Collection<?> getSortableContainerPropertyIds() {
final Container c = getContainerDataSource();
- if (c instanceof Container.Sortable && !isSortDisabled()) {
+ if (c instanceof Container.Sortable && isSortEnabled()) {
return ((Container.Sortable) c).getSortableContainerPropertyIds();
} else {
- return new LinkedList<Object>();
+ return Collections.EMPTY_LIST;
}
}
@@ -4338,37 +4427,48 @@ public class Table extends AbstractSelect implements Action.Container,
* would support this.
*
* @return True iff sorting is disabled.
+ * @deprecated Use {@link #isSortEnabled()} instead
*/
+ @Deprecated
public boolean isSortDisabled() {
- return sortDisabled;
+ return !isSortEnabled();
}
/**
- * Disables the sorting altogether.
+ * Checks if sorting is enabled.
*
- * To disable sorting altogether, set to true. In this case no sortable
- * columns are given even in the case where datasource would support this.
+ * @return true if sorting by the user is allowed, false otherwise
+ */
+ public boolean isSortEnabled() {
+ return sortEnabled;
+ }
+
+ /**
+ * Disables the sorting by the user altogether.
*
* @param sortDisabled
* True iff sorting is disabled.
+ * @deprecated Use {@link #setSortEnabled(boolean)} instead
*/
+ @Deprecated
public void setSortDisabled(boolean sortDisabled) {
- if (this.sortDisabled != sortDisabled) {
- this.sortDisabled = sortDisabled;
- requestRepaint();
- }
+ setSortEnabled(!sortDisabled);
}
/**
- * Table does not support lazy options loading mode. Setting this true will
- * throw UnsupportedOperationException.
+ * Enables or disables sorting.
+ * <p>
+ * Setting this to false disallows sorting by the user. It is still possible
+ * to call {@link #sort()}.
+ * </p>
*
- * @see com.vaadin.ui.Select#setLazyLoading(boolean)
+ * @param sortEnabled
+ * true to allow the user to sort the table, false to disallow it
*/
- public void setLazyLoading(boolean useLazyLoading) {
- if (useLazyLoading) {
- throw new UnsupportedOperationException(
- "Lazy options loading is not supported by Table.");
+ public void setSortEnabled(boolean sortEnabled) {
+ if (this.sortEnabled != sortEnabled) {
+ this.sortEnabled = sortEnabled;
+ requestRepaint();
}
}
@@ -4455,6 +4555,7 @@ public class Table extends AbstractSelect implements Action.Container,
}
// Identical to AbstractCompoenentContainer.setEnabled();
+
@Override
public void setEnabled(boolean enabled) {
super.setEnabled(enabled);
@@ -4466,10 +4567,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.
@@ -4583,7 +4680,6 @@ public class Table extends AbstractSelect implements Action.Container,
* initialized from server and no subsequent requests requests are needed
* during that drag and drop operation.
*/
- @ClientCriterion(VLazyInitItemIdentifiers.class)
public static abstract class TableDropCriterion extends ServerSideCriterion {
private Table table;
@@ -4597,6 +4693,7 @@ public class Table extends AbstractSelect implements Action.Container,
* com.vaadin.event.dd.acceptcriteria.ServerSideCriterion#getIdentifier
* ()
*/
+
@Override
protected String getIdentifier() {
return TableDropCriterion.class.getCanonicalName();
@@ -4628,6 +4725,7 @@ public class Table extends AbstractSelect implements Action.Container,
* com.vaadin.event.dd.acceptcriteria.AcceptCriterion#paintResponse(
* com.vaadin.terminal.PaintTarget)
*/
+
@Override
public void paintResponse(PaintTarget target) throws PaintException {
/*
@@ -5299,4 +5397,11 @@ public class Table extends AbstractSelect implements Action.Container,
public boolean isComponentVisible(Component childComponent) {
return true;
}
+
+ private final Logger getLogger() {
+ if (logger == null) {
+ logger = Logger.getLogger(Table.class.getName());
+ }
+ return logger;
+ }
}
diff --git a/src/com/vaadin/ui/Tree.java b/src/com/vaadin/ui/Tree.java
index db738fee58..dacb3a2027 100644
--- a/src/com/vaadin/ui/Tree.java
+++ b/src/com/vaadin/ui/Tree.java
@@ -34,7 +34,6 @@ import com.vaadin.event.dd.DragSource;
import com.vaadin.event.dd.DropHandler;
import com.vaadin.event.dd.DropTarget;
import com.vaadin.event.dd.TargetDetails;
-import com.vaadin.event.dd.acceptcriteria.ClientCriterion;
import com.vaadin.event.dd.acceptcriteria.ClientSideCriterion;
import com.vaadin.event.dd.acceptcriteria.ServerSideCriterion;
import com.vaadin.event.dd.acceptcriteria.TargetDetailIs;
@@ -43,8 +42,6 @@ import com.vaadin.terminal.PaintException;
import com.vaadin.terminal.PaintTarget;
import com.vaadin.terminal.Resource;
import com.vaadin.terminal.gwt.client.MouseEventDetails;
-import com.vaadin.terminal.gwt.client.ui.dd.VLazyInitItemIdentifiers;
-import com.vaadin.terminal.gwt.client.ui.dd.VTargetInSubtree;
import com.vaadin.terminal.gwt.client.ui.dd.VerticalDropLocation;
import com.vaadin.terminal.gwt.client.ui.tree.TreeConnector;
import com.vaadin.terminal.gwt.client.ui.tree.VTree;
@@ -1396,7 +1393,6 @@ public class Tree extends AbstractSelect implements Container.Hierarchical,
* initialized from server and no subsequent requests requests are needed
* during that drag and drop operation.
*/
- @ClientCriterion(VLazyInitItemIdentifiers.class)
public static abstract class TreeDropCriterion extends ServerSideCriterion {
private Tree tree;
@@ -1513,7 +1509,6 @@ public class Tree extends AbstractSelect implements Container.Hierarchical,
* <p>
* The root items is also consider to be valid target.
*/
- @ClientCriterion(VTargetInSubtree.class)
public class TargetInSubtree extends ClientSideCriterion {
private Object rootId;
diff --git a/src/com/vaadin/ui/TreeTable.java b/src/com/vaadin/ui/TreeTable.java
index 9607add2c9..3294f6fab0 100644
--- a/src/com/vaadin/ui/TreeTable.java
+++ b/src/com/vaadin/ui/TreeTable.java
@@ -49,9 +49,6 @@ import com.vaadin.ui.Tree.ExpandListener;
@SuppressWarnings({ "serial" })
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();
@@ -84,6 +81,7 @@ public class TreeTable extends Table implements Hierarchical {
* Consider adding getDepth to {@link Collapsible}, might help
* scalability with some container implementations.
*/
+
public int getDepth(Object itemId) {
int depth = 0;
Hierarchical hierarchicalContainer = getContainerDataSource();
@@ -222,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();
}
@@ -789,4 +787,8 @@ public class TreeTable extends Table implements Hierarchical {
requestRepaint();
}
+ private static final Logger getLogger() {
+ return Logger.getLogger(TreeTable.class.getName());
+ }
+
}
diff --git a/src/com/vaadin/ui/UniqueSerializable.java b/src/com/vaadin/ui/UniqueSerializable.java
new file mode 100644
index 0000000000..828b285538
--- /dev/null
+++ b/src/com/vaadin/ui/UniqueSerializable.java
@@ -0,0 +1,30 @@
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+package com.vaadin.ui;
+
+import java.io.Serializable;
+
+/**
+ * A base class for generating an unique object that is serializable.
+ * <p>
+ * 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 {
+
+ @Override
+ public int hashCode() {
+ return getClass().hashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ return getClass() == obj.getClass();
+ }
+}
diff --git a/src/com/vaadin/ui/Window.java b/src/com/vaadin/ui/Window.java
index 3c17baf414..8866362587 100644
--- a/src/com/vaadin/ui/Window.java
+++ b/src/com/vaadin/ui/Window.java
@@ -8,7 +8,6 @@ import java.io.Serializable;
import java.lang.reflect.Method;
import java.util.Map;
-import com.vaadin.Application;
import com.vaadin.event.FieldEvents.BlurEvent;
import com.vaadin.event.FieldEvents.BlurListener;
import com.vaadin.event.FieldEvents.BlurNotifier;
@@ -24,47 +23,26 @@ import com.vaadin.terminal.PaintException;
import com.vaadin.terminal.PaintTarget;
import com.vaadin.terminal.Vaadin6Component;
import com.vaadin.terminal.gwt.client.MouseEventDetails;
+import com.vaadin.terminal.gwt.client.ui.root.VRoot;
import com.vaadin.terminal.gwt.client.ui.window.WindowServerRpc;
import com.vaadin.terminal.gwt.client.ui.window.WindowState;
/**
- * A component that represents an application (browser native) window or a sub
- * window.
+ * A component that represents a floating popup window that can be added to a
+ * {@link Root}. A window is added to a {@code Root} using
+ * {@link Root#addWindow(Window)}. </p>
* <p>
- * If the window is a application window or a sub window depends on how it is
- * added to the application. Adding a {@code Window} to a {@code Window} using
- * {@link Window#addWindow(Window)} makes it a sub window and adding a
- * {@code Window} to the {@code Application} using
- * {@link Application#addWindow(Window)} makes it an application window.
+ * The contents of a window is set using {@link #setContent(ComponentContainer)}
+ * or by using the {@link #Window(String, ComponentContainer)} constructor. The
+ * contents can in turn contain other components. By default, a
+ * {@link VerticalLayout} is used as content.
* </p>
* <p>
- * An application window is the base of any view in a Vaadin application. All
- * applications contain a main application window (set using
- * {@link Application#setMainWindow(Window)} which is what is initially shown to
- * the user. The contents of a window is set using
- * {@link #setContent(ComponentContainer)}. The contents can in turn contain
- * other components. For multi-tab applications there is one window instance per
- * opened tab.
+ * A window can be positioned on the screen using absolute coordinates (pixels)
+ * or set to be centered using {@link #center()}
* </p>
* <p>
- * A sub window is floating popup style window that can be added to an
- * application window. Like the application window its content is set using
- * {@link #setContent(ComponentContainer)}. A sub window can be positioned on
- * the screen using absolute coordinates (pixels). The default content of the
- * Window is set to be suitable for application windows. For sub windows it
- * might be necessary to set the size of the content to work as expected.
- * </p>
- * <p>
- * Window caption is displayed in the browser title bar for application level
- * windows and in the window header for sub windows.
- * </p>
- * <p>
- * Certain methods in this class are only meaningful for sub windows and other
- * parts only for application windows. These are marked using <b>Sub window
- * only</b> and <b>Application window only</b> respectively in the javadoc.
- * </p>
- * <p>
- * Sub window is to be split into a separate component in Vaadin 7.
+ * The caption is displayed in the window header.
* </p>
*
* @author Vaadin Ltd.
@@ -83,6 +61,10 @@ public class Window extends Panel implements FocusNotifier, BlurNotifier,
}
};
+ private int browserWindowWidth = -1;
+
+ private int browserWindowHeight = -1;
+
/**
* Creates a new unnamed window with a default layout.
*/
@@ -119,6 +101,7 @@ public class Window extends Panel implements FocusNotifier, BlurNotifier,
*
* @see com.vaadin.ui.Panel#addComponent(com.vaadin.ui.Component)
*/
+
@Override
public void addComponent(Component c) {
if (c instanceof Window) {
@@ -136,6 +119,7 @@ public class Window extends Panel implements FocusNotifier, BlurNotifier,
*
* @see com.vaadin.ui.Panel#paintContent(com.vaadin.terminal.PaintTarget)
*/
+
@Override
public synchronized void paintContent(PaintTarget target)
throws PaintException {
@@ -153,6 +137,7 @@ public class Window extends Panel implements FocusNotifier, BlurNotifier,
*
* @see com.vaadin.ui.Panel#changeVariables(java.lang.Object, java.util.Map)
*/
+
@Override
public void changeVariables(Object source, Map<String, Object> variables) {
@@ -161,15 +146,29 @@ public class Window extends Panel implements FocusNotifier, BlurNotifier,
// size is handled in super class, but resize events only in windows ->
// so detect if size change occurs before super.changeVariables()
if (variables.containsKey("height")
- && (getHeightUnits() != UNITS_PIXELS || (Integer) variables
+ && (getHeightUnits() != Unit.PIXELS || (Integer) variables
.get("height") != getHeight())) {
sizeHasChanged = true;
}
if (variables.containsKey("width")
- && (getWidthUnits() != UNITS_PIXELS || (Integer) variables
+ && (getWidthUnits() != Unit.PIXELS || (Integer) variables
.get("width") != getWidth())) {
sizeHasChanged = true;
}
+ Integer browserHeightVar = (Integer) variables
+ .get(VRoot.BROWSER_HEIGHT_VAR);
+ if (browserHeightVar != null
+ && browserHeightVar.intValue() != browserWindowHeight) {
+ browserWindowHeight = browserHeightVar.intValue();
+ sizeHasChanged = true;
+ }
+ Integer browserWidthVar = (Integer) variables
+ .get(VRoot.BROWSER_WIDTH_VAR);
+ if (browserWidthVar != null
+ && browserWidthVar.intValue() != browserWindowWidth) {
+ browserWindowWidth = browserWidthVar.intValue();
+ sizeHasChanged = true;
+ }
super.changeVariables(source, variables);
@@ -604,8 +603,13 @@ public class Window extends Panel implements FocusNotifier, BlurNotifier,
}
/**
- * Request to center this window on the screen. <b>Note:</b> affects
- * sub-windows only.
+ * Sets this window to be centered relative to its parent window. Affects
+ * sub-windows only. If the window is resized as a result of the size of its
+ * content changing, it will keep itself centered as long as its position is
+ * not explicitly changed programmatically or by the user.
+ * <p>
+ * <b>NOTE:</b> This method has several issues as currently implemented.
+ * Please refer to http://dev.vaadin.com/ticket/8971 for details.
*/
public void center() {
getState().setCentered(true);
@@ -788,6 +792,7 @@ public class Window extends Panel implements FocusNotifier, BlurNotifier,
*
* @see com.vaadin.event.FieldEvents.FocusNotifier#addListener(com.vaadin.event.FieldEvents.FocusListener)
*/
+
public void addListener(FocusListener listener) {
addListener(FocusEvent.EVENT_ID, FocusEvent.class, listener,
FocusListener.focusMethod);
@@ -804,6 +809,7 @@ public class Window extends Panel implements FocusNotifier, BlurNotifier,
*
* @see com.vaadin.event.FieldEvents.BlurNotifier#addListener(com.vaadin.event.FieldEvents.BlurListener)
*/
+
public void addListener(BlurListener listener) {
addListener(BlurEvent.EVENT_ID, BlurEvent.class, listener,
BlurListener.blurMethod);
@@ -819,6 +825,7 @@ public class Window extends Panel implements FocusNotifier, BlurNotifier,
* If the window is a sub-window focusing will cause the sub-window to be
* brought on top of other sub-windows on gain keyboard focus.
*/
+
@Override
public void focus() {
/*
@@ -834,5 +841,4 @@ public class Window extends Panel implements FocusNotifier, BlurNotifier,
public WindowState getState() {
return (WindowState) super.getState();
}
-
}
diff --git a/src/com/vaadin/ui/themes/ChameleonTheme.java b/src/com/vaadin/ui/themes/ChameleonTheme.java
index bfb9686018..5ae8cd4e57 100644
--- a/src/com/vaadin/ui/themes/ChameleonTheme.java
+++ b/src/com/vaadin/ui/themes/ChameleonTheme.java
@@ -5,7 +5,7 @@ package com.vaadin.ui.themes;
public class ChameleonTheme extends BaseTheme {
- public static final String THEME_NAME = "Chameleon";
+ public static final String THEME_NAME = "chameleon";
/***************************************************************************
* Label styles
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);
diff --git a/tests/server-side/com/vaadin/tests/VaadinClasses.java b/tests/server-side/com/vaadin/tests/VaadinClasses.java
index b74af660e4..0ee193e8f1 100644
--- a/tests/server-side/com/vaadin/tests/VaadinClasses.java
+++ b/tests/server-side/com/vaadin/tests/VaadinClasses.java
@@ -15,8 +15,6 @@ import java.util.Enumeration;
import java.util.List;
import java.util.jar.JarEntry;
-import org.junit.Test;
-
import com.vaadin.Application;
import com.vaadin.ui.Component;
import com.vaadin.ui.ComponentContainer;
@@ -29,6 +27,9 @@ import com.vaadin.ui.PopupView;
import com.vaadin.ui.Root;
import com.vaadin.ui.VerticalSplitPanel;
import com.vaadin.ui.Window;
+import com.vaadin.ui.themes.BaseTheme;
+
+import org.junit.Test;
@SuppressWarnings("deprecation")
public class VaadinClasses {
@@ -71,6 +72,15 @@ public class VaadinClasses {
}
}
+ public static List<Class<? extends BaseTheme>> getThemeClasses() {
+ try {
+ return findClasses(BaseTheme.class, "com.vaadin.ui.themes");
+ } catch (IOException e) {
+ e.printStackTrace();
+ return null;
+ }
+ }
+
public static List<Class<? extends Object>> getAllServerSideClasses() {
try {
return findClassesNoTests(Object.class, "com.vaadin", new String[] {
diff --git a/tests/server-side/com/vaadin/tests/data/bean/Person.java b/tests/server-side/com/vaadin/tests/data/bean/Person.java
index 2cb3a29368..f7bad31d0e 100644
--- a/tests/server-side/com/vaadin/tests/data/bean/Person.java
+++ b/tests/server-side/com/vaadin/tests/data/bean/Person.java
@@ -130,4 +130,14 @@ public class Person {
this.birthDate = birthDate;
}
+ public static Person createTestPerson1() {
+ return new Person("Foo", "Bar", "yeah@cool.com", 46, Sex.MALE,
+ new Address("Street", 1123, "Turku", Country.FINLAND));
+ }
+
+ public static Person createTestPerson2() {
+ return new Person("Maya", "Dinkelstein", "maya@foo.bar", 18,
+ Sex.FEMALE, new Address("Red street", 12, "Amsterdam",
+ Country.NETHERLANDS));
+ }
}
diff --git a/tests/server-side/com/vaadin/tests/data/converter/ConverterFactory.java b/tests/server-side/com/vaadin/tests/data/converter/ConverterFactory.java
new file mode 100644
index 0000000000..4bd9cf0cf7
--- /dev/null
+++ b/tests/server-side/com/vaadin/tests/data/converter/ConverterFactory.java
@@ -0,0 +1,100 @@
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+package com.vaadin.tests.data.converter;
+
+import java.util.Locale;
+
+import junit.framework.TestCase;
+
+import com.vaadin.Application;
+import com.vaadin.data.util.converter.Converter;
+import com.vaadin.data.util.converter.DefaultConverterFactory;
+import com.vaadin.ui.TextField;
+
+public class ConverterFactory extends TestCase {
+
+ public static class ConvertTo42 implements Converter<String, Integer> {
+
+ public Integer convertToModel(String value, Locale locale)
+ throws com.vaadin.data.util.converter.Converter.ConversionException {
+ return 42;
+ }
+
+ public String convertToPresentation(Integer value, Locale locale)
+ throws com.vaadin.data.util.converter.Converter.ConversionException {
+ return "42";
+ }
+
+ public Class<Integer> getModelType() {
+ return Integer.class;
+ }
+
+ public Class<String> getPresentationType() {
+ return String.class;
+ }
+
+ }
+
+ public static class ConverterFactory42 extends DefaultConverterFactory {
+ @Override
+ public <PRESENTATION, MODEL> Converter<PRESENTATION, MODEL> createConverter(
+ Class<PRESENTATION> presentationType, Class<MODEL> modelType) {
+ if (modelType == Integer.class) {
+ return (Converter<PRESENTATION, MODEL>) new ConvertTo42();
+ }
+
+ return super.createConverter(presentationType, modelType);
+ }
+ }
+
+ public void testApplicationConverterFactoryInBackgroundThread() {
+ Application.setCurrent(null);
+ final Application appWithCustomIntegerConverter = new Application();
+ appWithCustomIntegerConverter
+ .setConverterFactory(new ConverterFactory42());
+
+ TextField tf = new TextField("", "123") {
+ @Override
+ public Application getApplication() {
+ return appWithCustomIntegerConverter;
+ };
+ };
+ tf.setConverter(Integer.class);
+ // The application converter always returns 42. Current application is
+ // null
+ assertEquals(42, tf.getConvertedValue());
+ }
+
+ public void testApplicationConverterFactoryForDetachedComponent() {
+ final Application appWithCustomIntegerConverter = new Application();
+ appWithCustomIntegerConverter
+ .setConverterFactory(new ConverterFactory42());
+ Application.setCurrent(appWithCustomIntegerConverter);
+
+ TextField tf = new TextField("", "123");
+ tf.setConverter(Integer.class);
+ // The application converter always returns 42. Current application is
+ // null
+ assertEquals(42, tf.getConvertedValue());
+ }
+
+ public void testApplicationConverterFactoryForDifferentThanCurrentApplication() {
+ final Application fieldAppWithCustomIntegerConverter = new Application();
+ fieldAppWithCustomIntegerConverter
+ .setConverterFactory(new ConverterFactory42());
+ Application.setCurrent(new Application());
+
+ TextField tf = new TextField("", "123") {
+ @Override
+ public Application getApplication() {
+ return fieldAppWithCustomIntegerConverter;
+ }
+ };
+ tf.setConverter(Integer.class);
+
+ // The application converter always returns 42. Application.getCurrent()
+ // should not be used
+ assertEquals(42, tf.getConvertedValue());
+ }
+}
diff --git a/tests/server-side/com/vaadin/tests/server/TestThemeNames.java b/tests/server-side/com/vaadin/tests/server/TestThemeNames.java
new file mode 100644
index 0000000000..22fe315730
--- /dev/null
+++ b/tests/server-side/com/vaadin/tests/server/TestThemeNames.java
@@ -0,0 +1,38 @@
+package com.vaadin.tests.server;
+
+import java.io.File;
+import java.lang.reflect.Field;
+import java.util.List;
+
+import junit.framework.TestCase;
+
+import com.vaadin.tests.VaadinClasses;
+import com.vaadin.ui.themes.BaseTheme;
+
+public class TestThemeNames extends TestCase {
+ public void testThemeNames() {
+ File baseDir = new File(SourceFileChecker.getBaseDir()
+ + "WebContent/VAADIN/themes/");
+
+ List<Class<? extends BaseTheme>> themeClasses = VaadinClasses
+ .getThemeClasses();
+ for (Class<? extends BaseTheme> themeClass : themeClasses) {
+ try {
+ Field field = themeClass.getField("THEME_NAME");
+ String themeName = (String) field.get(null);
+
+ File themeDir = new File(baseDir, themeName);
+ File styleFile = new File(themeDir, "styles.css");
+
+ assertTrue("Can't find " + styleFile + " for theme "
+ + themeClass.getName(), styleFile.exists());
+
+ // Test that casing matches
+ assertEquals(themeDir.getCanonicalFile().getName(), themeName);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+}
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/abstractfield/AbstractFieldValueConversions.java b/tests/server-side/com/vaadin/tests/server/component/abstractfield/AbstractFieldValueConversions.java
index 050ab282a6..446228583a 100644
--- a/tests/server-side/com/vaadin/tests/server/component/abstractfield/AbstractFieldValueConversions.java
+++ b/tests/server-side/com/vaadin/tests/server/component/abstractfield/AbstractFieldValueConversions.java
@@ -4,6 +4,7 @@ import java.util.Locale;
import junit.framework.TestCase;
+import com.vaadin.Application;
import com.vaadin.data.util.MethodProperty;
import com.vaadin.data.util.converter.Converter;
import com.vaadin.data.util.converter.StringToIntegerConverter;
@@ -159,4 +160,45 @@ public class AbstractFieldValueConversions extends TestCase {
}
+ public static class NumberBean {
+ private Number number;
+
+ public Number getNumber() {
+ return number;
+ }
+
+ public void setNumber(Number number) {
+ this.number = number;
+ }
+
+ }
+
+ public void testNumberDoubleConverterChange() {
+ final Application a = new Application();
+ Application.setCurrent(a);
+ TextField tf = new TextField() {
+ @Override
+ public Application getApplication() {
+ return a;
+ }
+ };
+ NumberBean nb = new NumberBean();
+ nb.setNumber(490);
+
+ tf.setPropertyDataSource(new MethodProperty<Number>(nb, "number"));
+ assertEquals(490, tf.getPropertyDataSource().getValue());
+ assertEquals("490", tf.getValue());
+
+ Converter c1 = tf.getConverter();
+
+ tf.setPropertyDataSource(new MethodProperty<Number>(nb, "number"));
+ Converter c2 = tf.getConverter();
+ assertTrue(
+ "StringToNumber converter is ok for integer types and should stay even though property is changed",
+ c1 == c2);
+ assertEquals(490, tf.getPropertyDataSource().getValue());
+ assertEquals("490", tf.getValue());
+
+ }
+
}
diff --git a/tests/server-side/com/vaadin/tests/server/component/abstractfield/DefaultConverterFactory.java b/tests/server-side/com/vaadin/tests/server/component/abstractfield/DefaultConverterFactory.java
index e39b5d6629..25430fc9a5 100644
--- a/tests/server-side/com/vaadin/tests/server/component/abstractfield/DefaultConverterFactory.java
+++ b/tests/server-side/com/vaadin/tests/server/component/abstractfield/DefaultConverterFactory.java
@@ -27,7 +27,7 @@ public class DefaultConverterFactory extends TestCase {
public void testDefaultNumberConversion() {
Application app = new Application();
- Application.setCurrentApplication(app);
+ Application.setCurrent(app);
TextField tf = new TextField();
tf.setLocale(new Locale("en", "US"));
tf.setPropertyDataSource(new MethodProperty<Integer>(paulaBean,
diff --git a/tests/server-side/com/vaadin/tests/server/component/abstractfield/RemoveListenersOnDetach.java b/tests/server-side/com/vaadin/tests/server/component/abstractfield/RemoveListenersOnDetach.java
index 851fece4d1..94385700d8 100644
--- a/tests/server-side/com/vaadin/tests/server/component/abstractfield/RemoveListenersOnDetach.java
+++ b/tests/server-side/com/vaadin/tests/server/component/abstractfield/RemoveListenersOnDetach.java
@@ -4,6 +4,7 @@ import static org.junit.Assert.assertEquals;
import org.junit.Test;
+import com.vaadin.Application;
import com.vaadin.data.Property;
import com.vaadin.data.util.AbstractProperty;
import com.vaadin.data.util.converter.Converter.ConversionException;
@@ -25,10 +26,13 @@ public class RemoveListenersOnDetach {
}
};
+ private Application application = new Application() {
+
+ };
@Override
public Class<?> getType() {
- return null;
+ return String.class;
}
@Override
@@ -48,6 +52,11 @@ public class RemoveListenersOnDetach {
public com.vaadin.ui.Root getRoot() {
return root;
};
+
+ @Override
+ public Application getApplication() {
+ return application;
+ };
};
Property property = new AbstractProperty() {
@@ -61,7 +70,7 @@ public class RemoveListenersOnDetach {
}
public Class<?> getType() {
- return null;
+ return String.class;
}
};
diff --git a/tests/server-side/com/vaadin/tests/server/component/label/LabelConverters.java b/tests/server-side/com/vaadin/tests/server/component/label/LabelConverters.java
new file mode 100644
index 0000000000..5ba15cac6c
--- /dev/null
+++ b/tests/server-side/com/vaadin/tests/server/component/label/LabelConverters.java
@@ -0,0 +1,59 @@
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+package com.vaadin.tests.server.component.label;
+
+import junit.framework.TestCase;
+
+import com.vaadin.Application;
+import com.vaadin.data.Property;
+import com.vaadin.data.util.MethodProperty;
+import com.vaadin.tests.data.bean.Person;
+import com.vaadin.ui.Label;
+
+public class LabelConverters extends TestCase {
+
+ public void testLabelSetDataSourceLaterOn() {
+ Person p = Person.createTestPerson1();
+ Label l = new Label("My label");
+ assertEquals("My label", l.getValue());
+ assertNull(l.getConverter());
+ l.setPropertyDataSource(new MethodProperty<String>(p, "firstName"));
+ assertEquals(p.getFirstName(), l.getValue());
+ p.setFirstName("123");
+ assertEquals("123", l.getValue());
+ }
+
+ public void testIntegerDataSource() {
+ Application.setCurrent(new Application());
+ Label l = new Label("Foo");
+ Property ds = new MethodProperty<Integer>(Person.createTestPerson1(),
+ "age");
+ l.setPropertyDataSource(ds);
+ assertEquals(String.valueOf(Person.createTestPerson1().getAge()),
+ l.getValue());
+ }
+
+ public void testSetValueWithDataSource() {
+ try {
+ MethodProperty<String> property = new MethodProperty<String>(
+ Person.createTestPerson1(), "firstName");
+ Label l = new Label(property);
+ l.setValue("Foo");
+ fail("setValue should throw an exception when a data source is set");
+ } catch (Exception e) {
+ }
+
+ }
+
+ public void testLabelWithoutDataSource() {
+ Label l = new Label("My label");
+ assertEquals("My label", l.getValue());
+ assertNull(l.getConverter());
+ assertNull(l.getPropertyDataSource());
+ l.setValue("New value");
+ assertEquals("New value", l.getValue());
+ assertNull(l.getConverter());
+ assertNull(l.getPropertyDataSource());
+ }
+}
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/server/component/tabsheet/TestTabSheet.java b/tests/server-side/com/vaadin/tests/server/component/tabsheet/TestTabSheet.java
index 40d0ffd17d..0ef8ae5a76 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)));
+ }
}
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<String>() {
@@ -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/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..fc0d1b60a0
--- /dev/null
+++ b/tests/server-side/com/vaadin/tests/server/navigator/ClassBasedViewProviderTest.java
@@ -0,0 +1,117 @@
+/*
+@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 {
+
+ public static class TestView extends Label implements View {
+ public String parameters = null;
+
+ public void navigateTo(String parameters) {
+ this.parameters = parameters;
+ }
+
+ }
+
+ public static class TestView2 extends TestView {
+
+ }
+
+ public void testCreateProviderWithNullName() throws Exception {
+ try {
+ new ClassBasedViewProvider(null, TestView.class);
+ fail("Should not be able to create view provider with null name");
+ } catch (IllegalArgumentException e) {
+ }
+ }
+
+ public void testCreateProviderWithEmptyStringName() throws Exception {
+ new ClassBasedViewProvider("", TestView.class);
+ }
+
+ public void testCreateProviderNullViewClass() throws Exception {
+ try {
+ new ClassBasedViewProvider("test", null);
+ fail("Should not be able to create view provider with null view class");
+ } catch (IllegalArgumentException e) {
+ }
+ }
+
+ public void testViewNameGetter() throws Exception {
+ ClassBasedViewProvider provider1 = new ClassBasedViewProvider("",
+ TestView.class);
+ assertEquals("View name should be empty", "", provider1.getViewName());
+
+ ClassBasedViewProvider provider2 = new ClassBasedViewProvider("test",
+ TestView.class);
+ assertEquals("View name does not match", "test",
+ provider2.getViewName());
+ }
+
+ public void testViewClassGetter() throws Exception {
+ ClassBasedViewProvider provider = new ClassBasedViewProvider("test",
+ TestView.class);
+ assertEquals("Incorrect view class returned by getter", TestView.class,
+ provider.getViewClass());
+ }
+
+ public void testGetViewNameForNullString() throws Exception {
+ ClassBasedViewProvider provider = new ClassBasedViewProvider("test",
+ TestView.class);
+ assertNull("Received view name for null view string",
+ provider.getViewName((String) null));
+ }
+
+ public void testGetViewNameForEmptyString() throws Exception {
+ ClassBasedViewProvider provider1 = new ClassBasedViewProvider("",
+ TestView.class);
+ assertEquals(
+ "Did not find view name for empty view string in a provider with empty string registered",
+ "", provider1.getViewName(""));
+
+ ClassBasedViewProvider provider2 = new ClassBasedViewProvider("test",
+ TestView.class);
+ assertNull(
+ "Found view name for empty view string when none registered",
+ provider2.getViewName(""));
+ }
+
+ public void testGetViewNameWithParameters() throws Exception {
+ ClassBasedViewProvider provider = new ClassBasedViewProvider("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 testGetView() throws Exception {
+ ClassBasedViewProvider provider = new ClassBasedViewProvider("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());
+ }
+
+ public void testGetViewIncorrectViewName() throws Exception {
+ ClassBasedViewProvider provider = new ClassBasedViewProvider("test",
+ TestView.class);
+
+ View view = provider.getView("test2");
+ assertNull("Got view from a provider for incorrect view name", view);
+ }
+
+}
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..03f49d4ab6
--- /dev/null
+++ b/tests/server-side/com/vaadin/tests/server/navigator/NavigatorTest.java
@@ -0,0 +1,569 @@
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+
+package com.vaadin.tests.server.navigator;
+
+import java.util.LinkedList;
+
+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.Navigator.SimpleViewDisplay;
+import com.vaadin.navigator.View;
+import com.vaadin.navigator.ViewChangeListener;
+import com.vaadin.navigator.ViewChangeListener.ViewChangeEvent;
+import com.vaadin.navigator.ViewDisplay;
+import com.vaadin.navigator.ViewProvider;
+import com.vaadin.terminal.Page;
+import com.vaadin.tests.server.navigator.ClassBasedViewProviderTest.TestView;
+import com.vaadin.tests.server.navigator.ClassBasedViewProviderTest.TestView2;
+
+public class NavigatorTest extends TestCase {
+
+ // TODO test internal parameters (and absence of them)
+ // TODO test listeners blocking navigation, multiple listeners
+
+ public static class NullDisplay implements ViewDisplay {
+ public void showView(View view) {
+ // do nothing
+ }
+ }
+
+ public static class NullFragmentManager implements FragmentManager {
+ public String getFragment() {
+ return null;
+ }
+
+ public void setFragment(String fragment) {
+ // do nothing
+ }
+ }
+
+ public static class TestDisplay implements ViewDisplay {
+ private View currentView;
+
+ public void showView(View view) {
+ currentView = view;
+ }
+
+ public View getCurrentView() {
+ return currentView;
+ }
+ }
+
+ public static class TestNavigator extends Navigator {
+ public TestNavigator() {
+ super(new NullFragmentManager(), new TestDisplay());
+ }
+
+ public View getView(String viewAndParameters) {
+ navigateTo(viewAndParameters);
+ return ((TestDisplay) getDisplay()).getCurrentView();
+ }
+ }
+
+ public static class ViewChangeTestListener implements ViewChangeListener {
+ private final LinkedList<ViewChangeEvent> referenceEvents = new LinkedList<ViewChangeListener.ViewChangeEvent>();
+ private final LinkedList<Boolean> referenceIsCheck = new LinkedList<Boolean>();
+ private final LinkedList<Boolean> checkReturnValues = new LinkedList<Boolean>();
+
+ public void addExpectedIsViewChangeAllowed(ViewChangeEvent event,
+ boolean returnValue) {
+ referenceIsCheck.add(true);
+ referenceEvents.add(event);
+ checkReturnValues.add(returnValue);
+ }
+
+ public void addExpectedNavigatorViewChange(ViewChangeEvent event) {
+ referenceIsCheck.add(false);
+ referenceEvents.add(event);
+ }
+
+ public boolean isReady() {
+ return referenceEvents.isEmpty();
+ }
+
+ public boolean equalsReferenceEvent(ViewChangeEvent event,
+ ViewChangeEvent reference) {
+ if (event == null) {
+ return false;
+ }
+ if (reference.getNavigator() != event.getNavigator()) {
+ return false;
+ }
+ if (reference.getOldView() != event.getOldView()) {
+ return false;
+ }
+ if (reference.getNewView() != event.getNewView()) {
+ return false;
+ }
+ if (!stringEquals(reference.getViewName(), event.getViewName())) {
+ return false;
+ }
+ if (!stringEquals(reference.getFragmentParameters(),
+ event.getFragmentParameters())) {
+ return false;
+ }
+ return true;
+ }
+
+ private static boolean stringEquals(String string1, String string2) {
+ if (string1 == null) {
+ return string2 == null;
+ } else {
+ return string1.equals(string2);
+ }
+ }
+
+ public boolean isViewChangeAllowed(ViewChangeEvent event) {
+ if (referenceEvents.isEmpty()) {
+ fail("Unexpected call to isViewChangeAllowed()");
+ }
+ ViewChangeEvent reference = referenceEvents.remove();
+ Boolean isCheck = referenceIsCheck.remove();
+ if (!isCheck) {
+ fail("Expected navigatorViewChanged(), received isViewChangeAllowed()");
+ }
+ // here to make sure exactly the correct values are removed from
+ // each queue
+ Boolean returnValue = checkReturnValues.remove();
+ if (!equalsReferenceEvent(event, reference)) {
+ fail("View change event does not match reference event");
+ }
+ return returnValue;
+ }
+
+ public void navigatorViewChanged(ViewChangeEvent event) {
+ if (referenceEvents.isEmpty()) {
+ fail("Unexpected call to navigatorViewChanged()");
+ }
+ ViewChangeEvent reference = referenceEvents.remove();
+ Boolean isCheck = referenceIsCheck.remove();
+ if (isCheck) {
+ fail("Expected isViewChangeAllowed(), received navigatorViewChanged()");
+ }
+ if (!equalsReferenceEvent(event, reference)) {
+ fail("View change event does not match reference event");
+ }
+ }
+ }
+
+ 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);
+ 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);
+ 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);
+ 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("test2")).andReturn("test2");
+ EasyMock.expect(provider.getView("test2")).andReturn(view2);
+ EasyMock.expect(manager.getFragment()).andReturn("view1");
+ view2.navigateTo(null);
+ display.showView(view2);
+ manager.setFragment("test2");
+
+ EasyMock.expect(provider.getViewName("")).andReturn("test1");
+ EasyMock.expect(provider.getView("test1")).andReturn(view1);
+ 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);
+ 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("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);
+ ViewChangeTestListener listener = new ViewChangeTestListener();
+
+ // create navigator to test
+ Navigator navigator = new Navigator(manager, display);
+
+ // prepare mocks: what to expect
+ EasyMock.expect(provider.getViewName("test1")).andReturn("test1");
+ EasyMock.expect(provider.getView("test1")).andReturn(view1);
+ ViewChangeEvent event1 = new ViewChangeEvent(navigator, null, view1,
+ "test1", null);
+ listener.addExpectedIsViewChangeAllowed(event1, true);
+ EasyMock.expect(manager.getFragment()).andReturn("");
+ view1.navigateTo(null);
+ display.showView(view1);
+ manager.setFragment("test1");
+ listener.addExpectedNavigatorViewChange(event1);
+
+ EasyMock.expect(provider.getViewName("test2")).andReturn("test2");
+ EasyMock.expect(provider.getView("test2")).andReturn(view2);
+ ViewChangeEvent event2 = new ViewChangeEvent(navigator, view1, view2,
+ "test2", null);
+ listener.addExpectedIsViewChangeAllowed(event2, true);
+ EasyMock.expect(manager.getFragment()).andReturn("view1");
+ view2.navigateTo(null);
+ display.showView(view2);
+ manager.setFragment("test2");
+ listener.addExpectedNavigatorViewChange(event2);
+
+ control.replay();
+
+ // test navigator
+ navigator.registerProvider(provider);
+ navigator.addListener(listener);
+
+ navigator.navigateTo("test1");
+ navigator.navigateTo("test2");
+
+ if (!listener.isReady()) {
+ fail("Missing listener calls");
+ }
+ }
+
+ 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);
+ ViewChangeTestListener listener1 = new ViewChangeTestListener();
+ ViewChangeTestListener listener2 = new ViewChangeTestListener();
+
+ Navigator navigator = new Navigator(manager, display);
+
+ // 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);
+ EasyMock.expect(manager.getFragment()).andReturn("");
+ ViewChangeEvent event1 = new ViewChangeEvent(navigator, null, view1,
+ "test1", null);
+ listener1.addExpectedIsViewChangeAllowed(event1, false);
+
+ // second listener blocks second view change
+ EasyMock.expect(provider.getViewName("test1/test")).andReturn("test1");
+ EasyMock.expect(provider.getView("test1")).andReturn(view1);
+ EasyMock.expect(manager.getFragment()).andReturn("");
+ ViewChangeEvent event2 = new ViewChangeEvent(navigator, null, view1,
+ "test1", "test");
+ listener1.addExpectedIsViewChangeAllowed(event2, true);
+ listener2.addExpectedIsViewChangeAllowed(event2, false);
+
+ // both listeners allow view change
+ EasyMock.expect(provider.getViewName("test1/bar")).andReturn("test1");
+ EasyMock.expect(provider.getView("test1")).andReturn(view1);
+ EasyMock.expect(manager.getFragment()).andReturn("");
+ ViewChangeEvent event3 = new ViewChangeEvent(navigator, null, view1,
+ "test1", "bar");
+ listener1.addExpectedIsViewChangeAllowed(event3, true);
+ listener2.addExpectedIsViewChangeAllowed(event3, true);
+ view1.navigateTo("bar");
+ display.showView(view1);
+ manager.setFragment("test1/bar");
+ listener1.addExpectedNavigatorViewChange(event3);
+ listener2.addExpectedNavigatorViewChange(event3);
+
+ // both listeners allow view change from non-null view
+ EasyMock.expect(provider.getViewName("test2")).andReturn("test2");
+ EasyMock.expect(provider.getView("test2")).andReturn(view2);
+ EasyMock.expect(manager.getFragment()).andReturn("view1");
+ ViewChangeEvent event4 = new ViewChangeEvent(navigator, view1, view2,
+ "test2", null);
+ listener1.addExpectedIsViewChangeAllowed(event4, true);
+ listener2.addExpectedIsViewChangeAllowed(event4, true);
+ view2.navigateTo(null);
+ display.showView(view2);
+ manager.setFragment("test2");
+ listener1.addExpectedNavigatorViewChange(event4);
+ listener2.addExpectedNavigatorViewChange(event4);
+
+ control.replay();
+
+ // test navigator
+ navigator.registerProvider(provider);
+ navigator.addListener(listener1);
+ navigator.addListener(listener2);
+
+ navigator.navigateTo("test1");
+ navigator.navigateTo("test1/test");
+ navigator.navigateTo("test1/bar");
+ navigator.navigateTo("test2");
+
+ if (!listener1.isReady()) {
+ fail("Missing listener calls for listener1");
+ }
+ if (!listener2.isReady()) {
+ fail("Missing listener calls for listener2");
+ }
+ }
+
+ public void testDefaultDisplayType() {
+ IMocksControl control = EasyMock.createControl();
+ Page page = control.createMock(Page.class);
+
+ Navigator navigator = new Navigator(page);
+
+ assertEquals("Default display should be a SimpleViewDisplay",
+ SimpleViewDisplay.class, navigator.getDisplay().getClass());
+ }
+
+ public void testAddViewInstance() throws Exception {
+ View view = new TestView();
+
+ TestNavigator navigator = new TestNavigator();
+
+ navigator.addView("test", view);
+
+ assertEquals("Registered view instance not returned by navigator",
+ view, navigator.getView("test"));
+ }
+
+ public void testAddViewInstanceSameName() throws Exception {
+ View view1 = new TestView();
+ View view2 = new TestView2();
+
+ TestNavigator navigator = new TestNavigator();
+
+ navigator.addView("test", view1);
+ navigator.addView("test", view2);
+
+ assertEquals(
+ "Adding second view with same name should override previous view",
+ view2, navigator.getView("test"));
+ }
+
+ public void testAddViewClass() throws Exception {
+ TestNavigator navigator = new TestNavigator();
+
+ navigator.addView("test", TestView.class);
+
+ View view = navigator.getView("test");
+ assertNotNull("Received null view", view);
+ assertEquals("Received incorrect type of view", TestView.class,
+ view.getClass());
+ }
+
+ public void testAddViewClassSameName() throws Exception {
+ TestNavigator navigator = new TestNavigator();
+
+ navigator.addView("test", TestView.class);
+ navigator.addView("test", TestView2.class);
+
+ assertEquals(
+ "Adding second view class with same name should override previous view",
+ TestView2.class, navigator.getView("test").getClass());
+ }
+
+ public void testAddViewInstanceAndClassSameName() throws Exception {
+ TestNavigator navigator = new TestNavigator();
+
+ navigator.addView("test", TestView.class);
+ TestView2 view2 = new TestView2();
+ navigator.addView("test", view2);
+
+ assertEquals(
+ "Adding second view class with same name should override previous view",
+ view2, navigator.getView("test"));
+
+ navigator.addView("test", TestView.class);
+
+ assertEquals(
+ "Adding second view class with same name should override previous view",
+ TestView.class, navigator.getView("test").getClass());
+ }
+
+ public void testAddViewWithNullName() throws Exception {
+ Navigator navigator = new Navigator(new NullFragmentManager(),
+ new NullDisplay());
+
+ try {
+ navigator.addView(null, new TestView());
+ fail("addView() accepted null view name");
+ } catch (IllegalArgumentException e) {
+ }
+ try {
+ navigator.addView(null, TestView.class);
+ fail("addView() accepted null view name");
+ } catch (IllegalArgumentException e) {
+ }
+ }
+
+ public void testAddViewWithNullInstance() throws Exception {
+ Navigator navigator = new Navigator(new NullFragmentManager(),
+ new NullDisplay());
+
+ try {
+ navigator.addView("test", (View) null);
+ fail("addView() accepted null view instance");
+ } catch (IllegalArgumentException e) {
+ }
+ }
+
+ public void testAddViewWithNullClass() throws Exception {
+ Navigator navigator = new Navigator(new NullFragmentManager(),
+ new NullDisplay());
+
+ try {
+ navigator.addView("test", (Class<View>) null);
+ fail("addView() accepted null view class");
+ } catch (IllegalArgumentException e) {
+ }
+ }
+
+ public void testRemoveViewInstance() throws Exception {
+ View view = new TestView();
+
+ TestNavigator navigator = new TestNavigator();
+
+ navigator.addView("test", view);
+ navigator.removeView("test");
+
+ assertNull("View not removed", navigator.getView("test"));
+ }
+
+ public void testRemoveViewInstanceNothingElse() throws Exception {
+ View view = new TestView();
+ View view2 = new TestView2();
+
+ TestNavigator navigator = new TestNavigator();
+
+ navigator.addView("test", view);
+ navigator.addView("test2", view2);
+ navigator.removeView("test");
+
+ assertEquals("Removed extra views", view2, navigator.getView("test2"));
+ }
+
+ public void testRemoveViewClass() throws Exception {
+ TestNavigator navigator = new TestNavigator();
+
+ navigator.addView("test", TestView.class);
+ navigator.removeView("test");
+
+ assertNull("View not removed", navigator.getView("test"));
+ }
+
+ public void testRemoveViewClassNothingElse() throws Exception {
+ TestNavigator navigator = new TestNavigator();
+
+ navigator.addView("test", TestView.class);
+ navigator.addView("test2", TestView2.class);
+ navigator.removeView("test");
+
+ assertEquals("Removed extra views", TestView2.class,
+ navigator.getView("test2").getClass());
+ }
+
+ public void testGetViewNestedNames() throws Exception {
+ TestNavigator navigator = new TestNavigator();
+
+ navigator.addView("test/subview", TestView2.class);
+ navigator.addView("test", TestView.class);
+
+ assertEquals("Incorrect view name found for subview string",
+ TestView2.class, navigator.getView("test/subview").getClass());
+ assertEquals(
+ "Incorrect view name found for subview string with empty parameters",
+ TestView2.class, navigator.getView("test/subview/").getClass());
+ assertEquals(
+ "Incorrect view name found for subview string with parameters",
+ TestView2.class, navigator.getView("test/subview/parameters")
+ .getClass());
+ assertEquals("Incorrect view name found for top level view string",
+ TestView.class, navigator.getView("test").getClass());
+ assertEquals(
+ "Incorrect view name found for top level view string with empty parameters",
+ TestView.class, navigator.getView("test/").getClass());
+ assertEquals(
+ "Incorrect view name found for top level view string with parameters starting like subview name",
+ TestView.class, navigator.getView("test/subviewnothere")
+ .getClass());
+ }
+
+ public void testGetViewLongestPrefixOrder() throws Exception {
+ TestNavigator navigator = new TestNavigator();
+
+ navigator.addView("test/subview", TestView2.class);
+ navigator.addView("test", TestView.class);
+
+ assertEquals("Incorrect view name found", TestView.class, navigator
+ .getView("test").getClass());
+
+ // other order
+
+ TestNavigator navigator2 = new TestNavigator();
+
+ navigator2.addView("test", TestView.class);
+ navigator2.addView("test/subview", TestView2.class);
+
+ assertEquals("Incorrect view name found", TestView.class, navigator2
+ .getView("test").getClass());
+ }
+}
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..65294b2913
--- /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.terminal.Page;
+import com.vaadin.terminal.Page.FragmentChangedEvent;
+
+public class UriFragmentManagerTest extends TestCase {
+
+ public void testGetSetFragment() {
+ Page page = EasyMock.createMock(Page.class);
+ UriFragmentManager manager = new UriFragmentManager(page, null);
+
+ // prepare mock
+ EasyMock.expect(page.getFragment()).andReturn("");
+ page.setFragment("test");
+ EasyMock.expect(page.getFragment()).andReturn("test");
+ EasyMock.replay(page);
+
+ // 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);
+ Page page = control.createMock(Page.class);
+
+ UriFragmentManager manager = new UriFragmentManager(page, navigator);
+
+ EasyMock.expect(page.getFragment()).andReturn("test");
+ navigator.navigateTo("test");
+ control.replay();
+
+ FragmentChangedEvent event = page.new FragmentChangedEvent(page,
+ "oldtest");
+ manager.fragmentChanged(event);
+ }
+}
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));
+ }
+
+}
diff --git a/tests/test.xml b/tests/test.xml
index 67e48ee137..222fe0a452 100644
--- a/tests/test.xml
+++ b/tests/test.xml
@@ -11,7 +11,7 @@
<!-- Configuration -->
<!-- ================================================================== -->
<!-- Browsers to use for testing -->
- <property name="browsers-windows" value="winxp-ie8,win7-ie9,winxp-firefox12,winxp-safari5,winxp-googlechrome18,winxp-opera11" />
+ <property name="browsers-windows" value="winxp-ie8,win7-ie9,winxp-firefox12,winxp-safari5,winxp-googlechrome19,winxp-opera11" />
<property name="browsers-linux" value="linux-firefox3,linux-opera10,linux-googlechrome8" />
<property name="browsers-mac" value="osx-firefox3,osx-opera10,osx-googlechrome8,osx-safari4,osx-safari5" />
@@ -114,6 +114,8 @@
<path refid="classpath" />
<pathelement path="${class-dir}" />
</classpath>
+
+ <formatter usefile="false" type="plain"/>
<jvmarg value="-Dcom.vaadin.testbench.tester.host=${com.vaadin.testbench.tester.host}" />
<jvmarg value="-Dcom.vaadin.testbench.deployment.url=${com.vaadin.testbench.deployment.url}" />
diff --git a/tests/testbench/com/vaadin/launcher/ApplicationRunnerServlet.java b/tests/testbench/com/vaadin/launcher/ApplicationRunnerServlet.java
index 33d63b0413..dd93b1a8b6 100644
--- a/tests/testbench/com/vaadin/launcher/ApplicationRunnerServlet.java
+++ b/tests/testbench/com/vaadin/launcher/ApplicationRunnerServlet.java
@@ -9,7 +9,6 @@ import java.net.MalformedURLException;
import java.net.URL;
import java.util.Collections;
import java.util.LinkedHashSet;
-import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -45,9 +44,6 @@ 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.
@@ -241,8 +237,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 "
- + pkg + "." + baseName, e2);
+ getLogger().log(
+ Level.FINE,
+ "Failed to find application class " + pkg + "."
+ + baseName, e2);
}
if (appClass != null) {
return appClass;
@@ -289,4 +287,8 @@ public class ApplicationRunnerServlet extends AbstractApplicationServlet {
};
}
+ private Logger getLogger() {
+ return Logger.getLogger(ApplicationRunnerServlet.class.getName());
+ }
+
}
diff --git a/tests/testbench/com/vaadin/tests/TestBench.java b/tests/testbench/com/vaadin/tests/TestBench.java
index c3bb24cbef..1ac497e574 100644
--- a/tests/testbench/com/vaadin/tests/TestBench.java
+++ b/tests/testbench/com/vaadin/tests/TestBench.java
@@ -16,6 +16,8 @@ import com.vaadin.Application;
import com.vaadin.data.Property;
import com.vaadin.data.util.HierarchicalContainer;
import com.vaadin.terminal.ExternalResource;
+import com.vaadin.terminal.Page;
+import com.vaadin.terminal.Page.FragmentChangedEvent;
import com.vaadin.ui.Component;
import com.vaadin.ui.CustomComponent;
import com.vaadin.ui.HorizontalSplitPanel;
@@ -23,8 +25,6 @@ import com.vaadin.ui.Label;
import com.vaadin.ui.Layout;
import com.vaadin.ui.Link;
import com.vaadin.ui.Panel;
-import com.vaadin.ui.Root;
-import com.vaadin.ui.Root.FragmentChangedEvent;
import com.vaadin.ui.Root.LegacyWindow;
import com.vaadin.ui.Tree;
import com.vaadin.ui.VerticalLayout;
@@ -119,7 +119,7 @@ public class TestBench extends com.vaadin.Application.LegacyApplication
VerticalLayout lo = new VerticalLayout();
lo.addComponent(menu);
- mainWindow.addListener(new Root.FragmentChangedListener() {
+ mainWindow.getPage().addListener(new Page.FragmentChangedListener() {
public void fragmentChanged(FragmentChangedEvent source) {
String fragment = source.getFragment();
if (fragment != null && !"".equals(fragment)) {
diff --git a/tests/testbench/com/vaadin/tests/TestComponentAddAndRecursion.java b/tests/testbench/com/vaadin/tests/TestComponentAddAndRecursion.java
index 48eff0336e..3adaff93ea 100644
--- a/tests/testbench/com/vaadin/tests/TestComponentAddAndRecursion.java
+++ b/tests/testbench/com/vaadin/tests/TestComponentAddAndRecursion.java
@@ -3,6 +3,7 @@
*/
package com.vaadin.tests;
+import com.vaadin.terminal.Page;
import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.CustomComponent;
@@ -10,7 +11,6 @@ import com.vaadin.ui.GridLayout;
import com.vaadin.ui.Label;
import com.vaadin.ui.Notification;
import com.vaadin.ui.Panel;
-import com.vaadin.ui.Root;
import com.vaadin.ui.VerticalLayout;
/**
@@ -92,13 +92,13 @@ public class TestComponentAddAndRecursion extends CustomComponent {
public void buttonClick(ClickEvent event) {
try {
p3.addComponent(p2);
- Root.getCurrentRoot().showNotification("ERROR",
- "This should have failed",
- Notification.TYPE_ERROR_MESSAGE);
+ new Notification("ERROR", "This should have failed",
+ Notification.TYPE_ERROR_MESSAGE).show(Page
+ .getCurrent());
} catch (Exception e) {
- Root.getCurrentRoot().showNotification("OK",
- "threw, as expected",
- Notification.TYPE_ERROR_MESSAGE);
+ new Notification("OK", "threw, as expected",
+ Notification.TYPE_ERROR_MESSAGE).show(Page
+ .getCurrent());
}
}
@@ -111,13 +111,13 @@ public class TestComponentAddAndRecursion extends CustomComponent {
p.addComponent(p2);
try {
p3.addComponent(p);
- Root.getCurrentRoot().showNotification("ERROR",
- "This should have failed",
- Notification.TYPE_ERROR_MESSAGE);
+ new Notification("ERROR", "This should have failed",
+ Notification.TYPE_ERROR_MESSAGE).show(Page
+ .getCurrent());
} catch (Exception e) {
- Root.getCurrentRoot().showNotification("OK",
- "threw, as expected",
- Notification.TYPE_ERROR_MESSAGE);
+ new Notification("OK", "threw, as expected",
+ Notification.TYPE_ERROR_MESSAGE).show(Page
+ .getCurrent());
}
}
diff --git a/tests/testbench/com/vaadin/tests/TestForWindowOpen.java b/tests/testbench/com/vaadin/tests/TestForWindowOpen.java
index c9dbf8dabe..75395f0d5c 100644
--- a/tests/testbench/com/vaadin/tests/TestForWindowOpen.java
+++ b/tests/testbench/com/vaadin/tests/TestForWindowOpen.java
@@ -24,7 +24,7 @@ public class TestForWindowOpen extends CustomComponent {
public void buttonClick(ClickEvent event) {
final ExternalResource r = new ExternalResource(
"http://www.google.com");
- Root.getCurrentRoot().open(r);
+ Root.getCurrent().getPage().open(r);
}
@@ -36,7 +36,7 @@ public class TestForWindowOpen extends CustomComponent {
public void buttonClick(ClickEvent event) {
final ExternalResource r = new ExternalResource(
"http://www.google.com");
- Root.getCurrentRoot().open(r, "mytarget");
+ Root.getCurrent().getPage().open(r, "mytarget");
}
@@ -48,7 +48,7 @@ public class TestForWindowOpen extends CustomComponent {
public void buttonClick(ClickEvent event) {
final ExternalResource r = new ExternalResource(
"http://www.google.com");
- Root.getCurrentRoot().open(r, "secondtarget");
+ Root.getCurrent().getPage().open(r, "secondtarget");
}
diff --git a/tests/testbench/com/vaadin/tests/TestForWindowing.java b/tests/testbench/com/vaadin/tests/TestForWindowing.java
index f97ea33d61..b9e14608f5 100644
--- a/tests/testbench/com/vaadin/tests/TestForWindowing.java
+++ b/tests/testbench/com/vaadin/tests/TestForWindowing.java
@@ -85,7 +85,7 @@ public class TestForWindowing extends CustomComponent {
w.addComponent(s);
- Root.getCurrentRoot().addWindow(w);
+ Root.getCurrent().addWindow(w);
}
diff --git a/tests/testbench/com/vaadin/tests/appengine/GAESyncTest.java b/tests/testbench/com/vaadin/tests/appengine/GAESyncTest.java
index 7d5e298286..58faec35f0 100644
--- a/tests/testbench/com/vaadin/tests/appengine/GAESyncTest.java
+++ b/tests/testbench/com/vaadin/tests/appengine/GAESyncTest.java
@@ -91,7 +91,8 @@ public class GAESyncTest extends Application.LegacyApplication {
public void buttonClick(ClickEvent event) {
if (getRoot() == getMainWindow()) {
- getRoot().showNotification("main");
+ getRoot().getPage().showNotification(
+ new Notification("main"));
try {
Thread.sleep((5000));
} catch (InterruptedException e) {
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 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head profile="http://selenium-ide.openqa.org/profiles/test-case">
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<link rel="selenium.base" href="" />
+<title>TabSheetWithDisappearingContent</title>
+</head>
+<body>
+<table cellpadding="1" cellspacing="1" border="1">
+<thead>
+<tr><td rowspan="1" colspan="3">TabSheetWithDisappearingContent</td></tr>
+</thead><tbody>
+<tr>
+ <td>open</td>
+ <td>/run/com.vaadin.tests.application.TerminalErrorNotification?restartApplication&amp;debug</td>
+ <td></td>
+</tr>
+<tr>
+ <td>click</td>
+ <td>vaadin=runcomvaadintestsapplicationTerminalErrorNotification::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VButton[0]/domChild[0]/domChild[0]</td>
+ <td></td>
+</tr>
+<tr>
+ <td>assertElementPresent</td>
+ <td>vaadin=runcomvaadintestsapplicationTerminalErrorNotification::Root/VNotification[0]</td>
+ <td></td>
+</tr>
+<tr>
+ <td>assertText</td>
+ <td>vaadin=runcomvaadintestsapplicationTerminalErrorNotification::Root/VNotification[0]/HTML[0]/domChild[0]</td>
+ <td>Got an exception: You asked for it</td>
+</tr>
+</tbody></table>
+</body>
+</html>
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..f2ae7a3891
--- /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.Notification;
+import com.vaadin.ui.Root;
+
+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();
+
+ Root mainWindow = getMainWindow();
+ if (mainWindow != null) {
+ Throwable throwable = event.getThrowable();
+
+ // Find the root cause
+ while (throwable.getCause() != null) {
+ throwable = throwable.getCause();
+ }
+
+ Notification.show("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);
+ }
+
+}
diff --git a/tests/testbench/com/vaadin/tests/application/ThreadLocalInstances.java b/tests/testbench/com/vaadin/tests/application/ThreadLocalInstances.java
index 68a0bb3805..fd65adf209 100644
--- a/tests/testbench/com/vaadin/tests/application/ThreadLocalInstances.java
+++ b/tests/testbench/com/vaadin/tests/application/ThreadLocalInstances.java
@@ -16,8 +16,8 @@ import com.vaadin.ui.Root;
public class ThreadLocalInstances extends AbstractTestApplication {
private static final Application staticInitApplication = Application
- .getCurrentApplication();
- private static final Root staticInitRoot = Root.getCurrentRoot();
+ .getCurrent();
+ private static final Root staticInitRoot = Root.getCurrent();
private final Root mainWindow = new Root() {
boolean paintReported = false;
@@ -92,8 +92,8 @@ public class ThreadLocalInstances extends AbstractTestApplication {
}
private void reportCurrentStatus(String phase) {
- reportStatus(phase, Application.getCurrentApplication(),
- Root.getCurrentRoot());
+ reportStatus(phase, Application.getCurrent(),
+ Root.getCurrent());
}
private void reportStatus(String phase, Application application, Root root) {
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());
}
});
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 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head profile="http://selenium-ide.openqa.org/profiles/test-case">
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<link rel="selenium.base" href="http://localhost:8888/" />
+<title>New Test</title>
+</head>
+<body>
+<table cellpadding="1" cellspacing="1" border="1">
+<thead>
+<tr><td rowspan="1" colspan="3">New Test</td></tr>
+</thead><tbody>
+<tr>
+ <td>open</td>
+ <td>/run/ClassThatIsNotPresent?restartApplication</td>
+ <td></td>
+</tr>
+<tr>
+ <td>assertText</td>
+ <td>//pre[1]</td>
+ <td>java.lang.InstantiationException: Failed to load application class: ClassThatIsNotPresent</td>
+</tr>
+</tbody></table>
+</body>
+</html>
diff --git a/tests/testbench/com/vaadin/tests/components/AbstractTestRoot.java b/tests/testbench/com/vaadin/tests/components/AbstractTestRoot.java
index fd90cf2d6e..875d2b1df8 100644
--- a/tests/testbench/com/vaadin/tests/components/AbstractTestRoot.java
+++ b/tests/testbench/com/vaadin/tests/components/AbstractTestRoot.java
@@ -15,7 +15,7 @@ public abstract class AbstractTestRoot extends Root {
@Override
public void init(WrappedRequest request) {
- setCaption(getClass().getName());
+ getPage().setTitle(getClass().getName());
Label label = new Label(getTestDescription(), ContentMode.XHTML);
label.setWidth("100%");
@@ -57,7 +57,7 @@ public abstract class AbstractTestRoot extends Root {
protected abstract Integer getTicketNumber();
protected WebBrowser getBrowser() {
- ApplicationContext context = Application.getCurrentApplication()
+ ApplicationContext context = Application.getCurrent()
.getContext();
if (context instanceof AbstractWebApplicationContext) {
AbstractWebApplicationContext webContext = (AbstractWebApplicationContext) context;
diff --git a/tests/testbench/com/vaadin/tests/components/DisableEnableCascadeStyles.html b/tests/testbench/com/vaadin/tests/components/DisableEnableCascadeStyles.html
new file mode 100644
index 0000000000..ac3a4f0cb0
--- /dev/null
+++ b/tests/testbench/com/vaadin/tests/components/DisableEnableCascadeStyles.html
@@ -0,0 +1,250 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head profile="http://selenium-ide.openqa.org/profiles/test-case">
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<link rel="selenium.base" href="http://localhost:8888/" />
+<title>DisableEnableCascadeStyles</title>
+</head>
+<body>
+<table cellpadding="1" cellspacing="1" border="1">
+<thead>
+<tr><td rowspan="1" colspan="3">DisableEnableCascadeStyles</td></tr>
+</thead><tbody>
+<tr>
+ <td>open</td>
+ <td>/run/com.vaadin.tests.components.DisableEnableCascadeStyles?restartApplication</td>
+ <td></td>
+</tr>
+<!--disable tabsheet-->
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentsDisableEnableCascadeStyles::/VVerticalLayout[0]/VVerticalLayout[0]/VButton[1]/domChild[0]/domChild[0]</td>
+ <td></td>
+</tr>
+<!--assert css class names for bottom level components-->
+<tr>
+ <td>assertCSSClass</td>
+ <td>vaadin=runcomvaadintestscomponentsDisableEnableCascadeStyles::/VVerticalLayout[0]/VVerticalLayout[0]/VPanel[0]/VTabsheet[0]/VTabsheetPanel[0]/VVerticalLayout[0]/VButton[0]</td>
+ <td>v-disabled</td>
+</tr>
+<tr>
+ <td>assertCSSClass</td>
+ <td>vaadin=runcomvaadintestscomponentsDisableEnableCascadeStyles::/VVerticalLayout[0]/VVerticalLayout[0]/VPanel[0]/VTabsheet[0]/VTabsheetPanel[0]/VVerticalLayout[0]/VNativeButton[0]</td>
+ <td>v-disabled</td>
+</tr>
+<tr>
+ <td>assertCSSClass</td>
+ <td>vaadin=runcomvaadintestscomponentsDisableEnableCascadeStyles::/VVerticalLayout[0]/VVerticalLayout[0]/VPanel[0]/VTabsheet[0]/VTabsheetPanel[0]/VVerticalLayout[0]/VTextField[0]</td>
+ <td>v-disabled</td>
+</tr>
+<tr>
+ <td>assertCSSClass</td>
+ <td>vaadin=runcomvaadintestscomponentsDisableEnableCascadeStyles::/VVerticalLayout[0]/VVerticalLayout[0]/VPanel[0]/VTabsheet[0]/VTabsheetPanel[0]/VVerticalLayout[0]/VTextArea[0]</td>
+ <td>v-disabled</td>
+</tr>
+<!--assert css class name for component captions-->
+<tr>
+ <td>assertCSSClass</td>
+ <td>vaadin=runcomvaadintestscomponentsDisableEnableCascadeStyles::/VVerticalLayout[0]/VVerticalLayout[0]/VPanel[0]/VTabsheet[0]/VTabsheetPanel[0]/VVerticalLayout[0]/domChild[2]/domChild[0]</td>
+ <td>v-disabled</td>
+</tr>
+<tr>
+ <td>assertCSSClass</td>
+ <td>vaadin=runcomvaadintestscomponentsDisableEnableCascadeStyles::/VVerticalLayout[0]/VVerticalLayout[0]/VPanel[0]/VTabsheet[0]/VTabsheetPanel[0]/VVerticalLayout[0]/domChild[3]/domChild[0]</td>
+ <td>v-disabled</td>
+</tr>
+<!--enable tabsheet-->
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentsDisableEnableCascadeStyles::/VVerticalLayout[0]/VVerticalLayout[0]/VButton[1]/domChild[0]/domChild[0]</td>
+ <td></td>
+</tr>
+<!--assert css class names for bottom level components-->
+<tr>
+ <td>assertNotCSSClass</td>
+ <td>vaadin=runcomvaadintestscomponentsDisableEnableCascadeStyles::/VVerticalLayout[0]/VVerticalLayout[0]/VPanel[0]/VTabsheet[0]/VTabsheetPanel[0]/VVerticalLayout[0]/VButton[0]</td>
+ <td>v-disabled</td>
+</tr>
+<tr>
+ <td>assertNotCSSClass</td>
+ <td>vaadin=runcomvaadintestscomponentsDisableEnableCascadeStyles::/VVerticalLayout[0]/VVerticalLayout[0]/VPanel[0]/VTabsheet[0]/VTabsheetPanel[0]/VVerticalLayout[0]/VNativeButton[0]</td>
+ <td>v-disabled</td>
+</tr>
+<tr>
+ <td>assertNotCSSClass</td>
+ <td>vaadin=runcomvaadintestscomponentsDisableEnableCascadeStyles::/VVerticalLayout[0]/VVerticalLayout[0]/VPanel[0]/VTabsheet[0]/VTabsheetPanel[0]/VVerticalLayout[0]/VTextField[0]</td>
+ <td>v-disabled</td>
+</tr>
+<tr>
+ <td>assertNotCSSClass</td>
+ <td>vaadin=runcomvaadintestscomponentsDisableEnableCascadeStyles::/VVerticalLayout[0]/VVerticalLayout[0]/VPanel[0]/VTabsheet[0]/VTabsheetPanel[0]/VVerticalLayout[0]/VTextArea[0]</td>
+ <td>v-disabled</td>
+</tr>
+<!--assert css class name for component captions-->
+<tr>
+ <td>assertNotCSSClass</td>
+ <td>vaadin=runcomvaadintestscomponentsDisableEnableCascadeStyles::/VVerticalLayout[0]/VVerticalLayout[0]/VPanel[0]/VTabsheet[0]/VTabsheetPanel[0]/VVerticalLayout[0]/domChild[2]/domChild[0]</td>
+ <td>v-disabled</td>
+</tr>
+<tr>
+ <td>assertNotCSSClass</td>
+ <td>vaadin=runcomvaadintestscomponentsDisableEnableCascadeStyles::/VVerticalLayout[0]/VVerticalLayout[0]/VPanel[0]/VTabsheet[0]/VTabsheetPanel[0]/VVerticalLayout[0]/domChild[3]/domChild[0]</td>
+ <td>v-disabled</td>
+</tr>
+<!--disable layout containing components-->
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentsDisableEnableCascadeStyles::/VVerticalLayout[0]/VVerticalLayout[0]/VButton[2]/domChild[0]/domChild[0]</td>
+ <td></td>
+</tr>
+<!--assert css class names for bottom level components-->
+<tr>
+ <td>assertCSSClass</td>
+ <td>vaadin=runcomvaadintestscomponentsDisableEnableCascadeStyles::/VVerticalLayout[0]/VVerticalLayout[0]/VPanel[0]/VTabsheet[0]/VTabsheetPanel[0]/VVerticalLayout[0]/VButton[0]</td>
+ <td>v-disabled</td>
+</tr>
+<tr>
+ <td>assertCSSClass</td>
+ <td>vaadin=runcomvaadintestscomponentsDisableEnableCascadeStyles::/VVerticalLayout[0]/VVerticalLayout[0]/VPanel[0]/VTabsheet[0]/VTabsheetPanel[0]/VVerticalLayout[0]/VNativeButton[0]</td>
+ <td>v-disabled</td>
+</tr>
+<tr>
+ <td>assertCSSClass</td>
+ <td>vaadin=runcomvaadintestscomponentsDisableEnableCascadeStyles::/VVerticalLayout[0]/VVerticalLayout[0]/VPanel[0]/VTabsheet[0]/VTabsheetPanel[0]/VVerticalLayout[0]/VTextField[0]</td>
+ <td>v-disabled</td>
+</tr>
+<tr>
+ <td>assertCSSClass</td>
+ <td>vaadin=runcomvaadintestscomponentsDisableEnableCascadeStyles::/VVerticalLayout[0]/VVerticalLayout[0]/VPanel[0]/VTabsheet[0]/VTabsheetPanel[0]/VVerticalLayout[0]/VTextArea[0]</td>
+ <td>v-disabled</td>
+</tr>
+<!--assert css class name for component captions-->
+<tr>
+ <td>assertCSSClass</td>
+ <td>vaadin=runcomvaadintestscomponentsDisableEnableCascadeStyles::/VVerticalLayout[0]/VVerticalLayout[0]/VPanel[0]/VTabsheet[0]/VTabsheetPanel[0]/VVerticalLayout[0]/domChild[2]/domChild[0]</td>
+ <td>v-disabled</td>
+</tr>
+<tr>
+ <td>assertCSSClass</td>
+ <td>vaadin=runcomvaadintestscomponentsDisableEnableCascadeStyles::/VVerticalLayout[0]/VVerticalLayout[0]/VPanel[0]/VTabsheet[0]/VTabsheetPanel[0]/VVerticalLayout[0]/domChild[3]/domChild[0]</td>
+ <td>v-disabled</td>
+</tr>
+<!--enable layout containing components-->
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentsDisableEnableCascadeStyles::/VVerticalLayout[0]/VVerticalLayout[0]/VButton[2]/domChild[0]/domChild[0]</td>
+ <td></td>
+</tr>
+<!--assert css class names for bottom level components-->
+<tr>
+ <td>assertNotCSSClass</td>
+ <td>vaadin=runcomvaadintestscomponentsDisableEnableCascadeStyles::/VVerticalLayout[0]/VVerticalLayout[0]/VPanel[0]/VTabsheet[0]/VTabsheetPanel[0]/VVerticalLayout[0]/VButton[0]</td>
+ <td>v-disabled</td>
+</tr>
+<tr>
+ <td>assertNotCSSClass</td>
+ <td>vaadin=runcomvaadintestscomponentsDisableEnableCascadeStyles::/VVerticalLayout[0]/VVerticalLayout[0]/VPanel[0]/VTabsheet[0]/VTabsheetPanel[0]/VVerticalLayout[0]/VNativeButton[0]</td>
+ <td>v-disabled</td>
+</tr>
+<tr>
+ <td>assertNotCSSClass</td>
+ <td>vaadin=runcomvaadintestscomponentsDisableEnableCascadeStyles::/VVerticalLayout[0]/VVerticalLayout[0]/VPanel[0]/VTabsheet[0]/VTabsheetPanel[0]/VVerticalLayout[0]/VTextField[0]</td>
+ <td>v-disabled</td>
+</tr>
+<tr>
+ <td>assertNotCSSClass</td>
+ <td>vaadin=runcomvaadintestscomponentsDisableEnableCascadeStyles::/VVerticalLayout[0]/VVerticalLayout[0]/VPanel[0]/VTabsheet[0]/VTabsheetPanel[0]/VVerticalLayout[0]/VTextArea[0]</td>
+ <td>v-disabled</td>
+</tr>
+<!--assert css class name for component captions-->
+<tr>
+ <td>assertNotCSSClass</td>
+ <td>vaadin=runcomvaadintestscomponentsDisableEnableCascadeStyles::/VVerticalLayout[0]/VVerticalLayout[0]/VPanel[0]/VTabsheet[0]/VTabsheetPanel[0]/VVerticalLayout[0]/domChild[2]/domChild[0]</td>
+ <td>v-disabled</td>
+</tr>
+<tr>
+ <td>assertNotCSSClass</td>
+ <td>vaadin=runcomvaadintestscomponentsDisableEnableCascadeStyles::/VVerticalLayout[0]/VVerticalLayout[0]/VPanel[0]/VTabsheet[0]/VTabsheetPanel[0]/VVerticalLayout[0]/domChild[3]/domChild[0]</td>
+ <td>v-disabled</td>
+</tr>
+<!--disable all bottom level components-->
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentsDisableEnableCascadeStyles::/VVerticalLayout[0]/VVerticalLayout[0]/VButton[3]/domChild[0]/domChild[0]</td>
+ <td></td>
+</tr>
+<!--assert css class names for bottom level components-->
+<tr>
+ <td>assertCSSClass</td>
+ <td>vaadin=runcomvaadintestscomponentsDisableEnableCascadeStyles::/VVerticalLayout[0]/VVerticalLayout[0]/VPanel[0]/VTabsheet[0]/VTabsheetPanel[0]/VVerticalLayout[0]/VButton[0]</td>
+ <td>v-disabled</td>
+</tr>
+<tr>
+ <td>assertCSSClass</td>
+ <td>vaadin=runcomvaadintestscomponentsDisableEnableCascadeStyles::/VVerticalLayout[0]/VVerticalLayout[0]/VPanel[0]/VTabsheet[0]/VTabsheetPanel[0]/VVerticalLayout[0]/VNativeButton[0]</td>
+ <td>v-disabled</td>
+</tr>
+<tr>
+ <td>assertCSSClass</td>
+ <td>vaadin=runcomvaadintestscomponentsDisableEnableCascadeStyles::/VVerticalLayout[0]/VVerticalLayout[0]/VPanel[0]/VTabsheet[0]/VTabsheetPanel[0]/VVerticalLayout[0]/VTextField[0]</td>
+ <td>v-disabled</td>
+</tr>
+<tr>
+ <td>assertCSSClass</td>
+ <td>vaadin=runcomvaadintestscomponentsDisableEnableCascadeStyles::/VVerticalLayout[0]/VVerticalLayout[0]/VPanel[0]/VTabsheet[0]/VTabsheetPanel[0]/VVerticalLayout[0]/VTextArea[0]</td>
+ <td>v-disabled</td>
+</tr>
+<!--assert css class name for component captions-->
+<tr>
+ <td>assertCSSClass</td>
+ <td>vaadin=runcomvaadintestscomponentsDisableEnableCascadeStyles::/VVerticalLayout[0]/VVerticalLayout[0]/VPanel[0]/VTabsheet[0]/VTabsheetPanel[0]/VVerticalLayout[0]/domChild[2]/domChild[0]</td>
+ <td>v-disabled</td>
+</tr>
+<tr>
+ <td>assertCSSClass</td>
+ <td>vaadin=runcomvaadintestscomponentsDisableEnableCascadeStyles::/VVerticalLayout[0]/VVerticalLayout[0]/VPanel[0]/VTabsheet[0]/VTabsheetPanel[0]/VVerticalLayout[0]/domChild[3]/domChild[0]</td>
+ <td>v-disabled</td>
+</tr>
+<!--enable all bottom level components-->
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentsDisableEnableCascadeStyles::/VVerticalLayout[0]/VVerticalLayout[0]/VButton[3]/domChild[0]/domChild[0]</td>
+ <td></td>
+</tr>
+<!--assert css class names for bottom level components-->
+<tr>
+ <td>assertNotCSSClass</td>
+ <td>vaadin=runcomvaadintestscomponentsDisableEnableCascadeStyles::/VVerticalLayout[0]/VVerticalLayout[0]/VPanel[0]/VTabsheet[0]/VTabsheetPanel[0]/VVerticalLayout[0]/VButton[0]</td>
+ <td>v-disabled</td>
+</tr>
+<tr>
+ <td>assertNotCSSClass</td>
+ <td>vaadin=runcomvaadintestscomponentsDisableEnableCascadeStyles::/VVerticalLayout[0]/VVerticalLayout[0]/VPanel[0]/VTabsheet[0]/VTabsheetPanel[0]/VVerticalLayout[0]/VNativeButton[0]</td>
+ <td>v-disabled</td>
+</tr>
+<tr>
+ <td>assertNotCSSClass</td>
+ <td>vaadin=runcomvaadintestscomponentsDisableEnableCascadeStyles::/VVerticalLayout[0]/VVerticalLayout[0]/VPanel[0]/VTabsheet[0]/VTabsheetPanel[0]/VVerticalLayout[0]/VTextField[0]</td>
+ <td>v-disabled</td>
+</tr>
+<tr>
+ <td>assertNotCSSClass</td>
+ <td>vaadin=runcomvaadintestscomponentsDisableEnableCascadeStyles::/VVerticalLayout[0]/VVerticalLayout[0]/VPanel[0]/VTabsheet[0]/VTabsheetPanel[0]/VVerticalLayout[0]/VTextArea[0]</td>
+ <td>v-disabled</td>
+</tr>
+<!--assert css class name for component captions-->
+<tr>
+ <td>assertNotCSSClass</td>
+ <td>vaadin=runcomvaadintestscomponentsDisableEnableCascadeStyles::/VVerticalLayout[0]/VVerticalLayout[0]/VPanel[0]/VTabsheet[0]/VTabsheetPanel[0]/VVerticalLayout[0]/domChild[2]/domChild[0]</td>
+ <td>v-disabled</td>
+</tr>
+<tr>
+ <td>assertNotCSSClass</td>
+ <td>vaadin=runcomvaadintestscomponentsDisableEnableCascadeStyles::/VVerticalLayout[0]/VVerticalLayout[0]/VPanel[0]/VTabsheet[0]/VTabsheetPanel[0]/VVerticalLayout[0]/domChild[3]/domChild[0]</td>
+ <td>v-disabled</td>
+</tr>
+
+</tbody></table>
+</body>
+</html>
diff --git a/tests/testbench/com/vaadin/tests/components/DisableEnableCascadeStyles.java b/tests/testbench/com/vaadin/tests/components/DisableEnableCascadeStyles.java
new file mode 100644
index 0000000000..f3391afd1f
--- /dev/null
+++ b/tests/testbench/com/vaadin/tests/components/DisableEnableCascadeStyles.java
@@ -0,0 +1,142 @@
+package com.vaadin.tests.components;
+
+import java.util.Iterator;
+
+import com.vaadin.ui.Button;
+import com.vaadin.ui.Button.ClickEvent;
+import com.vaadin.ui.Button.ClickListener;
+import com.vaadin.ui.Component;
+import com.vaadin.ui.NativeButton;
+import com.vaadin.ui.Panel;
+import com.vaadin.ui.TabSheet;
+import com.vaadin.ui.TextArea;
+import com.vaadin.ui.TextField;
+import com.vaadin.ui.VerticalLayout;
+
+public class DisableEnableCascadeStyles extends TestBase {
+
+ private Panel outerPanel;
+ private TabSheet innerTabsheet;
+ private Button button;
+ private TextArea textArea;
+ private TextField textField;
+ private VerticalLayout layout;
+ private NativeButton nativeButton;
+ private Button enableDisablePanelButton;
+ private Button enableDisableTabSheetButton;
+ private Button enableDisableLayoutButton;
+ private Button enableDisableComponentsButton;
+
+ @Override
+ protected void setup() {
+
+ outerPanel = new Panel("Outer panel, enabled");
+ innerTabsheet = new TabSheet();
+ innerTabsheet.setCaption("Inner Tabsheet, enabled");
+
+ button = new Button("Button, enabled");
+ nativeButton = new NativeButton("NativeButton, enabled");
+ textField = new TextField("TextField with caption and value, enabled");
+ textField.setValue("Text");
+ textArea = new TextArea("TextArea with caption and value, enabled");
+ textArea.setValue("Text");
+ layout = new VerticalLayout();
+ layout.setCaption("VerticalLayout, enabled");
+ layout.addComponent(button);
+ layout.addComponent(nativeButton);
+ layout.addComponent(textField);
+ layout.addComponent(textArea);
+
+ outerPanel.setContent(innerTabsheet);
+ innerTabsheet.addTab(layout, "Tab containing layout");
+
+ addComponent(outerPanel);
+
+ enableDisablePanelButton = new Button("Disable panel",
+ new ClickListener() {
+
+ public void buttonClick(ClickEvent event) {
+ enableDisable(outerPanel, enableDisablePanelButton);
+
+ }
+ });
+
+ enableDisableTabSheetButton = new Button("Disable TabSheet",
+ new ClickListener() {
+
+ public void buttonClick(ClickEvent event) {
+ enableDisable(innerTabsheet,
+ enableDisableTabSheetButton);
+
+ }
+ });
+
+ enableDisableLayoutButton = new Button("Disable Tab content (Layout)",
+ new ClickListener() {
+
+ public void buttonClick(ClickEvent event) {
+ enableDisable(layout, enableDisableLayoutButton);
+
+ }
+ });
+ enableDisableComponentsButton = new Button("Disable Layout Components",
+ new ClickListener() {
+
+ public void buttonClick(ClickEvent event) {
+ for (Iterator<Component> i = layout
+ .getComponentIterator(); i.hasNext();) {
+ final Component c = i.next();
+ if (c.isEnabled()) {
+ c.setEnabled(false);
+ c.setCaption(c.getCaption().replace("enabled",
+ "disabled"));
+ } else {
+ c.setEnabled(true);
+ c.setCaption(c.getCaption().replace("disabled",
+ "enabled"));
+ }
+ }
+ if (layout.getComponent(0).isEnabled()) {
+ enableDisableComponentsButton
+ .setCaption(enableDisableComponentsButton
+ .getCaption().replace("Enable",
+ "Disable"));
+ } else {
+ enableDisableComponentsButton
+ .setCaption(enableDisableComponentsButton
+ .getCaption().replace("Disable",
+ "Enable"));
+ }
+ }
+ });
+ addComponent(enableDisablePanelButton);
+ addComponent(enableDisableTabSheetButton);
+ addComponent(enableDisableLayoutButton);
+ addComponent(enableDisableComponentsButton);
+ }
+
+ protected void enableDisable(Component target, Button button) {
+ if (target.isEnabled()) {
+ target.setEnabled(false);
+ button.setCaption(button.getCaption().replace("Disable", "Enable"));
+ target.setCaption(target.getCaption()
+ .replace("enabled", "disabled"));
+ } else {
+ target.setEnabled(true);
+ button.setCaption(button.getCaption().replace("Enable", "Disable"));
+ target.setCaption(target.getCaption()
+ .replace("disabled", "enabled"));
+ }
+ }
+
+ @Override
+ protected String getDescription() {
+ return "Tests the disable state is cascaded correctly to children components that can be disabled. The children and their captions must get the v-disabled style name.";
+ }
+
+ @Override
+ protected Integer getTicketNumber() {
+ return 8708;
+ }
+
+} \ No newline at end of file
diff --git a/tests/testbench/com/vaadin/tests/components/TestBase.java b/tests/testbench/com/vaadin/tests/components/TestBase.java
index 6524a30fb7..b3c0f63dcb 100644
--- a/tests/testbench/com/vaadin/tests/components/TestBase.java
+++ b/tests/testbench/com/vaadin/tests/components/TestBase.java
@@ -26,6 +26,16 @@ public abstract class TestBase extends AbstractTestCase {
}
private LegacyWindow window;
+
+ @Override
+ public void setMainWindow(LegacyWindow 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 VerticalLayout layout;
public TestBase() {
diff --git a/tests/testbench/com/vaadin/tests/components/TouchScrollables.java b/tests/testbench/com/vaadin/tests/components/TouchScrollables.java
index 053691e738..8ad12da85f 100644
--- a/tests/testbench/com/vaadin/tests/components/TouchScrollables.java
+++ b/tests/testbench/com/vaadin/tests/components/TouchScrollables.java
@@ -24,6 +24,7 @@ import com.vaadin.ui.CssLayout;
import com.vaadin.ui.HorizontalSplitPanel;
import com.vaadin.ui.Label;
import com.vaadin.ui.Layout;
+import com.vaadin.ui.Notification;
import com.vaadin.ui.Panel;
import com.vaadin.ui.TabSheet;
import com.vaadin.ui.Table;
@@ -189,7 +190,7 @@ public class TouchScrollables extends TestBase {
}
public void handleAction(Action action, Object sender, Object target) {
- getLayout().getRoot().showNotification(action.getCaption());
+ Notification.show(action.getCaption());
}
});
diff --git a/tests/testbench/com/vaadin/tests/components/beanitemcontainer/BeanItemContainerNullValues.java b/tests/testbench/com/vaadin/tests/components/beanitemcontainer/BeanItemContainerNullValues.java
index 9045d18940..f613a8b14f 100644
--- a/tests/testbench/com/vaadin/tests/components/beanitemcontainer/BeanItemContainerNullValues.java
+++ b/tests/testbench/com/vaadin/tests/components/beanitemcontainer/BeanItemContainerNullValues.java
@@ -30,11 +30,11 @@ public class BeanItemContainerNullValues extends TestBase {
Button b = new Button("Disable sorting", new Button.ClickListener() {
public void buttonClick(ClickEvent event) {
- table.setSortDisabled(!table.isSortDisabled());
- if (table.isSortDisabled()) {
- event.getButton().setCaption("Enable sorting");
- } else {
+ table.setSortEnabled(!table.isSortEnabled());
+ if (table.isSortEnabled()) {
event.getButton().setCaption("Disable sorting");
+ } else {
+ event.getButton().setCaption("Enable sorting");
}
}
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 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head profile="http://selenium-ide.openqa.org/profiles/test-case">
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<link rel="selenium.base" href="" />
+<title>New Test</title>
+</head>
+<body>
+<table cellpadding="1" cellspacing="1" border="1">
+<thead>
+<tr><td rowspan="1" colspan="3">New Test</td></tr>
+</thead><tbody>
+<tr>
+ <td>open</td>
+ <td>/run/com.vaadin.tests.components.button.ButtonEnterWithWindowShortcut?restartApplication</td>
+ <td></td>
+</tr>
+<tr>
+ <td>pressSpecialKey</td>
+ <td>vaadin=runcomvaadintestscomponentsbuttonButtonEnterWithWindowShortcut::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[1]/VButton[0]</td>
+ <td>enter</td>
+</tr>
+<tr>
+ <td>assertText</td>
+ <td>vaadin=runcomvaadintestscomponentsbuttonButtonEnterWithWindowShortcut::PID_SLog_row_0</td>
+ <td>1. button click listener fired</td>
+</tr>
+<tr>
+ <td>pressSpecialKey</td>
+ <td>vaadin=runcomvaadintestscomponentsbuttonButtonEnterWithWindowShortcut::</td>
+ <td>enter</td>
+</tr>
+<tr>
+ <td>assertText</td>
+ <td>vaadin=runcomvaadintestscomponentsbuttonButtonEnterWithWindowShortcut::PID_SLog_row_0</td>
+ <td>2. enter pressed in window</td>
+</tr>
+<!-- Can't test using space because of #8827 -->
+<!-- <tr>
+ <td>pressSpecialKey</td>
+ <td>vaadin=runcomvaadintestscomponentsbuttonButtonEnterWithWindowShortcut::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[1]/VButton[0]</td>
+ <td>space</td>
+</tr>
+<tr>
+ <td>assertText</td>
+ <td>vaadin=runcomvaadintestscomponentsbuttonButtonEnterWithWindowShortcut::PID_SLog_row_0</td>
+ <td>3. button click listener fired</td>
+</tr>
+<tr>
+ <td>pressSpecialKey</td>
+ <td>vaadin=runcomvaadintestscomponentsbuttonButtonEnterWithWindowShortcut::</td>
+ <td>space</td>
+</tr>
+<tr>
+ <td>assertText</td>
+ <td>vaadin=runcomvaadintestscomponentsbuttonButtonEnterWithWindowShortcut::PID_SLog_row_0</td>
+ <td>4. space pressed in window</td>
+</tr> -->
+</tbody></table>
+</body>
+</html>
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);
+ }
+
+}
diff --git a/tests/testbench/com/vaadin/tests/components/button/ButtonTabIndex.java b/tests/testbench/com/vaadin/tests/components/button/ButtonTabIndex.java
new file mode 100644
index 0000000000..048e0698f3
--- /dev/null
+++ b/tests/testbench/com/vaadin/tests/components/button/ButtonTabIndex.java
@@ -0,0 +1,53 @@
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+package com.vaadin.tests.components.button;
+
+import com.vaadin.tests.components.TestBase;
+import com.vaadin.ui.Button;
+import com.vaadin.ui.NativeButton;
+import com.vaadin.ui.TextField;
+
+public class ButtonTabIndex extends TestBase {
+
+ @Override
+ protected void setup() {
+ TextField tf1 = new TextField("Tab index 0");
+ tf1.setTabIndex(0);
+ TextField tf2 = new TextField("Tab index -1, focused initially");
+ tf2.setTabIndex(-1);
+ tf2.focus();
+ addComponent(tf1);
+ addComponent(tf2);
+
+ addComponent(createButton(1));
+ addComponent(createButton(5));
+ addComponent(createNativeButton(3));
+ addComponent(createButton(4));
+ addComponent(createNativeButton(2));
+
+ }
+
+ private Button createButton(int i) {
+ Button b = new Button("Button with tab index " + i);
+ b.setTabIndex(i);
+ return b;
+ }
+
+ private NativeButton createNativeButton(int i) {
+ NativeButton b = new NativeButton("NativeButton with tab index " + i);
+ b.setTabIndex(i);
+ return b;
+ }
+
+ @Override
+ protected String getDescription() {
+ return "Test for tab indexes for Button and NativeButton";
+ }
+
+ @Override
+ protected Integer getTicketNumber() {
+ return 9022;
+ }
+
+}
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
@@ -33,6 +33,11 @@
</tr>
<tr>
<td>click</td>
+ <td>vaadin=runcomvaadintestscomponentscomboboxComboBoxInvalidNullSelection::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[3]/VButton[0]/domChild[0]/domChild[0]</td>
+ <td></td>
+</tr>
+<tr>
+ <td>click</td>
<td>vaadin=runcomvaadintestscomponentscomboboxComboBoxInvalidNullSelection::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[1]/VButton[0]/domChild[0]/domChild[0]</td>
<td></td>
</tr>
diff --git a/tests/testbench/com/vaadin/tests/components/customfield/AddressFormExample.java b/tests/testbench/com/vaadin/tests/components/customfield/AddressFormExample.java
index 55e61e3980..02c080e8fd 100644
--- a/tests/testbench/com/vaadin/tests/components/customfield/AddressFormExample.java
+++ b/tests/testbench/com/vaadin/tests/components/customfield/AddressFormExample.java
@@ -4,6 +4,7 @@ import com.vaadin.tests.components.TestBase;
import com.vaadin.tests.util.Address;
import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickEvent;
+import com.vaadin.ui.Notification;
/**
* Demonstrate a custom field which is a form, and contains another custom field
@@ -23,10 +24,9 @@ public class AddressFormExample extends TestBase {
public void buttonClick(ClickEvent event) {
field.commit();
Address address = field.getValue();
- field.getRoot().showNotification(
- "Address saved: " + address.getStreetAddress() + ", "
- + address.getPostalCode() + ", "
- + address.getCity());
+ Notification.show("Address saved: "
+ + address.getStreetAddress() + ", "
+ + address.getPostalCode() + ", " + address.getCity());
}
});
addComponent(commitButton);
diff --git a/tests/testbench/com/vaadin/tests/components/customfield/BooleanFieldExample.java b/tests/testbench/com/vaadin/tests/components/customfield/BooleanFieldExample.java
index 2f9720a1c1..694c5b54f9 100644
--- a/tests/testbench/com/vaadin/tests/components/customfield/BooleanFieldExample.java
+++ b/tests/testbench/com/vaadin/tests/components/customfield/BooleanFieldExample.java
@@ -10,6 +10,7 @@ import com.vaadin.ui.Component;
import com.vaadin.ui.DefaultFieldFactory;
import com.vaadin.ui.Field;
import com.vaadin.ui.Form;
+import com.vaadin.ui.Notification;
import com.vaadin.ui.VerticalLayout;
public class BooleanFieldExample extends TestBase {
@@ -62,13 +63,10 @@ public class BooleanFieldExample extends TestBase {
Button submit = new Button("Submit", new ClickListener() {
public void buttonClick(ClickEvent event) {
form.commit();
- layout.getRoot()
- .showNotification(
- "The custom boolean field value is "
- + data.isCustom()
- + ".<br>"
- + "The checkbox (default boolean field) value is "
- + data.isNormal() + ".");
+ Notification.show("The custom boolean field value is "
+ + data.isCustom() + ".<br>"
+ + "The checkbox (default boolean field) value is "
+ + data.isNormal() + ".");
}
});
layout.addComponent(submit);
diff --git a/tests/testbench/com/vaadin/tests/components/draganddropwrapper/DragStartModes.html b/tests/testbench/com/vaadin/tests/components/draganddropwrapper/DragStartModes.html
new file mode 100644
index 0000000000..3e7a7cb0a7
--- /dev/null
+++ b/tests/testbench/com/vaadin/tests/components/draganddropwrapper/DragStartModes.html
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head profile="http://selenium-ide.openqa.org/profiles/test-case">
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<link rel="selenium.base" href="" />
+<title>DragStartModes</title>
+</head>
+<body>
+<table cellpadding="1" cellspacing="1" border="1">
+<thead>
+<tr><td rowspan="1" colspan="3">DragStartModes</td></tr>
+</thead><tbody>
+<tr>
+ <td>open</td>
+ <td>/run/com.vaadin.tests.components.draganddropwrapper.DragStartModes?restartApplication</td>
+ <td></td>
+</tr>
+<tr>
+ <td>drag</td>
+ <td>vaadin=runcomvaadintestscomponentsdraganddropwrapperDragStartModes::PID_SlabelCOMPONENT</td>
+ <td>50,10</td>
+</tr>
+<tr>
+ <td>mouseMoveAt</td>
+ <td>vaadin=runcomvaadintestscomponentsdraganddropwrapperDragStartModes::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[4]/VLabel[0]</td>
+ <td>50,10</td>
+</tr>
+<tr>
+ <td>screenCapture</td>
+ <td></td>
+ <td>drag-mode-component</td>
+</tr>
+<tr>
+ <td>drop</td>
+ <td>vaadin=runcomvaadintestscomponentsdraganddropwrapperDragStartModes::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[4]/VLabel[0]</td>
+ <td>50,10</td>
+</tr>
+<tr>
+ <td>drag</td>
+ <td>vaadin=runcomvaadintestscomponentsdraganddropwrapperDragStartModes::PID_SlabelWRAPPER</td>
+ <td>50,10</td>
+</tr>
+<tr>
+ <td>mouseMoveAt</td>
+ <td>vaadin=runcomvaadintestscomponentsdraganddropwrapperDragStartModes::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[4]/VLabel[0]</td>
+ <td>50,10</td>
+</tr>
+<tr>
+ <td>screenCapture</td>
+ <td></td>
+ <td>drag-mode-wrapper</td>
+</tr>
+<tr>
+ <td>drop</td>
+ <td>vaadin=runcomvaadintestscomponentsdraganddropwrapperDragStartModes::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[4]/VLabel[0]</td>
+ <td>50,10</td>
+</tr>
+
+</tbody></table>
+</body>
+</html>
diff --git a/tests/testbench/com/vaadin/tests/components/draganddropwrapper/DragStartModes.java b/tests/testbench/com/vaadin/tests/components/draganddropwrapper/DragStartModes.java
new file mode 100644
index 0000000000..d23c502a45
--- /dev/null
+++ b/tests/testbench/com/vaadin/tests/components/draganddropwrapper/DragStartModes.java
@@ -0,0 +1,46 @@
+package com.vaadin.tests.components.draganddropwrapper;
+
+import com.vaadin.tests.components.TestBase;
+import com.vaadin.tests.util.TestUtils;
+import com.vaadin.ui.Component;
+import com.vaadin.ui.DragAndDropWrapper;
+import com.vaadin.ui.DragAndDropWrapper.DragStartMode;
+import com.vaadin.ui.Label;
+
+public class DragStartModes extends TestBase {
+
+ @Override
+ protected void setup() {
+
+ TestUtils.injectCSS(getMainWindow(),
+ ".v-ddwrapper { background: #ACF; }");
+
+ addComponent(makeWrapper(DragStartMode.NONE));
+ addComponent(makeWrapper(DragStartMode.COMPONENT));
+ addComponent(makeWrapper(DragStartMode.WRAPPER));
+ addComponent(makeWrapper(DragStartMode.HTML5));
+
+ addComponent(new Label("Drop here"));
+ }
+
+ private Component makeWrapper(DragStartMode mode) {
+ Label label = new Label("Drag start mode: " + mode);
+ label.setDebugId("label" + mode);
+ DragAndDropWrapper wrapper = new DragAndDropWrapper(label);
+ wrapper.setHTML5DataFlavor("Text", "HTML5!");
+ wrapper.setDragStartMode(mode);
+ wrapper.setWidth("200px");
+ return wrapper;
+ }
+
+ @Override
+ protected String getDescription() {
+ return "Different drag start modes should show correct drag images";
+ }
+
+ @Override
+ protected Integer getTicketNumber() {
+ return 8949;
+ }
+
+}
diff --git a/tests/testbench/com/vaadin/tests/components/draganddropwrapper/TooltipHandlingWhenNotDefined.html b/tests/testbench/com/vaadin/tests/components/draganddropwrapper/TooltipHandlingWhenNotDefined.html
new file mode 100644
index 0000000000..08dc608787
--- /dev/null
+++ b/tests/testbench/com/vaadin/tests/components/draganddropwrapper/TooltipHandlingWhenNotDefined.html
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head profile="http://selenium-ide.openqa.org/profiles/test-case">
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<link rel="selenium.base" href="" />
+<title>TooltipHandlingWhenNotDefined</title>
+</head>
+<body>
+<table cellpadding="1" cellspacing="1" border="1">
+<thead>
+<tr><td rowspan="1" colspan="3">TooltipHandlingWhenNotDefined</td></tr>
+</thead><tbody>
+<tr>
+ <td>open</td>
+ <td>/run/com.vaadin.tests.components.draganddropwrapper.TooltipHandlingWhenNotDefined?restartApplication</td>
+ <td></td>
+</tr>
+<tr>
+ <td>mouseOver</td>
+ <td>vaadin=runcomvaadintestscomponentsdraganddropwrapperTooltipHandlingWhenNotDefined::PID_StooltipLabel</td>
+ <td></td>
+</tr>
+<tr>
+ <td>pause</td>
+ <td></td>
+ <td>3000</td>
+</tr>
+<tr>
+ <td>screenCapture</td>
+ <td></td>
+ <td>tooltip-shown</td>
+</tr>
+</tbody>
+</table>
+</body>
+</html>
diff --git a/tests/testbench/com/vaadin/tests/components/draganddropwrapper/TooltipHandlingWhenNotDefined.java b/tests/testbench/com/vaadin/tests/components/draganddropwrapper/TooltipHandlingWhenNotDefined.java
new file mode 100644
index 0000000000..0735b3e622
--- /dev/null
+++ b/tests/testbench/com/vaadin/tests/components/draganddropwrapper/TooltipHandlingWhenNotDefined.java
@@ -0,0 +1,41 @@
+package com.vaadin.tests.components.draganddropwrapper;
+
+import com.vaadin.tests.components.TestBase;
+import com.vaadin.ui.CssLayout;
+import com.vaadin.ui.DragAndDropWrapper;
+import com.vaadin.ui.DragAndDropWrapper.DragStartMode;
+import com.vaadin.ui.Label;
+
+public class TooltipHandlingWhenNotDefined extends TestBase {
+
+ @Override
+ protected void setup() {
+
+ CssLayout wrapperLayout = new CssLayout();
+ wrapperLayout.setWidth("100%");
+
+ Label label = new Label("Can I has the tooltip?", Label.CONTENT_XHTML);
+ label.setDebugId("tooltipLabel");
+ label.setDescription("Good! Tooltip works!");
+ label.setSizeUndefined();
+ wrapperLayout.addComponent(label);
+
+ DragAndDropWrapper wrapper = new DragAndDropWrapper(wrapperLayout);
+ wrapper.setWidth("100%");
+ wrapper.setDragStartMode(DragStartMode.WRAPPER);
+
+ addComponent(wrapper);
+
+ }
+
+ @Override
+ protected String getDescription() {
+ return "Wrapper most not prevent child from showing tooltip";
+ }
+
+ @Override
+ protected Integer getTicketNumber() {
+ return 7766;
+ }
+
+}
diff --git a/tests/testbench/com/vaadin/tests/components/formlayout/FormLayoutErrorHover.html b/tests/testbench/com/vaadin/tests/components/formlayout/FormLayoutErrorHover.html
new file mode 100644
index 0000000000..f6fc12af0a
--- /dev/null
+++ b/tests/testbench/com/vaadin/tests/components/formlayout/FormLayoutErrorHover.html
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head profile="http://selenium-ide.openqa.org/profiles/test-case">
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<link rel="selenium.base" href="" />
+<title>PropertyValueChange</title>
+</head>
+<body>
+<table cellpadding="1" cellspacing="1" border="1">
+<thead>
+<tr><td rowspan="1" colspan="3">PropertyValueChange</td></tr>
+</thead><tbody>
+<tr>
+ <td>open</td>
+ <td>/run/com.vaadin.tests.components.formlayout.FormLayoutErrorHover?restartApplication&amp;debug</td>
+ <td></td>
+</tr>
+<tr>
+ <td>enterCharacter</td>
+ <td>vaadin=runcomvaadintestscomponentsformlayoutFormLayoutErrorHover::/VVerticalLayout[0]/VVerticalLayout[0]/VFormLayout[0]/VFormLayout$VFormLayoutTable[0]/VPopupCalendar[0]#field</td>
+ <td>asdf</td>
+</tr>
+<tr>
+ <td>pressSpecialKey</td>
+ <td>vaadin=runcomvaadintestscomponentsformlayoutFormLayoutErrorHover::/VVerticalLayout[0]/VVerticalLayout[0]/VFormLayout[0]/VFormLayout$VFormLayoutTable[0]/VPopupCalendar[0]#field</td>
+ <td>enter</td>
+</tr>
+<!--Hover error indicator-->
+<tr>
+ <td>mouseOver</td>
+ <td>vaadin=runcomvaadintestscomponentsformlayoutFormLayoutErrorHover::/VVerticalLayout[0]/VVerticalLayout[0]/VFormLayout[0]/domChild[0]/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[0]</td>
+ <td></td>
+</tr>
+<tr>
+ <td>pause</td>
+ <td></td>
+ <td>2000</td>
+</tr>
+<tr>
+ <td>assertText</td>
+ <td>vaadin=runcomvaadintestscomponentsformlayoutFormLayoutErrorHover::Root/VTooltip[0]/FlowPanel[0]/VErrorMessage[0]/HTML[0]/domChild[0]</td>
+ <td>Date format not recognized</td>
+</tr>
+</tbody></table>
+</body>
+</html>
diff --git a/tests/testbench/com/vaadin/tests/components/formlayout/FormLayoutErrorHover.java b/tests/testbench/com/vaadin/tests/components/formlayout/FormLayoutErrorHover.java
new file mode 100644
index 0000000000..b65a448830
--- /dev/null
+++ b/tests/testbench/com/vaadin/tests/components/formlayout/FormLayoutErrorHover.java
@@ -0,0 +1,33 @@
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+package com.vaadin.tests.components.formlayout;
+
+import com.vaadin.terminal.WrappedRequest;
+import com.vaadin.tests.components.AbstractTestRoot;
+import com.vaadin.ui.FormLayout;
+import com.vaadin.ui.PopupDateField;
+
+public class FormLayoutErrorHover extends AbstractTestRoot {
+
+ @Override
+ protected void setup(WrappedRequest request) {
+ FormLayout formLayout = new FormLayout();
+ PopupDateField fromDate = new PopupDateField("Date");
+ fromDate.setImmediate(true);
+ formLayout.addComponent(fromDate);
+
+ addComponent(formLayout);
+ }
+
+ @Override
+ protected String getTestDescription() {
+ return "Enter some random text to the date field and press enter. Then hover the error indicator. This should show a message about the error.";
+ }
+
+ @Override
+ protected Integer getTicketNumber() {
+ return Integer.valueOf(8794);
+ }
+
+}
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 100644
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<FormLayout> {
+
+ @Override
+ protected Class getTestClass() {
+ return FormLayout.class;
+ }
+
+}
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<String> propertyIds = new ArrayList<String>();
+ 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<String>(
+ 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);
+ }
+
+}
diff --git a/tests/testbench/com/vaadin/tests/components/javascriptcomponent/BasicJavaScriptComponent.java b/tests/testbench/com/vaadin/tests/components/javascriptcomponent/BasicJavaScriptComponent.java
new file mode 100644
index 0000000000..5f2f945c8b
--- /dev/null
+++ b/tests/testbench/com/vaadin/tests/components/javascriptcomponent/BasicJavaScriptComponent.java
@@ -0,0 +1,81 @@
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+package com.vaadin.tests.components.javascriptcomponent;
+
+import java.util.Arrays;
+import java.util.List;
+
+import com.vaadin.annotations.LoadScripts;
+import com.vaadin.external.json.JSONArray;
+import com.vaadin.external.json.JSONException;
+import com.vaadin.terminal.WrappedRequest;
+import com.vaadin.terminal.gwt.client.communication.ServerRpc;
+import com.vaadin.terminal.gwt.client.ui.JavaScriptComponentState;
+import com.vaadin.tests.components.AbstractTestRoot;
+import com.vaadin.ui.AbstractJavaScriptComponent;
+import com.vaadin.ui.JavaScriptCallback;
+import com.vaadin.ui.Notification;
+
+@LoadScripts({ "/statictestfiles/jsconnector.js" })
+public class BasicJavaScriptComponent extends AbstractTestRoot {
+
+ public interface ExampleClickRpc extends ServerRpc {
+ public void onClick(String message);
+ }
+
+ public static class SpecialState extends JavaScriptComponentState {
+ private List<String> data;
+
+ public List<String> getData() {
+ return data;
+ }
+
+ public void setData(List<String> data) {
+ this.data = data;
+ }
+ }
+
+ public static class ExampleWidget extends AbstractJavaScriptComponent {
+ public ExampleWidget() {
+ registerRpc(new ExampleClickRpc() {
+ public void onClick(String message) {
+ Notification.show("Got a click: " + message);
+ }
+ });
+ registerCallback("onclick", new JavaScriptCallback() {
+ public void call(JSONArray arguments) throws JSONException {
+ Notification.show("Got a callback: "
+ + arguments.getString(0));
+ }
+ });
+ getState().setData(Arrays.asList("a", "b", "c"));
+ }
+
+ @Override
+ public SpecialState getState() {
+ return (SpecialState) super.getState();
+ }
+ }
+
+ @Override
+ protected void setup(WrappedRequest request) {
+ ExampleWidget c = new ExampleWidget();
+ c.setCaption("test caption");
+ c.setDescription("Some description");
+ addComponent(c);
+ }
+
+ @Override
+ protected String getTestDescription() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ protected Integer getTicketNumber() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+}
diff --git a/tests/testbench/com/vaadin/tests/components/notification/Notifications.java b/tests/testbench/com/vaadin/tests/components/notification/Notifications.java
index 27aef918d1..5a158c8f03 100644
--- a/tests/testbench/com/vaadin/tests/components/notification/Notifications.java
+++ b/tests/testbench/com/vaadin/tests/components/notification/Notifications.java
@@ -1,12 +1,12 @@
package com.vaadin.tests.components.notification;
+import com.vaadin.terminal.Page;
import com.vaadin.tests.components.TestBase;
import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.Button.ClickListener;
import com.vaadin.ui.NativeSelect;
import com.vaadin.ui.Notification;
-import com.vaadin.ui.Root;
import com.vaadin.ui.TextArea;
public class Notifications extends TestBase implements ClickListener {
@@ -53,7 +53,6 @@ public class Notifications extends TestBase implements ClickListener {
public void buttonClick(ClickEvent event) {
Notification n = new Notification(tf.getValue(),
(Integer) type.getValue());
- Root.getCurrentRoot().showNotification(n);
-
+ n.show(Page.getCurrent());
}
}
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 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head profile="http://selenium-ide.openqa.org/profiles/test-case">
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<link rel="selenium.base" href="" />
+<title>NotificationsAndModalWindow</title>
+</head>
+<body>
+<table cellpadding="1" cellspacing="1" border="1">
+<thead>
+<tr><td rowspan="1" colspan="3">NotificationsAndModalWindow</td></tr>
+</thead><tbody>
+<tr>
+ <td>open</td>
+ <td>/run/com.vaadin.tests.components.notification.NotificationsAndModalWindow?restartApplication</td>
+ <td></td>
+</tr>
+<tr>
+ <td>click</td>
+ <td>vaadin=runcomvaadintestscomponentsnotificationNotificationsAndModalWindow::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VButton[0]/domChild[0]/domChild[0]</td>
+ <td></td>
+</tr>
+<tr>
+ <td>closeNotification</td>
+ <td>vaadin=runcomvaadintestscomponentsnotificationNotificationsAndModalWindow::Root/VNotification[1]</td>
+ <td>0,0</td>
+</tr>
+<tr>
+ <td>closeNotification</td>
+ <td>vaadin=runcomvaadintestscomponentsnotificationNotificationsAndModalWindow::Root/VNotification[0]</td>
+ <td>0,0</td>
+</tr>
+<tr>
+ <td>assertElementNotPresent</td>
+ <td>vaadin=runcomvaadintestscomponentsnotificationNotificationsAndModalWindow::Root/VNotification[0]</td>
+ <td></td>
+</tr>
+
+</tbody></table>
+</body>
+</html>
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..547ef3077b
--- /dev/null
+++ b/tests/testbench/com/vaadin/tests/components/notification/NotificationsAndModalWindow.java
@@ -0,0 +1,39 @@
+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.Notification;
+import com.vaadin.ui.Window;
+
+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;
+ }
+
+}
diff --git a/tests/testbench/com/vaadin/tests/components/notification/NotificationsHtmlAllowed.java b/tests/testbench/com/vaadin/tests/components/notification/NotificationsHtmlAllowed.java
index 152688d109..8e42db57f3 100644
--- a/tests/testbench/com/vaadin/tests/components/notification/NotificationsHtmlAllowed.java
+++ b/tests/testbench/com/vaadin/tests/components/notification/NotificationsHtmlAllowed.java
@@ -1,12 +1,12 @@
package com.vaadin.tests.components.notification;
+import com.vaadin.terminal.Page;
import com.vaadin.tests.components.TestBase;
import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.Button.ClickListener;
import com.vaadin.ui.CheckBox;
import com.vaadin.ui.Notification;
-import com.vaadin.ui.Root;
import com.vaadin.ui.TextArea;
import com.vaadin.ui.TextField;
@@ -46,15 +46,13 @@ public class NotificationsHtmlAllowed extends TestBase implements ClickListener
public void buttonClick(ClickEvent event) {
Notification n = makeNotification();
- Root.getCurrentRoot().showNotification(n);
-
+ n.show(Page.getCurrent());
}
private Notification makeNotification() {
- Notification n = new Notification((String) captionField.getValue(),
- (String) messageField.getValue(),
- Notification.TYPE_HUMANIZED_MESSAGE,
- (Boolean) htmlAllowedBox.getValue());
+ Notification n = new Notification(captionField.getValue(),
+ messageField.getValue(), Notification.TYPE_HUMANIZED_MESSAGE,
+ htmlAllowedBox.getValue());
return n;
}
}
diff --git a/tests/testbench/com/vaadin/tests/components/orderedlayout/LayoutClickListenerTest.html b/tests/testbench/com/vaadin/tests/components/orderedlayout/LayoutClickListenerTest.html
index ea0a039dbe..f0fd1568b1 100644
--- a/tests/testbench/com/vaadin/tests/components/orderedlayout/LayoutClickListenerTest.html
+++ b/tests/testbench/com/vaadin/tests/components/orderedlayout/LayoutClickListenerTest.html
@@ -3,7 +3,7 @@
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head profile="http://selenium-ide.openqa.org/profiles/test-case">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
-<link rel="selenium.base" href="" />
+<link rel="selenium.base" href="http://localhost:8070" />
<title>LayoutClickListenerTest</title>
</head>
<body>
@@ -19,67 +19,67 @@
<tr>
<td>mouseClick</td>
<td>vaadin=runcomvaadintestscomponentsorderedlayoutLayoutClickListenerTest::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VGridLayout[0]/AbsolutePanel[0]/ChildComponentContainer[0]/VTextField[0]</td>
- <td></td>
+ <td>5,5</td>
</tr>
<tr>
<td>mouseClick</td>
<td>vaadin=runcomvaadintestscomponentsorderedlayoutLayoutClickListenerTest::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VGridLayout[0]/AbsolutePanel[0]/ChildComponentContainer[1]/VLink[0]/domChild[0]/domChild[0]</td>
- <td></td>
+ <td>5,5</td>
</tr>
<tr>
<td>mouseClick</td>
<td>vaadin=runcomvaadintestscomponentsorderedlayoutLayoutClickListenerTest::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VGridLayout[0]/AbsolutePanel[0]/ChildComponentContainer[2]/VFilterSelect[0]/domChild[0]</td>
- <td></td>
+ <td>5,5</td>
</tr>
<tr>
<td>mouseClick</td>
<td>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]</td>
- <td></td>
+ <td>5,5</td>
</tr>
<tr>
<td>mouseClick</td>
<td>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]</td>
- <td></td>
+ <td>5,5</td>
</tr>
<tr>
<td>mouseClick</td>
<td>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]</td>
- <td></td>
+ <td>5,5</td>
</tr>
<tr>
<td>mouseClick</td>
<td>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]</td>
- <td></td>
+ <td>5,5</td>
</tr>
<tr>
<td>mouseClick</td>
- <td>vaadin=runcomvaadintestscomponentsorderedlayoutLayoutClickListenerTest::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VGridLayout[0]/AbsolutePanel[0]/ChildComponentContainer[3]/VTabsheet[0]/VTabsheetPanel[0]/VVerticalLayout[0]/domChild[1]</td>
- <td></td>
+ <td>vaadin=runcomvaadintestscomponentsorderedlayoutLayoutClickListenerTest::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VGridLayout[0]/AbsolutePanel[0]/ChildComponentContainer[3]/VTabsheet[0]/VTabsheetPanel[0]/VVerticalLayout[0]</td>
+ <td>396,87</td>
</tr>
<tr>
<td>mouseClick</td>
<td>vaadin=runcomvaadintestscomponentsorderedlayoutLayoutClickListenerTest::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VGridLayout[0]/AbsolutePanel[0]/ChildComponentContainer[4]/VVerticalLayout[0]/ChildComponentContainer[0]/VLabel[0]</td>
- <td></td>
+ <td>5,5</td>
</tr>
<tr>
<td>mouseClick</td>
<td>vaadin=runcomvaadintestscomponentsorderedlayoutLayoutClickListenerTest::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VGridLayout[0]/AbsolutePanel[0]/ChildComponentContainer[4]/VVerticalLayout[0]/ChildComponentContainer[1]/VTextField[0]</td>
- <td></td>
+ <td>5,5</td>
</tr>
<tr>
<td>mouseClick</td>
<td>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]</td>
- <td></td>
+ <td>5,5</td>
</tr>
<tr>
<td>mouseClick</td>
<td>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]</td>
- <td></td>
+ <td>5,5</td>
</tr>
<tr>
<td>mouseClick</td>
- <td>vaadin=runcomvaadintestscomponentsorderedlayoutLayoutClickListenerTest::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VGridLayout[0]/domChild[0]</td>
- <td></td>
+ <td>vaadin=runcomvaadintestscomponentsorderedlayoutLayoutClickListenerTest::/VVerticalLayout[0]/VVerticalLayout[0]/VGridLayout[0]</td>
+ <td>1135,146</td>
</tr>
<tr>
<td>screenCapture</td>
diff --git a/tests/testbench/com/vaadin/tests/components/panel/PanelChangeContents.html b/tests/testbench/com/vaadin/tests/components/panel/PanelChangeContents.html
new file mode 100644
index 0000000000..bff19c4846
--- /dev/null
+++ b/tests/testbench/com/vaadin/tests/components/panel/PanelChangeContents.html
@@ -0,0 +1,77 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head profile="http://selenium-ide.openqa.org/profiles/test-case">
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<link rel="selenium.base" href="" />
+<title>New Test</title>
+</head>
+<body>
+<table cellpadding="1" cellspacing="1" border="1">
+<thead>
+<tr><td rowspan="1" colspan="3">New Test</td></tr>
+</thead><tbody>
+<tr>
+ <td>open</td>
+ <td>/run/com.vaadin.tests.components.panel.PanelChangeContents?restartApplication</td>
+ <td></td>
+</tr>
+<tr>
+ <td>assertText</td>
+ <td>vaadin=runcomvaadintestscomponentspanelPanelChangeContents::/VVerticalLayout[0]/VPanel[0]/VVerticalLayout[0]/VLabel[0]</td>
+ <td>stats</td>
+</tr>
+<tr>
+ <td>click</td>
+ <td>vaadin=runcomvaadintestscomponentspanelPanelChangeContents::/VVerticalLayout[0]/VHorizontalLayout[0]/VButton[1]/domChild[0]/domChild[0]</td>
+ <td></td>
+</tr>
+<tr>
+ <td>assertText</td>
+ <td>vaadin=runcomvaadintestscomponentspanelPanelChangeContents::/VVerticalLayout[0]/VPanel[0]/VVerticalLayout[0]/VLabel[0]</td>
+ <td>companies</td>
+</tr>
+<tr>
+ <td>click</td>
+ <td>vaadin=runcomvaadintestscomponentspanelPanelChangeContents::/VVerticalLayout[0]/VHorizontalLayout[0]/VButton[2]/domChild[0]/domChild[0]</td>
+ <td></td>
+</tr>
+<tr>
+ <td>assertText</td>
+ <td>vaadin=runcomvaadintestscomponentspanelPanelChangeContents::/VVerticalLayout[0]/VPanel[0]/VVerticalLayout[0]/VLabel[0]</td>
+ <td>settings</td>
+</tr>
+<tr>
+ <td>click</td>
+ <td>vaadin=runcomvaadintestscomponentspanelPanelChangeContents::/VVerticalLayout[0]/VHorizontalLayout[0]/VButton[0]/domChild[0]</td>
+ <td></td>
+</tr>
+<tr>
+ <td>assertText</td>
+ <td>vaadin=runcomvaadintestscomponentspanelPanelChangeContents::/VVerticalLayout[0]/VPanel[0]/VVerticalLayout[0]/VLabel[0]</td>
+ <td>stats</td>
+</tr>
+<tr>
+ <td>click</td>
+ <td>vaadin=runcomvaadintestscomponentspanelPanelChangeContents::/VVerticalLayout[0]/VHorizontalLayout[0]/VButton[1]/domChild[0]/domChild[0]</td>
+ <td></td>
+</tr>
+<tr>
+ <td>assertText</td>
+ <td>vaadin=runcomvaadintestscomponentspanelPanelChangeContents::/VVerticalLayout[0]/VPanel[0]/VVerticalLayout[0]/VLabel[0]</td>
+ <td>companies</td>
+</tr>
+<tr>
+ <td>click</td>
+ <td>vaadin=runcomvaadintestscomponentspanelPanelChangeContents::/VVerticalLayout[0]/VHorizontalLayout[0]/VButton[2]/domChild[0]/domChild[0]</td>
+ <td></td>
+</tr>
+<tr>
+ <td>assertText</td>
+ <td>vaadin=runcomvaadintestscomponentspanelPanelChangeContents::/VVerticalLayout[0]/VPanel[0]/VVerticalLayout[0]/VLabel[0]</td>
+ <td>settings</td>
+</tr>
+
+</tbody></table>
+</body>
+</html>
diff --git a/tests/testbench/com/vaadin/tests/components/panel/PanelChangeContents.java b/tests/testbench/com/vaadin/tests/components/panel/PanelChangeContents.java
new file mode 100644
index 0000000000..4859b22932
--- /dev/null
+++ b/tests/testbench/com/vaadin/tests/components/panel/PanelChangeContents.java
@@ -0,0 +1,73 @@
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+package com.vaadin.tests.components.panel;
+
+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.Button.ClickListener;
+import com.vaadin.ui.HorizontalLayout;
+import com.vaadin.ui.Label;
+import com.vaadin.ui.Panel;
+import com.vaadin.ui.VerticalLayout;
+
+public class PanelChangeContents extends AbstractTestRoot implements
+ ClickListener {
+
+ VerticalLayout stats = new VerticalLayout();
+ VerticalLayout companies = new VerticalLayout();
+ VerticalLayout settings = new VerticalLayout();
+
+ Button statsButton = new Button("Stats", this);
+ Button companiesButton = new Button("Companies", this);
+ Button settingsButton = new Button("Settings", this);
+
+ private Panel panel;
+
+ @Override
+ protected void setup(WrappedRequest request) {
+ VerticalLayout content = new VerticalLayout();
+ setSizeFull();
+ HorizontalLayout buttons = new HorizontalLayout();
+ stats.addComponent(new Label("stats"));
+ companies.addComponent(new Label("companies"));
+ settings.addComponent(new Label("settings"));
+ buttons.addComponent(statsButton);
+ buttons.addComponent(companiesButton);
+ buttons.addComponent(settingsButton);
+ panel = new Panel();
+ panel.setSizeFull();
+ panel.setContent(stats);
+ content.addComponent(buttons);
+ content.addComponent(panel);
+ content.setMargin(true);
+ content.setSpacing(true);
+ content.setExpandRatio(panel, 1);
+ setContent(content);
+ }
+
+ public void buttonClick(ClickEvent event) {
+ if (event.getButton() == statsButton) {
+ panel.setContent(stats);
+ } else if (event.getButton() == companiesButton) {
+ panel.setContent(companies);
+ } else if (event.getButton() == settingsButton) {
+ panel.setContent(settings);
+ }
+
+ }
+
+ @Override
+ protected String getTestDescription() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ protected Integer getTicketNumber() {
+ return 8735;
+ }
+
+}
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 @@
</tr>
<tr>
<td>mouseClick</td>
- <td>vaadin=runcomvaadintestscomponentspanelPanelClickListenerRelativeCoordinates::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VPanel[0]</td>
- <td>287,25</td>
+ <td>vaadin=runcomvaadintestscomponentspanelPanelClickListenerRelativeCoordinates::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VPanel[0]/VVerticalLayout[0]</td>
+ <td>287,6</td>
</tr>
-<!-- Should really be 287, 25 but due to v-view border-top it is not always... <tr>
+<!-- Should really be 287, 25 but due to v-view border-top it is not always... Additional differences caused by targeting the click on the child element to make it behave like a real click (#4120)<tr>
<td>assertText</td>
<td>vaadin=runcomvaadintestscomponentspanelPanelClickListenerRelativeCoordinates::Root/VNotification[0]/HTML[0]/domChild[0]</td>
<td>287, 25</td>
diff --git a/tests/testbench/com/vaadin/tests/components/richtextarea/RichTextAreaWithKeyboardShortcuts.java b/tests/testbench/com/vaadin/tests/components/richtextarea/RichTextAreaWithKeyboardShortcuts.java
index 95691ef9d7..98f31cd68c 100644
--- a/tests/testbench/com/vaadin/tests/components/richtextarea/RichTextAreaWithKeyboardShortcuts.java
+++ b/tests/testbench/com/vaadin/tests/components/richtextarea/RichTextAreaWithKeyboardShortcuts.java
@@ -6,6 +6,7 @@ import com.vaadin.event.ShortcutAction;
import com.vaadin.tests.components.TestBase;
import com.vaadin.ui.AbstractField;
import com.vaadin.ui.Component;
+import com.vaadin.ui.Notification;
import com.vaadin.ui.Panel;
import com.vaadin.ui.RichTextArea;
import com.vaadin.ui.Window;
@@ -30,7 +31,7 @@ public class RichTextAreaWithKeyboardShortcuts extends TestBase {
String string = f.getValue().toString();
msg += " Value: " + string;
- f.getRoot().showNotification(msg);
+ Notification.show(msg);
}
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..c91d742581
--- /dev/null
+++ b/tests/testbench/com/vaadin/tests/components/root/TestRootWidgetset.html
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head profile="http://selenium-ide.openqa.org/profiles/test-case">
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<link rel="selenium.base" href="" />
+<title>Ticket4607</title>
+</head>
+<body>
+<table cellpadding="1" cellspacing="1" border="1">
+<thead>
+<tr><td rowspan="1" colspan="3">Ticket4607</td></tr>
+</thead><tbody>
+<tr>
+ <td>open</td>
+ <td>/run/com.vaadin.tests.components.root.TestRootWidgetset</td>
+ <td></td>
+</tr>
+<tr>
+ <td>assertText</td>
+ <td>vaadin=runcomvaadintestscomponentsrootTestRootWidgetset::/VVerticalLayout[0]/VVerticalLayout[0]/VLabel[0]</td>
+ <td>This component is available in TestingWidgetset, but not in DefaultWidgetset</td>
+</tr>
+<tr>
+ <td>open</td>
+ <td>/run/com.vaadin.tests.components.root.TestRootWidgetset2</td>
+ <td></td>
+</tr>
+<tr>
+ <td>assertText</td>
+ <td>vaadin=runcomvaadintestscomponentsrootTestRootWidgetset2::/VVerticalLayout[0]/VVerticalLayout[0]/VUnknownComponent[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]</td>
+ <td>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.</td>
+</tr>
+</tbody></table>
+</body>
+</html>
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/components/root/UriFragmentTest.java b/tests/testbench/com/vaadin/tests/components/root/UriFragmentTest.java
index 6078161996..251672fb9a 100644
--- a/tests/testbench/com/vaadin/tests/components/root/UriFragmentTest.java
+++ b/tests/testbench/com/vaadin/tests/components/root/UriFragmentTest.java
@@ -1,5 +1,7 @@
package com.vaadin.tests.components.root;
+import com.vaadin.terminal.Page;
+import com.vaadin.terminal.Page.FragmentChangedEvent;
import com.vaadin.terminal.WrappedRequest;
import com.vaadin.tests.components.AbstractTestRoot;
import com.vaadin.ui.Button;
@@ -14,7 +16,7 @@ public class UriFragmentTest extends AbstractTestRoot {
protected void setup(WrappedRequest request) {
addComponent(fragmentLabel);
updateLabel();
- addListener(new FragmentChangedListener() {
+ getPage().addListener(new Page.FragmentChangedListener() {
public void fragmentChanged(FragmentChangedEvent event) {
updateLabel();
}
@@ -22,13 +24,13 @@ public class UriFragmentTest extends AbstractTestRoot {
addComponent(new Button("Navigate to #test",
new Button.ClickListener() {
public void buttonClick(ClickEvent event) {
- setFragment("test");
+ getPage().setFragment("test");
}
}));
}
private void updateLabel() {
- String fragment = getFragment();
+ String fragment = getPage().getFragment();
if (fragment == null) {
fragmentLabel.setValue("No URI fragment set");
} else {
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 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head profile="http://selenium-ide.openqa.org/profiles/test-case">
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<link rel="selenium.base" href="" />
+<title>StylingPopupOpener</title>
+</head>
+<body>
+<table cellpadding="1" cellspacing="1" border="1">
+<thead>
+<tr><td rowspan="1" colspan="3">StylingPopupOpener</td></tr>
+</thead><tbody>
+<tr>
+ <td>open</td>
+ <td>/run/com.vaadin.tests.components.select.StylingPopupOpener?restartApplication</td>
+ <td></td>
+</tr>
+<tr>
+ <td>click</td>
+ <td>vaadin=runcomvaadintestscomponentsselectStylingPopupOpener::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[1]/VButton[0]/domChild[0]/domChild[0]</td>
+ <td></td>
+</tr>
+<tr>
+ <td>screenCapture</td>
+ <td></td>
+ <td></td>
+</tr>
+
+</tbody></table>
+</body>
+</html>
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;
+ }
+
+}
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 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head profile="http://selenium-ide.openqa.org/profiles/test-case">
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<link rel="selenium.base" href="" />
+<title>SliderOrientation</title>
+</head>
+<body>
+<table cellpadding="1" cellspacing="1" border="1">
+<thead>
+<tr><td rowspan="1" colspan="3">SliderOrientation</td></tr>
+</thead><tbody>
+<tr>
+ <td>open</td>
+ <td>/run/com.vaadin.tests.components.slider.SliderTest?restartApplication</td>
+ <td></td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentssliderSliderTest::PID_Smenu#item0</td>
+ <td>5,6</td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentssliderSliderTest::Root/VOverlay[0]/VMenuBar[0]#item4</td>
+ <td>41,7</td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentssliderSliderTest::Root/VOverlay[1]/VMenuBar[0]#item3</td>
+ <td>37,3</td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentssliderSliderTest::Root/VOverlay[2]/VMenuBar[0]#item1</td>
+ <td>19,7</td>
+</tr>
+<tr>
+ <td>screenCapture</td>
+ <td></td>
+ <td>change-orientation-to-vertical</td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentssliderSliderTest::PID_Smenu#item0</td>
+ <td>33,1</td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentssliderSliderTest::Root/VOverlay[0]/VMenuBar[0]#item4</td>
+ <td>63,11</td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentssliderSliderTest::Root/VOverlay[1]/VMenuBar[0]#item3</td>
+ <td>30,1</td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentssliderSliderTest::Root/VOverlay[2]/VMenuBar[0]#item0</td>
+ <td>10,10</td>
+</tr>
+<tr>
+ <td>screenCapture</td>
+ <td></td>
+ <td>change-orientation-to-horizontal</td>
+</tr>
+
+</tbody></table>
+</body>
+</html>
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 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head profile="http://selenium-ide.openqa.org/profiles/test-case">
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<link rel="selenium.base" href="http://arturwin.office.itmill.com:9999/" />
+<title>New Test</title>
+</head>
+<body>
+<table cellpadding="1" cellspacing="1" border="1">
+<thead>
+<tr><td rowspan="1" colspan="3">New Test</td></tr>
+</thead><tbody>
+<tr>
+ <td>open</td>
+ <td>/run/com.vaadin.tests.components.slider.SliderTest?debug&amp;restartApplication</td>
+ <td></td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentssliderSliderTest::PID_Smenu#item0</td>
+ <td>24,2</td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentssliderSliderTest::Root/VOverlay[0]/VMenuBar[0]#item1</td>
+ <td>35,12</td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentssliderSliderTest::Root/VOverlay[1]/VMenuBar[0]#item1</td>
+ <td>74,3</td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentssliderSliderTest::Root/VOverlay[2]/VMenuBar[0]#item2</td>
+ <td>30,6</td>
+</tr>
+<tr>
+ <td>showTooltip</td>
+ <td>vaadin=runcomvaadintestscomponentssliderSliderTest::PID_StestComponent/domChild[2]/domChild[0]</td>
+ <td>0,0</td>
+</tr>
+<tr>
+ <td>waitForElementPresent</td>
+ <td>vaadin=runcomvaadintestscomponentssliderSliderTest::Root/VTooltip[0]/FlowPanel[0]/domChild[1]</td>
+ <td></td>
+</tr>
+<tr>
+ <td>assertText</td>
+ <td>vaadin=runcomvaadintestscomponentssliderSliderTest::Root/VTooltip[0]/FlowPanel[0]/domChild[1]</td>
+ <td>This is a semi-long text that might wrap.</td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentssliderSliderTest::/VVerticalLayout[0]/ChildComponentContainer[0]/VLabel[0]</td>
+ <td>40,16</td>
+</tr>
+<tr>
+ <td>waitForElementNotPresent</td>
+ <td>vaadin=runcomvaadintestscomponentssliderSliderTest::Root/VTooltip[0]/FlowPanel[0]/domChild[1]</td>
+ <td></td>
+</tr>
+
+</tbody></table>
+</body>
+</html>
diff --git a/tests/testbench/com/vaadin/tests/components/splitpanel/HorizontalSplitPanelSplitterClick.html b/tests/testbench/com/vaadin/tests/components/splitpanel/HorizontalSplitPanelSplitterClick.html
index e8be62015f..d91b3d8c4a 100644
--- a/tests/testbench/com/vaadin/tests/components/splitpanel/HorizontalSplitPanelSplitterClick.html
+++ b/tests/testbench/com/vaadin/tests/components/splitpanel/HorizontalSplitPanelSplitterClick.html
@@ -78,18 +78,19 @@
<tr>
<td>mouseClick</td>
<td>vaadin=runcomvaadintestscomponentssplitpanelHorizontalSplitPanels::PID_StestComponent/domChild[0]/domChild[2]/domChild[0]</td>
- <td>10,15</td>
+ <td>5,5</td>
</tr>
<tr>
<td>assertText</td>
<td>vaadin=runcomvaadintestscomponentssplitpanelHorizontalSplitPanels::PID_SLog_row_0</td>
- <td>3. SplitterClickEvent: left at 10,15</td>
+ <td>3. SplitterClickEvent: left at 5,5</td>
</tr>
<tr>
<td>screenCapture</td>
<td></td>
<td>reverseSplitterClicked</td>
</tr>
+
</tbody></table>
</body>
</html>
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..70d619edac
--- /dev/null
+++ b/tests/testbench/com/vaadin/tests/components/splitpanel/SplitPanelWithMinimumAndMaximum.html
@@ -0,0 +1,262 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head profile="http://selenium-ide.openqa.org/profiles/test-case">
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<link rel="selenium.base" href="" />
+<title>SplitPanelWithMinimumAndMaximum</title>
+</head>
+<body>
+<table cellpadding="1" cellspacing="1" border="1">
+<thead>
+<tr><td rowspan="1" colspan="3">SplitPanelWithMinimumAndMaximum</td></tr>
+</thead><tbody>
+<tr>
+ <td>open</td>
+ <td>/run/com.vaadin.tests.components.splitpanel.SplitPanelWithMinimumAndMaximum?restartApplication</td>
+ <td></td>
+</tr>
+<tr>
+ <td>dragAndDrop</td>
+ <td>vaadin=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]</td>
+ <td>-239,0</td>
+</tr>
+<tr>
+ <td>dragAndDrop</td>
+ <td>vaadin=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]</td>
+ <td>-340,0</td>
+</tr>
+<tr>
+ <td>dragAndDrop</td>
+ <td>vaadin=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]</td>
+ <td>-300,0</td>
+</tr>
+<tr>
+ <td>dragAndDrop</td>
+ <td>vaadin=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]</td>
+ <td>-79,0</td>
+</tr>
+<tr>
+ <td>dragAndDrop</td>
+ <td>vaadin=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]</td>
+ <td>-179,0</td>
+</tr>
+<tr>
+ <td>dragAndDrop</td>
+ <td>vaadin=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]</td>
+ <td>-78,0</td>
+</tr>
+<tr>
+ <td>dragAndDrop</td>
+ <td>vaadin=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]</td>
+ <td>-150,0</td>
+</tr>
+<tr>
+ <td>dragAndDrop</td>
+ <td>vaadin=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]</td>
+ <td>-371,0</td>
+</tr>
+<tr>
+ <td>screenCapture</td>
+ <td></td>
+ <td>horizontal-splits-left</td>
+</tr>
+<tr>
+ <td>dragAndDrop</td>
+ <td>vaadin=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]</td>
+ <td>418,0</td>
+</tr>
+<tr>
+ <td>dragAndDrop</td>
+ <td>vaadin=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]</td>
+ <td>418,0</td>
+</tr>
+<tr>
+ <td>dragAndDrop</td>
+ <td>vaadin=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]</td>
+ <td>450,0</td>
+</tr>
+<tr>
+ <td>dragAndDrop</td>
+ <td>vaadin=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]</td>
+ <td>450,0</td>
+</tr>
+<tr>
+ <td>dragAndDrop</td>
+ <td>vaadin=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]</td>
+ <td>418,0</td>
+</tr>
+<tr>
+ <td>dragAndDrop</td>
+ <td>vaadin=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]</td>
+ <td>418,0</td>
+</tr>
+<tr>
+ <td>dragAndDrop</td>
+ <td>vaadin=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]</td>
+ <td>450,0</td>
+</tr>
+<tr>
+ <td>dragAndDrop</td>
+ <td>vaadin=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]</td>
+ <td>450,0</td>
+</tr>
+<tr>
+ <td>screenCapture</td>
+ <td></td>
+ <td>horizontal-splits-right</td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=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]</td>
+ <td>44,2</td>
+</tr>
+<tr>
+ <td>dragAndDrop</td>
+ <td>vaadin=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]</td>
+ <td>0,-206</td>
+</tr>
+<tr>
+ <td>dragAndDrop</td>
+ <td>vaadin=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]</td>
+ <td>0,-348</td>
+</tr>
+<tr>
+ <td>dragAndDrop</td>
+ <td>vaadin=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]</td>
+ <td>0,-300</td>
+</tr>
+<tr>
+ <td>dragAndDrop</td>
+ <td>vaadin=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]</td>
+ <td>0,-55</td>
+</tr>
+<tr>
+ <td>dragAndDrop</td>
+ <td>vaadin=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]</td>
+ <td>0,-155</td>
+</tr>
+<tr>
+ <td>dragAndDrop</td>
+ <td>vaadin=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]</td>
+ <td>0,-13</td>
+</tr>
+<tr>
+ <td>dragAndDrop</td>
+ <td>vaadin=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]</td>
+ <td>0,-300</td>
+</tr>
+<tr>
+ <td>dragAndDrop</td>
+ <td>vaadin=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]</td>
+ <td>0,-300</td>
+</tr>
+<tr>
+ <td>screenCapture</td>
+ <td></td>
+ <td>vertical-splits-up</td>
+</tr>
+<tr>
+ <td>dragAndDrop</td>
+ <td>vaadin=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]</td>
+ <td>0,361</td>
+</tr>
+<tr>
+ <td>dragAndDrop</td>
+ <td>vaadin=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]</td>
+ <td>0,361</td>
+</tr>
+<tr>
+ <td>dragAndDrop</td>
+ <td>vaadin=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]</td>
+ <td>0,350</td>
+</tr>
+<tr>
+ <td>dragAndDrop</td>
+ <td>vaadin=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]</td>
+ <td>0,350</td>
+</tr>
+<tr>
+ <td>dragAndDrop</td>
+ <td>vaadin=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]</td>
+ <td>0,361</td>
+</tr>
+<tr>
+ <td>dragAndDrop</td>
+ <td>vaadin=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]</td>
+ <td>0,361</td>
+</tr>
+<tr>
+ <td>dragAndDrop</td>
+ <td>vaadin=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]</td>
+ <td>0,300</td>
+</tr>
+<tr>
+ <td>dragAndDrop</td>
+ <td>vaadin=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]</td>
+ <td>0,300</td>
+</tr>
+<tr>
+ <td>screenCapture</td>
+ <td></td>
+ <td>vertical-splits-down</td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>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]</td>
+ <td>25,5</td>
+</tr>
+<tr>
+ <td>dragAndDrop</td>
+ <td>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]</td>
+ <td>-239,0</td>
+</tr>
+<tr>
+ <td>screenCapture</td>
+ <td></td>
+ <td>togglable-to-min-with-limit-enabled</td>
+</tr>
+<tr>
+ <td>click</td>
+ <td>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]</td>
+ <td></td>
+</tr>
+<tr>
+ <td>dragAndDrop</td>
+ <td>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]</td>
+ <td>-60,0</td>
+</tr>
+<tr>
+ <td>screenCapture</td>
+ <td></td>
+ <td>togglable-to-min-with-limit-disabled</td>
+</tr>
+<tr>
+ <td>dragAndDrop</td>
+ <td>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]</td>
+ <td>478,0</td>
+</tr>
+<tr>
+ <td>screenCapture</td>
+ <td></td>
+ <td>togglable-to-max-with-limit-enabled</td>
+</tr>
+<tr>
+ <td>click</td>
+ <td>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]</td>
+ <td></td>
+</tr>
+<tr>
+ <td>dragAndDrop</td>
+ <td>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]</td>
+ <td>113,0</td>
+</tr>
+<tr>
+ <td>screenCapture</td>
+ <td></td>
+ <td>togglable-to-max-with-limit-disabled</td>
+</tr>
+
+</tbody></table>
+</body>
+</html>
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..f7c3dd84e4
--- /dev/null
+++ b/tests/testbench/com/vaadin/tests/components/splitpanel/SplitPanelWithMinimumAndMaximum.java
@@ -0,0 +1,332 @@
+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;
+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.setMinSplitPosition(
+ 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.setMinSplitPosition(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.setMinSplitPosition(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.setMinSplitPosition(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
+ .setMinSplitPosition(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
+ .setMinSplitPosition(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.setMinSplitPosition(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
+ .setMinSplitPosition(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.setMinSplitPosition(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.setMinSplitPosition(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.setMinSplitPosition(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.setMinSplitPosition(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
+ .setMinSplitPosition(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.setMinSplitPosition(
+ 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.setMinSplitPosition(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.setMinSplitPosition(
+ 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();
+
+ 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");
+ 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;
+ }
+}
diff --git a/tests/testbench/com/vaadin/tests/components/splitpanel/VerticalSplitPanelSplitterClick.html b/tests/testbench/com/vaadin/tests/components/splitpanel/VerticalSplitPanelSplitterClick.html
index d8a101b0a5..cc384b6de6 100644
--- a/tests/testbench/com/vaadin/tests/components/splitpanel/VerticalSplitPanelSplitterClick.html
+++ b/tests/testbench/com/vaadin/tests/components/splitpanel/VerticalSplitPanelSplitterClick.html
@@ -78,18 +78,19 @@
<tr>
<td>mouseClick</td>
<td>vaadin=runcomvaadintestscomponentssplitpanelVerticalSplitPanels::PID_StestComponent/domChild[0]/domChild[2]/domChild[0]</td>
- <td>12,13</td>
+ <td>5,5</td>
</tr>
<tr>
<td>assertText</td>
<td>vaadin=runcomvaadintestscomponentssplitpanelVerticalSplitPanels::PID_SLog_row_0</td>
- <td>3. SplitterClickEvent: left at 12,13</td>
+ <td>3. SplitterClickEvent: left at 5,5</td>
</tr>
<tr>
<td>screenCapture</td>
<td></td>
<td>reverseSplitterClicked</td>
</tr>
+
</tbody></table>
</body>
</html>
diff --git a/tests/testbench/com/vaadin/tests/components/table/HeaderClick.java b/tests/testbench/com/vaadin/tests/components/table/HeaderClick.java
index 970618374e..d5debcfe16 100644
--- a/tests/testbench/com/vaadin/tests/components/table/HeaderClick.java
+++ b/tests/testbench/com/vaadin/tests/components/table/HeaderClick.java
@@ -45,7 +45,7 @@ public class HeaderClick extends TestBase {
CheckBox sortEnabledCheckbox = new CheckBox("Sortable");
sortEnabledCheckbox.setImmediate(true);
- sortEnabledCheckbox.setValue(!table.isSortDisabled());
+ sortEnabledCheckbox.setValue(table.isSortEnabled());
sortEnabledCheckbox.addListener(new Property.ValueChangeListener() {
public void valueChange(ValueChangeEvent event) {
diff --git a/tests/testbench/com/vaadin/tests/components/table/HeaderFooterClickLeftRightMiddle.java b/tests/testbench/com/vaadin/tests/components/table/HeaderFooterClickLeftRightMiddle.java
index 091891043f..cd54e21395 100644
--- a/tests/testbench/com/vaadin/tests/components/table/HeaderFooterClickLeftRightMiddle.java
+++ b/tests/testbench/com/vaadin/tests/components/table/HeaderFooterClickLeftRightMiddle.java
@@ -93,10 +93,10 @@ public class HeaderFooterClickLeftRightMiddle extends TestBase {
CheckBox sortEnabledCheckbox = new CheckBox("Sortable");
sortEnabledCheckbox.setImmediate(true);
- sortEnabledCheckbox.setValue(!table.isSortDisabled());
+ sortEnabledCheckbox.setValue(table.isSortEnabled());
sortEnabledCheckbox.addListener(new ValueChangeListener() {
public void valueChange(ValueChangeEvent event) {
- table.setSortDisabled(!(Boolean) event.getProperty().getValue());
+ table.setSortEnabled((Boolean) event.getProperty().getValue());
}
});
diff --git a/tests/testbench/com/vaadin/tests/components/table/MultiSelectWithNotIdentityEqualIds.java b/tests/testbench/com/vaadin/tests/components/table/MultiSelectWithNotIdentityEqualIds.java
index 9178b284f3..6773f0a96c 100644
--- a/tests/testbench/com/vaadin/tests/components/table/MultiSelectWithNotIdentityEqualIds.java
+++ b/tests/testbench/com/vaadin/tests/components/table/MultiSelectWithNotIdentityEqualIds.java
@@ -5,6 +5,7 @@ import com.vaadin.data.Property;
import com.vaadin.data.Property.ValueChangeEvent;
import com.vaadin.data.util.IndexedContainer;
import com.vaadin.tests.components.TestBase;
+import com.vaadin.ui.Notification;
import com.vaadin.ui.Table;
@SuppressWarnings("serial")
@@ -20,8 +21,7 @@ public class MultiSelectWithNotIdentityEqualIds extends TestBase {
t.setImmediate(true);
t.addListener(new Property.ValueChangeListener() {
public void valueChange(ValueChangeEvent event) {
- t.getRoot()
- .showNotification("Selected: " + event.getProperty());
+ Notification.show("Selected: " + event.getProperty());
}
});
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
@@ -22,6 +22,11 @@
<td>10,10</td>
</tr>
<tr>
+ <td>pause</td>
+ <td>1000</td>
+ <td></td>
+</tr>
+<tr>
<td>assertText</td>
<td>vaadin=runRowUpdateShouldRetainContextMenu::Root/VContextMenu[0]#option0</td>
<td>Action 1</td>
diff --git a/tests/testbench/com/vaadin/tests/components/table/ScrollCausesRequestLoop.java b/tests/testbench/com/vaadin/tests/components/table/ScrollCausesRequestLoop.java
index c140e7e412..75468af247 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.Root.LegacyWindow;
import com.vaadin.ui.Table;
-public class ScrollCausesRequestLoop extends TestBase {
+public class ScrollCausesRequestLoop extends AbstractTestCase {
@Override
- protected void setup() {
+ public void init() {
setMainWindow(new LegacyWindow("", 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 3b0234d805..44367d0fe1 100644
--- a/tests/testbench/com/vaadin/tests/components/table/ScrollDetachSynchronization.java
+++ b/tests/testbench/com/vaadin/tests/components/table/ScrollDetachSynchronization.java
@@ -46,6 +46,7 @@ public class ScrollDetachSynchronization extends TestBase {
mainLayout.setExpandRatio(firstLayout, 1);
first.addListener(new Button.ClickListener() {
+
public void buttonClick(ClickEvent event) {
if (mainLayout.getComponent(1).equals(secondLayout)) {
mainLayout.replaceComponent(secondLayout, firstLayout);
@@ -54,6 +55,7 @@ public class ScrollDetachSynchronization extends TestBase {
}
});
second.addListener(new Button.ClickListener() {
+
public void buttonClick(ClickEvent event) {
if (mainLayout.getComponent(1).equals(firstLayout)) {
mainLayout.replaceComponent(firstLayout, secondLayout);
diff --git a/tests/testbench/com/vaadin/tests/components/table/SortLabelsInTable.html b/tests/testbench/com/vaadin/tests/components/table/SortLabelsInTable.html
new file mode 100644
index 0000000000..51f13af004
--- /dev/null
+++ b/tests/testbench/com/vaadin/tests/components/table/SortLabelsInTable.html
@@ -0,0 +1,192 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head profile="http://selenium-ide.openqa.org/profiles/test-case">
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<link rel="selenium.base" href="" />
+<title>New Test</title>
+</head>
+<body>
+<table cellpadding="1" cellspacing="1" border="1">
+<thead>
+<tr><td rowspan="1" colspan="3">New Test</td></tr>
+</thead><tbody>
+<tr>
+ <td>open</td>
+ <td>/run/com.vaadin.tests.components.table.SortLabelsInTable?restartApplication</td>
+ <td></td>
+</tr>
+<tr>
+ <td>assertText</td>
+ <td>vaadin=runcomvaadintestscomponentstableSortLabelsInTable::/VVerticalLayout[0]/VVerticalLayout[0]/VScrollTable[0]/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[0]/domChild[0]/domChild[0]</td>
+ <td>Text 0</td>
+</tr>
+<tr>
+ <td>assertText</td>
+ <td>vaadin=runcomvaadintestscomponentstableSortLabelsInTable::/VVerticalLayout[0]/VVerticalLayout[0]/VScrollTable[0]/FocusableScrollPanel[0]/VScrollTable$VScrollTableBody[0]/VScrollTable$VScrollTableBody$VScrollTableRow[0]/VLabel[0]</td>
+ <td>Label 0</td>
+</tr>
+<tr>
+ <td>assertText</td>
+ <td>vaadin=runcomvaadintestscomponentstableSortLabelsInTable::/VVerticalLayout[0]/VVerticalLayout[0]/VScrollTable[0]/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[14]/domChild[0]/domChild[0]</td>
+ <td>Text 14</td>
+</tr>
+<tr>
+ <td>assertText</td>
+ <td>vaadin=runcomvaadintestscomponentstableSortLabelsInTable::/VVerticalLayout[0]/VVerticalLayout[0]/VScrollTable[0]/FocusableScrollPanel[0]/VScrollTable$VScrollTableBody[0]/VScrollTable$VScrollTableBody$VScrollTableRow[14]/VLabel[0]</td>
+ <td>Label 14</td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentstableSortLabelsInTable::/VVerticalLayout[0]/VVerticalLayout[0]/VScrollTable[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]/domChild[2]</td>
+ <td>22,11</td>
+</tr>
+<tr>
+ <td>assertText</td>
+ <td>vaadin=runcomvaadintestscomponentstableSortLabelsInTable::/VVerticalLayout[0]/VVerticalLayout[0]/VScrollTable[0]/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[0]/domChild[0]/domChild[0]</td>
+ <td>Text 0</td>
+</tr>
+<tr>
+ <td>assertText</td>
+ <td>vaadin=runcomvaadintestscomponentstableSortLabelsInTable::/VVerticalLayout[0]/VVerticalLayout[0]/VScrollTable[0]/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[2]/domChild[0]/domChild[0]</td>
+ <td>Text 10</td>
+</tr>
+<tr>
+ <td>assertText</td>
+ <td>vaadin=runcomvaadintestscomponentstableSortLabelsInTable::/VVerticalLayout[0]/VVerticalLayout[0]/VScrollTable[0]/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[14]/domChild[0]/domChild[0]</td>
+ <td>Text 4</td>
+</tr>
+<tr>
+ <td>assertText</td>
+ <td>vaadin=runcomvaadintestscomponentstableSortLabelsInTable::/VVerticalLayout[0]/VVerticalLayout[0]/VScrollTable[0]/FocusableScrollPanel[0]/VScrollTable$VScrollTableBody[0]/VScrollTable$VScrollTableBody$VScrollTableRow[0]/VLabel[0]</td>
+ <td>Label 0</td>
+</tr>
+<tr>
+ <td>assertText</td>
+ <td>vaadin=runcomvaadintestscomponentstableSortLabelsInTable::/VVerticalLayout[0]/VVerticalLayout[0]/VScrollTable[0]/FocusableScrollPanel[0]/VScrollTable$VScrollTableBody[0]/VScrollTable$VScrollTableBody$VScrollTableRow[2]/VLabel[0]</td>
+ <td>Label 10</td>
+</tr>
+<tr>
+ <td>assertText</td>
+ <td>vaadin=runcomvaadintestscomponentstableSortLabelsInTable::/VVerticalLayout[0]/VVerticalLayout[0]/VScrollTable[0]/FocusableScrollPanel[0]/VScrollTable$VScrollTableBody[0]/VScrollTable$VScrollTableBody$VScrollTableRow[11]/VLabel[0]</td>
+ <td>Label 19</td>
+</tr>
+<tr>
+ <td>assertText</td>
+ <td>vaadin=runcomvaadintestscomponentstableSortLabelsInTable::/VVerticalLayout[0]/VVerticalLayout[0]/VScrollTable[0]/FocusableScrollPanel[0]/VScrollTable$VScrollTableBody[0]/VScrollTable$VScrollTableBody$VScrollTableRow[14]/VLabel[0]</td>
+ <td>Label 4</td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentstableSortLabelsInTable::/VVerticalLayout[0]/VVerticalLayout[0]/VScrollTable[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]/domChild[2]</td>
+ <td>14,3</td>
+</tr>
+<tr>
+ <td>assertText</td>
+ <td>vaadin=runcomvaadintestscomponentstableSortLabelsInTable::/VVerticalLayout[0]/VVerticalLayout[0]/VScrollTable[0]/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[0]/domChild[0]/domChild[0]</td>
+ <td>Text 9</td>
+</tr>
+<tr>
+ <td>assertText</td>
+ <td>vaadin=runcomvaadintestscomponentstableSortLabelsInTable::/VVerticalLayout[0]/VVerticalLayout[0]/VScrollTable[0]/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[8]/domChild[0]/domChild[0]</td>
+ <td>Text 19</td>
+</tr>
+<tr>
+ <td>assertText</td>
+ <td>vaadin=runcomvaadintestscomponentstableSortLabelsInTable::/VVerticalLayout[0]/VVerticalLayout[0]/VScrollTable[0]/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[14]/domChild[0]/domChild[0]</td>
+ <td>Text 13</td>
+</tr>
+<tr>
+ <td>assertText</td>
+ <td>vaadin=runcomvaadintestscomponentstableSortLabelsInTable::/VVerticalLayout[0]/VVerticalLayout[0]/VScrollTable[0]/FocusableScrollPanel[0]/VScrollTable$VScrollTableBody[0]/VScrollTable$VScrollTableBody$VScrollTableRow[0]/VLabel[0]</td>
+ <td>Label 9</td>
+</tr>
+<tr>
+ <td>assertText</td>
+ <td>vaadin=runcomvaadintestscomponentstableSortLabelsInTable::/VVerticalLayout[0]/VVerticalLayout[0]/VScrollTable[0]/FocusableScrollPanel[0]/VScrollTable$VScrollTableBody[0]/VScrollTable$VScrollTableBody$VScrollTableRow[8]/VLabel[0]</td>
+ <td>Label 19</td>
+</tr>
+<tr>
+ <td>assertText</td>
+ <td>vaadin=runcomvaadintestscomponentstableSortLabelsInTable::/VVerticalLayout[0]/VVerticalLayout[0]/VScrollTable[0]/FocusableScrollPanel[0]/VScrollTable$VScrollTableBody[0]/VScrollTable$VScrollTableBody$VScrollTableRow[14]/VLabel[0]</td>
+ <td>Label 13</td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentstableSortLabelsInTable::/VVerticalLayout[0]/VVerticalLayout[0]/VScrollTable[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]/domChild[1]/domChild[2]</td>
+ <td>28,13</td>
+</tr>
+<tr>
+ <td>assertText</td>
+ <td>vaadin=runcomvaadintestscomponentstableSortLabelsInTable::/VVerticalLayout[0]/VVerticalLayout[0]/VScrollTable[0]/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[0]/domChild[0]/domChild[0]</td>
+ <td>Text 9</td>
+</tr>
+<tr>
+ <td>assertText</td>
+ <td>vaadin=runcomvaadintestscomponentstableSortLabelsInTable::/VVerticalLayout[0]/VVerticalLayout[0]/VScrollTable[0]/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[8]/domChild[0]/domChild[0]</td>
+ <td>Text 19</td>
+</tr>
+<tr>
+ <td>assertText</td>
+ <td>vaadin=runcomvaadintestscomponentstableSortLabelsInTable::/VVerticalLayout[0]/VVerticalLayout[0]/VScrollTable[0]/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[14]/domChild[0]/domChild[0]</td>
+ <td>Text 13</td>
+</tr>
+<tr>
+ <td>assertText</td>
+ <td>vaadin=runcomvaadintestscomponentstableSortLabelsInTable::/VVerticalLayout[0]/VVerticalLayout[0]/VScrollTable[0]/FocusableScrollPanel[0]/VScrollTable$VScrollTableBody[0]/VScrollTable$VScrollTableBody$VScrollTableRow[0]/VLabel[0]</td>
+ <td>Label 9</td>
+</tr>
+<tr>
+ <td>assertText</td>
+ <td>vaadin=runcomvaadintestscomponentstableSortLabelsInTable::/VVerticalLayout[0]/VVerticalLayout[0]/VScrollTable[0]/FocusableScrollPanel[0]/VScrollTable$VScrollTableBody[0]/VScrollTable$VScrollTableBody$VScrollTableRow[8]/VLabel[0]</td>
+ <td>Label 19</td>
+</tr>
+<tr>
+ <td>assertText</td>
+ <td>vaadin=runcomvaadintestscomponentstableSortLabelsInTable::/VVerticalLayout[0]/VVerticalLayout[0]/VScrollTable[0]/FocusableScrollPanel[0]/VScrollTable$VScrollTableBody[0]/VScrollTable$VScrollTableBody$VScrollTableRow[14]/VLabel[0]</td>
+ <td>Label 13</td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentstableSortLabelsInTable::/VVerticalLayout[0]/VVerticalLayout[0]/VScrollTable[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]/domChild[1]/domChild[2]</td>
+ <td>26,9</td>
+</tr>
+<tr>
+ <td>assertText</td>
+ <td>vaadin=runcomvaadintestscomponentstableSortLabelsInTable::/VVerticalLayout[0]/VVerticalLayout[0]/VScrollTable[0]/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[0]/domChild[0]/domChild[0]</td>
+ <td>Text 0</td>
+</tr>
+<tr>
+ <td>assertText</td>
+ <td>vaadin=runcomvaadintestscomponentstableSortLabelsInTable::/VVerticalLayout[0]/VVerticalLayout[0]/VScrollTable[0]/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[2]/domChild[0]/domChild[0]</td>
+ <td>Text 10</td>
+</tr>
+<tr>
+ <td>assertText</td>
+ <td>vaadin=runcomvaadintestscomponentstableSortLabelsInTable::/VVerticalLayout[0]/VVerticalLayout[0]/VScrollTable[0]/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[14]/domChild[0]/domChild[0]</td>
+ <td>Text 4</td>
+</tr>
+<tr>
+ <td>assertText</td>
+ <td>vaadin=runcomvaadintestscomponentstableSortLabelsInTable::/VVerticalLayout[0]/VVerticalLayout[0]/VScrollTable[0]/FocusableScrollPanel[0]/VScrollTable$VScrollTableBody[0]/VScrollTable$VScrollTableBody$VScrollTableRow[0]/VLabel[0]</td>
+ <td>Label 0</td>
+</tr>
+<tr>
+ <td>assertText</td>
+ <td>vaadin=runcomvaadintestscomponentstableSortLabelsInTable::/VVerticalLayout[0]/VVerticalLayout[0]/VScrollTable[0]/FocusableScrollPanel[0]/VScrollTable$VScrollTableBody[0]/VScrollTable$VScrollTableBody$VScrollTableRow[2]/VLabel[0]</td>
+ <td>Label 10</td>
+</tr>
+<tr>
+ <td>assertText</td>
+ <td>vaadin=runcomvaadintestscomponentstableSortLabelsInTable::/VVerticalLayout[0]/VVerticalLayout[0]/VScrollTable[0]/FocusableScrollPanel[0]/VScrollTable$VScrollTableBody[0]/VScrollTable$VScrollTableBody$VScrollTableRow[11]/VLabel[0]</td>
+ <td>Label 19</td>
+</tr>
+<tr>
+ <td>assertText</td>
+ <td>vaadin=runcomvaadintestscomponentstableSortLabelsInTable::/VVerticalLayout[0]/VVerticalLayout[0]/VScrollTable[0]/FocusableScrollPanel[0]/VScrollTable$VScrollTableBody[0]/VScrollTable$VScrollTableBody$VScrollTableRow[14]/VLabel[0]</td>
+ <td>Label 4</td>
+</tr>
+
+</tbody></table>
+</body>
+</html>
diff --git a/tests/testbench/com/vaadin/tests/components/table/SortLabelsInTable.java b/tests/testbench/com/vaadin/tests/components/table/SortLabelsInTable.java
new file mode 100644
index 0000000000..d46b9bf01d
--- /dev/null
+++ b/tests/testbench/com/vaadin/tests/components/table/SortLabelsInTable.java
@@ -0,0 +1,38 @@
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+package com.vaadin.tests.components.table;
+
+import com.vaadin.data.Item;
+import com.vaadin.tests.components.TestBase;
+import com.vaadin.ui.Label;
+import com.vaadin.ui.Table;
+
+public class SortLabelsInTable extends TestBase {
+
+ @Override
+ protected void setup() {
+ Table t = new Table("A table with a text column and a Label column");
+ t.addContainerProperty("text", String.class, null);
+ t.addContainerProperty("label", Label.class, null);
+
+ for (int i = 0; i < 20; i++) {
+ Item item = t.addItem("" + i);
+ item.getItemProperty("text").setValue("Text " + i);
+ item.getItemProperty("label").setValue(new Label("Label " + i));
+ }
+ addComponent(t);
+ }
+
+ @Override
+ protected String getDescription() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ protected Integer getTicketNumber() {
+ return 8845;
+ }
+
+}
diff --git a/tests/testbench/com/vaadin/tests/components/table/TableClickValueChangeInteraction.java b/tests/testbench/com/vaadin/tests/components/table/TableClickValueChangeInteraction.java
index ff5aa89d84..79a7eca852 100644
--- a/tests/testbench/com/vaadin/tests/components/table/TableClickValueChangeInteraction.java
+++ b/tests/testbench/com/vaadin/tests/components/table/TableClickValueChangeInteraction.java
@@ -60,6 +60,7 @@ public class TableClickValueChangeInteraction extends TestBase {
table.setHeight("100px");
if (listenClicks) {
table.addListener(new ItemClickListener() {
+
public void itemClick(ItemClickEvent event) {
table.requestRepaint();
clickLabel.setValue("Click " + event.getItemId());
@@ -68,6 +69,7 @@ public class TableClickValueChangeInteraction extends TestBase {
}
if (listenValueChanges) {
table.addListener(new ValueChangeListener() {
+
public void valueChange(ValueChangeEvent event) {
valueChangeLabel.setValue("Value "
+ event.getProperty().getValue());
diff --git a/tests/testbench/com/vaadin/tests/components/table/TableContextMenu.java b/tests/testbench/com/vaadin/tests/components/table/TableContextMenu.java
index 16323e5024..06afd406ef 100644
--- a/tests/testbench/com/vaadin/tests/components/table/TableContextMenu.java
+++ b/tests/testbench/com/vaadin/tests/components/table/TableContextMenu.java
@@ -2,6 +2,7 @@ package com.vaadin.tests.components.table;
import com.vaadin.event.Action;
import com.vaadin.tests.components.TestBase;
+import com.vaadin.ui.Notification;
import com.vaadin.ui.Table;
public class TableContextMenu extends TestBase {
@@ -16,7 +17,7 @@ public class TableContextMenu extends TestBase {
table.addActionHandler(new Action.Handler() {
public void handleAction(Action action, Object sender, Object target) {
- getLayout().getRoot().showNotification("Done that :-)");
+ Notification.show("Done that :-)");
}
public Action[] getActions(Object target, Object sender) {
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..3101615cfd
--- /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.LegacyApplication;
+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.Root.LegacyWindow;
+import com.vaadin.ui.Table;
+import com.vaadin.ui.VerticalLayout;
+
+public class TableFirstRowFlicker extends LegacyApplication {
+
+ Table t;
+
+ @Override
+ public void init() {
+ LegacyWindow mainWindow = new LegacyWindow(getClass().getName());
+ setMainWindow(mainWindow);
+ mainWindow.getContent().setSizeFull();
+
+ 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
diff --git a/tests/testbench/com/vaadin/tests/components/table/TableInTabsheet.java b/tests/testbench/com/vaadin/tests/components/table/TableInTabsheet.java
new file mode 100644
index 0000000000..27e624b810
--- /dev/null
+++ b/tests/testbench/com/vaadin/tests/components/table/TableInTabsheet.java
@@ -0,0 +1,114 @@
+package com.vaadin.tests.components.table;
+
+import java.net.MalformedURLException;
+
+import com.vaadin.terminal.WrappedRequest;
+import com.vaadin.terminal.gwt.client.ui.label.ContentMode;
+import com.vaadin.tests.components.AbstractTestRoot;
+import com.vaadin.ui.AbsoluteLayout;
+import com.vaadin.ui.HorizontalLayout;
+import com.vaadin.ui.Label;
+import com.vaadin.ui.TabSheet;
+import com.vaadin.ui.Table;
+import com.vaadin.ui.Table.Align;
+import com.vaadin.ui.VerticalLayout;
+import com.vaadin.ui.themes.Reindeer;
+
+public class TableInTabsheet extends AbstractTestRoot {
+
+ @Override
+ protected void setup(WrappedRequest request) {
+ getRoot().setCaption("test");
+ VerticalLayout vPrinc = new VerticalLayout();
+ vPrinc.setStyleName(Reindeer.LAYOUT_BLUE);
+
+ vPrinc.addComponent(title());
+ vPrinc.addComponent(page());
+ vPrinc.addComponent(new Label("Dvlop Tecnologia."));
+ setContent(vPrinc);
+ }
+
+ private VerticalLayout title() {
+
+ VerticalLayout vP = new VerticalLayout();
+ vP.setStyleName(Reindeer.LAYOUT_BLACK);
+ Label tit = new Label("<h1> Tab/Table Test</h1>", ContentMode.XHTML);
+ vP.addComponent(tit);
+ return vP;
+
+ }
+
+ private VerticalLayout page() {
+
+ VerticalLayout vP = new VerticalLayout();
+ vP.setStyleName(Reindeer.LAYOUT_BLUE);
+ TabSheet t = new TabSheet();
+ t.setWidth(1000, Unit.PIXELS);
+
+ HorizontalLayout hP = new HorizontalLayout();
+ t.addTab(Ranking(), "Ranking");
+ try {
+
+ t.addTab(GDocs(""), "Dez 2011");
+ t.addTab(GDocs(""), "Jan 2012");
+ t.addTab(GDocs(""), "Abr 2012");
+
+ } catch (MalformedURLException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ hP.addComponent(t);
+ vP.addComponent(hP);
+ return vP;
+
+ }
+
+ private AbsoluteLayout Ranking() {
+
+ AbsoluteLayout vT = new AbsoluteLayout();
+ vT.setHeight(500, Unit.PIXELS);
+ vT.setWidth(900, Unit.PIXELS);
+ vT.setStyleName(Reindeer.LAYOUT_BLUE);
+
+ final Table table = new Table("Ranking Oficial");
+
+ table.addContainerProperty("Atleta", String.class, null);
+ table.addContainerProperty("P", String.class, null);
+ table.addContainerProperty("Dez/11", Integer.class, null);
+ table.setColumnAlignment("Dez/11", Align.CENTER);
+ table.addContainerProperty("Jan/12", Integer.class, null);
+ table.setColumnAlignment("Jan/12", Align.CENTER);
+ table.addContainerProperty("Abr/12", String.class, null);
+ table.addContainerProperty("Total", Integer.class, null);
+ table.setColumnAlignment("Total", Align.CENTER);
+
+ table.addItem(new Object[] { "Araujo", "D.1", 8, 8, " ", 16 }, 1);
+ table.addItem(new Object[] { "Claudio", "D.2", 2, 10, " ", 12 }, 2);
+ table.setPageLength(12);
+
+ vT.addComponent(table, "left: 50px; top: 50px;");
+ return vT;
+
+ }
+
+ private VerticalLayout GDocs(String end) throws MalformedURLException {
+
+ VerticalLayout vT = new VerticalLayout();
+ vT.setHeight(500, Unit.PIXELS);
+ vT.setWidth(900, Unit.PIXELS);
+
+ return vT;
+
+ }
+
+ @Override
+ protected String getTestDescription() {
+ return "Chaning to a different tab and then back to the first tab should properly render the table.";
+ }
+
+ @Override
+ protected Integer getTicketNumber() {
+ return Integer.valueOf(8714);
+ }
+
+}
diff --git a/tests/testbench/com/vaadin/tests/components/table/TableShouldNotEatValueChanges.java b/tests/testbench/com/vaadin/tests/components/table/TableShouldNotEatValueChanges.java
index a1686dee3f..d64bc0035d 100644
--- a/tests/testbench/com/vaadin/tests/components/table/TableShouldNotEatValueChanges.java
+++ b/tests/testbench/com/vaadin/tests/components/table/TableShouldNotEatValueChanges.java
@@ -27,10 +27,8 @@ public class TableShouldNotEatValueChanges extends TestBase {
ItemClickListener l = new ItemClickListener() {
public void itemClick(ItemClickEvent event) {
- tf.getRoot().showNotification(
- "TF Value on the server:" + tf.getValue(),
+ Notification.show("TF Value on the server:" + tf.getValue(),
Notification.TYPE_WARNING_MESSAGE);
-
}
};
t.addListener(l);
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 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head profile="http://selenium-ide.openqa.org/profiles/test-case">
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<link rel="selenium.base" href="" />
+<title>TableWithNoncollapsibleColumns</title>
+</head>
+<body>
+<table cellpadding="1" cellspacing="1" border="1">
+<thead>
+<tr><td rowspan="1" colspan="3">TableWithNoncollapsibleColumns</td></tr>
+</thead><tbody>
+<tr>
+ <td>open</td>
+ <td>/run/com.vaadin.tests.components.table.TableWithNoncollapsibleColumns?restartApplication</td>
+ <td></td>
+</tr>
+<tr>
+ <td>click</td>
+ <td>vaadin=runcomvaadintestscomponentstableTableWithNoncollapsibleColumns::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VVerticalLayout[0]/ChildComponentContainer[3]/VButton[0]/domChild[0]/domChild[0]</td>
+ <td></td>
+</tr>
+<tr>
+ <td>screenCapture</td>
+ <td></td>
+ <td>column-3-collapsed</td>
+</tr>
+<tr>
+ <td>click</td>
+ <td>vaadin=runcomvaadintestscomponentstableTableWithNoncollapsibleColumns::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VVerticalLayout[0]/ChildComponentContainer[4]/VButton[0]/domChild[0]/domChild[0]</td>
+ <td></td>
+</tr>
+<tr>
+ <td>screenCapture</td>
+ <td></td>
+ <td>column-3-noncollapsible</td>
+</tr>
+<tr>
+ <td>click</td>
+ <td>vaadin=runcomvaadintestscomponentstableTableWithNoncollapsibleColumns::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VVerticalLayout[0]/ChildComponentContainer[1]/VButton[0]/domChild[0]/domChild[0]</td>
+ <td></td>
+</tr>
+<tr>
+ <td>click</td>
+ <td>vaadin=runcomvaadintestscomponentstableTableWithNoncollapsibleColumns::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VVerticalLayout[0]/ChildComponentContainer[2]/VButton[0]/domChild[0]/domChild[0]</td>
+ <td></td>
+</tr>
+<tr>
+ <td>click</td>
+ <td>vaadin=runcomvaadintestscomponentstableTableWithNoncollapsibleColumns::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VVerticalLayout[0]/ChildComponentContainer[3]/VButton[0]/domChild[0]/domChild[0]</td>
+ <td></td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentstableTableWithNoncollapsibleColumns::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VVerticalLayout[0]/ChildComponentContainer[0]/VScrollTable[0]/domChild[0]/domChild[1]</td>
+ <td>9,7</td>
+</tr>
+<tr>
+ <td>screenCapture</td>
+ <td></td>
+ <td>column-menu-after-collapsing-all-columns</td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentstableTableWithNoncollapsibleColumns::Root/VContextMenu[0]#option2</td>
+ <td>93,4</td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentstableTableWithNoncollapsibleColumns::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VVerticalLayout[0]/ChildComponentContainer[0]/VScrollTable[0]/domChild[0]/domChild[1]</td>
+ <td>7,10</td>
+</tr>
+<tr>
+ <td>screenCapture</td>
+ <td></td>
+ <td>column-menu-after-expanding-column-2</td>
+</tr>
+
+</tbody></table>
+</body>
+</html>
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..404ba5d779
--- /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.setColumnCollapsible("Column 1 - noncollapsible", false);
+ 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.setColumnCollapsible(
+ "Column 3 - toggle collapsing",
+ !table.isColumnCollapsible("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 47c858f441..11ffff0655 100644
--- a/tests/testbench/com/vaadin/tests/components/table/Tables.java
+++ b/tests/testbench/com/vaadin/tests/components/table/Tables.java
@@ -78,6 +78,14 @@ public class Tables<T extends Table> extends AbstractSelectTestCase<T>
}
};
+ private Command<T, Boolean> columnCollapsibleCommand = new Command<T, Boolean>() {
+
+ public void execute(T c, Boolean collapsible, Object propertyId) {
+ c.setColumnCollapsible(propertyId, collapsible);
+
+ }
+ };
+
protected Command<T, Boolean> columnResizeListenerCommand = new Command<T, Boolean>() {
public void execute(Table c, Boolean value, Object data) {
@@ -648,6 +656,9 @@ public class Tables<T extends Table> extends AbstractSelectTestCase<T>
createSelectAction("Expand ratio", category, expandOptions,
"- remove -", columnExpandRatioCommand, propertyId);
t.log("Expand");
+ createBooleanAction("Collapsible", category, true,
+ columnCollapsibleCommand, propertyId);
+
// Footer text (move)
// Header text (move)
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 @@
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head profile="http://selenium-ide.openqa.org/profiles/test-case">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
-<link rel="selenium.base" href="" />
+<link rel="selenium.base" href="http://localhost:8067/" />
<title>TestCurrentPageFirstItem</title>
</head>
<body>
@@ -36,6 +36,41 @@
<td></td>
<td></td>
</tr>
+<tr>
+ <td>click</td>
+ <td>vaadin=runTestCurrentPageFirstItem::/VHorizontalLayout[0]/ChildComponentContainer[4]/VButton[0]/domChild[0]/domChild[0]</td>
+ <td></td>
+</tr>
+<tr>
+ <td>click</td>
+ <td>vaadin=runTestCurrentPageFirstItem::/VHorizontalLayout[0]/ChildComponentContainer[5]/VButton[0]/domChild[0]/domChild[0]</td>
+ <td></td>
+</tr>
+<tr>
+ <td>click</td>
+ <td>vaadin=runTestCurrentPageFirstItem::/VHorizontalLayout[0]/ChildComponentContainer[4]/VButton[0]/domChild[0]/domChild[0]</td>
+ <td></td>
+</tr>
+<tr>
+ <td>click</td>
+ <td>vaadin=runTestCurrentPageFirstItem::/VHorizontalLayout[0]/ChildComponentContainer[5]/VButton[0]/domChild[0]/domChild[0]</td>
+ <td></td>
+</tr>
+<tr>
+ <td>click</td>
+ <td>vaadin=runTestCurrentPageFirstItem::/VHorizontalLayout[0]/ChildComponentContainer[4]/VButton[0]/domChild[0]/domChild[0]</td>
+ <td></td>
+</tr>
+<tr>
+ <td>click</td>
+ <td>vaadin=runTestCurrentPageFirstItem::/VHorizontalLayout[0]/ChildComponentContainer[5]/VButton[0]/domChild[0]/domChild[0]</td>
+ <td></td>
+</tr>
+<tr>
+ <td>screenCapture</td>
+ <td></td>
+ <td></td>
+</tr>
</tbody></table>
</body>
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..d61a2cbc62
--- /dev/null
+++ b/tests/testbench/com/vaadin/tests/components/tabsheet/TabSheetWithDisappearingContent.html
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head profile="http://selenium-ide.openqa.org/profiles/test-case">
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<link rel="selenium.base" href="http://localhost:8070" />
+<title>TabSheetWithDisappearingContent</title>
+</head>
+<body>
+<table cellpadding="1" cellspacing="1" border="1">
+<thead>
+<tr><td rowspan="1" colspan="3">TabSheetWithDisappearingContent</td></tr>
+</thead><tbody>
+<tr>
+ <td>open</td>
+ <td>/run/com.vaadin.tests.components.tabsheet.TabSheetWithDisappearingContent?restartApplication</td>
+ <td></td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentstabsheetTabSheetWithDisappearingContent::/VVerticalLayout[0]/VVerticalLayout[0]/VTabsheet[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]/domChild[2]/domChild[0]/domChild[0]/domChild[0]</td>
+ <td>14,7</td>
+</tr>
+<tr>
+ <td>assertText</td>
+ <td>vaadin=runcomvaadintestscomponentstabsheetTabSheetWithDisappearingContent::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VTabsheet[0]/VTabsheetPanel[0]/VVerticalLayout[0]/ChildComponentContainer[0]/VLabel[0]</td>
+ <td>Content 1</td>
+</tr>
+<tr>
+ <td>assertVisible</td>
+ <td>vaadin=runcomvaadintestscomponentstabsheetTabSheetWithDisappearingContent::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VTabsheet[0]/VTabsheetPanel[0]/VVerticalLayout[0]/ChildComponentContainer[0]/VLabel[0]</td>
+ <td></td>
+</tr>
+
+</tbody></table>
+</body>
+</html>
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;
+ }
+
+}
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("<b>foo</b><br/><i>bar</i>");
+ 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;
+ }
+}
diff --git a/tests/testbench/com/vaadin/tests/components/treetable/ProgrammaticCollapse.java b/tests/testbench/com/vaadin/tests/components/treetable/ProgrammaticCollapse.java
index 2f84c8a68d..447ce6c465 100644
--- a/tests/testbench/com/vaadin/tests/components/treetable/ProgrammaticCollapse.java
+++ b/tests/testbench/com/vaadin/tests/components/treetable/ProgrammaticCollapse.java
@@ -4,6 +4,7 @@ import com.vaadin.tests.components.TestBase;
import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.Button.ClickListener;
+import com.vaadin.ui.Notification;
import com.vaadin.ui.TreeTable;
import com.vaadin.ui.VerticalLayout;
@@ -31,8 +32,7 @@ public class ProgrammaticCollapse extends TestBase {
new ClickListener() {
public void buttonClick(ClickEvent event) {
boolean collapsed = !table.isCollapsed(1);
- table.getRoot().showNotification(
- "set collapsed: " + collapsed);
+ Notification.show("set collapsed: " + collapsed);
table.setCollapsed(1, collapsed);
}
}));
@@ -40,8 +40,7 @@ public class ProgrammaticCollapse extends TestBase {
new ClickListener() {
public void buttonClick(ClickEvent event) {
boolean collapsed = !table.isCollapsed(100);
- table.getRoot().showNotification(
- "set collapsed: " + collapsed);
+ Notification.show("set collapsed: " + collapsed);
table.setCollapsed(100, collapsed);
}
}));
@@ -51,8 +50,7 @@ public class ProgrammaticCollapse extends TestBase {
public void buttonClick(ClickEvent event) {
collapsed = !collapsed;
- table.getRoot().showNotification(
- "set collapsed: " + collapsed);
+ Notification.show("set collapsed: " + collapsed);
for (int i = 0; i < 50; ++i) {
table.setCollapsed(i * 2, collapsed);
}
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 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head profile="http://selenium-ide.openqa.org/profiles/test-case">
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<link rel="selenium.base" href="" />
+<title>TestAnimatedExpandCollapse</title>
+</head>
+<body>
+<table cellpadding="1" cellspacing="1" border="1">
+<thead>
+<tr><td rowspan="1" colspan="3">TestAnimatedExpandCollapse</td></tr>
+</thead><tbody>
+<tr>
+ <td>open</td>
+ <td>/run/com.vaadin.tests.components.treetable.TreeTableTest?restartApplication</td>
+ <td></td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentstreetableTreeTableTest::PID_Smenu#item0</td>
+ <td>38,10</td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentstreetableTreeTableTest::Root/VOverlay[0]/VMenuBar[0]#item0</td>
+ <td>35,5</td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentstreetableTreeTableTest::Root/VOverlay[1]/VMenuBar[0]#item7</td>
+ <td>30,12</td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentstreetableTreeTableTest::PID_StestComponent/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]</td>
+ <td>12,7</td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentstreetableTreeTableTest::PID_StestComponent/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[0]/domChild[0]</td>
+ <td>31,7</td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentstreetableTreeTableTest::PID_StestComponent/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[2]/domChild[0]/domChild[0]/domChild[0]</td>
+ <td>29,8</td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentstreetableTreeTableTest::PID_StestComponent/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[3]/domChild[0]/domChild[0]/domChild[0]</td>
+ <td>30,6</td>
+</tr>
+<tr>
+ <td>assertText</td>
+ <td>vaadin=runcomvaadintestscomponentstreetableTreeTableTest::PID_StestComponent/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[0]</td>
+ <td>Item 4,1</td>
+</tr>
+<tr>
+ <td>assertText</td>
+ <td>vaadin=runcomvaadintestscomponentstreetableTreeTableTest::PID_StestComponent/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[2]/domChild[0]/domChild[0]</td>
+ <td>Item 5,1</td>
+</tr>
+<tr>
+ <td>assertText</td>
+ <td>vaadin=runcomvaadintestscomponentstreetableTreeTableTest::PID_StestComponent/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[3]/domChild[0]/domChild[0]</td>
+ <td>Item 6,1</td>
+</tr>
+<tr>
+ <td>assertText</td>
+ <td>vaadin=runcomvaadintestscomponentstreetableTreeTableTest::PID_StestComponent/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[4]/domChild[0]/domChild[0]</td>
+ <td>Item 7,1</td>
+</tr>
+
+</tbody></table>
+</body>
+</html>
diff --git a/tests/testbench/com/vaadin/tests/components/treetable/TreeTableCacheOnPartialUpdate.html b/tests/testbench/com/vaadin/tests/components/treetable/TreeTableCacheOnPartialUpdate.html
index b22d77a94c..499c30c86a 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 @@
<td>9,-995</td>
</tr>
<tr>
- <td>mouseClick</td>
- <td>vaadin=runcomvaadintestscomponentstreetableTreeTableCacheOnPartialUpdates::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[3]/VTreeTable[0]/FocusableScrollPanel[0]/VTreeTable$VTreeTableScrollBody[0]/VTreeTable$VTreeTableScrollBody$VTreeTableRow[34]/VNativeButton[0]</td>
- <td>93,-991</td>
+ <td>assertText</td>
+ <td>vaadin=runcomvaadintestscomponentstreetableTreeTableCacheOnPartialUpdates::PID_SLog_row_0</td>
+ <td>20. Row Item TestBean [col1=40 (children), col2=AN] expanded. Row index: 39</td>
</tr>
<tr>
<td>mouseClick</td>
- <td>vaadin=runcomvaadintestscomponentstreetableTreeTableCacheOnPartialUpdates::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[3]/VTreeTable[0]/FocusableScrollPanel[0]/VTreeTable$VTreeTableScrollBody[0]/VTreeTable$VTreeTableScrollBody$VTreeTableRow[35]/VNativeButton[0]</td>
- <td>123,-991</td>
+ <td>vaadin=runcomvaadintestscomponentstreetableTreeTableCacheOnPartialUpdates::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[3]/VTreeTable[0]/FocusableScrollPanel[0]/VTreeTable$VTreeTableScrollBody[0]/VTreeTable$VTreeTableScrollBody$VTreeTableRow[34]/VNativeButton[0]</td>
+ <td>93,-991</td>
</tr>
<tr>
- <td>mouseClick</td>
- <td>vaadin=runcomvaadintestscomponentstreetableTreeTableCacheOnPartialUpdates::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[3]/VTreeTable[0]/FocusableScrollPanel[0]/VTreeTable$VTreeTableScrollBody[0]/VTreeTable$VTreeTableScrollBody$VTreeTableRow[44]/VNativeButton[0]</td>
- <td>114,-1000</td>
+ <td>assertText</td>
+ <td>vaadin=runcomvaadintestscomponentstreetableTreeTableCacheOnPartialUpdates::PID_SLog_row_0</td>
+ <td>21. Button Item TestBean [col1=40 (children), col2=AN]/col3 clicked. Row index: 39</td>
</tr>
<tr>
<td>mouseClick</td>
- <td>vaadin=runcomvaadintestscomponentstreetableTreeTableCacheOnPartialUpdates::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[3]/VTreeTable[0]/FocusableScrollPanel[0]/VTreeTable$VTreeTableScrollBody[0]/VTreeTable$VTreeTableScrollBody$VTreeTableRow[34]/VNativeButton[0]</td>
- <td>118,-993</td>
+ <td>vaadin=runcomvaadintestscomponentstreetableTreeTableCacheOnPartialUpdates::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[3]/VTreeTable[0]/FocusableScrollPanel[0]/VTreeTable$VTreeTableScrollBody[0]/VTreeTable$VTreeTableScrollBody$VTreeTableRow[35]/VNativeButton[0]</td>
+ <td>123,-991</td>
</tr>
<tr>
<td>assertText</td>
- <td>vaadin=runcomvaadintestscomponentstreetableTreeTableCacheOnPartialUpdates::PID_SLog_row_4</td>
- <td>20. Row Item TestBean [col1=40 (children), col2=AN] expanded. Row index: 39</td>
+ <td>vaadin=runcomvaadintestscomponentstreetableTreeTableCacheOnPartialUpdates::PID_SLog_row_0</td>
+ <td>22. Button Item TestBean [col1=40.1, col2=AN.A]/col3 clicked. Row index: 40</td>
</tr>
<tr>
- <td>assertText</td>
- <td>vaadin=runcomvaadintestscomponentstreetableTreeTableCacheOnPartialUpdates::PID_SLog_row_3</td>
- <td>21. Button Item TestBean [col1=40 (children), col2=AN]/col3 clicked. Row index: 39</td>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentstreetableTreeTableCacheOnPartialUpdates::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[3]/VTreeTable[0]/FocusableScrollPanel[0]/VTreeTable$VTreeTableScrollBody[0]/VTreeTable$VTreeTableScrollBody$VTreeTableRow[40]/VNativeButton[0]</td>
+ <td>114,-1000</td>
</tr>
<tr>
<td>assertText</td>
- <td>vaadin=runcomvaadintestscomponentstreetableTreeTableCacheOnPartialUpdates::PID_SLog_row_2</td>
- <td>22. Button Item TestBean [col1=40.1, col2=AN.A]/col3 clicked. Row index: 40</td>
+ <td>vaadin=runcomvaadintestscomponentstreetableTreeTableCacheOnPartialUpdates::PID_SLog_row_0</td>
+ <td>23. Button Item TestBean [col1=40.6, col2=AN.F]/col3 clicked. Row index: 45</td>
</tr>
<tr>
- <td>assertText</td>
- <td>vaadin=runcomvaadintestscomponentstreetableTreeTableCacheOnPartialUpdates::PID_SLog_row_1</td>
- <td>23. Button Item TestBean [col1=40.10, col2=AN.J]/col3 clicked. Row index: 49</td>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentstreetableTreeTableCacheOnPartialUpdates::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[3]/VTreeTable[0]/FocusableScrollPanel[0]/VTreeTable$VTreeTableScrollBody[0]/VTreeTable$VTreeTableScrollBody$VTreeTableRow[34]/VNativeButton[0]</td>
+ <td>118,-993</td>
</tr>
<tr>
<td>assertText</td>
@@ -288,29 +288,34 @@
<td>9,-998</td>
</tr>
<tr>
+ <td>assertText</td>
+ <td>vaadin=runcomvaadintestscomponentstreetableTreeTableCacheOnPartialUpdates::PID_SLog_row_0</td>
+ <td>25. Row Item TestBean [col1=40 (children), col2=AN] collapsed. Row index: 39</td>
+</tr>
+<tr>
<td>mouseClick</td>
<td>vaadin=runcomvaadintestscomponentstreetableTreeTableCacheOnPartialUpdates::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[3]/VTreeTable[0]/FocusableScrollPanel[0]/VTreeTable$VTreeTableScrollBody[0]/VTreeTable$VTreeTableScrollBody$VTreeTableRow[34]/VNativeButton[0]</td>
<td>42,-990</td>
</tr>
<tr>
- <td>mouseClick</td>
- <td>vaadin=runcomvaadintestscomponentstreetableTreeTableCacheOnPartialUpdates::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[3]/VTreeTable[0]/FocusableScrollPanel[0]/VTreeTable$VTreeTableScrollBody[0]/VTreeTable$VTreeTableScrollBody$VTreeTableRow[29]/VNativeButton[0]</td>
- <td>84,-990</td>
+ <td>assertText</td>
+ <td>vaadin=runcomvaadintestscomponentstreetableTreeTableCacheOnPartialUpdates::PID_SLog_row_0</td>
+ <td>26. Button Item TestBean [col1=40 (children), col2=AN]/col3 clicked. Row index: 39</td>
</tr>
<tr>
<td>mouseClick</td>
- <td>vaadin=runcomvaadintestscomponentstreetableTreeTableCacheOnPartialUpdates::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[3]/VTreeTable[0]/FocusableScrollPanel[0]/VTreeTable$VTreeTableScrollBody[0]/VTreeTable$VTreeTableScrollBody$VTreeTableRow[42]/VNativeButton[0]</td>
- <td>98,-998</td>
+ <td>vaadin=runcomvaadintestscomponentstreetableTreeTableCacheOnPartialUpdates::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[3]/VTreeTable[0]/FocusableScrollPanel[0]/VTreeTable$VTreeTableScrollBody[0]/VTreeTable$VTreeTableScrollBody$VTreeTableRow[29]/VNativeButton[0]</td>
+ <td>84,-990</td>
</tr>
<tr>
<td>assertText</td>
- <td>vaadin=runcomvaadintestscomponentstreetableTreeTableCacheOnPartialUpdates::PID_SLog_row_2</td>
- <td>26. Button Item TestBean [col1=40 (children), col2=AN]/col3 clicked. Row index: 39</td>
+ <td>vaadin=runcomvaadintestscomponentstreetableTreeTableCacheOnPartialUpdates::PID_SLog_row_0</td>
+ <td>27. Button Item TestBean [col1=35, col2=AI]/col3 clicked. Row index: 34</td>
</tr>
<tr>
- <td>assertText</td>
- <td>vaadin=runcomvaadintestscomponentstreetableTreeTableCacheOnPartialUpdates::PID_SLog_row_1</td>
- <td>27. Button Item TestBean [col1=35, col2=AI]/col3 clicked. Row index: 34</td>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentstreetableTreeTableCacheOnPartialUpdates::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[3]/VTreeTable[0]/FocusableScrollPanel[0]/VTreeTable$VTreeTableScrollBody[0]/VTreeTable$VTreeTableScrollBody$VTreeTableRow[42]/VNativeButton[0]</td>
+ <td>98,-998</td>
</tr>
<tr>
<td>assertText</td>
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);
+ }
+
+}
diff --git a/tests/testbench/com/vaadin/tests/components/window/LazyWindowResize.java b/tests/testbench/com/vaadin/tests/components/window/LazyWindowResize.java
index 49da6758ea..9eaabf7340 100644
--- a/tests/testbench/com/vaadin/tests/components/window/LazyWindowResize.java
+++ b/tests/testbench/com/vaadin/tests/components/window/LazyWindowResize.java
@@ -2,14 +2,14 @@ package com.vaadin.tests.components.window;
import com.vaadin.data.Property.ValueChangeEvent;
import com.vaadin.data.Property.ValueChangeListener;
+import com.vaadin.terminal.Page.BrowserWindowResizeEvent;
+import com.vaadin.terminal.Page.BrowserWindowResizeListener;
import com.vaadin.terminal.gwt.client.ui.label.ContentMode;
import com.vaadin.tests.components.AbstractTestCase;
import com.vaadin.tests.util.Log;
import com.vaadin.tests.util.LoremIpsum;
import com.vaadin.ui.CheckBox;
import com.vaadin.ui.Label;
-import com.vaadin.ui.Root.BrowserWindowResizeEvent;
-import com.vaadin.ui.Root.BrowserWindowResizeListener;
import com.vaadin.ui.Root.LegacyWindow;
import com.vaadin.ui.Window;
import com.vaadin.ui.Window.ResizeEvent;
diff --git a/tests/testbench/com/vaadin/tests/components/window/RepaintWindowContents.html b/tests/testbench/com/vaadin/tests/components/window/RepaintWindowContents.html
new file mode 100644
index 0000000000..9cbcf1d5ea
--- /dev/null
+++ b/tests/testbench/com/vaadin/tests/components/window/RepaintWindowContents.html
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head profile="http://selenium-ide.openqa.org/profiles/test-case">
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<link rel="selenium.base" href="http://arturwin.office.itmill.com:8888/" />
+<title>New Test</title>
+</head>
+<body>
+<table cellpadding="1" cellspacing="1" border="1">
+<thead>
+<tr><td rowspan="1" colspan="3">New Test</td></tr>
+</thead><tbody>
+<tr>
+ <td>open</td>
+ <td>/run/com.vaadin.tests.components.window.RepaintWindowContents?restartApplication</td>
+ <td></td>
+</tr>
+<tr>
+ <td>assertText</td>
+ <td>vaadin=runcomvaadintestscomponentswindowRepaintWindowContents::/VWindow[0]/FocusableScrollPanel[0]/VVerticalLayout[0]/VButton[0]/domChild[0]/domChild[0]</td>
+ <td>Button 1</td>
+</tr>
+<tr>
+ <td>click</td>
+ <td>vaadin=runcomvaadintestscomponentswindowRepaintWindowContents::/VWindow[0]/FocusableScrollPanel[0]/VVerticalLayout[0]/VButton[0]/domChild[0]/domChild[0]</td>
+ <td></td>
+</tr>
+<tr>
+ <td>assertText</td>
+ <td>vaadin=runcomvaadintestscomponentswindowRepaintWindowContents::/VWindow[0]/FocusableScrollPanel[0]/VVerticalLayout[0]/VButton[0]/domChild[0]/domChild[0]</td>
+ <td>Button 2</td>
+</tr>
+<tr>
+ <td>click</td>
+ <td>vaadin=runcomvaadintestscomponentswindowRepaintWindowContents::/VWindow[0]/FocusableScrollPanel[0]/VVerticalLayout[0]/VButton[0]/domChild[0]/domChild[0]</td>
+ <td></td>
+</tr>
+<tr>
+ <td>assertText</td>
+ <td>vaadin=runcomvaadintestscomponentswindowRepaintWindowContents::/VWindow[0]/FocusableScrollPanel[0]/VVerticalLayout[0]/VButton[0]/domChild[0]/domChild[0]</td>
+ <td>Button 1</td>
+</tr>
+<tr>
+ <td>click</td>
+ <td>vaadin=runcomvaadintestscomponentswindowRepaintWindowContents::/VWindow[0]/FocusableScrollPanel[0]/VVerticalLayout[0]/VButton[0]/domChild[0]</td>
+ <td></td>
+</tr>
+<tr>
+ <td>assertText</td>
+ <td>vaadin=runcomvaadintestscomponentswindowRepaintWindowContents::/VWindow[0]/FocusableScrollPanel[0]/VVerticalLayout[0]/VButton[0]/domChild[0]/domChild[0]</td>
+ <td>Button 2</td>
+</tr>
+
+</tbody></table>
+</body>
+</html>
diff --git a/tests/testbench/com/vaadin/tests/components/window/RepaintWindowContents.java b/tests/testbench/com/vaadin/tests/components/window/RepaintWindowContents.java
new file mode 100644
index 0000000000..353eb535ca
--- /dev/null
+++ b/tests/testbench/com/vaadin/tests/components/window/RepaintWindowContents.java
@@ -0,0 +1,56 @@
+package com.vaadin.tests.components.window;
+
+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.Button.ClickListener;
+import com.vaadin.ui.Layout;
+import com.vaadin.ui.VerticalLayout;
+import com.vaadin.ui.Window;
+
+public class RepaintWindowContents extends AbstractTestRoot {
+ private static final long serialVersionUID = 1L;
+
+ @SuppressWarnings("serial")
+ @Override
+ protected void setup(WrappedRequest request) {
+ final Window window = new Window("Test window");
+ addWindow(window);
+
+ final Layout layout1 = new VerticalLayout();
+ Button button1 = new Button("Button 1");
+ layout1.addComponent(button1);
+
+ final Layout layout2 = new VerticalLayout();
+ Button button2 = new Button("Button 2");
+ layout2.addComponent(button2);
+
+ window.setContent(layout1);
+
+ button1.addListener(new ClickListener() {
+
+ public void buttonClick(ClickEvent event) {
+ window.setContent(layout2);
+ }
+ });
+
+ button2.addListener(new ClickListener() {
+
+ public void buttonClick(ClickEvent event) {
+ window.setContent(layout1);
+ }
+ });
+ }
+
+ @Override
+ protected String getTestDescription() {
+ return "Clicking the button switches the content between content1 and content2";
+ }
+
+ @Override
+ protected Integer getTicketNumber() {
+ return 8832;
+ }
+
+} \ No newline at end of file
diff --git a/tests/testbench/com/vaadin/tests/components/window/SubWindowFocusAndBlurListeners.java b/tests/testbench/com/vaadin/tests/components/window/SubWindowFocusAndBlurListeners.java
index 988d47e29f..1e342abe01 100644
--- a/tests/testbench/com/vaadin/tests/components/window/SubWindowFocusAndBlurListeners.java
+++ b/tests/testbench/com/vaadin/tests/components/window/SubWindowFocusAndBlurListeners.java
@@ -10,6 +10,7 @@ import com.vaadin.event.ShortcutAction;
import com.vaadin.tests.components.TestBase;
import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickEvent;
+import com.vaadin.ui.Notification;
import com.vaadin.ui.Root;
import com.vaadin.ui.TextField;
import com.vaadin.ui.Window;
@@ -36,15 +37,13 @@ public class SubWindowFocusAndBlurListeners extends TestBase {
window.addComponent(new TextField());
window.addListener(new FocusListener() {
public void focus(FocusEvent event) {
- event.getComponent().getRoot()
- .showNotification("Focused window");
+ Notification.show("Focused window");
}
});
window.addListener(new BlurListener() {
public void blur(BlurEvent event) {
- event.getComponent().getRoot()
- .showNotification("Blurred window");
+ Notification.show("Blurred window");
}
});
@@ -57,7 +56,7 @@ public class SubWindowFocusAndBlurListeners extends TestBase {
}
public void handleAction(Action action, Object sender, Object target) {
- window.getRoot().showNotification("Action!");
+ Notification.show("Action!");
}
});
diff --git a/tests/testbench/com/vaadin/tests/components/window/UndefinedHeightSubWindowAndContent.html b/tests/testbench/com/vaadin/tests/components/window/UndefinedHeightSubWindowAndContent.html
new file mode 100644
index 0000000000..a3b56cd12a
--- /dev/null
+++ b/tests/testbench/com/vaadin/tests/components/window/UndefinedHeightSubWindowAndContent.html
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head profile="http://selenium-ide.openqa.org/profiles/test-case">
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<link rel="selenium.base" href="" />
+<title>UndefinedHeightSubWindowAndContent</title>
+</head>
+<body>
+<table cellpadding="1" cellspacing="1" border="1">
+<thead>
+<tr><td rowspan="1" colspan="3">UndefinedHeightSubWindowAndContent</td></tr>
+</thead><tbody>
+<tr>
+ <td>open</td>
+ <td>/run/com.vaadin.tests.components.window.UndefinedHeightSubWindowAndContent?restartApplication</td>
+ <td></td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentswindowUndefinedHeightSubWindowAndContent::/VWindow[0]/FocusableScrollPanel[0]/VVerticalLayout[0]/ChildComponentContainer[0]/VForm[0]/VFormLayout[0]/VFormLayout$VFormLayoutTable[0]/VTextField[0]</td>
+ <td>52,11</td>
+</tr>
+<tr>
+ <td>enterCharacter</td>
+ <td>vaadin=runcomvaadintestscomponentswindowUndefinedHeightSubWindowAndContent::/VWindow[0]/FocusableScrollPanel[0]/VVerticalLayout[0]/ChildComponentContainer[0]/VForm[0]/VFormLayout[0]/VFormLayout$VFormLayoutTable[0]/VTextField[0]</td>
+ <td>invalid</td>
+</tr>
+<tr>
+ <td>pressSpecialKey</td>
+ <td>vaadin=runcomvaadintestscomponentswindowUndefinedHeightSubWindowAndContent::/VWindow[0]/FocusableScrollPanel[0]/VVerticalLayout[0]/ChildComponentContainer[0]/VForm[0]/VFormLayout[0]/VFormLayout$VFormLayoutTable[0]/VTextField[0]</td>
+ <td>enter</td>
+</tr>
+<tr>
+ <td>screenCapture</td>
+ <td></td>
+ <td>form_full_width_1_error</td>
+</tr>
+<tr>
+ <td>enterCharacter</td>
+ <td>vaadin=runcomvaadintestscomponentswindowUndefinedHeightSubWindowAndContent::/VWindow[0]/FocusableScrollPanel[0]/VVerticalLayout[0]/ChildComponentContainer[0]/VForm[0]/VFormLayout[0]/VFormLayout$VFormLayoutTable[0]/VTextField[0]</td>
+ <td>valid</td>
+</tr>
+<tr>
+ <td>pressSpecialKey</td>
+ <td>vaadin=runcomvaadintestscomponentswindowUndefinedHeightSubWindowAndContent::/VWindow[0]/FocusableScrollPanel[0]/VVerticalLayout[0]/ChildComponentContainer[0]/VForm[0]/VFormLayout[0]/VFormLayout$VFormLayoutTable[0]/VTextField[0]</td>
+ <td>enter</td>
+</tr>
+<tr>
+ <td>screenCapture</td>
+ <td></td>
+ <td>form_full_width_2_valid</td>
+</tr>
+
+</tbody></table>
+</body>
+</html>
diff --git a/tests/testbench/com/vaadin/tests/components/window/UndefinedHeightSubWindowAndContent.java b/tests/testbench/com/vaadin/tests/components/window/UndefinedHeightSubWindowAndContent.java
new file mode 100644
index 0000000000..ed259b2f4c
--- /dev/null
+++ b/tests/testbench/com/vaadin/tests/components/window/UndefinedHeightSubWindowAndContent.java
@@ -0,0 +1,58 @@
+package com.vaadin.tests.components.window;
+
+import com.vaadin.data.Validator;
+import com.vaadin.tests.components.TestBase;
+import com.vaadin.ui.Form;
+import com.vaadin.ui.TextField;
+import com.vaadin.ui.VerticalLayout;
+import com.vaadin.ui.Window;
+
+public class UndefinedHeightSubWindowAndContent extends TestBase {
+
+ @Override
+ protected void setup() {
+ Window subWindow = new Window("No scrollbars!");
+ subWindow.setWidth("300px");
+ subWindow.center();
+ subWindow.setModal(true);
+ VerticalLayout layout = new VerticalLayout();
+ layout.setWidth("100%");
+ subWindow.setContent(layout);
+
+ final Form form = new Form();
+ form.setImmediate(true);
+ form.setValidationVisible(true);
+ form.setCaption("This is a form");
+ form.setDescription("How do you do?");
+ final TextField field1 = new TextField("Write here");
+ field1.setImmediate(true);
+ field1.addValidator(new Validator() {
+
+ public void validate(Object value) throws InvalidValueException {
+ if (!isValid(value)) {
+ throw new InvalidValueException("FAIL!");
+ }
+ }
+
+ public boolean isValid(Object value) {
+ return field1.getValue().equals("valid");
+ }
+ });
+ form.addField("Field 1", field1);
+ layout.addComponent(form);
+
+ getMainWindow().addWindow(subWindow);
+ subWindow.bringToFront();
+ }
+
+ @Override
+ protected String getDescription() {
+ return "When both window and its content have undefined height, window must not reserve space for a scroll bar when it is not needed.";
+ }
+
+ @Override
+ protected Integer getTicketNumber() {
+ return 8852;
+ }
+
+}
diff --git a/tests/testbench/com/vaadin/tests/components/window/WindowClickEvents.html b/tests/testbench/com/vaadin/tests/components/window/WindowClickEvents.html
index f679779d4b..af5b9ec180 100644
--- a/tests/testbench/com/vaadin/tests/components/window/WindowClickEvents.html
+++ b/tests/testbench/com/vaadin/tests/components/window/WindowClickEvents.html
@@ -3,13 +3,13 @@
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head profile="http://selenium-ide.openqa.org/profiles/test-case">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
-<link rel="selenium.base" href="" />
-<title>New Test</title>
+<link rel="selenium.base" href="http://localhost:8070" />
+<title>WindowClickEvents</title>
</head>
<body>
<table cellpadding="1" cellspacing="1" border="1">
<thead>
-<tr><td rowspan="1" colspan="3">New Test</td></tr>
+<tr><td rowspan="1" colspan="3">WindowClickEvents</td></tr>
</thead><tbody>
<tr>
<td>setSpeed</td>
@@ -23,8 +23,8 @@
</tr>
<tr>
<td>mouseClick</td>
- <td>vaadin=runcomvaadintestscomponentswindowWindowClickEvents::/VVerticalLayout[0]/domChild[0]</td>
- <td>154,150</td>
+ <td>vaadin=runcomvaadintestscomponentswindowWindowClickEvents::/VVerticalLayout[0]/VLabel[0]</td>
+ <td>150,5</td>
</tr>
<tr>
<td>assertText</td>
@@ -72,6 +72,7 @@
<td>vaadin=runcomvaadintestscomponentswindowWindowClickEvents::PID_SLog_row_1</td>
<td>4. Click using left on Sub window</td>
</tr>
+
</tbody></table>
</body>
</html>
diff --git a/tests/testbench/com/vaadin/tests/components/window/WindowResizeListener.java b/tests/testbench/com/vaadin/tests/components/window/WindowResizeListener.java
index c6563f200f..ac6c313d29 100644
--- a/tests/testbench/com/vaadin/tests/components/window/WindowResizeListener.java
+++ b/tests/testbench/com/vaadin/tests/components/window/WindowResizeListener.java
@@ -2,13 +2,13 @@ package com.vaadin.tests.components.window;
import com.vaadin.data.Property;
import com.vaadin.data.Property.ValueChangeEvent;
+import com.vaadin.terminal.Page;
+import com.vaadin.terminal.Page.BrowserWindowResizeEvent;
import com.vaadin.tests.components.TestBase;
import com.vaadin.ui.Button;
import com.vaadin.ui.CheckBox;
import com.vaadin.ui.Label;
import com.vaadin.ui.Layout;
-import com.vaadin.ui.Root;
-import com.vaadin.ui.Root.BrowserWindowResizeEvent;
import com.vaadin.ui.Window;
public class WindowResizeListener extends TestBase {
@@ -33,7 +33,7 @@ public class WindowResizeListener extends TestBase {
final Label l = new Label();
getLayout().addComponent(l);
- getMainWindow().addListener(new Root.BrowserWindowResizeListener() {
+ getMainWindow().addListener(new Page.BrowserWindowResizeListener() {
public void browserWindowResized(BrowserWindowResizeEvent event) {
l.setValue("Current browser window size: "
+ getMainWindow().getBrowserWindowWidth() + " x "
diff --git a/tests/testbench/com/vaadin/tests/containers/TableWithFileSystemContainer.java b/tests/testbench/com/vaadin/tests/containers/TableWithFileSystemContainer.java
index 459c234c24..25d0053fb2 100644
--- a/tests/testbench/com/vaadin/tests/containers/TableWithFileSystemContainer.java
+++ b/tests/testbench/com/vaadin/tests/containers/TableWithFileSystemContainer.java
@@ -4,7 +4,6 @@ import java.io.File;
import com.vaadin.data.util.FilesystemContainer;
import com.vaadin.tests.components.TestBase;
-import com.vaadin.ui.Root.LegacyWindow;
import com.vaadin.ui.Table;
public class TableWithFileSystemContainer extends TestBase {
@@ -13,7 +12,6 @@ public class TableWithFileSystemContainer extends TestBase {
@Override
public void setup() {
- setMainWindow(new LegacyWindow(""));
Table table = new Table("Documents", new FilesystemContainer(new File(
testPath)));
table.setWidth("100%");
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);
+ }
+
+}
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
--- /dev/null
+++ b/tests/testbench/com/vaadin/tests/dd/ScrolledDropTarget.html.disabled
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);
+ }
+
+}
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 @@
</thead><tbody>
<tr>
<td>open</td>
- <td>/run/com.vaadin.tests.debug.DebugWindowPresent?restartApplication&amp;debug</td>
+ <td>/run/com.vaadin.tests.debug.DebugWindowPresent?restartApplication&amp;debug&amp;otherparam</td>
+ <td></td>
+</tr>
+<tr>
+ <td>assertElementPresent</td>
+ <td>vaadin=runcomvaadintestsdebugDebugWindowPresent::Root/VDebugConsole[0]</td>
+ <td></td>
+</tr>
+<tr>
+ <td>open</td>
+ <td>/run/com.vaadin.tests.debug.DebugWindowPresent?debug&amp;restartApplication</td>
<td></td>
</tr>
<tr>
@@ -31,6 +41,66 @@
<td>vaadin=runcomvaadintestsdebugDebugWindowPresent::Root/VDebugConsole[0]</td>
<td></td>
</tr>
+<tr>
+ <td>open</td>
+ <td>/run/com.vaadin.tests.debug.DebugWindowPresent?restartApplication&amp;mode=debug</td>
+ <td></td>
+</tr>
+<tr>
+ <td>assertElementNotPresent</td>
+ <td>vaadin=runcomvaadintestsdebugDebugWindowPresent::Root/VDebugConsole[0]</td>
+ <td></td>
+</tr>
+<tr>
+ <td>open</td>
+ <td>/run/com.vaadin.tests.debug.DebugWindowPresent?nodebug&amp;restartApplication</td>
+ <td></td>
+</tr>
+<tr>
+ <td>assertElementNotPresent</td>
+ <td>vaadin=runcomvaadintestsdebugDebugWindowPresent::Root/VDebugConsole[0]</td>
+ <td></td>
+</tr>
+<tr>
+ <td>open</td>
+ <td>/run/com.vaadin.tests.debug.DebugWindowPresent?restartApplication&amp;nodebug</td>
+ <td></td>
+</tr>
+<tr>
+ <td>assertElementNotPresent</td>
+ <td>vaadin=runcomvaadintestsdebugDebugWindowPresent::Root/VDebugConsole[0]</td>
+ <td></td>
+</tr>
+<tr>
+ <td>open</td>
+ <td>/run/com.vaadin.tests.debug.DebugWindowPresent?restartApplication&amp;debug=quiet</td>
+ <td></td>
+</tr>
+<tr>
+ <td>assertElementNotPresent</td>
+ <td>vaadin=runcomvaadintestsdebugDebugWindowPresent::Root/VDebugConsole[0]</td>
+ <td></td>
+</tr>
+<tr>
+ <td>open</td>
+ <td>/run/com.vaadin.tests.debug.DebugWindowPresent?debug=quiet&amp;restartApplication</td>
+ <td></td>
+</tr>
+<tr>
+ <td>assertElementNotPresent</td>
+ <td>vaadin=runcomvaadintestsdebugDebugWindowPresent::Root/VDebugConsole[0]</td>
+ <td></td>
+</tr>
+<tr>
+ <td>open</td>
+ <td>/run/com.vaadin.tests.debug.DebugWindowPresent?restartApplication&amp;debug=quiet#/asdf</td>
+ <td></td>
+</tr>
+<tr>
+ <td>assertElementNotPresent</td>
+ <td>vaadin=runcomvaadintestsdebugDebugWindowPresent::Root/VDebugConsole[0]</td>
+ <td></td>
+</tr>
</tbody></table>
</body>
</html>
diff --git a/tests/testbench/com/vaadin/tests/extensions/HelloWorldExtensionTest.java b/tests/testbench/com/vaadin/tests/extensions/HelloWorldExtensionTest.java
new file mode 100644
index 0000000000..b56e05b2a0
--- /dev/null
+++ b/tests/testbench/com/vaadin/tests/extensions/HelloWorldExtensionTest.java
@@ -0,0 +1,38 @@
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+package com.vaadin.tests.extensions;
+
+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 HelloWorldExtensionTest 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 Extension";
+ }
+
+ @Override
+ protected Integer getTicketNumber() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+}
diff --git a/tests/testbench/com/vaadin/tests/extensions/JavascriptManagerTest.html b/tests/testbench/com/vaadin/tests/extensions/JavascriptManagerTest.html
new file mode 100644
index 0000000000..7bdb8cd50f
--- /dev/null
+++ b/tests/testbench/com/vaadin/tests/extensions/JavascriptManagerTest.html
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head profile="http://selenium-ide.openqa.org/profiles/test-case">
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<link rel="selenium.base" href="http://localhost:8888/" />
+<title>New Test</title>
+</head>
+<body>
+<table cellpadding="1" cellspacing="1" border="1">
+<thead>
+<tr><td rowspan="1" colspan="3">New Test</td></tr>
+</thead><tbody>
+<tr>
+ <td>open</td>
+ <td>/run/com.vaadin.tests.extensions.JavascriptManagerTest?restartApplication</td>
+ <td></td>
+</tr>
+<tr>
+ <td>assertText</td>
+ <td>vaadin=runcomvaadintestsextensionsJavascriptManagerTest::/VVerticalLayout[0]/VVerticalLayout[0]/VVerticalLayout[0]/VLabel[4]</td>
+ <td>1. Got 4 arguments</td>
+</tr>
+<tr>
+ <td>assertText</td>
+ <td>vaadin=runcomvaadintestsextensionsJavascriptManagerTest::/VVerticalLayout[0]/VVerticalLayout[0]/VVerticalLayout[0]/VLabel[3]</td>
+ <td>2. Argument 1 as a number: 42</td>
+</tr>
+<tr>
+ <td>assertText</td>
+ <td>vaadin=runcomvaadintestsextensionsJavascriptManagerTest::/VVerticalLayout[0]/VVerticalLayout[0]/VVerticalLayout[0]/VLabel[2]</td>
+ <td>3. Argument 2 as a string: text</td>
+</tr>
+<tr>
+ <td>assertText</td>
+ <td>vaadin=runcomvaadintestsextensionsJavascriptManagerTest::/VVerticalLayout[0]/VVerticalLayout[0]/VVerticalLayout[0]/VLabel[1]</td>
+ <td>4. Argument 3.p as a boolean: true</td>
+</tr>
+<tr>
+ <td>assertText</td>
+ <td>vaadin=runcomvaadintestsextensionsJavascriptManagerTest::/VVerticalLayout[0]/VVerticalLayout[0]/VVerticalLayout[0]/VLabel[0]</td>
+ <td>5. Argument 4 is JSONObject.NULL: true</td>
+</tr>
+
+</tbody></table>
+</body>
+</html>
diff --git a/tests/testbench/com/vaadin/tests/extensions/JavascriptManagerTest.java b/tests/testbench/com/vaadin/tests/extensions/JavascriptManagerTest.java
new file mode 100644
index 0000000000..65f0735ab5
--- /dev/null
+++ b/tests/testbench/com/vaadin/tests/extensions/JavascriptManagerTest.java
@@ -0,0 +1,50 @@
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+
+package com.vaadin.tests.extensions;
+
+import com.vaadin.external.json.JSONArray;
+import com.vaadin.external.json.JSONException;
+import com.vaadin.external.json.JSONObject;
+import com.vaadin.terminal.WrappedRequest;
+import com.vaadin.tests.components.AbstractTestRoot;
+import com.vaadin.tests.util.Log;
+import com.vaadin.ui.JavaScript;
+import com.vaadin.ui.JavaScriptCallback;
+
+public class JavascriptManagerTest extends AbstractTestRoot {
+
+ private Log log = new Log(5);
+
+ @Override
+ protected void setup(WrappedRequest request) {
+ addComponent(log);
+ final JavaScript js = JavaScript.getCurrent();
+ js.addCallback("testing.doTest", new JavaScriptCallback() {
+ public void call(JSONArray arguments) throws JSONException {
+ log.log("Got " + arguments.length() + " arguments");
+ log.log("Argument 1 as a number: " + arguments.getInt(0));
+ log.log("Argument 2 as a string: " + arguments.getString(1));
+ log.log("Argument 3.p as a boolean: "
+ + arguments.getJSONObject(2).getBoolean("p"));
+ log.log("Argument 4 is JSONObject.NULL: "
+ + (arguments.get(3) == JSONObject.NULL));
+ js.removeCallback("testing.doTest");
+ }
+ });
+ js.execute("window.testing.doTest(42, 'text', {p: true}, null)");
+ }
+
+ @Override
+ protected String getTestDescription() {
+ return "Test javascript callback handling by adding a callback and invoking the javascript.";
+ }
+
+ @Override
+ protected Integer getTicketNumber() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+}
diff --git a/tests/testbench/com/vaadin/tests/extensions/SimpleJavaScriptExtensionTest.java b/tests/testbench/com/vaadin/tests/extensions/SimpleJavaScriptExtensionTest.java
new file mode 100644
index 0000000000..bbfe3f0f46
--- /dev/null
+++ b/tests/testbench/com/vaadin/tests/extensions/SimpleJavaScriptExtensionTest.java
@@ -0,0 +1,116 @@
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+
+package com.vaadin.tests.extensions;
+
+import com.vaadin.annotations.LoadScripts;
+import com.vaadin.external.json.JSONArray;
+import com.vaadin.external.json.JSONException;
+import com.vaadin.terminal.AbstractJavaScriptExtension;
+import com.vaadin.terminal.WrappedRequest;
+import com.vaadin.terminal.gwt.client.JavaScriptExtensionState;
+import com.vaadin.terminal.gwt.client.communication.ClientRpc;
+import com.vaadin.terminal.gwt.client.communication.ServerRpc;
+import com.vaadin.tests.components.AbstractTestRoot;
+import com.vaadin.ui.Button;
+import com.vaadin.ui.Button.ClickEvent;
+import com.vaadin.ui.JavaScriptCallback;
+import com.vaadin.ui.Notification;
+
+@LoadScripts({ "/statictestfiles/jsextension.js" })
+public class SimpleJavaScriptExtensionTest extends AbstractTestRoot {
+
+ public static class SimpleJavaScriptExtensionState extends
+ JavaScriptExtensionState {
+ private String prefix;
+
+ public void setPrefix(String prefix) {
+ this.prefix = prefix;
+ }
+
+ public String getPrefix() {
+ return prefix;
+ }
+ }
+
+ public static interface SimpleJavaScriptExtensionClientRpc extends
+ ClientRpc {
+ public void greet(String message);
+ }
+
+ public static interface SimpleJavaScriptExtensionServerRpc extends
+ ServerRpc {
+ public void greet(String message);
+ }
+
+ public static class SimpleJavascriptExtension extends
+ AbstractJavaScriptExtension {
+
+ public SimpleJavascriptExtension() {
+ registerRpc(new SimpleJavaScriptExtensionServerRpc() {
+ public void greet(String message) {
+ Notification.show(getState().getPrefix() + message);
+ }
+ });
+ registerCallback("greetToServer", new JavaScriptCallback() {
+ public void call(JSONArray arguments) throws JSONException {
+ Notification.show(getState().getPrefix()
+ + arguments.getString(0));
+ }
+ });
+ }
+
+ @Override
+ public SimpleJavaScriptExtensionState getState() {
+ return (SimpleJavaScriptExtensionState) super.getState();
+ }
+
+ public void setPrefix(String prefix) {
+ getState().setPrefix(prefix);
+ requestRepaint();
+ }
+
+ public void greetRpc(String message) {
+ getRpcProxy(SimpleJavaScriptExtensionClientRpc.class)
+ .greet(message);
+ }
+
+ public void greetCallback(String message) {
+ invokeCallback("greetToClient", message);
+ }
+ }
+
+ @Override
+ protected void setup(WrappedRequest request) {
+ final SimpleJavascriptExtension simpleJavascriptExtension = new SimpleJavascriptExtension();
+ simpleJavascriptExtension.setPrefix("Prefix: ");
+ addExtension(simpleJavascriptExtension);
+ addComponent(new Button("Send rpc greeting",
+ new Button.ClickListener() {
+ public void buttonClick(ClickEvent event) {
+ simpleJavascriptExtension.greetRpc("Rpc greeting");
+ }
+ }));
+ addComponent(new Button("Send callback greeting",
+ new Button.ClickListener() {
+ public void buttonClick(ClickEvent event) {
+ simpleJavascriptExtension
+ .greetCallback("Callback greeting");
+ }
+ }));
+ }
+
+ @Override
+ protected String getTestDescription() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ protected Integer getTicketNumber() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+}
diff --git a/tests/testbench/com/vaadin/tests/fieldgroup/AbstractBeanFieldGroupTest.java b/tests/testbench/com/vaadin/tests/fieldgroup/AbstractBeanFieldGroupTest.java
index 584ce0ec36..b73a29efea 100644
--- a/tests/testbench/com/vaadin/tests/fieldgroup/AbstractBeanFieldGroupTest.java
+++ b/tests/testbench/com/vaadin/tests/fieldgroup/AbstractBeanFieldGroupTest.java
@@ -7,7 +7,7 @@ import com.vaadin.tests.util.Log;
import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.Button.ClickListener;
-import com.vaadin.ui.Root;
+import com.vaadin.ui.Notification;
public abstract class AbstractBeanFieldGroupTest extends TestBase {
@@ -64,7 +64,7 @@ public abstract class AbstractBeanFieldGroupTest extends TestBase {
} catch (CommitException e) {
msg = "Commit failed: " + e.getMessage();
}
- Root.getCurrentRoot().showNotification(msg);
+ Notification.show(msg);
log.log(msg);
}
diff --git a/tests/testbench/com/vaadin/tests/fieldgroup/BasicPersonForm.java b/tests/testbench/com/vaadin/tests/fieldgroup/BasicPersonForm.java
index f95c172348..c86cb6f5e8 100644
--- a/tests/testbench/com/vaadin/tests/fieldgroup/BasicPersonForm.java
+++ b/tests/testbench/com/vaadin/tests/fieldgroup/BasicPersonForm.java
@@ -18,8 +18,8 @@ import com.vaadin.tests.data.bean.Sex;
import com.vaadin.tests.util.Log;
import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickEvent;
+import com.vaadin.ui.Notification;
import com.vaadin.ui.Panel;
-import com.vaadin.ui.Root;
import com.vaadin.ui.Table;
import com.vaadin.ui.TextArea;
import com.vaadin.ui.TextField;
@@ -125,7 +125,7 @@ public class BasicPersonForm extends TestBase {
} catch (CommitException e) {
msg = "Commit failed: " + e.getMessage();
}
- Root.getCurrentRoot().showNotification(msg);
+ Notification.show(msg);
log.log(msg);
}
diff --git a/tests/testbench/com/vaadin/tests/fieldgroup/FieldBinderWithBeanValidation.java b/tests/testbench/com/vaadin/tests/fieldgroup/FieldBinderWithBeanValidation.java
index 9ff553ce61..6c6cd8024b 100644
--- a/tests/testbench/com/vaadin/tests/fieldgroup/FieldBinderWithBeanValidation.java
+++ b/tests/testbench/com/vaadin/tests/fieldgroup/FieldBinderWithBeanValidation.java
@@ -13,7 +13,7 @@ import com.vaadin.tests.data.bean.Sex;
import com.vaadin.tests.util.Log;
import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickEvent;
-import com.vaadin.ui.Root;
+import com.vaadin.ui.Notification;
import com.vaadin.ui.Table;
import com.vaadin.ui.TextArea;
import com.vaadin.ui.TextField;
@@ -52,7 +52,7 @@ public class FieldBinderWithBeanValidation extends TestBase {
} catch (CommitException e) {
msg = "Commit failed: " + e.getMessage();
}
- Root.getCurrentRoot().showNotification(msg);
+ Notification.show(msg);
log.log(msg);
}
diff --git a/tests/testbench/com/vaadin/tests/integration/EmbedSizeTest.java b/tests/testbench/com/vaadin/tests/integration/EmbedSizeTest.java
index eb26faacc0..1b6d384e70 100644
--- a/tests/testbench/com/vaadin/tests/integration/EmbedSizeTest.java
+++ b/tests/testbench/com/vaadin/tests/integration/EmbedSizeTest.java
@@ -2,11 +2,12 @@ package com.vaadin.tests.integration;
import com.vaadin.data.Property.ValueChangeEvent;
import com.vaadin.data.Property.ValueChangeListener;
+import com.vaadin.terminal.Page;
+import com.vaadin.terminal.Page.BrowserWindowResizeEvent;
import com.vaadin.tests.components.TestBase;
import com.vaadin.tests.util.Log;
import com.vaadin.ui.CheckBox;
-import com.vaadin.ui.Root;
-import com.vaadin.ui.Root.BrowserWindowResizeEvent;
+import com.vaadin.ui.Root.LegacyWindow;
public class EmbedSizeTest extends TestBase {
@@ -14,14 +15,13 @@ public class EmbedSizeTest extends TestBase {
@Override
protected void setup() {
- Root mainWindow = getMainWindow();
+ LegacyWindow mainWindow = getMainWindow();
mainWindow.setSizeUndefined();
mainWindow.getContent().setSizeUndefined();
mainWindow.setImmediate(true);
CheckBox lazyCheckBox = new CheckBox("Lazy resize");
lazyCheckBox.addListener(new ValueChangeListener() {
-
public void valueChange(ValueChangeEvent event) {
CheckBox cb = (CheckBox) event.getProperty();
Boolean resizeLazy = cb.getValue();
@@ -34,11 +34,10 @@ public class EmbedSizeTest extends TestBase {
addComponent(lazyCheckBox);
addComponent(log);
- mainWindow.addListener(new Root.BrowserWindowResizeListener() {
+ mainWindow.addListener(new Page.BrowserWindowResizeListener() {
public void browserWindowResized(BrowserWindowResizeEvent event) {
log.log("Resize event: " + event.getWidth() + " x "
+ event.getHeight());
-
}
});
}
diff --git a/tests/testbench/com/vaadin/tests/integration/JSR286PortletApplication.java b/tests/testbench/com/vaadin/tests/integration/JSR286PortletRoot.java
index 7ba6f2c0c0..b4de4fd3da 100644
--- a/tests/testbench/com/vaadin/tests/integration/JSR286PortletApplication.java
+++ b/tests/testbench/com/vaadin/tests/integration/JSR286PortletRoot.java
@@ -18,8 +18,8 @@ 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.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;
@@ -28,17 +28,16 @@ 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;
+import com.vaadin.ui.VerticalLayout;
/**
* Adapted from old PortletDemo to support integration testing.
*/
-public class JSR286PortletApplication extends Application.LegacyApplication {
+public class JSR286PortletRoot extends Root {
- LegacyWindow main = new LegacyWindow();
TextField tf = new TextField("Some value");
Label userInfo = new Label();
Link portletEdit = new Link();
@@ -46,16 +45,19 @@ public class JSR286PortletApplication extends Application.LegacyApplication {
Link someAction = null;
@Override
- public void init() {
- setMainWindow(main);
-
+ 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(this));
+ new FlagSeResource(getApplication()));
main.addComponent(appResourceTest);
Embedded specialNameResourceTest = new Embedded(
"Test ApplicationResources with special names",
- new SpecialNameResource(this));
+ new SpecialNameResource(getApplication()));
main.addComponent(specialNameResourceTest);
userInfo.setCaption("User info");
@@ -79,11 +81,12 @@ public class JSR286PortletApplication extends Application.LegacyApplication {
});
main.addComponent(upload);
- if (getContext() instanceof PortletApplicationContext2) {
- PortletApplicationContext2 ctx = (PortletApplicationContext2) getContext();
- ctx.addPortletListener(this, new DemoPortletListener());
+ if (getApplication().getContext() instanceof PortletApplicationContext2) {
+ PortletApplicationContext2 ctx = (PortletApplicationContext2) getApplication()
+ .getContext();
+ ctx.addPortletListener(getApplication(), new DemoPortletListener());
} else {
- getMainWindow().showNotification("Not inited via Portal!",
+ Notification.show("Not inited via Portal!",
Notification.TYPE_ERROR_MESSAGE);
}
@@ -93,7 +96,7 @@ public class JSR286PortletApplication extends Application.LegacyApplication {
public void handleActionRequest(ActionRequest request,
ActionResponse response, Root window) {
- main.addComponent(new Label("Action received"));
+ getContent().addComponent(new Label("Action received"));
}
public void handleRenderRequest(RenderRequest request,
@@ -106,11 +109,10 @@ public class JSR286PortletApplication extends Application.LegacyApplication {
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);
+ new Notification("Portlet status", "Mode: "
+ + request.getPortletMode() + " State: "
+ + request.getWindowState(),
+ Notification.TYPE_WARNING_MESSAGE).show(getPage());
// Display current user info
Map<?, ?> uinfo = (Map<?, ?>) request
@@ -160,7 +162,9 @@ public class JSR286PortletApplication extends Application.LegacyApplication {
try {
someAction = new Link("An action", new ExternalResource(
url.toString()));
- main.addComponent(someAction);
+ someAction.setDebugId("someAction");
+
+ addComponent(someAction);
} catch (Exception e) {
// Oops
System.err.println("Could not create someAction: " + e);
diff --git a/tests/testbench/com/vaadin/tests/integration/LiferayThemeDemo.java b/tests/testbench/com/vaadin/tests/integration/LiferayThemeDemo.java
index 0250658bc9..9397206f1e 100644
--- a/tests/testbench/com/vaadin/tests/integration/LiferayThemeDemo.java
+++ b/tests/testbench/com/vaadin/tests/integration/LiferayThemeDemo.java
@@ -9,6 +9,7 @@ import com.vaadin.data.Property;
import com.vaadin.data.Property.ValueChangeEvent;
import com.vaadin.event.Action;
import com.vaadin.terminal.ExternalResource;
+import com.vaadin.terminal.Page;
import com.vaadin.terminal.Resource;
import com.vaadin.terminal.ThemeResource;
import com.vaadin.terminal.gwt.client.ui.label.ContentMode;
@@ -595,11 +596,8 @@ public class LiferayThemeDemo extends Application.LegacyApplication {
Button show = new Button("Humanized Notification",
new Button.ClickListener() {
public void buttonClick(ClickEvent event) {
- event.getButton()
- .getRoot()
- .showNotification(title.getValue(),
- message.getValue());
-
+ new Notification(title.getValue(), message.getValue())
+ .show(Page.getCurrent());
}
});
l.addComponent(show);
@@ -607,10 +605,9 @@ public class LiferayThemeDemo extends Application.LegacyApplication {
l.addComponent(new Label("Warning", ContentMode.XHTML));
show = new Button("Warning Notification", new Button.ClickListener() {
public void buttonClick(ClickEvent event) {
- event.getButton()
- .getRoot()
- .showNotification(title.getValue(), message.getValue(),
- Notification.TYPE_WARNING_MESSAGE);
+ new Notification(title.getValue(), message.getValue(),
+ Notification.TYPE_WARNING_MESSAGE).show(Page
+ .getCurrent());
}
});
@@ -619,10 +616,8 @@ public class LiferayThemeDemo extends Application.LegacyApplication {
l.addComponent(new Label("Error", ContentMode.XHTML));
show = new Button("Error Notification", new Button.ClickListener() {
public void buttonClick(ClickEvent event) {
- event.getButton()
- .getRoot()
- .showNotification(title.getValue(), message.getValue(),
- Notification.TYPE_ERROR_MESSAGE);
+ new Notification(title.getValue(), message.getValue(),
+ Notification.TYPE_ERROR_MESSAGE).show(Page.getCurrent());
}
});
@@ -631,10 +626,9 @@ public class LiferayThemeDemo extends Application.LegacyApplication {
l.addComponent(new Label("Tray", ContentMode.XHTML));
show = new Button("Tray Notification", new Button.ClickListener() {
public void buttonClick(ClickEvent event) {
- event.getButton()
- .getRoot()
- .showNotification(title.getValue(), message.getValue(),
- Notification.TYPE_TRAY_NOTIFICATION);
+ new Notification(title.getValue(), message.getValue(),
+ Notification.TYPE_TRAY_NOTIFICATION).show(Page
+ .getCurrent());
}
});
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..20967203bc
--- /dev/null
+++ b/tests/testbench/com/vaadin/tests/integration/PortletSizeInLiferayFreeformLayoutApplication.java
@@ -0,0 +1,31 @@
+package com.vaadin.tests.integration;
+
+import com.vaadin.Application.LegacyApplication;
+import com.vaadin.ui.Label;
+import com.vaadin.ui.Root.LegacyWindow;
+import com.vaadin.ui.VerticalLayout;
+
+/**
+ * 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
+ LegacyApplication {
+ @Override
+ public void init() {
+ LegacyWindow mainWindow = new LegacyWindow("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);
+ }
+
+}
diff --git a/tests/testbench/com/vaadin/tests/layouts/GridLayoutCaptions.java b/tests/testbench/com/vaadin/tests/layouts/GridLayoutCaptions.java
index 1fe33d62ca..9ad9adb43a 100644
--- a/tests/testbench/com/vaadin/tests/layouts/GridLayoutCaptions.java
+++ b/tests/testbench/com/vaadin/tests/layouts/GridLayoutCaptions.java
@@ -28,6 +28,7 @@ public class GridLayoutCaptions extends TestBase {
private CssLayout wrapper2 = new CssLayout();
private FormFieldFactory fff = new FormFieldFactory() {
+
public Field<?> createField(Item item, Object propertyId,
Component uiContext) {
@@ -177,11 +178,10 @@ public class GridLayoutCaptions extends TestBase {
@Override
protected void setup() {
- LegacyWindow mainWindow = new LegacyWindow(
- "Formlayoutcaptionboom Application");
+ LegacyWindow mainWindow = getMainWindow();
+
Label label = new Label("Hello Vaadin user");
mainWindow.addComponent(label);
- setMainWindow(mainWindow);
DataPOJO forDemo = new DataPOJO();
@@ -194,6 +194,7 @@ public class GridLayoutCaptions extends TestBase {
mainWindow.addComponent(aFormWithGl);
Button b = new Button("Give me an error!", new Button.ClickListener() {
+
public void buttonClick(ClickEvent event) {
aFormWithGl.createErrors();
@@ -203,6 +204,7 @@ public class GridLayoutCaptions extends TestBase {
Button b2 = new Button("Get rid of an error!",
new Button.ClickListener() {
+
public void buttonClick(ClickEvent event) {
aFormWithGl.clearErrors();
diff --git a/tests/testbench/com/vaadin/tests/layouts/GridLayoutExpandRatioModification.java b/tests/testbench/com/vaadin/tests/layouts/GridLayoutExpandRatioModification.java
index f7f4ac2d4c..314a8d7b03 100644
--- a/tests/testbench/com/vaadin/tests/layouts/GridLayoutExpandRatioModification.java
+++ b/tests/testbench/com/vaadin/tests/layouts/GridLayoutExpandRatioModification.java
@@ -21,10 +21,10 @@ public class GridLayoutExpandRatioModification extends TestBase implements
@Override
public void setup() {
- LegacyWindow main = new LegacyWindow("The Main Window");
+ LegacyWindow main = getMainWindow();
+
mainLayout = new GridLayout(3, 3);
main.setContent(mainLayout);
- setMainWindow(main);
// The upper layout
vl1 = new VerticalLayout();
diff --git a/tests/testbench/com/vaadin/tests/layouts/TestLayoutClickListeners.html b/tests/testbench/com/vaadin/tests/layouts/TestLayoutClickListeners.html
index 317e13ac80..2cc695e4fa 100644
--- a/tests/testbench/com/vaadin/tests/layouts/TestLayoutClickListeners.html
+++ b/tests/testbench/com/vaadin/tests/layouts/TestLayoutClickListeners.html
@@ -59,8 +59,8 @@
</tr>
<tr>
<td>mouseClick</td>
- <td>vaadin=runcomvaadintestslayoutsTestLayoutClickListeners::/VVerticalLayout[0]/ChildComponentContainer[1]/VHorizontalLayout[0]/ChildComponentContainer[0]/VVerticalLayout[0]/ChildComponentContainer[1]/VGridLayout[0]/domChild[0]</td>
- <td>87,42</td>
+ <td>vaadin=runcomvaadintestslayoutsTestLayoutClickListeners::/VVerticalLayout[0]/ChildComponentContainer[1]/VHorizontalLayout[0]/ChildComponentContainer[0]/VVerticalLayout[0]/ChildComponentContainer[1]/VGridLayout[0]/domChild[0]/domChild[0]</td>
+ <td>491,79</td>
</tr>
<tr>
<td>waitForVaadin</td>
@@ -185,6 +185,130 @@
<td>vaadin=runcomvaadintestslayoutsTestLayoutClickListeners::/VVerticalLayout[0]/ChildComponentContainer[0]/VVerticalLayout[0]/ChildComponentContainer[0]/VLabel[0]</td>
<td>exact:Button A button with its own click listener was clicked</td>
</tr>
+<!--Drag in GridLayout-->
+<tr>
+ <td>drag</td>
+ <td>vaadin=runcomvaadintestslayoutsTestLayoutClickListeners::/VVerticalLayout[0]/ChildComponentContainer[1]/VHorizontalLayout[0]/ChildComponentContainer[0]/VVerticalLayout[0]/ChildComponentContainer[1]/VGridLayout[0]/AbsolutePanel[0]/ChildComponentContainer[0]/VLabel[0]</td>
+ <td>40,8</td>
+</tr>
+<tr>
+ <td>drop</td>
+ <td>vaadin=runcomvaadintestslayoutsTestLayoutClickListeners::/VVerticalLayout[0]/ChildComponentContainer[1]/VHorizontalLayout[0]/ChildComponentContainer[0]/VVerticalLayout[0]/ChildComponentContainer[1]/VGridLayout[0]/AbsolutePanel[0]/ChildComponentContainer[0]/VLabel[0]</td>
+ <td>40,8</td>
+</tr>
+<tr>
+ <td>assertText</td>
+ <td>vaadin=runcomvaadintestslayoutsTestLayoutClickListeners::PID_SLog_row_0</td>
+ <td>exact:GridLayout: left click on This is label 1</td>
+</tr>
+<tr>
+ <td>drag</td>
+ <td>vaadin=runcomvaadintestslayoutsTestLayoutClickListeners::/VVerticalLayout[0]/ChildComponentContainer[1]/VHorizontalLayout[0]/ChildComponentContainer[0]/VVerticalLayout[0]/ChildComponentContainer[1]/VGridLayout[0]/AbsolutePanel[0]/ChildComponentContainer[0]/VLabel[0]</td>
+ <td>24,7</td>
+</tr>
+<tr>
+ <td>drop</td>
+ <td>vaadin=runcomvaadintestslayoutsTestLayoutClickListeners::/VVerticalLayout[0]/ChildComponentContainer[1]/VHorizontalLayout[0]/ChildComponentContainer[0]/VVerticalLayout[0]/ChildComponentContainer[1]/VGridLayout[0]/AbsolutePanel[0]/ChildComponentContainer[4]/VTextField[0]</td>
+ <td>46,13</td>
+</tr>
+<tr>
+ <td>assertText</td>
+ <td>vaadin=runcomvaadintestslayoutsTestLayoutClickListeners::PID_SLog_row_0</td>
+ <td>exact:GridLayout: left click on This is label 1</td>
+</tr>
+<!--Drag in VerticalLayout-->
+<tr>
+ <td>drag</td>
+ <td>vaadin=runcomvaadintestslayoutsTestLayoutClickListeners::/VVerticalLayout[0]/ChildComponentContainer[1]/VHorizontalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[4]/VTextField[0]</td>
+ <td>25,9</td>
+</tr>
+<tr>
+ <td>drop</td>
+ <td>vaadin=runcomvaadintestslayoutsTestLayoutClickListeners::/VVerticalLayout[0]/ChildComponentContainer[1]/VHorizontalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[4]/VTextField[0]</td>
+ <td>25,9</td>
+</tr>
+<tr>
+ <td>assertText</td>
+ <td>vaadin=runcomvaadintestslayoutsTestLayoutClickListeners::PID_SLog_row_0</td>
+ <td>exact:VerticalLayout: left click on This is tf5</td>
+</tr>
+<tr>
+ <td>drag</td>
+ <td>vaadin=runcomvaadintestslayoutsTestLayoutClickListeners::/VVerticalLayout[0]/ChildComponentContainer[1]/VHorizontalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/domChild[0]/domChild[8]/domChild[0]/domChild[0]</td>
+ <td>28,11</td>
+</tr>
+<tr>
+ <td>drop</td>
+ <td>vaadin=runcomvaadintestslayoutsTestLayoutClickListeners::/VVerticalLayout[0]/ChildComponentContainer[1]/VHorizontalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[8]/VTextField[0]</td>
+ <td>39,7</td>
+</tr>
+<tr>
+ <td>assertText</td>
+ <td>vaadin=runcomvaadintestslayoutsTestLayoutClickListeners::PID_SLog_row_0</td>
+ <td>exact:VerticalLayout: left click on This is tf5</td>
+</tr>
+<!--Drag in AbsoluteLayout-->
+<tr>
+ <td>drag</td>
+ <td>vaadin=runcomvaadintestslayoutsTestLayoutClickListeners::/VVerticalLayout[0]/ChildComponentContainer[1]/VHorizontalLayout[0]/ChildComponentContainer[2]/VAbsoluteLayout[0]/domChild[0]/domChild[0]/domChild[1]/domChild[0]</td>
+ <td>21,9</td>
+</tr>
+<tr>
+ <td>drop</td>
+ <td>vaadin=runcomvaadintestslayoutsTestLayoutClickListeners::/VVerticalLayout[0]/ChildComponentContainer[1]/VHorizontalLayout[0]/ChildComponentContainer[2]/VAbsoluteLayout[0]/domChild[0]/domChild[0]/domChild[1]/domChild[0]</td>
+ <td>21,9</td>
+</tr>
+<tr>
+ <td>assertText</td>
+ <td>vaadin=runcomvaadintestslayoutsTestLayoutClickListeners::PID_SLog_row_0</td>
+ <td>exact:AbsoluteLayout: left click on This is its caption</td>
+</tr>
+<tr>
+ <td>drag</td>
+ <td>vaadin=runcomvaadintestslayoutsTestLayoutClickListeners::/VVerticalLayout[0]/ChildComponentContainer[1]/VHorizontalLayout[0]/ChildComponentContainer[2]/VAbsoluteLayout[0]/VAbsoluteLayout$AbsoluteWrapper[0]/VTextField[0]</td>
+ <td>54,7</td>
+</tr>
+<tr>
+ <td>drop</td>
+ <td>vaadin=runcomvaadintestslayoutsTestLayoutClickListeners::/VVerticalLayout[0]/ChildComponentContainer[1]/VHorizontalLayout[0]/ChildComponentContainer[2]/VAbsoluteLayout[0]/VAbsoluteLayout$AbsoluteWrapper[1]/VTextField[0]</td>
+ <td>52,10</td>
+</tr>
+<tr>
+ <td>assertText</td>
+ <td>vaadin=runcomvaadintestslayoutsTestLayoutClickListeners::PID_SLog_row_0</td>
+ <td>exact:AbsoluteLayout: left click on This is its caption</td>
+</tr>
+<!--Drag in CSSLayout-->
+<tr>
+ <td>drag</td>
+ <td>vaadin=runcomvaadintestslayoutsTestLayoutClickListeners::/VVerticalLayout[0]/ChildComponentContainer[1]/VHorizontalLayout[0]/ChildComponentContainer[3]/VCssLayout[0]/VCssLayout$FlowPane[0]/VTextField[0]</td>
+ <td>51,7</td>
+</tr>
+<tr>
+ <td>drop</td>
+ <td>vaadin=runcomvaadintestslayoutsTestLayoutClickListeners::/VVerticalLayout[0]/ChildComponentContainer[1]/VHorizontalLayout[0]/ChildComponentContainer[3]/VCssLayout[0]/VCssLayout$FlowPane[0]/VTextField[0]</td>
+ <td>51,7</td>
+</tr>
+<tr>
+ <td>assertText</td>
+ <td>vaadin=runcomvaadintestslayoutsTestLayoutClickListeners::PID_SLog_row_0</td>
+ <td>exact:CSSLayout: left click on This is its caption</td>
+</tr>
+<tr>
+ <td>drag</td>
+ <td>vaadin=runcomvaadintestslayoutsTestLayoutClickListeners::/VVerticalLayout[0]/ChildComponentContainer[1]/VHorizontalLayout[0]/ChildComponentContainer[3]/VCssLayout[0]/domChild[0]/domChild[0]/domChild[2]/domChild[0]</td>
+ <td>31,7</td>
+</tr>
+<tr>
+ <td>drop</td>
+ <td>vaadin=runcomvaadintestslayoutsTestLayoutClickListeners::/VVerticalLayout[0]/ChildComponentContainer[1]/VHorizontalLayout[0]/ChildComponentContainer[3]/VCssLayout[0]/VCssLayout$FlowPane[0]/VTextField[1]</td>
+ <td>33,7</td>
+</tr>
+<tr>
+ <td>assertText</td>
+ <td>vaadin=runcomvaadintestslayoutsTestLayoutClickListeners::PID_SLog_row_0</td>
+ <td>exact:CSSLayout: left click on This is its caption</td>
+</tr>
</tbody></table>
</body>
</html>
diff --git a/tests/testbench/com/vaadin/tests/layouts/VerticalLayoutExpandRatioModification.java b/tests/testbench/com/vaadin/tests/layouts/VerticalLayoutExpandRatioModification.java
index d41b288e03..44a1e27cb8 100644
--- a/tests/testbench/com/vaadin/tests/layouts/VerticalLayoutExpandRatioModification.java
+++ b/tests/testbench/com/vaadin/tests/layouts/VerticalLayoutExpandRatioModification.java
@@ -20,10 +20,10 @@ public class VerticalLayoutExpandRatioModification extends TestBase implements
@Override
public void setup() {
- LegacyWindow main = new LegacyWindow("The Main Window");
+ LegacyWindow main = getMainWindow();
+
mainLayout = new VerticalLayout();
main.setContent(mainLayout);
- setMainWindow(main);
// The upper layout
vl1 = new VerticalLayout();
diff --git a/tests/testbench/com/vaadin/tests/minitutorials/v7a1/AutoGeneratingForm.java b/tests/testbench/com/vaadin/tests/minitutorials/v7a1/AutoGeneratingForm.java
new file mode 100644
index 0000000000..8eef5c08e8
--- /dev/null
+++ b/tests/testbench/com/vaadin/tests/minitutorials/v7a1/AutoGeneratingForm.java
@@ -0,0 +1,77 @@
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+
+package com.vaadin.tests.minitutorials.v7a1;
+
+import com.vaadin.data.fieldgroup.BeanFieldGroup;
+import com.vaadin.data.fieldgroup.FieldGroup;
+import com.vaadin.data.util.BeanItem;
+import com.vaadin.terminal.WrappedRequest;
+import com.vaadin.ui.Root;
+
+/**
+ * Mini tutorial code for
+ * https://vaadin.com/wiki/-/wiki/Main/Auto%20generating%20
+ * a%20form%20based%20on%20a%20bean%20-%20Vaadin%206%20style%20Form
+ *
+ * @author Vaadin Ltd
+ * @version @VERSION@
+ * @since 7.0.0
+ */
+public class AutoGeneratingForm extends Root {
+
+ @Override
+ protected void init(WrappedRequest request) {
+ FieldGroup fieldGroup = new BeanFieldGroup<Person>(Person.class);
+
+ // We need an item data source before we create the fields to be able to
+ // find the properties, otherwise we have to specify them by hand
+ fieldGroup.setItemDataSource(new BeanItem<Person>(new Person("John",
+ "Doe", 34)));
+
+ // Loop through the properties, build fields for them and add the fields
+ // to this root
+ for (Object propertyId : fieldGroup.getUnboundPropertyIds()) {
+ addComponent(fieldGroup.buildAndBind(propertyId));
+ }
+ }
+
+}
+
+class Person {
+ private String firstName, lastName;
+ private int age;
+
+ // + setters and getters
+
+ public Person(String firstName, String lastName, int age) {
+ this.firstName = firstName;
+ this.lastName = lastName;
+ this.age = age;
+ }
+
+ public String getFirstName() {
+ return firstName;
+ }
+
+ public void setFirstName(String firstName) {
+ this.firstName = firstName;
+ }
+
+ public String getLastName() {
+ return lastName;
+ }
+
+ public void setLastName(String lastName) {
+ this.lastName = lastName;
+ }
+
+ public int getAge() {
+ return age;
+ }
+
+ public void setAge(int age) {
+ this.age = age;
+ }
+}
diff --git a/tests/testbench/com/vaadin/tests/minitutorials/v7a1/BasicApplication.java b/tests/testbench/com/vaadin/tests/minitutorials/v7a1/BasicApplication.java
new file mode 100644
index 0000000000..3907209097
--- /dev/null
+++ b/tests/testbench/com/vaadin/tests/minitutorials/v7a1/BasicApplication.java
@@ -0,0 +1,28 @@
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+
+package com.vaadin.tests.minitutorials.v7a1;
+
+import com.vaadin.terminal.WrappedRequest;
+import com.vaadin.ui.Label;
+import com.vaadin.ui.Root;
+import com.vaadin.ui.VerticalLayout;
+
+/**
+ * Mini tutorial code for
+ * https://vaadin.com/wiki/-/wiki/Main/Creating%20a%20basic%20application
+ *
+ * @author Vaadin Ltd
+ * @version @VERSION@
+ * @since 7.0.0
+ */
+public class BasicApplication extends Root {
+
+ @Override
+ protected void init(WrappedRequest request) {
+ VerticalLayout view = new VerticalLayout();
+ view.addComponent(new Label("Hello Vaadin!"));
+ setContent(view);
+ }
+}
diff --git a/tests/testbench/com/vaadin/tests/minitutorials/v7a1/CreatingPreserveState.java b/tests/testbench/com/vaadin/tests/minitutorials/v7a1/CreatingPreserveState.java
new file mode 100644
index 0000000000..c175fd6065
--- /dev/null
+++ b/tests/testbench/com/vaadin/tests/minitutorials/v7a1/CreatingPreserveState.java
@@ -0,0 +1,31 @@
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+
+package com.vaadin.tests.minitutorials.v7a1;
+
+import com.vaadin.terminal.WrappedRequest;
+import com.vaadin.ui.Root;
+import com.vaadin.ui.TextField;
+
+/**
+ * Mini tutorial code for
+ * https://vaadin.com/wiki/-/wiki/Main/Creating%20an%20application
+ * %20that%20preserves%20state%20on%20refresh
+ *
+ * @author Vaadin Ltd
+ * @version @VERSION@
+ * @since 7.0.0
+ */
+public class CreatingPreserveState extends Root {
+ private static int windowCounter = 0;
+
+ @Override
+ public void init(WrappedRequest request) {
+ TextField tf = new TextField("Window #" + (++windowCounter));
+ tf.setImmediate(true);
+ getContent().addComponent(tf);
+ getApplication().setRootPreserved(true);
+ }
+
+}
diff --git a/tests/testbench/com/vaadin/tests/minitutorials/CustomConverterFactoryRoot.java b/tests/testbench/com/vaadin/tests/minitutorials/v7a1/CustomConverterFactoryRoot.java
index de32a817a1..89b4a0f8db 100644
--- a/tests/testbench/com/vaadin/tests/minitutorials/CustomConverterFactoryRoot.java
+++ b/tests/testbench/com/vaadin/tests/minitutorials/v7a1/CustomConverterFactoryRoot.java
@@ -1,4 +1,4 @@
-package com.vaadin.tests.minitutorials;
+package com.vaadin.tests.minitutorials.v7a1;
import com.vaadin.terminal.WrappedRequest;
import com.vaadin.tests.components.AbstractTestRoot;
diff --git a/tests/testbench/com/vaadin/tests/minitutorials/v7a1/DefineRootTheme.java b/tests/testbench/com/vaadin/tests/minitutorials/v7a1/DefineRootTheme.java
new file mode 100644
index 0000000000..3bd17547fa
--- /dev/null
+++ b/tests/testbench/com/vaadin/tests/minitutorials/v7a1/DefineRootTheme.java
@@ -0,0 +1,31 @@
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+
+package com.vaadin.tests.minitutorials.v7a1;
+
+import com.vaadin.annotations.Theme;
+import com.vaadin.terminal.WrappedRequest;
+import com.vaadin.ui.Label;
+import com.vaadin.ui.Root;
+import com.vaadin.ui.VerticalLayout;
+
+/**
+ * Mini tutorial code for
+ * https://vaadin.com/wiki/-/wiki/Main/Defining%20the%20theme%20for%20a%20Root
+ *
+ * @author Vaadin Ltd
+ * @version @VERSION@
+ * @since 7.0.0
+ */
+@Theme("hello-theme")
+public class DefineRootTheme extends Root {
+
+ @Override
+ protected void init(WrappedRequest request) {
+ VerticalLayout view = new VerticalLayout();
+ view.addComponent(new Label("Hello Vaadin"));
+ setContent(view);
+ }
+
+}
diff --git a/tests/testbench/com/vaadin/tests/minitutorials/v7a1/DifferentFeaturesForDifferentClients.java b/tests/testbench/com/vaadin/tests/minitutorials/v7a1/DifferentFeaturesForDifferentClients.java
new file mode 100644
index 0000000000..cf4c3b9267
--- /dev/null
+++ b/tests/testbench/com/vaadin/tests/minitutorials/v7a1/DifferentFeaturesForDifferentClients.java
@@ -0,0 +1,63 @@
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+
+package com.vaadin.tests.minitutorials.v7a1;
+
+import com.vaadin.Application;
+import com.vaadin.RootRequiresMoreInformationException;
+import com.vaadin.terminal.WrappedRequest;
+import com.vaadin.terminal.WrappedRequest.BrowserDetails;
+import com.vaadin.terminal.gwt.server.WebBrowser;
+import com.vaadin.ui.Label;
+import com.vaadin.ui.Root;
+
+/**
+ * Mini tutorial code for
+ * https://vaadin.com/wiki/-/wiki/Main/Creating%20an%20application
+ * %20with%20different%20features%20for%20different%20clients
+ *
+ * @author Vaadin Ltd
+ * @version @VERSION@
+ * @since 7.0.0
+ */
+public class DifferentFeaturesForDifferentClients extends Application {
+
+ @Override
+ protected Root getRoot(WrappedRequest request)
+ throws RootRequiresMoreInformationException {
+ BrowserDetails browserDetails = request.getBrowserDetails();
+ // This is a limitation of 7.0.0.alpha1 that there is no better way to
+ // check if WebBrowser has been fully initialized
+ if (browserDetails.getUriFragment() == null) {
+ throw new RootRequiresMoreInformationException();
+ }
+
+ // could also use screen size, browser version etc.
+ if (browserDetails.getWebBrowser().isTouchDevice()) {
+ return new TouchRoot();
+ } else {
+ return new DefaultRoot();
+ }
+ }
+}
+
+class DefaultRoot extends Root {
+ @Override
+ protected void init(WrappedRequest request) {
+ getContent().addComponent(
+ new Label("This browser does not support touch events"));
+ }
+}
+
+class TouchRoot extends Root {
+ @Override
+ protected void init(WrappedRequest request) {
+ WebBrowser webBrowser = request.getBrowserDetails().getWebBrowser();
+ String screenSize = "" + webBrowser.getScreenWidth() + "x"
+ + webBrowser.getScreenHeight();
+ getContent().addComponent(
+ new Label("Using a touch enabled device with screen size"
+ + screenSize));
+ }
+}
diff --git a/tests/testbench/com/vaadin/tests/minitutorials/DynamicImageRoot.java b/tests/testbench/com/vaadin/tests/minitutorials/v7a1/DynamicImageRoot.java
index a0e6a54c41..9ed2bd2c75 100644
--- a/tests/testbench/com/vaadin/tests/minitutorials/DynamicImageRoot.java
+++ b/tests/testbench/com/vaadin/tests/minitutorials/v7a1/DynamicImageRoot.java
@@ -1,4 +1,4 @@
-package com.vaadin.tests.minitutorials;
+package com.vaadin.tests.minitutorials.v7a1;
import java.awt.image.BufferedImage;
import java.io.IOException;
diff --git a/tests/testbench/com/vaadin/tests/minitutorials/v7a1/FindCurrentRootAndApplication.java b/tests/testbench/com/vaadin/tests/minitutorials/v7a1/FindCurrentRootAndApplication.java
new file mode 100644
index 0000000000..b237666caa
--- /dev/null
+++ b/tests/testbench/com/vaadin/tests/minitutorials/v7a1/FindCurrentRootAndApplication.java
@@ -0,0 +1,44 @@
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+
+package com.vaadin.tests.minitutorials.v7a1;
+
+import com.vaadin.Application;
+import com.vaadin.terminal.WrappedRequest;
+import com.vaadin.ui.Button;
+import com.vaadin.ui.Button.ClickEvent;
+import com.vaadin.ui.Button.ClickListener;
+import com.vaadin.ui.Notification;
+import com.vaadin.ui.Root;
+
+/**
+ * Mini tutorial code for
+ * https://vaadin.com/wiki/-/wiki/Main/Finding%20the%20current
+ * %20Root%20and%20Application
+ *
+ * @author Vaadin Ltd
+ * @version @VERSION@
+ * @since 7.0.0
+ */
+public class FindCurrentRootAndApplication extends Root {
+
+ @Override
+ protected void init(WrappedRequest request) {
+ Button helloButton = new Button("Say Hello");
+ helloButton.addListener(new ClickListener() {
+ public void buttonClick(ClickEvent event) {
+ String msg = "Running in ";
+ msg += Application.getCurrent().isProductionMode() ? "production"
+ : "debug";
+ msg += " mode in a Root with the caption "
+ + Root.getCurrent().getCaption();
+
+ Notification.show(msg);
+ }
+ });
+
+ addComponent(helloButton);
+ }
+
+}
diff --git a/tests/testbench/com/vaadin/tests/minitutorials/FormUsingExistingLayout.java b/tests/testbench/com/vaadin/tests/minitutorials/v7a1/FormUsingExistingLayout.java
index 9d20867d24..1e460b2f6e 100644
--- a/tests/testbench/com/vaadin/tests/minitutorials/FormUsingExistingLayout.java
+++ b/tests/testbench/com/vaadin/tests/minitutorials/v7a1/FormUsingExistingLayout.java
@@ -1,4 +1,4 @@
-package com.vaadin.tests.minitutorials;
+package com.vaadin.tests.minitutorials.v7a1;
import com.vaadin.data.fieldgroup.FieldGroup;
import com.vaadin.data.fieldgroup.PropertyId;
diff --git a/tests/testbench/com/vaadin/tests/minitutorials/FormatTableValue.java b/tests/testbench/com/vaadin/tests/minitutorials/v7a1/FormatTableValue.java
index aba1447d2c..e487c6d3c4 100644
--- a/tests/testbench/com/vaadin/tests/minitutorials/FormatTableValue.java
+++ b/tests/testbench/com/vaadin/tests/minitutorials/v7a1/FormatTableValue.java
@@ -1,4 +1,4 @@
-package com.vaadin.tests.minitutorials;
+package com.vaadin.tests.minitutorials.v7a1;
import java.text.NumberFormat;
import java.util.Locale;
diff --git a/tests/testbench/com/vaadin/tests/minitutorials/IntegerTextFieldDataSource.java b/tests/testbench/com/vaadin/tests/minitutorials/v7a1/IntegerTextFieldDataSource.java
index 5c0efea3ea..dd32242062 100644
--- a/tests/testbench/com/vaadin/tests/minitutorials/IntegerTextFieldDataSource.java
+++ b/tests/testbench/com/vaadin/tests/minitutorials/v7a1/IntegerTextFieldDataSource.java
@@ -1,4 +1,4 @@
-package com.vaadin.tests.minitutorials;
+package com.vaadin.tests.minitutorials.v7a1;
import com.vaadin.data.Property;
import com.vaadin.data.util.BeanItem;
@@ -8,7 +8,7 @@ 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.Root;
+import com.vaadin.ui.Notification;
import com.vaadin.ui.TextField;
public class IntegerTextFieldDataSource extends AbstractTestRoot {
@@ -40,12 +40,9 @@ public class IntegerTextFieldDataSource extends AbstractTestRoot {
Integer propertyValue = integerProperty.getValue();
int dataModelValue = myBean.getValue();
- Root.getCurrentRoot().showNotification(
- "UI value (String): " + uiValue
- + "<br />Property value (Integer): "
- + propertyValue
- + "<br />Data model value (int): "
- + dataModelValue);
+ Notification.show("UI value (String): " + uiValue
+ + "<br />Property value (Integer): " + propertyValue
+ + "<br />Data model value (int): " + dataModelValue);
}
});
diff --git a/tests/testbench/com/vaadin/tests/minitutorials/IntegerTextFieldStandalone.java b/tests/testbench/com/vaadin/tests/minitutorials/v7a1/IntegerTextFieldStandalone.java
index 45bc49ba72..9c720e45a5 100644
--- a/tests/testbench/com/vaadin/tests/minitutorials/IntegerTextFieldStandalone.java
+++ b/tests/testbench/com/vaadin/tests/minitutorials/v7a1/IntegerTextFieldStandalone.java
@@ -1,4 +1,4 @@
-package com.vaadin.tests.minitutorials;
+package com.vaadin.tests.minitutorials.v7a1;
import com.vaadin.data.util.converter.Converter.ConversionException;
import com.vaadin.data.util.converter.StringToIntegerConverter;
@@ -8,7 +8,7 @@ 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.Root;
+import com.vaadin.ui.Notification;
import com.vaadin.ui.TextField;
public class IntegerTextFieldStandalone extends AbstractTestRoot {
@@ -24,14 +24,12 @@ public class IntegerTextFieldStandalone extends AbstractTestRoot {
try {
Integer convertedValue = (Integer) textField
.getConvertedValue();
- Root.getCurrentRoot().showNotification(
- "UI value (String): " + uiValue
- + "<br />Converted value (Integer): "
- + convertedValue);
+ Notification.show("UI value (String): " + uiValue
+ + "<br />Converted value (Integer): "
+ + convertedValue);
} catch (ConversionException e) {
e.printStackTrace();
- Root.getCurrentRoot().showNotification(
- "Could not convert value: " + uiValue);
+ Notification.show("Could not convert value: " + uiValue);
}
}
});
diff --git a/tests/testbench/com/vaadin/tests/minitutorials/v7a1/MultiTabApplication.java b/tests/testbench/com/vaadin/tests/minitutorials/v7a1/MultiTabApplication.java
new file mode 100644
index 0000000000..89c6ef52c4
--- /dev/null
+++ b/tests/testbench/com/vaadin/tests/minitutorials/v7a1/MultiTabApplication.java
@@ -0,0 +1,51 @@
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+
+package com.vaadin.tests.minitutorials.v7a1;
+
+import com.vaadin.terminal.ExternalResource;
+import com.vaadin.terminal.WrappedRequest;
+import com.vaadin.ui.Label;
+import com.vaadin.ui.Link;
+import com.vaadin.ui.Root;
+import com.vaadin.ui.VerticalLayout;
+
+/**
+ * Mini tutorial code for
+ * https://vaadin.com/wiki/-/wiki/Main/Creating%20multi%20tab%20applications
+ *
+ * @author Vaadin Ltd
+ * @version @VERSION@
+ * @since 7.0.0
+ */
+public class MultiTabApplication extends Root {
+
+ private class MainView extends VerticalLayout {
+ public MainView() {
+ addComponent(new Link("Edit person 1", new ExternalResource(
+ "?editPerson=person1")));
+ addComponent(new Link("Edit person 2", new ExternalResource(
+ "?editPerson=person2")));
+ }
+ }
+
+ private class EditPersonView extends VerticalLayout {
+
+ public EditPersonView(String person) {
+ addComponent(new Label("Editor for " + person));
+ }
+
+ }
+
+ @Override
+ public void init(WrappedRequest request) {
+ String person = request.getParameter("editPerson");
+ if (person == null) {
+ setContent(new MainView());
+ } else {
+ setContent(new EditPersonView(person));
+ }
+ }
+
+}
diff --git a/tests/testbench/com/vaadin/tests/minitutorials/MyConverterFactory.java b/tests/testbench/com/vaadin/tests/minitutorials/v7a1/MyConverterFactory.java
index 456654e10a..17c37f2115 100644
--- a/tests/testbench/com/vaadin/tests/minitutorials/MyConverterFactory.java
+++ b/tests/testbench/com/vaadin/tests/minitutorials/v7a1/MyConverterFactory.java
@@ -1,4 +1,4 @@
-package com.vaadin.tests.minitutorials;
+package com.vaadin.tests.minitutorials.v7a1;
import com.vaadin.data.util.converter.Converter;
import com.vaadin.data.util.converter.DefaultConverterFactory;
diff --git a/tests/testbench/com/vaadin/tests/minitutorials/MyStringToDoubleConverter.java b/tests/testbench/com/vaadin/tests/minitutorials/v7a1/MyStringToDoubleConverter.java
index 38268bdf68..483f841ce2 100644
--- a/tests/testbench/com/vaadin/tests/minitutorials/MyStringToDoubleConverter.java
+++ b/tests/testbench/com/vaadin/tests/minitutorials/v7a1/MyStringToDoubleConverter.java
@@ -1,4 +1,4 @@
-package com.vaadin.tests.minitutorials;
+package com.vaadin.tests.minitutorials.v7a1;
import java.text.NumberFormat;
import java.util.Locale;
diff --git a/tests/testbench/com/vaadin/tests/minitutorials/StringMyTypeConverter.java b/tests/testbench/com/vaadin/tests/minitutorials/v7a1/StringMyTypeConverter.java
index e28788f743..4ccd73b2b3 100644
--- a/tests/testbench/com/vaadin/tests/minitutorials/StringMyTypeConverter.java
+++ b/tests/testbench/com/vaadin/tests/minitutorials/v7a1/StringMyTypeConverter.java
@@ -1,4 +1,4 @@
-package com.vaadin.tests.minitutorials;
+package com.vaadin.tests.minitutorials.v7a1;
import java.util.Locale;
@@ -9,6 +9,7 @@ import com.vaadin.tests.components.AbstractTestRoot;
import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.Button.ClickListener;
+import com.vaadin.ui.Notification;
import com.vaadin.ui.TextField;
public class StringMyTypeConverter extends AbstractTestRoot {
@@ -26,12 +27,11 @@ public class StringMyTypeConverter extends AbstractTestRoot {
public void buttonClick(ClickEvent event) {
try {
Name name = (Name) textField.getConvertedValue();
- getRoot().showNotification(
- "First name: " + name.getFirstName()
- + "<br />Last name: " + name.getLastName());
+ Notification.show("First name: " + name.getFirstName()
+ + "<br />Last name: " + name.getLastName());
} catch (ConversionException e) {
e.printStackTrace();
- getRoot().showNotification(e.getCause().getMessage());
+ Notification.show(e.getCause().getMessage());
}
}
}));
diff --git a/tests/testbench/com/vaadin/tests/minitutorials/v7a1/UsingBeanValidation.java b/tests/testbench/com/vaadin/tests/minitutorials/v7a1/UsingBeanValidation.java
new file mode 100644
index 0000000000..eb297ebd36
--- /dev/null
+++ b/tests/testbench/com/vaadin/tests/minitutorials/v7a1/UsingBeanValidation.java
@@ -0,0 +1,74 @@
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+
+package com.vaadin.tests.minitutorials.v7a1;
+
+import javax.validation.constraints.Max;
+import javax.validation.constraints.Min;
+import javax.validation.constraints.Size;
+
+import com.vaadin.data.util.BeanItem;
+import com.vaadin.data.validator.BeanValidator;
+import com.vaadin.terminal.WrappedRequest;
+import com.vaadin.ui.Root;
+import com.vaadin.ui.TextField;
+
+/**
+ * Mini tutorial code for
+ * https://vaadin.com/wiki/-/wiki/Main/Using%20Bean%20Validation
+ * %20to%20validate%20input
+ *
+ * @author Vaadin Ltd
+ * @version @VERSION@
+ * @since 7.0.0
+ */
+public class UsingBeanValidation extends Root {
+ class Person {
+
+ @Size(min = 5, max = 50)
+ private String name;
+
+ @Min(0)
+ @Max(100)
+ private int age;
+
+ // + constructor + setters + getters
+
+ public Person(String name, int age) {
+ this.name = name;
+ this.age = age;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public int getAge() {
+ return age;
+ }
+
+ private void setN() {
+ // TODO Auto-generated method stub
+
+ }
+ }
+
+ @Override
+ protected void init(WrappedRequest request) {
+ Person person = new Person("John", 26);
+ BeanItem<Person> item = new BeanItem<Person>(person);
+
+ TextField firstName = new TextField("First name",
+ item.getItemProperty("name"));
+ firstName.setImmediate(true);
+ addComponent(firstName);
+
+ firstName.addValidator(new BeanValidator(Person.class, "name"));
+ }
+
+}
diff --git a/tests/testbench/com/vaadin/tests/minitutorials/v7a1/UsingUriFragments.java b/tests/testbench/com/vaadin/tests/minitutorials/v7a1/UsingUriFragments.java
new file mode 100644
index 0000000000..e98b698c07
--- /dev/null
+++ b/tests/testbench/com/vaadin/tests/minitutorials/v7a1/UsingUriFragments.java
@@ -0,0 +1,54 @@
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+
+package com.vaadin.tests.minitutorials.v7a1;
+
+import com.vaadin.terminal.Page.FragmentChangedEvent;
+import com.vaadin.terminal.Page.FragmentChangedListener;
+import com.vaadin.terminal.WrappedRequest;
+import com.vaadin.ui.Button;
+import com.vaadin.ui.Button.ClickEvent;
+import com.vaadin.ui.Label;
+import com.vaadin.ui.Root;
+
+/**
+ * Mini tutorial code for
+ * https://vaadin.com/wiki/-/wiki/Main/Using%20URI%20fragments
+ *
+ * @author Vaadin Ltd
+ * @version @VERSION@
+ * @since 7.0.0
+ */
+public class UsingUriFragments extends Root {
+
+ @Override
+ protected void init(WrappedRequest request) {
+ Label label = new Label("Hello, your fragment is "
+ + request.getBrowserDetails().getUriFragment());
+ getContent().addComponent(label);
+
+ // React to fragment changes
+ getPage().addListener(new FragmentChangedListener() {
+ public void fragmentChanged(FragmentChangedEvent source) {
+ handleFragment(source.getFragment());
+ }
+ });
+
+ // Handle the fragment received in the initial request
+ handleFragment(request.getBrowserDetails().getUriFragment());
+
+ addComponent(new Button("Show and set fragment",
+ new Button.ClickListener() {
+ public void buttonClick(ClickEvent event) {
+ handleFragment(getPage().getFragment());
+ getPage().setFragment("customFragment");
+ }
+ }));
+ }
+
+ private void handleFragment(String uriFragment) {
+ addComponent(new Label("Got new fragment: " + uriFragment));
+ }
+
+}
diff --git a/tests/testbench/com/vaadin/tests/minitutorials/v7a1/UsingXyzWhenInitializing.java b/tests/testbench/com/vaadin/tests/minitutorials/v7a1/UsingXyzWhenInitializing.java
new file mode 100644
index 0000000000..426ef3525e
--- /dev/null
+++ b/tests/testbench/com/vaadin/tests/minitutorials/v7a1/UsingXyzWhenInitializing.java
@@ -0,0 +1,52 @@
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+
+package com.vaadin.tests.minitutorials.v7a1;
+
+import com.vaadin.terminal.WrappedRequest;
+import com.vaadin.ui.Label;
+import com.vaadin.ui.Root;
+
+/**
+ * Mini tutorial code for
+ * https://vaadin.com/wiki/-/wiki/Main/Using%20URI%20or%20
+ * parameters%20or%20screen%20size%20when%20initializing%20an%20application
+ *
+ * @author Vaadin Ltd
+ * @version @VERSION@
+ * @since 7.0.0
+ */
+public class UsingXyzWhenInitializing extends Root {
+
+ @Override
+ protected void init(WrappedRequest request) {
+ String name = request.getParameter("name");
+ if (name == null) {
+ name = "Unknown";
+ }
+
+ getContent().addComponent(new Label("Hello " + name));
+
+ String pathInfo = request.getRequestPathInfo();
+ if ("/viewSource".equals(pathInfo)) {
+ getContent().addComponent(new Label("This is the source"));
+ } else {
+ getContent().addComponent(new Label("Welcome to my application"));
+ }
+
+ // WebBrowser browser = request.getBrowserDetails().getWebBrowser();
+ // String resolution = "Your browser window on startup was "
+ // + browser.getClientWidth() + "x" + browser.getClientHeight();
+ // if (browser.getClientWidth() > 1024) {
+ // getContent().addComponent(
+ // new Label("The is the large version of the application. "
+ // + resolution));
+ // } else {
+ // getContent().addComponent(
+ // new Label("This is the small version of the application. "
+ // + resolution));
+ // }
+ }
+
+}
diff --git a/tests/testbench/com/vaadin/tests/minitutorials/v7a2/ComponentInStateComponent.java b/tests/testbench/com/vaadin/tests/minitutorials/v7a2/ComponentInStateComponent.java
new file mode 100644
index 0000000000..78a945901d
--- /dev/null
+++ b/tests/testbench/com/vaadin/tests/minitutorials/v7a2/ComponentInStateComponent.java
@@ -0,0 +1,26 @@
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+
+package com.vaadin.tests.minitutorials.v7a2;
+
+import com.vaadin.tests.widgetset.client.minitutorials.v7a2.ComponentInStateState;
+import com.vaadin.ui.AbstractComponent;
+import com.vaadin.ui.Component;
+
+public class ComponentInStateComponent extends AbstractComponent {
+
+ @Override
+ public ComponentInStateState getState() {
+ return (ComponentInStateState) super.getState();
+ }
+
+ public void setOtherComponent(Component component) {
+ getState().setOtherComponent(component);
+ requestRepaint();
+ }
+
+ public Component getOtherComponent() {
+ return (Component) getState().getOtherComponent();
+ }
+}
diff --git a/tests/testbench/com/vaadin/tests/minitutorials/v7a2/ComponentInStateRoot.java b/tests/testbench/com/vaadin/tests/minitutorials/v7a2/ComponentInStateRoot.java
new file mode 100644
index 0000000000..61b5f98f99
--- /dev/null
+++ b/tests/testbench/com/vaadin/tests/minitutorials/v7a2/ComponentInStateRoot.java
@@ -0,0 +1,27 @@
+package com.vaadin.tests.minitutorials.v7a2;
+
+import com.vaadin.annotations.Widgetset;
+import com.vaadin.terminal.WrappedRequest;
+import com.vaadin.ui.Label;
+import com.vaadin.ui.Root;
+
+/**
+ * Mini tutorial code for
+ * https://vaadin.com/wiki/-/wiki/Main/Using%20Components%
+ * 20in%20the%20shared%20state
+ *
+ * @author Vaadin Ltd
+ * @version @VERSION@
+ * @since 7.0.0
+ */
+@Widgetset("com.vaadin.tests.widgetset.TestingWidgetSet")
+public class ComponentInStateRoot extends Root {
+ @Override
+ protected void init(WrappedRequest request) {
+ ComponentInStateComponent component = new ComponentInStateComponent();
+ component.setOtherComponent(this);
+ addComponent(component);
+ addComponent(new Label("Server-side type of other component: "
+ + component.getOtherComponent().getClass().getName()));
+ }
+}
diff --git a/tests/testbench/com/vaadin/tests/minitutorials/v7a2/MyComponent.java b/tests/testbench/com/vaadin/tests/minitutorials/v7a2/MyComponent.java
new file mode 100644
index 0000000000..5c4fa9d10b
--- /dev/null
+++ b/tests/testbench/com/vaadin/tests/minitutorials/v7a2/MyComponent.java
@@ -0,0 +1,47 @@
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+
+package com.vaadin.tests.minitutorials.v7a2;
+
+import com.vaadin.terminal.gwt.client.MouseEventDetails;
+import com.vaadin.tests.widgetset.client.minitutorials.v7a2.MyComponentClientRpc;
+import com.vaadin.tests.widgetset.client.minitutorials.v7a2.MyComponentServerRpc;
+import com.vaadin.tests.widgetset.client.minitutorials.v7a2.MyComponentState;
+import com.vaadin.ui.AbstractComponent;
+
+public class MyComponent extends AbstractComponent {
+ private int clickCount = 0;
+
+ private MyComponentServerRpc rpc = new MyComponentServerRpc() {
+ public void clicked(MouseEventDetails mouseDetails) {
+ clickCount++;
+
+ // nag every 5:th click
+ if (clickCount % 5 == 0) {
+ getRpcProxy(MyComponentClientRpc.class).alert(
+ "Ok, that's enough!");
+ }
+
+ setText("You have clicked " + clickCount + " times");
+ }
+ };
+
+ public MyComponent() {
+ registerRpc(rpc);
+ }
+
+ @Override
+ public MyComponentState getState() {
+ return (MyComponentState) super.getState();
+ }
+
+ public void setText(String text) {
+ getState().setText(text);
+ requestRepaint();
+ }
+
+ public String getText() {
+ return getState().getText();
+ }
+}
diff --git a/tests/testbench/com/vaadin/tests/minitutorials/v7a2/MyComponentRoot.java b/tests/testbench/com/vaadin/tests/minitutorials/v7a2/MyComponentRoot.java
new file mode 100644
index 0000000000..77792436f5
--- /dev/null
+++ b/tests/testbench/com/vaadin/tests/minitutorials/v7a2/MyComponentRoot.java
@@ -0,0 +1,36 @@
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+
+package com.vaadin.tests.minitutorials.v7a2;
+
+import com.vaadin.annotations.Widgetset;
+import com.vaadin.terminal.WrappedRequest;
+import com.vaadin.ui.Root;
+
+/**
+ * Mini tutorial code for
+ * https://vaadin.com/wiki/-/wiki/Main/Creating%20a%20simple%20component,
+ * https://vaadin.com/wiki/-/wiki/Main/Creating%20a%20simple%20component,
+ * https://vaadin.com/wiki/-/wiki/Main/Sending%
+ * 20events%20from%20the%20client%20to%20the%20server%20using%20RPC,
+ * https://vaadin
+ * .com/wiki/-/wiki/Main/Using%20RPC%20to%20send%20events%20to%20the%20client
+ *
+ * @author Vaadin Ltd
+ * @version @VERSION@
+ * @since 7.0.0
+ */
+@Widgetset("com.vaadin.tests.widgetset.TestingWidgetSet")
+public class MyComponentRoot extends Root {
+
+ @Override
+ protected void init(WrappedRequest request) {
+ MyComponent component = new MyComponent();
+
+ component.setText("My component text");
+
+ addComponent(component);
+ }
+
+} \ No newline at end of file
diff --git a/tests/testbench/com/vaadin/tests/minitutorials/v7a2/MyPickerConnector.java b/tests/testbench/com/vaadin/tests/minitutorials/v7a2/MyPickerConnector.java
new file mode 100644
index 0000000000..ea278da218
--- /dev/null
+++ b/tests/testbench/com/vaadin/tests/minitutorials/v7a2/MyPickerConnector.java
@@ -0,0 +1,61 @@
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+
+package com.vaadin.tests.minitutorials.v7a2;
+
+import com.google.gwt.user.client.Element;
+import com.vaadin.terminal.gwt.client.ui.AbstractComponentConnector;
+import com.vaadin.terminal.gwt.client.ui.SimpleManagedLayout;
+import com.vaadin.terminal.gwt.client.ui.layout.ElementResizeEvent;
+import com.vaadin.terminal.gwt.client.ui.layout.ElementResizeListener;
+
+/**
+ * Mini tutorial code for
+ * https://vaadin.com/wiki/-/wiki/Main/Widget%20styling%20using%20only%20CSS,
+ * https
+ * ://vaadin.com/wiki/-/wiki/Main/Lightweight%20calculations%20of%20widget%20l
+ * ayout and https://vaadin.com/wiki/-/wiki/Main/Complex%20widget%20layouts
+ *
+ * @author Vaadin Ltd
+ * @version @VERSION@
+ * @since 7.0.0
+ */
+public class MyPickerConnector extends AbstractComponentConnector implements
+ SimpleManagedLayout {
+ @Override
+ public MyPickerWidget getWidget() {
+ return (MyPickerWidget) super.getWidget();
+ }
+
+ private final ElementResizeListener listener = new ElementResizeListener() {
+ public void onElementResize(ElementResizeEvent e) {
+ int buttonWidth = getLayoutManager().getOuterWidth(e.getElement());
+ buttonWidth -= getLayoutManager().getMarginRight(e.getElement());
+ getWidget().adjustButtonSpace(buttonWidth);
+ }
+ };
+
+ @Override
+ protected void init() {
+ Element button = getWidget().getWidget(1).getElement();
+ getLayoutManager().addElementResizeListener(button, listener);
+
+ getLayoutManager().registerDependency(this, button);
+ }
+
+ @Override
+ public void onUnregister() {
+ Element button = getWidget().getWidget(1).getElement();
+ getLayoutManager().removeElementResizeListener(button, listener);
+
+ getLayoutManager().unregisterDependency(this, button);
+ }
+
+ public void layout() {
+ Element button = getWidget().getWidget(1).getElement();
+ int buttonWidth = getLayoutManager().getOuterWidth(button);
+ buttonWidth -= getLayoutManager().getMarginRight(button);
+ getWidget().adjustButtonSpace(buttonWidth);
+ }
+}
diff --git a/tests/testbench/com/vaadin/tests/minitutorials/v7a2/MyPickerWidget.java b/tests/testbench/com/vaadin/tests/minitutorials/v7a2/MyPickerWidget.java
new file mode 100644
index 0000000000..213a1b9e6b
--- /dev/null
+++ b/tests/testbench/com/vaadin/tests/minitutorials/v7a2/MyPickerWidget.java
@@ -0,0 +1,51 @@
+package com.vaadin.tests.minitutorials.v7a2;
+
+import com.google.gwt.dom.client.Document;
+import com.google.gwt.dom.client.Style.Unit;
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.ClickHandler;
+import com.google.gwt.user.client.Window;
+import com.google.gwt.user.client.ui.ComplexPanel;
+import com.google.gwt.user.client.ui.PushButton;
+import com.google.gwt.user.client.ui.TextBox;
+
+public class MyPickerWidget extends ComplexPanel {
+
+ public static final String CLASSNAME = "mypicker";
+
+ private final TextBox textBox = new TextBox();
+ private final PushButton button = new PushButton("...");
+
+ public MyPickerWidget() {
+ setElement(Document.get().createDivElement());
+ setStylePrimaryName(CLASSNAME);
+
+ textBox.setStylePrimaryName(CLASSNAME + "-field");
+ button.setStylePrimaryName(CLASSNAME + "-button");
+
+ add(textBox, getElement());
+ add(button, getElement());
+
+ button.addClickHandler(new ClickHandler() {
+ public void onClick(ClickEvent event) {
+ Window.alert("Calendar picker not yet supported!");
+ }
+ });
+ }
+
+ public void setButtonText(String buttonText, boolean adjustSpace) {
+ if (buttonText == null || buttonText.length() == 0) {
+ buttonText = "...";
+ }
+ button.setText(buttonText);
+
+ if (adjustSpace) {
+ adjustButtonSpace(button.getOffsetWidth());
+ }
+ }
+
+ public void adjustButtonSpace(int width) {
+ getElement().getStyle().setPaddingRight(width, Unit.PX);
+ button.getElement().getStyle().setMarginRight(-width, Unit.PX);
+ }
+} \ No newline at end of file
diff --git a/tests/testbench/com/vaadin/tests/minitutorials/v7a2/ResourceInStateComponent.java b/tests/testbench/com/vaadin/tests/minitutorials/v7a2/ResourceInStateComponent.java
new file mode 100644
index 0000000000..f9d4cb38e6
--- /dev/null
+++ b/tests/testbench/com/vaadin/tests/minitutorials/v7a2/ResourceInStateComponent.java
@@ -0,0 +1,30 @@
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+
+package com.vaadin.tests.minitutorials.v7a2;
+
+import com.vaadin.terminal.Resource;
+import com.vaadin.terminal.gwt.server.ResourceReference;
+import com.vaadin.tests.widgetset.client.minitutorials.v7a2.ResourceInStateState;
+import com.vaadin.ui.AbstractComponent;
+
+public class ResourceInStateComponent extends AbstractComponent {
+ @Override
+ public ResourceInStateState getState() {
+ return (ResourceInStateState) super.getState();
+ }
+
+ public void setMyIcon(Resource icon) {
+ getState().setMyIcon(new ResourceReference(icon));
+ }
+
+ public Resource getMyIcon() {
+ ResourceReference ref = ((ResourceReference) getState().getMyIcon());
+ if (ref != null) {
+ return ref.getResource();
+ } else {
+ return null;
+ }
+ }
+}
diff --git a/tests/testbench/com/vaadin/tests/minitutorials/v7a2/ResourceInStateRoot.java b/tests/testbench/com/vaadin/tests/minitutorials/v7a2/ResourceInStateRoot.java
new file mode 100644
index 0000000000..135d36828d
--- /dev/null
+++ b/tests/testbench/com/vaadin/tests/minitutorials/v7a2/ResourceInStateRoot.java
@@ -0,0 +1,32 @@
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+
+package com.vaadin.tests.minitutorials.v7a2;
+
+import com.vaadin.annotations.Widgetset;
+import com.vaadin.terminal.ThemeResource;
+import com.vaadin.terminal.WrappedRequest;
+import com.vaadin.ui.Root;
+
+/**
+ * Mini tutorial code for
+ * https://vaadin.com/wiki/-/wiki/Main/Using%20Resources%20
+ * in%20the%20shared%20state
+ *
+ * @author Vaadin Ltd
+ * @version @VERSION@
+ * @since 7.0.0
+ */
+@Widgetset("com.vaadin.tests.widgetset.TestingWidgetSet")
+public class ResourceInStateRoot extends Root {
+
+ @Override
+ protected void init(WrappedRequest request) {
+ ResourceInStateComponent component = new ResourceInStateComponent();
+ component.setIcon(new ThemeResource("../runo/icons/32/calendar.png"));
+
+ addComponent(component);
+ }
+
+}
diff --git a/tests/testbench/com/vaadin/tests/minitutorials/v7a2/WidgetContainer.java b/tests/testbench/com/vaadin/tests/minitutorials/v7a2/WidgetContainer.java
new file mode 100644
index 0000000000..3c2f9a68b4
--- /dev/null
+++ b/tests/testbench/com/vaadin/tests/minitutorials/v7a2/WidgetContainer.java
@@ -0,0 +1,46 @@
+package com.vaadin.tests.minitutorials.v7a2;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import com.vaadin.ui.AbstractComponentContainer;
+import com.vaadin.ui.Component;
+
+public class WidgetContainer extends AbstractComponentContainer {
+
+ List<Component> children = new ArrayList<Component>();
+
+ @Override
+ public void addComponent(Component c) {
+ children.add(c);
+ super.addComponent(c);
+ requestRepaint();
+ }
+
+ @Override
+ public void removeComponent(Component c) {
+ children.remove(c);
+ super.removeComponent(c);
+ requestRepaint();
+ }
+
+ public void replaceComponent(Component oldComponent, Component newComponent) {
+ int index = children.indexOf(oldComponent);
+ if (index != -1) {
+ children.remove(index);
+ children.add(index, newComponent);
+ fireComponentDetachEvent(oldComponent);
+ fireComponentAttachEvent(newComponent);
+ requestRepaint();
+ }
+ }
+
+ public int getComponentCount() {
+ return children.size();
+ }
+
+ public Iterator<Component> getComponentIterator() {
+ return children.iterator();
+ }
+} \ No newline at end of file
diff --git a/tests/testbench/com/vaadin/tests/minitutorials/v7a2/WidgetcontainerRoot.java b/tests/testbench/com/vaadin/tests/minitutorials/v7a2/WidgetcontainerRoot.java
new file mode 100644
index 0000000000..3b24ec400e
--- /dev/null
+++ b/tests/testbench/com/vaadin/tests/minitutorials/v7a2/WidgetcontainerRoot.java
@@ -0,0 +1,44 @@
+package com.vaadin.tests.minitutorials.v7a2;
+
+import java.util.Random;
+
+import com.vaadin.annotations.Widgetset;
+import com.vaadin.terminal.WrappedRequest;
+import com.vaadin.ui.Button;
+import com.vaadin.ui.Button.ClickEvent;
+import com.vaadin.ui.Button.ClickListener;
+import com.vaadin.ui.CheckBox;
+import com.vaadin.ui.Component;
+import com.vaadin.ui.Label;
+import com.vaadin.ui.Root;
+
+@Widgetset("com.vaadin.tests.widgetset.TestingWidgetSet")
+public class WidgetcontainerRoot extends Root {
+ @Override
+ public void init(WrappedRequest request) {
+ Label label = new Label("Hello Vaadin user");
+ addComponent(label);
+ final WidgetContainer widgetContainer = new WidgetContainer();
+ addComponent(widgetContainer);
+ widgetContainer.addComponent(new Label(
+ "Click the button to add components to the WidgetContainer."));
+ Button button = new Button("Add more components", new ClickListener() {
+
+ public void buttonClick(ClickEvent event) {
+ Random randomGenerator = new Random();
+ int random = randomGenerator.nextInt(3);
+ Component component;
+ if (random % 3 == 0) {
+ component = new Label("A new label");
+ } else if (random % 3 == 1) {
+ component = new Button("A button!");
+ } else {
+ component = new CheckBox("A textfield");
+ }
+ widgetContainer.addComponent(component);
+ }
+ });
+ addComponent(button);
+ }
+
+} \ No newline at end of file
diff --git a/tests/testbench/com/vaadin/tests/serialization/SerializerTest.java b/tests/testbench/com/vaadin/tests/serialization/SerializerTest.java
new file mode 100644
index 0000000000..d0b672fbf9
--- /dev/null
+++ b/tests/testbench/com/vaadin/tests/serialization/SerializerTest.java
@@ -0,0 +1,273 @@
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+
+package com.vaadin.tests.serialization;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import com.vaadin.annotations.Widgetset;
+import com.vaadin.terminal.WrappedRequest;
+import com.vaadin.terminal.gwt.client.Connector;
+import com.vaadin.tests.components.AbstractTestRoot;
+import com.vaadin.tests.util.Log;
+import com.vaadin.tests.widgetset.client.ComplexTestBean;
+import com.vaadin.tests.widgetset.client.SerializerTestRpc;
+import com.vaadin.tests.widgetset.client.SimpleTestBean;
+import com.vaadin.tests.widgetset.server.SerializerTestExtension;
+
+@Widgetset("com.vaadin.tests.widgetset.TestingWidgetSet")
+public class SerializerTest extends AbstractTestRoot {
+
+ private Log log = new Log(40);
+
+ @Override
+ protected void setup(WrappedRequest request) {
+ final SerializerTestExtension testExtension = new SerializerTestExtension();
+ addExtension(testExtension);
+ addComponent(log);
+
+ SerializerTestRpc rpc = testExtension
+ .getRpcProxy(SerializerTestRpc.class);
+ rpc.sendBoolean(true, Boolean.FALSE, new boolean[] { true, true, false,
+ true, false, false });
+ rpc.sendByte((byte) 5, Byte.valueOf((byte) -12), new byte[] { 3, 1, 2 });
+ rpc.sendChar('\u222b', Character.valueOf('Ã¥'), "aBcD".toCharArray());
+ rpc.sendInt(Integer.MAX_VALUE, Integer.valueOf(0), new int[] { 5, 7 });
+ rpc.sendLong(577431841358l, Long.valueOf(0), new long[] {
+ -57841235865l, 57 });
+ rpc.sendFloat(3.14159f, Float.valueOf(Math.nextUp(1)), new float[] {
+ 57, 0, -12 });
+ rpc.sendDouble(Math.PI, Double.valueOf(-Math.E), new double[] {
+ Double.MAX_VALUE, Double.MIN_VALUE });
+ rpc.sendString("This is a tesing string ‡");
+ rpc.sendConnector(this);
+ rpc.sendBean(
+ new ComplexTestBean(new SimpleTestBean(0),
+ new SimpleTestBean(1), Arrays.asList(
+ new SimpleTestBean(3), new SimpleTestBean(4)),
+ 5), new SimpleTestBean(6),
+ new SimpleTestBean[] { new SimpleTestBean(7) });
+ rpc.sendNull("Not null", null);
+ rpc.sendNestedArray(new int[][] { { 5 }, { 7 } },
+ new SimpleTestBean[][] { { new SimpleTestBean(4),
+ new SimpleTestBean(2) } });
+ rpc.sendList(Arrays.asList(5, 8, -234), Arrays.<Connector> asList(this,
+ testExtension), Arrays.asList(new SimpleTestBean(234),
+ new SimpleTestBean(-568)));
+ // Disabled because of #8861
+ // rpc.sendArrayList(
+ // Arrays.asList(new int[] { 1, 2 }, new int[] { 3, 4 }),
+ // Arrays.asList(new Integer[] { 5, 6 }, new Integer[] { 7, 8 }),
+ // Collections
+ // .singletonList(new SimpleTestBean[] { new SimpleTestBean(
+ // 7) }));
+ // Disabled because of #8861
+ // rpc.sendListArray(
+ // new List[] { Arrays.asList(1, 2), Arrays.asList(3, 4) },
+ // new List[] { Collections.singletonList(new SimpleTestBean(-1)) });
+ rpc.sendSet(new HashSet<Integer>(Arrays.asList(4, 7, 12)), Collections
+ .singleton((Connector) this), new HashSet<SimpleTestBean>(
+ Arrays.asList(new SimpleTestBean(1), new SimpleTestBean(2))));
+
+ rpc.sendMap(new HashMap<String, SimpleTestBean>() {
+ {
+ put("1", new SimpleTestBean(1));
+ put("2", new SimpleTestBean(2));
+ }
+ }, new HashMap<Connector, Boolean>() {
+ {
+ put(testExtension, true);
+ put(getRoot(), false);
+ }
+ }, new HashMap<Integer, Connector>() {
+ {
+ put(5, testExtension);
+ put(10, getRoot());
+ }
+ }, new HashMap<SimpleTestBean, SimpleTestBean>() {
+ {
+ put(new SimpleTestBean(5), new SimpleTestBean(-5));
+ put(new SimpleTestBean(-4), new SimpleTestBean(4));
+ }
+ });
+ rpc.sendWrappedGenerics(new HashMap<Set<SimpleTestBean>, Map<Integer, List<SimpleTestBean>>>() {
+ {
+ put(Collections.singleton(new SimpleTestBean(42)),
+ new HashMap<Integer, List<SimpleTestBean>>() {
+ {
+ put(1, Arrays.asList(new SimpleTestBean(1),
+ new SimpleTestBean(3)));
+ }
+ });
+ }
+ });
+
+ testExtension.registerRpc(new SerializerTestRpc() {
+ public void sendBoolean(boolean value, Boolean boxedValue,
+ boolean[] array) {
+ log.log("sendBoolean: " + value + ", " + boxedValue + ", "
+ + Arrays.toString(array));
+ }
+
+ public void sendByte(byte value, Byte boxedValue, byte[] array) {
+ log.log("sendByte: " + value + ", " + boxedValue + ", "
+ + Arrays.toString(array));
+ }
+
+ public void sendChar(char value, Character boxedValue, char[] array) {
+ log.log("sendChar: " + value + ", " + boxedValue + ", "
+ + Arrays.toString(array));
+ }
+
+ public void sendInt(int value, Integer boxedValue, int[] array) {
+ log.log("sendInt: " + value + ", " + boxedValue + ", "
+ + Arrays.toString(array));
+ }
+
+ public void sendLong(long value, Long boxedValue, long[] array) {
+ log.log("sendLong: " + value + ", " + boxedValue + ", "
+ + Arrays.toString(array));
+ }
+
+ public void sendFloat(float value, Float boxedValue, float[] array) {
+ log.log("sendFloat: " + value + ", " + boxedValue + ", "
+ + Arrays.toString(array));
+ }
+
+ public void sendDouble(double value, Double boxedValue,
+ double[] array) {
+ log.log("sendDouble: " + value + ", " + boxedValue + ", "
+ + Arrays.toString(array));
+ }
+
+ public void sendString(String value) {
+ log.log("sendString: " + value);
+ }
+
+ public void sendConnector(Connector connector) {
+ log.log("sendConnector: " + connector.getClass().getName());
+ }
+
+ public void sendBean(ComplexTestBean complexBean,
+ SimpleTestBean simpleBean, SimpleTestBean[] array) {
+ log.log("sendBean: " + complexBean + ", " + simpleBean + ", "
+ + Arrays.toString(array));
+ }
+
+ public void sendNull(String value1, String value2) {
+ log.log("sendNull: " + value1 + ", " + value2);
+ }
+
+ public void sendNestedArray(int[][] nestedIntArray,
+ SimpleTestBean[][] nestedBeanArray) {
+ log.log("sendNestedArray: "
+ + Arrays.deepToString(nestedIntArray) + ", "
+ + Arrays.deepToString(nestedBeanArray));
+ }
+
+ public void sendList(List<Integer> intList,
+ List<Connector> connectorList, List<SimpleTestBean> beanList) {
+ log.log("sendList: " + intList + ", "
+ + connectorCollectionToString(connectorList) + ", "
+ + beanList);
+ }
+
+ private String connectorCollectionToString(
+ Collection<Connector> collection) {
+ StringBuilder sb = new StringBuilder();
+
+ for (Connector connector : collection) {
+ if (sb.length() != 0) {
+ sb.append(", ");
+ }
+ sb.append(connector.getClass());
+ }
+
+ String string = sb.toString();
+ return string;
+ }
+
+ public void sendArrayList(List<int[]> primitiveArrayList,
+ List<Integer[]> objectArrayList,
+ List<SimpleTestBean[]> beanArrayList) {
+ log.log("sendArrayList: " + primitiveArrayList + ", "
+ + objectArrayList + ", " + beanArrayList);
+ }
+
+ public void sendListArray(List<Integer>[] objectListArray,
+ List<SimpleTestBean>[] beanListArray) {
+ log.log("sendArrayList: " + Arrays.toString(objectListArray)
+ + ", " + Arrays.toString(beanListArray));
+ }
+
+ public void sendSet(Set<Integer> intSet,
+ Set<Connector> connectorSet, Set<SimpleTestBean> beanSet) {
+ log.log("sendSet: " + intSet + ", "
+ + connectorCollectionToString(connectorSet) + ", "
+ + beanSet);
+ }
+
+ public void sendMap(Map<String, SimpleTestBean> stringMap,
+ Map<Connector, Boolean> connectorMap,
+ Map<Integer, Connector> intMap,
+ Map<SimpleTestBean, SimpleTestBean> beanMap) {
+ StringBuilder sb = new StringBuilder();
+ for (Entry<Connector, Boolean> entry : connectorMap.entrySet()) {
+ if (sb.length() == 0) {
+ sb.append('[');
+ } else {
+ sb.append(", ");
+ }
+ sb.append(entry.getKey().getClass().getName());
+ sb.append('=');
+ sb.append(entry.getValue());
+ }
+ sb.append(']');
+ String connectorMapString = sb.toString();
+
+ sb = new StringBuilder();
+ for (Entry<Integer, Connector> entry : intMap.entrySet()) {
+ if (sb.length() == 0) {
+ sb.append('[');
+ } else {
+ sb.append(", ");
+ }
+ sb.append(entry.getKey());
+ sb.append('=');
+ sb.append(entry.getValue().getClass().getName());
+ }
+ sb.append(']');
+ String intMapString = sb.toString();
+
+ log.log("sendMap: " + stringMap + ", " + connectorMapString
+ + ", " + intMapString + ", " + beanMap);
+ }
+
+ public void sendWrappedGenerics(
+ Map<Set<SimpleTestBean>, Map<Integer, List<SimpleTestBean>>> generics) {
+ log.log("sendWrappedGenerics: " + generics.toString());
+ }
+
+ });
+ }
+
+ @Override
+ protected String getTestDescription() {
+ return "Test for lots of different cases of encoding and decoding variuos data types";
+ }
+
+ @Override
+ protected Integer getTicketNumber() {
+ return Integer.valueOf(8655);
+ }
+
+}
diff --git a/tests/testbench/com/vaadin/tests/tickets/Ticket1465ModalNotification.java b/tests/testbench/com/vaadin/tests/tickets/Ticket1465ModalNotification.java
index 9459c7cc85..9a777d655c 100644
--- a/tests/testbench/com/vaadin/tests/tickets/Ticket1465ModalNotification.java
+++ b/tests/testbench/com/vaadin/tests/tickets/Ticket1465ModalNotification.java
@@ -5,7 +5,6 @@ import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.Label;
import com.vaadin.ui.Notification;
-import com.vaadin.ui.Root;
import com.vaadin.ui.Root.LegacyWindow;
import com.vaadin.ui.Window;
@@ -25,7 +24,7 @@ public class Ticket1465ModalNotification extends Application.LegacyApplication {
new Button.ClickListener() {
public void buttonClick(ClickEvent event) {
- Root.getCurrentRoot().showNotification(
+ Notification.show(
"Try clicking the button in main window!",
Notification.TYPE_ERROR_MESSAGE);
@@ -37,7 +36,7 @@ public class Ticket1465ModalNotification extends Application.LegacyApplication {
new Button.ClickListener() {
public void buttonClick(ClickEvent event) {
- Root.getCurrentRoot().showNotification(
+ Notification.show(
"Try clicking the button in main window!",
Notification.TYPE_WARNING_MESSAGE);
}
@@ -48,7 +47,7 @@ public class Ticket1465ModalNotification extends Application.LegacyApplication {
new Button.ClickListener() {
public void buttonClick(ClickEvent event) {
- Root.getCurrentRoot().showNotification(
+ Notification.show(
"Try clicking the button in main window!",
Notification.TYPE_HUMANIZED_MESSAGE);
}
diff --git a/tests/testbench/com/vaadin/tests/tickets/Ticket2998.java b/tests/testbench/com/vaadin/tests/tickets/Ticket2998.java
index 6cf5c8f754..a3ff6808dc 100644
--- a/tests/testbench/com/vaadin/tests/tickets/Ticket2998.java
+++ b/tests/testbench/com/vaadin/tests/tickets/Ticket2998.java
@@ -20,6 +20,7 @@ import com.vaadin.ui.Field;
import com.vaadin.ui.FormLayout;
import com.vaadin.ui.Layout;
import com.vaadin.ui.ListSelect;
+import com.vaadin.ui.Notification;
import com.vaadin.ui.Panel;
import com.vaadin.ui.Root.LegacyWindow;
import com.vaadin.ui.Table;
@@ -181,8 +182,7 @@ public class Ticket2998 extends Application.LegacyApplication {
@SuppressWarnings("unused")
float f = Float.parseFloat((String) value);
} catch (Exception e) {
- f.getRoot()
- .showNotification("Bad number value");
+ Notification.show("Bad number value");
f.setValue(0);
}
}
diff --git a/tests/testbench/com/vaadin/tests/tickets/Ticket34.java b/tests/testbench/com/vaadin/tests/tickets/Ticket34.java
index 1c55bcbe7d..f6fbe05e38 100644
--- a/tests/testbench/com/vaadin/tests/tickets/Ticket34.java
+++ b/tests/testbench/com/vaadin/tests/tickets/Ticket34.java
@@ -4,13 +4,13 @@ import java.util.HashMap;
import java.util.Map;
import com.vaadin.Application;
+import com.vaadin.terminal.Page;
+import com.vaadin.terminal.Page.FragmentChangedEvent;
import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.Component;
import com.vaadin.ui.Label;
import com.vaadin.ui.Panel;
-import com.vaadin.ui.Root;
-import com.vaadin.ui.Root.FragmentChangedEvent;
import com.vaadin.ui.Root.LegacyWindow;
import com.vaadin.ui.TextField;
import com.vaadin.ui.VerticalLayout;
@@ -32,7 +32,7 @@ public class Ticket34 extends Application.LegacyApplication {
"Test app for URI fragment management/reading", mainLayout);
setMainWindow(mainWin);
- mainWin.addListener(new Root.FragmentChangedListener() {
+ mainWin.getPage().addListener(new Page.FragmentChangedListener() {
public void fragmentChanged(FragmentChangedEvent event) {
getMainWindow().showNotification(
@@ -93,7 +93,7 @@ public class Ticket34 extends Application.LegacyApplication {
public void buttonClick(ClickEvent event) {
String viewName = tf.getValue().toString();
// fragmentChangedListener will change the view if possible
- event.getButton().getRoot().setFragment(viewName);
+ event.getButton().getRoot().getPage().setFragment(viewName);
}
});
diff --git a/tests/testbench/com/vaadin/tests/tickets/Ticket6002.java b/tests/testbench/com/vaadin/tests/tickets/Ticket6002.java
index 0875e3de48..c68dc9d534 100644
--- a/tests/testbench/com/vaadin/tests/tickets/Ticket6002.java
+++ b/tests/testbench/com/vaadin/tests/tickets/Ticket6002.java
@@ -13,8 +13,7 @@ public class Ticket6002 extends TestBase {
@Override
public void setup() {
- LegacyWindow main = new LegacyWindow("The Main Window");
- setMainWindow(main);
+ LegacyWindow main = getMainWindow();
final VerticalLayout mainLayout = new VerticalLayout();
main.setContent(mainLayout);
@@ -32,6 +31,7 @@ public class Ticket6002 extends TestBase {
final TextField tf1 = new TextField(
"Changing this field modifies only the textfield", property1);
tf1.addListener(new Property.ValueChangeListener() {
+
public void valueChange(ValueChangeEvent event) {
// This value change event is called twice if the new
// input value is an integer. The second time is during
@@ -56,6 +56,7 @@ public class Ticket6002 extends TestBase {
"Changing this field modifies the layout - do it twice",
property2);
tf2.addListener(new Property.ValueChangeListener() {
+
public void valueChange(ValueChangeEvent event) {
// This value change event is called twice if the new
// input value is an integer. The second time is during
diff --git a/tests/testbench/com/vaadin/tests/util/TestUtils.java b/tests/testbench/com/vaadin/tests/util/TestUtils.java
index 551e7a7ed8..a9e1518c54 100644
--- a/tests/testbench/com/vaadin/tests/util/TestUtils.java
+++ b/tests/testbench/com/vaadin/tests/util/TestUtils.java
@@ -112,7 +112,7 @@ public class TestUtils {
+ "document.body.style.WebkitAppearance=='string') /* webkit only */ ? 'innerText' "
+ ": 'innerHTML'] = '" + cssString + "';}";
- w.executeJavaScript(script);
+ w.getPage().getJavaScript().execute(script);
}
public static IndexedContainer getISO3166Container() {
diff --git a/tests/testbench/com/vaadin/tests/validation/RequiredErrorMessage.java b/tests/testbench/com/vaadin/tests/validation/RequiredErrorMessage.java
index e18b8ffd4e..7b03bc7ec2 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.Root.LegacyWindow;
import com.vaadin.ui.TextField;
import com.vaadin.ui.VerticalLayout;
-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 LegacyWindow main = new LegacyWindow(getClass().getName());
setMainWindow(main);
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 @@
+<module>
+ <!-- WS Compiler: manually edited -->
+
+ <!-- Inherit the DefaultWidgetSet -->
+ <inherits name="com.vaadin.terminal.gwt.DefaultWidgetSet" />
+</module>
diff --git a/tests/testbench/com/vaadin/tests/widgetset/client/ComplexTestBean.java b/tests/testbench/com/vaadin/tests/widgetset/client/ComplexTestBean.java
new file mode 100644
index 0000000000..e465ee2624
--- /dev/null
+++ b/tests/testbench/com/vaadin/tests/widgetset/client/ComplexTestBean.java
@@ -0,0 +1,70 @@
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+
+package com.vaadin.tests.widgetset.client;
+
+import java.util.List;
+
+import com.vaadin.terminal.gwt.client.communication.SharedState;
+
+@SuppressWarnings("javadoc")
+public class ComplexTestBean extends SharedState {
+ private SimpleTestBean innerBean1;
+ private SimpleTestBean innerBean2;
+ private List<SimpleTestBean> innerBeanCollection;
+ private int privimite;
+
+ public ComplexTestBean() {
+ // Default
+ }
+
+ public ComplexTestBean(SimpleTestBean innerBean1,
+ SimpleTestBean innerBean2,
+ List<SimpleTestBean> innerBeanCollection, int privimite) {
+ this.innerBean1 = innerBean1;
+ this.innerBean2 = innerBean2;
+ this.innerBeanCollection = innerBeanCollection;
+ this.privimite = privimite;
+ }
+
+ public SimpleTestBean getInnerBean1() {
+ return innerBean1;
+ }
+
+ public void setInnerBean1(SimpleTestBean innerBean) {
+ innerBean1 = innerBean;
+ }
+
+ public SimpleTestBean getInnerBean2() {
+ return innerBean2;
+ }
+
+ public void setInnerBean2(SimpleTestBean innerBean2) {
+ this.innerBean2 = innerBean2;
+ }
+
+ public List<SimpleTestBean> getInnerBeanCollection() {
+ return innerBeanCollection;
+ }
+
+ public void setInnerBeanCollection(List<SimpleTestBean> innerBeanCollection) {
+ this.innerBeanCollection = innerBeanCollection;
+ }
+
+ public int getPrivimite() {
+ return privimite;
+ }
+
+ public void setPrivimite(int privimite) {
+ this.privimite = privimite;
+ }
+
+ @Override
+ public String toString() {
+ return "ComplexTestBean [innerBean1=" + innerBean1 + ", innerBean2="
+ + innerBean2 + ", innerBeanCollection=" + innerBeanCollection
+ + ", privimite=" + privimite + "]";
+ }
+
+}
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/client/SerializerTestConnector.java b/tests/testbench/com/vaadin/tests/widgetset/client/SerializerTestConnector.java
new file mode 100644
index 0000000000..72bfbe285a
--- /dev/null
+++ b/tests/testbench/com/vaadin/tests/widgetset/client/SerializerTestConnector.java
@@ -0,0 +1,227 @@
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+
+package com.vaadin.tests.widgetset.client;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import com.vaadin.terminal.gwt.client.Connector;
+import com.vaadin.terminal.gwt.client.communication.RpcProxy;
+import com.vaadin.terminal.gwt.client.communication.StateChangeEvent;
+import com.vaadin.terminal.gwt.client.extensions.AbstractExtensionConnector;
+import com.vaadin.terminal.gwt.client.ui.Connect;
+import com.vaadin.tests.widgetset.server.SerializerTestExtension;
+
+@Connect(SerializerTestExtension.class)
+public class SerializerTestConnector extends AbstractExtensionConnector {
+
+ private SerializerTestRpc rpc = RpcProxy.create(SerializerTestRpc.class,
+ this);
+
+ public SerializerTestConnector() {
+ registerRpc(SerializerTestRpc.class, new SerializerTestRpc() {
+ public void sendWrappedGenerics(
+ Map<Set<SimpleTestBean>, Map<Integer, List<SimpleTestBean>>> generics) {
+ Map<Set<SimpleTestBean>, Map<Integer, List<SimpleTestBean>>> updated = new HashMap<Set<SimpleTestBean>, Map<Integer, List<SimpleTestBean>>>();
+
+ SimpleTestBean firstValue = generics.values().iterator().next()
+ .get(Integer.valueOf(1)).get(0);
+ Set<SimpleTestBean> key = new HashSet<SimpleTestBean>(Arrays
+ .asList(firstValue));
+
+ Map<Integer, List<SimpleTestBean>> value = new HashMap<Integer, List<SimpleTestBean>>();
+ Set<SimpleTestBean> firstKeyValue = generics.keySet()
+ .iterator().next();
+ value.put(Integer.valueOf(1), new ArrayList<SimpleTestBean>(
+ firstKeyValue));
+
+ updated.put(key, value);
+
+ rpc.sendWrappedGenerics(updated);
+ }
+
+ public void sendString(String value) {
+ char[] chars = value.toCharArray();
+ Arrays.sort(chars);
+ rpc.sendString(new String(chars));
+ }
+
+ public void sendSet(Set<Integer> intSet,
+ Set<Connector> connectorSet, Set<SimpleTestBean> beanSet) {
+
+ beanSet.iterator().next().setValue(intSet.size());
+ Set<Integer> updatedIntSet = new HashSet<Integer>();
+
+ for (Integer integer : intSet) {
+ updatedIntSet.add(Integer.valueOf(-integer.intValue()));
+ }
+ rpc.sendSet(updatedIntSet,
+ Collections.singleton(getRootConnector()), beanSet);
+ }
+
+ public void sendNestedArray(int[][] nestedIntArray,
+ SimpleTestBean[][] nestedBeanArray) {
+ rpc.sendNestedArray(new int[][] { { nestedIntArray[1][0],
+ nestedIntArray[0][0] } }, new SimpleTestBean[][] {
+ { nestedBeanArray[0][1] }, { nestedBeanArray[0][0] } });
+ }
+
+ public void sendMap(Map<String, SimpleTestBean> stringMap,
+ Map<Connector, Boolean> connectorMap,
+ Map<Integer, Connector> intMap,
+ Map<SimpleTestBean, SimpleTestBean> beanMap) {
+ Map<SimpleTestBean, SimpleTestBean> updatedBeanMap = new HashMap<SimpleTestBean, SimpleTestBean>();
+ for (Entry<SimpleTestBean, SimpleTestBean> entry : beanMap
+ .entrySet()) {
+ updatedBeanMap.put(entry.getValue(), entry.getKey());
+ }
+
+ rpc.sendMap(Collections.singletonMap("a", stringMap.get("b")),
+ Collections.singletonMap(getThisConnector(),
+ connectorMap.get(getRootConnector())),
+ Collections.singletonMap(
+ Integer.valueOf(stringMap.size()),
+ getThisConnector()), updatedBeanMap);
+ }
+
+ public void sendLong(long value, Long boxedValue, long[] array) {
+ rpc.sendLong(array[0], Long.valueOf(value), new long[] {
+ array[1], boxedValue.longValue() });
+ }
+
+ public void sendList(List<Integer> intList,
+ List<Connector> connectorList, List<SimpleTestBean> beanList) {
+ Collections.sort(intList);
+ Collections.reverse(beanList);
+ rpc.sendList(intList,
+ Arrays.asList(getThisConnector(), getRootConnector()),
+ beanList);
+ }
+
+ public void sendInt(int value, Integer boxedValue, int[] array) {
+ rpc.sendInt(array.length, Integer.valueOf(array[0]), new int[] {
+ value, boxedValue.intValue() });
+ }
+
+ public void sendFloat(float value, Float boxedValue, float[] array) {
+ Arrays.sort(array);
+ rpc.sendFloat(boxedValue.floatValue(), Float.valueOf(value),
+ array);
+ }
+
+ public void sendDouble(double value, Double boxedValue,
+ double[] array) {
+ rpc.sendDouble(value + boxedValue.doubleValue(),
+ Double.valueOf(value - boxedValue.doubleValue()),
+ new double[] { array.length, array[0], array[1] });
+ }
+
+ public void sendConnector(Connector connector) {
+ rpc.sendConnector(getThisConnector());
+ }
+
+ public void sendChar(char value, Character boxedValue, char[] array) {
+ rpc.sendChar(Character.toUpperCase(boxedValue.charValue()),
+ Character.valueOf(value), new String(array)
+ .toLowerCase().toCharArray());
+ }
+
+ public void sendByte(byte value, Byte boxedValue, byte[] array) {
+ // There will most certainly be a bug that is not discovered
+ // because this particular method doesn't do anything with it's
+ // values...
+ rpc.sendByte(value, boxedValue, array);
+ }
+
+ public void sendBoolean(boolean value, Boolean boxedValue,
+ boolean[] array) {
+ boolean[] inverseArray = new boolean[array.length];
+ for (int i = 0; i < array.length; i++) {
+ inverseArray[i] = !array[i];
+ }
+ rpc.sendBoolean(boxedValue == Boolean.TRUE,
+ Boolean.valueOf(!value), inverseArray);
+ }
+
+ public void sendBean(ComplexTestBean complexBean,
+ SimpleTestBean simpleBean, SimpleTestBean[] array) {
+ SimpleTestBean updatedSimpleBean = new SimpleTestBean();
+ updatedSimpleBean.setValue(complexBean.getInnerBean1()
+ .getValue());
+
+ ComplexTestBean updatedComplexBean = new ComplexTestBean();
+ updatedComplexBean.setInnerBean1(complexBean.getInnerBean2());
+ updatedComplexBean.setInnerBean2(complexBean
+ .getInnerBeanCollection().get(0));
+ updatedComplexBean.setInnerBeanCollection(Arrays.asList(
+ simpleBean, updatedSimpleBean));
+ updatedComplexBean.setPrivimite(complexBean.getPrivimite() + 1);
+
+ ArrayList<SimpleTestBean> arrayList = new ArrayList<SimpleTestBean>(
+ Arrays.asList(array));
+ Collections.reverse(arrayList);
+
+ rpc.sendBean(updatedComplexBean, updatedSimpleBean,
+ arrayList.toArray(new SimpleTestBean[array.length]));
+ }
+
+ public void sendArrayList(List<int[]> primitiveArrayList,
+ List<Integer[]> objectArrayList,
+ List<SimpleTestBean[]> beanArrayList) {
+ Collections.reverse(beanArrayList);
+ List<Integer[]> updatedObjectArrayList = new ArrayList<Integer[]>();
+ for (int[] array : primitiveArrayList) {
+ updatedObjectArrayList.add(new Integer[] {
+ Integer.valueOf(array.length),
+ Integer.valueOf(array[0]) });
+ }
+
+ rpc.sendArrayList(Arrays.asList(
+ new int[] { primitiveArrayList.size() },
+ new int[] { objectArrayList.get(0).length }),
+ updatedObjectArrayList, beanArrayList);
+ }
+
+ public void sendNull(String value1, String value2) {
+ rpc.sendNull(value2, value1);
+ }
+
+ public void sendListArray(List<Integer>[] objectListArray,
+ List<SimpleTestBean>[] beanListArray) {
+ rpc.sendListArray(new List[] { objectListArray[1],
+ objectListArray[0] }, new List[] { Collections
+ .singletonList(beanListArray[0].get(0)) });
+ }
+ });
+ }
+
+ private Connector getRootConnector() {
+ return getConnection().getRootConnector();
+ }
+
+ private Connector getThisConnector() {
+ // Cast to Connector for use in e.g. Collections.singleton() to get a
+ // Set<Connector>
+ return this;
+ }
+
+ @Override
+ public ComplexTestBean getState() {
+ return (ComplexTestBean) super.getState();
+ }
+
+ @Override
+ public void onStateChanged(StateChangeEvent stateChangeEvent) {
+ // TODO do something clever
+ }
+
+}
diff --git a/tests/testbench/com/vaadin/tests/widgetset/client/SerializerTestRpc.java b/tests/testbench/com/vaadin/tests/widgetset/client/SerializerTestRpc.java
new file mode 100644
index 0000000000..5b73e1d34d
--- /dev/null
+++ b/tests/testbench/com/vaadin/tests/widgetset/client/SerializerTestRpc.java
@@ -0,0 +1,64 @@
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+
+package com.vaadin.tests.widgetset.client;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import com.vaadin.terminal.gwt.client.Connector;
+import com.vaadin.terminal.gwt.client.communication.ClientRpc;
+import com.vaadin.terminal.gwt.client.communication.ServerRpc;
+
+@SuppressWarnings("javadoc")
+public interface SerializerTestRpc extends ServerRpc, ClientRpc {
+ public void sendBoolean(boolean value, Boolean boxedValue, boolean[] array);
+
+ public void sendByte(byte value, Byte boxedValue, byte[] array);
+
+ public void sendChar(char value, Character boxedValue, char[] array);
+
+ public void sendInt(int value, Integer boxedValue, int[] array);
+
+ public void sendLong(long value, Long boxedValue, long[] array);
+
+ public void sendFloat(float value, Float boxedValue, float[] array);
+
+ public void sendDouble(double value, Double boxedValue, double[] array);
+
+ public void sendString(String value);
+
+ public void sendConnector(Connector connector);
+
+ public void sendBean(ComplexTestBean complexBean,
+ SimpleTestBean simpleBean, SimpleTestBean[] array);
+
+ public void sendNull(String value1, String value2);
+
+ public void sendNestedArray(int[][] nestedIntArray,
+ SimpleTestBean[][] nestedBeanArray);
+
+ public void sendList(List<Integer> intList, List<Connector> connectorList,
+ List<SimpleTestBean> beanList);
+
+ public void sendArrayList(List<int[]> primitiveArrayList,
+ List<Integer[]> objectArrayList,
+ List<SimpleTestBean[]> beanArrayList);
+
+ public void sendListArray(List<Integer>[] objectListArray,
+ List<SimpleTestBean>[] beanListArray);
+
+ public void sendSet(Set<Integer> intSet, Set<Connector> connectorSet,
+ Set<SimpleTestBean> beanSet);
+
+ public void sendMap(Map<String, SimpleTestBean> stringMap,
+ Map<Connector, Boolean> connectorMap,
+ Map<Integer, Connector> intMap,
+ Map<SimpleTestBean, SimpleTestBean> beanMap);
+
+ public void sendWrappedGenerics(
+ Map<Set<SimpleTestBean>, Map<Integer, List<SimpleTestBean>>> generics);
+
+}
diff --git a/tests/testbench/com/vaadin/tests/widgetset/client/SimpleTestBean.java b/tests/testbench/com/vaadin/tests/widgetset/client/SimpleTestBean.java
new file mode 100644
index 0000000000..43ad51e758
--- /dev/null
+++ b/tests/testbench/com/vaadin/tests/widgetset/client/SimpleTestBean.java
@@ -0,0 +1,38 @@
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+
+package com.vaadin.tests.widgetset.client;
+
+import java.io.Serializable;
+
+public class SimpleTestBean implements Serializable {
+ private int value;
+
+ public SimpleTestBean() {
+ this(0);
+ }
+
+ public SimpleTestBean(int value) {
+ this.value = value;
+ }
+
+ public int getValue() {
+ return value;
+ }
+
+ public void setValue(int value) {
+ this.value = value;
+ }
+
+ @Override
+ public String toString() {
+ return "SimpleTestBean(" + value + ")";
+ }
+
+ @Override
+ public int hashCode() {
+ // Implement hash code to get consistent HashSet.toString
+ return value;
+ }
+} \ No newline at end of file
diff --git a/tests/testbench/com/vaadin/tests/widgetset/client/minitutorials/v7a2/ComponentInStateState.java b/tests/testbench/com/vaadin/tests/widgetset/client/minitutorials/v7a2/ComponentInStateState.java
new file mode 100644
index 0000000000..a5a5f504ab
--- /dev/null
+++ b/tests/testbench/com/vaadin/tests/widgetset/client/minitutorials/v7a2/ComponentInStateState.java
@@ -0,0 +1,20 @@
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+
+package com.vaadin.tests.widgetset.client.minitutorials.v7a2;
+
+import com.vaadin.terminal.gwt.client.ComponentState;
+import com.vaadin.terminal.gwt.client.Connector;
+
+public class ComponentInStateState extends ComponentState {
+ private Connector otherComponent;
+
+ public Connector getOtherComponent() {
+ return otherComponent;
+ }
+
+ public void setOtherComponent(Connector otherComponent) {
+ this.otherComponent = otherComponent;
+ }
+}
diff --git a/tests/testbench/com/vaadin/tests/widgetset/client/minitutorials/v7a2/ComponentInStateStateConnector.java b/tests/testbench/com/vaadin/tests/widgetset/client/minitutorials/v7a2/ComponentInStateStateConnector.java
new file mode 100644
index 0000000000..6e855f7c04
--- /dev/null
+++ b/tests/testbench/com/vaadin/tests/widgetset/client/minitutorials/v7a2/ComponentInStateStateConnector.java
@@ -0,0 +1,38 @@
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+
+package com.vaadin.tests.widgetset.client.minitutorials.v7a2;
+
+import com.google.gwt.user.client.ui.Label;
+import com.vaadin.terminal.gwt.client.ComponentConnector;
+import com.vaadin.terminal.gwt.client.communication.StateChangeEvent;
+import com.vaadin.terminal.gwt.client.ui.AbstractComponentConnector;
+import com.vaadin.terminal.gwt.client.ui.Connect;
+import com.vaadin.tests.minitutorials.v7a2.ComponentInStateComponent;
+
+@Connect(ComponentInStateComponent.class)
+public class ComponentInStateStateConnector extends AbstractComponentConnector {
+ @Override
+ public void onStateChanged(StateChangeEvent stateChangeEvent) {
+ super.onStateChanged(stateChangeEvent);
+
+ getWidget().setText(
+ "Client-side type of other component: "
+ + getOtherComponent().getClass().getName());
+ }
+
+ public ComponentConnector getOtherComponent() {
+ return (ComponentConnector) getState().getOtherComponent();
+ }
+
+ @Override
+ public ComponentInStateState getState() {
+ return (ComponentInStateState) super.getState();
+ }
+
+ @Override
+ public Label getWidget() {
+ return (Label) super.getWidget();
+ }
+}
diff --git a/tests/testbench/com/vaadin/tests/widgetset/client/minitutorials/v7a2/MyComponentClientRpc.java b/tests/testbench/com/vaadin/tests/widgetset/client/minitutorials/v7a2/MyComponentClientRpc.java
new file mode 100644
index 0000000000..68e2df533c
--- /dev/null
+++ b/tests/testbench/com/vaadin/tests/widgetset/client/minitutorials/v7a2/MyComponentClientRpc.java
@@ -0,0 +1,9 @@
+package com.vaadin.tests.widgetset.client.minitutorials.v7a2;
+
+import com.vaadin.terminal.gwt.client.communication.ClientRpc;
+
+public interface MyComponentClientRpc extends ClientRpc {
+
+ public void alert(String message);
+
+} \ No newline at end of file
diff --git a/tests/testbench/com/vaadin/tests/widgetset/client/minitutorials/v7a2/MyComponentConnector.java b/tests/testbench/com/vaadin/tests/widgetset/client/minitutorials/v7a2/MyComponentConnector.java
new file mode 100644
index 0000000000..2a131c07c8
--- /dev/null
+++ b/tests/testbench/com/vaadin/tests/widgetset/client/minitutorials/v7a2/MyComponentConnector.java
@@ -0,0 +1,56 @@
+package com.vaadin.tests.widgetset.client.minitutorials.v7a2;
+
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.ClickHandler;
+import com.google.gwt.user.client.Window;
+import com.vaadin.terminal.gwt.client.MouseEventDetails;
+import com.vaadin.terminal.gwt.client.MouseEventDetailsBuilder;
+import com.vaadin.terminal.gwt.client.communication.RpcProxy;
+import com.vaadin.terminal.gwt.client.communication.StateChangeEvent;
+import com.vaadin.terminal.gwt.client.ui.AbstractComponentConnector;
+import com.vaadin.terminal.gwt.client.ui.Connect;
+import com.vaadin.tests.minitutorials.v7a2.MyComponent;
+
+@Connect(MyComponent.class)
+public class MyComponentConnector extends AbstractComponentConnector {
+
+ MyComponentServerRpc rpc = RpcProxy
+ .create(MyComponentServerRpc.class, this);
+
+ public MyComponentConnector() {
+ getWidget().addClickHandler(new ClickHandler() {
+ public void onClick(ClickEvent event) {
+
+ final MouseEventDetails mouseDetails = MouseEventDetailsBuilder
+ .buildMouseEventDetails(event.getNativeEvent(),
+ getWidget().getElement());
+
+ rpc.clicked(mouseDetails);
+ }
+ });
+ registerRpc(MyComponentClientRpc.class, new MyComponentClientRpc() {
+ public void alert(String message) {
+ Window.alert(message);
+ }
+ });
+ }
+
+ @Override
+ public MyComponentState getState() {
+ return (MyComponentState) super.getState();
+ }
+
+ @Override
+ public void onStateChanged(StateChangeEvent stateChangeEvent) {
+ super.onStateChanged(stateChangeEvent);
+
+ final String text = getState().getText();
+ getWidget().setText(text);
+ }
+
+ @Override
+ public MyComponentWidget getWidget() {
+ return (MyComponentWidget) super.getWidget();
+ }
+
+} \ No newline at end of file
diff --git a/tests/testbench/com/vaadin/tests/widgetset/client/minitutorials/v7a2/MyComponentServerRpc.java b/tests/testbench/com/vaadin/tests/widgetset/client/minitutorials/v7a2/MyComponentServerRpc.java
new file mode 100644
index 0000000000..7f273c28d2
--- /dev/null
+++ b/tests/testbench/com/vaadin/tests/widgetset/client/minitutorials/v7a2/MyComponentServerRpc.java
@@ -0,0 +1,10 @@
+package com.vaadin.tests.widgetset.client.minitutorials.v7a2;
+
+import com.vaadin.terminal.gwt.client.MouseEventDetails;
+import com.vaadin.terminal.gwt.client.communication.ServerRpc;
+
+public interface MyComponentServerRpc extends ServerRpc {
+
+ public void clicked(MouseEventDetails mouseDetails);
+
+} \ No newline at end of file
diff --git a/tests/testbench/com/vaadin/tests/widgetset/client/minitutorials/v7a2/MyComponentState.java b/tests/testbench/com/vaadin/tests/widgetset/client/minitutorials/v7a2/MyComponentState.java
new file mode 100644
index 0000000000..a80aa7bca8
--- /dev/null
+++ b/tests/testbench/com/vaadin/tests/widgetset/client/minitutorials/v7a2/MyComponentState.java
@@ -0,0 +1,17 @@
+package com.vaadin.tests.widgetset.client.minitutorials.v7a2;
+
+import com.vaadin.terminal.gwt.client.ComponentState;
+
+public class MyComponentState extends ComponentState {
+
+ private String text;
+
+ public String getText() {
+ return text;
+ }
+
+ public void setText(String text) {
+ this.text = text;
+ }
+
+} \ No newline at end of file
diff --git a/tests/testbench/com/vaadin/tests/widgetset/client/minitutorials/v7a2/MyComponentWidget.java b/tests/testbench/com/vaadin/tests/widgetset/client/minitutorials/v7a2/MyComponentWidget.java
new file mode 100644
index 0000000000..ab03d51806
--- /dev/null
+++ b/tests/testbench/com/vaadin/tests/widgetset/client/minitutorials/v7a2/MyComponentWidget.java
@@ -0,0 +1,16 @@
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+
+package com.vaadin.tests.widgetset.client.minitutorials.v7a2;
+
+import com.google.gwt.user.client.ui.Label;
+
+public class MyComponentWidget extends Label {
+ public static final String CLASSNAME = "mycomponent";
+
+ public MyComponentWidget() {
+ setText("This is MyComponent");
+ setStyleName(CLASSNAME);
+ }
+}
diff --git a/tests/testbench/com/vaadin/tests/widgetset/client/minitutorials/v7a2/ResourceInStateConnector.java b/tests/testbench/com/vaadin/tests/widgetset/client/minitutorials/v7a2/ResourceInStateConnector.java
new file mode 100644
index 0000000000..f05d4a0eb9
--- /dev/null
+++ b/tests/testbench/com/vaadin/tests/widgetset/client/minitutorials/v7a2/ResourceInStateConnector.java
@@ -0,0 +1,38 @@
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+
+package com.vaadin.tests.widgetset.client.minitutorials.v7a2;
+
+import com.google.gwt.user.client.ui.Image;
+import com.vaadin.terminal.gwt.client.communication.StateChangeEvent;
+import com.vaadin.terminal.gwt.client.communication.URLReference;
+import com.vaadin.terminal.gwt.client.ui.AbstractComponentConnector;
+import com.vaadin.terminal.gwt.client.ui.Connect;
+import com.vaadin.tests.minitutorials.v7a2.ResourceInStateComponent;
+
+@Connect(ResourceInStateComponent.class)
+public class ResourceInStateConnector extends AbstractComponentConnector {
+ @Override
+ public void onStateChanged(StateChangeEvent stateChangeEvent) {
+ super.onStateChanged(stateChangeEvent);
+
+ URLReference icon = getState().getMyIcon();
+ if (icon != null) {
+ getWidget().setUrl(icon.getURL());
+ } else {
+ getWidget().setUrl("");
+ }
+
+ }
+
+ @Override
+ public ResourceInStateState getState() {
+ return (ResourceInStateState) super.getState();
+ }
+
+ @Override
+ public Image getWidget() {
+ return (Image) super.getWidget();
+ }
+}
diff --git a/tests/testbench/com/vaadin/tests/widgetset/client/minitutorials/v7a2/ResourceInStateState.java b/tests/testbench/com/vaadin/tests/widgetset/client/minitutorials/v7a2/ResourceInStateState.java
new file mode 100644
index 0000000000..7c124e7bf8
--- /dev/null
+++ b/tests/testbench/com/vaadin/tests/widgetset/client/minitutorials/v7a2/ResourceInStateState.java
@@ -0,0 +1,17 @@
+package com.vaadin.tests.widgetset.client.minitutorials.v7a2;
+
+import com.vaadin.terminal.gwt.client.ComponentState;
+import com.vaadin.terminal.gwt.client.communication.URLReference;
+
+public class ResourceInStateState extends ComponentState {
+
+ private URLReference myIcon;
+
+ public URLReference getMyIcon() {
+ return myIcon;
+ }
+
+ public void setMyIcon(URLReference icon) {
+ myIcon = icon;
+ }
+} \ No newline at end of file
diff --git a/tests/testbench/com/vaadin/tests/widgetset/client/minitutorials/v7a2/VWidgetContainer.java b/tests/testbench/com/vaadin/tests/widgetset/client/minitutorials/v7a2/VWidgetContainer.java
new file mode 100644
index 0000000000..6ec0a6da7c
--- /dev/null
+++ b/tests/testbench/com/vaadin/tests/widgetset/client/minitutorials/v7a2/VWidgetContainer.java
@@ -0,0 +1,12 @@
+package com.vaadin.tests.widgetset.client.minitutorials.v7a2;
+
+import com.google.gwt.user.client.ui.VerticalPanel;
+
+public class VWidgetContainer extends VerticalPanel {
+
+ public static final String CLASSNAME = "v-widgetcontainer";
+
+ public VWidgetContainer() {
+ setStyleName(CLASSNAME);
+ }
+} \ No newline at end of file
diff --git a/tests/testbench/com/vaadin/tests/widgetset/client/minitutorials/v7a2/WidgetContainerConnector.java b/tests/testbench/com/vaadin/tests/widgetset/client/minitutorials/v7a2/WidgetContainerConnector.java
new file mode 100644
index 0000000000..012060f437
--- /dev/null
+++ b/tests/testbench/com/vaadin/tests/widgetset/client/minitutorials/v7a2/WidgetContainerConnector.java
@@ -0,0 +1,35 @@
+package com.vaadin.tests.widgetset.client.minitutorials.v7a2;
+
+import java.util.List;
+
+import com.google.gwt.core.client.GWT;
+import com.google.gwt.user.client.ui.Widget;
+import com.vaadin.terminal.gwt.client.ComponentConnector;
+import com.vaadin.terminal.gwt.client.ConnectorHierarchyChangeEvent;
+import com.vaadin.terminal.gwt.client.ui.AbstractComponentContainerConnector;
+import com.vaadin.terminal.gwt.client.ui.Connect;
+import com.vaadin.tests.minitutorials.v7a2.WidgetContainer;
+
+@Connect(WidgetContainer.class)
+public class WidgetContainerConnector extends
+ AbstractComponentContainerConnector {
+
+ @Override
+ public void onConnectorHierarchyChange(ConnectorHierarchyChangeEvent event) {
+ List<ComponentConnector> children = getChildComponents();
+ VWidgetContainer widget = (VWidgetContainer) getWidget();
+ widget.clear();
+ for (ComponentConnector connector : children) {
+ widget.add(connector.getWidget());
+ }
+ super.onConnectorHierarchyChange(event);
+ }
+
+ @Override
+ protected Widget createWidget() {
+ return GWT.create(VWidgetContainer.class);
+ }
+
+ public void updateCaption(ComponentConnector connector) {
+ }
+} \ No newline at end of file
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 {
+
+}
diff --git a/tests/testbench/com/vaadin/tests/widgetset/server/SerializerTestExtension.java b/tests/testbench/com/vaadin/tests/widgetset/server/SerializerTestExtension.java
new file mode 100644
index 0000000000..99c05e8f76
--- /dev/null
+++ b/tests/testbench/com/vaadin/tests/widgetset/server/SerializerTestExtension.java
@@ -0,0 +1,22 @@
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+
+package com.vaadin.tests.widgetset.server;
+
+import com.vaadin.terminal.AbstractExtension;
+import com.vaadin.tests.widgetset.client.ComplexTestBean;
+import com.vaadin.tests.widgetset.client.SerializerTestRpc;
+
+public class SerializerTestExtension extends AbstractExtension {
+
+ @Override
+ public ComplexTestBean getState() {
+ return (ComplexTestBean) super.getState();
+ }
+
+ public void registerRpc(SerializerTestRpc rpc) {
+ super.registerRpc(rpc);
+ }
+
+}