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/QskScaleRenderer.h
|
||||
nodes/QskSGNode.h
|
||||
nodes/QskSlideInNode.h
|
||||
nodes/QskStrokeNode.h
|
||||
nodes/QskStippledLineRenderer.h
|
||||
nodes/QskShapeNode.h
|
||||
|
@ -147,7 +146,6 @@ list(APPEND SOURCES
|
|||
nodes/QskRichTextRenderer.cpp
|
||||
nodes/QskScaleRenderer.cpp
|
||||
nodes/QskSGNode.cpp
|
||||
nodes/QskSlideInNode.cpp
|
||||
nodes/QskStrokeNode.cpp
|
||||
nodes/QskStippledLineRenderer.cpp
|
||||
nodes/QskShapeNode.cpp
|
||||
|
@ -210,7 +208,6 @@ list(APPEND HEADERS
|
|||
controls/QskQuickItem.h
|
||||
controls/QskRadioBox.h
|
||||
controls/QskRadioBoxSkinlet.h
|
||||
controls/QskSlideIn.h
|
||||
controls/QskScrollArea.h
|
||||
controls/QskScrollBox.h
|
||||
controls/QskScrollView.h
|
||||
|
@ -317,7 +314,6 @@ list(APPEND SOURCES
|
|||
controls/QskScrollBox.cpp
|
||||
controls/QskScrollView.cpp
|
||||
controls/QskScrollViewSkinlet.cpp
|
||||
controls/QskSlideIn.cpp
|
||||
controls/QskRadioBox.cpp
|
||||
controls/QskRadioBoxSkinlet.cpp
|
||||
controls/QskSegmentedBar.cpp
|
||||
|
|
|
@ -14,6 +14,11 @@
|
|||
#include <qguiapplication.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()
|
||||
{
|
||||
// a skin hint ???
|
||||
|
@ -51,8 +56,104 @@ static bool qskCheckDirection( Qt::Edge edge, const QskPanGesture* gesture )
|
|||
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
|
||||
{
|
||||
// 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
|
||||
{
|
||||
using Inherited = QskPanGestureRecognizer;
|
||||
|
@ -108,27 +209,59 @@ namespace
|
|||
class QskDrawer::PrivateData
|
||||
{
|
||||
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;
|
||||
|
||||
qreal dragMargin = qskDefaultDragMargin();
|
||||
Qt::Edge edge;
|
||||
};
|
||||
|
||||
QskDrawer::QskDrawer( QQuickItem* parentItem )
|
||||
: QskDrawer( Qt::LeftEdge, parentItem )
|
||||
{
|
||||
}
|
||||
|
||||
QskDrawer::QskDrawer( Qt::Edge edge, QQuickItem* parentItem )
|
||||
: Inherited ( parentItem )
|
||||
, m_data( new PrivateData )
|
||||
, m_data( new PrivateData( edge ) )
|
||||
{
|
||||
#if 1
|
||||
setZ( 1 );
|
||||
#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 );
|
||||
setInteractive( true );
|
||||
setAdjustingToParentGeometry( true );
|
||||
|
||||
connect( this, &QskPopup::transitioningChanged,
|
||||
this, &QQuickItem::setClip );
|
||||
}
|
||||
|
||||
QskDrawer::~QskDrawer()
|
||||
{
|
||||
delete m_data->listener;
|
||||
}
|
||||
|
||||
Qt::Edge QskDrawer::edge() const
|
||||
|
@ -227,9 +360,98 @@ void QskDrawer::itemChange( QQuickItem::ItemChange change,
|
|||
if ( parentItem() && isInteractive() )
|
||||
qskCatchMouseEvents( parentItem() );
|
||||
|
||||
m_data->resetListener( this );
|
||||
break;
|
||||
}
|
||||
|
||||
case QQuickItem::ItemVisibleHasChanged:
|
||||
{
|
||||
m_data->resetListener( this );
|
||||
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"
|
||||
|
|
|
@ -6,13 +6,13 @@
|
|||
#ifndef 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
|
||||
|
||||
using Inherited = QskSlideIn;
|
||||
using Inherited = QskPopup;
|
||||
|
||||
Q_PROPERTY( Qt::Edge edge READ edge WRITE setEdge NOTIFY edgeChanged )
|
||||
|
||||
|
@ -24,10 +24,12 @@ class QSK_EXPORT QskDrawer : public QskSlideIn
|
|||
|
||||
public:
|
||||
QskDrawer( QQuickItem* = nullptr );
|
||||
QskDrawer( Qt::Edge, QQuickItem* = nullptr );
|
||||
|
||||
~QskDrawer() override;
|
||||
|
||||
void setEdge( Qt::Edge );
|
||||
Qt::Edge edge() const override final;
|
||||
Qt::Edge edge() const;
|
||||
|
||||
void setInteractive( bool );
|
||||
bool isInteractive() const;
|
||||
|
@ -36,14 +38,19 @@ class QSK_EXPORT QskDrawer : public QskSlideIn
|
|||
void resetDragMargin();
|
||||
qreal dragMargin() const;
|
||||
|
||||
QRectF clipRect() const override;
|
||||
|
||||
Q_SIGNALS:
|
||||
void edgeChanged( Qt::Edge );
|
||||
void dragMarginChanged( qreal );
|
||||
void interactiveChanged( bool );
|
||||
|
||||
protected:
|
||||
void itemChange( ItemChange, const ItemChangeData& ) override;
|
||||
void gestureEvent( QskGestureEvent* ) override;
|
||||
void itemChange( ItemChange, const ItemChangeData& ) override;
|
||||
|
||||
void updateResources() override;
|
||||
void updateNode( QSGNode* ) override;
|
||||
|
||||
private:
|
||||
class PrivateData;
|
||||
|
|
|
@ -18,6 +18,10 @@
|
|||
#include <qvariant.h>
|
||||
#include <qeventloop.h>
|
||||
|
||||
QSK_QT_PRIVATE_BEGIN
|
||||
#include <private/qquickitem_p.h>
|
||||
QSK_QT_PRIVATE_END
|
||||
|
||||
QSK_SUBCONTROL( QskMenu, Overlay )
|
||||
QSK_SUBCONTROL( QskMenu, Panel )
|
||||
QSK_SUBCONTROL( QskMenu, Segment )
|
||||
|
@ -62,13 +66,17 @@ QskMenu::QskMenu( QQuickItem* parent )
|
|||
setPopupFlag( QskPopup::CloseOnPressOutside, true );
|
||||
setPopupFlag( QskPopup::DeleteOnClose, true );
|
||||
|
||||
setPlacementPolicy( QskPlacementPolicy::Ignore );
|
||||
setSubcontrolProxy( Inherited::Overlay, Overlay );
|
||||
|
||||
initSizePolicy( QskSizePolicy::Fixed, QskSizePolicy::Fixed );
|
||||
|
||||
// we hide the focus indicator while sliding
|
||||
connect( this, &QskMenu::transitioningChanged, this,
|
||||
&QskControl::focusIndicatorRectChanged );
|
||||
connect( this, &QskMenu::transitioningChanged,
|
||||
this, &QskControl::focusIndicatorRectChanged );
|
||||
|
||||
connect( this, &QskPopup::transitioningChanged,
|
||||
this, &QQuickItem::setClip );
|
||||
|
||||
connect( this, &QskMenu::opened, this,
|
||||
[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
|
||||
|
||||
// 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();
|
||||
}
|
||||
|
||||
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 )
|
||||
{
|
||||
if( m_data->currentIndex < 0 )
|
||||
|
@ -434,8 +485,6 @@ void QskMenu::mouseReleaseEvent( QMouseEvent* event )
|
|||
|
||||
void QskMenu::aboutToShow()
|
||||
{
|
||||
setGeometry( QRectF( m_data->origin, sizeConstraint() ) );
|
||||
|
||||
if ( m_data->currentIndex < 0 )
|
||||
{
|
||||
if ( !m_data->actions.isEmpty() )
|
||||
|
|
|
@ -81,6 +81,8 @@ class QSK_EXPORT QskMenu : public QskPopup
|
|||
|
||||
bool isPressed() const;
|
||||
|
||||
QRectF clipRect() const override;
|
||||
|
||||
Q_INVOKABLE int exec();
|
||||
|
||||
Q_SIGNALS:
|
||||
|
@ -115,6 +117,9 @@ class QSK_EXPORT QskMenu : public QskPopup
|
|||
void aboutToShow() override;
|
||||
void trigger( int );
|
||||
|
||||
void updateResources() override;
|
||||
void updateNode( QSGNode* ) override;
|
||||
|
||||
private:
|
||||
void traverse( int steps );
|
||||
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
#include "QskLabelData.h"
|
||||
|
||||
#include "QskSGNode.h"
|
||||
#include "QskSlideInNode.h"
|
||||
|
||||
#include <qfontmetrics.h>
|
||||
#include <qmath.h>
|
||||
|
@ -223,26 +222,13 @@ QSGNode* QskMenuSkinlet::updateSubNode(
|
|||
{
|
||||
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 );
|
||||
|
||||
auto rect = popup->contentsRect();
|
||||
if ( rect.isEmpty() )
|
||||
return nullptr;
|
||||
|
||||
auto slideInNode = QskSGNode::ensureNode< QskSlideInNode >( node );
|
||||
|
||||
slideInNode->updateTranslation(
|
||||
rect, Qt::TopEdge, popup->transitioningFactor() );
|
||||
|
||||
auto contentsNode = updateContentsNode( popup, slideInNode->contentsNode() );
|
||||
slideInNode->setContentsNode( contentsNode );
|
||||
|
||||
return slideInNode;
|
||||
return updateContentsNode( popup, node );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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