Well, we currently have a pretty nicely working little GUI. Now we want to add a Main Menu to it.
The Pollock UserInterface framework has a special method, all ready for you to use. The method is #getMainMenu. This method's only requirement is that it answer a Pollock Menu. A quick note about that. The Menu and MenuItem objects we are going to be creating are the model objects that will be used to construct the actual menu bar, and menu bar items. We never have to actually instantiate the MenuBar pane and MenuBarItem panes, or hook them together. The UserInterface framework takes care of this for us.
Let's start off with just the main menu bar:
getMainMenu
| menu |
menu := Menu menuItems: (Array
with: ((MenuItem label: '&File') nameKey: #file)
with: ((MenuItem label: '&System') nameKey: #system)
with: ((MenuItem label: '&Browse') nameKey: #browse)).
^menu
Here, we use the Menu class's #menuItems: method to both create the Menu object, and add a collection of MenuItems. You will notice that I have given each menu item a nameKey. This is a unique identity based value (usually a Symbol) that that can be used later to look for the menu items in the menu. It can also be used to find the MenuBarItem panes in the main menu, should we later wish to manipulate them.
If we now start up our ClassHierarchyBrowser, we'll see that we now have a MenuBar, that does the proper mouse and keyboard based highlighting stuff. But of course, as yet, it does nothing very interesting.
For our File menu, we'll just have an Exit menu item. For our System menu, we'll have four items: "Microsoft Look", "MacOSX Look" and "Motif Look", a separator, and then an item called "Console Text". Finally, for our Browse menu, we'll have a single item called "Open On Selected Class".
I'll get into they mean in a moment, but for now, let's start with the basic code (added to the #getMainMenu method):
Here you see I'm using the #addMenuItem: method instead of the #menuItems I used for the menu bar. I could use either, it doesn't matter. To add these new menus to the main menu's menu bar, I use the #submenu: method. Note also, that I added the separator by simply sending #addSeparator to the menu. This illustrates that in effect adding items to a menu is a linear process.
We can open our ClassHierarchyBrowser now, and see that all the menus show up, and you can select them, and do all the standard things, but of course, they still do nothing. But I don't care for the moment, because our menu looks very plain, and I don't like that. Let's add some hotkeys and icons and make it look pretty:
The above is published as version 1.19 in the Package named "PollockBlog" on the Cincom public repository.
Here we have added shortcut keys to all the menu items. For the Exit menu item, it's #F4 and I set the modifier to be "InputState altMask". You can use any of the key state modifier values of InputState: altMask, shiftMask and ctrlMask. And, you can add them together such as I did for the "Open On Selected Class" menu item. The UserInterface menu building system will automatically add the appropriate hotkey text next to the menu item. Also note that I didn't specify any shortcut modifiers for the Look items. This is because when the UserInterface framework sees a character as the shortcut key, it automatically adds the "alt" modifier if you do not specify one.
To specify the images, I'm using a tool support class: ResourceRetriever. This is an object that is used in many tools that allows us to defer getting the actual resource. Give it a class name and a selector, and when the time comes to get the object for display, it then answers the proper thing. We could have just as easily just written "ToolbarIconLibrary visualFor: #fileOpen" or a method in our own UserInterface that answers an image, but this way, the image is not embedded in the Menu, and instead the lightweight ResourceRetriever stands in. That always feels like goodness to me.
Now we have a nice looking set of menus. But they do nothing. We'll hook up the behavior next week... for now, I'll explain what I want to have for each menu item.
Exit: This should simply close the ClassHierarchyBrowser
Microsoft Look, MacOSX Look and Motif Look: Selecting one of these should dynamically change the look of the system to one of these looks. Also, there should be an indicator next to the menu item that is the "current" look.
Console Text: This item when clicked, will toggle between your normal foreground/background color of the text pane, to a White on Black. Also, an indicator will show when the system is in "Console Text" mode.
Open On Selected Class: When this is selected a new ClassHierarchyBrowser will open on the currently selected class (and any subclasses of that class). Also, if there is no Class selected, this item will be disabled.
As I said above, next week we'll add and hook up all the behavior for our Menu Bar items.