aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatti Tahvonen <matti.tahvonen@itmill.com>2008-12-08 14:15:24 +0000
committerMatti Tahvonen <matti.tahvonen@itmill.com>2008-12-08 14:15:24 +0000
commit53a12f615ad79a7c6c478ed51fabaaaef75037ab (patch)
tree6d7ac52bb49a074c0459cc81ad2f43639dae0e1b
parent6ca7337c6d09f03e54f090030f25d9ec1ffdf6ba (diff)
downloadvaadin-framework-53a12f615ad79a7c6c478ed51fabaaaef75037ab.tar.gz
vaadin-framework-53a12f615ad79a7c6c478ed51fabaaaef75037ab.zip
fixes #2297, #2287 and optimizes other onload event handlings.
svn changeset:6121/svn branch:trunk
-rw-r--r--src/com/itmill/toolkit/terminal/gwt/client/ICaption.java9
-rw-r--r--src/com/itmill/toolkit/terminal/gwt/client/Util.java64
-rw-r--r--src/com/itmill/toolkit/terminal/gwt/client/ui/IButton.java7
-rw-r--r--src/com/itmill/toolkit/terminal/gwt/client/ui/ICheckBox.java6
-rw-r--r--src/com/itmill/toolkit/terminal/gwt/client/ui/ICustomLayout.java80
-rw-r--r--src/com/itmill/toolkit/terminal/gwt/client/ui/IEmbedded.java8
-rw-r--r--src/com/itmill/toolkit/terminal/gwt/client/ui/IGridLayout.java5
-rw-r--r--src/com/itmill/toolkit/terminal/gwt/client/ui/ILabel.java25
-rw-r--r--src/com/itmill/toolkit/terminal/gwt/client/ui/ILink.java6
9 files changed, 138 insertions, 72 deletions
diff --git a/src/com/itmill/toolkit/terminal/gwt/client/ICaption.java b/src/com/itmill/toolkit/terminal/gwt/client/ICaption.java
index 2b99b3fb1a..f1e73ef536 100644
--- a/src/com/itmill/toolkit/terminal/gwt/client/ICaption.java
+++ b/src/com/itmill/toolkit/terminal/gwt/client/ICaption.java
@@ -4,14 +4,10 @@
package com.itmill.toolkit.terminal.gwt.client;
-import java.util.HashSet;
-import java.util.Set;
-
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.ui.HTML;
-import com.google.gwt.user.client.ui.Widget;
import com.itmill.toolkit.terminal.gwt.client.ui.Icon;
public class ICaption extends HTML {
@@ -236,11 +232,8 @@ public class ICaption extends HTML {
* The size of the icon might affect the size of the component so we
* must report the size change to the parent
*/
- Set<Widget> w = new HashSet<Widget>();
- w.add((Widget) owner);
- Util.componentSizeUpdated(w);
+ Util.notifyParentOfSizeChange(this, true);
}
-
}
public static boolean isNeeded(UIDL uidl) {
diff --git a/src/com/itmill/toolkit/terminal/gwt/client/Util.java b/src/com/itmill/toolkit/terminal/gwt/client/Util.java
index c08648089c..183a5001e0 100644
--- a/src/com/itmill/toolkit/terminal/gwt/client/Util.java
+++ b/src/com/itmill/toolkit/terminal/gwt/client/Util.java
@@ -14,6 +14,7 @@ import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.DeferredCommand;
import com.google.gwt.user.client.Element;
+import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.RootPanel;
@@ -34,6 +35,56 @@ public class Util {
debugger;
}-*/;
+ private static final int LAZY_SIZE_CHANGE_TIMEOUT = 400;
+ private static Set<Widget> latelyChangedWidgets = new HashSet<Widget>();
+
+ private static Timer lazySizeChangeTimer = new Timer() {
+ private boolean lazySizeChangeTimerScheduled = false;
+
+ public void run() {
+ componentSizeUpdated(latelyChangedWidgets);
+ latelyChangedWidgets.clear();
+ lazySizeChangeTimerScheduled = false;
+ }
+
+ @Override
+ public void schedule(int delayMillis) {
+ if (lazySizeChangeTimerScheduled) {
+ cancel();
+ } else {
+ lazySizeChangeTimerScheduled = true;
+ }
+ super.schedule(delayMillis);
+ }
+ };
+
+ /**
+ * This helper method can be called if components size have been changed
+ * outside rendering phase. It notifies components parent about the size
+ * change so it can react.
+ *
+ * When using this method, developer should consider if size changes could
+ * be notified lazily. If lazy flag is true, method will save widget and
+ * wait for a moment until it notifies parents in chunks. This may vastly
+ * optimize layout in various situation. Example: if component have a lot of
+ * images their onload events may fire "layout phase" many times in a short
+ * period.
+ *
+ * @param widget
+ * @param lazy
+ * run componentSizeUpdated lazyly
+ */
+ public static void notifyParentOfSizeChange(Widget widget, boolean lazy) {
+ if (lazy) {
+ latelyChangedWidgets.add(widget);
+ lazySizeChangeTimer.schedule(LAZY_SIZE_CHANGE_TIMEOUT);
+ } else {
+ Set<Widget> widgets = new HashSet<Widget>();
+ widgets.add(widget);
+ Util.componentSizeUpdated(widgets);
+ }
+ }
+
/**
* Called when the size of one or more widgets have changed during
* rendering. Finds parent container and notifies them of the size change.
@@ -428,13 +479,14 @@ public class Util {
RootPanel.getBodyElement().appendChild(scroller);
detectedScrollbarSize = scroller.getOffsetWidth()
- scroller.getPropertyInt("clientWidth");
-
+
// Asserting the detected value causes a problem
- // at least in Hosted Mode Browser/Linux/GWT-1.5.3, so
- // use a default if detection fails.
- if (detectedScrollbarSize == 0)
- detectedScrollbarSize = 20;
-
+ // at least in Hosted Mode Browser/Linux/GWT-1.5.3, so
+ // use a default if detection fails.
+ if (detectedScrollbarSize == 0) {
+ detectedScrollbarSize = 20;
+ }
+
RootPanel.getBodyElement().removeChild(scroller);
}
diff --git a/src/com/itmill/toolkit/terminal/gwt/client/ui/IButton.java b/src/com/itmill/toolkit/terminal/gwt/client/ui/IButton.java
index 1faeda88ec..80d5078e6f 100644
--- a/src/com/itmill/toolkit/terminal/gwt/client/ui/IButton.java
+++ b/src/com/itmill/toolkit/terminal/gwt/client/ui/IButton.java
@@ -4,8 +4,6 @@
package com.itmill.toolkit.terminal.gwt.client.ui;
-import java.util.HashSet;
-
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.Event;
@@ -128,9 +126,8 @@ public class IButton extends Button implements Paintable {
super.onBrowserEvent(event);
if (DOM.eventGetType(event) == Event.ONLOAD) {
- HashSet<Widget> set = new HashSet<Widget>();
- set.add(this);
- Util.componentSizeUpdated(set);
+ Util.notifyParentOfSizeChange(this, true);
+
} else if (DOM.eventGetType(event) == Event.ONMOUSEDOWN) {
clickPending = true;
} else if (DOM.eventGetType(event) == Event.ONMOUSEMOVE) {
diff --git a/src/com/itmill/toolkit/terminal/gwt/client/ui/ICheckBox.java b/src/com/itmill/toolkit/terminal/gwt/client/ui/ICheckBox.java
index c3b3c8d0c0..96db1ed2c2 100644
--- a/src/com/itmill/toolkit/terminal/gwt/client/ui/ICheckBox.java
+++ b/src/com/itmill/toolkit/terminal/gwt/client/ui/ICheckBox.java
@@ -4,8 +4,6 @@
package com.itmill.toolkit.terminal.gwt.client.ui;
-import java.util.HashSet;
-
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.Event;
@@ -96,9 +94,7 @@ public class ICheckBox extends com.google.gwt.user.client.ui.CheckBox implements
public void onBrowserEvent(Event event) {
super.onBrowserEvent(event);
if (event.getTypeInt() == Event.ONLOAD) {
- HashSet<Widget> set = new HashSet<Widget>();
- set.add(this);
- Util.componentSizeUpdated(set);
+ Util.notifyParentOfSizeChange(this, true);
}
if (client != null) {
client.handleTooltipEvent(event, this);
diff --git a/src/com/itmill/toolkit/terminal/gwt/client/ui/ICustomLayout.java b/src/com/itmill/toolkit/terminal/gwt/client/ui/ICustomLayout.java
index e3e2cda345..03eea1a630 100644
--- a/src/com/itmill/toolkit/terminal/gwt/client/ui/ICustomLayout.java
+++ b/src/com/itmill/toolkit/terminal/gwt/client/ui/ICustomLayout.java
@@ -9,8 +9,11 @@ import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
+import com.google.gwt.dom.client.ImageElement;
+import com.google.gwt.dom.client.NodeList;
import com.google.gwt.user.client.DOM;
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.itmill.toolkit.terminal.gwt.client.ApplicationConnection;
@@ -21,6 +24,7 @@ import com.itmill.toolkit.terminal.gwt.client.ICaptionWrapper;
import com.itmill.toolkit.terminal.gwt.client.Paintable;
import com.itmill.toolkit.terminal.gwt.client.RenderSpace;
import com.itmill.toolkit.terminal.gwt.client.UIDL;
+import com.itmill.toolkit.terminal.gwt.client.Util;
/**
* Custom Layout implements complex layout defined with HTML template.
@@ -56,6 +60,8 @@ public class ICustomLayout extends ComplexPanel implements Paintable,
/** Has the template been loaded from contents passed in UIDL **/
private boolean hasTemplateContents = false;
+ private Element elementWithNativeResizeFunction;
+
public ICustomLayout() {
setElement(DOM.createDiv());
// Clear any unwanted styling
@@ -204,16 +210,20 @@ public class ICustomLayout extends ComplexPanel implements Paintable,
// Connect body of the template to DOM
template = extractBodyAndScriptsFromTemplate(template);
- DOM.setInnerHTML(getElement(), template);
+ getElement().setInnerHTML(template);
// Remap locations to elements
locationToElement.clear();
scanForLocations(getElement());
String themeUri = client.getThemeUri();
- prefixImgSrcs(getElement(), themeUri + "/layouts/");
+ initImgElements(getElement(), themeUri + "/layouts/");
- publishResizedFunction(DOM.getFirstChild(getElement()));
+ elementWithNativeResizeFunction = DOM.getFirstChild(getElement());
+ if (elementWithNativeResizeFunction == null) {
+ elementWithNativeResizeFunction = getElement();
+ }
+ publishResizedFunction(elementWithNativeResizeFunction);
}
@@ -236,10 +246,10 @@ public class ICustomLayout extends ComplexPanel implements Paintable,
/** Collect locations from template */
private void scanForLocations(Element elem) {
- final String location = getLocation(elem);
- if (location != null) {
+ final String location = elem.getAttribute("location");
+ if (!"".equals(location)) {
locationToElement.put(location, elem);
- DOM.setInnerHTML(elem, "");
+ elem.setInnerHTML("");
} else {
final int len = DOM.getChildCount(elem);
for (int i = 0; i < len; i++) {
@@ -248,12 +258,6 @@ public class ICustomLayout extends ComplexPanel implements Paintable,
}
}
- /** Get the location attribute for given element */
- private static native String getLocation(Element elem)
- /*-{
- return elem.getAttribute("location");
- }-*/;
-
/** Evaluate given script in browser document */
private static native void eval(String script)
/*-{
@@ -264,25 +268,28 @@ public class ICustomLayout extends ComplexPanel implements Paintable,
}
}-*/;
- /** Prefix all img tag srcs with given prefix. */
- private static native void prefixImgSrcs(Element e, String srcPrefix)
- /*-{
- try {
- var divs = e.getElementsByTagName("img");
- var base = "" + $doc.location;
- var l = base.length-1;
- while (l >= 0 && base.charAt(l) != "/") l--;
- base = base.substring(0,l+1);
- for (var i = 0; i < divs.length; i++) {
- var div = divs[i];
- var src = div.getAttribute("src");
- if (src.indexOf("/")==0 || src.match(/\w+:\/\//)) {
- continue;
- }
- div.setAttribute("src",srcPrefix + src);
- }
- } catch (e) { alert(e + " " + srcPrefix);}
- }-*/;
+ /**
+ * Img elements needs some special handling in custom layout
+ *
+ * Prefixes img tag srcs with given prefix, if it has a relative uri.
+ *
+ * Img elements will also get their onload events sunk to notify paren of
+ * possible size change.
+ *
+ */
+ private static void initImgElements(Element e, String srcPrefix) {
+ NodeList<com.google.gwt.dom.client.Element> nodeList = e
+ .getElementsByTagName("IMG");
+ for (int i = 0; i < nodeList.getLength(); i++) {
+ com.google.gwt.dom.client.ImageElement img = (ImageElement) nodeList
+ .getItem(i);
+ String src = img.getSrc();
+ if (!(src.startsWith("/") || src.contains("://"))) {
+ img.setSrc(srcPrefix + src);
+ }
+ DOM.sinkEvents((Element) img.cast(), Event.ONLOAD);
+ }
+ }
/**
* Extract body part and script tags from raw html-template.
@@ -436,7 +443,7 @@ public class ICustomLayout extends ComplexPanel implements Paintable,
@Override
public void onDetach() {
super.onDetach();
- detachResizedFunction(DOM.getFirstChild(getElement()));
+ detachResizedFunction(elementWithNativeResizeFunction);
}
private native void detachResizedFunction(Element element)
@@ -491,4 +498,13 @@ public class ICustomLayout extends ComplexPanel implements Paintable,
return new RenderSpace(pe.getOffsetWidth(), pe.getOffsetHeight(), true);
}
+ @Override
+ public void onBrowserEvent(Event event) {
+ super.onBrowserEvent(event);
+ if (event.getTypeInt() == Event.ONLOAD) {
+ Util.notifyParentOfSizeChange(this, true);
+ event.cancelBubble(true);
+ }
+ }
+
}
diff --git a/src/com/itmill/toolkit/terminal/gwt/client/ui/IEmbedded.java b/src/com/itmill/toolkit/terminal/gwt/client/ui/IEmbedded.java
index 883a75c333..5598552dbb 100644
--- a/src/com/itmill/toolkit/terminal/gwt/client/ui/IEmbedded.java
+++ b/src/com/itmill/toolkit/terminal/gwt/client/ui/IEmbedded.java
@@ -4,14 +4,10 @@
package com.itmill.toolkit.terminal.gwt.client.ui;
-import java.util.HashSet;
-import java.util.Set;
-
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.ui.HTML;
-import com.google.gwt.user.client.ui.Widget;
import com.itmill.toolkit.terminal.gwt.client.ApplicationConnection;
import com.itmill.toolkit.terminal.gwt.client.Paintable;
import com.itmill.toolkit.terminal.gwt.client.UIDL;
@@ -137,9 +133,7 @@ public class IEmbedded extends HTML implements Paintable {
public void onBrowserEvent(Event event) {
super.onBrowserEvent(event);
if (DOM.eventGetType(event) == Event.ONLOAD) {
- Set<Widget> w = new HashSet<Widget>();
- w.add(this);
- Util.componentSizeUpdated(w);
+ Util.notifyParentOfSizeChange(this, true);
}
}
}
diff --git a/src/com/itmill/toolkit/terminal/gwt/client/ui/IGridLayout.java b/src/com/itmill/toolkit/terminal/gwt/client/ui/IGridLayout.java
index b4c2f862ef..e135c30b29 100644
--- a/src/com/itmill/toolkit/terminal/gwt/client/ui/IGridLayout.java
+++ b/src/com/itmill/toolkit/terminal/gwt/client/ui/IGridLayout.java
@@ -327,11 +327,8 @@ public class IGridLayout extends SimplePanel implements Paintable, Container {
client.handleComponentRelativeSize((Widget) c);
}
if (heightChanged && "".equals(height)) {
- Set<Widget> s = new HashSet<Widget>();
- s.add(this);
- Util.componentSizeUpdated(s);
+ Util.notifyParentOfSizeChange(this, false);
}
-
}
}
}
diff --git a/src/com/itmill/toolkit/terminal/gwt/client/ui/ILabel.java b/src/com/itmill/toolkit/terminal/gwt/client/ui/ILabel.java
index 1336578fb7..77addf8323 100644
--- a/src/com/itmill/toolkit/terminal/gwt/client/ui/ILabel.java
+++ b/src/com/itmill/toolkit/terminal/gwt/client/ui/ILabel.java
@@ -4,6 +4,9 @@
package com.itmill.toolkit.terminal.gwt.client.ui;
+import com.google.gwt.dom.client.Element;
+import com.google.gwt.dom.client.NodeList;
+import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.ui.HTML;
import com.itmill.toolkit.terminal.gwt.client.ApplicationConnection;
@@ -33,6 +36,11 @@ public class ILabel extends HTML implements Paintable {
public void onBrowserEvent(Event event) {
super.onBrowserEvent(event);
+ if (event.getTypeInt() == Event.ONLOAD) {
+ Util.notifyParentOfSizeChange(this, true);
+ event.cancelBubble(true);
+ return;
+ }
if (client != null) {
client.handleTooltipEvent(event, this);
}
@@ -46,6 +54,8 @@ public class ILabel extends HTML implements Paintable {
this.client = client;
+ boolean sinkOnloads = false;
+
final String mode = uidl.getStringAttribute("mode");
if (mode == null || "text".equals(mode)) {
setText(uidl.getChildString(0));
@@ -55,13 +65,28 @@ public class ILabel extends HTML implements Paintable {
setHTML(uidl.getChildrenAsXML());
} else if ("xhtml".equals(mode)) {
setHTML(uidl.getChildUIDL(0).getChildUIDL(0).getChildString(0));
+ sinkOnloads = true;
} else if ("xml".equals(mode)) {
setHTML(uidl.getChildUIDL(0).getChildString(0));
} else if ("raw".equals(mode)) {
setHTML(uidl.getChildUIDL(0).getChildString(0));
+ sinkOnloads = true;
} else {
setText("");
}
+ if (sinkOnloads) {
+ sinkOnloadsForContainedImgs();
+ }
+ }
+
+ private void sinkOnloadsForContainedImgs() {
+ NodeList<Element> images = getElement().getElementsByTagName("img");
+ for (int i = 0; i < images.getLength(); i++) {
+ Element img = images.getItem(i);
+ DOM.sinkEvents((com.google.gwt.user.client.Element) img,
+ Event.ONLOAD);
+ }
+
}
@Override
diff --git a/src/com/itmill/toolkit/terminal/gwt/client/ui/ILink.java b/src/com/itmill/toolkit/terminal/gwt/client/ui/ILink.java
index 80154fb9d0..4e5f5ee34c 100644
--- a/src/com/itmill/toolkit/terminal/gwt/client/ui/ILink.java
+++ b/src/com/itmill/toolkit/terminal/gwt/client/ui/ILink.java
@@ -4,8 +4,6 @@
package com.itmill.toolkit.terminal.gwt.client.ui;
-import java.util.HashSet;
-
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.Event;
@@ -164,9 +162,7 @@ public class ILink extends HTML implements Paintable, ClickListener {
public void onBrowserEvent(Event event) {
final Element target = DOM.eventGetTarget(event);
if (event.getTypeInt() == Event.ONLOAD) {
- HashSet<Widget> set = new HashSet<Widget>();
- set.add(this);
- Util.componentSizeUpdated(set);
+ Util.notifyParentOfSizeChange(this, true);
}
if (client != null) {
client.handleTooltipEvent(event, this);