src/declarative/graphicsitems/qdeclarativeanchors.cpp
changeset 33 3e2da88830cd
parent 30 5dc02b23752f
child 37 758a864f9613
equal deleted inserted replaced
30:5dc02b23752f 33:3e2da88830cd
    51 QT_BEGIN_NAMESPACE
    51 QT_BEGIN_NAMESPACE
    52 
    52 
    53 //TODO: should we cache relationships, so we don't have to check each time (parent-child or sibling)?
    53 //TODO: should we cache relationships, so we don't have to check each time (parent-child or sibling)?
    54 //TODO: support non-parent, non-sibling (need to find lowest common ancestor)
    54 //TODO: support non-parent, non-sibling (need to find lowest common ancestor)
    55 
    55 
       
    56 static qreal hcenter(QGraphicsItem *i)
       
    57 {
       
    58     QGraphicsItemPrivate *item = QGraphicsItemPrivate::get(i);
       
    59 
       
    60     qreal width = item->width();
       
    61     int iw = width;
       
    62     if (iw % 2)
       
    63         return (width + 1) / 2;
       
    64     else
       
    65         return width / 2;
       
    66 }
       
    67 
       
    68 static qreal vcenter(QGraphicsItem *i)
       
    69 {
       
    70     QGraphicsItemPrivate *item = QGraphicsItemPrivate::get(i);
       
    71 
       
    72     qreal height = item->height();
       
    73     int ih = height;
       
    74     if (ih % 2)
       
    75         return (height + 1) / 2;
       
    76     else
       
    77         return height / 2;
       
    78 }
       
    79 
    56 //### const item?
    80 //### const item?
    57 //local position
    81 //local position
    58 static qreal position(QGraphicsObject *item, QDeclarativeAnchorLine::AnchorLine anchorLine)
    82 static qreal position(QGraphicsObject *item, QDeclarativeAnchorLine::AnchorLine anchorLine)
    59 {
    83 {
    60     qreal ret = 0.0;
    84     qreal ret = 0.0;
    71         break;
    95         break;
    72     case QDeclarativeAnchorLine::Bottom:
    96     case QDeclarativeAnchorLine::Bottom:
    73         ret = item->y() + d->height();
    97         ret = item->y() + d->height();
    74         break;
    98         break;
    75     case QDeclarativeAnchorLine::HCenter:
    99     case QDeclarativeAnchorLine::HCenter:
    76         ret = item->x() + d->width()/2;
   100         ret = item->x() + hcenter(item);
    77         break;
   101         break;
    78     case QDeclarativeAnchorLine::VCenter:
   102     case QDeclarativeAnchorLine::VCenter:
    79         ret = item->y() + d->height()/2;
   103         ret = item->y() + vcenter(item);
    80         break;
   104         break;
    81     case QDeclarativeAnchorLine::Baseline:
   105     case QDeclarativeAnchorLine::Baseline:
    82         if (d->isDeclarativeItem)
   106         if (d->isDeclarativeItem)
    83             ret = item->y() + static_cast<QDeclarativeItem*>(item)->baselineOffset();
   107             ret = item->y() + static_cast<QDeclarativeItem*>(item)->baselineOffset();
    84         break;
   108         break;
    90 }
   114 }
    91 
   115 
    92 //position when origin is 0,0
   116 //position when origin is 0,0
    93 static qreal adjustedPosition(QGraphicsObject *item, QDeclarativeAnchorLine::AnchorLine anchorLine)
   117 static qreal adjustedPosition(QGraphicsObject *item, QDeclarativeAnchorLine::AnchorLine anchorLine)
    94 {
   118 {
    95     int ret = 0;
   119     qreal ret = 0.0;
    96     QGraphicsItemPrivate *d = QGraphicsItemPrivate::get(item);
   120     QGraphicsItemPrivate *d = QGraphicsItemPrivate::get(item);
    97     switch(anchorLine) {
   121     switch(anchorLine) {
    98     case QDeclarativeAnchorLine::Left:
   122     case QDeclarativeAnchorLine::Left:
    99         ret = 0;
   123         ret = 0.0;
   100         break;
   124         break;
   101     case QDeclarativeAnchorLine::Right:
   125     case QDeclarativeAnchorLine::Right:
   102         ret = d->width();
   126         ret = d->width();
   103         break;
   127         break;
   104     case QDeclarativeAnchorLine::Top:
   128     case QDeclarativeAnchorLine::Top:
   105         ret = 0;
   129         ret = 0.0;
   106         break;
   130         break;
   107     case QDeclarativeAnchorLine::Bottom:
   131     case QDeclarativeAnchorLine::Bottom:
   108         ret = d->height();
   132         ret = d->height();
   109         break;
   133         break;
   110     case QDeclarativeAnchorLine::HCenter:
   134     case QDeclarativeAnchorLine::HCenter:
   111         ret = d->width()/2;
   135         ret = hcenter(item);
   112         break;
   136         break;
   113     case QDeclarativeAnchorLine::VCenter:
   137     case QDeclarativeAnchorLine::VCenter:
   114         ret = d->height()/2;
   138         ret = vcenter(item);
   115         break;
   139         break;
   116     case QDeclarativeAnchorLine::Baseline:
   140     case QDeclarativeAnchorLine::Baseline:
   117         if (d->isDeclarativeItem)
   141         if (d->isDeclarativeItem)
   118             ret = static_cast<QDeclarativeItem*>(item)->baselineOffset();
   142             ret = static_cast<QDeclarativeItem*>(item)->baselineOffset();
   119         break;
   143         break;
   187     if (!centerIn || fill || !isItemComplete())
   211     if (!centerIn || fill || !isItemComplete())
   188         return;
   212         return;
   189 
   213 
   190     if (updatingCenterIn < 2) {
   214     if (updatingCenterIn < 2) {
   191         ++updatingCenterIn;
   215         ++updatingCenterIn;
   192         QGraphicsItemPrivate *itemPrivate = QGraphicsItemPrivate::get(item);
       
   193         if (centerIn == item->parentItem()) {
   216         if (centerIn == item->parentItem()) {
   194             QGraphicsItemPrivate *parentPrivate = QGraphicsItemPrivate::get(item->parentItem());
   217             QPointF p(hcenter(item->parentItem()) - hcenter(item) + hCenterOffset,
   195             QPointF p((parentPrivate->width() - itemPrivate->width()) / 2. + hCenterOffset,
   218                       vcenter(item->parentItem()) - vcenter(item) + vCenterOffset);
   196                       (parentPrivate->height() - itemPrivate->height()) / 2. + vCenterOffset);
       
   197             setItemPos(p);
   219             setItemPos(p);
   198 
   220 
   199         } else if (centerIn->parentItem() == item->parentItem()) {
   221         } else if (centerIn->parentItem() == item->parentItem()) {
   200             QGraphicsItemPrivate *centerPrivate = QGraphicsItemPrivate::get(centerIn);
   222             QPointF p(centerIn->x() + hcenter(centerIn) - hcenter(item) + hCenterOffset,
   201             QPointF p(centerIn->x() + (centerPrivate->width() - itemPrivate->width()) / 2. + hCenterOffset,
   223                       centerIn->y() + vcenter(centerIn) - vcenter(item) + vCenterOffset);
   202                       centerIn->y() + (centerPrivate->height() - itemPrivate->height()) / 2. + vCenterOffset);
       
   203             setItemPos(p);
   224             setItemPos(p);
   204         }
   225         }
   205 
   226 
   206         --updatingCenterIn;
   227         --updatingCenterIn;
   207     } else {
   228     } else {
   457     setCenterIn(0);
   478     setCenterIn(0);
   458 }
   479 }
   459 
   480 
   460 bool QDeclarativeAnchorsPrivate::calcStretch(const QDeclarativeAnchorLine &edge1,
   481 bool QDeclarativeAnchorsPrivate::calcStretch(const QDeclarativeAnchorLine &edge1,
   461                                     const QDeclarativeAnchorLine &edge2,
   482                                     const QDeclarativeAnchorLine &edge2,
   462                                     int offset1,
   483                                     qreal offset1,
   463                                     int offset2,
   484                                     qreal offset2,
   464                                     QDeclarativeAnchorLine::AnchorLine line,
   485                                     QDeclarativeAnchorLine::AnchorLine line,
   465                                     int &stretch)
   486                                     qreal &stretch)
   466 {
   487 {
   467     bool edge1IsParent = (edge1.item == item->parentItem());
   488     bool edge1IsParent = (edge1.item == item->parentItem());
   468     bool edge2IsParent = (edge2.item == item->parentItem());
   489     bool edge2IsParent = (edge2.item == item->parentItem());
   469     bool edge1IsSibling = (edge1.item->parentItem() == item->parentItem());
   490     bool edge1IsSibling = (edge1.item->parentItem() == item->parentItem());
   470     bool edge2IsSibling = (edge2.item->parentItem() == item->parentItem());
   491     bool edge2IsSibling = (edge2.item->parentItem() == item->parentItem());
   471 
   492 
   472     bool invalid = false;
   493     bool invalid = false;
   473     if ((edge2IsParent && edge1IsParent) || (edge2IsSibling && edge1IsSibling)) {
   494     if ((edge2IsParent && edge1IsParent) || (edge2IsSibling && edge1IsSibling)) {
   474         stretch = ((int)position(edge2.item, edge2.anchorLine) + offset2)
   495         stretch = (position(edge2.item, edge2.anchorLine) + offset2)
   475                     - ((int)position(edge1.item, edge1.anchorLine) + offset1);
   496                     - (position(edge1.item, edge1.anchorLine) + offset1);
   476     } else if (edge2IsParent && edge1IsSibling) {
   497     } else if (edge2IsParent && edge1IsSibling) {
   477         stretch = ((int)position(edge2.item, edge2.anchorLine) + offset2)
   498         stretch = (position(edge2.item, edge2.anchorLine) + offset2)
   478                     - ((int)position(item->parentObject(), line)
   499                     - (position(item->parentObject(), line)
   479                     + (int)position(edge1.item, edge1.anchorLine) + offset1);
   500                     + position(edge1.item, edge1.anchorLine) + offset1);
   480     } else if (edge2IsSibling && edge1IsParent) {
   501     } else if (edge2IsSibling && edge1IsParent) {
   481         stretch = ((int)position(item->parentObject(), line) + (int)position(edge2.item, edge2.anchorLine) + offset2)
   502         stretch = (position(item->parentObject(), line) + position(edge2.item, edge2.anchorLine) + offset2)
   482                     - ((int)position(edge1.item, edge1.anchorLine) + offset1);
   503                     - (position(edge1.item, edge1.anchorLine) + offset1);
   483     } else
   504     } else
   484         invalid = true;
   505         invalid = true;
   485 
   506 
   486     return invalid;
   507     return invalid;
   487 }
   508 }
   495         ++updatingVerticalAnchor;
   516         ++updatingVerticalAnchor;
   496         QGraphicsItemPrivate *itemPrivate = QGraphicsItemPrivate::get(item);
   517         QGraphicsItemPrivate *itemPrivate = QGraphicsItemPrivate::get(item);
   497         if (usedAnchors & QDeclarativeAnchors::TopAnchor) {
   518         if (usedAnchors & QDeclarativeAnchors::TopAnchor) {
   498             //Handle stretching
   519             //Handle stretching
   499             bool invalid = true;
   520             bool invalid = true;
   500             int height = 0;
   521             qreal height = 0.0;
   501             if (usedAnchors & QDeclarativeAnchors::BottomAnchor) {
   522             if (usedAnchors & QDeclarativeAnchors::BottomAnchor) {
   502                 invalid = calcStretch(top, bottom, topMargin, -bottomMargin, QDeclarativeAnchorLine::Top, height);
   523                 invalid = calcStretch(top, bottom, topMargin, -bottomMargin, QDeclarativeAnchorLine::Top, height);
   503             } else if (usedAnchors & QDeclarativeAnchors::VCenterAnchor) {
   524             } else if (usedAnchors & QDeclarativeAnchors::VCenterAnchor) {
   504                 invalid = calcStretch(top, vCenter, topMargin, vCenterOffset, QDeclarativeAnchorLine::Top, height);
   525                 invalid = calcStretch(top, vCenter, topMargin, vCenterOffset, QDeclarativeAnchorLine::Top, height);
   505                 height *= 2;
   526                 height *= 2;
   514                 setItemY(position(top.item, top.anchorLine) + topMargin);
   535                 setItemY(position(top.item, top.anchorLine) + topMargin);
   515             }
   536             }
   516         } else if (usedAnchors & QDeclarativeAnchors::BottomAnchor) {
   537         } else if (usedAnchors & QDeclarativeAnchors::BottomAnchor) {
   517             //Handle stretching (top + bottom case is handled above)
   538             //Handle stretching (top + bottom case is handled above)
   518             if (usedAnchors & QDeclarativeAnchors::VCenterAnchor) {
   539             if (usedAnchors & QDeclarativeAnchors::VCenterAnchor) {
   519                 int height = 0;
   540                 qreal height = 0.0;
   520                 bool invalid = calcStretch(vCenter, bottom, vCenterOffset, -bottomMargin,
   541                 bool invalid = calcStretch(vCenter, bottom, vCenterOffset, -bottomMargin,
   521                                               QDeclarativeAnchorLine::Top, height);
   542                                               QDeclarativeAnchorLine::Top, height);
   522                 if (!invalid)
   543                 if (!invalid)
   523                     setItemHeight(height*2);
   544                     setItemHeight(height*2);
   524             }
   545             }
   533             //(stetching handled above)
   554             //(stetching handled above)
   534 
   555 
   535             //Handle vCenter
   556             //Handle vCenter
   536             if (vCenter.item == item->parentItem()) {
   557             if (vCenter.item == item->parentItem()) {
   537                 setItemY(adjustedPosition(vCenter.item, vCenter.anchorLine)
   558                 setItemY(adjustedPosition(vCenter.item, vCenter.anchorLine)
   538                               - itemPrivate->height()/2 + vCenterOffset);
   559                               - vcenter(item) + vCenterOffset);
   539             } else if (vCenter.item->parentItem() == item->parentItem()) {
   560             } else if (vCenter.item->parentItem() == item->parentItem()) {
   540                 setItemY(position(vCenter.item, vCenter.anchorLine) - itemPrivate->height()/2 + vCenterOffset);
   561                 setItemY(position(vCenter.item, vCenter.anchorLine) - vcenter(item) + vCenterOffset);
   541             }
   562             }
   542         } else if (usedAnchors & QDeclarativeAnchors::BaselineAnchor) {
   563         } else if (usedAnchors & QDeclarativeAnchors::BaselineAnchor) {
   543             //Handle baseline
   564             //Handle baseline
   544             if (baseline.item == item->parentItem()) {
   565             if (baseline.item == item->parentItem()) {
   545                 if (itemPrivate->isDeclarativeItem)
   566                 if (itemPrivate->isDeclarativeItem)
   567         ++updatingHorizontalAnchor;
   588         ++updatingHorizontalAnchor;
   568         QGraphicsItemPrivate *itemPrivate = QGraphicsItemPrivate::get(item);
   589         QGraphicsItemPrivate *itemPrivate = QGraphicsItemPrivate::get(item);
   569         if (usedAnchors & QDeclarativeAnchors::LeftAnchor) {
   590         if (usedAnchors & QDeclarativeAnchors::LeftAnchor) {
   570             //Handle stretching
   591             //Handle stretching
   571             bool invalid = true;
   592             bool invalid = true;
   572             int width = 0;
   593             qreal width = 0.0;
   573             if (usedAnchors & QDeclarativeAnchors::RightAnchor) {
   594             if (usedAnchors & QDeclarativeAnchors::RightAnchor) {
   574                 invalid = calcStretch(left, right, leftMargin, -rightMargin, QDeclarativeAnchorLine::Left, width);
   595                 invalid = calcStretch(left, right, leftMargin, -rightMargin, QDeclarativeAnchorLine::Left, width);
   575             } else if (usedAnchors & QDeclarativeAnchors::HCenterAnchor) {
   596             } else if (usedAnchors & QDeclarativeAnchors::HCenterAnchor) {
   576                 invalid = calcStretch(left, hCenter, leftMargin, hCenterOffset, QDeclarativeAnchorLine::Left, width);
   597                 invalid = calcStretch(left, hCenter, leftMargin, hCenterOffset, QDeclarativeAnchorLine::Left, width);
   577                 width *= 2;
   598                 width *= 2;
   586                 setItemX(position(left.item, left.anchorLine) + leftMargin);
   607                 setItemX(position(left.item, left.anchorLine) + leftMargin);
   587             }
   608             }
   588         } else if (usedAnchors & QDeclarativeAnchors::RightAnchor) {
   609         } else if (usedAnchors & QDeclarativeAnchors::RightAnchor) {
   589             //Handle stretching (left + right case is handled in updateLeftAnchor)
   610             //Handle stretching (left + right case is handled in updateLeftAnchor)
   590             if (usedAnchors & QDeclarativeAnchors::HCenterAnchor) {
   611             if (usedAnchors & QDeclarativeAnchors::HCenterAnchor) {
   591                 int width = 0;
   612                 qreal width = 0.0;
   592                 bool invalid = calcStretch(hCenter, right, hCenterOffset, -rightMargin,
   613                 bool invalid = calcStretch(hCenter, right, hCenterOffset, -rightMargin,
   593                                               QDeclarativeAnchorLine::Left, width);
   614                                               QDeclarativeAnchorLine::Left, width);
   594                 if (!invalid)
   615                 if (!invalid)
   595                     setItemWidth(width*2);
   616                     setItemWidth(width*2);
   596             }
   617             }
   602                 setItemX(position(right.item, right.anchorLine) - itemPrivate->width() - rightMargin);
   623                 setItemX(position(right.item, right.anchorLine) - itemPrivate->width() - rightMargin);
   603             }
   624             }
   604         } else if (usedAnchors & QDeclarativeAnchors::HCenterAnchor) {
   625         } else if (usedAnchors & QDeclarativeAnchors::HCenterAnchor) {
   605             //Handle hCenter
   626             //Handle hCenter
   606             if (hCenter.item == item->parentItem()) {
   627             if (hCenter.item == item->parentItem()) {
   607                 setItemX(adjustedPosition(hCenter.item, hCenter.anchorLine) - itemPrivate->width()/2 + hCenterOffset);
   628                 setItemX(adjustedPosition(hCenter.item, hCenter.anchorLine) - hcenter(item) + hCenterOffset);
   608             } else if (hCenter.item->parentItem() == item->parentItem()) {
   629             } else if (hCenter.item->parentItem() == item->parentItem()) {
   609                 setItemX(position(hCenter.item, hCenter.anchorLine) - itemPrivate->width()/2 + hCenterOffset);
   630                 setItemX(position(hCenter.item, hCenter.anchorLine) - hcenter(item) + hCenterOffset);
   610             }
   631             }
   611         }
   632         }
   612 
   633 
   613         --updatingHorizontalAnchor;
   634         --updatingHorizontalAnchor;
   614     } else {
   635     } else {