diff options
Diffstat (limited to 'client')
12 files changed, 334 insertions, 14 deletions
diff --git a/client/src/com/vaadin/client/BrowserInfo.java b/client/src/com/vaadin/client/BrowserInfo.java index fab393eedc..2f8c70e183 100644 --- a/client/src/com/vaadin/client/BrowserInfo.java +++ b/client/src/com/vaadin/client/BrowserInfo.java @@ -229,6 +229,10 @@ public class BrowserInfo { return isIE() && getBrowserMajorVersion() == 9; } + public boolean isIE10() { + return isIE() && getBrowserMajorVersion() == 10; + } + public boolean isChrome() { return browserDetails.isChrome(); } diff --git a/client/src/com/vaadin/client/ComponentLocator.java b/client/src/com/vaadin/client/ComponentLocator.java index e69c55d445..47fb29777c 100644 --- a/client/src/com/vaadin/client/ComponentLocator.java +++ b/client/src/com/vaadin/client/ComponentLocator.java @@ -332,6 +332,11 @@ public class ComponentLocator { } catch (Exception e) { return null; } + + if (element == null) { + return null; + } + } } diff --git a/client/src/com/vaadin/client/Util.java b/client/src/com/vaadin/client/Util.java index 7aea69a61d..bf4dca7712 100644 --- a/client/src/com/vaadin/client/Util.java +++ b/client/src/com/vaadin/client/Util.java @@ -25,11 +25,13 @@ import java.util.List; import com.google.gwt.core.client.Scheduler; import com.google.gwt.core.client.Scheduler.ScheduledCommand; import com.google.gwt.dom.client.AnchorElement; +import com.google.gwt.dom.client.DivElement; import com.google.gwt.dom.client.Document; import com.google.gwt.dom.client.NativeEvent; import com.google.gwt.dom.client.Node; import com.google.gwt.dom.client.NodeList; import com.google.gwt.dom.client.Style; +import com.google.gwt.dom.client.Style.Display; import com.google.gwt.dom.client.Touch; import com.google.gwt.user.client.Command; import com.google.gwt.user.client.DOM; @@ -1207,8 +1209,23 @@ public class Util { * @return the corresponding absolute URL as a string */ public static String getAbsoluteUrl(String url) { - AnchorElement a = Document.get().createAnchorElement(); - a.setHref(url); - return a.getHref(); + if (BrowserInfo.get().isIE8()) { + // The hard way - must use innerHTML and attach to DOM in IE8 + DivElement divElement = Document.get().createDivElement(); + divElement.getStyle().setDisplay(Display.NONE); + + RootPanel.getBodyElement().appendChild(divElement); + divElement.setInnerHTML("<a href='" + escapeHTML(url) + "' ></a>"); + + AnchorElement a = divElement.getChild(0).cast(); + String href = a.getHref(); + + RootPanel.getBodyElement().removeChild(divElement); + return href; + } else { + AnchorElement a = Document.get().createAnchorElement(); + a.setHref(url); + return a.getHref(); + } } } diff --git a/client/src/com/vaadin/client/extensions/BrowserPopupOpenerConnector.java b/client/src/com/vaadin/client/extensions/BrowserPopupOpenerConnector.java new file mode 100644 index 0000000000..2615444832 --- /dev/null +++ b/client/src/com/vaadin/client/extensions/BrowserPopupOpenerConnector.java @@ -0,0 +1,58 @@ +/* + * Copyright 2012 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.client.extensions; + +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.Widget; +import com.vaadin.client.ComponentConnector; +import com.vaadin.client.ServerConnector; +import com.vaadin.server.BrowserPopupOpener; +import com.vaadin.shared.ui.BrowserPopupExtensionState; +import com.vaadin.shared.ui.Connect; + +/** + * Client-side code for {@link BrowserPopupOpener} + * + * @author Vaadin Ltd + * @since 7.0.0 + */ +@Connect(BrowserPopupOpener.class) +public class BrowserPopupOpenerConnector extends AbstractExtensionConnector + implements ClickHandler { + + @Override + protected void extend(ServerConnector target) { + final Widget targetWidget = ((ComponentConnector) target).getWidget(); + + targetWidget.addDomHandler(this, ClickEvent.getType()); + } + + @Override + public BrowserPopupExtensionState getState() { + return (BrowserPopupExtensionState) super.getState(); + } + + @Override + public void onClick(ClickEvent event) { + String url = getResourceUrl("popup"); + if (url != null) { + Window.open(url, getState().target, getState().features); + } + } +} diff --git a/client/src/com/vaadin/client/extensions/FileDownloaderConnector.java b/client/src/com/vaadin/client/extensions/FileDownloaderConnector.java new file mode 100644 index 0000000000..6308de9c05 --- /dev/null +++ b/client/src/com/vaadin/client/extensions/FileDownloaderConnector.java @@ -0,0 +1,77 @@ +/* + * Copyright 2012 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.client.extensions; + +import com.google.gwt.dom.client.Document; +import com.google.gwt.dom.client.IFrameElement; +import com.google.gwt.dom.client.Style; +import com.google.gwt.dom.client.Style.Unit; +import com.google.gwt.dom.client.Style.Visibility; +import com.google.gwt.event.dom.client.ClickEvent; +import com.google.gwt.event.dom.client.ClickHandler; +import com.google.gwt.user.client.ui.RootPanel; +import com.google.gwt.user.client.ui.Widget; +import com.vaadin.client.ComponentConnector; +import com.vaadin.client.ServerConnector; +import com.vaadin.server.FileDownloader; +import com.vaadin.shared.ui.Connect; + +@Connect(FileDownloader.class) +public class FileDownloaderConnector extends AbstractExtensionConnector + implements ClickHandler { + + private IFrameElement iframe; + + @Override + protected void extend(ServerConnector target) { + final Widget downloadWidget = ((ComponentConnector) target).getWidget(); + + downloadWidget.addDomHandler(this, ClickEvent.getType()); + } + + @Override + public void onClick(ClickEvent event) { + final String url = getResourceUrl("dl"); + if (url != null && !url.isEmpty()) { + if (iframe != null) { + // make sure it is not on dom tree already, might start + // multiple downloads at once + iframe.removeFromParent(); + } + iframe = Document.get().createIFrameElement(); + + Style style = iframe.getStyle(); + style.setVisibility(Visibility.HIDDEN); + style.setHeight(0, Unit.PX); + style.setWidth(0, Unit.PX); + + iframe.setFrameBorder(0); + iframe.setTabIndex(-1); + iframe.setSrc(url); + RootPanel.getBodyElement().appendChild(iframe); + } + } + + @Override + public void setParent(ServerConnector parent) { + super.setParent(parent); + if (parent == null) { + iframe.removeFromParent(); + } + } + +} diff --git a/client/src/com/vaadin/client/metadata/TypeDataBundle.java b/client/src/com/vaadin/client/metadata/TypeDataBundle.java index 158672e3a6..96f4884d52 100644 --- a/client/src/com/vaadin/client/metadata/TypeDataBundle.java +++ b/client/src/com/vaadin/client/metadata/TypeDataBundle.java @@ -22,7 +22,10 @@ public abstract class TypeDataBundle implements RunAsyncCallback { @Override public void onFailure(Throwable reason) { - ConnectorBundleLoader.get().setLoadFailure(getName(), reason); + ConnectorBundleLoader.get().setLoadFailure( + getName(), + new RuntimeException("Failed to load bundle " + getName() + + ": " + reason.getMessage(), reason)); } public abstract void load(); diff --git a/client/src/com/vaadin/client/ui/absolutelayout/AbsoluteLayoutConnector.java b/client/src/com/vaadin/client/ui/absolutelayout/AbsoluteLayoutConnector.java index 0877b563a0..e4b2440ef7 100644 --- a/client/src/com/vaadin/client/ui/absolutelayout/AbsoluteLayoutConnector.java +++ b/client/src/com/vaadin/client/ui/absolutelayout/AbsoluteLayoutConnector.java @@ -15,6 +15,8 @@ */ package com.vaadin.client.ui.absolutelayout; +import java.util.List; + import com.google.gwt.user.client.Element; import com.vaadin.client.ComponentConnector; import com.vaadin.client.ConnectorHierarchyChangeEvent; @@ -23,6 +25,7 @@ import com.vaadin.client.Util; import com.vaadin.client.VCaption; import com.vaadin.client.communication.RpcProxy; import com.vaadin.client.communication.StateChangeEvent; +import com.vaadin.client.communication.StateChangeEvent.StateChangeHandler; import com.vaadin.client.ui.AbstractComponentContainerConnector; import com.vaadin.client.ui.LayoutClickEventHandler; import com.vaadin.shared.ui.Connect; @@ -53,6 +56,22 @@ public class AbsoluteLayoutConnector extends }; }; + private StateChangeHandler childStateChangeHandler = new StateChangeHandler() { + @Override + public void onStateChanged(StateChangeEvent stateChangeEvent) { + ComponentConnector child = (ComponentConnector) stateChangeEvent + .getConnector(); + List<String> childStyles = child.getState().styles; + if (childStyles == null) { + getWidget().setWidgetWrapperStyleNames(child.getWidget(), + (String[]) null); + } else { + getWidget().setWidgetWrapperStyleNames(child.getWidget(), + childStyles.toArray(new String[childStyles.size()])); + } + } + }; + private AbsoluteLayoutServerRpc rpc; /* @@ -160,11 +179,13 @@ public class AbsoluteLayoutConnector extends for (ComponentConnector child : getChildComponents()) { if (!getWidget().contains(child.getWidget())) { getWidget().add(child.getWidget()); + child.addStateChangeHandler(childStateChangeHandler); } } for (ComponentConnector oldChild : event.getOldChildren()) { if (oldChild.getParent() != this) { getWidget().remove(oldChild.getWidget()); + oldChild.removeStateChangeHandler(childStateChangeHandler); } } } diff --git a/client/src/com/vaadin/client/ui/absolutelayout/VAbsoluteLayout.java b/client/src/com/vaadin/client/ui/absolutelayout/VAbsoluteLayout.java index 6c58933dd3..fbf534a5b5 100644 --- a/client/src/com/vaadin/client/ui/absolutelayout/VAbsoluteLayout.java +++ b/client/src/com/vaadin/client/ui/absolutelayout/VAbsoluteLayout.java @@ -62,7 +62,7 @@ public class VAbsoluteLayout extends ComplexPanel { @Override public void add(Widget child) { AbsoluteWrapper wrapper = new AbsoluteWrapper(child); - wrapper.setStyleName(getStylePrimaryName() + "-wrapper"); + wrapper.updateStyleNames(); super.add(wrapper, canvas); } @@ -292,7 +292,7 @@ public class VAbsoluteLayout extends ComplexPanel { for (Widget w : getChildren()) { if (w instanceof AbsoluteWrapper) { AbsoluteWrapper wrapper = (AbsoluteWrapper) w; - wrapper.setStyleName(getStylePrimaryName() + "-wrapper"); + wrapper.updateStyleNames(); } } } @@ -305,6 +305,23 @@ public class VAbsoluteLayout extends ComplexPanel { for (Widget widget : getChildren()) { if (widget instanceof AbsoluteWrapper) { AbsoluteWrapper wrapper = (AbsoluteWrapper) widget; + + /* + * Cleanup old wrappers which have been left empty by other + * inner layouts moving the widget from the wrapper into their + * own hierarchy. This usually happens when a call to + * setWidget(widget) is done in an inner layout which + * automatically detaches the widget from the parent, in this + * case the wrapper, and re-attaches it somewhere else. This has + * to be done in the layout phase since the order of the + * hierarchy events are not defined. + */ + if (wrapper.getWidget() == null) { + wrapper.destroy(); + super.remove(wrapper); + continue; + } + Style wrapperStyle = wrapper.getElement().getStyle(); Style widgetStyle = wrapper.getWidget().getElement().getStyle(); if (widgetStyle.getHeight() != null @@ -341,6 +358,23 @@ public class VAbsoluteLayout extends ComplexPanel { for (Widget widget : getChildren()) { if (widget instanceof AbsoluteWrapper) { AbsoluteWrapper wrapper = (AbsoluteWrapper) widget; + + /* + * Cleanup old wrappers which have been left empty by other + * inner layouts moving the widget from the wrapper into their + * own hierarchy. This usually happens when a call to + * setWidget(widget) is done in an inner layout which + * automatically detaches the widget from the parent, in this + * case the wrapper, and re-attaches it somewhere else. This has + * to be done in the layout phase since the order of the + * hierarchy events are not defined. + */ + if (wrapper.getWidget() == null) { + wrapper.destroy(); + super.remove(wrapper); + continue; + } + Style wrapperStyle = wrapper.getElement().getStyle(); Style widgetStyle = wrapper.getWidget().getElement().getStyle(); @@ -372,6 +406,24 @@ public class VAbsoluteLayout extends ComplexPanel { } /** + * Sets style names for the wrapper wrapping the widget in the layout. The + * style names will be prefixed with v-absolutelayout-wrapper. + * + * @param widget + * The widget which wrapper we want to add the stylenames to + * @param stylenames + * The style names that should be added to the wrapper + */ + public void setWidgetWrapperStyleNames(Widget widget, String... stylenames) { + AbsoluteWrapper wrapper = getChildWrapper(widget); + if (wrapper == null) { + throw new IllegalArgumentException( + "No wrapper for widget found, has the widget been added to the layout?"); + } + wrapper.setWrapperStyleNames(stylenames); + } + + /** * Internal wrapper for wrapping widgets in the Absolute layout */ protected class AbsoluteWrapper extends SimplePanel { @@ -383,6 +435,7 @@ public class VAbsoluteLayout extends ComplexPanel { private String zIndex; private VCaption caption; + private String[] extraStyleNames; /** * Constructor @@ -486,5 +539,30 @@ public class VAbsoluteLayout extends ComplexPanel { - caption.getHeight()); } } + + /** + * Sets the style names of the wrapper. Will be prefixed with the + * v-absolutelayout-wrapper prefix + * + * @param stylenames + * The wrapper style names + */ + public void setWrapperStyleNames(String... stylenames) { + extraStyleNames = stylenames; + updateStyleNames(); + } + + /** + * Updates the style names using the primary style name as prefix + */ + protected void updateStyleNames() { + setStyleName(VAbsoluteLayout.this.getStylePrimaryName() + + "-wrapper"); + if(extraStyleNames != null){ + for (String stylename : extraStyleNames) { + addStyleDependentName(stylename); + } + } + } } } diff --git a/client/src/com/vaadin/client/ui/csslayout/CssLayoutConnector.java b/client/src/com/vaadin/client/ui/csslayout/CssLayoutConnector.java index 12ebb6a375..cfdda3dd1c 100644 --- a/client/src/com/vaadin/client/ui/csslayout/CssLayoutConnector.java +++ b/client/src/com/vaadin/client/ui/csslayout/CssLayoutConnector.java @@ -93,6 +93,7 @@ public class CssLayoutConnector extends AbstractLayoutConnector { @Override public void onStateChanged(StateChangeEvent stateChangeEvent) { super.onStateChanged(stateChangeEvent); + clickEventHandler.handleEventHandlerRegistration(); for (ComponentConnector child : getChildComponents()) { if (!getState().childCss.containsKey(child)) { @@ -123,8 +124,6 @@ public class CssLayoutConnector extends AbstractLayoutConnector { */ @Override public void onConnectorHierarchyChange(ConnectorHierarchyChangeEvent event) { - clickEventHandler.handleEventHandlerRegistration(); - int index = 0; for (ComponentConnector child : getChildComponents()) { VCaption childCaption = childToCaption.get(child); diff --git a/client/src/com/vaadin/client/ui/orderedlayout/AbstractOrderedLayoutConnector.java b/client/src/com/vaadin/client/ui/orderedlayout/AbstractOrderedLayoutConnector.java index 7da2e17cbe..9707db610e 100644 --- a/client/src/com/vaadin/client/ui/orderedlayout/AbstractOrderedLayoutConnector.java +++ b/client/src/com/vaadin/client/ui/orderedlayout/AbstractOrderedLayoutConnector.java @@ -83,8 +83,18 @@ public abstract class AbstractOrderedLayoutConnector extends slot.setRelativeWidth(child.isRelativeWidth()); slot.setRelativeHeight(child.isRelativeHeight()); + // Update slot style names + List<String> childStyles = child.getState().styles; + if (childStyles == null) { + getWidget().setSlotStyleNames(child.getWidget(), + (String[]) null); + } else { + getWidget().setSlotStyleNames(child.getWidget(), + childStyles.toArray(new String[childStyles + .size()])); + } + updateSlotListeners(child); - // updateAllSlotListeners(); updateLayoutHeight(); } diff --git a/client/src/com/vaadin/client/ui/orderedlayout/VOrderedLayout.java b/client/src/com/vaadin/client/ui/orderedlayout/VOrderedLayout.java index e9cdc42b86..99fd681d63 100644 --- a/client/src/com/vaadin/client/ui/orderedlayout/VOrderedLayout.java +++ b/client/src/com/vaadin/client/ui/orderedlayout/VOrderedLayout.java @@ -149,6 +149,8 @@ public class VOrderedLayout extends FlowPanel { */ public static final class Slot extends SimplePanel { + public static final String SLOT_CLASSNAME = "v-slot"; + private Element spacer; private Element captionWrap; private Element caption; @@ -177,8 +179,8 @@ public class VOrderedLayout extends FlowPanel { */ private Slot(Widget widget, VOrderedLayout layout) { this.layout = layout; + setStyleName(SLOT_CLASSNAME); setWidget(widget); - setStylePrimaryName("v-slot"); } /** @@ -190,6 +192,24 @@ public class VOrderedLayout extends FlowPanel { } /** + * Sets the style names for the slot containing the widget + * + * @param stylenames + * The style names for the slot + */ + protected void setStyleNames(String... stylenames) { + setStyleName(SLOT_CLASSNAME); + if (stylenames != null) { + for (String stylename : stylenames) { + addStyleDependentName(stylename); + } + } + + // Ensure alignment style names are correct + setAlignment(alignment); + } + + /** * Sets how the widget is aligned inside the slot * * @param alignment @@ -198,20 +218,21 @@ public class VOrderedLayout extends FlowPanel { public void setAlignment(AlignmentInfo alignment) { this.alignment = alignment; - if (alignment.isHorizontalCenter()) { + if (alignment != null && alignment.isHorizontalCenter()) { addStyleName(ALIGN_CLASS_PREFIX + "center"); removeStyleName(ALIGN_CLASS_PREFIX + "right"); - } else if (alignment.isRight()) { + } else if (alignment != null && alignment.isRight()) { addStyleName(ALIGN_CLASS_PREFIX + "right"); removeStyleName(ALIGN_CLASS_PREFIX + "center"); } else { removeStyleName(ALIGN_CLASS_PREFIX + "right"); removeStyleName(ALIGN_CLASS_PREFIX + "center"); } - if (alignment.isVerticalCenter()) { + + if (alignment != null && alignment.isVerticalCenter()) { addStyleName(ALIGN_CLASS_PREFIX + "middle"); removeStyleName(ALIGN_CLASS_PREFIX + "bottom"); - } else if (alignment.isBottom()) { + } else if (alignment != null && alignment.isBottom()) { addStyleName(ALIGN_CLASS_PREFIX + "bottom"); removeStyleName(ALIGN_CLASS_PREFIX + "middle"); } else { @@ -970,4 +991,20 @@ public class VOrderedLayout extends FlowPanel { super.setHeight(height); definedHeight = (height != null && !"".equals(height)); } + + /** + * Sets the slots style names. The style names will be prefixed with the + * v-slot prefix. + * + * @param stylenames + * The style names of the slot. + */ + public void setSlotStyleNames(Widget widget, String... stylenames) { + Slot slot = getSlot(widget); + if (slot == null) { + throw new IllegalArgumentException( + "A slot for the widget could not be found. Has the widget been added to the layout?"); + } + slot.setStyleNames(stylenames); + } } diff --git a/client/tests/src/com/vaadin/client/TestVBrowserDetailsUserAgentParser.java b/client/tests/src/com/vaadin/client/TestVBrowserDetailsUserAgentParser.java index b1d60f50b5..4ce03d885d 100644 --- a/client/tests/src/com/vaadin/client/TestVBrowserDetailsUserAgentParser.java +++ b/client/tests/src/com/vaadin/client/TestVBrowserDetailsUserAgentParser.java @@ -26,6 +26,8 @@ public class TestVBrowserDetailsUserAgentParser extends TestCase { private static final String IE9_BETA_IN_IE8_MODE_WINDOWS_7 = "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C)"; private static final String IE9_BETA_WINDOWS_7 = "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)"; + private static final String IE10_WINDOWS_8 = "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0)"; + // "Version/" was added in 10.00 private static final String OPERA964_WINDOWS = "Opera/9.64(Windows NT 5.1; U; en) Presto/2.1.1"; private static final String OPERA1010_WINDOWS = "Opera/9.80 (Windows NT 5.1; U; en) Presto/2.2.15 Version/10.10"; @@ -353,6 +355,15 @@ public class TestVBrowserDetailsUserAgentParser extends TestCase { assertWindows(bd); } + public void testIE10() { + VBrowserDetails bd = new VBrowserDetails(IE10_WINDOWS_8); + assertEngineVersion(bd, 6); + assertIE(bd); + assertBrowserMajorVersion(bd, 10); + assertBrowserMinorVersion(bd, 0); + assertWindows(bd); + } + /* * Helper methods below */ |