AnchorBox improved
This commit is contained in:
parent
d5604823c2
commit
a655c96c8b
@ -30,22 +30,22 @@ namespace
|
|||||||
switch( anchorPoint )
|
switch( anchorPoint )
|
||||||
{
|
{
|
||||||
case Qt::AnchorLeft:
|
case Qt::AnchorLeft:
|
||||||
return Term( left );
|
return Term( m_left );
|
||||||
|
|
||||||
case Qt::AnchorHorizontalCenter:
|
case Qt::AnchorHorizontalCenter:
|
||||||
return centerH();
|
return centerH();
|
||||||
|
|
||||||
case Qt::AnchorRight:
|
case Qt::AnchorRight:
|
||||||
return Term( right );
|
return Term( m_right );
|
||||||
|
|
||||||
case Qt::AnchorTop:
|
case Qt::AnchorTop:
|
||||||
return Term( top );
|
return Term( m_top );
|
||||||
|
|
||||||
case Qt::AnchorVerticalCenter:
|
case Qt::AnchorVerticalCenter:
|
||||||
return centerV();
|
return centerV();
|
||||||
|
|
||||||
case Qt::AnchorBottom:
|
case Qt::AnchorBottom:
|
||||||
return Term( bottom );
|
return Term( m_bottom );
|
||||||
}
|
}
|
||||||
|
|
||||||
return Expression();
|
return Expression();
|
||||||
@ -58,17 +58,23 @@ namespace
|
|||||||
|
|
||||||
QRectF rect() const
|
QRectF rect() const
|
||||||
{
|
{
|
||||||
return QRectF( left.value(), top.value(),
|
return QRectF( m_left.value(), m_top.value(),
|
||||||
right.value() - left.value(), bottom.value() - top.value() );
|
m_right.value() - m_left.value(), m_bottom.value() - m_top.value() );
|
||||||
}
|
}
|
||||||
|
|
||||||
Expression width() const { return right - left; }
|
inline Expression width() const { return m_right - m_left; }
|
||||||
Expression height() const { return bottom - top; }
|
inline Expression height() const { return m_bottom - m_top; }
|
||||||
|
|
||||||
Expression centerH() const { return left + 0.5 * width(); }
|
inline Expression centerH() const { return m_left + 0.5 * width(); }
|
||||||
Expression centerV() const { return top + 0.5 * height(); }
|
inline Expression centerV() const { return m_top + 0.5 * height(); }
|
||||||
|
|
||||||
Variable left, right, top, bottom;
|
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& bottom() const { return m_bottom; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
Variable m_left, m_right, m_top, m_bottom;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Anchor
|
class Anchor
|
||||||
@ -85,13 +91,19 @@ namespace
|
|||||||
class AnchorBox::PrivateData
|
class AnchorBox::PrivateData
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
void setupSolver( int type, Solver& );
|
void setupSolver( Solver& );
|
||||||
|
void setItemGeometries( const AnchorBox*, const QRectF& );
|
||||||
|
|
||||||
|
private:
|
||||||
|
void setupAnchorConstraints( Solver& );
|
||||||
|
void setupSizeConstraints( Solver& );
|
||||||
|
|
||||||
|
public:
|
||||||
QMap< QQuickItem*, Geometry > geometries;
|
QMap< QQuickItem*, Geometry > geometries;
|
||||||
QVector< Anchor > anchors;
|
QVector< Anchor > anchors;
|
||||||
};
|
};
|
||||||
|
|
||||||
void AnchorBox::PrivateData::setupSolver( int type, Solver& solver )
|
void AnchorBox::PrivateData::setupAnchorConstraints( Solver& solver )
|
||||||
{
|
{
|
||||||
for ( const auto& anchor : anchors )
|
for ( const auto& anchor : anchors )
|
||||||
{
|
{
|
||||||
@ -102,57 +114,96 @@ void AnchorBox::PrivateData::setupSolver( int type, Solver& solver )
|
|||||||
== r2.expressionAt( anchor.edge2 ) );
|
== r2.expressionAt( anchor.edge2 ) );
|
||||||
|
|
||||||
#if 1
|
#if 1
|
||||||
if ( type < 0 )
|
|
||||||
{
|
{
|
||||||
|
const auto o = qskOrientation( anchor.edge1 );
|
||||||
|
|
||||||
|
/*
|
||||||
|
A constraint with medium strength to make anchored item
|
||||||
|
being stretched according to their stretch factors s1, s2.
|
||||||
|
( For the moment we don't support having specific factors. )
|
||||||
|
*/
|
||||||
const auto s1 = 1.0;
|
const auto s1 = 1.0;
|
||||||
const auto s2 = 1.0;
|
const auto s2 = 1.0;
|
||||||
const auto o = qskOrientation( anchor.edge1 );
|
|
||||||
|
|
||||||
Constraint c( r1.length( o ) * s1 == r2.length( o ) * s2, Strength::medium );
|
Constraint c( r1.length( o ) * s1 == r2.length( o ) * s2, Strength::medium );
|
||||||
solver.addConstraint( c );
|
solver.addConstraint( c );
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AnchorBox::PrivateData::setupSizeConstraints( Solver& solver )
|
||||||
|
{
|
||||||
for ( auto it = geometries.begin(); it != geometries.end(); ++it )
|
for ( auto it = geometries.begin(); it != geometries.end(); ++it )
|
||||||
{
|
{
|
||||||
const auto item = it.key();
|
const auto item = it.key();
|
||||||
auto& r = it.value();
|
auto& r = it.value();
|
||||||
|
|
||||||
if ( type < 0 || type == Qt::MinimumSize )
|
|
||||||
{
|
{
|
||||||
|
// minimum size
|
||||||
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.right() >= r.left() + minSize.width() );
|
||||||
|
|
||||||
if ( minSize.height() >= 0.0 )
|
if ( minSize.height() >= 0.0 )
|
||||||
solver.addConstraint( r.bottom >= r.top + minSize.height() );
|
solver.addConstraint( r.bottom() >= r.top() + minSize.height() );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( type < 0 || type == Qt::PreferredSize )
|
|
||||||
{
|
{
|
||||||
|
// 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.right() == r.left() + prefSize.width(), Strength::strong );
|
||||||
solver.addConstraint( c1 );
|
solver.addConstraint( c1 );
|
||||||
|
|
||||||
Constraint c2( r.bottom == r.top + prefSize.height(), Strength::strong );
|
Constraint c2( r.bottom() == r.top() + prefSize.height(), Strength::strong );
|
||||||
solver.addConstraint( c2 );
|
solver.addConstraint( c2 );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( type < 0 || type == Qt::MaximumSize )
|
|
||||||
{
|
{
|
||||||
|
// 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.right() <= r.left() + maxSize.width() );
|
||||||
|
|
||||||
if ( maxSize.height() >= 0.0 )
|
if ( maxSize.height() >= 0.0 )
|
||||||
solver.addConstraint( r.bottom <= r.top + maxSize.height() );
|
solver.addConstraint( r.bottom() <= r.top() + maxSize.height() );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AnchorBox::PrivateData::setupSolver( Solver& solver )
|
||||||
|
{
|
||||||
|
setupAnchorConstraints( solver );
|
||||||
|
setupSizeConstraints( solver );
|
||||||
|
}
|
||||||
|
|
||||||
|
void AnchorBox::PrivateData::setItemGeometries(
|
||||||
|
const AnchorBox* box, const QRectF& rect )
|
||||||
|
{
|
||||||
|
Solver solver;
|
||||||
|
setupSolver( solver );
|
||||||
|
|
||||||
|
const auto& r0 = geometries[ const_cast< AnchorBox* >( box ) ];
|
||||||
|
|
||||||
|
solver.addConstraint( r0.left() == rect.left() );
|
||||||
|
solver.addConstraint( r0.right() == rect.right() );
|
||||||
|
solver.addConstraint( r0.top() == rect.top() );
|
||||||
|
solver.addConstraint( r0.bottom() == rect.bottom() );
|
||||||
|
|
||||||
|
solver.updateVariables();
|
||||||
|
|
||||||
|
for ( auto it = geometries.begin(); it != geometries.end(); ++it )
|
||||||
|
qskSetItemGeometry( it.key(), it.value().rect() );
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
qDebug() << "=== Rect:" << rect;
|
||||||
|
for ( auto it = geometries.begin(); it != geometries.end(); ++it )
|
||||||
|
qDebug() << it.key()->objectName() << it.value().rect();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
AnchorBox::AnchorBox( QQuickItem* parent )
|
AnchorBox::AnchorBox( QQuickItem* parent )
|
||||||
: QskControl( parent )
|
: QskControl( parent )
|
||||||
, m_data( new PrivateData )
|
, m_data( new PrivateData )
|
||||||
@ -206,40 +257,9 @@ void AnchorBox::addAnchor( QQuickItem* item1, Qt::AnchorPoint edge1,
|
|||||||
m_data->anchors += anchor;
|
m_data->anchors += anchor;
|
||||||
}
|
}
|
||||||
|
|
||||||
QSizeF AnchorBox::boxHint( Qt::SizeHint which )
|
QSizeF AnchorBox::layoutSizeHint( Qt::SizeHint, const QSizeF& ) const
|
||||||
{
|
{
|
||||||
Solver solver;
|
return QSizeF();
|
||||||
m_data->setupSolver( which, solver );
|
|
||||||
solver.updateVariables();
|
|
||||||
|
|
||||||
auto& r0 = m_data->geometries[ this ];
|
|
||||||
|
|
||||||
return QSizeF( r0.rect().size() );
|
|
||||||
}
|
|
||||||
|
|
||||||
void AnchorBox::setItemGeometries( const QRectF& rect )
|
|
||||||
{
|
|
||||||
Solver solver;
|
|
||||||
m_data->setupSolver( -1, solver );
|
|
||||||
|
|
||||||
auto& r0 = m_data->geometries[ this ];
|
|
||||||
|
|
||||||
solver.addConstraint( r0.left == rect.left() );
|
|
||||||
solver.addConstraint( r0.right == rect.right() );
|
|
||||||
solver.addConstraint( r0.top == rect.top() );
|
|
||||||
solver.addConstraint( r0.bottom == rect.bottom() );
|
|
||||||
|
|
||||||
solver.updateVariables();
|
|
||||||
|
|
||||||
const auto& geometries = m_data->geometries;
|
|
||||||
for ( auto it = geometries.begin(); it != geometries.end(); ++it )
|
|
||||||
qskSetItemGeometry( it.key(), it.value().rect() );
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
qDebug() << "=== Rect:" << rect;
|
|
||||||
for ( auto it = geometries.begin(); it != geometries.end(); ++it )
|
|
||||||
qDebug() << it.key()->objectName() << it.value().rect();
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AnchorBox::geometryChangeEvent( QskGeometryChangeEvent* event )
|
void AnchorBox::geometryChangeEvent( QskGeometryChangeEvent* event )
|
||||||
@ -253,7 +273,7 @@ void AnchorBox::geometryChangeEvent( QskGeometryChangeEvent* event )
|
|||||||
void AnchorBox::updateLayout()
|
void AnchorBox::updateLayout()
|
||||||
{
|
{
|
||||||
if ( !maybeUnresized() )
|
if ( !maybeUnresized() )
|
||||||
setItemGeometries( layoutRect() );
|
m_data->setItemGeometries( this, layoutRect() );
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "moc_AnchorBox.cpp"
|
#include "moc_AnchorBox.cpp"
|
||||||
|
@ -21,15 +21,13 @@ class AnchorBox : public QskControl
|
|||||||
void addAnchor( QQuickItem*, Qt::AnchorPoint, Qt::AnchorPoint );
|
void addAnchor( QQuickItem*, Qt::AnchorPoint, Qt::AnchorPoint );
|
||||||
void addAnchor( QQuickItem*, Qt::AnchorPoint, QQuickItem*, Qt::AnchorPoint );
|
void addAnchor( QQuickItem*, Qt::AnchorPoint, QQuickItem*, Qt::AnchorPoint );
|
||||||
|
|
||||||
QSizeF boxHint( Qt::SizeHint );
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void geometryChangeEvent( QskGeometryChangeEvent* ) override;
|
void geometryChangeEvent( QskGeometryChangeEvent* ) override;
|
||||||
void updateLayout() override;
|
void updateLayout() override;
|
||||||
|
|
||||||
private:
|
QSizeF layoutSizeHint( Qt::SizeHint, const QSizeF& ) const override;
|
||||||
void setItemGeometries( const QRectF& );
|
|
||||||
|
|
||||||
|
private:
|
||||||
class PrivateData;
|
class PrivateData;
|
||||||
std::unique_ptr< PrivateData > m_data;
|
std::unique_ptr< PrivateData > m_data;
|
||||||
};
|
};
|
||||||
|
@ -66,11 +66,6 @@ class MyBox : public AnchorBox
|
|||||||
virtual void geometryChangeEvent( QskGeometryChangeEvent* event ) override
|
virtual void geometryChangeEvent( QskGeometryChangeEvent* event ) override
|
||||||
{
|
{
|
||||||
AnchorBox::geometryChangeEvent( event );
|
AnchorBox::geometryChangeEvent( event );
|
||||||
#if 1
|
|
||||||
qDebug() << boxHint( Qt::MinimumSize );
|
|
||||||
qDebug() << boxHint( Qt::PreferredSize );
|
|
||||||
qDebug() << boxHint( Qt::MaximumSize );
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user