Purpose

Popup controls are UI components that are displayed in a user intrusive fashion above the main pane. They in most cases expect user input, in few cases they just provide read only information for the user. In this document, the uses of popup list and popup heading components are covered.

A popup list is a window-owning host control to many kinds of list or grid components with default softkey observer behavior and with automatically calculated size that is determined by its contained control. A popup heading is a control that is used to display the title in certain dialogs. The popup heading component is mainly used by popup lists, message and list queries. More information about message and list queries can be found in Queries API documentation.

Constraints

None.

Classification and release information

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

API description

The API exposes the functionality through which the user can create, initialize, change a popup list control as well as retrieve user selection from them. Furthermore there is a way to add a find box to the popup list that would interact to provide a UI based filtering mechanism.

The main functionality of this API is available through the CAknPopupList class. The class is mostly used in situations when the user is required to select an item from a list. There can be cases when a list is just providing read-only information to the user (e.g. today’s call list).

The CAknPopupList class furthermore provides the necessary framework for adding the listbox to the control stack, attaching commands to the CBA relevant to the list box type, and processing all key events. The class also removes itself from the control stack and removes the CBA bindings when the user dismisses the popup list.

The list placed into the popup list can be of any kind such as a regular text list, markable list or multi-selection list as long as they are derived from the CEikListBox class. Popup API does not provide any means to register popup list specific observers to it. If it is important to observe state changes (e.g. the title needs to be changed as user moves the highlight) then registering a list observer to the contained list is recommended.

This API provides also a popup heading component, encapsulated in the CAknPopupHeadingPane class. It provides functions to modify the title text and set header image and animation. The CAknPopupHeadingPane class is used by popup list, message and list queries.

Use cases

The main use cases of Popups API are:

  • Initialization of the popup list

    • Basic initialization

    • Enabling find box

  • Showing the popup list

  • Retrieving user response

  • Dismissing the popup list

  • Customizing popup lists

  • Accessing popup heading

  • Setting text to popup heading

  • Manipulation of the popup heading image

  • Manipulation of the popup heading animation

API class structure

A number of classes are directly or indirectly involved when using Popups API.

The class diagram in Figure 1 shows that popup uses a CEikListBox created by the client and maintains a reference to it throughout its lifetime. A heading of type CAknPopupHeadingPane is optionally created depending on whether the user specified a title or not. A find box ( CAknSearchField ) is created optionally while the CBA softkeys are an integral part of the popup (the user can specify on construction what CBA structure to use and it can be changed later too).

Relevant constituents of Popups API


Relevant constituents of Popups API

Related APIs
  • CAknPopupHeadingPane
  • CAknSearchField
  • CEikListBox
Related APIs
  • CAknPopupHeadingPane
  • CAknPopupList
  • CEikListBox

Using Popups API

Initialization of the popup list

Basic Initialization

The first thing a developer needs when dealing with popup list is a list (using lists is not a subject of this document, if you want a thorough list usage guide then consult the header link List API document.)

As the list itself needs a parent we cannot initialize the list before creating the popup list. So the proper order is:

  • Construct the list using the standard leaving new operator.

  • Create the popup list using its NewL() static function.

  • Finally initialize the list (Call its ConstructL() ) .

In the code below and hereinafter we will use an imaginary client class called CMyClient .

              
               CMyClient::ShowMyPopupListL()
               
    {
    // Create a list instance:
    CEikListBox* list = new( ELeave ) CAknSinglePopupMenuStyleListBox;
    CleanupStack::PushL( list );//prevent memory leaks
     
    // Couple the popup with the list:
    // We need to create the popup now as list would need it as a parent.
    CAknPopupList* popup = CAknPopupList::NewL( 
                 list, // passing our list to the popup
                       // ownership is not taken
                 R_AVKON_SOFTKEYS_OK_BACK, // softkey resource id.
                 AknPopupLayouts::EMenuWindow);// popup layout type
    CleanupStack::PushL( popup );
    list->ConstructL( popup,CEikListBox::ELeftDownInViewRect );
    // Finish list initialization:
    list->View()->SetListEmptyTextL( _L( "List is empty" ) );
    list->CreateScrollBarFrameL( ETrue );
    list->ScrollBarFrame()->SetScrollBarVisibilityL(
                    CEikScrollBarFrame::EOff,
                    CEikScrollBarFrame::EAuto);
    // Add items to the list:
    CDesCArrayFlat* items = new(ELeave)CDesCArrayFlat( 1 );
    CleanupStack::PushL( items );
    for ( TInt ii=0; ii<8; ii++ )
        {
        TBuf<80> text;
        text.Format( _L( "Listbox Item %d" ), ii+1 );
        items->AppendL( text );
        }

    CleanupStack::Pop(); // items
    CTextListBoxModel* model=list->Model();
    model->SetItemTextArray( items );
    model->SetOwnershipType( ELbmOwnsItemArray );
    …   
    }

It is important to note that CAknPopupList::NewL() takes an AknPopupLayouts::TAknPopupLayouts parameter which provides the popup with layout info (i.e. how exactly are position and size of the popup and the contained components). To avoid an unwanted look you need find out the right value based on the list type you use. See header AknPopupLayout.h class AknPopupLayouts .

Related APIs
  • AknPopupLayouts
  • AknPopupLayouts::TAknPopupLayouts
  • CAknPopupList::NewL()
  • CMyClient
  • ConstructL()
  • NewL()

Enabling find box

It is also possible to add a find box to the popup. It is mostly important when the number of items in the list can be high so the user can filter the list items while typing: only the items which match the typed characters are shown. This is how the initialization code needs to be augmented.

              
               CMyClient::ShowMyPopupListL()
               
    {
    … // code from initialisation section
    popup->EnableFind();
        
    }

The CAknPopupList EnableFind() call returns a TBool to indicate if construction was successful. Use it if you want to have error handling code for the failure case.

Related APIs
  • TBool

Showing the popup list

After initialization the popup is ready to be displayed. It is fairly simple to do.

             
              CMyClient::ShowMyPopupListL()
              
    {
    … // code from initialisation section (with or without the optional part
    popup->ExecuteLD();  
    CleanupStack::Pop(); //popup
    CleanupStack::PopAndDestroy(); //list
    }

The code above does not process user input, which is unlikely to be acceptable in a real situation.

Notice CleanupStack::Pop() after ExecuteLD() , that is required as during the initialization the popup was put on the cleanup stack. Removing it from there should be done after ExecuteLD() . ExecuteLD() deletes the popup so PopAndDestoy() is not recommended). This ensures leave-safety. Note if the popup is declared as a member of the class then you would need to set it to NULL after the ExecuteLD() to avoid double deleting in the destructor. Of course in this case the popup must not be pushed on the cleanup stack.

The list object has to be destroyed as the popup does not take care of that. That is done by the final PopAndDestroy() .

ExecuteLD() displays the popup on the screen and does not return until the user dismisses it or a CancelPopup() is called in the code. This however is a non-blocking function from the whole application point of view. This means that the application can still receive all kinds of events (e.g. network events, timer events). The technique the popup uses is the same as with dialogs – it nests a new active scheduler loop. Being aware of this is important, another event handling code (i.e. CActive::RunL() ) may still be running while the popup is shown. If you need to access the popup while its ExecuteLD() is running then it should be declared as a member variable.

Related APIs
  • CActive::RunL()
  • CancelPopup()
  • CleanupStack::Pop()
  • ExecuteLD()
  • PopAndDestoy()
  • PopAndDestroy()

Retrieving user response

In a usual scenario it is natural to expect that the client can get hold of the user response (let it be the selected item or the marked item). There are two aspects of it:

  • Did the user dismiss the popup indicating a cancellation of a started operation?

  • If the user accepted the prompt what was the response?

To find an answer to the first question the return value of ExecuteLD() needs to be checked. The user response on the other hand can be received from reading the list state.

             
              CMyClient::ShowMyPopupListL()
              
    {
    … // code from initialisation section (with or without the optional part
    if ( popup->ExecuteLD() )
        {
        TInt index = iList->CurrentItemIndex();
        TBuf<50> text;
        text.Format(_L("Item %d selected"), index+1);
        User::InfoPrint(text);
        }
     else
        {
        User::InfoPrint(_L("Listbox Cancelled"));
        }
    CleanupStack::Pop(); //popup
    CleanupStack::PopAndDestroy(); //list
    }
Related APIs
  • ExecuteLD()

Dismissing the popup list

While the popup is shown all user events are forwarded to it. However it is possible to get other events from the system. Some events would result in a new UI state where the popup is not needed anymore. The developer has the means to dismiss the popup programmatically. To be able to do that the popup has to be accessible through a member variable. We assume that the iPopup member variable points to the popup list object (or NULL if it is dismissed).

             
              CMyClient::DismissPopupListL()
              
    {
    if ( iPopup )//Checking for NULL is needed because if the popup is dismissed iPopup is set to NULL
        {
        iPopup->CancelPopup();
        iPopup = NULL;
        }
    }

The CancelPopup() call makes the ExecuteLD() call return (in the next active scheduler loop) and its return value is EFalse indicating cancellation.

Note: It is not possible to use delete iPopup instead of iPopup->CancelPopup() because the destructor of CAknPopupList is a protected method.

Related APIs
  • CAknPopupList
  • CancelPopup()
  • EFalse
  • ExecuteLD()
  • NULL
  • iPopup
  • iPopup->CancelPopup()

Customizing popup lists

CAknPopupList may be derived in order to provide a specific type of popup list. That is, for a text-only popup selection list, the NewL() function may be overloaded in order to create a listbox of a specific type, before passing it to the CAknPopupList::NewL() function.

It maybe necessary to override the AttemptExitL() function to save the return value in that (e.g. if you do want to store the return value in pointer passed on construction).

By overriding OfferKeyEventL() it is possible to make the derived popup list react to key events that the base class ignored (e.g. it can delete an item from the list when Clear key is pressed).

ProcessCommandL should be overwritten when new nonstandard commandIDs are attached to the CBA in the resource. By default the following Avkon command ids are handled as a positive reply (OK) to the popup list: EAknSoftkeySelect , EAknSoftkeyYes , EAknSoftkeyOk , EAknSoftkeyDone .

Whereas EAknSoftkeyExit , EAknSoftkeyClose , EAknSoftkeyNo , EAknSoftkeyCancel , EAknSoftkeyBack are handled as a negative answer from the user.

Note: If you want to provide a more specific popup list through derivation do not forget to hide the functions of the base class that you do not intend to expose to the users.

Related APIs
  • AttemptExitL()
  • CAknPopupList
  • CAknPopupList::NewL()
  • EAknSoftkeyBack
  • EAknSoftkeyCancel
  • EAknSoftkeyClose
  • EAknSoftkeyDone
  • EAknSoftkeyExit
  • EAknSoftkeyNo
  • EAknSoftkeyOk
  • EAknSoftkeySelect
  • EAknSoftkeyYes
  • NewL()
  • OfferKeyEventL()
  • ProcessCommandL

Accessing popup heading

As we said earlier, popup heading is used not only by popup list, but also by other UI components. The heading is implemented by the class CAknPopupHeadingPane .

Typical use-cases for popup heading:

  • Popup list ( CAknPopupList ),

  • Queries, especially message and list queries ( CAknQueryDialog -derived classes: CAknMessageQueryDialog , CAknListQueryDialog ).

More information about the query dialogs can be found in Queries API documentation.

In case of popup list, the heading cannot be set from resource - it can be set only from code. After setting the title with SetTitleL() with a non empty text, CAknPopupList::Heading() should return the CAknPopupHeadingPane object associated with the heading of the popup:

             
              CMyClient::ShowMyPopupListL()
              
    {
    … // code from initialisation section
    popup->SetTitleL( _L( "My popup title" ) );
    CAknPopupHeadingPane* heading = popup->Heading();
    …
    }

In case of queries, CAknQueryDialog::QueryHeading() should return the CAknPopupHeadingPane object associated with the heading of the query (see Queries API documentation):

             
              CMyClient::ShowMyMessageQueryL()
              
    {
    … // initialization of message, heading
    CAknMessageQueryDialog* dlg = CAknMessageQueryDialog::NewL(*message);
    dlg->PrepareLC(R_AVKON_MESSAGE_QUERY_DIALOG);
    dlg->QueryHeading()->SetTextL(*header);
    dlg->RunLD();
    … // releasing message, heading
    }
Related APIs
  • CAknListQueryDialog
  • CAknMessageQueryDialog
  • CAknPopupHeadingPane
  • CAknPopupList
  • CAknPopupList::Heading()
  • CAknQueryDialog
  • CAknQueryDialog::QueryHeading()
  • SetTitleL()

Setting text to popup heading

In case of queries, heading text is usually defined in the resource (see Queries API documentation), but there is the possibility to set the text from code with the help of the CAknPopupHeadingPane::SetTextL() method.

In case of popup list, it is optional to add a title to the popup during initialization. It will implicitly create a heading object (to which it is possible to get a pointer) in the popup.

             
              CMyClient::ShowMyPopupListL()
              
    {
    … // code from initialisation section
    popup->SetTitleL( _L( "My popup title" ) );
    … 
    }
Related APIs
  • CAknPopupHeadingPane::SetTextL()

Manipulation of the image

We can enhance the look of the popup heading by decorating it with an image.

The following example illustrates the setting of a header image in case of a popup list:

             
              CMyClient::ShowMyPopupListL()
              
    {
    … // code from initialisation section
    popup->SetTitleL( _L( "My popup title" ) );
    CAknPopupHeadingPane* heading = popup->Heading();
    if ( heading )
        {
        _LIT( KMyImageLocation, "c:\\flower.mbm" );
        CEikImage* img = new (ELeave) CEikImage();
        CleanupStack::PushL( img );
        img->CreatePictureFromFileL( KMyImageLocation, 0, 1 );
        heading->SetHeaderImageL( img );
        CleanupStack::PopAndDestroy();//img
        }
     …
     }

Note: the CAknPopupHeadingPane object is created inside the popup list using a lazy construction method. That is it only is constructed when needed. In this particular case that happens after the popup->SetTitleL() call.

Related APIs
  • CAknPopupHeadingPane
  • popup->SetTitleL()

Manipulation of the animation

It is also possible to add an animation to the heading in a similar way. There CAknPopupHeadingPane::SetHeaderAnimationL() needs to be passed the resource ID associated with the animation. The animation is started automatically but can be controlled externally through CAknPopupHeadingPane::StartAnimationL and CancelAnimation() functions.

Related APIs
  • CAknPopupHeadingPane::SetHeaderAnimationL()
  • CAknPopupHeadingPane::StartAnimationL
  • CancelAnimation()

Error handling

Popups API uses standard Symbian platform error reporting mechanism. It does not define any panic codes of its own. Leaves and system wide error codes as the 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 popup list largely depends on the list added to it and the number of list items that are contained in a static list model. A popup list and a popup heading have a very minimal overhead.

Limitations of the API

This API cannot be used by a component without a UI environment (e.g. a Symbian server process cannot use the API). The API does not have functionality for a dedicated Options menu to the popup.

Glossary

Abbreviations

Popups API abbreviations

API Application Programming Interface

CBA

Command Button Area

ID

Identifier

OS

Operating System

Definitions

Popups API definitions

Popup A window owning container control to other controls.

Find box

A box that can come with a list to provide ‘filtering as you type’ mechanism.