gwtd3 / gwt-d3

A GWT wrapper library around the d3.js library
Other
131 stars 53 forks source link

Is it possible to use gwt-d3 for Java desktop applications? #124

Open stefaneidelloth opened 8 years ago

stefaneidelloth commented 8 years ago

Hello, I would like to use D3 in an Eclipse Plugin and I plan to do it with a JavaFx WebEngine that communicates to JavaScript 1. I never used gwt nor D3 before and I wonder If gwt-d3 could be a full alternative to wrap D3 in my Java desktop application or if gwt-d3 could work in combination with the JavaFx WebEngine. Would you recommend to reuse some of your code or to start from scratch? Sunny regards, Stefan

anthonime commented 8 years ago

Hi Stefan,

I have not a direct answer to your question since I don't know what it is possible to do with JavaFx webengine. But if I were you I would do the following actions in order to eliminate one by one the uncertainity: 1) does JavaFx WebEngine support the Javascript's API required by d3.js ? ==> just try to wrap one or two bostock snippets provided here http://bl.ocks.org/mbostock in an empty Javafx WebEngine project 2) does JavaFx WebEngine support SVG rendering ? ==> same as 1) but try a snippet with SVG tags 3) how can I use GWT and JavaFX together ? ==> I don't think it is possible but I don't know neither JavaFX nor WebEngine... but maybe you can create a normal GWT application that you deploy somewhere, and then include this webpage in an iframe inside you WebEngine/JavaFX project ?

stefaneidelloth commented 8 years ago

Hi Anthony ,

thank you for your answer. I already managed to communicate with d3 from within JavaFx and the points 1)...2) are fine. The WebEngine gives me an object d3Obj of type JSObject that corresponds to the d3 JavaScript object. And I have the possibility to invoke JavaScript methods on that Java object, passing the method name as String argument: JSObject chart= (JSObject) d3Obj.call("select", ".chart");

Instead of using that method invocation stuff for each call I would prefer some neat wrapping classes. In the meanwhile I also wrote a stackoverflow question where I put a few more details:

https://stackoverflow.com/questions/32510744/how-to-create-a-javascript-wrapper-to-be-used-with-javafx-webview-is-jsni-an-op

I also found the project http://dexvis.com, where Patrick Martin somehow calls d3 from JavaFx. Unfortunately that project is not open source and he did not yet answer to my eMail.

After reading more about GWT I currently see two options for point 3): I. Create something like the debug mode for GWT and use some magic to plug in the JavaFx WebEngine in that work flow. Since the debug mode for GWT seems to be quite complex I do not want to try that one. II. Tranform the gwt-d3 code with some search and replace operations & regular expression ... and some (a lot of?) manual fine tuning ... in a new GitHub project.

A code section

public static final native Selection select(String selector)/-{ return $wnd.d3.select(selector); }-/;

from D3.java would be transformed in something like (using generics might make it shorter.)

public static final Selection select(String selector) { JSObject resultObj = invoke("select", selector); Selection result = new Selection(webEngine, resultObj); return result; };

Each of the transformed classes would inherit from an abstract base class that:

If I would succeed with option II. and get all that working... how should I handle your copyright notices in the class files? I would add my name, update the date and leave the rest as is?

/**

A third option might be to change gwt-d3 to some hybrid code that would work for both, GWT and JavaFx. However I do not know if JSNI would allow that .... and it would add some significant overhead to your project, I guess. Unfortunately the native code is not given with annotations but as comments.

public static final native Selection select(String selector) { if (javaFxModeIsActive) { delegateWorkToBaseClass(webEngine, "select", selector) } } /-{ return $wnd.d3.select(selector); }-/;

Best regards,

Stefan

anthonime commented 8 years ago

Stefan,

The third option (JSNI + java implementation in the same time) for sure will not compile (neither in the Java compiler nor in the GWT compiler): a "native" method must not have an implementation.

Even if it's not ideal, I would go to the 2nd option. You can do whatever you like with the copiright notices (even drop them), but please just mention (if you open source the code) that you based your work on the gwt-d3 codebase (with a link).

stefaneidelloth commented 8 years ago

Thanks a lot! Today I created my first chart and the transformation from gwt-d3 to javafx-d3 seems to work so far. After finishing the remaining classes ... will me take a few days... I'll create a new GitHub project and link it here. Below is a Java snippet from an example that is already working.

private void executeJavaScript() {

    //inject d3 into web engine
    String d3Content = getD3Content("d3.js");
    webEngine.executeScript(d3Content);

    //create d3 wrapper 
    D3 d3 = new D3(webEngine);

    //do some example d3 stuff  
    Double[] data = { 4.0, 8.0, 15.0, 16.0, 23.0, 42.0 };

    Double width = 420.0;
    Double barHeight = 20.0;        
    Double maxX = Collections.max(Arrays.asList(data));             

    LinearScale x = d3.scale()
            .linear()
            .domain(0.0, maxX)
            .range(0.0, width); 

    d3.createJsVariable("x", x);

    Selection chart = d3.select(".chart")
            .attr("width", width)
            .attr("height", barHeight * data.length);       

    String expression = "function(d, i) { return \"translate(0,\" + i *" + barHeight + " + \")\"; }";   

    Selection bar = chart.selectAll("g")
            .data(data)
            .enter()
            .append("g")
            .attrExpression("transform", expression);

    bar.append("rect")
    .attr("width", x)
    .attr("height", barHeight - 1); 

    bar.append("text")
     .attrExpression("x", "function(d) { return x(d) - 3; }")
     .attr("y", barHeight / 2)
     .attr("dy", ".35em")
     .textExpression("function(d) { return d; }");
} 
stefaneidelloth commented 8 years ago

Hi Anthony , here is the new project: https://github.com/stefaneidelloth/javafx-d3 If you would like to change the way how the gwt-d3 project is referenced (e.g. include your name or change the license information), please let me know. Sunny regards, Stefan