uifw/EikStd/coctlsrc/EIKSCRLB.CPP
changeset 0 2f259fa3e83a
child 3 8ca85d2f0db7
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/uifw/EikStd/coctlsrc/EIKSCRLB.CPP	Tue Feb 02 01:00:49 2010 +0200
@@ -0,0 +1,2398 @@
+/*
+* Copyright (c) 1997-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:
+*
+*/
+
+
+#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
+#include <uikon/eikdefmacros.h>
+#endif
+#include <eikscrlb.h>
+#include <eikpanic.h>
+#include <eikcoctlpanic.h>
+#include <eikenv.h>
+#include <AknLayout.lag>
+#include <eikcba.h>
+#include <AknsDrawUtils.h>
+#include <AknUtils.h>
+#include <aknappui.h>
+#include <AknsUtils.h>
+#include <AknLayout2ScalableDef.h>
+#include <aknlayoutscalable_avkon.cdl.h>
+#include <AknInfoPopupNoteController.h>
+#include <aknpointereventmodifier.h>
+#include <AknTasHook.h>
+#include <touchfeedback.h>
+
+
+#include "AknDoubleSpanScrollIndicator.h"
+#include "eikscrlb.h"
+#include "EIKSBEXT.H"
+
+const TInt KIntensity = 50; // 50%
+
+const TInt KScrollBarWidth=9;
+// const TInt KScrollButtonHeight=10;
+// const TInt KArrowHeadScrollBarLength=20;
+
+// Constants for double span scrollbar
+const TInt KAknDoubleSpanScrollBarWidth = 6;
+const TInt KDoubleSpanMaxModelValue     = 0x1FFF7FFF;
+const TInt KDoubleSpanMinModelValue     = -0x1FFF7FFF;
+const TInt16 KDoubleSpanMaxScaleValue   = 0x3FFF;
+const TInt16 KDoubleSpanMinScaleValue   = 1;
+const TInt KDoubleSpanMaxRawValue       = 0x8000;
+
+// Mask values for double span scrollbar
+const TUint KDoubleSpanModelMaskBitsHigh       = 0xFFFF0000;
+const TUint KDoubleSpanModelMaskBitsLow        = 0x0000FFFF;
+const TUint KDoubleSpanModelMaskBitsScale      = 0x3FFF0000;
+const TUint KDoubleSpanModelMaskBitsType       = 0x3FFFFFFF;
+const TUint16 KDoubleSpanModelMaskBitsScale16 = 0x3FFF;
+
+const TInt KScrollRepeatTimeout = 250000; // 0.25 seconds
+const TInt KScrollDragTimeout =    66000; // 0.66 seconds means 16 fps
+
+EXPORT_C TBool TEikScrollBarModel::operator==(const TEikScrollBarModel aModel) const
+    {
+    return ((iScrollSpan==aModel.iScrollSpan)&(iThumbSpan==aModel.iThumbSpan)&(iThumbPosition==aModel.iThumbPosition));
+    }
+
+EXPORT_C TEikScrollBarModel::TEikScrollBarModel(TInt aScrollSpan,TInt aThumbSpan,TInt aThumbPosition)
+    : iScrollSpan(aScrollSpan),
+    iThumbSpan(aThumbSpan),
+    iThumbPosition(aThumbPosition)
+    {}
+
+EXPORT_C TBool TEikScrollBarModel::ScrollBarUseful() const
+    {
+    return iThumbSpan<iScrollSpan;
+    }
+
+EXPORT_C TInt TEikScrollBarModel::MaxThumbPos() const
+    {
+    return iScrollSpan-iThumbSpan;
+    }
+
+EXPORT_C void TEikScrollBarModel::CheckBounds()
+// Ensure the thumbposition remains within it's valid range
+    {
+    iThumbPosition=Max(0,Min(iThumbPosition,iScrollSpan-1));
+    }
+
+TEikScrollBarModel::TEikScrollBarModelType TEikScrollBarModel::ScrollBarModelType() const
+    {
+    TUint type = (~KDoubleSpanModelMaskBitsType) & iScrollSpan;
+    if (type == EAknDoubleSpanScrollBarModel)
+        {
+        return EAknDoubleSpanScrollBarModel;
+        }
+    else
+        {
+        return EEikScrollBarModel;
+        }
+    }
+
+//
+// CEikScrollBar class
+//
+
+EXPORT_C CEikScrollBar::~CEikScrollBar()
+// Destructor
+    {
+    AKNTASHOOK_REMOVE();
+    DisconnectExternalFrames();
+    delete(iButtons.iIncreaseNudge);
+    delete(iButtons.iDecreaseNudge);
+    delete iExtension;
+    }
+
+EXPORT_C CEikScrollBar::CEikScrollBar()
+// Default constructor
+    {
+    SetNonFocusing();
+    SetComponentsToInheritVisibility();
+    AKNTASHOOK_ADD( this, "CEikScrollBar" );
+    }
+
+EXPORT_C void CEikScrollBar::ConstructL(MEikScrollBarObserver* aScrollBarObserver,const CCoeControl* aParent,
+                                        TOrientation aOrientation,TInt /*aLength*/,TInt /*aScrollBarFlags*/)
+// Second-phase construction
+    {
+    // If extension has not been created by deriving class, create default extension.
+    if (!iExtension)
+        {
+        iExtension = new(ELeave) CEikScrollBarExtension(this);
+        }
+
+    if(AknLayoutUtils::PenEnabled())
+        {
+        CEikScrollBarExtension* extension = static_cast<CEikScrollBarExtension*> (iExtension);
+        extension->SetScrollBarObserver(aScrollBarObserver);
+        }
+
+    CreateWindowL(aParent);
+
+    if(aParent)
+        SetObserver(aParent->Observer());
+    else
+        SetObserver(NULL);
+
+    iOrientation=aOrientation;
+    // Fix scrollbar frame's position to middle of cba
+    CreateRequiredComponentsL();
+    Window().SetPointerGrab(ETrue);
+    EnableDragEvents();
+    MakeVisible(EFalse);
+    ActivateL();
+    }
+
+EXPORT_C TInt CEikScrollBar::CountComponentControls() const
+    {
+    TInt controlCount = 0;
+    if(iButtons.iIncreaseNudge)
+        {
+        controlCount++;
+        }
+    if(iButtons.iDecreaseNudge)
+        {
+        controlCount++;
+        }
+    return controlCount;
+    }
+
+EXPORT_C CCoeControl* CEikScrollBar::ComponentControl(TInt aIndex) const
+    {
+    if (aIndex==0)
+        return iButtons.iIncreaseNudge;
+    else
+        return iButtons.iDecreaseNudge;
+    }
+
+EXPORT_C void CEikScrollBar::SetLengthL(TInt /*aLength*/)
+// Change the scrollbar's length.  Will redraw
+    {
+    }
+
+EXPORT_C void CEikScrollBar::SetModelL(const TEikScrollBarModel* aModel)
+    {
+    SetModel(aModel);
+    }
+
+EXPORT_C void CEikScrollBar::SetModel(const TEikScrollBarModel* aModel)
+// Change the scrollbar model
+    {
+    if (*aModel==iModel)
+        return;
+    DoSetModel(aModel);
+    }
+
+EXPORT_C void CEikScrollBar::SetLengthAndModelL(TInt /*aLength*/,const TEikScrollBarModel* aModel)
+// Change the length and model at once to avoid a double update of the scrollbar
+    {
+    SetModel(aModel);
+    }
+
+EXPORT_C void CEikScrollBar::SetModelThumbPosition(TInt /*aThumbPos*/)
+    {
+    }
+
+EXPORT_C void CEikScrollBar::SetFocusPosToThumbPos(TInt /*aFocusPosition*/)
+    {
+    }
+
+EXPORT_C TInt CEikScrollBar::ThumbPosition() const
+// Retrun the model's thumb position (eg in response to a scroll event)
+    {
+    if (iExtension)
+        {
+        return iExtension->ThumbPosition();
+        }
+    else
+        {
+        return 0;
+        }
+    }
+
+EXPORT_C TInt CEikScrollBar::ScrollBarBreadth() const
+// returns the height of a horizontal scrollbar or width of a vertical scrollbar
+    {
+    if (iExtension)
+        {
+        return iExtension->ScrollBarBreadth();
+        }
+    else
+        {
+        return 0;
+        }
+    }
+
+EXPORT_C TInt CEikScrollBar::MinVisibleLength(const TInt /*aScrollBarFlags*/)
+// STATIC - Calculates the minimum length in which scrollbar will remain "visible" (not necessarily with all it's components though)
+    {
+    return 0;
+    }
+
+EXPORT_C void CEikScrollBar::SetDecreaseButtonsDimmed(TBool /*aDimmed*/)
+// Dim out the decrease buttons
+    {
+    }
+
+EXPORT_C void CEikScrollBar::SetIncreaseButtonsDimmed(TBool /*aDimmed*/)
+// Dim out the increase buttons
+    {
+    }
+
+EXPORT_C void CEikScrollBar::SetAllButtonsDimmed(TBool /*aDimmed*/)
+// Dim out all buttons
+    {
+    }
+
+void CEikScrollBar::CreateRequiredComponentsL()
+// Allocates and constructs all the required components of the scrollbar
+    {
+    if (iExtension)
+        {
+        iExtension->CreateRequiredComponentsL();
+        }
+    }
+
+EXPORT_C void CEikScrollBar::CreateButtonL(CAknScrollButton*& /*aButton*/,CAknScrollButton::TType /*aType*/)
+// Create the appropriate button
+    {
+    }
+
+void CEikScrollBar::DestroyButton(CAknScrollButton*& aButton)
+// destroy a button
+    {
+    delete aButton;
+    aButton=NULL;
+    }
+
+EXPORT_C void CEikScrollBar::SetButtonPositionL(CAknScrollButton* /*aButton*/)
+// Calculates and sets a buttons position,making necessary adjustments for densely packed buttons
+    {
+    }
+
+void CEikScrollBar::DoSetModel(const TEikScrollBarModel* aModel)
+// Just change the internal model checking it's valid
+    {
+    if (iExtension)
+        {
+        iExtension->DoSetModel(aModel);
+        }
+    }
+
+void CEikScrollBar::SizeChanged()
+    {
+    // Update position of components
+    if (iButtons.iIncreaseNudge)
+        {
+        TRAP_IGNORE(SetButtonPositionL(iButtons.iIncreaseNudge));
+        }
+    if (iButtons.iDecreaseNudge)
+        {
+        TRAP_IGNORE(SetButtonPositionL(iButtons.iDecreaseNudge));
+        }
+    }
+
+EXPORT_C TInt CEikScrollBar::DefaultScrollBarBreadth()
+    {
+    return KScrollBarWidth;
+    }
+
+EXPORT_C void CEikScrollBar::HandleControlEventL(CCoeControl* /*aControl*/, TCoeEvent /*aEventType*/)
+    {
+    }
+
+EXPORT_C void CEikScrollBar::HandlePointerEventL(const TPointerEvent& aPointerEvent)
+    {
+    CEikBorderedControl::HandlePointerEventL(aPointerEvent);
+    }
+
+EXPORT_C void CEikScrollBar::SetExtensionAreaType(TScrollBarExtensionAreaType aType)
+    {
+    if(ScrollBarType() == CEikScrollBar::EDoubleSpan)
+        {
+        CAknDoubleSpanScrollBarExtension* extension = static_cast<CAknDoubleSpanScrollBarExtension*> (iExtension);
+        extension->iExtensionType = aType;
+        }
+    }
+
+EXPORT_C void* CEikScrollBar::ExtensionInterface( TUid /*aInterface*/ )
+    {
+    return NULL;
+    }
+
+EXPORT_C void CEikScrollBar::Reserved_2()
+    {
+    }
+
+EXPORT_C void CEikScrollBar::MakeVisible(TBool aVisible)
+    {
+    if (COMPARE_BOOLS(aVisible, IsVisible()))
+        return;
+
+    TAknWindowLineLayout lay(AKN_LAYOUT_WINDOW_Control_pane_elements_Line_1);
+    TAknLayoutRect lr;
+    lr.LayoutRect( Rect(), lay );
+    TRect r( lr.Rect() );
+    SetExtent( r.iTl, TSize( aVisible ? r.Width() : 0, 2 * r.Height() ) );
+
+    // Arrow head scroll bar will not be displayed
+    if ( iExtension->ScrollBarType() == CEikScrollBar::EArrowHead )
+        {
+        CCoeControl::MakeVisible( EFalse );
+        }
+    else
+        {
+        CCoeControl::MakeVisible( aVisible );
+        }
+
+
+    if (Cba())
+        {
+        Cba()->UpdateCbaLabels( aVisible );
+        }
+    }
+
+EXPORT_C void CEikScrollBar::SetContainingCba(CEikCba* aCba)
+    {
+    // This is technically a compatability break, because it means that SetContainingCba
+    // must only be called after ConstructL(). Fortunately, the only place where this API
+    // should ever be called is already correct.
+    __ASSERT_ALWAYS(iExtension, Panic(EEikPanicScrollBarExtensionNotCreated));
+    iExtension->SetContainingCba(aCba);
+    }
+
+CEikCba* CEikScrollBar::Cba() const
+    {
+    if (iExtension)
+        return iExtension->Cba();
+    else
+        return NULL;
+    }
+
+void CEikScrollBar::AddExternalFrameL(CEikScrollBarFrame* aFrame)
+    {
+    __ASSERT_ALWAYS(iExtension, Panic(EEikPanicScrollBarExtensionNotCreated));
+    iExtension->AddExternalFrameL(aFrame);
+    }
+
+void CEikScrollBar::RemoveExternalFrame(CEikScrollBarFrame* aFrame)
+    {
+    __ASSERT_ALWAYS(iExtension, Panic(EEikPanicScrollBarExtensionNotCreated));
+    iExtension->RemoveExternalFrame(aFrame);
+    }
+
+void CEikScrollBar::DisconnectExternalFrames()
+    {
+    if (iExtension)
+        {
+        iExtension->DisconnectExternalFrames();
+        }
+    }
+
+CEikScrollBar::TScrollBarType CEikScrollBar::ScrollBarType()
+    {
+    if (iExtension)
+        {
+        return static_cast<CEikScrollBar::TScrollBarType> (iExtension->ScrollBarType());
+        }
+    return CEikScrollBar::TScrollBarType(ENormalScrollBar);
+     }
+
+
+
+// ----------------------------------------------------------------------------
+// CEikScrollBar::SetScrollBarObserver
+//
+// Sets scroll bar observer. This enables changing of the observer also after the
+// scroll bar has been constructed.
+// ----------------------------------------------------------------------------
+//
+void CEikScrollBar::SetScrollBarObserver(MEikScrollBarObserver* aScrollBarObserver)
+    {
+    if( !AknLayoutUtils::PenEnabled() )
+        {
+        return;
+        }
+
+    if(ScrollBarType() == CEikScrollBar::EDoubleSpan)
+        {
+        CAknDoubleSpanScrollBarExtension* extension = static_cast<CAknDoubleSpanScrollBarExtension*> (iExtension);
+        extension->SetScrollBarObserver(aScrollBarObserver);
+        }
+    else
+        {
+        CEikScrollBarExtension* extension = static_cast<CEikScrollBarExtension*> (iExtension);
+        extension->SetScrollBarObserver(aScrollBarObserver);
+        }
+    }
+
+//
+// class CEikScrollBarExtension
+//
+
+CEikScrollBarExtension::CEikScrollBarExtension(CEikScrollBar* aParent)
+: iExternalFrames(1)
+    {
+    iParent=aParent;
+    }
+
+CEikScrollBarExtension::~CEikScrollBarExtension()
+    {
+    }
+
+
+void CEikScrollBarExtension::SetLengthL(TInt /*aLength*/)
+    {
+    }
+
+void CEikScrollBarExtension::SetModelL(const TEikScrollBarModel* /*aModel*/)
+    {
+    }
+
+void CEikScrollBarExtension::SetModel(const TEikScrollBarModel* /*aModel*/)
+    {
+    }
+
+void CEikScrollBarExtension::SetLengthAndModelL(TInt /*aLength*/,const TEikScrollBarModel* /*aModel*/)
+    {
+    }
+
+void CEikScrollBarExtension::SetModelThumbPosition(TInt /*aThumbPos*/)
+    {
+    }
+
+void CEikScrollBarExtension::SetFocusPosToThumbPos(TInt /*aFocusPosition*/)
+    {
+    }
+
+TInt CEikScrollBarExtension::ThumbPosition() const
+    {
+    return(iParent->iModel.iThumbPosition);
+    }
+
+TInt CEikScrollBarExtension::ScrollBarBreadth() const
+    {
+    if (iParent->iOrientation==CEikScrollBar::EHorizontal)
+        return iParent->iSize.iHeight;
+    return iParent->iSize.iWidth;
+    }
+
+void CEikScrollBarExtension::SetDecreaseButtonsDimmed(TBool /*aDimmed*/)
+    {
+    }
+
+void CEikScrollBarExtension::SetIncreaseButtonsDimmed(TBool /*aDimmed*/)
+    {
+    }
+
+void CEikScrollBarExtension::SetAllButtonsDimmed(TBool /*aDimmed*/)
+    {
+    }
+
+void CEikScrollBarExtension::SetContainingCba(CEikCba* aCba)
+    {
+    iCba = aCba;
+    }
+
+TInt CEikScrollBarExtension::ScrollBarType()
+    {
+    return CEikScrollBar::EArrowHead;
+    }
+
+void CEikScrollBarExtension::CreateButtonL(CAknScrollButton*& /*aButton*/,CAknScrollButton::TType /*aType*/)
+    {
+    }
+
+void CEikScrollBarExtension::DoSetModel(const TEikScrollBarModel* aModel)
+    {
+    iParent->iModel=(*aModel);
+    iParent->iModel.CheckBounds();
+
+    TInt focusPosition=iParent->iModel.iThumbPosition;
+    if ((focusPosition!=-1) && iParent && iParent->iButtons.iIncreaseNudge && iParent->iButtons.iDecreaseNudge)
+        {
+        iParent->iButtons.iIncreaseNudge->SetPosition(focusPosition, iParent->iModel.iScrollSpan);
+        iParent->iButtons.iDecreaseNudge->SetPosition(focusPosition, iParent->iModel.iScrollSpan);
+        }
+    }
+
+CEikCba* CEikScrollBarExtension::Cba() const
+    {
+    return iCba;
+    }
+
+void CEikScrollBarExtension::AddExternalFrameL(CEikScrollBarFrame* aFrame)
+    {
+    iExternalFrames.AppendL(aFrame);
+    }
+
+
+void CEikScrollBarExtension::RemoveExternalFrame(CEikScrollBarFrame* aFrame)
+    {
+    TInt count = iExternalFrames.Count();
+    for (TInt ii=count-1; ii>=0; ii--)
+        {
+        if (iExternalFrames[ii] == aFrame)
+            {
+            iExternalFrames[ii]->DisconnectExternalScrollBar(iParent);
+            iExternalFrames.Delete(ii);
+            }
+        }
+    }
+
+void CEikScrollBarExtension::DisconnectExternalFrames()
+    {
+    TInt count = iExternalFrames.Count();
+    for (TInt ii=count-1; ii>=0; ii--)
+        {
+        iExternalFrames[ii]->DisconnectExternalScrollBar(iParent);
+        }
+    iExternalFrames.Reset();
+    }
+
+void CEikScrollBarExtension::CreateRequiredComponentsL()
+    {
+    TBool horiz=(iParent->iOrientation==CEikScrollBar::EHorizontal);
+    iParent->CreateButtonL(iParent->iButtons.iDecreaseNudge,horiz ? CAknScrollButton::ENudgeLeft : CAknScrollButton::ENudgeUp);
+    iParent->CreateButtonL(iParent->iButtons.iIncreaseNudge,horiz ? CAknScrollButton::ENudgeRight : CAknScrollButton::ENudgeDown);
+    }
+
+void CEikScrollBarExtension::DestroyButton(CAknScrollButton*& /*aButton*/)
+    {
+    }
+
+void CEikScrollBarExtension::SetButtonPositionL(CAknScrollButton* /*aButton*/)
+    {
+    }
+
+
+void CEikScrollBarExtension::SetScrollBarObserver(MEikScrollBarObserver* aScrollBarObserver)
+    {
+    iScrollBarObserver = aScrollBarObserver;
+    }
+
+MEikScrollBarObserver* CEikScrollBarExtension::ScrollBarObserver()
+    {
+    return iScrollBarObserver;
+    }
+
+TBool CEikScrollBarExtension::HasModelChanged(const TEikScrollBarModel* /*aModel*/)
+    {
+    return EFalse;
+    }
+TInt CEikScrollBarExtension::Reserved_1(){return 0;};
+TInt CEikScrollBarExtension::Reserved_2(){return 0;};
+
+
+
+//
+// class CEikArrowHeadScrollBar
+//
+
+EXPORT_C CEikArrowHeadScrollBar::CEikArrowHeadScrollBar(CCoeControl* aParentWindow)
+    : iParentControl(aParentWindow)
+    {
+    AKNTASHOOK_ADD( this, "CEikArrowHeadScrollBar" );
+    }
+
+EXPORT_C CEikArrowHeadScrollBar::~CEikArrowHeadScrollBar()
+    {
+    AKNTASHOOK_REMOVE();
+    }
+
+EXPORT_C void CEikArrowHeadScrollBar::ConstructL(MEikScrollBarObserver* aScrollBarObserver,const CCoeControl* aParent,
+                                                 TOrientation aOrientation,TInt aLength,TInt aScrollBarFlags)
+// Second-phase construction
+    {
+    iExtension = new(ELeave) CEikScrollBarExtension(this);
+    CEikScrollBar::ConstructL(aScrollBarObserver,aParent,aOrientation,aLength,aScrollBarFlags);
+    }
+
+void CEikArrowHeadScrollBar::CreateButtonL(CAknScrollButton*& aButton,CAknScrollButton::TType aType)
+// Create the appropriate button
+    {
+    if (aButton)
+        return;
+    CAknScrollButton* button=CAknScrollButton::NewL(aType);
+    CleanupStack::PushL(button);
+     button->CreateWindowOnlyForArrowsL(iParentControl);
+    button->SetObserver((MCoeControlObserver*)this);
+    SetButtonPositionL(button);
+    button->SetTypeOfScrollBarUsingButton(CAknScrollButton::EArrowHead);
+    CleanupStack::Pop(); // button
+    aButton=button;
+    }
+
+void CEikArrowHeadScrollBar::SetButtonPositionL(CAknScrollButton* aButton)
+    {
+    TInt index = aButton->Type()==CAknScrollButton::ENudgeDown ? 1 : 0;
+    TAknWindowLineLayout lay( AKN_LAYOUT_TABLE_Control_pane_elements(index) );
+    TAknLayoutRect lr;
+    lr.LayoutRect( Rect(), lay );
+    TRect r( lr.Rect() );
+    aButton->SetExtent( r.iTl, TSize( Size().iWidth, r.Height() ) );
+    }
+
+EXPORT_C void CEikArrowHeadScrollBar::HandlePointerEventL(const TPointerEvent& aPointerEvent)
+    {
+    CEikScrollBar::HandlePointerEventL(aPointerEvent);
+    }
+
+EXPORT_C void* CEikArrowHeadScrollBar::ExtensionInterface( TUid /*aInterface*/ )
+    {
+    return NULL;
+    }
+
+//
+// class CAknDoubleSpanScrollBar
+//
+EXPORT_C CAknDoubleSpanScrollBar::CAknDoubleSpanScrollBar(CCoeControl* aParentWindow)
+    : iParentControl(aParentWindow)
+    {
+    AKNTASHOOK_ADD( this, "CAknDoubleSpanScrollBar" );
+    }
+
+EXPORT_C CAknDoubleSpanScrollBar::~CAknDoubleSpanScrollBar()
+    {
+    AKNTASHOOK_REMOVE();
+    if ( iAvkonAppUiBase )
+        {
+        CAknPointerEventModifier* modifier = iAvkonAppUiBase->PointerEventModifier();
+        
+        if ( modifier )
+            {
+            modifier->Pop( *this );
+            }
+        }
+        
+    AknsUtils::DeregisterControlPosition( this );
+    }
+
+EXPORT_C void CAknDoubleSpanScrollBar::ConstructL(TBool aWindowOwning, MEikScrollBarObserver* aScrollBarObserver,const CCoeControl* aParent,
+                                                 TOrientation aOrientation,TInt /*aLength*/,TInt aScrollBarFlags )
+    {
+    iExtension = new(ELeave) CAknDoubleSpanScrollBarExtension(this);
+    CAknDoubleSpanScrollBarExtension* extension = static_cast<CAknDoubleSpanScrollBarExtension*> (iExtension);
+
+    extension->iScrollBarFlags = aScrollBarFlags;
+    extension->iExtensionType = ENormalExpandedTouchArea;
+
+    if ( AknLayoutUtils::PenEnabled() )
+        {
+        extension->SetScrollBarObserver(aScrollBarObserver); // sets also the owning observer
+
+        extension->iPopupController = CAknInfoPopupNoteController::NewL();
+        extension->iPopupController->SetTooltipModeL( ETrue );
+        extension->iPopupController->SetTimeDelayBeforeShow( 1 );
+        extension->iShowPopup = EFalse;
+        }
+
+    if (aWindowOwning)
+        {
+        CreateWindowL(aParent);
+        if ( CAknEnv::Static()->TransparencyEnabled() )
+            {
+            Window().SetRequiredDisplayMode( EColor16MA );
+            if ( Window().SetTransparencyAlphaChannel() == KErrNone )
+                {
+                Window().SetBackgroundColor( ~0 );
+                }
+            }
+        }
+    else if(aParent)
+        {
+        SetContainerWindowL(*aParent);
+        }
+    else
+        {
+        User::Leave(KErrArgument);
+        }
+
+    if( aParent )
+        SetObserver(aParent->Observer());
+    else
+        SetObserver(NULL);
+
+    iOrientation=aOrientation;
+    CreateRequiredComponentsL();
+
+    if (aWindowOwning)
+        {
+        Window().SetPointerGrab(ETrue);
+        EnableDragEvents();
+        if (extension->iScrollIndicator)
+               extension->iScrollIndicator->SetAsWindowOwning(ETrue);
+
+
+        // By default set background to transparent
+        SetTransparentBackground(ETrue);
+        }
+
+    SetComponentsToInheritVisibility(ETrue);
+    MakeVisible(EFalse);
+    ActivateL();
+    }
+
+
+EXPORT_C void CAknDoubleSpanScrollBar::ConstructL(MEikScrollBarObserver* aScrollBarObserver,const CCoeControl* aParent,
+                                                 TOrientation aOrientation,TInt aLength,TInt aScrollBarFlags)
+// Second-phase construction, overides method from CEikScrollBar
+    {
+    ConstructL(ETrue, aScrollBarObserver, aParent, aOrientation, aLength, aScrollBarFlags);
+    }
+
+
+// ----------------------------------------------------------------------------
+// CAknDoubleSpanScrollBar::CreateButtonL
+//
+// Creates buttons for double span scrollbar when __PEN_SUPPORT is enabled
+// ----------------------------------------------------------------------------
+//
+void CAknDoubleSpanScrollBar::CreateButtonL(CAknScrollButton*& aButton, CAknScrollButton::TType aType)
+// Create the appropriate button
+    {
+    if( !AknLayoutUtils::PenEnabled() )
+        {
+        // No buttons exist in this type of scrollbar
+        return;
+        }
+
+    if (aButton)
+        {
+        return;
+        }
+    CAknScrollButton* button = CAknScrollButton::NewL(aType, CAknScrollButton::ENormal);
+    CleanupStack::PushL(button);
+    if ( OwnsWindow() && AknLayoutUtils::PenEnabled() )
+        {
+        button->CreateWindowOnlyForArrowsL( this );
+        }
+    button->SetContainerWindowL( *this );
+
+    CleanupStack::Pop(); // button
+    aButton = button;
+    }
+
+
+// ----------------------------------------------------------------------------
+// CAknDoubleSpanScrollBar::SetButtonPositionL
+//
+// Sets button position when AknLayoutUtils::PenEnabled() returns ETrue
+// This function is called from CAknDoubleSpanScrollBar::SizeChanged() function
+// The button rectangle should be set in this function according to LAF spec
+// ----------------------------------------------------------------------------
+//
+void CAknDoubleSpanScrollBar::SetButtonPositionL(CAknScrollButton* aButton)
+    {
+    if( !AknLayoutUtils::PenEnabled() )
+        {
+        // No buttons exist in this type of scrollbar
+        return;
+        }
+
+    if ( aButton )
+        {
+        if( iExtension )
+            {
+            TAknWindowComponentLayout buttonLayout;
+            TAknLayoutRect buttonRect;
+
+            switch(aButton->Type())
+                {
+                case CAknScrollButton::ENudgeUp:
+                    buttonLayout = AknLayoutScalable_Avkon::scroll_sc2_up_pane( 1 );
+                    buttonRect.LayoutRect( Rect(), buttonLayout.LayoutLine() );
+                    aButton->SetRect( buttonRect.Rect() );
+                    break;
+                case CAknScrollButton::ENudgeDown:
+                    buttonLayout = AknLayoutScalable_Avkon::scroll_sc2_down_pane( 1 );
+                    buttonRect.LayoutRect( Rect(), buttonLayout.LayoutLine() );
+                    aButton->SetRect( buttonRect.Rect() );
+                    break;
+                case CAknScrollButton::ENudgeLeft:
+                    buttonLayout = AknLayoutScalable_Avkon::scroll_sc2_left_pane();
+                    buttonRect.LayoutRect( Rect(), buttonLayout.LayoutLine() );
+                    aButton->SetRect( buttonRect.Rect() );
+                    break;
+                case CAknScrollButton::ENudgeRight:
+                    buttonLayout = AknLayoutScalable_Avkon::scroll_sc2_right_pane();
+                    buttonRect.LayoutRect( Rect(), buttonLayout.LayoutLine() );
+                    aButton->SetRect( buttonRect.Rect() );
+                    break;
+                default:
+                    break;
+                }
+            }
+        }
+    }
+
+
+EXPORT_C void CAknDoubleSpanScrollBar::MakeVisible(TBool aVisible)
+    {
+    CAknPointerEventModifier* modifier = iAvkonAppUiBase ? iAvkonAppUiBase->PointerEventModifier() : NULL;
+    
+    if ( modifier )
+        {
+        CAknDoubleSpanScrollBarExtension* extension = static_cast<CAknDoubleSpanScrollBarExtension*> (iExtension);
+        if ( aVisible  && (extension->iScrollIndicator->ScrollSpan() > 0) )
+            {
+            modifier->Push( *this, ExtensionArea() );
+            }
+        else
+            {
+            modifier->Pop( *this );
+            }
+        }
+
+    CCoeControl::MakeVisible(aVisible);
+    }
+
+EXPORT_C TInt CAknDoubleSpanScrollBar::CountComponentControls() const
+    {
+    TInt controlCount = 0;
+    if (iExtension)
+        {
+        CAknDoubleSpanScrollBarExtension* extension = static_cast<CAknDoubleSpanScrollBarExtension*> (iExtension);
+        if (extension->iScrollIndicator)
+            {
+            controlCount = 1;
+            }
+        }
+    if(AknLayoutUtils::PenEnabled())
+        {
+        if(iButtons.iIncreaseNudge)
+            {
+            controlCount++;
+            }
+        if(iButtons.iDecreaseNudge)
+            {
+            controlCount++;
+            }
+        }
+
+    return controlCount;
+    }
+
+EXPORT_C CCoeControl* CAknDoubleSpanScrollBar::ComponentControl(TInt aIndex) const
+    {
+    CCoeControl* control = NULL;
+    if (aIndex==0 && iExtension)
+        {
+        CAknDoubleSpanScrollBarExtension* extension = static_cast<CAknDoubleSpanScrollBarExtension*> (iExtension);
+        control = extension->iScrollIndicator;
+        }
+    if(AknLayoutUtils::PenEnabled())
+        {
+        if(aIndex == 1)
+            {
+            control = iButtons.iIncreaseNudge;
+            }
+        else if(aIndex == 2)
+            {
+            control = iButtons.iDecreaseNudge;
+            }
+        }
+
+    return control;
+    }
+
+
+EXPORT_C void CAknDoubleSpanScrollBar::SizeChanged()
+    {
+    CAknPointerEventModifier* modifier = iAvkonAppUiBase ? iAvkonAppUiBase->PointerEventModifier() : NULL;
+    
+    if ( modifier && IsVisible() )
+        {
+        modifier->Update( *this, ExtensionArea() );
+        }
+
+    AknsUtils::RegisterControlPosition( this );
+    if (iExtension)
+        {
+        CAknDoubleSpanScrollBarExtension* extension = static_cast<CAknDoubleSpanScrollBarExtension*> (iExtension);
+        CAknDoubleSpanScrollIndicator* indicator = extension->iScrollIndicator;
+        // set indicator size to same as the whole scrollbar.
+        if (indicator)
+           {
+            TAknWindowComponentLayout combinedRect;
+
+            TInt variety = 0;
+            TInt scVariety = 0;
+            // No pen check as the layout for the non-pen is not taken from layout data
+            // if in future made so, this must be changed to support also non-pen situations
+            if( AknLayoutUtils::PenEnabled() )
+                {
+                if ( iOrientation == EHorizontal)
+                    {
+                    variety = 2;
+                    scVariety = 1;
+                    }
+                else
+                    {
+                    variety = 1;
+                    }
+                }
+
+
+            combinedRect = TAknWindowComponentLayout::Compose( AknLayoutScalable_Avkon::scroll_pane( scVariety ),
+                                                               AknLayoutScalable_Avkon::bg_scroll_pane( variety ) );
+            TAknLayoutRect indicatorRect;
+
+            if (OwnsWindow())
+                {
+                if( AknLayoutUtils::PenEnabled() &&
+                    ( extension->iScrollBarFlags & EEnableNudgeButtons ) )
+                    {
+                    // when the pen support is enabled, the space for arrows must be reserved.
+                    indicatorRect.LayoutRect( Rect(), combinedRect.LayoutLine() );
+                    indicator->SetRect( indicatorRect.Rect() );
+                    }
+                else
+                    {
+                    indicator->SetExtent(TPoint(0,0),Size());
+                    }
+
+                if (indicator->TransparentBackground())
+                    {
+                    // This will refresh the transparency masks
+                    SetTransparentBackground(ETrue);
+                    }
+                }
+            else
+                {
+                if( AknLayoutUtils::PenEnabled() &&
+                    ( extension->iScrollBarFlags & EEnableNudgeButtons ) )
+                    {
+                    // when the pen support is enabled, the space for arrows must be reserved.
+                    TRect rect( Position(), Size() );
+                    indicatorRect.LayoutRect( rect, combinedRect.LayoutLine() );
+                    indicator->SetRect( indicatorRect.Rect() );
+                    }
+                else
+                    {
+                    indicator->SetExtent(Position(),Size());
+                    }
+                }
+            }
+
+        if(AknLayoutUtils::PenEnabled())
+            {
+            if ( !iButtons.iIncreaseNudge || !iButtons.iDecreaseNudge )
+                {
+                TRAP_IGNORE( CreateRequiredComponentsL() );
+                }
+            // Set scroll button positions
+            TRAP_IGNORE( SetButtonPositionL( iButtons.iIncreaseNudge ) );
+            TRAP_IGNORE( SetButtonPositionL( iButtons.iDecreaseNudge ) );
+            }
+        }
+    }
+
+
+// ----------------------------------------------------------------------------
+// CAknDoubleSpanScrollBar::HandlePointerEventL
+//
+// Handles pointer events.
+// ----------------------------------------------------------------------------
+//
+EXPORT_C void CAknDoubleSpanScrollBar::HandlePointerEventL(const TPointerEvent& aPointerEvent)
+    {
+    if( !AknLayoutUtils::PenEnabled() || !iExtension)
+        {
+        return;
+        }
+
+    if ( aPointerEvent.iType == TPointerEvent::EButton1Down && GrabbingComponent() != this && OwnsWindow() )
+        {
+        ClaimPointerGrab( EFalse );
+        }
+
+    CAknDoubleSpanScrollBarExtension* extension =
+        static_cast<CAknDoubleSpanScrollBarExtension*> (iExtension);
+    CAknDoubleSpanScrollIndicator* indicator = extension->iScrollIndicator;
+
+    RDrawableWindow* pointerWindow = &Window();
+    TRect rect(indicator->Rect());
+
+    // scale the pointer event position relative to indicator rect
+    // this has effect only if the scroll bar is not window owning
+    TPoint eventPos(aPointerEvent.iPosition - rect.iTl);
+
+    // use x or y values depending on orientation
+    TInt position(eventPos.iY);
+    TInt scrollSpanPix(rect.Height());
+    if(iOrientation == EHorizontal)
+        {
+        position = eventPos.iX;
+        scrollSpanPix = rect.Width();
+        }
+
+    // get current values from the indicator
+    TInt scrollSpan(indicator->ScrollSpan());
+    TInt thumbSpan(indicator->WindowSize());
+    TInt thumbPosition(indicator->FocusPosition());
+    TInt thumbSpanPix     = indicator->GetCurrentThumbSpanInPixels();
+    TInt thumbPositionPix = indicator->GetCurrentThumbPositionInPixels();
+    // clear the pointer down info on pen up and hide info popup
+    TInt lastPointerDownOn = extension->iPointerDownOn;
+    // The real span area available (as pixels)
+    scrollSpanPix -= thumbSpanPix;
+
+            
+         // touch release on thumb
+         TBool thumbPressed = 
+                 ( position < (thumbPositionPix + thumbSpanPix) 
+                         && position > thumbPositionPix );
+         if ( thumbPressed &&
+              aPointerEvent.iType == TPointerEvent::EButton1Up &&
+              thumbSpan < scrollSpan )
+             {
+             MTouchFeedback* feedback = MTouchFeedback::Instance();
+
+             CCoeControl* parent = Parent();
+             TBool feedbackEnabled = !IsDimmed() && IsVisible();
+             if (parent && feedbackEnabled)
+                 {
+                 // check the same for the parent
+                 feedbackEnabled = !parent->IsDimmed() && parent->IsVisible();
+                 }
+             if ( feedback && feedbackEnabled )
+                 {
+                 feedback->InstantFeedback( this, 
+                                            ETouchFeedbackSlider, 
+                                            ETouchFeedbackVibra, 
+                                            aPointerEvent );
+                 }
+             }
+     
+    // check that scroll bar is useful
+    if (thumbSpan < scrollSpan)
+        {
+        // check where the pointer down occured
+        if(aPointerEvent.iType == TPointerEvent::EButton1Down )
+            {
+            indicator->SetBackgroudHighlight( ETrue );
+
+            extension->iPointerDownPosition  = position;
+            
+            if(iButtons.iIncreaseNudge &&
+               iButtons.iIncreaseNudge->Rect().Contains(aPointerEvent.iPosition))
+                {
+                extension->iPointerDownOn = CEikScrollBar::EIncreaseNudgeButton;
+                }
+            else if(iButtons.iDecreaseNudge &&
+                    iButtons.iDecreaseNudge->Rect().Contains(aPointerEvent.iPosition))
+                {
+                extension->iPointerDownOn = CEikScrollBar::EDecreaseNudgeButton;
+                }
+            else if (position < thumbPositionPix)
+                {
+                extension->iPointerDownOn = CEikScrollBar::EDecreaseShaft;
+                }
+            else if (position < (thumbPositionPix + thumbSpanPix))
+                {
+                extension->iDragged = EFalse;
+                extension->iPointerDownOn = CEikScrollBar::EThumb;
+                extension->iPointerOffsetFromThumb = position - thumbPositionPix;
+
+                indicator->SetHandleHighlight( ETrue );
+                indicator->DrawDeferred();
+                }
+            else
+                {
+                extension->iPointerDownOn = CEikScrollBar::EIncreaseShaft;
+                }
+            }
+
+        if (aPointerEvent.iType == TPointerEvent::EButton1Up)
+            {
+            extension->iPointerDownOn = CEikScrollBar::ENone;
+
+            // Highlight off always when the pointer is lifted
+            indicator->SetHandleHighlight( EFalse );
+            indicator->DrawDeferred();
+            indicator->SetBackgroudHighlight( EFalse );
+
+            if ( extension->iPopupController )
+                {
+                extension->iPopupController->HideInfoPopupNote();
+                    extension->iShowPopup = EFalse;
+                }
+            }
+
+        // respond to the pointer event
+        switch(extension->iPointerDownOn)
+            {
+            case CEikScrollBar::EDecreaseShaft:
+            case CEikScrollBar::EIncreaseShaft:
+                {
+                TEikScrollEvent event = EEikScrollPageUp;
+                if(aPointerEvent.iType == TPointerEvent::EButton1Down ||
+                   aPointerEvent.iType == TPointerEvent::EButtonRepeat)
+                    {
+                    if(extension->iPointerDownOn == CEikScrollBar::EDecreaseShaft)
+                        {
+                        event = iOrientation==EHorizontal ? EEikScrollPageLeft : EEikScrollPageUp;
+                        thumbPosition -= thumbSpan;
+                        thumbPosition = Max(0, thumbPosition);
+
+
+                        TInt prevPosValue = extension->ThumbPosition();
+                        
+                        // This will update the thumb's pixel extent, used
+                        // below
+                        extension->SetModelThumbPosition(thumbPosition);
+                        indicator->SetIndicatorValues(scrollSpan, thumbPosition, thumbSpan, 0, 0);
+
+                        TInt afterPosValue = extension->ThumbPosition();
+                        if (prevPosValue != afterPosValue)
+                            {
+                            MTouchFeedback* feedback = MTouchFeedback::Instance();
+
+                            CCoeControl* parent = Parent();
+                            TBool feedbackEnabled = !IsDimmed() && IsVisible();
+                            if (parent && feedbackEnabled)
+                                {
+                                // check the same for the parent
+                                feedbackEnabled = !parent->IsDimmed() && parent->IsVisible();
+                                }
+                            if ( feedback && feedbackEnabled )
+                                {
+                                feedback->InstantFeedback( this, ETouchFeedbackSlider, aPointerEvent );
+                                }
+                            }
+
+                        // request pointer repeat until the thumb reaches the pen down position
+                        TInt newThumbPosPix = indicator->GetCurrentThumbPositionInPixels();
+                        if(position < newThumbPosPix)
+                            {
+                            TRect ignoreRect(rect);
+                            TRect rt = ExtensionArea();
+                            if(iOrientation == EVertical)
+                                {
+                                ignoreRect.iTl = TPoint(rt.iTl.iX, rect.iTl.iY);
+                                ignoreRect.iBr = TPoint(ignoreRect.iBr.iX, newThumbPosPix + rect.iTl.iY);
+                                }
+                            else
+                                {
+                                ignoreRect.iTl = TPoint(rect.iTl.iX, rt.iTl.iY);
+                                ignoreRect.iBr = TPoint(newThumbPosPix, rt.iBr.iY);
+                                }
+                            // repeat until thumb reaches the stylus down position
+                            pointerWindow->RequestPointerRepeatEvent(KScrollRepeatTimeout, ignoreRect);
+                            }
+                        
+
+                        }
+                    else
+                        {
+                        event = iOrientation==EHorizontal ? EEikScrollPageRight : EEikScrollPageDown;
+                        thumbPosition += thumbSpan;
+                        thumbPosition = Min((scrollSpan - thumbSpan), thumbPosition);
+
+                        TInt prevPosValue = extension->ThumbPosition();
+                        extension->SetModelThumbPosition(thumbPosition);
+                        indicator->SetIndicatorValues(scrollSpan, thumbPosition, thumbSpan, 0, 0);
+
+                        TInt afterPosValue = extension->ThumbPosition();
+                        if (prevPosValue != afterPosValue)
+                            {
+                            MTouchFeedback* feedback = MTouchFeedback::Instance();
+
+                            CCoeControl* parent = Parent();
+                            TBool feedbackEnabled = !IsDimmed() && IsVisible();
+                            if (parent && feedbackEnabled)
+                                {
+                                // check the same for the parent
+                                feedbackEnabled = !parent->IsDimmed() && parent->IsVisible();
+                                }
+                            if ( feedback && feedbackEnabled )
+                                {
+                                feedback->InstantFeedback( this, ETouchFeedbackSlider, aPointerEvent );
+                                }
+                            }
+
+                        // request pointer repeat until the thumb reaches the pen down position
+                        TInt newThumbPosPix = indicator->GetCurrentThumbPositionInPixels();
+                        newThumbPosPix += thumbSpanPix;
+
+                        if(position > newThumbPosPix )
+                            {
+                            TRect ignoreRect(rect);
+                            TRect rt = ExtensionArea();
+                            if(iOrientation == EVertical)
+                                {
+                                ignoreRect.iTl = TPoint(rt.iTl.iX, newThumbPosPix + rect.iTl.iY);
+                                }
+                            else
+                                {
+                                ignoreRect.iTl = TPoint(newThumbPosPix, rt.iTl.iY);
+                                }
+                            // repeat until thumb reaches the stylus down position
+                            pointerWindow->RequestPointerRepeatEvent(KScrollRepeatTimeout, ignoreRect);
+
+                            }
+                        
+                        }
+
+                    if(indicator->DrawBackgroundState())
+                        indicator->DrawNow();
+                    else
+                        indicator->DrawDeferred();
+
+                    if(extension->ScrollBarObserver())
+                        {
+                        extension->ScrollBarObserver()->HandleScrollEventL(this, event);
+                        }
+                    }
+
+                }
+                break;
+
+            case CEikScrollBar::EThumb:
+                if( aPointerEvent.iType == TPointerEvent::EButton1Down )
+                    {
+                    MTouchFeedback* feedback = MTouchFeedback::Instance();
+
+                    if ( feedback )
+                        {
+                        TTouchFeedbackType fbType = TTouchFeedbackType( 
+                                                        ETouchFeedbackAudio |
+                                                        ETouchFeedbackVibra );
+                          
+                        feedback->InstantFeedback( this, ETouchFeedbackSlider, fbType, aPointerEvent );
+                        }
+                    }
+
+                if( aPointerEvent.iType == TPointerEvent::EDrag 
+                   || aPointerEvent.iType == TPointerEvent::EButtonRepeat )
+                    {
+                    // performace improving. Too many drag event received, handling every single event 
+                    // will use too much CPU time.
+                    TTime now;
+                    now.HomeTime();                    
+                    if ( extension->iDragged &&
+                         now.MicroSecondsFrom( extension->iLastDrag ) 
+                         < KScrollDragTimeout )
+                        {                        
+                        break; // ignore drag for this time
+                        }
+                    extension->iDragged = ETrue; // after this time, iLastDragged has value.
+                    extension->iLastDrag = now;
+                    
+                    thumbPositionPix = position - extension->iPointerOffsetFromThumb;
+                    TInt oldPosition = thumbPosition;
+                    TReal newPosition = thumbPositionPix * ( scrollSpan - thumbSpan ) / (TReal)scrollSpanPix;
+                    thumbPosition = newPosition;
+
+                    // round the value to the nearest possible position
+                    if( TInt(newPosition * 2) >= ((thumbPosition * 2) + 1 ))
+                        {
+                        ++thumbPosition;
+                        }
+
+                    // enforce limits
+                    thumbPosition = Max(0, thumbPosition);
+                    thumbPosition = Min((scrollSpan - thumbSpan), thumbPosition);
+
+                    if(thumbPosition != oldPosition)
+                        {
+                        // Smooth continuous tactile feedback is produced
+                        // during thumb dragging. The tactile feedback API 
+                        // filters out possible re-startings of the effect.
+                        MTouchFeedback* feedback = MTouchFeedback::Instance();
+
+                        if ( feedback )
+                            {
+                            TTimeIntervalMicroSeconds32 timeout( 300000 );
+                            feedback->StartFeedback( this, 
+                                                     ETouchContinuousSlider, 
+                                                     &aPointerEvent, 
+                                                     KIntensity, // intensity 50%
+                                                     timeout );
+                            }
+                        extension->SetModelThumbPosition(thumbPosition);
+                        indicator->SetIndicatorValues(scrollSpan, thumbPosition, thumbSpan, 0, 0);
+
+                        if(indicator->DrawBackgroundState())
+                            indicator->DrawNow();
+                        else
+                            indicator->DrawDeferred();
+
+                        if(extension->ScrollBarObserver())
+                            {
+                            extension->ScrollBarObserver()->HandleScrollEventL(
+                                this,
+                                iOrientation==EHorizontal ? EEikScrollThumbDragHoriz : EEikScrollThumbDragVert);
+                            }
+                        }
+                    // Show popup info
+                    if ( extension->iShowPopup && extension->iPopupController )
+                        {
+                        TPoint infoPoint = PositionRelativeToScreen();
+
+                        if ( iOrientation == EVertical )
+                            {
+                            if ( AknLayoutUtils::LayoutMirrored() )
+                                {
+                                infoPoint.iX += Rect().Width();
+                                infoPoint.iY += aPointerEvent.iPosition.iY;
+                                extension->iPopupController->SetPositionAndAlignment (
+                                    infoPoint, EHLeftVCenter );
+                                }
+                            else
+                                {
+                                infoPoint.iY += aPointerEvent.iPosition.iY;
+                                extension->iPopupController->SetPositionAndAlignment (
+                                    infoPoint, EHRightVCenter );
+                                }
+                            }
+                        else if ( iOrientation == EHorizontal )
+                            {
+                            infoPoint.iX += aPointerEvent.iPosition.iX;
+                            extension->iPopupController->SetPositionAndAlignment(
+                                infoPoint, EHCenterVBottom );
+                            }
+                        extension->iPopupController->ShowInfoPopupNote();
+                        extension->iShowPopup = EFalse;
+                        }
+                    }
+                break;
+
+            case CEikScrollBar::ENone:
+                {
+                // Stop the continuous tactile feedback that may be playing
+                // at the time due to possible previous thumb dragging.
+                MTouchFeedback* feedback = MTouchFeedback::Instance();
+
+                if ( feedback )
+                    {
+                    feedback->StopFeedback( this );
+                    }
+                }
+
+                if(lastPointerDownOn == CEikScrollBar::EThumb)
+                    {
+                    if(extension->ScrollBarObserver())
+                        {
+                        extension->ScrollBarObserver()->HandleScrollEventL(
+                            this,
+                            iOrientation==EHorizontal ? EEikScrollThumbReleaseHoriz : EEikScrollThumbReleaseVert);
+                        }
+
+                    }
+                break;
+
+            case CEikScrollBar::EIncreaseNudgeButton:
+                // handle increase scroll button press (right or down button)
+                if(aPointerEvent.iType == TPointerEvent::EButton1Down ||
+                   aPointerEvent.iType == TPointerEvent::EButtonRepeat)
+                    {
+                    TInt oldPosition = thumbPosition;
+                    thumbPosition++;
+                    thumbPosition = Min((scrollSpan - thumbSpan), thumbPosition);
+
+                    if(oldPosition != thumbPosition)
+                        {
+                        // Note: Depending on layout and style the nudge
+                        //       button may be obsolete.
+                        // Sensitive feedback given for each "nudge"
+                        MTouchFeedback* feedback = MTouchFeedback::Instance();
+                        if ( feedback )
+                            {
+                            feedback->InstantFeedback ( this, ETouchFeedbackSlider, aPointerEvent );
+                            }
+                        extension->SetModelThumbPosition(thumbPosition);
+                        indicator->SetIndicatorValues(scrollSpan, thumbPosition, thumbSpan, 0, 0);
+                        if(indicator->DrawBackgroundState())
+                            indicator->DrawNow();
+                        else
+                            indicator->DrawDeferred();
+                        }
+
+                    // even if the thumb position did not change (thumb has reached its last
+                    // possible position), we must send the event
+                    // to the observer, so that it can implement the looping scrolling if necessary
+                    if(extension->ScrollBarObserver())
+                        {
+                        extension->ScrollBarObserver()->HandleScrollEventL(
+                            this,
+                            iOrientation==EHorizontal ? EEikScrollRight : EEikScrollDown);
+                        }
+                    // repeat untill stylus is lifted or dragged outside the button
+                    TRect nudgeRect( iButtons.iIncreaseNudge->Rect() );
+
+                    pointerWindow->RequestPointerRepeatEvent(KScrollRepeatTimeout, nudgeRect );
+                    }
+
+                break;
+
+            case CEikScrollBar::EDecreaseNudgeButton:
+                // handle decrease scroll button press (left or up button)
+                if(aPointerEvent.iType == TPointerEvent::EButton1Down ||
+                   aPointerEvent.iType == TPointerEvent::EButtonRepeat)
+                    {
+                    TInt oldPosition = thumbPosition;
+                    thumbPosition--;
+                    thumbPosition = Max(0, thumbPosition);
+                    if(oldPosition != thumbPosition)
+                        {
+                        // Note: Depending on layout and style the nudge
+                        //       button may be obsolete.
+                        // Sensitive feedback given for each "nudge"
+                        MTouchFeedback* feedback = MTouchFeedback::Instance();
+                        if ( feedback )
+                            {
+                            feedback->InstantFeedback ( this, ETouchFeedbackSlider, aPointerEvent );
+                            }
+                        extension->SetModelThumbPosition(thumbPosition);
+                        indicator->SetIndicatorValues(scrollSpan, thumbPosition, thumbSpan, 0, 0);
+                        if(indicator->DrawBackgroundState())
+                            indicator->DrawNow();
+                        else
+                            indicator->DrawDeferred();
+                        }
+
+                    // even if the thumb position did not change (thumb has reached its first
+                    // possible position), we must send the event
+                    // to the observer, so that it can implement the looping scrolling if necessary
+                    if(extension->ScrollBarObserver())
+                        {
+                        extension->ScrollBarObserver()->HandleScrollEventL(
+                            this,
+                            iOrientation==EHorizontal ? EEikScrollLeft : EEikScrollUp);
+                        }
+                    // repeat untill stylus is lifted or dragged outside the button
+                    TRect nudgeRect( iButtons.iDecreaseNudge->Rect() );
+
+                    pointerWindow->RequestPointerRepeatEvent(KScrollRepeatTimeout, nudgeRect );
+                    }
+
+                break;
+
+            default:
+                break;
+
+            } // end: of switch
+
+        } // end of: if (thumbSpan < scrollSpan)
+    }
+
+EXPORT_C void* CAknDoubleSpanScrollBar::ExtensionInterface( TUid /*aInterface*/ )
+    {
+    return NULL;
+    }
+
+EXPORT_C void CAknDoubleSpanScrollBar::SetFixedLayoutRect(TRect aScrollBarRect)
+    {
+    if (iExtension)
+        {
+        CAknDoubleSpanScrollBarExtension* extension = static_cast<CAknDoubleSpanScrollBarExtension*> (iExtension);
+        extension->iFixedLayoutRect = aScrollBarRect;
+        SetRect(aScrollBarRect);
+        }
+    }
+
+EXPORT_C void CAknDoubleSpanScrollBar::SetScrollPopupInfoTextL( const TDesC& aText )
+    {
+    if ( !AknLayoutUtils::PenEnabled() )
+        {
+        return;
+        }
+
+    if ( iExtension )
+        {
+        CAknDoubleSpanScrollBarExtension* extension = static_cast<CAknDoubleSpanScrollBarExtension*> (iExtension);
+
+        if ( extension->iPopupController )
+            {
+            if ( aText.Length() > 0 )
+                {
+                extension->iPopupController->SetTextL( aText );
+                extension->iShowPopup = ETrue;
+                }
+            else
+                {
+                extension->iPopupController->HideInfoPopupNote();
+                extension->iShowPopup = EFalse;
+                }
+            }
+        }
+    }
+
+TRect CAknDoubleSpanScrollBar::FixedLayoutRect()
+    {
+    TRect fixedLayoutRect;
+    if (iExtension)
+        {
+        CAknDoubleSpanScrollBarExtension* extension = static_cast<CAknDoubleSpanScrollBarExtension*> (iExtension);
+        fixedLayoutRect = extension->iFixedLayoutRect;
+        }
+    return fixedLayoutRect;
+    }
+
+void CAknDoubleSpanScrollBar::SetTransparentBackground(TBool aTransparentBackground)
+    {
+    // In transparency-enabled builds, consider making this function
+    // act as if DrawBackground( EFalse ) was called..
+
+    TBool transparencyIsSupported = EFalse; // Transparent windows are not supported for now
+
+    if (iExtension && OwnsWindow() && transparencyIsSupported)
+        {
+        CAknDoubleSpanScrollBarExtension* extension = static_cast<CAknDoubleSpanScrollBarExtension*> (iExtension);
+        CAknDoubleSpanScrollIndicator* indicator = extension->iScrollIndicator;
+
+        if (aTransparentBackground)
+            {
+            // removed old transparency related code
+            }
+        else
+            {
+            Window().SetNonTransparent();
+            }
+
+        indicator->SetTransparentBackground(aTransparentBackground);
+
+        }
+
+    }
+
+TBool CAknDoubleSpanScrollBar::DrawBackgroundState()
+    {
+    CAknDoubleSpanScrollBarExtension* extension = static_cast<CAknDoubleSpanScrollBarExtension*> (iExtension);
+    CAknDoubleSpanScrollIndicator* indicator = extension->iScrollIndicator;
+
+    return indicator->DrawBackgroundState();
+    }
+
+void CAknDoubleSpanScrollBar::DrawBackground(TBool aDraw)
+    {
+    CAknDoubleSpanScrollBarExtension* extension = static_cast<CAknDoubleSpanScrollBarExtension*> (iExtension);
+    CAknDoubleSpanScrollIndicator* indicator = extension->iScrollIndicator;
+
+    indicator->SetDrawBackgroundState(aDraw);
+    }
+
+
+// ---------------------------------------------------------------------------
+// CAknDoubleSpanScrollBar::ResetPressedDownHighlight
+// ---------------------------------------------------------------------------
+//
+void CAknDoubleSpanScrollBar::ResetPressedDownHighlight()
+    {
+    CAknDoubleSpanScrollBarExtension* extension =
+        static_cast<CAknDoubleSpanScrollBarExtension*>( iExtension );
+        
+    CAknDoubleSpanScrollIndicator* indicator = extension->iScrollIndicator;
+    
+    indicator->SetHandleHighlight( EFalse );
+    }
+
+
+//
+// class CAknDoubleSpanScrollBarExtension
+//
+
+CAknDoubleSpanScrollBarExtension::CAknDoubleSpanScrollBarExtension(CEikScrollBar* aParent)
+: iExternalFrames(1), iActiveScheduledDraw(NULL)
+    {
+    iParent=aParent;
+    }
+
+CAknDoubleSpanScrollBarExtension::~CAknDoubleSpanScrollBarExtension()
+    {
+    delete iScrollIndicator;
+    iScrollIndicator = NULL;
+
+    if ( iPopupController )
+        {
+        delete iPopupController;
+        iPopupController = NULL;
+        }
+
+    if(iActiveScheduledDraw && iActiveScheduledDraw->IsActive())
+        iActiveScheduledDraw->Cancel();
+
+    delete iActiveScheduledDraw;
+    }
+
+
+void CAknDoubleSpanScrollBarExtension::SetLengthL(TInt /*aLength*/)
+    {
+    }
+
+void CAknDoubleSpanScrollBarExtension::SetModelL(const TEikScrollBarModel* /*aModel*/)
+    {
+    }
+
+void CAknDoubleSpanScrollBarExtension::SetModel(const TEikScrollBarModel* /*aModel*/)
+    {
+    }
+
+void CAknDoubleSpanScrollBarExtension::SetLengthAndModelL(TInt /*aLength*/,const TEikScrollBarModel* /*aModel*/)
+    {
+    }
+
+// ----------------------------------------------------------------------------
+// CAknDoubleSpanScrollBarExtension::SetModelThumbPosition
+// Sets the thumb position to the model. This function has to be used because
+// CAknDoubleSpanScrollBar does not have direct access to the model.
+// ----------------------------------------------------------------------------
+//
+void CAknDoubleSpanScrollBarExtension::SetModelThumbPosition(TInt aThumbPos)
+    {
+    if( !AknLayoutUtils::PenEnabled() )
+        {
+        return;
+        }
+
+    if (iParent->iModel.ScrollBarModelType() == TEikScrollBarModel::EAknDoubleSpanScrollBarModel)
+        {
+        static_cast <TAknDoubleSpanScrollBarModel*> (&iParent->iModel)->SetFocusPosition(aThumbPos);
+        }
+    else
+        {
+        // Incorrect model is used, but in most cases we can work with the TEikScrollBarModel model.
+        iParent->iModel.iThumbPosition = aThumbPos;
+        }
+    }
+
+void CAknDoubleSpanScrollBarExtension::SetFocusPosToThumbPos(TInt /*aFocusPosition*/)
+    {
+    }
+
+TInt CAknDoubleSpanScrollBarExtension::ThumbPosition() const
+    {
+    if (iParent->iModel.ScrollBarModelType() == TEikScrollBarModel::EAknDoubleSpanScrollBarModel)
+        {
+        if( AknLayoutUtils::PenEnabled() )
+            {
+            // it is more effective to cast the pointer and use it directly
+            // than creating a copy of the model just to return a value
+            return static_cast <TAknDoubleSpanScrollBarModel*> (&iParent->iModel)->FocusPosition();
+            }
+        else
+            {
+            TAknDoubleSpanScrollBarModel& model = static_cast <TAknDoubleSpanScrollBarModel&> (iParent->iModel);
+            return model.FocusPosition();
+            }
+        }
+    else
+        {
+            // Error. User of the API is perhaps assigning values directly to TEikScrollBarModel
+            // member variables which is not allowed with EAknDoubleSpanScrollBarModel.
+            // #ifdef _DEBUG
+            // RDebug::Print(_L("CAknDoubleSpanScrollBarExtension: Please, use TAknDoubleSpanScrollBarModel instead of TEikScrollBarModel"));
+            // #endif
+            // In most cases we can work with the TEikScrollBarModel model.
+            return iParent->iModel.iThumbPosition;
+        }
+    }
+
+TInt CAknDoubleSpanScrollBarExtension::ScrollBarBreadth() const
+    {
+    if (iScrollIndicator)
+        return iScrollIndicator->IndicatorWidth();
+    else
+        return KAknDoubleSpanScrollBarWidth;
+    }
+
+void CAknDoubleSpanScrollBarExtension::SetDecreaseButtonsDimmed(TBool /*aDimmed*/)
+    {
+    }
+
+void CAknDoubleSpanScrollBarExtension::SetIncreaseButtonsDimmed(TBool /*aDimmed*/)
+    {
+    }
+
+void CAknDoubleSpanScrollBarExtension::SetAllButtonsDimmed(TBool /*aDimmed*/)
+    {
+    }
+
+void CAknDoubleSpanScrollBarExtension::SetContainingCba(CEikCba* /*aCba*/)
+    {
+    // Not needed in this type of scrollbar
+    }
+
+TInt CAknDoubleSpanScrollBarExtension::ScrollBarType()
+    {
+    return CEikScrollBarFrame::EDoubleSpan;
+    }
+
+void CAknDoubleSpanScrollBarExtension::CreateButtonL(CAknScrollButton*& /*aButton*/,CAknScrollButton::TType /*aType*/)
+    {
+    }
+
+void CAknDoubleSpanScrollBarExtension::DoSetModel(const TEikScrollBarModel* aModel)
+    {
+    iParent->iModel=(*aModel);
+    if (iScrollIndicator)
+        {
+        if (aModel->ScrollBarModelType() == TEikScrollBarModel::EAknDoubleSpanScrollBarModel)
+            {
+            const TAknDoubleSpanScrollBarModel* model = static_cast <const TAknDoubleSpanScrollBarModel*> (aModel);
+
+            iScrollIndicator->SetIndicatorValues(model->ScrollSpan(),
+                model->FocusPosition(),
+                model->WindowSize(),
+                model->FieldPosition(),
+                model->FieldSize());
+            }
+        else
+            {
+            // Error. User of the API is perhaps assigning values directly to TEikScrollBarModel
+            // member variables which is not allowed with TAknDoubleSpanScrollBarModel.
+            // #ifdef _DEBUG
+            // RDebug::Print(_L("CAknDoubleSpanScrollBarExtension: Please, use TAknDoubleSpanScrollBarModel instead of TEikScrollBarModel"));
+            // #endif
+            // In most cases we can work with the TEikScrollBarModel model.
+            iScrollIndicator->SetIndicatorValues(aModel->iScrollSpan,
+                aModel->iThumbPosition,
+                aModel->iThumbSpan,
+                0,
+                0);
+            }
+
+        if (iParent->OwnsWindow() && iScrollIndicator->TransparentBackground())
+            {
+            iParent->Window().HandleTransparencyUpdate();
+            }
+        if(iScrollIndicator->IsVisible())
+            {
+            if(iScrollIndicator->DrawBackgroundState() && !iParent->OwnsWindow())
+                {
+                if(HasModelChanged(aModel))
+                    {
+                    TInt err = KErrNone;
+                    if(!iActiveScheduledDraw) // create if not initialized
+                        TRAP(err, iActiveScheduledDraw = CIdle::NewL(EPriorityHigh));
+                    if(!err && !iActiveScheduledDraw->IsActive())
+                        iActiveScheduledDraw->Start(TCallBack(ScheduledDraw,this));
+                    }
+                }
+            else
+                {
+                iParent->DrawDeferred();                 
+                }
+
+            }
+        }
+    }
+
+TBool CAknDoubleSpanScrollBarExtension::HasModelChanged(const TEikScrollBarModel* aModel)
+    {
+    if(iPreviousModel.ScrollBarModelType() == TEikScrollBarModel::EAknDoubleSpanScrollBarModel &&
+        aModel->ScrollBarModelType() == TEikScrollBarModel::EAknDoubleSpanScrollBarModel)
+        {
+        TAknDoubleSpanScrollBarModel* previousModel = static_cast<TAknDoubleSpanScrollBarModel*> (&iPreviousModel);
+        const TAknDoubleSpanScrollBarModel* model = static_cast<const TAknDoubleSpanScrollBarModel*> (aModel);
+        if(previousModel->ScrollSpan() != model->ScrollSpan() ||
+        previousModel->FocusPosition() != model->FocusPosition() ||
+        previousModel->WindowSize() != model->WindowSize() ||
+        previousModel->FieldPosition() != model->FieldPosition() ||
+        previousModel->FieldSize() != model->FieldSize())
+            {
+            iPreviousModel = *aModel;
+            return ETrue;
+            }
+        }
+    else if(iPreviousModel.ScrollBarModelType() == TEikScrollBarModel::EEikScrollBarModel &&
+        aModel->ScrollBarModelType() == TEikScrollBarModel::EAknDoubleSpanScrollBarModel)
+        {
+        const TAknDoubleSpanScrollBarModel* model = static_cast<const TAknDoubleSpanScrollBarModel*> (aModel);
+        if(iPreviousModel.iScrollSpan != model->ScrollSpan() ||
+        iPreviousModel.iThumbPosition != model->FocusPosition() ||
+        iPreviousModel.iThumbSpan != model->WindowSize())
+            {
+            iPreviousModel = *aModel;
+            return ETrue;
+            }
+        }
+    else if(iPreviousModel.ScrollBarModelType() == TEikScrollBarModel::EAknDoubleSpanScrollBarModel &&
+        aModel->ScrollBarModelType() == TEikScrollBarModel::EEikScrollBarModel)
+        {
+        TAknDoubleSpanScrollBarModel* previousModel = static_cast<TAknDoubleSpanScrollBarModel*> (&iPreviousModel);
+        if(previousModel->ScrollSpan() != aModel->iScrollSpan ||
+        previousModel->FocusPosition() != aModel->iThumbPosition ||
+        previousModel->WindowSize() != aModel->iThumbSpan)
+            {
+            iPreviousModel = *aModel;
+            return ETrue;
+            }
+        }
+    else
+        {
+        if(iPreviousModel.iScrollSpan != aModel->iScrollSpan ||
+        iPreviousModel.iThumbPosition != aModel->iThumbPosition ||
+        iPreviousModel.iThumbSpan != aModel->iThumbSpan)
+            {
+            iPreviousModel = *aModel;
+            return ETrue;
+            }
+        }
+    iPreviousModel = *aModel;
+    return EFalse;
+    }
+
+CEikCba* CAknDoubleSpanScrollBarExtension::Cba() const
+    {
+    return NULL; // Not needed in this type of scrollbar
+    }
+
+void CAknDoubleSpanScrollBarExtension::AddExternalFrameL(CEikScrollBarFrame* aFrame)
+    {
+    iExternalFrames.AppendL(aFrame);
+    iScrollBarObserver = aFrame->ScrollBarFrameObserver();
+    }
+
+
+void CAknDoubleSpanScrollBarExtension::RemoveExternalFrame(CEikScrollBarFrame* aFrame)
+    {
+    TInt count = iExternalFrames.Count();
+    for (TInt ii=count-1; ii>=0; ii--)
+        {
+        if (iExternalFrames[ii] == aFrame)
+            {
+            iExternalFrames[ii]->DisconnectExternalScrollBar(iParent);
+            iExternalFrames.Delete(ii);
+            }
+        }
+
+    count = iExternalFrames.Count();
+    if(count == 0) //no externally owned anymore
+        {
+        iScrollBarObserver = iOwningScrollBarObserver;
+        }
+    else // set the next external frame as observer
+        {
+        iScrollBarObserver = iExternalFrames[(count - 1)]->ScrollBarFrameObserver();
+        }
+    }
+
+void CAknDoubleSpanScrollBarExtension::DisconnectExternalFrames()
+    {
+    TInt count = iExternalFrames.Count();
+    for (TInt ii=count-1; ii>=0; ii--)
+        {
+        iExternalFrames[ii]->DisconnectExternalScrollBar(iParent);
+        }
+    iExternalFrames.Reset();
+    }
+
+void CAknDoubleSpanScrollBarExtension::CreateRequiredComponentsL()
+    {
+    if ( !iScrollIndicator )
+        {
+        iScrollIndicator = CAknDoubleSpanScrollIndicator::NewL( iParent->iOrientation );
+        iScrollIndicator->SetContainerWindowL( *iParent );
+        iScrollIndicator->SetRect( iParent->Rect() );
+        iScrollIndicator->SetComponentsToInheritVisibility(ETrue);
+        }
+
+    if ( AknLayoutUtils::PenEnabled() &&
+        ( iScrollBarFlags & CEikScrollBar::EEnableNudgeButtons ) )
+        {
+        TBool horiz=(iParent->iOrientation == CEikScrollBar::EHorizontal);
+
+        if ( !iParent->iButtons.iDecreaseNudge )
+            {
+            iParent->CreateButtonL(iParent->iButtons.iDecreaseNudge,horiz ? CAknScrollButton::ENudgeLeft : CAknScrollButton::ENudgeUp);
+            }
+
+        if ( !iParent->iButtons.iIncreaseNudge )
+            {
+            iParent->CreateButtonL(iParent->iButtons.iIncreaseNudge,horiz ? CAknScrollButton::ENudgeRight : CAknScrollButton::ENudgeDown);
+            }
+        }
+    }
+
+void CAknDoubleSpanScrollBarExtension::DestroyButton(CAknScrollButton*& /*aButton*/)
+    {
+    }
+
+void CAknDoubleSpanScrollBarExtension::SetButtonPositionL(CAknScrollButton* /*aButton*/)
+    {
+    }
+
+void CAknDoubleSpanScrollBarExtension::SetScrollBarObserver(MEikScrollBarObserver* aScrollBarObserver)
+    {
+    iScrollBarObserver = aScrollBarObserver;
+
+    if(iExternalFrames.Count() == 0)
+        {
+        iOwningScrollBarObserver = aScrollBarObserver;
+        }
+    }
+
+MEikScrollBarObserver* CAknDoubleSpanScrollBarExtension::ScrollBarObserver()
+    {
+    return iScrollBarObserver;
+    }
+
+TInt CAknDoubleSpanScrollBarExtension::ScheduledDraw( TAny* aThis )
+    {
+    static_cast<CAknDoubleSpanScrollBarExtension*>( aThis )->DoScheduledDraw();
+    return 0;
+    }
+
+void CAknDoubleSpanScrollBarExtension::DoScheduledDraw()
+    {
+    if(iParent)
+        iParent->DrawNow();
+    }
+
+
+TInt CAknDoubleSpanScrollBarExtension::Reserved_1(){return 0;};
+TInt CAknDoubleSpanScrollBarExtension::Reserved_2(){return 0;};
+
+
+//
+// TAknDoubleSpanScrollBarModel class
+//
+//
+// This class stores its own model in its base class (TEikScrollBarModel)
+// member variables as following:
+//
+//
+// bits 31 to 0
+//
+// ZZAAAAAAAAAAAAA BBBBBBBBBBBBBBBB   (iScrollSpane)
+// CCCCCCCCCCCCCCC DDDDDDDDDDDDDDDD   (iThumbSpan)
+// EEEEEEEEEEEEEEE FFFFFFFFFFFFFFFF   (iThumbPosition)
+//
+// Bits ZZ = model type.
+//           00 EikScrollBarModel
+//           11 EikScrollBarModel
+//           10 TAknDoubleSpanScrollBarModel
+//           01 Reserved for future
+//
+// Bits   AAAAAAAAAAAAA = scale
+// Bits BBBBBBBBBBBBBBB = scroll span
+// Bits CCCCCCCCCCCCCCC = focus position
+// Bits DDDDDDDDDDDDDDD = field position
+// Bits EEEEEEEEEEEEEEE = field size
+// Bits FFFFFFFFFFFFFFF = window size
+//
+//
+// Reason for this solution is to preserve binary compatibility with the old model.
+//
+// If this model is not supported by the scrollbar system, then values are stored
+// as in the base class for compatibility resons.
+
+EXPORT_C TAknDoubleSpanScrollBarModel::TAknDoubleSpanScrollBarModel()
+    {
+    if (ModelIsSupported())
+        {
+        SetScrollBarModelType(EAknDoubleSpanScrollBarModel);
+        SetScale(KDoubleSpanMinScaleValue);
+        SetScrollSpanValue(0);
+        SetFocusPositionValue(0);
+        SetFieldPositionValue(0);
+        SetFieldSizeValue(0);
+        SetWindowSizeValue(0);
+        }
+    else
+        {
+        iScrollSpan = 0;
+        iThumbSpan = 0;
+        iThumbPosition = 0;
+        }
+    }
+
+EXPORT_C TAknDoubleSpanScrollBarModel::TAknDoubleSpanScrollBarModel(const TEikScrollBarModel& aEikModel)
+    {
+
+    if(aEikModel.ScrollBarModelType() == EAknDoubleSpanScrollBarModel)
+        {
+        const TAknDoubleSpanScrollBarModel* model = static_cast <const TAknDoubleSpanScrollBarModel*> (&aEikModel);
+
+        // if parameter is
+        if (model->ModelIsSupported())
+            {
+            iScrollSpan = aEikModel.iScrollSpan;
+            iThumbSpan = aEikModel.iThumbSpan;
+            iThumbPosition = aEikModel.iThumbPosition;
+            }
+        else if(!ModelIsSupported() && model->ModelIsSupported())
+            {
+            SetScrollBarModelType(EAknDoubleSpanScrollBarModel);
+            SetScale(KDoubleSpanMinScaleValue);
+            SetScrollSpan(CheckMinMaxValue(model->ScrollSpan()));
+            SetFocusPosition(CheckMinMaxValue(model->FocusPosition()));
+            SetWindowSize(CheckMinMaxValue(model->WindowSize()));
+            SetFieldPositionValue(0);
+            SetFieldSizeValue(0);
+            }
+        }
+    // if parameter is only eikscb
+    else if(ModelIsSupported() && aEikModel.ScrollBarModelType() == EEikScrollBarModel)
+        {
+        SetScrollBarModelType(EAknDoubleSpanScrollBarModel);
+        SetScale(KDoubleSpanMinScaleValue);
+        SetScrollSpan(CheckMinMaxValue(aEikModel.iScrollSpan));
+        SetFocusPosition(CheckMinMaxValue(aEikModel.iThumbPosition));
+        SetWindowSize(CheckMinMaxValue(aEikModel.iThumbSpan));
+        SetFieldPositionValue(0);
+        SetFieldSizeValue(0);
+        }
+    else
+        {
+        SetScrollBarModelType(EAknDoubleSpanScrollBarModel);
+        SetScale(KDoubleSpanMinScaleValue);
+        SetScrollSpan(CheckMinMaxValue(aEikModel.iScrollSpan));
+        SetFocusPosition(CheckMinMaxValue(aEikModel.iThumbPosition));
+        SetWindowSize(CheckMinMaxValue(aEikModel.iThumbSpan));
+        SetFieldPositionValue(0);
+        SetFieldSizeValue(0);
+        }
+    }
+
+
+EXPORT_C TInt TAknDoubleSpanScrollBarModel::ScrollSpan() const
+    {
+    if (ModelIsSupported())
+        {
+        // Assert that API user has not set TEikScrollBarModel values directly
+        __ASSERT_ALWAYS(ScrollBarModelType() == EAknDoubleSpanScrollBarModel,Panic(EEikPanicOutOfRange));
+        return Scale() * ScrollSpanValue();
+        }
+    else
+        {
+        return iScrollSpan;
+        }
+    }
+
+EXPORT_C void TAknDoubleSpanScrollBarModel::SetScrollSpan(TInt aScrollSpan)
+    {
+    if (ModelIsSupported())
+        {
+        // Assert that API user has not set TEikScrollBarModel values directly
+        __ASSERT_ALWAYS(ScrollBarModelType() == EAknDoubleSpanScrollBarModel,Panic(EEikPanicOutOfRange));
+        SetScrollSpanValue(PrepareScaledValue(CheckMinMaxValue(aScrollSpan)));
+        }
+    else
+        {
+        iScrollSpan = aScrollSpan;
+        }
+    }
+
+EXPORT_C TInt TAknDoubleSpanScrollBarModel::FocusPosition() const
+    {
+    if (ModelIsSupported())
+        {
+        // Assert that API user has not set TEikScrollBarModel values directly
+        __ASSERT_ALWAYS(ScrollBarModelType() == EAknDoubleSpanScrollBarModel,Panic(EEikPanicOutOfRange));
+        return Scale() * FocusPositionValue();
+        }
+    else
+        {
+        return iThumbPosition;
+        }
+    }
+
+EXPORT_C void TAknDoubleSpanScrollBarModel::SetFocusPosition(TInt aFocusPosition)
+    {
+    if (ModelIsSupported())
+        {
+        // Assert that API user has not set TEikScrollBarModel values directly
+        __ASSERT_ALWAYS(ScrollBarModelType() == EAknDoubleSpanScrollBarModel,Panic(EEikPanicOutOfRange));
+        SetFocusPositionValue(PrepareScaledValue(CheckMinMaxValue(aFocusPosition)));
+        }
+    else
+        {
+        iThumbPosition = aFocusPosition;
+        }
+    }
+
+EXPORT_C TInt TAknDoubleSpanScrollBarModel::FieldPosition() const
+    {
+    if (ModelIsSupported())
+        {
+        // Assert that API user has not set TEikScrollBarModel values directly
+        __ASSERT_ALWAYS(ScrollBarModelType() == EAknDoubleSpanScrollBarModel,Panic(EEikPanicOutOfRange));
+        return Scale() * FieldPositionValue();
+        }
+    else
+        {
+        return 0;
+        }
+    }
+
+EXPORT_C void TAknDoubleSpanScrollBarModel::SetFieldPosition(TInt aFieldPosition)
+    {
+    if (ModelIsSupported())
+        {
+        // Assert that API user has not set TEikScrollBarModel values directly
+        __ASSERT_ALWAYS(ScrollBarModelType() == EAknDoubleSpanScrollBarModel,Panic(EEikPanicOutOfRange));
+        SetFieldPositionValue(PrepareScaledValue(CheckMinMaxValue(aFieldPosition)));
+        }
+    else
+        {
+        // do nothing
+        }
+    }
+
+EXPORT_C TInt TAknDoubleSpanScrollBarModel::FieldSize() const
+    {
+    if (ModelIsSupported())
+        {
+        // Assert that API user has not set TEikScrollBarModel values directly
+        __ASSERT_ALWAYS(ScrollBarModelType() == EAknDoubleSpanScrollBarModel,Panic(EEikPanicOutOfRange));
+        return Scale() * FieldSizeValue();
+        }
+    else
+        {
+        return 0;
+        }
+    }
+
+EXPORT_C void TAknDoubleSpanScrollBarModel::SetFieldSize(TInt aFieldSize)
+    {
+    if (ModelIsSupported())
+        {
+        // Assert that API user has not set TEikScrollBarModel values directly
+        __ASSERT_ALWAYS(ScrollBarModelType() == EAknDoubleSpanScrollBarModel,Panic(EEikPanicOutOfRange));
+        SetFieldSizeValue(PrepareScaledValue(CheckMinMaxValue(aFieldSize)));
+        }
+    else
+        {
+        // do nothing
+        }
+    }
+
+EXPORT_C TInt TAknDoubleSpanScrollBarModel::WindowSize() const
+    {
+    if (ModelIsSupported())
+        {
+        // Assert that API user has not set TEikScrollBarModel values directly
+        __ASSERT_ALWAYS(ScrollBarModelType() == EAknDoubleSpanScrollBarModel,Panic(EEikPanicOutOfRange));
+        return Scale() * WindowSizeValue();
+        }
+    else
+        {
+        return iThumbSpan;
+        }
+    }
+
+EXPORT_C void TAknDoubleSpanScrollBarModel::SetWindowSize (TInt aWindowSize)
+    {
+    if (ModelIsSupported())
+        {
+        // Assert that API user has not set TEikScrollBarModel values directly
+        __ASSERT_ALWAYS(ScrollBarModelType() == EAknDoubleSpanScrollBarModel,Panic(EEikPanicOutOfRange));
+        SetWindowSizeValue(PrepareScaledValue(CheckMinMaxValue(aWindowSize)));
+        }
+    else
+        {
+        iThumbSpan = aWindowSize;
+        }
+    }
+
+TUint16 TAknDoubleSpanScrollBarModel::Scale() const
+    {
+    TUint16 scale = TUint16(KDoubleSpanModelMaskBitsScale16 & HighBytes(iScrollSpan));
+    return scale;
+    }
+
+void TAknDoubleSpanScrollBarModel::SetScale(TUint16 aScale)
+    {
+    __ASSERT_ALWAYS(aScale != 0,Panic(EEikPanicOutOfRange));
+    __ASSERT_ALWAYS(aScale <= KDoubleSpanMaxScaleValue,Panic(EEikPanicOutOfRange));
+
+    iScrollSpan &= ~KDoubleSpanModelMaskBitsScale;
+    iScrollSpan |= KDoubleSpanModelMaskBitsScale & (TInt(aScale) << 16);
+    }
+
+// getter/setters for raw values without scaling
+TInt16 TAknDoubleSpanScrollBarModel::ScrollSpanValue() const
+    {
+    return LowBytes(iScrollSpan);
+    }
+
+void TAknDoubleSpanScrollBarModel::SetScrollSpanValue(TInt16 aScrollSpan)
+    {
+    SetLowBytes(iScrollSpan, aScrollSpan);
+    }
+
+TInt16 TAknDoubleSpanScrollBarModel::FocusPositionValue() const
+    {
+    return HighBytes(iThumbSpan);
+    }
+
+void TAknDoubleSpanScrollBarModel::SetFocusPositionValue(TInt16 aFocusPosition)
+    {
+    SetHighBytes(iThumbSpan, aFocusPosition);
+    }
+
+TInt16 TAknDoubleSpanScrollBarModel::FieldPositionValue() const
+    {
+    return LowBytes(iThumbSpan);
+    }
+
+void TAknDoubleSpanScrollBarModel::SetFieldPositionValue(TInt16 aFieldPosition)
+    {
+    SetLowBytes(iThumbSpan, aFieldPosition);
+    }
+
+TInt16 TAknDoubleSpanScrollBarModel::FieldSizeValue() const
+    {
+    return HighBytes(iThumbPosition);
+    }
+
+void TAknDoubleSpanScrollBarModel::SetFieldSizeValue(TInt16 aFieldSize)
+    {
+    SetHighBytes(iThumbPosition, aFieldSize);
+    }
+
+TInt16 TAknDoubleSpanScrollBarModel::WindowSizeValue() const
+    {
+    return LowBytes(iThumbPosition);
+    }
+
+void TAknDoubleSpanScrollBarModel::SetWindowSizeValue(TInt16 aWindowSize)
+    {
+    SetLowBytes(iThumbPosition, aWindowSize);
+    }
+
+TInt16 TAknDoubleSpanScrollBarModel::LowBytes(TInt aInt) const
+    {
+    return TInt16(KDoubleSpanModelMaskBitsLow & aInt);
+    }
+
+TInt16 TAknDoubleSpanScrollBarModel::HighBytes(TInt aInt) const
+    {
+    return TInt16((KDoubleSpanModelMaskBitsHigh & aInt) >> 16);
+    }
+
+void TAknDoubleSpanScrollBarModel::SetLowBytes(TInt& aInt, TInt16 aValue)
+    {
+    aInt &= KDoubleSpanModelMaskBitsHigh;
+    aInt |= TInt(KDoubleSpanModelMaskBitsLow & aValue);
+    }
+
+void TAknDoubleSpanScrollBarModel::SetHighBytes(TInt& aInt, TInt16 aValue)
+    {
+    aInt &= KDoubleSpanModelMaskBitsLow;
+    aInt |= TInt(aValue) << 16;
+    }
+
+TInt16 TAknDoubleSpanScrollBarModel::PrepareScaledValue(TInt aNonScaledValue)
+    {
+     __ASSERT_ALWAYS(KDoubleSpanMinModelValue <= aNonScaledValue && aNonScaledValue <= KDoubleSpanMaxModelValue, Panic(EEikPanicOutOfRange));
+
+    TUint16 requiredScale = KDoubleSpanMinScaleValue;
+    if (aNonScaledValue < 0)
+        {
+        requiredScale = TUint16(( -aNonScaledValue / KDoubleSpanMaxRawValue ) + KDoubleSpanMinScaleValue);
+        }
+    else
+        {
+        requiredScale = TUint16(( aNonScaledValue / KDoubleSpanMaxRawValue ) + KDoubleSpanMinScaleValue);
+        }
+
+    if ( requiredScale > Scale() )
+        {
+         ReScale( requiredScale );
+        }
+    TInt16 scaledValue = TInt16(aNonScaledValue / Scale());
+     return scaledValue;
+    }
+
+void TAknDoubleSpanScrollBarModel::ReScale(TUint16 aNewScale)
+    {
+    __ASSERT_ALWAYS(aNewScale != 0,Panic(EEikPanicOutOfRange));
+    __ASSERT_ALWAYS(aNewScale <= KDoubleSpanMaxScaleValue,Panic(EEikPanicOutOfRange));
+
+    SetScrollSpanValue(TInt16((ScrollSpanValue() * Scale())/aNewScale));
+    SetFocusPositionValue(TInt16((FocusPositionValue() * Scale())/aNewScale));
+    SetFieldPositionValue(TInt16((FieldPositionValue() * Scale())/aNewScale));
+    SetFieldSizeValue(TInt16((FieldSizeValue() * Scale())/aNewScale));
+    SetWindowSizeValue(TInt16((WindowSizeValue() * Scale())/aNewScale));
+    SetScale(aNewScale);
+    }
+
+void TAknDoubleSpanScrollBarModel::SetScrollBarModelType(TEikScrollBarModelType aModelType)
+    {
+    iScrollSpan &= KDoubleSpanModelMaskBitsType;
+    iScrollSpan |= (~KDoubleSpanModelMaskBitsType) & aModelType;
+    }
+
+TInt TAknDoubleSpanScrollBarModel::CheckMinMaxValue(TInt aValue)
+    {
+    if ((aValue > 0) && (aValue > KDoubleSpanMaxModelValue))
+        {
+        return KDoubleSpanMaxModelValue;
+        }
+    if ((aValue < 0) && (aValue < KDoubleSpanMinModelValue))
+        {
+        return KDoubleSpanMinModelValue;
+        }
+    return aValue;
+    }
+
+TBool TAknDoubleSpanScrollBarModel::ModelIsSupported()
+    {
+    // Check here feature flags etc. to decide if this device can support this
+    // type of model and scrollbars.
+    return ETrue;
+    }
+
+TRect CAknDoubleSpanScrollBar::ExtensionArea() const
+    {
+    // Usage of hard-coded parent rectangle is acceptable since we're
+    // interested in only about the ratio between scrollbar and extension.
+    TAknLayoutRect layoutRect;
+    layoutRect.LayoutRect( TRect( 0, 0, 200, 200 ), AknLayoutScalable_Avkon::listscroll_gen_pane( 0 ).LayoutLine() );
+    
+    TRect parent( layoutRect.Rect() ); // parent of both extension and scrollbar
+    
+    layoutRect.LayoutRect( parent, AknLayoutScalable_Avkon::scroll_pane( 0 ).LayoutLine() );
+    
+    TRect scrollbar( layoutRect.Rect() );
+    
+    CAknDoubleSpanScrollBarExtension* extension1 = static_cast<CAknDoubleSpanScrollBarExtension*> (iExtension);
+    if( extension1->iExtensionType & ENormalExpandedTouchArea )
+        layoutRect.LayoutRect( parent, AknLayoutScalable_Avkon::aid_size_touch_scroll_bar( 0 ).LayoutLine() );
+    else if( extension1->iExtensionType & EScaleExpandedTouchArea )
+        layoutRect.LayoutRect( parent, AknLayoutScalable_Avkon::aid_size_touch_scroll_bar_cale( 0 ).LayoutLine() );
+    else
+        layoutRect.LayoutRect( parent, AknLayoutScalable_Avkon::aid_size_touch_scroll_bar( 0 ).LayoutLine() );
+    TRect extension( layoutRect.Rect() );
+
+    TRect area;
+    
+    if ( iOrientation == CEikScrollBar::EVertical )
+        {
+        area.iTl.iX = extension.iTl.iX - scrollbar.iTl.iX;
+        area.iTl.iY = scrollbar.iTl.iY - extension.iTl.iY;
+        area.iBr.iX = area.iTl.iX + extension.Width();
+        area.iBr.iY = iSize.iHeight + ( extension.Height() - scrollbar.Height() );
+        }
+    else
+        {
+        area.iTl.iX = scrollbar.iTl.iY - extension.iTl.iY;
+        area.iTl.iY = scrollbar.Width() - extension.Width();
+        area.iBr.iX = iSize.iWidth + ( extension.Height() - scrollbar.Height() );
+        area.iBr.iY = area.iTl.iY + extension.Width();
+        }
+    
+    return area;
+    }
+