]> source.dussan.org Git - vaadin-framework.git/commitdiff
Initial MeasureManager and working Horizontal/VerticalLayout (#8313)
authorLeif Åstrand <leif@vaadin.com>
Mon, 30 Jan 2012 10:01:48 +0000 (12:01 +0200)
committerLeif Åstrand <leif@vaadin.com>
Mon, 30 Jan 2012 10:01:48 +0000 (12:01 +0200)
src/com/vaadin/terminal/gwt/client/ApplicationConnection.java
src/com/vaadin/terminal/gwt/client/ComponentDetail.java
src/com/vaadin/terminal/gwt/client/FastStringSet.java [new file with mode: 0644]
src/com/vaadin/terminal/gwt/client/MeasureManager.java [new file with mode: 0644]
src/com/vaadin/terminal/gwt/client/Util.java
src/com/vaadin/terminal/gwt/client/VPaintableMap.java
src/com/vaadin/terminal/gwt/client/ui/VHorizontalLayout.java
src/com/vaadin/terminal/gwt/client/ui/VMeasuringOrderedLayout.java [new file with mode: 0644]
src/com/vaadin/terminal/gwt/client/ui/VOrderedLayout.java [deleted file]
src/com/vaadin/terminal/gwt/client/ui/VVerticalLayout.java

index 4252ab0aa6092fc40627c33f8593836384babbb6..064c2404adafc66e48017e643bf29b7f884824fb 100644 (file)
@@ -12,11 +12,14 @@ import java.util.Iterator;
 import java.util.Map;
 import java.util.Set;
 
+import com.google.gwt.core.client.Duration;
 import com.google.gwt.core.client.GWT;
 import com.google.gwt.core.client.JavaScriptObject;
 import com.google.gwt.core.client.JsArray;
 import com.google.gwt.core.client.JsArrayString;
 import com.google.gwt.core.client.Scheduler;
+import com.google.gwt.core.client.Scheduler.ScheduledCommand;
+import com.google.gwt.dom.client.Style;
 import com.google.gwt.http.client.Request;
 import com.google.gwt.http.client.RequestBuilder;
 import com.google.gwt.http.client.RequestCallback;
@@ -34,7 +37,6 @@ import com.google.gwt.user.client.ui.Focusable;
 import com.google.gwt.user.client.ui.HasWidgets;
 import com.google.gwt.user.client.ui.Widget;
 import com.vaadin.terminal.gwt.client.ApplicationConfiguration.ErrorMessage;
-import com.vaadin.terminal.gwt.client.RenderInformation.Size;
 import com.vaadin.terminal.gwt.client.ui.Field;
 import com.vaadin.terminal.gwt.client.ui.VAbstractPaintableWidget;
 import com.vaadin.terminal.gwt.client.ui.VContextMenu;
@@ -1000,6 +1002,8 @@ public class ApplicationConnection {
                 ArrayList<VPaintableWidget> updatedVPaintableWidgets = new ArrayList<VPaintableWidget>();
                 componentCaptionSizeChanges.clear();
 
+                Duration updateDuration = new Duration();
+
                 int length = changes.length();
                 for (int i = 0; i < length; i++) {
                     try {
@@ -1045,25 +1049,10 @@ public class ApplicationConnection {
                             json.getValueMap("dd"));
                 }
 
-                // Check which widgets' size has been updated
-                Set<Widget> sizeUpdatedWidgets = new HashSet<Widget>();
-
-                sizeUpdatedWidgets.addAll(componentCaptionSizeChanges);
-
-                for (VPaintableWidget paintable : updatedVPaintableWidgets) {
-                    Widget widget = paintable.getWidgetForPaintable();
-                    Size oldSize = paintableMap.getOffsetSize(paintable);
-                    Size newSize = new Size(widget.getOffsetWidth(),
-                            widget.getOffsetHeight());
-
-                    if (oldSize == null || !oldSize.equals(newSize)) {
-                        sizeUpdatedWidgets.add(widget);
-                        paintableMap.setOffsetSize(paintable, newSize);
-                    }
-
-                }
+                VConsole.log("updateFromUidl: "
+                        + updateDuration.elapsedMillis() + " ms");
 
-                Util.componentSizeUpdated(sizeUpdatedWidgets);
+                doLayout(false);
 
                 if (meta != null) {
                     if (meta.containsKey("appError")) {
@@ -1806,6 +1795,17 @@ public class ApplicationConnection {
 
         Widget component = paintableMap.getWidget(paintable);
 
+        Style style = component.getElement().getStyle();
+
+        // Dirty if either dimension changed between relative and non-relative
+        if (w.endsWith("%") != style.getWidth().endsWith("%")
+                || h.endsWith("%") != style.getHeight().endsWith("%")) {
+            MeasureManager.MeasuredSize measuredSize = getMeasuredSize(paintable);
+            if (measuredSize != null) {
+                measuredSize.setDirty(true);
+            }
+        }
+
         // Set defined sizes
         component.setHeight(h);
         component.setWidth(w);
@@ -1838,13 +1838,11 @@ public class ApplicationConnection {
      * development. Published to JavaScript.
      */
     public void forceLayout() {
-        Set<Widget> set = new HashSet<Widget>();
-        for (VPaintable paintable : paintableMap.getPaintables()) {
-            if (paintable instanceof VPaintableWidget) {
-                set.add(((VPaintableWidget) paintable).getWidgetForPaintable());
-            }
-        }
-        Util.componentSizeUpdated(set);
+        Duration duration = new Duration();
+
+        doLayout(false);
+
+        VConsole.log("forceLayout in " + duration.elapsedMillis() + " ms");
     }
 
     private void internalRunDescendentsLayout(HasWidgets container) {
@@ -2249,4 +2247,27 @@ public class ApplicationConnection {
                 eventIdentifier);
     }
 
+    private boolean layoutScheduled = false;
+    private ScheduledCommand layoutCommand = new ScheduledCommand() {
+        public void execute() {
+            layoutScheduled = false;
+
+            MeasureManager.get().doLayout(ApplicationConnection.this);
+        }
+    };
+
+    public void doLayout(boolean lazy) {
+        if (!lazy) {
+            layoutCommand.execute();
+        } else if (!layoutScheduled) {
+            layoutScheduled = true;
+            Scheduler.get().scheduleDeferred(layoutCommand);
+        }
+    }
+
+    public MeasureManager.MeasuredSize getMeasuredSize(
+            VPaintableWidget paintable) {
+        return paintableMap.getMeasuredSize(paintable);
+    }
+
 }
index 04e990ddead962612983adbb9682cbee441e67a9..e70a49fdade0f50474f5683481cc82d2fcaa31c4 100644 (file)
@@ -6,11 +6,13 @@ package com.vaadin.terminal.gwt.client;
 import java.util.HashMap;
 
 import com.google.gwt.core.client.JsArrayString;
+import com.vaadin.terminal.gwt.client.MeasureManager.MeasuredSize;
 import com.vaadin.terminal.gwt.client.RenderInformation.Size;
 
 class ComponentDetail {
 
     private TooltipInfo tooltipInfo = new TooltipInfo();
+    private MeasureManager.MeasuredSize measuredSize = new MeasureManager.MeasuredSize();
 
     public ComponentDetail() {
 
@@ -108,4 +110,8 @@ class ComponentDetail {
         }
         return false;
     }
+
+    public MeasureManager.MeasuredSize getMeasuredSize() {
+        return measuredSize;
+    }
 }
diff --git a/src/com/vaadin/terminal/gwt/client/FastStringSet.java b/src/com/vaadin/terminal/gwt/client/FastStringSet.java
new file mode 100644 (file)
index 0000000..e5ba40d
--- /dev/null
@@ -0,0 +1,40 @@
+package com.vaadin.terminal.gwt.client;
+
+import com.google.gwt.core.client.JavaScriptObject;
+import com.google.gwt.core.client.JsArrayString;
+
+public final class FastStringSet extends JavaScriptObject {
+    protected FastStringSet() {
+        // JSO constructor
+    }
+
+    public native boolean contains(String string)
+    /*-{
+        return this.hasOwnProperty(string);
+    }-*/;
+
+    public native void add(String string)
+    /*-{
+        this[string] = true;
+    }-*/;
+
+    public native void addAll(JsArrayString array)
+    /*-{
+        for(var i = 0; i < array.length; i++) {
+            this[array[i]] = true;
+        }
+    }-*/;
+
+    public native JsArrayString dump()
+    /*-{
+        var array = [];
+        for(var string in this) {
+            array.push(string);
+        }
+        return array;
+    }-*/;
+
+    public static FastStringSet create() {
+        return JavaScriptObject.createObject().cast();
+    }
+}
\ No newline at end of file
diff --git a/src/com/vaadin/terminal/gwt/client/MeasureManager.java b/src/com/vaadin/terminal/gwt/client/MeasureManager.java
new file mode 100644 (file)
index 0000000..c2e254b
--- /dev/null
@@ -0,0 +1,280 @@
+package com.vaadin.terminal.gwt.client;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+
+import com.google.gwt.core.client.JsArrayString;
+import com.google.gwt.user.client.ui.HasWidgets;
+import com.google.gwt.user.client.ui.RequiresResize;
+import com.google.gwt.user.client.ui.Widget;
+import com.vaadin.terminal.gwt.client.ui.VMeasuringOrderedLayout;
+
+public class MeasureManager {
+
+    public static final class MeasuredSize {
+        private int width = -1;
+        private int height = -1;
+        private boolean isDirty = true;
+        private int captionWidth = 0;
+        private int captionHeight = 0;
+
+        public int getHeight() {
+            return height;
+        }
+
+        public int getWidth() {
+            return width;
+        }
+
+        public void setHeight(int height) {
+            if (this.height != height) {
+                isDirty = true;
+            }
+            this.height = height;
+        }
+
+        public void setWidth(int width) {
+            if (width != this.width) {
+                isDirty = true;
+            }
+            this.width = width;
+        }
+
+        public boolean isDirty() {
+            return isDirty;
+        }
+
+        public void setDirty(boolean isDirty) {
+            this.isDirty = isDirty;
+        }
+
+        public void setCaptionHeight(int captionHeight) {
+            if (captionHeight != this.captionHeight) {
+                isDirty = true;
+            }
+            this.captionHeight = captionHeight;
+        }
+
+        public void setCaptionWidth(int captionWidth) {
+            if (captionWidth != this.captionWidth) {
+                isDirty = true;
+            }
+            this.captionWidth = captionWidth;
+        }
+
+        public int getCaptionHeight() {
+            return captionHeight;
+        }
+
+        public int getCaptionWidth() {
+            return captionWidth;
+        }
+    }
+
+    private static MeasureManager instance = new MeasureManager();
+
+    public static Collection<VPaintableWidget> getChildren(
+            VPaintableWidget paintable, ApplicationConnection client) {
+        if (!(paintable instanceof Container)) {
+            return Collections.emptySet();
+        }
+        Widget widget = paintable.getWidgetForPaintable();
+        Collection<VPaintableWidget> children = new ArrayList<VPaintableWidget>();
+
+        addDescendantPaintables(widget, children, client);
+
+        return children;
+    }
+
+    private static void addDescendantPaintables(Widget widget,
+            Collection<VPaintableWidget> paintables,
+            ApplicationConnection client) {
+        if (widget instanceof HasWidgets) {
+            VPaintableMap paintableMap = client.getPaintableMap();
+            for (Widget child : (HasWidgets) widget) {
+                VPaintableWidget paintable = paintableMap.getPaintable(child);
+                if (paintable != null) {
+                    paintables.add(paintable);
+                } else {
+                    addDescendantPaintables(child, paintables, client);
+                }
+            }
+        }
+    }
+
+    private static VPaintableWidget getParentPaintable(
+            VPaintableWidget paintable, VPaintableMap paintableMap) {
+        Widget widget = paintable.getWidgetForPaintable();
+        while (true) {
+            widget = widget.getParent();
+            if (widget == null) {
+                return null;
+            }
+            VPaintableWidget parentPaintable = paintableMap
+                    .getPaintable(widget);
+            if (parentPaintable != null) {
+                return parentPaintable;
+            }
+            // Else continue with the parent
+        }
+    }
+
+    public void doLayout(ApplicationConnection client) {
+        VPaintableMap paintableMap = client.getPaintableMap();
+        VPaintableWidget[] paintableWidgets = paintableMap
+                .getRegisteredPaintableWidgets();
+
+        int passes = 0;
+        long start = System.currentTimeMillis();
+        while (true) {
+            long passStart = System.currentTimeMillis();
+            passes++;
+            long measureStart = System.currentTimeMillis();
+            FastStringSet changedSet = findChangedWidgets(paintableWidgets,
+                    paintableMap);
+            JsArrayString changed = changedSet.dump();
+            long measureEnd = System.currentTimeMillis();
+
+            VConsole.log("Measure in " + (measureEnd - measureStart) + " ms");
+
+            if (changed.length() == 0) {
+                VConsole.log("No more changes in pass " + passes);
+                break;
+            }
+
+            if (passes > 100) {
+                VConsole.log("Aborting layout");
+                break;
+            }
+
+            FastStringSet affectedContainers = FastStringSet.create();
+            for (int i = 0; i < changed.length(); i++) {
+                VPaintableWidget paintable = (VPaintableWidget) paintableMap
+                        .getPaintable(changed.get(i));
+                VPaintableWidget parentPaintable = getParentPaintable(
+                        paintable, paintableMap);
+                if (parentPaintable instanceof Container) {
+                    affectedContainers
+                            .add(paintableMap.getPid(parentPaintable));
+                }
+            }
+
+            long layoutStart = System.currentTimeMillis();
+            for (int i = 0; i < changed.length(); i++) {
+                String pid = changed.get(i);
+                VPaintableWidget paintable = (VPaintableWidget) paintableMap
+                        .getPaintable(pid);
+                if (!affectedContainers.contains(pid)) {
+                    Widget widget = paintable.getWidgetForPaintable();
+                    if (widget instanceof RequiresResize) {
+                        // TODO Do nothing here if parent instanceof
+                        // ProvidesRepaint?
+                        ((RequiresResize) widget).onResize();
+                    }
+                }
+            }
+
+            JsArrayString affectedPids = affectedContainers.dump();
+            for (int i = 0; i < affectedPids.length(); i++) {
+                // Find all changed children
+                String containerPid = affectedPids.get(i);
+                VPaintableWidget container = (VPaintableWidget) paintableMap
+                        .getPaintable(containerPid);
+                Collection<VPaintableWidget> children = getChildren(container,
+                        client);
+                HashSet<Widget> changedChildren = new HashSet<Widget>();
+
+                for (VPaintableWidget child : children) {
+                    if (changedSet.contains(paintableMap.getPid(child))) {
+                        changedChildren.add(child.getWidgetForPaintable());
+                    }
+                }
+
+                ((Container) container).requestLayout(changedChildren);
+            }
+
+            long layoutEnd = System.currentTimeMillis();
+            VConsole.log(affectedPids.length()
+                    + " requestLayout invocations in "
+                    + (layoutEnd - layoutStart) + "ms");
+
+            long passEnd = System.currentTimeMillis();
+            StringBuilder b = new StringBuilder();
+            b.append(changed.length());
+            b.append(" changed widgets in pass ");
+            b.append(passes);
+            b.append(" in ");
+            b.append((passEnd - passStart));
+            b.append(" ms: ");
+            if (changed.length() < 10) {
+                for (int i = 0; i < changed.length(); i++) {
+                    if (i != 0) {
+                        b.append(", ");
+                    }
+                    b.append(changed.get(i));
+                }
+            }
+            VConsole.log(b.toString());
+        }
+        long end = System.currentTimeMillis();
+        VConsole.log("Total layout time: " + (end - start) + "ms");
+    }
+
+    private FastStringSet findChangedWidgets(
+            VPaintableWidget[] paintableWidgets, VPaintableMap paintableMap) {
+
+        FastStringSet changed = FastStringSet.create();
+        for (VPaintableWidget paintableWidget : paintableWidgets) {
+            Widget widget = paintableWidget.getWidgetForPaintable();
+            if (paintableWidget instanceof VMeasuringOrderedLayout) {
+                VMeasuringOrderedLayout hasCaptions = (VMeasuringOrderedLayout) paintableWidget;
+                Collection<VCaption> childCaptions = hasCaptions
+                        .getChildCaptions();
+                for (VCaption vCaption : childCaptions) {
+                    VPaintableWidget captionOwner = vCaption.getOwner();
+                    MeasureManager.MeasuredSize measuredSize = paintableMap
+                            .getMeasuredSize(captionOwner);
+
+                    int captionHeight = vCaption.getOffsetHeight();
+                    int captionWidth = vCaption.getOffsetWidth();
+                    if (captionHeight == 0 || captionWidth == 0) {
+                        // Empty caption is probably detached
+                        if (!Util.isAttachedAndDisplayed(vCaption)) {
+                            // Ignore if it is detached
+                            continue;
+                        }
+                    }
+                    measuredSize.setCaptionHeight(captionHeight);
+                    measuredSize.setCaptionWidth(captionWidth);
+                    if (measuredSize.isDirty()) {
+                        changed.add(paintableMap.getPid(captionOwner));
+                        measuredSize.setDirty(false);
+                    }
+                }
+            }
+
+            MeasureManager.MeasuredSize measuredSize = paintableMap
+                    .getMeasuredSize(paintableWidget);
+
+            measuredSize.setWidth(widget.getOffsetWidth());
+            measuredSize.setHeight(widget.getOffsetHeight());
+
+            if (measuredSize.isDirty()) {
+                changed.add(paintableMap.getPid(paintableWidget));
+                measuredSize.setDirty(false);
+            }
+        }
+
+        return changed;
+    }
+
+    private MeasureManager() {
+        // Singleton constructor
+    }
+
+    public static MeasureManager get() {
+        return instance;
+    }
+}
index 0a3d83ff3d3cda1423a3856bfa4cb9ad15ce48da..39b44a506c41bf55f3288e9d3e4c0bbff75fc80c 100644 (file)
@@ -5,11 +5,7 @@
 package com.vaadin.terminal.gwt.client;
 
 import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Set;
+import java.util.List;
 
 import com.google.gwt.core.client.Scheduler;
 import com.google.gwt.core.client.Scheduler.ScheduledCommand;
@@ -24,7 +20,6 @@ import com.google.gwt.user.client.DOM;
 import com.google.gwt.user.client.Element;
 import com.google.gwt.user.client.Event;
 import com.google.gwt.user.client.EventListener;
-import com.google.gwt.user.client.Timer;
 import com.google.gwt.user.client.Window;
 import com.google.gwt.user.client.ui.HasWidgets;
 import com.google.gwt.user.client.ui.RootPanel;
@@ -65,30 +60,6 @@ public class Util {
         return el;
     }-*/;
 
-    private static final int LAZY_SIZE_CHANGE_TIMEOUT = 400;
-    private static Set<Widget> latelyChangedWidgets = new HashSet<Widget>();
-
-    private static Timer lazySizeChangeTimer = new Timer() {
-        private boolean lazySizeChangeTimerScheduled = false;
-
-        @Override
-        public void run() {
-            componentSizeUpdated(latelyChangedWidgets);
-            latelyChangedWidgets.clear();
-            lazySizeChangeTimerScheduled = false;
-        }
-
-        @Override
-        public void schedule(int delayMillis) {
-            if (lazySizeChangeTimerScheduled) {
-                cancel();
-            } else {
-                lazySizeChangeTimerScheduled = true;
-            }
-            super.schedule(delayMillis);
-        }
-    };
-
     /**
      * This helper method can be called if components size have been changed
      * outside rendering phase. It notifies components parent about the size
@@ -106,58 +77,40 @@ public class Util {
      *            run componentSizeUpdated lazyly
      */
     public static void notifyParentOfSizeChange(Widget widget, boolean lazy) {
-        if (lazy) {
-            latelyChangedWidgets.add(widget);
-            lazySizeChangeTimer.schedule(LAZY_SIZE_CHANGE_TIMEOUT);
-        } else {
-            Set<Widget> widgets = new HashSet<Widget>();
-            widgets.add(widget);
-            Util.componentSizeUpdated(widgets);
+        ApplicationConnection applicationConnection = findApplicationConnectionFor(widget);
+        if (applicationConnection != null) {
+            applicationConnection.doLayout(lazy);
         }
     }
 
-    /**
-     * Called when the size of one or more widgets have changed during
-     * rendering. Finds parent container and notifies them of the size change.
-     * 
-     * @param paintables
-     */
-    public static void componentSizeUpdated(Set<Widget> widgets) {
-        if (widgets.isEmpty()) {
-            return;
-        }
+    private static boolean findAppConnectionWarningDisplayed = false;
 
-        Map<Container, Set<Widget>> childWidgets = new HashMap<Container, Set<Widget>>();
+    private static ApplicationConnection findApplicationConnectionFor(
+            Widget widget) {
+        if (!findAppConnectionWarningDisplayed) {
+            findAppConnectionWarningDisplayed = true;
+            VConsole.log("Warning: Using Util.findApplicationConnectionFor which should be eliminated once there is a better way to find the ApplicationConnection for a Paintable");
+        }
 
-        for (Widget widget : widgets) {
-            if (!widget.isAttached()) {
+        List<ApplicationConnection> runningApplications = ApplicationConfiguration
+                .getRunningApplications();
+        for (ApplicationConnection applicationConnection : runningApplications) {
+            VPaintableMap paintableMap = applicationConnection
+                    .getPaintableMap();
+            VPaintableWidget paintable = paintableMap.getPaintable(widget);
+            if (paintable == null) {
                 continue;
             }
-
-            // ApplicationConnection.getConsole().log(
-            // "Widget " + Util.getSimpleName(widget) + " size updated");
-            Widget parent = widget.getParent();
-            while (parent != null && !(parent instanceof Container)) {
-                parent = parent.getParent();
-            }
-            if (parent != null) {
-                Set<Widget> set = childWidgets.get(parent);
-                if (set == null) {
-                    set = new HashSet<Widget>();
-                    childWidgets.put((Container) parent, set);
+            String pid = paintableMap.getPid(paintable);
+            if (pid != null) {
+                VPaintable otherPaintable = paintableMap.getPaintable(pid);
+                if (otherPaintable == paintable) {
+                    return applicationConnection;
                 }
-                set.add(widget);
-            }
-        }
-
-        Set<Widget> parentChanges = new HashSet<Widget>();
-        for (Container parent : childWidgets.keySet()) {
-            if (!parent.requestLayout(childWidgets.get(parent))) {
-                parentChanges.add(parent.getWidgetForPaintable());
             }
         }
 
-        componentSizeUpdated(parentChanges);
+        return null;
     }
 
     public static float parseRelativeSize(String size) {
@@ -614,20 +567,7 @@ public class Util {
 
     public static void updateRelativeChildrenAndSendSizeUpdateEvent(
             ApplicationConnection client, HasWidgets container, Widget widget) {
-        /*
-         * Relative sized children must be updated first so the component has
-         * the correct outer dimensions when signaling a size change to the
-         * parent.
-         */
-        Iterator<Widget> childIterator = container.iterator();
-        while (childIterator.hasNext()) {
-            Widget w = childIterator.next();
-            client.handleComponentRelativeSize(w);
-        }
-
-        HashSet<Widget> widgets = new HashSet<Widget>();
-        widgets.add(widget);
-        Util.componentSizeUpdated(widgets);
+        notifyParentOfSizeChange(widget, false);
     }
 
     public static native int getRequiredWidth(
index c810d56e5106605ba56c0604b452e69a3ad82e3d..31aec87aa04aeb554cc97f06889c2075ddb17eba 100644 (file)
@@ -3,6 +3,7 @@
  */\r
 package com.vaadin.terminal.gwt.client;\r
 \r
+import java.util.ArrayList;\r
 import java.util.Collection;\r
 import java.util.Collections;\r
 import java.util.HashMap;\r
@@ -16,6 +17,7 @@ import com.google.gwt.user.client.Element;
 import com.google.gwt.user.client.ui.HasWidgets;\r
 import com.google.gwt.user.client.ui.Widget;\r
 import com.vaadin.terminal.Paintable;\r
+import com.vaadin.terminal.gwt.client.MeasureManager.MeasuredSize;\r
 import com.vaadin.terminal.gwt.client.RenderInformation.Size;\r
 \r
 public class VPaintableMap {\r
@@ -208,6 +210,21 @@ public class VPaintableMap {
 \r
     }\r
 \r
+    public VPaintableWidget[] getRegisteredPaintableWidgets() {\r
+        ArrayList<VPaintableWidget> result = new ArrayList<VPaintableWidget>();\r
+\r
+        for (VPaintable paintable : getPaintables()) {\r
+            if (paintable instanceof VPaintableWidget) {\r
+                VPaintableWidget paintableWidget = (VPaintableWidget) paintable;\r
+                if (!unregistryBag.contains(getPid(paintable))) {\r
+                    result.add(paintableWidget);\r
+                }\r
+            }\r
+        }\r
+\r
+        return result.toArray(new VPaintableWidget[result.size()]);\r
+    }\r
+\r
     void purgeUnregistryBag(boolean unregisterPaintables) {\r
         if (unregisterPaintables) {\r
             for (String pid : unregistryBag) {\r
@@ -375,4 +392,17 @@ public class VPaintableMap {
         return getPid(w) != null;\r
     }\r
 \r
+    /**\r
+     * FIXME: Should not be here\r
+     */\r
+    @Deprecated\r
+    public MeasuredSize getMeasuredSize(VPaintableWidget paintable) {\r
+        ComponentDetail componentDetail = getComponentDetail(paintable);\r
+        if (componentDetail == null) {\r
+            return null;\r
+        }\r
+\r
+        return componentDetail.getMeasuredSize();\r
+    }\r
+\r
 }\r
index b3a036f7488f00257b14fe970c312e6ac3daf70d..30796b16606fdd4afeddca093292726094f178f8 100644 (file)
@@ -3,12 +3,12 @@
  */
 package com.vaadin.terminal.gwt.client.ui;
 
-public class VHorizontalLayout extends VOrderedLayout {
+public class VHorizontalLayout extends VMeasuringOrderedLayout {
 
     public static final String CLASSNAME = "v-horizontallayout";
 
     public VHorizontalLayout() {
-        super(CLASSNAME, ORIENTATION_HORIZONTAL);
+        super(CLASSNAME, false);
     }
 
 }
diff --git a/src/com/vaadin/terminal/gwt/client/ui/VMeasuringOrderedLayout.java b/src/com/vaadin/terminal/gwt/client/ui/VMeasuringOrderedLayout.java
new file mode 100644 (file)
index 0000000..817cf9b
--- /dev/null
@@ -0,0 +1,539 @@
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+package com.vaadin.terminal.gwt.client.ui;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+import com.google.gwt.dom.client.DivElement;
+import com.google.gwt.dom.client.Document;
+import com.google.gwt.dom.client.Element;
+import com.google.gwt.dom.client.Style;
+import com.google.gwt.dom.client.Style.Overflow;
+import com.google.gwt.dom.client.Style.Position;
+import com.google.gwt.dom.client.Style.Unit;
+import com.google.gwt.user.client.DOM;
+import com.google.gwt.user.client.ui.ComplexPanel;
+import com.google.gwt.user.client.ui.RequiresResize;
+import com.google.gwt.user.client.ui.Widget;
+import com.vaadin.terminal.gwt.client.ApplicationConnection;
+import com.vaadin.terminal.gwt.client.Container;
+import com.vaadin.terminal.gwt.client.MeasureManager;
+import com.vaadin.terminal.gwt.client.RenderSpace;
+import com.vaadin.terminal.gwt.client.UIDL;
+import com.vaadin.terminal.gwt.client.VCaption;
+import com.vaadin.terminal.gwt.client.VPaintableMap;
+import com.vaadin.terminal.gwt.client.VPaintableWidget;
+import com.vaadin.terminal.gwt.client.ValueMap;
+
+public class VMeasuringOrderedLayout extends ComplexPanel implements Container,
+        RequiresResize {
+
+    public static final String CLASSNAME = "v-orderedlayout";
+
+    private static final int MARGIN_SIZE = 20;
+
+    private final boolean isVertical;
+
+    private ApplicationConnection client;
+
+    private String id;
+
+    private RenderSpace space;
+
+    private ValueMap expandRatios;
+
+    private ValueMap alignments;
+
+    private Map<VPaintableWidget, VCaption> captions = new HashMap<VPaintableWidget, VCaption>();
+
+    private boolean spacing;
+
+    private VMarginInfo activeMarginsInfo;
+
+    protected VMeasuringOrderedLayout(String className, boolean isVertical) {
+        DivElement element = Document.get().createDivElement();
+        setElement(element);
+        // TODO These should actually be defined in css
+        Style style = element.getStyle();
+        style.setOverflow(Overflow.HIDDEN);
+        style.setPosition(Position.RELATIVE);
+
+        setStyleName(className);
+        this.isVertical = isVertical;
+    }
+
+    public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
+        this.client = client;
+        id = uidl.getId();
+        if (client.updateComponent(this, uidl, true)) {
+            return;
+        }
+
+        long start = System.currentTimeMillis();
+        // long childTime = 0;
+
+        HashSet<Widget> previousChildren = new HashSet<Widget>();
+        for (Widget child : this) {
+            if (!(child instanceof VCaption)) {
+                previousChildren.add(child);
+            }
+        }
+        // TODO Support reordering elements!
+        for (final Iterator<Object> it = uidl.getChildIterator(); it.hasNext();) {
+            final UIDL childUIDL = (UIDL) it.next();
+            final VPaintableWidget child = client.getPaintable(childUIDL);
+            Widget widget = child.getWidgetForPaintable();
+
+            if (widget.getParent() != this) {
+                DivElement wrapper = Document.get().createDivElement();
+                wrapper.getStyle().setPosition(Position.ABSOLUTE);
+                getElement().appendChild(wrapper);
+                add(widget, wrapper);
+            }
+
+            if (!childUIDL.getBooleanAttribute("cached")) {
+                child.updateFromUIDL(childUIDL, client);
+                client.getMeasuredSize(child).setDirty(true);
+            }
+            // TODO Update alignments and expand ratios
+
+            previousChildren.remove(widget);
+        }
+
+        for (Widget widget : previousChildren) {
+            Element wrapper = getWrapper(widget);
+            VCaption caption = captions.remove(widget);
+            if (caption != null) {
+                remove(caption);
+            }
+            remove(widget);
+            // Remove the wrapper
+            getElement().removeChild(wrapper);
+
+            client.unregisterPaintable((VPaintableWidget) widget);
+        }
+
+        int bitMask = uidl.getIntAttribute("margins");
+        if (activeMarginsInfo == null
+                || activeMarginsInfo.getBitMask() != bitMask) {
+            activeMarginsInfo = new VMarginInfo(bitMask);
+        }
+
+        spacing = uidl.getBooleanAttribute("spacing");
+        expandRatios = uidl.getMapAttribute("expandRatios");
+        alignments = uidl.getMapAttribute("alignments");
+        client.getMeasuredSize(this).setDirty(true);
+    }
+
+    private static Element getWrapper(Widget widget) {
+        return widget.getElement().getParentElement();
+    }
+
+    private void add(Widget widget, DivElement wrapper) {
+        add(widget, (com.google.gwt.user.client.Element) wrapper.cast());
+    }
+
+    public void onResize() {
+        requestLayout(Collections.<Widget> emptySet());
+    }
+
+    private static boolean isUndefinedInDirection(Widget widget,
+            boolean isVertical) {
+        String dimension = getDimensionInDirection(widget, isVertical);
+        return dimension == null || dimension.length() == 0;
+    }
+
+    private static boolean isRelativeInDirection(Widget widget,
+            boolean isVertical) {
+        String dimension = getDimensionInDirection(widget, isVertical);
+        return dimension != null && dimension.endsWith("%");
+    }
+
+    private static String getDimensionInDirection(Widget widget,
+            boolean vertical) {
+        com.google.gwt.user.client.Element element = widget.getElement();
+        Style style = element.getStyle();
+        if (vertical) {
+            return style.getHeight();
+        } else {
+            return style.getWidth();
+        }
+    }
+
+    public void replaceChildComponent(Widget oldComponent, Widget newComponent) {
+        throw new UnsupportedOperationException();
+    }
+
+    public boolean hasChildComponent(Widget component) {
+        return component.getParent() == this;
+    }
+
+    public void updateCaption(VPaintableWidget component, UIDL uidl) {
+        if (VCaption.isNeeded(uidl)) {
+            VCaption caption = captions.get(component);
+            if (caption == null) {
+                caption = new VCaption(component, client);
+
+                Widget widget = (Widget) component;
+                Element wrapper = getWrapper(widget);
+
+                // Logical attach.
+                getChildren().add(caption);
+
+                // Physical attach.
+                DOM.insertBefore(
+                        (com.google.gwt.user.client.Element) wrapper.cast(),
+                        caption.getElement(), widget.getElement());
+
+                // Adopt.
+                adopt(caption);
+                captions.put(component, caption);
+            }
+            caption.updateCaption(uidl);
+        } else {
+            VCaption removedCaption = captions.remove(component);
+            if (removedCaption != null) {
+                remove(removedCaption);
+                MeasureManager.MeasuredSize measuredSize = client
+                        .getMeasuredSize(component);
+                measuredSize.setCaptionHeight(0);
+                measuredSize.setCaptionWidth(0);
+            }
+        }
+
+    }
+
+    private void layoutPrimaryDirection() {
+        Collection<VPaintableWidget> children = MeasureManager.getChildren(
+                this, client);
+
+        // First pass - get total expand ratio and allocated size
+        int totalAllocated = 0;
+        double totalExpand = 0;
+        for (VPaintableWidget child : children) {
+            Widget widget = child.getWidgetForPaintable();
+
+            totalExpand += getExpandRatio(child);
+
+            int captionAllocation;
+            if (isVertical) {
+                captionAllocation = getCaptionHeight(child);
+                getWrapper(widget).getStyle().setPaddingTop(captionAllocation,
+                        Unit.PX);
+            } else {
+                captionAllocation = 0;
+            }
+
+            if (!isRelativeInDirection(widget, isVertical)) {
+                totalAllocated += getMeasuredInDirection(child, isVertical)
+                        + captionAllocation;
+            }
+        }
+        int startMargin = getStartMarginInDirection(isVertical);
+        int totalMargins = startMargin + getEndMarginInDirection(isVertical);
+
+        totalAllocated += totalMargins
+                + (getSpacingInDirection(isVertical) * (children.size() - 1));
+
+        Style ownStyle = getElement().getStyle();
+        double ownSize;
+        if (isUndefinedInDirection(this, isVertical)) {
+            ownSize = totalAllocated;
+            ownStyle.setProperty(getMinPropertyName(isVertical),
+                    totalAllocated, Unit.PX);
+        } else {
+            ownSize = getMeasuredInDirection(this, isVertical);
+            ownStyle.clearProperty(getMinPropertyName(isVertical));
+        }
+
+        double unallocatedSpace = Math.max(0, ownSize - totalAllocated);
+
+        double currentLocation = startMargin;
+        for (VPaintableWidget child : children) {
+            Widget widget = child.getWidgetForPaintable();
+            Element wrapper = getWrapper(widget);
+            Style wrapperStyle = wrapper.getStyle();
+
+            double childExpandRatio;
+            if (totalExpand == 0) {
+                childExpandRatio = 1d / children.size();
+            } else {
+                childExpandRatio = getExpandRatio(child) / totalExpand;
+            }
+
+            double extraPixels = unallocatedSpace * childExpandRatio;
+
+            boolean relative = isRelativeInDirection(widget, isVertical);
+
+            double size = getMeasuredInDirection(child, isVertical);
+            int captionHeight = getCaptionHeight(child);
+
+            if (isVertical) {
+                size += captionHeight;
+            } else if (!relative) {
+                size = Math.max(size, getCaptionWidth(child));
+            }
+
+            double allocatedSpace = extraPixels;
+            if (!relative) {
+                allocatedSpace += size;
+            }
+
+            int alignment = getAlignmentInDirection(getAlignment(child),
+                    isVertical);
+
+            if (relative) {
+                double captionReservation = isVertical ? captionHeight : 0;
+                wrapperStyle.setProperty(getSizeProperty(isVertical),
+                        allocatedSpace - captionReservation, Unit.PX);
+            } else {
+                wrapperStyle.clearProperty(getSizeProperty(isVertical));
+            }
+
+            double startPosition = currentLocation;
+            if (alignment == 0) {
+                // Centered
+                startPosition += (allocatedSpace - size) / 2;
+            } else if (alignment == 1) {
+                // Right or bottom
+                startPosition += allocatedSpace - size;
+            }
+
+            wrapperStyle.setProperty(getStartProperty(isVertical),
+                    startPosition, Unit.PX);
+
+            currentLocation += allocatedSpace
+                    + getSpacingInDirection(isVertical);
+        }
+    }
+
+    private int getEndMarginInDirection(boolean isVertical) {
+        if (isVertical) {
+            return activeMarginsInfo.hasBottom() ? MARGIN_SIZE : 0;
+        } else {
+            return activeMarginsInfo.hasRight() ? MARGIN_SIZE : 0;
+        }
+    }
+
+    private int getStartMarginInDirection(boolean isVertical) {
+        if (isVertical) {
+            return activeMarginsInfo.hasTop() ? MARGIN_SIZE : 0;
+        } else {
+            return activeMarginsInfo.hasLeft() ? MARGIN_SIZE : 0;
+        }
+    }
+
+    private void layoutSecondaryDirection() {
+        Collection<VPaintableWidget> children = MeasureManager.getChildren(
+                this, client);
+
+        int maxSize = 0;
+        for (VPaintableWidget child : children) {
+            Widget widget = child.getWidgetForPaintable();
+
+            int captionAllocation;
+            if (!isVertical) {
+                captionAllocation = getCaptionHeight(child);
+                getWrapper(widget).getStyle().setPaddingTop(captionAllocation,
+                        Unit.PX);
+            } else {
+                captionAllocation = 0;
+            }
+
+            if (!isRelativeInDirection(widget, !isVertical)) {
+                int childSize = getMeasuredInDirection(child, !isVertical)
+                        + captionAllocation;
+                maxSize = Math.max(maxSize, childSize);
+            }
+        }
+
+        int startMargin = getStartMarginInDirection(!isVertical);
+        int totalMargins = startMargin + getEndMarginInDirection(!isVertical);
+
+        double availableSpace;
+        Style ownStyle = getElement().getStyle();
+
+        if (isUndefinedInDirection(this, !isVertical)) {
+            ownStyle.setProperty(getMinPropertyName(!isVertical), maxSize
+                    + totalMargins, Unit.PX);
+            availableSpace = maxSize;
+        } else {
+            ownStyle.clearProperty(getMinPropertyName(!isVertical));
+            availableSpace = getMeasuredInDirection(this, !isVertical)
+                    - totalMargins;
+        }
+
+        for (VPaintableWidget child : children) {
+            Widget widget = child.getWidgetForPaintable();
+            Element wrapper = getWrapper(widget);
+            Style wrapperStyle = wrapper.getStyle();
+
+            boolean relative = isRelativeInDirection(widget, !isVertical);
+
+            int captionHeight = getCaptionHeight(child);
+
+            double allocatedSize = getMeasuredInDirection(child, !isVertical);
+            if (!isVertical) {
+                allocatedSize += captionHeight;
+            } else if (!relative) {
+                allocatedSize = Math.max(allocatedSize, getCaptionWidth(child));
+            }
+
+            int alignment = getAlignmentInDirection(getAlignment(child),
+                    !isVertical);
+
+            double startPosition = startMargin;
+            if (alignment == 0) {
+                startPosition += (availableSpace - allocatedSize) / 2;
+                // Centered
+            } else if (alignment == 1) {
+                // Right or bottom
+                startPosition += (availableSpace - allocatedSize);
+            }
+
+            wrapperStyle.setProperty(getStartProperty(!isVertical),
+                    startPosition, Unit.PX);
+
+            if (relative) {
+                double captionReservation = !isVertical ? captionHeight : 0;
+                wrapperStyle.setProperty(getSizeProperty(!isVertical),
+                        availableSpace - captionReservation, Unit.PX);
+            } else {
+                wrapperStyle.clearProperty(getSizeProperty(!isVertical));
+            }
+        }
+    }
+
+    public boolean requestLayout(Set<Widget> changed) {
+        layoutPrimaryDirection();
+        layoutSecondaryDirection();
+
+        // Doesn't matter right now...
+        return true;
+    }
+
+    private static int getAlignmentInDirection(AlignmentInfo alignment,
+            boolean isVertical) {
+        if (alignment == null) {
+            return -1;
+        }
+        if (isVertical) {
+            if (alignment.isTop()) {
+                return -1;
+            } else if (alignment.isBottom()) {
+                return 1;
+            } else {
+                return 0;
+            }
+        } else {
+            if (alignment.isLeft()) {
+                return -1;
+            } else if (alignment.isRight()) {
+                return 1;
+            } else {
+                return 0;
+            }
+        }
+    }
+
+    private int getSpacingInDirection(boolean isVertical) {
+        if (spacing) {
+            return 20;
+        } else {
+            return 0;
+        }
+    }
+
+    private int getCaptionWidth(VPaintableWidget child) {
+        MeasureManager.MeasuredSize measuredSize = client
+                .getMeasuredSize(child);
+        return measuredSize.getCaptionWidth();
+    }
+
+    private int getCaptionHeight(VPaintableWidget child) {
+        MeasureManager.MeasuredSize measuredSize = client
+                .getMeasuredSize(child);
+        int captionHeight = measuredSize.getCaptionHeight();
+
+        VCaption caption = captions.get(child);
+        if (caption != null) {
+            caption.getElement().getStyle()
+                    .setMarginTop(-captionHeight, Unit.PX);
+        }
+        return captionHeight;
+    }
+
+    private AlignmentInfo getAlignment(VPaintableWidget child) {
+        String pid = VPaintableMap.get(client).getPid(child);
+        if (alignments.containsKey(pid)) {
+            return new AlignmentInfo(alignments.getInt(pid));
+        } else {
+            return AlignmentInfo.TOP_LEFT;
+        }
+    }
+
+    private double getExpandRatio(VPaintableWidget child) {
+        String pid = VPaintableMap.get(client).getPid(child);
+        if (expandRatios.containsKey(pid)) {
+            return expandRatios.getRawNumber(pid);
+        } else {
+            return 0;
+        }
+    }
+
+    private static String getSizeProperty(boolean isVertical) {
+        return isVertical ? "height" : "width";
+    }
+
+    private static String getStartProperty(boolean isVertical) {
+        return isVertical ? "top" : "left";
+    }
+
+    private static String getMinPropertyName(boolean isVertical) {
+        return isVertical ? "minHeight" : "minWidth";
+    }
+
+    private int getMeasuredInDirection(VPaintableWidget paintable,
+            boolean isVertical) {
+        MeasureManager.MeasuredSize measuredSize = client
+                .getMeasuredSize(paintable);
+        if (isVertical) {
+            return measuredSize.getHeight();
+        } else {
+            return measuredSize.getWidth();
+        }
+    }
+
+    public Collection<VCaption> getChildCaptions() {
+        return captions.values();
+    }
+
+    public RenderSpace getAllocatedSpace(Widget child) {
+        // Concept borrowed from CSS layout
+        if (space == null) {
+            space = new RenderSpace(-1, -1) {
+                @Override
+                public int getWidth() {
+                    return getOffsetWidth();
+                }
+
+                @Override
+                public int getHeight() {
+                    return getOffsetHeight();
+                }
+            };
+        }
+        return space;
+    }
+
+    public Widget getWidgetForPaintable() {
+        return this;
+    }
+}
diff --git a/src/com/vaadin/terminal/gwt/client/ui/VOrderedLayout.java b/src/com/vaadin/terminal/gwt/client/ui/VOrderedLayout.java
deleted file mode 100644 (file)
index f490e51..0000000
+++ /dev/null
@@ -1,976 +0,0 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-package com.vaadin.terminal.gwt.client.ui;
-
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.Set;
-
-import com.google.gwt.core.client.JsArrayString;
-import com.google.gwt.dom.client.Style.Unit;
-import com.google.gwt.event.dom.client.DomEvent.Type;
-import com.google.gwt.event.shared.EventHandler;
-import com.google.gwt.event.shared.HandlerRegistration;
-import com.google.gwt.user.client.Element;
-import com.google.gwt.user.client.ui.Widget;
-import com.vaadin.terminal.gwt.client.ApplicationConnection;
-import com.vaadin.terminal.gwt.client.BrowserInfo;
-import com.vaadin.terminal.gwt.client.EventId;
-import com.vaadin.terminal.gwt.client.RenderInformation.FloatSize;
-import com.vaadin.terminal.gwt.client.RenderInformation.Size;
-import com.vaadin.terminal.gwt.client.RenderSpace;
-import com.vaadin.terminal.gwt.client.UIDL;
-import com.vaadin.terminal.gwt.client.Util;
-import com.vaadin.terminal.gwt.client.VPaintableMap;
-import com.vaadin.terminal.gwt.client.VPaintableWidget;
-import com.vaadin.terminal.gwt.client.ValueMap;
-import com.vaadin.terminal.gwt.client.ui.layout.CellBasedLayout;
-import com.vaadin.terminal.gwt.client.ui.layout.ChildComponentContainer;
-
-public class VOrderedLayout extends CellBasedLayout {
-
-    public static final String CLASSNAME = "v-orderedlayout";
-
-    private int orientation;
-
-    // Can be removed once OrderedLayout is removed
-    private boolean allowOrientationUpdate = false;
-
-    /**
-     * Size of the layout excluding any margins.
-     */
-    private Size activeLayoutSize = new Size(0, 0);
-
-    private boolean isRendering = false;
-
-    private String width = "";
-
-    private boolean sizeHasChangedDuringRendering = false;
-
-    private ValueMap expandRatios;
-
-    private double expandRatioSum;
-
-    private double defaultExpandRatio;
-
-    private ValueMap alignments;
-
-    private LayoutClickEventHandler clickEventHandler = new LayoutClickEventHandler(
-            this, EventId.LAYOUT_CLICK) {
-
-        @Override
-        protected VPaintableWidget getChildComponent(Element element) {
-            return getComponent(element);
-        }
-
-        @Override
-        protected <H extends EventHandler> HandlerRegistration registerHandler(
-                H handler, Type<H> type) {
-            return addDomHandler(handler, type);
-        }
-    };
-
-    public VOrderedLayout() {
-        this(CLASSNAME, ORIENTATION_VERTICAL);
-        allowOrientationUpdate = true;
-    }
-
-    protected VOrderedLayout(String className, int orientation) {
-        setStyleName(className);
-        this.orientation = orientation;
-
-        STYLENAME_SPACING = className + "-spacing";
-        STYLENAME_MARGIN_TOP = className + "-margin-top";
-        STYLENAME_MARGIN_RIGHT = className + "-margin-right";
-        STYLENAME_MARGIN_BOTTOM = className + "-margin-bottom";
-        STYLENAME_MARGIN_LEFT = className + "-margin-left";
-    }
-
-    @Override
-    public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
-        isRendering = true;
-        super.updateFromUIDL(uidl, client);
-
-        // Only non-cached, visible UIDL:s can introduce changes
-        if (uidl.getBooleanAttribute("cached")
-                || uidl.getBooleanAttribute("invisible")) {
-            isRendering = false;
-            return;
-        }
-
-        clickEventHandler.handleEventHandlerRegistration(client);
-
-        if (allowOrientationUpdate) {
-            handleOrientationUpdate(uidl);
-        }
-
-        // IStopWatch w = new IStopWatch("OrderedLayout.updateFromUIDL");
-
-        ArrayList<Widget> uidlWidgets = new ArrayList<Widget>(
-                uidl.getChildCount());
-        ArrayList<ChildComponentContainer> relativeSizeComponents = new ArrayList<ChildComponentContainer>();
-        ArrayList<UIDL> relativeSizeComponentUIDL = new ArrayList<UIDL>();
-
-        int pos = 0;
-        for (final Iterator<Object> it = uidl.getChildIterator(); it.hasNext();) {
-            final UIDL childUIDL = (UIDL) it.next();
-            final VPaintableWidget childPaintable = client
-                    .getPaintable(childUIDL);
-            Widget widget = childPaintable.getWidgetForPaintable();
-
-            // Create container for component
-            ChildComponentContainer childComponentContainer = getComponentContainer(widget);
-
-            if (childComponentContainer == null) {
-                // This is a new component
-                childComponentContainer = createChildContainer(childPaintable);
-            } else {
-                /*
-                 * The widget may be null if the same paintable has been
-                 * rendered in a different component container while this has
-                 * been invisible. Ensure the childComponentContainer has the
-                 * widget attached. See e.g. #5372
-                 */
-                childComponentContainer.setPaintable(childPaintable);
-            }
-
-            addOrMoveChild(childComponentContainer, pos++);
-
-            /*
-             * Components which are to be expanded in the same orientation as
-             * the layout are rendered later when it is clear how much space
-             * they can use
-             */
-            if (!Util.isCached(childUIDL)) {
-                FloatSize relativeSize = Util.parseRelativeSize(childUIDL);
-                childComponentContainer.setRelativeSize(relativeSize);
-            }
-
-            if (childComponentContainer.isComponentRelativeSized(orientation)) {
-                relativeSizeComponents.add(childComponentContainer);
-                relativeSizeComponentUIDL.add(childUIDL);
-            } else {
-                if (isDynamicWidth()) {
-                    childComponentContainer.renderChild(childUIDL, client, -1);
-                } else {
-                    childComponentContainer.renderChild(childUIDL, client,
-                            activeLayoutSize.getWidth());
-                }
-                if (sizeHasChangedDuringRendering && Util.isCached(childUIDL)) {
-                    // notify cached relative sized component about size
-                    // chance
-                    client.handleComponentRelativeSize(childComponentContainer
-                            .getWidget());
-                }
-            }
-
-            uidlWidgets.add(widget);
-
-        }
-
-        // w.mark("Rendering of "
-        // + (uidlWidgets.size() - relativeSizeComponents.size())
-        // + " absolute size components done");
-
-        /*
-         * Remove any children after pos. These are the ones that previously
-         * were in the layout but have now been removed
-         */
-        removeChildrenAfter(pos);
-
-        // w.mark("Old children removed");
-
-        /* Fetch alignments and expand ratio from UIDL */
-        updateAlignmentsAndExpandRatios(uidl, uidlWidgets);
-        // w.mark("Alignments and expand ratios updated");
-
-        /* Fetch widget sizes from rendered components */
-        updateWidgetSizes();
-        // w.mark("Widget sizes updated");
-
-        recalculateLayout();
-        // w.mark("Layout size calculated (" + activeLayoutSize +
-        // ") offsetSize: "
-        // + getOffsetWidth() + "," + getOffsetHeight());
-
-        /* Render relative size components */
-        for (int i = 0; i < relativeSizeComponents.size(); i++) {
-            ChildComponentContainer childComponentContainer = relativeSizeComponents
-                    .get(i);
-            UIDL childUIDL = relativeSizeComponentUIDL.get(i);
-
-            if (isDynamicWidth()) {
-                childComponentContainer.renderChild(childUIDL, client, -1);
-            } else {
-                childComponentContainer.renderChild(childUIDL, client,
-                        activeLayoutSize.getWidth());
-            }
-
-            if (Util.isCached(childUIDL)) {
-                /*
-                 * We must update the size of the relative sized component if
-                 * the expand ratio or something else in the layout changes
-                 * which affects the size of a relative sized component
-                 */
-                client.handleComponentRelativeSize(childComponentContainer
-                        .getWidget());
-            }
-
-            // childComponentContainer.updateWidgetSize();
-        }
-
-        // w.mark("Rendering of " + (relativeSizeComponents.size())
-        // + " relative size components done");
-
-        /* Fetch widget sizes for relative size components */
-        for (ChildComponentContainer childComponentContainer : widgetToComponentContainer
-                .values()) {
-
-            /* Update widget size from DOM */
-            childComponentContainer.updateWidgetSize();
-        }
-
-        // w.mark("Widget sizes updated");
-
-        /*
-         * Components with relative size in main direction may affect the layout
-         * size in the other direction
-         */
-        if ((isHorizontal() && isDynamicHeight())
-                || (isVertical() && isDynamicWidth())) {
-            layoutSizeMightHaveChanged();
-        }
-        // w.mark("Layout dimensions updated");
-
-        /* Update component spacing */
-        updateContainerMargins();
-
-        /*
-         * Update component sizes for components with relative size in non-main
-         * direction
-         */
-        if (updateRelativeSizesInNonMainDirection()) {
-            // Sizes updated - might affect the other dimension so we need to
-            // recheck the widget sizes and recalculate layout dimensions
-            updateWidgetSizes();
-            layoutSizeMightHaveChanged();
-        }
-        calculateAlignments();
-        // w.mark("recalculateComponentSizesAndAlignments done");
-
-        setRootSize();
-
-        if (BrowserInfo.get().isIE()) {
-            /*
-             * This should fix the issue with padding not always taken into
-             * account for the containers leading to no spacing between
-             * elements.
-             */
-            root.getStyle().setProperty("zoom", "1");
-        }
-
-        // w.mark("runDescendentsLayout done");
-        isRendering = false;
-        sizeHasChangedDuringRendering = false;
-    }
-
-    private void layoutSizeMightHaveChanged() {
-        Size oldSize = new Size(activeLayoutSize.getWidth(),
-                activeLayoutSize.getHeight());
-        calculateLayoutDimensions();
-
-        /*
-         * If layout dimension changes we must also update container sizes
-         */
-        if (!oldSize.equals(activeLayoutSize)) {
-            calculateContainerSize();
-        }
-    }
-
-    private void updateWidgetSizes() {
-        for (ChildComponentContainer childComponentContainer : widgetToComponentContainer
-                .values()) {
-
-            /*
-             * Update widget size from DOM
-             */
-            childComponentContainer.updateWidgetSize();
-        }
-    }
-
-    private void recalculateLayout() {
-
-        /* Calculate space for relative size components */
-        int spaceForExpansion = calculateLayoutDimensions();
-
-        if (!widgetToComponentContainer.isEmpty()) {
-            /* Divide expansion space between component containers */
-            expandComponentContainers(spaceForExpansion);
-
-            /* Update container sizes */
-            calculateContainerSize();
-        }
-
-    }
-
-    private void expandComponentContainers(int spaceForExpansion) {
-        int remaining = spaceForExpansion;
-        for (ChildComponentContainer childComponentContainer : widgetToComponentContainer
-                .values()) {
-            remaining -= childComponentContainer.expand(orientation,
-                    spaceForExpansion);
-        }
-
-        if (remaining > 0) {
-
-            // Some left-over pixels due to rounding errors
-
-            // Add one pixel to each container until there are no pixels left
-            // FIXME extra pixels should be divided among expanded widgets if
-            // such a widgets exists
-
-            Iterator<Widget> widgetIterator = iterator();
-            while (widgetIterator.hasNext() && remaining-- > 0) {
-                ChildComponentContainer childComponentContainer = (ChildComponentContainer) widgetIterator
-                        .next();
-                childComponentContainer.expandExtra(orientation, 1);
-            }
-        }
-
-    }
-
-    private void handleOrientationUpdate(UIDL uidl) {
-        int newOrientation = ORIENTATION_VERTICAL;
-        if ("horizontal".equals(uidl.getStringAttribute("orientation"))) {
-            newOrientation = ORIENTATION_HORIZONTAL;
-        }
-
-        if (orientation != newOrientation) {
-            orientation = newOrientation;
-
-            for (ChildComponentContainer childComponentContainer : widgetToComponentContainer
-                    .values()) {
-                childComponentContainer.setOrientation(orientation);
-            }
-        }
-
-    }
-
-    /**
-     * Updated components with relative height in horizontal layouts and
-     * components with relative width in vertical layouts. This is only needed
-     * if the height (horizontal layout) or width (vertical layout) has not been
-     * specified.
-     */
-    private boolean updateRelativeSizesInNonMainDirection() {
-        int updateDirection = 1 - orientation;
-        if ((updateDirection == ORIENTATION_HORIZONTAL && !isDynamicWidth())
-                || (updateDirection == ORIENTATION_VERTICAL && !isDynamicHeight())) {
-            return false;
-        }
-
-        boolean updated = false;
-        for (ChildComponentContainer componentContainer : widgetToComponentContainer
-                .values()) {
-            if (componentContainer.isComponentRelativeSized(updateDirection)) {
-                client.handleComponentRelativeSize(componentContainer
-                        .getWidget());
-            }
-
-            updated = true;
-        }
-
-        return updated;
-    }
-
-    private int calculateLayoutDimensions() {
-        int summedWidgetWidth = 0;
-        int summedWidgetHeight = 0;
-
-        int maxWidgetWidth = 0;
-        int maxWidgetHeight = 0;
-
-        // Calculate layout dimensions from component dimensions
-        for (ChildComponentContainer childComponentContainer : widgetToComponentContainer
-                .values()) {
-
-            int widgetHeight = 0;
-            int widgetWidth = 0;
-            if (childComponentContainer.isComponentRelativeSized(orientation)) {
-                if (orientation == ORIENTATION_HORIZONTAL) {
-                    widgetHeight = getWidgetHeight(childComponentContainer);
-                } else {
-                    widgetWidth = getWidgetWidth(childComponentContainer);
-                }
-            } else {
-                widgetWidth = getWidgetWidth(childComponentContainer);
-                widgetHeight = getWidgetHeight(childComponentContainer);
-            }
-
-            summedWidgetWidth += widgetWidth;
-            summedWidgetHeight += widgetHeight;
-
-            maxWidgetHeight = Math.max(maxWidgetHeight, widgetHeight);
-            maxWidgetWidth = Math.max(maxWidgetWidth, widgetWidth);
-        }
-
-        if (isHorizontal()) {
-            summedWidgetWidth += activeSpacing.hSpacing
-                    * (widgetToComponentContainer.size() - 1);
-        } else {
-            summedWidgetHeight += activeSpacing.vSpacing
-                    * (widgetToComponentContainer.size() - 1);
-        }
-
-        Size layoutSize = updateLayoutDimensions(summedWidgetWidth,
-                summedWidgetHeight, maxWidgetWidth, maxWidgetHeight);
-
-        int remainingSpace;
-        if (isHorizontal()) {
-            remainingSpace = layoutSize.getWidth() - summedWidgetWidth;
-        } else {
-            remainingSpace = layoutSize.getHeight() - summedWidgetHeight;
-        }
-        if (remainingSpace < 0) {
-            remainingSpace = 0;
-        }
-
-        // ApplicationConnection.getConsole().log(
-        // "Layout size: " + activeLayoutSize);
-        return remainingSpace;
-    }
-
-    private int getWidgetHeight(ChildComponentContainer childComponentContainer) {
-        Size s = childComponentContainer.getWidgetSize();
-        return s.getHeight()
-                + childComponentContainer.getCaptionHeightAboveComponent();
-    }
-
-    private int getWidgetWidth(ChildComponentContainer childComponentContainer) {
-        Size s = childComponentContainer.getWidgetSize();
-        int widgetWidth = s.getWidth()
-                + childComponentContainer.getCaptionWidthAfterComponent();
-
-        /*
-         * If the component does not have a specified size in the main direction
-         * the caption may determine the space used by the component
-         */
-        if (!childComponentContainer.widgetHasSizeSpecified(orientation)) {
-            int captionWidth = childComponentContainer
-                    .getCaptionRequiredWidth();
-
-            if (captionWidth > widgetWidth) {
-                widgetWidth = captionWidth;
-            }
-        }
-
-        return widgetWidth;
-    }
-
-    private void calculateAlignments() {
-        int w = 0;
-        int h = 0;
-
-        if (isHorizontal()) {
-            // HORIZONTAL
-            h = activeLayoutSize.getHeight();
-            if (!isDynamicWidth()) {
-                w = -1;
-            }
-
-        } else {
-            // VERTICAL
-            w = activeLayoutSize.getWidth();
-            if (!isDynamicHeight()) {
-                h = -1;
-            }
-        }
-
-        for (ChildComponentContainer childComponentContainer : widgetToComponentContainer
-                .values()) {
-            childComponentContainer.updateAlignments(w, h);
-        }
-
-    }
-
-    private void calculateContainerSize() {
-
-        /*
-         * Container size here means the size the container gets from the
-         * component. The expansion size is not include in this but taken
-         * separately into account.
-         */
-        int height = 0, width = 0;
-        Iterator<Widget> widgetIterator = iterator();
-        if (isHorizontal()) {
-            height = activeLayoutSize.getHeight();
-            int availableWidth = activeLayoutSize.getWidth();
-            boolean first = true;
-            while (widgetIterator.hasNext()) {
-                ChildComponentContainer childComponentContainer = (ChildComponentContainer) widgetIterator
-                        .next();
-                if (!childComponentContainer
-                        .isComponentRelativeSized(ORIENTATION_HORIZONTAL)) {
-                    /*
-                     * Only components with non-relative size in the main
-                     * direction has a container size
-                     */
-                    width = childComponentContainer.getWidgetSize().getWidth()
-                            + childComponentContainer
-                                    .getCaptionWidthAfterComponent();
-
-                    /*
-                     * If the component does not have a specified size in the
-                     * main direction the caption may determine the space used
-                     * by the component
-                     */
-                    if (!childComponentContainer
-                            .widgetHasSizeSpecified(orientation)) {
-                        int captionWidth = childComponentContainer
-                                .getCaptionRequiredWidth();
-                        // ApplicationConnection.getConsole().log(
-                        // "Component width: " + width
-                        // + ", caption width: " + captionWidth);
-                        if (captionWidth > width) {
-                            width = captionWidth;
-                        }
-                    }
-                } else {
-                    width = 0;
-                }
-
-                if (!isDynamicWidth()) {
-                    if (availableWidth == 0) {
-                        /*
-                         * Let the overflowing components overflow. IE has
-                         * problems with zero sizes.
-                         */
-                        // width = 0;
-                        // height = 0;
-                    } else if (width > availableWidth) {
-                        width = availableWidth;
-
-                        if (!first) {
-                            width -= activeSpacing.hSpacing;
-                        }
-                        availableWidth = 0;
-                    } else {
-                        availableWidth -= width;
-                        if (!first) {
-                            availableWidth -= activeSpacing.hSpacing;
-                        }
-                    }
-
-                    first = false;
-                }
-
-                childComponentContainer.setContainerSize(width, height);
-            }
-        } else {
-            width = activeLayoutSize.getWidth();
-            while (widgetIterator.hasNext()) {
-                ChildComponentContainer childComponentContainer = (ChildComponentContainer) widgetIterator
-                        .next();
-
-                if (!childComponentContainer
-                        .isComponentRelativeSized(ORIENTATION_VERTICAL)) {
-                    /*
-                     * Only components with non-relative size in the main
-                     * direction has a container size
-                     */
-                    height = childComponentContainer.getWidgetSize()
-                            .getHeight()
-                            + childComponentContainer
-                                    .getCaptionHeightAboveComponent();
-                } else {
-                    height = 0;
-                }
-
-                childComponentContainer.setContainerSize(width, height);
-            }
-
-        }
-
-    }
-
-    private Size updateLayoutDimensions(int totalComponentWidth,
-            int totalComponentHeight, int maxComponentWidth,
-            int maxComponentHeight) {
-
-        /* Only need to calculate dynamic dimensions */
-        if (!isDynamicHeight() && !isDynamicWidth()) {
-            return activeLayoutSize;
-        }
-
-        int activeLayoutWidth = 0;
-        int activeLayoutHeight = 0;
-
-        // Update layout dimensions
-        if (isHorizontal()) {
-            // Horizontal
-            if (isDynamicWidth()) {
-                activeLayoutWidth = totalComponentWidth;
-            }
-
-            if (isDynamicHeight()) {
-                activeLayoutHeight = maxComponentHeight;
-            }
-
-        } else {
-            // Vertical
-            if (isDynamicWidth()) {
-                activeLayoutWidth = maxComponentWidth;
-            }
-
-            if (isDynamicHeight()) {
-                activeLayoutHeight = totalComponentHeight;
-            }
-        }
-
-        if (isDynamicWidth()) {
-            setActiveLayoutWidth(activeLayoutWidth);
-            setOuterLayoutWidth(activeLayoutSize.getWidth());
-        }
-
-        if (isDynamicHeight()) {
-            setActiveLayoutHeight(activeLayoutHeight);
-            setOuterLayoutHeight(activeLayoutSize.getHeight());
-        }
-
-        return activeLayoutSize;
-    }
-
-    private void setActiveLayoutWidth(int activeLayoutWidth) {
-        if (activeLayoutWidth < 0) {
-            activeLayoutWidth = 0;
-        }
-        activeLayoutSize.setWidth(activeLayoutWidth);
-    }
-
-    private void setActiveLayoutHeight(int activeLayoutHeight) {
-        if (activeLayoutHeight < 0) {
-            activeLayoutHeight = 0;
-        }
-        activeLayoutSize.setHeight(activeLayoutHeight);
-
-    }
-
-    private void setOuterLayoutWidth(int activeLayoutWidth) {
-        // Don't call setWidth to avoid triggering all kinds of recalculations
-        // Also don't call super.setWidth to avoid messing with the
-        // dynamicWidth property
-        int newPixelWidth = (activeLayoutWidth + activeMargins.getHorizontal());
-        getElement().getStyle().setWidth(newPixelWidth, Unit.PX);
-    }
-
-    private void setOuterLayoutHeight(int activeLayoutHeight) {
-        // Don't call setHeight to avoid triggering all kinds of recalculations
-        // Also don't call super.setHeight to avoid messing with the
-        // dynamicHeight property
-        int newPixelHeight = (activeLayoutHeight + activeMargins.getVertical());
-        getElement().getStyle().setHeight(newPixelHeight, Unit.PX);
-    }
-
-    /**
-     * Updates the spacing between components. Needs to be done only when
-     * components are added/removed.
-     */
-    private void updateContainerMargins() {
-        ChildComponentContainer firstChildComponent = getFirstChildComponentContainer();
-        if (firstChildComponent != null) {
-            firstChildComponent.setMarginLeft(0);
-            firstChildComponent.setMarginTop(0);
-
-            for (ChildComponentContainer childComponent : widgetToComponentContainer
-                    .values()) {
-                if (childComponent == firstChildComponent) {
-                    continue;
-                }
-
-                if (isHorizontal()) {
-                    childComponent.setMarginLeft(activeSpacing.hSpacing);
-                } else {
-                    childComponent.setMarginTop(activeSpacing.vSpacing);
-                }
-            }
-        }
-    }
-
-    private boolean isHorizontal() {
-        return orientation == ORIENTATION_HORIZONTAL;
-    }
-
-    private boolean isVertical() {
-        return orientation == ORIENTATION_VERTICAL;
-    }
-
-    private ChildComponentContainer createChildContainer(VPaintableWidget child) {
-
-        // Create a container DIV for the child
-        ChildComponentContainer childComponent = new ChildComponentContainer(
-                child, orientation);
-
-        return childComponent;
-
-    }
-
-    public RenderSpace getAllocatedSpace(Widget child) {
-        int width = 0;
-        int height = 0;
-        ChildComponentContainer childComponentContainer = getComponentContainer(child);
-        // WIDTH CALCULATION
-        if (isVertical()) {
-            width = activeLayoutSize.getWidth();
-            width -= childComponentContainer.getCaptionWidthAfterComponent();
-        } else if (!isDynamicWidth()) {
-            // HORIZONTAL
-            width = childComponentContainer.getContSize().getWidth();
-            width -= childComponentContainer.getCaptionWidthAfterComponent();
-        }
-
-        // HEIGHT CALCULATION
-        if (isHorizontal()) {
-            height = activeLayoutSize.getHeight();
-            height -= childComponentContainer.getCaptionHeightAboveComponent();
-        } else if (!isDynamicHeight()) {
-            // VERTICAL
-            height = childComponentContainer.getContSize().getHeight();
-            height -= childComponentContainer.getCaptionHeightAboveComponent();
-        }
-
-        // ApplicationConnection.getConsole().log(
-        // "allocatedSpace for " + Util.getSimpleName(child) + ": "
-        // + width + "," + height);
-        RenderSpace space = new RenderSpace(width, height);
-        return space;
-    }
-
-    private void recalculateLayoutAndComponentSizes() {
-        recalculateLayout();
-
-        if (!(isDynamicHeight() && isDynamicWidth())) {
-            /* First update relative sized components */
-            for (ChildComponentContainer componentContainer : widgetToComponentContainer
-                    .values()) {
-                client.handleComponentRelativeSize(componentContainer
-                        .getWidget());
-
-                // Update widget size from DOM
-                componentContainer.updateWidgetSize();
-            }
-        }
-
-        if (isDynamicHeight()) {
-            /*
-             * Height is not necessarily correct anymore as the height of
-             * components might have changed if the width has changed.
-             */
-
-            /*
-             * Get the new widget sizes from DOM and calculate new container
-             * sizes
-             */
-            updateWidgetSizes();
-
-            /* Update layout dimensions based on widget sizes */
-            recalculateLayout();
-        }
-
-        updateRelativeSizesInNonMainDirection();
-        calculateAlignments();
-
-        setRootSize();
-    }
-
-    private void setRootSize() {
-        root.getStyle().setPropertyPx("width", activeLayoutSize.getWidth());
-        root.getStyle().setPropertyPx("height", activeLayoutSize.getHeight());
-    }
-
-    public boolean requestLayout(Set<Widget> children) {
-        for (Widget p : children) {
-            /* Update widget size from DOM */
-            ChildComponentContainer componentContainer = getComponentContainer(p);
-            // This should no longer be needed (after #2563)
-            // if (isDynamicWidth()) {
-            // componentContainer.setUnlimitedContainerWidth();
-            // } else {
-            // componentContainer.setLimitedContainerWidth(activeLayoutSize
-            // .getWidth());
-            // }
-
-            componentContainer.updateWidgetSize();
-
-            /*
-             * If this is the result of an caption icon onload event the caption
-             * size may have changed
-             */
-            componentContainer.updateCaptionSize();
-        }
-
-        Size sizeBefore = new Size(activeLayoutSize.getWidth(),
-                activeLayoutSize.getHeight());
-
-        recalculateLayoutAndComponentSizes();
-        boolean sameSize = (sizeBefore.equals(activeLayoutSize));
-        if (!sameSize) {
-            /* Must inform child components about possible size updates */
-            client.runDescendentsLayout(this);
-        }
-
-        /* Automatically propagated upwards if the size has changed */
-
-        return sameSize;
-    }
-
-    @Override
-    public void setHeight(String height) {
-        Size sizeBefore = new Size(activeLayoutSize.getWidth(),
-                activeLayoutSize.getHeight());
-
-        super.setHeight(height);
-
-        if (height != null && !height.equals("")) {
-            setActiveLayoutHeight(getOffsetHeight()
-                    - activeMargins.getVertical());
-        }
-
-        if (isRendering) {
-            sizeHasChangedDuringRendering = true;
-        } else {
-            recalculateLayoutAndComponentSizes();
-            boolean sameSize = (sizeBefore.equals(activeLayoutSize));
-            if (!sameSize) {
-                /* Must inform child components about possible size updates */
-                client.runDescendentsLayout(this);
-            }
-        }
-    }
-
-    @Override
-    public void setWidth(String width) {
-        if (this.width.equals(width) || !isVisible()) {
-            return;
-        }
-        Size sizeBefore = new Size(activeLayoutSize.getWidth(),
-                activeLayoutSize.getHeight());
-
-        super.setWidth(width);
-        this.width = width;
-        if (width != null && !width.equals("")) {
-            setActiveLayoutWidth(getOffsetWidth()
-                    - activeMargins.getHorizontal());
-        }
-
-        if (isRendering) {
-            sizeHasChangedDuringRendering = true;
-        } else {
-            recalculateLayoutAndComponentSizes();
-            boolean sameSize = (sizeBefore.equals(activeLayoutSize));
-            if (!sameSize) {
-                /* Must inform child components about possible size updates */
-                client.runDescendentsLayout(this);
-            }
-            /*
-             * If the height changes as a consequence of this we must inform the
-             * parent also
-             */
-            if (isDynamicHeight()
-                    && sizeBefore.getHeight() != activeLayoutSize.getHeight()) {
-                Util.notifyParentOfSizeChange(this, false);
-            }
-
-        }
-    }
-
-    protected void updateAlignmentsAndExpandRatios(UIDL uidl,
-            ArrayList<Widget> renderedWidgets) {
-
-        /*
-         */
-        alignments = uidl.getMapAttribute("alignments");
-
-        /*
-         * UIDL contains a map of paintable ids to expand ratios
-         */
-
-        expandRatios = uidl.getMapAttribute("expandRatios");
-        expandRatioSum = -1.0;
-
-        for (int i = 0; i < renderedWidgets.size(); i++) {
-            Widget widget = renderedWidgets.get(i);
-            String pid = VPaintableMap.get(client).getPid(widget);
-
-            ChildComponentContainer container = getComponentContainer(widget);
-
-            // Calculate alignment info
-            container.setAlignment(getAlignment(pid));
-
-            // Update expand ratio
-            container.setNormalizedExpandRatio(getExpandRatio(pid));
-        }
-    }
-
-    private AlignmentInfo getAlignment(String pid) {
-        if (alignments.containsKey(pid)) {
-            return new AlignmentInfo(alignments.getInt(pid));
-        } else {
-            return AlignmentInfo.TOP_LEFT;
-        }
-    }
-
-    private double getExpandRatio(String pid) {
-        if (expandRatioSum < 0) {
-            expandRatioSum = 0;
-            JsArrayString keyArray = expandRatios.getKeyArray();
-            int length = keyArray.length();
-            for (int i = 0; i < length; i++) {
-                expandRatioSum += expandRatios.getRawNumber(keyArray.get(i));
-            }
-            if (expandRatioSum == 0) {
-                // by default split equally among components
-                defaultExpandRatio = 1.0 / widgetToComponentContainer.size();
-            } else {
-                defaultExpandRatio = 0;
-            }
-        }
-        if (expandRatios.containsKey(pid)) {
-            return expandRatios.getRawNumber(pid) / expandRatioSum;
-        } else {
-            return defaultExpandRatio;
-        }
-    }
-
-    public void updateCaption(VPaintableWidget paintable, UIDL uidl) {
-        Widget widget = paintable.getWidgetForPaintable();
-        ChildComponentContainer componentContainer = getComponentContainer(widget);
-        componentContainer.updateCaption(uidl, client);
-        if (!isRendering) {
-            /*
-             * This was a component-only update and the possible size change
-             * must be propagated to the layout
-             */
-            client.captionSizeUpdated(widget);
-        }
-    }
-
-    /**
-     * Returns the deepest nested child component which contains "element". The
-     * child component is also returned if "element" is part of its caption.
-     * 
-     * @param element
-     *            An element that is a nested sub element of the root element in
-     *            this layout
-     * @return The Paintable which the element is a part of. Null if the element
-     *         belongs to the layout and not to a child.
-     */
-    private VPaintableWidget getComponent(Element element) {
-        return Util.getPaintableForElement(client, this, element);
-    }
-
-    public Widget getWidgetForPaintable() {
-        return this;
-    }
-
-}
index fe5749ec8b03d549e93dcba64ed31f90aaa57e45..03b71321b2631530ade8a08f7729142e6c6e8077 100644 (file)
@@ -3,12 +3,12 @@
  */
 package com.vaadin.terminal.gwt.client.ui;
 
-public class VVerticalLayout extends VOrderedLayout {
+public class VVerticalLayout extends VMeasuringOrderedLayout {
 
     public static final String CLASSNAME = "v-verticallayout";
 
     public VVerticalLayout() {
-        super(CLASSNAME, ORIENTATION_VERTICAL);
+        super(CLASSNAME, true);
     }
 
 }