Notify change in computed properties model
authorJaroslav Tulach <jaroslav.tulach@apidesign.org>
Mon, 21 Jan 2013 07:00:56 +0100
branchmodel
changeset 498607f062485cc
parent 496 a06c98795b01
child 499 af027874f93e
Notify change in computed properties
javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/PageProcessor.java
javaquery/demo-calculator/src/main/java/org/apidesign/bck2brwsr/mavenhtml/App.java
javaquery/demo-calculator/src/main/resources/org/apidesign/bck2brwsr/mavenhtml/Calculator.xhtml
     1.1 --- a/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/PageProcessor.java	Sun Jan 20 21:01:46 2013 +0100
     1.2 +++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/PageProcessor.java	Mon Jan 21 07:00:56 2013 +0100
     1.3 @@ -24,8 +24,11 @@
     1.4  import java.util.ArrayList;
     1.5  import java.util.Collection;
     1.6  import java.util.Collections;
     1.7 +import java.util.HashMap;
     1.8 +import java.util.LinkedHashSet;
     1.9  import java.util.List;
    1.10  import java.util.Locale;
    1.11 +import java.util.Map;
    1.12  import java.util.Set;
    1.13  import javax.annotation.processing.AbstractProcessor;
    1.14  import javax.annotation.processing.Completion;
    1.15 @@ -106,8 +109,9 @@
    1.16                      }
    1.17                      w.append("  }\n");
    1.18                      List<String> propsGetSet = new ArrayList<String>();
    1.19 -                    generateProperties(w, p.properties(), propsGetSet);
    1.20 -                    generateComputedProperties(w, e.getEnclosedElements(), propsGetSet);
    1.21 +                    Map<String,Collection<String>> propsDeps = new HashMap<String, Collection<String>>();
    1.22 +                    generateComputedProperties(w, e.getEnclosedElements(), propsGetSet, propsDeps);
    1.23 +                    generateProperties(w, p.properties(), propsGetSet, propsDeps);
    1.24                      w.append("  private static org.apidesign.bck2brwsr.htmlpage.Knockout ko;\n");
    1.25                      if (!propsGetSet.isEmpty()) {
    1.26                          w.write("public static void applyBindings() {\n");
    1.27 @@ -259,7 +263,8 @@
    1.28      }
    1.29  
    1.30      private static void generateProperties(
    1.31 -        Writer w, Property[] properties, Collection<String> props
    1.32 +        Writer w, Property[] properties, Collection<String> props,
    1.33 +        Map<String,Collection<String>> deps
    1.34      ) throws IOException {
    1.35          for (Property p : properties) {
    1.36              final String tn = typeName(p);
    1.37 @@ -271,7 +276,15 @@
    1.38              w.write("}\n");
    1.39              w.write("public static void " + gs[1] + "(" + tn + " v) {\n");
    1.40              w.write("  prop_" + p.name() + " = v;\n");
    1.41 -            w.write("  if (ko != null) ko.valueHasMutated(\"" + p.name() + "\");\n");
    1.42 +            w.write("  if (ko != null) {\n");
    1.43 +            w.write("    ko.valueHasMutated(\"" + p.name() + "\");\n");
    1.44 +            final Collection<String> dependants = deps.get(p.name());
    1.45 +            if (dependants != null) {
    1.46 +                for (String depProp : dependants) {
    1.47 +                    w.write("    ko.valueHasMutated(\"" + depProp + "\");\n");
    1.48 +                }
    1.49 +            }
    1.50 +            w.write("  }\n");
    1.51              w.write("}\n");
    1.52              
    1.53              props.add(p.name());
    1.54 @@ -280,8 +293,9 @@
    1.55          }
    1.56      }
    1.57  
    1.58 -    private void generateComputedProperties(
    1.59 -        Writer w, Collection<? extends Element> arr, Collection<String> props
    1.60 +    private boolean generateComputedProperties(
    1.61 +        Writer w, Collection<? extends Element> arr, Collection<String> props,
    1.62 +        Map<String,Collection<String>> deps
    1.63      ) throws IOException {
    1.64          for (Element e : arr) {
    1.65              if (e.getKind() != ElementKind.METHOD) {
    1.66 @@ -292,16 +306,25 @@
    1.67              }
    1.68              ExecutableElement ee = (ExecutableElement)e;
    1.69              final String tn = ee.getReturnType().toString();
    1.70 -            String[] gs = toGetSet(ee.getSimpleName().toString(), tn);
    1.71 -
    1.72 +            final String sn = ee.getSimpleName().toString();
    1.73 +            String[] gs = toGetSet(sn, tn);
    1.74 +            
    1.75              w.write("public static " + tn + " " + gs[0] + "() {\n");
    1.76              w.write("  return " + e.getEnclosingElement().getSimpleName() + '.' + e.getSimpleName() + "(");
    1.77              String sep = "";
    1.78              for (VariableElement pe : ee.getParameters()) {
    1.79 -                String[] call = toGetSet(pe.getSimpleName().toString(), pe.asType().toString());
    1.80 +                final String dn = pe.getSimpleName().toString();
    1.81 +                String[] call = toGetSet(dn, pe.asType().toString());
    1.82                  w.write(sep);
    1.83                  w.write(call[0] + "()");
    1.84                  sep = ", ";
    1.85 +                
    1.86 +                Collection<String> depends = deps.get(dn);
    1.87 +                if (depends == null) {
    1.88 +                    depends = new LinkedHashSet<String>();
    1.89 +                    deps.put(dn, depends);
    1.90 +                }
    1.91 +                depends.add(sn);
    1.92              }
    1.93              w.write(");\n");
    1.94              w.write("}\n");
    1.95 @@ -310,6 +333,8 @@
    1.96              props.add(gs[2]);
    1.97              props.add(null);
    1.98          }
    1.99 +        
   1.100 +        return true;
   1.101      }
   1.102  
   1.103      private static String[] toGetSet(String name, String type) {
   1.104 @@ -326,11 +351,12 @@
   1.105              pref = "is";
   1.106              bck2brwsrType = "Z";
   1.107          }
   1.108 +        final String nu = n.replace('.', '_');
   1.109          return new String[]{
   1.110              pref + n, 
   1.111              "set" + n, 
   1.112 -            pref + n + "__" + bck2brwsrType,
   1.113 -            "set" + n + "__V" + bck2brwsrType
   1.114 +            pref + nu + "__" + bck2brwsrType,
   1.115 +            "set" + nu + "__V" + bck2brwsrType
   1.116          };
   1.117      }
   1.118  
   1.119 @@ -338,10 +364,7 @@
   1.120          try {
   1.121              return p.type().getName();
   1.122          } catch (MirroredTypeException ex) {
   1.123 -            if (ex.getTypeMirror().getKind().isPrimitive()) {
   1.124 -                return ex.getTypeMirror().toString();
   1.125 -            }
   1.126 -            throw ex;
   1.127 +            return ex.getTypeMirror().toString();
   1.128          }
   1.129      }
   1.130  }
     2.1 --- a/javaquery/demo-calculator/src/main/java/org/apidesign/bck2brwsr/mavenhtml/App.java	Sun Jan 20 21:01:46 2013 +0100
     2.2 +++ b/javaquery/demo-calculator/src/main/java/org/apidesign/bck2brwsr/mavenhtml/App.java	Mon Jan 21 07:00:56 2013 +0100
     2.3 @@ -17,6 +17,7 @@
     2.4   */
     2.5  package org.apidesign.bck2brwsr.mavenhtml;
     2.6  
     2.7 +import org.apidesign.bck2brwsr.htmlpage.api.ComputedProperty;
     2.8  import org.apidesign.bck2brwsr.htmlpage.api.On;
     2.9  import static org.apidesign.bck2brwsr.htmlpage.api.OnEvent.*;
    2.10  import org.apidesign.bck2brwsr.htmlpage.api.Page;
    2.11 @@ -29,34 +30,52 @@
    2.12   * @author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    2.13   */
    2.14  @Page(xhtml="Calculator.xhtml", properties = {
    2.15 -    @Property(name = "display", type = double.class)
    2.16 +    @Property(name = "memory", type = double.class),
    2.17 +    @Property(name = "display", type = double.class),
    2.18 +    @Property(name = "operation", type = String.class),
    2.19 +    @Property(name = "hover", type = boolean.class)
    2.20  })
    2.21  public class App {
    2.22 -    private static double memory;
    2.23 -    private static String operation;
    2.24 -    
    2.25      @On(event = CLICK, id="clear")
    2.26      static void clear() {
    2.27 -        memory = 0;
    2.28 -        operation = null;
    2.29 +        Calculator.setMemory(0);
    2.30 +        Calculator.setOperation(null);
    2.31          Calculator.setDisplay(0);
    2.32      }
    2.33      
    2.34      @On(event = CLICK, id= { "plus", "minus", "mul", "div" })
    2.35      static void applyOp(String op) {
    2.36 -        memory = Calculator.getDisplay();
    2.37 -        operation = op;
    2.38 +        Calculator.setMemory(Calculator.getDisplay());
    2.39 +        Calculator.setOperation(op);
    2.40          Calculator.setDisplay(0);
    2.41      }
    2.42 +
    2.43 +    @On(event = MOUSE_OVER, id= { "result" })
    2.44 +    static void attemptingIn(String op) {
    2.45 +        Calculator.setHover(true);
    2.46 +    }
    2.47 +    @On(event = MOUSE_OUT, id= { "result" })
    2.48 +    static void attemptingOut(String op) {
    2.49 +        Calculator.setHover(false);
    2.50 +    }
    2.51      
    2.52      @On(event = CLICK, id="result")
    2.53      static void computeTheValue() {
    2.54 -        switch (operation) {
    2.55 -            case "plus": Calculator.setDisplay(memory + Calculator.getDisplay()); break;
    2.56 -            case "minus": Calculator.setDisplay(memory - Calculator.getDisplay()); break;
    2.57 -            case "mul": Calculator.setDisplay(memory * Calculator.getDisplay()); break;
    2.58 -            case "div": Calculator.setDisplay(memory / Calculator.getDisplay()); break;
    2.59 -            default: throw new IllegalStateException(operation);
    2.60 +        Calculator.setDisplay(compute(
    2.61 +            Calculator.getOperation(), 
    2.62 +            Calculator.getMemory(), 
    2.63 +            Calculator.getDisplay()
    2.64 +        ));
    2.65 +        Calculator.setMemory(0);
    2.66 +    }
    2.67 +    
    2.68 +    private static double compute(String op, double memory, double display) {
    2.69 +        switch (op) {
    2.70 +            case "plus": return memory + display;
    2.71 +            case "minus": return memory - display;
    2.72 +            case "mul": return memory * display;
    2.73 +            case "div": return memory / display;
    2.74 +            default: throw new IllegalStateException(op);
    2.75          }
    2.76      }
    2.77      
    2.78 @@ -76,10 +95,18 @@
    2.79              Calculator.setDisplay(Double.parseDouble(txt));
    2.80          }
    2.81      }
    2.82 -    
    2.83 +
    2.84 +    @ComputedProperty
    2.85 +    public static String displayPreview(
    2.86 +        double display, boolean hover, double memory, String operation
    2.87 +    ) {
    2.88 +        if (!hover) {
    2.89 +            return "Type numbers and perform simple operations! Press '=' to get result.";
    2.90 +        }
    2.91 +        return "Attempt to compute " + memory + " " + operation + " " + display + " = " + compute(operation, memory, display);
    2.92 +    }
    2.93      
    2.94      static {
    2.95 -        Calculator.setDisplay(10.0);
    2.96          Calculator.applyBindings();
    2.97      }
    2.98  }
     3.1 --- a/javaquery/demo-calculator/src/main/resources/org/apidesign/bck2brwsr/mavenhtml/Calculator.xhtml	Sun Jan 20 21:01:46 2013 +0100
     3.2 +++ b/javaquery/demo-calculator/src/main/resources/org/apidesign/bck2brwsr/mavenhtml/Calculator.xhtml	Mon Jan 21 07:00:56 2013 +0100
     3.3 @@ -76,7 +76,9 @@
     3.4                  </tr>
     3.5              </tbody>
     3.6          </table>
     3.7 -
     3.8 +        <p>
     3.9 +            <div data-bind="text: displayPreview"></div>
    3.10 +        </p>
    3.11          <script src="bootjava.js"/>
    3.12          
    3.13          <hr/>