Просмотр исходного кода

Add LayoutManager.setNeedsMeasure and change how layouts are started

tags/7.0.0.alpha2
Leif Åstrand 12 лет назад
Родитель
Сommit
c5ab6b8c89

+ 3
- 63
src/com/vaadin/terminal/gwt/client/ApplicationConnection.java Просмотреть файл

@@ -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;
}

+ 74
- 27
src/com/vaadin/terminal/gwt/client/LayoutManager.java Просмотреть файл

@@ -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;
}
}

+ 13
- 13
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;
}
}


+ 11
- 1
src/com/vaadin/terminal/gwt/client/ui/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;
@@ -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

+ 36
- 34
src/com/vaadin/terminal/gwt/client/ui/VAbstractSplitPanel.java Просмотреть файл

@@ -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) {

+ 8
- 4
src/com/vaadin/terminal/gwt/client/ui/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;
@@ -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();
}

}

+ 1
- 6
src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java Просмотреть файл

@@ -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);
}

/**

+ 7
- 1
src/com/vaadin/terminal/gwt/client/ui/VView.java Просмотреть файл

@@ -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();
}
}


+ 4
- 1
src/com/vaadin/terminal/gwt/client/ui/VWindow.java Просмотреть файл

@@ -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

Загрузка…
Отмена
Сохранить