using gestures to open the drawer

This commit is contained in:
Uwe Rathmann 2023-10-09 09:02:36 +02:00
parent ef68c66b10
commit bfff8c3fe1
8 changed files with 104 additions and 82 deletions

View File

@ -17,32 +17,6 @@
namespace namespace
{ {
inline qreal distanceToEdge(
const QRectF& rect, const QPointF& pos, int edge )
{
qreal dt = 10e6;
switch( edge )
{
case Qt::TopEdge:
dt = pos.y() - rect.top();
break;
case Qt::BottomEdge:
dt = rect.bottom() - pos.y();
break;
case Qt::LeftEdge:
dt = pos.x() - rect.left();
break;
case Qt::RightEdge:
dt = rect.right() - pos.x();
break;
}
return std::abs( dt );
}
class Drawer : public QskDrawer class Drawer : public QskDrawer
{ {
public: public:
@ -50,7 +24,7 @@ namespace
: QskDrawer( parent ) : QskDrawer( parent )
{ {
#if 1 #if 1
setAnimationHint( Panel | QskAspect::Position, 2000 ); setAnimationHint( Panel | QskAspect::Position, 1000 );
#endif #endif
setEdge( edge ); setEdge( edge );
@ -101,51 +75,6 @@ namespace
const auto edge = static_cast< Qt::Edge >( 1 << i ); const auto edge = static_cast< Qt::Edge >( 1 << i );
m_drawers[i] = new Drawer( edge, this ); m_drawers[i] = new Drawer( edge, this );
} }
setAcceptedMouseButtons( Qt::LeftButton );
}
protected:
virtual bool contains( const QPointF& pos ) const
{
if ( auto control = qskControlCast( parentItem() ) )
{
// we want to catch clicks on the margins of the parent
auto r = rect();
if ( !r.contains( pos ) )
{
r = r.marginsAdded( control->margins() );
return r.contains( pos );
}
return false;
}
return QskControl::contains( pos );
}
void mousePressEvent( QMouseEvent* event ) override
{
const auto pos = qskMousePosition( event );
int drawerIndex = -1;
qreal minDist = 10e6;
for ( int i = 0; i < 4; i++ )
{
const auto edge = static_cast< Qt::Edge >( 1 << i );
const auto dist = distanceToEdge( rect(), pos, edge );
if ( dist < minDist )
{
minDist = dist;
drawerIndex = i;
}
}
if ( drawerIndex >= 0 )
m_drawers[drawerIndex]->open();
} }
private: private:

View File

@ -7,6 +7,10 @@
#include "QskAspect.h" #include "QskAspect.h"
#include "QskAnimationHint.h" #include "QskAnimationHint.h"
#include "QskQuick.h" #include "QskQuick.h"
#include "QskEvent.h"
#include "QskPanGestureRecognizer.h"
#include "QskGesture.h"
QSK_QT_PRIVATE_BEGIN QSK_QT_PRIVATE_BEGIN
#include <private/qquickitem_p.h> #include <private/qquickitem_p.h>
@ -77,6 +81,49 @@ namespace
private: private:
QskDrawer* m_drawer = nullptr; QskDrawer* m_drawer = nullptr;
}; };
class GestureRecognizer : public QskPanGestureRecognizer
{
using Inherited = QskPanGestureRecognizer;
public:
GestureRecognizer( QskDrawer* drawer )
: QskPanGestureRecognizer( drawer )
{
setWatchedItem( drawer->parentItem() );
setTargetItem( drawer );
}
protected:
QRectF gestureRect() const override
{
auto drawer = qobject_cast< QskDrawer* >( parent() );
const auto dist = 50;
auto rect = qskItemRect( watchedItem() );
switch( drawer->edge() )
{
case Qt::LeftEdge:
rect.setRight( rect.left() + dist );
break;
case Qt::RightEdge:
rect.setLeft( rect.right() - dist );
break;
case Qt::TopEdge:
rect.setBottom( rect.top() + dist );
break;
case Qt::BottomEdge:
rect.setTop( rect.bottom() - dist );
break;
}
return rect;
}
};
} }
class QskDrawer::PrivateData class QskDrawer::PrivateData
@ -108,6 +155,11 @@ QskDrawer::QskDrawer( QQuickItem* parentItem )
setPlacementPolicy( QskPlacementPolicy::Ignore ); setPlacementPolicy( QskPlacementPolicy::Ignore );
if ( parentItem ) if ( parentItem )
m_data->listener = new GeometryListener( this ); m_data->listener = new GeometryListener( this );
(void) new GestureRecognizer( this );
#if 1
parentItem->setAcceptedMouseButtons( Qt::LeftButton );
#endif
} }
QskDrawer::~QskDrawer() QskDrawer::~QskDrawer()
@ -130,6 +182,20 @@ void QskDrawer::setEdge( Qt::Edge edge )
edgeChanged( edge ); edgeChanged( edge );
} }
void QskDrawer::gestureEvent( QskGestureEvent* event )
{
if ( event->gesture()->type() == QskGesture::Pan )
{
const auto gesture = static_cast< const QskPanGesture* >( event->gesture().get() );
if ( gesture->state() == QskGesture::Finished )
open();
return;
}
Inherited::gestureEvent( event );
}
QRectF QskDrawer::layoutRectForSize( const QSizeF& size ) const QRectF QskDrawer::layoutRectForSize( const QSizeF& size ) const
{ {
return Inherited::layoutRectForSize( size ); return Inherited::layoutRectForSize( size );

View File

@ -36,6 +36,8 @@ class QSK_EXPORT QskDrawer : public QskPopup
void aboutToShow() override; void aboutToShow() override;
void itemChange( ItemChange, const ItemChangeData& ) override; void itemChange( ItemChange, const ItemChangeData& ) override;
void gestureEvent( QskGestureEvent* ) override;
private: private:
void startFading( bool ); void startFading( bool );

View File

@ -69,6 +69,9 @@ class QskGestureRecognizer::PrivateData
} }
QQuickItem* watchedItem = nullptr; QQuickItem* watchedItem = nullptr;
#if 1
QQuickItem* targetItem = nullptr; // QPointer ???
#endif
QVector< QMouseEvent* > pendingEvents; QVector< QMouseEvent* > pendingEvents;
@ -121,6 +124,16 @@ QQuickItem* QskGestureRecognizer::watchedItem() const
return m_data->watchedItem; return m_data->watchedItem;
} }
void QskGestureRecognizer::setTargetItem( QQuickItem* item )
{
m_data->targetItem = item;
}
QQuickItem* QskGestureRecognizer::targetItem() const
{
return m_data->targetItem;
}
void QskGestureRecognizer::setAcceptedMouseButtons( Qt::MouseButtons buttons ) void QskGestureRecognizer::setAcceptedMouseButtons( Qt::MouseButtons buttons )
{ {
m_data->buttons = buttons; m_data->buttons = buttons;

View File

@ -43,11 +43,16 @@ class QSK_EXPORT QskGestureRecognizer : public QObject
QskGestureRecognizer( QObject* parent = nullptr ); QskGestureRecognizer( QObject* parent = nullptr );
~QskGestureRecognizer() override; ~QskGestureRecognizer() override;
bool eventFilter( QObject* object, QEvent* event) override; bool eventFilter( QObject*, QEvent* ) override;
// the item where the gesture happens
void setWatchedItem( QQuickItem* ); void setWatchedItem( QQuickItem* );
QQuickItem* watchedItem() const; QQuickItem* watchedItem() const;
// the item processing the gesture events
void setTargetItem( QQuickItem* );
QQuickItem* targetItem() const;
// Qt::NoButton means: all buttons accepted // Qt::NoButton means: all buttons accepted
void setAcceptedMouseButtons( Qt::MouseButtons ); void setAcceptedMouseButtons( Qt::MouseButtons );
Qt::MouseButtons acceptedMouseButtons() const; Qt::MouseButtons acceptedMouseButtons() const;

View File

@ -7,10 +7,11 @@
#include "QskEvent.h" #include "QskEvent.h"
#include "QskGesture.h" #include "QskGesture.h"
#include <qcoreapplication.h>
#include <qline.h> #include <qline.h>
#include <qmath.h> #include <qmath.h>
#include <qquickitem.h> #include <qquickitem.h>
#include <qguiapplication.h>
#include <qstylehints.h>
static inline bool qskIsInOrientation( static inline bool qskIsInOrientation(
const QPointF& from, const QPointF& to, Qt::Orientations orientations ) const QPointF& from, const QPointF& to, Qt::Orientations orientations )
@ -60,9 +61,14 @@ static inline qreal qskAngle(
} }
static void qskSendPanGestureEvent( static void qskSendPanGestureEvent(
QQuickItem* item, QskGesture::State state, qreal velocity, qreal angle, QskGestureRecognizer* recognizer, QskGesture::State state,
const QPointF& origin, const QPointF& lastPosition, const QPointF& position ) qreal velocity, qreal angle, const QPointF& origin,
const QPointF& lastPosition, const QPointF& position )
{ {
auto item = recognizer->targetItem();
if ( item == nullptr )
item = recognizer->watchedItem();
auto gesture = std::make_shared< QskPanGesture >(); auto gesture = std::make_shared< QskPanGesture >();
gesture->setState( state ); gesture->setState( state );
@ -146,7 +152,7 @@ class QskPanGestureRecognizer::PrivateData
public: public:
Qt::Orientations orientations = Qt::Horizontal | Qt::Vertical; Qt::Orientations orientations = Qt::Horizontal | Qt::Vertical;
int minDistance = 15; int minDistance = QGuiApplication::styleHints()->startDragDistance() + 5;
quint64 timestampVelocity = 0.0; // timestamp of the last mouse event quint64 timestampVelocity = 0.0; // timestamp of the last mouse event
qreal angle = 0.0; qreal angle = 0.0;
@ -243,12 +249,12 @@ void QskPanGestureRecognizer::processMove( const QPointF& pos, quint64 timestamp
if ( started ) if ( started )
{ {
qskSendPanGestureEvent( watchedItem(), QskGesture::Started, qskSendPanGestureEvent( this, QskGesture::Started,
velocity, m_data->angle, m_data->origin, m_data->origin, m_data->pos ); velocity, m_data->angle, m_data->origin, m_data->origin, m_data->pos );
} }
else else
{ {
qskSendPanGestureEvent( watchedItem(), QskGesture::Updated, qskSendPanGestureEvent( this, QskGesture::Updated,
velocity, m_data->angle, m_data->origin, oldPos, m_data->pos ); velocity, m_data->angle, m_data->origin, oldPos, m_data->pos );
} }
} }
@ -261,7 +267,7 @@ void QskPanGestureRecognizer::processRelease( const QPointF&, quint64 timestamp
const ulong elapsedTotal = timestamp - timestampStarted(); const ulong elapsedTotal = timestamp - timestampStarted();
const qreal velocity = m_data->velocityTracker.velocity( elapsedTotal ); const qreal velocity = m_data->velocityTracker.velocity( elapsedTotal );
qskSendPanGestureEvent( watchedItem(), QskGesture::Finished, qskSendPanGestureEvent( this, QskGesture::Finished,
velocity, m_data->angle, m_data->origin, m_data->pos, m_data->pos ); velocity, m_data->angle, m_data->origin, m_data->pos, m_data->pos );
} }
} }

View File

@ -23,11 +23,12 @@ class QSK_EXPORT QskPanGestureRecognizer : public QskGestureRecognizer
void setOrientations( Qt::Orientations ); void setOrientations( Qt::Orientations );
Qt::Orientations orientations() const; Qt::Orientations orientations() const;
private: protected:
void processPress( const QPointF&, quint64 timestamp, bool isFinal ) override; void processPress( const QPointF&, quint64 timestamp, bool isFinal ) override;
void processMove( const QPointF&, quint64 timestamp ) override; void processMove( const QPointF&, quint64 timestamp ) override;
void processRelease( const QPointF&, quint64 timestamp ) override; void processRelease( const QPointF&, quint64 timestamp ) override;
private:
class PrivateData; class PrivateData;
std::unique_ptr< PrivateData > m_data; std::unique_ptr< PrivateData > m_data;
}; };

View File

@ -121,7 +121,7 @@ namespace
scheme = Qt::ColorScheme::Unknown; scheme = Qt::ColorScheme::Unknown;
} }
const auto systemScheme = qGuiApp->styleHints()->colorScheme(); const auto systemScheme = QGuiApplication::styleHints()->colorScheme();
if( scheme == systemScheme ) if( scheme == systemScheme )
{ {