From ebbd5e73fd6ff94b4d3a2d271c4e47359a5ceab4 Mon Sep 17 00:00:00 2001 From: Joonas Lehtinen Date: Fri, 11 Jul 2008 16:41:58 +0000 Subject: [PATCH] Optimizing IOrderedLayout svn changeset:5096/svn branch:trunk --- .../gwt/client/ui/IOrderedLayout.java | 247 ++++++++---------- 1 file changed, 110 insertions(+), 137 deletions(-) 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 7c49f75b05..bf8f0afa69 100644 --- a/src/com/itmill/toolkit/terminal/gwt/client/ui/IOrderedLayout.java +++ b/src/com/itmill/toolkit/terminal/gwt/client/ui/IOrderedLayout.java @@ -134,6 +134,7 @@ public class IOrderedLayout extends Panel implements Container, if (oldOrientationMode == orientationMode && newTableMode == tableMode) { return; } + boolean oldTableMode = tableMode; tableMode = newTableMode; // Constuct base DOM-structure and clean any already attached @@ -175,10 +176,16 @@ public class IOrderedLayout extends Panel implements Container, for (int i = 0; i < childWidgetWrappers.size(); i++) { WidgetWrapper wr = (WidgetWrapper) childWidgetWrappers.get(i); orientationMode = oldOrientationMode; + tableMode = oldTableMode; Element oldWrElement = wr.getElementWrappingWidgetAndCaption(); orientationMode = currentOrientationMode; + tableMode = newTableMode; + String classe = DOM.getElementAttribute(oldWrElement, "class"); wr.resetRootElement(); Element newWrElement = wr.getElementWrappingWidgetAndCaption(); + if (classe != null && classe.length() > 0) { + DOM.setElementAttribute(newWrElement, "class", classe); + } while (DOM.getChildCount(oldWrElement) > 0) { Element c = DOM.getFirstChild(oldWrElement); DOM.removeChild(oldWrElement, c); @@ -305,9 +312,7 @@ public class IOrderedLayout extends Panel implements Container, handleAlignmentsSpacingAndMargins(uidl); // Reset sizes for the children - // TODO These might be optimized by combining these methods - updateChildHeights(); - updateChildWidths(); + updateChildSizes(); // Paint children for (int i = 0; i < childsToPaint.size(); i++) { @@ -368,157 +373,148 @@ public class IOrderedLayout extends Panel implements Container, childLayoutsHaveChanged = true; } - /** Recalculate and apply child heights */ - private void updateChildHeights() { + /** Recalculate and apply the space given for each child in this layout. */ + private void updateChildSizes() { + + int numChild = childWidgets.size(); + int childHeightTotal = -1; + int childHeightDivisor = 1; + int childWidthTotal = -1; + int childWidthDivisor = 1; // Vertical layout is calculated by us if (height != null) { // Calculate the space for fixed contents minus marginals - int size; if (tableMode) { // If we know explicitly set pixel-size, use that if (height != null && height.endsWith("px")) { try { - size = Integer.parseInt(height.substring(0, height - .length() - 2)); + childHeightTotal = Integer.parseInt(height.substring(0, + height.length() - 2)); // For negative sizes, use measurements - if (size < 0) { - size = rootOffsetMeasure("offsetHeight"); + if (childHeightTotal < 0) { + childHeightTotal = rootOffsetMeasure("offsetHeight"); } } catch (NumberFormatException e) { // In case of invalid number, try to measure the size; - size = rootOffsetMeasure("offsetHeight"); + childHeightTotal = rootOffsetMeasure("offsetHeight"); } } // If not, try to measure the size else { - size = rootOffsetMeasure("offsetHeight"); + childHeightTotal = rootOffsetMeasure("offsetHeight"); } } else { - size = DOM.getElementPropertyInt(root, "offsetHeight"); + childHeightTotal = DOM.getElementPropertyInt(root, + "offsetHeight"); } - size -= margins.hasTop() ? marginTop : 0; - size -= margins.hasBottom() ? marginBottom : 0; + childHeightTotal -= margins.hasTop() ? marginTop : 0; + childHeightTotal -= margins.hasBottom() ? marginBottom : 0; // Reduce spacing from the size - int numChild = childWidgets.size(); if (hasComponentSpacing) { - size -= ((orientationMode == ORIENTATION_HORIZONTAL) ? hSpacing + childHeightTotal -= ((orientationMode == ORIENTATION_HORIZONTAL) ? hSpacing : vSpacing) * (numChild - 1); } - // 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); - } + // Total space is divided among the children + if (orientationMode == ORIENTATION_VERTICAL) { + childHeightDivisor = numChild; } } - // Vertically layout is calculated by the browsers - else { - for (Iterator i = childWidgetWrappers.iterator(); i.hasNext();) { - ((WidgetWrapper) i.next()).forceHeight(-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, root); - DOM.removeChild(parent, root); - int size = DOM.getElementPropertyInt(measure, offset); - DOM.insertBefore(parent, root, measure); - DOM.removeChild(parent, measure); - // In case the no space would be given for this element - // without pushing, use the current side of the root - return size; - } - - /** Recalculate and apply child widths */ - private void updateChildWidths() { // layout is calculated by us if (width != null) { // Calculate the space for fixed contents minus marginals - int size; // If we know explicitly set pixel-size, use that if (width != null && width.endsWith("px")) { try { - size = Integer.parseInt(width.substring(0, - width.length() - 2)); + childWidthTotal = Integer.parseInt(width.substring(0, width + .length() - 2)); // For negative sizes, use measurements - if (size < 0) { - size = rootOffsetMeasure("offsetWidth"); + if (childWidthTotal < 0) { + childWidthTotal = rootOffsetMeasure("offsetWidth"); } } catch (NumberFormatException e) { // In case of invalid number, try to measure the size; - size = rootOffsetMeasure("offsetWidth"); + childWidthTotal = rootOffsetMeasure("offsetWidth"); } } // If not, try to measure the size else { - size = rootOffsetMeasure("offsetWidth"); + childWidthTotal = rootOffsetMeasure("offsetWidth"); } - size -= margins.hasLeft() ? marginLeft : 0; - size -= margins.hasRight() ? marginRight : 0; + childWidthTotal -= margins.hasLeft() ? marginLeft : 0; + childWidthTotal -= margins.hasRight() ? marginRight : 0; // Reduce spacing from the size - int numChild = childWidgets.size(); if (hasComponentSpacing && orientationMode == ORIENTATION_HORIZONTAL) { - size -= hSpacing * (numChild - 1); + childWidthTotal -= hSpacing * (numChild - 1); } - // Set the sizes for each child + // Total space is divided among the children 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); - } + childWidthDivisor = numChild; } } - // Layout is calculated by the browsers - else { - for (Iterator i = childWidgetWrappers.iterator(); i.hasNext();) { - ((WidgetWrapper) i.next()).forceWidth(-1); + // Set the sizes for each child + for (Iterator i = childWidgetWrappers.iterator(); i.hasNext();) { + int w, h; + if (childHeightDivisor > 1) { + h = Math.round(((float) childHeightTotal) + / (childHeightDivisor--)); + childHeightTotal -= h; + } else { + h = childHeightTotal; } + if (childWidthDivisor > 1) { + w = Math.round(((float) childWidthTotal) + / (childWidthDivisor--)); + childWidthTotal -= h; + } else { + w = childWidthTotal; + } + WidgetWrapper ww = (WidgetWrapper) i.next(); + // TODO COMBINE THESE + ww.forceSize(w, h); } + } + /** + * 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, root); + DOM.removeChild(parent, root); + int size = DOM.getElementPropertyInt(measure, offset); + DOM.insertBefore(parent, root, measure); + DOM.removeChild(parent, measure); + // In case the no space would be given for this element + // without pushing, use the current side of the root + return size; } /** Parse alignments from UIDL and pass whem to correct widgetwrappers */ @@ -599,97 +595,72 @@ public class IOrderedLayout extends Panel implements Container, } /** - * Set the height given for the wrapped widget in pixels. + * Set the width and height given for the wrapped widget in pixels. * * -1 if unconstrained. */ - public void forceHeight(int pixelHeight) { + public void forceSize(int pixelWidth, int pixelHeight) { // If we are already at the correct size, do nothing - if (lastForcedPixelHeight == pixelHeight) { + if (lastForcedPixelHeight == pixelHeight + && lastForcedPixelWidth == pixelWidth) { 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(); + if (tableMode && (pixelHeight >= 0 || pixelWidth >= 0)) { + if (clipperDiv == null) { + createClipperDiv(); } } - Element e = clipperDiv != null ? clipperDiv - : getElementWrappingAlignmentStructures(); - - // 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; + // ClipperDiv is not needed, remove if necessary + else if (clipperDiv != null) { + removeClipperDiv(); } - // 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 : getElementWrappingAlignmentStructures(); // Overflow DOM.setStyleAttribute(e, "overflowX", pixelWidth < 0 ? "" : "hidden"); + DOM.setStyleAttribute(e, "overflowY", pixelHeight < 0 ? "" + : "hidden"); - // Set width + // Set size DOM.setStyleAttribute(e, "width", pixelWidth < 0 ? "" : pixelWidth + "px"); + DOM.setStyleAttribute(e, "height", + pixelHeight < 0 ? (e == clipperDiv || !tableMode ? "100%" + : "") : pixelHeight + "px"); + // Set cached values lastForcedPixelWidth = pixelWidth; + lastForcedPixelHeight = pixelHeight; } /** Create a DIV for clipping the child */ private void createClipperDiv() { clipperDiv = DOM.createDiv(); final Element e = getElementWrappingClipperDiv(); + String classe = DOM.getElementAttribute(e, "class"); while (DOM.getChildCount(e) > 0) { final Element c = DOM.getFirstChild(e); DOM.removeChild(e, c); DOM.appendChild(clipperDiv, c); } + if (classe != null && classe.length() > 0) { + DOM.removeElementAttribute(e, "class"); + DOM.setElementAttribute(clipperDiv, "class", classe); + } DOM.appendChild(e, clipperDiv); } /** Undo createClipperDiv() */ private void removeClipperDiv() { final Element e = getElementWrappingClipperDiv(); + String classe = DOM.getElementAttribute(clipperDiv, "class"); while (DOM.getChildCount(clipperDiv) > 0) { final Element c = DOM.getFirstChild(clipperDiv); DOM.removeChild(clipperDiv, c); @@ -697,6 +668,9 @@ public class IOrderedLayout extends Panel implements Container, } DOM.removeChild(e, clipperDiv); clipperDiv = null; + if (classe != null && classe.length() > 0) { + DOM.setElementAttribute(e, "class", classe); + } } /** @@ -1170,8 +1144,7 @@ public class IOrderedLayout extends Panel implements Container, /* documented at super */ public void iLayout() { - updateChildHeights(); - updateChildWidths(); + updateChildSizes(); Util.runDescendentsLayout(this); childLayoutsHaveChanged = false; } -- 2.39.5