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 <QskPlatform.h>
#include <qguiapplication.h>
#include <qscreen.h>
static const int qskDuration = 150;
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
{
public:
@ -453,12 +487,16 @@ void Editor::setupPushButton()
setBoxShape( Q::Panel, 100, Qt::RelativeSize );
setAlignment( Q::Graphic | A::Alignment, Qt::AlignLeft );
setPadding( Q::Graphic, 5 );
setAlignment( Q::Graphic | A::Alignment, Qt::AlignCenter );
setStrutSize( Q::Graphic, 24_dp, 24_dp );
setPadding( Q::Graphic, 0 );
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):

View File

@ -230,6 +230,31 @@ void QskPushButton::updateResources()
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
{
return subControlContentsRect( size, Panel );

View File

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

View File

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

View File

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