imageeditor/plugins/RedEyePlugin/src/ImageEditorRedEyeReductionControl.cpp
changeset 1 edfc90759b9f
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/imageeditor/plugins/RedEyePlugin/src/ImageEditorRedEyeReductionControl.cpp	Fri Jan 29 13:53:17 2010 +0200
@@ -0,0 +1,1530 @@
+/*
+* Copyright (c) 2010 Ixonos Plc.
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of the "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:
+* Ixonos Plc
+*
+* Description: 
+* Control class for RedEyeReduction plugin.
+*
+*/
+
+
+//  INCLUDES
+#include <fbs.h>
+#include <badesca.h>
+#include <gdi.h>
+#include <eikenv.h>
+#include <bitdev.h>
+#include <eikmenup.h>
+#include <coehelp.h>
+
+#include <aknview.h>
+#include <aknutils.h>
+
+#include <ImageEditorUI.mbg>
+
+
+#include <AknInfoPopupNoteController.h> 
+#include <redeyereduction.rsg> 
+#include <bautils.h> 
+#include <ConeResLoader.h> 
+#include <csxhelp/sie.hlp.hrh>
+
+#ifdef RD_TACTILE_FEEDBACK 
+#include <touchfeedback.h>
+#endif /* RD_TACTILE_FEEDBACK  */
+
+#include "ImageEditorUI.hrh"
+#include "ImageEditorPluginBase.hrh"
+#include "RedEyeReduction.hrh"
+#include "DrawUtils.h"
+#include "PluginInfo.h"
+#include "SystemParameters.h"
+#include "ImageEditorUids.hrh"
+
+#include "ImageEditorRedEyeReductionControl.h"
+#include "ImageEditorUIDefs.h" 
+#include "iepb.h"
+#include "definitions.def"
+
+// 	DEBUG LOG
+#include "imageeditordebugutils.h"
+_LIT(KRedEyeReductionPluginLogFile, "RedEyeReductionPlugin.log");
+
+//  CONSTANTS
+const TReal KPosParamMin        = 0.0;
+const TReal KPosParamMax        = 1.0;
+const TReal KPosParamStep       = 0.01;
+const TReal KPosParamDef        = 0.5;
+
+const TReal KRadiusParamMin      = 0.0;
+const TReal KRadiusParamMax      = 0.4;
+const TReal KRadiusParamStep     = 0.0025;
+const TReal KRadiusParamDef      = 0.05;
+
+const TInt KMoveSelectionIndex    = 0;
+const TInt KResizeSelectionIndex  = 1;
+
+// Default values from CPreviewControlBase not used
+const TInt KRedEyeFastKeyTimerDelayInMicroseconds = 500000;
+const TInt KRedEyeFastKeyTimerIntervalInMicroseconds = 50000;
+const TInt KRedEyeFastKeyTimerMultiplyThresholdInTicks = 9;
+const TInt KRedEyeBigNavigationStepMultiplier = 3;
+
+// Touch constants
+const TInt KTouchScaleMaxStepCount  = 50;
+
+// Panic category
+_LIT (KComponentName, "ImageEditorRedEyeReduction" );
+
+// Resource file name
+_LIT (KPgnResourceFile, "redeyereduction.rsc"); 
+
+//=============================================================================
+TInt CImageEditorRedEyeReductionControl::DancingAntzCallback (TAny * aPtr)
+{
+	((CImageEditorRedEyeReductionControl *)aPtr)->OnDancingAntzCallBack();
+	return KErrNone;
+}
+
+//=============================================================================
+TInt CImageEditorRedEyeReductionControl::FastKeyCallback (TAny * aPtr)
+{
+	TRAPD( err, ((CImageEditorRedEyeReductionControl *)aPtr)->OnFastKeyCallBackL() );
+	return err;
+}
+
+//=============================================================================
+CImageEditorRedEyeReductionControl * CImageEditorRedEyeReductionControl::NewL (
+	const TRect &		aRect,
+	CCoeControl	*		aParent
+	)
+{
+    CImageEditorRedEyeReductionControl * self = new (ELeave) CImageEditorRedEyeReductionControl;
+    CleanupStack::PushL (self);
+    self->ConstructL (aRect, aParent);
+    CleanupStack::Pop ();   // self
+    return self;
+}
+
+//=============================================================================
+CImageEditorRedEyeReductionControl::CImageEditorRedEyeReductionControl () :
+iState( ERedEyeReductionStateMin ),
+iX( KPosParamDef ),
+iY( KPosParamDef ),
+iR( KRadiusParamDef ),
+iHandleEventKeys (ETrue),
+iTickCount (0),
+iNaviStepMultiplier (KDefaultSmallNavigationStepMultiplier),
+iReadyToRender(ETrue),
+iDoNotUpdateParameters(EFalse),
+iCursorDragEnabled( EFalse )
+{
+    
+}
+
+//=============================================================================
+CImageEditorRedEyeReductionControl::~CImageEditorRedEyeReductionControl ()
+{
+    delete iCrossHair;
+    delete iCrossHairMask;
+    iUndoArray.Close();
+    if( iTimer )
+    {
+        iTimer->Cancel();
+    }
+    delete iTimer;
+    iVisibleImageRectPrev = NULL;
+    iVisibleImageRect = NULL;
+    iEditorView = NULL;
+    iItem = NULL;
+    
+    delete iPopupController;
+	delete iTooltipLocate;
+	delete iTooltipOutline;
+
+}
+
+//=============================================================================
+void CImageEditorRedEyeReductionControl::ConstructL (
+	const TRect &		/*aRect*/,
+	CCoeControl	*		aParent
+	)
+{
+	LOG_INIT(KRedEyeReductionPluginLogFile);
+	LOG( KRedEyeReductionPluginLogFile, "CImageEditorRedEyeReductionControl::ConstructL" );
+
+	//	Set parent window
+	SetContainerWindowL (*aParent);
+
+    //	Create timer for fast keys and dancing ants
+    iTimer = CPeriodic::NewL (CActive::EPriorityStandard);
+
+	//	Create CROSSHAIR image
+    SDrawUtils::GetIndicatorBitmapL( 
+        iCrossHair, 
+        iCrossHairMask, 
+        EMbmImageeditoruiQgn_indi_imed_cursor_super, // cross-hair
+        EMbmImageeditoruiQgn_indi_imed_cursor_super_mask
+        );
+
+	iPopupController = CAknInfoPopupNoteController::NewL();    
+	
+	TFileName resourcefile;
+	resourcefile.Append(KPgnResourcePath);
+	resourcefile.Append(KPgnResourceFile);
+    User::LeaveIfError( CompleteWithAppPath( resourcefile ) );
+
+    //	Read tooltip resources  
+    //  (RConeResourceLoader selects the language using BaflUtils::NearestLanguageFile)
+    RConeResourceLoader resLoader ( *CEikonEnv::Static() );
+    CleanupClosePushL ( resLoader );
+	resLoader.OpenL ( resourcefile );
+	
+	iTooltipLocate = CEikonEnv::Static()->AllocReadResourceL(R_TOOLTIP_REDEYE_LOCATE);    
+	iTooltipOutline = CEikonEnv::Static()->AllocReadResourceL(R_TOOLTIP_REDEYE_OUTLINE);    
+      
+    CleanupStack::PopAndDestroy(); // resLoader
+
+#ifdef RD_TACTILE_FEEDBACK 
+    iTouchFeedBack = MTouchFeedback::Instance();
+#endif /* RD_TACTILE_FEEDBACK  */
+    
+	//	Activate control
+    ActivateL();
+    
+    EnableDragEvents();
+}
+
+//=============================================================================
+void CImageEditorRedEyeReductionControl::SetView (CAknView * aView)
+{
+    LOG( KRedEyeReductionPluginLogFile, "CImageEditorRedEyeReductionControl::SetView" );
+    
+    iEditorView = aView;
+}
+
+//=============================================================================
+void CImageEditorRedEyeReductionControl::SetSelectedUiItemL (CPluginInfo * aItem)
+{
+    LOG( KRedEyeReductionPluginLogFile, "CImageEditorRedEyeReductionControl::SetSelectedUiItemL" );
+
+    iItem = aItem;
+}
+
+//=============================================================================
+void CImageEditorRedEyeReductionControl::PrepareL ()
+{
+    LOG( KRedEyeReductionPluginLogFile, "CImageEditorRedEyeReductionControl::PrepareL" );
+
+#ifdef __TOUCH_ONLY_DEVICE_RER_PLUGIN_ACTION__         
+    // The whole crosshair set state is skipped totally in touch-only devices
+    ToResizeStateL();
+#else        
+    ToMoveStateL();
+#endif    
+                
+    // Store parameters for the initial filter. 
+    // This is a special case. For the other filters, the parameters
+    // are stored implicitly when calling 
+    iEditorView->HandleCommandL (EImageEditorStoreParameters);
+}
+
+//=============================================================================
+TKeyResponse CImageEditorRedEyeReductionControl::OfferKeyEventL (
+    const TKeyEvent &   aKeyEvent,
+    TEventCode          aType
+    )
+{
+    TKeyResponse response = EKeyWasNotConsumed;
+
+    //  If busy, do not handle anything
+    if ( Busy() )
+    {
+        response = EKeyWasConsumed;
+    }
+
+    //  EEventKey
+    else if (EEventKey == aType && iHandleEventKeys)
+    {
+        
+		switch (aKeyEvent.iCode)
+		{
+
+			case EKeyDownArrow:
+			{
+                //  Adjust crop point
+                NaviDown();
+                DrawNow();
+                response = EKeyWasConsumed;
+                break;
+			}
+
+			case EKeyUpArrow:
+			{
+                //  Adjust crop point
+                NaviUp();
+                DrawNow();
+                response = EKeyWasConsumed;
+                break;
+			}
+
+			case EKeyRightArrow:
+			{
+                //  Adjust crop point
+                NaviRight();
+                DrawNow();
+				response = EKeyWasConsumed;
+                break;
+			}
+
+            case EKeyLeftArrow:
+			{
+                //  Adjust crop point
+                NaviLeft();
+                DrawNow();
+				response = EKeyWasConsumed;
+                break;
+			}
+
+            case EKeyOK:
+            case EKeyEnter:
+            {
+                KeyOkL();
+                DrawNow();
+                response = EKeyWasConsumed;
+                break;
+            }
+
+			default:
+			{
+				break;
+			}
+		}
+    }
+
+    else if (EEventKey == aType && !iHandleEventKeys)
+    {
+        response = EKeyWasConsumed;
+    }
+
+    //  EEventKeyDown
+    else if (EEventKeyDown == aType)
+    {
+        switch (aKeyEvent.iScanCode)
+        {
+            case EStdKeyLeftArrow:
+            case EStdKeyRightArrow:
+            case EStdKeyUpArrow:
+            case EStdKeyDownArrow:
+            {   
+                iPressedKeyScanCode = aKeyEvent.iScanCode;
+                StartFastKeyTimer();
+                response = EKeyWasConsumed;
+                break;
+            }
+            default:
+                break;
+        }
+    }
+
+    //  EEventKeyUp
+    else if (EEventKeyUp == aType)
+    {
+        if (aKeyEvent.iScanCode == iPressedKeyScanCode)
+        {
+            iHandleEventKeys = ETrue;
+            if (iState == ERedEyeReductionStateResizeSelection)
+            {
+                StartDancingAntzTimer();
+            }
+            else if( iTimer )
+            {
+                iTimer->Cancel();
+            }
+            response = EKeyWasConsumed;
+            
+            ShowTooltip();
+        }
+    }
+
+    return response;
+}
+    
+//=============================================================================
+void CImageEditorRedEyeReductionControl::SizeChanged()
+{
+}
+
+//=============================================================================
+TRect CImageEditorRedEyeReductionControl::GetParam ()
+{
+	LOG( KRedEyeReductionPluginLogFile, "CImageEditorRedEyeReductionControl::GetParam" );
+	if (iUndoArray.Count() == 0 || iDoNotUpdateParameters)
+	{
+		LOG( KRedEyeReductionPluginLogFile, "\tiRedEyeRect: (0,0), (0,0)" );
+		return TRect();
+	}
+	else
+	{
+		LOGFMT4( KRedEyeReductionPluginLogFile, "\tiRedEyeRect: (%d,%d), (%d,%d)", iRedEyeRect.iTl.iX, iRedEyeRect.iTl.iY, iRedEyeRect.iBr.iX, iRedEyeRect.iBr.iY );
+		ComputeParams();
+		return iRedEyeRect;
+	}
+}
+
+//=============================================================================
+void CImageEditorRedEyeReductionControl::SetSystemParameters (const CSystemParameters * aPars) 
+{
+    LOG( KRedEyeReductionPluginLogFile, "CImageEditorRedEyeReductionControl::SetSystemParameters" );
+
+    iVisibleImageRect = &(aPars->VisibleImageRect()); 
+    iVisibleImageRectPrev = &(aPars->VisibleImageRectPrev());
+	iSysPars = aPars;
+
+    __ASSERT_ALWAYS( iVisibleImageRectPrev && iVisibleImageRectPrev, User::Panic(KComponentName, KErrNotReady) );
+    LOGFMT4( KRedEyeReductionPluginLogFile, "\tiVisibleImageRect: (%d,%d), (%d,%d)", iVisibleImageRect->iTl.iX, iVisibleImageRect->iTl.iY, iVisibleImageRect->iBr.iX, iVisibleImageRect->iBr.iY );
+    LOGFMT2( KRedEyeReductionPluginLogFile, "\tVisible image rect size: %d,%d", (iVisibleImageRect->iBr.iX - iVisibleImageRect->iTl.iX) + 1, (iVisibleImageRect->iBr.iY - iVisibleImageRect->iTl.iY) + 1 );
+    LOGFMT2( KRedEyeReductionPluginLogFile, "\tSize(): %d,%d", Size().iWidth, Size().iHeight );
+    LOGFMT4( KRedEyeReductionPluginLogFile, "\tiVisibleImageRectPrev: (%d,%d), (%d,%d)", iVisibleImageRectPrev->iTl.iX, iVisibleImageRectPrev->iTl.iY, iVisibleImageRectPrev->iBr.iX, iVisibleImageRectPrev->iBr.iY );
+    LOGFMT2( KRedEyeReductionPluginLogFile, "\tiVisibleImageRectPrev size: %d,%d", iVisibleImageRectPrev->Width(), iVisibleImageRectPrev->Height() );
+}
+
+//=============================================================================
+void CImageEditorRedEyeReductionControl::HandlePluginCommandL (const TInt aCommand)
+{
+    LOGFMT( KRedEyeReductionPluginLogFile, "CImageEditorRedEyeReductionControl::HandlePluginCommandL: %d", aCommand );
+
+    switch (aCommand) 
+    {
+        case EImageEditorFocusGained:
+        {
+            if (iState == ERedEyeReductionStateResizeSelection)
+            {
+                StartDancingAntzTimer();
+            }
+            break;
+        }
+        case EImageEditorFocusLost:
+        {
+            if (iTimer)
+            {
+                iTimer->Cancel();
+            }
+            break;
+        }
+        case EPgnSoftkeyIdCancel:
+        {
+            CancelPluginL();
+            break;
+        }
+        case EPgnSoftkeyIdDone:
+        {        
+            iDoNotUpdateParameters = ETrue;
+            iEditorView->HandleCommandL (EImageEditorApplyPlugin);
+            break;
+        }
+        case ERedEyeReductionPgnMenuCmdSet:
+        case EPgnSoftkeyIdSet:
+        {
+            KeyOkL();
+            DrawNow();
+            break;
+        }
+        case ERedEyeReductionPgnMenuCmdReduceRed:
+        case EPgnSoftkeyIdReduceRed:
+        {
+            KeyOkL();
+            DrawNow();
+            break;
+        }
+        case ERedEyeReductionPgnMenuCmdUndo:
+        {
+            UndoL();
+            iEditorView->HandleCommandL (EImageEditorUpdateSoftkeys);
+            break;
+        }
+        case ERedEyeReductionPgnMenuCmdCancel:
+        {
+            CancelPluginL();
+            break;
+        }
+        case EImageEditorPreGlobalZoomChange:
+        case EImageEditorPreGlobalPanChange:
+		{
+			iDoNotUpdateParameters = ETrue;
+			break;
+		}
+        case EImageEditorGlobalZoomChanged:
+        case EImageEditorGlobalPanChanged:
+        {
+			iDoNotUpdateParameters = EFalse;
+			DrawNow();
+	        break;
+        }
+        
+    	case EImageEditorPreScreenModeChange:
+    	{
+    		TReal relscale = iSysPars->RelScale();
+			TRect virect = *iVisibleImageRect;
+			virect.iTl.iX = (TInt)((virect.iTl.iX / relscale) + 0.5);
+			virect.iTl.iY = (TInt)((virect.iTl.iY / relscale) + 0.5);
+			virect.iBr.iX = (TInt)((virect.iBr.iX / relscale) + 0.5);
+			virect.iBr.iY = (TInt)((virect.iBr.iY / relscale) + 0.5);
+			iLockPoint.iX = virect.iTl.iX + iX * virect.Width();
+			iLockPoint.iY = virect.iTl.iY + iY * virect.Height();
+    		break;
+    	}
+    	case EImageEditorPostScreenModeChange:
+    	{
+    		TReal relscale = iSysPars->RelScale();
+			TRect virect = *iVisibleImageRect;
+			virect.iTl.iX = (TInt)((virect.iTl.iX / relscale) + 0.5);
+			virect.iTl.iY = (TInt)((virect.iTl.iY / relscale) + 0.5);
+			virect.iBr.iX = (TInt)((virect.iBr.iX / relscale) + 0.5);
+			virect.iBr.iY = (TInt)((virect.iBr.iY / relscale) + 0.5);
+			iX = (TReal)(iLockPoint.iX - virect.iTl.iX) / virect.Width();
+			iY = (TReal)(iLockPoint.iY - virect.iTl.iY) / virect.Height();
+			ClipPosition();
+			DrawNow();
+    		break;
+    	}
+        
+        default:
+        {
+            break;
+        }
+    }
+}
+
+//=============================================================================
+TInt CImageEditorRedEyeReductionControl::GetSoftkeyIndexL()
+{
+    
+    TInt index = -1;
+  if ( iState == ERedEyeReductionStateResizeSelection )
+        {
+        if ( !iUndoArray.Count() )
+            {
+            index = 3;
+            }
+        else
+            {
+            index = 1;
+            }            
+        }
+    else if ( iState == ERedEyeReductionStateMoveCrosshair )
+        {
+        if ( !iUndoArray.Count() )
+            {
+            index = 0;
+            }
+        else
+            {
+            index = 2;
+            }  
+        }
+   
+  
+       
+    LOGFMT( KRedEyeReductionPluginLogFile, "CImageEditorRedEyeReductionControl::GetSoftkeyIndexL: %d", index );
+
+    return index;
+}
+
+//=============================================================================
+TBitField CImageEditorRedEyeReductionControl::GetDimmedMenuItems()
+{
+	LOG( KRedEyeReductionPluginLogFile, "CImageEditorRedEyeReductionControl::GetDimmedMenuItems" );
+
+    TBitField dimmedMenuItems;
+    TInt count = iItem->MenuItems().Count();
+
+    switch (iState) 
+    {
+    case ERedEyeReductionStateMoveCrosshair:
+        {
+            // Dim the command ERedEyeReductionPgnMenuCmdReduceRed, and also 
+            // ERedEyeReductionPgnMenuCmdUndo if selecting the first eye.
+            for ( TInt i = 0; i < count; i++)
+            {
+                // get the menu item id
+                TInt menuItem = iItem->MenuItems().At(i).iCommandId;
+                if ( menuItem == ERedEyeReductionPgnMenuCmdReduceRed ||
+                    ( iUndoArray.Count() == 0 && menuItem == ERedEyeReductionPgnMenuCmdUndo) 
+                    )
+                {
+                    dimmedMenuItems.SetBit( i );
+                }
+            }
+            break;
+        }
+    case ERedEyeReductionStateResizeSelection:
+        {
+            // Dim the command ERedEyeReductionPgnMenuCmdSet.
+            for ( TInt i = 0; i < count; i++)
+            {
+                // get the menu item id
+                TInt menuItem = iItem->MenuItems().At(i).iCommandId;
+                
+#ifdef __TOUCH_ONLY_DEVICE_RER_PLUGIN_ACTION__ 
+                if ( menuItem == ERedEyeReductionPgnMenuCmdSet ||
+                   ( iUndoArray.Count() == 0 && menuItem == ERedEyeReductionPgnMenuCmdUndo))
+                {
+                    dimmedMenuItems.SetBit( i );
+                }                
+#else
+                if ( menuItem == ERedEyeReductionPgnMenuCmdSet )
+                {
+                    dimmedMenuItems.SetBit( i );
+                }
+#endif                
+                
+            }
+            break;
+        }
+    default:
+        {
+            ASSERT( EFalse );
+            break;
+        }
+    }
+    return dimmedMenuItems;
+}
+
+//=============================================================================
+TPtrC CImageEditorRedEyeReductionControl::GetNaviPaneTextL (
+    TBool& aLeftNaviPaneScrollButtonVisibile, 
+    TBool& aRightNaviPaneScrollButtonVisible )
+{
+    aLeftNaviPaneScrollButtonVisibile = EFalse;
+    aRightNaviPaneScrollButtonVisible = EFalse;
+    return iNaviPaneText;
+}
+
+//=============================================================================
+void CImageEditorRedEyeReductionControl::Draw (const TRect & aRect) const
+{
+    LOG( KRedEyeReductionPluginLogFile, "CImageEditorRedEyeReductionControl::Draw()" );
+
+    CPreviewControlBase::DrawPreviewImage (aRect);
+
+#ifdef VERBOSE
+    LOGFMT4( KRedEyeReductionPluginLogFile, "\tiVisibleImageRect: (%d,%d), (%d,%d)", iVisibleImageRect->iTl.iX, iVisibleImageRect->iTl.iY, iVisibleImageRect->iBr.iX, iVisibleImageRect->iBr.iY );
+    LOGFMT2( KRedEyeReductionPluginLogFile, "\tVisible image rect size: %d,%d", (iVisibleImageRect->iBr.iX - iVisibleImageRect->iTl.iX) + 1, (iVisibleImageRect->iBr.iY - iVisibleImageRect->iTl.iY) + 1 );
+    LOGFMT2( KRedEyeReductionPluginLogFile, "\tSize(): %d,%d", Size().iWidth, Size().iHeight );
+    LOGFMT4( KRedEyeReductionPluginLogFile, "\tiVisibleImageRectPrev: (%d,%d), (%d,%d)", iVisibleImageRectPrev->iTl.iX, iVisibleImageRectPrev->iTl.iY, iVisibleImageRectPrev->iBr.iX, iVisibleImageRectPrev->iBr.iY );
+    LOGFMT2( KRedEyeReductionPluginLogFile, "\tiVisibleImageRectPrev size: %d,%d", iVisibleImageRectPrev->Width(), iVisibleImageRectPrev->Height() );
+#endif
+
+    //  In move state draw the crosshair
+    if ( iState == ERedEyeReductionStateMoveCrosshair )
+    {
+		//  Get graphics context
+		CWindowGc & gc = SystemGc();
+
+		gc.SetPenStyle (CGraphicsContext::ENullPen);
+		gc.SetBrushStyle (CGraphicsContext::ENullBrush);
+
+        TSize chSize = iCrossHair->SizeInPixels();
+		TPoint center = CursorLocation();
+        gc.BitBltMasked (
+            TPoint(center.iX - (chSize.iWidth >> 1), center.iY - (chSize.iHeight >> 1)), 
+            iCrossHair, 
+            TRect (chSize), 
+            iCrossHairMask, 
+            EFalse
+            );
+    }
+
+    // In resize state draw the selection circle
+    else if ( iState == ERedEyeReductionStateResizeSelection )
+    {
+		DrawDancingAntz(Rect());
+    }
+}
+
+//=============================================================================
+void CImageEditorRedEyeReductionControl::DrawDancingAntz (const TRect & /*aRect*/) const
+{
+	//  Get graphics context
+    CWindowGc & gc = SystemGc();
+
+    //  Compute center point of the area
+    TPoint center = CursorLocation();
+
+    //  Compute selection rectangle
+    TRect rect ( SelectionRect( center ) ); 
+
+    //  Draw the "dancing ants" ellipse
+	gc.SetDrawMode (CGraphicsContext::EDrawModePEN);
+    gc.SetBrushStyle (CGraphicsContext::ENullBrush);
+    gc.SetBrushColor (KRgbBlack);
+	
+	//	Draw 
+    gc.SetPenStyle (CGraphicsContext::ESolidPen);
+	gc.SetPenColor ((iAntFlag) ? (KRgbBlack) : (KRgbWhite));
+    gc.DrawEllipse (rect);
+    
+	//	Draw dashed line
+	gc.SetPenStyle (CGraphicsContext::EDashedPen);
+	gc.SetPenColor ((iAntFlag) ? (KRgbWhite) : (KRgbBlack));
+    gc.DrawEllipse (rect);
+
+}
+
+//=============================================================================
+void CImageEditorRedEyeReductionControl::UndoL()
+    {
+    TInt count = iUndoArray.Count();
+
+    LOGFMT( KRedEyeReductionPluginLogFile, "CImageEditorRedEyeReductionControl::UndoL(): iUndoArray.Count() == %d", count );
+
+    switch (iState) 
+        {
+        case ERedEyeReductionStateMoveCrosshair:
+            {
+            if ( count > 0 )
+                {
+    			// Remove the latest selected red eye area
+                // (It would be possible to set the cursor back to the point 
+                //  which was the location of the previous eye, but that 
+                // depends also on the zoom and pan values, which are not 
+                // available for plugins)
+                iUndoArray.Remove( count - 1 );
+
+    			// Undo the filter
+    			iEditorView->HandleCommandL (EImageEditorUndoFilter);
+                
+    			if ( iUndoArray.Count() == 0)
+			        {
+                    // One filter is added already when opening the plugin. If 
+                    // this initial filter is undone, we need to create a new one.
+    				iEditorView->HandleCommandL (EImageEditorStoreParameters);
+    				iEditorView->HandleCommandL (EImageEditorAddFilterToEngine);
+
+			        }
+                else
+                    {
+                    // Restore parameters
+                    iRedEyeRect = iUndoArray[ count - 2 ];
+                    }
+                }
+            break;
+            }
+        case ERedEyeReductionStateResizeSelection:
+            {
+        
+#ifdef __TOUCH_ONLY_DEVICE_RER_PLUGIN_ACTION__  
+            // in touch-only device do the same thing here in resize state as 
+            // in non-touch device in move state->remove/undo filter 
+            if ( count > 0 )
+                {
+                    		
+            iUndoArray.Remove( count - 1 );
+
+    		// Undo the filter
+    		iEditorView->HandleCommandL (EImageEditorUndoFilter);
+            
+    			if ( iUndoArray.Count() == 0)
+    		        {
+                    // One filter is added already when opening the plugin. If this
+                    // initial filter is undone, we need to create a new one.
+    				iEditorView->HandleCommandL (EImageEditorStoreParameters);
+    				iEditorView->HandleCommandL (EImageEditorAddFilterToEngine);
+
+    		        }
+                else
+                    {
+                    // Restore parameters
+                    iRedEyeRect = iUndoArray[ count - 2 ];
+                    }
+                }
+
+#else 
+                
+            // In the resize state consider that undo means
+            // going back to the move crosshair state (non-touch)
+            ToMoveStateL();
+#endif                                   
+                                   
+            break;
+            }
+        
+        default:
+            {
+            ASSERT( EFalse );
+            break;
+            }
+        }
+
+    DrawNow();
+    }
+    
+
+//=============================================================================
+void CImageEditorRedEyeReductionControl::NaviDown()
+{
+    switch (iState) 
+    {
+    case ERedEyeReductionStateMoveCrosshair:
+        {
+            iY += (KPosParamStep * iNaviStepMultiplier);
+            if (iY > KPosParamMax)
+            {
+                iY = KPosParamMax;
+            }
+            break;
+        }
+    case ERedEyeReductionStateResizeSelection:
+        {
+            iR -= (KRadiusParamStep * iNaviStepMultiplier);
+            if (iR < KRadiusParamMin)
+            {
+                iR = KRadiusParamMin;
+            }
+            break;
+        }
+    default:
+        {
+            ASSERT( EFalse );
+            break;
+        }
+    }
+}
+
+//=============================================================================
+void CImageEditorRedEyeReductionControl::NaviUp()
+{
+    switch (iState) 
+    {
+    case ERedEyeReductionStateMoveCrosshair:
+        {
+            iY -= (KPosParamStep * iNaviStepMultiplier);
+            if (iY < KPosParamMin)
+            {
+                iY = KPosParamMin;
+            }
+            break;
+        }
+    case ERedEyeReductionStateResizeSelection:
+        {
+            iR += (KRadiusParamStep * iNaviStepMultiplier);
+            if (iR > KRadiusParamMax)
+            {
+                iR = KRadiusParamMax;
+            }
+            break;
+        }
+    default:
+        {
+            break;
+        } 
+    }
+}
+
+//=============================================================================
+void CImageEditorRedEyeReductionControl::NaviRight()
+{
+    switch (iState) 
+    {
+	case ERedEyeReductionStateMoveCrosshair:
+        {
+            iX += (KPosParamStep * iNaviStepMultiplier);
+            if (iX > KPosParamMax)
+            {
+                iX = KPosParamMax;
+            }
+            break;
+        }
+	case ERedEyeReductionStateResizeSelection:
+        {
+            iR += (KRadiusParamStep * iNaviStepMultiplier);
+            if (iR > KRadiusParamMax)
+            {
+                iR = KRadiusParamMax;
+            }
+            break;
+        }
+	default:
+        {
+            break;
+        }
+    }
+}
+
+//=============================================================================
+void CImageEditorRedEyeReductionControl::NaviLeft()
+{
+    switch (iState) 
+    {
+    case ERedEyeReductionStateMoveCrosshair:
+        {
+            iX -= (KPosParamStep * iNaviStepMultiplier);
+            if (iX < KPosParamMin)
+            {
+                iX = KPosParamMin;
+            }
+    	    break;
+        }
+    case ERedEyeReductionStateResizeSelection:
+        {
+            iR -= (KRadiusParamStep * iNaviStepMultiplier);
+            if (iR < KRadiusParamMin)
+            {
+                iR = KRadiusParamMin;
+            }
+            break;
+        }
+    default:
+        {
+    	    break;
+        }
+    }
+}
+
+//=============================================================================
+void CImageEditorRedEyeReductionControl::KeyOkL()
+{
+    switch (iState) 
+    {
+    case ERedEyeReductionStateMoveCrosshair:
+        {
+            ToResizeStateL();
+            break;
+        }
+    case ERedEyeReductionStateResizeSelection:
+        {
+            if ( iUndoArray.Count() > 0)
+            {
+			    AddFilterToEngineL();
+            }
+			else
+			{
+
+                // Update the filter parameters
+                ComputeParams();
+
+                // Store coodinates
+                iUndoArray.Append( iRedEyeRect );
+
+				// Render 
+				iEditorView->HandleCommandL (EImageEditorCmdRender);
+			}
+
+			
+#ifdef __TOUCH_ONLY_DEVICE_RER_PLUGIN_ACTION__ 
+            // Loop only inside Resize state in touch-only devices
+            ToResizeStateL();            
+
+#else
+            
+            // Go back to move state (non-touch)                
+            ToMoveStateL();
+#endif                
+			                          
+            break;
+        }
+
+    case ERedEyeReductionStateDone:
+        {
+            if ( iUndoArray.Count() > 0)
+            {
+			    AddFilterToEngineL();
+            }
+			else
+            {            	
+                // Update the filter parameters
+                ComputeParams();
+
+                // Store coodinates
+                iUndoArray.Append( iRedEyeRect );
+                                
+                // Render 
+            	iEditorView->HandleCommandL (EImageEditorCmdRender);
+			
+			}
+            break;
+        }
+
+    default:
+        {
+            break;
+        }
+    }
+}
+
+//=============================================================================
+void CImageEditorRedEyeReductionControl::CancelPluginL()
+{
+    LOG( KRedEyeReductionPluginLogFile, "CImageEditorRedEyeReductionControl::CancelPluginL" );
+
+    iState = ERedEyeReductionStateMin;
+
+    // Undo all the filters exept for the first one,
+    // which is cancelled by the framework.
+    TInt count = iUndoArray.Count();
+    while ( count > 1) 
+    {
+        iEditorView->HandleCommandL (EImageEditorUndoFilter);
+        count--;
+    }
+
+    iEditorView->HandleCommandL (EImageEditorCancelPlugin);
+}
+
+//=============================================================================
+void CImageEditorRedEyeReductionControl::ToMoveStateL()
+{
+	LOG( KRedEyeReductionPluginLogFile, "CImageEditorRedEyeReductionControl::ToMoveState" );
+
+	// Stop dancing antz timer
+	if (iTimer)
+	{
+		iTimer->Cancel();
+	}
+
+    // Update navi pane text
+    iState = ERedEyeReductionStateMoveCrosshair;
+    iNaviPaneText.Copy ( iItem->Parameters()[KMoveSelectionIndex] );
+    iEditorView->HandleCommandL (EImageEditorUpdateNavipane);
+    // Update softkeys
+    iEditorView->HandleCommandL (EImageEditorUpdateSoftkeys);
+
+	ShowTooltip();
+}
+
+//=============================================================================
+void CImageEditorRedEyeReductionControl::ToResizeStateL()
+{
+	LOG( KRedEyeReductionPluginLogFile, "CImageEditorRedEyeReductionControl::ToResizeState" );
+
+    // Start the timer
+    StartDancingAntzTimer();
+
+    // Reset the selection radius
+    iR = KRadiusParamDef;
+
+    // Update navi pane text
+    iState = ERedEyeReductionStateResizeSelection;
+    iNaviPaneText.Copy ( iItem->Parameters()[KResizeSelectionIndex] );
+    iEditorView->HandleCommandL (EImageEditorUpdateNavipane);
+
+    // Update softkeys
+    iEditorView->HandleCommandL (EImageEditorUpdateSoftkeys);
+
+	ShowTooltip();
+}
+
+//=============================================================================
+TPoint CImageEditorRedEyeReductionControl::CursorLocation() const
+{
+    __ASSERT_ALWAYS( iVisibleImageRectPrev, User::Panic(KComponentName, KErrNotReady) );
+	TInt x = (TInt) (iX * (iVisibleImageRectPrev->Width())) + iVisibleImageRectPrev->iTl.iX;
+	TInt y = (TInt) (iY * (iVisibleImageRectPrev->Height())) + iVisibleImageRectPrev->iTl.iY;
+    return TPoint( x, y );
+}
+
+//=============================================================================
+TRect CImageEditorRedEyeReductionControl::SelectionRect( const TPoint& aCenter ) const
+{
+    __ASSERT_ALWAYS( iVisibleImageRectPrev, User::Panic(KComponentName, KErrNotReady) );
+
+    // Radius iR is relative to the real image's x dimension.
+    // To obtain a circe, y-dimenson must be scaled accordingly.
+    TInt vpWidth = (iVisibleImageRect->iBr.iX - iVisibleImageRect->iTl.iX);
+    TInt vpHeight = (iVisibleImageRect->iBr.iY - iVisibleImageRect->iTl.iY);
+    TReal xyRatio = (TReal) vpHeight / vpWidth;
+
+    //  Compute rectangle inside the image area
+    TInt width = iVisibleImageRectPrev->Width();
+    TInt height = iVisibleImageRectPrev->Height();
+
+    TInt ulc = aCenter.iX - (TInt)( iR * width + 0.5 );           // upper left corner x
+    TInt ulr = aCenter.iY - (TInt)( iR * height / xyRatio + 0.5); // upper left corner y
+    TInt lrc = aCenter.iX + (TInt)( iR * width + 0.5 );           // lower right corner x
+    TInt lrr = aCenter.iY + (TInt)( iR * height / xyRatio + 0.5); // lower right corner y
+
+    return TRect ( ulc, ulr, lrc, lrr );
+}
+
+//=============================================================================
+void CImageEditorRedEyeReductionControl::ComputeParams()
+{
+    LOG( KRedEyeReductionPluginLogFile, "CImageEditorRedEyeReductionControl::ComputeParams()" );
+
+    __ASSERT_ALWAYS( iVisibleImageRect, User::Panic(KComponentName, KErrNotReady) );
+
+    // Compute the coordinates
+
+    TInt vpWidth = iVisibleImageRect->iBr.iX - iVisibleImageRect->iTl.iX;
+    TInt vpHeight = iVisibleImageRect->iBr.iY - iVisibleImageRect->iTl.iY;
+
+    TInt r      = (TInt) (iR * vpWidth + 0.5);
+    TInt ulc    = (TInt) (iX * vpWidth + 0.5 ) - r;
+    TInt ulr    = (TInt) (iY * vpHeight + 0.5 ) - r;
+    TInt side   = (TInt) (2 * iR * vpWidth + 0.5);
+
+    // Set the filter parameters.
+    // The coordinates iX and iR are relative to the viewport image,
+    // whereas the filter parameters are relative to the source image.
+   	iRedEyeRect.iTl.iX = iVisibleImageRect->iTl.iX + ulc;
+    iRedEyeRect.iTl.iY = iVisibleImageRect->iTl.iY + ulr;
+    iRedEyeRect.iBr.iX = iRedEyeRect.iTl.iX + side;
+    iRedEyeRect.iBr.iY = iRedEyeRect.iTl.iY + side;
+
+    iReadyToRender = ETrue;   
+}
+
+//=============================================================================
+void CImageEditorRedEyeReductionControl::AddFilterToEngineL()
+{
+    LOG( KRedEyeReductionPluginLogFile, "CImageEditorRedEyeReductionControl::AddFilterToEngineL" );
+
+    // Update the filter parameters
+    ComputeParams();
+
+    // Store coodinates for undo
+    iUndoArray.Append( iRedEyeRect );
+
+   	// Force adding the filter to the engine. This includes setting the undo point.
+	iEditorView->HandleCommandL (EImageEditorAddFilterToEngine);
+	iEditorView->HandleCommandL (EImageEditorStoreParameters);
+
+    // Render 
+	iEditorView->HandleCommandL (EImageEditorCmdRender);
+}
+
+//=============================================================================
+void CImageEditorRedEyeReductionControl::StartDancingAntzTimer()
+{
+    LOG( KRedEyeReductionPluginLogFile, "CImageEditorRedEyeReductionControl::StartDancingAntzTimer()" );
+
+    iNaviStepMultiplier = KDefaultSmallNavigationStepMultiplier;
+
+	if (iTimer)
+	{
+        iTimer->Cancel();
+		iTimer->Start(
+			TTimeIntervalMicroSeconds32 (KDancingAntzTimerDelayInMicroseconds),
+			TTimeIntervalMicroSeconds32 (KDancingAntzTimerIntervalInMicroseconds),
+			TCallBack (DancingAntzCallback, this)
+			);
+	}
+}
+
+//=============================================================================
+void CImageEditorRedEyeReductionControl::StartFastKeyTimer()
+{
+    LOG( KRedEyeReductionPluginLogFile, "CImageEditorRedEyeReductionControl::StartFastKeyTimer()" );
+
+    iNaviStepMultiplier = KDefaultSmallNavigationStepMultiplier;
+    iTickCount = 0;
+
+	if (iTimer)
+	{
+		iTimer->Cancel();
+		iTimer->Start(
+			TTimeIntervalMicroSeconds32 (KRedEyeFastKeyTimerDelayInMicroseconds),
+			TTimeIntervalMicroSeconds32 (KRedEyeFastKeyTimerIntervalInMicroseconds),
+			TCallBack (FastKeyCallback, this)
+			);
+	}
+}
+
+//=============================================================================
+void CImageEditorRedEyeReductionControl::OnDancingAntzCallBack()
+{
+	iAntFlag = !iAntFlag;
+	ActivateGc();
+	DrawDancingAntz (Rect());
+	DeactivateGc();
+}
+
+//=============================================================================
+void CImageEditorRedEyeReductionControl::OnFastKeyCallBackL()
+{
+#ifdef VERBOSE
+    LOGFMT2( KRedEyeReductionPluginLogFile, "CImageEditorRedEyeReductionControl::OnFastKeyCallBackL: iNaviStepMultiplier: %d, iTickCount: %d", iNaviStepMultiplier, iTickCount );
+#endif
+
+    if (iTickCount > KRedEyeFastKeyTimerMultiplyThresholdInTicks)
+    {
+        iNaviStepMultiplier = KRedEyeBigNavigationStepMultiplier;
+        LOG( KRedEyeReductionPluginLogFile, "CImageEditorRedEyeReductionControl::OnFastKeyCallBackL: switching to big steps" );
+    }
+    else
+    {
+        iTickCount++;
+    }
+
+    iHandleEventKeys = EFalse;
+
+	switch (iPressedKeyScanCode)
+	{
+		case EStdKeyDownArrow:
+		{
+            NaviDown();
+			break;
+		}
+		case EStdKeyUpArrow:
+		{
+            NaviUp();
+			break;
+		}
+		case EStdKeyLeftArrow:
+		{
+			NaviLeft();
+			break;
+		}
+		case EStdKeyRightArrow:
+		{
+            NaviRight();
+			break;
+		}
+        default:
+            break;
+	}
+	DrawNow();
+}
+
+//=============================================================================
+TBool CImageEditorRedEyeReductionControl::IsReadyToRender() const
+{
+    return iReadyToRender;
+}
+
+//=============================================================================
+void CImageEditorRedEyeReductionControl::GetHelpContext(TCoeHelpContext& aContext) const
+{
+    aContext.iMajor = TUid::Uid(UID_IMAGE_EDITOR);
+    aContext.iContext = KSIE_HLP_REDEYE;
+}
+
+//=============================================================================
+void CImageEditorRedEyeReductionControl::ClipPosition()
+{
+    if (iX < KPosParamMin)
+    {
+        iX = KPosParamMin;
+    }
+    else if (iX > KPosParamMax)
+    {
+        iX = KPosParamMax;
+    }
+
+    if (iY < KPosParamMin)
+    {
+        iY = KPosParamMin;
+    }
+    else if (iY > KPosParamMax)
+    {
+        iY = KPosParamMax;
+    }
+}
+
+//=============================================================================
+void CImageEditorRedEyeReductionControl::HandlePointerEventL(
+                                            const TPointerEvent &aPointerEvent)
+    {        
+    if( AknLayoutUtils::PenEnabled() )
+		{		
+		TBool drawNow ( EFalse );
+		switch( aPointerEvent.iType )
+			{
+			case TPointerEvent::EButton1Down:
+				{
+				iPopupController->HideInfoPopupNote();
+			    // Enable dragging if in cursor area tapped 
+			    // (both move and resize cases)
+			    if ( CursorTapped( aPointerEvent.iPosition ) )
+			        {			        
+			        iCursorDragEnabled = ETrue;
+			        drawNow = EFalse;
+			        }
+			    else if ( iState == ERedEyeReductionStateResizeSelection )
+			        {			        
+			        // Tapping outside cursor area just stores the pointer
+			        // position
+			        if ( !CursorTapped( aPointerEvent.iPosition ) )
+			            {
+			            iPointerPosition = aPointerEvent.iPosition;
+			            drawNow = EFalse;
+			            }    
+			        }
+				
+#ifdef RD_TACTILE_FEEDBACK
+				if ( iTouchFeedBack )
+					{
+					iTouchFeedBack->InstantFeedback( ETouchFeedbackBasic );
+					RDebug::Printf( "ImageEditor::ImageEditorRedEyeReductionControl: ETouchFeedback" );
+					}
+#endif /* RD_TACTILE_FEEDBACK  */
+			    
+				break;
+				}
+			case TPointerEvent::EDrag:
+				{
+				// Sets the new cursor position when drag is enabled
+				// (i.e. EButton1Down has happened in cursor area)
+                if ( ( iState == ERedEyeReductionStateMoveCrosshair || 
+                       iState ==ERedEyeReductionStateResizeSelection ) 
+                       && iCursorDragEnabled )
+                    {
+                    SetCursorPosition( aPointerEvent.iPosition );
+			    	// prevents user to move cursor outside image area
+			    	ClipPosition();	
+			    	drawNow = ETrue;	    
+                    }
+                    
+                // Selection cursor can be grown or made smaller moving
+                // pen up and down outside the cursor area
+                if ( iState == ERedEyeReductionStateResizeSelection && 
+                     !iCursorDragEnabled )
+                    {                    
+                    if ( CalculateResize( iPointerPosition, 
+				                          aPointerEvent.iPosition ) )
+                        {
+                        iPointerPosition = aPointerEvent.iPosition;
+                        drawNow = ETrue;
+                        }
+                    else
+                        {
+                        drawNow = EFalse;
+                        }    
+                    }    
+                                                            
+				break;		
+				}
+			case TPointerEvent::EButton1Up:
+				{
+				// Sets crosshair cursor to a new position
+				if ( iState == ERedEyeReductionStateMoveCrosshair )
+				    {
+				    SetCursorPosition( aPointerEvent.iPosition );
+			    	ClipPosition();
+			    	drawNow = ETrue;
+				    }
+			
+				ShowTooltip();
+				    
+				iCursorDragEnabled = EFalse;    
+				break;
+				}
+						
+			default:
+				{
+				break;	
+				}	
+			}
+	
+		CCoeControl::HandlePointerEventL( aPointerEvent );
+    
+        if ( drawNow ) 
+            {
+            DrawNow();    
+            }	
+		}
+    }
+
+//=============================================================================    
+void CImageEditorRedEyeReductionControl::SetCursorPosition( TPoint aNewPosition )
+    {    
+    //Set new x value
+    iX = TReal( aNewPosition.iX - iVisibleImageRectPrev->iTl.iX ) /
+			  ( iVisibleImageRectPrev->iBr.iX - iVisibleImageRectPrev->iTl.iX );
+    
+    //Set new y value
+    iY = TReal( aNewPosition.iY - iVisibleImageRectPrev->iTl.iY  ) /
+			  ( iVisibleImageRectPrev->iBr.iY - iVisibleImageRectPrev->iTl.iY ); 
+    }
+
+
+//=============================================================================    
+TRect CImageEditorRedEyeReductionControl::CrossHairCursorRect() const
+    {   
+     
+    TSize chSize = iCrossHair->SizeInPixels();
+	TPoint center = CursorLocation();
+    TPoint topLeftCorner(center.iX - (chSize.iWidth >> 1), 
+                         center.iY - (chSize.iHeight >> 1));
+    
+    TRect moveCursorRect( topLeftCorner, chSize );
+    
+    return moveCursorRect;
+    
+    }
+    
+//=============================================================================
+TBool CImageEditorRedEyeReductionControl::CursorTapped( TPoint aTappedPosition ) const
+    {
+    TBool cursorTapped( EFalse );
+    TRect cursorRect;
+    
+    if ( iState == ERedEyeReductionStateMoveCrosshair )
+        {
+		cursorRect = CrossHairCursorRect();
+		
+		TPoint newTLCorner = TPoint( cursorRect.iTl.iX - ( cursorRect.Width() / 2 ),
+		                             cursorRect.iTl.iY - ( cursorRect.Height() / 2 ) );		                             
+		TPoint newBRCorner = TPoint( cursorRect.iBr.iX + ( cursorRect.Width() / 2 ),
+		                             cursorRect.iBr.iY + ( cursorRect.Height() / 2 ));
+		
+		// Make tappable rect double sized to crosshair rect
+		TRect doubleCursorRect = TRect( newTLCorner, newBRCorner );
+		
+		cursorTapped = doubleCursorRect.Contains( aTappedPosition );
+		}
+	else if ( iState == ERedEyeReductionStateResizeSelection )
+	    {
+		cursorRect = SelectionRect( CursorLocation() );
+		cursorTapped = cursorRect.Contains( aTappedPosition );
+		}
+		
+    return cursorTapped;
+    } 
+
+//=============================================================================    
+void CImageEditorRedEyeReductionControl::ShowTooltip()
+    {   
+    iPopupController->HideInfoPopupNote();
+    
+    if ( iState == ERedEyeReductionStateMoveCrosshair )
+        { 
+        TPoint center = CursorLocation();
+        SDrawUtils::ShowToolTip( iPopupController,
+                                 this,
+                                 center,
+                                 EHLeftVBottom,
+                                 *iTooltipLocate );
+        }
+    else if ( iState == ERedEyeReductionStateResizeSelection )
+        {
+        TRect circleRect ( SelectionRect( CursorLocation() ) );
+        TPoint center( circleRect.Center() );
+        
+        SDrawUtils::ShowToolTip( iPopupController,
+                                 this,
+                                 center,
+                                 EHLeftVBottom,
+                                 *iTooltipOutline );
+        }
+    }
+
+//=============================================================================
+TBool CImageEditorRedEyeReductionControl::CalculateResize( TPoint aStartPoint, 
+                                                  TPoint aEndPoint )
+    {
+    // Whether bubble is resized in this function or not
+    TBool radiusChanged( EFalse );
+    // Store old scale value
+    TReal oldRadius = iR;
+    TReal changeThreshold( 0.001 );  
+    
+    // Get system parameters
+    TRect visibleImageRectPrev( iSysPars->VisibleImageRectPrev() );
+            
+    // Compute change on the screen
+    TInt deltaX = aEndPoint.iX - aStartPoint.iX;
+    TInt deltaY = aEndPoint.iY - aStartPoint.iY;
+   	
+   	// Use bigger dimension
+	TInt maxChangeInPixels;
+	if ( visibleImageRectPrev.Height() > visibleImageRectPrev.Width() )
+	    {
+	    maxChangeInPixels = visibleImageRectPrev.Height();
+	    }
+	else
+	    {
+	    maxChangeInPixels = visibleImageRectPrev.Width();
+	    }
+	  
+	TInt oneStepInPixels =  maxChangeInPixels / KTouchScaleMaxStepCount;
+	TReal scaleStep = ( KRadiusParamMax - KRadiusParamMin ) / KTouchScaleMaxStepCount;
+
+    // Relates to second and fourth corners. Defines how steep/gentle the 
+    // moving angle has to be in order to scale.
+    TInt slopeAngleFactor = 3;
+    
+    // The first quarter (movement towards upper-right corner)
+    if( ( deltaX > 0 && deltaY <= 0 ) || ( deltaX >= 0 && deltaY < 0 ) )
+        {
+        // use bigger value
+        if (Abs( deltaX ) >= Abs( deltaY) )
+            {
+            iR += scaleStep * ( Abs( deltaX ) / oneStepInPixels );
+            }
+        else
+            {
+            iR += scaleStep * ( Abs( deltaY ) / oneStepInPixels );
+            }				                             
+        }
+    // The second (movement towards lower-right corner)  	
+    else if( ( deltaX > 0 && deltaY >= 0 ) || ( deltaX >= 0 && deltaY > 0 ) )
+        {
+        if( deltaX > slopeAngleFactor * deltaY )
+            {			                
+	        iR += scaleStep * ( Abs( deltaX ) / oneStepInPixels );    
+            }
+	        			               
+        else if ( slopeAngleFactor * deltaX < deltaY )
+            {			              
+	        iR -= scaleStep * ( Abs( deltaY ) / oneStepInPixels ); 
+	        }
+        }    
+    // The third (movement towards lower-left corner)
+    else if( ( deltaX < 0 && deltaY >= 0 ) || ( deltaX <= 0 && deltaY > 0 ) )
+        {
+        if (Abs( deltaX ) >= Abs( deltaY) )
+            {
+            iR -= scaleStep * ( Abs( deltaX ) / oneStepInPixels );    
+            }
+        else
+            {
+            iR -= scaleStep * ( Abs( deltaY ) / oneStepInPixels ); 
+            }
+        }
+    // The fourth (movement towards upper-left corner)
+    else if( ( deltaX < 0 && deltaY <= 0 ) || ( deltaX <= 0 && deltaY < 0 ) )
+        {
+        if( slopeAngleFactor * Abs( deltaX ) < Abs( deltaY ) )
+            {
+            iR += scaleStep * ( Abs( deltaY ) / oneStepInPixels ); 
+            }
+        else if ( Abs( deltaX ) > slopeAngleFactor * Abs( deltaY ) )
+            {
+            iR -= scaleStep * ( Abs( deltaX ) / oneStepInPixels );    
+	        }
+        }
+    
+    // Check the limits        
+    if (iR > KRadiusParamMax)
+        {
+        iR = KRadiusParamMax;
+        radiusChanged = ETrue;
+        }
+    
+    if (iR < KRadiusParamMin)
+        {
+        iR = KRadiusParamMin;
+        radiusChanged = ETrue;
+        }
+                                
+    if ( Abs( oldRadius - iR ) > changeThreshold )
+        {
+        radiusChanged = ETrue;
+        }
+        
+    return radiusChanged;
+    
+    }    
+// End of File