summaryrefslogtreecommitdiffstats
path: root/src/com/vaadin
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/vaadin')
-rw-r--r--src/com/vaadin/terminal/gwt/client/ApplicationConfiguration.java42
-rwxr-xr-xsrc/com/vaadin/terminal/gwt/client/ApplicationConnection.java290
-rw-r--r--src/com/vaadin/terminal/gwt/client/DefaultWidgetSet.java10
-rw-r--r--src/com/vaadin/terminal/gwt/client/WidgetMap.java4
-rw-r--r--src/com/vaadin/terminal/gwt/client/WidgetSet.java4
-rw-r--r--src/com/vaadin/terminal/gwt/widgetsetutils/WidgetMapGenerator.java102
-rw-r--r--src/com/vaadin/ui/Button.java4
-rw-r--r--src/com/vaadin/ui/ClientWidget.java31
-rw-r--r--src/com/vaadin/ui/CustomComponent.java2
-rw-r--r--src/com/vaadin/ui/HorizontalLayout.java2
-rw-r--r--src/com/vaadin/ui/Label.java2
-rw-r--r--src/com/vaadin/ui/OrderedLayout.java2
-rw-r--r--src/com/vaadin/ui/SplitPanel.java2
-rw-r--r--src/com/vaadin/ui/TextField.java2
-rw-r--r--src/com/vaadin/ui/UriFragmentUtility.java2
-rw-r--r--src/com/vaadin/ui/VerticalLayout.java2
16 files changed, 326 insertions, 177 deletions
diff --git a/src/com/vaadin/terminal/gwt/client/ApplicationConfiguration.java b/src/com/vaadin/terminal/gwt/client/ApplicationConfiguration.java
index bf66921235..f54032cfdb 100644
--- a/src/com/vaadin/terminal/gwt/client/ApplicationConfiguration.java
+++ b/src/com/vaadin/terminal/gwt/client/ApplicationConfiguration.java
@@ -6,11 +6,12 @@ package com.vaadin.terminal.gwt.client;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
+import java.util.LinkedList;
import java.util.List;
-import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.core.client.JsArrayString;
+import com.google.gwt.user.client.Command;
import com.vaadin.terminal.gwt.client.ui.VUnknownComponent;
public class ApplicationConfiguration {
@@ -37,6 +38,11 @@ public class ApplicationConfiguration {
private String windowId;
+ // TODO consider to make this hashmap per application
+ LinkedList<Command> callbacks = new LinkedList<Command>();
+
+ private int widgetsLoading;
+
private static ArrayList<ApplicationConnection> unstartedApplications = new ArrayList<ApplicationConnection>();
private static ArrayList<ApplicationConnection> runningApplications = new ArrayList<ApplicationConnection>();
@@ -146,11 +152,6 @@ public class ApplicationConfiguration {
* the widgetset that is running the apps
*/
public static void initConfigurations(WidgetSet widgetset) {
- String wsname = widgetset.getClass().getName();
- String module = GWT.getModuleName();
- int lastdot = module.lastIndexOf(".");
- String base = module.substring(0, lastdot);
- String simpleName = module.substring(lastdot + 1);
if (initedWidgetSet != null) {
// Multiple widgetsets inited; can happen with custom WS + entry
@@ -241,7 +242,7 @@ public class ApplicationConfiguration {
for (int i = 0; i < keyArray.length(); i++) {
String key = keyArray.get(i).intern();
int value = valueMap.getInt(key);
- classes[value] = widgetSet.getImplementationByClassName(key);
+ classes[value] = widgetSet.getImplementationByClassName(key, this);
if (classes[value] == VUnknownComponent.class) {
if (unknownComponents == null) {
unknownComponents = new HashMap<String, String>();
@@ -267,4 +268,31 @@ public class ApplicationConfiguration {
}
return null;
}
+
+ /**
+ *
+ * @param c
+ */
+ void runWhenWidgetsLoaded(Command c) {
+ if (widgetsLoading == 0) {
+ c.execute();
+ } else {
+ callbacks.add(c);
+ }
+ }
+
+ void widgetLoadStart() {
+ widgetsLoading++;
+ }
+
+ void widgetLoaded() {
+ widgetsLoading--;
+ if (widgetsLoading == 0 && !callbacks.isEmpty()) {
+ for (Command cmd : callbacks) {
+ cmd.execute();
+ }
+ callbacks.clear();
+ }
+
+ }
}
diff --git a/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java b/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java
index 9d649bcd99..449971ac39 100755
--- a/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java
+++ b/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java
@@ -670,10 +670,10 @@ public class ApplicationConnection {
private void handleReceivedJSONMessage(Response response) {
final Date start = new Date();
- String jsonText = response.getText();
// for(;;);[realjson]
- jsonText = jsonText.substring(9, jsonText.length() - 1);
- ValueMap json;
+ final String jsonText = response.getText().substring(9,
+ response.getText().length() - 1);
+ final ValueMap json;
try {
json = parseJSONResponse(jsonText);
} catch (final Exception e) {
@@ -714,159 +714,181 @@ public class ApplicationConnection {
json.getValueMap("typeMappings"), widgetSet);
}
- if (json.containsKey("locales")) {
- // Store locale data
- JsArray<ValueMap> valueMapArray = json
- .getJSValueMapArray("locales");
- LocaleService.addLocales(valueMapArray);
- }
+ Command c = new Command() {
+ public void execute() {
- ValueMap meta = null;
- if (json.containsKey("meta")) {
- meta = json.getValueMap("meta");
- if (meta.containsKey("repaintAll")) {
- view.clear();
- idToPaintableDetail.clear();
- if (meta.containsKey("invalidLayouts")) {
- validatingLayouts = true;
- zeroWidthComponents = new HashSet<Paintable>();
- zeroHeightComponents = new HashSet<Paintable>();
+ if (json.containsKey("locales")) {
+ // Store locale data
+ JsArray<ValueMap> valueMapArray = json
+ .getJSValueMapArray("locales");
+ LocaleService.addLocales(valueMapArray);
}
- }
- if (meta.containsKey("timedRedirect")) {
- final ValueMap timedRedirect = meta
- .getValueMap("timedRedirect");
- redirectTimer = new Timer() {
- @Override
- public void run() {
- redirect(timedRedirect.getString("url"));
+
+ ValueMap meta = null;
+ if (json.containsKey("meta")) {
+ meta = json.getValueMap("meta");
+ if (meta.containsKey("repaintAll")) {
+ view.clear();
+ idToPaintableDetail.clear();
+ if (meta.containsKey("invalidLayouts")) {
+ validatingLayouts = true;
+ zeroWidthComponents = new HashSet<Paintable>();
+ zeroHeightComponents = new HashSet<Paintable>();
+ }
}
- };
- sessionExpirationInterval = timedRedirect.getInt("interval");
- }
- }
+ if (meta.containsKey("timedRedirect")) {
+ final ValueMap timedRedirect = meta
+ .getValueMap("timedRedirect");
+ redirectTimer = new Timer() {
+ @Override
+ public void run() {
+ redirect(timedRedirect.getString("url"));
+ }
+ };
+ sessionExpirationInterval = timedRedirect
+ .getInt("interval");
+ }
+ }
- if (redirectTimer != null) {
- redirectTimer.schedule(1000 * sessionExpirationInterval);
- }
+ if (redirectTimer != null) {
+ redirectTimer.schedule(1000 * sessionExpirationInterval);
+ }
- // Process changes
- JsArray<ValueMap> changes = json.getJSValueMapArray("changes");
+ // Process changes
+ JsArray<ValueMap> changes = json.getJSValueMapArray("changes");
- ArrayList<Paintable> updatedWidgets = new ArrayList<Paintable>();
- relativeSizeChanges.clear();
- componentCaptionSizeChanges.clear();
+ ArrayList<Paintable> updatedWidgets = new ArrayList<Paintable>();
+ relativeSizeChanges.clear();
+ componentCaptionSizeChanges.clear();
- int length = changes.length();
- for (int i = 0; i < length; i++) {
- try {
- final UIDL change = changes.get(i).cast();
- try {
- console.dirUIDL(change);
- } catch (final Exception e) {
- ClientExceptionHandler.displayError(e);
- // TODO: dir doesn't work in any browser although it should
- // work (works in hosted mode)
- // it partially did at some part but now broken.
- }
- final UIDL uidl = change.getChildUIDL(0);
- // TODO optimize
- final Paintable paintable = getPaintable(uidl.getId());
- if (paintable != null) {
- paintable.updateFromUIDL(uidl, this);
- // paintable may have changed during render to another
- // implementation, use the new one for updated widgets map
- updatedWidgets.add(idToPaintableDetail.get(uidl.getId())
- .getComponent());
- } else {
- if (!uidl.getTag().equals(
- configuration.getEncodedWindowTag())) {
- ClientExceptionHandler
- .displayError("Received update for "
- + uidl.getTag()
- + ", but there is no such paintable ("
- + uidl.getId() + ") rendered.");
- } else {
- view.updateFromUIDL(uidl, this);
+ int length = changes.length();
+ for (int i = 0; i < length; i++) {
+ try {
+ final UIDL change = changes.get(i).cast();
+ try {
+ console.dirUIDL(change);
+ } catch (final Exception e) {
+ ClientExceptionHandler.displayError(e);
+ // TODO: dir doesn't work in any browser although it
+ // should
+ // work (works in hosted mode)
+ // it partially did at some part but now broken.
+ }
+ final UIDL uidl = change.getChildUIDL(0);
+ // TODO optimize
+ final Paintable paintable = getPaintable(uidl.getId());
+ if (paintable != null) {
+ paintable.updateFromUIDL(uidl,
+ ApplicationConnection.this);
+ // paintable may have changed during render to
+ // another
+ // implementation, use the new one for updated
+ // widgets map
+ updatedWidgets.add(idToPaintableDetail.get(
+ uidl.getId()).getComponent());
+ } else {
+ if (!uidl.getTag().equals(
+ configuration.getEncodedWindowTag())) {
+ ClientExceptionHandler
+ .displayError("Received update for "
+ + uidl.getTag()
+ + ", but there is no such paintable ("
+ + uidl.getId() + ") rendered.");
+ } else {
+ view.updateFromUIDL(uidl,
+ ApplicationConnection.this);
+ }
+ }
+ } catch (final Throwable e) {
+ ClientExceptionHandler.displayError(e);
}
}
- } catch (final Throwable e) {
- ClientExceptionHandler.displayError(e);
- }
- }
- if (json.containsKey("dd")) {
- // response contains data for drag and drop service
- VDragAndDropManager.get().handleServerResponse(
- json.getValueMap("dd"));
- }
+ if (json.containsKey("dd")) {
+ // response contains data for drag and drop service
+ VDragAndDropManager.get().handleServerResponse(
+ json.getValueMap("dd"));
+ }
- // Check which widgets' size has been updated
- Set<Paintable> sizeUpdatedWidgets = new HashSet<Paintable>();
+ // Check which widgets' size has been updated
+ Set<Paintable> sizeUpdatedWidgets = new HashSet<Paintable>();
- updatedWidgets.addAll(relativeSizeChanges);
- sizeUpdatedWidgets.addAll(componentCaptionSizeChanges);
+ updatedWidgets.addAll(relativeSizeChanges);
+ sizeUpdatedWidgets.addAll(componentCaptionSizeChanges);
- for (Paintable paintable : updatedWidgets) {
- ComponentDetail detail = idToPaintableDetail.get(getPid(paintable));
- Widget widget = (Widget) paintable;
- Size oldSize = detail.getOffsetSize();
- Size newSize = new Size(widget.getOffsetWidth(), widget
- .getOffsetHeight());
+ for (Paintable paintable : updatedWidgets) {
+ ComponentDetail detail = idToPaintableDetail
+ .get(getPid(paintable));
+ Widget widget = (Widget) paintable;
+ Size oldSize = detail.getOffsetSize();
+ Size newSize = new Size(widget.getOffsetWidth(), widget
+ .getOffsetHeight());
- if (oldSize == null || !oldSize.equals(newSize)) {
- sizeUpdatedWidgets.add(paintable);
- detail.setOffsetSize(newSize);
- }
+ if (oldSize == null || !oldSize.equals(newSize)) {
+ sizeUpdatedWidgets.add(paintable);
+ detail.setOffsetSize(newSize);
+ }
- }
+ }
- Util.componentSizeUpdated(sizeUpdatedWidgets);
+ Util.componentSizeUpdated(sizeUpdatedWidgets);
- if (meta != null) {
- if (meta.containsKey("appError")) {
- ValueMap error = meta.getValueMap("appError");
- String html = "";
- if (error.containsKey("caption")
- && error.getString("caption") != null) {
- html += "<h1>" + error.getAsString("caption") + "</h1>";
- }
- if (error.containsKey("message")
- && error.getString("message") != null) {
- html += "<p>" + error.getAsString("message") + "</p>";
- }
- String url = null;
- if (error.containsKey("url")) {
- url = error.getString("url");
- }
+ if (meta != null) {
+ if (meta.containsKey("appError")) {
+ ValueMap error = meta.getValueMap("appError");
+ String html = "";
+ if (error.containsKey("caption")
+ && error.getString("caption") != null) {
+ html += "<h1>" + error.getAsString("caption")
+ + "</h1>";
+ }
+ if (error.containsKey("message")
+ && error.getString("message") != null) {
+ html += "<p>" + error.getAsString("message")
+ + "</p>";
+ }
+ String url = null;
+ if (error.containsKey("url")) {
+ url = error.getString("url");
+ }
- if (html.length() != 0) {
- /* 45 min */
- VNotification n = new VNotification(1000 * 60 * 45);
- n.addEventListener(new NotificationRedirect(url));
- n.show(html, VNotification.CENTERED_TOP,
- VNotification.STYLE_SYSTEM);
- } else {
- redirect(url);
+ if (html.length() != 0) {
+ /* 45 min */
+ VNotification n = new VNotification(1000 * 60 * 45);
+ n.addEventListener(new NotificationRedirect(url));
+ n.show(html, VNotification.CENTERED_TOP,
+ VNotification.STYLE_SYSTEM);
+ } else {
+ redirect(url);
+ }
+ applicationRunning = false;
+ }
+ if (validatingLayouts) {
+ getConsole().printLayoutProblems(meta,
+ ApplicationConnection.this,
+ zeroHeightComponents, zeroWidthComponents);
+ zeroHeightComponents = null;
+ zeroWidthComponents = null;
+ validatingLayouts = false;
+
+ }
}
- applicationRunning = false;
- }
- if (validatingLayouts) {
- getConsole().printLayoutProblems(meta, this,
- zeroHeightComponents, zeroWidthComponents);
- zeroHeightComponents = null;
- zeroWidthComponents = null;
- validatingLayouts = false;
- }
- }
+ // TODO build profiling for widget impl loading time
+
+ final long prosessingTime = (new Date().getTime())
+ - start.getTime();
+ console.log(" Processing time was "
+ + String.valueOf(prosessingTime) + "ms for "
+ + jsonText.length() + " characters of JSON");
+ console.log("Referenced paintables: "
+ + idToPaintableDetail.size());
- final long prosessingTime = (new Date().getTime()) - start.getTime();
- console.log(" Processing time was " + String.valueOf(prosessingTime)
- + "ms for " + jsonText.length() + " characters of JSON");
- console.log("Referenced paintables: " + idToPaintableDetail.size());
+ endRequest();
- endRequest();
+ }
+ };
+ configuration.runWhenWidgetsLoaded(c);
}
/**
diff --git a/src/com/vaadin/terminal/gwt/client/DefaultWidgetSet.java b/src/com/vaadin/terminal/gwt/client/DefaultWidgetSet.java
index c34e5d8bb3..ae6001c1aa 100644
--- a/src/com/vaadin/terminal/gwt/client/DefaultWidgetSet.java
+++ b/src/com/vaadin/terminal/gwt/client/DefaultWidgetSet.java
@@ -9,7 +9,6 @@ import com.google.gwt.user.client.ui.Widget;
import com.vaadin.terminal.gwt.client.ui.VButton;
import com.vaadin.terminal.gwt.client.ui.VCheckBox;
import com.vaadin.terminal.gwt.client.ui.VDateFieldCalendar;
-import com.vaadin.terminal.gwt.client.ui.VDragAndDropWrapper;
import com.vaadin.terminal.gwt.client.ui.VFilterSelect;
import com.vaadin.terminal.gwt.client.ui.VListSelect;
import com.vaadin.terminal.gwt.client.ui.VNativeSelect;
@@ -69,7 +68,7 @@ public class DefaultWidgetSet implements WidgetSet {
Class<? extends Paintable> widgetClass = conf
.getWidgetClassByEncodedTag(tag);
- // TODO add our quirks
+ // add our historical quirks
if (widgetClass == VButton.class && uidl.hasAttribute("type")) {
return VCheckBox.class;
@@ -119,10 +118,13 @@ public class DefaultWidgetSet implements WidgetSet {
}
public Class<? extends Paintable> getImplementationByClassName(
- String fullyqualifiedName) {
+ String fullyqualifiedName,
+ ApplicationConfiguration applicationConfiguration) {
Class<? extends Paintable> implementationByServerSideClassName = map
- .getImplementationByServerSideClassName(fullyqualifiedName);
+ .getImplementationByServerSideClassName(fullyqualifiedName,
+ applicationConfiguration);
return implementationByServerSideClassName;
}
+
}
diff --git a/src/com/vaadin/terminal/gwt/client/WidgetMap.java b/src/com/vaadin/terminal/gwt/client/WidgetMap.java
index d9df64b8d0..c6e50b0f51 100644
--- a/src/com/vaadin/terminal/gwt/client/WidgetMap.java
+++ b/src/com/vaadin/terminal/gwt/client/WidgetMap.java
@@ -12,6 +12,7 @@ import com.vaadin.terminal.gwt.client.ui.VWindow;
public abstract class WidgetMap {
public Paintable instantiate(Class<? extends Paintable> classType) {
+
/*
* Yes, this (including the generated) may look very odd code, but due
* the nature of GWT, we cannot do this with reflect. Luckily this is
@@ -36,6 +37,7 @@ public abstract class WidgetMap {
}
public abstract Class<? extends Paintable> getImplementationByServerSideClassName(
- String fullyqualifiedName);
+ String fullyqualifiedName,
+ ApplicationConfiguration applicationConfiguration);
}
diff --git a/src/com/vaadin/terminal/gwt/client/WidgetSet.java b/src/com/vaadin/terminal/gwt/client/WidgetSet.java
index 832e985397..f2a960b950 100644
--- a/src/com/vaadin/terminal/gwt/client/WidgetSet.java
+++ b/src/com/vaadin/terminal/gwt/client/WidgetSet.java
@@ -42,9 +42,11 @@ public interface WidgetSet extends EntryPoint {
* qualified name.
*
* @param fullyQualifiedName
+ * @param applicationConfiguration
* @return
*/
public Class<? extends Paintable> getImplementationByClassName(
- String fullyQualifiedName);
+ String fullyQualifiedName,
+ ApplicationConfiguration applicationConfiguration);
}
diff --git a/src/com/vaadin/terminal/gwt/widgetsetutils/WidgetMapGenerator.java b/src/com/vaadin/terminal/gwt/widgetsetutils/WidgetMapGenerator.java
index abbf0fad0c..72bfdd1fd8 100644
--- a/src/com/vaadin/terminal/gwt/widgetsetutils/WidgetMapGenerator.java
+++ b/src/com/vaadin/terminal/gwt/widgetsetutils/WidgetMapGenerator.java
@@ -78,6 +78,8 @@ public class WidgetMapGenerator extends Generator {
ClassSourceFileComposerFactory composer = null;
composer = new ClassSourceFileComposerFactory(packageName, className);
composer.addImport("com.google.gwt.core.client.GWT");
+ composer.addImport("java.util.HashMap");
+ composer.addImport("com.google.gwt.core.client.RunAsyncCallback");
composer.setSuperclass("com.vaadin.terminal.gwt.client.WidgetMap");
SourceWriter sourceWriter = composer.createSourceWriter(context,
printWriter);
@@ -145,12 +147,10 @@ public class WidgetMapGenerator extends Generator {
}
/**
- * This method is protected to allow easy creation of optimized widgetsets.
- * <p>
- * TODO we need some sort of mechanism to easily exclude/include components
- * from widgetset. Properties in gwt.xml is one option. Now only possible by
- * extending this class, overriding getUsedPaintables() method and
- * redefining deferred binding rule.
+ * This method is protected to allow creation of optimized widgetsets. The
+ * Widgetset will contain only implementation returned by this function. If
+ * one knows which widgets are needed for the application, returning only
+ * them here will significantly optimize the size of the produced JS.
*
* @return a collections of Vaadin components that will be added to
* widgetset
@@ -159,16 +159,42 @@ public class WidgetMapGenerator extends Generator {
return ClassPathExplorer.getPaintablesHavingWidgetAnnotation();
}
+ /**
+ * Returns true if the widget for given component will be lazy loaded by the
+ * client. The default implementation reads the information from the
+ * {@link ClientWidget} annotation.
+ * <p>
+ * The method can be overridden to optimize the widget loading mechanism. If
+ * the Widgetset is wanted to be optimized for a network with a high latency
+ * or for a one with a very fast throughput, it may be good to return false
+ * for every component.
+ *
+ * @param paintableType
+ * @return true iff the widget for given component should be lazy loaded by
+ * the client side engine
+ */
+ protected boolean isLazyLoaded(Class<? extends Paintable> paintableType) {
+ ClientWidget annotation = paintableType
+ .getAnnotation(ClientWidget.class);
+ return annotation.lazyLoad();
+ }
+
private void generateInstantiatorMethod(
SourceWriter sourceWriter,
Collection<Class<? extends Paintable>> paintablesHavingWidgetAnnotation) {
+
sourceWriter
- .println("public Paintable instantiate(Class<? extends Paintable> classType) {");
- sourceWriter.indent();
+ .println("public interface Instantiator { public Paintable get();};");
+
+ // TODO detect if it would be noticably faster to instantiate with a
+ // lookup with index than with the hashmap
sourceWriter
- .println("Paintable p = super.instantiate(classType); if(p!= null) return p;");
+ .println("private HashMap<Class,Instantiator> instmap = new HashMap<Class,Instantiator>();");
+ sourceWriter
+ .println("public void ensureInstantiator(Class<? extends Paintable> classType, final ApplicationConfiguration c) {");
+ sourceWriter.println("if(!instmap.containsKey(classType)){");
for (Class<? extends Paintable> class1 : paintablesHavingWidgetAnnotation) {
ClientWidget annotation = class1.getAnnotation(ClientWidget.class);
Class<? extends com.vaadin.terminal.gwt.client.Paintable> clientClass = annotation
@@ -177,14 +203,50 @@ public class WidgetMapGenerator extends Generator {
// VView's are not instantiated by widgetset
continue;
}
- sourceWriter.print("if (");
- sourceWriter.print(clientClass.getName());
- sourceWriter.print(".class == classType) return GWT.create(");
- sourceWriter.print(clientClass.getName());
- sourceWriter.println(".class );");
- sourceWriter.print("else ");
+ sourceWriter.print("if( classType == " + clientClass.getName()
+ + ".class) {");
+
+ String instantiator = "new Instantiator() { public Paintable get(){ return GWT.create("
+ + clientClass.getName() + ".class );}}";
+
+ if (isLazyLoaded(class1)) {
+ sourceWriter
+ .print("c.widgetLoadStart();GWT.runAsync(new RunAsyncCallback() {\n"
+ + " public void onSuccess() {");
+
+ sourceWriter.print("instmap.put(");
+ sourceWriter.print(clientClass.getName());
+ sourceWriter.print(".class, ");
+ sourceWriter.print(instantiator);
+ sourceWriter.println("); c.widgetLoaded();");
+ sourceWriter
+ .print(" }\n"
+ + "\n"
+ + " public void onFailure(Throwable reason) {c.widgetLoaded();\n"
+ + "\n" + " }\n" + " });\n");
+
+ } else {
+ // widget implementation in initially loaded js script
+ sourceWriter.print("instmap.put(");
+ sourceWriter.print(clientClass.getName());
+ sourceWriter.print(".class, ");
+ sourceWriter.print(instantiator);
+ sourceWriter.print(");");
+ }
+ sourceWriter.print("}");
}
- sourceWriter.println("return null;");
+
+ sourceWriter.println("}");
+
+ sourceWriter.println("}");
+
+ sourceWriter
+ .println("public Paintable instantiate(Class<? extends Paintable> 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("}");
}
@@ -200,7 +262,7 @@ public class WidgetMapGenerator extends Generator {
Collection<Class<? extends Paintable>> paintablesHavingWidgetAnnotation) {
sourceWriter
.println("public Class<? extends Paintable> "
- + "getImplementationByServerSideClassName(String fullyQualifiedName) {");
+ + "getImplementationByServerSideClassName(String fullyQualifiedName, ApplicationConfiguration c) {");
sourceWriter.indent();
sourceWriter
.println("fullyQualifiedName = fullyQualifiedName.intern();");
@@ -211,9 +273,10 @@ public class WidgetMapGenerator extends Generator {
.value();
sourceWriter.print("if ( fullyQualifiedName == \"");
sourceWriter.print(class1.getName());
- sourceWriter.print("\" ) return ");
+ sourceWriter.print("\" ) { ensureInstantiator("
+ + clientClass.getName() + ".class, c); return ");
sourceWriter.print(clientClass.getName());
- sourceWriter.println(".class;");
+ sourceWriter.println(".class;}");
sourceWriter.print("else ");
}
sourceWriter
@@ -222,5 +285,4 @@ public class WidgetMapGenerator extends Generator {
sourceWriter.println("}");
}
-
}
diff --git a/src/com/vaadin/ui/Button.java b/src/com/vaadin/ui/Button.java
index 2a38348105..99daf2b34c 100644
--- a/src/com/vaadin/ui/Button.java
+++ b/src/com/vaadin/ui/Button.java
@@ -33,7 +33,7 @@ import com.vaadin.ui.themes.BaseTheme;
* @since 3.0
*/
@SuppressWarnings("serial")
-@ClientWidget(VButton.class)
+@ClientWidget(value = VButton.class, lazyLoad = false)
public class Button extends AbstractField implements FieldEvents.BlurNotifier,
FieldEvents.FocusNotifier {
@@ -472,7 +472,7 @@ public class Button extends AbstractField implements FieldEvents.BlurNotifier,
@Override
public void handleAction(Object sender, Object target) {
- this.button.fireClick();
+ button.fireClick();
}
}
diff --git a/src/com/vaadin/ui/ClientWidget.java b/src/com/vaadin/ui/ClientWidget.java
index 989f70ce55..39aecf1f86 100644
--- a/src/com/vaadin/ui/ClientWidget.java
+++ b/src/com/vaadin/ui/ClientWidget.java
@@ -12,6 +12,7 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import com.vaadin.terminal.gwt.client.Paintable;
+import com.vaadin.terminal.gwt.widgetsetutils.WidgetMapGenerator;
/**
* Annotation defining the default client side counterpart in GWT terminal for
@@ -35,4 +36,34 @@ public @interface ClientWidget {
* @return the client side counterpart for the annotated component
*/
Class<? extends Paintable> value();
+
+ /**
+ * 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.
+ * <p>
+ * 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.
+ * <p>
+ * 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.
+ * <p>
+ * 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.
+ *
+ * @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.
+ */
+ boolean lazyLoad() default true;
+
}
diff --git a/src/com/vaadin/ui/CustomComponent.java b/src/com/vaadin/ui/CustomComponent.java
index 661c72b951..46e92384f8 100644
--- a/src/com/vaadin/ui/CustomComponent.java
+++ b/src/com/vaadin/ui/CustomComponent.java
@@ -26,7 +26,7 @@ import com.vaadin.terminal.gwt.client.ui.VCustomComponent;
* @since 3.0
*/
@SuppressWarnings("serial")
-@ClientWidget(VCustomComponent.class)
+@ClientWidget(value = VCustomComponent.class, lazyLoad = false)
public class CustomComponent extends AbstractComponentContainer {
/**
diff --git a/src/com/vaadin/ui/HorizontalLayout.java b/src/com/vaadin/ui/HorizontalLayout.java
index b3ae1aadfa..3308b5764e 100644
--- a/src/com/vaadin/ui/HorizontalLayout.java
+++ b/src/com/vaadin/ui/HorizontalLayout.java
@@ -17,7 +17,7 @@ import com.vaadin.terminal.gwt.client.ui.VHorizontalLayout;
* @since 5.3
*/
@SuppressWarnings("serial")
-@ClientWidget(VHorizontalLayout.class)
+@ClientWidget(value = VHorizontalLayout.class, lazyLoad = false)
public class HorizontalLayout extends AbstractOrderedLayout {
public HorizontalLayout() {
diff --git a/src/com/vaadin/ui/Label.java b/src/com/vaadin/ui/Label.java
index 22aa0514e1..288692a365 100644
--- a/src/com/vaadin/ui/Label.java
+++ b/src/com/vaadin/ui/Label.java
@@ -38,7 +38,7 @@ import com.vaadin.terminal.gwt.client.ui.VLabel;
* @since 3.0
*/
@SuppressWarnings("serial")
-@ClientWidget(VLabel.class)
+@ClientWidget(value = VLabel.class, lazyLoad = false)
public class Label extends AbstractComponent implements Property,
Property.Viewer, Property.ValueChangeListener,
Property.ValueChangeNotifier, Comparable {
diff --git a/src/com/vaadin/ui/OrderedLayout.java b/src/com/vaadin/ui/OrderedLayout.java
index 9e2825c519..dafaf54e8e 100644
--- a/src/com/vaadin/ui/OrderedLayout.java
+++ b/src/com/vaadin/ui/OrderedLayout.java
@@ -24,7 +24,7 @@ import com.vaadin.terminal.gwt.client.ui.VOrderedLayout;
*/
@SuppressWarnings("serial")
@Deprecated
-@ClientWidget(VOrderedLayout.class)
+@ClientWidget(value = VOrderedLayout.class, lazyLoad = false)
public class OrderedLayout extends AbstractOrderedLayout {
/* Predefined orientations */
diff --git a/src/com/vaadin/ui/SplitPanel.java b/src/com/vaadin/ui/SplitPanel.java
index fe2da5d370..fc443052e8 100644
--- a/src/com/vaadin/ui/SplitPanel.java
+++ b/src/com/vaadin/ui/SplitPanel.java
@@ -30,7 +30,7 @@ import com.vaadin.tools.ReflectTools;
* @since 5.0
*/
@SuppressWarnings("serial")
-@ClientWidget(VSplitPanelHorizontal.class)
+@ClientWidget(value = VSplitPanelHorizontal.class, lazyLoad = false)
public class SplitPanel extends AbstractLayout {
/* Predefined orientations */
diff --git a/src/com/vaadin/ui/TextField.java b/src/com/vaadin/ui/TextField.java
index 88451717ce..9baeea744b 100644
--- a/src/com/vaadin/ui/TextField.java
+++ b/src/com/vaadin/ui/TextField.java
@@ -38,7 +38,7 @@ import com.vaadin.terminal.gwt.client.ui.VTextField;
* @since 3.0
*/
@SuppressWarnings("serial")
-@ClientWidget(VTextField.class)
+@ClientWidget(value = VTextField.class, lazyLoad = false)
public class TextField extends AbstractField implements
FieldEvents.BlurNotifier, FieldEvents.FocusNotifier {
diff --git a/src/com/vaadin/ui/UriFragmentUtility.java b/src/com/vaadin/ui/UriFragmentUtility.java
index 4b4eee36c2..a99b2803ca 100644
--- a/src/com/vaadin/ui/UriFragmentUtility.java
+++ b/src/com/vaadin/ui/UriFragmentUtility.java
@@ -20,7 +20,7 @@ import com.vaadin.terminal.gwt.client.ui.VUriFragmentUtility;
*
*/
@SuppressWarnings("serial")
-@ClientWidget(VUriFragmentUtility.class)
+@ClientWidget(value = VUriFragmentUtility.class, lazyLoad = false)
public class UriFragmentUtility extends AbstractComponent {
/**
diff --git a/src/com/vaadin/ui/VerticalLayout.java b/src/com/vaadin/ui/VerticalLayout.java
index de6f294ffe..52b928ed82 100644
--- a/src/com/vaadin/ui/VerticalLayout.java
+++ b/src/com/vaadin/ui/VerticalLayout.java
@@ -18,7 +18,7 @@ import com.vaadin.terminal.gwt.client.ui.VVerticalLayout;
* @since 5.3
*/
@SuppressWarnings("serial")
-@ClientWidget(VVerticalLayout.class)
+@ClientWidget(value = VVerticalLayout.class, lazyLoad = false)
public class VerticalLayout extends AbstractOrderedLayout {
public VerticalLayout() {