Kirigami-addons

DoubleFloatingButton.qml
1// SPDX-FileCopyrightText: 2023 Mathis BrĂ¼chert <mbb@kaidan.im>
2// SPDX-FileCopyrightText: 2023 Carl Schwan <carl@carlschwan.eu>
3//
4// SPDX-License-Identifier: LGPL-2.0-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
5
6import QtQuick 2.15
7import QtQuick.Layouts 1.15
8import QtQuick.Controls 2.15 as QQC2
9import QtQuick.Templates 2.15 as T
10import org.kde.kirigami 2.20 as Kirigami
11
12/**
13 * This component allows to display two buttons at the bottom of a page.
14 *
15 * @code{.qml}
16 * import QtQuick 2.15
17 * import QtQuick.Controls 2.15 as QQC2
18 * import org.kde.kirigami 2.20 as Kirigami
19 * import org.kde.kirigamiaddons.components 1.0 as KirigamiComponents
20 *
21 * Kirigami.ScrollablePage {
22 * ListView {
23 * model: []
24 * delegate: QQC2.ItemDelegate {}
25 *
26 * KirigamiComponents.DoubleFloatingButton {
27 * anchors {
28 * right: parent.right
29 * bottom: parent.bottom
30 * margins: Kirigami.Units.largeSpacing
31 * }
32 *
33 * leadingAction: Kirigami.Action {
34 * text: "Zoom Out"
35 * icon.name: "list-remove"
36 * }
37 *
38 * trailingAction: Kirigami.Action {
39 * text: "Zoom In"
40 * icon.name: "list-add"
41 * }
42 * }
43 * }
44 * }
45 * @endcode
46 *
47 * @since Kirigami Addons 0.11
48 */
49Kirigami.ShadowedRectangle {
50 id: root
51
52 /**
53 * This property holds the leading action.
54 */
55 property Kirigami.Action leadingAction
57 /**
58 * This property holds the trailing action.
59 */
60 property Kirigami.Action trailingAction
61
62 // Note: binding corners to each other results in binding loops, because
63 // they share one common NOTIFY signal. Storing properties wastes memory.
64 // So these two expressions are implemented as little helper functions.
65
66 // Left for leading and right for trailing buttons
67 function __radiusA(): real {
68 return LayoutMirroring.enabled ? 0 : radius;
69 }
70
71 // and vice-versa
72 function __radiusB(): real {
73 return LayoutMirroring.enabled ? radius : 0;
74 }
75
76 readonly property real __padding: radius === Infinity
77 ? Math.round(Math.max(Math.max(leadingButton.__effectiveIconSize.width, leadingButton.__effectiveIconSize.height), Math.max(trailingButton.__effectiveIconSize.width, trailingButton.__effectiveIconSize.height)) * (Math.sqrt(2) - 1))
78 : Kirigami.Settings.hasTransientTouchInput ? (Kirigami.Units.largeSpacing * 2) : Kirigami.Units.largeSpacing
79
80
81
82 // Extra clickable area that adjusts both paddings and insets.
83 property real margins: 0
84 property real topMargin: margins
85 property real leftMargin: margins
86 property real rightMargin: margins
87 property real bottomMargin: margins
88
89 radius: Kirigami.Units.largeSpacing
90 color: Kirigami.Theme.backgroundColor
91
92 implicitHeight: Math.max(leadingButton.implicitBackgroundHeight + leadingButton.topInset + leadingButton.bottomInset,
93 leadingButton.implicitContentHeight + leadingButton.topPadding + leadingButton.bottomPadding)
94 implicitWidth: 2 * implicitHeight - 1
95
96 shadow {
97 size: 10
98 xOffset: 0
99 yOffset: 2
100 color: Qt.rgba(0, 0, 0, 0.2)
101 }
102
103 T.RoundButton {
104 id: leadingButton
105
106 LayoutMirroring.enabled: root.LayoutMirroring.enabled
107
108 readonly property size __effectiveIconSize: Qt.size(
109 root.leadingAction.icon.height > 0 ? root.leadingAction.icon.height : Kirigami.Units.iconSizes.medium,
110 root.leadingAction.icon.width > 0 ? root.leadingAction.icon.width : Kirigami.Units.iconSizes.medium,
111 )
112
113 // Fit icon into a square bounded by a circle bounded by button
114 padding: root.__padding
115
116 topPadding: padding + root.topMargin
117 leftPadding: padding + root.leftMargin
118 rightPadding: padding + root.rightMargin
119 bottomPadding: padding + root.bottomMargin
120
121 // If user overrides individual padding value, we should adjust background. By default all insets will be 0.
122 topInset: root.topMargin
123 leftInset: root.leftMargin
124 rightInset: root.rightMargin
125 bottomInset: root.bottomMargin
126
127 z: (down || visualFocus || (enabled && hovered)) ? 2 : leadingButtonBorderAnimation.running ? 1 : 0
128
129 background: Kirigami.ShadowedRectangle {
130 id: leadingButtonBackground
131
132 Kirigami.Theme.inherit: false
133 Kirigami.Theme.colorSet: Kirigami.Theme.Button
134
135 corners {
136 topLeftRadius: root.__radiusA()
137 bottomLeftRadius: root.__radiusA()
138 topRightRadius: root.__radiusB()
139 bottomRightRadius: root.__radiusB()
140 }
141
142 border {
143 width: 1
144 color: if (leadingButton.down || leadingButton.visualFocus) {
145 Kirigami.ColorUtils.tintWithAlpha(Kirigami.Theme.hoverColor, Kirigami.Theme.backgroundColor, 0.4)
146 } else if (leadingButton.enabled && leadingButton.hovered) {
147 Kirigami.ColorUtils.tintWithAlpha(Kirigami.Theme.hoverColor, Kirigami.Theme.backgroundColor, 0.6)
148 } else {
149 Kirigami.ColorUtils.linearInterpolation(Kirigami.Theme.backgroundColor, Kirigami.Theme.textColor, Kirigami.Theme.frameContrast)
150 }
151 }
152
153
154 color: if (leadingButton.down || leadingButton.visualFocus) {
155 Kirigami.ColorUtils.tintWithAlpha(Kirigami.Theme.hoverColor, Kirigami.Theme.backgroundColor, 0.6)
156 } else if (leadingButton.enabled && leadingButton.hovered) {
157 Kirigami.ColorUtils.tintWithAlpha(Kirigami.Theme.hoverColor, Kirigami.Theme.backgroundColor, 0.8)
158 } else {
159 Kirigami.Theme.backgroundColor
160 }
161
162 Behavior on color {
163 enabled: true
164 ColorAnimation {
165 duration: Kirigami.Units.longDuration
166 easing.type: Easing.OutCubic
167 }
168 }
169
170 Behavior on border.color {
171 enabled: true
172 ColorAnimation {
173 id: leadingButtonBorderAnimation
174 duration: Kirigami.Units.longDuration
175 easing.type: Easing.OutCubic
176 }
177 }
178 }
179
180 contentItem: Item {
181 implicitWidth: parent.__effectiveIconSize.width
182 implicitHeight: parent.__effectiveIconSize.height
183
184 Kirigami.Icon {
185 anchors.fill: parent
186 color: root.leadingAction.icon.color
187 source: root.leadingAction.icon.name !== "" ? root.leadingAction.icon.name : root.leadingAction.icon.source
188 }
189 }
190
191 action: root.leadingAction
192 anchors.left: root.left
193 height: root.height
194 width: root.height
195 enabled: action ? action.enabled : false
196 display: QQC2.AbstractButton.IconOnly
197 QQC2.ToolTip.visible: hovered && QQC2.ToolTip.text.length > 0
198 QQC2.ToolTip.delay: Kirigami.Units.toolTipDelay
199 QQC2.ToolTip.text: action.tooltip
200 }
201
202 T.RoundButton {
203 id: trailingButton
204
205 readonly property size __effectiveIconSize: Qt.size(
206 root.trailingAction.icon.height > 0 ? root.trailingAction.icon.height : Kirigami.Units.iconSizes.medium,
207 root.trailingAction.icon.width > 0 ? root.trailingAction.icon.width : Kirigami.Units.iconSizes.medium,
208 )
209
210 // Fit icon into a square bounded by a circle bounded by button
211 padding: root.__padding
212
213 topPadding: padding + root.topMargin
214 leftPadding: padding + root.leftMargin
215 rightPadding: padding + root.rightMargin
216 bottomPadding: padding + root.bottomMargin
217
218 // If user overrides individual padding value, we should adjust background. By default all insets will be 0.
219 topInset: root.topMargin
220 leftInset: root.leftMargin
221 rightInset: root.rightMargin
222 bottomInset: root.bottomMargin
223
224 LayoutMirroring.enabled: root.LayoutMirroring.enabled
225
226 z: (down || visualFocus || (enabled && hovered)) ? 2 : trailingButtonBorderAnimation.running ? 1 : 0
227
228 background: Kirigami.ShadowedRectangle {
229 Kirigami.Theme.inherit: false
230 Kirigami.Theme.colorSet: Kirigami.Theme.Button
231
232 corners {
233 topLeftRadius: root.__radiusB()
234 bottomLeftRadius: root.__radiusB()
235 topRightRadius: root.__radiusA()
236 bottomRightRadius: root.__radiusA()
237 }
238
239 border {
240 width: 1
241 color: if (trailingButton.down || trailingButton.visualFocus) {
242 Kirigami.ColorUtils.tintWithAlpha(Kirigami.Theme.hoverColor, Kirigami.Theme.backgroundColor, 0.4)
243 } else if (trailingButton.enabled && trailingButton.hovered) {
244 Kirigami.ColorUtils.tintWithAlpha(Kirigami.Theme.hoverColor, Kirigami.Theme.backgroundColor, 0.6)
245 } else {
246 Kirigami.ColorUtils.linearInterpolation(Kirigami.Theme.backgroundColor, Kirigami.Theme.textColor, Kirigami.Theme.frameContrast)
247 }
248 }
249
250 color: if (trailingButton.down || trailingButton.visualFocus) {
251 Kirigami.ColorUtils.tintWithAlpha(Kirigami.Theme.hoverColor, Kirigami.Theme.backgroundColor, 0.6)
252 } else if (trailingButton.enabled && trailingButton.hovered) {
253 Kirigami.ColorUtils.tintWithAlpha(Kirigami.Theme.hoverColor, Kirigami.Theme.backgroundColor, 0.8)
254 } else {
255 Kirigami.Theme.backgroundColor
256 }
257
258 Behavior on color {
259 enabled: true
260 ColorAnimation {
261 duration: Kirigami.Units.longDuration
262 easing.type: Easing.OutCubic
263 }
264 }
265
266 Behavior on border.color {
267 id: trailingButtonBorderAnimation
268 enabled: true
269 ColorAnimation {
270 duration: Kirigami.Units.longDuration
271 easing.type: Easing.OutCubic
272 }
273 }
274 }
275
276 contentItem: Item {
277 implicitWidth: parent.__effectiveIconSize.width
278 implicitHeight: parent.__effectiveIconSize.height
279
280 Kirigami.Icon {
281 anchors.fill: parent
282 color: root.trailingAction.icon.color
283 source: root.trailingAction.icon.name !== "" ? root.trailingAction.icon.name : root.trailingAction.icon.source
284 }
285 }
286
287 action: root.trailingAction
288 anchors.right: root.right
289 height: root.height
290 width: root.height
291 enabled: action ? action.enabled : false
292 display: QQC2.AbstractButton.IconOnly
293 QQC2.ToolTip.visible: hovered && QQC2.ToolTip.text.length > 0
294 QQC2.ToolTip.delay: Kirigami.Units.toolTipDelay
295 QQC2.ToolTip.text: action.tooltip
296 }
297}
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Mon Nov 18 2024 12:12:26 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.