Some thoughts on menus:
If you need to create a new menu item, first override CytoscapeAction and then do: Cytoscape.getCyMenus().addAction(newAction). You should only have to create JMenuItems yourself in very limited circumstances.
You can set the protected boolean variable "useCheckBoxMenuItem" to true in your CytoscapeAction to get a JCheckBoxMenuItem instead of a normal JMenuItem. However, you can avoid mode errors if instead of using check boxes, you just change the title of the action like in View->Hide Overiew / View->Show Overview.
To set the enabled state of the menu, simply override the menuSelected(MenuEvent e) method in your CytoscapeAction. This method is called after a menu has been clicked on, but before it is rendered. So, if your menu item shouldn't be enabled unless a network has been loaded, then just test to see if the current network isn't null or the null network in the menuSelected method. Conveniently, I've added enableForNetwork() and enableForNetworkAndView() methods to CytoscapeAction that you can call. Using these helps prevent the same code from being written 700 times.
This approach spreads these nearly identical checks out across lots of different actions, which some might perceive as a bad idea. The alternative that existed in CyMenus prior to my changes were elaborate checks in CyMenus that attempted to set the status of all the menu items in a menu at once. The problem with the old approach is that it forced CyMenus to know about the internal needs of the different actions which breaks modularity. Now, only the actions themselves need to know what their internal state should be, which is much better encapsulation.
- The one caveat with the menuSelected approach is that it doesn't handle the toolbar. Unfortunately, there isn't an analogous method call for toolbar buttons, so there needs to be a different approach for buttons.
Please avoid polluting CytoscapeDesktop. If you find yourself using CytoscapeDesktop as a place to initialize some data structure, stop and think about whether that's necessary. Also look at how CyLayouts, PluginManager, and CyHelpBroker initialize themselves. Again, the goal here is to reduce dependencies between classes which will help when we finally get around to things like headless mode.
Mike Smoot