--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/uifw/EikStd/coctlsrc/AknDoubleSpanScrollIndicator.cpp Tue Feb 02 01:00:49 2010 +0200
@@ -0,0 +1,1128 @@
+/*
+* Copyright (c) 2004 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: Indicator for double span scroll bar.
+*
+*
+*/
+
+
+#include "AknDoubleSpanScrollIndicator.h"
+#include "AknDoubleSpanScrollIndicatorItem.h"
+#include <aknconsts.h>
+#include <avkon.mbg>
+#include <AknUtils.h>
+#include <AknsDrawUtils.h>
+#include <aknlayoutscalable_avkon.cdl.h>
+#include <aknappui.h>
+#include <AknDef.h>
+#include <AknPriv.hrh>
+#include <AknTasHook.h>
+#include <AknsDrawUtils.h>
+// Do not use these constants directly, use implemented private methods instead.
+// const TInt KScrollBackgroundMinVisibleSizeInPixels = 4; // minimum distance handle and scb bottom.
+//const TInt KHandleBackgroundMinSizeInPixels = 24; // double spanned non focused handle minimum size
+//const TInt KHandleMinSizeInPixels = 12; // focused handle minimum size
+const TInt KPrecision = 8; // Used in pixel effect calculations
+
+CAknDoubleSpanScrollIndicator* CAknDoubleSpanScrollIndicator::NewL(CEikScrollBar::TOrientation aOrientation)
+ {
+ CAknDoubleSpanScrollIndicator* self = new (ELeave) CAknDoubleSpanScrollIndicator();
+ CleanupStack::PushL(self);
+ self->ConstructL(aOrientation);
+ CleanupStack::Pop();
+ return self;
+ }
+
+CAknDoubleSpanScrollIndicator::CAknDoubleSpanScrollIndicator()
+: iOwnsWindow(EFalse), iTransparentBackground(EFalse), iDrawBackground(ETrue),
+ iBackgroundHighlight(EFalse),iDrawBackgroundBitmap(EFalse)
+ {
+ AKNTASHOOK_ADD( this, "CAknDoubleSpanScrollIndicator" );
+ }
+
+CAknDoubleSpanScrollIndicator::~CAknDoubleSpanScrollIndicator()
+ {
+ AKNTASHOOK_REMOVE();
+ AknsUtils::DeregisterControlPosition( this );
+
+ delete iBackgroundBar;
+ delete iHighlightBackgroundBar;
+ delete iHandleBar;
+ delete iHighlightHandleBar;
+
+
+ }
+
+void CAknDoubleSpanScrollIndicator::ConstructL(CEikScrollBar::TOrientation aOrientation)
+ {
+ iOrientation = aOrientation;
+ CreateScrollBarItemsL();
+ UpdateScrollBarLayout();
+ }
+
+void CAknDoubleSpanScrollIndicator::Draw(const TRect& /*aRect*/) const
+ {
+ CWindowGc& gc = SystemGc();
+
+ if(iDrawBackground)
+ {
+ DrawBackground();
+ }
+
+ CAknDoubleSpanScrollIndicatorItem* handleBackgroundBar =
+ iBackgroundHighlight && iHighlightBackgroundBar ?
+ iHighlightBackgroundBar : iBackgroundBar;
+
+ DrawTiled(gc, iBackgroundRect, handleBackgroundBar);
+
+ TBool showHandleBarBackground = iFieldPosition >= 0 && iFieldSize > 0;
+ if(showHandleBarBackground)
+ {
+ DrawTiled(gc, iHandleBackgroundRect, iHighlightBackgroundBar);
+ }
+
+ CAknDoubleSpanScrollIndicatorItem* handleBar =
+ iHandleHighlight && iHighlightHandleBar ?
+ iHighlightHandleBar : iHandleBar;
+
+ DrawTiled(gc, iHandleRect, handleBar);
+ }
+void CAknDoubleSpanScrollIndicator::UpdateScrollBarLayout()
+ {
+ iHeadItemSize = 12;
+ iMidItemSize = 12 * 5;
+ iTailItemSize = 12;
+
+ TRect rect = Rect();
+ if(rect.IsEmpty())
+ {
+ return;
+ }
+
+ TInt varietyIndex ( 0 );
+ if ( iOrientation == CEikScrollBar::EHorizontal )
+ {
+ varietyIndex = 1;
+ }
+
+ TAknLayoutRect layRect;
+ TAknWindowComponentLayout layout = AknLayoutScalable_Avkon::scroll_bg_pane_g1( varietyIndex ); //top
+ layRect.LayoutRect( rect, layout.LayoutLine() );
+ TSize newSize = layRect.Rect().Size();
+ iHeadItemSize = (iOrientation == CEikScrollBar::EVertical?newSize.iHeight:newSize.iWidth);
+
+ layout = AknLayoutScalable_Avkon::scroll_bg_pane_g3(varietyIndex); // bottom
+ layRect.LayoutRect(rect, layout.LayoutLine());
+ newSize = layRect.Rect().Size();
+ iTailItemSize = (iOrientation == CEikScrollBar::EVertical?newSize.iHeight:newSize.iWidth);
+
+ layout = AknLayoutScalable_Avkon::scroll_bg_pane_g2(varietyIndex); //middle
+ layRect.LayoutRect(rect, layout.LayoutLine());
+ newSize = layRect.Rect().Size();
+ // iMidItemSize = (iOrientation == CEikScrollBar::EVertical?newSize.iHeight:newSize.iWidth) * 5;
+ }
+
+void CAknDoubleSpanScrollIndicator::DrawTiled(
+ CWindowGc& aGc, const TRect& aRect,
+ CAknDoubleSpanScrollIndicatorItem *aIndicatorItem) const
+ {
+ if (aRect.IsEmpty())
+ return;
+
+ TRect headRect = aRect;
+ TRect tailRect = aRect;
+ TRect midRect = aRect;
+ TInt midDrawLength;
+ TSize midSize;
+ if (iOrientation == CEikScrollBar::EVertical)
+ {
+ if ((iHeadItemSize + iTailItemSize) <= aRect.Height())
+ {
+ headRect.SetHeight(iHeadItemSize);
+ tailRect.iTl.iY = tailRect.iBr.iY - iTailItemSize;
+ }
+ else
+ {
+ headRect.SetHeight((aRect.Height() >> 1));
+ tailRect.iTl.iY = tailRect.iBr.iY - headRect.Height();
+ }
+ midRect.iTl.iY += headRect.Height();
+ midRect.iBr.iY -= tailRect.Height();
+ midDrawLength = midRect.Height();
+ midSize.SetSize(midRect.Width(), iMidItemSize);
+ }
+ else
+ {
+ headRect.SetWidth( iHeadItemSize );
+ tailRect.iTl.iX = tailRect.iBr.iX - iTailItemSize;
+
+ midRect.iTl.iX += iHeadItemSize;
+ midRect.iBr.iX -= iTailItemSize;
+ midDrawLength = midRect.Width();
+ midSize.SetSize(iMidItemSize, midRect.Height());
+ }
+
+ MAknsSkinInstance* skin = AknsUtils::SkinInstance();
+
+ CFbsBitmap *bmp = NULL;
+ CFbsBitmap *mask = NULL;
+ AknsUtils::GetCachedMaskedBitmap(skin, aIndicatorItem->iTopId, bmp, mask);
+ AknIconUtils::SetSize(bmp, headRect.Size(), EAspectRatioNotPreserved);
+ AknIconUtils::SetSize(mask, headRect.Size(), EAspectRatioNotPreserved);
+ aGc.BitBltMasked(headRect.iTl, bmp, TRect(TPoint(0, 0), headRect.Size()), mask, ETrue);
+
+ AknsUtils::GetCachedMaskedBitmap(skin, aIndicatorItem->iMidId, bmp, mask);
+ AknIconUtils::SetSize(bmp, midSize, EAspectRatioNotPreserved);
+ AknIconUtils::SetSize(mask, midSize, EAspectRatioNotPreserved);
+
+ TInt count = midDrawLength / iMidItemSize;
+ TPoint destPos(midRect.iTl.iX, midRect.iTl.iY);
+ TRect sourRect(TPoint(0, 0), bmp->SizeInPixels());
+ for(TInt i = 0; i < count; i++)
+ {
+ aGc.BitBltMasked(destPos, bmp, sourRect, mask, ETrue);
+ iOrientation == CEikScrollBar::EVertical?destPos.iY += iMidItemSize : destPos.iX += iMidItemSize;
+ }
+ iOrientation == CEikScrollBar::EVertical?sourRect.iBr.iY = midRect.Height() % iMidItemSize
+ :sourRect.iBr.iX = midRect.Width() % iMidItemSize;
+ aGc.BitBltMasked(destPos, bmp, sourRect, mask, ETrue);
+
+ AknsUtils::GetCachedMaskedBitmap(skin, aIndicatorItem->iBottomId, bmp, mask);
+ AknIconUtils::SetSize(bmp, tailRect.Size(), EAspectRatioNotPreserved);
+ AknIconUtils::SetSize(mask, tailRect.Size(), EAspectRatioNotPreserved);
+ aGc.BitBltMasked(tailRect.iTl, bmp, TRect(TPoint(0, 0), tailRect.Size()), mask, ETrue);
+ }
+
+void CAknDoubleSpanScrollIndicator::CalculateRects()
+ {
+ iBackgroundRect = Rect();
+
+ //
+ // sanity checks for values used in drawing
+ //
+ TInt checkedScrollSpan = iScrollSpan; // all items
+ TInt checkedFocusPosition = iFocusPosition; // current item
+ TInt checkedWindowSize = iWindowSize; // number of visible items
+ TInt checkedFieldPosition = iFieldPosition; // position in sub list
+ TInt checkedFieldSize = iFieldSize; // number of visible items in sub list
+
+ CheckValues(checkedScrollSpan,
+ checkedFocusPosition,
+ checkedWindowSize,
+ checkedFieldPosition,
+ checkedFieldSize);
+
+ // If span (max number of items) is zero, then draw only the background
+ if (checkedScrollSpan == 0)
+ {
+ iHandleBackgroundRect = TRect(0,0,0,0);
+ iHandleRect = TRect(0,0,0,0);
+ return;
+ }
+
+ //
+ // Transform values into pixels and rects.
+ //
+ TInt scrollBarHeightInPixels( 0 );
+
+ if ( iOrientation == CEikScrollBar::EHorizontal )
+ {
+ scrollBarHeightInPixels = iBackgroundRect.Width();
+ }
+ else
+ {
+ scrollBarHeightInPixels = iBackgroundRect.Height();
+ }
+
+ // The code block below was probably used to prevent
+ // a truncation-vs-rounding error from happening
+ /*
+ if ((checkedWindowSize > 0) && (checkedScrollSpan > 0))
+ {
+ if((checkedFocusPosition + checkedWindowSize) == checkedScrollSpan)
+ windowSizeInPixels = scrollBarHeightInPixels - focusPositionInPixels;
+ else
+ windowSizeInPixels = scrollBarHeightInPixels*checkedWindowSize/checkedScrollSpan;
+ }
+ */
+
+ TInt windowSizeInPixels =
+ Max( checkedWindowSize * scrollBarHeightInPixels / checkedScrollSpan,
+ HandleBackgroundMinSizeInPixels() );
+
+ TInt roomForMovementInSpan = checkedScrollSpan - checkedWindowSize;
+ TInt roomForMovementInPixels =
+ scrollBarHeightInPixels - windowSizeInPixels;
+
+ TInt focusPositionInPixels( 0 );
+
+ if ( roomForMovementInSpan > 0 && roomForMovementInPixels > 0 )
+ {
+ focusPositionInPixels =
+ checkedFocusPosition * roomForMovementInPixels /
+ roomForMovementInSpan;
+ }
+
+ // If window would cover whole scrollbar, then modify
+ // it to leave the thumb little short from bottom
+ TInt scrollBarHandleMaxSizeInPixels = ScrollHandleMaxVisibleSizeInPixels();
+ if (windowSizeInPixels >= scrollBarHeightInPixels)
+ {
+ windowSizeInPixels = scrollBarHandleMaxSizeInPixels;
+ }
+
+ TBool doubleSpanInUse = (checkedFieldPosition >= 0) && (checkedFieldSize > 0);
+ TInt minHandleBackgroundSize = 0;
+ TInt fieldSizeInPixels = 0; // sub field size
+ TInt fieldPositionInPixels = 0;
+ if (doubleSpanInUse)
+ {
+ fieldSizeInPixels = windowSizeInPixels/checkedFieldSize;
+ fieldPositionInPixels = windowSizeInPixels*checkedFieldPosition/checkedFieldSize;
+ minHandleBackgroundSize = HandleBackgroundMinSizeInPixels();
+ }
+ else
+ {
+ minHandleBackgroundSize = HandleMinSizeInPixels();
+ }
+
+ TInt handleMinSize = HandleMinSizeInPixels();
+ // Similar compensation for handle if double span is in use
+ if (doubleSpanInUse && (fieldSizeInPixels < handleMinSize))
+ {
+ TInt extraPixels = 0;
+ TInt extraPixelCompensationInterval = 0;
+ TInt extraPixelCompensation = 0;
+ extraPixels = handleMinSize - fieldSizeInPixels;
+ extraPixelCompensationInterval = windowSizeInPixels/extraPixels;
+ if (extraPixelCompensationInterval != 0)
+ {
+ extraPixelCompensation = fieldPositionInPixels/extraPixelCompensationInterval;
+ if (extraPixelCompensation > handleMinSize)
+ {
+ extraPixelCompensation = handleMinSize;
+ }
+ }
+
+ if ((fieldPositionInPixels - extraPixelCompensation) > 0)
+ {
+ fieldPositionInPixels -= extraPixelCompensation;
+ }
+
+ // Additional compensation at the end is sometimes needed as above compensation is not
+ // always accurate because the fieldPositionInPixels is not anymore in "right" place.
+ if (checkedFieldPosition < (checkedFieldSize - 1))
+ {
+ if ((fieldPositionInPixels + handleMinSize) >= windowSizeInPixels - 1)
+ {
+ fieldPositionInPixels = windowSizeInPixels - (handleMinSize + 2);
+ }
+ }
+ fieldSizeInPixels = handleMinSize;
+ }
+
+
+ // If orientation is horizontal, then rotate rects here first
+ // 90 degrees. At the end of this function rotate them back again.
+ if (iOrientation == CEikScrollBar::EHorizontal)
+ {
+ TRect original = iBackgroundRect;
+ iBackgroundRect.iBr.iX = original.iTl.iX + original.Height();
+ iBackgroundRect.iBr.iY = original.iTl.iY + original.Width();
+ iHandleBackgroundRect = TRect(0,0,0,0);
+ iHandleRect = TRect(0,0,0,0);
+ }
+
+ // handle background
+ iHandleBackgroundRect = iBackgroundRect;
+ iHandleBackgroundRect.iTl.iY += focusPositionInPixels;
+ iHandleBackgroundRect.iBr.iY = iHandleBackgroundRect.iTl.iY + windowSizeInPixels;
+
+ if (iHandleBackgroundRect.iBr.iY > iBackgroundRect.iBr.iY)
+ {
+ iHandleBackgroundRect.iBr.iY = iBackgroundRect.iBr.iY;
+ iHandleBackgroundRect.iTl.iY = iBackgroundRect.iBr.iY - windowSizeInPixels;
+ }
+
+ // fields
+ iHandleRect= iHandleBackgroundRect;
+ iHandleRect.iTl.iY += fieldPositionInPixels;
+ iHandleRect.iBr.iY = iHandleRect.iTl.iY + fieldSizeInPixels;
+ if (iHandleRect.iTl.iY < iHandleBackgroundRect.iTl.iY)
+ {
+ iHandleRect.iTl.iY = iHandleBackgroundRect.iTl.iY;
+ }
+
+ if (iHandleRect.iBr.iY > iHandleBackgroundRect.iBr.iY)
+ {
+ iHandleRect.iBr.iY = iHandleBackgroundRect.iBr.iY;
+ }
+
+ // if double span is not used, set the handle to cover whole handle background area.
+ if (!doubleSpanInUse)
+ {
+ iHandleRect.SetHeight(iHandleBackgroundRect.Height());
+ }
+
+ // check overflow
+ if (iHandleBackgroundRect.iBr.iY > iBackgroundRect.iBr.iY)
+ {
+
+ iHandleBackgroundRect.iBr.iY = iBackgroundRect.iBr.iY;
+ iHandleBackgroundRect.iTl.iY = iBackgroundRect.iBr.iY - minHandleBackgroundSize;
+ }
+ if (iHandleBackgroundRect.iTl.iY < iBackgroundRect.iTl.iY)
+ {
+ iHandleBackgroundRect.iTl.iY = iBackgroundRect.iTl.iY;
+ }
+
+ // check overflow
+ if (iHandleRect.iBr.iY > iHandleBackgroundRect.iBr.iY)
+ {
+ iHandleRect.iBr.iY = iHandleBackgroundRect.iBr.iY;
+ iHandleRect.iTl.iY = iHandleBackgroundRect.iBr.iY - handleMinSize;
+ }
+ if (iHandleRect.iTl.iY < iHandleBackgroundRect.iTl.iY)
+ {
+ iHandleRect.iTl.iY = iHandleBackgroundRect.iTl.iY;
+ }
+
+ // If calculations were done to 90 degrees rotated rects, rotate those back here.
+ if (iOrientation == CEikScrollBar::EHorizontal)
+ {
+ TRect originalBackgroundRect = iBackgroundRect;
+ iBackgroundRect.SetWidth(originalBackgroundRect.Height());
+ iBackgroundRect.SetHeight(originalBackgroundRect.Width());
+
+ TRect originalHandleBackgroundRect = iHandleBackgroundRect;
+ iHandleBackgroundRect = iBackgroundRect;
+
+ iHandleBackgroundRect.iTl.iX += originalHandleBackgroundRect.iTl.iY - originalBackgroundRect.iTl.iY;
+ iHandleBackgroundRect.iBr.iX = iHandleBackgroundRect.iTl.iX + originalHandleBackgroundRect.Height();
+
+ TRect originalHandleRect = iHandleRect;
+ iHandleRect = iBackgroundRect;
+
+ iHandleRect.iTl.iX += originalHandleRect.iTl.iY - originalBackgroundRect.iTl.iY;
+ iHandleRect.iBr.iX = iHandleRect.iTl.iX + originalHandleRect.Height();
+ }
+ }
+
+
+void CAknDoubleSpanScrollIndicator::CheckValues(TInt& aScrollSpan, TInt& aFocusPosition, TInt& aWindowSize, TInt& aFieldPosition, TInt& aFieldSize) const
+ {
+ // Scrollspan
+ if (aScrollSpan <= 0)
+ {
+ // Default values, only background will be drawn
+ aScrollSpan = 0;
+ aWindowSize = 0;
+ aFocusPosition = 0;
+ aFieldSize = 0;
+ aFieldPosition = 0;
+ return;
+ }
+
+ // Window size
+ if (aWindowSize < 1)
+ {
+ aWindowSize = 1;
+ }
+ if (aWindowSize > aScrollSpan)
+ {
+ aWindowSize = aScrollSpan;
+ }
+
+ // FocusPosition
+ if (aFocusPosition < 0)
+ {
+ aFocusPosition = 0;
+ }
+ if (aFocusPosition + aWindowSize > aScrollSpan)
+ {
+ aFocusPosition = aScrollSpan - aWindowSize;
+ }
+
+ // Field size & position
+ if (aFieldSize <= 0)
+ {
+ aFieldSize = 0;
+ aFieldPosition = 0;
+ }
+ else
+ {
+ // Field position
+ if (aFieldPosition < 0)
+ {
+ aFieldPosition = 0;
+ }
+ if (aFieldPosition > aFieldSize - 1)
+ {
+ aFieldPosition = aFieldSize - 1;
+ }
+
+ }
+ }
+
+
+void CAknDoubleSpanScrollIndicator::SizeChanged()
+ {
+ TRect rect( Rect() );
+ if(iOldRect != rect)
+ {
+ iOldRect = rect;
+ AknsUtils::RegisterControlPosition( this );
+ CalculateRects();
+
+ if (iOwnsWindow)
+ {
+ TRAP_IGNORE(CreateBackgroundBitmapL());
+ }
+
+ UpdateScrollBarLayout();
+
+ if (IsVisible() & iOwnsWindow)
+ DrawDeferred();
+ }
+ }
+
+void CAknDoubleSpanScrollIndicator::SetIndicatorValues(TInt aScrollSpan, TInt aFocusPosition, TInt aWindowSize, TInt aFieldPosition, TInt aFieldSize)
+ {
+ // if nothing changed
+ if((iScrollSpan == aScrollSpan) &&
+ (iFocusPosition == aFocusPosition) &&
+ (iWindowSize == aWindowSize) &&
+ (iFieldPosition == aFieldPosition) &&
+ (iFieldSize == aFieldSize))
+ return;
+
+ iScrollSpan = aScrollSpan;
+ iFocusPosition = aFocusPosition;
+ iWindowSize = aWindowSize;
+ iFieldPosition = aFieldPosition;
+ iFieldSize = aFieldSize;
+
+ // Calculate the sizes for graphics
+ CalculateRects();
+ if( iWindowSize > 0 )
+ {
+ // layout handle graphics
+ LayoutHandleGraphics();
+ }
+ }
+
+TInt CAknDoubleSpanScrollIndicator::ScrollSpan()
+ {
+ return iScrollSpan;
+ }
+
+TInt CAknDoubleSpanScrollIndicator::FocusPosition()
+ {
+ return iFocusPosition;
+ }
+
+TInt CAknDoubleSpanScrollIndicator::WindowSize()
+ {
+ return iWindowSize;
+ }
+
+TInt CAknDoubleSpanScrollIndicator::FieldPosition()
+ {
+ return iFieldPosition;
+ }
+
+TInt CAknDoubleSpanScrollIndicator::FieldSize()
+ {
+ return iFieldSize;
+ }
+
+void CAknDoubleSpanScrollIndicator::SetTransparentBackground(TBool aTransparentBackground)
+ {
+ iTransparentBackground = aTransparentBackground;
+ }
+
+TBool CAknDoubleSpanScrollIndicator::TransparentBackground()
+ {
+ return iTransparentBackground;
+ }
+
+void CAknDoubleSpanScrollIndicator::HandleResourceChange(TInt aType)
+ {
+ if ( aType == KAknsMessageSkinChange )
+ {
+ iDrawBackgroundBitmap = ETrue;
+ }
+ else if( aType == KAknMessageFocusLost || KEikMessageUnfadeWindows == aType)
+ {
+ if( HandleHighlight() )
+ {
+ SetHandleHighlight(EFalse);
+ DrawDeferred();
+ }
+ if( BackgroudHighlight() )
+ {
+ SetBackgroudHighlight( EFalse );
+ }
+
+ }
+
+ // SizeChanged handles this. The Scb is always layouted by its parent
+ // if(aType == KEikDynamicLayoutVariantSwitch)
+
+
+ CCoeControl::HandleResourceChange(aType);
+ }
+
+CAknDoubleSpanScrollIndicatorItem* CAknDoubleSpanScrollIndicator::LoadScrollIndicatorItemL(
+ const TAknsItemID &aTopId,
+ const TAknsItemID &aMidId,
+ const TAknsItemID &aBottomId)
+ {
+ return CAknDoubleSpanScrollIndicatorItem::NewL(ETrue,
+ aTopId, 0, 0,
+ aMidId, 0, 0,
+ aBottomId, 0, 0);
+ }
+
+
+void CAknDoubleSpanScrollIndicator::CreateScrollBarItemsL()
+ {
+ // create items
+ if(iOrientation == CEikScrollBar::EVertical)
+ {
+ iBackgroundBar = LoadScrollIndicatorItemL(
+ KAknsIIDQsnCpScrollBgTop,
+ KAknsIIDQsnCpScrollBgMiddle,
+ KAknsIIDQsnCpScrollBgBottom);
+
+ iHandleBar = LoadScrollIndicatorItemL(
+ KAknsIIDQsnCpScrollHandleTop,
+ KAknsIIDQsnCpScrollHandleMiddle,
+ KAknsIIDQsnCpScrollHandleBottom);
+
+
+
+ if(AknLayoutUtils::PenEnabled())
+ {
+ iHighlightBackgroundBar = LoadScrollIndicatorItemL(
+ KAknsIIDQsnCpScrollHandleBgTop,
+ KAknsIIDQsnCpScrollHandleBgMiddle,
+ KAknsIIDQsnCpScrollHandleBgBottom);
+
+ iHighlightHandleBar = LoadScrollIndicatorItemL(
+ KAknsIIDQsnCpScrollHandleTopPressed,
+ KAknsIIDQsnCpScrollHandleMiddlePressed,
+ KAknsIIDQsnCpScrollHandleBottomPressed);
+ }
+ }
+ else
+ {
+ iBackgroundBar = LoadScrollIndicatorItemL(
+ KAknsIIDQsnCpScrollHorizontalBgTop,
+ KAknsIIDQsnCpScrollHorizontalBgMiddle,
+ KAknsIIDQsnCpScrollHorizontalBgBottom);
+
+ iHandleBar = LoadScrollIndicatorItemL(
+ KAknsIIDQsnCpScrollHorizontalHandleTop,
+ KAknsIIDQsnCpScrollHorizontalHandleMiddle,
+ KAknsIIDQsnCpScrollHorizontalHandleBottom);
+
+
+
+ if(AknLayoutUtils::PenEnabled())
+ {
+ //Handle background bar image missing....
+ /*
+ iHandleBackgroundBar = LoadScrollIndicatorItem(
+ KAknsIIDQsnCpScrollHorizontalHandleBgTop,
+ KAknsIIDQsnCpScrollHorizontalHandleBgMiddle,
+ KAknsIIDQsnCpScrollHorizontalHandleBgBottom);
+ */
+
+ iHighlightHandleBar = LoadScrollIndicatorItemL(
+ KAknsIIDQsnCpScrollHorizontalHandleTopPressed,
+ KAknsIIDQsnCpScrollHorizontalHandleMiddlePressed,
+ KAknsIIDQsnCpScrollHorizontalHandleBottomPressed);
+ }
+ }
+ }
+
+TInt CAknDoubleSpanScrollIndicator::IndicatorWidth()
+ {
+ TAknWindowComponentLayout layout;
+
+ if(iOrientation == CEikScrollBar::EHorizontal)
+ layout = AknLayoutScalable_Avkon::scroll_pane(1);
+ else
+ layout = AknLayoutScalable_Avkon::scroll_pane(0);
+
+ TAknLayoutRect layRect;
+ TRect mainpaneRect;
+ AknLayoutUtils::LayoutMetricsRect( AknLayoutUtils::EMainPane, mainpaneRect );
+ layRect.LayoutRect(mainpaneRect, layout.LayoutLine());
+
+ if(iOrientation == CEikScrollBar::EHorizontal)
+ return layRect.Rect().Height();
+ else
+ return layRect.Rect().Width();
+ }
+
+TInt CAknDoubleSpanScrollIndicator::ScrollHandleMaxVisibleSizeInPixels()
+ {
+ TRect scbRect = Rect();
+ if ( iOrientation == CEikScrollBar::EHorizontal )
+ scbRect.SetRect(scbRect.iTl, TSize(scbRect.Height(), scbRect.Width()));
+
+ TAknLayoutRect layRect;
+ TAknWindowComponentLayout layout = AknLayoutScalable_Avkon::aid_size_max_handle();
+ layRect.LayoutRect(scbRect, layout.LayoutLine());
+ return layRect.Rect().Height();
+ }
+
+TInt CAknDoubleSpanScrollIndicator::HandleBackgroundMinSizeInPixels()
+ {
+ return HandleMinSizeInPixels();
+ }
+
+TInt CAknDoubleSpanScrollIndicator::HandleMinSizeInPixels()
+ {
+ // We have the minimum size as aid value, do not layout to the handle layout as it is not correct
+ // on behalf of height argument (not set as maximum)
+ TRect scbRect = Rect();
+ if ( iOrientation == CEikScrollBar::EHorizontal )
+ scbRect.SetRect(scbRect.iTl, TSize(scbRect.Height(), scbRect.Width()));
+
+ TAknLayoutRect layRect;
+ TAknWindowComponentLayout layout = AknLayoutScalable_Avkon::aid_size_min_handle();
+ layRect.LayoutRect(scbRect, layout.LayoutLine());
+
+ return layRect.Rect().Height();
+ }
+
+
+void CAknDoubleSpanScrollIndicator::SetAsWindowOwning(TBool aOwnsWindow)
+ {
+ iOwnsWindow = aOwnsWindow;
+ }
+
+void CAknDoubleSpanScrollIndicator::SetDrawBackgroundState(TBool aDraw)
+ {
+ iDrawBackground = aDraw;
+ }
+
+TBool CAknDoubleSpanScrollIndicator::DrawBackgroundState()
+ {
+ return iDrawBackground;
+ }
+
+// Prepares background for window-owning scrollbar
+void CAknDoubleSpanScrollIndicator::CreateBackgroundBitmapL()
+ {
+
+ }
+
+void CAknDoubleSpanScrollIndicator::DrawBackground() const
+ {
+ CWindowGc& gc=SystemGc();
+ TPoint pos = Position();
+ TRect rect = Rect();
+ MAknsSkinInstance* skin = AknsUtils::SkinInstance();
+ MAknsControlContext* cc = AknsDrawUtils::ControlContext( this );
+
+ if(!iTransparentBackground)
+ {
+ if (iOwnsWindow ) // owns window
+ {
+ // Redraw the background to bitmap if the skin or the size is changed.
+ // Note that the indicator itself is not window owning but the actual window owning
+ // component is the scrollbar class, therefore the window may be in different position
+ // and size than the indicator itself
+ RWindow& win = Window();
+ iDrawBackgroundBitmap = EFalse;
+ TRect bmpRect(win.Position() + pos, rect.Size()); // There may be an arrow on top of scb
+ if ( CAknEnv::Static()->TransparencyEnabled() )
+ {
+ AknsDrawUtils::DrawBackground( skin, cc, NULL, gc,
+ rect.iTl, bmpRect, KAknsDrawParamNoClearUnderImage );
+ }
+ else
+ {
+ AknsDrawUtils::DrawBackground( skin, cc, NULL, gc,
+ TPoint(0,0), bmpRect , KAknsDrawParamNoClearUnderImage );
+
+
+ }
+ }
+ else //SB is non-window-owning
+ {
+ if ( CAknEnv::Static()->TransparencyEnabled() )
+ {
+ AknsDrawUtils::Background( skin, cc, this, gc, rect, KAknsDrawParamNoClearUnderImage );
+ }
+ else
+ {
+ AknsDrawUtils::Background( skin, cc, this, gc, rect );
+ }
+ }
+ }
+ }
+
+void CAknDoubleSpanScrollIndicator::LayoutHandleGraphics()
+ {
+
+ // We layout the handle middle graphics here according to the given inidcator values
+ TRect rect = Rect();
+
+ if (!iHandleBar || rect.IsEmpty())
+ return;
+
+ TInt varietyIndex = 0;
+ TInt varietyIndexForHandle = 0;
+ if (iOrientation == CEikScrollBar::EHorizontal)
+ {
+ varietyIndex = 1;
+ varietyIndexForHandle = 2;
+ }
+
+ TAknLayoutRect layRect;
+ TAknWindowComponentLayout // layout handle bottom & top as they do not scale according to handle size
+ layout = AknLayoutScalable_Avkon::scroll_handle_pane(varietyIndexForHandle); // handle (the shadow if two handles)
+ layRect.LayoutRect(rect, layout.LayoutLine());
+ layout = AknLayoutScalable_Avkon::scroll_handle_focus_pane(varietyIndex); // focus handle
+ // The horizontal data for focus handle is missing so switch the values from the vertical data
+ TAknWindowLineLayout layoutLine = layout.LayoutLine();
+ if (iOrientation == CEikScrollBar::EHorizontal)
+ {
+ TInt height = layoutLine.iH;
+ TInt width = layoutLine.iW;
+ layoutLine.iW = height;
+ layoutLine.iH = width;
+ }
+ layRect.LayoutRect(layRect.Rect(), layoutLine);
+ rect = layRect.Rect(); // parent rect is now the focus handle
+
+ // the retangle includes the variated length of the middle,
+ // the top and bottom graphics must subtracted from the value
+
+ // do not change the handle retangle, the full size is needed in drawing
+ // set the width or height to be correct
+ if (iOrientation == CEikScrollBar::EVertical)
+ {
+ iHandleRect.iTl.iX = rect.iTl.iX;
+ iHandleRect.iBr.iX = rect.iBr.iX;
+ }
+ else
+ {
+ iHandleRect.iTl.iY = rect.iTl.iY;
+ iHandleRect.iBr.iY = rect.iBr.iY;
+ }
+
+
+ }
+
+TInt CAknDoubleSpanScrollIndicator::GetCurrentThumbSpanInPixels()
+ {
+ return ( iOrientation == CEikScrollBar::EVertical ?
+ iHandleBackgroundRect.Height() :
+ iHandleBackgroundRect.Width() );
+ }
+
+TInt CAknDoubleSpanScrollIndicator::GetCurrentThumbPositionInPixels()
+ {
+ TInt ret;
+
+ if ( iOrientation == CEikScrollBar::EHorizontal )
+ {
+ ret = iHandleBackgroundRect.iTl.iX -
+ iBackgroundRect.iTl.iX;
+ }
+ else
+ {
+ ret = iHandleBackgroundRect.iTl.iY -
+ iBackgroundRect.iTl.iY;
+ }
+
+ return ret;
+ }
+
+void CAknDoubleSpanScrollIndicator::SetHandleHighlight( TBool aHandleHighlight )
+ {
+ // This does nothing in non-touch
+ iHandleHighlight = aHandleHighlight;
+ SetBackgroudHighlight(aHandleHighlight);
+ }
+
+TBool CAknDoubleSpanScrollIndicator::HandleHighlight() const
+ {
+ return iHandleHighlight;
+ }
+
+void CAknDoubleSpanScrollIndicator::SetTouchAreaControl( CCoeControl* aTouchAreaControl )
+ {
+ iTouchAreaControl = aTouchAreaControl;
+ }
+
+ void CAknDoubleSpanScrollIndicator::SetBackgroudHighlight( TBool aBackgroudHighlight )
+ {
+ // This does nothing in non-touch
+ iBackgroundHighlight = aBackgroudHighlight;
+
+ }
+
+TBool CAknDoubleSpanScrollIndicator::BackgroudHighlight() const
+ {
+ return iBackgroundHighlight;
+ }
+CFbsBitmap* CAknDoubleSpanScrollIndicator::CopyAndApplyEffectL(
+ const CFbsBitmap* aSource, TBool aCopyOnly )
+ {
+ CFbsBitmap* newBitmap = NULL;
+
+
+ newBitmap = new ( ELeave ) CFbsBitmap;
+
+
+
+ TInt err = newBitmap->Create( aSource->SizeInPixels(), aSource->DisplayMode() );
+
+ // We still have to return a dummy bitmap object, even if
+ // the creation fails.
+ if ( err == KErrNone )
+ {
+ SEpocBitmapHeader header = aSource->Header();
+
+ // We support only 16-bit (5-6-5), since this is the default
+ // display mode icons are created in. Otherwise just copy.
+ if ( !aCopyOnly && aSource->DisplayMode() == EColor64K )
+ {
+ // Don't modify header data.
+ TInt size = ( header.iBitmapSize - header.iStructSize ) /
+ sizeof( TUint16 );
+
+ aSource->BeginDataAccess();
+
+ TUint16* source = (TUint16*)aSource->DataAddress();
+ TUint16* dest = (TUint16*)newBitmap->DataAddress();
+
+ for ( TInt i = 0; i < size; ++i )
+ {
+ *dest = *source++;
+ TBitmapFx::PixelEffect( dest++ );
+ }
+
+ aSource->EndDataAccess( ETrue );
+ }
+ else
+ {
+ // This is probably faster than blitting it. Copy
+ // the header data in the same run to minimize size
+ // calculations, although it's already correct in the
+ // new bitmap.
+ TInt size = aSource->Header().iBitmapSize;
+
+ aSource->BeginDataAccess();
+
+ Mem::Copy( newBitmap->DataAddress(),
+ aSource->DataAddress(),
+ size );
+
+ aSource->EndDataAccess( ETrue );
+ }
+ }
+
+
+ return newBitmap;
+ }
+
+
+void TBitmapFx::PixelEffect( TUint16* aPixelData )
+ {
+ // Note: the calculations in this function are based on
+ // graphic designers' conception of what Photoshop does
+ // to images with certain values. There might also be some
+ // room for optimizations.
+
+ TRGB rgb;
+
+ rgb.iR = ( *aPixelData & 0xF800 ) >> 11;
+ rgb.iG = ( *aPixelData & 0x7E0 ) >> 5;
+ rgb.iB = ( *aPixelData & 0x1F );
+
+ // Scale to 65280 (0xFF00). Under no circumstances should these
+ // values end up being > 0xFF00 or < 0x00
+ rgb.iR *= 2105.82f;
+ rgb.iG *= 1036.20f;
+ rgb.iB *= 2105.82f;
+
+ // Convert RGB to HSL
+ TInt min = Min( rgb.iR, Min( rgb.iG, rgb.iB ) );
+ TInt max = Max( rgb.iR, Max( rgb.iG, rgb.iB ) );
+ TInt delta = max - min;
+
+ THSL hsl = { 0, 0, 0 } ;
+
+ // Lightness
+ hsl.iL = ( max + min ) >> 1;
+
+ if ( delta == 0 )
+ {
+ hsl.iH = 0;
+ hsl.iS = 0;
+ }
+ else
+ {
+ // Hue
+ if ( max == rgb.iR )
+ {
+ hsl.iH = 10880 * ( rgb.iG - rgb.iB ) / delta;
+ }
+ else if ( max == rgb.iG )
+ {
+ hsl.iH = 10880 * ( rgb.iB - rgb.iR ) / delta + 21760;
+ }
+ else if ( max == rgb.iB )
+ {
+ hsl.iH = 10880 * ( rgb.iR - rgb.iG ) / delta + 43520;
+ }
+
+ // Saturation
+ if ( hsl.iL <= 32640 )
+ {
+ hsl.iS = ( delta << KPrecision ) / ( ( max + min ) >> KPrecision );
+ }
+ else
+ {
+ hsl.iS = ( delta << KPrecision ) / ( ( 0x1FE00 - ( max + min ) ) >> KPrecision );
+ }
+ }
+
+ // Apply hue shift, moved to proper range in HueToRGB()
+ hsl.iH += 0x715;
+
+ // Apply saturation
+ // +10 in -100..100 in Photoshop terms. According to related material
+ // corresponds to 0xCC0 when applied to 0x00..0xFF00
+ hsl.iS += 0xCC0;
+
+ if ( hsl.iS > 0xFF00 )
+ {
+ hsl.iS = 0xFF00;
+ }
+
+ // Convert back to RGB
+ TInt v1;
+ TInt v2;
+
+ if ( hsl.iS == 0 )
+ {
+ rgb.iR = ( hsl.iL * 255 ) >> KPrecision;
+ rgb.iG = ( hsl.iL * 255 ) >> KPrecision;
+ rgb.iB = ( hsl.iL * 255 ) >> KPrecision;
+ }
+ else
+ {
+ if ( hsl.iL < 32640 )
+ {
+ v2 = ( hsl.iL * ( ( 0xFF00 + hsl.iS ) >> KPrecision ) ) >> KPrecision;
+ }
+ else
+ {
+ v2 = ( hsl.iL + hsl.iS ) - ( ( hsl.iS >> KPrecision ) * ( hsl.iL >> KPrecision ) );
+ }
+
+ v1 = 2 * hsl.iL - v2;
+
+ rgb.iR = ( HueToRGB( v1, v2, hsl.iH + 0x54FF ) );
+ rgb.iG = ( HueToRGB( v1, v2, hsl.iH ) );
+ rgb.iB = ( HueToRGB( v1, v2, hsl.iH - 0x54FF ) );
+ }
+
+ rgb.iR /= 2105.82f;
+ rgb.iG /= 1036.20f;
+ rgb.iB /= 2105.82f;
+
+ // Apply contrast.. However, the original req stated that the
+ // contrast value should be +6 in a range of -100..100.
+ // With 5 and 6 bit values and fixed point math such a small value has
+ // no effect, so it has been left out. The code is here in case
+ // the contrast value is updated at some point.
+ /*
+ const TInt contrast = ( 6 * 65536 / 200 ) + 65536;
+
+ rgb.iR -= 15;
+ rgb.iG -= 31;
+ rgb.iB -= 15;
+
+ rgb.iR *= contrast;
+ rgb.iG *= contrast;
+ rgb.iB *= contrast;
+
+ rgb.iR /= 65536;
+ rgb.iG /= 65536;
+ rgb.iB /= 65536;
+
+ rgb.iR += 15;
+ rgb.iG += 31;
+ rgb.iB += 15;
+ */
+
+ // Apply brightness, -40 in a range of -100..100 for
+ // 0..255 rgb values, which corresponds to -5 for 5 bit
+ // and -10 for 6 bit rgb values.
+ rgb.iR -= 5;
+ rgb.iG -= 10;
+ rgb.iB -= 5;
+
+ if ( rgb.iR < 0 ) rgb.iR = 0;
+ if ( rgb.iG < 0 ) rgb.iG = 0;
+ if ( rgb.iB < 0 ) rgb.iB = 0;
+
+ if ( rgb.iR > 31 ) rgb.iR = 31;
+ if ( rgb.iG > 63 ) rgb.iG = 63;
+ if ( rgb.iB > 31 ) rgb.iB = 31;
+
+ *aPixelData =
+ ( rgb.iB | ( rgb.iG << 5 ) | ( rgb.iR << 11 ) );
+ }
+
+TInt TBitmapFx::HueToRGB( TInt v1, TInt v2, TInt aH )
+ {
+ while ( aH < 0 )
+ {
+ aH += 0xFF00;
+ }
+
+ while ( aH >= 0xFF00 )
+ {
+ aH -= 0xFF00;
+ }
+
+ if ( ( ( 6 * aH ) ) < 0xFF00 )
+ {
+ return v1 + ( ( v2 - v1 ) * ( ( 6 * aH ) >> KPrecision ) >> KPrecision );
+ }
+
+ if ( ( ( 2 * aH ) ) < 0xFF00 )
+ {
+ return v2;
+ }
+
+ if ( ( ( 3 * aH ) ) < 0x1FE00 )
+ {
+ return v1 + ( ( v2 - v1 ) * ( ( ( 0xA9FF - aH ) * 6 ) >> KPrecision ) >> KPrecision );
+ }
+
+ return v1;
+ }
+