QskMenu::Cursor animation added
This commit is contained in:
parent
1a0ea4a3c4
commit
78d39d242f
@ -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()
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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 );
|
||||
|
@ -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;
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user