work in progress

This commit is contained in:
Uwe Rathmann 2020-04-17 16:05:57 +02:00
parent e108487d4e
commit 73572dd06e
4 changed files with 98 additions and 40 deletions

View File

@ -108,6 +108,9 @@ class AnchorBox::PrivateData
QMap< QQuickItem*, Geometry > geometries; QMap< QQuickItem*, Geometry > geometries;
QVector< Anchor > anchors; QVector< Anchor > anchors;
Solver solver; Solver solver;
QSizeF hints[3];
bool hasValidHints = false;
}; };
AnchorBox::AnchorBox( QQuickItem* parent ) AnchorBox::AnchorBox( QQuickItem* parent )
@ -209,28 +212,57 @@ QSizeF AnchorBox::layoutSizeHint( Qt::SizeHint which, const QSizeF& constraint )
return QSizeF(); return QSizeF();
} }
const auto& r0 = m_data->geometries[ const_cast< AnchorBox* >( this ) ]; if ( !m_data->hasValidHints )
Solver& solver = m_data->solver;
solver.reset();
auto that = const_cast< AnchorBox* >( this );
that->setupAnchorConstraints();
that->setupSizeConstraints( which == Qt::PreferredSize );
if ( which != Qt::PreferredSize )
{ {
const qreal b = ( which == Qt::MinimumSize ) ? 0.0 : QskLayoutHint::unlimited; auto that = const_cast< AnchorBox* >( this );
// why do we need strong here ? that->updateHints();
solver.addConstraint( Constraint( r0.width() == b, Strength::strong ) ); m_data->hasValidHints = true;
solver.addConstraint( Constraint( r0.height() == b, Strength::strong ) );
} }
solver.updateVariables(); return m_data->hints[ which ];
solver.reset(); }
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 ) void AnchorBox::geometryChangeEvent( QskGeometryChangeEvent* event )
@ -246,39 +278,50 @@ void AnchorBox::updateLayout()
if ( maybeUnresized() ) if ( maybeUnresized() )
return; return;
auto& geometries = m_data->geometries;
const auto rect = layoutRect(); 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; Solver& solver = m_data->solver;
if ( !solver.hasEditVariable( r0.width() ) ) if ( !solver.hasConstraints() )
{ {
setupAnchorConstraints(); setupAnchorConstraints( solver );
setupSizeConstraints( true ); setupSizeConstraints( solver );
const double strength = 0.9 * Strength::required;
solver.addEditVariable( r0.width(), strength ); solver.addEditVariable( r0.width(), strength );
solver.addEditVariable( r0.height(), strength ); solver.addEditVariable( r0.height(), strength );
} }
solver.suggestValue( r0.width(), rect.width() ); solver.suggestValue( r0.width(), width );
solver.suggestValue( r0.height(), rect.height() ); solver.suggestValue( r0.height(), height );
solver.updateVariables(); 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; auto& geometries = m_data->geometries;
for ( const auto& anchor : m_data->anchors ) 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; auto& geometries = m_data->geometries;
for ( auto it = geometries.begin(); it != geometries.end(); ++it ) for ( auto it = geometries.begin(); it != geometries.end(); ++it )
@ -367,7 +409,6 @@ void AnchorBox::setupSizeConstraints( bool preferred )
solver.addConstraint( r.height() >= minSize.height() ); solver.addConstraint( r.height() >= minSize.height() );
} }
if ( preferred )
{ {
// preferred size // preferred size
const auto prefSize = qskSizeConstraint( item, Qt::PreferredSize ); const auto prefSize = qskSizeConstraint( item, Qt::PreferredSize );
@ -391,5 +432,4 @@ void AnchorBox::setupSizeConstraints( bool preferred )
} }
} }
#include "moc_AnchorBox.cpp" #include "moc_AnchorBox.cpp"

View File

@ -8,6 +8,8 @@
#include "QskControl.h" #include "QskControl.h"
class Solver;
class AnchorBox : public QskControl class AnchorBox : public QskControl
{ {
Q_OBJECT Q_OBJECT
@ -36,8 +38,10 @@ class AnchorBox : public QskControl
QSizeF layoutSizeHint( Qt::SizeHint, const QSizeF& ) const override; QSizeF layoutSizeHint( Qt::SizeHint, const QSizeF& ) const override;
private: private:
void setupAnchorConstraints(); void updateHints();
void setupSizeConstraints( bool ); void updateVariables( qreal width, qreal height );
void setupAnchorConstraints( Solver& );
void setupSizeConstraints( Solver& );
class PrivateData; class PrivateData;
std::unique_ptr< PrivateData > m_data; std::unique_ptr< PrivateData > m_data;

View File

@ -388,6 +388,8 @@ class SimplexSolver
void removeConstraint( const Constraint& ); void removeConstraint( const Constraint& );
bool hasConstraint( const Constraint& ) const; bool hasConstraint( const Constraint& ) const;
bool hasConstraints() const;
void addEditVariable( const Variable&, double strength ); void addEditVariable( const Variable&, double strength );
void removeEditVariable( const Variable& ); void removeEditVariable( const Variable& );
@ -439,6 +441,11 @@ SimplexSolver::~SimplexSolver()
clearRows(); clearRows();
} }
bool SimplexSolver::hasConstraints() const
{
return !m_constraints.empty();
}
void SimplexSolver::addConstraint( const Constraint& constraint ) void SimplexSolver::addConstraint( const Constraint& constraint )
{ {
if( m_constraints.find( constraint ) != m_constraints.end() ) 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 ) void Solver::addConstraint( const Constraint& constraint )
{ {
m_solver->addConstraint( constraint ); m_solver->addConstraint( constraint );

View File

@ -14,6 +14,8 @@ class Solver
Solver(); Solver();
~Solver(); ~Solver();
bool hasConstraints() const;
void addConstraint( const Constraint& ); void addConstraint( const Constraint& );
void removeConstraint( const Constraint& ); void removeConstraint( const Constraint& );
bool hasConstraint( const Constraint& ) const; bool hasConstraint( const Constraint& ) const;