Skip to content

Commit 0991190

Browse files
committed
Add missing file
1 parent 6b4851d commit 0991190

File tree

1 file changed

+177
-0
lines changed

1 file changed

+177
-0
lines changed
Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
/*
2+
* Copyright 2024 elementary, Inc. (https://elementary.io)
3+
* SPDX-License-Identifier: GPL-3.0-or-later
4+
*
5+
* Authored by: Leonhard Kargl <[email protected]>
6+
*/
7+
8+
/**
9+
* A class that will animate a property of a {@link Clutter.Actor} one to one with a gesture or
10+
* with easing without a gesture. Respects the enable animation setting.
11+
*/
12+
public class Gala.GesturePropertyTransition : Object {
13+
/**
14+
* Emitted when all animations are finished that is when the property has reached the target value
15+
* either via gesture or via easing or combined.
16+
*/
17+
public signal void done ();
18+
19+
/**
20+
* The actor whose property will be animated.
21+
*/
22+
public Clutter.Actor actor { get; construct; }
23+
24+
public GestureTracker gesture_tracker { get; construct; }
25+
26+
/**
27+
* The property that will be animated. To be properly animated it has to be marked as
28+
* animatable in the Clutter documentation and should be numeric.
29+
*/
30+
public string property { get; construct; }
31+
32+
/**
33+
* The starting value of the animation or null to use the current value. The value
34+
* has to be of the same type as the property.
35+
*/
36+
public Value? from_value { get; construct set; }
37+
38+
/**
39+
* The value to animate to. It has to be of the same type as the property.
40+
*/
41+
public Value to_value { get; construct set; }
42+
43+
/**
44+
* If not null this can be used to have an intermediate step before animating back to the origin.
45+
* Therefore using this makes mostly sense if {@link to_value} equals {@link from_value}.
46+
* This is mostly used for the nudge animations when trying to switch workspaces where there isn't one anymore.
47+
*/
48+
public Value? intermediate_value { get; construct; }
49+
50+
public GesturePropertyTransition (
51+
Clutter.Actor actor,
52+
GestureTracker gesture_tracker,
53+
string property,
54+
Value? from_value,
55+
Value to_value,
56+
Value? intermediate_value = null
57+
) {
58+
Object (
59+
actor: actor,
60+
gesture_tracker: gesture_tracker,
61+
property: property,
62+
from_value: from_value,
63+
to_value: to_value,
64+
intermediate_value: intermediate_value
65+
);
66+
}
67+
68+
construct {
69+
done.connect (unref);
70+
}
71+
72+
/**
73+
* Starts animating the property from {@link from_value} to {@link to_value}. If with_gesture is true
74+
* it will connect to the gesture trackers signals and animate according to the input finishing with an easing
75+
* to the final position. If with_gesture is false it will just ease to the {@link to_value}.
76+
* #this will keep itself alive until the animation finishes so it is safe to immediatly unref it after creation and calling start.
77+
*/
78+
public void start (bool with_gesture) {
79+
ref ();
80+
81+
Value current_value = {};
82+
actor.get_property (property, ref current_value);
83+
84+
if (from_value == null) {
85+
from_value = current_value;
86+
87+
ulong done_handler = 0;
88+
done_handler = done.connect (() => {
89+
from_value = null;
90+
disconnect (done_handler);
91+
});
92+
} else if (from_value.type () != current_value.type ()) {
93+
warning ("from_value of type %s is not of the same type as the property %s which is %s. Can't animate.", from_value.type_name (), property, current_value.type_name ());
94+
done ();
95+
return;
96+
}
97+
98+
if (current_value.type () != to_value.type ()) {
99+
warning ("to_value of type %s is not of the same type as the property %s which is %s. Can't animate.", to_value.type_name (), property, current_value.type_name ());
100+
done ();
101+
return;
102+
}
103+
104+
GestureTracker.OnBegin on_animation_begin = () => {
105+
actor.set_property (property, from_value);
106+
};
107+
108+
GestureTracker.OnUpdate on_animation_update = (percentage) => {
109+
var animation_value = GestureTracker.animation_value (value_to_float (from_value), value_to_float (intermediate_value ?? to_value), percentage);
110+
actor.set_property (property, value_from_float (animation_value));
111+
};
112+
113+
GestureTracker.OnEnd on_animation_end = (percentage, cancel_action, calculated_duration) => {
114+
if (cancel_action) {
115+
return;
116+
}
117+
118+
actor.save_easing_state ();
119+
actor.set_easing_mode (Clutter.AnimationMode.EASE_OUT_QUAD);
120+
actor.set_easing_duration (gesture_tracker.settings.is_animation_enabled () ? calculated_duration : 0);
121+
actor.set_property (property, cancel_action ? from_value : to_value);
122+
actor.restore_easing_state ();
123+
124+
unowned var transition = actor.get_transition (property);
125+
if (transition == null) {
126+
done ();
127+
} else {
128+
transition.stopped.connect (() => done ());
129+
}
130+
};
131+
132+
if (with_gesture && gesture_tracker.settings.is_animation_enabled ()) {
133+
gesture_tracker.connect_handlers (on_animation_begin, on_animation_update, on_animation_end);
134+
} else {
135+
on_animation_begin (0);
136+
if (intermediate_value != null) {
137+
actor.save_easing_state ();
138+
actor.set_easing_mode (Clutter.AnimationMode.EASE_OUT_QUAD);
139+
actor.set_easing_duration (gesture_tracker.settings.is_animation_enabled () ? gesture_tracker.min_animation_duration : 0);
140+
actor.set_property (property, intermediate_value);
141+
actor.restore_easing_state ();
142+
143+
unowned var transition = actor.get_transition (property);
144+
if (transition == null) {
145+
on_animation_end (1, false, gesture_tracker.min_animation_duration);
146+
} else {
147+
transition.stopped.connect (() => on_animation_end (1, false, gesture_tracker.min_animation_duration));
148+
}
149+
} else {
150+
on_animation_end (1, false, gesture_tracker.min_animation_duration);
151+
}
152+
}
153+
}
154+
155+
private float value_to_float (Value val) {
156+
Value float_val = Value (typeof (float));
157+
if (val.transform (ref float_val)) {
158+
return float_val.get_float ();
159+
}
160+
161+
critical ("Non numeric property specified");
162+
return 0;
163+
}
164+
165+
private Value value_from_float (float f) {
166+
var float_val = Value (typeof (float));
167+
float_val.set_float (f);
168+
169+
var val = Value (from_value.type ());
170+
171+
if (!float_val.transform (ref val)) {
172+
warning ("Failed to transform float to give type");
173+
}
174+
175+
return val;
176+
}
177+
}

0 commit comments

Comments
 (0)