From 8231bc935b39eca35415fdb782ed9189b1cfdfa0 Mon Sep 17 00:00:00 2001 From: Matti Tahvonen Date: Tue, 15 Jun 2010 12:38:24 +0000 Subject: refining code splitting + adding documentation. Monolithic client side is now default (6.3 style), but the package includes other generator strategies that can be thrown in for custom requirements. svn changeset:13669/svn branch:6.4 --- .../vaadin/terminal/gwt/DefaultWidgetSet.gwt.xml | 2 +- src/com/vaadin/terminal/gwt/client/WidgetSet.java | 2 +- .../widgetsetutils/CustomWidgetMapGenerator.java | 83 ++++++++++++++++++++++ .../widgetsetutils/EagerWidgetMapGenerator.java | 28 ++++++++ .../gwt/widgetsetutils/LazyWidgetMapGenerator.java | 23 ++++++ .../gwt/widgetsetutils/WidgetMapGenerator.java | 60 +++++++++++++++- src/com/vaadin/ui/ClientWidget.java | 52 ++++++++------ tests/src/com/vaadin/tests/dd/DDTest6.java | 3 +- 8 files changed, 227 insertions(+), 26 deletions(-) create mode 100644 src/com/vaadin/terminal/gwt/widgetsetutils/CustomWidgetMapGenerator.java create mode 100644 src/com/vaadin/terminal/gwt/widgetsetutils/EagerWidgetMapGenerator.java create mode 100644 src/com/vaadin/terminal/gwt/widgetsetutils/LazyWidgetMapGenerator.java diff --git a/src/com/vaadin/terminal/gwt/DefaultWidgetSet.gwt.xml b/src/com/vaadin/terminal/gwt/DefaultWidgetSet.gwt.xml index 1413377717..c7809cfffe 100644 --- a/src/com/vaadin/terminal/gwt/DefaultWidgetSet.gwt.xml +++ b/src/com/vaadin/terminal/gwt/DefaultWidgetSet.gwt.xml @@ -30,7 +30,7 @@ + class="com.vaadin.terminal.gwt.widgetsetutils.EagerWidgetMapGenerator"> diff --git a/src/com/vaadin/terminal/gwt/client/WidgetSet.java b/src/com/vaadin/terminal/gwt/client/WidgetSet.java index d5375114b5..33638b54f3 100644 --- a/src/com/vaadin/terminal/gwt/client/WidgetSet.java +++ b/src/com/vaadin/terminal/gwt/client/WidgetSet.java @@ -96,7 +96,7 @@ public class WidgetSet { return VWindow.class; } else if (widgetClass == VFilterSelect.class) { if (uidl.hasAttribute("type")) { - // TODO check if all type checks are really neede + // TODO check if all type checks are really needed final String type = uidl.getStringAttribute("type").intern(); if (type == "twincol") { return VTwinColSelect.class; diff --git a/src/com/vaadin/terminal/gwt/widgetsetutils/CustomWidgetMapGenerator.java b/src/com/vaadin/terminal/gwt/widgetsetutils/CustomWidgetMapGenerator.java new file mode 100644 index 0000000000..e67a429ee3 --- /dev/null +++ b/src/com/vaadin/terminal/gwt/widgetsetutils/CustomWidgetMapGenerator.java @@ -0,0 +1,83 @@ +/* +@ITMillApache2LicenseForJavaFiles@ + */ +package com.vaadin.terminal.gwt.widgetsetutils; + +import java.util.Collection; +import java.util.HashSet; + +import com.vaadin.terminal.Paintable; +import com.vaadin.ui.ClientWidget; +import com.vaadin.ui.ClientWidget.LoadStyle; + +/** + * An abstract helper class that can be used to easily build a widgetset with + * customized load styles for each components. In three abstract methods one can + * override the default values given in {@link ClientWidget} annotations. + * + * @see WidgetMapGenerator + * + */ +public abstract class CustomWidgetMapGenerator extends WidgetMapGenerator { + + private Collection> eagerPaintables = new HashSet>(); + private Collection> lazyPaintables = new HashSet>(); + private Collection> deferredPaintables = new HashSet>(); + + @Override + protected LoadStyle getLoadStyle(Class paintableType) { + if (eagerPaintables == null) { + init(); + } + if (eagerPaintables.contains(paintableType)) { + return LoadStyle.EAGER; + } + if (lazyPaintables.contains(paintableType)) { + return LoadStyle.LAZY; + } + if (deferredPaintables.contains(paintableType)) { + return LoadStyle.DEFERRED; + } + return super.getLoadStyle(paintableType); + } + + private void init() { + Class[] eagerComponents = getEagerComponents(); + if (eagerComponents != null) { + for (Class class1 : eagerComponents) { + eagerPaintables.add(class1); + } + } + Class[] lazyComponents = getEagerComponents(); + if (lazyComponents != null) { + for (Class class1 : lazyComponents) { + lazyPaintables.add(class1); + } + } + Class[] deferredComponents = getEagerComponents(); + if (deferredComponents != null) { + for (Class class1 : deferredComponents) { + deferredPaintables.add(class1); + } + } + } + + /** + * @return an array of components whose load style should be overridden to + * {@link LoadStyle#EAGER} + */ + protected abstract Class[] getEagerComponents(); + + /** + * @return an array of components whose load style should be overridden to + * {@link LoadStyle#LAZY} + */ + protected abstract Class[] getLazyComponents(); + + /** + * @return an array of components whose load style should be overridden to + * {@link LoadStyle#DEFERRED} + */ + protected abstract Class[] getDeferredComponents(); + +} diff --git a/src/com/vaadin/terminal/gwt/widgetsetutils/EagerWidgetMapGenerator.java b/src/com/vaadin/terminal/gwt/widgetsetutils/EagerWidgetMapGenerator.java new file mode 100644 index 0000000000..a5d1963a5f --- /dev/null +++ b/src/com/vaadin/terminal/gwt/widgetsetutils/EagerWidgetMapGenerator.java @@ -0,0 +1,28 @@ +/* +@ITMillApache2LicenseForJavaFiles@ + */ +package com.vaadin.terminal.gwt.widgetsetutils; + +import com.vaadin.terminal.Paintable; +import com.vaadin.ui.ClientWidget.LoadStyle; + +/** + * WidgetMap generator that builds a widgetset that packs all included widgets + * into a single JavaScript file loaded at application initialization. Initially + * loaded data will be relatively large, but minimal amount of server requests + * will be done. + *

+ * This is the default generator in version 6.4 and produces similar type of + * widgetset as in previous versions of Vaadin. To activate "code splitting", + * use the {@link WidgetMapGenerator} instead, that loads most components + * deferred. + * + * @see WidgetMapGenerator + * + */ +public class EagerWidgetMapGenerator extends WidgetMapGenerator { + @Override + protected LoadStyle getLoadStyle(Class paintableType) { + return LoadStyle.EAGER; + } +} diff --git a/src/com/vaadin/terminal/gwt/widgetsetutils/LazyWidgetMapGenerator.java b/src/com/vaadin/terminal/gwt/widgetsetutils/LazyWidgetMapGenerator.java new file mode 100644 index 0000000000..b3fd921e2f --- /dev/null +++ b/src/com/vaadin/terminal/gwt/widgetsetutils/LazyWidgetMapGenerator.java @@ -0,0 +1,23 @@ +/* +@ITMillApache2LicenseForJavaFiles@ + */ +package com.vaadin.terminal.gwt.widgetsetutils; + +import com.vaadin.terminal.Paintable; +import com.vaadin.ui.ClientWidget.LoadStyle; + +/** + * WidgetMap generator that builds a widgetset that optimizes the transferred + * data. Widgets are loaded only when used if the widgetset is built with this + * generator. + * + * @see WidgetMapGenerator + * + */ +public class LazyWidgetMapGenerator extends WidgetMapGenerator { + @Override + protected LoadStyle getLoadStyle(Class paintableType) { + return LoadStyle.LAZY; + } + +} diff --git a/src/com/vaadin/terminal/gwt/widgetsetutils/WidgetMapGenerator.java b/src/com/vaadin/terminal/gwt/widgetsetutils/WidgetMapGenerator.java index 4da8c0a925..b4e5df316c 100644 --- a/src/com/vaadin/terminal/gwt/widgetsetutils/WidgetMapGenerator.java +++ b/src/com/vaadin/terminal/gwt/widgetsetutils/WidgetMapGenerator.java @@ -4,6 +4,7 @@ package com.vaadin.terminal.gwt.widgetsetutils; import java.io.PrintWriter; +import java.util.ArrayList; import java.util.Collection; import java.util.Date; import java.util.Iterator; @@ -25,8 +26,43 @@ import com.vaadin.ui.ClientWidget; import com.vaadin.ui.ClientWidget.LoadStyle; /** - * GWT generator to build WidgetMapImpl dynamically based on - * {@link ClientWidget} annotations available in workspace. + * WidgetMapGenerator's are GWT generator to build WidgetMapImpl dynamically + * based on {@link ClientWidget} annotations available in workspace. By + * modifying the generator it is possible to do some fine tuning for the + * generated widgetset (aka client side engine). The components to be included + * in the client side engine can modified be overriding + * {@link #getUsedPaintables()}. + *

+ * The generator also decides how the client side component implementations are + * loaded to the browser. The default generator is + * {@link EagerWidgetMapGenerator} that builds a monolithic client side engine + * that loads all widget implementation on application initialization. This has + * been the only option until Vaadin 6.4. + *

+ * This generator uses the loadStyle hints from the {@link ClientWidget} + * annotations. Depending on the {@link LoadStyle} used, the widget may be + * included in the initially loaded JavaScript, loaded when the application has + * started and there is no communication to server or lazy loaded when the + * implementation is absolutely needed. + *

+ * The GWT module description file of the widgetset ( + * ...Widgetset.gwt.xml) can be used to define the + * WidgetMapGenarator. An example that defines this generator to be used: + * + *

+ * 
+ * <generate-with
+ *           class="com.vaadin.terminal.gwt.widgetsetutils.MyWidgetMapGenerator">
+ *          <when-type-is class="com.vaadin.terminal.gwt.client.WidgetMap" />
+ * </generate-with>
+ * 
+ * 
+ * 
+ * + *

+ * Vaadin package also includes {@link LazyWidgetMapGenerator}, which is a good + * option if the transferred data should be minimized, and + * {@link CustomWidgetMapGenerator} for easy overriding of loading strategies. * */ public class WidgetMapGenerator extends Generator { @@ -195,6 +231,7 @@ public class WidgetMapGenerator extends Generator { sourceWriter.println("if(!instmap.containsKey(classType)){"); boolean first = true; + ArrayList> lazyLoadedWidgets = new ArrayList>(); for (Class class1 : paintablesHavingWidgetAnnotation) { ClientWidget annotation = class1.getAnnotation(ClientWidget.class); Class clientClass = annotation @@ -224,6 +261,7 @@ public class WidgetMapGenerator extends Generator { + clientClass.getName() + ".class," + instantiator + ");}});\n"); + lazyLoadedWidgets.add(class1); if (loadStyle == LoadStyle.DEFERRED) { deferredWidgets.add(class1); @@ -262,6 +300,24 @@ public class WidgetMapGenerator extends Generator { sourceWriter.println("};"); sourceWriter.println("}"); + + // in constructor add a "thread" that lazyly loads lazy loaded widgets + // if communication to server idles + + // TODO an array of lazy loaded widgets + + // TODO an index of last ensured widget in array + + sourceWriter + .println("public Paintable instantiate(Class classType) {"); + sourceWriter.indent(); + sourceWriter + .println("Paintable p = super.instantiate(classType); if(p!= null) return p;"); + sourceWriter.println("return instmap.get(classType).get();"); + + sourceWriter.outdent(); + sourceWriter.println("}"); + } /** diff --git a/src/com/vaadin/ui/ClientWidget.java b/src/com/vaadin/ui/ClientWidget.java index 0848309b31..1bfe58da66 100644 --- a/src/com/vaadin/ui/ClientWidget.java +++ b/src/com/vaadin/ui/ClientWidget.java @@ -12,6 +12,9 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import com.vaadin.terminal.gwt.client.Paintable; +import com.vaadin.terminal.gwt.widgetsetutils.CustomWidgetMapGenerator; +import com.vaadin.terminal.gwt.widgetsetutils.EagerWidgetMapGenerator; +import com.vaadin.terminal.gwt.widgetsetutils.LazyWidgetMapGenerator; import com.vaadin.terminal.gwt.widgetsetutils.WidgetMapGenerator; /** @@ -21,10 +24,9 @@ import com.vaadin.terminal.gwt.widgetsetutils.WidgetMapGenerator; * With this annotation server side Vaadin component is marked to have a client * side counterpart. The value of the annotation is the class of client side * implementation. - * *

* Note, even though client side implementation is needed during development, - * one may safely remove them from classpath of the production server. + * one may safely remove them from the classpath of the production server. * * @since 6.2 */ @@ -37,33 +39,41 @@ public @interface ClientWidget { Class value(); /** - * TODO rewrite for EAGER, DEFERRED, LAZY - * - * The lazy loading of a widget implementation means the client side - * component is not included in the initial JavaScript application loaded - * when the application starts. Instead the implementation is loaded to the - * client when it is first needed. + * Depending on the used WidgetMap generator, these optional hints may be + * used to define how the client side components are loaded by the browser. + * The default is to eagerly load all widgets + * {@link EagerWidgetMapGenerator}, but if the {@link WidgetMapGenerator} is + * used by the widgetset, these load style hints are respected. + *

+ * Lazy loading of a widget implementation means the client side component + * is not included in the initial JavaScript application loaded when the + * application starts. Instead the implementation is loaded to the client + * when it is first needed. Lazy loaded widget can be achieved by giving + * {@link LoadStyle#LAZY} value in ClientWidget annotation. *

* Lazy loaded widgets don't stress the size and startup time of the client * side as much as eagerly loaded widgets. On the other hand there is a * slight latency when lazy loaded widgets are first used as the client side * needs to visit the server to fetch the client side implementation. *

- * In common situations the default value should be fine. If the widget - * implementation commonly used and often on first view it is better set - * lazy loading off for it. Also if the component implementation is really - * thing, it may by justified to make the widget implementation eagerly - * loaded. + * The {@link LoadStyle#DEFERRED} will also not stress the initially loaded + * JavaScript file. If this load style is defined, the widget implementation + * is preemptively loaded to the browser after the application is started + * and the communication to server idles. This load style kind of combines + * the best of both worlds. *

- * Tunings to widget loading can also be made by overriding - * {@link WidgetMapGenerator} in GWT module. Tunings might be helpful if the - * end users have slow connections and especially if they have high latency - * in their network. + * Fine tunings to widget loading can also be made by overriding + * {@link WidgetMapGenerator} in the GWT module. Tunings might be helpful if + * the end users have slow connections and especially if they have high + * latency in their network. The {@link CustomWidgetMapGenerator} is an + * abstract generator implementation for easy customization. Vaadin package + * also includes {@link LazyWidgetMapGenerator} that makes as many widgets + * lazily loaded as possible. + * + * @since 6.4 * - * @return if true (default), the GWT code generator will make the client - * side implementation lazy loaded. Displaying it first time on the - * screen slightly increases, but widgets implementation does not - * stress the initialization of the client side engine. + * @return the hint for the widget set generator how the client side + * implementation should be loaded to the browser */ LoadStyle loadStyle() default LoadStyle.DEFERRED; diff --git a/tests/src/com/vaadin/tests/dd/DDTest6.java b/tests/src/com/vaadin/tests/dd/DDTest6.java index 74a7e39db1..39e5a3e355 100644 --- a/tests/src/com/vaadin/tests/dd/DDTest6.java +++ b/tests/src/com/vaadin/tests/dd/DDTest6.java @@ -24,8 +24,8 @@ import com.vaadin.event.dd.DragAndDropEvent; import com.vaadin.event.dd.DropHandler; import com.vaadin.event.dd.acceptcriteria.AcceptAll; import com.vaadin.event.dd.acceptcriteria.AcceptCriterion; -import com.vaadin.event.dd.acceptcriteria.SourceIsTarget; import com.vaadin.event.dd.acceptcriteria.Not; +import com.vaadin.event.dd.acceptcriteria.SourceIsTarget; import com.vaadin.terminal.ApplicationResource; import com.vaadin.terminal.Resource; import com.vaadin.terminal.StreamResource; @@ -371,6 +371,7 @@ public class DDTest6 extends TestBase { WrapperTargetDetails dropTargetDetails = (WrapperTargetDetails) dropEvent .getTargetDetails(); + MouseEventDetails mouseEvent = dropTargetDetails .getMouseEvent(); -- cgit v1.2.3