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 i ]]> Welcome back (you did read the first part of this series?)! Ok, having done a bit of magic to Scene Builder 2.0 ea in the last part of this series, let's go for some more integration. Goal of this part is to get the hierarchy view from Scene Builder running inside the NetBeans navigator view- looking like this

First thing you will need is to publicize the EditorController so it will be available in the global lookup and can be used from the upcoming NavigatorPanel. The following code does this. private MultiViewElementCallback callback; private DataObject dao; private EditorController editorController; private Lookup lkp; private InstanceContent ic; private JFXPanel jfxPanel; public SBFxmlMultiViewElement(Lookup lookup) { Platform.setImplicitExit(false); dao = lookup.lookup(DataObject.class); assert dao != null; ic = new InstanceContent(); lkp = new AbstractLookup(ic); } @Override public JComponent getVisualRepresentation() { if (null == 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 { editorController = new EditorController(); Node node = new AbstractNode(Children.LEAF, Lookups.fixed(editorController)); ic.add(node); 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 Lookup getLookup() { return lkp; } Since we do not want the Scene Builder navigator view to show up in the normal XML based MultiViewElement, it is necessary to create a replacment NavigatorLookupHint. The following code (living in the same file as above code) creates a hint for the a synthetic content type called "text/scenebuilder" - I am sure there is a better content type name (names are hard), but it does what is necessary. class SBTypeLookupHint implements NavigatorLookupHint { public String getContentType () { return "text/scenebuilder"; } } Now add an instance of this hint to the lookup. Change the constructor as follows: public SBFxmlMultiViewElement(Lookup lookup) { Platform.setImplicitExit(false); dao = lookup.lookup(DataObject.class); assert dao != null; ic = new InstanceContent(); ic.add(new SBTypeLookupHint()); lkp = new AbstractLookup(ic); } Based on this we can now create the NavigatorPanel @NavigatorPanel.Registration(displayName = "Hierarchy", mimeType = "text/scenebuilder") public class FxmlNavigator implements NavigatorPanel, LookupListener { private JFXPanel panel = new JFXPanel(); private Lookup lkp; private InstanceContent ic; private Lookup.Result editorControllerResult; public FxmlNavigator() { ic = new InstanceContent(); lkp = new AbstractLookup(ic); } @Override public String getDisplayName() { return "Hierarchy"; } @Override public String getDisplayHint() { return "Hierarchy Hint"; } @Override public JComponent getComponent() { return panel; } @Override public void panelActivated(Lookup lkp) { editorControllerResult = lkp.lookupResult(EditorController.class); editorControllerResult.addLookupListener(this); resultChanged(new LookupEvent(editorControllerResult)); } @Override public void panelDeactivated() { } @Override public Lookup getLookup() { return lkp; } @Override public void resultChanged(LookupEvent le) { final Optional optionalController = editorControllerResult.allInstances().stream().findFirst(); if (optionalController.isPresent()) { Platform.runLater(new Runnable() { @Override public void run() { HierarchyPanelController h = new HierarchyPanelController(optionalController.get()); final BorderPane pane = new BorderPane(); pane.setCenter(h.getPanelRoot()); Scene scene = new Scene(pane); panel.setScene(scene); } }); } } } I am sure the code can be improved - just let me know and create a pull request ;-) 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 further integration steps - maybe palette or property sheet.