uifw/AvKon/src/akncontext.cpp
changeset 0 2f259fa3e83a
child 38 c52421ed5f07
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/uifw/AvKon/src/akncontext.cpp	Tue Feb 02 01:00:49 2010 +0200
@@ -0,0 +1,652 @@
+/*
+* Copyright (c) 2002 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:
+*
+*/
+
+
+// INCLUDE FILES
+#include <eikfutil.h>
+#include <eikappui.h>
+#include <eikapp.h>
+
+#include <apgcli.h>
+#include <apgicnfl.h>
+#include <apgwgnam.h> 
+
+#include <gulicon.h>
+#include <gulutil.h>
+#include <eikimage.h>
+
+#include <AknIconUtils.h>
+
+#include <AknsUtils.h>
+#include <AknsDrawUtils.h>
+
+#include <AknTasHook.h>
+#include "AknPanic.h"
+#include "AknUtils.h"
+#include "aknconsts.h"
+#include "akncontext.h"
+
+#include <avkon.mbg>
+#include <eikspane.h>
+
+#include "aknnavi.h"
+#include "AknBitmapMirrorUtils.h"
+#include "AknNaviConstants.h"
+#include "aknappui.h"
+#include <AknDef.h>
+
+
+NONSHARABLE_CLASS(CAknContextPaneExtension): public CBase
+	{
+public:
+	CAknContextPaneExtension();
+	~CAknContextPaneExtension();
+public:
+    CEikImage*  iContextImage;
+    CEikImage*  iDefaultContextImage;
+    TInt        iCurrentColorScheme;
+    };
+
+CAknContextPaneExtension::CAknContextPaneExtension()
+	{
+	}
+
+CAknContextPaneExtension::~CAknContextPaneExtension()
+	{
+	}
+
+EXPORT_C CAknContextPane::CAknContextPane()
+    {
+    AKNTASHOOK_ADD( this, "CAknContextPane" );
+    }
+
+EXPORT_C CAknContextPane::~CAknContextPane()
+    {
+    AKNTASHOOK_REMOVE();
+    AknsUtils::DeregisterControlPosition( this );
+	if (iExtension)
+		{
+		AknsUtils::DeregisterControlPosition( iExtension->iContextImage );
+		AknsUtils::DeregisterControlPosition( iExtension->iDefaultContextImage );
+		delete iExtension->iContextImage;
+		delete iExtension->iDefaultContextImage;
+		delete iExtension;
+		}
+    }
+
+EXPORT_C void CAknContextPane::ConstructL()
+    {
+    CommonConstructL();
+    TRAP_IGNORE(SetPictureToDefaultL()); // Trapped because of Java midlet issues
+    }
+
+
+EXPORT_C void CAknContextPane::ConstructFromResourceL(TResourceReader& aReader)
+    {
+    CommonConstructL();
+    ReadFromResourceFileL(aReader);
+    }
+
+EXPORT_C void CAknContextPane::SetPicture(const CFbsBitmap* aBitmap, const CFbsBitmap* aMaskBitmap)
+    {
+    TBool bitmapChanged = EFalse;
+    if (iExtension->iContextImage)
+        {
+        bitmapChanged = ETrue;
+        iExtension->iContextImage->SetPictureOwnedExternally(EFalse);
+        iExtension->iContextImage->SetPicture(aBitmap, aMaskBitmap);
+        }
+    else
+        {
+        // Try to create new iContextImage object.
+        TRAPD( error, InitL() );
+        if ( !error )
+            {
+            bitmapChanged = ETrue;
+            iExtension->iContextImage->SetPictureOwnedExternally(EFalse);
+            iExtension->iContextImage->SetPicture(aBitmap, aMaskBitmap);
+            }
+        else
+            {
+            // Ownership taken - delete if there is not memory to create new iContextImage.
+            delete aBitmap;
+            delete aMaskBitmap;
+            }
+        }
+
+    if ( bitmapChanged )
+        {
+        SizeChanged();	
+        DrawNow();
+        }
+    }
+
+EXPORT_C void CAknContextPane::SetPicture(CEikImage* aImage)
+    {
+    __ASSERT_ALWAYS(aImage && aImage->Bitmap(), Panic(EAknPanicNullPointer));
+
+    delete iExtension->iContextImage;   
+    iExtension->iContextImage = aImage;
+	if (!iExtension->iContextImage->DrawableWindow())
+		{
+		TRAP_IGNORE(iExtension->iContextImage->SetContainerWindowL(*this));
+		}
+	__ASSERT_DEBUG(iExtension->iContextImage->DrawableWindow(), Panic(EAknPanicNullPointer));
+
+    iExtension->iContextImage->SetPictureOwnedExternally(EFalse);
+
+    SizeChanged();
+    DrawNow();
+    }
+
+EXPORT_C void CAknContextPane::SetPictureFromFileL(const TDesC& aFileName, TInt aMainId, TInt aMaskId)
+    {
+    delete iExtension->iContextImage;
+    iExtension->iContextImage = NULL;
+    
+    InitL();
+    iExtension->iContextImage->CreatePictureFromFileL(aFileName, aMainId, aMaskId);
+    
+    SizeChanged();
+    DrawNow();
+    }
+
+
+EXPORT_C void CAknContextPane::SetFromResourceL(TResourceReader& aReader)
+    {
+    ReadFromResourceFileL(aReader);
+    }
+
+
+void FindRootApplication(TInt aCount, TInt& aWgId, RArray<RWsSession::TWindowGroupChainInfo>* aWgIds )
+    {
+    // Go through all window group IDs looking for the current one
+    for (TInt i=0;i<aCount;i++)
+        {
+        RWsSession::TWindowGroupChainInfo wgId=(*aWgIds)[i];
+        
+        if ( wgId.iId == aWgId ) // found my wg
+        	{
+            if (wgId.iParentId <= 0) // I'm standalone application
+                break;
+            else
+                {
+                aWgId = wgId.iParentId;
+                FindRootApplication(aCount, aWgId, aWgIds);
+                }
+        	}
+        }
+ 
+    }
+
+
+EXPORT_C void CAknContextPane::SetPictureToDefaultL()
+    {
+    if (iExtension->iDefaultContextImage)
+        {
+        CFbsBitmap* bitmap = new (ELeave) CFbsBitmap();
+        CleanupStack::PushL(bitmap);                
+        CFbsBitmap* mask = new (ELeave) CFbsBitmap();                
+        
+        if ( iExtension->iDefaultContextImage->Bitmap() )
+            {
+            bitmap->Duplicate(iExtension->iDefaultContextImage->Bitmap()->Handle());
+            }
+        if ( iExtension->iDefaultContextImage->Mask() )
+            {
+            mask->Duplicate(iExtension->iDefaultContextImage->Mask()->Handle());
+            }
+        SetPicture(bitmap, mask); 
+        CleanupStack::Pop(); // bitmap
+        return;
+        }
+
+    CFbsBitmap* bitmap = NULL;
+    CFbsBitmap* mask = NULL;
+
+    // statuspane
+    TAknLayoutRect statuspane;
+    statuspane.LayoutRect(iAvkonAppUi->ApplicationRect(), AknLayout::status_pane(iAvkonAppUi->ApplicationRect(),0));
+       
+    // context pane
+    TAknWindowLineLayout contextPaneLayout = AknLayout::context_pane(statuspane.Rect(), 0);    
+    TAknLayoutRect contextPaneLayoutRect;
+    contextPaneLayoutRect.LayoutRect(statuspane.Rect(), contextPaneLayout);
+    TRect contextPaneRect = contextPaneLayoutRect.Rect(); 
+
+    // context pane elements    
+    TAknWindowLineLayout contextPaneElements = 
+        AknLayout::Context_pane_elements_Line_1();    
+    TAknLayoutRect rect;
+    rect.LayoutRect(contextPaneRect, contextPaneElements);
+
+    // -- Wg chaining support ---
+    RWsSession& ws = iEikonEnv->WsSession();    
+
+    TInt wgCount=ws.NumWindowGroups();
+	TInt wgId = iEikonEnv->RootWin().Identifier();
+    
+    RArray<RWsSession::TWindowGroupChainInfo>* wgIds=new(ELeave) RArray<RWsSession::TWindowGroupChainInfo>(wgCount);
+    CleanupStack::PushL(wgIds);
+    CleanupClosePushL(*wgIds);
+
+    User::LeaveIfError(ws.WindowGroupList(wgIds));
+    
+    FindRootApplication(wgCount, wgId, wgIds );
+    
+	CleanupStack::PopAndDestroy(2);  // wgids
+	
+    CApaWindowGroupName* windowName = CApaWindowGroupName::NewLC(ws, wgId);
+    TUid appUid  = windowName->AppUid();
+	CleanupStack::PopAndDestroy();  //windowName
+
+    // ------
+
+    AknsUtils::CreateAppIconLC( AknsUtils::SkinInstance(), 
+        appUid, EAknsAppIconTypeContext,
+        bitmap, mask );
+    
+    SetPictureSize( bitmap, 
+        rect.Rect().Size() ) ;
+
+    iExtension->iDefaultContextImage = new (ELeave) CEikImage;
+    CFbsBitmap* defaultBitmap = new (ELeave) CFbsBitmap();
+    CleanupStack::PushL(defaultBitmap);                
+    CFbsBitmap* defaultMask = new (ELeave) CFbsBitmap();                
+    defaultBitmap->Duplicate(bitmap->Handle());
+    defaultMask->Duplicate(mask->Handle());
+    iExtension->iDefaultContextImage->SetPicture(defaultBitmap, defaultMask);
+    iExtension->iDefaultContextImage->SetPictureOwnedExternally(EFalse);
+
+    // ownership of the defaultBitmap moved to iDefaultContextImage.
+    CleanupStack::Pop( 3 ); // defaultBitmap,  mask, bitmap
+    SetPicture( bitmap, mask );    
+    }
+
+EXPORT_C const CEikImage& CAknContextPane::Picture() const
+    {
+    return *(iExtension->iContextImage);
+    }
+
+EXPORT_C CEikImage* CAknContextPane::SwapPicture(CEikImage* aNewImage)
+    {
+    CEikImage* previousImage = iExtension->iContextImage;
+    iExtension->iContextImage = aNewImage;
+    if (iExtension->iContextImage)
+        {
+        if (!iExtension->iContextImage->DrawableWindow())
+            {
+            TRAP_IGNORE( iExtension->iContextImage->SetContainerWindowL(*this) );
+            }
+
+        __ASSERT_DEBUG(iExtension->iContextImage->DrawableWindow(), Panic(EAknPanicNullPointer));
+
+        iExtension->iContextImage->SetPictureOwnedExternally(EFalse);
+        }
+    SizeChanged();
+    DrawNow();
+    
+    return previousImage;
+    }
+
+
+EXPORT_C void CAknContextPane::SizeChanged()
+    {
+    if (Rect() != TRect(0,0,0,0)) // Fix for Parent getting parent relative data. 
+        {
+        if (iExtension->iContextImage && iExtension->iContextImage->Bitmap()) 
+            {
+            TAknLayoutRect layoutRect;
+            layoutRect.LayoutRect(Rect(), AknLayout::Context_pane_elements_Line_1());
+
+            TBool sameIcons = EFalse;
+
+            if ( iExtension->iDefaultContextImage &&
+                 iExtension->iDefaultContextImage->Bitmap() &&
+                 iExtension->iDefaultContextImage->Bitmap()->Handle() ==
+                 iExtension->iContextImage->Bitmap()->Handle() )
+                {
+                sameIcons = ETrue;
+                }
+        
+            // This potentially changes bitmap handles.
+            SetPictureSize( const_cast<CFbsBitmap*>( iExtension->iContextImage->Bitmap() ),
+                layoutRect.Rect().Size());
+
+            if ( sameIcons )
+                {
+                // Must duplicate again after SetSize.
+                CFbsBitmap* bitmap = const_cast<CFbsBitmap*>(
+                    iExtension->iDefaultContextImage->Bitmap() );
+                CFbsBitmap* mask = const_cast<CFbsBitmap*>(
+                    iExtension->iDefaultContextImage->Mask() );
+
+                if ( bitmap )
+                    {
+                    // ignore error
+                    bitmap->Duplicate( iExtension->iContextImage->Bitmap()->Handle() );
+                    }
+
+                if ( mask )
+                    {
+                    // ignore error
+                    mask->Duplicate( iExtension->iContextImage->Mask()->Handle() );
+                    }
+                }
+
+            TSize bmpSize=iExtension->iContextImage->Bitmap()->SizeInPixels();
+            TGulAlignment iAlignment;
+            iAlignment.SetHAlignment(EHCenter);
+            iAlignment.SetVAlignment(EVCenter);
+            iExtension->iContextImage->SetRect(iAlignment.InnerRect(Rect(),bmpSize));
+            AknsUtils::RegisterControlPosition( iExtension->iContextImage );
+            }
+        AknsUtils::RegisterControlPosition( this );
+        }
+    }
+
+
+EXPORT_C void CAknContextPane::HandleResourceChange( TInt aType ) 
+    {
+    if ( aType == KEikColorResourceChange || aType==KEikDynamicLayoutVariantSwitch )
+        {
+        DrawDeferred();
+        }
+    else if( aType == KAknsMessageSkinChange )
+        {
+        if( iExtension->iDefaultContextImage && iExtension->iContextImage )
+            {
+            const CFbsBitmap* defBmp = iExtension->iDefaultContextImage->Bitmap();
+            const CFbsBitmap* bmp = iExtension->iContextImage->Bitmap();
+            if( defBmp && bmp )
+                {
+                // Update icon only if the default context image is used.
+                // Otherwise, the application is responsible of updating the
+                // image upon skin change (since it has set a non-default image).
+                if( defBmp->Handle() == bmp->Handle() )
+                    {
+                    delete iExtension->iDefaultContextImage;
+                    iExtension->iDefaultContextImage = NULL;
+                    TRAP_IGNORE(SetPictureToDefaultL()); // Ignore error
+                    }
+                }
+            }
+        }
+    }
+
+
+EXPORT_C TInt CAknContextPane::CountComponentControls() const
+    {
+    if (iExtension->iContextImage)
+        {
+        return 1;
+        }
+    return 0;
+    }
+
+
+EXPORT_C CCoeControl* CAknContextPane::ComponentControl(TInt /*aIndex*/) const
+    {
+    return (iExtension->iContextImage);
+    }
+
+
+EXPORT_C void CAknContextPane::Draw(const TRect& /*aRect*/) const
+    {
+    CWindowGc& gc=SystemGc();
+
+    // screen
+    TRect screenRect = iAvkonAppUi->ApplicationRect();
+    
+    //TAknWindowLineLayout screenLayout = AknLayout::screen();
+    //TRect screenRect = screenLayout.Rect();
+
+
+    // app window
+    TAknWindowLineLayout applicationWindowLayout =
+        AknLayout::application_window(screenRect);
+    
+    TAknLayoutRect applicationWindowLayoutRect;
+    applicationWindowLayoutRect.LayoutRect(screenRect, applicationWindowLayout);
+    TRect applicationWindowRect = applicationWindowLayoutRect.Rect(); 
+
+    // statuspane
+    TAknWindowLineLayout statusPaneLayout = 
+        AknLayout::status_pane(applicationWindowRect, 0);
+
+    TAknLayoutRect statusPaneLayoutRect;
+    statusPaneLayoutRect.LayoutRect(applicationWindowRect, statusPaneLayout);
+    TRect statusPaneRect = statusPaneLayoutRect.Rect(); 
+
+    // context pane
+    TAknWindowLineLayout contextPaneLayout = 
+        AknLayout::context_pane(statusPaneRect, 0);
+    
+    TAknLayoutRect contextPaneLayoutRect;
+    contextPaneLayoutRect.LayoutRect(statusPaneRect, contextPaneLayout);
+    TRect contextPaneRect = contextPaneLayoutRect.Rect(); 
+
+    TAknWindowLineLayout naviPaneGraphicsLayout = 
+        AknLayout::Status_pane_elements_Line_1();
+
+    TAknWindowLineLayout naviWipeGraphicsLayout = 
+        AknLayout::Status_pane_elements_Line_2();
+
+    TAknLayoutRect naviPaneGraphicsLayoutRect;
+    naviPaneGraphicsLayoutRect.LayoutRect(statusPaneRect, naviPaneGraphicsLayout);
+    TRect naviPaneGraphicsRect = naviPaneGraphicsLayoutRect.Rect(); 
+
+    TAknLayoutRect naviWipeGraphicsLayoutRect;
+    naviWipeGraphicsLayoutRect.LayoutRect(statusPaneRect, naviWipeGraphicsLayout);
+    TRect naviWipeGraphicsRect = naviWipeGraphicsLayoutRect.Rect(); 
+
+    TRect rect(Rect());
+
+    TRect barRect = contextPaneRect;
+    if (barRect.Intersects(naviPaneGraphicsRect))
+        {
+        barRect.Intersection(naviPaneGraphicsRect);
+        
+        // calculate new origo, relative to context pane.
+        barRect.iTl.iX -= contextPaneRect.iTl.iX;
+        barRect.iTl.iY -= contextPaneRect.iTl.iY;
+        barRect.iBr.iX -= contextPaneRect.iTl.iX;
+        barRect.iBr.iY -= contextPaneRect.iTl.iY;
+        }
+    else
+        {
+        barRect = TRect(0,0,0,0);
+        }
+    
+
+    MAknsSkinInstance* skin = AknsUtils::SkinInstance();
+    MAknsControlContext* cc = AknsDrawUtils::ControlContext(this);
+
+        // Solid or wipe comes from background
+    if( !AknsDrawUtils::Background( skin, cc, this, gc, rect ) )
+        {
+        // Default drawing if skinning is not available
+        gc.Clear(rect); 
+        gc.SetPenStyle(CGraphicsContext::ENullPen);
+        gc.SetBrushStyle(CGraphicsContext::ESolidBrush);
+        gc.SetBrushColor(AKN_LAF_COLOR(KStatusPaneBackgroundGraphicsColorUsual));
+        gc.DrawRect(barRect);
+        }
+    }
+
+
+void CAknContextPane::CommonConstructL()
+    {
+    InitL();
+    // Wipe is never used initally anymore 
+    SetNaviPaneBackgroundType( EAknNaviPaneBackgroundTypeSolid );
+    }
+
+
+TUid CAknContextPane::AppUid()
+    {
+    // Returns application's Uid. 
+    // In embedded applications, root application's Uid is returned.
+    CEikAppUi* root = iEikonEnv->EikAppUi();
+    while (root->ContainerAppUi())
+        {
+        root = root->ContainerAppUi();
+        }
+    
+    CEikApplication* app = root->Application();
+    if (app)
+        {
+        return app->AppDllUid();
+        }
+    return KNullUid;
+    }
+
+
+void CAknContextPane::ReadFromResourceFileL(TResourceReader& aReader)
+    {
+    HBufC* bitmapFile = aReader.ReadHBufCL();	// bmp filename
+    TInt bitmapId = aReader.ReadInt16();	// bmp id
+    TInt maskId = aReader.ReadInt16();	// bmp mask id
+    
+    if ( bitmapFile ) 
+        {
+        CleanupStack::PushL(bitmapFile);
+        if (bitmapId != -1)
+            {
+            SetPictureFromFileL(*bitmapFile, bitmapId, maskId);
+            }
+        CleanupStack::PopAndDestroy();  // bitmapFile
+        }
+    else
+        {
+        TRAP_IGNORE(SetPictureToDefaultL()); // Trapped because of Java midlet issues
+        }
+    }
+
+void CAknContextPane::LoadNaviWipeBitmapL()
+    {    
+    // Naviwipe is no more used (since 3.0)
+    }
+
+void CAknContextPane::SetNaviPaneBackgroundType( TInt /*aType*/ ) 
+    {
+    // Naviwipe is no more used (since 3.0)
+    }
+
+EXPORT_C void CAknContextPane::HandlePointerEventL(const TPointerEvent& aPointerEvent) 
+    { 
+    CAknControl::HandlePointerEventL(aPointerEvent); 
+    }
+
+EXPORT_C void* CAknContextPane::ExtensionInterface( TUid /*aInterface*/ ) 
+    { 
+    return NULL;
+    }
+
+TTypeUid::Ptr CAknContextPane::MopSupplyObject(TTypeUid aId)
+    {
+    if(aId.iUid == CAknContextPane::ETypeId)
+        {
+        // Return self, this code makes it possible to workaround the fact
+        // that statuspane controls cannot be safely casted after
+        // retrieving them using CEikStatusPaneBase::ControlL().
+        // 
+        // So now the caller could do something like this rather safely:
+        //
+        // CEikStatusPaneBase* statusPane = CEikStatusPaneBase::Current();
+        // CAknContextPane* contextPane = NULL;
+        //
+        //if (statusPane && 
+        //    statusPane->PaneCapabilities(TUid::Uid(EEikStatusPaneUidContext)).IsInCurrentLayout())
+        //    {
+        //    CCoeControl* control = statusPane->ControlL(TUid::Uid( EEikStatusPaneUidContext ));
+        //    control->MopGetObject(contextPane);
+        //    }
+        //
+        //if (contextPane)
+        //  {
+        //  // The retrieved control was type of CAknContextPane
+        //  }
+        //else
+        //  {
+        //  // The retrieved control was NOT type of CAknContextPane. 
+        //  // Someone has perhaps swap the control in the statuspane.
+        //  }
+        return aId.MakePtr(this);
+        }
+
+    return CCoeControl::MopSupplyObject(aId);
+    }
+
+void CAknContextPane::InitL()
+    {
+    if (!iExtension)
+        {
+        iExtension = new (ELeave) CAknContextPaneExtension(); 
+        }
+    iExtension->iContextImage = new (ELeave) CEikImage;
+    iExtension->iContextImage->SetContainerWindowL(*this);
+	__ASSERT_DEBUG(iExtension->iContextImage->DrawableWindow(), Panic(EAknPanicNullPointer));
+    iExtension->iContextImage->SetNonFocusing();
+    iExtension->iContextImage->SetAlignment(EHCenterVCenter);
+    }
+
+void CAknContextPane::SetPictureSize(CFbsBitmap* aPicture, TSize aSize)
+    {
+    const TSize KLegacyScreenSize = TSize(176,208);
+    const TSize KLegacyPictureMaxSize = TSize(44,44);
+    
+    if (!aPicture)
+        return;
+
+    TRect screenRect = iAvkonAppUi->ApplicationRect();
+    TSize originalSize = aPicture->SizeInPixels();
+    
+    TBool isLegacyScreenSize = 
+        (screenRect.Height() == KLegacyScreenSize.iHeight && 
+         screenRect.Width() == KLegacyScreenSize.iWidth);
+
+    TBool isBitmap = !AknIconUtils::IsMifIcon(aPicture);        
+
+    TBool isBitmapValidLegacySize = 
+        (originalSize.iHeight <= KLegacyPictureMaxSize.iHeight &&
+         originalSize.iWidth <= KLegacyPictureMaxSize.iWidth);
+
+    // If we are in legacy screen size and the given bitmap is bitmap (not SVG originated)
+    // and its size is ok we don't set the size. This is done because
+    // some legacy app have contextpane icons sizes other than
+    // 44x44 and those look better if left not scaled.
+    if (isLegacyScreenSize && 
+        isBitmap &&
+        isBitmapValidLegacySize)        
+        {
+        return;
+        }
+
+    // Perf optimization: We dont set the size if context pane is not in current status pane layout. When
+    // status pane layout changes, this method will be called again and size is set then.
+    CEikStatusPaneBase* statusPane = CEikStatusPaneBase::Current();
+   	if (statusPane && statusPane->PaneCapabilities(TUid::Uid(EEikStatusPaneUidContext)).IsInCurrentLayout())
+   		{
+		AknIconUtils::SetSize( aPicture, aSize);
+   		}
+    }
+
+
+//  End of File  
+
+