/*
* Copyright (c) 2002-2006 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:  Volume editor class
*
*/


// INCLUDE FILES
#include "Aknvolumecontrol.h"
#include <gulicon.h>
#include <AknPanic.h>
#include <AknNaviObserver.h>
#include <AknUtils.h>
#include <barsread.h>
#include <AknStatuspaneUtils.h>
#include <aknnavide.h>
#include <AknsDrawUtils.h>
#include <AknsFrameBackgroundControlContext.h>
#include <aknappui.h>
#include <aknconsts.h>
#include <aknlayoutscalable_avkon.cdl.h>
#include <skinlayout.cdl.h>
#include <avkon.mbg>
#include <AknVolumePopup.h>

#include <AknTasHook.h>
#include <touchfeedback.h>
#include <aknlayoutscalable_apps.cdl.h>
// CONSTANTS
const TInt KVolumeMinValue  = 1;
const TInt KVolumeMaxValue  = 10;
const TInt KVolumeLevels    = 10;

const TInt KVolumeButtonDown        = 0x01;
const TInt KVolumeNaviPaneMuted     = 0x02;
const TInt KVolumeStepChange        = 0x04;
const TInt KVolumeLevelNotFound     = 0;
const TInt KVolumeLevelMuteTapped   = 2000;

const TInt KVolumeNaviPaneMutedValue = 0;

// Define the loaded icon types - this affects drawing.
const TInt KGfxModeNotLoaded    = 0;
const TInt KGfxModeNew          = 1;// 1 slider type icon (+mask)
const TInt KGfxModeOld          = 2;// 10 ball icons, one for each volume level (+masks)
const TInt KScrollRepeatTimeout = 250000; // 0.25 seconds
// ----------------------------------------------------------------------------
// Extension class
//
// ----------------------------------------------------------------------------
//
NONSHARABLE_CLASS(CVolumeExtension) : public CBase
    {
    public:
        CVolumeExtension();
        ~CVolumeExtension();

        // Methods for svg drawing
        static TBool UseSvgDrawing();
        void DeleteBitmaps();
        void SetIconSizes( TInt aStyle, const TRect& aParent ) const;

        void LoadBitmapsL( TInt aStyle, const TRect& aParent );
        
        // Sub-methods used by LoadBitmapsL
        void TryLoadBitmapsSkinnedL( MAknsSkinInstance* aSkin );
        void TryLoadBitmapsDefaultLargeL( MAknsSkinInstance* aSkin );
        void TryLoadBitmapsDefaultSmallL( MAknsSkinInstance* aSkin );
        void TryLoadBitmapsNoSkinL();
        
        void CalculateParentRect( TInt aStyle, const TRect& aParent );
        void DrawSvgSmallVolume( TInt aStyle, const TRect& aRect,
                                CBitmapContext& aGc, TInt aValue );
        void DrawSvgSettingsVolume( const TRect& aRect,
                                CWindowGc& aGc, TInt aValue );
        static void CreateSvgSettingsIconL( const TRect& aRect,
                                            TInt aValue, 
                                            CGulIcon* aIcon );
        static void CreateDynRangeStyleSettingsIconL( const TRect& aRect,
                                            TInt aValue, 
                                            CGulIcon* aIcon,
                                            TInt aMinimum,
                                            TInt aMaximum );                                   
                                            
        void DrawSvgSettingsIconL( const TRect& aRect,
                                    TInt aValue,
                                    CGulIcon* aIcon );
        void DrawDynRangeStyleSettingsIconL( const TRect& aRect,
                                    TInt aValue,
                                    CGulIcon* aIcon,
                                    TInt aMinimum, 
                                    TInt aMaximum );
                                    
        TInt GetVolumeLevelByPosition( const TInt& aStyle,
                                       const TPoint& aPoint,
                                       const TRect& aAreaRect ) const;

        TRect RectFromLayout( const TRect& aParent,
                              const TAknWindowComponentLayout& aComponentLayout
                            ) const;

        CFbsBitmap* iActiveIcons[KVolumeLevels];
        CFbsBitmap* iInActiveIcons[KVolumeLevels];
        CFbsBitmap* iActiveMasks[KVolumeLevels];
        CFbsBitmap* iInActiveMasks[KVolumeLevels];

        TRect iParentRect;  // Volume indicator area
        TRect iMuteRect; // Mute indicator rect for tapping 

        TRect iVolumeLevels[ KVolumeLevels ]; // Deprecated
        TInt iFlags;

        // Volume icons will be loaded the first time they are drawn,
        // not when the control is constructed.
        TBool iHasBeenDrawn;
        TFileName iBmpFilename;
        TInt iBmpId;
        TInt iBmpMask;

        CPeriodic* iTimer;
        TInt iEffectTimerCount;
        TInt iAnimatedEffectValue;
        
        TInt iStoredLevel;
        
        // For hi-res volume control implementation
        TInt iMinimumValue;
        TInt iMaximumValue;
        TInt iGfxMode; // Defines which icons are loaded when drawing
        TInt iOldScaleSettingVolume; // for 9 step setting volume
        
        /**
        * Flag to define whether or not this control is topmost on the navi pane's
        * control stack.
        */
        TBool iIsOnNaviStack;
        TInt iOldLevel;
        TBool iReduce;        
        
        TBool iNoDraw;        
        TBool iGrabPoint;

       /**
        * Extended touch area used 
        */
        TBool iUseExtendedTouchArea;
        
       /**
        * Touch area 
        */        
        TRect iTouchArea;
    };

// ----------------------------------------------------------------------------
// CAknVolumeControl::CAknVolumeControl()
// Default constructor.
// ----------------------------------------------------------------------------
//
EXPORT_C CAknVolumeControl::CAknVolumeControl()
    {
    AKNTASHOOK_ADD( this, "CAknVolumeControl" );
    }

// ----------------------------------------------------------------------------
// CAknVolumeControl::~CAknVolumeControl()
// Destructor.
// ----------------------------------------------------------------------------
//
EXPORT_C CAknVolumeControl::~CAknVolumeControl()
    {
    AKNTASHOOK_REMOVE();
    AknsUtils::DeregisterControlPosition( this );
    delete iBitmap;
    delete iMaskBitmap;
    delete iExtension;
    }

// ----------------------------------------------------------------------------
// CAknVolumeControl::SetValue(TInt aValue)
// Sets the value.
// ----------------------------------------------------------------------------
//
EXPORT_C void CAknVolumeControl::SetValue( TInt aValue )
    {
    // NOTE: In settings page layouts (EDynRangeSettingsVolumeControl) 
    // using dynamic min and max values defined in the resource file. The 
    // values cannot be checked in SetValue() because SetValue() is called 
    // before ConstructFromResource() which actually reads the min and max 
    // values as well as the default value even though it is also given in 
    // the settings page constructor parameter.
    //
    if ( !iExtension )
        {
        return;
        }
    
    TBool valueChanged( aValue != iValue );
    
    switch( iStyle )
        {
        case EDynRangeSettingsVolumeControl:
        case EDynRangeNaviPaneVolumeControl:
            // Do not check EDynRangeSettingsVolumeControl because it's value 
            // might be set before the actual min and max are read from the 
            // resource (settings page feature).
            // Navi pane's EDynRangeNaviPaneVolumeControl is also ignored.
            break;
        default:
            __ASSERT_DEBUG( aValue >= iExtension->iMinimumValue && 
                            aValue <= iExtension->iMaximumValue, 
                            Panic( EAknPanicOutOfRange ) );
        }
    
    iValue = aValue;

    if ( iExtension )
        {
        iExtension->iFlags &= ~KVolumeNaviPaneMuted;
        }

    if ( iStyle == ENaviPaneVolumeControl || 
         iStyle == EDynRangeNaviPaneVolumeControl )
        {
        TInt event = MAknNavigationObserver::ENaviEventHandleNavigation;
        if ( iValue <= iExtension->iMinimumValue )
            {
            event=MAknNavigationObserver::ENaviEventLeftMostItemReached;
            if ( iValue == iExtension->iMinimumValue )
                {
                iExtension->iFlags |= KVolumeNaviPaneMuted;
                }
            }
        else if ( iExtension->iMaximumValue == iValue )
            {
            event = MAknNavigationObserver::ENaviEventRightMostItemReached;
            }
        
        TRAP_IGNORE(
            ReportEventL(
                STATIC_CAST( MCoeControlObserver::TCoeEvent, event ) ) );

        if ( valueChanged )
            {
            TRAP_IGNORE(
                ReportEventL(
                    MCoeControlObserver::EEventStateChanged ) );
            }

        SetVolumeLayout( iStyle );
        if ( !iExtension->iNoDraw )
            {
            DrawNow();    
            }        
        
        // Volume popup is used instead of navi pane volume control,
        // pass the new value also to the popup.
        CAknVolumePopup* parent = static_cast<CAknVolumePopup*> ( Parent() );
        if ( parent && parent->ComponentControl( 5 ) == this )
            {
            if ( valueChanged )
                {
                parent->SetValue( aValue );
                }

            if ( iExtension->iIsOnNaviStack && ( valueChanged ||
                aValue == iExtension->iMinimumValue ||
                aValue == iExtension->iMaximumValue ) )
                {
                // Show the popup only if status pane is visible
                // to maintain same kind of functionality as in
                // navi pane volume control.
                CEikStatusPaneBase* sp = CEikStatusPaneBase::Current();
                if ( sp && sp->IsVisible() )
                    {
                    TRAP_IGNORE( parent->ShowVolumePopupL() );
                    }
                }
            }
        }
    }

// ----------------------------------------------------------------------------
// CAknVolumeControl::Value() const
// Returns the value.
// ----------------------------------------------------------------------------
//
EXPORT_C TInt CAknVolumeControl::Value() const
    {
    return iValue;
    }

// ----------------------------------------------------------------------------
// CAknVolumeControl::SetRange()
//
// ----------------------------------------------------------------------------
//
EXPORT_C void CAknVolumeControl::SetRange( TInt aMinimumValue, 
                                           TInt aMaximumValue )
    {
    TBool rangeChanged( aMinimumValue != iExtension->iMinimumValue ||
                        aMaximumValue != iExtension->iMaximumValue );
    
    __ASSERT_DEBUG( aMinimumValue < aMaximumValue, 
                     Panic( EAknPanicInvalidValue ) );
    if ( iExtension )
        {
        iExtension->iMinimumValue = aMinimumValue;
        iExtension->iMaximumValue = aMaximumValue;
        }
        
    // disable old volume control scaling
    if(iExtension->iOldScaleSettingVolume)
        {
        iExtension->iOldScaleSettingVolume = EFalse;
        }
        
    if ( iExtension->iIsOnNaviStack )
        {
        // Volume popup is used instead of navi pane volume control,
        // pass the new range also to the popup.
        CAknVolumePopup* parent = static_cast<CAknVolumePopup*> ( Parent() );

        if ( parent && parent->ComponentControl( 5 ) == this )
            {
            if ( rangeChanged )
                {
                parent->SetRange( aMinimumValue, aMaximumValue );
                }
            }
        }
    }

// ----------------------------------------------------------------------------
// CAknVolumeControl::GetRange()
//
// ----------------------------------------------------------------------------
//
EXPORT_C void CAknVolumeControl::GetRange( TInt& aMinimumValue, 
                                           TInt& aMaximumValue )
    {
    if ( iExtension )
        {
        aMinimumValue = iExtension->iMinimumValue;
        aMaximumValue = iExtension->iMaximumValue;
        }
    }

// ----------------------------------------------------------------------------
// CAknVolumeControl::CreateBitmapL()
//
// ----------------------------------------------------------------------------
//
EXPORT_C CFbsBitmap* CAknVolumeControl::CreateBitmapL(TInt aValue)
    {
    CGulIcon* icon = 
            CreateSetStyleListBoxIconL( aValue ); // now have ownership
    icon->SetBitmapsOwnedExternally( ETrue );
    CFbsBitmap* bitmap = icon->Bitmap();
    CFbsBitmap* mask = icon->Mask();
    delete icon;
    delete mask;
    return bitmap; // Ownership transferred
    }

// ----------------------------------------------------------------------------
// CAknVolumeControl::CreateSetStyleListBoxIconL()
// Draw volume control in setting list item
// ----------------------------------------------------------------------------
//
EXPORT_C CGulIcon* CAknVolumeControl::CreateSetStyleListBoxIconL( TInt aValue )
    {
    
    // Make the icon and put it in the array
    CGulIcon* icon = CGulIcon::NewLC();

    TRect origin;
    AknLayoutUtils::LayoutMetricsRect( AknLayoutUtils::EMainPane, origin );

    TAknLayoutRect layoutRect;
    layoutRect.LayoutRect(origin,
                    AknLayoutScalable_Avkon::listscroll_gen_pane(0));
    layoutRect.LayoutRect(layoutRect.Rect(),
                    AknLayoutScalable_Avkon::list_gen_pane(0));
    layoutRect.LayoutRect(layoutRect.Rect(),
                    AknLayoutScalable_Avkon::list_setting_number_pane(0));
    layoutRect.LayoutRect(layoutRect.Rect(),
                    AknLayoutScalable_Avkon::set_value_pane(0));
    layoutRect.LayoutRect(layoutRect.Rect(),
                    AknLayoutScalable_Avkon::volume_small_pane_cp());
    TRect rect(layoutRect.Rect());

    // Move to 0,0
    rect.Move(-rect.iTl.iX,-rect.iTl.iY);

    CVolumeExtension::CreateSvgSettingsIconL( rect, aValue, icon );

    CleanupStack::Pop( icon ); // icon - not owned anymore, do not destroy

    return icon; // Ownership transferred
    }

// ----------------------------------------------------------------------------
// CAknVolumeControl::CreateScalableListBoxIconL()
// Draw a scalable volume control in setting list item
// ----------------------------------------------------------------------------
//
EXPORT_C CGulIcon* CAknVolumeControl::CreateSetDynRangeStyleListBoxIconL( 
                                                                 TInt aValue,
                                                                 TInt aMinimum,
                                                                 TInt aMaximum )
    {
    
    
    // Make the icon and put it in the array
    CGulIcon* icon = CGulIcon::NewLC();

    TRect origin;
    AknLayoutUtils::LayoutMetricsRect( AknLayoutUtils::EMainPane, origin );

    TAknLayoutRect layoutRect;
    layoutRect.LayoutRect(origin,
                    AknLayoutScalable_Avkon::listscroll_gen_pane(0));
    layoutRect.LayoutRect(layoutRect.Rect(),
                    AknLayoutScalable_Avkon::list_gen_pane(0));
    layoutRect.LayoutRect(layoutRect.Rect(),
                    AknLayoutScalable_Avkon::list_setting_number_pane(0));
    layoutRect.LayoutRect(layoutRect.Rect(),
                    AknLayoutScalable_Avkon::set_value_pane(0));
    layoutRect.LayoutRect(layoutRect.Rect(),
                    AknLayoutScalable_Avkon::volume_small_pane_cp());
    TRect rect(layoutRect.Rect());

    // Move to 0,0
    rect.Move(-rect.iTl.iX,-rect.iTl.iY);

    CVolumeExtension::CreateDynRangeStyleSettingsIconL( rect, aValue, icon, 
                                                        aMinimum, aMaximum );

    CleanupStack::Pop( icon ); // icon - not owned anymore, do not destroy

    return icon; // Ownership transferred
    }
  
    
// ----------------------------------------------------------------------------
// CAknVolumeControl::HandleNaviStackChange()
// ----------------------------------------------------------------------------
//    
void CAknVolumeControl::HandleNaviStackChange( TBool aIsOnNaviStack )
    {
    if ( iExtension )
        {
        iExtension->iIsOnNaviStack = aIsOnNaviStack;
        }
    }
    
    
// ----------------------------------------------------------------------------
// CAknVolumeControl::MinimumSize()
// Returns the size.
// ----------------------------------------------------------------------------
//
TSize CAknVolumeControl::MinimumSize()
    {
    TAknLayoutRect layout;
    if ( iStyle == ENaviPaneVolumeControl )
        {
        if ( AknStatuspaneUtils::SmallLayoutActive() )
            {
            layout.LayoutRect( Rect(),
                        AknLayoutScalable_Avkon::volume_small2_pane() );        
            }
        else
            {
            layout.LayoutRect( Rect(),
                        AknLayoutScalable_Avkon::volume_small_pane() );        
            }
        
        return layout.Rect().Size();
        }
    else // Setting Page & Popup volume control
        {
        return Rect().Size();
        }
    }

// ----------------------------------------------------------------------------
// CAknVolumeControl::OfferKeyEventL
// Handles the key events.
// ----------------------------------------------------------------------------
//
TKeyResponse CAknVolumeControl::OfferKeyEventL( const TKeyEvent& aKeyEvent,
                                                TEventCode aType )
    {
    if ( aType == EEventKey )
        {
        TInt volumeValue = Value();
        switch( aKeyEvent.iCode )
            {
            case EKeyLeftArrow:
                {
                if (volumeValue > iExtension->iMinimumValue)
                    {
                    volumeValue--;
                    SetValue( volumeValue );
                    if ( iStyle != EDynRangePopupVolumeControl &&
                         !iExtension->iNoDraw )
                        {                        
                        DrawNow();
                        }
                    ReportEventL( MCoeControlObserver::EEventStateChanged );
                    }
                else
                    {
                    CAknVolumePopup* parent =
                        static_cast<CAknVolumePopup*> ( Parent() );
                    if ( iExtension &&
                         iExtension->iIsOnNaviStack &&
                         parent &&
                         parent->ComponentControl( 5 ) == this )
                        {
                        // Show the volume popup even if volume level is not changed
                        // to indicate that a volume adjustment key event has been
                        // received.
                        CEikStatusPaneBase* sp = CEikStatusPaneBase::Current();
                        if ( sp && sp->IsVisible() )
                            {
                            // Show the popup only if status pane is visible
                            // to maintain same kind of functionality as in
                            // navi pane volume control.
                            parent->ShowVolumePopupL();
                            }
                        }
                        
                    if ( iStyle != ESettingsVolumeControl )
                        {
                        TInt event = MAknNavigationObserver::ENaviEventLeftMostItemReached;
                        ReportEventL( 
                            STATIC_CAST( MCoeControlObserver::TCoeEvent, event ) );
                        }
#ifdef RD_ANIMATION_EFFECTS
                    else if (iExtension && (iExtension->iGfxMode == KGfxModeOld))
                        {
                        // only with old volume graphics
                        StartTimerL();
                        }
#endif
                    }
                    
                return EKeyWasConsumed;
                }
            case EKeyRightArrow:
                {
                if ( iExtension && (volumeValue < iExtension->iMaximumValue) )
                    {
                    volumeValue++;
                    SetValue( volumeValue );
                    if ( iStyle != EDynRangePopupVolumeControl && 
                         !iExtension->iNoDraw )
                        {                        
                        DrawNow();
                        }
                    ReportEventL( MCoeControlObserver::EEventStateChanged );                    
                    }
                else
                    {
                    CAknVolumePopup* parent =
                        static_cast<CAknVolumePopup*> ( Parent() );
                    if ( iExtension &&
                         iExtension->iIsOnNaviStack &&
                         parent &&
                         parent->ComponentControl( 5 ) == this )
                        {
                        // Show the volume popup even if volume level is not changed
                        // to indicate that a volume adjustment key event has been
                        // received.
                        CEikStatusPaneBase* sp = CEikStatusPaneBase::Current();
                        if ( sp && sp->IsVisible() )
                            {
                            // Show the popup only if status pane is visible
                            // to maintain same kind of functionality as in
                            // navi pane volume control.
                            parent->ShowVolumePopupL();
                            }
                        }
                        
                    if ( iStyle != ESettingsVolumeControl )
                        {
                        TInt event = MAknNavigationObserver::ENaviEventRightMostItemReached;
                        ReportEventL(
                            STATIC_CAST( MCoeControlObserver::TCoeEvent, event ) );
                        }
#ifdef RD_ANIMATION_EFFECTS
                    else if (iExtension && iExtension->iGfxMode == KGfxModeOld)
                        {
                        // only with old volume graphics
                        StartTimerL();
                        }
#endif
                    }
                    
                return EKeyWasConsumed;
                }
            default:
                break;
            }
        }
    return EKeyWasNotConsumed;
    }

// ----------------------------------------------------------------------------
// CAknVolumeControl::ConstructFromResourceL(TResourceReader& aReader)
// Basic construct from the resource function.
// ----------------------------------------------------------------------------
//
EXPORT_C void CAknVolumeControl::ConstructFromResourceL(
                            TResourceReader& aReader)
    {
    TBool newResourceStructUsed = EFalse;
    
    iStyle=aReader.ReadInt16();
        
    if(iStyle == -1) // 0xfffffff
        {
        newResourceStructUsed = ETrue;
        iStyle=aReader.ReadInt16();
        }
             
    if (iStyle == ESmallPopupVolumeControl || 
        iStyle == ESmallPopupVolumeControlWithPercent )
        {
        iStyle = EDynRangePopupVolumeControl;
        }
    __ASSERT_ALWAYS( iStyle == ESettingsVolumeControl
                     || iStyle == ENaviPaneVolumeControl
                     || iStyle == EPopupVolumeControl
                     || iStyle == EDynRangeSettingsVolumeControl
                     || iStyle == EDynRangeNaviPaneVolumeControl
                     || iStyle == EDynRangePopupVolumeControl,
                     Panic( EAknPanicOutOfRange ) );

    iExtension = new(ELeave) CVolumeExtension;
    iExtension->iTimer = CPeriodic::NewL( CActive::EPriorityStandard );

    TInt value = aReader.ReadInt16();


    TPtrC bmpFile=aReader.ReadTPtrC();
    TFileName filename( bmpFile );
    CompleteWithAppPath( filename );
    TInt bmpId=aReader.ReadInt16();
    TInt bmpMask=aReader.ReadInt16();
    
    if ( iStyle != ESettingsVolumeControl )
        {
        iExtension->iBmpFilename = filename;
        iExtension->iBmpId = bmpId;
        iExtension->iBmpMask = bmpMask;
        
        CreateNaviIconL();
        // Rest of the volume icons will be loaded later.
        }
    
    // Read default min and max volume values from new VOLUME struct used by 
    // new hi-res volume layout resources. These are not defined in older 
    // layout resources so do not read these in this case.
    if( newResourceStructUsed )
        {
        iExtension->iMinimumValue = aReader.ReadInt16();
        iExtension->iMaximumValue = aReader.ReadInt16();
        __ASSERT_DEBUG( iExtension->iMinimumValue < iExtension->iMaximumValue, 
                        Panic( EAknPanicInvalidValue ) );
        
        }
    // setting volume, also dyn range uses 1-10 scale if using old struct
    else if(iStyle == ESettingsVolumeControl || iStyle == EDynRangeSettingsVolumeControl)
        {
        // set scaled value calculation to note the old 1-10 scale with 10 graphics
        iExtension->iOldScaleSettingVolume = ETrue;
        iExtension->iMinimumValue = KVolumeMinValue;
        iExtension->iMaximumValue = KVolumeMaxValue;
        }
    else
        {
        iExtension->iMinimumValue = KVolumeNaviPaneMutedValue;
        iExtension->iMaximumValue = KVolumeMaxValue;
        }
    
    if ( iStyle == EPopupVolumeControl)
        {
        iStyle = EDynRangePopupVolumeControl;
        }
    // SetValue checks iMinimumValue and iMaximumValue which must be read before this
    SetValue( value );
    }

// ----------------------------------------------------------------------------
// CAknVolumeControl::SizeChanged()
// Sets the layout.
// ----------------------------------------------------------------------------
//
void CAknVolumeControl::SizeChanged()
    {
    AknsUtils::RegisterControlPosition( this );
    SetVolumeLayout( iStyle );
    if ( AknLayoutUtils::PenEnabled()&& 
         iExtension &&
         !iExtension->iGrabPoint )
        {
        // Enable drag events, it will then be possible to drag from thumb
        EnableDragEvents();
        
        //Enable dragging to start from thumb and then move outside the slider
        DrawableWindow()->SetPointerGrab( ETrue );
        
        iExtension->iGrabPoint = ETrue;
        }
    }

// ----------------------------------------------------------------------------
// CAknVolumeControl::SetVolumeLayout(TInt aStyle)
// Pure layout function.
// ----------------------------------------------------------------------------
//
void CAknVolumeControl::SetVolumeLayout( TInt aStyle )
    {
    TAknLayoutRect layout;
    TRect rect(Rect());
    TRect parentRect( Rect() );

    switch ( aStyle )
        {
        case ESettingsVolumeControl:
            {
            layout.LayoutRect( rect,
                                AknLayoutScalable_Avkon::volume_set_pane_g1() );
            iStartPos = layout.Rect().iTl;

            if ( iExtension )
                {
                iExtension->CalculateParentRect( aStyle, rect );
                UseExtendedTouchArea();
                return;
                }
            }
            break;

        case ENaviPaneVolumeControl:
        case EDynRangeNaviPaneVolumeControl:        
            {
            MAknsSkinInstance* skin = AknsUtils::SkinInstance();
            TRgb color;
            AknsUtils::GetCachedColor( skin, color, KAknsIIDQsnIconColors,
                                        EAknsCIQsnIconColorsCG7 );
            TRAP_IGNORE ( CreateNaviIconL() );
            if (AknStatuspaneUtils::StaconPaneActive())
                {
                rect = CAknNavigationDecorator::DecoratedControlRect(
                            CAknNavigationDecorator::ENaviVolume );
                layout.LayoutRect( rect,
                        AknLayoutScalable_Avkon::volume_small_pane() );
                iStartPos = TPoint( layout.Rect().iTl.iX ,
                                    layout.Rect().iTl.iY );
                layout.LayoutRect( rect,
                        AknLayoutScalable_Avkon::navi_navi_volume_pane_g1() );
                iBmpPos = TPoint( layout.Rect().iTl.iX ,
                                  layout.Rect().iTl.iY );
                
                }
            else if (AknStatuspaneUtils::IdleLayoutActive())
                {
                layout.LayoutRect( rect,
                    AknLayoutScalable_Avkon::volume_small_pane() );
                iStartPos = TPoint( layout.Rect().iTl.iX - rect.iTl.iX,
                                    layout.Rect().iTl.iY );

                layout.LayoutRect( rect,
                    AknLayoutScalable_Avkon::navi_navi_volume_pane_g1() );
                iBmpPos = TPoint( layout.Rect().iTl.iX - rect.iTl.iX,
                                  layout.Rect().iTl.iY );

                }
            else if ( AknStatuspaneUtils::SmallLayoutActive() )
                {
                //Get the volume strength indicator layout
                layout.LayoutRect( rect,
                    AknLayoutScalable_Avkon::volume_small2_pane() );
                //volume strength indicator start position
                iStartPos = TPoint( layout.Rect().iTl.iX, 
                                    layout.Rect().iTl.iY );
                
                //Bitmap layout
                layout.LayoutRect( parentRect, 
                    AknLayoutScalable_Avkon::status_small_volume_pane_g1()
                    );
                iBmpPos = TPoint( layout.Rect().iTl.iX,
                                  layout.Rect().iTl.iY );
                }
            else
                {
                layout.LayoutRect( rect,
                    AknLayoutScalable_Avkon::volume_small_pane() );
                iStartPos = TPoint( layout.Rect().iTl.iX - rect.iTl.iX,
                                    layout.Rect().iTl.iY );
                layout.LayoutRect( rect,
                    AknLayoutScalable_Avkon::navi_navi_volume_pane_g1() );
                iBmpPos = TPoint( layout.Rect().iTl.iX - rect.iTl.iX,
                                  layout.Rect().iTl.iY );
                }
            if ( iBitmap != NULL )
                {
                AknIconUtils::SetIconColor( iBitmap, color );
                AknIconUtils::SetSize(iBitmap, layout.Rect().Size());
                if ( iExtension )
                    {
                    iExtension->iMuteRect = layout.Rect();
                    }
                }
            }
            break;

        case EPopupVolumeControl:
            // just use given rect!
            iStartPos = TPoint( rect.iTl.iX, rect.iTl.iY ); 
            break;

        default:
            // does not happen
            break;
        }

    if ( iExtension )
        {
        iExtension->CalculateParentRect( aStyle, parentRect );
        }
    }

// ----------------------------------------------------------------------------
// CAknVolumeControl::Draw(const TRect& aRect) const
// Implementation of automatically called control drawing function from 
// CCoeControl.
// ----------------------------------------------------------------------------
//
void CAknVolumeControl::Draw( const TRect& /*aRect*/ ) const
    {
    if ( iExtension->iNoDraw )
        {
        return;
        }
    /*
    * If there are volume graphics in active skin, use those to be compatible 
    * with 2.6 skins, then check for svg graphics. If that fails, draw using 
    * legacy code
    */
    if ( iExtension && !iExtension->iHasBeenDrawn )
        {
        TRAP_IGNORE( iExtension->LoadBitmapsL( iStyle, Rect()
                                               /*iAvkonAppUi->ApplicationRect() */));
        iExtension->iHasBeenDrawn = ETrue;
        }
    
    if( iExtension && iExtension->iGfxMode == KGfxModeNew)
        {
        DrawDynRangeSettingsStyleVolumeControl( iExtension->iParentRect );
        }
    else if( iExtension )
        {
            switch( iStyle )
            {
            case ESettingsVolumeControl:
                DrawSettingsStyleVolumeControl( Rect() );
                break;
            default:
                if( AknsUtils::AvkonSkinEnabled() )
                    {
                    DrawSkinnedDefaultStyleVolumeControl( Rect() );
                    }
                else
                    {
                    DrawDefaultStyleVolumeControl( Rect() );
                    }
                break;
            }    
        }
    
    }

// ----------------------------------------------------------------------------
// CAknVolumeControl::DrawSettingsStyleVolumeControl
//
// ----------------------------------------------------------------------------
//
void CAknVolumeControl::DrawSettingsStyleVolumeControl( const TRect& aRect ) const
    {
    CWindowGc& gc=SystemGc();
    MAknsSkinInstance* skin = AknsUtils::SkinInstance();
    MAknsControlContext* edCc = AknsDrawUtils::ControlContext( this );
    AknsDrawUtils::Background( skin, edCc, this, gc, aRect );

    gc.SetBrushStyle(CGraphicsContext::ESolidBrush);
    gc.SetPenStyle(CGraphicsContext::ENullPen);

    if (AknsUtils::AvkonSkinEnabled() && iExtension)
        {
        gc.SetBrushStyle(CGraphicsContext::ENullBrush);
        iExtension->DrawSvgSettingsVolume( iExtension->iParentRect, 
                                           gc, 
                                           ScaledValue() );
        return;
        }
    else
        {
        //I'm not sure whether this branch is useless or not ,so I didn't delete this branch.
        TInt colorIndex = 0;
        for (TInt i=0; i < KVolumeLevels; i++) // there is ten bars
            {
            if ( i < ScaledValue() )
                {
                colorIndex = 1;
                }
            else
                {
                colorIndex = 0;
                }
            TRect rect = Rect();
            TAknWindowLineLayout layout = AKN_LAYOUT_TABLE_Setting_volume_pane_elements_SUB_TABLE_0(i + 1, colorIndex);
            TAknLayoutRect volumeBarLayout;
            volumeBarLayout.LayoutRect(rect, layout);
            if ( iExtension && AknLayoutUtils::PenEnabled() )
                {
                // Store rect for every level. We can then decide what level was clicked
                iExtension->iVolumeLevels[i] = volumeBarLayout.Rect();
                }
            gc.SetBrushColor( volumeBarLayout.Color() );
            gc.DrawRect( volumeBarLayout.Rect() );
            }
        }
    }


// ----------------------------------------------------------------------------
// CAknVolumeControl::DrawDynRangeSettingsStyleVolumeControl
//
// ----------------------------------------------------------------------------
//
void CAknVolumeControl::DrawDynRangeSettingsStyleVolumeControl( 
    const TRect& aVolumeArea ) const
    {
    // !!! Assumptions used: Sizes of iExtension->iInActiveIcons[0],
    // iExtension->iActiveIcons[0], corresponding masks and 
    // aVolumeArea are identical.
    CWindowGc& gc=SystemGc();
    if ( !Background() )
        {
        MAknsSkinInstance* skin = AknsUtils::SkinInstance();
        MAknsControlContext* edCc = AknsDrawUtils::ControlContext( this );
        
        if ( iStyle != EDynRangePopupVolumeControl )
            {        
            AknsDrawUtils::Background( skin, edCc, this, gc, aVolumeArea );
            }
        }
    else
        {
        Background()->Draw( gc, *this, aVolumeArea );
        }

    // Only skin enabled version should exist
    TRect iconRect(0,0, iExtension->iActiveIcons[0]->SizeInPixels().iWidth,
                        iExtension->iActiveIcons[0]->SizeInPixels().iHeight );

    TRect activeRect;// rect area used for active volume slider icon
    TRect inactiveRect;// rect area used for inactive volume slider icon
    
    CalcVolumeIconAreas( Value(), 
                         aVolumeArea, 
                         activeRect, 
                         inactiveRect );
    
    // Area of the actual icon to be drawn in rect area
    TRect activeIcon( 0, 0, 
                      activeRect.iBr.iX - activeRect.iTl.iX, 
                      activeRect.iBr.iY - activeRect.iTl.iY ); 
    
    // Area of the actual icon to be drawn in rect area
    TRect inactiveIcon( inactiveRect.iTl.iX - aVolumeArea.iTl.iX, 
                        0,
                        inactiveRect.iBr.iX - aVolumeArea.iTl.iX,
                        inactiveRect.iBr.iY - aVolumeArea.iTl.iY );

    gc.BitBltMasked( activeRect.iTl, 
                     iExtension->iActiveIcons[0], 
                     activeIcon, 
                     iExtension->iActiveMasks[0], ETrue );

    gc.BitBltMasked( inactiveRect.iTl, 
                     iExtension->iInActiveIcons[0], 
                     inactiveIcon, 
                     iExtension->iInActiveMasks[0], ETrue );
    // Draw speaker or mute icon
    if ( ( iBitmap != NULL ) && ( iMaskBitmap != NULL ) )
        {
        TRect bmpRect(TPoint(0,0),TSize(iBitmap->SizeInPixels()));
        if (iStyle == EDynRangeNaviPaneVolumeControl)  // popup handles icons itself
            {
            gc.BitBltMasked(iBmpPos, iBitmap, bmpRect, iMaskBitmap, ETrue);
            }
        }    
    }


// ----------------------------------------------------------------------------
// CAknVolumeControl::CalcVolumeIconAreas()
//
// ----------------------------------------------------------------------------
//
void CAknVolumeControl::CalcVolumeIconAreas( const TInt aVolume, 
                                             const TRect& aDrawArea,
                                             TRect& aActiveRect, 
                                             TRect& aInactiveRect ) const
    {
    // Calculate drawing area split between active and inactive icon areas in percentage
    // it is caculating the activeRatio by iOldScaleSettingVolume
    // it is very important for drawing the volumecontrol
    // because the tester requires there must be at least one piece of shadow in it,
    // if we set the iMinimumValue not as (iMinimunValue+1) in HandlePointerEventL and 
    // draw the aActiveRect like this, all things go well. 
    TInt activeRatio;
    if( !iExtension->iOldScaleSettingVolume )
        {
        activeRatio = ( aVolume - iExtension->iMinimumValue ) * 100
                        / ( iExtension->iMaximumValue - iExtension->iMinimumValue );
        }
    
    else
        {
        activeRatio = aVolume * 10;
        }
    aActiveRect.iTl.iX = aDrawArea.iTl.iX;
    aActiveRect.iTl.iY = aDrawArea.iTl.iY;
    aActiveRect.iBr.iX = aDrawArea.iTl.iX + ( aDrawArea.iBr.iX - aDrawArea.iTl.iX ) * activeRatio / 100;
    aActiveRect.iBr.iY = aDrawArea.iBr.iY;
    
    aInactiveRect.iTl.iX = aActiveRect.iBr.iX /*+ 1*/;
    aInactiveRect.iTl.iY = aDrawArea.iTl.iY;
    aInactiveRect.iBr.iX = aDrawArea.iBr.iX;
    aInactiveRect.iBr.iY = aDrawArea.iBr.iY;
    }
    
    
// ----------------------------------------------------------------------------
// CAknVolumeControl::DrawDefaultStyleVolumeControl()
// NON SKINNED DRAW!
// ----------------------------------------------------------------------------
//
void CAknVolumeControl::DrawDefaultStyleVolumeControl( const TRect& /*aRect*/ ) const
    {
    CWindowGc& gc=SystemGc();
    MAknsSkinInstance* skin = AknsUtils::SkinInstance();
    
    //I'm not sure whether this branch is useless or not ,so I didn't delete this branch.
    TInt volumeLIndex;
    TAknLayoutRect layoutRect;

    if ( AknStatuspaneUtils::IdleLayoutActive() )
        {
        volumeLIndex = 0;
        }
    else
        {
        volumeLIndex = 1;
        }

    TRect parent( TSize( 0, 0 ) );
    TRect volumeNaviPaneRect;   // volume_navi_pane

    gc.SetBrushStyle(CGraphicsContext::ESolidBrush);
    gc.SetPenStyle(CGraphicsContext::ENullPen); // column drawing should have no outline
    TRgb c1, c2;

    if (iStyle == ENaviPaneVolumeControl)
        {
        layoutRect.LayoutRect( parent, AKN_LAYOUT_WINDOW_volume_navi_pane( volumeLIndex ) );
        volumeNaviPaneRect = layoutRect.Rect();

        layoutRect.LayoutRect( volumeNaviPaneRect, AKN_LAYOUT_TABLE_Volume_pane_elements__one_( 0, 0 ) );
        c1 = layoutRect.Color();
        layoutRect.LayoutRect( volumeNaviPaneRect, AKN_LAYOUT_TABLE_Volume_pane_elements__one_( 0, 1 ) );
        c2 = layoutRect.Color();
        }
    else  // Popup volume needs different colors
        {
        layoutRect.LayoutRect( Rect(), AKN_LAYOUT_TABLE_Volume_pane_elements__one_( 0, 0 ) );
        c1 = layoutRect.Color();
        layoutRect.LayoutRect( Rect(), AKN_LAYOUT_TABLE_Setting_volume_pane_elements_SUB_TABLE_0( 2, 0 ) );
        c2 = layoutRect.Color();
        }

    for (TInt i=0; i < KVolumeLevels; i++) // there is ten bars
        {
        if ( i < ScaledValue())
            {
            gc.SetBrushColor(c1);
            }
        else
            {
            gc.SetBrushColor(c2);
            }

        if ( iStyle != ENaviPaneVolumeControl )
            {
            TRect tempRect( 0, 0, 0, 0 );
            layoutRect.LayoutRect( tempRect, AKN_LAYOUT_TABLE_Volume_pane_elements__one_( i, 0 ) );
            TPoint start( iStartPos.iX + layoutRect.Rect().iTl.iX, iStartPos.iY + layoutRect.Rect().iTl.iY );
            TSize size( layoutRect.Rect().Size() );
            gc.DrawRect( TRect( start, size ) );

            if ( AknLayoutUtils::PenEnabled() )
                {
                // Store rect for every level. We can then decide what level was clicked
                iExtension->iVolumeLevels[i] = layoutRect.Rect();
                }
            }
        else
            {
            layoutRect.LayoutRect( volumeNaviPaneRect, AKN_LAYOUT_TABLE_Volume_pane_elements__one_( i, 0 ) );
            gc.DrawRect( layoutRect.Rect() );

            if ( AknLayoutUtils::PenEnabled() )
                {
                // Store rect for every level. We can then decide what level was clicked
                iExtension->iVolumeLevels[i] = layoutRect.Rect();
                }
            }
        }
    
    }
    
    
// ----------------------------------------------------------------------------
// CAknVolumeControl::DrawSkinnedDefaultStyleVolumeControl()
//
// ----------------------------------------------------------------------------
//
void CAknVolumeControl::DrawSkinnedDefaultStyleVolumeControl( 
    const TRect& /*aRect*/ ) const
    {
    CWindowGc& gc=SystemGc();
    // No test on AknsUtils::AvkonSkinEnabled() because this control is used in
    // the navipane Skinned bitmap.
    if ( !Background() )
        {
        MAknsSkinInstance* skin = AknsUtils::SkinInstance();
        AknsDrawUtils::Background( skin, 
                               AknsDrawUtils::ControlContext( this ), 
                               this, 
                               gc, 
                               Rect() );
        }
    else
        {
        Background()->Draw( gc, *this, Rect() );
        }


    // Draw speaker or mute icon
    if ( ( iBitmap != NULL ) && ( iMaskBitmap != NULL ) )
        {
        TRect bmpRect(TPoint(0,0),TSize(iBitmap->SizeInPixels()));
        if (iStyle == ENaviPaneVolumeControl)  // popup handles icons itself
            {
            gc.BitBltMasked(iBmpPos, iBitmap, bmpRect, iMaskBitmap, ETrue);
            }
        }
    if ( iExtension )
        {
        if ( ( iStyle != ENaviPaneVolumeControl ) || 
               !( iExtension->iFlags & KVolumeNaviPaneMuted ) )
            {
            iExtension->DrawSvgSmallVolume( iStyle,
                                            iExtension->iParentRect,
                                            gc,
                                            ScaledValue() );
            return;
            }
        }

    }


// ----------------------------------------------------------------------------
// CAknVolumeControl::ExtensionInterface()
//
// ----------------------------------------------------------------------------
//
EXPORT_C void* CAknVolumeControl::ExtensionInterface( TUid /*aInterface*/ )
    {
    return NULL;
    }

// ----------------------------------------------------------------------------
// CAknVolumeControl::HandlePointerEventL()
// Processes Volumecontrol's pointer event's.
// This function requests what volume level contains the clicked point
// And then set's new volumelevel according to that.
// ----------------------------------------------------------------------------
//
EXPORT_C void CAknVolumeControl::HandlePointerEventL(
                        const TPointerEvent& aPointerEvent)
    {
    if ( AknLayoutUtils::PenEnabled() && iExtension )
        {
        if ( IsDimmed() )
            {
            iExtension->iFlags &= ~KVolumeButtonDown;
            return;
            }

        TRect rect;
        if ( iExtension->iUseExtendedTouchArea )
            {
            rect = iExtension->iTouchArea;
            }
        else
            {
            AknLayoutUtils::LayoutMetricsRect( 
                    AknLayoutUtils::EApplicationWindow, rect );            
            }

        TInt level = KVolumeLevelNotFound;
        if( !rect.Contains( aPointerEvent.iPosition ) )
            {
            level = Value();
            }
        else
            {
            level = iExtension->GetVolumeLevelByPosition( iStyle, 
                aPointerEvent.iPosition, rect );
            }

        TBool valueChanged( EFalse ); // if pointerevent changes volume level                
        
        switch( aPointerEvent.iType )
            {
            case TPointerEvent::EButton1Down:
                {
                MTouchFeedback* feedback = MTouchFeedback::Instance();
                if ( feedback )
                    {
                    feedback->InstantFeedback( ETouchFeedbackSlider );
                    }
                }
            case TPointerEvent::EDrag:
            case TPointerEvent::EButtonRepeat: // fall trough
                {
                // click was inside VolumeControl
                if ( rect.Contains( aPointerEvent.iPosition ) )
                    {
                    // Pointer down in volumeControl
                    iExtension->iFlags |= KVolumeButtonDown;
                    valueChanged = ETrue;                    
                    }
                Window().RequestPointerRepeatEvent( KScrollRepeatTimeout, rect );
                }
                break;

            case TPointerEvent::EButton1Up:
                {
                // if pointer was putted down inside VolumeControl
                iExtension->iFlags &= ~KVolumeButtonDown;
                }
                break;
            
            default:
                break;                
            }        
        // get clicked volume level depending type of volumebar
        if ( valueChanged )
            {            
            if ( aPointerEvent.iType == TPointerEvent::EButton1Down )
                {
                iExtension->iReduce = ( level <= Value() );
                iExtension->iOldLevel = level;
                }
            if ( level < Value() )
                {
                iExtension->iReduce = ETrue;
                }
            else if ( level > Value() + 1 )
                {
                iExtension->iReduce = ( level < iExtension->iOldLevel );                
                }
            else if ( iExtension->iReduce && 
                ( level == Value() || level == Value() + 1 ) )
                {
                level--;
                }
            }
        //value step change
        // correction should not be done when outside of control
        if( iExtension->iFlags & KVolumeStepChange )
            {
            if( level > Value() )
                {
                level = Value() + 1;
                }
            else if( level < Value() )
                {
                level = Value() - 1;
                }            
            }//value step change over
        if ( level < iExtension->iMinimumValue )
           {
           level = iExtension->iMinimumValue;
           }
       else if ( level > iExtension->iMaximumValue )
           {
           level = iExtension->iMaximumValue;
           }
        
        iExtension->iOldLevel = level;
        
        if ( level == KVolumeLevelMuteTapped )
            {
            if ( aPointerEvent.iType == TPointerEvent::EButton1Up )
                {
                // mute indicator was tapped
                if ( Value() == iExtension->iMinimumValue )
                    {
                    // restore saved value
                    level = iExtension->iStoredLevel; 
                    iExtension->iStoredLevel = iExtension->iMinimumValue;
                    }
                else
                    {
                    // mute
                    iExtension->iStoredLevel = Value();
                    level = iExtension->iMinimumValue;
                    }
                valueChanged = ETrue;
                }
            else
                {
                // ignore 
                return;
                }
            }

        if ( valueChanged && (level != iValue) )
            {
            if ( aPointerEvent.iType == TPointerEvent::EDrag || 
                 aPointerEvent.iType == TPointerEvent::EButtonRepeat )
                {
                MTouchFeedback* feedback = MTouchFeedback::Instance();
                if ( feedback )
                    {
                    feedback->InstantFeedback( this, ETouchFeedbackSlider );    
                    }                
                }
            
            iValue = level;
            SetValue(iValue);
            ReportEventL(MCoeControlObserver::EEventStateChanged);
            DrawDeferred();
            }
        }
    }


// ----------------------------------------------------------------------------
// CAknVolumeControl::HandleNaviDecoratorEventL()
// Observes navigation decorator's events
// currently possibly events are right and left arrow presses by pointer
// increments/decrements volumelevel depending on event.
// ----------------------------------------------------------------------------
//
EXPORT_C void CAknVolumeControl::HandleNaviDecoratorEventL( TInt aEventID )
    {
    if ( AknLayoutUtils::PenEnabled() )
        {
        switch(aEventID)
            {
            case MAknNaviDecoratorObserver::EAknNaviDecoratorEventLeftTabArrow:
                {
                if ( iExtension && iValue > iExtension->iMinimumValue )
                    {
                    iValue -= 1;
                    SetValue( iValue );
                    ReportEventL(MCoeControlObserver::EEventStateChanged);
                    DrawDeferred();
                    }
                }
                break;

            case MAknNaviDecoratorObserver::EAknNaviDecoratorEventRightTabArrow:
                if ( iExtension && iValue < iExtension->iMaximumValue )
                    {
                    iValue+=1;
                    SetValue(iValue);
                    ReportEventL(MCoeControlObserver::EEventStateChanged);
                    DrawDeferred();
                    }
                break;

            default:
                break;
            }
        }
    }


// ----------------------------------------------------------------------------
// CAknVolumeControl::IndicationDrawCallbackL()
//
// ----------------------------------------------------------------------------
//
TInt CAknVolumeControl::IndicationDrawCallbackL( TAny* aThis )
    {
    CAknVolumeControl* volumeControl =
        static_cast<CAknVolumeControl*>(aThis);

    volumeControl->SmallDirectionIndicationL();

    return KErrNone;
    }

// ----------------------------------------------------------------------------
// CAknVolumeControl::SmallDirectionIndicationL()
//
// ----------------------------------------------------------------------------
//
void CAknVolumeControl::SmallDirectionIndicationL()
    {
    // We must calculate redraw area either the biggest or the smallest
    // volume bar

    TRect rect;
    TPoint p;
    TRect srcRect;
    TRect bmpRect;

    // check the icon or bitmap is not null
    TBool checkNull(EFalse);

    // Cancel blinking if moved from min or max position, unless the area is
    // blank. Then redraw and cancel after redraw
    if( iExtension && iValue != iExtension->iAnimatedEffectValue &&
        iExtension->iEffectTimerCount%2 == 0)
        {
        iExtension->iTimer->Cancel();
        return;
        }

    // CDMA case
    if( iExtension && iExtension->iAnimatedEffectValue == 0 )
        {
        iExtension->iAnimatedEffectValue += 1;
        }
    
    TInt scaledValue = ScaledValue(); // scale the value to make possible the dynamic range
    if ( iExtension && iStyle == ESettingsVolumeControl )
        {
        rect = iExtension->RectFromLayout( iExtension->iParentRect,
            AknLayoutScalable_Avkon::volume_set_pane_g(
                            scaledValue - 1 ));
        if (AknsUtils::AvkonSkinEnabled() && iExtension)
            {
            p = TPoint( rect.iTl.iX, rect.iTl.iY );
            srcRect = TRect(0, 0, rect.Width(), rect.Height());
            }
        }
    else  // navipane volume control, popup volume control
        {
        if ( iBitmap != NULL )
            {
            bmpRect = TRect(TPoint(0,0),TSize(iBitmap->SizeInPixels()));
            }
        
        if ( iExtension && AknStatuspaneUtils::SmallLayoutActive() )
            {
            rect = iExtension->RectFromLayout( iExtension->iParentRect,
                AknLayoutScalable_Avkon::volume_small2_pane_g(
                            scaledValue - 1 ) );
            }
        else if( iExtension )
            {
            rect = iExtension->RectFromLayout( iExtension->iParentRect,
                        AknLayoutScalable_Avkon::volume_small_pane_g(
                                scaledValue - 1 ) );
            }
            
        p = TPoint( rect.iTl.iX, rect.iTl.iY );
        srcRect = TRect(0, 0, rect.Width(), rect.Height());
        }

    Window().Invalidate(rect);
    ActivateGc();

    Window().BeginRedraw(rect);
    CWindowGc& gc=SystemGc();
    if( !Background() )
        {
        MAknsSkinInstance* skin = AknsUtils::SkinInstance();

        MAknsControlContext* edCc = AknsDrawUtils::ControlContext( this );
        AknsDrawUtils::Background( skin, edCc, this, gc, rect);        
        }
    else
        {
        Background()->Draw( gc, *this, rect );
        }
    if( iExtension && iExtension->iEffectTimerCount%2 == 1)
        {
        checkNull = ( iExtension->iActiveIcons[
                        scaledValue-1] != NULL )
                    && ( iExtension->iActiveMasks[
                        scaledValue-1] != NULL );
        if (iStyle==ESettingsVolumeControl)
            {
            gc.SetBrushStyle(CGraphicsContext::ESolidBrush);
            gc.SetPenStyle(CGraphicsContext::ENullPen);
            if ( AknsUtils::AvkonSkinEnabled() && iExtension
                 && checkNull )
                {
                gc.SetBrushStyle(CGraphicsContext::ENullBrush);
                gc.BitBltMasked( p, 
                                 iExtension->iActiveIcons[
                                    scaledValue-1],
                                 srcRect,
                                 iExtension->iActiveMasks[
                                    scaledValue-1],
                                 ETrue);
                }
            }
        else
            {
            if ( iExtension && checkNull )
                {
                gc.BitBltMasked( p, 
                                 iExtension->iActiveIcons[
                                    scaledValue-1],
                                 srcRect,
                                 iExtension->iActiveMasks[
                                    scaledValue-1],
                                 ETrue);
                }
            }
        }
    Window().EndRedraw();
    DeactivateGc();
    if( iExtension )
        {
        iExtension->iEffectTimerCount++;
        }

    // Stop timer if done normal-inverted-normal-inverted-normal sequence
    //  or the user has changed the value from the min or max
    if( iExtension && 
        ( iExtension->iEffectTimerCount > 3 || iExtension->iAnimatedEffectValue != iValue ) )
        {
        iExtension->iTimer->Cancel();
        }

    }

// ----------------------------------------------------------------------------
// CAknVolumeControl::StartTimerL()
//
// ----------------------------------------------------------------------------
//
void CAknVolumeControl::StartTimerL()
    {
    if(iExtension->iTimer->IsActive())
        return; // do not re-start as we have the feedback ongoing

    iExtension->iEffectTimerCount = 0;
    iExtension->iAnimatedEffectValue = ScaledValue();

    const TTimeIntervalMicroSeconds32 KVolumeFeedbackActionTime = 160*1000;

    TCallBack callback(IndicationDrawCallbackL,this);
    iExtension->iTimer->Start(KVolumeFeedbackActionTime,
        KVolumeFeedbackActionTime, callback);
    }


// ----------------------------------------------------------------------------
// CAknVolumeControl::CreateNaviIconL()
// (Re)creates the navi pane icon.
// ----------------------------------------------------------------------------
//
void CAknVolumeControl::CreateNaviIconL()
    {
    if ( !iExtension )
        {
        return;
        }

    TInt bmpId = iExtension->iBmpId;
    TInt bmpMask = iExtension->iBmpMask;

    // We compare to avkon.rh STRUCT VOLUME default values
    if ( iExtension->iBmpFilename.CompareF(_L("")) != 0 )
        {
        MAknsSkinInstance *skin = AknsUtils::SkinInstance();
        if ( iExtension->iFlags & KVolumeNaviPaneMuted )
            {
            delete iBitmap;
            iBitmap = NULL;
            delete iMaskBitmap;
            iMaskBitmap = NULL;
            AknsUtils::CreateColorIconL(skin,
                                    KAknsIIDQgnIndiSpeakerMuted,
                                    KAknsIIDQsnTextColors,
                                    EAknsCIQsnTextColorsCG19,
                                    iBitmap,
                                    iMaskBitmap,
                                    KAvkonBitmapFile,                                 
                                    EMbmAvkonQgn_indi_speaker_muted,
                                    EMbmAvkonQgn_indi_speaker_muted_mask,
                                    KRgbWhite );
            }
        else
            {
            if ( bmpId != -1 )
                {
                delete iBitmap;
                iBitmap = NULL;
                delete iMaskBitmap;
                iMaskBitmap = NULL;

                if ( bmpMask != -1 )
                    {
                    AknsUtils::CreateColorIconL( skin,
                            KAknsIIDQgnIndiSpeakerActive,
                            KAknsIIDQsnTextColors,
                            EAknsCIQsnTextColorsCG19,
                            iBitmap,
                            iMaskBitmap,
                            iExtension->iBmpFilename,                                 
                            bmpId,
                            bmpMask,
                            KRgbWhite );
                    // sizes are set in setlayoutl
                    }
                else
                    {
                    iBitmap = AknIconUtils::CreateIconL(
                                iExtension->iBmpFilename, bmpId );
                    }
                }
            }
        }
    }



// ----------------------------------------------------------------------------
// CAknVolumeControl::ScaledValue()
//
// ----------------------------------------------------------------------------
//
TInt CAknVolumeControl::ScaledValue() const
    {
    TInt scaledValue = iValue;
    if(iExtension && !iExtension->iOldScaleSettingVolume)
        {
        scaledValue = 10 * ( iValue - iExtension->iMinimumValue ) 
           / ( iExtension->iMaximumValue - iExtension->iMinimumValue );
        }
    return scaledValue;
    }


// ----------------------------------------------------------------------------
// CAknVolumeControl::UseExtendedTouchArea
//
// ----------------------------------------------------------------------------
//
void CAknVolumeControl::UseExtendedTouchArea()
    {
    TRect touchActiveArea;
    TPoint winPosition( Window().AbsPosition() );
    TRect appRect;
    AknLayoutUtils::LayoutMetricsRect( AknLayoutUtils::EApplicationWindow,
            appRect );
    TAknLayoutRect mainpaneRect;
    mainpaneRect.LayoutRect( appRect, AknLayoutScalable_Apps::main_pane(3) );
    touchActiveArea = mainpaneRect.Rect();

    touchActiveArea.Move( touchActiveArea.iTl.iX - winPosition.iX,
            touchActiveArea.iTl.iY - winPosition.iY );
    iExtension->iTouchArea = touchActiveArea;
    iExtension->iUseExtendedTouchArea = ETrue;
    }


// ----------------------------------------------------------------------------
// CVolumeExtension::
//
// ----------------------------------------------------------------------------
//
CVolumeExtension::CVolumeExtension():
    iMinimumValue( KVolumeNaviPaneMutedValue ), 
    iMaximumValue( KVolumeMaxValue ), 
    iGfxMode( KGfxModeNotLoaded ),
    iOldScaleSettingVolume(EFalse),
    iGrabPoint( EFalse )
    {
    iFlags |= KVolumeStepChange;
    }

// ----------------------------------------------------------------------------
// CAknVolumeControl::HandleResourceChange()
// Handles a change to CAknVolumeControl's resources.
// Currently it handles the change of Skins
// ----------------------------------------------------------------------------
//
EXPORT_C void CAknVolumeControl::HandleResourceChange(TInt aType)
    {
    if ((aType==KAknsMessageSkinChange) || (aType == KEikColorResourceChange)
            || (aType == KEikDynamicLayoutVariantSwitch))
        {
        SizeChanged();
        if ( iExtension )
            {
            iExtension->iHasBeenDrawn = EFalse;
            }
        }
    CCoeControl::HandleResourceChange( aType );
    }
    
void CAknVolumeControl::SuppressDrawing( TBool aSuppress )
    {
    if ( iExtension )
        {
        iExtension->iNoDraw = aSuppress;    
        }    
    }

// ----------------------------------------------------------------------------
// CVolumeExtension::~CVolumeExtension
//
// ----------------------------------------------------------------------------
//
CVolumeExtension::~CVolumeExtension()
    {
    DeleteBitmaps();
    if(iTimer && iTimer->IsActive())
        iTimer->Cancel();
    delete iTimer;
    }

// ----------------------------------------------------------------------------
// CVolumeExtension::UseSvgDrawing
//
// ----------------------------------------------------------------------------
//
TBool CVolumeExtension::UseSvgDrawing()
    {
    return ETrue;
    }

// ----------------------------------------------------------------------------
// CVolumeExtension::DeleteBitmaps
//
// ----------------------------------------------------------------------------
//
void CVolumeExtension::DeleteBitmaps()
    {
    TInt i;

    for( i = 0; i < KVolumeLevels; i++)
        {
        delete iActiveIcons[i];
        iActiveIcons[i] = NULL;
        delete iActiveMasks[i];
        iActiveMasks[i] = NULL;
        delete iInActiveIcons[i];
        iInActiveIcons[i] = NULL;
        delete iInActiveMasks[i];
        iInActiveMasks[i] = NULL;
        }
    }

// ----------------------------------------------------------------------------
// CVolumeExtension::SetIconSizes
//
// ----------------------------------------------------------------------------
//
void CVolumeExtension::SetIconSizes( TInt aStyle, const TRect& aParent ) const
    {
    TSize s;

    if( iGfxMode == KGfxModeOld )
        {
        for( TInt i = 0; i < KVolumeLevels; i++)
            {
            switch ( aStyle )
                {
                case ESettingsVolumeControl:
                    s = RectFromLayout( aParent,
                        AknLayoutScalable_Avkon::volume_set_pane_g(i) ).Size();
                    break;
                case ENaviPaneVolumeControl:
                    {
                    TRect parentRect(aParent);
                    if ( AknStatuspaneUtils::SmallLayoutActive() )
                        {
                        parentRect = RectFromLayout(
                                    parentRect,
                                    AknLayoutScalable_Avkon::volume_small2_pane()
                                    );
                        s = RectFromLayout(
                                parentRect,
                                AknLayoutScalable_Avkon::volume_small2_pane_g( i ) 
                                ).Size();
                        }
                    else
                        {
                        parentRect = RectFromLayout(
                                    parentRect,
                                    AknLayoutScalable_Avkon::volume_small_pane()
                                    );
                        s = RectFromLayout(
                                parentRect,
                                AknLayoutScalable_Avkon::volume_small_pane_g(i) 
                                ).Size();
                        }
                    }
                    break;
                case EPopupVolumeControl:
                    s = RectFromLayout(
                            aParent,
                            AknLayoutScalable_Avkon::volume_small_pane_g( i ) 
                            ).Size();
                    break;
                case EDynRangeSettingsVolumeControl:
                case EDynRangeNaviPaneVolumeControl:
                case EDynRangePopupVolumeControl:
                    s.iHeight = iParentRect.Height();
                    s.iWidth = iParentRect.Width();
                    break;
                default:
                    // can not happen
                    break;
                }
            if ( iActiveIcons[i] != NULL )
                {
                AknIconUtils::SetSize( iActiveIcons[i],
                                    s, EAspectRatioNotPreserved );
                }
            if ( iInActiveIcons[i] != NULL )
                {
                AknIconUtils::SetSize( iInActiveIcons[i],s,
                                        EAspectRatioNotPreserved );
                }
            }
        }
    else
        {
        s.iHeight = iParentRect.Height();
        s.iWidth = iParentRect.Width();

        if ( iActiveIcons[0] != NULL )
            {
            AknIconUtils::SetSize( iActiveIcons[0], s, 
                                   EAspectRatioNotPreserved );
            }
        if ( iInActiveIcons[0] != NULL )
            {
            AknIconUtils::SetSize( iInActiveIcons[0], s,
                                   EAspectRatioNotPreserved );
            }

        }
   
    }

// ----------------------------------------------------------------------------
// CVolumeExtension::LoadBitmapsL
//
// Multiple fallback levels for loading bitmaps:
// 1. Try loading new bitmaps using skin (icons will be scaled)
// 2. Try loading old bitmaps using skin (either small or large icons)
// 3. Load new bitmaps without skins (icons will be scaled)
// ----------------------------------------------------------------------------
//
void CVolumeExtension::LoadBitmapsL( TInt aStyle, const TRect& aParent )
    {
    DeleteBitmaps();

    MAknsSkinInstance* skin = AknsUtils::SkinInstance();
    TInt err = -1;// Init to any value but 0

//TODO: Verify that new skins are available and loaded

    // 1. Load new with skin           
    TRAP( err, TryLoadBitmapsSkinnedL( skin ) );
    iGfxMode = KGfxModeNew;

    // 2. Load old with skin
    if( err ) 
        {
        switch( aStyle ) 
            {
            case ESettingsVolumeControl:
                TRAP( err, TryLoadBitmapsDefaultLargeL( skin ) );
                iGfxMode = KGfxModeOld;
                break;
            case ENaviPaneVolumeControl:
            case EPopupVolumeControl:
                TRAP( err, TryLoadBitmapsDefaultSmallL( skin ) );
                iGfxMode = KGfxModeOld;
                break;
            }
        }
    
    // 3. Load new without skin
    if( err )
        {
        iGfxMode = KGfxModeNotLoaded;
        TRAP( err, TryLoadBitmapsNoSkinL() ); // Last chance - must succeed.
        iGfxMode = KGfxModeNew;
        }
    // There absolutely are no whatsoever icons available  -> abort!
    User::LeaveIfError( err );

    SetIconSizes( aStyle, aParent );
    }


// ----------------------------------------------------------------------------
// CVolumeExtension::TryLoadBitmapsSkinnedL
//
// ----------------------------------------------------------------------------
//
void CVolumeExtension::TryLoadBitmapsSkinnedL( MAknsSkinInstance* aSkin )
    {
    AknsUtils::CreateIconL(
        aSkin,
        KAknsIIDQgnGrafVolumeSetOff,
        iInActiveIcons[0],
        iInActiveMasks[0],
        KNullDesC, // Disables fallback
        EMbmAvkonQgn_graf_volume_small_off,
        EMbmAvkonQgn_graf_volume_small_off_mask ) ;

    AknsUtils::CreateIconL(
        aSkin,
        KAknsIIDQgnGrafVolumeSetOn,
        iActiveIcons[0],
        iActiveMasks[0],
        KNullDesC, // Disables fallback
        EMbmAvkonQgn_graf_volume_small_on,
        EMbmAvkonQgn_graf_volume_small_on_mask );
    }


// ----------------------------------------------------------------------------
// CVolumeExtension::
//
// ----------------------------------------------------------------------------
//
void CVolumeExtension::TryLoadBitmapsDefaultSmallL( MAknsSkinInstance* aSkin )
    {
    const TAknsItemID iconOffSkinIDArray[] = 
        {
        KAknsIIDQgnGrafVolumeSmall1Off,
        KAknsIIDQgnGrafVolumeSmall2Off,
        KAknsIIDQgnGrafVolumeSmall3Off,
        KAknsIIDQgnGrafVolumeSmall4Off,
        KAknsIIDQgnGrafVolumeSmall5Off,
        KAknsIIDQgnGrafVolumeSmall6Off,
        KAknsIIDQgnGrafVolumeSmall7Off,
        KAknsIIDQgnGrafVolumeSmall8Off,
        KAknsIIDQgnGrafVolumeSmall9Off,
        KAknsIIDQgnGrafVolumeSmall10Off
        };
    const TAknsItemID iconOnSkinIDArray[] = 
        {
        KAknsIIDQgnGrafVolumeSmall1On,
        KAknsIIDQgnGrafVolumeSmall2On,
        KAknsIIDQgnGrafVolumeSmall3On,
        KAknsIIDQgnGrafVolumeSmall4On,
        KAknsIIDQgnGrafVolumeSmall5On,
        KAknsIIDQgnGrafVolumeSmall6On,
        KAknsIIDQgnGrafVolumeSmall7On,
        KAknsIIDQgnGrafVolumeSmall8On,
        KAknsIIDQgnGrafVolumeSmall9On,
        KAknsIIDQgnGrafVolumeSmall10On
        };
    const TInt iconOffIDArray[] = 
        {
        EMbmAvkonQgn_graf_volume_small_1_off,
        EMbmAvkonQgn_graf_volume_small_2_off,
        EMbmAvkonQgn_graf_volume_small_3_off,
        EMbmAvkonQgn_graf_volume_small_4_off,
        EMbmAvkonQgn_graf_volume_small_5_off,
        EMbmAvkonQgn_graf_volume_small_6_off,
        EMbmAvkonQgn_graf_volume_small_7_off,
        EMbmAvkonQgn_graf_volume_small_8_off,
        EMbmAvkonQgn_graf_volume_small_9_off,
        EMbmAvkonQgn_graf_volume_small_10_off
        };
    const TInt iconOffMaskIDArray[] = 
        {
        EMbmAvkonQgn_graf_volume_small_1_off_mask,
        EMbmAvkonQgn_graf_volume_small_2_off_mask,
        EMbmAvkonQgn_graf_volume_small_3_off_mask,
        EMbmAvkonQgn_graf_volume_small_4_off_mask,
        EMbmAvkonQgn_graf_volume_small_5_off_mask,
        EMbmAvkonQgn_graf_volume_small_6_off_mask,
        EMbmAvkonQgn_graf_volume_small_7_off_mask,
        EMbmAvkonQgn_graf_volume_small_8_off_mask,
        EMbmAvkonQgn_graf_volume_small_9_off_mask,
        EMbmAvkonQgn_graf_volume_small_10_off_mask
        };
    const TInt iconOnIDArray[] = 
        {
        EMbmAvkonQgn_graf_volume_small_1_on,
        EMbmAvkonQgn_graf_volume_small_2_on,
        EMbmAvkonQgn_graf_volume_small_3_on,
        EMbmAvkonQgn_graf_volume_small_4_on,
        EMbmAvkonQgn_graf_volume_small_5_on,
        EMbmAvkonQgn_graf_volume_small_6_on,
        EMbmAvkonQgn_graf_volume_small_7_on,
        EMbmAvkonQgn_graf_volume_small_8_on,
        EMbmAvkonQgn_graf_volume_small_9_on,
        EMbmAvkonQgn_graf_volume_small_10_on
        };
    const TInt iconOnMaskIDArray[] = 
        {
        EMbmAvkonQgn_graf_volume_small_1_on_mask,
        EMbmAvkonQgn_graf_volume_small_2_on_mask,
        EMbmAvkonQgn_graf_volume_small_3_on_mask,
        EMbmAvkonQgn_graf_volume_small_4_on_mask,
        EMbmAvkonQgn_graf_volume_small_5_on_mask,
        EMbmAvkonQgn_graf_volume_small_6_on_mask,
        EMbmAvkonQgn_graf_volume_small_7_on_mask,
        EMbmAvkonQgn_graf_volume_small_8_on_mask,
        EMbmAvkonQgn_graf_volume_small_9_on_mask,
        EMbmAvkonQgn_graf_volume_small_10_on_mask
        };
    
    for ( TInt i=0; i<10; i++ )
        {
        AknsUtils::CreateIconL( 
                aSkin, 
                iconOffSkinIDArray[i],
                iInActiveIcons[i],
                iInActiveMasks[i],
                KNullDesC,
                iconOffIDArray[i],
                iconOffMaskIDArray[i]
                );
        AknsUtils::CreateIconL( 
                aSkin, 
                iconOnSkinIDArray[i],
                iActiveIcons[i],
                iActiveMasks[i],
                KNullDesC,
                iconOnIDArray[i],
                iconOnMaskIDArray[i]
                );
        }
    }
    
    
// ----------------------------------------------------------------------------
// CVolumeExtension::
//
// ----------------------------------------------------------------------------
//
void CVolumeExtension::TryLoadBitmapsDefaultLargeL( MAknsSkinInstance* aSkin )
    {
    const TAknsItemID iconOffSkinIDArray[] = 
        {
        KAknsIIDQgnGrafVolumeSet1Off,
        KAknsIIDQgnGrafVolumeSet2Off,
        KAknsIIDQgnGrafVolumeSet3Off,
        KAknsIIDQgnGrafVolumeSet4Off,
        KAknsIIDQgnGrafVolumeSet5Off,
        KAknsIIDQgnGrafVolumeSet6Off,
        KAknsIIDQgnGrafVolumeSet7Off,
        KAknsIIDQgnGrafVolumeSet8Off,
        KAknsIIDQgnGrafVolumeSet9Off,
        KAknsIIDQgnGrafVolumeSet10Off
        };
    const TAknsItemID iconOnSkinIDArray[] = 
        {
        KAknsIIDQgnGrafVolumeSet1On,
        KAknsIIDQgnGrafVolumeSet2On,
        KAknsIIDQgnGrafVolumeSet3On,
        KAknsIIDQgnGrafVolumeSet4On,
        KAknsIIDQgnGrafVolumeSet5On,
        KAknsIIDQgnGrafVolumeSet6On,
        KAknsIIDQgnGrafVolumeSet7On,
        KAknsIIDQgnGrafVolumeSet8On,
        KAknsIIDQgnGrafVolumeSet9On,
        KAknsIIDQgnGrafVolumeSet10On
        };
    const TInt iconOffIDArray[] = 
        {
        EMbmAvkonQgn_graf_volume_set_1_off,
        EMbmAvkonQgn_graf_volume_set_2_off,
        EMbmAvkonQgn_graf_volume_set_3_off,
        EMbmAvkonQgn_graf_volume_set_4_off,
        EMbmAvkonQgn_graf_volume_set_5_off,
        EMbmAvkonQgn_graf_volume_set_6_off,
        EMbmAvkonQgn_graf_volume_set_7_off,
        EMbmAvkonQgn_graf_volume_set_8_off,
        EMbmAvkonQgn_graf_volume_set_9_off,
        EMbmAvkonQgn_graf_volume_set_10_off
        };
    const TInt iconOffMaskIDArray[] = 
        {
        EMbmAvkonQgn_graf_volume_set_1_off_mask,
        EMbmAvkonQgn_graf_volume_set_2_off_mask,
        EMbmAvkonQgn_graf_volume_set_3_off_mask,
        EMbmAvkonQgn_graf_volume_set_4_off_mask,
        EMbmAvkonQgn_graf_volume_set_5_off_mask,
        EMbmAvkonQgn_graf_volume_set_6_off_mask,
        EMbmAvkonQgn_graf_volume_set_7_off_mask,
        EMbmAvkonQgn_graf_volume_set_8_off_mask,
        EMbmAvkonQgn_graf_volume_set_9_off_mask,
        EMbmAvkonQgn_graf_volume_set_10_off_mask
        };
    const TInt iconOnIDArray[] = 
        {
        EMbmAvkonQgn_graf_volume_set_1_on,
        EMbmAvkonQgn_graf_volume_set_2_on,
        EMbmAvkonQgn_graf_volume_set_3_on,
        EMbmAvkonQgn_graf_volume_set_4_on,
        EMbmAvkonQgn_graf_volume_set_5_on,
        EMbmAvkonQgn_graf_volume_set_6_on,
        EMbmAvkonQgn_graf_volume_set_7_on,
        EMbmAvkonQgn_graf_volume_set_8_on,
        EMbmAvkonQgn_graf_volume_set_9_on,
        EMbmAvkonQgn_graf_volume_set_10_on
        };
    const TInt iconOnMaskIDArray[] = 
        {
        EMbmAvkonQgn_graf_volume_set_1_on_mask,
        EMbmAvkonQgn_graf_volume_set_2_on_mask,
        EMbmAvkonQgn_graf_volume_set_3_on_mask,
        EMbmAvkonQgn_graf_volume_set_4_on_mask,
        EMbmAvkonQgn_graf_volume_set_5_on_mask,
        EMbmAvkonQgn_graf_volume_set_6_on_mask,
        EMbmAvkonQgn_graf_volume_set_7_on_mask,
        EMbmAvkonQgn_graf_volume_set_8_on_mask,
        EMbmAvkonQgn_graf_volume_set_9_on_mask,
        EMbmAvkonQgn_graf_volume_set_10_on_mask
        };

    for ( TInt i=0; i<10; i++ )
        {
        AknsUtils::CreateIconL( 
                aSkin, 
                iconOffSkinIDArray[i],
                iInActiveIcons[i],
                iInActiveMasks[i],
                KNullDesC,
                iconOffIDArray[i],
                iconOffMaskIDArray[i]
                );
        AknsUtils::CreateIconL( 
                aSkin, 
                iconOnSkinIDArray[i],
                iActiveIcons[i],
                iActiveMasks[i],
                KNullDesC,
                iconOnIDArray[i],
                iconOnMaskIDArray[i]
                );
        }
    
    }


// ----------------------------------------------------------------------------
// CVolumeExtension::TryLoadBitmapsNoSkinL
//
// ----------------------------------------------------------------------------
//
void CVolumeExtension::TryLoadBitmapsNoSkinL()
    {
    AknIconUtils::CreateIconL(
            iInActiveIcons[0],
            iInActiveMasks[0],
            KAvkonBitmapFile,
            EMbmAvkonQgn_graf_volume_small_off,
            EMbmAvkonQgn_graf_volume_small_off_mask );
    AknIconUtils::CreateIconL(
            iActiveIcons[0],
            iActiveMasks[0],
            KAvkonBitmapFile,
            EMbmAvkonQgn_graf_volume_small_on,
            EMbmAvkonQgn_graf_volume_small_on_mask );
    }
    
// ----------------------------------------------------------------------------
// CVolumeExtension::CalculateParentRect
//
// ----------------------------------------------------------------------------
//
void CVolumeExtension::CalculateParentRect( TInt aStyle, const TRect& aParent )
    {
    switch (aStyle)
        {
        case ENaviPaneVolumeControl:
        case EDynRangeNaviPaneVolumeControl:
                {
                // Rect() gives navi_navi_volume_pane in the control hierarchy.
                if ( AknStatuspaneUtils::SmallLayoutActive() )
                    {
                    iParentRect = RectFromLayout(
                                aParent,
                                AknLayoutScalable_Avkon::volume_small2_pane()
                                );
                    }
                else
                    {
                    iParentRect = RectFromLayout(
                                aParent,
                                AknLayoutScalable_Avkon::volume_small_pane()
                                );
                    }
                }
            break;
        case ESettingsVolumeControl:
        case EPopupVolumeControl:
        default:
            iParentRect = aParent; // Rect()
            break;
        }
    }

// ----------------------------------------------------------------------------
// CVolumeExtension::DrawSvgSmallVolume
//
// ----------------------------------------------------------------------------
//
void CVolumeExtension::DrawSvgSmallVolume(
                        TInt aStyle,
                        const TRect& aRect,
                        CBitmapContext& aGc,
                        TInt aValue
                        )
    {
    TRect r;
    for (TInt i = 0; i < KVolumeLevels; i++)
        {
        if ( aStyle == EPopupVolumeControl )
            {
            r = RectFromLayout( aRect,
                        AknLayoutScalable_Avkon::volume_small_pane_g( i ) );
            }
        else // navi pane volume control
            {
            if ( AknStatuspaneUtils::SmallLayoutActive() )
                {
                r = RectFromLayout( aRect,
                        AknLayoutScalable_Avkon::volume_small2_pane_g( i ) );
                }
            else
                {
                r = RectFromLayout( aRect,
                        AknLayoutScalable_Avkon::volume_small_pane_g( i ) );
                }
            }
            
        TPoint p( r.iTl.iX, r.iTl.iY );
        TRect srcRect(0, 0, r.Width(), r.Height());

        if ( AknLayoutUtils::PenEnabled() )
            {
            // Store rect for every level.
            // We can then decide what level was clicked
            iVolumeLevels[i] = r;
            }

        if ( i < aValue )
            {
            if ( ( iActiveIcons[i] != NULL ) && ( iActiveMasks[i] != NULL ) )
                {
                aGc.BitBltMasked( p, iActiveIcons[i],
                                    srcRect, iActiveMasks[i], ETrue);
                }
            }
        else
            {
            if ( ( iInActiveIcons[i] != NULL ) 
                && ( iInActiveMasks[i] != NULL ) )
                {
                aGc.BitBltMasked( p, iInActiveIcons[i], 
                                    srcRect, iInActiveMasks[i], ETrue);
                }
            }
        }
    }

// ----------------------------------------------------------------------------
// CVolumeExtension::DrawSvgSettingsVolume
//
// ----------------------------------------------------------------------------
//
void CVolumeExtension::DrawSvgSettingsVolume( const TRect& aRect,
                        CWindowGc& aGc, TInt aValue )
    {
    TRect r;
    for (TInt i = 0; i < KVolumeLevels; i++)
        {
        r = RectFromLayout( aRect,
                    AknLayoutScalable_Avkon::volume_set_pane_g( i ) );
        TPoint p( r.iTl.iX, r.iTl.iY );
        TRect srcRect(0, 0, r.Width(), r.Height());

        if ( AknLayoutUtils::PenEnabled() )
            {
            // Store rect for every level.
            // We can then decide what level was clicked
            iVolumeLevels[i] = r;
            }

        if ( i < aValue )
            {
            if ( ( iActiveIcons[i] != NULL ) && ( iActiveMasks[i] != NULL ) )
                {
                aGc.BitBltMasked( p, iActiveIcons[i],
                                    srcRect, iActiveMasks[i], ETrue);
                }
            }
        else
            {
            if ( ( iInActiveIcons[i] != NULL )
                    && ( iInActiveMasks[i] != NULL ) )
                {
                aGc.BitBltMasked( p, iInActiveIcons[i], srcRect, 
                                    iInActiveMasks[i], ETrue);
                }
            }
        }
    }

// ----------------------------------------------------------------------------
// CVolumeExtension::
//
// ----------------------------------------------------------------------------
//
void CVolumeExtension::CreateSvgSettingsIconL(
                const TRect& aRect, TInt aValue, CGulIcon* aIcon )
    {
    CVolumeExtension* extension = new (ELeave) CVolumeExtension;
    CleanupStack::PushL( extension );

    extension->LoadBitmapsL( ENaviPaneVolumeControl, aRect );
    extension->DrawSvgSettingsIconL( aRect, aValue, aIcon );

    CleanupStack::PopAndDestroy(); // extension
    }
// ----------------------------------------------------------------------------
// CVolumeExtension::
//
// ----------------------------------------------------------------------------
//
void CVolumeExtension::CreateDynRangeStyleSettingsIconL( const TRect& aRect, 
                                                    TInt aValue, 
                                                    CGulIcon* aIcon, 
                                                    TInt aMinimum,
                                                    TInt aMaximum )
    {
    CVolumeExtension* extension = new (ELeave) CVolumeExtension;
    CleanupStack::PushL( extension );

    extension->LoadBitmapsL( EDynRangeSettingsVolumeControl, aRect );
    extension->DrawDynRangeStyleSettingsIconL( aRect, aValue, aIcon, aMinimum, aMaximum );

    CleanupStack::PopAndDestroy(); // extension
    }
// ----------------------------------------------------------------------------
// CVolumeExtension::
//
// ----------------------------------------------------------------------------
//
void CVolumeExtension::DrawSvgSettingsIconL(
                const TRect& aRect, TInt aValue, CGulIcon* aIcon )
    {
    __ASSERT_DEBUG( ( aValue >= iMinimumValue )
                            && (aValue <= iMaximumValue), 
                    Panic(EAknPanicOutOfRange) );
    if( iGfxMode == KGfxModeNew )
        {
        DrawDynRangeStyleSettingsIconL( aRect, aValue, aIcon, iMinimumValue, iMaximumValue );            
        }
    else
        {
            
        // The actual bitmap
        CFbsBitmap* bitmap = new (ELeave) CFbsBitmap;
        CleanupStack::PushL( bitmap );

        bitmap->Create( aRect.Size(),
                    CCoeEnv::Static()->ScreenDevice()->DisplayMode() );
        CFbsBitGc* fbsBitGc = CFbsBitGc::NewL();
        CleanupStack::PushL( fbsBitGc );
        CFbsBitmapDevice* bmpDevice = CFbsBitmapDevice::NewL( bitmap );
        CleanupStack::PushL( bmpDevice );
        fbsBitGc->Activate( bmpDevice );

        TRect r;

        for (TInt i = 0; i < KVolumeLevels; i++)
            {
            r = RectFromLayout( aRect,
                    AknLayoutScalable_Avkon::volume_small_pane_cp_g(i));
            TPoint p( r.iTl.iX, r.iTl.iY );
            TRect srcRect(0, 0, r.Width(), r.Height());

            if ( AknLayoutUtils::PenEnabled() )
                {
                // Store rect for every level.
                // We can then decide what level was clicked
                iVolumeLevels[i] = r;
                }

            if ( i < aValue )
                {
                if ( iActiveIcons[i] != NULL )
                    {
                    AknIconUtils::SetSize( iActiveIcons[i], r.Size() );
                    fbsBitGc->BitBlt( p, iActiveIcons[i], srcRect );
                    }
                }
            else
                {
                if ( iInActiveIcons[i] != NULL )
                    {
                    AknIconUtils::SetSize( iInActiveIcons[i], r.Size() );
                    fbsBitGc->BitBlt( p, iInActiveIcons[i], srcRect );
                    }
                }
            }
                
        CleanupStack::PopAndDestroy( 2 ); // bmpDevice, fbsBitGc
        aIcon->SetBitmap( bitmap ); // Transfers ownership
        CleanupStack::Pop(); // bitmap

        // The mask
        CFbsBitmap* mask = new (ELeave) CFbsBitmap;
        CleanupStack::PushL( mask );

        mask->Create( aRect.Size(), iActiveMasks[0]->DisplayMode() );
        fbsBitGc = CFbsBitGc::NewL();
        CleanupStack::PushL( fbsBitGc );
        bmpDevice = CFbsBitmapDevice::NewL( mask );
        CleanupStack::PushL( bmpDevice );
        fbsBitGc->Activate( bmpDevice );
        fbsBitGc->SetPenStyle( CGraphicsContext::ENullPen );
        fbsBitGc->SetBrushStyle( CGraphicsContext::ESolidBrush );
        fbsBitGc->SetBrushColor( KRgbBlack );
        fbsBitGc->DrawRect( TRect( aRect.Size() ) );

        fbsBitGc->SetBrushStyle( CGraphicsContext::ENullBrush );

        for ( TInt i = 0; i < KVolumeLevels; i++ )
            {
            r = RectFromLayout( aRect,
                    AknLayoutScalable_Avkon::volume_small_pane_cp_g( i ) );
            TPoint p( r.iTl.iX, r.iTl.iY );
            TRect srcRect( 0, 0, r.Width(), r.Height() );

            if ( i < aValue )
                {
                if ( ( iActiveMasks[i] != NULL ) )
                    {
                    AknIconUtils::SetSize( iActiveMasks[i], r.Size() );
                    fbsBitGc->BitBlt( p, iActiveMasks[i], srcRect );
                    }
                }
            else
                {
                if ( iInActiveMasks[i] != NULL )
                    {
                    AknIconUtils::SetSize( iInActiveMasks[i], r.Size() );
                    fbsBitGc->BitBlt( p, iInActiveMasks[i], srcRect );
                    }
                }
            }

        CleanupStack::PopAndDestroy( 2 ); // bmpDevice, fbsBitGc
        aIcon->SetMask( mask ); // Transfers ownership
        CleanupStack::Pop(); // mask
        }
    }
// ----------------------------------------------------------------------------
// CVolumeExtension::
//
// ----------------------------------------------------------------------------
//
void CVolumeExtension::DrawDynRangeStyleSettingsIconL( const TRect& aRect, 
                                                  TInt aValue, 
                                                  CGulIcon* aIcon, 
                                                  TInt aMinimum, 
                                                  TInt aMaximum )
    {
    __ASSERT_DEBUG( ( aValue >= aMinimum )
                            && (aValue <= aMaximum), 
                    Panic(EAknPanicOutOfRange) );
    
    // The actual bitmap
    CFbsBitmap* bitmap = new (ELeave) CFbsBitmap;
    CleanupStack::PushL( bitmap );

    bitmap->Create( aRect.Size(),
                CCoeEnv::Static()->ScreenDevice()->DisplayMode() );
    CFbsBitGc* fbsBitGc = CFbsBitGc::NewL();
    CleanupStack::PushL( fbsBitGc );
    CFbsBitmapDevice* bmpDevice = CFbsBitmapDevice::NewL( bitmap );
    CleanupStack::PushL( bmpDevice );
    fbsBitGc->Activate( bmpDevice );

    TRect r( aRect );
    // the following is original code
    // TRect activeRect(r.iTl.iX, r.iTl.iY, r.Width() * aValue/( aMaximum - aMinimum + 1 ), r.Height()); 
    // but the following is changed 
    // just remove +1 from denominator, because it should be aMaximum - aMinimum 
    // and caculate the activeRect seperately according to the iOld ScaleSettingVolume.
    TInt range;
    if( iOldScaleSettingVolume )
        {
        range = KVolumeLevels ;      
        } 
    else
        {
        range = aMaximum - aMinimum ;
        }
    TRect activeRect(r.iTl.iX, r.iTl.iY, r.Width() * aValue/range, r.Height()); 
    TRect inActiveRect( activeRect.iBr.iX, activeRect.iTl.iY, r.iBr.iX, r.iBr.iY );

   if ( iActiveIcons[0] != NULL && iInActiveIcons[0] != NULL )
       {
       // add the last parameter for every SetSize() function
       // In order to make the solid graphic has the same size as the volume control                 
       AknIconUtils::SetSize( iActiveIcons[0], r.Size(),EAspectRatioNotPreserved );
       fbsBitGc->BitBlt( activeRect.iTl, iActiveIcons[0], activeRect );
       AknIconUtils::SetSize( iInActiveIcons[0], r.Size(),EAspectRatioNotPreserved );
       fbsBitGc->BitBlt( inActiveRect.iTl, iInActiveIcons[0], inActiveRect );       

       }

    CleanupStack::PopAndDestroy( 2 ); // bmpDevice, fbsBitGc
    aIcon->SetBitmap( bitmap ); // Transfers ownership
    CleanupStack::Pop(); // bitmap

    // The mask
    CFbsBitmap* mask = new (ELeave) CFbsBitmap;
    CleanupStack::PushL( mask );

    mask->Create( aRect.Size(), iActiveMasks[0]->DisplayMode() );
    fbsBitGc = CFbsBitGc::NewL();
    CleanupStack::PushL( fbsBitGc );
    bmpDevice = CFbsBitmapDevice::NewL( mask );
    CleanupStack::PushL( bmpDevice );
    fbsBitGc->Activate( bmpDevice );
    fbsBitGc->SetPenStyle( CGraphicsContext::ENullPen );
    fbsBitGc->SetBrushStyle( CGraphicsContext::ESolidBrush );
    fbsBitGc->SetBrushColor( KRgbBlack );
    fbsBitGc->DrawRect( TRect( aRect.Size() ) );

    fbsBitGc->SetBrushStyle( CGraphicsContext::ENullBrush );
    
   if ( iActiveMasks[0] != NULL && iInActiveMasks[0] != NULL )
       {
       // add the last parameter for every SetSize() function
       // In order to make the solid graphic has the same size as the volume control   
       AknIconUtils::SetSize( iActiveMasks[0], r.Size(),EAspectRatioNotPreserved );
       fbsBitGc->BitBlt( activeRect.iTl, iActiveMasks[0], activeRect );
       AknIconUtils::SetSize( iInActiveMasks[0], r.Size(),EAspectRatioNotPreserved );
       fbsBitGc->BitBlt( inActiveRect.iTl, iInActiveMasks[0], inActiveRect );
       } 
          
    CleanupStack::PopAndDestroy( 2 ); // bmpDevice, fbsBitGc
    aIcon->SetMask( mask ); // Transfers ownership
    CleanupStack::Pop(); // mask
    }

// ----------------------------------------------------------------------------
// CVolumeExtension::RectFromLayout
//
// ----------------------------------------------------------------------------
//
TRect CVolumeExtension::RectFromLayout(const TRect& aParent,
                const TAknWindowComponentLayout& aComponentLayout) const
    {
    TAknWindowLineLayout lineLayout = aComponentLayout.LayoutLine();
    TAknLayoutRect layoutRect;
    layoutRect.LayoutRect(aParent,lineLayout);
    return layoutRect.Rect();
    }

// ----------------------------------------------------------------------------
// CVolumeExtension::GetVolumeLevelByPosition()
// This function Searches which iVolumeLevels array's element (TRect) contains
// aPoint. The array is ordered so that the index can then be used to return 
// correct volume level. aAreaRect is used to add volumelevel's height to cover
// whole area so user does not need to click "inside" level. This function also
// calculates gap between volumelevel rects and returns correct volumelevel
// also from clicks to these gaps
// ----------------------------------------------------------------------------
//
TInt CVolumeExtension::GetVolumeLevelByPosition( const TInt& ,
                                                 const TPoint& aPoint, 
                                                 const TRect& aAreaRect ) const
    {
    if ( AknLayoutUtils::PenEnabled() )
        {
        TInt volumeLevel = KVolumeLevelNotFound; 
        TInt range = iMaximumValue - iMinimumValue ;
        // Use hi-res volume control with dynamic volume range
        if( iGfxMode == KGfxModeNew )
            {
            // Check the point's position in iParentRect x-axis. Use this to 
            // define a value between iMinimumValue  and iMaximumValue. Step 
            // size is always 1 (value is rounded up).
             TInt pointInVolumeAxis = aPoint.iX - iParentRect.iTl.iX;
            // This rouds up to integer.
            TInt total( pointInVolumeAxis * range );
            TInt volumePosition = total / iParentRect.Width() + iMinimumValue;
            if ( total % iParentRect.Width() > 0 )
                {
                volumePosition++;
                }             
            
            if( volumePosition >= iMinimumValue && volumePosition <= iMaximumValue )
                {
                volumeLevel = volumePosition;
                }
            else if(volumePosition > iMaximumValue)
                {
                volumeLevel = iMaximumValue;
                }
            else
                {
                volumeLevel = iMinimumValue;
                }
            }
        // Use old volume implementation with range [0,10]
        else 
            {
            TRect nextRect;
            TRect thisRect = iVolumeLevels[0];
            
            if ( iMuteRect.Contains( aPoint ))
                {
                return KVolumeLevelMuteTapped;
                }

            for (TInt i = 1; i <= KVolumeLevels; i++)
                {
                // do not read next rect, if this is last round
                if ( i < KVolumeLevels )
                    {
                    // read rect for volume level i
                    nextRect = iVolumeLevels[i];

                    // set thisRect to contain half of gap between this and next
                    //  rect
                    // + 1 because right and bottom borders are not "inside" rect
                    thisRect.iBr.iX = (nextRect.iTl.iX - thisRect.iBr.iX)/2
                                        + thisRect.iBr.iX;

                    // set nextRect to contain other half of gap
                    //  between these two rects
                    nextRect.iTl.iX = thisRect.iBr.iX;
                    }

                // set volumebars where pointer is accepted
                //  for it to be as high as area.
                thisRect.iTl.iY = aAreaRect.iTl.iY;
                thisRect.iBr.iY = aAreaRect.iBr.iY;

                if ( thisRect.Contains( aPoint ))
                    {
                    // Because array is zero indexed, but volumes starts at 1
                    //--> Conversion by adding one before return.
                    // (and here so that it needs to be done only once)
                    volumeLevel = i;
                    volumeLevel = volumeLevel * range/KVolumeLevels;
                    break;
                    }
                thisRect = nextRect;
                }
            if( aPoint.iX > iVolumeLevels[KVolumeLevels-1].iBr.iX )
                {
                volumeLevel = iMaximumValue;
                }
            else if( aPoint.iX < iVolumeLevels[0].iBr.iX )
                {
                volumeLevel = iMinimumValue;    
                }
            }
        return volumeLevel;
        }
    else
        {
        // Should not occur, just prevent complier's warning
        return 0;
        }
    }

//  End of File
