From a7e30c2550ca82c738b9b62e583cee5d3ee902e6 Mon Sep 17 00:00:00 2001 From: Uwe Rathmann Date: Sun, 5 Apr 2020 19:25:59 +0200 Subject: [PATCH] non dynamic size constraints do work for simple use cases --- playground/anchors/AnchorBox.cpp | 103 ++++++++++++++++++++++++++----- playground/anchors/AnchorBox.h | 8 +++ playground/anchors/main.cpp | 33 ++++------ 3 files changed, 108 insertions(+), 36 deletions(-) diff --git a/playground/anchors/AnchorBox.cpp b/playground/anchors/AnchorBox.cpp index 0dc0757f..dfc44f9d 100644 --- a/playground/anchors/AnchorBox.cpp +++ b/playground/anchors/AnchorBox.cpp @@ -12,6 +12,7 @@ #include #include +#include #include @@ -20,6 +21,15 @@ static inline Qt::Orientation qskOrientation( int edge ) return ( edge <= Qt::AnchorRight ) ? Qt::Horizontal : Qt::Vertical; } +static inline Qt::AnchorPoint qskAnchorPoint( + Qt::Corner corner, Qt::Orientation orientation ) +{ + if ( orientation == Qt::Horizontal ) + return ( corner & 0x1 ) ? Qt::AnchorRight : Qt::AnchorLeft; + else + return ( corner >= 0x2 ) ? Qt::AnchorBottom : Qt::AnchorTop; +} + namespace { class Geometry @@ -51,17 +61,23 @@ namespace return Expression(); } - Expression length( Qt::Orientation orientation ) + inline Expression length( Qt::Orientation orientation ) { return ( orientation == Qt::Horizontal ) ? width() : height(); } - QRectF rect() const + inline QRectF rect() const { return QRectF( m_left.value(), m_top.value(), m_right.value() - m_left.value(), m_bottom.value() - m_top.value() ); } + inline QSizeF size() const + { + return QSizeF( m_right.value() - m_left.value(), + m_bottom.value() - m_top.value() ); + } + inline Expression width() const { return m_right - m_left; } inline Expression height() const { return m_bottom - m_top; } @@ -91,12 +107,10 @@ namespace class AnchorBox::PrivateData { public: - void setupSolver( Solver& ); void setItemGeometries( const AnchorBox*, const QRectF& ); - private: void setupAnchorConstraints( Solver& ); - void setupSizeConstraints( Solver& ); + void setupSizeConstraints( const AnchorBox*, bool, Solver& ); public: QMap< QQuickItem*, Geometry > geometries; @@ -132,11 +146,15 @@ void AnchorBox::PrivateData::setupAnchorConstraints( Solver& solver ) } } -void AnchorBox::PrivateData::setupSizeConstraints( Solver& solver ) +void AnchorBox::PrivateData::setupSizeConstraints( + const AnchorBox* box, bool preferred, Solver& solver ) { for ( auto it = geometries.begin(); it != geometries.end(); ++it ) { const auto item = it.key(); + if ( item == box ) + continue; + auto& r = it.value(); { @@ -150,6 +168,7 @@ void AnchorBox::PrivateData::setupSizeConstraints( Solver& solver ) solver.addConstraint( r.bottom() >= r.top() + minSize.height() ); } + if ( preferred ) { // preferred size const auto prefSize = qskSizeConstraint( item, Qt::PreferredSize ); @@ -173,17 +192,13 @@ void AnchorBox::PrivateData::setupSizeConstraints( Solver& solver ) } } -void AnchorBox::PrivateData::setupSolver( Solver& solver ) -{ - setupAnchorConstraints( solver ); - setupSizeConstraints( solver ); -} - void AnchorBox::PrivateData::setItemGeometries( const AnchorBox* box, const QRectF& rect ) { + // Unefficient as we are always starting from scratch TODO ... Solver solver; - setupSolver( solver ); + setupAnchorConstraints( solver ); + setupSizeConstraints( box, true, solver ); const auto& r0 = geometries[ const_cast< AnchorBox* >( box ) ]; @@ -215,6 +230,41 @@ AnchorBox::~AnchorBox() { } +void AnchorBox::addAnchors( QQuickItem* item, Qt::Orientations orientations ) +{ + addAnchors( item, this, orientations ); +} + +void AnchorBox::addAnchors( QQuickItem* item1, + QQuickItem* item2, Qt::Orientations orientations ) +{ + if ( orientations & Qt::Horizontal ) + { + addAnchor( item1, Qt::AnchorLeft, item2, Qt::AnchorLeft ); + addAnchor( item1, Qt::AnchorRight, item2, Qt::AnchorRight ); + } + if ( orientations & Qt::Vertical ) + { + addAnchor( item1, Qt::AnchorTop, item2, Qt::AnchorTop ); + addAnchor( item1, Qt::AnchorBottom, item2, Qt::AnchorBottom ); + } +} + +void AnchorBox::addAnchors( QQuickItem* item, Qt::Corner corner ) +{ + addAnchors( item, corner, this, corner ); +} + +void AnchorBox::addAnchors( QQuickItem* item1, + Qt::Corner corner1, QQuickItem* item2, Qt::Corner corner2 ) +{ + addAnchor( item1, qskAnchorPoint( corner1, Qt::Horizontal ), + item2, qskAnchorPoint( corner2, Qt::Horizontal ) ); + + addAnchor( item1, qskAnchorPoint( corner1, Qt::Vertical ), + item2, qskAnchorPoint( corner2, Qt::Vertical ) ); +} + void AnchorBox::addAnchor( QQuickItem* item, Qt::AnchorPoint edge1, Qt::AnchorPoint edge2 ) { @@ -257,9 +307,32 @@ void AnchorBox::addAnchor( QQuickItem* item1, Qt::AnchorPoint edge1, m_data->anchors += anchor; } -QSizeF AnchorBox::layoutSizeHint( Qt::SizeHint, const QSizeF& ) const +QSizeF AnchorBox::layoutSizeHint( Qt::SizeHint which, const QSizeF& constraint ) const { - return QSizeF(); + if ( constraint.width() >= 0.0 || constraint.height() >= 0.0 ) + { + // TODO ... + return QSizeF(); + } + + const auto& r0 = m_data->geometries[ const_cast< AnchorBox* >( this ) ]; + + Solver solver; + m_data->setupAnchorConstraints( solver ); + m_data->setupSizeConstraints( this, which == Qt::PreferredSize, solver ); + + if ( which != Qt::PreferredSize ) + { + const qreal b = ( which == Qt::MinimumSize ) ? 0.0 : QskLayoutHint::unlimited; + + // why do we need strong here ? + solver.addConstraint( Constraint( r0.width() == b, Strength::strong ) ); + solver.addConstraint( Constraint( r0.height() == b, Strength::strong ) ); + } + + solver.updateVariables(); + + return r0.size(); } void AnchorBox::geometryChangeEvent( QskGeometryChangeEvent* event ) diff --git a/playground/anchors/AnchorBox.h b/playground/anchors/AnchorBox.h index 92293eca..81ab7d21 100644 --- a/playground/anchors/AnchorBox.h +++ b/playground/anchors/AnchorBox.h @@ -18,8 +18,16 @@ class AnchorBox : public QskControl AnchorBox( QQuickItem* parent = nullptr ); ~AnchorBox() override; + // anchoring to the box void addAnchor( QQuickItem*, Qt::AnchorPoint, Qt::AnchorPoint ); + void addAnchors( QQuickItem*, Qt::Corner ); + void addAnchors( QQuickItem*, Qt::Orientations = Qt::Horizontal | Qt::Vertical ); + + // anchoring between 2 children void addAnchor( QQuickItem*, Qt::AnchorPoint, QQuickItem*, Qt::AnchorPoint ); + void addAnchors( QQuickItem*, Qt::Corner, QQuickItem*, Qt::Corner ); + void addAnchors( QQuickItem*, QQuickItem*, + Qt::Orientations = Qt::Horizontal | Qt::Vertical ); protected: void geometryChangeEvent( QskGeometryChangeEvent* ) override; diff --git a/playground/anchors/main.cpp b/playground/anchors/main.cpp index 52acfc0a..7f758ec6 100644 --- a/playground/anchors/main.cpp +++ b/playground/anchors/main.cpp @@ -54,7 +54,6 @@ class MyBox : public AnchorBox : AnchorBox( parent ) { setObjectName( "Box" ); - setup1(); } @@ -115,27 +114,11 @@ void MyBox::setup1() void MyBox::setup2() { auto a = new TestRectangle( "PaleVioletRed" ); + auto b = new TestRectangle( "DarkSeaGreen" ); - addAnchor( a, Qt::AnchorLeft, Qt::AnchorLeft ); - addAnchor( a, Qt::AnchorTop, Qt::AnchorTop ); - - -#if 0 - auto b = new Rectangle( "DarkSeaGreen" ); - addAnchor( a, Qt::AnchorRight, b, Qt::AnchorLeft ); - addAnchor( b, Qt::AnchorRight, m_layout, Qt::AnchorRight ); -#endif - -#if 1 - auto c = new TestRectangle( "SkyBlue" ); - addAnchor( a, Qt::AnchorBottom, c, Qt::AnchorTop ); - addAnchor( a, Qt::AnchorRight, c, Qt::AnchorRight ); - - auto d = new TestRectangle( "Coral" ); - addAnchor( c, Qt::AnchorLeft, d, Qt::AnchorLeft ); - addAnchor( c, Qt::AnchorBottom, d, Qt::AnchorTop ); - addAnchor( d, Qt::AnchorRight, Qt::AnchorRight ); -#endif + addAnchors( a, Qt::TopLeftCorner ); + addAnchors( a, Qt::BottomRightCorner, b, Qt::TopLeftCorner ); + addAnchors( b, Qt::BottomRightCorner ); } void MyBox::setup3() @@ -175,6 +158,14 @@ int main( int argc, char* argv[] ) auto box = new MyBox(); +#if 1 + for ( int i = Qt::MinimumSize; i <= Qt::MaximumSize; i++ ) + { + const auto which = static_cast< Qt::SizeHint >( i ); + qDebug() << which << box->effectiveSizeHint( which ); + } +#endif + QskWindow window; window.addItem( box ); window.resize( 600, 600 );