1// SPDX-FileCopyrightText: 2021 Nheko Contributors
2//
3// SPDX-License-Identifier: GPL-3.0-or-later
4
5import QtGraphicalEffects 1.0
6import QtQuick 2.10
7import QtQuick.Controls 2.3
8
9Item {
10    id: ripple
11
12    property alias clip: backgroundLayer.clip
13    property real radius: 0
14    property color color: "#22000000"
15    property real maxRadius: Math.max(width, height)
16    readonly property real radiusAnimationRate: 0.05
17    readonly property real radiusTailAnimationRate: 0.5
18    readonly property real opacityAnimationDuration: 300
19    readonly property real diameter: radius * 2
20    property real centerX
21    property real centerY
22    property var rippleTarget: parent
23
24    function start() {
25        console.log("Starting ripple animation");
26        ripple.state = "ACTIVE";
27    }
28
29    function stop() {
30        console.log("Stopping ripple animation");
31        ripple.state = "NORMAL";
32    }
33
34    anchors.fill: parent
35    state: "NORMAL"
36    states: [
37        State {
38            name: "NORMAL"
39        },
40        State {
41            name: "ACTIVE"
42        }
43    ]
44    transitions: [
45        Transition {
46            from: "NORMAL"
47            to: "ACTIVE"
48
49            SequentialAnimation {
50                ScriptAction {
51                    script: {
52                        ripple.opacity = 1;
53                        ripple.visible = true;
54                    }
55                }
56
57                NumberAnimation {
58                    id: radius_animation
59
60                    target: ripple
61                    properties: "radius"
62                    from: 0
63                    to: ripple.maxRadius
64                    duration: ripple.maxRadius / ripple.radiusAnimationRate
65
66                    easing {
67                        type: Easing.OutQuad
68                    }
69
70                }
71
72            }
73
74        },
75        Transition {
76            from: "ACTIVE"
77            to: "NORMAL"
78
79            SequentialAnimation {
80                ParallelAnimation {
81                    NumberAnimation {
82                        id: radius_tail_animation
83
84                        target: ripple
85                        properties: "radius"
86                        to: ripple.maxRadius
87                        duration: ripple.maxRadius / ripple.radiusTailAnimationRate
88
89                        easing {
90                            type: Easing.Linear
91                        }
92
93                    }
94
95                    NumberAnimation {
96                        id: opacity_animation
97
98                        target: ripple
99                        properties: "opacity"
100                        to: 0
101                        duration: ripple.opacityAnimationDuration
102
103                        easing {
104                            type: Easing.InQuad
105                        }
106
107                    }
108
109                }
110
111                ScriptAction {
112                    script: {
113                        ripple.visible = false;
114                    }
115                }
116
117            }
118
119        }
120    ]
121
122    Connections {
123        // Button
124        // Default to center
125
126        function onPressed(mouse) {
127            // MouseArea
128            if (mouse) {
129                ripple.centerX = mouse.x;
130                ripple.centerY = mouse.y;
131            } else if (rippleTarget.pressX) {
132                ripple.centerX = rippleTarget.pressX;
133                ripple.centerY = rippleTarget.pressY;
134            } else {
135                ripple.centerX = width / 2;
136                ripple.centerY = height / 2;
137            }
138            ripple.start();
139        }
140
141        function onReleased() {
142            ripple.stop();
143        }
144
145        function onExited() {
146            ripple.stop();
147        }
148
149        function onCanceled() {
150            ripple.stop();
151        }
152
153        function onClicked() {
154            ripple.stop();
155        }
156
157        target: rippleTarget
158        ignoreUnknownSignals: true
159    }
160
161    Rectangle {
162        id: backgroundLayer
163
164        anchors.fill: parent
165        color: "transparent"
166        clip: true
167
168        Rectangle {
169            id: circle
170
171            x: ripple.centerX - ripple.radius
172            y: ripple.centerY - ripple.radius
173            height: ripple.diameter
174            width: ripple.diameter
175            radius: ripple.radius
176            color: ripple.color
177        }
178
179    }
180
181}
182