aboutsummaryrefslogtreecommitdiffstats
path: root/client
diff options
context:
space:
mode:
authorLeif Åstrand <leif@vaadin.com>2015-08-28 21:47:26 +0300
committerTeemu Suo-Anttila <teemusa@vaadin.com>2015-11-03 13:45:09 +0200
commitbc78b47d1df883e71aa99082c52502efe4f48a3a (patch)
treec4167c5d61ab4b2a77be0b27720d52c016672c2a /client
parentcbc4c878f8b1964552ffce759cef27708f512215 (diff)
downloadvaadin-framework-bc78b47d1df883e71aa99082c52502efe4f48a3a.tar.gz
vaadin-framework-bc78b47d1df883e71aa99082c52502efe4f48a3a.zip
Force FormLayout children to shrink with the layout (#11154)
The <table> used by the FormLayout doesn't reduce its size if any child component has locked its own size (which is the case with e.g. Table and some other components doing explicit pixel calculations). To work around this, we need to detect the situation, force the <table> to reduce its width by temporarily assigning explicit widths to the cells and then remove the forced size after all children have adjusted. Change-Id: Iacef62979acf24c869a5cbeb82efb0c1e537ec95
Diffstat (limited to 'client')
-rw-r--r--client/src/com/vaadin/client/ui/VFormLayout.java2
-rw-r--r--client/src/com/vaadin/client/ui/formlayout/FormLayoutConnector.java145
2 files changed, 145 insertions, 2 deletions
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 bab4153649..3f0b4345c4 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.FormLayoutState;
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 FormLayoutState 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;
+ }
+ }
+
}