QskMenu::Cursor animation added

This commit is contained in:
Uwe Rathmann 2021-12-29 16:23:19 +01:00
parent 1a0ea4a3c4
commit 78d39d242f
4 changed files with 81 additions and 16 deletions

View File

@ -303,6 +303,7 @@ void Editor::setupPopup()
void Editor::setupMenu()
{
using A = QskAspect;
using Q = QskMenu;
const QColor c1( 78, 158, 38 );
@ -312,7 +313,7 @@ void Editor::setupMenu()
setVGradient( Q::Panel, c1, c2 );
const bool isCascading = qskMaybeDesktopPlatform();
setFlagHint( Q::Panel | QskAspect::Style, isCascading );
setFlagHint( Q::Panel | A::Style, isCascading );
#if 0
setPadding( Q::Separator, QMarginsF( 10, 0, 10, 0 ) );
@ -329,10 +330,11 @@ void Editor::setupMenu()
setColor( Q::Text, QColor( 255, 255, 255 ) );
setFontRole( Q::Text, QskSkin::SmallFont );
setMetric( Q::Panel | QskAspect::Position, 0 );
setMetric( Q::Panel | QskAspect::Position | QskPopup::Closed, 1 );
setMetric( Q::Panel | A::Position, 0 );
setMetric( Q::Panel | A::Position | QskPopup::Closed, 1 );
setAnimation( Q::Panel | QskAspect::Metric, 200 );
setAnimation( Q::Panel | A::Metric, 150 );
setAnimation( Q::Cursor | A::Metric, 50, QEasingCurve::OutCubic );
}
void Editor::setupTextLabel()

View File

@ -36,7 +36,7 @@ class QskMenu::PrivateData
QskTextOptions textOptions;
QPointF origin;
int currentIndex = 0;
int currentIndex = -1;
bool isPressed = false;
};
@ -157,9 +157,13 @@ QskTextOptions QskMenu::textOptions() const
void QskMenu::setCurrentIndex( int index )
{
if( index >= 0 && index < count()
&& ( index != m_data->currentIndex ) )
if( index < 0 || index >= count() )
index = -1;
if( index != m_data->currentIndex )
{
setPositionHint( Cursor, index );
m_data->currentIndex = index;
update();
@ -239,14 +243,29 @@ void QskMenu::wheelEvent( QWheelEvent* event )
void QskMenu::traverse( int steps )
{
auto& index = m_data->currentIndex;
if ( count() == 0 || ( steps % count() == 0 ) )
return;
index = ( index + steps ) % count();
if ( index < 0 )
index += count();
auto index = m_data->currentIndex + steps;
update();
Q_EMIT currentIndexChanged( index );
auto newIndex = index % count();
if ( newIndex < 0 )
newIndex += count();
if ( hasAnimationHint( Cursor | QskAspect::Metric ) )
{
// when cycling we want slide in
if ( index < 0 )
setPositionHint( Cursor, count() );
if ( index >= count() )
setPositionHint( Cursor, -1 );
movePositionHint( Cursor, newIndex );
}
setCurrentIndex( newIndex );
}
QskColorFilter QskMenu::graphicFilterAt( int index ) const
@ -288,6 +307,10 @@ void QskMenu::mouseReleaseEvent( QMouseEvent* event )
void QskMenu::aboutToShow()
{
setGeometry( QRectF( m_data->origin, sizeConstraint() ) );
if ( m_data->currentIndex < 0 )
setCurrentIndex( 0 );
Inherited::aboutToShow();
}

View File

@ -11,6 +11,7 @@
#include <QskFunctions.h>
#include <QskSkinStateChanger.h>
#include <QskMargins.h>
#include <QskFunctions.h>
#include <qfontmetrics.h>
@ -222,20 +223,57 @@ QskMenuSkinlet::QskMenuSkinlet( QskSkin* skin )
appendNodeRoles( { PanelRole } );
}
QRectF QskMenuSkinlet::cursorRect(
const QskSkinnable* skinnable, const QRectF& contentsRect, int index ) const
{
const auto count = sampleCount( skinnable, QskMenu::Cell );
auto rect = sampleRect( skinnable, contentsRect,
QskMenu::Cell, qBound( 0, index, count ) );
if ( index < 0 )
rect.setBottom( rect.top() );
if ( index >= count )
rect.setTop( rect.bottom() );
return rect;
}
QRectF QskMenuSkinlet::subControlRect(
const QskSkinnable* skinnable, const QRectF& contentsRect,
QskAspect::Subcontrol subControl ) const
{
using Q = QskMenu;
const auto menu = static_cast< const QskMenu* >( skinnable );
if( subControl == QskMenu::Panel )
if( subControl == Q::Panel )
{
return contentsRect;
}
if( subControl == QskMenu::Cursor )
if( subControl == Q::Cursor )
{
return menu->cellRect( menu->currentIndex() );
if ( menu->currentIndex() < 0 )
return QRectF();
const qreal pos = menu->positionHint( Q::Cursor );
const int pos1 = qFloor( pos );
const int pos2 = qCeil( pos );
auto rect = cursorRect( skinnable, contentsRect, pos1 );
if ( pos1 != pos2 )
{
const auto r = cursorRect( skinnable, contentsRect, pos2 );
const qreal ratio = ( pos - pos1 ) / ( pos2 - pos1 );
rect = qskInterpolatedRect( rect, r, ratio );
}
return rect;
}
return Inherited::subControlRect( skinnable, contentsRect, subControl );

View File

@ -49,6 +49,8 @@ class QSK_EXPORT QskMenuSkinlet : public QskPopupSkinlet
QskAspect::Subcontrol, int index, QSGNode* ) const override;
private:
QRectF cursorRect( const QskSkinnable*, const QRectF&, int index ) const;
class PrivateData;
std::unique_ptr< PrivateData > m_data;
};