Fluid 1.3.0
Material Design for QtQuick and Qml
Loading...
Searching...
No Matches
IconLabel.qml
Go to the documentation of this file.
1// SPDX-FileCopyrightText: 2026 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
2// SPDX-License-Identifier: MPL-2.0
3
4import QtQuick
5import Fluid as MD
6
18Item {
19 id: root
20 Accessible.ignored: true
21
25 enum Display {
26 IconOnly,
27 TextOnly,
28 TextBesideIcon,
29 TextUnderIcon
30 }
31
32 component IconData: QtObject {
33 property string name
34 property url source
35 property real width: -1
36 property real height: -1
37 property color color
38 }
39
41 property IconData icon: IconData {}
42
44 property alias text: label.text
45
47 property alias typescale: label.typescale
48
50 property alias lineHeight: label.lineHeight
51
53 property alias color: label.color
54
56 property real textOpacity: 1.0
57
59 property bool mirrored: false
60
62 property bool mirrorIconInRtl: false
63
67 readonly property bool hasIcon: icon.name.length > 0 || icon.source.toString().length > 0
68
72 readonly property bool showIcon: hasIcon && display !== IconLabel.TextOnly
73
77 readonly property bool showText: text.length > 0 && display !== IconLabel.IconOnly
78
82 property int display: IconLabel.TextBesideIcon
83
87 readonly property int effectiveDisplay: {
88 switch (display) {
89 case IconLabel.TextBesideIcon:
90 case IconLabel.TextUnderIcon:
91 if (showIcon && showText)
92 return display;
93 return showIcon ? IconLabel.IconOnly : IconLabel.TextOnly;
94 default:
95 return display;
96 }
97 }
98
102 property real spacing: MD.Tokens.measurement.space100
103
107 readonly property real effectiveSpacing: showIcon && showText ? spacing : 0
108
109 implicitWidth: {
110 switch (effectiveDisplay) {
111 case IconLabel.IconOnly:
112 return iconItem.implicitWidth;
113 case IconLabel.TextOnly:
114 return label.implicitWidth;
115 case IconLabel.TextBesideIcon:
116 return iconItem.implicitWidth + label.implicitWidth + effectiveSpacing;
117 case IconLabel.TextUnderIcon:
118 return Math.max(iconItem.implicitWidth, label.implicitWidth);
119 }
120 }
121 implicitHeight: {
122 switch (effectiveDisplay) {
123 case IconLabel.IconOnly:
124 return iconItem.implicitHeight;
125 case IconLabel.TextOnly:
126 return label.implicitHeight;
127 case IconLabel.TextBesideIcon:
128 return Math.max(iconItem.implicitHeight, label.implicitHeight);
129 case IconLabel.TextUnderIcon:
130 return iconItem.implicitHeight + label.implicitHeight + effectiveSpacing;
131 }
132 }
133
134 Item {
135 id: iconItem
136 objectName: "iconLabelIcon"
137
138 implicitWidth: root.icon.width
139 implicitHeight: root.icon.height
140 visible: root.showIcon
141
142 transform: Scale {
143 objectName: "iconLabelMirrorTransform"
144 origin.x: iconItem.width / 2
145 origin.y: iconItem.height / 2
146 xScale: root.mirrorIconInRtl && root.mirrored ? -1 : 1
147 }
148
149 Image {
150 objectName: "iconLabelSourceImage"
151 anchors.fill: parent
152 source: root.icon.source
153 sourceSize: Qt.size(root.icon.width, root.icon.height)
154 fillMode: Image.PreserveAspectFit
155 visible: root.icon.source.toString().length > 0
156 }
157
158 MD.Symbol {
159 objectName: "iconLabelSymbol"
160 anchors.fill: parent
161 name: root.icon.name
162 iconWidth: root.icon.width
163 iconHeight: root.icon.height
164 color: root.icon.color.a > 0 ? root.icon.color : label.color
165 visible: root.icon.source.toString().length === 0 && name.length > 0
166 }
167 }
168
169 MD.Label {
170 id: label
171 objectName: "iconLabelText"
172
173 font.pixelSize: typescale.fontSize
174 font.weight: typescale.fontWeight
175 //font.letterSpacing: typescale.tracking
176
177 wrapMode: MD.Label.NoWrap
178 elide: MD.Label.ElideRight
179 opacity: root.textOpacity
180 visible: root.showText && opacity > 0
181 }
182
183 states: [
184 State {
185 name: "iconOnly"
186 when: root.effectiveDisplay === IconLabel.IconOnly
187
188 AnchorChanges {
189 target: iconItem
190 anchors.left: undefined
191 anchors.right: undefined
192 anchors.top: undefined
193 anchors.bottom: undefined
194 anchors.horizontalCenter: root.horizontalCenter
195 anchors.verticalCenter: root.verticalCenter
196 }
197
198 AnchorChanges {
199 target: label
200 anchors.left: undefined
201 anchors.right: undefined
202 anchors.top: undefined
203 anchors.bottom: undefined
204 anchors.horizontalCenter: undefined
205 anchors.verticalCenter: undefined
206 }
207 },
208 State {
209 name: "textOnly"
210 when: root.effectiveDisplay === IconLabel.TextOnly
211
212 AnchorChanges {
213 target: label
214 anchors.left: undefined
215 anchors.right: undefined
216 anchors.top: undefined
217 anchors.bottom: undefined
218 anchors.horizontalCenter: root.horizontalCenter
219 anchors.verticalCenter: root.verticalCenter
220 }
221
222 AnchorChanges {
223 target: iconItem
224 anchors.left: undefined
225 anchors.right: undefined
226 anchors.top: undefined
227 anchors.bottom: undefined
228 anchors.horizontalCenter: undefined
229 anchors.verticalCenter: undefined
230 }
231 },
232 State {
233 name: "textBesideIcon"
234 when: root.effectiveDisplay === IconLabel.TextBesideIcon && !root.mirrored
235
236 AnchorChanges {
237 target: iconItem
238 anchors.left: root.left
239 anchors.right: undefined
240 anchors.top: undefined
241 anchors.bottom: undefined
242 anchors.horizontalCenter: undefined
243 anchors.verticalCenter: root.verticalCenter
244 }
245
246 AnchorChanges {
247 target: label
248 anchors.left: iconItem.right
249 anchors.right: undefined
250 anchors.top: undefined
251 anchors.bottom: undefined
252 anchors.horizontalCenter: undefined
253 anchors.verticalCenter: root.verticalCenter
254 }
255
256 PropertyChanges {
257 target: label
258 anchors.leftMargin: root.effectiveSpacing
259 anchors.rightMargin: 0
260 anchors.topMargin: 0
261 anchors.bottomMargin: 0
262 }
263 },
264 State {
265 name: "textBesideIconMirrored"
266 when: root.effectiveDisplay === IconLabel.TextBesideIcon && root.mirrored
267
268 AnchorChanges {
269 target: iconItem
270 anchors.left: undefined
271 anchors.right: root.right
272 anchors.top: undefined
273 anchors.bottom: undefined
274 anchors.horizontalCenter: undefined
275 anchors.verticalCenter: root.verticalCenter
276 }
277
278 AnchorChanges {
279 target: label
280 anchors.left: undefined
281 anchors.right: iconItem.left
282 anchors.top: undefined
283 anchors.bottom: undefined
284 anchors.horizontalCenter: undefined
285 anchors.verticalCenter: root.verticalCenter
286 }
287
288 PropertyChanges {
289 target: label
290 anchors.leftMargin: 0
291 anchors.rightMargin: root.effectiveSpacing
292 anchors.topMargin: 0
293 anchors.bottomMargin: 0
294 }
295 },
296 State {
297 name: "textUnderIcon"
298 when: root.effectiveDisplay === IconLabel.TextUnderIcon
299
300 AnchorChanges {
301 target: iconItem
302 anchors.left: undefined
303 anchors.right: undefined
304 anchors.top: root.top
305 anchors.bottom: undefined
306 anchors.horizontalCenter: root.horizontalCenter
307 anchors.verticalCenter: undefined
308 }
309
310 AnchorChanges {
311 target: label
312 anchors.left: undefined
313 anchors.right: undefined
314 anchors.top: iconItem.bottom
315 anchors.bottom: undefined
316 anchors.horizontalCenter: root.horizontalCenter
317 anchors.verticalCenter: undefined
318 }
319
320 PropertyChanges {
321 target: label
322 anchors.leftMargin: 0
323 anchors.rightMargin: 0
324 anchors.topMargin: root.effectiveSpacing
325 anchors.bottomMargin: 0
326 }
327 }
328 ]
329}
Lays out an icon and text as a single reusable visual.
Definition IconLabel.qml:16