]> source.dussan.org Git - vaadin-framework.git/commitdiff
Measure size correctly when element has border and/or padding (#18181)
authorArtur Signell <artur@vaadin.com>
Sun, 7 Jun 2015 17:14:01 +0000 (20:14 +0300)
committerVaadin Code Review <review@vaadin.com>
Thu, 11 Jun 2015 06:53:40 +0000 (06:53 +0000)
Change-Id: I821ad3985c78cd0c2a66b37078885ea0612d5ad1

client/src/com/vaadin/client/WidgetUtil.java
uitest/src/com/vaadin/tests/util/WidgetUtilTest.java [new file with mode: 0644]
uitest/src/com/vaadin/tests/widgetset/client/WidgetUtilTestComponentState.java [new file with mode: 0644]
uitest/src/com/vaadin/tests/widgetset/client/WidgetUtilTestConnector.java [new file with mode: 0644]
uitest/src/com/vaadin/tests/widgetset/client/WidgetUtilTestWidget.java [new file with mode: 0644]
uitest/src/com/vaadin/tests/widgetset/server/WidgetUtilUI.java [new file with mode: 0644]

index 3157b844bd549252afc5b4d11a0ebbdeeb8b369f..e89e87595347a78eb8acbf94470ca9be31cd2077 100644 (file)
@@ -611,17 +611,12 @@ public class WidgetUtil {
          var cs = element.ownerDocument.defaultView.getComputedStyle(element);
          var heightPx = cs.height;
          if(heightPx == 'auto'){
-             // Fallback for when IE reports auto
-             heightPx = @com.vaadin.client.WidgetUtil::getRequiredHeightBoundingClientRect(Lcom/google/gwt/dom/client/Element;)(element) + 'px';
+             // Fallback for inline elements
+             return @com.vaadin.client.WidgetUtil::getRequiredHeightBoundingClientRect(Lcom/google/gwt/dom/client/Element;)(element);
          }
-         var borderTopPx = cs.borderTop;
-         var borderBottomPx = cs.borderBottom;
-         var paddingTopPx = cs.paddingTop;
-         var paddingBottomPx = cs.paddingBottom;
-
-         var height = heightPx.substring(0,heightPx.length-2);
-         var border = borderTopPx.substring(0,borderTopPx.length-2)+borderBottomPx.substring(0,borderBottomPx.length-2);
-         var padding = paddingTopPx.substring(0,paddingTopPx.length-2)+paddingBottomPx.substring(0,paddingBottomPx.length-2);
+         var height = parseFloat(heightPx); // Will automatically skip "px" suffix
+         var border = parseFloat(cs.borderTopWidth) + parseFloat(cs.borderBottomWidth); // Will automatically skip "px" suffix 
+         var padding = parseFloat(cs.paddingTop) + parseFloat(cs.paddingBottom); // Will automatically skip "px" suffix
          return Math.ceil(height+border+padding);
      }-*/;
 
@@ -631,17 +626,12 @@ public class WidgetUtil {
          var cs = element.ownerDocument.defaultView.getComputedStyle(element);
          var widthPx = cs.width;
          if(widthPx == 'auto'){
-             // Fallback for when IE reports auto
-             widthPx = @com.vaadin.client.WidgetUtil::getRequiredWidthBoundingClientRect(Lcom/google/gwt/dom/client/Element;)(element) + 'px';
+             // Fallback for inline elements
+             return @com.vaadin.client.WidgetUtil::getRequiredWidthBoundingClientRect(Lcom/google/gwt/dom/client/Element;)(element);
          }
-         var borderLeftPx = cs.borderLeft;
-         var borderRightPx = cs.borderRight;
-         var paddingLeftPx = cs.paddingLeft;
-         var paddingRightPx = cs.paddingRight;
-
-         var width = widthPx.substring(0,widthPx.length-2);
-         var border = borderLeftPx.substring(0,borderLeftPx.length-2)+borderRightPx.substring(0,borderRightPx.length-2);
-         var padding = paddingLeftPx.substring(0,paddingLeftPx.length-2)+paddingRightPx.substring(0,paddingRightPx.length-2);
+         var width = parseFloat(widthPx); // Will automatically skip "px" suffix
+         var border = parseFloat(cs.borderLeftWidth) + parseFloat(cs.borderRightWidth); // Will automatically skip "px" suffix
+         var padding = parseFloat(cs.paddingLeft) + parseFloat(cs.paddingRight); // Will automatically skip "px" suffix
          return Math.ceil(width+border+padding);
      }-*/;
 
diff --git a/uitest/src/com/vaadin/tests/util/WidgetUtilTest.java b/uitest/src/com/vaadin/tests/util/WidgetUtilTest.java
new file mode 100644 (file)
index 0000000..2af015b
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2000-2014 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.tests.util;
+
+import java.util.List;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.openqa.selenium.By;
+import org.openqa.selenium.WebElement;
+import org.openqa.selenium.remote.DesiredCapabilities;
+
+import com.vaadin.testbench.parallel.Browser;
+import com.vaadin.testbench.parallel.BrowserUtil;
+import com.vaadin.tests.tb3.MultiBrowserTest;
+import com.vaadin.tests.widgetset.server.WidgetUtilUI;
+
+public class WidgetUtilTest extends MultiBrowserTest {
+
+    @Override
+    public List<DesiredCapabilities> getBrowsersToTest() {
+        List<DesiredCapabilities> l = super.getBrowsersToTest();
+        // IE8 does not support getComputedStyle
+        l.remove(Browser.IE8.getDesiredCapabilities());
+        return l;
+    }
+
+    @Test
+    public void testBlockElementRequiredSizeComputedStyle() {
+        openTestURL();
+        WebElement testComponent = findElement(By
+                .className("v-widget-util-test"));
+        testComponent.click();
+
+        int padding = (int) Math.ceil(2.4 + 3.5);
+        int border = (int) Math.ceil(1.8 * 2);
+        int baseWidth = 300;
+        int baseHeight = 50;
+
+        if (BrowserUtil.isPhantomJS(getDesiredCapabilities())
+                && getDesiredCapabilities().getVersion().equals("1")) {
+            // PhantomJS1 rounds padding to integers
+            padding = 2 + 3;
+        }
+
+        if (browserRoundsBorderToInteger(getDesiredCapabilities())) {
+            border = 1 * 2;
+        }
+
+        assertExpectedSize(testComponent, "noBorderPadding", baseWidth + "x"
+                + baseHeight);
+
+        assertExpectedSize(testComponent, "border", (baseWidth + border) + "x"
+                + (baseHeight + border));
+
+        assertExpectedSize(testComponent, "padding", (baseWidth + padding)
+                + "x" + (baseHeight + padding));
+
+        assertExpectedSize(testComponent, "borderPadding",
+                (baseWidth + border + padding) + "x"
+                        + (baseHeight + border + padding));
+
+    }
+
+    private void assertExpectedSize(WebElement testComponent, String id,
+            String size) {
+        WebElement e = testComponent.findElement(By.id(id));
+        Assert.assertEquals(id + ": " + size, e.getText());
+    }
+
+    private boolean browserRoundsBorderToInteger(
+            DesiredCapabilities capabilities) {
+        // Note that this is how the Windows browsers in the test cluster work.
+        // On Mac, Firefox works slightly differently (rounds border to 1.5px).
+        return (BrowserUtil.isChrome(capabilities)
+                || BrowserUtil.isPhantomJS(capabilities) || BrowserUtil
+                    .isFirefox(capabilities));
+    }
+
+    @Override
+    protected Class<?> getUIClass() {
+        return WidgetUtilUI.class;
+    }
+}
diff --git a/uitest/src/com/vaadin/tests/widgetset/client/WidgetUtilTestComponentState.java b/uitest/src/com/vaadin/tests/widgetset/client/WidgetUtilTestComponentState.java
new file mode 100644 (file)
index 0000000..aa946d4
--- /dev/null
@@ -0,0 +1,7 @@
+package com.vaadin.tests.widgetset.client;
+
+import com.vaadin.shared.AbstractComponentState;
+
+public class WidgetUtilTestComponentState extends AbstractComponentState {
+    public boolean inline = false;
+}
diff --git a/uitest/src/com/vaadin/tests/widgetset/client/WidgetUtilTestConnector.java b/uitest/src/com/vaadin/tests/widgetset/client/WidgetUtilTestConnector.java
new file mode 100644 (file)
index 0000000..2776f69
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2000-2014 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.tests.widgetset.client;
+
+import com.vaadin.client.communication.StateChangeEvent;
+import com.vaadin.client.ui.AbstractComponentConnector;
+import com.vaadin.shared.ui.Connect;
+import com.vaadin.tests.widgetset.server.WidgetUtilUI.WidgetUtilTestComponent;
+
+@Connect(WidgetUtilTestComponent.class)
+public class WidgetUtilTestConnector extends AbstractComponentConnector {
+
+    @Override
+    public void onStateChanged(StateChangeEvent stateChangeEvent) {
+        super.onStateChanged(stateChangeEvent);
+        getWidget().construct(getState().inline);
+
+    }
+
+    @Override
+    public WidgetUtilTestWidget getWidget() {
+        return (WidgetUtilTestWidget) super.getWidget();
+    }
+
+    @Override
+    public WidgetUtilTestComponentState getState() {
+        return (WidgetUtilTestComponentState) super.getState();
+    }
+
+}
diff --git a/uitest/src/com/vaadin/tests/widgetset/client/WidgetUtilTestWidget.java b/uitest/src/com/vaadin/tests/widgetset/client/WidgetUtilTestWidget.java
new file mode 100644 (file)
index 0000000..6ff0f24
--- /dev/null
@@ -0,0 +1,140 @@
+/*
+ * Copyright 2000-2014 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.tests.widgetset.client;
+
+import com.google.gwt.dom.client.DivElement;
+import com.google.gwt.dom.client.Document;
+import com.google.gwt.dom.client.Element;
+import com.google.gwt.dom.client.Style;
+import com.google.gwt.dom.client.Style.BorderStyle;
+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.ui.Widget;
+import com.vaadin.client.WidgetUtil;
+
+public class WidgetUtilTestWidget extends Widget {
+
+    private Element noBorderPadding;
+    private Element border;
+    private Element padding;
+    private Element borderPadding;
+    private DivElement result;
+    private boolean inline;
+    private DivElement root;
+
+    public WidgetUtilTestWidget() {
+        Document doc = Document.get();
+
+        root = doc.createDivElement();
+        root.addClassName("v-widget-util-test");
+        setElement(root);
+
+        addDomHandler(new ClickHandler() {
+            @Override
+            public void onClick(ClickEvent event) {
+                showSizes();
+            }
+        }, ClickEvent.getType());
+    }
+
+    public void construct(boolean inline) {
+        this.inline = inline;
+
+        noBorderPadding = createElement();
+
+        border = createElement();
+        setBorder(border);
+
+        padding = createElement();
+        setPadding(padding);
+
+        borderPadding = createElement();
+        setBorder(borderPadding);
+        setPadding(borderPadding);
+
+        root.appendChild(noBorderPadding);
+        root.appendChild(border);
+        root.appendChild(padding);
+        root.appendChild(borderPadding);
+
+        result = Document.get().createDivElement();
+        result.addClassName("result");
+        result.getStyle().setWidth(500, Unit.PX);
+        root.appendChild(result);
+    }
+
+    private void setBorder(Element e) {
+        Style borderStyle = e.getStyle();
+        borderStyle.setBorderStyle(BorderStyle.SOLID);
+        borderStyle.setBorderWidth(1.8, Unit.PX);
+    }
+
+    private void setPadding(Element e) {
+        Style borderStyle = e.getStyle();
+        borderStyle.setPaddingLeft(2.4, Unit.PX);
+        borderStyle.setPaddingRight(3.5, Unit.PX);
+        borderStyle.setPaddingTop(2.4, Unit.PX);
+        borderStyle.setPaddingBottom(3.5, Unit.PX);
+    }
+
+    private Element createElement() {
+        Element e;
+        if (inline) {
+            e = Document.get().createSpanElement();
+            e.getStyle().setBackgroundColor("green");
+        } else {
+            e = Document.get().createDivElement();
+            e.getStyle().setWidth(300, Unit.PX);
+            e.getStyle().setHeight(50, Unit.PX);
+            e.getStyle().setBackgroundColor("blue");
+        }
+        e.getStyle().setMargin(3.7, Unit.PX);
+        return e;
+    }
+
+    public void showSizes() {
+        String sizes = "Measured required width x height<br/>";
+
+        sizes += "<div id='noBorderPadding'>noBorderPadding: "
+                + WidgetUtil.getRequiredWidthComputedStyle(noBorderPadding);
+        sizes += "x"
+                + WidgetUtil.getRequiredHeightComputedStyle(noBorderPadding)
+                + "</div>";
+        sizes += "<div id='border'>border: "
+                + WidgetUtil.getRequiredWidthComputedStyle(border);
+        sizes += "x" + WidgetUtil.getRequiredHeightComputedStyle(border);
+        sizes += "</div>";
+
+        sizes += "<div id='padding'>padding: "
+                + WidgetUtil.getRequiredWidthComputedStyle(padding);
+        sizes += "x" + WidgetUtil.getRequiredHeightComputedStyle(padding);
+        sizes += "</div>";
+
+        sizes += "<div id='borderPadding'>borderPadding: "
+                + WidgetUtil.getRequiredWidthComputedStyle(borderPadding);
+        sizes += "x" + WidgetUtil.getRequiredHeightComputedStyle(borderPadding)
+                + "</div>";
+
+        result.setInnerHTML(sizes);
+
+        if (inline) {
+            result.getStyle().setPaddingTop(200, Unit.PX);
+        }
+
+    }
+
+}
diff --git a/uitest/src/com/vaadin/tests/widgetset/server/WidgetUtilUI.java b/uitest/src/com/vaadin/tests/widgetset/server/WidgetUtilUI.java
new file mode 100644 (file)
index 0000000..0489a86
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2000-2014 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.tests.widgetset.server;
+
+import com.vaadin.annotations.Widgetset;
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.tests.components.AbstractTestUI;
+import com.vaadin.tests.widgetset.TestingWidgetSet;
+import com.vaadin.tests.widgetset.client.WidgetUtilTestComponentState;
+import com.vaadin.ui.AbstractComponent;
+
+@Widgetset(TestingWidgetSet.NAME)
+public class WidgetUtilUI extends AbstractTestUI {
+
+    public static class WidgetUtilTestComponent extends AbstractComponent {
+
+        public WidgetUtilTestComponent(boolean inline) {
+            getState().inline = inline;
+        }
+
+        @Override
+        protected WidgetUtilTestComponentState getState() {
+            return (WidgetUtilTestComponentState) super.getState();
+        }
+    }
+
+    @Override
+    protected void setup(VaadinRequest request) {
+        addComponent(new WidgetUtilTestComponent(
+                request.getParameter("inline") != null));
+    }
+}