A Progress Hate
Saving Gome

Declaring a Progress Note
A progress note contains a progress bar. At regular intervals during the execution of the process it is necessary to increment and redraw the progress bar. The process needs to run asynchronously in small steps, preferably using an Active Object Otherwise, the thread will block and the note will not update or may not even display until the processing is complete.
An Active Object is created in the usual way by deriving from CActive. In ProgressNote, CProgressNoteGameSaverAO is declared as an Active Object:
class CProgressNoteGameSaverAO : public CActive, MProgressDialogCallback private: // from CActive void RunLQ; void DoCancel();
private: //data CAknProgressDialog* iProgressDialog;
A progress note is a nonwaiting dialog. That is, while the dialog is executing, the application can continue processing in the background. This is essential if the note is to update correctly. A progress note should be declared as member data, and then deleted in the class destructor. If execution completes normally—that is, no leave occurs—the progress note deletes itself and sets the pointer to it to NULL. However, if a leave occurs during the background processing, the note has no knowledge of this and cannot delete itself. Therefore, its deletion must be handled in the destructor. (You will see how it is possible for the dialog to null the pointer to itself in the next step of the ProgressNote example.)
Creating a Progress Note for a Variable-Length Process
A progress note is constructed just before a long-running process is about to begin, usually within an Active Object. In
ProgressNote, the note is constructed in CProgressNoteGameSaverAO::SaveGameL().
[View full widthl void CProgressNoteGameSaverAO::SaveGameL0
iProgressDialog = new (ELeave) CAknProgressDialog(reinterpret_cast<CEikDialog**> * (&iProgressDialog));
There are two constructors that can be used to create a variable-length progress note. The one used here creates a progress note that will display only after 1.5 seconds of processing and will display for a minimum of 1.5 seconds. If the processing completes within the initial 1.5 seconds, the note will not be displayed. This stops the note from flashing on screen and then disappearing in the case of short processes. The other constructor has a TBool parameter, which can be set to ETRue to prevent this delay. Use this only if you are certain that processing will take at least 1.5 seconds.
Both constructors have a parameter referred to in the documentation as a self-pointer. It is actually the address of the member data pointer for the note, so in the ProgressNote example it is the address of iProgressDialog. The method expects a CEikDialog**, so a reinterpret cast is required, as shown in SaveGameLO- The note sets the self-pointer to NULL when it deletes itself. As discussed in the previous step, this is to allow the safe deletion of the note in the destructor if necessary, without any possibility of a double deletion occurring.
Executing a Progress Note
Once the progress note is constructed, it can be prepared and run. This is performed in
CProgressNoteGameSaverAO::SaveGamel_0:
iProgressDialog->PrepareLC(R_PROGRESSNOTE_SAVING_GAME_NOTE); iProgressDialog->SetCallback(this);
CEikProgresslnfo* progressBar = iProgressDialog->GetProgresslnfoLO;
progressBar->SetFinalValue(KFinalValue);
iProgressDialog->RunLDO;
SaveGamePartToFileO;
progressBar->lncrementAndDraw(Klncrement);
SetActiveO;
As methods will be called on the progress note, the dialog is prepared for use by calling Preparel_C()and passing through the resource. (The definition of the DIALOG resource, r_progressnote_saving_game_note, can be found in ProgressNote.rss.)
As with all dialogs, progress notes are, by default, nonwaiting. Nonwaiting progress notes do not return a value when they finish executing, so this cannot be used to determine whether the user cancelled the note or the process completed normally. Instead, a callback is set on the note by calling CAknProgressDialog::SetCallback(), passing in an MProgressDialogCallback object. DialogDismissedLO is called on the callback object when the dialog has been dismissed. The mechanics of this function is discussed in detail later—see Completion of a Progress Note and User Cancellation.
As the progress bar will represent the proportion of the task completed, it is necessary to set the number of individual units for the bar. The progress bar, of type CEikProgresslnfo, can be retrieved by calling GetProgresslnfoL()on the dialog. A call to CEikProgresslnfo: :SetFinalValueO is used to set the number of units the bar represents. Note that, although GetProgresslnfoLO returns a pointer to the progress bar, the application does not take ownership of it.
The note is instantiated using RunLDO—this returns immediately, allowing processing to begin. The RunLDO method has a "D" suffix, which usually indicates that the object deletes itself just before the method returns. In common with other nonwaiting dialogs, however, the note does not delete when the RunLDO method returns. Instead it is deleted when ProcessFinishedLO is called, or, if the user dismisses the note, after a call to the DialogDismissedLO method (called by OkToExitLO).
The processing in the ProgressNote example is performed in the SaveGamePartToFileO function. This encapsulates an asynchronous request, hence the call to SetActiveO-
Updating a Progress Note as a Process Executes
It is necessary to update the progress bar at regular stages during the execution of the process and dismiss it when processing finishes. The Runl_0 of the Active Object is the natural place to do this.
void CProgressNoteGameSaverAO::Runl_0 if (NsProcessDoneO) SaveGamePartToFileO;
¡ProgressDialog->GetProgresslnfoLO->lncrementAndDraw(Klncrement); SetActiveO;
else iProgressDialog->ProcessFinishedl_0;
The Runl_0 method should first check whether all processing is complete. In the ProgressNote example, the local method IsProcessDoneO is used to determine this—it simply checks that a counter has not reached its limit. If processing is complete, the progress note should be informed by calling its ProcessFinishedLO method. The note will then call the DialogDismissedLO method and delete itself, setting its self-pointer to null.
If processing is not yet complete, then the following steps should be continued until it is:
1. Perform a step in the processing. The ProgressNote example simulates saving the game in the SaveGamePartToFileO method—this is the asynchronous request for the Active Object.
2. Update the progress bar accordingly, using the lncrementAndDraw() method. In the ProgressNote example, the steps are of even length, so the progress bar can be incremented by a constant value, Klncrement. If the process has uneven steps, you may use a variable for this. The progress bar, instead of being incremented and drawn, can be set and drawn using the SetAndDraw() method. This disregards any previous value for the progress bar and sets its position to that specified in the arguments to the method.
Set the Active Object to be active. This is so that RunL() is called again to complete the next step, if there Is one. The progress note will dismiss automatically, once It has been incremented sufficiently that It has reached its final value. The final value should be selected and Incremented with care, to ensure that It does not dismiss before the processing Is complete.
Completion of a Progress Note and User Cancellation
MProgressDialogCallback::DialogDismissedl_0 ¡S called when the progress dialog is dismissed. Perform any cleanup in this method—in the case of a user cancellation—or do further processing after a successful completion.
In the ProgressNote application, IsProcessDoneO is called to determine whether or not the processing was complete when the dialog was dismissed. If it was not, then the user must have chosen to cancel the processing, so the saving of the game will be canceled.
void CProgressNoteGameSaverAO::DialogDismissedL(Tlnt /*aButtonld*/) if (NsProcessDoneO)
CancelGameSaveO; else
CompleteGameSaveO;
iStepsCompleted = 0;
Fixed-Period Progress Notes
If the length of time a process will take is known, a progress dialog can be instantiated and its display can be updated automatically. Again, this is performed within an Active Object. However, the note object itself increments and redraws the progress bar automatically, so there is no need for this to be done in the code.
[View full widthl const Tint KFinalValue = 5; const Tint Klnterval = 100; const Tint Klncrement = 1;
SaveGamePartToFileO; SetActiveO;
¡ProgressDialog = new (ELeave) CAknProgressDialog(KFinalValue, Klncrement, Klnterval, * reinterpret_cast<CEikDialog**>(&iProgressDialog));
¡ProgressDialog->ExecuteLD(R_PROGRESSNOTE_SAVING_GAME_NOTE);
The following three parameters are required. They determine how the progress bar increments, and the length of the process:
• Final Value— As in the ProgressNote example, this determines the number of units in the progress bar.
• Increment— The number of units the progress will move when it is incremented.
• Interval— How often the progress bar increments in hundredths of a second.
For example, for a process that takes 5 seconds the bar could be 5 units long, with 1 -unit increments, and increments occurring every second. The progress note would display for 5 seconds. The following formula can be used to calculate approximate values for an application: duration = interval * final value / increment.
You may need to experiment with the values to make a progress bar update smoothly and to give it the appearance of doing something all the time. An interval of less than 100 can cause the total time the note displays to increase dramatically from what might be expected. Dismissing the dialog as soon as the processing is finished is possible, but it might be confusing for the user if the progress bar does not reach its final value.
Global Notes
A global note dialog is displayed on screen even if the application that owns it is not in focus. The code used to display a global note is quite simple, but should be used sparingly. It does not require the definition of a note in a resource structure, although this can be done for a customized note.
Construction and execution of a global note is performed using the NewLCO and ShowNoteLO methods. A note type is supplied to the ShowNoteLO method, plus the text to be displayed. The aknnotifystd.h header file defines the possible note types in the TAknGlobalNoteType enumeration.
HBufC* noteText;
noteText = StringLoader::LoadLC(R_GLOBAL_NOTE_TEXT);
CAknGlobalNote* globalNote = CAknGlobalNote::NewLCO;
iNoteld = globalNote->ShowNoteL(EAknGlobalPermanentNote, *noteText);
CleanupStack::PopAndDestroy(globalNote);
CleanupStack::PopAndDestroy(noteText);
All global notes have a CancelNoteLO method that can be called to dismiss them. This method requires the ID of the note to be cancelled—the ID returned when calling the ShowNoteLO method. Permanent notes do not timeout and cannot be dismissed by the user, they must be cancelled programmatically using CancelNoteLQ-
WARNING
Global notes do not have menus or soft keys defined and so will lock the Ul of a device until cancelled.
^ Previous
Queries
Series 60 applications use various queries to ask the user a question, which may determine how the application then proceeds. A response to a query may require the user to enter some data, select one or more items from a list or simply confirm an action. The basic types of query are a confirmation query, a data query, a list query and a global query.
A confirmation query poses a question to which there is only a positive or a negative response—for example, confirming whether a saved game should be deleted. It is possible for a confirmation query to have a single answer. A data query requests that a user enter some text, for example, a player's name. The text can be plain or formatted as a password, PIN, phone number, date, time, duration, or floating-point number. Table 6-3 provides a more comprehensive list of the different types. A multiline data query can have two lines of text, each plain or formatted as per single-line data queries.
|
Type |
Class |
Layout |
Control |
|
Plain Text |
CAknTextQueryDialog |
EDataLayout |
EDWIN |
|
Phone |
CAknTextQueryDialog |
EPhoneLayout |
EDWIN |
|
Number | |||
|
PIN |
CAknTextQueryDialog |
EPinLayout |
SECRETED |
|
Password |
CAknTextQueryDialog |
ECodeLayout |
SECRETED |
|
Date |
CAknTimeQueryDialog |
EDateLayout |
DATE_EDITOR |
|
Time |
CAknTimeQueryDialog |
ETimeLayout |
TIME_EDITOR |
|
Duration |
CAknDurationQueryDialog |
EDurationLayout |
DURATION_EDITOR |
|
Float |
CAknFloatingPointQueryDialog |
EFIoatingPointLayout |
FLPTED |
|
Multiline |
CAknMultiLineDataQueryDialog |
Each |
Varies depending on usage. Up |
|
AVKO N_DATA_Q U ERY |
to two lines. | ||
|
has a value from | |||
|
EAknMultilineData Layout | |||
|
depending on the type of | |||
|
control | |||
|
Number |
CAknNumberQueryDialog |
ENumberLayout |
AVKON_INTEGER_EDWIN |
A list query contains a menu list, from which one or more items can be selected. Items in the list can contain one or two lines of text, with or without an icon or heading. As with all lists, items must have the same type of content.
Queries can be local to the application or global. The three types mentioned earlier are all local. Series 60 hides local queries when another application switches to the foreground, but global queries are not hidden.
NOTE
Global queries are not dialogs, strictly speaking, as they do not inherit from CEikDialog.
You can use global queries for servers or applications that are currently in the background. Do this only if the information to be conveyed to the user is very important. If you display a global query from your application, the user cannot switch away to another application until they dismiss it. Global queries can be used to confirm an action, display a message or request an item be selected from a list. The different types are listed in Table 6-4.
_Table 6-4. Global Queries_
Type of Global Query Description
Confirmation Poses a question in a global manner, such as confirming whether to deleteall games. You can customize a global confirmation query so that it plays a tone, dismisses with any key rather than just the soft keys, or shows a different icon and animation.
Message Displays a message with a header—for example, informing that the current game will close. You can customize a global message query so that it plays a tone and/or shows a small icon in the top right-hand corner.
List Contains a selection list from which you can select an item. The items can contain a single line of text only. The query focuses the first item of the list by default, but you can change this.
The following section discusses three example applications that deal with data queries (DataQuery), list queries (ListQuery), and global queries (GlobalQuery). A confirmation query is very similar to a data query and therefore is not covered explicitly here, although sample code can be found in DataQuery.
Data Queries
The example application DataQuery provides sample implementations of both a confirmation query and a data query. As you would expect, the techniques involved in creating these dialogs are similar, and therefore only the data query will be analyzed in detail here.
DataQuery has just one menu option, Exit. If the user chooses to exit the application, a dialog is shown asking if they would like to save the game. This dialog is a confirmation query with soft key options ofYes and No, as shown in Figure 6-23.
- Figure 6-23. Confirmation query.
If the user decides to save the game, a data query is displayed, requesting a name for the saved game, as shown in Figure 6-24. This subsection describes how to define and execute the data query.
- Figure 6-24. Data query.
Defining a Data Query in Resource
As a data query is a type of dialog, it should be defined in a DIALOG resource.
RESOURCE DIALOG r_dataquery_data_query flags = EGeneralQueryFlags;
buttons = R_AV KON_SOFTKEYS_OK_CANCEL;
DLG_LINE {
type = EAknCtQuery;
id = EDataQueryDlgCldDataQuery;
control = AVKON_DATA_QUERY {
layout = EDataLayout; control =
EDWIN {
width = KMaxGameNameLength; lines = 1;
maxlength = KMaxGameNameLength; };
The flags should be set to EGeneralQueryFlags or EAknGeneralQueryFlags—both equate to the same thing. The dialog should contain a single dialog line, which contains the query control. An appropriate layout for the DataQuery example is EDataLayout—other layouts are defined in avkon.hrh. An EDWIN control is used for the data entry. Optionally, it is possible to set the text for the control's label, but in DataQuery, the label text is set dynamically.
Table 6-3 shows the type of control to use for each type of query. Chapter 8 gives more details on EDWIN and other editor resources.
Constructing and Executing a Data Query
The general method for executing a data query is to construct it using the Newl_()method and execute it using ExecuteLD(). In DataQuery this is performed in CDataQueryContainer::SaveGamel_(). A descriptor representing the game's name is passed into the query on construction. This will be modified using the contents of the editor control.
TBuf<KMaxGameNamel_ength> gameName;
CAknTextQueryDialog* gameNameQuery = CAknTextQueryDialog::NewL(gameName); CleanupStack::Pushl_(gameNameQuery);
HBufC* prompt = StringLoader::LoadLC(R_DATA_QUERY_PROMPT); gameNameQuery->SetPromptL(*prompt);
NOTE
A heading can be set for a query, and this should be constructed as a dialog line. The exception to this is a multiline data query. This has two dialog lines, each of which must contain a query.
CleanupStack::PopAndDestroy(prompt); CleanupStack::Pop(gameNameQuery);
if (gameNameQuery->ExecuteLD(R_DATAQUERY_DATA_QUERY)) SaveGameToFileL(gameName);
# CAknQueryDialog is the base class for all local queries. It provides
TfP overloaded NewL() methods, which construct an appropriate derived class based on the type of the argument.
After constructing the query, a prompt can be set that will be displayed with the control. This is done by calling the SetPromptL() method, passing in a constant reference to a descriptor containing the prompt. InDataQuery, a string is loaded from resource into the prompt descriptor. Because the method is not leave-safe, the query should be put onto the Cleanup Stack before it is called. However, before ExecuteLD() is called, it must be popped off the stack, because the query will put itself onto the Cleanup Stack as part of the execution.
List Queries
A list query contains a menu list, from which the user can select one or more items. Items in the list can contain one or two lines of text with or without an icon or heading. As with all lists, items must have the same type of content. This subsection gives details of how to construct a list query, with the application ListQuery providing the basis of the discussion. This application is very similar to the previous example, DataQuery, but instead of asking the user to enter a name for the saved game, it presents a list of names for the user to choose from, as shown in Figure 6-25.
Figure 6-25. List query.
|
List Query | ||
|
Select a game: | ||
|
Saued Game 1 | ||
|
Saved Game 2 Saued Game 3 Saued Game 4 | ||
|
Gk Cancel | ||
List Query Resources
The resource type for a list query is an AVKON_LIST_QUERY resource. The resource should have a single dialog line, AVKON_LIST_QUERY_DLG_LINE, containing an AVKON_LIST_QUERY_CONTROL. The control should define the listtype field to indicate the type of list the query will contain. This could be one of the pop-up menu list types, but in ListQuery a single line of text is chosen. The listbox refers to an AVKON_LIST_QUERY_LIST resource. To define the list items statically, an array identifier can be specified. The arrayjd specified in the AVKON_LIST_QUERY_LIST resource structure can refer to another resource containing an array of static strings representing the list items. In the ListQuery example, the list items are going to be defined dynamically, so the resource is left blank.
RESOURCE AVKON_LIST_QUERY r_listquery_list_query
items =
control = AVKON_LIST_QUERY_CONTROL
listtype = EAknCtSinglePopupMenuListBox; heading = SELECT_GAME_TEXT;
listbox = AVKON_LIST_QUERY_LIST {
// array of items will be defined dynamically };
, The AVKON_LIST_QUERY has aflags field, which defaults to
TfP EGeneralQueryFlags, and asoftkeys field, which defaults toOk and
Cancel. These values can be overridden for a custom list query.
Creating and Executing a List Query
In ListQuery, the query list is created in CListQueryContainer::SaveGamel_(). The CAknListQueryDialog constructor takes a reference to a Tint. This represents the index of the selected item and can be set to a nonzero value to preselect a particular item in the list. The Tint passed in is updated by the control with the user selection.
Tint index(O);
CAknListQueryDialog* query = new (ELeave) CAknListQueryDialog(&index);
As you might expect, the list query contains a list, which in turn contains an item array. In ListQuery, an item array is a set up in the local method SetupListQueryltemArrayL(), which is called from
CListQueryContainer::ConstructL(). The item array is a standard list item array, which is covered further in Chapter 7.
Setting the item array is done once the construction of the query is completed by PrepareLC(). In ListQuery this is performed in CListQueryContainer::SaveGameL() by calling the query's SetltemTextArray() method.
query->PrepareLC(R_LISTQUERY_LIST_QUERY);
query->SetltemTextArray(iListQueryltemArray);
query->SetOwnershipType(ELbmDoesNotOwnltemArray);
To see which item was selected by the user, rather than just its index, the application should take ownership of the item array by calling SetOwnershipType(). The query destroys itself after execution, so if the application does not take ownership of the array, it will be destroyed too.
A list query is invoked in the same manner as other queries—that is, using PrepareLC() and RunLD()or using ExecuteLD(). In ListQuery, PrepareLC() is used, so RunLD() is used for execution.
if (query->RunLD()) SaveGameToFileL((*iListQueryltemArray)[index]);
The execution methods return a TBool indicating whether the user closed the query by pressing Ok (Etrue) or Cancel (EFalse). Assuming the application owns the item array, it can obtain the selected item, by using the Tint passed to the query on construction, to index into the array of items. Here the resulting list item is passed to a local method called SaveGameToFileLQ.
Multiselection List Queries
A multiselection list allows the user to choose more than one list item. A multiselection list query is created in the same way as a list query, with the following exceptions:
• An AVKON_MULTISELECTION_LIST_QUERY_DLG_LINE is used rather than a AVKON_LIST_QUERY_DLG_LINE in the AVKON_LIST_QUERY.
• The listboxin the AVKON_LIST_QUERY_LIST is set to bean AVKON_MULTISELECTION_LIST_QUERY_LIST.
• The list items will need to contain an icon index to refer to the check box—for example, "1 \tMy Item". The list class supplies the bitmaps for the check boxes automatically, so unlike in multiselection lists, adding them to the list's icon array is not required.
• The list query is constructed, passing in a Tint array (C Selection I ndexArray). This will contain the indices of the selected items, once the query is dismissed.
Using Global Queries
A global query always takes focus, even when the application that owns it is running in the background. The user cannot task away from a global query, they must dismiss it, and so this type of query should be used sparingly—applications should not dominate the screen if the user has tasked away.
Global queries are slightly more complex than the queries seen so far. Their functionality relies on both the notifier framework and the Active Object mechanism. The notifier framework is an operating system facility that allows messages or dialogs to be displayed.
To produce a global query, an Active Object has to be constructed to handle the dismissal of the dialog.
The example application, GlobalQuery, implements a global query to inform the user that a game will be closed, as shown in Figure 6-26. This note is displayed when the application is opened.
- Figure 6-26. Global query.
Creating a Global Message Query
GlobalQuery does nothing more than create a global query and then handle its dismissal—no other processing takes place. The query is created by the container class, CGIobalQueryContainer, during its construction. An Active Object, CGIobalQueryQueryHandlerAO, handles the notification of the dialog's dismissal from the framework. Because the GlobalQuery example is trivial, the Active Object simply informs an observer class that the dialog has been closed.
Since the container launches the query, it is also defined as the observer. The container class therefore implements the interface, MGIobalQueryCloseGameObserver, which has one method, CloseGameL(). A reduced class definition for CGIobalQueryContainer, presenting only the parts involved in the query construction, is shown below:
class CGIobalQueryContainer: public CCoeControl, MGIobalQueryCloseGameObserver public: // from MGIobalQueryCloseGameObserver void CloseGameLQ;
private: // constructor void ConstructL(const TRect& aRect);
private: //data CGIobalQueryQueryHandlerAO* ¡QueryHandlerAO;
CAknGlobalMsgQuery* iGlobalMsgQuery; };
Before a global query can be executed, the Active Object (CActive derived class) must be constructed and set active. As the query is shown upon startup of GlobalQuery, this is performed in
CGIobalQueryContainer::ConstructL().
¡QueryHandlerAO = CGIobalQueryQueryHandlerAO::NewL(*this); ¡QueryHandlerAO->Start();
The NewL() function of the Active Object takes a reference to a MGIobalQueryCloseGameObserver object. As the container class itself is the observer, a dereferenced this pointer is passed in.
In the GlobalQuery example, the Active Object's Start() method initiates the process. It simply sets it to be active using the SetActive() method.
The query itself is created in the container's ConstructL() method: IView full width]
HBufC* header = StringLoader::LoadLC(R_GLOBALQUERY_HEADER_TEXT); HBufC* message = StringLoader::LoadLC(R_GLOBALQUERY_MESSAGE_TEXT);
¡GlobalMsgQuery = CAknGlobalMsgQuery::NewL();
¡GlobalMsgQuery->ShowMsgQueryL(iQueryHandlerAO->iStatus, "message, * R_AVKON_SOFTKEYS_OK_CANCEL, *header, KNullDesC);
CleanupStack::PopAndDestroy(message); CleanupStack::PopAndDestroy(header);
A global message query is constructed via NewL()and is executed using the ShowMsgQueryL() method. ShowMsgQueryL() has a number of parameters, some of which have default values and so are optional:
• TRequestStatus& aStatus— The ¡Status of the Active Object that will handle the query's dismissal. The message query will set this to the value of the soft key used to dismiss it, which in turn will cause the Active Object's RunLQ method to run.
• const TDesC& aMsgText— The text the query will display.
• Tint aSoftkeys— The resource identity for the soft keys.
• const TDesC& aHeaderText— A heading for the query.
• const TDesC& aHeaderlmageFile— The name of the file containing the icon to be displayed with the query. The file should be an .mbg file. Set this to an empty string using KNullDesC if an icon is not required.
• Tint almageld— The ID of the icon to be used for the query. This is optional, but must be specified if a file name is given in the previous parameter.
• Tint almageMaskld—The ID of the icon mask. This is optional, but it must be specified if a file name is given in the previous parameter.
• CAknQueryDialog::TTone aTone— Tone to play when the query displays (optional).
Handling Dismissal of a Global Message Query
When the query is dismissed by the user, it causes the Active Object's RunL() to be called: void CGIobalQueryQueryHandlerAO::RunL()
¡CloseGameObserver.CloseGameLO; }
Testing the value of ¡Status will reveal which soft key dismissed the query, and appropriate action can be taken. (The soft key values are defined in avkon.hrh.) In the GlobalQuery example, if Ok is pressed, MGIobalQueryCloseGameObserver::CloseGameL() is called, which is implemented in the container. The Active Object is then cancelled, using its CancelQ method.
It Is very Important that the RunLQ method should complete quickly.
Other Global Queries
In addition to global message queries, global confirmation queries and global list queries can be created. Creating these types of queries is very similar to creating the global message query. A global confirmation query should be created using CAknGlobalConfirmationQuery::NewL()and executed using ShowConfirmationQueryL(), while a global list query is created using CAknGlobalListQuery::NewL() and executed with ShowListQueryL().
List Dialogs
Series 60 provides two types of list dialogs: a selection list dialog, as shown in Figure 6-27, and a markable list dialog, as shown in Figure 6-28. The lists behave in the same way as standard lists, but are contained within a dialog. A selection list dialog can optionally have a find pane—this allows the user to search for items in the list by entering matching characters from the start of the item name.
Figure 6-27. Selection list dialog with find pane.
|
3 |
3 Level | ||
|
□ Q |
PR Level B Level | ||
|
* |
i | ||
|
□k |
Cancel | ||
Figure 6-28. Markable list dialog.
|
P Level PP Level |
•s | |
|
B Leuel |
•s | |
|
Gk |
Cancel | |
Both types of list are constructed using the same techniques. The focus in this subsection is on the selection list dialog—the application ListDIg is used to illustrate the main principles involved.
On startup, the ListDIg application displays a list of saved games. Each has a small icon representing the number of players and a single line of text representing the name. There is a find pane at the bottom of the screen, which allows the user to search for items in the list. As characters are typed in, a filter is applied to the list so that only those items that match the entered text are listed, as shown in Figure 6-29. In the ListDIg example, selection of an item from the list results in a call to the empty method PlaySelectedGameQ—no game-playing functionality has been implemented.
- Figure 6-29. List filtering.
Defining a Selection List Dialog in a Resource
A selection list dialog should be defined in a DIALOG resource structure. A find pane is implemented in the resource file, so the DIALOG resource structure in this example has two DLG_LINE sections. If the filtering facility is not required, the second line can simply be omitted. The list items could be defined dynamically in the code, but here they are defined statically in the resource r_listdlg_list_array:
RESOURCE DIALOG r_listdlg_dialog flags = EAknDialogSelectionList;
buttons = R_AV KON_SOFTKEYS_OK_CANCEL;
DLG_LINE {
type = EAknCtSingleGraphicListBox; id = ESelectionListControl;
control = LISTBOX {
flags = EAknListBoxSelectionList;
arrayjd = r_listdlg_list_array; };
DLG_LINE {
itemflags = EEikDIgltemNonFocusing; id = EFindControl;
type = EAknCtSelectionListFixedFind; }
Further details of list types, item formats, and their appearance are provided in Chapter 7.
Constructing a Selection List Dialog
Construction of a selection list dialog is performed using its NewL() method. This function has three mandatory parameters. The first, a Tlnt&, is used to return the selected item in the list. The second parameter is the list item array. This is a standard list item array, containing descriptors representing the list items. In ListDIg, the list items are defined statically in the resource, so this parameter is set to NULL. However, if a dynamic array of items is required, an array of descriptors can be created and passed through instead. The list does not take ownership of the array, so its subsequent deletion must be performed externally. The third parameter should be the value of the resource for any menu bar required. In the ListDIg example, the dialog is defined in the resource file with Ok and Cancel soft keys, so there is no need for a menu bar, and so zero is passed in. If an Options menu is needed, an appropriate MENU_BAR resource should be passed in here.
In ListDIg, the dialog is constructed in CListDlgContainer::ConstructL(): Tint openedltem(O);
// Construct and prepare the dialog
CAknSelectionListDialog* dialog = CAknSelectionListDialog::NewL(openedltem, NULL, 0);
Adding Icons to a Selection List Dialog
For a selection list to contain graphics items, they must be added to the dialog's icon array. [View full widthl dialog->PrepareLC(R_LISTDLG_DIALOG);
HBufC* iconFileName = StringLoader::LoadLC(R_ICON_FILE_NAME); CArrayPtr<CGullcon>* icons = new (ELeave) CAknlconArray(KNumberOflcons);
CleanupStack::PushL(icons);
¡cons->AppendL(iEikonEnv->Createlconl_(*iconFileName, EMbmDialoglistexl 1 player,
* EMbmDialoglistexl 1 player_mask));
¡cons->AppendL(iEikonEnv->CreatelconL(*iconFileName, EMbmDialoglistexl2player,
* EMbmDialoglistexl2player_mask));
dialog->SetlconArrayL(icons); // transferring ownership of icons CleanupStack::Pop(icons);
CleanupStack::PopAndDestroy(iconFileName);
The list's item drawer owns the icons. Icons cannot be added to the list before it exists, so the dialog must be prepared first. This is performed using the standard dialog PrepareLC() method, passing in the dialog resource. A standard array of list icons could then be created and set into the dialog using its SetlconArrayL() method. See Chapter 8 for further details on lists and icon arrays.
Executing a Selection List Dialog
After the dialog has been prepared, it is executed using the standard RunLD() method. If dialog preparation is not required, then the standard ExecuteLD() method can be used instead.
if (dialog->RunLD ()) PlaySelectedGame(openedltem);
As usual, this returns a TBool Indicating whether the dialog closed with a positive or negative action. Once closed, the Tint, supplied on construction, in this case openedltem, will contain the index value of the selected item.
Markable List Dialogs
To create a markable list dialog that allows the user to select more than one item, a few alterations are necessary to the ListDIg application.
The DIALOG resource should be defined as for the selection list, but the flags should be set to EAknDialogMarkableList and the LISTBOX flags should be EAknListBoxMarkableList. A markable list dialog is defined by the CAknMarkableListDialog class. It is instantiated by passing in an array (CArrayFix<Tlnt>) by reference, which contains the selected indices. A reference to a context-sensitive menu can also be passed in.
For a markable list without graphics, default marking icons will be supplied automatically. For a markable list with graphics, they are supplied as in the selection list example ListDIg. The marking graphics are added as the first element of the array. (The IDs for the standard marking graphic can be accessed from avkon.mbg.)
The array is executed using the usual ExecuteLD(), or PrepareLC() and RunLD().

Summary
This chapter has described the different types of dialogs available in Series 60. Using example applications, it has demonstrated how to create the most commonly used types. Dialog types range from providing simple notifications to the user through to sophisticated data display and data entry capabilities.
Some guidance has been given about when each type of dialog should be used. It is recommended that you also consult the Series 60 Ul Style Guide in the SDK documentation for further detailed information.
Dialogs are commonly used Ul component that can be employed to convey information to the user or to query information from them. In the following chapters, you will learn about other controls that can be used to communicate with the user, such as lists and editor controls.

Chapter 7. Lists
Lists are user interface controls for presenting a collection of items, in a one- or two-dimensional display
A list is a user interface control containing a number of items, each of which can be individually selected and activated. Series 60 provides a range of list types that are in common use throughout the platform. This chapter describes the various list types available, and discusses example applications to demonstrate how each type is used.
Series 60 lists are divided into three broad categories: vertical lists, grids and settings lists. Vertical lists are used for laying out a one-dimensional set of items—each occupying the full width of the screen, as shown in Figure 7-1.
- Figure 7-1. Vertical list.
Grids are used for two-dimensional arrangements of items, as shown in Figure 7-2.
Figure 7-2. Grid.
Rcse Hearts itummu
Post a comment