constraints simplified

This commit is contained in:
Uwe Rathmann 2020-04-13 11:23:36 +02:00
parent a7e30c2550
commit 22fc80bb39
1 changed files with 75 additions and 32 deletions

View File

@ -46,7 +46,7 @@ namespace
return centerH(); return centerH();
case Qt::AnchorRight: case Qt::AnchorRight:
return Term( m_right ); return right();
case Qt::AnchorTop: case Qt::AnchorTop:
return Term( m_top ); return Term( m_top );
@ -55,42 +55,40 @@ namespace
return centerV(); return centerV();
case Qt::AnchorBottom: case Qt::AnchorBottom:
return Term( m_bottom ); return bottom();
} }
return Expression(); return Expression();
} }
inline Expression length( Qt::Orientation orientation ) inline const Variable& length( Qt::Orientation orientation )
{ {
return ( orientation == Qt::Horizontal ) ? width() : height(); return ( orientation == Qt::Horizontal ) ? m_width : m_height;
} }
inline QRectF rect() const inline QRectF rect() const
{ {
return QRectF( m_left.value(), m_top.value(), return QRectF( m_left.value(), m_top.value(),
m_right.value() - m_left.value(), m_bottom.value() - m_top.value() ); m_width.value(), m_height.value() );
} }
inline QSizeF size() const inline QSizeF size() const
{ {
return QSizeF( m_right.value() - m_left.value(), return QSizeF( m_width.value(), m_height.value() );
m_bottom.value() - m_top.value() );
} }
inline Expression width() const { return m_right - m_left; } inline Expression centerH() const { return m_left + 0.5 * m_width; }
inline Expression height() const { return m_bottom - m_top; } inline Expression centerV() const { return m_top + 0.5 * m_height; }
inline Expression right() const { return m_left + m_width; }
inline Expression centerH() const { return m_left + 0.5 * width(); } inline Expression bottom() const { return m_top + m_height; }
inline Expression centerV() const { return m_top + 0.5 * height(); }
inline const Variable& left() const { return m_left; } inline const Variable& left() const { return m_left; }
inline const Variable& right() const { return m_right; }
inline const Variable& top() const { return m_top; } inline const Variable& top() const { return m_top; }
inline const Variable& bottom() const { return m_bottom; } inline const Variable& width() const { return m_width; }
inline const Variable& height() const { return m_height; }
private: private:
Variable m_left, m_right, m_top, m_bottom; Variable m_left, m_top, m_width, m_height;
}; };
class Anchor class Anchor
@ -109,7 +107,7 @@ class AnchorBox::PrivateData
public: public:
void setItemGeometries( const AnchorBox*, const QRectF& ); void setItemGeometries( const AnchorBox*, const QRectF& );
void setupAnchorConstraints( Solver& ); void setupAnchorConstraints( const AnchorBox*, Solver& );
void setupSizeConstraints( const AnchorBox*, bool, Solver& ); void setupSizeConstraints( const AnchorBox*, bool, Solver& );
public: public:
@ -117,17 +115,53 @@ class AnchorBox::PrivateData
QVector< Anchor > anchors; QVector< Anchor > anchors;
}; };
void AnchorBox::PrivateData::setupAnchorConstraints( Solver& solver ) void AnchorBox::PrivateData::setupAnchorConstraints(
const AnchorBox* box, Solver& solver )
{ {
for ( const auto& anchor : anchors ) for ( const auto& anchor : anchors )
{ {
auto& r1 = geometries[ anchor.item1 ]; auto& r1 = geometries[ anchor.item1 ];
auto& r2 = geometries[ anchor.item2 ]; auto& r2 = geometries[ anchor.item2 ];
solver.addConstraint( r1.expressionAt( anchor.edge1 ) const auto expr1 = r1.expressionAt( anchor.edge1 );
== r2.expressionAt( anchor.edge2 ) );
Expression expr2;
if ( anchor.item2 == box )
{
switch( anchor.edge2 )
{
case Qt::AnchorLeft:
case Qt::AnchorTop:
expr2 = 0;
break;
case Qt::AnchorHorizontalCenter:
expr2 = Term( 0.5 * r2.width() );
break;
case Qt::AnchorRight:
expr2 = Term( r2.width() );
break;
case Qt::AnchorVerticalCenter:
expr2 = Term( 0.5 * r2.height() );
break;
case Qt::AnchorBottom:
expr2 = Term( r2.height() );
break;
}
}
else
{
expr2 = r2.expressionAt( anchor.edge2 );
}
solver.addConstraint( expr1 == expr2 );
#if 1 #if 1
if ( anchor.item2 != box )
{ {
const auto o = qskOrientation( anchor.edge1 ); const auto o = qskOrientation( anchor.edge1 );
@ -162,10 +196,10 @@ void AnchorBox::PrivateData::setupSizeConstraints(
const auto minSize = qskSizeConstraint( item, Qt::MinimumSize ); const auto minSize = qskSizeConstraint( item, Qt::MinimumSize );
if ( minSize.width() >= 0.0 ) if ( minSize.width() >= 0.0 )
solver.addConstraint( r.right() >= r.left() + minSize.width() ); solver.addConstraint( r.width() >= minSize.width() );
if ( minSize.height() >= 0.0 ) if ( minSize.height() >= 0.0 )
solver.addConstraint( r.bottom() >= r.top() + minSize.height() ); solver.addConstraint( r.height() >= minSize.height() );
} }
if ( preferred ) if ( preferred )
@ -173,10 +207,10 @@ void AnchorBox::PrivateData::setupSizeConstraints(
// preferred size // preferred size
const auto prefSize = qskSizeConstraint( item, Qt::PreferredSize ); const auto prefSize = qskSizeConstraint( item, Qt::PreferredSize );
Constraint c1( r.right() == r.left() + prefSize.width(), Strength::strong ); Constraint c1( r.width() == prefSize.width(), Strength::strong );
solver.addConstraint( c1 ); solver.addConstraint( c1 );
Constraint c2( r.bottom() == r.top() + prefSize.height(), Strength::strong ); Constraint c2( r.height() == prefSize.height(), Strength::strong );
solver.addConstraint( c2 ); solver.addConstraint( c2 );
} }
@ -184,10 +218,10 @@ void AnchorBox::PrivateData::setupSizeConstraints(
// maximum size // maximum size
const auto maxSize = qskSizeConstraint( item, Qt::MaximumSize ); const auto maxSize = qskSizeConstraint( item, Qt::MaximumSize );
if ( maxSize.width() >= 0.0 ) if ( maxSize.width() >= 0.0 )
solver.addConstraint( r.right() <= r.left() + maxSize.width() ); solver.addConstraint( r.width() <= maxSize.width() );
if ( maxSize.height() >= 0.0 ) if ( maxSize.height() >= 0.0 )
solver.addConstraint( r.bottom() <= r.top() + maxSize.height() ); solver.addConstraint( r.height() <= maxSize.height() );
} }
} }
} }
@ -197,20 +231,26 @@ void AnchorBox::PrivateData::setItemGeometries(
{ {
// Unefficient as we are always starting from scratch TODO ... // Unefficient as we are always starting from scratch TODO ...
Solver solver; Solver solver;
setupAnchorConstraints( solver ); setupAnchorConstraints( box, solver );
setupSizeConstraints( box, true, solver ); setupSizeConstraints( box, true, solver );
const auto& r0 = geometries[ const_cast< AnchorBox* >( box ) ]; const auto& r0 = geometries[ const_cast< AnchorBox* >( box ) ];
solver.addConstraint( r0.left() == rect.left() ); const double strength = 0.9 * Strength::required;
solver.addConstraint( r0.right() == rect.right() );
solver.addConstraint( r0.top() == rect.top() ); solver.addEditVariable( r0.width(), strength );
solver.addConstraint( r0.bottom() == rect.bottom() ); solver.addEditVariable( r0.height(), strength );
solver.suggestValue( r0.width(), rect.width() );
solver.suggestValue( r0.height(), rect.height() );
solver.updateVariables(); solver.updateVariables();
for ( auto it = geometries.begin(); it != geometries.end(); ++it ) for ( auto it = geometries.begin(); it != geometries.end(); ++it )
qskSetItemGeometry( it.key(), it.value().rect() ); {
const auto r = it.value().rect().translated( rect.left(), rect.top() );
qskSetItemGeometry( it.key(), r );
}
#if 0 #if 0
qDebug() << "=== Rect:" << rect; qDebug() << "=== Rect:" << rect;
@ -277,6 +317,9 @@ void AnchorBox::addAnchor( QQuickItem* item1, Qt::AnchorPoint edge1,
if ( item1 == item2 || item1 == nullptr || item2 == nullptr ) if ( item1 == item2 || item1 == nullptr || item2 == nullptr )
return; return;
if ( item1 == this )
std::swap( item1, item2 );
if ( item1 != this ) if ( item1 != this )
{ {
if ( item1->parent() == nullptr ) if ( item1->parent() == nullptr )
@ -318,7 +361,7 @@ QSizeF AnchorBox::layoutSizeHint( Qt::SizeHint which, const QSizeF& constraint )
const auto& r0 = m_data->geometries[ const_cast< AnchorBox* >( this ) ]; const auto& r0 = m_data->geometries[ const_cast< AnchorBox* >( this ) ];
Solver solver; Solver solver;
m_data->setupAnchorConstraints( solver ); m_data->setupAnchorConstraints( this, solver );
m_data->setupSizeConstraints( this, which == Qt::PreferredSize, solver ); m_data->setupSizeConstraints( this, which == Qt::PreferredSize, solver );
if ( which != Qt::PreferredSize ) if ( which != Qt::PreferredSize )