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.
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).
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
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:
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
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.