]> source.dussan.org Git - vaadin-framework.git/commitdiff
Moved BoxLayout to new package
authorJouni Koivuviita <jouni@vaadin.com>
Fri, 17 Aug 2012 10:37:10 +0000 (13:37 +0300)
committerJouni Koivuviita <jouni@vaadin.com>
Fri, 17 Aug 2012 10:37:10 +0000 (13:37 +0300)
client/src/com/vaadin/terminal/gwt/client/ComponentLocator.java
client/src/com/vaadin/terminal/gwt/client/ui/orderedlayout/AbstractBoxLayoutConnector.java [new file with mode: 0644]
client/src/com/vaadin/terminal/gwt/client/ui/orderedlayout/HorizontalBoxLayoutConnector.java [new file with mode: 0644]
client/src/com/vaadin/terminal/gwt/client/ui/orderedlayout/HorizontalLayoutConnector.java
client/src/com/vaadin/terminal/gwt/client/ui/orderedlayout/VBoxLayout.java [new file with mode: 0644]
client/src/com/vaadin/terminal/gwt/client/ui/orderedlayout/VerticalBoxLayoutConnector.java [new file with mode: 0644]
client/src/com/vaadin/terminal/gwt/client/ui/orderedlayout/VerticalLayoutConnector.java

index f30c73156237a34517206e21a16a4807d5d258cd..e515c2626c34aa2bc403d2879baa64c65a3abc0c 100644 (file)
@@ -28,8 +28,8 @@ import com.vaadin.shared.ComponentState;
 import com.vaadin.shared.Connector;
 import com.vaadin.shared.communication.SharedState;
 import com.vaadin.terminal.gwt.client.ui.SubPartAware;
-import com.vaadin.terminal.gwt.client.ui.VBoxLayout;
 import com.vaadin.terminal.gwt.client.ui.gridlayout.VGridLayout;
+import com.vaadin.terminal.gwt.client.ui.orderedlayout.VBoxLayout;
 import com.vaadin.terminal.gwt.client.ui.orderedlayout.VMeasuringOrderedLayout;
 import com.vaadin.terminal.gwt.client.ui.root.VRoot;
 import com.vaadin.terminal.gwt.client.ui.tabsheet.VTabsheetPanel;
diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/orderedlayout/AbstractBoxLayoutConnector.java b/client/src/com/vaadin/terminal/gwt/client/ui/orderedlayout/AbstractBoxLayoutConnector.java
new file mode 100644 (file)
index 0000000..bbf9aed
--- /dev/null
@@ -0,0 +1,598 @@
+/* 
+@VaadinApache2LicenseForJavaFiles@
+ */
+package com.vaadin.terminal.gwt.client.ui.orderedlayout;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+
+import com.google.gwt.dom.client.Style.Unit;
+import com.google.gwt.user.client.Element;
+import com.vaadin.shared.AbstractFieldState;
+import com.vaadin.shared.ui.AlignmentInfo;
+import com.vaadin.shared.ui.LayoutClickRpc;
+import com.vaadin.shared.ui.VMarginInfo;
+import com.vaadin.shared.ui.orderedlayout.AbstractOrderedLayoutServerRpc;
+import com.vaadin.shared.ui.orderedlayout.AbstractOrderedLayoutState;
+import com.vaadin.terminal.gwt.client.ComponentConnector;
+import com.vaadin.terminal.gwt.client.ConnectorHierarchyChangeEvent;
+import com.vaadin.terminal.gwt.client.Util;
+import com.vaadin.terminal.gwt.client.communication.RpcProxy;
+import com.vaadin.terminal.gwt.client.communication.StateChangeEvent;
+import com.vaadin.terminal.gwt.client.communication.StateChangeEvent.StateChangeHandler;
+import com.vaadin.terminal.gwt.client.ui.AbstractFieldConnector;
+import com.vaadin.terminal.gwt.client.ui.AbstractLayoutConnector;
+import com.vaadin.terminal.gwt.client.ui.LayoutClickEventHandler;
+import com.vaadin.terminal.gwt.client.ui.layout.ElementResizeEvent;
+import com.vaadin.terminal.gwt.client.ui.layout.ElementResizeListener;
+import com.vaadin.terminal.gwt.client.ui.orderedlayout.VBoxLayout.CaptionPosition;
+import com.vaadin.terminal.gwt.client.ui.orderedlayout.VBoxLayout.Slot;
+
+public abstract class AbstractBoxLayoutConnector extends
+        AbstractLayoutConnector /* implements PostLayoutListener */{
+
+    AbstractOrderedLayoutServerRpc rpc;
+
+    private LayoutClickEventHandler clickEventHandler = new LayoutClickEventHandler(
+            this) {
+
+        @Override
+        protected ComponentConnector getChildComponent(Element element) {
+            return Util.getConnectorForElement(getConnection(), getWidget(),
+                    element);
+        }
+
+        @Override
+        protected LayoutClickRpc getLayoutClickRPC() {
+            return rpc;
+        };
+
+    };
+
+    @Override
+    public void init() {
+        super.init();
+        rpc = RpcProxy.create(AbstractOrderedLayoutServerRpc.class, this);
+        getWidget().setLayoutManager(getLayoutManager());
+    }
+
+    @Override
+    public AbstractOrderedLayoutState getState() {
+        return (AbstractOrderedLayoutState) super.getState();
+    }
+
+    @Override
+    public VBoxLayout getWidget() {
+        return (VBoxLayout) super.getWidget();
+    }
+
+    /**
+     * For bookkeeping. Used to determine if extra calculations are needed for
+     * horizontal layout.
+     */
+    private HashSet<ComponentConnector> hasVerticalAlignment = new HashSet<ComponentConnector>();
+
+    /**
+     * For bookkeeping. Used to determine if extra calculations are needed for
+     * horizontal layout.
+     */
+    private HashSet<ComponentConnector> hasRelativeHeight = new HashSet<ComponentConnector>();
+
+    /**
+     * For bookkeeping. Used to determine if extra calculations are needed for
+     * horizontal layout.
+     */
+    private HashSet<ComponentConnector> hasExpandRatio = new HashSet<ComponentConnector>();
+
+    /**
+     * For bookkeeping. Used in extra calculations for horizontal layout.
+     */
+    private HashSet<Element> needsMeasure = new HashSet<Element>();
+
+    /**
+     * For bookkeeping. Used in extra calculations for horizontal layout.
+     */
+    // private HashMap<Element, Integer> childElementHeight = new
+    // HashMap<Element, Integer>();
+
+    /**
+     * For bookkeeping. Used in extra calculations for horizontal layout.
+     */
+    private HashMap<Element, Integer> childCaptionElementHeight = new HashMap<Element, Integer>();
+
+    public void updateCaption(ComponentConnector child) {
+        Slot slot = getWidget().getSlot(child);
+
+        String caption = child.getState().getCaption();
+        String iconUrl = child.getState().getIcon() != null ? child.getState()
+                .getIcon().getURL() : null;
+        List<String> styles = child.getState().getStyles();
+        String error = child.getState().getErrorMessage();
+        boolean showError = error != null;
+        if (child.getState() instanceof AbstractFieldState) {
+            AbstractFieldState abstractFieldState = (AbstractFieldState) child
+                    .getState();
+            showError = showError && !abstractFieldState.isHideErrors();
+        }
+        boolean required = false;
+        if (child instanceof AbstractFieldConnector) {
+            required = ((AbstractFieldConnector) child).isRequired();
+        }
+        boolean enabled = child.getState().isEnabled();
+
+        slot.setCaption(caption, iconUrl, styles, error, showError, required,
+                enabled);
+
+        slot.setRelativeWidth(child.isRelativeWidth());
+        slot.setRelativeHeight(child.isRelativeHeight());
+
+        if (slot.hasCaption()) {
+            CaptionPosition pos = slot.getCaptionPosition();
+            getLayoutManager().addElementResizeListener(
+                    slot.getCaptionElement(), slotCaptionResizeListener);
+            if (child.isRelativeHeight()
+                    && (pos == CaptionPosition.TOP || pos == CaptionPosition.BOTTOM)) {
+                getWidget().updateCaptionOffset(slot.getCaptionElement());
+            } else if (child.isRelativeWidth()
+                    && (pos == CaptionPosition.LEFT || pos == CaptionPosition.RIGHT)) {
+                getWidget().updateCaptionOffset(slot.getCaptionElement());
+            }
+        } else {
+            childCaptionElementHeight.remove(child.getWidget().getElement());
+        }
+
+        updateLayoutHeight();
+
+        if (needsExpand()) {
+            updateExpand();
+        }
+    }
+
+    @Override
+    public void onConnectorHierarchyChange(ConnectorHierarchyChangeEvent event) {
+        super.onConnectorHierarchyChange(event);
+
+        List<ComponentConnector> previousChildren = event.getOldChildren();
+        int currentIndex = 0;
+        VBoxLayout layout = getWidget();
+
+        for (ComponentConnector child : getChildComponents()) {
+            Slot slot = layout.getSlot(child);
+            if (slot.getParent() != layout) {
+                child.addStateChangeHandler(childStateChangeHandler);
+            }
+            layout.addOrMoveSlot(slot, currentIndex++);
+        }
+
+        for (ComponentConnector child : previousChildren) {
+            if (child.getParent() != this) {
+                Slot slot = layout.getSlot(child);
+                hasVerticalAlignment.remove(child);
+                hasRelativeHeight.remove(child);
+                hasExpandRatio.remove(child);
+                needsMeasure.remove(child.getWidget().getElement());
+                // childElementHeight.remove(child.getWidget().getElement());
+                childCaptionElementHeight
+                        .remove(child.getWidget().getElement());
+                getLayoutManager().removeElementResizeListener(
+                        child.getWidget().getElement(),
+                        childComponentResizeListener);
+                if (slot.hasCaption()) {
+                    getLayoutManager()
+                            .removeElementResizeListener(
+                                    slot.getCaptionElement(),
+                                    slotCaptionResizeListener);
+                }
+                if (slot.getSpacingElement() != null) {
+                    getLayoutManager().removeElementResizeListener(
+                            slot.getSpacingElement(), spacingResizeListener);
+                }
+                child.removeStateChangeHandler(childStateChangeHandler);
+                layout.removeSlot(child.getWidget());
+            }
+        }
+
+        // If some component is added/removed, we need to recalculate the expand
+        if (needsExpand()) {
+            updateExpand();
+        } else {
+            getWidget().clearExpand();
+        }
+
+    }
+
+    @Override
+    public void onStateChanged(StateChangeEvent stateChangeEvent) {
+        super.onStateChanged(stateChangeEvent);
+
+        clickEventHandler.handleEventHandlerRegistration();
+        getWidget().setMargin(new VMarginInfo(getState().getMarginsBitmask()));
+        getWidget().setSpacing(getState().isSpacing());
+
+        hasExpandRatio.clear();
+        hasVerticalAlignment.clear();
+        hasRelativeHeight.clear();
+        needsMeasure.clear();
+
+        boolean equalExpandRatio = getWidget().vertical ? !isUndefinedHeight()
+                : !isUndefinedWidth();
+        for (ComponentConnector child : getChildComponents()) {
+            double expandRatio = getState().getChildData().get(child)
+                    .getExpandRatio();
+            if (expandRatio > 0) {
+                equalExpandRatio = false;
+                break;
+            }
+        }
+
+        for (ComponentConnector child : getChildComponents()) {
+            Slot slot = getWidget().getSlot(child);
+
+            AlignmentInfo alignment = new AlignmentInfo(getState()
+                    .getChildData().get(child).getAlignmentBitmask());
+            slot.setAlignment(alignment);
+
+            double expandRatio = getState().getChildData().get(child)
+                    .getExpandRatio();
+            if (equalExpandRatio) {
+                expandRatio = 1;
+            } else if (expandRatio == 0) {
+                expandRatio = -1;
+            }
+            slot.setExpandRatio(expandRatio);
+
+            // Bookkeeping to identify special cases that need extra
+            // calculations
+            if (alignment.isVerticalCenter() || alignment.isBottom()) {
+                hasVerticalAlignment.add(child);
+            }
+
+            if (expandRatio > 0) {
+                hasExpandRatio.add(child);
+            }
+
+            // if (child.getState().isRelativeHeight()) {
+            // hasRelativeHeight.add(child);
+            // } else {
+            // needsMeasure.add(child.getWidget().getElement());
+            // }
+        }
+
+        updateAllSlotListeners();
+
+        updateLayoutHeight();
+    }
+
+    StateChangeHandler childStateChangeHandler = new StateChangeHandler() {
+        public void onStateChanged(StateChangeEvent stateChangeEvent) {
+
+            ComponentConnector child = (ComponentConnector) stateChangeEvent
+                    .getConnector();
+
+            // We need to update the slot size if the component size is changed
+            // to relative
+            Slot slot = getWidget().getSlot(child);
+            slot.setRelativeWidth(child.isRelativeWidth());
+            slot.setRelativeHeight(child.isRelativeHeight());
+
+            // For relative sized widgets, we need to set the caption offset
+            // if (slot.hasCaption()) {
+            // CaptionPosition pos = slot.getCaptionPosition();
+            // if (child.isRelativeHeight()
+            // && (pos == CaptionPosition.TOP || pos == CaptionPosition.BOTTOM))
+            // {
+            // getWidget().updateCaptionOffset(slot.getCaptionElement());
+            // } else if (child.isRelativeWidth()
+            // && (pos == CaptionPosition.LEFT || pos == CaptionPosition.RIGHT))
+            // {
+            // getWidget().updateCaptionOffset(slot.getCaptionElement());
+            // }
+            // }
+
+            updateSlotListeners(child);
+            // updateAllSlotListeners();
+
+            updateLayoutHeight();
+        }
+    };
+
+    private boolean needsFixedHeight() {
+        if (!getWidget().vertical
+                && isUndefinedHeight()
+                && (hasRelativeHeight.size() > 0 || (hasVerticalAlignment
+                        .size() > 0 && hasVerticalAlignment.size() < getChildren()
+                        .size()))) {
+            return true;
+        }
+        return false;
+    }
+
+    private boolean needsExpand() {
+        boolean canApplyExpand = (getWidget().vertical && !isUndefinedHeight())
+                || (!getWidget().vertical && !isUndefinedWidth());
+        return hasExpandRatio.size() > 0 && canApplyExpand;
+    }
+
+    private void updateAllSlotListeners() {
+        for (ComponentConnector child : getChildComponents()) {
+            updateSlotListeners(child);
+        }
+        // if (needsFixedHeight()) {
+        // getWidget().clearHeight();
+        // setLayoutHeightListener(true);
+        // getLayoutManager().setNeedsMeasure(AbstractBoxLayoutConnector.this);
+        // } else {
+        // setLayoutHeightListener(false);
+        // }
+    }
+
+    /**
+     * Add/remove necessary ElementResizeListeners for one slot. This should be
+     * called after each update to the slot's or it's widget.
+     */
+    private void updateSlotListeners(ComponentConnector child) {
+        Slot slot = getWidget().getSlot(child);
+
+        // Clear all possible listeners first
+        dontListen(slot.getWidget().getElement(), childComponentResizeListener);
+        if (slot.hasCaption()) {
+            dontListen(slot.getCaptionElement(), slotCaptionResizeListener);
+        }
+        if (slot.hasSpacing()) {
+            dontListen(slot.getSpacingElement(), spacingResizeListener);
+        }
+
+        // Add all necessary listeners
+        if (needsFixedHeight()) {
+            listen(slot.getWidget().getElement(), childComponentResizeListener);
+            if (slot.hasCaption()) {
+                listen(slot.getCaptionElement(), slotCaptionResizeListener);
+            }
+        } else if ((child.isRelativeHeight() || child.isRelativeWidth())
+                && slot.hasCaption()) {
+            // If the slot has caption, we need to listen for it's size changes
+            // in order to update the padding/margin offset for relative sized
+            // components
+            listen(slot.getCaptionElement(), slotCaptionResizeListener);
+        }
+
+        if (needsExpand()) {
+            listen(slot.getWidget().getElement(), childComponentResizeListener);
+            if (slot.hasSpacing()) {
+                listen(slot.getSpacingElement(), spacingResizeListener);
+            }
+        }
+
+        if (child.isRelativeHeight()) {
+            hasRelativeHeight.add(child);
+            needsMeasure.remove(child.getWidget().getElement());
+        } else {
+            hasRelativeHeight.remove(child);
+            needsMeasure.add(child.getWidget().getElement());
+        }
+
+    }
+
+    // public void postLayout() {
+    // if (needsFixedHeight()) {
+    // // Re-measure all elements that are available
+    // for (Element el : needsMeasure) {
+    // childElementHeight.put(el, getLayoutManager()
+    // .getOuterHeight(el));
+    //
+    // Element captionElement = el.getParentElement()
+    // .getFirstChildElement().cast();
+    // if (captionElement.getClassName().contains("v-caption")) {
+    // childCaptionElementHeight.put(el, getLayoutManager()
+    // .getOuterHeight(captionElement));
+    // }
+    // }
+    // // System.out.println("  ###  Child sizes: "
+    // // + childElementHeight.values().toString());
+    // // System.out.println("  ###  Caption sizes: "
+    // // + childCaptionElementHeight.values().toString());
+    //
+    // int height = getMaxHeight()
+    // + getLayoutManager().getBorderHeight(
+    // getWidget().getElement())
+    // + getLayoutManager().getPaddingHeight(
+    // getWidget().getElement());
+    // getWidget().getElement().getStyle().setHeight(height, Unit.PX);
+    // }
+    // }
+
+    // private ElementResizeListener layoutResizeListener = new
+    // ElementResizeListener() {
+    // public void onElementResize(ElementResizeEvent e) {
+    // updateLayoutHeight();
+    // if (needsExpand() && (isUndefinedHeight() || isUndefinedWidth())) {
+    // updateExpand();
+    // }
+    // }
+    // };
+
+    private ElementResizeListener slotCaptionResizeListener = new ElementResizeListener() {
+        public void onElementResize(ElementResizeEvent e) {
+
+            // Get all needed element references
+            Element captionElement = (Element) e.getElement().cast();
+
+            // Caption position determines if the widget element is the first or
+            // last child inside the caption wrap
+            CaptionPosition pos = getWidget().getCaptionPositionFromElement(
+                    (Element) captionElement.getParentElement().cast());
+
+            // The default is the last child
+            Element widgetElement = captionElement.getParentElement()
+                    .getLastChild().cast();
+
+            // ...but if caption position is bottom or right, the widget is the
+            // first child
+            if (pos == CaptionPosition.BOTTOM || pos == CaptionPosition.RIGHT) {
+                widgetElement = captionElement.getParentElement()
+                        .getFirstChildElement().cast();
+            }
+
+            if (captionElement == widgetElement) {
+                // Caption element already detached
+                dontListen(captionElement, slotCaptionResizeListener);
+                childCaptionElementHeight.remove(widgetElement);
+                return;
+            }
+
+            String widgetWidth = widgetElement.getStyle().getWidth();
+            String widgetHeight = widgetElement.getStyle().getHeight();
+
+            if (widgetHeight.endsWith("%")
+                    && (pos == CaptionPosition.TOP || pos == CaptionPosition.BOTTOM)) {
+                getWidget().updateCaptionOffset(captionElement);
+            } else if (widgetWidth.endsWith("%")
+                    && (pos == CaptionPosition.LEFT || pos == CaptionPosition.RIGHT)) {
+                getWidget().updateCaptionOffset(captionElement);
+            }
+
+            int h = getLayoutManager().getOuterHeight(captionElement)
+                    - getLayoutManager().getMarginHeight(captionElement);
+            childCaptionElementHeight.put(widgetElement, h);
+
+            // if (needsFixedHeight()) {
+            // getWidget().clearHeight();
+            // getLayoutManager().setNeedsMeasure(
+            // AbstractBoxLayoutConnector.this);
+            // }
+
+            updateLayoutHeight();
+
+            if (needsExpand()) {
+                updateExpand();
+            }
+        }
+    };
+
+    private ElementResizeListener childComponentResizeListener = new ElementResizeListener() {
+        public void onElementResize(ElementResizeEvent e) {
+            // int h = getLayoutManager().getOuterHeight(e.getElement());
+            // childElementHeight.put((Element) e.getElement().cast(), h);
+            updateLayoutHeight();
+
+            if (needsExpand()) {
+                updateExpand();
+            }
+        }
+    };
+
+    private ElementResizeListener spacingResizeListener = new ElementResizeListener() {
+        public void onElementResize(ElementResizeEvent e) {
+            if (needsExpand()) {
+                updateExpand();
+            }
+        }
+    };
+
+    private void updateLayoutHeight() {
+        if (needsFixedHeight()) {
+            int h = getMaxHeight();
+            h += getLayoutManager().getBorderHeight(getWidget().getElement())
+                    + getLayoutManager().getPaddingHeight(
+                            getWidget().getElement());
+            getWidget().getElement().getStyle().setHeight(h, Unit.PX);
+            getLayoutManager().setNeedsMeasure(this);
+        }
+    }
+
+    private void updateExpand() {
+        // System.out.println("All sizes: "
+        // + childElementHeight.values().toString() + " - Caption sizes: "
+        // + childCaptionElementHeight.values().toString());
+        getWidget().updateExpand();
+    }
+
+    private int getMaxHeight() {
+        int highestNonRelative = -1;
+        int highestRelative = -1;
+
+        for (ComponentConnector child : getChildComponents()) {
+            // TODO would be more efficient to measure the slot element if both
+            // caption and child widget elements need to be measured. Keeping
+            // track of what to measure is the most difficult part of this
+            // layout.
+            Element el = child.getWidget().getElement();
+            CaptionPosition pos = getWidget().getCaptionPositionFromElement(
+                    (Element) el.getParentElement().cast());
+            if (needsMeasure.contains(el)) {
+                int h = getLayoutManager().getOuterHeight(el);
+                String sHeight = el.getStyle().getHeight();
+                // Only add the caption size to the height of the slot if
+                // coption position is top or bottom
+                if (childCaptionElementHeight.containsKey(el)
+                        && (sHeight == null || !sHeight.endsWith("%"))
+                        && (pos == CaptionPosition.TOP || pos == CaptionPosition.BOTTOM)) {
+                    h += childCaptionElementHeight.get(el);
+                }
+                if (h > highestNonRelative) {
+                    highestNonRelative = h;
+                }
+            } else {
+                int h = getLayoutManager().getOuterHeight(el);
+                if (childCaptionElementHeight.containsKey(el)
+                        && (pos == CaptionPosition.TOP || pos == CaptionPosition.BOTTOM)) {
+                    h += childCaptionElementHeight.get(el);
+                }
+                if (h > highestRelative) {
+                    highestRelative = h;
+                }
+            }
+        }
+        return highestNonRelative > -1 ? highestNonRelative : highestRelative;
+    }
+
+    @Override
+    public void onUnregister() {
+        // Cleanup all ElementResizeListeners
+
+        // dontListen(getWidget().getElement(), layoutResizeListener);
+
+        for (ComponentConnector child : getChildComponents()) {
+            Slot slot = getWidget().getSlot(child);
+            if (slot.hasCaption()) {
+                dontListen(slot.getCaptionElement(), slotCaptionResizeListener);
+            }
+
+            if (slot.getSpacingElement() != null) {
+                dontListen(slot.getSpacingElement(), spacingResizeListener);
+            }
+
+            dontListen(slot.getWidget().getElement(),
+                    childComponentResizeListener);
+        }
+
+        super.onUnregister();
+    }
+
+    // private void setLayoutHeightListener(boolean add) {
+    // if (add) {
+    // listen(getWidget().getElement(), layoutResizeListener);
+    // } else {
+    // dontListen(getWidget().getElement(), layoutResizeListener);
+    // if (!needsExpand()) {
+    // System.out.println("Clearing element sizes");
+    // childElementHeight.clear();
+    // childCaptionElementHeight.clear();
+    // }
+    // }
+    // }
+
+    /*
+     * Convenience methods
+     */
+
+    private void listen(Element el, ElementResizeListener listener) {
+        getLayoutManager().addElementResizeListener(el, listener);
+    }
+
+    private void dontListen(Element el, ElementResizeListener listener) {
+        getLayoutManager().removeElementResizeListener(el, listener);
+    }
+
+}
diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/orderedlayout/HorizontalBoxLayoutConnector.java b/client/src/com/vaadin/terminal/gwt/client/ui/orderedlayout/HorizontalBoxLayoutConnector.java
new file mode 100644 (file)
index 0000000..d18ea8a
--- /dev/null
@@ -0,0 +1,19 @@
+/* 
+@VaadinApache2LicenseForJavaFiles@
+ */
+package com.vaadin.terminal.gwt.client.ui.orderedlayout;
+
+import com.vaadin.shared.ui.Connect;
+import com.vaadin.shared.ui.Connect.LoadStyle;
+import com.vaadin.ui.HorizontalLayout;
+
+@Connect(value = HorizontalLayout.class, loadStyle = LoadStyle.EAGER)
+public class HorizontalBoxLayoutConnector extends AbstractBoxLayoutConnector {
+
+    @Override
+    public void init() {
+        super.init();
+        getWidget().setVertical(false);
+    }
+
+}
index 195622854d965b2e1542abd3df2b38b06ee39091..f22b558afdf0d045f53d6149f36360d5815705ea 100644 (file)
  */
 package com.vaadin.terminal.gwt.client.ui.orderedlayout;
 
-import com.vaadin.shared.ui.Connect;
-import com.vaadin.shared.ui.Connect.LoadStyle;
-import com.vaadin.ui.HorizontalLayout;
 
-@Connect(value = HorizontalLayout.class, loadStyle = LoadStyle.EAGER)
+//@Connect(value = HorizontalLayout.class, loadStyle = LoadStyle.EAGER)
 public class HorizontalLayoutConnector extends AbstractOrderedLayoutConnector {
 
     @Override
diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/orderedlayout/VBoxLayout.java b/client/src/com/vaadin/terminal/gwt/client/ui/orderedlayout/VBoxLayout.java
new file mode 100644 (file)
index 0000000..4e84708
--- /dev/null
@@ -0,0 +1,756 @@
+/* 
+@VaadinApache2LicenseForJavaFiles@
+ */
+package com.vaadin.terminal.gwt.client.ui.orderedlayout;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import com.google.gwt.dom.client.Node;
+import com.google.gwt.dom.client.Style;
+import com.google.gwt.dom.client.Style.Unit;
+import com.google.gwt.regexp.shared.MatchResult;
+import com.google.gwt.regexp.shared.RegExp;
+import com.google.gwt.user.client.DOM;
+import com.google.gwt.user.client.Element;
+import com.google.gwt.user.client.Event;
+import com.google.gwt.user.client.ui.FlowPanel;
+import com.google.gwt.user.client.ui.SimplePanel;
+import com.google.gwt.user.client.ui.UIObject;
+import com.google.gwt.user.client.ui.Widget;
+import com.vaadin.shared.ui.AlignmentInfo;
+import com.vaadin.shared.ui.VMarginInfo;
+import com.vaadin.terminal.gwt.client.ComponentConnector;
+import com.vaadin.terminal.gwt.client.LayoutManager;
+
+public class VBoxLayout extends FlowPanel {
+
+    public static final String CLASSNAME = "v-boxlayout";
+
+    private static final String ALIGN_CLASS_PREFIX = "v-align-";
+
+    protected boolean spacing = false;
+
+    protected boolean vertical = true;
+
+    protected boolean definedHeight = false;
+
+    private Map<Widget, Slot> widgetToSlot = new HashMap<Widget, Slot>();
+
+    private LayoutManager layoutManager;
+
+    public VBoxLayout() {
+        setStyleName(CLASSNAME);
+        setVertical(true);
+    }
+
+    public void setVertical(boolean isVertical) {
+        vertical = isVertical;
+        if (vertical) {
+            addStyleName("v-vertical");
+            removeStyleName("v-horizontal");
+        } else {
+            addStyleName("v-horizontal");
+            removeStyleName("v-vertical");
+        }
+    }
+
+    public void addOrMoveSlot(Slot slot, int index) {
+        if (slot.getParent() == this) {
+            int currentIndex = getWidgetIndex(slot);
+            if (index == currentIndex) {
+                return;
+            }
+        }
+        insert(slot, index);
+    }
+
+    @Override
+    protected void insert(Widget child, Element container, int beforeIndex,
+            boolean domInsert) {
+        // Validate index; adjust if the widget is already a child of this
+        // panel.
+        beforeIndex = adjustIndex(child, beforeIndex);
+
+        // Detach new child.
+        child.removeFromParent();
+
+        // Logical attach.
+        getChildren().insert(child, beforeIndex);
+
+        // Physical attach.
+        container = expandWrapper != null ? expandWrapper : getElement();
+        if (domInsert) {
+            DOM.insertChild(container, child.getElement(),
+                    spacing ? beforeIndex * 2 : beforeIndex);
+        } else {
+            DOM.appendChild(container, child.getElement());
+        }
+
+        // Adopt.
+        adopt(child);
+    }
+
+    public Slot removeSlot(Widget widget) {
+        Slot slot = widgetToSlot.get(widget);
+        remove(slot);
+        widgetToSlot.remove(widget);
+        return slot;
+    }
+
+    public Slot getSlot(ComponentConnector connector) {
+        Slot slot = widgetToSlot.get(connector.getWidget());
+        if (slot == null) {
+            slot = new Slot(connector);
+            widgetToSlot.put(connector.getWidget(), slot);
+        }
+        return slot;
+    }
+
+    public enum CaptionPosition {
+        TOP, RIGHT, BOTTOM, LEFT
+    }
+
+    protected class Slot extends SimplePanel {
+
+        private ComponentConnector connector;
+
+        private Element spacer;
+
+        private Element captionWrap;
+        private Element caption;
+        private Element captionText;
+        private Icon icon;
+        private Element errorIcon;
+        private Element requiredIcon;
+
+        // Caption is placed after component unless there is some part which
+        // moves it above.
+        private CaptionPosition captionPosition = CaptionPosition.RIGHT;
+
+        private AlignmentInfo alignment;
+        private double expandRatio = -1;
+
+        public Slot(ComponentConnector connector) {
+            this.connector = connector;
+            setWidget(connector.getWidget());
+            setStylePrimaryName("v-slot");
+        }
+
+        public AlignmentInfo getAlignment() {
+            return alignment;
+        }
+
+        public void setAlignment(AlignmentInfo alignment) {
+            this.alignment = alignment;
+
+            if (alignment.isHorizontalCenter()) {
+                addStyleName(ALIGN_CLASS_PREFIX + "center");
+                removeStyleName(ALIGN_CLASS_PREFIX + "right");
+            } else if (alignment.isRight()) {
+                addStyleName(ALIGN_CLASS_PREFIX + "right");
+                removeStyleName(ALIGN_CLASS_PREFIX + "center");
+            } else {
+                removeStyleName(ALIGN_CLASS_PREFIX + "right");
+                removeStyleName(ALIGN_CLASS_PREFIX + "center");
+            }
+            if (alignment.isVerticalCenter()) {
+                addStyleName(ALIGN_CLASS_PREFIX + "middle");
+                removeStyleName(ALIGN_CLASS_PREFIX + "bottom");
+            } else if (alignment.isBottom()) {
+                addStyleName(ALIGN_CLASS_PREFIX + "bottom");
+                removeStyleName(ALIGN_CLASS_PREFIX + "middle");
+            } else {
+                removeStyleName(ALIGN_CLASS_PREFIX + "middle");
+                removeStyleName(ALIGN_CLASS_PREFIX + "bottom");
+            }
+        }
+
+        public void setExpandRatio(double expandRatio) {
+            this.expandRatio = expandRatio;
+        }
+
+        public double getExpandRatio() {
+            return expandRatio;
+        }
+
+        public void setSpacing(boolean spacing) {
+            if (spacing && spacer == null) {
+                spacer = DOM.createDiv();
+                spacer.addClassName("v-spacing");
+                getElement().getParentElement().insertBefore(spacer,
+                        getElement());
+            } else if (!spacing && spacer != null) {
+                spacer.removeFromParent();
+                spacer = null;
+            }
+        }
+
+        public Element getSpacingElement() {
+            return spacer;
+        }
+
+        public boolean hasSpacing() {
+            return getSpacingElement() != null;
+        }
+
+        protected int getSpacingSize(boolean vertical) {
+            if (spacer == null) {
+                return 0;
+            }
+
+            if (layoutManager != null) {
+                if (vertical) {
+                    return layoutManager.getOuterHeight(spacer);
+                } else {
+                    return layoutManager.getOuterWidth(spacer);
+                }
+            }
+            // TODO place for optimization (in expense of theme
+            // flexibility): only measure one of the elements and cache the
+            // value
+            return vertical ? spacer.getOffsetHeight() : spacer
+                    .getOffsetWidth();
+            // }
+        }
+
+        public void setCaptionPosition(CaptionPosition captionPosition) {
+            if (caption == null) {
+                return;
+            }
+
+            captionWrap.removeClassName("v-caption-on-"
+                    + this.captionPosition.name().toLowerCase());
+
+            this.captionPosition = captionPosition;
+            if (captionPosition == CaptionPosition.BOTTOM
+                    || captionPosition == CaptionPosition.RIGHT) {
+                captionWrap.appendChild(caption);
+            } else {
+                captionWrap.insertFirst(caption);
+            }
+
+            captionWrap.addClassName("v-caption-on-"
+                    + captionPosition.name().toLowerCase());
+        }
+
+        public CaptionPosition getCaptionPosition() {
+            return captionPosition;
+        }
+
+        // TODO refactor VCaption and use that instead: creates a tight coupling
+        // between this layout and Vaadin, but it's already coupled
+        public void setCaption(String captionText, String iconUrl,
+                List<String> styles, String error, boolean showError,
+                boolean required, boolean enabled) {
+
+            // TODO place for optimization: check if any of these have changed
+            // since last time, and only run those changes
+
+            // Caption wrappers
+            if (captionText != null || iconUrl != null || error != null
+                    || required) {
+                if (caption == null) {
+                    caption = DOM.createDiv();
+                    captionWrap = DOM.createDiv();
+                    captionWrap.addClassName("v");
+                    captionWrap.addClassName("v-has-caption");
+                    getElement().appendChild(captionWrap);
+                    captionWrap.appendChild(getWidget().getElement());
+                }
+            } else if (caption != null) {
+                getElement().appendChild(getWidget().getElement());
+                captionWrap.removeFromParent();
+                caption = null;
+                captionWrap = null;
+            }
+
+            // Caption text
+            if (captionText != null) {
+                if (this.captionText == null) {
+                    this.captionText = DOM.createSpan();
+                    this.captionText.addClassName("v-captiontext");
+                    caption.appendChild(this.captionText);
+                }
+                if (captionText.trim().equals("")) {
+                    this.captionText.setInnerHTML("&nbsp;");
+                } else {
+                    this.captionText.setInnerText(captionText);
+                }
+            } else if (this.captionText != null) {
+                this.captionText.removeFromParent();
+                this.captionText = null;
+            }
+
+            // Icon
+            if (iconUrl != null) {
+                if (icon == null) {
+                    icon = new Icon();
+                    // icon = DOM.createImg();
+                    // icon.setClassName("v-icon");
+                    caption.insertFirst(icon.getElement());
+                }
+                // icon.setAttribute("src", iconUrl);
+                icon.setUri(iconUrl);
+            } else if (icon != null) {
+                icon.getElement().removeFromParent();
+                icon = null;
+            }
+
+            // Required
+            if (required) {
+                if (requiredIcon == null) {
+                    requiredIcon = DOM.createSpan();
+                    // TODO decide something better
+                    requiredIcon.setInnerHTML("*");
+                    requiredIcon.setClassName("v-required-field-indicator");
+                }
+                caption.appendChild(requiredIcon);
+            } else if (requiredIcon != null) {
+                requiredIcon.removeFromParent();
+                requiredIcon = null;
+            }
+
+            // Error
+            if (error != null && showError) {
+                if (errorIcon == null) {
+                    errorIcon = DOM.createSpan();
+                    errorIcon.setClassName("v-errorindicator");
+                }
+                caption.appendChild(errorIcon);
+            } else if (errorIcon != null) {
+                errorIcon.removeFromParent();
+                errorIcon = null;
+            }
+
+            if (caption != null) {
+                // Styles
+                caption.setClassName("v-caption");
+
+                if (styles != null) {
+                    for (String style : styles) {
+                        caption.addClassName("v-caption-" + style);
+                    }
+                }
+
+                if (enabled) {
+                    caption.removeClassName("v-disabled");
+                } else {
+                    caption.addClassName("v-disabled");
+                }
+
+                // Caption position
+                if (captionText != null || iconUrl != null) {
+                    setCaptionPosition(CaptionPosition.TOP);
+                } else {
+                    setCaptionPosition(CaptionPosition.RIGHT);
+                }
+            }
+
+            // TODO theme flexibility: add extra styles to captionWrap as well?
+
+        }
+
+        public boolean hasCaption() {
+            return caption != null;
+        }
+
+        public Element getCaptionElement() {
+            return caption;
+        }
+
+        public void setRelativeWidth(boolean relativeWidth) {
+            updateRelativeSize(relativeWidth, "width");
+        }
+
+        public void setRelativeHeight(boolean relativeHeight) {
+            updateRelativeSize(relativeHeight, "height");
+        }
+
+        private void updateRelativeSize(boolean isRelativeSize, String direction) {
+            if (isRelativeSize && hasCaption()) {
+                captionWrap.getStyle().setProperty(
+                        direction,
+                        getWidget().getElement().getStyle()
+                                .getProperty(direction));
+                captionWrap.addClassName("v-has-" + direction);
+            } else if (hasCaption()) {
+                if (direction.equals("height")) {
+                    captionWrap.getStyle().clearHeight();
+                } else {
+                    captionWrap.getStyle().clearWidth();
+                }
+                captionWrap.removeClassName("v-has-" + direction);
+                captionWrap.getStyle().clearPaddingTop();
+                captionWrap.getStyle().clearPaddingRight();
+                captionWrap.getStyle().clearPaddingBottom();
+                captionWrap.getStyle().clearPaddingLeft();
+                caption.getStyle().clearMarginTop();
+                caption.getStyle().clearMarginRight();
+                caption.getStyle().clearMarginBottom();
+                caption.getStyle().clearMarginLeft();
+            }
+        }
+
+        @Override
+        public void onBrowserEvent(Event event) {
+            super.onBrowserEvent(event);
+            if (DOM.eventGetType(event) == Event.ONLOAD
+                    && icon.getElement() == DOM.eventGetTarget(event)) {
+                if (layoutManager != null) {
+                    layoutManager.layoutLater();
+                } else {
+                    updateCaptionOffset(caption);
+                }
+            }
+        }
+
+        @Override
+        protected Element getContainerElement() {
+            if (captionWrap == null) {
+                return getElement();
+            } else {
+                return captionWrap;
+            }
+        }
+
+        @Override
+        protected void onDetach() {
+            if (spacer != null) {
+                spacer.removeFromParent();
+            }
+            super.onDetach();
+        }
+
+        @Override
+        protected void onAttach() {
+            super.onAttach();
+            if (spacer != null) {
+                getElement().getParentElement().insertBefore(spacer,
+                        getElement());
+            }
+        }
+
+    }
+
+    protected class Icon extends UIObject {
+        public static final String CLASSNAME = "v-icon";
+        private String myUrl;
+
+        public Icon() {
+            setElement(DOM.createImg());
+            DOM.setElementProperty(getElement(), "alt", "");
+            setStyleName(CLASSNAME);
+        }
+
+        public void setUri(String url) {
+            if (!url.equals(myUrl)) {
+                /*
+                 * Start sinking onload events, widgets responsibility to react.
+                 * We must do this BEFORE we set src as IE fires the event
+                 * immediately if the image is found in cache (#2592).
+                 */
+                sinkEvents(Event.ONLOAD);
+
+                DOM.setElementProperty(getElement(), "src", url);
+                myUrl = url;
+            }
+        }
+
+    }
+
+    void setLayoutManager(LayoutManager manager) {
+        layoutManager = manager;
+    }
+
+    private static final RegExp captionPositionRegexp = RegExp
+            .compile("v-caption-on-(\\S+)");
+
+    CaptionPosition getCaptionPositionFromElement(Element captionWrap) {
+        // Get caption position from the classname
+        MatchResult matcher = captionPositionRegexp.exec(captionWrap
+                .getClassName());
+        if (matcher == null || matcher.getGroupCount() < 2) {
+            return CaptionPosition.TOP;
+        }
+        String captionClass = matcher.getGroup(1);
+        CaptionPosition captionPosition = CaptionPosition.valueOf(
+                CaptionPosition.class, captionClass.toUpperCase());
+        return captionPosition;
+    }
+
+    void updateCaptionOffset(Element caption) {
+
+        Element captionWrap = caption.getParentElement().cast();
+
+        Style captionWrapStyle = captionWrap.getStyle();
+        captionWrapStyle.clearPaddingTop();
+        captionWrapStyle.clearPaddingRight();
+        captionWrapStyle.clearPaddingBottom();
+        captionWrapStyle.clearPaddingLeft();
+
+        Style captionStyle = caption.getStyle();
+        captionStyle.clearMarginTop();
+        captionStyle.clearMarginRight();
+        captionStyle.clearMarginBottom();
+        captionStyle.clearMarginLeft();
+
+        // Get caption position from the classname
+        CaptionPosition captionPosition = getCaptionPositionFromElement(captionWrap);
+
+        if (captionPosition == CaptionPosition.LEFT
+                || captionPosition == CaptionPosition.RIGHT) {
+            int captionWidth;
+            if (layoutManager != null) {
+                captionWidth = layoutManager.getOuterWidth(caption)
+                        - layoutManager.getMarginWidth(caption);
+            } else {
+                captionWidth = caption.getOffsetWidth();
+            }
+            if (captionWidth > 0) {
+                if (captionPosition == CaptionPosition.LEFT) {
+                    captionWrapStyle.setPaddingLeft(captionWidth, Unit.PX);
+                    captionStyle.setMarginLeft(-captionWidth, Unit.PX);
+                } else {
+                    captionWrapStyle.setPaddingRight(captionWidth, Unit.PX);
+                    captionStyle.setMarginRight(-captionWidth, Unit.PX);
+                }
+            }
+        }
+        if (captionPosition == CaptionPosition.TOP
+                || captionPosition == CaptionPosition.BOTTOM) {
+            int captionHeight;
+            if (layoutManager != null) {
+                captionHeight = layoutManager.getOuterHeight(caption)
+                        - layoutManager.getMarginHeight(caption);
+            } else {
+                captionHeight = caption.getOffsetHeight();
+            }
+            if (captionHeight > 0) {
+                if (captionPosition == CaptionPosition.TOP) {
+                    captionWrapStyle.setPaddingTop(captionHeight, Unit.PX);
+                    captionStyle.setMarginTop(-captionHeight, Unit.PX);
+                } else {
+                    captionWrapStyle.setPaddingBottom(captionHeight, Unit.PX);
+                    captionStyle.setMarginBottom(-captionHeight, Unit.PX);
+                }
+            }
+        }
+    }
+
+    private void toggleStyleName(String name, boolean enabled) {
+        if (enabled) {
+            addStyleName(name);
+        } else {
+            removeStyleName(name);
+        }
+    }
+
+    void setMargin(VMarginInfo marginInfo) {
+        toggleStyleName("v-margin-top", marginInfo.hasTop());
+        toggleStyleName("v-margin-right", marginInfo.hasRight());
+        toggleStyleName("v-margin-bottom", marginInfo.hasBottom());
+        toggleStyleName("v-margin-left", marginInfo.hasLeft());
+    }
+
+    protected void setSpacing(boolean spacingEnabled) {
+        spacing = spacingEnabled;
+        for (Slot slot : widgetToSlot.values()) {
+            if (getWidgetIndex(slot) > 0) {
+                slot.setSpacing(spacingEnabled);
+            }
+        }
+    }
+
+    private void recalculateExpands() {
+        double total = 0;
+        for (Slot slot : widgetToSlot.values()) {
+            if (slot.getExpandRatio() > -1) {
+                total += slot.getExpandRatio();
+            } else {
+                if (vertical) {
+                    slot.getElement().getStyle().clearHeight();
+                } else {
+                    slot.getElement().getStyle().clearWidth();
+                }
+            }
+        }
+        for (Slot slot : widgetToSlot.values()) {
+            if (slot.getExpandRatio() > -1) {
+                if (vertical) {
+                    slot.setHeight((100 * (slot.getExpandRatio() / total))
+                            + "%");
+                    if (slot.connector.isRelativeHeight()) {
+                        layoutManager.setNeedsMeasure(slot.connector);
+                    }
+                } else {
+                    slot.setWidth((100 * (slot.getExpandRatio() / total)) + "%");
+                    if (slot.connector.isRelativeWidth()) {
+                        layoutManager.setNeedsMeasure(slot.connector);
+                    }
+                }
+            }
+        }
+    }
+
+    private Element expandWrapper;
+
+    void clearExpand() {
+        if (expandWrapper != null) {
+            for (; expandWrapper.getChildCount() > 0;) {
+                Element el = expandWrapper.getChild(0).cast();
+                getElement().appendChild(el);
+                if (vertical) {
+                    el.getStyle().clearHeight();
+                    el.getStyle().clearMarginTop();
+                } else {
+                    el.getStyle().clearWidth();
+                    el.getStyle().clearMarginLeft();
+                }
+            }
+            expandWrapper.removeFromParent();
+            expandWrapper = null;
+        }
+    }
+
+    public void updateExpand() {
+        boolean isExpanding = false;
+        for (Widget slot : getChildren()) {
+            if (((Slot) slot).getExpandRatio() > -1) {
+                isExpanding = true;
+            } else {
+                if (vertical) {
+                    slot.getElement().getStyle().clearHeight();
+                } else {
+                    slot.getElement().getStyle().clearWidth();
+                }
+            }
+            slot.getElement().getStyle().clearMarginLeft();
+            slot.getElement().getStyle().clearMarginTop();
+        }
+
+        if (isExpanding) {
+            if (expandWrapper == null) {
+                expandWrapper = DOM.createDiv();
+                expandWrapper.setClassName("v-expand");
+                for (; getElement().getChildCount() > 0;) {
+                    Node el = getElement().getChild(0);
+                    expandWrapper.appendChild(el);
+                }
+                getElement().appendChild(expandWrapper);
+            }
+
+            int totalSize = 0;
+            for (Widget w : getChildren()) {
+                Slot slot = (Slot) w;
+                if (slot.getExpandRatio() == -1) {
+                    if (layoutManager != null) {
+                        // TODO check caption position
+                        if (vertical) {
+                            int size = layoutManager.getOuterHeight(slot
+                                    .getWidget().getElement())
+                                    - layoutManager.getMarginHeight(slot
+                                            .getWidget().getElement());
+                            if (slot.hasCaption()) {
+                                size += layoutManager.getOuterHeight(slot
+                                        .getCaptionElement())
+                                        - layoutManager.getMarginHeight(slot
+                                                .getCaptionElement());
+                            }
+                            if (size > 0) {
+                                totalSize += size;
+                            }
+                        } else {
+                            int max = -1;
+                            max = layoutManager.getOuterWidth(slot.getWidget()
+                                    .getElement())
+                                    - layoutManager.getMarginWidth(slot
+                                            .getWidget().getElement());
+                            if (slot.hasCaption()) {
+                                int max2 = layoutManager.getOuterWidth(slot
+                                        .getCaptionElement())
+                                        - layoutManager.getMarginWidth(slot
+                                                .getCaptionElement());
+                                max = Math.max(max, max2);
+                            }
+                            if (max > 0) {
+                                totalSize += max;
+                            }
+                        }
+                    } else {
+                        totalSize += vertical ? slot.getOffsetHeight() : slot
+                                .getOffsetWidth();
+                    }
+                }
+                // TODO fails in Opera, always returns 0
+                int spacingSize = slot.getSpacingSize(vertical);
+                if (spacingSize > 0) {
+                    totalSize += spacingSize;
+                }
+            }
+
+            // When we set the margin to the first child, we don't need
+            // overflow:hidden in the layout root element, since the wrapper
+            // would otherwise be placed outside of the layout root element
+            // and block events on elements below it.
+            if (vertical) {
+                expandWrapper.getStyle().setPaddingTop(totalSize, Unit.PX);
+                expandWrapper.getFirstChildElement().getStyle()
+                        .setMarginTop(-totalSize, Unit.PX);
+            } else {
+                expandWrapper.getStyle().setPaddingLeft(totalSize, Unit.PX);
+                expandWrapper.getFirstChildElement().getStyle()
+                        .setMarginLeft(-totalSize, Unit.PX);
+            }
+
+            recalculateExpands();
+        }
+    }
+
+    public void recalculateLayoutHeight() {
+        // Only needed if a horizontal layout is undefined high, and contains
+        // relative height children or vertical alignments
+        if (vertical || definedHeight) {
+            return;
+        }
+
+        boolean hasRelativeHeightChildren = false;
+        boolean hasVAlign = false;
+
+        for (Widget slot : getChildren()) {
+            Widget widget = ((Slot) slot).getWidget();
+            String h = widget.getElement().getStyle().getHeight();
+            if (h != null && h.indexOf("%") > -1) {
+                hasRelativeHeightChildren = true;
+            }
+            AlignmentInfo a = ((Slot) slot).getAlignment();
+            if (a != null && (a.isVerticalCenter() || a.isBottom())) {
+                hasVAlign = true;
+            }
+        }
+
+        if (hasRelativeHeightChildren || hasVAlign) {
+            int newHeight;
+            if (layoutManager != null) {
+                newHeight = layoutManager.getOuterHeight(getElement())
+                        - layoutManager.getMarginHeight(getElement());
+            } else {
+                newHeight = getElement().getOffsetHeight();
+            }
+            VBoxLayout.this.getElement().getStyle()
+                    .setHeight(newHeight, Unit.PX);
+        }
+
+    }
+
+    void clearHeight() {
+        getElement().getStyle().clearHeight();
+    }
+
+    @Override
+    public void setHeight(String height) {
+        super.setHeight(height);
+        definedHeight = (height != null && !"".equals(height));
+    }
+}
diff --git a/client/src/com/vaadin/terminal/gwt/client/ui/orderedlayout/VerticalBoxLayoutConnector.java b/client/src/com/vaadin/terminal/gwt/client/ui/orderedlayout/VerticalBoxLayoutConnector.java
new file mode 100644 (file)
index 0000000..a480a79
--- /dev/null
@@ -0,0 +1,19 @@
+/* 
+@VaadinApache2LicenseForJavaFiles@
+ */
+package com.vaadin.terminal.gwt.client.ui.orderedlayout;
+
+import com.vaadin.shared.ui.Connect;
+import com.vaadin.shared.ui.Connect.LoadStyle;
+import com.vaadin.ui.VerticalLayout;
+
+@Connect(value = VerticalLayout.class, loadStyle = LoadStyle.EAGER)
+public class VerticalBoxLayoutConnector extends AbstractBoxLayoutConnector {
+
+    @Override
+    public void init() {
+        super.init();
+        getWidget().setVertical(true);
+    }
+
+}
index 441ba9c156bc97f72d89c341e2ba04a9ca2ccecf..c53494775c8ea0909ce170c044e949dc6a74af11 100644 (file)
  */
 package com.vaadin.terminal.gwt.client.ui.orderedlayout;
 
-import com.vaadin.shared.ui.Connect;
-import com.vaadin.shared.ui.Connect.LoadStyle;
-import com.vaadin.ui.VerticalLayout;
 
-@Connect(value = VerticalLayout.class, loadStyle = LoadStyle.EAGER)
+//@Connect(value = VerticalLayout.class, loadStyle = LoadStyle.EAGER)
 public class VerticalLayoutConnector extends AbstractOrderedLayoutConnector {
 
     @Override