Tips_gui   >   Menus   >   Menus On-The-Fly
When I wrote my first Omnis Studio application each menu was built using the menu class editor. Each menu line was added to a menu class and code was put behind the menu item to carry out the requested action.
Later I learned how to build menus on-the-fly and discovered the following advantages to them:
The following example may help to explain how using menus on-the-fly makes application development easier.
You have a window menu called $constructMenus method, add one line of code, then go to the observer of the menu events and add a $BackOrderedItems method, write the code to print the report, and you're done! You never need to touch the menu class.
and a user asks you to add a new report called . With menus on-the-fly, you simply go to theIf you are supporting a multi-language application, menus on-the-fly are a great benefit because the menu text is assigned at runtime.
If you have already read the topic
you will find this section is similar with just a few differences.All the methods needed to create menus on-the-fly are listed in this section.
Press the
Menus on-the-fly are a great way to write flexible and easy to maintain applications! button in the to open a demo window.In the window class a special method, $constructMenus, is called by $construct when the window instance is constructed. The $constructMenus method is responsible for adding menus to the window and adding menu lines to the menus.
The sample code below is in the $constructMenus method of the demo window.
; Make sure $hasmenus is set to true.
Do $cinst.$hasmenus.$assign(kTrue)
; Add the demo menu to the $menus group of the window instance.
Do $cinst.$menus.$add('mMenusOnTheFlyDemo') Returns rMenu
; Set the menu title.
Do rMenu.$title.$assign('Reports')
; Attach this window instance as an "events observer" to be notified of any menu events.
; The second parameter is the 'dispatcher' call back method name.
Do rMenu.$attachEventsObserver($cinst,'$doReportsMenuCmnd')
; Add some menu lines to the menu.
Do rMenu.$addMenuLine('Report1','Report 1') Returns rLine
Do rMenu.$addMenuLine() ;; Empty line.
Do rMenu.$addMenuLine('Report2','Report 2',kTrue) Returns rLine
Do rMenu.$addMenuLine('NoRecipientMethod','No Recipient Method',kTrue) Returns rLine
Quit method kTrue
The $doMenuCmnd window class method is the dispatcher for all messages received from the menus to which the window class has attached itself as an events observer. You can use the same dispatcher method for multiple menus.
The $doMenuCmnd method prefixes a $ character the selected menu line's $name and checks for a recipient class method using $cando. If the method is available $doMenuCmnd forwards the message to the method.
The sample code below is in the $doMenuCmnd method of the demo window.
; This method forwards to reports menu message to a public method matching the name of the menu line selected.
; Calculate the public method name based on the selected menu line name.
Calculate MethodName as con('$',pfrMenuLine().$name)
; Test to make sure the method name exists.
If $cinst.[MethodName].$cando
OK message [sys(85)] (Icon) {The event message has been received by the dispatcher method [$cmethod().$name]////Parameter 1 is a reference to the menu line '[pfrMenuLine().$name]'////This message is about to be forwarded to the [MethodName] window class method.}
Do $cinst.[MethodName](pfrMenuLine) Returns FlagOK
Else
OK message [sys(85)] (Icon) {Error!////The window class method '[MethodName]' could not be found.////Unable to dispatch the request.}
Calculate FlagOK as kFalse
End If
Quit method FlagOK
The demo menu only allows a single events observer per menu class instance. You could allow for multiple observers by storing the observer references in one row ivar, and the call back method names in another row variable. See the topic
for more information.; $attachEventsObserver(pfrObserver,pCallBackMethodName)
; Store a reference to the observer instance.
Set reference irObserver to pfrObserver.$ref
; Store the 'Dispatcher' method. (Optional)
Calculate iCallBackMethodName as pCallBackMethodName
Quit method kTrue
The menu instance receives $addMenuLine messages with the parameters pMenuName and pMenuText. The $addMenuLine method adds a menu line to the menu instance and returns a reference to the added menu line.
Sample code is listed below.
; $addMenuLine(pName,pText,pbElipsis)
; Append ... to the pText if pbElipsis is set to true. Default is false.
Calculate Text as con(pText,pick(pbElipsis=1,'','...'))
; Add a menu line object to the menu instance.
; $add(cText,bEnabled,bChecked)
Do $cinst.$objs.$add(Text,kTrue,kFalse) Returns rMenuLine
; Assign the name to the menu item.
Do rMenuLine.$name.$assign(pName)
; Return a reference to the added menu item.
Quit method rMenuLine
When the user clicks on a menu item, a $event message is sent to the menu item. Since the menu item was added on-the-fly there is no $event message so the message automatically is passed to the $control method of the menu instance.
The mReports menu sends a $printReport message to the registered observers.
The menu's $control method uses $cobj().$name to figure out which menu item was selected by the user. The menu line name is used prefixed with a $ character and used as the first parameter sent to the registered observers, the second menu line $text is used as the second parameter sent to the registered observers.
Sample code is shown below.
On evClick
; Test to make sure the callback message can be sent to the observer.
If irObserver.[iCallBackMethodName].$cando
; Send a message to the observer.
Do irObserver.[iCallBackMethodName]($cobj)
Else
; Unable to send the message. Report an error.
OK message [sys(85)] (Icon) {The call back method, [iCallBackMethodName], is not found in the menu events observer of [irObserver().$name].}
End If
Quit method kTrue
The following is a summary of event for the
demo.