Purpose

Options menus provide the user with a list of options. The selection of an option may lead to displaying a submenu.

The main Options menu, if available, is displayed from an Options softkey.

Menus can also be displayed from:

  • CAknDialog ,

  • CAknSettingPage .

Menus can be added to other UI components, too.

Constraints

None.

Classification and release information

Options Menu API is an SDK API and part of S60 3rd Edition.

Constraints

None.

Related APIs
  • CAknDialog
  • CAknSettingPage

API description

Options Menu API provides support for a number of menus (called menu panes), each attached to a main menu bar or a menu item.

The menu support is implemented in two main classes: CEikMenuBar and CEikMenuPane . The menu structure is defined in the resource file as a menu bar structure ( MENU_BAR ), which references one or more menu panes in a list of MENU_TITLE structures. The menu bar itself is usually referenced in the application information resource structure ( EIK_APP_INFO ) or in the view resource structure ( AVKON_VIEW ), but can also be referenced in AVKON_SETTING_PAGE resource structure or a menu bar resource structure can directly be passed to CAknDialog ’s ConstructL() .

All the menu pane resources of a menu bar are read on construction and joined to form a single menu pane. This ensures that the menu panes are stacked on top of each other, with the first pane at the bottom of the menu pane, and the last at the top. The txt fields of MENU_TITLE s are omitted. This allows applications to specify menus based on a set of individual menu option groups.

When the application is started, the menu bar is constructed and the menu bar resource is read. Whenever the menu is displayed, or the user navigates between menu panes, a menu pane is constructed and the appropriate menu pane resource is read.

Use cases

The main use cases of the Options Menu API are:

  • Specifying menus in resource files

  • Initializing menus

    • Adding menu items

    • Removing menu items

    • Testing the existence of menu items

  • Handling command IDs

  • Context sensitive menus

  • Opening menus

  • Closing menus

  • Marquee

  • Indicating items

    • Items with check mark

    • Radio button group

  • Application-level hotkeys

API class structure

Options menu API contains little number of classes providing functionality of the interface. In the following class diagrams, the API classes are grouped together according to their roles and functionality.

Class diagram in Figure 1 shows that the API consists mainly from the CEikMenuBar and the CEikMenuPane classes. CEikMenuBar represents the first level of the menu and encapsulates a number of menu panes through the nested class CItemArray . An item in it ( CEikMenuPaneItem ) refers to the resource ID of the relevant menu pane CEikMenuPane .

The most often used API part is CEikMenuPane . Menu manipulation is usually done with this. In case of this class, CItemArray cannot be got. An item or item data can be queried directly with the methods of the CEikMenuPane class.

The Figure shows, that each menu pane item either generates a command to the menu observer, or opens a submenu pane (cascading).

Each menu bar has one observer: MEikMenuObserver . Clients of the API cannot change or add observers after menu bar and menu pane construction. MEikMenuObserver is implemented by the UI components that support menu. They have been listed already above.

The UML diagram of the Options Menu API


The UML diagram of the Options Menu API

Related APIs
  • CEikMenuBar
  • CEikMenuPane
  • CEikMenuPaneItem
  • CItemArray
  • MEikMenuObserver
Related APIs
  • AVKON_SETTING_PAGE
  • AVKON_VIEW
  • CAknDialog
  • CEikMenuBar
  • CEikMenuPane
  • ConstructL()
  • EIK_APP_INFO
  • MENU_BAR
  • MENU_TITLE

Using the Options Menu API

Specifying menus in resource files

The first step of using menus is to specify them in resource files. The main descriptor of a menu is the MENU_BAR resource structure. The desired menu panes (usually only one) must be listed in the titles field of it. The txt fields are ignored, however:

             
              RESOURCE MENU_BAR r_myapp_menu_bar
              
    {
    titles=
        {
        MENU_TITLE { txt="System"; menu_pane=r_system_menu; },
        MENU_TITLE { txt="App"; menu_pane=r_app_menu; },
        MENU_TITLE { txt="Context"; menu_pane=r_context_menu; }
        };
    }

The menu panes are collection of menu items. The items are listed in the items field. An item may open a cascading submenu. Cascading submenus are also menu pane resources:

             
              RESOURCE MENU_PANE r_system_menu
              
    {
    items=
        {
        MENU_ITEM { command=EMyappSystemFile; txt="File"; 
                    cascade=r_system_file; },
        MENU_ITEM { command=EAknCmdExit; txt="Exit"; }
        };
    } 

RESOURCE MENU_PANE r_system_file
    {
    items =
        {
        MENU_ITEM { command=EMyappFileOpen; txt=”Open”; },
        MENU_ITEM { command=EMyappFileSave; txt=”Save”; },
        };
    }

The menu bar structure then can be linked to the EIK_APP_INFO resource, or to an AVKON_VIEW resource, if the application uses views:

             
              RESOURCE EIK_APP_INFO
              
    {
    menubar=r_myapp_menu_bar;
    cba=R_AVKON_SOFTKEYS_OPTIONS_EXIT;
    }

RESOURCE AVKON_VIEW r_browser_content_view
    {
    menubar=r_myapp_menu_bar;
    cba=R_AVKON_SOFTKEYS_OPTIONS_EXIT;
    }

A menu bar can also be referenced in AVKON_SETTING_PAGE resource structure:

             
              RESOURCE AVKON_SETTING_PAGE r_slider_setting_page
              
    {
    label = "Slider Page label";
    hint_text = "This is a long hint text message";
    menubar= r_slider_page_menubar;
    softkey_resource = R_AVKON_SOFTKEYS_OPTIONS_BACK;
    type = EAknCtSlider;
    editor_resource_id = r_setting_app_slider;
    }

A menu bar resource structure can directly be passed to CAknDialog ’s ConstructL() . In the following example CFileOpenDialog is derived from CAknDialog :

             
              TInt CFileOpenDialog::ExecuteLD()
              
{
    CleanupStack::PushL( this ); 
    ConstructL( R_FILE_OPEN_MENUBAR );
    CleanupStack::Pop( this );
    …
    return CAknDialog::ExecuteLD( R_FILE_OPEN_DIALOG );
}
Related APIs
  • AVKON_SETTING_PAGE
  • AVKON_VIEW
  • CAknDialog
  • CFileOpenDialog
  • ConstructL()
  • EIK_APP_INFO
  • MENU_BAR
  • txt

Initializing menus

In order for applications to modify the contents of the menu pane at run time, DynInitMenuPaneL() is called on the menu bar observer (typically the application UI) to change the options. This function is called every time just before a menu pane is launched, with the menu pane resource as the function parameter.

Adding menu items

The following example illustrates adding one item to the menu pane:

              
               void CMyappView::DynInitMenuPaneL( TInt aResourceId,
               
                                   CEikMenuPane* aMenuPane )
    {
    if ( aResourceId == R_COMMON_MENU )
        {
        CEikMenuPaneItem::SData menuFindNext;
        menuFindNext.iCommandId = EMyappFindNext;
        menuFindNext.iCascadeId = 0;
        menuFindNext.iFlags = 0;
        menuFindNext.iText = KMyappFindNext;
        aMenuPane->AddMenuItemL( menuFindNext );
        }
    }

There is the possibility to add more than one item. The resource ID parameter of AddMenuItemsL() must refer to a valid MENU_PANE resource:

              
               void CMyappAppUi::DynInitMenuPaneL(
               
    TInt aResourceId,
    CEikMenuPane* aMenuPane )
    {
    if ( aResourceId == R_AVKON_FORM_MENUPANE ) 
        {
        aMenuPane->AddMenuItemsL( R_GENERAL_STATUS_MENU_PANE );
        }
    }

A new menu item can be inserted to a given position. The following example inserts a new item at the last position:

              
               void CMyappView::DynInitMenuPaneL( TInt aResourceId,
               
                                   CEikMenuPane* aMenuPane )
    {
    if ( aResourceId == R_COMMON_MENU )
        {
        CEikMenuPaneItem::SData menuFindNext;
        menuFindNext.iCommandId = EMyappFindNext;
        menuFindNext.iCascadeId = 0;
        menuFindNext.iFlags = 0;
        menuFindNext.iText = KMyappFindNext;
        aMenuPane->InsertMenuItemL( menuFindNext, 
                                    aMenuPane->NumberOfItemsInPane() );
        }
    }
Related APIs
  • AddMenuItemsL()
  • MENU_PANE

Removing menu items

The following example illustrates deleting one item from the menu pane:

              
               void CMyappAppUi::DynInitMenuPaneL( TInt aResourceId, 
               
                                    CEikMenuPane* aMenuPane )
    {
    if ( aResourceId == R_COMMON_MENU )
        {
        if ( IsLastOccurrence() )
            aMenuPane-> DeleteMenuItem( EMyappFindNext );
        if ( IsFirstOccurrence() )
            aMenuPane-> DeleteMenuItem( EMyappFindPrevious );
        }
    }

There is the possibility to delete more than one item between the specified indexes. The example deletes all items from the menu pane:

              
               aMenuPane->DeleteBetweenMenuItems( 0, aMenuPane->NumberOfItemsInPane() - 1 );
              
             

When a menu pane is dismissed and opened again, items not desired have to be deleted again!

Dimming a menu item simply removes the item from the menu pane. The item will not be visible at all!

              
               void CMyappView::DynInitMenuPaneL( TInt aResourceId,
               
                                   CEikMenuPane* aMenuPane )
    {
    if ( aResourceId == R_COMMON_MENU )
        {
        aMenuPane->SetItemDimmed( EMyappFindNext, IsLastOccurrence() );
        aMenuPane->SetItemDimmed( EMyappFindPrevious, IsFirstOccurrence() );
        }
    }

Menu items not wanted are usually removed with SetItemDimmed() .

Related APIs
  • SetItemDimmed()

Testing the existence of menu items

The following example tests the existence of a given menu item:

              
               void CMyappView::DynInitMenuPaneL( TInt aResourceId,
               
                                   CEikMenuPane* aMenuPane )
    {
    if ( aResourceId == R_COMMON_MENU )
        {
        TInt pos( 0 );
        if ( aMenuPane->MenuItemExists( EMyappFindNext, pos ) && 
             IsLastOccurrence() )
            {
            aMenuPane->SetItemDimmed( EMyappFindNext, ETrue );
            }
        }
    }
Related APIs
  • DynInitMenuPaneL()

Handling command IDs

When an option is activated, the observer of the menu pane is fired to handle the activated menu command ID. It is given to CAknAppUi::HandleCommandL in the application UI or CAknView::HandleCommandL , if the application view handles the commands.

Example:

             
              void CMyAppUi::HandleCommandL( TInt aCommand )
              
    {
    switch ( aCommand )
        {
        case EEikCmdExit:
            {
            Exit();
            break;
            }
        case EAknSoftkeyExit:
        case EAknCmdExit:
            {
            CAknEnv::RunAppShutter();
            break;
            }
        case EMyappCmdDoSomething:
            {
            …
            break;
            }
        default:
            {
            CAknAppUi::HandleCommandL( aCommand );
            break;
            }
        }
    }

Common command IDs can be found in files:

  • eikon.hrh

  • uikon.hrh

  • avkon.hrh

See also Closing menus .

Related APIs
  • CAknAppUi::HandleCommandL
  • CAknView::HandleCommandL
  • avkon.hrh
  • eikon.hrh
  • uikon.hrh

Context-sensitive menus

Since each section of the menu pane is defined as a separate menu pane resource, application developers may combine menu panes to give the desired menu options for each application state. Each of the unique menu sections should be defined once as a menu pane resource, after which a menu bar resource may be defined for each application state that is required.

The current menu can be changed at any time by calling

             
              iEikonEnv->AppUiFactory()->MenuBar()->SetMenuTitleResourceId();
             
            

with the new menu bar resource ID, or an existing menu can be altered by simply adding new items to it or removing existing items from it.

Menu and the application UI framework give some more support to implement context sensitive menus. The client code can specify context menu with CEikMenuBar ’s SetContextMenuTitleResourceId() , and then call TryDisplayContextMenuBarL() when the menu must be opened. The application UI base class CAknAppUi supports opening the context menu, if the client application forwards the command EAknSoftkeyContextOptions to CAknAppUi::ProcessCommandL() .

Some application opens a context-sensitive, simplified menu when the OK key is pressed. It can be achieved by opening the menu in OfferKeyEventL() when EKeyOK is received.

Related APIs
  • CAknAppUi
  • CAknAppUi::ProcessCommandL()
  • CEikMenuBar
  • EAknSoftkeyContextOptions
  • EKeyOK
  • OfferKeyEventL()
  • SetContextMenuTitleResourceId()
  • TryDisplayContextMenuBarL()

Opening menus

The menu bar is shown when the user presses the Options softkey.

When a UI component implements its own menu, the menu bar can be displayed (opened) with the following code:

             
              iMenuBar->TryDisplayMenuBarL();
             
            

This method constructs the correct menu bar and displays it.

CAknAppUi -, CAknViewAppUi -, CAknView - and CAknSettingPage -derived classes can open the menu by calling the base class’ ProcessCommandL() with EAknSoftkeyOptions . The same stands for context menus set by SetContextMenuTitleResourceId() , but with the exception that they must use EAknSoftkeyContextOptions as parameter.

CAknDialog -derived classes can open the menu by calling OkToExitL() with EAknSoftkeyOptions .

Related APIs
  • CAknAppUi
  • CAknDialog
  • CAknSettingPage
  • CAknView
  • CAknViewAppUi
  • EAknSoftkeyContextOptions
  • EAknSoftkeyOptions
  • OkToExitL()
  • ProcessCommandL()
  • SetContextMenuTitleResourceId()

Closing menus

The menu bar is closed when an option is selected or is canceled by the user pressing the Cancel softkey.

When a UI component implements its own menu, the menu bar can be hidden (closed) with the following code:

             
              iMenuBar->StopDisplayingMenuBar();
             
            

Note that in non- AppUi or view classes, a menu calls ProcessCommandL() of the menu observers that implement MEikMenuObserver . In this case, it is the responsibility of the code handling the command to dismiss the menu with StopDisplayingMenuBar() .

The ProcessCommandL() method of CAknDialog and CAknSettingPage stops displaying the menu bar, thus CAknDialog -derived classes are advised to call the base class’ ProcessCommandL() in their own ProcessCommandL() .

Related APIs
  • AppUi
  • CAknDialog
  • CAknSettingPage
  • MEikMenuObserver
  • ProcessCommandL()
  • StopDisplayingMenuBar()

Marquee

It is possible to enable horizontal scrolling (the so called marquee) of long menu items that do not fit into the available width. By default, marquee is disabled. To enable marquee, EnableMarqueeL() must be called with parameter ETrue in DynInitMenuPaneL() :

             
              aMenuPane->EnableMarqueeL( ETrue );
             
            
Related APIs
  • DynInitMenuPaneL()
  • ETrue
  • EnableMarqueeL()

Indicating items

There are two indication types supported:

  • Items with check mark

  • Radio button group containing several items

A menu can contain indicated items in it with the following constraints:

  • Only cascading submenus are allowed to contain indicated items in it (indication of such items in the main menu bar is ignored).

  • A menu is allowed to contain only one of the two types.

  • A menu is allowed to contain at most one radio button group.

Notice that menu pane doesn't keep a track on the status of these items and when menu is displayed again the status will be set to the one which was specified in the resource structure unless SetItemButtonState() was called. So an application is responsible for setting the right status for those items in DynInitMenuPaneL() using the method:

             
              void SetItemButtonState( TInt aCommandId, TInt aButtonState );
             
            

Items with a check mark

An item with a check mark can be created by using EEikMenuItemCheckBox flag for the menu item. To set the item to be marked on initialization, the EEikMenuItemSymbolOn flag should be specified.

Here is an example for the resource structure:

              
MENU_ITEM 
    {
    command = ESomeCmdId;
    txt = qtn_some_text;
    flags = EEikMenuItemCheckBox | EEikMenuItemSymbolOn;
    }

Here is an example on how to set the status of an item having a check mark:

              
               void CMyAppUi::DynInitMenuPaneL( TInt aResourceId, CEikMenuPane* aMenuPane )
               
    {
    if ( aResourceId == R_MYAPP_CASCADE_WEATHER )
        {
        aMenuPane->SetItemButtonState( EMyappCmdSunny, 
                                       iIsWeatherSunny?
                                           EEikMenuItemSymbolOn:
                                           EEikMenuItemSymbolIndeterminate );
        }
    }
Related APIs
  • EEikMenuItemCheckBox
  • EEikMenuItemSymbolOn

Radio button groups

For the radio button group creation, the flags EEikMenuItemRadioStart and EEikMenuItemRadioEnd should be used:

              
               MENU_ITEM 
               
    {
    command = ESomeCmdId1;
    txt = qtn_some_text_1;
    flags = EEikMenuItemRadioStart;
    },
MENU_ITEM 
    {
    command = ESomeCmdId2;
    txt = qtn_some_text_2;
    flags = EEikMenuItemSymbolOn;
    },

    …

MENU_ITEM 
    {
    command = ESomeCmdIdN;
    txt = qtn_some_text_n;
    flags = EEikMenuItemRadioEnd;
    }

If none of the items has EEikMenuItemSymbolOn flag set, then the first item in the radio button group will have indication on. If several items in the group have this flag on, then the last one will be indicated

Here is an example of how to set the status of items in a radio button group:

              
               void CMyAppUi::DynInitMenuPaneL( TInt aResourceId, CEikMenuPane* aMenuPane )
               
    {
    if ( aResourceId == R_MYAPP_CASCADE_ORDER_DRINK )
        {
        if ( iSelectedDrink == EMyappWater )
            aMenuPane->SetItemButtonState( EMyappCmdWater, 
                                           EEikMenuItemSymbolOn );
        else if ( iSelectedDrink == EMyappJuice )
            aMenuPane->SetItemButtonState( EMyappCmdJuice, 
                                           EEikMenuItemSymbolOn );
        else if ( iSelectedDrink == EMyappBeer )
            aMenuPane->SetItemButtonState( EMyappCmdBeer, 
                                           EEikMenuItemSymbolOn );
        }
    }
Related APIs
  • EEikMenuItemRadioEnd
  • EEikMenuItemRadioStart
  • EEikMenuItemSymbolOn
Related APIs
  • DynInitMenuPaneL()
  • SetItemButtonState()

Application-level hotkeys

Application-level hotkeys are not strongly connected to the Options Menu API, but one reason for mention them here is that they omit command IDs like menus.

The application UI framework enables the definition of hotkeys. A hotkey generates a command that is handed over to the application UI’s HandleCommandL() method.

First of all, a hotkey resource of the type HOTKEYS must be defined. The following example defines two hotkeys. When the user presses Ctrl-e, it generates the command EAknCmdExit , and when Ctrl-t, then it generates EMyappCmdTest . Note that these keys work when the Ctrl is also pressed down. This is why they are listed under the ‘control’ field of HOTKEYS .

             
              RESOURCE HOTKEYS r_myapp_hotkeys
              
    {
    control =
        {
        HOTKEY { command=EAknCmdExit; key='e'; },
        HOTKEY { command=EMyappCmdTest; key='t'; }
        };
    }

Even if hotkeys are defined in EIK_APP_INFO resource structure of the application, they are not handled. In order the hotkeys to be handled by the application, the derived application UI class’ ConstructL() must call the base class’ CreateHotKeyControlL() method with the ID of the HOTKEYS resource defined in the application’s resource file:

             
              void CMyAppUi::ConstructL()
              
    {
    BaseConstructL();
    …
    CreateHotKeyControlL( R_MYAPP_HOTKEYS );
    }
Related APIs
  • ConstructL()
  • CreateHotKeyControlL()
  • EAknCmdExit
  • EIK_APP_INFO
  • EMyappCmdTest
  • HOTKEYS
  • HandleCommandL()

Error handling

Options Menu API uses standard Symbian platform error reporting mechanism. Leaves and system wide error codes as function return values are used if the error is recoverable. A client application can handle these errors similarly as a normal Symbian platform application.

Memory overhead

Memory consumption of the Options Menu API is directly proportional to the number of menus and the number of items in each menu defined by the client.

Limitations of the API

Menu bar titles are not displayed - as stated before, menu pane resources of a menu bar are read on construction and joined to form a single menu pane. The title texts and icons are not displayed at all.

Menu pane item icons are not supported. Even if the relevant methods of CEikMenuPaneItem are called, icons are not displayed.

Menu item text has no size limit, but at most only the first ENominalTextLength characters will be displayed.

Separators are not supported.

Menu item accelerator hotkeys are not supported: CEikMenuPaneItem ’s iHotKeyCode is ignored. Note that this hotkey differs from the one that is defined on application-level by the resource structure HOTKEYS .

Related APIs
  • CEikMenuPaneItem
  • ENominalTextLength
  • HOTKEYS
  • iHotKeyCode

Extensions to the API

None.

Glossary

None.

Abbreviations

Options Menu API abbreviations

API Application Programming Interface

ID

Identifier

OS

Operating System