QSkinny 0.8.0
C++/Qt UI toolkit
Loading...
Searching...
No Matches
QskComboBoxSkinlet.cpp
1/******************************************************************************
2 * QSkinny - Copyright (C) The authors
3 * SPDX-License-Identifier: BSD-3-Clause
4 *****************************************************************************/
5
6#include "QskComboBoxSkinlet.h"
7#include "QskComboBox.h"
8
9#include "QskGraphic.h"
10#include "QskLabelData.h"
11
12#include "QskSGNode.h"
13#include "QskSubcontrolLayoutEngine.h"
14
15namespace
16{
17 class LayoutEngine : public QskSubcontrolLayoutEngine
18 {
19 public:
20 LayoutEngine( const QskComboBox* box )
21 : QskSubcontrolLayoutEngine( Qt::Horizontal )
22 {
23 setSpacing( box->spacingHint( QskComboBox::Panel ) );
24
25 QSizeF graphicSize;
26 QString text;
27
28 if ( box->currentIndex() >= 0 )
29 {
30 const auto option = box->optionAt( box->currentIndex() );
31
32 graphicSize = option.icon().graphic().defaultSize();
33 text = option.text();
34 }
35 else
36 {
37 text = box->placeholderText();
38 }
39
40 setGraphicTextElements( box,
41 QskComboBox::Text, text, QskComboBox::Icon, graphicSize );
42
43 const auto alignment = box->alignmentHint(
44 QskComboBox::Panel, Qt::AlignLeft );
45
46 setFixedContent( QskComboBox::Text, Qt::Horizontal, alignment );
47 }
48 };
49}
50
51QskComboBoxSkinlet::QskComboBoxSkinlet( QskSkin* skin )
52 : Inherited( skin )
53{
54 setNodeRoles( { PanelRole, IconRole, TextRole, StatusIndicatorRole } );
55}
56
57QskComboBoxSkinlet::~QskComboBoxSkinlet() = default;
58
59QRectF QskComboBoxSkinlet::subControlRect( const QskSkinnable* skinnable,
60 const QRectF& contentsRect, QskAspect::Subcontrol subControl ) const
61{
62 using Q = QskComboBox;
63
64 const auto* box = static_cast< const QskComboBox* >( skinnable );
65
66 if ( subControl == Q::Panel )
67 return contentsRect;
68
69 if ( subControl == Q::Text || subControl == Q::Icon )
70 {
71 const auto r = box->subControlContentsRect( contentsRect, Q::Panel );
72
73 LayoutEngine layoutEngine( box );
74 layoutEngine.setGeometries( r );
75
76 return layoutEngine.subControlRect( subControl );
77 }
78
79 if( subControl == Q::StatusIndicator )
80 {
81 auto rect = box->innerBox( Q::Panel, contentsRect );
82 const auto size = box->strutSizeHint( Q::StatusIndicator );
83 rect.setLeft( rect.right() - size.width() );
84 return rect;
85 }
86
87 return Inherited::subControlRect( skinnable, contentsRect, subControl );
88}
89
90QSGNode* QskComboBoxSkinlet::updateSubNode(
91 const QskSkinnable* skinnable, quint8 nodeRole, QSGNode* node ) const
92{
93 using Q = QskComboBox;
94
95 const auto box = static_cast< const QskComboBox* >( skinnable );
96
97 switch ( nodeRole )
98 {
99 case PanelRole:
100 return updateBoxNode( box, node, Q::Panel );
101
102 case IconRole:
103 {
104 const auto option = box->optionAt( box->currentIndex() );
105 return updateGraphicNode( box, node,
106 option.icon().graphic(), Q::Icon );
107 }
108
109 case TextRole:
110 return updateTextNode( box, node );
111
112 case StatusIndicatorRole:
113 return updateSymbolNode( box, node, Q::StatusIndicator );
114 }
115
116 return Inherited::updateSubNode( skinnable, nodeRole, node );
117}
118
119QSGNode* QskComboBoxSkinlet::updateTextNode(
120 const QskComboBox* box, QSGNode* node ) const
121{
122 using Q = QskComboBox;
123
124 const auto rect = box->subControlRect( Q::Text ).toAlignedRect();
125
126 const auto textHeight = box->effectiveFontHeight( Q::Text );
127 if ( !box->clip() && ( rect.height() < textHeight ) )
128 return nullptr;
129
130 const auto alignment = box->alignmentHint( Q::Text, Qt::AlignLeft | Qt::AlignVCenter );
131
132 return QskSkinlet::updateTextNode( box, node, rect,
133 alignment, box->currentText(), Q::Text );
134}
135
136QSizeF QskComboBoxSkinlet::sizeHint( const QskSkinnable* skinnable,
137 Qt::SizeHint which, const QSizeF& ) const
138{
139 using Q = QskComboBox;
140
141 if ( which != Qt::PreferredSize )
142 return QSizeF();
143
144 const auto box = static_cast< const QskComboBox* >( skinnable );
145
146 LayoutEngine layoutEngine( box );
147 auto size = layoutEngine.sizeHint( which, QSizeF() );
148
149 const auto spacingHint = box->spacingHint( Q::Panel );
150 const auto menuGraphicHint = box->strutSizeHint( Q::StatusIndicator );
151
152 size.rwidth() += spacingHint + menuGraphicHint.width();
153
154 size = box->outerBoxSize( Q::Panel, size );
155 size = size.expandedTo( box->strutSizeHint( Q::Panel ) );
156 size = size.grownBy( skinnable->marginHint( Q::Panel ) );
157
158 return size;
159}
160
161#include "moc_QskComboBoxSkinlet.cpp"
Subcontrol
For use within the rendering or lay-outing of a specific QskSkinnable.
Definition QskAspect.h:104
QRectF subControlRect(QskAspect::Subcontrol) const
QRectF subControlContentsRect(QskAspect::Subcontrol) const
qreal spacingHint(QskAspect, QskSkinHintStatus *=nullptr) const
Retrieves a spacing 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.
QRectF innerBox(QskAspect, const QRectF &outerBox) const
Calculate the rectangle, whith paddings, indentations being subtracted.
Qt::Alignment alignmentHint(QskAspect, Qt::Alignment=Qt::Alignment()) const
Retrieves an alignment hint.