Geertjan is a DZone Zone Leader and has posted 467 posts at DZone. You can read more from them at their website. View Full User Profile

How to Integrate JavaFX into the NetBeans Platform Toolbar

04.26.2013
| 3695 views |
  • submit to reddit

Next up, now that we know how to replace the NetBeans Platform menubar with a new one from JavaFX (see yesterday's article on this theme), let's see how to achieve the same for the toolbar:

The toolbar above not only uses JavaFX, but is also tabbed. So, specifically, the JavaFX classes TabPane, Pane, ToolBar, and Button are used in combination with Actions loaded from the NetBeans Platform filesystem's "Toolbars" folder, within a JFXPanel, which is placed in the RootPane of the NetBeans Platform, using a layout made available by the instructions provided by Chris Böhme from PinkMatter, as described in detail, with code, here:

http://netbeans.dzone.com/how-create-tabbed-toolbar-on-nb

Therefore, the starting point for creating the result shown in the screenshot above is to get all the code described in the link above into a NetBeans module. That means you'll have an Installer class and a MyRootPaneLayout class.

However, the ToolbarComponentProvider class is pretty different:

public abstract class ToolbarComponentProvider {

    public abstract JComponent createToolbar();

    public static ToolbarComponentProvider getDefault() {
        ToolbarComponentProvider provider =
                Lookup.getDefault().lookup(ToolbarComponentProvider.class);
        if (provider == null) {
            provider = new DefaultToolbarComponentProvider();
        }
        return provider;
    }

    private static class DefaultToolbarComponentProvider
            extends ToolbarComponentProvider {
        @Override
        public JComponent createToolbar() {
            final JFXPanel toolbarFXPanel = new JFXPanel();
            Platform.runLater(new Runnable() {
                @Override
                public void run() {
                    Scene scene = new Scene(new VBox(), 400, 70);
                    TabPane pane = new TabPane();
                    FileObject menuFolder = FileUtil.getConfigFile("Toolbars");
                    FileObject[] mainToolBarKids = menuFolder.getChildren();
                    for (FileObject oneMainToolBarKid
                            : FileUtil.getOrder(Arrays.asList(mainToolBarKids), true)) {
                        Tab tab = new Tab(oneMainToolBarKid.getName());
                        ToolBar newToolbarFromFileObject = new ToolBar();
                        tab.setContent(newToolbarFromFileObject);
                        pane.getTabs().add(tab);
                        try {
                            buildToolBarStructure(
                                    oneMainToolBarKid, 
                                    newToolbarFromFileObject);
                        } catch (FileNotFoundException ex) {
                            Exceptions.printStackTrace(ex);
                        }
                    }
                    ((VBox) scene.getRoot()).getChildren().add(pane);
                    toolbarFXPanel.setScene(scene);
                }
            });
            return toolbarFXPanel;
        }
    }

    private static void buildToolBarStructure(
            FileObject oneMainToolBarKid,
            ToolBar newToolbarFromFileObject) throws FileNotFoundException {
        for (FileObject oneSecondLevelToolBarKid : oneMainToolBarKid.getChildren()) {
            final Action instanceObj =
                    FileUtil.getConfigObject(
                    oneSecondLevelToolBarKid.getPath(),
                    Action.class);
            //Name stuff:
            String name = (String) instanceObj.getValue(Action.NAME);
            String cutAmpersand = Actions.cutAmpersand(name);
            //Icon stuff:
            Icon icon = (Icon) instanceObj.getValue(Action.SMALL_ICON);
            ImageView iv = new ImageView();
            //Optionally, include the name in the button:
            //Button toolbarButton = new Button(cutAmpersand);
            Button toolbarButton = new Button();
            if (icon != null) {
                java.awt.Image awtImage = ImageUtilities.icon2Image(icon);
                Image image = new Image(getInputStream(awtImage));
                iv.setImage(image);
                toolbarButton.setGraphic(iv);
            }
            toolbarButton.setOnAction(new EventHandler<ActionEvent>() {
                @Override
                public void handle(final ActionEvent t) {
                    try {
                        SwingUtilities.invokeAndWait(new Runnable() {
                            @Override
                            public void run() {
                                java.awt.event.ActionEvent event =
                                        new java.awt.event.ActionEvent(
                                        t.getSource(),
                                        t.hashCode(),
                                        t.toString());
                                instanceObj.actionPerformed(event);
                            }
                        });
                    } catch (InterruptedException ex) {
                        Exceptions.printStackTrace(ex);
                    } catch (InvocationTargetException ex) {
                        Exceptions.printStackTrace(ex);
                    }
                }
            });
            newToolbarFromFileObject.getItems().add(toolbarButton);
        }
    }

    private static InputStream getInputStream(java.awt.Image image) {
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        InputStream fis = null;
        try {
            ImageIO.write((RenderedImage) image, "png", os);
            fis = new ByteArrayInputStream(os.toByteArray());
        } catch (IOException ex) {
            Exceptions.printStackTrace(ex);
        }
        return fis;
    }

}

That's all. Now you'll have a tabbed toolbar that embeds the JFXPanel and then embeds a TabPane, Pane, and ToolBar, on top of each other, plus a Button for each Action registered in the "Toolbars" folder of the NetBeans Platform filesystem, to attain the result shown in the screenshot at the start of this article.

Published at DZone with permission of its author, Geertjan Wielenga.

Comments

Toni Epple replied on Mon, 2013/05/06 - 11:07pm

 Hi Geertjan,

I'm reading your series on adding JavaFX to NetBeans in many places inside NB Platform. Great idea! I also tried this one, but it seems whenever I press a button the application stalls.

Edit: Ah, found it: it's the invokeAndWait. Replace with invokeLater and it works fine!

Thanks,

Toni

Toni Epple replied on Mon, 2013/05/06 - 11:22pm

Here's some additional code to keep the enabled state. Make toolbarButton final and add:

final Button toolbarButton = new Button();
  SwingUtilities.invokeLater(new Runnable() {
  @Override
  public void run() {
  final boolean enabled = instanceObj.isEnabled();
  Platform.runLater(new Runnable() {
  @Override
  public void run() {
  toolbarButton.setDisable(!enabled);
  }
  });
  }
  });


  instanceObj.addPropertyChangeListener(new PropertyChangeListener() {
  @Override
  public void propertyChange(final PropertyChangeEvent evt) {
  if (evt.getPropertyName().equals("enabled")) {
  Platform.runLater(new Runnable() {
  @Override
  public void run() {
  toolbarButton.setDisable(!(Boolean) evt.getNewValue());
  }
  });
   
  }
  }
  });

Geertjan Wielenga replied on Tue, 2013/05/07 - 12:28am

 Many thanks! I am now also using this solution in the menu bar.

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.