Controlling menu visibility
If there's a public protocol for adding items to the browser menus, people will use it. Since the menus are quite large already, we also implemented methods to control the visibility of menu items. Similar to the enable block that ENVY already offers, we have a visible block. This block is evaluated when the menu is needed, and, depending on the block returning true or false, the menu item will be displayed or not. For the sake of ease of use, we have added "visible" versions of all the standard CwMenu menu hooks.
• add:label:enable:toggle:visible:for:
• add:label:enable:toggle:visible:for:accelerator:acceleratorText:
• add:label:enable:toggle:visible:for:after:
• add:label:enable:toggle:visible:for:before:
• add:label:enable:visible:for:
• add:label:enable:visible:for:after:
• add:label:enable:visible:for:before:
• add:label:toggle:visible:for:
• addSubMenu:label:enable:visible:for:
• addSubMenu:label:enable:visible:for:after:
• addSubMenu:label:enable:visible:for:before:
As an example, let's take a look at a method used in the Refactoring Browser Extensions application supplied in the repository.
addToDefaultTextMenu: aMenu browser: aBrowser
| block aNode notNil isVariable isMessage |
block := aMenu configureBlock.
^aMenu
configureBlock: [
block value.
aNode := aBrowser findNode.
notNil := aNode notNil.
isVariable := notNil and: [ aNode isVariable ].
isMessage := notNil and: [ aNode isMessage ] ];
add: #extractMethod
label: 'Extract Method'
enable: [ aBrowser isOneMethodSelected ]
for: aBrowser;
addSubMenu: #temporaryMenu
label: 'Selection...'
enable: true
visible: [ isVariable and: [
(aNode whoDefines: aNode name) notNil ] ]
for: aBrowser;
addSubMenu: #instVarSubMenu
label: 'Selection...'
enable: true
visible: [ isVariable and: [ | cl |
(cl := aBrowser selectedClass) notNil and: [
cl allInstVarNames includes: aNode name ] ] ]
for: aBrowser;
...
addSubMenu: #messageMenu
label: 'Selection...'
enable: true
visible: [ isMessage ]
for: aBrowser;
...
yourself
The reason for using this technique is that the Refactoring Browser itself has context-sensitive submenus in the text pane, which offer different options depending on what text, if any, is selected. VA Smalltalk caches the browser menus upon creating the browser, making dynamic menu changes very difficult. If we look at the code excerpt above, we see that all the necessary submenus are instantiated, but only the submenu with a true #visible: block will be displayed.
Last modified date: 01/29/2015