This article was written and submitted by an external developer. The Google Desktop Team thanks Jeremy Glassenberg for his time and expertise.
Menus aren't just for medium- or large-sized applications. Even little Google Desktop Gadgets can benefit from a menu. Perhaps your gadget has a few customizable options, but not enough to fill an entire Options View. Furthermore, users may prefer simple menu selections over having to open up an Options View.
By now, you surely have encountered a gadget's menu and its default menu items such as "Hide", "Collapse", etc. In this article, I will show you how to customize the content of the menu for your own needs.
I recommend following this article with the MenuItems sample gadget that is included in the SDK. You can browse its source code here.
That gadget is a good start, but it leaves out some advanced features. In this article, we enhance MenuItems to demonstrate everything that can be accomplished with Google Desktop's menu API.
In order to customize the menu, first have the gadget run the following line of code upon loading:
// Set up menu management handler. pluginHelper.onAddCustomMenuItems = onYourMenuManagementFunction;
onYourMenuManagementFunction
is the function
that generates your custom menu. It is called whenever a user opens the gadget's menu.
Next, we define the actual menu creation function and specify what menu items to add. Below is a sample function to create a basic menu (based on the MenuItems gadget).
function onYourMenuManagementFunction(menu) { // Add each item. Note that this needs to be done each time this function is // called. menu.AddItem("ITEM_A", gddMenuItemFlagChecked, onItemAClick); menu.AddItem("ITEM_B", gddMenuItemFlagGrayed, null); menu.AddItem("ITEM_C", 0, onItemCClick); }
The above code creates three menu items, each of which demonstrates a basic functionality.
The first menu item displays "ITEM_A"
, has a checkmark next to it, and calls onItemAClick
when it's selected.
The second creates a grayed menu item that does nothing when selected.
Finally, the third menu item looks perfectly normal, and calls onItemCClick
when selected. The resulting menu is shown on the right.
As you can see, setting up basic items on a menu is straightforward.
The function menu.AddItem(itemName, flags, onClick)
creates a new menu item.
The first parameter is a string of what will be displayed. The second parameter can be a flag to specify certain properties for your menu items.
Finally, the third parameter of menu.AddItem(itemName, flags, onClick)
is the name of the function to be called if that menu item is selected.
The optional flags for the second parameter are:
gddMenuItemFlagGrayed
gddMenuItemFlagChecked
The gddMenuItemFlagGrayed
flag will result in a grayed item. This is usually done to imply that the item cannot be selected. In actuality, such items can still call a function when clicked. However, I would not recommend allowing these items to do anything when grayed, as that would just confuse users. Try and follow common design standards.
The gddMenuItemFlagChecked
flag sets a menu item to be "checked", which just places a checkmark next to it. This can be seen in the "Item A" menu item in Figure 1.
Grayed or checked menu items are not really useful if they cannot be changed. Why create a menu item that is always grayed-out? The item must be there for a reason, to be enabled at a later time. This section explains how to create menu items whose appearances vary according to the situation.
Let's revisit our earlier function that creates three menu items. In order to enable a grayed item or un-check a checked item, we simply change the second parameter. We can modify this function so that the style changes, depending on certain conditions.
The following code provides a more dynamic menu:
function onYourMenuManagementFunction(menu) { // Add each item. Note that this needs to be done each time this function is // called. menu.AddItem(ITEM_A, itemCChecked ? 0 : gddMenuItemFlagChecked, onItemAClick); menu.AddItem("ITEM_B", gddMenuItemFlagGrayed, null); menu.AddItem(ITEM_C, itemCChecked ? gddMenuItemFlagChecked : 0, onItemCClick); }
Now, the first menu item is checked only when the variable itemCChecked
is true
. Otherwise, it is un-checked.
The reverse is true for the third menu item, so we now have two items that "compete" for the check. The result can be seen in Figure 2.
The custom menu handling function is called whenever a user opens the menu options. Thus, you can define how the menu is displayed every time it opens by adding conditions such as those shown above.
This last bit of information should provide all you need to create hierarchical menus. Instead of just creating a long list of options, you may want to organize the items into sub-menus.
This is accomplished by using the menu.AddPopup(sub_menu_name)
function.
Let's add such functionality to our previous example.
function onAddCustomMenuItems(menu) { // Add each item. Note that this needs to be done each time this function is // called. menu.AddItem(ITEM_A, itemCChecked ? 0 : gddMenuItemFlagChecked, onItemAClick); var sub_item = menu.AddPopup("Sub_item"); sub_item.AddItem("sub_item_1", 0, onItemAClick); sub_item.AddItem("sub_item_2", 0, onItemAClick); menu.AddItem(ITEM_B, gddMenuItemFlagGrayed, null); menu.AddItem(ITEM_C, itemCChecked ? gddMenuItemFlagChecked : 0, onItemCClick); }
The resulting menu looks like this:
To create a sub-menu, we first call menu.AddPopup("Sub_item");
This function takes one parameter: the text to display for the sub-menu. Note that this function returns a variable, which we should store for future use.
After that, we can treat sub_item
as if it were the menu
object.
Thus, sub_item
acts as a "menu-in-a-menu".
There is one last function that may be of use in order to have better control over the style of your menu items. Let's say you add an item that may be disabled (grayed), depending on some complicated circumstances.
Using terse conditional statements within the AddItem
function might make your code hard to read and difficult to maintain.
That is where SetItemStyle(item_text, style)
comes in handy.
This function can be applied by simply calling menu.SetItemStyle(item_text, style)
to an existing item. The first parameter is the text of the item you want to change. The second parameter is the new style you want to apply. For example, the following two functions result in the same menu:
//first function, without SetItemStyle function onAddCustomMenuItems(menu) { menu.AddItem(ITEM_C, itemCChecked ? gddMenuItemFlagChecked : 0, onItemCClick); } //second function, with SetItemStyle function onAddCustomMenuItems(menu) { menu.AddItem(ITEM_C, 0, onItemCClick); if (itemCChecked){ menu.SetItemStyle(ITEM_C, gddMenuItemFlagChecked); } }
As the above code snippet demonstrates, using SetItemStyle
is a cleaner way of manipulating a menu item's appearance. The benefits of using this method become more evident as the menus become more complex.
I hope this article has shed some light on how to implement menus. Once you get the hang of creating menus, you'll probably start to see the vital role of menus in high quality UI designs — and the vast possibilities that menus can bring to your own gadgets. Gadgets are usually better when they are more convenient for their users, so take the advice here to add a little more quality to your gadgets.
Good luck!
I am currently an MBA student at Carnegie Mellon University. I have a B.S. Degree in Computer Science from UIUC. Prior to grad school, I worked as an intern at Salesforce.com, Microsoft, Northwestern University, and Technion. More recently, I worked for two web startups in Pittsburgh: mSpoke and GeoNexxus.
Favorite Quote: "Come on, guys. If we don't try now, we'll never know how horribly they can beat us. That's the sort of thing that can haunt you." -Homer J. Simpson
This work is licensed under a
Creative Commons Attribution 3.0 United States License.