--- a/browsercore/core/webdirectionalnavigation.cpp Fri Jun 11 16:23:26 2010 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,403 +0,0 @@
-/*
-* Copyright (c) 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:
-*
-*/
-
-
-#include "qmath.h"
-#include "qpainter.h"
-#include "qwebpage.h"
-#include "qwebview.h"
-#include "qwebframe.h"
-#include "qwebelement.h"
-#include "webdirectionalnavigation.h"
-
-namespace WRT {
-
-const int KInitialSize = 20;
-const int KNormalScrollRange = 40;
-const int KFullStep = 14;
-const double KMaxDistance = 1000000;
-
-/*!
- \class WebDirectionalNavigation
- \since cwrt 1.0
- \brief cwrt navigation.
-
- \sa WebNavigation, WebTouchNavigation, WebCursorNavigation, WebHtmlTabIndexedNavigation
-*/
-WebDirectionalNavigation::WebDirectionalNavigation(QWebPage* webPage,QObject* view) :
- m_webPage(webPage)
-, m_view(view)
-{
- install();
-}
-
-WebDirectionalNavigation::~WebDirectionalNavigation()
-{
- uninstall();
-}
-
-void WebDirectionalNavigation::install()
-{
- m_view->installEventFilter(this);
- //initiallayoutCompleted();
-}
-
-void WebDirectionalNavigation::uninstall()
-{
- if (m_view)
- m_view->removeEventFilter(this);
-}
-
-void WebDirectionalNavigation::initiallayoutCompleted()
-{
- m_webElement = m_webPage->currentFrame()->findFirstElement(QString("a,input,select,textarea,object"));
- if (!m_webElement.isNull()) {
- m_webElement.setFocus();
- m_focusPoint = m_webElement.geometry().topLeft();
- setCurrentFrameScrollPosition(m_focusPoint);
- }
-}
-
-double WebDirectionalNavigation::calculateElementDistance(int direction, const QRect& possibleRect)
-{
- // Roughly based on this algorithm http://www.w3.org/TR/WICD/#nav-distance-fkt
- // Deviates in that the overlap is not calculated. Instead, if there is any overlap
- // selection is restricted to x or y direction only. This helps for differnt size elments
- // all lying on the same plane, but might mess up backtracking the naviation path.
-
- QRect focusedRect(0,0,1,1);
- if (!m_webElement.isNull())
- focusedRect = QRect(m_webElement.geometry());
-
- //calculate the next focuspoint
- switch (direction) {
- case Qt::Key_Up:
- if (m_focusPoint.x() < focusedRect.x())
- m_focusPoint.setX(focusedRect.x());
- else if (m_focusPoint.x() > focusedRect.right())
- m_focusPoint.setX(focusedRect.right());
- m_focusPoint.setY(focusedRect.y());
- break;
- case Qt::Key_Down:
- if (m_focusPoint.x() < focusedRect.x())
- m_focusPoint.setX(focusedRect.x());
- else if (m_focusPoint.x() > focusedRect.right())
- m_focusPoint.setX(focusedRect.right());
- m_focusPoint.setY(focusedRect.bottom());
- break;
- case Qt::Key_Right:
- m_focusPoint.setX(focusedRect.right());
- if (m_focusPoint.y() < focusedRect.y())
- m_focusPoint.setY(focusedRect.y());
- else if (m_focusPoint.y() > focusedRect.bottom())
- m_focusPoint.setY(focusedRect.bottom());
- break;
- case Qt::Key_Left:
- m_focusPoint.setX(focusedRect.x());
- if (m_focusPoint.y() < focusedRect.y())
- m_focusPoint.setY(focusedRect.y());
- else if (m_focusPoint.y() > focusedRect.bottom())
- m_focusPoint.setY(focusedRect.bottom());
- break;
- }
-
- // Make sure the rectangle falls within the search area
- if (direction == Qt::Key_Up && possibleRect.bottom() > m_focusPoint.y()
- || direction == Qt::Key_Down && possibleRect.y() < m_focusPoint.y()
- || direction == Qt::Key_Right && possibleRect.x() < m_focusPoint.x()
- || direction == Qt::Key_Left && possibleRect.right() > m_focusPoint.x())
- return KMaxDistance;
-
- // The absolute distance (dx or dy) on the navigation axis between the opposing edges of the currently focused
- // element and each of the candidates.
- double distanceX = 0;
- double distanceY = 0;
-
- if (direction == Qt::Key_Up) {
- // adjust the x distance based on the closest edge
- if (m_focusPoint.x() < possibleRect.x())
- distanceX = possibleRect.x() - m_focusPoint.x();
- else if (m_focusPoint.x() > possibleRect.right())
- distanceX = m_focusPoint.x() - possibleRect.right();
- distanceY = m_focusPoint.y() - possibleRect.bottom();
- } else if (direction == Qt::Key_Down) {
- // adjust the x distance based on the closest edge
- if (m_focusPoint.x() < possibleRect.x())
- distanceX = possibleRect.x() - m_focusPoint.x();
- else if (m_focusPoint.x() > possibleRect.right())
- distanceX = m_focusPoint.x() - possibleRect.right();
- distanceY = possibleRect.y() - m_focusPoint.y();
- } else if (direction == Qt::Key_Right) {
- distanceX = possibleRect.x() - m_focusPoint.x();
- // adjust the y distance based on the closest edge
- if (m_focusPoint.y() < possibleRect.y())
- distanceY = possibleRect.y() - m_focusPoint.y();
- else if (m_focusPoint.y() > possibleRect.bottom())
- distanceY = m_focusPoint.y() - possibleRect.bottom();
- } else if (direction == Qt::Key_Left) {
- distanceX = m_focusPoint.x() - possibleRect.right();
- // adjust the y distance based on the closest edge
- if (m_focusPoint.y() < possibleRect.y())
- distanceY = possibleRect.y() - m_focusPoint.y();
- else if (m_focusPoint.y() > possibleRect.bottom())
- distanceY = m_focusPoint.y() - possibleRect.bottom();
- }
-
- // The absolute distance on the axis orthogonal to the navigation axis between
- // the opposing edges of currently focused element and each of candidates
- double displacement = 0;
-
- // The euclidean distance
- double euclideanDist = sqrt(distanceX * distanceX + distanceY * distanceY);
-
- // Area of the document to search
- QRect searchRect(m_webPage->currentFrame()->scrollPosition(),m_webPage->viewportSize());
-
- if (direction == Qt::Key_Up || direction == Qt::Key_Down) {
- // if the rectangles are on the same plane set the euclideanDist to zero to favor this navigation
- if ((possibleRect.x() == focusedRect.x())
- || (possibleRect.right() > focusedRect.x() && possibleRect.right() < focusedRect.right())
- || (possibleRect.x() > focusedRect.x() && possibleRect.x() < focusedRect.right())
- || (possibleRect.x() > focusedRect.x() && possibleRect.right() < focusedRect.right())
- || (possibleRect.x() < focusedRect.x() && possibleRect.right() > focusedRect.right())) {
- euclideanDist = 0;
- distanceX = 0;
- } else {
- // displacement is added for being orthogonally far from the current rectangle.
- if (possibleRect.x() > focusedRect.right())
- displacement = possibleRect.x() - focusedRect.right();
- if (possibleRect.right() < focusedRect.x())
- displacement = focusedRect.x() - possibleRect.right();
-
- // This is a little sketchy, but if the rectangles are all
- // touching set the displacment to 1 so rects on the same plane win
- if (displacement == 0)
- displacement = 1;
-
- // if the focus is within the view limit the diagonal search by half the search rectangle
- if (searchRect.intersects(focusedRect) && (displacement > (searchRect.width()/2)))
- return KMaxDistance;
-
- }
-
- } else if (direction == Qt::Key_Left || direction == Qt::Key_Right) {
-
- // if the rectangles are on the same plane set the euclideanDist to zero to favor this navigation
- if ((possibleRect.y() == focusedRect.y())
- || (possibleRect.bottom() > focusedRect.y() && possibleRect.bottom() < focusedRect.bottom())
- || (possibleRect.y() > focusedRect.y() && possibleRect.y() < focusedRect.bottom())
- || (possibleRect.y() > focusedRect.y() && possibleRect.bottom() < focusedRect.bottom())
- || (possibleRect.y() < focusedRect.y() && possibleRect.bottom() > focusedRect.bottom())) {
- euclideanDist = 0;
- distanceY = 0;
- } else {
- // displacement is added for being orthogonally far from the current rectangle.
- if (possibleRect.y() > focusedRect.bottom())
- displacement = possibleRect.y() - focusedRect.bottom();
- if (possibleRect.bottom() < focusedRect.y())
- displacement = focusedRect.y() - possibleRect.bottom();
-
- // This is a little sketchy, but if the rectangles are all
- // touching set the displacment to 1 so rects on the same plane win
- if (displacement == 0)
- displacement = 1;
-
- // if the focus is within the view limit the diagonal search by half the search rectangle
- if (searchRect.intersects(focusedRect) && (displacement > (searchRect.height()/2)))
- return KMaxDistance;
- }
- }
-
- return euclideanDist + distanceX + distanceY + 2 * (displacement);
-}
-
-
-
-bool WebDirectionalNavigation::nextElementInDirection(int direction)
-{
- double bestDistance = KMaxDistance;
- QWebElement bestElement;
-#if QT_VERSION < 0x040600
- QList<QWebElement> elementList = m_webPage->currentFrame()->findAllElements(QString("a,input,select,textarea,object"));
-#else
- QList<QWebElement> elementList = m_webPage->currentFrame()->findAllElements(QString("a,input,select,textarea,object")).toList();
-#endif
- QList<QWebElement>::iterator it;
- for (it = elementList.begin(); it != elementList.end(); it++) {
- QWebElement el(*it);
- QRect nRect(el.geometry());
- if (nRect.isValid()) {
- if (QRect(m_webPage->currentFrame()->scrollPosition(),m_webPage->viewportSize()).intersects(nRect)) {
- double distance = calculateElementDistance (direction, nRect);
- if (bestDistance > distance) {
- bestDistance = distance;
- bestElement = el;
- }
- }
- }
- }
-
- if (!bestElement.isNull() && bestElement != m_webElement) {
- m_webElement.setStyleProperty("outline", m_webElementStyle);
- m_webElement = bestElement;
- m_webElement.setFocus();
- m_webElementStyle = m_webElement.styleProperty("outline", QWebElement::ComputedStyle);
- m_webElement.setStyleProperty("outline", "3px ridge rgb(140,140,255)");
- scrollFrame(direction);
- return true;
- }
-
- scrollFrameOneDirection (direction, KNormalScrollRange);
- return false;
-}
-
-
-bool WebDirectionalNavigation::eventFilter(QObject *object, QEvent *event)
-{
- if (object == m_view) {
- switch (event->type()) {
- case QEvent::KeyPress: {
- QKeyEvent* ev = static_cast<QKeyEvent*>(event);
- if (ev->key() == Qt::Key_Up || ev->key() == Qt::Key_Down
- || ev->key() == Qt::Key_Left || ev->key() == Qt::Key_Right )
- {
- return true;
- }
- if (ev->key() == Qt::Key_Select )
- {
- QKeyEvent rockerEnterEvent(QEvent::KeyPress, Qt::Key_Enter, Qt::NoModifier);
- m_webPage->event(&rockerEnterEvent);
- return true;
- }
- }
- break;
- case QEvent::KeyRelease: {
- QKeyEvent* ev = static_cast<QKeyEvent*>(event);
- if (ev->key() == Qt::Key_Up || ev->key() == Qt::Key_Down
- || ev->key() == Qt::Key_Left || ev->key() == Qt::Key_Right )
- {
- nextElementInDirection(ev->key());
- return true;
- }
- if (ev->key() == Qt::Key_Select )
- {
- QKeyEvent rockerEnterEvent(QEvent::KeyPress, Qt::Key_Enter, Qt::NoModifier);
- m_webPage->event(&rockerEnterEvent);
- return true;
- }
- }
- break;
- default:
- return false;
- break;
- } // end of switch statement
- } // end of if statement
- return false;
-}
-
-
-void WebDirectionalNavigation::scrollFrame(int direction)
-{
-
- int xadjust = m_webPage->viewportSize().width()/5;
- int yadjust = m_webPage->viewportSize().height()/5;
-
- switch (direction) {
- case Qt::Key_Left: {
- int distanceX = xadjust - m_webElement.geometry().x();
- if (distanceX > 0)
- scrollCurrentFrame(-distanceX,0);
- }
- break;
- case Qt::Key_Right: {
- int distanceX = m_webElement.geometry().right() - m_webPage->viewportSize().width()-xadjust;
- if (distanceX > 0)
- scrollCurrentFrame(distanceX,0);
- }
- break;
- case Qt::Key_Up: {
- int distanceY = yadjust - m_webElement.geometry().y();
- if (distanceY > 0)
- scrollCurrentFrame(0,-distanceY);
- }
- break;
- case Qt::Key_Down: {
- int distanceY = m_webElement.geometry().bottom() - m_webPage->viewportSize().height()-yadjust;
- if (distanceY > 0)
- scrollCurrentFrame(0,distanceY);
- }
- break;
- }
-}
-
-void WebDirectionalNavigation::scrollFrameOneDirection (int direction, int distance)
-{
- int dx = 0;
- int dy = 0;
-
- switch (direction) {
- case Qt::Key_Up: {
- dy = -distance;
- }
- break;
- case Qt::Key_Down: {
- dy = +distance;
- }
- break;
- case Qt::Key_Left: {
- dx = -distance;
- }
- break;
- case Qt::Key_Right: {
- dx = distance;
- }
- break;
- default:
- break;
- }
-
- scrollCurrentFrame(dx, dy);
-}
-
-void WebDirectionalNavigation::scrollCurrentFrame (int dx, int dy)
-{
- QPoint scrollPosition = m_webPage->currentFrame()->scrollPosition();
- m_webPage->currentFrame()->scroll(dx, dy);
-
- /* emit pageScrollPositionZero singal if it's mainFrame scrolling or scroll to top*/
- if (m_webPage->currentFrame() == m_webPage->mainFrame()) {
- if (scrollPosition.y() == 0 || m_webPage->currentFrame()->scrollPosition().y() == 0) {
- emit pageScrollPositionZero();
- }
- }
-}
-
-void WebDirectionalNavigation::setCurrentFrameScrollPosition (QPoint& pos)
-{
- QPoint scrollPosition = m_webPage->currentFrame()->scrollPosition();
- m_webPage->currentFrame()->setScrollPosition(pos);
-
- /* emit pageScrollPositionZero singal if it's mainFrame scrolling or scroll to top*/
- if (m_webPage->currentFrame() == m_webPage->mainFrame()) {
- if (scrollPosition.y() == 0 || m_webPage->currentFrame()->scrollPosition().y() == 0) {
- emit pageScrollPositionZero();
- }
- }
-}
-
-}
-