6#include "QskSpinBoxSkinlet.h"
8#include "QskFunctions.h"
9#include "QskSkinStateChanger.h"
11#include <qfontmetrics.h>
14static bool qskIsButtonHovered(
26 const auto pos = spinBox->mapFromGlobal( QCursor::pos() );
27 return r.contains( pos );
34static inline QskAspect::States qskButtonStates(
39 auto spinBox =
static_cast< const QskSpinBox*
>( skinnable );
41 auto states = spinBox->skinStates();
43 if ( spinBox->isEnabled() )
45 if ( subControl == Q::DownIndicator || subControl == Q::DownPanel )
47 if ( !spinBox->isWrapping() && spinBox->value() <= spinBox->minimum() )
50 if ( !qskIsButtonHovered( spinBox, Q::DownPanel ) )
53 else if ( subControl == Q::UpIndicator || subControl == Q::UpPanel )
55 if ( !spinBox->isWrapping() && spinBox->value() >= spinBox->maximum() )
58 if ( !qskIsButtonHovered( spinBox, Q::UpPanel ) )
66QskSpinBoxSkinlet::QskSpinBoxSkinlet(
QskSkin* )
68 setNodeRoles( { PanelRole, UpPanelRole, DownPanelRole, TextPanelRole,
69 UpIndicatorRole, DownIndicatorRole, TextRole } );
72QRectF QskSpinBoxSkinlet::subControlRect(
const QskSkinnable* skinnable,
78 stateChanger.setStates( qskButtonStates( skinnable, subControl ) );
80 if ( subControl == Q::Panel )
83 if ( subControl == Q::DownIndicator )
86 if ( subControl == Q::UpIndicator )
89 if ( subControl == Q::Text )
92 if ( subControl == Q::DownPanel || subControl == Q::UpPanel )
93 return buttonRect( skinnable, contentsRect, subControl );
95 if ( subControl == Q::TextPanel )
96 return textPanelRect( skinnable, contentsRect );
98 return Inherited::subControlRect( skinnable, contentsRect, subControl );
101QSGNode* QskSpinBoxSkinlet::updateSubNode(
102 const QskSkinnable* skinnable,
const quint8 nodeRole, QSGNode*
const node )
const
112 return updateBoxNode( skinnable, node, Q::Panel );
117 stateChanger.setStates( qskButtonStates( skinnable, Q::UpPanel ) );
118 return updateBoxNode( skinnable, node, Q::UpPanel );
123 stateChanger.setStates( qskButtonStates( skinnable, Q::DownPanel ) );
124 return updateBoxNode( skinnable, node, Q::DownPanel );
127 case UpIndicatorRole:
129 stateChanger.setStates( qskButtonStates( skinnable, Q::UpIndicator ) );
130 return updateSymbolNode( skinnable, node, Q::UpIndicator );
133 case DownIndicatorRole:
135 stateChanger.setStates( qskButtonStates( skinnable, Q::DownIndicator ) );
136 return updateSymbolNode( skinnable, node, Q::DownIndicator );
141 return updateBoxNode( skinnable, node, Q::TextPanel );
146 auto spinBox =
static_cast< const QskSpinBox*
>( skinnable );
147 return updateTextNode( spinBox, node, spinBox->valueText(), Q::Text );
151 return Inherited::updateSubNode( skinnable, nodeRole, node );
154QRectF QskSpinBoxSkinlet::textPanelRect(
155 const QskSkinnable* skinnable,
const QRectF& rect )
const
159 auto spinBox =
static_cast< const QskSpinBox*
>( skinnable );
161 auto r = spinBox->
innerBox( Q::Panel, rect );
163 const auto decoration = spinBox->decoration();
164 if ( decoration == Q::NoDecoration )
167 const auto spacing = spinBox->
spacingHint( Q::Panel );
169 if ( decoration == Q::UpDownControl )
171 const auto w = subControlRect( skinnable, rect, Q::UpPanel ).width();
173 r.setRight( r.right() - spacing - w );
175 else if ( decoration == Q::ButtonsRight )
177 const auto w1 = subControlRect( skinnable, rect, Q::DownPanel ).width();
179 r.setRight( r.right() - w1 - spacing );
181 const auto w2 = subControlRect( skinnable, rect, Q::UpPanel ).width();
183 r.setRight( r.right() - w2 - spacing );
187 const auto w1 = subControlRect( skinnable, rect, Q::DownPanel ).width();
189 r.setLeft( r.left() + w1 + spacing );
191 const auto w2 = subControlRect( skinnable, rect, Q::UpPanel ).width();
193 r.setRight( r.right() - w2 - spacing );
199QRectF QskSpinBoxSkinlet::buttonRect(
const QskSkinnable* skinnable,
204 const auto spinBox =
static_cast< const QskSpinBox*
>( skinnable );
206 const auto rect = spinBox->
innerBox( Q::Panel, contentsRect );
208 if (
const auto decoration = spinBox->decoration() )
212 if ( decoration == Q::UpDownControl )
217 w = std::max( hint1.width(), hint2.width() );
221 h = 0.5 * rect.height();
223 x = rect.right() - w;
224 y = ( subControl == Q::UpPanel ) ? rect.top() : rect.bottom() - h;
226 else if ( decoration == Q::ButtonsRight )
238 if( subControl == Q::UpPanel )
240 const auto downRect = subControlRect( skinnable, contentsRect, Q::DownPanel );
241 x = downRect.left() - w;
245 x = rect.right() - w;
248 y = rect.top() + 0.5 * ( rect.height() - h );
262 x = ( subControl == Q::UpPanel ) ? rect.right() - w : rect.left();
263 y = rect.top() + 0.5 * ( rect.height() - h );
266 return QRectF( x, y, w, h );
272QSizeF QskSpinBoxSkinlet::sizeHint(
const QskSkinnable* skinnable,
273 Qt::SizeHint which,
const QSizeF& )
const
275 if ( which != Qt::PreferredSize )
280 const auto spinBox =
static_cast< const QskSpinBox*
>( skinnable );
288 const auto w1 = qskHorizontalAdvance( fm,
289 spinBox->textFromValue( spinBox->minimum() ).left( 18 ) );
291 const auto w2 = qskHorizontalAdvance( fm,
292 spinBox->textFromValue( spinBox->maximum() ).left( 18 ) );
294 hint.setWidth( std::max( w1, w2 ) );
295 hint.setHeight( fm.height() );
297 hint = hint.grownBy( spinBox->
paddingHint( Q::TextPanel ) );
298 hint = hint.expandedTo( spinBox->
strutSizeHint( Q::TextPanel ) );
301 if (
const auto decoration = spinBox->decoration() )
303 const auto spacing = spinBox->
spacingHint( Q::Panel );
305 const auto hintDown = spinBox->
strutSizeHint( Q::DownPanel );
307 if ( decoration == QskSpinBox::UpDownControl )
309 qreal w = std::max( hintDown.width(), hintUp.width() );
312 if ( hintDown.height() >= 0.0 )
313 h += hintDown.height();
315 if ( hintUp.height() >= 0.0 )
316 h += hintUp.height();
318 hint.rwidth() += ( w >= 0.0 ) ? w : hint.height();
319 hint.rwidth() += spacing;
321 hint.rheight() = std::max( h, hint.height() );
325 if ( hintDown.width() > 0.0 )
326 hint.rwidth() += hintDown.width() + spacing;
328 if ( hintUp.width() > 0.0 )
329 hint.rwidth() += hintUp.width() + spacing;
331 const auto h = std::max( hintUp.height(), hintDown.height() );
332 hint.rheight() = qMax( h, hint.height() );
336 hint = hint.grownBy( spinBox->
paddingHint( Q::Panel ) );
337 hint = hint.expandedTo( spinBox->
strutSizeHint( Q::Panel ) );
342#include "moc_QskSpinBoxSkinlet.cpp"
Subcontrol
For use within the rendering or lay-outing of a specific QskSkinnable.
QRectF subControlRect(QskAspect::Subcontrol) const
static const QskAspect::State Disabled
static const QskAspect::State Hovered
qreal spacingHint(QskAspect, QskSkinHintStatus *=nullptr) const
Retrieves a spacing hint.
QMarginsF paddingHint(QskAspect, QskSkinHintStatus *=nullptr) const
Retrieves a padding hint.
QFont effectiveFont(QskAspect) const
QSizeF strutSizeHint(QskAspect, QskSkinHintStatus *=nullptr) const
Retrieves a strut size hint.
QRectF subControlContentsRect(const QRectF &, QskAspect::Subcontrol) const
Calculate the inner rectangle for subControl.
QRectF innerBox(QskAspect, const QRectF &outerBox) const
Calculate the rectangle, whith paddings, indentations being subtracted.
A control to edit, increment and decrement number values.