Adding an item to a menu
The item and the action command
If you are creating an item you surely want it to execute an action. If you flip the switch, you expect it to turn on the lights, either with the switch next to the door or the switch above your bed. That is important, you can have ten different switches (items) but the command is one: "turn on, lights".
Normally you have to create the item/s and the action command. This tutorial explains both and how to enable the action command but knowing the difference will help you on the way.
Where to add and when to enable
There are three places to add a menu: the main menu, a toolbar or a contextual menu. And each one enables/disables its action command using setOptionEnabled() in another place:
|Where do you want it?||Main menu||Toolbar||Contextual menu|
|To add the item modify:||Main menu class||The specific class of the toolbar||The specific class of the contextual menu|
|To enable/disable it modify:||The updateOptions methods of MainPanelMenuAssistant class||The updateOptions methods of MainPanelMenuAssistant class||The specific class of the contextual menu|
|The one who listens to the item:||The actionPerformed method of MainPanelListenerAssistant||The actionPerformed method of MainPanelListenerAssistant||The actionPerformed method of MainPanelListenerAssistant|
You can easily do every step looking at the code of other menu items in the same menu.
Locate the desired menu class, these are the possible ones as for now (june 2018):
* MainMenu * StandardToolBar * EditionToolBar * InferenceToolBar * LinkContextualMenu * NodeContextualMenu * NetworkContextualMenu * InstanceContextualMenu * UncertaintyContextualMenu
Create the menu item as an attribute in the menu class.
Create a private getter for it. This getter should initialize the menu item by defining its name, action command and listener, if it is a toolbar, also the icon, tooltip, and other toolbar specifics.
2.1. For the name create a string attribute in the class that acts as a list of names:
MenuItemNames. Use already created items in the menu to place this adding in order to keep it sorted and be consistent with the other modifications, for instance, if I created a "removeNodeAndChildsMenuItem" I would make every modification after the "removeMenuItem" ones.
2.2. Then create an xml entry for the name in each localized language (That is, in
2.3. For the action command create a string attribute in the class that acts as a list of action commands
ActionCommands. Again, use already created items to place the entry.
2.4 [Toolbar specifics] Set the icon path in the icon loader list (the same as names and action commands, remember the localization). Put the icon image in the resorce folder. Set focusable to false. Set the tooltip (and localize it) and program the mouse move listener to reset it.
Create an entry for your item in the protected getter of the menu:
Here is a table that summarizes the modifications you should made:
|Menu class||Declare menu item|
|Add the item to the menu in initialization methods|
|Create a private getter that initializes the item|
|Create an entry in the protected getter|
|[Toolbar] Set icon, tooltip and mouselistener|
|Action command list class||Create the action command|
|Name list class||Create the name|
|[Toolbar] Icon loader||Create the icon path|
|XML localization files||Localize the name (and toolbar things) in every language|
The updateOptions methods
These methods set if each option should be active after the event they describe happen. Some examples are NetworkModified or AllNetworksClosed.
Enabling is different in contextual menus because they are created on the click while the main menu and the toolbars are always there (even if you don't see them). So if an action command is called from both the main menu and a contextual menu, you only need to write your code in the updateOptions methods.
Enabling in main menu and toolbars
Go to MainPanelMenuAssistant and go through the updateOption methods, adding a setOptionEnabled with your action command when necessary. If you need to test for more conditions, add a separate class
yourActionValidator that checks them in the constraints folder of the gui module (search for
ValidName class or
Enabling in contextual menus
Do it in the constructor of the menu class, after the initialize method. First, add a separate class
yourActionValidator that checks your conditions in the constraints folder of the gui module (search for
ValidName class or
ArcReversalValidator class). Then make the constructor of the menu call this test and enable/disable the menu item.
At this point, the menu will show your option and make it available when the constraint is met, but clicking on it will render a message like
Not implemented function.
MainPanelListenerAssistant is listening to your item. Now you could make it run an edit.