menu separators added
This commit is contained in:
parent
8b5077ed2b
commit
36001a6fec
@ -88,10 +88,11 @@ class GraphicLabel : public QskGraphicLabel
|
||||
QskMenu menu( this );
|
||||
menu.setPopupFlag( QskPopup::DeleteOnClose, false );
|
||||
|
||||
menu.addItem( "image://shapes/Rectangle/White", "Print" );
|
||||
menu.addItem( "image://shapes/Diamond/Yellow", "Save As" );
|
||||
menu.addItem( "image://shapes/Ellipse/Red", "Setup" );
|
||||
menu.addItem( "image://shapes/Hexagon/PapayaWhip", "Help" );
|
||||
menu.addOption( "image://shapes/Rectangle/White", "Print" );
|
||||
menu.addOption( "image://shapes/Diamond/Yellow", "Save As" );
|
||||
menu.addOption( "image://shapes/Ellipse/Red", "Setup" );
|
||||
menu.addSeparator();
|
||||
menu.addOption( "image://shapes/Hexagon/PapayaWhip", "Help" );
|
||||
|
||||
menu.setOrigin( qskMousePosition( event ) );
|
||||
|
||||
|
@ -317,9 +317,9 @@ void Editor::setupMenu()
|
||||
|
||||
#if 0
|
||||
setPadding( Q::Separator, QMarginsF( 10, 0, 10, 0 ) );
|
||||
setMetric( Q::Separator | QskAspect::Size, 3 );
|
||||
setVGradient( Q::Separator, c2, c1 );
|
||||
#endif
|
||||
setMetric( Q::Separator | A::Size, 2 );
|
||||
setSeparator( Q::Separator | A::Horizontal );
|
||||
|
||||
setPadding( Q::Cell, QskMargins( 2, 10, 2, 10 ) );
|
||||
setSpacing( Q::Cell, 5 );
|
||||
|
@ -16,23 +16,35 @@ QSK_SUBCONTROL( QskMenu, Cell )
|
||||
QSK_SUBCONTROL( QskMenu, Cursor )
|
||||
QSK_SUBCONTROL( QskMenu, Text )
|
||||
QSK_SUBCONTROL( QskMenu, Graphic )
|
||||
QSK_SUBCONTROL( QskMenu, Separator )
|
||||
|
||||
QSK_SYSTEM_STATE( QskMenu, Selected, QskAspect::FirstSystemState << 2 )
|
||||
|
||||
namespace
|
||||
{
|
||||
struct Entry
|
||||
class Option
|
||||
{
|
||||
QUrl graphicSource;
|
||||
public:
|
||||
Option( const QUrl& graphicSource, const QString& text )
|
||||
: graphicSource( graphicSource )
|
||||
, text( text )
|
||||
{
|
||||
if( !graphicSource.isEmpty() )
|
||||
graphic = Qsk::loadGraphic( graphicSource );
|
||||
}
|
||||
|
||||
const QUrl graphicSource;
|
||||
const QString text;
|
||||
|
||||
QskGraphic graphic;
|
||||
QString text;
|
||||
};
|
||||
}
|
||||
|
||||
class QskMenu::PrivateData
|
||||
{
|
||||
public:
|
||||
QVector< Entry > entries;
|
||||
QVector< Option > options;
|
||||
QVector< int > separators;
|
||||
|
||||
QskTextOptions textOptions;
|
||||
QPointF origin;
|
||||
@ -94,13 +106,9 @@ QPointF QskMenu::origin() const
|
||||
return m_data->origin;
|
||||
}
|
||||
|
||||
void QskMenu::addItem( const QUrl& graphicSource, const QString& text )
|
||||
void QskMenu::addOption( const QUrl& graphicSource, const QString& text )
|
||||
{
|
||||
QskGraphic graphic;
|
||||
if( !graphicSource.isEmpty() )
|
||||
graphic = Qsk::loadGraphic( graphicSource );
|
||||
|
||||
m_data->entries += { graphicSource, graphic, text };
|
||||
m_data->options += Option( graphicSource, text );
|
||||
|
||||
resetImplicitSize();
|
||||
update();
|
||||
@ -109,38 +117,52 @@ void QskMenu::addItem( const QUrl& graphicSource, const QString& text )
|
||||
countChanged( count() );
|
||||
}
|
||||
|
||||
void QskMenu::addItem( const QString& graphicSource, const QString& text )
|
||||
void QskMenu::addOption( const QString& graphicSource, const QString& text )
|
||||
{
|
||||
addItem( QUrl( graphicSource ), text );
|
||||
}
|
||||
|
||||
void QskMenu::addSeparator()
|
||||
{
|
||||
// TODO ...
|
||||
}
|
||||
|
||||
void QskMenu::clear()
|
||||
{
|
||||
m_data->entries.clear();
|
||||
addOption( QUrl( graphicSource ), text );
|
||||
}
|
||||
|
||||
int QskMenu::count() const
|
||||
{
|
||||
return m_data->entries.count();
|
||||
return m_data->options.count();
|
||||
}
|
||||
|
||||
QVariant QskMenu::itemAt( int index ) const
|
||||
void QskMenu::addSeparator()
|
||||
{
|
||||
const auto& entries = m_data->entries;
|
||||
m_data->separators += m_data->options.count();
|
||||
|
||||
if( index < 0 || index >= entries.count() )
|
||||
return QVariant();
|
||||
resetImplicitSize();
|
||||
update();
|
||||
}
|
||||
|
||||
const auto& entry = m_data->entries[ index ];
|
||||
int QskMenu::separatorPosition( int index ) const
|
||||
{
|
||||
return m_data->separators.value( index, -1 );
|
||||
}
|
||||
|
||||
int QskMenu::separatorCount() const
|
||||
{
|
||||
return m_data->separators.count();
|
||||
}
|
||||
|
||||
void QskMenu::clear()
|
||||
{
|
||||
m_data->options.clear();
|
||||
m_data->separators.clear();
|
||||
}
|
||||
|
||||
QVariantList QskMenu::optionAt( int index ) const
|
||||
{
|
||||
const auto& options = m_data->options;
|
||||
|
||||
if( index < 0 || index >= options.count() )
|
||||
return QVariantList();
|
||||
|
||||
const auto& option = options[ index ];
|
||||
|
||||
QVariantList list;
|
||||
list += QVariant::fromValue( entry.graphic );
|
||||
list += QVariant::fromValue( entry.text );
|
||||
list += QVariant::fromValue( option.graphic );
|
||||
list += QVariant::fromValue( option.text );
|
||||
|
||||
return list;
|
||||
}
|
||||
@ -270,12 +292,6 @@ void QskMenu::traverse( int steps )
|
||||
setCurrentIndex( newIndex );
|
||||
}
|
||||
|
||||
QskColorFilter QskMenu::graphicFilterAt( int index ) const
|
||||
{
|
||||
Q_UNUSED( index )
|
||||
return QskColorFilter();
|
||||
}
|
||||
|
||||
void QskMenu::mousePressEvent( QMouseEvent* event )
|
||||
{
|
||||
// QGuiApplication::styleHints()->setFocusOnTouchRelease ??
|
||||
|
@ -32,7 +32,7 @@ class QSK_EXPORT QskMenu : public QskPopup
|
||||
using Inherited = QskPopup;
|
||||
|
||||
public:
|
||||
QSK_SUBCONTROLS( Panel, Cell, Cursor, Text, Graphic )
|
||||
QSK_SUBCONTROLS( Panel, Cell, Cursor, Text, Graphic, Separator )
|
||||
QSK_STATES( Selected )
|
||||
|
||||
QskMenu( QQuickItem* parentItem = nullptr );
|
||||
@ -45,22 +45,25 @@ class QSK_EXPORT QskMenu : public QskPopup
|
||||
void setOrigin( const QPointF& );
|
||||
QPointF origin() const;
|
||||
|
||||
// insert, remove, functors, actions, QskGraphic ...
|
||||
void addItem( const QUrl& graphicSource, const QString& text );
|
||||
void addItem( const QString& graphicSource, const QString& text );
|
||||
|
||||
void addSeparator();
|
||||
|
||||
virtual QVariant itemAt( int ) const;
|
||||
virtual int count() const;
|
||||
virtual void clear();
|
||||
|
||||
void setTextOptions( const QskTextOptions& textOptions );
|
||||
QskTextOptions textOptions() const;
|
||||
|
||||
// insert, remove, functors, actions, QskGraphic ...
|
||||
void addOption( const QUrl& graphicSource, const QString& text );
|
||||
void addOption( const QString& graphicSource, const QString& text );
|
||||
|
||||
QVariantList optionAt( int ) const;
|
||||
int count() const;
|
||||
|
||||
void addSeparator();
|
||||
|
||||
int separatorPosition( int ) const;
|
||||
int separatorCount() const;
|
||||
|
||||
void clear();
|
||||
|
||||
int currentIndex() const;
|
||||
|
||||
virtual QskColorFilter graphicFilterAt( int index ) const;
|
||||
QRectF focusIndicatorRect() const override;
|
||||
|
||||
QRectF cellRect( int index ) const;
|
||||
|
@ -19,20 +19,12 @@
|
||||
template< class T >
|
||||
static inline QVariant qskSampleAt( const QskMenu* menu, int index )
|
||||
{
|
||||
const auto item = menu->itemAt( index );
|
||||
|
||||
if ( item.canConvert< T >() )
|
||||
return item;
|
||||
|
||||
if ( item.canConvert< QVariantList >() )
|
||||
{
|
||||
const auto list = item.value< QVariantList >();
|
||||
const auto list = menu->optionAt( index );
|
||||
for ( const auto& value : list )
|
||||
{
|
||||
if ( value.canConvert< T >() )
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
@ -70,6 +62,18 @@ class QskMenuSkinlet::PrivateData
|
||||
m_cellHeight = m_cellWidth = m_graphicWidth = m_textWidth = -1.0;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
inline qreal graphicWidth( const QskMenu* menu ) const
|
||||
{
|
||||
if ( m_isCaching )
|
||||
@ -291,7 +295,16 @@ QRectF QskMenuSkinlet::sampleRect(
|
||||
if ( subControl == Q::Cell )
|
||||
{
|
||||
const auto r = menu->subControlContentsRect( Q::Panel );
|
||||
const auto h = m_data->cellHeight( menu );
|
||||
|
||||
auto h = m_data->cellHeight( menu );
|
||||
|
||||
if ( int n = m_data->separatorsBefore( menu, index ) )
|
||||
{
|
||||
// spacing ???
|
||||
|
||||
const qreal separatorH = menu->metric( Q::Separator | QskAspect::Size );
|
||||
h += n * separatorH;
|
||||
}
|
||||
|
||||
return QRectF( r.x(), r.y() + index * h, r.width(), h );
|
||||
}
|
||||
@ -322,6 +335,26 @@ QRectF QskMenuSkinlet::sampleRect(
|
||||
}
|
||||
}
|
||||
|
||||
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 cellRect = sampleRect( skinnable, contentsRect, Q::Cell, pos );
|
||||
r.setBottom( cellRect.top() ); // spacing ???
|
||||
}
|
||||
|
||||
const qreal h = menu->metric( Q::Separator | QskAspect::Size );
|
||||
r.setTop( r.bottom() - h );
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
return Inherited::sampleRect(
|
||||
skinnable, contentsRect, subControl, index );
|
||||
}
|
||||
@ -345,6 +378,12 @@ int QskMenuSkinlet::sampleCount(
|
||||
return menu->count();
|
||||
}
|
||||
|
||||
if ( subControl == Q::Separator )
|
||||
{
|
||||
const auto menu = static_cast< const QskMenu* >( skinnable );
|
||||
return menu->separatorCount();
|
||||
}
|
||||
|
||||
return Inherited::sampleCount( skinnable, subControl );
|
||||
}
|
||||
|
||||
@ -391,8 +430,8 @@ QSGNode* QskMenuSkinlet::updateContentsNode(
|
||||
QSGNode* QskMenuSkinlet::updateMenuNode(
|
||||
const QskSkinnable* skinnable, QSGNode* contentsNode ) const
|
||||
{
|
||||
enum { Panel, Background, Cursor, Graphic, Text };
|
||||
static QVector< quint8 > roles = { Panel, Background, Cursor, Graphic, Text };
|
||||
enum { Panel, Cell, Cursor, Graphic, Text, Separator };
|
||||
static QVector< quint8 > roles = { Panel, Separator, Cell, Cursor, Graphic, Text };
|
||||
|
||||
if ( contentsNode == nullptr )
|
||||
contentsNode = new QSGNode();
|
||||
@ -410,7 +449,7 @@ QSGNode* QskMenuSkinlet::updateMenuNode(
|
||||
newNode = updateBoxNode( skinnable, oldNode, QskMenu::Panel );
|
||||
break;
|
||||
}
|
||||
case Background:
|
||||
case Cell:
|
||||
{
|
||||
newNode = updateSeriesNode( skinnable, QskMenu::Cell, oldNode );
|
||||
break;
|
||||
@ -430,6 +469,11 @@ QSGNode* QskMenuSkinlet::updateMenuNode(
|
||||
newNode = updateSeriesNode( skinnable, QskMenu::Text, oldNode );
|
||||
break;
|
||||
}
|
||||
case Separator:
|
||||
{
|
||||
newNode = updateSeriesNode( skinnable, QskMenu::Separator, oldNode );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
QskSGNode::replaceChildNode( roles, role, contentsNode, oldNode, newNode );
|
||||
@ -475,34 +519,42 @@ QSGNode* QskMenuSkinlet::updateSampleNode( const QskSkinnable* skinnable,
|
||||
subControl, Qt::AlignVCenter | Qt::AlignLeft );
|
||||
|
||||
return QskSkinlet::updateTextNode( menu, node, rect, alignment,
|
||||
text, menu->textOptions(), QskMenu::Text );
|
||||
text, QskTextOptions(), Q::Text );
|
||||
}
|
||||
|
||||
if ( subControl == Q::Separator )
|
||||
{
|
||||
return updateBoxNode( menu, node, rect, subControl );
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
QSizeF QskMenuSkinlet::sizeHint( const QskSkinnable* skinnable,
|
||||
Qt::SizeHint which, const QSizeF& ) const
|
||||
{
|
||||
if ( which != Qt::PreferredSize )
|
||||
return QSizeF();
|
||||
|
||||
const PrivateData::CacheGuard guard( m_data.get() );
|
||||
using Q = QskMenu;
|
||||
const auto menu = static_cast< const QskMenu* >( skinnable );
|
||||
|
||||
const auto count = sampleCount( skinnable, QskMenu::Cell );
|
||||
const PrivateData::CacheGuard guard( m_data.get() );
|
||||
|
||||
qreal w = 0.0;
|
||||
qreal h = 0.0;
|
||||
|
||||
if ( count > 0 )
|
||||
if ( const auto count = sampleCount( skinnable, Q::Cell ) )
|
||||
{
|
||||
const auto menu = static_cast< const QskMenu* >( skinnable );
|
||||
|
||||
w = m_data->cellWidth( menu );
|
||||
h = count * m_data->cellHeight( menu );
|
||||
}
|
||||
|
||||
if ( const auto count = sampleCount( skinnable, Q::Separator ) )
|
||||
{
|
||||
h += count * menu->metric( Q::Separator | QskAspect::Size );
|
||||
}
|
||||
|
||||
auto hint = skinnable->outerBoxSize( QskMenu::Panel, QSizeF( w, h ) );
|
||||
hint = hint.expandedTo( skinnable->strutSizeHint( QskMenu::Panel ) );
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user