4pragma ComponentBehavior: Bound
7import QtQuick.Templates as T
9import "../internal" as Internal
10import "../core/BadgeContent.js" as BadgeContent
11import "../core/UiMetrics.js" as UiMetrics
12import "../internal/MotionAnimation.js" as MotionAnimation
31 property var badgeContent: _badgeAction ? _badgeAction.badgeContent :
""
34 property bool badgeNotification: _badgeAction ? _badgeAction.badgeNotification :
false
37 property bool badgeVisible: _badgeAction ? _badgeAction.badgeVisible :
true
40 property string badgeAccessibleDescription: _badgeAction ? _badgeAction.badgeAccessibleDescription :
""
43 property int badgeVariant: MD.Badge.Auto
45 readonly
property MD.Action _badgeAction: action as MD.Action
46 readonly
property bool _showBadge: badgeVisible
47 && (badgeNotification || BadgeContent.hasContent(badgeContent))
49 component IconData: QtObject {
53 property bool fill: false
116 property int widthVariant: MD.
IconButton.Width.Default
119 property var __buttonGroup: null
120 property real __groupTopLeftRadius: -1
121 property real __groupTopRightRadius: -1
122 property real __groupBottomLeftRadius: -1
123 property real __groupBottomRightRadius: -1
131 property IconData checkedIcon: IconData {}
134 property bool mirrorIconInRtl: false
140 property bool tintSourceIcon: true
146 property color contentColor: {
148 case MD.IconButton.Type.Filled:
149 return checked ? MD.Style.onPrimaryColor : MD.Style.onSurfaceVariantColor;
150 case MD.IconButton.Type.Tonal:
151 return checked ? MD.Style.onSecondaryColor : MD.Style.onSecondaryContainerColor;
152 case MD.IconButton.Type.Outlined:
153 return checked ? MD.Style.inverseOnSurfaceColor : MD.Style.onSurfaceVariantColor;
154 case MD.IconButton.Type.Standard:
155 return checked ? MD.Style.primaryColor : MD.Style.onSurfaceVariantColor;
163 property color containerColor: {
165 case MD.IconButton.Type.Filled:
166 return checked ? MD.Style.primaryColor : MD.Style.surfaceContainerColor;
167 case MD.IconButton.Type.Tonal:
168 return checked ? MD.Style.secondaryColor : MD.Style.secondaryContainerColor;
169 case MD.IconButton.Type.Outlined:
170 return checked ? MD.Style.inverseSurfaceColor :
"transparent";
171 case MD.IconButton.Type.Standard:
172 return "transparent";
177 property color disabledContentColor: MD.Style.onSurfaceColor
180 property color disabledContainerColor: MD.Style.onSurfaceColor
183 property color outlineColor: MD.Style.outlineVariantColor
186 readonly
property color effectiveContentColor: visualState.contentColor
189 readonly
property real effectiveContentOpacity: visualState.contentOpacity
192 readonly
property color effectiveContainerColor: visualState.containerColor
195 readonly
property bool usingCheckedIcon: checked && (checkedIcon.name.length > 0 || checkedIcon.source.toString().length > 0)
198 readonly property
string effectiveIconName: usingCheckedIcon ? checkedIcon.name : icon.name
201 readonly property url effectiveIconSource: usingCheckedIcon ? checkedIcon.source : icon.source
204 readonly property color effectiveIconColor: {
205 const explicitColor = usingCheckedIcon ? checkedIcon.color : icon.color;
206 return explicitColor.a > 0 ? explicitColor : effectiveContentColor;
210 readonly
property bool effectiveIconFill: checked && (usingCheckedIcon ? checkedIcon.fill :
true)
213 readonly property
bool effectiveIconMirrored: mirrorIconInRtl && mirrored
215 icon.width: visualState.iconSize.width
216 icon.height: visualState.iconSize.height
218 implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset, implicitContentWidth + leftPadding + rightPadding)
219 implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset, implicitContentHeight + topPadding + bottomPadding)
221 leftInset: visualState.inset.width / 2
222 rightInset: visualState.inset.width / 2
223 topInset: visualState.inset.height / 2
224 bottomInset: visualState.inset.height / 2
231 focusPolicy: Qt.StrongFocus
235 __buttonGroup.__childCheckedChanged(control);
237 onActiveFocusChanged: {
238 if (activeFocus && __buttonGroup)
239 __buttonGroup.__childFocused(control);
243 __buttonGroup.__childGeometryChanged();
245 onImplicitWidthChanged: {
247 __buttonGroup.__childGeometryChanged();
251 __buttonGroup.__childrenChanged();
255 __buttonGroup.__childrenChanged();
257 Keys.onPressed:
event => {
258 if (__buttonGroup && __buttonGroup.__handleKey(control, event))
259 event.accepted =
true;
263 enabled: control.__buttonGroup && control.__buttonGroup.__geometryInitialized
264 && control.__buttonGroup.variant === control.__buttonGroup.__standardVariant
266 easing.type: Easing.BezierSpline
267 easing.bezierCurve: MotionAnimation.expressiveFastSpatialCurve
268 duration: MotionAnimation.expressiveFastSpatialDuration
272 enabled: control.__buttonGroup && control.__buttonGroup.__geometryInitialized
273 && control.__buttonGroup.variant === control.__buttonGroup.__standardVariant
275 easing.type: Easing.BezierSpline
276 easing.bezierCurve: MotionAnimation.expressiveFastSpatialCurve
277 duration: MotionAnimation.expressiveFastSpatialDuration
281 Accessible.role: __buttonGroup && __buttonGroup.selectionMode === __buttonGroup.__singleSelectionMode
282 ? Accessible.RadioButton
283 : (__buttonGroup && __buttonGroup.selectionMode === __buttonGroup.__multiSelectionMode
284 ? Accessible.CheckBox : Accessible.Button)
285 Accessible.checkable: checkable
286 Accessible.checked: checked
287 Accessible.name: BadgeContent.accessibleName(text,
288 iconButtonBadge && iconButtonBadge.visible ? iconButtonBadge.accessibleDescription :
"")
293 readonly property real currentContainerHeight: {
294 switch (control.size) {
295 case MD.IconButton.Size.ExtraSmall:
return MD.Tokens.iconButton.containerHeightExtraSmall;
296 case MD.IconButton.Size.Small:
return MD.Tokens.iconButton.containerHeightSmall;
297 case MD.IconButton.Size.Medium:
return MD.Tokens.iconButton.containerHeightMedium;
298 case MD.IconButton.Size.Large:
return MD.Tokens.iconButton.containerHeightLarge;
299 case MD.IconButton.Size.ExtraLarge:
return MD.Tokens.iconButton.containerHeightExtraLarge;
302 readonly
property real currentIconSize: {
303 switch (control.size) {
304 case MD.IconButton.Size.ExtraSmall:
return MD.Tokens.iconButton.iconSizeExtraSmall;
305 case MD.IconButton.Size.Small:
return MD.Tokens.iconButton.iconSizeSmall;
306 case MD.IconButton.Size.Medium:
return MD.Tokens.iconButton.iconSizeMedium;
307 case MD.IconButton.Size.Large:
return MD.Tokens.iconButton.iconSizeLarge;
308 case MD.IconButton.Size.ExtraLarge:
return MD.Tokens.iconButton.iconSizeExtraLarge;
311 readonly
property real currentLeadingSpace: {
312 if (control.widthVariant === MD.IconButton.Width.Narrow) {
313 switch (control.size) {
314 case MD.IconButton.Size.ExtraSmall:
return MD.Tokens.iconButton.narrowLeadingSpaceExtraSmall;
315 case MD.IconButton.Size.Small:
return MD.Tokens.iconButton.narrowLeadingSpaceSmall;
316 case MD.IconButton.Size.Medium:
return MD.Tokens.iconButton.narrowLeadingSpaceMedium;
317 case MD.IconButton.Size.Large:
return MD.Tokens.iconButton.narrowLeadingSpaceLarge;
318 case MD.IconButton.Size.ExtraLarge:
return MD.Tokens.iconButton.narrowLeadingSpaceExtraLarge;
321 if (control.widthVariant === MD.IconButton.Width.Wide) {
322 switch (control.size) {
323 case MD.IconButton.Size.ExtraSmall:
return MD.Tokens.iconButton.wideLeadingSpaceExtraSmall;
324 case MD.IconButton.Size.Small:
return MD.Tokens.iconButton.wideLeadingSpaceSmall;
325 case MD.IconButton.Size.Medium:
return MD.Tokens.iconButton.wideLeadingSpaceMedium;
326 case MD.IconButton.Size.Large:
return MD.Tokens.iconButton.wideLeadingSpaceLarge;
327 case MD.IconButton.Size.ExtraLarge:
return MD.Tokens.iconButton.wideLeadingSpaceExtraLarge;
330 switch (control.size) {
331 case MD.IconButton.Size.ExtraSmall:
return MD.Tokens.iconButton.defaultLeadingSpaceExtraSmall;
332 case MD.IconButton.Size.Small:
return MD.Tokens.iconButton.defaultLeadingSpaceSmall;
333 case MD.IconButton.Size.Medium:
return MD.Tokens.iconButton.defaultLeadingSpaceMedium;
334 case MD.IconButton.Size.Large:
return MD.Tokens.iconButton.defaultLeadingSpaceLarge;
335 case MD.IconButton.Size.ExtraLarge:
return MD.Tokens.iconButton.defaultLeadingSpaceExtraLarge;
338 readonly
property real currentTrailingSpace: {
339 if (control.widthVariant === MD.IconButton.Width.Narrow) {
340 switch (control.size) {
341 case MD.IconButton.Size.ExtraSmall:
return MD.Tokens.iconButton.narrowTrailingSpaceExtraSmall;
342 case MD.IconButton.Size.Small:
return MD.Tokens.iconButton.narrowTrailingSpaceSmall;
343 case MD.IconButton.Size.Medium:
return MD.Tokens.iconButton.narrowTrailingSpaceMedium;
344 case MD.IconButton.Size.Large:
return MD.Tokens.iconButton.narrowTrailingSpaceLarge;
345 case MD.IconButton.Size.ExtraLarge:
return MD.Tokens.iconButton.narrowTrailingSpaceExtraLarge;
348 if (control.widthVariant === MD.IconButton.Width.Wide) {
349 switch (control.size) {
350 case MD.IconButton.Size.ExtraSmall:
return MD.Tokens.iconButton.wideTrailingSpaceExtraSmall;
351 case MD.IconButton.Size.Small:
return MD.Tokens.iconButton.wideTrailingSpaceSmall;
352 case MD.IconButton.Size.Medium:
return MD.Tokens.iconButton.wideTrailingSpaceMedium;
353 case MD.IconButton.Size.Large:
return MD.Tokens.iconButton.wideTrailingSpaceLarge;
354 case MD.IconButton.Size.ExtraLarge:
return MD.Tokens.iconButton.wideTrailingSpaceExtraLarge;
357 switch (control.size) {
358 case MD.IconButton.Size.ExtraSmall:
return MD.Tokens.iconButton.defaultTrailingSpaceExtraSmall;
359 case MD.IconButton.Size.Small:
return MD.Tokens.iconButton.defaultTrailingSpaceSmall;
360 case MD.IconButton.Size.Medium:
return MD.Tokens.iconButton.defaultTrailingSpaceMedium;
361 case MD.IconButton.Size.Large:
return MD.Tokens.iconButton.defaultTrailingSpaceLarge;
362 case MD.IconButton.Size.ExtraLarge:
return MD.Tokens.iconButton.defaultTrailingSpaceExtraLarge;
365 readonly
property real outlineWidth: {
366 switch (control.size) {
367 case MD.IconButton.Size.ExtraSmall:
return MD.Tokens.iconButton.outlinedOutlineWidthExtraSmall;
368 case MD.IconButton.Size.Small:
return MD.Tokens.iconButton.outlinedOutlineWidthSmall;
369 case MD.IconButton.Size.Medium:
return MD.Tokens.iconButton.outlinedOutlineWidthMedium;
370 case MD.IconButton.Size.Large:
return MD.Tokens.iconButton.outlinedOutlineWidthLarge;
371 case MD.IconButton.Size.ExtraLarge:
return MD.Tokens.iconButton.outlinedOutlineWidthExtraLarge;
374 property size buttonSize: Qt.size(currentIconSize + currentLeadingSpace + currentTrailingSpace, currentContainerHeight)
375 property size iconSize: Qt.size(currentIconSize, currentIconSize)
377 property size inset: {
378 const minimum = MD.Tokens.iconButton.minimumInteractiveSize;
379 return Qt.size(Math.max(minimum, visualState.buttonSize.width) - visualState.buttonSize.width,
380 Math.max(minimum, visualState.buttonSize.height) - visualState.buttonSize.height);
383 property MD.shapeValue containerShape: {
384 const tokens = MD.Tokens.iconButton;
385 if (control.pressed) {
386 switch (control.size) {
387 case MD.IconButton.Size.ExtraSmall:
return tokens.pressedContainerShapeExtraSmall;
388 case MD.IconButton.Size.Small:
return tokens.pressedContainerShapeSmall;
389 case MD.IconButton.Size.Medium:
return tokens.pressedContainerShapeMedium;
390 case MD.IconButton.Size.Large:
return tokens.pressedContainerShapeLarge;
391 case MD.IconButton.Size.ExtraLarge:
return tokens.pressedContainerShapeExtraLarge;
394 if (control.checked) {
395 if (control.shape === MD.IconButton.Shape.Square)
396 return tokens.selectedContainerShapeSquare;
397 switch (control.size) {
398 case MD.IconButton.Size.ExtraSmall:
return tokens.selectedContainerShapeRoundExtraSmall;
399 case MD.IconButton.Size.Small:
return tokens.selectedContainerShapeRoundSmall;
400 case MD.IconButton.Size.Medium:
return tokens.selectedContainerShapeRoundMedium;
401 case MD.IconButton.Size.Large:
return tokens.selectedContainerShapeRoundLarge;
402 case MD.IconButton.Size.ExtraLarge:
return tokens.selectedContainerShapeRoundExtraLarge;
405 if (control.shape === MD.IconButton.Shape.Round)
406 return tokens.containerShapeRound;
407 switch (control.size) {
408 case MD.IconButton.Size.ExtraSmall:
return tokens.containerShapeSquareExtraSmall;
409 case MD.IconButton.Size.Small:
return tokens.containerShapeSquareSmall;
410 case MD.IconButton.Size.Medium:
return tokens.containerShapeSquareMedium;
411 case MD.IconButton.Size.Large:
return tokens.containerShapeSquareLarge;
412 case MD.IconButton.Size.ExtraLarge:
return tokens.containerShapeSquareExtraLarge;
416 property color containerColor: control.containerColor
417 property color contentColor: control.contentColor
418 property color stateLayerColor:
"transparent"
420 property real contentOpacity: 1.0
421 property real containerOpacity: 1.0
422 property real stateLayerOpacity: 0.0
428 when: !control.enabled
431 visualState.containerColor: control.type === MD.IconButton.Type.Standard ?
"transparent" : control.disabledContainerColor
432 visualState.contentColor: control.disabledContentColor
433 visualState.containerOpacity: MD.Tokens.iconButton.disabledContainerOpacity
434 visualState.contentOpacity: MD.Tokens.iconButton.disabledIconOpacity
439 when: control.down && control.enabled
442 visualState.stateLayerColor: control.effectiveIconColor
443 visualState.stateLayerOpacity: MD.Tokens.iconButton.pressedStateLayerOpacity
448 when: control.visualFocus && control.enabled
451 visualState.stateLayerColor: control.effectiveIconColor
452 visualState.stateLayerOpacity: MD.Tokens.iconButton.focusStateLayerOpacity
457 when: control.hovered && control.enabled
460 visualState.stateLayerColor: control.effectiveIconColor
461 visualState.stateLayerOpacity: MD.Tokens.iconButton.hoverStateLayerOpacity
469 implicitWidth: control.icon.width
470 implicitHeight: control.icon.height
474 objectName:
"iconButtonIconSlot"
475 anchors.centerIn: parent
476 width: control.icon.width
477 height: control.icon.height
478 visible: control.effectiveIconSource.toString().length > 0
479 || control.effectiveIconName.length > 0
480 Accessible.ignored:
true
483 origin.x: iconSlot.width / 2
484 origin.y: iconSlot.height / 2
485 xScale: control.effectiveIconMirrored ? -1 : 1
490 objectName:
"iconButtonSourceImage"
492 source: control.effectiveIconSource
493 sourceSize: Qt.size(control.icon.width, control.icon.height)
494 fillMode: Image.PreserveAspectFit
495 color: control.tintSourceIcon ? control.effectiveIconColor :
"transparent"
496 opacity: visualState.contentOpacity
497 visible: control.effectiveIconSource.toString().length > 0
498 Accessible.ignored:
true
502 objectName:
"iconButtonSymbol"
504 name: control.effectiveIconName
505 iconWidth: control.icon.width
506 iconHeight: control.icon.height
507 color: control.effectiveIconColor
508 opacity: visualState.contentOpacity
509 fill: control.effectiveIconFill
510 visible: control.effectiveIconSource.toString().length === 0 && name.length > 0
511 Accessible.ignored:
true
517 objectName:
"iconButtonBadge"
519 layoutMirrored: control.mirrored
520 count: BadgeContent.count(control.badgeContent)
521 text: BadgeContent.text(control.badgeContent)
522 locale: control.locale
523 variant: control.badgeNotification ? MD.Badge.Small : control.badgeVariant
524 accessibleDescription: control.badgeAccessibleDescription.length > 0
525 ? control.badgeAccessibleDescription : _defaultAccessibleDescription
526 visible: control._showBadge && targetAvailable
530 background: Rectangle {
531 implicitWidth: visualState.buttonSize.width
532 implicitHeight: visualState.buttonSize.height
534 topLeftRadius: control.__groupTopLeftRadius >= 0 ? control.__groupTopLeftRadius : UiMetrics.resolveShapeRadius(visualState.containerShape.topLeft, width, height)
535 topRightRadius: control.__groupTopRightRadius >= 0 ? control.__groupTopRightRadius : UiMetrics.resolveShapeRadius(visualState.containerShape.topRight, width, height)
536 bottomLeftRadius: control.__groupBottomLeftRadius >= 0 ? control.__groupBottomLeftRadius : UiMetrics.resolveShapeRadius(visualState.containerShape.bottomLeft, width, height)
537 bottomRightRadius: control.__groupBottomRightRadius >= 0 ? control.__groupBottomRightRadius : UiMetrics.resolveShapeRadius(visualState.containerShape.bottomRight, width, height)
539 Behavior on topLeftRadius {
540 enabled: !control.__buttonGroup || control.__buttonGroup.__geometryInitialized
542 easing.type: Easing.BezierSpline
543 easing.bezierCurve: MotionAnimation.expressiveFastSpatialCurve
544 duration: MotionAnimation.expressiveFastSpatialDuration
547 Behavior on topRightRadius {
548 enabled: !control.__buttonGroup || control.__buttonGroup.__geometryInitialized
550 easing.type: Easing.BezierSpline
551 easing.bezierCurve: MotionAnimation.expressiveFastSpatialCurve
552 duration: MotionAnimation.expressiveFastSpatialDuration
555 Behavior on bottomLeftRadius {
556 enabled: !control.__buttonGroup || control.__buttonGroup.__geometryInitialized
558 easing.type: Easing.BezierSpline
559 easing.bezierCurve: MotionAnimation.expressiveFastSpatialCurve
560 duration: MotionAnimation.expressiveFastSpatialDuration
563 Behavior on bottomRightRadius {
564 enabled: !control.__buttonGroup || control.__buttonGroup.__geometryInitialized
566 easing.type: Easing.BezierSpline
567 easing.bezierCurve: MotionAnimation.expressiveFastSpatialCurve
568 duration: MotionAnimation.expressiveFastSpatialDuration
572 border.width: control.type === MD.IconButton.Type.Outlined && !control.checked ? visualState.outlineWidth : 0
573 border.color: control.outlineColor
575 opacity: visualState.containerOpacity
576 color: visualState.containerColor
581 topLeftRadius: parent.topLeftRadius
582 topRightRadius: parent.topRightRadius
583 bottomLeftRadius: parent.bottomLeftRadius
584 bottomRightRadius: parent.bottomRightRadius
586 pressed: control.pressed
587 pressX: control.pressX
588 pressY: control.pressY
590 stateOpacity: visualState.stateLayerOpacity
591 color: visualState.stateLayerColor