diff options
19 files changed, 467 insertions, 24 deletions
diff --git a/client/src/com/vaadin/client/ApplicationConnection.java b/client/src/com/vaadin/client/ApplicationConnection.java index 1faf39394d..4141f9f2dc 100644 --- a/client/src/com/vaadin/client/ApplicationConnection.java +++ b/client/src/com/vaadin/client/ApplicationConnection.java @@ -27,6 +27,9 @@ import java.util.List; import java.util.Map; import java.util.Set; +import com.google.gwt.aria.client.LiveValue; +import com.google.gwt.aria.client.RelevantValue; +import com.google.gwt.aria.client.Roles; import com.google.gwt.core.client.Duration; import com.google.gwt.core.client.GWT; import com.google.gwt.core.client.JavaScriptObject; @@ -81,6 +84,7 @@ import com.vaadin.client.ui.AbstractConnector; import com.vaadin.client.ui.VContextMenu; import com.vaadin.client.ui.VNotification; import com.vaadin.client.ui.VNotification.HideEvent; +import com.vaadin.client.ui.VOverlay; import com.vaadin.client.ui.dd.VDragAndDropManager; import com.vaadin.client.ui.ui.UIConnector; import com.vaadin.client.ui.window.WindowConnector; @@ -456,6 +460,15 @@ public class ApplicationConnection { webkitMaybeIgnoringRequests = true; } }); + + // Ensure the overlay container is added to the dom and set as a live + // area for assistive devices + Element overlayContainer = VOverlay.getOverlayContainer(this); + Roles.getAlertRole().setAriaLiveProperty(overlayContainer, + LiveValue.ASSERTIVE); + setOverlayContainerLabel(getUIConnector().getState().overlayContainerLabel); + Roles.getAlertRole().setAriaRelevantProperty(overlayContainer, + RelevantValue.ADDITIONS); } /** @@ -3421,4 +3434,17 @@ public class ApplicationConnection { public void handlePushMessage(String message) { handleJSONText(message, 200); } + + /** + * Set the label of the container element, where tooltip, notification and + * dialgs are added to. + * + * @param overlayContainerLabel + * label for the container + */ + public void setOverlayContainerLabel(String overlayContainerLabel) { + Roles.getAlertRole().setAriaLabelProperty( + VOverlay.getOverlayContainer(this), + getUIConnector().getState().overlayContainerLabel); + } } diff --git a/client/src/com/vaadin/client/BrowserInfo.java b/client/src/com/vaadin/client/BrowserInfo.java index 73f3a68193..b3490c3ca4 100644 --- a/client/src/com/vaadin/client/BrowserInfo.java +++ b/client/src/com/vaadin/client/BrowserInfo.java @@ -396,10 +396,19 @@ public class BrowserInfo { && (getOperatingSystemMajorVersion() == 3 || getOperatingSystemMajorVersion() == 4); } + public boolean isAndroid23() { + return isAndroid() && getOperatingSystemMajorVersion() == 2 + && getOperatingSystemMinorVersion() == 3; + } + private int getOperatingSystemMajorVersion() { return browserDetails.getOperatingSystemMajorVersion(); } + private int getOperatingSystemMinorVersion() { + return browserDetails.getOperatingSystemMinorVersion(); + } + /** * Returns the browser major version e.g., 3 for Firefox 3.5, 4 for Chrome * 4, 8 for Internet Explorer 8. diff --git a/client/src/com/vaadin/client/VTooltip.java b/client/src/com/vaadin/client/VTooltip.java index 61d155d668..6191821988 100644 --- a/client/src/com/vaadin/client/VTooltip.java +++ b/client/src/com/vaadin/client/VTooltip.java @@ -16,7 +16,6 @@ package com.vaadin.client; import com.google.gwt.aria.client.Id; -import com.google.gwt.aria.client.LiveValue; import com.google.gwt.aria.client.Roles; import com.google.gwt.event.dom.client.BlurEvent; import com.google.gwt.event.dom.client.BlurHandler; @@ -86,10 +85,8 @@ public class VTooltip extends VOverlay { DOM.appendChild(layoutElement, description); setSinkShadowEvents(true); - // WAI-ARIA additions + // Used to bind the tooltip to the owner for assistive devices layoutElement.setId(uniqueId); - Roles.getTooltipRole().setAriaLiveProperty(getElement(), - LiveValue.POLITE); description.setId(DOM.createUniqueId()); Roles.getTooltipRole().set(layoutElement); diff --git a/client/src/com/vaadin/client/ui/VContextMenu.java b/client/src/com/vaadin/client/ui/VContextMenu.java index e601c8027a..02ee5b07c5 100644 --- a/client/src/com/vaadin/client/ui/VContextMenu.java +++ b/client/src/com/vaadin/client/ui/VContextMenu.java @@ -29,12 +29,17 @@ import com.google.gwt.event.dom.client.HasBlurHandlers; import com.google.gwt.event.dom.client.HasFocusHandlers; import com.google.gwt.event.dom.client.HasKeyDownHandlers; import com.google.gwt.event.dom.client.HasKeyPressHandlers; +import com.google.gwt.event.dom.client.KeyCodes; import com.google.gwt.event.dom.client.KeyDownEvent; import com.google.gwt.event.dom.client.KeyDownHandler; import com.google.gwt.event.dom.client.KeyPressEvent; import com.google.gwt.event.dom.client.KeyPressHandler; +import com.google.gwt.event.dom.client.KeyUpEvent; +import com.google.gwt.event.dom.client.KeyUpHandler; import com.google.gwt.event.dom.client.LoadEvent; import com.google.gwt.event.dom.client.LoadHandler; +import com.google.gwt.event.logical.shared.CloseEvent; +import com.google.gwt.event.logical.shared.CloseHandler; import com.google.gwt.event.shared.HandlerRegistration; import com.google.gwt.user.client.Command; import com.google.gwt.user.client.DOM; @@ -43,6 +48,7 @@ import com.google.gwt.user.client.Window; import com.google.gwt.user.client.ui.MenuBar; import com.google.gwt.user.client.ui.MenuItem; import com.google.gwt.user.client.ui.PopupPanel; +import com.google.gwt.user.client.ui.RootPanel; import com.google.gwt.user.client.ui.impl.FocusImpl; import com.vaadin.client.Focusable; import com.vaadin.client.Util; @@ -57,6 +63,8 @@ public class VContextMenu extends VOverlay implements SubPartAware { private int top; + private Element focusedElement; + private VLazyExecutor delayedImageLoadExecutioner = new VLazyExecutor(100, new ScheduledCommand() { @Override @@ -77,6 +85,20 @@ public class VContextMenu extends VOverlay implements SubPartAware { setWidget(menu); setStyleName("v-contextmenu"); getElement().setId(DOM.createUniqueId()); + + addCloseHandler(new CloseHandler<PopupPanel>() { + @Override + public void onClose(CloseEvent<PopupPanel> event) { + Element currentFocus = Util.getFocusedElement(); + if (focusedElement != null + && (currentFocus == null + || menu.getElement().isOrHasChild(currentFocus) || RootPanel + .getBodyElement().equals(currentFocus))) { + focusedElement.focus(); + focusedElement = null; + } + } + }); } protected void imagesLoaded() { @@ -117,6 +139,10 @@ public class VContextMenu extends VOverlay implements SubPartAware { // Attach onload listeners to all images Util.sinkOnloadForImages(menu.getElement()); + // Store the currently focused element, which will be re-focused when + // context menu is closed + focusedElement = Util.getFocusedElement(); + setPopupPositionAndShow(new PositionCallback() { @Override public void setPosition(int offsetWidth, int offsetHeight) { @@ -170,10 +196,11 @@ public class VContextMenu extends VOverlay implements SubPartAware { */ class CMenuBar extends MenuBar implements HasFocusHandlers, HasBlurHandlers, HasKeyDownHandlers, HasKeyPressHandlers, - Focusable, LoadHandler { + Focusable, LoadHandler, KeyUpHandler { public CMenuBar() { super(true); addDomHandler(this, LoadEvent.getType()); + addDomHandler(this, KeyUpEvent.getType()); } @Override @@ -242,6 +269,13 @@ public class VContextMenu extends VOverlay implements SubPartAware { delayedImageLoadExecutioner.trigger(); } + @Override + public void onKeyUp(KeyUpEvent event) { + // Allow to close context menu with ESC + if (event.getNativeKeyCode() == KeyCodes.KEY_ESCAPE) { + hide(); + } + } } @Override diff --git a/client/src/com/vaadin/client/ui/VFormLayout.java b/client/src/com/vaadin/client/ui/VFormLayout.java index b2dc13178e..6c2661d1d8 100644 --- a/client/src/com/vaadin/client/ui/VFormLayout.java +++ b/client/src/com/vaadin/client/ui/VFormLayout.java @@ -95,6 +95,8 @@ public class VFormLayout extends SimplePanel { public VFormLayoutTable() { DOM.setElementProperty(getElement(), "cellPadding", "0"); DOM.setElementProperty(getElement(), "cellSpacing", "0"); + + Roles.getPresentationRole().set(getElement()); } /* diff --git a/client/src/com/vaadin/client/ui/VOverlay.java b/client/src/com/vaadin/client/ui/VOverlay.java index d35201460e..9e809758ca 100644 --- a/client/src/com/vaadin/client/ui/VOverlay.java +++ b/client/src/com/vaadin/client/ui/VOverlay.java @@ -27,6 +27,7 @@ import com.google.gwt.event.logical.shared.CloseEvent; import com.google.gwt.event.logical.shared.CloseHandler; import com.google.gwt.user.client.DOM; import com.google.gwt.user.client.Element; +import com.google.gwt.user.client.Window; import com.google.gwt.user.client.ui.PopupPanel; import com.google.gwt.user.client.ui.RootPanel; import com.google.gwt.user.client.ui.Widget; @@ -689,4 +690,68 @@ public class VOverlay extends PopupPanel implements CloseHandler<PopupPanel> { return container; } + @Override + public void center() { + super.center(); + + // Some devices can be zoomed in, we should center to the visual + // viewport for those devices + BrowserInfo b = BrowserInfo.get(); + if (b.isAndroid() || b.isIOS()) { + int left = (getVisualViewportWidth() - getOffsetWidth()) >> 1; + int top = (getVisualViewportHeight() - getOffsetHeight()) >> 1; + setPopupPosition(Math.max(Window.getScrollLeft() + left, 0), + Math.max(Window.getScrollTop() + top, 0)); + } + + } + + /** + * Gets the visual viewport width, which is useful for e.g iOS where the + * view can be zoomed in while keeping the layout viewport intact. + * + * Falls back to layout viewport; for those browsers/devices the difference + * is that the scrollbar with is included (if there is a scrollbar). + * + * @since 7.0.7 + * @return + */ + private int getVisualViewportWidth() { + int w = (int) getSubpixelInnerWidth(); + if (w < 0) { + return Window.getClientWidth(); + } else { + return w; + } + } + + /** + * Gets the visual viewport height, which is useful for e.g iOS where the + * view can be zoomed in while keeping the layout viewport intact. + * + * Falls back to layout viewport; for those browsers/devices the difference + * is that the scrollbar with is included (if there is a scrollbar). + * + * @since 7.0.7 + * @return + */ + private int getVisualViewportHeight() { + int h = (int) getSubpixelInnerHeight(); + if (h < 0) { + return Window.getClientHeight(); + } else { + return h; + } + } + + private native double getSubpixelInnerWidth() + /*-{ + return $wnd.innerWidth !== undefined ? $wnd.innerWidth : -1; + }-*/; + + private native double getSubpixelInnerHeight() + /*-{ + return $wnd.innerHeight !== undefined ? $wnd.innerHeight :-1; + }-*/; + } diff --git a/client/src/com/vaadin/client/ui/VScrollTable.java b/client/src/com/vaadin/client/ui/VScrollTable.java index 8705a826cc..e2e82a1959 100644 --- a/client/src/com/vaadin/client/ui/VScrollTable.java +++ b/client/src/com/vaadin/client/ui/VScrollTable.java @@ -6692,6 +6692,17 @@ public class VScrollTable extends FlowPanel implements HasWidgets, private void setContainerHeight() { if (!isDynamicHeight()) { + + /* + * Android 2.3 cannot measure the height of the inline-block + * properly, and will return the wrong offset height. So for android + * 2.3 we set the element to a block element while measuring and + * then restore it which yields the correct result. #11331 + */ + if (BrowserInfo.get().isAndroid23()) { + getElement().getStyle().setDisplay(Display.BLOCK); + } + containerHeight = getOffsetHeight(); containerHeight -= showColHeaders ? tHead.getOffsetHeight() : 0; containerHeight -= tFoot.getOffsetHeight(); @@ -6699,7 +6710,12 @@ public class VScrollTable extends FlowPanel implements HasWidgets, if (containerHeight < 0) { containerHeight = 0; } + scrollBodyPanel.setHeight(containerHeight + "px"); + + if (BrowserInfo.get().isAndroid23()) { + getElement().getStyle().clearDisplay(); + } } } diff --git a/client/src/com/vaadin/client/ui/VTextualDate.java b/client/src/com/vaadin/client/ui/VTextualDate.java index 9307455a83..9d7e31faab 100644 --- a/client/src/com/vaadin/client/ui/VTextualDate.java +++ b/client/src/com/vaadin/client/ui/VTextualDate.java @@ -82,6 +82,9 @@ public class VTextualDate extends VDateField implements Field, ChangeHandler, getClient() .updateVariable(getId(), EventId.FOCUS, "", true); } + + // Needed for tooltip event handling + VTextualDate.this.fireEvent(event); } }); text.addBlurHandler(new BlurHandler() { @@ -100,6 +103,9 @@ public class VTextualDate extends VDateField implements Field, ChangeHandler, EventId.BLUR)) { getClient().updateVariable(getId(), EventId.BLUR, "", true); } + + // Needed for tooltip event handling + VTextualDate.this.fireEvent(event); } }); diff --git a/client/src/com/vaadin/client/ui/ui/UIConnector.java b/client/src/com/vaadin/client/ui/ui/UIConnector.java index 079e133438..643d687f1d 100644 --- a/client/src/com/vaadin/client/ui/ui/UIConnector.java +++ b/client/src/com/vaadin/client/ui/ui/UIConnector.java @@ -68,6 +68,7 @@ import com.vaadin.shared.ui.ComponentStateUtil; import com.vaadin.shared.ui.Connect; import com.vaadin.shared.ui.Connect.LoadStyle; import com.vaadin.shared.ui.ui.PageClientRpc; +import com.vaadin.shared.ui.ui.PageState; import com.vaadin.shared.ui.ui.ScrollClientRpc; import com.vaadin.shared.ui.ui.UIClientRpc; import com.vaadin.shared.ui.ui.UIConstants; @@ -138,7 +139,7 @@ public class UIConnector extends AbstractSingleComponentContainerConnector getRpcProxy(UIServerRpc.class).resize(event.getHeight(), event.getWidth(), Window.getClientWidth(), Window.getClientHeight()); - if (getState().immediate) { + if (getState().immediate || getPageState().hasResizeListeners) { getConnection().sendPendingVariableChanges(); } } @@ -504,6 +505,23 @@ public class UIConnector extends AbstractSingleComponentContainerConnector return (UIState) super.getState(); } + /** + * Returns the state of the Page associated with the UI. + * <p> + * Note that state is considered an internal part of the connector. You + * should not rely on the state object outside of the connector who owns it. + * If you depend on the state of other connectors you should use their + * public API instead of their state object directly. The page state might + * not be an independent state object but can be embedded in UI state. + * </p> + * + * @since 7.1 + * @return state object of the page + */ + public PageState getPageState() { + return getState().pageState; + } + @Override public void onConnectorHierarchyChange(ConnectorHierarchyChangeEvent event) { ComponentConnector oldChild = null; @@ -611,6 +629,11 @@ public class UIConnector extends AbstractSingleComponentContainerConnector if (stateChangeEvent.hasPropertyChanged("pushMode")) { getConnection().setPushEnabled(getState().pushMode.isEnabled()); } + + if (stateChangeEvent.hasPropertyChanged("overlayContainerLabel")) { + getConnection().setOverlayContainerLabel( + getState().overlayContainerLabel); + } } private void configurePolling() { diff --git a/scripts/automerge7.sh b/scripts/automerge7.sh index 564296f5db..7b8c37a5aa 100755 --- a/scripts/automerge7.sh +++ b/scripts/automerge7.sh @@ -67,6 +67,14 @@ maybe_commit_and_push() { pushMerged } +can_merge() { + commit=$1 + git merge --no-commit --no-ff $commit > /dev/null 2>&1 + result=$? + git reset --hard HEAD > /dev/null 2>&1 + return $result +} + nothingToCommit=`git status | grep "nothing to commit"` if [ "$nothingToCommit" == "" ] then @@ -89,9 +97,21 @@ do commitMsg=`git log -n 1 --format=oneline --abbrev-commit $commit` if [ "$mergeDirective" == "" ] then - pendingCommit=$commit - pendingCommitMessage=$pendingCommitMessage"$commitMsg\n" - echo pendingCommitMessage: $pendingCommitMessage + if can_merge $commit + then + pendingCommit=$commit + pendingCommitMessage=$pendingCommitMessage"$commitMsg\n" + echo pendingCommitMessage: $pendingCommitMessage + else + maybe_commit_and_push $pendingCommit "$pendingCommitMessage" + pendingCommit= + pendingCommitMessage= + echo + echo "Stopping merge because $commit because of merge conflicts" + echo "The following commit must be manually merged." + show $commit + exit 3 + fi elif [ "$mergeDirective" == "no" ] then maybe_commit_and_push $pendingCommit "$pendingCommitMessage" diff --git a/server/src/com/vaadin/server/Page.java b/server/src/com/vaadin/server/Page.java index a7e0f7dcb3..d4c16fe7f7 100644 --- a/server/src/com/vaadin/server/Page.java +++ b/server/src/com/vaadin/server/Page.java @@ -30,7 +30,9 @@ import java.util.Map; import com.vaadin.event.EventRouter; import com.vaadin.shared.ui.BorderStyle; import com.vaadin.shared.ui.ui.PageClientRpc; +import com.vaadin.shared.ui.ui.PageState; import com.vaadin.shared.ui.ui.UIConstants; +import com.vaadin.shared.ui.ui.UIState; import com.vaadin.ui.JavaScript; import com.vaadin.ui.LegacyWindow; import com.vaadin.ui.Link; @@ -220,7 +222,7 @@ public class Page implements Serializable { } } - private static final Method BROWSWER_RESIZE_METHOD = ReflectTools + private static final Method BROWSER_RESIZE_METHOD = ReflectTools .findMethod(BrowserWindowResizeListener.class, "browserWindowResized", BrowserWindowResizeEvent.class); @@ -417,8 +419,11 @@ public class Page implements Serializable { */ private URI location; - public Page(UI uI) { + private final PageState state; + + public Page(UI uI, PageState state) { this.uI = uI; + this.state = state; } private void addListener(Class<?> eventType, Object target, Method method) { @@ -604,20 +609,27 @@ public class Page implements Serializable { } /** - * Adds a new {@link BrowserWindowResizeListener} to this uI. The listener - * will be notified whenever the browser window within which this uI resides + * Adds a new {@link BrowserWindowResizeListener} to this UI. The listener + * will be notified whenever the browser window within which this UI resides * is resized. + * <p> + * In most cases, the UI should be in lazy resize mode when using browser + * window resize listeners. Otherwise, a large number of events can be + * received while a resize is being performed. Use + * {@link UI#setResizeLazy(boolean)}. + * </p> * * @param resizeListener * the listener to add * * @see BrowserWindowResizeListener#browserWindowResized(BrowserWindowResizeEvent) - * @see #setResizeLazy(boolean) + * @see UI#setResizeLazy(boolean) */ public void addBrowserWindowResizeListener( BrowserWindowResizeListener resizeListener) { addListener(BrowserWindowResizeEvent.class, resizeListener, - BROWSWER_RESIZE_METHOD); + BROWSER_RESIZE_METHOD); + getState(true).hasResizeListeners = true; } /** @@ -639,7 +651,9 @@ public class Page implements Serializable { public void removeBrowserWindowResizeListener( BrowserWindowResizeListener resizeListener) { removeListener(BrowserWindowResizeEvent.class, resizeListener, - BROWSWER_RESIZE_METHOD); + BROWSER_RESIZE_METHOD); + getState(true).hasResizeListeners = eventRouter + .hasListeners(BrowserWindowResizeEvent.class); } /** @@ -1038,4 +1052,29 @@ public class Page implements Serializable { uI.getRpcProxy(PageClientRpc.class).reload(); } + /** + * Returns the page state. + * <p> + * The page state is transmitted to UIConnector together with + * {@link UIState} rather than as an individual entity. + * </p> + * <p> + * The state should be considered an internal detail of Page. Classes + * outside of Page should not access it directly but only through public + * APIs provided by Page. + * </p> + * + * @since 7.1 + * @param markAsDirty + * true to mark the state as dirty + * @return PageState object that can be read in any case and modified if + * markAsDirty is true + */ + protected PageState getState(boolean markAsDirty) { + if (markAsDirty) { + uI.markAsDirty(); + } + return state; + } + } diff --git a/server/src/com/vaadin/ui/AbstractField.java b/server/src/com/vaadin/ui/AbstractField.java index 6648f69ff9..3bca63a3b7 100644 --- a/server/src/com/vaadin/ui/AbstractField.java +++ b/server/src/com/vaadin/ui/AbstractField.java @@ -323,7 +323,7 @@ public abstract class AbstractField<T> extends AbstractComponent implements */ @Override public boolean isModified() { - return getState().modified; + return getState(false).modified; } private void setModified(boolean modified) { @@ -1276,7 +1276,7 @@ public abstract class AbstractField<T> extends AbstractComponent implements */ @Override public int getTabIndex() { - return getState().tabIndex; + return getState(false).tabIndex; } /* @@ -1408,7 +1408,7 @@ public abstract class AbstractField<T> extends AbstractComponent implements */ @Override public boolean isRequired() { - return getState().required; + return getState(false).required; } /** @@ -1663,6 +1663,11 @@ public abstract class AbstractField<T> extends AbstractComponent implements } @Override + protected AbstractFieldState getState(boolean markAsDirty) { + return (AbstractFieldState) super.getState(markAsDirty); + } + + @Override public void beforeClientResponse(boolean initial) { super.beforeClientResponse(initial); diff --git a/server/src/com/vaadin/ui/UI.java b/server/src/com/vaadin/ui/UI.java index 3574c5527d..0a4ed7c491 100644 --- a/server/src/com/vaadin/ui/UI.java +++ b/server/src/com/vaadin/ui/UI.java @@ -117,7 +117,7 @@ public abstract class UI extends AbstractSingleComponentContainer implements /** Identifies the click event */ private ConnectorTracker connectorTracker = new ConnectorTracker(this); - private Page page = new Page(this); + private Page page = new Page(this, getState(false).pageState); private LoadingIndicatorConfiguration loadingIndicatorConfiguration = new LoadingIndicatorConfigurationImpl( this); @@ -686,10 +686,16 @@ public abstract class UI extends AbstractSingleComponentContainer implements /** * Should resize operations be lazy, i.e. should there be a delay before - * layout sizes are recalculated. Speeds up resize operations in slow UIs - * with the penalty of slightly decreased usability. + * layout sizes are recalculated and resize events are sent to the server. + * Speeds up resize operations in slow UIs with the penalty of slightly + * decreased usability. * <p> * Default value: <code>false</code> + * </p> + * <p> + * When there are active window resize listeners, lazy resize mode should be + * used to avoid a large number of events during resize. + * </p> * * @param resizeLazy * true to use a delay before recalculating sizes, false to @@ -1327,4 +1333,28 @@ public abstract class UI extends AbstractSingleComponentContainer implements getState().pushMode = pushMode; } + /** + * Get the label that is added to the container element, where tooltip, + * notification and dialogs are added to. + * + * @return the label of the container + */ + public String getOverlayContainerLabel() { + return getState().overlayContainerLabel; + } + + /** + * Sets the label that is added to the container element, where tooltip, + * notifications and dialogs are added to. + * <p> + * This is helpful for users of assistive devices, as this element is + * reachable for them. + * </p> + * + * @param overlayContainerLabel + * label to use for the container + */ + public void setOverlayContainerLabel(String overlayContainerLabel) { + getState().overlayContainerLabel = overlayContainerLabel; + } } diff --git a/server/tests/src/com/vaadin/server/VaadinSessionTest.java b/server/tests/src/com/vaadin/server/VaadinSessionTest.java index 8f471afd46..61a1581a6f 100644 --- a/server/tests/src/com/vaadin/server/VaadinSessionTest.java +++ b/server/tests/src/com/vaadin/server/VaadinSessionTest.java @@ -74,7 +74,7 @@ public class VaadinSessionTest { session.storeInSession(mockService, mockWrappedSession); ui = new UI() { - Page page = new Page(this) { + Page page = new Page(this, getState(false).pageState) { @Override public void init(VaadinRequest request) { } diff --git a/shared/src/com/vaadin/shared/ui/ui/PageState.java b/shared/src/com/vaadin/shared/ui/ui/PageState.java new file mode 100644 index 0000000000..0b51eb4bba --- /dev/null +++ b/shared/src/com/vaadin/shared/ui/ui/PageState.java @@ -0,0 +1,33 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.vaadin.shared.ui.ui; + +import java.io.Serializable; + +/** + * The shared state of a {@link com.vaadin.server.Page Page}. + * + * Note that at the moment this is not a stand-alone state class but embedded in + * {@link UIState}. This might change in the future. + * + * @since 7.1 + */ +public class PageState implements Serializable { + /** + * True if the page has browser window resize listeners. + */ + public boolean hasResizeListeners = false; +}
\ No newline at end of file diff --git a/shared/src/com/vaadin/shared/ui/ui/UIState.java b/shared/src/com/vaadin/shared/ui/ui/UIState.java index e8be9d674c..16c1ed16c7 100644 --- a/shared/src/com/vaadin/shared/ui/ui/UIState.java +++ b/shared/src/com/vaadin/shared/ui/ui/UIState.java @@ -27,6 +27,10 @@ public class UIState extends TabIndexState { public PushMode pushMode = PushMode.DISABLED; + // Informing users of assistive devices, that the content of this container + // is announced automatically and does not need to be navigated into + public String overlayContainerLabel = "This content is announced automatically and does not need to be navigated into."; + public static class LoadingIndicatorConfigurationState implements Serializable { public int firstDelay = 300; @@ -42,9 +46,14 @@ public class UIState extends TabIndexState { public int maxWidth = 500; } + /** + * State related to the {@link Page} class. + */ + public PageState pageState = new PageState(); + { primaryStyleName = "v-ui"; // Default is 1 for legacy reasons tabIndex = 1; } -}
\ No newline at end of file +} diff --git a/uitest/src/com/vaadin/tests/components/gridlayout/GridLayoutWithNonIntegerWidth.java b/uitest/src/com/vaadin/tests/components/gridlayout/GridLayoutWithNonIntegerWidth.java new file mode 100644 index 0000000000..8312b15ba7 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/gridlayout/GridLayoutWithNonIntegerWidth.java @@ -0,0 +1,53 @@ +package com.vaadin.tests.components.gridlayout; + +import com.vaadin.server.VaadinRequest; +import com.vaadin.tests.components.AbstractTestUI; +import com.vaadin.ui.GridLayout; +import com.vaadin.ui.HorizontalLayout; +import com.vaadin.ui.Label; +import com.vaadin.ui.Panel; +import com.vaadin.ui.VerticalLayout; + +/** + * Main UI class + */ +@SuppressWarnings("serial") +public class GridLayoutWithNonIntegerWidth extends AbstractTestUI { + + @Override + protected void setup(VaadinRequest request) { + Panel p1 = new Panel("Panel with GridLayout"); + GridLayout grid = new GridLayout(1, 1, new Label("A")); + grid.setWidth(100, Unit.PERCENTAGE); + p1.setContent(grid); + p1.setWidth("354.390625px"); + + Panel p2 = new Panel("Panel with HorizontalLayout"); + HorizontalLayout hl = new HorizontalLayout(new Label("A")); + hl.setWidth(100, Unit.PERCENTAGE); + p2.setContent(hl); + p2.setWidth("354.390625px"); + + setContent(new VerticalLayout(p1, p2)); + } + + /* + * (non-Javadoc) + * + * @see com.vaadin.tests.components.AbstractTestUI#getTestDescription() + */ + @Override + protected String getTestDescription() { + return "Neither of the panels should contain scrollbars"; + } + + /* + * (non-Javadoc) + * + * @see com.vaadin.tests.components.AbstractTestUI#getTicketNumber() + */ + @Override + protected Integer getTicketNumber() { + return 11775; + } +}
\ No newline at end of file diff --git a/uitest/src/com/vaadin/tests/components/ui/TooltipConfiguration.html b/uitest/src/com/vaadin/tests/components/ui/TooltipConfiguration.html index c1734481c6..e41cf5e176 100644 --- a/uitest/src/com/vaadin/tests/components/ui/TooltipConfiguration.html +++ b/uitest/src/com/vaadin/tests/components/ui/TooltipConfiguration.html @@ -55,6 +55,11 @@ </tr> <tr> <td>mouseMoveAt</td> + <td>vaadin=runcomvaadintestscomponentsuiTooltipConfiguration::</td> + <td>0,0</td> +</tr> +<tr> + <td>mouseMoveAt</td> <td>vaadin=runcomvaadintestscomponentsuiTooltipConfiguration::PID_SshortTooltip</td> <td>0,0</td> </tr> @@ -117,6 +122,11 @@ </tr> <tr> <td>mouseMoveAt</td> + <td>vaadin=runcomvaadintestscomponentsuiTooltipConfiguration::</td> + <td>0,0</td> +</tr> +<tr> + <td>mouseMoveAt</td> <td>vaadin=runcomvaadintestscomponentsuiTooltipConfiguration::PID_SlongTooltip</td> <td>0,0</td> </tr> diff --git a/uitest/src/com/vaadin/tests/components/window/CenteredInVisualViewport.java b/uitest/src/com/vaadin/tests/components/window/CenteredInVisualViewport.java new file mode 100644 index 0000000000..428b2ae3f9 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/window/CenteredInVisualViewport.java @@ -0,0 +1,66 @@ +package com.vaadin.tests.components.window; + +import com.vaadin.tests.components.TestBase; +import com.vaadin.ui.Button; +import com.vaadin.ui.Button.ClickEvent; +import com.vaadin.ui.GridLayout; +import com.vaadin.ui.Label; +import com.vaadin.ui.Window; + +public class CenteredInVisualViewport extends TestBase { + + @Override + protected String getDescription() { + return "Should open centered, even if zoomed in on one button (e.g zoom in iOS)"; + } + + @Override + protected Integer getTicketNumber() { + return 11614; + } + + @Override + protected void setup() { + GridLayout layout = new GridLayout(3, 3); + layout.setWidth("1000px"); + layout.setHeight("1000px"); + addComponent(layout); + + Button b = new Button("Open", new Button.ClickListener() { + + @Override + public void buttonClick(ClickEvent event) { + Window centered = new Window("A window", new Label( + "Centered window")); + centered.center(); + getMainWindow().addWindow(centered); + } + }); + layout.addComponent(b, 0, 0); + + b = new Button("Open", new Button.ClickListener() { + + @Override + public void buttonClick(ClickEvent event) { + Window centered = new Window("A window", new Label( + "Centered window")); + centered.center(); + getMainWindow().addWindow(centered); + } + }); + layout.addComponent(b, 1, 1); + + b = new Button("Open", new Button.ClickListener() { + + @Override + public void buttonClick(ClickEvent event) { + Window centered = new Window("A window", new Label( + "Centered window")); + centered.center(); + getMainWindow().addWindow(centered); + } + }); + layout.addComponent(b, 2, 2); + + } +} |