]> source.dussan.org Git - vaadin-framework.git/commitdiff
Add LayoutManager.setNeedsMeasure and change how layouts are started
authorLeif Åstrand <leif@vaadin.com>
Tue, 10 Apr 2012 09:39:09 +0000 (12:39 +0300)
committerLeif Åstrand <leif@vaadin.com>
Tue, 10 Apr 2012 09:39:09 +0000 (12:39 +0300)
src/com/vaadin/terminal/gwt/client/ApplicationConnection.java
src/com/vaadin/terminal/gwt/client/LayoutManager.java
src/com/vaadin/terminal/gwt/client/Util.java
src/com/vaadin/terminal/gwt/client/ui/TableConnector.java
src/com/vaadin/terminal/gwt/client/ui/VAbstractSplitPanel.java
src/com/vaadin/terminal/gwt/client/ui/VDragAndDropWrapper.java
src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java
src/com/vaadin/terminal/gwt/client/ui/VView.java
src/com/vaadin/terminal/gwt/client/ui/VWindow.java

index e9a2a5b8be2ebe2d2f197155cd205ff38809a390..6a8856eaee68b20602e82e25cff17efbeca8072b 100644 (file)
@@ -1123,7 +1123,9 @@ public class ApplicationConnection {
                         + (updateDuration.elapsedMillis() - startProcessing)
                         + " ms");
 
-                doLayout(false);
+                LayoutManager layoutManager = getLayoutManager();
+                layoutManager.setEverythingNeedsMeasure();
+                layoutManager.layoutNow();
 
                 updateDuration
                         .logDuration(" * Layout processing completed", 10);
@@ -2182,40 +2184,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 " + view.getClass().getName());
-            runDescendentsLayout(view.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;
     }
@@ -2377,36 +2347,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;
     }
index a9a58845b47c684a1ed545e1de35029099920a98..875551e621a77436bb047161a48b16e3dfd4cab8 100644 (file)
@@ -13,6 +13,7 @@ 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.Unit;
+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;
@@ -34,11 +35,23 @@ public class LayoutManager {
     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 final 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) {
             throw new RuntimeException(
@@ -136,11 +149,28 @@ public class LayoutManager {
         }
     }
 
-    public void doLayout() {
+    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");
 
         Map<ManagedLayout, Integer> layoutCounts = new HashMap<ManagedLayout, Integer>();
@@ -148,8 +178,6 @@ public class LayoutManager {
         int passes = 0;
         Duration totalDuration = new Duration();
 
-        currentDependencyTree = new LayoutDependencyTree();
-
         for (ManagedLayout layout : needsHorizontalLayout) {
             currentDependencyTree.setNeedsHorizontalLayout(layout, true);
         }
@@ -158,6 +186,12 @@ public class LayoutManager {
         }
         needsHorizontalLayout.clear();
         needsVerticalLayout.clear();
+
+        for (ComponentConnector connector : needsMeasure) {
+            currentDependencyTree.setNeedsMeasure(connector, true);
+        }
+        needsMeasure.clear();
+
         measureNonPaintables();
 
         VConsole.log("Layout init in " + totalDuration.elapsedMillis() + " ms");
@@ -167,7 +201,8 @@ public class LayoutManager {
             passes++;
 
             int measuredConnectorCount = measureConnectors(
-                    currentDependencyTree, passes == 1);
+                    currentDependencyTree, everythingNeedsMeasure);
+            everythingNeedsMeasure = false;
 
             int measureTime = passDuration.elapsedMillis();
             VConsole.log("  Measured " + measuredConnectorCount
@@ -287,7 +322,6 @@ public class LayoutManager {
         VConsole.log("Invoke post layout listeners in "
                 + (totalDuration.elapsedMillis() - postLayoutStart) + " ms");
 
-        currentDependencyTree = null;
         VConsole.log("Total layout phase time: "
                 + totalDuration.elapsedMillis() + "ms");
     }
@@ -445,7 +479,8 @@ public class LayoutManager {
                 setNeedsUpdate((ManagedLayout) connector);
             }
         }
-        doLayout();
+        setEverythingNeedsMeasure();
+        layoutNow();
     }
 
     // TODO Rename to setNeedsLayout
@@ -531,19 +566,19 @@ public class LayoutManager {
     }
 
     public void reportOuterHeight(ComponentConnector component, int outerHeight) {
-        if (!isLayoutRunning()) {
-            throw new IllegalStateException(
-                    "Can only report sizes when layout is running");
-        }
         MeasuredSize measuredSize = getMeasuredSize(component);
-        boolean heightChanged = measuredSize.setOuterHeight(outerHeight);
+        if (isLayoutRunning()) {
+            boolean heightChanged = measuredSize.setOuterHeight(outerHeight);
 
-        if (heightChanged) {
-            onConnectorChange(component, false, true);
-            notifyListenersAndDepdendents(component.getWidget().getElement(),
-                    false, true);
+            if (heightChanged) {
+                onConnectorChange(component, false, true);
+                notifyListenersAndDepdendents(component.getWidget()
+                        .getElement(), false, true);
+            }
+            currentDependencyTree.setNeedsVerticalMeasure(component, false);
+        } else if (measuredSize.getOuterHeight() != outerHeight) {
+            setNeedsMeasure(component);
         }
-        currentDependencyTree.setNeedsVerticalMeasure(component, false);
     }
 
     public void reportHeightAssignedToRelative(ComponentConnector component,
@@ -571,20 +606,19 @@ public class LayoutManager {
     }
 
     public void reportOuterWidth(ComponentConnector component, int outerWidth) {
-        if (!isLayoutRunning()) {
-            throw new IllegalStateException(
-                    "Can only report sizes when layout is running");
-        }
-
         MeasuredSize measuredSize = getMeasuredSize(component);
-        boolean widthChanged = measuredSize.setOuterWidth(outerWidth);
+        if (isLayoutRunning()) {
+            boolean widthChanged = measuredSize.setOuterWidth(outerWidth);
 
-        if (widthChanged) {
-            onConnectorChange(component, true, false);
-            notifyListenersAndDepdendents(component.getWidget().getElement(),
-                    true, false);
+            if (widthChanged) {
+                onConnectorChange(component, true, false);
+                notifyListenersAndDepdendents(component.getWidget()
+                        .getElement(), true, false);
+            }
+            currentDependencyTree.setNeedsHorizontalMeasure(component, false);
+        } else if (measuredSize.getOuterWidth() != outerWidth) {
+            setNeedsMeasure(component);
         }
-        currentDependencyTree.setNeedsHorizontalMeasure(component, false);
     }
 
     public void addElementResizeListener(Element element,
@@ -618,4 +652,17 @@ public class LayoutManager {
             setMeasuredSize(element, null);
         }
     }
+
+    public void setNeedsMeasure(ComponentConnector component) {
+        if (isLayoutRunning()) {
+            currentDependencyTree.setNeedsMeasure(component, true);
+        } else {
+            needsMeasure.add(component);
+            layoutLater();
+        }
+    }
+
+    public void setEverythingNeedsMeasure() {
+        everythingNeedsMeasure = true;
+    }
 }
index 374d2103794fb291fae831c847d06737af7ee231..bfe63caefd57ee438e7a8f65760985e3e83d6b80 100644 (file)
@@ -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;
             }
         }
 
index 7acdc84b5fc6bc9a35a3d732a7ca8e1c07b3ec91..2c546f40b18bc25d961978f86a6d25eab44daa80 100644 (file)
@@ -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;
@@ -279,7 +280,16 @@ 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().setNeedsUpdate(TableConnector.this);
+                    getLayoutManager().layoutNow();
+                }
+            });
+        }
     }
 
     @Override
index 55742f24b366ad43ac63568277581260126c0c15..f08cbf58e92f071e870e556738268441afcb6094 100644 (file)
@@ -301,23 +301,25 @@ public class VAbstractSplitPanel extends ComplexPanel {
                     (pixelPosition + getSplitterSize()) + "px");
 
             LayoutManager layoutManager = LayoutManager.get(client);
-            if (layoutManager.isLayoutRunning()) {
-                ConnectorMap connectorMap = ConnectorMap.get(client);
-                if (firstChild != null) {
-                    ComponentConnector connector = connectorMap
-                            .getConnector(firstChild);
-                    if (connector.isRelativeWidth()) {
-                        layoutManager.reportWidthAssignedToRelative(connector,
-                                pixelPosition);
-                    }
+            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);
-                    }
+            }
+            if (secondChild != null) {
+                ComponentConnector connector = connectorMap
+                        .getConnector(secondChild);
+                if (connector.isRelativeWidth()) {
+                    layoutManager.reportWidthAssignedToRelative(connector,
+                            secondContainerWidth);
+                } else {
+                    layoutManager.setNeedsMeasure(connector);
                 }
             }
             break;
@@ -348,23 +350,25 @@ public class VAbstractSplitPanel extends ComplexPanel {
                     (pixelPosition + getSplitterSize()) + "px");
 
             layoutManager = LayoutManager.get(client);
-            if (layoutManager.isLayoutRunning()) {
-                ConnectorMap connectorMap = ConnectorMap.get(client);
-                if (firstChild != null) {
-                    ComponentConnector connector = connectorMap
-                            .getConnector(firstChild);
-                    if (connector.isRelativeHeight()) {
-                        layoutManager.reportHeightAssignedToRelative(connector,
-                                pixelPosition);
-                    }
+            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);
-                    }
+            }
+            if (secondChild != null) {
+                ComponentConnector connector = connectorMap
+                        .getConnector(secondChild);
+                if (connector.isRelativeHeight()) {
+                    layoutManager.reportHeightAssignedToRelative(connector,
+                            secondContainerHeight);
+                } else {
+                    layoutManager.setNeedsMeasure(connector);
                 }
             }
 
@@ -504,7 +508,6 @@ public class VAbstractSplitPanel extends ComplexPanel {
         }
 
         setSplitPosition(newX + "px");
-        client.doLayout(false);
     }
 
     private void onVerticalMouseMove(int y) {
@@ -548,7 +551,6 @@ public class VAbstractSplitPanel extends ComplexPanel {
         }
 
         setSplitPosition(newY + "px");
-        client.doLayout(false);
     }
 
     public void onMouseUp(Event event) {
index d87bc78038a68151776d7193c5c55e05b79283e1..d87b7a5c21e01ff511eb29c674ba5c814bfbb5e3 100644 (file)
@@ -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;
@@ -564,10 +565,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);
@@ -578,9 +584,7 @@ public class VDragAndDropWrapper extends VCustomComponent implements
         emphasizedVDrop = verticalDropLocation;
         emphasizedHDrop = horizontalDropLocation;
 
-        // TODO build (to be an example) an emphasis mode where drag image
-        // is fitted before or after the content
-        client.doLayout(false);
+        notifySizePotentiallyChanged();
     }
 
 }
index b372ad7e13b50642c30c9350f97d04e4d20c31f8..6668afecdcc5a7c611ce6ace0e7b3a1a5cf63889 100644 (file)
@@ -458,7 +458,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
@@ -1622,9 +1622,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();
@@ -1877,8 +1874,6 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
                 Util.runWebkitOverflowAutoFix(scrollBodyPanel.getElement());
             }
         });
-
-        client.doLayout(true);
     }
 
     /**
index 1c655ec6d9201e727b26aaf00a401431854a0000..e69b11a8f3da4a2c491b1dde5a5c0ba07ce60ade 100644 (file)
@@ -24,6 +24,7 @@ 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.UIDL;
 import com.vaadin.terminal.gwt.client.VConsole;
@@ -155,13 +156,18 @@ public class VView 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;
+            connector.getLayoutManager()
+                    .reportOuterHeight(connector, newHeight);
             changed = true;
             VConsole.log("New window height: " + height);
         }
@@ -169,7 +175,7 @@ public class VView extends SimplePanel implements ResizeHandler,
             VConsole.log("Running layout functions due to window resize");
             sendClientResized();
 
-            connection.doLayout(false);
+            connector.getLayoutManager().layoutNow();
         }
     }
 
index 4bc7bdf371385d79b4cb2fba9278566b469e7330..35dfc5225ce8bb28abcd1a06ba0eec84d68be359 100644 (file)
@@ -702,7 +702,10 @@ public class VWindow extends VOverlay implements ShortcutActionHandlerOwner,
             client.runDescendentsLayout((HasWidgets) layout.getWidget());
         }
 
-        client.doLayout(false);
+        LayoutManager layoutManager = LayoutManager.get(client);
+        layoutManager.setNeedsMeasure(ConnectorMap.get(client).getConnector(
+                this));
+        layoutManager.layoutNow();
     }
 
     @Override