aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--WebContent/VAADIN/themes/base/formlayout/formlayout.scss1
-rw-r--r--WebContent/VAADIN/themes/reindeer/formlayout/formlayout.scss1
-rw-r--r--client/src/com/vaadin/client/ui/VFormLayout.java2
-rw-r--r--client/src/com/vaadin/client/ui/formlayout/FormLayoutConnector.java145
-rw-r--r--uitest/src/com/vaadin/tests/components/formlayout/FormLayoutResizing.java85
-rw-r--r--uitest/src/com/vaadin/tests/components/formlayout/FormLayoutResizingTest.java100
6 files changed, 332 insertions, 2 deletions
diff --git a/WebContent/VAADIN/themes/base/formlayout/formlayout.scss b/WebContent/VAADIN/themes/base/formlayout/formlayout.scss
index a8006fdfe3..2e2a3213f9 100644
--- a/WebContent/VAADIN/themes/base/formlayout/formlayout.scss
+++ b/WebContent/VAADIN/themes/base/formlayout/formlayout.scss
@@ -19,6 +19,7 @@
}
.#{$primaryStyleName}-errorcell, .#{$primaryStyleName}-captioncell {
width: 1px; /* Don't use any extra space */
+ min-width: 1px;
}
.#{$primaryStyleName}-captioncell .v-caption {
overflow: visible;
diff --git a/WebContent/VAADIN/themes/reindeer/formlayout/formlayout.scss b/WebContent/VAADIN/themes/reindeer/formlayout/formlayout.scss
index 51b8a96b60..7f8871fdac 100644
--- a/WebContent/VAADIN/themes/reindeer/formlayout/formlayout.scss
+++ b/WebContent/VAADIN/themes/reindeer/formlayout/formlayout.scss
@@ -2,6 +2,7 @@
.#{$primaryStyleName}-errorcell {
width: 13px;
+ min-width: 13px;
}
.#{$primaryStyleName}-cell .v-errorindicator {
width: 13px;
diff --git a/client/src/com/vaadin/client/ui/VFormLayout.java b/client/src/com/vaadin/client/ui/VFormLayout.java
index bcbb3ebf7b..3719688f2b 100644
--- a/client/src/com/vaadin/client/ui/VFormLayout.java
+++ b/client/src/com/vaadin/client/ui/VFormLayout.java
@@ -86,7 +86,7 @@ public class VFormLayout extends SimplePanel {
private static final int COLUMN_CAPTION = 0;
private static final int COLUMN_ERRORFLAG = 1;
- private static final int COLUMN_WIDGET = 2;
+ public static final int COLUMN_WIDGET = 2;
private HashMap<Widget, Caption> widgetToCaption = new HashMap<Widget, Caption>();
private HashMap<Widget, ErrorFlag> widgetToError = new HashMap<Widget, ErrorFlag>();
diff --git a/client/src/com/vaadin/client/ui/formlayout/FormLayoutConnector.java b/client/src/com/vaadin/client/ui/formlayout/FormLayoutConnector.java
index 9517619cf3..febbb5d6a2 100644
--- a/client/src/com/vaadin/client/ui/formlayout/FormLayoutConnector.java
+++ b/client/src/com/vaadin/client/ui/formlayout/FormLayoutConnector.java
@@ -15,26 +15,124 @@
*/
package com.vaadin.client.ui.formlayout;
+import java.util.HashMap;
+import java.util.Map;
+
import com.google.gwt.dom.client.Element;
import com.google.gwt.user.client.ui.Widget;
import com.vaadin.client.ComponentConnector;
import com.vaadin.client.ConnectorHierarchyChangeEvent;
+import com.vaadin.client.LayoutManager;
import com.vaadin.client.TooltipInfo;
import com.vaadin.client.WidgetUtil;
import com.vaadin.client.communication.StateChangeEvent;
import com.vaadin.client.ui.AbstractFieldConnector;
import com.vaadin.client.ui.AbstractLayoutConnector;
+import com.vaadin.client.ui.PostLayoutListener;
import com.vaadin.client.ui.VFormLayout;
import com.vaadin.client.ui.VFormLayout.Caption;
import com.vaadin.client.ui.VFormLayout.ErrorFlag;
import com.vaadin.client.ui.VFormLayout.VFormLayoutTable;
+import com.vaadin.client.ui.layout.ElementResizeEvent;
+import com.vaadin.client.ui.layout.ElementResizeListener;
import com.vaadin.shared.ui.Connect;
import com.vaadin.shared.ui.MarginInfo;
import com.vaadin.shared.ui.orderedlayout.AbstractOrderedLayoutState;
import com.vaadin.ui.FormLayout;
@Connect(FormLayout.class)
-public class FormLayoutConnector extends AbstractLayoutConnector {
+public class FormLayoutConnector extends AbstractLayoutConnector implements
+ PostLayoutListener {
+
+ private Map<ComponentConnector, String> oldMaxWidths = null;
+
+ private static final ElementResizeListener dummyFirstCellResizeListener = new ElementResizeListener() {
+ @Override
+ public void onElementResize(ElementResizeEvent e) {
+ // Ignore event, listener added just to make measurements available
+ }
+ };
+
+ // Detects situations when there's something inside the FormLayout that
+ // prevents it from shrinking
+ private ElementResizeListener resizeListener = new ElementResizeListener() {
+ @Override
+ public void onElementResize(ElementResizeEvent e) {
+ LayoutManager layoutManager = getLayoutManager();
+ double tableWidth = layoutManager
+ .getOuterWidthDouble(getWidget().table.getElement());
+ double ownWidth = layoutManager.getInnerWidthDouble(getWidget()
+ .getElement());
+ if (ownWidth < tableWidth) {
+ // Something inside the table prevents it from shrinking,
+ // temporarily force column widths
+ double excessWidth = tableWidth - ownWidth;
+
+ // All td elements in the component column have the same width,
+ // so we only need to check the width of the first one to know
+ // how wide the column is.
+ Element firstComponentTd = findFirstComponentTd();
+ if (firstComponentTd == null) {
+ // Can't do anything if there are no rows
+ return;
+ }
+
+ double componentColWidth = layoutManager
+ .getOuterWidthDouble(firstComponentTd);
+
+ if (componentColWidth == -1) {
+ // Didn't get a proper width reading, best to not touch
+ // anything
+ return;
+ }
+
+ // Restrict content td width
+ // Round down to prevent interactions with fractional sizes of
+ // other columns
+ int targetWidth = (int) Math.floor(componentColWidth
+ - excessWidth);
+
+ // Target might be negative if captions are wider than the total
+ // available width
+ targetWidth = Math.max(0, targetWidth);
+
+ if (oldMaxWidths == null) {
+ oldMaxWidths = new HashMap<ComponentConnector, String>();
+ }
+
+ for (ComponentConnector child : getChildComponents()) {
+ Element childElement = child.getWidget().getElement();
+ if (!oldMaxWidths.containsKey(child)) {
+ oldMaxWidths.put(child,
+ childElement.getPropertyString("maxWidth"));
+ }
+ childElement.getStyle().setPropertyPx("maxWidth",
+ targetWidth);
+ layoutManager.reportOuterWidth(child, targetWidth);
+ }
+ }
+ }
+ };
+
+ @Override
+ protected void init() {
+ super.init();
+ getLayoutManager().addElementResizeListener(
+ getWidget().table.getElement(), resizeListener);
+ getLayoutManager().addElementResizeListener(getWidget().getElement(),
+ resizeListener);
+ addComponentCellListener();
+ }
+
+ @Override
+ public void onUnregister() {
+ getLayoutManager().removeElementResizeListener(
+ getWidget().table.getElement(), resizeListener);
+ getLayoutManager().removeElementResizeListener(
+ getWidget().getElement(), resizeListener);
+ removeComponentCellListener();
+ super.onUnregister();
+ }
@Override
public AbstractOrderedLayoutState getState() {
@@ -57,6 +155,8 @@ public class FormLayoutConnector extends AbstractLayoutConnector {
VFormLayout formLayout = getWidget();
VFormLayoutTable formLayoutTable = getWidget().table;
+ removeComponentCellListener();
+
int childId = 0;
formLayoutTable.setRowCount(getChildComponents().size());
@@ -87,6 +187,33 @@ public class FormLayoutConnector extends AbstractLayoutConnector {
formLayoutTable.cleanReferences(oldChild.getWidget());
}
+ addComponentCellListener();
+ }
+
+ private void addComponentCellListener() {
+ Element td = findFirstComponentTd();
+ if (td != null) {
+ getLayoutManager().addElementResizeListener(td,
+ dummyFirstCellResizeListener);
+ }
+ }
+
+ private void removeComponentCellListener() {
+ Element td = findFirstComponentTd();
+ if (td != null) {
+ getLayoutManager().removeElementResizeListener(td,
+ dummyFirstCellResizeListener);
+ }
+ }
+
+ private Element findFirstComponentTd() {
+ VFormLayoutTable table = getWidget().table;
+ if (table.getRowCount() == 0) {
+ return null;
+ } else {
+ return table.getCellFormatter().getElement(0,
+ VFormLayoutTable.COLUMN_WIDGET);
+ }
}
@Override
@@ -148,4 +275,20 @@ public class FormLayoutConnector extends AbstractLayoutConnector {
return true;
}
+ @Override
+ public void postLayout() {
+ if (oldMaxWidths != null) {
+ for (ComponentConnector child : getChildComponents()) {
+ Element childNode = child.getWidget().getElement();
+ String oldValue = oldMaxWidths.get(child);
+ if (oldValue == null) {
+ childNode.getStyle().clearProperty("maxWidth");
+ } else {
+ childNode.getStyle().setProperty("maxWidth", oldValue);
+ }
+ }
+ oldMaxWidths = null;
+ }
+ }
+
}
diff --git a/uitest/src/com/vaadin/tests/components/formlayout/FormLayoutResizing.java b/uitest/src/com/vaadin/tests/components/formlayout/FormLayoutResizing.java
new file mode 100644
index 0000000000..7ed91979e2
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/formlayout/FormLayoutResizing.java
@@ -0,0 +1,85 @@
+/*
+ * 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.formlayout;
+
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.tests.components.AbstractTestUI;
+import com.vaadin.ui.Button;
+import com.vaadin.ui.Button.ClickEvent;
+import com.vaadin.ui.Component;
+import com.vaadin.ui.CssLayout;
+import com.vaadin.ui.FormLayout;
+import com.vaadin.ui.Table;
+import com.vaadin.ui.TextField;
+import com.vaadin.ui.VerticalLayout;
+
+public class FormLayoutResizing extends AbstractTestUI {
+
+ @Override
+ protected void setup(VaadinRequest request) {
+ FormLayout form1 = createForm("Table", createTable());
+
+ CssLayout cssLayout = new CssLayout(createTable());
+ cssLayout.setWidth("100%");
+ FormLayout form2 = createForm("Wrap", cssLayout);
+
+ final VerticalLayout view = new VerticalLayout(form1, form2);
+ view.setWidth("400px");
+
+ addComponent(view);
+
+ addComponent(new Button("Toggle width", new Button.ClickListener() {
+ @Override
+ public void buttonClick(ClickEvent event) {
+ if ((int) view.getWidth() == 400) {
+ view.setWidth("600px");
+ } else {
+ view.setWidth("400px");
+ }
+ }
+ }));
+ }
+
+ private static FormLayout createForm(String caption, Component table) {
+ table.setCaption(caption);
+
+ TextField tf = new TextField("Text field");
+ tf.setWidth("100%");
+
+ FormLayout form = new FormLayout();
+ form.setWidth("100%");
+
+ form.addComponent(tf);
+ form.addComponent(table);
+ return form;
+ }
+
+ private static Table createTable() {
+ Table table = new Table();
+ table.setHeight("100px");
+
+ table.addContainerProperty("Column 1", String.class, "");
+ table.addContainerProperty("Column 2", String.class, "");
+ table.setWidth("100%");
+ return table;
+ }
+
+ @Override
+ protected String getTestDescription() {
+ return "100% wide Table inside FormLayout should resize when the layout width changes";
+ }
+
+}
diff --git a/uitest/src/com/vaadin/tests/components/formlayout/FormLayoutResizingTest.java b/uitest/src/com/vaadin/tests/components/formlayout/FormLayoutResizingTest.java
new file mode 100644
index 0000000000..3285503aeb
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/formlayout/FormLayoutResizingTest.java
@@ -0,0 +1,100 @@
+/*
+ * 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.formlayout;
+
+import java.util.List;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.openqa.selenium.By;
+import org.openqa.selenium.WebElement;
+
+import com.vaadin.testbench.elements.ButtonElement;
+import com.vaadin.testbench.elements.FormLayoutElement;
+import com.vaadin.testbench.elements.TableElement;
+import com.vaadin.testbench.parallel.BrowserUtil;
+import com.vaadin.tests.tb3.MultiBrowserThemeTest;
+
+public class FormLayoutResizingTest extends MultiBrowserThemeTest {
+ @Test
+ public void testTableResizing() {
+ openTestURL();
+
+ List<TableElement> tables = $(TableElement.class).all();
+ Assert.assertEquals("Sanity check", 2, tables.size());
+
+ List<FormLayoutElement> layouts = $(FormLayoutElement.class).all();
+ Assert.assertEquals("Sanity check", 2, layouts.size());
+
+ ButtonElement toggleButton = $(ButtonElement.class).first();
+
+ int[] originalWidths = getWidths(tables);
+
+ // In some browser and theme combinations, the original rendering is
+ // slightly too wide. Find out this overshoot and adjust the expected
+ // table width accordingly.
+ for (int i = 0; i < 2; i++) {
+ FormLayoutElement formLayout = layouts.get(i);
+ WebElement table = formLayout.findElement(By.tagName("table"));
+ int overshoot = table.getSize().width - formLayout.getSize().width;
+ originalWidths[i] -= overshoot;
+ }
+
+ // Toggle size from 400 px to 600 px
+ toggleButton.click();
+
+ int[] expandedWidths = getWidths(tables);
+
+ Assert.assertEquals("Table should have grown ",
+ originalWidths[0] + 200, expandedWidths[0]);
+ Assert.assertEquals("Wrapped table should have grown ",
+ originalWidths[1] + 200, expandedWidths[1]);
+
+ // Toggle size from 600 px to 400 px
+ toggleButton.click();
+
+ int[] collapsedWidths = getWidths(tables);
+
+ Assert.assertEquals("Table should return to original width ",
+ originalWidths[0], collapsedWidths[0]);
+ Assert.assertEquals("Wrapped table should return to original width ",
+ originalWidths[1], collapsedWidths[1]);
+
+ // Verify that growing is not restricted after triggering the fix
+ // Toggle size from 400 px to 600 px
+ toggleButton.click();
+
+ expandedWidths = getWidths(tables);
+
+ Assert.assertEquals("Table should have grown ",
+ originalWidths[0] + 200, expandedWidths[0]);
+ Assert.assertEquals("Wrapped table should have grown ",
+ originalWidths[1] + 200, expandedWidths[1]);
+ }
+
+ @Override
+ protected boolean useNativeEventsForIE() {
+ return !BrowserUtil.isIE(getDesiredCapabilities(), 11);
+ }
+
+ private static int[] getWidths(List<TableElement> tables) {
+ int[] widths = new int[tables.size()];
+ for (int i = 0; i < widths.length; i++) {
+ widths[i] = tables.get(i).getSize().width;
+ }
+ return widths;
+ }
+}