--- 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 <QLineF>
-#include <QtGlobal>
-#include <QPointF>
-#include <math.h>
-
-#include <HbInstance>
-
-
-#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<QRectF> HsAnchorPointInBottomRight::convert(
- const QRectF &contentArea,
- const QList<QRectF> &existingRects,
- const QList<QRectF> &newRects,
- const QPointF &startPoint)
-{
- Q_UNUSED(existingRects);
-
- QList<QRectF> 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<newRects.count();++i) {
- widgetRect = newRects.at(i);
- widgetRect.moveBottomRight(anchorPoint);
- //if widget rect doesn't fit, try to move it
- if(!contentArea.contains(widgetRect)) {
- /*! precondition is that
- widget's max height < content area height
- widget's max widht < content area width
- */
- widgetRect.moveBottomRight(contentArea.bottomRight());
- // anchorPoin is always previous bottom right
- anchorPoint = widgetRect.bottomRight();
- }
- toGeometries << widgetRect;
- anchorPoint -= offsetPoint;
-
- }
- return toGeometries;
-}
-
-
-/*!
- \class HsAnchorPointInCenter
- \brief Diagonal widget positioning algorithm.
-
- Sets widget's center point to follow content area's diagonal.
- Widgets are positioned to certain offset to each other.
-*/
-#ifdef COVERAGE_MEASUREMENT
-#pragma CTC SKIP
-#endif //COVERAGE_MEASUREMENT
-QList<QRectF> HsAnchorPointInCenter::convert(
- const QRectF &contentArea,
- const QList<QRectF> &existingRects,
- const QList<QRectF> &newRects,
- const QPointF &startPoint )
-{
- Q_UNUSED(existingRects);
- Q_UNUSED(startPoint)
-
- QList<QRectF> 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<QRectF> HsWidgetOrganizer::convert(
- const QRectF &contentArea,
- const QList<QRectF> &existingRects,
- const QList<QRectF> &newRects,
- const QPointF &startPoint)
-{
- Q_UNUSED(startPoint)
-
- // TODO: maybe we can utilize start point in some use cases / optimizations?
-
- QList<QRectF> 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<bool> 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<QRectF> 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<QRectF> tmpExistingRects;
- tmpExistingRects += newRects;
- tmpExistingRects += existingRects;
- HsAnchorPointInCenter *centerAlgorithm = new HsAnchorPointInCenter();
- QList<QRectF> 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
-