uifw/AvKon/src/aknindicatorpopupcontent.cpp
changeset 0 2f259fa3e83a
child 16 71dd06cfe933
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/uifw/AvKon/src/aknindicatorpopupcontent.cpp	Tue Feb 02 01:00:49 2010 +0200
@@ -0,0 +1,1552 @@
+/*
+* Copyright (c) 2007,2008 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:  Content that is shown inside a universal status
+*                indicator popup.
+*
+*/
+
+
+// SYSTEM INCLUDE FILES
+
+#include <AknsDrawUtils.h>
+#include <aknlayoutscalable_avkon.cdl.h>
+#include <AknsConstants.h>
+#include <AknUtils.h>
+#include "akndigitalclock.h"
+#include <avkon.mbg>
+#include <gulicon.h>
+#include <barsread.h>
+#include <AknIndicator.h>
+#include <AknIndicatorPlugin.h>
+#include <AknIndicatorPluginImplUIDs.hrh>
+#include <AknIndicatorContainer.h>
+#include <apgcli.h>
+#include <aknconsts.h>
+#include <aknglobalpopupprioritycontroller.h>
+#include <AknTasHook.h> // for testability hooks
+#include <touchfeedback.h>
+
+
+// USER INCLUDE FILES
+#include "aknindicatorpopupcontent.h"
+#include "aknindicatorpopup.h"
+#include "AknBatteryIcon.h"
+#include "AknSignalIcon.h"
+
+
+// CONSTANTS
+
+/** Granularity of the indicator item array. */
+const TInt KItemArrayGranularity = 8;
+
+/** Path to the clock application, launched directly from the popup. */
+_LIT( KClockApplication, "\\sys\\bin\\clock.exe" );
+
+/** Internal state flags. */
+enum TIndicatorPopupContentFlags
+    {
+    /** Pointer down event has happened inside this control. */
+    EAknIndicatorPopupContentButton1Down        = 0x00000001,
+    /** Clock application is being launched. */
+    EAknIndicatorPopupContentClockBeingLaunched = 0x00000002
+    };
+
+const TInt KBatteryAreaIndex = 0;
+const TInt KSignalAreaIndex  = 1;
+
+
+// =============================================================================
+// CAknIndicatorPopupItem
+// Item class declaration & definition.
+// =============================================================================
+//
+NONSHARABLE_CLASS( CAknIndicatorPopupItem ) : public CBase
+    {
+public:
+
+    /**
+    * Default constructor.
+    *
+    * @param  aUid       UID of the indicator.
+    * @param  aPlugin    Pointer to the indicator's ECOM plugin,
+    *                    can be NULL.
+    * @param  aPriority  Display priority of the indicator.
+    * @param  aTextType  Type of the item text.
+    */
+    CAknIndicatorPopupItem( TInt aUid,
+                            CAknIndicatorPlugin* aPlugin,
+                            TInt aPriority,
+                            TInt aTextType );
+
+    /**
+    * Destructor.
+    */
+    ~CAknIndicatorPopupItem();
+
+    /**
+    * Second-phase constructor to be used with custom icon.
+    *
+    * @param  aText  Item text.
+    * @param  aIcon  Indicator icon.
+    */
+    void ConstructL( const TDesC& aText,
+                     const CGulIcon* aIcon );
+
+    /**
+    * Second-phase constructor to be used with the default
+    * indicator icon.
+    *
+    * @param  aText    Item text.
+    * @param  aIconID  Index of the indicator icon.
+    * @param  aIconID  Index of the indicator icon mask.
+    */
+    void ConstructL( const TDesC& aText,
+                     TInt aIconID,
+                     TInt aIconMaskID );
+
+    /**
+    * Sets the area of this item in the popup.
+    *
+    * @param  aRect  Rectangle of this item, relative
+    *                to the popup.
+    */
+    void SetRect( const TRect& aRect );
+
+    /**
+    * Changes the indicator icon of the item or updates
+    * the color when skin changes.
+    *
+    * @param  aIcon  Pointer to the new icon if the icon
+    *                is to be changed.
+    */
+    void UpdateIndicatorIconL( const CGulIcon* aIcon = NULL );
+
+    /**
+    * Updates the item text.
+    *
+    * @param  aText  Item text.
+    */
+    void UpdateTextL( const TDesC& aText, TInt aTextType );
+
+    /**
+    * Draws the item.
+    *
+    * @param  aGc  Reference to the window graphics context.
+    */
+    void DrawItem( CWindowGc& aGc );
+
+public: // Member data
+
+    /** UID of the indicator. */
+    TInt                  iUid;
+
+    /** Indicator priority. */
+    TInt                  iPriority;
+
+    /** Item text, owned. */
+    HBufC*                iText;
+
+    /** Type of the text. */
+    TInt                  iTextType;
+
+    /** Item area. */
+    TRect                 iRect;
+
+    /** Indicator icon area. */
+    TRect                 iIconRect;
+
+    /** Default indicator icon, owned. */
+    CGulIcon*             iIcon;
+
+    /** Custom indicator icon, not owned. */
+    const CGulIcon*       iCustomIcon;
+
+    /** Index of the default indicator icon. */
+    TInt                  iIconID;
+
+    /** Index of the default indicator icon mask. */
+    TInt                  iIconMaskID;
+
+    /** Pointer to the indicator plugin, not owned. */
+    CAknIndicatorPlugin*  iPlugin;
+    };
+
+
+// -----------------------------------------------------------------------------
+// CAknIndicatorPopupItem::CAknIndicatorPopupItem
+// Default constructor
+// -----------------------------------------------------------------------------
+//
+CAknIndicatorPopupItem::CAknIndicatorPopupItem( TInt aUid,
+                                                CAknIndicatorPlugin* aPlugin,
+                                                TInt aPriority,
+                                                TInt aTextType )
+    : iUid( aUid ),
+      iPriority( aPriority ),
+      iTextType( aTextType ),
+      iPlugin( aPlugin )
+    {
+    }
+
+
+// -----------------------------------------------------------------------------
+// CAknIndicatorPopupItem::CAknIndicatorPopupItem
+// Destructor
+// -----------------------------------------------------------------------------
+//
+CAknIndicatorPopupItem::~CAknIndicatorPopupItem()
+    {
+    delete iText;
+    delete iIcon;
+    }
+
+
+// -----------------------------------------------------------------------------
+// CAknIndicatorPopupItem::ConstructL
+// Second-phase constructor
+// -----------------------------------------------------------------------------
+//
+void CAknIndicatorPopupItem::ConstructL( const TDesC& aText,
+                                         const CGulIcon* aIcon )
+    {
+    delete iText;
+    iText = NULL;
+    iText = aText.AllocL();
+
+    iCustomIcon = aIcon;
+    }
+
+
+// -----------------------------------------------------------------------------
+// CAknIndicatorPopupItem::ConstructL
+// Second-phase constructor
+// -----------------------------------------------------------------------------
+//
+void CAknIndicatorPopupItem::ConstructL( const TDesC& aText,
+                                         TInt aIconID,
+                                         TInt aIconMaskID )
+    {
+    delete iText;
+    iText = NULL;
+    iText = aText.AllocL();
+
+    iIconID     = aIconID;
+    iIconMaskID = aIconMaskID;
+
+    UpdateIndicatorIconL();
+    }
+
+
+// -----------------------------------------------------------------------------
+// CAknIndicatorPopupItem::SetRect
+// -----------------------------------------------------------------------------
+//
+void CAknIndicatorPopupItem::SetRect( const TRect& aRect )
+    {
+    iRect = aRect;
+
+    TAknLayoutRect layoutRect;
+    layoutRect.LayoutRect(
+        iRect,
+        AknLayoutScalable_Avkon::list_single_uniindi_pane_g1() );
+    iIconRect = layoutRect.Rect();
+
+    CFbsBitmap* bitmap = NULL;
+
+    if ( iCustomIcon )
+        {
+        bitmap = iCustomIcon->Bitmap();
+        }
+    else if ( iIcon )
+        {
+        bitmap = iIcon->Bitmap();
+        }
+
+    if ( bitmap )
+        {
+        AknIconUtils::SetSize( bitmap,
+                               iIconRect.Size(),
+                               EAspectRatioPreserved );
+        }
+    }
+
+
+// -----------------------------------------------------------------------------
+// CAknIndicatorPopupItem::UpdateIndicatorIconL
+// -----------------------------------------------------------------------------
+//
+void CAknIndicatorPopupItem::UpdateIndicatorIconL( const CGulIcon* aIcon )
+    {
+    if ( iCustomIcon &&
+         !aIcon )
+        {
+        // Custom icon in use
+        if ( iPlugin )
+            {
+            iCustomIcon = NULL;
+            TRAPD( err, iCustomIcon = iPlugin->IconL( iUid ) );
+
+            if ( !err && iCustomIcon )
+                {
+                // Icon update succeeded.
+                AknIconUtils::SetSize( iCustomIcon->Bitmap(),
+                                       iIconRect.Size(),
+                                       EAspectRatioPreserved );
+                return;
+                }
+
+            // Else use the default icon.
+            }
+        }
+
+    delete iIcon;
+    iIcon = NULL;
+
+    if ( aIcon )
+        {
+        iCustomIcon = aIcon;
+
+        AknIconUtils::SetSize( iCustomIcon->Bitmap(),
+                               iIconRect.Size(),
+                               EAspectRatioPreserved );
+        }
+    else
+        {
+        CFbsBitmap* bitmap;
+        CFbsBitmap* mask;
+
+        MAknsSkinInstance* skin = AknsUtils::SkinInstance();
+
+        AknsUtils::CreateColorIconLC(
+            skin,
+            KAknsIIDDefault,
+            KAknsIIDQsnIconColors,
+            EAknsCIQsnIconColorsCG20,
+            bitmap,
+            mask,
+            KAvkonBitmapFile,
+            iIconID,
+            iIconMaskID,
+            KRgbGray );
+
+        AknIconUtils::SetSize( bitmap,
+                               iIconRect.Size(),
+                               EAspectRatioPreserved );
+
+        iIcon = CGulIcon::NewL( bitmap, mask );
+
+        CleanupStack::Pop( 2, bitmap );
+        }
+    }
+
+
+// -----------------------------------------------------------------------------
+// CAknIndicatorPopupItem::UpdateTextL
+// -----------------------------------------------------------------------------
+//
+void CAknIndicatorPopupItem::UpdateTextL( const TDesC& aText, TInt aTextType )
+    {
+    delete iText;
+    iText = NULL;
+    iText = aText.AllocL();
+    iTextType = aTextType;
+    }
+
+
+// -----------------------------------------------------------------------------
+// CAknIndicatorPopupItem::DrawItem
+// -----------------------------------------------------------------------------
+//
+void CAknIndicatorPopupItem::DrawItem( CWindowGc& aGc )
+    {
+    // Use custom icon if it exists.
+    const CGulIcon* icon = iCustomIcon;
+    if ( !icon )
+        {
+        icon = iIcon;
+        }
+
+    if ( icon && icon->Bitmap() && icon->Mask() )
+        {
+        aGc.BitBltMasked( iIconRect.iTl,
+                          icon->Bitmap(),
+                          iIconRect.Size(),
+                          icon->Mask(),
+                          ETrue );
+        }
+
+    MAknsSkinInstance* skin = AknsUtils::SkinInstance();
+
+    TAknTextLineLayout textLayout(
+        AknLayoutScalable_Avkon::list_single_uniindi_pane_t1().LayoutLine() );
+
+    TRgb textColor;
+
+    if ( iTextType == CAknIndicatorPlugin::EAknIndicatorPluginLinkText )
+        {
+        aGc.SetUnderlineStyle( EUnderlineOn );
+        AknsUtils::GetCachedColor( skin,
+                                   textColor,
+                                   KAknsIIDQsnHighlightColors,
+                                   EAknsCIQsnHighlightColorsCG3 );
+        }
+    else
+        {
+        AknsUtils::GetCachedColor( skin,
+                                   textColor,
+                                   KAknsIIDQsnTextColors,
+                                   EAknsCIQsnTextColorsCG55 );
+        }
+
+    TAknLayoutText layoutText;
+    layoutText.LayoutText( iRect, textLayout );
+    layoutText.DrawText( aGc, *iText, ETrue, textColor );
+
+    aGc.SetUnderlineStyle( EUnderlineOff );
+    }
+
+
+// =============================================================================
+// CAknIndicatorPopupContent
+// =============================================================================
+//
+
+// -----------------------------------------------------------------------------
+// CAknIndicatorPopupContent::NewL
+// -----------------------------------------------------------------------------
+//
+CAknIndicatorPopupContent* CAknIndicatorPopupContent::NewL()
+    {
+    CAknIndicatorPopupContent* self = CAknIndicatorPopupContent::NewLC();
+    CleanupStack::Pop( self );
+    return self;
+    }
+
+
+// -----------------------------------------------------------------------------
+// CAknIndicatorPopupContent::NewLC
+// -----------------------------------------------------------------------------
+//
+CAknIndicatorPopupContent* CAknIndicatorPopupContent::NewLC()
+    {
+    CAknIndicatorPopupContent* self = new (ELeave) CAknIndicatorPopupContent;
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    AKNTASHOOK_ADDL( self, "CAknIndicatorPopupContent" );
+    return self;
+    }
+
+
+// -----------------------------------------------------------------------------
+// Destructor.
+// -----------------------------------------------------------------------------
+//
+CAknIndicatorPopupContent::~CAknIndicatorPopupContent()
+    {
+    AKNTASHOOK_REMOVE();
+    // Ensure here that this popup is removed from the global
+    // popup priority stack.
+    AknGlobalPopupPriorityController::RemovePopupPriority( *this );
+
+    iItems.ResetAndDestroy();
+    iItems.Close();
+
+    delete iClock;
+    delete iBattery;
+    delete iSignal;
+
+    if ( iBatteryPlugin || iSignalPlugin )
+        {
+        delete iBatteryPlugin;
+        delete iSignalPlugin;
+        REComSession::FinalClose();
+        }
+
+    MTouchFeedback* feedback = MTouchFeedback::Instance();
+    if ( feedback )
+        {
+        feedback->RemoveFeedbackForControl( this );
+        }
+
+    delete iSeparatorIcon;
+    }
+
+
+// -----------------------------------------------------------------------------
+// From class CCoeControl
+// CAknIndicatorPopupContent::MinimumSize
+// -----------------------------------------------------------------------------
+//
+TSize CAknIndicatorPopupContent::MinimumSize()
+    {
+    TInt items( iItems.Count() );
+
+    // Get the maximum number of indicator items from layout data.
+    TAknLayoutScalableParameterLimits limits(
+        AknLayoutScalable_Avkon::list_single_uniindi_pane_ParamLimits() );
+    TInt variety( limits.LastRow() + 1 ); // Last variety for no indicator items
+
+    if ( items > 0 )
+        {
+        if ( items <= variety )
+            {
+            variety -= items;
+            }
+        else
+            {
+            variety = 0; // Maximum number of items.
+            }
+        }
+
+    TRect applicationWindow;
+    AknLayoutUtils::LayoutMetricsRect( AknLayoutUtils::EApplicationWindow,
+                                       applicationWindow );
+
+    TAknLayoutRect layoutRect;
+    layoutRect.LayoutRect(
+        applicationWindow,
+        AknLayoutScalable_Avkon::popup_uni_indicator_window( variety ) );
+
+    return TSize( layoutRect.Rect().Size() );
+    }
+
+
+// -----------------------------------------------------------------------------
+// From class CCoeControl
+// CAknIndicatorPopupContent::HandleResourceChange
+// -----------------------------------------------------------------------------
+//
+void CAknIndicatorPopupContent::HandleResourceChange( TInt aType )
+    {
+    CCoeControl::HandleResourceChange( aType );
+
+    TInt  itemCount( iItems.Count() );
+
+    switch ( aType )
+        {
+        case KAknsMessageSkinChange:
+            {
+            // Update clock text color.
+            TRgb textColor;
+
+            MAknsSkinInstance* skin = AknsUtils::SkinInstance();
+
+            AknsUtils::GetCachedColor( skin,
+                                       textColor,
+                                       KAknsIIDQsnTextColors,
+                                       EAknsCIQsnTextColorsCG55 );
+
+            iClock->SetColor( textColor );
+
+            // Update signal icon.
+            iSignal->SetColorIndex( 0 ); // reset skin color
+            TRAP_IGNORE( SetSignalStateL( iSignalState ) );
+            // Color of the battery indicator is changed by it's container.
+            iBattery->HandleResourceChange( aType );
+            // Update the signal icon and separator line color.
+            TRAP_IGNORE( LoadIconsL() );
+
+            // Update the color of the indicator icons.
+            for ( TInt i = 0; i < itemCount; i++ )
+                {
+                TRAP_IGNORE( iItems[i]->UpdateIndicatorIconL() );
+                }
+            break;
+            }
+
+        case KEikMessageFadeAllWindows:
+            {
+            if ( !Window().IsFaded() )
+                {
+                Window().SetFaded( ETrue,
+                                   RWindowTreeNode::EFadeIncludeChildren );
+                }
+            break;
+            }
+
+        case KEikMessageUnfadeWindows:
+            {
+            if ( Window().IsFaded() )
+                {
+                Window().SetFaded( EFalse,
+                                   RWindowTreeNode::EFadeIncludeChildren );
+                }
+            break;
+            }
+
+        default:
+            break;
+        }
+    }
+
+
+// -----------------------------------------------------------------------------
+// From class CCoeControl
+// CAknIndicatorPopupContent::HandlePointerEventL
+// -----------------------------------------------------------------------------
+//
+void CAknIndicatorPopupContent::HandlePointerEventL(
+    const TPointerEvent& aPointerEvent )
+    {
+    if ( Rect().Contains( aPointerEvent.iPosition ) )
+        {
+        CBase* currentFocusedItem = NULL;
+        switch ( aPointerEvent.iType )
+            {
+            case TPointerEvent::EButton1Down:
+                // Set flag that down was inside the popup.
+                iFlags |= EAknIndicatorPopupContentButton1Down;
+                iPreviousPressedDownItem = NULL;
+                
+                if ( iClock->Rect().Contains( aPointerEvent.iPosition ))
+                    {
+                    currentFocusedItem = iClock;
+                    iPressedDownRect = iClockPressedDownArea;
+                    }
+                else if ( iSignalArea.Contains( aPointerEvent.iPosition ))
+                    {
+                    currentFocusedItem = iSignal;
+                    iPressedDownRect = iSignalPressedDownArea;
+                    }
+                else if ( iBatteryArea.Contains( aPointerEvent.iPosition ))
+                    {
+                    currentFocusedItem = iBattery;
+                    iPressedDownRect = iBatteryArea;
+                    }
+                else
+                    {
+                    CAknIndicatorPopupItem* item = TappedItem( aPointerEvent.iPosition );
+                    if ( item )
+                        {
+                        currentFocusedItem = item;
+                        iPressedDownRect = item->iRect;
+                        }
+                    else
+                    // No item get tapped
+                        {                        
+                        return;
+                        }                   
+                    }
+                iEnablePressedDownState = ETrue;
+                Window().Invalidate( iPressedDownRect );                
+                iPreviousPressedDownItem = currentFocusedItem;
+                break;    
+
+            case TPointerEvent::EDrag:
+                if ( iClock->Rect().Contains( aPointerEvent.iPosition ))
+                    {
+                    currentFocusedItem = iClock;
+                    }
+                else if ( iSignalArea.Contains( aPointerEvent.iPosition ))
+                    {
+                    currentFocusedItem = iSignal;
+                    }
+                else if ( iBatteryArea.Contains( aPointerEvent.iPosition ))
+                    {
+                    currentFocusedItem = iBattery;
+                    }
+                else
+                    {
+                    currentFocusedItem = TappedItem( aPointerEvent.iPosition );
+                    }
+  
+                if( currentFocusedItem != iPreviousPressedDownItem )
+                    {
+                    iFlags &= ~EAknIndicatorPopupContentButton1Down;
+                    iEnablePressedDownState = EFalse;
+                    Window().Invalidate( iPressedDownRect );                    
+                    }
+                break;
+
+            case TPointerEvent::EButton1Up:
+                if ( iFlags & EAknIndicatorPopupContentButton1Down )
+                    {
+                    // Up happened, reset button down flag.
+                    iFlags &= ( ~EAknIndicatorPopupContentButton1Down );
+                    iEnablePressedDownState = EFalse;
+
+                    if ( iBatteryPlugin &&
+                         iBatteryArea.Contains( aPointerEvent.iPosition ) )
+                        {
+                        ReportEventL(
+                            static_cast<MCoeControlObserver::TCoeEvent>(
+                                EAknIndicatorPopupTapEvent ) );
+                            
+                        // Dummy value used as indicator UID parameter,
+                        // as it's not used by the battery indicator plugin.
+                        iBatteryPlugin->HandleIndicatorTapL( 0 );
+                        break;
+                        }
+                    else if ( iSignalPlugin &&
+                         iSignalArea.Contains( aPointerEvent.iPosition ) )
+                        {
+                        ReportEventL(
+                            static_cast<MCoeControlObserver::TCoeEvent>(
+                                EAknIndicatorPopupTapEvent ) );
+
+                        // Dummy value used as indicator UID parameter,
+                        // as it's not used by the signal indicator plugin.
+                        iSignalPlugin->HandleIndicatorTapL( 0 );
+                        break;
+                        }
+                    else if ( iClock &&
+                              iClock->Rect().Contains( aPointerEvent.iPosition ) )
+                        {
+                        ReportEventL(
+                            static_cast<MCoeControlObserver::TCoeEvent>(
+                                EAknIndicatorPopupTapEvent ) );
+
+                        if ( !( iFlags & EAknIndicatorPopupContentClockBeingLaunched ) )
+                            {
+                            // Start clock application directly when down event
+                            // happens in clock, this functionality was previously
+                            // in the CAknDigitalClock.
+                            RApaLsSession apa;
+                            User::LeaveIfError( apa.Connect() );
+                            CleanupClosePushL( apa );
+                            CApaCommandLine* cmdLine = CApaCommandLine::NewLC();
+                            cmdLine->SetExecutableNameL( KClockApplication );
+                            cmdLine->SetCommandL( EApaCommandRun );
+                            User::LeaveIfError( apa.StartApp( *cmdLine ) );
+                            CleanupStack::PopAndDestroy( 2, &apa ); // cmdLine and apa
+
+                            // Set the flag indicating that clock is being launched.
+                            iFlags |= EAknIndicatorPopupContentClockBeingLaunched;
+                            }
+                        }
+
+                    CAknIndicatorPopupItem* item = TappedItem( aPointerEvent.iPosition );
+                    if ( item )
+                        {
+                        ReportEventL(
+                            static_cast<MCoeControlObserver::TCoeEvent>(
+                                EAknIndicatorPopupTapEvent ) );
+                        
+                        item->iPlugin->HandleIndicatorTapL( item->iUid );
+                        break;
+                        }
+                    }
+                break;
+
+            default:
+                break;
+            }
+        }
+    else if ( iFlags & EAknIndicatorPopupContentButton1Down )// Drag to outside
+        {
+        iFlags &= ~EAknIndicatorPopupContentButton1Down;
+        iEnablePressedDownState = EFalse;
+        Window().Invalidate( iPressedDownRect );
+        }
+    }
+
+
+// -----------------------------------------------------------------------------
+// From class CCoeControl
+// CAknIndicatorPopupContent::CountComponentControls
+// -----------------------------------------------------------------------------
+//
+TInt CAknIndicatorPopupContent::CountComponentControls() const
+    {
+    TInt count = 0;
+
+    if ( iClock )
+        {
+        count++;
+        }
+
+    if ( iBattery )
+        {
+        count++;
+        }
+
+    if ( iSignal )
+        {
+        count++;
+        }
+
+    return count;
+    }
+
+
+// -----------------------------------------------------------------------------
+// From class CCoeControl
+// CAknIndicatorPopupContent::ComponentControl
+// -----------------------------------------------------------------------------
+//
+CCoeControl* CAknIndicatorPopupContent::ComponentControl( TInt aIndex ) const
+    {
+    CCoeControl* componentControl = NULL;
+
+    switch ( aIndex )
+        {
+        case 0:
+            componentControl = iClock;
+            break;
+        case 1:
+            componentControl = iBattery;
+            break;
+        case 2:
+            componentControl = iSignal;
+            break;
+        default:
+            break;
+        }
+
+    return componentControl;
+    }
+
+
+// -----------------------------------------------------------------------------
+// From class CCoeControl.
+// CAknIndicatorPopupContent::SetContainerWindowL
+// -----------------------------------------------------------------------------
+//
+void CAknIndicatorPopupContent::SetContainerWindowL(
+    const CCoeControl& aContainer )
+    {
+    CCoeControl::SetContainerWindowL( aContainer );
+
+    if( iClock )
+        {
+        iClock->SetContainerWindowL( aContainer );
+        }
+    }
+
+
+// ---------------------------------------------------------------------------
+// CAknIndicatorPopupContent::AddItemL
+// ---------------------------------------------------------------------------
+//
+void CAknIndicatorPopupContent::AddItemL( TInt aIndicatorUid,
+                                          const TDesC& aText,
+                                          TInt aTextType,
+                                          const CGulIcon* aIcon,
+                                          CAknIndicatorPlugin* aPlugin,
+                                          TInt aPriority )
+    {
+    TInt  itemCount( iItems.Count() );
+    for ( TInt i = 0; i < itemCount; i++ )
+        {
+        if ( iItems[i]->iUid == aIndicatorUid )
+            {
+            // Indicator item exists already.
+            return;
+            }
+        }
+
+    CAknIndicatorPopupItem* newItem =
+        new (ELeave) CAknIndicatorPopupItem( aIndicatorUid,
+                                             aPlugin,
+                                             aPriority,
+                                             aTextType );
+
+    if ( aIcon )
+        {
+        // If the plugin provides an icon, use it.
+        newItem->ConstructL( aText, aIcon );
+        }
+    else
+        {
+        // Otherwise use the same icon as in the indicator pane.
+        TInt bitmapID;
+        TInt maskID;
+
+        CAknIndicator::GetBitmapIndexL(
+            CAknIndicatorContainer::EUniversalIndicators,
+            aIndicatorUid,
+            bitmapID,
+            maskID );
+
+        newItem->ConstructL( aText, bitmapID, maskID );
+        }
+
+    if ( aPlugin )
+        {
+        aPlugin->SetPluginObserver( this );
+        }
+
+    iItems.AppendL( newItem );
+
+    // Discard possible pressed down highlight when the popup size changes,
+    // as the position of the highlighted item may change.
+    iEnablePressedDownState = EFalse;
+    
+    SizeChanged();
+    }
+
+
+// ---------------------------------------------------------------------------
+// CAknIndicatorPopupContent::RemoveItem
+// ---------------------------------------------------------------------------
+//
+void CAknIndicatorPopupContent::RemoveItem( TInt aIndicatorUid )
+    {
+    TInt itemCount( iItems.Count() );
+    for ( TInt i = 0; i < itemCount; i++ )
+        {
+        if ( iItems[i]->iUid == aIndicatorUid )
+            {
+            delete iItems[i];
+            iItems[i] = NULL;
+            iItems.Remove( i );
+            break;
+            }
+        }
+
+    // Discard possible pressed down highlight when the popup size changes,
+    // as the position of the highlighted item may change.
+    iEnablePressedDownState = EFalse;
+    
+    SizeChanged();
+    }
+
+
+// ---------------------------------------------------------------------------
+// CAknIndicatorPopupContent::SetContentVisible
+// ---------------------------------------------------------------------------
+//
+void CAknIndicatorPopupContent::SetContentVisible( TBool aVisible )
+    {
+    if ( aVisible )
+        {
+        SizeChanged(); // also includes UpdateFeedbackAreas()
+        }
+    if ( iClock )
+        {
+        // The clock timer needs to be running only when the
+        // popup is visible.
+        if ( aVisible )
+            {
+            // Error ignored, if this leaves then the clock
+            // is not updated if time changes while popup is visible.
+            iClock->StartTimer();
+            }
+        else
+            {
+            iClock->StopTimer();
+            }
+        }
+
+
+    if ( !aVisible )
+        {
+        // Remove this popup from the global popup priority stack.
+        AknGlobalPopupPriorityController::RemovePopupPriority( *this );
+
+        // Clear the state flags.
+        iFlags &= ( ~EAknIndicatorPopupContentButton1Down );
+        iFlags &= ( ~EAknIndicatorPopupContentClockBeingLaunched );
+        }
+    else
+        {
+        // Add this popup from the global popup priority stack so
+        // that it can receive key events.
+        // Note that the popup priority is not set, so it has
+        // priority the default priority, which is 0.
+        AknGlobalPopupPriorityController::ShowPopup( *this, ETrue );
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// CAknIndicatorPopupContent::SetBatteryStateL
+// ---------------------------------------------------------------------------
+//
+void CAknIndicatorPopupContent::SetBatteryStateL( TInt aState )
+    {
+    if ( iBattery )
+        {
+        iBattery->SetBatteryIconL( aState );
+        }
+    }
+// ---------------------------------------------------------------------------
+// CAknIndicatorPopupContent::SetSignalStateL
+// ---------------------------------------------------------------------------
+//
+void CAknIndicatorPopupContent::SetSignalStateL( TInt aState )
+    {
+    TInt newState( aState );
+    
+    if ( iSignal )
+        {
+        if ( newState == KAknSignalOffLineMode )
+            {
+            // Set offline state icon to the signal area. 
+            iSignal->SetOffLine( ETrue );
+            }
+        else if ( newState == KAknSignalOffLineMode - 1 )
+            {
+            // This aState parameter is used to inform about connection
+            // state change from offline mode. Signal icon is set not
+            // to be in offline state and the correct signal state is
+            // used from iSignalState.
+            iSignal->SetOffLine( EFalse );
+            newState = iSignalState;
+            }
+        iSignal->LoadIconL( newState, EAknsCIQsnIconColorsCG5 );
+        }
+
+    // Ensure that the new value is valid, offline mode state is
+    // not stored as a signal state.
+    if ( newState >= 0 &&
+         newState <= EAknSignalHsdpaIndicatorMultipdp ) // last signal state
+        {
+        iSignalState = newState;
+        }
+    }
+// -----------------------------------------------------------------------------
+// CAknIndicatorPopupContent::HandlePluginUpdateL
+// -----------------------------------------------------------------------------
+//
+void CAknIndicatorPopupContent::HandlePluginUpdateL( TInt aUid )
+    {
+    TInt  itemCount( iItems.Count() );
+    for ( TInt i = 0; i < itemCount; i++ )
+        {
+        if ( iItems[i]->iUid == aUid &&
+             iItems[i]->iPlugin ) // Can update only if we have a
+            {                     // pointer to the plugin.
+            // Update text
+            TInt textType;
+            HBufC* text = iItems[i]->iPlugin->TextL( aUid, textType );
+            if ( text )
+                {
+                CleanupStack::PushL( text );
+                iItems[i]->UpdateTextL( *text, textType );
+                CleanupStack::PopAndDestroy( text );
+                }
+
+            // Update icon
+            const CGulIcon* icon = NULL;
+            TRAPD( err, icon = iItems[i]->iPlugin->IconL( aUid ) );
+            if ( !err && icon )
+                {
+                iItems[i]->UpdateIndicatorIconL( icon );
+                }
+
+            break;
+            }
+        }
+
+    DrawDeferred();
+    }
+
+
+// -----------------------------------------------------------------------------
+// CAknIndicatorPopupContent::UpdateAllIndicatorsL
+// -----------------------------------------------------------------------------
+//
+void CAknIndicatorPopupContent::UpdateAllIndicatorsL()
+    {
+    CAknIndicatorPlugin* plugin = NULL;
+    TInt  itemCount( iItems.Count() );
+
+    for ( TInt i = 0; i < itemCount; i++ )
+        {
+        plugin = iItems[i]->iPlugin;
+
+        if ( plugin ) // Can update only if we have a
+            {         // pointer to the plugin.
+            TInt uid( iItems[i]->iUid );
+
+            // Update text
+            TInt textType;
+            HBufC* text = plugin->TextL( uid, textType );
+            if ( text )
+                {
+                CleanupStack::PushL( text );
+                iItems[i]->UpdateTextL( *text, textType );
+                CleanupStack::PopAndDestroy( text );
+                }
+
+            // Update icon
+            const CGulIcon* icon = NULL;
+            TRAPD( err, icon = plugin->IconL( uid ) );
+            if ( !err && icon )
+                {
+                iItems[i]->UpdateIndicatorIconL( icon );
+                }
+            }
+        }
+    }
+
+
+// -----------------------------------------------------------------------------
+// Default constructor.
+// -----------------------------------------------------------------------------
+//
+CAknIndicatorPopupContent::CAknIndicatorPopupContent()
+    : iItems( KItemArrayGranularity )
+    {
+    }
+
+
+// -----------------------------------------------------------------------------
+// CAknIndicatorPopupContent::ConstructL
+// -----------------------------------------------------------------------------
+//
+void CAknIndicatorPopupContent::ConstructL()
+    {
+    iClock = CAknDigitalClock::NewL( this );
+    TAknTextLineLayout clockLayout(
+        AknLayoutScalable_Avkon::uniindi_top_pane_t1( 1 ).LayoutLine() );
+
+    // Ensure that the left and right values of the clock text layout
+    // are zero, currently the whole top area is set as the parent
+    // for this layout, so it's narrowed by reducting the
+    // signal pane area.
+    clockLayout.il = 0;
+    clockLayout.ir = 0;
+    iClock->SetTimeLayout( clockLayout );
+    TRgb textColor;
+
+    MAknsSkinInstance* skin = AknsUtils::SkinInstance();
+
+    AknsUtils::GetCachedColor( skin,
+                               textColor,
+                               KAknsIIDQsnTextColors,
+                               EAknsCIQsnTextColorsCG55 );
+    iClock->SetColor( textColor );
+
+    iBattery = CAknBatteryIcon::NewL();
+    iBattery->SetContainerWindowL( *this );
+    iSignal = CAknSignalIcon::NewL();
+    iSignal->SetContainerWindowL( *this );
+
+    // Create default signal icon.
+    iSignal->LoadIconL( 0, EAknsCIQsnIconColorsCG5 );
+
+    // Set this to draw the icon also in offline mode.
+    iSignal->SetOffLineIconDraw( ETrue );
+    TRAPD( err, iBatteryPlugin = CAknIndicatorPlugin::NewL(
+        TUid::Uid( KImplUIDBatteryIndicatorPlugin ) ) );
+    if ( err == KErrNone )
+        {
+        iBatteryPlugin->SetPluginObserver( this );
+        }
+    TRAPD( err1, iSignalPlugin  = CAknIndicatorPlugin::NewL(
+        TUid::Uid( KImplUIDSignalIndicatorPlugin ) ) );
+    if ( err1 == KErrNone )
+        {
+        iSignalPlugin->SetPluginObserver( this );
+        }
+
+    iFeedback = MTouchFeedback::Instance();
+
+    // Load the separator line and signal icon graphics.
+    LoadIconsL();
+    
+    iEnablePressedDownState = EFalse;
+    iPreviousPressedDownItem = NULL;
+    }
+
+
+// -----------------------------------------------------------------------------
+// CAknIndicatorPopupContent::PrioritizeIndicatorsL
+// -----------------------------------------------------------------------------
+//
+void CAknIndicatorPopupContent::PrioritizeIndicatorsL()
+    {
+    TInt count = iItems.Count();
+    if ( count < 2 )
+        {
+        return;
+        }
+
+    CAknIndicatorPopupItem* temp;
+    for ( TInt ii = 1; ii < count; ii++ )
+        {
+        temp = iItems[ii];
+        TInt tempPriority = temp->iPriority;
+
+        if ( tempPriority >= 0 )
+            {
+            for ( TInt jj = 0; jj <= ii; jj++ )
+                {
+                TInt indicatorPriority = iItems[jj]->iPriority;
+
+                if ( tempPriority < indicatorPriority )
+                    {
+                    iItems.Remove( ii );
+                    iItems.InsertL( temp, jj );
+                    break;
+                    }
+                else if ( jj == ( ii - 1 ) )
+                    {
+                    break;
+                    }
+                }
+            }
+        }
+    }
+
+
+// -----------------------------------------------------------------------------
+// CAknIndicatorPopupContent::UpdateFeedbackAreas
+//
+// Digital clock takes care of its own feedback, but we have to either
+// enable or block feedback for signal indicator, according to
+// wheather it has associated plug-in or not (if it has plug-in, then
+// something happens when it is tapped and feedback should be produced).
+//
+// In addition we have to set feedback to every item, which acts as a link.
+// -----------------------------------------------------------------------------
+//
+void CAknIndicatorPopupContent::UpdateFeedbackAreas()
+    {
+    if ( iFeedback )
+        {
+        // First remove all old feedback areas
+        iFeedback->RemoveFeedbackForControl( this );
+        if ( iBatteryPlugin )
+            {
+            // Set battery indicator's feedback area    
+            CFeedbackSpec* fbSpec = CFeedbackSpec::New();
+            if ( fbSpec )
+                {
+                fbSpec->AddFeedback( ETouchEventStylusDown,
+                                     ETouchFeedbackSensitiveButton );
+                fbSpec->AddFeedback( ETouchEventStylusUp,
+                                     ETouchFeedbackSensitiveButton,
+                                     ETouchFeedbackVibra );
+
+                iFeedback->SetFeedbackArea( this, 
+                                            KBatteryAreaIndex, 
+                                            iBatteryArea, 
+                                            fbSpec );
+                delete fbSpec;                                
+                }
+            }
+            
+        if ( iSignalPlugin )
+            {
+            // Set signal indicator's feedback area
+            CFeedbackSpec* fbSpec = CFeedbackSpec::New();
+            if ( fbSpec )
+                {
+                fbSpec->AddFeedback( ETouchEventStylusDown,
+                                     ETouchFeedbackSensitiveButton );
+                fbSpec->AddFeedback( ETouchEventStylusUp,
+                                     ETouchFeedbackSensitiveButton,
+                                     ETouchFeedbackVibra );
+
+                iFeedback->SetFeedbackArea( this, 
+                                            KSignalAreaIndex, 
+                                            iSignalArea, 
+                                            fbSpec );
+                delete fbSpec;                                
+                }
+            }
+
+        // Go through the items, and set feedback areas for those which act
+        // as link (i.e. have associated plugin)
+        TInt itemCount( iItems.Count() );
+
+        for ( TInt i = 0; i < itemCount; i++ )
+            {
+            if ( iItems[i]->iPlugin &&
+                 iItems[i]->iTextType ==
+                     CAknIndicatorPlugin::EAknIndicatorPluginLinkText &&
+                 iItems[i]->iRect != TRect( 0, 0, 0, 0 ) )
+                {
+                CFeedbackSpec* fbSpec = CFeedbackSpec::New();
+                if ( fbSpec )
+                    {
+                    fbSpec->AddFeedback( ETouchEventStylusDown,
+                                         ETouchFeedbackSensitiveButton );
+
+                    iFeedback->SetFeedbackArea( this,
+                                                KSignalAreaIndex + i + 1,
+                                                iItems[i]->iRect,
+                                                fbSpec );
+                    delete fbSpec;                                
+                    }
+                }
+            }
+        }
+    }
+
+
+// -----------------------------------------------------------------------------
+// CAknIndicatorPopupContent::LoadIconsL
+// -----------------------------------------------------------------------------
+//
+void CAknIndicatorPopupContent::LoadIconsL()
+    {
+    TRect rect( Rect() );
+
+    delete iSeparatorIcon;
+    iSeparatorIcon = NULL;
+
+    CFbsBitmap* bitmap = NULL;
+    CFbsBitmap* mask   = NULL;
+
+    AknsUtils::CreateColorIconL( AknsUtils::SkinInstance(),
+                                 KAknsIIDQgnGrafLineVerticalFade,
+                                 KAknsIIDQsnLineColors,
+                                 EAknsCIQsnLineColorsCG3,
+                                 bitmap,
+                                 mask,
+                                 KNullDesC,
+                                 KErrNotFound,
+                                 KErrNotFound,
+                                 KRgbGray );
+
+    iSeparatorIcon = CGulIcon::NewL( bitmap, mask );
+
+    TAknLayoutRect layoutRect;
+    layoutRect.LayoutRect(
+        rect,
+        AknLayoutScalable_Avkon::uniindi_top_pane() );
+
+    layoutRect.LayoutRect(
+        layoutRect.Rect(),
+        AknLayoutScalable_Avkon::uniindi_top_pane_g3( 1 ) );
+
+    AknIconUtils::SetSize( iSeparatorIcon->Bitmap(),
+                           layoutRect.Rect().Size(),
+                           EAspectRatioNotPreserved );
+
+    //
+    // Create a custom signal icon for connectivity manager link.
+    //
+
+    CFbsBitmap* signalBitmap = NULL;
+    CFbsBitmap* signalMask   = NULL;
+
+    AknsUtils::CreateColorIconL( AknsUtils::SkinInstance(),
+                                 KAknsIIDQgnPropLinkConnectionManager,
+                                 KAknsIIDQsnIconColors,
+                                 EAknsCIQsnIconColorsCG5,
+                                 signalBitmap,
+                                 signalMask,
+                                 AknIconUtils::AvkonIconFileName(),
+                                 EMbmAvkonQgn_prop_link_connection_manager,
+                                 EMbmAvkonQgn_prop_link_connection_manager_mask,
+                                 KRgbGray );
+
+    // Ownership is transferred.
+    iSignal->SetSignalIcon( signalBitmap );
+    iSignal->SetSignalIconMask( signalMask );
+    }
+
+// -----------------------------------------------------------------------------
+// CAknIndicatorPopupContent::TappedItem
+// -----------------------------------------------------------------------------
+//
+CAknIndicatorPopupItem* 
+CAknIndicatorPopupContent::TappedItem(const TPoint& aPoint) const
+    {    
+    for ( TInt ii = 0; ii < iItems.Count(); ii++ )
+        {
+        CAknIndicatorPopupItem* item = iItems[ii];                    
+        if ( item->iRect.Contains( aPoint ) && item->iPlugin
+             && item->iTextType ==
+             CAknIndicatorPlugin::EAknIndicatorPluginLinkText )
+            {
+            return item;
+            }                        
+        }
+    return NULL;
+    }
+
+// -----------------------------------------------------------------------------
+// From class CCoeControl
+// CAknIndicatorPopupContent::SizeChanged
+// -----------------------------------------------------------------------------
+//
+void CAknIndicatorPopupContent::SizeChanged()
+    {
+    TRect rect( Rect() );
+
+    // Popup window top area
+    TAknLayoutRect layoutRect;
+    layoutRect.LayoutRect( rect,
+                           AknLayoutScalable_Avkon::uniindi_top_pane() );
+    TRect topRect( layoutRect.Rect() );
+
+    // Signal pane area
+    layoutRect.LayoutRect( topRect,
+                           AknLayoutScalable_Avkon::uniindi_top_pane_g1() );
+    TRect signalRect( layoutRect.Rect() );
+
+    // Battery pane area
+    layoutRect.LayoutRect( topRect,
+                           AknLayoutScalable_Avkon::uniindi_top_pane_g2() );
+    TRect batteryRect( layoutRect.Rect() );
+    
+    // Clock pane area
+    layoutRect.LayoutRect( topRect,
+                           AknLayoutScalable_Avkon::aid_area_touch_clock() );
+    TRect clockRect( layoutRect.Rect() );
+
+    // Separator line size
+    layoutRect.LayoutRect(
+        topRect,
+        AknLayoutScalable_Avkon::uniindi_top_pane_g3() );
+    TRect separatorRect = layoutRect.Rect();
+    TSize separatorSize( layoutRect.Rect().Size() );
+
+    TBool layoutMirrored( AknLayoutUtils::LayoutMirrored() );
+
+    iClock->SetRect( clockRect );
+    iBattery->SetRect( batteryRect );
+    iSignal->SetRect( signalRect );
+
+    // Make the touch responsive areas of signal pane
+    // slightly larger by not taking into account the margins from
+    // top and sides.
+    iBatteryArea = batteryRect;
+    iSignalArea  = signalRect;
+
+    if ( layoutMirrored )
+        {
+        iBatteryArea.iTl    = topRect.iTl;
+        iBatteryArea.iBr.iY = topRect.iBr.iY;
+        iSignalArea.iBr     = topRect.iBr;
+        iSignalArea.iTl.iY  = topRect.iTl.iY;
+        }
+    else
+        {
+        iBatteryArea.iBr    = topRect.iBr;
+        iBatteryArea.iTl.iY = topRect.iTl.iY;
+        iBatteryArea.iTl.iX = clockRect.iBr.iX;
+        iSignalArea.iTl     = topRect.iTl;
+        iSignalArea.iBr.iY  = topRect.iBr.iY;
+        }
+
+    // Calculate permanent component press down effect rect
+    iSignalPressedDownArea = iSignalArea;
+    iClockPressedDownArea = clockRect;
+        
+    // Indicator area
+    layoutRect.LayoutRect( rect,
+                           AknLayoutScalable_Avkon::list_uniindi_pane() );
+    TRect listRect( layoutRect.Rect() );
+
+    TRAP_IGNORE( PrioritizeIndicatorsL() );
+
+    TAknLayoutScalableParameterLimits limits(
+        AknLayoutScalable_Avkon::list_single_uniindi_pane_ParamLimits() );
+    TInt maxNumberOfIndicatorsShown = limits.LastRow();
+
+    TInt itemCount( iItems.Count() );
+
+    for ( TInt i = 0; i < itemCount; i++ )
+        {
+        if ( i <= maxNumberOfIndicatorsShown )
+            {
+            layoutRect.LayoutRect(
+                listRect,
+                AknLayoutScalable_Avkon::list_single_uniindi_pane( 0, 0, i ) );
+            iItems[i]->SetRect( layoutRect.Rect() );
+            }
+        else
+            {
+            iItems[i]->SetRect( TRect( 0, 0, 0, 0 ) );
+            }
+        }
+
+    UpdateFeedbackAreas();
+
+    AknIconUtils::SetSize( iSeparatorIcon->Bitmap(),
+                           separatorSize,
+                           EAspectRatioNotPreserved );
+
+    DrawDeferred();
+    }
+
+
+// -----------------------------------------------------------------------------
+// From class CCoeControl
+// CAknIndicatorPopupContent::Draw
+// -----------------------------------------------------------------------------
+//
+void CAknIndicatorPopupContent::Draw( const TRect& aRect ) const
+    {
+    if ( AknLayoutUtils::PenEnabled() )
+        {
+        CWindowGc& gc = SystemGc();
+
+        MAknsSkinInstance* skin = AknsUtils::SkinInstance();
+
+        TRect rect( Rect() );
+
+        TAknLayoutRect layoutRect;
+        layoutRect.LayoutRect(
+            rect,
+            AknLayoutScalable_Avkon::uniindi_top_pane() );
+        TRect topRect( layoutRect.Rect() );
+
+        layoutRect.LayoutRect(
+            topRect,
+            AknLayoutScalable_Avkon::bg_uniindi_top_pane( 1 ) );
+        TRect topCenterRect( layoutRect.Rect() );
+        layoutRect.LayoutRect(
+            topRect,
+            AknLayoutScalable_Avkon::uniindi_top_pane_g3() );
+        TRect leftSeparatorRect( layoutRect.Rect() );
+        
+        layoutRect.LayoutRect(
+            topRect,
+            AknLayoutScalable_Avkon::uniindi_top_pane_g3( 1 ) );
+        TRect separatorRect( layoutRect.Rect() );
+       
+        layoutRect.LayoutRect(
+            topRect,
+            AknLayoutScalable_Avkon::uniindi_top_pane_g4() );
+        TRect rightSeparatorRect( layoutRect.Rect() );
+
+        // Draw the button frame to the permanent items area.
+        AknsDrawUtils::DrawFrame( skin,
+                                  gc,
+                                  topRect,
+                                  topCenterRect,
+                                  KAknsIIDQsnFrPopupHeading,
+                                  KAknsIIDQsnFrPopupHeadingCenter );
+        if ( iEnablePressedDownState )
+            {  
+            AknsDrawUtils::DrawFrame( skin,
+                                      gc,
+                                      iPressedDownRect,
+                                      iPressedDownRect,
+                                      KAknsIIDQsnFrListPressed,
+                                      KAknsIIDQsnFrListCenterPressed);
+            }
+        CFbsBitmap* bitmap = iSeparatorIcon->Bitmap();
+        CFbsBitmap* mask   = iSeparatorIcon->Mask();
+
+        // Draw the separator line on the top pane.
+        gc.BitBltMasked( leftSeparatorRect.iTl,
+                         bitmap,
+                         leftSeparatorRect.Size(),
+                         mask,
+                         ETrue );
+                          
+        gc.BitBltMasked( rightSeparatorRect.iTl,
+                         bitmap,
+                         rightSeparatorRect.Size(),
+                         mask,
+                         ETrue );
+
+        // Draw the indicator items.
+        for ( TInt i = 0; i < iItems.Count(); i++ )
+            {
+            if ( aRect.Intersects( iItems[i]->iRect ) )
+                {
+                iItems[i]->DrawItem( gc );
+                }
+            }
+        }
+    }