]> source.dussan.org Git - vaadin-framework.git/commitdiff
Refactor to use LayoutSlot for children (#8313)
authorLeif Åstrand <leif@vaadin.com>
Thu, 9 Feb 2012 12:45:12 +0000 (14:45 +0200)
committerLeif Åstrand <leif@vaadin.com>
Thu, 9 Feb 2012 12:45:12 +0000 (14:45 +0200)
src/com/vaadin/terminal/gwt/client/ui/VMeasuringOrderedLayout.java
src/com/vaadin/terminal/gwt/client/ui/VMeasuringOrderedLayoutPaintable.java
src/com/vaadin/terminal/gwt/client/ui/layout/VLayoutSlot.java [new file with mode: 0644]
src/com/vaadin/terminal/gwt/client/ui/layout/VPaintableLayoutSlot.java [new file with mode: 0644]

index fcfbc3fb642fe2e526b489d3a0996347f37ed545..088eaf46f666c8db21dad41f3646d46d2ac7996a 100644 (file)
@@ -3,34 +3,21 @@
  */
 package com.vaadin.terminal.gwt.client.ui;
 
-import java.util.HashMap;
-import java.util.Map;
-
 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.user.client.DOM;
+import com.google.gwt.user.client.Element;
 import com.google.gwt.user.client.ui.ComplexPanel;
 import com.google.gwt.user.client.ui.Widget;
 import com.vaadin.terminal.gwt.client.VCaption;
-import com.vaadin.terminal.gwt.client.VPaintableWidget;
-import com.vaadin.terminal.gwt.client.ValueMap;
+import com.vaadin.terminal.gwt.client.ui.layout.VLayoutSlot;
 
 public class VMeasuringOrderedLayout extends ComplexPanel {
 
-    public static final String CLASSNAME = "v-orderedlayout";
-
     final boolean isVertical;
 
-    ValueMap expandRatios;
-
-    ValueMap alignments;
-
-    Map<VPaintableWidget, VCaption> captions = new HashMap<VPaintableWidget, VCaption>();
-
     final DivElement spacingMeasureElement;
 
     protected VMeasuringOrderedLayout(String className, boolean isVertical) {
@@ -50,60 +37,159 @@ public class VMeasuringOrderedLayout extends ComplexPanel {
         this.isVertical = isVertical;
     }
 
-    static Element getWrapper(Widget widget) {
-        return widget.getElement().getParentElement();
-    }
+    public void addSlot(VLayoutSlot layoutSlot) {
+        Widget widget = layoutSlot.getWidget();
+        Element wrapperElement = layoutSlot.getWrapperElement();
 
-    private void add(Widget widget, DivElement wrapper) {
-        add(widget, (com.google.gwt.user.client.Element) wrapper.cast());
-    }
+        getElement().appendChild(wrapperElement);
+        add(widget, wrapperElement);
 
-    void addChildWidget(Widget widget) {
-        DivElement wrapper = Document.get().createDivElement();
-        wrapper.getStyle().setPosition(Position.ABSOLUTE);
-        getElement().appendChild(wrapper);
-        add(widget, wrapper);
-        widget.getElement().getStyle()
-                .setProperty("MozBoxSizing", "border-box");
-        widget.getElement().getStyle().setProperty("boxSizing", "border-box");
-    }
-
-    void addCaption(VCaption caption, Widget widget) {
-        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);
+        widget.setLayoutData(layoutSlot);
     }
 
     private void togglePrefixedStyleName(String name, boolean enabled) {
         if (enabled) {
-            addStyleName(CLASSNAME + name);
+            addStyleDependentName(name);
         } else {
-            removeStyleName(CLASSNAME + name);
+            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());
+        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 = getStyleName();
         if (spacingEnabled) {
-            spacingMeasureElement.addClassName(CLASSNAME + "-spacing-on");
-            spacingMeasureElement.removeClassName(CLASSNAME + "-spacing-off");
+            spacingMeasureElement.addClassName(styleName + "-spacing-on");
+            spacingMeasureElement.removeClassName(styleName + "-spacing-off");
         } else {
-            spacingMeasureElement.removeClassName(CLASSNAME + "-spacing-on");
-            spacingMeasureElement.addClassName(CLASSNAME + "-spacing-off");
+            spacingMeasureElement.removeClassName(styleName + "-spacing-on");
+            spacingMeasureElement.addClassName(styleName + "-spacing-off");
+        }
+    }
+
+    public void removeSlot(VLayoutSlot slot) {
+        VCaption caption = slot.getCaption();
+        if (caption != null) {
+            remove(caption);
+        }
+
+        remove(slot.getWidget());
+        getElement().removeChild(slot.getWrapperElement());
+    }
+
+    public VLayoutSlot getSlotForChild(Widget widget) {
+        return (VLayoutSlot) widget.getLayoutData();
+    }
+
+    public void setCaption(Widget child, VCaption caption) {
+        VLayoutSlot slot = getSlotForChild(child);
+
+        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);
+        }
+    }
+
+    public int layoutPrimaryDirection(int spacingSize, int allocatedSize,
+            int startPadding) {
+        int actuallyAllocated = 0;
+        double totalExpand = 0;
+
+        int childCount = 0;
+        for (Widget child : this) {
+            if (child instanceof VCaption) {
+                continue;
+            }
+            childCount++;
+
+            VLayoutSlot slot = getSlotForChild(child);
+            totalExpand += slot.getExpandRatio();
+
+            if (!slot.isRelativeInDirection(isVertical)) {
+                actuallyAllocated += slot.getUsedSizeInDirection(isVertical);
+            }
+        }
+
+        actuallyAllocated += spacingSize * (childCount - 1);
+
+        if (allocatedSize == -1) {
+            allocatedSize = actuallyAllocated;
+        }
+
+        double unallocatedSpace = Math
+                .max(0, allocatedSize - actuallyAllocated);
+
+        double currentLocation = startPadding;
+
+        for (Widget child : this) {
+            if (child instanceof VCaption) {
+                continue;
+            }
+
+            VLayoutSlot slot = getSlotForChild(child);
+
+            double childExpandRatio;
+            if (totalExpand == 0) {
+                childExpandRatio = 1d / childCount;
+            } else {
+                childExpandRatio = slot.getExpandRatio() / totalExpand;
+            }
+
+            double extraPixels = unallocatedSpace * childExpandRatio;
+            double allocatedSpace = extraPixels;
+            if (!slot.isRelativeInDirection(isVertical)) {
+                allocatedSpace += slot.getUsedSizeInDirection(isVertical);
+            }
+
+            slot.positionInDirection(currentLocation, allocatedSpace,
+                    isVertical);
+            currentLocation += allocatedSpace + spacingSize;
+        }
+
+        return allocatedSize;
+    }
+
+    public int layoutSecondaryDirection(int allocatedSize, int startPadding) {
+        int maxSize = 0;
+        for (Widget child : this) {
+            if (child instanceof VCaption) {
+                continue;
+            }
+
+            VLayoutSlot slot = getSlotForChild(child);
+            if (!slot.isRelativeInDirection(!isVertical)) {
+                maxSize = Math.max(maxSize,
+                        slot.getUsedSizeInDirection(!isVertical));
+            }
         }
+
+        if (allocatedSize == -1) {
+            allocatedSize = maxSize;
+        }
+
+        for (Widget child : this) {
+            if (child instanceof VCaption) {
+                continue;
+            }
+
+            VLayoutSlot slot = getSlotForChild(child);
+            slot.positionInDirection(startPadding, allocatedSize, !isVertical);
+        }
+
+        return allocatedSize;
     }
 }
index 0ce5c8e89f09565a11deccb29cecb903a0b17249..c995e681d13083a7187b6c1034cace7be2058944 100644 (file)
@@ -1,12 +1,9 @@
 package com.vaadin.terminal.gwt.client.ui;
 
-import java.util.Collection;
 import java.util.HashSet;
 import java.util.Iterator;
 
-import com.google.gwt.dom.client.Element;
 import com.google.gwt.dom.client.Style;
-import com.google.gwt.dom.client.Style.Unit;
 import com.google.gwt.user.client.ui.Widget;
 import com.vaadin.terminal.gwt.client.ApplicationConnection;
 import com.vaadin.terminal.gwt.client.CalculatingLayout;
@@ -15,6 +12,9 @@ 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;
+import com.vaadin.terminal.gwt.client.ui.layout.VLayoutSlot;
+import com.vaadin.terminal.gwt.client.ui.layout.VPaintableLayoutSlot;
 
 public abstract class VMeasuringOrderedLayoutPaintable extends
         VAbstractPaintableWidgetContainer implements CalculatingLayout {
@@ -25,27 +25,21 @@ public abstract class VMeasuringOrderedLayoutPaintable extends
     }
 
     public void updateCaption(VPaintableWidget component, UIDL uidl) {
+        VMeasuringOrderedLayout layout = getWidgetForPaintable();
         if (VCaption.isNeeded(uidl)) {
-            VCaption caption = getWidgetForPaintable().captions.get(component);
+            VLayoutSlot layoutSlot = layout.getSlotForChild(component
+                    .getWidgetForPaintable());
+            VCaption caption = layoutSlot.getCaption();
             if (caption == null) {
                 caption = new VCaption(component, getConnection());
 
                 Widget widget = component.getWidgetForPaintable();
 
-                getWidgetForPaintable().addCaption(caption, widget);
-                getWidgetForPaintable().captions.put(component, caption);
-
-                getMeasuredSize().registerDependency(caption.getElement());
+                layout.setCaption(widget, caption);
             }
             caption.updateCaption(uidl);
         } else {
-            VCaption removedCaption = getWidgetForPaintable().captions
-                    .remove(component);
-            if (removedCaption != null) {
-                getWidgetForPaintable().remove(removedCaption);
-                getMeasuredSize().deRegisterDependency(
-                        removedCaption.getElement());
-            }
+            layout.setCaption(component.getWidgetForPaintable(), null);
         }
     }
 
@@ -64,86 +58,66 @@ public abstract class VMeasuringOrderedLayoutPaintable extends
         HashSet<VPaintableWidget> previousChildren = new HashSet<VPaintableWidget>(
                 getChildren());
 
+        VMeasuringOrderedLayout layout = getWidgetForPaintable();
+
+        ValueMap expandRatios = uidl.getMapAttribute("expandRatios");
+        ValueMap alignments = uidl.getMapAttribute("alignments");
+
         // 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() != getWidgetForPaintable()) {
-                getWidgetForPaintable().addChildWidget(widget);
+            VLayoutSlot slot = layout.getSlotForChild(widget);
+
+            if (widget.getParent() != layout) {
+                slot = new VPaintableLayoutSlot(child);
+                layout.addSlot(slot);
+            }
+
+            String pid = child.getId();
+
+            AlignmentInfo alignment;
+            if (alignments.containsKey(pid)) {
+                alignment = new AlignmentInfo(alignments.getInt(pid));
+            } else {
+                alignment = AlignmentInfo.TOP_LEFT;
             }
+            slot.setAlignment(alignment);
+
+            double expandRatio;
+            if (expandRatios.containsKey(pid)) {
+                expandRatio = expandRatios.getRawNumber(pid);
+            } else {
+                expandRatio = 0;
+            }
+            slot.setExpandRatio(expandRatio);
 
             if (!childUIDL.getBooleanAttribute("cached")) {
                 child.updateFromUIDL(childUIDL, client);
                 child.getMeasuredSize().setDirty(true);
             }
-            // TODO Update alignments and expand ratios
 
             previousChildren.remove(child);
         }
 
         for (VPaintableWidget child : previousChildren) {
             Widget widget = child.getWidgetForPaintable();
-            Element wrapper = VMeasuringOrderedLayout.getWrapper(widget);
-            VCaption caption = getWidgetForPaintable().captions.remove(widget);
-            if (caption != null) {
-                getWidgetForPaintable().remove(caption);
-            }
-            getWidgetForPaintable().remove(widget);
-            // Remove the wrapper
-            getWidgetForPaintable().getElement().removeChild(wrapper);
+            layout.removeSlot(layout.getSlotForChild(widget));
 
             VPaintableMap vPaintableMap = VPaintableMap.get(client);
             vPaintableMap.unregisterPaintable(child);
         }
 
         int bitMask = uidl.getIntAttribute("margins");
-        getWidgetForPaintable()
-                .updateMarginStyleNames(new VMarginInfo(bitMask));
+        layout.updateMarginStyleNames(new VMarginInfo(bitMask));
 
-        getWidgetForPaintable().updateSpacingStyleName(
-                uidl.getBooleanAttribute("spacing"));
+        layout.updateSpacingStyleName(uidl.getBooleanAttribute("spacing"));
 
-        getWidgetForPaintable().expandRatios = uidl
-                .getMapAttribute("expandRatios");
-        getWidgetForPaintable().alignments = uidl.getMapAttribute("alignments");
         getMeasuredSize().setDirty(true);
     }
 
-    private int getCaptionWidth(VPaintableWidget child) {
-        VCaption caption = getWidgetForPaintable().captions.get(child);
-        if (caption == null) {
-            return 0;
-        } else {
-            return getMeasuredSize().getDependencyOuterWidth(
-                    caption.getElement());
-        }
-    }
-
-    private int getCaptionHeight(VPaintableWidget child) {
-        VCaption caption = getWidgetForPaintable().captions.get(child);
-        if (caption != null) {
-            int captionHeight = getMeasuredSize().getDependencyOuterHeight(
-                    caption.getElement());
-
-            caption.getElement().getStyle()
-                    .setMarginTop(-captionHeight, Unit.PX);
-            return captionHeight;
-        } else {
-            return 0;
-        }
-    }
-
-    private static boolean isRelativeInDirection(VPaintableWidget paintable,
-            boolean isVertical) {
-        if (isVertical) {
-            return paintable.isRelativeHeight();
-        } else {
-            return paintable.isRelativeWidth();
-        }
-    }
-
     private int getSizeForInnerSize(int size, boolean isVertical) {
         MeasuredSize measuredSize = getMeasuredSize();
         if (isVertical) {
@@ -159,26 +133,11 @@ public abstract class VMeasuringOrderedLayoutPaintable extends
         return isVertical ? "height" : "width";
     }
 
-    private static String getStartProperty(boolean isVertical) {
-        return isVertical ? "top" : "left";
-    }
-
-    private static boolean isUndefinedInDirection(VPaintableWidget paintable,
-            boolean isVertical) {
+    private boolean isUndefinedInDirection(boolean isVertical) {
         if (isVertical) {
-            return paintable.isUndefinedHeight();
+            return isUndefinedHeight();
         } else {
-            return paintable.isUndefinedWidth();
-        }
-    }
-
-    private static int getOuterSizeInDirection(VPaintableWidget paintable,
-            boolean isVertical) {
-        MeasuredSize measuredSize = paintable.getMeasuredSize();
-        if (isVertical) {
-            return measuredSize.getOuterHeight();
-        } else {
-            return measuredSize.getOuterWidth();
+            return isUndefinedWidth();
         }
     }
 
@@ -190,147 +149,31 @@ public abstract class VMeasuringOrderedLayoutPaintable extends
         }
     }
 
-    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 void layoutPrimaryDirection() {
-        Collection<VPaintableWidget> children = getChildren();
-
-        // First pass - get total expand ratio and allocated size
-        int totalAllocated = 0;
-        double totalExpand = 0;
-        for (VPaintableWidget child : children) {
-            Widget widget = child.getWidgetForPaintable();
+        VMeasuringOrderedLayout layout = getWidgetForPaintable();
+        boolean isVertical = layout.isVertical;
+        boolean isUndefined = isUndefinedInDirection(isVertical);
 
-            totalExpand += getExpandRatio(child);
+        int startPadding = getStartPadding(isVertical);
+        int spacingSize = getSpacingInDirection(isVertical);
+        int allocatedSize;
 
-            int captionAllocation;
-            if (getWidgetForPaintable().isVertical) {
-                captionAllocation = getCaptionHeight(child);
-                getWidgetForPaintable();
-                VMeasuringOrderedLayout.getWrapper(widget).getStyle()
-                        .setPaddingTop(captionAllocation, Unit.PX);
-            } else {
-                captionAllocation = 0;
-            }
-
-            if (!isRelativeInDirection(child,
-                    getWidgetForPaintable().isVertical)) {
-                int childSize = getOuterSizeInDirection(child,
-                        getWidgetForPaintable().isVertical);
-                if (getWidgetForPaintable().isVertical) {
-                    childSize += captionAllocation;
-                } else {
-                    childSize = Math.max(childSize, getCaptionWidth(child));
-                }
-                totalAllocated += childSize;
-            }
+        if (isUndefined) {
+            allocatedSize = -1;
+        } else {
+            allocatedSize = getInnerSizeInDirection(isVertical);
         }
 
-        totalAllocated += getSpacingInDirection(getWidgetForPaintable().isVertical)
-                * (children.size() - 1);
+        allocatedSize = layout.layoutPrimaryDirection(spacingSize,
+                allocatedSize, startPadding);
 
         Style ownStyle = getWidgetForPaintable().getElement().getStyle();
-        double ownSize;
-        if (isUndefinedInDirection(this, getWidgetForPaintable().isVertical)) {
-            ownSize = totalAllocated;
-            ownStyle.setPropertyPx(
-                    getSizeProperty(getWidgetForPaintable().isVertical),
-                    getSizeForInnerSize(totalAllocated,
-                            getWidgetForPaintable().isVertical));
+        if (isUndefined) {
+            ownStyle.setPropertyPx(getSizeProperty(isVertical),
+                    getSizeForInnerSize(allocatedSize, isVertical));
         } else {
-            ownSize = getInnerSizeInDirection(getWidgetForPaintable().isVertical);
-            ownStyle.setProperty(
-                    getSizeProperty(getWidgetForPaintable().isVertical),
-                    getDefinedSize(getWidgetForPaintable().isVertical));
-        }
-
-        double unallocatedSpace = Math.max(0, ownSize - totalAllocated);
-
-        double currentLocation = getStartPadding(getWidgetForPaintable().isVertical);
-        for (VPaintableWidget child : children) {
-            Widget widget = child.getWidgetForPaintable();
-            getWidgetForPaintable();
-            Element wrapper = VMeasuringOrderedLayout.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(child,
-                    getWidgetForPaintable().isVertical);
-
-            double size = getOuterSizeInDirection(child,
-                    getWidgetForPaintable().isVertical);
-            int captionHeight = getCaptionHeight(child);
-
-            if (getWidgetForPaintable().isVertical) {
-                size += captionHeight;
-            } else if (!relative) {
-                size = Math.max(size, getCaptionWidth(child));
-            }
-
-            double allocatedSpace = extraPixels;
-            if (!relative) {
-                allocatedSpace += size;
-            }
-
-            int alignment = getAlignmentInDirection(getAlignment(child),
-                    getWidgetForPaintable().isVertical);
-
-            if (relative) {
-                double captionReservation = getWidgetForPaintable().isVertical ? captionHeight
-                        : 0;
-                wrapperStyle.setProperty(
-                        getSizeProperty(getWidgetForPaintable().isVertical),
-                        allocatedSpace - captionReservation, Unit.PX);
-            } else {
-                wrapperStyle
-                        .clearProperty(getSizeProperty(getWidgetForPaintable().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(getWidgetForPaintable().isVertical),
-                    startPosition, Unit.PX);
-
-            currentLocation += allocatedSpace
-                    + getSpacingInDirection(getWidgetForPaintable().isVertical);
+            ownStyle.setProperty(getSizeProperty(isVertical),
+                    getDefinedSize(isVertical));
         }
     }
 
@@ -345,93 +188,33 @@ public abstract class VMeasuringOrderedLayoutPaintable extends
     }
 
     private void layoutSecondaryDirection() {
-        Collection<VPaintableWidget> children = getChildren();
+        VMeasuringOrderedLayout layout = getWidgetForPaintable();
+        boolean isVertical = layout.isVertical;
+        boolean isUndefined = isUndefinedInDirection(!isVertical);
 
-        int maxSize = 0;
-        for (VPaintableWidget child : children) {
-            Widget widget = child.getWidgetForPaintable();
-
-            int captionAllocation;
-            if (!getWidgetForPaintable().isVertical) {
-                captionAllocation = getCaptionHeight(child);
-                getWidgetForPaintable();
-                VMeasuringOrderedLayout.getWrapper(widget).getStyle()
-                        .setPaddingTop(captionAllocation, Unit.PX);
-            } else {
-                captionAllocation = 0;
-            }
+        int startPadding = getStartPadding(!isVertical);
 
-            if (!isRelativeInDirection(child,
-                    !getWidgetForPaintable().isVertical)) {
-                int childSize = getOuterSizeInDirection(child,
-                        !getWidgetForPaintable().isVertical)
-                        + captionAllocation;
-                maxSize = Math.max(maxSize, childSize);
-            }
+        int allocatedSize;
+        if (isUndefined) {
+            allocatedSize = -1;
+        } else {
+            allocatedSize = getInnerSizeInDirection(!isVertical);
         }
 
-        double availableSpace;
+        allocatedSize = layout.layoutSecondaryDirection(allocatedSize,
+                startPadding);
+
         Style ownStyle = getWidgetForPaintable().getElement().getStyle();
 
-        if (isUndefinedInDirection(this, !getWidgetForPaintable().isVertical)) {
+        if (isUndefined) {
             ownStyle.setPropertyPx(
                     getSizeProperty(!getWidgetForPaintable().isVertical),
-                    getSizeForInnerSize(maxSize,
+                    getSizeForInnerSize(allocatedSize,
                             !getWidgetForPaintable().isVertical));
-
-            availableSpace = maxSize;
         } else {
             ownStyle.setProperty(
                     getSizeProperty(!getWidgetForPaintable().isVertical),
                     getDefinedSize(!getWidgetForPaintable().isVertical));
-            availableSpace = getInnerSizeInDirection(!getWidgetForPaintable().isVertical);
-        }
-
-        for (VPaintableWidget child : children) {
-            Widget widget = child.getWidgetForPaintable();
-            getWidgetForPaintable();
-            Element wrapper = VMeasuringOrderedLayout.getWrapper(widget);
-            Style wrapperStyle = wrapper.getStyle();
-
-            boolean relative = isRelativeInDirection(child,
-                    !getWidgetForPaintable().isVertical);
-
-            int captionHeight = getCaptionHeight(child);
-
-            double allocatedSize = getOuterSizeInDirection(child,
-                    !getWidgetForPaintable().isVertical);
-            if (!getWidgetForPaintable().isVertical) {
-                allocatedSize += captionHeight;
-            } else if (!relative) {
-                allocatedSize = Math.max(allocatedSize, getCaptionWidth(child));
-            }
-
-            int alignment = getAlignmentInDirection(getAlignment(child),
-                    !getWidgetForPaintable().isVertical);
-
-            double startPosition = getStartPadding(getWidgetForPaintable().isVertical);
-            if (alignment == 0) {
-                startPosition += (availableSpace - allocatedSize) / 2;
-                // Centered
-            } else if (alignment == 1) {
-                // Right or bottom
-                startPosition += (availableSpace - allocatedSize);
-            }
-
-            wrapperStyle.setProperty(
-                    getStartProperty(!getWidgetForPaintable().isVertical),
-                    startPosition, Unit.PX);
-
-            if (relative) {
-                double captionReservation = !getWidgetForPaintable().isVertical ? captionHeight
-                        : 0;
-                wrapperStyle.setProperty(
-                        getSizeProperty(!getWidgetForPaintable().isVertical),
-                        availableSpace - captionReservation, Unit.PX);
-            } else {
-                wrapperStyle
-                        .clearProperty(getSizeProperty(!getWidgetForPaintable().isVertical));
-            }
         }
     }
 
@@ -467,22 +250,4 @@ public abstract class VMeasuringOrderedLayoutPaintable extends
         }
     }
 
-    AlignmentInfo getAlignment(VPaintableWidget child) {
-        String pid = child.getId();
-        if (getWidgetForPaintable().alignments.containsKey(pid)) {
-            return new AlignmentInfo(
-                    getWidgetForPaintable().alignments.getInt(pid));
-        } else {
-            return AlignmentInfo.TOP_LEFT;
-        }
-    }
-
-    double getExpandRatio(VPaintableWidget child) {
-        String pid = child.getId();
-        if (getWidgetForPaintable().expandRatios.containsKey(pid)) {
-            return getWidgetForPaintable().expandRatios.getRawNumber(pid);
-        } else {
-            return 0;
-        }
-    }
 }
diff --git a/src/com/vaadin/terminal/gwt/client/ui/layout/VLayoutSlot.java b/src/com/vaadin/terminal/gwt/client/ui/layout/VLayoutSlot.java
new file mode 100644 (file)
index 0000000..9cb2a3a
--- /dev/null
@@ -0,0 +1,199 @@
+package com.vaadin.terminal.gwt.client.ui.layout;
+
+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.DOM;
+import com.google.gwt.user.client.Element;
+import com.google.gwt.user.client.ui.Widget;
+import com.vaadin.terminal.gwt.client.VCaption;
+import com.vaadin.terminal.gwt.client.ui.AlignmentInfo;
+
+public abstract class VLayoutSlot {
+
+    private final Element wrapper = Document.get().createDivElement().cast();
+
+    private AlignmentInfo alignment;
+    private VCaption caption;
+    private final Widget widget;
+
+    private double expandRatio;
+
+    public VLayoutSlot(Widget widget) {
+        this.widget = widget;
+
+        wrapper.getStyle().setPosition(Position.ABSOLUTE);
+
+        // TODO set box sizing in CSS
+        Style widgetStyle = widget.getElement().getStyle();
+        widgetStyle.setProperty("MozBoxSizing", "border-box");
+        widgetStyle.setProperty("boxSizing", "border-box");
+    }
+
+    public VCaption getCaption() {
+        return caption;
+    }
+
+    public void setCaption(VCaption caption) {
+        if (this.caption != null) {
+            this.caption.removeFromParent();
+        }
+        this.caption = caption;
+        if (caption != null) {
+            // Physical attach.
+            DOM.insertBefore(wrapper, caption.getElement(), widget.getElement());
+            caption.getElement().getStyle().setPosition(Position.ABSOLUTE);
+        }
+    }
+
+    public AlignmentInfo getAlignment() {
+        return alignment;
+    }
+
+    public Widget getWidget() {
+        return widget;
+    }
+
+    public void setAlignment(AlignmentInfo alignment) {
+        this.alignment = alignment;
+    }
+
+    public void positionHorizontally(double currentLocation,
+            double allocatedSpace) {
+        Style style = wrapper.getStyle();
+
+        if (isRelativeWidth()) {
+            style.setWidth(allocatedSpace, Unit.PX);
+        } else {
+            style.setWidth(getUsedWidth(), Unit.PX);
+        }
+
+        VCaption caption = getCaption();
+        Style captionStyle = caption != null ? caption.getElement().getStyle()
+                : null;
+
+        AlignmentInfo alignment = getAlignment();
+        if (!alignment.isLeft()) {
+            double usedWidth = getWidgetWidth();
+            if (alignment.isHorizontalCenter()) {
+                currentLocation += (allocatedSpace - usedWidth) / 2d;
+                if (captionStyle != null) {
+                    double captionWidth = getCaptionWidth();
+                    captionStyle.setLeft(usedWidth / 2 - (captionWidth / 2),
+                            Unit.PX);
+                    captionStyle.clearRight();
+                }
+            } else {
+                currentLocation += (allocatedSpace - usedWidth);
+                if (captionStyle != null) {
+                    captionStyle.clearLeft();
+                    captionStyle.setRight(0, Unit.PX);
+                }
+            }
+        } else {
+            if (captionStyle != null) {
+                captionStyle.setLeft(0, Unit.PX);
+                captionStyle.clearRight();
+            }
+        }
+
+        style.setLeft(currentLocation, Unit.PX);
+    }
+
+    public void positionVertically(double currentLocation, double allocatedSpace) {
+        Style style = wrapper.getStyle();
+
+        VCaption caption = getCaption();
+        double captionHeight = caption != null ? getCaptionHeight() : 0;
+        double contentHeight = allocatedSpace - captionHeight;
+
+        if (isRelativeHeight()) {
+            style.setHeight(contentHeight, Unit.PX);
+        } else {
+            style.clearHeight();
+        }
+
+        if (caption != null) {
+            style.setPaddingTop(getCaptionHeight(), Unit.PX);
+            caption.getElement().getStyle().setTop(0, Unit.PX);
+        } else {
+            style.clearPaddingTop();
+        }
+
+        AlignmentInfo alignment = getAlignment();
+        if (!alignment.isTop()) {
+            double actualHeight = getWidgetHeight() + captionHeight;
+            if (alignment.isVerticalCenter()) {
+                currentLocation += (allocatedSpace - actualHeight) / 2d;
+            } else {
+                currentLocation += (allocatedSpace - actualHeight);
+            }
+        }
+
+        style.setTop(currentLocation, Unit.PX);
+    }
+
+    public void positionInDirection(double currentLocation,
+            double allocatedSpace, boolean isVertical) {
+        if (isVertical) {
+            positionVertically(currentLocation, allocatedSpace);
+        } else {
+            positionHorizontally(currentLocation, allocatedSpace);
+        }
+    }
+
+    public int getWidgetSizeInDirection(boolean isVertical) {
+        return isVertical ? getWidgetHeight() : getWidgetWidth();
+    }
+
+    public int getUsedWidth() {
+        int captionWidth = (caption != null ? getCaptionWidth() : 0);
+        return Math.max(captionWidth, getWidgetWidth());
+    }
+
+    public int getUsedHeight() {
+        int captionHeight = (caption != null ? getCaptionHeight() : 0);
+        return getWidgetHeight() + captionHeight;
+    }
+
+    public int getUsedSizeInDirection(boolean isVertical) {
+        return isVertical ? getUsedHeight() : getUsedWidth();
+    }
+
+    protected abstract int getCaptionHeight();
+
+    protected abstract int getCaptionWidth();
+
+    public abstract int getWidgetHeight();
+
+    public abstract int getWidgetWidth();
+
+    public abstract boolean isUndefinedHeight();
+
+    public abstract boolean isUndefinedWidth();
+
+    public boolean isUndefinedInDirection(boolean isVertical) {
+        return isVertical ? isUndefinedHeight() : isUndefinedWidth();
+    }
+
+    public abstract boolean isRelativeHeight();
+
+    public abstract boolean isRelativeWidth();
+
+    public boolean isRelativeInDirection(boolean isVertical) {
+        return isVertical ? isRelativeHeight() : isRelativeWidth();
+    }
+
+    public Element getWrapperElement() {
+        return wrapper;
+    }
+
+    public void setExpandRatio(double expandRatio) {
+        this.expandRatio = expandRatio;
+    }
+
+    public double getExpandRatio() {
+        return expandRatio;
+    }
+}
\ No newline at end of file
diff --git a/src/com/vaadin/terminal/gwt/client/ui/layout/VPaintableLayoutSlot.java b/src/com/vaadin/terminal/gwt/client/ui/layout/VPaintableLayoutSlot.java
new file mode 100644 (file)
index 0000000..17afab0
--- /dev/null
@@ -0,0 +1,79 @@
+package com.vaadin.terminal.gwt.client.ui.layout;
+
+import com.vaadin.terminal.gwt.client.MeasuredSize;
+import com.vaadin.terminal.gwt.client.VCaption;
+import com.vaadin.terminal.gwt.client.VPaintableWidget;
+
+public class VPaintableLayoutSlot extends VLayoutSlot {
+
+    final VPaintableWidget paintable;
+
+    public VPaintableLayoutSlot(VPaintableWidget paintable) {
+        super(paintable.getWidgetForPaintable());
+        this.paintable = paintable;
+    }
+
+    public VPaintableWidget getPaintable() {
+        return paintable;
+    }
+
+    @Override
+    protected int getCaptionHeight() {
+        VCaption caption = getCaption();
+        return caption != null ? getParentSize().getDependencyOuterHeight(
+                caption.getElement()) : 0;
+    }
+
+    private MeasuredSize getParentSize() {
+        return paintable.getParent().getMeasuredSize();
+    }
+
+    @Override
+    protected int getCaptionWidth() {
+        VCaption caption = getCaption();
+        return caption != null ? getParentSize().getDependencyOuterWidth(
+                caption.getElement()) : 0;
+    }
+
+    @Override
+    public void setCaption(VCaption caption) {
+        VCaption oldCaption = getCaption();
+        if (oldCaption != null) {
+            getParentSize().deRegisterDependency(oldCaption.getElement());
+        }
+        super.setCaption(caption);
+        if (caption != null) {
+            getParentSize().registerDependency(caption.getElement());
+        }
+    }
+
+    @Override
+    public int getWidgetHeight() {
+        return paintable.getMeasuredSize().getOuterHeight();
+    }
+
+    @Override
+    public int getWidgetWidth() {
+        return paintable.getMeasuredSize().getOuterWidth();
+    }
+
+    @Override
+    public boolean isUndefinedHeight() {
+        return paintable.isUndefinedHeight();
+    }
+
+    @Override
+    public boolean isUndefinedWidth() {
+        return paintable.isUndefinedWidth();
+    }
+
+    @Override
+    public boolean isRelativeHeight() {
+        return paintable.isRelativeHeight();
+    }
+
+    @Override
+    public boolean isRelativeWidth() {
+        return paintable.isRelativeWidth();
+    }
+}