diff -r 5b6f26637ad3 -r f4a778e096c2 phonebookui/Phonebook2/UIControls/src/CPbk2NamesListReadyState.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/phonebookui/Phonebook2/UIControls/src/CPbk2NamesListReadyState.cpp Wed Sep 01 12:29:52 2010 +0100 @@ -0,0 +1,2436 @@ +/* +* Copyright (c) 2005-2007 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: Phonebook 2 names list ready state. +* +*/ + + +// INCLUDE FILES +#include "CPbk2NamesListReadyState.h" + +// Phonebook 2 +#include "CPbk2AdaptiveSearchGridFiller.h" +#include "CPbk2ThumbnailLoader.h" +#include "CPbk2ContactViewListBox.h" +#include "CPbk2ContactViewIterator.h" +#include "MPbk2UiControlEventSender.h" +#include "CPbk2FindDelay.h" +#include "CPbk2NamesListControl.h" +#include "CPbk2FindStringSplitter.h" +#include +#include +#include +#include +#include +#include "TPbk2FindTextUtil.h" +#include + +#include "PmuCommands.hrh" // For accessing EPmuCmdCascadingBackup +#include "Pbk2USimUI.hrh" // For accessing EPsu2CmdCascadingSimMemory +#include +#include + +// Virtual Phonebook +#include +#include +#include +#include +#include +#include +#include + +// System includes +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Debugging headers +#include +#include "CPbk2PredictiveSearchFilter.h" +#include "cpbk2predictiveviewstack.h" + + +/// Unnamed namespace for local definitions +namespace { + +// LOCAL CONSTANTS AND MACROS +const TInt KNumberOfControls = 2; // listbox and findbox +const TInt KFindDelayTime = 700000; // microseconds +const TInt KFindDelayThresholdContacts = 1000; // amount of contacts to + // activate find delay + +#ifdef _DEBUG +enum TPanicCode + { + EPanicLogic_ComponentControl = 1, + EPanicLogic_FindTextL, + EPanicLogic_PreConds_SetCurrentItemIndexAndDraw, + EPanicLogic_Command_index_out_of_bounds + }; + +void Panic(TPanicCode aReason) + { + _LIT(KPanicText, "CPbk2NamesListReadyState"); + User::Panic(KPanicText, aReason); + } +#endif // _DEBUG + + +NONSHARABLE_CLASS(TCleanupEnableListBoxViewRedraw) + { + public: // Interface + + /** + * Constructor. + * + * @param aListBoxView The list box view + */ + inline TCleanupEnableListBoxViewRedraw( CListBoxView& aListBoxView ) + : iCleanupItem( CleanupOp, &aListBoxView ) + { + } + + /** + * Returns the cleanup item. + */ + inline operator TCleanupItem() const + { + return iCleanupItem; + } + + private: // Implementation + static void CleanupOp( + TAny* aPtr ); + + private: // Data + /// Own: Cleanup item + TCleanupItem iCleanupItem; + }; + +// -------------------------------------------------------------------------- +// TCleanupEnableListBoxViewRedraw::CleanupOp +// -------------------------------------------------------------------------- +// +void TCleanupEnableListBoxViewRedraw::CleanupOp( TAny* aPtr ) + { + static_cast(aPtr)->SetDisableRedraw(EFalse); + } + + +/** + * Resolves the next index of the listbox according the key event. + * If key event is UP, the index is decreased from current index. + * If key event is DOWN, the index is increased from current index. + * If current index is last & event is DOWN, the new index is set to first. + * If current index is first & event is UP, the new index is set to last. + * + * @param aKeyEvent Key event. + * @param aListBox List box. + * @return Next index of the list item. + */ +TInt NextFocusIndex + ( const TKeyEvent& aKeyEvent, CEikListBox& aListBox ) + { + TInt result( KErrNotFound ); + const TInt KFirstItemIndex( 0 ); + TInt itemCount( aListBox.Model()->NumberOfItems() ); + const TInt KLastItemIndex( itemCount - 1 ); + TInt currentItemIndex( aListBox.CurrentItemIndex() ); + if ( aKeyEvent.iCode == EKeyDownArrow ) + { + result = currentItemIndex + 1; + if ( result > KLastItemIndex ) + { + // Set to first + result = KFirstItemIndex; + } + } + else if ( aKeyEvent.iCode == EKeyUpArrow ) + { + result = currentItemIndex - 1; + if ( result < KFirstItemIndex ) + { + // Set to last + result = KLastItemIndex; + } + } + else + { + result = currentItemIndex; + } + return result; + } + +} /// namespace + +// -------------------------------------------------------------------------- +// CPbk2NamesListReadyState::CPbk2NamesListReadyState +// -------------------------------------------------------------------------- +// +inline CPbk2NamesListReadyState::CPbk2NamesListReadyState( + const CCoeControl& aParent, + CPbk2ContactViewListBox& aListBox, + MPbk2FilteredViewStack& aViewStack, + CAknSearchField* aFindBox, + CPbk2ThumbnailLoader& aThumbnailLoader, + MPbk2UiControlEventSender& aEventSender, + MPbk2ContactNameFormatter& aNameFormatter, + RPointerArray& aCommandItems, + CPbk2PredictiveSearchFilter& aSearchFilter ) : + iParent( aParent ), + iListBox( aListBox ), + iViewStack( aViewStack ), + iFindBox( aFindBox ), + iThumbnailLoader( aThumbnailLoader ), + iEventSender( aEventSender ), + iNameFormatter( aNameFormatter ), + iCommandItems( aCommandItems ), + iSearchFilter(aSearchFilter) + { + } + +// -------------------------------------------------------------------------- +// CPbk2NamesListReadyState::~CPbk2NamesListReadyState +// -------------------------------------------------------------------------- +// +CPbk2NamesListReadyState::~CPbk2NamesListReadyState() + { + UnsubscribeCmdItemsVisibility(); + iListBox.SetListCommands( NULL ); + + delete iAdaptiveSearchGridFiller; + delete iFindPolicy; + delete iFindDelay; + delete iFindTextBuf; + iSelectedItems.Close(); + delete iStringArray; + delete iStringSplitter; + iIteratorIndexes.Close(); + } + +// -------------------------------------------------------------------------- +// CPbk2NamesListReadyState::NewL +// -------------------------------------------------------------------------- +// +CPbk2NamesListReadyState* CPbk2NamesListReadyState::NewLC + ( const CCoeControl* aParent, CPbk2ContactViewListBox& aListBox, + MPbk2FilteredViewStack& aViewStack, CAknSearchField* aFindBox, + CPbk2ThumbnailLoader& aThumbnailLoader, + MPbk2UiControlEventSender& aEventSender, + MPbk2ContactNameFormatter& aNameFormatter, + RPointerArray& aCommandItems, + CPbk2PredictiveSearchFilter& aSearchFilter ) + { + CPbk2NamesListReadyState* self = new (ELeave) CPbk2NamesListReadyState( + *aParent, aListBox, aViewStack, aFindBox, aThumbnailLoader, + aEventSender, aNameFormatter, aCommandItems, aSearchFilter ); + CleanupStack::PushL(self); + self->ConstructL(); + return self; + } + +// -------------------------------------------------------------------------- +// CPbk2NamesListReadyState::ConstructL +// -------------------------------------------------------------------------- +// +inline void CPbk2NamesListReadyState::ConstructL() + { + if ( iFindBox ) + { + if (!iFindBox->IsFocused() && iParent.IsFocused() ) + { + iFindBox->SetFocus(ETrue); + } + iFindBox->ResetL(); + } + + iFindDelay = CPbk2FindDelay::NewL( *this ); + + // Create contact find policy + CVPbkContactManager& manager = + Phonebook2::Pbk2AppUi()->ApplicationServices().ContactManager(); + CVPbkContactFindPolicy::TParam param = + CVPbkContactFindPolicy::TParam( + manager.FieldTypes(), + manager.FsSession() ); + iFindPolicy = CVPbkContactFindPolicy::NewL( param ); + + if( iFindBox ) + { + iFindBox->AddAdaptiveSearchTextObserverL( this ); + iAdaptiveSearchGridFiller = CPbk2AdaptiveSearchGridFiller::NewL( *iFindBox, iNameFormatter ); + } + } + +void CPbk2NamesListReadyState::UnsubscribeCmdItemsVisibility() const + { + for ( TInt i = 0; i < iCommandItems.Count(); ++i ) + { + iCommandItems[i]->SetVisibilityObserver( NULL ); + } + } + +void CPbk2NamesListReadyState::SubscribeCmdItemsVisibility() + { + for ( TInt i = 0; i < iCommandItems.Count(); ++i ) + { + iCommandItems[i]->SetVisibilityObserver( this ); + } + } + +// -------------------------------------------------------------------------- +// CPbk2NamesListReadyState::ActivateStateL +// -------------------------------------------------------------------------- +// +void CPbk2NamesListReadyState::ActivateStateL() + { + PBK2_DEBUG_PRINT(PBK2_DEBUG_STRING + ("CPbk2NamesListReadyState::ActivateStateL(0x%x)"), this ); + + AllowCommandsToShowThemselves( ETrue ); + UpdateAdaptiveSearchGridL( EFalse ); + } + +// -------------------------------------------------------------------------- +// CPbk2NamesListReadyState::DeactivateState +// -------------------------------------------------------------------------- +// +void CPbk2NamesListReadyState::DeactivateState() + { + PBK2_DEBUG_PRINT(PBK2_DEBUG_STRING + ("CPbk2NamesListReadyState::DeactivateState(0x%x)"), this ); + + AllowCommandsToShowThemselves( EFalse ); + HideThumbnail(); + // Stop creating adaptive search grid. + if (iAdaptiveSearchGridFiller) + { + if (iAdaptiveSearchGridFiller->IsActive()) + { + iAdaptiveSearchGridFiller->StopFilling(); + } + } + } + +// -------------------------------------------------------------------------- +// CPbk2NamesListReadyState::CountComponentControls +// -------------------------------------------------------------------------- +// +TInt CPbk2NamesListReadyState::CountComponentControls() const + { + TInt numberOfControls( KNumberOfControls ); + if ( !iFindBox ) + { + --numberOfControls; + } + return numberOfControls; + } + +// -------------------------------------------------------------------------- +// CPbk2NamesListReadyState::ComponentControl +// -------------------------------------------------------------------------- +// +CCoeControl* CPbk2NamesListReadyState::ComponentControl(TInt aIndex) const + { + switch (aIndex) + { + case 0: + { + return &iListBox; + } + case 1: + { + return iFindBox; + } + default: + { + // Illegal state + __ASSERT_DEBUG(EFalse, Panic(EPanicLogic_ComponentControl)); + return NULL; + } + } + } + +// -------------------------------------------------------------------------- +// CPbk2NamesListReadyState::SizeChanged +// -------------------------------------------------------------------------- +// +void CPbk2NamesListReadyState::SizeChanged() + { + const TRect rect(iParent.Rect()); + PBK2_DEBUG_PRINT(PBK2_DEBUG_STRING + ("CPbk2NamesListReadyState::SizeChanged(0x%x), rect=(%d,%d,%d,%d)"), + this, rect.iTl.iX, rect.iTl.iY, rect.iBr.iX, rect.iBr.iY); + + if ( iFindBox ) + { + AknLayoutUtils::LayoutControl(&iListBox, rect, + AKN_LAYOUT_WINDOW_list_gen_pane(1)); + + AknLayoutUtils::LayoutControl( iFindBox, rect, + AKN_LAYOUT_WINDOW_find_pane ); + if (iFindBox->IsVisible() && iListBox.IsVisible()) + { + iFindBox->SetLinePos(EABColumn); + } + } + else + { + AknLayoutUtils::LayoutControl(&iListBox, rect, + AKN_LAYOUT_WINDOW_list_gen_pane(0)); + } + } + +// -------------------------------------------------------------------------- +// CPbk2NamesListReadyState::MakeComponentsVisible +// -------------------------------------------------------------------------- +// +void CPbk2NamesListReadyState::MakeComponentsVisible(TBool aVisible) + { + PBK2_DEBUG_PRINT(PBK2_DEBUG_STRING + ("CPbk2NamesListReadyState::MakeComponentsVisible(0x%x,%d)"), + this, aVisible); + + iListBox.MakeVisible(aVisible); + + CEikScrollBar *scrollBar = iListBox.ScrollBarFrame()->GetScrollBarHandle + (CEikScrollBar::EVertical); + if ( scrollBar ) + { + scrollBar->MakeVisible(aVisible); + } + + if ( iFindBox ) + { + if ( (iFindBox->IsVisible()&&!aVisible) || (!iFindBox->IsVisible()&&aVisible) ) + { + iFindBox->MakeVisible(aVisible); + } + } + + // Have to call to make sure that scrollbar is updated when state of + // control is changing. + TRAP_IGNORE( iListBox.UpdateScrollBarsL() ); + + // Change visible state + iVisible = aVisible; + } + +// -------------------------------------------------------------------------- +// CPbk2NamesListReadyState::ActivateL +// -------------------------------------------------------------------------- +// +void CPbk2NamesListReadyState::ActivateL() + { + PBK2_DEBUG_PRINT(PBK2_DEBUG_STRING + ("CPbk2NamesListReadyState::ActivateL(0x%x)"), this ); + + if ( iFindBox ) + { + // Adjust find box cursor + CEikEdwin& findEditor = iFindBox->Editor(); + findEditor.SetCursorPosL(findEditor.TextLength(), EFalse); + } + } + +// -------------------------------------------------------------------------- +// CPbk2NamesListReadyState::Draw +// -------------------------------------------------------------------------- +// +void CPbk2NamesListReadyState::Draw + ( const TRect& aRect, CWindowGc& aGc ) const + { + PBK2_DEBUG_PRINT( PBK2_DEBUG_STRING( + "CPbk2NamesListReadyState::Draw(0x%x, TRect(%d,%d,%d,%d))" ), + this, aRect.iTl.iX, aRect.iTl.iY, aRect.iBr.iX, aRect.iBr.iY ); + + if ( !iVisible ) + { + // If control is not visible (blanked) draw a blank background + MAknsSkinInstance* skin = AknsUtils::SkinInstance(); + MAknsControlContext* cc = + AknsDrawUtils::ControlContext( &iListBox ); + + if ( !AknsDrawUtils::Background( skin, cc, &iListBox, aGc, aRect ) ) + { + // Blank background if no skin present + aGc.SetPenStyle( CGraphicsContext::ENullPen ); + aGc.SetBrushStyle( CGraphicsContext::ESolidBrush ); + aGc.DrawRect( aRect ); + } + } + } + +// -------------------------------------------------------------------------- +// CPbk2NamesListReadyState::DialogMenuBar +// -------------------------------------------------------------------------- +// +CEikMenuBar* CPbk2NamesListReadyState::DialogMenuBar(CAknAppUi* aAppUi) + { + CEikMenuBar* menuBar = NULL; + + // Check for an active dialog and fetch its menu bar + if (aAppUi->IsDisplayingMenuOrDialog()) + { + CCoeControl* ctrl = aAppUi->TopFocusedControl(); + if (ctrl) + { + CEikDialog* dialog = ctrl->MopGetObjectNoChaining(dialog); + if (dialog) + { + dialog->MopGetObject(menuBar); + } + } + } + return menuBar; + } + +// -------------------------------------------------------------------------- +// CPbk2NamesListReadyState::ViewMenuBar +// -------------------------------------------------------------------------- +// +CEikMenuBar* CPbk2NamesListReadyState::ViewMenuBar(CAknAppUi* aAppUi) + { + CEikMenuBar* menuBar = NULL; + + // Check for an active view + TVwsViewId uid; + if (aAppUi->GetActiveViewId(uid) == KErrNone) + { + if ( uid.iAppUid != uid.iViewUid ) + { + CAknView* view = + static_cast (aAppUi)->View(uid.iViewUid); + if ( view ) + { + menuBar = view->MenuBar(); + } + } + } + return menuBar; + } + +// -------------------------------------------------------------------------- +// CPbk2NamesListReadyState::MenuBar +// -------------------------------------------------------------------------- +// +CEikMenuBar* CPbk2NamesListReadyState::MenuBar(CAknAppUi* aAppUi) + { + // Try fetching a menu bar from currently displayed dialog + CEikMenuBar* menuBar = DialogMenuBar( aAppUi ); + + if ( !menuBar ) // Menu bar was not dialog based + { + // Try fetching a menu bar from an active view + menuBar = ViewMenuBar(aAppUi); + } + + if ( !menuBar ) // Menu bar was not view based + { + // Finally, try fetching a menu bar from AppUi + menuBar = CEikonEnv::Static()->AppUiFactory()->MenuBar(); + } + return menuBar; + } + +// -------------------------------------------------------------------------- +// CPbk2NamesListReadyState::OfferKeyEventL +// -------------------------------------------------------------------------- +// +TKeyResponse CPbk2NamesListReadyState::OfferKeyEventL + (const TKeyEvent& aKeyEvent, TEventCode aType) + { + // Remember current index and selection before + // listbox has handled the event. + TInt oldItemIndex( iListBox.CurrentItemIndex() ); + TBool oldItemMarkedBefore + ( iListBox.View()->ItemIsSelected( oldItemIndex ) ); + + // Remember next index based on key event (UP, DOWN) + // and selection before listbox has handled the event. + TInt newItemIndex( NextFocusIndex( aKeyEvent, iListBox ) ); + TBool newItemMarkedBefore + ( iListBox.View()->ItemIsSelected( newItemIndex ) ); + + TKeyResponse result( EKeyWasNotConsumed ); + if ( iFindBox ) + { + //If the FindBox is locked then dont offer the event to the findbox + if (!iSearchFilter.IsLocked()) + { + // use the "C" key to delete the Adaptive search character must + // change the focus to Adaptive search pane + if ( aKeyEvent.iCode == EKeyBackspace && iAdaptiveSearchGridFiller ) + { + iAdaptiveSearchGridFiller->SetFocusToAdaptiveSearchGrid(); + } + + // Offer the key event first to findbox + result = iFindBox->OfferKeyEventL( aKeyEvent, aType ); + + CPbk2PredictiveViewStack& predictiveViewStack = static_cast( iViewStack ); + + TInt contactItemIndex = newItemIndex - CommandItemCount(); + + if ( contactItemIndex >= 0 && oldItemIndex != newItemIndex && iSearchFilter.IsPredictiveActivated() && iViewStack.Level() && + !predictiveViewStack.IsNonMatchingMarkedContact( contactItemIndex ) ) + { + iSearchFilter.CommitFindPaneTextL( iViewStack, iNameFormatter, contactItemIndex ); + } + + } + else + { + //If FindPane is locked, then forward only the backspace key. + if ( aKeyEvent.iCode == EKeyBackspace ) + { + // Offer the key event first to findbox + result = iFindBox->OfferKeyEventL( aKeyEvent, aType ); + } + } + } + + // And then offer the event to listbox if necessary + if ( result == EKeyWasNotConsumed ) + { + // Use hash key to mark and unmark list item + if ( (aKeyEvent.iScanCode == EStdKeyHash) + && MenuBar( iAvkonAppUi )->ItemSpecificCommandsEnabled() ) + { + if ( aType == EEventKeyUp ) + { + if ( newItemMarkedBefore ) + { + iListBox.View()->DeselectItem( newItemIndex ); + } + else + { + iListBox.View()->SelectItemL( newItemIndex ); + } + } + result = EKeyWasConsumed; + } + else + { + result = iListBox.OfferKeyEventL( aKeyEvent, aType ); + } + } + else + { + // Find box consumed the key event, abort abort + return result; + } + + // If listbox handles the event, test if the selections have changed. + if ( result == EKeyWasConsumed ) + { + // If newItemIndex is found (it is not KErrNotFound) and + // if newItemIndex is not the same as oldItemIndex + if ( newItemIndex != KErrNotFound + && newItemIndex != oldItemIndex ) + { + // Check if the new item index has marked afterwards. + TBool newItemMarkedAfter + ( iListBox.View()->ItemIsSelected( newItemIndex ) ); + + // If new item selection has changed, send event. + if ( newItemMarkedBefore != newItemMarkedAfter ) + { + // Send event about changed state + TPbk2ControlEvent + event( TPbk2ControlEvent::EContactSelected ); + event.iInt = newItemIndex; + if ( !newItemMarkedAfter ) + { + event.iEventType = + TPbk2ControlEvent::EContactUnselected; + } + iEventSender.SendEventToObserversL( event ); + + //if commands marked, unmark it back + if ( !IsContactAtListboxIndex( newItemIndex ) && newItemMarkedAfter ) + { + UnmarkCommands(); + event.iEventType = TPbk2ControlEvent::EContactUnselected; + iEventSender.SendEventToObserversL( event ); + } + } + } + + // Check if old item's selection has changed and send event. + TBool oldItemMarkedAfter + ( iListBox.View()->ItemIsSelected( oldItemIndex ) ); + if ( oldItemMarkedBefore != oldItemMarkedAfter ) + { + // Send event about changed state + TPbk2ControlEvent + event( TPbk2ControlEvent::EContactSelected ); + event.iInt = oldItemIndex; + if ( !oldItemMarkedAfter ) + { + event.iEventType = + TPbk2ControlEvent::EContactUnselected; + } + iEventSender.SendEventToObserversL( event ); + + //if commands marked, unmark it back + if ( !IsContactAtListboxIndex( oldItemIndex ) && oldItemMarkedAfter ) + { + UnmarkCommands(); + event.iEventType = TPbk2ControlEvent::EContactUnselected; + iEventSender.SendEventToObserversL( event ); + } + } + } + + return result; + } + +// -------------------------------------------------------------------------- +// CPbk2NamesListReadyState::HandlePointerEventL +// Event sending differs from OfferKeyEventL's solution on purpose. +// -------------------------------------------------------------------------- +// +void CPbk2NamesListReadyState::HandlePointerEventL + ( const TPointerEvent& aPointerEvent ) + { + iSearchFieldPointed = EFalse; + if ( iFindBox ) + { + if ( iFindBox->Rect().Contains( aPointerEvent.iPosition ) ) + { + iFindBox->HandlePointerEventL( aPointerEvent ); + iSearchFieldPointed = ETrue; + } + } + + TInt previousItemIndex = iListBox.CurrentItemIndex(); + iListBox.HandlePointerEventL( aPointerEvent ); + + // Handle focus change when dragging + if ( previousItemIndex != iListBox.CurrentItemIndex() && + aPointerEvent.iType == TPointerEvent::EDrag ) + { + HandleFocusChangeL(); + } + + if ( !iSearchFieldPointed && FocusableItemPointed() && + aPointerEvent.iType == TPointerEvent::EButton1Up ) + { + // Send selection events based on marking + TInt focusIndex = iListBox.CurrentItemIndex(); + TInt commands = CommandItemCount(); + const TBool markedAfter = iListBox.View()->ItemIsSelected( focusIndex ); + + TPbk2ControlEvent event( TPbk2ControlEvent::EContactSelected ); + event.iInt = focusIndex; + if ( !markedAfter ) + { + event.iEventType = TPbk2ControlEvent::EContactUnselected; + } + else if ( focusIndex < commands) + { + UnmarkCommands(); + } + iEventSender.SendEventToObserversL( event ); + + } + + TInt currentIndex = iListBox.CurrentItemIndex(); + CPbk2PredictiveViewStack& predictiveViewStack = static_cast( iViewStack ); + + TInt contactItemIndex = currentIndex - CommandItemCount(); + if ( contactItemIndex >= 0 && iFindBox && iSearchFilter.IsPredictiveActivated() && iViewStack.Level() && + !predictiveViewStack.IsNonMatchingMarkedContact( contactItemIndex ) ) + { + iSearchFilter.CommitFindPaneTextL( iViewStack, iNameFormatter, contactItemIndex ); + } + + } + +// -------------------------------------------------------------------------- +// CPbk2NamesListReadyState::NamesListState +// -------------------------------------------------------------------------- +// +TInt CPbk2NamesListReadyState::NamesListState() const + { + return CPbk2NamesListControl::EStateReady; + } + +// -------------------------------------------------------------------------- +// CPbk2NamesListReadyState::HandleContactViewEventL +// -------------------------------------------------------------------------- +// +void CPbk2NamesListReadyState::HandleContactViewEventL + (TInt aEvent, TInt aIndex) + { + // need to calculate list index from contact + // view index + TInt listIndex = CommandItemCount() + aIndex; + HandleListboxEventL(aEvent, listIndex, EFalse ); + + TInt currentFocusIndex = iListBox.CurrentItemIndex(); + TBool marked = iListBox.View()->ItemIsSelected( currentFocusIndex ); + + //update findpane according to the new focused contact after delete operation. + //Do nothing if the next focused contact is marked because it would not be found. + if ( aEvent == MPbk2NamesListState::EItemRemoved + && iSearchFilter.IsPredictiveActivated() + && iViewStack.Level() + && iFindBox + && iFindBox->TextLength() != 0 + && !marked) + { + iSearchFilter.CommitFindPaneTextL( iViewStack, iNameFormatter, currentFocusIndex ); + } + } + +// -------------------------------------------------------------------------- +// CPbk2NamesListReadyState::HandleCommandEventL +// -------------------------------------------------------------------------- +// +void CPbk2NamesListReadyState::HandleCommandEventL + (TInt aEvent, TInt /* aCommandIndex*/ ) + { + HandleListboxEventL(aEvent, 0, ETrue ); + } + +// -------------------------------------------------------------------------- +// CPbk2NamesListReadyState::HandleListboxEventL +// -------------------------------------------------------------------------- +// +void CPbk2NamesListReadyState::HandleListboxEventL + (TInt aEvent, TInt aListboxIndex, TBool aMantainFocus ) + { + switch (aEvent) + { + case EItemAdded: + { + //contact added, grid might not have all necessary characters. + //this could be optimized, we could just check the added contact and + //update map if the performance is not enough + UpdateAdaptiveSearchGridL( ETrue ); + + // Inform find box and list box + UpdateFindBoxL(); + + TInt topIndex = iListBox.TopItemIndex(); + iListBox.HandleEventL(aEvent, aListboxIndex); + + // Maintain focus + // TODO: similar focus handling code in case item delete in iListBox.HandleEventL + // to consider to move this focus code there as well + if (aListboxIndex >= 0 && aListboxIndex < iListBox.NumberOfItems() ) + { + if ( aMantainFocus ) + { + //keep focused item and top item if its not 0 + if ( aListboxIndex <= iListBox.CurrentItemIndex() && + ( iListBox.CurrentItemIndex() + 1 ) < iListBox.NumberOfItems() ) + { + iListBox.SetCurrentItemIndex( + iListBox.CurrentItemIndex() + 1 ); + if ( topIndex > 0 && ( topIndex + 1 ) < iListBox.NumberOfItems() ) + { + iListBox.SetTopItemIndex( topIndex + 1 ); + } + } + } + else + { + //change focus to the added item + if ( aListboxIndex != iListBox.CurrentItemIndex() ) + { + iListBox.SetCurrentItemIndex( aListboxIndex ); + } + } + } + + iParent.DrawDeferred(); + HandleFocusChangeL(); + break; + } + case EItemRemoved: + { + //contact removed, grids might have unecessary characters + UpdateAdaptiveSearchGridL( ETrue ); + + // Inform find box and list box + UpdateFindBoxL(); + iListBox.HandleEventL(aEvent, aListboxIndex); + + // Maintain focus + if (aListboxIndex >= 0 && aListboxIndex < iListBox.NumberOfItems() ) + { + if ( aMantainFocus ) + { + //no op + } + else + { + //change focus + if ( aListboxIndex != iListBox.CurrentItemIndex() ) + { + iListBox.SetCurrentItemIndex( aListboxIndex ); + } + } + } + + iParent.DrawDeferred(); + HandleFocusChangeL(); + break; + } + case EContactViewUpdated: + { + UpdateAdaptiveSearchGridL( ETrue ); + break; + } + default: + { + // Do nothing + break; + } + } + } + +// -------------------------------------------------------------------------- +// CPbk2NamesListReadyState::CoeControl +// -------------------------------------------------------------------------- +// +CCoeControl& CPbk2NamesListReadyState::CoeControl() + { + CCoeControl* tmp = NULL; + return *static_cast(tmp); + } + +// -------------------------------------------------------------------------- +// CPbk2NamesListReadyState::HandleControlEventL +// -------------------------------------------------------------------------- +// +void CPbk2NamesListReadyState::HandleControlEventL( CCoeControl* aControl, + MCoeControlObserver::TCoeEvent aEventType, TInt aParam ) + { + if ( aEventType == MCoeControlObserver::EEventStateChanged ) + { + // Find box + if ( aControl == iFindBox ) + { + if( aParam ) + { + //means the search came from adaptive search grid + if( iAdaptiveSearchGridFiller ) + { + iAdaptiveSearchGridFiller->InvalidateAdaptiveSearchGrid(); + } + } + + if ( iFindDelay->IsActive() ) + { + iFindDelay->Cancel(); + } + //if aParam is ETrue, it means that event came from adaptive search, which means + //we do not want to delay filtering + if ( ( !aParam ) && + ( iFindDelay ) && + ( NumberOfContacts() >= KFindDelayThresholdContacts ) ) + { + iFindDelay->After( TTimeIntervalMicroSeconds32( KFindDelayTime ) ); + } + else + { + UpdateFindResultL(); + } + } + // List + else if ( aControl == &iListBox ) + { + HandleFocusChangeL(); + } + } + } + +// -------------------------------------------------------------------------- +// CPbk2NamesListReadyState::TopContactL +// -------------------------------------------------------------------------- +// +const MVPbkViewContact* CPbk2NamesListReadyState::TopContactL() + { + const MVPbkViewContact* contact = NULL; + + // There is an offset between listbox indexes and view indexes. + const TInt topListboxIndex = iListBox.TopItemIndex(); + const TInt enabledCommandCount = CommandItemCount(); + // Check whether the index is valid. Also check whether the top + // really is a contact. + if ( topListboxIndex >= 0 && topListboxIndex >= enabledCommandCount ) + { + // Map from listbox index to view index + contact = &iViewStack.ContactAtL( + topListboxIndex - enabledCommandCount ); + } + return contact; + } + +// -------------------------------------------------------------------------- +// CPbk2NamesListReadyState::ParentControl +// -------------------------------------------------------------------------- +// +MPbk2ContactUiControl* CPbk2NamesListReadyState::ParentControl() const + { + // Names list control does not have a parent control + return NULL; + } + +// -------------------------------------------------------------------------- +// CPbk2NamesListReadyState::NumberOfContacts +// -------------------------------------------------------------------------- +// +TInt CPbk2NamesListReadyState::NumberOfContacts() const + { + // The listbox can also have command items. + TInt result = iListBox.NumberOfItems() - CommandItemCount(); + if ( result < 0 ) + { + result = 0; // No contacts + } + return result; + } + +// -------------------------------------------------------------------------- +// CPbk2NamesListReadyState::FocusedContactL +// -------------------------------------------------------------------------- +// +const MVPbkBaseContact* CPbk2NamesListReadyState::FocusedContactL() const + { + return FocusedViewContactL(); + } + +// -------------------------------------------------------------------------- +// CPbk2NamesListReadyState::FocusedViewContactL +// -------------------------------------------------------------------------- +// +const MVPbkViewContact* CPbk2NamesListReadyState::FocusedViewContactL() const + { + const MVPbkViewContact* contact = NULL; + + // There is an offset between listbox indexes and view indexes. + const TInt focusListboxIndex = iListBox.CurrentItemIndex(); + const TInt enabledCommandCount = CommandItemCount(); + // Is the focus on a contact. Check... + if (focusListboxIndex >= 0 && focusListboxIndex >= enabledCommandCount ) + { + // Yes, the focus is on a contact. + // Map from listbox index to view index + contact = &iViewStack.ContactAtL( + focusListboxIndex - enabledCommandCount ); + } + return contact; + } + +// -------------------------------------------------------------------------- +// CPbk2NamesListReadyState::FocusedStoreContact +// -------------------------------------------------------------------------- +// +const MVPbkStoreContact* CPbk2NamesListReadyState::FocusedStoreContact() const + { + return NULL; + } + +// -------------------------------------------------------------------------- +// CPbk2NamesListReadyState::SetFocusedContactL +// -------------------------------------------------------------------------- +// +void CPbk2NamesListReadyState::SetFocusedContactL + ( const MVPbkBaseContact& aContact ) + { + SetFocusedContactL( KErrNotSupported, &aContact ); + } + +// -------------------------------------------------------------------------- +// CPbk2NamesListReadyState::SetFocusedContactL +// -------------------------------------------------------------------------- +// +void CPbk2NamesListReadyState::SetFocusedContactL + ( const MVPbkContactBookmark& aContactBookmark ) + { + TInt viewIndex = iViewStack.IndexOfBookmarkL( aContactBookmark ); + SetFocusedContactL( viewIndex, NULL ); + } + +// -------------------------------------------------------------------------- +// CPbk2NamesListReadyState::SetFocusedContactL +// -------------------------------------------------------------------------- +// +void CPbk2NamesListReadyState::SetFocusedContactL + ( const MVPbkContactLink& aContactLink ) + { + TInt viewIndex = iViewStack.IndexOfLinkL( aContactLink ); + SetFocusedContactL( viewIndex, NULL ); + } + +// -------------------------------------------------------------------------- +// CPbk2NamesListReadyState::FocusedContactIndex +// -------------------------------------------------------------------------- +// +TInt CPbk2NamesListReadyState::FocusedContactIndex() const + { + // The result is a view index. There is an offset between listbox indexes + // and view indexes. + + TInt viewIndex = KErrNotFound; + const TInt currentListboxIndex = iListBox.CurrentItemIndex(); + const TInt commandCount = CommandItemCount(); + // Is the focus on a contact or on a command item? Check: + if ( currentListboxIndex >= commandCount ) + { + // Yes, the focus is on a contact. + // Need to map from listbox indexes to view indexes. + viewIndex = currentListboxIndex - commandCount; + } + return viewIndex; + } + +// -------------------------------------------------------------------------- +// CPbk2NamesListReadyState::SetFocusedContactIndex +// -------------------------------------------------------------------------- +// +void CPbk2NamesListReadyState::SetFocusedContactIndexL( TInt aIndex ) + { + // The aIndex is a view index. There is an offset between listbox indexes + // and view indexes. + + if ( aIndex < 0 ) + { + aIndex = 0; + } + const TInt enabledCommandCount = CommandItemCount(); + if ( aIndex > iListBox.BottomItemIndex() - enabledCommandCount ) + { + aIndex = iListBox.BottomItemIndex() - enabledCommandCount; + } + + SetFocusedContactL( aIndex, NULL ); + } + +// -------------------------------------------------------------------------- +// CPbk2NamesListReadyState::NumberOfContactFields +// -------------------------------------------------------------------------- +// +TInt CPbk2NamesListReadyState::NumberOfContactFields() const + { + return KErrNotSupported; + } + +// -------------------------------------------------------------------------- +// CPbk2NamesListReadyState::FocusedField +// -------------------------------------------------------------------------- +// +const MVPbkBaseContactField* CPbk2NamesListReadyState::FocusedField() const + { + // There is no field level focus + return NULL; + } + +// -------------------------------------------------------------------------- +// CPbk2NamesListReadyState::FocusedFieldIndex +// -------------------------------------------------------------------------- +// +TInt CPbk2NamesListReadyState::FocusedFieldIndex() const + { + // There is no field level focus + return KErrNotFound; + } + +// -------------------------------------------------------------------------- +// CPbk2NamesListReadyState::SetFocusedFieldIndex +// -------------------------------------------------------------------------- +// +void CPbk2NamesListReadyState::SetFocusedFieldIndex( TInt /*aIndex*/ ) + { + // Do nothing + } + +// -------------------------------------------------------------------------- +// CPbk2NamesListReadyState::ContactsMarked +// -------------------------------------------------------------------------- +// +TBool CPbk2NamesListReadyState::ContactsMarked() const + { + return iListBox.ContactsMarked(); + } + +// -------------------------------------------------------------------------- +// CPbk2NamesListReadyState::SelectedContactsL +// -------------------------------------------------------------------------- +// +MVPbkContactLinkArray* + CPbk2NamesListReadyState::SelectedContactsL() const + { + // Get listbox selection indexes, a reference only + const CListBoxView::CSelectionIndexArray* selArray = + iListBox.SelectionIndexes(); + + + TInt count = 1; // initialize to one, because if there are + // no selections we operate with one focused contact + if (selArray) + { + count = selArray->Count(); + } + + CVPbkContactLinkArray* linkArray = NULL; + + if (count > 0) + { + linkArray = CVPbkContactLinkArray::NewLC(); + + // Loop through the selections and construct a link for + // each of the contacts + const TInt commandItemCount = CommandItemCount(); + for (TInt i=0; iAt(i); + if ( IsContactAtListboxIndex( singleSelection ) ) + { + // Take the view contact from the view, the ownership + // stays at the view + const MVPbkViewContact* contact = + &iViewStack.ContactAtL( singleSelection - commandItemCount ); + MVPbkContactLink* link = contact->CreateLinkLC(); + if (link) + { + linkArray->AppendL(link); + CleanupStack::Pop(); // the array takes ownership of the link + } + } + } + + CleanupStack::Pop(linkArray); + } + + return linkArray; + } + +// -------------------------------------------------------------------------- +// CPbk2NamesListReadyState::SelectedContactsOrFocusedContactL +// -------------------------------------------------------------------------- +// +MVPbkContactLinkArray* + CPbk2NamesListReadyState::SelectedContactsOrFocusedContactL() const + { + MVPbkContactLinkArray* result = NULL; + result = SelectedContactsL(); + + if ( !result ) + { + CVPbkContactLinkArray* array = CVPbkContactLinkArray::NewLC(); + const MVPbkBaseContact* focusedContact = FocusedContactL(); + if ( focusedContact ) + { + MVPbkContactLink* link = focusedContact->CreateLinkLC(); + CleanupStack::Pop(); // link + array->AppendL( link ); + } + else + { + // there was no focused contact, check if this is the my card + AppendMyCardLinkIfExistL( *array ); + } + CleanupStack::Pop(); // array + result = array; + } + + return result; + } + +// -------------------------------------------------------------------------- +// CPbk2NamesListReadyState::AppendMyCardLinkIfExistL +// -------------------------------------------------------------------------- +// +void CPbk2NamesListReadyState::AppendMyCardLinkIfExistL( CVPbkContactLinkArray& aArray ) const + { + TInt currentItem = iListBox.CurrentItemIndex(); + // if focused index is command item + if( currentItem < CommandItemCount() ) + { + // check if the command is my card ( this search is copied from CommandItemAt - function to avoid const cast) + // Some of the commands might be disabled. Skip those. + TInt enabledCount = 0; + TInt indexOfResult = KErrNotFound; + for ( TInt n = 0; n < iCommandItems.Count() && indexOfResult == KErrNotFound; ++n ) + { + if ( iCommandItems[ n ]->IsEnabled() ) + { + enabledCount++; + if ( enabledCount-1 == currentItem ) + { + indexOfResult = n; + } + } + } + MPbk2UiControlCmdItem* item = iCommandItems[ indexOfResult ]; + // check if the command item was a my card + if( item->CommandId() == EPbk2CmdOpenMyCard ) + { + // get extension point and my card link + TAny* object = item->ControlCmdItemExtension( TUid::Uid( KPbk2ControlCmdItemExtensionUID ) ); + if( object ) + { + MPbk2DoubleListboxCmdItemExtension* extension = + static_cast( object ); + // if extension exists + if( extension ) + { + const MVPbkContactLink* link = extension->Link(); + // if link exists, add it to the array + if( link ) + { + aArray.AppendL( link->CloneLC() ); + CleanupStack::Pop(); + } + } + } + } + } + } + + +// -------------------------------------------------------------------------- +// CPbk2NamesListReadyState::SelectedContactsIteratorL +// -------------------------------------------------------------------------- +// +MPbk2ContactLinkIterator* + CPbk2NamesListReadyState::SelectedContactsIteratorL() const + { + // Get listbox selection indexes, a reference only + const CListBoxView::CSelectionIndexArray* selArray = + iListBox.SelectionIndexes(); + + TInt count = 0; + if ( selArray ) + { + count = selArray->Count(); + } + + MPbk2ContactLinkIterator* iterator = NULL; + + if ( count > 0 ) + { + // Need to map the listbox indexes to view indexes. + // Also need to filter out cmd items. + iIteratorIndexes.Reset(); + const TInt commandItemCount = CommandItemCount(); + const TInt selectionCount = selArray->Count(); + for ( TInt n = 0; n < selectionCount; ++n ) + { + const TInt listboxIndex = selArray->At( n ); + if ( listboxIndex >= commandItemCount) + { + // It is a contact. + // Do a mapping from listbox index to view index + iIteratorIndexes.AppendL( listboxIndex - commandItemCount ); + } + } + iterator = CPbk2ContactViewIterator::NewLC + ( iViewStack, iIteratorIndexes.Array() ); + CleanupStack::Pop(); // iterator + } + + return iterator; + } + +// -------------------------------------------------------------------------- +// CPbk2NamesListReadyState::SelectedContactStoresL +// -------------------------------------------------------------------------- +// +CArrayPtr* + CPbk2NamesListReadyState::SelectedContactStoresL() const + { + // This is not a state of the contact store control + return NULL; + } + +// -------------------------------------------------------------------------- +// CPbk2NamesListReadyState::ClearMarks +// -------------------------------------------------------------------------- +// +void CPbk2NamesListReadyState::ClearMarks() + { + iListBox.View()->ClearSelection(); + } + +// -------------------------------------------------------------------------- +// CPbk2NamesListReadyState::SetSelectedContactL +// -------------------------------------------------------------------------- +// +void CPbk2NamesListReadyState::SetSelectedContactL + ( TInt aIndex, TBool aSelected ) + { + if ( aSelected ) + { + iListBox.View()->SelectItemL( aIndex ); + } + else + { + iListBox.View()->DeselectItem( aIndex ); + } + } + +// -------------------------------------------------------------------------- +// CPbk2NamesListReadyState::SetSelectedContactL +// -------------------------------------------------------------------------- +// +void CPbk2NamesListReadyState::SetSelectedContactL( + const MVPbkContactBookmark& aContactBookmark, + TBool aSelected ) + { + TInt cmdItemCount = CommandItemCount(); + TInt index = iViewStack.IndexOfBookmarkL( aContactBookmark ); + if ( index != KErrNotFound ) + { + SetSelectedContactL( cmdItemCount+index, aSelected ); + } + } + +// -------------------------------------------------------------------------- +// CPbk2NamesListReadyState::SetSelectedContactL +// -------------------------------------------------------------------------- +// +void CPbk2NamesListReadyState::SetSelectedContactL( + const MVPbkContactLink& aContactLink, + TBool aSelected ) + { + TInt cmdItemCount = CommandItemCount(); + TInt index = iViewStack.IndexOfLinkL( aContactLink ); + if ( index != KErrNotFound ) + { + SetSelectedContactL( index+cmdItemCount, aSelected ); + } + } + + +TInt CPbk2NamesListReadyState::CommandItemCount() const + { + // Some of the commands might be disabled. Don't count those. + TInt enabledCommandCount = 0; + for ( TInt n = 0; n < iCommandItems.Count(); ++n ) + { + if ( iCommandItems[ n ]->IsEnabled() ) + { + enabledCommandCount++; + } + } + return enabledCommandCount; + } + +const MPbk2UiControlCmdItem& +CPbk2NamesListReadyState::CommandItemAt( TInt aIndex ) const + { + // Some of the commands might be disabled. Skip those. + TInt enabledCount = 0; + TInt indexOfResult = KErrNotFound; + + for ( TInt n = 0; n < iCommandItems.Count()&& indexOfResult == KErrNotFound; ++n ) + { + if ( iCommandItems[ n ]->IsEnabled() ) + { + enabledCount++; + if ( enabledCount-1 == aIndex ) + { + indexOfResult = n; + } + } + } + + return *iCommandItems[ indexOfResult ]; + } + +const MPbk2UiControlCmdItem* +CPbk2NamesListReadyState::FocusedCommandItem() const + { + const MPbk2UiControlCmdItem* cmdItem = NULL; + // Is the focus on a command item: + TInt focusListIndex = iListBox.CurrentItemIndex(); + const TInt commandItemCount = CommandItemCount(); + if ( focusListIndex != KErrNotFound && focusListIndex < commandItemCount ) + { + // Yes it's a command item. + cmdItem = &CommandItemAt(focusListIndex); + } + return cmdItem; + } + +void CPbk2NamesListReadyState::DeleteCommandItemL( TInt /*aIndex*/ ) + { + // ownership & management of iCommandItems is wasted in names list + // control. Do nothing here + } + +void CPbk2NamesListReadyState::AddCommandItemL(MPbk2UiControlCmdItem* /*aCommand*/, TInt /*aIndex*/) + { + // ownership & management of iCommandItems is wasted in names list + // control. Do nothing here + } + +// -------------------------------------------------------------------------- +// CPbk2NamesListReadyState::DynInitMenuPaneL +// -------------------------------------------------------------------------- +// +void CPbk2NamesListReadyState::DynInitMenuPaneL( + TInt aResourceId, CEikMenuPane* aMenuPane) const + { + TInt commandItemCount = CommandItemCount(); + + // Stores the position of the searched menu item. + // This position is not needed or used anywhere + TInt pos; + + if ((iListBox.SelectionIndexes()->Count() + commandItemCount ) + == iListBox.Model()->NumberOfItems()) + { + if (aMenuPane->MenuItemExists( EAknCmdMarkingModeEnter, pos ) ) + { + aMenuPane->SetItemDimmed( EAknCmdMarkingModeEnter, ETrue ); + } + } + + } + +// -------------------------------------------------------------------------- +// CPbk2NamesListReadyState::ProcessCommandL +// -------------------------------------------------------------------------- +// +void CPbk2NamesListReadyState::ProcessCommandL + (TInt aCommandId) const + { + AknSelectionService::HandleMarkableListProcessCommandL + (aCommandId, &iListBox); + + // Send event + TPbk2ControlEvent event( TPbk2ControlEvent::EContactSelected ); + event.iInt = iListBox.CurrentItemIndex(); + + switch( aCommandId ) + { + case EAknCmdMark: + case EAknMarkAll: + { + // Send event about changed state + iEventSender.SendEventToObserversL( event ); + // commands should stay unmarked + UnmarkCommands(); + break; + } + + case EAknCmdUnmark: + { + event.iEventType = TPbk2ControlEvent::EContactUnselected; + iEventSender.SendEventToObserversL( event ); + break; + } + + case EAknUnmarkAll: + { + // Send event about changed state + event.iEventType = TPbk2ControlEvent::EContactUnselectedAll; + iEventSender.SendEventToObserversL( event ); + break; + } + + default:; + } + } + +// -------------------------------------------------------------------------- +// CPbk2NamesListReadyState::UpdateAfterCommandExecution +// -------------------------------------------------------------------------- +// +void CPbk2NamesListReadyState::UpdateAfterCommandExecution() + { + // Do nothing + } + +// -------------------------------------------------------------------------- +// CPbk2NamesListReadyState::GetMenuFilteringFlagsL +// -------------------------------------------------------------------------- +// +TInt CPbk2NamesListReadyState::GetMenuFilteringFlagsL() const + { + TInt ret = KPbk2ListContainsItems; + if (ContactsMarked()) + { + ret |= KPbk2ListContainsMarkedItems; + } + else + { + ret |= KPbk2ListContainsNoMarkedItems; + } + return ret; + } + +// -------------------------------------------------------------------------- +// CPbk2NamesListReadyState::ControlStateL +// -------------------------------------------------------------------------- +// +CPbk2ViewState* CPbk2NamesListReadyState::ControlStateL() const + { + // State objects do not handle control state changes + return NULL; + } + +// -------------------------------------------------------------------------- +// CPbk2NamesListReadyState::SetFocusedContactL +// -------------------------------------------------------------------------- +// +void CPbk2NamesListReadyState::SetFocusedContactL( TInt aIndex, + const MVPbkBaseContact* aContact ) + { + // The aIndex is a view index. There is an offset between listbox indexes + // and view indexes. + + TInt viewIndex = KErrNotReady; + + if ( aContact ) + { + MVPbkContactBookmark* bookmark = aContact->CreateBookmarkLC(); + TInt contactIndex = iViewStack.IndexOfBookmarkL( *bookmark ); + CleanupStack::PopAndDestroy(); // bookmark + + if ( contactIndex >= 0 && + contactIndex < iViewStack.ContactCountL() ) + { + viewIndex = contactIndex; + } + } + + if ( viewIndex == KErrNotReady ) + { + if ( aIndex >= 0 && + aIndex < iViewStack.ContactCountL() ) + { + viewIndex = aIndex; + } + } + + // Need to map current listbox index to view indexes. + // But at the same time check whether the current item is a contact. + const TInt enabledCommandCount = CommandItemCount(); + TInt currentContactAsViewIndex = KErrNotReady; + if ( iListBox.CurrentItemIndex() >= enabledCommandCount ) + { + // Yes, the current item is a contact. + currentContactAsViewIndex = + iListBox.CurrentItemIndex() - enabledCommandCount; + } + + // If index is valid, and not already the current one, then use it to set + // the current item. + if ( viewIndex != KErrNotReady && viewIndex != currentContactAsViewIndex ) + { + iListBox.SetCurrentItemIndex( viewIndex + enabledCommandCount ); + // Force hiding of thumbnail from previously focused contact + HideThumbnail(); + HandleFocusChangeL(); + } + + // Should be drawn always to be sure that UI is updated + iParent.DrawDeferred(); + } + +// -------------------------------------------------------------------------- +// CPbk2NamesListReadyState::RestoreControlStateL +// -------------------------------------------------------------------------- +// +void CPbk2NamesListReadyState::RestoreControlStateL + (CPbk2ViewState* aState) + { + TBool redraw = EFalse; + if (aState->Flags() & CPbk2ViewState::EInitialized) + { + iListBox.Reset(); + redraw = ETrue; + } + else + { + if (iViewStack.ContactCountL() > 0) + { + if (aState->Flags() & CPbk2ViewState::EFocusFirst) + { + iListBox.SetCurrentItemIndex(0); + } + else if (aState->Flags() & CPbk2ViewState::EFocusLast) + { + iListBox.SetCurrentItemIndex(iListBox.Model()->NumberOfItems()-1); + } + else + { + // Restore top contact + const MVPbkContactLink* topContact = aState->TopContact(); + if (topContact) + { + const TInt viewIndex = iViewStack.IndexOfLinkL(*topContact); + if (viewIndex >= 0) + { + const TInt prevListboxIndex = iListBox.TopItemIndex(); + // There is an offset between listbox indexes + // and view indexes. + const TInt listboxIndex = viewIndex + CommandItemCount(); + iListBox.SetTopItemIndex(listboxIndex); + iListBox.FixTopItemIndex(); + if (listboxIndex != prevListboxIndex) + { + redraw = ETrue; + } + } + } + + const MVPbkContactLink* focusedContact = aState->FocusedContact(); + if (focusedContact) + { + const TInt viewIndex = + iViewStack.IndexOfLinkL(*focusedContact); + if (viewIndex >= 0) + { + const TInt prevListboxIndex = iListBox.CurrentItemIndex(); + // There is an offset between listbox indexes + // and view indexes. + const TInt listboxIndex = viewIndex + CommandItemCount(); + iListBox.SetCurrentItemIndex(listboxIndex); + if (listboxIndex != prevListboxIndex) + { + redraw = ETrue; + } + } + } + } + // Restore selections + const MVPbkContactLinkArray* markedContacts = + aState->MarkedContacts(); + if (RestoreMarkedContactsL(markedContacts)) + { + redraw = ETrue; + } + } + } + if (redraw) + { + iParent.DrawDeferred(); + iListBox.UpdateScrollBarsL(); + HandleFocusChangeL(); + } + } + +// -------------------------------------------------------------------------- +// CPbk2NamesListReadyState::FindTextL +// -------------------------------------------------------------------------- +// +const TDesC& CPbk2NamesListReadyState::FindTextL() + { + if ( iFindBox ) + { + TPbk2FindTextUtil::EnsureFindTextBufSizeL( + *iFindBox, + &iFindTextBuf ); + TPtr bufPtr = iFindTextBuf->Des(); + iFindBox->GetSearchText(bufPtr); + return *iFindTextBuf; + } + + return KNullDesC; + } + + +// -------------------------------------------------------------------------- +// CPbk2NamesListReadyState::ResetFindL +// -------------------------------------------------------------------------- +// +void CPbk2NamesListReadyState::ResetFindL() + { + if ( iFindBox && iFindBox->TextLength() > 0 ) + { + iSearchFilter.ResetL(); + iFindBox->ResetL(); + iViewStack.Reset(); + iFindBox->DrawDeferred(); + } + } + +// -------------------------------------------------------------------------- +// CPbk2NamesListReadyState::HideThumbnail +// -------------------------------------------------------------------------- +// +void CPbk2NamesListReadyState::HideThumbnail() + { + } + +// -------------------------------------------------------------------------- +// CPbk2NamesListReadyState::ShowThumbnail +// -------------------------------------------------------------------------- +// +void CPbk2NamesListReadyState::ShowThumbnail() + { + } + +// -------------------------------------------------------------------------- +// CPbk2NamesListReadyState::SetBlank +// -------------------------------------------------------------------------- +// +void CPbk2NamesListReadyState::SetBlank(TBool aBlank) + { + if (!aBlank) + { + // Redraw + iParent.DrawDeferred(); + TRAPD( error, + iListBox.UpdateScrollBarsL(); + HandleFocusChangeL(); + ); + if ( error != KErrNone ) + { + CCoeEnv::Static()->HandleError( error ); + } + } + } + +// -------------------------------------------------------------------------- +// CPbk2NamesListReadyState::RegisterCommand +// -------------------------------------------------------------------------- +// +void CPbk2NamesListReadyState::RegisterCommand( + MPbk2Command* /*aCommand*/ ) + { + // Do nothing + } + +// -------------------------------------------------------------------------- +// CPbk2NamesListReadyState::SetTextL +// -------------------------------------------------------------------------- +// +void CPbk2NamesListReadyState::SetTextL( const TDesC& aText ) + { + iListBox.View()->SetListEmptyTextL( aText ); + } + +// -------------------------------------------------------------------------- +// CPbk2NamesListReadyState::ContactUiControlExtension +// -------------------------------------------------------------------------- +// +TAny* CPbk2NamesListReadyState::ContactUiControlExtension(TUid aExtensionUid ) + { + if( aExtensionUid == KMPbk2ContactUiControlExtension2Uid ) + { + return static_cast( this ); + } + + return NULL; + } + +// -------------------------------------------------------------------------- +// CPbk2NamesListReadyState::FocusedItemPointed +// -------------------------------------------------------------------------- +// +TBool CPbk2NamesListReadyState::FocusedItemPointed() + { + return iListBox.FocusedItemPointed(); + } + +// -------------------------------------------------------------------------- +// CPbk2NamesListReadyState::FocusableItemPointed +// -------------------------------------------------------------------------- +// +TBool CPbk2NamesListReadyState::FocusableItemPointed() + { + return iListBox.FocusableItemPointed(); + } + +// -------------------------------------------------------------------------- +// CPbk2NamesListReadyState::SearchFieldPointed +// -------------------------------------------------------------------------- +// +TBool CPbk2NamesListReadyState::SearchFieldPointed() + { + return iSearchFieldPointed; + } + +// -------------------------------------------------------------------------- +// CPbk2NamesListReadyState::TopViewChangedL +// +// This is called when top view is changed. However this happens before .e.g +// the view containing top contacts is ready and therefore in this point of +// execution we don't know whether there will be e.g. "Add to favorites" +// command item visible or not +// -------------------------------------------------------------------------- +// +void CPbk2NamesListReadyState::TopViewChangedL( + MVPbkContactViewBase& aOldView ) + { + PBK2_DEBUG_PRINT(PBK2_DEBUG_STRING + ("CPbk2NamesListReadyState::TopViewChangedL begin") ); + + // Switch view + TInt countBefore = aOldView.ContactCountL(); + TInt countAfter = iViewStack.ContactCountL(); + + PBK2_DEBUG_PRINT(PBK2_DEBUG_STRING + ("CPbk2NamesListReadyState::TopViewChangedL:before=%d,now=%d"), + countBefore, countAfter ); + + // Markings must be checked before HandleItemAdditionL or + // HandleItemRemovalL because they reset markings + TBool marked = ContactsMarked(); + + // Handle list box changes + // Promotion item "Add to favourites" should not be visible if top view is + // not base view (iViewStack.Level() !== 0). Remote search may be shown when there + // is text entered in find box. MyCard enabled similarly as add favorites. + TBool addFavoOk = iViewStack.Level() == 0 && !(iFindBox && iFindBox->TextLength()); + UpdateCommandEnabled( EPbk2CmdAddFavourites, addFavoOk ); + UpdateCommandEnabled( EPbk2CmdRcl, !addFavoOk ); + UpdateCommandEnabled( EPbk2CmdOpenMyCard, addFavoOk ); + + if ( countAfter > countBefore ) //count does not contain command items + { + iListBox.HandleItemAdditionL(); + } + if ( countAfter < countBefore ) + { + iListBox.HandleItemRemovalL(); + } + + UpdateAdaptiveSearchGridL( EFalse ); + + if ( marked ) + { + // update markings to the new view + RestoreMarkedItemsL( iSelectedItems ); + } + + if ( iSearchFilter.IsPredictiveActivated() ) + { + TInt indexOfMatchedItem = iSearchFilter.CommitFindPaneTextL( iViewStack, iNameFormatter ); + if ( indexOfMatchedItem == KErrNotFound ) + { + indexOfMatchedItem = 0; + } + iListBox.SetCurrentItemIndexAndDraw(indexOfMatchedItem); + } + else + { + SetCurrentItemIndexAndDrawL(); + } + + HandleFocusChangeL(); + + PBK2_DEBUG_PRINT(PBK2_DEBUG_STRING + ("CPbk2NamesListReadyState::TopViewChangedL end") ); + } + +// -------------------------------------------------------------------------- +// CPbk2NamesListReadyState::TopViewUpdatedL +// -------------------------------------------------------------------------- +// +void CPbk2NamesListReadyState::TopViewUpdatedL() + { + PBK2_DEBUG_PRINT(PBK2_DEBUG_STRING + ("CPbk2NamesListReadyState::TopViewUpdatedL begin") ); + + // Promotion item "Add to favourites" should not be visible if top view is + // not base view (iViewStack.Level() !== 0). Remote search may be shown when there + // is text entered in find box. MyCard enabled similarly as add favorites. + TBool addFavoOk = iViewStack.Level() == 0 && !(iFindBox && iFindBox->TextLength()); + + UpdateCommandEnabled( EPbk2CmdAddFavourites, addFavoOk ); + UpdateCommandEnabled( EPbk2CmdRcl, !addFavoOk ); + UpdateCommandEnabled( EPbk2CmdOpenMyCard, addFavoOk ); + UpdateAdaptiveSearchGridL( ETrue ); + + if ( ContactsMarked() ) + { + // The view didn't change so we have to restore the items that + // were saved last time the find box was updated. + RestoreMarkedItemsL( iSelectedItems ); + SetCurrentItemIndexAndDrawL(); + } + HandleFocusChangeL(); + } + +// -------------------------------------------------------------------------- +// CPbk2NamesListReadyState::BaseViewChangedL +// -------------------------------------------------------------------------- +// +void CPbk2NamesListReadyState::BaseViewChangedL() + { + HandleFocusChangeL(); + } + +// -------------------------------------------------------------------------- +// CPbk2NamesListReadyState::ViewStackError +// -------------------------------------------------------------------------- +// +void CPbk2NamesListReadyState::ViewStackError( TInt /*aError*/ ) + { + // CPbk2NameListControl is listening to view stack errors and handles + // them. This is UI control's internal design and the state can + // ignore the error + } + +// -------------------------------------------------------------------------- +// CPbk2NamesListReadyState::ContactAddedToBaseView +// -------------------------------------------------------------------------- +// +void CPbk2NamesListReadyState::ContactAddedToBaseView( + MVPbkContactViewBase& /*aBaseView*/, TInt /*aIndex*/, + const MVPbkContactLink& /*aContactLink*/ ) + { + // CPbk2NameListControl handles this. + } + +// -------------------------------------------------------------------------- +// CPbk2NamesListReadyState::FindDelayComplete +// -------------------------------------------------------------------------- +// +void CPbk2NamesListReadyState::FindDelayComplete() + { + TRAPD( error, UpdateFindResultL() ); + if ( error != KErrNone ) + { + CCoeEnv::Static()->HandleError( error ); + iViewStack.Reset(); + } + } + +// -------------------------------------------------------------------------- +// CPbk2NamesListReadyState::AdaptiveSearchTextChanged +// -------------------------------------------------------------------------- +// +void CPbk2NamesListReadyState::AdaptiveSearchTextChanged( CAknSearchField* aSearchField ) + { + //Add this line to call CPbk2AdaptiveSearchGridFiller::InvalidateAdaptiveSearchGrid() + //to control GRID must be updated always after user has pressed a key, even if the keymap does not changed + HandleControlEventL( aSearchField, MCoeControlObserver::EEventStateChanged, ETrue ); + + //this callback method is only used to notice when language has changed and + //to update adaptive search grid. + + if( aSearchField->LanguageChanged() ) + { + UpdateAdaptiveSearchGridL( ETrue ); + } + } + +// -------------------------------------------------------------------------- +// CPbk2NamesListReadyState::CmdItemVisibilityChanged +// -------------------------------------------------------------------------- +// +void CPbk2NamesListReadyState::CmdItemVisibilityChanged( TInt aCmdItemId, TBool aVisible ) + { + TInt cmdItemIndex = FindCommand(aCmdItemId); + TInt cmdListBoxIndex = EnabledCommandCount(); + if( aVisible ) + { + cmdListBoxIndex--; + } + // Update the HiddenSelection property of the command items. + TListItemProperties prop( iListBox.ItemDrawer()->Properties(cmdListBoxIndex) ); + prop.SetHiddenSelection(aVisible); + + TRAP_IGNORE( + iListBox.ItemDrawer()->SetPropertiesL(cmdListBoxIndex, prop); + + HandleCommandEventL( + (aVisible ? EItemAdded : EItemRemoved), + cmdItemIndex); + ); + } + +// -------------------------------------------------------------------------- +// CPbk2NamesListReadyState::RestoreMarkedContactsL +// Marks specified contacts in the listbox. +// +// @param aMarkedContacts Contacts to mark. +// @return True if any contacts were marked in the list. +// -------------------------------------------------------------------------- +// +TBool CPbk2NamesListReadyState::RestoreMarkedContactsL + (const MVPbkContactLinkArray* aMarkedContacts) + { + TBool result = EFalse; + DisableRedrawEnablePushL(); + iListBox.ClearSelection(); + if (aMarkedContacts) + { + const TInt count = aMarkedContacts->Count(); + for (TInt i=0; i < count; ++i) + { + const MVPbkContactLink& contact = aMarkedContacts->At(i); + const TInt viewIndex = iViewStack.IndexOfLinkL(contact); + if (viewIndex >= 0) + { + const TInt listboxIndex = viewIndex + CommandItemCount(); + iListBox.View()->SelectItemL(listboxIndex); + result = ETrue; + } + } + } + CleanupStack::PopAndDestroy(); // DisableRedrawEnablePushL + return result; + } + +// -------------------------------------------------------------------------- +// CPbk2NamesListReadyState::RestoreMarkedItemsL +// -------------------------------------------------------------------------- +// +void CPbk2NamesListReadyState::RestoreMarkedItemsL( + const MVPbkContactBookmarkCollection& aSelectedItems ) + { + PBK2_DEBUG_PRINT(PBK2_DEBUG_STRING + ("CPbk2NamesListReadyState::RestoreMarkedItemsL: %d items"), + aSelectedItems.Count() ); + + DisableRedrawEnablePushL(); + iListBox.ClearSelection(); + const TInt count = aSelectedItems.Count(); + for ( TInt i = 0; i < count; ++i ) + { + TInt index = iViewStack.IndexOfBookmarkL( aSelectedItems.At( i ) ) + CommandItemCount(); + if ( index >= 0 ) + { + iListBox.View()->SelectItemL( index ); + } + } + CleanupStack::PopAndDestroy(); // DisableRedrawEnablePushL + } + +// -------------------------------------------------------------------------- +// CPbk2NamesListReadyState::DisableRedrawEnablePushL +// -------------------------------------------------------------------------- +// +void CPbk2NamesListReadyState::DisableRedrawEnablePushL() + { + CListBoxView& listBoxView = *iListBox.View(); + listBoxView.SetDisableRedraw(ETrue); + CleanupStack::PushL(TCleanupEnableListBoxViewRedraw(listBoxView)); + } + +// -------------------------------------------------------------------------- +// CPbk2NamesListReadyState::HandleFocusChangeL +// -------------------------------------------------------------------------- +// +void CPbk2NamesListReadyState::HandleFocusChangeL() + { + iEventSender.SendEventToObserversL( + TPbk2ControlEvent::TPbk2ControlEvent::EControlFocusChanged ); + } + +// -------------------------------------------------------------------------- +// CPbk2NamesListReadyState::UpdateFindResultL +// -------------------------------------------------------------------------- +// +void CPbk2NamesListReadyState::UpdateFindResultL() + { + TBuf findPaneTxt( FindTextL() ); + + if ( iSearchFilter.StartFindPaneInlineEditL( findPaneTxt ) ) + { + TBool selectionChanged = HasSelectedItemsChangedL(); + + MVPbkContactBookmarkCollection* marked = NULL; + if ( ContactsMarked() ) + { + marked = &SelectedItemsL( iViewStack ); + } + else + { + // User has removed all the marks so update also bookmarks. + iSelectedItems.RemoveAndDeleteAll(); + } + + // Extract the find text into array + if ( !iStringSplitter ) + { + iStringSplitter = CPbk2FindStringSplitter::NewL( iNameFormatter ); + } + MDesCArray* temp = iStringSplitter->SplitTextIntoArrayL( findPaneTxt ); + delete iStringArray; + iStringArray = temp; + + iViewStack.UpdateFilterL( *iStringArray, marked, selectionChanged ); + + UpdateAdaptiveSearchGridL( EFalse ); + } + } + +// -------------------------------------------------------------------------- +// CPbk2NamesListReadyState::UpdateFindBoxL +// -------------------------------------------------------------------------- +// +void CPbk2NamesListReadyState::UpdateFindBoxL() + { + if ( iFindBox ) + { + if ( iViewStack.ContactCountL() > 0 && iParent.IsFocused() ) + { + iFindBox->SetFocusing( ETrue ); + // If findbox is focusing, SetFocus would clear some flag of Fep, + // and it will cause 'b','c',''e',...could not be entered for the + // first character by V-ITUT. + if ( !iFindBox->IsFocused() ) + { + iFindBox->SetFocus( ETrue, EDrawNow ); + } + } + } + } + +// -------------------------------------------------------------------------- +// CPbk2NamesListReadyState::SelectedItemsL +// -------------------------------------------------------------------------- +// +MVPbkContactBookmarkCollection& CPbk2NamesListReadyState::SelectedItemsL( + MVPbkContactViewBase& aCurrentView ) + { + // Get listbox selection indexes, a reference only + const CListBoxView::CSelectionIndexArray* selArray = + iListBox.SelectionIndexes(); + + if ( selArray ) + { + iSelectedItems.RemoveAndDeleteAll(); + const TInt count = selArray->Count(); + for ( TInt i = 0; i < count; ++i ) + { + + iSelectedItems.AppendL( + aCurrentView.CreateBookmarkLC( selArray->At(i) - CommandItemCount() ) ); + CleanupStack::Pop(); + } + } + + PBK2_DEBUG_PRINT(PBK2_DEBUG_STRING + ("CPbk2NamesListReadyState::SelectedItemsL:%d marked"), + iSelectedItems.Count() ); + + return iSelectedItems; + } + +// -------------------------------------------------------------------------- +// CPbk2NamesListReadyState::HasSelectedItemsChangedL +// -------------------------------------------------------------------------- +// +TBool CPbk2NamesListReadyState::HasSelectedItemsChangedL() + { + TBool result = EFalse; + + // Get listbox selection indexes, a reference only + const CListBoxView::CSelectionIndexArray* selArray = + iListBox.SelectionIndexes(); + + if ( selArray ) + { + TInt bookmarkCount = iSelectedItems.Count(); + TInt markedCount = selArray->Count(); + // Changed if number of items are different + result = bookmarkCount != markedCount; + if ( !result ) + { + // There are equeal amount of items. Compare as long + // as the difference is found + for ( TInt i = 0; i < bookmarkCount && !result; ++i ) + { + result = selArray->At(i) != + iViewStack.IndexOfBookmarkL( iSelectedItems.At(i) ); + } + } + } + else if ( iSelectedItems.Count() > 0 ) + { + result = ETrue; + } + + PBK2_DEBUG_PRINT(PBK2_DEBUG_STRING + ("CPbk2NamesListReadyState::HasSelectedItemsChangedL: %d "), + result ); + + return result; + } + +// -------------------------------------------------------------------------- +// CPbk2NamesListReadyState::SetCurrentItemIndexAndDrawL +// -------------------------------------------------------------------------- +// +void CPbk2NamesListReadyState::SetCurrentItemIndexAndDrawL() + { + __ASSERT_DEBUG( &iListBox && iFindPolicy, + Panic(EPanicLogic_PreConds_SetCurrentItemIndexAndDraw) ); + + if ( iStringArray && iStringArray->MdcaCount() > 0 ) + { + TBool isCurrentItemSet( EFalse ); + const TInt count( iViewStack.ContactCountL() ); + for ( TInt i(0); i < count; ++i ) + { + const MVPbkViewContact& contact = iViewStack.ContactAtL( i ); + if ( iFindPolicy->MatchContactNameL( *iStringArray, contact ) ) + { + isCurrentItemSet = ETrue; + iListBox.SetCurrentItemIndexAndDraw(i); + break; + } + } + if ( !isCurrentItemSet ) + { + iListBox.SetCurrentItemIndexAndDraw(0); + } + } + } + +void CPbk2NamesListReadyState::UpdateAdaptiveSearchGridL( TBool aClearCache ) + { + if( ( !iAdaptiveSearchGridFiller ) || ( !iFindBox ) ) + { + return; + } + + CAknSearchField::TSearchFieldStyle searchStyle = iFindBox->SearchFieldStyle(); + + if ( searchStyle != CAknSearchField::EAdaptiveSearch ) + { + delete iAdaptiveSearchGridFiller; + iAdaptiveSearchGridFiller = NULL; + return; + } + + iAdaptiveSearchGridFiller->StartFillingL( iViewStack, FindTextL(), aClearCache ); + } + +/** + * Tells whether the listbox line contains a contact or not. + * Does not check that the aListboxIndex is within range of listbox. + * @param aListboxIndex The position in the listbox to be checked. + */ +TBool CPbk2NamesListReadyState::IsContactAtListboxIndex( TInt aListboxIndex ) const + { + // There can be command items at the top of the list. + // The command items are not contacts. + const TInt enabledCommandCount = CommandItemCount(); + return aListboxIndex >= enabledCommandCount; + } + +void CPbk2NamesListReadyState::AllowCommandsToShowThemselves( TBool aVisible ) + { + if ( aVisible ) + { + // ownership not transferred + iListBox.SetListCommands( &iCommandItems ); + SubscribeCmdItemsVisibility(); + UpdateCommandEnabled( EPbk2CmdAddFavourites, ETrue ); //By default add favorites may be shown + UpdateCommandEnabled( EPbk2CmdOpenMyCard, ETrue ); + } + else + { + UpdateCommandEnabled( EPbk2CmdRcl, EFalse ); + UpdateCommandEnabled( EPbk2CmdAddFavourites, EFalse ); + UpdateCommandEnabled( EPbk2CmdOpenMyCard, EFalse ); + UnsubscribeCmdItemsVisibility(); + iListBox.SetListCommands( NULL ); + } + } + +void CPbk2NamesListReadyState::UpdateCommandEnabled( TInt aCommandId, TBool aEnabled ) + { + for ( TInt i = 0; i < iCommandItems.Count(); i++ ) + { + if ( iCommandItems[i]->CommandId() == aCommandId ) + { + iCommandItems[i]->SetEnabled( aEnabled ); + break; + } + } + } + +TBool CPbk2NamesListReadyState::IsCommandEnabled(TInt aCommandId) const + { + TBool res = EFalse; + for ( TInt i = 0; i < iCommandItems.Count(); i++ ) + { + if ( iCommandItems[i]->CommandId() == aCommandId ) + { + res = iCommandItems[i]->IsEnabled(); + break; + } + } + return res; + } + +// +// Search for a command in iCommandItems and returns its index +// +TInt CPbk2NamesListReadyState::FindCommand(TInt aCommandId) const + { + TInt result = KErrNotFound; + for ( TInt i = 0; i < iCommandItems.Count(); ++i ) + { + if ( iCommandItems[i]->CommandId() == aCommandId ) + { + result = i; + break; + } + + } + return result; + } + +TInt CPbk2NamesListReadyState::CalculateListboxIndex(TInt aCommandIndex) const + { + //TInt num = 0; + TInt num(KErrNotFound); + for ( TInt i = 0; i <= aCommandIndex; ++i ) + { + if(iCommandItems[i]->IsEnabled()) + { + ++num; + } + } + return num; + } + + +void CPbk2NamesListReadyState::UnmarkCommands() const + { + for ( TInt i = 0; i < CommandItemCount(); i++ ) + { + iListBox.View()->DeselectItem( i ); + } + } + +TInt CPbk2NamesListReadyState::EnabledCommandCount() const + { + TInt result = 0; + for ( TInt i = 0; i < iCommandItems.Count(); ++i ) + { + if(iCommandItems[i]->IsEnabled()) + { + result++; + } + } + return result; + } + +// End of File