/*
* 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 "WebScrollingDeceleratorGH.h"
#include "WebView.h"
#include "WebFrame.h"
#include "WebFrameView.h"
#include "WebPageScrollHandler.h"
#include "PlatformScrollbar.h"
#include "WebScrollbarDrawer.h"
#include "WebKitLogger.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 = 60000; // scroll timer interval in microseconds
const float KDeccelerationLow = -350.0;
const float KDeccelerationHigh = -600.0;
const float KSpeedHigh = 2000.0;
int decelTimerCB(TAny* ptr);
// ============================ MEMBER FUNCTIONS ===============================
// -----------------------------------------------------------------------------
// WebScrollingDeceleratorGH::NewL
// The two-phase Symbian constructor
// -----------------------------------------------------------------------------
//
WebScrollingDeceleratorGH* WebScrollingDeceleratorGH::NewL(WebView& webView)
{
WebScrollingDeceleratorGH* self = new (ELeave) WebScrollingDeceleratorGH(webView);
CleanupStack::PushL(self);
self->ConstructL();
CleanupStack::Pop(); //self
return self;
}
// -----------------------------------------------------------------------------
// WebScrollingDeceleratorGH::WebScrollingDeceleratorGH
// C++ default constructor can NOT contain any code, that
// might leave.
// -----------------------------------------------------------------------------
//
WebScrollingDeceleratorGH::WebScrollingDeceleratorGH(WebView& webView)
: m_webView( webView )
{
}
// -----------------------------------------------------------------------------
// WebScrollingDeceleratorGH::ConstructL
// -----------------------------------------------------------------------------
void WebScrollingDeceleratorGH::ConstructL()
{
m_decelTimer = CPeriodic::NewL(CActive::EPriorityStandard);
m_deceleration = KDeccelerationHigh;
}
// -----------------------------------------------------------------------------
// Destructor
// -----------------------------------------------------------------------------
WebScrollingDeceleratorGH::~WebScrollingDeceleratorGH()
{
delete m_decelTimer;
}
int WebScrollingDeceleratorGH::getDecceleration()
{
return m_deceleration;
}
int decelTimerCB(TAny* ptr)
{
(static_cast<WebScrollingDeceleratorGH*>(ptr))->scroll();
return false;
}
void WebScrollingDeceleratorGH::cancelDecel()
{
m_decelelatorSwitch = false;
if (m_decelTimer->IsActive()) {
m_webView.setScrolling(false);
m_decelTimer->Cancel();
}
}
void WebScrollingDeceleratorGH::startDecel(TRealPoint& speed, WebScrollbarDrawer* scrollbarDrawer)
{
m_decelelatorSwitch = true;
m_scrollbarDrawer = scrollbarDrawer;
float speedX = speed.iX;
float speedY = speed.iY;
float absSpeedX = abs(speedX);
float absSpeedY = abs(speedY);
if (absSpeedX > KSpeedHigh) {
speedX = KSpeedHigh * speedX/absSpeedX ;
m_deceleration = KDeccelerationLow;
}
if (absSpeedY > KSpeedHigh) {
speedY = KSpeedHigh * speedY/absSpeedY;
m_deceleration = KDeccelerationLow;
}
m_initSpeed.iX = (-1) * speedX;
m_initSpeed.iY = (-1) * speedY;
m_numscrollsteps = 0;
if (m_decelTimer->IsActive()) {
m_webView.setScrolling(false);
m_decelTimer->Cancel();
}
WebFrameView* scrollingView = m_webView.pageScrollHandler()->currentScrollingFrameView();
if (scrollingView) {
m_webView.setScrolling(true);
m_startPos = scrollingView->contentPos();
m_lastPos = m_startPos;
m_decelTimer->Start(0, KScrollIntervalTimeout,
TCallBack(&decelTimerCB, this));
}
}
void WebScrollingDeceleratorGH::scroll()
{
if (!m_decelelatorSwitch) return;
// X = Vst*t - 0.5*a*(t * t)
TPoint dist;
TReal32 intervalInSec = static_cast<TReal32>(KScrollIntervalTimeout) / 1000000;
TReal32 t = (m_numscrollsteps++) * intervalInSec;
TReal32 dx = 0.0;
TReal32 dy = 0.0;
TReal32 vx = 0.0;
TReal32 vy = 0.0;
TReal32 accelX = 0.0;
TReal32 accelY = 0.0;
TReal32 deceleration = getDecceleration();
if (m_initSpeed.iX) {
accelX = (m_initSpeed.iX > 0) ? deceleration : (-1) * deceleration;
vx = m_initSpeed.iX + accelX * t;
dx = m_initSpeed.iX * t + 0.5 * accelX * (t * t);
}
if (m_initSpeed.iY) {
accelY = (m_initSpeed.iY > 0) ? deceleration : (-1) * deceleration;
vy = m_initSpeed.iY + accelY * t;
dy = m_initSpeed.iY * t + 0.5 * accelY * (t * t);
}
dist.SetXY(static_cast<TInt>(dx), static_cast<TInt>(dy));
WebFrameView* scrollingView = m_webView.pageScrollHandler()->currentScrollingFrameView();
TPoint cpos = scrollingView->contentPos();
dist = scrollingView->toDocCoords(dist);
TPoint pos = m_startPos + dist;
WebPageScrollHandler* handler = m_webView.pageScrollHandler();
if ((vx * m_initSpeed.iX < 0) || (vy * m_initSpeed.iY < 0) || (vx + vy == 0) ||
(m_numscrollsteps > 1 && !scrollingView->needScroll(pos) &&
!handler->currentScrollingElement())) {
if (m_scrollbarDrawer) {
m_scrollbarDrawer->fadeScrollbar();
}
m_webView.setScrolling(false);
m_decelTimer->Cancel();
handler->clearScrollingElement();
m_webView.setViewIsScrolling(false);
m_webView.toggleRepaintTimer(true);
}
else {
TPoint scrollDelta = pos - m_lastPos;
handler->scrollContent(scrollDelta);
m_lastPos = pos;
}
}
// End of File