ongoing work on QskDrawer
This commit is contained in:
parent
eff3641c4c
commit
7294d5a01e
|
@ -230,6 +230,7 @@ namespace
|
||||||
|
|
||||||
{
|
{
|
||||||
auto drawer = new Drawer( parentItem() );
|
auto drawer = new Drawer( parentItem() );
|
||||||
|
drawer->setSizePolicy( Qt::Horizontal, QskSizePolicy::Fixed );
|
||||||
drawer->setEdge( Qt::RightEdge );
|
drawer->setEdge( Qt::RightEdge );
|
||||||
|
|
||||||
auto burger = new QskPushButton( "≡", this );
|
auto burger = new QskPushButton( "≡", this );
|
||||||
|
|
|
@ -7,15 +7,104 @@
|
||||||
#include <QskAnimationHint.h>
|
#include <QskAnimationHint.h>
|
||||||
#include <QskQuick.h>
|
#include <QskQuick.h>
|
||||||
|
|
||||||
|
QSK_QT_PRIVATE_BEGIN
|
||||||
|
#include <private/qquickitem_p.h>
|
||||||
|
#include <private/qquickitemchangelistener_p.h>
|
||||||
|
QSK_QT_PRIVATE_END
|
||||||
|
|
||||||
QSK_SUBCONTROL( QskDrawer, Panel )
|
QSK_SUBCONTROL( QskDrawer, Panel )
|
||||||
QSK_SUBCONTROL( QskDrawer, Overlay )
|
QSK_SUBCONTROL( QskDrawer, Overlay )
|
||||||
|
|
||||||
|
static QRectF qskDrawerRect( const QRectF& rect,
|
||||||
|
Qt::Edge edge, qreal pos, const QSizeF& size )
|
||||||
|
{
|
||||||
|
QRectF r( 0.0, 0.0, size.width(), size.height() );
|
||||||
|
|
||||||
|
const auto progress = pos = 1.0 - pos;
|
||||||
|
|
||||||
|
switch( edge )
|
||||||
|
{
|
||||||
|
case Qt::LeftEdge:
|
||||||
|
{
|
||||||
|
r.moveRight( rect.left() + progress * size.width() );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Qt::RightEdge:
|
||||||
|
{
|
||||||
|
r.moveLeft( rect.right() - progress * size.width() );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Qt::TopEdge:
|
||||||
|
{
|
||||||
|
r.moveBottom( rect.top() + progress * size.height() );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Qt::BottomEdge:
|
||||||
|
{
|
||||||
|
r.moveTop( rect.bottom() - progress * size.height() );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
class GeometryListener final : public QQuickItemChangeListener
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
GeometryListener( QskDrawer* drawer )
|
||||||
|
: m_drawer( drawer )
|
||||||
|
{
|
||||||
|
if ( drawer->parentItem() )
|
||||||
|
{
|
||||||
|
auto d = QQuickItemPrivate::get( drawer->parentItem() );
|
||||||
|
d->addItemChangeListener( this, QQuickItemPrivate::Geometry );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void itemGeometryChanged( QQuickItem*,
|
||||||
|
QQuickGeometryChange, const QRectF& ) override
|
||||||
|
{
|
||||||
|
m_drawer->polish();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
QskDrawer* m_drawer = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Box : public QskBox
|
||||||
|
{
|
||||||
|
using Inherited = QskBox;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Box( QskDrawer* drawer )
|
||||||
|
: QskBox( drawer )
|
||||||
|
{
|
||||||
|
setSubcontrolProxy( QskBox::Panel, Panel );
|
||||||
|
setPanel( true );
|
||||||
|
setAutoLayoutChildren( true );
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
setBackgroundColor( Qt::darkCyan );
|
||||||
|
setMargins( 20 );
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
class QskDrawer::PrivateData
|
class QskDrawer::PrivateData
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
QskControl* content = nullptr;
|
QskControl* content = nullptr;
|
||||||
QskBox* contentBox = nullptr;
|
Box* contentBox = nullptr;
|
||||||
Qt::Edge edge = Qt::LeftEdge;
|
Qt::Edge edge = Qt::LeftEdge;
|
||||||
|
|
||||||
|
GeometryListener* listener = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
QskDrawer::QskDrawer( QQuickItem* parentItem )
|
QskDrawer::QskDrawer( QQuickItem* parentItem )
|
||||||
|
@ -26,23 +115,28 @@ QskDrawer::QskDrawer( QQuickItem* parentItem )
|
||||||
|
|
||||||
setPopupFlag( PopupFlag::CloseOnPressOutside, true );
|
setPopupFlag( PopupFlag::CloseOnPressOutside, true );
|
||||||
|
|
||||||
m_data->contentBox = new QskBox(this);
|
m_data->contentBox = new Box(this);
|
||||||
m_data->contentBox->setSubcontrolProxy( QskBox::Panel, Panel );
|
|
||||||
m_data->contentBox->setPanel( true );
|
|
||||||
|
|
||||||
setSubcontrolProxy( Inherited::Overlay, Overlay );
|
setSubcontrolProxy( Inherited::Overlay, Overlay );
|
||||||
|
|
||||||
setFaderAspect( Panel | QskAspect::Metric );
|
setFaderAspect( Panel | QskAspect::Position | QskAspect::Metric );
|
||||||
|
|
||||||
connect(this, &QskDrawer::closed, this, [this]() {
|
connect( this, &QskDrawer::closed,
|
||||||
startTransition( Panel | QskAspect::Metric,
|
this, [this]() { startFading( false ); } );
|
||||||
animationHint( Panel | QskAspect::Position ),
|
|
||||||
0.0, 1.0 );
|
/*
|
||||||
});
|
The drawer wants to be on top of the parent - not being
|
||||||
|
layouted into its layoutRect(). So we opt out and do
|
||||||
|
the layout updates manually.
|
||||||
|
*/
|
||||||
|
setPlacementPolicy( QskPlacementPolicy::Ignore );
|
||||||
|
if ( parentItem )
|
||||||
|
m_data->listener = new GeometryListener( this );
|
||||||
}
|
}
|
||||||
|
|
||||||
QskDrawer::~QskDrawer()
|
QskDrawer::~QskDrawer()
|
||||||
{
|
{
|
||||||
|
delete m_data->listener;
|
||||||
}
|
}
|
||||||
|
|
||||||
Qt::Edge QskDrawer::edge() const
|
Qt::Edge QskDrawer::edge() const
|
||||||
|
@ -69,70 +163,58 @@ void QskDrawer::setContent( QskControl* content )
|
||||||
m_data->content = content;
|
m_data->content = content;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QSizeF QskDrawer::layoutSizeHint(
|
||||||
|
Qt::SizeHint which, const QSizeF& constraint ) const
|
||||||
|
{
|
||||||
|
// we need to handle QEvent::LayoutRequest
|
||||||
|
return m_data->contentBox->effectiveSizeHint( which, constraint );
|
||||||
|
}
|
||||||
|
|
||||||
|
QRectF QskDrawer::layoutRectForSize( const QSizeF& size ) const
|
||||||
|
{
|
||||||
|
return Inherited::layoutRectForSize( size );
|
||||||
|
}
|
||||||
|
|
||||||
void QskDrawer::updateLayout()
|
void QskDrawer::updateLayout()
|
||||||
{
|
{
|
||||||
if ( !isOpen() && !isFading() )
|
if ( !( isOpen() || isFading() ) )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const auto padding = paddingHint( Panel );
|
const auto targetRect = qskItemRect( parentItem() );
|
||||||
|
const auto size = qskConstrainedItemSize( this, targetRect.size() );
|
||||||
|
|
||||||
auto contentSize = m_data->content->preferredSize();
|
const auto rect = qskDrawerRect( targetRect,
|
||||||
contentSize = contentSize.grownBy( padding );
|
m_data->edge, metric( faderAspect() ), size );
|
||||||
|
|
||||||
const auto parentSize = parentItem()->size();
|
|
||||||
|
|
||||||
switch( m_data->edge )
|
|
||||||
{
|
|
||||||
case Qt::Edge::LeftEdge:
|
|
||||||
{
|
|
||||||
qreal x = metric( faderAspect() ) * contentSize.width() * -1.0;
|
|
||||||
|
|
||||||
qskSetItemGeometry( m_data->contentBox,
|
|
||||||
x, 0, contentSize.width(), parentSize.height() );
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case Qt::Edge::RightEdge:
|
|
||||||
{
|
|
||||||
qreal x = ( metric( faderAspect() ) * contentSize.width() )
|
|
||||||
+ parentSize.width() - contentSize.width();
|
|
||||||
|
|
||||||
qskSetItemGeometry( m_data->contentBox,
|
|
||||||
x, 0, contentSize.width(), parentSize.height() );
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case Qt::Edge::TopEdge:
|
|
||||||
{
|
|
||||||
qreal y = metric( faderAspect() ) * contentSize.height();
|
|
||||||
|
|
||||||
qskSetItemGeometry( m_data->contentBox,
|
|
||||||
0, -y, parentSize.width(), contentSize.height() );
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case Qt::Edge::BottomEdge:
|
|
||||||
{
|
|
||||||
qreal y = metric( faderAspect() ) * contentSize.height() + parentSize.height() -
|
|
||||||
contentSize.height();
|
|
||||||
|
|
||||||
qskSetItemGeometry( m_data->contentBox,
|
|
||||||
0, y, parentSize.width(), contentSize.height() );
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
m_data->content->setGeometry( QPointF( padding.left(), padding.top() ),
|
|
||||||
m_data->contentBox->size().shrunkBy( padding ) );
|
|
||||||
|
|
||||||
|
qskSetItemGeometry( m_data->contentBox, rect );
|
||||||
Inherited::updateLayout();
|
Inherited::updateLayout();
|
||||||
}
|
}
|
||||||
|
|
||||||
void QskDrawer::aboutToShow()
|
void QskDrawer::aboutToShow()
|
||||||
{
|
{
|
||||||
startTransition( Panel | QskAspect::Metric,
|
startFading( true );
|
||||||
animationHint( Panel | QskAspect::Position ), 1.0, 0.0 );
|
|
||||||
|
|
||||||
Inherited::aboutToShow();
|
Inherited::aboutToShow();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QskDrawer::itemChange( QQuickItem::ItemChange change,
|
||||||
|
const QQuickItem::ItemChangeData& value )
|
||||||
|
{
|
||||||
|
Inherited::itemChange( change, value );
|
||||||
|
|
||||||
|
if ( change == QQuickItem::ItemParentHasChanged )
|
||||||
|
{
|
||||||
|
delete m_data->listener;
|
||||||
|
m_data->listener = new GeometryListener( this );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void QskDrawer::startFading( bool open )
|
||||||
|
{
|
||||||
|
const auto from = open ? 1.0 : 0.0;
|
||||||
|
const auto to = open ? 0.0 : 1.0;
|
||||||
|
|
||||||
|
const auto hint = animationHint( Panel | QskAspect::Position );
|
||||||
|
startTransition( faderAspect(), hint, from, to );
|
||||||
|
}
|
||||||
|
|
||||||
#include "moc_QskDrawer.cpp"
|
#include "moc_QskDrawer.cpp"
|
||||||
|
|
|
@ -21,6 +21,7 @@ class QSK_EXPORT QskDrawer : public QskPopup
|
||||||
void setEdge( Qt::Edge );
|
void setEdge( Qt::Edge );
|
||||||
Qt::Edge edge() const;
|
Qt::Edge edge() const;
|
||||||
|
|
||||||
|
QRectF layoutRectForSize( const QSizeF& ) const override;
|
||||||
void updateLayout() override;
|
void updateLayout() override;
|
||||||
|
|
||||||
void setContent( QskControl* );
|
void setContent( QskControl* );
|
||||||
|
@ -30,8 +31,13 @@ class QSK_EXPORT QskDrawer : public QskPopup
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void aboutToShow() override;
|
void aboutToShow() override;
|
||||||
|
void itemChange( ItemChange, const ItemChangeData& ) override;
|
||||||
|
|
||||||
|
QSizeF layoutSizeHint( Qt::SizeHint, const QSizeF& ) const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void startFading( bool );
|
||||||
|
|
||||||
class PrivateData;
|
class PrivateData;
|
||||||
std::unique_ptr< PrivateData > m_data;
|
std::unique_ptr< PrivateData > m_data;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue