qskinny/src/controls/QskMenuSkinlet.cpp

572 lines
15 KiB
C++
Raw Normal View History

2022-04-20 12:20:41 +00:00
/******************************************************************************
* QSkinny - Copyright (C) 2016 Uwe Rathmann
* This file may be used under the terms of the QSkinny License, Version 1.0
*****************************************************************************/
2021-12-23 17:36:32 +00:00
#include "QskMenuSkinlet.h"
#include "QskMenu.h"
2022-04-20 12:20:41 +00:00
#include "QskBoxNode.h"
#include "QskGraphic.h"
#include "QskColorFilter.h"
#include "QskTextOptions.h"
#include "QskSGNode.h"
#include "QskFunctions.h"
#include "QskMargins.h"
#include "QskFunctions.h"
2021-12-23 17:36:32 +00:00
#include <qfontmetrics.h>
2021-12-29 15:54:16 +00:00
#include <qmath.h>
2021-12-23 17:36:32 +00:00
2021-12-27 08:50:14 +00:00
template< class T >
static inline QVariant qskSampleAt( const QskMenu* menu, int index )
2021-12-27 08:50:14 +00:00
{
2022-01-06 17:36:15 +00:00
const auto list = menu->optionAt( index );
for ( const auto& value : list )
2021-12-27 08:50:14 +00:00
{
2022-01-06 17:36:15 +00:00
if ( value.canConvert< T >() )
return value;
2021-12-27 08:50:14 +00:00
}
2021-12-28 14:33:13 +00:00
return QVariant();
2021-12-27 08:50:14 +00:00
}
template< class T >
static inline T qskValueAt( const QskMenu* menu, int index )
{
const auto sample = qskSampleAt< T >( menu, index );
return sample.template value< T >();
}
2021-12-28 14:33:13 +00:00
class QskMenuSkinlet::PrivateData
2021-12-23 17:36:32 +00:00
{
2021-12-28 14:33:13 +00:00
public:
class CacheGuard
2021-12-23 17:36:32 +00:00
{
2021-12-28 14:33:13 +00:00
public:
2022-01-04 12:47:40 +00:00
CacheGuard( PrivateData* data )
2021-12-28 14:33:13 +00:00
: m_data( data )
2021-12-23 17:36:32 +00:00
{
2021-12-28 14:33:13 +00:00
m_data->enableCache( true );
2021-12-23 17:36:32 +00:00
}
2021-12-23 18:05:59 +00:00
2021-12-28 14:33:13 +00:00
~CacheGuard()
{
m_data->enableCache( false );
}
2022-03-23 10:54:34 +00:00
private:
2022-01-04 12:47:40 +00:00
PrivateData* m_data;
2021-12-28 14:33:13 +00:00
};
2021-12-23 18:05:59 +00:00
2021-12-28 14:33:13 +00:00
void enableCache( bool on )
2021-12-23 17:36:32 +00:00
{
2021-12-28 14:33:13 +00:00
m_isCaching = on;
m_segmentHeight = m_segmentWidth = m_graphicWidth = m_textWidth = -1.0;
2021-12-23 18:05:59 +00:00
}
2022-01-06 17:36:15 +00:00
inline int separatorsBefore( const QskMenu* menu, int index ) const
{
int i = 0;
for ( ; i < menu->separatorCount(); i++ )
{
if ( menu->separatorPosition( i ) > index )
break;
}
return i;
}
2021-12-28 14:33:13 +00:00
inline qreal graphicWidth( const QskMenu* menu ) const
{
if ( m_isCaching )
{
if ( m_graphicWidth < 0.0 )
m_graphicWidth = graphicWidthInternal( menu );
2021-12-24 15:50:34 +00:00
2021-12-28 14:33:13 +00:00
return m_graphicWidth;
}
2021-12-24 15:50:34 +00:00
2021-12-28 14:33:13 +00:00
return graphicWidthInternal( menu );
}
2021-12-24 15:50:34 +00:00
2021-12-28 14:33:13 +00:00
inline qreal textWidth( const QskMenu* menu ) const
{
if ( m_isCaching )
{
if ( m_textWidth < 0.0 )
m_textWidth = textWidthInternal( menu );
2021-12-24 15:50:34 +00:00
2021-12-28 14:33:13 +00:00
return m_textWidth;
}
2021-12-24 15:50:34 +00:00
2021-12-28 14:33:13 +00:00
return textWidthInternal( menu );
}
2021-12-23 17:36:32 +00:00
inline qreal segmentWidth( const QskMenu* menu ) const
2021-12-28 14:33:13 +00:00
{
if ( m_isCaching )
{
if ( m_segmentWidth < 0.0 )
m_segmentWidth = segmentWidthInternal( menu );
2021-12-23 17:36:32 +00:00
return m_segmentWidth;
2021-12-28 14:33:13 +00:00
}
2021-12-23 17:36:32 +00:00
return segmentWidthInternal( menu );
2021-12-28 14:33:13 +00:00
}
2021-12-23 17:36:32 +00:00
inline qreal segmentHeight( const QskMenu* menu ) const
2021-12-28 14:33:13 +00:00
{
if ( m_isCaching )
{
if ( m_segmentHeight < 0.0 )
m_segmentHeight = segmentHeightInternal( menu );
return m_segmentHeight;
2021-12-28 14:33:13 +00:00
}
return segmentHeightInternal( menu );
2021-12-28 14:33:13 +00:00
}
2021-12-23 17:36:32 +00:00
2021-12-28 14:33:13 +00:00
private:
qreal graphicWidthInternal( const QskMenu* menu ) const
2021-12-23 17:36:32 +00:00
{
2021-12-28 14:33:13 +00:00
const auto skinlet = menu->effectiveSkinlet();
2021-12-23 17:36:32 +00:00
2021-12-28 14:33:13 +00:00
const auto hint = menu->strutSizeHint( QskMenu::Graphic );
const qreal textHeight = menu->effectiveFontHeight( QskMenu::Text );
2021-12-23 17:36:32 +00:00
2021-12-28 14:33:13 +00:00
const auto h = qMax( hint.height(), textHeight );
2021-12-23 17:36:32 +00:00
2021-12-28 14:33:13 +00:00
qreal maxW = 0.0;
for ( int i = 0; i < menu->count(); i++ )
2021-12-24 15:20:34 +00:00
{
const auto sample = skinlet->sampleAt( menu, QskMenu::Graphic, i );
if ( sample.canConvert< QskGraphic >() )
2021-12-24 15:20:34 +00:00
{
const auto graphic = sample.value< QskGraphic >();
2021-12-28 14:33:13 +00:00
if ( !graphic.isNull() )
{
const auto w = graphic.widthForHeight( h );
if( w > maxW )
maxW = w;
}
2021-12-24 15:20:34 +00:00
}
}
2021-12-23 17:36:32 +00:00
2021-12-28 14:33:13 +00:00
return qMax( hint.width(), maxW );
}
2021-12-24 15:20:34 +00:00
2021-12-28 14:33:13 +00:00
qreal textWidthInternal( const QskMenu* menu ) const
{
const auto skinlet = menu->effectiveSkinlet();
2021-12-23 17:36:32 +00:00
2021-12-28 14:33:13 +00:00
const QFontMetricsF fm( menu->effectiveFont( QskMenu::Text ) );
2021-12-23 17:36:32 +00:00
2021-12-28 14:33:13 +00:00
auto maxWidth = 0.0;
2021-12-23 17:36:32 +00:00
2021-12-28 14:33:13 +00:00
for ( int i = 0; i < menu->count(); i++ )
{
const auto sample = skinlet->sampleAt( menu, QskMenu::Text, i );
if ( sample.canConvert< QString >() )
2021-12-28 14:33:13 +00:00
{
2022-03-24 16:33:40 +00:00
const auto text = sample.toString();
2021-12-28 14:33:13 +00:00
if( !text.isEmpty() )
{
const auto w = qskHorizontalAdvance( fm, text );
if( w > maxWidth )
maxWidth = w;
}
}
}
2021-12-23 17:36:32 +00:00
2021-12-28 14:33:13 +00:00
return maxWidth;
2021-12-23 17:36:32 +00:00
}
qreal segmentWidthInternal( const QskMenu* menu ) const
2021-12-28 14:33:13 +00:00
{
using Q = QskMenu;
const auto spacing = menu->spacingHint( Q::Segment );
const auto padding = menu->paddingHint( Q::Segment );
2021-12-28 14:33:13 +00:00
auto w = graphicWidth( menu ) + spacing + textWidth( menu );
2021-12-23 17:36:32 +00:00
2021-12-28 14:33:13 +00:00
w += padding.left() + padding.right();
2021-12-23 17:36:32 +00:00
const auto minWidth = menu->strutSizeHint( Q::Segment ).width();
2021-12-28 14:33:13 +00:00
return qMax( w, minWidth );
}
2021-12-23 17:36:32 +00:00
qreal segmentHeightInternal( const QskMenu* menu ) const
2021-12-23 17:36:32 +00:00
{
2021-12-28 14:33:13 +00:00
using Q = QskMenu;
2021-12-23 17:36:32 +00:00
2021-12-28 14:33:13 +00:00
const auto graphicHeight = menu->strutSizeHint( Q::Graphic ).height();
const auto textHeight = menu->effectiveFontHeight( Q::Text );
const auto padding = menu->paddingHint( Q::Segment );
2021-12-23 17:36:32 +00:00
2021-12-28 14:33:13 +00:00
qreal h = qMax( graphicHeight, textHeight );
h += padding.top() + padding.bottom();
2021-12-23 18:05:59 +00:00
const auto minHeight = menu->strutSizeHint( Q::Segment ).height();
2021-12-28 14:33:13 +00:00
h = qMax( h, minHeight );
2021-12-27 08:50:14 +00:00
2021-12-28 14:33:13 +00:00
return h;
2021-12-23 17:36:32 +00:00
}
2021-12-28 14:33:13 +00:00
bool m_isCaching;
2021-12-23 17:36:32 +00:00
2021-12-28 14:33:13 +00:00
mutable qreal m_graphicWidth = -1.0;
mutable qreal m_textWidth = -1.0;
mutable qreal m_segmentHeight = -1.0;
mutable qreal m_segmentWidth = -1.0;
2021-12-28 14:33:13 +00:00
};
2021-12-23 17:36:32 +00:00
QskMenuSkinlet::QskMenuSkinlet( QskSkin* skin )
: Inherited( skin )
2021-12-28 14:33:13 +00:00
, m_data( new PrivateData() )
2021-12-23 17:36:32 +00:00
{
appendNodeRoles( { PanelRole } );
}
fix build on Windows (#176) * fix build on Windows fixes the following error from CI: common\QskAspect.cpp(199): error C2666: 'QFlags<QskAspect::State>::operator &': 3 overloads have similar conversions D:\a\qskinny\Qt\5.15.2\msvc2019_64\include\QtCore/qflags.h(146): note: could be 'QFlags<QskAspect::State> QFlags<QskAspect::State>::operator &(Enum) noexcept const' with [ Enum=QskAspect::State ] D:\a\qskinny\Qt\5.15.2\msvc2019_64\include\QtCore/qflags.h(145): note: or 'QFlags<QskAspect::State> QFlags<QskAspect::State>::operator &(uint) noexcept const' D:\a\qskinny\Qt\5.15.2\msvc2019_64\include\QtCore/qflags.h(144): note: or 'QFlags<QskAspect::State> QFlags<QskAspect::State>::operator &(int) noexcept const' common\QskAspect.cpp(199): note: or 'built-in C++ operator&(QFlags<QskAspect::State>::Int, quint16)' common\QskAspect.cpp(199): note: while trying to match the argument list '(QskAspect::States, const quint16)' * fix build on Windows fixes the following error from CI: C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Tools\MSVC\14.31.31103\include\memory(3124): error C2027: use of undefined type 'QskMenuSkinlet::PrivateData' D:\a\qskinny\qskinny\src\controls\QskMenuSkinlet.h(54): note: see declaration of 'QskMenuSkinlet::PrivateData' C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Tools\MSVC\14.31.31103\include\memory(3123): note: while compiling class template member function 'void std::default_delete<QskMenuSkinlet::PrivateData>::operator ()(_Ty *) noexcept const' with [ _Ty=QskMenuSkinlet::PrivateData ] C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Tools\MSVC\14.31.31103\include\memory(3233): note: see reference to function template instantiation 'void std::default_delete<QskMenuSkinlet::PrivateData>::operator ()(_Ty *) noexcept const' being compiled with [ _Ty=QskMenuSkinlet::PrivateData ] C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Tools\MSVC\14.31.31103\include\memory(3160): note: see reference to class template instantiation 'std::default_delete<QskMenuSkinlet::PrivateData>' being compiled D:\a\qskinny\qskinny\src\controls\QskMenuSkinlet.h(55): note: see reference to class template instantiation 'std::unique_ptr<QskMenuSkinlet::PrivateData,std::default_delete<QskMenuSkinlet::PrivateData>>' being compiled C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Tools\MSVC\14.31.31103\include\memory(3124): error C2338: can't delete an incomplete type C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Tools\MSVC\14.31.31103\include\memory(3125): warning C4150: deletion of pointer to incomplete type 'QskMenuSkinlet::PrivateData'; no destructor called D:\a\qskinny\qskinny\src\controls\QskMenuSkinlet.h(54): note: see declaration of 'QskMenuSkinlet::PrivateData
2022-04-13 09:24:18 +00:00
QskMenuSkinlet::~QskMenuSkinlet() = default;
2021-12-29 15:23:19 +00:00
QRectF QskMenuSkinlet::cursorRect(
const QskSkinnable* skinnable, const QRectF& contentsRect, int index ) const
{
const auto count = sampleCount( skinnable, QskMenu::Segment );
2021-12-29 15:23:19 +00:00
auto rect = sampleRect( skinnable, contentsRect,
QskMenu::Segment, qBound( 0, index, count ) );
2021-12-29 15:23:19 +00:00
if ( index < 0 )
rect.setBottom( rect.top() );
if ( index >= count )
rect.setTop( rect.bottom() );
return rect;
}
2021-12-23 17:36:32 +00:00
QRectF QskMenuSkinlet::subControlRect(
const QskSkinnable* skinnable, const QRectF& contentsRect,
QskAspect::Subcontrol subControl ) const
{
2021-12-29 15:23:19 +00:00
using Q = QskMenu;
2021-12-24 15:20:34 +00:00
const auto menu = static_cast< const QskMenu* >( skinnable );
2021-12-29 15:23:19 +00:00
if( subControl == Q::Panel )
2021-12-23 17:36:32 +00:00
{
return contentsRect;
}
2021-12-29 15:23:19 +00:00
if( subControl == Q::Cursor )
2021-12-24 15:20:34 +00:00
{
2021-12-29 15:23:19 +00:00
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;
2021-12-24 15:20:34 +00:00
}
2021-12-23 17:36:32 +00:00
return Inherited::subControlRect( skinnable, contentsRect, subControl );
}
QRectF QskMenuSkinlet::sampleRect(
2021-12-24 15:50:34 +00:00
const QskSkinnable* skinnable, const QRectF& contentsRect,
QskAspect::Subcontrol subControl, int index ) const
{
2021-12-28 14:33:13 +00:00
using Q = QskMenu;
2021-12-24 15:50:34 +00:00
2021-12-28 14:33:13 +00:00
const auto menu = static_cast< const QskMenu* >( skinnable );
2021-12-24 15:50:34 +00:00
if ( subControl == Q::Segment )
2021-12-28 14:33:13 +00:00
{
const auto r = menu->subControlContentsRect( Q::Panel );
2022-01-06 17:36:15 +00:00
auto h = m_data->segmentHeight( menu );
2022-01-06 17:36:15 +00:00
if ( int n = m_data->separatorsBefore( menu, index ) )
{
// spacing ???
const qreal separatorH = menu->metric( Q::Separator | QskAspect::Size );
h += n * separatorH;
}
2021-12-24 15:50:34 +00:00
return QRectF( r.x(), r.y() + index * h, r.width(), h );
}
2021-12-28 14:33:13 +00:00
if ( subControl == QskMenu::Graphic || subControl == QskMenu::Text )
{
const auto r = sampleRect( menu, contentsRect, Q::Segment, index );
2021-12-28 14:33:13 +00:00
const auto graphicWidth = m_data->graphicWidth( menu );
if ( subControl == QskMenu::Graphic )
{
auto graphicRect = r;
graphicRect.setWidth( graphicWidth );
const auto padding = menu->paddingHint( QskMenu::Graphic );
graphicRect = graphicRect.marginsRemoved( padding );
2021-12-28 14:33:13 +00:00
return graphicRect;
2021-12-28 14:33:13 +00:00
}
else
{
auto textRect = r;
if ( graphicWidth > 0.0 )
{
const auto spacing = skinnable->spacingHint( Q::Segment );
2021-12-28 14:33:13 +00:00
textRect.setX( r.x() + graphicWidth + spacing );
}
return textRect;
}
}
2022-01-06 17:36:15 +00:00
if ( subControl == QskMenu::Separator )
{
const int pos = menu->separatorPosition( index );
if ( pos < 0 )
return QRectF();
QRectF r = menu->subControlContentsRect( Q::Panel );
if ( pos < menu->count() )
{
const auto segmentRect = sampleRect( skinnable, contentsRect, Q::Segment, pos );
r.setBottom( segmentRect.top() ); // spacing ???
2022-01-06 17:36:15 +00:00
}
const qreal h = menu->metric( Q::Separator | QskAspect::Size );
r.setTop( r.bottom() - h );
return r;
}
return Inherited::sampleRect(
2021-12-24 15:50:34 +00:00
skinnable, contentsRect, subControl, index );
}
int QskMenuSkinlet::sampleIndexAt(
2021-12-28 14:33:13 +00:00
const QskSkinnable* skinnable, const QRectF& contentsRect,
QskAspect::Subcontrol subControl, const QPointF& pos ) const
{
const PrivateData::CacheGuard guard( m_data.get() );
return Inherited::sampleIndexAt( skinnable, contentsRect, subControl, pos );
2021-12-28 14:33:13 +00:00
}
int QskMenuSkinlet::sampleCount(
const QskSkinnable* skinnable, QskAspect::Subcontrol subControl ) const
2021-12-26 08:15:15 +00:00
{
2021-12-28 14:33:13 +00:00
using Q = QskMenu;
if ( subControl == Q::Segment || subControl == Q::Graphic || subControl == Q::Text )
2021-12-26 08:15:15 +00:00
{
const auto menu = static_cast< const QskMenu* >( skinnable );
return menu->count();
}
2021-12-26 08:15:15 +00:00
2022-01-06 17:36:15 +00:00
if ( subControl == Q::Separator )
{
const auto menu = static_cast< const QskMenu* >( skinnable );
return menu->separatorCount();
}
return Inherited::sampleCount( skinnable, subControl );
}
2021-12-26 08:15:15 +00:00
QskAspect::States QskMenuSkinlet::sampleStates(
const QskSkinnable* skinnable, QskAspect::Subcontrol subControl, int index ) const
{
2021-12-28 14:33:13 +00:00
using Q = QskMenu;
auto states = Inherited::sampleStates( skinnable, subControl, index );
2021-12-26 08:15:15 +00:00
if ( subControl == Q::Segment || subControl == Q::Graphic || subControl == Q::Text )
{
const auto menu = static_cast< const QskMenu* >( skinnable );
if ( menu->currentIndex() == index )
states |= QskMenu::Selected;
2021-12-26 08:15:15 +00:00
}
return states;
2021-12-26 08:15:15 +00:00
}
QVariant QskMenuSkinlet::sampleAt( const QskSkinnable* skinnable,
2021-12-28 14:33:13 +00:00
QskAspect::Subcontrol subControl, int index ) const
{
using Q = QskMenu;
const auto menu = static_cast< const QskMenu* >( skinnable );
if ( subControl == Q::Graphic )
return qskSampleAt< QskGraphic >( menu, index );
2021-12-28 14:33:13 +00:00
if ( subControl == Q::Text )
return qskSampleAt< QString >( menu, index );
2021-12-28 14:33:13 +00:00
return Inherited::sampleAt( skinnable, subControl, index );
2021-12-28 14:33:13 +00:00
}
2021-12-23 17:36:32 +00:00
QSGNode* QskMenuSkinlet::updateContentsNode(
const QskPopup* popup, QSGNode* contentsNode ) const
{
2021-12-28 14:33:13 +00:00
const PrivateData::CacheGuard guard( m_data.get() );
return updateMenuNode( popup, contentsNode );
}
QSGNode* QskMenuSkinlet::updateMenuNode(
const QskSkinnable* skinnable, QSGNode* contentsNode ) const
{
enum { Panel, Segment, Cursor, Graphic, Text, Separator };
static QVector< quint8 > roles = { Panel, Separator, Segment, Cursor, Graphic, Text };
2021-12-23 17:36:32 +00:00
if ( contentsNode == nullptr )
contentsNode = new QSGNode();
for ( const auto role : roles )
{
auto oldNode = QskSGNode::findChildNode( contentsNode, role );
2021-12-24 15:20:34 +00:00
QSGNode* newNode = nullptr;
2021-12-23 17:36:32 +00:00
switch( role )
{
case Panel:
{
2021-12-28 14:33:13 +00:00
newNode = updateBoxNode( skinnable, oldNode, QskMenu::Panel );
2021-12-23 17:36:32 +00:00
break;
}
case Segment:
2021-12-23 17:36:32 +00:00
{
newNode = updateSeriesNode( skinnable, QskMenu::Segment, oldNode );
2021-12-23 17:36:32 +00:00
break;
}
case Cursor:
{
2021-12-28 14:33:13 +00:00
newNode = updateBoxNode( skinnable, oldNode, QskMenu::Cursor );
2021-12-23 17:36:32 +00:00
break;
}
2021-12-28 14:33:13 +00:00
case Graphic:
2021-12-23 17:36:32 +00:00
{
2021-12-28 14:33:13 +00:00
newNode = updateSeriesNode( skinnable, QskMenu::Graphic, oldNode );
break;
}
case Text:
{
newNode = updateSeriesNode( skinnable, QskMenu::Text, oldNode );
2021-12-23 17:36:32 +00:00
break;
2021-12-23 18:05:59 +00:00
}
2022-01-06 17:36:15 +00:00
case Separator:
{
newNode = updateSeriesNode( skinnable, QskMenu::Separator, oldNode );
break;
}
2021-12-23 17:36:32 +00:00
}
QskSGNode::replaceChildNode( roles, role, contentsNode, oldNode, newNode );
}
return contentsNode;
}
QSGNode* QskMenuSkinlet::updateSampleNode( const QskSkinnable* skinnable,
2021-12-28 14:33:13 +00:00
QskAspect::Subcontrol subControl, int index, QSGNode* node ) const
{
using Q = QskMenu;
auto menu = static_cast< const QskMenu* >( skinnable );
const auto rect = sampleRect( menu, menu->contentsRect(), subControl, index );
2021-12-28 14:33:13 +00:00
if ( subControl == Q::Segment )
2021-12-28 14:33:13 +00:00
{
return updateBoxNode( menu, node, rect, subControl );
}
if ( subControl == Q::Graphic )
{
const auto graphic = qskValueAt< QskGraphic >( menu, index );
if ( graphic.isNull() )
return nullptr;
2021-12-28 14:33:13 +00:00
const auto alignment = menu->alignmentHint( subControl, Qt::AlignCenter );
const auto filter = menu->effectiveGraphicFilter( subControl );
return QskSkinlet::updateGraphicNode(
menu, node, graphic, filter, rect, alignment );
2021-12-28 14:33:13 +00:00
}
if ( subControl == Q::Text )
{
const auto text = qskValueAt< QString >( menu, index );
if ( text.isEmpty() )
return nullptr;
2021-12-28 14:33:13 +00:00
const auto alignment = menu->alignmentHint(
subControl, Qt::AlignVCenter | Qt::AlignLeft );
return QskSkinlet::updateTextNode( menu, node, rect, alignment,
text, menu->textOptions(), Q::Text );
2022-01-06 17:36:15 +00:00
}
if ( subControl == Q::Separator )
{
return updateBoxNode( menu, node, rect, subControl );
2021-12-28 14:33:13 +00:00
}
return nullptr;
}
2021-12-23 17:36:32 +00:00
QSizeF QskMenuSkinlet::sizeHint( const QskSkinnable* skinnable,
Qt::SizeHint which, const QSizeF& ) const
{
if ( which != Qt::PreferredSize )
return QSizeF();
2022-01-06 17:36:15 +00:00
using Q = QskMenu;
const auto menu = static_cast< const QskMenu* >( skinnable );
2021-12-28 14:33:13 +00:00
2022-01-06 17:36:15 +00:00
const PrivateData::CacheGuard guard( m_data.get() );
2021-12-28 14:33:13 +00:00
qreal w = 0.0;
qreal h = 0.0;
if ( const auto count = sampleCount( skinnable, Q::Segment ) )
2021-12-28 14:33:13 +00:00
{
w = m_data->segmentWidth( menu );
h = count * m_data->segmentHeight( menu );
2021-12-28 14:33:13 +00:00
}
2021-12-23 17:36:32 +00:00
2022-01-06 17:36:15 +00:00
if ( const auto count = sampleCount( skinnable, Q::Separator ) )
{
h += count * menu->metric( Q::Separator | QskAspect::Size );
}
2021-12-28 14:33:13 +00:00
auto hint = skinnable->outerBoxSize( QskMenu::Panel, QSizeF( w, h ) );
hint = hint.expandedTo( skinnable->strutSizeHint( QskMenu::Panel ) );
2021-12-23 17:36:32 +00:00
2021-12-28 14:33:13 +00:00
return hint;
2021-12-23 17:36:32 +00:00
}
#include "moc_QskMenuSkinlet.cpp"