2023-07-10 05:53:00 -04:00
|
|
|
import St from 'gi://St';
|
|
|
|
import Clutter from 'gi://Clutter';
|
2023-07-10 00:58:21 -04:00
|
|
|
|
2023-07-10 05:53:00 -04:00
|
|
|
import * as Params from './params.js';
|
2023-07-10 00:58:21 -04:00
|
|
|
|
2023-07-10 05:53:00 -04:00
|
|
|
const SCROLL_TIME = 100;
|
2023-07-10 00:58:21 -04:00
|
|
|
|
|
|
|
const WIGGLE_OFFSET = 6;
|
|
|
|
const WIGGLE_DURATION = 65;
|
|
|
|
const N_WIGGLES = 3;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* adjustAnimationTime:
|
|
|
|
*
|
|
|
|
* @param {number} msecs - time in milliseconds
|
|
|
|
*
|
|
|
|
* Adjust `msecs` to account for St's enable-animations
|
|
|
|
* and slow-down-factor settings
|
|
|
|
*/
|
2023-07-10 05:53:00 -04:00
|
|
|
export function adjustAnimationTime(msecs) {
|
2023-07-10 00:58:21 -04:00
|
|
|
const settings = St.Settings.get();
|
|
|
|
|
|
|
|
if (!settings.enable_animations)
|
|
|
|
return 0;
|
|
|
|
return settings.slow_down_factor * msecs;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Animate scrolling a scrollview until an actor is visible.
|
|
|
|
*
|
|
|
|
* @param {St.ScrollView} scrollView - the scroll view the actor is in
|
|
|
|
* @param {Clutter.Actor} actor - the actor
|
|
|
|
*/
|
2023-07-10 05:53:00 -04:00
|
|
|
export function ensureActorVisibleInScrollView(scrollView, actor) {
|
2023-07-10 00:58:21 -04:00
|
|
|
const {adjustment} = scrollView.vscroll;
|
|
|
|
let [value, lower_, upper, stepIncrement_, pageIncrement_, pageSize] = adjustment.get_values();
|
|
|
|
|
|
|
|
let offset = 0;
|
|
|
|
const vfade = scrollView.get_effect('fade');
|
|
|
|
if (vfade)
|
|
|
|
offset = vfade.fade_margins.top;
|
|
|
|
|
|
|
|
let box = actor.get_allocation_box();
|
|
|
|
let y1 = box.y1, y2 = box.y2;
|
|
|
|
|
|
|
|
let parent = actor.get_parent();
|
|
|
|
while (parent !== scrollView) {
|
|
|
|
if (!parent)
|
|
|
|
throw new Error('actor not in scroll view');
|
|
|
|
|
|
|
|
box = parent.get_allocation_box();
|
|
|
|
y1 += box.y1;
|
|
|
|
y2 += box.y1;
|
|
|
|
parent = parent.get_parent();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (y1 < value + offset)
|
|
|
|
value = Math.max(0, y1 - offset);
|
|
|
|
else if (y2 > value + pageSize - offset)
|
|
|
|
value = Math.min(upper, y2 + offset - pageSize);
|
|
|
|
else
|
|
|
|
return;
|
|
|
|
|
|
|
|
adjustment.ease(value, {
|
|
|
|
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
|
|
|
|
duration: SCROLL_TIME,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* "Wiggles" a clutter actor. A "wiggle" is an animation the moves an actor
|
|
|
|
* back and forth on the X axis a specified amount of times.
|
|
|
|
*
|
|
|
|
* @param {Clutter.Actor} actor - an actor to animate
|
|
|
|
* @param {object} params - options for the animation
|
|
|
|
* @param {number} params.offset - the offset to move the actor by per-wiggle
|
|
|
|
* @param {number} params.duration - the amount of time to move the actor per-wiggle
|
|
|
|
* @param {number} params.wiggleCount - the number of times to wiggle the actor
|
|
|
|
*/
|
2023-07-10 05:53:00 -04:00
|
|
|
export function wiggle(actor, params) {
|
2023-07-10 00:58:21 -04:00
|
|
|
if (!St.Settings.get().enable_animations)
|
|
|
|
return;
|
|
|
|
|
|
|
|
params = Params.parse(params, {
|
|
|
|
offset: WIGGLE_OFFSET,
|
|
|
|
duration: WIGGLE_DURATION,
|
|
|
|
wiggleCount: N_WIGGLES,
|
|
|
|
});
|
|
|
|
actor.translation_x = 0;
|
|
|
|
|
|
|
|
// Accelerate before wiggling
|
|
|
|
actor.ease({
|
|
|
|
translation_x: -params.offset,
|
|
|
|
duration: params.duration,
|
|
|
|
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
|
|
|
|
onComplete: () => {
|
|
|
|
// Wiggle
|
|
|
|
actor.ease({
|
|
|
|
translation_x: params.offset,
|
|
|
|
duration: params.duration,
|
|
|
|
mode: Clutter.AnimationMode.LINEAR,
|
|
|
|
repeatCount: params.wiggleCount,
|
|
|
|
autoReverse: true,
|
|
|
|
onComplete: () => {
|
|
|
|
// Decelerate and return to the original position
|
|
|
|
actor.ease({
|
|
|
|
translation_x: 0,
|
|
|
|
duration: params.duration,
|
|
|
|
mode: Clutter.AnimationMode.EASE_IN_QUAD,
|
|
|
|
});
|
|
|
|
},
|
|
|
|
});
|
|
|
|
},
|
|
|
|
});
|
|
|
|
}
|