[gnome-shell/wip/gdm-shell: 5/6] wip: batch: add mechanism for doing animation series



commit 6e92afc5a2a597102880c6219a8d4d5b35bdd341
Author: Ray Strode <rstrode redhat com>
Date:   Wed Jun 29 22:00:35 2011 -0400

    wip: batch: add mechanism for doing animation series
    
    In order for transformation animations to look good, they need to have
    some order to them (e.g., fade out hidden items, then shrink to close
    the void left over).
    
    You can sort of fake ordering by playing with timeout durations, but
    that's hardly ideal.
    
    This commit adds a new set of "Batch" classes for doing a series of
    tasks in order or concurrently.

 js/Makefile.am   |    1 +
 js/misc/batch.js |  197 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 198 insertions(+), 0 deletions(-)
---
diff --git a/js/Makefile.am b/js/Makefile.am
index 5cd0267..f3fad16 100644
--- a/js/Makefile.am
+++ b/js/Makefile.am
@@ -2,6 +2,7 @@
 jsdir = $(pkgdatadir)/js
 
 nobase_dist_js_DATA = 	\
+	misc/batch.js		\
 	misc/config.js		\
 	misc/docInfo.js		\
 	misc/fileUtils.js	\
diff --git a/js/misc/batch.js b/js/misc/batch.js
new file mode 100644
index 0000000..06a4b67
--- /dev/null
+++ b/js/misc/batch.js
@@ -0,0 +1,197 @@
+/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*-
+ *
+ * Copyright 2011 Red Hat, Inc
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+const Lang = imports.lang;
+const Signals = imports.signals;
+
+function Hold() {
+    this._init();
+}
+
+Hold.prototype = {
+    _init: function() {
+        this._acquisitions = 1;
+    },
+
+    acquire: function() {
+        this._acquisitions++;
+    },
+
+    release: function() {
+        this._acquisitions--;
+
+        if (this._acquisitions == 0) {
+            this.emit('release');
+        }
+    }
+}
+Signals.addSignalMethods(Hold.prototype);
+
+function Task(task) {
+    this._init(task);
+}
+
+Task.prototype = {
+    _init: function(handler) {
+        this._handler = handler;
+    },
+
+    run: function() {
+        if (this._handler)
+            return this._handler();
+    },
+};
+Signals.addSignalMethods(Task.prototype);
+
+function Batch(tasks) {
+    this._init(tasks);
+}
+
+Batch.prototype = {
+    __proto__: Task.prototype,
+    _init: function(tasks) {
+        Task.prototype._init.call(this, null);
+
+        this.tasks = [];
+
+        for (let i = 0; i < tasks.length; i++) {
+            let task;
+
+            if (tasks[i] instanceof Task) {
+                task = tasks[i];
+            } else if (typeof tasks[i] == 'function') {
+                task = new Task(tasks[i]);
+            } else {
+                throw new Error('Batch tasks must be functions or Task or Batch objects');
+            }
+
+            this.tasks.push(task);
+        }
+    },
+
+    process: function() {
+        throw new Error('Not implemented');
+    },
+
+    runTask: function() {
+        if (!(this._currentTaskIndex in this.tasks)) {
+            return;
+        }
+
+        return this.tasks[this._currentTaskIndex].run();
+    },
+
+    finish: function() {
+        this.hold.release();
+    },
+
+    nextTask: function() {
+        this._currentTaskIndex++;
+
+        // if the entire batch of tasks is finished, release
+        // the hold and notify anyone waiting on the batch
+        if (this._currentTaskIndex >= this.tasks.length) {
+            this.finish();
+            return;
+        }
+
+        this.process();
+    },
+
+    _start: function() {
+        // acquire a hold to get released when the entire
+        // batch of tasks is finished
+        this.hold = new Hold();
+        this._currentTaskIndex = 0;
+        this.process();
+    },
+
+    run: function() {
+        this._start();
+
+        // hold may be destroyed at this point
+        // if we're already done running
+        return this.hold;
+    }
+
+};
+Signals.addSignalMethods(Batch.prototype);
+
+function ConcurrentBatch(tasks) {
+    this._init(tasks);
+}
+
+ConcurrentBatch.prototype = {
+    __proto__: Batch.prototype,
+
+    _init: function(tasks) {
+        Batch.prototype._init.call(this, tasks);
+    },
+
+    process: function() {
+       let hold = this.runTask();
+
+       if (hold) {
+           this.hold.acquire();
+           hold.connect('release',
+                        Lang.bind(this, function() {
+                            this.hold.release();
+                            this.nextTask();
+                        }));
+       }
+
+       // Regardless of the state of the just run task,
+       // fire off the next one, so all the tasks can run
+       // concurrently.
+       this.nextTask();
+    }
+};
+Signals.addSignalMethods(ConcurrentBatch.prototype);
+
+function ConsecutiveBatch(tasks) {
+    this._init(tasks);
+}
+
+ConsecutiveBatch.prototype = {
+    __proto__: Batch.prototype,
+
+    _init: function(tasks) {
+        Batch.prototype._init.call(this, tasks);
+    },
+
+    process: function() {
+       let hold = this.runTask();
+
+       if (hold) {
+           // This task is inhibiting the batch. Wait on it
+           // before processing the next one.
+           hold.connect('release',
+                        Lang.bind(this, function() {
+                            this.nextTask();
+                        }));
+           return;
+       } else {
+           // This task finished, process the next one
+           this.nextTask();
+       }
+    }
+};
+Signals.addSignalMethods(ConsecutiveBatch.prototype);
+



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]