src/gui/graphicsview/qgraphicsanchorlayout.cpp
changeset 3 41300fa6a67c
parent 0 1918ee327afb
child 4 3b1da2848fc7
--- a/src/gui/graphicsview/qgraphicsanchorlayout.cpp	Tue Jan 26 12:42:25 2010 +0200
+++ b/src/gui/graphicsview/qgraphicsanchorlayout.cpp	Tue Feb 02 00:43:10 2010 +0200
@@ -48,36 +48,73 @@
     \ingroup geomanagement
     \ingroup graphicsview-api
 
-    The anchor layout is a layout where one can specify how widgets should be placed relative to
-    each other. The specification is called an anchor, and it is set up by calling anchor().
+    The anchor layout allows developers to specify how widgets should be placed relative to
+    each other, and to the layout itself. The specification is made by adding anchors to the
+    layout by calling addAnchor(), addAnchors() or addCornerAnchors().
+
+    Existing anchors in the layout can be accessed with the anchor() function.
+    Items that are anchored are automatically added to the layout, and if items
+    are removed, all their anchors will be automatically removed.
+
+    \beginfloatleft
+    \inlineimage simpleanchorlayout-example.png Using an anchor layout to align simple colored widgets.
+    \endfloat
+
     Anchors are always set up between edges of an item, where the "center" is also considered to
-    be an edge. Considering this example:
-    \code
-        QGraphicsAnchorLayout *l = new QGraphicsAnchorLayout;
-        QGraphicsWidget *a = new QGraphicsWidget;
-        QGraphicsWidget *b = new QGraphicsWidget;
-        l->anchor(a, Qt::AnchorRight, b, Qt::AnchorLeft);
-    \endcode
+    be an edge. Consider the following example:
+
+    \snippet examples/graphicsview/simpleanchorlayout/main.cpp adding anchors
+
+    Here, the right edge of item \c a is anchored to the left edge of item \c b and the bottom
+    edge of item \c a is anchored to the top edge of item \c b, with the result that
+    item \c b will be placed diagonally to the right and below item \c b.
+
+    The addCornerAnchors() function provides a simpler way of anchoring the corners
+    of two widgets than the two individual calls to addAnchor() shown in the code
+    above. Here, we see how a widget can be anchored to the top-left corner of the enclosing
+    layout:
+
+    \snippet examples/graphicsview/simpleanchorlayout/main.cpp adding a corner anchor
+
+    In cases where anchors are used to match the widths or heights of widgets, it is
+    convenient to use the addAnchors() function. As with the other functions for specifying
+    anchors, it can also be used to anchor a widget to a layout.
 
-    Here is the right edge of item A anchored to the left edge of item B, with the result that
-    item B will be placed to the right of item A, with a spacing between A and B. If the
-    spacing is negative, the items will overlap to some extent. Items that are anchored are
-    automatically added to the layout, and if items are removed, all their anchors will be
-    automatically removed
+    \clearfloat
+    \section1 Size Hints and Size Policies in an Anchor Layout
+
+    QGraphicsAnchorLayout respects each item's size hints and size policies.
+    Note that there are some properties of QSizePolicy that are \l{Known issues}{not respected}.
+
+    \section1 Spacing within an Anchor Layout
 
-    \section1 Size Hints and Size Policies in QGraphicsAnchorLayout
+    The layout may distribute some space between the items. If the spacing has not been
+    explicitly specified, the actual amount of space will usually be 0.
+
+    However, if the first edge is the \e opposite of the second edge (e.g., the right edge
+    of the first widget is anchored to the left edge of the second widget), the size of the
+    anchor will be queried from the style through a pixel metric:
+    \l{QStyle::}{PM_LayoutHorizontalSpacing} for horizontal anchors and
+    \l{QStyle::}{PM_LayoutVerticalSpacing} for vertical anchors.
 
-    QGraphicsAnchorLayout respects each item's size hints and size policies. However it does
-    not respect stretch factors currently. This might change in the future, so please refrain
-    from using stretch factors in anchor layout to avoid any future regressions.
+    If the spacing is negative, the items will overlap to some extent.
+
 
-    \section1 Spacing within QGraphicsAnchorLayout
+    \section1 Known issues
+    There are some features that QGraphicsAnchorLayout currently does not support.
+    This might change in the future, so avoid using these features if you want to
+    avoid any future regressions in behaviour:
+    \list
 
-    Between the items, the layout can distribute some space. If the spacing has not been
-    explicitly specified, the actual amount of space will usually be 0, but if the first edge
-    is the "opposite" of the second edge (i.e. Right is anchored to Left or vice-versa), the
-    size of the anchor will be queried from the style through the pixelMetric
-    PM_LayoutHorizontalSpacing (or PM_LayoutVerticalSpacing for vertical anchors).
+    \o Stretch factors are not respected.
+
+    \o QSizePolicy::ExpandFlag is not respected.
+
+    \o Height for width is not respected.
+
+    \endlist
+
+    \sa QGraphicsLinearLayout, QGraphicsGridLayout, QGraphicsLayout
 */
 
 /*!
@@ -99,7 +136,7 @@
 
 */
 #include "qgraphicsanchorlayout_p.h"
-
+#ifndef QT_NO_GRAPHICSVIEW
 QT_BEGIN_NAMESPACE
 
 QGraphicsAnchor::QGraphicsAnchor(QGraphicsAnchorLayout *parentLayout)
@@ -121,7 +158,7 @@
     \property QGraphicsAnchor::sizePolicy
     \brief the size policy for the QGraphicsAnchor.
 
-    By setting the size policy on an anchor you can configure how the item can resize itself
+    By setting the size policy on an anchor you can configure how the anchor can resize itself
     from its preferred spacing. For instance, if the anchor has the size policy
     QSizePolicy::Minimum, the spacing is the minimum size of the anchor. However, its size
     can grow up to the anchors maximum size. If the default size policy is QSizePolicy::Fixed,
@@ -210,12 +247,12 @@
 
 /*!
     Creates an anchor between the edge \a firstEdge of item \a firstItem and the edge \a secondEdge
-    of item \a secondItem. The magnitude of the anchor is picked up from the style. Anchors
+    of item \a secondItem. The spacing of the anchor is picked up from the style. Anchors
     between a layout edge and an item edge will have a size of 0.
     If there is already an anchor between the edges, the the new anchor will replace the old one.
 
     \a firstItem and \a secondItem are automatically added to the layout if they are not part
-    of the layout. This means that count() can increase with up to 2.
+    of the layout. This means that count() can increase by up to 2.
 
     The spacing an anchor will get depends on the type of anchor. For instance, anchors from the
     Right edge of one item to the Left edge of another (or vice versa) will use the default
@@ -228,7 +265,7 @@
     Calling this function where \a firstItem or \a secondItem are ancestors of the layout have
     undefined behaviour.
 
-    \sa addCornerAnchors(), addAnchors()
+    \sa addAnchors(), addCornerAnchors()
  */
 QGraphicsAnchor *
 QGraphicsAnchorLayout::addAnchor(QGraphicsLayoutItem *firstItem, Qt::AnchorPoint firstEdge,
@@ -253,29 +290,26 @@
 }
 
 /*!
-    Creates two anchors between \a firstItem and \a secondItem, where one is for the horizontal
-    edge and another one for the vertical edge that the corners \a firstCorner and \a
-    secondCorner specifies.
-    The magnitude of the anchors is picked up from the style.
+    Creates two anchors between \a firstItem and \a secondItem specified by the corners,
+    \a firstCorner and \a secondCorner, where one is for the horizontal edge and another
+    one for the vertical edge.
 
-    This is a convenience function, since anchoring corners can be expressed as anchoring two edges.
-    For instance,
-    \code
-      layout->addAnchor(layout, Qt::AnchorTop, b, Qt::AnchorTop);
-      layout->addAnchor(layout, Qt::AnchorLeft, b, Qt::AnchorLeft);
-    \endcode
+    This is a convenience function, since anchoring corners can be expressed as anchoring
+    two edges. For instance:
 
-    has the same effect as
+    \snippet examples/graphicsview/simpleanchorlayout/main.cpp adding a corner anchor in two steps
 
-    \code
-      layout->addCornerAnchors(layout, Qt::TopLeft, b, Qt::TopLeft);
-    \endcode
+    This can also be achieved with the following line of code:
+
+    \snippet examples/graphicsview/simpleanchorlayout/main.cpp adding a corner anchor
 
     If there is already an anchor between the edge pairs, it will be replaced by the anchors that
     this function specifies.
 
     \a firstItem and \a secondItem are automatically added to the layout if they are not part of the
-    layout. This means that count() can increase with up to 2.
+    layout. This means that count() can increase by up to 2.
+
+    \sa addAnchor(), addAnchors()
 */
 void QGraphicsAnchorLayout::addCornerAnchors(QGraphicsLayoutItem *firstItem,
                                              Qt::Corner firstCorner,
@@ -287,14 +321,14 @@
     // Horizontal anchor
     Qt::AnchorPoint firstEdge = (firstCorner & 1 ? Qt::AnchorRight: Qt::AnchorLeft);
     Qt::AnchorPoint secondEdge = (secondCorner & 1 ? Qt::AnchorRight: Qt::AnchorLeft);
-    d->addAnchor(firstItem, firstEdge, secondItem, secondEdge);
+    if (d->addAnchor(firstItem, firstEdge, secondItem, secondEdge)) {
+        // Vertical anchor
+        firstEdge = (firstCorner & 2 ? Qt::AnchorBottom: Qt::AnchorTop);
+        secondEdge = (secondCorner & 2 ? Qt::AnchorBottom: Qt::AnchorTop);
+        d->addAnchor(firstItem, firstEdge, secondItem, secondEdge);
 
-    // Vertical anchor
-    firstEdge = (firstCorner & 2 ? Qt::AnchorBottom: Qt::AnchorTop);
-    secondEdge = (secondCorner & 2 ? Qt::AnchorBottom: Qt::AnchorTop);
-    d->addAnchor(firstItem, firstEdge, secondItem, secondEdge);
-
-    invalidate();
+        invalidate();
+    }
 }
 
 /*!
@@ -302,27 +336,29 @@
     edges of \a secondItem, so that \a firstItem has the same size as
     \a secondItem in the dimensions specified by \a orientations.
 
-    Calling this convenience function with the following arguments
-    \code
-    l->addAnchors(firstItem, secondItem, Qt::Horizontal)
-    \endcode
+    For example, the following example anchors the left and right edges of two items
+    to match their widths:
+
+    \snippet examples/graphicsview/simpleanchorlayout/main.cpp adding anchors to match sizes in two steps
 
-    is the same as
+    This can also be achieved using the following line of code:
 
-    \code
-    l->addAnchor(firstItem, Qt::AnchorLeft, secondItem, Qt::AnchorLeft);
-    l->addAnchor(firstItem, Qt::AnchorRight, secondItem, Qt::AnchorRight);
-    \endcode
+    \snippet examples/graphicsview/simpleanchorlayout/main.cpp adding anchors to match sizes
+
+    \sa addAnchor(), addCornerAnchors()
 */
 void QGraphicsAnchorLayout::addAnchors(QGraphicsLayoutItem *firstItem,
                                        QGraphicsLayoutItem *secondItem,
                                        Qt::Orientations orientations)
 {
+    bool ok = true;
     if (orientations & Qt::Horizontal) {
-        addAnchor(secondItem, Qt::AnchorLeft, firstItem, Qt::AnchorLeft);
-        addAnchor(firstItem, Qt::AnchorRight, secondItem, Qt::AnchorRight);
+        // Currently, if the first is ok, then the rest of the calls should be ok
+        ok = addAnchor(secondItem, Qt::AnchorLeft, firstItem, Qt::AnchorLeft) != 0;
+        if (ok)
+            addAnchor(firstItem, Qt::AnchorRight, secondItem, Qt::AnchorRight);
     }
-    if (orientations & Qt::Vertical) {
+    if (orientations & Qt::Vertical && ok) {
         addAnchor(secondItem, Qt::AnchorTop, firstItem, Qt::AnchorTop);
         addAnchor(firstItem, Qt::AnchorBottom, secondItem, Qt::AnchorBottom);
     }
@@ -337,12 +373,6 @@
 {
     Q_D(QGraphicsAnchorLayout);
 
-    // ### We don't support negative spacing yet
-    if (spacing < 0) {
-        spacing = 0;
-        qWarning() << "QGraphicsAnchorLayout does not support negative spacing.";
-    }
-
     d->spacings[0] = spacing;
     invalidate();
 }
@@ -356,12 +386,6 @@
 {
     Q_D(QGraphicsAnchorLayout);
 
-    // ### We don't support negative spacing yet
-    if (spacing < 0) {
-        spacing = 0;
-        qWarning() << "QGraphicsAnchorLayout does not support negative spacing.";
-    }
-
     d->spacings[1] = spacing;
     invalidate();
 }
@@ -372,7 +396,8 @@
     If an item is anchored with no spacing associated with the anchor, it will use the default
     spacing.
 
-    Currently QGraphicsAnchorLayout does not support negative default spacings.
+    QGraphicsAnchorLayout does not support negative spacings. Setting a negative value will unset the
+    previous spacing and make the layout use the spacing provided by the current widget style.
 
     \sa setHorizontalSpacing(), setVerticalSpacing()
 */
@@ -380,14 +405,6 @@
 {
     Q_D(QGraphicsAnchorLayout);
 
-    // ### Currently we do not support negative anchors inside the graph.
-    // To avoid those being created by a negative spacing, we must
-    // make this test.
-    if (spacing < 0) {
-        spacing = 0;
-        qWarning() << "QGraphicsAnchorLayout does not support negative spacing.";
-    }
-
     d->spacings[0] = d->spacings[1] = spacing;
     invalidate();
 }
@@ -400,7 +417,7 @@
 qreal QGraphicsAnchorLayout::horizontalSpacing() const
 {
     Q_D(const QGraphicsAnchorLayout);
-    return d->effectiveSpacing(QGraphicsAnchorLayoutPrivate::Horizontal);
+    return d->styleInfo().defaultSpacing(Qt::Horizontal);
 }
 
 /*!
@@ -411,7 +428,7 @@
 qreal QGraphicsAnchorLayout::verticalSpacing() const
 {
     Q_D(const QGraphicsAnchorLayout);
-    return d->effectiveSpacing(QGraphicsAnchorLayoutPrivate::Vertical);
+    return d->styleInfo().defaultSpacing(Qt::Vertical);
 }
 
 /*!
@@ -444,9 +461,6 @@
         return;
 
     // Removing an item affects both horizontal and vertical graphs
-    d->restoreSimplifiedGraph(QGraphicsAnchorLayoutPrivate::Horizontal);
-    d->restoreSimplifiedGraph(QGraphicsAnchorLayoutPrivate::Vertical);
-
     d->removeCenterConstraints(item, QGraphicsAnchorLayoutPrivate::Horizontal);
     d->removeCenterConstraints(item, QGraphicsAnchorLayoutPrivate::Vertical);
     d->removeAnchors(item);
@@ -481,7 +495,8 @@
 {
     Q_D(QGraphicsAnchorLayout);
     QGraphicsLayout::invalidate();
-    d->calculateGraphCacheDirty = 1;
+    d->calculateGraphCacheDirty = true;
+    d->styleInfoDirty = true;
 }
 
 /*!
@@ -515,3 +530,4 @@
 }
 
 QT_END_NAMESPACE
+#endif //QT_NO_GRAPHICSVIEW