uifw/AvKon/src/aknpointereventmodifier.cpp
changeset 0 2f259fa3e83a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/uifw/AvKon/src/aknpointereventmodifier.cpp	Tue Feb 02 01:00:49 2010 +0200
@@ -0,0 +1,289 @@
+/*
+* Copyright (c) 2008-2009 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:  Avkon pointer event modifier.
+*
+*/
+
+
+#include <aknpointereventmodifier.h>
+#include <coecntrl.h>
+
+// ======== MEMBER FUNCTIONS ========
+
+// ---------------------------------------------------------------------------
+// CAknPointerEventModifier::NewL
+// ---------------------------------------------------------------------------
+//
+CAknPointerEventModifier* CAknPointerEventModifier::NewL()
+    {
+    CAknPointerEventModifier* self = new ( ELeave ) CAknPointerEventModifier;
+    return self;
+    }
+    
+// ---------------------------------------------------------------------------
+// CAknPointerEventModifier::~CAknPointerEventModifier()
+// ---------------------------------------------------------------------------
+//
+CAknPointerEventModifier::~CAknPointerEventModifier()
+    {
+    iStack.Close();
+    }
+    
+// ---------------------------------------------------------------------------
+// CAknPointerEventModifier::CAknPointerEventModifier
+// ---------------------------------------------------------------------------
+//
+CAknPointerEventModifier::CAknPointerEventModifier()
+    {
+    }
+
+// ---------------------------------------------------------------------------
+// CAknPointerEventModifier::Push
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void CAknPointerEventModifier::Push( CCoeControl& aControl, 
+    const TRect& aRect )
+    {
+    // Figure out aControl's window-owning parent. This will also work as a
+    // sanity check for the aControl argument.
+    CCoeControl* parent = aControl.Parent();
+    
+    while ( parent && !parent->OwnsWindow() )
+        {
+        parent = parent->Parent();
+        }
+        
+    if ( !parent )
+        {
+        return;
+        }
+    
+    if ( !ControlIsInStack( aControl ) )
+        {
+        TStackItem item;
+        item.iControl = &aControl;
+        item.iParent = parent;
+        item.iExtensionArea = aRect;
+        
+        if ( iStack.Insert( item, 0 ) == KErrNone )
+            {
+            iIsValid = EFalse;
+            }
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// CAknPointerEventModifier::Pop
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void CAknPointerEventModifier::Pop( const CCoeControl& aControl )
+    {
+    for ( TInt i = 0; i < iStack.Count(); ++i )
+        {
+        if ( iStack[i].iControl == &aControl )
+            {
+            iStack.Remove( i );
+            iIsValid = EFalse;
+            return;
+            }
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// CAknPointerEventModifier::Update
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void CAknPointerEventModifier::Update( const CCoeControl& aControl, 
+    const TRect& aRect )
+    {
+    for ( TInt i = 0; i < iStack.Count(); ++i )
+        {
+        if ( iStack[i].iControl == &aControl )
+            {
+            iStack[i].iExtensionArea = aRect;
+            break;
+            }
+        }
+    }
+    
+// ---------------------------------------------------------------------------
+// CAknPointerEventModifier::HandlePointerEvent
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void CAknPointerEventModifier::HandlePointerEvent( TPointerEvent& aEvent, 
+    CCoeControl*& aDestination )
+    {
+    if ( iStack.Count() > 0 && aEvent.iType == TPointerEvent::EButton1Down )
+        {
+        if ( !iIsValid )
+            {
+            iStack.Sort( CAknPointerEventModifier::Compare );
+            }
+            
+        for ( TInt i = 0; i < iStack.Count(); ++i )
+            {
+            if ( ModifyEvent( iStack[i], aEvent, aDestination ) )
+                {
+                break;
+                }
+            }
+        }
+    }
+    
+// ---------------------------------------------------------------------------
+// CAknPointerEventModifier::Invalidate
+// ---------------------------------------------------------------------------
+//
+void CAknPointerEventModifier::Invalidate()
+    {
+    iIsValid = ETrue;
+    }
+
+// ---------------------------------------------------------------------------
+// CAknPointerEventModifier::ControlIsInStack
+// ---------------------------------------------------------------------------
+//
+TBool CAknPointerEventModifier::ControlIsInStack( const CCoeControl& aControl )
+    {
+    for ( TInt i = 0; i < iStack.Count(); ++i )
+        {
+        if ( iStack[i].iControl == &aControl )
+            {
+            return ETrue;
+            }
+        }
+    
+    return EFalse;
+    }
+
+// ---------------------------------------------------------------------------
+// CAknPointerEventModifier::ModifyEvent
+// ---------------------------------------------------------------------------
+//
+TBool CAknPointerEventModifier::ModifyEvent( TStackItem& aItem, 
+    TPointerEvent& aEvent, CCoeControl*& aDestination )
+    {
+    TBool wasModified = EFalse;
+    
+    // Control window's existence has been checked already in 
+    // CAknPointerEventModifier::Push.
+    if ( !aItem.iControl->DrawableWindow()->IsFaded() )
+        {
+        TBool isVertical = ( aItem.iControl->Size().iHeight > aItem.iControl->Size().iWidth );
+        
+        if ( aDestination == aItem.iParent )
+            {
+            // calculate hit area
+            TRect hitArea( aItem.iControl->Position() + 
+                aItem.iExtensionArea.iTl, aItem.iExtensionArea.Size() );
+            TSize controlSize( aItem.iControl->Size() );
+
+            if ( hitArea.Contains( aEvent.iPosition ) )
+                {
+                if ( aItem.iControl->OwnsWindow() )
+                    {
+                    aDestination = aItem.iControl;
+                    
+                    if ( isVertical )
+                        {
+                        aEvent.iPosition.iX = controlSize.iWidth >> 1;
+                        aEvent.iPosition.iY -= aItem.iControl->Position().iY;
+                        }
+                    else
+                        {
+                        aEvent.iPosition.iX -= aItem.iControl->Position().iX;
+                        aEvent.iPosition.iY = controlSize.iHeight >> 1;
+                        }
+                    }
+                else
+                    {
+                    if ( isVertical )
+                        {
+                        aEvent.iPosition.iX = aItem.iControl->Position().iX + 
+                            ( controlSize.iWidth >> 1 );
+                        }
+                    else
+                        {
+                        aEvent.iPosition.iY = aItem.iControl->Position().iY +
+                            ( controlSize.iHeight >> 1 );
+                        }
+                    }
+                    
+                wasModified = ETrue;
+                }
+            }
+        else if ( aDestination->Parent() && 
+            aDestination->Parent()->DrawableWindow() == aItem.iParent->DrawableWindow() &&
+             ( aDestination->Parent() != aItem.iParent ))
+            {
+            // This branch handles external scrollbars. It should be checked
+            // via MOP chain if the aItem.iControl really is a scrollbar before
+            // this API is taken into use with other controls.
+            TPoint topLeft( aItem.iControl->Position().iX - 
+                aDestination->Position().iX, 
+                aItem.iControl->Position().iY - aDestination->Position().iY );
+            TRect hitArea( topLeft + 
+                aItem.iExtensionArea.iTl, aItem.iExtensionArea.Size() );
+
+            if ( hitArea.Contains( aEvent.iPosition ) )
+                {
+                TInt controlPosition = aItem.iControl->Position().iY;
+                TInt positionInParent = aEvent.iPosition.iY + aDestination->Position().iY;
+                
+                if ( isVertical )
+                    {
+                    aEvent.iPosition.iX = aItem.iControl->Size().iWidth >> 1;
+                    aEvent.iPosition.iY = positionInParent - controlPosition;
+                    }
+                else
+                    {
+                    aEvent.iPosition.iX = aEvent.iPosition.iX + 
+                        aDestination->Position().iX - aItem.iControl->Position().iX;
+                    aEvent.iPosition.iY = aItem.iControl->Size().iHeight >> 1;
+                    }
+                    
+                aDestination = aItem.iControl;
+                
+                wasModified = ETrue;
+                }
+            }
+        }
+        
+    return wasModified;
+    }
+    
+// ---------------------------------------------------------------------------
+// CAknPointerEventModifier::Compare
+// ---------------------------------------------------------------------------
+//
+TInt CAknPointerEventModifier::Compare( const TStackItem& aFirst, 
+    const TStackItem& aSecond )
+    {
+    TInt retval = -1; // aFirst is in front of aSecond
+    TInt firstPosition = aFirst.iParent->DrawableWindow()->OrdinalPosition();
+    TInt secondPosition = aSecond.iParent->DrawableWindow()->OrdinalPosition();
+    
+    if ( secondPosition < firstPosition && secondPosition >= 0 )
+        {
+        // aSecond is in front of aFirst in z-order
+        retval = 1;
+        }
+    else if ( firstPosition == secondPosition )
+        {
+        // aFirst and aSecond have the same parent window
+        retval = 0;
+        }
+    
+    return retval;
+    }