]> source.dussan.org Git - vaadin-framework.git/commitdiff
Update GridLayout to use VLayoutSlot (#8313)
authorLeif Åstrand <leif@vaadin.com>
Tue, 21 Feb 2012 13:27:36 +0000 (15:27 +0200)
committerLeif Åstrand <leif@vaadin.com>
Tue, 21 Feb 2012 13:27:36 +0000 (15:27 +0200)
WebContent/VAADIN/themes/base/gridlayout/gridlayout.css
src/com/vaadin/terminal/gwt/client/ui/VGridLayout.java
src/com/vaadin/terminal/gwt/client/ui/VGridLayoutPaintable.java
src/com/vaadin/terminal/gwt/client/ui/layout/ChildComponentContainer.java [deleted file]

index 38e2bb3aed8b3ca07ba32599950609c02df26f71..9edaf152a0faee3cb76dc38f20860eac82f2293c 100644 (file)
@@ -1,3 +1,9 @@
+.v-gridlayout {
+       position: relative;
+}
+.v-gridlayout-slot {
+       position: absolute;
+}
 .v-gridlayout-margin-top {
        padding-top: 12px;
 }
index 62851219013718bda1fa3ce8e40f1db42618e4b9..0d56f47a6f2852eb6ca8c520f026a56515c77c32 100644 (file)
@@ -4,56 +4,39 @@
 
 package com.vaadin.terminal.gwt.client.ui;
 
-import java.util.ArrayList;
 import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
-import java.util.Set;
 
 import com.google.gwt.dom.client.DivElement;
 import com.google.gwt.dom.client.Document;
+import com.google.gwt.dom.client.Style;
+import com.google.gwt.dom.client.Style.Position;
+import com.google.gwt.dom.client.Style.Unit;
 import com.google.gwt.user.client.Element;
-import com.google.gwt.user.client.ui.AbsolutePanel;
-import com.google.gwt.user.client.ui.SimplePanel;
+import com.google.gwt.user.client.ui.ComplexPanel;
 import com.google.gwt.user.client.ui.Widget;
 import com.vaadin.terminal.gwt.client.ApplicationConnection;
-import com.vaadin.terminal.gwt.client.RenderSpace;
-import com.vaadin.terminal.gwt.client.StyleConstants;
+import com.vaadin.terminal.gwt.client.MeasuredSize;
 import com.vaadin.terminal.gwt.client.UIDL;
 import com.vaadin.terminal.gwt.client.Util;
+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.ui.layout.ChildComponentContainer;
+import com.vaadin.terminal.gwt.client.ui.layout.VLayoutSlot;
+import com.vaadin.terminal.gwt.client.ui.layout.VPaintableLayoutSlot;
 
-public class VGridLayout extends SimplePanel {
+public class VGridLayout extends ComplexPanel {
 
     public static final String CLASSNAME = "v-gridlayout";
 
-    private DivElement margin = Document.get().createDivElement();
-
-    final AbsolutePanel canvas = new AbsolutePanel();
-
     ApplicationConnection client;
 
-    protected HashMap<Widget, ChildComponentContainer> widgetToComponentContainer = new HashMap<Widget, ChildComponentContainer>();
-
     HashMap<Widget, Cell> widgetToCell = new HashMap<Widget, Cell>();
 
-    private int spacingPixelsHorizontal;
-    private int spacingPixelsVertical;
-
     int[] columnWidths;
     int[] rowHeights;
 
-    private int height;
-
-    private int width;
-
-    private boolean undefinedWidth;
-
-    private boolean undefinedHeight;
-
     int[] colExpandRatioArray;
 
     int[] rowExpandRatioArray;
@@ -62,22 +45,26 @@ public class VGridLayout extends SimplePanel {
 
     private int[] minRowHeights;
 
-    boolean rendering;
-
-    HashMap<Widget, ChildComponentContainer> nonRenderedWidgets;
-
-    boolean sizeChangedDuringRendering = false;
+    DivElement spacingMeasureElement;
 
     public VGridLayout() {
         super();
-        getElement().appendChild(margin);
+        setElement(Document.get().createDivElement());
+
+        spacingMeasureElement = Document.get().createDivElement();
+        Style spacingStyle = spacingMeasureElement.getStyle();
+        spacingStyle.setPosition(Position.ABSOLUTE);
+        getElement().appendChild(spacingMeasureElement);
+
         setStyleName(CLASSNAME);
-        setWidget(canvas);
     }
 
-    @Override
-    protected Element getContainerElement() {
-        return margin.cast();
+    private MeasuredSize getMeasuredSize() {
+        return getPaintable().getMeasuredSize();
+    }
+
+    private VPaintableWidget getPaintable() {
+        return VPaintableMap.get(client).getPaintable(this);
     }
 
     /**
@@ -104,7 +91,7 @@ public class VGridLayout extends SimplePanel {
      * @return
      */
     protected int getHorizontalSpacing() {
-        return spacingPixelsHorizontal;
+        return getMeasuredSize().getDependencyOuterWidth(spacingMeasureElement);
     }
 
     /**
@@ -113,7 +100,8 @@ public class VGridLayout extends SimplePanel {
      * @return
      */
     protected int getVerticalSpacing() {
-        return spacingPixelsVertical;
+        return getMeasuredSize()
+                .getDependencyOuterHeight(spacingMeasureElement);
     }
 
     static int[] cloneArray(int[] toBeCloned) {
@@ -127,10 +115,11 @@ public class VGridLayout extends SimplePanel {
     void expandRows() {
         if (!isUndefinedHeight()) {
             int usedSpace = minRowHeights[0];
+            int verticalSpacing = getVerticalSpacing();
             for (int i = 1; i < minRowHeights.length; i++) {
-                usedSpace += spacingPixelsVertical + minRowHeights[i];
+                usedSpace += verticalSpacing + minRowHeights[i];
             }
-            int availableSpace = getOffsetHeight() - marginTopAndBottom;
+            int availableSpace = getMeasuredSize().getInnerHeight();
             int excessSpace = availableSpace - usedSpace;
             int distributed = 0;
             if (excessSpace > 0) {
@@ -150,125 +139,36 @@ public class VGridLayout extends SimplePanel {
         }
     }
 
-    void updateHeight(int height, boolean undefinedHeight) {
-        if (height != this.height || this.undefinedHeight != undefinedHeight) {
-            this.undefinedHeight = undefinedHeight;
-            this.height = height;
-            if (rendering) {
-                sizeChangedDuringRendering = true;
-            } else {
-                expandRows();
-                layoutCells();
-                for (Widget w : widgetToCell.keySet()) {
-                    client.handleComponentRelativeSize(w);
-                }
-            }
-        }
+    void updateHeight() {
+        // Detect minimum heights & calculate spans
+        detectRowHeights();
+
+        // Expand
+        expandRows();
+
+        // Position
+        layoutCellsVertically();
     }
 
-    void updateWidth(int width, boolean undefinedWidth) {
-        if (width != this.width || undefinedWidth != this.undefinedWidth) {
-            this.undefinedWidth = undefinedWidth;
-            this.width = width;
-            if (rendering) {
-                sizeChangedDuringRendering = true;
-            } else {
-                int[] oldWidths = cloneArray(columnWidths);
-                expandColumns();
-                boolean heightChanged = false;
-                HashSet<Integer> dirtyRows = null;
-                for (int i = 0; i < oldWidths.length; i++) {
-                    if (columnWidths[i] != oldWidths[i]) {
-                        Cell[] column = cells[i];
-                        for (int j = 0; j < column.length; j++) {
-                            Cell c = column[j];
-                            if (c != null && c.cc != null
-                                    && c.widthCanAffectHeight()) {
-                                c.cc.setContainerSize(c.getAvailableWidth(),
-                                        c.getAvailableHeight());
-                                client.handleComponentRelativeSize(c.cc
-                                        .getWidget());
-                                c.cc.updateWidgetSize();
-                                int newHeight = c.getHeight();
-                                if (columnWidths[i] < oldWidths[i]
-                                        && newHeight > minRowHeights[j]
-                                        && c.rowspan == 1) {
-                                    /*
-                                     * The width of this column was reduced and
-                                     * this affected the height. The height is
-                                     * now greater than the previously
-                                     * calculated minHeight for the row.
-                                     */
-                                    minRowHeights[j] = newHeight;
-                                    if (newHeight > rowHeights[j]) {
-                                        /*
-                                         * The new height is greater than the
-                                         * previously calculated rowHeight -> we
-                                         * need to recalculate heights later on
-                                         */
-                                        rowHeights[j] = newHeight;
-                                        heightChanged = true;
-                                    }
-                                } else if (newHeight < minRowHeights[j]) {
-                                    /*
-                                     * The new height of the component is less
-                                     * than the previously calculated min row
-                                     * height. The min row height may be
-                                     * affected and must thus be recalculated
-                                     */
-                                    if (dirtyRows == null) {
-                                        dirtyRows = new HashSet<Integer>();
-                                    }
-                                    dirtyRows.add(j);
-                                }
-                            }
-                        }
-                    }
-                }
-                if (dirtyRows != null) {
-                    /* flag indicating that there is a potential row shrinking */
-                    boolean rowMayShrink = false;
-                    for (Integer rowIndex : dirtyRows) {
-                        int oldMinimum = minRowHeights[rowIndex];
-                        int newMinimum = 0;
-                        for (int colIndex = 0; colIndex < columnWidths.length; colIndex++) {
-                            Cell cell = cells[colIndex][rowIndex];
-                            if (cell != null && !cell.hasRelativeHeight()
-                                    && cell.getHeight() > newMinimum) {
-                                newMinimum = cell.getHeight();
-                            }
-                        }
-                        if (newMinimum < oldMinimum) {
-                            minRowHeights[rowIndex] = rowHeights[rowIndex] = newMinimum;
-                            rowMayShrink = true;
-                        }
-                    }
-                    if (rowMayShrink) {
-                        distributeRowSpanHeights();
-                        minRowHeights = cloneArray(rowHeights);
-                        heightChanged = true;
-                    }
+    void updateWidth() {
+        // Detect widths & calculate spans
+        detectColWidths();
+        // Expand
+        expandColumns();
+        // Position
+        layoutCellsHorizontally();
 
-                }
-                layoutCells();
-                for (Widget w : widgetToCell.keySet()) {
-                    client.handleComponentRelativeSize(w);
-                }
-                if (heightChanged && isUndefinedHeight()) {
-                    Util.notifyParentOfSizeChange(this, false);
-                }
-            }
-        }
     }
 
     void expandColumns() {
         if (!isUndefinedWidth()) {
             int usedSpace = minColumnWidths[0];
+            int horizontalSpacing = getHorizontalSpacing();
             for (int i = 1; i < minColumnWidths.length; i++) {
-                usedSpace += spacingPixelsHorizontal + minColumnWidths[i];
+                usedSpace += horizontalSpacing + minColumnWidths[i];
             }
-            canvas.setWidth("");
-            int availableSpace = canvas.getOffsetWidth();
+
+            int availableSpace = getMeasuredSize().getInnerWidth();
             int excessSpace = availableSpace - usedSpace;
             int distributed = 0;
             if (excessSpace > 0) {
@@ -288,70 +188,58 @@ public class VGridLayout extends SimplePanel {
         }
     }
 
-    void layoutCells() {
-        int x = 0;
+    void layoutCellsVertically() {
+        int verticalSpacing = getVerticalSpacing();
         int y = 0;
         for (int i = 0; i < cells.length; i++) {
             y = 0;
             for (int j = 0; j < cells[i].length; j++) {
                 Cell cell = cells[i][j];
                 if (cell != null) {
-                    cell.layout(x, y);
+                    cell.layoutVertically(y);
                 }
-                y += rowHeights[j] + spacingPixelsVertical;
+                y += rowHeights[j] + verticalSpacing;
             }
-            x += columnWidths[i] + spacingPixelsHorizontal;
         }
 
-        if (isUndefinedWidth()) {
-            canvas.setWidth((x - spacingPixelsHorizontal) + "px");
-        } else {
-            // main element defines width
-            canvas.setWidth("");
+        if (isUndefinedHeight()) {
+            int innerHeight = y - verticalSpacing;
+            getElement().getStyle().setHeight(innerHeight, Unit.PX);
         }
+    }
 
-        int canvasHeight;
-        if (isUndefinedHeight()) {
-            canvasHeight = y - spacingPixelsVertical;
-        } else {
-            canvasHeight = getOffsetHeight() - marginTopAndBottom;
-            if (canvasHeight < 0) {
-                canvasHeight = 0;
+    void layoutCellsHorizontally() {
+        int x = 0;
+        int horizontalSpacing = getHorizontalSpacing();
+        for (int i = 0; i < cells.length; i++) {
+            for (int j = 0; j < cells[i].length; j++) {
+                Cell cell = cells[i][j];
+                if (cell != null) {
+                    cell.layoutHorizontally(x);
+                }
             }
+            x += columnWidths[i] + horizontalSpacing;
+        }
+
+        if (isUndefinedWidth()) {
+            getElement().getStyle().setWidth((x - horizontalSpacing), Unit.PX);
         }
-        canvas.setHeight(canvasHeight + "px");
     }
 
     private boolean isUndefinedHeight() {
-        return undefinedHeight;
+        return getPaintable().isUndefinedHeight();
     }
 
     private boolean isUndefinedWidth() {
-        return undefinedWidth;
-    }
-
-    void renderRemainingComponents(LinkedList<Cell> pendingCells) {
-        for (Cell cell : pendingCells) {
-            cell.render();
-        }
+        return getPaintable().isUndefinedWidth();
     }
 
-    void detectRowHeights() {
-
+    private void detectRowHeights() {
         // collect min rowheight from non-rowspanned cells
         for (int i = 0; i < cells.length; i++) {
             for (int j = 0; j < cells[i].length; j++) {
                 Cell cell = cells[i][j];
                 if (cell != null) {
-                    /*
-                     * Setting fixing container width may in some situations
-                     * affect height. Example: Label with wrapping text without
-                     * or with relative width.
-                     */
-                    if (cell.cc != null && cell.widthCanAffectHeight()) {
-                        cell.cc.setWidth(cell.getAvailableWidth() + "px");
-                        cell.cc.updateWidgetSize();
-                    }
                     if (cell.rowspan == 1) {
                         if (!cell.hasRelativeHeight()
                                 && rowHeights[j] < cell.getHeight()) {
@@ -369,6 +257,29 @@ public class VGridLayout extends SimplePanel {
         minRowHeights = cloneArray(rowHeights);
     }
 
+    private void detectColWidths() {
+        // collect min colwidths from non-colspanned cells
+        for (int i = 0; i < cells.length; i++) {
+            for (int j = 0; j < cells[i].length; j++) {
+                Cell cell = cells[i][j];
+                if (cell != null) {
+                    if (cell.colspan == 1) {
+                        if (!cell.hasRelativeWidth()
+                                && columnWidths[i] < cell.getWidth()) {
+                            columnWidths[i] = cell.getWidth();
+                        }
+                    } else {
+                        storeColSpannedCell(cell);
+                    }
+                }
+            }
+        }
+
+        distributeColSpanWidths();
+
+        minColumnWidths = cloneArray(columnWidths);
+    }
+
     private void storeRowSpannedCell(Cell cell) {
         SpanList l = null;
         for (SpanList list : rowSpans) {
@@ -391,20 +302,6 @@ public class VGridLayout extends SimplePanel {
         l.cells.add(cell);
     }
 
-    void renderRemainingComponentsWithNoRelativeHeight(
-            LinkedList<Cell> pendingCells) {
-
-        for (Iterator<Cell> iterator = pendingCells.iterator(); iterator
-                .hasNext();) {
-            Cell cell = iterator.next();
-            if (!cell.hasRelativeHeight()) {
-                cell.render();
-                iterator.remove();
-            }
-        }
-
-    }
-
     /**
      * Iterates colspanned cells, ensures cols have enough space to accommodate
      * them
@@ -416,7 +313,7 @@ public class VGridLayout extends SimplePanel {
                 // subsequent renders
                 int width = cell.hasRelativeWidth() ? 0 : cell.getWidth();
                 distributeSpanSize(columnWidths, cell.col, cell.colspan,
-                        spacingPixelsHorizontal, width, colExpandRatioArray);
+                        getHorizontalSpacing(), width, colExpandRatioArray);
             }
         }
     }
@@ -432,7 +329,7 @@ public class VGridLayout extends SimplePanel {
                 // subsequent renders
                 int height = cell.hasRelativeHeight() ? 0 : cell.getHeight();
                 distributeSpanSize(rowHeights, cell.row, cell.rowspan,
-                        spacingPixelsVertical, height, rowExpandRatioArray);
+                        getVerticalSpacing(), height, rowExpandRatioArray);
             }
         }
     }
@@ -492,8 +389,6 @@ public class VGridLayout extends SimplePanel {
     private LinkedList<SpanList> colSpans = new LinkedList<SpanList>();
     private LinkedList<SpanList> rowSpans = new LinkedList<SpanList>();
 
-    private int marginTopAndBottom;
-
     private class SpanList {
         final int span;
         List<Cell> cells = new LinkedList<Cell>();
@@ -526,226 +421,28 @@ public class VGridLayout extends SimplePanel {
         l.cells.add(cell);
     }
 
-    void detectSpacing(UIDL uidl) {
-        DivElement spacingmeter = Document.get().createDivElement();
-        spacingmeter.setClassName(CLASSNAME + "-" + "spacing-"
-                + (uidl.getBooleanAttribute("spacing") ? "on" : "off"));
-        spacingmeter.getStyle().setProperty("width", "0");
-        spacingmeter.getStyle().setProperty("height", "0");
-        canvas.getElement().appendChild(spacingmeter);
-        spacingPixelsHorizontal = spacingmeter.getOffsetWidth();
-        spacingPixelsVertical = spacingmeter.getOffsetHeight();
-        canvas.getElement().removeChild(spacingmeter);
-    }
-
-    void handleMargins(UIDL uidl) {
-        final VMarginInfo margins = new VMarginInfo(
-                uidl.getIntAttribute("margins"));
-
-        String styles = CLASSNAME + "-margin";
-        if (margins.hasTop()) {
-            styles += " " + CLASSNAME + "-" + StyleConstants.MARGIN_TOP;
-        }
-        if (margins.hasRight()) {
-            styles += " " + CLASSNAME + "-" + StyleConstants.MARGIN_RIGHT;
-        }
-        if (margins.hasBottom()) {
-            styles += " " + CLASSNAME + "-" + StyleConstants.MARGIN_BOTTOM;
-        }
-        if (margins.hasLeft()) {
-            styles += " " + CLASSNAME + "-" + StyleConstants.MARGIN_LEFT;
-        }
-        margin.setClassName(styles);
-
-        marginTopAndBottom = margin.getOffsetHeight()
-                - canvas.getOffsetHeight();
-    }
-
-    public boolean requestLayout(final Set<Widget> changedChildren) {
-        boolean needsLayout = false;
-        boolean reDistributeColSpanWidths = false;
-        boolean reDistributeRowSpanHeights = false;
-        int offsetHeight = canvas.getOffsetHeight();
-        int offsetWidth = canvas.getOffsetWidth();
-        if (isUndefinedWidth() || isUndefinedHeight()) {
-            needsLayout = true;
-        }
-        ArrayList<Integer> dirtyColumns = new ArrayList<Integer>();
-        ArrayList<Integer> dirtyRows = new ArrayList<Integer>();
-        for (Widget widget : changedChildren) {
-
-            Cell cell = widgetToCell.get(widget);
-            if (!cell.hasRelativeHeight() || !cell.hasRelativeWidth()) {
-                // cell sizes will only stay still if only relatively
-                // sized components
-                // check if changed child affects min col widths
-                assert cell.cc != null;
-                cell.cc.setWidth("");
-                cell.cc.setHeight("");
-
-                cell.cc.updateWidgetSize();
-
-                /*
-                 * If this is the result of an caption icon onload event the
-                 * caption size may have changed
-                 */
-                cell.cc.updateCaptionSize();
-
-                int width = cell.getWidth();
-                int allocated = columnWidths[cell.col];
-                for (int i = 1; i < cell.colspan; i++) {
-                    allocated += spacingPixelsHorizontal
-                            + columnWidths[cell.col + i];
-                }
-                if (allocated < width) {
-                    needsLayout = true;
-                    if (cell.colspan == 1) {
-                        // do simple column width expansion
-                        columnWidths[cell.col] = minColumnWidths[cell.col] = width;
-                    } else {
-                        // mark that col span expansion is needed
-                        reDistributeColSpanWidths = true;
-                    }
-                } else if (allocated != width) {
-                    // size is smaller thant allocated, column might
-                    // shrink
-                    dirtyColumns.add(cell.col);
-                }
-
-                int height = cell.getHeight();
-
-                allocated = rowHeights[cell.row];
-                for (int i = 1; i < cell.rowspan; i++) {
-                    allocated += spacingPixelsVertical
-                            + rowHeights[cell.row + i];
-                }
-                if (allocated < height) {
-                    needsLayout = true;
-                    if (cell.rowspan == 1) {
-                        // do simple row expansion
-                        rowHeights[cell.row] = minRowHeights[cell.row] = height;
-                    } else {
-                        // mark that row span expansion is needed
-                        reDistributeRowSpanHeights = true;
-                    }
-                } else if (allocated != height) {
-                    // size is smaller than allocated, row might shrink
-                    dirtyRows.add(cell.row);
-                }
-            }
-        }
-
-        if (dirtyColumns.size() > 0) {
-            for (Integer colIndex : dirtyColumns) {
-                int colW = 0;
-                for (int i = 0; i < rowHeights.length; i++) {
-                    Cell cell = cells[colIndex][i];
-                    if (cell != null && cell.getChildUIDL() != null
-                            && !cell.hasRelativeWidth() && cell.colspan == 1) {
-                        int width = cell.getWidth();
-                        if (width > colW) {
-                            colW = width;
-                        }
-                    }
-                }
-                minColumnWidths[colIndex] = colW;
-            }
-            needsLayout = true;
-            // ensure colspanned columns have enough space
-            columnWidths = cloneArray(minColumnWidths);
-            distributeColSpanWidths();
-            reDistributeColSpanWidths = false;
-        }
-
-        if (reDistributeColSpanWidths) {
-            distributeColSpanWidths();
-        }
-
-        if (dirtyRows.size() > 0) {
-            needsLayout = true;
-            for (Integer rowIndex : dirtyRows) {
-                // recalculate min row height
-                int rowH = minRowHeights[rowIndex] = 0;
-                // loop all columns on row rowIndex
-                for (int i = 0; i < columnWidths.length; i++) {
-                    Cell cell = cells[i][rowIndex];
-                    if (cell != null && cell.getChildUIDL() != null
-                            && !cell.hasRelativeHeight() && cell.rowspan == 1) {
-                        int h = cell.getHeight();
-                        if (h > rowH) {
-                            rowH = h;
-                        }
-                    }
-                }
-                minRowHeights[rowIndex] = rowH;
-            }
-            // TODO could check only some row spans
-            rowHeights = cloneArray(minRowHeights);
-            distributeRowSpanHeights();
-            reDistributeRowSpanHeights = false;
-        }
-
-        if (reDistributeRowSpanHeights) {
-            distributeRowSpanHeights();
-        }
-
-        if (needsLayout) {
-            expandColumns();
-            expandRows();
-            layoutCells();
-            // loop all relative sized components and update their size
-            for (int i = 0; i < cells.length; i++) {
-                for (int j = 0; j < cells[i].length; j++) {
-                    Cell cell = cells[i][j];
-                    if (cell != null
-                            && cell.cc != null
-                            && (cell.hasRelativeHeight() || cell
-                                    .hasRelativeWidth())) {
-                        client.handleComponentRelativeSize(cell.cc.getWidget());
-                    }
-                }
-            }
-        }
-        if (canvas.getOffsetHeight() != offsetHeight
-                || canvas.getOffsetWidth() != offsetWidth) {
-            return false;
-        } else {
-            return true;
-        }
-    }
-
     Cell[][] cells;
 
     /**
      * Private helper class.
      */
     class Cell {
-        private boolean relHeight = false;
-        private boolean relWidth = false;
-        private boolean widthCanAffectHeight = false;
-
         public Cell(UIDL c) {
             row = c.getIntAttribute("y");
             col = c.getIntAttribute("x");
-            setUidl(c);
+            updateFromUidl(c);
         }
 
-        public boolean widthCanAffectHeight() {
-            return widthCanAffectHeight;
+        public boolean hasContent() {
+            return hasContent;
         }
 
         public boolean hasRelativeHeight() {
-            return relHeight;
-        }
-
-        public RenderSpace getAllocatedSpace() {
-            return new RenderSpace(getAvailableWidth()
-                    - cc.getCaptionWidthAfterComponent(), getAvailableHeight()
-                    - cc.getCaptionHeightAboveComponent());
-        }
-
-        public boolean hasContent() {
-            return childUidl != null;
+            if (slot != null) {
+                return slot.getPaintable().isRelativeHeight();
+            } else {
+                return true;
+            }
         }
 
         /**
@@ -754,7 +451,7 @@ public class VGridLayout extends SimplePanel {
         private int getAvailableWidth() {
             int width = columnWidths[col];
             for (int i = 1; i < colspan; i++) {
-                width += spacingPixelsHorizontal + columnWidths[col + i];
+                width += getHorizontalSpacing() + columnWidths[col + i];
             }
             return width;
         }
@@ -765,110 +462,65 @@ public class VGridLayout extends SimplePanel {
         private int getAvailableHeight() {
             int height = rowHeights[row];
             for (int i = 1; i < rowspan; i++) {
-                height += spacingPixelsVertical + rowHeights[row + i];
+                height += getVerticalSpacing() + rowHeights[row + i];
             }
             return height;
         }
 
-        public void layout(int x, int y) {
-            if (cc != null && cc.isAttached()) {
-                canvas.setWidgetPosition(cc, x, y);
-                cc.setContainerSize(getAvailableWidth(), getAvailableHeight());
-                cc.setAlignment(new AlignmentInfo(alignment));
-                cc.updateAlignments(getAvailableWidth(), getAvailableHeight());
+        public void layoutHorizontally(int x) {
+            if (slot != null) {
+                slot.positionHorizontally(x, getAvailableWidth());
             }
         }
 
-        public int getWidth() {
-            if (cc != null) {
-                int w = cc.getWidgetSize().getWidth()
-                        + cc.getCaptionWidthAfterComponent();
-                return w;
-            } else {
-                return 0;
+        public void layoutVertically(int y) {
+            if (slot != null) {
+                slot.positionVertically(y, getAvailableHeight());
             }
         }
 
-        public int getHeight() {
-            if (cc != null) {
-                return cc.getWidgetSize().getHeight()
-                        + cc.getCaptionHeightAboveComponent();
+        public int getWidth() {
+            if (slot != null) {
+                return slot.getUsedWidth();
             } else {
                 return 0;
             }
         }
 
-        public boolean renderIfNoRelativeWidth() {
-            if (childUidl == null) {
-                return false;
-            }
-            if (!hasRelativeWidth()) {
-                render();
-                return true;
+        public int getHeight() {
+            if (slot != null) {
+                return slot.getUsedHeight();
             } else {
-                return false;
+                return 0;
             }
         }
 
         protected boolean hasRelativeWidth() {
-            return relWidth;
-        }
-
-        protected void render() {
-            assert childUidl != null;
-
-            VPaintableWidget paintable = client.getPaintable(childUidl);
-            Widget w = paintable.getWidgetForPaintable();
-            assert paintable != null;
-            if (cc == null || cc.getWidget() != w) {
-                if (widgetToComponentContainer.containsKey(w)) {
-                    // Component moving from one place to another
-                    cc = widgetToComponentContainer.get(w);
-                    cc.setWidth("");
-                    cc.setHeight("");
-                    /*
-                     * Widget might not be set if moving from another component
-                     * and this layout has been hidden when moving out, see
-                     * #5372
-                     */
-                    cc.setPaintable(paintable);
-                } else {
-                    // A new component
-                    cc = new ChildComponentContainer(paintable,
-                            ChildComponentContainer.ORIENTATION_VERTICAL);
-                    widgetToComponentContainer.put(w, cc);
-                    cc.setWidth("");
-                    canvas.add(cc, 0, 0);
-                }
-                widgetToCell.put(w, this);
-            }
-            cc.renderChild(childUidl, client, -1);
-            if (sizeChangedDuringRendering && Util.isCached(childUidl)) {
-                client.handleComponentRelativeSize(cc.getWidget());
+            if (slot != null) {
+                return slot.getPaintable().isRelativeWidth();
+            } else {
+                return true;
             }
-            cc.updateWidgetSize();
-            nonRenderedWidgets.remove(w);
-        }
-
-        public UIDL getChildUIDL() {
-            return childUidl;
         }
 
         final int row;
         final int col;
         int colspan = 1;
         int rowspan = 1;
-        UIDL childUidl;
-        int alignment;
-        // may be null after setUidl() if content has vanished or changed, set
-        // in render()
-        ChildComponentContainer cc;
 
-        public void setUidl(UIDL c) {
+        private boolean hasContent;
+
+        private AlignmentInfo alignment;
+
+        VPaintableLayoutSlot slot;
+
+        public void updateFromUidl(UIDL cellUidl) {
             // Set cell width
-            colspan = c.hasAttribute("w") ? c.getIntAttribute("w") : 1;
+            colspan = cellUidl.hasAttribute("w") ? cellUidl
+                    .getIntAttribute("w") : 1;
             // Set cell height
-            rowspan = c.hasAttribute("h") ? c.getIntAttribute("h") : 1;
+            rowspan = cellUidl.hasAttribute("h") ? cellUidl
+                    .getIntAttribute("h") : 1;
             // ensure we will lose reference to old cells, now overlapped by
             // this cell
             for (int i = 0; i < colspan; i++) {
@@ -879,52 +531,32 @@ public class VGridLayout extends SimplePanel {
                 }
             }
 
-            c = c.getChildUIDL(0); // we are interested about childUidl
-            if (childUidl != null) {
-                if (c == null) {
-                    // content has vanished, old content will be removed from
-                    // canvas later during the render phase
-                    cc = null;
-                } else if (cc != null
-                        && cc.getWidget() != client.getPaintable(c)
-                                .getWidgetForPaintable()) {
-                    // content has changed
-                    cc = null;
-                    VPaintableWidget paintable = client.getPaintable(c);
-                    Widget w = paintable.getWidgetForPaintable();
-                    if (widgetToComponentContainer.containsKey(w)) {
-                        // cc exist for this component (moved) use that for this
-                        // cell
-                        cc = widgetToComponentContainer.get(w);
-                        cc.setWidth("");
-                        cc.setHeight("");
-                        widgetToCell.put(w, this);
+            UIDL childUidl = cellUidl.getChildUIDL(0); // we are interested
+                                                       // about childUidl
+            hasContent = childUidl != null;
+            if (hasContent) {
+                VPaintableWidget paintable = client.getPaintable(childUidl);
+
+                if (slot == null || slot.getPaintable() != paintable) {
+                    slot = new VPaintableLayoutSlot(CLASSNAME, paintable);
+                    Element slotWrapper = slot.getWrapperElement();
+                    getElement().appendChild(slotWrapper);
+
+                    Widget widget = paintable.getWidgetForPaintable();
+                    insert(widget, slotWrapper, getWidgetCount(), false);
+                    Cell oldCell = widgetToCell.put(widget, this);
+                    if (oldCell != null) {
+                        oldCell.slot.getWrapperElement().removeFromParent();
+                        oldCell.slot = null;
                     }
                 }
+
+                paintable.updateFromUIDL(childUidl, client);
             }
-            childUidl = c;
-            updateRelSizeStatus(c);
         }
 
-        protected void updateRelSizeStatus(UIDL uidl) {
-            if (uidl != null && !uidl.getBooleanAttribute("cached")) {
-                if (uidl.hasAttribute("height")
-                        && uidl.getStringAttribute("height").contains("%")) {
-                    relHeight = true;
-                } else {
-                    relHeight = false;
-                }
-                if (uidl.hasAttribute("width")) {
-                    widthCanAffectHeight = relWidth = uidl.getStringAttribute(
-                            "width").contains("%");
-                    if (uidl.hasAttribute("height")) {
-                        widthCanAffectHeight = false;
-                    }
-                } else {
-                    widthCanAffectHeight = !uidl.hasAttribute("height");
-                    relWidth = false;
-                }
-            }
+        public void setAlignment(AlignmentInfo alignmentInfo) {
+            slot.setAlignment(alignmentInfo);
         }
     }
 
@@ -936,7 +568,7 @@ public class VGridLayout extends SimplePanel {
             cell = new Cell(c);
             cells[col][row] = cell;
         } else {
-            cell.setUidl(c);
+            cell.updateFromUidl(c);
         }
         return cell;
     }
@@ -955,4 +587,47 @@ public class VGridLayout extends SimplePanel {
         return Util.getPaintableForElement(client, this, element);
     }
 
+    void setCaption(Widget widget, VCaption caption) {
+        VLayoutSlot slot = widgetToCell.get(widget).slot;
+
+        if (caption != null) {
+            // Logical attach.
+            getChildren().add(caption);
+        }
+
+        // Physical attach if not null, also removes old caption
+        slot.setCaption(caption);
+
+        if (caption != null) {
+            // Adopt.
+            adopt(caption);
+        }
+    }
+
+    private void togglePrefixedStyleName(String name, boolean enabled) {
+        if (enabled) {
+            addStyleDependentName(name);
+        } else {
+            removeStyleDependentName(name);
+        }
+    }
+
+    void updateMarginStyleNames(VMarginInfo marginInfo) {
+        togglePrefixedStyleName("margin-top", marginInfo.hasTop());
+        togglePrefixedStyleName("margin-right", marginInfo.hasRight());
+        togglePrefixedStyleName("margin-bottom", marginInfo.hasBottom());
+        togglePrefixedStyleName("margin-left", marginInfo.hasLeft());
+    }
+
+    void updateSpacingStyleName(boolean spacingEnabled) {
+        String styleName = getStylePrimaryName();
+        if (spacingEnabled) {
+            spacingMeasureElement.addClassName(styleName + "-spacing-on");
+            spacingMeasureElement.removeClassName(styleName + "-spacing-off");
+        } else {
+            spacingMeasureElement.removeClassName(styleName + "-spacing-on");
+            spacingMeasureElement.addClassName(styleName + "-spacing-off");
+        }
+    }
+
 }
index 909612933b66d889f841aa0c702317cdfe2bb88c..beb72d45b4efd4f097022c6f07706536223f26f4 100644 (file)
@@ -3,11 +3,8 @@
  */
 package com.vaadin.terminal.gwt.client.ui;
 
-import java.util.Collection;
-import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
-import java.util.LinkedList;
 
 import com.google.gwt.core.client.GWT;
 import com.google.gwt.event.dom.client.DomEvent.Type;
@@ -19,10 +16,11 @@ import com.vaadin.terminal.gwt.client.ApplicationConnection;
 import com.vaadin.terminal.gwt.client.CalculatingLayout;
 import com.vaadin.terminal.gwt.client.EventId;
 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.ui.VGridLayout.Cell;
-import com.vaadin.terminal.gwt.client.ui.layout.ChildComponentContainer;
+import com.vaadin.terminal.gwt.client.ui.layout.VLayoutSlot;
 
 public class VGridLayoutPaintable extends VAbstractPaintableWidgetContainer
         implements CalculatingLayout {
@@ -41,53 +39,48 @@ public class VGridLayoutPaintable extends VAbstractPaintableWidgetContainer
         }
     };
 
+    public VGridLayoutPaintable() {
+        getMeasuredSize().registerDependency(
+                getWidgetForPaintable().spacingMeasureElement);
+    }
+
     @Override
     public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
-        getWidgetForPaintable().rendering = true;
-        getWidgetForPaintable().client = client;
+        VGridLayout layout = getWidgetForPaintable();
+        layout.client = client;
 
         super.updateFromUIDL(uidl, client);
         if (!isRealUpdate(uidl)) {
-            getWidgetForPaintable().rendering = false;
             return;
         }
         clickEventHandler.handleEventHandlerRegistration(client);
 
-        getWidgetForPaintable().canvas.setWidth("0px");
-
-        getWidgetForPaintable().handleMargins(uidl);
-        getWidgetForPaintable().detectSpacing(uidl);
-
         int cols = uidl.getIntAttribute("w");
         int rows = uidl.getIntAttribute("h");
 
-        getWidgetForPaintable().columnWidths = new int[cols];
-        getWidgetForPaintable().rowHeights = new int[rows];
+        layout.columnWidths = new int[cols];
+        layout.rowHeights = new int[rows];
 
-        if (getWidgetForPaintable().cells == null) {
-            getWidgetForPaintable().cells = new Cell[cols][rows];
-        } else if (getWidgetForPaintable().cells.length != cols
-                || getWidgetForPaintable().cells[0].length != rows) {
+        if (layout.cells == null) {
+            layout.cells = new Cell[cols][rows];
+        } else if (layout.cells.length != cols
+                || layout.cells[0].length != rows) {
             Cell[][] newCells = new Cell[cols][rows];
-            for (int i = 0; i < getWidgetForPaintable().cells.length; i++) {
-                for (int j = 0; j < getWidgetForPaintable().cells[i].length; j++) {
+            for (int i = 0; i < layout.cells.length; i++) {
+                for (int j = 0; j < layout.cells[i].length; j++) {
                     if (i < cols && j < rows) {
-                        newCells[i][j] = getWidgetForPaintable().cells[i][j];
+                        newCells[i][j] = layout.cells[i][j];
                     }
                 }
             }
-            getWidgetForPaintable().cells = newCells;
+            layout.cells = newCells;
         }
 
-        getWidgetForPaintable().nonRenderedWidgets = (HashMap<Widget, ChildComponentContainer>) getWidgetForPaintable().widgetToComponentContainer
-                .clone();
-
         final int[] alignments = uidl.getIntArrayAttribute("alignments");
         int alignmentIndex = 0;
 
-        LinkedList<Cell> pendingCells = new LinkedList<Cell>();
-
-        LinkedList<Cell> relativeHeighted = new LinkedList<Cell>();
+        HashSet<Widget> nonRenderedWidgets = new HashSet<Widget>(
+                layout.widgetToCell.keySet());
 
         for (final Iterator<?> i = uidl.getChildIterator(); i.hasNext();) {
             final UIDL r = (UIDL) i.next();
@@ -95,96 +88,59 @@ public class VGridLayoutPaintable extends VAbstractPaintableWidgetContainer
                 for (final Iterator<?> j = r.getChildIterator(); j.hasNext();) {
                     final UIDL c = (UIDL) j.next();
                     if ("gc".equals(c.getTag())) {
-                        Cell cell = getWidgetForPaintable().getCell(c);
+                        Cell cell = layout.getCell(c);
                         if (cell.hasContent()) {
-                            boolean rendered = cell.renderIfNoRelativeWidth();
-                            cell.alignment = alignments[alignmentIndex++];
-                            if (!rendered) {
-                                pendingCells.add(cell);
-                            }
-
-                            if (cell.colspan > 1) {
-                                getWidgetForPaintable().storeColSpannedCell(
-                                        cell);
-                            } else if (rendered) {
-                                // strore non-colspanned widths to columnWidth
-                                // array
-                                if (getWidgetForPaintable().columnWidths[cell.col] < cell
-                                        .getWidth()) {
-                                    getWidgetForPaintable().columnWidths[cell.col] = cell
-                                            .getWidth();
-                                }
-                            }
-                            if (cell.hasRelativeHeight()) {
-                                relativeHeighted.add(cell);
-                            }
+                            cell.setAlignment(new AlignmentInfo(
+                                    alignments[alignmentIndex++]));
+                            nonRenderedWidgets.remove(cell.slot.getWidget());
                         }
                     }
                 }
             }
         }
 
-        getWidgetForPaintable().colExpandRatioArray = uidl
-                .getIntArrayAttribute("colExpand");
-        getWidgetForPaintable().rowExpandRatioArray = uidl
-                .getIntArrayAttribute("rowExpand");
-        getWidgetForPaintable().distributeColSpanWidths();
-
-        getWidgetForPaintable().minColumnWidths = VGridLayout
-                .cloneArray(getWidgetForPaintable().columnWidths);
-        getWidgetForPaintable().expandColumns();
-
-        getWidgetForPaintable().renderRemainingComponentsWithNoRelativeHeight(
-                pendingCells);
-
-        getWidgetForPaintable().detectRowHeights();
-
-        getWidgetForPaintable().expandRows();
-
-        getWidgetForPaintable().renderRemainingComponents(pendingCells);
-
-        for (Cell cell : relativeHeighted) {
-            // rendering done above so cell.cc should not be null
-            Widget widget2 = cell.cc.getWidget();
-            client.handleComponentRelativeSize(widget2);
-            cell.cc.updateWidgetSize();
-        }
-
-        getWidgetForPaintable().layoutCells();
+        layout.colExpandRatioArray = uidl.getIntArrayAttribute("colExpand");
+        layout.rowExpandRatioArray = uidl.getIntArrayAttribute("rowExpand");
 
         // clean non rendered components
-        for (Widget w : getWidgetForPaintable().nonRenderedWidgets.keySet()) {
-            ChildComponentContainer childComponentContainer = getWidgetForPaintable().widgetToComponentContainer
-                    .get(w);
-            getWidgetForPaintable().widgetToCell.remove(w);
-            getWidgetForPaintable().widgetToComponentContainer.remove(w);
-            childComponentContainer.removeFromParent();
-            VPaintableMap paintableMap = VPaintableMap.get(client);
-            paintableMap.unregisterPaintable(paintableMap.getPaintable(w));
+        for (Widget w : nonRenderedWidgets) {
+            Cell cell = layout.widgetToCell.remove(w);
+            cell.slot.setCaption(null);
+
+            if (w.getParent() == layout) {
+                w.removeFromParent();
+                VPaintableMap paintableMap = VPaintableMap.get(client);
+                paintableMap.unregisterPaintable(paintableMap.getPaintable(w));
+            }
+            cell.slot.getWrapperElement().removeFromParent();
         }
-        getWidgetForPaintable().nonRenderedWidgets = null;
 
-        getWidgetForPaintable().rendering = false;
-        getWidgetForPaintable().sizeChangedDuringRendering = false;
+        int bitMask = uidl.getIntAttribute("margins");
+        layout.updateMarginStyleNames(new VMarginInfo(bitMask));
 
+        layout.updateSpacingStyleName(uidl.getBooleanAttribute("spacing"));
+
+        getMeasuredSize().setHeightNeedsUpdate();
+        getMeasuredSize().setWidthNeedsUpdate();
     }
 
-    public void updateCaption(VPaintableWidget paintable, UIDL uidl) {
-        Widget widget = paintable.getWidgetForPaintable();
-        ChildComponentContainer cc = getWidgetForPaintable().widgetToComponentContainer
-                .get(widget);
-        if (cc != null) {
-            cc.updateCaption(uidl, getConnection(), getMeasuredSize());
-        }
-        if (!getWidgetForPaintable().rendering) {
-            // ensure rel size details are updated
-            getWidgetForPaintable().widgetToCell.get(widget)
-                    .updateRelSizeStatus(uidl);
-            /*
-             * This was a component-only update and the possible size change
-             * must be propagated to the layout
-             */
-            getConnection().captionSizeUpdated(widget);
+    public void updateCaption(VPaintableWidget component, UIDL uidl) {
+        VGridLayout layout = getWidgetForPaintable();
+        if (VCaption.isNeeded(uidl)) {
+            Cell cell = layout.widgetToCell.get(component
+                    .getWidgetForPaintable());
+            VLayoutSlot layoutSlot = cell.slot;
+            VCaption caption = layoutSlot.getCaption();
+            if (caption == null) {
+                caption = new VCaption(component, getConnection());
+
+                Widget widget = component.getWidgetForPaintable();
+
+                layout.setCaption(widget, caption);
+            }
+            caption.updateCaption(uidl);
+        } else {
+            layout.setCaption(component.getWidgetForPaintable(), null);
         }
     }
 
@@ -199,24 +155,10 @@ public class VGridLayoutPaintable extends VAbstractPaintableWidgetContainer
     }
 
     public void updateVerticalSizes() {
-        int innerHeight = getMeasuredSize().getInnerHeight();
-        getWidgetForPaintable().updateHeight(innerHeight, isUndefinedHeight());
-        layoutAllChildren();
-    }
-
-    private void layoutAllChildren() {
-        HashSet<Widget> childWidgets = new HashSet<Widget>();
-        Collection<VPaintableWidget> children = getChildren();
-        for (VPaintableWidget vPaintableWidget : children) {
-            childWidgets.add(vPaintableWidget.getWidgetForPaintable());
-        }
-        getWidgetForPaintable().requestLayout(childWidgets);
+        getWidgetForPaintable().updateHeight();
     }
 
     public void updateHorizontalSizes() {
-        int innerWidth = getMeasuredSize().getInnerWidth();
-        getWidgetForPaintable().updateWidth(innerWidth, isUndefinedWidth());
-
-        layoutAllChildren();
+        getWidgetForPaintable().updateWidth();
     }
 }
diff --git a/src/com/vaadin/terminal/gwt/client/ui/layout/ChildComponentContainer.java b/src/com/vaadin/terminal/gwt/client/ui/layout/ChildComponentContainer.java
deleted file mode 100644 (file)
index 6972cfb..0000000
+++ /dev/null
@@ -1,757 +0,0 @@
-/*
-@VaadinApache2LicenseForJavaFiles@
- */
-package com.vaadin.terminal.gwt.client.ui.layout;
-
-import java.util.Iterator;
-import java.util.NoSuchElementException;
-
-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.Display;
-import com.google.gwt.user.client.ui.Panel;
-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.MeasuredSize;
-import com.vaadin.terminal.gwt.client.RenderInformation.FloatSize;
-import com.vaadin.terminal.gwt.client.RenderInformation.Size;
-import com.vaadin.terminal.gwt.client.UIDL;
-import com.vaadin.terminal.gwt.client.Util;
-import com.vaadin.terminal.gwt.client.VCaption;
-import com.vaadin.terminal.gwt.client.VConsole;
-import com.vaadin.terminal.gwt.client.VPaintableWidget;
-import com.vaadin.terminal.gwt.client.ui.AlignmentInfo;
-
-public class ChildComponentContainer extends Panel {
-
-    public static final int ORIENTATION_VERTICAL = 0;
-    public static final int ORIENTATION_HORIZONTAL = 1;
-
-    /**
-     * Size of the container DIV excluding any margins and also excluding the
-     * expansion amount (containerExpansion)
-     */
-    private Size contSize = new Size(0, 0);
-
-    /**
-     * Size of the widget inside the container DIV
-     */
-    private Size widgetSize = new Size(0, 0);
-    /**
-     * Size of the caption
-     */
-    private int captionRequiredWidth = 0;
-    private int captionWidth = 0;
-    private int captionHeight = 0;
-
-    /**
-     * 
-     * Padding added to the container when it is larger than the component.
-     */
-    private Size containerExpansion = new Size(0, 0);
-
-    private double expandRatio;
-
-    // private int containerMarginLeft = 0;
-    private int containerMarginTop = 0;
-
-    AlignmentInfo alignment = AlignmentInfo.TOP_LEFT;
-
-    private int alignmentLeftOffsetForWidget = 0;
-    private int alignmentLeftOffsetForCaption = 0;
-    /**
-     * Top offset for implementing alignment. Top offset is set to the container
-     * DIV as it otherwise would have to be set to either the Caption or the
-     * Widget depending on whether there is a caption and where the caption is
-     * located.
-     */
-    private int alignmentTopOffset = 0;
-
-    // private Margins alignmentOffset = new Margins(0, 0, 0, 0);
-    private VCaption caption = null;
-    private DivElement containerDIV;
-    private DivElement widgetDIV;
-    private VPaintableWidget paintable;
-    private Widget widget;
-    private FloatSize relativeSize = null;
-
-    public ChildComponentContainer(VPaintableWidget child, int orientation) {
-        super();
-
-        containerDIV = Document.get().createDivElement();
-
-        widgetDIV = Document.get().createDivElement();
-
-        setElement(containerDIV);
-        containerDIV.getStyle().setProperty("height", "0");
-        containerDIV.getStyle().setProperty("width", "0px");
-        containerDIV.getStyle().setProperty("overflow", "hidden");
-
-        if (BrowserInfo.get().isIE()) {
-            /*
-             * IE requires position: relative on overflow:hidden elements if
-             * they should hide position:relative elements. Without this e.g. a
-             * 1000x1000 Panel inside an 500x500 OrderedLayout will not be
-             * clipped but fully shown.
-             */
-            containerDIV.getStyle().setProperty("position", "relative");
-            widgetDIV.getStyle().setProperty("position", "relative");
-        }
-
-        containerDIV.appendChild(widgetDIV);
-
-        setOrientation(orientation);
-
-        setPaintable(child);
-    }
-
-    public void setPaintable(VPaintableWidget childPaintable) {
-        paintable = childPaintable;
-        setWidget(childPaintable.getWidgetForPaintable());
-    }
-
-    private void setWidget(Widget w) {
-        // Validate
-        if (w == widget) {
-            return;
-        }
-
-        // Detach new child.
-        if (w != null) {
-            w.removeFromParent();
-        }
-
-        // Remove old child.
-        if (widget != null) {
-            remove(widget);
-        }
-
-        // Logical attach.
-        widget = w;
-
-        if (w != null) {
-            // Physical attach.
-            widgetDIV.appendChild(widget.getElement());
-            adopt(w);
-            w.getElement().getStyle().setDisplay(Display.INLINE_BLOCK);
-        }
-    }
-
-    private static void setFloat(Element div, String floatString) {
-        if (BrowserInfo.get().isIE()) {
-            div.getStyle().setProperty("styleFloat", floatString);
-            // IE requires display:inline for margin-left to work together
-            // with float:left
-            if (floatString.equals("left")) {
-                div.getStyle().setProperty("display", "inline");
-            } else {
-                div.getStyle().setProperty("display", "block");
-            }
-
-        } else {
-            div.getStyle().setProperty("cssFloat", floatString);
-        }
-    }
-
-    public void setOrientation(int orientation) {
-        if (orientation == ORIENTATION_HORIZONTAL) {
-            setFloat(getElement(), "left");
-        } else {
-            setFloat(getElement(), "");
-        }
-        setHeight("0px");
-        // setWidth("0px");
-        contSize.setHeight(0);
-        contSize.setWidth(0);
-        // containerMarginLeft = 0;
-        containerMarginTop = 0;
-        containerDIV.getStyle().setProperty("paddingLeft", "0");
-        containerDIV.getStyle().setProperty("paddingTop", "0");
-
-        containerExpansion.setHeight(0);
-        containerExpansion.setWidth(0);
-
-        // Clear old alignments
-        clearAlignments();
-
-    }
-
-    public void renderChild(UIDL childUIDL, ApplicationConnection client,
-            int fixedWidth) {
-        /*
-         * Must remove width specification from container before rendering to
-         * allow components to grow in horizontal direction.
-         * 
-         * For fixed width layouts we specify the width directly so that height
-         * is automatically calculated correctly (e.g. for Labels).
-         */
-        /*
-         * This should no longer be needed (after #2563) as all components are
-         * such that they can be rendered inside a 0x0 DIV.
-         * 
-         * The exception seems to be complex components (Tree and Table) on
-         * Opera (#3444).
-         */
-        if (fixedWidth < 0 && BrowserInfo.get().isOpera()) {
-            setUnlimitedContainerWidth();
-        }
-        paintable.updateFromUIDL(childUIDL, client);
-    }
-
-    public void setUnlimitedContainerWidth() {
-        setLimitedContainerWidth(1000000);
-    }
-
-    public void setLimitedContainerWidth(int width) {
-        containerDIV.getStyle().setProperty("width", width + "px");
-    }
-
-    public void updateWidgetSize() {
-        /*
-         * Widget wrapper includes margin which the widget offsetWidth/Height
-         * does not include
-         */
-        int w = Util.getRequiredWidth(widgetDIV);
-        int h = Util.getRequiredHeight(widgetDIV);
-
-        widgetSize.setWidth(w);
-        widgetSize.setHeight(h);
-
-        // ApplicationConnection.getConsole().log(
-        // Util.getSimpleName(widget) + " size is " + w + "," + h);
-
-    }
-
-    public void setMarginLeft(int marginLeft) {
-        // containerMarginLeft = marginLeft;
-        containerDIV.getStyle().setPropertyPx("paddingLeft", marginLeft);
-    }
-
-    public void setMarginTop(int marginTop) {
-        containerMarginTop = marginTop;
-        containerDIV.getStyle().setPropertyPx("paddingTop",
-                marginTop + alignmentTopOffset);
-
-        updateContainerDOMSize();
-    }
-
-    public void updateAlignments(int parentWidth, int parentHeight) {
-        if (parentHeight == -1) {
-            parentHeight = contSize.getHeight();
-        }
-        if (parentWidth == -1) {
-            parentWidth = contSize.getWidth();
-        }
-
-        alignmentTopOffset = calculateVerticalAlignmentTopOffset(parentHeight);
-
-        calculateHorizontalAlignment(parentWidth);
-
-        applyAlignments();
-
-    }
-
-    private void applyAlignments() {
-
-        // Update top margin to take alignment into account
-        setMarginTop(containerMarginTop);
-
-        if (caption != null) {
-            caption.getElement().getStyle()
-                    .setPropertyPx("marginLeft", alignmentLeftOffsetForCaption);
-        }
-        widgetDIV.getStyle().setPropertyPx("marginLeft",
-                alignmentLeftOffsetForWidget);
-    }
-
-    public int getCaptionRequiredWidth() {
-        if (caption == null) {
-            return 0;
-        }
-
-        return captionRequiredWidth;
-    }
-
-    public int getCaptionWidth() {
-        if (caption == null) {
-            return 0;
-        }
-
-        return captionWidth;
-    }
-
-    public int getCaptionHeight() {
-        if (caption == null) {
-            return 0;
-        }
-
-        return captionHeight;
-    }
-
-    public int getCaptionWidthAfterComponent() {
-        if (caption == null || !caption.shouldBePlacedAfterComponent()) {
-            return 0;
-        }
-
-        return getCaptionWidth();
-    }
-
-    public int getCaptionHeightAboveComponent() {
-        if (caption == null || caption.shouldBePlacedAfterComponent()) {
-            return 0;
-        }
-
-        return getCaptionHeight();
-    }
-
-    private int calculateVerticalAlignmentTopOffset(int emptySpace) {
-        if (alignment.isTop()) {
-            return 0;
-        }
-
-        if (caption != null) {
-            if (caption.shouldBePlacedAfterComponent()) {
-                /*
-                 * Take into account the rare case that the caption on the right
-                 * side of the component AND is higher than the component
-                 */
-                emptySpace -= Math.max(widgetSize.getHeight(),
-                        caption.getHeight());
-            } else {
-                emptySpace -= widgetSize.getHeight();
-                emptySpace -= getCaptionHeight();
-            }
-        } else {
-            /*
-             * There is no caption and thus we do not need to take anything but
-             * the widget into account
-             */
-            emptySpace -= widgetSize.getHeight();
-        }
-
-        int top = 0;
-        if (alignment.isVerticalCenter()) {
-            top = emptySpace / 2;
-        } else if (alignment.isBottom()) {
-            top = emptySpace;
-        }
-
-        if (top < 0) {
-            top = 0;
-        }
-        return top;
-    }
-
-    private void calculateHorizontalAlignment(int emptySpace) {
-        alignmentLeftOffsetForCaption = 0;
-        alignmentLeftOffsetForWidget = 0;
-
-        if (alignment.isLeft()) {
-            return;
-        }
-
-        int captionSpace = emptySpace;
-        int widgetSpace = emptySpace;
-
-        if (caption != null) {
-            // There is a caption
-            if (caption.shouldBePlacedAfterComponent()) {
-                /*
-                 * The caption is after component. In this case the caption
-                 * needs no alignment.
-                 */
-                captionSpace = 0;
-                widgetSpace -= widgetSize.getWidth();
-                widgetSpace -= getCaptionWidth();
-            } else {
-                /*
-                 * The caption is above the component. Caption and widget needs
-                 * separate alignment offsets.
-                 */
-                widgetSpace -= widgetSize.getWidth();
-                captionSpace -= getCaptionWidth();
-            }
-        } else {
-            /*
-             * There is no caption and thus we do not need to take anything but
-             * the widget into account
-             */
-            captionSpace = 0;
-            widgetSpace -= widgetSize.getWidth();
-        }
-
-        if (alignment.isHorizontalCenter()) {
-            alignmentLeftOffsetForCaption = captionSpace / 2;
-            alignmentLeftOffsetForWidget = widgetSpace / 2;
-        } else if (alignment.isRight()) {
-            alignmentLeftOffsetForCaption = captionSpace;
-            alignmentLeftOffsetForWidget = widgetSpace;
-        }
-
-        if (alignmentLeftOffsetForCaption < 0) {
-            alignmentLeftOffsetForCaption = 0;
-        }
-        if (alignmentLeftOffsetForWidget < 0) {
-            alignmentLeftOffsetForWidget = 0;
-        }
-
-    }
-
-    public void setAlignment(AlignmentInfo alignmentInfo) {
-        alignment = alignmentInfo;
-    }
-
-    public Size getWidgetSize() {
-        return widgetSize;
-    }
-
-    public void updateCaption(UIDL uidl, ApplicationConnection client,
-            MeasuredSize parentSize) {
-        if (VCaption.isNeeded(uidl)) {
-            // We need a caption
-
-            VCaption newCaption = caption;
-
-            if (newCaption == null) {
-                newCaption = new VCaption(paintable, client);
-                // Set initial height to avoid Safari flicker
-                newCaption.setHeight("18px");
-                parentSize.registerDependency(newCaption.getElement());
-                // newCaption.setHeight(newCaption.getHeight()); // This might
-                // be better... ??
-                if (BrowserInfo.get().isIE()) {
-                    /*
-                     * Must attach caption here so IE sends an immediate onload
-                     * event for images coming from the cache
-                     */
-                    setCaption(newCaption);
-                }
-            }
-
-            boolean positionChanged = newCaption.updateCaption(uidl);
-
-            if (newCaption != caption || positionChanged) {
-                setCaption(newCaption);
-            }
-
-        } else {
-            // Caption is not needed
-            if (caption != null) {
-                parentSize.deRegisterDependency(caption.getElement());
-                remove(caption);
-            }
-
-        }
-
-        updateCaptionSize();
-
-        if (relativeSize == null) {
-            /*
-             * relativeSize may be null if component is updated via independent
-             * update, after it has initially been hidden. See #4608
-             * 
-             * It might also change in which case there would be similar issues.
-             * 
-             * Yes, it is an ugly hack. Don't come telling me about it.
-             */
-            setRelativeSize(Util.parseRelativeSize(uidl));
-        }
-    }
-
-    public void updateCaptionSize() {
-        captionWidth = 0;
-        captionHeight = 0;
-
-        if (caption != null) {
-            captionWidth = caption.getRenderedWidth();
-            captionHeight = caption.getHeight();
-            captionRequiredWidth = caption.getRequiredWidth();
-
-            /*
-             * ApplicationConnection.getConsole().log(
-             * "Caption rendered width: " + captionWidth +
-             * ", caption required width: " + captionRequiredWidth +
-             * ", caption height: " + captionHeight);
-             */
-        }
-
-    }
-
-    private void setCaption(VCaption newCaption) {
-        // Validate
-        // if (newCaption == caption) {
-        // return;
-        // }
-
-        // Detach new child.
-        if (newCaption != null) {
-            newCaption.removeFromParent();
-        }
-
-        // Remove old child.
-        if (caption != null && newCaption != caption) {
-            remove(caption);
-        }
-
-        // Logical attach.
-        caption = newCaption;
-
-        if (caption != null) {
-            // Physical attach.
-            if (caption.shouldBePlacedAfterComponent()) {
-                Util.setFloat(caption.getElement(), "left");
-                containerDIV.appendChild(caption.getElement());
-            } else {
-                Util.setFloat(caption.getElement(), "");
-                containerDIV.insertBefore(caption.getElement(), widgetDIV);
-            }
-
-            adopt(caption);
-        }
-
-    }
-
-    @Override
-    public boolean remove(Widget child) {
-        // Validate
-        if (child != caption && child != widget) {
-            return false;
-        }
-
-        // Orphan
-        orphan(child);
-
-        // Physical && Logical Detach
-        if (child == caption) {
-            containerDIV.removeChild(child.getElement());
-            caption = null;
-        } else {
-            widgetDIV.removeChild(child.getElement());
-            widget = null;
-        }
-
-        return true;
-    }
-
-    public Iterator<Widget> iterator() {
-        return new ChildComponentContainerIterator<Widget>();
-    }
-
-    public class ChildComponentContainerIterator<T> implements Iterator<Widget> {
-        private int id = 0;
-
-        public boolean hasNext() {
-            return (id < size());
-        }
-
-        public Widget next() {
-            Widget w = get(id);
-            id++;
-            return w;
-        }
-
-        private Widget get(int i) {
-            if (i == 0) {
-                if (widget != null) {
-                    return widget;
-                } else if (caption != null) {
-                    return caption;
-                } else {
-                    throw new NoSuchElementException();
-                }
-            } else if (i == 1) {
-                if (widget != null && caption != null) {
-                    return caption;
-                } else {
-                    throw new NoSuchElementException();
-                }
-            } else {
-                throw new NoSuchElementException();
-            }
-        }
-
-        public void remove() {
-            int toRemove = id - 1;
-            if (toRemove == 0) {
-                if (widget != null) {
-                    ChildComponentContainer.this.remove(widget);
-                } else if (caption != null) {
-                    ChildComponentContainer.this.remove(caption);
-                } else {
-                    throw new IllegalStateException();
-                }
-
-            } else if (toRemove == 1) {
-                if (widget != null && caption != null) {
-                    ChildComponentContainer.this.remove(caption);
-                } else {
-                    throw new IllegalStateException();
-                }
-            } else {
-                throw new IllegalStateException();
-            }
-
-            id--;
-        }
-    }
-
-    public int size() {
-        if (widget != null) {
-            if (caption != null) {
-                return 2;
-            } else {
-                return 1;
-            }
-        } else {
-            if (caption != null) {
-                return 1;
-            } else {
-                return 0;
-            }
-        }
-    }
-
-    public Widget getWidget() {
-        return widget;
-    }
-
-    /**
-     * Return true if the size of the widget has been specified in the selected
-     * orientation.
-     * 
-     * @return
-     */
-    public boolean widgetHasSizeSpecified(int orientation) {
-        String size;
-        if (orientation == ORIENTATION_HORIZONTAL) {
-            size = widget.getElement().getStyle().getProperty("width");
-        } else {
-            size = widget.getElement().getStyle().getProperty("height");
-        }
-        return (size != null && !size.equals(""));
-    }
-
-    public boolean isComponentRelativeSized(int orientation) {
-        if (relativeSize == null) {
-            return false;
-        }
-        if (orientation == ORIENTATION_HORIZONTAL) {
-            return relativeSize.getWidth() >= 0;
-        } else {
-            return relativeSize.getHeight() >= 0;
-        }
-    }
-
-    public void setRelativeSize(FloatSize relativeSize) {
-        this.relativeSize = relativeSize;
-    }
-
-    public Size getContSize() {
-        return contSize;
-    }
-
-    public void clearAlignments() {
-        alignmentLeftOffsetForCaption = 0;
-        alignmentLeftOffsetForWidget = 0;
-        alignmentTopOffset = 0;
-        applyAlignments();
-
-    }
-
-    /**
-     * Sets the normalized expand ratio of this slot. The fraction that this
-     * slot will use of "excess space".
-     * 
-     * @param expandRatio
-     */
-    public void setNormalizedExpandRatio(double expandRatio) {
-        this.expandRatio = expandRatio;
-    }
-
-    public int expand(int orientation, int spaceForExpansion) {
-        int expansionAmount = (int) (spaceForExpansion * expandRatio);
-
-        if (orientation == ORIENTATION_HORIZONTAL) {
-            // HORIZONTAL
-            containerExpansion.setWidth(expansionAmount);
-        } else {
-            // VERTICAL
-            containerExpansion.setHeight(expansionAmount);
-        }
-
-        return expansionAmount;
-    }
-
-    public void expandExtra(int orientation, int extra) {
-        if (orientation == ORIENTATION_HORIZONTAL) {
-            // HORIZONTAL
-            containerExpansion.setWidth(containerExpansion.getWidth() + extra);
-        } else {
-            // VERTICAL
-            containerExpansion
-                    .setHeight(containerExpansion.getHeight() + extra);
-        }
-
-    }
-
-    public void setContainerSize(int widgetAndCaptionWidth,
-            int widgetAndCaptionHeight) {
-
-        int containerWidth = widgetAndCaptionWidth;
-        containerWidth += containerExpansion.getWidth();
-
-        int containerHeight = widgetAndCaptionHeight;
-        containerHeight += containerExpansion.getHeight();
-
-        // ApplicationConnection.getConsole().log(
-        // "Setting container size for " + Util.getSimpleName(widget)
-        // + " to " + containerWidth + "," + containerHeight);
-
-        if (containerWidth < 0) {
-            VConsole.log("containerWidth should never be negative: "
-                    + containerWidth);
-            containerWidth = 0;
-        }
-        if (containerHeight < 0) {
-            VConsole.log("containerHeight should never be negative: "
-                    + containerHeight);
-            containerHeight = 0;
-        }
-
-        contSize.setWidth(containerWidth);
-        contSize.setHeight(containerHeight);
-
-        updateContainerDOMSize();
-    }
-
-    public void updateContainerDOMSize() {
-        int width = contSize.getWidth();
-        int height = contSize.getHeight() - alignmentTopOffset;
-        if (width < 0) {
-            width = 0;
-        }
-        if (height < 0) {
-            height = 0;
-        }
-
-        setWidth(width + "px");
-        setHeight(height + "px");
-
-        // Also update caption max width
-        if (caption != null) {
-            if (caption.shouldBePlacedAfterComponent()) {
-                caption.setMaxWidth(captionWidth);
-            } else {
-                caption.setMaxWidth(width);
-            }
-            captionWidth = caption.getRenderedWidth();
-
-            // Remove initial height
-            caption.setHeight("");
-        }
-
-    }
-
-}