diff --git a/content/treestyletab/treestyletab.css b/content/treestyletab/treestyletab.css index b9755198..5b96e4ba 100644 --- a/content/treestyletab/treestyletab.css +++ b/content/treestyletab/treestyletab.css @@ -25,11 +25,12 @@ .tabbrowser-strip[treestyletab-tabbar-autohide="hidden"]+splitter, tabbrowser:not([treestyletab-tabbar-autohide="hidden"]) .treestyletab-tabbar-toggler, #TabsToolbar[treestyletab-tabbar-autohide="hidden"] > *, -#TabsToolbar:not([treestyletab-tabbar-autohide-state="expanded"]) #treestyletab-tabbar-resizer-box, +#TabsToolbar #treestyletab-tabbar-resizer-box, #appcontent[ahFull="true"] .tabbrowser-strip[ahHIDE="true"]+splitter /* AutoHide */, .tabbrowser-strip[treestyletab-tabbar-fixed="true"]+splitter, .tabbrowser-strip[treestyletab-print-preview="true"], .tabbrowser-strip[treestyletab-print-preview="true"]+splitter, +#TabsToolbar .treestyletab-splitter, #TabsToolbar[treestyletab-print-preview="true"], window[chromehidden~="toolbar"] .tabbrowser-strip[treestyletab-tabbar-placeholder="true"], window[chromehidden~="toolbar"] .tabbrowser-strip[treestyletab-tabbar-placeholder="true"]+splitter { @@ -114,19 +115,31 @@ tabbrowser[treestyletab-mode="vertical"] .tabs-stack > *:first-child + * > hbox: overflow: hidden !important; } -#TabsToolbar[treestyletab-tabbar-autohide-state="expanded"] > *, -.tabs-toolbar-inner-box[treestyletab-tabbar-autohide-state="expanded"] > * { +#TabsToolbar[treestyletab-mode="vertical"][treestyletab-tabbar-autohide][treestyletab-tabbar-autohide-state="expanded"] + > *, +.tabs-toolbar-inner-box[treestyletab-tabbar-autohide][treestyletab-tabbar-autohide-state="expanded"]:not([treestyletab-tabbar-fixed="true"]) + > * { position: relative; z-index: 2; } -#TabsToolbar[treestyletab-tabbar-autohide-state="expanded"] #treestyletab-tabbar-resizer-box { +#TabsToolbar[treestyletab-mode="vertical"][treestyletab-tabbar-autohide][treestyletab-tabbar-autohide-state="expanded"] + #treestyletab-tabbar-resizer-box { position: absolute; bottom: 0; left: 0; right: 0; top: 0; z-index: 1; + line-height: 0; /* to avoid an useless space above the splitter */ + font-size: 0; /* to avoid an useless space above the splitter */ } +#TabsToolbar[treestyletab-mode="vertical"][treestyletab-tabbar-autohide][treestyletab-tabbar-autohide-state="expanded"] + #treestyletab-tabbar-resizer-box, +#TabsToolbar[treestyletab-mode="vertical"][treestyletab-tabbar-autohide][treestyletab-tabbar-autohide-state="expanded"]:not([treestyletab-tabbar-fixed="true"]) + .treestyletab-splitter { + visibility: visible; +} + diff --git a/content/treestyletab/treestyletab.js b/content/treestyletab/treestyletab.js index b4f1463e..2a4a6308 100644 --- a/content/treestyletab/treestyletab.js +++ b/content/treestyletab/treestyletab.js @@ -333,7 +333,7 @@ var TreeStyleTabService = { window.removeEventListener('load', this, false); window.addEventListener('unload', this, false); document.addEventListener('popupshowing', this, false); - document.addEventListener('popuphiding', this, false); + document.addEventListener('popuphiding', this, true); document.addEventListener('TreeStyleTabCollapsedStateChange', this, false); document.addEventListener('TreeStyleTabTabbarPositionChanged', this, false); document.addEventListener('TreeStyleTabTabbarStateChanged', this, false); @@ -1358,7 +1358,7 @@ catch(e) { this.endListenKeyEventsFor(this.LISTEN_FOR_AUTOEXPAND_BY_FOCUSCHANGE); document.removeEventListener('popupshowing', this, false); - document.removeEventListener('popuphiding', this, false); + document.removeEventListener('popuphiding', this, true); document.removeEventListener('TreeStyleTabCollapsedStateChange', this, false); document.removeEventListener('TreeStyleTabTabbarPositionChanged', this, false); document.removeEventListener('TreeStyleTabTabbarStateChanged', this, false); @@ -1411,34 +1411,13 @@ catch(e) { return this.onTabRestored(aEvent); case 'popupshowing': - if (aEvent.originalTarget.boxObject && - !this.evaluateXPath( - 'local-name() = "tooltip" or local-name() ="panel" or '+ - 'parent::*/ancestor-or-self::*[local-name()="popup" or local-name()="menupopup"]', - aEvent.originalTarget, - XPathResult.BOOLEAN_TYPE - ).booleanValue) { - this.popupMenuShown = true; - window.setTimeout(function(aSelf, aPopup) { - if (!aPopup.boxObject.width || !aPopup.boxObject.height) - aSelf.popupMenuShown = false; - }, 10, this, aEvent.originalTarget); - } + this.onPopupShown(aEvent.originalTarget); if ((aEvent.originalTarget.getAttribute('anonid') || aEvent.originalTarget.id) == 'alltabs-popup') this.updateAllTabsPopup(aEvent); return; case 'popuphiding': - if (aEvent.originalTarget.boxObject && - !this.evaluateXPath( - 'local-name() = "tooltip" or local-name() ="panel" or '+ - 'parent::*/ancestor-or-self::*[local-name()="popup" or local-name()="menupopup"]', - aEvent.originalTarget, - XPathResult.BOOLEAN_TYPE - ).booleanValue) { - this.popupMenuShown = false; - } - return; + return this.onPopupHidden(aEvent.originalTarget); case 'TreeStyleTabCollapsedStateChange': return this.updateAeroPeekPreviews(); @@ -1618,25 +1597,30 @@ catch(e) { onTabbarResized : function TSTService_onTabbarResized(aEvent) { - var b = this.getTabBrowserFromChild(aEvent.currentTarget); - var box = (b.treeStyleTab.tabStripPlaceHolder || this.getTabStrip(b)).boxObject; + var target = aEvent.currentTarget; + var b = this.getTabBrowserFromChild(target); + var strip = this.getTabStrip(b); + var box = (b.treeStyleTab.tabStripPlaceHolder || strip).boxObject; window.setTimeout(function(aSelf) { if (!b.treeStyleTab.clickedOnTabbarResizerGrippy) { if (!b.treeStyleTab.isVertical) { - aSelf.setTreePref('tabbar.height', aSelf.maxTabbarHeight(box.height, b)); + let height = aSelf.maxTabbarHeight(box.height, b); + aSelf.setTreePref('tabbar.height', height); } else { + let width = aSelf.maxTabbarWidth(box.width, b); if (!b.treeStyleTab.autoHide.expanded) - aSelf.setTreePref('tabbar.shrunkenWidth', aSelf.maxTabbarWidth(box.width, b)); + aSelf.setTreePref('tabbar.shrunkenWidth', width); else - aSelf.setTreePref('tabbar.width', aSelf.maxTabbarWidth(box.width, b)); + aSelf.setTreePref('tabbar.width', width); } } - b.treeStyleTab.updateFloatingTabbar(); + b.treeStyleTab.updateFloatingTabbar(true); b.treeStyleTab.clickedOnTabbarResizerGrippy = false; }, 10, this); }, - onTabbarResizerClick : function TSTService_onTabbarResizerClick(aEvent) + + onTabbarResizerClick : function TSTService_onTabbarResizerClick(aEvent) { var b = this.getTabBrowserFromChild(aEvent.currentTarget); b.treeStyleTab.clickedOnTabbarResizerGrippy = this.evaluateXPath( @@ -1646,6 +1630,59 @@ catch(e) { ).booleanValue; }, + onFloatingTabbarResizeStart : function TSTService_onFloatingTabbarResizeStart(aEvent) + { + aEvent.stopPropagation(); + aEvent.target.setCapture(true); + this.floatingTabbarResizeResizing = true; + var b = this.getTabBrowserFromChild(aEvent.target); + var strip = this.getTabStrip(b); + this.floatingTabbarResizeStartWidth = strip.boxObject.width; + this.floatingTabbarResizeStartHeight = strip.boxObject.height; + this.floatingTabbarResizeStartX = aEvent.screenX; + this.floatingTabbarResizeStartY = aEvent.screenY; + }, + onFloatingTabbarResizeEnd : function TSTService_onFloatingTabbarResizeEnd(aEvent) + { + aEvent.stopPropagation(); + aEvent.target.releaseCapture(); + this.floatingTabbarResizeResizing = false; + this.floatingTabbarResizeStartWidth = -1; + this.floatingTabbarResizeStartHeight = -1; + this.floatingTabbarResizeStartX = -1; + this.floatingTabbarResizeStartY = -1; + }, + onFloatingTabbarResizing : function TSTService_onFloatingTabbarResizing(aEvent) + { + if (!this.floatingTabbarResizeResizing) + return; + + aEvent.stopPropagation(); + var b = this.getTabBrowserFromChild(aEvent.target); + var width = this.floatingTabbarResizeStartWidth; + var height = this.floatingTabbarResizeStartHeight; + var pos = b.treeStyleTab.currentTabbarPosition; + if (b.treeStyleTab.isVertical) { + let delta = aEvent.screenX - this.floatingTabbarResizeStartX; + width += (pos == 'left' ? delta : -delta ); + this.setTreePref('tabbar.width', Math.max(0, width)); + if (b.treeStyleTab.autoHide.mode == b.treeStyleTab.autoHide.kMODE_SHRINK && + b.treeStyleTab._tabStripPlaceHolder) + b.treeStyleTab._tabStripPlaceHolder.setAttribute('width', this.getTreePref('tabbar.shrunkenWidth')); + } + else { + let delta = aEvent.screenY - this.floatingTabbarResizeStartY; + height += (pos == 'top' ? delta : -delta ); + this.setTreePref('tabbar.height', Math.max(0, height)); + } + b.treeStyleTab.updateFloatingTabbar(true); + }, + floatingTabbarResizeResizing : false, + floatingTabbarResizeStartWidth : -1, + floatingTabbarResizeStartHeight : -1, + floatingTabbarResizeStartX : -1, + floatingTabbarResizeStartY : -1, + showHideSubtreeMenuItem : function TSTService_showHideSubtreeMenuItem(aMenuItem, aTabs) { if (!aMenuItem || @@ -1782,6 +1819,49 @@ catch(e) { delete this._tabsOnTopDefaultState; } }, + + onPopupShown : function TSTService_onPopupShown(aPopup) + { + if (!aPopup.boxObject || + this.evaluateXPath( + 'local-name() = "tooltip" or local-name() ="panel" or '+ + 'parent::*/ancestor-or-self::*[local-name()="popup" or local-name()="menupopup"]', + aEvent.originalTarget, + XPathResult.BOOLEAN_TYPE + ).booleanValue) + return; + + window.setTimeout(function(aSelf) { + if (!aPopup.boxObject.width && !aPopup.boxObject.height) + return; + + var id = aPopup.id; + var item = document.getElementById(id) ? id : aPopup ; + var index = TreeStyleTabService._shownPopups.indexOf(item); + if (index < 0) + TreeStyleTabService._shownPopups.push(item); + }, 10, this); + }, + + onPopupHidden : function TSTService_onPopupHidden(aPopup) + { + var id = aPopup.id; + aPopup = document.getElementById(id) || aPopup; + var index = TreeStyleTabService._shownPopups.indexOf(aPopup); + if (index > -1) + TreeStyleTabService._shownPopups.splice(index, 1); + }, + + isPopupShown : function TSTService_isPopupShown() + { + TreeStyleTabService._shownPopups = TreeStyleTabService._shownPopups.filter(function(aItem) { + if (typeof aItem == 'string') + aItem = document.getElementById(aItem); + return aItem && aItem.boxObject && aItem.boxObject.width && aItem.boxObject.height; + }); + return TreeStyleTabService._shownPopups.length > 0; + }, + _shownPopups : [], /* Tree Style Tabの初期化が行われる前に復元されたセッションについてツリー構造を復元 */ diff --git a/content/treestyletab/treestyletab.xul b/content/treestyletab/treestyletab.xul index f681402d..c41c06cb 100644 --- a/content/treestyletab/treestyletab.xul +++ b/content/treestyletab/treestyletab.xul @@ -148,8 +148,14 @@ - - + + + diff --git a/content/treestyletab/treestyletabbrowser.js b/content/treestyletab/treestyletabbrowser.js index f66bb9d2..cf9e788c 100644 --- a/content/treestyletab/treestyletabbrowser.js +++ b/content/treestyletab/treestyletabbrowser.js @@ -743,7 +743,7 @@ TreeStyleTabBrowser.prototype = { this.autoHide; - this.fireTabbarPositionEvent('TreeStyleTabTabbarPositionChanged', 'top', position); /* PUBLIC API */ + this.fireTabbarPositionEvent(false, 'top', position); /* PUBLIC API */ b = null; @@ -1263,7 +1263,7 @@ TreeStyleTabBrowser.prototype = { }, 0, this.mTabBrowser); }, - updateFloatingTabbar : function TSTBrowser_updateFloatingTabbar(aWidth, aHeight, aJustNow) + updateFloatingTabbar : function TSTBrowser_updateFloatingTabbar(aJustNow) { // this method is just for Firefox 4.0 or later if (!this.isFloating) return; @@ -1274,16 +1274,16 @@ TreeStyleTabBrowser.prototype = { } if (aJustNow) { - this.updateFloatingTabbarInternal(aWidth, aHeight); + this.updateFloatingTabbarInternal(); } else { this.updateFloatingTabbarTimer = window.setTimeout(function(aSelf) { aSelf.updateFloatingTabbarTimer = null; - aSelf.updateFloatingTabbarInternal(aWidth, aHeight) + aSelf.updateFloatingTabbarInternal() }, 0, this); } }, - updateFloatingTabbarInternal : function TSTBrowser_updateFloatingTabbarInternal(aWidth, aHeight) + updateFloatingTabbarInternal : function TSTBrowser_updateFloatingTabbarInternal() { var strip = this.tabStrip; var tabContainerBox = this.getTabContainerBox(this.mTabBrowser); @@ -1298,8 +1298,8 @@ TreeStyleTabBrowser.prototype = { let realWidth = parseInt(this._tabStripPlaceHolder.getAttribute('width') || box.width); let realHeight = parseInt(this._tabStripPlaceHolder.getAttribute('height') || box.height); - let width = aWidth || realWidth; - let height = aHeight || realHeight; + let width = (this.autoHide.expanded && this.isVertical ? this.maxTabbarWidth(this.getTreePref('tabbar.width')) : 0 ) || realWidth; + let height = (this.autoHide.expanded && !this.isVertical ? this.maxTabbarHeight(this.getTreePref('tabbar.height')) : 0 ) || realHeight; let xOffset = pos == 'right' ? width - realWidth : 0 ; let yOffset = pos == 'bottom' ? height - realHeight : 0 ; @@ -1309,11 +1309,12 @@ TreeStyleTabBrowser.prototype = { strip.style.width = (tabContainerBox.width = width)+'px'; strip.style.height = (tabContainerBox.height = height)+'px'; - let resizerStyle = this.floatingTabbarResizerBox.style; - resizerStyle.top = pos == 'top' ? realHeight+'px' : '' ; - resizerStyle.right = pos == 'right' ? realWidth+'px' : '' ; - resizerStyle.left = pos == 'left' ? realWidth+'px' : '' ; - resizerStyle.bottom = pos == 'bottom' ? realHeight+'px' : '' ; + this.updateFloatingTabbarResizer({ + width : width, + realWidth : realWidth, + height : height, + realHeight : realHeight + }); tabContainerBox.collapsed = (this.splitter && this.splitter.getAttribute('state') == 'collapsed'); @@ -1366,9 +1367,52 @@ TreeStyleTabBrowser.prototype = { if ('_positionPinnedTabs' in this.mTabBrowser.mTabContainer) this.mTabBrowser.mTabContainer._positionPinnedTabs(); }, - get floatingTabbarResizerBox() + updateFloatingTabbarResizer : function TSTBrowser_updateFloatingTabbarResizer(aSize) { - return document.getElementById('treestyletab-tabbar-resizer-box'); + var width = aSize.width; + var realWidth = aSize.realWidth; + var height = aSize.height; + var realHeight = aSize.realHeight; + var pos = this.currentTabbarPosition; + var vertical = this.isVertical; + + var splitter = document.getElementById('treestyletab-tabbar-resizer-splitter'); + var box = splitter.parentNode; + + box.orient = splitter.orient = vertical ? 'horizontal' : 'vertical' ; + box.width = (width - realWidth) || width; + box.height = (height - realHeight) || height; + + var boxStyle = box.style; + boxStyle.top = pos == 'top' ? realHeight+'px' : '' ; + boxStyle.right = pos == 'right' ? realWidth+'px' : '' ; + boxStyle.left = pos == 'left' ? realWidth+'px' : '' ; + boxStyle.bottom = pos == 'bottom' ? realHeight+'px' : '' ; + + if (vertical) { + splitter.removeAttribute('width'); + splitter.setAttribute('height', height); + } + else { + splitter.setAttribute('width', width); + splitter.removeAttribute('height'); + } + + var splitterWidth = splitter.boxObject.width; + var splitterHeight = splitter.boxObject.height; + var splitterStyle = splitter.style; + splitterStyle.marginTop = pos == 'bottom' ? (-splitterHeight)+'px' : + vertical ? '0' : + box.height+'px' ; + splitterStyle.marginRight = pos == 'left' ? (-splitterWidth)+'px' : + !vertical ? '0' : + box.width+'px' ; + splitterStyle.marginLeft = pos == 'right' ? (-splitterWidth)+'px' : + !vertical ? '0' : + box.width+'px' ; + splitterStyle.marginBottom = pos == 'top' ? (-splitterHeight)+'px' : + vertical ? '0' : + box.height+'px' ; }, resetTabbarSize : function TSTBrowser_resetTabbarSize() diff --git a/content/treestyletab/treestyletabbrowser_autoHide.js b/content/treestyletab/treestyletabbrowser_autoHide.js index bacc37cf..5bddf667 100644 --- a/content/treestyletab/treestyletabbrowser_autoHide.js +++ b/content/treestyletab/treestyletabbrowser_autoHide.js @@ -191,10 +191,13 @@ TreeStyleTabBrowserAutoHide.prototype = { this.clearBG(); this.updateTransparency(); - sv.container.style.margin = 0; + if (!sv.isFloating) + sv.container.style.margin = 0; sv.removeTabbrowserAttribute(this.kAUTOHIDE); sv.removeTabbrowserAttribute(this.kSTATE); sv.removeTabbrowserAttribute(this.kTRANSPARENT); + + sv.setTabStripAttribute('width', this.widthFromMode); }, // fullscreen @@ -540,7 +543,11 @@ TreeStyleTabBrowserAutoHide.prototype = { switch (this.mode) { case this.kMODE_DISABLED: + break; + case this.kMODE_HIDE: + if (sv.isFloating) + sv.updateFloatingTabbar(true); break; default: @@ -548,7 +555,7 @@ TreeStyleTabBrowserAutoHide.prototype = { if (pos == 'left' || pos == 'right') { let width = sv.maxTabbarWidth(this.getTreePref('tabbar.width')); if (sv.isFloating) // Firefox 4.0- - sv.updateFloatingTabbar(width, 0, true); + sv.updateFloatingTabbar(true); else // -Firefox 3.6 sv.setTabStripAttribute('width', width); } @@ -575,19 +582,23 @@ TreeStyleTabBrowserAutoHide.prototype = { switch (this.mode) { case this.kMODE_DISABLED: + sv.setTabbrowserAttribute(this.kAUTOHIDE, 'hidden'); + sv.setTabbrowserAttribute(this.kSTATE, this.kSTATE_HIDDEN); + break; + case this.kMODE_HIDE: sv.setTabbrowserAttribute(this.kAUTOHIDE, 'hidden'); sv.setTabbrowserAttribute(this.kSTATE, this.kSTATE_HIDDEN); + sv.updateFloatingTabbar(true); break; default: case this.kMODE_SHRINK: sv.setTabbrowserAttribute(this.kAUTOHIDE, 'show'); sv.setTabbrowserAttribute(this.kSTATE, this.kSTATE_SHRUNKEN); - if (pos == 'left' || pos == 'right') { + if (pos == 'left' || pos == 'right') sv.setTabStripAttribute('width', this.getTreePref('tabbar.shrunkenWidth')); - sv.updateFloatingTabbar(0, 0, true); - } + sv.updateFloatingTabbar(true); break; } }, @@ -871,6 +882,7 @@ TreeStyleTabBrowserAutoHide.prototype = { else { sv.removeTabbrowserAttribute(this.kTRANSPARENT); } + sv.updateFloatingTabbar(); }, // event handling @@ -1004,7 +1016,10 @@ TreeStyleTabBrowserAutoHide.prototype = { return; case 'TreeStyleTabTabbarPositionChanged': - if (this.enabled) this.show(); + if (this.enabled) { + this.hide(); + this.show(); + } this.updateTransparency(); return; @@ -1113,7 +1128,7 @@ TreeStyleTabBrowserAutoHide.prototype = { return true; if ( - !sv.popupMenuShown && + !sv.isPopupShown() && ( !this.expanded || this.showHideReason & this.kKEEP_SHOWN_ON_MOUSEOVER @@ -1125,7 +1140,9 @@ TreeStyleTabBrowserAutoHide.prototype = { onResize : function TSTAutoHide_onResize(aEvent) { + var sv = this.mOwner; if ( + sv.isFloating || !aEvent.originalTarget || ( aEvent.originalTarget.ownerDocument != document && @@ -1135,7 +1152,6 @@ TreeStyleTabBrowserAutoHide.prototype = { ) { return; } - var sv = this.mOwner; switch (sv.currentTabbarPosition) { case 'left': diff --git a/modules/utils.js b/modules/utils.js index 8e216a33..41d7414f 100644 --- a/modules/utils.js +++ b/modules/utils.js @@ -1881,8 +1881,8 @@ var TreeStyleTabUtils = { if (expanded != originalExpanded || shrunken != originalShrunken) { this.tabbarWidthResetting = true; - this.setTreePref('tabbar.width', expanded); - this.setTreePref('tabbar.shrunkenWidth', shrunken); + this.setTreePref('tabbar.width', Math.max(0, expanded)); + this.setTreePref('tabbar.shrunkenWidth', Math.max(0, shrunken)); this.tabbarWidthResetting = false; } }, diff --git a/skin/classic/treestyletab/ui.css b/skin/classic/treestyletab/ui.css index 6871f02c..3d684c80 100644 --- a/skin/classic/treestyletab/ui.css +++ b/skin/classic/treestyletab/ui.css @@ -120,7 +120,12 @@ tabbrowser[treestyletab-drop-position] { #TabsToolbar[treestyletab-drop-position="top"]:not([treestyletab-tabbar-position="top"]), #TabsToolbar[treestyletab-drop-position="right"]:not([treestyletab-tabbar-position="right"]), #TabsToolbar[treestyletab-drop-position="bottom"]:not([treestyletab-tabbar-position="bottom"]), -#TabsToolbar[treestyletab-drop-position="left"]:not([treestyletab-tabbar-position="left"]) { +#TabsToolbar[treestyletab-drop-position="left"]:not([treestyletab-tabbar-position="left"]), +#TabsToolbar[treestyletab-drop-position="center"] #treestyletab-tabbar-resizer-box, +#TabsToolbar[treestyletab-drop-position="top"]:not([treestyletab-tabbar-position="top"]) #treestyletab-tabbar-resizer-box, +#TabsToolbar[treestyletab-drop-position="right"]:not([treestyletab-tabbar-position="right"]) #treestyletab-tabbar-resizer-box, +#TabsToolbar[treestyletab-drop-position="bottom"]:not([treestyletab-tabbar-position="bottom"]) #treestyletab-tabbar-resizer-box, +#TabsToolbar[treestyletab-drop-position="left"]:not([treestyletab-tabbar-position="left"]) #treestyletab-tabbar-resizer-box { opacity: 0.5; } tabbrowser[treestyletab-drop-position="top"]:not([treestyletab-tabbar-position="top"]) {