From cf48f5eaa6319912c8265aedec1db3ff7a12c21e Mon Sep 17 00:00:00 2001 From: Anna Koskinen Date: Fri, 10 Oct 2014 10:51:11 +0300 Subject: [PATCH] Fixed the sizing of relative-sized components in AbsoluteLayout (#13131) Change-Id: Ibc0757fa383b15dbf33f0b75a7d20ee78db5e88a --- .../AbsoluteLayoutConnector.java | 38 ++- .../AbsoluteLayoutRelativeSizeContent.java | 218 ++++++++++++++++++ ...AbsoluteLayoutRelativeSizeContentTest.java | 120 ++++++++++ 3 files changed, 374 insertions(+), 2 deletions(-) create mode 100644 uitest/src/com/vaadin/tests/components/absolutelayout/AbsoluteLayoutRelativeSizeContent.java create mode 100644 uitest/src/com/vaadin/tests/components/absolutelayout/AbsoluteLayoutRelativeSizeContentTest.java diff --git a/client/src/com/vaadin/client/ui/absolutelayout/AbsoluteLayoutConnector.java b/client/src/com/vaadin/client/ui/absolutelayout/AbsoluteLayoutConnector.java index 366775e9a2..e1234d436a 100644 --- a/client/src/com/vaadin/client/ui/absolutelayout/AbsoluteLayoutConnector.java +++ b/client/src/com/vaadin/client/ui/absolutelayout/AbsoluteLayoutConnector.java @@ -183,8 +183,42 @@ public class AbsoluteLayoutConnector extends } private void setChildWidgetPosition(ComponentConnector child) { - getWidget().setWidgetPosition(child.getWidget(), - getState().connectorToCssPosition.get(child.getConnectorId())); + String position = getState().connectorToCssPosition.get(child + .getConnectorId()); + if (position == null) { + position = ""; + } + // make sure relative sizes get displayed correctly + String width = child.getState().width; + if (width != null && width.endsWith("%")) { + position = addDefaultPositionIfMissing(position, "left"); + position = addDefaultPositionIfMissing(position, "right"); + } + String height = child.getState().height; + if (height != null && height.endsWith("%")) { + position = addDefaultPositionIfMissing(position, "top"); + position = addDefaultPositionIfMissing(position, "bottom"); + } + getWidget().setWidgetPosition(child.getWidget(), position); + } + + /** + * Adds default value of 0.0px for the given property if it's missing from + * the position string altogether. If the property value is already set no + * changes are needed. + * + * @param position + * original position styles + * @param property + * the property that needs to have a value + * @return updated position, or the original string if no updates were + * needed + */ + private String addDefaultPositionIfMissing(String position, String property) { + if (!position.contains(property)) { + position = position + property + ":0.0px;"; + } + return position; } /* diff --git a/uitest/src/com/vaadin/tests/components/absolutelayout/AbsoluteLayoutRelativeSizeContent.java b/uitest/src/com/vaadin/tests/components/absolutelayout/AbsoluteLayoutRelativeSizeContent.java new file mode 100644 index 0000000000..4e1c8f5ca2 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/absolutelayout/AbsoluteLayoutRelativeSizeContent.java @@ -0,0 +1,218 @@ +/* + * 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.components.absolutelayout; + +import com.vaadin.annotations.Theme; +import com.vaadin.server.VaadinRequest; +import com.vaadin.shared.ui.MarginInfo; +import com.vaadin.tests.components.AbstractTestUI; +import com.vaadin.ui.AbsoluteLayout; +import com.vaadin.ui.Component; +import com.vaadin.ui.HorizontalLayout; +import com.vaadin.ui.Table; + +/** + * Tests how AbsoluteLayout handles relative sized contents. + * + * @author Vaadin Ltd + */ +@Theme("tests-tickets") +public class AbsoluteLayoutRelativeSizeContent extends AbstractTestUI { + + @Override + protected void setup(VaadinRequest request) { + HorizontalLayout level1 = new HorizontalLayout( + createComparisonTableOnFixed(), createTableOnFixed(), + createHalfTableOnFixed(), + createHalfTableAndFixedTableOnFixed(), createHalfTableOnFull()); + level1.setSpacing(true); + level1.setWidth(100, Unit.PERCENTAGE); + level1.setExpandRatio( + level1.getComponent(level1.getComponentCount() - 1), 1); + level1.setMargin(new MarginInfo(true, false, false, false)); + + HorizontalLayout level2 = new HorizontalLayout(createFullOnFixed(), + createFullOnFull()); + level2.setSpacing(true); + level2.setWidth(100, Unit.PERCENTAGE); + level2.setExpandRatio( + level2.getComponent(level2.getComponentCount() - 1), 1); + level2.setMargin(new MarginInfo(true, false, false, false)); + + addComponent(level1); + addComponent(level2); + } + + /** + * Creates an {@link AbsoluteLayout} of fixed size that contains a + * full-sized {@link Table} that has been forced to full size with css. + * Represents the workaround given for this ticket. + * + * @return the created layout + */ + private Component createComparisonTableOnFixed() { + AbsoluteLayout absoluteLayout = new AbsoluteLayout(); + absoluteLayout.setWidth(200, Unit.PIXELS); + absoluteLayout.setHeight(200, Unit.PIXELS); + absoluteLayout.setCaption("comparison table in full size"); + + Table table = new Table(); + table.setSizeFull(); + table.setId("comparison-table"); + absoluteLayout.addComponent(table, "top:0;bottom:0;left:0;right:0;"); + return absoluteLayout; + } + + /** + * Creates an {@link AbsoluteLayout} of fixed size that contains a + * full-sized {@link Table}. + * + * @return the created layout + */ + private Component createTableOnFixed() { + AbsoluteLayout absoluteLayout = new AbsoluteLayout(); + absoluteLayout.setWidth(200, Unit.PIXELS); + absoluteLayout.setHeight(200, Unit.PIXELS); + absoluteLayout.setCaption("full-sized table expected"); + + Table table = new Table(); + table.setSizeFull(); + table.setId("full-table"); + absoluteLayout.addComponent(table); + return absoluteLayout; + } + + /** + * Creates an {@link AbsoluteLayout} of fixed size that contains a + * half-sized {@link Table}. + * + * @return the created layout + */ + private Component createHalfTableOnFixed() { + AbsoluteLayout absoluteLayout = new AbsoluteLayout(); + absoluteLayout.setWidth(200, Unit.PIXELS); + absoluteLayout.setHeight(200, Unit.PIXELS); + absoluteLayout.setCaption("half-sized table expected"); + + Table table = new Table(); + table.setWidth(50, Unit.PERCENTAGE); + table.setHeight(50, Unit.PERCENTAGE); + table.setId("half-table"); + absoluteLayout.addComponent(table); + return absoluteLayout; + } + + /** + * Creates an {@link AbsoluteLayout} of fixed size that contains a + * half-sized {@link Table} and a fixed size {@link Table}. + * + * @return the created layout + */ + private Component createHalfTableAndFixedTableOnFixed() { + AbsoluteLayout absoluteLayout = new AbsoluteLayout(); + absoluteLayout.setWidth(200, Unit.PIXELS); + absoluteLayout.setHeight(200, Unit.PIXELS); + absoluteLayout.setCaption("half-sized and tiny expected"); + + Table table = new Table(); + table.setWidth(50, Unit.PERCENTAGE); + table.setHeight(50, Unit.PERCENTAGE); + table.setId("halfwithtiny-table"); + absoluteLayout.addComponent(table); + + Table tableTiny = new Table(); + tableTiny.setWidth(50, Unit.PIXELS); + tableTiny.setHeight(50, Unit.PIXELS); + absoluteLayout.addComponent(tableTiny, "right:50;"); + return absoluteLayout; + } + + /** + * Creates an {@link AbsoluteLayout} of full size that contains a half-sized + * {@link Table}. + * + * @return the created layout + */ + private Component createHalfTableOnFull() { + AbsoluteLayout absoluteLayout = new AbsoluteLayout(); + absoluteLayout.setSizeFull(); + absoluteLayout.setId("halfinfull-layout"); + absoluteLayout.setCaption("half-sized table expected"); + + Table table = new Table(); + table.setWidth(50, Unit.PERCENTAGE); + table.setHeight(50, Unit.PERCENTAGE); + table.setId("halfinfull-table"); + absoluteLayout.addComponent(table); + return absoluteLayout; + } + + /** + * Creates an {@link AbsoluteLayout} of fixed size that contains a + * fixed-sized {@link AbsoluteLayout}. + * + * @return the created layout + */ + private Component createFullOnFixed() { + AbsoluteLayout absoluteLayout = new AbsoluteLayout(); + absoluteLayout.setWidth(200, Unit.PIXELS); + absoluteLayout.setHeight(200, Unit.PIXELS); + absoluteLayout.setId("fullonfixed-outer"); + absoluteLayout.addStyleName("green"); + absoluteLayout.setCaption("yellow area expected"); + + AbsoluteLayout absoluteLayout2 = new AbsoluteLayout(); + absoluteLayout2.setSizeFull(); + absoluteLayout2.setId("fullonfixed-inner"); + absoluteLayout2.addStyleName("yellow"); + + absoluteLayout.addComponent(absoluteLayout2, "top:50px;left:100px;"); + return absoluteLayout; + } + + /** + * Creates an {@link AbsoluteLayout} of full size that contains another + * full-sized {@link AbsoluteLayout}. + * + * @return the created layout + */ + private AbsoluteLayout createFullOnFull() { + AbsoluteLayout absoluteLayout = new AbsoluteLayout(); + absoluteLayout.setSizeFull(); + absoluteLayout.setId("fullonfull-outer"); + absoluteLayout.addStyleName("cyan"); + absoluteLayout.setCaption("area with red border expected"); + + AbsoluteLayout absoluteLayout2 = new AbsoluteLayout(); + absoluteLayout2.setSizeFull(); + absoluteLayout2.setId("fullonfull-inner"); + absoluteLayout2.addStyleName("redborder"); + + absoluteLayout.addComponent(absoluteLayout2, "top:50px;left:100px;"); + return absoluteLayout; + } + + @Override + protected String getTestDescription() { + return "Full size component in AbsoluteLayout shouldn't get undefined size"; + } + + @Override + protected Integer getTicketNumber() { + return 13131; + } + +} diff --git a/uitest/src/com/vaadin/tests/components/absolutelayout/AbsoluteLayoutRelativeSizeContentTest.java b/uitest/src/com/vaadin/tests/components/absolutelayout/AbsoluteLayoutRelativeSizeContentTest.java new file mode 100644 index 0000000000..6cb8c476c9 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/absolutelayout/AbsoluteLayoutRelativeSizeContentTest.java @@ -0,0 +1,120 @@ +/* + * 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.components.absolutelayout; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.core.Is.is; +import static org.hamcrest.number.IsCloseTo.closeTo; + +import org.junit.Before; +import org.junit.Test; +import org.openqa.selenium.By; +import org.openqa.selenium.WebElement; + +import com.vaadin.tests.tb3.MultiBrowserTest; + +/** + * Tests how AbsoluteLayout handles relative sized contents. + * + * @author Vaadin Ltd + */ +public class AbsoluteLayoutRelativeSizeContentTest extends MultiBrowserTest { + + @Override + @Before + public void setup() throws Exception { + super.setup(); + openTestURL(); + + waitForElementPresent(By.id("comparison-table")); + }; + + @Test + public void testFullAgainstComparison() { + WebElement comparison = findElement(By.id("comparison-table")); + WebElement full = findElement(By.id("full-table")); + + assertThat("Full table should be as wide as comparison table", + full.getSize().width, is(comparison.getSize().width)); + assertThat("Full table should be as high as comparison table", + full.getSize().height, is(comparison.getSize().height)); + } + + @Test + public void testHalfAgainstComparison() { + WebElement comparison = findElement(By.id("comparison-table")); + WebElement half = findElement(By.id("half-table")); + + assertThat( + "Half-sized table should be half as wide as comparison table", + half.getSize().width, is(comparison.getSize().width / 2)); + assertThat( + "Half-sized table should be half as high as comparison table", + half.getSize().height, is(comparison.getSize().height / 2)); + } + + @Test + public void testHalfWithTinyAgainstComparison() { + WebElement comparison = findElement(By.id("comparison-table")); + WebElement half = findElement(By.id("halfwithtiny-table")); + + assertThat( + "Half-sized table should be half as wide as comparison table even if there are other components in the layout", + half.getSize().width, is(comparison.getSize().width / 2)); + assertThat( + "Half-sized table should be half as high as comparison table even if there are other components in the layout", + half.getSize().height, is(comparison.getSize().height / 2)); + } + + @Test + public void testHalfAgainstFullLayout() { + WebElement layout = findElement(By.id("halfinfull-layout")); + WebElement half = findElement(By.id("halfinfull-table")); + + assertThat("Half-sized table should be half as wide as full layout", + (double) half.getSize().width, + closeTo(((double) layout.getSize().width) / 2, 0.5)); + assertThat("Half-sized table should be half as high as full layout", + (double) half.getSize().height, + closeTo(((double) layout.getSize().height) / 2, 0.5)); + } + + @Test + public void testFullOnFixedWithSetLocation() { + WebElement outer = findElement(By.id("fullonfixed-outer")); + WebElement inner = findElement(By.id("fullonfixed-inner")); + + assertThat( + "Inner layout should be as wide as outer layout minus left position", + inner.getSize().width, is(outer.getSize().width - 100)); + assertThat( + "Inner layout should be as high as outer layout minus top position", + inner.getSize().height, is(outer.getSize().height - 50)); + } + + @Test + public void testFullOnFullWithSetLocation() { + WebElement outer = findElement(By.id("fullonfull-outer")); + WebElement inner = findElement(By.id("fullonfull-inner")); + + assertThat( + "Inner layout should be as wide as outer layout minus left position", + inner.getSize().width, is(outer.getSize().width - 100)); + assertThat( + "Inner layout should be as high as outer layout minus top position", + inner.getSize().height, is(outer.getSize().height - 50)); + } +} -- 2.39.5