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 S60 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.
API category | public |
API type | c++ |
Existed since | Legacy S60 0.9 |
API libraries | avkon.lib |
Location | /sf/mw/classicui/classicui_pub/popups_api
|
Buildfiles | /sf/mw/classicui/classicui_pub/popups_api/group/bld.inf
|
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.
Popup API is an SDK API and part of S60 release 3.x.
None.
The main use cases of Popups API are:
Classes | Files |
---|---|
|
/epoc32/include/mw/aknpopuplayout.h
CAknPopupField
/epoc32/include/mw/AknPopupField.h
CAknPopupField::CAknPopupFieldBitmapButton
/epoc32/include/mw/AknPopupField.h
CAknPopupFieldList
/epoc32/include/mw/AknPopupFieldList.h
CAknPopupFieldText
/epoc32/include/mw/AknPopupFieldText.h
CAknPopupHeadingPane
/epoc32/include/mw/aknPopupHeadingPane.h
CAknPopupList
/epoc32/include/mw/aknPopup.h
CAknPopupSettingList
/epoc32/include/mw/aknpopupsettingpage.h
CAknPopupSettingPage
/epoc32/include/mw/aknpopupsettingpage.h
MAknFadedComponent
/epoc32/include/mw/AknPopupFader.h
MAknPopupFieldObserver
/epoc32/include/mw/AknPopupField.h
MAknPopupSettingListObserver
/epoc32/include/mw/aknpopupsettingpage.h
TAknPopupFader
/epoc32/include/mw/AknPopupFader.h
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).
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:
NewL()
static function.
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
.
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.
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.
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:
operation?
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 }
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.
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.
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:
CAknPopupList
),
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 }
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" ) ); … }
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.
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.
Popups API uses standard Symbian OS 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 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.
This API cannot be used by a component without a UI environment (e.g. a Symbian OS server process cannot use the API). The API does not have functionality for a dedicated Options menu to the popup.
API | Application Programming Interface |
CBA | Command Button Area |
ID | Identifier |
OS | Operating System |
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. |