From: Joonas Lehtinen Date: Thu, 10 Jul 2008 14:21:18 +0000 (+0000) Subject: Major changes in OrderedLayout X-Git-Tag: 6.7.0.beta1~4447 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=1a7c1d14ca7461f010d7940f1c1678424098b43e;p=vaadin-framework.git Major changes in OrderedLayout These changes include: - Redesigned IOrderedLayout DOM-structure - Changes OrderedLayout Horizontal mode constructor defaults to 100% wide (this has been practical default since Millstone 3.0 as undefined width have been broken in horizontal mode) - Ensured appearance of error exclamation marks in captions without required status, icon or caption text - Closes #1911 : Optimize IOrderedLayout dom-structure by removing intermediate margin-div - Closes #1915 : IOrderedLayout caculates right margin incorrectly in horizontal mode when width is not set - Closes #1921 : IOrderedLayout needs cross-browser DOM structures - Probably introduces many new regressions All-in-all OrderedLayout is still work in progress and should not yet be included in 5.2.x releases svn changeset:5079/svn branch:trunk --- diff --git a/src/com/itmill/toolkit/terminal/gwt/client/Caption.java b/src/com/itmill/toolkit/terminal/gwt/client/Caption.java index eec807edfa..a2a33a39d8 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/Caption.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/Caption.java @@ -113,9 +113,7 @@ public class Caption extends HTML { isEmpty = false; if (errorIndicatorElement == null) { errorIndicatorElement = DOM.createDiv(); - if (Util.isIE()) { - DOM.setInnerHTML(errorIndicatorElement, " "); - } + DOM.setInnerHTML(errorIndicatorElement, " "); DOM.setElementProperty(errorIndicatorElement, "className", "i-errorindicator"); DOM.appendChild(getElement(), errorIndicatorElement); diff --git a/src/com/itmill/toolkit/terminal/gwt/client/ui/IOrderedLayout.java b/src/com/itmill/toolkit/terminal/gwt/client/ui/IOrderedLayout.java index 34cc6fda40..211410ac3b 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/ui/IOrderedLayout.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/ui/IOrderedLayout.java @@ -50,16 +50,16 @@ public class IOrderedLayout extends Panel implements Container, protected ApplicationConnection client; /** - * Reference to Element where wrapped childred are contained. Normally a TR - * or a TBODY element. + * Reference to Element where wrapped childred are contained. Normally a + * DIV, TR or a TBODY element. */ private Element wrappedChildContainer; /** * Elements that provides the Layout interface implementation. Root element - * of the component. In vertical mode this is the outmost div. + * of the component. This is the outmost div or table. */ - private final Element root; + private Element root; /** * List of child widgets. This is not the list of wrappers, but the actual @@ -68,11 +68,18 @@ public class IOrderedLayout extends Panel implements Container, private final Vector childWidgets = new Vector(); /** - * Fixed cell-size mode is used when height/width is explicitly given for - * vertical/horizontal orderedlayout. + * In table mode, the root element is table instead of div. */ - private boolean fixedCellSize = false; + private boolean tableMode = false; + /** Last set width of the component. Null if undefined (instead of being ""). */ + private String width = null; + + /** + * Last set height of the component. Null if undefined (instead of being + * ""). + */ + private String height = null; /** * List of child widget wrappers. These wrappers are in exact same indexes * as the widgets in childWidgets list. @@ -82,15 +89,12 @@ public class IOrderedLayout extends Panel implements Container, /** Whether the component has spacing enabled. */ private boolean hasComponentSpacing; - /** Whether the component has spacing enabled. */ - private int previouslyAppliedFixedSize = -1; - /** Information about margin states. */ private MarginInfo margins = new MarginInfo(0); /** * Flag that indicates that the child layouts must be updated as soon as - * possible. + * possible. This will be done in the end of updateFromUIDL. */ private boolean childLayoutsHaveChanged = false; @@ -100,95 +104,77 @@ public class IOrderedLayout extends Panel implements Container, *

* There are two modes - vertical and horizontal. *

- * where root, margin and childcontainer refer to the root element, margin - * element and the element that contain WidgetWrappers. + * where root and childcontainer refer to the root element and the element + * that contain WidgetWrappers. *

* */ public IOrderedLayout() { - - root = DOM.createDiv(); - createAndEmptyWrappedChildContainer(); + wrappedChildContainer = root = DOM.createDiv(); setElement(root); setStyleName(CLASSNAME); } - /** - * Constuct base DOM-scrtucture and clean any already attached - * widgetwrappers from DOM. - */ - private void createAndEmptyWrappedChildContainer() { - if (orientationMode == ORIENTATION_HORIZONTAL) { - final String structure = "
"; - DOM.setInnerHTML(root, structure); - wrappedChildContainer = DOM.getFirstChild(DOM.getFirstChild(DOM - .getFirstChild(root))); - if (!BrowserInfo.get().isIE()) { - DOM.setStyleAttribute(root, "display", "table"); - } - } else { - wrappedChildContainer = root; - DOM.setInnerHTML(root, ""); - DOM.setStyleAttribute(root, "display", "block"); - } - } - /** * Update orientation, if it has changed. * * @param newOrientationMode */ - private void updateOrientation(UIDL uidl) { + private void rebuildRootDomStructure(boolean forceUpdate) { - // Parse new mode from UIDL - int newOrientationMode = "horizontal".equals(uidl - .getStringAttribute("orientation")) ? ORIENTATION_HORIZONTAL - : ORIENTATION_VERTICAL; + // Should we have table as a root element? + boolean newTableMode = !(orientationMode == ORIENTATION_VERTICAL && width != null); - // Only change the mode if when needed - if (orientationMode == newOrientationMode) { + // Already in correct mode? + if (!forceUpdate && newTableMode == tableMode) { return; } + tableMode = newTableMode; - // Remove fixed state - removeFixedSizes(); + // Constuct base DOM-structure and clean any already attached + // widgetwrappers from DOM. + if (tableMode) { + Element tmp = DOM.createDiv(); + final String structure = "
"; + DOM.setInnerHTML(tmp, structure); + root = DOM.getFirstChild(tmp); + DOM.removeChild(tmp, root); + wrappedChildContainer = DOM.getFirstChild(DOM.getFirstChild(root)); + } else { + wrappedChildContainer = root = DOM.createDiv(); + } - orientationMode = newOrientationMode; + // Restore component size + if (width != null && !"".equals(width)) { + DOM.setStyleAttribute(root, "width", width); + } + if (height != null && !"".equals(height)) { + DOM.setStyleAttribute(root, "height", height); + } - createAndEmptyWrappedChildContainer(); + // Reset widget main element + String styles = getStyleName(); + setElement(root); + setStyleName(styles); // Reinsert all widget wrappers to this container for (int i = 0; i < childWidgetWrappers.size(); i++) { WidgetWrapper wr = (WidgetWrapper) childWidgetWrappers.get(i); - Element oldWrElement = wr.resetRootElement(); - Element newWrElement = wr.getElement(); - String oldStyle = DOM.getElementAttribute(oldWrElement, "class"); - if (oldStyle != null) { - DOM.setElementAttribute(newWrElement, "class", oldStyle); - } + Element oldWrElement = wr.getWrappingElement(); + wr.resetRootElement(); + Element newWrElement = wr.getWrappingElement(); while (DOM.getChildCount(oldWrElement) > 0) { Element c = DOM.getFirstChild(oldWrElement); DOM.removeChild(oldWrElement, c); DOM.appendChild(newWrElement, c); } - DOM.appendChild(wrappedChildContainer, newWrElement); - } - - // Reconsider being fixed - String rootWidth = DOM.getStyleAttribute(root, "width"); - String rootHeight = DOM.getStyleAttribute(root, "height"); - if ((orientationMode == ORIENTATION_HORIZONTAL && rootWidth != null && !"" - .equals(rootWidth)) - || (orientationMode == ORIENTATION_VERTICAL - && rootHeight != null && !"".equals(rootHeight))) { - fixedCellSize = true; - updateFixedSizes(); + DOM.appendChild(wrappedChildContainer, wr.getElement()); } // Update child layouts @@ -201,27 +187,27 @@ public class IOrderedLayout extends Panel implements Container, this.client = client; // Only non-cached UIDL:s can introduce changes - if (!uidl.getBooleanAttribute("cached")) { - - updateMarginAndSpacingSizesFromCSS(uidl); - - // Swith between orientation modes if necessary - updateOrientation(uidl); - - // Handle layout margins - if (margins.getBitMask() != uidl.getIntAttribute("margins")) { - handleMargins(uidl); - } - - // Handle component spacing later in handleAlignments() method - hasComponentSpacing = uidl.getBooleanAttribute("spacing"); + if (uidl.getBooleanAttribute("cached")) { + return; } + updateMarginAndSpacingSizesFromCSS(uidl); + // Update sizes, ... if (client.updateComponent(this, uidl, false)) { return; } + // Rebuild DOM tree root if necessary + int oldO = orientationMode; + orientationMode = "horizontal".equals(uidl + .getStringAttribute("orientation")) ? ORIENTATION_HORIZONTAL + : ORIENTATION_VERTICAL; + rebuildRootDomStructure(oldO != orientationMode); + + // Handle component spacing later in handleAlignments() method + hasComponentSpacing = uidl.getBooleanAttribute("spacing"); + // Collect the list of contained widgets after this update final Vector newWidgets = new Vector(); for (final Iterator it = uidl.getChildIterator(); it.hasNext();) { @@ -244,6 +230,8 @@ public class IOrderedLayout extends Panel implements Container, // unpainted ones later final Vector paintedWidgets = new Vector(); + final Vector childsToPaint = new Vector(); + // Add any new widgets to the ordered layout Widget oldChild = null; while (newWidgetsIterator.hasNext()) { @@ -287,7 +275,7 @@ public class IOrderedLayout extends Panel implements Container, } // Update the child component - ((Paintable) newChild).updateFromUIDL(newChildUIDL, client); + childsToPaint.add(new Object[] { newChild, newChildUIDL }); // Add this newly handled component to the list of painted // components @@ -303,12 +291,22 @@ public class IOrderedLayout extends Panel implements Container, } // Handle component alignments - handleAlignments(uidl); + handleAlignmentsSpacingAndMargins(uidl); - // If the layout has fixed width|height, recalculate cell-sizes - updateFixedSizes(); + // Reset sizes for the children + // TODO These might be optimized by combining these methods + updateChildHeights(); + updateChildWidths(); + + // Paint children + for (int i = 0; i < childsToPaint.size(); i++) { + Object[] t = (Object[]) childsToPaint.get(i); + ((Paintable) t[0]).updateFromUIDL((UIDL) t[1], client); + } // Update child layouts + // TODO This is most probably unnedessary and should be done within + // update Child H/W if (childLayoutsHaveChanged) { Util.runDescendentsLayout(this); childLayoutsHaveChanged = false; @@ -331,22 +329,16 @@ public class IOrderedLayout extends Panel implements Container, * While setting width, ensure that margin div is also resized properly. * Furthermore, enable/disable fixed mode */ - public void setWidth(String width) { - super.setWidth(width); + public void setWidth(String newWidth) { - if (width == null || "".equals(width)) { - DOM.setStyleAttribute(root, "overflowX", ""); + width = newWidth == null || "".equals(newWidth) ? null : newWidth; - if (fixedCellSize && orientationMode == ORIENTATION_HORIZONTAL) { - removeFixedSizes(); - } + // When we use divs at root - for them using 100% width should be + // calculated with "" + if (!tableMode && "100%".equals(newWidth)) { + super.setWidth(""); } else { - - DOM.setStyleAttribute(root, "overflowX", "hidden"); - - if (orientationMode == ORIENTATION_HORIZONTAL) { - fixedCellSize = true; - } + super.setWidth(newWidth); } // Update child layouts @@ -357,155 +349,128 @@ public class IOrderedLayout extends Panel implements Container, * While setting height, ensure that margin div is also resized properly. * Furthermore, enable/disable fixed mode */ - public void setHeight(String height) { - super.setHeight(height); - - // Horizontal Table height must follow root height - if (orientationMode == ORIENTATION_HORIZONTAL) { - DOM.setStyleAttribute(DOM.getFirstChild(root), "height", height); - } - - if (height == null || "".equals(height)) { - DOM.setStyleAttribute(root, "overflowY", ""); + public void setHeight(String newHeight) { + super.setHeight(newHeight); + height = newHeight == null || "".equals(newHeight) ? null : newHeight; - // Removing fixed size is needed only when it is in use - if (fixedCellSize && orientationMode == ORIENTATION_VERTICAL) { - removeFixedSizes(); - } + // Update child layouts + childLayoutsHaveChanged = true; + } - } else { + /** Recalculate and apply child heights */ + private void updateChildHeights() { - DOM.setStyleAttribute(root, "overflowY", "hidden"); + // Vertical layout is calculated by us + if (height != null) { - // Turn on vertical orientation mode if needed - if (orientationMode == ORIENTATION_VERTICAL) { - fixedCellSize = true; + // Calculate the space for fixed contents minus marginals + int size; + if (tableMode) { + size = rootOffsetMeasure("offsetHeight"); + } else { + size = DOM.getElementPropertyInt(root, "offsetHeight"); } - } - - // Update child layouts - childLayoutsHaveChanged = true; - } - - /** Remove fixed sizes from use */ - private void removeFixedSizes() { + size -= margins.hasTop() ? marginTop : 0; + size -= margins.hasBottom() ? marginBottom : 0; - // If already removed, do not do it twice - if (!fixedCellSize) { - return; - } + // Reduce spacing from the size + int numChild = childWidgets.size(); + if (hasComponentSpacing) { + size -= ((orientationMode == ORIENTATION_HORIZONTAL) ? hSpacing + : vSpacing) + * (numChild - 1); + } - // Remove unneeded attributes from each wrapper - String wh = (orientationMode == ORIENTATION_HORIZONTAL) ? "width" - : "height"; - for (Iterator i = childWidgetWrappers.iterator(); i.hasNext();) { - Element we = ((WidgetWrapper) i.next()).getElement(); - DOM.setStyleAttribute(we, wh, ""); - DOM.setStyleAttribute(we, "overflow", ""); + // Set the sizes for each child + if (orientationMode == ORIENTATION_HORIZONTAL) { + for (Iterator i = childWidgetWrappers.iterator(); i.hasNext();) { + ((WidgetWrapper) i.next()).forceHeight(size); + } + } else { + for (Iterator i = childWidgetWrappers.iterator(); i.hasNext();) { + final int ws = Math.round(((float) size) / (numChild--)); + size -= ws; + ((WidgetWrapper) i.next()).forceHeight(ws); + } + } } - // Remove unneeded attributes from horizontal layouts table - if (orientationMode == ORIENTATION_HORIZONTAL) { - Element table = DOM.getParent(DOM.getParent(wrappedChildContainer)); - DOM.setStyleAttribute(table, "tableLayout", "auto"); - DOM.setStyleAttribute(table, "width", ""); + // Vertically layout is calculated by the browsers + else { + for (Iterator i = childWidgetWrappers.iterator(); i.hasNext();) { + ((WidgetWrapper) i.next()).forceHeight(-1); + } } + } - fixedCellSize = false; - previouslyAppliedFixedSize = -1; - + /** + * Measure how much space the root element could get. + * + * This measures the space allocated by the parent for the root element + * without letting root element to affect the calculation. + * + * @param offset + * offsetWidth or offsetHeight + */ + private int rootOffsetMeasure(String offset) { + Element measure = DOM.createDiv(); + DOM.setStyleAttribute(measure, "height", "100%"); + Element parent = DOM.getParent(root); + DOM.insertBefore(parent, measure, getElement()); + DOM.removeChild(parent, root); + int size = DOM.getElementPropertyInt(measure, offset); + DOM.insertBefore(parent, root, measure); + DOM.removeChild(parent, measure); + return size; } - /** Reset the fixed cell-sizes for children. */ - private void updateFixedSizes() { + /** Recalculate and apply child widths */ + private void updateChildWidths() { + // Horizontal layout is calculated by us + if (width != null && orientationMode == ORIENTATION_HORIZONTAL) { - // Do not do anything if we really should not be doing this - if (!fixedCellSize) { - return; - } + // Calculate the space for fixed contents minus marginals + int size = rootOffsetMeasure("offsetWidth"); - // Calculate the space for fixed contents minus marginals - int size = DOM.getElementPropertyInt(root, - (orientationMode == ORIENTATION_HORIZONTAL) ? "offsetWidth" - : "offsetHeight"); - if (orientationMode == ORIENTATION_HORIZONTAL) { size -= margins.hasLeft() ? marginLeft : 0; size -= margins.hasRight() ? marginRight : 0; - } else { - size -= margins.hasTop() ? marginTop : 0; - size -= margins.hasBottom() ? marginBottom : 0; - } - // Horizontal layouts need fixed mode tables - if (orientationMode == ORIENTATION_HORIZONTAL) { - Element table = DOM.getParent(DOM.getParent(wrappedChildContainer)); - DOM.setStyleAttribute(table, "tableLayout", "fixed"); - DOM.setStyleAttribute(table, "width", "" + size + "px"); - } + // Reduce spacing from the size + int numChild = childWidgets.size(); + if (hasComponentSpacing) { + size -= hSpacing * (numChild - 1); + } - // Reduce spacing from the size - int numChild = childWidgets.size(); - if (hasComponentSpacing) { - size -= ((orientationMode == ORIENTATION_HORIZONTAL) ? hSpacing - : vSpacing) - * (numChild - 1); + // Set the sizes for each child + if (orientationMode == ORIENTATION_HORIZONTAL) { + for (Iterator i = childWidgetWrappers.iterator(); i.hasNext();) { + final int ws = Math.round(((float) size) / (numChild--)); + size -= ws; + ((WidgetWrapper) i.next()).forceWidth(ws); + } + } else { + for (Iterator i = childWidgetWrappers.iterator(); i.hasNext();) { + ((WidgetWrapper) i.next()).forceWidth(size); + } + } } - // Have we set fixed sizes before? - boolean firstTime = (previouslyAppliedFixedSize < 0); - - // If so, are they already correct? - if (size == previouslyAppliedFixedSize) { - return; - } - previouslyAppliedFixedSize = size; - - // Set the sizes for each child - String wh = (orientationMode == ORIENTATION_HORIZONTAL) ? "width" - : "height"; - for (Iterator i = childWidgetWrappers.iterator(); i.hasNext();) { - Element we = ((WidgetWrapper) i.next()).getElement(); - final int ws = Math.round(((float) size) / (numChild--)); - size -= ws; - DOM.setStyleAttribute(we, wh, "" + ws + "px"); - if (firstTime) { - DOM.setStyleAttribute(we, "overflow", "hidden"); + // Horizontal layout is calculated by the browsers + else { + for (Iterator i = childWidgetWrappers.iterator(); i.hasNext();) { + ((WidgetWrapper) i.next()).forceWidth(-1); } } - fixedCellSize = true; - - // Update child layouts - childLayoutsHaveChanged = true; } - /** Enable/disable margins classes for the margin div when needed */ - protected void handleMargins(UIDL uidl) { + /** Parse alignments from UIDL and pass whem to correct widgetwrappers */ + private void handleAlignmentsSpacingAndMargins(UIDL uidl) { // Only update margins when they have changed - MarginInfo newMargins = new MarginInfo(uidl.getIntAttribute("margins")); - if (newMargins.equals(margins)) { - return; - } - margins = newMargins; - - // Update margin classes - DOM.setStyleAttribute(root, "paddingTop", margins.hasTop() ? marginTop - + "px" : "0"); - DOM.setStyleAttribute(root, "paddingLeft", - margins.hasLeft() ? marginLeft + "px" : "0"); - DOM.setStyleAttribute(root, "paddingBottom", - margins.hasBottom() ? marginBottom + "px" : "0"); - DOM.setStyleAttribute(root, "paddingRight", - margins.hasRight() ? marginRight + "px" : "0"); - - // Update child layouts - childLayoutsHaveChanged = true; - } - - /** Parse alignments from UIDL and pass whem to correct widgetwrappers */ - private void handleAlignments(UIDL uidl) { + // TODO this should be optimized to avoid reupdating these + margins = new MarginInfo(uidl.getIntAttribute("margins")); // Component alignments as a comma separated list. // See com.itmill.toolkit.terminal.gwt.client.ui.AlignmentInfo.java for @@ -527,9 +492,9 @@ public class IOrderedLayout extends Panel implements Container, wr.setAlignment(ai.getVerticalAlignment(), ai .getHorizontalAlignment()); - // Handle spacing in this loop as well - wr.setSpacingEnabled(alignmentIndex == 1 ? false - : hasComponentSpacing); + // Handle spacing and margins in this loop as well + wr.setSpacingAndMargins(alignmentIndex == 1, + alignmentIndex == alignments.length); } } @@ -541,7 +506,10 @@ public class IOrderedLayout extends Panel implements Container, class WidgetWrapper extends UIObject { Element td; + Element clipperDiv; Caption caption = null; + int lastForcedPixelHeight = -1; + int lastForcedPixelWidth = -1; /** Set the root element */ public WidgetWrapper() { @@ -549,24 +517,135 @@ public class IOrderedLayout extends Panel implements Container, } /** - * Create td or div - depending on the orientation of the layout and set - * it as root. + * Set the height given for the wrapped widget in pixels. + * + * -1 if unconstrained. + */ + public void forceHeight(int pixelHeight) { + + // If we are already at the correct size, do nothing + if (lastForcedPixelHeight == pixelHeight) { + return; + } + + // Clipper DIV is needed? + if (tableMode) { + if (pixelHeight >= 0) { + if (clipperDiv == null) { + createClipperDiv(); + } + } + // Needed to remove unnecessary clipper DIV + else if (clipperDiv != null && lastForcedPixelWidth < 0) { + removeClipperDiv(); + } + } + Element e = clipperDiv != null ? clipperDiv : getWrappingElement(); + + // Overflow + DOM.setStyleAttribute(e, "overflowY", pixelHeight < 0 ? "" + : "hidden"); + + // Set height + DOM.setStyleAttribute(e, "height", + pixelHeight < 0 ? (e == clipperDiv || !tableMode ? "100%" + : "") : pixelHeight + "px"); + + lastForcedPixelHeight = pixelHeight; + } + + /** + * Set the width given for the wrapped widget in pixels. + * + * -1 if unconstrained. + */ + public void forceWidth(int pixelWidth) { + + // If we are already at the correct size, do nothing + if (lastForcedPixelWidth == pixelWidth) { + return; + } + + // Clipper DIV needed + if (tableMode) { + if (pixelWidth >= 0) { + if (clipperDiv == null) { + createClipperDiv(); + } + } + // Needed to remove unnecessary clipper DIV + else if (clipperDiv != null && lastForcedPixelHeight < 0) { + removeClipperDiv(); + } + } + Element e = clipperDiv != null ? clipperDiv : getWrappingElement(); + + // Overflow + DOM.setStyleAttribute(e, "overflowX", pixelWidth < 0 ? "" + : "hidden"); + + // Set width + DOM.setStyleAttribute(e, "width", pixelWidth < 0 ? "" : pixelWidth + + "px"); + + lastForcedPixelWidth = pixelWidth; + } + + /** Create a DIV inside TD for clipping child */ + private void createClipperDiv() { + clipperDiv = DOM.createDiv(); + final Element e = getWrappingElement(); + while (DOM.getChildCount(e) > 0) { + final Element c = DOM.getFirstChild(e); + DOM.removeChild(e, c); + DOM.appendChild(clipperDiv, c); + } + DOM.appendChild(e, clipperDiv); + } + + /** Undo createClipperDiv() */ + private void removeClipperDiv() { + final Element e = getWrappingElement(); + while (DOM.getChildCount(clipperDiv) > 0) { + final Element c = DOM.getFirstChild(clipperDiv); + DOM.removeChild(clipperDiv, c); + DOM.appendChild(e, c); + } + DOM.removeChild(e, clipperDiv); + clipperDiv = null; + } + + /** Get the element containing the caption and the wrapped widget. */ + private Element getWrappingElement() { + if (!tableMode || orientationMode == ORIENTATION_HORIZONTAL) { + return getElement(); + } + return DOM.getFirstChild(getElement()); + } + + /** + * Create tr, td or div - depending on the orientation of the layout and + * set it as root. * * @return Previous root element. */ - private Element resetRootElement() { - Element e = getElement(); - if (orientationMode == ORIENTATION_VERTICAL) { + private void resetRootElement() { + if (tableMode) { + if (orientationMode == ORIENTATION_HORIZONTAL) { + setElement(DOM.createTD()); + } else { + Element tr = DOM.createTR(); + DOM.appendChild(tr, DOM.createTD()); + setElement(tr); + } + } else { setElement(DOM.createDiv()); // Apply 'hasLayout' for IE (needed to get accurate dimension // calculations) if (BrowserInfo.get().isIE()) { DOM.setStyleAttribute(getElement(), "zoom", "1"); } - } else { - setElement(DOM.createTD()); } - return e; } /** Update the caption of the element contained in this wrapper. */ @@ -595,25 +674,30 @@ public class IOrderedLayout extends Panel implements Container, // As the caption has just been created, insert it to DOM if (after) { - DOM.appendChild(getElement(), captionElement); - DOM.setElementAttribute(getElement(), "class", + DOM.appendChild(getWrappingElement(), captionElement); + DOM.setElementAttribute(getWrappingElement(), "class", "i-orderedlayout-w"); caption.addStyleName("i-orderedlayout-c"); widget.addStyleName("i-orderedlayout-w-e"); } else { - DOM.insertChild(getElement(), captionElement, 0); + DOM + .insertChild(getWrappingElement(), + captionElement, 0); } } else // Caption exists. Move it to correct position if needed - if (after == (DOM.getChildIndex(getElement(), widgetElement) > DOM - .getChildIndex(getElement(), captionElement))) { - Element firstElement = DOM.getChild(getElement(), DOM - .getChildCount(getElement()) - 2); - DOM.removeChild(getElement(), firstElement); - DOM.appendChild(getElement(), firstElement); - DOM.setElementAttribute(getElement(), "class", + if (after == (DOM.getChildIndex(getWrappingElement(), + widgetElement) > DOM.getChildIndex( + getWrappingElement(), captionElement))) { + Element firstElement = DOM.getChild(getWrappingElement(), + DOM.getChildCount(getWrappingElement()) - 2); + if (firstElement != null) { + DOM.removeChild(getWrappingElement(), firstElement); + DOM.appendChild(getWrappingElement(), firstElement); + } + DOM.setElementAttribute(getWrappingElement(), "class", after ? "i-orderedlayout-w" : ""); if (after) { caption.addStyleName("i-orderedlayout-c"); @@ -631,9 +715,9 @@ public class IOrderedLayout extends Panel implements Container, // Remove existing caption from DOM if (caption != null) { - DOM.removeChild(getElement(), caption.getElement()); + DOM.removeChild(getWrappingElement(), caption.getElement()); caption = null; - DOM.setElementAttribute(getElement(), "class", ""); + DOM.setElementAttribute(getWrappingElement(), "class", ""); widget.removeStyleName("i-orderedlayout-w-e"); caption.removeStyleName("i-orderedlayout-w-c"); } @@ -647,22 +731,25 @@ public class IOrderedLayout extends Panel implements Container, // Set vertical alignment if (BrowserInfo.get().isIE()) { - DOM.setElementAttribute(getElement(), "vAlign", + DOM.setElementAttribute(getWrappingElement(), "vAlign", verticalAlignment); } else { if (orientationMode == ORIENTATION_VERTICAL) { if (verticalAlignment == null || verticalAlignment.equals("top")) { - DOM.setStyleAttribute(getElement(), "display", "block"); - DOM.setStyleAttribute(getElement(), "width", ""); + DOM.setStyleAttribute(getWrappingElement(), "display", + "block"); + DOM + .setStyleAttribute(getWrappingElement(), + "width", ""); } else { - DOM.setStyleAttribute(getElement(), "display", + DOM.setStyleAttribute(getWrappingElement(), "display", "table-cell"); - DOM.setStyleAttribute(getElement(), "width", + DOM.setStyleAttribute(getWrappingElement(), "width", "1000000px"); } } - DOM.setStyleAttribute(getElement(), "verticalAlign", + DOM.setStyleAttribute(getWrappingElement(), "verticalAlign", verticalAlignment); } @@ -679,27 +766,32 @@ public class IOrderedLayout extends Panel implements Container, if (td == null) { // Store and remove the current childs (widget and caption) - Element c1 = DOM.getFirstChild(getElement()); - DOM.removeChild(getElement(), c1); - Element c2 = DOM.getFirstChild(getElement()); + Element c1 = DOM.getFirstChild(getWrappingElement()); + if (c1 != null) { + DOM.removeChild(getWrappingElement(), c1); + } + Element c2 = DOM.getFirstChild(getWrappingElement()); if (c2 != null) { - DOM.removeChild(getElement(), c2); + DOM.removeChild(getWrappingElement(), c2); } // Construct table structure to align children final String t = "
" + "
" + "
"; - DOM.setInnerHTML(getElement(), t); + DOM.setInnerHTML(getWrappingElement(), t); td = DOM.getFirstChild(DOM.getFirstChild(DOM - .getFirstChild(DOM.getFirstChild(getElement())))); + .getFirstChild(DOM + .getFirstChild(getWrappingElement())))); Element itd = DOM.getFirstChild(DOM.getFirstChild(DOM .getFirstChild(DOM.getFirstChild(td)))); // Restore children inside the - DOM.appendChild(itd, c1); - if (c2 != null) { - DOM.appendChild(itd, c2); + if (c1 != null) { + DOM.appendChild(itd, c1); + if (c2 != null) { + DOM.appendChild(itd, c2); + } } } else { @@ -733,25 +825,48 @@ public class IOrderedLayout extends Panel implements Container, Element content = DOM.getFirstChild(itd); if (content != null) { DOM.removeChild(itd, content); - DOM.appendChild(getElement(), content); + DOM.appendChild(getWrappingElement(), content); } } // Remove unneeded table element - DOM.removeChild(getElement(), DOM.getFirstChild(getElement())); + DOM.removeChild(getWrappingElement(), DOM + .getFirstChild(getWrappingElement())); td = null; } } /** Set class for spacing */ - void setSpacingEnabled(boolean b) { - DOM.setStyleAttribute(getElement(), - orientationMode == ORIENTATION_HORIZONTAL ? "paddingLeft" - : "marginTop", - b ? (orientationMode == ORIENTATION_HORIZONTAL ? hSpacing - : vSpacing) - + "px" : "0"); + void setSpacingAndMargins(boolean first, boolean last) { + + if (orientationMode == ORIENTATION_HORIZONTAL) { + DOM + .setStyleAttribute(getWrappingElement(), "paddingLeft", + first ? (margins.hasLeft() ? marginLeft + "px" + : "0") + : (hasComponentSpacing ? hSpacing + + "px" : "0")); + DOM.setStyleAttribute(getWrappingElement(), "paddingRight", + last ? (margins.hasRight() ? marginRight + "px" : "0") + : ""); + DOM.setStyleAttribute(getWrappingElement(), "paddingTop", + margins.hasTop() ? marginTop + "px" : ""); + DOM.setStyleAttribute(getWrappingElement(), "paddingBottom", + margins.hasBottom() ? marginBottom + "px" : ""); + } else { + DOM.setStyleAttribute(getWrappingElement(), "paddingLeft", + margins.hasLeft() ? marginLeft + "px" : "0"); + DOM.setStyleAttribute(getWrappingElement(), "paddingRight", + margins.hasRight() ? marginRight + "px" : "0"); + DOM + .setStyleAttribute(getWrappingElement(), "paddingTop", + first ? (margins.hasTop() ? marginTop + "px" + : "") : (hasComponentSpacing ? vSpacing + + "px" : "0")); + DOM.setStyleAttribute(getWrappingElement(), "paddingBottom", + last && margins.hasBottom() ? marginBottom + "px" : ""); + } } } @@ -832,7 +947,7 @@ public class IOrderedLayout extends Panel implements Container, childWidgetWrappers.insertElementAt(wrapper, atIndex); DOM.insertChild(wrappedChildContainer, wrapper.getElement(), atIndex + nonWidgetChildElements); - DOM.appendChild(wrapper.getElement(), child.getElement()); + DOM.appendChild(wrapper.getWrappingElement(), child.getElement()); /* * Adopt: Call {@link #adopt(Widget)} to finalize the add as the @@ -910,7 +1025,9 @@ public class IOrderedLayout extends Panel implements Container, /* documented at super */ public void iLayout() { - updateFixedSizes(); + updateChildHeights(); + updateChildWidths(); Util.runDescendentsLayout(this); + childLayoutsHaveChanged = false; } } diff --git a/src/com/itmill/toolkit/ui/OrderedLayout.java b/src/com/itmill/toolkit/ui/OrderedLayout.java index a3c3da5392..225253ea2e 100644 --- a/src/com/itmill/toolkit/ui/OrderedLayout.java +++ b/src/com/itmill/toolkit/ui/OrderedLayout.java @@ -68,6 +68,8 @@ public class OrderedLayout extends AbstractLayout implements */ public OrderedLayout() { orientation = ORIENTATION_VERTICAL; + setWidth(100); + setWidthUnits(UNITS_PERCENTAGE); } /** @@ -79,6 +81,10 @@ public class OrderedLayout extends AbstractLayout implements */ public OrderedLayout(int orientation) { this.orientation = orientation; + if (orientation == ORIENTATION_VERTICAL) { + setWidth(100); + setWidthUnits(UNITS_PERCENTAGE); + } } /**