From 81e9155879a7d0eb614b7ab3a44b80787c2c45df Mon Sep 17 00:00:00 2001 From: piro Date: Sat, 20 Oct 2007 16:47:08 +0000 Subject: [PATCH] =?UTF-8?q?=E3=81=AA=E3=82=81=E3=82=89=E3=81=8B=E3=82=B9?= =?UTF-8?q?=E3=82=AF=E3=83=AD=E3=83=BC=E3=83=AB=E3=82=92=E5=AE=9F=E8=A3=85?= 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@1251 599a83e7-65a4-db11-8015-0010dcdd6dc2 --- content/treestyletab/treestyletab.css | 11 +- content/treestyletab/treestyletab.js | 179 +++++++++++++++++++++++++- defaults/preferences/treestyletab.js | 2 + 3 files changed, 188 insertions(+), 4 deletions(-) diff --git a/content/treestyletab/treestyletab.css b/content/treestyletab/treestyletab.css index 3e760cf1..316fc025 100644 --- a/content/treestyletab/treestyletab.css +++ b/content/treestyletab/treestyletab.css @@ -33,11 +33,20 @@ tabbrowser[treestyletab-vertical="true"] > tabbox { -moz-box-orient: horizontal !important; } -tabbrowser[treestyletab-vertical="true"] .tabbrowser-strip { +tabbrowser[treestyletab-vertical="true"] .tabbrowser-arrowscrollbox > scrollbox { overflow-x: hidden; overflow-y: auto; } +tabbrowser[treestyletab-vertical="true"] .tabs-stack > * + * > hbox { + -moz-box-flex: 1 !important; +} + +/* +tabbrowser[treestyletab-vertical="true"] .tabbrowser-arrowscrollbox > scrollbox > .scrollbox-innerbox { + -moz-box-flex: 0 !important; +} +*/ tabbrowser[treestyletab-tabbar-position="right"] .tabbrowser-tab .tab-image-middle { diff --git a/content/treestyletab/treestyletab.js b/content/treestyletab/treestyletab.js index 2391ffe4..285b77d3 100644 --- a/content/treestyletab/treestyletab.js +++ b/content/treestyletab/treestyletab.js @@ -84,7 +84,7 @@ var TreeStyleTabService = { _ObserverService : null, /* Utilities */ - + isEventFiredOnTabIcon : function(aEvent) { var tab = this.getTabFromEvent(aEvent); @@ -204,6 +204,17 @@ var TreeStyleTabService = { return (box.getAttribute('orient') || window.getComputedStyle(box, '').getPropertyValue('-moz-box-orient')) == 'vertical'; }, + isTabVisible : function(aTab) + { + if (!aTab) return false; + var tabBox = aTab.boxObject; + var barBox = this.getTabBrowserFromChildren(aTab).mTabContainer.mTabstrip.boxObject; + return (tabBox.screenX >= barBox.screenX && + tabBox.screenX + tabBox.width <= barBox.screenX + barBox.width && + tabBox.screenY >= barBox.screenY && + tabBox.screenY + tabBox.height <= barBox.screenY + barBox.height); + }, + cleanUpTabsArray : function(aTabs) { var b = this.getTabBrowserFromChildren(aTabs[0]); @@ -358,6 +369,19 @@ var TreeStyleTabService = { ) ); + eval('aTabBrowser.mTabContainer._handleTabSelect = '+ + aTabBrowser.mTabContainer._handleTabSelect.toSource().replace( + /\{/, + <> + ) + ); + eval('aTabBrowser.mTabContainer._notifyBackgroundTab = '+ aTabBrowser.mTabContainer._notifyBackgroundTab.toSource().replace( /\.screenX/g, '[TreeStyleTabService.positionProp]' @@ -733,7 +757,7 @@ catch(e) { }, /* Event Handling */ - + handleEvent : function(aEvent) { switch (aEvent.type) @@ -1019,7 +1043,7 @@ catch(e) { var b = this.getTabBrowserFromChildren(aEvent.originalTarget); this.setPref('extensions.treestyletab.tabbar.width', b.mStrip.boxObject.width); }, - + /* Tab Utilities */ getTabValue : function(aTab, aKey) @@ -1389,6 +1413,8 @@ catch(e) { ref.parentNode.insertBefore(splitter, ref); } + var scrollInnerBox = document.getAnonymousNodes(aTabBrowser.mTabContainer.mTabstrip._scrollbox)[0]; + if (pos & this.kTABBAR_VERTICAL) { this.positionProp = 'screenY'; this.sizeProp = 'height'; @@ -1396,6 +1422,7 @@ catch(e) { aTabBrowser.mTabBox.orient = 'horizontal'; aTabBrowser.mTabContainer.orient = aTabBrowser.mTabContainer.mTabstrip.orient = 'vertical'; + scrollInnerBox.removeAttribute('flex'); aTabBrowser.mPanelContainer.removeAttribute('width'); aTabBrowser.mStrip.setAttribute('width', this.getPref('extensions.treestyletab.tabbar.width')); @@ -1427,6 +1454,7 @@ catch(e) { aTabBrowser.mTabBox.orient = 'vertical'; aTabBrowser.mTabContainer.orient = aTabBrowser.mTabContainer.mTabstrip.orient = 'horizontal'; + scrollInnerBox.setAttribute('flex', 1); aTabBrowser.mStrip.removeAttribute('width'); aTabBrowser.mPanelContainer.removeAttribute('width'); @@ -1733,6 +1761,9 @@ catch(e) { this.collapseExpandTab(tabs[i], aCollapse); } + if (!aCollapse) + this.scrollToTabSubTree(aTab); + b.__treestyletab__doingCollapseExpand = false; }, @@ -1802,6 +1833,148 @@ catch(e) { this.collapseExpandTabSubTree(aTab, false); }, +/* scroll */ + + scrollTo : function(aTabBrowser, aEndX, aEndY) + { + if (this.getPref('extensions.treestyletab.tabbar.scroll.smooth')) + this.smoothScrollTo(aTabBrowser, aEndX, aEndY); + else + this.getTabBrowserFromChildren(aTabBrowser).mTabstrip.scrollBoxObject.scrollTo(aEndX, aEndY); + }, + + smoothScrollTo : function(aTabBrowser, aEndX, aEndY) + { + var b = this.getTabBrowserFromChildren(aTabBrowser); + + if (b.__treestyletab__smoothScrollTimer) { + window.clearInterval(b.__treestyletab__smoothScrollTimer); + b.__treestyletab__smoothScrollTimer = null; + } + + var scrollBoxObject = b.mTabContainer.mTabstrip.scrollBoxObject; + var x = {}, y = {}; + scrollBoxObject.getPosition(x, y); + b.__treestyletab__smoothScrollTimer = window.setInterval( + this.smoothScrollToCallback, + 10, + this, + b, + x.value, + y.value, + aEndX, + aEndY, + Date.now(), + this.getPref('extensions.treestyletab.tabbar.scroll.timeout') + ); + }, + + smoothScrollToCallback : function(aSelf, aTabBrowser, aStartX, aStartY, aEndX, aEndY, aStartTime, aTimeout) + { + var newX = aStartX + parseInt( + (aEndX - aStartX) * ((Date.now() - aStartTime) / aTimeout) + ); + var newY = aStartY + parseInt( + (aEndY - aStartY) * ((Date.now() - aStartTime) / aTimeout) + ); + + var scrollBoxObject = aTabBrowser.mTabContainer.mTabstrip.scrollBoxObject; + var x = {}, y = {}; + scrollBoxObject.getPosition(x, y); + + var w = {}, h = {}; + scrollBoxObject.getScrolledSize(w, h); + var maxX = Math.max(0, w.value - scrollBoxObject.width); + var maxY = Math.max(0, h.value - scrollBoxObject.height); + + if ( + ( + aEndX - aStartX > 0 ? + x.value >= Math.min(aEndX, maxX) : + x.value <= Math.min(aEndX, maxX) + ) && + ( + aEndY - aStartY > 0 ? + y.value >= Math.min(aEndY, maxY) : + y.value <= Math.min(aEndY, maxY) + ) + ) { + if (aTabBrowser.__treestyletab__smoothScrollTimer) { + window.clearInterval(aTabBrowser.__treestyletab__smoothScrollTimer); + aTabBrowser.__treestyletab__smoothScrollTimer = null; + } + return; + } + + scrollBoxObject.scrollTo(newX, newY); + }, + + scrollToTab : function(aTab) + { + if (!aTab || this.isTabVisible(aTab)) return; + + var b = this.getTabBrowserFromChildren(aTab); + + var scrollBoxObject = b.mTabContainer.mTabstrip.scrollBoxObject; + var w = {}, h = {}; + scrollBoxObject.getScrolledSize(w, h); + + var targetTabBox = aTab.boxObject; + var baseTabBox = aTab.parentNode.firstChild.boxObject; + + var targetX = (aTab.boxObject.screenX < scrollBoxObject.screenX) ? + (targetTabBox.screenX - baseTabBox.screenX) - (targetTabBox.width * 0.5) : + (targetTabBox.screenX - baseTabBox.screenX) - scrollBoxObject.width + (targetTabBox.width * 1.5) ; + + var targetY = (aTab.boxObject.screenY < scrollBoxObject.screenY) ? + (targetTabBox.screenY - baseTabBox.screenY) - (targetTabBox.height * 0.5) : + (targetTabBox.screenY - baseTabBox.screenY) - scrollBoxObject.height + (targetTabBox.height * 1.5) ; + + this.scrollTo(b, targetX, targetY); + }, + + scrollToTabSubTree : function(aTab) + { + var b = this.getTabBrowserFromChildren(aTab); + var descendant = this.getDescendantTabs(aTab); + var lastVisible = aTab; + for (var i = descendant.length-1; i > -1; i--) + { + if (descendant[i].getAttribute(this.kCOLLAPSED) == 'true') continue; + lastVisible = descendant[i]; + break; + } + + var containerPosition = b.mStrip.boxObject[this.positionProp]; + var containerSize = b.mStrip.boxObject[this.sizeProp]; + var parentPosition = aTab.boxObject[this.positionProp]; + var lastPosition = lastVisible.boxObject[this.positionProp]; + var tabSize = lastVisible.boxObject[this.sizeProp]; + + if (this.isTabVisible(aTab) && this.isTabVisible(lastVisible)) { + return; + } + + if (lastPosition - parentPosition + tabSize > containerSize - tabSize) { // out of screen + var endPos = parentPosition - b.mTabContainer.firstChild.boxObject[this.positionProp] - tabSize * 0.5; + var endX = this.isTabVertical(aTab) ? 0 : endPos ; + var endY = this.isTabVertical(aTab) ? endPos : 0 ; + this.scrollTo(b, endX, endY); + } + else if (!this.isTabVisible(aTab) && this.isTabVisible(lastVisible)) { + this.scrollToTab(aTab); + } + else if (this.isTabVisible(aTab) && !this.isTabVisible(lastVisible)) { + this.scrollToTab(lastVisible); + } + else if (parentPosition < containerPosition) { + this.scrollToTab(aTab); + } + else { + this.scrollToTab(lastVisible); + } + }, + removeTabSubTree : function(aTabOrTabs) { var tabs = aTabOrTabs; diff --git a/defaults/preferences/treestyletab.js b/defaults/preferences/treestyletab.js index 589ad492..87e01a2c 100644 --- a/defaults/preferences/treestyletab.js +++ b/defaults/preferences/treestyletab.js @@ -7,6 +7,8 @@ pref("extensions.treestyletab.focusMode", 1); pref("extensions.treestyletab.levelMargin", 12); pref("extensions.treestyletab.tabbar.width", 200); pref("extensions.treestyletab.tabbar.position", "left"); +pref("extensions.treestyletab.tabbar.scroll.smooth", true); +pref("extensions.treestyletab.tabbar.scroll.timeout", 250); pref("browser.link.open_newwindow.restriction", 0);