]> source.dussan.org Git - vaadin-framework.git/commitdiff
Added method for a component to notify its parent container when its size change
authorArtur Signell <artur.signell@itmill.com>
Fri, 19 Sep 2008 07:47:48 +0000 (07:47 +0000)
committerArtur Signell <artur.signell@itmill.com>
Fri, 19 Sep 2008 07:47:48 +0000 (07:47 +0000)
svn changeset:5453/svn branch:trunk

14 files changed:
src/com/itmill/toolkit/terminal/gwt/client/ApplicationConnection.java
src/com/itmill/toolkit/terminal/gwt/client/Container.java
src/com/itmill/toolkit/terminal/gwt/client/ContainerResizedListener.java
src/com/itmill/toolkit/terminal/gwt/client/Util.java
src/com/itmill/toolkit/terminal/gwt/client/ui/IAccordion.java
src/com/itmill/toolkit/terminal/gwt/client/ui/ICustomComponent.java
src/com/itmill/toolkit/terminal/gwt/client/ui/ICustomLayout.java
src/com/itmill/toolkit/terminal/gwt/client/ui/IExpandLayout.java
src/com/itmill/toolkit/terminal/gwt/client/ui/IFormLayout.java
src/com/itmill/toolkit/terminal/gwt/client/ui/IGridLayout.java
src/com/itmill/toolkit/terminal/gwt/client/ui/IOrderedLayout.java
src/com/itmill/toolkit/terminal/gwt/client/ui/IPopupView.java
src/com/itmill/toolkit/terminal/gwt/client/ui/ITabsheet.java
src/com/itmill/toolkit/terminal/gwt/client/ui/absolutegrid/ISizeableGridLayout.java

index 4de30f7f3206ec1b5308544a003081b0ef09753d..9c26bdc063e0a341c19d12e8ccefa67d5dd96aae 100755 (executable)
@@ -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<Widget> sizeUpdatedWidgets = new HashSet<Widget>();
+
         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()
index b79fe2c6063e1e079163039252a40f7caa872edf..8675a0cb5523749c7fa23fdbd2cd17c0fe9b1af8 100644 (file)
@@ -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();
 }
index d3634a1804c3dae990a0dde9a172682dfac22808..0ad667782bf1d2ff63d7903c6f45671e5e2d6ca2 100644 (file)
@@ -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);
 }
index 8981054d707c00cc1682fc1aaca2456003673196..24ceb5d21bca917a6dd3f82583f34a52da133537 100644 (file)
@@ -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<Widget> widgets) {
+        if (widgets.isEmpty()) {
+            return;
+        }
+
+        Set<Container> parents = new HashSet<Container>();
+
+        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<Widget> parentChanges = new HashSet<Widget>();
+        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.
index 1790e0154099b07969be718ff1f117f0e6af5f7e..b194f8947d39c3bf4f8066239af04c21955aef23 100644 (file)
@@ -299,4 +299,9 @@ public class IAccordion extends ITabsheetBase implements
         }
     }
 
+    public boolean childComponentSizesUpdated() {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
 }
index 34de921c9e027417e0557f7e61368909d7ca2591..3de0b5761ad1bcbe757c8c51050b2c5dde297d53 100644 (file)
@@ -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;
+    }
+
 }
index e10f9965036e4d177d919419742e21bd1d5ffc79..9307b31ffa77214b206eb6595c7f6377f689b02e 100644 (file)
@@ -476,4 +476,10 @@ public class ICustomLayout extends ComplexPanel implements Paintable,
                return false;
        }
     }-*/;
+
+    public boolean childComponentSizesUpdated() {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
 }
index 081660cd83756499deb636f5e42aac36d72c9d7f..6ac56770eb73c1726b362b1c418f91dc106466bd 100644 (file)
@@ -768,4 +768,10 @@ public class IExpandLayout extends ComplexPanel implements
         }
         rendering = false;
     }
+
+    public boolean childComponentSizesUpdated() {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
 }
index e9e2343a2ebdc65c160b06191c56b618275b3ec6..0fe7226c4497f465dce5d0bdaa628cd3e20217ad 100644 (file)
@@ -301,4 +301,10 @@ public class IFormLayout extends FlexTable implements Container {
         }
 
     }
+
+    public boolean childComponentSizesUpdated() {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
 }
index e418ec109afd87928ae0b68a6501ef1501032a2b..df86e676eb878ed9168d97e0276e8d4269b9b4b0 100644 (file)
@@ -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;
+    }
+
 }
index 213b6f0764de260cef121ae1d94d3805d89ac3b4..bab7e4c9ef3074f08eb0516b282f98ea88ae89e9 100644 (file)
@@ -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;
+        }
+
+    }
+
 }
index a4867d44af147629bee4b55e0caf39e86a404a5f..efa6f38bdf0e18d0d8d76dfe491ebbe26ad54453 100644 (file)
@@ -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<Element> 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
index 566c81f8965fcc2efd81866f4bb9998675c7c675..b52b0543d619a0d1df6d1772e4b146c1856307f6 100644 (file)
@@ -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;
+    }
 }
index 80489b881a7ce0055ec032ecd042bed3cde8aaf9..c1788b5f9b3dc45d04561826aa61e333bd7867ce 100644 (file)
@@ -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 {