temporary improvements for push buttons - until we have a general layout class

for graphic/text combinations
This commit is contained in:
Uwe Rathmann 2022-08-03 18:28:53 +02:00
parent 3763bd5bad
commit bc5510f7ef
5 changed files with 147 additions and 60 deletions

View File

@ -45,10 +45,44 @@
#include <QskNamespace.h> #include <QskNamespace.h>
#include <QskPlatform.h> #include <QskPlatform.h>
#include <qguiapplication.h>
#include <qscreen.h>
static const int qskDuration = 150; static const int qskDuration = 150;
namespace namespace
{ {
// see: https://en.wikipedia.org/wiki/Device-independent_pixel
inline qreal dpToPixels( long double value )
{
static qreal factor = -1.0;
if ( factor < 0.0 )
{
factor = 1.0;
#if 0
if ( const auto screen = QGuiApplication::primaryScreen() )
{
// is this calculation correct ? TODO ...
factor = screen->logicalDotsPerInch() / 160.0;
}
#endif
}
return value * factor;
}
inline double operator ""_dp( long double value )
{
return dpToPixels( value );
}
inline double operator ""_dp( unsigned long long int value )
{
return dpToPixels( value );
}
class Editor : private QskSkinHintTableEditor class Editor : private QskSkinHintTableEditor
{ {
public: public:
@ -453,12 +487,16 @@ void Editor::setupPushButton()
setBoxShape( Q::Panel, 100, Qt::RelativeSize ); setBoxShape( Q::Panel, 100, Qt::RelativeSize );
setAlignment( Q::Graphic | A::Alignment, Qt::AlignLeft ); setAlignment( Q::Graphic | A::Alignment, Qt::AlignCenter );
setPadding( Q::Graphic, 5 ); setStrutSize( Q::Graphic, 24_dp, 24_dp );
setPadding( Q::Graphic, 0 );
setFontRole( Q::Text, QskMaterial3Skin::M3LabelLarge ); setFontRole( Q::Text, QskMaterial3Skin::M3LabelLarge );
setAlignment( Q::Text, Qt::AlignCenter ); setPadding( Q::Text, 0 );
setAlignment( Q::Text | A::Alignment, Qt::AlignCenter );
setAlignment( Q::Text | A::Alignment | A::Horizontal,
Qt::AlignLeft | Qt::AlignVCenter );
// normal buttons (i.e. Filled): // normal buttons (i.e. Filled):

View File

@ -230,6 +230,31 @@ void QskPushButton::updateResources()
m_data->ensureGraphic( this ); m_data->ensureGraphic( this );
} }
QskAspect::Placement QskPushButton::effectivePlacement() const
{
if ( hasGraphic() && !text().isEmpty() )
{
// for the moment we only support the direction. TODO ...
auto aspect = Panel | QskAspect::Direction;
aspect.setPlacement( QskAspect::Vertical ); // to avoid recursions TODO ...
const auto dir = flagHint( aspect, Qsk::LeftToRight );
switch( dir )
{
case Qsk::LeftToRight:
case Qsk::RightToLeft:
return QskAspect::Horizontal;
case Qsk::TopToBottom:
case Qsk::BottomToTop:
return QskAspect::Vertical;
}
}
return Inherited::effectivePlacement();
}
QRectF QskPushButton::layoutRectForSize( const QSizeF& size ) const QRectF QskPushButton::layoutRectForSize( const QSizeF& size ) const
{ {
return subControlContentsRect( size, Panel ); return subControlContentsRect( size, Panel );

View File

@ -72,6 +72,7 @@ class QSK_EXPORT QskPushButton : public QskAbstractButton
QFont font() const; QFont font() const;
QRectF layoutRectForSize( const QSizeF& ) const override; QRectF layoutRectForSize( const QSizeF& ) const override;
QskAspect::Placement effectivePlacement() const override;
public Q_SLOTS: public Q_SLOTS:
void setText( const QString& ); void setText( const QString& );

View File

@ -105,12 +105,12 @@ QRectF QskPushButtonSkinlet::textRect(
if ( r.isEmpty() || !button->hasGraphic() ) if ( r.isEmpty() || !button->hasGraphic() )
return r; return r;
if ( qskOrientation( button ) == Qt::Horizontal )
{
/* /*
For horizontal layouts Text depends on Graphic, while For horizontal layouts Text depends on Graphic, while
for vertical Graphic depends on Text. Confusing ... for vertical Graphic depends on Text. Confusing ...
*/ */
if ( qskOrientation( button ) == Qt::Horizontal )
{
const auto graphicsRect = subControlRect( button, contentsRect, Q::Graphic ); const auto graphicsRect = subControlRect( button, contentsRect, Q::Graphic );
const auto spacing = button->spacingHint( Q::Panel ); const auto spacing = button->spacingHint( Q::Panel );
@ -136,9 +136,17 @@ QRectF QskPushButtonSkinlet::graphicRect(
return r; return r;
const auto orientation = qskOrientation( button ); const auto orientation = qskOrientation( button );
const auto maxSize = button->strutSizeHint( Q::Graphic );
const qreal maxW = maxSize.width();
const qreal maxH = maxSize.height();
if ( orientation == Qt::Vertical ) if ( orientation == Qt::Vertical )
{ {
/*
For horizontal layouts Text depends on Graphic, while
for vertical Graphic depends on Text. Confusing ...
*/
const auto textRect = subControlRect( button, contentsRect, Q::Text ); const auto textRect = subControlRect( button, contentsRect, Q::Text );
const auto h = textRect.height() + button->spacingHint( Q::Panel ); const auto h = textRect.height() + button->spacingHint( Q::Panel );
@ -146,15 +154,10 @@ QRectF QskPushButtonSkinlet::graphicRect(
return QRectF(); return QRectF();
r.setBottom( r.bottom() - h ); r.setBottom( r.bottom() - h );
}
const auto maxSize = button->strutSizeHint( Q::Graphic ); if ( maxW >= 0 || maxH >= 0 )
if ( maxSize.width() >= 0 || maxSize.height() >= 0 )
{ {
// limiting the size by graphicSize // limiting the size by maxSize
const qreal maxW = maxSize.width();
const qreal maxH = maxSize.height();
if ( maxW >= 0.0 && maxW < r.width() ) if ( maxW >= 0.0 && maxW < r.width() )
{ {
@ -168,6 +171,23 @@ QRectF QskPushButtonSkinlet::graphicRect(
r.setHeight( maxH ); r.setHeight( maxH );
} }
} }
}
else
{
if ( maxW >= 0 || maxH >= 0 )
{
if ( maxW >= 0.0 && maxW < r.width() )
{
r.setWidth( maxW );
}
if ( maxH >= 0.0 && maxH < r.height() )
{
r.setY( r.center().y() - 0.5 * maxH );
r.setHeight( maxH );
}
}
}
r = r.marginsRemoved( button->paddingHint( Q::Graphic ) ); r = r.marginsRemoved( button->paddingHint( Q::Graphic ) );
@ -178,10 +198,10 @@ QRectF QskPushButtonSkinlet::graphicRect(
{ {
sz.scale( r.size(), Qt::KeepAspectRatio ); sz.scale( r.size(), Qt::KeepAspectRatio );
const auto align = ( orientation == Qt::Horizontal ) if ( orientation == Qt::Vertical )
? ( Qt::AlignLeft | Qt::AlignTop ) : Qt::AlignCenter; r = qskAlignedRectF( r, sz, Qt::AlignCenter );
else
r = qskAlignedRectF( r, sz.width(), sz.height(), align ); r = qskAlignedRectF( r, sz, Qt::AlignLeft | Qt::AlignVCenter );
} }
} }
@ -267,7 +287,7 @@ QSizeF QskPushButtonSkinlet::sizeHint( const QskSkinnable* skinnable,
QSizeF size( 0, 0 ); QSizeF size( 0, 0 );
const QFontMetricsF fm( button->effectiveFont( QskPushButton::Text ) ); const QFontMetricsF fm( button->effectiveFont( Q::Text ) );
if ( !button->text().isEmpty() ) if ( !button->text().isEmpty() )
{ {
@ -278,47 +298,20 @@ QSizeF QskPushButtonSkinlet::sizeHint( const QskSkinnable* skinnable,
if ( button->hasGraphic() ) if ( button->hasGraphic() )
{ {
const auto sz = button->strutSizeHint( Q::Graphic ); const auto hint = graphicSizeHint( button );
qreal w = sz.width();
qreal h = sz.height();
if ( w < 0.0 || h < 0.0 )
{
const auto graphic = button->graphic();
if ( !graphic.isEmpty() )
{
if ( ( w < 0.0 ) && ( h < 0.0 ) )
{
// strutSizeHint( Graphic ) ???
h = 1.5 * fm.height();
}
if ( w < 0 )
{
w = graphic.widthForHeight( h );
}
else if ( h < 0 )
{
h = graphic.heightForWidth( w );
}
}
}
const auto padding = button->paddingHint( Q::Graphic ); const auto padding = button->paddingHint( Q::Graphic );
const auto orientation = qskOrientation( button ); const auto orientation = qskOrientation( button );
if( orientation == Qt::Horizontal ) if( orientation == Qt::Horizontal )
{ {
size.rwidth() += padding.left() + w + padding.right(); size.rwidth() += padding.left() + hint.width() + padding.right();
size.rheight() = qMax( size.height(), h ); size.rheight() = qMax( size.height(), hint.height() );
} }
else else
{ {
size.rheight() += padding.top() + h + padding.bottom(); size.rheight() += padding.top() + hint.height() + padding.bottom();
size.rwidth() = qMax( size.width(), w ); size.rwidth() = qMax( size.width(), hint.width() );
} }
} }
@ -328,4 +321,32 @@ QSizeF QskPushButtonSkinlet::sizeHint( const QskSkinnable* skinnable,
return size; return size;
} }
QSizeF QskPushButtonSkinlet::graphicSizeHint( const QskPushButton* button ) const
{
using Q = QskPushButton;
auto size = button->strutSizeHint( Q::Graphic );
if ( !size.isEmpty() )
return size;
const auto& graphic = button->graphic();
auto w = size.width();
auto h = size.height();
if ( w > 0.0 )
{
h = graphic.heightForWidth( w );
}
else
{
if ( h <= 0.0 )
h = 1.5 * button->effectiveFontHeight( Q::Text );
w = graphic.widthForHeight( h );
}
return QSizeF( w, h );
}
#include "moc_QskPushButtonSkinlet.cpp" #include "moc_QskPushButtonSkinlet.cpp"

View File

@ -45,6 +45,8 @@ class QSK_EXPORT QskPushButtonSkinlet : public QskSkinlet
QRectF graphicRect( const QskPushButton*, const QRectF& ) const; QRectF graphicRect( const QskPushButton*, const QRectF& ) const;
QRectF rippleRect( const QskPushButton*, const QRectF& ) const; QRectF rippleRect( const QskPushButton*, const QRectF& ) const;
QSizeF graphicSizeHint( const QskPushButton* ) const;
QSGNode* updateTextNode( const QskPushButton*, QSGNode* ) const; QSGNode* updateTextNode( const QskPushButton*, QSGNode* ) const;
QSGNode* updateRippleNode( const QskPushButton*, QSGNode* ) const; QSGNode* updateRippleNode( const QskPushButton*, QSGNode* ) const;
}; };