From 233e83b20512a5e3748542f1c279a5c7ec6310ad Mon Sep 17 00:00:00 2001 From: Fabian Bumberger Date: Mon, 14 Jan 2013 15:00:41 +0100 Subject: [PATCH] Allow aligning items in a grid This change introduces two new properties, horizontalItemAlignment and verticalItemAlignment to a Grid element. This gives the user the possibility to align the items. Change-Id: I7322a689f1bbc1da342bd618f6c30dd8c139ee29 Reviewed-by: Alan Alpert --- .../doc/images/gridLayout_aligncenter.png | Bin 0 -> 476 bytes src/quick/doc/images/gridLayout_aligntop.png | Bin 0 -> 472 bytes .../doc/images/gridLayout_aligntopleft.png | Bin 0 -> 477 bytes src/quick/items/qquickitemsmodule.cpp | 2 + src/quick/items/qquickpositioners.cpp | 111 ++++++++++++++- src/quick/items/qquickpositioners_p.h | 24 ++++ .../quick/qquickpositioners/data/gridtest.qml | 6 +- .../tst_qquickpositioners.cpp | 126 ++++++++++++++++++ 8 files changed, 266 insertions(+), 3 deletions(-) create mode 100644 src/quick/doc/images/gridLayout_aligncenter.png create mode 100644 src/quick/doc/images/gridLayout_aligntop.png create mode 100644 src/quick/doc/images/gridLayout_aligntopleft.png diff --git a/src/quick/doc/images/gridLayout_aligncenter.png b/src/quick/doc/images/gridLayout_aligncenter.png new file mode 100644 index 0000000000000000000000000000000000000000..f31ed25e792c04e6bb368f9221f12ff339891f3b GIT binary patch literal 476 zcmeAS@N?(olHy`uVBq!ia0vp^T|ivN!2~2rp2^t&Db50q$YKTtZeb8+WSBKa0w~B{ z;_2(kewUGtSA}i;3>_f`2F7Yn7srr_TW{~$`WIJFWhAo|1B!-_-r|KbD*B-Y^KtGpYmS+!oe^1 zP*Be15Ku$NWwm!wOJ0J_oX)mbPwf)2YzsTYzMCG;?caYqZn(_7!mP3=y5Q-;f7S0R z=L5MPGE%G08$L38lzYnbu8YixD<5mzY~1(w?OYbElf3SZpJ06Ox|c0S?>(;duYGSX z_cA@^?B$O6;?hOUHh=RIYO61Ao;5kT+3Xv{H8A^N{)0IbfBVlV?zlGrZ0otb z>Eear9}S<*s`2jvU;*KaYaDOh&=nHo^qy#gftH~FxtjEku)vX1)~o+oZEIy>{_L69*J zbq_(NHoJpO1={csBsGT#BD8$svGoBTjvFp>uh1(hmVT*Q>2Ys*%;nHeC0|&d*8Q3r z_4@7--`^kkzqj4J`uSsx>iLteC)r$ImS*HXsrJ*}C$qjq?D-CM_2QX!JLfL!kMGa< zxMulV#SMI|vu@t`HAn8fEzCC{dqK|lz|sE!q$Mi0Ik+HbcUBe1w;*@Dd{%v4ZKtQ* z^q9%s^~*osQPcOEebyK3Rj?N>J1*UozTzcv82K0fWvINbVxS_Mavc~e44$rjF6*2U FngH5{#~c6v literal 0 HcmV?d00001 diff --git a/src/quick/doc/images/gridLayout_aligntopleft.png b/src/quick/doc/images/gridLayout_aligntopleft.png new file mode 100644 index 0000000000000000000000000000000000000000..5a4a2fe211dc97bfd8d544eea323e05e06ce3498 GIT binary patch literal 477 zcmeAS@N?(olHy`uVBq!ia0vp^T|ivN!2~2rp2^t&Db50q$YKTtZeb8+WSBKa0w~B{ z;_2(kewUGt*W7|%tU#NAfw9KZ#WAGf*4w+beuoVh+8&+{bz^JuvSmn5aqH>OE)aHG zcTtv2?T8Dzv4Wb0Q>Jh3r#;E5we0)fESWfIN>uihZ0+3){U06($~`=&Y*W$VUh(0@ z3g7DenoEy={kx;#_vclA-$~`4zn%VN#+?@S{tq1dK!uCtX0^q<&icXu)@XAGsPW34 z%#G1@M{?8MKnj#?4mAT!LXwB;O%?~*1=7;IX|Lo6P8$N&Xx3`SvtM;y0{-o0P-Q?WUtn;O%+UH2UnY4Wx_r06n`)n&froQk< z&s+ZX=V|q9o4;HB@#Qo+9rnpPEn^Fn20IwlJ+Ib1-KX&E{5vCqDxW-%gTe~ HDWM4fDo4(@ literal 0 HcmV?d00001 diff --git a/src/quick/items/qquickitemsmodule.cpp b/src/quick/items/qquickitemsmodule.cpp index 043baebd0a..71c23111d5 100644 --- a/src/quick/items/qquickitemsmodule.cpp +++ b/src/quick/items/qquickitemsmodule.cpp @@ -222,6 +222,8 @@ static void qt_quickitems_defineModule(const char *uri, int major, int minor) #ifndef QT_NO_ACCESSIBILITY qmlRegisterUncreatableType("QtQuick", 2, 0, "Accessible",QQuickAccessibleAttached::tr("Accessible is only available via attached properties")); #endif + + qmlRegisterType(uri, 2, 1, "Grid"); } void QQuickItemsModule::defineModule() diff --git a/src/quick/items/qquickpositioners.cpp b/src/quick/items/qquickpositioners.cpp index 2b03ed2dc4..df80e77bfa 100644 --- a/src/quick/items/qquickpositioners.cpp +++ b/src/quick/items/qquickpositioners.cpp @@ -1102,6 +1102,8 @@ QQuickGrid::QQuickGrid(QQuickItem *parent) , m_useRowSpacing(false) , m_useColumnSpacing(false) , m_flow(LeftToRight) + , m_hItemAlign(AlignLeft) + , m_vItemAlign(AlignTop) { } @@ -1248,6 +1250,7 @@ void QQuickGrid::setLayoutDirection(Qt::LayoutDirection layoutDirection) prePositioning(); emit layoutDirectionChanged(); emit effectiveLayoutDirectionChanged(); + emit effectiveHorizontalAlignmentChanged(effectiveHAlign()); } } @@ -1266,6 +1269,97 @@ Qt::LayoutDirection QQuickGrid::effectiveLayoutDirection() const return QQuickBasePositionerPrivate::getEffectiveLayoutDirection(this); } +/*! + \qmlproperty enumeration QtQuick2::Grid::horizontalItmeAlignment + \qmlproperty enumeration QtQuick2::Grid::verticalItemAlignment + \qmlproperty enumeration QtQuick2::Grid::effectiveHorizontalItemAlignment + + Sets the horizontal and vertical alignment of items in the Grid. By default, + the items are vertically aligned to the top. Horizontal + alignment follows the layoutDirection of the Grid, for example when having a layoutDirection + from LeftToRight, the items will be aligned on the left. + + The valid values for \c horizontalItemAlignment are, \c Grid.AlignLeft, \c Grid.AlignRight and + \c Grid.AlignHCenter. + + The valid values for \c verticalItemAlignment are \c Grid.AlignTop, \c Grid.AlignBottom + and \c Grid.AlignVCenter. + + The below images show three examples of how to align items. + + \table + \row + \li + \li \inlineimage gridLayout_aligntopleft.png + \li \inlineimage gridLayout_aligntop.png + \li \inlineimage gridLayout_aligncenter.png + \row + \li Horizontal alignment + \li AlignLeft + \li AlignHCenter + \li AlignHCenter + \row + \li Vertical alignment + \li AlignTop + \li AlignTop + \li AlignVCenter + \endtable + + + When mirroring the layout using either the attached property LayoutMirroring::enabled or + by setting the layoutDirection, the horizontal alignment of items will be mirrored as well. + However, the property \c horizontalItemAlignment will remain unchanged. + To query the effective horizontal alignment of items, use the read-only property + \c effectiveHorizontalItemAlignment. + + \sa Grid::layoutDirection, {LayoutMirroring}{LayoutMirroring} +*/ +QQuickGrid::HAlignment QQuickGrid::hItemAlign() const +{ + return m_hItemAlign; +} +void QQuickGrid::setHItemAlign(HAlignment align) +{ + if (m_hItemAlign != align) { + m_hItemAlign = align; + prePositioning(); + emit horizontalAlignmentChanged(align); + emit effectiveHorizontalAlignmentChanged(effectiveHAlign()); + } +} + +QQuickGrid::HAlignment QQuickGrid::effectiveHAlign() const +{ + HAlignment effectiveAlignment = m_hItemAlign; + if (effectiveLayoutDirection() == Qt::RightToLeft) { + switch (hItemAlign()) { + case AlignLeft: + effectiveAlignment = AlignRight; + break; + case AlignRight: + effectiveAlignment = AlignLeft; + break; + default: + break; + } + } + return effectiveAlignment; +} + + +QQuickGrid::VAlignment QQuickGrid::vItemAlign() const +{ + return m_vItemAlign; +} +void QQuickGrid::setVItemAlign(VAlignment align) +{ + if (m_vItemAlign != align) { + m_vItemAlign = align; + prePositioning(); + emit verticalAlignmentChanged(align); + } +} + void QQuickGrid::doPositioning(QSizeF *contentSize) { //Precondition: All items in the positioned list have a valid item pointer and should be positioned @@ -1362,9 +1456,22 @@ void QQuickGrid::doPositioning(QSizeF *contentSize) for (int i = 0; i < positionedItems.count(); ++i) { PositionedItem &child = positionedItems[i]; qreal childXOffset = xoffset; + + if (effectiveHAlign() == AlignRight) + childXOffset += maxColWidth[curCol] - child.item->width(); + else if (hItemAlign() == AlignHCenter) + childXOffset += (maxColWidth[curCol] - child.item->width())/2.0; + if (!d->isLeftToRight()) - childXOffset -= child.item->width(); - positionItem(childXOffset, yoffset, &child); + childXOffset -= maxColWidth[curCol]; + + qreal alignYOffset = yoffset; + if (m_vItemAlign == AlignVCenter) + alignYOffset += (maxRowHeight[curRow] - child.item->height())/2.0; + else if (m_vItemAlign == AlignBottom) + alignYOffset += maxRowHeight[curRow] - child.item->height(); + + positionItem(childXOffset, alignYOffset, &child); if (m_flow == LeftToRight) { if (d->isLeftToRight()) diff --git a/src/quick/items/qquickpositioners_p.h b/src/quick/items/qquickpositioners_p.h index aeb722dd60..1ff5a7a74c 100644 --- a/src/quick/items/qquickpositioners_p.h +++ b/src/quick/items/qquickpositioners_p.h @@ -220,6 +220,9 @@ class Q_AUTOTEST_EXPORT QQuickGrid : public QQuickBasePositioner Q_PROPERTY(Flow flow READ flow WRITE setFlow NOTIFY flowChanged) Q_PROPERTY(Qt::LayoutDirection layoutDirection READ layoutDirection WRITE setLayoutDirection NOTIFY layoutDirectionChanged) Q_PROPERTY(Qt::LayoutDirection effectiveLayoutDirection READ effectiveLayoutDirection NOTIFY effectiveLayoutDirectionChanged) + Q_PROPERTY(HAlignment horizontalItemAlignment READ hItemAlign WRITE setHItemAlign NOTIFY horizontalAlignmentChanged REVISION 1) + Q_PROPERTY(HAlignment effectiveHorizontalItemAlignment READ effectiveHAlign NOTIFY effectiveHorizontalAlignmentChanged REVISION 1) + Q_PROPERTY(VAlignment verticalItemAlignment READ vItemAlign WRITE setVItemAlign NOTIFY verticalAlignmentChanged REVISION 1) public: QQuickGrid(QQuickItem *parent=0); @@ -247,6 +250,22 @@ public: void setLayoutDirection (Qt::LayoutDirection); Qt::LayoutDirection effectiveLayoutDirection() const; + Q_ENUMS(HAlignment) + Q_ENUMS(VAlignment) + enum HAlignment { AlignLeft = Qt::AlignLeft, + AlignRight = Qt::AlignRight, + AlignHCenter = Qt::AlignHCenter}; + enum VAlignment { AlignTop = Qt::AlignTop, + AlignBottom = Qt::AlignBottom, + AlignVCenter = Qt::AlignVCenter }; + + HAlignment hItemAlign() const; + void setHItemAlign(HAlignment align); + HAlignment effectiveHAlign() const; + + VAlignment vItemAlign() const; + void setVItemAlign(VAlignment align); + Q_SIGNALS: void rowsChanged(); void columnsChanged(); @@ -255,6 +274,9 @@ Q_SIGNALS: void effectiveLayoutDirectionChanged(); void rowSpacingChanged(); void columnSpacingChanged(); + Q_REVISION(1) void horizontalAlignmentChanged(HAlignment alignment); + Q_REVISION(1) void effectiveHorizontalAlignmentChanged(HAlignment alignment); + Q_REVISION(1) void verticalAlignmentChanged(VAlignment alignment); protected: virtual void doPositioning(QSizeF *contentSize); @@ -268,6 +290,8 @@ private: bool m_useRowSpacing; bool m_useColumnSpacing; Flow m_flow; + HAlignment m_hItemAlign; + VAlignment m_vItemAlign; Q_DISABLE_COPY(QQuickGrid) }; diff --git a/tests/auto/quick/qquickpositioners/data/gridtest.qml b/tests/auto/quick/qquickpositioners/data/gridtest.qml index 50bec1377b..fbe0b22b15 100644 --- a/tests/auto/quick/qquickpositioners/data/gridtest.qml +++ b/tests/auto/quick/qquickpositioners/data/gridtest.qml @@ -1,11 +1,15 @@ -import QtQuick 2.0 +import QtQuick 2.1 Item { width: 640 height: 480 property bool testRightToLeft: false + property int testHAlignment: Grid.AlignLeft; + property int testVAlignment: Grid.AlignTop; Grid { layoutDirection: testRightToLeft ? Qt.RightToLeft : Qt.LeftToRight + horizontalItemAlignment: testHAlignment + verticalItemAlignment: testVAlignment objectName: "grid" columns: 3 Rectangle { diff --git a/tests/auto/quick/qquickpositioners/tst_qquickpositioners.cpp b/tests/auto/quick/qquickpositioners/tst_qquickpositioners.cpp index 98999e540a..9cceaab5dd 100644 --- a/tests/auto/quick/qquickpositioners/tst_qquickpositioners.cpp +++ b/tests/auto/quick/qquickpositioners/tst_qquickpositioners.cpp @@ -78,6 +78,8 @@ private slots: void test_grid_animated(); void test_grid_animated_rightToLeft(); void test_grid_zero_columns(); + void test_grid_H_alignment(); + void test_grid_V_alignment(); void test_propertychanges(); void test_repeater(); void test_flow(); @@ -1418,6 +1420,130 @@ void tst_qquickpositioners::test_grid_zero_columns() delete window; } +void tst_qquickpositioners::test_grid_H_alignment() +{ + QQuickView *window = createView(testFile("gridtest.qml")); + + window->rootObject()->setProperty("testHAlignment", QQuickGrid::AlignHCenter); + + QQuickRectangle *one = window->rootObject()->findChild("one"); + QVERIFY(one != 0); + QQuickRectangle *two = window->rootObject()->findChild("two"); + QVERIFY(two != 0); + QQuickRectangle *three = window->rootObject()->findChild("three"); + QVERIFY(three != 0); + QQuickRectangle *four = window->rootObject()->findChild("four"); + QVERIFY(four != 0); + QQuickRectangle *five = window->rootObject()->findChild("five"); + QVERIFY(five != 0); + + QCOMPARE(one->x(), 0.0); + QCOMPARE(one->y(), 0.0); + QCOMPARE(two->x(), 50.0); + QCOMPARE(two->y(), 0.0); + QCOMPARE(three->x(), 70.0); + QCOMPARE(three->y(), 0.0); + QCOMPARE(four->x(), 0.0); + QCOMPARE(four->y(), 50.0); + QCOMPARE(five->x(), 55.0); + QCOMPARE(five->y(), 50.0); + + QQuickItem *grid = window->rootObject()->findChild("grid"); + QCOMPARE(grid->width(), 100.0); + QCOMPARE(grid->height(), 100.0); + + window->rootObject()->setProperty("testHAlignment", QQuickGrid::AlignRight); + + QCOMPARE(one->x(), 0.0); + QCOMPARE(one->y(), 0.0); + QCOMPARE(two->x(), 50.0); + QCOMPARE(two->y(), 0.0); + QCOMPARE(three->x(), 70.0); + QCOMPARE(three->y(), 0.0); + QCOMPARE(four->x(), 0.0); + QCOMPARE(four->y(), 50.0); + QCOMPARE(five->x(), 60.0); + QCOMPARE(five->y(), 50.0); + QCOMPARE(grid->width(), 100.0); + QCOMPARE(grid->height(), 100.0); + + window->rootObject()->setProperty("testRightToLeft", true); + + QCOMPARE(one->x(), 50.0); + QCOMPARE(one->y(), 0.0); + QCOMPARE(two->x(), 30.0); + QCOMPARE(two->y(), 0.0); + QCOMPARE(three->x(), 0.0); + QCOMPARE(three->y(), 0.0); + QCOMPARE(four->x(), 50.0); + QCOMPARE(four->y(), 50.0); + QCOMPARE(five->x(), 30.0); + QCOMPARE(five->y(), 50.0); + QCOMPARE(grid->width(), 100.0); + QCOMPARE(grid->height(), 100.0); + + window->rootObject()->setProperty("testHAlignment", QQuickGrid::AlignHCenter); + + QCOMPARE(one->x(), 50.0); + QCOMPARE(one->y(), 0.0); + QCOMPARE(two->x(), 30.0); + QCOMPARE(two->y(), 0.0); + QCOMPARE(three->x(), 0.0); + QCOMPARE(three->y(), 0.0); + QCOMPARE(four->x(), 50.0); + QCOMPARE(four->y(), 50.0); + QCOMPARE(five->x(), 35.0); + QCOMPARE(five->y(), 50.0); + QCOMPARE(grid->width(), 100.0); + QCOMPARE(grid->height(), 100.0); + + delete window; +} + +void tst_qquickpositioners::test_grid_V_alignment() +{ + QQuickView *window = createView(testFile("gridtest.qml")); + + window->rootObject()->setProperty("testVAlignment", QQuickGrid::AlignVCenter); + + QQuickRectangle *one = window->rootObject()->findChild("one"); + QVERIFY(one != 0); + QQuickRectangle *two = window->rootObject()->findChild("two"); + QVERIFY(two != 0); + QQuickRectangle *three = window->rootObject()->findChild("three"); + QVERIFY(three != 0); + QQuickRectangle *four = window->rootObject()->findChild("four"); + QVERIFY(four != 0); + QQuickRectangle *five = window->rootObject()->findChild("five"); + QVERIFY(five != 0); + + QCOMPARE(one->x(), 0.0); + QCOMPARE(one->y(), 0.0); + QCOMPARE(two->x(), 50.0); + QCOMPARE(two->y(), 0.0); + QCOMPARE(three->x(), 70.0); + QCOMPARE(three->y(), 15.0); + QCOMPARE(four->x(), 0.0); + QCOMPARE(four->y(), 50.0); + QCOMPARE(five->x(), 50.0); + QCOMPARE(five->y(), 70.0); + + window->rootObject()->setProperty("testVAlignment", QQuickGrid::AlignBottom); + + QCOMPARE(one->x(), 0.0); + QCOMPARE(one->y(), 0.0); + QCOMPARE(two->x(), 50.0); + QCOMPARE(two->y(), 0.0); + QCOMPARE(three->x(), 70.0); + QCOMPARE(three->y(), 30.0); + QCOMPARE(four->x(), 0.0); + QCOMPARE(four->y(), 50.0); + QCOMPARE(five->x(), 50.0); + QCOMPARE(five->y(), 90.0); + + delete window; +} + void tst_qquickpositioners::test_propertychanges() { QQuickView *window = createView(testFile("propertychangestest.qml"));