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