diff options
author | Leif Åstrand <leif@vaadin.com> | 2012-04-03 08:58:24 +0300 |
---|---|---|
committer | Leif Åstrand <leif@vaadin.com> | 2012-04-03 08:58:24 +0300 |
commit | cd67770bbcc2b252334cd02c2cf9d92992e10ece (patch) | |
tree | 9935513da702c7d2dd972dfe6e00f4107247feeb /src/com/vaadin/terminal | |
parent | a19c07e1b351b2a03e184bc92811868a0f1fba72 (diff) | |
download | vaadin-framework-cd67770bbcc2b252334cd02c2cf9d92992e10ece.tar.gz vaadin-framework-cd67770bbcc2b252334cd02c2cf9d92992e10ece.zip |
Let ManagedLayouts report sizes back to the LayoutManager.
Also improved the way non-ManagedLayouts are handled.
Diffstat (limited to 'src/com/vaadin/terminal')
5 files changed, 229 insertions, 112 deletions
diff --git a/src/com/vaadin/terminal/gwt/client/LayoutManager.java b/src/com/vaadin/terminal/gwt/client/LayoutManager.java index 402e4f3bfe..1cae4c357d 100644 --- a/src/com/vaadin/terminal/gwt/client/LayoutManager.java +++ b/src/com/vaadin/terminal/gwt/client/LayoutManager.java @@ -3,7 +3,6 @@ */ package com.vaadin.terminal.gwt.client; -import java.util.Arrays; import java.util.Collection; import java.util.HashSet; import java.util.Set; @@ -23,7 +22,8 @@ public class LayoutManager { private ApplicationConnection connection; private final Set<Element> nonPaintableElements = new HashSet<Element>(); private final MeasuredSize nullSize = new MeasuredSize(); - private boolean layoutRunning = false; + + private LayoutDependencyTree currentDependencyTree; private final Collection<ManagedLayout> needsHorizontalLayout = new HashSet<ManagedLayout>(); private final Collection<ManagedLayout> needsVerticalLayout = new HashSet<ManagedLayout>(); @@ -108,40 +108,30 @@ public class LayoutManager { } public boolean isLayoutRunning() { - return layoutRunning; + return currentDependencyTree != null; } public void doLayout() { - if (layoutRunning) { + if (isLayoutRunning()) { throw new IllegalStateException( "Can't start a new layout phase before the previous layout phase ends."); } VConsole.log("Starting layout phase"); - layoutRunning = true; - - ConnectorMap paintableMap = connection.getConnectorMap(); - ComponentConnector[] paintableWidgets = paintableMap - .getComponentConnectors(); int passes = 0; Duration totalDuration = new Duration(); - LayoutDependencyTree layoutDependencyTree = new LayoutDependencyTree(); + currentDependencyTree = new LayoutDependencyTree(); - for (ComponentConnector componentConnector : paintableWidgets) { - layoutDependencyTree.setNeedsMeasure(componentConnector, true); - if (needsHorizontalLayout.contains(componentConnector)) { - layoutDependencyTree.setNeedsHorizontalLayout( - componentConnector, true); - } - if (needsVerticalLayout.contains(componentConnector)) { - layoutDependencyTree.setNeedsVerticalLayout(componentConnector, - true); - } + for (ManagedLayout layout : needsHorizontalLayout) { + currentDependencyTree.setNeedsHorizontalLayout(layout, true); + } + for (ManagedLayout layout : needsVerticalLayout) { + currentDependencyTree.setNeedsVerticalLayout(layout, true); } needsHorizontalLayout.clear(); needsVerticalLayout.clear(); - measureNonPaintables(layoutDependencyTree); + measureNonPaintables(currentDependencyTree); VConsole.log("Layout init in " + totalDuration.elapsedMillis() + " ms"); @@ -150,7 +140,7 @@ public class LayoutManager { passes++; int measuredConnectorCount = measureConnectors( - layoutDependencyTree, passes == 1); + currentDependencyTree, passes == 1); int measureTime = passDuration.elapsedMillis(); VConsole.log("Measured " + measuredConnectorCount + " elements in " @@ -158,40 +148,40 @@ public class LayoutManager { FastStringSet updatedSet = FastStringSet.create(); - for (ComponentConnector connector : layoutDependencyTree - .getHorizontalLayoutTargets()) { - if (connector instanceof DirectionalManagedLayout) { - DirectionalManagedLayout cl = (DirectionalManagedLayout) connector; - cl.layoutHorizontally(); - layoutDependencyTree.markAsHorizontallyLayouted(connector); - } else if (connector instanceof SimpleManagedLayout) { - SimpleManagedLayout rr = (SimpleManagedLayout) connector; - rr.layout(); - layoutDependencyTree.markAsHorizontallyLayouted(connector); - layoutDependencyTree.markAsVerticallyLayouted(connector); - } else { - layoutDependencyTree.markAsHorizontallyLayouted(connector); - layoutDependencyTree.markAsVerticallyLayouted(connector); + while (currentDependencyTree.hasHorizontalConnectorToLayout() + || currentDependencyTree.hasVerticaConnectorToLayout()) { + for (ManagedLayout layout : currentDependencyTree + .getHorizontalLayoutTargets()) { + if (layout instanceof DirectionalManagedLayout) { + currentDependencyTree + .markAsHorizontallyLayouted(layout); + DirectionalManagedLayout cl = (DirectionalManagedLayout) layout; + cl.layoutHorizontally(); + } else { + currentDependencyTree + .markAsHorizontallyLayouted(layout); + currentDependencyTree.markAsVerticallyLayouted(layout); + SimpleManagedLayout rr = (SimpleManagedLayout) layout; + rr.layout(); + } + updatedSet.add(layout.getConnectorId()); } - updatedSet.add(connector.getConnectorId()); - } - for (ComponentConnector connector : layoutDependencyTree - .getVerticalLayoutTargets()) { - if (connector instanceof DirectionalManagedLayout) { - DirectionalManagedLayout cl = (DirectionalManagedLayout) connector; - cl.layoutVertically(); - layoutDependencyTree.markAsVerticallyLayouted(connector); - } else if (connector instanceof SimpleManagedLayout) { - SimpleManagedLayout rr = (SimpleManagedLayout) connector; - rr.layout(); - layoutDependencyTree.markAsHorizontallyLayouted(connector); - layoutDependencyTree.markAsVerticallyLayouted(connector); - } else { - layoutDependencyTree.markAsHorizontallyLayouted(connector); - layoutDependencyTree.markAsVerticallyLayouted(connector); + for (ManagedLayout layout : currentDependencyTree + .getVerticalLayoutTargets()) { + if (layout instanceof DirectionalManagedLayout) { + currentDependencyTree.markAsVerticallyLayouted(layout); + DirectionalManagedLayout cl = (DirectionalManagedLayout) layout; + cl.layoutVertically(); + } else { + currentDependencyTree + .markAsHorizontallyLayouted(layout); + currentDependencyTree.markAsVerticallyLayouted(layout); + SimpleManagedLayout rr = (SimpleManagedLayout) layout; + rr.layout(); + } + updatedSet.add(layout.getConnectorId()); } - updatedSet.add(connector.getConnectorId()); } JsArrayString changed = updatedSet.dump(); @@ -229,46 +219,63 @@ public class LayoutManager { } } - VConsole.log("Layout phase done"); - VConsole.log("Calling post layout listeners"); - - for (ComponentConnector vPaintableWidget : paintableWidgets) { - if (vPaintableWidget instanceof PostLayoutListener) { - ((PostLayoutListener) vPaintableWidget).postLayout(); + int postLayoutStart = totalDuration.elapsedMillis(); + for (ComponentConnector connector : connection.getConnectorMap() + .getComponentConnectors()) { + if (connector instanceof PostLayoutListener) { + ((PostLayoutListener) connector).postLayout(); } } + VConsole.log("Invoke post layout listeners in " + + (totalDuration.elapsedMillis() - postLayoutStart) + " ms"); - layoutRunning = false; + currentDependencyTree = null; VConsole.log("Total layout phase time: " + totalDuration.elapsedMillis() + "ms"); } private int measureConnectors(LayoutDependencyTree layoutDependencyTree, boolean measureAll) { - - Collection<ComponentConnector> measureTargets; + int measureCount = 0; if (measureAll) { - measureTargets = Arrays.asList(ConnectorMap.get(connection) - .getComponentConnectors()); - } else { - measureTargets = layoutDependencyTree.getMeasureTargets(); + ComponentConnector[] connectors = ConnectorMap.get(connection) + .getComponentConnectors(); + for (ComponentConnector connector : connectors) { + measueConnector(layoutDependencyTree, connector); + } + for (ComponentConnector connector : connectors) { + layoutDependencyTree.setNeedsMeasure(connector, false); + } + measureCount += connectors.length; } - for (ComponentConnector paintableWidget : measureTargets) { - Element element = paintableWidget.getWidget().getElement(); - MeasuredSize measuredSize = getMeasuredSize(paintableWidget); - MeasureResult measureResult = measuredAndUpdate(element, - measuredSize, layoutDependencyTree); - - if (measureResult.isHeightChanged()) { - layoutDependencyTree.markHeightAsChanged(paintableWidget); + + while (layoutDependencyTree.hasConnectorsToMeasure()) { + Collection<ComponentConnector> measureTargets = layoutDependencyTree + .getMeasureTargets(); + for (ComponentConnector connector : measureTargets) { + measueConnector(layoutDependencyTree, connector); } - if (measureResult.isWidthChanged()) { - layoutDependencyTree.markWidthAsChanged(paintableWidget); + for (ComponentConnector connector : measureTargets) { + layoutDependencyTree.setNeedsMeasure(connector, false); } + measureCount++; + } + return measureCount; + } + + private void measueConnector(LayoutDependencyTree layoutDependencyTree, + ComponentConnector connector) { + Element element = connector.getWidget().getElement(); + MeasuredSize measuredSize = getMeasuredSize(connector); + MeasureResult measureResult = measuredAndUpdate(element, measuredSize, + layoutDependencyTree); - layoutDependencyTree.setNeedsMeasure(paintableWidget, false); + if (measureResult.isHeightChanged()) { + layoutDependencyTree.markHeightAsChanged(connector); + } + if (measureResult.isWidthChanged()) { + layoutDependencyTree.markWidthAsChanged(connector); } - return measureTargets.size(); } private void measureNonPaintables(LayoutDependencyTree layoutDependencyTree) { @@ -276,6 +283,8 @@ public class LayoutManager { MeasuredSize measuredSize = getMeasuredSize(element, null); measuredAndUpdate(element, measuredSize, layoutDependencyTree); } + VConsole.log("Measured " + nonPaintableElements.size() + + " non paintable elements"); } private MeasureResult measuredAndUpdate(Element element, @@ -285,7 +294,7 @@ public class LayoutManager { JsArrayString dependents = measuredSize.getDependents(); for (int i = 0; i < dependents.length(); i++) { String pid = dependents.get(i); - ComponentConnector dependent = (ComponentConnector) connection + ManagedLayout dependent = (ManagedLayout) connection .getConnectorMap().getConnector(pid); if (dependent != null) { if (measureResult.isHeightChanged()) { @@ -399,4 +408,33 @@ public class LayoutManager { public int getMarginLeft(Element element) { return getMeasuredSize(element, nullSize).getMarginLeft(); } + + public void reportOuterHeight(ComponentConnector component, int outerHeight) { + if (!isLayoutRunning()) { + throw new IllegalStateException( + "Can only report sizes when layout is running"); + } + MeasuredSize measuredSize = getMeasuredSize(component); + boolean heightChanged = measuredSize.setOuterHeight(outerHeight); + + if (heightChanged) { + currentDependencyTree.markHeightAsChanged(component); + } + currentDependencyTree.setNeedsVerticalMeasure(component, false); + } + + public void reportOuterWidth(ComponentConnector component, int outerWidth) { + if (!isLayoutRunning()) { + throw new IllegalStateException( + "Can only report sizes when layout is running"); + } + + MeasuredSize measuredSize = getMeasuredSize(component); + boolean widthChanged = measuredSize.setOuterWidth(outerWidth); + + if (widthChanged) { + currentDependencyTree.markWidthAsChanged(component); + } + currentDependencyTree.setNeedsHorizontalMeasure(component, false); + } } diff --git a/src/com/vaadin/terminal/gwt/client/ui/AbstractOrderedLayoutConnector.java b/src/com/vaadin/terminal/gwt/client/ui/AbstractOrderedLayoutConnector.java index e58dce5223..825b54bab6 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/AbstractOrderedLayoutConnector.java +++ b/src/com/vaadin/terminal/gwt/client/ui/AbstractOrderedLayoutConnector.java @@ -24,8 +24,8 @@ import com.vaadin.terminal.gwt.client.ui.layout.VLayoutSlot; public abstract class AbstractOrderedLayoutConnector extends AbstractComponentContainerConnector implements DirectionalManagedLayout { - public interface AbstractOrderedLayoutServerRPC extends - LayoutClickRPC, ServerRpc { + public interface AbstractOrderedLayoutServerRPC extends LayoutClickRPC, + ServerRpc { } @@ -174,14 +174,23 @@ public abstract class AbstractOrderedLayoutConnector extends Style ownStyle = getWidget().getElement().getStyle(); if (isUndefined) { - ownStyle.setPropertyPx(getSizeProperty(isVertical), - getSizeForInnerSize(allocatedSize, isVertical)); + int outerSize = getSizeForInnerSize(allocatedSize, isVertical); + ownStyle.setPropertyPx(getSizeProperty(isVertical), outerSize); + reportUndefinedSize(outerSize, isVertical); } else { ownStyle.setProperty(getSizeProperty(isVertical), getDefinedSize(isVertical)); } } + private void reportUndefinedSize(int outerSize, boolean isVertical) { + if (isVertical) { + getLayoutManager().reportOuterHeight(this, outerSize); + } else { + getLayoutManager().reportOuterWidth(this, outerSize); + } + } + private int getSpacingInDirection(boolean isVertical) { if (isVertical) { return getLayoutManager().getOuterHeight( @@ -212,8 +221,11 @@ public abstract class AbstractOrderedLayoutConnector extends Style ownStyle = getWidget().getElement().getStyle(); if (isUndefined) { + int outerSize = getSizeForInnerSize(allocatedSize, + !getWidget().isVertical); ownStyle.setPropertyPx(getSizeProperty(!getWidget().isVertical), - getSizeForInnerSize(allocatedSize, !getWidget().isVertical)); + outerSize); + reportUndefinedSize(outerSize, !isVertical); } else { ownStyle.setProperty(getSizeProperty(!getWidget().isVertical), getDefinedSize(!getWidget().isVertical)); diff --git a/src/com/vaadin/terminal/gwt/client/ui/layout/ComponentConnectorLayoutSlot.java b/src/com/vaadin/terminal/gwt/client/ui/layout/ComponentConnectorLayoutSlot.java index 8ff012e086..d479e8da9d 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/layout/ComponentConnectorLayoutSlot.java +++ b/src/com/vaadin/terminal/gwt/client/ui/layout/ComponentConnectorLayoutSlot.java @@ -57,6 +57,16 @@ public class ComponentConnectorLayoutSlot extends VLayoutSlot { } @Override + protected void reportActualRelativeHeight(int allocatedHeight) { + getLayoutManager().reportOuterHeight(child, allocatedHeight); + } + + @Override + protected void reportActualRelativeWidth(int allocatedWidth) { + getLayoutManager().reportOuterWidth(child, allocatedWidth); + } + + @Override public int getWidgetHeight() { return getLayoutManager() .getOuterHeight(child.getWidget().getElement()); diff --git a/src/com/vaadin/terminal/gwt/client/ui/layout/LayoutDependencyTree.java b/src/com/vaadin/terminal/gwt/client/ui/layout/LayoutDependencyTree.java index d8164b9587..acfd9dcf0f 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/layout/LayoutDependencyTree.java +++ b/src/com/vaadin/terminal/gwt/client/ui/layout/LayoutDependencyTree.java @@ -11,6 +11,7 @@ import com.vaadin.terminal.gwt.client.ComponentConnector; import com.vaadin.terminal.gwt.client.ComponentContainerConnector; import com.vaadin.terminal.gwt.client.ComponentState; import com.vaadin.terminal.gwt.client.Util; +import com.vaadin.terminal.gwt.client.ui.ManagedLayout; public class LayoutDependencyTree { private class LayoutDependency { @@ -44,7 +45,7 @@ public class LayoutDependencyTree { boolean removed = layoutBlockers.remove(blocker); if (removed && layoutBlockers.isEmpty()) { if (needsLayout) { - getLayoutQueue(direction).add(connector); + getLayoutQueue(direction).add((ManagedLayout) connector); } else { propagateNoUpcomingLayout(); } @@ -97,13 +98,17 @@ public class LayoutDependencyTree { } public void setNeedsLayout(boolean needsLayout) { + if (!(connector instanceof ManagedLayout)) { + throw new IllegalStateException( + "Only managed layouts can need layout"); + } if (needsLayout && !this.needsLayout) { // If enabling needsLayout this.needsLayout = needsLayout; if (layoutBlockers.isEmpty()) { // Add to queue if there are no blockers - getLayoutQueue(direction).add(connector); + getLayoutQueue(direction).add((ManagedLayout) connector); // Only need to propagate if not already propagated when // setting blockers propagatePotentialLayout(); @@ -204,7 +209,13 @@ public class LayoutDependencyTree { for (ComponentConnector connector : getNeedsSizeForLayout()) { LayoutDependency layoutDependency = getDependency(connector, direction); - layoutDependency.setNeedsLayout(true); + if (connector instanceof ManagedLayout) { + layoutDependency.setNeedsLayout(true); + } else { + // Should simulate setNeedsLayout(true) + markAsLayouted -> + // propagate needs measure + layoutDependency.propagatePostLayoutMeasure(); + } } } @@ -216,6 +227,10 @@ public class LayoutDependencyTree { return; } setNeedsLayout(false); + propagatePostLayoutMeasure(); + } + + private void propagatePostLayoutMeasure() { for (ComponentConnector resized : getResizedByLayout()) { LayoutDependency layoutDependency = getDependency(resized, direction); @@ -281,10 +296,19 @@ public class LayoutDependencyTree { public void setNeedsMeasure(ComponentConnector connector, boolean needsMeasure) { + setNeedsHorizontalMeasure(connector, needsMeasure); + setNeedsVerticalMeasure(connector, needsMeasure); + } + + public void setNeedsHorizontalMeasure(ComponentConnector connector, + boolean needsMeasure) { LayoutDependency dependency = getDependency(connector, HORIZONTAL); dependency.setNeedsMeasure(needsMeasure); + } - dependency = getDependency(connector, VERTICAL); + public void setNeedsVerticalMeasure(ComponentConnector connector, + boolean needsMeasure) { + LayoutDependency dependency = getDependency(connector, VERTICAL); dependency.setNeedsMeasure(needsMeasure); } @@ -301,8 +325,8 @@ public class LayoutDependencyTree { } @SuppressWarnings("unchecked") - private Collection<ComponentConnector> getLayoutQueue(int direction) { - return (Collection<ComponentConnector>) layoutQueueInDirection[direction]; + private Collection<ManagedLayout> getLayoutQueue(int direction) { + return (Collection<ManagedLayout>) layoutQueueInDirection[direction]; } @SuppressWarnings("unchecked") @@ -310,25 +334,24 @@ public class LayoutDependencyTree { return (Collection<ComponentConnector>) measureQueueInDirection[direction]; } - public void setNeedsHorizontalLayout(ComponentConnector connector, + public void setNeedsHorizontalLayout(ManagedLayout layout, boolean needsLayout) { - LayoutDependency dependency = getDependency(connector, HORIZONTAL); + LayoutDependency dependency = getDependency(layout, HORIZONTAL); dependency.setNeedsLayout(needsLayout); } - public void setNeedsVerticalLayout(ComponentConnector connector, - boolean needsLayout) { - LayoutDependency dependency = getDependency(connector, VERTICAL); + public void setNeedsVerticalLayout(ManagedLayout layout, boolean needsLayout) { + LayoutDependency dependency = getDependency(layout, VERTICAL); dependency.setNeedsLayout(needsLayout); } - public void markAsHorizontallyLayouted(ComponentConnector connector) { - LayoutDependency dependency = getDependency(connector, HORIZONTAL); + public void markAsHorizontallyLayouted(ManagedLayout layout) { + LayoutDependency dependency = getDependency(layout, HORIZONTAL); dependency.markAsLayouted(); } - public void markAsVerticallyLayouted(ComponentConnector connector) { - LayoutDependency dependency = getDependency(connector, VERTICAL); + public void markAsVerticallyLayouted(ManagedLayout layout) { + LayoutDependency dependency = getDependency(layout, VERTICAL); dependency.markAsLayouted(); } @@ -388,14 +411,27 @@ public class LayoutDependencyTree { return b.toString(); } - public ComponentConnector[] getHorizontalLayoutTargets() { - Collection<ComponentConnector> queue = getLayoutQueue(HORIZONTAL); - return queue.toArray(new ComponentConnector[queue.size()]); + public boolean hasConnectorsToMeasure() { + return !measureQueueInDirection[HORIZONTAL].isEmpty() + || !measureQueueInDirection[VERTICAL].isEmpty(); + } + + public boolean hasHorizontalConnectorToLayout() { + return !getLayoutQueue(HORIZONTAL).isEmpty(); + } + + public boolean hasVerticaConnectorToLayout() { + return !getLayoutQueue(VERTICAL).isEmpty(); + } + + public ManagedLayout[] getHorizontalLayoutTargets() { + Collection<ManagedLayout> queue = getLayoutQueue(HORIZONTAL); + return queue.toArray(new ManagedLayout[queue.size()]); } - public ComponentConnector[] getVerticalLayoutTargets() { - Collection<ComponentConnector> queue = getLayoutQueue(VERTICAL); - return queue.toArray(new ComponentConnector[queue.size()]); + public ManagedLayout[] getVerticalLayoutTargets() { + Collection<ManagedLayout> queue = getLayoutQueue(VERTICAL); + return queue.toArray(new ManagedLayout[queue.size()]); } public Collection<ComponentConnector> getMeasureTargets() { diff --git a/src/com/vaadin/terminal/gwt/client/ui/layout/VLayoutSlot.java b/src/com/vaadin/terminal/gwt/client/ui/layout/VLayoutSlot.java index 1caa87cce5..c02061a2fe 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/layout/VLayoutSlot.java +++ b/src/com/vaadin/terminal/gwt/client/ui/layout/VLayoutSlot.java @@ -94,14 +94,20 @@ public abstract class VLayoutSlot { style.clearProperty("width"); } + double allocatedContentWidth = 0; + if (isRelativeWidth()) { + String percentWidth = getWidget().getElement().getStyle() + .getWidth(); + double percentage = parsePercent(percentWidth); + allocatedContentWidth = availableWidth * (percentage / 100); + reportActualRelativeWidth(Math.round((float) allocatedContentWidth)); + } + AlignmentInfo alignment = getAlignment(); if (!alignment.isLeft()) { double usedWidth; if (isRelativeWidth()) { - String percentWidth = getWidget().getElement().getStyle() - .getWidth(); - double percentage = parsePercent(percentWidth); - usedWidth = availableWidth * (percentage / 100); + usedWidth = allocatedContentWidth; } else { usedWidth = getWidgetWidth(); } @@ -156,13 +162,20 @@ public abstract class VLayoutSlot { style.clearHeight(); } + double allocatedContentHeight = 0; + if (isRelativeHeight()) { + String height = getWidget().getElement().getStyle().getHeight(); + double percentage = parsePercent(height); + allocatedContentHeight = contentHeight * (percentage / 100); + reportActualRelativeHeight(Math + .round((float) allocatedContentHeight)); + } + AlignmentInfo alignment = getAlignment(); if (!alignment.isTop()) { double usedHeight; if (isRelativeHeight()) { - String height = getWidget().getElement().getStyle().getHeight(); - double percentage = parsePercent(height); - usedHeight = captionHeight + contentHeight * (percentage / 100); + usedHeight = captionHeight + allocatedContentHeight; } else { usedHeight = getUsedHeight(); } @@ -176,6 +189,14 @@ public abstract class VLayoutSlot { style.setTop(currentLocation, Unit.PX); } + protected void reportActualRelativeHeight(int allocatedHeight) { + // Default implementation does nothing + } + + protected void reportActualRelativeWidth(int allocatedWidth) { + // Default implementation does nothing + } + public void positionInDirection(double currentLocation, double allocatedSpace, boolean isVertical) { if (isVertical) { |