Support for event parameters for methods annotated by @On(event). Basic idea by me, tests provided by Toni. Thanks a lot.
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/ConvertTypes.java Tue Mar 05 19:00:36 2013 +0100
1.3 @@ -0,0 +1,51 @@
1.4 +/**
1.5 + * Back 2 Browser Bytecode Translator
1.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
1.7 + *
1.8 + * This program is free software: you can redistribute it and/or modify
1.9 + * it under the terms of the GNU General Public License as published by
1.10 + * the Free Software Foundation, version 2 of the License.
1.11 + *
1.12 + * This program is distributed in the hope that it will be useful,
1.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1.15 + * GNU General Public License for more details.
1.16 + *
1.17 + * You should have received a copy of the GNU General Public License
1.18 + * along with this program. Look for COPYING file in the top folder.
1.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
1.20 + */
1.21 +package org.apidesign.bck2brwsr.htmlpage;
1.22 +
1.23 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
1.24 +
1.25 +/**
1.26 + *
1.27 + * @author Jaroslav Tulach <jtulach@netbeans.org>
1.28 + */
1.29 +public final class ConvertTypes {
1.30 + ConvertTypes() {
1.31 + }
1.32 +
1.33 + public static String toString(Object object, String property) {
1.34 + Object ret = getProperty(object, property);
1.35 + return ret == null ? null : ret.toString();
1.36 + }
1.37 +
1.38 + public static double toDouble(Object object, String property) {
1.39 + Object ret = getProperty(object, property);
1.40 + return ret instanceof Number ? ((Number)ret).doubleValue() : Double.NaN;
1.41 + }
1.42 +
1.43 + public static int toInt(Object object, String property) {
1.44 + Object ret = getProperty(object, property);
1.45 + return ret instanceof Number ? ((Number)ret).intValue() : Integer.MIN_VALUE;
1.46 + }
1.47 +
1.48 + @JavaScriptBody(args = { "object", "property" },
1.49 + body = "var p = object[property]; return p ? p : null;"
1.50 + )
1.51 + private static Object getProperty(Object object, String property) {
1.52 + return null;
1.53 + }
1.54 +}
2.1 --- a/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/PageProcessor.java Tue Mar 05 18:47:29 2013 +0100
2.2 +++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/PageProcessor.java Tue Mar 05 19:00:36 2013 +0100
2.3 @@ -45,6 +45,7 @@
2.4 import javax.lang.model.element.TypeElement;
2.5 import javax.lang.model.element.VariableElement;
2.6 import javax.lang.model.type.MirroredTypeException;
2.7 +import javax.lang.model.type.TypeKind;
2.8 import javax.lang.model.type.TypeMirror;
2.9 import javax.tools.Diagnostic;
2.10 import javax.tools.FileObject;
2.11 @@ -209,7 +210,19 @@
2.12 }
2.13 first = false;
2.14 if (ve.asType() == stringType) {
2.15 - params.append('"').append(id).append('"');
2.16 + if (ve.getSimpleName().contentEquals("id")) {
2.17 + params.append('"').append(id).append('"');
2.18 + continue;
2.19 + }
2.20 + params.append("org.apidesign.bck2brwsr.htmlpage.ConvertTypes.toString(ev, \"");
2.21 + params.append(ve.getSimpleName().toString());
2.22 + params.append("\")");
2.23 + continue;
2.24 + }
2.25 + if (processingEnv.getTypeUtils().getPrimitiveType(TypeKind.DOUBLE) == ve.asType()) {
2.26 + params.append("org.apidesign.bck2brwsr.htmlpage.ConvertTypes.toDouble(ev, \"");
2.27 + params.append(ve.getSimpleName().toString());
2.28 + params.append("\")");
2.29 continue;
2.30 }
2.31 String rn = ve.asType().toString();
2.32 @@ -222,7 +235,7 @@
2.33 continue;
2.34 }
2.35 processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR,
2.36 - "@On method can only accept String or " + className + " arguments",
2.37 + "@On method can only accept String named 'id' or " + className + " arguments",
2.38 ee
2.39 );
2.40 return false;
2.41 @@ -252,10 +265,10 @@
2.42 }
2.43 w.append(" }\n");
2.44 if (dispatchCnt > 0) {
2.45 - w.append("class OnDispatch implements Runnable {\n");
2.46 + w.append("class OnDispatch implements OnHandler {\n");
2.47 w.append(" private final int dispatch;\n");
2.48 w.append(" OnDispatch(int d) { dispatch = d; }\n");
2.49 - w.append(" public void run() {\n");
2.50 + w.append(" public void onEvent(Object ev) {\n");
2.51 w.append(" switch (dispatch) {\n");
2.52 w.append(dispatch);
2.53 w.append(" }\n");
3.1 --- a/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/Element.java Tue Mar 05 18:47:29 2013 +0100
3.2 +++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/Element.java Tue Mar 05 19:00:36 2013 +0100
3.3 @@ -61,14 +61,18 @@
3.4
3.5 /** Executes given runnable when user performs a "click" on the given
3.6 * element.
3.7 + * @param data an array of one element to fill with event parameter (if any)
3.8 * @param r the runnable to execute, never null
3.9 */
3.10 @JavaScriptBody(
3.11 args={ "ev", "r" },
3.12 body="var e = window.document.getElementById(this._id());\n"
3.13 - + "e[ev._id()] = function() { r.run__V(); };\n"
3.14 + + "e[ev._id()] = function(ev) {\n"
3.15 + + " var d = ev ? ev : null;\n"
3.16 + + " r.onEvent__VLjava_lang_Object_2(d);\n"
3.17 + + "};\n"
3.18 )
3.19 - final void on(OnEvent ev, Runnable r) {
3.20 + final void on(OnEvent ev, OnHandler r) {
3.21 }
3.22
3.23 /** Shows alert message dialog in a browser.
4.1 --- a/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/OnController.java Tue Mar 05 18:47:29 2013 +0100
4.2 +++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/OnController.java Tue Mar 05 19:00:36 2013 +0100
4.3 @@ -30,14 +30,33 @@
4.4 this.arr = arr;
4.5 }
4.6
4.7 + /** Registers an event handler on associated {@link OnEvent}
4.8 + * and {@link Element}
4.9 + *
4.10 + * @param handler the handler to be called when the event occurs
4.11 + */
4.12 + public void perform(final OnHandler handler) {
4.13 + for (Element e : arr) {
4.14 + e.on(event, handler);
4.15 + }
4.16 + }
4.17 +
4.18 /** Registers a runnable to be performed on associated {@link OnEvent}
4.19 * and {@link Element}.
4.20 *
4.21 * @see OnEvent#of
4.22 */
4.23 - public void perform(Runnable r) {
4.24 + public void perform(final Runnable r) {
4.25 + class W implements OnHandler {
4.26 + @Override
4.27 + public void onEvent(Object event) throws Exception {
4.28 + r.run();
4.29 + }
4.30 + }
4.31 + perform(new W());
4.32 + OnHandler w = new W();
4.33 for (Element e : arr) {
4.34 - e.on(event, r);
4.35 + e.on(event, w);
4.36 }
4.37 }
4.38 }
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
5.2 +++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/OnHandler.java Tue Mar 05 19:00:36 2013 +0100
5.3 @@ -0,0 +1,33 @@
5.4 +/**
5.5 + * Back 2 Browser Bytecode Translator
5.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
5.7 + *
5.8 + * This program is free software: you can redistribute it and/or modify
5.9 + * it under the terms of the GNU General Public License as published by
5.10 + * the Free Software Foundation, version 2 of the License.
5.11 + *
5.12 + * This program is distributed in the hope that it will be useful,
5.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
5.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5.15 + * GNU General Public License for more details.
5.16 + *
5.17 + * You should have received a copy of the GNU General Public License
5.18 + * along with this program. Look for COPYING file in the top folder.
5.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
5.20 + */
5.21 +package org.apidesign.bck2brwsr.htmlpage.api;
5.22 +
5.23 +/** Handler to be called when an event in an HTML {@link Page} appears.
5.24 + * @see OnEvent
5.25 + * @see OnController
5.26 + *
5.27 + * @author Jaroslav Tulach <jtulach@netbeans.org>
5.28 + */
5.29 +public interface OnHandler {
5.30 + /** Called when a DOM event appears
5.31 + *
5.32 + * @param event the event as produced by the browser
5.33 + * @throws Exception execution can throw exception
5.34 + */
5.35 + public void onEvent(Object event) throws Exception;
5.36 +}
6.1 --- a/javaquery/api/src/test/java/org/apidesign/bck2brwsr/htmlpage/PageController.java Tue Mar 05 18:47:29 2013 +0100
6.2 +++ b/javaquery/api/src/test/java/org/apidesign/bck2brwsr/htmlpage/PageController.java Tue Mar 05 19:00:36 2013 +0100
6.3 @@ -60,4 +60,9 @@
6.4 }
6.5 PAGE.PG_TITLE.setText(id);
6.6 }
6.7 +
6.8 + @On(event = CLICK, id={ "pg.canvas" })
6.9 + static void clickCanvas(String id, double layerX) {
6.10 + PAGE.PG_CANVAS.setWidth((int) layerX);
6.11 + }
6.12 }
7.1 --- a/javaquery/api/src/test/java/org/apidesign/bck2brwsr/htmlpage/ProcessPageTest.java Tue Mar 05 18:47:29 2013 +0100
7.2 +++ b/javaquery/api/src/test/java/org/apidesign/bck2brwsr/htmlpage/ProcessPageTest.java Tue Mar 05 19:00:36 2013 +0100
7.3 @@ -36,11 +36,12 @@
7.4 assertNotNull(is, "Sample HTML page found");
7.5 ProcessPage res = ProcessPage.readPage(is);
7.6 final Set<String> ids = res.ids();
7.7 - assertEquals(ids.size(), 3, "Three ids found: " + ids);
7.8 + assertEquals(ids.size(), 4, "Four ids found: " + ids);
7.9
7.10 assertEquals(res.tagNameForId("pg.title"), "title");
7.11 assertEquals(res.tagNameForId("pg.button"), "button");
7.12 assertEquals(res.tagNameForId("pg.text"), "input");
7.13 + assertEquals(res.tagNameForId("pg.canvas"), "canvas");
7.14 }
7.15
7.16 @Test public void testCompileAndRunPageController() throws Exception {
7.17 @@ -53,11 +54,13 @@
7.18 + "doc.title.innerHTML = 'nothing';\n"
7.19 + "doc.text = new Object();\n"
7.20 + "doc.text.value = 'something';\n"
7.21 + + "doc.canvas = new Object();\n"
7.22 + "doc.getElementById = function(id) {\n"
7.23 + " switch(id) {\n"
7.24 + " case 'pg.button': return doc.button;\n"
7.25 + " case 'pg.title': return doc.title;\n"
7.26 + " case 'pg.text': return doc.text;\n"
7.27 + + " case 'pg.canvas': return doc.canvas;\n"
7.28 + " }\n"
7.29 + " throw id;\n"
7.30 + " }\n"
7.31 @@ -92,11 +95,13 @@
7.32 + "doc.title.innerHTML = 'nothing';\n"
7.33 + "doc.text = new Object();\n"
7.34 + "doc.text.value = 'something';\n"
7.35 + + "doc.canvas = new Object();\n"
7.36 + "doc.getElementById = function(id) {\n"
7.37 + " switch(id) {\n"
7.38 + " case 'pg.button': return doc.button;\n"
7.39 + " case 'pg.title': return doc.title;\n"
7.40 + " case 'pg.text': return doc.text;\n"
7.41 + + " case 'pg.canvas': return doc.canvas;\n"
7.42 + " }\n"
7.43 + " throw id;\n"
7.44 + " }\n"
7.45 @@ -123,6 +128,52 @@
7.46 assertEquals(ret, "pg.title", "Title has been passed to the method argument");
7.47 }
7.48
7.49 + @Test public void clickWithArgumentAndParameterCalled() throws Exception {
7.50 + StringBuilder sb = new StringBuilder();
7.51 + sb.append(
7.52 + "var window = new Object();\n"
7.53 + + "var doc = new Object();\n"
7.54 + + "var eventObject = new Object();\n"
7.55 + + "eventObject.layerX = 100;\n"
7.56 + + "doc.button = new Object();\n"
7.57 + + "doc.title = new Object();\n"
7.58 + + "doc.title.innerHTML = 'nothing';\n"
7.59 + + "doc.text = new Object();\n"
7.60 + + "doc.text.value = 'something';\n"
7.61 + + "doc.canvas = new Object();\n"
7.62 + + "doc.canvas.width = 200;\n"
7.63 + + "doc.getElementById = function(id) {\n"
7.64 + + " switch(id) {\n"
7.65 + + " case 'pg.button': return doc.button;\n"
7.66 + + " case 'pg.title': return doc.title;\n"
7.67 + + " case 'pg.text': return doc.text;\n"
7.68 + + " case 'pg.canvas': return doc.canvas;\n"
7.69 + + " }\n"
7.70 + + " throw id;\n"
7.71 + + " }\n"
7.72 + + "\n"
7.73 + + "function clickAndCheck() {\n"
7.74 + + " doc.canvas.onclick(eventObject);\n"
7.75 + + " return doc.canvas.width.toString();\n"
7.76 + + "};\n"
7.77 + + "\n"
7.78 + + "window.document = doc;\n"
7.79 + );
7.80 + Invocable i = compileClass(sb,
7.81 + "org/apidesign/bck2brwsr/htmlpage/PageController"
7.82 + );
7.83 +
7.84 + Object ret = null;
7.85 + try {
7.86 + ret = i.invokeFunction("clickAndCheck");
7.87 + } catch (ScriptException ex) {
7.88 + fail("Execution failed in " + sb, ex);
7.89 + } catch (NoSuchMethodException ex) {
7.90 + fail("Cannot find method in " + sb, ex);
7.91 + }
7.92 + assertEquals(ret, "100", "layerX has been passed to the method argument");
7.93 + }
7.94 +
7.95 static Invocable compileClass(StringBuilder sb, String... names) throws ScriptException, IOException {
7.96 if (sb == null) {
7.97 sb = new StringBuilder();
8.1 --- a/javaquery/api/src/test/resources/org/apidesign/bck2brwsr/htmlpage/TestPage.html Tue Mar 05 18:47:29 2013 +0100
8.2 +++ b/javaquery/api/src/test/resources/org/apidesign/bck2brwsr/htmlpage/TestPage.html Tue Mar 05 19:00:36 2013 +0100
8.3 @@ -26,5 +26,6 @@
8.4 <body>
8.5 New title: <input id="pg.text"/>
8.6 <button id="pg.button">Change title!</button>
8.7 + <canvas id="pg.canvas" width="100"/>
8.8 </body>
8.9 </html>