6#include "QskSliderSkinlet.h"
8#include "QskFunctions.h"
9#include "QskIntervalF.h"
20static inline qreal qskSubcontrolExtent(
26static inline bool qskHasFilling(
const QskSlider* slider )
28 const auto policy = slider->
flagHint< Qsk::Policy >(
29 Q::Fill | QskAspect::Option, Qsk::Always );
37 return qskFuzzyCompare( slider->origin(), slider->minimum() );
44static QRectF qskInnerRect(
const QskSlider* slider,
49 const qreal extent = qskSubcontrolExtent( slider, subControl );
53 if ( slider->orientation() == Qt::Horizontal )
55 if ( extent < r.height() )
57 r.setTop( r.center().y() - 0.5 * extent );
58 r.setHeight( extent );
63 if ( extent < r.width() )
65 r.setLeft( r.center().x() - 0.5 * extent );
74static inline QPair< qreal, qreal > qskTickSpan( qreal min, qreal max, qreal length )
79 min += 0.5 * ( max - min - length );
87QskSliderSkinlet::QskSliderSkinlet(
QskSkin* skin )
90 setNodeRoles( { PanelRole, GrooveRole, FillRole, TicksRole, HandleRole } );
93QskSliderSkinlet::~QskSliderSkinlet()
97QRectF QskSliderSkinlet::subControlRect(
const QskSkinnable* skinnable,
100 const auto slider =
static_cast< const QskSlider*
>( skinnable );
102 if ( subControl == Q::Panel )
103 return panelRect( slider, contentsRect );
105 if ( subControl == Q::Groove )
106 return qskInnerRect( slider, contentsRect, Q::Groove );
108 if ( subControl == Q::Fill )
109 return fillRect( slider, contentsRect );
111 if ( subControl == Q::Scale )
112 return subControlRect( skinnable, contentsRect, Q::Groove );
114 if ( subControl == Q::Handle )
115 return handleRect( slider, contentsRect );
117 return Inherited::subControlRect( skinnable, contentsRect, subControl );
120QSGNode* QskSliderSkinlet::updateSubNode(
121 const QskSkinnable* skinnable, quint8 nodeRole, QSGNode* node )
const
123 const auto slider =
static_cast< const QskSlider*
>( skinnable );
128 return updateBoxNode( slider, node, Q::Panel );
131 return updateBoxNode( slider, node, Q::Groove );
134 return updateBoxNode( slider, node, Q::Fill );
137 return updateBoxNode( slider, node, Q::Handle );
140 return updateSeriesNode( slider, Q::Tick, node );
143 return Inherited::updateSubNode( skinnable, nodeRole, node );
146int QskSliderSkinlet::sampleCount(
const QskSkinnable* skinnable,
149 if ( subControl == Q::Tick )
151 const auto slider =
static_cast< const QskSlider*
>( skinnable );
152 return graduation( slider ).count();
155 return Inherited::sampleCount( skinnable, subControl );
158QVariant QskSliderSkinlet::sampleAt(
const QskSkinnable* skinnable,
161 if ( subControl == Q::Tick )
163 const auto slider =
static_cast< const QskSlider*
>( skinnable );
164 return graduation( slider ).value( index );
167 return Inherited::sampleAt( skinnable, subControl, index );
170QskAspect::States QskSliderSkinlet::sampleStates(
173 auto states = Inherited::sampleStates( skinnable, subControl, index );
175 const auto slider =
static_cast< const QskSlider*
>( skinnable );
177 if ( subControl == Q::Tick && qskHasFilling( slider ) )
179 const auto tickValue = sampleAt( skinnable, subControl, index );
180 if ( tickValue.canConvert< qreal >() )
182 const auto intv = QskIntervalF::normalized(
183 slider->origin(), slider->value() );
185 if ( intv.contains( tickValue.value< qreal >() ) )
193QRectF QskSliderSkinlet::sampleRect(
194 const QskSkinnable* skinnable,
const QRectF& contentsRect,
197 if ( subControl == Q::Tick )
199 const auto slider =
static_cast< const QskSlider*
>( skinnable );
200 return tickRect( slider, contentsRect, index );
203 return Inherited::sampleRect( skinnable, contentsRect, subControl, index );
206QSGNode* QskSliderSkinlet::updateSampleNode(
const QskSkinnable* skinnable,
209 if ( subControl == Q::Tick )
211 const auto slider =
static_cast< const QskSlider*
>( skinnable );
212 const auto rect = sampleRect( slider, slider->
contentsRect(), subControl, index );
214 return updateBoxNode( skinnable, node, rect, subControl );
217 return Inherited::updateSampleNode( skinnable, subControl, index, node );
220QRectF QskSliderSkinlet::panelRect(
221 const QskSlider* slider,
const QRectF& contentsRect )
const
223 auto r = contentsRect;
225 const qreal extent = qskSubcontrolExtent( slider, Q::Panel );
226 if ( extent >= 0 && extent < r.height() )
230 if ( slider->orientation() == Qt::Horizontal )
232 r = qskAlignedRectF( r, r.width(),
233 extent, alignment & Qt::AlignVertical_Mask );
237 r = qskAlignedRectF( r, extent, r.height(),
238 alignment & Qt::AlignHorizontal_Mask );
245QRectF QskSliderSkinlet::fillRect(
246 const QskSlider* slider,
const QRectF& contentsRect )
const
248 if ( !qskHasFilling( slider ) )
251 auto pos1 = slider->valueAsRatio( slider->origin() );
252 auto pos2 = qBound( 0.0, slider->positionHint( Q::Handle ), 1.0 );
254 if ( slider->isInverted() )
263 auto r = qskInnerRect( slider, contentsRect, Q::Fill );
265 auto scaleRect = subControlRect( slider, contentsRect, Q::Scale );
267 if ( slider->orientation() == Qt::Horizontal )
269 if ( !qFuzzyIsNull( pos1 ) )
270 r.setLeft( scaleRect.left() + pos1 * scaleRect.width() );
272 r.setRight( scaleRect.left() + pos2 * scaleRect.width() );
276 if ( !qFuzzyIsNull( pos1 ) )
277 r.setBottom( scaleRect.bottom() - pos1 * scaleRect.height() );
279 r.setTop( scaleRect.bottom() - pos2 * scaleRect.height() );
285QRectF QskSliderSkinlet::handleRect(
286 const QskSlider* slider,
const QRectF& contentsRect )
const
289 const auto pos = qBound( 0.0, slider->positionHint( Q::Handle ), 1.0 );
291 const auto r = subControlRect( slider, contentsRect, Q::Scale );
292 auto center = r.center();
294 if ( slider->orientation() == Qt::Horizontal )
296 if ( handleSize.height() < 0.0 )
297 handleSize.setHeight( r.height() );
299 if ( handleSize.width() < 0.0 )
300 handleSize.setWidth( handleSize.height() );
302 if ( slider->isInverted() )
303 center.setX( r.right() - pos * r.width() );
305 center.setX( r.left() + pos * r.width() );
309 if ( handleSize.width() < 0.0 )
310 handleSize.setWidth( r.width() );
312 if ( handleSize.height() < 0.0 )
313 handleSize.setHeight( handleSize.width() );
315 if ( slider->isInverted() )
316 center.setY( r.top() + pos * r.height() );
318 center.setY( r.bottom() - pos * r.height() );
321 QRectF handleRect( 0, 0, handleSize.width(), handleSize.height() );
322 handleRect.moveCenter( center );
327QRectF QskSliderSkinlet::tickRect(
const QskSlider* slider,
328 const QRectF& contentsRect,
int index )
const
330 const auto tickValue = sampleAt( slider, Q::Tick, index );
331 if ( !tickValue.canConvert< qreal >() )
334 auto tickPos = slider->valueAsRatio( tickValue.value< qreal >() );
335 if ( slider->isInverted() )
336 tickPos = 1.0 - tickPos;
338 const auto r = subControlRect( slider, contentsRect, Q::Scale );
340 const auto padding = slider->
paddingHint( Q::Scale );
343 if( slider->orientation() == Qt::Horizontal )
345 const auto x = tickPos * r.width() - 0.5 * size.width();
347 const auto span = qskTickSpan(
348 padding.top(), r.height() - padding.bottom(), size.height() );
350 return QRectF( r.x() + x, r.y() + span.first,
351 size.width(), span.second - span.first );
355 const auto y = tickPos * r.height() + 0.5 * size.height();
357 const auto span = qskTickSpan(
358 padding.left(), r.width() - padding.right(), size.width() );
360 return QRectF( r.x() + span.first, r.bottom() - y,
361 span.second - span.first, size.height() );
365QSizeF QskSliderSkinlet::sizeHint(
const QskSkinnable* skinnable,
366 Qt::SizeHint which,
const QSizeF& )
const
368 if ( which != Qt::PreferredSize )
371 auto extent = qskSubcontrolExtent( skinnable, Q::Panel );
372 extent = qMax( extent, qskSubcontrolExtent( skinnable, Q::Groove ) );
373 extent = qMax( extent, qskSubcontrolExtent( skinnable, Q::Fill ) );
375 const auto slider =
static_cast< const QskSlider*
>( skinnable );
379 if ( slider->orientation() == Qt::Horizontal )
380 hint.setHeight( qMax( hint.height(), extent ) );
382 hint.setWidth( qMax( hint.width(), extent ) );
387bool QskSliderSkinlet::hasGraduation(
const QskSlider* slider )
const
389 if ( slider->stepSize() )
391 const auto policy = slider->
flagHint< Qsk::Policy >(
392 Q::Tick | QskAspect::Option, Qsk::Never );
400 return slider->isSnapping();
410QVector< qreal > QskSliderSkinlet::graduation(
const QskSlider* slider )
const
412 QVector< qreal > graduation;
414 if ( hasGraduation( slider ) )
416 const auto from = slider->minimum();
417 const auto to = slider->maximum();
419 auto step = slider->stepSize();
423 const auto n = qCeil( ( to - from ) / step ) - 1;
425 graduation.reserve( n );
427 for (
int i = 1; i <= n; i++ )
428 graduation += from + i * step;
434#include "moc_QskSliderSkinlet.cpp"
Lookup key for a QskSkinHintTable.
Subcontrol
For use within the rendering or lay-outing of a specific QskSkinnable.
QRectF subControlContentsRect(QskAspect::Subcontrol) const
QRectF contentsRect() const
QMarginsF paddingHint(QskAspect, QskSkinHintStatus *=nullptr) const
Retrieves a padding hint.
QSizeF strutSizeHint(QskAspect, QskSkinHintStatus *=nullptr) const
Retrieves a strut size hint.
T flagHint(QskAspect, T=T()) const
Retrieves a flag hint.
Qt::Alignment alignmentHint(QskAspect, Qt::Alignment=Qt::Alignment()) const
Retrieves an alignment hint.