[gnome-shell] dash: Animate item and size changes
- From: Florian Müllner <fmuellner src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-shell] dash: Animate item and size changes
- Date: Wed, 9 Feb 2011 21:36:23 +0000 (UTC)
commit d6020f1402f3b5405388b507eb8c0a67216bdf37
Author: Florian Müllner <fmuellner gnome org>
Date: Fri Jan 21 12:06:13 2011 +0100
dash: Animate item and size changes
In general, all changes in the shell interface should be backed
by animations to give the interface a more natural feel and provide
feedback of what's happening. Currently the dash violates that
principle, as items simply appear/disappear or change size abruptly,
so add animations for application list and icon size changes.
https://bugzilla.gnome.org/show_bug.cgi?id=636156
js/ui/dash.js | 171 ++++++++++++++++++++++++++++++++++++++++++++++++++++++---
1 files changed, 162 insertions(+), 9 deletions(-)
---
diff --git a/js/ui/dash.js b/js/ui/dash.js
index 7a88e50..975d794 100644
--- a/js/ui/dash.js
+++ b/js/ui/dash.js
@@ -14,8 +14,11 @@ const AppFavorites = imports.ui.appFavorites;
const DND = imports.ui.dnd;
const IconGrid = imports.ui.iconGrid;
const Main = imports.ui.main;
+const Tweener = imports.ui.tweener;
const Workspace = imports.ui.workspace;
+const DASH_ANIMATION_TIME = 0.2;
+
// A container like StBin, but taking the child's scale into account
// when requesting a size
function DashItemContainer() {
@@ -34,6 +37,8 @@ DashItemContainer.prototype = {
this.actor._delegate = this;
this.child = null;
+ this._childScale = 1;
+ this._childOpacity = 255;
},
_allocate: function(actor, box, flags) {
@@ -90,6 +95,67 @@ DashItemContainer.prototype = {
this.child = actor;
this.actor.add_actor(this.child);
+ },
+
+ animateIn: function() {
+ if (this.child == null)
+ return;
+
+ this.childScale = 0;
+ this.childOpacity = 0;
+ Tweener.addTween(this,
+ { childScale: 1.0,
+ childOpacity: 255,
+ time: DASH_ANIMATION_TIME,
+ transition: 'easeOutQuad'
+ });
+ },
+
+ animateOutAndDestroy: function() {
+ if (this.child == null) {
+ this.actor.destroy();
+ return;
+ }
+
+ this.childScale = 1.0;
+ Tweener.addTween(this,
+ { childScale: 0.0,
+ childOpacity: 0,
+ time: DASH_ANIMATION_TIME,
+ transition: 'easeOutQuad',
+ onComplete: Lang.bind(this, function() {
+ this.actor.destroy();
+ })
+ });
+ },
+
+ set childScale(scale) {
+ this._childScale = scale;
+
+ if (this.child == null)
+ return;
+
+ this.child.set_scale_with_gravity(scale, scale,
+ Clutter.Gravity.CENTER);
+ this.actor.queue_relayout();
+ },
+
+ get childScale() {
+ return this._childScale;
+ },
+
+ set childOpacity(opacity) {
+ this._childOpacity = opacity;
+
+ if (this.child == null)
+ return;
+
+ this.child.set_opacity(opacity);
+ this.actor.queue_redraw();
+ },
+
+ get childOpacity() {
+ return this._childOpacity;
}
};
@@ -113,6 +179,12 @@ RemoveFavoriteIcon.prototype = {
this._iconBin._delegate = this;
this.setChild(this._iconBin);
+ this.hiding = false;
+ },
+
+ animateOutAndDestroy: function() {
+ DashItemContainer.prototype.animateOutAndDestroy.call(this);
+ this.hiding = true;
},
_createIcon: function(size) {
@@ -181,6 +253,7 @@ Dash.prototype = {
this._dragPlaceholder = null;
this._dragPlaceholderPos = -1;
+ this._animatingPlaceholdersCount = 0;
this._favRemoveTarget = null;
this._box = new St.BoxLayout({ name: 'dash',
@@ -234,9 +307,15 @@ Dash.prototype = {
_onDragEnd: function() {
this._clearDragPlaceholder();
if (this._favRemoveTarget) {
- this._favRemoveTarget.actor.destroy();
+ this._favRemoveTarget.actor.hide();
this._adjustIconSize();
- this._favRemoveTarget = null;
+ this._favRemoveTarget.actor.show();
+
+ this._favRemoveTarget.animateOutAndDestroy();
+ this._favRemoveTarget.actor.connect('destroy', Lang.bind(this,
+ function() {
+ this._favRemoveTarget = null;
+ }));
}
DND.removeMonitor(this._dragMonitor);
},
@@ -261,6 +340,7 @@ Dash.prototype = {
this._favRemoveTarget.icon.setIconSize(this._iconSize);
this._box.add(this._favRemoveTarget.actor);
this._adjustIconSize();
+ this._favRemoveTarget.animateIn();
}
let favRemoveHovered = false;
@@ -343,11 +423,29 @@ Dash.prototype = {
if (newIconSize == this._iconSize)
return;
+ let oldIconSize = this._iconSize;
this._iconSize = newIconSize;
+ let scale = oldIconSize / newIconSize;
for (let i = 0; i < iconChildren.length; i++) {
let icon = iconChildren[i]._delegate.child._delegate.icon;
+
+ // Set the new size immediately, to keep the icons' sizes
+ // in sync with this._iconSize
icon.setIconSize(this._iconSize);
+ let [targetWidth, targetHeight] = icon.icon.get_size();
+
+ // Scale the icon's texture to the previous size and
+ // tween to the new size
+ icon.icon.set_size(icon.icon.width * scale,
+ icon.icon.height * scale);
+
+ Tweener.addTween(icon.icon,
+ { width: targetWidth,
+ height: targetHeight,
+ time: DASH_ANIMATION_TIME,
+ transition: 'easeOutQuad'
+ });
}
},
@@ -452,15 +550,33 @@ Dash.prototype = {
this._box.insert_actor(addedItems[i].item.actor,
addedItems[i].pos);
+ // Hide removed actors to not take them into account
+ // when adjusting the icon size ...
for (let i = 0; i < removedActors.length; i++)
- removedActors[i].destroy();
+ removedActors[i].hide();
+
+ // ... and do the same for the remove target if necessary
+ if (this._favRemoveTarget && this._favRemoveTarget.hiding)
+ this._favRemoveTarget.actor.hide();
this._adjustIconSize();
+
+ if (this._favRemoveTarget && this._favRemoveTarget.hiding)
+ this._favRemoveTarget.actor.show();
+
+ for (let i = 0; i < removedActors.length; i++) {
+ removedActors[i].show();
+ let item = removedActors[i]._delegate;
+ item.animateOutAndDestroy();
+ }
+
+ for (let i = 0; i < addedItems.length; i++)
+ addedItems[i].item.animateIn();
},
_clearDragPlaceholder: function() {
if (this._dragPlaceholder) {
- this._dragPlaceholder.actor.destroy();
+ this._dragPlaceholder.animateOutAndDestroy();
this._dragPlaceholder = null;
this._dragPlaceholderPos = -1;
}
@@ -482,7 +598,8 @@ Dash.prototype = {
let favPos = favorites.indexOf(app);
- let numChildren = this._box.get_children().length;
+ let children = this._box.get_children();
+ let numChildren = children.length;
let boxHeight = this._box.height;
// Keep the placeholder out of the index calculation; assuming that
@@ -496,17 +613,49 @@ Dash.prototype = {
let pos = Math.round(y * numChildren / boxHeight);
if (pos != this._dragPlaceholderPos && pos <= numFavorites) {
- this._dragPlaceholderPos = pos;
- if (this._dragPlaceholder)
- this._dragPlaceholder.actor.destroy();
+ if (this._animatingPlaceholdersCount > 0) {
+ let appChildren = children.filter(function(actor) {
+ return actor._delegate &&
+ actor._delegate.child &&
+ actor._delegate.child._delegate &&
+ actor._delegate.child._delegate.app;
+ });
+ this._dragPlaceholderPos = children.indexOf(appChildren[pos]);
+ } else {
+ this._dragPlaceholderPos = pos;
+ }
// Don't allow positioning before or after self
- if (favPos != -1 && (pos == favPos || pos == favPos + 1))
+ if (favPos != -1 && (pos == favPos || pos == favPos + 1)) {
+ if (this._dragPlaceholder) {
+ this._dragPlaceholder.animateOutAndDestroy();
+ this._animatingPlaceholdersCount++;
+ this._dragPlaceholder.actor.connect('destroy',
+ Lang.bind(this, function() {
+ this._animatingPlaceholdersCount--;
+ }));
+ }
+ this._dragPlaceholder = null;
+
return DND.DragMotionResult.CONTINUE;
+ }
+
+ // If the placeholder already exists, we just move
+ // it, but if we are adding it, expand its size in
+ // an animation
+ let fadeIn;
+ if (this._dragPlaceholder) {
+ this._dragPlaceholder.actor.destroy();
+ fadeIn = false;
+ } else {
+ fadeIn = true;
+ }
this._dragPlaceholder = new DragPlaceholderItem();
this._box.insert_actor(this._dragPlaceholder.actor,
this._dragPlaceholderPos);
+ if (fadeIn)
+ this._dragPlaceholder.animateIn();
}
let srcIsFavorite = (favPos != -1);
@@ -540,6 +689,10 @@ Dash.prototype = {
let favPos = 0;
let children = this._box.get_children();
for (let i = 0; i < this._dragPlaceholderPos; i++) {
+ if (this._dragPlaceholder &&
+ children[i] == this._dragPlaceholder.actor)
+ continue;
+
let childId = children[i]._delegate.child._delegate.app.get_id();
if (childId == id)
continue;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]