/*
* Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of the License "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 scrolling decelerator
*
*/
// INCLUDE FILES
#include <../bidi.h>
#include "WebScrollingDecelerator.h"
#include "WebView.h"
#include "WebFrame.h"
#include "WebFrameView.h"
#include "WebPageScrollHandler.h"
#include "PlatformScrollbar.h"
// constants
const int KRecordSize = 4;
// The following deceleration curve is generated by a script
// It lists the timeout dt values in microseconds.
const int KDecelCurveSize = 10;
const int KScrollIntervalTimeout = 40000; // scroll timer interval in microseconds
// ============================ MEMBER FUNCTIONS ===============================
// -----------------------------------------------------------------------------
// WebScrollingDecelerator::NewL
// The two-phase Symbian constructor
// -----------------------------------------------------------------------------
//
WebScrollingDecelerator* WebScrollingDecelerator::NewL(WebView& webView)
{
WebScrollingDecelerator* self = new (ELeave) WebScrollingDecelerator(webView);
CleanupStack::PushL(self);
self->ConstructL();
CleanupStack::Pop(); //self
return self;
}
// -----------------------------------------------------------------------------
// WebScrollingDecelerator::WebScrollingDecelerator
// C++ default constructor can NOT contain any code, that
// might leave.
// -----------------------------------------------------------------------------
//
WebScrollingDecelerator::WebScrollingDecelerator(WebView& webView)
: CTimer(EPriorityHigh), m_webView( webView )
{
}
// -----------------------------------------------------------------------------
// WebScrollingDecelerator::ConstructL
// -----------------------------------------------------------------------------
void WebScrollingDecelerator::ConstructL()
{
CTimer::ConstructL();
CActiveScheduler::Add( this );
m_dragPosition.Reset();
}
// -----------------------------------------------------------------------------
// Destructor
// -----------------------------------------------------------------------------
WebScrollingDecelerator::~WebScrollingDecelerator()
{
Cancel();
}
// -----------------------------------------------------------------------------
// WebScrollingDecelerator::updatePos
// update record of position
// -----------------------------------------------------------------------------
//
void WebScrollingDecelerator::updatePos()
{
if (m_dragPosition.Count() >= KRecordSize)
{
// pop item from front
m_dragPosition.Remove(0);
}
// and add this one to the end
TPoint currPosition = m_webView.pageScrollHandler()->currentScrollingFrameView()->contentPos();
m_dragPosition.Append(currPosition);
}
// -----------------------------------------------------------------------------
// WebScrollingDecelerator::startDecel
// initialize and start deceleration
// -----------------------------------------------------------------------------
//
void WebScrollingDecelerator::startDecelL()
{
int count = m_dragPosition.Count();
m_normalizedCurrentPosition.iX = m_webView.pageScrollHandler()->currentScrollingFrameView()->contentPos().iX * 100;
m_normalizedCurrentPosition.iY = m_webView.pageScrollHandler()->currentScrollingFrameView()->contentPos().iY * 100;
if (count > 0)
{
// set the delta based upon the change span of points collected averaged over the span, so long as we have moved
int dx = (m_dragPosition[count - 1].iX - m_dragPosition[0].iX)* 100;
int dy = (m_dragPosition[count - 1].iY - m_dragPosition[0].iY) * 100;
if (abs(dx) > 0 || abs(dy) > 0)
{
m_scrolldelta.SetXY( (dx/count), (dy/count) );
WebFrameView* view = m_webView.pageScrollHandler()->currentScrollingFrameView();
m_scrolldelta = view->toDocCoords(m_scrolldelta);
// init num steps
m_numscrollsteps = 0;
// call the RunL function directly, this first time. CTimer will call it from now on.
m_decelelatorSwitch = ETrue;
RunL();
}
}
m_dragPosition.Reset();
}
// -----------------------------------------------------------------------------
// WebScrollingDecelerator::RunL
// continue deceleration
// -----------------------------------------------------------------------------
//
void WebScrollingDecelerator::RunL()
{
WebFrameView* scrollingView = m_webView.pageScrollHandler()->currentScrollingFrameView();
// use a pre-calulated deceleration curve to calculate dt
if ((m_numscrollsteps >= KDecelCurveSize ) || !m_decelelatorSwitch)
{
// done
Cancel();
m_webView.setViewIsScrolling(false);
return;
}
// step to next
m_numscrollsteps++;
// do the scrolling
if (m_webView.pageScrollHandler() && scrollingView) {
TPoint newpos;
/* With each step decrease m_scrolldelta by 50% */
m_scrolldelta.iX = m_scrolldelta.iX >> 1;
m_scrolldelta.iY = m_scrolldelta.iY >> 1;
m_normalizedCurrentPosition += m_scrolldelta;
newpos.iX = m_normalizedCurrentPosition.iX/100;
newpos.iY = m_normalizedCurrentPosition.iY/100;
scrollingView->scrollTo(newpos);
if (scrollingView->vScrollbar()) {
scrollingView->vScrollbar()->setValue(newpos.iY);
}
if (scrollingView->hScrollbar()) {
scrollingView->hScrollbar()->setValue(newpos.iX);
}
After(KScrollIntervalTimeout);
}
}
// End of File