javauis/lcdui_akn/lcdui/src/CMIDChoiceGroupModel.cpp
branchRCL_3
changeset 19 04becd199f91
child 77 7cee158cb8cd
equal deleted inserted replaced
16:f5050f1da672 19:04becd199f91
       
     1 /*
       
     2 * Copyright (c) 2003-2006 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  The CMIDChoiceGroup listbox model
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 #include "CMIDChoiceGroupModel.h"
       
    20 #include "CMIDDisplayable.h"
       
    21 
       
    22 #include <e32def.h>
       
    23 
       
    24 #include <aknconsts.h>
       
    25 // using TMifAvkon enumeration
       
    26 #include <avkon.mbg>
       
    27 // LAF
       
    28 // AknLayoutScalable_Avkon::list_single_2graphic_pane_g2_cp4()
       
    29 #include <aknlayoutscalable_avkon.cdl.h>
       
    30 
       
    31 #include <j2me/jdebug.h>
       
    32 
       
    33 // Index where element icons start in the icon array. They're
       
    34 // preceded by selection state icons (currently 2, selected and nonselected)
       
    35 const TInt KElementIconStartIndex = 2;
       
    36 
       
    37 /** This macro is executed each time a trapped call returns an error code different than KErrNone */
       
    38 #undef  TRAP_INSTRUMENTATION_LEAVE
       
    39 #define TRAP_INSTRUMENTATION_LEAVE(aResult) DEBUG_INT2("In CMIDChoiceGroupModel.cpp, trapped method was called at line %D and got exception %D", __LINE__, aResult);
       
    40 
       
    41 
       
    42 // C'tor
       
    43 CMIDChoiceGroupModel::CMIDChoiceGroupModel(
       
    44     MMIDChoiceGroup::TChoiceType aType)
       
    45         : CAknFilteredTextListBoxModel(),
       
    46         iType(aType),
       
    47         iUpdating(EFalse)
       
    48 {
       
    49 }
       
    50 
       
    51 
       
    52 // D'tor
       
    53 CMIDChoiceGroupModel::~CMIDChoiceGroupModel()
       
    54 {
       
    55     // Delete element array
       
    56     if (iElements)
       
    57     {
       
    58         //all elemnts in iElements array should be destroyed
       
    59         //to prevent memory leak
       
    60         iElements->ResetAndDestroy();
       
    61         delete iElements;
       
    62     }
       
    63 
       
    64     // Delete icon array, do not delete icons
       
    65     if (iIconArray)
       
    66     {
       
    67         iIconArray->Reset();
       
    68         delete iIconArray;
       
    69     }
       
    70 
       
    71     // Delete icons
       
    72     delete iIconSelected;
       
    73     delete iIconNotSelected;
       
    74     delete iIconDummy;
       
    75 }
       
    76 
       
    77 
       
    78 // Two-phase constructor, initialises member arrays and stuff
       
    79 void CMIDChoiceGroupModel::ConstructL(CEikonEnv* aEikonEnv)
       
    80 {
       
    81     ASSERT(aEikonEnv);
       
    82 
       
    83     // Create element array
       
    84     iElements = new(ELeave) CArrayPtrFlat<CMIDChoiceGroupElement>(
       
    85         KCGElementArrayGranularity);
       
    86 
       
    87     // Create icon array
       
    88     iIconArray = new(ELeave) CArrayPtrFlat<CGulIcon>(
       
    89         KCGElementArrayGranularity);
       
    90 
       
    91     ReConstructSelectionIconsL();
       
    92 
       
    93     // Create the dummy icon (zero-sized bitmap)
       
    94     CFbsBitmap* bitmap = new(ELeave) CFbsBitmap();
       
    95     bitmap->Create(TSize(0,0), aEikonEnv->DefaultDisplayMode());
       
    96 
       
    97     CleanupStack::PushL(bitmap);
       
    98     iIconDummy = CGulIcon::NewL(bitmap);
       
    99     CleanupStack::Pop(); // bitmap
       
   100 }
       
   101 
       
   102 /** Create selection icons according to type */
       
   103 void CMIDChoiceGroupModel::ReConstructSelectionIconsL()
       
   104 {
       
   105     TFileName avkonbmpFilename = AknIconUtils::AvkonIconFileName();
       
   106     MAknsSkinInstance* skin = AknsUtils::SkinInstance();
       
   107 
       
   108     const TAknsItemID& selectedSkinId = (iType == MMIDChoiceGroup::EMultiple) ? KAknsIIDQgnIndiCheckboxOn :
       
   109                                         KAknsIIDQgnIndiRadiobuttOn;
       
   110 
       
   111     const TAknsItemID& notSelectedSkinId = (iType == MMIDChoiceGroup::EMultiple) ? KAknsIIDQgnIndiCheckboxOff :
       
   112                                            KAknsIIDQgnIndiRadiobuttOff;
       
   113 
       
   114     TInt selectedIconId = (iType == MMIDChoiceGroup::EMultiple) ? EMbmAvkonQgn_indi_checkbox_on : EMbmAvkonQgn_indi_radiobutt_on;
       
   115     TInt selectedMaskId = (iType == MMIDChoiceGroup::EMultiple) ? EMbmAvkonQgn_indi_checkbox_on_mask : EMbmAvkonQgn_indi_radiobutt_on_mask;
       
   116     TInt notSelectedIconId = (iType == MMIDChoiceGroup::EMultiple) ? EMbmAvkonQgn_indi_checkbox_off : EMbmAvkonQgn_indi_radiobutt_off;
       
   117     TInt notSelectedMaskId = (iType == MMIDChoiceGroup::EMultiple) ? EMbmAvkonQgn_indi_checkbox_off_mask : EMbmAvkonQgn_indi_radiobutt_off_mask;
       
   118 
       
   119     CFbsBitmap* bitmap = NULL;
       
   120     CFbsBitmap* mask = NULL;
       
   121 
       
   122     TRect screenRect;
       
   123     AknLayoutUtils::LayoutMetricsRect(AknLayoutUtils::EScreen, screenRect);
       
   124 
       
   125     TAknLayoutRect layoutRect;
       
   126     // layout in respect of the whole screen as only the icon size is needed
       
   127     layoutRect.LayoutRect(screenRect, AknLayoutScalable_Avkon::list_single_2graphic_pane_g2_cp4().LayoutLine());
       
   128 
       
   129     TSize iconSize(layoutRect.Rect().Width(), layoutRect.Rect().Height());
       
   130 
       
   131     AknsUtils::CreateColorIconLC(skin, notSelectedSkinId, KAknsIIDQsnIconColors,
       
   132                                  EAknsCIQsnIconColorsCG14, bitmap, mask, avkonbmpFilename, notSelectedIconId,
       
   133                                  notSelectedMaskId, KRgbBlue, iconSize, EAspectRatioPreservedAndUnusedSpaceRemoved);
       
   134 
       
   135     CGulIcon* iconNotSelected = CGulIcon::NewL(bitmap, mask);
       
   136     CleanupStack::Pop(2); //bitmap, mask
       
   137 
       
   138     delete iIconNotSelected;
       
   139     iIconNotSelected = iconNotSelected;
       
   140 
       
   141     AknsUtils::CreateColorIconLC(skin, selectedSkinId, KAknsIIDQsnIconColors,
       
   142                                  EAknsCIQsnIconColorsCG14, bitmap, mask, avkonbmpFilename, selectedIconId,
       
   143                                  selectedMaskId, KRgbBlue, iconSize, EAspectRatioPreservedAndUnusedSpaceRemoved);
       
   144 
       
   145     CGulIcon* iconSelected = CGulIcon::NewL(bitmap, mask);
       
   146     CleanupStack::Pop(2); //bitmap, mask
       
   147 
       
   148     delete iIconSelected;
       
   149     iIconSelected = iconSelected;
       
   150 }
       
   151 
       
   152 // Base class overrides
       
   153 
       
   154 // The model contains more than just the strings - need to override
       
   155 // number of items query
       
   156 TInt CMIDChoiceGroupModel::NumberOfItems() const
       
   157 {
       
   158     return iElements ? iElements->Count() : 0;
       
   159 }
       
   160 
       
   161 
       
   162 // Provides a string with correct indices to images
       
   163 TPtrC CMIDChoiceGroupModel::ItemText(TInt aItemIndex) const
       
   164 {
       
   165     CMIDChoiceGroupElement* pElement = ElementAt(aItemIndex);
       
   166 
       
   167     if (pElement)
       
   168     {
       
   169         return (pElement->LboxText(aItemIndex + KElementIconStartIndex));
       
   170     }
       
   171 
       
   172     return TPtrC(KNullDesC);
       
   173 }
       
   174 
       
   175 
       
   176 // Base class override
       
   177 void CMIDChoiceGroupModel::SetItemTextArray(MDesCArray* /*aItemTextArray*/)
       
   178 {
       
   179     // Strings are stored in elements, so this is just to make sure
       
   180     // the base class does nothing.
       
   181 }
       
   182 
       
   183 
       
   184 // Returns a pointer to the item text array, which is not used,
       
   185 // because strings are stored inside elements.
       
   186 MDesCArray* CMIDChoiceGroupModel::ItemTextArray() const
       
   187 {
       
   188     return NULL;
       
   189 }
       
   190 
       
   191 
       
   192 // Add an element to the end of the array
       
   193 void CMIDChoiceGroupModel::AppendElementL(CMIDChoiceGroupElement* aElement)
       
   194 {
       
   195     // Sanity check
       
   196     if (!iElements)
       
   197     {
       
   198         ASSERT(EFalse);
       
   199         return;
       
   200     }
       
   201 
       
   202     // If this is the first added element and choice is single selection
       
   203     // type, initially make the first item selected
       
   204     if ((iType != MMIDChoiceGroup::EMultiple) && (NumberOfItems() == 0))
       
   205     {
       
   206         aElement->SetSelected(ETrue);
       
   207     }
       
   208 
       
   209     iElements->AppendL(aElement);
       
   210 
       
   211     // If not in the middle of an update, refresh a bit
       
   212     if (!iUpdating)
       
   213     {
       
   214         // Refresh icon array
       
   215         UpdateIconArrayL();
       
   216 
       
   217         // Report event
       
   218         ReportEventL(MMIDChoiceGroupModelObserver::EElementAdded);
       
   219     }
       
   220 }
       
   221 
       
   222 
       
   223 // Insert an element at <aIndex>. Space must be reserved.
       
   224 void CMIDChoiceGroupModel::InsertElementL(
       
   225     TInt aIndex,
       
   226     CMIDChoiceGroupElement* aElement)
       
   227 {
       
   228     if ((iElements) && (aIndex >= 0) && (aIndex <= NumberOfItems()))
       
   229     {
       
   230         // If this is the first added element and choice is single selection
       
   231         // type, initially make the first inserted item selected
       
   232         if ((iType != MMIDChoiceGroup::EMultiple) && (NumberOfItems() == 0))
       
   233         {
       
   234             aElement->SetSelected(ETrue);
       
   235         }
       
   236 
       
   237         iElements->InsertL(aIndex, aElement);
       
   238 
       
   239         // If not in the middle of an update, refresh a bit
       
   240         if (!iUpdating)
       
   241         {
       
   242             // Refresh icon array
       
   243             UpdateIconArrayL();
       
   244 
       
   245             // Report element addition
       
   246             ReportEventL(MMIDChoiceGroupModelObserver::EElementAdded);
       
   247         }
       
   248     }
       
   249     else
       
   250     {
       
   251         ASSERT(EFalse);
       
   252     }
       
   253 }
       
   254 
       
   255 
       
   256 // Delete element at <aIndex>
       
   257 void CMIDChoiceGroupModel::DeleteElementL(TInt aIndex)
       
   258 {
       
   259     if ((iElements) && (aIndex >= 0) && (aIndex <= NumberOfItems()))
       
   260     {
       
   261 
       
   262         if (iType != MMIDChoiceGroup::EMultiple && NumberOfItems() > 1)
       
   263         {
       
   264             CMIDChoiceGroupElement* pElement = ElementAt(aIndex);
       
   265 
       
   266             if (pElement)
       
   267             {
       
   268                 if (pElement->IsSelected())
       
   269                 {
       
   270                     if ((aIndex + 1) < NumberOfItems())
       
   271                     {
       
   272                         CMIDChoiceGroupElement* pNextElement = ElementAt(aIndex+1);
       
   273                         pNextElement->SetSelected(ETrue);
       
   274                     }
       
   275                     else
       
   276                     {
       
   277                         CMIDChoiceGroupElement* pPrevElement = ElementAt(aIndex-1);
       
   278                         pPrevElement->SetSelected(ETrue);
       
   279                     }
       
   280                 }
       
   281             }
       
   282         }
       
   283 
       
   284         // Grab hold of the element for deletion, remove from array
       
   285         // and compress the array
       
   286         CMIDChoiceGroupElement* ptr = iElements->At(aIndex);
       
   287         iElements->Delete(aIndex);
       
   288         delete ptr;
       
   289         iElements->Compress();
       
   290 
       
   291         // If not in the middle of an update, refresh a bit
       
   292         if (!iUpdating)
       
   293         {
       
   294             // Refresh icon array.
       
   295             UpdateIconArrayL();
       
   296 
       
   297             // Update the looks of the control
       
   298             ReportEventL(MMIDChoiceGroupModelObserver::EElementDeleted);
       
   299         }
       
   300     }
       
   301     else
       
   302     {
       
   303         ASSERT(EFalse);
       
   304     }
       
   305 }
       
   306 
       
   307 
       
   308 // Delete all elements
       
   309 void CMIDChoiceGroupModel::DeleteAllL()
       
   310 {
       
   311     if (iElements)
       
   312     {
       
   313         iElements->ResetAndDestroy();
       
   314 
       
   315         // If not updating, refresh now
       
   316         if (!iUpdating)
       
   317         {
       
   318             // Recreate icon array
       
   319             UpdateIconArrayL();
       
   320 
       
   321             // Report event
       
   322             ReportEventL(MMIDChoiceGroupModelObserver::EElementDeleted);
       
   323         }
       
   324     }
       
   325 }
       
   326 
       
   327 
       
   328 // Set properties of element at <aIndex>
       
   329 void CMIDChoiceGroupModel::SetElementL(
       
   330     TInt aIndex,
       
   331     const TDesC& aText,
       
   332     CFbsBitmap* aBitmap,
       
   333     CFbsBitmap* aMask)
       
   334 {
       
   335     CMIDChoiceGroupElement* pElement = ElementAt(aIndex);
       
   336 
       
   337     if (pElement)
       
   338     {
       
   339         // Set new properties
       
   340         pElement->SetTextL(aText);
       
   341         if (aBitmap)
       
   342         {
       
   343             pElement->SetIconL(*aBitmap, aMask);
       
   344         }
       
   345         else
       
   346         {
       
   347             pElement->SetIcon(NULL, EFalse);
       
   348         }
       
   349 
       
   350         // Refresh stuff, if not in the middle of an update
       
   351         if (!iUpdating)
       
   352         {
       
   353             // Icon may have changed, recreate array.
       
   354             UpdateIconArrayL();
       
   355 
       
   356             // Report event
       
   357             ReportEventL(MMIDChoiceGroupModelObserver::EElementModified);
       
   358         }
       
   359     }
       
   360 }
       
   361 
       
   362 
       
   363 // Get element at position <aIndex>
       
   364 CMIDChoiceGroupElement* CMIDChoiceGroupModel::ElementAt(TInt aIndex) const
       
   365 {
       
   366     if ((iElements) && (aIndex >= 0) && (aIndex < NumberOfItems()))
       
   367     {
       
   368         return iElements->At(aIndex);
       
   369     }
       
   370     else
       
   371     {
       
   372         return NULL;
       
   373     }
       
   374 }
       
   375 
       
   376 
       
   377 // Reserve space for <aCount> elements
       
   378 void CMIDChoiceGroupModel::SetReserveL(TInt aCount)
       
   379 {
       
   380     if ((iElements) && (aCount >= NumberOfItems()))
       
   381     {
       
   382         iElements->SetReserveL(aCount);
       
   383     }
       
   384 }
       
   385 
       
   386 
       
   387 // Retrieves the icon array, recreates if flag is set
       
   388 CArrayPtr<CGulIcon>* CMIDChoiceGroupModel::IconArray(TBool aReCreate)
       
   389 {
       
   390     if (aReCreate)
       
   391     {
       
   392         // Recreate, trap & ignore leaves
       
   393         TRAP_IGNORE(UpdateIconArrayL());
       
   394     }
       
   395 
       
   396     return iIconArray;
       
   397 }
       
   398 
       
   399 
       
   400 // Set selection state of item at <index>.
       
   401 // If an item is set selected in an exclusive type choice, also
       
   402 // deselects other items.
       
   403 // Deselection of an item in an exlusive choice has no effect.
       
   404 void CMIDChoiceGroupModel::SelectElementL(TInt aIndex, TBool aSelected)
       
   405 {
       
   406     ASSERT(iElements);
       
   407 
       
   408     // Quick sanity check
       
   409     if ((aIndex < 0) || (aIndex >= NumberOfItems()))
       
   410     {
       
   411         return;
       
   412     }
       
   413 
       
   414     // Exclusive and popup are both single-selection types
       
   415     if (iType != MMIDChoiceGroup::EMultiple)
       
   416     {
       
   417         if (!aSelected)
       
   418         {
       
   419             // Deselecting in an exclusive - void op
       
   420             return;
       
   421         }
       
   422 
       
   423         // Remove any previous selection
       
   424         ClearSelection();
       
   425     }
       
   426 
       
   427     // Set the selection state of the element
       
   428     CMIDChoiceGroupElement* pElement = ElementAt(aIndex);
       
   429 
       
   430     if (pElement)
       
   431     {
       
   432         pElement->SetSelected(aSelected);
       
   433     }
       
   434 
       
   435     // Report selection
       
   436     ReportEventL(MMIDChoiceGroupModelObserver::EElementSelected);
       
   437 }
       
   438 
       
   439 
       
   440 // Begin a model update. During an update, the observer will not
       
   441 // reveive notifications about element actions.
       
   442 void CMIDChoiceGroupModel::BeginUpdate()
       
   443 {
       
   444     iUpdating = ETrue;
       
   445 
       
   446     // Report update start
       
   447     TRAP_IGNORE(ReportEventL(MMIDChoiceGroupModelObserver::EUpdateStarted));
       
   448 }
       
   449 
       
   450 
       
   451 // End a model update. At the end the icon array will be
       
   452 // recreated, and the associated control refreshed.
       
   453 void CMIDChoiceGroupModel::EndUpdate()
       
   454 {
       
   455     iUpdating = EFalse;
       
   456 
       
   457     // Create array, refresh control
       
   458     TRAPD(ignore, UpdateIconArrayL());
       
   459 
       
   460     // Report update end (observer should redraw)
       
   461     TRAP(ignore, ReportEventL(MMIDChoiceGroupModelObserver::EUpdateEnded));
       
   462 }
       
   463 
       
   464 
       
   465 // Returns the index of the selected element in an exclusive
       
   466 // choice, or -1
       
   467 TInt CMIDChoiceGroupModel::SelectedElement()
       
   468 {
       
   469     TInt nSelected = -1;
       
   470 
       
   471     // Exclusive & Popup are both single-selection
       
   472     if (iType != MMIDChoiceGroup::EMultiple)
       
   473     {
       
   474         // Loop through the elements, look for a selected one
       
   475         TInt nCount = NumberOfItems();
       
   476 
       
   477         for (TInt i = 0; i < nCount; i++)
       
   478         {
       
   479             CMIDChoiceGroupElement* pElement = ElementAt(i);
       
   480 
       
   481             if (pElement)
       
   482             {
       
   483                 if (pElement->IsSelected())
       
   484                 {
       
   485                     // Found, break out
       
   486                     nSelected = i;
       
   487                     break;
       
   488                 }
       
   489             }
       
   490         }
       
   491     }
       
   492 
       
   493     return nSelected;
       
   494 }
       
   495 
       
   496 
       
   497 // --- private functions ---
       
   498 
       
   499 // Clears all selections, does not report, as is used when
       
   500 // subsequently a selection is set (in an exclusive choice)
       
   501 void CMIDChoiceGroupModel::ClearSelection()
       
   502 {
       
   503     // Loop through the elements and clear element selections
       
   504     TInt nCount = NumberOfItems();
       
   505     for (TInt i = 0; i < nCount; i++)
       
   506     {
       
   507         CMIDChoiceGroupElement* pElement = ElementAt(i);
       
   508 
       
   509         if (pElement)
       
   510         {
       
   511             pElement->SetSelected(EFalse);
       
   512         }
       
   513     }
       
   514 }
       
   515 
       
   516 
       
   517 // Reports element actions to observer
       
   518 void CMIDChoiceGroupModel::ReportEventL(
       
   519     MMIDChoiceGroupModelObserver::TChoiceGroupModelEvent aEvent)
       
   520 {
       
   521     if (iObserver)
       
   522     {
       
   523         iObserver->HandleChoiceGroupModelEventL(this, aEvent);
       
   524     }
       
   525 }
       
   526 
       
   527 
       
   528 // Create an icon array to be given to the lbox column data.
       
   529 // This should be done every time the contents of the model are changed,
       
   530 // or icon array is retrieved with the create flag set.
       
   531 // NOTE that the indices in the array and the item strings should
       
   532 // be synchronised. The selection icon is always at index
       
   533 // 0 (selected) and 1 (not selected)
       
   534 void CMIDChoiceGroupModel::UpdateIconArrayL()
       
   535 {
       
   536     ASSERT(iElements);
       
   537     ASSERT(iIconArray);
       
   538 
       
   539     // Clear array, DO NOT DELETE icons
       
   540     iIconArray->Reset();
       
   541 
       
   542     TInt nCount = NumberOfItems();
       
   543 
       
   544     if (nCount <= 0)
       
   545     {
       
   546         return;
       
   547     }
       
   548 
       
   549     // First add the selection icons
       
   550     iIconArray->AppendL(iIconSelected);
       
   551     iIconArray->AppendL(iIconNotSelected);
       
   552 
       
   553     // Then loop through the elements and add their icons
       
   554     for (TInt i = 0; i < nCount; i++)
       
   555     {
       
   556         CMIDChoiceGroupElement *pElement = ElementAt(i);
       
   557 
       
   558         if (pElement)
       
   559         {
       
   560             CGulIcon* icon = pElement->Icon();
       
   561 
       
   562             if (icon)
       
   563             {
       
   564                 // Add the elements icon
       
   565                 iIconArray->AppendL(icon);
       
   566             }
       
   567             else
       
   568             {
       
   569                 // Add a zero-sized dummy icon
       
   570                 iIconArray->AppendL(iIconDummy);
       
   571             }
       
   572         }
       
   573     }
       
   574 }
       
   575 
       
   576 TBool CMIDChoiceGroupModel::HasIcons() const
       
   577 {
       
   578     TInt itemCount = NumberOfItems();
       
   579     for (TInt i = 0; i < itemCount; ++i)
       
   580     {
       
   581         CMIDChoiceGroupElement *element = ElementAt(i);
       
   582 
       
   583         if (element && element->Icon())
       
   584         {
       
   585             return ETrue;
       
   586         }
       
   587     }
       
   588 
       
   589     return EFalse;
       
   590 }
       
   591