Allow multi-value @OnClick ids
authorJaroslav Tulach <jaroslav.tulach@apidesign.org>
Tue, 30 Oct 2012 12:23:13 +0100
changeset 124a5f8cb32549e
parent 123 2085fbe399b6
child 125 981e5fd8c813
Allow multi-value @OnClick ids
htmlpage/src/main/java/org/apidesign/bck2brwsr/htmlpage/PageProcessor.java
htmlpage/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/OnClick.java
htmlpage/src/test/java/org/apidesign/bck2brwsr/htmlpage/PageController.java
htmlpage/src/test/java/org/apidesign/bck2brwsr/htmlpage/ProcessPageTest.java
     1.1 --- a/htmlpage/src/main/java/org/apidesign/bck2brwsr/htmlpage/PageProcessor.java	Tue Oct 30 09:26:54 2012 +0100
     1.2 +++ b/htmlpage/src/main/java/org/apidesign/bck2brwsr/htmlpage/PageProcessor.java	Tue Oct 30 12:23:13 2012 +0100
     1.3 @@ -39,6 +39,7 @@
     1.4  import javax.lang.model.element.Modifier;
     1.5  import javax.lang.model.element.PackageElement;
     1.6  import javax.lang.model.element.TypeElement;
     1.7 +import javax.lang.model.type.TypeMirror;
     1.8  import javax.tools.Diagnostic;
     1.9  import javax.tools.FileObject;
    1.10  import javax.tools.StandardLocation;
    1.11 @@ -138,6 +139,7 @@
    1.12      }
    1.13  
    1.14      private boolean initializeOnClick(PackageElement pe, Writer w, ProcessPage pp) throws IOException {
    1.15 +        TypeMirror stringType = processingEnv.getElementUtils().getTypeElement("java.lang.String").asType();
    1.16          for (Element clazz : pe.getEnclosedElements()) {
    1.17              if (clazz.getKind() != ElementKind.CLASS) {
    1.18                  continue;
    1.19 @@ -146,28 +148,40 @@
    1.20              for (Element method : clazz.getEnclosedElements()) {
    1.21                  OnClick oc = method.getAnnotation(OnClick.class);
    1.22                  if (oc != null) {
    1.23 -                    if (pp.tagNameForId(oc.id()) == null) {
    1.24 -                        processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "id = " + oc.id() + " does not exist in the HTML page. Found only " + pp.ids(), method);
    1.25 -                        return false;
    1.26 -                    }
    1.27 -                    ExecutableElement ee = (ExecutableElement)method;
    1.28 -                    if (!ee.getParameters().isEmpty()) {
    1.29 -                        processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "@OnClose method can't take arguments", ee);
    1.30 -                        return false;
    1.31 -                    }
    1.32 -                    if (!ee.getModifiers().contains(Modifier.STATIC)) {
    1.33 -                        processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "@OnClose method has to be static", ee);
    1.34 -                        return false;
    1.35 -                    }
    1.36 -                    if (ee.getModifiers().contains(Modifier.PRIVATE)) {
    1.37 -                        processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "@OnClose method can't be private", ee);
    1.38 -                        return false;
    1.39 -                    }
    1.40 -                    w.append("  ").append(cnstnt(oc.id())).
    1.41 -                        append(".addOnClick(new Runnable() { public void run() {\n");
    1.42 -                    w.append("    ").append(type.getSimpleName().toString()).
    1.43 -                        append('.').append(ee.getSimpleName()).append("();\n");
    1.44 -                    w.append("  }});\n");
    1.45 +                    for (String id : oc.id()) {
    1.46 +                        if (pp.tagNameForId(id) == null) {
    1.47 +                            processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "id = " + oc.id() + " does not exist in the HTML page. Found only " + pp.ids(), method);
    1.48 +                            return false;
    1.49 +                        }
    1.50 +                        ExecutableElement ee = (ExecutableElement)method;
    1.51 +                        boolean hasParam;
    1.52 +                        if (ee.getParameters().isEmpty()) {
    1.53 +                            hasParam = false;
    1.54 +                        } else {
    1.55 +                            if (ee.getParameters().size() != 1 || ee.getParameters().get(0).asType() != stringType) {
    1.56 +                                processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "@OnClick method should either have no arguments or one String argument", ee);
    1.57 +                                return false;
    1.58 +                            }
    1.59 +                            hasParam = true;
    1.60 +                        }
    1.61 +                        if (!ee.getModifiers().contains(Modifier.STATIC)) {
    1.62 +                            processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "@OnClick method has to be static", ee);
    1.63 +                            return false;
    1.64 +                        }
    1.65 +                        if (ee.getModifiers().contains(Modifier.PRIVATE)) {
    1.66 +                            processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "@OnClick method can't be private", ee);
    1.67 +                            return false;
    1.68 +                        }
    1.69 +                        w.append("  ").append(cnstnt(id)).
    1.70 +                            append(".addOnClick(new Runnable() { public void run() {\n");
    1.71 +                        w.append("    ").append(type.getSimpleName().toString()).
    1.72 +                            append('.').append(ee.getSimpleName()).append("(");
    1.73 +                        if (hasParam) {
    1.74 +                            w.append("\"").append(id).append("\"");
    1.75 +                        }
    1.76 +                        w.append(");\n");
    1.77 +                        w.append("  }});\n");
    1.78 +                    }           
    1.79                  }
    1.80              }
    1.81          }
     2.1 --- a/htmlpage/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/OnClick.java	Tue Oct 30 09:26:54 2012 +0100
     2.2 +++ b/htmlpage/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/OnClick.java	Tue Oct 30 12:23:13 2012 +0100
     2.3 @@ -30,5 +30,5 @@
     2.4  @Retention(RetentionPolicy.SOURCE)
     2.5  @Target(ElementType.METHOD)
     2.6  public @interface OnClick {
     2.7 -    String id();
     2.8 +    String[] id();
     2.9  }
     3.1 --- a/htmlpage/src/test/java/org/apidesign/bck2brwsr/htmlpage/PageController.java	Tue Oct 30 09:26:54 2012 +0100
     3.2 +++ b/htmlpage/src/test/java/org/apidesign/bck2brwsr/htmlpage/PageController.java	Tue Oct 30 12:23:13 2012 +0100
     3.3 @@ -46,4 +46,12 @@
     3.4      static void updateTitle() {
     3.5          TestPage.PG_TITLE.setText("You want this window to be named " + TestPage.PG_TEXT.getValue());
     3.6      }
     3.7 +    
     3.8 +    @OnClick(id={ "pg.title", "pg.text" })
     3.9 +    static void click(String id) {
    3.10 +        if (!id.equals("pg.title")) {
    3.11 +            throw new IllegalStateException();
    3.12 +        }
    3.13 +        TestPage.PG_TITLE.setText(id);
    3.14 +    }
    3.15  }
     4.1 --- a/htmlpage/src/test/java/org/apidesign/bck2brwsr/htmlpage/ProcessPageTest.java	Tue Oct 30 09:26:54 2012 +0100
     4.2 +++ b/htmlpage/src/test/java/org/apidesign/bck2brwsr/htmlpage/ProcessPageTest.java	Tue Oct 30 12:23:13 2012 +0100
     4.3 @@ -81,6 +81,45 @@
     4.4          }
     4.5          assertEquals(ret, "You want this window to be named something", "We expect that the JavaCode performs all the wiring");
     4.6      }
     4.7 +    
     4.8 +    @Test public void clickWithArgumentCalled() throws Exception {
     4.9 +        StringBuilder sb = new StringBuilder();
    4.10 +        sb.append(
    4.11 +              "var window = new Object();\n"
    4.12 +            + "var doc = new Object();\n"
    4.13 +            + "doc.button = new Object();\n"
    4.14 +            + "doc.title = new Object();\n"
    4.15 +            + "doc.title.innerHTML = 'nothing';\n"
    4.16 +            + "doc.text = new Object();\n"
    4.17 +            + "doc.text.value = 'something';\n"
    4.18 +            + "doc.getElementById = function(id) {\n"
    4.19 +            + "    switch(id) {\n"
    4.20 +            + "      case 'pg.button': return doc.button;\n"
    4.21 +            + "      case 'pg.title': return doc.title;\n"
    4.22 +            + "      case 'pg.text': return doc.text;\n"
    4.23 +            + "    }\n"
    4.24 +            + "    throw id;\n"
    4.25 +            + "  }\n"
    4.26 +            + "\n"
    4.27 +            + "function clickAndCheck() {\n"
    4.28 +            + "  doc.title.onclick();\n"
    4.29 +            + "  return doc.title.innerHTML.toString();\n"
    4.30 +            + "};\n"
    4.31 +            + "\n"
    4.32 +            + "window.document = doc;\n"
    4.33 +        );
    4.34 +        Invocable i = compileClass(sb, "org/apidesign/bck2brwsr/htmlpage/PageController");
    4.35 +
    4.36 +        Object ret = null;
    4.37 +        try {
    4.38 +            ret = i.invokeFunction("clickAndCheck");
    4.39 +        } catch (ScriptException ex) {
    4.40 +            fail("Execution failed in " + sb, ex);
    4.41 +        } catch (NoSuchMethodException ex) {
    4.42 +            fail("Cannot find method in " + sb, ex);
    4.43 +        }
    4.44 +        assertEquals(ret, "pg.title", "Title has been passed to the method argument");
    4.45 +    }
    4.46  
    4.47      static Invocable compileClass(StringBuilder sb, String... names) throws ScriptException, IOException {
    4.48          if (sb == null) {