void QDeclarativeAnchorsPrivate::centerInChanged() { if (!centerIn || fill || !isItemComplete()) return; if (updatingCenterIn < 2) { ++updatingCenterIn; QGraphicsItemPrivate *itemPrivate = QGraphicsItemPrivate::get(item); if (centerIn == item->parentItem()) { QGraphicsItemPrivate *parentPrivate = QGraphicsItemPrivate::get(item->parentItem()); QPointF p((parentPrivate->width() - itemPrivate->width()) / 2. + hCenterOffset, (parentPrivate->height() - itemPrivate->height()) / 2. + vCenterOffset); setItemPos(p); } else if (centerIn->parentItem() == item->parentItem()) { QGraphicsItemPrivate *centerPrivate = QGraphicsItemPrivate::get(centerIn); QPointF p(centerIn->x() + (centerPrivate->width() - itemPrivate->width()) / 2. + hCenterOffset, centerIn->y() + (centerPrivate->height() - itemPrivate->height()) / 2. + vCenterOffset); setItemPos(p); } --updatingCenterIn; } else { // ### Make this certain :) qmlInfo(item) << QDeclarativeAnchors::tr("Possible anchor loop detected on centerIn."); } }
//position when origin is 0,0 static qreal adjustedPosition(QGraphicsObject *item, QDeclarativeAnchorLine::AnchorLine anchorLine) { int ret = 0; QGraphicsItemPrivate *d = QGraphicsItemPrivate::get(item); switch(anchorLine) { case QDeclarativeAnchorLine::Left: ret = 0; break; case QDeclarativeAnchorLine::Right: ret = d->width(); break; case QDeclarativeAnchorLine::Top: ret = 0; break; case QDeclarativeAnchorLine::Bottom: ret = d->height(); break; case QDeclarativeAnchorLine::HCenter: ret = d->width()/2; break; case QDeclarativeAnchorLine::VCenter: ret = d->height()/2; break; case QDeclarativeAnchorLine::Baseline: if (d->isDeclarativeItem) ret = static_cast<QDeclarativeItem*>(item)->baselineOffset(); break; default: break; } return ret; }
void QDeclarativeAnchorsPrivate::updateHorizontalAnchors() { if (fill || centerIn || !isItemComplete()) return; if (updatingHorizontalAnchor < 2) { ++updatingHorizontalAnchor; QGraphicsItemPrivate *itemPrivate = QGraphicsItemPrivate::get(item); if (usedAnchors & QDeclarativeAnchors::LeftAnchor) { //Handle stretching bool invalid = true; int width = 0; if (usedAnchors & QDeclarativeAnchors::RightAnchor) { invalid = calcStretch(left, right, leftMargin, -rightMargin, QDeclarativeAnchorLine::Left, width); } else if (usedAnchors & QDeclarativeAnchors::HCenterAnchor) { invalid = calcStretch(left, hCenter, leftMargin, hCenterOffset, QDeclarativeAnchorLine::Left, width); width *= 2; } if (!invalid) setItemWidth(width); //Handle left if (left.item == item->parentItem()) { setItemX(adjustedPosition(left.item, left.anchorLine) + leftMargin); } else if (left.item->parentItem() == item->parentItem()) { setItemX(position(left.item, left.anchorLine) + leftMargin); } } else if (usedAnchors & QDeclarativeAnchors::RightAnchor) { //Handle stretching (left + right case is handled in updateLeftAnchor) if (usedAnchors & QDeclarativeAnchors::HCenterAnchor) { int width = 0; bool invalid = calcStretch(hCenter, right, hCenterOffset, -rightMargin, QDeclarativeAnchorLine::Left, width); if (!invalid) setItemWidth(width*2); } //Handle right if (right.item == item->parentItem()) { setItemX(adjustedPosition(right.item, right.anchorLine) - itemPrivate->width() - rightMargin); } else if (right.item->parentItem() == item->parentItem()) { setItemX(position(right.item, right.anchorLine) - itemPrivate->width() - rightMargin); } } else if (usedAnchors & QDeclarativeAnchors::HCenterAnchor) { //Handle hCenter if (hCenter.item == item->parentItem()) { setItemX(adjustedPosition(hCenter.item, hCenter.anchorLine) - itemPrivate->width()/2 + hCenterOffset); } else if (hCenter.item->parentItem() == item->parentItem()) { setItemX(position(hCenter.item, hCenter.anchorLine) - itemPrivate->width()/2 + hCenterOffset); } } --updatingHorizontalAnchor; } else { // ### Make this certain :) qmlInfo(item) << QDeclarativeAnchors::tr("Possible anchor loop detected on horizontal anchor."); } }
void QDeclarativeBasePositioner::prePositioning() { Q_D(QDeclarativeBasePositioner); if (!isComponentComplete()) return; if (d->doingPositioning) return; d->queuedPositioning = false; d->doingPositioning = true; //Need to order children by creation order modified by stacking order QList<QGraphicsItem *> children = d->QGraphicsItemPrivate::children; std::sort(children.begin(), children.end(), QGraphicsItemPrivate::insertionOrder); QPODVector<PositionedItem,8> oldItems; positionedItems.copyAndClear(oldItems); for (int ii = 0; ii < children.count(); ++ii) { QGraphicsObject *child = children.at(ii)->toGraphicsObject(); if (!child) continue; QGraphicsItemPrivate *childPrivate = static_cast<QGraphicsItemPrivate*>(QGraphicsItemPrivate::get(child)); PositionedItem *item = 0; PositionedItem posItem(child); int wIdx = oldItems.find(posItem); if (wIdx < 0) { d->watchChanges(child); positionedItems.append(posItem); item = &positionedItems[positionedItems.count()-1]; item->isNew = true; if (child->opacity() <= 0.0 || childPrivate->explicitlyHidden || !childPrivate->width() || !childPrivate->height()) item->isVisible = false; } else { item = &oldItems[wIdx]; // Items are only omitted from positioning if they are explicitly hidden // i.e. their positioning is not affected if an ancestor is hidden. if (child->opacity() <= 0.0 || childPrivate->explicitlyHidden || !childPrivate->width() || !childPrivate->height()) { item->isVisible = false; } else if (!item->isVisible) { item->isVisible = true; item->isNew = true; } else { item->isNew = false; } positionedItems.append(*item); } } QSizeF contentSize; doPositioning(&contentSize); if(d->addTransition || d->moveTransition) finishApplyTransitions(); d->doingPositioning = false; //Set implicit size to the size of its children setImplicitHeight(contentSize.height()); setImplicitWidth(contentSize.width()); }
/* Depends on the width/height of the back item, and so needs reevaulating if those change. */ void QDeclarativeFlipablePrivate::setBackTransform() { QTransform mat; QGraphicsItemPrivate *dBack = QGraphicsItemPrivate::get(back); mat.translate(dBack->width()/2,dBack->height()/2); if (dBack->width() && wantBackYFlipped) mat.rotate(180, Qt::YAxis); if (dBack->height() && wantBackXFlipped) mat.rotate(180, Qt::XAxis); mat.translate(-dBack->width()/2,-dBack->height()/2); back->setTransform(mat); }
//### const item? //local position static qreal position(QGraphicsObject *item, QDeclarativeAnchorLine::AnchorLine anchorLine) { qreal ret = 0.0; QGraphicsItemPrivate *d = QGraphicsItemPrivate::get(item); switch(anchorLine) { case QDeclarativeAnchorLine::Left: ret = item->x(); break; case QDeclarativeAnchorLine::Right: ret = item->x() + d->width(); break; case QDeclarativeAnchorLine::Top: ret = item->y(); break; case QDeclarativeAnchorLine::Bottom: ret = item->y() + d->height(); break; case QDeclarativeAnchorLine::HCenter: ret = item->x() + hcenter(item); break; case QDeclarativeAnchorLine::VCenter: ret = item->y() + vcenter(item); break; case QDeclarativeAnchorLine::Baseline: if (d->isDeclarativeItem) ret = item->y() + static_cast<QDeclarativeItem*>(item)->baselineOffset(); break; default: break; } return ret; }
void QDeclarativeAnchorsPrivate::fillChanged() { Q_Q(QDeclarativeAnchors); if (!fill || !isItemComplete()) return; if (updatingFill < 2) { ++updatingFill; qreal horizontalMargin = q->mirrored() ? rightMargin : leftMargin; if (fill == item->parentItem()) { //child-parent setItemPos(QPointF(horizontalMargin, topMargin)); } else if (fill->parentItem() == item->parentItem()) { //siblings setItemPos(QPointF(fill->x()+horizontalMargin, fill->y()+topMargin)); } QGraphicsItemPrivate *fillPrivate = QGraphicsItemPrivate::get(fill); setItemSize(QSizeF(fillPrivate->width()-leftMargin-rightMargin, fillPrivate->height()-topMargin-bottomMargin)); --updatingFill; } else { // ### Make this certain :) qmlInfo(item) << QDeclarativeAnchors::tr("Possible anchor loop detected on fill."); } }
QT_BEGIN_NAMESPACE //TODO: should we cache relationships, so we don't have to check each time (parent-child or sibling)? //TODO: support non-parent, non-sibling (need to find lowest common ancestor) //### const item? //local position static qreal position(QGraphicsObject *item, QDeclarativeAnchorLine::AnchorLine anchorLine) { qreal ret = 0.0; QGraphicsItemPrivate *d = QGraphicsItemPrivate::get(item); switch(anchorLine) { case QDeclarativeAnchorLine::Left: ret = item->x(); break; case QDeclarativeAnchorLine::Right: ret = item->x() + d->width(); break; case QDeclarativeAnchorLine::Top: ret = item->y(); break; case QDeclarativeAnchorLine::Bottom: ret = item->y() + d->height(); break; case QDeclarativeAnchorLine::HCenter: ret = item->x() + d->width()/2; break; case QDeclarativeAnchorLine::VCenter: ret = item->y() + d->height()/2; break; case QDeclarativeAnchorLine::Baseline: if (d->isDeclarativeItem) ret = item->y() + static_cast<QDeclarativeItem*>(item)->baselineOffset(); break; default: break; } return ret; }
QT_BEGIN_NAMESPACE //TODO: should we cache relationships, so we don't have to check each time (parent-child or sibling)? //TODO: support non-parent, non-sibling (need to find lowest common ancestor) static qreal hcenter(QGraphicsItem *i) { QGraphicsItemPrivate *item = QGraphicsItemPrivate::get(i); qreal width = item->width(); int iw = width; if (iw % 2) return (width + 1) / 2; else return width / 2; }
void QDeclarativeAnchorsPrivate::updateHorizontalAnchors() { Q_Q(QDeclarativeAnchors); if (fill || centerIn || !isItemComplete()) return; if (updatingHorizontalAnchor < 3) { ++updatingHorizontalAnchor; qreal effectiveRightMargin, effectiveLeftMargin, effectiveHorizontalCenterOffset; QDeclarativeAnchorLine effectiveLeft, effectiveRight, effectiveHorizontalCenter; QDeclarativeAnchors::Anchor effectiveLeftAnchor, effectiveRightAnchor; if (q->mirrored()) { effectiveLeftAnchor = QDeclarativeAnchors::RightAnchor; effectiveRightAnchor = QDeclarativeAnchors::LeftAnchor; effectiveLeft.item = right.item; effectiveLeft.anchorLine = reverseAnchorLine(right.anchorLine); effectiveRight.item = left.item; effectiveRight.anchorLine = reverseAnchorLine(left.anchorLine); effectiveHorizontalCenter.item = hCenter.item; effectiveHorizontalCenter.anchorLine = reverseAnchorLine(hCenter.anchorLine); effectiveLeftMargin = rightMargin; effectiveRightMargin = leftMargin; effectiveHorizontalCenterOffset = -hCenterOffset; } else { effectiveLeftAnchor = QDeclarativeAnchors::LeftAnchor; effectiveRightAnchor = QDeclarativeAnchors::RightAnchor; effectiveLeft = left; effectiveRight = right; effectiveHorizontalCenter = hCenter; effectiveLeftMargin = leftMargin; effectiveRightMargin = rightMargin; effectiveHorizontalCenterOffset = hCenterOffset; } QGraphicsItemPrivate *itemPrivate = QGraphicsItemPrivate::get(item); if (usedAnchors & effectiveLeftAnchor) { //Handle stretching bool invalid = true; qreal width = 0.0; if (usedAnchors & effectiveRightAnchor) { invalid = calcStretch(effectiveLeft, effectiveRight, effectiveLeftMargin, -effectiveRightMargin, QDeclarativeAnchorLine::Left, width); } else if (usedAnchors & QDeclarativeAnchors::HCenterAnchor) { invalid = calcStretch(effectiveLeft, effectiveHorizontalCenter, effectiveLeftMargin, effectiveHorizontalCenterOffset, QDeclarativeAnchorLine::Left, width); width *= 2; } if (!invalid) setItemWidth(width); //Handle left if (effectiveLeft.item == item->parentItem()) { setItemX(adjustedPosition(effectiveLeft.item, effectiveLeft.anchorLine) + effectiveLeftMargin); } else if (effectiveLeft.item->parentItem() == item->parentItem()) { setItemX(position(effectiveLeft.item, effectiveLeft.anchorLine) + effectiveLeftMargin); } } else if (usedAnchors & effectiveRightAnchor) { //Handle stretching (left + right case is handled in updateLeftAnchor) if (usedAnchors & QDeclarativeAnchors::HCenterAnchor) { qreal width = 0.0; bool invalid = calcStretch(effectiveHorizontalCenter, effectiveRight, effectiveHorizontalCenterOffset, -effectiveRightMargin, QDeclarativeAnchorLine::Left, width); if (!invalid) setItemWidth(width*2); } //Handle right if (effectiveRight.item == item->parentItem()) { setItemX(adjustedPosition(effectiveRight.item, effectiveRight.anchorLine) - itemPrivate->width() - effectiveRightMargin); } else if (effectiveRight.item->parentItem() == item->parentItem()) { setItemX(position(effectiveRight.item, effectiveRight.anchorLine) - itemPrivate->width() - effectiveRightMargin); } } else if (usedAnchors & QDeclarativeAnchors::HCenterAnchor) { //Handle hCenter if (effectiveHorizontalCenter.item == item->parentItem()) { setItemX(adjustedPosition(effectiveHorizontalCenter.item, effectiveHorizontalCenter.anchorLine) - hcenter(item) + effectiveHorizontalCenterOffset); } else if (effectiveHorizontalCenter.item->parentItem() == item->parentItem()) { setItemX(position(effectiveHorizontalCenter.item, effectiveHorizontalCenter.anchorLine) - hcenter(item) + effectiveHorizontalCenterOffset); } } --updatingHorizontalAnchor; } else { // ### Make this certain :) qmlInfo(item) << QDeclarativeAnchors::tr("Possible anchor loop detected on horizontal anchor."); } }
void QDeclarativeGrid::doPositioning(QSizeF *contentSize) { QDeclarativeBasePositionerPrivate *d = static_cast<QDeclarativeBasePositionerPrivate*>(QDeclarativeBasePositionerPrivate::get(this)); int c = m_columns; int r = m_rows; //Is allocating the extra QPODVector too much overhead? QPODVector<PositionedItem, 8> visibleItems;//we aren't concerned with invisible items visibleItems.reserve(positionedItems.count()); for(int i=0; i<positionedItems.count(); i++) if(positionedItems[i].item && positionedItems[i].isVisible) visibleItems.append(positionedItems[i]); int numVisible = visibleItems.count(); if (m_columns <= 0 && m_rows <= 0) { c = 4; r = (numVisible+3)/4; } else if (m_rows <= 0) { r = (numVisible+(m_columns-1))/m_columns; } else if (m_columns <= 0) { c = (numVisible+(m_rows-1))/m_rows; } if(r==0 || c==0) return; //Nothing to do QList<int> maxColWidth; QList<int> maxRowHeight; int childIndex =0; if (m_flow == LeftToRight) { for (int i=0; i < r; i++) { for (int j=0; j < c; j++) { if (j==0) maxRowHeight << 0; if (i==0) maxColWidth << 0; if (childIndex == visibleItems.count()) break; const PositionedItem &child = visibleItems.at(childIndex++); QGraphicsItemPrivate *childPrivate = QGraphicsItemPrivate::get(child.item); if (childPrivate->width() > maxColWidth[j]) maxColWidth[j] = childPrivate->width(); if (childPrivate->height() > maxRowHeight[i]) maxRowHeight[i] = childPrivate->height(); } } } else { for (int j=0; j < c; j++) { for (int i=0; i < r; i++) { if (j==0) maxRowHeight << 0; if (i==0) maxColWidth << 0; if (childIndex == visibleItems.count()) break; const PositionedItem &child = visibleItems.at(childIndex++); QGraphicsItemPrivate *childPrivate = QGraphicsItemPrivate::get(child.item); if (childPrivate->width() > maxColWidth[j]) maxColWidth[j] = childPrivate->width(); if (childPrivate->height() > maxRowHeight[i]) maxRowHeight[i] = childPrivate->height(); } } } int widthSum = 0; for(int j=0; j < maxColWidth.size(); j++) { if(j) widthSum += spacing(); widthSum += maxColWidth[j]; } int heightSum = 0; for(int i=0; i < maxRowHeight.size(); i++) { if(i) heightSum += spacing(); heightSum += maxRowHeight[i]; } contentSize->setHeight(heightSum); contentSize->setWidth(widthSum); int end = 0; if(widthValid()) end = width(); else end = widthSum; int xoffset=0; if(!d->isLeftToRight()) xoffset=end; int yoffset=0; int curRow =0; int curCol =0; for (int i = 0; i < visibleItems.count(); ++i) { const PositionedItem &child = visibleItems.at(i); int childXOffset = xoffset; if(!d->isLeftToRight()) childXOffset -= QGraphicsItemPrivate::get(child.item)->width(); if((child.item->x()!=childXOffset)||(child.item->y()!=yoffset)) { positionX(childXOffset, child); positionY(yoffset, child); } if (m_flow == LeftToRight) { if(d->isLeftToRight()) xoffset+=maxColWidth[curCol]+spacing(); else xoffset-=maxColWidth[curCol]+spacing(); curCol++; curCol%=c; if (!curCol) { yoffset+=maxRowHeight[curRow]+spacing(); if(d->isLeftToRight()) xoffset=0; else xoffset=end; curRow++; if (curRow>=r) break; } } else { yoffset+=maxRowHeight[curRow]+spacing(); curRow++; curRow%=r; if (!curRow) { if(d->isLeftToRight()) xoffset+=maxColWidth[curCol]+spacing(); else xoffset-=maxColWidth[curCol]+spacing(); yoffset=0; curCol++; if (curCol>=c) break; } } } }
void QDeclarativeFlow::doPositioning(QSizeF *contentSize) { Q_D(QDeclarativeFlow); int hoffset = 0; int voffset = 0; int linemax = 0; QList<int> hoffsets; for (int i = 0; i < positionedItems.count(); ++i) { const PositionedItem &child = positionedItems.at(i); if (!child.item || !child.isVisible) continue; QGraphicsItemPrivate *childPrivate = QGraphicsItemPrivate::get(child.item); if (d->flow == LeftToRight) { if (widthValid() && hoffset && hoffset + childPrivate->width() > width()) { hoffset = 0; voffset += linemax + spacing(); linemax = 0; } } else { if (heightValid() && voffset && voffset + childPrivate->height() > height()) { voffset = 0; hoffset += linemax + spacing(); linemax = 0; } } if(d->isLeftToRight()) { if(child.item->x() != hoffset) positionX(hoffset, child); } else { hoffsets << hoffset; } if(child.item->y() != voffset) positionY(voffset, child); contentSize->setWidth(qMax(contentSize->width(), hoffset + childPrivate->width())); contentSize->setHeight(qMax(contentSize->height(), voffset + childPrivate->height())); if (d->flow == LeftToRight) { hoffset += childPrivate->width(); hoffset += spacing(); linemax = qMax(linemax, qCeil(childPrivate->height())); } else { voffset += childPrivate->height(); voffset += spacing(); linemax = qMax(linemax, qCeil(childPrivate->width())); } } if(d->isLeftToRight()) return; int end; if(widthValid()) end = width(); else end = contentSize->width(); int acc = 0; for (int i = 0; i < positionedItems.count(); ++i) { const PositionedItem &child = positionedItems.at(i); if (!child.item || !child.isVisible) continue; hoffset = end - hoffsets[acc++] - QGraphicsItemPrivate::get(child.item)->width(); if(child.item->x() != hoffset) positionX(hoffset, child); } }