much easier implementation used - the only hack is about updating the
clip node manually for each updatePaintNode
This commit is contained in:
parent
a9621f19ed
commit
4afe56990b
|
@ -9,6 +9,7 @@
|
|||
#include <QskControl.h>
|
||||
#include <QskDrawer.h>
|
||||
#include <QskPushButton.h>
|
||||
#include <QskFocusIndicator.h>
|
||||
#include <QskWindow.h>
|
||||
#include <QskEvent.h>
|
||||
#include <QskAnimationHint.h>
|
||||
|
@ -30,31 +31,32 @@ namespace
|
|||
content->setAutoLayoutChildren( true );
|
||||
content->setMargins( 20 );
|
||||
|
||||
auto button = new QskPushButton( "Push Me", content );
|
||||
button->setSizePolicy( QskSizePolicy::Fixed, QskSizePolicy::Fixed );
|
||||
button->setLayoutAlignmentHint( Qt::AlignCenter );
|
||||
|
||||
const auto size = content->sizeHint();
|
||||
|
||||
switch( edge )
|
||||
{
|
||||
case Qt::LeftEdge:
|
||||
content->setBackgroundColor( QskRgb::Tomato );
|
||||
content->setFixedWidth( 100 );
|
||||
break;
|
||||
|
||||
case Qt::RightEdge:
|
||||
content->setFixedWidth( 200 );
|
||||
content->setFixedWidth( 1.5 * size.width() );
|
||||
content->setBackgroundColor( QskRgb::Orchid );
|
||||
break;
|
||||
|
||||
case Qt::TopEdge:
|
||||
content->setFixedHeight( 100 );
|
||||
content->setBackgroundColor( QskRgb::Chartreuse );
|
||||
break;
|
||||
|
||||
case Qt::BottomEdge:
|
||||
content->setFixedHeight( 200 );
|
||||
content->setFixedHeight( 2 * size.height() );
|
||||
content->setBackgroundColor( QskRgb::Wheat );
|
||||
break;
|
||||
}
|
||||
|
||||
auto button = new QskPushButton( "Push Me", content );
|
||||
button->setPreferredHeight( 100 );
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -127,6 +129,7 @@ int main( int argc, char* argv[] )
|
|||
SkinnyShortcut::enable( SkinnyShortcut::AllShortcuts );
|
||||
|
||||
QskWindow window;
|
||||
window.addItem( new QskFocusIndicator() );
|
||||
window.addItem( new MainBox() );
|
||||
window.resize( 600, 600 );
|
||||
window.show();
|
||||
|
|
|
@ -51,44 +51,6 @@ static bool qskCheckDirection( Qt::Edge edge, const QskPanGesture* gesture )
|
|||
return false;
|
||||
}
|
||||
|
||||
static inline QRectF qskAlignedToEdge(
|
||||
const QRectF& rect, const QSizeF& size, Qt::Edge edge )
|
||||
{
|
||||
QRectF r( 0.0, 0.0, size.width(), size.height() );
|
||||
|
||||
switch( edge )
|
||||
{
|
||||
case Qt::LeftEdge:
|
||||
{
|
||||
r.setHeight( rect.height() );
|
||||
r.moveRight( rect.left() + size.width() );
|
||||
break;
|
||||
}
|
||||
case Qt::RightEdge:
|
||||
{
|
||||
r.setHeight( rect.height() );
|
||||
r.moveLeft( rect.right() - size.width() );
|
||||
break;
|
||||
}
|
||||
|
||||
case Qt::TopEdge:
|
||||
{
|
||||
r.setWidth( rect.width() );
|
||||
r.moveBottom( rect.top() + size.height() );
|
||||
break;
|
||||
}
|
||||
|
||||
case Qt::BottomEdge:
|
||||
{
|
||||
r.setWidth( rect.width() );
|
||||
r.moveTop( rect.bottom() - size.height() );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
class GestureRecognizer : public QskPanGestureRecognizer
|
||||
|
@ -231,24 +193,6 @@ qreal QskDrawer::dragMargin() const
|
|||
return m_data->dragMargin;
|
||||
}
|
||||
|
||||
bool QskDrawer::event( QEvent* event )
|
||||
{
|
||||
if ( event->type() == QEvent::PolishRequest )
|
||||
{
|
||||
if ( const auto item = parentItem() )
|
||||
{
|
||||
auto r = qskItemRect( item );
|
||||
r = qskAlignedToEdge( r, sizeConstraint( Qt::PreferredSize ), edge() );
|
||||
|
||||
setGeometry( r );
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return Inherited::event( event );
|
||||
}
|
||||
|
||||
void QskDrawer::gestureEvent( QskGestureEvent* event )
|
||||
{
|
||||
if ( event->gesture()->type() == QskGesture::Pan )
|
||||
|
|
|
@ -42,8 +42,6 @@ class QSK_EXPORT QskDrawer : public QskSlideIn
|
|||
void interactiveChanged( bool );
|
||||
|
||||
protected:
|
||||
bool event( QEvent* ) override;
|
||||
|
||||
void itemChange( ItemChange, const ItemChangeData& ) override;
|
||||
void gestureEvent( QskGestureEvent* ) override;
|
||||
|
||||
|
|
|
@ -76,20 +76,28 @@ static inline QVariant qskAligned05( const QVariant& value )
|
|||
|
||||
#endif
|
||||
|
||||
static inline bool qskCheckReceiverThread( const QObject* receiver )
|
||||
static inline void qskSendAnimatorEvent(
|
||||
const QskAspect aspect, int index, bool on, QObject* receiver )
|
||||
{
|
||||
/*
|
||||
QskInputPanelSkinlet changes the skin state, what leads to
|
||||
sending events from the wrong thread. Until we have fixed it
|
||||
let's block sending the event to avoid running into assertions
|
||||
in QCoreApplication::sendEvent
|
||||
*/
|
||||
const auto state = on ? QskAnimatorEvent::Started : QskAnimatorEvent::Terminated;
|
||||
|
||||
const QThread* thread = receiver->thread();
|
||||
if ( thread == nullptr )
|
||||
return true;
|
||||
const auto thread = receiver->thread();
|
||||
if ( thread && ( thread != QThread::currentThread() ) )
|
||||
{
|
||||
/*
|
||||
QskInputPanelSkinlet changes the skin state, what leads to
|
||||
sending events from the wrong thread. We can't use
|
||||
QCoreApplication::sendEvent then, TODO ...
|
||||
*/
|
||||
|
||||
return ( thread == QThread::currentThread() );
|
||||
auto event = new QskAnimatorEvent( aspect, index, state );
|
||||
QCoreApplication::postEvent( receiver, event );
|
||||
}
|
||||
else
|
||||
{
|
||||
QskAnimatorEvent event( aspect, index, state );
|
||||
QCoreApplication::sendEvent( receiver, &event );
|
||||
}
|
||||
}
|
||||
|
||||
QskHintAnimator::QskHintAnimator() noexcept
|
||||
|
@ -338,11 +346,7 @@ void QskHintAnimatorTable::start( QskControl* control,
|
|||
|
||||
animator->start();
|
||||
|
||||
if ( qskCheckReceiverThread( control ) )
|
||||
{
|
||||
QskAnimatorEvent event( aspect, index, QskAnimatorEvent::Started );
|
||||
QCoreApplication::sendEvent( control, &event );
|
||||
}
|
||||
qskSendAnimatorEvent( aspect, index, true, control );
|
||||
}
|
||||
|
||||
const QskHintAnimator* QskHintAnimatorTable::animator( QskAspect aspect, int index ) const
|
||||
|
@ -390,15 +394,7 @@ bool QskHintAnimatorTable::cleanup()
|
|||
it = animators.erase( it );
|
||||
|
||||
if ( control )
|
||||
{
|
||||
if ( qskCheckReceiverThread( control ) )
|
||||
{
|
||||
auto event = new QskAnimatorEvent(
|
||||
aspect, index, QskAnimatorEvent::Terminated );
|
||||
|
||||
QCoreApplication::postEvent( control, event );
|
||||
}
|
||||
}
|
||||
qskSendAnimatorEvent( aspect, index, false, control );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -4,14 +4,14 @@
|
|||
*****************************************************************************/
|
||||
|
||||
#include "QskSlideIn.h"
|
||||
#include "QskAnimationHint.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 )
|
||||
static QPointF qskSlideInTranslation( const QskSlideIn* slideIn, const QSizeF& size )
|
||||
{
|
||||
const auto ratio = 1.0 - slideIn->transitioningFactor();
|
||||
|
||||
|
@ -21,59 +21,44 @@ static QPointF qskSlideInTranslation( const QskSlideIn* slideIn )
|
|||
switch( slideIn->edge() )
|
||||
{
|
||||
case Qt::LeftEdge:
|
||||
dx = -ratio * slideIn->width();
|
||||
dx = -ratio * size.width();
|
||||
break;
|
||||
|
||||
case Qt::RightEdge:
|
||||
dx = ratio * slideIn->width();
|
||||
dx = ratio * size.width();
|
||||
break;
|
||||
|
||||
case Qt::TopEdge:
|
||||
dy = -ratio * slideIn->height();
|
||||
dy = -ratio * size.height();
|
||||
break;
|
||||
|
||||
case Qt::BottomEdge:
|
||||
dy = ratio * slideIn->height();
|
||||
dy = ratio * size.height();
|
||||
break;
|
||||
}
|
||||
|
||||
return QPointF( dx, dy );
|
||||
}
|
||||
|
||||
static inline QRectF qskUnboundedClipRect( const QRectF& rect, Qt::Edge edge )
|
||||
static inline QRectF qskAlignedToEdge(
|
||||
const QRectF& r, const QSizeF& sz, Qt::Edge edge )
|
||||
{
|
||||
/*
|
||||
When sliding we want to clip against the edge, where the drawer
|
||||
slides in/out. However the size of the slidein is often smaller than the
|
||||
one of the parent and we would clip the overlay node
|
||||
and all content, that is located outside the drawer geometry.
|
||||
|
||||
So we expand the clip rectangle to "unbounded" at the other edges.
|
||||
*/
|
||||
constexpr qreal d = 1e6;
|
||||
|
||||
QRectF r( -d, -d, 2.0 * d, 2.0 * d );
|
||||
|
||||
switch( edge )
|
||||
{
|
||||
case Qt::LeftEdge:
|
||||
r.setLeft( rect.left() );
|
||||
break;
|
||||
return QRectF( r.left(), r.top(), sz.width(), r.height() );
|
||||
|
||||
case Qt::RightEdge:
|
||||
r.setRight( rect.right() );
|
||||
break;
|
||||
return QRectF( r.right() - sz.width(), r.top(), sz.width(), r.height() );
|
||||
|
||||
case Qt::TopEdge:
|
||||
r.setTop( rect.top() );
|
||||
break;
|
||||
return QRectF( r.left(), r.top(), r.width(), sz.height() );
|
||||
|
||||
case Qt::BottomEdge:
|
||||
r.setBottom( rect.bottom() );
|
||||
break;
|
||||
return QRectF( r.left(), r.bottom() - sz.height(), r.width(), sz.height() );
|
||||
}
|
||||
|
||||
return r;
|
||||
return QRectF();
|
||||
}
|
||||
|
||||
namespace
|
||||
|
@ -106,8 +91,7 @@ namespace
|
|||
private:
|
||||
void adjust()
|
||||
{
|
||||
QEvent event( QEvent::PolishRequest );
|
||||
QCoreApplication::sendEvent( m_adjustedItem, &event );
|
||||
m_adjustedItem->polish();
|
||||
}
|
||||
|
||||
void setEnabled( bool on )
|
||||
|
@ -159,7 +143,7 @@ QskSlideIn::QskSlideIn( QQuickItem* parentItem )
|
|||
setPlacementPolicy( QskPlacementPolicy::Ignore );
|
||||
|
||||
connect( this, &QskPopup::transitioningChanged,
|
||||
this, &QskSlideIn::setClip );
|
||||
this, &QQuickItem::setClip );
|
||||
}
|
||||
|
||||
QskSlideIn::~QskSlideIn()
|
||||
|
@ -197,17 +181,89 @@ void QskSlideIn::itemChange( QQuickItem::ItemChange change,
|
|||
}
|
||||
}
|
||||
|
||||
QRectF QskSlideIn::clipRect() const
|
||||
void QskSlideIn::updateResources()
|
||||
{
|
||||
if ( !isTransitioning() )
|
||||
return Inherited::clipRect();
|
||||
Inherited::updateResources();
|
||||
|
||||
return qskUnboundedClipRect( rect(), edge() );
|
||||
/*
|
||||
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::layoutRectForSize( const QSizeF& size ) const
|
||||
QRectF QskSlideIn::clipRect() const
|
||||
{
|
||||
return QRectF( qskSlideInTranslation( this ), size );
|
||||
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"
|
||||
|
|
|
@ -25,12 +25,12 @@ class QSK_EXPORT QskSlideIn : public QskPopup
|
|||
void setAdjustingToParentGeometry( bool on );
|
||||
bool isAdjustingToParentGeometry() const;
|
||||
|
||||
QRectF layoutRectForSize( const QSizeF& ) const override;
|
||||
|
||||
protected:
|
||||
QskSlideIn( QQuickItem* = nullptr );
|
||||
|
||||
void itemChange( ItemChange, const ItemChangeData& ) override;
|
||||
void updateResources() override;
|
||||
void updateNode( QSGNode* ) override;
|
||||
|
||||
private:
|
||||
class PrivateData;
|
||||
|
|
Loading…
Reference in New Issue