ListBox: Part VIII
8. MultiSelection and Markable ListBoxes

Keywords:

Multiselection and markable listboxes provide essentially the same kind of support for selecting multiple items. The differences between them are more visible at the usage level.

Markable listbox should be used to allow an operation to be applied to multiple items at once. In that usage scenario individual items are marked and the operation is executed from a menu, effectivelly being applied to all marked items. Typical example are the lists managed by the user.

Multiselection list box should be used only as a way to collect items, without performing an action on them directly from the menu. Typically, there is already an operation in progress which needs an item list as its input, and multiselection listbox is there only to carry out the task of getting that list.

Corresponding menus also reflect this difference: markable listbox has as a left softkey 'Options', offering actions to be performed on the list. Multiselection listbox has as a left softkey 'Done' or 'OK'.

The way items are selected also differs slightly. In a markable listbox, item is selected using Selection key while holding Edit key (Edit key maps to Shift key in the emulator). In a multiselection listbox, item is selected simply by pressing Selection key.

For both marked and multiselection listbox, performing selection on an already selected item deselects it.

While differences do exist on the usage level, there are no differences on the programming level: both types of listboxes expose the same methods for manipulation of selected items.

First of all, appropriate listbox flags should be used to create a markable listbox (EAknListBoxMarkableList or EAknListBoxMarkableListWithShortcuts) or a multiselection listbox (EAknListBoxMultiselectionList or EAknListBoxMultiselectionListWithShortcuts). These flags are passed in a call to ConstructL() method.

ListBox Container code:

listBox = new (ELeave) ...;
listBox->ConstructL(this,AknListBoxMultiselectionList);
or
listBox->ConstructL(this, EAknListBoxMarkableList);

Markable listbox manipulation is implemented by CAknMarkableListDialog, class that does the whole work of constructing a markable listbox from a resource, creating icons and handling commands Mark/Unmark/Mark All/Unmark All from Options menu (both execution and visibility).

Multiselection list doesn't have a direct counterpart to this dialog.

However, there is no reason why multiselection list shouldn't use Mark/Unmark/Mark All/Unmark All options in a menu. Fortunately, it's easy to implement: menu resource used by CAknMarkableListDialog is a menu pane R_AVKON_MENUPANE_MARKABLE_LIST, available to any application.

To have it as a part of an application menu, it is enough to add it in a menu pane resource:

RESOURCE MENU_PANE r_main_menu
{
 items=
 {
   MENU_ITEM { command=EListBoxCmdAddItem; txt="Add"; },
   MENU_ITEM { command=EListBoxCmdRemoveItem; txt="Remove";
               flags = EEikMenuItemSeparatorAfter; },
   MENU_ITEM { command = EMenuDummyCmdId; txt = "Select";
                  cascade = R_AVKON_MENUPANE_MARKABLE_LIST; }
 };
}

R_AVKON_MENUPANE_MARKABLE_LIST menu pane contains four items: Mark, Unmark, Mark All and Unmark All, with the corresponding predefined IDs EAknCmdMark, EAknCmdUnmark, EAknMarkAll, EAknUnmarkAll (see avkon.hrh).

Wiring these four commands to method(s) that select and deselect items is what CAknMarkableListDialog does. (It also implements actual selection methods.)

However, handling these four commands yourself isn't a big problem either. First, they have to be intercepted in a central place where all commands arrive -- in the application UI's HandleCommandL() method. (In the example below, list box is a component of a container; container implements a single selection method internally calling listbox methods.)

void CMyListBoxUi::HandleCommandL(TInt cmd)
{
 switch (cmd)
 {
   ...
   case EAknCmdMark:
     {
       TInt currentItem = _container->getCurrentListBoxItem();
       if (currentItem != -1)
         _container->cmdMark(currentItem, true);
     }
     break;
   case EAknMarkAll:
     _container->cmdMark(-1, true);
     break;
   case EAknCmdUnmark:
     {
       TInt currentItem = _container->getCurrentListBoxItem();
       if (currentItem != -1)
         _container->cmdMark(currentItem, false);
     }
     break;
   case EAknUnmarkAll:
     _container->cmdMark(-1, false);
     break;
     ...

Here is one possible way to implement item selection code in the container (a single method for selecting/deselecting):

void CMyListBoxContainer::cmdMark(TInt item, TBool mark)
{
 CTextListBoxModel* model = _listBox->Model();
 TInt itemCount = model->NumberOfItems();
 CListBoxView* listBoxView = _listBox->View();
 if (mark)
 {
   for (TUint i = 0; i < itemCount; i++)
     if (item == -1 || item == i)
       listBoxView->SelectItemL(i);
 }
 else
 {
   for (TUint i = 0; i < itemCount; i++)
     if (item == -1 || item == i)
       listBoxView->DeselectItem(i);
 }
}

Listbox selection is implemented by CListBoxView-derived view class, accessible through View() method on a listbox. Apart from item-based selection methods like SelectItemL, DeselectItem and ToggleItemL, this class also offers a method for multiple item selection (SetSelectionIndexesL) and a method for retrieving the list of currently selected items (GetSelectionIndexesL). Both methods operate on CSelectionIndexArray, which is just a typedef to CArrayFix.

This pretty much rounds up basic listbox concepts and manipulation. Don't give up, the real-life sample is just a few pages away.


:<: Part VII
Part IX :>:

Tutorial posted November 16th, 2003 by klisa1 categories [ ]

Re: ListBox: Part VIII

Hi Eric can you put some light as in if there is a find box how to select the item ?

thanks