From 640dd28d217800c3ad56eeb20d7d40b4f7615224 Mon Sep 17 00:00:00 2001 From: Artur Signell Date: Sun, 7 Jun 2015 20:14:01 +0300 Subject: [PATCH] Measure size correctly when element has border and/or padding (#18181) Change-Id: I821ad3985c78cd0c2a66b37078885ea0612d5ad1 --- client/src/com/vaadin/client/WidgetUtil.java | 30 ++-- .../com/vaadin/tests/util/WidgetUtilTest.java | 97 ++++++++++++ .../client/WidgetUtilTestComponentState.java | 7 + .../client/WidgetUtilTestConnector.java | 43 ++++++ .../client/WidgetUtilTestWidget.java | 140 ++++++++++++++++++ .../tests/widgetset/server/WidgetUtilUI.java | 45 ++++++ 6 files changed, 342 insertions(+), 20 deletions(-) create mode 100644 uitest/src/com/vaadin/tests/util/WidgetUtilTest.java create mode 100644 uitest/src/com/vaadin/tests/widgetset/client/WidgetUtilTestComponentState.java create mode 100644 uitest/src/com/vaadin/tests/widgetset/client/WidgetUtilTestConnector.java create mode 100644 uitest/src/com/vaadin/tests/widgetset/client/WidgetUtilTestWidget.java create mode 100644 uitest/src/com/vaadin/tests/widgetset/server/WidgetUtilUI.java diff --git a/client/src/com/vaadin/client/WidgetUtil.java b/client/src/com/vaadin/client/WidgetUtil.java index 3157b844bd..e89e875953 100644 --- a/client/src/com/vaadin/client/WidgetUtil.java +++ b/client/src/com/vaadin/client/WidgetUtil.java @@ -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 index 0000000000..2af015b406 --- /dev/null +++ b/uitest/src/com/vaadin/tests/util/WidgetUtilTest.java @@ -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 getBrowsersToTest() { + List 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 index 0000000000..aa946d4ceb --- /dev/null +++ b/uitest/src/com/vaadin/tests/widgetset/client/WidgetUtilTestComponentState.java @@ -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 index 0000000000..2776f698fe --- /dev/null +++ b/uitest/src/com/vaadin/tests/widgetset/client/WidgetUtilTestConnector.java @@ -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 index 0000000000..6ff0f2433e --- /dev/null +++ b/uitest/src/com/vaadin/tests/widgetset/client/WidgetUtilTestWidget.java @@ -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
"; + + sizes += "
noBorderPadding: " + + WidgetUtil.getRequiredWidthComputedStyle(noBorderPadding); + sizes += "x" + + WidgetUtil.getRequiredHeightComputedStyle(noBorderPadding) + + "
"; + sizes += "
border: " + + WidgetUtil.getRequiredWidthComputedStyle(border); + sizes += "x" + WidgetUtil.getRequiredHeightComputedStyle(border); + sizes += "
"; + + sizes += "
padding: " + + WidgetUtil.getRequiredWidthComputedStyle(padding); + sizes += "x" + WidgetUtil.getRequiredHeightComputedStyle(padding); + sizes += "
"; + + sizes += "
borderPadding: " + + WidgetUtil.getRequiredWidthComputedStyle(borderPadding); + sizes += "x" + WidgetUtil.getRequiredHeightComputedStyle(borderPadding) + + "
"; + + 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 index 0000000000..0489a8676f --- /dev/null +++ b/uitest/src/com/vaadin/tests/widgetset/server/WidgetUtilUI.java @@ -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)); + } +} -- 2.39.5