//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::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."); } }
/* 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."); } }
static qreal vcenter(QGraphicsItem *i) { QGraphicsItemPrivate *item = QGraphicsItemPrivate::get(i); qreal height = item->height(); int ih = height; if (ih % 2) return (height + 1) / 2; else return height / 2; }
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; }
void QDeclarativeAnchorsPrivate::updateVerticalAnchors() { if (fill || centerIn || !isItemComplete()) return; if (updatingVerticalAnchor < 2) { ++updatingVerticalAnchor; QGraphicsItemPrivate *itemPrivate = QGraphicsItemPrivate::get(item); if (usedAnchors & QDeclarativeAnchors::TopAnchor) { //Handle stretching bool invalid = true; qreal height = 0.0; if (usedAnchors & QDeclarativeAnchors::BottomAnchor) { invalid = calcStretch(top, bottom, topMargin, -bottomMargin, QDeclarativeAnchorLine::Top, height); } else if (usedAnchors & QDeclarativeAnchors::VCenterAnchor) { invalid = calcStretch(top, vCenter, topMargin, vCenterOffset, QDeclarativeAnchorLine::Top, height); height *= 2; } if (!invalid) setItemHeight(height); //Handle top if (top.item == item->parentItem()) { setItemY(adjustedPosition(top.item, top.anchorLine) + topMargin); } else if (top.item->parentItem() == item->parentItem()) { setItemY(position(top.item, top.anchorLine) + topMargin); } } else if (usedAnchors & QDeclarativeAnchors::BottomAnchor) { //Handle stretching (top + bottom case is handled above) if (usedAnchors & QDeclarativeAnchors::VCenterAnchor) { qreal height = 0.0; bool invalid = calcStretch(vCenter, bottom, vCenterOffset, -bottomMargin, QDeclarativeAnchorLine::Top, height); if (!invalid) setItemHeight(height*2); } //Handle bottom if (bottom.item == item->parentItem()) { setItemY(adjustedPosition(bottom.item, bottom.anchorLine) - itemPrivate->height() - bottomMargin); } else if (bottom.item->parentItem() == item->parentItem()) { setItemY(position(bottom.item, bottom.anchorLine) - itemPrivate->height() - bottomMargin); } } else if (usedAnchors & QDeclarativeAnchors::VCenterAnchor) { //(stetching handled above) //Handle vCenter if (vCenter.item == item->parentItem()) { setItemY(adjustedPosition(vCenter.item, vCenter.anchorLine) - vcenter(item) + vCenterOffset); } else if (vCenter.item->parentItem() == item->parentItem()) { setItemY(position(vCenter.item, vCenter.anchorLine) - vcenter(item) + vCenterOffset); } } else if (usedAnchors & QDeclarativeAnchors::BaselineAnchor) { //Handle baseline if (baseline.item == item->parentItem()) { if (itemPrivate->isDeclarativeItem) setItemY(adjustedPosition(baseline.item, baseline.anchorLine) - static_cast<QDeclarativeItem *>(item)->baselineOffset() + baselineOffset); } else if (baseline.item->parentItem() == item->parentItem()) { if (itemPrivate->isDeclarativeItem) setItemY(position(baseline.item, baseline.anchorLine) - static_cast<QDeclarativeItem *>(item)->baselineOffset() + baselineOffset); } } --updatingVerticalAnchor; } else { // ### Make this certain :) qmlInfo(item) << QDeclarativeAnchors::tr("Possible anchor loop detected on vertical 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 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()); }
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); } }