[gnome-shell/swarm] Prototyping swarm animation
- From: Carlos Soriano <csoriano src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-shell/swarm] Prototyping swarm animation
- Date: Sun, 16 Mar 2014 22:32:47 +0000 (UTC)
commit 6caf09982a2ee1b21b162b25e4090a7df2fe0073
Author: Carlos Soriano <carlos soriano89 gmail com>
Date: Sun Mar 16 23:21:28 2014 +0100
Prototyping swarm animation
js/ui/appDisplay.js | 40 +++++++++++++
js/ui/iconGrid.js | 157 +++++++++++++++++++++++++++++++++++++++++++++----
js/ui/viewSelector.js | 3 +
3 files changed, 189 insertions(+), 11 deletions(-)
---
diff --git a/js/ui/appDisplay.js b/js/ui/appDisplay.js
index 2d8fc38..a1aeda8 100644
--- a/js/ui/appDisplay.js
+++ b/js/ui/appDisplay.js
@@ -612,6 +612,10 @@ const AllView = new Lang.Class({
// Update folder views
for (let i = 0; i < this.folderIcons.length; i++)
this.folderIcons[i].adaptToSize(availWidth, availHeight);
+ },
+
+ swarmAnimation: function() {
+ //this._grid.swarmAnimation(0);
}
});
Signals.addSignalMethods(AllView.prototype);
@@ -677,6 +681,10 @@ const FrequentView = new Lang.Class({
let availWidth = box.x2 - box.x1;
let availHeight = box.y2 - box.y1;
this._grid.adaptToSize(availWidth, availHeight);
+ },
+
+ swarmAnimation: function() {
+ //this._grid.swarmAnimation();
}
});
@@ -782,6 +790,28 @@ const AppDisplay = new Lang.Class({
initialView = Views.ALL;
this._showView(initialView);
this._updateFrequentVisibility();
+
+ // ViewSelector null in Main.overview, so we can't connect to page-changed
+ // signal. Manage all from view selector for now calling swamAnimation
+ /*
+ log(Main);
+ log(Main.overview);
+ log(Main.overview.viewSelector);
+ Main.overview.viewSelector.connect('page-changed', Lang.bind(this,
+ function() {
+ if (Main.overview.viewSelector.getActivePage() == ViewSelector.ViewPage.APPS) {
+ this._views[global.settings.get_uint('app-picker-view')].swarmAnimation();
+ }
+ }));
+ */
+ },
+
+ swarmAnimation: function() {
+ log("appDisplay");
+ log(this._views);
+ let view = this._views[global.settings.get_uint('app-picker-view')].view;
+ log(view);
+ view.swarmAnimation();
},
_showView: function(activeIndex) {
@@ -1019,6 +1049,7 @@ const FolderIcon = new Lang.Class({
_init: function(id, path, parentView) {
this.id = id;
+ this._path = path;
this._parentView = parentView;
this._folder = new Gio.Settings({ schema_id: 'org.gnome.desktop.app-folders.folder',
@@ -1184,6 +1215,10 @@ const FolderIcon = new Lang.Class({
this.view.adaptToSize(width, height);
this._popupInvalidated = true;
},
+
+ clone: function() {
+ return new FolderIcon(this.id, this._path, this._parentView);
+ }
});
Signals.addSignalMethods(FolderIcon.prototype);
@@ -1320,6 +1355,7 @@ const AppIcon = new Lang.Class({
iconParams['createIcon'] = Lang.bind(this, this._createIcon);
iconParams['setSizeManually'] = true;
+ this._iconParams = iconParams;
this.icon = new IconGrid.BaseIcon(app.get_name(), iconParams);
this.actor.set_child(this.icon.actor);
@@ -1494,6 +1530,10 @@ const AppIcon = new Lang.Class({
shouldShowTooltip: function() {
return this.actor.hover && (!this._menu || !this._menu.isOpen);
},
+
+ clone: function() {
+ return new AppIcon(this.app, this._iconParams);
+ }
});
Signals.addSignalMethods(AppIcon.prototype);
diff --git a/js/ui/iconGrid.js b/js/ui/iconGrid.js
index 51fba64..ad605b6 100644
--- a/js/ui/iconGrid.js
+++ b/js/ui/iconGrid.js
@@ -10,12 +10,17 @@ 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 SWARM_ANIMATION_TIME = 0.7;
+const SWARM_ANIMATION_MAX_DELAY_FOR_ITEM = 0.3;
+const SWARM_ANIMATION_FADE_IN_TIME_FOR_ITEM = 0.3;
+
const BaseIcon = new Lang.Class({
Name: 'BaseIcon',
@@ -23,7 +28,9 @@ const BaseIcon = new Lang.Class({
params = Params.parse(params, { createIcon: null,
setSizeManually: false,
showLabel: true });
-
+ this.labelForClone = label;
+ this.paramsForClone = params;
+
let styleClass = 'overview-icon';
if (params.showLabel)
styleClass += ' overview-icon-with-label';
@@ -214,6 +221,14 @@ const IconGrid = new Lang.Class({
this._grid.connect('get-preferred-width', Lang.bind(this, this._getPreferredWidth));
this._grid.connect('get-preferred-height', Lang.bind(this, this._getPreferredHeight));
this._grid.connect('allocate', Lang.bind(this, this._allocate));
+
+ this._paintedItems = [];
+ this._animating = false;
+ this._mappedId = this.actor.connect("notify::allocation", Lang.bind(this,
+ function() {
+ if (this.actor.mapped)
+ this.swarmAnimation();
+ }));
},
_getPreferredWidth: function (grid, forHeight, alloc) {
@@ -242,6 +257,17 @@ const IconGrid = new Lang.Class({
return children;
},
+ _getVisibleItems: function() {;
+ items = this._items.filter(function(item) {
+ return item.actor.visible;
+ });
+ return items;
+ },
+
+ _getPaintedItems: function() {;
+ return this._paintedItems;
+ },
+
_getPreferredHeight: function (grid, forWidth, alloc) {
if (this._fillParent)
// Ignore all size requests of children and request a size of 0;
@@ -276,7 +302,7 @@ const IconGrid = new Lang.Class({
box = this._grid.get_theme_node().get_content_box(gridBox);
}
- let children = this._getVisibleChildren();
+ let items = this._getVisibleItems();
let availWidth = box.x2 - box.x1;
let availHeight = box.y2 - box.y1;
let spacing = this._getSpacing();
@@ -298,15 +324,18 @@ const IconGrid = new Lang.Class({
let y = box.y1 + this.topPadding;
let columnIndex = 0;
let rowIndex = 0;
- for (let i = 0; i < children.length; i++) {
- let childBox = this._calculateChildBox(children[i], x, y, box);
+ this._paintedItems = [];
+ log("allocating opacity 0");
+ for (let i = 0; i < items.length; i++) {
+ let childBox = this._calculateChildBox(items[i].actor, x, y, box);
if (this._rowLimit && rowIndex >= this._rowLimit ||
this._fillParent && childBox.y2 > availHeight - this.bottomPadding) {
- this._grid.set_skip_paint(children[i], true);
+ this._grid.set_skip_paint(items[i].actor, true);
} else {
- children[i].allocate(childBox, flags);
- this._grid.set_skip_paint(children[i], false);
+ items[i].actor.allocate(childBox, flags);
+ this._grid.set_skip_paint(items[i].actor, false);
+ this._paintedItems.push(items[i]);
}
columnIndex++;
@@ -324,6 +353,58 @@ const IconGrid = new Lang.Class({
}
},
+ swarmAnimation: function() {
+ if (this._animating)
+ return;
+
+ this._animating = true;
+ let items = this._paintedItems;
+ log("animating" + items);
+
+ for (let index = 0; index < items.length; index++) {
+ items[index].actor.opacity = 0;
+ this._animateItem(items[index], this);
+ }
+ },
+
+ _animateItem: function(item) {
+ let itemClone = item.clone();
+ itemClone.actor.reactive = false;
+ let [width, height] = item.actor.get_transformed_size();
+ itemClone.actor.set_size(width, height);
+
+ let [finalX, finalY] = item.actor.get_transformed_position();
+
+ let dashShowAppsIcon = Main.overview._dash._showAppsIcon;
+ let [startX, startY] = dashShowAppsIcon.get_transformed_position();
+ itemClone.actor.set_position(startX, startY);
+ itemClone.actor.opacity = 0;
+ Tweener.addTween(itemClone.actor,
+ { x: finalX,
+ y: finalY,
+ time: SWARM_ANIMATION_TIME,
+ transition: 'easeInOutQuad',
+ delay: Math.random() * SWARM_ANIMATION_MAX_DELAY_FOR_ITEM,
+ onStart: function() {
+ Tweener.addTween(itemClone.actor,
+ { opacity : 255,
+ transition: 'easeInOutQuad',
+ time: SWARM_ANIMATION_FADE_IN_TIME_FOR_ITEM });
+ },
+ onComplete: Lang.bind(this, function() {
+ log("opacity 255");
+ item.actor.opacity = 255;
+ itemClone.actor.destroy();
+ // Assume the random value of delay is not important,
+ // and setting animating to true in the first finished
+ // animation is fine.
+ this._animating = false;
+ })
+ });
+
+ Main.uiGroup.add_actor(itemClone.actor);
+ },
+
_calculateChildBox: function(child, x, y, box) {
let [childMinWidth, childMinHeight, childNaturalWidth, childNaturalHeight] =
child.get_preferred_size();
@@ -538,6 +619,13 @@ const PaginatedIconGrid = new Lang.Class({
this._rowsPerPage = 0;
this._spaceBetweenPages = 0;
this._childrenPerPage = 0;
+
+ this._mappedId = 0;
+ this._mappedId = this.actor.connect("notify::allocation", Lang.bind(this,
+ function() {
+ if (this.actor.mapped)
+ this.swarmAnimation(0);
+ }));
},
_getPreferredHeight: function (grid, forWidth, alloc) {
@@ -578,10 +666,16 @@ const PaginatedIconGrid = new Lang.Class({
let columnIndex = 0;
let rowIndex = 0;
- for (let i = 0; i < children.length; i++) {
- let childBox = this._calculateChildBox(children[i], x, y, box);
- children[i].allocate(childBox, flags);
- this._grid.set_skip_paint(children[i], false);
+/*
+ let dimmedItems = this._getItemsInPage(0);
+ for (let index = 0; index < dimmedItems.length; index++)
+ dimmedItems[index].actor.opacity = 0;*/
+
+ let visibleItems = this._getVisibleItems();
+ for (let i = 0; i < visibleItems.length; i++) {
+ let childBox = this._calculateChildBox(visibleItems[i].actor, x, y, box);
+ visibleItems[i].actor.allocate(childBox, flags);
+ this._grid.set_skip_paint(visibleItems[i].actor, false);
columnIndex++;
if (columnIndex == nColumns) {
@@ -598,6 +692,33 @@ const PaginatedIconGrid = new Lang.Class({
}
},
+ swarmAnimation: function(page) {
+ log("animating " + this._animating);
+ if (this._animating)
+ return;
+ log("paginated swarm");
+ /*this.actor.disconnect(this._mappedId);
+ this._mappedId = 0;
+
+ log("animating" + items);
+ if (items.length == 0) {
+ this._mappedId = this.actor.connect("notify::allocation", Lang.bind(this,
+ function() {
+ if (this.actor.mapped)
+ this.swarmAnimation(0);
+ }));
+ }*/
+ let items = this._getItemsInPage(page);
+ // TODO: Fix this
+ if (items.length == 0)
+ return;
+ this._animating = true;
+ for (let index = 0; index < items.length; index++) {
+ items[index].actor.opacity = 0;
+ this._animateItem(items[index]);
+ }
+ },
+
_computePages: function (availWidthPerPage, availHeightPerPage) {
let [nColumns, usedWidth] = this._computeLayout(availWidthPerPage);
let nRows;
@@ -649,6 +770,20 @@ const PaginatedIconGrid = new Lang.Class({
return Math.floor(index / this._childrenPerPage);
},
+ _getItemsInPage: function(pageNumber) {
+ let items = this._getVisibleItems();
+ let firstIndex = this._childrenPerPage * pageNumber;
+ let indexOffset = 0;
+ let itemsInPage = []
+
+ while (indexOffset < this._childrenPerPage && firstIndex + indexOffset < items.length) {
+ itemsInPage.push(items[firstIndex + indexOffset]);
+ indexOffset++;
+ }
+
+ return itemsInPage;
+ },
+
/**
* openExtraSpace:
* @sourceItem: the item for which to create extra space
diff --git a/js/ui/viewSelector.js b/js/ui/viewSelector.js
index 79fcde6..6632dd2 100644
--- a/js/ui/viewSelector.js
+++ b/js/ui/viewSelector.js
@@ -240,6 +240,9 @@ const ViewSelector = new Lang.Class({
});
else
this._fadePageIn(oldPage);
+
+ if (this._activePage == this._appsPage)
+ this.appDisplay.swarmAnimation();
},
_a11yFocusPage: function(page) {
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]