diff --git a/examples/thumbnails/main.cpp b/examples/thumbnails/main.cpp index 8245314b..fc7f2be3 100644 --- a/examples/thumbnails/main.cpp +++ b/examples/thumbnails/main.cpp @@ -164,9 +164,15 @@ int main( int argc, char* argv[] ) new QskPushButton( "Push Me", buttonBox ); new QskPushButton( "Push Me", buttonBox ); + auto iconGrid = new IconGrid(); + + // don't allow to shrink the iconGrid + iconGrid->setSizePolicy( QskSizePolicy::MinimumExpanding, + QskSizePolicy::MinimumExpanding ); + auto scrollArea = new ScrollArea( box ); scrollArea->setMargins( QMarginsF( 25, 25, 5, 5 ) ); - scrollArea->setScrolledItem( new IconGrid() ); + scrollArea->setScrolledItem( iconGrid ); auto focusIndicator = new QskFocusIndicator(); focusIndicator->setBoxBorderColorsHint( QskFocusIndicator::Panel, Qt::darkRed ); diff --git a/src/common/QskSizePolicy.h b/src/common/QskSizePolicy.h index 9f5c8028..6ca85081 100644 --- a/src/common/QskSizePolicy.h +++ b/src/common/QskSizePolicy.h @@ -24,10 +24,12 @@ class QSK_EXPORT QskSizePolicy public: enum Flag { - GrowFlag = 1, - ExpandFlag = 2, - ShrinkFlag = 4, - IgnoreFlag = 8 + GrowFlag = 1 << 0, + ExpandFlag = 1 << 1, + ShrinkFlag = 1 << 2, + IgnoreFlag = 1 << 3, + + ConstrainedFlag = IgnoreFlag }; enum Policy @@ -39,7 +41,7 @@ class QSK_EXPORT QskSizePolicy MinimumExpanding = GrowFlag | ExpandFlag, Expanding = GrowFlag | ShrinkFlag | ExpandFlag, Ignored = ShrinkFlag | GrowFlag | IgnoreFlag, - Constrained = IgnoreFlag + Constrained = ConstrainedFlag }; Q_ENUM( Flag ) diff --git a/src/controls/QskScrollArea.cpp b/src/controls/QskScrollArea.cpp index 8b4be243..a4c8dc3e 100644 --- a/src/controls/QskScrollArea.cpp +++ b/src/controls/QskScrollArea.cpp @@ -16,48 +16,6 @@ QSK_QT_PRIVATE_BEGIN #include QSK_QT_PRIVATE_END -static QSizeF qskAdjustedSize( const QQuickItem* item, const QSizeF& targetSize ) -{ - using namespace QskLayoutConstraint; - - QSizeF sz = effectiveConstraint( item, Qt::PreferredSize ); - - qreal w = sz.width(); - qreal h = sz.height(); - - if ( targetSize != sz ) - { - const QSizeF minSize = effectiveConstraint( item, Qt::MinimumSize ); - const QSizeF maxSize = effectiveConstraint( item, Qt::MaximumSize ); - - const auto policy = sizePolicy( item ); - - if ( targetSize.width() > w ) - { - if ( policy.horizontalPolicy() & QskSizePolicy::GrowFlag ) - w = qMin( maxSize.width(), targetSize.width() ); - } - else if ( targetSize.width() < w ) - { - if ( policy.horizontalPolicy() & QskSizePolicy::ShrinkFlag ) - w = qMax( minSize.width(), w ); - } - - if ( targetSize.height() > h ) - { - if ( policy.verticalPolicy() & QskSizePolicy::GrowFlag ) - h = qMin( maxSize.height(), targetSize.height() ); - } - else if ( targetSize.height() < h ) - { - if ( policy.verticalPolicy() & QskSizePolicy::ShrinkFlag ) - h = qMax( minSize.height(), h ); - } - } - - return QSizeF( w, h ); -} - namespace { class ViewportClipNode final : public QQuickDefaultClipNode @@ -485,7 +443,7 @@ void QskScrollArea::adjustItem() moment we ignore this and start with a simplified code. */ #endif - auto newSize = qskAdjustedSize( item, rect.size() ); + const auto newSize = QskLayoutConstraint::adjustedSize( item, rect.size() ); item->setSize( newSize ); } diff --git a/src/controls/QskScrollView.cpp b/src/controls/QskScrollView.cpp index 9b63f7d5..f1faed04 100644 --- a/src/controls/QskScrollView.cpp +++ b/src/controls/QskScrollView.cpp @@ -628,50 +628,54 @@ QPointF QskScrollView::boundedScrollPos( const QPointF& pos ) const Qt::Orientations QskScrollView::scrollableOrientations() const { + // layoutRect ??? const QRectF vr = contentsRect(); - Qt::ScrollBarPolicy policyV = m_data->verticalScrollBarPolicy; - Qt::ScrollBarPolicy policyH = m_data->horizontalScrollBarPolicy; + auto policyVertical = m_data->verticalScrollBarPolicy; + auto policyHorizontal = m_data->horizontalScrollBarPolicy; - if ( policyV == Qt::ScrollBarAsNeeded ) + if ( policyVertical == Qt::ScrollBarAsNeeded ) { - qreal h = vr.height(); - if ( policyH == Qt::ScrollBarAlwaysOn ) - h -= metric( HorizontalScrollBar | QskAspect::Size ); + qreal height = vr.height(); - if ( m_data->scrollableSize.height() > h ) - policyV = Qt::ScrollBarAlwaysOn; + if ( policyHorizontal == Qt::ScrollBarAlwaysOn ) + height -= metric( HorizontalScrollBar | QskAspect::Size ); + + if ( m_data->scrollableSize.height() > height ) + policyVertical = Qt::ScrollBarAlwaysOn; } - if ( policyH == Qt::ScrollBarAsNeeded ) + if ( policyHorizontal == Qt::ScrollBarAsNeeded ) { - qreal w = vr.width(); - if ( policyV == Qt::ScrollBarAlwaysOn ) - w -= metric( VerticalScrollBar | QskAspect::Size ); + qreal width = vr.width(); - if ( m_data->scrollableSize.width() > w ) + if ( policyVertical == Qt::ScrollBarAlwaysOn ) + width -= metric( VerticalScrollBar | QskAspect::Size ); + + if ( m_data->scrollableSize.width() > width ) { - policyH = Qt::ScrollBarAlwaysOn; + policyHorizontal = Qt::ScrollBarAlwaysOn; // we have to check the vertical once more - if ( ( policyV == Qt::ScrollBarAsNeeded ) && + if ( ( policyVertical == Qt::ScrollBarAsNeeded ) && ( m_data->scrollableSize.height() > vr.height() - metric( HorizontalScrollBar | QskAspect::Size ) ) ) { - policyV = Qt::ScrollBarAlwaysOn; + policyVertical = Qt::ScrollBarAlwaysOn; } } } - Qt::Orientations o; - if ( policyH == Qt::ScrollBarAlwaysOn ) - o |= Qt::Horizontal; + Qt::Orientations orientations; - if ( policyV == Qt::ScrollBarAlwaysOn ) - o |= Qt::Vertical; + if ( policyHorizontal == Qt::ScrollBarAlwaysOn ) + orientations |= Qt::Horizontal; - return o; + if ( policyVertical == Qt::ScrollBarAlwaysOn ) + orientations |= Qt::Vertical; + + return orientations; } #include "moc_QskScrollView.cpp" diff --git a/src/controls/QskScrollViewSkinlet.cpp b/src/controls/QskScrollViewSkinlet.cpp index 14189aea..4c54716b 100644 --- a/src/controls/QskScrollViewSkinlet.cpp +++ b/src/controls/QskScrollViewSkinlet.cpp @@ -54,6 +54,7 @@ QRectF QskScrollViewSkinlet::subControlRect( if ( subControl == QskScrollView::Panel ) { + // layoutRect ??? return scrollView->contentsRect(); } diff --git a/src/layouts/QskLayoutConstraint.cpp b/src/layouts/QskLayoutConstraint.cpp index 00976131..3ea523f1 100644 --- a/src/layouts/QskLayoutConstraint.cpp +++ b/src/layouts/QskLayoutConstraint.cpp @@ -39,6 +39,23 @@ static inline bool qskHasHintFor( const QQuickItem* item, const char* method ) return false; } +static inline qreal qskAdjustedValue( QskSizePolicy::Policy policy, qreal value, qreal targetValue ) +{ + if ( targetValue > value ) + { + if ( policy & QskSizePolicy::GrowFlag ) + return targetValue; + } + else if ( targetValue < value ) + { + if ( policy & QskSizePolicy::ShrinkFlag ) + return targetValue; + } + + return value; +} + + bool QskLayoutConstraint::hasDynamicConstraint( const QQuickItem* item ) { if ( const QskControl* control = qobject_cast< const QskControl* >( item ) ) @@ -141,3 +158,68 @@ QskSizePolicy QskLayoutConstraint::sizePolicy( const QQuickItem* item ) return QskSizePolicy( QskSizePolicy::Preferred, QskSizePolicy::Preferred ); } + +QSizeF QskLayoutConstraint::boundedSize( const QQuickItem* item, const QSizeF& size ) +{ + const auto minSize = effectiveConstraint( item, Qt::MinimumSize ); + const auto maxSize = effectiveConstraint( item, Qt::MaximumSize ); + + qreal width = size.width(); + qreal height = size.height(); + + if ( ( minSize.width() >= 0 ) && ( minSize.width() > width ) ) + width = minSize.width(); + + if ( ( minSize.height() >= 0 ) && ( minSize.height() > height ) ) + height = minSize.height(); + + if ( ( maxSize.width() >= 0 ) && ( maxSize.width() < width ) ) + width = maxSize.width(); + + if ( ( maxSize.height() >= 0 ) && ( maxSize.height() < height ) ) + height = maxSize.height(); + + return QSizeF( width, height ); +} + +QSizeF QskLayoutConstraint::adjustedSize( const QQuickItem* item, const QSizeF& targetSize ) +{ + const auto policy = sizePolicy( item ); + + const auto boundedSize = QskLayoutConstraint::boundedSize( item, targetSize ); + const auto preferredSize = effectiveConstraint( item, Qt::PreferredSize ); + + qreal w; + qreal h; + + if ( policy.horizontalPolicy() == QskSizePolicy::Constrained ) + { + h = qskAdjustedValue( policy.verticalPolicy(), + preferredSize.height(), boundedSize.height() ); + + w = widthForHeight( item, h ); + + if ( w < boundedSize.height() ) + w = boundedSize.height(); + } + else if ( policy.verticalPolicy() == QskSizePolicy::Constrained ) + { + w = qskAdjustedValue( policy.horizontalPolicy(), + preferredSize.width(), boundedSize.width() ); + + h = heightForWidth( item, w ); + + if ( h < boundedSize.height() ) + h = boundedSize.height(); + } + else + { + w = qskAdjustedValue( policy.horizontalPolicy(), + preferredSize.width(), boundedSize.width() ); + + h = qskAdjustedValue( policy.verticalPolicy(), + preferredSize.height(), boundedSize.height() ); + } + + return QSizeF( w, h ); +} diff --git a/src/layouts/QskLayoutConstraint.h b/src/layouts/QskLayoutConstraint.h index c2d5d0d6..244666fa 100644 --- a/src/layouts/QskLayoutConstraint.h +++ b/src/layouts/QskLayoutConstraint.h @@ -24,6 +24,11 @@ namespace QskLayoutConstraint 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& ); + // QGridLayoutEngine internally uses FLT_MAX const qreal unlimited = std::numeric_limits< float >::max(); }