Text menu: handling choices
This lesson demonstrates how to handle a menu choice made by a user.
The menuPick message
The menuPick handler
This menuPick handler works with a menu button that's set up as a hierarchical menu, with Font, Size, and Color submenus, plus menu items for "Plain", "Bold", "Italic", and "Underline".
The parameter, pMenuItem, that's passed with the menuPick message contains the text of the menu item the user chose. If the menu item is in a submenu, the parameter includes the submenu name and the menu item, separated by a bar (|). For example, if the user chose "Red" from the "Color" submenu, the pMenuItem parameter is "Color|Red".
Separating the menu item from the submenu
To make it easier to separate the menu item from the submenu, the first thing the handler does is to set the itemDelimiter property to "|". By default, the itemDelimiter is a comma, but you can set it to any character. Once this itemDelimiter is set, if the user chose a submenu item, the submenu name is item 1 of the parameter, and the menu item is item 2 of the parameter.
switch item 1 of pMenuItem
## the submenu name
case "Font"
set the textFont of field "Example Text" to item 2 of pMenuItem
break
...
The switch control structure that forms the heart of this handler checks the first item in the pMenuItem parameter. If the user chose a menu item from a submenu, item 1 is the name of the submenu. If the menu item is a plain menu item, not part of a submenu, then the parameter consists of the menu item's name, and "item 1" is the whole parameter. The switch control structure includes a clause for each top-level menu item, whether it's a submenu or a regular menu item.
The Font, Size and Color submenus
If the user chose a menu item from the "Font" submenu, the handler sets the field's textFont property to the font that was chosen from the submenu. (This is item 2 of the parameter.) The "Size" and "Color" submenus are handled similarly: item 2 of the parameter is the size or color the user chose from the submenu.
case "Font"
set the textFont of field "Example Text" to item 2 of pMenuItem
break
The Style items
This menu has four ordinary menu items at the bottom: Plain, Bold, Italic, and Underline. The parameter for ordinary menu items is just the name of the menu item, and there is only one "|"-delimited item in the parameter, so the expression item 1 of pMenuItem evaluates to the name of the menu item. Because of this, the same switch control structure, which tests item 1 of pMenuItem, works for the submenus and the ordinary menu items.
If the user chooses "Plain", it's simple to change the style. Setting the field's textStyle property to empty removes the style information.
case "Plain"
## plain removes all styles:
set the textStyle of field "Example Text" to empty
If the user chooses "Bold", "Italic", or "Underline", the handler must first figure out whether the style is already applied. If so, the style needs to be removed (without disturbing other styles); if not, it needs to be added to any existing styles. For example, if the field is already bold and underlined, and the user chooses "Underline", the underlining is removed but the boldfacing is retained.
put the textStyle of field "Example Text" into tCurrentStyle
set the itemDelimiter to comma
if pMenuItem is among the items of tCurrentStyle then
## already has that style, so remove it
delete item (itemOffset(pMenuItem,tCurrentStyle)) of tCurrentStyle
else
## add the style to any existing styles
if tCurrentStyle is "plain" then
put pMenuItem into tCurrentStyle
else
put comma & pMenuItem after tCurrentStyle
end if
end if
set the textStyle of field "Example Text" to tCurrentStyle
The textStyle of an object
The textStyle of an object consists of one or more styles, separated by commas. For example, the textStyle of a bold underlined field reports "bold,underline". To find out whether the chosen menu item is already a style of the field, the handler checks whether it's one of the items in the field's textStyle. (Remember that earlier in the handler, we set the itemDelimiter to "|" to be able to separate submenus from their menu items. Since we've already handled all the submenus, we don't need to use this itemDelimiter any more, so we set it back to a comma in order to more easily handle the textStyle.)
If the style the user chose from the menu is already a textStyle of the field, the handler removes that style. If not, it adds the style to the existing textStyle. We need to handle one case, where no special styles are set yet, specially. If there are no styles set, the textStyle property reports "plain". However, if you set the textStyle to a string that includes "plain" as one of the items, any styles before "plain" are ignored. (For example, setting the textStyle to "italic,plain,bold" ignores the italic.) To avoid this problem, if the textStyle property reports "plain", the handler substitutes the chosen style, instead of adding it to the existing style.
The menuPick handler code
on menuPick pMenuItem
local tCurrentStyle
set the itemDelimiter to "|"
switch item 1 of pMenuItem
## the submenu name
case "Font"
set the textFont of field "Example Text" to item 2 of pMenuItem
break
case "Size"
set the textSize of field "Example Text" to item 2 of pMenuItem
break
case "Color"
set the textColor of field "Example Text" to item 2 of pMenuItem
break
case "Plain"
## plain removes all styles:
set the textStyle of field "Example Text" to empty
case "Bold"
case "Italic"
case "Underline"
## all three remaining menu items
## are handled with the same piece of code
put the textStyle of field "Example Text" into tCurrentStyle
set the itemDelimiter to comma
if pMenuItem is among the items of tCurrentStyle then
## already has that style, so remove it
delete item (itemOffset(pMenuItem,tCurrentStyle)) of tCurrentStyle
else
## add the style to any existing styles
if tCurrentStyle is "plain" then
put pMenuItem into tCurrentStyle
else
put comma & pMenuItem after tCurrentStyle
end if
end if
set the textStyle of field "Example Text" to tCurrentStyle
end switch
end menuPick
Steve
Just wondering: isn't there supposed to be a "break" after the case "Plain" line? Without it, the tCurrentStyle is set to "empty" and that will cause the script to hang on the last line.