dots/widgets/TextButton.qml
2025-06-10 21:46:51 -04:00

204 lines
5.4 KiB
QML

import QtQuick
import Qt5Compat.GraphicalEffects
import Quickshell
import Quickshell.Widgets
import ".."
Item {
id: root
property string icon
property bool enabled: true
property bool highlight: true
property bool clickable: false
property bool useMask: true
property bool useVariableFill: false
property real size: 18
property real outerSize: size
property color hoverColor: ShellSettings.colors["inverse_primary"]
property color iconColor: ShellSettings.colors["primary"]
property real buttonRadius: 6
property real padding: 4
property real fillValue: 0.0
property real fillTarget: 0.0
property real fillHover: 1.0
property real fillNormal: 0.0
property int fillDuration: 300
signal clicked(var mouse)
implicitWidth: outerSize + (padding * 2)
implicitHeight: outerSize + (padding * 2)
Rectangle {
id: backgroundRect
anchors.fill: parent
radius: root.buttonRadius
color: mouseArea.containsMouse && root.highlight ? root.hoverColor : "transparent"
visible: root.highlight
Behavior on color {
ColorAnimation {
duration: 200
easing.type: Easing.InOutCubic
}
}
}
NumberAnimation {
id: fillAnimation
target: root
property: "fillValue"
duration: root.fillDuration
easing.type: Easing.OutCubic
to: root.fillTarget
}
Text {
id: variableFillIcon
visible: root.useVariableFill
anchors.centerIn: parent
font.family: "Material Symbols Outlined"
renderType: Text.NativeRendering
textFormat: Text.PlainText
font.pointSize: root.size * 0.8
text: root.icon
color: root.enabled ?? root.iconColor
opacity: root.enabled ? 1.0 : 0.5
font.variableAxes: {
"FILL": root.fillValue.toFixed(1)
}
Behavior on color {
ColorAnimation {
duration: 200
easing.type: Easing.InOutCubic
}
}
}
Item {
id: maskedIcon
visible: root.useMask && !root.useVariableFill
anchors.centerIn: parent
width: root.size
height: root.size
smooth: true
layer.enabled: true
layer.effect: OpacityMask {
source: Rectangle {
width: root.size
height: root.size
color: "white"
}
maskSource: IconImage {
mipmap: true
implicitSize: root.size
source: Quickshell.iconPath(root.icon)
opacity: root.enabled ? 1.0 : 0.5
smooth: true
}
}
transform: Translate {
x: mouseArea.containsMouse ? -1 : 0
y: mouseArea.containsMouse ? -2 : 0
Behavior on x {
NumberAnimation {
duration: 450
easing.type: Easing.OutElastic
easing.amplitude: 1.0
easing.period: 0.3
}
}
Behavior on y {
NumberAnimation {
duration: 450
easing.type: Easing.OutElastic
easing.amplitude: 1.0
easing.period: 0.3
}
}
}
Rectangle {
anchors.fill: parent
color: root.enabled ?? root.iconColor
Behavior on color {
ColorAnimation {
duration: 200
easing.type: Easing.InOutCubic
}
}
}
}
IconImage {
id: unmaskedIcon
visible: !root.useMask && !root.useVariableFill
anchors.centerIn: parent
source: Quickshell.iconPath(root.icon)
implicitSize: root.size
opacity: root.enabled ? 1.0 : 0.5
transform: Translate {
x: mouseArea.containsMouse ? -1 : 0
y: mouseArea.containsMouse ? -2 : 0
Behavior on x {
NumberAnimation {
duration: 350
easing.type: Easing.OutElastic
easing.amplitude: 1.0
easing.period: 0.6
}
}
Behavior on y {
NumberAnimation {
duration: 350
easing.type: Easing.OutElastic
easing.amplitude: 1.0
easing.period: 0.6
}
}
}
Behavior on opacity {
NumberAnimation {
duration: 200
easing.type: Easing.InOutCubic
}
}
}
MouseArea {
id: mouseArea
anchors.fill: parent
cursorShape: root.clickable ? Qt.PointingHandCursor : ""
enabled: root.clickable && root.enabled
hoverEnabled: true
acceptedButtons: Qt.LeftButton | Qt.RightButton | Qt.MiddleButton
onClicked: function (mouse) {
root.clicked(mouse);
}
onContainsMouseChanged: {
if (root.useVariableFill) {
root.fillTarget = containsMouse ? root.fillHover : root.fillNormal;
fillAnimation.restart();
}
}
}
Component.onCompleted: {
if (useVariableFill) {
fillValue = fillNormal;
}
}
}