Bläddra i källkod

Defer nested components to paint them as top-level changes (#8304).

Refactoring and changes to paint nested component contents after the
component in which they are nested. The client side can create
uninitialized components immediately but defer configuring them.
tags/7.0.0.alpha2
Henri Sara 12 år sedan
förälder
incheckning
3588a2fad5

+ 30
- 4
src/com/vaadin/terminal/PaintTarget.java Visa fil

@@ -36,6 +36,31 @@ public interface PaintTarget extends Serializable {
public void addSection(String sectionTagName, String sectionData)
throws PaintException;

/**
* Result of starting to paint a Paintable (
* {@link PaintTarget#startPaintable(Paintable, String)}).
*
* @since 7.0
*/
public enum PaintStatus {
/**
* Painting started, addVariable() and addAttribute() etc. methods may
* be called.
*/
PAINTING,
/**
* Paintable is cached on the client side and unmodified - only an
* indication of that should be painted.
*/
CACHED,
/**
* A previously unpainted or painted {@link Paintable} has been queued
* be created/update later in a separate change in the same set of
* changes.
*/
DEFER
};

/**
* Prints element start tag of a paintable section. Starts a paintable
* section using the given tag. The PaintTarget may implement a caching
@@ -52,21 +77,22 @@ public interface PaintTarget extends Serializable {
* </p>
* <p>
* Each paintable being painted should be closed by a matching
* {@link #endPaintable(Paintable)}.
* {@link #endPaintable(Paintable)} regardless of the {@link PaintStatus}
* returned.
* </p>
*
* @param paintable
* the paintable to start.
* @param tag
* the name of the start tag.
* @return <code>true</code> if paintable found in cache, <code>false</code>
* otherwise.
* @return {@link PaintStatus} - ready to paint, already cached on the
* client or defer painting to another change
* @throws PaintException
* if the paint operation failed.
* @see #startTag(String)
* @since 7.0 (previously using startTag(Paintable, String))
*/
public boolean startPaintable(Paintable paintable, String tag)
public PaintStatus startPaintable(Paintable paintable, String tag)
throws PaintException;

/**

+ 2
- 0
src/com/vaadin/terminal/gwt/client/ApplicationConnection.java Visa fil

@@ -1865,6 +1865,8 @@ public class ApplicationConnection {
*/
public VPaintableWidget getPaintable(UIDL uidl) {
final String pid = uidl.getId();
// the actual content UIDL may be deferred, but it always contains
// enough information to create a paintable instance
if (!paintableMap.hasPaintable(pid)) {
// Create and register a new paintable if no old was found
VPaintableWidget p = widgetSet.createWidget(uidl.getTag(),

+ 2
- 1
src/com/vaadin/terminal/gwt/client/ui/VAbstractPaintableWidget.java Visa fil

@@ -106,7 +106,8 @@ public abstract class VAbstractPaintableWidget implements VPaintableWidget {
}

protected static boolean isRealUpdate(UIDL uidl) {
return !isCachedUpdate(uidl) && !uidl.getBooleanAttribute("invisible");
return !isCachedUpdate(uidl) && !uidl.getBooleanAttribute("invisible")
&& !uidl.hasAttribute("deferred");
}

protected static boolean isCachedUpdate(UIDL uidl) {

+ 19
- 23
src/com/vaadin/terminal/gwt/client/ui/layout/CellBasedLayoutPaintable.java Visa fil

@@ -15,25 +15,24 @@ public abstract class CellBasedLayoutPaintable extends
public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
getWidgetForPaintable().client = client;

// Only non-cached UIDL:s can introduce changes
if (isCachedUpdate(uidl)) {
return;
if (isRealUpdate(uidl)) {
/**
* Margin and spacing detection depends on classNames and must be
* set before setting size. Here just update the details from UIDL
* and from overridden setStyleName run actual margin detections.
*/
updateMarginAndSpacingInfo(uidl);
}

/**
* Margin and spacind detection depends on classNames and must be set
* before setting size. Here just update the details from UIDL and from
* overridden setStyleName run actual margin detections.
*/
updateMarginAndSpacingInfo(uidl);

/*
* This call should be made first. Ensure correct implementation, handle
* size etc.
*/
super.updateFromUIDL(uidl, client);

handleDynamicDimensions(uidl);
if (isRealUpdate(uidl)) {
handleDynamicDimensions(uidl);
}
}

private void handleDynamicDimensions(UIDL uidl) {
@@ -58,18 +57,15 @@ public abstract class CellBasedLayoutPaintable extends
}

void updateMarginAndSpacingInfo(UIDL uidl) {
if (!uidl.hasAttribute("invisible")) {
int bitMask = uidl.getIntAttribute("margins");
if (getWidgetForPaintable().activeMarginsInfo.getBitMask() != bitMask) {
getWidgetForPaintable().activeMarginsInfo = new VMarginInfo(
bitMask);
getWidgetForPaintable().marginsNeedsRecalculation = true;
}
boolean spacing = uidl.getBooleanAttribute("spacing");
if (spacing != getWidgetForPaintable().spacingEnabled) {
getWidgetForPaintable().marginsNeedsRecalculation = true;
getWidgetForPaintable().spacingEnabled = spacing;
}
int bitMask = uidl.getIntAttribute("margins");
if (getWidgetForPaintable().activeMarginsInfo.getBitMask() != bitMask) {
getWidgetForPaintable().activeMarginsInfo = new VMarginInfo(bitMask);
getWidgetForPaintable().marginsNeedsRecalculation = true;
}
boolean spacing = uidl.getBooleanAttribute("spacing");
if (spacing != getWidgetForPaintable().spacingEnabled) {
getWidgetForPaintable().marginsNeedsRecalculation = true;
getWidgetForPaintable().spacingEnabled = spacing;
}
}


+ 4
- 3
src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java Visa fil

@@ -856,12 +856,13 @@ public abstract class AbstractCommunicationManager implements
// rendered already (changes with only cached flag)
if (paintTarget.needsToBePainted(p)) {
paintTarget.startTag("change");
paintTarget.addAttribute("format", "uidl");
final String pid = getPaintableId(p);
paintTarget.addAttribute("pid", pid);

// TODO this should paint subcomponents as references and
// defer painting their contents to another top-level change
// paints subcomponents as references (via
// JsonPaintTarget.startPaintable()) and defers painting
// their contents to another top-level change (via
// queuePaintable())
p.paint(paintTarget);

paintTarget.endTag("change");

+ 30
- 16
src/com/vaadin/terminal/gwt/server/JsonPaintTarget.java Visa fil

@@ -11,6 +11,7 @@ import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.Serializable;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
@@ -90,6 +91,8 @@ public class JsonPaintTarget implements PaintTarget {

private Collection<Paintable> identifiersCreatedDueRefPaint;

private Collection<Paintable> deferredPaintables;

private final Collection<Class<? extends Paintable>> usedPaintableTypes = new LinkedList<Class<? extends Paintable>>();

/**
@@ -120,6 +123,8 @@ public class JsonPaintTarget implements PaintTarget {
openPaintables = new Stack<Paintable>();
openPaintableTags = new Stack<String>();

deferredPaintables = new ArrayList<Paintable>();

cacheEnabled = cachingRequired;
}

@@ -677,37 +682,46 @@ public class JsonPaintTarget implements PaintTarget {
/*
* (non-Javadoc)
*
* @see com.vaadin.terminal.PaintTarget#startTag(com.vaadin.terminal
* @see com.vaadin.terminal.PaintTarget#startPaintable(com.vaadin.terminal
* .Paintable, java.lang.String)
*/
public boolean startPaintable(Paintable paintable, String tagName)
public PaintStatus startPaintable(Paintable paintable, String tagName)
throws PaintException {
startTag(tagName, true);
final boolean isPreviouslyPainted = manager.hasPaintableId(paintable)
&& (identifiersCreatedDueRefPaint == null || !identifiersCreatedDueRefPaint
.contains(paintable));
.contains(paintable))
&& !deferredPaintables.contains(paintable);
final String id = manager.getPaintableId(paintable);
paintable.addListener(manager);
addAttribute("id", id);

// TODO if to queue if already painting a paintable
// if (openPaintables.isEmpty()) {
// queue for painting later if already painting a paintable
boolean topLevelPaintableTag = openPaintables.isEmpty();

openPaintables.push(paintable);
openPaintableTags.push(tagName);

paintedComponents.add(paintable);
// } else {
// // notify manager: add to paint queue instead of painting now
// manager.queuePaintable(paintable);
// // TODO return suitable value to defer painting and close tag if a
// // paintable tag is already open
// }
if (cacheEnabled && isPreviouslyPainted) {
// cached (unmodified) paintable, paint the it now
paintedComponents.add(paintable);
deferredPaintables.remove(paintable);
return PaintStatus.CACHED;
} else if (!topLevelPaintableTag) {
// notify manager: add to paint queue instead of painting now
manager.queuePaintable(paintable);
deferredPaintables.add(paintable);
return PaintStatus.DEFER;
} else {
// not a nested paintable, paint the it now
paintedComponents.add(paintable);
deferredPaintables.remove(paintable);

if (paintable instanceof CustomLayout) {
customLayoutArgumentsOpen = true;
if (paintable instanceof CustomLayout) {
customLayoutArgumentsOpen = true;
}
return PaintStatus.PAINTING;
}

return cacheEnabled && isPreviouslyPainted;
}

public void endPaintable(Paintable paintable) throws PaintException {

+ 11
- 7
src/com/vaadin/ui/AbstractComponent.java Visa fil

@@ -27,6 +27,7 @@ import com.vaadin.event.ShortcutListener;
import com.vaadin.terminal.ErrorMessage;
import com.vaadin.terminal.PaintException;
import com.vaadin.terminal.PaintTarget;
import com.vaadin.terminal.PaintTarget.PaintStatus;
import com.vaadin.terminal.Resource;
import com.vaadin.terminal.Terminal;
import com.vaadin.terminal.gwt.client.ComponentState;
@@ -753,9 +754,16 @@ public abstract class AbstractComponent implements Component, MethodEventSource
*/
public void paint(PaintTarget target) throws PaintException {
final String tag = target.getTag(this);
if (!target.startPaintable(this, tag)
|| repaintRequestListenersNotified) {

final PaintStatus status = target.startPaintable(this, tag);
if (PaintStatus.DEFER == status) {
// nothing to do but flag as deferred and close the paintable tag
// paint() will be called again later to paint the contents
target.addAttribute("deferred", true);
} else if (PaintStatus.CACHED == status
&& !repaintRequestListenersNotified) {
// Contents have not changed, only cached presentation can be used
target.addAttribute("cached", true);
} else {
// Paint the contents of the component

// Only paint content of visible components.
@@ -809,10 +817,6 @@ public abstract class AbstractComponent implements Component, MethodEventSource
} else {
target.addAttribute("invisible", true);
}
} else {

// Contents have not changed, only cached presentation can be used
target.addAttribute("cached", true);
}
target.endPaintable(this);


Laddar…
Avbryt
Spara