From 73572dd06e81334d046294b1cda65166b6b2575a Mon Sep 17 00:00:00 2001 From: Uwe Rathmann Date: Fri, 17 Apr 2020 16:05:57 +0200 Subject: [PATCH] work in progress --- playground/anchors/AnchorBox.cpp | 116 +++++++++++++++++++++---------- playground/anchors/AnchorBox.h | 8 ++- playground/anchors/Solver.cpp | 12 ++++ playground/anchors/Solver.h | 2 + 4 files changed, 98 insertions(+), 40 deletions(-) diff --git a/playground/anchors/AnchorBox.cpp b/playground/anchors/AnchorBox.cpp index 09a74579..5cba5761 100644 --- a/playground/anchors/AnchorBox.cpp +++ b/playground/anchors/AnchorBox.cpp @@ -108,6 +108,9 @@ class AnchorBox::PrivateData QMap< QQuickItem*, Geometry > geometries; QVector< Anchor > anchors; Solver solver; + + QSizeF hints[3]; + bool hasValidHints = false; }; AnchorBox::AnchorBox( QQuickItem* parent ) @@ -209,28 +212,57 @@ QSizeF AnchorBox::layoutSizeHint( Qt::SizeHint which, const QSizeF& constraint ) return QSizeF(); } - const auto& r0 = m_data->geometries[ const_cast< AnchorBox* >( this ) ]; - - Solver& solver = m_data->solver; - solver.reset(); - - auto that = const_cast< AnchorBox* >( this ); - that->setupAnchorConstraints(); - that->setupSizeConstraints( which == Qt::PreferredSize ); - - if ( which != Qt::PreferredSize ) + if ( !m_data->hasValidHints ) { - const qreal b = ( which == Qt::MinimumSize ) ? 0.0 : QskLayoutHint::unlimited; + auto that = const_cast< AnchorBox* >( this ); - // why do we need strong here ? - solver.addConstraint( Constraint( r0.width() == b, Strength::strong ) ); - solver.addConstraint( Constraint( r0.height() == b, Strength::strong ) ); + that->updateHints(); + m_data->hasValidHints = true; } - solver.updateVariables(); - solver.reset(); + return m_data->hints[ which ]; +} - return r0.size(); +void AnchorBox::updateHints() +{ + const auto& r0 = m_data->geometries[ const_cast< AnchorBox* >( this ) ]; + + Solver solver; + + setupAnchorConstraints( solver ); + setupSizeConstraints( solver ); + + { + solver.updateVariables(); + m_data->hints[ Qt::PreferredSize ] = r0.size(); + } + + const double strength = 0.9 * Strength::required; + + solver.addEditVariable( r0.width(), strength ); + solver.addEditVariable( r0.height(), strength ); + + { + solver.suggestValue( r0.width(), 0.0 ); + solver.suggestValue( r0.height(), 0.0 ); + + solver.updateVariables(); + m_data->hints[ Qt::MinimumSize ] = r0.size(); + } + + { + /* + The solver seems to run into overflows with + std::numeric_limits< unsigned float >::max() + */ + const qreal max = std::numeric_limits< unsigned int >::max(); + + solver.suggestValue( r0.width(), max ); + solver.suggestValue( r0.height(), max ); + + solver.updateVariables(); + m_data->hints[ Qt::MaximumSize ] = r0.size(); + } } void AnchorBox::geometryChangeEvent( QskGeometryChangeEvent* event ) @@ -246,39 +278,50 @@ void AnchorBox::updateLayout() if ( maybeUnresized() ) return; - auto& geometries = m_data->geometries; - const auto rect = layoutRect(); - const auto& r0 = geometries[ this ]; - const double strength = 0.9 * Strength::required; + updateVariables( rect.width(), rect.height() ); + + const auto& geometries = m_data->geometries; + for ( auto it = geometries.begin(); it != geometries.end(); ++it ) + { + auto item = it.key(); + if ( item != this ) + { + auto r = it.value().rect(); + r.translate( rect.left(), rect.top() ); + + qskSetItemGeometry( item, r ); + } + } + +} + +void AnchorBox::updateVariables( qreal width, qreal height ) +{ + const auto& r0 = m_data->geometries[ this ]; Solver& solver = m_data->solver; - if ( !solver.hasEditVariable( r0.width() ) ) + if ( !solver.hasConstraints() ) { - setupAnchorConstraints(); - setupSizeConstraints( true ); + setupAnchorConstraints( solver ); + setupSizeConstraints( solver ); + + const double strength = 0.9 * Strength::required; solver.addEditVariable( r0.width(), strength ); solver.addEditVariable( r0.height(), strength ); } - solver.suggestValue( r0.width(), rect.width() ); - solver.suggestValue( r0.height(), rect.height() ); + solver.suggestValue( r0.width(), width ); + solver.suggestValue( r0.height(), height ); solver.updateVariables(); - - for ( auto it = geometries.begin(); it != geometries.end(); ++it ) - { - const auto r = it.value().rect().translated( rect.left(), rect.top() ); - qskSetItemGeometry( it.key(), r ); - } } -void AnchorBox::setupAnchorConstraints() +void AnchorBox::setupAnchorConstraints( Solver& solver ) { - auto& solver = m_data->solver; auto& geometries = m_data->geometries; for ( const auto& anchor : m_data->anchors ) @@ -343,9 +386,8 @@ void AnchorBox::setupAnchorConstraints() } } -void AnchorBox::setupSizeConstraints( bool preferred ) +void AnchorBox::setupSizeConstraints( Solver& solver ) { - auto& solver = m_data->solver; auto& geometries = m_data->geometries; for ( auto it = geometries.begin(); it != geometries.end(); ++it ) @@ -367,7 +409,6 @@ void AnchorBox::setupSizeConstraints( bool preferred ) solver.addConstraint( r.height() >= minSize.height() ); } - if ( preferred ) { // preferred size const auto prefSize = qskSizeConstraint( item, Qt::PreferredSize ); @@ -391,5 +432,4 @@ void AnchorBox::setupSizeConstraints( bool preferred ) } } - #include "moc_AnchorBox.cpp" diff --git a/playground/anchors/AnchorBox.h b/playground/anchors/AnchorBox.h index b661c3f7..73a6a7ce 100644 --- a/playground/anchors/AnchorBox.h +++ b/playground/anchors/AnchorBox.h @@ -8,6 +8,8 @@ #include "QskControl.h" +class Solver; + class AnchorBox : public QskControl { Q_OBJECT @@ -36,8 +38,10 @@ class AnchorBox : public QskControl QSizeF layoutSizeHint( Qt::SizeHint, const QSizeF& ) const override; private: - void setupAnchorConstraints(); - void setupSizeConstraints( bool ); + void updateHints(); + void updateVariables( qreal width, qreal height ); + void setupAnchorConstraints( Solver& ); + void setupSizeConstraints( Solver& ); class PrivateData; std::unique_ptr< PrivateData > m_data; diff --git a/playground/anchors/Solver.cpp b/playground/anchors/Solver.cpp index 6987234e..3c94c567 100644 --- a/playground/anchors/Solver.cpp +++ b/playground/anchors/Solver.cpp @@ -388,6 +388,8 @@ class SimplexSolver void removeConstraint( const Constraint& ); bool hasConstraint( const Constraint& ) const; + bool hasConstraints() const; + void addEditVariable( const Variable&, double strength ); void removeEditVariable( const Variable& ); @@ -439,6 +441,11 @@ SimplexSolver::~SimplexSolver() clearRows(); } +bool SimplexSolver::hasConstraints() const +{ + return !m_constraints.empty(); +} + void SimplexSolver::addConstraint( const Constraint& constraint ) { if( m_constraints.find( constraint ) != m_constraints.end() ) @@ -1034,6 +1041,11 @@ Solver::~Solver() { } +bool Solver::hasConstraints() const +{ + return m_solver->hasConstraints(); +} + void Solver::addConstraint( const Constraint& constraint ) { m_solver->addConstraint( constraint ); diff --git a/playground/anchors/Solver.h b/playground/anchors/Solver.h index 3f721550..06c055a8 100644 --- a/playground/anchors/Solver.h +++ b/playground/anchors/Solver.h @@ -14,6 +14,8 @@ class Solver Solver(); ~Solver(); + bool hasConstraints() const; + void addConstraint( const Constraint& ); void removeConstraint( const Constraint& ); bool hasConstraint( const Constraint& ) const;