diff options
author | Leif Åstrand <leif@vaadin.com> | 2015-08-28 21:47:26 +0300 |
---|---|---|
committer | Teemu Suo-Anttila <teemusa@vaadin.com> | 2015-11-03 13:45:09 +0200 |
commit | bc78b47d1df883e71aa99082c52502efe4f48a3a (patch) | |
tree | c4167c5d61ab4b2a77be0b27720d52c016672c2a /client | |
parent | cbc4c878f8b1964552ffce759cef27708f512215 (diff) | |
download | vaadin-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.java | 2 | ||||
-rw-r--r-- | client/src/com/vaadin/client/ui/formlayout/FormLayoutConnector.java | 145 |
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; + } + } + } |