QskMenu using position for transitioning, QskSlideIn code removed
This commit is contained in:
parent
4afe56990b
commit
2dd5f34948
|
@ -115,7 +115,6 @@ list(APPEND HEADERS
|
||||||
nodes/QskRichTextRenderer.h
|
nodes/QskRichTextRenderer.h
|
||||||
nodes/QskScaleRenderer.h
|
nodes/QskScaleRenderer.h
|
||||||
nodes/QskSGNode.h
|
nodes/QskSGNode.h
|
||||||
nodes/QskSlideInNode.h
|
|
||||||
nodes/QskStrokeNode.h
|
nodes/QskStrokeNode.h
|
||||||
nodes/QskStippledLineRenderer.h
|
nodes/QskStippledLineRenderer.h
|
||||||
nodes/QskShapeNode.h
|
nodes/QskShapeNode.h
|
||||||
|
@ -147,7 +146,6 @@ list(APPEND SOURCES
|
||||||
nodes/QskRichTextRenderer.cpp
|
nodes/QskRichTextRenderer.cpp
|
||||||
nodes/QskScaleRenderer.cpp
|
nodes/QskScaleRenderer.cpp
|
||||||
nodes/QskSGNode.cpp
|
nodes/QskSGNode.cpp
|
||||||
nodes/QskSlideInNode.cpp
|
|
||||||
nodes/QskStrokeNode.cpp
|
nodes/QskStrokeNode.cpp
|
||||||
nodes/QskStippledLineRenderer.cpp
|
nodes/QskStippledLineRenderer.cpp
|
||||||
nodes/QskShapeNode.cpp
|
nodes/QskShapeNode.cpp
|
||||||
|
@ -210,7 +208,6 @@ list(APPEND HEADERS
|
||||||
controls/QskQuickItem.h
|
controls/QskQuickItem.h
|
||||||
controls/QskRadioBox.h
|
controls/QskRadioBox.h
|
||||||
controls/QskRadioBoxSkinlet.h
|
controls/QskRadioBoxSkinlet.h
|
||||||
controls/QskSlideIn.h
|
|
||||||
controls/QskScrollArea.h
|
controls/QskScrollArea.h
|
||||||
controls/QskScrollBox.h
|
controls/QskScrollBox.h
|
||||||
controls/QskScrollView.h
|
controls/QskScrollView.h
|
||||||
|
@ -317,7 +314,6 @@ list(APPEND SOURCES
|
||||||
controls/QskScrollBox.cpp
|
controls/QskScrollBox.cpp
|
||||||
controls/QskScrollView.cpp
|
controls/QskScrollView.cpp
|
||||||
controls/QskScrollViewSkinlet.cpp
|
controls/QskScrollViewSkinlet.cpp
|
||||||
controls/QskSlideIn.cpp
|
|
||||||
controls/QskRadioBox.cpp
|
controls/QskRadioBox.cpp
|
||||||
controls/QskRadioBoxSkinlet.cpp
|
controls/QskRadioBoxSkinlet.cpp
|
||||||
controls/QskSegmentedBar.cpp
|
controls/QskSegmentedBar.cpp
|
||||||
|
|
|
@ -14,6 +14,11 @@
|
||||||
#include <qguiapplication.h>
|
#include <qguiapplication.h>
|
||||||
#include <qstylehints.h>
|
#include <qstylehints.h>
|
||||||
|
|
||||||
|
QSK_QT_PRIVATE_BEGIN
|
||||||
|
#include <private/qquickitem_p.h>
|
||||||
|
#include <private/qquickitemchangelistener_p.h>
|
||||||
|
QSK_QT_PRIVATE_END
|
||||||
|
|
||||||
static inline qreal qskDefaultDragMargin()
|
static inline qreal qskDefaultDragMargin()
|
||||||
{
|
{
|
||||||
// a skin hint ???
|
// a skin hint ???
|
||||||
|
@ -51,8 +56,104 @@ static bool qskCheckDirection( Qt::Edge edge, const QskPanGesture* gesture )
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline QRectF qskAlignedToEdge(
|
||||||
|
const QRectF& r, const QSizeF& sz, Qt::Edge edge )
|
||||||
|
{
|
||||||
|
switch( edge )
|
||||||
|
{
|
||||||
|
case Qt::LeftEdge:
|
||||||
|
return QRectF( r.left(), r.top(), sz.width(), r.height() );
|
||||||
|
|
||||||
|
case Qt::RightEdge:
|
||||||
|
return QRectF( r.right() - sz.width(), r.top(), sz.width(), r.height() );
|
||||||
|
|
||||||
|
case Qt::TopEdge:
|
||||||
|
return QRectF( r.left(), r.top(), r.width(), sz.height() );
|
||||||
|
|
||||||
|
case Qt::BottomEdge:
|
||||||
|
return QRectF( r.left(), r.bottom() - sz.height(), r.width(), sz.height() );
|
||||||
|
}
|
||||||
|
|
||||||
|
return QRectF();
|
||||||
|
}
|
||||||
|
|
||||||
|
static QPointF qskDrawerTranslation( const QskDrawer* drawer, const QSizeF& size )
|
||||||
|
{
|
||||||
|
const auto ratio = 1.0 - drawer->transitioningFactor();
|
||||||
|
|
||||||
|
auto dx = 0.0;
|
||||||
|
auto dy = 0.0;
|
||||||
|
|
||||||
|
switch( drawer->edge() )
|
||||||
|
{
|
||||||
|
case Qt::LeftEdge:
|
||||||
|
dx = -ratio * size.width();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Qt::RightEdge:
|
||||||
|
dx = ratio * size.width();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Qt::TopEdge:
|
||||||
|
dy = -ratio * size.height();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Qt::BottomEdge:
|
||||||
|
dy = ratio * size.height();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return QPointF( dx, dy );
|
||||||
|
}
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
// Using an eventFilter for QskEvent::GeometryChange instead ???
|
||||||
|
|
||||||
|
class GeometryListener final : public QQuickItemChangeListener
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
GeometryListener( QQuickItem* item, QQuickItem* adjustedItem )
|
||||||
|
: m_item( item )
|
||||||
|
, m_adjustedItem( adjustedItem )
|
||||||
|
{
|
||||||
|
adjust();
|
||||||
|
setEnabled( true );
|
||||||
|
}
|
||||||
|
|
||||||
|
~GeometryListener()
|
||||||
|
{
|
||||||
|
setEnabled( false );
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void itemGeometryChanged( QQuickItem*,
|
||||||
|
QQuickGeometryChange, const QRectF& ) override
|
||||||
|
{
|
||||||
|
adjust();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void adjust()
|
||||||
|
{
|
||||||
|
m_adjustedItem->polish();
|
||||||
|
}
|
||||||
|
|
||||||
|
void setEnabled( bool on )
|
||||||
|
{
|
||||||
|
const auto changeTypes = QQuickItemPrivate::Geometry;
|
||||||
|
|
||||||
|
auto d = QQuickItemPrivate::get( m_item );
|
||||||
|
if ( on )
|
||||||
|
d->addItemChangeListener( this, changeTypes );
|
||||||
|
else
|
||||||
|
d->removeItemChangeListener( this, changeTypes );
|
||||||
|
}
|
||||||
|
|
||||||
|
QQuickItem* m_item;
|
||||||
|
QQuickItem* m_adjustedItem;
|
||||||
|
};
|
||||||
|
|
||||||
class GestureRecognizer : public QskPanGestureRecognizer
|
class GestureRecognizer : public QskPanGestureRecognizer
|
||||||
{
|
{
|
||||||
using Inherited = QskPanGestureRecognizer;
|
using Inherited = QskPanGestureRecognizer;
|
||||||
|
@ -108,27 +209,59 @@ namespace
|
||||||
class QskDrawer::PrivateData
|
class QskDrawer::PrivateData
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Qt::Edge edge = Qt::LeftEdge;
|
PrivateData( Qt::Edge edge )
|
||||||
|
: edge( edge )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void resetListener( QskDrawer* drawer )
|
||||||
|
{
|
||||||
|
delete listener;
|
||||||
|
listener = nullptr;
|
||||||
|
|
||||||
|
if ( drawer->parentItem() && drawer->isVisible() )
|
||||||
|
listener = new GeometryListener( drawer->parentItem(), drawer );
|
||||||
|
}
|
||||||
|
|
||||||
|
GeometryListener* listener = nullptr;
|
||||||
GestureRecognizer* gestureRecognizer = nullptr;
|
GestureRecognizer* gestureRecognizer = nullptr;
|
||||||
|
|
||||||
qreal dragMargin = qskDefaultDragMargin();
|
qreal dragMargin = qskDefaultDragMargin();
|
||||||
|
Qt::Edge edge;
|
||||||
};
|
};
|
||||||
|
|
||||||
QskDrawer::QskDrawer( QQuickItem* parentItem )
|
QskDrawer::QskDrawer( QQuickItem* parentItem )
|
||||||
|
: QskDrawer( Qt::LeftEdge, parentItem )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
QskDrawer::QskDrawer( Qt::Edge edge, QQuickItem* parentItem )
|
||||||
: Inherited ( parentItem )
|
: Inherited ( parentItem )
|
||||||
, m_data( new PrivateData )
|
, m_data( new PrivateData( edge ) )
|
||||||
{
|
{
|
||||||
#if 1
|
#if 1
|
||||||
setZ( 1 );
|
setZ( 1 );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
setPopupFlag( PopupFlag::CloseOnPressOutside, true );
|
||||||
|
|
||||||
|
/*
|
||||||
|
A drawer wants to be on top of its parent - not being
|
||||||
|
layouted into its layoutRect(). So we opt out and do
|
||||||
|
the layout updates manually.
|
||||||
|
*/
|
||||||
|
setPlacementPolicy( QskPlacementPolicy::Ignore );
|
||||||
|
|
||||||
setAutoLayoutChildren( true );
|
setAutoLayoutChildren( true );
|
||||||
setInteractive( true );
|
setInteractive( true );
|
||||||
setAdjustingToParentGeometry( true );
|
|
||||||
|
connect( this, &QskPopup::transitioningChanged,
|
||||||
|
this, &QQuickItem::setClip );
|
||||||
}
|
}
|
||||||
|
|
||||||
QskDrawer::~QskDrawer()
|
QskDrawer::~QskDrawer()
|
||||||
{
|
{
|
||||||
|
delete m_data->listener;
|
||||||
}
|
}
|
||||||
|
|
||||||
Qt::Edge QskDrawer::edge() const
|
Qt::Edge QskDrawer::edge() const
|
||||||
|
@ -227,9 +360,98 @@ void QskDrawer::itemChange( QQuickItem::ItemChange change,
|
||||||
if ( parentItem() && isInteractive() )
|
if ( parentItem() && isInteractive() )
|
||||||
qskCatchMouseEvents( parentItem() );
|
qskCatchMouseEvents( parentItem() );
|
||||||
|
|
||||||
|
m_data->resetListener( this );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case QQuickItem::ItemVisibleHasChanged:
|
||||||
|
{
|
||||||
|
m_data->resetListener( this );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QskDrawer::updateResources()
|
||||||
|
{
|
||||||
|
Inherited::updateResources();
|
||||||
|
|
||||||
|
/*
|
||||||
|
Adjusting the geometry to the parent needs to be done before
|
||||||
|
the layouting of the children ( -> autoLayoutChildren ) is done.
|
||||||
|
So we are using this hook even if it is not about resources: TODO ...
|
||||||
|
*/
|
||||||
|
if ( const auto item = parentItem() )
|
||||||
|
{
|
||||||
|
auto r = qskItemRect( item );
|
||||||
|
r = qskAlignedToEdge( r, sizeConstraint( Qt::PreferredSize ), edge() );
|
||||||
|
|
||||||
|
r.translate( qskDrawerTranslation( this, r.size() ) );
|
||||||
|
setGeometry( r );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void QskDrawer::updateNode( QSGNode* node )
|
||||||
|
{
|
||||||
|
if ( isTransitioning() && clip() )
|
||||||
|
{
|
||||||
|
if ( auto clipNode = QQuickItemPrivate::get( this )->clipNode() )
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
The clipRect is changing while transitioning. Couldn't
|
||||||
|
find a way how to trigger updates - maybe be enabling/disabling
|
||||||
|
the clip. So we do the updates manually. TODO ...
|
||||||
|
*/
|
||||||
|
const auto r = clipRect();
|
||||||
|
if ( r != clipNode->rect() )
|
||||||
|
{
|
||||||
|
clipNode->setRect( r );
|
||||||
|
clipNode->update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Inherited::updateNode( node );
|
||||||
|
}
|
||||||
|
|
||||||
|
QRectF QskDrawer::clipRect() const
|
||||||
|
{
|
||||||
|
if ( isTransitioning() && parentItem() )
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
We might not fit into our parent and our children not
|
||||||
|
into our rect. So we want to have a clip against the
|
||||||
|
edge, where the drawer slides in/out only.
|
||||||
|
Otherwise we would have unwanted effects, when clipping gets
|
||||||
|
disabled once the transition is over.
|
||||||
|
*/
|
||||||
|
constexpr qreal d = 1e6;
|
||||||
|
|
||||||
|
QRectF r( -d, -d, 2.0 * d, 2.0 * d );
|
||||||
|
|
||||||
|
switch( edge() )
|
||||||
|
{
|
||||||
|
case Qt::LeftEdge:
|
||||||
|
r.setLeft( -x() );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Qt::RightEdge:
|
||||||
|
r.setRight( parentItem()->width() - x() );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Qt::TopEdge:
|
||||||
|
r.setTop( -y() );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Qt::BottomEdge:
|
||||||
|
r.setBottom( parentItem()->height() - y() );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Inherited::clipRect();
|
||||||
|
}
|
||||||
|
|
||||||
#include "moc_QskDrawer.cpp"
|
#include "moc_QskDrawer.cpp"
|
||||||
|
|
|
@ -6,13 +6,13 @@
|
||||||
#ifndef QSK_DRAWER_H
|
#ifndef QSK_DRAWER_H
|
||||||
#define QSK_DRAWER_H
|
#define QSK_DRAWER_H
|
||||||
|
|
||||||
#include "QskSlideIn.h"
|
#include "QskPopup.h"
|
||||||
|
|
||||||
class QSK_EXPORT QskDrawer : public QskSlideIn
|
class QSK_EXPORT QskDrawer : public QskPopup
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
using Inherited = QskSlideIn;
|
using Inherited = QskPopup;
|
||||||
|
|
||||||
Q_PROPERTY( Qt::Edge edge READ edge WRITE setEdge NOTIFY edgeChanged )
|
Q_PROPERTY( Qt::Edge edge READ edge WRITE setEdge NOTIFY edgeChanged )
|
||||||
|
|
||||||
|
@ -24,10 +24,12 @@ class QSK_EXPORT QskDrawer : public QskSlideIn
|
||||||
|
|
||||||
public:
|
public:
|
||||||
QskDrawer( QQuickItem* = nullptr );
|
QskDrawer( QQuickItem* = nullptr );
|
||||||
|
QskDrawer( Qt::Edge, QQuickItem* = nullptr );
|
||||||
|
|
||||||
~QskDrawer() override;
|
~QskDrawer() override;
|
||||||
|
|
||||||
void setEdge( Qt::Edge );
|
void setEdge( Qt::Edge );
|
||||||
Qt::Edge edge() const override final;
|
Qt::Edge edge() const;
|
||||||
|
|
||||||
void setInteractive( bool );
|
void setInteractive( bool );
|
||||||
bool isInteractive() const;
|
bool isInteractive() const;
|
||||||
|
@ -36,14 +38,19 @@ class QSK_EXPORT QskDrawer : public QskSlideIn
|
||||||
void resetDragMargin();
|
void resetDragMargin();
|
||||||
qreal dragMargin() const;
|
qreal dragMargin() const;
|
||||||
|
|
||||||
|
QRectF clipRect() const override;
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
void edgeChanged( Qt::Edge );
|
void edgeChanged( Qt::Edge );
|
||||||
void dragMarginChanged( qreal );
|
void dragMarginChanged( qreal );
|
||||||
void interactiveChanged( bool );
|
void interactiveChanged( bool );
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void itemChange( ItemChange, const ItemChangeData& ) override;
|
|
||||||
void gestureEvent( QskGestureEvent* ) override;
|
void gestureEvent( QskGestureEvent* ) override;
|
||||||
|
void itemChange( ItemChange, const ItemChangeData& ) override;
|
||||||
|
|
||||||
|
void updateResources() override;
|
||||||
|
void updateNode( QSGNode* ) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class PrivateData;
|
class PrivateData;
|
||||||
|
|
|
@ -18,6 +18,10 @@
|
||||||
#include <qvariant.h>
|
#include <qvariant.h>
|
||||||
#include <qeventloop.h>
|
#include <qeventloop.h>
|
||||||
|
|
||||||
|
QSK_QT_PRIVATE_BEGIN
|
||||||
|
#include <private/qquickitem_p.h>
|
||||||
|
QSK_QT_PRIVATE_END
|
||||||
|
|
||||||
QSK_SUBCONTROL( QskMenu, Overlay )
|
QSK_SUBCONTROL( QskMenu, Overlay )
|
||||||
QSK_SUBCONTROL( QskMenu, Panel )
|
QSK_SUBCONTROL( QskMenu, Panel )
|
||||||
QSK_SUBCONTROL( QskMenu, Segment )
|
QSK_SUBCONTROL( QskMenu, Segment )
|
||||||
|
@ -62,13 +66,17 @@ QskMenu::QskMenu( QQuickItem* parent )
|
||||||
setPopupFlag( QskPopup::CloseOnPressOutside, true );
|
setPopupFlag( QskPopup::CloseOnPressOutside, true );
|
||||||
setPopupFlag( QskPopup::DeleteOnClose, true );
|
setPopupFlag( QskPopup::DeleteOnClose, true );
|
||||||
|
|
||||||
|
setPlacementPolicy( QskPlacementPolicy::Ignore );
|
||||||
setSubcontrolProxy( Inherited::Overlay, Overlay );
|
setSubcontrolProxy( Inherited::Overlay, Overlay );
|
||||||
|
|
||||||
initSizePolicy( QskSizePolicy::Fixed, QskSizePolicy::Fixed );
|
initSizePolicy( QskSizePolicy::Fixed, QskSizePolicy::Fixed );
|
||||||
|
|
||||||
// we hide the focus indicator while sliding
|
// we hide the focus indicator while sliding
|
||||||
connect( this, &QskMenu::transitioningChanged, this,
|
connect( this, &QskMenu::transitioningChanged,
|
||||||
&QskControl::focusIndicatorRectChanged );
|
this, &QskControl::focusIndicatorRectChanged );
|
||||||
|
|
||||||
|
connect( this, &QskPopup::transitioningChanged,
|
||||||
|
this, &QQuickItem::setClip );
|
||||||
|
|
||||||
connect( this, &QskMenu::opened, this,
|
connect( this, &QskMenu::opened, this,
|
||||||
[this]() { m_data->triggeredIndex = -1; } );
|
[this]() { m_data->triggeredIndex = -1; } );
|
||||||
|
@ -80,6 +88,17 @@ QskMenu::~QskMenu()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QRectF QskMenu::clipRect() const
|
||||||
|
{
|
||||||
|
if ( isTransitioning() )
|
||||||
|
{
|
||||||
|
constexpr qreal d = 1e6;
|
||||||
|
return QRectF( -d, m_data->origin.y() - y(), 2.0 * d, d );
|
||||||
|
}
|
||||||
|
|
||||||
|
return Inherited::clipRect();
|
||||||
|
}
|
||||||
|
|
||||||
#if 1
|
#if 1
|
||||||
|
|
||||||
// has no effect as we do not offer submenus yet. TODO ...
|
// has no effect as we do not offer submenus yet. TODO ...
|
||||||
|
@ -262,6 +281,38 @@ QString QskMenu::triggeredText() const
|
||||||
return optionAt( m_data->triggeredIndex ).text();
|
return optionAt( m_data->triggeredIndex ).text();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QskMenu::updateResources()
|
||||||
|
{
|
||||||
|
const auto size = sizeConstraint();
|
||||||
|
const auto dy = ( 1.0 - transitioningFactor() ) * size.height();
|
||||||
|
|
||||||
|
setGeometry( m_data->origin.x(), m_data->origin.y() - dy,
|
||||||
|
size.width(), size.height() );
|
||||||
|
}
|
||||||
|
|
||||||
|
void QskMenu::updateNode( QSGNode* node )
|
||||||
|
{
|
||||||
|
if ( isTransitioning() && clip() )
|
||||||
|
{
|
||||||
|
if ( auto clipNode = QQuickItemPrivate::get( this )->clipNode() )
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
The clipRect is changing while transitioning. Couldn't
|
||||||
|
find a way how to trigger updates - maybe be enabling/disabling
|
||||||
|
the clip. So we do the updates manually. TODO ...
|
||||||
|
*/
|
||||||
|
const auto r = clipRect();
|
||||||
|
if ( r != clipNode->rect() )
|
||||||
|
{
|
||||||
|
clipNode->setRect( r );
|
||||||
|
clipNode->update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Inherited::updateNode( node );
|
||||||
|
}
|
||||||
|
|
||||||
void QskMenu::keyPressEvent( QKeyEvent* event )
|
void QskMenu::keyPressEvent( QKeyEvent* event )
|
||||||
{
|
{
|
||||||
if( m_data->currentIndex < 0 )
|
if( m_data->currentIndex < 0 )
|
||||||
|
@ -434,8 +485,6 @@ void QskMenu::mouseReleaseEvent( QMouseEvent* event )
|
||||||
|
|
||||||
void QskMenu::aboutToShow()
|
void QskMenu::aboutToShow()
|
||||||
{
|
{
|
||||||
setGeometry( QRectF( m_data->origin, sizeConstraint() ) );
|
|
||||||
|
|
||||||
if ( m_data->currentIndex < 0 )
|
if ( m_data->currentIndex < 0 )
|
||||||
{
|
{
|
||||||
if ( !m_data->actions.isEmpty() )
|
if ( !m_data->actions.isEmpty() )
|
||||||
|
|
|
@ -81,6 +81,8 @@ class QSK_EXPORT QskMenu : public QskPopup
|
||||||
|
|
||||||
bool isPressed() const;
|
bool isPressed() const;
|
||||||
|
|
||||||
|
QRectF clipRect() const override;
|
||||||
|
|
||||||
Q_INVOKABLE int exec();
|
Q_INVOKABLE int exec();
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
|
@ -115,6 +117,9 @@ class QSK_EXPORT QskMenu : public QskPopup
|
||||||
void aboutToShow() override;
|
void aboutToShow() override;
|
||||||
void trigger( int );
|
void trigger( int );
|
||||||
|
|
||||||
|
void updateResources() override;
|
||||||
|
void updateNode( QSGNode* ) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void traverse( int steps );
|
void traverse( int steps );
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,6 @@
|
||||||
#include "QskLabelData.h"
|
#include "QskLabelData.h"
|
||||||
|
|
||||||
#include "QskSGNode.h"
|
#include "QskSGNode.h"
|
||||||
#include "QskSlideInNode.h"
|
|
||||||
|
|
||||||
#include <qfontmetrics.h>
|
#include <qfontmetrics.h>
|
||||||
#include <qmath.h>
|
#include <qmath.h>
|
||||||
|
@ -223,26 +222,13 @@ QSGNode* QskMenuSkinlet::updateSubNode(
|
||||||
{
|
{
|
||||||
case ContentsRole:
|
case ContentsRole:
|
||||||
{
|
{
|
||||||
/*
|
|
||||||
QskSlideInNode works for controls made of nodes - not for
|
|
||||||
containers of other quick items. TODO ...
|
|
||||||
*/
|
|
||||||
|
|
||||||
const auto popup = static_cast< const QskPopup* >( skinnable );
|
const auto popup = static_cast< const QskPopup* >( skinnable );
|
||||||
|
|
||||||
auto rect = popup->contentsRect();
|
auto rect = popup->contentsRect();
|
||||||
if ( rect.isEmpty() )
|
if ( rect.isEmpty() )
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
auto slideInNode = QskSGNode::ensureNode< QskSlideInNode >( node );
|
return updateContentsNode( popup, node );
|
||||||
|
|
||||||
slideInNode->updateTranslation(
|
|
||||||
rect, Qt::TopEdge, popup->transitioningFactor() );
|
|
||||||
|
|
||||||
auto contentsNode = updateContentsNode( popup, slideInNode->contentsNode() );
|
|
||||||
slideInNode->setContentsNode( contentsNode );
|
|
||||||
|
|
||||||
return slideInNode;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,269 +0,0 @@
|
||||||
/******************************************************************************
|
|
||||||
* QSkinny - Copyright (C) 2016 Uwe Rathmann
|
|
||||||
* SPDX-License-Identifier: BSD-3-Clause
|
|
||||||
*****************************************************************************/
|
|
||||||
|
|
||||||
#include "QskSlideIn.h"
|
|
||||||
#include "QskQuick.h"
|
|
||||||
|
|
||||||
QSK_QT_PRIVATE_BEGIN
|
|
||||||
#include <private/qquickitem_p.h>
|
|
||||||
#include <private/qquickitemchangelistener_p.h>
|
|
||||||
QSK_QT_PRIVATE_END
|
|
||||||
|
|
||||||
static QPointF qskSlideInTranslation( const QskSlideIn* slideIn, const QSizeF& size )
|
|
||||||
{
|
|
||||||
const auto ratio = 1.0 - slideIn->transitioningFactor();
|
|
||||||
|
|
||||||
auto dx = 0.0;
|
|
||||||
auto dy = 0.0;
|
|
||||||
|
|
||||||
switch( slideIn->edge() )
|
|
||||||
{
|
|
||||||
case Qt::LeftEdge:
|
|
||||||
dx = -ratio * size.width();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Qt::RightEdge:
|
|
||||||
dx = ratio * size.width();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Qt::TopEdge:
|
|
||||||
dy = -ratio * size.height();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Qt::BottomEdge:
|
|
||||||
dy = ratio * size.height();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return QPointF( dx, dy );
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline QRectF qskAlignedToEdge(
|
|
||||||
const QRectF& r, const QSizeF& sz, Qt::Edge edge )
|
|
||||||
{
|
|
||||||
switch( edge )
|
|
||||||
{
|
|
||||||
case Qt::LeftEdge:
|
|
||||||
return QRectF( r.left(), r.top(), sz.width(), r.height() );
|
|
||||||
|
|
||||||
case Qt::RightEdge:
|
|
||||||
return QRectF( r.right() - sz.width(), r.top(), sz.width(), r.height() );
|
|
||||||
|
|
||||||
case Qt::TopEdge:
|
|
||||||
return QRectF( r.left(), r.top(), r.width(), sz.height() );
|
|
||||||
|
|
||||||
case Qt::BottomEdge:
|
|
||||||
return QRectF( r.left(), r.bottom() - sz.height(), r.width(), sz.height() );
|
|
||||||
}
|
|
||||||
|
|
||||||
return QRectF();
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace
|
|
||||||
{
|
|
||||||
// Using an eventFilter for QskEvent::GeometryChange instead ???
|
|
||||||
|
|
||||||
class GeometryListener final : public QQuickItemChangeListener
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
GeometryListener( QQuickItem* item, QQuickItem* adjustedItem )
|
|
||||||
: m_item( item )
|
|
||||||
, m_adjustedItem( adjustedItem )
|
|
||||||
{
|
|
||||||
adjust();
|
|
||||||
setEnabled( true );
|
|
||||||
}
|
|
||||||
|
|
||||||
~GeometryListener()
|
|
||||||
{
|
|
||||||
setEnabled( false );
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
void itemGeometryChanged( QQuickItem*,
|
|
||||||
QQuickGeometryChange, const QRectF& ) override
|
|
||||||
{
|
|
||||||
adjust();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
void adjust()
|
|
||||||
{
|
|
||||||
m_adjustedItem->polish();
|
|
||||||
}
|
|
||||||
|
|
||||||
void setEnabled( bool on )
|
|
||||||
{
|
|
||||||
const auto changeTypes = QQuickItemPrivate::Geometry;
|
|
||||||
|
|
||||||
auto d = QQuickItemPrivate::get( m_item );
|
|
||||||
if ( on )
|
|
||||||
d->addItemChangeListener( this, changeTypes );
|
|
||||||
else
|
|
||||||
d->removeItemChangeListener( this, changeTypes );
|
|
||||||
}
|
|
||||||
|
|
||||||
QQuickItem* m_item;
|
|
||||||
QQuickItem* m_adjustedItem;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
class QskSlideIn::PrivateData
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
inline void resetListener( QskSlideIn* slideIn )
|
|
||||||
{
|
|
||||||
delete listener;
|
|
||||||
listener = nullptr;
|
|
||||||
|
|
||||||
if ( adjustingToParentGeometry )
|
|
||||||
{
|
|
||||||
if ( slideIn->parentItem() && slideIn->isVisible() )
|
|
||||||
listener = new GeometryListener( slideIn->parentItem(), slideIn );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool adjustingToParentGeometry = false;
|
|
||||||
GeometryListener* listener = nullptr;
|
|
||||||
};
|
|
||||||
|
|
||||||
QskSlideIn::QskSlideIn( QQuickItem* parentItem )
|
|
||||||
: Inherited ( parentItem )
|
|
||||||
, m_data( new PrivateData )
|
|
||||||
{
|
|
||||||
setPopupFlag( PopupFlag::CloseOnPressOutside, true );
|
|
||||||
|
|
||||||
/*
|
|
||||||
A slider wants to be on top of its parent - not being
|
|
||||||
layouted into its layoutRect(). So we opt out and do
|
|
||||||
the layout updates manually.
|
|
||||||
*/
|
|
||||||
setPlacementPolicy( QskPlacementPolicy::Ignore );
|
|
||||||
|
|
||||||
connect( this, &QskPopup::transitioningChanged,
|
|
||||||
this, &QQuickItem::setClip );
|
|
||||||
}
|
|
||||||
|
|
||||||
QskSlideIn::~QskSlideIn()
|
|
||||||
{
|
|
||||||
delete m_data->listener;
|
|
||||||
}
|
|
||||||
|
|
||||||
void QskSlideIn::setAdjustingToParentGeometry( bool on )
|
|
||||||
{
|
|
||||||
if ( on != m_data->adjustingToParentGeometry )
|
|
||||||
{
|
|
||||||
m_data->adjustingToParentGeometry = on;
|
|
||||||
m_data->resetListener( this );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool QskSlideIn::isAdjustingToParentGeometry() const
|
|
||||||
{
|
|
||||||
return m_data->adjustingToParentGeometry;
|
|
||||||
}
|
|
||||||
|
|
||||||
void QskSlideIn::itemChange( QQuickItem::ItemChange change,
|
|
||||||
const QQuickItem::ItemChangeData& value )
|
|
||||||
{
|
|
||||||
Inherited::itemChange( change, value );
|
|
||||||
|
|
||||||
switch( static_cast< int >( change ) )
|
|
||||||
{
|
|
||||||
case QQuickItem::ItemParentHasChanged:
|
|
||||||
case QQuickItem::ItemVisibleHasChanged:
|
|
||||||
{
|
|
||||||
m_data->resetListener( this );
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void QskSlideIn::updateResources()
|
|
||||||
{
|
|
||||||
Inherited::updateResources();
|
|
||||||
|
|
||||||
/*
|
|
||||||
Adjusting the geometry to the parent needs to be done before
|
|
||||||
the layouting of the children ( -> autoLayoutChildren ) is done.
|
|
||||||
So we are using this hook even if it is not about resources: TODO ...
|
|
||||||
*/
|
|
||||||
if ( const auto item = parentItem() )
|
|
||||||
{
|
|
||||||
auto r = qskItemRect( item );
|
|
||||||
r = qskAlignedToEdge( r, sizeConstraint( Qt::PreferredSize ), edge() );
|
|
||||||
|
|
||||||
r.translate( qskSlideInTranslation( this, r.size() ) );
|
|
||||||
setGeometry( r );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QRectF QskSlideIn::clipRect() const
|
|
||||||
{
|
|
||||||
if ( isTransitioning() && parentItem() )
|
|
||||||
{
|
|
||||||
// parent rectangle translated into the coordinate system of the slideIn
|
|
||||||
const QRectF rect( -position(), parentItem()->size() );
|
|
||||||
|
|
||||||
/*
|
|
||||||
We might not fit into our parent and our children not
|
|
||||||
into our rect. So we want to have a clip against the
|
|
||||||
edge, where the drawer slides in/out only.
|
|
||||||
Otherwise we would have unwanted effects, when clipping gets
|
|
||||||
disabled once the transition is over.
|
|
||||||
*/
|
|
||||||
constexpr qreal d = 1e6;
|
|
||||||
|
|
||||||
QRectF r( -d, -d, 2.0 * d, 2.0 * d );
|
|
||||||
|
|
||||||
switch( edge() )
|
|
||||||
{
|
|
||||||
case Qt::LeftEdge:
|
|
||||||
r.setLeft( rect.left() );
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Qt::RightEdge:
|
|
||||||
r.setRight( rect.right() );
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Qt::TopEdge:
|
|
||||||
r.setTop( rect.top() );
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Qt::BottomEdge:
|
|
||||||
r.setBottom( rect.bottom() );
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Inherited::clipRect();
|
|
||||||
}
|
|
||||||
|
|
||||||
void QskSlideIn::updateNode( QSGNode* node )
|
|
||||||
{
|
|
||||||
if ( isTransitioning() && clip() )
|
|
||||||
{
|
|
||||||
if ( auto clipNode = QQuickItemPrivate::get( this )->clipNode() )
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
The clipRect is changing while transitioning. Couldn't
|
|
||||||
find a way how to trigger updates - maybe be enabling/disabling
|
|
||||||
the clip. So we do the updates manually. TODO ...
|
|
||||||
*/
|
|
||||||
const auto r = clipRect();
|
|
||||||
if ( r != clipNode->rect() )
|
|
||||||
{
|
|
||||||
clipNode->setRect( r );
|
|
||||||
clipNode->update();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Inherited::updateNode( node );
|
|
||||||
}
|
|
||||||
|
|
||||||
#include "moc_QskSlideIn.cpp"
|
|
|
@ -1,40 +0,0 @@
|
||||||
/******************************************************************************
|
|
||||||
* QSkinny - Copyright (C) 2016 Uwe Rathmann
|
|
||||||
* SPDX-License-Identifier: BSD-3-Clause
|
|
||||||
*****************************************************************************/
|
|
||||||
|
|
||||||
#ifndef QSK_SLIDE_IN_H
|
|
||||||
#define QSK_SLIDE_IN_H
|
|
||||||
|
|
||||||
#include "QskPopup.h"
|
|
||||||
#include <qnamespace.h>
|
|
||||||
|
|
||||||
class QSK_EXPORT QskSlideIn : public QskPopup
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
using Inherited = QskPopup;
|
|
||||||
|
|
||||||
public:
|
|
||||||
~QskSlideIn() override;
|
|
||||||
|
|
||||||
virtual Qt::Edge edge() const = 0;
|
|
||||||
|
|
||||||
QRectF clipRect() const override;
|
|
||||||
|
|
||||||
void setAdjustingToParentGeometry( bool on );
|
|
||||||
bool isAdjustingToParentGeometry() const;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
QskSlideIn( QQuickItem* = nullptr );
|
|
||||||
|
|
||||||
void itemChange( ItemChange, const ItemChangeData& ) override;
|
|
||||||
void updateResources() override;
|
|
||||||
void updateNode( QSGNode* ) override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
class PrivateData;
|
|
||||||
std::unique_ptr< PrivateData > m_data;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,146 +0,0 @@
|
||||||
/******************************************************************************
|
|
||||||
* QSkinny - Copyright (C) 2016 Uwe Rathmann
|
|
||||||
* SPDX-License-Identifier: BSD-3-Clause
|
|
||||||
*****************************************************************************/
|
|
||||||
|
|
||||||
#include "QskSlideInNode.h"
|
|
||||||
#include "QskSGNode.h"
|
|
||||||
#include <qtransform.h>
|
|
||||||
|
|
||||||
QSK_QT_PRIVATE_BEGIN
|
|
||||||
#include <private/qsgnode_p.h>
|
|
||||||
QSK_QT_PRIVATE_END
|
|
||||||
|
|
||||||
class QskSlideInNodePrivate final : public QSGNodePrivate
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
~QskSlideInNodePrivate()
|
|
||||||
{
|
|
||||||
delete clipNode;
|
|
||||||
delete transformNode;
|
|
||||||
delete contentsNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
void reparentContentNode( QskSlideInNode* node )
|
|
||||||
{
|
|
||||||
if ( contentsNode )
|
|
||||||
{
|
|
||||||
QSGNode* parentNode = transformNode;
|
|
||||||
|
|
||||||
if ( parentNode == nullptr )
|
|
||||||
parentNode = clipNode;
|
|
||||||
|
|
||||||
if ( parentNode == nullptr )
|
|
||||||
parentNode = node;
|
|
||||||
|
|
||||||
QskSGNode::setParentNode( contentsNode, parentNode );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QSGClipNode* clipNode = nullptr;
|
|
||||||
QSGTransformNode* transformNode = nullptr;
|
|
||||||
QSGNode* contentsNode = nullptr;
|
|
||||||
};
|
|
||||||
|
|
||||||
QskSlideInNode::QskSlideInNode()
|
|
||||||
: QSGNode( *new QskSlideInNodePrivate, QSGNode::BasicNodeType )
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
QskSlideInNode::~QskSlideInNode() = default;
|
|
||||||
|
|
||||||
void QskSlideInNode::updateTranslation( const QRectF& rect,
|
|
||||||
Qt::Edge edge, qreal progress )
|
|
||||||
{
|
|
||||||
Q_UNUSED( edge ); // TODO ...
|
|
||||||
|
|
||||||
Q_D( QskSlideInNode );
|
|
||||||
|
|
||||||
{
|
|
||||||
// clipping
|
|
||||||
|
|
||||||
if ( progress >= 0.0 && progress < 1.0 )
|
|
||||||
{
|
|
||||||
if ( d->clipNode == nullptr )
|
|
||||||
{
|
|
||||||
d->clipNode = new QSGClipNode();
|
|
||||||
d->clipNode->setFlag( QSGNode::OwnedByParent, false );
|
|
||||||
d->clipNode->setIsRectangular( true );
|
|
||||||
}
|
|
||||||
|
|
||||||
d->clipNode->setClipRect( rect );
|
|
||||||
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
delete d->clipNode;
|
|
||||||
d->clipNode = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( d->clipNode )
|
|
||||||
QskSGNode::setParentNode( d->clipNode, this );
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
// translation
|
|
||||||
|
|
||||||
qreal dx = 0.0;
|
|
||||||
qreal dy = ( progress - 1.0 ) * rect.height();
|
|
||||||
|
|
||||||
if ( dx != 0.0 || dy != 0.0 )
|
|
||||||
{
|
|
||||||
if ( d->transformNode == nullptr )
|
|
||||||
{
|
|
||||||
d->transformNode = new QSGTransformNode();
|
|
||||||
d->transformNode->setFlag( QSGNode::OwnedByParent, false );
|
|
||||||
}
|
|
||||||
|
|
||||||
QTransform transform;
|
|
||||||
transform.translate( dx, dy );
|
|
||||||
|
|
||||||
d->transformNode->setMatrix( transform );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
delete d->transformNode;
|
|
||||||
d->transformNode = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( d->transformNode )
|
|
||||||
{
|
|
||||||
QSGNode* parentNode = d->clipNode;
|
|
||||||
if ( parentNode == nullptr )
|
|
||||||
parentNode = this;
|
|
||||||
|
|
||||||
QskSGNode::setParentNode( d->transformNode, parentNode );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
d->reparentContentNode( this );
|
|
||||||
}
|
|
||||||
|
|
||||||
void QskSlideInNode::setContentsNode( QSGNode* node )
|
|
||||||
{
|
|
||||||
Q_D( QskSlideInNode );
|
|
||||||
|
|
||||||
if ( d->contentsNode == node )
|
|
||||||
return;
|
|
||||||
|
|
||||||
if ( node )
|
|
||||||
node->setFlag( QSGNode::OwnedByParent, false );
|
|
||||||
|
|
||||||
delete d->contentsNode;
|
|
||||||
d->contentsNode = node;
|
|
||||||
|
|
||||||
d->reparentContentNode( this );
|
|
||||||
}
|
|
||||||
|
|
||||||
QSGNode* QskSlideInNode::contentsNode()
|
|
||||||
{
|
|
||||||
return d_func()->contentsNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
const QSGNode* QskSlideInNode::contentsNode() const
|
|
||||||
{
|
|
||||||
return d_func()->contentsNode;
|
|
||||||
}
|
|
|
@ -1,33 +0,0 @@
|
||||||
/******************************************************************************
|
|
||||||
* QSkinny - Copyright (C) 2016 Uwe Rathmann
|
|
||||||
* SPDX-License-Identifier: BSD-3-Clause
|
|
||||||
*****************************************************************************/
|
|
||||||
|
|
||||||
#ifndef QSK_SLIDE_IN_NODE_H
|
|
||||||
#define QSK_SLIDE_IN_NODE_H
|
|
||||||
|
|
||||||
#include "QskGlobal.h"
|
|
||||||
|
|
||||||
#include <qsgnode.h>
|
|
||||||
#include <qnamespace.h>
|
|
||||||
|
|
||||||
class QskSlideInNodePrivate;
|
|
||||||
|
|
||||||
class QSK_EXPORT QskSlideInNode : public QSGNode
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
QskSlideInNode();
|
|
||||||
~QskSlideInNode() override;
|
|
||||||
|
|
||||||
void updateTranslation( const QRectF&, Qt::Edge, qreal progress );
|
|
||||||
|
|
||||||
void setContentsNode( QSGNode* );
|
|
||||||
|
|
||||||
QSGNode* contentsNode();
|
|
||||||
const QSGNode* contentsNode() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
Q_DECLARE_PRIVATE( QskSlideInNode )
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
Loading…
Reference in New Issue