/*
* Copyright 2010 Gal Dolber.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
package com.guit.rebind.guitview;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.core.ext.typeinfo.JClassType;
import com.google.gwt.dom.client.Element;
import com.google.gwt.editor.client.Editor;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiTemplate;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.Focusable;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.user.rebind.ClassSourceFileComposerFactory;
import com.google.gwt.user.rebind.SourceWriter;
import com.guit.client.View;
import com.guit.client.ViewProperties;
import com.guit.client.ViewType;
import com.guit.client.apt.GwtPresenter;
import com.guit.client.binder.GwtEditor;
import com.guit.rebind.common.AbstractGenerator;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Set;
public class GuitViewGenerator extends AbstractGenerator {
protected ViewType viewType;
protected Class<? extends com.google.gwt.dom.client.Element> widgetElementClass;
public GuitViewGenerator() {
implementationPostfix = "_GuitViewImpl";
}
@Override
protected void generate(SourceWriter writer) throws UnableToCompleteException {
JClassType pojo = null;
HashMap<String, String> editorPaths = new HashMap<String, String>();
boolean isEditor = baseClass.isAnnotationPresent(GwtEditor.class);
GwtEditor editor = null;
if (isEditor) {
editor = baseClass.getAnnotation(GwtEditor.class);
pojo = getType(editor.pojo().getCanonicalName());
String[] paths = editor.paths();
for (String p : paths) {
String[] parts = p.split("=");
if (parts.length != 2) {
error(
"Error processing paths, it should have the following format: {fieldName}={path}. i.e: address=data.address . Found: %s, path: %s",
baseClass.getQualifiedSourceName(), p);
}
editorPaths.put(parts[0], parts[1]);
}
}
// User template
String template = GuitViewHelper.getDeclaredTemplateName(baseClass, context, logger);
Set<GuitViewField> uiFields =
GuitViewHelper.findUiFields(baseClass, logger, typeOracle, pojo, editorPaths, template);
writer.println("@UiTemplate(\"" + template + "\")");
String bindedType = "Widget";
if (viewType.equals(ViewType.WIDGET)) {
bindedType = widgetElementClass.getCanonicalName();
}
writer.println("public interface Binder extends UiBinder<" + bindedType + ", " + implName
+ ">{}");
writer.println("private Binder binder = GWT.create(Binder.class);");
writer.println("public void bind() {");
switch (viewType) {
case COMPOSITE:
writer.println("initWidget(binder.createAndBindUi(this));");
break;
case WIDGET:
writer.println("setElement(binder.createAndBindUi(this));");
break;
case ROOTLESS:
writer.println("_guit$widget = binder.createAndBindUi(this);");
break;
}
writer.println("}");
if (baseClass.isAnnotationPresent(GwtPresenter.class)) {
GwtPresenter gwtPresenter = baseClass.getAnnotation(GwtPresenter.class);
// Autofocus
String autofocus = gwtPresenter.autofocus();
int autofocusDelay = gwtPresenter.autofocusDelay();
JClassType autofocusType = null;
if (!autofocus.isEmpty()) {
for (GuitViewField f : uiFields) {
if (f.getName().equals(autofocus)) {
autofocusType = getType(f.getType());
break;
}
}
String scheduledCommand = ScheduledCommand.class.getCanonicalName();
writer.println("private " + scheduledCommand + " focusCmd = new " + scheduledCommand
+ "() {");
writer.println(" @Override");
writer.println(" public void execute() {");
if (autofocusDelay > 0) {
writer.println(" new " + Timer.class.getCanonicalName() + "() {");
writer.println(" @Override");
writer.println(" public void run() {");
}
if (autofocusType.isAssignableTo(getType(Focusable.class.getCanonicalName()))) {
writer.println(" " + autofocus + ".setFocus(true);");
} else if (autofocusType.isAssignableTo(getType(Widget.class.getCanonicalName()))) {
writer.println(" " + autofocus + ".getElement().focus();");
} else {
writer.println(" " + autofocus + ".focus();");
}
if (autofocusDelay > 0) {
writer.println(" }");
writer.println(" }.schedule(" + autofocusDelay + ");");
}
writer.println(" }");
writer.println("};");
writer.println("public void autofocus() {");
writer.println(" " + Scheduler.class.getCanonicalName()
+ ".get().scheduleDeferred(focusCmd);");
writer.println("}");
writer.println("@Override");
writer.println("protected void onLoad() {");
writer.println(" autofocus();");
writer.println("}");
}
}
writer.println("private Widget _guit$widget;");
writer.println("public Widget asWidget() {");
switch (viewType) {
case COMPOSITE:
case WIDGET:
writer.println("return this;");
break;
case ROOTLESS:
writer.println("return _guit$widget;");
break;
}
writer.println("}");
for (GuitViewField f : uiFields) {
writer.println(f.getDeclaration());
}
}
@Override
protected void processComposer(ClassSourceFileComposerFactory composer) {
composer.addImport(UiField.class.getCanonicalName());
composer.addImport(UiTemplate.class.getCanonicalName());
composer.addImport(UiBinder.class.getCanonicalName());
composer.addImport(Widget.class.getCanonicalName());
composer.addImport(GWT.class.getCanonicalName());
composer.addImplementedInterface(View.class.getCanonicalName());
if (baseClass.isAnnotationPresent(GwtEditor.class)) {
GwtEditor editor = baseClass.getAnnotation(GwtEditor.class);
composer.addImplementedInterface(Editor.class.getCanonicalName() + "<"
+ editor.pojo().getCanonicalName() + ">");
}
// View type
ViewProperties properties = null;
if (baseClass.isAnnotationPresent(ViewProperties.class)) {
properties = baseClass.getAnnotation(ViewProperties.class);
viewType = properties.type();
if (viewType.equals(ViewType.WIDGET)) {
widgetElementClass = Element.class;
}
} else {
viewType = ViewType.COMPOSITE;
}
switch (viewType) {
case COMPOSITE:
composer.setSuperclass(Composite.class.getCanonicalName());
break;
case WIDGET:
composer.setSuperclass(Widget.class.getCanonicalName());
break;
default:
break;
}
}
@Override
protected ClassSourceFileComposerFactory createComposer() throws UnableToCompleteException {
return new ClassSourceFileComposerFactory(generatedPackage
+ (GuitViewHelper.isOnViewPackage(baseClass, context, logger) ? ".view" : ""), implName);
}
@Override
protected PrintWriter createPrintWriter() throws UnableToCompleteException {
return context.tryCreate(logger, generatedPackage
+ (GuitViewHelper.isOnViewPackage(baseClass, context, logger) ? ".view" : ""), implName);
}
}