summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorEduardo M. Fleury <eduardo.fleury@openbossa.org>2009-09-23 19:02:35 (GMT)
committerJan-Arve Sæther <jan-arve.saether@nokia.com>2009-10-06 09:28:26 (GMT)
commit1728f846d9fb53a699782005d6478c0f23f9b82e (patch)
tree5916d02718f0a25f50e54167a05e05d3d2655349 /src
parentbfc1a75616e1c96a018349084fae844d7efbc177 (diff)
downloadQt-1728f846d9fb53a699782005d6478c0f23f9b82e.zip
Qt-1728f846d9fb53a699782005d6478c0f23f9b82e.tar.gz
Qt-1728f846d9fb53a699782005d6478c0f23f9b82e.tar.bz2
QGraphicsAnchorLayout: Enabling Simplex support for Expanding size policy
To support the expanding size policy we had to change the way the setup process work. Previously we used to calculate three key-frames using the simplex solver: - sizeAtMinimum: the value an anchor should be in when the layout is at its minimum size. Calculated using simplex solver to minimize the layout size. - sizeAtPreferred: the value an anchor should be in when the layout is at its preferred size. Calculated using simplex solver to minimize the deviation from the items preferred sizes. - sizeAtMaximum: the value an anchor should be in when the layout is at its maximum size. Calculated using simplex solver to maximize the layout size. That worked fine but didn't diferentiate standard items from the "expanding" ones. In other words, all items would grow from their sizeAtPreferred to their sizeAtMaximum at the same rate. To support the idea of "expanding" items, ie. items that should grow faster than the others, we added a fourth state, between preferred and maximum. Now we have the following interpolation order: sizeAtMinimum -> sizeAtPreferred -> sizeAtExpanding -> sizeAtMaximum. The definition of the "expanding" state is that all "expanding" items should have grown all the way to their "sizeAtMaximum" values whereas non expanding items should have kept their preferred sizes. The only exception is that non-expanding items are allowed to grow if that is necessary to allow the "expanding" items to reach their sizeAtMaximum. So, the visual result is that if the layout is resized from its preferred size to its maximum size, the expanding items will grow first and then, in a second phase, the other items will grow. This commit adds QGALPrivate::solveExpanding() and calls it from calculateGraphs(). Signed-off-by: Eduardo M. Fleury <eduardo.fleury@openbossa.org> Reviewed-by: Artur Duque de Souza <artur.souza@openbossa.org>
Diffstat (limited to 'src')
-rw-r--r--src/gui/graphicsview/qgraphicsanchorlayout_p.cpp98
-rw-r--r--src/gui/graphicsview/qgraphicsanchorlayout_p.h1
2 files changed, 88 insertions, 11 deletions
diff --git a/src/gui/graphicsview/qgraphicsanchorlayout_p.cpp b/src/gui/graphicsview/qgraphicsanchorlayout_p.cpp
index fc3bc8a..93ccf83 100644
--- a/src/gui/graphicsview/qgraphicsanchorlayout_p.cpp
+++ b/src/gui/graphicsview/qgraphicsanchorlayout_p.cpp
@@ -1635,11 +1635,18 @@ void QGraphicsAnchorLayoutPrivate::calculateGraphs(
qreal min, max;
feasible = solveMinMax(trunkConstraints, trunkPath, &min, &max);
- // Solve for preferred. The objective function is calculated from the constraints
- // and variables internally.
- feasible &= solvePreferred(trunkConstraints);
-
if (feasible) {
+ // Solve for preferred. The objective function is calculated from the constraints
+ // and variables internally.
+ solvePreferred(trunkConstraints);
+
+ // remove sizeHintConstraints from trunkConstraints
+ trunkConstraints = parts[0];
+
+ // Solve for expanding. The objective function and the constraints from items
+ // are calculated internally.
+ solveExpanding(trunkConstraints);
+
// Propagate the new sizes down the simplified graph, ie. tell the
// group anchors to set their children anchors sizes.
@@ -1649,23 +1656,23 @@ void QGraphicsAnchorLayoutPrivate::calculateGraphs(
for (int i = 0; i < trunkVariables.count(); ++i)
trunkVariables.at(i)->updateChildrenSizes();
- // Calculate and set the preferred size for the layout from the edge sizes that
- // were calculated above.
+ // Calculate and set the preferred and expanding sizes for the layout,
+ // from the edge sizes that were calculated above.
qreal pref(0.0);
+ qreal expanding(0.0);
foreach (const AnchorData *ad, trunkPath.positives) {
pref += ad->sizeAtPreferred;
+ expanding += ad->sizeAtExpanding;
}
foreach (const AnchorData *ad, trunkPath.negatives) {
pref -= ad->sizeAtPreferred;
+ expanding -= ad->sizeAtExpanding;
}
+
sizeHints[orientation][Qt::MinimumSize] = min;
sizeHints[orientation][Qt::PreferredSize] = pref;
sizeHints[orientation][Qt::MaximumSize] = max;
-
- // XXX implement Expanding simplex
- for (int i = 0; i < trunkVariables.count(); ++i)
- trunkVariables.at(i)->sizeAtExpanding = trunkVariables.at(i)->sizeAtPreferred;
- sizeAtExpanding[orientation] = pref;
+ sizeAtExpanding[orientation] = expanding;
}
} else {
#if 0
@@ -2315,6 +2322,75 @@ bool QGraphicsAnchorLayoutPrivate::solvePreferred(QList<QSimplexConstraint *> co
return feasible;
}
+void QGraphicsAnchorLayoutPrivate::solveExpanding(QList<QSimplexConstraint *> constraints)
+{
+ QList<AnchorData *> variables = getVariables(constraints);
+ QList<QSimplexConstraint *> itemConstraints;
+ QSimplexConstraint *objective = new QSimplexConstraint;
+
+ // Use all items that belong to trunk to:
+ // - add solveExpanding-specific item constraints
+ // - create the objective function
+ for (int i = 0; i < variables.size(); ++i) {
+ AnchorData *ad = variables[i];
+ if (ad->isExpanding) {
+ // Add constraint to lock expanding anchor in its sizeAtMaximum
+ QSimplexConstraint *itemC = new QSimplexConstraint;
+ itemC->ratio = QSimplexConstraint::Equal;
+ itemC->variables.insert(ad, 1.0);
+ itemC->constant = ad->sizeAtMaximum;
+ itemConstraints << itemC;
+ } else {
+ // Add constraints to lock anchor between their sizeAtPreferred and sizeAtMaximum
+ QSimplexConstraint *itemC = new QSimplexConstraint;
+ itemC->ratio = QSimplexConstraint::MoreOrEqual;
+ itemC->variables.insert(ad, 1.0);
+ itemC->constant = qMin(ad->sizeAtPreferred, ad->sizeAtMaximum);
+ itemConstraints << itemC;
+
+ itemC = new QSimplexConstraint;
+ itemC->ratio = QSimplexConstraint::LessOrEqual;
+ itemC->variables.insert(ad, 1.0);
+ itemC->constant = qMax(ad->sizeAtPreferred, ad->sizeAtMaximum);
+ itemConstraints << itemC;
+
+ // Add anchor to objective function
+ if (ad->sizeAtPreferred < ad->sizeAtMaximum) {
+ // Try to shrink this variable towards its sizeAtPreferred value
+ objective->variables.insert(ad, 1.0);
+ } else {
+ // Try to grow this variable towards its sizeAtPreferred value
+ objective->variables.insert(ad, -1.0);
+ }
+ }
+ }
+
+ // Solve
+ if (objective->variables.size() == variables.size()) {
+ // If no anchors are expanding, we don't need to run the simplex
+ // Set all variables to their preferred size
+ for (int i = 0; i < variables.size(); ++i) {
+ variables[i]->sizeAtExpanding = variables[i]->sizeAtPreferred;
+ }
+ } else {
+ // Run simplex
+ QSimplex simplex;
+ bool feasible = simplex.setConstraints(constraints + itemConstraints);
+ Q_ASSERT(feasible);
+
+ simplex.setObjective(objective);
+ simplex.solveMin();
+
+ // Collect results
+ for (int i = 0; i < variables.size(); ++i) {
+ variables[i]->sizeAtExpanding = variables[i]->result;
+ }
+ }
+
+ delete objective;
+ qDeleteAll(itemConstraints);
+}
+
/*!
\internal
Returns true if there are no arrangement that satisfies all constraints.
diff --git a/src/gui/graphicsview/qgraphicsanchorlayout_p.h b/src/gui/graphicsview/qgraphicsanchorlayout_p.h
index 4c6c2aa..47df786 100644
--- a/src/gui/graphicsview/qgraphicsanchorlayout_p.h
+++ b/src/gui/graphicsview/qgraphicsanchorlayout_p.h
@@ -495,6 +495,7 @@ public:
bool solveMinMax(QList<QSimplexConstraint *> constraints,
GraphPath path, qreal *min, qreal *max);
bool solvePreferred(QList<QSimplexConstraint *> constraints);
+ void solveExpanding(QList<QSimplexConstraint *> constraints);
bool hasConflicts() const;
#ifdef QT_DEBUG