[gnome-shell/wip/swarm: 1/7] appDisplay: Animate folder view items
- From: Carlos Soriano <csoriano src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-shell/wip/swarm: 1/7] appDisplay: Animate folder view items
- Date: Fri, 22 Aug 2014 14:24:34 +0000 (UTC)
commit 758d773bff33ba2ef1494abe821359be82695579
Author: Carlos Soriano <carlos soriano89 gmail com>
Date: Tue Jun 17 12:47:00 2014 +0200
appDisplay: Animate folder view items
Add a new animation to folder view based on designers mockups that
emulates pulsating icons.
The code on iconGrid is though to work well for the upcoming patches to
animate AllView and FrequentView.
https://bugzilla.gnome.org/show_bug.cgi?id=734726
js/ui/appDisplay.js | 21 +++++++++-
js/ui/iconGrid.js | 102 +++++++++++++++++++++++++++++++++++++++++++++++---
2 files changed, 114 insertions(+), 9 deletions(-)
---
diff --git a/js/ui/appDisplay.js b/js/ui/appDisplay.js
index 0bf435e..e1edf43 100644
--- a/js/ui/appDisplay.js
+++ b/js/ui/appDisplay.js
@@ -964,6 +964,10 @@ const FolderView = new Lang.Class({
Util.ensureActorVisibleInScrollView(this.actor, actor);
},
+ animate: function(animationType, animationDirection) {
+ this._grid.animate(animationType, animationDirection);
+ },
+
createFolderIcon: function(size) {
let layout = new Clutter.GridLayout();
let icon = new St.Widget({ layout_manager: layout,
@@ -1339,8 +1343,20 @@ const AppFolderPopup = new Lang.Class({
this.actor.show();
this._boxPointer.setArrowActor(this._source.actor);
+ // We need to hide the icons of the view until the boxpointer animation
+ // is completed so we can animate the icons after as we like withouth
+ // showing them while boxpointer is animating.
+ this._view.actor.opacity = 0;
this._boxPointer.show(BoxPointer.PopupAnimation.FADE |
- BoxPointer.PopupAnimation.SLIDE);
+ BoxPointer.PopupAnimation.SLIDE,
+ Lang.bind(this,
+ function() {
+ // Restore the view opacity, so now we show the icons and animate
+ // them
+ this._view.actor.opacity = 255;
+ this._view.animate(IconGrid.AnimationType.PULSE,
+ IconGrid.AnimationDirection.IN);
+ }));
this.emit('open-state-changed', true);
},
@@ -1352,7 +1368,8 @@ const AppFolderPopup = new Lang.Class({
this._grabHelper.ungrab({ actor: this.actor });
this._boxPointer.hide(BoxPointer.PopupAnimation.FADE |
- BoxPointer.PopupAnimation.SLIDE);
+ BoxPointer.PopupAnimation.SLIDE,
+ this._view.animateOut);
this._isOpen = false;
this.emit('open-state-changed', false);
},
diff --git a/js/ui/iconGrid.js b/js/ui/iconGrid.js
index 4c555ac..a5bf413 100644
--- a/js/ui/iconGrid.js
+++ b/js/ui/iconGrid.js
@@ -10,12 +10,26 @@ const St = imports.gi.St;
const Lang = imports.lang;
const Params = imports.misc.params;
const Tweener = imports.ui.tweener;
+const Main = imports.ui.main;
const ICON_SIZE = 96;
const MIN_ICON_SIZE = 16;
const EXTRA_SPACE_ANIMATION_TIME = 0.25;
+const ANIMATION_TIME_IN = 0.350;
+const ANIMATION_MAX_DELAY_FOR_ITEM = 2/3 * ANIMATION_TIME_IN;
+
+const ANIMATION_BOUNCE_ICON_SCALE = 1.1;
+
+const AnimationType = {
+ PULSE: 0
+};
+
+const AnimationDirection = {
+ IN: 0
+};
+
const BaseIcon = new Lang.Class({
Name: 'BaseIcon',
@@ -338,15 +352,89 @@ const IconGrid = new Lang.Class({
}
},
- _calculateChildBox: function(child, x, y, box) {
- let [childMinWidth, childMinHeight, childNaturalWidth, childNaturalHeight] =
- child.get_preferred_size();
+ /**
+ * Intended to be override by subclasses if they need a diferent
+ * set of items to be animated.
+ */
+ _getChildrenToAnimate: function() {
+ return this._getVisibleChildren();
+ },
+
+ animate: function(animationType, animationDirection) {
+ let actors = this._getChildrenToAnimate();
+ if (this._animating || actors.length == 0)
+ return;
+ this._animating = true;
+
+ for (let index = 0; index < actors.length; index++)
+ actors[index].opacity = 0;
+ switch (animationType) {
+ case AnimationType.PULSE:
+ this._animatePulse(actors, animationDirection);
+ break;
+ default:
+ log("animation doesn't exist. Icongrid won\'t work");
+ }
+ },
+
+ _animatePulse: function(actors, animationDirection) {
+ for (let index = 0; index < actors.length; index++) {
+ let delay = index / actors.length * ANIMATION_MAX_DELAY_FOR_ITEM;
+ let [originalX, originalY] = actors[index].get_transformed_position();
+ let [originalWidth, originalHeight,,] = this._getAllocatedChildSizeAndSpacing(actors[index]);
+
+ let actorClone = new Clutter.Clone({ source: actors[index],
+ reactive: false });
+ Main.uiGroup.add_actor(actorClone);
+
+ actorClone.set_position(originalX, originalY);
+ actorClone.set_scale(0, 0);
+ actorClone.set_pivot_point(0.5, 0.5);
+ actorClone.set_size(originalWidth, originalHeight);
+
+ // Defeat onComplete anonymous function closure
+ let actor= actors[index];
+ let isLastItem= index == actors.length - 1;
+ Tweener.addTween(actorClone,
+ { time: ANIMATION_TIME_IN / 4,
+ transition: 'easeInOutQuad',
+ delay: delay,
+ scale_x: ANIMATION_BOUNCE_ICON_SCALE,
+ scale_y: ANIMATION_BOUNCE_ICON_SCALE,
+ onComplete: Lang.bind(this, function() {
+ Tweener.addTween(actorClone,
+ { time: ANIMATION_TIME_IN - ANIMATION_TIME_IN / 4,
+ transition: 'easeInOutQuad',
+ scale_x: 1,
+ scale_y: 1,
+ onComplete: Lang.bind(this, function() {
+ if (isLastItem) {
+ this._animating = false;
+ this.emit('animation-done');
+ }
+ actor.opacity = 255;
+ actorClone.destroy();
+ })
+ });
+ })
+ });
+ }
+ },
+
+ _getAllocatedChildSizeAndSpacing: function(child) {
+ let [,, natWidth, natHeight] = child.get_preferred_size();
+ let width = Math.min(this._getHItemSize(), natWidth);
+ let xSpacing = Math.max(0, width - natWidth) / 2;
+ let height = Math.min(this._getVItemSize(), natHeight);
+ let ySpacing = Math.max(0, height - natHeight) / 2;
+ return [width, height, xSpacing, ySpacing];
+ },
+
+ _calculateChildBox: function(child, x, y, box) {
/* Center the item in its allocation horizontally */
- let width = Math.min(this._getHItemSize(), childNaturalWidth);
- let childXSpacing = Math.max(0, width - childNaturalWidth) / 2;
- let height = Math.min(this._getVItemSize(), childNaturalHeight);
- let childYSpacing = Math.max(0, height - childNaturalHeight) / 2;
+ let [width, height, childXSpacing, childYSpacing] =
+ this._getAllocatedChildSizeAndSpacing(child);
let childBox = new Clutter.ActorBox();
if (Clutter.get_default_text_direction() == Clutter.TextDirection.RTL) {
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]