svn changeset:13652/svn branch:6.4tags/6.7.0.beta1
import java.util.LinkedList; | import java.util.LinkedList; | ||||
import java.util.List; | import java.util.List; | ||||
import com.google.gwt.core.client.EntryPoint; | |||||
import com.google.gwt.core.client.GWT; | |||||
import com.google.gwt.core.client.JavaScriptObject; | import com.google.gwt.core.client.JavaScriptObject; | ||||
import com.google.gwt.core.client.JsArrayString; | import com.google.gwt.core.client.JsArrayString; | ||||
import com.google.gwt.user.client.Command; | import com.google.gwt.user.client.Command; | ||||
import com.google.gwt.user.client.Timer; | |||||
import com.vaadin.terminal.gwt.client.ui.VUnknownComponent; | import com.vaadin.terminal.gwt.client.ui.VUnknownComponent; | ||||
public class ApplicationConfiguration { | |||||
public class ApplicationConfiguration implements EntryPoint { | |||||
// can only be inited once, to avoid multiple-entrypoint-problem | |||||
private static WidgetSet initedWidgetSet; | |||||
private static WidgetSet widgetSet = GWT.create(WidgetSet.class); | |||||
private String id; | private String id; | ||||
private String themeUri; | private String themeUri; | ||||
private String windowId; | private String windowId; | ||||
// TODO consider to make this hashmap per application | |||||
static// TODO consider to make this hashmap per application | |||||
LinkedList<Command> callbacks = new LinkedList<Command>(); | LinkedList<Command> callbacks = new LinkedList<Command>(); | ||||
private int widgetsLoading; | |||||
private static int widgetsLoading; | |||||
private static ArrayList<ApplicationConnection> unstartedApplications = new ArrayList<ApplicationConnection>(); | private static ArrayList<ApplicationConnection> unstartedApplications = new ArrayList<ApplicationConnection>(); | ||||
private static ArrayList<ApplicationConnection> runningApplications = new ArrayList<ApplicationConnection>(); | private static ArrayList<ApplicationConnection> runningApplications = new ArrayList<ApplicationConnection>(); | ||||
* @param widgetset | * @param widgetset | ||||
* the widgetset that is running the apps | * the widgetset that is running the apps | ||||
*/ | */ | ||||
public static void initConfigurations(WidgetSet widgetset) { | |||||
if (initedWidgetSet != null) { | |||||
// Multiple widgetsets inited; can happen with custom WS + entry | |||||
// point | |||||
String msg = "Ignoring " + widgetset.getClass().getName() | |||||
+ ", because " + initedWidgetSet.getClass().getName() | |||||
+ " was already inited (if this is wrong, your entry point" | |||||
+ " is probably not first your .gwt.xml)."; | |||||
throw new IllegalStateException(msg); | |||||
} | |||||
initedWidgetSet = widgetset; | |||||
public static void initConfigurations() { | |||||
ArrayList<String> appIds = new ArrayList<String>(); | ArrayList<String> appIds = new ArrayList<String>(); | ||||
loadAppIdListFromDOM(appIds); | loadAppIdListFromDOM(appIds); | ||||
for (Iterator<String> it = appIds.iterator(); it.hasNext();) { | for (Iterator<String> it = appIds.iterator(); it.hasNext();) { | ||||
String appId = it.next(); | String appId = it.next(); | ||||
ApplicationConfiguration appConf = getConfigFromDOM(appId); | ApplicationConfiguration appConf = getConfigFromDOM(appId); | ||||
ApplicationConnection a = new ApplicationConnection(widgetset, | |||||
ApplicationConnection a = new ApplicationConnection(widgetSet, | |||||
appConf); | appConf); | ||||
unstartedApplications.add(a); | unstartedApplications.add(a); | ||||
} | } | ||||
deferredWidgetLoadLoop.scheduleRepeating(100); | |||||
} | } | ||||
/** | /** | ||||
for (int i = 0; i < keyArray.length(); i++) { | for (int i = 0; i < keyArray.length(); i++) { | ||||
String key = keyArray.get(i).intern(); | String key = keyArray.get(i).intern(); | ||||
int value = valueMap.getInt(key); | int value = valueMap.getInt(key); | ||||
classes[value] = widgetSet.getImplementationByClassName(key, this); | |||||
classes[value] = widgetSet.getImplementationByClassName(key); | |||||
if (classes[value] == VUnknownComponent.class) { | if (classes[value] == VUnknownComponent.class) { | ||||
if (unknownComponents == null) { | if (unknownComponents == null) { | ||||
unknownComponents = new HashMap<String, String>(); | unknownComponents = new HashMap<String, String>(); | ||||
* | * | ||||
* @param c | * @param c | ||||
*/ | */ | ||||
void runWhenWidgetsLoaded(Command c) { | |||||
static void runWhenWidgetsLoaded(Command c) { | |||||
if (widgetsLoading == 0) { | if (widgetsLoading == 0) { | ||||
c.execute(); | c.execute(); | ||||
} else { | } else { | ||||
} | } | ||||
} | } | ||||
void widgetLoadStart() { | |||||
static void startWidgetLoading() { | |||||
widgetsLoading++; | widgetsLoading++; | ||||
} | } | ||||
void widgetLoaded() { | |||||
static void endWidgetLoading() { | |||||
widgetsLoading--; | widgetsLoading--; | ||||
if (widgetsLoading == 0 && !callbacks.isEmpty()) { | if (widgetsLoading == 0 && !callbacks.isEmpty()) { | ||||
for (Command cmd : callbacks) { | for (Command cmd : callbacks) { | ||||
} | } | ||||
} | } | ||||
/* | |||||
* This loop loads widget implementation that should be loaded deferred. | |||||
*/ | |||||
private static final Timer deferredWidgetLoadLoop = new Timer() { | |||||
private static final int FREE_LIMIT = 4; | |||||
int communicationFree = 0; | |||||
int nextWidgetIndex = 0; | |||||
@Override | |||||
public void run() { | |||||
if (!isBusy()) { | |||||
Class<? extends Paintable> nextType = getNextType(); | |||||
if (nextType == null) { | |||||
// ensured that all widgets are loaded | |||||
cancel(); | |||||
} else { | |||||
widgetSet.loadImplementation(nextType); | |||||
} | |||||
} | |||||
} | |||||
private Class<? extends Paintable> getNextType() { | |||||
Class<? extends Paintable>[] deferredLoadedWidgets = widgetSet | |||||
.getDeferredLoadedWidgets(); | |||||
if (deferredLoadedWidgets.length <= nextWidgetIndex) { | |||||
return null; | |||||
} else { | |||||
return deferredLoadedWidgets[nextWidgetIndex++]; | |||||
} | |||||
} | |||||
private boolean isBusy() { | |||||
if (widgetsLoading > 0) { | |||||
communicationFree = 0; | |||||
return false; | |||||
} | |||||
for (ApplicationConnection app : runningApplications) { | |||||
if (app.hasActiveRequest()) { | |||||
// if an UIDL request or widget loading is active, mark as | |||||
// busy | |||||
communicationFree = 0; | |||||
return false; | |||||
} | |||||
} | |||||
communicationFree++; | |||||
return communicationFree < FREE_LIMIT; | |||||
} | |||||
}; | |||||
public void onModuleLoad() { | |||||
initConfigurations(); | |||||
startNextApplication(); | |||||
} | |||||
} | } |
} | } | ||||
}; | }; | ||||
configuration.runWhenWidgetsLoaded(c); | |||||
ApplicationConfiguration.runWhenWidgetsLoaded(c); | |||||
} | } | ||||
/** | /** |
/* | |||||
@ITMillApache2LicenseForJavaFiles@ | |||||
*/ | |||||
package com.vaadin.terminal.gwt.client; | |||||
import com.google.gwt.core.client.GWT; | |||||
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.VFilterSelect; | |||||
import com.vaadin.terminal.gwt.client.ui.VListSelect; | |||||
import com.vaadin.terminal.gwt.client.ui.VNativeSelect; | |||||
import com.vaadin.terminal.gwt.client.ui.VOptionGroup; | |||||
import com.vaadin.terminal.gwt.client.ui.VPasswordField; | |||||
import com.vaadin.terminal.gwt.client.ui.VPopupCalendar; | |||||
import com.vaadin.terminal.gwt.client.ui.VSplitPanelHorizontal; | |||||
import com.vaadin.terminal.gwt.client.ui.VSplitPanelVertical; | |||||
import com.vaadin.terminal.gwt.client.ui.VTextArea; | |||||
import com.vaadin.terminal.gwt.client.ui.VTextField; | |||||
import com.vaadin.terminal.gwt.client.ui.VTwinColSelect; | |||||
import com.vaadin.terminal.gwt.client.ui.VUnknownComponent; | |||||
import com.vaadin.terminal.gwt.client.ui.VView; | |||||
import com.vaadin.terminal.gwt.client.ui.VWindow; | |||||
public class DefaultWidgetSet implements WidgetSet { | |||||
/** | |||||
* DefaultWidgetSet (and its extensions) delegate instantiation of widgets | |||||
* and client-server mathing to WidgetMap. The actual implementations are | |||||
* generated with gwts deferred binding. | |||||
*/ | |||||
private WidgetMap map; | |||||
/** | |||||
* This is the entry point method. It will start the first | |||||
*/ | |||||
public void onModuleLoad() { | |||||
try { | |||||
ApplicationConfiguration.initConfigurations(this); | |||||
} catch (Exception e) { | |||||
// Log & don't continue; | |||||
// custom WidgetSets w/ entry points will cause this | |||||
ApplicationConnection.getConsole().log(e.getMessage()); | |||||
return; | |||||
} | |||||
ApplicationConfiguration.startNextApplication(); // start first app | |||||
map = GWT.create(WidgetMap.class); | |||||
} | |||||
public Paintable createWidget(UIDL uidl, ApplicationConfiguration conf) { | |||||
final Class<? extends Paintable> classType = resolveWidgetType(uidl, | |||||
conf); | |||||
if (classType == null || classType == VUnknownComponent.class) { | |||||
String serverSideName = conf | |||||
.getUnknownServerClassNameByEncodedTagName(uidl.getTag()); | |||||
return new VUnknownComponent(serverSideName); | |||||
} | |||||
return map.instantiate(classType); | |||||
} | |||||
protected Class<? extends Paintable> resolveWidgetType(UIDL uidl, | |||||
ApplicationConfiguration conf) { | |||||
final String tag = uidl.getTag(); | |||||
Class<? extends Paintable> widgetClass = conf | |||||
.getWidgetClassByEncodedTag(tag); | |||||
// add our historical quirks | |||||
if (widgetClass == VButton.class && uidl.hasAttribute("type")) { | |||||
return VCheckBox.class; | |||||
} else if (widgetClass == VView.class && uidl.hasAttribute("sub")) { | |||||
return VWindow.class; | |||||
} else if (widgetClass == VFilterSelect.class) { | |||||
if (uidl.hasAttribute("type")) { | |||||
// TODO check if all type checks are really neede | |||||
final String type = uidl.getStringAttribute("type").intern(); | |||||
if (type == "twincol") { | |||||
return VTwinColSelect.class; | |||||
} else if (type == "optiongroup") { | |||||
return VOptionGroup.class; | |||||
} else if (type == "native") { | |||||
return VNativeSelect.class; | |||||
} else if (type == "list") { | |||||
return VListSelect.class; | |||||
} else if (uidl.hasAttribute("selectmode") | |||||
&& uidl.getStringAttribute("selectmode") | |||||
.equals("multi")) { | |||||
return VListSelect.class; | |||||
} | |||||
} | |||||
} else if (widgetClass == VTextField.class) { | |||||
if (uidl.hasAttribute("multiline")) { | |||||
return VTextArea.class; | |||||
} else if (uidl.hasAttribute("secret")) { | |||||
return VPasswordField.class; | |||||
} | |||||
} else if (widgetClass == VPopupCalendar.class) { | |||||
if (uidl.hasAttribute("type") | |||||
&& uidl.getStringAttribute("type").equals("inline")) { | |||||
return VDateFieldCalendar.class; | |||||
} | |||||
} else if (widgetClass == VSplitPanelHorizontal.class | |||||
&& uidl.hasAttribute("vertical")) { | |||||
return VSplitPanelVertical.class; | |||||
} | |||||
return widgetClass; | |||||
} | |||||
public boolean isCorrectImplementation(Widget currentWidget, UIDL uidl, | |||||
ApplicationConfiguration conf) { | |||||
return currentWidget.getClass() == resolveWidgetType(uidl, conf); | |||||
} | |||||
public Class<? extends Paintable> getImplementationByClassName( | |||||
String fullyqualifiedName, | |||||
ApplicationConfiguration applicationConfiguration) { | |||||
Class<? extends Paintable> implementationByServerSideClassName = map | |||||
.getImplementationByServerSideClassName(fullyqualifiedName, | |||||
applicationConfiguration); | |||||
return implementationByServerSideClassName; | |||||
} | |||||
} |
package com.vaadin.terminal.gwt.client; | |||||
/** | |||||
* A helper class used by WidgetMap implementation. Used by the generated code. | |||||
*/ | |||||
interface WidgetInstantiator { | |||||
public Paintable get(); | |||||
} |
package com.vaadin.terminal.gwt.client; | |||||
import com.google.gwt.core.client.RunAsyncCallback; | |||||
/** A helper class used by WidgetMap implementation. Used by the generated code. */ | |||||
abstract class WidgetLoader implements RunAsyncCallback { | |||||
public void onFailure(Throwable reason) { | |||||
ApplicationConfiguration.endWidgetLoading(); | |||||
} | |||||
public void onSuccess() { | |||||
addInstantiator(); | |||||
ApplicationConfiguration.endWidgetLoading(); | |||||
} | |||||
abstract void addInstantiator(); | |||||
} |
*/ | */ | ||||
package com.vaadin.terminal.gwt.client; | package com.vaadin.terminal.gwt.client; | ||||
import com.vaadin.terminal.gwt.client.ui.VDateFieldCalendar; | |||||
import com.vaadin.terminal.gwt.client.ui.VPasswordField; | |||||
import com.vaadin.terminal.gwt.client.ui.VSplitPanelVertical; | |||||
import com.vaadin.terminal.gwt.client.ui.VTextArea; | |||||
import com.vaadin.terminal.gwt.client.ui.VWindow; | |||||
import java.util.HashMap; | |||||
public abstract class WidgetMap { | |||||
abstract class WidgetMap { | |||||
public Paintable instantiate(Class<? extends Paintable> classType) { | |||||
protected static HashMap<Class, WidgetInstantiator> instmap = new HashMap<Class, WidgetInstantiator>(); | |||||
/* | |||||
* 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 | |||||
* mostly written by WidgetSetGenerator, here are just some hacks. Extra | |||||
* instantiation code is needed if client side widget has no "native" | |||||
* counterpart on client side. | |||||
*/ | |||||
if (VSplitPanelVertical.class == classType) { | |||||
return new VSplitPanelVertical(); | |||||
} else if (VTextArea.class == classType) { | |||||
return new VTextArea(); | |||||
} else if (VDateFieldCalendar.class == classType) { | |||||
return new VDateFieldCalendar(); | |||||
} else if (VPasswordField.class == classType) { | |||||
return new VPasswordField(); | |||||
} else if (VWindow.class == classType) { | |||||
return new VWindow(); | |||||
} else { | |||||
return null; // let generated type handle this | |||||
} | |||||
public Paintable instantiate(Class<? extends Paintable> classType) { | |||||
return instmap.get(classType).get(); | |||||
} | } | ||||
public abstract Class<? extends Paintable> getImplementationByServerSideClassName( | public abstract Class<? extends Paintable> getImplementationByServerSideClassName( | ||||
String fullyqualifiedName, | |||||
ApplicationConfiguration applicationConfiguration); | |||||
String fullyqualifiedName); | |||||
public abstract Class<? extends Paintable>[] getDeferredLoadedWidgets(); | |||||
public abstract void ensureInstantiator(Class<? extends Paintable> classType); | |||||
} | } |
package com.vaadin.terminal.gwt.client; | package com.vaadin.terminal.gwt.client; | ||||
import com.google.gwt.core.client.EntryPoint; | |||||
import com.google.gwt.core.client.GWT; | |||||
import com.google.gwt.user.client.ui.Widget; | 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.VFilterSelect; | |||||
import com.vaadin.terminal.gwt.client.ui.VListSelect; | |||||
import com.vaadin.terminal.gwt.client.ui.VNativeSelect; | |||||
import com.vaadin.terminal.gwt.client.ui.VOptionGroup; | |||||
import com.vaadin.terminal.gwt.client.ui.VPasswordField; | |||||
import com.vaadin.terminal.gwt.client.ui.VPopupCalendar; | |||||
import com.vaadin.terminal.gwt.client.ui.VSplitPanelHorizontal; | |||||
import com.vaadin.terminal.gwt.client.ui.VSplitPanelVertical; | |||||
import com.vaadin.terminal.gwt.client.ui.VTextArea; | |||||
import com.vaadin.terminal.gwt.client.ui.VTextField; | |||||
import com.vaadin.terminal.gwt.client.ui.VTwinColSelect; | |||||
import com.vaadin.terminal.gwt.client.ui.VUnknownComponent; | |||||
import com.vaadin.terminal.gwt.client.ui.VView; | |||||
import com.vaadin.terminal.gwt.client.ui.VWindow; | |||||
public interface WidgetSet extends EntryPoint { | |||||
public class WidgetSet { | |||||
/** | |||||
* WidgetSet (and its extensions) delegate instantiation of widgets and | |||||
* client-server matching to WidgetMap. The actual implementations are | |||||
* generated with gwts generators/deferred binding. | |||||
*/ | |||||
private WidgetMap widgetMap = GWT.create(WidgetMap.class); | |||||
/** | /** | ||||
* Create an uninitialized component that best matches given UIDL. The | * Create an uninitialized component that best matches given UIDL. The | ||||
* @return New uninitialized and unregistered component that can paint given | * @return New uninitialized and unregistered component that can paint given | ||||
* UIDL. | * UIDL. | ||||
*/ | */ | ||||
public Paintable createWidget(UIDL uidl, ApplicationConfiguration conf); | |||||
public Paintable createWidget(UIDL uidl, ApplicationConfiguration conf) { | |||||
/* | |||||
* Yes, this (including the generated code in WidgetMap) may look very | |||||
* odd code, but due the nature of GWT, we cannot do this any cleaner. | |||||
* Luckily this is mostly written by WidgetSetGenerator, here are just | |||||
* some hacks. Extra instantiation code is needed if client side widget | |||||
* has no "native" counterpart on client side. | |||||
* | |||||
* TODO should try to get rid of these exceptions here | |||||
*/ | |||||
final Class<? extends Paintable> classType = resolveWidgetType(uidl, | |||||
conf); | |||||
if (classType == null || classType == VUnknownComponent.class) { | |||||
String serverSideName = conf | |||||
.getUnknownServerClassNameByEncodedTagName(uidl.getTag()); | |||||
return new VUnknownComponent(serverSideName); | |||||
} else if (VSplitPanelVertical.class == classType) { | |||||
return new VSplitPanelVertical(); | |||||
} else if (VTextArea.class == classType) { | |||||
return new VTextArea(); | |||||
} else if (VDateFieldCalendar.class == classType) { | |||||
return new VDateFieldCalendar(); | |||||
} else if (VPasswordField.class == classType) { | |||||
return new VPasswordField(); | |||||
} else if (VWindow.class == classType) { | |||||
return new VWindow(); | |||||
} else { | |||||
/* | |||||
* let the auto generated code instantiate this type | |||||
*/ | |||||
return widgetMap.instantiate(classType); | |||||
} | |||||
} | |||||
protected Class<? extends Paintable> resolveWidgetType(UIDL uidl, | |||||
ApplicationConfiguration conf) { | |||||
final String tag = uidl.getTag(); | |||||
Class<? extends Paintable> widgetClass = conf | |||||
.getWidgetClassByEncodedTag(tag); | |||||
// add our historical quirks | |||||
if (widgetClass == VButton.class && uidl.hasAttribute("type")) { | |||||
return VCheckBox.class; | |||||
} else if (widgetClass == VView.class && uidl.hasAttribute("sub")) { | |||||
return VWindow.class; | |||||
} else if (widgetClass == VFilterSelect.class) { | |||||
if (uidl.hasAttribute("type")) { | |||||
// TODO check if all type checks are really neede | |||||
final String type = uidl.getStringAttribute("type").intern(); | |||||
if (type == "twincol") { | |||||
return VTwinColSelect.class; | |||||
} else if (type == "optiongroup") { | |||||
return VOptionGroup.class; | |||||
} else if (type == "native") { | |||||
return VNativeSelect.class; | |||||
} else if (type == "list") { | |||||
return VListSelect.class; | |||||
} else if (uidl.hasAttribute("selectmode") | |||||
&& uidl.getStringAttribute("selectmode") | |||||
.equals("multi")) { | |||||
return VListSelect.class; | |||||
} | |||||
} | |||||
} else if (widgetClass == VTextField.class) { | |||||
if (uidl.hasAttribute("multiline")) { | |||||
return VTextArea.class; | |||||
} else if (uidl.hasAttribute("secret")) { | |||||
return VPasswordField.class; | |||||
} | |||||
} else if (widgetClass == VPopupCalendar.class) { | |||||
if (uidl.hasAttribute("type") | |||||
&& uidl.getStringAttribute("type").equals("inline")) { | |||||
return VDateFieldCalendar.class; | |||||
} | |||||
} else if (widgetClass == VSplitPanelHorizontal.class | |||||
&& uidl.hasAttribute("vertical")) { | |||||
return VSplitPanelVertical.class; | |||||
} | |||||
return widgetClass; | |||||
} | |||||
/** | /** | ||||
* Test if the given component implementation conforms to UIDL. | * Test if the given component implementation conforms to UIDL. | ||||
* class than currentWidget | * class than currentWidget | ||||
*/ | */ | ||||
public boolean isCorrectImplementation(Widget currentWidget, UIDL uidl, | public boolean isCorrectImplementation(Widget currentWidget, UIDL uidl, | ||||
ApplicationConfiguration conf); | |||||
ApplicationConfiguration conf) { | |||||
return currentWidget.getClass() == resolveWidgetType(uidl, conf); | |||||
} | |||||
/** | /** | ||||
* Due its nature, GWT does not support dynamic classloading. To bypass this | * Due its nature, GWT does not support dynamic classloading. To bypass this | ||||
* @return | * @return | ||||
*/ | */ | ||||
public Class<? extends Paintable> getImplementationByClassName( | public Class<? extends Paintable> getImplementationByClassName( | ||||
String fullyQualifiedName, | |||||
ApplicationConfiguration applicationConfiguration); | |||||
String fullyqualifiedName) { | |||||
Class<? extends Paintable> implementationByServerSideClassName = widgetMap | |||||
.getImplementationByServerSideClassName(fullyqualifiedName); | |||||
return implementationByServerSideClassName; | |||||
} | |||||
public Class<? extends Paintable>[] getDeferredLoadedWidgets() { | |||||
return widgetMap.getDeferredLoadedWidgets(); | |||||
} | |||||
public void loadImplementation(Class<? extends Paintable> nextType) { | |||||
widgetMap.ensureInstantiator(nextType); | |||||
} | |||||
} | } |
import java.util.Collection; | import java.util.Collection; | ||||
import java.util.Date; | import java.util.Date; | ||||
import java.util.Iterator; | import java.util.Iterator; | ||||
import java.util.LinkedList; | |||||
import java.util.TreeSet; | import java.util.TreeSet; | ||||
import com.google.gwt.core.ext.Generator; | import com.google.gwt.core.ext.Generator; | ||||
import com.vaadin.terminal.Paintable; | import com.vaadin.terminal.Paintable; | ||||
import com.vaadin.terminal.gwt.client.ui.VView; | import com.vaadin.terminal.gwt.client.ui.VView; | ||||
import com.vaadin.ui.ClientWidget; | import com.vaadin.ui.ClientWidget; | ||||
import com.vaadin.ui.ClientWidget.LoadStyle; | |||||
/** | /** | ||||
* GWT generator to build WidgetMapImpl dynamically based on | * GWT generator to build WidgetMapImpl dynamically based on | ||||
* @return true iff the widget for given component should be lazy loaded by | * @return true iff the widget for given component should be lazy loaded by | ||||
* the client side engine | * the client side engine | ||||
*/ | */ | ||||
protected boolean isLazyLoaded(Class<? extends Paintable> paintableType) { | |||||
protected LoadStyle getLoadStyle(Class<? extends Paintable> paintableType) { | |||||
ClientWidget annotation = paintableType | ClientWidget annotation = paintableType | ||||
.getAnnotation(ClientWidget.class); | .getAnnotation(ClientWidget.class); | ||||
return annotation.lazyLoad(); | |||||
return annotation.loadStyle(); | |||||
} | } | ||||
private void generateInstantiatorMethod( | private void generateInstantiatorMethod( | ||||
SourceWriter sourceWriter, | SourceWriter sourceWriter, | ||||
Collection<Class<? extends Paintable>> paintablesHavingWidgetAnnotation) { | Collection<Class<? extends Paintable>> paintablesHavingWidgetAnnotation) { | ||||
sourceWriter | |||||
.println("public interface Instantiator { public Paintable get();};"); | |||||
Collection<Class<?>> deferredWidgets = new LinkedList<Class<?>>(); | |||||
// TODO detect if it would be noticably faster to instantiate with a | // TODO detect if it would be noticably faster to instantiate with a | ||||
// lookup with index than with the hashmap | // lookup with index than with the hashmap | ||||
sourceWriter | sourceWriter | ||||
.println("private HashMap<Class,Instantiator> instmap = new HashMap<Class,Instantiator>();"); | |||||
sourceWriter | |||||
.println("public void ensureInstantiator(Class<? extends Paintable> classType, final ApplicationConfiguration c) {"); | |||||
.println("public void ensureInstantiator(Class<? extends Paintable> classType) {"); | |||||
sourceWriter.println("if(!instmap.containsKey(classType)){"); | sourceWriter.println("if(!instmap.containsKey(classType)){"); | ||||
boolean first = true; | |||||
for (Class<? extends Paintable> class1 : paintablesHavingWidgetAnnotation) { | for (Class<? extends Paintable> class1 : paintablesHavingWidgetAnnotation) { | ||||
ClientWidget annotation = class1.getAnnotation(ClientWidget.class); | ClientWidget annotation = class1.getAnnotation(ClientWidget.class); | ||||
Class<? extends com.vaadin.terminal.gwt.client.Paintable> clientClass = annotation | Class<? extends com.vaadin.terminal.gwt.client.Paintable> clientClass = annotation | ||||
// VView's are not instantiated by widgetset | // VView's are not instantiated by widgetset | ||||
continue; | continue; | ||||
} | } | ||||
if (!first) { | |||||
sourceWriter.print(" else "); | |||||
} else { | |||||
first = false; | |||||
} | |||||
sourceWriter.print("if( classType == " + clientClass.getName() | sourceWriter.print("if( classType == " + clientClass.getName() | ||||
+ ".class) {"); | + ".class) {"); | ||||
String instantiator = "new Instantiator() { public Paintable get(){ return GWT.create(" | |||||
+ clientClass.getName() + ".class );}}"; | |||||
String instantiator = "new WidgetInstantiator() {\n public Paintable get() {\n return GWT.create(" | |||||
+ clientClass.getName() + ".class );\n}\n}\n"; | |||||
if (isLazyLoaded(class1)) { | |||||
sourceWriter | |||||
.print("c.widgetLoadStart();GWT.runAsync(new RunAsyncCallback() {\n" | |||||
+ " public void onSuccess() {"); | |||||
LoadStyle loadStyle = getLoadStyle(class1); | |||||
sourceWriter.print("instmap.put("); | |||||
sourceWriter.print(clientClass.getName()); | |||||
sourceWriter.print(".class, "); | |||||
sourceWriter.print(instantiator); | |||||
sourceWriter.println("); c.widgetLoaded();"); | |||||
if (loadStyle != LoadStyle.EAGER) { | |||||
sourceWriter | sourceWriter | ||||
.print(" }\n" | |||||
+ "\n" | |||||
+ " public void onFailure(Throwable reason) {c.widgetLoaded();\n" | |||||
+ "\n" + " }\n" + " });\n"); | |||||
.print("ApplicationConfiguration.startWidgetLoading();\n" | |||||
+ "GWT.runAsync( \n" | |||||
+ "new WidgetLoader() { void addInstantiator() {instmap.put(" | |||||
+ clientClass.getName() | |||||
+ ".class," | |||||
+ instantiator + ");}});\n"); | |||||
if (loadStyle == LoadStyle.DEFERRED) { | |||||
deferredWidgets.add(class1); | |||||
} | |||||
} else { | } else { | ||||
// widget implementation in initially loaded js script | // widget implementation in initially loaded js script | ||||
sourceWriter.println("}"); | sourceWriter.println("}"); | ||||
sourceWriter | 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();"); | |||||
.println("public Class<? extends Paintable>[] getDeferredLoadedWidgets() {"); | |||||
sourceWriter.outdent(); | |||||
sourceWriter.println("return new Class[] {"); | |||||
first = true; | |||||
for (Class<?> class2 : deferredWidgets) { | |||||
if (!first) { | |||||
sourceWriter.println(","); | |||||
} | |||||
first = false; | |||||
ClientWidget annotation = class2.getAnnotation(ClientWidget.class); | |||||
Class<? extends com.vaadin.terminal.gwt.client.Paintable> value = annotation | |||||
.value(); | |||||
sourceWriter.print(value.getName() + ".class"); | |||||
} | |||||
sourceWriter.println("};"); | |||||
sourceWriter.println("}"); | sourceWriter.println("}"); | ||||
} | } | ||||
Collection<Class<? extends Paintable>> paintablesHavingWidgetAnnotation) { | Collection<Class<? extends Paintable>> paintablesHavingWidgetAnnotation) { | ||||
sourceWriter | sourceWriter | ||||
.println("public Class<? extends Paintable> " | .println("public Class<? extends Paintable> " | ||||
+ "getImplementationByServerSideClassName(String fullyQualifiedName, ApplicationConfiguration c) {"); | |||||
+ "getImplementationByServerSideClassName(String fullyQualifiedName) {"); | |||||
sourceWriter.indent(); | sourceWriter.indent(); | ||||
sourceWriter | sourceWriter | ||||
.println("fullyQualifiedName = fullyQualifiedName.intern();"); | .println("fullyQualifiedName = fullyQualifiedName.intern();"); | ||||
sourceWriter.print("if ( fullyQualifiedName == \""); | sourceWriter.print("if ( fullyQualifiedName == \""); | ||||
sourceWriter.print(class1.getName()); | sourceWriter.print(class1.getName()); | ||||
sourceWriter.print("\" ) { ensureInstantiator(" | sourceWriter.print("\" ) { ensureInstantiator(" | ||||
+ clientClass.getName() + ".class, c); return "); | |||||
+ clientClass.getName() + ".class); return "); | |||||
sourceWriter.print(clientClass.getName()); | sourceWriter.print(clientClass.getName()); | ||||
sourceWriter.println(".class;}"); | sourceWriter.println(".class;}"); | ||||
sourceWriter.print("else "); | sourceWriter.print("else "); |