wip
This commit is contained in:
parent
33b3ddb5e3
commit
2a7a68e915
|
@ -28,13 +28,25 @@ QSK_SUBCONTROL( QskMenu, Separator )
|
||||||
|
|
||||||
QSK_SYSTEM_STATE( QskMenu, Selected, QskAspect::FirstSystemState << 2 )
|
QSK_SYSTEM_STATE( QskMenu, Selected, QskAspect::FirstSystemState << 2 )
|
||||||
|
|
||||||
|
QVector< int > qskSeparators( const QVector< QskLabelData >& options )
|
||||||
|
{
|
||||||
|
QVector< int > separators;
|
||||||
|
|
||||||
|
for ( int i = 0; i < options.count(); i++ )
|
||||||
|
{
|
||||||
|
if ( options[i].isEmpty() )
|
||||||
|
separators += i;
|
||||||
|
}
|
||||||
|
|
||||||
|
return separators;
|
||||||
|
}
|
||||||
|
|
||||||
class QskMenu::PrivateData
|
class QskMenu::PrivateData
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
QPointF origin;
|
QPointF origin;
|
||||||
|
|
||||||
QVector< QskLabelData > options;
|
QVector< QskLabelData > options;
|
||||||
// QVector< bool > enabled;
|
|
||||||
QVector< int > separators;
|
QVector< int > separators;
|
||||||
|
|
||||||
int triggeredIndex = -1;
|
int triggeredIndex = -1;
|
||||||
|
@ -128,13 +140,16 @@ int QskMenu::addOption( const QskLabelData& option )
|
||||||
{
|
{
|
||||||
m_data->options += option;
|
m_data->options += option;
|
||||||
|
|
||||||
|
if ( option.isEmpty() )
|
||||||
|
m_data->separators += m_data->options.count() - 1;
|
||||||
|
|
||||||
resetImplicitSize();
|
resetImplicitSize();
|
||||||
update();
|
update();
|
||||||
|
|
||||||
if ( isComponentComplete() )
|
if ( isComponentComplete() )
|
||||||
Q_EMIT optionsChanged();
|
Q_EMIT optionsChanged();
|
||||||
|
|
||||||
return count() - 1;
|
return m_data->options.count() - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QskMenu::setOptions( const QStringList& options )
|
void QskMenu::setOptions( const QStringList& options )
|
||||||
|
@ -145,6 +160,7 @@ void QskMenu::setOptions( const QStringList& options )
|
||||||
void QskMenu::setOptions( const QVector< QskLabelData >& options )
|
void QskMenu::setOptions( const QVector< QskLabelData >& options )
|
||||||
{
|
{
|
||||||
m_data->options = options;
|
m_data->options = options;
|
||||||
|
m_data->separators = qskSeparators( options );
|
||||||
|
|
||||||
if ( m_data->currentIndex >= 0 )
|
if ( m_data->currentIndex >= 0 )
|
||||||
{
|
{
|
||||||
|
@ -163,7 +179,6 @@ void QskMenu::setOptions( const QVector< QskLabelData >& options )
|
||||||
|
|
||||||
void QskMenu::clear()
|
void QskMenu::clear()
|
||||||
{
|
{
|
||||||
m_data->separators.clear();
|
|
||||||
setOptions( QVector< QskLabelData >() );
|
setOptions( QVector< QskLabelData >() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -177,27 +192,19 @@ QskLabelData QskMenu::optionAt( int index ) const
|
||||||
return m_data->options.value( index );
|
return m_data->options.value( index );
|
||||||
}
|
}
|
||||||
|
|
||||||
int QskMenu::count() const
|
int QskMenu::optionsCount() const
|
||||||
{
|
{
|
||||||
return m_data->options.count();
|
return m_data->options.count();
|
||||||
}
|
}
|
||||||
|
|
||||||
void QskMenu::addSeparator()
|
void QskMenu::addSeparator()
|
||||||
{
|
{
|
||||||
m_data->separators += m_data->options.count();
|
addOption( QskLabelData() );
|
||||||
|
|
||||||
resetImplicitSize();
|
|
||||||
update();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int QskMenu::separatorPosition( int index ) const
|
QVector< int > QskMenu::separators() const
|
||||||
{
|
{
|
||||||
return m_data->separators.value( index, -1 );
|
return m_data->separators;
|
||||||
}
|
|
||||||
|
|
||||||
int QskMenu::separatorCount() const
|
|
||||||
{
|
|
||||||
return m_data->separators.count();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int QskMenu::currentIndex() const
|
int QskMenu::currentIndex() const
|
||||||
|
@ -207,8 +214,15 @@ int QskMenu::currentIndex() const
|
||||||
|
|
||||||
void QskMenu::setCurrentIndex( int index )
|
void QskMenu::setCurrentIndex( int index )
|
||||||
{
|
{
|
||||||
if( index < 0 || index >= count() )
|
if( index < 0 || index >= m_data->options.count() )
|
||||||
|
{
|
||||||
index = -1;
|
index = -1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ( m_data->options[index].isEmpty() ) // a seperator
|
||||||
|
index = -1;
|
||||||
|
}
|
||||||
|
|
||||||
if( index != m_data->currentIndex )
|
if( index != m_data->currentIndex )
|
||||||
{
|
{
|
||||||
|
@ -308,22 +322,38 @@ void QskMenu::wheelEvent( QWheelEvent* event )
|
||||||
|
|
||||||
void QskMenu::traverse( int steps )
|
void QskMenu::traverse( int steps )
|
||||||
{
|
{
|
||||||
if ( count() == 0 || ( steps % count() == 0 ) )
|
const auto count = m_data->options.count();
|
||||||
|
|
||||||
|
const auto n = count - m_data->separators.count();
|
||||||
|
if ( ( n <= 0 ) || ( steps % n == 0 ) )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
auto index = m_data->currentIndex + steps;
|
auto index = m_data->currentIndex;
|
||||||
|
for ( auto i : m_data->separators )
|
||||||
|
{
|
||||||
|
if ( i < index )
|
||||||
|
index--;
|
||||||
|
}
|
||||||
|
|
||||||
auto newIndex = index % count();
|
index += steps;
|
||||||
|
|
||||||
|
auto newIndex = index % n;
|
||||||
if ( newIndex < 0 )
|
if ( newIndex < 0 )
|
||||||
newIndex += count();
|
newIndex += n;
|
||||||
|
|
||||||
|
for ( int i = 0; i < newIndex; i++)
|
||||||
|
{
|
||||||
|
if ( m_data->options[i].isEmpty() )
|
||||||
|
newIndex++;
|
||||||
|
}
|
||||||
|
|
||||||
// when cycling we want slide in
|
// when cycling we want slide in
|
||||||
|
|
||||||
int startIndex = m_data->currentIndex;
|
int startIndex = m_data->currentIndex;
|
||||||
|
|
||||||
if ( index < 0 )
|
if ( index < 0 )
|
||||||
startIndex = count();
|
startIndex = count;
|
||||||
else if ( index >= count() )
|
else if ( index >= n )
|
||||||
startIndex = -1;
|
startIndex = -1;
|
||||||
|
|
||||||
movePositionHint( Cursor, startIndex, newIndex );
|
movePositionHint( Cursor, startIndex, newIndex );
|
||||||
|
|
|
@ -26,7 +26,7 @@ class QSK_EXPORT QskMenu : public QskPopup
|
||||||
Q_PROPERTY( QVector< QskLabelData > options READ options
|
Q_PROPERTY( QVector< QskLabelData > options READ options
|
||||||
WRITE setOptions NOTIFY optionsChanged )
|
WRITE setOptions NOTIFY optionsChanged )
|
||||||
|
|
||||||
Q_PROPERTY( int count READ count )
|
Q_PROPERTY( int optionsCount READ optionsCount )
|
||||||
|
|
||||||
Q_PROPERTY( int currentIndex READ currentIndex
|
Q_PROPERTY( int currentIndex READ currentIndex
|
||||||
WRITE setCurrentIndex NOTIFY currentIndexChanged )
|
WRITE setCurrentIndex NOTIFY currentIndexChanged )
|
||||||
|
@ -65,12 +65,10 @@ class QSK_EXPORT QskMenu : public QskPopup
|
||||||
QVector< QskLabelData > options() const;
|
QVector< QskLabelData > options() const;
|
||||||
QskLabelData optionAt( int ) const;
|
QskLabelData optionAt( int ) const;
|
||||||
|
|
||||||
int count() const;
|
int optionsCount() const;
|
||||||
|
|
||||||
void addSeparator();
|
void addSeparator();
|
||||||
|
QVector< int > separators() const;
|
||||||
int separatorPosition( int ) const;
|
|
||||||
int separatorCount() const;
|
|
||||||
|
|
||||||
void clear();
|
void clear();
|
||||||
|
|
||||||
|
|
|
@ -47,10 +47,12 @@ class QskMenuSkinlet::PrivateData
|
||||||
|
|
||||||
inline int separatorsBefore( const QskMenu* menu, int index ) const
|
inline int separatorsBefore( const QskMenu* menu, int index ) const
|
||||||
{
|
{
|
||||||
|
const auto separators = menu->separators();
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for ( ; i < menu->separatorCount(); i++ )
|
for ( ; i < separators.count(); i++ )
|
||||||
{
|
{
|
||||||
if ( menu->separatorPosition( i ) > index )
|
if ( separators[i] >= index )
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -112,26 +114,22 @@ class QskMenuSkinlet::PrivateData
|
||||||
private:
|
private:
|
||||||
qreal graphicWidthInternal( const QskMenu* menu ) const
|
qreal graphicWidthInternal( const QskMenu* menu ) const
|
||||||
{
|
{
|
||||||
const auto skinlet = menu->effectiveSkinlet();
|
|
||||||
|
|
||||||
const auto hint = menu->strutSizeHint( QskMenu::Icon );
|
const auto hint = menu->strutSizeHint( QskMenu::Icon );
|
||||||
const qreal textHeight = menu->effectiveFontHeight( QskMenu::Text );
|
const qreal textHeight = menu->effectiveFontHeight( QskMenu::Text );
|
||||||
|
|
||||||
const auto h = qMax( hint.height(), textHeight );
|
const auto h = qMax( hint.height(), textHeight );
|
||||||
|
|
||||||
qreal maxW = 0.0;
|
qreal maxW = 0.0;
|
||||||
for ( int i = 0; i < menu->count(); i++ )
|
|
||||||
|
const auto options = menu->options();
|
||||||
|
for ( auto& option : options )
|
||||||
{
|
{
|
||||||
const auto sample = skinlet->sampleAt( menu, QskMenu::Icon, i );
|
const auto graphic = option.icon().graphic();
|
||||||
if ( sample.canConvert< QskGraphic >() )
|
if ( !graphic.isNull() )
|
||||||
{
|
{
|
||||||
const auto graphic = sample.value< QskGraphic >();
|
const auto w = graphic.widthForHeight( h );
|
||||||
if ( !graphic.isNull() )
|
if( w > maxW )
|
||||||
{
|
maxW = w;
|
||||||
const auto w = graphic.widthForHeight( h );
|
|
||||||
if( w > maxW )
|
|
||||||
maxW = w;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,24 +138,18 @@ class QskMenuSkinlet::PrivateData
|
||||||
|
|
||||||
qreal textWidthInternal( const QskMenu* menu ) const
|
qreal textWidthInternal( const QskMenu* menu ) const
|
||||||
{
|
{
|
||||||
const auto skinlet = menu->effectiveSkinlet();
|
|
||||||
|
|
||||||
const QFontMetricsF fm( menu->effectiveFont( QskMenu::Text ) );
|
const QFontMetricsF fm( menu->effectiveFont( QskMenu::Text ) );
|
||||||
|
|
||||||
auto maxWidth = 0.0;
|
auto maxWidth = 0.0;
|
||||||
|
|
||||||
for ( int i = 0; i < menu->count(); i++ )
|
const auto options = menu->options();
|
||||||
|
for ( auto& option : options )
|
||||||
{
|
{
|
||||||
const auto sample = skinlet->sampleAt( menu, QskMenu::Text, i );
|
if( !option.text().isEmpty() )
|
||||||
if ( sample.canConvert< QString >() )
|
|
||||||
{
|
{
|
||||||
const auto text = sample.toString();
|
const auto w = qskHorizontalAdvance( fm, option.text() );
|
||||||
if( !text.isEmpty() )
|
if( w > maxWidth )
|
||||||
{
|
maxWidth = w;
|
||||||
const auto w = qskHorizontalAdvance( fm, text );
|
|
||||||
if( w > maxWidth )
|
|
||||||
maxWidth = w;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -324,17 +316,16 @@ QRectF QskMenuSkinlet::sampleRect(
|
||||||
|
|
||||||
if ( subControl == QskMenu::Separator )
|
if ( subControl == QskMenu::Separator )
|
||||||
{
|
{
|
||||||
const int pos = menu->separatorPosition( index );
|
const auto separators = menu->separators();
|
||||||
if ( pos < 0 )
|
if ( index >= separators.count() )
|
||||||
return QRectF();
|
return QRectF();
|
||||||
|
|
||||||
QRectF r = menu->subControlContentsRect( Q::Panel );
|
const int pos = separators[ index ];
|
||||||
|
|
||||||
if ( pos < menu->count() )
|
auto r = menu->subControlContentsRect( Q::Panel );
|
||||||
{
|
|
||||||
const auto segmentRect = sampleRect( skinnable, contentsRect, Q::Segment, pos );
|
const auto segmentRect = sampleRect( skinnable, contentsRect, Q::Segment, pos );
|
||||||
r.setBottom( segmentRect.top() ); // spacing ???
|
r.setBottom( segmentRect.top() ); // spacing ???
|
||||||
}
|
|
||||||
|
|
||||||
const qreal h = menu->metric( Q::Separator | QskAspect::Size );
|
const qreal h = menu->metric( Q::Separator | QskAspect::Size );
|
||||||
r.setTop( r.bottom() - h );
|
r.setTop( r.bottom() - h );
|
||||||
|
@ -362,13 +353,13 @@ int QskMenuSkinlet::sampleCount(
|
||||||
if ( subControl == Q::Segment || subControl == Q::Icon || subControl == Q::Text )
|
if ( subControl == Q::Segment || subControl == Q::Icon || subControl == Q::Text )
|
||||||
{
|
{
|
||||||
const auto menu = static_cast< const QskMenu* >( skinnable );
|
const auto menu = static_cast< const QskMenu* >( skinnable );
|
||||||
return menu->count();
|
return menu->optionsCount() - menu->separators().count();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( subControl == Q::Separator )
|
if ( subControl == Q::Separator )
|
||||||
{
|
{
|
||||||
const auto menu = static_cast< const QskMenu* >( skinnable );
|
const auto menu = static_cast< const QskMenu* >( skinnable );
|
||||||
return menu->separatorCount();
|
return menu->separators().count();
|
||||||
}
|
}
|
||||||
|
|
||||||
return Inherited::sampleCount( skinnable, subControl );
|
return Inherited::sampleCount( skinnable, subControl );
|
||||||
|
|
Loading…
Reference in New Issue