uifw/AvKon/src/akndiscreetpopupcontrol.cpp
changeset 14 3320e4e6e8bb
parent 0 2f259fa3e83a
--- a/uifw/AvKon/src/akndiscreetpopupcontrol.cpp	Tue Feb 02 01:00:49 2010 +0200
+++ b/uifw/AvKon/src/akndiscreetpopupcontrol.cpp	Fri Apr 16 15:13:44 2010 +0300
@@ -26,19 +26,26 @@
 #include <bautils.h>
 #include <barsread.h>
 #include <gulicon.h>
-#include <gfxtranseffect/gfxtranseffect.h>
-#include <akntransitionutils.h>
 #include <avkon.hrh>
 #include "akndiscreetpopupcontrol.h"
 #include "akndiscreetpopupdrawer.h"
 
 _LIT( KDiscreetPopupWindowGroupName, "Discreet pop-up" );
 
+const TInt KOpacityChangeSpeed( 18 );
+const TInt KAlphaMax( 255 );
+const TInt KAlphaMin( 0 );
 const TInt KShortTimeout( 1500000 );
 const TInt KLongTimeout( 3000000 );
+const TInt KShowDelay( 300000 );
+const TInt KShowInterval( 50000 );
+const TInt KHideDelay( 50000 );
+const TInt KHideInterval( 50000 );
 const TInt KGlobalShowOrdinalPriority( ECoeWinPriorityAlwaysAtFront * 4 );
 const TInt KLocalShowOrdinalPriority( ECoeWinPriorityNormal + 1 );
 const TInt KLocalHideOrdinalPosition( -10 );
+const TInt KOpacityDismissFactor( 3 );
+const TInt KMaxFadeTime( 1000000 );
 
 /**
  * Internal discreet popup control flags.
@@ -48,6 +55,7 @@
     EPressedDown,     // Pointer down is received in popup area
     EDismissed,       // Popup is dismissed (pointer up is received in popup area)
     EGlobal,          // Popup is global
+    EFading,          // Popup is closing (fading)
     EDragged          // Pointer is dragged while popup open
     };
 
@@ -180,9 +188,6 @@
         {
         HidePopup();
         }
-
-    GfxTransEffect::Deregister( this );
-
     if ( iInternalFlags.IsSet( EGlobal ) )
         {
         iWindowGroup.Close();
@@ -250,6 +255,11 @@
 //
 void CAknDiscreetPopupControl::MakeVisible( TBool aVisible )
     {
+    if ( iTimer )
+        {
+        iTimer->Cancel();
+        }
+    
     CCoeControl::MakeVisible( aVisible );
  
     if( iInternalFlags.IsSet( EGlobal ) )
@@ -260,7 +270,21 @@
         {
         Window().SetOrdinalPosition( 0, KLocalShowOrdinalPriority );
         }    
-
+        
+    if ( aVisible && iTimer )
+        {
+        iAlpha = 0;
+        iInternalFlags.Clear( EFading );
+        iInternalFlags.Clear( EDismissed );
+        
+        iTimer->Start( KShowDelay, 
+                       KShowInterval, 
+                       TCallBack( TimeOut, this ) );
+                             
+        iFadeTime.HomeTime(); 
+        TTimeIntervalMicroSeconds32 timeout( KShowDelay );
+        iFadeTime += timeout;
+        }
     UpdateNonFadingStatus();
     }
 
@@ -289,13 +313,14 @@
         {
         iInternalFlags.Set( EGlobal );
         }
+    iInternalFlags.Set( EDismissed );
 
-    iInternalFlags.Set( EDismissed );
-    iCommand = aCommand;
-    iCommandObserver = aCommandObserver;
-
-    GfxTransEffect::Register( this, KGfxDiscreetPopupControlUid );
-    
+    // Action allowed only when touch enabled
+    if ( AknLayoutUtils::PenEnabled() )
+        {
+        iCommand = aCommand;
+        iCommandObserver = aCommandObserver;
+        }
     AKNTASHOOK_ADD( this, "CAknDiscreetPopupControl" );
     }
 
@@ -334,7 +359,15 @@
         
     iTimer = CPeriodic::NewL( 0 );
     
-    EnableWindowTransparency();
+    // try to enable window transparency
+    if( CAknEnv::Static()->TransparencyEnabled() )
+        {
+        Window().SetRequiredDisplayMode( EColor16MA );
+        if ( Window().SetTransparencyAlphaChannel() == KErrNone )
+            {
+            Window().SetBackgroundColor( ~0 );
+            }
+        }
 
     Window().SetPointerGrab( ETrue );
     EnableDragEvents();
@@ -401,13 +434,74 @@
 //
 void CAknDiscreetPopupControl::DoTimeOut()
     {
-    if ( !iInternalFlags.IsSet( EPressedDown ) )
+    if ( iInternalFlags.IsSet( EFading ) && iAlpha <= KAlphaMin )
         {
+        // popup has faded completely, exit
         TRAP_IGNORE( RequestExitL() );
         }
     else
         {
-        iTimer->Cancel();
+        TInt opacityChange = 
+            iInternalFlags.IsSet( EFading ) ? -KOpacityChangeSpeed : KOpacityChangeSpeed;
+        
+        if ( iInternalFlags.IsSet( EPressedDown ) 
+             && iInternalFlags.IsSet( EFading ) )
+            {
+            iAlpha = KAlphaMax;
+            opacityChange = 0;
+            }
+        
+        if ( iInternalFlags.IsSet( EDismissed ) )
+            {
+            opacityChange *= KOpacityDismissFactor;
+            }
+        iAlpha += opacityChange;
+        
+        TTime now;     
+        now.HomeTime();
+        TInt fadeTime( now.MicroSecondsFrom( iFadeTime ).Int64() );
+            
+        if ( fadeTime > KMaxFadeTime )
+            {          
+            if ( !iInternalFlags.IsSet( EFading ) )
+                {
+                // fade in animation is taking too long, 
+                // make popup fully visible
+                iAlpha = KAlphaMax;
+                }
+            else
+                {
+                // fade out animation is taking too long, 
+                // make popup invisible
+                iAlpha = KAlphaMin;    
+                }   
+            }         
+        
+        if ( iAlpha >= KAlphaMax )
+            {
+            // popup is completely visible. set the EFading flag and set timeout
+            iAlpha = KAlphaMax;
+            iInternalFlags.Set( EFading );
+            iTimer->Cancel();
+            //fade out after timeout
+            TTimeIntervalMicroSeconds32 timeout( KShortTimeout );
+            if ( iFlags & KAknDiscreetPopupDurationLong )
+                {
+                timeout = KLongTimeout;
+                }
+            iTimer->Start( timeout, 
+                           KHideInterval, 
+                           TCallBack( TimeOut, this ) );
+                           
+            iFadeTime.HomeTime();
+            iFadeTime += timeout;            
+            }
+        else if ( iAlpha < KAlphaMin )
+            {
+            iAlpha = KAlphaMin;
+            }
+
+        DrawNow();
         }
     }
 
@@ -539,30 +633,7 @@
     User::ResetInactivityTime();
 
     PlayTone();
-    
-    if ( GfxTransEffect::IsRegistered( this ) )
-        {
-        iInternalFlags.Clear( EDismissed );
-        GfxTransEffect::Begin( this, KGfxControlAppearAction );
-        MakeVisible( ETrue );
-        GfxTransEffect::SetDemarcation( this, iPosition );
-        GfxTransEffect::End( this );
-        }
-    else
-        {
-        MakeVisible( ETrue );
-        }
-
-    TTimeIntervalMicroSeconds32 timeout( KShortTimeout );
-    
-    if ( iFlags & KAknDiscreetPopupDurationLong )
-        {
-        timeout = KLongTimeout;
-        }
-    
-    iTimer->Start( timeout, 
-                   0, 
-                   TCallBack( TimeOut, this ) );
+    MakeVisible( ETrue );
     }
 
 
@@ -572,17 +643,7 @@
 //
 void CAknDiscreetPopupControl::HidePopup()
     {
-    if ( GfxTransEffect::IsRegistered( this ) )
-        {
-        GfxTransEffect::Begin( this, KGfxControlDisappearAction );
-        MakeVisible( EFalse );
-        GfxTransEffect::End( this );
-        }
-    else
-        {
-        MakeVisible( EFalse );
-        }
-
+    MakeVisible( EFalse );
     AppUi()->RemoveFromStack( this );
     }
 
@@ -639,7 +700,26 @@
         return;
         }
 
-    iDrawer->Draw( SystemGc(), Rect() );
+    CFbsBitmap* popupBitmap( iDrawer->PopupBitmap( Size() ) );
+    
+    // create a transparent mask for the popup
+    CFbsBitmap* transParentBitmap = 
+        iDrawer->TransparentMask( popupBitmap->SizeInPixels(), iAlpha );
+    
+    // blit the bitmap to screen with the transparent mask
+    CWindowGc& gc = SystemGc();
+    if( transParentBitmap )
+        {
+        gc.BitBltMasked( Rect().iTl, 
+                         popupBitmap, 
+                         popupBitmap->SizeInPixels(), 
+                         transParentBitmap, 
+                         EFalse );	
+        }
+    else
+        {
+        gc.BitBlt( Rect().iTl, popupBitmap );
+        }
     }
 
 
@@ -741,7 +821,11 @@
          && iInternalFlags.IsClear( EDismissed ) )
         {
         SetPressedDownState( ETrue );
-        ImmediateFeedback( ETouchFeedbackSensitive );
+        // Play feedback only when popup is completely visible (or fading away)
+        if ( iInternalFlags.IsSet( EFading ) )
+            {
+            ImmediateFeedback( ETouchFeedbackSensitive );
+            }
         }
 
     // Pointer drag - reset pressed-down state if pointer out of popup area
@@ -761,18 +845,21 @@
     // Pointer up - reset pressed-down state 
     else if ( aPointerEvent.iType == TPointerEvent::EButton1Up )
         {
-        if ( eventInRect )
+        if ( iInternalFlags.IsSet( EFading )
+             && iInternalFlags.IsSet( EPressedDown )
+             && eventInRect )
             {
+            // Notify popup tap
             NotifyObserverL();
+            // Start fading away
+            if ( iInternalFlags.IsClear( EDismissed ) )
+                {
+                iTimer->Cancel();
+                iInternalFlags.Set( EFading );
+                iInternalFlags.Set( EDismissed );
+                iTimer->Start( KHideDelay, KHideInterval, TCallBack( TimeOut, this ) );
+                }
             }
-        
-        // Start fading away
-        if ( iInternalFlags.IsClear( EDismissed ) )
-            {
-            iInternalFlags.Set( EDismissed );
-            RequestExitL();
-            }
-
         SetPressedDownState( EFalse );
         }
     }