When the CTree control detects that a popup menu needs to be displayed, it calls the instance of the CTreeNode and asks it for a list of items to display in the context menu. The following are rules or guidelines for how CTreeNode objects should build this array:
The signature for the CTreeNode method is:
public Component[] getContextMenuItems();
Even though this method is declared to return an array of Component objects, it is highly recommended that the objects returned all be instances of the JMenuItem class (or classes derived from JMenuItem).
The state of any menu items returned from the getContextMenuItems() method must be properly initialized; that is, enabled/disabled, checked.
The JMenuItem objects (or whatever objects) must be properly linked to the specific CTreeNode object that is being called. The event passed in the actionPerformed() call will contain none of this contextual information.
The CTree then calls each plug-in, retrieving any additional menu items for the specified CTreeNode object. If there are additional items, the CTree places a separator after the original menu items, then places all of the plug-in items in the popup menu, and then, if the CTreeNode can be put on custom views, puts another separator and the menu items related to custom views.
For a plug-in to respond to the CTree properly in this case, add a class called ConsoleTreeHandler to the plug-in root package. In our example, this would be com.MyPlugin.ConsoleTreeHandler. Add a method called “getContextMenuItemsFor()” to this class. The source code could look something like the following example:
public static Component[] getContextMenuItmsFor(CTreeNode node) { // strictly speaking, this check for null should never be // necessary if (node == null) return new Component[0]; if (node instanceof SomeSpecificTreeNode) { JMenuItem theItem = new JMenuItem("Walk"); JMenuItem anotherItem = new JMenuItem("Don't walk"); theItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { // take action here. } } return new Component[] { theItem, anotherItem }; } else if (node instanceof SomeOtherTreeNode) { // different set of menu items here. } // and if we're not interested in any other types. return new Component[0]. }
Items of interest for this operation:
This method can be declared to return anything. For instance, for better type safety within your own code, you could declare the method to be “public static JMenuItem[] getContextMenuItemsFor(CTreeNode node)”; however, the CTree object making the call will only use items that are derived from the Component class.
This example is very bare bones; for instance, the returned JMenuItem object does not know which CTreeNode object it should be working with; even worse, one of the items does not have an action listener associated with it. For a complete example of this, please see the sample plug-ins developed by the Administration Services development team.
CTreeNode (being derived from DefaultMutableTreeNode) objects have a user object. This is available through the getUserObject() method. The intent is that the user object for a node represents that data that the node has been created for and this is the data that would need to be associated with the menu item. For instance, a node might have an object representing an Essbase application. In the above example, we would then perform a node.getUserObject() call to obtain this Essbase application object
Because plug-ins are called in the order that the user has arranged them in the Component Manager dialog box, there currently is no way to force the menu items from one plug-in to appear before the menu items of another plug-in.