From 6a4511f03f46a3873c3ad65a8bb4608ba0ac8ab7 Mon Sep 17 00:00:00 2001 From: piro Date: Sat, 26 Dec 2009 20:02:30 +0000 Subject: [PATCH] =?UTF-8?q?=E3=82=BF=E3=83=96=E3=83=90=E3=83=BC=E3=81=AE?= =?UTF-8?q?=E4=BD=8D=E7=BD=AE=E5=A4=89=E6=9B=B4=E5=B1=A5=E6=AD=B4=E3=82=92?= =?UTF-8?q?=E8=87=AA=E5=89=8D=E3=81=A7=E4=BF=9D=E6=8C=81=E3=81=9B=E3=81=9A?= =?UTF-8?q?=E3=80=81=E3=83=A9=E3=82=A4=E3=83=96=E3=83=A9=E3=83=AA=E3=81=AB?= =?UTF-8?q?=E4=BB=BB=E3=81=9B=E3=82=8B=E3=82=88=E3=81=86=E3=81=AB=E3=81=97?= =?UTF-8?q?=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit git-svn-id: http://www.cozmixng.org/repos/piro/treestyletab/trunk@5674 599a83e7-65a4-db11-8015-0010dcdd6dc2 --- content/treestyletab/res/operationHistory.js | 267 ++++++++++++++++++ content/treestyletab/treestyletab.xul | 1 + ...treestyletabbrowser_tabpanelDNDObserver.js | 7 + modules/utils.js | 73 ----- 4 files changed, 275 insertions(+), 73 deletions(-) create mode 100644 content/treestyletab/res/operationHistory.js diff --git a/content/treestyletab/res/operationHistory.js b/content/treestyletab/res/operationHistory.js new file mode 100644 index 00000000..e7c17f91 --- /dev/null +++ b/content/treestyletab/res/operationHistory.js @@ -0,0 +1,267 @@ +/* + UI Operations Global Undo History Manager + + Usage: + // window specific events + window['piro.sakura.ne.jp'].operationHistory.addEntry( + 'MyAddonFeature', + { undo : function() { ... }, + redo : function() { ... } }, + window + ); + window['piro.sakura.ne.jp'].operationHistory.undo('MyAddonFeature', window); + window['piro.sakura.ne.jp'].operationHistory.redo('MyAddonFeature', window); + + // global events (not associated to window) + window['piro.sakura.ne.jp'].operationHistory.addEntry( + 'MyAddonFeature', + { ... } + ); + window['piro.sakura.ne.jp'].operationHistory.undo('MyAddonFeature'); + + // anonymous, window specifit + window['piro.sakura.ne.jp'].operationHistory.addEntry({ ... }, window); + window['piro.sakura.ne.jp'].operationHistory.undo(window); + + // anonymous, global + window['piro.sakura.ne.jp'].operationHistory.addEntry({ ... }); + window['piro.sakura.ne.jp'].operationHistory.undo(); + + lisence: The MIT License, Copyright (c) 2009 SHIMODA "Piro" Hiroshi + http://www.cozmixng.org/repos/piro/fx3-compatibility-lib/trunk/license.txt + original: + http://www.cozmixng.org/repos/piro/fx3-compatibility-lib/trunk/operationHistory.js +*/ +(function() { + const currentRevision = 1; + + if (!('piro.sakura.ne.jp' in window)) window['piro.sakura.ne.jp'] = {}; + + var loadedRevision = 'operationHistory' in window['piro.sakura.ne.jp'] ? + window['piro.sakura.ne.jp'].operationHistory.revision : + 0 ; + if (loadedRevision && loadedRevision > currentRevision) { + return; + } + + var tables = {}; + if (loadedRevision) { + tables = window['piro.sakura.ne.jp'].operationHistory._tables; + window['piro.sakura.ne.jp'].destroy(); + } + + var Cc = Components.classes; + var Ci = Components.interfaces; + + window['piro.sakura.ne.jp'].operationHistory = { + revision : currentRevision, + + kMAX_ENTRIES : 999, + kWINDOW_ID : 'UIOperationGlobalHistoryWindowID', + + _doingUndo : false, + _tables : tables, + + initialized : false, + + init : function() + { + var targets = this.WindowMediator.getZOrderDOMWindowEnumerator('navigator:browser', true); + while (targets.hasMoreElements()) + { + let target = targets.getNext().QueryInterface(Ci.nsIDOMWindowInternal); + if ( + 'piro.sakura.ne.jp' in target && + 'operationHistory' in target['piro.sakura.ne.jp'] && + target['piro.sakura.ne.jp'].operationHistory.initialized + ) { + this._tables = target['piro.sakura.ne.jp'].operationHistory._tables; + break; + } + } + + window.addEventListener('unload', this, false); + + this.initialized = true; + }, + + destroy : function() + { + window.removeEventListener('unload', this, false); + }, + + addEntry : function() + { + if (this._doingUndo) + return; + + var options = this._getOptionsFromArguments(arguments); + + var history = options.history; + var entries = history.entries; + + entries = entries.slice(0, history.index+1); + entries.push(options.data); + entries = entries.slice(-this.kMAX_ENTRIES); + + history.entries = entries; + history.index = entries.length-1; + }, + + undo : function() + { + var options = this._getOptionsFromArguments(arguments); + var history = options.history; + if (history.index < 0) + return false; + + var error; + + this._doingUndo = true; + var data = history.entries[history.index--]; + try { + data.undo(); + } + catch(e) { + error = e; + } + this._dispatchEvent(options); + this._doingUndo = false; + + if (error) throw error; + return true; + }, + + redo : function() + { + var options = this._getOptionsFromArguments(arguments); + var history = options.history; + if (history.index > history.entries.length-1) + return false; + + var error; + + this._doingUndo = true; + var data = history.entries[history.index++]; + try { + data.redo(); + } + catch(e) { + error = e; + } + this._dispatchEvent(options); + this._doingUndo = false; + + if (error) throw error; + return true; + }, + + _dispatchEvent : function(aOptions) + { + var d = aOptions.window ? aOptions.window.document : document ; + var event = d.createEvent('Events'); + event.initEvent('UIOperationGlobalHistoryUndo', true, false); + event.name = aOptions.name; + d.dispatchEvent(event); + }, + + _getOptionsFromArguments : function(aArguments) + { + var w, name, data; + Array.slice(aArguments).some(function(aArg) { + if (aArg instanceof Ci.nsIDOMWindow) + w = aArg; + else if (typeof aArg == 'string') + name = aArg; + else if (aArg) + data = aArg; + + return (w && name && data); + }); + + if (!name) + name = w ? 'window' : 'global' ; + + var windowId = this.SessionStore.getWindowValue(window, this.kWINDOW_ID); + if (!windowId) { + windowId = 'window-'+Date.now()+parseInt(Math.random() * 65000); + this.SessionStore.setWindowValue(window, this.kWINDOW_ID, windowId); + } + + var tableName = w ? encodeURIComponent(name)+'::'+windowId : encodeURIComponent(name) ; + if (!(tableName in this._tables)) { + this._tables[tableName] = { + entries : [], + index : -1, + windowId : windowId + }; + } + + return { + name : name, + window : w, + windowId : windowId, + data : data, + history : this._tables[tableName] + }; + }, + + _getWindowById : function(aId) + { + var targets = this.WindowMediator.getZOrderDOMWindowEnumerator('navigator:browser', true); + while (targets.hasMoreElements()) + { + let target = targets.getNext().QueryInterface(Ci.nsIDOMWindowInternal); + if (aId == this.SessionStore.getWindowValue(target, this.kWINDOW_ID)) + return target; + } + return null; + }, + + _deleteWindowTables : function() + { + var id = this.SessionStore.getWindowValue(window, this.kWINDOW_ID); + if (!id) return; + + var removedTables = []; + for (let i in this._tables) + { + if (id == this._tables[i].windowId) + removedTables.push(i); + } + removedTables.forEach(function(aName) { + delete this._tables[aName]; + }, this); + }, + + get WindowMediator() { + if (!this._WindowMediator) { + this._WindowMediator = Cc['@mozilla.org/appshell/window-mediator;1'].getService(Ci.nsIWindowMediator); + } + return this._WindowMediator; + }, + _WindowMediator : null, + + get SessionStore() { + if (!this._SessionStore) { + this._SessionStore = Cc['@mozilla.org/browser/sessionstore;1'].getService(Ci.nsISessionStore); + } + return this._SessionStore; + }, + _SessionStore : null, + + handleEvent : function(aEvent) + { + switch (aEvent.type) + { + case 'unload': + this._deleteWindowTables(); + this.destroy(); + return; + } + } + + }; + + window['piro.sakura.ne.jp'].operationHistory.init(); +})(); diff --git a/content/treestyletab/treestyletab.xul b/content/treestyletab/treestyletab.xul index dc8b666b..00e22739 100644 --- a/content/treestyletab/treestyletab.xul +++ b/content/treestyletab/treestyletab.xul @@ -12,6 +12,7 @@