From 7e03fef9298ea8ee26ac80770a8847e926bf4669 Mon Sep 17 00:00:00 2001 From: Piro / YUKI Hiroshi Date: Sat, 2 Mar 2013 22:12:28 +0900 Subject: [PATCH] Observe changes of UI shown/hidden not only the browser bottom box but also the toolbox (for #470) --- modules/browserUIShowHideObserver.js | 118 +++++++++++++++++++++++++++ modules/window.js | 85 +++++-------------- 2 files changed, 140 insertions(+), 63 deletions(-) create mode 100644 modules/browserUIShowHideObserver.js diff --git a/modules/browserUIShowHideObserver.js b/modules/browserUIShowHideObserver.js new file mode 100644 index 00000000..1d90d923 --- /dev/null +++ b/modules/browserUIShowHideObserver.js @@ -0,0 +1,118 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is the Tree Style Tab. + * + * The Initial Developer of the Original Code is YUKI "Piro" Hiroshi. + * Portions created by the Initial Developer are Copyright (C) 2013 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): YUKI "Piro" Hiroshi + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ******/ + +const EXPORTED_SYMBOLS = ['BrowserUIShowHideObserver']; + +function BrowserUIShowHideObserver(aOwner, aBox) { + this.owner = aOwner; + this.box = aBox; + this.init(); +} +BrowserUIShowHideObserver.prototype = { + get MutationObserver() + { + var w = this.box.ownerDocument.defaultView; + return w.MutationObserver || w.MozMutationObserver; + }, + + init : function BrowserUIShowHideObserver_onInit() + { + if (!this.MutationObserver) + return; + this.observer = new this.MutationObserver(function(aMutations, aObserver) { + self.onChildListModified(aMutations, aObserver); + }); + this.observer.observe(this.box, { childList : true }); + this.initChildrenObserver(); + }, + onChildListModified : function BrowserUIShowHideObserver_onChildListModified(aMutations, aObserver) + { + aMutations.forEach(function(aMutation) { + if (aMutation.type != 'childList') + return; + this.destroyChildrenObserver(); + this.initChildrenObserver(); + }, this); + }, + + destroy : function BrowserUIShowHideObserver_destroy() + { + if (this.observer) { + this.destroyChildrenObserver(); + this.observer.disconnect(); + delete this.observer; + } + delete this.box; + delete this.owner; + }, + + initChildrenObserver : function BrowserUIShowHideObserver_initChildrenObserver(aParent) + { + Array.forEach(this.box.childNodes, function(aChild) { + var observer = aChild.__treestyletab__attributeObserver; + if (observer) + return; + + var self = this; + observer = new this.MutationObserver(function(aMutations, aObserver) { + self.onAttributeModified(aMutations, aObserver); + }); + observer.observe(aChild, { attributes : true }); + aChild.__treestyletab__attributeObserver = observer; + }, this) + }, + onAttributeModified : function BrowserUIShowHideObserver_onAttributeModified(aMutations, aObserver) + { + aMutations.forEach(function(aMutation) { + if (aMutation.type != 'attributes') + return; + if (aMutation.attributeName == 'hidden' || + aMutation.attributeName == 'collapsed') + this.owner.browser.treeStyleTab.updateFloatingTabbar(this.owner.kTABBAR_UPDATE_BY_WINDOW_RESIZE); + }, this); + }, + + destroyChildrenObserver : function BrowserUIShowHideObserver_destroyChildrenObserver(aParent) + { + Array.forEach(this.box.childNodes, function(aChild) { + var observer = aChild.__treestyletab__attributeObserver; + if (!observer) + return; + + observer.disconnect(); + delete aChild.__treestyletab__attributeObserver; + }, this) + } +}; diff --git a/modules/window.js b/modules/window.js index 41594df8..cf3fc5f1 100644 --- a/modules/window.js +++ b/modules/window.js @@ -60,7 +60,7 @@ XPCOMUtils.defineLazyModuleGetter(this, 'TreeStyleTabBrowser', 'resource://trees XPCOMUtils.defineLazyModuleGetter(this, 'utils', 'resource://treestyletab-modules/utils.js', 'TreeStyleTabUtils'); XPCOMUtils.defineLazyModuleGetter(this, 'AutoHideWindow', 'resource://treestyletab-modules/autoHide.js'); XPCOMUtils.defineLazyModuleGetter(this, 'TreeStyleTabThemeManager', 'resource://treestyletab-modules/themeManager.js'); - +XPCOMUtils.defineLazyModuleGetter(this, 'BrowserUIShowHideObserver', 'resource://treestyletab-modules/browserUIShowHideObserver.js'); function TreeStyleTabWindow(aWindow) { @@ -85,10 +85,6 @@ TreeStyleTabWindow.prototype = { window : null, document : null, - get MutationObserver() - { - return this.window.MutationObserver || this.window.MozMutationObserver; - }, /* API */ @@ -164,6 +160,12 @@ TreeStyleTabWindow.prototype = { w.gBrowser ; }, + get browserToolbox() + { + var w = this.window; + return w.gToolbox || w.gNavToolbox; + }, + get browserBottomBox() { return this.document.getElementById('browser-bottombox'); @@ -219,8 +221,7 @@ TreeStyleTabWindow.prototype = { get isToolbarCustomizing() { - var w = this.window; - var toolbox = w.gToolbox || w.gNavToolbox; + var toolbox = this.browserToolbox; return toolbox && toolbox.customizing; }, @@ -359,8 +360,7 @@ TreeStyleTabWindow.prototype = { d.addEventListener(this.kEVENT_TYPE_TABBAR_STATE_CHANGED, this, false); d.addEventListener(this.kEVENT_TYPE_FOCUS_NEXT_TAB, this, false); - if (this.MutationObserver) - this.initBrowserBottomBoxObserver(); + this.initUIShowHideObserver(); var appcontent = d.getElementById('appcontent'); appcontent.addEventListener('SubBrowserAdded', this, false); @@ -458,29 +458,15 @@ TreeStyleTabWindow.prototype = { } }, - initBrowserBottomBoxObserver : function TSTWindow_initBrowserBottomBoxObserver() + initUIShowHideObserver : function TSTWindow_initUIShowHideObserver() { - var self = this; - this.browserBottomBoxObserver = new this.MutationObserver(function(aMutations, aObserver) { - self.handleMutations(aMutations, aObserver); - }); - this.browserBottomBoxObserver.observe(this.browserBottomBox, { childList : true }); - this.initBrowserBottomBoxChildListeners(); - }, - - initBrowserBottomBoxChildListeners : function TSTWindow_initBrowserBottomBoxChildListeners() - { - Array.forEach(this.browserBottomBox.childNodes, function(aChild) { - var observer = aChild.__treestyletab__attributeObserver; - if (!observer) { - var self = this; - observer = new this.MutationObserver(function(aMutations, aObserver) { - self.handleMutations(aMutations, aObserver); - }); - observer.observe(aChild, { attributes : true }); - aChild.__treestyletab__attributeObserver = observer; - } - }, this) + var toolbox = this.browserToolbox; + if (toolbox) + this.browserToolboxObserver = new BrowserUIShowHideObserver(this, toolbox); + + var bottomBox = this.browserBottomBox; + if (bottomBox) + this.browserBottomBoxObserver = new BrowserUIShowHideObserver(this, bottomBox); }, destroy : function TSTWindow_destroy() @@ -511,9 +497,12 @@ TreeStyleTabWindow.prototype = { d.removeEventListener(this.kEVENT_TYPE_TABBAR_STATE_CHANGED, this, false); d.removeEventListener(this.kEVENT_TYPE_FOCUS_NEXT_TAB, this, false); + if (this.browserToolboxObserver) { + this.browserToolboxObserver.destroy(); + delete this.browserToolboxObserver; + } if (this.browserBottomBoxObserver) { - this.destroyBrowserBottomBoxChildListeners(); - this.browserBottomBoxObserver.disconnect(); + this.browserBottomBoxObserver.destroy(); delete this.browserBottomBoxObserver; } @@ -550,17 +539,6 @@ TreeStyleTabWindow.prototype = { aTabBrowser.treeStyleTab.destroy(); delete aTabBrowser.treeStyleTab; }, - - destroyBrowserBottomBoxChildListeners : function TSTWindow_destroyBrowserBottomBoxChildListeners() - { - Array.forEach(this.browserBottomBox.childNodes, function(aChild) { - var observer = aChild.__treestyletab__attributeObserver; - if (observer) { - observer.disconnect(); - delete aChild.__treestyletab__attributeObserver; - } - }, this) - }, /* Event Handling */ @@ -1225,25 +1203,6 @@ TreeStyleTabWindow.prototype = { } this._restoringTabs = []; }, - - handleMutations : function TSTWindow_handleMutations(aMutations, aObserver) - { - aMutations.forEach(function(aMutation) { - switch (aMutation.type) - { - case 'childList': - this.destroyBrowserBottomBoxChildListeners(); - this.initBrowserBottomBoxChildListeners(); - break; - - case 'attributes': - if (aMutation.attributeName == 'hidden' || - aMutation.attributeName == 'collapsed') - this.browser.treeStyleTab.updateFloatingTabbar(this.kTABBAR_UPDATE_BY_WINDOW_RESIZE); - break; - } - }, this); - }, /* Commands */