/* * Copyright 2016 cruxframework.org. * * 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 org.cruxframework.crux.core.rebind.screen.widget; import java.io.PrintWriter; import java.util.Iterator; import org.cruxframework.crux.core.client.screen.DeviceAdaptive.Device; import org.cruxframework.crux.core.client.screen.views.ViewFactory; import org.cruxframework.crux.core.rebind.AbstractProxyCreator; import org.cruxframework.crux.core.rebind.CruxGeneratorException; import org.cruxframework.crux.core.rebind.controller.ControllerProxyCreator; import org.cruxframework.crux.core.rebind.screen.Event; import org.cruxframework.crux.core.rebind.screen.EventFactory; import org.cruxframework.crux.core.rebind.screen.View; import org.cruxframework.crux.core.rebind.screen.View.NativeControllerCall; import com.google.gwt.core.ext.typeinfo.JClassType; import com.google.gwt.core.ext.typeinfo.JMethod; import com.google.gwt.core.ext.typeinfo.JType; import com.google.gwt.user.rebind.ClassSourceFileComposerFactory; /** * A Helper class to handle calls to crux controllers on native HTML elements * @author Thiago da Rosa de Bustamante * */ public class NativeControllersProxyCreator extends AbstractProxyCreator { private ViewFactoryCreator viewFactoryCreator; public NativeControllersProxyCreator(ViewFactoryCreator viewFactoryCreator) { super(viewFactoryCreator.getContext(), false); this.viewFactoryCreator = viewFactoryCreator; } @Override public String getProxyQualifiedName() { return ViewFactory.class.getPackage().getName() + "." + getProxySimpleName(); } @Override public String getProxySimpleName() { String className = ViewFactoryCreator.getViewNativeControllersType(viewFactoryCreator.getView().getId(), viewFactoryCreator.getDevice()); return className; }; @Override protected void generateProxyContructor(SourcePrinter printer) throws CruxGeneratorException { printer.println("public " + getProxySimpleName() + "("+org.cruxframework.crux.core.client.screen.views.View.class.getCanonicalName()+" view){"); printer.println("this."+ViewFactoryCreator.getViewVariable() + " = view;"); printer.println("}"); } protected void generateProxyFields(SourcePrinter printer) throws CruxGeneratorException { printer.println("private " + org.cruxframework.crux.core.client.screen.views.View.class.getCanonicalName() + " " + ViewFactoryCreator.getViewVariable() + ";"); } @Override protected void generateProxyMethods(SourcePrinter printer) throws CruxGeneratorException { String proxyName = getProxyQualifiedName(); StringBuilder initMethods = new StringBuilder(); View view = viewFactoryCreator.getView(); String device = viewFactoryCreator.getDevice(); Iterator<NativeControllerCall> nativeControllerCalls = view.iterateNativeControllerCalls(); while(nativeControllerCalls.hasNext()) { NativeControllerCall nativeControllerCall = nativeControllerCalls.next(); String methodName = nativeControllerCall.getMethod(); Event event = EventFactory.getEvent(methodName, nativeControllerCall.getControllerCall()); JClassType eventType = getControllerMethodParameter(nativeControllerCall); printer.print("public final void bridge_" + methodName + "("); if (eventType != null) { printer.print(eventType.getParameterizedQualifiedSourceName() + " e"); } printer.println("){"); printer.print(viewFactoryCreator.getControllerAccessHandler().getControllerExpression(event.getController(), Device.valueOf(device)) + "." + event.getMethod()+ControllerProxyCreator.EXPOSED_METHOD_SUFFIX+"("); if (eventType != null) { printer.print("e"); } printer.println(");"); printer.println("}"); printer.println("public native void register_" + methodName + "("+proxyName+" proxy)/*-{"); printer.println("$wnd."+methodName+" = function(e){"); if (eventType != null) { printer.println("proxy.@"+proxyName+"::bridge_" + methodName+"(L"+ eventType.getParameterizedQualifiedSourceName().replace('.', '/')+";)(e);"); } else { printer.println("proxy.@"+proxyName+"::bridge_" + methodName+"()();"); } printer.println("}"); printer.println("}-*/;"); initMethods.append("register_" + methodName + "(this);\n"); } printer.println("public void init(){"); printer.println(initMethods.toString()); printer.println("}"); } protected JClassType getControllerMethodParameter(NativeControllerCall nativeControllerCall) { View view = viewFactoryCreator.getView(); String device = viewFactoryCreator.getDevice(); JMethod[] possibleEventHandlers = EvtProcessor.getControllerDomEventHandlers(context, "nativeEvent", nativeControllerCall.getControllerCall(), view, Device.valueOf(device)); if (possibleEventHandlers.length == 0) { throw new CruxGeneratorException("Error creating native HTML controller call for event["+nativeControllerCall.getControllerCall()+"]." + "There is no possible handler for this call on target controller. The event handler method must be annotated with @Expose, be public " + "and have no parameter or a single parameter of type NativeEvent."); } try { JMethod method = possibleEventHandlers[0]; JType[] parameterTypes = method.getParameterTypes(); if (parameterTypes.length > 0) { JClassType parameterType = parameterTypes[0].isClassOrInterface(); return parameterType; } else { return null; } } catch (Exception e) { throw new CruxGeneratorException("Error creating native HTML controller call for event["+nativeControllerCall.getControllerCall()+"].", e); } } @Override protected SourcePrinter getSourcePrinter() { String packageName = ViewFactory.class.getPackage().getName(); PrintWriter printWriter = context.getGeneratorContext().tryCreate(context.getLogger(), packageName, getProxySimpleName()); if (printWriter == null) { return null; } ClassSourceFileComposerFactory composerFactory = new ClassSourceFileComposerFactory(packageName, getProxySimpleName()); return new SourceCodePrinter(composerFactory.createSourceWriter(context.getGeneratorContext(), printWriter), context.getLogger()); } }