split implementation of full tooltip
This commit is contained in:
parent
e2039d9370
commit
71d517d51b
@ -153,13 +153,7 @@
|
|||||||
oncommand="TreeStyleTabService.toggleFixed(TreeStyleTabService.getTabBrowserFromChild(this));"/>
|
oncommand="TreeStyleTabService.toggleFixed(TreeStyleTabService.getTabBrowserFromChild(this));"/>
|
||||||
|
|
||||||
</menupopup>
|
</menupopup>
|
||||||
<tooltip id="treestyletab-full-tree-tooltip"
|
<tooltip id="treestyletab-full-tree-tooltip">
|
||||||
onclick="this.hidePopup();"
|
|
||||||
onpopuphiding="
|
|
||||||
var range = document.createRange();
|
|
||||||
range.selectNodeContents(this.firstChild);
|
|
||||||
range.deleteContents();
|
|
||||||
">
|
|
||||||
<arrowscrollbox flex="1" orient="vertical"/>
|
<arrowscrollbox flex="1" orient="vertical"/>
|
||||||
</tooltip>
|
</tooltip>
|
||||||
</popupset>
|
</popupset>
|
||||||
|
@ -42,6 +42,7 @@ const Ci = Components.interfaces;
|
|||||||
// rap();
|
// rap();
|
||||||
|
|
||||||
Components.utils.import('resource://treestyletab-modules/window.js');
|
Components.utils.import('resource://treestyletab-modules/window.js');
|
||||||
|
Components.utils.import('resource://treestyletab-modules/fullTooltip.js');
|
||||||
|
|
||||||
function TreeStyleTabBrowser(aWindowService, aTabBrowser)
|
function TreeStyleTabBrowser(aWindowService, aTabBrowser)
|
||||||
{
|
{
|
||||||
@ -136,12 +137,6 @@ TreeStyleTabBrowser.prototype = {
|
|||||||
{
|
{
|
||||||
return (this._tabStripPlaceHolder = value);
|
return (this._tabStripPlaceHolder = value);
|
||||||
},
|
},
|
||||||
|
|
||||||
get tabTooltip()
|
|
||||||
{
|
|
||||||
return this.document.getElementById('tabbrowser-tab-tooltip') || // Firefox 4.0-
|
|
||||||
this.evaluateXPath('descendant::xul:tooltip', this.mTabBrowser.mStrip, Ci.nsIDOMXPathResult.FIRST_ORDERED_NODE_TYPE).singleNodeValue; // -Firefox 3.6
|
|
||||||
},
|
|
||||||
|
|
||||||
/* properties */
|
/* properties */
|
||||||
|
|
||||||
@ -1279,7 +1274,7 @@ TreeStyleTabBrowser.prototype = {
|
|||||||
this.scrollBox.addEventListener('overflow', this, true);
|
this.scrollBox.addEventListener('overflow', this, true);
|
||||||
this.scrollBox.addEventListener('underflow', this, true);
|
this.scrollBox.addEventListener('underflow', this, true);
|
||||||
|
|
||||||
this.tabTooltip.addEventListener('popupshowing', this, true);
|
this.fullTooltipManager = new FullTooltipManager(this);
|
||||||
},
|
},
|
||||||
|
|
||||||
_ensureNewSplitter : function TSTBrowser__ensureNewSplitter()
|
_ensureNewSplitter : function TSTBrowser__ensureNewSplitter()
|
||||||
@ -1845,7 +1840,8 @@ TreeStyleTabBrowser.prototype = {
|
|||||||
this.scrollBox.removeEventListener('overflow', this, true);
|
this.scrollBox.removeEventListener('overflow', this, true);
|
||||||
this.scrollBox.removeEventListener('underflow', this, true);
|
this.scrollBox.removeEventListener('underflow', this, true);
|
||||||
|
|
||||||
this.tabTooltip.removeEventListener('popupshowing', this, true);
|
this.fullTooltipManager.destroy();
|
||||||
|
delete this.fullTooltipManager;
|
||||||
},
|
},
|
||||||
|
|
||||||
saveCurrentState : function TSTBrowser_saveCurrentState()
|
saveCurrentState : function TSTBrowser_saveCurrentState()
|
||||||
@ -2404,7 +2400,10 @@ TreeStyleTabBrowser.prototype = {
|
|||||||
return this.onScroll(aEvent);
|
return this.onScroll(aEvent);
|
||||||
|
|
||||||
case 'popupshowing':
|
case 'popupshowing':
|
||||||
return this.onPopupShowing(aEvent)
|
return this.onPopupShowing(aEvent);
|
||||||
|
|
||||||
|
case 'popuphiding':
|
||||||
|
return this.onPopupHiding(aEvent);
|
||||||
|
|
||||||
case 'mouseover':
|
case 'mouseover':
|
||||||
this._initDNDObservers();
|
this._initDNDObservers();
|
||||||
@ -3915,178 +3914,10 @@ TreeStyleTabBrowser.prototype = {
|
|||||||
|
|
||||||
onPopupShowing : function TSTBrowser_onPopupShowing(aEvent)
|
onPopupShowing : function TSTBrowser_onPopupShowing(aEvent)
|
||||||
{
|
{
|
||||||
if (aEvent.target.localName == 'tooltip')
|
if (aEvent.target == aEvent.currentTarget)
|
||||||
this.handleTooltip(aEvent);
|
|
||||||
else if (aEvent.target == aEvent.currentTarget)
|
|
||||||
this.initTabContextMenu(aEvent);
|
this.initTabContextMenu(aEvent);
|
||||||
},
|
},
|
||||||
|
|
||||||
handleTooltip : function TSTBrowser_handleTooltip(aEvent)
|
|
||||||
{
|
|
||||||
this.cancelFullTooltip();
|
|
||||||
|
|
||||||
var tab = this.getTabFromChild(this.document.tooltipNode);
|
|
||||||
if (!tab || tab.localName != 'tab')
|
|
||||||
return;
|
|
||||||
|
|
||||||
var label;
|
|
||||||
var collapsed = this.isSubtreeCollapsed(tab);
|
|
||||||
var mode = this.getTreePref('tooltip.mode');
|
|
||||||
var showTree = collapsed || mode == this.kTOOLTIP_MODE_ALWAYS;
|
|
||||||
|
|
||||||
var base = parseInt(tab.getAttribute(this.kNEST) || 0);
|
|
||||||
var descendant = this.getDescendantTabs(tab);
|
|
||||||
var indentPart = ' ';
|
|
||||||
var tree = null;
|
|
||||||
var fullTooltipExtraLabel = '';
|
|
||||||
if (mode > this.kTOOLTIP_MODE_DEFAULT &&
|
|
||||||
descendant.length) {
|
|
||||||
let tabs = [tab].concat(descendant);
|
|
||||||
let tabsToBeListed = tabs.slice(0, Math.max(1, this.getTreePref('tooltip.maxCount')));
|
|
||||||
tree = tabsToBeListed
|
|
||||||
.map(function(aTab) {
|
|
||||||
let label = aTab.getAttribute('label');
|
|
||||||
let indent = '';
|
|
||||||
let nest = parseInt(aTab.getAttribute(this.kNEST) || 0) - base;
|
|
||||||
for (let i = 0; i < nest; i++)
|
|
||||||
{
|
|
||||||
indent += indentPart;
|
|
||||||
}
|
|
||||||
return this.treeBundle.getFormattedString('tooltip.item.label', [label, indent]);
|
|
||||||
}, this)
|
|
||||||
.join('\n');
|
|
||||||
if (tabs.length != tabsToBeListed.length) {
|
|
||||||
tree += '\n'+indentPart+this.treeBundle.getFormattedString('tooltip.more', [tabs.length-tabsToBeListed.length]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ('mOverCloseButton' in tab && tab.mOverCloseButton) {
|
|
||||||
if (descendant.length &&
|
|
||||||
(collapsed || this.getTreePref('closeParentBehavior') == this.kCLOSE_PARENT_BEHAVIOR_CLOSE_ALL_CHILDREN)) {
|
|
||||||
label = tree || tab.getAttribute('label');
|
|
||||||
label = showTree ?
|
|
||||||
this.treeBundle.getFormattedString('tooltip.closeTree.labeled', [label]) :
|
|
||||||
this.treeBundle.getString('tooltip.closeTree') ;
|
|
||||||
if (showTree)
|
|
||||||
fullTooltipExtraLabel = this.treeBundle.getFormattedString('tooltip.closeTree.labeled', ['%TREE%']).split(/\s*%TREE%\s*/);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (tab.getAttribute(this.kTWISTY_HOVER) == 'true') {
|
|
||||||
let key = showTree ?
|
|
||||||
'tooltip.expandSubtree' :
|
|
||||||
'tooltip.collapseSubtree' ;
|
|
||||||
label = tree || tab.getAttribute('label');
|
|
||||||
label = label ?
|
|
||||||
this.treeBundle.getFormattedString(key+'.labeled', [label]) :
|
|
||||||
this.treeBundle.getString(key) ;
|
|
||||||
}
|
|
||||||
else if (showTree) {
|
|
||||||
label = tree;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (label) {
|
|
||||||
aEvent.target.setAttribute('label', label);
|
|
||||||
aEvent.stopPropagation();
|
|
||||||
|
|
||||||
this.showFullTooltip(aEvent.target, tab, fullTooltipExtraLabel);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
kTOOLTIP_MODE_DEFAULT : 0,
|
|
||||||
kTOOLTIP_MODE_COLLAPSED : 1,
|
|
||||||
kTOOLTIP_MODE_ALWAYS : 2,
|
|
||||||
|
|
||||||
showFullTooltip : function TSTBrowser_showFullTooltip(aBaseTooltip, aTab, aExtraLabels)
|
|
||||||
{
|
|
||||||
this.cancelFullTooltip();
|
|
||||||
|
|
||||||
var delay = this.getTreePref('tooltip.fullTooltipDelay');
|
|
||||||
if (delay < 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
var doc = this.document;
|
|
||||||
var tooltip = doc.getElementById('treestyletab-full-tree-tooltip');
|
|
||||||
tooltip.style.maxWidth = this.window.screen.availWidth+'px';
|
|
||||||
tooltip.style.maxHeight = this.window.screen.availHeight+'px';
|
|
||||||
|
|
||||||
var range = doc.createRange();
|
|
||||||
range.selectNodeContents(tooltip.firstChild);
|
|
||||||
range.deleteContents();
|
|
||||||
range.insertNode(this.createFullTooltipContents(aTab, aExtraLabels));
|
|
||||||
|
|
||||||
this._fullTooltipTimer = this.window.setTimeout(function() {
|
|
||||||
aBaseTooltip.hidePopup();
|
|
||||||
// open as a context menu popup to reposition it automatically
|
|
||||||
tooltip.openPopup(aBaseTooltip, 'overlap', 0, 0, true, false);
|
|
||||||
}, Math.max(delay, 0));
|
|
||||||
|
|
||||||
var self = this;
|
|
||||||
aBaseTooltip.addEventListener('popuphiding', function() {
|
|
||||||
aBaseTooltip.removeEventListener('popuphiding', arguments.callee, true);
|
|
||||||
self.cancelFullTooltip();
|
|
||||||
}, true);
|
|
||||||
},
|
|
||||||
cancelFullTooltip : function TSTBrowser_destroyFullTooltip()
|
|
||||||
{
|
|
||||||
if (this._fullTooltipTimer) {
|
|
||||||
this.window.clearTimeout(this._fullTooltipTimer);
|
|
||||||
this._fullTooltipTimer = null;
|
|
||||||
}
|
|
||||||
this.document.getElementById('treestyletab-full-tree-tooltip').hidePopup();
|
|
||||||
},
|
|
||||||
createFullTooltipContents : function TSTBrowser_createFullTooltipContents(aTab, aExtraLabels)
|
|
||||||
{
|
|
||||||
var doc = this.document;
|
|
||||||
|
|
||||||
const XHTMLNS = 'http://www.w3.org/1999/xhtml';
|
|
||||||
var tree = (function(aTab) {
|
|
||||||
var item = doc.createElement('hbox');
|
|
||||||
item.setAttribute('align', 'center');
|
|
||||||
var favicon = item.appendChild(doc.createElement('image'));
|
|
||||||
favicon.setAttribute('src', aTab.getAttribute('image') || 'chrome://mozapps/skin/places/defaultFavicon.png');
|
|
||||||
favicon.setAttribute('style', 'max-width:16px;max-height:16px;');
|
|
||||||
var label = item.appendChild(doc.createElement('label'));
|
|
||||||
label.setAttribute('value', aTab.label);
|
|
||||||
label.setAttribute('tooltiptext', aTab.label);
|
|
||||||
label.setAttribute('crop', 'end');
|
|
||||||
label.setAttribute('class', 'text-link');
|
|
||||||
label.addEventListener('click', function(aEvent) {
|
|
||||||
doc.defaultView.gBrowser.selectedTab = aTab; // aTab.selected = true;
|
|
||||||
}, true);
|
|
||||||
var children = this.getChildTabs(aTab);
|
|
||||||
if (children.length) {
|
|
||||||
let items = children.map(arguments.callee, this);
|
|
||||||
let childrenBox = doc.createElement('vbox');
|
|
||||||
items.forEach(function(aChild) {
|
|
||||||
childrenBox.appendChild(aChild);
|
|
||||||
});
|
|
||||||
childrenBox.setAttribute('align', 'stretch');
|
|
||||||
childrenBox.setAttribute('style', 'margin-left:1.5em');
|
|
||||||
let container = doc.createElement('vbox');
|
|
||||||
container.appendChild(item);
|
|
||||||
container.appendChild(childrenBox);
|
|
||||||
return container;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return item;
|
|
||||||
}
|
|
||||||
}).call(this, aTab);
|
|
||||||
|
|
||||||
var root = doc.createDocumentFragment();
|
|
||||||
|
|
||||||
if (aExtraLabels) {
|
|
||||||
if (typeof aExtraLabels == 'string')
|
|
||||||
aExtraLabels = [aExtraLabels];
|
|
||||||
aExtraLabels.forEach(function(aLabel) {
|
|
||||||
root.appendChild(doc.createElement('description'))
|
|
||||||
.appendChild(doc.createTextNode(aLabel));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
root.insertBefore(tree, root.firstChild && root.firstChild.nextSibling);
|
|
||||||
|
|
||||||
return root;
|
|
||||||
},
|
|
||||||
|
|
||||||
initTabContextMenu : function TSTBrowser_initTabContextMenu(aEvent)
|
initTabContextMenu : function TSTBrowser_initTabContextMenu(aEvent)
|
||||||
{
|
{
|
||||||
var b = this.mTabBrowser;
|
var b = this.mTabBrowser;
|
||||||
@ -4646,7 +4477,7 @@ TreeStyleTabBrowser.prototype = {
|
|||||||
), this);
|
), this);
|
||||||
},
|
},
|
||||||
|
|
||||||
partTabs : function TSTBrowser_partTabs(aTabs)
|
partTabs : function TSTBrowser_partTabs(aTabs)
|
||||||
{
|
{
|
||||||
var aTabs = Array.slice(aTabs);
|
var aTabs = Array.slice(aTabs);
|
||||||
for each (let tab in aTabs)
|
for each (let tab in aTabs)
|
||||||
@ -5026,7 +4857,7 @@ TreeStyleTabBrowser.prototype = {
|
|||||||
{
|
{
|
||||||
return this.moveTabsInternal(aTabs, { insertBefore : aInsertBefore });
|
return this.moveTabsInternal(aTabs, { insertBefore : aInsertBefore });
|
||||||
},
|
},
|
||||||
duplicateTabs : function TSTBrowser_duplicateTabs(aTabs, aInsertBefore) /* PUBLIC API */
|
duplicateTabs : function TSTBrowser_duplicateTabs(aTabs, aInsertBefore) /* PUBLIC API */
|
||||||
{
|
{
|
||||||
return this.moveTabsInternal(aTabs, { insertBefore : aInsertBefore, duplicate : true });
|
return this.moveTabsInternal(aTabs, { insertBefore : aInsertBefore, duplicate : true });
|
||||||
},
|
},
|
||||||
@ -5129,7 +4960,7 @@ TreeStyleTabBrowser.prototype = {
|
|||||||
return newTabs;
|
return newTabs;
|
||||||
},
|
},
|
||||||
|
|
||||||
importTab : function TSTBrowser_importTab(aTab)
|
importTab : function TSTBrowser_importTab(aTab)
|
||||||
{
|
{
|
||||||
var newTab = this.mTabBrowser.addTab();
|
var newTab = this.mTabBrowser.addTab();
|
||||||
newTab.linkedBrowser.stop();
|
newTab.linkedBrowser.stop();
|
||||||
@ -5139,7 +4970,7 @@ TreeStyleTabBrowser.prototype = {
|
|||||||
return newTab;
|
return newTab;
|
||||||
},
|
},
|
||||||
|
|
||||||
duplicateTabAsOrphan : function TSTBrowser_duplicateTabAsOrphan(aTab)
|
duplicateTabAsOrphan : function TSTBrowser_duplicateTabAsOrphan(aTab)
|
||||||
{
|
{
|
||||||
var newTab = this.mTabBrowser.duplicateTab(aTab);
|
var newTab = this.mTabBrowser.duplicateTab(aTab);
|
||||||
this.deleteTabValue(newTab, this.kCHILDREN);
|
this.deleteTabValue(newTab, this.kCHILDREN);
|
||||||
|
315
modules/fullTooltip.js
Normal file
315
modules/fullTooltip.js
Normal file
@ -0,0 +1,315 @@
|
|||||||
|
/* ***** 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 SHIMODA Hiroshi.
|
||||||
|
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||||
|
* the Initial Developer. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Contributor(s): SHIMODA Hiroshi <piro.outsider.reflex@gmail.com>
|
||||||
|
*
|
||||||
|
* 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 = ['FullTooltipManager'];
|
||||||
|
|
||||||
|
const Cc = Components.classes;
|
||||||
|
const Ci = Components.interfaces;
|
||||||
|
|
||||||
|
Components.utils.import('resource://treestyletab-modules/utils.js');
|
||||||
|
|
||||||
|
function FullTooltipManager(aOwner)
|
||||||
|
{
|
||||||
|
this.init(aOwner);
|
||||||
|
}
|
||||||
|
FullTooltipManager.prototype = {
|
||||||
|
__proto__ : TreeStyleTabUtils,
|
||||||
|
|
||||||
|
kTOOLTIP_MODE_DEFAULT : 0,
|
||||||
|
kTOOLTIP_MODE_COLLAPSED : 1,
|
||||||
|
kTOOLTIP_MODE_ALWAYS : 2,
|
||||||
|
|
||||||
|
get window()
|
||||||
|
{
|
||||||
|
return this.owner.window;
|
||||||
|
},
|
||||||
|
|
||||||
|
get document()
|
||||||
|
{
|
||||||
|
return this.owner.document;
|
||||||
|
},
|
||||||
|
|
||||||
|
get tabTooltip()
|
||||||
|
{
|
||||||
|
return this.document.getElementById('tabbrowser-tab-tooltip') || // Firefox 4.0-
|
||||||
|
this.evaluateXPath('descendant::xul:tooltip', this.mTabBrowser.mStrip, Ci.nsIDOMXPathResult.FIRST_ORDERED_NODE_TYPE).singleNodeValue; // -Firefox 3.6
|
||||||
|
},
|
||||||
|
|
||||||
|
get tabFullTooltip()
|
||||||
|
{
|
||||||
|
return this.document.getElementById('treestyletab-full-tree-tooltip');
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
init : function FTM_init(aOwner)
|
||||||
|
{
|
||||||
|
this.owner = aOwner;
|
||||||
|
|
||||||
|
this.tabTooltip.addEventListener('popupshowing', this, true);
|
||||||
|
this.tabTooltip.addEventListener('popuphiding', this, true);
|
||||||
|
this.tabFullTooltip.addEventListener('click', this, true);
|
||||||
|
this.tabFullTooltip.addEventListener('popuphiding', this, true);
|
||||||
|
},
|
||||||
|
|
||||||
|
destroy : function FTM_destroy()
|
||||||
|
{
|
||||||
|
this.tabTooltip.removeEventListener('popupshowing', this, true);
|
||||||
|
this.tabTooltip.removeEventListener('popuphiding', this, true);
|
||||||
|
this.tabFullTooltip.removeEventListener('click', this, true);
|
||||||
|
this.tabFullTooltip.removeEventListener('popuphiding', this, true);
|
||||||
|
|
||||||
|
delete this.owner;
|
||||||
|
},
|
||||||
|
|
||||||
|
handleEvent : function FTM_handleEvent(aEvent)
|
||||||
|
{
|
||||||
|
switch (aEvent.type)
|
||||||
|
{
|
||||||
|
case 'click':
|
||||||
|
return this.onClick(aEvent);
|
||||||
|
|
||||||
|
case 'popupshowing':
|
||||||
|
return this.onPopupShowing(aEvent);
|
||||||
|
|
||||||
|
case 'popuphiding':
|
||||||
|
return this.onPopupHiding(aEvent);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
onClick : function FTM_onClick(aEvent)
|
||||||
|
{
|
||||||
|
var label = this.evaluateXPath('ancestor-or-self::xul:label[@class="text-link"][1]', aEvent.target, Ci.nsIDOMXPathResult.FIRST_ORDERED_NODE_TYPE).singleNodeValue;
|
||||||
|
if (label) {
|
||||||
|
let id = label.getAttribute(this.kID);
|
||||||
|
let tab = this.getTabById(id, this.owner.browser);
|
||||||
|
if (tab)
|
||||||
|
this.owner.browser.selectedTab = tab;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.tabFullTooltip.hidePopup();
|
||||||
|
},
|
||||||
|
|
||||||
|
onPopupShowing : function FTM_onPopupShowing(aEvent)
|
||||||
|
{
|
||||||
|
this.cancel();
|
||||||
|
this.handleDefaultTooltip(aEvent);
|
||||||
|
},
|
||||||
|
|
||||||
|
onPopupHiding : function FTM_onPopupHiding(aEvent)
|
||||||
|
{
|
||||||
|
if (aEvent.target == this.tabTooltip)
|
||||||
|
this.cancel();
|
||||||
|
else if (aEvent.target == this.tabFullTooltip)
|
||||||
|
this.clear();
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
handleDefaultTooltip : function FTM_handleDefaultTooltip(aEvent)
|
||||||
|
{
|
||||||
|
var tab = this.getTabFromChild(this.document.tooltipNode);
|
||||||
|
if (!tab || tab.localName != 'tab')
|
||||||
|
return;
|
||||||
|
|
||||||
|
var label;
|
||||||
|
var collapsed = this.isSubtreeCollapsed(tab);
|
||||||
|
var mode = this.getTreePref('tooltip.mode');
|
||||||
|
var showTree = collapsed || mode == this.kTOOLTIP_MODE_ALWAYS;
|
||||||
|
|
||||||
|
var base = parseInt(tab.getAttribute(this.kNEST) || 0);
|
||||||
|
var descendant = this.getDescendantTabs(tab);
|
||||||
|
var indentPart = ' ';
|
||||||
|
var tree = null;
|
||||||
|
var fullTooltipExtraLabel = '';
|
||||||
|
if (mode > this.kTOOLTIP_MODE_DEFAULT &&
|
||||||
|
descendant.length) {
|
||||||
|
let tabs = [tab].concat(descendant);
|
||||||
|
let tabsToBeListed = tabs.slice(0, Math.max(1, this.getTreePref('tooltip.maxCount')));
|
||||||
|
tree = tabsToBeListed
|
||||||
|
.map(function(aTab) {
|
||||||
|
let label = aTab.getAttribute('label');
|
||||||
|
let indent = '';
|
||||||
|
let nest = parseInt(aTab.getAttribute(this.kNEST) || 0) - base;
|
||||||
|
for (let i = 0; i < nest; i++)
|
||||||
|
{
|
||||||
|
indent += indentPart;
|
||||||
|
}
|
||||||
|
return this.treeBundle.getFormattedString('tooltip.item.label', [label, indent]);
|
||||||
|
}, this)
|
||||||
|
.join('\n');
|
||||||
|
if (tabs.length != tabsToBeListed.length) {
|
||||||
|
tree += '\n'+indentPart+this.treeBundle.getFormattedString('tooltip.more', [tabs.length-tabsToBeListed.length]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ('mOverCloseButton' in tab && tab.mOverCloseButton) {
|
||||||
|
if (descendant.length &&
|
||||||
|
(collapsed || this.getTreePref('closeParentBehavior') == this.kCLOSE_PARENT_BEHAVIOR_CLOSE_ALL_CHILDREN)) {
|
||||||
|
label = tree || tab.getAttribute('label');
|
||||||
|
label = showTree ?
|
||||||
|
this.treeBundle.getFormattedString('tooltip.closeTree.labeled', [label]) :
|
||||||
|
this.treeBundle.getString('tooltip.closeTree') ;
|
||||||
|
if (showTree)
|
||||||
|
fullTooltipExtraLabel = this.treeBundle.getFormattedString('tooltip.closeTree.labeled', ['%TREE%']).split(/\s*%TREE%\s*/);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (tab.getAttribute(this.kTWISTY_HOVER) == 'true') {
|
||||||
|
let key = showTree ?
|
||||||
|
'tooltip.expandSubtree' :
|
||||||
|
'tooltip.collapseSubtree' ;
|
||||||
|
label = tree || tab.getAttribute('label');
|
||||||
|
label = label ?
|
||||||
|
this.treeBundle.getFormattedString(key+'.labeled', [label]) :
|
||||||
|
this.treeBundle.getString(key) ;
|
||||||
|
}
|
||||||
|
else if (showTree) {
|
||||||
|
label = tree;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!label)
|
||||||
|
return;
|
||||||
|
|
||||||
|
aEvent.target.setAttribute('label', label);
|
||||||
|
aEvent.stopPropagation();
|
||||||
|
|
||||||
|
this.setup(aEvent.target, tab, fullTooltipExtraLabel);
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
setup : function FTM_setup(aBaseTooltip, aTab, aExtraLabels)
|
||||||
|
{
|
||||||
|
this.cancel();
|
||||||
|
|
||||||
|
var delay = this.getTreePref('tooltip.fullTooltipDelay');
|
||||||
|
if (delay < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
this._fullTooltipTimer = this.window.setTimeout(function(aSelf) {
|
||||||
|
aBaseTooltip.hidePopup();
|
||||||
|
|
||||||
|
var tooltip = aSelf.tabFullTooltip;
|
||||||
|
tooltip.style.maxWidth = aSelf.window.screen.availWidth+'px';
|
||||||
|
tooltip.style.maxHeight = aSelf.window.screen.availHeight+'px';
|
||||||
|
|
||||||
|
aSelf.fill(aTab, aExtraLabels);
|
||||||
|
|
||||||
|
// open as a context menu popup to reposition it automatically
|
||||||
|
tooltip.openPopup(aBaseTooltip, 'overlap', 0, 0, true, false);
|
||||||
|
}, Math.max(delay, 0), this);
|
||||||
|
},
|
||||||
|
|
||||||
|
cancel : function FTM_destroyFullTooltip()
|
||||||
|
{
|
||||||
|
if (this._fullTooltipTimer) {
|
||||||
|
this.window.clearTimeout(this._fullTooltipTimer);
|
||||||
|
this._fullTooltipTimer = null;
|
||||||
|
}
|
||||||
|
this.tabFullTooltip.hidePopup();
|
||||||
|
},
|
||||||
|
|
||||||
|
fill : function FTM_fill(aTab, aExtraLabels)
|
||||||
|
{
|
||||||
|
this.clear();
|
||||||
|
|
||||||
|
var tree = this.createTabItem(aTab);
|
||||||
|
var root = this.document.createDocumentFragment();
|
||||||
|
|
||||||
|
if (aExtraLabels) {
|
||||||
|
if (typeof aExtraLabels == 'string')
|
||||||
|
aExtraLabels = [aExtraLabels];
|
||||||
|
aExtraLabels.forEach(function(aLabel) {
|
||||||
|
root.appendChild(this.document.createElement('description'))
|
||||||
|
.appendChild(this.document.createTextNode(aLabel));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
root.insertBefore(tree, root.firstChild && root.firstChild.nextSibling);
|
||||||
|
|
||||||
|
var range = this.document.createRange();
|
||||||
|
range.selectNodeContents(this.tabFullTooltip.firstChild);
|
||||||
|
range.insertNode(root);
|
||||||
|
range.detach();
|
||||||
|
},
|
||||||
|
|
||||||
|
clear : function FTM_clear()
|
||||||
|
{
|
||||||
|
var range = this.document.createRange();
|
||||||
|
range.selectNodeContents(this.tabFullTooltip.firstChild);
|
||||||
|
range.deleteContents();
|
||||||
|
range.detach();
|
||||||
|
},
|
||||||
|
|
||||||
|
createTabItem : function FTM_createTabItem(aTab)
|
||||||
|
{
|
||||||
|
var item = this.document.createElement('hbox');
|
||||||
|
item.setAttribute('align', 'center');
|
||||||
|
|
||||||
|
var favicon = item.appendChild(this.document.createElement('image'));
|
||||||
|
favicon.setAttribute('src', aTab.getAttribute('image') || 'chrome://mozapps/skin/places/defaultFavicon.png');
|
||||||
|
favicon.setAttribute('style', 'max-width:16px;max-height:16px;');
|
||||||
|
|
||||||
|
var label = item.appendChild(this.document.createElement('label'));
|
||||||
|
label.setAttribute('value', aTab.label);
|
||||||
|
label.setAttribute('tooltiptext', aTab.label);
|
||||||
|
label.setAttribute('crop', 'end');
|
||||||
|
label.setAttribute('class', 'text-link');
|
||||||
|
label.setAttribute(this.kID, this.getTabValue(aTab, this.kID));
|
||||||
|
|
||||||
|
var children = this.createTabChildren(aTab);
|
||||||
|
if (children) {
|
||||||
|
let container = this.document.createElement('vbox');
|
||||||
|
container.appendChild(item);
|
||||||
|
container.appendChild(children);
|
||||||
|
return container;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
createTabChildren : function FTM_createTabChildren(aTab)
|
||||||
|
{
|
||||||
|
var children = this.getChildTabs(aTab);
|
||||||
|
if (!children.length)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
var container = this.document.createElement('vbox');
|
||||||
|
children.forEach(function(aChild) {
|
||||||
|
container.appendChild(this.createTabItem(aChild));
|
||||||
|
}, this);
|
||||||
|
container.setAttribute('align', 'stretch');
|
||||||
|
container.setAttribute('style', 'margin-left:1.5em');
|
||||||
|
return container;
|
||||||
|
}
|
||||||
|
};
|
Loading…
x
Reference in New Issue
Block a user