From: Artur Signell Date: Fri, 19 Sep 2008 07:47:48 +0000 (+0000) Subject: Added method for a component to notify its parent container when its size change X-Git-Tag: 6.7.0.beta1~4135 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=9db9cd325d50aa177052409e25faff343cb7e828;p=vaadin-framework.git Added method for a component to notify its parent container when its size change svn changeset:5453/svn branch:trunk --- diff --git a/src/com/itmill/toolkit/terminal/gwt/client/ApplicationConnection.java b/src/com/itmill/toolkit/terminal/gwt/client/ApplicationConnection.java index 4de30f7f32..9c26bdc063 100755 --- a/src/com/itmill/toolkit/terminal/gwt/client/ApplicationConnection.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/ApplicationConnection.java @@ -6,7 +6,9 @@ package com.itmill.toolkit.terminal.gwt.client; import java.util.Date; import java.util.HashMap; +import java.util.HashSet; import java.util.Iterator; +import java.util.Set; import java.util.Vector; import com.google.gwt.core.client.GWT; @@ -503,6 +505,9 @@ public class ApplicationConnection { // Process changes final JSONArray changes = (JSONArray) ((JSONObject) json) .get("changes"); + + Set sizeUpdatedWidgets = new HashSet(); + for (int i = 0; i < changes.size(); i++) { try { final UIDL change = new UIDL((JSONArray) changes.get(i)); @@ -517,7 +522,16 @@ public class ApplicationConnection { final UIDL uidl = change.getChildUIDL(0); final Paintable paintable = getPaintable(uidl.getId()); if (paintable != null) { + Widget widget = (Widget) paintable; + int w = widget.getOffsetWidth(); + int h = widget.getOffsetHeight(); + paintable.updateFromUIDL(uidl, this); + + if (w != widget.getOffsetWidth() + || h != widget.getOffsetHeight()) { + sizeUpdatedWidgets.add((Widget) paintable); + } } else { if (!uidl.getTag().equals("window")) { ClientExceptionHandler @@ -534,6 +548,8 @@ public class ApplicationConnection { } } + Util.componentSizeUpdated(sizeUpdatedWidgets); + if (meta != null) { if (meta.containsKey("focus")) { final String focusPid = meta.get("focus").isString() diff --git a/src/com/itmill/toolkit/terminal/gwt/client/Container.java b/src/com/itmill/toolkit/terminal/gwt/client/Container.java index b79fe2c606..8675a0cb55 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/Container.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/Container.java @@ -49,4 +49,12 @@ public interface Container extends Paintable { */ void updateCaption(Paintable component, UIDL uidl); + /** + * Called when a child components size has been updated in the rendering + * phase. + * + * @return true if the size of the Container remains the same, false if the + * event need to be propagated to the Containers parent + */ + boolean childComponentSizesUpdated(); } diff --git a/src/com/itmill/toolkit/terminal/gwt/client/ContainerResizedListener.java b/src/com/itmill/toolkit/terminal/gwt/client/ContainerResizedListener.java index d3634a1804..0ad667782b 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/ContainerResizedListener.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/ContainerResizedListener.java @@ -21,6 +21,12 @@ public interface ContainerResizedListener { * these numbers. If the parent container does not know (has not calculated) * or cannot produce (undefined dimensions) one of these numbers -1 is * passed. + * + * Note that these numbers should not be considered the maximum size for the + * widget if the layout has undefined dimension. In that case the currently + * allocated space is passed (eg. OrderedLayout with undefined width might + * pass availableWidth 100 if the widest component in the layout is 100 but + * it will still stretch if another 200 pixel wide component is rendered) */ public void iLayout(int availableWidth, int availableHeight); } diff --git a/src/com/itmill/toolkit/terminal/gwt/client/Util.java b/src/com/itmill/toolkit/terminal/gwt/client/Util.java index 8981054d70..24ceb5d21b 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/Util.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/Util.java @@ -4,7 +4,9 @@ package com.itmill.toolkit.terminal.gwt.client; +import java.util.HashSet; import java.util.Iterator; +import java.util.Set; import com.google.gwt.user.client.DOM; import com.google.gwt.user.client.Element; @@ -37,6 +39,43 @@ public class Util { el.oncontextmenu = null; }-*/; + /** + * Called when the size of one or more widgets have changed during + * rendering. Finds parent container and notifies them of the size change. + * + * @param widgets + */ + public static void componentSizeUpdated(Set widgets) { + if (widgets.isEmpty()) { + return; + } + + Set parents = new HashSet(); + + for (Widget widget : widgets) { +/* ApplicationConnection.getConsole().log( + "Size changed for widget: " + + widget.toString().split(">")[0]); +*/ + Widget parent = widget.getParent(); + while (parent != null && !(parent instanceof Container)) { + parent = parent.getParent(); + } + if (parent != null) { + parents.add((Container) parent); + } + } + + Set parentChanges = new HashSet(); + for (Container parent : parents) { + if (!parent.childComponentSizesUpdated()) { + parentChanges.add((Widget) parent); + } + } + + componentSizeUpdated(parentChanges); + } + /** * Traverses recursively ancestors until ContainerResizedListener child * widget is found. They will delegate it futher if needed. diff --git a/src/com/itmill/toolkit/terminal/gwt/client/ui/IAccordion.java b/src/com/itmill/toolkit/terminal/gwt/client/ui/IAccordion.java index 1790e01540..b194f8947d 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/ui/IAccordion.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/ui/IAccordion.java @@ -299,4 +299,9 @@ public class IAccordion extends ITabsheetBase implements } } + public boolean childComponentSizesUpdated() { + // TODO Auto-generated method stub + return false; + } + } diff --git a/src/com/itmill/toolkit/terminal/gwt/client/ui/ICustomComponent.java b/src/com/itmill/toolkit/terminal/gwt/client/ui/ICustomComponent.java index 34de921c9e..3de0b5761a 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/ui/ICustomComponent.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/ui/ICustomComponent.java @@ -61,4 +61,9 @@ public class ICustomComponent extends SimplePanel implements Container { // TODO custom component could handle its composition roots caption } + public boolean childComponentSizesUpdated() { + // TODO Auto-generated method stub + return false; + } + } diff --git a/src/com/itmill/toolkit/terminal/gwt/client/ui/ICustomLayout.java b/src/com/itmill/toolkit/terminal/gwt/client/ui/ICustomLayout.java index e10f996503..9307b31ffa 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/ui/ICustomLayout.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/ui/ICustomLayout.java @@ -476,4 +476,10 @@ public class ICustomLayout extends ComplexPanel implements Paintable, return false; } }-*/; + + public boolean childComponentSizesUpdated() { + // TODO Auto-generated method stub + return false; + } + } diff --git a/src/com/itmill/toolkit/terminal/gwt/client/ui/IExpandLayout.java b/src/com/itmill/toolkit/terminal/gwt/client/ui/IExpandLayout.java index 081660cd83..6ac56770eb 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/ui/IExpandLayout.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/ui/IExpandLayout.java @@ -768,4 +768,10 @@ public class IExpandLayout extends ComplexPanel implements } rendering = false; } + + public boolean childComponentSizesUpdated() { + // TODO Auto-generated method stub + return false; + } + } diff --git a/src/com/itmill/toolkit/terminal/gwt/client/ui/IFormLayout.java b/src/com/itmill/toolkit/terminal/gwt/client/ui/IFormLayout.java index e9e2343a2e..0fe7226c44 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/ui/IFormLayout.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/ui/IFormLayout.java @@ -301,4 +301,10 @@ public class IFormLayout extends FlexTable implements Container { } } + + public boolean childComponentSizesUpdated() { + // TODO Auto-generated method stub + return false; + } + } diff --git a/src/com/itmill/toolkit/terminal/gwt/client/ui/IGridLayout.java b/src/com/itmill/toolkit/terminal/gwt/client/ui/IGridLayout.java index e418ec109a..df86e676eb 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/ui/IGridLayout.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/ui/IGridLayout.java @@ -286,6 +286,11 @@ public class IGridLayout extends SimplePanel implements Paintable, Container, wrapper.updateCaption(uidl); } + public boolean childComponentSizesUpdated() { + // TODO Auto-generated method stub + return false; + } + } private void iLayout() { @@ -312,4 +317,9 @@ public class IGridLayout extends SimplePanel implements Paintable, Container, Util.runDescendentsLayout(this); } + public boolean childComponentSizesUpdated() { + // TODO Auto-generated method stub + return false; + } + } diff --git a/src/com/itmill/toolkit/terminal/gwt/client/ui/IOrderedLayout.java b/src/com/itmill/toolkit/terminal/gwt/client/ui/IOrderedLayout.java index 213b6f0764..bab7e4c9ef 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/ui/IOrderedLayout.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/ui/IOrderedLayout.java @@ -320,6 +320,10 @@ public class IOrderedLayout extends Panel implements Container, */ private boolean childLayoutsHaveChanged = false; + private int renderedHeight; + + private int renderedWidth; + /** * Construct the DOM of the orderder layout. * @@ -535,7 +539,7 @@ public class IOrderedLayout extends Panel implements Container, handleAlignmentsSpacingAndMargins(uidl); // Reset sizes for the children - updateChildSizes(); + updateChildSizes(-1, -1); // Paint children for (int i = 0; i < childsToPaint.size(); i++) { @@ -550,6 +554,11 @@ public class IOrderedLayout extends Panel implements Container, Util.runDescendentsLayout(this); childLayoutsHaveChanged = false; } + + /* Store the rendered size so we later can see if it has changed */ + renderedWidth = root.getOffsetWidth(); + renderedHeight = root.getOffsetHeight(); + } private void updateMarginAndSpacingSizesFromCSS(UIDL uidl) { @@ -657,7 +666,7 @@ public class IOrderedLayout extends Panel implements Container, } /** Recalculate and apply the space given for each child in this layout. */ - private void updateChildSizes() { + private void updateChildSizes(int renderedWidth, int renderedHeight) { int numChild = childWidgets.size(); int childHeightTotal = -1; @@ -672,7 +681,7 @@ public class IOrderedLayout extends Panel implements Container, if (tableMode) { // If we know explicitly set pixel-size, use that - if (height != null && height.endsWith("px")) { + if (height.endsWith("px")) { try { childHeightTotal = Integer.parseInt(height.substring(0, height.length() - 2)); @@ -686,9 +695,13 @@ public class IOrderedLayout extends Panel implements Container, // In case of invalid number, try to measure the size; childHeightTotal = rootOffsetMeasure("offsetHeight"); } - } - // If not, try to measure the size - else { + } else if (height.endsWith("%") && renderedHeight >= 0) { + // If we have a relative height and know how large we are we + // can + // simply use that + childWidthTotal = renderedHeight; + } else { + // If not pixels, nor percentage, try to measure the size childHeightTotal = rootOffsetMeasure("offsetHeight"); } @@ -718,7 +731,7 @@ public class IOrderedLayout extends Panel implements Container, // Calculate the space for fixed contents minus marginals // If we know explicitly set pixel-size, use that - if (width != null && width.endsWith("px")) { + if (width.endsWith("px")) { try { childWidthTotal = Integer.parseInt(width.substring(0, width .length() - 2)); @@ -733,9 +746,12 @@ public class IOrderedLayout extends Panel implements Container, // In case of invalid number, try to measure the size; childWidthTotal = rootOffsetMeasure("offsetWidth"); } - } - // If not, try to measure the size - else { + } else if (width.endsWith("%") && renderedWidth >= 0) { + // If we have a relative width and know how large we are we can + // simply use that + childWidthTotal = renderedWidth; + } else { + // If not pixels, nor percentage, try to measure the size childWidthTotal = rootOffsetMeasure("offsetWidth"); } @@ -872,6 +888,8 @@ public class IOrderedLayout extends Panel implements Container, */ int lastForcedPixelWidth = -1; + int horizontalPadding = 0, verticalPadding = 0; + /** Widget Wrapper root element */ Element wrapperElement; @@ -1252,31 +1270,72 @@ public class IOrderedLayout extends Panel implements Container, final Element e = getElementWrappingWidgetAndCaption(); + int paddingLeft = 0, paddingRight = 0, paddingTop = 0, paddingBottom = 0; + if (orientationMode == ORIENTATION_HORIZONTAL) { - DOM.setStyleAttribute(e, "paddingLeft", first ? (margins - .hasLeft() ? marginLeft + "px" : "0") - : (hasComponentSpacing ? hSpacing + "px" : "0")); - DOM.setStyleAttribute(e, "paddingRight", last ? (margins - .hasRight() ? marginRight + "px" : "0") : ""); - DOM.setStyleAttribute(e, "paddingTop", - margins.hasTop() ? marginTop + "px" : ""); - DOM.setStyleAttribute(e, "paddingBottom", - margins.hasBottom() ? marginBottom + "px" : ""); + if (first) { + if (margins.hasLeft()) { + paddingLeft = marginLeft; + } + } else if (hasComponentSpacing) { + paddingLeft = hSpacing; + } + + if (last) { + if (margins.hasRight()) { + paddingRight = marginRight; + } + } + + if (margins.hasTop()) { + paddingTop = marginTop; + } + if (margins.hasBottom()) { + paddingBottom = marginBottom; + } + } else { - DOM.setStyleAttribute(e, "paddingLeft", - margins.hasLeft() ? marginLeft + "px" : "0"); - DOM.setStyleAttribute(e, "paddingRight", - margins.hasRight() ? marginRight + "px" : "0"); - DOM.setStyleAttribute(e, "paddingTop", first ? (margins - .hasTop() ? marginTop + "px" : "") - : (hasComponentSpacing ? vSpacing + "px" : "0")); - DOM.setStyleAttribute(e, "paddingBottom", last - && margins.hasBottom() ? marginBottom + "px" : ""); + if (margins.hasLeft()) { + paddingLeft = marginLeft; + } + if (margins.hasRight()) { + paddingRight = marginRight; + } + + if (first) { + if (margins.hasTop()) { + paddingTop = marginTop; + } + } else if (hasComponentSpacing) { + paddingTop = vSpacing; + } + if (last && margins.hasBottom()) { + paddingBottom = marginBottom; + } + } + + horizontalPadding = paddingLeft + paddingRight; + verticalPadding = paddingTop + paddingBottom; + + DOM.setStyleAttribute(e, "paddingLeft", paddingLeft + "px"); + DOM.setStyleAttribute(e, "paddingRight", paddingRight + "px"); + + DOM.setStyleAttribute(e, "paddingTop", paddingTop + "px"); + DOM.setStyleAttribute(e, "paddingBottom", paddingBottom + "px"); } public int getAllocatedHeight() { if (lastForcedPixelHeight == -1) { + if (height == null) { + /* + * We have no height specified so return the space allocated + * by components so far + */ + return getElementWrappingClipperDiv().getOffsetHeight() + - horizontalPadding; + } + return -1; } @@ -1289,6 +1348,15 @@ public class IOrderedLayout extends Panel implements Container, } public int getAllocatedWidth() { + if (width == null) { + /* + * We have no width specified so return the space allocated by + * components so far + */ + return getElementWrappingClipperDiv().getOffsetWidth() + - horizontalPadding; + } + return lastForcedPixelWidth; } } @@ -1451,7 +1519,7 @@ public class IOrderedLayout extends Panel implements Container, /* documented at super */ public void iLayout(int availableWidth, int availableHeight) { - updateChildSizes(); + updateChildSizes(availableWidth, availableHeight); Util.runDescendentsLayout(this); childLayoutsHaveChanged = false; } @@ -1475,4 +1543,35 @@ public class IOrderedLayout extends Panel implements Container, return -1; } + + public boolean childComponentSizesUpdated() { + if (height != null && width != null) { + /* + * If the height and width has been specified for this layout the + * child components cannot make the size of the layout change + */ + + return true; + } + + int currentHeight = getElement().getOffsetHeight(); + int currentWidth = getElement().getOffsetWidth(); + + if (currentHeight != renderedHeight || currentWidth != renderedWidth) { + /* + * Size has changed so we let the child components know about the + * new size. + */ + iLayout(-1, -1); + return false; + } else { + /* + * Size has not changed so we do not need to propagate the event + * further + */ + return true; + } + + } + } diff --git a/src/com/itmill/toolkit/terminal/gwt/client/ui/IPopupView.java b/src/com/itmill/toolkit/terminal/gwt/client/ui/IPopupView.java index a4867d44af..efa6f38bdf 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/ui/IPopupView.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/ui/IPopupView.java @@ -171,10 +171,10 @@ public class IPopupView extends HTML implements Paintable { } public static native void nativeBlur(Element e) /*-{ - if(e.focus) { - e.blur(); - } - }-*/; + if(e.focus) { + e.blur(); + } + }-*/; private class CustomPopup extends IToolkitOverlay implements Container { @@ -228,7 +228,7 @@ public class IPopupView extends HTML implements Paintable { // Notify children that have used the keyboard for (Iterator iterator = activeChildren.iterator(); iterator .hasNext();) { - nativeBlur((Element) iterator.next()); + nativeBlur(iterator.next()); } activeChildren.clear(); remove(popupComponentWidget); @@ -312,6 +312,11 @@ public class IPopupView extends HTML implements Paintable { } } + public boolean childComponentSizesUpdated() { + // TODO Auto-generated method stub + return false; + } + }// class CustomPopup }// class IPopupView diff --git a/src/com/itmill/toolkit/terminal/gwt/client/ui/ITabsheet.java b/src/com/itmill/toolkit/terminal/gwt/client/ui/ITabsheet.java index 566c81f896..b52b0543d6 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/ui/ITabsheet.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/ui/ITabsheet.java @@ -478,4 +478,9 @@ public class ITabsheet extends ITabsheetBase implements ICaption c = (ICaption) captions.get("" + i); c.updateCaption(uidl); } + + public boolean childComponentSizesUpdated() { + // TODO Auto-generated method stub + return false; + } } diff --git a/src/com/itmill/toolkit/terminal/gwt/client/ui/absolutegrid/ISizeableGridLayout.java b/src/com/itmill/toolkit/terminal/gwt/client/ui/absolutegrid/ISizeableGridLayout.java index 80489b881a..c1788b5f9b 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/ui/absolutegrid/ISizeableGridLayout.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/ui/absolutegrid/ISizeableGridLayout.java @@ -249,6 +249,11 @@ public class ISizeableGridLayout extends IAbsoluteGrid implements Paintable, return marginPixels; } + public boolean childComponentSizesUpdated() { + // TODO Auto-generated method stub + return false; + } + } class MarginPixels {