diff -r e4f038c420f7 -r 3ac3aaebaee5 homescreenapp/hsutils/src/hswidgetpositioningonwidgetadd.cpp --- a/homescreenapp/hsutils/src/hswidgetpositioningonwidgetadd.cpp Mon Sep 13 13:03:23 2010 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,454 +0,0 @@ -/* -* Copyright (c) 2010 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 -#include -#include -#include - -#include - - -#include "hswidgetpositioningonwidgetadd.h" - -const qreal offset = 40; //TODO: Implement this as configurable parameter - - -/*! - \class HsWidgetPositioningOnWidgetAdd - \ingroup group_hsutils - \brief -*/ - -/*! - \class HsWidgetPositioningOnWidgetAdd - \brief Defines widget positioning on widget add. - - Widget positioning on widget add sets positions for - a set of home screen widgets added from application library. -*/ - -/*! - Sets the positioning \a instance as the current one. - Deletes the existing instance if present. -*/ -void HsWidgetPositioningOnWidgetAdd::setInstance( - HsWidgetPositioningOnWidgetAdd *instance) -{ - if (mInstance) - delete mInstance; - mInstance = instance; -} - -/*! - Returns the current positioning instance. -*/ -HsWidgetPositioningOnWidgetAdd *HsWidgetPositioningOnWidgetAdd::instance() -{ - return mInstance; -} - -/*! - Stores the current positioning instance. -*/ -HsWidgetPositioningOnWidgetAdd *HsWidgetPositioningOnWidgetAdd::mInstance = 0; - -/*! - \class HsAnchorPointInBottomRight - \brief Diagonal widget positioning algorithm. - - Sets widget's lower right corner to follow content area's diagonal. - Widgets are positioned to certain offset to each other. -*/ -QList HsAnchorPointInBottomRight::convert( - const QRectF &contentArea, - const QList &existingRects, - const QList &newRects, - const QPointF &startPoint) -{ - Q_UNUSED(existingRects); - - QList toGeometries; - - //Offset for widgets' bottom right position to each other - qreal k = contentArea.height()/contentArea.width(); //slope of the diagonal - qreal offset_x = offset/(sqrt(k + 1)); - qreal offset_y = k*offset_x; - QPointF offsetPoint(offset_x, offset_y); - - QPointF anchorPoint; - - if(startPoint.isNull()){ - - QLineF diagonal(contentArea.topLeft(), contentArea.bottomRight()); - QLineF widgetRightSide(contentArea.center().x()+ newRects.at(0).width()/2, - contentArea.top(), - contentArea.center().x()+ newRects.at(0).width()/2, - contentArea.bottom()); - - // right side line intersection with diagonal will be bottom right position - // for the first rect - if(QLineF::BoundedIntersection != - diagonal.intersect(widgetRightSide, &anchorPoint)) { - return newRects; //Return original since undefined error. - //In this case widget's must be wider than the content area. - } - }else{ - anchorPoint = startPoint - offsetPoint; - } - - QRectF widgetRect; - for(int i=0;i HsAnchorPointInCenter::convert( - const QRectF &contentArea, - const QList &existingRects, - const QList &newRects, - const QPointF &startPoint ) -{ - Q_UNUSED(existingRects); - Q_UNUSED(startPoint) - - QList toGeometries; - - //Offset for widgets' centers position to each other - qreal k = contentArea.height()/contentArea.width(); //slope of the diagonal - qreal offset_x = offset/(sqrt(k + 1)); - qreal offset_y = k*offset_x; - QPointF offsetPoint(offset_x, offset_y); - - //First widget to the center of the content area - QPointF anchorPoint = contentArea.center(); - foreach (QRectF g, newRects) { - g.moveCenter(anchorPoint); - toGeometries << g; - anchorPoint -= offsetPoint; - if(!contentArea.contains(anchorPoint)) { - anchorPoint = contentArea.bottomRight(); - } - } - return toGeometries; -} - -/*! - \class HsWidgetOrganizer - \brief Advanced widget positioning algorithm. - - Organizes widget's starting from upper left corner towards right, - and then continues the on the next line. -*/ -QList HsWidgetOrganizer::convert( - const QRectF &contentArea, - const QList &existingRects, - const QList &newRects, - const QPointF &startPoint) -{ - Q_UNUSED(startPoint) - - // TODO: maybe we can utilize start point in some use cases / optimizations? - - QList toGeometries; - - // TODO: anchor distance to configuration? - // TODO: optimize anchor distance based on new content amount - // TODO: snap value to same as anchor distance? - mAnchorDistance = 5; - QList temp; - mAnchors = temp; - - // test flag -// int test = 0; - - // initialize anchor network for widget positions -// if (test == 0) { - initAnchors(contentArea.size()); -// } else { -// mAnchorDistance = 2; -// initAnchors(QSizeF(6,6)); -// } - - // mark existing rects (widgets) reserved - foreach (QRectF rect, existingRects) { - // TODO: could mStartWidthAnchorPoint, mEndWidthAnchorPoint, mEndHeightAnchorPoint be somehow refactored better way? - mStartWidthAnchorPoint.setX(lenghtInAnchorPoints(rect.x() - contentArea.x())); - mEndWidthAnchorPoint.setX(lenghtInAnchorPoints(rect.x() + rect.width() - contentArea.x())); - mStartWidthAnchorPoint.setY(lenghtInAnchorPoints(rect.y() - contentArea.y())); - mEndHeightAnchorPoint.setY(lenghtInAnchorPoints(rect.y() + rect.height() - contentArea.y())); - // mark reserved anchor points - markReservedAnchors(); - mStartWidthAnchorPoint = QPointF(0,0); - mEndWidthAnchorPoint = QPointF(0,0); - mEndHeightAnchorPoint = QPointF(0,0); - } - - QList notOrganizedRects; - - // get positions for all new rects (widgets) - for ( int i = 0; i < newRects.count(); i++) { - bool found = false; -// if (test == 0) { - // find first free anchor point for rect - found = getAnchorPoint(newRects.at(i).size()); -// } else { -// found = getAnchorPoint(QSizeF(2,2)); -// } - - if (found) { - // save to geometry list - toGeometries << QRectF(mStartWidthAnchorPoint.x() * mAnchorDistance + contentArea.x(), - mStartWidthAnchorPoint.y() * mAnchorDistance + contentArea.y(), - newRects.at(i).width(), newRects.at(i).height()); - // mark new widgets rect reserved - markReservedAnchors(); - // TODO: these optimizations could be used for empty page - //mStartWidthAnchorPoint.setX(mEndWidthAnchorPoint.x() + 1); - //mStartWidthAnchorPoint.setY(mEndWidthAnchorPoint.y()); - } else { - // collect widgets that do not fit - notOrganizedRects << newRects.at(i); - } - // TODO: remove these to optimize for empty page - mStartWidthAnchorPoint = QPointF(0,0); - mEndWidthAnchorPoint = QPointF(0,0); - } - - // use center algorithm with offset for the rest widget that did not fit to screen - if (notOrganizedRects.count() > 0) { - QList tmpExistingRects; - tmpExistingRects += newRects; - tmpExistingRects += existingRects; - HsAnchorPointInCenter *centerAlgorithm = new HsAnchorPointInCenter(); - QList calculatedRects = - centerAlgorithm->convert(contentArea, tmpExistingRects, notOrganizedRects, QPointF()); - toGeometries += calculatedRects; - delete centerAlgorithm; - } - - return toGeometries; -} - - -/*! - Initializes anchor points for context area -*/ -bool HsWidgetOrganizer::initAnchors(const QSizeF &areaSize) -{ - // mandatory check ups - // TODO: these mAnchorDistance checks to earlier phase - if (areaSize == QSizeF(0,0) || areaSize.width() < mAnchorDistance || - areaSize.height() < mAnchorDistance || mAnchorDistance == 0 || mAnchorDistance == 1) { - return false; - } - mAnchorColumns = 0; - mAnchorRows = 0; - - // TODO: can we optimize anchor amount utilizing minimum widget size - mAnchorColumns = lenghtInAnchorPoints(areaSize.width()); - mAnchorRows = lenghtInAnchorPoints(areaSize.height()); - - // create anchor network - for (int i = 0; i < (mAnchorRows * mAnchorColumns); i++) { - mAnchors << false; - } - // zero start points - mStartWidthAnchorPoint = QPointF(0,0); - mEndWidthAnchorPoint = QPointF(0,0); - - return true; -} - -/*! - Finds anchor points for content size -*/ -bool HsWidgetOrganizer::getAnchorPoint(const QSizeF &contentSize) -{ - bool anchorFound = false; - - while (anchorFound == false) { - // if no width found for content - if (!searchWidthSpace(contentSize)) { - // when content organized in height order remove this line for optimization - mStartWidthAnchorPoint = QPointF(0,0); - mEndWidthAnchorPoint = QPointF(0,0); - return false; - } - // search height for content - int height = lenghtInAnchorPoints(contentSize.height()); - anchorFound = searchHeightSpace(height); - } - return true; -} - -/*! - Searches anchor point width for content size -*/ -bool HsWidgetOrganizer::searchWidthSpace(const QSizeF &contentSize) -{ - int availableWidth = 0; - int contentWidth = lenghtInAnchorPoints(contentSize.width()); - // TODO: use this optimizations for empty page - //int contentHeight = lenghtInAnchorPoints(contentSize.height()); - bool newRow = true; - - for (int i = getIndexForCoordinate(mStartWidthAnchorPoint); i <= mAnchors.count(); i++) { - // no width left on the page - if ((newRow == false) && ((i % (mAnchorColumns)) == 0)) { - availableWidth = 0; - // jump to new row - mStartWidthAnchorPoint.setX(0); - // TODO: use this optimizations for empty page - //mStartWidthAnchorPoint.setY(mStartWidthAnchorPoint.y() + contentHeight + 1); - mStartWidthAnchorPoint.setY(mStartWidthAnchorPoint.y() + 1); - i = getIndexForCoordinate(mStartWidthAnchorPoint) - 1; - // if no height found - if (i < 0) { - return false; - } - newRow = true; - } else { - // if enough width found - if (availableWidth == contentWidth) { - mEndWidthAnchorPoint = getAnchorCoordinates(i); - if (mEndWidthAnchorPoint == QPointF()) { - return false; - } - return true; - } - // if anchor reserved - if (mAnchors[i] == true) { - availableWidth = 0; - } else { - // update available width - availableWidth = availableWidth + 1; - } - newRow = false; - } - } - return false; -} - -/*! - Searches anchor point area for content size -*/ -bool HsWidgetOrganizer::searchHeightSpace(int contentHeight) -{ - mEndHeightAnchorPoint = QPointF(0,0); - - for (int i = mStartWidthAnchorPoint.x(); i <= mEndWidthAnchorPoint.x(); i++) { - for (int j = mStartWidthAnchorPoint.y(); j <= (mStartWidthAnchorPoint.y() + contentHeight); j++) { - int index = getIndexForCoordinate(QPointF(i,j)); - // check that index is not out of bounds - if (index == -1) { - // update start width point one step - mStartWidthAnchorPoint.setX(mStartWidthAnchorPoint.x() + 1); - return false; - } - // if anchor reserved - if (mAnchors[index] == true) { - // update start width point one step - mStartWidthAnchorPoint.setX(mStartWidthAnchorPoint.x() + 1); - return false; - } - } - } - mEndHeightAnchorPoint = QPointF(mEndWidthAnchorPoint.x(), mEndWidthAnchorPoint.y() + contentHeight); - return true; -} - -/*! - Marks reserved anchor points based on pre-defined starting and ending points -*/ -bool HsWidgetOrganizer::markReservedAnchors() -{ - for (int i = mStartWidthAnchorPoint.x(); i <= mEndWidthAnchorPoint.x(); i++) { - for (int j = mStartWidthAnchorPoint.y(); j <= mEndHeightAnchorPoint.y(); j++) { - mAnchors[getIndexForCoordinate(QPointF(i,j))] = true; - } - } - return true; -} - -/*! - Returns pixel coordinate based on anchor coordinate -*/ -QPointF HsWidgetOrganizer::getAnchorCoordinates(int index) -{ - if (index < mAnchors.count()) { - int x = index % mAnchorColumns; - int y = (index - x) / mAnchorColumns; - return QPointF(x,y); - } else { - return QPointF(); - } -} - -/*! - Returns anchor coordinate based on pixel coordinate -*/ -int HsWidgetOrganizer::getIndexForCoordinate(QPointF position) -{ - int index = (position.y() * mAnchorColumns) + position.x(); - if (index < mAnchors.count()) { - return index; - } else { - return -1; - } -} - -/*! - Calculates pixel length as anchor points -*/ -int HsWidgetOrganizer::lenghtInAnchorPoints(QVariant length) -{ - // check remainder - int remainder = length.toInt() % mAnchorDistance; - return ((length.toInt() - remainder) / mAnchorDistance); -} - -#ifdef COVERAGE_MEASUREMENT -#pragma CTC ENDSKIP -#endif //COVERAGE_MEASUREMENT -