QskScrollArea respecting dynamic constraints

This commit is contained in:
Uwe 2018-11-17 09:22:11 +01:00
parent 4c5e656283
commit f3d6cdd669
7 changed files with 129 additions and 71 deletions

View File

@ -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 );

View File

@ -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 )

View File

@ -16,48 +16,6 @@ QSK_QT_PRIVATE_BEGIN
#include <private/qquickwindow_p.h>
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 );
}

View File

@ -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"

View File

@ -54,6 +54,7 @@ QRectF QskScrollViewSkinlet::subControlRect(
if ( subControl == QskScrollView::Panel )
{
// layoutRect ???
return scrollView->contentsRect();
}

View File

@ -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 );
}

View File

@ -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();
}