diff --git a/src/layouts/QskLayoutConstraint.cpp b/src/layouts/QskLayoutConstraint.cpp index 103de00c..69bf25e4 100644 --- a/src/layouts/QskLayoutConstraint.cpp +++ b/src/layouts/QskLayoutConstraint.cpp @@ -6,6 +6,7 @@ #include "QskLayoutConstraint.h" #include "QskControl.h" #include "QskSizePolicy.h" +#include "QskLayoutHint.h" #include "QskFunctions.h" #include @@ -129,6 +130,22 @@ QskLayoutConstraint::Type QskLayoutConstraint::constraintType( const QQuickItem* return constraintType; } +bool QskLayoutConstraint::isConstrained( + const QQuickItem* item, Qt::Orientation orientation ) +{ + switch( constraintType( item ) ) + { + case QskLayoutConstraint::WidthForHeight: + return orientation == Qt::Horizontal; + + case QskLayoutConstraint::HeightForWidth: + return orientation == Qt::Vertical; + + default: + return false; + } +} + qreal QskLayoutConstraint::heightForWidth( const QQuickItem* item, qreal width ) { if ( auto control = qskControlCast( item ) ) @@ -186,7 +203,7 @@ qreal QskLayoutConstraint::constrainedMetric( } qreal QskLayoutConstraint::constrainedChildrenMetric( - Type type, const QskControl* control, qreal widthOrHeight ) + Type type, const QskControl* control, qreal constraint ) { auto constrainFunction = ( type == WidthForHeight ) ? widthForHeight : heightForWidth; @@ -200,7 +217,7 @@ qreal QskLayoutConstraint::constrainedChildrenMetric( { if ( !control->isTransparentForPositioner() ) { - const auto v = constrainFunction( control, widthOrHeight ); + const auto v = constrainFunction( control, constraint ); if ( v > constrainedValue ) constrainedValue = v; } @@ -460,3 +477,50 @@ QRectF QskLayoutConstraint::itemRect( const QQuickItem* item, return qskAlignedRectF( rect, size.width(), size.height(), alignment ); } +QskLayoutHint QskLayoutConstraint::layoutHint( + const QQuickItem* item, Qt::Orientation orientation, qreal constraint ) +{ + if ( item == nullptr ) + return QskLayoutHint(); + + const auto policy = sizePolicy( item ).policy( orientation ); + + if ( constraint >= 0.0 ) + { + if ( !isConstrained( item, orientation ) ) + constraint = -1.0; + } + + qreal minimum, preferred, maximum; + + const auto expandFlags = QskSizePolicy::GrowFlag | QskSizePolicy::ExpandFlag; + + if ( ( policy & QskSizePolicy::ShrinkFlag ) && + ( policy & expandFlags ) && ( policy & QskSizePolicy::IgnoreFlag ) ) + { + // we don't need to calculate the preferred size + + minimum = sizeHint( item, Qt::MinimumSize, orientation, constraint ); + maximum = sizeHint( item, Qt::MaximumSize, orientation, constraint ); + preferred = minimum; + } + else + { + preferred = sizeHint( item, Qt::PreferredSize, orientation, constraint ); + + if ( policy & QskSizePolicy::ShrinkFlag ) + minimum = sizeHint( item, Qt::MinimumSize, orientation, constraint ); + else + minimum = preferred; + + if ( policy & expandFlags ) + maximum = sizeHint( item, Qt::MaximumSize, orientation, constraint ); + else + maximum = preferred; + + if ( policy & QskSizePolicy::IgnoreFlag ) + preferred = minimum; + } + + return QskLayoutHint( minimum, preferred, maximum ); +} diff --git a/src/layouts/QskLayoutConstraint.h b/src/layouts/QskLayoutConstraint.h index 657c31a0..734e0ef0 100644 --- a/src/layouts/QskLayoutConstraint.h +++ b/src/layouts/QskLayoutConstraint.h @@ -13,6 +13,7 @@ class QskSizePolicy; class QskControl; +class QskLayoutHint; class QQuickItem; class QSizeF; class QRectF; @@ -33,17 +34,18 @@ namespace QskLayoutConstraint QSK_EXPORT qreal widthForHeight( const QQuickItem*, qreal height ); QSK_EXPORT Type constraintType( const QQuickItem* ); + QSK_EXPORT bool isConstrained( const QQuickItem*, Qt::Orientation ); QSK_EXPORT qreal constrainedMetric( Type, const QskControl*, qreal value, std::function< qreal( Type, const QskControl*, qreal ) > ); - QSK_EXPORT qreal constrainedChildrenMetric( Type, const QskControl*, qreal width ); + QSK_EXPORT qreal constrainedChildrenMetric( + Type, const QskControl*, qreal constraint ); QSK_EXPORT QSizeF effectiveConstraint( const QQuickItem*, Qt::SizeHint ); QSK_EXPORT QskSizePolicy sizePolicy( const QQuickItem* ); - // bounded by Qt::MinimumSize/Qt::MaximumSize QSK_EXPORT QSizeF boundedSize( const QQuickItem*, const QSizeF& ); QSK_EXPORT QSizeF adjustedSize( const QQuickItem*, const QSizeF& ); @@ -56,7 +58,9 @@ namespace QskLayoutConstraint QSK_EXPORT QRectF itemRect( const QQuickItem*, const QRectF&, Qt::Alignment ); - // QGridLayoutEngine internally uses FLT_MAX + QSK_EXPORT QskLayoutHint layoutHint( + const QQuickItem*, Qt::Orientation, qreal constraint ); + const qreal unlimited = std::numeric_limits< float >::max(); } diff --git a/src/layouts/QskLinearLayoutEngine.cpp b/src/layouts/QskLinearLayoutEngine.cpp index 12e22eea..b0f6e12a 100644 --- a/src/layouts/QskLinearLayoutEngine.cpp +++ b/src/layouts/QskLinearLayoutEngine.cpp @@ -53,7 +53,6 @@ namespace EntryData& operator=( const EntryData& ); bool isIgnored() const; - bool isConstrained( Qt::Orientation ) const; qreal spacer() const { return m_isSpacer ? m_spacer : -1.0; } QQuickItem* item() const { return m_isSpacer ? nullptr : m_item; } @@ -200,24 +199,6 @@ bool EntryData::isIgnored() const return false; } -bool EntryData::isConstrained( Qt::Orientation orientation ) const -{ - if ( m_isSpacer ) - return false; - - switch( QskLayoutConstraint::constraintType( m_item ) ) - { - case QskLayoutConstraint::WidthForHeight: - return orientation == Qt::Horizontal; - - case QskLayoutConstraint::HeightForWidth: - return orientation == Qt::Vertical; - - default: - return false; - } -} - EntryTable::EntryTable( Qt::Orientation orientation, uint dimension ) : m_dimension( dimension ) , m_sumIgnored( -1 ) @@ -496,95 +477,39 @@ QskLayoutConstraint::Type EntryTable::constraintType() const QskLayoutChain::Cell EntryTable::cell( const EntryData& entry, Qt::Orientation orientation, qreal constraint ) const { - int stretch = 0; - bool canGrow = true; - qreal minimum, preferred, maximum; + QskLayoutChain::Cell cell; + cell.canGrow = true; if ( const auto item = entry.item() ) { + cell.hint = QskLayoutConstraint::layoutHint( item, orientation, constraint ); + const auto policy = QskLayoutConstraint::sizePolicy( item ).policy( orientation ); - if ( constraint >= 0.0 ) - { - if ( !entry.isConstrained( orientation ) ) - constraint = -1.0; - } - - const auto expandFlags = QskSizePolicy::GrowFlag | QskSizePolicy::ExpandFlag; - - if ( ( policy & QskSizePolicy::ShrinkFlag ) && - ( policy & expandFlags ) && ( policy & QskSizePolicy::IgnoreFlag ) ) - { - // we don't need to calculate the preferred size - - minimum = QskLayoutConstraint::sizeHint( - item, Qt::MinimumSize, orientation, constraint ); - - maximum = QskLayoutConstraint::sizeHint( - item, Qt::MaximumSize, orientation, constraint ); - - preferred = minimum; - } - else - { - preferred = QskLayoutConstraint::sizeHint( - item, Qt::PreferredSize, orientation, constraint ); - - minimum = maximum = preferred; - - if ( policy & QskSizePolicy::ShrinkFlag ) - { - minimum = QskLayoutConstraint::sizeHint( - item, Qt::MinimumSize, orientation, constraint ); - } - - if ( policy & expandFlags ) - { - maximum = QskLayoutConstraint::sizeHint( - item, Qt::MaximumSize, orientation, constraint ); - } - - if ( policy & QskSizePolicy::IgnoreFlag ) - preferred = minimum; - } - if ( orientation == m_orientation ) { if ( entry.stretch() < 0 ) - stretch = ( policy & QskSizePolicy::ExpandFlag ) ? 1 : 0; + cell.stretch = ( policy & QskSizePolicy::ExpandFlag ) ? 1 : 0; else - stretch = entry.stretch(); + cell.stretch = entry.stretch(); } - canGrow = policy & QskSizePolicy::GrowFlag; + cell.canGrow = policy & QskSizePolicy::GrowFlag; } else { - // a spacer - if ( orientation == m_orientation ) { - minimum = preferred = maximum = entry.spacer(); + cell.hint.setMinimum( entry.spacer() ); + cell.hint.setPreferred( entry.spacer() ); - // >= 0 ??? - if ( entry.stretch() > 0 ) - maximum = QskLayoutConstraint::unlimited; + if ( entry.stretch() <= 0 ) + cell.hint.setMaximum( entry.spacer() ); - stretch = qMax( entry.stretch(), 0 ); - } - else - { - minimum = 0.0; - preferred = 0.0; - maximum = QskLayoutConstraint::unlimited; + cell.stretch = qMax( entry.stretch(), 0 ); } } - QskLayoutChain::Cell cell; - cell.hint = QskLayoutHint( minimum, preferred, maximum ); - cell.stretch = stretch; - cell.canGrow = canGrow; - return cell; }