fep/aknfep/UiPlugins/AknFepUiInterface/AvkonImpl/src/AknFepAvkonCandidatePopup.cpp
changeset 40 2cb9bae34d17
parent 31 f1bdd6b078d1
child 49 37f5d84451bd
equal deleted inserted replaced
31:f1bdd6b078d1 40:2cb9bae34d17
     1 /*
       
     2 * Copyright (c) 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:             Avkon implementation of non-focusing popup menu to show word candidates.
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 
       
    20 
       
    21 
       
    22 
       
    23 
       
    24 
       
    25 
       
    26 
       
    27 
       
    28 
       
    29 
       
    30 #include <eikenv.h>
       
    31 #include <eikappui.h>
       
    32 #include <badesca.h>
       
    33 #include <coemain.h>
       
    34 #include <aknPopupHeadingPane.h>
       
    35 #include <aknsfld.h>
       
    36 #include <AknsFrameBackgroundControlContext.h>
       
    37 #include <aknlists.h>
       
    38 #include <aknmessagequerycontrol.h> 
       
    39 #include <skinlayout.cdl.h>
       
    40 #include <AknLayout2ScalableDef.h>
       
    41 #include <aknlayoutscalable_avkon.cdl.h>
       
    42 #include <layoutmetadata.cdl.h>
       
    43 #include <aknlayoutscalable_apps.cdl.h>
       
    44 #include <AknFepInternalCRKeys.h>
       
    45 #include <AvkonInternalCRKeys.h>
       
    46 
       
    47 #include <aknfep.rsg>
       
    48 #include <AknFepGlobalEnums.h>
       
    49 #include <avkon.hrh>
       
    50 #include "AknFepAvkonCandidatePopup.h"
       
    51 #include "AknPriv.hrh"
       
    52 const TInt KChrKeyTimeout = 250000;
       
    53 const TInt KChrKeyRepeatDelay = 1000000;
       
    54 
       
    55 const TInt KScreenWidthQHDLandscape = 640;
       
    56 const TInt KScreenHeightQHDLandscape = 360;
       
    57 const TInt KOffsetWidthForCandidatePopup = 32;
       
    58 
       
    59 /**
       
    60 * Creates the pop-up list
       
    61 *
       
    62 */
       
    63 CAknFepAvkonCandidatePopup* CAknFepAvkonCandidatePopup::NewL( MAknFepCandidatePopupCallback& aOwner )
       
    64     {
       
    65     CAknFepAvkonCandidatePopup* self = new(ELeave)CAknFepAvkonCandidatePopup( aOwner );        
       
    66     CleanupStack::PushL(self);
       
    67     self->ConstructL();
       
    68     CleanupStack::Pop(self);
       
    69     return self;
       
    70     }
       
    71 
       
    72 
       
    73 /**
       
    74 * C++ constructor
       
    75 *
       
    76 * @param    aOwner  The owner of the popup list. Provides the candidates and receives notification
       
    77 *                   when candidate selected.
       
    78 *
       
    79 */
       
    80 CAknFepAvkonCandidatePopup::CAknFepAvkonCandidatePopup( MAknFepCandidatePopupCallback& aOwner )
       
    81     : CAknPopupList()
       
    82     , iOwner(aOwner)
       
    83     , iKeyboard(EPtiKeyboardNone)
       
    84     {
       
    85         
       
    86     }
       
    87     
       
    88     
       
    89 /**
       
    90 * 2nd phase construction
       
    91 *
       
    92 */
       
    93 void CAknFepAvkonCandidatePopup::ConstructL()
       
    94     {
       
    95     // Construct the inner listbox and the base class
       
    96    	iList = new( ELeave ) CAknSinglePopupMenuStyleListBox;
       
    97    	TInt primaryCandidate = 0;
       
    98     
       
    99     CRepository* aknFepRepository = NULL;
       
   100     aknFepRepository = CRepository::NewL(KCRUidAknFep);
       
   101     if(aknFepRepository)
       
   102     	{
       
   103        	aknFepRepository->Get(KAknFepPrimaryCandidateFlag, primaryCandidate);
       
   104         delete aknFepRepository;
       
   105         }
       
   106     
       
   107     TInt keyboardLayout = 0;
       
   108     RProperty::Get(KCRUidAvkon, KAknKeyBoardLayout, keyboardLayout);
       
   109     TPtiKeyboardType layout = (TPtiKeyboardType)keyboardLayout;
       
   110     
       
   111 	// Not use embedded CBA, so new the CBA seperately
       
   112     TInt cbaResource = 0;
       
   113     if(primaryCandidate && layout != EPtiKeyboard12Key  )
       
   114     	{
       
   115     	CAknPopupList::ConstructL( iList,R_AKNFEP_SOFTKEYS_OK_CANCEL_SELECT,
       
   116     						   AknPopupLayouts::EMenuWindow );
       
   117 		cbaResource = R_AKNFEP_SOFTKEYS_OK_CANCEL_SELECT;
       
   118     	}
       
   119     else
       
   120     	{
       
   121     	CAknPopupList::ConstructL( iList, R_AKNFEP_SOFTKEYS_SPELL_CANCEL_SELECT,
       
   122     						   AknPopupLayouts::EMenuWindow );  
       
   123 	    cbaResource = R_AKNFEP_SOFTKEYS_SPELL_CANCEL_SELECT;
       
   124     	}
       
   125 	// To add new CBA, here set its flag as the base class, 
       
   126 	// but just not set Embedded flag.
       
   127 	TUint flags = CEikButtonGroupContainer::EAddToStack;
       
   128     if ( AknLayoutUtils::PenEnabled() )
       
   129         {
       
   130         flags |= CEikButtonGroupContainer::EDelayActivation;
       
   131         }
       
   132 	// Destroy the CBA constructed in base class, and new its own CBA
       
   133     delete iPopoutCba;
       
   134     iPopoutCba =  CEikButtonGroupContainer::NewL(
       
   135             CEikButtonGroupContainer::ECba,
       
   136             CEikButtonGroupContainer::EHorizontal,
       
   137             this, cbaResource, *this, flags );	
       
   138 
       
   139 	iList->ConstructL( this, CEikListBox::ELeftDownInViewRect );
       
   140     iList->CreateScrollBarFrameL( ETrue );
       
   141     iList->ScrollBarFrame()->SetScrollBarVisibilityL( CEikScrollBarFrame::EOff,      //< horizontal
       
   142                                                       CEikScrollBarFrame::EAuto );   //< vertical
       
   143     iList->SetNonFocusing();
       
   144 
       
   145 
       
   146     // Construct the item array
       
   147     iCandidates = new (ELeave) CDesCArrayFlat( KPredictiveListCandidateMax ); 
       
   148     CTextListBoxModel* model = iList->Model();
       
   149     model->SetItemTextArray( iCandidates );
       
   150     model->SetOwnershipType( ELbmDoesNotOwnItemArray );
       
   151     iChrKeypressMonitor = CPeriodic::NewL(CActive::EPriorityStandard);
       
   152     SetNonFocusing();
       
   153     MakeVisible(EFalse); 
       
   154     }
       
   155     
       
   156 
       
   157 MAknFepCandidatePopup::~MAknFepCandidatePopup()
       
   158 {
       
   159 	
       
   160 }
       
   161 
       
   162 /**
       
   163 * Destructor
       
   164 *
       
   165 */
       
   166 CAknFepAvkonCandidatePopup::~CAknFepAvkonCandidatePopup()
       
   167     {
       
   168     delete iList;
       
   169     delete iCandidates;
       
   170     if( iChrKeypressMonitor )
       
   171         {
       
   172         iChrKeypressMonitor->Cancel();
       
   173         delete iChrKeypressMonitor;
       
   174         iChrKeypressMonitor = NULL;
       
   175         }
       
   176     }
       
   177  
       
   178 
       
   179 TPtrC CAknFepAvkonCandidatePopup::ActiveWord() const
       
   180     {
       
   181     if ( iCandidates->Count()>*iSelectedIdx && *iSelectedIdx>0 )
       
   182         {
       
   183         return (*iCandidates)[*iSelectedIdx];    
       
   184         }
       
   185     else
       
   186         {
       
   187         return TPtrC( KNullDesC );
       
   188         }
       
   189     }
       
   190     
       
   191     
       
   192 TPtrC CAknFepAvkonCandidatePopup::ExactWord() const
       
   193     {
       
   194     if ( iCandidates->Count() > 0 )
       
   195         {
       
   196         return (*iCandidates)[0];        
       
   197         }
       
   198     else
       
   199         {
       
   200         return TPtrC( KNullDesC );
       
   201         }
       
   202     }
       
   203  
       
   204  
       
   205 /**
       
   206 * Makes the pop-up selection list visible.
       
   207 *
       
   208 * @param        aInlineEditorRect   Tells the place of the inline editor. If possible, the popup is opened
       
   209 *                                   so that it does not hide the inline editor.
       
   210 *
       
   211 * @param        aSelectedIdx        Input/output argument for the selected index. If legal index is given in,
       
   212 *                                   it will be used as default selection. Otherwise the default selection will
       
   213 *                                   be the currently active word. On succesful exit this variable contains
       
   214 *                                   the index selected by the user.
       
   215 *
       
   216 * @param        aLastKeyEvent       The last key event received by the popup. On return this is the event
       
   217 *                                   which closed the popup.
       
   218 *               
       
   219 * @return       The command id used to close the window. EAknFepSoftkeySpell, EAknSoftkeyCancel, or EAknSoftkeySelect
       
   220 */
       
   221 TInt CAknFepAvkonCandidatePopup::ExecutePopupL( const TRect& aInlineEditorRect, TInt& aSelectedIdx,
       
   222 												TKeyEvent& aLastKeyEvent, TBool aRightToLeftLanguage,
       
   223 												TInt aKeyboard )
       
   224     {
       
   225     iSelectedIdx = &aSelectedIdx;
       
   226     iLastKeyEvent = &aLastKeyEvent;
       
   227     iKeyboard = (TPtiKeyboardType)aKeyboard;
       
   228     //This is the inline text rectangle, this is needed in the event of a layout change
       
   229     iInlineTextRect = aInlineEditorRect;
       
   230     
       
   231     TInt requestedSelection = *iSelectedIdx;
       
   232     iOwner.GetCandidatesL( *iCandidates, *iSelectedIdx );
       
   233     if ( requestedSelection >= 0 && requestedSelection < iCandidates->Count() )
       
   234         {
       
   235         *iSelectedIdx = requestedSelection;
       
   236         }
       
   237     
       
   238     iListBox->SetCurrentItemIndex( *iSelectedIdx );
       
   239     
       
   240     iRightToLeftCandidate = aRightToLeftLanguage;
       
   241     
       
   242     const TSize screenSize = iAvkonAppUi->ApplicationRect().Size(); //TSize(AKN_LAYOUT_WINDOW_screen.iW,AKN_LAYOUT_WINDOW_screen.iH);
       
   243     iPopoutCba->SetBoundingRect(TRect(screenSize));
       
   244 
       
   245     SetupWindowLayout(iWindowType);
       
   246     SetupWindowLocation( aInlineEditorRect );
       
   247 
       
   248     iListBox->SetListBoxObserver(this);        
       
   249 
       
   250     iEikonEnv->RemoveFromStack(this);
       
   251     iEikonEnv->EikAppUi()->AddToStackL(this,ECoeStackPriorityDialog/*ECoeStackPriorityFep*/);
       
   252 
       
   253 
       
   254     ActivateL();
       
   255     // this is required here to make code like
       
   256     // iList->SetCurrentItemIndex( last item of the list );
       
   257     // iPopupList->ExecuteLD();
       
   258     // to work as it used to. Without this current item of the
       
   259     // list would be topmost item, and there would be unused empty
       
   260     // space below that.
       
   261     iListBox->UpdateScrollBarsL();
       
   262 
       
   263     // The main rule is to make the first index (the exact match) visible. However, the active index should never
       
   264     // be hidden.
       
   265     iListBox->ScrollToMakeItemVisible( 0 );
       
   266     if ( iListBox->BottomItemIndex() < *iSelectedIdx )
       
   267         {
       
   268         iListBox->ScrollToMakeItemVisible( *iSelectedIdx );
       
   269         }
       
   270         
       
   271     // Ensure that the popup is on top. Without this the popup window is left in the background at least
       
   272     // in the dialogs of the Phonebook application.
       
   273     //Window().SetOrdinalPosition(0);
       
   274     //iPopoutCba->SetContainerWindowL( Window() ); this didn't help
       
   275         
       
   276     // Make the popup visible
       
   277     iPopoutCba->MakeVisible(ETrue);
       
   278     iListBox->MakeVisible(ETrue);    
       
   279     MakeVisible(ETrue);
       
   280     SetFocus(ETrue);
       
   281     FadeBehindPopup(EFalse);
       
   282     TInt returnValue;
       
   283     iReturn = &returnValue;
       
   284     iLastCommandId = EAknSoftkeySelect;
       
   285     iWait.Start();
       
   286     return returnValue;
       
   287     }
       
   288 
       
   289 
       
   290 /**
       
   291 * Called when the popup is closed. Unlike the base class, this class does not commit suicide on this situation.
       
   292 *
       
   293 * @return        ETrue if the popup was accepted. EFalse if the popup was cancelled
       
   294 */
       
   295 void CAknFepAvkonCandidatePopup::AttemptExitL(TBool aAccept)
       
   296     {
       
   297     *iSelectedIdx = iList->CurrentItemIndex();
       
   298 
       
   299     if (iCoeEnv && iEikonEnv)
       
   300         {
       
   301         iEikonEnv->RemoveFromStack(this);
       
   302         }
       
   303       
       
   304     SetFocus(EFalse);
       
   305     MakeVisible(EFalse);
       
   306     ListBox()->MakeVisible(EFalse);    
       
   307     iPopoutCba->MakeVisible(EFalse);
       
   308 
       
   309     if (iReturn) //Always not null unless ExecutePopupL leaves
       
   310         {
       
   311         if (!aAccept)
       
   312             {
       
   313             *iReturn = EAknSoftkeyCancel;
       
   314             }
       
   315         else
       
   316             {
       
   317             *iReturn = iLastCommandId;                        
       
   318             }
       
   319         }
       
   320 	if(iWait.IsStarted())
       
   321     iWait.AsyncStop();
       
   322     }
       
   323 
       
   324 
       
   325 void CAknFepAvkonCandidatePopup::HandleResourceChange(TInt aType)
       
   326     {
       
   327     CAknPopupList::HandleResourceChange(aType);
       
   328     //When there is a dynamic layout change, the candidate list position needs to be aligned with
       
   329     //the new position of the inline text.
       
   330     if(aType == KEikDynamicLayoutVariantSwitch)
       
   331         {
       
   332         // Move back candidate popup control priority.
       
   333         iEikonEnv->RemoveFromStack(this);        
       
   334         TRAP_IGNORE( iEikonEnv->EikAppUi()->AddToStackL(this, ECoeStackPriorityDialog )) ;       
       
   335         // Get candidate update position based on layout.
       
   336         TRAP_IGNORE(iOwner.GetUpdateCandidatePositionL(iInlineTextRect));
       
   337 
       
   338 	// Ensure that the popup is on top.
       
   339 	Window().SetOrdinalPosition(0); 
       
   340  
       
   341         SetupWindowLocation( iInlineTextRect);
       
   342         DrawNow();
       
   343         }
       
   344     else if(aType == KAknMessageFocusLost)
       
   345     	FadeBehindPopup(ETrue);
       
   346  
       
   347     }
       
   348 
       
   349 
       
   350 void CAknFepAvkonCandidatePopup::UnFocus()
       
   351     {
       
   352     //Remove the candidate list from the control stack so that it does not receive any key event.
       
   353     if (iCoeEnv && iEikonEnv)
       
   354         {
       
   355         iEikonEnv->RemoveFromStack(this);
       
   356         }
       
   357     //Un-Focus the candidate list
       
   358     SetFocus(EFalse);
       
   359     }
       
   360 void CAknFepAvkonCandidatePopup::ShowAtNewPosition(TRect aRect)
       
   361     {
       
   362     if (iCoeEnv && iEikonEnv)
       
   363         {
       
   364         TRAP_IGNORE( iEikonEnv->EikAppUi()->AddToStackL(this,ECoeStackPriorityDialog/*ECoeStackPriorityFep*/ ));
       
   365         }
       
   366     SetFocus(ETrue);
       
   367     iInlineTextRect = aRect;
       
   368     SetupWindowLocation( iInlineTextRect);
       
   369     DrawNow();
       
   370     }
       
   371 
       
   372 void CAknFepAvkonCandidatePopup::SetFocusAddStackReducePriorityL()
       
   373     {
       
   374     if (iCoeEnv && iEikonEnv)
       
   375         {
       
   376         iEikonEnv->EikAppUi()->AddToStackL(this, ECoeStackPriorityDefault-1/*ECoeStackPriorityDialog-1*/ );
       
   377         }
       
   378     SetFocus(ETrue);
       
   379     }
       
   380 
       
   381 TInt CAknFepAvkonCandidatePopup::HandleChrKeyMonitorCallback(TAny* aParam)
       
   382     {
       
   383     // the timer will be cancelled only when the key up event is received
       
   384     // the down arrow key event is simulated now
       
   385     TKeyEvent keyEvent;
       
   386     keyEvent.iCode = EKeyDownArrow;	
       
   387 //    TEventCode type = EEventKey;
       
   388     TRAP_IGNORE( ((CAknFepAvkonCandidatePopup*)aParam)->ListBox()->OfferKeyEventL(keyEvent, EEventKey) );
       
   389     // Prevent the screen saver
       
   390     User::ResetInactivityTime();
       
   391     return 1;
       
   392     }
       
   393 
       
   394 /**
       
   395 * Modified from CAknPopupList::OfferKeyEventL().
       
   396 */
       
   397 TKeyResponse CAknFepAvkonCandidatePopup::OfferKeyEventL(const TKeyEvent& aKeyEvent, 
       
   398 														TEventCode aType)
       
   399     {
       
   400     *iLastKeyEvent = aKeyEvent;
       
   401     
       
   402     // Selection key is substituted with the space key. Thus, selecting a candidate with the selection
       
   403     // key auto-appends space character.
       
   404     if ( aKeyEvent.iScanCode == EStdKeyDevice3 )
       
   405         {
       
   406         //iLastKeyEvent->iScanCode = EStdKeySpace;
       
   407         iLastKeyEvent->iCode = EKeyOK;
       
   408         }
       
   409     // Asterisk is substituted with arrow down key to get same functionality in ITU-T keypads
       
   410     // Emulator sends key event with scancode EStdKeyNkpAsterisk and hardware an event
       
   411     // with code '*' so we check for both
       
   412     else if ( ( (aKeyEvent.iScanCode == EStdKeyNkpAsterisk || aKeyEvent.iCode == '*' ) 
       
   413             && iKeyboard == EPtiKeyboard12Key ) )
       
   414         {
       
   415         iLastKeyEvent->iCode = EKeyDownArrow;
       
   416         }
       
   417     else if( aKeyEvent.iScanCode == EStdKeyLeftFunc
       
   418             && iKeyboard == EPtiKeyboardHalfQwerty  ) 
       
   419     	{
       
   420     	if( aType == EEventKeyDown)
       
   421     		{
       
   422     		iLastKeyEvent->iCode = EKeyDownArrow;	
       
   423     		// start the timer
       
   424     		if(iChrKeypressMonitor->IsActive())
       
   425     		    {
       
   426     		    iChrKeypressMonitor->Cancel();
       
   427     		    }
       
   428             iChrKeypressMonitor->Start( KChrKeyRepeatDelay, KChrKeyTimeout, 
       
   429                 TCallBack(HandleChrKeyMonitorCallback, this));
       
   430 
       
   431     		aType = EEventKey;
       
   432     		}    	
       
   433     	else
       
   434     		{
       
   435     		iChrKeypressMonitor->Cancel();
       
   436     		return EKeyWasNotConsumed;
       
   437     		}
       
   438     	}
       
   439     // this must be first check, since window will be faded when fast
       
   440     // swap window is visible
       
   441     if (aType==EEventKey && aKeyEvent.iCode == EKeyEscape)
       
   442         {
       
   443         AttemptExitL(EFalse);
       
   444         return EKeyWasConsumed;
       
   445         }
       
   446 
       
   447     if ( Window().IsFaded() )
       
   448         {
       
   449         // this happens, when popuplist has a findbox, and user
       
   450         // presses shift to launch fep menu. Fep menu has priority menu
       
   451         // in control stack, but we have dialog priority. As result,
       
   452         // keyevents will get here first. If we return
       
   453         // EKeyWasNotConsumed, fep menu will catch those events
       
   454         // next.
       
   455         return EKeyWasNotConsumed;
       
   456         }
       
   457 
       
   458     TBool needRefresh = EFalse;
       
   459     TKeyResponse res = AknFind::HandleFindOfferKeyEventL(aKeyEvent, aType, this,
       
   460     													 ListBox(), FindBox(), EFalse, needRefresh);
       
   461 
       
   462     if (needRefresh && FindBox())
       
   463         {
       
   464         DrawNow();
       
   465         }
       
   466 
       
   467     if ( res == EKeyWasConsumed )
       
   468         {
       
   469         return res;
       
   470         }
       
   471  
       
   472     if (aType==EEventKey)
       
   473         {
       
   474         // Handle arrow keys based on iScancode
       
   475         TBool keyEventHandled = EFalse;
       
   476         switch (iLastKeyEvent->iScanCode)
       
   477             {
       
   478             case EStdKeyUpArrow: //fall through
       
   479             case EStdKeyDownArrow:
       
   480             			keyEventHandled = ETrue;
       
   481                  return iListBox->OfferKeyEventL(*iLastKeyEvent, aType);
       
   482                  
       
   483             case EStdKeyLeftArrow:
       
   484                     if(iRightToLeftCandidate)
       
   485                         // These keys confirm the selection and are then handled by AknFepManager
       
   486                         AttemptExitL(ETrue);
       
   487                     else
       
   488                         // These keys cancel the selection and are then handled by AknFepManager
       
   489                         AttemptExitL(EFalse);
       
   490                     keyEventHandled = ETrue;
       
   491                     return EKeyWasConsumed;
       
   492                 
       
   493             case EStdKeyRightArrow:  
       
   494                     if(iRightToLeftCandidate)
       
   495                             // These keys cancel the selection and are then handled by AknFepManager
       
   496                             AttemptExitL(EFalse);
       
   497                         else
       
   498                             // These keys confirm the selection and are then handled by AknFepManager
       
   499                             AttemptExitL(ETrue);
       
   500                			keyEventHandled = ETrue;
       
   501                     return EKeyWasConsumed;
       
   502 
       
   503             }
       
   504         if (!keyEventHandled)
       
   505         	{
       
   506         // Handle through iCode
       
   507 	        switch (iLastKeyEvent->iCode)
       
   508 	            {
       
   509 	
       
   510 	            case EKeyUpArrow: //fall through
       
   511 	            case EKeyDownArrow:
       
   512 	                 return iListBox->OfferKeyEventL(*iLastKeyEvent, aType);
       
   513 	                 
       
   514 	            case EKeyLeftArrow:
       
   515 	                    if(iRightToLeftCandidate)
       
   516 	                        // These keys confirm the selection and are then handled by AknFepManager
       
   517 	                        AttemptExitL(ETrue);
       
   518 	                    else
       
   519 	                        // These keys cancel the selection and are then handled by AknFepManager
       
   520 	                        AttemptExitL(EFalse);
       
   521 	                    return EKeyWasConsumed;
       
   522 	                
       
   523 	            case EKeyRightArrow:  
       
   524 	                    if(iRightToLeftCandidate)
       
   525 	                            // These keys cancel the selection and are then handled by AknFepManager
       
   526 	                            AttemptExitL(EFalse);
       
   527 	                        else
       
   528 	                            // These keys confirm the selection and are then handled by AknFepManager
       
   529 	                            AttemptExitL(ETrue);
       
   530 	                    
       
   531 	                        return EKeyWasConsumed;
       
   532 	
       
   533 	            
       
   534 	            case EKeyEnter:
       
   535 	            case EKeyOK:
       
   536 	            case EKeySpace:
       
   537 	            case EKeyTab:
       
   538 	            default:
       
   539 	                // These keys confirm the selection and are then handled by AknFepManager
       
   540 	                AttemptExitL(ETrue);
       
   541 	                return EKeyWasConsumed;                
       
   542 							case	EKeyApplication:
       
   543 							case	EKeyPhoneEnd:
       
   544 							// Flip open close event.
       
   545 				      case EKeyFlipOpen:
       
   546 				      case EKeyFlipClose:            
       
   547 									AttemptExitL(EFalse);
       
   548 				            		return EKeyWasNotConsumed;
       
   549 	   
       
   550 	            }
       
   551           }              
       
   552         }
       
   553         
       
   554      // For Layout switching
       
   555      // If user switch the layout, means QWERTY to ITU-T and vice versa
       
   556      // Keyboard layout going to cahnge, So, not need to open the candidate
       
   557      // list as it is, becz its may predict differnt list of word.
       
   558         if (aKeyEvent.iScanCode == EStdKeyApplicationE ||
       
   559             aKeyEvent.iScanCode ==  EStdKeyApplication10 ||
       
   560         	aKeyEvent.iScanCode ==   EStdKeyDeviceF ||
       
   561     		aKeyEvent.iScanCode ==   EStdKeyDeviceA ||
       
   562         	aKeyEvent.iScanCode ==   EStdKeyApplication12 ||
       
   563         	aKeyEvent.iScanCode ==   EStdKeyApplication15 ||
       
   564         	aKeyEvent.iScanCode ==   EStdKeyApplication16 ||
       
   565         	aKeyEvent.iScanCode ==   EStdKeyDeviceB)
       
   566 	        {
       
   567 	        AttemptExitL(EFalse);
       
   568 	        return EKeyWasConsumed;
       
   569 	        }
       
   570  
       
   571     return EKeyWasNotConsumed;
       
   572     }
       
   573 
       
   574 
       
   575 /**
       
   576 * Process commands from CBA buttons.
       
   577 * @param  aCommandId  The command to handle.
       
   578 */
       
   579 void CAknFepAvkonCandidatePopup::ProcessCommandL(TInt aCommandId)
       
   580     {
       
   581     iLastCommandId = aCommandId;
       
   582     if (aCommandId==EAknFepSoftkeySpell 
       
   583     || aCommandId == EAknSoftkeyOk)
       
   584        {
       
   585         AttemptExitL(ETrue);
       
   586         }
       
   587     else
       
   588         {
       
   589         CAknPopupList::ProcessCommandL(aCommandId);
       
   590         }
       
   591     }
       
   592 
       
   593 
       
   594 /**
       
   595 * Calculates the position for the popup window and places it there
       
   596 * @param    aInlineEditorRect   The placement of the inline editor is used as reference.
       
   597 *                               The inline editor is not hidden if possible.
       
   598 */
       
   599 void CAknFepAvkonCandidatePopup::SetupWindowLocation( const TRect& aInlineEditorRect )
       
   600     {
       
   601     TRect clientRect;
       
   602     AknLayoutUtils::LayoutMetricsRect(AknLayoutUtils::EMainPane, clientRect);
       
   603     
       
   604     TRect popupRect = Rect();
       
   605     
       
   606     // 1. Is it possible to place the popup under the inline editor
       
   607     if ( aInlineEditorRect.iBr.iY + popupRect.Height() < clientRect.iBr.iY )
       
   608         {
       
   609         SetPosition( TPoint(aInlineEditorRect.iTl.iX, aInlineEditorRect.iBr.iY) );        
       
   610         }
       
   611         
       
   612     // 2. Is it possible to place the popup on the right side of the inline editor
       
   613     else if ( aInlineEditorRect.iBr.iX + popupRect.Width() < clientRect.iBr.iX )
       
   614         {
       
   615         SetPosition( TPoint(aInlineEditorRect.iBr.iX, aInlineEditorRect.iTl.iY) );
       
   616         }
       
   617         
       
   618     // 3. Is it possible to place the popup above the inline editor
       
   619     else if ( aInlineEditorRect.iTl.iY > popupRect.Height() )
       
   620         {
       
   621         SetPosition( aInlineEditorRect.iTl - TPoint(0, popupRect.Height()) );
       
   622         }
       
   623         
       
   624     // 4. Is it possible to place the popup on the left side of the inline editor
       
   625     else if ( aInlineEditorRect.iTl.iX > popupRect.Width() )
       
   626         {
       
   627         SetPosition( aInlineEditorRect.iTl - TPoint(popupRect.Width(), 0) );
       
   628         }
       
   629 
       
   630     // 5. If everything else fails, place the popup in the center of the screen
       
   631     else
       
   632         {
       
   633         TInt xMargins = clientRect.Width() - popupRect.Width();
       
   634         TInt yMargins = clientRect.Height() - popupRect.Height();
       
   635         SetPosition( TPoint(xMargins/2, yMargins/2) );
       
   636         }
       
   637         
       
   638         
       
   639         
       
   640     // Shift popup to left if necessary
       
   641     if ( Position().iX + popupRect.Width() > clientRect.iBr.iX )
       
   642         {
       
   643         SetPosition( TPoint(clientRect.iBr.iX-popupRect.Width(), Position().iY) );
       
   644         }
       
   645 
       
   646     // Shift popup upwards if necessary
       
   647     if ( Position().iY + popupRect.Height() > clientRect.iBr.iY )
       
   648         {
       
   649         SetPosition( TPoint(Position().iX, clientRect.iBr.iY-popupRect.Height()) );
       
   650         }
       
   651     }
       
   652 
       
   653 
       
   654 /**
       
   655 * Sets up the layout of the popup window.
       
   656 * Modified from CAknPopupList::SetupWindowLayout()
       
   657 */
       
   658 void CAknFepAvkonCandidatePopup::SetupWindowLayout(AknPopupLayouts::TAknPopupLayouts aType)
       
   659     {
       
   660     // A linked list for HandleSizeChanged().
       
   661     TAknPopupLayoutsNode list = { 0, EListNode, ListBox() };
       
   662     TAknPopupLayoutsNode heading = { &list, EHeadingNode, Heading() };
       
   663     TAknPopupLayoutsNode windowOwning = { &heading, EWindowOwningNode, this };
       
   664     TAknPopupLayoutsNode findPane = { &windowOwning, EFindBoxNode, FindBox() };
       
   665     TAknPopupLayoutsNode *listBegin = &findPane;
       
   666     
       
   667     HandleSizeChanged( Layout(), aType, listBegin );
       
   668 
       
   669     // create skin context for popuplist (list itemdrawer uses normal list skinning)
       
   670     TRect windowRect = Rect();
       
   671 
       
   672     TAknLayoutRect topLeft;
       
   673     topLeft.LayoutRect(windowRect, 
       
   674     				   SkinLayout::Popup_windows_skin_placing__frame_general__Line_2());
       
   675 
       
   676     TAknLayoutRect bottomRight;
       
   677     bottomRight.LayoutRect(windowRect,
       
   678     					   SkinLayout::Popup_windows_skin_placing__frame_general__Line_5());
       
   679 
       
   680     TRect outerRect = TRect(topLeft.Rect().iTl, bottomRight.Rect().iBr);
       
   681     TRect innerRect = TRect(topLeft.Rect().iBr, bottomRight.Rect().iTl);
       
   682     
       
   683     // we can safely use FormattedCellData only if normal popup layouts are in use
       
   684     switch(iWindowType)
       
   685         {
       
   686         case AknPopupLayouts::EMenuUnknownColumnWindow:
       
   687         case AknPopupLayouts::EMenuUnknownFormattedCellWindow:
       
   688             break;
       
   689         default:  
       
   690             {
       
   691             CFormattedCellListBoxData *boxData =
       
   692             	((CEikFormattedCellListBox*)ListBox())->ItemDrawer()->FormattedCellData();
       
   693 
       
   694             boxData->SetSkinPopupFrame(&KAknsIIDQsnFrPopup,&KAknsIIDQsnFrPopupCenter);
       
   695             boxData->SetSkinPopupFramePosition(outerRect,innerRect);
       
   696             }
       
   697             break;
       
   698         }
       
   699 
       
   700     //CListItemDrawer::SetItemCellSize needs to be called to set the selection bar width
       
   701     TSize cellSize = iList->ItemDrawer()->ItemCellSize();
       
   702     cellSize.iWidth = iLayout.iListRect.Rect().Width();
       
   703     iList->ItemDrawer()->SetItemCellSize( cellSize );
       
   704     }
       
   705     
       
   706 
       
   707 /**
       
   708 * Calculates the width of the popup window based on the candidates available on the list. 
       
   709 * The with is always set to as small as possible without truncation. 
       
   710 * The client application area is used as reference to ensure that the popup is never wider
       
   711 * than the application area.
       
   712 */
       
   713 TInt CAknFepAvkonCandidatePopup::CalculateWindowWidth( const TRect& aClientRect )
       
   714     {
       
   715     // Fetch the font
       
   716     const CFont* font = AknLayoutUtils::FontFromId(AKN_LAYOUT_TEXT_List_pane_texts__menu_single__Line_1(0).FontId());
       
   717 	
       
   718 	TInt maxTextWidth = 0;
       
   719 	
       
   720 	for (TInt i=0 ; i<iCandidates->Count() ; ++i)
       
   721 	    {
       
   722 	    TInt curTextWidth = font->TextWidthInPixels( (*iCandidates)[i] );
       
   723         if ( curTextWidth > maxTextWidth )
       
   724             {
       
   725             maxTextWidth = curTextWidth;
       
   726             }
       
   727    	    }
       
   728    	
       
   729    	TInt popupWidth = maxTextWidth + ( 2 * font->MaxCharWidthInPixels() ); 
       
   730    	
       
   731    	// Modified as per Avkon team's suggestions
       
   732    	// From Avkon:-
       
   733     // Layout data of listscroll_menu_pane are changed for CR 417-35260.
       
   734     // The change is just for QHD landscape model.
       
   735     // The CR makes listscroll_menu_pane's ir or il bigger than normal,
       
   736     // so that width of list item is smaller than needs. Then, first cell 
       
   737     // of list item can not be drawn on proper position.
       
   738     // Adjustment of layout is a solution for this problem. This is not a perfect idea, but
       
   739     // creating a new layout for popuplist is too complex to do that. Adjustment is a must.
       
   740 
       
   741    	if ( Layout_Meta_Data::IsLandscapeOrientation() )
       
   742         {
       
   743          const TSize screenSize = iAvkonAppUi->ApplicationRect().Size();
       
   744          
       
   745          if( KScreenWidthQHDLandscape == screenSize.iWidth && 
       
   746              KScreenHeightQHDLandscape == screenSize.iHeight )
       
   747              {
       
   748              popupWidth += KOffsetWidthForCandidatePopup;
       
   749              }
       
   750         }
       
   751 
       
   752    	if ( popupWidth > aClientRect.Width() )
       
   753    	    {
       
   754    	    popupWidth = aClientRect.Width();
       
   755    	    }
       
   756    	    
       
   757    	return popupWidth;
       
   758     }
       
   759 
       
   760     
       
   761 /**
       
   762 * Utility function copied from aknpopuplayout.cpp
       
   763 */
       
   764 static CCoeControl *FindControl(TAknPopupLayoutsNode *aNode, TInt aId)
       
   765     {
       
   766     while(aNode)
       
   767         {
       
   768         if (aId == aNode->iId)
       
   769             {
       
   770             return aNode->iControl;
       
   771             }
       
   772         aNode = aNode -> iNext;
       
   773         }
       
   774     return NULL;
       
   775     }
       
   776 
       
   777 /**
       
   778 * Utility function copied from aknpopuplayout.cpp
       
   779 */
       
   780 static TInt GetMaxListHeight()
       
   781     {
       
   782     TAknLayoutRect temp, layout;
       
   783 
       
   784     TRect mainPane;
       
   785     TRect statusPane;
       
   786     TRect controlPane;
       
   787     AknLayoutUtils::LayoutMetricsRect( AknLayoutUtils::EMainPane, mainPane );
       
   788     AknLayoutUtils::LayoutMetricsRect( AknLayoutUtils::EStatusPane, statusPane );
       
   789     AknLayoutUtils::LayoutMetricsRect( AknLayoutUtils::EControlPane, controlPane );
       
   790     
       
   791     // in landscape orientation popuplist can't go on top of statuspane
       
   792     if ( !Layout_Meta_Data::IsLandscapeOrientation() )
       
   793         {
       
   794         mainPane.iTl.iY -= statusPane.Height();
       
   795         }
       
   796     
       
   797     
       
   798     // treat mainpane+statuspane area as popup window
       
   799     // too bad we can't use this, because e.g. QVGA landscape has border-size 7
       
   800     // in avkon layout and border-size 9 in skin drawing...
       
   801 	/*temp.LayoutRect( mainPane, AknLayoutScalable_Avkon::listscroll_menu_pane(0));
       
   802 	layout.LayoutRect( temp.Rect(), AknLayoutScalable_Avkon::list_menu_pane(0));
       
   803     return layout.Rect().Height();*/
       
   804     	
       
   805     // shadow
       
   806     TInt varietyIndex = Layout_Meta_Data::IsLandscapeOrientation();
       
   807     
       
   808     TAknLayoutRect insideArea;
       
   809     insideArea.LayoutRect(
       
   810         mainPane,
       
   811         AknLayoutScalable_Avkon::bg_popup_window_pane_g1(varietyIndex) );
       
   812     
       
   813     return insideArea.Rect().Height();
       
   814     }
       
   815     
       
   816 /**
       
   817 * Modified from AknPopupLayouts::HandleSizeChanged()
       
   818 */
       
   819 void CAknFepAvkonCandidatePopup::HandleSizeChanged( TAknPopupWindowLayoutDef &aDef,
       
   820                                                 AknPopupLayouts::TAknPopupLayouts /*aLayout_1*/,
       
   821                                                 TAknPopupLayoutsNode *aNode)
       
   822     {
       
   823     CAknPopupHeadingPane *heading = (CAknPopupHeadingPane*)FindControl(aNode, EHeadingNode);
       
   824     CEikListBox *listBox = (CEikListBox*)FindControl(aNode, EListNode);
       
   825     CCoeControl *windowOwningControl = FindControl(aNode, EWindowOwningNode);
       
   826     //CAknMessageQueryControl *msgQueryCtrl = (CAknMessageQueryControl*)FindControl(aNode, EMessageBoxNode);
       
   827     
       
   828     //TInt layout = aLayout_1;
       
   829     TInt numofitems = listBox->Model()->NumberOfItems();
       
   830 
       
   831     TRAP_IGNORE( listBox->View()->ItemDrawer()->SetSkinEnabledL(ETrue) );
       
   832     
       
   833     TInt maxListHeight = GetMaxListHeight();
       
   834 
       
   835     // position popup window's bottom correctly
       
   836     TRect clientRect;
       
   837     AknLayoutUtils::LayoutMetricsRect(AknLayoutUtils::EMainPane, clientRect);
       
   838     // set windowrect to minimum size - this will be adjusted later    
       
   839     TAknLayoutRect windowRect;
       
   840     windowRect.LayoutRect( clientRect, AknLayoutScalable_Avkon::popup_menu_window(8));
       
   841    
       
   842     aDef.iWindowRect = windowRect.Rect();
       
   843     aDef.iWindowRect.SetWidth( CalculateWindowWidth(clientRect) );
       
   844     TRAP_IGNORE( listBox->View()->ItemDrawer()->SetSkinEnabledL(ETrue) );
       
   845     
       
   846     TInt minItems = 1;
       
   847     
       
   848     TAknWindowLineLayout listLayout;
       
   849     TAknLayoutScalableParameterLimits listLimits;
       
   850     
       
   851     listLayout = AknLayoutScalable_Avkon::list_single_pane_cp2(0);
       
   852     listLimits = AknLayoutScalable_Avkon::list_single_pane_cp2_ParamLimits();
       
   853 
       
   854 	TInt maxLayoutItems = listLimits.LastRow() + 1; // last row is a zero based index, we need num items which is 1 based
       
   855         
       
   856     TAknLayoutRect listItemRect;
       
   857 	listItemRect.LayoutRect( aDef.iWindowRect, listLayout);
       
   858     TInt listItemHeight = listItemRect.Rect().Height();
       
   859     TInt maxItems = maxListHeight / listItemHeight;
       
   860     // minItems == 1 only if the popuplist is dynamically changeable
       
   861     if ( (numofitems > 1) && (minItems == 1) )
       
   862         {
       
   863         minItems = numofitems;
       
   864         }
       
   865     if (minItems > maxItems)
       
   866         {
       
   867         minItems = maxItems;
       
   868         }
       
   869     // maxItems might be greater than max items from layout -> use layout's maximum
       
   870     if (minItems > maxLayoutItems)
       
   871         {
       
   872         minItems = maxLayoutItems;
       
   873         }
       
   874 
       
   875     TRect window_rect = AknPopupLayouts::MenuRect(aDef);
       
   876 
       
   877     TAknLayoutRect temp, layout;
       
   878     temp.LayoutRect( window_rect, AknLayoutScalable_Avkon::listscroll_menu_pane(0));
       
   879 	layout.LayoutRect( temp.Rect(), AknLayoutScalable_Avkon::list_menu_pane(0));
       
   880 	
       
   881 	
       
   882     TRect tempListRect = layout.Rect(); // this is list's rect for the whole window
       
   883 
       
   884     // We really don't want parent relative list layout here because findbox will be overwritten.
       
   885     // Just calculate list height and use that.
       
   886     TRect nullRect(0,0,0,0);
       
   887     listLayout.iH = (TInt16)(minItems * listItemHeight);
       
   888     listLayout.ib = ELayoutEmpty;
       
   889 
       
   890     aDef.iListRect.LayoutRect(tempListRect,
       
   891         listLayout);
       
   892 
       
   893     // we have to scale iWindowRect to list rect - layout is not (yet) correct
       
   894     TInt usedHeight = aDef.iListRect.Rect().Height();
       
   895 
       
   896     // popupwindow's inside area
       
   897     TInt varietyIndex = Layout_Meta_Data::IsLandscapeOrientation();
       
   898     
       
   899     TAknLayoutRect insideArea;
       
   900     insideArea.LayoutRect(
       
   901         window_rect,
       
   902         AknLayoutScalable_Avkon::bg_popup_window_pane_g1(varietyIndex) );
       
   903 
       
   904     if (layout.Rect().Height() < usedHeight)
       
   905         {
       
   906         aDef.iWindowRect.iTl.iY -= (usedHeight - layout.Rect().Height());
       
   907         }
       
   908     
       
   909 
       
   910     // now we finally know the window rect
       
   911     AknPopupLayouts::MenuPopupWindowGraphics(aDef);
       
   912     
       
   913     TAknWindowLineLayout line = AknLayoutScalable_Avkon::listscroll_menu_pane(0).LayoutLine();
       
   914         
       
   915     layout.LayoutRect(AknPopupLayouts::MenuRect(aDef), line);
       
   916     TRect scrollBarClientRect(layout.Rect());
       
   917 
       
   918     varietyIndex = 0;
       
   919     AknLayoutUtils::LayoutVerticalScrollBar(
       
   920         listBox->ScrollBarFrame(),
       
   921         scrollBarClientRect, 
       
   922         AknLayoutScalable_Avkon::scroll_pane_cp25(varietyIndex).LayoutLine() ) ;
       
   923 
       
   924     windowOwningControl->SetRect(AknPopupLayouts::WindowRect(aDef));
       
   925     AknPopupLayouts::HandleSizeAndPositionOfComponents(aDef, listBox, heading);
       
   926 
       
   927     window_rect = AknPopupLayouts::WindowRect(aDef);
       
   928     MAknsControlContext *cc = AknsDrawUtils::ControlContext( listBox );
       
   929     TBool defaultContext = EFalse;
       
   930     if (!cc)
       
   931         {
       
   932         cc = listBox->View()->ItemDrawer()->SkinBackgroundControlContext();
       
   933         defaultContext = ETrue;
       
   934         }
       
   935     if (cc)
       
   936         {
       
   937         CAknsBasicBackgroundControlContext *bcc = (CAknsBasicBackgroundControlContext*)cc;
       
   938         TAknLayoutRect popupBgRect;
       
   939          popupBgRect.LayoutRect(window_rect,
       
   940                                SkinLayout::Popup_windows_skin_placing__background_slice__Line_1(window_rect));
       
   941     
       
   942          bcc->SetBitmap(KAknsIIDQsnFrPopupCenter);
       
   943         if (defaultContext) bcc->SetRect(popupBgRect.Rect());
       
   944         bcc->SetParentPos(windowOwningControl->PositionRelativeToScreen());
       
   945         if (defaultContext)
       
   946             bcc->SetParentPos(TPoint(0,0));
       
   947         }        
       
   948     }
       
   949 
       
   950 // end of file