summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLeif Åstrand <leif@vaadin.com>2012-04-12 10:39:20 +0300
committerLeif Åstrand <leif@vaadin.com>2012-04-12 10:39:20 +0300
commitb65f72265230869b03a09c4e8c353f39b8cc1ecf (patch)
tree731f563917e0f7316cbf2f5e250d9c7c8c569d26
parenteff08ecdc070f998d4efd5c1f367173d0321708d (diff)
parenta6e0aed3ba959bc81b2e97ccd9e1098190501ebb (diff)
downloadvaadin-framework-b65f72265230869b03a09c4e8c353f39b8cc1ecf.tar.gz
vaadin-framework-b65f72265230869b03a09c4e8c353f39b8cc1ecf.zip
Merge branch 'layoutgraph'
Conflicts: src/com/vaadin/terminal/gwt/client/ApplicationConnection.java src/com/vaadin/terminal/gwt/client/LayoutManager.java src/com/vaadin/terminal/gwt/client/ui/AbsoluteLayoutConnector.java src/com/vaadin/terminal/gwt/client/ui/AbstractOrderedLayoutConnector.java src/com/vaadin/terminal/gwt/client/ui/AbstractSplitPanelConnector.java src/com/vaadin/terminal/gwt/client/ui/AccordionConnector.java src/com/vaadin/terminal/gwt/client/ui/FormConnector.java src/com/vaadin/terminal/gwt/client/ui/GridLayoutConnector.java src/com/vaadin/terminal/gwt/client/ui/PanelConnector.java src/com/vaadin/terminal/gwt/client/ui/RootConnector.java src/com/vaadin/terminal/gwt/client/ui/TableConnector.java src/com/vaadin/terminal/gwt/client/ui/TabsheetConnector.java src/com/vaadin/terminal/gwt/client/ui/TwinColSelectConnector.java src/com/vaadin/terminal/gwt/client/ui/VAbstractSplitPanel.java src/com/vaadin/terminal/gwt/client/ui/VAccordion.java src/com/vaadin/terminal/gwt/client/ui/VDragAndDropWrapper.java src/com/vaadin/terminal/gwt/client/ui/VGridLayout.java src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java src/com/vaadin/terminal/gwt/client/ui/VTabsheet.java src/com/vaadin/terminal/gwt/client/ui/VTabsheetPanel.java src/com/vaadin/terminal/gwt/client/ui/VView.java src/com/vaadin/terminal/gwt/client/ui/VWindow.java src/com/vaadin/terminal/gwt/client/ui/WindowConnector.java
-rw-r--r--src/com/vaadin/terminal/gwt/client/ApplicationConnection.java77
-rw-r--r--src/com/vaadin/terminal/gwt/client/BrowserInfo.java12
-rw-r--r--src/com/vaadin/terminal/gwt/client/LayoutManager.java620
-rw-r--r--src/com/vaadin/terminal/gwt/client/MeasuredSize.java73
-rw-r--r--src/com/vaadin/terminal/gwt/client/Util.java29
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/absolutelayout/AbsoluteLayoutConnector.java2
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/accordion/AccordionConnector.java3
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/accordion/VAccordion.java3
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/draganddropwrapper/VDragAndDropWrapper.java10
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/form/FormConnector.java52
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/gridlayout/GridLayoutConnector.java13
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/gridlayout/VGridLayout.java8
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/layout/ComponentConnectorLayoutSlot.java10
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/layout/ElementResizeEvent.java25
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/layout/ElementResizeListener.java9
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/layout/LayoutDependencyTree.java521
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/layout/MayScrollChildren.java10
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/layout/VLayoutSlot.java35
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/orderedlayout/AbstractOrderedLayoutConnector.java36
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/panel/PanelConnector.java17
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/root/RootConnector.java10
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/root/VRoot.java11
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/splitpanel/AbstractSplitPanelConnector.java24
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/splitpanel/VAbstractSplitPanel.java49
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/table/TableConnector.java14
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/table/VScrollTable.java7
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/tabsheet/TabsheetConnector.java3
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/tabsheet/VTabsheet.java1
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/tabsheet/VTabsheetPanel.java15
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/twincolselect/TwinColSelectConnector.java6
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/window/VWindow.java6
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/window/WindowConnector.java15
32 files changed, 1397 insertions, 329 deletions
diff --git a/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java b/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java
index 555112a636..a2816728f9 100644
--- a/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java
+++ b/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java
@@ -1130,7 +1130,9 @@ public class ApplicationConnection {
+ (updateDuration.elapsedMillis() - startProcessing)
+ " ms");
- doLayout(false);
+ LayoutManager layoutManager = getLayoutManager();
+ layoutManager.setEverythingNeedsMeasure();
+ layoutManager.layoutNow();
updateDuration
.logDuration(" * Layout processing completed", 10);
@@ -1229,7 +1231,8 @@ public class ApplicationConnection {
} else if ((cc instanceof RootConnector && cc == getRootConnector())) {
// RootConnector for this connection, leave as-is
} else if (cc instanceof WindowConnector
- && getRootConnector().hasSubWindow((WindowConnector) cc)) {
+ && getRootConnector().hasSubWindow(
+ (WindowConnector) cc)) {
// Sub window attached to this RootConnector, leave
// as-is
} else {
@@ -1279,8 +1282,10 @@ public class ApplicationConnection {
// RootConnector has been created but not
// initialized as the connector id has not been
// known
- connectorMap.registerConnector(connectorId, rootConnector);
- rootConnector.doInit(connectorId, ApplicationConnection.this);
+ connectorMap.registerConnector(connectorId,
+ rootConnector);
+ rootConnector.doInit(connectorId,
+ ApplicationConnection.this);
}
} catch (final Throwable e) {
VConsole.error(e);
@@ -1945,7 +1950,7 @@ public class ApplicationConnection {
public void forceLayout() {
Duration duration = new Duration();
- layoutManager.foceLayout();
+ layoutManager.forceLayout();
VConsole.log("forceLayout in " + duration.elapsedMillis() + " ms");
}
@@ -2189,40 +2194,8 @@ public class ApplicationConnection {
}
- /*
- * Helper to run layout functions triggered by child components with a
- * decent interval.
- */
- private final Timer layoutTimer = new Timer() {
-
- private boolean isPending = false;
-
- @Override
- public void schedule(int delayMillis) {
- if (!isPending) {
- super.schedule(delayMillis);
- isPending = true;
- }
- }
-
- @Override
- public void run() {
- VConsole.log("Running re-layout of " + rootConnector.getClass().getName());
- runDescendentsLayout(rootConnector.getWidget());
- isPending = false;
- }
- };
-
private ConnectorMap connectorMap = GWT.create(ConnectorMap.class);
- /**
- * Components can call this function to run all layout functions. This is
- * usually done, when component knows that its size has changed.
- */
- public void requestLayoutPhase() {
- layoutTimer.schedule(500);
- }
-
protected String getUidlSecurityKey() {
return uidlSecurityKey;
}
@@ -2384,36 +2357,6 @@ public class ApplicationConnection {
eventIdentifier);
}
- private boolean layoutPending = false;
- private ScheduledCommand layoutCommand = new ScheduledCommand() {
- public void execute() {
- /*
- * Layout again if a new layout is requested while the current one
- * is running.
- */
- while (layoutPending) {
- layoutPending = false;
- layoutManager.doLayout();
- }
- }
- };
-
- public void doLayout(boolean lazy) {
- if (!lazy) {
- layoutPending = true;
- layoutCommand.execute();
- } else if (!layoutPending) {
- layoutPending = true;
- /*
- * Current layoutCommand will do layouts again if layoutScheduled is
- * set to true -> no need to schedule another command
- */
- if (!layoutManager.isLayoutRunning()) {
- Scheduler.get().scheduleDeferred(layoutCommand);
- }
- }
- }
-
LayoutManager getLayoutManager() {
return layoutManager;
}
diff --git a/src/com/vaadin/terminal/gwt/client/BrowserInfo.java b/src/com/vaadin/terminal/gwt/client/BrowserInfo.java
index 50a59e4975..ef1dc481b1 100644
--- a/src/com/vaadin/terminal/gwt/client/BrowserInfo.java
+++ b/src/com/vaadin/terminal/gwt/client/BrowserInfo.java
@@ -300,4 +300,16 @@ public class BrowserInfo {
return touchDevice;
}
+ /**
+ * Indicates whether the browser might require juggling to properly update
+ * sizes inside elements with overflow: auto.
+ *
+ * @return <code>true</code> if the browser requires the workaround,
+ * otherwise <code>false</code>
+ */
+ public boolean requiresOverflowAutoFix() {
+ return (getWebkitVersion() > 0 || getOperaVersion() >= 11)
+ && Util.getNativeScrollbarSize() > 0;
+ }
+
}
diff --git a/src/com/vaadin/terminal/gwt/client/LayoutManager.java b/src/com/vaadin/terminal/gwt/client/LayoutManager.java
index 60a2d3543a..4338f1284a 100644
--- a/src/com/vaadin/terminal/gwt/client/LayoutManager.java
+++ b/src/com/vaadin/terminal/gwt/client/LayoutManager.java
@@ -3,23 +3,57 @@
*/
package com.vaadin.terminal.gwt.client;
+import java.util.Collection;
+import java.util.HashMap;
import java.util.HashSet;
+import java.util.Map;
import java.util.Set;
import com.google.gwt.core.client.Duration;
import com.google.gwt.core.client.JsArrayString;
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.user.client.Timer;
+import com.vaadin.terminal.gwt.client.MeasuredSize.MeasureResult;
import com.vaadin.terminal.gwt.client.ui.ManagedLayout;
import com.vaadin.terminal.gwt.client.ui.PostLayoutListener;
import com.vaadin.terminal.gwt.client.ui.SimpleManagedLayout;
+import com.vaadin.terminal.gwt.client.ui.layout.ElementResizeEvent;
+import com.vaadin.terminal.gwt.client.ui.layout.ElementResizeListener;
+import com.vaadin.terminal.gwt.client.ui.layout.LayoutDependencyTree;
import com.vaadin.terminal.gwt.client.ui.notification.VNotification;
public class LayoutManager {
private static final String LOOP_ABORT_MESSAGE = "Aborting layout after 100 passes. This would probably be an infinite loop.";
+
+ private static final boolean debugLogging = false;
+
private ApplicationConnection connection;
- private final Set<Element> nonPaintableElements = new HashSet<Element>();
+ private final Set<Element> measuredNonPaintableElements = 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>();
+
+ private final Collection<ComponentConnector> needsMeasure = new HashSet<ComponentConnector>();
+
+ private Collection<ComponentConnector> pendingOverflowFixes = new HashSet<ComponentConnector>();
+
+ private final Map<Element, Collection<ElementResizeListener>> elementResizeListeners = new HashMap<Element, Collection<ElementResizeListener>>();
+ private final Set<Element> listenersToFire = new HashSet<Element>();
+
+ private boolean layoutPending = false;
+ private Timer layoutTimer = new Timer() {
+ @Override
+ public void run() {
+ cancel();
+ layoutNow();
+ }
+ };
+ private boolean everythingNeedsMeasure = false;
public void setConnection(ApplicationConnection connection) {
if (this.connection != null) {
@@ -35,14 +69,7 @@ public class LayoutManager {
public void registerDependency(ManagedLayout owner, Element element) {
MeasuredSize measuredSize = ensureMeasured(element);
-
- MeasuredSize ownerSize = getMeasuredSize(owner);
- if (measuredSize.isHeightNeedsUpdate()) {
- ownerSize.setHeightNeedsUpdate();
- }
- if (measuredSize.isWidthNeedsUpdate()) {
- ownerSize.setWidthNeedsUpdate();
- }
+ setNeedsUpdate(owner);
measuredSize.addDependent(owner.getConnectorId());
}
@@ -52,7 +79,7 @@ public class LayoutManager {
measuredSize = new MeasuredSize();
if (ConnectorMap.get(connection).getConnector(element) == null) {
- nonPaintableElements.add(element);
+ measuredNonPaintableElements.add(element);
}
setMeasuredSize(element, measuredSize);
}
@@ -62,6 +89,8 @@ public class LayoutManager {
private boolean needsMeasure(Element e) {
if (connection.getConnectorMap().getConnectorId(e) != null) {
return true;
+ } else if (elementResizeListeners.containsKey(e)) {
+ return true;
} else if (getMeasuredSize(e, nullSize).hasDependents()) {
return true;
} else {
@@ -85,8 +114,8 @@ public class LayoutManager {
return element.vMeasuredSize || defaultSize;
}-*/;
- private final MeasuredSize getMeasuredSize(ComponentConnector paintable) {
- Element element = paintable.getWidget().getElement();
+ private final MeasuredSize getMeasuredSize(ComponentConnector connector) {
+ Element element = connector.getWidget().getElement();
MeasuredSize measuredSize = getMeasuredSize(element, null);
if (measuredSize == null) {
measuredSize = new MeasuredSize();
@@ -101,129 +130,187 @@ public class LayoutManager {
return;
}
measuredSize.removeDependent(owner.getConnectorId());
- if (!needsMeasure(element)) {
- nonPaintableElements.remove(element);
- setMeasuredSize(element, null);
- }
+ stopMeasuringIfUnecessary(element);
}
public boolean isLayoutRunning() {
- return layoutRunning;
+ return currentDependencyTree != null;
+ }
+
+ private void countLayout(Map<ManagedLayout, Integer> layoutCounts,
+ ManagedLayout layout) {
+ Integer count = layoutCounts.get(layout);
+ if (count == null) {
+ count = Integer.valueOf(0);
+ } else {
+ count = Integer.valueOf(count.intValue() + 1);
+ }
+ layoutCounts.put(layout, count);
+ if (count.intValue() > 2) {
+ VConsole.error(Util.getConnectorString(layout)
+ + " has been layouted " + count.intValue() + " times");
+ }
}
- public void doLayout() {
- if (layoutRunning) {
+ private void layoutLater() {
+ if (!layoutPending) {
+ layoutPending = true;
+ layoutTimer.schedule(100);
+ }
+ }
+
+ public void layoutNow() {
+ if (isLayoutRunning()) {
throw new IllegalStateException(
"Can't start a new layout phase before the previous layout phase ends.");
}
+ layoutPending = false;
+ try {
+ currentDependencyTree = new LayoutDependencyTree();
+ doLayout();
+ } finally {
+ currentDependencyTree = null;
+ }
+ }
+
+ private void doLayout() {
VConsole.log("Starting layout phase");
- layoutRunning = true;
- ConnectorMap paintableMap = connection.getConnectorMap();
- ComponentConnector[] paintableWidgets = paintableMap
- .getComponentConnectors();
+ Map<ManagedLayout, Integer> layoutCounts = new HashMap<ManagedLayout, Integer>();
int passes = 0;
Duration totalDuration = new Duration();
+ for (ManagedLayout layout : needsHorizontalLayout) {
+ currentDependencyTree.setNeedsHorizontalLayout(layout, true);
+ }
+ for (ManagedLayout layout : needsVerticalLayout) {
+ currentDependencyTree.setNeedsVerticalLayout(layout, true);
+ }
+ needsHorizontalLayout.clear();
+ needsVerticalLayout.clear();
+
+ for (ComponentConnector connector : needsMeasure) {
+ currentDependencyTree.setNeedsMeasure(connector, true);
+ }
+ needsMeasure.clear();
+
+ measureNonPaintables();
+
+ VConsole.log("Layout init in " + totalDuration.elapsedMillis() + " ms");
+
while (true) {
Duration passDuration = new Duration();
passes++;
- measureElements(paintableWidgets);
-
- FastStringSet needsHeightUpdate = FastStringSet.create();
- FastStringSet needsWidthUpdate = FastStringSet.create();
-
- for (ComponentConnector paintable : paintableWidgets) {
- MeasuredSize measuredSize = getMeasuredSize(paintable);
- boolean managed = isManagedLayout(paintable);
- ComponentContainerConnector parent = paintable.getParent();
- boolean managedParent = parent != null
- && isManagedLayout(parent);
+ int measuredConnectorCount = measureConnectors(
+ currentDependencyTree, everythingNeedsMeasure);
+ everythingNeedsMeasure = false;
+ if (measuredConnectorCount == 0) {
+ VConsole.log("No more changes in pass " + passes);
+ break;
+ }
- if (measuredSize.isHeightNeedsUpdate()) {
- if (managed) {
- needsHeightUpdate.add(paintable.getConnectorId());
- }
- if (!paintable.isRelativeHeight() && managedParent) {
- needsHeightUpdate.add(parent.getConnectorId());
- }
- }
- if (measuredSize.isWidthNeedsUpdate()) {
- if (managed) {
- needsWidthUpdate.add(paintable.getConnectorId());
- }
- if (!paintable.isRelativeWidth() && managedParent) {
- needsWidthUpdate.add(parent.getConnectorId());
+ int measureTime = passDuration.elapsedMillis();
+ VConsole.log(" Measured " + measuredConnectorCount
+ + " elements in " + measureTime + " ms");
+
+ if (!listenersToFire.isEmpty()) {
+ for (Element element : listenersToFire) {
+ Collection<ElementResizeListener> listeners = elementResizeListeners
+ .get(element);
+ ElementResizeListener[] array = listeners
+ .toArray(new ElementResizeListener[listeners.size()]);
+ ElementResizeEvent event = new ElementResizeEvent(this,
+ element);
+ for (ElementResizeListener listener : array) {
+ listener.onElementResize(event);
}
}
- measuredSize.clearDirtyState();
+ int measureListenerTime = passDuration.elapsedMillis();
+ VConsole.log(" Fired resize listeners for "
+ + listenersToFire.size() + " elements in "
+ + (measureListenerTime - measureTime) + " ms");
+ measureTime = measuredConnectorCount;
+ listenersToFire.clear();
}
- int measureTime = passDuration.elapsedMillis();
- VConsole.log("Measure in " + measureTime + " ms");
-
FastStringSet updatedSet = FastStringSet.create();
- JsArrayString needsWidthUpdateArray = needsWidthUpdate.dump();
-
- for (int i = 0; i < needsWidthUpdateArray.length(); i++) {
- String pid = needsWidthUpdateArray.get(i);
-
- ServerConnector paintable = paintableMap.getConnector(pid);
- if (paintable instanceof DirectionalManagedLayout) {
- DirectionalManagedLayout cl = (DirectionalManagedLayout) paintable;
- cl.layoutHorizontally();
- } else if (paintable instanceof SimpleManagedLayout) {
- SimpleManagedLayout rr = (SimpleManagedLayout) paintable;
- rr.layout();
- needsHeightUpdate.remove(pid);
+ while (currentDependencyTree.hasHorizontalConnectorToLayout()
+ || currentDependencyTree.hasVerticaConnectorToLayout()) {
+ for (ManagedLayout layout : currentDependencyTree
+ .getHorizontalLayoutTargets()) {
+ if (layout instanceof DirectionalManagedLayout) {
+ currentDependencyTree
+ .markAsHorizontallyLayouted(layout);
+ DirectionalManagedLayout cl = (DirectionalManagedLayout) layout;
+ cl.layoutHorizontally();
+ countLayout(layoutCounts, cl);
+ } else {
+ currentDependencyTree
+ .markAsHorizontallyLayouted(layout);
+ currentDependencyTree.markAsVerticallyLayouted(layout);
+ SimpleManagedLayout rr = (SimpleManagedLayout) layout;
+ rr.layout();
+ countLayout(layoutCounts, rr);
+ }
+ if (debugLogging) {
+ updatedSet.add(layout.getConnectorId());
+ }
}
- updatedSet.add(pid);
- }
- JsArrayString needsHeightUpdateArray = needsHeightUpdate.dump();
- for (int i = 0; i < needsHeightUpdateArray.length(); i++) {
- String pid = needsHeightUpdateArray.get(i);
-
- ComponentConnector paintable = (ComponentConnector) paintableMap
- .getConnector(pid);
- if (paintable instanceof DirectionalManagedLayout) {
- DirectionalManagedLayout cl = (DirectionalManagedLayout) paintable;
- cl.layoutVertically();
- } else if (paintable instanceof SimpleManagedLayout) {
- SimpleManagedLayout rr = (SimpleManagedLayout) paintable;
- rr.layout();
+ for (ManagedLayout layout : currentDependencyTree
+ .getVerticalLayoutTargets()) {
+ if (layout instanceof DirectionalManagedLayout) {
+ currentDependencyTree.markAsVerticallyLayouted(layout);
+ DirectionalManagedLayout cl = (DirectionalManagedLayout) layout;
+ cl.layoutVertically();
+ countLayout(layoutCounts, cl);
+ } else {
+ currentDependencyTree
+ .markAsHorizontallyLayouted(layout);
+ currentDependencyTree.markAsVerticallyLayouted(layout);
+ SimpleManagedLayout rr = (SimpleManagedLayout) layout;
+ rr.layout();
+ countLayout(layoutCounts, rr);
+ }
+ if (debugLogging) {
+ updatedSet.add(layout.getConnectorId());
+ }
}
- updatedSet.add(pid);
}
- JsArrayString changed = updatedSet.dump();
- VConsole.log(changed.length() + " requestLayout invocations in "
- + (passDuration.elapsedMillis() - measureTime) + "ms");
-
- StringBuilder b = new StringBuilder();
- b.append(changed.length());
- b.append(" changed widgets in pass ");
- b.append(passes);
- b.append(" in ");
- b.append(passDuration.elapsedMillis());
- b.append(" ms: ");
- if (changed.length() < 10) {
- for (int i = 0; i < changed.length(); i++) {
- if (i != 0) {
- b.append(", ");
+ if (debugLogging) {
+ JsArrayString changedCids = updatedSet.dump();
+
+ StringBuilder b = new StringBuilder(" ");
+ b.append(changedCids.length());
+ b.append(" requestLayout invocations in ");
+ b.append(passDuration.elapsedMillis() - measureTime);
+ b.append(" ms");
+ if (changedCids.length() < 30) {
+ for (int i = 0; i < changedCids.length(); i++) {
+ if (i != 0) {
+ b.append(", ");
+ } else {
+ b.append(": ");
+ }
+ String connectorString = changedCids.get(i);
+ if (changedCids.length() < 10) {
+ ServerConnector connector = ConnectorMap.get(
+ connection).getConnector(connectorString);
+ connectorString = Util
+ .getConnectorString(connector);
+ }
+ b.append(connectorString);
}
- b.append(changed.get(i));
}
+ VConsole.log(b.toString());
}
- VConsole.log(b.toString());
- if (changed.length() == 0) {
- VConsole.log("No more changes in pass " + passes);
- break;
- }
+ VConsole.log("Pass " + passes + " completed in "
+ + passDuration.elapsedMillis() + " ms");
if (passes > 100) {
VConsole.log(LOOP_ABORT_MESSAGE);
@@ -234,82 +321,232 @@ 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;
VConsole.log("Total layout phase time: "
+ totalDuration.elapsedMillis() + "ms");
}
- private void measureElements(ComponentConnector[] paintableWidgets) {
+ private void logConnectorStatus(int connectorId) {
+ currentDependencyTree
+ .logDependencyStatus((ComponentConnector) ConnectorMap.get(
+ connection).getConnector(Integer.toString(connectorId)));
+ }
+
+ private int measureConnectors(LayoutDependencyTree layoutDependencyTree,
+ boolean measureAll) {
+ if (!pendingOverflowFixes.isEmpty()) {
+ Duration duration = new Duration();
+
+ HashMap<Element, String> originalOverflows = new HashMap<Element, String>();
+
+ HashSet<ComponentConnector> delayedOverflowFixes = new HashSet<ComponentConnector>();
+
+ // First set overflow to hidden (and save previous value so it can
+ // be restored later)
+ for (ComponentConnector componentConnector : pendingOverflowFixes) {
+ // Delay the overflow fix if the involved connectors might still
+ // change
+ if (!currentDependencyTree
+ .noMoreChangesExpected(componentConnector)
+ || !currentDependencyTree
+ .noMoreChangesExpected(componentConnector
+ .getParent())) {
+ delayedOverflowFixes.add(componentConnector);
+ continue;
+ }
+
+ if (debugLogging) {
+ VConsole.log("Doing overflow fix for "
+ + Util.getConnectorString(componentConnector)
+ + " in "
+ + Util.getConnectorString(componentConnector
+ .getParent()));
+ }
+
+ Element parentElement = componentConnector.getWidget()
+ .getElement().getParentElement();
+ Style style = parentElement.getStyle();
+ String originalOverflow = style.getOverflow();
+
+ if (originalOverflow != null
+ && !originalOverflows.containsKey(parentElement)) {
+ // Store original value for restore, but only the first time
+ // the value is changed
+ originalOverflows.put(parentElement, originalOverflow);
+ }
+
+ style.setOverflow(Overflow.HIDDEN);
+ }
+
+ pendingOverflowFixes.removeAll(delayedOverflowFixes);
+
+ // Then ensure all scrolling elements are reflowed by measuring
+ for (ComponentConnector componentConnector : pendingOverflowFixes) {
+ componentConnector.getWidget().getElement().getParentElement()
+ .getOffsetHeight();
+ }
+
+ // Finally restore old overflow value and update bookkeeping
+ for (ComponentConnector componentConnector : pendingOverflowFixes) {
+ Element parentElement = componentConnector.getWidget()
+ .getElement().getParentElement();
+ parentElement.getStyle().setProperty("overflow",
+ originalOverflows.get(parentElement));
+
+ layoutDependencyTree.setNeedsMeasure(componentConnector, true);
+ }
+ if (!pendingOverflowFixes.isEmpty()) {
+ VConsole.log("Did overflow fix for "
+ + pendingOverflowFixes.size() + " elements in "
+ + duration.elapsedMillis() + " ms");
+ }
+ pendingOverflowFixes = delayedOverflowFixes;
+ }
+
+ int measureCount = 0;
+ if (measureAll) {
+ ComponentConnector[] connectors = ConnectorMap.get(connection)
+ .getComponentConnectors();
+ for (ComponentConnector connector : connectors) {
+ measueConnector(connector);
+ }
+ for (ComponentConnector connector : connectors) {
+ layoutDependencyTree.setNeedsMeasure(connector, false);
+ }
+ measureCount += connectors.length;
+ }
+
+ while (layoutDependencyTree.hasConnectorsToMeasure()) {
+ Collection<ComponentConnector> measureTargets = layoutDependencyTree
+ .getMeasureTargets();
+ for (ComponentConnector connector : measureTargets) {
+ measueConnector(connector);
+ measureCount++;
+ }
+ for (ComponentConnector connector : measureTargets) {
+ layoutDependencyTree.setNeedsMeasure(connector, false);
+ }
+ }
+ return measureCount;
+ }
+
+ private void measueConnector(ComponentConnector connector) {
+ Element element = connector.getWidget().getElement();
+ MeasuredSize measuredSize = getMeasuredSize(connector);
+ MeasureResult measureResult = measuredAndUpdate(element, measuredSize);
- for (ComponentConnector paintableWidget : paintableWidgets) {
- Element element = paintableWidget.getWidget().getElement();
- MeasuredSize measuredSize = getMeasuredSize(paintableWidget);
- measuredAndUpdate(element, measuredSize);
+ if (measureResult.isChanged()) {
+ onConnectorChange(connector, measureResult.isWidthChanged(),
+ measureResult.isHeightChanged());
}
+ }
- for (Element element : nonPaintableElements) {
- MeasuredSize measuredSize = getMeasuredSize(element, null);
- measuredAndUpdate(element, measuredSize);
- measuredSize.clearDirtyState();
+ private void onConnectorChange(ComponentConnector connector,
+ boolean widthChanged, boolean heightChanged) {
+ setNeedsOverflowFix(connector);
+ if (heightChanged) {
+ currentDependencyTree.markHeightAsChanged(connector);
+ }
+ if (widthChanged) {
+ currentDependencyTree.markWidthAsChanged(connector);
}
}
- private void measuredAndUpdate(Element element, MeasuredSize measuredSize) {
- if (measuredSize.measure(element)) {
- JsArrayString dependents = measuredSize.getDependents();
- for (int i = 0; i < dependents.length(); i++) {
- String pid = dependents.get(i);
- ComponentConnector dependent = (ComponentConnector) connection
- .getConnectorMap().getConnector(pid);
- if (dependent != null) {
- MeasuredSize dependentSize = getMeasuredSize(dependent);
- if (measuredSize.isHeightNeedsUpdate()) {
- dependentSize.setHeightNeedsUpdate();
- }
- if (measuredSize.isWidthNeedsUpdate()) {
- dependentSize.setWidthNeedsUpdate();
- }
+ private void setNeedsOverflowFix(ComponentConnector connector) {
+ // IE9 doesn't need the original fix, but for some reason it needs this
+ if (BrowserInfo.get().requiresOverflowAutoFix()
+ || BrowserInfo.get().isIE9()) {
+ ComponentConnector scrollingBoundary = currentDependencyTree
+ .getScrollingBoundary(connector);
+ if (scrollingBoundary != null) {
+ pendingOverflowFixes.add(scrollingBoundary);
+ }
+ }
+ }
+
+ private void measureNonPaintables() {
+ for (Element element : measuredNonPaintableElements) {
+ measuredAndUpdate(element, getMeasuredSize(element, null));
+ }
+ VConsole.log("Measured " + measuredNonPaintableElements.size()
+ + " non paintable elements");
+ }
+
+ private MeasureResult measuredAndUpdate(Element element,
+ MeasuredSize measuredSize) {
+ MeasureResult measureResult = measuredSize.measure(element);
+ if (measureResult.isChanged()) {
+ notifyListenersAndDepdendents(element,
+ measureResult.isWidthChanged(),
+ measureResult.isHeightChanged());
+ }
+ return measureResult;
+ }
+
+ private void notifyListenersAndDepdendents(Element element,
+ boolean widthChanged, boolean heightChanged) {
+ assert widthChanged || heightChanged;
+
+ MeasuredSize measuredSize = getMeasuredSize(element, nullSize);
+ JsArrayString dependents = measuredSize.getDependents();
+ for (int i = 0; i < dependents.length(); i++) {
+ String pid = dependents.get(i);
+ ManagedLayout dependent = (ManagedLayout) connection
+ .getConnectorMap().getConnector(pid);
+ if (dependent != null) {
+ if (heightChanged) {
+ currentDependencyTree.setNeedsVerticalLayout(dependent,
+ true);
+ }
+ if (widthChanged) {
+ currentDependencyTree.setNeedsHorizontalLayout(dependent,
+ true);
}
}
}
+ if (elementResizeListeners.containsKey(element)) {
+ listenersToFire.add(element);
+ }
}
private static boolean isManagedLayout(ComponentConnector paintable) {
return paintable instanceof ManagedLayout;
}
- public void foceLayout() {
+ public void forceLayout() {
ConnectorMap paintableMap = connection.getConnectorMap();
ComponentConnector[] paintableWidgets = paintableMap
.getComponentConnectors();
- for (ComponentConnector vPaintableWidget : paintableWidgets) {
- MeasuredSize measuredSize = getMeasuredSize(vPaintableWidget);
- measuredSize.setHeightNeedsUpdate();
- measuredSize.setWidthNeedsUpdate();
+ for (ComponentConnector connector : paintableWidgets) {
+ if (connector instanceof ManagedLayout) {
+ setNeedsUpdate((ManagedLayout) connector);
+ }
}
- doLayout();
+ setEverythingNeedsMeasure();
+ layoutNow();
}
+ // TODO Rename to setNeedsLayout
public final void setNeedsUpdate(ManagedLayout layout) {
setWidthNeedsUpdate(layout);
setHeightNeedsUpdate(layout);
}
public final void setWidthNeedsUpdate(ManagedLayout layout) {
- getMeasuredSize(layout).setWidthNeedsUpdate();
+ needsHorizontalLayout.add(layout);
}
public final void setHeightNeedsUpdate(ManagedLayout layout) {
- getMeasuredSize(layout).setHeightNeedsUpdate();
+ needsVerticalLayout.add(layout);
}
public boolean isMeasured(Element element) {
@@ -379,4 +616,105 @@ public class LayoutManager {
public int getMarginLeft(Element element) {
return getMeasuredSize(element, nullSize).getMarginLeft();
}
+
+ public void reportOuterHeight(ComponentConnector component, int outerHeight) {
+ MeasuredSize measuredSize = getMeasuredSize(component);
+ if (isLayoutRunning()) {
+ boolean heightChanged = measuredSize.setOuterHeight(outerHeight);
+
+ if (heightChanged) {
+ onConnectorChange(component, false, true);
+ notifyListenersAndDepdendents(component.getWidget()
+ .getElement(), false, true);
+ }
+ currentDependencyTree.setNeedsVerticalMeasure(component, false);
+ } else if (measuredSize.getOuterHeight() != outerHeight) {
+ setNeedsMeasure(component);
+ }
+ }
+
+ public void reportHeightAssignedToRelative(ComponentConnector component,
+ int assignedHeight) {
+ assert component.isRelativeHeight();
+
+ float percentSize = parsePercent(component.getState().getHeight());
+ int effectiveHeight = Math.round(assignedHeight * (percentSize / 100));
+
+ reportOuterHeight(component, effectiveHeight);
+ }
+
+ public void reportWidthAssignedToRelative(ComponentConnector component,
+ int assignedWidth) {
+ assert component.isRelativeWidth();
+
+ float percentSize = parsePercent(component.getState().getWidth());
+ int effectiveWidth = Math.round(assignedWidth * (percentSize / 100));
+
+ reportOuterWidth(component, effectiveWidth);
+ }
+
+ private static float parsePercent(String size) {
+ return Float.parseFloat(size.substring(0, size.length() - 1));
+ }
+
+ public void reportOuterWidth(ComponentConnector component, int outerWidth) {
+ MeasuredSize measuredSize = getMeasuredSize(component);
+ if (isLayoutRunning()) {
+ boolean widthChanged = measuredSize.setOuterWidth(outerWidth);
+
+ if (widthChanged) {
+ onConnectorChange(component, true, false);
+ notifyListenersAndDepdendents(component.getWidget()
+ .getElement(), true, false);
+ }
+ currentDependencyTree.setNeedsHorizontalMeasure(component, false);
+ } else if (measuredSize.getOuterWidth() != outerWidth) {
+ setNeedsMeasure(component);
+ }
+ }
+
+ public void addElementResizeListener(Element element,
+ ElementResizeListener listener) {
+ Collection<ElementResizeListener> listeners = elementResizeListeners
+ .get(element);
+ if (listeners == null) {
+ listeners = new HashSet<ElementResizeListener>();
+ elementResizeListeners.put(element, listeners);
+ ensureMeasured(element);
+ }
+ listeners.add(listener);
+ }
+
+ public void removeElementResizeListener(Element element,
+ ElementResizeListener listener) {
+ Collection<ElementResizeListener> listeners = elementResizeListeners
+ .get(element);
+ if (listeners != null) {
+ listeners.remove(listener);
+ if (listeners.isEmpty()) {
+ elementResizeListeners.remove(element);
+ stopMeasuringIfUnecessary(element);
+ }
+ }
+ }
+
+ private void stopMeasuringIfUnecessary(Element element) {
+ if (!needsMeasure(element)) {
+ measuredNonPaintableElements.remove(element);
+ setMeasuredSize(element, null);
+ }
+ }
+
+ public void setNeedsMeasure(ComponentConnector component) {
+ if (isLayoutRunning()) {
+ currentDependencyTree.setNeedsMeasure(component, true);
+ } else {
+ needsMeasure.add(component);
+ layoutLater();
+ }
+ }
+
+ public void setEverythingNeedsMeasure() {
+ everythingNeedsMeasure = true;
+ }
}
diff --git a/src/com/vaadin/terminal/gwt/client/MeasuredSize.java b/src/com/vaadin/terminal/gwt/client/MeasuredSize.java
index e8078031e3..97822fa8ec 100644
--- a/src/com/vaadin/terminal/gwt/client/MeasuredSize.java
+++ b/src/com/vaadin/terminal/gwt/client/MeasuredSize.java
@@ -7,6 +7,28 @@ import com.google.gwt.core.client.JsArrayString;
import com.google.gwt.dom.client.Element;
public class MeasuredSize {
+ public static class MeasureResult {
+ private final boolean widthChanged;
+ private final boolean heightChanged;
+
+ private MeasureResult(boolean widthChanged, boolean heightChanged) {
+ this.widthChanged = widthChanged;
+ this.heightChanged = heightChanged;
+ }
+
+ public boolean isHeightChanged() {
+ return heightChanged;
+ }
+
+ public boolean isWidthChanged() {
+ return widthChanged;
+ }
+
+ public boolean isChanged() {
+ return heightChanged || widthChanged;
+ }
+ }
+
private int width = -1;
private int height = -1;
@@ -14,9 +36,6 @@ public class MeasuredSize {
private int[] borders = new int[4];
private int[] margins = new int[4];
- private boolean heightChanged = true;
- private boolean widthChanged = true;
-
private FastStringSet dependents = FastStringSet.create();
public int getOuterHeight() {
@@ -61,17 +80,21 @@ public class MeasuredSize {
- sumWidths(paddings);
}
- public void setOuterHeight(int height) {
+ public boolean setOuterHeight(int height) {
if (this.height != height) {
- heightChanged = true;
this.height = height;
+ return true;
+ } else {
+ return false;
}
}
- public void setOuterWidth(int width) {
+ public boolean setOuterWidth(int width) {
if (this.width != width) {
- widthChanged = true;
this.width = width;
+ return true;
+ } else {
+ return false;
}
}
@@ -147,9 +170,9 @@ public class MeasuredSize {
return paddings[3];
}
- boolean measure(Element element) {
- boolean wasHeightChanged = heightChanged;
- boolean wasWidthChanged = widthChanged;
+ public MeasureResult measure(Element element) {
+ boolean heightChanged = false;
+ boolean widthChanged = false;
ComputedStyle computedStyle = new ComputedStyle(element);
int[] paddings = computedStyle.getPadding();
@@ -181,26 +204,17 @@ public class MeasuredSize {
int requiredHeight = Util.getRequiredHeight(element);
int marginHeight = sumHeights(margins);
- setOuterHeight(requiredHeight + marginHeight);
+ if (setOuterHeight(requiredHeight + marginHeight)) {
+ heightChanged = true;
+ }
int requiredWidth = Util.getRequiredWidth(element);
int marginWidth = sumWidths(margins);
- setOuterWidth(requiredWidth + marginWidth);
-
- return wasHeightChanged != heightChanged
- || wasWidthChanged != widthChanged;
- }
-
- void clearDirtyState() {
- heightChanged = widthChanged = false;
- }
-
- public boolean isHeightNeedsUpdate() {
- return heightChanged;
- }
+ if (setOuterWidth(requiredWidth + marginWidth)) {
+ widthChanged = true;
+ }
- public boolean isWidthNeedsUpdate() {
- return widthChanged;
+ return new MeasureResult(widthChanged, heightChanged);
}
private static boolean hasWidthChanged(int[] sizes1, int[] sizes2) {
@@ -211,11 +225,4 @@ public class MeasuredSize {
return sizes1[0] != sizes2[0] || sizes1[2] != sizes2[2];
}
- public void setWidthNeedsUpdate() {
- widthChanged = true;
- }
-
- public void setHeightNeedsUpdate() {
- heightChanged = true;
- }
} \ No newline at end of file
diff --git a/src/com/vaadin/terminal/gwt/client/Util.java b/src/com/vaadin/terminal/gwt/client/Util.java
index faaad8c7d2..bfe63caefd 100644
--- a/src/com/vaadin/terminal/gwt/client/Util.java
+++ b/src/com/vaadin/terminal/gwt/client/Util.java
@@ -79,23 +79,23 @@ public class Util {
* @param widget
* @param lazy
* run componentSizeUpdated lazyly
+ *
+ * @deprecated since 7.0, use
+ * {@link LayoutManager#setNeedsMeasure(ComponentConnector)}
+ * instead
*/
+ @Deprecated
public static void notifyParentOfSizeChange(Widget widget, boolean lazy) {
- ApplicationConnection applicationConnection = findApplicationConnectionFor(widget);
- if (applicationConnection != null) {
- applicationConnection.doLayout(lazy);
+ ComponentConnector connector = findConnectorFor(widget);
+ if (connector != null) {
+ connector.getLayoutManager().setNeedsMeasure(connector);
+ if (!lazy) {
+ connector.getLayoutManager().layoutNow();
+ }
}
}
- private static boolean findAppConnectionWarningDisplayed = false;
-
- private static ApplicationConnection findApplicationConnectionFor(
- Widget widget) {
- if (!findAppConnectionWarningDisplayed) {
- findAppConnectionWarningDisplayed = true;
- VConsole.log("Warning: Using Util.findApplicationConnectionFor which should be eliminated once there is a better way to find the ApplicationConnection for a Paintable");
- }
-
+ private static ComponentConnector findConnectorFor(Widget widget) {
List<ApplicationConnection> runningApplications = ApplicationConfiguration
.getRunningApplications();
for (ApplicationConnection applicationConnection : runningApplications) {
@@ -105,7 +105,7 @@ public class Util {
continue;
}
if (connector.getConnection() == applicationConnection) {
- return applicationConnection;
+ return connector;
}
}
@@ -433,8 +433,7 @@ public class Util {
public static void runWebkitOverflowAutoFix(final Element elem) {
// Add max version if fix lands sometime to Webkit
// Starting from Opera 11.00, also a problem in Opera
- if ((BrowserInfo.get().getWebkitVersion() > 0 || BrowserInfo.get()
- .getOperaVersion() >= 11) && getNativeScrollbarSize() > 0) {
+ if (BrowserInfo.get().requiresOverflowAutoFix()) {
final String originalOverflow = elem.getStyle().getProperty(
"overflow");
if ("hidden".equals(originalOverflow)) {
diff --git a/src/com/vaadin/terminal/gwt/client/ui/absolutelayout/AbsoluteLayoutConnector.java b/src/com/vaadin/terminal/gwt/client/ui/absolutelayout/AbsoluteLayoutConnector.java
index a893657c40..f33d582ef1 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/absolutelayout/AbsoluteLayoutConnector.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/absolutelayout/AbsoluteLayoutConnector.java
@@ -176,6 +176,7 @@ public class AbsoluteLayoutConnector extends
- wrapper.getElement().getOffsetTop();
}
wrapperStyle.setHeight(h, Unit.PX);
+ getLayoutManager().reportHeightAssignedToRelative(paintable, h);
} else {
wrapperStyle.clearHeight();
}
@@ -207,6 +208,7 @@ public class AbsoluteLayoutConnector extends
- wrapper.getElement().getOffsetLeft();
}
wrapperStyle.setWidth(w, Unit.PX);
+ getLayoutManager().reportWidthAssignedToRelative(paintable, w);
} else {
wrapperStyle.clearWidth();
}
diff --git a/src/com/vaadin/terminal/gwt/client/ui/accordion/AccordionConnector.java b/src/com/vaadin/terminal/gwt/client/ui/accordion/AccordionConnector.java
index e5eda7607b..8ab33f615d 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/accordion/AccordionConnector.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/accordion/AccordionConnector.java
@@ -13,12 +13,13 @@ import com.vaadin.terminal.gwt.client.UIDL;
import com.vaadin.terminal.gwt.client.ui.Component;
import com.vaadin.terminal.gwt.client.ui.SimpleManagedLayout;
import com.vaadin.terminal.gwt.client.ui.accordion.VAccordion.StackItem;
+import com.vaadin.terminal.gwt.client.ui.layout.MayScrollChildren;
import com.vaadin.terminal.gwt.client.ui.tabsheet.TabsheetBaseConnector;
import com.vaadin.ui.Accordion;
@Component(Accordion.class)
public class AccordionConnector extends TabsheetBaseConnector implements
- SimpleManagedLayout {
+ SimpleManagedLayout, MayScrollChildren {
@Override
public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
diff --git a/src/com/vaadin/terminal/gwt/client/ui/accordion/VAccordion.java b/src/com/vaadin/terminal/gwt/client/ui/accordion/VAccordion.java
index 71361b79ad..dcd520bbb3 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/accordion/VAccordion.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/accordion/VAccordion.java
@@ -254,9 +254,6 @@ public class VAccordion extends VTabsheetBase {
super.setWidth(maxWidth + "px");
openTab.setWidth(maxWidth);
}
-
- Util.runWebkitOverflowAutoFix(openTab.getContainerElement());
-
}
/**
diff --git a/src/com/vaadin/terminal/gwt/client/ui/draganddropwrapper/VDragAndDropWrapper.java b/src/com/vaadin/terminal/gwt/client/ui/draganddropwrapper/VDragAndDropWrapper.java
index c5f18ba23c..5cbfabbb11 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/draganddropwrapper/VDragAndDropWrapper.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/draganddropwrapper/VDragAndDropWrapper.java
@@ -25,6 +25,7 @@ import com.google.gwt.xhr.client.XMLHttpRequest;
import com.vaadin.terminal.gwt.client.ApplicationConnection;
import com.vaadin.terminal.gwt.client.ComponentConnector;
import com.vaadin.terminal.gwt.client.ConnectorMap;
+import com.vaadin.terminal.gwt.client.LayoutManager;
import com.vaadin.terminal.gwt.client.MouseEventDetailsBuilder;
import com.vaadin.terminal.gwt.client.Util;
import com.vaadin.terminal.gwt.client.VConsole;
@@ -565,10 +566,15 @@ public class VDragAndDropWrapper extends VCustomComponent implements
+ emphasizedHDrop.toString().toLowerCase(), false);
}
if (doLayout) {
- client.doLayout(false);
+ notifySizePotentiallyChanged();
}
}
+ private void notifySizePotentiallyChanged() {
+ LayoutManager.get(client).setNeedsMeasure(
+ ConnectorMap.get(client).getConnector(getElement()));
+ }
+
protected void emphasis(VDragEvent drag) {
deEmphasis(false);
VDragAndDropWrapper.setStyleName(getElement(), OVER_STYLE, true);
@@ -581,7 +587,7 @@ public class VDragAndDropWrapper extends VCustomComponent implements
// TODO build (to be an example) an emphasis mode where drag image
// is fitted before or after the content
- client.doLayout(false);
+ notifySizePotentiallyChanged();
}
}
diff --git a/src/com/vaadin/terminal/gwt/client/ui/form/FormConnector.java b/src/com/vaadin/terminal/gwt/client/ui/form/FormConnector.java
index 34d8461b20..11d5385213 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/form/FormConnector.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/form/FormConnector.java
@@ -16,17 +16,41 @@ import com.vaadin.terminal.gwt.client.ui.AbstractComponentContainerConnector;
import com.vaadin.terminal.gwt.client.ui.Component;
import com.vaadin.terminal.gwt.client.ui.Icon;
import com.vaadin.terminal.gwt.client.ui.ShortcutActionHandler;
-import com.vaadin.terminal.gwt.client.ui.SimpleManagedLayout;
+import com.vaadin.terminal.gwt.client.ui.layout.ElementResizeEvent;
+import com.vaadin.terminal.gwt.client.ui.layout.ElementResizeListener;
+import com.vaadin.terminal.gwt.client.ui.layout.MayScrollChildren;
import com.vaadin.ui.Form;
@Component(Form.class)
public class FormConnector extends AbstractComponentContainerConnector
- implements Paintable, SimpleManagedLayout {
+ implements Paintable, MayScrollChildren {
+
+ private final ElementResizeListener footerResizeListener = new ElementResizeListener() {
+ public void onElementResize(ElementResizeEvent e) {
+ VForm form = getWidget();
+
+ int footerHeight;
+ if (form.footer != null) {
+ LayoutManager lm = getLayoutManager();
+ footerHeight = lm.getOuterHeight(form.footer.getElement());
+ } else {
+ footerHeight = 0;
+ }
+
+ form.fieldContainer.getStyle().setPaddingBottom(footerHeight,
+ Unit.PX);
+ form.footerContainer.getStyle()
+ .setMarginTop(-footerHeight, Unit.PX);
+ }
+ };
@Override
- public void init() {
+ public void onUnregister() {
VForm form = getWidget();
- getLayoutManager().registerDependency(this, form.footerContainer);
+ if (form.footer != null) {
+ getLayoutManager().removeElementResizeListener(
+ form.footer.getElement(), footerResizeListener);
+ }
}
@Override
@@ -96,10 +120,16 @@ public class FormConnector extends AbstractComponentContainerConnector
.getFooter();
Widget newFooterWidget = newFooter.getWidget();
if (getWidget().footer == null) {
+ getLayoutManager().addElementResizeListener(
+ newFooterWidget.getElement(), footerResizeListener);
getWidget().add(newFooter.getWidget(),
getWidget().footerContainer);
getWidget().footer = newFooterWidget;
} else if (newFooter != getWidget().footer) {
+ getLayoutManager().removeElementResizeListener(
+ getWidget().footer.getElement(), footerResizeListener);
+ getLayoutManager().addElementResizeListener(
+ newFooterWidget.getElement(), footerResizeListener);
getWidget().remove(getWidget().footer);
getWidget().add(newFooter.getWidget(),
getWidget().footerContainer);
@@ -107,7 +137,10 @@ public class FormConnector extends AbstractComponentContainerConnector
getWidget().footer = newFooterWidget;
} else {
if (getWidget().footer != null) {
+ getLayoutManager().removeElementResizeListener(
+ getWidget().footer.getElement(), footerResizeListener);
getWidget().remove(getWidget().footer);
+ getWidget().footer = null;
}
}
@@ -163,17 +196,6 @@ public class FormConnector extends AbstractComponentContainerConnector
return GWT.create(VForm.class);
}
- public void layout() {
- VForm form = getWidget();
-
- LayoutManager lm = getLayoutManager();
- int footerHeight = lm.getOuterHeight(form.footerContainer)
- - lm.getMarginTop(form.footerContainer);
-
- form.fieldContainer.getStyle().setPaddingBottom(footerHeight, Unit.PX);
- form.footerContainer.getStyle().setMarginTop(-footerHeight, Unit.PX);
- }
-
@Override
public boolean isReadOnly() {
return super.isReadOnly() || getState().isPropertyReadOnly();
diff --git a/src/com/vaadin/terminal/gwt/client/ui/gridlayout/GridLayoutConnector.java b/src/com/vaadin/terminal/gwt/client/ui/gridlayout/GridLayoutConnector.java
index 9858ed362a..0a26fa020a 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/gridlayout/GridLayoutConnector.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/gridlayout/GridLayoutConnector.java
@@ -58,6 +58,19 @@ public class GridLayoutConnector extends AbstractComponentContainerConnector
}
@Override
+ public void onUnregister() {
+ VGridLayout layout = getWidget();
+ getLayoutManager().unregisterDependency(this,
+ layout.spacingMeasureElement);
+
+ // Unregister caption size dependencies
+ for (ComponentConnector child : getChildren()) {
+ Cell cell = layout.widgetToCell.get(child.getWidget());
+ cell.slot.setCaption(null);
+ }
+ }
+
+ @Override
public GridLayoutState getState() {
return (GridLayoutState) super.getState();
}
diff --git a/src/com/vaadin/terminal/gwt/client/ui/gridlayout/VGridLayout.java b/src/com/vaadin/terminal/gwt/client/ui/gridlayout/VGridLayout.java
index 1949cb191c..6c5d018161 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/gridlayout/VGridLayout.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/gridlayout/VGridLayout.java
@@ -211,6 +211,8 @@ public class VGridLayout extends ComplexPanel {
+ layoutManager.getPaddingBottom(element)
+ layoutManager.getBorderHeight(element);
element.getStyle().setHeight(outerHeight, Unit.PX);
+ getConnector().getLayoutManager().reportOuterHeight(getConnector(),
+ outerHeight);
}
}
@@ -234,6 +236,8 @@ public class VGridLayout extends ComplexPanel {
+ layoutManager.getPaddingRight(element)
+ layoutManager.getBorderWidth(element);
element.getStyle().setWidth(outerWidth, Unit.PX);
+ getConnector().getLayoutManager().reportOuterWidth(getConnector(),
+ outerWidth);
}
}
@@ -559,6 +563,10 @@ public class VGridLayout extends ComplexPanel {
if (slot == null || slot.getChild() != childConnector) {
slot = new ComponentConnectorLayoutSlot(CLASSNAME,
childConnector, getConnector());
+ if (childConnector.isRelativeWidth()) {
+ slot.getWrapperElement().getStyle()
+ .setWidth(100, Unit.PCT);
+ }
Element slotWrapper = slot.getWrapperElement();
getElement().appendChild(slotWrapper);
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/ElementResizeEvent.java b/src/com/vaadin/terminal/gwt/client/ui/layout/ElementResizeEvent.java
new file mode 100644
index 0000000000..a519f5db87
--- /dev/null
+++ b/src/com/vaadin/terminal/gwt/client/ui/layout/ElementResizeEvent.java
@@ -0,0 +1,25 @@
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+package com.vaadin.terminal.gwt.client.ui.layout;
+
+import com.google.gwt.dom.client.Element;
+import com.vaadin.terminal.gwt.client.LayoutManager;
+
+public class ElementResizeEvent {
+ private final Element element;
+ private final LayoutManager layoutManager;
+
+ public ElementResizeEvent(LayoutManager layoutManager, Element element) {
+ this.layoutManager = layoutManager;
+ this.element = element;
+ }
+
+ public Element getElement() {
+ return element;
+ }
+
+ public LayoutManager getLayoutManager() {
+ return layoutManager;
+ }
+}
diff --git a/src/com/vaadin/terminal/gwt/client/ui/layout/ElementResizeListener.java b/src/com/vaadin/terminal/gwt/client/ui/layout/ElementResizeListener.java
new file mode 100644
index 0000000000..d6d3de48b8
--- /dev/null
+++ b/src/com/vaadin/terminal/gwt/client/ui/layout/ElementResizeListener.java
@@ -0,0 +1,9 @@
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+
+package com.vaadin.terminal.gwt.client.ui.layout;
+
+public interface ElementResizeListener {
+ public void onElementResize(ElementResizeEvent e);
+} \ No newline at end of file
diff --git a/src/com/vaadin/terminal/gwt/client/ui/layout/LayoutDependencyTree.java b/src/com/vaadin/terminal/gwt/client/ui/layout/LayoutDependencyTree.java
new file mode 100644
index 0000000000..1ca8933ff2
--- /dev/null
+++ b/src/com/vaadin/terminal/gwt/client/ui/layout/LayoutDependencyTree.java
@@ -0,0 +1,521 @@
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+package com.vaadin.terminal.gwt.client.ui.layout;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+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.VConsole;
+import com.vaadin.terminal.gwt.client.ui.ManagedLayout;
+
+public class LayoutDependencyTree {
+ private class LayoutDependency {
+ private final ComponentConnector connector;
+ private final int direction;
+
+ private boolean needsLayout = false;
+ private boolean needsMeasure = false;
+
+ private boolean scrollingParentCached = false;
+ private ComponentConnector scrollingBoundary = null;
+
+ private Set<ComponentConnector> measureBlockers = new HashSet<ComponentConnector>();
+ private Set<ComponentConnector> layoutBlockers = new HashSet<ComponentConnector>();
+
+ public LayoutDependency(ComponentConnector connector, int direction) {
+ this.connector = connector;
+ this.direction = direction;
+ }
+
+ private void addLayoutBlocker(ComponentConnector blocker) {
+ boolean blockerAdded = layoutBlockers.add(blocker);
+ if (blockerAdded && layoutBlockers.size() == 1) {
+ if (needsLayout) {
+ getLayoutQueue(direction).remove(connector);
+ } else {
+ // Propagation already done if needsLayout is set
+ propagatePotentialLayout();
+ }
+ }
+ }
+
+ private void removeLayoutBlocker(ComponentConnector blocker) {
+ boolean removed = layoutBlockers.remove(blocker);
+ if (removed && layoutBlockers.isEmpty()) {
+ if (needsLayout) {
+ getLayoutQueue(direction).add((ManagedLayout) connector);
+ } else {
+ propagateNoUpcomingLayout();
+ }
+ }
+ }
+
+ private void addMeasureBlocker(ComponentConnector blocker) {
+ boolean blockerAdded = measureBlockers.add(blocker);
+ if (blockerAdded && measureBlockers.size() == 1) {
+ if (needsMeasure) {
+ getMeasureQueue(direction).remove(connector);
+ } else {
+ propagatePotentialResize();
+ }
+ }
+ }
+
+ private void removeMeasureBlocker(ComponentConnector blocker) {
+ boolean removed = measureBlockers.remove(blocker);
+ if (removed && measureBlockers.isEmpty()) {
+ if (needsMeasure) {
+ getMeasureQueue(direction).add(connector);
+ } else {
+ propagateNoUpcomingResize();
+ }
+ }
+ }
+
+ public void setNeedsMeasure(boolean needsMeasure) {
+ if (needsMeasure && !this.needsMeasure) {
+ // If enabling needsMeasure
+ this.needsMeasure = needsMeasure;
+
+ if (measureBlockers.isEmpty()) {
+ // Add to queue if there are no blockers
+ getMeasureQueue(direction).add(connector);
+ // Only need to propagate if not already propagated when
+ // setting blockers
+ propagatePotentialResize();
+ }
+ } else if (!needsMeasure && this.needsMeasure
+ && measureBlockers.isEmpty()) {
+ // Only disable if there are no blockers (elements gets measured
+ // in both directions even if there is a blocker in one
+ // direction)
+ this.needsMeasure = needsMeasure;
+ getMeasureQueue(direction).remove(connector);
+ propagateNoUpcomingResize();
+ }
+ }
+
+ public void setNeedsLayout(boolean needsLayout) {
+ if (!(connector instanceof ManagedLayout)) {
+ throw new IllegalStateException(
+ "Only managed layouts can need layout, layout attempted for "
+ + Util.getConnectorString(connector));
+ }
+ if (needsLayout && !this.needsLayout) {
+ // If enabling needsLayout
+ this.needsLayout = needsLayout;
+
+ if (layoutBlockers.isEmpty()) {
+ // Add to queue if there are no blockers
+ getLayoutQueue(direction).add((ManagedLayout) connector);
+ // Only need to propagate if not already propagated when
+ // setting blockers
+ propagatePotentialLayout();
+ }
+ } else if (!needsLayout && this.needsLayout
+ && layoutBlockers.isEmpty()) {
+ // Only disable if there are no layout blockers
+ // (SimpleManagedLayout gets layouted in both directions
+ // even if there is a blocker in one direction)
+ this.needsLayout = needsLayout;
+ getLayoutQueue(direction).remove(connector);
+ propagateNoUpcomingLayout();
+ }
+ }
+
+ private void propagatePotentialResize() {
+ for (ComponentConnector needsSize : getNeedsSizeForLayout()) {
+ LayoutDependency layoutDependency = getDependency(needsSize,
+ direction);
+ layoutDependency.addLayoutBlocker(connector);
+ }
+ }
+
+ private Collection<ComponentConnector> getNeedsSizeForLayout() {
+ // Find all connectors that need the size of this connector for
+ // layouting
+
+ // Parent needs size if it isn't relative?
+ // Connector itself needs size if it isn't undefined?
+ // Children doesn't care?
+
+ ArrayList<ComponentConnector> needsSize = new ArrayList<ComponentConnector>();
+
+ if (!isUndefinedInDirection(connector, direction)) {
+ needsSize.add(connector);
+ }
+ if (!isRelativeInDirection(connector, direction)) {
+ ComponentConnector parent = connector.getParent();
+ if (parent != null) {
+ needsSize.add(parent);
+ }
+ }
+
+ return needsSize;
+ }
+
+ private void propagateNoUpcomingResize() {
+ for (ComponentConnector mightNeedLayout : getNeedsSizeForLayout()) {
+ LayoutDependency layoutDependency = getDependency(
+ mightNeedLayout, direction);
+ layoutDependency.removeLayoutBlocker(connector);
+ }
+ }
+
+ private void propagatePotentialLayout() {
+ for (ComponentConnector sizeMightChange : getResizedByLayout()) {
+ LayoutDependency layoutDependency = getDependency(
+ sizeMightChange, direction);
+ layoutDependency.addMeasureBlocker(connector);
+ }
+ }
+
+ private Collection<ComponentConnector> getResizedByLayout() {
+ // Components that might get resized by a layout of this component
+
+ // Parent never resized
+ // Connector itself resized if undefined
+ // Children resized if relative
+
+ ArrayList<ComponentConnector> resized = new ArrayList<ComponentConnector>();
+ if (isUndefinedInDirection(connector, direction)) {
+ resized.add(connector);
+ }
+
+ if (connector instanceof ComponentContainerConnector) {
+ ComponentContainerConnector container = (ComponentContainerConnector) connector;
+ for (ComponentConnector child : container.getChildren()) {
+ if (isRelativeInDirection(child, direction)) {
+ resized.add(child);
+ }
+ }
+ }
+
+ return resized;
+ }
+
+ private void propagateNoUpcomingLayout() {
+ for (ComponentConnector sizeMightChange : getResizedByLayout()) {
+ LayoutDependency layoutDependency = getDependency(
+ sizeMightChange, direction);
+ layoutDependency.removeMeasureBlocker(connector);
+ }
+ }
+
+ public void markSizeAsChanged() {
+ // When the size has changed, all that use that size should be
+ // layouted
+ for (ComponentConnector connector : getNeedsSizeForLayout()) {
+ LayoutDependency layoutDependency = getDependency(connector,
+ direction);
+ if (connector instanceof ManagedLayout) {
+ layoutDependency.setNeedsLayout(true);
+ } else {
+ // Should simulate setNeedsLayout(true) + markAsLayouted ->
+ // propagate needs measure
+ layoutDependency.propagatePostLayoutMeasure();
+ }
+ }
+
+ // Should also go through the hierarchy to discover appeared or
+ // disappeared scrollbars
+ ComponentConnector scrollingBoundary = getScrollingBoundary(connector);
+ if (scrollingBoundary != null) {
+ getDependency(scrollingBoundary, getOppositeDirection())
+ .setNeedsMeasure(true);
+ }
+
+ }
+
+ /**
+ * Go up the hierarchy to find a component whose size might have changed
+ * in the other direction because changes to this component causes
+ * scrollbars to appear or disappear.
+ *
+ * @return
+ */
+ private LayoutDependency findPotentiallyChangedScrollbar() {
+ ComponentConnector currentConnector = connector;
+ while (true) {
+ ComponentContainerConnector parent = currentConnector
+ .getParent();
+ if (parent == null) {
+ return null;
+ }
+ if (parent instanceof MayScrollChildren) {
+ return getDependency(currentConnector,
+ getOppositeDirection());
+ }
+ currentConnector = parent;
+ }
+ }
+
+ private int getOppositeDirection() {
+ return direction == HORIZONTAL ? VERTICAL : HORIZONTAL;
+ }
+
+ public void markAsLayouted() {
+ if (!layoutBlockers.isEmpty()) {
+ // Don't do anything if there are layout blockers (SimpleLayout
+ // gets layouted in both directions even if one direction is
+ // blocked)
+ return;
+ }
+ setNeedsLayout(false);
+ propagatePostLayoutMeasure();
+ }
+
+ private void propagatePostLayoutMeasure() {
+ for (ComponentConnector resized : getResizedByLayout()) {
+ LayoutDependency layoutDependency = getDependency(resized,
+ direction);
+ layoutDependency.setNeedsMeasure(true);
+ }
+
+ // Special case for e.g. wrapping texts
+ if (direction == HORIZONTAL && !connector.isUndefinedWidth()
+ && connector.isUndefinedHeight()) {
+ LayoutDependency dependency = getDependency(connector, VERTICAL);
+ dependency.setNeedsMeasure(true);
+ }
+ }
+
+ @Override
+ public String toString() {
+ String s = getCompactConnectorString(connector) + "\n";
+ if (direction == VERTICAL) {
+ s += "Vertical";
+ } else {
+ s += "Horizontal";
+ }
+ ComponentState state = connector.getState();
+ s += " sizing: "
+ + getSizeDefinition(direction == VERTICAL ? state
+ .getHeight() : state.getWidth()) + "\n";
+
+ if (needsLayout) {
+ s += "Needs layout\n";
+ }
+ if (getLayoutQueue(direction).contains(connector)) {
+ s += "In layout queue\n";
+ }
+ s += "Layout blockers: " + blockersToString(layoutBlockers) + "\n";
+
+ if (needsMeasure) {
+ s += "Needs measure\n";
+ }
+ if (getMeasureQueue(direction).contains(connector)) {
+ s += "In measure queue\n";
+ }
+ s += "Measure blockers: " + blockersToString(measureBlockers);
+
+ return s;
+ }
+
+ public boolean noMoreChangesExpected() {
+ return !needsLayout && !needsMeasure && layoutBlockers.isEmpty()
+ && measureBlockers.isEmpty();
+ }
+
+ }
+
+ private static final int HORIZONTAL = 0;
+ private static final int VERTICAL = 1;
+
+ private final Map<?, ?>[] dependenciesInDirection = new Map<?, ?>[] {
+ new HashMap<ComponentConnector, LayoutDependency>(),
+ new HashMap<ComponentConnector, LayoutDependency>() };
+
+ private final Collection<?>[] measureQueueInDirection = new HashSet<?>[] {
+ new HashSet<ComponentConnector>(),
+ new HashSet<ComponentConnector>() };
+
+ private final Collection<?>[] layoutQueueInDirection = new HashSet<?>[] {
+ new HashSet<ComponentConnector>(),
+ new HashSet<ComponentConnector>() };
+
+ 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);
+ }
+
+ public void setNeedsVerticalMeasure(ComponentConnector connector,
+ boolean needsMeasure) {
+ LayoutDependency dependency = getDependency(connector, VERTICAL);
+ dependency.setNeedsMeasure(needsMeasure);
+ }
+
+ private LayoutDependency getDependency(ComponentConnector connector,
+ int direction) {
+ @SuppressWarnings("unchecked")
+ Map<ComponentConnector, LayoutDependency> dependencies = (Map<ComponentConnector, LayoutDependency>) dependenciesInDirection[direction];
+ LayoutDependency dependency = dependencies.get(connector);
+ if (dependency == null) {
+ dependency = new LayoutDependency(connector, direction);
+ dependencies.put(connector, dependency);
+ }
+ return dependency;
+ }
+
+ @SuppressWarnings("unchecked")
+ private Collection<ManagedLayout> getLayoutQueue(int direction) {
+ return (Collection<ManagedLayout>) layoutQueueInDirection[direction];
+ }
+
+ @SuppressWarnings("unchecked")
+ private Collection<ComponentConnector> getMeasureQueue(int direction) {
+ return (Collection<ComponentConnector>) measureQueueInDirection[direction];
+ }
+
+ public void setNeedsHorizontalLayout(ManagedLayout layout,
+ boolean needsLayout) {
+ LayoutDependency dependency = getDependency(layout, HORIZONTAL);
+ dependency.setNeedsLayout(needsLayout);
+ }
+
+ public void setNeedsVerticalLayout(ManagedLayout layout, boolean needsLayout) {
+ LayoutDependency dependency = getDependency(layout, VERTICAL);
+ dependency.setNeedsLayout(needsLayout);
+ }
+
+ public void markAsHorizontallyLayouted(ManagedLayout layout) {
+ LayoutDependency dependency = getDependency(layout, HORIZONTAL);
+ dependency.markAsLayouted();
+ }
+
+ public void markAsVerticallyLayouted(ManagedLayout layout) {
+ LayoutDependency dependency = getDependency(layout, VERTICAL);
+ dependency.markAsLayouted();
+ }
+
+ public void markHeightAsChanged(ComponentConnector connector) {
+ LayoutDependency dependency = getDependency(connector, VERTICAL);
+ dependency.markSizeAsChanged();
+ }
+
+ public void markWidthAsChanged(ComponentConnector connector) {
+ LayoutDependency dependency = getDependency(connector, HORIZONTAL);
+ dependency.markSizeAsChanged();
+ }
+
+ private static boolean isRelativeInDirection(ComponentConnector connector,
+ int direction) {
+ if (direction == HORIZONTAL) {
+ return connector.isRelativeWidth();
+ } else {
+ return connector.isRelativeHeight();
+ }
+ }
+
+ private static boolean isUndefinedInDirection(ComponentConnector connector,
+ int direction) {
+ if (direction == VERTICAL) {
+ return connector.isUndefinedHeight();
+ } else {
+ return connector.isUndefinedWidth();
+ }
+ }
+
+ private static String getCompactConnectorString(ComponentConnector connector) {
+ return Util.getSimpleName(connector) + " ("
+ + connector.getConnectorId() + ")";
+ }
+
+ private static String getSizeDefinition(String size) {
+ if (size == null || size.length() == 0) {
+ return "undefined";
+ } else if (size.endsWith("%")) {
+ return "relative";
+ } else {
+ return "fixed";
+ }
+ }
+
+ private static String blockersToString(
+ Collection<ComponentConnector> blockers) {
+ StringBuilder b = new StringBuilder("[");
+ for (ComponentConnector blocker : blockers) {
+ if (b.length() != 1) {
+ b.append(", ");
+ }
+ b.append(getCompactConnectorString(blocker));
+ }
+ b.append(']');
+ return b.toString();
+ }
+
+ 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 ManagedLayout[] getVerticalLayoutTargets() {
+ Collection<ManagedLayout> queue = getLayoutQueue(VERTICAL);
+ return queue.toArray(new ManagedLayout[queue.size()]);
+ }
+
+ public Collection<ComponentConnector> getMeasureTargets() {
+ Collection<ComponentConnector> measureTargets = new HashSet<ComponentConnector>(
+ getMeasureQueue(HORIZONTAL));
+ measureTargets.addAll(getMeasureQueue(VERTICAL));
+ return measureTargets;
+ }
+
+ public void logDependencyStatus(ComponentConnector connector) {
+ VConsole.log("====");
+ VConsole.log(getDependency(connector, HORIZONTAL).toString());
+ VConsole.log(getDependency(connector, VERTICAL).toString());
+ }
+
+ public boolean noMoreChangesExpected(ComponentConnector connector) {
+ return getDependency(connector, HORIZONTAL).noMoreChangesExpected()
+ && getDependency(connector, VERTICAL).noMoreChangesExpected();
+ }
+
+ public ComponentConnector getScrollingBoundary(ComponentConnector connector) {
+ LayoutDependency dependency = getDependency(connector, HORIZONTAL);
+ if (!dependency.scrollingParentCached) {
+ ComponentContainerConnector parent = dependency.connector
+ .getParent();
+ if (parent instanceof MayScrollChildren) {
+ dependency.scrollingBoundary = connector;
+ } else if (parent != null) {
+ dependency.scrollingBoundary = getScrollingBoundary(parent);
+ } else {
+ // No scrolling parent
+ }
+
+ dependency.scrollingParentCached = true;
+ }
+ return dependency.scrollingBoundary;
+ }
+}
diff --git a/src/com/vaadin/terminal/gwt/client/ui/layout/MayScrollChildren.java b/src/com/vaadin/terminal/gwt/client/ui/layout/MayScrollChildren.java
new file mode 100644
index 0000000000..62c9937c4c
--- /dev/null
+++ b/src/com/vaadin/terminal/gwt/client/ui/layout/MayScrollChildren.java
@@ -0,0 +1,10 @@
+/*
+@VaadinApache2LicenseForJavaFiles@
+ */
+package com.vaadin.terminal.gwt.client.ui.layout;
+
+import com.vaadin.terminal.gwt.client.ComponentContainerConnector;
+
+public interface MayScrollChildren extends ComponentContainerConnector {
+
+}
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) {
diff --git a/src/com/vaadin/terminal/gwt/client/ui/orderedlayout/AbstractOrderedLayoutConnector.java b/src/com/vaadin/terminal/gwt/client/ui/orderedlayout/AbstractOrderedLayoutConnector.java
index 486621fae2..4a9190e0f1 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/orderedlayout/AbstractOrderedLayoutConnector.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/orderedlayout/AbstractOrderedLayoutConnector.java
@@ -6,6 +6,7 @@ package com.vaadin.terminal.gwt.client.ui.orderedlayout;
import java.util.List;
import com.google.gwt.dom.client.Style;
+import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.ui.Widget;
import com.vaadin.terminal.gwt.client.ApplicationConnection;
@@ -56,6 +57,20 @@ public abstract class AbstractOrderedLayoutConnector extends
}
@Override
+ public void onUnregister() {
+ LayoutManager lm = getLayoutManager();
+
+ VMeasuringOrderedLayout layout = getWidget();
+ lm.unregisterDependency(this, layout.spacingMeasureElement);
+
+ // Unregister child caption listeners
+ for (ComponentConnector child : getChildren()) {
+ VLayoutSlot slot = layout.getSlotForChild(child.getWidget());
+ slot.setCaption(null);
+ }
+ }
+
+ @Override
public AbstractOrderedLayoutState getState() {
return (AbstractOrderedLayoutState) super.getState();
}
@@ -177,14 +192,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(
@@ -215,8 +239,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));
@@ -275,6 +302,9 @@ public abstract class AbstractOrderedLayoutConnector extends
.getStylePrimaryName(), child, this);
}
layout.addOrMove(slot, currentIndex++);
+ if (child.isRelativeWidth()) {
+ slot.getWrapperElement().getStyle().setWidth(100, Unit.PCT);
+ }
}
for (ComponentConnector child : previousChildren) {
diff --git a/src/com/vaadin/terminal/gwt/client/ui/panel/PanelConnector.java b/src/com/vaadin/terminal/gwt/client/ui/panel/PanelConnector.java
index 5fe5c6890e..43f58c10b8 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/panel/PanelConnector.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/panel/PanelConnector.java
@@ -15,7 +15,6 @@ import com.vaadin.terminal.gwt.client.LayoutManager;
import com.vaadin.terminal.gwt.client.MouseEventDetails;
import com.vaadin.terminal.gwt.client.Paintable;
import com.vaadin.terminal.gwt.client.UIDL;
-import com.vaadin.terminal.gwt.client.Util;
import com.vaadin.terminal.gwt.client.communication.RpcProxy;
import com.vaadin.terminal.gwt.client.ui.AbstractComponentContainerConnector;
import com.vaadin.terminal.gwt.client.ui.ClickEventHandler;
@@ -23,11 +22,13 @@ import com.vaadin.terminal.gwt.client.ui.Component;
import com.vaadin.terminal.gwt.client.ui.PostLayoutListener;
import com.vaadin.terminal.gwt.client.ui.ShortcutActionHandler;
import com.vaadin.terminal.gwt.client.ui.SimpleManagedLayout;
+import com.vaadin.terminal.gwt.client.ui.layout.MayScrollChildren;
import com.vaadin.ui.Panel;
@Component(Panel.class)
public class PanelConnector extends AbstractComponentContainerConnector
- implements Paintable, SimpleManagedLayout, PostLayoutListener {
+ implements Paintable, SimpleManagedLayout, PostLayoutListener,
+ MayScrollChildren {
private Integer uidlScrollTop;
@@ -56,6 +57,16 @@ public class PanelConnector extends AbstractComponentContainerConnector
}
@Override
+ public void onUnregister() {
+ VPanel panel = getWidget();
+ LayoutManager layoutManager = getLayoutManager();
+
+ layoutManager.unregisterDependency(this, panel.captionNode);
+ layoutManager.unregisterDependency(this, panel.bottomDecoration);
+ layoutManager.unregisterDependency(this, panel.contentNode);
+ }
+
+ @Override
public boolean delegateCaptionHandling() {
return false;
}
@@ -189,8 +200,6 @@ public class PanelConnector extends AbstractComponentContainerConnector
// Read actual value back to ensure update logic is correct
panel.scrollTop = panel.contentNode.getScrollTop();
panel.scrollLeft = panel.contentNode.getScrollLeft();
-
- Util.runWebkitOverflowAutoFix(panel.contentNode);
}
public void postLayout() {
diff --git a/src/com/vaadin/terminal/gwt/client/ui/root/RootConnector.java b/src/com/vaadin/terminal/gwt/client/ui/root/RootConnector.java
index 7e84ee1328..048e3ee94c 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/root/RootConnector.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/root/RootConnector.java
@@ -29,7 +29,6 @@ import com.vaadin.terminal.gwt.client.Focusable;
import com.vaadin.terminal.gwt.client.MouseEventDetails;
import com.vaadin.terminal.gwt.client.Paintable;
import com.vaadin.terminal.gwt.client.UIDL;
-import com.vaadin.terminal.gwt.client.Util;
import com.vaadin.terminal.gwt.client.VConsole;
import com.vaadin.terminal.gwt.client.communication.RpcProxy;
import com.vaadin.terminal.gwt.client.communication.StateChangeEvent;
@@ -39,13 +38,14 @@ import com.vaadin.terminal.gwt.client.ui.ClickEventHandler;
import com.vaadin.terminal.gwt.client.ui.Component;
import com.vaadin.terminal.gwt.client.ui.Component.LoadStyle;
import com.vaadin.terminal.gwt.client.ui.ShortcutActionHandler;
+import com.vaadin.terminal.gwt.client.ui.layout.MayScrollChildren;
import com.vaadin.terminal.gwt.client.ui.notification.VNotification;
import com.vaadin.terminal.gwt.client.ui.window.WindowConnector;
import com.vaadin.ui.Root;
@Component(value = Root.class, loadStyle = LoadStyle.EAGER)
public class RootConnector extends AbstractComponentContainerConnector
- implements Paintable {
+ implements Paintable, MayScrollChildren {
private RootServerRPC rpc = RpcProxy.create(RootServerRPC.class, this);
@@ -226,12 +226,6 @@ public class RootConnector extends AbstractComponentContainerConnector
getWidget().scrollable = false;
}
- // Safari workaround must be run after scrollTop is updated as it sets
- // scrollTop using a deferred command.
- if (BrowserInfo.get().isSafari()) {
- Util.runWebkitOverflowAutoFix(getWidget().getElement());
- }
-
if (uidl.hasAttribute("scrollTo")) {
final ComponentConnector connector = (ComponentConnector) uidl
.getPaintableAttribute("scrollTo", getConnection());
diff --git a/src/com/vaadin/terminal/gwt/client/ui/root/VRoot.java b/src/com/vaadin/terminal/gwt/client/ui/root/VRoot.java
index 8182753ab2..13fc55d7ea 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/root/VRoot.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/root/VRoot.java
@@ -20,8 +20,9 @@ import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.SimplePanel;
import com.vaadin.terminal.gwt.client.ApplicationConnection;
import com.vaadin.terminal.gwt.client.BrowserInfo;
+import com.vaadin.terminal.gwt.client.ComponentConnector;
+import com.vaadin.terminal.gwt.client.ConnectorMap;
import com.vaadin.terminal.gwt.client.Focusable;
-import com.vaadin.terminal.gwt.client.Util;
import com.vaadin.terminal.gwt.client.VConsole;
import com.vaadin.terminal.gwt.client.ui.ShortcutActionHandler;
import com.vaadin.terminal.gwt.client.ui.ShortcutActionHandler.ShortcutActionHandlerOwner;
@@ -150,23 +151,27 @@ public class VRoot extends SimplePanel implements ResizeHandler,
*/
protected void windowSizeMaybeChanged(int newWidth, int newHeight) {
boolean changed = false;
+ ComponentConnector connector = ConnectorMap.get(connection)
+ .getConnector(this);
if (width != newWidth) {
width = newWidth;
changed = true;
+ connector.getLayoutManager().reportOuterWidth(connector, newWidth);
VConsole.log("New window width: " + width);
}
if (height != newHeight) {
height = newHeight;
changed = true;
+ connector.getLayoutManager()
+ .reportOuterHeight(connector, newHeight);
VConsole.log("New window height: " + height);
}
if (changed) {
VConsole.log("Running layout functions due to window resize");
- Util.runWebkitOverflowAutoFix(getElement());
sendClientResized();
- connection.doLayout(false);
+ connector.getLayoutManager().layoutNow();
}
}
diff --git a/src/com/vaadin/terminal/gwt/client/ui/splitpanel/AbstractSplitPanelConnector.java b/src/com/vaadin/terminal/gwt/client/ui/splitpanel/AbstractSplitPanelConnector.java
index 66416cf0ec..f8fd2faf41 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/splitpanel/AbstractSplitPanelConnector.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/splitpanel/AbstractSplitPanelConnector.java
@@ -4,6 +4,7 @@
package com.vaadin.terminal.gwt.client.ui.splitpanel;
import java.util.LinkedList;
+import java.util.List;
import com.google.gwt.dom.client.NativeEvent;
import com.google.gwt.event.dom.client.DomEvent;
@@ -15,6 +16,7 @@ import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.ui.Widget;
import com.vaadin.terminal.gwt.client.ComponentConnector;
import com.vaadin.terminal.gwt.client.ConnectorHierarchyChangeEvent;
+import com.vaadin.terminal.gwt.client.LayoutManager;
import com.vaadin.terminal.gwt.client.MouseEventDetails;
import com.vaadin.terminal.gwt.client.communication.RpcProxy;
import com.vaadin.terminal.gwt.client.communication.StateChangeEvent;
@@ -140,6 +142,28 @@ public abstract class AbstractSplitPanelConnector extends
VAbstractSplitPanel splitPanel = getWidget();
splitPanel.setSplitPosition(splitPanel.position);
splitPanel.updateSizes();
+ // Report relative sizes in other direction for quicker propagation
+ List<ComponentConnector> children = getChildren();
+ for (ComponentConnector child : children) {
+ reportOtherDimension(child);
+ }
+ }
+
+ private void reportOtherDimension(ComponentConnector child) {
+ LayoutManager layoutManager = getLayoutManager();
+ if (this instanceof HorizontalSplitPanelConnector) {
+ if (child.isRelativeHeight()) {
+ int height = layoutManager.getInnerHeight(getWidget()
+ .getElement());
+ layoutManager.reportHeightAssignedToRelative(child, height);
+ }
+ } else {
+ if (child.isRelativeWidth()) {
+ int width = layoutManager.getInnerWidth(getWidget()
+ .getElement());
+ layoutManager.reportWidthAssignedToRelative(child, width);
+ }
+ }
}
@Override
diff --git a/src/com/vaadin/terminal/gwt/client/ui/splitpanel/VAbstractSplitPanel.java b/src/com/vaadin/terminal/gwt/client/ui/splitpanel/VAbstractSplitPanel.java
index 6aad93dc5c..166e79e92e 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/splitpanel/VAbstractSplitPanel.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/splitpanel/VAbstractSplitPanel.java
@@ -25,6 +25,9 @@ import com.google.gwt.user.client.ui.ComplexPanel;
import com.google.gwt.user.client.ui.Widget;
import com.vaadin.terminal.gwt.client.ApplicationConnection;
import com.vaadin.terminal.gwt.client.BrowserInfo;
+import com.vaadin.terminal.gwt.client.ComponentConnector;
+import com.vaadin.terminal.gwt.client.ConnectorMap;
+import com.vaadin.terminal.gwt.client.LayoutManager;
import com.vaadin.terminal.gwt.client.Util;
import com.vaadin.terminal.gwt.client.VConsole;
import com.vaadin.terminal.gwt.client.ui.TouchScrollDelegate;
@@ -299,6 +302,28 @@ public class VAbstractSplitPanel extends ComplexPanel {
DOM.setStyleAttribute(secondContainer, "left",
(pixelPosition + getSplitterSize()) + "px");
+ LayoutManager layoutManager = LayoutManager.get(client);
+ ConnectorMap connectorMap = ConnectorMap.get(client);
+ if (firstChild != null) {
+ ComponentConnector connector = connectorMap
+ .getConnector(firstChild);
+ if (connector.isRelativeWidth()) {
+ layoutManager.reportWidthAssignedToRelative(connector,
+ pixelPosition);
+ } else {
+ layoutManager.setNeedsMeasure(connector);
+ }
+ }
+ if (secondChild != null) {
+ ComponentConnector connector = connectorMap
+ .getConnector(secondChild);
+ if (connector.isRelativeWidth()) {
+ layoutManager.reportWidthAssignedToRelative(connector,
+ secondContainerWidth);
+ } else {
+ layoutManager.setNeedsMeasure(connector);
+ }
+ }
break;
case ORIENTATION_VERTICAL:
wholeSize = DOM.getElementPropertyInt(wrapper, "clientHeight");
@@ -326,6 +351,28 @@ public class VAbstractSplitPanel extends ComplexPanel {
DOM.setStyleAttribute(secondContainer, "top",
(pixelPosition + getSplitterSize()) + "px");
+ layoutManager = LayoutManager.get(client);
+ connectorMap = ConnectorMap.get(client);
+ if (firstChild != null) {
+ ComponentConnector connector = connectorMap
+ .getConnector(firstChild);
+ if (connector.isRelativeHeight()) {
+ layoutManager.reportHeightAssignedToRelative(connector,
+ pixelPosition);
+ } else {
+ layoutManager.setNeedsMeasure(connector);
+ }
+ }
+ if (secondChild != null) {
+ ComponentConnector connector = connectorMap
+ .getConnector(secondChild);
+ if (connector.isRelativeHeight()) {
+ layoutManager.reportHeightAssignedToRelative(connector,
+ secondContainerHeight);
+ } else {
+ layoutManager.setNeedsMeasure(connector);
+ }
+ }
break;
}
@@ -463,7 +510,6 @@ public class VAbstractSplitPanel extends ComplexPanel {
}
setSplitPosition(newX + "px");
- client.doLayout(false);
}
private void onVerticalMouseMove(int y) {
@@ -507,7 +553,6 @@ public class VAbstractSplitPanel extends ComplexPanel {
}
setSplitPosition(newY + "px");
- client.doLayout(false);
}
public void onMouseUp(Event event) {
diff --git a/src/com/vaadin/terminal/gwt/client/ui/table/TableConnector.java b/src/com/vaadin/terminal/gwt/client/ui/table/TableConnector.java
index 76c6c21571..e0cd3dc4c7 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/table/TableConnector.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/table/TableConnector.java
@@ -7,6 +7,7 @@ import java.util.Iterator;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.Scheduler;
+import com.google.gwt.core.client.Scheduler.ScheduledCommand;
import com.google.gwt.dom.client.Style.Position;
import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.ui.Widget;
@@ -282,7 +283,18 @@ public class TableConnector extends AbstractComponentContainerConnector
}
public void postLayout() {
- getWidget().sizeInit();
+ VScrollTable table = getWidget();
+ if (table.sizeNeedsInit) {
+ table.sizeInit();
+ Scheduler.get().scheduleFinally(new ScheduledCommand() {
+ public void execute() {
+ getLayoutManager().setNeedsMeasure(TableConnector.this);
+ getLayoutManager()
+ .setHeightNeedsUpdate(TableConnector.this);
+ getLayoutManager().layoutNow();
+ }
+ });
+ }
}
@Override
diff --git a/src/com/vaadin/terminal/gwt/client/ui/table/VScrollTable.java b/src/com/vaadin/terminal/gwt/client/ui/table/VScrollTable.java
index fbe1ef2f27..cf6209e312 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/table/VScrollTable.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/table/VScrollTable.java
@@ -465,7 +465,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
int serverCacheFirst = -1;
int serverCacheLast = -1;
- private boolean sizeNeedsInit = true;
+ boolean sizeNeedsInit = true;
/**
* Used to recall the position of an open context menu if we need to close
@@ -1629,9 +1629,6 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
* * Makes deferred request to get some cache rows
*/
void sizeInit() {
- if (!sizeNeedsInit) {
- return;
- }
sizeNeedsInit = false;
scrollBody.setContainerHeight();
@@ -1884,8 +1881,6 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
Util.runWebkitOverflowAutoFix(scrollBodyPanel.getElement());
}
});
-
- client.doLayout(true);
}
/**
diff --git a/src/com/vaadin/terminal/gwt/client/ui/tabsheet/TabsheetConnector.java b/src/com/vaadin/terminal/gwt/client/ui/tabsheet/TabsheetConnector.java
index 7423a536f2..0518b3a480 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/tabsheet/TabsheetConnector.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/tabsheet/TabsheetConnector.java
@@ -11,11 +11,12 @@ import com.vaadin.terminal.gwt.client.ComponentConnector;
import com.vaadin.terminal.gwt.client.UIDL;
import com.vaadin.terminal.gwt.client.ui.Component;
import com.vaadin.terminal.gwt.client.ui.SimpleManagedLayout;
+import com.vaadin.terminal.gwt.client.ui.layout.MayScrollChildren;
import com.vaadin.ui.TabSheet;
@Component(TabSheet.class)
public class TabsheetConnector extends TabsheetBaseConnector implements
- SimpleManagedLayout {
+ SimpleManagedLayout, MayScrollChildren {
@Override
public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
diff --git a/src/com/vaadin/terminal/gwt/client/ui/tabsheet/VTabsheet.java b/src/com/vaadin/terminal/gwt/client/ui/tabsheet/VTabsheet.java
index 908a984dbb..c97ede1252 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/tabsheet/VTabsheet.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/tabsheet/VTabsheet.java
@@ -943,7 +943,6 @@ public class VTabsheet extends VTabsheetBase implements Focusable,
public void iLayout() {
updateTabScroller();
- tp.runWebkitOverflowAutoFix();
}
/**
diff --git a/src/com/vaadin/terminal/gwt/client/ui/tabsheet/VTabsheetPanel.java b/src/com/vaadin/terminal/gwt/client/ui/tabsheet/VTabsheetPanel.java
index ee0571d3a7..f2b37c3a1c 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/tabsheet/VTabsheetPanel.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/tabsheet/VTabsheetPanel.java
@@ -13,7 +13,6 @@ import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.ui.ComplexPanel;
import com.google.gwt.user.client.ui.Widget;
-import com.vaadin.terminal.gwt.client.Util;
import com.vaadin.terminal.gwt.client.ui.TouchScrollDelegate;
/**
@@ -194,16 +193,12 @@ public class VTabsheetPanel extends ComplexPanel {
getElement().getStyle().setPropertyPx("height", height);
// widget wrapper height
- wrapperDiv.getStyle().setPropertyPx("height", height);
- runWebkitOverflowAutoFix();
- }
-
- public void runWebkitOverflowAutoFix() {
- if (visibleWidget != null) {
- Util.runWebkitOverflowAutoFix(DOM.getParent(visibleWidget
- .getElement()));
+ if (dynamicHeight) {
+ wrapperDiv.getStyle().clearHeight();
+ } else {
+ // widget wrapper height
+ wrapperDiv.getStyle().setPropertyPx("height", height);
}
-
}
public void replaceComponent(Widget oldComponent, Widget newComponent) {
diff --git a/src/com/vaadin/terminal/gwt/client/ui/twincolselect/TwinColSelectConnector.java b/src/com/vaadin/terminal/gwt/client/ui/twincolselect/TwinColSelectConnector.java
index de1095f664..d8ad511d86 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/twincolselect/TwinColSelectConnector.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/twincolselect/TwinColSelectConnector.java
@@ -36,6 +36,12 @@ public class TwinColSelectConnector extends OptionGroupBaseConnector implements
}
@Override
+ public void onUnregister() {
+ getLayoutManager().unregisterDependency(this,
+ getWidget().captionWrapper.getElement());
+ }
+
+ @Override
protected Widget createWidget() {
return GWT.create(VTwinColSelect.class);
}
diff --git a/src/com/vaadin/terminal/gwt/client/ui/window/VWindow.java b/src/com/vaadin/terminal/gwt/client/ui/window/VWindow.java
index 3a1e0e8663..2c5fadff3b 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/window/VWindow.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/window/VWindow.java
@@ -711,8 +711,10 @@ public class VWindow extends VOverlay implements ShortcutActionHandlerOwner,
client.runDescendentsLayout((HasWidgets) layout.getWidget());
}
- Util.runWebkitOverflowAutoFix(contentPanel.getElement());
- client.doLayout(false);
+ LayoutManager layoutManager = LayoutManager.get(client);
+ layoutManager.setNeedsMeasure(ConnectorMap.get(client).getConnector(
+ this));
+ layoutManager.layoutNow();
}
@Override
diff --git a/src/com/vaadin/terminal/gwt/client/ui/window/WindowConnector.java b/src/com/vaadin/terminal/gwt/client/ui/window/WindowConnector.java
index 57c931fac9..fbb7a3683b 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/window/WindowConnector.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/window/WindowConnector.java
@@ -21,7 +21,6 @@ import com.vaadin.terminal.gwt.client.LayoutManager;
import com.vaadin.terminal.gwt.client.MouseEventDetails;
import com.vaadin.terminal.gwt.client.Paintable;
import com.vaadin.terminal.gwt.client.UIDL;
-import com.vaadin.terminal.gwt.client.Util;
import com.vaadin.terminal.gwt.client.communication.RpcProxy;
import com.vaadin.terminal.gwt.client.ui.AbstractComponentContainerConnector;
import com.vaadin.terminal.gwt.client.ui.ClickEventHandler;
@@ -30,11 +29,12 @@ import com.vaadin.terminal.gwt.client.ui.PostLayoutListener;
import com.vaadin.terminal.gwt.client.ui.ShortcutActionHandler;
import com.vaadin.terminal.gwt.client.ui.ShortcutActionHandler.BeforeShortcutActionListener;
import com.vaadin.terminal.gwt.client.ui.SimpleManagedLayout;
+import com.vaadin.terminal.gwt.client.ui.layout.MayScrollChildren;
@Component(value = com.vaadin.ui.Window.class)
public class WindowConnector extends AbstractComponentContainerConnector
implements Paintable, BeforeShortcutActionListener,
- SimpleManagedLayout, PostLayoutListener {
+ SimpleManagedLayout, PostLayoutListener, MayScrollChildren {
private ClickEventHandler clickEventHandler = new ClickEventHandler(this) {
@Override
@@ -62,6 +62,15 @@ public class WindowConnector extends AbstractComponentContainerConnector
getLayoutManager().registerDependency(this, getWidget().footer);
}
+ @Override
+ public void onUnregister() {
+ LayoutManager lm = getLayoutManager();
+ VWindow window = getWidget();
+ lm.unregisterDependency(this, window.contentPanel.getElement());
+ lm.unregisterDependency(this, window.header);
+ lm.unregisterDependency(this, window.footer);
+ }
+
public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
getWidget().id = getConnectorId();
getWidget().client = client;
@@ -262,8 +271,6 @@ public class WindowConnector extends AbstractComponentContainerConnector
} else {
childStyle.clearPosition();
}
-
- Util.runWebkitOverflowAutoFix(window.contentPanel.getElement());
}
public void postLayout() {