animation: Optionally animate spinner start/stop

In contrast to generic animated icons, it is reasonable to expect
spinners to be invisible while inactive. Implement that behavior
in the new Spinner class and optionally animate the transitions.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/316
This commit is contained in:
Florian Müllner 2018-11-28 17:34:48 +01:00 committed by Florian Müllner
parent 22e21ad7d1
commit 945a019974
3 changed files with 51 additions and 50 deletions

View File

@ -8,7 +8,11 @@ const St = imports.gi.St;
const Signals = imports.signals; const Signals = imports.signals;
const Atk = imports.gi.Atk; const Atk = imports.gi.Atk;
const Tweener = imports.ui.tweener;
var ANIMATED_ICON_UPDATE_TIMEOUT = 16; var ANIMATED_ICON_UPDATE_TIMEOUT = 16;
var SPINNER_ANIMATION_TIME = 0.3;
var SPINNER_ANIMATION_DELAY = 1.0;
var Animation = new Lang.Class({ var Animation = new Lang.Class({
Name: 'Animation', Name: 'Animation',
@ -92,8 +96,46 @@ var Spinner = new Lang.Class({
Name: 'Spinner', Name: 'Spinner',
Extends: AnimatedIcon, Extends: AnimatedIcon,
_init(size) { _init(size, animate=false) {
let file = Gio.File.new_for_uri('resource:///org/gnome/shell/theme/process-working.svg'); let file = Gio.File.new_for_uri('resource:///org/gnome/shell/theme/process-working.svg');
this.parent(file, size); this.parent(file, size);
this.actor.opacity = 0;
this._animate = animate;
},
play() {
Tweener.removeTweens(this.actor);
if (this._animate) {
this.parent();
Tweener.addTween(this.actor, {
opacity: 255,
delay: SPINNER_ANIMATION_DELAY,
time: SPINNER_ANIMATION_TIME,
transition: 'linear'
});
} else {
this.actor.opacity = 255;
this.parent();
}
},
stop() {
Tweener.removeTweens(this.actor);
if (this._animate) {
Tweener.addTween(this.actor, {
opacity: 0,
time: SPINNER_ANIMATION_TIME,
transition: 'linear',
onComplete: () => {
this.stop(false);
}
});
} else {
this.actor.opacity = 0;
this.parent();
}
} }
}); });

View File

@ -17,8 +17,6 @@ const CheckBox = imports.ui.checkBox;
const Tweener = imports.ui.tweener; const Tweener = imports.ui.tweener;
var WORK_SPINNER_ICON_SIZE = 16; var WORK_SPINNER_ICON_SIZE = 16;
var WORK_SPINNER_ANIMATION_DELAY = 1.0;
var WORK_SPINNER_ANIMATION_TIME = 0.3;
var KeyringDialog = new Lang.Class({ var KeyringDialog = new Lang.Class({
Name: 'KeyringDialog', Name: 'KeyringDialog',
@ -69,27 +67,10 @@ var KeyringDialog = new Lang.Class({
if (!this._workSpinner) if (!this._workSpinner)
return; return;
Tweener.removeTweens(this._workSpinner.actor); if (working)
if (working) {
this._workSpinner.play(); this._workSpinner.play();
Tweener.addTween(this._workSpinner.actor, else
{ opacity: 255,
delay: WORK_SPINNER_ANIMATION_DELAY,
time: WORK_SPINNER_ANIMATION_TIME,
transition: 'linear'
});
} else {
Tweener.addTween(this._workSpinner.actor,
{ opacity: 0,
time: WORK_SPINNER_ANIMATION_TIME,
transition: 'linear',
onCompleteScope: this,
onComplete() {
if (this._workSpinner)
this._workSpinner.stop(); this._workSpinner.stop();
}
});
}
}, },
_buildControlTable() { _buildControlTable() {
@ -114,8 +95,7 @@ var KeyringDialog = new Lang.Class({
ShellEntry.addContextMenu(this._passwordEntry, { isPassword: true }); ShellEntry.addContextMenu(this._passwordEntry, { isPassword: true });
this._passwordEntry.clutter_text.connect('activate', this._onPasswordActivate.bind(this)); this._passwordEntry.clutter_text.connect('activate', this._onPasswordActivate.bind(this));
this._workSpinner = new Animation.Spinner(WORK_SPINNER_ICON_SIZE); this._workSpinner = new Animation.Spinner(WORK_SPINNER_ICON_SIZE, true);
this._workSpinner.actor.opacity = 0;
if (rtl) { if (rtl) {
layout.attach(this._workSpinner.actor, 0, row, 1, 1); layout.attach(this._workSpinner.actor, 0, row, 1, 1);

View File

@ -25,8 +25,6 @@ const Tweener = imports.ui.tweener;
var DIALOG_ICON_SIZE = 48; var DIALOG_ICON_SIZE = 48;
var WORK_SPINNER_ICON_SIZE = 16; var WORK_SPINNER_ICON_SIZE = 16;
var WORK_SPINNER_ANIMATION_DELAY = 1.0;
var WORK_SPINNER_ANIMATION_TIME = 0.3;
var AuthenticationDialog = new Lang.Class({ var AuthenticationDialog = new Lang.Class({
Name: 'AuthenticationDialog', Name: 'AuthenticationDialog',
@ -117,9 +115,7 @@ var AuthenticationDialog = new Lang.Class({
this._passwordBox.add(this._passwordEntry, this._passwordBox.add(this._passwordEntry,
{ expand: true }); { expand: true });
this._workSpinner = new Animation.Spinner(WORK_SPINNER_ICON_SIZE); this._workSpinner = new Animation.Spinner(WORK_SPINNER_ICON_SIZE, true);
this._workSpinner.actor.opacity = 0;
this._passwordBox.add(this._workSpinner.actor); this._passwordBox.add(this._workSpinner.actor);
this.setInitialKeyFocus(this._passwordEntry); this.setInitialKeyFocus(this._passwordEntry);
@ -163,27 +159,10 @@ var AuthenticationDialog = new Lang.Class({
}, },
_setWorking(working) { _setWorking(working) {
Tweener.removeTweens(this._workSpinner.actor); if (working)
if (working) {
this._workSpinner.play(); this._workSpinner.play();
Tweener.addTween(this._workSpinner.actor, else
{ opacity: 255,
delay: WORK_SPINNER_ANIMATION_DELAY,
time: WORK_SPINNER_ANIMATION_TIME,
transition: 'linear'
});
} else {
Tweener.addTween(this._workSpinner.actor,
{ opacity: 0,
time: WORK_SPINNER_ANIMATION_TIME,
transition: 'linear',
onCompleteScope: this,
onComplete() {
if (this._workSpinner)
this._workSpinner.stop(); this._workSpinner.stop();
}
});
}
}, },
performAuthentication() { performAuthentication() {