aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatti Tahvonen <matti.tahvonen@itmill.com>2010-06-29 17:52:15 +0000
committerMatti Tahvonen <matti.tahvonen@itmill.com>2010-06-29 17:52:15 +0000
commit01bada0feac4f2939b1e182c3f904f7f61a7b242 (patch)
tree7fbfc98d3e646cb8d9f79097f1d19d3f95fb822d
parent8dfc1400437ea34f67cd5995b27356d74960640f (diff)
downloadvaadin-framework-01bada0feac4f2939b1e182c3f904f7f61a7b242.tar.gz
vaadin-framework-01bada0feac4f2939b1e182c3f904f7f61a7b242.zip
"premature optimization is the redemption all subtree caching issues" :-)
One level deep optimization of child tree paints, when container size change may require child repaint. Fixes #2366 (optimized at appropriate level), #5270 and most likely #4581 svn changeset:13969/svn branch:6.4
-rw-r--r--src/com/vaadin/ui/AbstractComponentContainer.java140
1 files changed, 120 insertions, 20 deletions
diff --git a/src/com/vaadin/ui/AbstractComponentContainer.java b/src/com/vaadin/ui/AbstractComponentContainer.java
index f3e332961a..8df78be328 100644
--- a/src/com/vaadin/ui/AbstractComponentContainer.java
+++ b/src/com/vaadin/ui/AbstractComponentContainer.java
@@ -5,9 +5,13 @@
package com.vaadin.ui;
import java.lang.reflect.Method;
+import java.util.Collection;
+import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
+import com.vaadin.terminal.gwt.server.ComponentSizeValidator;
+
/**
* Extension to {@link AbstractComponent} that defines the default
* implementation for the methods in {@link ComponentContainer}. Basic UI
@@ -223,34 +227,130 @@ public abstract class AbstractComponentContainer extends AbstractComponent
@Override
public void setWidth(float width, int unit) {
- if (getWidth() < 0 && width >= 0) {
- // width becoming defined -> relative width children currently
- // painted undefined may become defined
- // TODO could be optimized(subtree of only those components
- // which have undefined height due this component), currently just
- // repaints whole subtree
- requestRepaintAll();
- } else if (getWidth() >= 0 && width < 0) {
- requestRepaintAll();
+ /*
+ * child tree repaints may be needed, due to our fall back support for
+ * invalid relative sizes
+ */
+ Collection<Component> dirtyChildren = null;
+ boolean childrenMayBecomeUndefined = false;
+ if (getWidth() == SIZE_UNDEFINED && width != SIZE_UNDEFINED) {
+ // children currently in invalid state may need repaint
+ dirtyChildren = getInvalidSizedChildren(false);
+ } else if ((width == SIZE_UNDEFINED && getWidth() != SIZE_UNDEFINED)
+ || (unit == UNITS_PERCENTAGE
+ && getWidthUnits() != UNITS_PERCENTAGE && !ComponentSizeValidator
+ .parentCanDefineWidth(this))) {
+ /*
+ * relative width children may get to invalid state if width becomes
+ * invalid. Width may also become invalid if units become percentage
+ * due to the fallback support
+ */
+ childrenMayBecomeUndefined = true;
+ dirtyChildren = getInvalidSizedChildren(false);
}
super.setWidth(width, unit);
+ repaintChangedChildTrees(dirtyChildren, childrenMayBecomeUndefined,
+ false);
+ }
+
+ private void repaintChangedChildTrees(
+ Collection<Component> invalidChildren,
+ boolean childrenMayBecomeUndefined, boolean vertical) {
+ if (childrenMayBecomeUndefined) {
+ Collection<Component> previouslyInvalidComponents = invalidChildren;
+ invalidChildren = getInvalidSizedChildren(vertical);
+ if (previouslyInvalidComponents != null) {
+ for (Iterator<Component> iterator = invalidChildren.iterator(); iterator
+ .hasNext();) {
+ Component component = iterator.next();
+ if (previouslyInvalidComponents.contains(component)) {
+ // still invalid don't repaint
+ iterator.remove();
+ }
+ }
+ }
+ } else if (invalidChildren != null) {
+ Collection<Component> stillInvalidChildren = getInvalidSizedChildren(vertical);
+ if (stillInvalidChildren != null) {
+ for (Component component : stillInvalidChildren) {
+ // didn't become valid
+ invalidChildren.remove(component);
+ }
+ }
+ }
+ if (invalidChildren != null) {
+ repaintChildTrees(invalidChildren);
+ }
+ }
+
+ private Collection<Component> getInvalidSizedChildren(final boolean vertical) {
+ HashSet<Component> components = null;
+ if (this instanceof Panel) {
+ Panel p = (Panel) this;
+ ComponentContainer content = p.getContent();
+ boolean valid = vertical ? ComponentSizeValidator
+ .checkHeights(content) : ComponentSizeValidator
+ .checkWidths(content);
+
+ if (!valid) {
+ components = new HashSet<Component>(1);
+ components.add(content);
+ }
+ } else {
+ for (Iterator<Component> componentIterator = getComponentIterator(); componentIterator
+ .hasNext();) {
+ Component component = componentIterator.next();
+ boolean valid = vertical ? ComponentSizeValidator
+ .checkHeights(component) : ComponentSizeValidator
+ .checkWidths(component);
+ if (!valid) {
+ if (components == null) {
+ components = new HashSet<Component>();
+ }
+ components.add(component);
+ }
+ }
+ }
+ return components;
+ }
+
+ private void repaintChildTrees(Collection<Component> dirtyChildren) {
+ for (Component c : dirtyChildren) {
+ if (c instanceof ComponentContainer) {
+ ComponentContainer cc = (ComponentContainer) c;
+ cc.requestRepaintAll();
+ } else {
+ c.requestRepaint();
+ }
+ }
}
@Override
public void setHeight(float height, int unit) {
- float currentHeight = getHeight();
- if (currentHeight < 0.0f && height >= 0.0f) {
- // height becoming defined -> relative height childs currently
- // painted undefined may become defined
- // TODO this could be optimized (subtree of only those components
- // which have undefined width due this component), currently just
- // repaints whole
- // subtree
- requestRepaintAll();
- } else if (currentHeight >= 0 && height < 0) {
- requestRepaintAll();
+ /*
+ * child tree repaints may be needed, due to our fall back support for
+ * invalid relative sizes
+ */
+ Collection<Component> dirtyChildren = null;
+ boolean childrenMayBecomeUndefined = false;
+ if (getHeight() == SIZE_UNDEFINED && height != SIZE_UNDEFINED) {
+ // children currently in invalid state may need repaint
+ dirtyChildren = getInvalidSizedChildren(true);
+ } else if ((height == SIZE_UNDEFINED && getHeight() != SIZE_UNDEFINED)
+ || (unit == UNITS_PERCENTAGE
+ && getHeightUnits() != UNITS_PERCENTAGE && !ComponentSizeValidator
+ .parentCanDefineHeight(this))) {
+ /*
+ * relative height children may get to invalid state if height
+ * becomes invalid. Height may also become invalid if units become
+ * percentage due to the fallback support.
+ */
+ childrenMayBecomeUndefined = true;
+ dirtyChildren = getInvalidSizedChildren(true);
}
super.setHeight(height, unit);
+ repaintChangedChildTrees(dirtyChildren, childrenMayBecomeUndefined,
+ true);
}
public void requestRepaintAll() {