summaryrefslogtreecommitdiffstats
path: root/src/gui/graphicsview/qgraphicsanchorlayout_p.cpp
diff options
context:
space:
mode:
authorEduardo M. Fleury <eduardo.fleury@openbossa.org>2009-09-25 22:02:21 (GMT)
committerJan-Arve Sæther <jan-arve.saether@nokia.com>2009-10-06 09:28:45 (GMT)
commitad69bb73754534f61658a83e85dadb75e603c90a (patch)
tree17dde728fa948725eea8139068ba4eed6fcbd86a /src/gui/graphicsview/qgraphicsanchorlayout_p.cpp
parentbcd08ab82b5df13f7687a504f868cb8b6ff8b75e (diff)
downloadQt-ad69bb73754534f61658a83e85dadb75e603c90a.zip
Qt-ad69bb73754534f61658a83e85dadb75e603c90a.tar.gz
Qt-ad69bb73754534f61658a83e85dadb75e603c90a.tar.bz2
QGraphicsAnchorLayout: Update solveExpanding to handle simplified graphs
The previous implementation of solveExpanding would assume that anchors were either completely expanding (would grow to their sizeAtMaximum) or non-expanding (would try to remain at their sizeAtPreferred). What happens however is that with simplification enabled, we may have anchors that are "partially" expanding. An example is a sequential anchor that groups together two leaf anchors where only one of them is expanding. In this case, the expected size of that group anchor would be the sum of the max size of the expanding child plus the preferred size of the non-expanding child. To handle the above case we added the "expSize" variable. It holds the expected value at Expanding for each anchor. Based on this, and the already calculated values of sizeAtMaximum and sizeAtPreferred, the solver calculates the actual sizeAtExpanding for them. Signed-off-by: Eduardo M. Fleury <eduardo.fleury@openbossa.org> Reviewed-by: Caio Marcelo de Oliveira Filho <caio.oliveira@openbossa.org>
Diffstat (limited to 'src/gui/graphicsview/qgraphicsanchorlayout_p.cpp')
-rw-r--r--src/gui/graphicsview/qgraphicsanchorlayout_p.cpp84
1 files changed, 72 insertions, 12 deletions
diff --git a/src/gui/graphicsview/qgraphicsanchorlayout_p.cpp b/src/gui/graphicsview/qgraphicsanchorlayout_p.cpp
index dd46722..cf1429c 100644
--- a/src/gui/graphicsview/qgraphicsanchorlayout_p.cpp
+++ b/src/gui/graphicsview/qgraphicsanchorlayout_p.cpp
@@ -2319,40 +2319,97 @@ bool QGraphicsAnchorLayoutPrivate::solvePreferred(QList<QSimplexConstraint *> co
return feasible;
}
+/*! Calculate the "expanding" keyframe
+
+ This new keyframe sits between the already existing sizeAtPreferred and
+ sizeAtMaximum keyframes. Its goal is to modify the interpolation between
+ the latter as to respect the "expanding" size policy of some anchors.
+
+ Previously all items would be subject to a linear interpolation between
+ sizeAtPreferred and sizeAtMaximum values. This will change now, the
+ expanding anchors will change their size before the others. To calculate
+ this keyframe we use the following logic:
+
+ 1) Ask each anchor for their desired expanding size (ad->expSize), this
+ value depends on the anchor expanding property in the following way:
+
+ - Expanding anchors want to grow towards their maximum size
+ - Non-expanding anchors want to remain at their preferred size.
+ - Composite anchors want to grow towards somewhere between their
+ preferred sizes. (*)
+
+ 2) Clamp their desired values to the value they assume in the neighbour
+ keyframes (sizeAtPreferred and sizeAtExpanding)
+
+ 3) Run simplex with a setup that ensures the following:
+
+ a. Anchors will change their value from their sizeAtPreferred towards
+ their sizeAtMaximum as much as required to ensure that ALL anchors
+ reach their respective "desired" expanding sizes.
+
+ b. No anchors will change their value beyond what is NEEDED to satisfy
+ the requirement above.
+
+ The final result is that, at the "expanding" keyframe expanding anchors
+ will grow and take with them all anchors that are parallel to them.
+ However, non-expanding anchors will remain at their preferred size unless
+ they are forced to grow by a parallel expanding anchor.
+
+ Note: For anchors where the sizeAtPreferred is bigger than sizeAtPreferred,
+ the visual effect when the layout grows from its preferred size is
+ the following: Expanding anchors will keep their size while non
+ expanding ones will shrink. Only after non-expanding anchors have
+ shrinked all the way, the expanding anchors will start to shrink too.
+*/
void QGraphicsAnchorLayoutPrivate::solveExpanding(QList<QSimplexConstraint *> constraints)
{
QList<AnchorData *> variables = getVariables(constraints);
QList<QSimplexConstraint *> itemConstraints;
QSimplexConstraint *objective = new QSimplexConstraint;
+ bool hasExpanding = false;
- // Use all items that belong to trunk to:
- // - add solveExpanding-specific item constraints
- // - create the objective function
+ // Construct the simplex constraints and objective
for (int i = 0; i < variables.size(); ++i) {
+ // For each anchor
AnchorData *ad = variables[i];
- if (ad->isExpanding) {
- // Add constraint to lock expanding anchor in its sizeAtMaximum
+
+ // Clamp the desired expanding size
+ qreal upperBoundary = qMax(ad->sizeAtPreferred, ad->sizeAtMaximum);
+ qreal lowerBoundary = qMin(ad->sizeAtPreferred, ad->sizeAtMaximum);
+ qreal boundedExpSize = qBound(lowerBoundary, ad->expSize, upperBoundary);
+
+ // Expanding anchors are those that want to move from their preferred size
+ if (boundedExpSize != ad->sizeAtPreferred)
+ hasExpanding = true;
+
+ // Lock anchor between boundedExpSize and sizeAtMaximum (ensure 3.a)
+ if (boundedExpSize == ad->sizeAtMaximum) {
+ // The interval has only one possible value, we can use an "Equal"
+ // constraint and don't need to add this variable to the objective.
QSimplexConstraint *itemC = new QSimplexConstraint;
itemC->ratio = QSimplexConstraint::Equal;
itemC->variables.insert(ad, 1.0);
- itemC->constant = ad->sizeAtMaximum;
+ itemC->constant = boundedExpSize;
itemConstraints << itemC;
} else {
- // Add constraints to lock anchor between their sizeAtPreferred and sizeAtMaximum
+ // Add MoreOrEqual and LessOrEqual constraints.
QSimplexConstraint *itemC = new QSimplexConstraint;
itemC->ratio = QSimplexConstraint::MoreOrEqual;
itemC->variables.insert(ad, 1.0);
- itemC->constant = qMin(ad->sizeAtPreferred, ad->sizeAtMaximum);
+ itemC->constant = qMin(boundedExpSize, ad->sizeAtMaximum);
itemConstraints << itemC;
itemC = new QSimplexConstraint;
itemC->ratio = QSimplexConstraint::LessOrEqual;
itemC->variables.insert(ad, 1.0);
- itemC->constant = qMax(ad->sizeAtPreferred, ad->sizeAtMaximum);
+ itemC->constant = qMax(boundedExpSize, ad->sizeAtMaximum);
itemConstraints << itemC;
- // Add anchor to objective function
- if (ad->sizeAtPreferred < ad->sizeAtMaximum) {
+ // Create objective to avoid the anchos from moving away from
+ // the preferred size more than the needed amount. (ensure 3.b)
+ // The objective function is the distance between sizeAtPreferred
+ // and sizeAtExpanding, it will be minimized.
+ if (ad->sizeAtExpanding < ad->sizeAtMaximum) {
// Try to shrink this variable towards its sizeAtPreferred value
objective->variables.insert(ad, 1.0);
} else {
@@ -2363,7 +2420,7 @@ void QGraphicsAnchorLayoutPrivate::solveExpanding(QList<QSimplexConstraint *> co
}
// Solve
- if (objective->variables.size() == variables.size()) {
+ if (hasExpanding == false) {
// 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) {
@@ -2372,9 +2429,12 @@ void QGraphicsAnchorLayoutPrivate::solveExpanding(QList<QSimplexConstraint *> co
} else {
// Run simplex
QSimplex simplex;
+
+ // Satisfy expanding (3.a)
bool feasible = simplex.setConstraints(constraints + itemConstraints);
Q_ASSERT(feasible);
+ // Reduce damage (3.b)
simplex.setObjective(objective);
simplex.solveMin();