I want to use the javascript framework rete inside my javafx application. I have an example code that works when opened in the browser. When I load this in my javafx application via webview, the visuals are displayed fine but it isn't interactive. For example I can't click on the dots to create new lines, can't move things around, etc. When I try to move stuff or create a line, I end up highlighting the text. Another weird thing is when I scroll the mousewheel to zoom out it zooms in and is flipped.

I looked at alternative browsers I could use but the only one I could find was jcef which doesn't work with javafx.

My Main Class:

    public static void main(String[] args) {
        launch(args);
    }

    public void start(Stage primaryStage) {
        primaryStage.setTitle("JavaFX WebView Example");

        WebView webView = new WebView();
        WebEngine webEngine = webView.getEngine();
        webEngine.load(Main.class.getResource("index.html").toString());

        VBox vBox = new VBox(webView);
        Scene scene = new Scene(vBox, 960, 600);

        primaryStage.setScene(scene);
        primaryStage.show();

    }

index.html

<!DOCTYPE html>
<html lang="en" >

<head>
  <meta charset="UTF-8">
  <title>Rete.js (dataflow, node editor)</title>



      <link rel="stylesheet" href="css/style.css">


</head>

<body>

  <div id="rete"></div>

<a target="_blank" href="https://github.com/retejs/rete"><img style="position: absolute; top: 0; right: 0; border: 0;" src="https://camo.githubusercontent.com/652c5b9acfaddf3a9c326fa6bde407b87f7be0f4/68747470733a2f2f73332e616d617a6f6e6177732e636f6d2f6769746875622f726962626f6e732f666f726b6d655f72696768745f6f72616e67655f6666373630302e706e67" alt="Fork me on GitHub" data-canonical-src="https://s3.amazonaws.com/github/ribbons/forkme_right_orange_ff7600.png"></a>
  <script src='https://cdn.jsdelivr.net/npm/[email protected]/build/rete.min.js'></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.min.js'></script>
<script src='https://cdn.jsdelivr.net/npm/[email protected]/build/vue-render-plugin.min.js'></script>
<script src='https://cdn.jsdelivr.net/npm/[email protected]/build/connection-plugin.min.js'></script>
<script src='https://cdn.jsdelivr.net/npm/[email protected]/alight.min.js'></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js'></script>
<script src='https://cdn.jsdelivr.net/npm/[email protected]/build/context-menu-plugin.min.js'></script>
<script src='https://cdn.jsdelivr.net/npm/[email protected]/build/area-plugin.min.js'></script>
<script src='https://cdn.jsdelivr.net/npm/[email protected]/build/comment-plugin.min.js'></script>
<script src='https://cdn.jsdelivr.net/npm/[email protected]/build/history-plugin.min.js'></script>
<script src='https://cdn.jsdelivr.net/npm/[email protected]/build/connection-mastery-plugin.min.js'></script>



    <script  src="js/index.js"></script>




</body>

</html>

Index.js:

var numSocket = new Rete.Socket('Number value');

var VueNumControl = {
  props: ['readonly', 'emitter', 'ikey', 'getData', 'putData'],
  template: '<input type="number" :readonly="readonly" :value="value" @input="change($event)" @dblclick.stop="" @pointermove.stop=""/>',
  data() {
    return {
      value: 0,
    }
  },
  methods: {
    change(e){
      this.value = +e.target.value;
      this.update();
    },
    update() {
      if (this.ikey)
        this.putData(this.ikey, this.value)
      this.emitter.trigger('process');
    }
  },
  mounted() {
    this.value = this.getData(this.ikey);
  }
}

class NumControl extends Rete.Control {

  constructor(emitter, key, readonly) {
    super(key);
    this.component = VueNumControl;
    this.props = { emitter, ikey: key, readonly };
  }

  setValue(val) {
    this.vueContext.value = val;
  }
}

class NumComponent extends Rete.Component {

    constructor(){
        super("Number");
    }

    builder(node) {
        var out1 = new Rete.Output('num', "Number", numSocket);

        return node.addControl(new NumControl(this.editor, 'num')).addOutput(out1);
    }

    worker(node, inputs, outputs) {
        outputs['num'] = node.data.num;
    }
}

class AddComponent extends Rete.Component {
    constructor(){
        super("Add");
    }

    builder(node) {
        var inp1 = new Rete.Input('num1',"Number", numSocket);
        var inp2 = new Rete.Input('num2', "Number2", numSocket);
        var out = new Rete.Output('num', "Number", numSocket);

        inp1.addControl(new NumControl(this.editor, 'num1'))
        inp2.addControl(new NumControl(this.editor, 'num2'))

        return node
            .addInput(inp1)
            .addInput(inp2)
            .addControl(new NumControl(this.editor, 'preview', true))
            .addOutput(out);
    }

    worker(node, inputs, outputs) {
        var n1 = inputs['num1'].length?inputs['num1'][0]:node.data.num1;
        var n2 = inputs['num2'].length?inputs['num2'][0]:node.data.num2;
        var sum = n1 + n2;

        this.editor.nodes.find(n => n.id == node.id).controls.get('preview').setValue(sum);
        outputs['num'] = sum;
    }
}

(async () => {
    var container = document.querySelector('#rete');
    var components = [new NumComponent(), new AddComponent()];

    var editor = new Rete.NodeEditor('[email protected]', container);
    editor.use(ConnectionPlugin.default);
    editor.use(VueRenderPlugin.default);    
    let readyMenu = [10, 12, 14];
    let dontHide = ['click'];
    editor.use(ContextMenuPlugin.default);
    editor.use(AreaPlugin);
    editor.use(CommentPlugin.default);
    editor.use(HistoryPlugin);
    editor.use(ConnectionMasteryPlugin.default);

    var engine = new Rete.Engine('[email protected]');

    components.map(c => {
        editor.register(c);
        engine.register(c);
    });

    var n1 = await components[0].createNode({num: 2});
    var n2 = await components[0].createNode({num: 0});
    var add = await components[1].createNode();

    n1.position = [80, 200];
    n2.position = [80, 400];
    add.position = [500, 240];


    editor.addNode(n1);
    editor.addNode(n2);
    editor.addNode(add);

    editor.connect(n1.outputs.get('num'), add.inputs.get('num1'));
    editor.connect(n2.outputs.get('num'), add.inputs.get('num2'));


    editor.on('process nodecreated noderemoved connectioncreated connectionremoved', async () => {
      console.log('process');
        await engine.abort();
        await engine.process(editor.toJSON());
    });

    editor.view.resize();
    AreaPlugin.zoomAt(editor);
    editor.trigger('process');
})();

Style.css:

  height: 100%;
  width: 100%;
}

.node .control input, .node .input-control input {
  width: 140px;
}

select, input {
  width: 100%;
  border-radius: 30px;
  background-color: white;
  padding: 2px 6px;
  border: 1px solid #999;
  font-size: 110%;
  width: 170px;
}

I want it behave the way it works when I opened the file in the browser where I can move the elements around, connect the elements, zoom in/out, move, etc.

Thanks for your help

0 Answers