uifw/AvKon/src/aknlongtapanimation.cpp
changeset 0 2f259fa3e83a
child 4 8ca85d2f0db7
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/uifw/AvKon/src/aknlongtapanimation.cpp	Tue Feb 02 01:00:49 2010 +0200
@@ -0,0 +1,419 @@
+/*
+* Copyright (c) 2006 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:  Implementation of long tap animation feature.
+*
+*/
+
+
+#include <AknBitmapAnimation.h>
+#include <AknsConstants.h>
+#include <AknUtils.h>
+#include <apgwgnam.h>
+#include <aknlayoutscalable_avkon.cdl.h>
+
+#include <AknTasHook.h> // for testability hooks
+#include <touchfeedback.h>
+const TInt KStartIntensity = 1;
+const TInt KEndIntensity = 100;
+#include "aknlongtapanimation.h"
+
+enum TInternalFlags
+	{
+	EAnimationStarted			     =	0x0001,
+	EAnimationHasWindowGroup         =  0x0002
+ 	};
+
+const TInt KConversionFromMillisecondsToMicroseconds = 1000;
+
+/**  window group's priority */
+const TInt KAknLongTapWindowPosition = 11; // window group's priority
+
+/** Window`s Position when hiding the animation which  does not own Window Group */
+const TInt KAknAnimationNotOwnWindowGroupWindowPosition = -10; // never at front  
+
+/**  window group's name */
+_LIT( KAknLongTapWgName, "LongTapAnim" ); // window groups name
+
+
+// ============================ EXTENSION CLASS ===============================
+
+NONSHARABLE_CLASS(CAknLongTapAnimationExtension) : public CBase
+    {
+    public:
+        CAknLongTapAnimationExtension();
+        ~CAknLongTapAnimationExtension();
+
+    public: // data 
+        TBool iVisible;
+        TInt iIndex;
+        TInt iFlags;
+		CPeriodic* iTimer;
+    };
+
+CAknLongTapAnimationExtension::CAknLongTapAnimationExtension() : iIndex(-1)
+    {
+    
+    }
+CAknLongTapAnimationExtension::~CAknLongTapAnimationExtension()
+    {
+    
+    }
+
+
+// ======== MEMBER FUNCTIONS ========
+
+// ---------------------------------------------------------------------------
+// Symbian two-phase constructor.
+// ---------------------------------------------------------------------------
+//
+EXPORT_C CAknLongTapAnimation* CAknLongTapAnimation::NewL()
+    {
+    CAknLongTapAnimation* self = CAknLongTapAnimation::NewLC();
+    CleanupStack::Pop( self );
+    return self;
+    }
+
+
+// ---------------------------------------------------------------------------
+// Symbian two-phase constructor.
+// ---------------------------------------------------------------------------
+//
+EXPORT_C CAknLongTapAnimation* CAknLongTapAnimation::NewLC()
+    {
+    CAknLongTapAnimation* self = new( ELeave ) CAknLongTapAnimation;
+    CleanupStack::PushL( self );
+    self->ConstructL( ETrue );
+    AKNTASHOOK_ADDL( self, "CAknLongTapAnimation" );
+    return self;
+    }
+
+// ---------------------------------------------------------------------------
+// CAknLongTapAnimation::NewL()
+// ---------------------------------------------------------------------------
+//
+EXPORT_C CAknLongTapAnimation* CAknLongTapAnimation::NewL( TBool aOwnWindowGroup )
+    {
+    if ( aOwnWindowGroup )
+        {
+        return CAknLongTapAnimation::NewL();
+        }
+    else
+        {
+        CAknLongTapAnimation* self = new( ELeave ) CAknLongTapAnimation;
+        CleanupStack::PushL( self );
+        self->ConstructL( EFalse );
+        CleanupStack::Pop( self );
+        AKNTASHOOK_ADDL( self, "CAknLongTapAnimation" );
+        return self;    
+        }    
+    }
+
+
+// ---------------------------------------------------------------------------
+// Destructor.
+// ---------------------------------------------------------------------------
+//
+CAknLongTapAnimation::~CAknLongTapAnimation()
+    {
+    AKNTASHOOK_REMOVE();
+    if( iExtension->iFlags & EAnimationHasWindowGroup )
+        {
+        iWindowGroup.Close();    
+        }
+	CancelAnimation();
+	
+    if (iExtension)
+        {
+	    delete iExtension->iTimer;
+        }
+    delete iAnim;
+    delete iExtension;
+    }
+    
+
+// ---------------------------------------------------------------------------
+// CAknLongTapAnimation::ShowAnimationL()
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void CAknLongTapAnimation::ShowAnimationL( const TInt aX, 
+                                                    const TInt aY )
+    {
+    TAknLayoutRect layoutRect;
+    TRect rect;
+    AknLayoutUtils::LayoutMetricsRect( 
+            AknLayoutUtils::EApplicationWindow, rect );
+    layoutRect.LayoutRect( rect, AknLayoutScalable_Avkon::misc_graphics() );
+    layoutRect.LayoutRect( layoutRect.Rect(), 
+        AknLayoutScalable_Avkon::misc_graphics() );
+    layoutRect.LayoutRect( layoutRect.Rect(),
+        AknLayoutScalable_Avkon::texts_graphics() );
+    layoutRect.LayoutRect( layoutRect.Rect(),
+        AknLayoutScalable_Avkon::cursor_press_pane() );
+    layoutRect.LayoutRect( layoutRect.Rect(),
+        AknLayoutScalable_Avkon::cursor_press_pane_g1() );
+    
+    SetRect( TRect( TPoint(aX, aY), layoutRect.Rect().Size() ));
+    
+    // Position window so that it will be directly on top of
+    // the location that was clicked.
+    TPoint point( aX - Rect().Width() / 2, aY - Rect().Height() / 2 );
+    Window().SetPosition( point );
+
+    iAnim->SetSize( layoutRect.Rect().Size() );
+    
+    iAnim->SetPosition( Rect().iTl );
+    
+    // finally, make window visible
+    if( iExtension->iFlags & EAnimationHasWindowGroup )
+        {
+        iWindowGroup.SetOrdinalPosition( 0, KAknLongTapWindowPosition );
+        }
+    else
+        {
+        //bring this window to front
+        Window().SetOrdinalPosition( 0 );
+        }    
+    SetVisibility(ETrue);
+    ActivateL();
+
+    MTouchFeedback* feedback = MTouchFeedback::Instance();
+    if ( feedback )
+        {
+        CBitmapAnimClientData* animData = iAnim->BitmapAnimData();	
+		TInt interval = animData->FrameIntervalInMilliSeconds()
+		             * KConversionFromMillisecondsToMicroseconds;
+        TInt frameCount = animData->FrameArray().Count();
+
+        // timeout should be greater than normal animation time 
+        // so that timeout does not interfere into normal operation
+        TInt timeout = interval * (frameCount+1); 
+        feedback->StartFeedback( this, ETouchContinuousSmooth, NULL, KStartIntensity, timeout );
+        }
+	StartAnimation();
+    }
+
+
+// ---------------------------------------------------------
+// CAknLongTapAnimation::HideAnimation
+// ---------------------------------------------------------
+//
+EXPORT_C void CAknLongTapAnimation::HideAnimation()
+    {
+    if( iExtension->iFlags & EAnimationHasWindowGroup )
+        {
+        iWindowGroup.SetOrdinalPosition( 0, ECoeWinPriorityNeverAtFront );
+        }
+    else
+        {
+        //bring this window to back
+        Window().SetOrdinalPosition( KAknAnimationNotOwnWindowGroupWindowPosition );
+            
+        }    
+
+	CancelAnimation();
+    iExtension->iIndex = 0;
+    DrawNow();
+		
+    SetVisibility(EFalse);
+    }
+
+
+// ---------------------------------------------------------------------------
+// CAknLongTapAnimation::CAknLongTapAnimation()
+// ---------------------------------------------------------------------------
+//
+CAknLongTapAnimation::CAknLongTapAnimation()
+    {
+    }
+
+
+// -----------------------------------------------------------------------------
+// CAknLongTapAnimation::ConstructL
+// Symbian 2nd phase constructor can leave.
+// -----------------------------------------------------------------------------
+//
+void CAknLongTapAnimation::ConstructL( TBool aOwnWindowGroup )
+    {
+	if (!iExtension)
+        {
+        iExtension = new( ELeave ) CAknLongTapAnimationExtension;
+        }
+
+    if ( aOwnWindowGroup )
+        {
+        //add flag
+        iExtension->iFlags |= EAnimationHasWindowGroup; 
+        
+        // create a window group for volume popup
+        // needed to prevent apps noticing this window
+        RWsSession& wsSession = iCoeEnv->WsSession();
+        iWindowGroup = RWindowGroup( wsSession );
+        User::LeaveIfError( iWindowGroup.Construct( 
+                                    (TUint32) &iWindowGroup, EFalse ) );
+        iWindowGroup.AutoForeground(EFalse);
+
+        CApaWindowGroupName* name = 
+                CApaWindowGroupName::NewLC( wsSession, (TUint32) &iWindowGroup );
+        name->SetHidden( ETrue );
+        name->SetCaptionL( KAknLongTapWgName );
+        User::LeaveIfError( name->SetWindowGroupName( iWindowGroup ));
+        CleanupStack::PopAndDestroy();  //name
+
+        iWindowGroup.SetOrdinalPosition( 0, ECoeWinPriorityNeverAtFront );
+        
+        // create control's window to own window group
+        CreateWindowL( &iWindowGroup );    
+        Window().SetNonFading(ETrue);
+        }
+    else
+        {
+        //remove flag
+        iExtension->iFlags &= ~EAnimationHasWindowGroup; 
+        //create window
+        CreateWindowL();
+        Window().SetOrdinalPosition( KAknAnimationNotOwnWindowGroupWindowPosition );
+        }    
+
+    EnableWindowTransparency();
+    Window().SetShadowDisabled(ETrue);
+
+    iExtension->iTimer = CPeriodic::NewL(CActive::EPriorityStandard);
+   
+    iAnim = CAknBitmapAnimation::NewL();
+    iAnim->ConstructFromSkinL( KAknsIIDQgnGrafLongPressAnim );
+
+    // set default behaviour
+    SetVisibility(EFalse);
+    }
+  
+
+// ---------------------------------------------------------
+// CAknLongTapAnimation::SetVisibility
+// ---------------------------------------------------------
+//
+void CAknLongTapAnimation::SetVisibility(TBool aVisibility)
+    {
+    iExtension->iVisible = aVisibility;
+    MakeVisible( aVisibility );
+    }
+
+
+// ---------------------------------------------------------
+// CAknLongTapAnimation::Draw
+// ---------------------------------------------------------
+//
+void CAknLongTapAnimation::Draw(const TRect& /*aRect*/) const
+ 	{	
+  	CWindowGc& gc = SystemGc();
+    gc.Reset();	
+    
+ 	if (!iExtension->iVisible || iExtension->iIndex < 0)
+ 		{
+ 		return;
+ 		}
+ 
+    CBitmapAnimClientData* animData = iAnim->BitmapAnimData();	
+    		
+    CFbsBitmap* bit  = animData->FrameArray().At(iExtension->iIndex)->Bitmap();
+    CFbsBitmap* mask = animData->FrameArray().At(iExtension->iIndex)->Mask();
+
+	TPoint pos = animData->FrameArray().At( iExtension->iIndex )->Position();
+    
+    if (mask)
+    	{
+    	gc.BitBltMasked(pos, bit, TRect(TPoint(0,0), bit->SizeInPixels()), mask, ETrue);
+    	}
+    else
+    	{
+    	gc.BitBlt(pos, bit, TRect(TPoint(0,0), bit->SizeInPixels()));
+    	}
+ 	}
+
+
+// ---------------------------------------------------------
+// CAknLongTapAnimation::StartAnimation
+// ---------------------------------------------------------
+//
+void CAknLongTapAnimation::StartAnimation()
+	{
+	iExtension->iIndex = -1;
+ 	if (!(iExtension->iFlags & EAnimationStarted))
+		{
+		TCallBack callback(AnimationCallback, this);
+		
+		TInt interval = iAnim->BitmapAnimData()->FrameIntervalInMilliSeconds() *
+			KConversionFromMillisecondsToMicroseconds;
+		
+		iExtension->iTimer->Start(0, interval, callback);
+		iExtension->iFlags |= EAnimationStarted;
+		}		
+	}
+
+// ---------------------------------------------------------
+// CAknLongTapAnimation::CancelAnimation
+// ---------------------------------------------------------
+//
+void CAknLongTapAnimation::CancelAnimation()
+	{
+    if (iExtension->iFlags & EAnimationStarted)
+		{
+		iExtension->iTimer->Cancel();
+		iExtension->iFlags &= ~EAnimationStarted;
+        MTouchFeedback* feedback = MTouchFeedback::Instance();
+        if ( feedback )
+            {
+            feedback->StopFeedback( this );
+            }
+		}
+	}
+
+
+// ---------------------------------------------------------
+// CAknLongTapAnimation::NextFrame
+// ---------------------------------------------------------
+//
+void CAknLongTapAnimation::NextFrame()
+	{
+	CBitmapAnimClientData* animData = iAnim->BitmapAnimData();	
+    TInt frameCount = animData->FrameArray().Count();
+		
+	iExtension->iIndex++;
+	if (iExtension->iIndex == frameCount)
+	{
+		iExtension->iIndex = frameCount - 1;
+	}
+    MTouchFeedback* feedback = MTouchFeedback::Instance();
+    if ( feedback )
+        {
+        // intensity should go from 0 to 100
+        TInt intensity = KEndIntensity
+                       * (iExtension->iIndex+1) / frameCount;
+        feedback->ModifyFeedback( this, intensity );
+        }
+	DrawNow();
+	}
+
+
+// ---------------------------------------------------------
+// CAknLongTapAnimation::AnimationCallback
+// ---------------------------------------------------------
+//
+TInt CAknLongTapAnimation::AnimationCallback(TAny* aPtr)
+	{
+	CAknLongTapAnimation* ptr = (CAknLongTapAnimation*)aPtr;
+	ptr->NextFrame();
+	return KErrNone;
+	}
+	
+//  End of File