XPathを使った簡潔な実装と、XPathを使わない高速な実装の両方を1箇所に記述するようにした

git-svn-id: http://www.cozmixng.org/repos/piro/treestyletab/trunk@6423 599a83e7-65a4-db11-8015-0010dcdd6dc2
This commit is contained in:
piro 2010-03-24 15:38:08 +00:00
parent 4f65a3a9a1
commit ea4d6ae68b
2 changed files with 201 additions and 144 deletions

View File

@ -133,29 +133,6 @@ TreeStyleTabBrowser.prototype = {
{ {
return false; return false;
}, },
getTabById : function TSTBrowser_getTabById(aId, aTabBrowserChildren) /* PUBLIC API */
{
if (aTabBrowserChildren && !(aTabBrowserChildren instanceof Ci.nsIDOMNode))
aTabBrowserChildren = null;
if (aTabBrowserChildren) {
var b = this.getTabBrowserFromChild(aTabBrowserChildren);
if (!b)
return null;
if (b != this.mTabBrowser)
return b.treeStyleTab.getTabById(aId);
}
return this._tabsCache[aId] || null;
},
getParentTab : function TSTBrowser_getParentTab(aTab) /* PUBLIC API */
{
if (!aTab) return null;
var b = this.getTabBrowserFromChild(aTab);
return b.treeStyleTab.getTabById(aTab.getAttribute(this.kPARENT));
},
/* initialize */ /* initialize */
@ -166,7 +143,7 @@ TreeStyleTabBrowser.prototype = {
var b = this.mTabBrowser; var b = this.mTabBrowser;
b.tabContainer.treeStyleTab = this; b.tabContainer.treeStyleTab = this;
this._tabsCache = {}; this.tabsHash = {};
this.internallyTabMovingCount = 0; this.internallyTabMovingCount = 0;
this.subTreeMovingCount = 0; this.subTreeMovingCount = 0;
@ -695,12 +672,12 @@ TreeStyleTabBrowser.prototype = {
window.setTimeout(function(aSelf) { window.setTimeout(function(aSelf) {
if (!aSelf.getTabValue(aTab, aSelf.kID)) { if (!aSelf.getTabValue(aTab, aSelf.kID)) {
aSelf.setTabValue(aTab, aSelf.kID, id); aSelf.setTabValue(aTab, aSelf.kID, id);
if (!(id in aSelf._tabsCache)) if (!(id in aSelf.tabsHash))
aSelf._tabsCache[id] = aTab; aSelf.tabsHash[id] = aTab;
} }
}, 0, this); }, 0, this);
if (!(id in this._tabsCache)) if (!(id in this.tabsHash))
this._tabsCache[id] = aTab; this.tabsHash[id] = aTab;
} }
aTab.__treestyletab__linkedTabBrowser = this.mTabBrowser; aTab.__treestyletab__linkedTabBrowser = this.mTabBrowser;
@ -1329,8 +1306,8 @@ TreeStyleTabBrowser.prototype = {
destroyTab : function TSTBrowser_destroyTab(aTab) destroyTab : function TSTBrowser_destroyTab(aTab)
{ {
var id = aTab.getAttribute(this.kID); var id = aTab.getAttribute(this.kID);
if (id in this._tabsCache) if (id in this.tabsHash)
delete this._tabsCache[id]; delete this.tabsHash[id];
delete aTab.__treestyletab__linkedTabBrowser; delete aTab.__treestyletab__linkedTabBrowser;
}, },
@ -2197,7 +2174,7 @@ TreeStyleTabBrowser.prototype = {
this.deleteTabValue(tab, this.kCLOSED_SET_ID); this.deleteTabValue(tab, this.kCLOSED_SET_ID);
this.setTabValue(tab, this.kID, id); this.setTabValue(tab, this.kID, id);
this._tabsCache[id] = tab; this.tabsHash[id] = tab;
if (closeSetId) if (closeSetId)
this.restoreClosedSet(closeSetId, tab); this.restoreClosedSet(closeSetId, tab);

View File

@ -51,6 +51,7 @@ Components.utils.import('resource://treestyletab-modules/stringBundle.js', strin
stringBundle = stringBundle.window['piro.sakura.ne.jp'].stringBundle; stringBundle = stringBundle.window['piro.sakura.ne.jp'].stringBundle;
var TreeStyleTabUtils = { var TreeStyleTabUtils = {
tabsHash : null,
/* attributes */ /* attributes */
kID : 'treestyletab-id', kID : 'treestyletab-id',
@ -845,12 +846,20 @@ var TreeStyleTabUtils = {
getTabById : function TSTUtils_getTabById(aId, aTabBrowserChildren) getTabById : function TSTUtils_getTabById(aId, aTabBrowserChildren)
{ {
if (!aId) return null; if (!aId) return null;
if (aTabBrowserChildren && !(aTabBrowserChildren instanceof Ci.nsIDOMNode))
aTabBrowserChildren = null;
var b = this.getTabBrowserFromChild(aTabBrowserChildren) || this.browser; var b = this.getTabBrowserFromChild(aTabBrowserChildren) || this.browser;
if (this.tabsHash) // XPath-less implementation
return this.tabsHash[aId] || null;
return this.evaluateXPath( return this.evaluateXPath(
'descendant::xul:tab[@'+this.kID+' = "'+aId+'"]', 'descendant::xul:tab[@'+this.kID+' = "'+aId+'"]',
b.mTabContainer, b.mTabContainer,
Ci.nsIDOMXPathResult.FIRST_ORDERED_NODE_TYPE Ci.nsIDOMXPathResult.FIRST_ORDERED_NODE_TYPE
).singleNodeValue; ).singleNodeValue;
}, },
isTabDuplicated : function TSTUtils_isTabDuplicated(aTab) isTabDuplicated : function TSTUtils_isTabDuplicated(aTab)
@ -859,19 +868,19 @@ var TreeStyleTabUtils = {
var id = this.getTabValue(aTab, this.kID); var id = this.getTabValue(aTab, this.kID);
var b = this.getTabBrowserFromChild(aTab) || this.browser; var b = this.getTabBrowserFromChild(aTab) || this.browser;
return this.evaluateXPath( return this.evaluateXPath(
'count(descendant::xul:tab[@'+this.kID+' = "'+id+'" or @'+this.kID_RESTORING+' = "'+id+'"]) > 1', 'count(descendant::xul:tab[@'+this.kID+' = "'+id+'" or @'+this.kID_RESTORING+' = "'+id+'"]) > 1',
b.mTabContainer, b.mTabContainer,
Ci.nsIDOMXPathResult.BOOLEAN_TYPE Ci.nsIDOMXPathResult.BOOLEAN_TYPE
).booleanValue; ).booleanValue;
}, },
getTabs : function TSTUtils_getTabs(aTabBrowserChild) /* OBSOLETE */ getTabs : function TSTUtils_getTabs(aTabBrowserChild) /* OBSOLETE */
{ {
var b = this.getTabBrowserFromChild(aTabBrowserChild); var b = this.getTabBrowserFromChild(aTabBrowserChild);
return this.evaluateXPath( return this.evaluateXPath(
'descendant::xul:tab', 'descendant::xul:tab',
b.mTabContainer b.mTabContainer
); );
}, },
getTabsArray : function TSTUtils_getTabsArray(aTabBrowserChild) getTabsArray : function TSTUtils_getTabsArray(aTabBrowserChild)
@ -1259,85 +1268,118 @@ var TreeStyleTabUtils = {
getParentTab : function TSTUtils_getParentTab(aTab) /* PUBLIC API */ getParentTab : function TSTUtils_getParentTab(aTab) /* PUBLIC API */
{ {
if (!aTab) return null; if (!aTab) return null;
var id = aTab.getAttribute(this.kID);
if (!id) return null; // not initialized yet if (this.tabsHash) { // XPath-less implementation
let parent = this.getTabById(aTab.getAttribute(this.kPARENT));
return (parent && parent._tPos < aTab._tPos) ? parent : null ;
}
return this.evaluateXPath( return this.evaluateXPath(
'preceding-sibling::xul:tab[contains('+ 'preceding-sibling::xul:tab[@'+this.kID+'="'++'"][1]',
'concat("|", @'+this.kCHILDREN+', "|"),'+ aTab,
'"|'+id+'|"'+ Ci.nsIDOMXPathResult.FIRST_ORDERED_NODE_TYPE
')][1]', ).singleNodeValue;
aTab,
Ci.nsIDOMXPathResult.FIRST_ORDERED_NODE_TYPE
).singleNodeValue;
}, },
getRootTab : function TSTUtils_getRootTab(aTab) /* PUBLIC API */ getRootTab : function TSTUtils_getRootTab(aTab) /* PUBLIC API */
{ {
var parent = aTab; if (!aTab) return null;
var root = aTab;
while (parent = this.getParentTab(parent)) if (this.tabsHash) { // XPath-less implementation
{ let parent = aTab;
root = parent; let root = aTab;
while (parent = this.getParentTab(parent))
{
root = parent;
}
return root;
} }
return root;
return this.evaluateXPath(
'(self::*[not(@'+this.kPARENT+')] | preceding-sibling::xul:tab[not(@'+this.kPARENT+')])[last()]',
aTab,
Ci.nsIDOMXPathResult.FIRST_ORDERED_NODE_TYPE
).singleNodeValue;
}, },
getNextSiblingTab : function TSTUtils_getNextSiblingTab(aTab) /* PUBLIC API */ getNextSiblingTab : function TSTUtils_getNextSiblingTab(aTab) /* PUBLIC API */
{ {
if (!aTab) return null; if (!aTab) return null;
var parentTab = this.getParentTab(aTab); if (this.tabsHash) { // XPath-less implementation
let parentTab = this.getParentTab(aTab);
if (!parentTab) { if (!parentTab) {
let next = aTab; let next = aTab;
do { do {
next = next.nextSibling; next = next.nextSibling;
}
while (next &&
next.nodeType == Ci.nsIDOMNode.ELEMENT_NODE &&
this.getParentTab(next));
return next;
} }
while (next &&
next.nodeType == Ci.nsIDOMNode.ELEMENT_NODE && let children = parentTab.getAttribute(this.kCHILDREN);
this.getParentTab(next)); if (children) {
return next; let list = ('|'+children).split('|'+aTab.getAttribute(this.kID))[1].split('|');
for (let i = 0, maxi = list.length; i < maxi; i++)
{
let firstChild = this.getTabById(list[i], aTab);
if (firstChild) return firstChild;
}
}
return null;
} }
var children = parentTab.getAttribute(this.kCHILDREN); var parent = aTab.getAttribute(this.kPARENT);
if (children) { return this.evaluateXPath(
let list = ('|'+children).split('|'+aTab.getAttribute(this.kID))[1].split('|'); 'following-sibling::xul:tab['+
for (let i = 0, maxi = list.length; i < maxi; i++) (parent ? '@'+this.kPARENT+'="'+parent+'"' : 'not(@'+this.kPARENT+')' )+
{ '][1]',
let firstChild = this.getTabById(list[i], aTab); aTab,
if (firstChild) return firstChild; Ci.nsIDOMXPathResult.FIRST_ORDERED_NODE_TYPE
} ).singleNodeValue;
}
return null;
}, },
getPreviousSiblingTab : function TSTUtils_getPreviousSiblingTab(aTab) /* PUBLIC API */ getPreviousSiblingTab : function TSTUtils_getPreviousSiblingTab(aTab) /* PUBLIC API */
{ {
if (!aTab) return null; if (!aTab) return null;
var parentTab = this.getParentTab(aTab); if (this.tabsHash) { // XPath-less implementation
let parentTab = this.getParentTab(aTab);
if (!parentTab) { if (!parentTab) {
let prev = aTab; let prev = aTab;
do { do {
prev = prev.previousSibling; prev = prev.previousSibling;
}
while (prev &&
prev.nodeType == Ci.nsIDOMNode.ELEMENT_NODE &&
this.getParentTab(prev));
return prev;
} }
while (prev &&
prev.nodeType == Ci.nsIDOMNode.ELEMENT_NODE && let children = parentTab.getAttribute(this.kCHILDREN);
this.getParentTab(prev)); if (children) {
return prev; let list = ('|'+children).split('|'+aTab.getAttribute(this.kID))[0].split('|');
for (let i = list.length-1; i > -1; i--)
{
let lastChild = this.getTabById(list[i], aTab);
if (lastChild) return lastChild;
}
}
return null;
} }
var children = parentTab.getAttribute(this.kCHILDREN); var parent = aTab.getAttribute(this.kPARENT);
if (children) { return this.evaluateXPath(
let list = ('|'+children).split('|'+aTab.getAttribute(this.kID))[0].split('|'); 'preceding-sibling::xul:tab['+
for (let i = list.length-1; i > -1; i--) (parent ? '@'+this.kPARENT+'="'+parent+'"' : 'not(@'+this.kPARENT+')' )+
{ '][1]',
let lastChild = this.getTabById(list[i], aTab); aTab,
if (lastChild) return lastChild; Ci.nsIDOMXPathResult.FIRST_ORDERED_NODE_TYPE
} ).singleNodeValue;
}
return null;
}, },
getChildTabs : function TSTUtils_getChildTabs(aTab, aAllTabsArray) /* PUBLIC API */ getChildTabs : function TSTUtils_getChildTabs(aTab, aAllTabsArray) /* PUBLIC API */
@ -1380,76 +1422,114 @@ var TreeStyleTabUtils = {
{ {
if (!aTab) return null; if (!aTab) return null;
var children = aTab.getAttribute(this.kCHILDREN); if (this.tabsHash) { // XPath-less implementation
var firstChild = null; let children = aTab.getAttribute(this.kCHILDREN);
if (children) { let firstChild = null;
let list = children.split('|'); if (children) {
for (let i = 0, maxi = list.length; i < maxi; i++) let list = children.split('|');
{ for (let i = 0, maxi = list.length; i < maxi; i++)
firstChild = this.getTabById(list[i], aTab); {
if (firstChild) break; firstChild = this.getTabById(list[i], aTab);
if (firstChild) break;
}
} }
return firstChild;
} }
return firstChild;
return this.evaluateXPath(
'following-sibling::xul:tab[@'+this.kPARENT+'="'+aTab.getAttribute(this.kID)+'"][1]',
aTab,
Ci.nsIDOMXPathResult.FIRST_ORDERED_NODE_TYPE
).singleNodeValue;
}, },
getLastChildTab : function TSTUtils_getLastChildTab(aTab) /* PUBLIC API */ getLastChildTab : function TSTUtils_getLastChildTab(aTab) /* PUBLIC API */
{ {
if (!aTab) return null; if (!aTab) return null;
var children = aTab.getAttribute(this.kCHILDREN); if (this.tabsHash) { // XPath-less implementation
var lastChild = null; let children = aTab.getAttribute(this.kCHILDREN);
if (children) { let lastChild = null;
let list = children.split('|'); if (children) {
for (let i = list.length-1; i > -1; i--) let list = children.split('|');
{ for (let i = list.length-1; i > -1; i--)
lastChild = this.getTabById(list[i], aTab); {
if (lastChild) break; lastChild = this.getTabById(list[i], aTab);
if (lastChild) break;
}
} }
return lastChild;
} }
return lastChild;
return this.evaluateXPath(
'following-sibling::xul:tab[@'+this.kPARENT+'="'+aTab.getAttribute(this.kID)+'"][last()]',
aTab,
Ci.nsIDOMXPathResult.FIRST_ORDERED_NODE_TYPE
).singleNodeValue;
}, },
getLastDescendantTab : function TSTUtils_getLastDescendantTab(aTab) /* PUBLIC API */ getLastDescendantTab : function TSTUtils_getLastDescendantTab(aTab) /* PUBLIC API */
{ {
if (!aTab) return null; if (!aTab) return null;
var tabs = this.getDescendantTabs(aTab); if (this.tabsHash) { // XPath-less implementation
return tabs.length ? tabs[tabs.length-1] : null ; let tabs = this.getDescendantTabs(aTab);
}, return tabs.length ? tabs[tabs.length-1] : null ;
getChildIndex : function TSTUtils_getChildIndex(aTab, aParent)
{
var parent = this.getParentTab(aTab);
if (!aParent || !parent || aParent != parent) {
parent = aTab;
while (parent && parent != aParent)
{
aTab = parent;
parent = this.getParentTab(parent);
}
if (parent != aParent)
return -1;
aParent = parent;
} }
if (aParent) { var parent = aTab.getAttribute(this.kPARENT);
let children = aParent.getAttribute(this.kCHILDREN); return this.evaluateXPath(
let list = children.split('|'); 'following-sibling::xul:tab['+
let id = aTab.getAttribute(this.kID); (parent ? '@'+this.kPARENT+'="'+parent+'"' : 'not(@'+this.kPARENT+')' )+
for (let i = 0, maxi = list.length; i < maxi; i++) '][1]/preceding-sibling::xul:tab[1][not(@'+this.kID+'="'+aTab.getAttribute(this.kID)+'")]',
{ aTab,
if (list[i] == id) return i; Ci.nsIDOMXPathResult.FIRST_ORDERED_NODE_TYPE
).singleNodeValue;
},
getChildIndex : function TSTUtils_getChildIndex(aTab, aParent) /* PUBLIC API */
{
if (this.tabsHash) { // XPath-less implementation
let parent = this.getParentTab(aTab);
if (!aParent || !parent || aParent != parent) {
parent = aTab;
while (parent && parent != aParent)
{
aTab = parent;
parent = this.getParentTab(parent);
}
if (parent != aParent)
return -1;
aParent = parent;
}
if (aParent) {
let children = aParent.getAttribute(this.kCHILDREN);
let list = children.split('|');
let id = aTab.getAttribute(this.kID);
for (let i = 0, maxi = list.length; i < maxi; i++)
{
if (list[i] == id) return i;
}
return -1;
}
else {
let tabs = this.rootTabs;
for (let i = 0, maxi = tabs.length; i < maxi; i++)
{
if (tabs[i] == aTab) return i;
}
} }
return -1; return -1;
} }
else {
let tabs = this.rootTabs; var parent = aTab.getAttribute(this.kPARENT);
for (let i = 0, maxi = tabs.length; i < maxi; i++) if (!parent) return -1;
{ return this.evaluateXPath(
if (tabs[i] == aTab) return i; 'count(preceding-sibling::xul:tab[@'+this.kPARENT+' and @'+this.kPARENT+'="'+parent+'"])',
} aTab,
} Ci.nsIDOMXPathResult.NUMBER_TYPE
).numberValue;
}, },
getXOffsetOfTab : function TSTUtils_getXOffsetOfTab(aTab) getXOffsetOfTab : function TSTUtils_getXOffsetOfTab(aTab)