Dynamic Menu - Usage

The usage of n_dynamic_menu is very simple and follows these simple steps :

1. Design dynamic menu ancestor

Using the Menu Painter, you will create the menu item ancestor that will provide the specific/generic behavior you want for each menu item you will create dynamically at run time.

This menu will have only one Item and will be coded as needed. The most simple case will be to add the possibility to react to the clicked event by invoking dynamically a dedicated user event declared at window level :

{m_dm_ancestor::clicked}
parentwindow.dynamic event ue_dm_clicked( this.tag )


Of course, you can code menu's events and functions as usual, but you should keep in mind that you have to be able to identify one instance from another one in the code that will make use of menu's message.
Here for example, we pass the tag value of the clicked menu (that have been set before with a unique value ) to identify it.

2. Declare instance variables to handles dynamic menus references

As the dynamic menus will be created at run time, you will need instances variables to holds their references at least during the lifetime of the used menu.
The most convenient way to do it is to declare a dynamic array of type menu at Window's Instance level, for example :
{w_dm::Instance Variable}
menu im_Dynamic[]

3. Use n_dynamic_menu

In the adequate script, declare a local variable of type n_dynamic_menu :

n_dynamic_menu lnv_dm


You will also need a local variable to hold a temporary reference to the new instance of your dynamic menu ancestor that you have designed before. Then instantiate it and set the needed properties (you can set all modifiable menu properties you want ):

...
m_dm_ancestor lm_tmp
integer li_limit
...
// Set dynamic menu properties
m_tmp = create m_dm_ancestor
lm_tmp.text = "My Dynamic Menu"
lm_tmp.enabled = true
lm_tmp.visible = true
lm_tmp.tag = "DM1"
...
// Store Dynamic Menu references
li_limit++
im_dynamic[li_limit] = m_lmp



You will also need to get the reference of the parent menu item under which will be inserted/added the dynamic menu item. Usually, it is more convenient to also use a local variable to hold its reference.
To do this there is two technics :

1st one - you know the name of the parent menu item :

menu lm_parent
...
lm_parent = w_dm.menuid.m_dm_parent
...


2nd one - you know its item index (as it was added dynamically just before, for example) :

menu lm_parent
integer li_last_inserted
...
lm_parent = im_Dynamic[li_last_inserted]
...


then effectively insert it :

...
li_last_inserted = lm_dm.of_insert_menu_at_end( lm_parent, lm_tmp )
.. 


Finally, code the dedicated ue_dm_clicked() event with adequate code:

{w_dm::ue_dm_clicked(string as_id)}
choose case as_id
     case "DM1"
        // Clicked Dynamic Menu handling code
...
     case else
        // Error handling code
...
end choose



In a more realistic scenario, properties of dynamic menu will be set based on informations extracted from the database using datastore, and the insertion of the dynamic menu items will be enclosed in a loop depending on the number of rows returned by the datastore. For example;

{obj::Instance variables}
Protected:
menu im_Dynamic[]
datastore ids_menus

{obj::of_set_menus(integer ai_menu_id) return integer}
long  ll_i
long  ll_last_inserted
long  ll_rowcount
menu lm_parent
m_dm_ancestor lm_tmp
n_dynamic_menu lnv_dm

if isnull( ai_menu_id ) or ai_menu_id < 1 then return -1

// Get Parent menu Reference
lm_parent = parent.menuid.item[ai_menu_id]

// Retrieve Specified Menu contents
ids_menu = create datastore
ids_menu.dataobject = "d_dynamic_menus"
ids_menu.settransobject(sqlca)

ll_rowcount = ids_menu.retrieve( ai_menu_id )
if ll_rowcount = 0 then return 0

// Create specified menu sub-items
for ll_i = 1 to ll_rowcount
   lm_tmp = create m_dm_dynamic
   lm_tmp.tag = ids_menu.object.id[ll_i]
   lm_tmp.text = ids_menu.object.label[ll_i]
   lm_tmp.enabled = (ids_menu.object.is_enabled[ll_i] = "Y")
   lm_tmp.visible = (ids_menu.object.is_visible[ll_i] = "Y")
 ...
   im_dynamic[ll_i] = lm_tmp  
   lm_dm.of_insert_menu_at_end( lm_parent, lm_tmp )
next

// Refresh parent menu
lm_dm.of_refresh_menu( lm_parent )

return 1



Navigation
Developer's Guide | Overview | Usage |Functions

Last edited Apr 6, 2016 at 10:48 PM by domangep, version 4