From: Leif Åstrand Date: Tue, 7 Feb 2012 10:10:40 +0000 (+0200) Subject: Split measuring ordered layout to paintable and widget (#8324) X-Git-Tag: 7.0.0.alpha2~434^2~90 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=61a38d640f9196ca41a351c6a8f9fb222c82efff;p=vaadin-framework.git Split measuring ordered layout to paintable and widget (#8324) --- diff --git a/src/com/vaadin/terminal/gwt/client/CalculatingLayout.java b/src/com/vaadin/terminal/gwt/client/CalculatingLayout.java new file mode 100644 index 0000000000..ada9ab140e --- /dev/null +++ b/src/com/vaadin/terminal/gwt/client/CalculatingLayout.java @@ -0,0 +1,7 @@ +package com.vaadin.terminal.gwt.client; + +public interface CalculatingLayout extends VPaintableWidgetContainer { + public void updateVerticalSizes(); + + public void updateHorizontalSizes(); +} \ No newline at end of file diff --git a/src/com/vaadin/terminal/gwt/client/MeasureManager.java b/src/com/vaadin/terminal/gwt/client/MeasureManager.java index 46d1aeb9fc..9bcecfd786 100644 --- a/src/com/vaadin/terminal/gwt/client/MeasureManager.java +++ b/src/com/vaadin/terminal/gwt/client/MeasureManager.java @@ -2,9 +2,7 @@ package com.vaadin.terminal.gwt.client; import java.util.ArrayList; import java.util.Collection; -import java.util.Collections; import java.util.HashMap; -import java.util.HashSet; import java.util.Map; import java.util.Map.Entry; @@ -85,10 +83,7 @@ public class MeasureManager { private static MeasureManager instance = new MeasureManager(); public static Collection getChildren( - VPaintableWidget paintable, ApplicationConnection client) { - if (!(paintable instanceof Container)) { - return Collections.emptySet(); - } + VPaintableWidgetContainer paintable, ApplicationConnection client) { Widget widget = paintable.getWidgetForPaintable(); Collection children = new ArrayList(); @@ -113,23 +108,6 @@ public class MeasureManager { } } - private static VPaintableWidget getParentPaintable( - VPaintableWidget paintable, VPaintableMap paintableMap) { - Widget widget = paintable.getWidgetForPaintable(); - while (true) { - widget = widget.getParent(); - if (widget == null) { - return null; - } - VPaintableWidget parentPaintable = paintableMap - .getPaintable(widget); - if (parentPaintable != null) { - return parentPaintable; - } - // Else continue with the parent - } - } - public void doLayout(ApplicationConnection client) { VPaintableMap paintableMap = client.getPaintableMap(); VPaintableWidget[] paintableWidgets = paintableMap @@ -162,9 +140,8 @@ public class MeasureManager { for (int i = 0; i < changed.length(); i++) { VPaintableWidget paintable = (VPaintableWidget) paintableMap .getPaintable(changed.get(i)); - VPaintableWidget parentPaintable = getParentPaintable( - paintable, paintableMap); - if (parentPaintable instanceof Container) { + VPaintableWidget parentPaintable = paintable.getParent(); + if (parentPaintable instanceof CalculatingLayout) { affectedContainers .add(paintableMap.getPid(parentPaintable)); } @@ -181,6 +158,10 @@ public class MeasureManager { // TODO Do nothing here if parent instanceof // ProvidesRepaint? ((RequiresResize) widget).onResize(); + } else if (paintable instanceof CalculatingLayout) { + CalculatingLayout calculating = (CalculatingLayout) paintable; + calculating.updateHorizontalSizes(); + calculating.updateVerticalSizes(); } } } @@ -189,19 +170,11 @@ public class MeasureManager { for (int i = 0; i < affectedPids.length(); i++) { // Find all changed children String containerPid = affectedPids.get(i); - VPaintableWidget container = (VPaintableWidget) paintableMap + CalculatingLayout container = (CalculatingLayout) paintableMap .getPaintable(containerPid); - Collection children = getChildren(container, - client); - HashSet changedChildren = new HashSet(); - - for (VPaintableWidget child : children) { - if (changedSet.contains(paintableMap.getPid(child))) { - changedChildren.add(child.getWidgetForPaintable()); - } - } - ((Container) container).requestLayout(changedChildren); + container.updateHorizontalSizes(); + container.updateVerticalSizes(); } long layoutEnd = System.currentTimeMillis(); diff --git a/src/com/vaadin/terminal/gwt/client/ui/VHorizontalLayoutPaintable.java b/src/com/vaadin/terminal/gwt/client/ui/VHorizontalLayoutPaintable.java index acc49ece18..2fee82e974 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VHorizontalLayoutPaintable.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VHorizontalLayoutPaintable.java @@ -5,7 +5,8 @@ package com.vaadin.terminal.gwt.client.ui; import com.google.gwt.core.client.GWT; -public class VHorizontalLayoutPaintable extends VOrderedLayoutPaintable { +public class VHorizontalLayoutPaintable extends + VMeasuringOrderedLayoutPaintable { @Override public VHorizontalLayout getWidgetForPaintable() { diff --git a/src/com/vaadin/terminal/gwt/client/ui/VMeasuringOrderedLayout.java b/src/com/vaadin/terminal/gwt/client/ui/VMeasuringOrderedLayout.java index fa82c5b59f..1154585191 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VMeasuringOrderedLayout.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VMeasuringOrderedLayout.java @@ -3,13 +3,8 @@ */ package com.vaadin.terminal.gwt.client.ui; -import java.util.Collection; -import java.util.Collections; import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; import java.util.Map; -import java.util.Set; import com.google.gwt.dom.client.DivElement; import com.google.gwt.dom.client.Document; @@ -17,45 +12,39 @@ import com.google.gwt.dom.client.Element; import com.google.gwt.dom.client.Style; import com.google.gwt.dom.client.Style.Overflow; import com.google.gwt.dom.client.Style.Position; -import com.google.gwt.dom.client.Style.Unit; import com.google.gwt.user.client.DOM; import com.google.gwt.user.client.ui.ComplexPanel; -import com.google.gwt.user.client.ui.RequiresResize; import com.google.gwt.user.client.ui.Widget; import com.vaadin.terminal.gwt.client.ApplicationConnection; -import com.vaadin.terminal.gwt.client.Container; -import com.vaadin.terminal.gwt.client.MeasureManager; import com.vaadin.terminal.gwt.client.RenderSpace; -import com.vaadin.terminal.gwt.client.UIDL; import com.vaadin.terminal.gwt.client.VCaption; import com.vaadin.terminal.gwt.client.VPaintableMap; import com.vaadin.terminal.gwt.client.VPaintableWidget; import com.vaadin.terminal.gwt.client.ValueMap; -public class VMeasuringOrderedLayout extends ComplexPanel implements Container, - RequiresResize { +public class VMeasuringOrderedLayout extends ComplexPanel { public static final String CLASSNAME = "v-orderedlayout"; private static final int MARGIN_SIZE = 20; - private final boolean isVertical; + final boolean isVertical; - private ApplicationConnection client; + ApplicationConnection client; - private String id; + String id; private RenderSpace space; - private ValueMap expandRatios; + ValueMap expandRatios; - private ValueMap alignments; + ValueMap alignments; - private Map captions = new HashMap(); + Map captions = new HashMap(); - private boolean spacing; + boolean spacing; - private VMarginInfo activeMarginsInfo; + VMarginInfo activeMarginsInfo; protected VMeasuringOrderedLayout(String className, boolean isVertical) { DivElement element = Document.get().createDivElement(); @@ -69,71 +58,7 @@ public class VMeasuringOrderedLayout extends ComplexPanel implements Container, this.isVertical = isVertical; } - public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { - this.client = client; - id = uidl.getId(); - if (client.updateComponent(this, uidl, true)) { - return; - } - - long start = System.currentTimeMillis(); - // long childTime = 0; - - HashSet previousChildren = new HashSet(); - for (Widget child : this) { - if (!(child instanceof VCaption)) { - previousChildren.add(child); - } - } - // TODO Support reordering elements! - for (final Iterator it = uidl.getChildIterator(); it.hasNext();) { - final UIDL childUIDL = (UIDL) it.next(); - final VPaintableWidget child = client.getPaintable(childUIDL); - Widget widget = child.getWidgetForPaintable(); - - if (widget.getParent() != this) { - DivElement wrapper = Document.get().createDivElement(); - wrapper.getStyle().setPosition(Position.ABSOLUTE); - getElement().appendChild(wrapper); - add(widget, wrapper); - } - - if (!childUIDL.getBooleanAttribute("cached")) { - child.updateFromUIDL(childUIDL, client); - client.getMeasuredSize(child).setDirty(true); - } - // TODO Update alignments and expand ratios - - previousChildren.remove(widget); - } - - for (Widget widget : previousChildren) { - Element wrapper = getWrapper(widget); - VCaption caption = captions.remove(widget); - if (caption != null) { - remove(caption); - } - remove(widget); - // Remove the wrapper - getElement().removeChild(wrapper); - - client.unregisterPaintable(VPaintableMap.get(client).getPaintable( - widget)); - } - - int bitMask = uidl.getIntAttribute("margins"); - if (activeMarginsInfo == null - || activeMarginsInfo.getBitMask() != bitMask) { - activeMarginsInfo = new VMarginInfo(bitMask); - } - - spacing = uidl.getBooleanAttribute("spacing"); - expandRatios = uidl.getMapAttribute("expandRatios"); - alignments = uidl.getMapAttribute("alignments"); - client.getMeasuredSize(this).setDirty(true); - } - - private static Element getWrapper(Widget widget) { + static Element getWrapper(Widget widget) { return widget.getElement().getParentElement(); } @@ -141,184 +66,7 @@ public class VMeasuringOrderedLayout extends ComplexPanel implements Container, add(widget, (com.google.gwt.user.client.Element) wrapper.cast()); } - public void onResize() { - requestLayout(Collections. emptySet()); - } - - private static boolean isUndefinedInDirection(Widget widget, - boolean isVertical) { - String dimension = getDimensionInDirection(widget, isVertical); - return dimension == null || dimension.length() == 0; - } - - private static boolean isRelativeInDirection(Widget widget, - boolean isVertical) { - String dimension = getDimensionInDirection(widget, isVertical); - return dimension != null && dimension.endsWith("%"); - } - - private static String getDimensionInDirection(Widget widget, - boolean vertical) { - com.google.gwt.user.client.Element element = widget.getElement(); - Style style = element.getStyle(); - if (vertical) { - return style.getHeight(); - } else { - return style.getWidth(); - } - } - - public void replaceChildComponent(Widget oldComponent, Widget newComponent) { - throw new UnsupportedOperationException(); - } - - public boolean hasChildComponent(Widget component) { - return component.getParent() == this; - } - - public void updateCaption(VPaintableWidget component, UIDL uidl) { - if (VCaption.isNeeded(uidl)) { - VCaption caption = captions.get(component); - if (caption == null) { - caption = new VCaption(component, client); - - Widget widget = (Widget) component; - Element wrapper = getWrapper(widget); - - // Logical attach. - getChildren().add(caption); - - // Physical attach. - DOM.insertBefore( - (com.google.gwt.user.client.Element) wrapper.cast(), - caption.getElement(), widget.getElement()); - - // Adopt. - adopt(caption); - captions.put(component, caption); - MeasureManager.MeasuredSize measuredSize = client - .getMeasuredSize(component); - - measuredSize.registerDependency(caption.getElement()); - } - caption.updateCaption(uidl); - } else { - VCaption removedCaption = captions.remove(component); - if (removedCaption != null) { - remove(removedCaption); - MeasureManager.MeasuredSize measuredSize = client - .getMeasuredSize(component); - measuredSize.deRegisterDependency(removedCaption.getElement()); - } - } - - } - - private void layoutPrimaryDirection() { - Collection children = MeasureManager.getChildren( - this, client); - - // First pass - get total expand ratio and allocated size - int totalAllocated = 0; - double totalExpand = 0; - for (VPaintableWidget child : children) { - Widget widget = child.getWidgetForPaintable(); - - totalExpand += getExpandRatio(child); - - int captionAllocation; - if (isVertical) { - captionAllocation = getCaptionHeight(child); - getWrapper(widget).getStyle().setPaddingTop(captionAllocation, - Unit.PX); - } else { - captionAllocation = 0; - } - - if (!isRelativeInDirection(widget, isVertical)) { - totalAllocated += getMeasuredInDirection(child, isVertical) - + captionAllocation; - } - } - int startMargin = getStartMarginInDirection(isVertical); - int totalMargins = startMargin + getEndMarginInDirection(isVertical); - - totalAllocated += totalMargins - + (getSpacingInDirection(isVertical) * (children.size() - 1)); - - Style ownStyle = getElement().getStyle(); - double ownSize; - if (isUndefinedInDirection(this, isVertical)) { - ownSize = totalAllocated; - ownStyle.setProperty(getMinPropertyName(isVertical), - totalAllocated, Unit.PX); - } else { - ownSize = getMeasuredInDirection(this, isVertical); - ownStyle.clearProperty(getMinPropertyName(isVertical)); - } - - double unallocatedSpace = Math.max(0, ownSize - totalAllocated); - - double currentLocation = startMargin; - for (VPaintableWidget child : children) { - Widget widget = child.getWidgetForPaintable(); - Element wrapper = getWrapper(widget); - Style wrapperStyle = wrapper.getStyle(); - - double childExpandRatio; - if (totalExpand == 0) { - childExpandRatio = 1d / children.size(); - } else { - childExpandRatio = getExpandRatio(child) / totalExpand; - } - - double extraPixels = unallocatedSpace * childExpandRatio; - - boolean relative = isRelativeInDirection(widget, isVertical); - - double size = getMeasuredInDirection(child, isVertical); - int captionHeight = getCaptionHeight(child); - - if (isVertical) { - size += captionHeight; - } else if (!relative) { - size = Math.max(size, getCaptionWidth(child)); - } - - double allocatedSpace = extraPixels; - if (!relative) { - allocatedSpace += size; - } - - int alignment = getAlignmentInDirection(getAlignment(child), - isVertical); - - if (relative) { - double captionReservation = isVertical ? captionHeight : 0; - wrapperStyle.setProperty(getSizeProperty(isVertical), - allocatedSpace - captionReservation, Unit.PX); - } else { - wrapperStyle.clearProperty(getSizeProperty(isVertical)); - } - - double startPosition = currentLocation; - if (alignment == 0) { - // Centered - startPosition += (allocatedSpace - size) / 2; - } else if (alignment == 1) { - // Right or bottom - startPosition += allocatedSpace - size; - } - - wrapperStyle.setProperty(getStartProperty(isVertical), - startPosition, Unit.PX); - - currentLocation += allocatedSpace - + getSpacingInDirection(isVertical); - } - } - - private int getEndMarginInDirection(boolean isVertical) { + int getEndMarginInDirection(boolean isVertical) { if (isVertical) { return activeMarginsInfo.hasBottom() ? MARGIN_SIZE : 0; } else { @@ -326,7 +74,7 @@ public class VMeasuringOrderedLayout extends ComplexPanel implements Container, } } - private int getStartMarginInDirection(boolean isVertical) { + int getStartMarginInDirection(boolean isVertical) { if (isVertical) { return activeMarginsInfo.hasTop() ? MARGIN_SIZE : 0; } else { @@ -334,120 +82,7 @@ public class VMeasuringOrderedLayout extends ComplexPanel implements Container, } } - private void layoutSecondaryDirection() { - Collection children = MeasureManager.getChildren( - this, client); - - int maxSize = 0; - for (VPaintableWidget child : children) { - Widget widget = child.getWidgetForPaintable(); - - int captionAllocation; - if (!isVertical) { - captionAllocation = getCaptionHeight(child); - getWrapper(widget).getStyle().setPaddingTop(captionAllocation, - Unit.PX); - } else { - captionAllocation = 0; - } - - if (!isRelativeInDirection(widget, !isVertical)) { - int childSize = getMeasuredInDirection(child, !isVertical) - + captionAllocation; - maxSize = Math.max(maxSize, childSize); - } - } - - int startMargin = getStartMarginInDirection(!isVertical); - int totalMargins = startMargin + getEndMarginInDirection(!isVertical); - - double availableSpace; - Style ownStyle = getElement().getStyle(); - - if (isUndefinedInDirection(this, !isVertical)) { - ownStyle.setProperty(getMinPropertyName(!isVertical), maxSize - + totalMargins, Unit.PX); - availableSpace = maxSize; - } else { - ownStyle.clearProperty(getMinPropertyName(!isVertical)); - availableSpace = getMeasuredInDirection(this, !isVertical) - - totalMargins; - } - - for (VPaintableWidget child : children) { - Widget widget = child.getWidgetForPaintable(); - Element wrapper = getWrapper(widget); - Style wrapperStyle = wrapper.getStyle(); - - boolean relative = isRelativeInDirection(widget, !isVertical); - - int captionHeight = getCaptionHeight(child); - - double allocatedSize = getMeasuredInDirection(child, !isVertical); - if (!isVertical) { - allocatedSize += captionHeight; - } else if (!relative) { - allocatedSize = Math.max(allocatedSize, getCaptionWidth(child)); - } - - int alignment = getAlignmentInDirection(getAlignment(child), - !isVertical); - - double startPosition = startMargin; - if (alignment == 0) { - startPosition += (availableSpace - allocatedSize) / 2; - // Centered - } else if (alignment == 1) { - // Right or bottom - startPosition += (availableSpace - allocatedSize); - } - - wrapperStyle.setProperty(getStartProperty(!isVertical), - startPosition, Unit.PX); - - if (relative) { - double captionReservation = !isVertical ? captionHeight : 0; - wrapperStyle.setProperty(getSizeProperty(!isVertical), - availableSpace - captionReservation, Unit.PX); - } else { - wrapperStyle.clearProperty(getSizeProperty(!isVertical)); - } - } - } - - public boolean requestLayout(Set changed) { - layoutPrimaryDirection(); - layoutSecondaryDirection(); - - // Doesn't matter right now... - return true; - } - - private static int getAlignmentInDirection(AlignmentInfo alignment, - boolean isVertical) { - if (alignment == null) { - return -1; - } - if (isVertical) { - if (alignment.isTop()) { - return -1; - } else if (alignment.isBottom()) { - return 1; - } else { - return 0; - } - } else { - if (alignment.isLeft()) { - return -1; - } else if (alignment.isRight()) { - return 1; - } else { - return 0; - } - } - } - - private int getSpacingInDirection(boolean isVertical) { + int getSpacingInDirection(boolean isVertical) { if (spacing) { return 20; } else { @@ -455,35 +90,7 @@ public class VMeasuringOrderedLayout extends ComplexPanel implements Container, } } - private int getCaptionWidth(VPaintableWidget child) { - VCaption caption = captions.get(child); - if (caption == null) { - return 0; - } else { - MeasureManager.MeasuredSize measuredSize = client - .getMeasuredSize(child); - return measuredSize.getDependencyWidth(caption.getElement()); - } - } - - private int getCaptionHeight(VPaintableWidget child) { - - VCaption caption = captions.get(child); - if (caption != null) { - MeasureManager.MeasuredSize measuredSize = client - .getMeasuredSize(child); - int captionHeight = measuredSize.getDependencyHeight(caption - .getElement()); - - caption.getElement().getStyle() - .setMarginTop(-captionHeight, Unit.PX); - return captionHeight; - } else { - return 0; - } - } - - private AlignmentInfo getAlignment(VPaintableWidget child) { + AlignmentInfo getAlignment(VPaintableWidget child) { String pid = VPaintableMap.get(client).getPid(child); if (alignments.containsKey(pid)) { return new AlignmentInfo(alignments.getInt(pid)); @@ -492,7 +99,7 @@ public class VMeasuringOrderedLayout extends ComplexPanel implements Container, } } - private double getExpandRatio(VPaintableWidget child) { + double getExpandRatio(VPaintableWidget child) { String pid = VPaintableMap.get(client).getPid(child); if (expandRatios.containsKey(pid)) { return expandRatios.getRawNumber(pid); @@ -501,52 +108,28 @@ public class VMeasuringOrderedLayout extends ComplexPanel implements Container, } } - private static String getSizeProperty(boolean isVertical) { - return isVertical ? "height" : "width"; - } - - private static String getStartProperty(boolean isVertical) { - return isVertical ? "top" : "left"; - } - - private static String getMinPropertyName(boolean isVertical) { - return isVertical ? "minHeight" : "minWidth"; + void addChildWidget(Widget widget) { + DivElement wrapper = Document.get().createDivElement(); + wrapper.getStyle().setPosition(Position.ABSOLUTE); + getElement().appendChild(wrapper); + add(widget, wrapper); } - private int getMeasuredInDirection(VPaintableWidget paintable, - boolean isVertical) { - MeasureManager.MeasuredSize measuredSize = client - .getMeasuredSize(paintable); - if (isVertical) { - return measuredSize.getHeight(); - } else { - return measuredSize.getWidth(); - } - } + void addCaption(VCaption caption, Widget widget) { + Element wrapper = getWrapper(widget); - public Collection getChildCaptions() { - return captions.values(); - } + // Logical attach. + getChildren().add(caption); - public RenderSpace getAllocatedSpace(Widget child) { - // Concept borrowed from CSS layout - if (space == null) { - space = new RenderSpace(-1, -1) { - @Override - public int getWidth() { - return getOffsetWidth(); - } + // Physical attach. + DOM.insertBefore((com.google.gwt.user.client.Element) wrapper.cast(), + caption.getElement(), widget.getElement()); - @Override - public int getHeight() { - return getOffsetHeight(); - } - }; - } - return space; + // Adopt. + adopt(caption); } - public Widget getWidgetForPaintable() { - return this; + void remove(VCaption caption) { + remove(caption); } } diff --git a/src/com/vaadin/terminal/gwt/client/ui/VMeasuringOrderedLayoutPaintable.java b/src/com/vaadin/terminal/gwt/client/ui/VMeasuringOrderedLayoutPaintable.java new file mode 100644 index 0000000000..d67574e90f --- /dev/null +++ b/src/com/vaadin/terminal/gwt/client/ui/VMeasuringOrderedLayoutPaintable.java @@ -0,0 +1,446 @@ +package com.vaadin.terminal.gwt.client.ui; + +import java.util.Collection; +import java.util.HashSet; +import java.util.Iterator; + +import com.google.gwt.dom.client.Element; +import com.google.gwt.dom.client.Style; +import com.google.gwt.dom.client.Style.Unit; +import com.google.gwt.user.client.ui.Widget; +import com.vaadin.terminal.gwt.client.ApplicationConnection; +import com.vaadin.terminal.gwt.client.CalculatingLayout; +import com.vaadin.terminal.gwt.client.MeasureManager; +import com.vaadin.terminal.gwt.client.UIDL; +import com.vaadin.terminal.gwt.client.VCaption; +import com.vaadin.terminal.gwt.client.VPaintableMap; +import com.vaadin.terminal.gwt.client.VPaintableWidget; + +public abstract class VMeasuringOrderedLayoutPaintable extends + VAbstractPaintableWidgetContainer implements CalculatingLayout { + + public void updateCaption(VPaintableWidget component, UIDL uidl) { + if (VCaption.isNeeded(uidl)) { + VCaption caption = getWidgetForPaintable().captions.get(component); + if (caption == null) { + caption = new VCaption(component, + getWidgetForPaintable().client); + + Widget widget = component.getWidgetForPaintable(); + + getWidgetForPaintable().addCaption(caption, widget); + getWidgetForPaintable().captions.put(component, caption); + + MeasureManager.MeasuredSize measuredSize = getWidgetForPaintable().client + .getMeasuredSize(component); + + measuredSize.registerDependency(caption.getElement()); + } + caption.updateCaption(uidl); + } else { + VCaption removedCaption = getWidgetForPaintable().captions + .remove(component); + if (removedCaption != null) { + getWidgetForPaintable().remove(removedCaption); + MeasureManager.MeasuredSize measuredSize = getWidgetForPaintable().client + .getMeasuredSize(component); + measuredSize.deRegisterDependency(removedCaption.getElement()); + } + } + } + + @Override + public VMeasuringOrderedLayout getWidgetForPaintable() { + return (VMeasuringOrderedLayout) super.getWidgetForPaintable(); + } + + public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { + getWidgetForPaintable().client = client; + getWidgetForPaintable().id = uidl.getId(); + if (client.updateComponent(this, uidl, true)) { + return; + } + + long start = System.currentTimeMillis(); + // long childTime = 0; + + HashSet previousChildren = new HashSet(); + for (Widget child : getWidgetForPaintable()) { + if (!(child instanceof VCaption)) { + previousChildren.add(child); + } + } + // TODO Support reordering elements! + for (final Iterator it = uidl.getChildIterator(); it.hasNext();) { + final UIDL childUIDL = (UIDL) it.next(); + final VPaintableWidget child = client.getPaintable(childUIDL); + Widget widget = child.getWidgetForPaintable(); + + if (widget.getParent() != getWidgetForPaintable()) { + getWidgetForPaintable().addChildWidget(widget); + } + + if (!childUIDL.getBooleanAttribute("cached")) { + child.updateFromUIDL(childUIDL, client); + client.getMeasuredSize(child).setDirty(true); + } + // TODO Update alignments and expand ratios + + previousChildren.remove(widget); + } + + for (Widget widget : previousChildren) { + Element wrapper = getWidgetForPaintable().getWrapper(widget); + VCaption caption = getWidgetForPaintable().captions.remove(widget); + if (caption != null) { + getWidgetForPaintable().remove(caption); + } + getWidgetForPaintable().remove(widget); + // Remove the wrapper + getWidgetForPaintable().getElement().removeChild(wrapper); + + client.unregisterPaintable(VPaintableMap.get(client).getPaintable( + widget)); + } + + int bitMask = uidl.getIntAttribute("margins"); + if (getWidgetForPaintable().activeMarginsInfo == null + || getWidgetForPaintable().activeMarginsInfo.getBitMask() != bitMask) { + getWidgetForPaintable().activeMarginsInfo = new VMarginInfo(bitMask); + } + + getWidgetForPaintable().spacing = uidl.getBooleanAttribute("spacing"); + getWidgetForPaintable().expandRatios = uidl + .getMapAttribute("expandRatios"); + getWidgetForPaintable().alignments = uidl.getMapAttribute("alignments"); + client.getMeasuredSize(this).setDirty(true); + } + + private int getCaptionWidth(VPaintableWidget child) { + VCaption caption = getWidgetForPaintable().captions.get(child); + if (caption == null) { + return 0; + } else { + MeasureManager.MeasuredSize measuredSize = getWidgetForPaintable().client + .getMeasuredSize(child); + return measuredSize.getDependencyWidth(caption.getElement()); + } + } + + private int getCaptionHeight(VPaintableWidget child) { + + VCaption caption = getWidgetForPaintable().captions.get(child); + if (caption != null) { + MeasureManager.MeasuredSize measuredSize = getWidgetForPaintable().client + .getMeasuredSize(child); + int captionHeight = measuredSize.getDependencyHeight(caption + .getElement()); + + caption.getElement().getStyle() + .setMarginTop(-captionHeight, Unit.PX); + return captionHeight; + } else { + return 0; + } + } + + private static boolean isRelativeInDirection(Widget widget, + boolean isVertical) { + String dimension = getDimensionInDirection(widget, isVertical); + return dimension != null && dimension.endsWith("%"); + } + + private static String getDimensionInDirection(Widget widget, + boolean vertical) { + com.google.gwt.user.client.Element element = widget.getElement(); + Style style = element.getStyle(); + if (vertical) { + return style.getHeight(); + } else { + return style.getWidth(); + } + } + + private static String getSizeProperty(boolean isVertical) { + return isVertical ? "height" : "width"; + } + + private static String getStartProperty(boolean isVertical) { + return isVertical ? "top" : "left"; + } + + private static String getMinPropertyName(boolean isVertical) { + return isVertical ? "minHeight" : "minWidth"; + } + + private static boolean isUndefinedInDirection(Widget widget, + boolean isVertical) { + String dimension = getDimensionInDirection(widget, isVertical); + return dimension == null || dimension.length() == 0; + } + + private int getMeasuredInDirection(VPaintableWidget paintable, + boolean isVertical) { + MeasureManager.MeasuredSize measuredSize = getWidgetForPaintable().client + .getMeasuredSize(paintable); + if (isVertical) { + return measuredSize.getHeight(); + } else { + return measuredSize.getWidth(); + } + } + + private static int getAlignmentInDirection(AlignmentInfo alignment, + boolean isVertical) { + if (alignment == null) { + return -1; + } + if (isVertical) { + if (alignment.isTop()) { + return -1; + } else if (alignment.isBottom()) { + return 1; + } else { + return 0; + } + } else { + if (alignment.isLeft()) { + return -1; + } else if (alignment.isRight()) { + return 1; + } else { + return 0; + } + } + } + + private void layoutPrimaryDirection() { + Collection children = MeasureManager.getChildren( + this, getWidgetForPaintable().client); + + // First pass - get total expand ratio and allocated size + int totalAllocated = 0; + double totalExpand = 0; + for (VPaintableWidget child : children) { + Widget widget = child.getWidgetForPaintable(); + + totalExpand += getWidgetForPaintable().getExpandRatio(child); + + int captionAllocation; + if (getWidgetForPaintable().isVertical) { + captionAllocation = getCaptionHeight(child); + getWidgetForPaintable().getWrapper(widget).getStyle() + .setPaddingTop(captionAllocation, Unit.PX); + } else { + captionAllocation = 0; + } + + if (!isRelativeInDirection(widget, + getWidgetForPaintable().isVertical)) { + totalAllocated += getMeasuredInDirection(child, + getWidgetForPaintable().isVertical) + captionAllocation; + } + } + int startMargin = getWidgetForPaintable().getStartMarginInDirection( + getWidgetForPaintable().isVertical); + int totalMargins = startMargin + + getWidgetForPaintable().getEndMarginInDirection( + getWidgetForPaintable().isVertical); + + totalAllocated += totalMargins + + (getWidgetForPaintable().getSpacingInDirection( + getWidgetForPaintable().isVertical) * (children.size() - 1)); + + Style ownStyle = getWidgetForPaintable().getElement().getStyle(); + double ownSize; + if (isUndefinedInDirection(getWidgetForPaintable(), + getWidgetForPaintable().isVertical)) { + ownSize = totalAllocated; + ownStyle.setProperty( + getMinPropertyName(getWidgetForPaintable().isVertical), + totalAllocated, Unit.PX); + } else { + ownSize = getMeasuredInDirection(this, + getWidgetForPaintable().isVertical); + ownStyle.clearProperty(getMinPropertyName(getWidgetForPaintable().isVertical)); + } + + double unallocatedSpace = Math.max(0, ownSize - totalAllocated); + + double currentLocation = startMargin; + for (VPaintableWidget child : children) { + Widget widget = child.getWidgetForPaintable(); + Element wrapper = getWidgetForPaintable().getWrapper(widget); + Style wrapperStyle = wrapper.getStyle(); + + double childExpandRatio; + if (totalExpand == 0) { + childExpandRatio = 1d / children.size(); + } else { + childExpandRatio = getWidgetForPaintable() + .getExpandRatio(child) / totalExpand; + } + + double extraPixels = unallocatedSpace * childExpandRatio; + + boolean relative = isRelativeInDirection(widget, + getWidgetForPaintable().isVertical); + + double size = getMeasuredInDirection(child, + getWidgetForPaintable().isVertical); + int captionHeight = getCaptionHeight(child); + + if (getWidgetForPaintable().isVertical) { + size += captionHeight; + } else if (!relative) { + size = Math.max(size, getCaptionWidth(child)); + } + + double allocatedSpace = extraPixels; + if (!relative) { + allocatedSpace += size; + } + + int alignment = getAlignmentInDirection(getWidgetForPaintable() + .getAlignment(child), getWidgetForPaintable().isVertical); + + if (relative) { + double captionReservation = getWidgetForPaintable().isVertical ? captionHeight + : 0; + wrapperStyle.setProperty( + getSizeProperty(getWidgetForPaintable().isVertical), + allocatedSpace - captionReservation, Unit.PX); + } else { + wrapperStyle + .clearProperty(getSizeProperty(getWidgetForPaintable().isVertical)); + } + + double startPosition = currentLocation; + if (alignment == 0) { + // Centered + startPosition += (allocatedSpace - size) / 2; + } else if (alignment == 1) { + // Right or bottom + startPosition += allocatedSpace - size; + } + + wrapperStyle.setProperty( + getStartProperty(getWidgetForPaintable().isVertical), + startPosition, Unit.PX); + + currentLocation += allocatedSpace + + getWidgetForPaintable().getSpacingInDirection( + getWidgetForPaintable().isVertical); + } + } + + private void layoutSecondaryDirection() { + Collection children = MeasureManager.getChildren( + this, getWidgetForPaintable().client); + + int maxSize = 0; + for (VPaintableWidget child : children) { + Widget widget = child.getWidgetForPaintable(); + + int captionAllocation; + if (!getWidgetForPaintable().isVertical) { + captionAllocation = getCaptionHeight(child); + getWidgetForPaintable().getWrapper(widget).getStyle() + .setPaddingTop(captionAllocation, Unit.PX); + } else { + captionAllocation = 0; + } + + if (!isRelativeInDirection(widget, + !getWidgetForPaintable().isVertical)) { + int childSize = getMeasuredInDirection(child, + !getWidgetForPaintable().isVertical) + + captionAllocation; + maxSize = Math.max(maxSize, childSize); + } + } + + int startMargin = getWidgetForPaintable().getStartMarginInDirection( + !getWidgetForPaintable().isVertical); + int totalMargins = startMargin + + getWidgetForPaintable().getEndMarginInDirection( + !getWidgetForPaintable().isVertical); + + double availableSpace; + Style ownStyle = getWidgetForPaintable().getElement().getStyle(); + + if (isUndefinedInDirection(getWidgetForPaintable(), + !getWidgetForPaintable().isVertical)) { + ownStyle.setProperty( + getMinPropertyName(!getWidgetForPaintable().isVertical), + maxSize + totalMargins, Unit.PX); + availableSpace = maxSize; + } else { + ownStyle.clearProperty(getMinPropertyName(!getWidgetForPaintable().isVertical)); + availableSpace = getMeasuredInDirection(this, + !getWidgetForPaintable().isVertical) - totalMargins; + } + + for (VPaintableWidget child : children) { + Widget widget = child.getWidgetForPaintable(); + Element wrapper = getWidgetForPaintable().getWrapper(widget); + Style wrapperStyle = wrapper.getStyle(); + + boolean relative = isRelativeInDirection(widget, + !getWidgetForPaintable().isVertical); + + int captionHeight = getCaptionHeight(child); + + double allocatedSize = getMeasuredInDirection(child, + !getWidgetForPaintable().isVertical); + if (!getWidgetForPaintable().isVertical) { + allocatedSize += captionHeight; + } else if (!relative) { + allocatedSize = Math.max(allocatedSize, getCaptionWidth(child)); + } + + int alignment = getAlignmentInDirection(getWidgetForPaintable() + .getAlignment(child), !getWidgetForPaintable().isVertical); + + double startPosition = startMargin; + if (alignment == 0) { + startPosition += (availableSpace - allocatedSize) / 2; + // Centered + } else if (alignment == 1) { + // Right or bottom + startPosition += (availableSpace - allocatedSize); + } + + wrapperStyle.setProperty( + getStartProperty(!getWidgetForPaintable().isVertical), + startPosition, Unit.PX); + + if (relative) { + double captionReservation = !getWidgetForPaintable().isVertical ? captionHeight + : 0; + wrapperStyle.setProperty( + getSizeProperty(!getWidgetForPaintable().isVertical), + availableSpace - captionReservation, Unit.PX); + } else { + wrapperStyle + .clearProperty(getSizeProperty(!getWidgetForPaintable().isVertical)); + } + } + } + + public void updateHorizontalSizes() { + if (getWidgetForPaintable().isVertical) { + layoutSecondaryDirection(); + } else { + layoutPrimaryDirection(); + } + } + + public void updateVerticalSizes() { + if (getWidgetForPaintable().isVertical) { + layoutPrimaryDirection(); + } else { + layoutSecondaryDirection(); + } + } +} diff --git a/src/com/vaadin/terminal/gwt/client/ui/VVerticalLayoutPaintable.java b/src/com/vaadin/terminal/gwt/client/ui/VVerticalLayoutPaintable.java index 71c6d91c69..2de30d4cc3 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VVerticalLayoutPaintable.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VVerticalLayoutPaintable.java @@ -5,7 +5,7 @@ package com.vaadin.terminal.gwt.client.ui; import com.google.gwt.core.client.GWT; -public class VVerticalLayoutPaintable extends VOrderedLayoutPaintable { +public class VVerticalLayoutPaintable extends VMeasuringOrderedLayoutPaintable { @Override public VVerticalLayout getWidgetForPaintable() {