uifw/EikStd/coctlsrc/EIKBTGPC.CPP
changeset 0 2f259fa3e83a
child 4 8ca85d2f0db7
equal deleted inserted replaced
-1:000000000000 0:2f259fa3e83a
       
     1 /*
       
     2 * Copyright (c) 2002-2007 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:  
       
    15 *
       
    16 */
       
    17 
       
    18 #include <barsread.h>
       
    19 #include <coemain.h>
       
    20 #include <eikbtgpc.h>
       
    21 #include <eikbtgrp.h>
       
    22 #include <eikbtgps.h>
       
    23 #include <eikenv.h>
       
    24 #include <eikcmobs.h>
       
    25 #include <eiktbar.h>
       
    26 #include <eikbtpan.h>
       
    27 #include <eikpanic.h>
       
    28 #include "LAFBTGPC.H"
       
    29 #include <eikbgfty.h>
       
    30 #include <uikon.hrh>
       
    31 #include <eikcmbut.h>
       
    32 #include <aknenv.h>
       
    33 #include <AknLayout.lag>
       
    34 #include <AknIconUtils.h>
       
    35 #include <aknappui.h>
       
    36 #include <AknUtils.h>
       
    37 #include <eiklbx.h>
       
    38 
       
    39 #ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
       
    40 #include <uikon/eikenvinterface.h> 
       
    41 #endif
       
    42 
       
    43 #include <AknTasHook.h>
       
    44 const TInt KCleanupNoCommand = -1;
       
    45 const TInt KNoCommand = 0;
       
    46 const TInt KIsValid = 1;
       
    47 
       
    48 inline CEikButtonGroupContainer::TCmdPos::TCmdPos()
       
    49     : iPos(KCleanupNoCommand), iCmd(KNoCommand)
       
    50     {
       
    51     }
       
    52     
       
    53 inline CEikButtonGroupContainer::TCmdPos::TCmdPos(TInt aPos, TInt aCmd)
       
    54     : iPos(aPos), iCmd(aCmd)
       
    55     {
       
    56     }
       
    57 
       
    58 inline CEikButtonGroupContainer::TCmdObserver::TCmdObserver(TInt aPos, 
       
    59     MEikCommandObserver& aObserver)
       
    60     : iPos(aPos), iObserver(aObserver)
       
    61     {
       
    62     }
       
    63 
       
    64 inline CEikButtonGroupContainer::CCmdObserverArray::CCmdObserverArray()
       
    65     : CArrayFixFlat<CEikButtonGroupContainer::TCmdObserver>(1)
       
    66     {
       
    67     }
       
    68 
       
    69 TInt CEikButtonGroupContainer::CCmdObserverArray::FindIndex(TInt aPos)
       
    70     {
       
    71     const TInt count = Count();
       
    72     TInt index = KErrNotFound;
       
    73     for (TInt ii = 0; ii < count; ii++)
       
    74         {
       
    75         if (At(ii).iPos == aPos)
       
    76             {
       
    77             index = ii;
       
    78             break;
       
    79             }
       
    80         }
       
    81     return index;
       
    82     }
       
    83 
       
    84 inline CCoeControl* CEikButtonGroupContainer::ButtonGroupAsControl() const
       
    85     {
       
    86     CCoeControl* ctrl = iButtonGroup->AsControl();
       
    87     // __ASSERT_DEBUG(ctrl...
       
    88     return ctrl;
       
    89     }
       
    90 
       
    91 /**
       
    92  * Creates a button group container in its own window. Requesting aUse as either EView or 
       
    93  * EDialog will create the default button set for the host device; the other options are 
       
    94  * included primarily for testing. aOrientation is required only for dialogs on pen based 
       
    95  * machines that may layout their buttons either horizontally or vertically. aResourceId 
       
    96  * may be NULL if buttons are to be added dynamically.
       
    97  */
       
    98 EXPORT_C CEikButtonGroupContainer* CEikButtonGroupContainer::NewL(
       
    99     TUse aUse,
       
   100     TOrientation aOrientation,
       
   101     MEikCommandObserver* aCommandObserver,
       
   102     TInt aResourceId,
       
   103     TUint aFlags)
       
   104     { // static
       
   105     CEikButtonGroupContainer* self = new(ELeave) CEikButtonGroupContainer(aUse);
       
   106     CleanupStack::PushL(self);
       
   107     self->ConstructL(aOrientation, aCommandObserver, aResourceId, NULL, aFlags);
       
   108     CleanupStack::Pop(); // self
       
   109     AKNTASHOOK_ADDL( self, "CEikButtonGroupContainer" );
       
   110     return self;
       
   111     }
       
   112 
       
   113 /**
       
   114  * Creates a button group container in aParent's window. Requesting aUse as either EView or 
       
   115  * EDialog will create the default button set for the host device; the other options are 
       
   116  * included primarily  for testing. aOrientation is required only for dialogs on pen based 
       
   117  * machines that may layout their buttons either horizontally or vertically. aResourceId 
       
   118  * may be NULL if buttons are to be added dynamically.
       
   119  */
       
   120 EXPORT_C CEikButtonGroupContainer* CEikButtonGroupContainer::NewL(
       
   121     TUse aUse,
       
   122     TOrientation aOrientation,
       
   123     MEikCommandObserver* aCommandObserver,
       
   124     TInt aResourceId,
       
   125     const CCoeControl& aParent,
       
   126     TUint aFlags)
       
   127     { // static
       
   128     CEikButtonGroupContainer* self = new(ELeave) CEikButtonGroupContainer(aUse);
       
   129     CleanupStack::PushL(self);
       
   130     self->SetContainerWindowL(aParent);
       
   131 
       
   132     RWindowGroup* targetGroup = NULL;
       
   133     
       
   134     if ( aFlags & EIsEmbedded )
       
   135         {
       
   136         aFlags |= EParentIsControl;
       
   137         targetGroup = (RWindowGroup*)&aParent;
       
   138         }
       
   139     
       
   140     self->ConstructL(aOrientation, aCommandObserver, aResourceId, targetGroup,
       
   141             aFlags);
       
   142     CleanupStack::Pop(); // self
       
   143     AKNTASHOOK_ADDL( self, "CEikButtonGroupContainer" );
       
   144     return self;
       
   145     }
       
   146 
       
   147 /**
       
   148  * Creates a button group container in aParentWg window group. Requesting aUse as either EView or 
       
   149  * EDialog will create the default button set for the host device; the other options are 
       
   150  * included primarily  for testing. aOrientation is required only for dialogs on pen based 
       
   151  * machines that may layout their buttons either horizontally or vertically. aResourceId 
       
   152  * may be NULL if buttons are to be added dynamically.
       
   153  */
       
   154 EXPORT_C CEikButtonGroupContainer* CEikButtonGroupContainer::NewL(
       
   155     TUse aUse,
       
   156     TOrientation aOrientation,
       
   157     MEikCommandObserver* aCommandObserver,
       
   158     TInt aResourceId,
       
   159     RWindowGroup& aParentWg,
       
   160     TUint aFlags)
       
   161     { // static
       
   162     CEikButtonGroupContainer* self = new(ELeave) CEikButtonGroupContainer(aUse);
       
   163     CleanupStack::PushL(self);
       
   164     self->ConstructL(aOrientation, aCommandObserver, aResourceId, &aParentWg, aFlags);
       
   165     CleanupStack::Pop(); // self
       
   166     AKNTASHOOK_ADDL( self, "CEikButtonGroupContainer" );
       
   167     return self;
       
   168     }
       
   169 
       
   170 EXPORT_C CEikButtonGroupContainer::~CEikButtonGroupContainer()
       
   171     {
       
   172     AKNTASHOOK_REMOVE();
       
   173     AVKONENV->InformCbaDeletion(this);
       
   174     CEikButtonGroupStack::Remove(*this);
       
   175     if (iButtonGroup)
       
   176         {
       
   177         iButtonGroup->Release();
       
   178         }
       
   179     if (iMSKObserverOwner)
       
   180         {
       
   181         iMSKObserverOwner->InformMSKButtonGroupDeletion();
       
   182         iMSKObserverOwner = NULL;
       
   183         }
       
   184     delete iCommandsCleanup;
       
   185     iCommandsCleanup = NULL;
       
   186     delete iObserverArray;
       
   187     iValid = KErrNotFound;
       
   188     iObserverArray = NULL;
       
   189     }
       
   190 
       
   191 /**
       
   192  * Returns a pointer to an app's currently active CEikButtonGroupContainer (if any).
       
   193  * Returns NULL if there are no containers active or none suitable for sharing.
       
   194  * Ownership of the pointer returned is not transferred.
       
   195  */
       
   196 EXPORT_C CEikButtonGroupContainer* CEikButtonGroupContainer::Current()
       
   197     { // static
       
   198     return CEikButtonGroupStack::Current();
       
   199     }
       
   200 
       
   201 /**
       
   202  * Removes the command identified by aCommandId, in position aPosition in the group, from the
       
   203  * command stack. Automatically retrieves the previous command details.
       
   204  *
       
   205  * Commands are added to the stack by calling AddCommandToStackL. 
       
   206  */
       
   207 EXPORT_C void CEikButtonGroupContainer::RemoveCommandFromStack(TInt aPosition, TInt aCommandId)
       
   208     {
       
   209     iButtonGroup->RemoveCommandFromStack(aPosition, aCommandId);
       
   210     }
       
   211 
       
   212 EXPORT_C void CEikButtonGroupContainer::SetDefaultCommand(TInt aCommandId)
       
   213     {
       
   214     iButtonGroup->SetDefaultCommand(aCommandId);
       
   215     }
       
   216 
       
   217 EXPORT_C TSize CEikButtonGroupContainer::CalcMinimumSizeL(TInt aResourceId) const
       
   218     {
       
   219     return iButtonGroup->CalcMinimumSizeL(aResourceId);
       
   220     }
       
   221 
       
   222 void CEikButtonGroupContainer::CleanupCommandDestroy(TAny* aPtr)
       
   223     { // static
       
   224     REINTERPRET_CAST(CEikButtonGroupContainer*, aPtr)->DoCleanupCommandPopAndDestroy();
       
   225     }
       
   226 
       
   227 /**
       
   228  * Places the command in position aPosition in the group on the cleanup stack. Typically used
       
   229  * when a control or view changes the contents of two or more buttons on receipt of focus. 
       
   230  * After altering one command with a call to AddCommandToStackL the push is made to
       
   231  * guarantee the display will be left in a consistent state if the second (and any subsequent)
       
   232  * calls to AddCommandToStackL fail.
       
   233  *
       
   234  * Only a single command can be pushed for each position.
       
   235  */
       
   236 EXPORT_C void CEikButtonGroupContainer::CleanupCommandPushL(TInt aPosition)
       
   237     {
       
   238     const TInt count = iCommandsCleanup->Count();
       
   239     TBool pushed = EFalse;
       
   240     for (TInt ii = 0; ii < count; ii++)
       
   241         {
       
   242         TCmdPos& cmdPos = (*iCommandsCleanup)[ii];
       
   243         __ASSERT_ALWAYS(cmdPos.iPos != aPosition, Panic(EEikPanicButtonGroupDuplicateCleanupPos));  
       
   244         if (cmdPos.iPos == KCleanupNoCommand)
       
   245             {
       
   246             cmdPos.iPos = aPosition;
       
   247             cmdPos.iCmd = iButtonGroup->CommandId(aPosition);
       
   248             pushed = ETrue;
       
   249             break;
       
   250             }
       
   251         }
       
   252     __ASSERT_ALWAYS(pushed, Panic(EEikPanicButtonGroupCleanupCorrupt));
       
   253     CleanupStack::PushL(TCleanupItem(CleanupCommandDestroy, this));
       
   254     }
       
   255 
       
   256 /**
       
   257  * Removes a command (or aCount commands) altered by calling AddCommandToStackL from the cleanup
       
   258  * stack without changing its state.
       
   259  */
       
   260 EXPORT_C void CEikButtonGroupContainer::CleanupCommandPop(TInt aCount)
       
   261     {
       
   262     while (aCount--)
       
   263         {
       
   264         DoCleanupCommandPop();
       
   265         CleanupStack::Pop();
       
   266         }
       
   267     }
       
   268 
       
   269 CEikButtonGroupContainer::TCmdPos CEikButtonGroupContainer::DoCleanupCommandPop()
       
   270     {
       
   271     const TInt count = iCommandsCleanup->Count();
       
   272     TInt index = -1;
       
   273     for (TInt ii = 0; ii < count; ii++)
       
   274         {
       
   275         if ((*iCommandsCleanup)[ii].iPos == KCleanupNoCommand)
       
   276             {
       
   277             index = ii - 1;
       
   278             __ASSERT_DEBUG(index != -1, Panic(EEikPanicButtonGroupCleanupCorrupt));
       
   279             break;
       
   280             }
       
   281         }
       
   282     if (index == -1)
       
   283         { // all cleanup slots are filled
       
   284         index = count-1;
       
   285         }
       
   286     TCmdPos cmdPos = (*iCommandsCleanup)[index];
       
   287     iCommandsCleanup->At(index) = TCmdPos();
       
   288     return cmdPos;
       
   289     }
       
   290 
       
   291 void CEikButtonGroupContainer::DoCleanupCommandPopAndDestroy()
       
   292     {
       
   293     TCmdPos cmdPos = DoCleanupCommandPop();
       
   294     RemoveCommandFromStack(cmdPos.iPos, cmdPos.iCmd);
       
   295     }
       
   296 
       
   297 /**
       
   298  * Returns the maximum number of commands a particular device supports.
       
   299  */
       
   300 EXPORT_C TInt CEikButtonGroupContainer::MaxCommands() const
       
   301     {
       
   302     return 4; // !!! need to get this from LAF
       
   303     }
       
   304 
       
   305 /**
       
   306  * Returns the number of buttons currently present.
       
   307  */
       
   308 EXPORT_C TInt CEikButtonGroupContainer::ButtonCount() const
       
   309     {
       
   310     return iButtonGroup->ButtonCount();
       
   311     }
       
   312 
       
   313 EXPORT_C void CEikButtonGroupContainer::DimCommand(TInt aCommandId, TBool aDimmed)
       
   314     {
       
   315     iButtonGroup->DimCommand(aCommandId, aDimmed);
       
   316     }
       
   317 
       
   318 EXPORT_C TBool CEikButtonGroupContainer::IsCommandDimmed(TInt aCommandId) const
       
   319     {
       
   320     return iButtonGroup->IsCommandDimmed(aCommandId);
       
   321     }
       
   322 
       
   323 EXPORT_C void CEikButtonGroupContainer::MakeCommandVisible(TInt aCommandId, TBool aVisible)
       
   324     {
       
   325     iButtonGroup->MakeCommandVisible(aCommandId, aVisible);
       
   326     }
       
   327 
       
   328 EXPORT_C TBool CEikButtonGroupContainer::IsCommandVisible(TInt aCommandId) const
       
   329     {
       
   330     return iButtonGroup->IsCommandVisible(aCommandId);
       
   331     }
       
   332 
       
   333 EXPORT_C void CEikButtonGroupContainer::AnimateCommand(TInt aCommandId)
       
   334     {
       
   335     iButtonGroup->AnimateCommand(aCommandId);
       
   336     }
       
   337 
       
   338 EXPORT_C void CEikButtonGroupContainer::DimCommandByPosition(TCommandPosition aPosition, 
       
   339     TBool aDimmed)
       
   340     {
       
   341     iButtonGroup->DimCommandByPosition((TInt)aPosition, aDimmed);
       
   342     }
       
   343 
       
   344 EXPORT_C TBool CEikButtonGroupContainer::IsCommandDimmedByPosition(TCommandPosition aPosition) const
       
   345     {
       
   346     return iButtonGroup->IsCommandDimmedByPosition((TInt)aPosition);
       
   347     }
       
   348 
       
   349 EXPORT_C void CEikButtonGroupContainer::MakeCommandVisibleByPosition(TCommandPosition aPosition, 
       
   350     TBool aVisible)
       
   351     {
       
   352     iButtonGroup->MakeCommandVisibleByPosition((TInt)aPosition, aVisible);
       
   353     }
       
   354 
       
   355 EXPORT_C TBool CEikButtonGroupContainer::IsCommandVisibleByPosition(
       
   356     TCommandPosition aPosition) const
       
   357     {
       
   358     return iButtonGroup->IsCommandVisibleByPosition((TInt)aPosition);
       
   359     }
       
   360 
       
   361 EXPORT_C void CEikButtonGroupContainer::AnimateCommandByPosition(TCommandPosition aPosition)
       
   362     {
       
   363     iButtonGroup->AnimateCommandByPosition((TInt)aPosition);
       
   364     }
       
   365 
       
   366 
       
   367 EXPORT_C TSize CEikButtonGroupContainer::MinimumSize()
       
   368     {
       
   369     TSize size = ButtonGroupAsControl()->MinimumSize();
       
   370     // add borders size from LAF
       
   371     return size;
       
   372     }
       
   373 
       
   374 CEikButtonGroupContainer::CEikButtonGroupContainer(TUse aUse)
       
   375     : iUse(aUse)
       
   376     {
       
   377     SetComponentsToInheritVisibility();
       
   378     }
       
   379 
       
   380 void CEikButtonGroupContainer::ConstructL(
       
   381     TOrientation aOrientation,
       
   382     MEikCommandObserver* aCommandObserver,
       
   383     TInt aResourceId,
       
   384     RWindowGroup* aParentWg,
       
   385     TUint aFlags)
       
   386     {
       
   387     iValid = KIsValid;
       
   388     iCommandObserver = aCommandObserver;
       
   389     const TInt numCmds = MaxCommands();
       
   390     iCommandsCleanup = new(ELeave) CArrayFixFlat<TCmdPos>(numCmds);
       
   391     for (TInt ii = 0; ii < numCmds; ii++)
       
   392         {
       
   393         iCommandsCleanup->AppendL(TCmdPos());
       
   394         }
       
   395 
       
   396     TInt buttonType = LafButtonGroupContainer::ButtonType(iUse);
       
   397 
       
   398     TBool addToButtonGroupStack = EFalse;
       
   399     
       
   400     EikButtonGroupFactory::TCreationData creationData(
       
   401         iUse,
       
   402         this,
       
   403         aResourceId,
       
   404         aParentWg,
       
   405         aFlags,
       
   406         aOrientation);
       
   407         
       
   408     iButtonGroup = (MEikButtonGroup*)EikButtonGroupFactory::CreateButtonGroupByTypeL(
       
   409         buttonType,
       
   410         creationData,
       
   411         addToButtonGroupStack);
       
   412         
       
   413     __ASSERT_ALWAYS(iButtonGroup, Panic(EEikPanicButtonGroupNotFoundInFactory));
       
   414     if(addToButtonGroupStack)
       
   415         {
       
   416         CEikButtonGroupStack::AddL(*this);
       
   417         }
       
   418 
       
   419     SetContainerWindowL(*(iButtonGroup->AsControl()));
       
   420     SetParent( NULL );
       
   421 
       
   422     // __ASSERT_DEBUG(iButtonGroup==NULL...
       
   423     if (!(aFlags&EDelayActivation))
       
   424         {
       
   425         ActivateL();
       
   426         }
       
   427     }
       
   428 
       
   429 /**
       
   430  * Sets the text, bitmaps and command ids specified at aResourceId into the buttons.
       
   431  *
       
   432  * @since ER5U 
       
   433  */
       
   434 EXPORT_C void CEikButtonGroupContainer::SetCommandSetL(TInt aResourceId)
       
   435     {
       
   436     iButtonGroup->SetCommandSetL(aResourceId);
       
   437     }
       
   438 
       
   439 /**
       
   440  * As with SetCommandL but allows the previous command to be retrieved at 
       
   441  * any time by calling RemoveCommand.  Panics if aPosition is out of range.
       
   442  *
       
   443  * @since ER5U 
       
   444  */
       
   445 EXPORT_C void CEikButtonGroupContainer::AddCommandSetToStackL(TInt aResourceId)
       
   446     {
       
   447     iButtonGroup->AddCommandSetToStackL(aResourceId);
       
   448     }
       
   449 
       
   450 EXPORT_C void CEikButtonGroupContainer::DoSetCommandL(
       
   451     TInt aPosition,
       
   452     TInt aCommandId,
       
   453     const TDesC* aText,
       
   454     const CFbsBitmap* aBitmap,
       
   455     const CFbsBitmap* aMask,
       
   456     TCommandOp aOp)
       
   457     {
       
   458     TPtrC text;
       
   459     if (aText)
       
   460         {
       
   461         text.Set(*aText);
       
   462         }
       
   463     else
       
   464         {
       
   465         text.Set(KNullDesC);
       
   466         }
       
   467     
       
   468     switch (aOp)
       
   469         {
       
   470         case ESet:
       
   471             iButtonGroup->SetCommandL(aPosition, aCommandId, &text, aBitmap, aMask);
       
   472             break;
       
   473         case EAdd:
       
   474             iButtonGroup->AddCommandL(aPosition, aCommandId, &text, aBitmap, aMask);
       
   475             break;
       
   476         case EPush:
       
   477             // slightly wasteful - could check whether extra slot is required first        
       
   478             iCommandsCleanup->AppendL(TCmdPos()); 
       
   479             iButtonGroup->AddCommandToStackL(aPosition, aCommandId, &text, aBitmap, aMask);
       
   480             break;
       
   481         }
       
   482     }
       
   483 
       
   484 EXPORT_C void CEikButtonGroupContainer::DoSetCommandL(
       
   485     TInt aPosition,
       
   486     TInt aCommandId,
       
   487     const TDesC* aText,
       
   488     const TDesC& aFile,
       
   489     TInt aBitmapId,
       
   490     TInt aMaskId,
       
   491     TCommandOp aOp)
       
   492     {
       
   493     CFbsBitmap* bitmap = AknIconUtils::CreateIconL(aFile, aBitmapId);
       
   494     CleanupStack::PushL(bitmap);
       
   495     CFbsBitmap* mask = AknIconUtils::CreateIconL(aFile, aMaskId);
       
   496     CleanupStack::PushL(mask);
       
   497     DoSetCommandL(aPosition, aCommandId, aText, bitmap, mask, aOp);
       
   498     CleanupStack::Pop(2); // bitmap, mask
       
   499     }
       
   500 
       
   501 EXPORT_C void CEikButtonGroupContainer::DoSetCommandL(
       
   502     TInt aCommandId,
       
   503     const TDesC* aText,
       
   504     const CFbsBitmap* aBitmap,
       
   505     const CFbsBitmap* aMask,
       
   506     TCommandOp aOp)
       
   507     {
       
   508     const TInt pos = PositionById(aCommandId);
       
   509     if (pos == KErrNotFound)
       
   510         {
       
   511         User::LeaveIfError(KErrNotFound);
       
   512         }
       
   513     DoSetCommandL(pos, aCommandId, aText, aBitmap, aMask, aOp);
       
   514     }
       
   515 
       
   516 EXPORT_C void CEikButtonGroupContainer::DoSetCommandL(
       
   517     TInt aCommandId,
       
   518     const TDesC* aText,
       
   519     const TDesC& aFile,
       
   520     TInt aBitmapId,
       
   521     TInt aMaskId,
       
   522     TCommandOp aOp)
       
   523     {
       
   524     const TInt pos = PositionById(aCommandId);
       
   525     if (pos == KErrNotFound)
       
   526         {
       
   527         User::LeaveIfError(KErrNotFound);
       
   528         }
       
   529     DoSetCommandL(pos, aCommandId, aText, aFile, aBitmapId, aMaskId, aOp);
       
   530     }
       
   531 
       
   532 EXPORT_C void CEikButtonGroupContainer::DoSetCommandL(
       
   533     TInt aPosition, 
       
   534     TInt aResourceId, 
       
   535     TCommandOp aOp)
       
   536     {
       
   537     switch(aOp)
       
   538         {
       
   539         case ESet:
       
   540             iButtonGroup->SetCommandL(aPosition, aResourceId);
       
   541             break;
       
   542         case EAdd:
       
   543             User::Leave(KErrNotSupported);
       
   544             break;
       
   545         case EPush:
       
   546             iButtonGroup->AddCommandToStackL(aPosition, aResourceId);
       
   547             break;
       
   548         };
       
   549     }
       
   550 
       
   551 /**
       
   552  * Returns the location of the button group. Typically the button group is external to the view 
       
   553  * which is using it. In some cases, such as in dialogs with button panels, the button group is 
       
   554  * internal to the control which is using it.
       
   555  */
       
   556 EXPORT_C CEikButtonGroupContainer::TLocation CEikButtonGroupContainer::Location() const
       
   557     {
       
   558     return CEikButtonGroupContainer::TLocation (LafButtonGroupContainer::Location(iUse));
       
   559     }
       
   560 
       
   561 /**
       
   562  * Returns the command button given by aCommandId.
       
   563  *
       
   564  * @since App-Framework_6.1 
       
   565  */
       
   566 EXPORT_C CEikCommandButton* CEikButtonGroupContainer::CommandButtonOrNull(TInt aCommandId) const
       
   567     {
       
   568     return iButtonGroup->GroupControlAsButton(aCommandId);
       
   569     }
       
   570 
       
   571 /**
       
   572  * Sets the boundary rectangle to aRect. The button group attaches itself to the inside of this 
       
   573  * rectangle.
       
   574  */
       
   575 EXPORT_C void CEikButtonGroupContainer::SetBoundingRect(const TRect& aRect)
       
   576     {
       
   577     iButtonGroup->SetBoundingRect(aRect);
       
   578     UpdateRect();
       
   579     }
       
   580 
       
   581 /**
       
   582  * Subtracts the area occupied by the button group from aBoundingRect. This method should 
       
   583  * be used in preference to querying the container's area at all times.
       
   584  */
       
   585 EXPORT_C void CEikButtonGroupContainer::ReduceRect(TRect& aBoundingRect) const
       
   586     {
       
   587     iButtonGroup->ReduceRect(aBoundingRect);
       
   588     CONST_CAST(CEikButtonGroupContainer*, this)->UpdateRect();
       
   589     }
       
   590 
       
   591 void CEikButtonGroupContainer::UpdateRect()
       
   592     {
       
   593     CCoeControl* ctrl = ButtonGroupAsControl();
       
   594     const TRect rect = ctrl->Rect();
       
   595     // TP: PositionRelativeToScreen() causes unnecessary Flush(). Thus it cannot be used.
       
   596     iPosition = rect.iTl;
       
   597     
       
   598     TRect screenRect = iAvkonAppUi->ApplicationRect();
       
   599     
       
   600 #ifdef RD_SCALABLE_UI_V2
       
   601     // ctrl position and size should be right
       
   602     iPosition = ctrl->Position();
       
   603     iSize = ctrl->Size();
       
   604 #else // RD_SCALABLE_UI_V2
       
   605     // For safety, still use the old code in portrait mode
       
   606     if (screenRect.Width() < screenRect.Height())
       
   607         {
       
   608         TAknWindowLineLayout layout(AKN_LAYOUT_WINDOW_control_pane(TSize(screenRect.Size())));
       
   609         TAknLayoutRect layoutRect;
       
   610         layoutRect.LayoutRect(screenRect, layout);
       
   611         iPosition.iY += screenRect.Height() - layoutRect.Rect().Height();
       
   612         iSize = rect.Size();
       
   613         }
       
   614     else
       
   615         {
       
   616         iPosition = ctrl->Position();
       
   617         iSize = ctrl->Size();
       
   618         }
       
   619 #endif // RD_SCALABLE_UI_V2
       
   620     }
       
   621 
       
   622 
       
   623 /**
       
   624  * Returns a pointer to the control with id aCommandId. This method is intended to allow access
       
   625  * to standard CCoeControl functionality only. Casting the return value is likely to fail on
       
   626  * different devices.
       
   627  */
       
   628 EXPORT_C CCoeControl* CEikButtonGroupContainer::ControlOrNull(TInt aCommandId) const
       
   629     {
       
   630     return iButtonGroup->GroupControlById(aCommandId);
       
   631     }
       
   632 
       
   633 /**
       
   634  * Returns a pointer to the button with id aCommandId. May return NULL on some devices.
       
   635  */
       
   636 EXPORT_C CEikCommandButton* CEikButtonGroupContainer::ButtonById(TInt aCommandId) const
       
   637     {
       
   638     return iButtonGroup->GroupControlAsButton(aCommandId);
       
   639     }
       
   640     
       
   641 /**
       
   642  * Returns the position in the group of the command identified by aCommandId. The return value is 
       
   643  * undefined if two buttons share the same id.
       
   644  */
       
   645 EXPORT_C TInt CEikButtonGroupContainer::PositionById(TInt aCommandId) const
       
   646     {
       
   647     return iButtonGroup->CommandPos(aCommandId);
       
   648     }
       
   649 
       
   650 /**
       
   651  * Changes the hotkey association for the command identified by aCommandId to the hot key flags 
       
   652  * aFlags and the key id aKeyId. Only supported for dialogs.
       
   653  */
       
   654 EXPORT_C void CEikButtonGroupContainer::UpdateHotKey(
       
   655     TInt aCommandId, 
       
   656     THotKeyFlags aFlags, 
       
   657     TInt aKeyId)
       
   658     {
       
   659     if (!(iUse == EDialog || iUse == EDialogButtons))
       
   660         {
       
   661         return;
       
   662         }
       
   663     TRAP_IGNORE(STATIC_CAST(CEikButtonPanel*, ButtonGroupAsControl())->UpdateHotKeyL(
       
   664         aCommandId, (CEikLabeledButton::TFlags)aFlags, aKeyId));
       
   665     }
       
   666 
       
   667 /**
       
   668  * Temporarily change the command observer for the button at aPos to aCommandObserver.
       
   669  * Panics if an updated observer is already present.
       
   670  */
       
   671 EXPORT_C void CEikButtonGroupContainer::UpdateCommandObserverL(
       
   672     TInt aPos, 
       
   673     MEikCommandObserver& aCommandObserver)
       
   674     {
       
   675     if (!iObserverArray)
       
   676         {
       
   677         iObserverArray = new(ELeave) CCmdObserverArray();
       
   678         }
       
   679     else
       
   680         {
       
   681         __ASSERT_ALWAYS(iObserverArray->FindIndex(aPos) == KErrNotFound, 
       
   682             Panic(EEikPanicButtonGroupDuplicateObserver));
       
   683         }
       
   684     TCmdObserver obs(aPos,aCommandObserver);
       
   685     iObserverArray->AppendL(obs);
       
   686     }
       
   687     
       
   688 EXPORT_C TBool CEikButtonGroupContainer::UpdatedCommandObserverExists(
       
   689     TCommandPosition aPosition) const
       
   690     {
       
   691     if ( !iObserverArray )
       
   692         {
       
   693         return EFalse;
       
   694         }
       
   695     const TInt pos = iObserverArray->FindIndex( aPosition );
       
   696     if ( pos != KErrNotFound )
       
   697         {
       
   698         return ETrue;
       
   699         }
       
   700     return EFalse; // no command observer found
       
   701     }
       
   702 
       
   703 void CEikButtonGroupContainer::UpdateMSKCommandObserver(
       
   704     CEikListBox* aMSKObserverOwner,
       
   705     MEikCommandObserver* aCommandObserver)
       
   706     {
       
   707     // badly coded applications may call this method for different listboxes
       
   708     // e.g. by activating more than one listbox for one view and never unfocusing them.
       
   709     // If this happens, the first MSK observer set will be used and other observers will
       
   710     // be discarded.
       
   711     if (iMSKObserverOwner && iMSKObserverOwner != aMSKObserverOwner && aCommandObserver)
       
   712         {
       
   713         // this will prevent listbox from calling already deleted buttongroup
       
   714         aMSKObserverOwner->InformMSKButtonGroupDeletion();
       
   715         return;
       
   716         }
       
   717     
       
   718     if (aCommandObserver == NULL && iMSKObserverOwner == aMSKObserverOwner)
       
   719         {
       
   720         iMSKObserverOwner = NULL;
       
   721         }
       
   722     else
       
   723         {
       
   724         iMSKObserverOwner = aMSKObserverOwner;
       
   725         }
       
   726         
       
   727     if (iButtonGroup)
       
   728         {
       
   729         iButtonGroup->SetMSKCommandObserver(aCommandObserver);    
       
   730         }
       
   731     }
       
   732     
       
   733 /**
       
   734  * Remove the temporary observer for the command at aPos.
       
   735  */
       
   736 EXPORT_C void CEikButtonGroupContainer::RemoveCommandObserver(TInt aPos)
       
   737     {
       
   738     if ( iValid != KIsValid )
       
   739         {
       
   740         return;
       
   741         }
       
   742     const TInt pos = ( iObserverArray? iObserverArray->FindIndex(aPos) : KErrNotFound );
       
   743     if (pos != KErrNotFound)
       
   744         {
       
   745         iObserverArray->Delete(pos);
       
   746         if (iObserverArray->Count() == 0)
       
   747             {
       
   748             delete iObserverArray;
       
   749             iObserverArray = NULL;
       
   750             }
       
   751         }
       
   752     }
       
   753 
       
   754 /**
       
   755  * Has the button group been explicitly instructed to suppress redraws
       
   756  */
       
   757 EXPORT_C TBool CEikButtonGroupContainer::DelayActivation() const
       
   758     {
       
   759     TUint flags = iButtonGroup->ButtonGroupFlags();
       
   760     return (flags&EDelayActivation);
       
   761     }
       
   762 
       
   763 EXPORT_C TKeyResponse CEikButtonGroupContainer::OfferKeyEventL(
       
   764     const TKeyEvent& aKeyEvent, 
       
   765     TEventCode aType)
       
   766     {
       
   767     return ButtonGroupAsControl()->OfferKeyEventL(aKeyEvent,aType);
       
   768     }
       
   769 
       
   770 void CEikButtonGroupContainer::MakeVisible(TBool aVisible)
       
   771     {
       
   772     ButtonGroupAsControl()->MakeVisible(aVisible);
       
   773     CCoeControl::MakeVisible(aVisible);
       
   774     }
       
   775 
       
   776 TInt CEikButtonGroupContainer::CountComponentControls() const
       
   777     {
       
   778     return 1;
       
   779     }
       
   780 
       
   781 CCoeControl* CEikButtonGroupContainer::ComponentControl(TInt aIndex) const
       
   782     {
       
   783     if (aIndex == 0)
       
   784         {
       
   785         return ButtonGroupAsControl();
       
   786         }
       
   787     return NULL;
       
   788     }
       
   789 
       
   790 void CEikButtonGroupContainer::SizeChanged()
       
   791     {
       
   792     TRect rect(Rect());
       
   793     // subtract any margins
       
   794     ButtonGroupAsControl()->SetRect(rect);
       
   795     }
       
   796 
       
   797 void CEikButtonGroupContainer::ProcessCommandL(TInt aCommandId)
       
   798     {
       
   799     // check for different observer
       
   800     const TInt cmdPos = PositionById(aCommandId);
       
   801     const TInt pos = (iObserverArray ? iObserverArray->FindIndex(cmdPos) : KErrNotFound);
       
   802     if (pos != KErrNotFound)
       
   803         {
       
   804         (*iObserverArray)[pos].iObserver.ProcessCommandL(aCommandId);
       
   805         }
       
   806     else // otherwise, pass event on to standard observer
       
   807         {
       
   808         iCommandObserver->ProcessCommandL(aCommandId);
       
   809         }
       
   810     }
       
   811 
       
   812 CCoeControl* CEikButtonGroupContainer::CreateCustomCommandControlL(TInt aControlType)
       
   813     {
       
   814     CCoeControl* ctrl = NULL;
       
   815     if (iCommandObserver)
       
   816         {
       
   817         ctrl = iCommandObserver->CreateCustomCommandControlL(aControlType);
       
   818         }
       
   819     return ctrl;
       
   820     }
       
   821 
       
   822 EXPORT_C void CEikButtonGroupContainer::Reserved_MtsmPosition()
       
   823     {
       
   824     }
       
   825 
       
   826 EXPORT_C void CEikButtonGroupContainer::Reserved_MtsmObject()
       
   827     {
       
   828     }
       
   829     
       
   830 #ifndef RD_ENHANCED_CBA
       
   831 EXPORT_C void CEikButtonGroupContainer::OfferCommandListL(const RArray<TInt>& /*aCommandList*/)
       
   832     {
       
   833 #else // RD_ENHANCED_CBA
       
   834 EXPORT_C void CEikButtonGroupContainer::OfferCommandListL(const RArray<TInt>& aCommandList)
       
   835     {
       
   836     static_cast<MEikEnhancedButtonGroup*>(iButtonGroup)->OfferCommandListL( aCommandList );
       
   837 #endif  
       
   838     }
       
   839 
       
   840 #ifndef RD_ENHANCED_CBA
       
   841 EXPORT_C void CEikButtonGroupContainer::OfferCommandListL(const TInt /*aResourceId*/)
       
   842     {
       
   843 #else // RD_ENHANCED_CBA    
       
   844 EXPORT_C void CEikButtonGroupContainer::OfferCommandListL(const TInt aResourceId)
       
   845     {
       
   846     static_cast<MEikEnhancedButtonGroup*>(iButtonGroup)->OfferCommandListL( aResourceId );
       
   847 #endif
       
   848     }
       
   849     
       
   850 #ifdef RD_ENHANCED_CBA  
       
   851 EXPORT_C TBool CEikButtonGroupContainer::IsCommandInGroup(const TInt aCommandId) const
       
   852     {
       
   853     return static_cast<MEikEnhancedButtonGroup*>(iButtonGroup)->IsCommandInGroup( aCommandId );
       
   854     }
       
   855 #else
       
   856 EXPORT_C TBool CEikButtonGroupContainer::IsCommandInGroup(const TInt /*aCommandId*/) const
       
   857     {
       
   858     return EFalse;
       
   859     }
       
   860 #endif      
       
   861 
       
   862     
       
   863 #ifndef RD_ENHANCED_CBA
       
   864 EXPORT_C void CEikButtonGroupContainer::ReplaceCommand(
       
   865     const TInt /*aCommandId*/, 
       
   866     const TInt /*aResourceId*/)
       
   867     {
       
   868 #else //  RD_ENHANCED_CBA
       
   869 EXPORT_C void CEikButtonGroupContainer::ReplaceCommand(
       
   870     const TInt aCommandId, 
       
   871     const TInt aResourceId )
       
   872     {
       
   873     static_cast<MEikEnhancedButtonGroup*>(iButtonGroup)->ReplaceCommand( aCommandId, aResourceId );
       
   874 #endif  
       
   875     }
       
   876 
       
   877 
       
   878 /**
       
   879  * Writes the internal state of the control and its components to aStream.
       
   880  * Does nothing in release mode.
       
   881  * Designed to be overidden and base called by subclasses.
       
   882  *
       
   883  * @internal
       
   884  * @since App-Framework_6.1
       
   885  */
       
   886 #ifndef _DEBUG
       
   887 EXPORT_C void CEikButtonGroupContainer::WriteInternalStateL(RWriteStream&) const
       
   888     {
       
   889     }
       
   890 #else
       
   891 EXPORT_C void CEikButtonGroupContainer::WriteInternalStateL(RWriteStream& aWriteStream) const
       
   892     {
       
   893     _LIT(KEikLitBtgrpcCtlSt, "<CEikButtonGroupContainer>");
       
   894     _LIT(KEikLitBtgrpcCtlEnd, "<\\CEikButtonGroupContainer>");
       
   895     _LIT(KEikLitBtgrpcCtlBtGrp, "<iButtonGroup>");
       
   896     _LIT(KEikLitBtgrpcCtlBtGrpEnd, "<\\iButtonGroup>");
       
   897     _LIT(KEikLitBtgrpcCtlUse, "<iUse>");
       
   898     _LIT(KEikLitBtgrpcCtlUseEnd, "<\\iUse>");
       
   899     _LIT(KEikLitBtgrpcCtlCleanup, "<iCommandsCleanup>");
       
   900     _LIT(KEikLitBtgrpcCtlCleanupEnd, "<\\iCommandsCleanup>");
       
   901     _LIT(KEikLitBtgrpcCtlObs, "<iCommandObserver>");
       
   902     _LIT(KEikLitBtgrpcCtlObsEnd, "<\\iCommandObserver>");
       
   903     _LIT(KEikLitBtgrpcCtlObsArray, "<iObserverArray>");
       
   904     _LIT(KEikLitBtgrpcCtlObsArrayEnd, "<\\iObserverArray>");
       
   905     _LIT(KEikLitBtgrpcCtlQLnk, "<iBtLink>");
       
   906     _LIT(KEikLitBtgrpcCtlQLnkEnd, "<\\iBtLink>");
       
   907 
       
   908     aWriteStream << KEikLitBtgrpcCtlSt;
       
   909     aWriteStream << KEikLitBtgrpcCtlBtGrp;
       
   910     aWriteStream.WriteInt32L((TInt)iButtonGroup);
       
   911     aWriteStream << KEikLitBtgrpcCtlBtGrpEnd;
       
   912     aWriteStream << KEikLitBtgrpcCtlUse;
       
   913     aWriteStream.WriteInt32L((TInt)iUse);
       
   914     aWriteStream << KEikLitBtgrpcCtlUseEnd;
       
   915 
       
   916     aWriteStream << KEikLitBtgrpcCtlCleanup;
       
   917     const TInt cmdCount = (iCommandsCleanup ? iCommandsCleanup->Count() : 0);
       
   918     for(TInt i = 0; i < cmdCount; i++)
       
   919         {
       
   920         TCmdPos& pos=(*iCommandsCleanup)[i];
       
   921         aWriteStream.WriteInt32L(pos.iCmd);
       
   922         aWriteStream.WriteInt32L(pos.iPos);
       
   923         }
       
   924     aWriteStream << KEikLitBtgrpcCtlCleanupEnd;
       
   925     aWriteStream << KEikLitBtgrpcCtlObs;
       
   926     aWriteStream.WriteInt32L((TInt)iCommandObserver);
       
   927     aWriteStream << KEikLitBtgrpcCtlObsEnd;
       
   928 
       
   929     aWriteStream << KEikLitBtgrpcCtlObsArray;
       
   930     const TInt obsCount = (iObserverArray ? iObserverArray->Count() :0);
       
   931     for(TInt j = 0; j < obsCount; j++)
       
   932         {
       
   933         TCmdObserver& obs = (*iObserverArray)[j];
       
   934         aWriteStream.WriteInt32L((TInt)&(obs.iObserver));
       
   935         aWriteStream.WriteInt32L(obs.iPos);
       
   936         }
       
   937     aWriteStream << KEikLitBtgrpcCtlObsArrayEnd;
       
   938     aWriteStream << KEikLitBtgrpcCtlQLnk;
       
   939     aWriteStream.WriteInt32L((TInt)iBtLink.iPrev);
       
   940     aWriteStream.WriteInt32L((TInt)iBtLink.iNext);
       
   941     aWriteStream << KEikLitBtgrpcCtlQLnkEnd;
       
   942     CCoeControl::WriteInternalStateL(aWriteStream);
       
   943     aWriteStream << KEikLitBtgrpcCtlEnd;
       
   944     }
       
   945 #endif