マルチプルタブハンドラが導入されている場合、コンテキストメニューやタブの選択メニューからサブツリーを閉じられるようにした

git-svn-id: http://www.cozmixng.org/repos/piro/treestyletab/trunk@1233 599a83e7-65a4-db11-8015-0010dcdd6dc2
This commit is contained in:
piro 2007-10-19 05:27:06 +00:00
parent d146e00622
commit 7578fb9ad8
7 changed files with 172 additions and 83 deletions

View File

@ -1,6 +1,7 @@
content treestyletab jar:chrome/treestyletab.jar!/content/treestyletab/ content treestyletab jar:chrome/treestyletab.jar!/content/treestyletab/
overlay chrome://browser/content/browser.xul chrome://treestyletab/content/treestyletab.xul overlay chrome://browser/content/browser.xul chrome://treestyletab/content/treestyletab.xul
overlay chrome://multipletab/content/config.xul chrome://treestyletab/content/multipletabConfigOverlay.xul
locale treestyletab en-US jar:chrome/treestyletab.jar!/locale/en-US/treestyletab/ locale treestyletab en-US jar:chrome/treestyletab.jar!/locale/en-US/treestyletab/
locale treestyletab ja jar:chrome/treestyletab.jar!/locale/ja/treestyletab/ locale treestyletab ja jar:chrome/treestyletab.jar!/locale/ja/treestyletab/

View File

@ -0,0 +1,27 @@
<?xml version="1.0"?>
<!DOCTYPE overlay SYSTEM "chrome://treestyletab/locale/treestyletab.dtd">
<overlay xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<preferences id="prefpane-selection-menu-preferences">
<preference id="extensions.multipletab.show.multipletab-selection-item-removeTabSubTree"
name="extensions.multipletab.show.multipletab-selection-item-removeTabSubTree"
type="bool"/>
</preferences>
<vbox id="prefpane-selection-menu-items">
<checkbox id="extensions.multipletab.show.multipletab-selection-item-removeTabSubTree-check"
preference="extensions.multipletab.show.multipletab-selection-item-removeTabSubTree"
label="&selection.removeTabSubTree.label;"/>
</vbox>
<preferences id="prefpane-context-menu-preferences">
<preference id="extensions.multipletab.show.context-item-removeTabSubTree"
name="extensions.multipletab.show.context-item-removeTabSubTree"
type="bool"/>
</preferences>
<vbox id="prefpane-context-menu-items">
<checkbox id="extensions.multipletab.show.context-item-removeTabSubTree-check"
preference="extensions.multipletab.show.context-item-removeTabSubTree"
label="&context.removeTabSubTree.label;"/>
</vbox>
</overlay>

View File

@ -11,6 +11,9 @@ var TreeStyleTabService = {
kTWISTY : 'treestyletab-tab-tree-twisty', kTWISTY : 'treestyletab-tab-tree-twisty',
kTWISTY_CONTAINER : 'treestyletab-tab-tree-twisty-container', kTWISTY_CONTAINER : 'treestyletab-tab-tree-twisty-container',
kMENUITEM_REMOVESUBTREE_MULTIPLETAB_SELECTION : 'multipletab-selection-item-removeTabSubTree',
kMENUITEM_REMOVESUBTREE_CONTEXT : 'context-item-removeTabSubTree',
kFOCUS_ALL : 0, kFOCUS_ALL : 0,
kFOCUS_VISIBLE : 1, kFOCUS_VISIBLE : 1,
@ -152,61 +155,22 @@ var TreeStyleTabService = {
return (target.localName == 'tabbrowser') ? target : null ; return (target.localName == 'tabbrowser') ? target : null ;
}, },
showHideMenuItems : function(aPopup) cleanUpTabsArray : function(aTabs)
{ {
var nodes = aPopup.childNodes; var b = this.getTabBrowserFromChildren(aTabs[0]);
var pref;
var b = this.getTabBrowserFromChildren(aPopup) || this.browser; var self = this;
var box = b.mTabContainer.mTabstrip || b.mTabContainer ; aTabs = aTabs.map(function(aTab) { return aTab.getAttribute(self.kID); });
var isVertical = ((box.getAttribute('orient') || window.getComputedStyle(box, '').getPropertyValue('-moz-box-orient')) == 'vertical'); aTabs.sort();
aTabs = aTabs.join('|').replace(/([^\|]+)(\|\1)+/g, '$1').split('|');
var label; for (var i = 0, maxi = aTabs.length; i < maxi; i++)
for (var i = 0, maxi = nodes.length; i < maxi; i++)
{ {
if ( aTabs[i] = this.getTabById(aTabs[i], b);
(isVertical && (label = nodes[i].getAttribute('label-vertical'))) ||
(!isVertical && (label = nodes[i].getAttribute('label-horizontal')))
)
nodes[i].setAttribute('label', label);
pref = this.getPref('extensions.multipletab.show.'+nodes[i].getAttribute('id').replace(/-tabbrowser[0-9]+$/, ''));
if (pref === null) continue;
if (pref)
nodes[i].removeAttribute('hidden');
else
nodes[i].setAttribute('hidden', true);
}
var separators = this.getSeparators(aPopup);
for (var i = separators.snapshotLength-1; i > -1; i--)
{
separators.snapshotItem(i).removeAttribute('hidden');
}
var separator;
while (separator = this.getObsoleteSeparator(aPopup))
{
separator.setAttribute('hidden', true);
} }
return aTabs;
}, },
getSeparators : function(aPopup)
{
return this.evaluateXPath('descendant::xul:menuseparator', aPopup);
},
getObsoleteSeparator : function(aPopup)
{
return this.evaluateXPath(
'descendant::xul:menuseparator[not(@hidden)][not(following-sibling::*[not(@hidden)]) or not(preceding-sibling::*[not(@hidden)]) or local-name(following-sibling::*[not(@hidden)]) = "menuseparator"]',
aPopup,
XPathResult.FIRST_ORDERED_NODE_TYPE
).singleNodeValue;
},
/* Initializing */ /* Initializing */
init : function() init : function()
@ -222,18 +186,19 @@ var TreeStyleTabService = {
this.addPrefListener(this); this.addPrefListener(this);
this.observe(null, 'nsPref:changed', 'extensions.treestyletab.'); this.observe(null, 'nsPref:changed', 'extensions.treestyletab.');
eval('window.nsBrowserAccess.prototype.openURI = '+ eval('window.nsBrowserAccess.prototype.openURI = '+
window.nsBrowserAccess.prototype.openURI.toSource().replace( window.nsBrowserAccess.prototype.openURI.toSource().replace(
/switch\s*\(aWhere\)/, /switch\s*\(aWhere\)/,
<><![CDATA[ <><![CDATA[
if (aOpener && if (aOpener &&
aWhere == Components.interfaces.nsIBrowserDOMWindow.OPEN_NEWTAB) { aWhere == Components.interfaces.nsIBrowserDOMWindow.OPEN_NEWTAB) {
var ownerBrowser = ('SplitBrowser' in window) ? TreeStyleTabService.getTabBrowserFromChildren(SplitBrowser.getSubBrowserAndBrowserFromFrame(aOpener.top).browser) : gBrowser ; (function(aOpener) {
var parentTab = TreeStyleTabService.getTabFromFrame(aOpener, ownerBrowser); var ownerBrowser = ('SplitBrowser' in window) ? TreeStyleTabService.getTabBrowserFromChildren(SplitBrowser.getSubBrowserAndBrowserFromFrame(aOpener.top).browser) : gBrowser ;
var parentTab = TreeStyleTabService.getTabFromFrame(aOpener, ownerBrowser);
ownerBrowser.__treestyletab__readyToAdoptNewTab = true; ownerBrowser.__treestyletab__readyToAdoptNewTab = true;
ownerBrowser.__treestyletab__parentTab = parentTab.getAttribute(TreeStyleTabService.kID); ownerBrowser.__treestyletab__parentTab = parentTab.getAttribute(TreeStyleTabService.kID);
})(aOpener);
} }
switch(aWhere) switch(aWhere)
]]></> ]]></>
@ -242,6 +207,48 @@ var TreeStyleTabService = {
window.QueryInterface(Components.interfaces.nsIDOMChromeWindow).browserDOMWindow = null; window.QueryInterface(Components.interfaces.nsIDOMChromeWindow).browserDOMWindow = null;
window.QueryInterface(Components.interfaces.nsIDOMChromeWindow).browserDOMWindow = new nsBrowserAccess(); window.QueryInterface(Components.interfaces.nsIDOMChromeWindow).browserDOMWindow = new nsBrowserAccess();
if ('MultipleTabService' in window) {
eval('MultipleTabService.showHideMenuItems = '+
MultipleTabService.showHideMenuItems.toSource().replace(
/var separators = /,
<><![CDATA[
(function(aPopup) {
var b;
var item;
var tabs;
if (aPopup.id == 'multipletab-selection-menu') {
b = MultipleTabService.browser;
item = document.getElementById(TreeStyleTabService.kMENUITEM_REMOVESUBTREE_MULTIPLETAB_SELECTION);
tabs = MultipleTabService.getSelectedTabs();
}
else { // context
b = TreeStyleTabService.getTabBrowserFromChildren(aPopup);
item = TreeStyleTabService.evaluateXPath(
'descendant::xul:menuitem[starts-with(@id, "'+TreeStyleTabService.kMENUITEM_REMOVESUBTREE_CONTEXT+'")]',
aPopup,
XPathResult.FIRST_ORDERED_NODE_TYPE
).singleNodeValue;
tabs = [b.mContextTab];
}
if (item.getAttribute('hidden') == 'true') return;
var hasSubTree = false;
for (var i = 0, maxi = tabs.length; i < maxi; i++)
{
if (!tabs[i].hasAttribute(TreeStyleTabService.kCHILDREN)) continue;
hasSubTree = true;
break;
}
if (hasSubTree)
item.removeAttribute('hidden');
else
item.setAttribute('hidden', true);
})(aPopup);
var separators = ]]></>
)
);
}
this.initTabBrowser(gBrowser); this.initTabBrowser(gBrowser);
}, },
@ -275,30 +282,31 @@ var TreeStyleTabService = {
/\{/, /\{/,
<><![CDATA[ <><![CDATA[
{ {
if (TreeStyleTabService.getPref('extensions.treestyletab.focusMode') == 1) { if (TreeStyleTabService.getPref('extensions.treestyletab.focusMode') == TreeStyleTabService.kFOCUS_VISIBLE) {
var xpathResult = TreeStyleTabService.evaluateXPath( (function(aDir, aWarp, aSelf) {
(arguments[0] < 0 ? 'preceding-sibling' : 'following-sibling' )+
'::xul:tab[not(@'+TreeStyleTabService.kCOLLAPSED+'="true")]',
this.selectedItem
);
var nextTab = xpathResult.snapshotItem(arguments[0] < 0 ? xpathResult.snapshotLength-1 : 0 );
if (!nextTab && arguments[1]) {
var xpathResult = TreeStyleTabService.evaluateXPath( var xpathResult = TreeStyleTabService.evaluateXPath(
'child::xul:tab[not(@'+TreeStyleTabService.kCOLLAPSED+'="true")]', (aDir < 0 ? 'preceding-sibling' : 'following-sibling' )+
this '::xul:tab[not(@'+TreeStyleTabService.kCOLLAPSED+'="true")]',
); aSelf.selectedItem
nextTab = xpathResult.snapshotItem(arguments[0] < 0 ? xpathResult.snapshotLength-1 : 0 ); );
} var nextTab = xpathResult.snapshotItem(aDir < 0 ? xpathResult.snapshotLength-1 : 0 );
if (nextTab && nextTab != this.selectedItem) { if (!nextTab && aWarp) {
this.selectNewTab(nextTab, arguments[0], arguments[1]); var xpathResult = TreeStyleTabService.evaluateXPath(
} 'child::xul:tab[not(@'+TreeStyleTabService.kCOLLAPSED+'="true")]',
aSelf
);
nextTab = xpathResult.snapshotItem(aDir < 0 ? xpathResult.snapshotLength-1 : 0 );
}
if (nextTab && nextTab != aSelf.selectedItem) {
aSelf.selectNewTab(nextTab, aDir, aWarp);
}
})(arguments[0], arguments[1], this);
return; return;
} }
]]></> ]]></>
) )
); );
var addTabMethod = 'addTab'; var addTabMethod = 'addTab';
var removeTabMethod = 'removeTab'; var removeTabMethod = 'removeTab';
if (aTabBrowser.__tabextensions__addTab) { if (aTabBrowser.__tabextensions__addTab) {
@ -330,25 +338,19 @@ var TreeStyleTabService = {
return retVal; return retVal;
}; };
// var tabContextMenu = document.getAnonymousElementByAttribute(aTabBrowser, 'anonid', 'tabContextMenu');
// tabContextMenu.addEventListener('popupshowing', this, false);
var tabs = aTabBrowser.mTabContainer.childNodes; var tabs = aTabBrowser.mTabContainer.childNodes;
for (var i = 0, maxi = tabs.length; i < maxi; i++) for (var i = 0, maxi = tabs.length; i < maxi; i++)
{ {
this.initTab(tabs[i], aTabBrowser); this.initTab(tabs[i], aTabBrowser);
} }
delete addTabMethod; delete addTabMethod;
delete removeTabMethod; delete removeTabMethod;
delete i; delete i;
delete maxi; delete maxi;
delete tabs; delete tabs;
}, },
initTab : function(aTab, aTabBrowser) initTab : function(aTab, aTabBrowser)
{ {
var id = 'tab-<'+Date.now()+'-'+parseInt(Math.random() * 65000)+'>'; var id = 'tab-<'+Date.now()+'-'+parseInt(Math.random() * 65000)+'>';
@ -395,7 +397,7 @@ var TreeStyleTabService = {
this.destroyTab(tabs[i]); this.destroyTab(tabs[i]);
} }
}, },
destroyTabBrowser : function(aTabBrowser) destroyTabBrowser : function(aTabBrowser)
{ {
var tabs = aTabBrowser.mTabContainer.childNodes; var tabs = aTabBrowser.mTabContainer.childNodes;
@ -415,11 +417,8 @@ var TreeStyleTabService = {
aTabBrowser.mTabContainer.removeEventListener('mousedown', this, true); aTabBrowser.mTabContainer.removeEventListener('mousedown', this, true);
aTabBrowser.mTabContainer.removeEventListener('select', this, true); aTabBrowser.mTabContainer.removeEventListener('select', this, true);
aTabBrowser.mPanelContainer.removeEventListener('click', this, true); aTabBrowser.mPanelContainer.removeEventListener('click', this, true);
// var tabContextMenu = document.getAnonymousElementByAttribute(aTabBrowser, 'anonid', 'tabContextMenu');
// tabContextMenu.removeEventListener('popupshowing', this, false);
}, },
destroyTab : function(aTab, aTabBrowser) destroyTab : function(aTab, aTabBrowser)
{ {
delete aTab.__treestyletab__linkedTabBrowser; delete aTab.__treestyletab__linkedTabBrowser;
@ -980,6 +979,36 @@ var TreeStyleTabService = {
b.__treestyletab__isSubTreeMoving = false; b.__treestyletab__isSubTreeMoving = false;
}, },
removeTabSubTree : function(aTabOrTabs)
{
var tabs = aTabOrTabs;
if (!(tabs instanceof Array)) {
tabs = [aTabOrTabs];
}
var descendant = [];
for (var i = 0, maxi = tabs.length; i < maxi; i++)
{
descendant = descendant.concat(this.getDescendantTabsOf(tabs[i]));
}
tabs = this.cleanUpTabsArray(tabs.concat(descendant));
var max = tabs.length;
if (!max) return;
var b = this.getTabBrowserFromChildren(tabs[0]);
if (
max > 1 &&
!b.warnAboutClosingTabs(true, max)
)
return;
for (var i = tabs.length-1; i > -1; i--)
{
b.removeTab(tabs[i]);
}
},
collapseExpandTabSubTree : function(aTab, aCollapse) collapseExpandTabSubTree : function(aTab, aCollapse)
{ {
if (!aTab) return; if (!aTab) return;

View File

@ -8,4 +8,20 @@
<script src="treestyletab.js" type="application/x-javascript"/> <script src="treestyletab.js" type="application/x-javascript"/>
<menupopup id="multipletab-selection-menu">
<menuitem id="multipletab-selection-item-removeTabSubTree"
insertafter="multipletab-selection-removeTabs"
label="&selection.removeTabSubTree.label;"
accesskey="&selection.removeTabSubTree.accesskey;"
oncommand="TreeStyleTabService.removeTabSubTree(MultipleTabService.getSelectedTabs());"/>
</menupopup>
<menupopup id="multipletab-tabcontext-menu-template">
<menuitem id="context-item-removeTabSubTree"
label="&context.removeTabSubTree.label;"
accesskey="&context.removeTabSubTree.accesskey;"
oncommand="TreeStyleTabService.removeTabSubTree(TreeStyleTabService.getTabBrowserFromChildren(this).mContextTab);"/>
</menupopup>
</overlay> </overlay>

View File

@ -6,6 +6,8 @@ pref("extensions.treestyletab.focusMode", 1);
pref("browser.link.open_newwindow.restriction", 0); pref("browser.link.open_newwindow.restriction", 0);
pref("extensions.multipletab.show.multipletab-selection-item-removeTabSubTree", true);
pref("extensions.multipletab.show.context-item-removeTabSubTree", true);
pref("extensions.treestyletab@piro.sakura.ne.jp.name", "chrome://treestyletab/locale/treestyletab.properties"); pref("extensions.treestyletab@piro.sakura.ne.jp.name", "chrome://treestyletab/locale/treestyletab.properties");
pref("extensions.treestyletab@piro.sakura.ne.jp.description", "chrome://treestyletab/locale/treestyletab.properties"); pref("extensions.treestyletab@piro.sakura.ne.jp.description", "chrome://treestyletab/locale/treestyletab.properties");

View File

@ -19,3 +19,10 @@
<!ENTITY config.jsopen.default "Open as Window when it have special width, height, etc. (default)"> <!ENTITY config.jsopen.default "Open as Window when it have special width, height, etc. (default)">
<!ENTITY config.jsopen.forcetab "Open as Tab instead of Window anyway"> <!ENTITY config.jsopen.forcetab "Open as Tab instead of Window anyway">
<!ENTITY selection.removeTabSubTree.label "Close Selected Sub Trees">
<!ENTITY selection.removeTabSubTree.accesskey "s">
<!ENTITY context.removeTabSubTree.label "Close this Sub Tree">
<!ENTITY context.removeTabSubTree.accesskey "s">

View File

@ -18,3 +18,10 @@
<!ENTITY config.jsopen.caption "Webページのスクリプトで開かれるウィンドウの制御"> <!ENTITY config.jsopen.caption "Webページのスクリプトで開かれるウィンドウの制御">
<!ENTITY config.jsopen.default "大きさや位置を指定されたウィンドウはウィンドウとして開く(初期値)"> <!ENTITY config.jsopen.default "大きさや位置を指定されたウィンドウはウィンドウとして開く(初期値)">
<!ENTITY config.jsopen.forcetab "スクリプトで開かれるウィンドウはすべてタブで開く"> <!ENTITY config.jsopen.forcetab "スクリプトで開かれるウィンドウはすべてタブで開く">
<!ENTITY selection.removeTabSubTree.label "すべてのサブツリーを閉じる">
<!ENTITY selection.removeTabSubTree.accesskey "s">
<!ENTITY context.removeTabSubTree.label "このサブツリーを閉じる">
<!ENTITY context.removeTabSubTree.accesskey "s">