Allow aligning items in a grid
authorFabian Bumberger <fbumberger@rim.com>
Mon, 14 Jan 2013 14:00:41 +0000 (15:00 +0100)
committerThe Qt Project <gerrit-noreply@qt-project.org>
Mon, 28 Jan 2013 19:42:48 +0000 (20:42 +0100)
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 <aalpert@rim.com>
src/quick/doc/images/gridLayout_aligncenter.png [new file with mode: 0644]
src/quick/doc/images/gridLayout_aligntop.png [new file with mode: 0644]
src/quick/doc/images/gridLayout_aligntopleft.png [new file with mode: 0644]
src/quick/items/qquickitemsmodule.cpp
src/quick/items/qquickpositioners.cpp
src/quick/items/qquickpositioners_p.h
tests/auto/quick/qquickpositioners/data/gridtest.qml
tests/auto/quick/qquickpositioners/tst_qquickpositioners.cpp

diff --git a/src/quick/doc/images/gridLayout_aligncenter.png b/src/quick/doc/images/gridLayout_aligncenter.png
new file mode 100644 (file)
index 0000000..f31ed25
Binary files /dev/null and b/src/quick/doc/images/gridLayout_aligncenter.png differ
diff --git a/src/quick/doc/images/gridLayout_aligntop.png b/src/quick/doc/images/gridLayout_aligntop.png
new file mode 100644 (file)
index 0000000..5b752b1
Binary files /dev/null and b/src/quick/doc/images/gridLayout_aligntop.png differ
diff --git a/src/quick/doc/images/gridLayout_aligntopleft.png b/src/quick/doc/images/gridLayout_aligntopleft.png
new file mode 100644 (file)
index 0000000..5a4a2fe
Binary files /dev/null and b/src/quick/doc/images/gridLayout_aligntopleft.png differ
index 043baeb..71c2311 100644 (file)
@@ -222,6 +222,8 @@ static void qt_quickitems_defineModule(const char *uri, int major, int minor)
 #ifndef QT_NO_ACCESSIBILITY
     qmlRegisterUncreatableType<QQuickAccessibleAttached>("QtQuick", 2, 0, "Accessible",QQuickAccessibleAttached::tr("Accessible is only available via attached properties"));
 #endif
+
+    qmlRegisterType<QQuickGrid, 1>(uri, 2, 1, "Grid");
 }
 
 void QQuickItemsModule::defineModule()
index 2b03ed2..df80e77 100644 (file)
@@ -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())
index aeb722d..1ff5a7a 100644 (file)
@@ -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)
 };
 
index 50bec13..fbe0b22 100644 (file)
@@ -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 {
index 98999e5..9cceaab 100644 (file)
@@ -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<QQuickRectangle*>("one");
+    QVERIFY(one != 0);
+    QQuickRectangle *two = window->rootObject()->findChild<QQuickRectangle*>("two");
+    QVERIFY(two != 0);
+    QQuickRectangle *three = window->rootObject()->findChild<QQuickRectangle*>("three");
+    QVERIFY(three != 0);
+    QQuickRectangle *four = window->rootObject()->findChild<QQuickRectangle*>("four");
+    QVERIFY(four != 0);
+    QQuickRectangle *five = window->rootObject()->findChild<QQuickRectangle*>("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<QQuickItem*>("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<QQuickRectangle*>("one");
+    QVERIFY(one != 0);
+    QQuickRectangle *two = window->rootObject()->findChild<QQuickRectangle*>("two");
+    QVERIFY(two != 0);
+    QQuickRectangle *three = window->rootObject()->findChild<QQuickRectangle*>("three");
+    QVERIFY(three != 0);
+    QQuickRectangle *four = window->rootObject()->findChild<QQuickRectangle*>("four");
+    QVERIFY(four != 0);
+    QQuickRectangle *five = window->rootObject()->findChild<QQuickRectangle*>("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"));