september 28, 2010

TopComponent Actions in a Flamingo Ribbonband

TopComponent Actions in a Flamingo Ribbonband

I recently added Flamingo to my RCP application using the OfficeLAF module. Now I wanted to add all my Topcomponents from the Window menu to a Ribbonband. I will add a blog post later about how to integrate OfficeLAF into a NetBeans RCP application.

I found two ways to do this. One that requires separate Actions to be created for each Topcomponent and the other that doesn't require any changes to the default TopcomponentActions in layer.xml

To use the later way we can use a Lookup to get all Actions from the Window menu but this gives us also the "Close window" "Reset Windows" actions aswell. But I found out that our actions are of the class AlwaysEnabledAction. Unfortuneatly this class is private so it can't be used in a instanceof if-statement. My solution to this was to use the name from NBBundle to find the correct Actions by the name.

JRibbonBand band = new JRibbonBand(NbBundle.getMessage(VCA2Ribbon.class, "WINDOWS"),new EmptyResizableIcon(32)); Collection<extends Action> actions = Lookups.forPath("Actions/Window";).lookupAll(Action.class);
List<String> myTopComponents = Arrays.asList(getMessageFromBundle("CTL_MyEditorAction"), getMessageFromBundle("CTL_MyPropertiesAction";));

After launching the application the Ribbon will look like below and when you click the icons the TopComponent will be opened up just like it would when selected in the Window menu.Now I can use the collection to match the name of the actions.

for (Action action : actions) { if (myTopComponents.contains(ActionUtil.lookupText(action))) { band.addCommandButton(new BoundCommandButton(JCommandButton.CommandButtonKind.ACTION_ONLY, ActionUtil.lookupText(action), ActionUtil.lookupDescription(action), ActionUtil.lookupIcon(action), ActionUtil.lookupIcon(action, true), action), RibbonElementPriority.TOP);

The other way

The other way I found was to create Actions that extends AbstractAction for each of my TopComponents calling them by the root name of the TopComponent without the TopComponent-part. So if the TopComponent is called MyEditorTopComponent create a class called MyEditorAction.

An empty interface also has to be created that we will use to match the actions against.

public interface MyAction { }
public class MyEditorAction extends AbstractAction implements MyAction{ public MyEditorAction() { super(NbBundle.getMessage(MyEditorAction.class, "CTL_ MyEditorAction";)); putValue(SMALL_ICON, new ImageIcon(ImageUtilities.loadImage(MyEditorTopComponent.ICON_PATH, true))); } @Override public void actionPerformed(ActionEvent e) { TopComponent win = MyEditorTopComponent.findInstance(); win.open(); win.requestActive(); } }

Edit layer.xml so you only have the file tag left for each topcomponent.

And we are done. Now we need to loop over the actions and add them to the Jribbon.

Collection actions = Utilities.actionsForPath("Actions/Window";); for (Action action : actions) { if (action instanceof MyAction){ band.addCommandButton(new BoundCommandButton(JCommandButton.CommandButtonKind.ACTION_ONLY, ActionUtil.lookupText(action), ActionUtil.lookupDescription(action), ActionUtil.lookupIcon(action), ActionUtil.lookupIcon(action, true), action), RibbonElementPriority.TOP); } }

After launching the application the Ribbon will look like below and when you click the icons the TopComponent will be opened up just like it would when selected in the Window menu.