idlehomescreen/xmluirendering/renderingplugins/xnmenufactory/src/xnmenuadapter.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Thu, 17 Dec 2009 08:40:49 +0200
changeset 0 f72a12da539e
child 1 5315654608de
permissions -rw-r--r--
Revision: 200949 Kit: 200951

/*
* Copyright (c) 2002-2004 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:  Implementation for wrapper for a menu
*
*/

// System includes
#include <utf.h>
#include <aknappui.h>
#include <e32base.h>
#include <coecntrl.h>
#include <eikbtgpc.h>
#include <eikcba.h>
#include <barsread.h>
#include <eiksoftkeyimage.h>
#include <aknlayoutscalable_avkon.cdl.h>
#include <layoutmetadata.cdl.h>

#include <AknStatuspaneUtils.h>
#include <AknUtils.h>
#include <AknIconUtils.h>
#include <eikspane.h>
#include <AknSgcc.h>
#include <aknview.h>

// User includes
#include "xnnodepluginif.h"
#include "xntype.h"
#include "xnproperty.h"

#include "xndompropertyvalue.h"
#include "xndomproperty.h"
#include "xndomlist.h"

#include "xnuienginepluginif.h"
#include "xncomponent.h"

#include "xnappuiadapter.h"
#include "xnbitmap.h"
#include "xnmenuadapter.h"
#include "xncomponentnodeimpl.h"
#include "c_xnutils.h"

#undef _AVKON_CBA_LSC

_LIT8( KWidgetSpecific, "Menu/WidgetSpecific" );
_LIT8( KViewSpecific, "Menu/ViewSpecific" );
_LIT8( KWidgetsHidden, "Menu/WidgetsHidden" );
_LIT8( KWidgetsShown, "Menu/WidgetsShown" );
_LIT8( KEditMode, "Menu/EditMode" );
_LIT8( KAlwaysShown, "Menu/AlwaysShown" );
_LIT8( KHsShowHelp, "hs_show_help" );

const TInt KMenuCommandFirst         = 6000;
const TInt KMenuCommandLast          = 6199;
const TInt KCBACommandFirst          = 6200;
const TInt KCBACommandSecond         = 6201;
const TInt KCBACommandMiddle         = 6202; 

const TInt KXnMenuArrayGranularity   = 6;
const TInt KWideScreenWidth          = 640;

_LIT( KMskIconDialer, "#dialer");

using namespace XnPropertyNames;

static CXnNodePluginIf* FindChildL(CXnNodePluginIf& aNode, 
    const TDesC8& aType, const TDesC8& aTarget = KNullDesC8);
	
class CXnSoftkeyItem: public CBase
    { 
public:           
    CXnSoftkeyItem() 
    : iNode( NULL ),         
      iPosition( 0 ), 
      iCommandId( 0 ),      
      iLabel( NULL ),
      iBitmap( NULL ),
      iMask( NULL ),
      iImageOn( EFalse ),  
      iInvertMask( EFalse ),
      iPreserveAspectRatio( EFalse ),            
      iUpdateAppearance( ETrue ),
      iOwnBitmaps( ETrue ),
      iDefault( EFalse )
#if 0 // MSK icon change
	  ,
      iId( KAknsIIDQsnIconColors ),
      iBmpFile( NULL ),
      iBmp( 0 ),
      iBmpM( 0 )
#endif // MSK icon change
        {
        }  
                              
    ~CXnSoftkeyItem()
        {
        Reset();            
        }
        
    void Reset()
        {
        delete iLabel;
        iLabel = NULL;        
        if ( iOwnBitmaps )
            {
            delete iBitmap;
            iBitmap = NULL;
            delete iMask;            
            iMask = NULL;            
            }
        else
            {
            iBitmap = NULL;
            iMask = NULL;
            }
        
        iImageOn = EFalse;        
        iInvertMask = EFalse;
        iPreserveAspectRatio = EFalse;
#if 0 // MSK icon change
        delete iBmpFile;
        iBmpFile = NULL;
#endif // MSK icon change
        }        
        
    CXnNodePluginIf* iNode;
    TInt             iPosition;
    TInt             iCommandId;    
    HBufC*           iLabel;
    CFbsBitmap*      iBitmap;
    CFbsBitmap*      iMask;    
    TBool            iImageOn;
    TBool            iInvertMask;
    TBool            iPreserveAspectRatio;    
    TBool            iUpdateAppearance;
    TBool            iOwnBitmaps;
    TBool            iDefault;
#if 0 // MSK icon change
    TAknsItemID      iId;
    HBufC*           iBmpFile;
    TInt32           iBmp;
    TInt32           iBmpM;
#endif // MSK icon change
    };


inline TAknWindowComponentLayout DoCompose( TAknWindowComponentLayout aLine1, 
    TAknWindowComponentLayout aLine2 ) 
    { 
    return TAknWindowComponentLayout::Compose( aLine1, aLine2 ); 
    }

inline TAknTextComponentLayout DoComposeText( TAknWindowComponentLayout aLine1, 
    TAknTextComponentLayout aLine2 ) 
    { 
    return TAknWindowComponentLayout::ComposeText( aLine1, aLine2 ); 
    }

// -----------------------------------------------------------------------------
// IsNodeVisibleL
// 
// -----------------------------------------------------------------------------
//
static TBool IsNodeVisibleL(CXnNodePluginIf& aNode)
    {          
    CXnProperty* propVisibility = aNode.VisibilityL();
    
    if( propVisibility )
        {
        const TDesC8& visibility = propVisibility->StringValue();
    
        if( visibility == XnPropertyNames::style::common::visibility::KHidden )
            {
            return EFalse;
            }    
        }
        
    CXnProperty* propDisplay = aNode.DisplayL();
    
    if( propDisplay )
        {
        const TDesC8& display = propDisplay->StringValue();
        
        if( display == XnPropertyNames::style::common::display::KNone )
            {
            return EFalse;
            }
        }
        
    CXnProperty* propDisabled = aNode.GetPropertyL( XnPropertyNames::common::KDisabled );
    
    if( propDisabled )
        {
        const TDesC8& disabled = propDisabled->StringValue();
        
        if( disabled == XnPropertyNames::KTrue )
            {
            return EFalse;
            }
        }
        
    return ETrue;
    }

#ifdef _AVKON_CBA_LSC
// -----------------------------------------------------------------------------
// 
// Calculate touch sensitive softkey area for Top button (landscape)
// -----------------------------------------------------------------------------         
static TRect SoftkeyRectTopTouch()
    {
    TRect screen;
    AknLayoutUtils::LayoutMetricsRect( AknLayoutUtils::EScreen, screen );

    TAknLayoutRect layoutRect;

    TAknWindowComponentLayout rightAreaLayout(
            AknLayoutScalable_Avkon::area_side_right_pane( 0 ) );


    layoutRect.LayoutRect( screen, DoCompose( rightAreaLayout,
            AknLayoutScalable_Avkon::sctrl_sk_top_pane() ).LayoutLine() );
    TRect topSKRect( layoutRect.Rect() );
    
    layoutRect.LayoutRect( topSKRect, 
                    AknLayoutScalable_Avkon::aid_touch_sctrl_top().LayoutLine() );
    return layoutRect.Rect();
    }

// -----------------------------------------------------------------------------
// 
// Calculate touch sensitive softkey area for right button (portrait)
// -----------------------------------------------------------------------------         
static TRect SoftkeyRectRightTouch()
    {
    TRect screen;
    AknLayoutUtils::LayoutMetricsRect( AknLayoutUtils::EScreen, screen );

    TAknLayoutRect layoutRect;

    TAknWindowComponentLayout bottomAreaLayout(
            AknLayoutScalable_Avkon::area_bottom_pane( 0 ) );


    layoutRect.LayoutRect( screen, DoCompose( bottomAreaLayout,
            AknLayoutScalable_Avkon::control_bg_pane() ).LayoutLine() );
    TRect rightSKRect( layoutRect.Rect() );
    layoutRect.LayoutRect(
    		rightSKRect,
            AknLayoutScalable_Avkon::aid_touch_ctrl_right().LayoutLine() );
    return layoutRect.Rect();
    }

// -----------------------------------------------------------------------------
// 
// Calculate touch sensitive softkey area for left button (portrait)
// -----------------------------------------------------------------------------         
static TRect SoftkeyRectLeftTouch()
    {
    TRect screen;
    AknLayoutUtils::LayoutMetricsRect( AknLayoutUtils::EScreen, screen );

    TAknLayoutRect layoutRect;

    TAknWindowComponentLayout bottomAreaLayout(
            AknLayoutScalable_Avkon::area_bottom_pane( 0 ) );


    layoutRect.LayoutRect( screen, DoCompose( bottomAreaLayout,
            AknLayoutScalable_Avkon::control_bg_pane() ).LayoutLine() );
    TRect leftSKRect( layoutRect.Rect() );
    layoutRect.LayoutRect(
    		leftSKRect,
            AknLayoutScalable_Avkon::aid_touch_ctrl_left().LayoutLine() );
 
    return layoutRect.Rect();

    }

// -----------------------------------------------------------------------------
// 
// Calculate touch sensitive softkey area for Bottom button (landscape)
// -----------------------------------------------------------------------------         
static TRect SoftkeyRectBottomTouch()
    {
    TRect screen;
    AknLayoutUtils::LayoutMetricsRect( AknLayoutUtils::EScreen, screen );
    
    TAknLayoutRect layoutRect;
        
    TAknWindowComponentLayout rightAreaLayout( AknLayoutScalable_Avkon::area_side_right_pane( 0 ) );
        
    layoutRect.LayoutRect( screen, DoCompose( rightAreaLayout,
                    AknLayoutScalable_Avkon::sctrl_sk_bottom_pane() ).LayoutLine() );
    TRect bottomSKRect( layoutRect.Rect() );
            
    layoutRect.LayoutRect( bottomSKRect,
                    AknLayoutScalable_Avkon::aid_touch_sctrl_bottom().LayoutLine() );
    return layoutRect.Rect();
    }
#endif
// -----------------------------------------------------------------------------
// 
// Calculate (whole) softkey area for Bottom button (landscape)
// -----------------------------------------------------------------------------         
static TBool HDLayoutActive()
    {
    TInt resourceId = 0;
    CEikStatusPaneBase* statusPane = CEikStatusPaneBase::Current();
    
    if ( statusPane ) // Return the resource ID of app statuspane if it exists.
        {
        resourceId = statusPane->CurrentLayoutResId();
        }
    else // If this app does not have statuspane, then we ask the layout from AknCapServer.
        {
        resourceId = CAknSgcClient::CurrentStatuspaneResource();
        }    
    
    TBool retVal = EFalse;
    
    if ( Layout_Meta_Data::IsLandscapeOrientation() )
        {
        // Can be widescreen only in landscape orientation.
        retVal = ( resourceId == R_AVKON_WIDESCREEN_PANE_LAYOUT_USUAL ||
                   resourceId == R_AVKON_WIDESCREEN_PANE_LAYOUT_IDLE  ||
                   resourceId == R_AVKON_WIDESCREEN_PANE_LAYOUT_USUAL_FLAT ||
                   resourceId == R_AVKON_WIDESCREEN_PANE_LAYOUT_IDLE_FLAT );
        }
        
    return retVal;
    }

// -----------------------------------------------------------------------------
// 
// Calculate softkey image graphics area for Bottom button (landscape)
// -----------------------------------------------------------------------------         
static TRect SoftkeyRectBottomGraphics()
    {
    TRect screen;
    AknLayoutUtils::LayoutMetricsRect( AknLayoutUtils::EScreen, screen );

    TAknWindowComponentLayout rightAreaLayout(
        AknLayoutScalable_Avkon::area_side_right_pane( 0 ) );
        
    TAknWindowComponentLayout bottomSKLayout(
        DoCompose( rightAreaLayout,
                   AknLayoutScalable_Avkon::sctrl_sk_bottom_pane() ) );

    // Calculate softkey rects.
    // Left (bottom in landscape) softkey layout.
    TAknLayoutRect leftSoftkeyLayoutRect;
    leftSoftkeyLayoutRect.LayoutRect( screen,
                                      bottomSKLayout.LayoutLine() );
    TRect leftSoftKeyButtonRect( leftSoftkeyLayoutRect.Rect() );

    // Calculate softkey image layout.
    // Left (bottom in landscape) softkey layout.
    TAknWindowLineLayout leftSoftkeyImageLayout( 
        DoCompose(
            bottomSKLayout,
            AknLayoutScalable_Avkon::sctrl_sk_bottom_pane_g1() ).LayoutLine() );
            

    TAknLayoutRect qgn_graf_sk_left;
    qgn_graf_sk_left.LayoutRect( screen, leftSoftkeyImageLayout );
    
    return qgn_graf_sk_left.Rect();    
    }

// -----------------------------------------------------------------------------
// 
// Calculate softkey image graphics area for Top button (landscape)
// -----------------------------------------------------------------------------         
static TRect SoftkeyRectTopGraphics()
    {
    TRect screen;
    AknLayoutUtils::LayoutMetricsRect( AknLayoutUtils::EScreen, screen );

    TAknWindowComponentLayout rightAreaLayout(
        AknLayoutScalable_Avkon::area_side_right_pane( 0 ) );
        
    TAknWindowComponentLayout topSKLayout(
        DoCompose( rightAreaLayout,
                   AknLayoutScalable_Avkon::sctrl_sk_top_pane() ) );
        
    // Calculate softkey rects.
    // Right (top in landscape) softkey layout.
    TAknLayoutRect rightSoftkeyLayoutRect;
    rightSoftkeyLayoutRect.LayoutRect( screen,
                                       topSKLayout.LayoutLine() );
    TRect rightSoftKeyButtonRect( rightSoftkeyLayoutRect.Rect() );
    
    // Left (bottom in landscape) softkey layout.
    // Right (top in landscape) softkey layout.
    TAknWindowLineLayout rightSoftkeyImageLayout( 
        DoCompose(
            topSKLayout,
            AknLayoutScalable_Avkon::sctrl_sk_top_pane_g1() ).LayoutLine() );
            
    TAknLayoutRect qgn_graf_sk_right;
    qgn_graf_sk_right.LayoutRect( screen, rightSoftkeyImageLayout );
    return qgn_graf_sk_right.Rect();    
    }
    

// -----------------------------------------------------------------------------
// SoftkeyRectL
// Calculate soft key rect
// -----------------------------------------------------------------------------             
static TRect SoftkeyRectL( CEikButtonGroupContainer& aContainer, TInt aPos, TBool aImageOn )
    {
    TRect rect;
    
    if( AknStatuspaneUtils::StaconPaneActive() )   
        {
        TInt variety( 0 );
                        
        if( AknStatuspaneUtils::StaconSoftKeysLeft() )
            {
            variety = 1;
            }
        
        TRect parentRect( iAvkonAppUi->ApplicationRect() );
                                                                              
        switch( aPos )
            {
            case CEikButtonGroupContainer::ELeftSoftkeyPosition:
                {
                TAknWindowComponentLayout layout0( AknLayoutScalable_Avkon::area_bottom_pane( 2 ) );
                TAknWindowComponentLayout layout1( AknLayoutScalable_Avkon::stacon_bottom_pane() );

                // If clock is shown in stacon, cba area is smaller.
                TInt bottomCbaVariety( variety );
                
                if( AknStatuspaneUtils::ExtendedStaconPaneActive() )
                    {
                    bottomCbaVariety += 2;
                    }

                TAknWindowComponentLayout layout2( AknLayoutScalable_Avkon::control_bottom_pane_stacon( bottomCbaVariety ) );    
                                                                                                                       
                if( aImageOn ) 
                    {
                    // Icon layout
                    TAknWindowComponentLayout iconLayout( AknLayoutScalable_Avkon::control_bottom_pane_stacon_g1() );
                                            
                    TAknWindowComponentLayout lskIconLayout( DoCompose( layout0, 
                        DoCompose( layout1, DoCompose( layout2, iconLayout ) ) ) );
                        
                    TAknWindowLineLayout lskIcon( lskIconLayout.LayoutLine() );                    
                    
                    TAknLayoutRect qgn_icon_lsk;
                    
                    qgn_icon_lsk.LayoutRect( parentRect, lskIcon );
                    
                    rect = qgn_icon_lsk.Rect();
                    }
                else
                    {
                    // Text layout
                    TAknTextComponentLayout textLayout( AknLayoutScalable_Avkon::control_bottom_pane_stacon_t1( variety ) );
                    
                    TAknTextComponentLayout lskTextLayout( DoComposeText( layout0, 
                        DoComposeText( layout1, DoComposeText( layout2, textLayout ) ) ) );
                                                                                         
                    TAknTextLineLayout lskText( lskTextLayout.LayoutLine() );                
                    
                    TAknLayoutText qgn_text_lsk;
                    
                    qgn_text_lsk.LayoutText( parentRect, lskText );
                    
                    rect = qgn_text_lsk.TextRect();
                    }                       
                }
                break;
            case CEikButtonGroupContainer::ERightSoftkeyPosition:
                {                                            
                TAknWindowComponentLayout layout0( AknLayoutScalable_Avkon::area_top_pane( 2 ) );
                TAknWindowComponentLayout layout1( AknLayoutScalable_Avkon::stacon_top_pane() );
                        
                TInt topCbaVariety( variety );
                
                if( AknStatuspaneUtils::ExtendedStaconPaneActive() )
                    {
                    topCbaVariety += 4;
                    }
                
                TAknWindowComponentLayout layout2( AknLayoutScalable_Avkon::control_top_pane_stacon( topCbaVariety ) );    
                          
                if( aImageOn ) 
                    {
                    // Icon layout
                    TAknWindowComponentLayout iconLayout( AknLayoutScalable_Avkon::control_top_pane_stacon_g1() );
                                            
                    TAknWindowComponentLayout rskIconLayout( DoCompose( layout0, 
                        DoCompose( layout1, DoCompose( layout2, iconLayout ) ) ) );
                        
                    TAknWindowLineLayout rskIcon( rskIconLayout.LayoutLine() );                    
                    
                    TAknLayoutRect qgn_icon_rsk;
                    
                    qgn_icon_rsk.LayoutRect( parentRect, rskIcon );
                    
                    rect = qgn_icon_rsk.Rect();
                    }
                else
                    {
                    // Text layout                                                          
                    TAknTextComponentLayout textLayout( AknLayoutScalable_Avkon::control_top_pane_stacon_t1( variety ) );
                    
                    TAknTextComponentLayout rskTextLayout( DoComposeText( layout0, 
                        DoComposeText( layout1, DoComposeText( layout2, textLayout ) ) ) );
                                                                                         
                    TAknTextLineLayout rskText( rskTextLayout.LayoutLine() );                
                                       
                    TAknLayoutText qgn_text_rsk;
                    
                    qgn_text_rsk.LayoutText( parentRect, rskText );
                    
                    rect = qgn_text_rsk.TextRect();
                    }      
                }
                break;
            default:
                User::Leave( KErrNotSupported );
                break;
                
            }                                  
        }
    else
        {        
        TInt textVariety( 0 );
        TInt graphVariety( 0 );
        
        TBool mskEnabled( AknLayoutUtils::MSKEnabled() && Layout_Meta_Data::IsMSKEnabled() );
        
        if ( mskEnabled )            
            {
            textVariety = Layout_Meta_Data::IsLandscapeOrientation() ? 2 : 3;
            graphVariety = Layout_Meta_Data::IsLandscapeOrientation() ? 2 : 4;
            }
        else
            {
            textVariety = Layout_Meta_Data::IsLandscapeOrientation() ? 2 : 0;
            graphVariety = Layout_Meta_Data::IsLandscapeOrientation() ? 2 : 4;
            }

        CEikCba* cba( static_cast< CEikCba* >( aContainer.ButtonGroup() ) );
        
        TRect parentRect( cba->Rect() );
        
        switch( aPos )
            {
            case CEikButtonGroupContainer::ELeftSoftkeyPosition:
                {                                
                if( aImageOn )
                    {
                    if ( HDLayoutActive() &&
                         AKN_LAYOUT_WINDOW_screen.iW == KWideScreenWidth )
                        {
                        rect = SoftkeyRectBottomGraphics();
                        }
                     else
                        {
                            
                        TAknLayoutRect qgn_icon_lsk;
                        
                        qgn_icon_lsk.LayoutRect( parentRect,
                            AknLayoutScalable_Avkon::control_pane_g1( graphVariety ).LayoutLine() );
                            
                        rect = qgn_icon_lsk.Rect();
                        }
                    }
                else
                    {
                    TAknLayoutText qgn_text_lsk;
                    
                    qgn_text_lsk.LayoutText( parentRect,                     
                        AknLayoutScalable_Avkon::control_pane_t1( textVariety ).LayoutLine() );
                    
                    rect = qgn_text_lsk.TextRect();
                    }  
                }
                break;
            case CEikButtonGroupContainer::ERightSoftkeyPosition:
                {                                
                if( aImageOn )
                    {
                    if ( HDLayoutActive() &&
                         AKN_LAYOUT_WINDOW_screen.iW == KWideScreenWidth )
                        {
                        rect = SoftkeyRectTopGraphics();
                        }
                     else
                        {
                        TAknLayoutRect qgn_icon_rsk;
                        
                        qgn_icon_rsk.LayoutRect( parentRect,
                            AknLayoutScalable_Avkon::control_pane_g2( graphVariety ).LayoutLine() );                       
                            
                        rect = qgn_icon_rsk.Rect();
                        }
                    }
                else
                    {
                    TAknLayoutText qgn_text_rsk;
                    
                    qgn_text_rsk.LayoutText( parentRect,                     
                        AknLayoutScalable_Avkon::control_pane_t2( textVariety ).LayoutLine() );                   
                    
                    rect = qgn_text_rsk.TextRect();
                    }    
                }
                break;
            case CEikButtonGroupContainer::EMiddleSoftkeyPosition:
                {                                
                if( !mskEnabled || aImageOn )
                    {
                    // No msk, or asking image size for msk
                    User::Leave( KErrNotSupported );
                    }
                else
                    {
                    TAknLayoutText qgn_text_msk;
                    
                    qgn_text_msk.LayoutText( parentRect,                     
                        AknLayoutScalable_Avkon::control_pane_t3( textVariety ).LayoutLine() );
                    
                    rect = qgn_text_msk.TextRect();
                    }    
                }
                break;                                                                                                        
            default:
                User::Leave( KErrNotFound );
                break;
            }                
        }        
        
    return rect;                       
    }
// -----------------------------------------------------------------------------
// Get softkey image rect
// -----------------------------------------------------------------------------
static TRect SoftkeyImageRect(CEikButtonGroupContainer& aContainer, TInt aPosition)
    {
    TRect ret;
#ifndef _AVKON_CBA_LSC    
    TAknLayoutRect softkeyImg;
    CEikCba* cba( static_cast< CEikCba* >( aContainer.ButtonGroup() ) );
    TRect parentRect( cba->Rect() );
    
    if(Layout_Meta_Data::IsLandscapeOrientation())
        {
        if(aPosition == CEikButtonGroupContainer::ELeftSoftkeyPosition)
            {
            TAknWindowComponentLayout wcl = AknLayoutScalable_Avkon::control_pane_g1(2);
            softkeyImg.LayoutRect(parentRect,wcl.LayoutLine() ); 
            }
        else if(aPosition == CEikButtonGroupContainer::ERightSoftkeyPosition)
            {
            TAknWindowComponentLayout wcl = AknLayoutScalable_Avkon::control_pane_g2(2);
            softkeyImg.LayoutRect(parentRect,wcl.LayoutLine() );     
            }
        }
    else
        {
        if(aPosition == CEikButtonGroupContainer::ELeftSoftkeyPosition)
            {
            TAknWindowComponentLayout wcl = AknLayoutScalable_Avkon::control_pane_g1(4);
            softkeyImg.LayoutRect(parentRect,wcl.LayoutLine() );  
            }
        else if(aPosition == CEikButtonGroupContainer::ERightSoftkeyPosition)
            {
            TAknWindowComponentLayout wcl = AknLayoutScalable_Avkon::control_pane_g2(4);
            softkeyImg.LayoutRect(parentRect,wcl.LayoutLine() );  
       
            }
        }
    ret = softkeyImg.Rect();
#else
    if ( Layout_Meta_Data::IsLandscapeOrientation() )
        {
        if(aPosition == CEikButtonGroupContainer::ELeftSoftkeyPosition)
            {
            ret = SoftkeyRectTopTouch();
            }
        else if(aPosition == CEikButtonGroupContainer::ERightSoftkeyPosition)
            {
            ret = SoftkeyRectBottomTouch();
            }
        }
    else // portrait
        {
        if(aPosition == CEikButtonGroupContainer::ELeftSoftkeyPosition)
           {
           ret = SoftkeyRectLeftTouch();
           }
       else if(aPosition == CEikButtonGroupContainer::ERightSoftkeyPosition)
           {
           ret = SoftkeyRectRightTouch();
           }
        }
#endif    
    return ret; 
    }
    
// -----------------------------------------------------------------------------
// CopyBitmapLC
// Copy bitmap
// -----------------------------------------------------------------------------         
static CFbsBitmap* CopyBitmapL( const CFbsBitmap* aBitmap ) 
    {   
    CFbsBitmap* copy = new ( ELeave ) CFbsBitmap;
    CleanupStack::PushL( copy );
    
    copy->Create( aBitmap->SizeInPixels(), aBitmap->DisplayMode() );

    CFbsBitmapDevice* dev = CFbsBitmapDevice::NewL( copy );
    CleanupStack::PushL( dev );
    
    CFbsBitGc* gc = CFbsBitGc::NewL();
    CleanupStack::PushL( gc );
    
    gc->Activate( dev );
    gc->BitBlt( TPoint( 0, 0 ), aBitmap );

    CleanupStack::PopAndDestroy( 2 ); // gc, dev
    
    CleanupStack::Pop( copy );
    
    return copy;
    }
       
// -----------------------------------------------------------------------------
// MenuTypeL
// This is used to deactivate "active applications" menu item using the theme
// Get the "menutype" property from menubar and check if it has value
// "menuoptions" (default) or "menuoptionsnotaskswapper" and return
// correct menu type.
// -----------------------------------------------------------------------------     
static CEikMenuBar::TMenuType MenuTypeL( CXnNodePluginIf& aMenubarNode )
    {
    CEikMenuBar::TMenuType menuType( CEikMenuBar::EMenuOptions );
    
    CXnProperty* property( aMenubarNode.GetPropertyL( XnPropertyNames::menu::KMenuType ) );
                                        
    if( property )
        {                
        if( property->StringValue() == XnPropertyNames::menu::menutype::KMenuOptionsNoTaskSwapper )
            {
            menuType = CEikMenuBar::EMenuOptionsNoTaskSwapper;
            }
        }

    return menuType;
    }
    
// -----------------------------------------------------------------------------
// FindChildL
// 
// -----------------------------------------------------------------------------
static CXnNodePluginIf* FindChildL( CXnNodePluginIf& aNode, 
    const TDesC8& aType, const TDesC8& aTarget )    
    {
    RPointerArray<CXnNodePluginIf> children( aNode.ChildrenL() );
    CleanupClosePushL( children );
    
    CXnNodePluginIf* retval( NULL );

    for( TInt i = 0; i < children.Count(); i++ )
        {
        CXnNodePluginIf* child( children[i] );
        
        if( child->Type()->Type() == aType )
            {
            if( aTarget == KNullDesC8 )
                {
                retval = child;
                break;
                }
            else
                {
                CXnProperty* target( child->GetPropertyL( KXnTarget ) );
                
                if( target && target->StringValue() == aTarget )
                    {
                    retval = child;
                    break;
                    }       
                
                CXnProperty* source( child->GetPropertyL( KXnSource ) );
                                               
                if( source && source->StringValue() == aTarget )
                    {
                    retval = child;
                    break;
                    }                               
                }
            }
        }
    
    CleanupStack::PopAndDestroy( &children );
    
    return retval;
    }

// ============================ MEMBER FUNCTIONS ===============================

// -----------------------------------------------------------------------------
// CXnMenuAdapter::NewL
// Symbian static 1st phase constructor
// -----------------------------------------------------------------------------
//
CXnMenuAdapter* CXnMenuAdapter::NewL( CXnControlAdapter* aParent, CXnNodePluginIf& aNode )
    {
	CXnMenuAdapter* self = new( ELeave ) CXnMenuAdapter;

    CleanupStack::PushL( self );
    self->ConstructL( aParent, aNode );
    CleanupStack::Pop( self );

    return self;	
    }

// -----------------------------------------------------------------------------
// CXnMenuAdapter::ConstructL
// Symbian 2nd phase constructor can leave.
// -----------------------------------------------------------------------------
//
void CXnMenuAdapter::ConstructL( CXnControlAdapter* /*aParent*/, CXnNodePluginIf& aNode )
    {
    iRootNode = &aNode;      
    
    CXnControlAdapter::ConstructL( aNode );        
    
    iUiEngine = iRootNode->UiEngineL();
    
    CAknAppUi* appui( iAvkonAppUi );
    
    iPreviousMenuPaneId = appui->StatusPane()->CurrentLayoutResId();
    
    CEikMenuBar* current( iEikonEnv->AppUiFactory()->SwapMenuBar( NULL ) );    
    appui->RemoveFromStack( current );                
	
    delete current;
	current = NULL;
		   
    InitSoftkeyItemsL();
    }
    
// -----------------------------------------------------------------------------
// CXnMenuAdapter::CXnMenuAdapter
// C++ default constructor
// -----------------------------------------------------------------------------
//
CXnMenuAdapter::CXnMenuAdapter(): 
    iMenuItems( KXnMenuArrayGranularity ), 
    iIdCounter( KMenuCommandFirst )
    {
    }

// -----------------------------------------------------------------------------
// CXnMenuAdapter::~CXnMenuAdapter
// C++ destructor
// -----------------------------------------------------------------------------
//
CXnMenuAdapter::~CXnMenuAdapter()
    {
    StopDisplayingMenu();

    if ( iAvkonAppUi )
        {
        iAvkonAppUi->RemoveFromStack( iMenuBar );
        }

    if ( iMenuBar )
        {
        delete iMenuBar;
        }

    iSoftkeyItems.ResetAndDestroy();
    iMenuItems.Reset();
    }

// -----------------------------------------------------------------------------
// Create scaled bitmap from source bitmap.
// -----------------------------------------------------------------------------
//
void CreateScaledBitmapL(
    const TRect& aRect,
    CFbsBitmap*& aTrgBitmap, 
    CFbsBitmap* aSrcBitmap,
    TBool aPreserveAspectRatio )    
    {
    TRect destRect = aRect;
        
    if( aPreserveAspectRatio )
    	{
	    // Calculate the bitmap image dimensions so that it uses maximum space 
	    // of the given rectangle and maintains aspect ratio.
    	TInt srcHeight = aSrcBitmap->SizeInPixels().iHeight;
    	TInt srcWidth = aSrcBitmap->SizeInPixels().iWidth;
    	TReal scaleRatio( 1 ); //no scale as defaul

		// If any dimension is 0, then we do not bother to scale
    	if( aRect.Width() > 0 && aRect.Height() > 0 )
    		{
	    	TReal xRatio = ( (TReal )srcWidth / ( TReal )aRect.Width() );
	    	TReal yRatio = ( ( TReal )srcHeight / ( TReal )aRect.Height() );
	    	
	    	//Find out appropriate scaling factor
	   		xRatio > yRatio ? ( scaleRatio = xRatio ) : ( scaleRatio = yRatio );
    		}
    	
    	// Scale the size for target bitmap
    	destRect.SetHeight( srcHeight / scaleRatio );
		destRect.SetWidth( srcWidth / scaleRatio );
    	}

    aTrgBitmap = new ( ELeave ) CFbsBitmap;
    CleanupStack::PushL( aTrgBitmap );
    
    // It is allowed to create zero height or width bitmap.    
    TInt err( aTrgBitmap->Create( destRect.Size(), aSrcBitmap->DisplayMode() ) );

    if( err == KErrNone )
        {
		CXnUtils::ScaleBitmapL( destRect, aTrgBitmap, aSrcBitmap );
        }

    // we do not own the bitmap so just Pop.
    CleanupStack::Pop( aTrgBitmap );
    }    

// -----------------------------------------------------------------------------
// CXnMenuAdapter::PrepareSoftkeyImageL
// Make a copy of originals and scale them to right size.
// Finally place the scaled icon to right position of drawing area.
// -----------------------------------------------------------------------------         
CEikImage* CXnMenuAdapter::PrepareSoftkeyImageL( const CXnSoftkeyItem& aItem, const TSize& aSize )
    {                         
    CFbsBitmap* bitmap( NULL );
    CFbsBitmap* mask( NULL );
    
    // Start from bitmap
    CFbsBitmap* source( aItem.iBitmap );    
        
    TInt count( 0 );
           
    // Go through bitmap and mask
    for( TInt i = 0; i < 2; i++ )
        {
        if( !source )
            {
            source = aItem.iMask;
            continue;
            }
            
        CFbsBitmap* scaled( NULL );            

        TScaleMode mode( aItem.iPreserveAspectRatio ? EAspectRatioPreserved : EAspectRatioNotPreserved );
            
        if( AknIconUtils::IsMifIcon( source ) )
            {                       
            AknIconUtils::SetSize( source, aSize, mode );
            
            scaled = CopyBitmapL( source );
            }
        else
            {                            
            CreateScaledBitmapL( TRect( aSize ), scaled, source, mode == EAspectRatioPreserved );        
            }

        CleanupStack::PushL( scaled );                
        
        if( !aItem.iPreserveAspectRatio )                        
            {                          
            count++;
                                 
            if( i == 0 )
                {                
                bitmap = scaled;                                
                }
            else
                {
                mask = scaled;
                }                                                                         
            }
        else
            {                        
            CFbsBitmap* target = new ( ELeave ) CFbsBitmap;
            CleanupStack::PushL( target );

            // Target is size of whole draw area
            User::LeaveIfError( target->Create( aSize, source->DisplayMode() ) );
        	
    	    CFbsBitmapDevice* dev = CFbsBitmapDevice::NewL( target );
    	    CleanupStack::PushL( dev );
    	    
    	    CFbsBitGc* gc = CFbsBitGc::NewL();
    	    CleanupStack::PushL( gc );
    	    
    	    gc->Activate( dev );
    	    
    	    gc->SetBrushStyle( CGraphicsContext::ESolidBrush );
    	    gc->SetPenStyle( CGraphicsContext::ENullPen );
    	    
    	    if( aItem.iInvertMask )
    	        {
        	    // White, with full transparent alpha channel
        	    gc->SetBrushColor( TRgb( 0x00FFFFFF, 0 ) );	       
    	        }
            else
                {
        	    // Black, with full transparent alpha channel
        	    gc->SetBrushColor( TRgb( 0x00000000, 0 ) );
                }	        
    	    
    	    // Make whole target area transparent
    	    gc->DrawRect( TRect( aSize ) );
    	   
    	   	TPoint iconPos;
    	   	
    	   	switch( AknLayoutUtils::CbaLocation() )
    	   	    {	   	    
    	   	    case AknLayoutUtils::EAknCbaLocationBottom:
    	   	        // Rsk must be moved to right, lsk is in correct place by default	   	        
    	   	        if ( aItem.iPosition != CEikButtonGroupContainer::ELeftSoftkeyPosition )
    	   	            {
    	   	            iconPos.iX = aSize.iWidth - scaled->SizeInPixels().iWidth;
    	   	            }
    	   	        break;	   	    	   	   
    	   	    case AknLayoutUtils::EAknCbaLocationRight:
    	   	        // Rsk and lsk must be moved to right	   	       
    	   	        iconPos.iX = aSize.iWidth - scaled->SizeInPixels().iWidth;
    	   	        break;
    	   	    case AknLayoutUtils::EAknCbaLocationLeft:
    	   	        // Already in correct position
    	   	    default:    	   	        
    	   	        break;    
    	   	    }
    	   	
    	   	// Align horizontally to center
            iconPos.iY = iconPos.iX ? 0 : ( ( aSize.iHeight - scaled->SizeInPixels().iHeight ) / 2 );
    	   		   	
    	   	gc->SetBrushStyle( CGraphicsContext::ENullBrush );
    	   			   	
    	   	// Blit image to correct position
    	   	gc->BitBlt( iconPos, scaled );    	

    		CleanupStack::PopAndDestroy( 2, dev );    		    		    		    		
    		
    		CleanupStack::Pop( target );
    		
    		CleanupStack::PopAndDestroy( scaled );
    		
    		CleanupStack::PushL( target );
            count++;                		    		
            
    		if( i == 0 )
    		    {
    		    bitmap = target;    		        		    
    		    }
            else
                {
                mask = target;
                }    		        		      
                
            
        	}                  
        
        // Go with mask next
        source = aItem.iMask;
        }    
        
    // Takes ownership of scaled bitmap and mask
    CEikImage* image = new ( ELeave ) CEikImage;
    
    image->SetPictureOwnedExternally( EFalse );
    image->SetPicture( bitmap, mask );        
                       
    CleanupStack::Pop( count ); 
    
    return image;
    }

// -----------------------------------------------------------------------------
// CXnMenuAdapter::SetSoftkeyAppearanceL
// 
// -----------------------------------------------------------------------------
//
void CXnMenuAdapter::SetSoftkeyAppearanceL( CXnSoftkeyItem& aItem )
    {
#if 0 // MSK icon change
    if( IsNodeVisibleL( *aItem.iNode) )
        {
        if( aItem.iImageOn )
            {
            ChangeSoftkeyImageL( aItem );
            }
        else if( aItem.iLabel )// change label
            {
            TBool left( EFalse );
            if ( aItem.iPosition == CEikButtonGroupContainer::ELeftSoftkeyPosition )
                {
                left = ETrue;
                EikSoftkeyImage::SetLabel( iContainer,left );
                }
            else if ( aItem.iPosition == CEikButtonGroupContainer::ERightSoftkeyPosition )
                {
                left = EFalse;
                EikSoftkeyImage::SetLabel( iContainer,left );
                }

            iContainer->SetCommandL( aItem.iPosition, aItem.iCommandId, *aItem.iLabel );
            }
        }
    }
#else // MSK icon change
    if( IsNodeVisibleL( *aItem.iNode) )
        {
        if( aItem.iPosition == CEikButtonGroupContainer::ELeftSoftkeyPosition 
            || aItem.iPosition == CEikButtonGroupContainer::ERightSoftkeyPosition)
            {
            if(aItem.iImageOn)
                {
                ChangeSoftkeyImageL(aItem);
                }
            else if(aItem.iLabel)// change label
                {
                TBool left(EFalse);
                if(aItem.iPosition == CEikButtonGroupContainer::ELeftSoftkeyPosition)
                    {
                    left = ETrue;
                    }
                EikSoftkeyImage::SetLabel( iContainer,left );
                iContainer->SetCommandL( aItem.iPosition, aItem.iCommandId, *aItem.iLabel );
                
                }
                                   
            }
        else if(aItem.iPosition == CEikButtonGroupContainer::EMiddleSoftkeyPosition)   
            {
            if( aItem.iLabel )
                {
                // Msk will have predefined image based on command id                                                            
                if( *aItem.iLabel == menu::KMSKDotImage16 )
                    {
                    aItem.iCommandId = KCBACommandFirst;
                    }                                           
                else if(*aItem.iLabel == KMskIconDialer)
                    {
#ifndef _AVKON_CBA_LSC                    
                    aItem.iCommandId = EAknSoftkeyDialler;
#endif                    
                    }
                else
                    {
                    aItem.iCommandId = KCBACommandMiddle;
                    }
                iContainer->SetCommandL( aItem.iPosition, aItem.iCommandId, *aItem.iLabel );
                }
            }
        }
    }
#endif // MSK icon change

// -----------------------------------------------------------------------------
// CXnMenuAdapter::InitSoftkeyItemsL
// 
// -----------------------------------------------------------------------------
//
void CXnMenuAdapter::InitSoftkeyItemsL()
    {                
    // No layout calulations needed
    iRootNode->SetLayoutCapable( EFalse );       
    
    // create softkeyitems to hold data
    
    RPointerArray< CXnNodePluginIf > children( iRootNode->ChildrenL() );
    CleanupClosePushL( children );
    CXnSoftkeyItem* item(0);
    for(TInt i=0;i<children.Count();++i)
        {
        if(children[i]->Type()->Type() == XnPropertyNames::softkey::KNodeName)
            {
            item = AppendSoftkeyItemL(children[i]);
            if(item)
                {
                item->iDefault = ETrue;
                }
            }
        }
    CleanupStack::PopAndDestroy( &children );
    
   }
    
// -----------------------------------------------------------------------------
// CXnMenuAdapter::InitSoftkeyItemL
// 
// -----------------------------------------------------------------------------
//
void CXnMenuAdapter::InitSoftkeyItemImageL( CXnSoftkeyItem& aItem)
    {
    CXnNodePluginIf* node( aItem.iNode );
    
    // No layout calulations needed
    node->SetLayoutCapable( EFalse );                                                                 

#if 0 // MSK icon change
    if ( aItem.iPosition == CEikButtonGroupContainer::EMiddleSoftkeyPosition )
        {
        aItem.iImageOn = ETrue;
        return;
        }
#endif // MSK icon change

    CXnProperty* pathProp( node->PathL() );
    if( pathProp )
        {     
        HBufC* bitmapPath( NULL );                                  
        HBufC* maskPath( NULL );
        
        bitmapPath = pathProp->StringValueL();
        CleanupStack::PushL( bitmapPath );
        TInt count( 1 );
        
        CXnProperty* maskProp( node->MaskPathL() );
                                        
        if( maskProp )
            {
            maskPath = maskProp->StringValueL();                                
            CleanupStack::PushL( maskPath );
            count++;
            }
                    
        CFbsBitmap* bitmap( NULL );
        CFbsBitmap* mask( NULL );
                                                                    
        // Call base class to get bitmap and mask                        
        GetBitmapAndMask( bitmapPath ? *bitmapPath : KNullDesC(), 
                          maskPath ? *maskPath : KNullDesC(), 
                          bitmap, mask );                            
                    
        aItem.iImageOn = ETrue;
        aItem.iBitmap = bitmap;
        aItem.iMask = mask;
        
        CXnProperty* maskInvertedProp( node->GetPropertyL( XnPropertyNames::image::KMaskInverted ) );
        
        if( maskInvertedProp )
            {                        
            if( maskInvertedProp->StringValue() == XnPropertyNames::KTrue )
                {
                aItem.iInvertMask = ETrue;
                }
            }
        
        CXnProperty* aspectRatioProp( node->GetPropertyL( XnPropertyNames::image::KS60AspectRatio ) );
        
        if( aspectRatioProp )
            {
            if( aspectRatioProp->StringValue() == XnPropertyNames::image::KPreserve )
                {
                aItem.iPreserveAspectRatio = ETrue;
                }
            }
                
        CleanupStack::PopAndDestroy( count ); // path and/or mask
        }    
    }

// -----------------------------------------------------------------------------
// CXnMenuAdapter::IsMskAvailable
// 
// -----------------------------------------------------------------------------
//
TBool CXnMenuAdapter::IsMskAvailable()
    {
    if( AknLayoutUtils::MSKEnabled() && Layout_Meta_Data::IsMSKEnabled() )
        {     
        return ETrue;
        }
    
    return EFalse;                
    }
    
// -----------------------------------------------------------------------------
// CXnMenuAdapter::AddMenuItemL
// 
// -----------------------------------------------------------------------------
//
TInt CXnMenuAdapter::AddMenuItemL( TInt aParentIndex, 
    CXnNodePluginIf* aNode, RPointerArray< const TDesC8 >& aGroups )
    {
    if ( !aNode )
        {
        return 0;
        }
    
    const TDesC8& name( aNode->Type()->Type() );
    
    TInt retval( 0 );
    
    TBool showByGroup( EFalse );
    
    const TDesC8* id( NULL );
    
    CXnProperty* prop( aNode->IdL() );
    
    if( prop )
        {            
        id = &prop->StringValue();
        }
    else
        {
        // If menuitem doesn't have id, group doesn't affect to it
        showByGroup = ETrue;
        }
    
    if( name == KXnMenuItem || 
        name == KXnDynMenuItem || 
        name == KXnWidgetMenuItem )
        {               
        const TDesC8& ns( aNode->Namespace() );
                       
        for( TInt i = 0; !showByGroup && i < aGroups.Count(); i++ )
            {                       
            const TDesC8& groupId( *(aGroups)[i] );
        
            CXnNodePluginIf* group( iUiEngine->FindNodeByIdL( groupId, ns ) );
            
            if( group )
                {
                RPointerArray< CXnNodePluginIf > 
                    children( group->ChildrenL() );
                
                CleanupClosePushL( children );
                
                for( TInt j = 0; j < children.Count(); j++ )
                    {
                    CXnProperty* prop( children[j]->GetPropertyL( 
                            XnPropertyNames::action::KName ) );
                                        
                    if( prop )
                        {
                        const TDesC8& name( prop->StringValue() );
                            
                        if( name == *id )
                            {
                            // The menuitem belongs to defined group
                            showByGroup = ETrue;
                            break;                            
                            }
                        }
                    }
                
                CleanupStack::PopAndDestroy( &children );                
                }            
            }
        
        if( !showByGroup || !IsNodeVisibleL( *aNode ) )
            {
            // Menuitem is invisible  
            return retval;
            }
        }
               
    TXnMenuItem item;

    item.iAutomaticSP = ETrue;
        
    item.iParentIndex = aParentIndex;
    item.iData.iFlags = 0;

    CXnNodePluginIf* menuItem( NULL );
    
    if( name == KXnMenuItem || name == KXnDynMenuItem )
        {
        menuItem = aNode;
        }
    else if( name == KXnWidgetMenuItem )
        {
        TRAP_IGNORE( menuItem = FindWidgetMenuItemL( aNode ) );
        }
    
    if( menuItem )
        {
        const TDesC8& type( menuItem->Type()->Type() );
        
        // check first if label comes from view
        CXnProperty* label( aNode->LabelL() );
        
        if ( !label )
            {
            // get label from widget
            label = menuItem->LabelL();
            }
        
        if( label )
            {
            HBufC* itemLabel = label->StringValueL();
            item.iData.iText.Copy( *itemLabel );
            delete itemLabel;
            }
        else
            {
            item.iData.iText.Copy( KNullDesC );
            }
    
        TBool okToAdd( ETrue );
        
        if( type == KXnDynMenuItem )
            {
            okToAdd = EFalse;
            
            if( iObserver )
                {
                okToAdd = iObserver->DynInitMenuItemL( menuItem->AppIfL() );
                }            
            }
        
        if( okToAdd )
            {
            if ( id && *id == KHsShowHelp )
                {
                // Help command id must be EAknCmdHelp to get editing input options
                // shown correctly  
                item.iData.iCommandId = EAknCmdHelp;
                }
            else
                {
                item.iData.iCommandId = iIdCounter++;
                }
            
            item.iData.iCascadeId = 0;
            item.iNode = menuItem;
            item.iIsCascade = EFalse;
            iMenuItems.AppendL( item );
            
            retval = 1;
            }               
        }
    
    if( name == KXnMenu )
        {
        // main level menu or submenu (cascade)               
        item.iData.iCommandId = iIdCounter++;

        if( aParentIndex == -1 )
            {
            item.iData.iCascadeId = R_AVKON_MENUPANE_EMPTY;
            }
        else
            {
            item.iData.iCascadeId = iIdCounter++;
            }
        
        item.iNode = aNode;
        item.iIsCascade = ETrue;        
        iMenuItems.AppendL( item );

        TInt currentIndex( iMenuItems.Count() - 1 );
        
        RPointerArray< CXnNodePluginIf > children( aNode->ChildrenL() );
        CleanupClosePushL( children );

        TInt count( 0 );
        
        for( TInt i = 0; i < children.Count(); i++ )
            {
            count += AddMenuItemL( currentIndex, children[i], aGroups );
            }
        
        if( aParentIndex != -1 && count == 0 )
            {
            // Empty submenu, don't show it            
            iMenuItems.Delete( currentIndex );
            // Reverse counter as well
            iIdCounter -= 2;
            }
        
        CleanupStack::PopAndDestroy( &children );
        
        retval = count;
        }

    return retval;
    }
    
// -----------------------------------------------------------------------------
// CXnMenuAdapter::PopulateMenuL
// 
// -----------------------------------------------------------------------------
//
void CXnMenuAdapter::PopulateMenuL()
    {
    iMenuItems.Reset();

    iIdCounter = KMenuCommandFirst;
       
    CXnNodePluginIf* focused( iUiEngine->FocusedNodeL() );
    
    const TDesC8& ns( iRootNode->Namespace() );
    
    TBool widgetSpecific( EFalse );
    
    for( ; focused ; focused = focused->ParentL() )
        {
        if( focused->AppIfL().InternalDomNodeType() == XnPropertyNames::KPlugin )
            {
            widgetSpecific = ETrue;
            break;
            }
        }

    TBool widgetsShown( iUiEngine->WidgetsVisible() );
    
    RPointerArray< const TDesC8 > groups;
    CleanupClosePushL( groups );
               
    if( iUiEngine->EditMode() )
        {
        groups.AppendL( &KEditMode );
        }
    else
        {
        groups.AppendL( widgetSpecific ? &KWidgetSpecific : &KViewSpecific );
        groups.AppendL( widgetsShown ? &KWidgetsShown : &KWidgetsHidden );        
        }
    
    groups.AppendL( &KAlwaysShown );
         
    // Recursively add menuitems
    AddMenuItemL( -1, iMenuBarNode, groups );
    
    CleanupStack::PopAndDestroy( &groups );
    }
  
// -----------------------------------------------------------------------------
// CXnMenuAdapter::OfferKeyEventL
// -----------------------------------------------------------------------------
//
TKeyResponse CXnMenuAdapter::OfferKeyEventL(const TKeyEvent& aKeyEvent,TEventCode aType)
    {    
    TKeyResponse resp( EKeyWasNotConsumed );
    
    if( IsMenuFocused() && aKeyEvent.iScanCode == EStdKeyNo )
        {
        StopDisplayingMenu();            
        
        iKeyEventNode = NULL;
        
        return resp;
        }        

    const TDesC8* pos( &KNullDesC8 );
    
    if( aKeyEvent.iScanCode == EStdKeyDevice0 )
        {
        pos = &XnPropertyNames::softkey::type::KLeft;
        }
    else if( aKeyEvent.iScanCode == EStdKeyDevice1 )
        {
        pos = &XnPropertyNames::softkey::type::KRight;
        }
    else if( aKeyEvent.iScanCode == EStdKeyDevice3 )
        {
        pos = &XnPropertyNames::softkey::type::KMiddle;
        }            
    
    if( aType == EEventKeyDown )
        {                                  
        iKeyEventNode = FindSoftkeyNodeL( *pos );           
        }
            
    if( aKeyEvent.iScanCode == EStdKeyDevice0 || 
        aKeyEvent.iScanCode == EStdKeyDevice1 || 
        aKeyEvent.iScanCode == EStdKeyDevice3 )
        {
        CXnNodePluginIf* node(  FindSoftkeyNodeL( *pos ) );
        
        if( node && node == iKeyEventNode )
            {
            // Let base class handle the event           
            resp = CXnControlAdapter::OfferKeyEventL( aKeyEvent, aType );                                        
            }            
        }
        
    if( aType == EEventKeyUp )
        {
        iKeyEventNode = NULL;
        }
        
    return resp;
    }
    
// -----------------------------------------------------------------------------
// CXnMenuAdapter::HandlePointerEventL
// -----------------------------------------------------------------------------
//
void CXnMenuAdapter::HandlePointerEventL( const TPointerEvent& aPointerEvent )
    {          
    CXnNodePluginIf* node( FindSoftkeyItemByPosition( aPointerEvent.iParentPosition ) );
    
    if( aPointerEvent.iType  == TPointerEvent::EButton1Down )
        {
        // The sofkey node which received the button down event
        iPointerEventNode = node;        
        }
        
    if( node && node == iPointerEventNode )
        {
        iUiEngine->DisableRenderUiLC();
        
        // Handle event if location is in the grabbing node's area    
        CXnControlAdapter::HandlePointerEventL( aPointerEvent );
        
        CleanupStack::PopAndDestroy();
        }
            
    if( aPointerEvent.iType  == TPointerEvent::EButton1Up )
        {
        // Reset grabbing node after the up event
        iPointerEventNode = NULL;
        }    
    }

// -----------------------------------------------------------------------------
// CXnMenuAdapter::DoEnterPowerSaveModeL
// Enter power save mode
// -----------------------------------------------------------------------------
void CXnMenuAdapter::DoEnterPowerSaveModeL(TModeEvent /*aEvent*/)
    {
    }
    
// -----------------------------------------------------------------------------
// CXnMenuAdapter::DoExitPowerSaveModeL
// Enter power save mode
// -----------------------------------------------------------------------------
void CXnMenuAdapter::DoExitPowerSaveModeL(TModeEvent /*aEvent*/)
    {
    } 
       
// -----------------------------------------------------------------------------
// CXnMenuAdapter::RestoreMenuL
// -----------------------------------------------------------------------------
//
void CXnMenuAdapter::RestoreMenuL( CCoeControl* aMenuControl, TInt aResourceId,        
    TMenuType aType )
    {
    // let all menu pane resources propogate to default implementation,
    // otherwise panic when trying to display menu
    if ( aType == MEikMenuObserver::EMenuPane )
        {
        if ( !( KMenuCommandFirst <= aResourceId && 
                aResourceId <= KMenuCommandLast ) 
            && aResourceId != R_AVKON_MENUPANE_EMPTY  )
            {
            MEikMenuObserver::RestoreMenuL( aMenuControl,aResourceId, aType );
            }
        else
            {
            AddItemsToMenuPaneL( ( CEikMenuPane* )aMenuControl, aResourceId );            
            }
        }  
    }

// -----------------------------------------------------------------------------
// CXnMenuAdapter::DynInitMenuPaneL
// -----------------------------------------------------------------------------
//
void CXnMenuAdapter::DynInitMenuPaneL( TInt aResourceId, 
    CEikMenuPane* aMenuPane )
    {
    if ( aResourceId == R_AVKON_MENUPANE_EMPTY )
        {
        RestoreMenuL( aMenuPane, aResourceId, MEikMenuObserver::EMenuPane );
        }    
    }
    
// -----------------------------------------------------------------------------
// CXnMenuAdapter::SetEmphasis
// -----------------------------------------------------------------------------
//
void CXnMenuAdapter::SetEmphasis( CCoeControl* aMenuControl, 
    TBool aEmphasis )
    {
    if ( iMenuBar && aMenuControl == iMenuBar )
        {   
        CXnAppUiAdapter* appui( 
            static_cast< CXnAppUiAdapter* >( iAvkonAppUi ) );

        if ( aEmphasis && !iMenuShown )
            {
            iMenuShown = ETrue;

            TRAP_IGNORE( appui->AddToStackL( appui->View(),
                                             iMenuBar,
                                             ECoeStackPriorityMenu ) );

            iMenuBar->MakeVisible( ETrue );
            }
        else if ( !aEmphasis && iMenuShown )
            {
            iMenuShown = EFalse;
         
            appui->RemoveFromStack( iMenuBar );
            
            iMenuBar->MakeVisible( EFalse );
            }
        }
    }

// -----------------------------------------------------------------------------
// CXnMenuAdapter::ProcessCommandL
// -----------------------------------------------------------------------------
//
void CXnMenuAdapter::ProcessCommandL( TInt aCommand )
    {     
    if ( ( KMenuCommandFirst <= aCommand && aCommand <= KMenuCommandLast ) || 
        aCommand == EAknCmdHelp )
        {
        // find item for this command
        for ( TInt i = 0; i< iMenuItems.Count(); i++ )
            {
            if ( iMenuItems[i].iData.iCommandId == aCommand )
                {
                CXnNodePluginIf* node( iMenuItems[i].iNode );
                
                if ( node )
                    {
                    StopDisplayingMenu();
                    
                    iUiEngine->DisableRenderUiLC();
                    
                    node->SetStateL( XnPropertyNames::style::common::KActive );
                    
                    CleanupStack::PopAndDestroy();                 
                    
                    break;
                    }                                    
                }
            }        
        }
    else
        {
        StopDisplayingMenu();

        if( aCommand == EEikCmdEditPaste )
            {
            // Paste event for AknCcpuSupport
            TKeyEvent pasteEvent = 
                { EKeyF18, EEikCmdEditPaste, EModifierCtrl, 1 };  
            
            iCoeEnv->SimulateKeyEventL( pasteEvent, EEventKey );
            }
        }
    }

// -----------------------------------------------------------------------------
// CXnMenuAdapter::SetContainerL
// 
// -----------------------------------------------------------------------------
//
void CXnMenuAdapter::SetContainerL( CEikButtonGroupContainer& aContainer )
    {
    TBool updateNeeded( EFalse );
    
    TInt statusPaneId( iAvkonAppUi->StatusPane()->CurrentLayoutResId() );
    
    if(iPreviousMenuPaneId != statusPaneId)
        {
        updateNeeded = ETrue;
        iPreviousMenuPaneId = statusPaneId;
        }
    
 	if((&aContainer) && (iContainer != &aContainer || updateNeeded))
        {
        iUpdateLskAppearance = ETrue;
        iUpdateMskAppearance = ETrue;
        iUpdateRskAppearance = ETrue;
        }
 	
	iContainer = &aContainer;
	
	UpdateSoftkeyAppearancesL();
	    
	if (iContainer)
	    {
        iContainer->DrawNow();        
	    }
    }

//--------------------------------------------------------------
// CXnMenuAdapter::IsMenuFocused
// ------------------------------------------------------------        
TBool CXnMenuAdapter::IsMenuFocused()
    {
    return iMenuShown;
    }

// -----------------------------------------------------------------------------
// CXnMenuAdapter::TryDisplayingMenuL
// Displays options menu if it is defined for the softkey item
// -----------------------------------------------------------------------------
//
void CXnMenuAdapter::TryDisplayingMenuL( const TDesC& aMenuNodeId )
    {
    HBufC8* id = CnvUtfConverter::ConvertFromUnicodeToUtf8L( aMenuNodeId );
    CleanupStack::PushL( id );
    CXnNodePluginIf* node( iUiEngine->FindNodeByIdL( *id, iRootNode->Namespace() ) );
    CleanupStack::PopAndDestroy( id );
    
    if( node && node->Type()->Type() == KXnMenu )
        {
        TryDisplayingMenuL();
        }
    }

// -----------------------------------------------------------------------------
// CXnMenuAdapter::TryDisplayingMenuL
// Displays options menu if it is defined for the softkey item
// -----------------------------------------------------------------------------
//
void CXnMenuAdapter::TryDisplayingMenuL()
    {
    StopDisplayingMenu();
    
    CreateMenuBarL();    
    
    if ( iMenuBar )
        {    
        CEikMenuBarTitle* title = new( ELeave ) CEikMenuBarTitle;
        CleanupStack::PushL( title );
            
        title->iData.iMenuPaneResourceId = R_AVKON_MENUPANE_EMPTY;    
        title->iTitleFlags = 0;
        
        // this cannot be done earlyer, than this callback
        iMenuBar->TitleArray()->AddTitleL( title );
        CleanupStack::Pop( title );
        
        iMenuBar->TryDisplayMenuBarL();
        }    
    }

// -----------------------------------------------------------------------------
// CXnMenuAdapter::StopDisplayingMenu
// -----------------------------------------------------------------------------
//
void CXnMenuAdapter::StopDisplayingMenu()
    {
    if( iMenuShown && iMenuBar )
        {
        iMenuBar->StopDisplayingMenuBar();
        }
    }

// ---------------------------------------------------------------------------
// CXnMenuAdapter::CreateMenuBarL
// ---------------------------------------------------------------------------
//
void CXnMenuAdapter::CreateMenuBarL()
    {
    if ( iMenuBar )
        {
        // All ready created
        return;
        }
    
    // Create
    RPointerArray< CXnNodePluginIf > children( iRootNode->ChildrenL() );
    CleanupClosePushL( children );
      
    for( TInt i = 0; i < children.Count(); i++ )
        {       
        CXnNodePluginIf* node( children[i] );
        
        TPtrC8 type( node->Type()->Type() );
                                                       
        // Currently only one menubar is allowed,
        // but it can be assigned to any of the CBAs
        // To change this, we have to create and maintain a list of menubars 
        if( type == KXnMenu )
            {
            iMenuBarNode = node;
            
            iMenuBar = new ( ELeave ) CEikMenuBar;
            iMenuBar->ConstructL( this );
            iMenuBar->SetMenuType( MenuTypeL( *iRootNode ) );
                        
            // All done
            break;
            }
        }
    CleanupStack::PopAndDestroy( &children );
    }

//--------------------------------------------------------------
// CXnMenuAdapter::HandleResourceChange
// Handles a change to the control's resources of type aType
// ------------------------------------------------------------    
void CXnMenuAdapter::HandleResourceChange( TInt aType )
    {	
    if( iMenuBar )
        {
        iMenuBar->HandleResourceChange( aType );
        }   	
    }
   
// -----------------------------------------------------------------------------
// CXnMenuAdapter::SetSoftKeyImageL
// 
// -----------------------------------------------------------------------------
//
void CXnMenuAdapter::SetSoftKeyImageL(
    CFbsBitmap* aBitmap, 
    CFbsBitmap* aMask, 
    XnMenuInterface::MXnMenuInterface::TSoftKeyPosition aPos, 
    CXnNodeAppIf* aNode,
    TBool aPreserveAspectRatio, TBool aInvertMask,
    TBool aTransferOwnership)
    {        
    if( ( !aBitmap && !aMask ) || aPos == XnMenuInterface::MXnMenuInterface::ECenter )
        {
        // No images present and image can be set only to lsk or rsk         
        User::Leave( KErrArgument );
        }

    CXnSoftkeyItem* softkey(NULL);
    
    if( aPos == XnMenuInterface::MXnMenuInterface::ELeft)
        {
        if( aNode )
            {
            softkey = SoftkeyItemL( aNode );
            }
        else
            {
            softkey = SoftkeyItemL(CEikButtonGroupContainer::ELeftSoftkeyPosition);
            }
        iUpdateLskAppearance = ETrue;
        }
    else if(aPos == XnMenuInterface::MXnMenuInterface::ERight)
        {
        if( aNode )
            {
            softkey = SoftkeyItemL( aNode );
            }
        else
            {
            softkey = SoftkeyItemL(CEikButtonGroupContainer::ERightSoftkeyPosition);
            }
        iUpdateRskAppearance = ETrue;
        }
    
    if(softkey)
        {
        softkey->Reset();
        softkey->iImageOn = ETrue;
                                                                    
        // Save new icon data
        softkey->iBitmap = aBitmap;
        softkey->iMask = aMask;
        softkey->iPreserveAspectRatio = aPreserveAspectRatio;
        softkey->iInvertMask = aInvertMask;
        softkey->iOwnBitmaps = aTransferOwnership;
        // Image set, mark node as dirty
        softkey->iNode->SetDirtyL();
                
        }
    }

#if 0 // MSK icon change
// -----------------------------------------------------------------------------
// CXnMenuAdapter::SetSoftKeyImageL
// 
// -----------------------------------------------------------------------------
//
void CXnMenuAdapter::SetSoftKeyImageL( const TAknsItemID& aId,
    const TDesC& aBmpFile,
    const TInt32 aBmp,
    const TInt32 aBmpM,
    XnMenuInterface::MXnMenuInterface::TSoftKeyPosition aPos, 
    TBool /*aEnable*/ )
    {
    CXnSoftkeyItem* softkey( NULL );

    switch( aPos )
        {
        case XnMenuInterface::MXnMenuInterface::ECenter:
            {
            softkey = SoftkeyItemL( CEikButtonGroupContainer::EMiddleSoftkeyPosition );           
            iUpdateMskAppearance = ETrue;
            break;
            }
        // Currently only MSK icon updating supported here
        case XnMenuInterface::MXnMenuInterface::ELeft:
        case XnMenuInterface::MXnMenuInterface::ERight:
        default:
            {
            break;
            }
        }

    if( softkey )
        {
        softkey->Reset();
        softkey->iImageOn = ETrue;

        // Save new icon data
        softkey->iBitmap = NULL;
        softkey->iMask = NULL;
        softkey->iPreserveAspectRatio = EFalse;
        softkey->iInvertMask = EFalse;
        softkey->iOwnBitmaps = ETrue;
        delete softkey->iBmpFile;
        softkey->iBmpFile = NULL;
        softkey->iBmpFile = aBmpFile.AllocL();
        softkey->iId.Set( aId );
        softkey->iBmp = aBmp;
        softkey->iBmpM = aBmpM;

        // Image set, mark node as dirty
        softkey->iNode->SetDirtyL();
        }
    }
#endif // MSK icon change

// -----------------------------------------------------------------------------
// CXnMenuAdapter::SetSoftKeyTextL
// 
// -----------------------------------------------------------------------------
//
void CXnMenuAdapter::SetSoftKeyTextL( const TDesC& aText, 
    XnMenuInterface::MXnMenuInterface::TSoftKeyPosition aPos )
    {       
    CXnSoftkeyItem* softkey(NULL);
    
    switch( aPos )
        {
        case XnMenuInterface::MXnMenuInterface::ELeft:
            softkey = SoftkeyItemL(CEikButtonGroupContainer::ELeftSoftkeyPosition);
            iUpdateLskAppearance = ETrue;
            break;
        case XnMenuInterface::MXnMenuInterface::ERight:
            softkey = SoftkeyItemL(CEikButtonGroupContainer::ERightSoftkeyPosition);
            iUpdateRskAppearance = ETrue;
            break;
        case XnMenuInterface::MXnMenuInterface::ECenter:  
            softkey = SoftkeyItemL(CEikButtonGroupContainer::EMiddleSoftkeyPosition);           
            iUpdateMskAppearance = ETrue;
            break;
        default:     
            break;
        }
    if(softkey)
        {
        softkey->Reset();
                                              
        softkey->iImageOn = EFalse;    
                                              
        softkey->iLabel = aText.AllocL();
        // Text set, mark parent as dirty
        softkey->iNode->SetDirtyL();
       }
    }

// -----------------------------------------------------------------------------
// CXnMenuAdapter::SetSoftKeyL
// 
// -----------------------------------------------------------------------------
//
void CXnMenuAdapter::SetSoftKeyL( CXnNodePluginIf* aSoftkeyNode, 
    XnMenuInterface::MXnMenuInterface::TSoftKeyPosition aPos )
    {

    CXnSoftkeyItem* item = AppendSoftkeyItemL(aSoftkeyNode);
    switch(aPos)
        {
        case XnMenuInterface::MXnMenuInterface::ELeft:
            if(item)
                {
                iVisibleLSK = item;
                }
            else
                {
                iVisibleLSK = NULL;                
                }
            iUpdateLskAppearance = ETrue;
            break;
        case XnMenuInterface::MXnMenuInterface::ECenter:
            if(item)
                {
                iVisibleMSK = item;
                }
            else
                {
                iVisibleMSK = NULL;                
                }
            iUpdateMskAppearance = ETrue;
            break;
        case XnMenuInterface::MXnMenuInterface::ERight:
            if(item)
                {
                iVisibleRSK = item;
                }
            else
                {
                iVisibleRSK = NULL;                
                }
            iUpdateRskAppearance = ETrue;
            break;
        }
    }

// -----------------------------------------------------------------------------
// CXnMenuAdapter::SoftKeyL
// 
// -----------------------------------------------------------------------------
//
CXnNodePluginIf* CXnMenuAdapter::SoftKeyL( XnMenuInterface::MXnMenuInterface::TSoftKeyPosition aPos )
    {
    CXnNodePluginIf* node(NULL);
    CXnSoftkeyItem* item = SoftkeyItemL(aPos);
    if(item)
        {
        node = item->iNode;
        }
    return node;
    }

// -----------------------------------------------------------------------------
// CXnMenuAdapter::HandleScreenDeviceChangedL
// 
// -----------------------------------------------------------------------------
//
void CXnMenuAdapter::HandleScreenDeviceChangedL()
    {
    CXnSoftkeyItem* left = 
        SoftkeyItemL(CEikButtonGroupContainer::ELeftSoftkeyPosition);
    
    CXnSoftkeyItem* middle = 
            SoftkeyItemL(CEikButtonGroupContainer::EMiddleSoftkeyPosition);
    CXnSoftkeyItem* right = 
            SoftkeyItemL(CEikButtonGroupContainer::ERightSoftkeyPosition);
            
    if(left && left->iImageOn)
        {
        iUpdateLskAppearance = ETrue;
        left->iNode->SetDirtyL();
        }
    if(right && right->iImageOn)
        {
        iUpdateRskAppearance = ETrue;
        right->iNode->SetDirtyL();
        }
    if(middle && middle->iImageOn)
        {
        iUpdateMskAppearance = ETrue;
        middle->iNode->SetDirtyL();
        }
    CXnControlAdapter::HandleScreenDeviceChangedL();
    } 
      
// -----------------------------------------------------------------------------
// CXnMenuAdapter::HandleMenuPropertyChangeL
// Change softkey appearance
// -----------------------------------------------------------------------------
//    
void CXnMenuAdapter::HandleMenuPropertyChangeL(CXnNodePluginIf* aNode, CXnProperty* aProperty)
    {
    if ( !aNode )
        {
        return;
        }
           
    const TDesC8& type( aNode->Type()->Type() ); 
    
    if ( type != softkey::KNodeName)
        {
        return;
        }
            
    // Find target softkey
    CXnSoftkeyItem* softkey( SoftkeyItemL( aNode ) );
        
    if ( !softkey )
        {
        return;
        }
    
    SetUpdateAppearanceL( softkey );  
    
    const TDesC8* name( &KNullDesC8() );
    
    if ( aProperty )
        {
        name = &aProperty->Property()->Name();
        }
    
    if ( *name == menu::KLabel )
       {             
       softkey->Reset();
       softkey->iImageOn = EFalse;    
       softkey->iLabel = aProperty->StringValueL();              
       }
    else if ( *name == style::common::KDisplay )
        {        
        if ( aProperty->StringValue() == XnPropertyNames::style::common::display::KNone )
            {
            if ( softkey->iPosition == CEikButtonGroupContainer::ELeftSoftkeyPosition ) 
                {
                EikSoftkeyImage::SetLabel( iContainer,ETrue );
                iContainer->SetCommandL( CEikButtonGroupContainer::ELeftSoftkeyPosition,KCBACommandFirst, KNullDesC );                
                }
            else if ( softkey->iPosition == CEikButtonGroupContainer::ERightSoftkeyPosition )
                {
                EikSoftkeyImage::SetLabel( iContainer,EFalse );
                iContainer->SetCommandL( CEikButtonGroupContainer::ERightSoftkeyPosition,KCBACommandSecond, KNullDesC );                
                }
            else if ( softkey->iPosition == CEikButtonGroupContainer::EMiddleSoftkeyPosition )
                {
                iContainer->SetCommandL( CEikButtonGroupContainer::EMiddleSoftkeyPosition,KCBACommandMiddle, KNullDesC );                
                }
            }
        }
    }    

// -----------------------------------------------------------------------------
// CXnMenuAdapter::SetObserver
// 
// -----------------------------------------------------------------------------
//    
void CXnMenuAdapter::SetObserver( XnMenuInterface::MXnMenuObserver& aObserver )   
    {
    iObserver = &aObserver;
    }

// -----------------------------------------------------------------------------
// CXnMenuAdapter::RemoveObserver
// 
// -----------------------------------------------------------------------------
//    
void CXnMenuAdapter::RemoveObserver()   
    {
    iObserver = NULL;
    }

// ---------------------------------------------------------------------------
// CXnMenuAdapter::FindSoftKeyNodeByPosition
// ---------------------------------------------------------------------------
//
TBool CXnMenuAdapter::FindSoftKeyNodeByPosition( 
    const TPoint& aPosition, 
    CXnNodePluginIf*& aNode )
    {
    CXnNodePluginIf* ret = FindSoftkeyItemByPosition(aPosition);
    aNode = ret;
    return (ret?ETrue:EFalse);
    }
// ---------------------------------------------------------------------------
// CXnMenuAdapter::ButtonTouchableRectByPosition
// Gets a CBA button rectangle. Touchable are is larger than controls rect
// ---------------------------------------------------------------------------
//
TRect CXnMenuAdapter::ButtonTouchableRectByPosition( TInt aPosition)
    {
    TRect rect( 0, 0, 0, 0 );
    
    TRect button1Rect( 0, 0, 0, 0 );
    TRect button2Rect( 0, 0, 0, 0 );
    TRect buttonMSKRect( 0, 0, 0, 0 );
     
    // In touch layouts the button areas are read from the
    // layout data because they are larger than the actual
    // control size.
#ifndef _AVKON_CBA_LSC
    CCoeControl* container = iContainer->ButtonGroup()->AsControl();
    TRect containerRect(container->PositionRelativeToScreen(),container->Size());
    TAknLayoutRect layoutRect;
    layoutRect.LayoutRect(
        containerRect,
        AknLayoutScalable_Avkon::control_pane_g6( 0 ).LayoutLine() );
    button1Rect = layoutRect.Rect();
    
    layoutRect.LayoutRect(
        containerRect,
        AknLayoutScalable_Avkon::control_pane_g8( 0 ).LayoutLine() );
    button2Rect = layoutRect.Rect();

    layoutRect.LayoutRect(
        containerRect,
        AknLayoutScalable_Avkon::control_pane_g7( 0 ).LayoutLine() );
    buttonMSKRect = layoutRect.Rect();
#else           
    if ( Layout_Meta_Data::IsLandscapeOrientation() )
        {
        button1Rect = SoftkeyRectTopTouch();
        button2Rect= SoftkeyRectBottomTouch();
        
        }
    else // portrait
        {
        button1Rect = SoftkeyRectLeftTouch();
        button2Rect = SoftkeyRectRightTouch();
        }
#endif
    
    switch ( aPosition )
        {
        case CEikButtonGroupContainer::ELeftSoftkeyPosition:
            {
            rect = button1Rect;
            break;
            }

        case CEikButtonGroupContainer::ERightSoftkeyPosition:
            {
            rect = button2Rect;
            break;
            }

        case CEikButtonGroupContainer::EMiddleSoftkeyPosition:
            {
            rect = buttonMSKRect;
            break;
            }

        default:
            {
            break;
            }
        }
        
        
    return rect;
    }

// ---------------------------------------------------------------------------
// CXnMenuAdapter::FindSoftkeyNodeL
// ---------------------------------------------------------------------------
//
CXnNodePluginIf* CXnMenuAdapter::FindSoftkeyNodeL(const TDesC8& aNodeType)
    {
    CXnNodePluginIf* ret(0);
    
    RPointerArray< CXnNodePluginIf > children( iRootNode->ChildrenL() );
    CleanupClosePushL( children );
    for(TInt i=0;i<children.Count();++i)
        {
        if(children[i]->Type()->Type() == XnPropertyNames::softkey::KNodeName)
            {
            if( SoftkeyPlaceL(*children[i]) == aNodeType 
                && IsNodeVisibleL( *children[i]) )
                {
                ret = children[i];
                break;
                }
            
            }
        }
    CleanupStack::PopAndDestroy( &children );
    return ret;
    }

// ---------------------------------------------------------------------------
// CXnMenuAdapter::UpdateSoftkeyAppearancesL
// ---------------------------------------------------------------------------
//
void CXnMenuAdapter::UpdateSoftkeyAppearancesL()
    {
    
    if(iUpdateLskAppearance)
        {
        CXnSoftkeyItem* left = 
            SoftkeyItemL(CEikButtonGroupContainer::ELeftSoftkeyPosition);
        if( left )
            {
            SetSoftkeyAppearanceL(*left);
            }
        iUpdateLskAppearance = EFalse;
        }
    if(iUpdateRskAppearance)
        {
        CXnSoftkeyItem* right = 
            SoftkeyItemL(CEikButtonGroupContainer::ERightSoftkeyPosition);
        if(right)
            {
            SetSoftkeyAppearanceL(*right);            
            }
        iUpdateRskAppearance = EFalse;
        }
    if(iUpdateMskAppearance)
        {
        CXnSoftkeyItem* middle = 
            SoftkeyItemL(CEikButtonGroupContainer::EMiddleSoftkeyPosition);
        if(middle)
            {
            SetSoftkeyAppearanceL(*middle);                
            }
        iUpdateMskAppearance = EFalse;
        }
    }
// ---------------------------------------------------------------------------
// CXnMenuAdapter::ChangeSoftkeyImageL
// ---------------------------------------------------------------------------
//
void CXnMenuAdapter::ChangeSoftkeyImageL(const CXnSoftkeyItem& aSoftkey)
    {
#if 0 // MSK icon change
    if ( aSoftkey.iPosition == CEikButtonGroupContainer::ELeftSoftkeyPosition || 
            aSoftkey.iPosition == CEikButtonGroupContainer::ERightSoftkeyPosition )
        {
#endif // MSK icon change
        TSize size;
        if(AknLayoutUtils::PenEnabled())
            {
            size = SoftkeyImageRect(*iContainer,aSoftkey.iPosition).Size();
            }
        else
            {
            size = SoftkeyRectL( *iContainer,aSoftkey.iPosition, aSoftkey.iImageOn ).Size();
            }

        CEikImage* image( PrepareSoftkeyImageL( aSoftkey, size ) );
        TBool left(ETrue);

        if(aSoftkey.iPosition != CEikButtonGroupContainer::ELeftSoftkeyPosition)
            {
            left = EFalse;
            }
        EikSoftkeyImage::SetImage( iContainer, *image, left );                        
#if 0 // MSK icon change
        }
    else if ( aSoftkey.iBmpFile )
        {
        CEikCba* cba = static_cast< CEikCba* >( iContainer->ButtonGroup() );
        // use iAvkonAppUi
        CAknAppUi* appUi = static_cast<CAknAppUi*>( CEikonEnv::Static()->AppUi() );
        cba->UpdateMSKIconL(
                aSoftkey.iId,
                aSoftkey.iBmpFile->Des(),
                aSoftkey.iBmp,
                aSoftkey.iBmpM,
                ETrue );
        cba->DrawNow();
        }
#endif // MSK icon change
    }

// ---------------------------------------------------------------------------
// CXnMenuAdapter::AddItemsToMenuPaneL
// ---------------------------------------------------------------------------
//
void CXnMenuAdapter::AddItemsToMenuPaneL(CEikMenuPane* aMenuPane, TInt aResourceId)
    {   
   TInt parentIndexForNotification( 0 );
   
   for ( TInt i = 0; i< iMenuItems.Count(); i++ )
       {
       // find items belong to this pane
       TInt parent( iMenuItems[i].iParentIndex );
       
       if ( parent >= 0 )
           {
           TInt cid( iMenuItems[parent].iData.iCascadeId );
           
           if ( cid == aResourceId )
               {
               if ( parent > 0 )
                   {
                   parentIndexForNotification = parent;
                   break;
                   }
               }
           }
       }
   
   TBool selectionEnabled( EFalse );
   TBool isRadio( EFalse );            
   
   if ( parentIndexForNotification != 0 )
       {
       CXnNodePluginIf* node( iMenuItems[parentIndexForNotification].iNode );
       
       CXnProperty* property( node->GetPropertyL( _L8( "selectiontype" ) ) );
       
       if ( property && property->StringValue() == _L8( "multi" ) )
           {
           selectionEnabled = ETrue;
           }
       else if ( property && property->StringValue() == _L8( "single" ) )
           {
           selectionEnabled = ETrue;
           isRadio = ETrue;
           }
           
       node->SetStateL( XnPropertyNames::style::common::KActive );
       node->UnsetStateL( XnPropertyNames::style::common::KActive );
       }
       
   PopulateMenuL();        
   
   for ( TInt i = 0; i< iMenuItems.Count(); i++ )
       {
       // find items belong to this pane
       TInt parent( iMenuItems[i].iParentIndex );
       
       if ( parent >= 0 )
           {
           TInt cid( iMenuItems[parent].iData.iCascadeId );
           
           if ( cid == aResourceId )
               {
               if ( selectionEnabled )
                   {
                   if ( !isRadio )
                       {
                       iMenuItems[i].iData.iFlags |= 
                           EEikMenuItemCheckBox;
                       }
                   else
                       {
                       iMenuItems[i].iData.iFlags |= 
                           EEikMenuItemRadioStart|
                           EEikMenuItemRadioMiddle|
                           EEikMenuItemRadioEnd;
                       }
                   }
                   
               aMenuPane->AddMenuItemL( iMenuItems[i].iData );
               
               if ( selectionEnabled )
                   {
                   CXnProperty* property( 
                       iMenuItems[i].iNode->GetPropertyL( XnPropertyNames::menu::KChecked ) );                           
                   
                   if ( property && property->StringValue() == XnPropertyNames::KTrue )
                       {
                       aMenuPane->SetItemButtonState(
                           iMenuItems[i].iData.iCommandId, EEikMenuItemSymbolOn );                                         
                       }
                   }
               }
           }
       } // for end      
    }

// ---------------------------------------------------------------------------
// CXnMenuAdapter::AppendSoftkeyItemL
// ---------------------------------------------------------------------------
//
CXnSoftkeyItem* CXnMenuAdapter::AppendSoftkeyItemL(CXnNodePluginIf* aNode)
    {
    if(!aNode)
        {
        return NULL;
        }
    CXnProperty* property = 
        aNode->GetPropertyL( XnPropertyNames::softkey::KTypeAttribute );     
    if(!property)
        {
        return NULL;
        }
    const TDesC8& skType = property->StringValue();
    if( skType != XnPropertyNames::softkey::type::KRight &&
        skType != XnPropertyNames::softkey::type::KLeft &&
        skType != XnPropertyNames::softkey::type::KMiddle )
        {
        return NULL;
        }
    for( TInt i=0; i<iSoftkeyItems.Count(); i++ )
        {
        if( iSoftkeyItems[i]->iNode == aNode )
            {
            return iSoftkeyItems[i];
            }
        }        
    CXnSoftkeyItem* softkey(0);
    softkey = new (ELeave) CXnSoftkeyItem;
    CleanupStack::PushL(softkey);
    
    if ( skType == XnPropertyNames::softkey::type::KRight )
       {
       softkey->iPosition = CEikButtonGroupContainer::ERightSoftkeyPosition;
       softkey->iCommandId = KCBACommandSecond;
       }
    else if ( skType == XnPropertyNames::softkey::type::KLeft )
       {
       softkey->iPosition = CEikButtonGroupContainer::ELeftSoftkeyPosition;
       softkey->iCommandId = KCBACommandFirst;
       }
    else 
        {
        softkey->iPosition = CEikButtonGroupContainer::EMiddleSoftkeyPosition;
        softkey->iCommandId = KCBACommandMiddle;
        }

    softkey->iNode = aNode;
    
    CXnProperty* labelProp( aNode->LabelL() );
    CXnProperty* targetProp( aNode->GetPropertyL(KXnTarget) );

    if(labelProp)
       {
       softkey->iImageOn = EFalse;
       softkey->iLabel = labelProp->StringValueL();
       }
    else if(targetProp)
        {
        softkey->iImageOn = EFalse;
        softkey->iLabel = FindSoftkeyLabelL(aNode);        
        }
#if 0 // MSK icon change
    else
       {
       InitSoftkeyItemImageL( *softkey );
       }
#else // MSK icon change
    else if(softkey->iPosition != CEikButtonGroupContainer::EMiddleSoftkeyPosition)
       { // we can't set own image to middle softkey
       InitSoftkeyItemImageL( *softkey );
       }
#endif // MSK icon change
    softkey->iUpdateAppearance = ETrue;
    iSoftkeyItems.AppendL(softkey);
    CleanupStack::Pop(softkey);
    return softkey;
    }
// ---------------------------------------------------------------------------
// CXnMenuAdapter::SoftkeyPlaceL
// ---------------------------------------------------------------------------
//
const TDesC8& CXnMenuAdapter::SoftkeyPlaceL(CXnNodePluginIf& aNode)
    {
    CXnProperty* property = 
        aNode.GetPropertyL( XnPropertyNames::softkey::KTypeAttribute );                           
                      
    if( property)
        {
        return property->StringValue();
        }
    return KNullDesC8;                  
    
    }

// -----------------------------------------------------------------------------
// CXnMenuAdapter::FindSoftkeyItemByPosition
// 
// -----------------------------------------------------------------------------
CXnNodePluginIf* CXnMenuAdapter::FindSoftkeyItemByPosition( const TPoint& aPosition )
    {
    CXnNodePluginIf* softkey(0);            
    TRAP_IGNORE( softkey = DoFindSoftkeyItemByPositionL( aPosition ) );    
    return softkey;
    }
    
// -----------------------------------------------------------------------------
// CXnMenuAdapter::DoFindSoftkeyItemByPositionL
// 
// -----------------------------------------------------------------------------
CXnNodePluginIf* CXnMenuAdapter::DoFindSoftkeyItemByPositionL( const TPoint& aPosition )
    {            
    TRect lsk( ButtonTouchableRectByPosition(CEikButtonGroupContainer::ELeftSoftkeyPosition) );
    TRect rsk( ButtonTouchableRectByPosition(CEikButtonGroupContainer::ERightSoftkeyPosition) );
    TRect msk( ButtonTouchableRectByPosition(CEikButtonGroupContainer::EMiddleSoftkeyPosition) );
    
    CXnNodePluginIf* softkey(NULL);
    CXnSoftkeyItem* item(NULL);
    if ( lsk.Contains(aPosition) )
        {
        item = SoftkeyItemL(CEikButtonGroupContainer::ELeftSoftkeyPosition);
        }
    else if(msk.Contains(aPosition))
        {
        item = SoftkeyItemL(CEikButtonGroupContainer::EMiddleSoftkeyPosition);
        }
    else if( rsk.Contains(aPosition) )
        {
        item = SoftkeyItemL(CEikButtonGroupContainer::ERightSoftkeyPosition);
        }
    if(item)
        {
        softkey = item->iNode;
        }        
    return softkey;
    }

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
CXnSoftkeyItem* CXnMenuAdapter::SoftkeyItemL(TInt aPosition)
    {
    CXnSoftkeyItem* softkeyItem(0);
    if(iVisibleLSK && aPosition == CEikButtonGroupContainer::ELeftSoftkeyPosition)
        {
        return iVisibleLSK;
        }
    else if(iVisibleRSK && aPosition == CEikButtonGroupContainer::ERightSoftkeyPosition)
        {
        return iVisibleRSK;
        }
    else if(iVisibleMSK && aPosition == CEikButtonGroupContainer::EMiddleSoftkeyPosition)
        {
        return iVisibleMSK;
        }

    // return default
    for(TInt i=0;i<iSoftkeyItems.Count();++i)
        {
        softkeyItem = iSoftkeyItems[i];
        if(softkeyItem->iPosition == aPosition &&
           softkeyItem->iDefault && 
           IsNodeVisibleL(*softkeyItem->iNode))
            {
            return softkeyItem; 
            }
        }
    return NULL;
    }

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
CXnSoftkeyItem* CXnMenuAdapter::SoftkeyItemL(CXnNodePluginIf* aNode)
    {
    CXnSoftkeyItem* softkeyItem(0);
    for(TInt i=0;i<iSoftkeyItems.Count();++i)
       {
       softkeyItem = iSoftkeyItems[i];
       if(softkeyItem->iNode == aNode)
           {
           return softkeyItem; 
           }
       }
    return NULL;
    }

CXnSoftkeyItem* CXnMenuAdapter::SoftkeyItemL(CXnNodeAppIf* aNode)
    {
    CXnSoftkeyItem* softkeyItem(0);
    for(TInt i=0;i<iSoftkeyItems.Count();++i)
       {
       softkeyItem = iSoftkeyItems[i];
       if(&(softkeyItem->iNode->AppIfL()) == aNode)
           {
           return softkeyItem; 
           }
       }
    return NULL;
    }
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------

void CXnMenuAdapter::SetUpdateAppearanceL(CXnSoftkeyItem* aItem)
    {
    if ( aItem && IsNodeVisibleL( *aItem->iNode ) )
        {
        aItem->iNode->SetDirtyL();
                
        switch ( aItem->iPosition )
            {
            case CEikButtonGroupContainer::ELeftSoftkeyPosition:
                iUpdateLskAppearance = ETrue;
                iVisibleLSK = NULL;
                break;
            case CEikButtonGroupContainer::EMiddleSoftkeyPosition:
                iUpdateMskAppearance = ETrue;
                iVisibleMSK = NULL;
                break;
            case CEikButtonGroupContainer::ERightSoftkeyPosition:
                iUpdateRskAppearance = ETrue;
                iVisibleRSK = NULL;
                break;
            }
        }
    }

// -----------------------------------------------------------------------------
// CXnMenuAdapter::FindWidgetMenuItemL
// 
// -----------------------------------------------------------------------------
CXnNodePluginIf* CXnMenuAdapter::FindWidgetMenuItemL( CXnNodePluginIf* aNode )
    {    
    CXnNodePluginIf* focusedNode( iUiEngine->FocusedNodeL() );

    CXnNodePluginIf* menuItem( NULL );
    
    if ( focusedNode && aNode )
        {
        // Get <plugin> element
        CXnNodePluginIf& pluginNode( iUiEngine->PluginNodeL( focusedNode ) );
        
        RPointerArray< CXnNodePluginIf > children( pluginNode.ChildrenL() );
        CleanupClosePushL( children );
        
        CXnNodePluginIf* widgetExtNode( NULL );
        
        if( children.Count() > 0 )
            {
            // children[0] must be <widget> element
            widgetExtNode = FindChildL( *children[0], KXnMenuExtension );
            }
                                                 
        if( !widgetExtNode )
            {
            widgetExtNode = focusedNode;
            }
        
        if ( widgetExtNode )
            {
            CXnProperty* prop( aNode->GetPropertyL( KXnSource ) );
            
            if ( prop )
                {
                const TDesC8& source( prop->StringValue() );
                
                // Try to find <menuitem>
                menuItem = FindChildL( *widgetExtNode, 
                                       KXnMenuItem, 
                                       source );
                
                if ( !menuItem )
                    {
                    // Try to find <dynmenuitem>
                    menuItem = FindChildL( *widgetExtNode, 
                                           KXnDynMenuItem, 
                                           source );
                    }
                }
            }
        
        CleanupStack::PopAndDestroy( &children );
        }
    
    if( menuItem && IsNodeVisibleL( *menuItem ) )
        {
        return menuItem;    
        }
    
    return NULL;
    }

// -----------------------------------------------------------------------------
// CXnMenuAdapter::FindSoftkeyLabelL
// 
// -----------------------------------------------------------------------------
HBufC* CXnMenuAdapter::FindSoftkeyLabelL( CXnNodePluginIf* aNode )
    {
    if( !aNode )
        {
        return NULL;
        }
    
    CXnProperty* targerProp( aNode->GetPropertyL( KXnTarget ) );
    
    if ( targerProp && iRootNode )
        {
        CXnNodePluginIf* widgetSoftkeyNode( 
                FindChildL( *iRootNode,               
                            KXnWidgetSoftkey, 
                            targerProp->StringValue() ) ); 
                          
        if ( widgetSoftkeyNode )
            {
            CXnProperty* label( widgetSoftkeyNode->LabelL() );
            
            if( label )
                {
                return label->StringValueL();
                }
            }
        }
    
    return NULL;;
    }

//end of file