Skip to main content

Embedding JavaFX Scene Builder 2.0 ea in NetBeans - Part 1

Posted by sven on December 1, 2013 at 5:30 AM PST

Tired of JavaFX Scene Builder being run in a separate process? Fed up with no real integration between your favorite IDE and JavaFX Scene Builder? There may be a solution heading towards you. Follow this small series of blog entries to join me on my journey towards an embedded JavaFX Scene Builder in NetBeans.

Finally, with the new developer preview builds of JavaFX Scene Builder 2.0 a new important change was introduced. The new version contains the so called "JavaFX Scene Builder Kit". The Release notes state that "JavaFX Scene Builder Kit is an API that allows the integration of Scene Builder panels and functionalities directly into the GUI of a larger application, or a Java IDE, such as NetBeans, IntelliJ, and Eclipse."

Having read this during Devoxx, I started looking into the documentation how to get started with the integration. Really excited about the possibilities I fired up my IDE and started throwing together some lines of code to just open up the main view of JavaFX SceneBuilder inside NetBeans. After fiddling a bit with the threading (a lot of things still have to be executed on the JavaFX Thread) I finally got to the point where the view should open. Yes should - bummer some exception "No such Method" was blocking me from seeing the result.

I asked about this problem on the OpenJFX mailing list (remember to join, if you are interested in JavaFX - it is a great source for information on what is going on). I got the confirmation that my JDK 8 ea build was too new and due to a small API change incompatible with Scene Builder 2.0 Early Access. So some more waiting....

Finally, I got pinged a couple of days ago, that with a new build of the developer peview this problem should now be gone. Great! So back to where I left the prototype, some more fiddling and I had my first TopComponent showing the JavaFX Scene Builder main view.

But somehow this still was a bit of a mess, so I decided to start going the full nine yards. NetBeans has some nice feature, it is called a MultiView. It allows you to register special views called MultiViewElement's for the same file type. So I registered my completely rewritten dirty prototype code as a MultiViewElement - and (drumroll) - see the result




The necessary code is quite simple (once you figure out some of the details ;-) )

@MultiViewElement.Registration(displayName = "#LBL_SceneBuilder",
        mimeType = "text/x-fxml+xml",
        persistenceType = TopComponent.PERSISTENCE_NEVER,
        preferredID = "SceneBuilder",
        position = 3000)
@NbBundle.Messages({
    "LBL_SceneBuilder=Visual"
})
public class SBFxmlMultiViewElement implements MultiViewElement {

    private MultiViewElementCallback callback;
    private DataObject dao;

    public SBFxmlMultiViewElement(Lookup lkp) {
        dao = lkp.lookup(DataObject.class);
        assert dao != null;
    }

    @Override
    public JComponent getVisualRepresentation() {
        final JFXPanel jfxPanel = new JFXPanel();
        try {
            final File fxmlFile = FileUtil.toFile(dao.getPrimaryFile());
            final String fxmlText = readContentFromFile(fxmlFile);
            final URL fxmlLocation = fxmlFile.toURI().toURL();
            Platform.runLater(new Runnable() {

                @Override
                public void run() {
                    try {
                        final EditorController editorController = new EditorController();
                        ContentPanelController contentPanelController = new ContentPanelController(editorController);
                        final BorderPane pane = new BorderPane();
                        pane.setCenter(contentPanelController.getPanelRoot());
                        Scene scene = new Scene(pane);
                        jfxPanel.setScene(scene);
                        editorController.setFxmlTextAndLocation(fxmlText, fxmlLocation);
                    } catch (IOException ex) {
                        Exceptions.printStackTrace(ex);
                    }
                }
            });


        } catch (IOException ex) {
            Exceptions.printStackTrace(ex);
        }
        return jfxPanel;
    }

    @Override
    public JComponent getToolbarRepresentation() {
        return new JPanel();
    }

    @Override
    public Action[] getActions() {
        return new Action[]{};
    }

    @Override
    public Lookup getLookup() {
        return Lookup.EMPTY;
    }

    @Override
    public void componentOpened() {
    }

    @Override
    public void componentClosed() {
    }

    @Override
    public void componentShowing() {
    }

    @Override
    public void componentHidden() {
    }

    @Override
    public void componentActivated() {
    }

    @Override
    public void componentDeactivated() {
    }

    @Override
    public UndoRedo getUndoRedo() {
        return UndoRedo.NONE;
    }

    @Override
    public void setMultiViewCallback(MultiViewElementCallback callback) {
        this.callback = callback;
    }

    @Override
    public CloseOperationState canCloseElement() {
        return CloseOperationState.STATE_OK;
    }

    private static String readContentFromFile(File file) throws IOException {
        final byte[] buffer;

        buffer = new byte[(int) file.length()];
        try (DataInputStream is = new DataInputStream(new FileInputStream(file))) {
            is.readFully(buffer);
        }

        return new String(buffer, Charset.forName("UTF-8"));
    }

}

Now you ask - can I download this magic plugin somewhere? The legal disclaimer from Oracle keeps me from redistributing the necessary SceneBuilderKit.jar. Sorry, you have to do it on your own. Get the sources from Bitbucket and try it out. The one thing you have to do is get Scene Builder 2.0 Early Access and put SceneBuilderKit.jar into the right directory (hint there is a file indicating, which one it is).

Stay tuned for the next part of this series, showing how to get the navigation integrated.

AttachmentSize
Initial Prototype of embedding JavaFX Scene Builder in NetBeans338.64 KB