better fading support for popups, being used in QskDrawer/QskMenu/QskSubWindow

This commit is contained in:
Uwe Rathmann 2023-11-03 18:13:24 +01:00
parent 3b4f167709
commit 1ab236de9f
21 changed files with 454 additions and 437 deletions

View File

@ -623,13 +623,14 @@ void Editor::setupDrawerMetrics()
using Q = QskDrawer; using Q = QskDrawer;
using A = QskAspect; using A = QskAspect;
#if 1 setAnimation( Q::Panel | A::Position, 300, QEasingCurve::OutCubic );
setAnimation( Q::Panel | A::Metric | A::Position, 200 );
#endif
} }
void Editor::setupDrawerColors( QskAspect::Section, const QskFluent2Theme& ) void Editor::setupDrawerColors(
QskAspect::Section section, const QskFluent2Theme& theme )
{ {
setGradient( QskDrawer::Panel | section,
theme.palette.background.solid.base );
} }
void Editor::setupFocusIndicatorMetrics() void Editor::setupFocusIndicatorMetrics()
@ -759,13 +760,7 @@ void Editor::setupMenuMetrics()
setStrutSize( Q::Icon, 12, 12 ); setStrutSize( Q::Icon, 12, 12 );
setPadding( Q::Icon, { 8, 8, 0, 8 } ); setPadding( Q::Icon, { 8, 8, 0, 8 } );
#if 1 setAnimation( Q::Panel | A::Position, 100 );
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( void Editor::setupMenuColors(
@ -876,9 +871,11 @@ void Editor::setupPageIndicatorColors(
void Editor::setupPopup( const QskFluent2Theme& theme ) void Editor::setupPopup( const QskFluent2Theme& theme )
{ {
using Q = QskPopup; using Q = QskPopup;
using A = QskAspect;
const auto& pal = theme.palette; const auto& pal = theme.palette;
setHint( Q::Overlay | A::Style, true );
setGradient( Q::Overlay, pal.background.overlay.defaultColor ); setGradient( Q::Overlay, pal.background.overlay.defaultColor );
} }
@ -1885,6 +1882,8 @@ void Editor::setupSwitchButtonColors(
void Editor::setupSubWindow( const QskFluent2Theme& theme ) void Editor::setupSubWindow( const QskFluent2Theme& theme )
{ {
using Q = QskSubWindow; using Q = QskSubWindow;
using A = QskAspect;
const auto& pal = theme.palette; const auto& pal = theme.palette;
setPadding( Q::Panel, { 0, 31, 0, 0 } ); setPadding( Q::Panel, { 0, 31, 0, 0 } );
@ -1902,6 +1901,8 @@ void Editor::setupSubWindow( const QskFluent2Theme& theme )
setColor( Q::TitleBarText, pal.fillColor.text.primary ); setColor( Q::TitleBarText, pal.fillColor.text.primary );
setAlignment( Q::TitleBarText, Qt::AlignLeft ); setAlignment( Q::TitleBarText, Qt::AlignLeft );
setTextOptions( Q::TitleBarText, Qt::ElideRight, QskTextOptions::NoWrap ); setTextOptions( Q::TitleBarText, Qt::ElideRight, QskTextOptions::NoWrap );
setAnimation( Q::Panel | A::Position, 300, QEasingCurve::OutCubic );
} }
void Editor::setupVirtualKeyboardMetrics() void Editor::setupVirtualKeyboardMetrics()

View File

@ -378,11 +378,9 @@ void Editor::setupMenu()
setColor( Q::Text, m_pal.onSurface ); setColor( Q::Text, m_pal.onSurface );
setFontRole( Q::Text, QskMaterial3Skin::M3BodyMedium ); 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 ); setAnimation( Q::Cursor | A::Position | A::Metric, 75, QEasingCurve::OutCubic );
setAnimation( Q::Panel | A::Position, 75 );
} }
void Editor::setupTextLabel() void Editor::setupTextLabel()
@ -811,7 +809,8 @@ void Editor::setupDrawer()
using Q = QskDrawer; using Q = QskDrawer;
using A = QskAspect; using A = QskAspect;
setAnimation( Q::Panel | A::Metric | A::Position, qskDuration ); setGradient( Q::Panel, m_pal.background );
setAnimation( Q::Panel | A::Position, 300, QEasingCurve::OutCubic );
} }
void Editor::setupSlider() void Editor::setupSlider()
@ -1261,6 +1260,7 @@ void Editor::setupSubWindow()
for ( auto subControl : { Q::Panel, Q::TitleBarPanel, Q::TitleBarText } ) for ( auto subControl : { Q::Panel, Q::TitleBarPanel, Q::TitleBarText } )
setAnimation( subControl | A::Color, qskDuration ); setAnimation( subControl | A::Color, qskDuration );
setAnimation( Q::Panel | A::Position, qskDuration, QEasingCurve::OutCubic );
} }
QskMaterial3Theme::QskMaterial3Theme( QskSkin::ColorScheme colorScheme ) QskMaterial3Theme::QskMaterial3Theme( QskSkin::ColorScheme colorScheme )

View File

@ -409,7 +409,7 @@ void Editor::setupPopup()
using Q = QskPopup; using Q = QskPopup;
setHint( Q::Overlay | A::Style, true ); setHint( Q::Overlay | A::Style, true );
setGradient( Q::Overlay, QColor( 220, 220, 220, 150 ) ); setGradient( Q::Overlay, qRgba( 220, 220, 220, 150 ) );
} }
void Editor::setupMenu() void Editor::setupMenu()
@ -446,11 +446,8 @@ void Editor::setupMenu()
setGraphicRole( Q::Icon | Q::Disabled, DisabledSymbol ); setGraphicRole( Q::Icon | Q::Disabled, DisabledSymbol );
setGraphicRole( Q::Icon | Q::Selected, CursorSymbol ); 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 ); setAnimation( Q::Cursor | A::Position | A::Metric, 75, QEasingCurve::OutCubic );
setAnimation( Q::Panel | A::Position, 100 );
} }
void Editor::setupTextLabel() void Editor::setupTextLabel()
@ -761,10 +758,11 @@ void Editor::setupDialogButtonBox()
void Editor::setupDrawer() void Editor::setupDrawer()
{ {
using A = QskAspect;
using Q = QskDrawer; using Q = QskDrawer;
using A = QskAspect;
setAnimation( Q::Panel | A::Metric | A::Position, qskDuration ); setPanel( Q::Panel, Plain );
setAnimation( Q::Panel | A::Position, 300, QEasingCurve::OutCubic );
} }
void Editor::setupTabButton() void Editor::setupTabButton()
@ -1126,8 +1124,12 @@ void Editor::setupSubWindow()
setAlignment( Q::TitleBarText, Qt::AlignLeft | Qt::AlignVCenter ); setAlignment( Q::TitleBarText, Qt::AlignLeft | Qt::AlignVCenter );
#if 1
for ( auto subControl : { Q::Panel, Q::TitleBarPanel, Q::TitleBarText } ) for ( auto subControl : { Q::Panel, Q::TitleBarPanel, Q::TitleBarText } )
setAnimation( subControl | A::Color, qskDuration ); setAnimation( subControl | A::Color, qskDuration );
#endif
setAnimation( Q::Panel | A::Position, qskDuration, QEasingCurve::OutCubic );
} }
void Editor::setupSpinBox() void Editor::setupSpinBox()

View File

@ -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
@ -178,6 +176,7 @@ list(APPEND HEADERS
controls/QskComboBoxSkinlet.h controls/QskComboBoxSkinlet.h
controls/QskControl.h controls/QskControl.h
controls/QskDrawer.h controls/QskDrawer.h
controls/QskDrawerSkinlet.h
controls/QskEvent.h controls/QskEvent.h
controls/QskFlickAnimator.h controls/QskFlickAnimator.h
controls/QskFocusIndicator.h controls/QskFocusIndicator.h
@ -281,6 +280,7 @@ list(APPEND SOURCES
controls/QskControlPrivate.cpp controls/QskControlPrivate.cpp
controls/QskDirtyItemFilter.cpp controls/QskDirtyItemFilter.cpp
controls/QskDrawer.cpp controls/QskDrawer.cpp
controls/QskDrawerSkinlet.cpp
controls/QskEvent.cpp controls/QskEvent.cpp
controls/QskFlickAnimator.cpp controls/QskFlickAnimator.cpp
controls/QskFocusIndicator.cpp controls/QskFocusIndicator.cpp

View File

@ -5,7 +5,6 @@
#include "QskDrawer.h" #include "QskDrawer.h"
#include "QskAspect.h" #include "QskAspect.h"
#include "QskAnimationHint.h"
#include "QskQuick.h" #include "QskQuick.h"
#include "QskEvent.h" #include "QskEvent.h"
@ -20,10 +19,6 @@ QSK_QT_PRIVATE_BEGIN
#include <private/qquickitemchangelistener_p.h> #include <private/qquickitemchangelistener_p.h>
QSK_QT_PRIVATE_END 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 ) QSK_SUBCONTROL( QskDrawer, Panel )
static inline qreal qskDefaultDragMargin() static inline qreal qskDefaultDragMargin()
@ -63,77 +58,60 @@ static bool qskCheckDirection( Qt::Edge edge, const QskPanGesture* gesture )
return false; return false;
} }
static void qskLayoutDrawer( const QRectF& rect, QskDrawer* drawer ) static inline QRectF qskAlignedToEdge(
const QRectF& r, const QSizeF& sz, Qt::Edge edge )
{ {
const auto size = qskSizeConstraint( drawer, Qt::PreferredSize ); switch( edge )
{
case Qt::LeftEdge:
return QRectF( r.left(), r.top(), sz.width(), r.height() );
QRectF r( 0.0, 0.0, size.width(), size.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->fadingFactor();
auto dx = 0.0;
auto dy = 0.0;
switch( drawer->edge() ) switch( drawer->edge() )
{ {
case Qt::LeftEdge: case Qt::LeftEdge:
{ dx = -ratio * size.width();
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;
}
}
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; break;
case Qt::RightEdge: case Qt::RightEdge:
x = ratio * size.width(); dx = ratio * size.width();
break; break;
case Qt::TopEdge: case Qt::TopEdge:
y = -ratio * size.height(); dy = -ratio * size.height();
break; break;
case Qt::BottomEdge: case Qt::BottomEdge:
y = ratio * size.height(); dy = ratio * size.height();
break; break;
} }
return QRectF( x, y, size.width(), size.height() ); return QPointF( dx, dy );
} }
namespace namespace
{ {
// Using an eventFilter for QskEvent::GeometryChange instead ???
class GeometryListener final : public QQuickItemChangeListener class GeometryListener final : public QQuickItemChangeListener
{ {
public: public:
@ -160,14 +138,7 @@ namespace
private: private:
void adjust() void adjust()
{ {
#if 0 m_adjustedItem->polish();
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 ) void setEnabled( bool on )
@ -184,10 +155,7 @@ namespace
QQuickItem* m_item; QQuickItem* m_item;
QQuickItem* m_adjustedItem; QQuickItem* m_adjustedItem;
}; };
}
namespace
{
class GestureRecognizer : public QskPanGestureRecognizer class GestureRecognizer : public QskPanGestureRecognizer
{ {
using Inherited = QskPanGestureRecognizer; using Inherited = QskPanGestureRecognizer;
@ -204,7 +172,7 @@ namespace
bool isAcceptedPos( const QPointF& pos ) const override bool isAcceptedPos( const QPointF& pos ) const override
{ {
auto drawer = qobject_cast< const QskDrawer* >( targetItem() ); auto drawer = qobject_cast< const QskDrawer* >( targetItem() );
if ( drawer->isTransitioning() ) if ( drawer->isFading() )
return false; return false;
auto rect = qskItemRect( watchedItem() ); auto rect = qskItemRect( watchedItem() );
@ -243,6 +211,11 @@ namespace
class QskDrawer::PrivateData class QskDrawer::PrivateData
{ {
public: public:
PrivateData( Qt::Edge edge )
: edge( edge )
{
}
inline void resetListener( QskDrawer* drawer ) inline void resetListener( QskDrawer* drawer )
{ {
delete listener; delete listener;
@ -252,37 +225,39 @@ class QskDrawer::PrivateData
listener = new GeometryListener( drawer->parentItem(), drawer ); listener = new GeometryListener( drawer->parentItem(), drawer );
} }
Qt::Edge edge = Qt::LeftEdge;
GestureRecognizer* gestureRecognizer = nullptr;
GeometryListener* listener = nullptr; GeometryListener* listener = 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
setAutoLayoutChildren( true );
setInteractive( true );
setPopupFlag( PopupFlag::CloseOnPressOutside, true ); setPopupFlag( PopupFlag::CloseOnPressOutside, true );
setTransitionAspect( Panel | QskAspect::Position | QskAspect::Metric );
/* /*
The drawer wants to be on top of the parent - not being A drawer wants to be on top of its parent - not being
layouted into its layoutRect(). So we opt out and do layouted into its layoutRect(). So we opt out and do
the layout updates manually. the layout updates manually.
*/ */
setPlacementPolicy( QskPlacementPolicy::Ignore ); setPlacementPolicy( QskPlacementPolicy::Ignore );
m_data->resetListener( this );
connect( this, &QskPopup::openChanged, this, &QskDrawer::setSliding ); setAutoLayoutChildren( true );
connect( this, &QskPopup::transitioningChanged, this, &QskDrawer::setIntermediate ); setInteractive( true );
connect( this, &QskPopup::fadingChanged, this, &QQuickItem::setClip );
} }
QskDrawer::~QskDrawer() QskDrawer::~QskDrawer()
@ -374,18 +349,6 @@ void QskDrawer::gestureEvent( QskGestureEvent* event )
Inherited::gestureEvent( 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, void QskDrawer::itemChange( QQuickItem::ItemChange change,
const QQuickItem::ItemChangeData& value ) const QQuickItem::ItemChangeData& value )
{ {
@ -409,74 +372,96 @@ void QskDrawer::itemChange( QQuickItem::ItemChange change,
} }
} }
void QskDrawer::setSliding( bool on ) void QskDrawer::updateResources()
{ {
const qreal from = on ? 0.0 : 1.0; Inherited::updateResources();
const qreal to = on ? 1.0 : 0.0;
const auto aspect = transitionAspect(); /*
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() );
auto hint = animationHint( aspect ); r.translate( qskDrawerTranslation( this, r.size() ) );
hint.updateFlags = QskAnimationHint::UpdatePolish; setGeometry( r );
}
}
startTransition( aspect, hint, from, to ); void QskDrawer::updateNode( QSGNode* node )
{
if ( isFading() && clip() )
{
if ( auto clipNode = QQuickItemPrivate::get( this )->clipNode() )
{
/*
The clipRect is changing while fading. 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 QRectF QskDrawer::clipRect() const
{ {
if ( !isTransitioning() ) if ( isFading() && parentItem() )
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 ); We might not fit into our parent and our children not
break; 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;
case Qt::RightEdge: QRectF r( -d, -d, 2.0 * d, 2.0 * d );
r.setRight( width() );
break;
case Qt::TopEdge: switch( edge() )
r.setTop( 0.0 ); {
break; case Qt::LeftEdge:
r.setLeft( -x() );
break;
case Qt::BottomEdge: case Qt::RightEdge:
r.setBottom( height() ); r.setRight( parentItem()->width() - x() );
break; break;
case Qt::TopEdge:
r.setTop( -y() );
break;
case Qt::BottomEdge:
r.setBottom( parentItem()->height() - y() );
break;
}
return r;
} }
return r; return Inherited::clipRect();
} }
void QskDrawer::setIntermediate( bool on ) QskAspect QskDrawer::fadingAspect() const
{ {
setClip( on ); return QskDrawer::Panel | QskAspect::Position;
Q_EMIT focusIndicatorRectChanged();
} }
QRectF QskDrawer::focusIndicatorRect() const QRectF QskDrawer::layoutRectForSize( const QSizeF& size ) const
{ {
if ( isTransitioning() ) return subControlContentsRect( size, Panel );
return QRectF();
return Inherited::focusIndicatorRect();
} }
#include "moc_QskDrawer.cpp" #include "moc_QskDrawer.cpp"

View File

@ -7,7 +7,6 @@
#define QSK_DRAWER_H #define QSK_DRAWER_H
#include "QskPopup.h" #include "QskPopup.h"
#include <qnamespace.h>
class QSK_EXPORT QskDrawer : public QskPopup class QSK_EXPORT QskDrawer : public QskPopup
{ {
@ -27,6 +26,8 @@ class QSK_EXPORT QskDrawer : public QskPopup
QSK_SUBCONTROLS( Panel ) QSK_SUBCONTROLS( Panel )
QskDrawer( QQuickItem* = nullptr ); QskDrawer( QQuickItem* = nullptr );
QskDrawer( Qt::Edge, QQuickItem* = nullptr );
~QskDrawer() override; ~QskDrawer() override;
void setEdge( Qt::Edge ); void setEdge( Qt::Edge );
@ -39,10 +40,10 @@ class QSK_EXPORT QskDrawer : public QskPopup
void resetDragMargin(); void resetDragMargin();
qreal dragMargin() const; qreal dragMargin() const;
QRectF layoutRectForSize( const QSizeF& ) const override;
QRectF clipRect() const override; QRectF clipRect() const override;
QRectF focusIndicatorRect() const override; QskAspect fadingAspect() const override;
QRectF layoutRectForSize( const QSizeF& ) const override;
Q_SIGNALS: Q_SIGNALS:
void edgeChanged( Qt::Edge ); void edgeChanged( Qt::Edge );
@ -50,14 +51,13 @@ class QSK_EXPORT QskDrawer : public QskPopup
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:
void setSliding( bool );
void setIntermediate( bool );
class PrivateData; class PrivateData;
std::unique_ptr< PrivateData > m_data; std::unique_ptr< PrivateData > m_data;
}; };

View File

@ -0,0 +1,45 @@
/******************************************************************************
* QSkinny - Copyright (C) 2016 Uwe Rathmann
* SPDX-License-Identifier: BSD-3-Clause
*****************************************************************************/
#include "QskDrawerSkinlet.h"
#include "QskDrawer.h"
QskDrawerSkinlet::QskDrawerSkinlet( QskSkin* skin )
: Inherited( skin )
{
appendNodeRoles( { PanelRole } );
}
QskDrawerSkinlet::~QskDrawerSkinlet() = default;
QRectF QskDrawerSkinlet::subControlRect(
const QskSkinnable* skinnable, const QRectF& contentsRect,
QskAspect::Subcontrol subControl ) const
{
if ( subControl == QskDrawer::Panel )
return contentsRect;
return Inherited::subControlRect( skinnable, contentsRect, subControl );
}
QSGNode* QskDrawerSkinlet::updateSubNode(
const QskSkinnable* skinnable, quint8 nodeRole, QSGNode* node ) const
{
if ( nodeRole == PanelRole )
return updateBoxNode( skinnable, node, QskDrawer::Panel );
return Inherited::updateSubNode( skinnable, nodeRole, node );
}
QSizeF QskDrawerSkinlet::sizeHint( const QskSkinnable* skinnable,
Qt::SizeHint which, const QSizeF& constraint ) const
{
if ( which == Qt::PreferredSize )
return skinnable->strutSizeHint( QskDrawer::Panel );
return Inherited::sizeHint( skinnable, which, constraint );
}
#include "moc_QskDrawerSkinlet.cpp"

View File

@ -0,0 +1,40 @@
/******************************************************************************
* QSkinny - Copyright (C) 2016 Uwe Rathmann
* SPDX-License-Identifier: BSD-3-Clause
*****************************************************************************/
#ifndef QSK_DRAWER_SKINLET_H
#define QSK_DRAWER_SKINLET_H
#include "QskPopupSkinlet.h"
class QSK_EXPORT QskDrawerSkinlet : public QskPopupSkinlet
{
Q_GADGET
using Inherited = QskPopupSkinlet;
public:
enum NodeRole
{
ContentsRole = Inherited::RoleCount,
PanelRole,
RoleCount
};
Q_INVOKABLE QskDrawerSkinlet( QskSkin* = nullptr );
~QskDrawerSkinlet() override;
QRectF subControlRect( const QskSkinnable*,
const QRectF&, QskAspect::Subcontrol ) const override;
QSizeF sizeHint( const QskSkinnable*,
Qt::SizeHint, const QSizeF& ) const override;
protected:
QSGNode* updateSubNode( const QskSkinnable*,
quint8 nodeRole, QSGNode* ) const override;
};
#endif

View File

@ -18,7 +18,10 @@
#include <qvariant.h> #include <qvariant.h>
#include <qeventloop.h> #include <qeventloop.h>
QSK_SUBCONTROL( QskMenu, Overlay ) QSK_QT_PRIVATE_BEGIN
#include <private/qquickitem_p.h>
QSK_QT_PRIVATE_END
QSK_SUBCONTROL( QskMenu, Panel ) QSK_SUBCONTROL( QskMenu, Panel )
QSK_SUBCONTROL( QskMenu, Segment ) QSK_SUBCONTROL( QskMenu, Segment )
QSK_SUBCONTROL( QskMenu, Cursor ) QSK_SUBCONTROL( QskMenu, Cursor )
@ -58,20 +61,23 @@ QskMenu::QskMenu( QQuickItem* parent )
, m_data( new PrivateData ) , m_data( new PrivateData )
{ {
setModal( true ); setModal( true );
setTransitionAspect( QskMenu::Panel | QskAspect::Position | QskAspect::Metric );
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, &QskPopup::fadingChanged,
&QskControl::focusIndicatorRectChanged ); this, &QskControl::focusIndicatorRectChanged );
connect( this, &QskMenu::opened, this, connect( this, &QskPopup::fadingChanged,
this, &QQuickItem::setClip );
connect( this, &QskPopup::opened, this,
[this]() { m_data->triggeredIndex = -1; } ); [this]() { m_data->triggeredIndex = -1; } );
setAcceptHoverEvents( true ); setAcceptHoverEvents( true );
@ -81,6 +87,17 @@ QskMenu::~QskMenu()
{ {
} }
QRectF QskMenu::clipRect() const
{
if ( isFading() )
{
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 ...
@ -263,6 +280,40 @@ QString QskMenu::triggeredText() const
return optionAt( m_data->triggeredIndex ).text(); return optionAt( m_data->triggeredIndex ).text();
} }
void QskMenu::updateResources()
{
qreal dy = 0.0;
if ( isFading() )
dy = ( 1.0 - fadingFactor() ) * height();
setPosition( m_data->origin.x(), m_data->origin.y() - dy );
Inherited::updateResources();
}
void QskMenu::updateNode( QSGNode* node )
{
if ( isFading() && clip() )
{
if ( auto clipNode = QQuickItemPrivate::get( this )->clipNode() )
{
/*
The clipRect is changing while fading. 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 )
@ -435,7 +486,7 @@ void QskMenu::mouseReleaseEvent( QMouseEvent* event )
void QskMenu::aboutToShow() void QskMenu::aboutToShow()
{ {
setGeometry( QRectF( m_data->origin, sizeConstraint() ) ); setSize( sizeConstraint() );
if ( m_data->currentIndex < 0 ) if ( m_data->currentIndex < 0 )
{ {
@ -448,7 +499,7 @@ void QskMenu::aboutToShow()
QRectF QskMenu::focusIndicatorRect() const QRectF QskMenu::focusIndicatorRect() const
{ {
if ( isTransitioning() ) if ( isFading() )
return QRectF(); return QRectF();
if( currentIndex() >= 0 ) if( currentIndex() >= 0 )
@ -492,6 +543,11 @@ void QskMenu::trigger( int index )
} }
} }
QskAspect QskMenu::fadingAspect() const
{
return QskMenu::Panel | QskAspect::Position;
}
int QskMenu::exec() int QskMenu::exec()
{ {
(void) execPopup(); (void) execPopup();

View File

@ -37,7 +37,7 @@ class QSK_EXPORT QskMenu : public QskPopup
using Inherited = QskPopup; using Inherited = QskPopup;
public: public:
QSK_SUBCONTROLS( Overlay, Panel, Segment, Cursor, Text, Icon, Separator ) QSK_SUBCONTROLS( Panel, Segment, Cursor, Text, Icon, Separator )
QSK_STATES( Selected, Pressed ) QSK_STATES( Selected, Pressed )
QskMenu( QQuickItem* parentItem = nullptr ); QskMenu( QQuickItem* parentItem = nullptr );
@ -81,6 +81,9 @@ class QSK_EXPORT QskMenu : public QskPopup
bool isPressed() const; bool isPressed() const;
QRectF clipRect() const override;
QskAspect fadingAspect() const override;
Q_INVOKABLE int exec(); Q_INVOKABLE int exec();
Q_SIGNALS: Q_SIGNALS:
@ -115,6 +118,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 );

View File

@ -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 );
const auto progress = popup->metric( popup->transitionAspect() );
slideInNode->updateTranslation( rect, Qt::TopEdge, progress );
auto contentsNode = updateContentsNode( popup, slideInNode->contentsNode() );
slideInNode->setContentsNode( contentsNode );
return slideInNode;
} }
} }

View File

@ -76,6 +76,23 @@ static bool qskReplayMousePress()
return false; return false;
} }
static void qskStartFading( QskPopup* popup, bool on )
{
const auto aspect = popup->fadingAspect();
auto hint = popup->animationHint( aspect );
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 namespace
{ {
class InputGrabber final : public QskInputGrabber class InputGrabber final : public QskInputGrabber
@ -139,7 +156,6 @@ class QskPopup::PrivateData
InputGrabber* inputGrabber = nullptr; InputGrabber* inputGrabber = nullptr;
uint priority = 0; uint priority = 0;
QskAspect transitionAspect;
int flags : 4; int flags : 4;
bool isModal : 1; bool isModal : 1;
@ -217,9 +233,11 @@ void QskPopup::setOpen( bool on )
else else
Q_EMIT closed(); Q_EMIT closed();
if ( isTransitioning() ) qskStartFading( this, on );
if ( isFading() )
{ {
Q_EMIT transitioningChanged( true ); Q_EMIT fadingChanged( true );
} }
else else
{ {
@ -238,9 +256,22 @@ bool QskPopup::isOpen() const
return !hasSkinState( QskPopup::Closed ); return !hasSkinState( QskPopup::Closed );
} }
bool QskPopup::isTransitioning() const QskAspect QskPopup::fadingAspect() const
{ {
return runningHintAnimator( m_data->transitionAspect ) != nullptr; return QskAspect();
}
bool QskPopup::isFading() const
{
return runningHintAnimator( fadingAspect() ) != nullptr;
}
qreal QskPopup::fadingFactor() const
{
if ( auto animator = runningHintAnimator( fadingAspect() ) )
return animator->currentValue().value< qreal >();
return isOpen() ? 1.0 : 0.0;
} }
QRectF QskPopup::overlayRect() const QRectF QskPopup::overlayRect() const
@ -291,44 +322,23 @@ 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 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 ) ) if ( ( aspect.value() == 0 ) )
{
return true;
}
if ( aspect == m_data->transitionAspect )
return true; return true;
if ( aspect.isColor() ) if ( aspect.subControl() == effectiveSubcontrol( fadingAspect().subControl() ) )
{ return true;
if ( aspect.subControl() == effectiveSubcontrol( QskPopup::Overlay ) )
return true; if ( aspect.subControl() == effectiveSubcontrol( QskPopup::Overlay ) )
} return true;
} }
return Inherited::isTransitionAccepted( aspect ); return Inherited::isTransitionAccepted( aspect );
@ -475,7 +485,7 @@ bool QskPopup::event( QEvent* event )
const auto animatorEvent = static_cast< QskAnimatorEvent* >( event ); const auto animatorEvent = static_cast< QskAnimatorEvent* >( event );
if ( ( animatorEvent->state() == QskAnimatorEvent::Terminated ) if ( ( animatorEvent->state() == QskAnimatorEvent::Terminated )
&& ( animatorEvent->aspect() == m_data->transitionAspect ) ) && ( animatorEvent->aspect() == fadingAspect() ) )
{ {
if ( !isOpen() ) if ( !isOpen() )
{ {
@ -485,7 +495,7 @@ bool QskPopup::event( QEvent* event )
deleteLater(); deleteLater();
} }
Q_EMIT transitioningChanged( false ); Q_EMIT fadingChanged( false );
} }
break; break;
@ -633,7 +643,7 @@ int QskPopup::execPopup()
*/ */
connect( popup, &QObject::destroyed, this, &EventLoop::reject ); connect( popup, &QObject::destroyed, this, &EventLoop::reject );
connect( popup, &QskPopup::transitioningChanged, this, &EventLoop::maybeQuit ); connect( popup, &QskPopup::fadingChanged, this, &EventLoop::maybeQuit );
connect( popup, &QskPopup::openChanged, this, &EventLoop::maybeQuit ); connect( popup, &QskPopup::openChanged, this, &EventLoop::maybeQuit );
} }
@ -648,7 +658,7 @@ int QskPopup::execPopup()
{ {
if ( auto popup = qobject_cast< const QskPopup* >( parent() ) ) if ( auto popup = qobject_cast< const QskPopup* >( parent() ) )
{ {
if ( popup->isOpen() || popup->isTransitioning() ) if ( popup->isOpen() || popup->isFading() )
return; return;
} }
@ -656,7 +666,7 @@ int QskPopup::execPopup()
} }
}; };
if ( isOpen() || isTransitioning() ) if ( isOpen() || isFading() )
{ {
qWarning() << "QskPopup::exec: popup is already opened"; qWarning() << "QskPopup::exec: popup is already opened";
return -1; return -1;

View File

@ -14,7 +14,7 @@ class QSK_EXPORT QskPopup : public QskControl
Q_PROPERTY( bool open READ isOpen WRITE setOpen NOTIFY openChanged ) Q_PROPERTY( bool open READ isOpen WRITE setOpen NOTIFY openChanged )
Q_PROPERTY( bool modal READ isModal WRITE setModal NOTIFY modalChanged ) Q_PROPERTY( bool modal READ isModal WRITE setModal NOTIFY modalChanged )
Q_PROPERTY( bool transitioning READ isTransitioning NOTIFY transitioningChanged ) Q_PROPERTY( bool fading READ isFading NOTIFY fadingChanged )
Q_PROPERTY( bool overlay READ hasOverlay Q_PROPERTY( bool overlay READ hasOverlay
WRITE setOverlay RESET resetOverlay NOTIFY overlayChanged ) WRITE setOverlay RESET resetOverlay NOTIFY overlayChanged )
@ -56,15 +56,13 @@ class QSK_EXPORT QskPopup : public QskControl
void setPriority( uint ); void setPriority( uint );
uint priority() const; uint priority() const;
// transitions between open/closed states
QskAspect transitionAspect() const;
void setTransitionAspect( QskAspect );
bool isTransitioning() const;
bool isOpen() const; bool isOpen() const;
bool isClosed() const; bool isClosed() const;
bool isFading() const;
qreal fadingFactor() const;
virtual QskAspect fadingAspect() const;
virtual QRectF overlayRect() const; virtual QRectF overlayRect() const;
public Q_SLOTS: public Q_SLOTS:
@ -78,7 +76,7 @@ class QSK_EXPORT QskPopup : public QskControl
void opened(); void opened();
void closed(); void closed();
void openChanged( bool ); void openChanged( bool );
void transitioningChanged( bool ); void fadingChanged( bool );
void modalChanged( bool ); void modalChanged( bool );
void overlayChanged( bool ); void overlayChanged( bool );

View File

@ -5,6 +5,12 @@
#include "QskPopupSkinlet.h" #include "QskPopupSkinlet.h"
#include "QskPopup.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 ) QskPopupSkinlet::QskPopupSkinlet( QskSkin* skin )
: Inherited( skin ) : Inherited( skin )
@ -28,13 +34,43 @@ QRectF QskPopupSkinlet::subControlRect( const QskSkinnable* skinnable,
QSGNode* QskPopupSkinlet::updateSubNode( QSGNode* QskPopupSkinlet::updateSubNode(
const QskSkinnable* skinnable, quint8 nodeRole, QSGNode* node ) const const QskSkinnable* skinnable, quint8 nodeRole, QSGNode* node ) const
{ {
const auto popup = static_cast< const QskPopup* >( skinnable );
switch ( nodeRole ) switch ( nodeRole )
{ {
case OverlayRole: case OverlayRole:
return updateBoxNode( skinnable, node, QskPopup::Overlay ); return updateOverlayNode( popup, node );
} }
return Inherited::updateSubNode( skinnable, nodeRole, node ); return Inherited::updateSubNode( skinnable, nodeRole, node );
} }
QSGNode* QskPopupSkinlet::updateOverlayNode(
const QskPopup* popup, QSGNode* node ) const
{
using Q = QskPopup;
const auto factor = popup->fadingFactor();
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" #include "moc_QskPopupSkinlet.cpp"

View File

@ -32,6 +32,9 @@
#include "QskComboBox.h" #include "QskComboBox.h"
#include "QskComboBoxSkinlet.h" #include "QskComboBoxSkinlet.h"
#include "QskDrawer.h"
#include "QskDrawerSkinlet.h"
#include "QskFocusIndicator.h" #include "QskFocusIndicator.h"
#include "QskFocusIndicatorSkinlet.h" #include "QskFocusIndicatorSkinlet.h"
@ -160,6 +163,7 @@ QskSkin::QskSkin( QObject* parent )
declareSkinlet< QskBox, QskBoxSkinlet >(); declareSkinlet< QskBox, QskBoxSkinlet >();
declareSkinlet< QskCheckBox, QskCheckBoxSkinlet >(); declareSkinlet< QskCheckBox, QskCheckBoxSkinlet >();
declareSkinlet< QskComboBox, QskComboBoxSkinlet >(); declareSkinlet< QskComboBox, QskComboBoxSkinlet >();
declareSkinlet< QskDrawer, QskDrawerSkinlet >();
declareSkinlet< QskFocusIndicator, QskFocusIndicatorSkinlet >(); declareSkinlet< QskFocusIndicator, QskFocusIndicatorSkinlet >();
declareSkinlet< QskGraphicLabel, QskGraphicLabelSkinlet >(); declareSkinlet< QskGraphicLabel, QskGraphicLabelSkinlet >();
declareSkinlet< QskListView, QskListViewSkinlet >(); declareSkinlet< QskListView, QskListViewSkinlet >();

View File

@ -253,4 +253,15 @@ void QskSubWindow::itemChange( QQuickItem::ItemChange change,
} }
} }
void QskSubWindow::updateResources()
{
setOpacity( fadingFactor() );
Inherited::updateResources();
}
QskAspect QskSubWindow::fadingAspect() const
{
return QskSubWindow::Panel | QskAspect::Position;
}
#include "moc_QskSubWindow.cpp" #include "moc_QskSubWindow.cpp"

View File

@ -83,6 +83,7 @@ class QSK_EXPORT QskSubWindow : public QskPopup
QRectF titleBarRect() const; QRectF titleBarRect() const;
QRectF layoutRectForSize( const QSizeF& ) const override; QRectF layoutRectForSize( const QSizeF& ) const override;
QskAspect fadingAspect() const override;
Q_SIGNALS: Q_SIGNALS:
void decorationsChanged( Decorations ); void decorationsChanged( Decorations );
@ -95,6 +96,8 @@ class QSK_EXPORT QskSubWindow : public QskPopup
bool event( QEvent* ) override; bool event( QEvent* ) override;
void updateLayout() override; void updateLayout() override;
void updateResources() override;
QSizeF layoutSizeHint( Qt::SizeHint, const QSizeF& ) const override; QSizeF layoutSizeHint( Qt::SizeHint, const QSizeF& ) const override;
void itemChange( QQuickItem::ItemChange, void itemChange( QQuickItem::ItemChange,

View File

@ -94,6 +94,18 @@ QSGNode* QskSubWindowSkinlet::updateSubNode(
return nullptr; return nullptr;
} }
case OverlayRole:
{
/*
Overloading QskPopupSkinlet: as the opacity of the subwindow already
depends on the fadingFactor we do not want the additional opacity
adjustments for the overlay node.
Maybe we should have a flag that indicates if the popup does
opacity or geometry transitions, when fading TODO ...
*/
updateBoxNode( subWindow, node, Q::Overlay );
break;
}
} }
return Inherited::updateSubNode( skinnable, nodeRole, node ); return Inherited::updateSubNode( skinnable, nodeRole, node );

View File

@ -77,6 +77,7 @@ static void qskSetupSubWindow(
const QString& title, QskDialog::Actions actions, const QString& title, QskDialog::Actions actions,
QskDialog::Action defaultAction, QskDialogSubWindow* subWindow ) QskDialog::Action defaultAction, QskDialogSubWindow* subWindow )
{ {
subWindow->setPopupFlag( QskPopup::DeleteOnClose );
subWindow->setModal( true ); subWindow->setModal( true );
subWindow->setWindowTitle( title ); subWindow->setWindowTitle( title );
subWindow->setDialogActions( actions ); subWindow->setDialogActions( actions );
@ -128,14 +129,14 @@ static QskDialog::Action qskMessageSubWindow(
const QString& text, int symbolType, QskDialog::Actions actions, const QString& text, int symbolType, QskDialog::Actions actions,
QskDialog::Action defaultAction ) QskDialog::Action defaultAction )
{ {
QskMessageSubWindow subWindow( window->contentItem() ); auto subWindow = new QskMessageSubWindow( window->contentItem() );
subWindow.setSymbolType( symbolType ); subWindow->setSymbolType( symbolType );
subWindow.setText( text ); subWindow->setText( text );
qskSetupSubWindow( title, actions, defaultAction, &subWindow ); qskSetupSubWindow( title, actions, defaultAction, subWindow );
( void ) subWindow.exec(); ( void ) subWindow->exec();
auto clickedAction = subWindow.clickedAction(); auto clickedAction = subWindow->clickedAction();
if ( clickedAction == QskDialog::NoAction ) if ( clickedAction == QskDialog::NoAction )
{ {
// dialog might have been closed by the window menu // dialog might have been closed by the window menu
@ -172,16 +173,16 @@ static QString qskSelectSubWindow(
QskDialog::Actions actions, QskDialog::Action defaultAction, QskDialog::Actions actions, QskDialog::Action defaultAction,
const QStringList& entries, int selectedRow ) const QStringList& entries, int selectedRow )
{ {
QskSelectionSubWindow subWindow( window->contentItem() ); auto subWindow = new QskSelectionSubWindow( window->contentItem() );
subWindow.setInfoText( text ); subWindow->setInfoText( text );
subWindow.setEntries( entries ); subWindow->setEntries( entries );
subWindow.setSelectedRow( selectedRow ); subWindow->setSelectedRow( selectedRow );
QString selectedEntry; QString selectedEntry;
qskSetupSubWindow( title, actions, defaultAction, &subWindow ); qskSetupSubWindow( title, actions, defaultAction, subWindow );
if ( subWindow.exec() == QskDialog::Accepted ) if ( subWindow->exec() == QskDialog::Accepted )
selectedEntry = subWindow.selectedEntry(); selectedEntry = subWindow->selectedEntry();
return selectedEntry; return selectedEntry;
} }

View File

@ -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;
}

View File

@ -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