environment: Add convenience method for property transitions

While we are now using implicit animations for all animatable properties,
there are still some cases where we animate other actor properties (for
example from a custom subclass) or associated objects like effects.

Those can still be animated using Clutter animations, as long as we use
the explicit API rather than implicit animations. Again this API is
cumbersome and tricky enough to warrant a convenience wrapper.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/666
This commit is contained in:
Florian Müllner 2017-06-10 04:14:12 +02:00
parent dfa41f6926
commit ef18f621ac

View File

@ -90,6 +90,25 @@ function _makeEaseCallback(params) {
}; };
} }
function _getPropertyTarget(actor, propName) {
if (!propName.startsWith('@'))
return [actor, propName];
let [type, name, prop] = propName.split('.');
switch (type) {
case '@layout':
return [actor.layout_manager, name];
case '@actions':
return [actor.get_action(name), prop];
case '@constraints':
return [actor.get_constraint(name), prop];
case '@effects':
return [actor.get_effect(name), prop];
}
throw new Error(`Invalid property name ${propName}`);
}
function _easeActor(actor, params) { function _easeActor(actor, params) {
actor.save_easing_state(); actor.save_easing_state();
@ -125,6 +144,45 @@ function _easeActor(actor, params) {
actor.restore_easing_state(); actor.restore_easing_state();
} }
function _easeActorProperty(actor, propName, target, params) {
// Avoid pointless difference with ease()
if (params.mode)
params.progress_mode = params.mode;
delete params.mode;
if (params.duration)
params.duration = adjustAnimationTime(params.duration);
let duration = Math.floor(params.duration || 0);
let callback = _makeEaseCallback(params);
// cancel overwritten transition
actor.remove_transition(propName);
if (duration == 0) {
let [obj, prop] = _getPropertyTarget(actor, propName);
obj[prop] = target;
if (callback)
callback(true);
return;
}
let pspec = actor.find_property(propName);
let transition = new Clutter.PropertyTransition(Object.assign({
property_name: propName,
interval: new Clutter.Interval({ value_type: pspec.value_type }),
remove_on_complete: true
}, params));
actor.add_transition(propName, transition);
transition.set_to(target);
if (callback)
_trackTransition(transition, callback);
}
function _loggingFunc(...args) { function _loggingFunc(...args) {
let fields = { 'MESSAGE': args.join(', ') }; let fields = { 'MESSAGE': args.join(', ') };
let domain = "GNOME Shell"; let domain = "GNOME Shell";
@ -173,6 +231,9 @@ function init() {
Clutter.Actor.prototype.ease = function(props, easingParams) { Clutter.Actor.prototype.ease = function(props, easingParams) {
_easeActor(this, props, easingParams); _easeActor(this, props, easingParams);
}; };
Clutter.Actor.prototype.ease_property = function(propName, target, params) {
_easeActorProperty(this, propName, target, params);
};
Clutter.Actor.prototype.toString = function() { Clutter.Actor.prototype.toString = function() {
return St.describe_actor(this); return St.describe_actor(this);