6#include "QskSegmentedBarSkinlet.h"
7#include "QskSegmentedBar.h"
9#include "QskLabelData.h"
10#include "QskGraphic.h"
11#include "QskColorFilter.h"
12#include "QskFunctions.h"
15#include "QskSkinStateChanger.h"
16#include "QskSubcontrolLayoutEngine.h"
17#include "QskBoxHints.h"
19#include <qfontmetrics.h>
29 auto boxHints = bar->boxHints( subControl );
31 const bool leading = ( index == 0 );
32 const bool trailing = ( index == bar->count() - 1 );
34 if ( !( leading || trailing ) )
38 if ( !bar->
flagHint<
bool >( Q::Panel | QskAspect::Option,
false ) )
42 auto& shape = boxHints.shape;
48 Qt::Corner corners[2];
50 corners[0] = Qt::TopLeftCorner;
52 if ( bar->orientation() == Qt::Vertical )
53 corners[1] = Qt::TopRightCorner;
55 corners[1] = Qt::BottomLeftCorner;
57 shape.setSizeMode( panelShape.sizeMode() );
58 shape.setRadius( corners[0], panelShape.radius( corners[0] ) );
59 shape.setRadius( corners[1], panelShape.radius( corners[1] ) );
64 Qt::Corner corners[2];
66 corners[0] = Qt::BottomRightCorner;
68 if ( bar->orientation() == Qt::Vertical )
69 corners[1] = Qt::BottomLeftCorner;
71 corners[1] = Qt::TopRightCorner;
73 shape.setSizeMode( panelShape.sizeMode() );
74 shape.setRadius( corners[0], panelShape.radius( corners[0] ) );
75 shape.setRadius( corners[1], panelShape.radius( corners[1] ) );
79 boxHints.borderColors = QColor();
89 if ( bar->selectedIndex() == index )
97 const auto icon = bar->symbolHint( Q::Icon | Q::Selected );
102 return bar->optionAt( index ).icon().graphic();
115 const auto option = bar->optionAt( index );
117 setGraphicTextElements( bar, Q::Text, option.text(),
118 Q::Icon, iconAt( bar, index ).defaultSize() );
120 if( bar->orientation() == Qt::Horizontal )
122 const auto alignment = bar->
alignmentHint( Q::Panel, Qt::AlignCenter );
123 setFixedContent( Q::Text, Qt::Horizontal, alignment );
129QskSegmentedBarSkinlet::QskSegmentedBarSkinlet(
QskSkin* skin )
132 setNodeRoles( { PanelRole, SegmentRole, SeparatorRole,
133 CursorRole, SplashRole, TextRole, IconRole } );
136QskSegmentedBarSkinlet::~QskSegmentedBarSkinlet() =
default;
138QRectF QskSegmentedBarSkinlet::subControlRect(
139 const QskSkinnable* skinnable,
const QRectF& contentsRect,
146 if( subControl == Q::Panel )
149 if( subControl == Q::Cursor )
150 return cursorRect( bar, contentsRect );
152 if( subControl == Q::Splash )
153 return splashRect( bar, contentsRect );
155 return Inherited::subControlRect( skinnable, contentsRect, subControl );
158QRectF QskSegmentedBarSkinlet::cursorRect(
163 if( bar->selectedIndex() < 0 || bar->count() <= 0 )
166 auto rect = subControlRect( bar, contentsRect, Q::Panel );
174 const qreal position = bar->positionHint( Q::Cursor );
176 const int index1 = qFloor( position );
177 const int index2 = qCeil( position );
179 auto cursorRect = segmentRect( bar, contentsRect, index1 );
180 if ( index1 != index2 )
182 const auto targetRect = segmentRect( bar, contentsRect, index2 );
183 cursorRect = qskInterpolatedRect( cursorRect, targetRect, position - index1 );
189QRectF QskSegmentedBarSkinlet::splashRect(
203 const int index = bar->indexAtPosition( pos );
205 if( index >= 0 && index < bar->count() )
207 const auto sr = segmentRect( bar, contentsRect, index );
211 if( bar->orientation() == Qt::Horizontal )
213 w = 2.0 * rect.width() * ratio;
214 h = 2.0 * rect.height();
218 w = 2.0 * rect.width();
219 h = 2.0 * rect.height() * ratio;
222 rect.setSize( { w, h } );
223 rect.moveCenter( pos );
224 rect = rect.intersected( sr );
231QRectF QskSegmentedBarSkinlet::segmentRect(
232 const QskSegmentedBar* bar,
const QRectF& contentsRect,
int index )
const
236 const auto count = bar->count();
238 auto rect = subControlRect( bar, contentsRect, Q::Panel );
240 if( bar->orientation() == Qt::Horizontal )
242 const qreal w = rect.width() / count;
244 rect.setLeft( index * w );
249 const qreal h = rect.height() / count;
251 rect.setTop( index * h );
258QRectF QskSegmentedBarSkinlet::separatorRect(
259 const QskSegmentedBar* bar,
const QRectF& contentsRect,
int index )
const
263 if( index == bar->count() - 1 )
266 auto rect = segmentRect( bar, contentsRect, index );
272 if( bar->orientation() == Qt::Horizontal )
274 rect.setLeft( rect.right() );
275 rect.setSize( { strutSize.width(), sh.height() } );
279 rect.setTop( rect.bottom() );
280 rect.setSize( { sh.width(), strutSize.height() } );
283 const auto padding = bar->
paddingHint( Q::Separator );
284 rect = rect.marginsRemoved( padding );
289QSGNode* QskSegmentedBarSkinlet::updateSubNode(
290 const QskSkinnable* skinnable, quint8 nodeRole, QSGNode* node )
const
299 return updateBoxNode( skinnable, node, Q::Cursor );
302 return updateSplashNode( bar, node );
305 return updateBoxNode( skinnable, node, Q::Panel );
308 return updateSeriesNode( skinnable, Q::Segment, node );
311 return updateSeriesNode( skinnable, Q::Separator, node );
314 return updateSeriesNode( skinnable, Q::Text, node );
317 return updateSeriesNode( skinnable, Q::Icon, node );
323QSizeF QskSegmentedBarSkinlet::segmentSizeHint(
328 const QSizeF sizeSymbol =
329 bar->symbolHint( Q::Icon | Q::Selected ).defaultSize();
333 for (
int i = 0; i < bar->count(); i++ )
335 const auto option = bar->optionAt( i );
337 auto iconSize = option.icon().graphic().defaultSize();
338 iconSize = iconSize.expandedTo( sizeSymbol );
340 LayoutEngine layoutEngine( bar, i );
341 layoutEngine.setGraphicTextElements( bar,
342 Q::Text, option.text(), Q::Icon, iconSize );
344 const auto size = layoutEngine.sizeHint( which, QSizeF() );
345 segmentSize = segmentSize.expandedTo( size );
348 segmentSize = bar->
outerBoxSize( Q::Segment, segmentSize );
349 segmentSize = segmentSize.expandedTo( bar->
strutSizeHint( Q::Segment ) );
350 segmentSize = segmentSize.grownBy( bar->
marginHint( Q::Segment ) );
355QSizeF QskSegmentedBarSkinlet::sizeHint(
const QskSkinnable* skinnable,
356 Qt::SizeHint which,
const QSizeF& )
const
360 if ( which != Qt::PreferredSize )
363 const auto count = sampleCount( skinnable, Q::Segment );
365 return QSizeF( 0, 0 );
372 const qreal spacing = skinnable->
spacingHint( Q::Panel );
375 const auto segmentSize = segmentSizeHint( bar, which );
377 if( bar->orientation() == Qt::Horizontal )
379 w = count * segmentSize.width() + ( count - 1 ) * spacing;
380 h = segmentSize.height();
384 w = segmentSize.width();
385 h = count * segmentSize.height() + ( count - 1 ) * spacing;
389 const auto hint = skinnable->
outerBoxSize( Q::Panel, QSizeF( w, h ) );
390 return hint.expandedTo( skinnable->
strutSizeHint( Q::Panel ) );
393int QskSegmentedBarSkinlet::sampleCount(
400QRectF QskSegmentedBarSkinlet::sampleRect(
const QskSkinnable* skinnable,
406 if ( subControl == Q::Segment )
408 return segmentRect( bar, contentsRect, index );
411 if ( subControl == Q::Separator )
413 return separatorRect( bar, contentsRect, index );
416 if ( subControl == Q::Text || subControl == Q::Icon )
418 const auto rect = sampleRect( skinnable, contentsRect, Q::Segment, index );
420 LayoutEngine layoutEngine( bar, index );
421 layoutEngine.setGeometries( rect );
423 return layoutEngine.subControlRect( subControl );
426 return Inherited::sampleRect( skinnable, contentsRect, subControl, index );
429QskAspect::States QskSegmentedBarSkinlet::sampleStates(
435 auto states = Inherited::sampleStates( skinnable, subControl, index );
439 if ( subControl == Q::Segment )
441 if ( bar->isSegmentEnabled( index ) )
443 if ( bar->selectedIndex() == index )
444 states |= Q::Selected;
452 Q::Segment |
Q::Hovered | A::Metric | A::Position ).toPointF();
454 if( !cursorPos.isNull() && bar->indexAtPosition( cursorPos ) == index )
460 states &=
~Q::Hovered;
463 const auto focusIndex = bar->positionHint( Q::Segment |
Q::Focused );
465 if( focusIndex >= 0 && focusIndex < bar->count() )
467 if( focusIndex == index )
473 states &=
~Q::Focused;
477 else if( subControl == Q::Icon || subControl == Q::Text )
479 if ( bar->isSegmentEnabled( index ) )
481 if ( bar->selectedIndex() == index )
482 states |= Q::Selected;
493QSGNode* QskSegmentedBarSkinlet::updateSampleNode(
const QskSkinnable* skinnable,
500 const auto rect = sampleRect( bar, bar->
contentsRect(), subControl, index );
502 if ( subControl == Q::Separator )
504 return updateBoxNode( skinnable, node, rect, subControl );
507 if ( subControl == Q::Segment )
509 const auto boxHints = effectiveBoxHints( subControl, bar, index );
510 return updateBoxNode( bar, node, rect, boxHints );
513 const auto alignment = bar->
alignmentHint( subControl, Qt::AlignCenter );
515 if ( subControl == Q::Text )
517 const auto text = bar->optionAt( index ).text();
519 if( !text.isEmpty() )
521 return QskSkinlet::updateTextNode( bar, node,
522 rect, alignment, text, Q::Text );
528 if ( subControl == Q::Icon )
530 const auto graphic = iconAt( bar, index );
532 if( !graphic.isEmpty() )
536 const auto graphicRect = rect.marginsRemoved( padding );
538 return QskSkinlet::updateGraphicNode(
539 bar, node, graphic, filter, graphicRect, alignment );
545 return Inherited::updateSampleNode( skinnable, subControl, index, node );
548QSGNode* QskSegmentedBarSkinlet::updateSplashNode(
554 if ( splashRect.isEmpty() )
557 auto clipNode = updateBoxClipNode(
562 auto boxNode = updateBoxNode( bar, clipNode->firstChild(), splashRect, Q::Splash );
563 if ( boxNode->parent() ==
nullptr )
564 clipNode->appendChildNode( boxNode );
570#include "moc_QskSegmentedBarSkinlet.cpp"
Lookup key for a QskSkinHintTable.
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
QRectF contentsRect() const
static const QskAspect::State Focused
A paint device for scalable graphics.
QVariant effectiveSkinHint(QskAspect, QskSkinHintStatus *=nullptr) const
Find the value for a specific aspect.
qreal spacingHint(QskAspect, QskSkinHintStatus *=nullptr) const
Retrieves a spacing hint.
QMarginsF paddingHint(QskAspect, QskSkinHintStatus *=nullptr) const
Retrieves a padding hint.
QMarginsF marginHint(QskAspect, QskSkinHintStatus *=nullptr) const
Retrieves a margin hint.
QSizeF strutSizeHint(QskAspect, QskSkinHintStatus *=nullptr) const
Retrieves a strut size hint.
QSizeF outerBoxSize(QskAspect, const QSizeF &innerBoxSize) const
Calculate the size, when being expanded by paddings, indentations.
QskBoxShapeMetrics boxShapeHint(QskAspect, QskSkinHintStatus *=nullptr) const
Retrieves a shape hint.
QskColorFilter effectiveGraphicFilter(QskAspect::Subcontrol) const
QskBoxBorderMetrics boxBorderMetricsHint(QskAspect, QskSkinHintStatus *=nullptr) const
Retrieves a border hint.
T flagHint(QskAspect, T=T()) const
Retrieves a flag hint.
qreal metric(QskAspect, QskSkinHintStatus *=nullptr) const
Retrieves a metric hint.
Qt::Alignment alignmentHint(QskAspect, Qt::Alignment=Qt::Alignment()) const
Retrieves an alignment hint.