implementation of dynamic constraints reorganized
This commit is contained in:
parent
8dc73dfdac
commit
dd39017dbe
@ -16,9 +16,9 @@ QskBox::~QskBox()
|
||||
{
|
||||
}
|
||||
|
||||
QRectF QskBox::layoutRect() const
|
||||
QRectF QskBox::layoutRectForSize( const QSizeF& size ) const
|
||||
{
|
||||
return innerBox( Panel, subControlRect( Panel ) );
|
||||
return innerBox( Panel, subControlRect( size, Panel ) );
|
||||
}
|
||||
|
||||
QSizeF QskBox::contentsSizeHint() const
|
||||
|
@ -20,7 +20,7 @@ class QSK_EXPORT QskBox : public QskControl
|
||||
QskBox( QQuickItem* parent = nullptr );
|
||||
~QskBox() override;
|
||||
|
||||
QRectF layoutRect() const override;
|
||||
QRectF layoutRectForSize( const QSizeF& ) const override;
|
||||
QSizeF contentsSizeHint() const override;
|
||||
};
|
||||
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "QskSkin.h"
|
||||
#include "QskSkinlet.h"
|
||||
#include "QskSkinHintTable.h"
|
||||
#include "QskLayoutConstraint.h"
|
||||
|
||||
#include <qglobalstatic.h>
|
||||
#include <qlocale.h>
|
||||
@ -1013,6 +1014,15 @@ QRectF QskControl::subControlRect( QskAspect::Subcontrol subControl ) const
|
||||
return effectiveSkinlet()->subControlRect( this, contentsRect(), subControl );
|
||||
}
|
||||
|
||||
QRectF QskControl::subControlRect(
|
||||
const QSizeF& size, QskAspect::Subcontrol subControl ) const
|
||||
{
|
||||
QRectF rect( 0.0, 0.0, size.width(), size.height() );
|
||||
rect = qskValidOrEmptyInnerRect( rect, margins() );
|
||||
|
||||
return effectiveSkinlet()->subControlRect( this, rect, subControl );
|
||||
}
|
||||
|
||||
bool QskControl::layoutMirroring() const
|
||||
{
|
||||
return d_func()->effectiveLayoutMirror;
|
||||
@ -1379,58 +1389,24 @@ void QskControl::resetImplicitSize()
|
||||
|
||||
qreal QskControl::heightForWidth( qreal width ) const
|
||||
{
|
||||
qreal h = -1;
|
||||
if ( !d_func()->autoLayoutChildren )
|
||||
return -1.0;
|
||||
|
||||
if ( d_func()->autoLayoutChildren )
|
||||
{
|
||||
const auto innerSize = layoutRect().size();
|
||||
const auto outerSize = size();
|
||||
using namespace QskLayoutConstraint;
|
||||
|
||||
width -= outerSize.width() - innerSize.width();
|
||||
|
||||
const auto children = childItems();
|
||||
for ( auto child : children )
|
||||
{
|
||||
if ( auto control = qobject_cast< const QskControl* >( child ) )
|
||||
{
|
||||
if ( !control->isTransparentForPositioner() )
|
||||
h = qMax( h, control->heightForWidth( width ) );
|
||||
}
|
||||
}
|
||||
|
||||
if ( h >= 0 )
|
||||
h += outerSize.height() - innerSize.height();
|
||||
}
|
||||
|
||||
return h;
|
||||
return constrainedMetric(
|
||||
HeightForWidth, this, width, constrainedChildrenMetric );
|
||||
}
|
||||
|
||||
qreal QskControl::widthForHeight( qreal height ) const
|
||||
{
|
||||
qreal w = -1;
|
||||
if ( !d_func()->autoLayoutChildren )
|
||||
return -1.0;
|
||||
|
||||
if ( d_func()->autoLayoutChildren )
|
||||
{
|
||||
const auto innerSize = layoutRect().size();
|
||||
const auto outerSize = size();
|
||||
using namespace QskLayoutConstraint;
|
||||
|
||||
height -= outerSize.height() - innerSize.height();
|
||||
|
||||
const auto children = childItems();
|
||||
for ( auto child : children )
|
||||
{
|
||||
if ( auto control = qobject_cast< const QskControl* >( child ) )
|
||||
{
|
||||
if ( !control->isTransparentForPositioner() )
|
||||
w = qMax( w, control->widthForHeight( height ) );
|
||||
}
|
||||
}
|
||||
|
||||
if ( w >= 0 )
|
||||
w += outerSize.width() - innerSize.width();
|
||||
}
|
||||
|
||||
return w;
|
||||
return constrainedMetric(
|
||||
WidthForHeight, this, height, constrainedChildrenMetric );
|
||||
}
|
||||
|
||||
bool QskControl::event( QEvent* event )
|
||||
@ -1932,9 +1908,10 @@ QskControl* QskControl::owningControl() const
|
||||
return const_cast< QskControl* >( this );
|
||||
}
|
||||
|
||||
QRectF QskControl::layoutRect() const
|
||||
QRectF QskControl::layoutRectForSize( const QSizeF& size ) const
|
||||
{
|
||||
return contentsRect();
|
||||
const QRectF r( 0.0, 0.0, size.width(), size.height() );
|
||||
return qskValidOrEmptyInnerRect( r, margins() );
|
||||
}
|
||||
|
||||
QRectF QskControl::gestureRect() const
|
||||
|
@ -110,12 +110,14 @@ class QSK_EXPORT QskControl : public QQuickItem, public QskSkinnable
|
||||
|
||||
QRectF rect() const;
|
||||
QRectF contentsRect() const;
|
||||
QRectF layoutRect() const;
|
||||
|
||||
virtual QRectF layoutRect() const;
|
||||
virtual QRectF layoutRectForSize( const QSizeF& ) const;
|
||||
virtual QRectF gestureRect() const;
|
||||
virtual QRectF focusIndicatorRect() const;
|
||||
|
||||
QRectF subControlRect( QskAspect::Subcontrol ) const;
|
||||
QRectF subControlRect( const QSizeF&, QskAspect::Subcontrol ) const;
|
||||
|
||||
void setAutoFillBackground( bool );
|
||||
bool autoFillBackground() const;
|
||||
@ -313,6 +315,11 @@ inline QSizeF QskControl::preferredSize() const
|
||||
return explicitSizeHint( Qt::PreferredSize );
|
||||
}
|
||||
|
||||
inline QRectF QskControl::layoutRect() const
|
||||
{
|
||||
return layoutRectForSize( size() );
|
||||
}
|
||||
|
||||
inline QskControl* qskControlCast( QObject* object )
|
||||
{
|
||||
return qobject_cast< QskControl* >( object );
|
||||
|
@ -245,9 +245,9 @@ void QskPushButton::updateLayout()
|
||||
}
|
||||
}
|
||||
|
||||
QRectF QskPushButton::layoutRect() const
|
||||
QRectF QskPushButton::layoutRectForSize( const QSizeF& size ) const
|
||||
{
|
||||
return innerBox( Panel, subControlRect( Panel ) );
|
||||
return innerBox( Panel, subControlRect( size, Panel ) );
|
||||
}
|
||||
|
||||
QSizeF QskPushButton::contentsSizeHint() const
|
||||
|
@ -65,7 +65,7 @@ class QSK_EXPORT QskPushButton : public QskAbstractButton
|
||||
QFont font() const;
|
||||
|
||||
QSizeF contentsSizeHint() const override;
|
||||
QRectF layoutRect() const override;
|
||||
QRectF layoutRectForSize( const QSizeF& ) const override;
|
||||
|
||||
public Q_SLOTS:
|
||||
void setText( const QString& );
|
||||
|
@ -231,11 +231,11 @@ void QskSubWindow::updateLayout()
|
||||
Inherited::updateLayout();
|
||||
}
|
||||
|
||||
QRectF QskSubWindow::layoutRect() const
|
||||
QRectF QskSubWindow::layoutRectForSize( const QSizeF& size ) const
|
||||
{
|
||||
QRectF rect = contentsRect();
|
||||
|
||||
const qreal top = rect.top() + subControlRect( TitleBar ).height();
|
||||
const qreal top = rect.top() + subControlRect( size, TitleBar ).height();
|
||||
rect.setTop( top );
|
||||
|
||||
return innerBox( Panel, rect );
|
||||
|
@ -79,7 +79,7 @@ class QSK_EXPORT QskSubWindow : public QskPopup
|
||||
QRectF titleBarRect() const;
|
||||
|
||||
QSizeF contentsSizeHint() const override;
|
||||
QRectF layoutRect() const override;
|
||||
QRectF layoutRectForSize( const QSizeF& ) const override;
|
||||
|
||||
Q_SIGNALS:
|
||||
void decoratedChanged();
|
||||
|
@ -101,9 +101,9 @@ QSizeF QskTabButton::contentsSizeHint() const
|
||||
return size;
|
||||
}
|
||||
|
||||
QRectF QskTabButton::layoutRect() const
|
||||
QRectF QskTabButton::layoutRectForSize( const QSizeF& size ) const
|
||||
{
|
||||
return innerBox( Panel, subControlRect( Panel ) );
|
||||
return innerBox( Panel, subControlRect( size, Panel ) );
|
||||
}
|
||||
|
||||
QskAspect::Placement QskTabButton::effectivePlacement() const
|
||||
|
@ -37,7 +37,7 @@ class QSK_EXPORT QskTabButton : public QskAbstractButton
|
||||
QskTextOptions textOptions() const;
|
||||
|
||||
QSizeF contentsSizeHint() const override;
|
||||
QRectF layoutRect() const override;
|
||||
QRectF layoutRectForSize( const QSizeF& ) const override;
|
||||
|
||||
QskAspect::Placement effectivePlacement() const override;
|
||||
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include "QskEvent.h"
|
||||
#include "QskLayoutEngine.h"
|
||||
#include "QskLayoutItem.h"
|
||||
#include "QskLayoutConstraint.h"
|
||||
|
||||
class QskLayoutBox::PrivateData
|
||||
{
|
||||
@ -266,24 +267,26 @@ QSizeF QskLayoutBox::layoutItemsSizeHint() const
|
||||
|
||||
qreal QskLayoutBox::heightForWidth( qreal width ) const
|
||||
{
|
||||
const auto m = margins();
|
||||
width -= m.left() + m.right();
|
||||
auto constrainedHeight =
|
||||
[this]( QskLayoutConstraint::Type, const QskControl*, qreal width )
|
||||
{
|
||||
return engine().heightForWidth( width );
|
||||
};
|
||||
|
||||
qreal height = engine().heightForWidth( width );
|
||||
|
||||
height += m.top() + m.bottom();
|
||||
return height;
|
||||
return QskLayoutConstraint::constrainedMetric(
|
||||
QskLayoutConstraint::HeightForWidth, this, width, constrainedHeight );
|
||||
}
|
||||
|
||||
qreal QskLayoutBox::widthForHeight( qreal height ) const
|
||||
{
|
||||
const auto m = margins();
|
||||
height -= m.top() + m.bottom();
|
||||
auto constrainedWidth =
|
||||
[this]( QskLayoutConstraint::Type, const QskControl*, qreal height )
|
||||
{
|
||||
return engine().widthForHeight( height );
|
||||
};
|
||||
|
||||
qreal width = engine().widthForHeight( height );
|
||||
|
||||
width += m.left() + m.right();
|
||||
return width;
|
||||
return QskLayoutConstraint::constrainedMetric(
|
||||
QskLayoutConstraint::WidthForHeight, this, height, constrainedWidth );
|
||||
}
|
||||
|
||||
void QskLayoutBox::geometryChangeEvent( QskGeometryChangeEvent* event )
|
||||
|
@ -7,6 +7,8 @@
|
||||
#include "QskControl.h"
|
||||
#include "QskSizePolicy.h"
|
||||
|
||||
#include <functional>
|
||||
|
||||
static inline qreal qskHintFor(
|
||||
const QQuickItem* item, const char* method, qreal widthOrHeight )
|
||||
{
|
||||
@ -85,6 +87,71 @@ qreal QskLayoutConstraint::widthForHeight( const QQuickItem* item, qreal height
|
||||
return qskHintFor( item, "widthForHeight", height );
|
||||
}
|
||||
|
||||
qreal QskLayoutConstraint::constrainedMetric(
|
||||
Type type, const QskControl* control, qreal widthOrHeight,
|
||||
std::function< qreal( Type, const QskControl*, qreal ) > constrainFunction )
|
||||
{
|
||||
#if 1
|
||||
/*
|
||||
In case of having a corner radius of Qt::RelativeSize the margins
|
||||
we might have a wrong result when using QskLayoutConstraint::unlimited.
|
||||
No idea how to solve this in a generic way: TODO ...
|
||||
*/
|
||||
#endif
|
||||
|
||||
const qreal upperLimit = 10e6;
|
||||
|
||||
if ( type == WidthForHeight )
|
||||
{
|
||||
const QSizeF outer( upperLimit, widthOrHeight );
|
||||
const QSizeF inner = control->layoutRectForSize( outer ).size();
|
||||
|
||||
qreal width = constrainFunction( type, control, inner.height() );
|
||||
|
||||
if ( width >= 0.0 )
|
||||
width += outer.width() - inner.width();
|
||||
|
||||
return width;
|
||||
}
|
||||
else
|
||||
{
|
||||
const QSizeF outer( widthOrHeight, upperLimit );
|
||||
const QSizeF inner = control->layoutRectForSize( outer ).size();
|
||||
|
||||
qreal height = constrainFunction( type, control, inner.width() );
|
||||
|
||||
if ( height >= 0.0 )
|
||||
height += outer.height() - inner.height();
|
||||
|
||||
return height;
|
||||
}
|
||||
}
|
||||
|
||||
qreal QskLayoutConstraint::constrainedChildrenMetric(
|
||||
Type type, const QskControl* control, qreal widthOrHeight )
|
||||
{
|
||||
auto constrainFunction =
|
||||
( type == WidthForHeight ) ? widthForHeight : heightForWidth;
|
||||
|
||||
qreal constrainedValue = -1.0;
|
||||
|
||||
const auto children = control->childItems();
|
||||
for ( auto child : children )
|
||||
{
|
||||
if ( auto control = qskControlCast( child ) )
|
||||
{
|
||||
if ( !control->isTransparentForPositioner() )
|
||||
{
|
||||
const auto v = constrainFunction( control, widthOrHeight );
|
||||
if ( v > constrainedValue )
|
||||
constrainedValue = v;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return constrainedValue;
|
||||
}
|
||||
|
||||
QSizeF QskLayoutConstraint::effectiveConstraint(
|
||||
const QQuickItem* item, Qt::SizeHint whichHint )
|
||||
{
|
||||
|
@ -12,15 +12,30 @@
|
||||
#include <limits>
|
||||
|
||||
class QskSizePolicy;
|
||||
class QskControl;
|
||||
class QQuickItem;
|
||||
class QSizeF;
|
||||
|
||||
namespace std { template< typename T > class function; }
|
||||
|
||||
namespace QskLayoutConstraint
|
||||
{
|
||||
enum Type
|
||||
{
|
||||
WidthForHeight,
|
||||
HeightForWidth
|
||||
};
|
||||
|
||||
QSK_EXPORT bool hasDynamicConstraint( const QQuickItem* );
|
||||
QSK_EXPORT qreal heightForWidth( const QQuickItem*, qreal width );
|
||||
QSK_EXPORT qreal widthForHeight( const QQuickItem*, qreal height );
|
||||
|
||||
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 QSizeF effectiveConstraint( const QQuickItem*, Qt::SizeHint );
|
||||
QSK_EXPORT QskSizePolicy sizePolicy( const QQuickItem* );
|
||||
|
||||
|
@ -11,6 +11,30 @@
|
||||
|
||||
#include <qpointer.h>
|
||||
|
||||
static qreal qskConstrainedValue( QskLayoutConstraint::Type type,
|
||||
const QskControl* control, qreal widthOrHeight )
|
||||
{
|
||||
using namespace QskLayoutConstraint;
|
||||
|
||||
auto constrainFunction =
|
||||
( type == WidthForHeight ) ? widthForHeight : heightForWidth;
|
||||
|
||||
qreal constrainedValue = -1;
|
||||
auto stackBox = static_cast< const QskStackBox* >( control );
|
||||
|
||||
for ( int i = 0; i < stackBox->itemCount(); i++ )
|
||||
{
|
||||
if ( const auto item = stackBox->itemAtIndex( i ) )
|
||||
{
|
||||
const qreal v = constrainFunction( item, widthOrHeight );
|
||||
if ( v > constrainedValue )
|
||||
constrainedValue = v;
|
||||
}
|
||||
}
|
||||
|
||||
return constrainedValue;
|
||||
}
|
||||
|
||||
class QskStackBox::PrivateData
|
||||
{
|
||||
public:
|
||||
@ -252,40 +276,14 @@ QSizeF QskStackBox::layoutItemsSizeHint() const
|
||||
|
||||
qreal QskStackBox::heightForWidth( qreal width ) const
|
||||
{
|
||||
const auto m = margins();
|
||||
width -= m.left() + m.right();
|
||||
|
||||
qreal height = -1;
|
||||
|
||||
const QskLayoutEngine& engine = this->engine();
|
||||
for ( int i = 0; i < engine.itemCount(); i++ )
|
||||
{
|
||||
const QskLayoutItem* layoutItem = engine.layoutItemAt( i );
|
||||
if ( const auto item = layoutItem->item() )
|
||||
height = qMax( height, QskLayoutConstraint::heightForWidth( item, width ) );
|
||||
}
|
||||
|
||||
height += m.top() + m.bottom();
|
||||
return height;
|
||||
return QskLayoutConstraint::constrainedMetric(
|
||||
QskLayoutConstraint::HeightForWidth, this, width, qskConstrainedValue );
|
||||
}
|
||||
|
||||
qreal QskStackBox::widthForHeight( qreal height ) const
|
||||
{
|
||||
const auto m = margins();
|
||||
height -= m.top() + m.bottom();
|
||||
|
||||
qreal width = -1;
|
||||
|
||||
const QskLayoutEngine& engine = this->engine();
|
||||
for ( int i = 0; i < engine.itemCount(); i++ )
|
||||
{
|
||||
const QskLayoutItem* layoutItem = engine.layoutItemAt( i );
|
||||
if ( const auto item = layoutItem->item() )
|
||||
width = qMax( width, QskLayoutConstraint::widthForHeight( item, height ) );
|
||||
}
|
||||
|
||||
width += m.left() + m.right();
|
||||
return width;
|
||||
return QskLayoutConstraint::constrainedMetric(
|
||||
QskLayoutConstraint::WidthForHeight, this, height, qskConstrainedValue );
|
||||
}
|
||||
|
||||
void QskStackBox::layoutItemInserted( QskLayoutItem* layoutItem, int index )
|
||||
|
Loading…
x
Reference in New Issue
Block a user