homescreenapp/hsutils/src/hswidgetpositioningonwidgetmove.cpp
changeset 62 341166945d65
child 63 52b0f64eeb51
child 77 4b195f3bea29
equal deleted inserted replaced
57:2e2dc3d30ca8 62:341166945d65
       
     1 /*
       
     2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:
       
    15 *
       
    16 */
       
    17 
       
    18 #include <QVector2D>
       
    19 #include "hswidgetpositioningonwidgetmove.h"
       
    20 #include "hsapp_defs.h"
       
    21 
       
    22 
       
    23 /*!
       
    24     The distance by which the line is extended on each side of reference points
       
    25 */
       
    26 #define SNAP_LINE_EXTEND_VALUE 10.0
       
    27 
       
    28 /*!
       
    29     Sets the snap method instance. The existing instance
       
    30     will be deleted.
       
    31 */
       
    32 void HsWidgetPositioningOnWidgetMove::setInstance(HsWidgetPositioningOnWidgetMove *instance)
       
    33 {
       
    34     if (mInstance)
       
    35         delete mInstance;
       
    36     mInstance = instance;
       
    37 }
       
    38 
       
    39 /*!
       
    40     Returns the snap method instance.
       
    41 */
       
    42 HsWidgetPositioningOnWidgetMove *HsWidgetPositioningOnWidgetMove::instance()
       
    43 {
       
    44     return mInstance;
       
    45 }
       
    46 
       
    47 /*!
       
    48     Points to the snap method instance.
       
    49 */
       
    50 HsWidgetPositioningOnWidgetMove *HsWidgetPositioningOnWidgetMove::mInstance = 0;
       
    51 
       
    52 /*!
       
    53     Constructor.
       
    54 */
       
    55 HsSnapToLines::HsSnapToLines() :
       
    56     mActiveRectWidth(0.0), mActiveRectHeight(0.0),
       
    57     mHorizontalSnapPosition(0.0), mVerticalSnapPosition(0.0),
       
    58     mHorizontalSnapFound(false),
       
    59     mVerticalSnapFound(false),
       
    60     mRectLieAbove(false), mLeftInRange(false), mRightInRange(false),
       
    61     mMinVerticalEdgesDistance(0.0), mVerticalDistance(0.0),
       
    62     mVerticalDistanceFromSelectedRect(0.0), mContainerVerticalEdgeDistance(0.0),
       
    63     mRectLieLeft(false), mTopInRange(false), mBottomInRange(false),
       
    64     mMinHorizontalEdgesDistance(0.0), mHorizontalDistance(0.0),
       
    65     mHorizontalDistanceFromSelectedRect(0.0), mContainerHorizontalEdgeDistance(0.0),
       
    66     mSnapEnabled(false), mSnapForce(0.0), mSnapGap(0.0), mSnapBorderGap(0.0),
       
    67     mRectVerticalEdgeLiesInLineWithVerticalLine(false), mRectLieAboveVerticalLine(false), mRectLieBelowVerticalLine(false),
       
    68     mRectHorizontalEdgeLiesInLineWithHorizontalLine(false), mRectLieLeftOfHorizontalLine(false), mRectLiesRightOfHorizontalLine(false)
       
    69 {
       
    70 
       
    71 }
       
    72 
       
    73 /*!
       
    74     Configures the snap-to-lines algorithm.
       
    75 */
       
    76 void HsSnapToLines::setConfiguration(const QVariantHash &configuration)
       
    77 {
       
    78     bool canConvert = false;
       
    79     mSnapEnabled = configuration[SNAPENABLED].toBool();
       
    80     //The following values should be in qreal, so the status received in canConvert is ignored
       
    81     mSnapForce = configuration[SNAPFORCE].toDouble(&canConvert);
       
    82     mSnapGap = configuration[SNAPGAP].toDouble(&canConvert);
       
    83     mSnapBorderGap = configuration[SNAPBORDERGAP].toDouble(&canConvert);
       
    84 }
       
    85 
       
    86 /*!
       
    87     Set the dimensions of container rect, active rect and position of Inactive Rects
       
    88     on the page.
       
    89 */
       
    90 void HsSnapToLines::setPagePresentation(const QRectF &containerRect, 
       
    91                                         const QList<QRectF> &inactiveRects,
       
    92                                         const QRectF &activeRect)
       
    93 {
       
    94     mContainerRect.setLeft(containerRect.left() + mSnapBorderGap);
       
    95     mContainerRect.setTop(containerRect.top() + mSnapBorderGap);
       
    96     mContainerRect.setRight(containerRect.right() - mSnapBorderGap);
       
    97     mContainerRect.setBottom(containerRect.bottom() - mSnapBorderGap);
       
    98 
       
    99     mActiveRectWidth = activeRect.width();
       
   100     mActiveRectHeight = activeRect.height();
       
   101 
       
   102     createSnappableRectangles(inactiveRects);
       
   103 }
       
   104 
       
   105 /*!
       
   106     Create the list of rects and flag if their sides are snappable from top or bottom or left or right,
       
   107     depending on other rects overlapping with the rect.
       
   108 */
       
   109 void HsSnapToLines::createSnappableRectangles(const QList<QRectF> &inactiveRects)
       
   110 {
       
   111     mInactiveSnapRects.clear();
       
   112 
       
   113     int i;
       
   114     for (i = 0; i<inactiveRects.count(); ++i) {
       
   115         QRectF rect = inactiveRects[i];
       
   116         HsSnapRectangle snapRectangle(rect);
       
   117 
       
   118         int j;
       
   119         for (j = 0; j<inactiveRects.count(); ++j) {
       
   120             QRectF rectToCompare = inactiveRects[j];
       
   121             if (rect != rectToCompare) {
       
   122                 //Check if the rectangles being compared intersect each other
       
   123                 if (rectToCompare.intersects(rect)) {
       
   124                     //As the widgets intersect, check which corner is contained,
       
   125                     //The corner that is contained is not snappable, when the moving widget is in the same position
       
   126                     if (rectToCompare.contains(rect.topLeft())) {
       
   127                         snapRectangle.isLeftSnapableForAbove = false;
       
   128                         snapRectangle.isTopSnapableForLeft = false;
       
   129                     }
       
   130 
       
   131                     if (rectToCompare.contains(rect.topRight())) {
       
   132                         snapRectangle.isRightSnapableForAbove = false;
       
   133                         snapRectangle.isTopSnapableForRight = false;
       
   134                     }
       
   135 
       
   136                     if (rectToCompare.contains(rect.bottomRight())) {
       
   137                         snapRectangle.isRightSnapableForBelow = false;
       
   138                         snapRectangle.isBottomSnapableForRight = false;
       
   139                     }
       
   140 
       
   141                     if (rectToCompare.contains(rect.bottomLeft())) {
       
   142                         snapRectangle.isLeftSnapableForBelow = false;
       
   143                         snapRectangle.isBottomSnapableForLeft = false;
       
   144                     }
       
   145                 }
       
   146             }
       
   147         }
       
   148         if (snapRectangle.isLeftSnapableForAbove || snapRectangle.isLeftSnapableForBelow ||
       
   149             snapRectangle.isRightSnapableForAbove || snapRectangle.isRightSnapableForBelow ||
       
   150             snapRectangle.isTopSnapableForLeft || snapRectangle.isTopSnapableForRight ||
       
   151             snapRectangle.isBottomSnapableForLeft || snapRectangle.isBottomSnapableForRight) {
       
   152                 mInactiveSnapRects.append(snapRectangle);
       
   153         }
       
   154     }
       
   155 }
       
   156 
       
   157 /*!
       
   158     Run the snap algorithm to with the position of moving rect, to get a snap result.
       
   159 */
       
   160 HsWidgetPositioningOnWidgetMove::Result HsSnapToLines::run(const QRectF &movingRect)
       
   161 {
       
   162     HsWidgetPositioningOnWidgetMove::Result result;
       
   163 
       
   164     if (mSnapEnabled) {
       
   165         mMovingRect = movingRect;
       
   166         mHorizontalSnapPosition = 0.0;
       
   167         mVerticalSnapPosition = 0.0;
       
   168 
       
   169         mVerticalLine = QLineF();
       
   170         mMinVerticalEdgesDistance = mSnapForce;
       
   171         mVerticalDistanceFromSelectedRect = 0.0;
       
   172         mContainerVerticalEdgeDistance = 0.0;
       
   173         mHorizontalSnapFound = false;
       
   174 
       
   175         mHorizontalLine = QLineF();
       
   176         mMinHorizontalEdgesDistance = mSnapForce;
       
   177         mHorizontalDistanceFromSelectedRect = 0.0;
       
   178         mContainerHorizontalEdgeDistance = 0.0;
       
   179         mVerticalSnapFound = false;
       
   180 
       
   181         checkForCenterSnapping();
       
   182         for (int i = 0; i < mInactiveSnapRects.count(); ++i) {
       
   183             mInactiveSnapRectToCompare = mInactiveSnapRects[i];
       
   184             mInactiveRectToCompare = mInactiveSnapRectToCompare.rectangle;
       
   185             if (!movingRect.intersects(mInactiveRectToCompare)) { //Only compare if Inactive Rect and moving rect do not overlap.
       
   186                 //TODO: Move the above check to another function...
       
   187                 // X - Direction Snapping
       
   188                 compareLeftSideOfMovingRectForSnapping();
       
   189                 compareRightSideOfMovingRectForSnapping();
       
   190                 // Y - Direction Snapping
       
   191                 compareTopOfMovingRectForSnapping();
       
   192                 compareBottomOfMovingRectForSnapping();
       
   193             }
       
   194         }
       
   195 
       
   196         if (mHorizontalSnapFound) {
       
   197             result.hasHorizontalSnap = true;
       
   198             result.horizontalSnapPosition = mHorizontalSnapPosition;
       
   199             extendVerticalLine();
       
   200             result.verticalSnapLine = mVerticalLine;
       
   201         }
       
   202 
       
   203         if (mVerticalSnapFound) {
       
   204             result.hasVerticalSnap = true;
       
   205             result.verticalSnapPosition = mVerticalSnapPosition;
       
   206             extendHorizontalLine();
       
   207             result.horizontalSnapLine = mHorizontalLine;
       
   208         }
       
   209     }
       
   210 
       
   211     return result;
       
   212 }
       
   213 
       
   214 /*!
       
   215     Check if the center of moving rect is in the snap force in the middle of continer rect.
       
   216 */
       
   217 void HsSnapToLines::checkForCenterSnapping()
       
   218 {
       
   219     QPointF centerOfContainerRect = mContainerRect.center();
       
   220 
       
   221     QRectF verticalSnapField = QRectF(QPointF(centerOfContainerRect.x() - (mSnapForce/2), mContainerRect.top()),
       
   222          QPointF(centerOfContainerRect.x() + (mSnapForce/2), mContainerRect.bottom()));
       
   223 
       
   224     //Check that the widget lies in the container rect, if the snapping position is proposed... is not required,
       
   225     //unless some widget is bigger than the page width
       
   226     QPointF centerOfMovingRect = mMovingRect.center();
       
   227     if (verticalSnapField.contains(centerOfMovingRect)) {
       
   228         mHorizontalSnapFound = true;
       
   229         mHorizontalSnapPosition = centerOfContainerRect.x() - mActiveRectWidth/2;
       
   230         mMinVerticalEdgesDistance = qAbs(centerOfContainerRect.x() - centerOfMovingRect.x());
       
   231         //save the points for the Vertical line
       
   232         mVerticalLine.setP1(QPointF(centerOfContainerRect.x(), mMovingRect.top()));
       
   233         mVerticalLine.setP2(QPointF(centerOfContainerRect.x(), mMovingRect.bottom()));
       
   234     }
       
   235 }
       
   236 
       
   237 /*!
       
   238     Check if the inactive rect being compared with moving rect lies above or below of moving rect.
       
   239 */
       
   240 void HsSnapToLines::checkInactiveRectLieAboveOrBelowOfMovingRect()
       
   241 {
       
   242     //Check if the inactive rect lies below or above of the moving rect
       
   243     mRectLieAbove = false;
       
   244     mVerticalDistance = 0.0;
       
   245     //Inactive Rect lies above or at the save Y position as the Moving Rect
       
   246     if (mInactiveRectToCompare.top() <= mMovingRect.top()) {
       
   247         mRectLieAbove = true;
       
   248         if (mInactiveRectToCompare.bottom() <= mMovingRect.top()) {
       
   249             mVerticalDistance = mMovingRect.top() - mInactiveRectToCompare.bottom();
       
   250         }
       
   251         else {
       
   252             mVerticalDistance = mMovingRect.top() - mInactiveRectToCompare.top();
       
   253         }
       
   254     }
       
   255     //Inactive Rect lies below the Moving Rect
       
   256     else {
       
   257         mRectLieAbove = false;
       
   258         if (mMovingRect.bottom() <= mInactiveRectToCompare.top()) {
       
   259             mVerticalDistance = mInactiveRectToCompare.top() - mMovingRect.bottom();
       
   260         }
       
   261         else {
       
   262             mVerticalDistance = mInactiveRectToCompare.bottom() - mMovingRect.bottom();
       
   263         }
       
   264     }
       
   265 }
       
   266 
       
   267 
       
   268 /*!
       
   269     Check if the left edge of moving rect is snappable to the incative rect's left or right edge.
       
   270     The inactive rect's edge is only chosen if it is a better fit for horizontal snapping.
       
   271 */
       
   272 void HsSnapToLines::compareLeftSideOfMovingRectForSnapping()
       
   273 {
       
   274     checkInactiveRectLieAboveOrBelowOfMovingRect();
       
   275 
       
   276     //calculate the distance of the moving rect's left edge to the inactive rect's left and right edges
       
   277     qreal leftToLeftOfInactiveRect = qAbs(mInactiveRectToCompare.left() - mMovingRect.left());
       
   278     qreal leftToRightOfInactiveRect = qAbs(mInactiveRectToCompare.right() - mMovingRect.left());
       
   279     mLeftInRange = false;
       
   280     mRightInRange = false;
       
   281 
       
   282     if (leftToLeftOfInactiveRect <= mMinVerticalEdgesDistance) {
       
   283         if (mRectLieAbove && mInactiveSnapRectToCompare.isLeftSnapableForBelow
       
   284          || !mRectLieAbove && mInactiveSnapRectToCompare.isLeftSnapableForAbove) { 
       
   285             mLeftInRange = true;
       
   286         }
       
   287     }
       
   288     if (leftToRightOfInactiveRect <= mMinVerticalEdgesDistance) {
       
   289         if (mRectLieAbove && mInactiveSnapRectToCompare.isRightSnapableForBelow
       
   290          || !mRectLieAbove && mInactiveSnapRectToCompare.isRightSnapableForAbove) {
       
   291             mRightInRange = true;
       
   292         }
       
   293     }
       
   294 
       
   295     //calculate the distance of inactive rect's left edge and container rect's left edge
       
   296     qreal differenceContainerLeftEdgeToInactiveRectLeftEdge = mInactiveRectToCompare.left() - mContainerRect.left();
       
   297     //calculate the distance of inactive rect's right edge and container rect's right edge
       
   298     qreal differenceContainerRightEdgeToInactiveRectRightEdge = mContainerRect.right() - mInactiveRectToCompare.right();
       
   299 
       
   300     qreal minDistancePosition = 0.0;
       
   301     qreal distanceVerticalEdges = 0.0;
       
   302     qreal xSnapGapAdjustment = 0.0;
       
   303 
       
   304     //If only one edge of inactive rect is in snappable range, save that position
       
   305     if ((mLeftInRange && !mRightInRange)
       
   306         || !mLeftInRange && mRightInRange) {
       
   307         if (mLeftInRange) {
       
   308             minDistancePosition = mInactiveRectToCompare.left();
       
   309             distanceVerticalEdges = leftToLeftOfInactiveRect;
       
   310             xSnapGapAdjustment = 0.0;
       
   311         }
       
   312         else {
       
   313             minDistancePosition = mInactiveRectToCompare.right();
       
   314             distanceVerticalEdges = leftToRightOfInactiveRect;
       
   315             xSnapGapAdjustment = mSnapGap;
       
   316         }
       
   317     }
       
   318     //else both edges of inactive rect are in range, check which is a better fit
       
   319     else if (mLeftInRange && mRightInRange) {
       
   320         //if left edge of moving rect to the left of the inactive rect is closer than the left edge of moving rect to the right of the inactive rect
       
   321         if (leftToLeftOfInactiveRect < leftToRightOfInactiveRect) {
       
   322             minDistancePosition = mInactiveRectToCompare.left();
       
   323             distanceVerticalEdges = leftToLeftOfInactiveRect;
       
   324             xSnapGapAdjustment = 0.0;
       
   325             mRightInRange = false;
       
   326         }
       
   327         //if the left edge of inactive rect to left of moving rect is at the same distance as the right edge of inactive rect to the right of moving rect
       
   328         else if (leftToLeftOfInactiveRect == leftToRightOfInactiveRect) {
       
   329             //if inactive rect lies towards the left or middle of container rect, then the left edge is priortized as the selected edge for outside snapping 
       
   330             if (differenceContainerLeftEdgeToInactiveRectLeftEdge <= differenceContainerRightEdgeToInactiveRectRightEdge) { 
       
   331                 minDistancePosition = mInactiveRectToCompare.left();
       
   332                 distanceVerticalEdges = leftToLeftOfInactiveRect;
       
   333                 xSnapGapAdjustment = 0.0;
       
   334                 mRightInRange = false;
       
   335             }
       
   336             //else right of the inactive rect lies more close to the right of the container rect, and hence prioritize it for snapping.
       
   337             else {
       
   338                 minDistancePosition = mInactiveRectToCompare.right();
       
   339                 distanceVerticalEdges = leftToRightOfInactiveRect;
       
   340                 xSnapGapAdjustment = mSnapGap;
       
   341                 mLeftInRange = false;
       
   342             }
       
   343         }
       
   344         //else right edge of inactive rect to the left of the moving rect is closer than the left edge of inactive rect to the left of the moving rect
       
   345         else{
       
   346             minDistancePosition = mInactiveRectToCompare.right();
       
   347             distanceVerticalEdges = leftToRightOfInactiveRect;
       
   348             xSnapGapAdjustment = mSnapGap;
       
   349             mLeftInRange = false;
       
   350         }
       
   351     }
       
   352 
       
   353     //Check if this inactive rect is better fit than the previous selected rect for X - snapping
       
   354     bool horizontalSnappingBetterFit = false;
       
   355     if (mLeftInRange || mRightInRange) {
       
   356         if (distanceVerticalEdges < mMinVerticalEdgesDistance) {
       
   357             horizontalSnappingBetterFit = true;
       
   358         }
       
   359         else if (distanceVerticalEdges == mMinVerticalEdgesDistance) { //the distance in the vertical edges is same as from the selected rectangle
       
   360             //check the position of rect with respect to Vertical line
       
   361             checkInactiveRectPositionToVerticalLine();
       
   362             //if horizontal snap position was previously found the rect's edges are in line with Vertical line
       
   363             if (mHorizontalSnapFound && mRectVerticalEdgeLiesInLineWithVerticalLine) {
       
   364                 if (mRectLieAboveVerticalLine || mRectLieBelowVerticalLine) {
       
   365                     extendVerticalLineToIncludeInactiveRect();
       
   366                 }
       
   367             }
       
   368             //here the case is that moving rect lies exactly in middle of two same sides of two inactive widgets.
       
   369             else {
       
   370                 //Prioritize first on the fact if the inactive rect is closer to the moving rect in Y - direction.
       
   371                 if (mVerticalDistance < mVerticalDistanceFromSelectedRect) {
       
   372                     horizontalSnappingBetterFit = true;
       
   373                 }
       
   374                 else if (mVerticalDistance == mVerticalDistanceFromSelectedRect) {
       
   375                     //Prioritize next if this Inactive rect is closer to the left edge of the container rect, then the previously selected rect
       
   376                     if (differenceContainerLeftEdgeToInactiveRectLeftEdge < mContainerVerticalEdgeDistance) {
       
   377                         horizontalSnappingBetterFit = true;
       
   378                     }
       
   379                     //Prioritize next if the Inactive widget's left edge lies near to left edge of the container rect
       
   380                     else if (differenceContainerLeftEdgeToInactiveRectLeftEdge < differenceContainerRightEdgeToInactiveRectRightEdge) {
       
   381                         horizontalSnappingBetterFit = true;
       
   382                     }
       
   383                     else {
       
   384                         //This else will happen if this rectangle being compared is exactly the same as the selected rectangle for snapping.
       
   385                         //In that case it does not matter which is the selected rectangle. Hence we leave the already selected rectangle as the better fit.
       
   386                     }
       
   387                 }
       
   388             }
       
   389         }
       
   390     }
       
   391 
       
   392     if (horizontalSnappingBetterFit) {
       
   393         qreal proposedRightOfActiveRect = minDistancePosition + xSnapGapAdjustment + mActiveRectWidth;
       
   394         if (qBound(mContainerRect.left(), proposedRightOfActiveRect, mContainerRect.right())
       
   395             == proposedRightOfActiveRect) {
       
   396             mHorizontalSnapFound = true;
       
   397             mHorizontalSnapPosition = minDistancePosition + xSnapGapAdjustment;
       
   398             mMinVerticalEdgesDistance = distanceVerticalEdges;
       
   399             mVerticalDistanceFromSelectedRect = mVerticalDistance;
       
   400             //Save the new distance of the Chosen Rectangle's left edge from Container's left edge
       
   401             mContainerVerticalEdgeDistance = differenceContainerLeftEdgeToInactiveRectLeftEdge;
       
   402 
       
   403             if (mRectLieAbove) {
       
   404                 mVerticalLine.setP1(QPointF(minDistancePosition, mInactiveRectToCompare.top()));
       
   405                 mVerticalLine.setP2(QPointF(minDistancePosition, mMovingRect.bottom()));
       
   406             }
       
   407             else {
       
   408                 mVerticalLine.setP1(QPointF(minDistancePosition, mInactiveRectToCompare.bottom()));
       
   409                 mVerticalLine.setP2(QPointF(minDistancePosition, mMovingRect.top()));
       
   410             }
       
   411         }
       
   412     }
       
   413 }
       
   414 
       
   415 /*!
       
   416     Check if the right edge of moving rect is snappable to the incative rect's left or right edge.
       
   417     The inactive rect's edge is only chosen if it is a better fit for horizontal snapping.
       
   418 */
       
   419 void HsSnapToLines::compareRightSideOfMovingRectForSnapping()
       
   420 {
       
   421     checkInactiveRectLieAboveOrBelowOfMovingRect();
       
   422 
       
   423     //calculate the distance of the moving rect's right edge to the inactive rect's left and right edges
       
   424     qreal rightToLeftOfInactiveRect = qAbs(mInactiveRectToCompare.left() - mMovingRect.right());
       
   425     qreal rightToRightOfInactiveRect = qAbs(mInactiveRectToCompare.right() - mMovingRect.right());
       
   426     mLeftInRange = false;
       
   427     mRightInRange = false;
       
   428 
       
   429     if (rightToLeftOfInactiveRect <= mMinVerticalEdgesDistance) {
       
   430         if (mRectLieAbove && mInactiveSnapRectToCompare.isLeftSnapableForBelow
       
   431          || !mRectLieAbove && mInactiveSnapRectToCompare.isLeftSnapableForAbove) {
       
   432             mLeftInRange = true;
       
   433         }
       
   434     }
       
   435     if (rightToRightOfInactiveRect <= mMinVerticalEdgesDistance) {
       
   436         if (mRectLieAbove && mInactiveSnapRectToCompare.isRightSnapableForBelow
       
   437          || !mRectLieAbove && mInactiveSnapRectToCompare.isRightSnapableForAbove) {
       
   438             mRightInRange = true;
       
   439         }
       
   440     }
       
   441 
       
   442     //calculate the distance of inactive rect's left edge and container rect's left edge
       
   443     qreal differenceContainerLeftEdgeToInactiveRectLeftEdge = mInactiveRectToCompare.left() - mContainerRect.left();
       
   444     //calculate the distance of inactive rect's right edge and container rect's right edge
       
   445     qreal differenceContainerRightEdgeToInactiveRectRightEdge = mContainerRect.right() - mInactiveRectToCompare.right();
       
   446     qreal minDistancePosition = 0.0;
       
   447     qreal distanceVerticalEdges = 0.0;
       
   448     qreal xSnapGapAdjustment = 0.0;
       
   449 
       
   450     //If only one edge of inactive rect is in snappable range, save that position
       
   451     if ((mLeftInRange && !mRightInRange)
       
   452         || !mLeftInRange && mRightInRange) {
       
   453         if (mLeftInRange) {
       
   454             minDistancePosition = mInactiveRectToCompare.left();
       
   455             distanceVerticalEdges = rightToLeftOfInactiveRect;
       
   456             xSnapGapAdjustment = mSnapGap;
       
   457         }
       
   458         else {
       
   459             minDistancePosition = mInactiveRectToCompare.right();
       
   460             distanceVerticalEdges = rightToRightOfInactiveRect;
       
   461             xSnapGapAdjustment = 0.0;
       
   462         }
       
   463     }
       
   464     //else both edges of inactive rect are in range, check which is a better fit
       
   465     else if (mLeftInRange && mRightInRange) {
       
   466         //if right edge of moving rect to the right of the inactive rect is closer than the right edge of moving rect to the left of inactive rect
       
   467         if (rightToRightOfInactiveRect < rightToLeftOfInactiveRect) {
       
   468             minDistancePosition = mInactiveRectToCompare.right();
       
   469             distanceVerticalEdges = rightToRightOfInactiveRect;
       
   470             xSnapGapAdjustment = 0.0;
       
   471             mLeftInRange = false;
       
   472         }
       
   473         //if the right edge of moving rect to right of inactive rect is at the same distance as the right edge of moving rect to the left of inactive rect
       
   474         else if (rightToRightOfInactiveRect == rightToLeftOfInactiveRect) {
       
   475             //if inactive rect lies towards the right of container rect, then the right edge is priortized as the selected edge for outside snapping
       
   476             if (differenceContainerRightEdgeToInactiveRectRightEdge < differenceContainerLeftEdgeToInactiveRectLeftEdge ) { 
       
   477                 minDistancePosition = mInactiveRectToCompare.right();
       
   478                 distanceVerticalEdges = rightToRightOfInactiveRect;
       
   479                 xSnapGapAdjustment = 0.0;
       
   480                 mLeftInRange = false;
       
   481             }
       
   482             //else left of the inactive rect lies more close to the left or middle of the container rect, and hence prioritize it
       
   483             else {
       
   484                 minDistancePosition = mInactiveRectToCompare.left();
       
   485                 distanceVerticalEdges = rightToLeftOfInactiveRect;
       
   486                 xSnapGapAdjustment = mSnapGap;
       
   487                 mRightInRange = false;
       
   488             }
       
   489         }
       
   490         //else right edge of moving rect to the left of the inactive rect is closer than the right edge of moving rect to the right of the incoming rect
       
   491         else{
       
   492             minDistancePosition = mInactiveRectToCompare.left();
       
   493             distanceVerticalEdges = rightToLeftOfInactiveRect;
       
   494             xSnapGapAdjustment = mSnapGap;
       
   495             mRightInRange = false;
       
   496         }
       
   497     }
       
   498 
       
   499     //Check if this inactive rect is better fit than the previous selected rect 
       
   500     bool horizontalSnappingBetterFit = false;
       
   501     if (mLeftInRange || mRightInRange) {
       
   502         if (distanceVerticalEdges < mMinVerticalEdgesDistance) {
       
   503             horizontalSnappingBetterFit = true;
       
   504         }
       
   505         else if (distanceVerticalEdges == mMinVerticalEdgesDistance) { //the distance in the vertical edge is same as from the selected rectangle
       
   506             //check the position of rect with respect to Vertical line
       
   507             checkInactiveRectPositionToVerticalLine();
       
   508             //if horizontal snap position was previously found and the rect's edge is in line with Vertical line
       
   509             if (mHorizontalSnapFound && mRectVerticalEdgeLiesInLineWithVerticalLine) {
       
   510                 if (mRectLieAboveVerticalLine || mRectLieBelowVerticalLine) {
       
   511                     extendVerticalLineToIncludeInactiveRect();
       
   512                 }
       
   513             }
       
   514             //here the case is that moving rect lies exactly in middle of two same sides of two inactive widgets.
       
   515             else {
       
   516                 //Prioritize first on the fact if the inactive rect is closer to the moving rect in Y - direction.
       
   517                 if (mVerticalDistance < mVerticalDistanceFromSelectedRect) {
       
   518                     horizontalSnappingBetterFit = true;
       
   519                 }
       
   520                 else if (mVerticalDistance == mVerticalDistanceFromSelectedRect) {
       
   521                     //Prioritize next if this Inactive rect is closer to the right edge of the container rect, then the previously selected rect
       
   522                     if (differenceContainerRightEdgeToInactiveRectRightEdge < mContainerVerticalEdgeDistance) {
       
   523                         horizontalSnappingBetterFit = true;
       
   524                     }
       
   525                     //Prioritize next if the Inactive rect's right edge lies near to right edge of the container rect
       
   526                     else if (differenceContainerRightEdgeToInactiveRectRightEdge < differenceContainerLeftEdgeToInactiveRectLeftEdge) {
       
   527                         horizontalSnappingBetterFit = true;
       
   528                     }
       
   529                     else {
       
   530                         //This else will happen if this rectangle being compared is exactly the same as the selected rectangle for snapping, but in opposite Y direction.
       
   531                         //In that case it does not matter which is the selected rectangle. Hece we leave the already selected rectangle as the better fit.
       
   532                     }
       
   533                 }
       
   534             }
       
   535         }
       
   536     }
       
   537 
       
   538     if (horizontalSnappingBetterFit) {
       
   539         qreal proposedLeftOfActiveRect = minDistancePosition - mActiveRectWidth - xSnapGapAdjustment;
       
   540         if (qBound(mContainerRect.left(), proposedLeftOfActiveRect, mContainerRect.right())
       
   541             == proposedLeftOfActiveRect) {
       
   542             mHorizontalSnapFound = true;
       
   543             mHorizontalSnapPosition = proposedLeftOfActiveRect;
       
   544             mMinVerticalEdgesDistance = distanceVerticalEdges;
       
   545             mVerticalDistanceFromSelectedRect = mVerticalDistance;
       
   546             //Save the new distance of the Chosen Rectangle's right edge from Container's right edge
       
   547             mContainerVerticalEdgeDistance = differenceContainerRightEdgeToInactiveRectRightEdge;
       
   548 
       
   549             if (mRectLieAbove) {
       
   550                 //save the points for the Vertical line
       
   551                 mVerticalLine.setP1(QPointF(minDistancePosition, mInactiveRectToCompare.top()));
       
   552                 mVerticalLine.setP2(QPointF(minDistancePosition, mMovingRect.bottom()));
       
   553             }
       
   554             else {
       
   555                 //save the points for the Vertical line
       
   556                 mVerticalLine.setP1(QPointF(minDistancePosition, mInactiveRectToCompare.bottom()));
       
   557                 mVerticalLine.setP2(QPointF(minDistancePosition, mMovingRect.top()));
       
   558             }
       
   559         }
       
   560     }
       
   561 }
       
   562 
       
   563 /*!
       
   564     Check if the inactive rect being compared with moving rect lies on left or right of moving rect.
       
   565 */
       
   566 void HsSnapToLines::checkInactiveRectLieLeftOrRightOfMovingRect()
       
   567 {
       
   568     mRectLieLeft = false;
       
   569     mHorizontalDistance = 0.0;
       
   570     //Inactive Rect lies left of the Moving Rect
       
   571     if (mInactiveRectToCompare.left() < mMovingRect.left()) {
       
   572         mRectLieLeft = true;
       
   573         if (mInactiveRectToCompare.right() <= mMovingRect.left()) {
       
   574             mHorizontalDistance = mMovingRect.left() - mInactiveRectToCompare.right();
       
   575         }
       
   576         else {
       
   577             mHorizontalDistance = mMovingRect.left() - mInactiveRectToCompare.left();
       
   578         }
       
   579     }
       
   580     //Inactive Rect lies right of the Moving Rect
       
   581     else {
       
   582         mRectLieLeft = false;
       
   583         if (mMovingRect.right() <= mInactiveRectToCompare.left()) {
       
   584             mHorizontalDistance = mInactiveRectToCompare.left() - mMovingRect.right();
       
   585         }
       
   586         else {
       
   587             mHorizontalDistance = mInactiveRectToCompare.right() - mMovingRect.right();
       
   588         }
       
   589     }
       
   590 }
       
   591 
       
   592 /*!
       
   593     Check if the top edge of moving rect is snappable to the incative rect's top or bottom edge.
       
   594     The inactive rect's edge is only chosen if it is a better fit for vertical snapping.
       
   595 */
       
   596 void HsSnapToLines::compareTopOfMovingRectForSnapping()
       
   597 {
       
   598     //Check if the inactive rect lies to the left or right of the moving rect
       
   599     checkInactiveRectLieLeftOrRightOfMovingRect();
       
   600 
       
   601     //calculate the distance of the moving rect's top edge to the inactive rect's top and bottom edges
       
   602     qreal topToTopOfInactiveRect = qAbs(mInactiveRectToCompare.top() - mMovingRect.top());
       
   603     qreal topToBottomOfInactiveRect = qAbs(mInactiveRectToCompare.bottom() - mMovingRect.top());
       
   604     mTopInRange = false;
       
   605     mBottomInRange = false;
       
   606 
       
   607     if (topToTopOfInactiveRect <= mMinHorizontalEdgesDistance) {
       
   608         if (mRectLieLeft && mInactiveSnapRectToCompare.isTopSnapableForRight
       
   609          || !mRectLieLeft && mInactiveSnapRectToCompare.isTopSnapableForLeft) {
       
   610             mTopInRange = true;
       
   611         }
       
   612     }
       
   613     if (topToBottomOfInactiveRect <= mMinHorizontalEdgesDistance) {
       
   614         if (mRectLieLeft && mInactiveSnapRectToCompare.isBottomSnapableForRight
       
   615          || !mRectLieLeft && mInactiveSnapRectToCompare.isBottomSnapableForLeft) {
       
   616             mBottomInRange = true;
       
   617         }
       
   618     }
       
   619 
       
   620     //calculate the distance of inactive rect's top edge and container rect's top edge
       
   621     qreal differenceContainerTopEdgeToInactiveRectTopEdge = mInactiveRectToCompare.top() - mContainerRect.top();
       
   622     //calculate the distance of inactive rect's bottom edge and container rect's bottom edge
       
   623     qreal differenceContainerBottomEdgeToInactiveRectBottomEdge = mContainerRect.bottom() - mInactiveRectToCompare.bottom();
       
   624     qreal minDistancePosition = 0.0;
       
   625     qreal distanceHorizontalEdges = 0.0;
       
   626     qreal ySnapGapAdjustment = 0.0;
       
   627 
       
   628     //If only one edge of inactive rect is in snappable range, save that position
       
   629     if ((mTopInRange && !mBottomInRange)
       
   630         || !mTopInRange && mBottomInRange) {
       
   631         if (mTopInRange) {
       
   632             minDistancePosition = mInactiveRectToCompare.top();
       
   633             distanceHorizontalEdges = topToTopOfInactiveRect;
       
   634             ySnapGapAdjustment = 0.0;
       
   635         }
       
   636         else {
       
   637             minDistancePosition = mInactiveRectToCompare.bottom();
       
   638             distanceHorizontalEdges = topToBottomOfInactiveRect;
       
   639             ySnapGapAdjustment = mSnapGap;
       
   640         }
       
   641     }
       
   642     //else both edges of inactive rect are in range, check which is a better fit
       
   643     else if (mTopInRange && mBottomInRange) {
       
   644         //if top edge of moving rect to the top of the inactive rect is closer than the bottom edge of moving rect to the bottom of the inactive rect
       
   645         if (topToTopOfInactiveRect < topToBottomOfInactiveRect) {
       
   646             minDistancePosition = mInactiveRectToCompare.top();
       
   647             distanceHorizontalEdges = topToTopOfInactiveRect;
       
   648             ySnapGapAdjustment = 0.0;
       
   649             mBottomInRange = false;
       
   650         }
       
   651         //if the top edge of moving rect to top of inactive rect is at the same distance as the top edge of moving rect to the bottom of inactive rect
       
   652         else if (topToTopOfInactiveRect == topToBottomOfInactiveRect) {
       
   653             //if inactive rect lies towards the top or middle of container rect, then the top edge is priortized as the selected edge for outside snapping
       
   654             if (differenceContainerTopEdgeToInactiveRectTopEdge <= differenceContainerBottomEdgeToInactiveRectBottomEdge) { 
       
   655                 minDistancePosition = mInactiveRectToCompare.top();
       
   656                 distanceHorizontalEdges = topToTopOfInactiveRect;
       
   657                 ySnapGapAdjustment = 0.0;
       
   658                 mBottomInRange = false;
       
   659             }
       
   660             //else bottom of the inactive rect lies more close to the bottom of the container rect, and hence prioritize it for snapping.
       
   661             else {
       
   662                 minDistancePosition = mInactiveRectToCompare.bottom();
       
   663                 distanceHorizontalEdges = topToBottomOfInactiveRect;
       
   664                 ySnapGapAdjustment = mSnapGap;
       
   665                 mTopInRange = false;
       
   666             }
       
   667         }
       
   668         //else top edge of moving rect to the bottom of the inactive rect is closer than the top edge of moving rect to the top of the inactive rect
       
   669         else{
       
   670             minDistancePosition = mInactiveRectToCompare.bottom();
       
   671             distanceHorizontalEdges = topToBottomOfInactiveRect;
       
   672             ySnapGapAdjustment = mSnapGap;
       
   673             mTopInRange = false;
       
   674         }
       
   675     }
       
   676 
       
   677     //Check if this inactive rect is better fit than the previous selected rect 
       
   678     bool verticalSnappingBetterFit = false;
       
   679     if (mTopInRange || mBottomInRange) {
       
   680         if (distanceHorizontalEdges < mMinHorizontalEdgesDistance) {
       
   681             verticalSnappingBetterFit = true;
       
   682         }
       
   683         else if (distanceHorizontalEdges == mMinHorizontalEdgesDistance) { //the distance in the horizontal edge is same as from the selected rectangle
       
   684             //check the position of rect with respect to horizontal line
       
   685             checkInactiveRectPositionToHorizontalLine();
       
   686             //if vertical snap position was already found and this rect's horizontal edges lies in line with Horizontal snap line
       
   687             if (mVerticalSnapFound && mRectHorizontalEdgeLiesInLineWithHorizontalLine) {
       
   688                 if (mRectLieLeftOfHorizontalLine || mRectLiesRightOfHorizontalLine) {
       
   689                     extendHorizontalLineToIncludeInactiveRect();
       
   690                 }
       
   691             }
       
   692             else {
       
   693                 //Prioritize first on the fact if the inactive rect is closer to the moving rect in X - direction.
       
   694                 if (mHorizontalDistance < mHorizontalDistanceFromSelectedRect) {
       
   695                     verticalSnappingBetterFit = true;
       
   696                 }
       
   697                 else if (mHorizontalDistance == mHorizontalDistanceFromSelectedRect) {
       
   698                     //Prioritize next if this Inactive rect is closer to the top edge of the container rect, then the previously selected rect
       
   699                     if (differenceContainerTopEdgeToInactiveRectTopEdge < mContainerHorizontalEdgeDistance) {
       
   700                         verticalSnappingBetterFit = true;
       
   701                     }
       
   702                     //Prioritize next if the Inactive widget's top edge lies near to top edge of the container rect
       
   703                     else if (differenceContainerTopEdgeToInactiveRectTopEdge < differenceContainerBottomEdgeToInactiveRectBottomEdge) {
       
   704                         verticalSnappingBetterFit = true;
       
   705                     }
       
   706                     else {
       
   707                         //This else will happen if this rectangle being compared is exactly the same as the selected rectangle for snapping, or in opposite X direction.
       
   708                         //In that case it does not matter which is the selected rectangle. Hence we leave the already selected rectangle as the better fit.
       
   709                     }
       
   710                 }
       
   711             }
       
   712         }
       
   713     }
       
   714 
       
   715     if (verticalSnappingBetterFit) {
       
   716         qreal proposedBottomOfActiveRect = minDistancePosition + mActiveRectHeight + ySnapGapAdjustment;
       
   717         if (qBound(mContainerRect.top(), proposedBottomOfActiveRect, mContainerRect.bottom())
       
   718             == proposedBottomOfActiveRect) {
       
   719             mVerticalSnapFound = true;
       
   720             mVerticalSnapPosition = minDistancePosition + ySnapGapAdjustment;
       
   721             mMinHorizontalEdgesDistance = distanceHorizontalEdges;
       
   722             mHorizontalDistanceFromSelectedRect = mHorizontalDistance;
       
   723             //Save the new distance of the Chosen Rectangle's top edge from Container's top edge
       
   724             mContainerHorizontalEdgeDistance = differenceContainerTopEdgeToInactiveRectTopEdge;
       
   725 
       
   726             if (mRectLieLeft) {
       
   727                 //save the points for the Horizontal line
       
   728                 mHorizontalLine.setP1(QPointF(mInactiveRectToCompare.left(), minDistancePosition));
       
   729                 mHorizontalLine.setP2(QPointF(mMovingRect.right(), minDistancePosition));
       
   730             }
       
   731             else {
       
   732                 //save the points for the Horizontal line
       
   733                 mHorizontalLine.setP1(QPointF(mInactiveRectToCompare.right(), minDistancePosition));
       
   734                 mHorizontalLine.setP2(QPointF(mMovingRect.left(), minDistancePosition));
       
   735             }
       
   736         }
       
   737     }
       
   738 }
       
   739 
       
   740 /*!
       
   741     Check if the bottom edge of moving rect is snappable to the incative rect's top or bottom edge.
       
   742     The inactive rect's edge is only chosen if it is a better fit for vertical snapping.
       
   743 */
       
   744 void HsSnapToLines::compareBottomOfMovingRectForSnapping()
       
   745 {
       
   746     //Check if the inactive rect lies to the left or right of the moving rect
       
   747     checkInactiveRectLieLeftOrRightOfMovingRect();
       
   748 
       
   749     //calculate the distance of the moving rect's bottom edge to the inactive rect's top and bottom edges
       
   750     qreal bottomToTopOfInactiveRect = qAbs(mInactiveRectToCompare.top() - mMovingRect.bottom());
       
   751     qreal bottomToBottomOfInactiveRect = qAbs(mInactiveRectToCompare.bottom() - mMovingRect.bottom());
       
   752     mTopInRange = false;
       
   753     mBottomInRange = false;
       
   754 
       
   755     if (bottomToTopOfInactiveRect <= mMinHorizontalEdgesDistance) {
       
   756         if (mRectLieLeft && mInactiveSnapRectToCompare.isTopSnapableForRight
       
   757          || !mRectLieLeft && mInactiveSnapRectToCompare.isTopSnapableForLeft) {
       
   758             mTopInRange = true;
       
   759         }
       
   760     }
       
   761     if (bottomToBottomOfInactiveRect <= mMinHorizontalEdgesDistance) {
       
   762         if (mRectLieLeft && mInactiveSnapRectToCompare.isBottomSnapableForRight
       
   763          || !mRectLieLeft && mInactiveSnapRectToCompare.isBottomSnapableForLeft) {
       
   764             mBottomInRange = true;
       
   765         }
       
   766     }
       
   767 
       
   768     //calculate the distance of inactive rect's top edge and container rect's top edge
       
   769     qreal differenceContainerTopEdgeToInactiveRectTopEdge = mInactiveRectToCompare.top() - mContainerRect.top();
       
   770     //calculate the distance of inactive rect's bottom edge and container rect's bottom edge
       
   771     qreal differenceContainerBottomEdgeToInactiveRectBottomEdge = mContainerRect.bottom() - mInactiveRectToCompare.bottom();
       
   772     qreal minDistancePosition = 0.0;
       
   773     qreal distanceHorizontalEdges = 0.0;
       
   774     qreal ySnapGapAdjustment = 0.0;
       
   775 
       
   776     //If only one edge of inactive rect is in snappable range, save that position
       
   777     if ((mTopInRange && !mBottomInRange)
       
   778         || !mTopInRange && mBottomInRange) {
       
   779         if (mTopInRange) {
       
   780             minDistancePosition = mInactiveRectToCompare.top();
       
   781             distanceHorizontalEdges = bottomToTopOfInactiveRect;
       
   782             ySnapGapAdjustment = mSnapGap;
       
   783         }
       
   784         else {
       
   785             minDistancePosition = mInactiveRectToCompare.bottom();
       
   786             distanceHorizontalEdges = bottomToBottomOfInactiveRect;
       
   787             ySnapGapAdjustment = 0.0;
       
   788         }
       
   789     }
       
   790     //else both edges of inactive rect are in range, check which is a better fit
       
   791     else if (mTopInRange && mBottomInRange) {
       
   792         //if bottom edge of moving rect to the bottom of inactive rect is closer than the bottom edge of moving rect to the top of the inactive rect
       
   793         if (bottomToBottomOfInactiveRect < bottomToTopOfInactiveRect ) {
       
   794             minDistancePosition = mInactiveRectToCompare.bottom();
       
   795             distanceHorizontalEdges = bottomToBottomOfInactiveRect;
       
   796             ySnapGapAdjustment = 0.0;
       
   797             mTopInRange = false;
       
   798         }
       
   799         //if bottom edge of moving rect to the bottom of inactive rect is at the same distance as the bottom edge of moving rect to the top of inactive rect
       
   800         else if (bottomToBottomOfInactiveRect == bottomToTopOfInactiveRect) {
       
   801             //if inactive rect lies towards the bottom of container rect, then the bottom edge is priortized as the selected edge for snapping
       
   802             //This is done for outside snapping
       
   803             if (differenceContainerBottomEdgeToInactiveRectBottomEdge < differenceContainerTopEdgeToInactiveRectTopEdge) {
       
   804                 minDistancePosition = mInactiveRectToCompare.bottom();
       
   805                 distanceHorizontalEdges = bottomToBottomOfInactiveRect;
       
   806                 ySnapGapAdjustment = 0.0;
       
   807                 mTopInRange = false;
       
   808             }
       
   809             //else top of the inactive rect lies more close to the top of the container rect or at the same distance, and hence prioritize it
       
   810             else {
       
   811                 minDistancePosition = mInactiveRectToCompare.top();
       
   812                 distanceHorizontalEdges = bottomToTopOfInactiveRect;
       
   813                 ySnapGapAdjustment = mSnapGap;
       
   814                 mBottomInRange = false;
       
   815             }
       
   816         }
       
   817         //else bottom edge of moving rect to the top of inactive rect is closer than the bottom edge of moving rect to the bottom of the inactive rect
       
   818         else{
       
   819             minDistancePosition = mInactiveRectToCompare.top();
       
   820             distanceHorizontalEdges = bottomToTopOfInactiveRect;
       
   821             ySnapGapAdjustment = mSnapGap;
       
   822             mBottomInRange = false;
       
   823         }
       
   824     }
       
   825 
       
   826     //Check if this inactive rect is better fit than the previous selected rect 
       
   827     bool verticalSnappingBetterFit = false;
       
   828     if (mTopInRange || mBottomInRange) {
       
   829         if (distanceHorizontalEdges < mMinHorizontalEdgesDistance) {
       
   830             verticalSnappingBetterFit = true;
       
   831         }
       
   832         else if (distanceHorizontalEdges == mMinHorizontalEdgesDistance) { //the distance in the horizontal edge is same as from the selected rectangle
       
   833             //check the position of rect with respect to horizontal line
       
   834             checkInactiveRectPositionToHorizontalLine();
       
   835             //if vertical snap was already found and the horizontal line of rect is in line with horizontal snap line
       
   836             if (mVerticalSnapFound && mRectHorizontalEdgeLiesInLineWithHorizontalLine) {
       
   837                 if (mRectLieLeftOfHorizontalLine || mRectLiesRightOfHorizontalLine) {
       
   838                     extendHorizontalLineToIncludeInactiveRect();
       
   839                 }
       
   840             }
       
   841             else {
       
   842                 //Prioritize first on the fact if the inactive rect is closer to the moving rect in X - direction.
       
   843                 if (mHorizontalDistance < mHorizontalDistanceFromSelectedRect) {
       
   844                     verticalSnappingBetterFit = true;
       
   845                 }
       
   846                 else if (mHorizontalDistance == mHorizontalDistanceFromSelectedRect) {
       
   847                     //Prioritize next if this Inactive rect is closer to the bottom edge of the container rect, then the previously selected rect
       
   848                     if (differenceContainerBottomEdgeToInactiveRectBottomEdge < mContainerHorizontalEdgeDistance) {
       
   849                         verticalSnappingBetterFit = true;
       
   850                     }
       
   851                     //Prioritize next if the Inactive widget's bottom edge lies near to bottom edge of the container rect
       
   852                     else if (differenceContainerBottomEdgeToInactiveRectBottomEdge < differenceContainerTopEdgeToInactiveRectTopEdge) {
       
   853                         verticalSnappingBetterFit = true;
       
   854                     }
       
   855                     else {
       
   856                         //This else will happen if this rectangle being compared is exactly the same as the selected rectangle for snapping, or in opposite X direction.
       
   857                         //In that case it does not matter which is the selected rectangle. Hence we leave the already selected rectangle as the better fit.
       
   858                     }
       
   859                 }
       
   860             }
       
   861         }
       
   862     }
       
   863 
       
   864     if (verticalSnappingBetterFit) {
       
   865         qreal proposedTopOfActiveRect = minDistancePosition - mActiveRectHeight - ySnapGapAdjustment;
       
   866         if (qBound(mContainerRect.top(), proposedTopOfActiveRect, mContainerRect.bottom())
       
   867             == proposedTopOfActiveRect) {
       
   868             mVerticalSnapFound = true;
       
   869             mVerticalSnapPosition = proposedTopOfActiveRect;
       
   870             mMinHorizontalEdgesDistance = distanceHorizontalEdges;
       
   871             mHorizontalDistanceFromSelectedRect = mHorizontalDistance;
       
   872             //Save the new distance of the Selected Rectangle's bottom edge from Container's bottom edge
       
   873             mContainerHorizontalEdgeDistance = differenceContainerBottomEdgeToInactiveRectBottomEdge;
       
   874 
       
   875             if (mRectLieLeft) {
       
   876                 //save the points for the Horizontal line
       
   877                 mHorizontalLine.setP1(QPointF(mInactiveRectToCompare.left(), minDistancePosition));
       
   878                 mHorizontalLine.setP2(QPointF(mMovingRect.right(), minDistancePosition));
       
   879             }
       
   880             else {
       
   881                 //save the points for the Horizontal line
       
   882                 mHorizontalLine.setP1(QPointF(mInactiveRectToCompare.right(), minDistancePosition));
       
   883                 mHorizontalLine.setP2(QPointF(mMovingRect.left(), minDistancePosition));
       
   884             }
       
   885         }
       
   886     }
       
   887 }
       
   888 
       
   889 /*!
       
   890     Extend the Vertical line on both side of reference(snapping) rectancles.
       
   891 */
       
   892 void HsSnapToLines::extendVerticalLine()
       
   893 {
       
   894     if (mVerticalLine.y1() <= mVerticalLine.y2()) {
       
   895         mVerticalLine.setP1(QPointF(mVerticalLine.x1(), mVerticalLine.y1() - SNAP_LINE_EXTEND_VALUE));
       
   896         mVerticalLine.setP2(QPointF(mVerticalLine.x2(), mVerticalLine.y2() + SNAP_LINE_EXTEND_VALUE));
       
   897     }
       
   898     else {
       
   899         mVerticalLine.setP1(QPointF(mVerticalLine.x1(), mVerticalLine.y1() + SNAP_LINE_EXTEND_VALUE));
       
   900         mVerticalLine.setP2(QPointF(mVerticalLine.x2(), mVerticalLine.y2() - SNAP_LINE_EXTEND_VALUE));
       
   901     }
       
   902 }
       
   903 
       
   904 /*!
       
   905     Extend the Horizontal line on both side of reference(snapping) rectancles.
       
   906 */
       
   907 void HsSnapToLines::extendHorizontalLine()
       
   908 {
       
   909     if (mHorizontalLine.x1() <= mHorizontalLine.x2()) {
       
   910         mHorizontalLine.setP1(QPointF(mHorizontalLine.x1() - SNAP_LINE_EXTEND_VALUE, mHorizontalLine.y1()));
       
   911         mHorizontalLine.setP2(QPointF(mHorizontalLine.x2() + SNAP_LINE_EXTEND_VALUE, mHorizontalLine.y2()));
       
   912     }
       
   913     else {
       
   914         mHorizontalLine.setP1(QPointF(mHorizontalLine.x1() + SNAP_LINE_EXTEND_VALUE, mHorizontalLine.y1()));
       
   915         mHorizontalLine.setP2(QPointF(mHorizontalLine.x2() - SNAP_LINE_EXTEND_VALUE, mHorizontalLine.y2()));
       
   916     }
       
   917 }
       
   918 
       
   919 /*!
       
   920     Check if the Vertical edge of the Rectangle lies out of the Vertical line.
       
   921     Also check if the rectangle's edge lies out of the line.
       
   922 */
       
   923 void HsSnapToLines::checkInactiveRectPositionToVerticalLine()
       
   924 {
       
   925     mRectVerticalEdgeLiesInLineWithVerticalLine = false;
       
   926     mRectLieAboveVerticalLine = false;
       
   927     mRectLieBelowVerticalLine = false;
       
   928 
       
   929     //if rectangle vertical edge lies inline with Vertical line.
       
   930     if ((mLeftInRange && mInactiveRectToCompare.left() == mVerticalLine.x1())
       
   931         || (mRightInRange && mInactiveRectToCompare.right() == mVerticalLine.x1())) {
       
   932         mRectVerticalEdgeLiesInLineWithVerticalLine = true;
       
   933         //if the rectangle lies below the vertical line
       
   934         if (mInactiveRectToCompare.bottom() > mVerticalLine.y1() && mInactiveRectToCompare.bottom() > mVerticalLine.y2()) {
       
   935             mRectLieBelowVerticalLine = true;
       
   936         }
       
   937         //if the rectangle lies above the vertical line
       
   938         if (mInactiveRectToCompare.top() < mVerticalLine.y1() && mInactiveRectToCompare.top() < mVerticalLine.y2()) {
       
   939             mRectLieAboveVerticalLine = true;
       
   940         }
       
   941     }
       
   942 }
       
   943 
       
   944 /*!
       
   945     Increase the Vertical line to include the inactive rect whose vertical edge is inline with vertical line
       
   946 */
       
   947 void HsSnapToLines::extendVerticalLineToIncludeInactiveRect()
       
   948 {
       
   949     if (mRectLieAboveVerticalLine) {
       
   950         if (mVerticalLine.y1() < mVerticalLine.y2()) {
       
   951             mVerticalLine.setP1(QPointF(mVerticalLine.x1(), mInactiveRectToCompare.top()));
       
   952         }
       
   953         else {
       
   954             mVerticalLine.setP2(QPointF(mVerticalLine.x1(), mInactiveRectToCompare.top()));
       
   955         }
       
   956     }
       
   957     if (mRectLieBelowVerticalLine) {
       
   958         if (mVerticalLine.y1() < mVerticalLine.y2()) {
       
   959             mVerticalLine.setP2(QPointF(mVerticalLine.x1(), mInactiveRectToCompare.bottom()));
       
   960         }
       
   961         else {
       
   962             mVerticalLine.setP1(QPointF(mVerticalLine.x1(), mInactiveRectToCompare.bottom()));
       
   963         }
       
   964     }
       
   965 }
       
   966 
       
   967 /*!
       
   968     Check if the Horizontal edge of the Rectangle lies inline with the Horizontal line.
       
   969     Also check if the rectangle's edge lies out of the line.
       
   970 */
       
   971 void HsSnapToLines::checkInactiveRectPositionToHorizontalLine()
       
   972 {
       
   973     mRectHorizontalEdgeLiesInLineWithHorizontalLine = false;
       
   974     mRectLieLeftOfHorizontalLine = false;
       
   975     mRectLiesRightOfHorizontalLine = false;
       
   976 
       
   977     //if rectangle horizontal edge lies inline with Horizontal line.
       
   978     if ((mTopInRange && mInactiveRectToCompare.top() == mHorizontalLine.y1())
       
   979         || (mBottomInRange && mInactiveRectToCompare.bottom() == mHorizontalLine.y1())) {
       
   980         mRectHorizontalEdgeLiesInLineWithHorizontalLine = true;
       
   981         //if the rectangle lies left of the horizontal line
       
   982         if (mInactiveRectToCompare.left() < mHorizontalLine.x1() && mInactiveRectToCompare.left() < mHorizontalLine.x2()) {
       
   983             mRectLieLeftOfHorizontalLine = true;
       
   984         }
       
   985         //if the rectangle lies right of the horizontal line
       
   986         if (mInactiveRectToCompare.right() > mHorizontalLine.x1() && mInactiveRectToCompare.right() > mHorizontalLine.x2()) {
       
   987             mRectLiesRightOfHorizontalLine = true;
       
   988         }
       
   989     }
       
   990 }
       
   991 
       
   992 /*!
       
   993     Increase the Horizontal line to include the inactive rect whose horizontal edge is inline with horizontal line
       
   994 */
       
   995 void HsSnapToLines::extendHorizontalLineToIncludeInactiveRect()
       
   996 {
       
   997     if (mRectLieLeftOfHorizontalLine) {
       
   998         if (mHorizontalLine.x1() < mHorizontalLine.x2()) {
       
   999             mHorizontalLine.setP1(QPointF(mInactiveRectToCompare.left(), mHorizontalLine.y1()));
       
  1000         }
       
  1001         else {
       
  1002             mHorizontalLine.setP2(QPointF(mInactiveRectToCompare.left(), mHorizontalLine.y1()));
       
  1003         }
       
  1004     }
       
  1005     if (mRectLiesRightOfHorizontalLine) {
       
  1006         if (mHorizontalLine.x1() < mHorizontalLine.x2()) {
       
  1007             mHorizontalLine.setP2(QPointF(mInactiveRectToCompare.right(), mHorizontalLine.y1()));
       
  1008         }
       
  1009         else {
       
  1010             mHorizontalLine.setP1(QPointF(mInactiveRectToCompare.right(), mHorizontalLine.y1()));
       
  1011         }
       
  1012     }
       
  1013 }