Squashed commit of the following:
commit c6aec22cbdbed31955e70ea73fc6863d9369ba22
Author: Uwe Rathmann <Uwe.Rathmann@tigertal.de>
Date: Tue Oct 24 11:34:55 2023 +0200
wip
commit 473946633e150129a3ba67ea321bda23fcd0f5a7
Author: Uwe Rathmann <Uwe.Rathmann@tigertal.de>
Date: Tue Oct 24 11:28:23 2023 +0200
wip
commit 368f6edac32457d6a060c2f2e8a722c0d15bf35c
Author: Uwe Rathmann <Uwe.Rathmann@tigertal.de>
Date: Tue Oct 24 11:26:46 2023 +0200
wip
commit eccffafec006d471cc691f3d10143219ec263c63
Author: Uwe Rathmann <Uwe.Rathmann@tigertal.de>
Date: Tue Oct 24 11:22:01 2023 +0200
wip
commit c5ae5025d4ed0ea7184fb8b4fa97df7f3ca54c0e
Author: Uwe Rathmann <Uwe.Rathmann@tigertal.de>
Date: Tue Oct 24 10:53:09 2023 +0200
wip
commit 174b1d946067c5b5c0bf4a9982d7b3f7f717d263
Author: Uwe Rathmann <Uwe.Rathmann@tigertal.de>
Date: Tue Oct 24 10:51:54 2023 +0200
wip
commit 3e89f17ea971adc19c89cca0eb38dc3e973a090e
Author: Uwe Rathmann <Uwe.Rathmann@tigertal.de>
Date: Tue Oct 24 10:15:17 2023 +0200
wip
commit 499a13ab74501c24f1e0effe56dfb9cf9ff9bf63
Author: Uwe Rathmann <Uwe.Rathmann@tigertal.de>
Date: Tue Oct 24 10:03:55 2023 +0200
wip
commit 935ffc6d23dcd20a2c70898f28063fcdffea0795
Merge: 82f44d41 0cf60b41
Author: Uwe Rathmann <Uwe.Rathmann@tigertal.de>
Date: Mon Oct 23 10:49:32 2023 +0200
Merge branch 'drawer' into Overlay
commit 0cf60b414cee9a26fa5a53f05938e69ab39294d7
Merge: da76eb6d 2013338d
Author: Uwe Rathmann <Uwe.Rathmann@tigertal.de>
Date: Mon Oct 23 10:49:13 2023 +0200
Merge branch 'features/drawer' into drawer
commit 82f44d41c03f8cedab8b1bf3f1c164dfa65200cf
Author: Uwe Rathmann <Uwe.Rathmann@tigertal.de>
Date: Sun Oct 22 10:44:50 2023 +0200
wip
commit 3b254ff4551d457e1581b5dbb85fae2dcf55e2cc
Author: Uwe Rathmann <Uwe.Rathmann@tigertal.de>
Date: Sun Oct 22 10:43:15 2023 +0200
wip
commit 81e2bd8b35fb4a361e67f8a56870d99ea05ffa4d
Author: Uwe Rathmann <Uwe.Rathmann@tigertal.de>
Date: Sun Oct 22 09:50:07 2023 +0200
wip
commit 916f5ca888f675bdded0b97b763de02c8c6c12ff
Author: Uwe Rathmann <Uwe.Rathmann@tigertal.de>
Date: Fri Oct 20 17:08:53 2023 +0200
wip
commit b3e8fd4d7cf4eab710b7781bb1e9dc730548d51b
Author: Uwe Rathmann <Uwe.Rathmann@tigertal.de>
Date: Fri Oct 20 17:03:12 2023 +0200
wip
commit da76eb6df5353029856084e6306db32cb2712b6b
Author: Uwe Rathmann <Uwe.Rathmann@tigertal.de>
Date: Fri Oct 20 16:05:19 2023 +0200
wip
commit 72fbd0b6fad4b33e09643e5a2c67833f6e2c4abd
Author: Uwe Rathmann <Uwe.Rathmann@tigertal.de>
Date: Fri Oct 20 15:21:14 2023 +0200
wip
commit 7f899d67d6c8f7f98212030ac0e83e86581cefff
Author: Uwe Rathmann <Uwe.Rathmann@tigertal.de>
Date: Fri Oct 20 15:00:42 2023 +0200
wip
commit 72872cad2a0749afe9c901775c18459ac4cd956a
Author: Uwe Rathmann <Uwe.Rathmann@tigertal.de>
Date: Fri Oct 20 13:49:05 2023 +0200
wip
commit f16572e29a5fe8851479e2be6e04ff2d991e9ebd
Author: Uwe Rathmann <Uwe.Rathmann@tigertal.de>
Date: Fri Oct 20 13:40:47 2023 +0200
wip
commit 4300a2cf225554f93cb492062f89af51dcc5df64
Author: Uwe Rathmann <Uwe.Rathmann@tigertal.de>
Date: Fri Oct 20 13:34:37 2023 +0200
wip
commit c85150bcb98934b144e4453f12fbe37c4900049f
Author: Uwe Rathmann <Uwe.Rathmann@tigertal.de>
Date: Fri Oct 20 13:32:44 2023 +0200
wip
commit 00d069d134319b0c3fb6d192cba32c31640e161f
Author: Uwe Rathmann <Uwe.Rathmann@tigertal.de>
Date: Fri Oct 20 13:21:45 2023 +0200
wip
commit 36b4a203a3d761d4a3a5e17e1ba2deb7f9b37740
Author: Uwe Rathmann <Uwe.Rathmann@tigertal.de>
Date: Fri Oct 20 12:52:52 2023 +0200
wip
commit e27fa8af6ddc233862ec431e2c129299e24f4ee0
Author: Uwe Rathmann <Uwe.Rathmann@tigertal.de>
Date: Fri Oct 20 11:12:42 2023 +0200
wip
commit 579a45149a92ffef72c569c79456a3a2c753e37c
Author: Uwe Rathmann <Uwe.Rathmann@tigertal.de>
Date: Fri Oct 20 10:57:51 2023 +0200
QskSlideIn added
This commit is contained in:
parent
2013338dd4
commit
e4b9b8bd1b
|
@ -23,10 +23,6 @@ namespace
|
|||
Drawer( Qt::Edge edge, QQuickItem* parent )
|
||||
: QskDrawer( parent )
|
||||
{
|
||||
#if 1
|
||||
setAnimationHint( transitionAspect(), 1000 );
|
||||
#endif
|
||||
|
||||
setEdge( edge );
|
||||
|
||||
auto content = new QskControl( this );
|
||||
|
|
|
@ -620,12 +620,6 @@ void Editor::setupDialogButtonBoxColors(
|
|||
|
||||
void Editor::setupDrawerMetrics()
|
||||
{
|
||||
using Q = QskDrawer;
|
||||
using A = QskAspect;
|
||||
|
||||
#if 1
|
||||
setAnimation( Q::Panel | A::Metric | A::Position, 200 );
|
||||
#endif
|
||||
}
|
||||
|
||||
void Editor::setupDrawerColors( QskAspect::Section, const QskFluent2Theme& )
|
||||
|
@ -744,7 +738,6 @@ void Editor::setupListViewColors(
|
|||
void Editor::setupMenuMetrics()
|
||||
{
|
||||
using Q = QskMenu;
|
||||
using A = QskAspect;
|
||||
|
||||
setPadding( Q::Panel, { 4, 6, 4, 6 } );
|
||||
setBoxBorderMetrics( Q::Panel, 1 );
|
||||
|
@ -758,14 +751,6 @@ void Editor::setupMenuMetrics()
|
|||
|
||||
setStrutSize( Q::Icon, 12, 12 );
|
||||
setPadding( Q::Icon, { 8, 8, 0, 8 } );
|
||||
|
||||
#if 1
|
||||
setPosition( Q::Panel, 1 );
|
||||
setPosition( Q::Panel | QskPopup::Closed, 0 );
|
||||
|
||||
// copied from Mat3 - what are the correct values for Fluent2 ???
|
||||
setAnimation( Q::Panel | A::Metric, 150 );
|
||||
#endif
|
||||
}
|
||||
|
||||
void Editor::setupMenuColors(
|
||||
|
@ -876,10 +861,14 @@ void Editor::setupPageIndicatorColors(
|
|||
void Editor::setupPopup( const QskFluent2Theme& theme )
|
||||
{
|
||||
using Q = QskPopup;
|
||||
using A = QskAspect;
|
||||
|
||||
const auto& pal = theme.palette;
|
||||
|
||||
setHint( Q::Overlay | A::Style, true );
|
||||
setGradient( Q::Overlay, pal.background.overlay.defaultColor );
|
||||
|
||||
setAnimation( Q::Popup, 200 );
|
||||
}
|
||||
|
||||
void Editor::setupProgressBarMetrics()
|
||||
|
|
|
@ -331,6 +331,8 @@ void Editor::setupPopup()
|
|||
|
||||
setHint( Q::Overlay | A::Style, true );
|
||||
setGradient( Q::Overlay, stateLayerColor( m_pal.outline, 0.8 ) );
|
||||
|
||||
setAnimation( Q::Popup, qskDuration );
|
||||
}
|
||||
|
||||
void Editor::setupMenu()
|
||||
|
@ -378,10 +380,6 @@ void Editor::setupMenu()
|
|||
setColor( Q::Text, m_pal.onSurface );
|
||||
setFontRole( Q::Text, QskMaterial3Skin::M3BodyMedium );
|
||||
|
||||
setPosition( Q::Panel, 1 );
|
||||
setPosition( Q::Panel | QskPopup::Closed, 0 );
|
||||
|
||||
setAnimation( Q::Panel | A::Metric, 150 );
|
||||
setAnimation( Q::Cursor | A::Position | A::Metric, 75, QEasingCurve::OutCubic );
|
||||
}
|
||||
|
||||
|
@ -808,10 +806,6 @@ void Editor::setupDialogButtonBox()
|
|||
|
||||
void Editor::setupDrawer()
|
||||
{
|
||||
using Q = QskDrawer;
|
||||
using A = QskAspect;
|
||||
|
||||
setAnimation( Q::Panel | A::Metric | A::Position, qskDuration );
|
||||
}
|
||||
|
||||
void Editor::setupSlider()
|
||||
|
|
|
@ -409,7 +409,9 @@ void Editor::setupPopup()
|
|||
using Q = QskPopup;
|
||||
|
||||
setHint( Q::Overlay | A::Style, true );
|
||||
setGradient( Q::Overlay, QColor( 220, 220, 220, 150 ) );
|
||||
setGradient( Q::Overlay, qRgba( 220, 220, 220, 150 ) );
|
||||
|
||||
setAnimation( Q::Popup, 200 );
|
||||
}
|
||||
|
||||
void Editor::setupMenu()
|
||||
|
@ -446,10 +448,6 @@ void Editor::setupMenu()
|
|||
setGraphicRole( Q::Icon | Q::Disabled, DisabledSymbol );
|
||||
setGraphicRole( Q::Icon | Q::Selected, CursorSymbol );
|
||||
|
||||
setPosition( Q::Panel, 1 );
|
||||
setPosition( Q::Panel | QskPopup::Closed, 0 );
|
||||
|
||||
setAnimation( Q::Panel | A::Metric, 150 );
|
||||
setAnimation( Q::Cursor | A::Position | A::Metric, 75, QEasingCurve::OutCubic );
|
||||
}
|
||||
|
||||
|
@ -761,10 +759,6 @@ void Editor::setupDialogButtonBox()
|
|||
|
||||
void Editor::setupDrawer()
|
||||
{
|
||||
using A = QskAspect;
|
||||
using Q = QskDrawer;
|
||||
|
||||
setAnimation( Q::Panel | A::Metric | A::Position, qskDuration );
|
||||
}
|
||||
|
||||
void Editor::setupTabButton()
|
||||
|
|
|
@ -210,6 +210,7 @@ list(APPEND HEADERS
|
|||
controls/QskQuickItem.h
|
||||
controls/QskRadioBox.h
|
||||
controls/QskRadioBoxSkinlet.h
|
||||
controls/QskSlideIn.h
|
||||
controls/QskScrollArea.h
|
||||
controls/QskScrollBox.h
|
||||
controls/QskScrollView.h
|
||||
|
@ -316,6 +317,7 @@ list(APPEND SOURCES
|
|||
controls/QskScrollBox.cpp
|
||||
controls/QskScrollView.cpp
|
||||
controls/QskScrollViewSkinlet.cpp
|
||||
controls/QskSlideIn.cpp
|
||||
controls/QskRadioBox.cpp
|
||||
controls/QskRadioBoxSkinlet.cpp
|
||||
controls/QskSegmentedBar.cpp
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
|
||||
#include "QskDrawer.h"
|
||||
#include "QskAspect.h"
|
||||
#include "QskAnimationHint.h"
|
||||
#include "QskQuick.h"
|
||||
#include "QskEvent.h"
|
||||
|
||||
|
@ -15,24 +14,13 @@
|
|||
#include <qguiapplication.h>
|
||||
#include <qstylehints.h>
|
||||
|
||||
QSK_QT_PRIVATE_BEGIN
|
||||
#include <private/qquickitem_p.h>
|
||||
#include <private/qquickitemchangelistener_p.h>
|
||||
QSK_QT_PRIVATE_END
|
||||
|
||||
/*
|
||||
Only used for the sliding in animation. Do we want to
|
||||
introduce a specific panel as background ???
|
||||
*/
|
||||
QSK_SUBCONTROL( QskDrawer, Panel )
|
||||
|
||||
static inline qreal qskDefaultDragMargin()
|
||||
{
|
||||
// a skin hint ???
|
||||
return QGuiApplication::styleHints()->startDragDistance();
|
||||
}
|
||||
|
||||
static void qskCatchMouseEvents( QQuickItem* item )
|
||||
static inline void qskCatchMouseEvents( QQuickItem* item )
|
||||
{
|
||||
#if 1
|
||||
// manipulating other items - do we really want to do this ?
|
||||
|
@ -63,13 +51,12 @@ static bool qskCheckDirection( Qt::Edge edge, const QskPanGesture* gesture )
|
|||
return false;
|
||||
}
|
||||
|
||||
static void qskLayoutDrawer( const QRectF& rect, QskDrawer* drawer )
|
||||
static inline QRectF qskAlignedToEdge(
|
||||
const QRectF& rect, const QSizeF& size, Qt::Edge edge )
|
||||
{
|
||||
const auto size = qskSizeConstraint( drawer, Qt::PreferredSize );
|
||||
|
||||
QRectF r( 0.0, 0.0, size.width(), size.height() );
|
||||
|
||||
switch( drawer->edge() )
|
||||
switch( edge )
|
||||
{
|
||||
case Qt::LeftEdge:
|
||||
{
|
||||
|
@ -99,91 +86,7 @@ static void qskLayoutDrawer( const QRectF& rect, QskDrawer* drawer )
|
|||
}
|
||||
}
|
||||
|
||||
drawer->setGeometry( r );
|
||||
}
|
||||
|
||||
static inline QRectF qskSlidingRect(
|
||||
const QSizeF& size, Qt::Edge edge, qreal ratio )
|
||||
{
|
||||
auto x = 0.0;
|
||||
auto y = 0.0;
|
||||
|
||||
ratio = 1.0 - ratio;
|
||||
|
||||
switch( edge )
|
||||
{
|
||||
case Qt::LeftEdge:
|
||||
x = -ratio * size.width();
|
||||
break;
|
||||
|
||||
case Qt::RightEdge:
|
||||
x = ratio * size.width();
|
||||
break;
|
||||
|
||||
case Qt::TopEdge:
|
||||
y = -ratio * size.height();
|
||||
break;
|
||||
|
||||
case Qt::BottomEdge:
|
||||
y = ratio * size.height();
|
||||
break;
|
||||
}
|
||||
|
||||
return QRectF( x, y, size.width(), size.height() );
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
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()
|
||||
{
|
||||
#if 0
|
||||
const auto pos = m_adjustedItem->mapFromItem( m_item, QPointF() );
|
||||
qskSetItemGeometry( m_adjustedItem,
|
||||
pos.x(), pos.y(), m_item->width(), m_item->height() );
|
||||
#else
|
||||
qskLayoutDrawer( QRectF( QPointF(), m_item->size() ),
|
||||
qobject_cast< QskDrawer* >( m_adjustedItem ) );
|
||||
#endif
|
||||
}
|
||||
|
||||
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;
|
||||
};
|
||||
return r;
|
||||
}
|
||||
|
||||
namespace
|
||||
|
@ -243,18 +146,8 @@ namespace
|
|||
class QskDrawer::PrivateData
|
||||
{
|
||||
public:
|
||||
inline void resetListener( QskDrawer* drawer )
|
||||
{
|
||||
delete listener;
|
||||
listener = nullptr;
|
||||
|
||||
if ( drawer->parentItem() && drawer->isVisible() )
|
||||
listener = new GeometryListener( drawer->parentItem(), drawer );
|
||||
}
|
||||
|
||||
Qt::Edge edge = Qt::LeftEdge;
|
||||
GestureRecognizer* gestureRecognizer = nullptr;
|
||||
GeometryListener* listener = nullptr;
|
||||
|
||||
qreal dragMargin = qskDefaultDragMargin();
|
||||
};
|
||||
|
@ -269,25 +162,11 @@ QskDrawer::QskDrawer( QQuickItem* parentItem )
|
|||
|
||||
setAutoLayoutChildren( true );
|
||||
setInteractive( true );
|
||||
|
||||
setPopupFlag( PopupFlag::CloseOnPressOutside, true );
|
||||
setTransitionAspect( Panel | QskAspect::Position | QskAspect::Metric );
|
||||
|
||||
/*
|
||||
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 );
|
||||
m_data->resetListener( this );
|
||||
|
||||
connect( this, &QskPopup::openChanged, this, &QskDrawer::setSliding );
|
||||
connect( this, &QskPopup::transitioningChanged, this, &QskDrawer::setIntermediate );
|
||||
setAdjustingToParentGeometry( true );
|
||||
}
|
||||
|
||||
QskDrawer::~QskDrawer()
|
||||
{
|
||||
delete m_data->listener;
|
||||
}
|
||||
|
||||
Qt::Edge QskDrawer::edge() const
|
||||
|
@ -352,6 +231,24 @@ qreal QskDrawer::dragMargin() const
|
|||
return m_data->dragMargin;
|
||||
}
|
||||
|
||||
bool QskDrawer::event( QEvent* event )
|
||||
{
|
||||
if ( event->type() == QEvent::PolishRequest )
|
||||
{
|
||||
if ( isAdjustingToParentGeometry() && parentItem() )
|
||||
{
|
||||
auto r = qskItemRect( parentItem() );
|
||||
r = qskAlignedToEdge( r, sizeConstraint( Qt::PreferredSize ), edge() );
|
||||
|
||||
setGeometry( r );
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return Inherited::event( event );
|
||||
}
|
||||
|
||||
void QskDrawer::keyPressEvent( QKeyEvent* event )
|
||||
{
|
||||
if ( isOpen() )
|
||||
|
@ -432,18 +329,6 @@ void QskDrawer::gestureEvent( QskGestureEvent* event )
|
|||
Inherited::gestureEvent( event );
|
||||
}
|
||||
|
||||
QRectF QskDrawer::layoutRectForSize( const QSizeF& size ) const
|
||||
{
|
||||
qreal ratio;
|
||||
|
||||
if ( isTransitioning() )
|
||||
ratio = metric( transitionAspect() );
|
||||
else
|
||||
ratio = isOpen() ? 1.0 : 0.0;
|
||||
|
||||
return qskSlidingRect( size, m_data->edge, ratio );
|
||||
}
|
||||
|
||||
void QskDrawer::itemChange( QQuickItem::ItemChange change,
|
||||
const QQuickItem::ItemChangeData& value )
|
||||
{
|
||||
|
@ -456,85 +341,9 @@ 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::setSliding( bool on )
|
||||
{
|
||||
const qreal from = on ? 0.0 : 1.0;
|
||||
const qreal to = on ? 1.0 : 0.0;
|
||||
|
||||
const auto aspect = transitionAspect();
|
||||
|
||||
auto hint = animationHint( aspect );
|
||||
hint.updateFlags = QskAnimationHint::UpdatePolish;
|
||||
|
||||
startTransition( aspect, hint, from, to );
|
||||
}
|
||||
|
||||
QRectF QskDrawer::clipRect() const
|
||||
{
|
||||
if ( !isTransitioning() )
|
||||
return Inherited::clipRect();
|
||||
|
||||
/*
|
||||
When fading we want to clip against the edge, where the drawer
|
||||
slides in/out. However the size of the drawer 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.
|
||||
|
||||
Note, that clipping against "rounded" rectangles can't be done
|
||||
properly by overloading clipRect. We would have to manipulate the clip node
|
||||
manually - like it is done in QskScrollArea. TODO ..
|
||||
*/
|
||||
constexpr qreal d = std::numeric_limits< short >::max();
|
||||
|
||||
QRectF r( -d, -d, 2.0 * d, 2.0 * d );
|
||||
|
||||
switch( m_data->edge )
|
||||
{
|
||||
case Qt::LeftEdge:
|
||||
r.setLeft( 0.0 );
|
||||
break;
|
||||
|
||||
case Qt::RightEdge:
|
||||
r.setRight( width() );
|
||||
break;
|
||||
|
||||
case Qt::TopEdge:
|
||||
r.setTop( 0.0 );
|
||||
break;
|
||||
|
||||
case Qt::BottomEdge:
|
||||
r.setBottom( height() );
|
||||
break;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
void QskDrawer::setIntermediate( bool on )
|
||||
{
|
||||
setClip( on );
|
||||
Q_EMIT focusIndicatorRectChanged();
|
||||
}
|
||||
|
||||
QRectF QskDrawer::focusIndicatorRect() const
|
||||
{
|
||||
if ( isTransitioning() )
|
||||
return QRectF();
|
||||
|
||||
return Inherited::focusIndicatorRect();
|
||||
}
|
||||
|
||||
#include "moc_QskDrawer.cpp"
|
||||
|
|
|
@ -6,14 +6,13 @@
|
|||
#ifndef QSK_DRAWER_H
|
||||
#define QSK_DRAWER_H
|
||||
|
||||
#include "QskPopup.h"
|
||||
#include <qnamespace.h>
|
||||
#include "QskSlideIn.h"
|
||||
|
||||
class QSK_EXPORT QskDrawer : public QskPopup
|
||||
class QSK_EXPORT QskDrawer : public QskSlideIn
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
using Inherited = QskPopup;
|
||||
using Inherited = QskSlideIn;
|
||||
|
||||
Q_PROPERTY( Qt::Edge edge READ edge WRITE setEdge NOTIFY edgeChanged )
|
||||
|
||||
|
@ -24,13 +23,11 @@ class QSK_EXPORT QskDrawer : public QskPopup
|
|||
WRITE setInteractive NOTIFY interactiveChanged )
|
||||
|
||||
public:
|
||||
QSK_SUBCONTROLS( Panel )
|
||||
|
||||
QskDrawer( QQuickItem* = nullptr );
|
||||
~QskDrawer() override;
|
||||
|
||||
void setEdge( Qt::Edge );
|
||||
Qt::Edge edge() const;
|
||||
Qt::Edge edge() const override final;
|
||||
|
||||
void setInteractive( bool );
|
||||
bool isInteractive() const;
|
||||
|
@ -39,26 +36,19 @@ class QSK_EXPORT QskDrawer : public QskPopup
|
|||
void resetDragMargin();
|
||||
qreal dragMargin() const;
|
||||
|
||||
QRectF layoutRectForSize( const QSizeF& ) const override;
|
||||
|
||||
QRectF clipRect() const override;
|
||||
QRectF focusIndicatorRect() const override;
|
||||
|
||||
Q_SIGNALS:
|
||||
void edgeChanged( Qt::Edge );
|
||||
void dragMarginChanged( qreal );
|
||||
void interactiveChanged( bool );
|
||||
|
||||
protected:
|
||||
bool event( QEvent* ) override;
|
||||
|
||||
void itemChange( ItemChange, const ItemChangeData& ) override;
|
||||
void gestureEvent( QskGestureEvent* ) override;
|
||||
void keyPressEvent( QKeyEvent* ) override;
|
||||
|
||||
private:
|
||||
void setSliding( bool );
|
||||
|
||||
void setIntermediate( bool );
|
||||
|
||||
class PrivateData;
|
||||
std::unique_ptr< PrivateData > m_data;
|
||||
};
|
||||
|
|
|
@ -58,7 +58,6 @@ QskMenu::QskMenu( QQuickItem* parent )
|
|||
, m_data( new PrivateData )
|
||||
{
|
||||
setModal( true );
|
||||
setTransitionAspect( QskMenu::Panel | QskAspect::Position | QskAspect::Metric );
|
||||
|
||||
setPopupFlag( QskPopup::CloseOnPressOutside, true );
|
||||
setPopupFlag( QskPopup::DeleteOnClose, true );
|
||||
|
|
|
@ -236,8 +236,8 @@ QSGNode* QskMenuSkinlet::updateSubNode(
|
|||
|
||||
auto slideInNode = QskSGNode::ensureNode< QskSlideInNode >( node );
|
||||
|
||||
const auto progress = popup->metric( popup->transitionAspect() );
|
||||
slideInNode->updateTranslation( rect, Qt::TopEdge, progress );
|
||||
slideInNode->updateTranslation(
|
||||
rect, Qt::TopEdge, popup->transitioningFactor() );
|
||||
|
||||
auto contentsNode = updateContentsNode( popup, slideInNode->contentsNode() );
|
||||
slideInNode->setContentsNode( contentsNode );
|
||||
|
|
|
@ -19,9 +19,16 @@ QSK_QT_PRIVATE_BEGIN
|
|||
#include <private/qquickitem_p.h>
|
||||
QSK_QT_PRIVATE_END
|
||||
|
||||
QSK_SUBCONTROL( QskPopup, Popup )
|
||||
QSK_SUBCONTROL( QskPopup, Overlay )
|
||||
|
||||
QSK_SYSTEM_STATE( QskPopup, Closed, QskAspect::FirstSystemState << 1 )
|
||||
|
||||
static QskAspect qskTransitioningAspect()
|
||||
{
|
||||
return QskPopup::Popup | QskAspect::Metric;
|
||||
}
|
||||
|
||||
static void qskSetFocus( QQuickItem* item, bool on )
|
||||
{
|
||||
if ( item->window() == nullptr )
|
||||
|
@ -76,6 +83,23 @@ static bool qskReplayMousePress()
|
|||
return false;
|
||||
}
|
||||
|
||||
static void qskStartTransition( QskPopup* popup, bool on )
|
||||
{
|
||||
const auto aspect = qskTransitioningAspect();
|
||||
|
||||
auto hint = popup->animationHint( aspect.subControl() );
|
||||
|
||||
if ( hint.isValid() )
|
||||
{
|
||||
hint.updateFlags = QskAnimationHint::UpdatePolish | QskAnimationHint::UpdateNode;
|
||||
|
||||
const qreal from = on ? 0.0 : 1.0;
|
||||
const qreal to = on ? 1.0 : 0.0;
|
||||
|
||||
popup->startTransition( aspect, hint, from, to );
|
||||
}
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
class InputGrabber final : public QskInputGrabber
|
||||
|
@ -139,7 +163,6 @@ class QskPopup::PrivateData
|
|||
InputGrabber* inputGrabber = nullptr;
|
||||
|
||||
uint priority = 0;
|
||||
QskAspect transitionAspect;
|
||||
|
||||
int flags : 4;
|
||||
bool isModal : 1;
|
||||
|
@ -217,6 +240,8 @@ void QskPopup::setOpen( bool on )
|
|||
else
|
||||
Q_EMIT closed();
|
||||
|
||||
qskStartTransition( this, on );
|
||||
|
||||
if ( isTransitioning() )
|
||||
{
|
||||
Q_EMIT transitioningChanged( true );
|
||||
|
@ -240,7 +265,15 @@ bool QskPopup::isOpen() const
|
|||
|
||||
bool QskPopup::isTransitioning() const
|
||||
{
|
||||
return runningHintAnimator( m_data->transitionAspect ) != nullptr;
|
||||
return runningHintAnimator( qskTransitioningAspect() ) != nullptr;
|
||||
}
|
||||
|
||||
qreal QskPopup::transitioningFactor() const
|
||||
{
|
||||
if ( auto animator = runningHintAnimator( qskTransitioningAspect() ) )
|
||||
return animator->currentValue().value< qreal >();
|
||||
|
||||
return isOpen() ? 1.0 : 0.0;
|
||||
}
|
||||
|
||||
QRectF QskPopup::overlayRect() const
|
||||
|
@ -291,45 +324,24 @@ void QskPopup::updateInputGrabber()
|
|||
}
|
||||
}
|
||||
|
||||
QskAspect QskPopup::transitionAspect() const
|
||||
{
|
||||
return m_data->transitionAspect;
|
||||
}
|
||||
|
||||
void QskPopup::setTransitionAspect( QskAspect aspect )
|
||||
{
|
||||
auto transitionAspect = aspect;
|
||||
transitionAspect.clearStates(); // animated values are always stateless
|
||||
|
||||
if ( transitionAspect == m_data->transitionAspect )
|
||||
return;
|
||||
|
||||
if ( isTransitioning() )
|
||||
{
|
||||
// stop the running animation TODO ...
|
||||
}
|
||||
|
||||
m_data->transitionAspect = transitionAspect;
|
||||
}
|
||||
|
||||
bool QskPopup::isTransitionAccepted( QskAspect aspect ) const
|
||||
{
|
||||
if ( isVisible() )
|
||||
if ( isVisible() && !isInitiallyPainted() )
|
||||
{
|
||||
/*
|
||||
Usually we suppress transitions, when a control has never been
|
||||
painted before as there is no valid starting point. Popups are
|
||||
different as we want to have smooth fade/slide appearances.
|
||||
*/
|
||||
if ( ( aspect.value() == 0 ) )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( aspect == m_data->transitionAspect )
|
||||
return true;
|
||||
|
||||
if ( aspect.isColor() )
|
||||
{
|
||||
if ( aspect.subControl() == effectiveSubcontrol( QskPopup::Popup ) )
|
||||
return true;
|
||||
|
||||
if ( aspect.subControl() == effectiveSubcontrol( QskPopup::Overlay ) )
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return Inherited::isTransitionAccepted( aspect );
|
||||
}
|
||||
|
@ -472,10 +484,10 @@ bool QskPopup::event( QEvent* event )
|
|||
}
|
||||
case QskEvent::Animator:
|
||||
{
|
||||
const auto animtorEvent = static_cast< QskAnimatorEvent* >( event );
|
||||
const auto animatorEvent = static_cast< QskAnimatorEvent* >( event );
|
||||
|
||||
if ( ( animtorEvent->state() == QskAnimatorEvent::Terminated )
|
||||
&& ( animtorEvent->aspect() == m_data->transitionAspect ) )
|
||||
if ( ( animatorEvent->state() == QskAnimatorEvent::Terminated )
|
||||
&& ( animatorEvent->aspect() == qskTransitioningAspect() ) )
|
||||
{
|
||||
if ( !isOpen() )
|
||||
{
|
||||
|
|
|
@ -24,7 +24,7 @@ class QSK_EXPORT QskPopup : public QskControl
|
|||
using Inherited = QskControl;
|
||||
|
||||
public:
|
||||
QSK_SUBCONTROLS( Overlay )
|
||||
QSK_SUBCONTROLS( Popup, Overlay )
|
||||
QSK_STATES( Closed )
|
||||
|
||||
enum PopupFlag
|
||||
|
@ -56,11 +56,8 @@ class QSK_EXPORT QskPopup : public QskControl
|
|||
void setPriority( uint );
|
||||
uint priority() const;
|
||||
|
||||
// transitions between open/closed states
|
||||
QskAspect transitionAspect() const;
|
||||
void setTransitionAspect( QskAspect );
|
||||
|
||||
bool isTransitioning() const;
|
||||
qreal transitioningFactor() const;
|
||||
|
||||
bool isOpen() const;
|
||||
bool isClosed() const;
|
||||
|
|
|
@ -5,6 +5,12 @@
|
|||
|
||||
#include "QskPopupSkinlet.h"
|
||||
#include "QskPopup.h"
|
||||
#include "QskRgbValue.h"
|
||||
|
||||
static inline QRgb qskInterpolatedRgb( QRgb rgb, qreal factor )
|
||||
{
|
||||
return QskRgb::toTransparent( rgb, qRound( factor * qAlpha( rgb ) ) );
|
||||
}
|
||||
|
||||
QskPopupSkinlet::QskPopupSkinlet( QskSkin* skin )
|
||||
: Inherited( skin )
|
||||
|
@ -28,13 +34,43 @@ QRectF QskPopupSkinlet::subControlRect( const QskSkinnable* skinnable,
|
|||
QSGNode* QskPopupSkinlet::updateSubNode(
|
||||
const QskSkinnable* skinnable, quint8 nodeRole, QSGNode* node ) const
|
||||
{
|
||||
const auto popup = static_cast< const QskPopup* >( skinnable );
|
||||
|
||||
switch ( nodeRole )
|
||||
{
|
||||
case OverlayRole:
|
||||
return updateBoxNode( skinnable, node, QskPopup::Overlay );
|
||||
return updateOverlayNode( popup, node );
|
||||
}
|
||||
|
||||
return Inherited::updateSubNode( skinnable, nodeRole, node );
|
||||
}
|
||||
|
||||
QSGNode* QskPopupSkinlet::updateOverlayNode(
|
||||
const QskPopup* popup, QSGNode* node ) const
|
||||
{
|
||||
using Q = QskPopup;
|
||||
|
||||
const auto factor = popup->transitioningFactor();
|
||||
if ( factor <= 0.0 )
|
||||
return nullptr;
|
||||
|
||||
const auto rect = popup->subControlRect( Q::Overlay );
|
||||
if ( rect.isEmpty() )
|
||||
return nullptr;
|
||||
|
||||
auto gradient = popup->gradientHint( Q::Overlay );
|
||||
|
||||
if ( gradient.isVisible() && factor != 1.0 )
|
||||
{
|
||||
auto stops = gradient.stops();
|
||||
|
||||
for ( auto& stop : stops )
|
||||
stop.setRgb( qskInterpolatedRgb( stop.rgb(), factor ) );
|
||||
|
||||
gradient.setStops( stops );
|
||||
}
|
||||
|
||||
return updateBoxNode( popup, node, rect, gradient, QskPopup::Overlay );
|
||||
}
|
||||
|
||||
#include "moc_QskPopupSkinlet.cpp"
|
||||
|
|
|
@ -0,0 +1,236 @@
|
|||
/******************************************************************************
|
||||
* QSkinny - Copyright (C) 2016 Uwe Rathmann
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*****************************************************************************/
|
||||
|
||||
#include "QskSlideIn.h"
|
||||
#include "QskAnimationHint.h"
|
||||
|
||||
QSK_QT_PRIVATE_BEGIN
|
||||
#include <private/qquickitem_p.h>
|
||||
#include <private/qquickitemchangelistener_p.h>
|
||||
QSK_QT_PRIVATE_END
|
||||
|
||||
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()
|
||||
{
|
||||
QEvent event( QEvent::PolishRequest );
|
||||
QCoreApplication::sendEvent( m_adjustedItem, &event );
|
||||
}
|
||||
|
||||
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, &QskSlideIn::setIntermediate );
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool QskSlideIn::event( QEvent* event )
|
||||
{
|
||||
if ( event->type() == QEvent::PolishRequest )
|
||||
{
|
||||
// isVisible ???
|
||||
if ( m_data->adjustingToParentGeometry && parentItem() )
|
||||
{
|
||||
setSize( parentItem()->size() );
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return Inherited::event( event );
|
||||
}
|
||||
|
||||
void QskSlideIn::setIntermediate( bool on )
|
||||
{
|
||||
setClip( on );
|
||||
Q_EMIT focusIndicatorRectChanged();
|
||||
}
|
||||
|
||||
QRectF QskSlideIn::focusIndicatorRect() const
|
||||
{
|
||||
if ( isTransitioning() )
|
||||
return QRectF();
|
||||
|
||||
return Inherited::focusIndicatorRect();
|
||||
}
|
||||
|
||||
QRectF QskSlideIn::clipRect() const
|
||||
{
|
||||
if ( !isTransitioning() )
|
||||
return Inherited::clipRect();
|
||||
|
||||
/*
|
||||
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.
|
||||
|
||||
Note, that clipping against "rounded" rectangles can't be done
|
||||
properly by overloading clipRect. We would have to manipulate the clip node
|
||||
manually - like it is done in QskScrollArea. TODO ..
|
||||
*/
|
||||
constexpr qreal d = std::numeric_limits< short >::max();
|
||||
|
||||
QRectF r( -d, -d, 2.0 * d, 2.0 * d );
|
||||
|
||||
switch( edge() )
|
||||
{
|
||||
case Qt::LeftEdge:
|
||||
r.setLeft( 0.0 );
|
||||
break;
|
||||
|
||||
case Qt::RightEdge:
|
||||
r.setRight( width() );
|
||||
break;
|
||||
|
||||
case Qt::TopEdge:
|
||||
r.setTop( 0.0 );
|
||||
break;
|
||||
|
||||
case Qt::BottomEdge:
|
||||
r.setBottom( height() );
|
||||
break;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
QRectF QskSlideIn::layoutRectForSize( const QSizeF& size ) const
|
||||
{
|
||||
const auto ratio = 1.0 - transitioningFactor();
|
||||
|
||||
auto x = 0.0;
|
||||
auto y = 0.0;
|
||||
|
||||
switch( edge() )
|
||||
{
|
||||
case Qt::LeftEdge:
|
||||
x = -ratio * size.width();
|
||||
break;
|
||||
|
||||
case Qt::RightEdge:
|
||||
x = ratio * size.width();
|
||||
break;
|
||||
|
||||
case Qt::TopEdge:
|
||||
y = -ratio * size.height();
|
||||
break;
|
||||
|
||||
case Qt::BottomEdge:
|
||||
y = ratio * size.height();
|
||||
break;
|
||||
}
|
||||
|
||||
return QRectF( x, y, size.width(), size.height() );
|
||||
}
|
||||
|
||||
#include "moc_QskSlideIn.cpp"
|
|
@ -0,0 +1,44 @@
|
|||
/******************************************************************************
|
||||
* 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 focusIndicatorRect() const override;
|
||||
QRectF clipRect() const override;
|
||||
|
||||
void setAdjustingToParentGeometry( bool on );
|
||||
bool isAdjustingToParentGeometry() const;
|
||||
|
||||
QRectF layoutRectForSize( const QSizeF& ) const override;
|
||||
|
||||
protected:
|
||||
QskSlideIn( QQuickItem* = nullptr );
|
||||
|
||||
bool event( QEvent* ) override;
|
||||
void itemChange( ItemChange, const ItemChangeData& ) override;
|
||||
|
||||
private:
|
||||
void setIntermediate( bool );
|
||||
|
||||
class PrivateData;
|
||||
std::unique_ptr< PrivateData > m_data;
|
||||
};
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue