Use LF instead of CRLF
This commit is contained in:
parent
c595c8ba22
commit
09f43c8f84
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0"?>
|
||||
<overlay xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
<script src="res/tabsDragUtils.js" type="application/javascript"/>
|
||||
<script src="treestyletab.js" type="application/javascript"/>
|
||||
<script src="bookmarksOverlay.js" type="application/javascript"/>
|
||||
</overlay>
|
||||
<?xml version="1.0"?>
|
||||
<overlay xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
<script src="res/tabsDragUtils.js" type="application/javascript"/>
|
||||
<script src="treestyletab.js" type="application/javascript"/>
|
||||
<script src="bookmarksOverlay.js" type="application/javascript"/>
|
||||
</overlay>
|
||||
|
@ -1,3 +1,3 @@
|
||||
#infoBox[minimal="true"] #treestyletab-parent-row {
|
||||
visibility: collapse;
|
||||
}
|
||||
#infoBox[minimal="true"] #treestyletab-parent-row {
|
||||
visibility: collapse;
|
||||
}
|
||||
|
@ -1,365 +1,365 @@
|
||||
Components.utils.import('resource://gre/modules/XPCOMUtils.jsm');
|
||||
XPCOMUtils.defineLazyModuleGetter(this,
|
||||
'TreeStyleTabUtils', 'resource://treestyletab-modules/utils.js');
|
||||
|
||||
(function() {
|
||||
let { inherit } = Components.utils.import('resource://treestyletab-modules/lib/inherit.jsm', {});
|
||||
var TreeStyleTabBookmarksServiceEditable = inherit(TreeStyleTabBookmarksService, {
|
||||
|
||||
instantApply : false,
|
||||
canceled : false,
|
||||
|
||||
get parentRow()
|
||||
{
|
||||
return document.getElementById('treestyletab-parent-row');
|
||||
},
|
||||
|
||||
get menulist()
|
||||
{
|
||||
return document.getElementById('treestyletab-parent-menulist');
|
||||
},
|
||||
get popup()
|
||||
{
|
||||
return document.getElementById('treestyletab-parent-popup');
|
||||
},
|
||||
|
||||
get separator()
|
||||
{
|
||||
return document.getElementById('treestyletab-parent-blank-item-separator');
|
||||
},
|
||||
get blankItem()
|
||||
{
|
||||
return document.getElementById('treestyletab-parent-blank-item');
|
||||
},
|
||||
|
||||
get isCreatingMultipleBookmarksInFolder()
|
||||
{
|
||||
return (
|
||||
window.arguments.length &&
|
||||
window.arguments[0] &&
|
||||
window.arguments[0].type == 'folder'
|
||||
);
|
||||
},
|
||||
|
||||
init : function TSTBMEditable_init()
|
||||
{
|
||||
if (this.isCreatingMultipleBookmarksInFolder) return;
|
||||
|
||||
// main browser window
|
||||
if ('StarUI' in window) {
|
||||
if ('_doShowEditBookmarkPanel' in StarUI) {
|
||||
eval('StarUI._doShowEditBookmarkPanel = '+StarUI._doShowEditBookmarkPanel.toSource().replace(
|
||||
'{',
|
||||
'{ TreeStyleTabBookmarksServiceEditable.initEditUI();'
|
||||
));
|
||||
}
|
||||
if ('quitEditMode' in StarUI) {
|
||||
eval('StarUI.quitEditMode = '+StarUI.quitEditMode.toSource().replace(
|
||||
'{',
|
||||
'{ TreeStyleTabBookmarksServiceEditable.saveParentFor(this._itemId);'
|
||||
));
|
||||
}
|
||||
if ('cancelButtonOnCommand' in StarUI) {
|
||||
eval('StarUI.cancelButtonOnCommand = '+StarUI.cancelButtonOnCommand.toSource().replace(
|
||||
'{',
|
||||
'{ TreeStyleTabBookmarksServiceEditable.canceled = true;'
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
// Bookmarks Property dialog
|
||||
if ('BookmarkPropertiesPanel' in window) {
|
||||
eval('BookmarkPropertiesPanel._endBatch = '+BookmarkPropertiesPanel._endBatch.toSource().replace(
|
||||
'PlacesUIUtils.ptm.endBatch();',
|
||||
'$& TreeStyleTabBookmarksServiceEditable.saveParentFor(this._itemId);'
|
||||
));
|
||||
}
|
||||
|
||||
// Places Organizer (Library)
|
||||
if ('PlacesOrganizer' in window) {
|
||||
this.instantApply = true;
|
||||
}
|
||||
|
||||
this.initEditUI();
|
||||
},
|
||||
|
||||
initEditUI : function TSTBMEditable_initEditUI()
|
||||
{
|
||||
if (
|
||||
this.editUIInitialized ||
|
||||
!('gEditItemOverlay' in window) ||
|
||||
this.isCreatingMultipleBookmarksInFolder
|
||||
)
|
||||
return;
|
||||
|
||||
var container = document.getElementById('editBookmarkPanelGrid');
|
||||
if (!container) return;
|
||||
|
||||
container = container.getElementsByTagName('rows')[0];
|
||||
var range = document.createRange();
|
||||
range.selectNodeContents(container);
|
||||
range.collapse(false);
|
||||
range.insertNode(range.createContextualFragment(
|
||||
('<row align="center" id="treestyletab-parent-row">' +
|
||||
' <label id="treestyletab-parent-label"' +
|
||||
' control="treestyletab-parent-menulist"/>' +
|
||||
' <menulist id="treestyletab-parent-menulist"' +
|
||||
' flex="1"' +
|
||||
' oncommand="TreeStyleTabBookmarksServiceEditable.onParentChange();">' +
|
||||
' <menupopup id="treestyletab-parent-popup">' +
|
||||
' <menuseparator id="treestyletab-parent-blank-item-separator"/>' +
|
||||
' <menuitem id="treestyletab-parent-blank-item"' +
|
||||
' value=""/>' +
|
||||
' </menupopup>' +
|
||||
' </menulist>' +
|
||||
'</row>').trim().replace(/>\s+</g, '><')));
|
||||
range.detach();
|
||||
document.getElementById('treestyletab-parent-label').setAttribute('value', TreeStyleTabUtils.treeBundle.getString('bookmarkProperty.parent.label'));
|
||||
this.blankItem.setAttribute('label', TreeStyleTabUtils.treeBundle.getString('bookmarkProperty.parent.blank.label'));
|
||||
|
||||
|
||||
eval('gEditItemOverlay._showHideRows = '+gEditItemOverlay._showHideRows.toSource().replace(
|
||||
/(\}\)?)$/,
|
||||
' TreeStyleTabBookmarksServiceEditable.parentRow.collapsed = this._element("keywordRow").collapsed && this._element("folderRow").collapsed;\n' +
|
||||
'$1'
|
||||
));
|
||||
|
||||
eval('gEditItemOverlay.initPanel = '+gEditItemOverlay.initPanel.toSource().replace(
|
||||
'if (this._itemType == Ci.nsINavBookmarksService.TYPE_BOOKMARK) {',
|
||||
'$& TreeStyleTabBookmarksServiceEditable.initParentMenuList();'
|
||||
));
|
||||
|
||||
eval('gEditItemOverlay.onItemMoved = '+gEditItemOverlay.onItemMoved.toSource().replace(
|
||||
'{',
|
||||
'$& if (aNewParent == this._getFolderIdFromMenuList()) TreeStyleTabBookmarksServiceEditable.initParentMenuList();'
|
||||
));
|
||||
|
||||
this.editUIInitialized = true;
|
||||
},
|
||||
editUIInitialized : false,
|
||||
|
||||
initParentMenuList : function TSTBMEditable_initParentMenuList()
|
||||
{
|
||||
var id = gEditItemOverlay.itemId;
|
||||
|
||||
this.menulist.disabled = true;
|
||||
this.menulist.setAttribute('label', '...');
|
||||
|
||||
var popup = this.popup;
|
||||
var range = document.createRange();
|
||||
range.selectNodeContents(popup);
|
||||
range.setEndBefore(this.separator);
|
||||
range.deleteContents();
|
||||
range.detach();
|
||||
|
||||
this.canceled = false;
|
||||
|
||||
// Ignore bookmark in the "unsorted bookmarks" folder, because
|
||||
// there can be very large number of bookmarks and they won't be
|
||||
// opened as a tree.
|
||||
if (PlacesUtils.bookmarks.getFolderIdForItem(id) == PlacesUtils.unfiledBookmarksFolderId)
|
||||
return;
|
||||
|
||||
this._createSiblingsFragment(id, (function(aSiblingsFragment) {
|
||||
var range = document.createRange();
|
||||
range.selectNodeContents(popup);
|
||||
range.setEndBefore(this.separator);
|
||||
range.insertNode(aSiblingsFragment);
|
||||
range.detach();
|
||||
|
||||
var selected = popup.getElementsByAttribute('selected', 'true')[0];
|
||||
this.menulist.disabled = false;
|
||||
this.menulist.value = (selected || this.blankItem).getAttribute('value');
|
||||
}).bind(this))
|
||||
},
|
||||
_doProgressively : function TSTBMEditable__doProgressively(aParams)
|
||||
{
|
||||
var name = aParams.name;
|
||||
if (this._doProgressivelyTimers[name])
|
||||
window.clearTimeout(this._doProgressivelyTimers[name]);
|
||||
|
||||
var interval = 100;
|
||||
var step = 10;
|
||||
var progressiveIteration = (function() {
|
||||
try {
|
||||
for (let i = 0; i < step; i++)
|
||||
{
|
||||
aParams.onProgress();
|
||||
}
|
||||
this._doProgressivelyTimers[name] = window.setTimeout(progressiveIteration, interval);
|
||||
}
|
||||
catch(e if e instanceof StopIteration) {
|
||||
aParams.onComplete();
|
||||
}
|
||||
catch(e) {
|
||||
Components.utils.reportError(e);
|
||||
}
|
||||
finally {
|
||||
this._doProgressivelyTimers[name] = null;
|
||||
}
|
||||
}).bind(this);
|
||||
this._doProgressivelyTimers[name] = window.setTimeout(progressiveIteration, interval);
|
||||
},
|
||||
_doProgressivelyTimers : {},
|
||||
_createSiblingsFragment : function TSTBMEditable__createSiblingsFragment(aCurrentItem, aCallback)
|
||||
{
|
||||
var itemsIterator = this._getSiblingItemsIterator(aCurrentItem);
|
||||
var items = [];
|
||||
this._doProgressively({
|
||||
name : '_createSiblingsFragment',
|
||||
onProgress : function() {
|
||||
items.push(itemsIterator.next());
|
||||
},
|
||||
onComplete : (function() {
|
||||
this._createSiblingsFragmentInternal(aCurrentItem, items, function(aSiblingsFragment) {
|
||||
aCallback(aSiblingsFragment);
|
||||
});
|
||||
}).bind(this)
|
||||
});
|
||||
},
|
||||
_createSiblingsFragmentInternal : function TSTBMEditable_createSiblingsFragmentInternal(aCurrentItem, aItems, aCallback)
|
||||
{
|
||||
var treeStructure = this.getTreeStructureFromItems(aItems);
|
||||
|
||||
var currentIndex = aItems.indexOf(aCurrentItem);
|
||||
var selected = treeStructure[currentIndex];
|
||||
if (selected > -1) {
|
||||
let offset = treeStructure.lastIndexOf(-1, currentIndex);
|
||||
let subStructure = treeStructure.slice(offset);
|
||||
selected = aItems[selected + offset];
|
||||
}
|
||||
|
||||
var fragment = document.createDocumentFragment();
|
||||
|
||||
var itemsIterator = Iterator(aItems);
|
||||
this._doProgressively({
|
||||
name : '_createSiblingsFragment',
|
||||
onProgress : (function() {
|
||||
let [index, id] = itemsIterator.next();
|
||||
|
||||
let label = PlacesUtils.bookmarks.getItemTitle(id);
|
||||
let menuitem = document.createElement('menuitem');
|
||||
menuitem.setAttribute('value', id);
|
||||
|
||||
let parent = index;
|
||||
let nest = 0;
|
||||
let disabled = false;
|
||||
while ((parent = treeStructure[parent]) != -1)
|
||||
{
|
||||
nest++;
|
||||
if (parent == currentIndex) disabled = true;
|
||||
}
|
||||
if (nest)
|
||||
menuitem.setAttribute('style', 'padding-left:'+nest+'em');
|
||||
|
||||
if (disabled || id == aCurrentItem) {
|
||||
menuitem.setAttribute('disabled', true);
|
||||
if (id == aCurrentItem)
|
||||
label = TreeStyleTabUtils.treeBundle.getFormattedString('bookmarkProperty.parent.current.label', [label]);
|
||||
}
|
||||
if (id == selected)
|
||||
menuitem.setAttribute('selected', true);
|
||||
|
||||
menuitem.setAttribute('label', label);
|
||||
|
||||
fragment.appendChild(menuitem);
|
||||
}).bind(this),
|
||||
onComplete : function() {
|
||||
aCallback(fragment);
|
||||
}
|
||||
});
|
||||
},
|
||||
_getItemsInFolderIterator : function TSTBMEditable_getItemsInFolderIterator(aId)
|
||||
{
|
||||
var count = 0;
|
||||
var item;
|
||||
try {
|
||||
while((item = PlacesUtils.bookmarks.getIdForItemAt(aId, count++)) != -1)
|
||||
{
|
||||
try {
|
||||
let uri = PlacesUtils.bookmarks.getBookmarkURI(item);
|
||||
if (uri.spec.indexOf('place:') != 0)
|
||||
yield item;
|
||||
}
|
||||
catch(e) {
|
||||
// this is not a normal bookmark.
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(e) {
|
||||
}
|
||||
},
|
||||
_getSiblingItemsIterator : function TSTBMEditable_getSiblingItemsIterator(aId)
|
||||
{
|
||||
return this._getItemsInFolderIterator(PlacesUtils.bookmarks.getFolderIdForItem(aId));
|
||||
},
|
||||
|
||||
saveParentFor : function TSTBMEditable_saveParentFor(aId)
|
||||
{
|
||||
var newParentId = parseInt(this.menulist.value || -1);
|
||||
if (this.canceled || newParentId == this.getParentItem(aId)) return;
|
||||
|
||||
var itemsIterator = this._getSiblingItemsIterator(aId);
|
||||
var items = [];
|
||||
this._doProgressively({
|
||||
name : '_createSiblingsFragment',
|
||||
onProgress : function() {
|
||||
items.push(itemsIterator.next());
|
||||
},
|
||||
onComplete : (function() {
|
||||
this._saveParentForInternal(aId, newParentId, items);
|
||||
}).bind(this)
|
||||
});
|
||||
},
|
||||
_saveParentForInternal : function TSTBMEditable_saveParentForInternal(aId, aNewParentId, aItems)
|
||||
{
|
||||
var treeStructure = this.getTreeStructureFromItems(aItems);
|
||||
|
||||
var parentIndex = aItems.indexOf(aNewParentId);
|
||||
var newIndex;
|
||||
if (TreeStyleTabUtils.getTreePref('insertNewChildAt') == this.kINSERT_FISRT) {
|
||||
newIndex = treeStructure.indexOf(parentIndex);
|
||||
}
|
||||
else {
|
||||
do {
|
||||
newIndex = parentIndex;
|
||||
parentIndex = treeStructure.lastIndexOf(parentIndex);
|
||||
}
|
||||
while (parentIndex > -1);
|
||||
newIndex++;
|
||||
}
|
||||
|
||||
PlacesUtils.setAnnotationsForItem(aId, [{
|
||||
name : this.kPARENT,
|
||||
value : aNewParentId,
|
||||
expires : PlacesUtils.annotations.EXPIRE_NEVER
|
||||
}]);
|
||||
|
||||
PlacesUtils.bookmarks.moveItem(aId, PlacesUtils.bookmarks.getFolderIdForItem(aId), newIndex);
|
||||
|
||||
if (this.instantApply) this.initParentMenuList();
|
||||
},
|
||||
|
||||
onParentChange : function TSTBMEditable_onParentChange()
|
||||
{
|
||||
if (!this.instantApply) return;
|
||||
this.saveParentFor(gEditItemOverlay.itemId);
|
||||
},
|
||||
|
||||
handleEvent : function TSTBMEditable_handleEvent(aEvent)
|
||||
{
|
||||
switch (aEvent.type)
|
||||
{
|
||||
case 'DOMContentLoaded':
|
||||
window.removeEventListener('DOMContentLoaded', this, false);
|
||||
this.init();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
window.addEventListener('DOMContentLoaded', TreeStyleTabBookmarksServiceEditable, false);
|
||||
|
||||
window.TreeStyleTabBookmarksServiceEditable = TreeStyleTabBookmarksServiceEditable;
|
||||
})();
|
||||
Components.utils.import('resource://gre/modules/XPCOMUtils.jsm');
|
||||
XPCOMUtils.defineLazyModuleGetter(this,
|
||||
'TreeStyleTabUtils', 'resource://treestyletab-modules/utils.js');
|
||||
|
||||
(function() {
|
||||
let { inherit } = Components.utils.import('resource://treestyletab-modules/lib/inherit.jsm', {});
|
||||
var TreeStyleTabBookmarksServiceEditable = inherit(TreeStyleTabBookmarksService, {
|
||||
|
||||
instantApply : false,
|
||||
canceled : false,
|
||||
|
||||
get parentRow()
|
||||
{
|
||||
return document.getElementById('treestyletab-parent-row');
|
||||
},
|
||||
|
||||
get menulist()
|
||||
{
|
||||
return document.getElementById('treestyletab-parent-menulist');
|
||||
},
|
||||
get popup()
|
||||
{
|
||||
return document.getElementById('treestyletab-parent-popup');
|
||||
},
|
||||
|
||||
get separator()
|
||||
{
|
||||
return document.getElementById('treestyletab-parent-blank-item-separator');
|
||||
},
|
||||
get blankItem()
|
||||
{
|
||||
return document.getElementById('treestyletab-parent-blank-item');
|
||||
},
|
||||
|
||||
get isCreatingMultipleBookmarksInFolder()
|
||||
{
|
||||
return (
|
||||
window.arguments.length &&
|
||||
window.arguments[0] &&
|
||||
window.arguments[0].type == 'folder'
|
||||
);
|
||||
},
|
||||
|
||||
init : function TSTBMEditable_init()
|
||||
{
|
||||
if (this.isCreatingMultipleBookmarksInFolder) return;
|
||||
|
||||
// main browser window
|
||||
if ('StarUI' in window) {
|
||||
if ('_doShowEditBookmarkPanel' in StarUI) {
|
||||
eval('StarUI._doShowEditBookmarkPanel = '+StarUI._doShowEditBookmarkPanel.toSource().replace(
|
||||
'{',
|
||||
'{ TreeStyleTabBookmarksServiceEditable.initEditUI();'
|
||||
));
|
||||
}
|
||||
if ('quitEditMode' in StarUI) {
|
||||
eval('StarUI.quitEditMode = '+StarUI.quitEditMode.toSource().replace(
|
||||
'{',
|
||||
'{ TreeStyleTabBookmarksServiceEditable.saveParentFor(this._itemId);'
|
||||
));
|
||||
}
|
||||
if ('cancelButtonOnCommand' in StarUI) {
|
||||
eval('StarUI.cancelButtonOnCommand = '+StarUI.cancelButtonOnCommand.toSource().replace(
|
||||
'{',
|
||||
'{ TreeStyleTabBookmarksServiceEditable.canceled = true;'
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
// Bookmarks Property dialog
|
||||
if ('BookmarkPropertiesPanel' in window) {
|
||||
eval('BookmarkPropertiesPanel._endBatch = '+BookmarkPropertiesPanel._endBatch.toSource().replace(
|
||||
'PlacesUIUtils.ptm.endBatch();',
|
||||
'$& TreeStyleTabBookmarksServiceEditable.saveParentFor(this._itemId);'
|
||||
));
|
||||
}
|
||||
|
||||
// Places Organizer (Library)
|
||||
if ('PlacesOrganizer' in window) {
|
||||
this.instantApply = true;
|
||||
}
|
||||
|
||||
this.initEditUI();
|
||||
},
|
||||
|
||||
initEditUI : function TSTBMEditable_initEditUI()
|
||||
{
|
||||
if (
|
||||
this.editUIInitialized ||
|
||||
!('gEditItemOverlay' in window) ||
|
||||
this.isCreatingMultipleBookmarksInFolder
|
||||
)
|
||||
return;
|
||||
|
||||
var container = document.getElementById('editBookmarkPanelGrid');
|
||||
if (!container) return;
|
||||
|
||||
container = container.getElementsByTagName('rows')[0];
|
||||
var range = document.createRange();
|
||||
range.selectNodeContents(container);
|
||||
range.collapse(false);
|
||||
range.insertNode(range.createContextualFragment(
|
||||
('<row align="center" id="treestyletab-parent-row">' +
|
||||
' <label id="treestyletab-parent-label"' +
|
||||
' control="treestyletab-parent-menulist"/>' +
|
||||
' <menulist id="treestyletab-parent-menulist"' +
|
||||
' flex="1"' +
|
||||
' oncommand="TreeStyleTabBookmarksServiceEditable.onParentChange();">' +
|
||||
' <menupopup id="treestyletab-parent-popup">' +
|
||||
' <menuseparator id="treestyletab-parent-blank-item-separator"/>' +
|
||||
' <menuitem id="treestyletab-parent-blank-item"' +
|
||||
' value=""/>' +
|
||||
' </menupopup>' +
|
||||
' </menulist>' +
|
||||
'</row>').trim().replace(/>\s+</g, '><')));
|
||||
range.detach();
|
||||
document.getElementById('treestyletab-parent-label').setAttribute('value', TreeStyleTabUtils.treeBundle.getString('bookmarkProperty.parent.label'));
|
||||
this.blankItem.setAttribute('label', TreeStyleTabUtils.treeBundle.getString('bookmarkProperty.parent.blank.label'));
|
||||
|
||||
|
||||
eval('gEditItemOverlay._showHideRows = '+gEditItemOverlay._showHideRows.toSource().replace(
|
||||
/(\}\)?)$/,
|
||||
' TreeStyleTabBookmarksServiceEditable.parentRow.collapsed = this._element("keywordRow").collapsed && this._element("folderRow").collapsed;\n' +
|
||||
'$1'
|
||||
));
|
||||
|
||||
eval('gEditItemOverlay.initPanel = '+gEditItemOverlay.initPanel.toSource().replace(
|
||||
'if (this._itemType == Ci.nsINavBookmarksService.TYPE_BOOKMARK) {',
|
||||
'$& TreeStyleTabBookmarksServiceEditable.initParentMenuList();'
|
||||
));
|
||||
|
||||
eval('gEditItemOverlay.onItemMoved = '+gEditItemOverlay.onItemMoved.toSource().replace(
|
||||
'{',
|
||||
'$& if (aNewParent == this._getFolderIdFromMenuList()) TreeStyleTabBookmarksServiceEditable.initParentMenuList();'
|
||||
));
|
||||
|
||||
this.editUIInitialized = true;
|
||||
},
|
||||
editUIInitialized : false,
|
||||
|
||||
initParentMenuList : function TSTBMEditable_initParentMenuList()
|
||||
{
|
||||
var id = gEditItemOverlay.itemId;
|
||||
|
||||
this.menulist.disabled = true;
|
||||
this.menulist.setAttribute('label', '...');
|
||||
|
||||
var popup = this.popup;
|
||||
var range = document.createRange();
|
||||
range.selectNodeContents(popup);
|
||||
range.setEndBefore(this.separator);
|
||||
range.deleteContents();
|
||||
range.detach();
|
||||
|
||||
this.canceled = false;
|
||||
|
||||
// Ignore bookmark in the "unsorted bookmarks" folder, because
|
||||
// there can be very large number of bookmarks and they won't be
|
||||
// opened as a tree.
|
||||
if (PlacesUtils.bookmarks.getFolderIdForItem(id) == PlacesUtils.unfiledBookmarksFolderId)
|
||||
return;
|
||||
|
||||
this._createSiblingsFragment(id, (function(aSiblingsFragment) {
|
||||
var range = document.createRange();
|
||||
range.selectNodeContents(popup);
|
||||
range.setEndBefore(this.separator);
|
||||
range.insertNode(aSiblingsFragment);
|
||||
range.detach();
|
||||
|
||||
var selected = popup.getElementsByAttribute('selected', 'true')[0];
|
||||
this.menulist.disabled = false;
|
||||
this.menulist.value = (selected || this.blankItem).getAttribute('value');
|
||||
}).bind(this))
|
||||
},
|
||||
_doProgressively : function TSTBMEditable__doProgressively(aParams)
|
||||
{
|
||||
var name = aParams.name;
|
||||
if (this._doProgressivelyTimers[name])
|
||||
window.clearTimeout(this._doProgressivelyTimers[name]);
|
||||
|
||||
var interval = 100;
|
||||
var step = 10;
|
||||
var progressiveIteration = (function() {
|
||||
try {
|
||||
for (let i = 0; i < step; i++)
|
||||
{
|
||||
aParams.onProgress();
|
||||
}
|
||||
this._doProgressivelyTimers[name] = window.setTimeout(progressiveIteration, interval);
|
||||
}
|
||||
catch(e if e instanceof StopIteration) {
|
||||
aParams.onComplete();
|
||||
}
|
||||
catch(e) {
|
||||
Components.utils.reportError(e);
|
||||
}
|
||||
finally {
|
||||
this._doProgressivelyTimers[name] = null;
|
||||
}
|
||||
}).bind(this);
|
||||
this._doProgressivelyTimers[name] = window.setTimeout(progressiveIteration, interval);
|
||||
},
|
||||
_doProgressivelyTimers : {},
|
||||
_createSiblingsFragment : function TSTBMEditable__createSiblingsFragment(aCurrentItem, aCallback)
|
||||
{
|
||||
var itemsIterator = this._getSiblingItemsIterator(aCurrentItem);
|
||||
var items = [];
|
||||
this._doProgressively({
|
||||
name : '_createSiblingsFragment',
|
||||
onProgress : function() {
|
||||
items.push(itemsIterator.next());
|
||||
},
|
||||
onComplete : (function() {
|
||||
this._createSiblingsFragmentInternal(aCurrentItem, items, function(aSiblingsFragment) {
|
||||
aCallback(aSiblingsFragment);
|
||||
});
|
||||
}).bind(this)
|
||||
});
|
||||
},
|
||||
_createSiblingsFragmentInternal : function TSTBMEditable_createSiblingsFragmentInternal(aCurrentItem, aItems, aCallback)
|
||||
{
|
||||
var treeStructure = this.getTreeStructureFromItems(aItems);
|
||||
|
||||
var currentIndex = aItems.indexOf(aCurrentItem);
|
||||
var selected = treeStructure[currentIndex];
|
||||
if (selected > -1) {
|
||||
let offset = treeStructure.lastIndexOf(-1, currentIndex);
|
||||
let subStructure = treeStructure.slice(offset);
|
||||
selected = aItems[selected + offset];
|
||||
}
|
||||
|
||||
var fragment = document.createDocumentFragment();
|
||||
|
||||
var itemsIterator = Iterator(aItems);
|
||||
this._doProgressively({
|
||||
name : '_createSiblingsFragment',
|
||||
onProgress : (function() {
|
||||
let [index, id] = itemsIterator.next();
|
||||
|
||||
let label = PlacesUtils.bookmarks.getItemTitle(id);
|
||||
let menuitem = document.createElement('menuitem');
|
||||
menuitem.setAttribute('value', id);
|
||||
|
||||
let parent = index;
|
||||
let nest = 0;
|
||||
let disabled = false;
|
||||
while ((parent = treeStructure[parent]) != -1)
|
||||
{
|
||||
nest++;
|
||||
if (parent == currentIndex) disabled = true;
|
||||
}
|
||||
if (nest)
|
||||
menuitem.setAttribute('style', 'padding-left:'+nest+'em');
|
||||
|
||||
if (disabled || id == aCurrentItem) {
|
||||
menuitem.setAttribute('disabled', true);
|
||||
if (id == aCurrentItem)
|
||||
label = TreeStyleTabUtils.treeBundle.getFormattedString('bookmarkProperty.parent.current.label', [label]);
|
||||
}
|
||||
if (id == selected)
|
||||
menuitem.setAttribute('selected', true);
|
||||
|
||||
menuitem.setAttribute('label', label);
|
||||
|
||||
fragment.appendChild(menuitem);
|
||||
}).bind(this),
|
||||
onComplete : function() {
|
||||
aCallback(fragment);
|
||||
}
|
||||
});
|
||||
},
|
||||
_getItemsInFolderIterator : function TSTBMEditable_getItemsInFolderIterator(aId)
|
||||
{
|
||||
var count = 0;
|
||||
var item;
|
||||
try {
|
||||
while((item = PlacesUtils.bookmarks.getIdForItemAt(aId, count++)) != -1)
|
||||
{
|
||||
try {
|
||||
let uri = PlacesUtils.bookmarks.getBookmarkURI(item);
|
||||
if (uri.spec.indexOf('place:') != 0)
|
||||
yield item;
|
||||
}
|
||||
catch(e) {
|
||||
// this is not a normal bookmark.
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(e) {
|
||||
}
|
||||
},
|
||||
_getSiblingItemsIterator : function TSTBMEditable_getSiblingItemsIterator(aId)
|
||||
{
|
||||
return this._getItemsInFolderIterator(PlacesUtils.bookmarks.getFolderIdForItem(aId));
|
||||
},
|
||||
|
||||
saveParentFor : function TSTBMEditable_saveParentFor(aId)
|
||||
{
|
||||
var newParentId = parseInt(this.menulist.value || -1);
|
||||
if (this.canceled || newParentId == this.getParentItem(aId)) return;
|
||||
|
||||
var itemsIterator = this._getSiblingItemsIterator(aId);
|
||||
var items = [];
|
||||
this._doProgressively({
|
||||
name : '_createSiblingsFragment',
|
||||
onProgress : function() {
|
||||
items.push(itemsIterator.next());
|
||||
},
|
||||
onComplete : (function() {
|
||||
this._saveParentForInternal(aId, newParentId, items);
|
||||
}).bind(this)
|
||||
});
|
||||
},
|
||||
_saveParentForInternal : function TSTBMEditable_saveParentForInternal(aId, aNewParentId, aItems)
|
||||
{
|
||||
var treeStructure = this.getTreeStructureFromItems(aItems);
|
||||
|
||||
var parentIndex = aItems.indexOf(aNewParentId);
|
||||
var newIndex;
|
||||
if (TreeStyleTabUtils.getTreePref('insertNewChildAt') == this.kINSERT_FISRT) {
|
||||
newIndex = treeStructure.indexOf(parentIndex);
|
||||
}
|
||||
else {
|
||||
do {
|
||||
newIndex = parentIndex;
|
||||
parentIndex = treeStructure.lastIndexOf(parentIndex);
|
||||
}
|
||||
while (parentIndex > -1);
|
||||
newIndex++;
|
||||
}
|
||||
|
||||
PlacesUtils.setAnnotationsForItem(aId, [{
|
||||
name : this.kPARENT,
|
||||
value : aNewParentId,
|
||||
expires : PlacesUtils.annotations.EXPIRE_NEVER
|
||||
}]);
|
||||
|
||||
PlacesUtils.bookmarks.moveItem(aId, PlacesUtils.bookmarks.getFolderIdForItem(aId), newIndex);
|
||||
|
||||
if (this.instantApply) this.initParentMenuList();
|
||||
},
|
||||
|
||||
onParentChange : function TSTBMEditable_onParentChange()
|
||||
{
|
||||
if (!this.instantApply) return;
|
||||
this.saveParentFor(gEditItemOverlay.itemId);
|
||||
},
|
||||
|
||||
handleEvent : function TSTBMEditable_handleEvent(aEvent)
|
||||
{
|
||||
switch (aEvent.type)
|
||||
{
|
||||
case 'DOMContentLoaded':
|
||||
window.removeEventListener('DOMContentLoaded', this, false);
|
||||
this.init();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
window.addEventListener('DOMContentLoaded', TreeStyleTabBookmarksServiceEditable, false);
|
||||
|
||||
window.TreeStyleTabBookmarksServiceEditable = TreeStyleTabBookmarksServiceEditable;
|
||||
})();
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?xml version="1.0"?>
|
||||
<?xml-stylesheet href="bookmarksOverlayEditable.css" type="text/css"?>
|
||||
<overlay xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
<script src="bookmarksOverlayEditable.js" type="application/javascript"/>
|
||||
</overlay>
|
||||
<?xml version="1.0"?>
|
||||
<?xml-stylesheet href="bookmarksOverlayEditable.css" type="text/css"?>
|
||||
<overlay xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
<script src="bookmarksOverlayEditable.js" type="application/javascript"/>
|
||||
</overlay>
|
||||
|
@ -1,15 +1,15 @@
|
||||
@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
|
||||
|
||||
[id="extensions.treestyletab.tabbar.style-radiogroup"] radio[src] .radio-icon {
|
||||
width: 52px;
|
||||
height: 62px;
|
||||
}
|
||||
|
||||
[id="extensions.treestyletab.twisty.style-radiogroup"] radio[src] .radio-icon {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
}
|
||||
|
||||
arrowscrollbox[overflow="true"] {
|
||||
border: 1px inset ThreeDFace;
|
||||
}
|
||||
@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
|
||||
|
||||
[id="extensions.treestyletab.tabbar.style-radiogroup"] radio[src] .radio-icon {
|
||||
width: 52px;
|
||||
height: 62px;
|
||||
}
|
||||
|
||||
[id="extensions.treestyletab.twisty.style-radiogroup"] radio[src] .radio-icon {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
}
|
||||
|
||||
arrowscrollbox[overflow="true"] {
|
||||
border: 1px inset ThreeDFace;
|
||||
}
|
||||
|
@ -1,375 +1,375 @@
|
||||
Components.utils.import('resource://gre/modules/Services.jsm');
|
||||
|
||||
const XULAppInfo = Services.appinfo;
|
||||
const comparator = Services.vc;
|
||||
var Prefs = Services.prefs;
|
||||
|
||||
Components.utils.import('resource://treestyletab-modules/lib/animationManager.js', {});
|
||||
Components.utils.import('resource://treestyletab-modules/lib/prefs.js', {});
|
||||
Components.utils.import('resource://treestyletab-modules/lib/namespace.jsm');
|
||||
var animationManager = getNamespaceFor('piro.sakura.ne.jp')['piro.sakura.ne.jp'].animationManager;
|
||||
var prefs = getNamespaceFor('piro.sakura.ne.jp')['piro.sakura.ne.jp'].prefs;
|
||||
|
||||
|
||||
function syncEnabledState(aElement, aEnabled)
|
||||
{
|
||||
if (typeof aElement == 'string')
|
||||
aElement = document.getElementById(aElement);
|
||||
if (typeof aEnabled == 'string')
|
||||
aEnabled = (new Function('return '+aEnabled)).call(aElement);
|
||||
|
||||
aElement.getAttribute('sync-enabled-state-targets')
|
||||
.replace(/$\s+|\s+$/g, '')
|
||||
.split(/\s+/)
|
||||
.map(function(aId) {
|
||||
if (!aId)
|
||||
return;
|
||||
var target = document.getElementById(aId);
|
||||
if (aEnabled)
|
||||
target.removeAttribute('disabled');
|
||||
else
|
||||
target.setAttribute('disabled', true);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
var gGroupBookmarkRadio,
|
||||
gGroupBookmarkUnderParent,
|
||||
gGroupBookmarkType,
|
||||
gGroupBookmarkBehaviorPref;
|
||||
|
||||
function ensureGroupBookmarkItems()
|
||||
{
|
||||
if (gGroupBookmarkBehaviorPref) return;
|
||||
|
||||
gGroupBookmarkRadio = document.getElementById('openGroupBookmark-radiogroup');
|
||||
gGroupBookmarkUnderParent = document.getElementById('openGroupBookmark.underParent-check');
|
||||
gGroupBookmarkType = document.getElementById('openGroupBookmark.subtreeType-menulist');
|
||||
gGroupBookmarkBehaviorPref = document.getElementById('extensions.treestyletab.openGroupBookmark.behavior');
|
||||
}
|
||||
|
||||
function init()
|
||||
{
|
||||
ensureGroupBookmarkItems();
|
||||
|
||||
// sizeToContent();
|
||||
}
|
||||
|
||||
|
||||
function initAppearancePane()
|
||||
{
|
||||
onChangeTabbarPosition();
|
||||
|
||||
var sidebar = document.getElementById('extensions.treestyletab.tabbar.style-sidebar');
|
||||
sidebar.removeAttribute('disabled');
|
||||
|
||||
var boxes = [
|
||||
document.getElementById('extensions.treestyletab.tabbar.style-arrowscrollbox'),
|
||||
document.getElementById('extensions.treestyletab.twisty.style-arrowscrollbox')
|
||||
];
|
||||
Array.slice(boxes[0].childNodes).concat(Array.slice(boxes[1].childNodes)).forEach(function(aItem) {
|
||||
let start = 0;
|
||||
let delta = 200;
|
||||
let radian = 90 * Math.PI / 180;
|
||||
aItem.style.overflow = 'hidden';
|
||||
aItem.width = 0;
|
||||
aItem.style.maxWidth = 0;
|
||||
let task = function(aTime, aBeginning, aChange, aDuration) {
|
||||
var width;
|
||||
if (aTime >= aDuration) {
|
||||
width = start + delta;
|
||||
finished = true;
|
||||
}
|
||||
else {
|
||||
width = start + (delta * Math.sin(aTime / aDuration * radian));
|
||||
finished = false;
|
||||
}
|
||||
aItem.removeAttribute('width');
|
||||
aItem.style.maxWidth = parseInt(width)+'px';
|
||||
|
||||
var itemBox = aItem.boxObject;
|
||||
var parentBox = aItem.parentNode.boxObject;
|
||||
if (
|
||||
parentBox.screenX > itemBox.screenX ||
|
||||
parentBox.screenX + parentBox.width < itemBox.screenX + itemBox.width
|
||||
) {
|
||||
aItem.parentNode.setAttribute('overflow', true);
|
||||
if (aItem.selected)
|
||||
aItem.parentNode.scrollBoxObject.ensureElementIsVisible(aItem);
|
||||
}
|
||||
|
||||
if (finished) {
|
||||
start = null;
|
||||
delta = null;
|
||||
radian = null;
|
||||
aItem = null;
|
||||
}
|
||||
return finished;
|
||||
};
|
||||
animationManager.addTask(task, 0, 0, 500, window);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
var gDropLinksOnRadioSet,
|
||||
gGroupBookmarkRadioSet,
|
||||
gLastStateIsVertical;
|
||||
var gTabbarPlacePositionInitialized = false;
|
||||
|
||||
function initTabPane()
|
||||
{
|
||||
gDropLinksOnTabRadioSet = new RadioSet(
|
||||
'extensions.treestyletab.dropLinksOnTab.behavior',
|
||||
'dropLinksOnTab-radiogroup',
|
||||
'dropLinksOnTab-check',
|
||||
'dropLinksOnTab-deck'
|
||||
);
|
||||
gGroupBookmarkRadioSet = new RadioSet(
|
||||
'extensions.treestyletab.openGroupBookmark.behavior',
|
||||
'openGroupBookmark-radiogroup',
|
||||
'openGroupBookmark-check',
|
||||
'openGroupBookmark-deck'
|
||||
);
|
||||
|
||||
var newTabPref = document.getElementById('extensions.treestyletab.autoAttach.newTabButton-box');
|
||||
newTabPref.removeAttribute('hidden');
|
||||
}
|
||||
|
||||
function onSyncGroupBookmarkUIToPref()
|
||||
{
|
||||
ensureGroupBookmarkItems();
|
||||
var behavior = gGroupBookmarkBehaviorPref.value;
|
||||
if (behavior & 1) behavior ^= 1;
|
||||
if (behavior & 2) behavior ^= 2;
|
||||
if (behavior & 4) behavior ^= 4;
|
||||
if (behavior & 256) behavior ^= 256;
|
||||
if (behavior & 512) behavior ^= 512;
|
||||
|
||||
behavior |= parseInt(gGroupBookmarkRadio.value);
|
||||
|
||||
if (gGroupBookmarkUnderParent.checked) behavior |= 256;
|
||||
if (gGroupBookmarkType.value == 'true') behavior |= 512;
|
||||
|
||||
var nodes = [
|
||||
gGroupBookmarkUnderParent,
|
||||
gGroupBookmarkType,
|
||||
gGroupBookmarkType.previousSibling,
|
||||
gGroupBookmarkType.nextSibling
|
||||
];
|
||||
for (let i = 0, maxi = nodes.length; i < maxi; i++)
|
||||
{
|
||||
let node = nodes[i];
|
||||
if (behavior & 1)
|
||||
node.removeAttribute('disabled');
|
||||
else
|
||||
node.setAttribute('disabled', true);
|
||||
}
|
||||
|
||||
return behavior;
|
||||
}
|
||||
|
||||
function onSyncGroupBookmarkPrefToUI()
|
||||
{
|
||||
ensureGroupBookmarkItems();
|
||||
var behavior = gGroupBookmarkBehaviorPref.value & 1 ? 1 :
|
||||
gGroupBookmarkBehaviorPref.value & 2 ? 2 :
|
||||
gGroupBookmarkBehaviorPref.value & 4 ? 4 :
|
||||
0;
|
||||
gGroupBookmarkUnderParent.checked = !!(gGroupBookmarkBehaviorPref.value & 256);
|
||||
gGroupBookmarkType.value = gGroupBookmarkBehaviorPref.value & 512 ? 'true' : 'false' ;
|
||||
return behavior;
|
||||
}
|
||||
|
||||
|
||||
function onChangeTabbarPosition()
|
||||
{
|
||||
var pos = document.getElementById('extensions.treestyletab.tabbar.position-radiogroup').value;
|
||||
var invertTab = document.getElementById('extensions.treestyletab.tabbar.invertTab-check');
|
||||
var invertTabContents = document.getElementById('extensions.treestyletab.tabbar.invertTabContents-check');
|
||||
var invertClosebox = document.getElementById('extensions.treestyletab.tabbar.invertClosebox-check');
|
||||
|
||||
invertTab.disabled = pos != 'right';
|
||||
// invertTabContents.disabled = pos != 'right';
|
||||
invertClosebox.setAttribute('label',
|
||||
invertClosebox.getAttribute(
|
||||
(pos == 'right' && invertTabContents.checked) ?
|
||||
'label-right' :
|
||||
'label-left'
|
||||
)
|
||||
);
|
||||
if (invertClosebox.checked != document.getElementById('extensions.treestyletab.tabbar.invertClosebox').defaultValue)
|
||||
invertClosebox.removeAttribute('collapsed');
|
||||
else
|
||||
invertClosebox.setAttribute('collapsed', true);
|
||||
|
||||
var maxTreeLevelH = document.getElementById('maxTreeLevel-horizontal');
|
||||
var maxTreeLevelV = document.getElementById('maxTreeLevel-vertical');
|
||||
var collapseCheckH = document.getElementById('extensions.treestyletab.allowSubtreeCollapseExpand.horizontal-check');
|
||||
var collapseCheckV = document.getElementById('extensions.treestyletab.allowSubtreeCollapseExpand.vertical-check');
|
||||
|
||||
if (pos == 'left' || pos == 'right') {
|
||||
maxTreeLevelH.setAttribute('collapsed', true);
|
||||
maxTreeLevelV.removeAttribute('collapsed');
|
||||
collapseCheckH.setAttribute('collapsed', true);
|
||||
collapseCheckV.removeAttribute('collapsed');
|
||||
}
|
||||
else {
|
||||
maxTreeLevelH.removeAttribute('collapsed');
|
||||
maxTreeLevelV.setAttribute('collapsed', true);
|
||||
collapseCheckH.removeAttribute('collapsed');
|
||||
collapseCheckV.setAttribute('collapsed', true);
|
||||
}
|
||||
|
||||
gTabbarPlacePositionInitialized = true;
|
||||
}
|
||||
|
||||
function onSyncMaxTreeLevelUIToPref(aTarget, aSetPrefValue)
|
||||
{
|
||||
aTarget = document.getElementById(aTarget);
|
||||
if (aTarget.sync)
|
||||
return;
|
||||
aTarget.sync = true;
|
||||
|
||||
var textbox = aTarget.parentNode.getElementsByTagName('textbox')[0];
|
||||
var prefValue = aTarget.checked ? textbox.value : 0 ;
|
||||
|
||||
if (aSetPrefValue)
|
||||
document.getElementById(aTarget.getAttribute('preference')).value = prefValue;
|
||||
|
||||
aTarget.sync = false;
|
||||
return prefValue;
|
||||
}
|
||||
|
||||
function onSyncMaxTreeLevelPrefToUI(aTarget)
|
||||
{
|
||||
aTarget = document.getElementById(aTarget);
|
||||
if (aTarget.sync)
|
||||
return;
|
||||
aTarget.sync = true;
|
||||
|
||||
var pref = document.getElementById(aTarget.getAttribute('preference'));
|
||||
var value = pref.value;
|
||||
var UIValue = value != 0;
|
||||
|
||||
var textbox = aTarget.parentNode.getElementsByTagName('textbox')[0];
|
||||
|
||||
if (UIValue)
|
||||
textbox.value = value;
|
||||
|
||||
syncEnabledState(aTarget, UIValue);
|
||||
|
||||
aTarget.sync = false;
|
||||
return UIValue;
|
||||
}
|
||||
|
||||
|
||||
function initAutoHidePane()
|
||||
{
|
||||
syncEnabledState('extensions.treestyletab.tabbar.autoShow.mousemove-check', 'this.checked');
|
||||
syncEnabledState('extensions.treestyletab.tabbar.autoShow.accelKeyDown-check', 'this.checked');
|
||||
syncEnabledState('extensions.treestyletab.tabbar.autoShow.feedback-check', 'this.checked');
|
||||
}
|
||||
|
||||
function onChangeAutoHideMode(aRadioGroup, aTogglePref)
|
||||
{
|
||||
if (aRadioGroup.value != 0)
|
||||
document.getElementById(aTogglePref).value = aRadioGroup.value;
|
||||
}
|
||||
|
||||
|
||||
function initTreePane()
|
||||
{
|
||||
syncEnabledState('extensions.treestyletab.closeParentBehavior-radiogroup', 'this.value == 0');
|
||||
|
||||
var focusMode = document.getElementById('extensions.treestyletab.focusMode-check');
|
||||
var focusModePref = document.getElementById('extensions.treestyletab.focusMode');
|
||||
if (focusModePref.value != focusModePref.defaultValue)
|
||||
focusMode.removeAttribute('collapsed');
|
||||
else
|
||||
focusMode.setAttribute('collapsed', true);
|
||||
}
|
||||
|
||||
|
||||
var gBookmarkDroppedTabsRadioSet,
|
||||
gUndoCloseTabSetRadioSet;
|
||||
|
||||
function initAdvancedPane()
|
||||
{
|
||||
gBookmarkDroppedTabsRadioSet = new RadioSet(
|
||||
'extensions.treestyletab.bookmarkDroppedTabs.behavior',
|
||||
'bookmarkDroppedTabs-radiogroup',
|
||||
'bookmarkDroppedTabs-check',
|
||||
'bookmarkDroppedTabs-deck'
|
||||
);
|
||||
|
||||
gUndoCloseTabSetRadioSet = new RadioSet(
|
||||
'extensions.treestyletab.undoCloseTabSet.behavior',
|
||||
'undoCloseTabSet-radiogroup',
|
||||
'undoCloseTabSet-check',
|
||||
'undoCloseTabSet-deck',
|
||||
1
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
function RadioSet(aPref, aRadio, aCheck, aDeck, aAskFlag)
|
||||
{
|
||||
this.pref = document.getElementById(aPref);
|
||||
this.radio = document.getElementById(aRadio);
|
||||
this.check = document.getElementById(aCheck);
|
||||
this.deck = document.getElementById(aDeck);
|
||||
this.backup = this.value || 1;
|
||||
this.askValue = aAskFlag;
|
||||
|
||||
if (this.askValue ? this.value & this.askValue : this.value == 0 ) {
|
||||
this.check.checked = true;
|
||||
this.deck.selectedIndex = 0;
|
||||
}
|
||||
else {
|
||||
this.check.checked = false;
|
||||
this.deck.selectedIndex = 1;
|
||||
}
|
||||
}
|
||||
RadioSet.prototype = {
|
||||
onChange : function(aDontUpdatePref)
|
||||
{
|
||||
if (this.checked) {
|
||||
this.backup = this.value;
|
||||
this.deck.selectedIndex = 0;
|
||||
if (this.askValue) {
|
||||
this.value |= this.askValue;
|
||||
}
|
||||
else {
|
||||
this.value = 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
this.deck.selectedIndex = 1;
|
||||
this.value = this.backup;
|
||||
if (this.askValue && this.value & this.askValue) {
|
||||
this.value ^= this.askValue;
|
||||
}
|
||||
}
|
||||
if (!aDontUpdatePref)
|
||||
this.pref.value = this.value;
|
||||
},
|
||||
|
||||
get checked()
|
||||
{
|
||||
return this.check.checked;
|
||||
},
|
||||
set checked(aValue)
|
||||
{
|
||||
return this.check.checked = aValue;
|
||||
},
|
||||
|
||||
get value()
|
||||
{
|
||||
return parseInt(this.radio.value);
|
||||
},
|
||||
set value(aValue)
|
||||
{
|
||||
return this.radio.value = aValue;
|
||||
}
|
||||
};
|
||||
Components.utils.import('resource://gre/modules/Services.jsm');
|
||||
|
||||
const XULAppInfo = Services.appinfo;
|
||||
const comparator = Services.vc;
|
||||
var Prefs = Services.prefs;
|
||||
|
||||
Components.utils.import('resource://treestyletab-modules/lib/animationManager.js', {});
|
||||
Components.utils.import('resource://treestyletab-modules/lib/prefs.js', {});
|
||||
Components.utils.import('resource://treestyletab-modules/lib/namespace.jsm');
|
||||
var animationManager = getNamespaceFor('piro.sakura.ne.jp')['piro.sakura.ne.jp'].animationManager;
|
||||
var prefs = getNamespaceFor('piro.sakura.ne.jp')['piro.sakura.ne.jp'].prefs;
|
||||
|
||||
|
||||
function syncEnabledState(aElement, aEnabled)
|
||||
{
|
||||
if (typeof aElement == 'string')
|
||||
aElement = document.getElementById(aElement);
|
||||
if (typeof aEnabled == 'string')
|
||||
aEnabled = (new Function('return '+aEnabled)).call(aElement);
|
||||
|
||||
aElement.getAttribute('sync-enabled-state-targets')
|
||||
.replace(/$\s+|\s+$/g, '')
|
||||
.split(/\s+/)
|
||||
.map(function(aId) {
|
||||
if (!aId)
|
||||
return;
|
||||
var target = document.getElementById(aId);
|
||||
if (aEnabled)
|
||||
target.removeAttribute('disabled');
|
||||
else
|
||||
target.setAttribute('disabled', true);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
var gGroupBookmarkRadio,
|
||||
gGroupBookmarkUnderParent,
|
||||
gGroupBookmarkType,
|
||||
gGroupBookmarkBehaviorPref;
|
||||
|
||||
function ensureGroupBookmarkItems()
|
||||
{
|
||||
if (gGroupBookmarkBehaviorPref) return;
|
||||
|
||||
gGroupBookmarkRadio = document.getElementById('openGroupBookmark-radiogroup');
|
||||
gGroupBookmarkUnderParent = document.getElementById('openGroupBookmark.underParent-check');
|
||||
gGroupBookmarkType = document.getElementById('openGroupBookmark.subtreeType-menulist');
|
||||
gGroupBookmarkBehaviorPref = document.getElementById('extensions.treestyletab.openGroupBookmark.behavior');
|
||||
}
|
||||
|
||||
function init()
|
||||
{
|
||||
ensureGroupBookmarkItems();
|
||||
|
||||
// sizeToContent();
|
||||
}
|
||||
|
||||
|
||||
function initAppearancePane()
|
||||
{
|
||||
onChangeTabbarPosition();
|
||||
|
||||
var sidebar = document.getElementById('extensions.treestyletab.tabbar.style-sidebar');
|
||||
sidebar.removeAttribute('disabled');
|
||||
|
||||
var boxes = [
|
||||
document.getElementById('extensions.treestyletab.tabbar.style-arrowscrollbox'),
|
||||
document.getElementById('extensions.treestyletab.twisty.style-arrowscrollbox')
|
||||
];
|
||||
Array.slice(boxes[0].childNodes).concat(Array.slice(boxes[1].childNodes)).forEach(function(aItem) {
|
||||
let start = 0;
|
||||
let delta = 200;
|
||||
let radian = 90 * Math.PI / 180;
|
||||
aItem.style.overflow = 'hidden';
|
||||
aItem.width = 0;
|
||||
aItem.style.maxWidth = 0;
|
||||
let task = function(aTime, aBeginning, aChange, aDuration) {
|
||||
var width;
|
||||
if (aTime >= aDuration) {
|
||||
width = start + delta;
|
||||
finished = true;
|
||||
}
|
||||
else {
|
||||
width = start + (delta * Math.sin(aTime / aDuration * radian));
|
||||
finished = false;
|
||||
}
|
||||
aItem.removeAttribute('width');
|
||||
aItem.style.maxWidth = parseInt(width)+'px';
|
||||
|
||||
var itemBox = aItem.boxObject;
|
||||
var parentBox = aItem.parentNode.boxObject;
|
||||
if (
|
||||
parentBox.screenX > itemBox.screenX ||
|
||||
parentBox.screenX + parentBox.width < itemBox.screenX + itemBox.width
|
||||
) {
|
||||
aItem.parentNode.setAttribute('overflow', true);
|
||||
if (aItem.selected)
|
||||
aItem.parentNode.scrollBoxObject.ensureElementIsVisible(aItem);
|
||||
}
|
||||
|
||||
if (finished) {
|
||||
start = null;
|
||||
delta = null;
|
||||
radian = null;
|
||||
aItem = null;
|
||||
}
|
||||
return finished;
|
||||
};
|
||||
animationManager.addTask(task, 0, 0, 500, window);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
var gDropLinksOnRadioSet,
|
||||
gGroupBookmarkRadioSet,
|
||||
gLastStateIsVertical;
|
||||
var gTabbarPlacePositionInitialized = false;
|
||||
|
||||
function initTabPane()
|
||||
{
|
||||
gDropLinksOnTabRadioSet = new RadioSet(
|
||||
'extensions.treestyletab.dropLinksOnTab.behavior',
|
||||
'dropLinksOnTab-radiogroup',
|
||||
'dropLinksOnTab-check',
|
||||
'dropLinksOnTab-deck'
|
||||
);
|
||||
gGroupBookmarkRadioSet = new RadioSet(
|
||||
'extensions.treestyletab.openGroupBookmark.behavior',
|
||||
'openGroupBookmark-radiogroup',
|
||||
'openGroupBookmark-check',
|
||||
'openGroupBookmark-deck'
|
||||
);
|
||||
|
||||
var newTabPref = document.getElementById('extensions.treestyletab.autoAttach.newTabButton-box');
|
||||
newTabPref.removeAttribute('hidden');
|
||||
}
|
||||
|
||||
function onSyncGroupBookmarkUIToPref()
|
||||
{
|
||||
ensureGroupBookmarkItems();
|
||||
var behavior = gGroupBookmarkBehaviorPref.value;
|
||||
if (behavior & 1) behavior ^= 1;
|
||||
if (behavior & 2) behavior ^= 2;
|
||||
if (behavior & 4) behavior ^= 4;
|
||||
if (behavior & 256) behavior ^= 256;
|
||||
if (behavior & 512) behavior ^= 512;
|
||||
|
||||
behavior |= parseInt(gGroupBookmarkRadio.value);
|
||||
|
||||
if (gGroupBookmarkUnderParent.checked) behavior |= 256;
|
||||
if (gGroupBookmarkType.value == 'true') behavior |= 512;
|
||||
|
||||
var nodes = [
|
||||
gGroupBookmarkUnderParent,
|
||||
gGroupBookmarkType,
|
||||
gGroupBookmarkType.previousSibling,
|
||||
gGroupBookmarkType.nextSibling
|
||||
];
|
||||
for (let i = 0, maxi = nodes.length; i < maxi; i++)
|
||||
{
|
||||
let node = nodes[i];
|
||||
if (behavior & 1)
|
||||
node.removeAttribute('disabled');
|
||||
else
|
||||
node.setAttribute('disabled', true);
|
||||
}
|
||||
|
||||
return behavior;
|
||||
}
|
||||
|
||||
function onSyncGroupBookmarkPrefToUI()
|
||||
{
|
||||
ensureGroupBookmarkItems();
|
||||
var behavior = gGroupBookmarkBehaviorPref.value & 1 ? 1 :
|
||||
gGroupBookmarkBehaviorPref.value & 2 ? 2 :
|
||||
gGroupBookmarkBehaviorPref.value & 4 ? 4 :
|
||||
0;
|
||||
gGroupBookmarkUnderParent.checked = !!(gGroupBookmarkBehaviorPref.value & 256);
|
||||
gGroupBookmarkType.value = gGroupBookmarkBehaviorPref.value & 512 ? 'true' : 'false' ;
|
||||
return behavior;
|
||||
}
|
||||
|
||||
|
||||
function onChangeTabbarPosition()
|
||||
{
|
||||
var pos = document.getElementById('extensions.treestyletab.tabbar.position-radiogroup').value;
|
||||
var invertTab = document.getElementById('extensions.treestyletab.tabbar.invertTab-check');
|
||||
var invertTabContents = document.getElementById('extensions.treestyletab.tabbar.invertTabContents-check');
|
||||
var invertClosebox = document.getElementById('extensions.treestyletab.tabbar.invertClosebox-check');
|
||||
|
||||
invertTab.disabled = pos != 'right';
|
||||
// invertTabContents.disabled = pos != 'right';
|
||||
invertClosebox.setAttribute('label',
|
||||
invertClosebox.getAttribute(
|
||||
(pos == 'right' && invertTabContents.checked) ?
|
||||
'label-right' :
|
||||
'label-left'
|
||||
)
|
||||
);
|
||||
if (invertClosebox.checked != document.getElementById('extensions.treestyletab.tabbar.invertClosebox').defaultValue)
|
||||
invertClosebox.removeAttribute('collapsed');
|
||||
else
|
||||
invertClosebox.setAttribute('collapsed', true);
|
||||
|
||||
var maxTreeLevelH = document.getElementById('maxTreeLevel-horizontal');
|
||||
var maxTreeLevelV = document.getElementById('maxTreeLevel-vertical');
|
||||
var collapseCheckH = document.getElementById('extensions.treestyletab.allowSubtreeCollapseExpand.horizontal-check');
|
||||
var collapseCheckV = document.getElementById('extensions.treestyletab.allowSubtreeCollapseExpand.vertical-check');
|
||||
|
||||
if (pos == 'left' || pos == 'right') {
|
||||
maxTreeLevelH.setAttribute('collapsed', true);
|
||||
maxTreeLevelV.removeAttribute('collapsed');
|
||||
collapseCheckH.setAttribute('collapsed', true);
|
||||
collapseCheckV.removeAttribute('collapsed');
|
||||
}
|
||||
else {
|
||||
maxTreeLevelH.removeAttribute('collapsed');
|
||||
maxTreeLevelV.setAttribute('collapsed', true);
|
||||
collapseCheckH.removeAttribute('collapsed');
|
||||
collapseCheckV.setAttribute('collapsed', true);
|
||||
}
|
||||
|
||||
gTabbarPlacePositionInitialized = true;
|
||||
}
|
||||
|
||||
function onSyncMaxTreeLevelUIToPref(aTarget, aSetPrefValue)
|
||||
{
|
||||
aTarget = document.getElementById(aTarget);
|
||||
if (aTarget.sync)
|
||||
return;
|
||||
aTarget.sync = true;
|
||||
|
||||
var textbox = aTarget.parentNode.getElementsByTagName('textbox')[0];
|
||||
var prefValue = aTarget.checked ? textbox.value : 0 ;
|
||||
|
||||
if (aSetPrefValue)
|
||||
document.getElementById(aTarget.getAttribute('preference')).value = prefValue;
|
||||
|
||||
aTarget.sync = false;
|
||||
return prefValue;
|
||||
}
|
||||
|
||||
function onSyncMaxTreeLevelPrefToUI(aTarget)
|
||||
{
|
||||
aTarget = document.getElementById(aTarget);
|
||||
if (aTarget.sync)
|
||||
return;
|
||||
aTarget.sync = true;
|
||||
|
||||
var pref = document.getElementById(aTarget.getAttribute('preference'));
|
||||
var value = pref.value;
|
||||
var UIValue = value != 0;
|
||||
|
||||
var textbox = aTarget.parentNode.getElementsByTagName('textbox')[0];
|
||||
|
||||
if (UIValue)
|
||||
textbox.value = value;
|
||||
|
||||
syncEnabledState(aTarget, UIValue);
|
||||
|
||||
aTarget.sync = false;
|
||||
return UIValue;
|
||||
}
|
||||
|
||||
|
||||
function initAutoHidePane()
|
||||
{
|
||||
syncEnabledState('extensions.treestyletab.tabbar.autoShow.mousemove-check', 'this.checked');
|
||||
syncEnabledState('extensions.treestyletab.tabbar.autoShow.accelKeyDown-check', 'this.checked');
|
||||
syncEnabledState('extensions.treestyletab.tabbar.autoShow.feedback-check', 'this.checked');
|
||||
}
|
||||
|
||||
function onChangeAutoHideMode(aRadioGroup, aTogglePref)
|
||||
{
|
||||
if (aRadioGroup.value != 0)
|
||||
document.getElementById(aTogglePref).value = aRadioGroup.value;
|
||||
}
|
||||
|
||||
|
||||
function initTreePane()
|
||||
{
|
||||
syncEnabledState('extensions.treestyletab.closeParentBehavior-radiogroup', 'this.value == 0');
|
||||
|
||||
var focusMode = document.getElementById('extensions.treestyletab.focusMode-check');
|
||||
var focusModePref = document.getElementById('extensions.treestyletab.focusMode');
|
||||
if (focusModePref.value != focusModePref.defaultValue)
|
||||
focusMode.removeAttribute('collapsed');
|
||||
else
|
||||
focusMode.setAttribute('collapsed', true);
|
||||
}
|
||||
|
||||
|
||||
var gBookmarkDroppedTabsRadioSet,
|
||||
gUndoCloseTabSetRadioSet;
|
||||
|
||||
function initAdvancedPane()
|
||||
{
|
||||
gBookmarkDroppedTabsRadioSet = new RadioSet(
|
||||
'extensions.treestyletab.bookmarkDroppedTabs.behavior',
|
||||
'bookmarkDroppedTabs-radiogroup',
|
||||
'bookmarkDroppedTabs-check',
|
||||
'bookmarkDroppedTabs-deck'
|
||||
);
|
||||
|
||||
gUndoCloseTabSetRadioSet = new RadioSet(
|
||||
'extensions.treestyletab.undoCloseTabSet.behavior',
|
||||
'undoCloseTabSet-radiogroup',
|
||||
'undoCloseTabSet-check',
|
||||
'undoCloseTabSet-deck',
|
||||
1
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
function RadioSet(aPref, aRadio, aCheck, aDeck, aAskFlag)
|
||||
{
|
||||
this.pref = document.getElementById(aPref);
|
||||
this.radio = document.getElementById(aRadio);
|
||||
this.check = document.getElementById(aCheck);
|
||||
this.deck = document.getElementById(aDeck);
|
||||
this.backup = this.value || 1;
|
||||
this.askValue = aAskFlag;
|
||||
|
||||
if (this.askValue ? this.value & this.askValue : this.value == 0 ) {
|
||||
this.check.checked = true;
|
||||
this.deck.selectedIndex = 0;
|
||||
}
|
||||
else {
|
||||
this.check.checked = false;
|
||||
this.deck.selectedIndex = 1;
|
||||
}
|
||||
}
|
||||
RadioSet.prototype = {
|
||||
onChange : function(aDontUpdatePref)
|
||||
{
|
||||
if (this.checked) {
|
||||
this.backup = this.value;
|
||||
this.deck.selectedIndex = 0;
|
||||
if (this.askValue) {
|
||||
this.value |= this.askValue;
|
||||
}
|
||||
else {
|
||||
this.value = 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
this.deck.selectedIndex = 1;
|
||||
this.value = this.backup;
|
||||
if (this.askValue && this.value & this.askValue) {
|
||||
this.value ^= this.askValue;
|
||||
}
|
||||
}
|
||||
if (!aDontUpdatePref)
|
||||
this.pref.value = this.value;
|
||||
},
|
||||
|
||||
get checked()
|
||||
{
|
||||
return this.check.checked;
|
||||
},
|
||||
set checked(aValue)
|
||||
{
|
||||
return this.check.checked = aValue;
|
||||
},
|
||||
|
||||
get value()
|
||||
{
|
||||
return parseInt(this.radio.value);
|
||||
},
|
||||
set value(aValue)
|
||||
{
|
||||
return this.radio.value = aValue;
|
||||
}
|
||||
};
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,50 +1,50 @@
|
||||
<?xml-stylesheet type="text/css" href="chrome://global/skin/"?>
|
||||
<?xml-stylesheet type="text/css" href="chrome://treestyletab/skin/group.css"?>
|
||||
<?xml-stylesheet type="text/css" href="chrome://treestyletab/skin/pseudo-tree.css"?>
|
||||
<!DOCTYPE page SYSTEM "chrome://treestyletab/locale/treestyletab.dtd">
|
||||
<page xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
title="&group.default;">
|
||||
<commandset>
|
||||
<command id="cmd_enterEdit" oncommand="groupTab.enterEdit()"/>
|
||||
</commandset>
|
||||
<keyset>
|
||||
<key keycode="VK_F2" command="cmd_enterEdit"/>
|
||||
</keyset>
|
||||
<stack flex="1">
|
||||
<box class="background-image-container">
|
||||
<image class="icon background-image"/>
|
||||
</box>
|
||||
<vbox class="label-container" flex="1">
|
||||
<hbox align="center">
|
||||
<deck id="deck" flex="1">
|
||||
<hbox align="center">
|
||||
<image class="icon"/>
|
||||
<label id="label"
|
||||
flex="1"
|
||||
crop="end"
|
||||
value="&group.default;"
|
||||
tooltiptext="&group.default;"/>
|
||||
</hbox>
|
||||
<hbox align="center">
|
||||
<image class="icon"/>
|
||||
<textbox id="editor"
|
||||
flex="1"
|
||||
value="&group.default;"/>
|
||||
</hbox>
|
||||
</deck>
|
||||
<checkbox id="temporary" label="&group.temporary;"
|
||||
oncommand="groupTab.temporary = this.checked;"/>
|
||||
</hbox>
|
||||
<vbox id="tree"
|
||||
flex="1"/>
|
||||
</vbox>
|
||||
</stack>
|
||||
<link xmlns="http://www.w3.org/1999/xhtml" rel="icon"
|
||||
href="chrome://treestyletab-group/skin/group.png"/>
|
||||
<script type="application/javascript"><![CDATA[
|
||||
|
||||
Components.utils.import('resource://treestyletab-modules/groupTab.js');
|
||||
new GroupTab(window);
|
||||
|
||||
]]></script>
|
||||
</page>
|
||||
<?xml-stylesheet type="text/css" href="chrome://global/skin/"?>
|
||||
<?xml-stylesheet type="text/css" href="chrome://treestyletab/skin/group.css"?>
|
||||
<?xml-stylesheet type="text/css" href="chrome://treestyletab/skin/pseudo-tree.css"?>
|
||||
<!DOCTYPE page SYSTEM "chrome://treestyletab/locale/treestyletab.dtd">
|
||||
<page xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
title="&group.default;">
|
||||
<commandset>
|
||||
<command id="cmd_enterEdit" oncommand="groupTab.enterEdit()"/>
|
||||
</commandset>
|
||||
<keyset>
|
||||
<key keycode="VK_F2" command="cmd_enterEdit"/>
|
||||
</keyset>
|
||||
<stack flex="1">
|
||||
<box class="background-image-container">
|
||||
<image class="icon background-image"/>
|
||||
</box>
|
||||
<vbox class="label-container" flex="1">
|
||||
<hbox align="center">
|
||||
<deck id="deck" flex="1">
|
||||
<hbox align="center">
|
||||
<image class="icon"/>
|
||||
<label id="label"
|
||||
flex="1"
|
||||
crop="end"
|
||||
value="&group.default;"
|
||||
tooltiptext="&group.default;"/>
|
||||
</hbox>
|
||||
<hbox align="center">
|
||||
<image class="icon"/>
|
||||
<textbox id="editor"
|
||||
flex="1"
|
||||
value="&group.default;"/>
|
||||
</hbox>
|
||||
</deck>
|
||||
<checkbox id="temporary" label="&group.temporary;"
|
||||
oncommand="groupTab.temporary = this.checked;"/>
|
||||
</hbox>
|
||||
<vbox id="tree"
|
||||
flex="1"/>
|
||||
</vbox>
|
||||
</stack>
|
||||
<link xmlns="http://www.w3.org/1999/xhtml" rel="icon"
|
||||
href="chrome://treestyletab-group/skin/group.png"/>
|
||||
<script type="application/javascript"><![CDATA[
|
||||
|
||||
Components.utils.import('resource://treestyletab-modules/groupTab.js');
|
||||
new GroupTab(window);
|
||||
|
||||
]]></script>
|
||||
</page>
|
||||
|
@ -1,5 +1,5 @@
|
||||
@namespace url("http://www.w3.org/1999/xhtml");
|
||||
|
||||
body > embed[name="plugin"] {
|
||||
visibility: hidden !important;
|
||||
}
|
||||
@namespace url("http://www.w3.org/1999/xhtml");
|
||||
|
||||
body > embed[name="plugin"] {
|
||||
visibility: hidden !important;
|
||||
}
|
||||
|
@ -1,35 +1,35 @@
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
|
||||
The contents of these files are subject to the Mozilla Public License Version
|
||||
1.1 (the "License"); you may not use these files 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 YUKI "Piro" Hiroshi.
|
||||
Portions created by the Initial Developer are Copyright (C) 2007-2014
|
||||
the Initial Developer. All Rights Reserved.
|
||||
|
||||
Contributor(s): YUKI "Piro" Hiroshi <piro.outsider.reflex@gmail.com>
|
||||
Alice0775 (fixes some compatibility problems)
|
||||
|
||||
Alternatively, the contents of these files 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 these files only
|
||||
under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
use your version of these files 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 these files under
|
||||
the terms of any one of the MPL, the GPL or the LGPL.
|
||||
|
||||
***** END LICENSE BLOCK *****
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
|
||||
The contents of these files are subject to the Mozilla Public License Version
|
||||
1.1 (the "License"); you may not use these files 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 YUKI "Piro" Hiroshi.
|
||||
Portions created by the Initial Developer are Copyright (C) 2007-2014
|
||||
the Initial Developer. All Rights Reserved.
|
||||
|
||||
Contributor(s): YUKI "Piro" Hiroshi <piro.outsider.reflex@gmail.com>
|
||||
Alice0775 (fixes some compatibility problems)
|
||||
|
||||
Alternatively, the contents of these files 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 these files only
|
||||
under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
use your version of these files 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 these files under
|
||||
the terms of any one of the MPL, the GPL or the LGPL.
|
||||
|
||||
***** END LICENSE BLOCK *****
|
||||
|
@ -1,22 +1,22 @@
|
||||
<?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"/>
|
||||
<preference id="extensions.multipletab.show.multipletab-selection-item-createSubtree"
|
||||
name="extensions.multipletab.show.multipletab-selection-item-createSubtree"
|
||||
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;"/>
|
||||
<checkbox id="extensions.multipletab.show.multipletab-selection-item-createSubtree-check"
|
||||
preference="extensions.multipletab.show.multipletab-selection-item-createSubtree"
|
||||
label="&selection.createSubtree.label;"/>
|
||||
</vbox>
|
||||
|
||||
</overlay>
|
||||
<?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"/>
|
||||
<preference id="extensions.multipletab.show.multipletab-selection-item-createSubtree"
|
||||
name="extensions.multipletab.show.multipletab-selection-item-createSubtree"
|
||||
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;"/>
|
||||
<checkbox id="extensions.multipletab.show.multipletab-selection-item-createSubtree-check"
|
||||
preference="extensions.multipletab.show.multipletab-selection-item-createSubtree"
|
||||
label="&selection.createSubtree.label;"/>
|
||||
</vbox>
|
||||
|
||||
</overlay>
|
||||
|
@ -1,33 +1,33 @@
|
||||
@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
|
||||
|
||||
/* hacks for Tab Mix Plus */
|
||||
|
||||
:root[treestyletab-enable-compatibility-tmp="true"]
|
||||
tabbrowser[treestyletab-mode="vertical"] #vide-bar,
|
||||
:root[treestyletab-enable-compatibility-tmp="true"]
|
||||
tabbrowser[treestyletab-mode="vertical"] #tabs-scroll-up-down-box,
|
||||
:root[treestyletab-enable-compatibility-tmp="true"]
|
||||
tabbrowser[treestyletab-mode="vertical"] #alltabs-place-holder,
|
||||
:root[treestyletab-enable-compatibility-tmp="true"]
|
||||
tabbrowser[treestyletab-mode="vertical"] .tabs-scroll {
|
||||
visibility: collapse !important;
|
||||
}
|
||||
|
||||
:root[treestyletab-enable-compatibility-tmp="true"]
|
||||
tabbrowser[treestyletab-mode="vertical"] tabs[flowing] > * .tabs-frame {
|
||||
overflow-x: hidden !important;
|
||||
overflow-y: auto !important;
|
||||
}
|
||||
|
||||
:root[treestyletab-enable-compatibility-tmp="true"]
|
||||
tabbrowser[treestyletab-mode="vertical"] tabs[flowing] > * .tabs-frame {
|
||||
box-flex: 1 !important;
|
||||
-moz-box-flex: 1 !important;
|
||||
}
|
||||
|
||||
.tabbrowser-tab[pinned] > .tab-image-left,
|
||||
.tabbrowser-tab[pinned] > .tab-drag-indicator-left,
|
||||
.tabbrowser-tab[pinned] > .tab-drag-indicator-right,
|
||||
.tabbrowser-tab[pinned] > .tab-image-right {
|
||||
display: none;
|
||||
}
|
||||
@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
|
||||
|
||||
/* hacks for Tab Mix Plus */
|
||||
|
||||
:root[treestyletab-enable-compatibility-tmp="true"]
|
||||
tabbrowser[treestyletab-mode="vertical"] #vide-bar,
|
||||
:root[treestyletab-enable-compatibility-tmp="true"]
|
||||
tabbrowser[treestyletab-mode="vertical"] #tabs-scroll-up-down-box,
|
||||
:root[treestyletab-enable-compatibility-tmp="true"]
|
||||
tabbrowser[treestyletab-mode="vertical"] #alltabs-place-holder,
|
||||
:root[treestyletab-enable-compatibility-tmp="true"]
|
||||
tabbrowser[treestyletab-mode="vertical"] .tabs-scroll {
|
||||
visibility: collapse !important;
|
||||
}
|
||||
|
||||
:root[treestyletab-enable-compatibility-tmp="true"]
|
||||
tabbrowser[treestyletab-mode="vertical"] tabs[flowing] > * .tabs-frame {
|
||||
overflow-x: hidden !important;
|
||||
overflow-y: auto !important;
|
||||
}
|
||||
|
||||
:root[treestyletab-enable-compatibility-tmp="true"]
|
||||
tabbrowser[treestyletab-mode="vertical"] tabs[flowing] > * .tabs-frame {
|
||||
box-flex: 1 !important;
|
||||
-moz-box-flex: 1 !important;
|
||||
}
|
||||
|
||||
.tabbrowser-tab[pinned] > .tab-image-left,
|
||||
.tabbrowser-tab[pinned] > .tab-drag-indicator-left,
|
||||
.tabbrowser-tab[pinned] > .tab-drag-indicator-right,
|
||||
.tabbrowser-tab[pinned] > .tab-image-right {
|
||||
display: none;
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,23 +1,23 @@
|
||||
(function() {
|
||||
/**
|
||||
* On secondary (and later) window, SSWindowStateBusy event can be fired
|
||||
* before DOMContentLoad, on "domwindowopened".
|
||||
*/
|
||||
var SSWindowStateBusyListener = function TSTSSWindowStateBusyListener(aEvent) {
|
||||
window.removeEventListener(aEvent.type, TSTSSWindowStateBusyListener, false);
|
||||
window.__treestyletab__WindowStateBusy = true;
|
||||
SSWindowStateBusyListener = undefined;
|
||||
};
|
||||
window.addEventListener('SSWindowStateBusy', SSWindowStateBusyListener, false);
|
||||
window.addEventListener('DOMContentLoad', function onDOMContentLoad(aEvent) {
|
||||
window.removeEventListener(aEvent.type, onDOMContentLoad, false);
|
||||
if (SSWindowStateBusyListener) {
|
||||
window.removeEventListener('SSWindowStateBusy', TSTSSWindowStateBusyListener, false);
|
||||
SSWindowStateBusyListener = undefined;
|
||||
}
|
||||
}, false);
|
||||
|
||||
var ns = {};
|
||||
Components.utils.import('resource://treestyletab-modules/window.js', ns);
|
||||
new ns.TreeStyleTabWindow(window);
|
||||
})();
|
||||
(function() {
|
||||
/**
|
||||
* On secondary (and later) window, SSWindowStateBusy event can be fired
|
||||
* before DOMContentLoad, on "domwindowopened".
|
||||
*/
|
||||
var SSWindowStateBusyListener = function TSTSSWindowStateBusyListener(aEvent) {
|
||||
window.removeEventListener(aEvent.type, TSTSSWindowStateBusyListener, false);
|
||||
window.__treestyletab__WindowStateBusy = true;
|
||||
SSWindowStateBusyListener = undefined;
|
||||
};
|
||||
window.addEventListener('SSWindowStateBusy', SSWindowStateBusyListener, false);
|
||||
window.addEventListener('DOMContentLoad', function onDOMContentLoad(aEvent) {
|
||||
window.removeEventListener(aEvent.type, onDOMContentLoad, false);
|
||||
if (SSWindowStateBusyListener) {
|
||||
window.removeEventListener('SSWindowStateBusy', TSTSSWindowStateBusyListener, false);
|
||||
SSWindowStateBusyListener = undefined;
|
||||
}
|
||||
}, false);
|
||||
|
||||
var ns = {};
|
||||
Components.utils.import('resource://treestyletab-modules/window.js', ns);
|
||||
new ns.TreeStyleTabWindow(window);
|
||||
})();
|
||||
|
@ -1,54 +1,54 @@
|
||||
<?xml version="1.0"?>
|
||||
|
||||
<bindings xmlns="http://www.mozilla.org/xbl"
|
||||
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
xmlns:xbl="http://www.mozilla.org/xbl">
|
||||
|
||||
<binding id="tab-icon"
|
||||
display="xul:stack">
|
||||
<content>
|
||||
<xul:image xbl:inherits="validate,src" class="tab-icon-image"/>
|
||||
<xbl:children/>
|
||||
</content>
|
||||
</binding>
|
||||
|
||||
<!--
|
||||
If these bindings are unexpectedly re-assigned, then all attributes
|
||||
(including sizes) are lost and the appearance becomes broken.
|
||||
To prevent this problem, the inner box should inherit all attributes
|
||||
given via setTabbrowserAttribute() method, from the parent element.
|
||||
See also: https://github.com/piroor/treestyletab/issues/538
|
||||
|
||||
On some versions, these inheritence are done by xbl:constructor.
|
||||
However, it causes infinitely loop on some environments, so
|
||||
now I use xbl:inherits.
|
||||
See also: https://github.com/piroor/treestyletab/issues/550
|
||||
-->
|
||||
|
||||
<binding id="toolbar"
|
||||
extends="chrome://treestyletab/content/base-toolbar-binding.xml#toolbar">
|
||||
<content><xul:hbox flex="1"
|
||||
xbl:inherits="orient,width,height,treestyletab-allow-subtree-collapse,treestyletab-animation-enabled,treestyletab-closebox-inverted,treestyletab-firsttab-border,treestyletab-invert-scrollbar,treestyletab-max-tree-level,treestyletab-mode,treestyletab-narrow-scrollbar,treestyletab-print-preview,treestyletab-stack-collapsed-tabs,treestyletab-style,treestyletab-tab-contents-inverted,treestyletab-tab-inverted,treestyletab-tabbar-autohide,treestyletab-tabbar-autohide-state,treestyletab-tabbar-fixed,treestyletab-tabbar-fixed-horizontal,treestyletab-tabbar-fixed-vertical,treestyletab-tabbar-position,treestyletab-tabbar-resizing,treestyletab-tabs-indented,treestyletab-twisty-style"
|
||||
anonid="toolbar-innerbox"
|
||||
class="treestyletab-toolbar-inner-box"><xbl:children/></xul:hbox></content>
|
||||
<implementation>
|
||||
<field name="treeStyleTabToolbarInnerBox" readonly="true">
|
||||
document.getAnonymousElementByAttribute(this, 'anonid', 'toolbar-innerbox')
|
||||
</field>
|
||||
</implementation>
|
||||
</binding>
|
||||
|
||||
<binding id="toolbar-drag"
|
||||
extends="chrome://treestyletab/content/base-toolbar-binding.xml#toolbar-drag">
|
||||
<content><xul:hbox flex="1"
|
||||
xbl:inherits="orient,width,height,treestyletab-allow-subtree-collapse,treestyletab-animation-enabled,treestyletab-closebox-inverted,treestyletab-firsttab-border,treestyletab-invert-scrollbar,treestyletab-max-tree-level,treestyletab-mode,treestyletab-narrow-scrollbar,treestyletab-print-preview,treestyletab-stack-collapsed-tabs,treestyletab-style,treestyletab-tab-contents-inverted,treestyletab-tab-inverted,treestyletab-tabbar-autohide,treestyletab-tabbar-autohide-state,treestyletab-tabbar-fixed,treestyletab-tabbar-fixed-horizontal,treestyletab-tabbar-fixed-vertical,treestyletab-tabbar-position,treestyletab-tabbar-resizing,treestyletab-tabs-indented,treestyletab-twisty-style"
|
||||
anonid="toolbar-innerbox"
|
||||
class="treestyletab-toolbar-inner-box"><xbl:children/></xul:hbox></content>
|
||||
<implementation>
|
||||
<field name="treeStyleTabToolbarInnerBox" readonly="true">
|
||||
document.getAnonymousElementByAttribute(this, 'anonid', 'toolbar-innerbox')
|
||||
</field>
|
||||
</implementation>
|
||||
</binding>
|
||||
|
||||
</bindings>
|
||||
<?xml version="1.0"?>
|
||||
|
||||
<bindings xmlns="http://www.mozilla.org/xbl"
|
||||
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
xmlns:xbl="http://www.mozilla.org/xbl">
|
||||
|
||||
<binding id="tab-icon"
|
||||
display="xul:stack">
|
||||
<content>
|
||||
<xul:image xbl:inherits="validate,src" class="tab-icon-image"/>
|
||||
<xbl:children/>
|
||||
</content>
|
||||
</binding>
|
||||
|
||||
<!--
|
||||
If these bindings are unexpectedly re-assigned, then all attributes
|
||||
(including sizes) are lost and the appearance becomes broken.
|
||||
To prevent this problem, the inner box should inherit all attributes
|
||||
given via setTabbrowserAttribute() method, from the parent element.
|
||||
See also: https://github.com/piroor/treestyletab/issues/538
|
||||
|
||||
On some versions, these inheritence are done by xbl:constructor.
|
||||
However, it causes infinitely loop on some environments, so
|
||||
now I use xbl:inherits.
|
||||
See also: https://github.com/piroor/treestyletab/issues/550
|
||||
-->
|
||||
|
||||
<binding id="toolbar"
|
||||
extends="chrome://treestyletab/content/base-toolbar-binding.xml#toolbar">
|
||||
<content><xul:hbox flex="1"
|
||||
xbl:inherits="orient,width,height,treestyletab-allow-subtree-collapse,treestyletab-animation-enabled,treestyletab-closebox-inverted,treestyletab-firsttab-border,treestyletab-invert-scrollbar,treestyletab-max-tree-level,treestyletab-mode,treestyletab-narrow-scrollbar,treestyletab-print-preview,treestyletab-stack-collapsed-tabs,treestyletab-style,treestyletab-tab-contents-inverted,treestyletab-tab-inverted,treestyletab-tabbar-autohide,treestyletab-tabbar-autohide-state,treestyletab-tabbar-fixed,treestyletab-tabbar-fixed-horizontal,treestyletab-tabbar-fixed-vertical,treestyletab-tabbar-position,treestyletab-tabbar-resizing,treestyletab-tabs-indented,treestyletab-twisty-style"
|
||||
anonid="toolbar-innerbox"
|
||||
class="treestyletab-toolbar-inner-box"><xbl:children/></xul:hbox></content>
|
||||
<implementation>
|
||||
<field name="treeStyleTabToolbarInnerBox" readonly="true">
|
||||
document.getAnonymousElementByAttribute(this, 'anonid', 'toolbar-innerbox')
|
||||
</field>
|
||||
</implementation>
|
||||
</binding>
|
||||
|
||||
<binding id="toolbar-drag"
|
||||
extends="chrome://treestyletab/content/base-toolbar-binding.xml#toolbar-drag">
|
||||
<content><xul:hbox flex="1"
|
||||
xbl:inherits="orient,width,height,treestyletab-allow-subtree-collapse,treestyletab-animation-enabled,treestyletab-closebox-inverted,treestyletab-firsttab-border,treestyletab-invert-scrollbar,treestyletab-max-tree-level,treestyletab-mode,treestyletab-narrow-scrollbar,treestyletab-print-preview,treestyletab-stack-collapsed-tabs,treestyletab-style,treestyletab-tab-contents-inverted,treestyletab-tab-inverted,treestyletab-tabbar-autohide,treestyletab-tabbar-autohide-state,treestyletab-tabbar-fixed,treestyletab-tabbar-fixed-horizontal,treestyletab-tabbar-fixed-vertical,treestyletab-tabbar-position,treestyletab-tabbar-resizing,treestyletab-tabs-indented,treestyletab-twisty-style"
|
||||
anonid="toolbar-innerbox"
|
||||
class="treestyletab-toolbar-inner-box"><xbl:children/></xul:hbox></content>
|
||||
<implementation>
|
||||
<field name="treeStyleTabToolbarInnerBox" readonly="true">
|
||||
document.getAnonymousElementByAttribute(this, 'anonid', 'toolbar-innerbox')
|
||||
</field>
|
||||
</implementation>
|
||||
</binding>
|
||||
|
||||
</bindings>
|
||||
|
@ -1,152 +1,152 @@
|
||||
<?xml version="1.0"?>
|
||||
|
||||
<?xml-stylesheet href="treestyletab.css" type="text/css"?>
|
||||
<?xml-stylesheet href="treestyletab-tmp.css" type="text/css"?><!-- hacks for Tab Mix Plus -->
|
||||
|
||||
<?xml-stylesheet href="chrome://treestyletab/skin/base.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://treestyletab/skin/twisty/twisty.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://treestyletab/skin/ui.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://treestyletab/skin/tmp.css" type="text/css"?><!-- hacks for Tab Mix Plus -->
|
||||
<?xml-stylesheet href="chrome://treestyletab/skin/platform-base.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://treestyletab/skin/pseudo-tree.css" type="text/css"?>
|
||||
|
||||
<!DOCTYPE overlay SYSTEM "chrome://treestyletab/locale/treestyletab.dtd">
|
||||
<overlay id="treestyletab-overlay"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
|
||||
<script src="res/stopRendering.js" type="application/javascript"/>
|
||||
<script src="res/tabsDragUtils.js" type="application/javascript"/>
|
||||
<script src="treestyletab.js" type="application/javascript"/>
|
||||
<script src="windowHelper.js" type="application/javascript"/>
|
||||
<script src="windowHelperHacks.js" type="application/javascript"/>
|
||||
<script src="bookmarksOverlay.js" type="application/javascript"/>
|
||||
<script src="bookmarksOverlayEditable.js" type="application/javascript"/>
|
||||
|
||||
|
||||
<script type="application/javascript"><![CDATA[
|
||||
// for backward compatibility
|
||||
var TreeStyleTabBrowserAutoHide = TreeStyleTabService.autoHideWindow;
|
||||
|
||||
// preload images
|
||||
TreeStyleTabService.observe(
|
||||
null,
|
||||
'nsPref:changed',
|
||||
'extensions.treestyletab.tabbar.style'
|
||||
);
|
||||
]]></script>
|
||||
|
||||
|
||||
<!-- Multiple Tab Handler -->
|
||||
<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());"
|
||||
multipletab-available="selectedTabs.length"/>
|
||||
<menuitem id="multipletab-selection-item-createSubtree"
|
||||
insertafter="multipletab-selection-splitWindow"
|
||||
label="&selection.createSubtree.label;"
|
||||
accesskey="&selection.createSubtree.accesskey;"
|
||||
oncommand="TreeStyleTabService.createSubtree(MultipleTabService.getSelectedTabs());"
|
||||
multipletab-enabled="TreeStyleTabService.canCreateSubtree(selectedTabs)"/>
|
||||
</menupopup>
|
||||
|
||||
<popupset id="mainPopupSet">
|
||||
<menupopup id="multipletab-tabcontext-menu-template">
|
||||
|
||||
<menuitem id="context-item-reloadTabSubtree"
|
||||
label="&context.reloadTabSubtree.label;"
|
||||
accesskey="&context.reloadTabSubtree.accesskey;"
|
||||
oncommand="TreeStyleTabService.reloadTabSubtree(TreeStyleTabService.getTabBrowserFromChild(this).mContextTab);"
|
||||
onclick="if (event.button == 1 || (event.button == 0 && TreeStyleTabService.isAccelKeyPressed(event))) {
|
||||
TreeStyleTabService.reloadTabSubtree(TreeStyleTabService.getTabBrowserFromChild(this).mContextTab, true);
|
||||
event.stopPropagation();
|
||||
this.parentNode.hidePopup();
|
||||
}"
|
||||
multipletab-insertafter="tabContextMenu.querySelector("*[id^='context_reloadTab']")"/>
|
||||
<menuitem id="context-item-reloadDescendantTabs"
|
||||
label="&context.reloadDescendantTabs.label;"
|
||||
accesskey="&context.reloadDescendantTabs.accesskey;"
|
||||
oncommand="TreeStyleTabService.reloadTabSubtree(TreeStyleTabService.getTabBrowserFromChild(this).mContextTab, true);"
|
||||
onclick="if (event.button == 1 || (event.button == 0 && TreeStyleTabService.isAccelKeyPressed(event))) {
|
||||
TreeStyleTabService.reloadTabSubtree(TreeStyleTabService.getTabBrowserFromChild(this).mContextTab);
|
||||
event.stopPropagation();
|
||||
this.parentNode.hidePopup();
|
||||
}"
|
||||
multipletab-insertafter="tabContextMenu.querySelector("*[id^='context-item-reloadTabSubtree']")"/>
|
||||
|
||||
<menuitem id="context-item-removeTabSubtree"
|
||||
label="&context.removeTabSubtree.label;"
|
||||
accesskey="&context.removeTabSubtree.accesskey;"
|
||||
oncommand="TreeStyleTabService.removeTabSubtree(TreeStyleTabService.getTabBrowserFromChild(this).mContextTab);"
|
||||
onclick="if (event.button == 1 || (event.button == 0 && TreeStyleTabService.isAccelKeyPressed(event))) {
|
||||
TreeStyleTabService.removeTabSubtree(TreeStyleTabService.getTabBrowserFromChild(this).mContextTab, true);
|
||||
event.stopPropagation();
|
||||
this.parentNode.hidePopup();
|
||||
}"
|
||||
multipletab-insertbefore="TreeStyleTabService.evaluateXPath(
|
||||
"(descendant::*[starts-with(@id, 'multipletab-context-removeAll') | starts-with(@id, 'context_closeTab')][1] | child::xul:menuitem[last()])/preceding-sibling::xul:menuseparator[1]"
|
||||
, tabContextMenu, XPathResult.FIRST_ORDERED_NODE_TYPE).singleNodeValue"/>
|
||||
<menuitem id="context-item-removeDescendantTabs"
|
||||
label="&context.removeDescendantTabs.label;"
|
||||
accesskey="&context.removeDescendantTabs.accesskey;"
|
||||
oncommand="TreeStyleTabService.removeTabSubtree(TreeStyleTabService.getTabBrowserFromChild(this).mContextTab, true);"
|
||||
onclick="if (event.button == 1 || (event.button == 0 && TreeStyleTabService.isAccelKeyPressed(event))) {
|
||||
TreeStyleTabService.removeTabSubtree(TreeStyleTabService.getTabBrowserFromChild(this).mContextTab);
|
||||
event.stopPropagation();
|
||||
this.parentNode.hidePopup();
|
||||
}"
|
||||
multipletab-insertafter="tabContextMenu.querySelector("*[id^='context-item-removeTabSubtree']")"/>
|
||||
<menuitem id="context-item-removeAllTabsButThisTree"
|
||||
label="&context.removeAllTabsBut.label;"
|
||||
accesskey="&context.removeAllTabsBut.accesskey;"
|
||||
oncommand="TreeStyleTabService.removeAllTabsBut(TreeStyleTabService.getTabBrowserFromChild(this).mContextTab);"
|
||||
multipletab-insertafter="tabContextMenu.querySelector("*[id^='context_closeOtherTabs']")"/>
|
||||
|
||||
<menuitem id="context-item-bookmarkTabSubtree"
|
||||
label="&context.bookmarkTabSubtree.label;"
|
||||
accesskey="&context.bookmarkTabSubtree.accesskey;"
|
||||
oncommand="TreeStyleTabBookmarksService.bookmarkTabSubtree(TreeStyleTabService.getTabBrowserFromChild(this).mContextTab);"
|
||||
multipletab-insertafter="TreeStyleTabService.evaluateXPath(
|
||||
"descendant::*[starts-with(@id, 'context_bookmarkTab')][1] | descendant::*[@command='Browser:BookmarkAllTabs']/preceding-sibling[1]"
|
||||
, tabContextMenu, XPathResult.FIRST_ORDERED_NODE_TYPE).singleNodeValue"/>
|
||||
|
||||
|
||||
<!-- simply appended items -->
|
||||
|
||||
<menuseparator id="context-separator-collapseExpandAll"/>
|
||||
<menuitem id="context-item-collapseAllSubtree"
|
||||
label="&context.collapseAllSubtree.label;"
|
||||
accesskey="&context.collapseAllSubtree.accesskey;"
|
||||
oncommand="TreeStyleTabService.getTabBrowserFromChild(this).treeStyleTab.collapseExpandAllSubtree(true);"/>
|
||||
<menuitem id="context-item-expandAllSubtree"
|
||||
label="&context.expandAllSubtree.label;"
|
||||
accesskey="&context.expandAllSubtree.accesskey;"
|
||||
oncommand="TreeStyleTabService.getTabBrowserFromChild(this).treeStyleTab.collapseExpandAllSubtree(false);"/>
|
||||
|
||||
<menuseparator id="context-separator-toggleAutoHide"/>
|
||||
<menuitem id="context-item-toggleAutoHide"
|
||||
label="&context.toggleAutoHide.label;"
|
||||
accesskey="&context.toggleAutoHide.accesskey;"
|
||||
type="checkbox"
|
||||
autocheck="false"
|
||||
oncommand="TreeStyleTabService.toggleAutoHide(TreeStyleTabService.getTabBrowserFromChild(this));"/>
|
||||
<menuitem id="context-item-toggleFixed"
|
||||
label="&context.toggleFixed.label;"
|
||||
label-horizontal="&context.toggleFixed.label.horizontal;"
|
||||
label-vertical="&context.toggleFixed.label.vertical;"
|
||||
accesskey="&context.toggleFixed.accesskey;"
|
||||
type="checkbox"
|
||||
autocheck="false"
|
||||
oncommand="TreeStyleTabService.toggleFixed(TreeStyleTabService.getTabBrowserFromChild(this));"/>
|
||||
</menupopup>
|
||||
<tooltip id="treestyletab-full-tree-tooltip"/>
|
||||
<panel id="treestyletab-autohide-content-area-screen"
|
||||
treestyletab-ignore-state="true"
|
||||
onpopupshown="if ('setConsumeRollupEvent' in this.popupBoxObject) this.popupBoxObject.setConsumeRollupEvent(Components.interfaces.nsIPopupBoxObject.ROLLUP_NO_CONSUME);"
|
||||
onclick="this.hidePopup();"
|
||||
onDOMMouseScroll="this.hidePopup()"/>
|
||||
</popupset>
|
||||
|
||||
</overlay>
|
||||
<?xml version="1.0"?>
|
||||
|
||||
<?xml-stylesheet href="treestyletab.css" type="text/css"?>
|
||||
<?xml-stylesheet href="treestyletab-tmp.css" type="text/css"?><!-- hacks for Tab Mix Plus -->
|
||||
|
||||
<?xml-stylesheet href="chrome://treestyletab/skin/base.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://treestyletab/skin/twisty/twisty.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://treestyletab/skin/ui.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://treestyletab/skin/tmp.css" type="text/css"?><!-- hacks for Tab Mix Plus -->
|
||||
<?xml-stylesheet href="chrome://treestyletab/skin/platform-base.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://treestyletab/skin/pseudo-tree.css" type="text/css"?>
|
||||
|
||||
<!DOCTYPE overlay SYSTEM "chrome://treestyletab/locale/treestyletab.dtd">
|
||||
<overlay id="treestyletab-overlay"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
|
||||
<script src="res/stopRendering.js" type="application/javascript"/>
|
||||
<script src="res/tabsDragUtils.js" type="application/javascript"/>
|
||||
<script src="treestyletab.js" type="application/javascript"/>
|
||||
<script src="windowHelper.js" type="application/javascript"/>
|
||||
<script src="windowHelperHacks.js" type="application/javascript"/>
|
||||
<script src="bookmarksOverlay.js" type="application/javascript"/>
|
||||
<script src="bookmarksOverlayEditable.js" type="application/javascript"/>
|
||||
|
||||
|
||||
<script type="application/javascript"><![CDATA[
|
||||
// for backward compatibility
|
||||
var TreeStyleTabBrowserAutoHide = TreeStyleTabService.autoHideWindow;
|
||||
|
||||
// preload images
|
||||
TreeStyleTabService.observe(
|
||||
null,
|
||||
'nsPref:changed',
|
||||
'extensions.treestyletab.tabbar.style'
|
||||
);
|
||||
]]></script>
|
||||
|
||||
|
||||
<!-- Multiple Tab Handler -->
|
||||
<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());"
|
||||
multipletab-available="selectedTabs.length"/>
|
||||
<menuitem id="multipletab-selection-item-createSubtree"
|
||||
insertafter="multipletab-selection-splitWindow"
|
||||
label="&selection.createSubtree.label;"
|
||||
accesskey="&selection.createSubtree.accesskey;"
|
||||
oncommand="TreeStyleTabService.createSubtree(MultipleTabService.getSelectedTabs());"
|
||||
multipletab-enabled="TreeStyleTabService.canCreateSubtree(selectedTabs)"/>
|
||||
</menupopup>
|
||||
|
||||
<popupset id="mainPopupSet">
|
||||
<menupopup id="multipletab-tabcontext-menu-template">
|
||||
|
||||
<menuitem id="context-item-reloadTabSubtree"
|
||||
label="&context.reloadTabSubtree.label;"
|
||||
accesskey="&context.reloadTabSubtree.accesskey;"
|
||||
oncommand="TreeStyleTabService.reloadTabSubtree(TreeStyleTabService.getTabBrowserFromChild(this).mContextTab);"
|
||||
onclick="if (event.button == 1 || (event.button == 0 && TreeStyleTabService.isAccelKeyPressed(event))) {
|
||||
TreeStyleTabService.reloadTabSubtree(TreeStyleTabService.getTabBrowserFromChild(this).mContextTab, true);
|
||||
event.stopPropagation();
|
||||
this.parentNode.hidePopup();
|
||||
}"
|
||||
multipletab-insertafter="tabContextMenu.querySelector("*[id^='context_reloadTab']")"/>
|
||||
<menuitem id="context-item-reloadDescendantTabs"
|
||||
label="&context.reloadDescendantTabs.label;"
|
||||
accesskey="&context.reloadDescendantTabs.accesskey;"
|
||||
oncommand="TreeStyleTabService.reloadTabSubtree(TreeStyleTabService.getTabBrowserFromChild(this).mContextTab, true);"
|
||||
onclick="if (event.button == 1 || (event.button == 0 && TreeStyleTabService.isAccelKeyPressed(event))) {
|
||||
TreeStyleTabService.reloadTabSubtree(TreeStyleTabService.getTabBrowserFromChild(this).mContextTab);
|
||||
event.stopPropagation();
|
||||
this.parentNode.hidePopup();
|
||||
}"
|
||||
multipletab-insertafter="tabContextMenu.querySelector("*[id^='context-item-reloadTabSubtree']")"/>
|
||||
|
||||
<menuitem id="context-item-removeTabSubtree"
|
||||
label="&context.removeTabSubtree.label;"
|
||||
accesskey="&context.removeTabSubtree.accesskey;"
|
||||
oncommand="TreeStyleTabService.removeTabSubtree(TreeStyleTabService.getTabBrowserFromChild(this).mContextTab);"
|
||||
onclick="if (event.button == 1 || (event.button == 0 && TreeStyleTabService.isAccelKeyPressed(event))) {
|
||||
TreeStyleTabService.removeTabSubtree(TreeStyleTabService.getTabBrowserFromChild(this).mContextTab, true);
|
||||
event.stopPropagation();
|
||||
this.parentNode.hidePopup();
|
||||
}"
|
||||
multipletab-insertbefore="TreeStyleTabService.evaluateXPath(
|
||||
"(descendant::*[starts-with(@id, 'multipletab-context-removeAll') | starts-with(@id, 'context_closeTab')][1] | child::xul:menuitem[last()])/preceding-sibling::xul:menuseparator[1]"
|
||||
, tabContextMenu, XPathResult.FIRST_ORDERED_NODE_TYPE).singleNodeValue"/>
|
||||
<menuitem id="context-item-removeDescendantTabs"
|
||||
label="&context.removeDescendantTabs.label;"
|
||||
accesskey="&context.removeDescendantTabs.accesskey;"
|
||||
oncommand="TreeStyleTabService.removeTabSubtree(TreeStyleTabService.getTabBrowserFromChild(this).mContextTab, true);"
|
||||
onclick="if (event.button == 1 || (event.button == 0 && TreeStyleTabService.isAccelKeyPressed(event))) {
|
||||
TreeStyleTabService.removeTabSubtree(TreeStyleTabService.getTabBrowserFromChild(this).mContextTab);
|
||||
event.stopPropagation();
|
||||
this.parentNode.hidePopup();
|
||||
}"
|
||||
multipletab-insertafter="tabContextMenu.querySelector("*[id^='context-item-removeTabSubtree']")"/>
|
||||
<menuitem id="context-item-removeAllTabsButThisTree"
|
||||
label="&context.removeAllTabsBut.label;"
|
||||
accesskey="&context.removeAllTabsBut.accesskey;"
|
||||
oncommand="TreeStyleTabService.removeAllTabsBut(TreeStyleTabService.getTabBrowserFromChild(this).mContextTab);"
|
||||
multipletab-insertafter="tabContextMenu.querySelector("*[id^='context_closeOtherTabs']")"/>
|
||||
|
||||
<menuitem id="context-item-bookmarkTabSubtree"
|
||||
label="&context.bookmarkTabSubtree.label;"
|
||||
accesskey="&context.bookmarkTabSubtree.accesskey;"
|
||||
oncommand="TreeStyleTabBookmarksService.bookmarkTabSubtree(TreeStyleTabService.getTabBrowserFromChild(this).mContextTab);"
|
||||
multipletab-insertafter="TreeStyleTabService.evaluateXPath(
|
||||
"descendant::*[starts-with(@id, 'context_bookmarkTab')][1] | descendant::*[@command='Browser:BookmarkAllTabs']/preceding-sibling[1]"
|
||||
, tabContextMenu, XPathResult.FIRST_ORDERED_NODE_TYPE).singleNodeValue"/>
|
||||
|
||||
|
||||
<!-- simply appended items -->
|
||||
|
||||
<menuseparator id="context-separator-collapseExpandAll"/>
|
||||
<menuitem id="context-item-collapseAllSubtree"
|
||||
label="&context.collapseAllSubtree.label;"
|
||||
accesskey="&context.collapseAllSubtree.accesskey;"
|
||||
oncommand="TreeStyleTabService.getTabBrowserFromChild(this).treeStyleTab.collapseExpandAllSubtree(true);"/>
|
||||
<menuitem id="context-item-expandAllSubtree"
|
||||
label="&context.expandAllSubtree.label;"
|
||||
accesskey="&context.expandAllSubtree.accesskey;"
|
||||
oncommand="TreeStyleTabService.getTabBrowserFromChild(this).treeStyleTab.collapseExpandAllSubtree(false);"/>
|
||||
|
||||
<menuseparator id="context-separator-toggleAutoHide"/>
|
||||
<menuitem id="context-item-toggleAutoHide"
|
||||
label="&context.toggleAutoHide.label;"
|
||||
accesskey="&context.toggleAutoHide.accesskey;"
|
||||
type="checkbox"
|
||||
autocheck="false"
|
||||
oncommand="TreeStyleTabService.toggleAutoHide(TreeStyleTabService.getTabBrowserFromChild(this));"/>
|
||||
<menuitem id="context-item-toggleFixed"
|
||||
label="&context.toggleFixed.label;"
|
||||
label-horizontal="&context.toggleFixed.label.horizontal;"
|
||||
label-vertical="&context.toggleFixed.label.vertical;"
|
||||
accesskey="&context.toggleFixed.accesskey;"
|
||||
type="checkbox"
|
||||
autocheck="false"
|
||||
oncommand="TreeStyleTabService.toggleFixed(TreeStyleTabService.getTabBrowserFromChild(this));"/>
|
||||
</menupopup>
|
||||
<tooltip id="treestyletab-full-tree-tooltip"/>
|
||||
<panel id="treestyletab-autohide-content-area-screen"
|
||||
treestyletab-ignore-state="true"
|
||||
onpopupshown="if ('setConsumeRollupEvent' in this.popupBoxObject) this.popupBoxObject.setConsumeRollupEvent(Components.interfaces.nsIPopupBoxObject.ROLLUP_NO_CONSUME);"
|
||||
onclick="this.hidePopup();"
|
||||
onDOMMouseScroll="this.hidePopup()"/>
|
||||
</popupset>
|
||||
|
||||
</overlay>
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
2808
modules/autoHide.js
2808
modules/autoHide.js
File diff suppressed because it is too large
Load Diff
5150
modules/base.js
5150
modules/base.js
File diff suppressed because it is too large
Load Diff
13624
modules/browser.js
13624
modules/browser.js
File diff suppressed because it is too large
Load Diff
@ -1,127 +1,127 @@
|
||||
/* ***** 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 YUKI "Piro" Hiroshi.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2013
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s): YUKI "Piro" Hiroshi <piro.outsider.reflex@gmail.com>
|
||||
* Infocatcher <https://github.com/Infocatcher>
|
||||
*
|
||||
* 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 = ['BrowserUIShowHideObserver'];
|
||||
|
||||
Components.utils.import('resource://treestyletab-modules/constants.js');
|
||||
|
||||
function BrowserUIShowHideObserver(aOwner, aBox) {
|
||||
this.owner = aOwner;
|
||||
this.box = aBox;
|
||||
this.init();
|
||||
}
|
||||
BrowserUIShowHideObserver.prototype = {
|
||||
get MutationObserver()
|
||||
{
|
||||
var w = this.box.ownerDocument.defaultView;
|
||||
return w.MutationObserver || w.MozMutationObserver;
|
||||
},
|
||||
|
||||
init : function BrowserUIShowHideObserver_onInit()
|
||||
{
|
||||
if (!this.MutationObserver)
|
||||
return;
|
||||
this.observer = new this.MutationObserver((function(aMutations, aObserver) {
|
||||
this.onMutation(aMutations, aObserver);
|
||||
}).bind(this));
|
||||
this.observer.observe(this.box, {
|
||||
childList : true,
|
||||
attributes : true,
|
||||
subtree : true,
|
||||
attributeFilter : [
|
||||
'hidden',
|
||||
'collapsed',
|
||||
'moz-collapsed', // Used in full screen mode
|
||||
'disablechrome'
|
||||
]
|
||||
});
|
||||
},
|
||||
onMutation : function BrowserUIShowHideObserver_onMutation(aMutations, aObserver)
|
||||
{
|
||||
aMutations.forEach(function(aMutation) {
|
||||
switch (aMutation.type)
|
||||
{
|
||||
case 'childList':
|
||||
if (aMutation.target == this.box)
|
||||
this.owner.browser.treeStyleTab.updateFloatingTabbar(TreeStyleTabConstants.kTABBAR_UPDATE_BY_WINDOW_RESIZE);
|
||||
return;
|
||||
|
||||
case 'attributes':
|
||||
this.onAttributeModified(aMutation, aObserver);
|
||||
return;
|
||||
}
|
||||
}, this);
|
||||
},
|
||||
|
||||
destroy : function BrowserUIShowHideObserver_destroy()
|
||||
{
|
||||
if (this.observer) {
|
||||
this.observer.disconnect();
|
||||
delete this.observer;
|
||||
}
|
||||
delete this.box;
|
||||
delete this.owner;
|
||||
},
|
||||
|
||||
onAttributeModified : function BrowserUIShowHideObserver_onAttributeModified(aMutation, aObserver)
|
||||
{
|
||||
if (this.handlingAttrChange)
|
||||
return;
|
||||
|
||||
var TST = this.owner.browser.treeStyleTab;
|
||||
if (
|
||||
// I must ignore show/hide of elements managed by TST,
|
||||
// to avoid infinity loop.
|
||||
aMutation.target.hasAttribute(TreeStyleTabConstants.kTAB_STRIP_ELEMENT) &&
|
||||
// However, I have to synchronize visibility of the real
|
||||
// tab bar and the placeholder's one. If they have
|
||||
// different visibility, then the tab bar is shown or
|
||||
// hidden by "auto hide tab bar" feature of someone
|
||||
// (Pale Moon, Tab Mix Plus, etc.)
|
||||
this.owner.browser.tabContainer.visible != TST.tabStripPlaceHolder.collapsed
|
||||
)
|
||||
return;
|
||||
|
||||
this.handlingAttrChange = true;
|
||||
|
||||
TST.updateFloatingTabbar(TreeStyleTabConstants.kTABBAR_UPDATE_BY_WINDOW_RESIZE);
|
||||
|
||||
var w = this.box.ownerDocument.defaultView;
|
||||
w.setTimeout((function() {
|
||||
this.handlingAttrChange = false;
|
||||
}).bind(this), 10);
|
||||
}
|
||||
};
|
||||
/* ***** 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 YUKI "Piro" Hiroshi.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2013
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s): YUKI "Piro" Hiroshi <piro.outsider.reflex@gmail.com>
|
||||
* Infocatcher <https://github.com/Infocatcher>
|
||||
*
|
||||
* 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 = ['BrowserUIShowHideObserver'];
|
||||
|
||||
Components.utils.import('resource://treestyletab-modules/constants.js');
|
||||
|
||||
function BrowserUIShowHideObserver(aOwner, aBox) {
|
||||
this.owner = aOwner;
|
||||
this.box = aBox;
|
||||
this.init();
|
||||
}
|
||||
BrowserUIShowHideObserver.prototype = {
|
||||
get MutationObserver()
|
||||
{
|
||||
var w = this.box.ownerDocument.defaultView;
|
||||
return w.MutationObserver || w.MozMutationObserver;
|
||||
},
|
||||
|
||||
init : function BrowserUIShowHideObserver_onInit()
|
||||
{
|
||||
if (!this.MutationObserver)
|
||||
return;
|
||||
this.observer = new this.MutationObserver((function(aMutations, aObserver) {
|
||||
this.onMutation(aMutations, aObserver);
|
||||
}).bind(this));
|
||||
this.observer.observe(this.box, {
|
||||
childList : true,
|
||||
attributes : true,
|
||||
subtree : true,
|
||||
attributeFilter : [
|
||||
'hidden',
|
||||
'collapsed',
|
||||
'moz-collapsed', // Used in full screen mode
|
||||
'disablechrome'
|
||||
]
|
||||
});
|
||||
},
|
||||
onMutation : function BrowserUIShowHideObserver_onMutation(aMutations, aObserver)
|
||||
{
|
||||
aMutations.forEach(function(aMutation) {
|
||||
switch (aMutation.type)
|
||||
{
|
||||
case 'childList':
|
||||
if (aMutation.target == this.box)
|
||||
this.owner.browser.treeStyleTab.updateFloatingTabbar(TreeStyleTabConstants.kTABBAR_UPDATE_BY_WINDOW_RESIZE);
|
||||
return;
|
||||
|
||||
case 'attributes':
|
||||
this.onAttributeModified(aMutation, aObserver);
|
||||
return;
|
||||
}
|
||||
}, this);
|
||||
},
|
||||
|
||||
destroy : function BrowserUIShowHideObserver_destroy()
|
||||
{
|
||||
if (this.observer) {
|
||||
this.observer.disconnect();
|
||||
delete this.observer;
|
||||
}
|
||||
delete this.box;
|
||||
delete this.owner;
|
||||
},
|
||||
|
||||
onAttributeModified : function BrowserUIShowHideObserver_onAttributeModified(aMutation, aObserver)
|
||||
{
|
||||
if (this.handlingAttrChange)
|
||||
return;
|
||||
|
||||
var TST = this.owner.browser.treeStyleTab;
|
||||
if (
|
||||
// I must ignore show/hide of elements managed by TST,
|
||||
// to avoid infinity loop.
|
||||
aMutation.target.hasAttribute(TreeStyleTabConstants.kTAB_STRIP_ELEMENT) &&
|
||||
// However, I have to synchronize visibility of the real
|
||||
// tab bar and the placeholder's one. If they have
|
||||
// different visibility, then the tab bar is shown or
|
||||
// hidden by "auto hide tab bar" feature of someone
|
||||
// (Pale Moon, Tab Mix Plus, etc.)
|
||||
this.owner.browser.tabContainer.visible != TST.tabStripPlaceHolder.collapsed
|
||||
)
|
||||
return;
|
||||
|
||||
this.handlingAttrChange = true;
|
||||
|
||||
TST.updateFloatingTabbar(TreeStyleTabConstants.kTABBAR_UPDATE_BY_WINDOW_RESIZE);
|
||||
|
||||
var w = this.box.ownerDocument.defaultView;
|
||||
w.setTimeout((function() {
|
||||
this.handlingAttrChange = false;
|
||||
}).bind(this), 10);
|
||||
}
|
||||
};
|
||||
|
@ -1,206 +1,206 @@
|
||||
/* ***** 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 YUKI "Piro" Hiroshi.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010-2014
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s): YUKI "Piro" Hiroshi <piro.outsider.reflex@gmail.com>
|
||||
* Tetsuharu OHZEKI <https://github.com/saneyuki>
|
||||
*
|
||||
* 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 = ['TreeStyleTabConstants'];
|
||||
|
||||
const TreeStyleTabConstants = Object.freeze({
|
||||
/* attributes */
|
||||
kID : 'treestyletab-id',
|
||||
kCHILDREN : 'treestyletab-children',
|
||||
kPARENT : 'treestyletab-parent',
|
||||
kANCESTOR : 'treestyletab-ancestors',
|
||||
kNEST : 'treestyletab-nest',
|
||||
kINSERT_BEFORE : 'treestyletab-insert-before',
|
||||
kINSERT_AFTER : 'treestyletab-insert-after',
|
||||
kCLOSED_SET_ID : 'treestyletab-closed-set-id',
|
||||
|
||||
kID_NEW : 'treestyletab-id-new',
|
||||
kID_RESTORING : 'treestyletab-id-restoring',
|
||||
kCHILDREN_RESTORING : 'treestyletab-children-restoring',
|
||||
|
||||
kSUBTREE_COLLAPSED : 'treestyletab-subtree-collapsed',
|
||||
kSUBTREE_EXPANDED_MANUALLY : 'treestyletab-subtree-expanded-manually',
|
||||
kCOLLAPSED : 'treestyletab-collapsed',
|
||||
kCOLLAPSED_DONE : 'treestyletab-collapsed-done',
|
||||
kCOLLAPSING_PHASE : 'treestyletab-collapsing-phase',
|
||||
kCOLLAPSING_PHASE_TO_BE_COLLAPSED : 'collapse',
|
||||
kCOLLAPSING_PHASE_TO_BE_EXPANDED : 'expand',
|
||||
kALLOW_COLLAPSE : 'treestyletab-allow-subtree-collapse',
|
||||
kALLOW_STACK : 'treestyletab-stack-collapsed-tabs',
|
||||
kREMOVED : 'treestyletab-removed',
|
||||
|
||||
kX_OFFSET : 'treestyletab-x-offset',
|
||||
kY_OFFSET : 'treestyletab-y-offset',
|
||||
|
||||
kTABBAR_POSITION : 'treestyletab-tabbar-position',
|
||||
kMODE : 'treestyletab-mode',
|
||||
|
||||
kHIDE_NEWTAB : 'treestyletab-hide-newtab-button',
|
||||
kSTYLE : 'treestyletab-style',
|
||||
kFIRSTTAB_BORDER : 'treestyletab-firsttab-border',
|
||||
kFIXED : 'treestyletab-tabbar-fixed',
|
||||
kRESIZING : 'treestyletab-tabbar-resizing',
|
||||
kINDENTED : 'treestyletab-tabs-indented',
|
||||
kMAX_LEVEL : 'treestyletab-max-tree-level',
|
||||
kPRINT_PREVIEW : 'treestyletab-print-preview',
|
||||
kANIMATION_ENABLED : 'treestyletab-animation-enabled',
|
||||
kINVERT_SCROLLBAR : 'treestyletab-invert-scrollbar',
|
||||
kNARROW_SCROLLBAR : 'treestyletab-narrow-scrollbar',
|
||||
kFAVICONIZED : 'treestyletab-faviconized',
|
||||
kBG_NOTIFY_PHASE : 'treestyletab-notifybgtab-phase',
|
||||
kIGNORE_POPUP_STATE : 'treestyletab-ignore-state',
|
||||
kDOM_FULLSCREEN_ACTIVATED : 'treestyletab-dom-fullscreen-activated',
|
||||
|
||||
kTAB_INVERTED : 'treestyletab-tab-inverted',
|
||||
kTAB_CONTENTS_INVERTED : 'treestyletab-tab-contents-inverted',
|
||||
kCLOSEBOX_INVERTED : 'treestyletab-closebox-inverted',
|
||||
|
||||
kTWISTY_HOVER : 'treestyletab-twisty-hover',
|
||||
kTWISTY_STYLE : 'treestyletab-twisty-style',
|
||||
|
||||
kDROP_POSITION : 'treestyletab-drop-position',
|
||||
kDRAG_TYPE_TABBAR : 'application/x-moz-treestyletab-tabbrowser-tabbar',
|
||||
kDROP_POSITION_UNKNOWN : 'unknown',
|
||||
kTABBAR_MOVE_FORCE : 'force',
|
||||
kTABBAR_MOVE_NORMAL : 'normal',
|
||||
|
||||
kTAB_STRIP_ELEMENT : 'treestyletab-tabstrip-element',
|
||||
|
||||
/* classes */
|
||||
kTWISTY : 'treestyletab-twisty',
|
||||
kCOUNTER : 'treestyletab-counter',
|
||||
kCOUNTER_CONTAINER : 'treestyletab-counter-container',
|
||||
kCOUNTER_PAREN : 'treestyletab-counter-paren',
|
||||
kSPLITTER : 'treestyletab-splitter',
|
||||
kTABBAR_TOGGLER : 'treestyletab-tabbar-toggler',
|
||||
kTABBAR_PLACEHOLDER : 'treestyletab-tabbar-placeholder',
|
||||
kTABBAR_TOOLBAR : 'treestyletab-tabbar-toolbar',
|
||||
kTABBAR_TOOLBAR_READY : 'treestyletab-tabbar-toolbar-ready',
|
||||
kTABBAR_TOOLBAR_READY_POPUP : 'treestyletab-tabbar-toolbar-ready-popup',
|
||||
|
||||
/* event types, topics */
|
||||
kEVENT_TYPE_TAB_FOCUS_SWITCHING_KEY_DOWN : 'nsDOMTreeStyleTabFocusSwitchingKeyDown',
|
||||
kEVENT_TYPE_TAB_FOCUS_SWITCHING_START : 'nsDOMTreeStyleTabFocusSwitchingStart',
|
||||
kEVENT_TYPE_TAB_FOCUS_SWITCHING_END : 'nsDOMTreeStyleTabFocusSwitchingEnd',
|
||||
kTAB_FOCUS_SWITCHING_SCROLL_DOWN : (1 << 0),
|
||||
kTAB_FOCUS_SWITCHING_SCROLL_UP : (1 << 1),
|
||||
kTAB_FOCUS_SWITCHING_STAND_BY : (1 << 2),
|
||||
kTAB_FOCUS_SWITCHING_ONLY_SHIFT_KEY : (1 << 3),
|
||||
kEVENT_TYPE_SUBTREE_CLOSING : 'nsDOMTreeStyleTabSubtreeClosing',
|
||||
kEVENT_TYPE_SUBTREE_CLOSED : 'nsDOMTreeStyleTabSubtreeClosed',
|
||||
kEVENT_TYPE_TAB_COLLAPSED_STATE_CHANGED : 'nsDOMTreeStyleTabCollapsedStateChange',
|
||||
kEVENT_TYPE_TABBAR_INITIALIZED : 'nsDOMTreeStyleTabTabbarInitialized',
|
||||
kEVENT_TYPE_TABBAR_POSITION_CHANGING : 'nsDOMTreeStyleTabTabbarPositionChanging',
|
||||
kEVENT_TYPE_TABBAR_POSITION_CHANGED : 'nsDOMTreeStyleTabTabbarPositionChanged',
|
||||
kEVENT_TYPE_TABBAR_STATE_CHANGING : 'nsDOMTreeStyleTabTabbarStateChanging',
|
||||
kEVENT_TYPE_TABBAR_STATE_CHANGED : 'nsDOMTreeStyleTabTabbarStateChanged',
|
||||
kEVENT_TYPE_FOCUS_NEXT_TAB : 'nsDOMTreeStyleTabFocusNextTab',
|
||||
kEVENT_TYPE_ATTACHED : 'nsDOMTreeStyleTabAttached',
|
||||
kEVENT_TYPE_DETACHED : 'nsDOMTreeStyleTabParted',
|
||||
|
||||
kEVENT_TYPE_PRINT_PREVIEW_ENTERED : 'nsDOMTreeStyleTabPrintPreviewEntered',
|
||||
kEVENT_TYPE_PRINT_PREVIEW_EXITED : 'nsDOMTreeStyleTabPrintPreviewExited',
|
||||
kEVENT_TYPE_AUTO_HIDE_STATE_CHANGING : 'nsDOMTreeStyleTabAutoHideStateChanging',
|
||||
kEVENT_TYPE_AUTO_HIDE_STATE_CHANGE : 'nsDOMTreeStyleTabAutoHideStateChange',
|
||||
|
||||
kTOPIC_INDENT_MODIFIED : 'TreeStyleTab:indentModified',
|
||||
kTOPIC_COLLAPSE_EXPAND_ALL : 'TreeStyleTab:collapseExpandAllSubtree',
|
||||
kTOPIC_CHANGE_TREEVIEW_AVAILABILITY : 'TreeStyleTab:changeTreeViewAvailability',
|
||||
|
||||
/* other constant values */
|
||||
kFOCUS_ALL : 0,
|
||||
kFOCUS_VISIBLE : 1,
|
||||
|
||||
kDROP_BEFORE : -1,
|
||||
kDROP_ON : 0,
|
||||
kDROP_AFTER : 1,
|
||||
|
||||
kACTION_MOVE : 1 << 0,
|
||||
kACTION_STAY : 1 << 1,
|
||||
kACTION_DUPLICATE : 1 << 2,
|
||||
kACTION_IMPORT : 1 << 3,
|
||||
kACTION_NEWTAB : 1 << 4,
|
||||
kACTION_ATTACH : 1 << 10,
|
||||
kACTION_PART : 1 << 11,
|
||||
kACTIONS_FOR_SOURCE : (1 << 0) | (1 << 1),
|
||||
kACTIONS_FOR_DESTINATION : (1 << 2) | (1 << 3),
|
||||
|
||||
kTABBAR_TOP : 1 << 0,
|
||||
kTABBAR_BOTTOM : 1 << 1,
|
||||
kTABBAR_LEFT : 1 << 2,
|
||||
kTABBAR_RIGHT : 1 << 3,
|
||||
|
||||
kTABBAR_HORIZONTAL : (1 << 0) | (1 << 1),
|
||||
kTABBAR_VERTICAL : (1 << 2) | (1 << 3),
|
||||
kTABBAR_REGULAR : (1 << 0) | (1 << 2),
|
||||
kTABBAR_INVERTED : (1 << 3) | (1 << 4),
|
||||
|
||||
kINSERT_FISRT : 0,
|
||||
kINSERT_LAST : 1,
|
||||
|
||||
kTABBAR_UPDATE_BY_UNKNOWN_REASON : (1 << 0),
|
||||
kTABBAR_UPDATE_BY_RESET : (1 << 1),
|
||||
kTABBAR_UPDATE_BY_PREF_CHANGE : (1 << 2),
|
||||
kTABBAR_UPDATE_BY_APPEARANCE_CHANGE : (1 << 3),
|
||||
kTABBAR_UPDATE_BY_SHOWHIDE_TABBAR : (1 << 4),
|
||||
kTABBAR_UPDATE_BY_TABBAR_RESIZE : (1 << 5),
|
||||
kTABBAR_UPDATE_BY_WINDOW_RESIZE : (1 << 6),
|
||||
kTABBAR_UPDATE_BY_FULLSCREEN : (1 << 7),
|
||||
kTABBAR_UPDATE_BY_AUTOHIDE : (1 << 9),
|
||||
kTABBAR_UPDATE_BY_INITIALIZE : (1 << 10),
|
||||
kTABBAR_UPDATE_BY_TOGGLE_SIDEBAR : (1 << 11),
|
||||
kTABBAR_UPDATE_NOW : (1 << 5) | (1 << 6) | (1 << 9) | (1 << 10),
|
||||
kTABBAR_UPDATE_SYNC_TO_TABBAR : (1 << 0) | (1 << 1) | (1 << 2) | (1 << 5) | (1 << 9),
|
||||
kTABBAR_UPDATE_SYNC_TO_PLACEHOLDER : (1 << 3) | (1 << 4) | (1 << 6) | (1 << 7) | (1 << 10) | (1 << 11),
|
||||
|
||||
kCLOSE_PARENT_BEHAVIOR_PROMOTE_FIRST_CHILD : 3,
|
||||
kCLOSE_PARENT_BEHAVIOR_PROMOTE_ALL_CHILDREN : 0,
|
||||
kCLOSE_PARENT_BEHAVIOR_DETACH_ALL_CHILDREN : 1,
|
||||
kCLOSE_PARENT_BEHAVIOR_SIMPLY_DETACH_ALL_CHILDREN : 4,
|
||||
kCLOSE_PARENT_BEHAVIOR_CLOSE_ALL_CHILDREN : 2, // onTabRemoved only
|
||||
|
||||
kRESTORE_TREE_LEVEL_NONE : 0,
|
||||
kRESTORE_TREE_ONLY_VISIBLE : 1,
|
||||
kRESTORE_TREE_ALL : 2,
|
||||
|
||||
kCOUNTER_ROLE_ALL_TABS : 1,
|
||||
kCOUNTER_ROLE_CONTAINED_TABS : 2,
|
||||
|
||||
MAX_TABBAR_SIZE_RATIO : 0.8,
|
||||
DEFAULT_SHRUNKEN_WIDTH_RATIO : 0.67,
|
||||
MIN_TABBAR_WIDTH : 24,
|
||||
MIN_TABBAR_HEIGHT : 24
|
||||
});
|
||||
/* ***** 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 YUKI "Piro" Hiroshi.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010-2014
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s): YUKI "Piro" Hiroshi <piro.outsider.reflex@gmail.com>
|
||||
* Tetsuharu OHZEKI <https://github.com/saneyuki>
|
||||
*
|
||||
* 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 = ['TreeStyleTabConstants'];
|
||||
|
||||
const TreeStyleTabConstants = Object.freeze({
|
||||
/* attributes */
|
||||
kID : 'treestyletab-id',
|
||||
kCHILDREN : 'treestyletab-children',
|
||||
kPARENT : 'treestyletab-parent',
|
||||
kANCESTOR : 'treestyletab-ancestors',
|
||||
kNEST : 'treestyletab-nest',
|
||||
kINSERT_BEFORE : 'treestyletab-insert-before',
|
||||
kINSERT_AFTER : 'treestyletab-insert-after',
|
||||
kCLOSED_SET_ID : 'treestyletab-closed-set-id',
|
||||
|
||||
kID_NEW : 'treestyletab-id-new',
|
||||
kID_RESTORING : 'treestyletab-id-restoring',
|
||||
kCHILDREN_RESTORING : 'treestyletab-children-restoring',
|
||||
|
||||
kSUBTREE_COLLAPSED : 'treestyletab-subtree-collapsed',
|
||||
kSUBTREE_EXPANDED_MANUALLY : 'treestyletab-subtree-expanded-manually',
|
||||
kCOLLAPSED : 'treestyletab-collapsed',
|
||||
kCOLLAPSED_DONE : 'treestyletab-collapsed-done',
|
||||
kCOLLAPSING_PHASE : 'treestyletab-collapsing-phase',
|
||||
kCOLLAPSING_PHASE_TO_BE_COLLAPSED : 'collapse',
|
||||
kCOLLAPSING_PHASE_TO_BE_EXPANDED : 'expand',
|
||||
kALLOW_COLLAPSE : 'treestyletab-allow-subtree-collapse',
|
||||
kALLOW_STACK : 'treestyletab-stack-collapsed-tabs',
|
||||
kREMOVED : 'treestyletab-removed',
|
||||
|
||||
kX_OFFSET : 'treestyletab-x-offset',
|
||||
kY_OFFSET : 'treestyletab-y-offset',
|
||||
|
||||
kTABBAR_POSITION : 'treestyletab-tabbar-position',
|
||||
kMODE : 'treestyletab-mode',
|
||||
|
||||
kHIDE_NEWTAB : 'treestyletab-hide-newtab-button',
|
||||
kSTYLE : 'treestyletab-style',
|
||||
kFIRSTTAB_BORDER : 'treestyletab-firsttab-border',
|
||||
kFIXED : 'treestyletab-tabbar-fixed',
|
||||
kRESIZING : 'treestyletab-tabbar-resizing',
|
||||
kINDENTED : 'treestyletab-tabs-indented',
|
||||
kMAX_LEVEL : 'treestyletab-max-tree-level',
|
||||
kPRINT_PREVIEW : 'treestyletab-print-preview',
|
||||
kANIMATION_ENABLED : 'treestyletab-animation-enabled',
|
||||
kINVERT_SCROLLBAR : 'treestyletab-invert-scrollbar',
|
||||
kNARROW_SCROLLBAR : 'treestyletab-narrow-scrollbar',
|
||||
kFAVICONIZED : 'treestyletab-faviconized',
|
||||
kBG_NOTIFY_PHASE : 'treestyletab-notifybgtab-phase',
|
||||
kIGNORE_POPUP_STATE : 'treestyletab-ignore-state',
|
||||
kDOM_FULLSCREEN_ACTIVATED : 'treestyletab-dom-fullscreen-activated',
|
||||
|
||||
kTAB_INVERTED : 'treestyletab-tab-inverted',
|
||||
kTAB_CONTENTS_INVERTED : 'treestyletab-tab-contents-inverted',
|
||||
kCLOSEBOX_INVERTED : 'treestyletab-closebox-inverted',
|
||||
|
||||
kTWISTY_HOVER : 'treestyletab-twisty-hover',
|
||||
kTWISTY_STYLE : 'treestyletab-twisty-style',
|
||||
|
||||
kDROP_POSITION : 'treestyletab-drop-position',
|
||||
kDRAG_TYPE_TABBAR : 'application/x-moz-treestyletab-tabbrowser-tabbar',
|
||||
kDROP_POSITION_UNKNOWN : 'unknown',
|
||||
kTABBAR_MOVE_FORCE : 'force',
|
||||
kTABBAR_MOVE_NORMAL : 'normal',
|
||||
|
||||
kTAB_STRIP_ELEMENT : 'treestyletab-tabstrip-element',
|
||||
|
||||
/* classes */
|
||||
kTWISTY : 'treestyletab-twisty',
|
||||
kCOUNTER : 'treestyletab-counter',
|
||||
kCOUNTER_CONTAINER : 'treestyletab-counter-container',
|
||||
kCOUNTER_PAREN : 'treestyletab-counter-paren',
|
||||
kSPLITTER : 'treestyletab-splitter',
|
||||
kTABBAR_TOGGLER : 'treestyletab-tabbar-toggler',
|
||||
kTABBAR_PLACEHOLDER : 'treestyletab-tabbar-placeholder',
|
||||
kTABBAR_TOOLBAR : 'treestyletab-tabbar-toolbar',
|
||||
kTABBAR_TOOLBAR_READY : 'treestyletab-tabbar-toolbar-ready',
|
||||
kTABBAR_TOOLBAR_READY_POPUP : 'treestyletab-tabbar-toolbar-ready-popup',
|
||||
|
||||
/* event types, topics */
|
||||
kEVENT_TYPE_TAB_FOCUS_SWITCHING_KEY_DOWN : 'nsDOMTreeStyleTabFocusSwitchingKeyDown',
|
||||
kEVENT_TYPE_TAB_FOCUS_SWITCHING_START : 'nsDOMTreeStyleTabFocusSwitchingStart',
|
||||
kEVENT_TYPE_TAB_FOCUS_SWITCHING_END : 'nsDOMTreeStyleTabFocusSwitchingEnd',
|
||||
kTAB_FOCUS_SWITCHING_SCROLL_DOWN : (1 << 0),
|
||||
kTAB_FOCUS_SWITCHING_SCROLL_UP : (1 << 1),
|
||||
kTAB_FOCUS_SWITCHING_STAND_BY : (1 << 2),
|
||||
kTAB_FOCUS_SWITCHING_ONLY_SHIFT_KEY : (1 << 3),
|
||||
kEVENT_TYPE_SUBTREE_CLOSING : 'nsDOMTreeStyleTabSubtreeClosing',
|
||||
kEVENT_TYPE_SUBTREE_CLOSED : 'nsDOMTreeStyleTabSubtreeClosed',
|
||||
kEVENT_TYPE_TAB_COLLAPSED_STATE_CHANGED : 'nsDOMTreeStyleTabCollapsedStateChange',
|
||||
kEVENT_TYPE_TABBAR_INITIALIZED : 'nsDOMTreeStyleTabTabbarInitialized',
|
||||
kEVENT_TYPE_TABBAR_POSITION_CHANGING : 'nsDOMTreeStyleTabTabbarPositionChanging',
|
||||
kEVENT_TYPE_TABBAR_POSITION_CHANGED : 'nsDOMTreeStyleTabTabbarPositionChanged',
|
||||
kEVENT_TYPE_TABBAR_STATE_CHANGING : 'nsDOMTreeStyleTabTabbarStateChanging',
|
||||
kEVENT_TYPE_TABBAR_STATE_CHANGED : 'nsDOMTreeStyleTabTabbarStateChanged',
|
||||
kEVENT_TYPE_FOCUS_NEXT_TAB : 'nsDOMTreeStyleTabFocusNextTab',
|
||||
kEVENT_TYPE_ATTACHED : 'nsDOMTreeStyleTabAttached',
|
||||
kEVENT_TYPE_DETACHED : 'nsDOMTreeStyleTabParted',
|
||||
|
||||
kEVENT_TYPE_PRINT_PREVIEW_ENTERED : 'nsDOMTreeStyleTabPrintPreviewEntered',
|
||||
kEVENT_TYPE_PRINT_PREVIEW_EXITED : 'nsDOMTreeStyleTabPrintPreviewExited',
|
||||
kEVENT_TYPE_AUTO_HIDE_STATE_CHANGING : 'nsDOMTreeStyleTabAutoHideStateChanging',
|
||||
kEVENT_TYPE_AUTO_HIDE_STATE_CHANGE : 'nsDOMTreeStyleTabAutoHideStateChange',
|
||||
|
||||
kTOPIC_INDENT_MODIFIED : 'TreeStyleTab:indentModified',
|
||||
kTOPIC_COLLAPSE_EXPAND_ALL : 'TreeStyleTab:collapseExpandAllSubtree',
|
||||
kTOPIC_CHANGE_TREEVIEW_AVAILABILITY : 'TreeStyleTab:changeTreeViewAvailability',
|
||||
|
||||
/* other constant values */
|
||||
kFOCUS_ALL : 0,
|
||||
kFOCUS_VISIBLE : 1,
|
||||
|
||||
kDROP_BEFORE : -1,
|
||||
kDROP_ON : 0,
|
||||
kDROP_AFTER : 1,
|
||||
|
||||
kACTION_MOVE : 1 << 0,
|
||||
kACTION_STAY : 1 << 1,
|
||||
kACTION_DUPLICATE : 1 << 2,
|
||||
kACTION_IMPORT : 1 << 3,
|
||||
kACTION_NEWTAB : 1 << 4,
|
||||
kACTION_ATTACH : 1 << 10,
|
||||
kACTION_PART : 1 << 11,
|
||||
kACTIONS_FOR_SOURCE : (1 << 0) | (1 << 1),
|
||||
kACTIONS_FOR_DESTINATION : (1 << 2) | (1 << 3),
|
||||
|
||||
kTABBAR_TOP : 1 << 0,
|
||||
kTABBAR_BOTTOM : 1 << 1,
|
||||
kTABBAR_LEFT : 1 << 2,
|
||||
kTABBAR_RIGHT : 1 << 3,
|
||||
|
||||
kTABBAR_HORIZONTAL : (1 << 0) | (1 << 1),
|
||||
kTABBAR_VERTICAL : (1 << 2) | (1 << 3),
|
||||
kTABBAR_REGULAR : (1 << 0) | (1 << 2),
|
||||
kTABBAR_INVERTED : (1 << 3) | (1 << 4),
|
||||
|
||||
kINSERT_FISRT : 0,
|
||||
kINSERT_LAST : 1,
|
||||
|
||||
kTABBAR_UPDATE_BY_UNKNOWN_REASON : (1 << 0),
|
||||
kTABBAR_UPDATE_BY_RESET : (1 << 1),
|
||||
kTABBAR_UPDATE_BY_PREF_CHANGE : (1 << 2),
|
||||
kTABBAR_UPDATE_BY_APPEARANCE_CHANGE : (1 << 3),
|
||||
kTABBAR_UPDATE_BY_SHOWHIDE_TABBAR : (1 << 4),
|
||||
kTABBAR_UPDATE_BY_TABBAR_RESIZE : (1 << 5),
|
||||
kTABBAR_UPDATE_BY_WINDOW_RESIZE : (1 << 6),
|
||||
kTABBAR_UPDATE_BY_FULLSCREEN : (1 << 7),
|
||||
kTABBAR_UPDATE_BY_AUTOHIDE : (1 << 9),
|
||||
kTABBAR_UPDATE_BY_INITIALIZE : (1 << 10),
|
||||
kTABBAR_UPDATE_BY_TOGGLE_SIDEBAR : (1 << 11),
|
||||
kTABBAR_UPDATE_NOW : (1 << 5) | (1 << 6) | (1 << 9) | (1 << 10),
|
||||
kTABBAR_UPDATE_SYNC_TO_TABBAR : (1 << 0) | (1 << 1) | (1 << 2) | (1 << 5) | (1 << 9),
|
||||
kTABBAR_UPDATE_SYNC_TO_PLACEHOLDER : (1 << 3) | (1 << 4) | (1 << 6) | (1 << 7) | (1 << 10) | (1 << 11),
|
||||
|
||||
kCLOSE_PARENT_BEHAVIOR_PROMOTE_FIRST_CHILD : 3,
|
||||
kCLOSE_PARENT_BEHAVIOR_PROMOTE_ALL_CHILDREN : 0,
|
||||
kCLOSE_PARENT_BEHAVIOR_DETACH_ALL_CHILDREN : 1,
|
||||
kCLOSE_PARENT_BEHAVIOR_SIMPLY_DETACH_ALL_CHILDREN : 4,
|
||||
kCLOSE_PARENT_BEHAVIOR_CLOSE_ALL_CHILDREN : 2, // onTabRemoved only
|
||||
|
||||
kRESTORE_TREE_LEVEL_NONE : 0,
|
||||
kRESTORE_TREE_ONLY_VISIBLE : 1,
|
||||
kRESTORE_TREE_ALL : 2,
|
||||
|
||||
kCOUNTER_ROLE_ALL_TABS : 1,
|
||||
kCOUNTER_ROLE_CONTAINED_TABS : 2,
|
||||
|
||||
MAX_TABBAR_SIZE_RATIO : 0.8,
|
||||
DEFAULT_SHRUNKEN_WIDTH_RATIO : 0.67,
|
||||
MIN_TABBAR_WIDTH : 24,
|
||||
MIN_TABBAR_HEIGHT : 24
|
||||
});
|
||||
|
@ -1,480 +1,480 @@
|
||||
/* ***** 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 YUKI "Piro" Hiroshi.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011-2014
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s): YUKI "Piro" Hiroshi <piro.outsider.reflex@gmail.com>
|
||||
* Tetsuharu OHZEKI <https://github.com/saneyuki>
|
||||
*
|
||||
* 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://gre/modules/XPCOMUtils.jsm');
|
||||
|
||||
Components.utils.import('resource://treestyletab-modules/lib/inherit.jsm');
|
||||
Components.utils.import('resource://treestyletab-modules/base.js');
|
||||
Components.utils.import('resource://treestyletab-modules/pseudoTreeBuilder.js');
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, 'utils', 'resource://treestyletab-modules/utils.js', 'TreeStyleTabUtils');
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, 'ScreenManager',
|
||||
'@mozilla.org/gfx/screenmanager;1', 'nsIScreenManager');
|
||||
|
||||
function FullTooltipManager(aOwner)
|
||||
{
|
||||
this.init(aOwner);
|
||||
}
|
||||
FullTooltipManager.prototype = inherit(TreeStyleTabBase, {
|
||||
|
||||
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');
|
||||
},
|
||||
|
||||
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, false);
|
||||
this.tabFullTooltip.addEventListener(PseudoTreeBuilder.kTAB_LINK_CLICK, this, true);
|
||||
this.tabFullTooltip.addEventListener('popupshown', this, true);
|
||||
this.tabFullTooltip.addEventListener('popuphidden', this, true);
|
||||
},
|
||||
|
||||
destroy : function FTM_destroy()
|
||||
{
|
||||
this.cancel();
|
||||
this.stopListenTooltipEvents();
|
||||
|
||||
this.tabTooltip.removeEventListener('popupshowing', this, true);
|
||||
this.tabTooltip.removeEventListener('popuphiding', this, true);
|
||||
|
||||
this.tabFullTooltip.removeEventListener('click', this, false);
|
||||
this.tabFullTooltip.removeEventListener(PseudoTreeBuilder.kTAB_LINK_CLICK, this, true);
|
||||
this.tabFullTooltip.removeEventListener('popupshown', this, true);
|
||||
this.tabFullTooltip.removeEventListener('popuphidden', this, true);
|
||||
|
||||
delete this.owner;
|
||||
},
|
||||
|
||||
handleEvent : function FTM_handleEvent(aEvent)
|
||||
{
|
||||
switch (aEvent.type)
|
||||
{
|
||||
case 'click':
|
||||
return this.onClick(aEvent);
|
||||
|
||||
case PseudoTreeBuilder.kTAB_LINK_CLICK:
|
||||
return this.onItemClick(aEvent);
|
||||
|
||||
case 'popupshowing':
|
||||
return this.onDefaultTooltipShowing(aEvent);
|
||||
|
||||
case 'popuphiding':
|
||||
return this.onDefaultTooltipHiding(aEvent);
|
||||
|
||||
case 'popupshown':
|
||||
return this.onShown(aEvent);
|
||||
|
||||
case 'popuphidden':
|
||||
return this.onHidden(aEvent);
|
||||
|
||||
case 'mousemove':
|
||||
return this.onTooltipMouseMove(aEvent);
|
||||
|
||||
case 'mouseover':
|
||||
return this.cancelDelayedHide();
|
||||
|
||||
case 'mouseout':
|
||||
return this.hideWithDelay();
|
||||
|
||||
default:
|
||||
return this.onTooltipEvent(aEvent);
|
||||
}
|
||||
},
|
||||
|
||||
getFullTooltipFromEvent : function FTM_getFullTooltipFromEvent(aEvent)
|
||||
{
|
||||
return this.evaluateXPath(
|
||||
'ancestor-or-self::xul:tooltip[@id="'+this.tabFullTooltip.id+'"]',
|
||||
aEvent.target,
|
||||
Ci.nsIDOMXPathResult.FIRST_ORDERED_NODE_TYPE
|
||||
).singleNodeValue;
|
||||
},
|
||||
|
||||
onClick : function FTM_onClick(aEvent)
|
||||
{
|
||||
this.tabFullTooltip.hidePopup();
|
||||
},
|
||||
|
||||
onItemClick : function FTM_onItemClick(aEvent)
|
||||
{
|
||||
var id = aEvent.detail.id;
|
||||
if (id) {
|
||||
let tab = this.getTabById(id, this.owner.browser);
|
||||
if (tab) {
|
||||
let event = aEvent.detail.sourceEvent;
|
||||
if (event.button == 1 ||
|
||||
(event.button == 0 && this.isAccelKeyPressed(event)))
|
||||
this.owner.browser.removeTab(tab);
|
||||
else if (event.button != 2)
|
||||
this.owner.browser.selectedTab = tab;
|
||||
}
|
||||
}
|
||||
this.tabFullTooltip.hidePopup();
|
||||
},
|
||||
|
||||
onDefaultTooltipShowing : function FTM_onDefaultTooltipShowing(aEvent)
|
||||
{
|
||||
this.cancel();
|
||||
this.handleDefaultTooltip(aEvent);
|
||||
},
|
||||
|
||||
onDefaultTooltipHiding : function FTM_onDefaultTooltipHiding(aEvent)
|
||||
{
|
||||
this.cancel();
|
||||
},
|
||||
|
||||
onShown : function FTM_onShown(aEvent)
|
||||
{
|
||||
this.startListenTooltipEvents();
|
||||
|
||||
var tooltip = this.tabFullTooltip;
|
||||
tooltip.setAttribute('popup-shown', true);
|
||||
|
||||
var w = {},
|
||||
h = {};
|
||||
var box = tooltip.boxObject;
|
||||
var scrollBoxObject = tooltip.firstChild.scrollBoxObject;
|
||||
scrollBoxObject.getScrolledSize(w, h);
|
||||
var currentW = box.width - scrollBoxObject.width + w.value;
|
||||
var currentH = box.height - scrollBoxObject.height + h.value;
|
||||
var currentX = box.screenX;
|
||||
var currentY = box.screenY;
|
||||
|
||||
var currentScreen = Cc['@mozilla.org/gfx/screenmanager;1']
|
||||
.getService(Ci.nsIScreenManager)
|
||||
.screenForRect(box.screenX, box.screenY, box.width, box.height);
|
||||
var screenLeft = {},
|
||||
screenTop = {},
|
||||
screenWidth = {},
|
||||
screenHeight = {};
|
||||
currentScreen.GetRect(screenLeft, screenTop, screenWidth, screenHeight);
|
||||
|
||||
var style = tooltip.style;
|
||||
style.maxWidth = screenWidth.value+'px';
|
||||
style.maxHeight = screenHeight.value+'px';
|
||||
style.minWidth = 0;
|
||||
style.minHeight = 0;
|
||||
if (currentX + currentW + screenLeft.value >= screenWidth.value)
|
||||
style.marginLeft = (Math.max(screenLeft.value, screenWidth.value - currentW) - this.window.screenX)+'px';
|
||||
if (currentY + currentH + screenTop.value >= screenHeight.value)
|
||||
style.marginTop = (Math.max(screenTop.value, screenHeight.value - currentH) - this.window.screenY)+'px';
|
||||
},
|
||||
|
||||
onHidden : function FTM_onHidden(aEvent)
|
||||
{
|
||||
this.tabFullTooltip.removeAttribute('popup-shown');
|
||||
this.stopListenTooltipEvents();
|
||||
this.clear();
|
||||
},
|
||||
|
||||
onTooltipMouseMove : function FTM_onTooltipMouseMove(aEvent)
|
||||
{
|
||||
if (this.getFullTooltipFromEvent(aEvent))
|
||||
this.cancelDelayedHide();
|
||||
else
|
||||
this.hideWithDelay();
|
||||
},
|
||||
|
||||
onTooltipEvent : function FTM_onTooltipEvent(aEvent)
|
||||
{
|
||||
if (!this.getFullTooltipFromEvent(aEvent))
|
||||
this.hide();
|
||||
},
|
||||
|
||||
startListenTooltipEvents : function FTM_startListenTooltipEvents()
|
||||
{
|
||||
if (this.listening)
|
||||
return;
|
||||
this.window.addEventListener('DOMMouseScroll', this, true);
|
||||
this.window.addEventListener('keydown', this, true);
|
||||
this.window.addEventListener('mousedown', this, true);
|
||||
this.window.addEventListener('mouseup', this, true);
|
||||
this.window.addEventListener('dragstart', this, true);
|
||||
this.window.addEventListener('mousemove', this, true);
|
||||
this.tabFullTooltip.addEventListener('mouseover', this, false);
|
||||
this.tabFullTooltip.addEventListener('mouseout', this, false);
|
||||
this.listening = true;
|
||||
},
|
||||
|
||||
stopListenTooltipEvents : function FTM_stopListenTooltipEvents()
|
||||
{
|
||||
if (!this.listening)
|
||||
return;
|
||||
this.window.removeEventListener('DOMMouseScroll', this, true);
|
||||
this.window.removeEventListener('keydown', this, true);
|
||||
this.window.removeEventListener('mousedown', this, true);
|
||||
this.window.removeEventListener('mouseup', this, true);
|
||||
this.window.removeEventListener('dragstart', this, true);
|
||||
this.window.removeEventListener('mousemove', this, true);
|
||||
this.tabFullTooltip.removeEventListener('mouseover', this, false);
|
||||
this.tabFullTooltip.removeEventListener('mouseout', this, false);
|
||||
this.listening = false;
|
||||
},
|
||||
|
||||
|
||||
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 = utils.getTreePref('tooltip.mode');
|
||||
|
||||
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, utils.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 utils.treeBundle.getFormattedString('tooltip.item.label', [label, indent]);
|
||||
}, this)
|
||||
.join('\n');
|
||||
if (tabs.length != tabsToBeListed.length) {
|
||||
tree += '\n'+indentPart+utils.treeBundle.getFormattedString('tooltip.more', [tabs.length-tabsToBeListed.length]);
|
||||
}
|
||||
}
|
||||
|
||||
var shouldShowTree = mode != this.kTOOLTIP_MODE_DEFAULT && (collapsed || mode == this.kTOOLTIP_MODE_ALWAYS);
|
||||
if ('mOverCloseButton' in tab && tab.mOverCloseButton) {
|
||||
if (descendant.length &&
|
||||
(collapsed || utils.getTreePref('closeParentBehavior') == this.kCLOSE_PARENT_BEHAVIOR_CLOSE_ALL_CHILDREN)) {
|
||||
label = tree || tab.getAttribute('label');
|
||||
label = label && shouldShowTree ?
|
||||
utils.treeBundle.getFormattedString('tooltip.closeTree.labeled', [label]) :
|
||||
utils.treeBundle.getString('tooltip.closeTree') ;
|
||||
fullTooltipExtraLabel = utils.treeBundle.getFormattedString('tooltip.closeTree.labeled', ['%TREE%']).split(/\s*%TREE%\s*/);
|
||||
}
|
||||
}
|
||||
else if (tab.getAttribute(this.kTWISTY_HOVER) == 'true') {
|
||||
let key = collapsed ?
|
||||
'tooltip.expandSubtree' :
|
||||
'tooltip.collapseSubtree' ;
|
||||
label = tree || tab.getAttribute('label');
|
||||
label = label && shouldShowTree ?
|
||||
utils.treeBundle.getFormattedString(key+'.labeled', [label]) :
|
||||
utils.treeBundle.getString(key) ;
|
||||
fullTooltipExtraLabel = utils.treeBundle.getFormattedString(key+'.labeled', ['%TREE%']).split(/\s*%TREE%\s*/);
|
||||
}
|
||||
else if (shouldShowTree) {
|
||||
label = tree;
|
||||
}
|
||||
|
||||
if (!label)
|
||||
return;
|
||||
|
||||
aEvent.target.setAttribute('label', label);
|
||||
aEvent.stopPropagation();
|
||||
|
||||
if (shouldShowTree)
|
||||
this.setup(aEvent.target, tab, fullTooltipExtraLabel);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* If the window is maximized, screenX and screenY can be out of
|
||||
* visible screen rect. On the other hand,
|
||||
* nsIPopupBoxObject#openPopupAtScreen() automatically reposition
|
||||
* the popup if it is going to be shown out of the visible screen
|
||||
* rect. As the result, the popup will be repositioned unexpectedly
|
||||
* if I use the raw screenX and screenY.
|
||||
* https://github.com/piroor/treestyletab/issues/302
|
||||
* To prevent such a result, I have to calculate valid base position
|
||||
* for the popup.
|
||||
*/
|
||||
get windowBasePosition() {
|
||||
var screen = ScreenManager.screenForRect(
|
||||
this.window.screenX,
|
||||
this.window.screenY,
|
||||
this.window.outerWidth,
|
||||
this.window.outerHeight
|
||||
);
|
||||
var screenMinX = {},
|
||||
screenMinY = {},
|
||||
screenMaxX = {},
|
||||
screenMaxY = {};
|
||||
screen.GetAvailRect(screenMinX, screenMinY, screenMaxX, screenMaxY);
|
||||
|
||||
return {
|
||||
x: Math.max(this.window.screenX, screenMinX.value),
|
||||
y: Math.max(this.window.screenY, screenMinY.value)
|
||||
};
|
||||
},
|
||||
|
||||
setup : function FTM_setup(aBaseTooltip, aTab, aExtraLabels)
|
||||
{
|
||||
this.cancel();
|
||||
|
||||
var delay = utils.getTreePref('tooltip.fullTooltipDelay');
|
||||
if (delay < 0)
|
||||
return;
|
||||
|
||||
this._fullTooltipTimer = this.window.setTimeout(function(aSelf) {
|
||||
var basePosition = aSelf.windowBasePosition;
|
||||
var box = aBaseTooltip.boxObject;
|
||||
var x = box.screenX - basePosition.x;
|
||||
var y = box.screenY - basePosition.y;
|
||||
var w = box.width;
|
||||
var h = box.height;
|
||||
aBaseTooltip.hidePopup();
|
||||
|
||||
aSelf.fill(aTab, aExtraLabels);
|
||||
|
||||
var tooltip = aSelf.tabFullTooltip;
|
||||
let (style = tooltip.style) {
|
||||
style.marginLeft = x+'px';
|
||||
style.marginTop = y+'px';
|
||||
style.maxWidth = style.minWidth = w+'px';
|
||||
style.maxHeight = style.minHeight = h+'px';
|
||||
}
|
||||
tooltip.openPopupAtScreen(basePosition.x, basePosition.y, false);
|
||||
}, Math.max(delay, 0), this);
|
||||
},
|
||||
|
||||
cancel : function FTM_destroyFullTooltip()
|
||||
{
|
||||
if (this._fullTooltipTimer) {
|
||||
this.window.clearTimeout(this._fullTooltipTimer);
|
||||
this._fullTooltipTimer = null;
|
||||
}
|
||||
this.hide();
|
||||
},
|
||||
|
||||
hide : function FTM_hide()
|
||||
{
|
||||
this.cancelDelayedHide();
|
||||
this.tabFullTooltip.hidePopup();
|
||||
},
|
||||
|
||||
|
||||
hideWithDelay : function FTM_hideWithDelay()
|
||||
{
|
||||
this.cancelDelayedHide();
|
||||
this._delayedHideTimer = this.window.setTimeout(function(aSelf) {
|
||||
aSelf.hide();
|
||||
}, 500, this);
|
||||
},
|
||||
|
||||
cancelDelayedHide : function FTM_cancelDelayedHide()
|
||||
{
|
||||
if (this._delayedHideTimer) {
|
||||
this.window.clearTimeout(this._delayedHideTimer);
|
||||
this._delayedHideTimer = null;
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
fill : function FTM_fill(aTab, aExtraLabels)
|
||||
{
|
||||
this.clear();
|
||||
|
||||
var tree = PseudoTreeBuilder.build(aTab);
|
||||
var root = this.document.createElement('arrowscrollbox');
|
||||
root.setAttribute('orient', 'vertical');
|
||||
root.setAttribute('flex', 1);
|
||||
|
||||
if (aExtraLabels) {
|
||||
if (typeof aExtraLabels == 'string')
|
||||
aExtraLabels = [aExtraLabels];
|
||||
for (let i = 0, maxi = aExtraLabels.length; i < maxi; i++)
|
||||
{
|
||||
let label = aExtraLabels[i];
|
||||
label = label.trim();
|
||||
if (!label)
|
||||
continue;
|
||||
root.appendChild(this.document.createElement('description'))
|
||||
.appendChild(this.document.createTextNode(label));
|
||||
}
|
||||
}
|
||||
|
||||
root.insertBefore(tree, root.firstChild && root.firstChild.nextSibling);
|
||||
|
||||
this.tabFullTooltip.appendChild(root);
|
||||
},
|
||||
|
||||
clear : function FTM_clear()
|
||||
{
|
||||
var range = this.document.createRange();
|
||||
range.selectNodeContents(this.tabFullTooltip);
|
||||
range.deleteContents();
|
||||
range.detach();
|
||||
}
|
||||
});
|
||||
/* ***** 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 YUKI "Piro" Hiroshi.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011-2014
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s): YUKI "Piro" Hiroshi <piro.outsider.reflex@gmail.com>
|
||||
* Tetsuharu OHZEKI <https://github.com/saneyuki>
|
||||
*
|
||||
* 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://gre/modules/XPCOMUtils.jsm');
|
||||
|
||||
Components.utils.import('resource://treestyletab-modules/lib/inherit.jsm');
|
||||
Components.utils.import('resource://treestyletab-modules/base.js');
|
||||
Components.utils.import('resource://treestyletab-modules/pseudoTreeBuilder.js');
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, 'utils', 'resource://treestyletab-modules/utils.js', 'TreeStyleTabUtils');
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, 'ScreenManager',
|
||||
'@mozilla.org/gfx/screenmanager;1', 'nsIScreenManager');
|
||||
|
||||
function FullTooltipManager(aOwner)
|
||||
{
|
||||
this.init(aOwner);
|
||||
}
|
||||
FullTooltipManager.prototype = inherit(TreeStyleTabBase, {
|
||||
|
||||
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');
|
||||
},
|
||||
|
||||
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, false);
|
||||
this.tabFullTooltip.addEventListener(PseudoTreeBuilder.kTAB_LINK_CLICK, this, true);
|
||||
this.tabFullTooltip.addEventListener('popupshown', this, true);
|
||||
this.tabFullTooltip.addEventListener('popuphidden', this, true);
|
||||
},
|
||||
|
||||
destroy : function FTM_destroy()
|
||||
{
|
||||
this.cancel();
|
||||
this.stopListenTooltipEvents();
|
||||
|
||||
this.tabTooltip.removeEventListener('popupshowing', this, true);
|
||||
this.tabTooltip.removeEventListener('popuphiding', this, true);
|
||||
|
||||
this.tabFullTooltip.removeEventListener('click', this, false);
|
||||
this.tabFullTooltip.removeEventListener(PseudoTreeBuilder.kTAB_LINK_CLICK, this, true);
|
||||
this.tabFullTooltip.removeEventListener('popupshown', this, true);
|
||||
this.tabFullTooltip.removeEventListener('popuphidden', this, true);
|
||||
|
||||
delete this.owner;
|
||||
},
|
||||
|
||||
handleEvent : function FTM_handleEvent(aEvent)
|
||||
{
|
||||
switch (aEvent.type)
|
||||
{
|
||||
case 'click':
|
||||
return this.onClick(aEvent);
|
||||
|
||||
case PseudoTreeBuilder.kTAB_LINK_CLICK:
|
||||
return this.onItemClick(aEvent);
|
||||
|
||||
case 'popupshowing':
|
||||
return this.onDefaultTooltipShowing(aEvent);
|
||||
|
||||
case 'popuphiding':
|
||||
return this.onDefaultTooltipHiding(aEvent);
|
||||
|
||||
case 'popupshown':
|
||||
return this.onShown(aEvent);
|
||||
|
||||
case 'popuphidden':
|
||||
return this.onHidden(aEvent);
|
||||
|
||||
case 'mousemove':
|
||||
return this.onTooltipMouseMove(aEvent);
|
||||
|
||||
case 'mouseover':
|
||||
return this.cancelDelayedHide();
|
||||
|
||||
case 'mouseout':
|
||||
return this.hideWithDelay();
|
||||
|
||||
default:
|
||||
return this.onTooltipEvent(aEvent);
|
||||
}
|
||||
},
|
||||
|
||||
getFullTooltipFromEvent : function FTM_getFullTooltipFromEvent(aEvent)
|
||||
{
|
||||
return this.evaluateXPath(
|
||||
'ancestor-or-self::xul:tooltip[@id="'+this.tabFullTooltip.id+'"]',
|
||||
aEvent.target,
|
||||
Ci.nsIDOMXPathResult.FIRST_ORDERED_NODE_TYPE
|
||||
).singleNodeValue;
|
||||
},
|
||||
|
||||
onClick : function FTM_onClick(aEvent)
|
||||
{
|
||||
this.tabFullTooltip.hidePopup();
|
||||
},
|
||||
|
||||
onItemClick : function FTM_onItemClick(aEvent)
|
||||
{
|
||||
var id = aEvent.detail.id;
|
||||
if (id) {
|
||||
let tab = this.getTabById(id, this.owner.browser);
|
||||
if (tab) {
|
||||
let event = aEvent.detail.sourceEvent;
|
||||
if (event.button == 1 ||
|
||||
(event.button == 0 && this.isAccelKeyPressed(event)))
|
||||
this.owner.browser.removeTab(tab);
|
||||
else if (event.button != 2)
|
||||
this.owner.browser.selectedTab = tab;
|
||||
}
|
||||
}
|
||||
this.tabFullTooltip.hidePopup();
|
||||
},
|
||||
|
||||
onDefaultTooltipShowing : function FTM_onDefaultTooltipShowing(aEvent)
|
||||
{
|
||||
this.cancel();
|
||||
this.handleDefaultTooltip(aEvent);
|
||||
},
|
||||
|
||||
onDefaultTooltipHiding : function FTM_onDefaultTooltipHiding(aEvent)
|
||||
{
|
||||
this.cancel();
|
||||
},
|
||||
|
||||
onShown : function FTM_onShown(aEvent)
|
||||
{
|
||||
this.startListenTooltipEvents();
|
||||
|
||||
var tooltip = this.tabFullTooltip;
|
||||
tooltip.setAttribute('popup-shown', true);
|
||||
|
||||
var w = {},
|
||||
h = {};
|
||||
var box = tooltip.boxObject;
|
||||
var scrollBoxObject = tooltip.firstChild.scrollBoxObject;
|
||||
scrollBoxObject.getScrolledSize(w, h);
|
||||
var currentW = box.width - scrollBoxObject.width + w.value;
|
||||
var currentH = box.height - scrollBoxObject.height + h.value;
|
||||
var currentX = box.screenX;
|
||||
var currentY = box.screenY;
|
||||
|
||||
var currentScreen = Cc['@mozilla.org/gfx/screenmanager;1']
|
||||
.getService(Ci.nsIScreenManager)
|
||||
.screenForRect(box.screenX, box.screenY, box.width, box.height);
|
||||
var screenLeft = {},
|
||||
screenTop = {},
|
||||
screenWidth = {},
|
||||
screenHeight = {};
|
||||
currentScreen.GetRect(screenLeft, screenTop, screenWidth, screenHeight);
|
||||
|
||||
var style = tooltip.style;
|
||||
style.maxWidth = screenWidth.value+'px';
|
||||
style.maxHeight = screenHeight.value+'px';
|
||||
style.minWidth = 0;
|
||||
style.minHeight = 0;
|
||||
if (currentX + currentW + screenLeft.value >= screenWidth.value)
|
||||
style.marginLeft = (Math.max(screenLeft.value, screenWidth.value - currentW) - this.window.screenX)+'px';
|
||||
if (currentY + currentH + screenTop.value >= screenHeight.value)
|
||||
style.marginTop = (Math.max(screenTop.value, screenHeight.value - currentH) - this.window.screenY)+'px';
|
||||
},
|
||||
|
||||
onHidden : function FTM_onHidden(aEvent)
|
||||
{
|
||||
this.tabFullTooltip.removeAttribute('popup-shown');
|
||||
this.stopListenTooltipEvents();
|
||||
this.clear();
|
||||
},
|
||||
|
||||
onTooltipMouseMove : function FTM_onTooltipMouseMove(aEvent)
|
||||
{
|
||||
if (this.getFullTooltipFromEvent(aEvent))
|
||||
this.cancelDelayedHide();
|
||||
else
|
||||
this.hideWithDelay();
|
||||
},
|
||||
|
||||
onTooltipEvent : function FTM_onTooltipEvent(aEvent)
|
||||
{
|
||||
if (!this.getFullTooltipFromEvent(aEvent))
|
||||
this.hide();
|
||||
},
|
||||
|
||||
startListenTooltipEvents : function FTM_startListenTooltipEvents()
|
||||
{
|
||||
if (this.listening)
|
||||
return;
|
||||
this.window.addEventListener('DOMMouseScroll', this, true);
|
||||
this.window.addEventListener('keydown', this, true);
|
||||
this.window.addEventListener('mousedown', this, true);
|
||||
this.window.addEventListener('mouseup', this, true);
|
||||
this.window.addEventListener('dragstart', this, true);
|
||||
this.window.addEventListener('mousemove', this, true);
|
||||
this.tabFullTooltip.addEventListener('mouseover', this, false);
|
||||
this.tabFullTooltip.addEventListener('mouseout', this, false);
|
||||
this.listening = true;
|
||||
},
|
||||
|
||||
stopListenTooltipEvents : function FTM_stopListenTooltipEvents()
|
||||
{
|
||||
if (!this.listening)
|
||||
return;
|
||||
this.window.removeEventListener('DOMMouseScroll', this, true);
|
||||
this.window.removeEventListener('keydown', this, true);
|
||||
this.window.removeEventListener('mousedown', this, true);
|
||||
this.window.removeEventListener('mouseup', this, true);
|
||||
this.window.removeEventListener('dragstart', this, true);
|
||||
this.window.removeEventListener('mousemove', this, true);
|
||||
this.tabFullTooltip.removeEventListener('mouseover', this, false);
|
||||
this.tabFullTooltip.removeEventListener('mouseout', this, false);
|
||||
this.listening = false;
|
||||
},
|
||||
|
||||
|
||||
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 = utils.getTreePref('tooltip.mode');
|
||||
|
||||
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, utils.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 utils.treeBundle.getFormattedString('tooltip.item.label', [label, indent]);
|
||||
}, this)
|
||||
.join('\n');
|
||||
if (tabs.length != tabsToBeListed.length) {
|
||||
tree += '\n'+indentPart+utils.treeBundle.getFormattedString('tooltip.more', [tabs.length-tabsToBeListed.length]);
|
||||
}
|
||||
}
|
||||
|
||||
var shouldShowTree = mode != this.kTOOLTIP_MODE_DEFAULT && (collapsed || mode == this.kTOOLTIP_MODE_ALWAYS);
|
||||
if ('mOverCloseButton' in tab && tab.mOverCloseButton) {
|
||||
if (descendant.length &&
|
||||
(collapsed || utils.getTreePref('closeParentBehavior') == this.kCLOSE_PARENT_BEHAVIOR_CLOSE_ALL_CHILDREN)) {
|
||||
label = tree || tab.getAttribute('label');
|
||||
label = label && shouldShowTree ?
|
||||
utils.treeBundle.getFormattedString('tooltip.closeTree.labeled', [label]) :
|
||||
utils.treeBundle.getString('tooltip.closeTree') ;
|
||||
fullTooltipExtraLabel = utils.treeBundle.getFormattedString('tooltip.closeTree.labeled', ['%TREE%']).split(/\s*%TREE%\s*/);
|
||||
}
|
||||
}
|
||||
else if (tab.getAttribute(this.kTWISTY_HOVER) == 'true') {
|
||||
let key = collapsed ?
|
||||
'tooltip.expandSubtree' :
|
||||
'tooltip.collapseSubtree' ;
|
||||
label = tree || tab.getAttribute('label');
|
||||
label = label && shouldShowTree ?
|
||||
utils.treeBundle.getFormattedString(key+'.labeled', [label]) :
|
||||
utils.treeBundle.getString(key) ;
|
||||
fullTooltipExtraLabel = utils.treeBundle.getFormattedString(key+'.labeled', ['%TREE%']).split(/\s*%TREE%\s*/);
|
||||
}
|
||||
else if (shouldShowTree) {
|
||||
label = tree;
|
||||
}
|
||||
|
||||
if (!label)
|
||||
return;
|
||||
|
||||
aEvent.target.setAttribute('label', label);
|
||||
aEvent.stopPropagation();
|
||||
|
||||
if (shouldShowTree)
|
||||
this.setup(aEvent.target, tab, fullTooltipExtraLabel);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* If the window is maximized, screenX and screenY can be out of
|
||||
* visible screen rect. On the other hand,
|
||||
* nsIPopupBoxObject#openPopupAtScreen() automatically reposition
|
||||
* the popup if it is going to be shown out of the visible screen
|
||||
* rect. As the result, the popup will be repositioned unexpectedly
|
||||
* if I use the raw screenX and screenY.
|
||||
* https://github.com/piroor/treestyletab/issues/302
|
||||
* To prevent such a result, I have to calculate valid base position
|
||||
* for the popup.
|
||||
*/
|
||||
get windowBasePosition() {
|
||||
var screen = ScreenManager.screenForRect(
|
||||
this.window.screenX,
|
||||
this.window.screenY,
|
||||
this.window.outerWidth,
|
||||
this.window.outerHeight
|
||||
);
|
||||
var screenMinX = {},
|
||||
screenMinY = {},
|
||||
screenMaxX = {},
|
||||
screenMaxY = {};
|
||||
screen.GetAvailRect(screenMinX, screenMinY, screenMaxX, screenMaxY);
|
||||
|
||||
return {
|
||||
x: Math.max(this.window.screenX, screenMinX.value),
|
||||
y: Math.max(this.window.screenY, screenMinY.value)
|
||||
};
|
||||
},
|
||||
|
||||
setup : function FTM_setup(aBaseTooltip, aTab, aExtraLabels)
|
||||
{
|
||||
this.cancel();
|
||||
|
||||
var delay = utils.getTreePref('tooltip.fullTooltipDelay');
|
||||
if (delay < 0)
|
||||
return;
|
||||
|
||||
this._fullTooltipTimer = this.window.setTimeout(function(aSelf) {
|
||||
var basePosition = aSelf.windowBasePosition;
|
||||
var box = aBaseTooltip.boxObject;
|
||||
var x = box.screenX - basePosition.x;
|
||||
var y = box.screenY - basePosition.y;
|
||||
var w = box.width;
|
||||
var h = box.height;
|
||||
aBaseTooltip.hidePopup();
|
||||
|
||||
aSelf.fill(aTab, aExtraLabels);
|
||||
|
||||
var tooltip = aSelf.tabFullTooltip;
|
||||
let (style = tooltip.style) {
|
||||
style.marginLeft = x+'px';
|
||||
style.marginTop = y+'px';
|
||||
style.maxWidth = style.minWidth = w+'px';
|
||||
style.maxHeight = style.minHeight = h+'px';
|
||||
}
|
||||
tooltip.openPopupAtScreen(basePosition.x, basePosition.y, false);
|
||||
}, Math.max(delay, 0), this);
|
||||
},
|
||||
|
||||
cancel : function FTM_destroyFullTooltip()
|
||||
{
|
||||
if (this._fullTooltipTimer) {
|
||||
this.window.clearTimeout(this._fullTooltipTimer);
|
||||
this._fullTooltipTimer = null;
|
||||
}
|
||||
this.hide();
|
||||
},
|
||||
|
||||
hide : function FTM_hide()
|
||||
{
|
||||
this.cancelDelayedHide();
|
||||
this.tabFullTooltip.hidePopup();
|
||||
},
|
||||
|
||||
|
||||
hideWithDelay : function FTM_hideWithDelay()
|
||||
{
|
||||
this.cancelDelayedHide();
|
||||
this._delayedHideTimer = this.window.setTimeout(function(aSelf) {
|
||||
aSelf.hide();
|
||||
}, 500, this);
|
||||
},
|
||||
|
||||
cancelDelayedHide : function FTM_cancelDelayedHide()
|
||||
{
|
||||
if (this._delayedHideTimer) {
|
||||
this.window.clearTimeout(this._delayedHideTimer);
|
||||
this._delayedHideTimer = null;
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
fill : function FTM_fill(aTab, aExtraLabels)
|
||||
{
|
||||
this.clear();
|
||||
|
||||
var tree = PseudoTreeBuilder.build(aTab);
|
||||
var root = this.document.createElement('arrowscrollbox');
|
||||
root.setAttribute('orient', 'vertical');
|
||||
root.setAttribute('flex', 1);
|
||||
|
||||
if (aExtraLabels) {
|
||||
if (typeof aExtraLabels == 'string')
|
||||
aExtraLabels = [aExtraLabels];
|
||||
for (let i = 0, maxi = aExtraLabels.length; i < maxi; i++)
|
||||
{
|
||||
let label = aExtraLabels[i];
|
||||
label = label.trim();
|
||||
if (!label)
|
||||
continue;
|
||||
root.appendChild(this.document.createElement('description'))
|
||||
.appendChild(this.document.createTextNode(label));
|
||||
}
|
||||
}
|
||||
|
||||
root.insertBefore(tree, root.firstChild && root.firstChild.nextSibling);
|
||||
|
||||
this.tabFullTooltip.appendChild(root);
|
||||
},
|
||||
|
||||
clear : function FTM_clear()
|
||||
{
|
||||
var range = this.document.createRange();
|
||||
range.selectNodeContents(this.tabFullTooltip);
|
||||
range.deleteContents();
|
||||
range.detach();
|
||||
}
|
||||
});
|
||||
|
@ -1,109 +1,109 @@
|
||||
/* ***** 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 YUKI "Piro" Hiroshi.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2013
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s): YUKI "Piro" 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 = ['FullscreenObserver'];
|
||||
|
||||
Components.utils.import('resource://treestyletab-modules/utils.js');
|
||||
|
||||
function FullscreenObserver(aWindow) {
|
||||
this.window = aWindow;
|
||||
this.init();
|
||||
}
|
||||
FullscreenObserver.prototype = {
|
||||
get MutationObserver()
|
||||
{
|
||||
var w = this.window;
|
||||
return w.MutationObserver || w.MozMutationObserver;
|
||||
},
|
||||
|
||||
init : function FullscreenObserver_onInit()
|
||||
{
|
||||
if (!this.MutationObserver)
|
||||
return;
|
||||
this.observer = new this.MutationObserver((function(aMutations, aObserver) {
|
||||
this.onMutation(aMutations, aObserver);
|
||||
}).bind(this));
|
||||
this.observer.observe(this.window.document.documentElement, {
|
||||
attributes : true,
|
||||
attributeFilter : ['sizemode']
|
||||
});
|
||||
|
||||
this.onSizeModeChange();
|
||||
},
|
||||
|
||||
destroy : function FullscreenObserver_destroy()
|
||||
{
|
||||
if (this.observer) {
|
||||
this.observer.disconnect();
|
||||
delete this.observer;
|
||||
}
|
||||
delete this.window;
|
||||
},
|
||||
|
||||
onMutation : function FullscreenObserver_onMutation(aMutations, aObserver)
|
||||
{
|
||||
this.window.setTimeout((function() {
|
||||
this.onSizeModeChange();
|
||||
}).bind(this), 10);
|
||||
},
|
||||
|
||||
onSizeModeChange : function FullscreenObserver_onSizeModeChange()
|
||||
{
|
||||
var w = this.window;
|
||||
var d = w.document;
|
||||
if (d.documentElement.getAttribute('sizemode') != 'fullscreen')
|
||||
return;
|
||||
|
||||
if (
|
||||
!w.FullScreen.useLionFullScreen && // see https://github.com/piroor/treestyletab/issues/645
|
||||
TreeStyleTabUtils.prefs.getPref('browser.fullscreen.autohide') // see https://github.com/piroor/treestyletab/issues/717
|
||||
) {
|
||||
let toolbox = w.gNavToolbox;
|
||||
toolbox.style.marginTop = -toolbox.getBoundingClientRect().height + 'px';
|
||||
}
|
||||
|
||||
var windowControls = d.getElementById('window-controls');
|
||||
var navigationToolbar = d.getElementById('nav-bar');
|
||||
if (!windowControls ||
|
||||
!navigationToolbar ||
|
||||
windowControls.parentNode == navigationToolbar ||
|
||||
(w.gBrowser.treeStyleTab.position == 'top' && w.gBrowser.treeStyleTab.fixed))
|
||||
return;
|
||||
|
||||
// the location bar is flex=1, so we should not apply it.
|
||||
// windowControls.setAttribute('flex', '1');
|
||||
navigationToolbar.appendChild(windowControls);
|
||||
}
|
||||
};
|
||||
/* ***** 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 YUKI "Piro" Hiroshi.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2013
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s): YUKI "Piro" 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 = ['FullscreenObserver'];
|
||||
|
||||
Components.utils.import('resource://treestyletab-modules/utils.js');
|
||||
|
||||
function FullscreenObserver(aWindow) {
|
||||
this.window = aWindow;
|
||||
this.init();
|
||||
}
|
||||
FullscreenObserver.prototype = {
|
||||
get MutationObserver()
|
||||
{
|
||||
var w = this.window;
|
||||
return w.MutationObserver || w.MozMutationObserver;
|
||||
},
|
||||
|
||||
init : function FullscreenObserver_onInit()
|
||||
{
|
||||
if (!this.MutationObserver)
|
||||
return;
|
||||
this.observer = new this.MutationObserver((function(aMutations, aObserver) {
|
||||
this.onMutation(aMutations, aObserver);
|
||||
}).bind(this));
|
||||
this.observer.observe(this.window.document.documentElement, {
|
||||
attributes : true,
|
||||
attributeFilter : ['sizemode']
|
||||
});
|
||||
|
||||
this.onSizeModeChange();
|
||||
},
|
||||
|
||||
destroy : function FullscreenObserver_destroy()
|
||||
{
|
||||
if (this.observer) {
|
||||
this.observer.disconnect();
|
||||
delete this.observer;
|
||||
}
|
||||
delete this.window;
|
||||
},
|
||||
|
||||
onMutation : function FullscreenObserver_onMutation(aMutations, aObserver)
|
||||
{
|
||||
this.window.setTimeout((function() {
|
||||
this.onSizeModeChange();
|
||||
}).bind(this), 10);
|
||||
},
|
||||
|
||||
onSizeModeChange : function FullscreenObserver_onSizeModeChange()
|
||||
{
|
||||
var w = this.window;
|
||||
var d = w.document;
|
||||
if (d.documentElement.getAttribute('sizemode') != 'fullscreen')
|
||||
return;
|
||||
|
||||
if (
|
||||
!w.FullScreen.useLionFullScreen && // see https://github.com/piroor/treestyletab/issues/645
|
||||
TreeStyleTabUtils.prefs.getPref('browser.fullscreen.autohide') // see https://github.com/piroor/treestyletab/issues/717
|
||||
) {
|
||||
let toolbox = w.gNavToolbox;
|
||||
toolbox.style.marginTop = -toolbox.getBoundingClientRect().height + 'px';
|
||||
}
|
||||
|
||||
var windowControls = d.getElementById('window-controls');
|
||||
var navigationToolbar = d.getElementById('nav-bar');
|
||||
if (!windowControls ||
|
||||
!navigationToolbar ||
|
||||
windowControls.parentNode == navigationToolbar ||
|
||||
(w.gBrowser.treeStyleTab.position == 'top' && w.gBrowser.treeStyleTab.fixed))
|
||||
return;
|
||||
|
||||
// the location bar is flex=1, so we should not apply it.
|
||||
// windowControls.setAttribute('flex', '1');
|
||||
navigationToolbar.appendChild(windowControls);
|
||||
}
|
||||
};
|
||||
|
@ -1,142 +1,142 @@
|
||||
/* ***** 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 YUKI "Piro" Hiroshi.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011-2014
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s): YUKI "Piro" Hiroshi <piro.outsider.reflex@gmail.com>
|
||||
* Tetsuharu OHZEKI <https://github.com/saneyuki>
|
||||
*
|
||||
* 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 = ['PseudoTreeBuilder'];
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
|
||||
Components.utils.import('resource://gre/modules/XPCOMUtils.jsm');
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, 'TreeStyleTabBase', 'resource://treestyletab-modules/base.js');
|
||||
|
||||
var PseudoTreeBuilder = {
|
||||
|
||||
kFAVICON : 'treestyletab-pseudo-tree-favicon',
|
||||
kROOTITEM : 'treestyletab-pseudo-tree-root-item',
|
||||
kTREEITEM : 'treestyletab-pseudo-tree-item',
|
||||
kTREEROW : 'treestyletab-pseudo-tree-row',
|
||||
kTREECHILDREN : 'treestyletab-pseudo-tree-children',
|
||||
|
||||
kTAB_LINK_CLICK : 'nsDOMTSTPseudoTreeItemClick',
|
||||
|
||||
build : function TB_build(aTab)
|
||||
{
|
||||
if (!aTab)
|
||||
return null;
|
||||
|
||||
var tree = this.createTabItem(aTab);
|
||||
|
||||
var row = tree.querySelector("."+this.kTREEROW);
|
||||
if (!row)
|
||||
return;
|
||||
|
||||
row.className += " "+this.kROOTITEM;
|
||||
|
||||
tree.setAttribute('onclick',
|
||||
('var doc = event.target.ownerDocument;\n' +
|
||||
'var label = doc.evaluate(\n' +
|
||||
' "ancestor-or-self::*[local-name()=\'label\' and contains(@class, \'text-link\')][1]",\n' +
|
||||
' event.target,\n' +
|
||||
' null,\n' +
|
||||
' Components.interfaces.nsIDOMXPathResult.FIRST_ORDERED_NODE_TYPE,\n' +
|
||||
' null\n' +
|
||||
' ).singleNodeValue;\n' +
|
||||
'if (label) {\n' +
|
||||
' var customEvent = new doc.defaultView.CustomEvent(%EVENT_TYPE%, {\n' +
|
||||
' bubbles : true,\n' +
|
||||
' cancelable : true,\n' +
|
||||
' detail : {\n' +
|
||||
' id : label.getAttribute("tab-id"),\n' +
|
||||
' sourceEvent : event\n' +
|
||||
' }\n' +
|
||||
' });\n' +
|
||||
' event.target.dispatchEvent(customEvent);\n' +
|
||||
'}').replace('%EVENT_TYPE%', this.kTAB_LINK_CLICK.quote()));
|
||||
|
||||
return tree;
|
||||
},
|
||||
|
||||
createTabItem : function TB_createTabItem(aTab)
|
||||
{
|
||||
var doc = aTab.ownerDocument;
|
||||
var w = doc.defaultView;
|
||||
|
||||
var item = doc.createElement('hbox');
|
||||
item.setAttribute('class', this.kTREEROW);
|
||||
|
||||
var favicon = item.appendChild(doc.createElement('image'));
|
||||
favicon.setAttribute('src', aTab.getAttribute('image') || 'chrome://mozapps/skin/places/defaultFavicon.png');
|
||||
favicon.setAttribute('class', this.kFAVICON);
|
||||
|
||||
var label = item.appendChild(doc.createElement('label'));
|
||||
label.setAttribute('value', aTab.label);
|
||||
var tooltip = aTab.label;
|
||||
var uri = aTab.linkedBrowser.currentURI.spec;
|
||||
if (w.isBlankPageURL ? !w.isBlankPageURL(uri) : (uri != 'about:blank')) tooltip += '\n' + uri;
|
||||
label.setAttribute('tooltiptext', tooltip);
|
||||
label.setAttribute('class', 'text-link '+this.kTREEITEM);
|
||||
label.setAttribute('tab-id', TreeStyleTabBase.getTabValue(aTab, TreeStyleTabBase.kID));
|
||||
|
||||
var children = this.createTabChildren(aTab);
|
||||
if (children) {
|
||||
let container = doc.createElement('vbox');
|
||||
container.appendChild(item);
|
||||
container.appendChild(children);
|
||||
return container;
|
||||
}
|
||||
else {
|
||||
return item;
|
||||
}
|
||||
},
|
||||
|
||||
createTabChildren : function TB_createTabChildren(aTab)
|
||||
{
|
||||
var doc = aTab.ownerDocument;
|
||||
|
||||
var children = TreeStyleTabBase.getChildTabs(aTab);
|
||||
if (!children.length)
|
||||
return null;
|
||||
|
||||
var container = doc.createElement('vbox');
|
||||
for (let i = 0, maxi = children.length; i < maxi; i++)
|
||||
{
|
||||
container.appendChild(this.createTabItem(children[i]));
|
||||
}
|
||||
container.setAttribute('class', this.kTREECHILDREN);
|
||||
return container;
|
||||
}
|
||||
};
|
||||
/* ***** 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 YUKI "Piro" Hiroshi.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011-2014
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s): YUKI "Piro" Hiroshi <piro.outsider.reflex@gmail.com>
|
||||
* Tetsuharu OHZEKI <https://github.com/saneyuki>
|
||||
*
|
||||
* 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 = ['PseudoTreeBuilder'];
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
|
||||
Components.utils.import('resource://gre/modules/XPCOMUtils.jsm');
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, 'TreeStyleTabBase', 'resource://treestyletab-modules/base.js');
|
||||
|
||||
var PseudoTreeBuilder = {
|
||||
|
||||
kFAVICON : 'treestyletab-pseudo-tree-favicon',
|
||||
kROOTITEM : 'treestyletab-pseudo-tree-root-item',
|
||||
kTREEITEM : 'treestyletab-pseudo-tree-item',
|
||||
kTREEROW : 'treestyletab-pseudo-tree-row',
|
||||
kTREECHILDREN : 'treestyletab-pseudo-tree-children',
|
||||
|
||||
kTAB_LINK_CLICK : 'nsDOMTSTPseudoTreeItemClick',
|
||||
|
||||
build : function TB_build(aTab)
|
||||
{
|
||||
if (!aTab)
|
||||
return null;
|
||||
|
||||
var tree = this.createTabItem(aTab);
|
||||
|
||||
var row = tree.querySelector("."+this.kTREEROW);
|
||||
if (!row)
|
||||
return;
|
||||
|
||||
row.className += " "+this.kROOTITEM;
|
||||
|
||||
tree.setAttribute('onclick',
|
||||
('var doc = event.target.ownerDocument;\n' +
|
||||
'var label = doc.evaluate(\n' +
|
||||
' "ancestor-or-self::*[local-name()=\'label\' and contains(@class, \'text-link\')][1]",\n' +
|
||||
' event.target,\n' +
|
||||
' null,\n' +
|
||||
' Components.interfaces.nsIDOMXPathResult.FIRST_ORDERED_NODE_TYPE,\n' +
|
||||
' null\n' +
|
||||
' ).singleNodeValue;\n' +
|
||||
'if (label) {\n' +
|
||||
' var customEvent = new doc.defaultView.CustomEvent(%EVENT_TYPE%, {\n' +
|
||||
' bubbles : true,\n' +
|
||||
' cancelable : true,\n' +
|
||||
' detail : {\n' +
|
||||
' id : label.getAttribute("tab-id"),\n' +
|
||||
' sourceEvent : event\n' +
|
||||
' }\n' +
|
||||
' });\n' +
|
||||
' event.target.dispatchEvent(customEvent);\n' +
|
||||
'}').replace('%EVENT_TYPE%', this.kTAB_LINK_CLICK.quote()));
|
||||
|
||||
return tree;
|
||||
},
|
||||
|
||||
createTabItem : function TB_createTabItem(aTab)
|
||||
{
|
||||
var doc = aTab.ownerDocument;
|
||||
var w = doc.defaultView;
|
||||
|
||||
var item = doc.createElement('hbox');
|
||||
item.setAttribute('class', this.kTREEROW);
|
||||
|
||||
var favicon = item.appendChild(doc.createElement('image'));
|
||||
favicon.setAttribute('src', aTab.getAttribute('image') || 'chrome://mozapps/skin/places/defaultFavicon.png');
|
||||
favicon.setAttribute('class', this.kFAVICON);
|
||||
|
||||
var label = item.appendChild(doc.createElement('label'));
|
||||
label.setAttribute('value', aTab.label);
|
||||
var tooltip = aTab.label;
|
||||
var uri = aTab.linkedBrowser.currentURI.spec;
|
||||
if (w.isBlankPageURL ? !w.isBlankPageURL(uri) : (uri != 'about:blank')) tooltip += '\n' + uri;
|
||||
label.setAttribute('tooltiptext', tooltip);
|
||||
label.setAttribute('class', 'text-link '+this.kTREEITEM);
|
||||
label.setAttribute('tab-id', TreeStyleTabBase.getTabValue(aTab, TreeStyleTabBase.kID));
|
||||
|
||||
var children = this.createTabChildren(aTab);
|
||||
if (children) {
|
||||
let container = doc.createElement('vbox');
|
||||
container.appendChild(item);
|
||||
container.appendChild(children);
|
||||
return container;
|
||||
}
|
||||
else {
|
||||
return item;
|
||||
}
|
||||
},
|
||||
|
||||
createTabChildren : function TB_createTabChildren(aTab)
|
||||
{
|
||||
var doc = aTab.ownerDocument;
|
||||
|
||||
var children = TreeStyleTabBase.getChildTabs(aTab);
|
||||
if (!children.length)
|
||||
return null;
|
||||
|
||||
var container = doc.createElement('vbox');
|
||||
for (let i = 0, maxi = children.length; i < maxi; i++)
|
||||
{
|
||||
container.appendChild(this.createTabItem(children[i]));
|
||||
}
|
||||
container.setAttribute('class', this.kTREECHILDREN);
|
||||
return container;
|
||||
}
|
||||
};
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,168 +1,168 @@
|
||||
/* ***** 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 YUKI "Piro" Hiroshi.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010-2013
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s): YUKI "Piro" Hiroshi <piro.outsider.reflex@gmail.com>
|
||||
* Tetsuharu OHZEKI <https://github.com/saneyuki>
|
||||
*
|
||||
* 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 = ['TabpanelDNDObserver'];
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
|
||||
Components.utils.import('resource://gre/modules/XPCOMUtils.jsm');
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, 'utils', 'resource://treestyletab-modules/utils.js', 'TreeStyleTabUtils');
|
||||
|
||||
|
||||
function TabpanelDNDObserver(aTabBrowser)
|
||||
{
|
||||
this.init(aTabBrowser);
|
||||
}
|
||||
|
||||
TabpanelDNDObserver.prototype = {
|
||||
|
||||
getDropPosition : function TabpanelDND_getDropPosition(aEvent)
|
||||
{
|
||||
var box = this.browser.boxObject;
|
||||
var W = box.width;
|
||||
var H = box.height;
|
||||
var X = box.screenX;
|
||||
var Y = box.screenY;
|
||||
var x = aEvent.screenX - X;
|
||||
var y = aEvent.screenY - Y;
|
||||
|
||||
if (x > (W * 0.33) &&
|
||||
x < (W * 0.66) &&
|
||||
y > (H * 0.33) &&
|
||||
y < (H * 0.66))
|
||||
return 'center';
|
||||
|
||||
var isTL = x <= W - (y * W / H);
|
||||
var isBL = x <= y * W / H;
|
||||
return (isTL && isBL) ? 'left' :
|
||||
(isTL && !isBL) ? 'top' :
|
||||
(!isTL && isBL) ? 'bottom' :
|
||||
'right' ;
|
||||
},
|
||||
|
||||
canDrop : function TabpanelDND_canDrop(aEvent)
|
||||
{
|
||||
var session = this.treeStyleTab.currentDragSession;
|
||||
return !!(
|
||||
session &&
|
||||
session.isDataFlavorSupported(this.treeStyleTab.kDRAG_TYPE_TABBAR) &&
|
||||
session.sourceNode &&
|
||||
session.sourceNode.ownerDocument == this.document
|
||||
);
|
||||
},
|
||||
|
||||
handleEvent : function TabpanelDND_handleEvent(aEvent)
|
||||
{
|
||||
// ignore drag and drop while toolbar customization
|
||||
if (this.treeStyleTab.isToolbarCustomizing)
|
||||
return;
|
||||
|
||||
switch (aEvent.type)
|
||||
{
|
||||
case 'dragleave': return this.onDragLeave(aEvent);
|
||||
case 'dragover': return this.onDragOver(aEvent);
|
||||
case 'drop': return this.onDrop(aEvent);
|
||||
}
|
||||
},
|
||||
|
||||
onDragLeave : function TabpanelDND_onDragLeave(aEvent)
|
||||
{
|
||||
if (!this.canDrop(aEvent)) return;
|
||||
var sv = this.treeStyleTab;
|
||||
if (this.browser.hasAttribute(sv.kDROP_POSITION))
|
||||
sv.setTabbrowserAttribute(sv.kDROP_POSITION, sv.kDROP_POSITION_UNKNOWN);
|
||||
},
|
||||
|
||||
onDragOver : function TabpanelDND_onDragOver(aEvent)
|
||||
{
|
||||
if (!this.canDrop(aEvent)) return;
|
||||
aEvent.preventDefault();
|
||||
var sv = this.treeStyleTab;
|
||||
sv.setTabbrowserAttribute(sv.kDROP_POSITION, this.getDropPosition(aEvent));
|
||||
},
|
||||
|
||||
onDrop : function TabpanelDND_onDrop(aEvent)
|
||||
{
|
||||
if (!this.canDrop(aEvent)) return;
|
||||
var sv = this.treeStyleTab;
|
||||
var dt = aEvent.dataTransfer;
|
||||
var position = this.getDropPosition(aEvent);
|
||||
if (position != 'center' &&
|
||||
position != sv.position) {
|
||||
if (utils.getTreePref('tabbar.fixed.autoCancelOnDrop') &&
|
||||
dt.getData(sv.kDRAG_TYPE_TABBAR) != sv.kTABBAR_MOVE_FORCE) {
|
||||
let orient = (position == 'left' || position == 'right') ? 'vertical' : 'horizontal' ;
|
||||
utils.setTreePref('tabbar.fixed.'+orient, false);
|
||||
}
|
||||
sv.setPrefForActiveWindow(function() {
|
||||
sv.position = sv.base.position = position;
|
||||
});
|
||||
}
|
||||
|
||||
aEvent.preventDefault();
|
||||
aEvent.stopPropagation();
|
||||
},
|
||||
|
||||
init : function TabpanelDND_init(aTabBrowser)
|
||||
{
|
||||
this.browser = aTabBrowser;
|
||||
this.document = aTabBrowser.ownerDocument;
|
||||
this.window = this.document.defaultView;
|
||||
this.treeStyleTab = aTabBrowser.treeStyleTab;
|
||||
|
||||
var b = this.treeStyleTab.mTabBrowser;
|
||||
b.mPanelContainer.addEventListener('dragover', this, true);
|
||||
b.mPanelContainer.addEventListener('dragleave', this, true);
|
||||
b.mPanelContainer.addEventListener('drop', this, true);
|
||||
},
|
||||
|
||||
destroy : function TabpanelDND_destroy()
|
||||
{
|
||||
var b = this.treeStyleTab.mTabBrowser;
|
||||
b.mPanelContainer.removeEventListener('dragover', this, true);
|
||||
b.mPanelContainer.removeEventListener('dragleave', this, true);
|
||||
b.mPanelContainer.removeEventListener('drop', this, true);
|
||||
|
||||
delete this.treeStyleTab;
|
||||
delete this.browser;
|
||||
delete this.document;
|
||||
delete this.window;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/* ***** 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 YUKI "Piro" Hiroshi.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010-2013
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s): YUKI "Piro" Hiroshi <piro.outsider.reflex@gmail.com>
|
||||
* Tetsuharu OHZEKI <https://github.com/saneyuki>
|
||||
*
|
||||
* 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 = ['TabpanelDNDObserver'];
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
|
||||
Components.utils.import('resource://gre/modules/XPCOMUtils.jsm');
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, 'utils', 'resource://treestyletab-modules/utils.js', 'TreeStyleTabUtils');
|
||||
|
||||
|
||||
function TabpanelDNDObserver(aTabBrowser)
|
||||
{
|
||||
this.init(aTabBrowser);
|
||||
}
|
||||
|
||||
TabpanelDNDObserver.prototype = {
|
||||
|
||||
getDropPosition : function TabpanelDND_getDropPosition(aEvent)
|
||||
{
|
||||
var box = this.browser.boxObject;
|
||||
var W = box.width;
|
||||
var H = box.height;
|
||||
var X = box.screenX;
|
||||
var Y = box.screenY;
|
||||
var x = aEvent.screenX - X;
|
||||
var y = aEvent.screenY - Y;
|
||||
|
||||
if (x > (W * 0.33) &&
|
||||
x < (W * 0.66) &&
|
||||
y > (H * 0.33) &&
|
||||
y < (H * 0.66))
|
||||
return 'center';
|
||||
|
||||
var isTL = x <= W - (y * W / H);
|
||||
var isBL = x <= y * W / H;
|
||||
return (isTL && isBL) ? 'left' :
|
||||
(isTL && !isBL) ? 'top' :
|
||||
(!isTL && isBL) ? 'bottom' :
|
||||
'right' ;
|
||||
},
|
||||
|
||||
canDrop : function TabpanelDND_canDrop(aEvent)
|
||||
{
|
||||
var session = this.treeStyleTab.currentDragSession;
|
||||
return !!(
|
||||
session &&
|
||||
session.isDataFlavorSupported(this.treeStyleTab.kDRAG_TYPE_TABBAR) &&
|
||||
session.sourceNode &&
|
||||
session.sourceNode.ownerDocument == this.document
|
||||
);
|
||||
},
|
||||
|
||||
handleEvent : function TabpanelDND_handleEvent(aEvent)
|
||||
{
|
||||
// ignore drag and drop while toolbar customization
|
||||
if (this.treeStyleTab.isToolbarCustomizing)
|
||||
return;
|
||||
|
||||
switch (aEvent.type)
|
||||
{
|
||||
case 'dragleave': return this.onDragLeave(aEvent);
|
||||
case 'dragover': return this.onDragOver(aEvent);
|
||||
case 'drop': return this.onDrop(aEvent);
|
||||
}
|
||||
},
|
||||
|
||||
onDragLeave : function TabpanelDND_onDragLeave(aEvent)
|
||||
{
|
||||
if (!this.canDrop(aEvent)) return;
|
||||
var sv = this.treeStyleTab;
|
||||
if (this.browser.hasAttribute(sv.kDROP_POSITION))
|
||||
sv.setTabbrowserAttribute(sv.kDROP_POSITION, sv.kDROP_POSITION_UNKNOWN);
|
||||
},
|
||||
|
||||
onDragOver : function TabpanelDND_onDragOver(aEvent)
|
||||
{
|
||||
if (!this.canDrop(aEvent)) return;
|
||||
aEvent.preventDefault();
|
||||
var sv = this.treeStyleTab;
|
||||
sv.setTabbrowserAttribute(sv.kDROP_POSITION, this.getDropPosition(aEvent));
|
||||
},
|
||||
|
||||
onDrop : function TabpanelDND_onDrop(aEvent)
|
||||
{
|
||||
if (!this.canDrop(aEvent)) return;
|
||||
var sv = this.treeStyleTab;
|
||||
var dt = aEvent.dataTransfer;
|
||||
var position = this.getDropPosition(aEvent);
|
||||
if (position != 'center' &&
|
||||
position != sv.position) {
|
||||
if (utils.getTreePref('tabbar.fixed.autoCancelOnDrop') &&
|
||||
dt.getData(sv.kDRAG_TYPE_TABBAR) != sv.kTABBAR_MOVE_FORCE) {
|
||||
let orient = (position == 'left' || position == 'right') ? 'vertical' : 'horizontal' ;
|
||||
utils.setTreePref('tabbar.fixed.'+orient, false);
|
||||
}
|
||||
sv.setPrefForActiveWindow(function() {
|
||||
sv.position = sv.base.position = position;
|
||||
});
|
||||
}
|
||||
|
||||
aEvent.preventDefault();
|
||||
aEvent.stopPropagation();
|
||||
},
|
||||
|
||||
init : function TabpanelDND_init(aTabBrowser)
|
||||
{
|
||||
this.browser = aTabBrowser;
|
||||
this.document = aTabBrowser.ownerDocument;
|
||||
this.window = this.document.defaultView;
|
||||
this.treeStyleTab = aTabBrowser.treeStyleTab;
|
||||
|
||||
var b = this.treeStyleTab.mTabBrowser;
|
||||
b.mPanelContainer.addEventListener('dragover', this, true);
|
||||
b.mPanelContainer.addEventListener('dragleave', this, true);
|
||||
b.mPanelContainer.addEventListener('drop', this, true);
|
||||
},
|
||||
|
||||
destroy : function TabpanelDND_destroy()
|
||||
{
|
||||
var b = this.treeStyleTab.mTabBrowser;
|
||||
b.mPanelContainer.removeEventListener('dragover', this, true);
|
||||
b.mPanelContainer.removeEventListener('dragleave', this, true);
|
||||
b.mPanelContainer.removeEventListener('drop', this, true);
|
||||
|
||||
delete this.treeStyleTab;
|
||||
delete this.browser;
|
||||
delete this.document;
|
||||
delete this.window;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
@ -1,178 +1,178 @@
|
||||
/* ***** 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 YUKI "Piro" Hiroshi.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011-2013
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s): YUKI "Piro" Hiroshi <piro.outsider.reflex@gmail.com>
|
||||
* Tetsuharu OHZEKI <https://github.com/saneyuki>
|
||||
*
|
||||
* 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 = ['TreeStyleTabThemeManager'];
|
||||
|
||||
const BASE = 'chrome://treestyletab/skin/';
|
||||
|
||||
Components.utils.import('resource://treestyletab-modules/base.js');
|
||||
|
||||
function TreeStyleTabThemeManager(aWindow)
|
||||
{
|
||||
this.window = aWindow;
|
||||
this._preLoadImagesForStyleDone = [];
|
||||
this._preLoadImagesForStyleDoneImages = [];
|
||||
}
|
||||
TreeStyleTabThemeManager.prototype = {
|
||||
destroy : function()
|
||||
{
|
||||
delete this.window;
|
||||
},
|
||||
|
||||
set : function(aStyle, aPosition)
|
||||
{
|
||||
if (this._lastStyles) {
|
||||
for (let i = 0, maxi = this._lastStyles.length; i < maxi; i++)
|
||||
{
|
||||
let style = this._lastStyles[i];
|
||||
style.parentNode.removeChild(style);
|
||||
}
|
||||
}
|
||||
this._lastStyles = null;
|
||||
|
||||
var styles = [];
|
||||
switch (aStyle)
|
||||
{
|
||||
default:
|
||||
break;
|
||||
|
||||
case 'plain':
|
||||
case 'flat':
|
||||
case 'mixed':
|
||||
styles.push(BASE+'square/base.css');
|
||||
if (aStyle != 'plain') {
|
||||
styles.push(BASE+'square/mixed.css');
|
||||
styles.push(BASE+'square/tab-surface.css');
|
||||
}
|
||||
if (aStyle != 'flat')
|
||||
styles.push(BASE+'square/dropshadow.css');
|
||||
styles.push(BASE+'platform-styled.css');
|
||||
styles.push(BASE+'square/platform.css');
|
||||
break;
|
||||
|
||||
case 'vertigo':
|
||||
styles.push(BASE+'square/base.css');
|
||||
styles.push(BASE+'square/vertigo.css');
|
||||
styles.push(BASE+'platform-styled.css');
|
||||
styles.push(BASE+'square/platform.css');
|
||||
break;
|
||||
|
||||
case 'metal':
|
||||
styles.push(BASE+'metal/base.css');
|
||||
styles.push(BASE+'metal/tab.css');
|
||||
styles.push(BASE+'metal/aero.css');
|
||||
styles.push(BASE+'platform-styled.css');
|
||||
styles.push(BASE+'metal/platform.css');
|
||||
break;
|
||||
|
||||
case 'sidebar':
|
||||
styles.push(BASE+'sidebar/sidebar.css');
|
||||
styles.push(BASE+'sidebar/aero.css');
|
||||
styles.push(BASE+'platform-styled.css');
|
||||
break;
|
||||
}
|
||||
|
||||
if (styles.length) {
|
||||
this._lastStyles = styles.map(function(aStyle) {
|
||||
var d = this.window.document;
|
||||
var pi = d.createProcessingInstruction(
|
||||
'xml-stylesheet',
|
||||
'type="text/css" href="'+aStyle+'"'
|
||||
);
|
||||
d.insertBefore(pi, d.documentElement);
|
||||
return pi;
|
||||
}, this);
|
||||
this.preloadImages(aStyle, aPosition);
|
||||
}
|
||||
},
|
||||
|
||||
preloadImages : function(aStyle, aPosition)
|
||||
{
|
||||
var key = aStyle+'-'+aPosition;
|
||||
if (!aStyle ||
|
||||
this._preLoadImagesForStyleDone.indexOf(key) > -1)
|
||||
return;
|
||||
this._preLoadImagesForStyleDone.push(key);
|
||||
|
||||
var images = key in this._preLoadImages ?
|
||||
this._preLoadImages[key] :
|
||||
null ;
|
||||
if (!images) return;
|
||||
|
||||
for (let i = 0, maxi = images.length; i < maxi; i++)
|
||||
{
|
||||
let image = images[i];
|
||||
if (this._preLoadImagesForStyleDoneImages.indexOf(image) > -1)
|
||||
continue;
|
||||
|
||||
(new this.window.Image()).src = image;
|
||||
this._preLoadImagesForStyleDoneImages.push(image);
|
||||
}
|
||||
},
|
||||
|
||||
_preLoadImages : {
|
||||
'metal-left' : [
|
||||
BASE+'metal/tab-active-l.png',
|
||||
BASE+'metal/tab-inactive-l.png',
|
||||
BASE+'metal/tab-active-selected-l.png',
|
||||
BASE+'metal/tab-inactive-selected-l.png',
|
||||
BASE+'metal/shadow-active-l.png',
|
||||
BASE+'metal/shadow-inactive-l.png'
|
||||
].concat(
|
||||
[
|
||||
BASE+'metal/tab-active-middle.png',
|
||||
BASE+'metal/tab-active-middle-selected.png',
|
||||
BASE+'metal/tab-inactive-middle.png',
|
||||
BASE+'metal/tab-inactive-middle-selected.png'
|
||||
]
|
||||
),
|
||||
'metal-right' : [
|
||||
BASE+'metal/tab-active-r.png',
|
||||
BASE+'metal/tab-inactive-r.png',
|
||||
BASE+'metal/tab-active-selected-r.png',
|
||||
BASE+'metal/tab-inactive-selected-r.png',
|
||||
BASE+'metal/shadow-active-r.png',
|
||||
BASE+'metal/shadow-inactive-r.png'
|
||||
].concat(
|
||||
[
|
||||
BASE+'metal/tab-active-middle.png',
|
||||
BASE+'metal/tab-active-middle-selected.png',
|
||||
BASE+'metal/tab-inactive-middle.png',
|
||||
BASE+'metal/tab-inactive-middle-selected.png'
|
||||
]
|
||||
)
|
||||
}
|
||||
};
|
||||
/* ***** 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 YUKI "Piro" Hiroshi.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011-2013
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s): YUKI "Piro" Hiroshi <piro.outsider.reflex@gmail.com>
|
||||
* Tetsuharu OHZEKI <https://github.com/saneyuki>
|
||||
*
|
||||
* 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 = ['TreeStyleTabThemeManager'];
|
||||
|
||||
const BASE = 'chrome://treestyletab/skin/';
|
||||
|
||||
Components.utils.import('resource://treestyletab-modules/base.js');
|
||||
|
||||
function TreeStyleTabThemeManager(aWindow)
|
||||
{
|
||||
this.window = aWindow;
|
||||
this._preLoadImagesForStyleDone = [];
|
||||
this._preLoadImagesForStyleDoneImages = [];
|
||||
}
|
||||
TreeStyleTabThemeManager.prototype = {
|
||||
destroy : function()
|
||||
{
|
||||
delete this.window;
|
||||
},
|
||||
|
||||
set : function(aStyle, aPosition)
|
||||
{
|
||||
if (this._lastStyles) {
|
||||
for (let i = 0, maxi = this._lastStyles.length; i < maxi; i++)
|
||||
{
|
||||
let style = this._lastStyles[i];
|
||||
style.parentNode.removeChild(style);
|
||||
}
|
||||
}
|
||||
this._lastStyles = null;
|
||||
|
||||
var styles = [];
|
||||
switch (aStyle)
|
||||
{
|
||||
default:
|
||||
break;
|
||||
|
||||
case 'plain':
|
||||
case 'flat':
|
||||
case 'mixed':
|
||||
styles.push(BASE+'square/base.css');
|
||||
if (aStyle != 'plain') {
|
||||
styles.push(BASE+'square/mixed.css');
|
||||
styles.push(BASE+'square/tab-surface.css');
|
||||
}
|
||||
if (aStyle != 'flat')
|
||||
styles.push(BASE+'square/dropshadow.css');
|
||||
styles.push(BASE+'platform-styled.css');
|
||||
styles.push(BASE+'square/platform.css');
|
||||
break;
|
||||
|
||||
case 'vertigo':
|
||||
styles.push(BASE+'square/base.css');
|
||||
styles.push(BASE+'square/vertigo.css');
|
||||
styles.push(BASE+'platform-styled.css');
|
||||
styles.push(BASE+'square/platform.css');
|
||||
break;
|
||||
|
||||
case 'metal':
|
||||
styles.push(BASE+'metal/base.css');
|
||||
styles.push(BASE+'metal/tab.css');
|
||||
styles.push(BASE+'metal/aero.css');
|
||||
styles.push(BASE+'platform-styled.css');
|
||||
styles.push(BASE+'metal/platform.css');
|
||||
break;
|
||||
|
||||
case 'sidebar':
|
||||
styles.push(BASE+'sidebar/sidebar.css');
|
||||
styles.push(BASE+'sidebar/aero.css');
|
||||
styles.push(BASE+'platform-styled.css');
|
||||
break;
|
||||
}
|
||||
|
||||
if (styles.length) {
|
||||
this._lastStyles = styles.map(function(aStyle) {
|
||||
var d = this.window.document;
|
||||
var pi = d.createProcessingInstruction(
|
||||
'xml-stylesheet',
|
||||
'type="text/css" href="'+aStyle+'"'
|
||||
);
|
||||
d.insertBefore(pi, d.documentElement);
|
||||
return pi;
|
||||
}, this);
|
||||
this.preloadImages(aStyle, aPosition);
|
||||
}
|
||||
},
|
||||
|
||||
preloadImages : function(aStyle, aPosition)
|
||||
{
|
||||
var key = aStyle+'-'+aPosition;
|
||||
if (!aStyle ||
|
||||
this._preLoadImagesForStyleDone.indexOf(key) > -1)
|
||||
return;
|
||||
this._preLoadImagesForStyleDone.push(key);
|
||||
|
||||
var images = key in this._preLoadImages ?
|
||||
this._preLoadImages[key] :
|
||||
null ;
|
||||
if (!images) return;
|
||||
|
||||
for (let i = 0, maxi = images.length; i < maxi; i++)
|
||||
{
|
||||
let image = images[i];
|
||||
if (this._preLoadImagesForStyleDoneImages.indexOf(image) > -1)
|
||||
continue;
|
||||
|
||||
(new this.window.Image()).src = image;
|
||||
this._preLoadImagesForStyleDoneImages.push(image);
|
||||
}
|
||||
},
|
||||
|
||||
_preLoadImages : {
|
||||
'metal-left' : [
|
||||
BASE+'metal/tab-active-l.png',
|
||||
BASE+'metal/tab-inactive-l.png',
|
||||
BASE+'metal/tab-active-selected-l.png',
|
||||
BASE+'metal/tab-inactive-selected-l.png',
|
||||
BASE+'metal/shadow-active-l.png',
|
||||
BASE+'metal/shadow-inactive-l.png'
|
||||
].concat(
|
||||
[
|
||||
BASE+'metal/tab-active-middle.png',
|
||||
BASE+'metal/tab-active-middle-selected.png',
|
||||
BASE+'metal/tab-inactive-middle.png',
|
||||
BASE+'metal/tab-inactive-middle-selected.png'
|
||||
]
|
||||
),
|
||||
'metal-right' : [
|
||||
BASE+'metal/tab-active-r.png',
|
||||
BASE+'metal/tab-inactive-r.png',
|
||||
BASE+'metal/tab-active-selected-r.png',
|
||||
BASE+'metal/tab-inactive-selected-r.png',
|
||||
BASE+'metal/shadow-active-r.png',
|
||||
BASE+'metal/shadow-inactive-r.png'
|
||||
].concat(
|
||||
[
|
||||
BASE+'metal/tab-active-middle.png',
|
||||
BASE+'metal/tab-active-middle-selected.png',
|
||||
BASE+'metal/tab-inactive-middle.png',
|
||||
BASE+'metal/tab-inactive-middle-selected.png'
|
||||
]
|
||||
)
|
||||
}
|
||||
};
|
||||
|
612
modules/utils.js
612
modules/utils.js
@ -1,306 +1,306 @@
|
||||
/* ***** 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 YUKI "Piro" Hiroshi.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010-2014
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s): YUKI "Piro" Hiroshi <piro.outsider.reflex@gmail.com>
|
||||
* Tetsuharu OHZEKI <https://github.com/saneyuki>
|
||||
*
|
||||
* 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 ******/
|
||||
|
||||
"use strict";
|
||||
|
||||
let EXPORTED_SYMBOLS = ['TreeStyleTabUtils'];
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
const Cu = Components.utils;
|
||||
|
||||
Cu.import('resource://gre/modules/XPCOMUtils.jsm');
|
||||
Cu.import('resource://treestyletab-modules/constants.js');
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, 'window', function() {
|
||||
Cu.import('resource://treestyletab-modules/lib/namespace.jsm');
|
||||
return getNamespaceFor('piro.sakura.ne.jp');
|
||||
});
|
||||
XPCOMUtils.defineLazyGetter(this, 'prefs', function() {
|
||||
Cu.import('resource://treestyletab-modules/lib/prefs.js');
|
||||
return window['piro.sakura.ne.jp'].prefs;
|
||||
});
|
||||
XPCOMUtils.defineLazyGetter(this, 'stringBundle', function() {
|
||||
Cu.import('resource://treestyletab-modules/lib/stringBundle.js', {});
|
||||
return window['piro.sakura.ne.jp'].stringBundle;
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, 'Task',
|
||||
'resource://gre/modules/Task.jsm');
|
||||
XPCOMUtils.defineLazyModuleGetter(this, 'TreeStyleTabConstants',
|
||||
'resource://treestyletab-modules/constants.js', 'TreeStyleTabConstants');
|
||||
|
||||
const TST_PREF_PREFIX = 'extensions.treestyletab.';
|
||||
const TST_PREF_VERSION = 10;
|
||||
|
||||
|
||||
let TreeStyleTabUtils = {
|
||||
|
||||
get prefs () {
|
||||
return prefs;
|
||||
},
|
||||
|
||||
/* Save/Load Prefs */
|
||||
|
||||
getTreePref : function TSTUtils_getTreePref(aPrefstring)
|
||||
{
|
||||
return prefs.getPref(TST_PREF_PREFIX + aPrefstring);
|
||||
},
|
||||
|
||||
setTreePref : function TSTUtils_setTreePref(aPrefstring, aNewValue)
|
||||
{
|
||||
return prefs.setPref(TST_PREF_PREFIX + aPrefstring, aNewValue);
|
||||
},
|
||||
|
||||
clearTreePref : function TSTUtils_clearTreePref(aPrefstring)
|
||||
{
|
||||
return prefs.clearPref(TST_PREF_PREFIX + aPrefstring);
|
||||
},
|
||||
|
||||
migratePrefs : function utils_migratePrefs()
|
||||
{
|
||||
// migrate old prefs
|
||||
var orientalPrefs = [];
|
||||
switch (this.getTreePref('prefsVersion'))
|
||||
{
|
||||
case 0:
|
||||
orientalPrefs = orientalPrefs.concat([
|
||||
'extensions.treestyletab.tabbar.fixed',
|
||||
'extensions.treestyletab.enableSubtreeIndent',
|
||||
'extensions.treestyletab.allowSubtreeCollapseExpand'
|
||||
]);
|
||||
case 1:
|
||||
case 2:
|
||||
if (this.getTreePref('urlbar.loadSameDomainToNewChildTab') !== null) {
|
||||
let value = this.getTreePref('urlbar.loadSameDomainToNewChildTab');
|
||||
this.setTreePref('urlbar.loadSameDomainToNewTab', value);
|
||||
this.setTreePref('urlbar.loadSameDomainToNewTab.asChild', value);
|
||||
if (value) {
|
||||
this.setTreePref('urlbar.loadDifferentDomainToNewTab', value);
|
||||
}
|
||||
this.clearTreePref('urlbar.loadSameDomainToNewChildTab');
|
||||
}
|
||||
case 3:
|
||||
if (this.getTreePref('loadDroppedLinkToNewChildTab') !== null) {
|
||||
this.setTreePref('dropLinksOnTab.behavior',
|
||||
this.getTreePref('loadDroppedLinkToNewChildTab.confirm') ?
|
||||
TreeStyleTabConstants.kDROPLINK_ASK :
|
||||
this.getTreePref('loadDroppedLinkToNewChildTab') ?
|
||||
TreeStyleTabConstants.kDROPLINK_NEWTAB :
|
||||
TreeStyleTabConstants.kDROPLINK_LOAD
|
||||
);
|
||||
this.clearTreePref('loadDroppedLinkToNewChildTab.confirm');
|
||||
this.clearTreePref('loadDroppedLinkToNewChildTab');
|
||||
}
|
||||
if (this.getTreePref('openGroupBookmarkAsTabSubTree') !== null) {
|
||||
let behavior = 0;
|
||||
if (this.getTreePref('openGroupBookmarkAsTabSubTree.underParent'))
|
||||
behavior += TreeStyleTabConstants.kGROUP_BOOKMARK_USE_DUMMY;
|
||||
if (!this.getTreePref('openGroupBookmarkBehavior.confirm')) {
|
||||
behavior += (
|
||||
this.getTreePref('openGroupBookmarkAsTabSubTree') ?
|
||||
TreeStyleTabConstants.kGROUP_BOOKMARK_SUBTREE :
|
||||
TreeStyleTabConstants.kGROUP_BOOKMARK_SEPARATE
|
||||
);
|
||||
}
|
||||
this.setTreePref('openGroupBookmark.behavior', behavior);
|
||||
this.clearTreePref('openGroupBookmarkBehavior.confirm');
|
||||
this.clearTreePref('openGroupBookmarkAsTabSubTree');
|
||||
this.clearTreePref('openGroupBookmarkAsTabSubTree.underParent');
|
||||
}
|
||||
case 4:
|
||||
let (subTreePrefs = [
|
||||
'extensions.treestyletab.autoCollapseExpandSubTreeOnSelect',
|
||||
'extensions.treestyletab.autoCollapseExpandSubTreeOnSelect.onCurrentTabRemove',
|
||||
'extensions.treestyletab.autoCollapseExpandSubTreeOnSelect.whileFocusMovingByShortcut',
|
||||
'extensions.treestyletab.autoExpandSubTreeOnAppendChild',
|
||||
'extensions.treestyletab.autoExpandSubTreeOnCollapsedChildFocused',
|
||||
'extensions.treestyletab.collapseExpandSubTree.dblclick',
|
||||
'extensions.treestyletab.createSubTree.underParent',
|
||||
'extensions.treestyletab.show.context-item-reloadTabSubTree',
|
||||
'extensions.treestyletab.show.context-item-removeTabSubTree',
|
||||
'extensions.treestyletab.show.context-item-bookmarkTabSubTree',
|
||||
'extensions.multipletab.show.multipletab-selection-item-removeTabSubTree',
|
||||
'extensions.multipletab.show.multipletab-selection-item-createSubTree'
|
||||
]) {
|
||||
for (let i = 0, maxi = subTreePrefs.length; i < maxi; i++)
|
||||
{
|
||||
let pref = subTreePrefs[i];
|
||||
let value = prefs.getPref(pref);
|
||||
if (value === null) {
|
||||
continue;
|
||||
}
|
||||
prefs.setPref(pref.replace('SubTree', 'Subtree'), value);
|
||||
prefs.clearPref(pref);
|
||||
}
|
||||
}
|
||||
case 5:
|
||||
let (behavior = this.getTreePref('openGroupBookmark.behavior')) {
|
||||
behavior = behavior | 2048;
|
||||
this.setTreePref('openGroupBookmark.behavior', behavior);
|
||||
}
|
||||
case 6:
|
||||
let (
|
||||
general = this.getTreePref('autoAttachNewTabsAsChildren'),
|
||||
search = this.getTreePref('autoAttachSearchResultAsChildren')
|
||||
) {
|
||||
if (general !== null)
|
||||
this.setTreePref('autoAttach', general);
|
||||
if (search !== null)
|
||||
this.setTreePref('autoAttach.searchResult', search);
|
||||
}
|
||||
case 7:
|
||||
let (
|
||||
enabled = this.getTreePref('autoCollapseExpandSubtreeOnSelect.whileFocusMovingByShortcut'),
|
||||
delay = this.getTreePref('autoCollapseExpandSubtreeOnSelect.whileFocusMovingByShortcut.delay')
|
||||
) {
|
||||
if (enabled !== null) {
|
||||
this.setTreePref('autoExpandSubtreeOnSelect.whileFocusMovingByShortcut', enabled);
|
||||
this.setTreePref('autoExpandSubtreeOnSelect.whileFocusMovingByShortcut.collapseOthers', enabled);
|
||||
}
|
||||
if (delay !== null)
|
||||
this.setTreePref('autoExpandSubtreeOnSelect.whileFocusMovingByShortcut.delay', delay);
|
||||
}
|
||||
case 8:
|
||||
orientalPrefs = orientalPrefs.concat([
|
||||
'extensions.treestyletab.indent',
|
||||
'extensions.treestyletab.indent.min'
|
||||
]);
|
||||
case 9:
|
||||
let (behavior = this.getTreePref('openGroupBookmark.behavior')) {
|
||||
if (behavior & 4) {
|
||||
behavior ^= 4;
|
||||
behavior |= 1;
|
||||
this.setTreePref('openGroupBookmark.behavior', behavior);
|
||||
}
|
||||
}
|
||||
default:
|
||||
for (let i = 0, maxi = orientalPrefs.length; i < maxi; i++)
|
||||
{
|
||||
let pref = orientalPrefs[i];
|
||||
let value = prefs.getPref(pref);
|
||||
if (value === null) {
|
||||
continue;
|
||||
}
|
||||
prefs.setPref(pref+'.horizontal', value);
|
||||
prefs.setPref(pref+'.vertical', value);
|
||||
prefs.clearPref(pref);
|
||||
}
|
||||
break;
|
||||
}
|
||||
this.setTreePref('prefsVersion', TST_PREF_VERSION);
|
||||
},
|
||||
|
||||
/* string bundle */
|
||||
get treeBundle () {
|
||||
return stringBundle.get('chrome://treestyletab/locale/treestyletab.properties');
|
||||
},
|
||||
get tabbrowserBundle () {
|
||||
return stringBundle.get('chrome://browser/locale/tabbrowser.properties');
|
||||
},
|
||||
|
||||
evalInSandbox : function utils_evalInSandbox(aCode, aOwner)
|
||||
{
|
||||
try {
|
||||
var sandbox = new Cu.Sandbox(aOwner || 'about:blank');
|
||||
return Cu.evalInSandbox(aCode, sandbox);
|
||||
}
|
||||
catch(e) {
|
||||
}
|
||||
return void(0);
|
||||
},
|
||||
|
||||
|
||||
isTabNotRestoredYet : function utils_isTabNotRestoredYet(aTab)
|
||||
{
|
||||
var browser = aTab.linkedBrowser;
|
||||
// Firefox 25 and later. See: https://bugzilla.mozilla.org/show_bug.cgi?id=867142
|
||||
if (this.TabRestoreStates &&
|
||||
this.TabRestoreStates.has(browser))
|
||||
return (
|
||||
this.TabRestoreStates.isNeedsRestore(browser) ||
|
||||
this.TabRestoreStates.isRestoring(browser)
|
||||
);
|
||||
|
||||
return !!browser.__SS_restoreState;
|
||||
},
|
||||
isTabNeedToBeRestored : function utils_isTabNeedToBeRestored(aTab)
|
||||
{
|
||||
var browser = aTab.linkedBrowser;
|
||||
// Firefox 25 and later. See: https://bugzilla.mozilla.org/show_bug.cgi?id=867142
|
||||
if (this.TabRestoreStates &&
|
||||
this.TabRestoreStates.has(browser))
|
||||
return this.TabRestoreStates.isNeedsRestore(browser);
|
||||
|
||||
return browser.__SS_restoreState == 1;
|
||||
},
|
||||
get SessionStoreInternal() {
|
||||
return this.SessionStoreNS.SessionStoreInternal;
|
||||
},
|
||||
get TabRestoreStates() {
|
||||
return this.SessionStoreNS.TabRestoreStates;
|
||||
},
|
||||
get SessionStoreNS() {
|
||||
if (!this._SessionStoreNS) {
|
||||
try {
|
||||
// resource://app/modules/sessionstore/SessionStore.jsm ?
|
||||
this._SessionStoreNS = Components.utils.import('resource:///modules/sessionstore/SessionStore.jsm', {});
|
||||
}
|
||||
catch(e) {
|
||||
this._SessionStoreNS = {};
|
||||
}
|
||||
}
|
||||
return this._SessionStoreNS;
|
||||
},
|
||||
|
||||
getShortcutOrURI : function utils_getShortcutOrURI(aBrowserWindow, aURI)
|
||||
{
|
||||
var done = false;
|
||||
aBrowserWindow.getShortcutOrURIAndPostData(aURI, function(aData) {
|
||||
aURI = aData.url;
|
||||
done = true;
|
||||
});
|
||||
|
||||
// this should be rewritten in asynchronous style...
|
||||
var thread = Cc['@mozilla.org/thread-manager;1'].getService().mainThread;
|
||||
while (!done)
|
||||
{
|
||||
thread.processNextEvent(true);
|
||||
}
|
||||
|
||||
return aURI;
|
||||
}
|
||||
};
|
||||
/* ***** 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 YUKI "Piro" Hiroshi.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010-2014
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s): YUKI "Piro" Hiroshi <piro.outsider.reflex@gmail.com>
|
||||
* Tetsuharu OHZEKI <https://github.com/saneyuki>
|
||||
*
|
||||
* 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 ******/
|
||||
|
||||
"use strict";
|
||||
|
||||
let EXPORTED_SYMBOLS = ['TreeStyleTabUtils'];
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
const Cu = Components.utils;
|
||||
|
||||
Cu.import('resource://gre/modules/XPCOMUtils.jsm');
|
||||
Cu.import('resource://treestyletab-modules/constants.js');
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, 'window', function() {
|
||||
Cu.import('resource://treestyletab-modules/lib/namespace.jsm');
|
||||
return getNamespaceFor('piro.sakura.ne.jp');
|
||||
});
|
||||
XPCOMUtils.defineLazyGetter(this, 'prefs', function() {
|
||||
Cu.import('resource://treestyletab-modules/lib/prefs.js');
|
||||
return window['piro.sakura.ne.jp'].prefs;
|
||||
});
|
||||
XPCOMUtils.defineLazyGetter(this, 'stringBundle', function() {
|
||||
Cu.import('resource://treestyletab-modules/lib/stringBundle.js', {});
|
||||
return window['piro.sakura.ne.jp'].stringBundle;
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, 'Task',
|
||||
'resource://gre/modules/Task.jsm');
|
||||
XPCOMUtils.defineLazyModuleGetter(this, 'TreeStyleTabConstants',
|
||||
'resource://treestyletab-modules/constants.js', 'TreeStyleTabConstants');
|
||||
|
||||
const TST_PREF_PREFIX = 'extensions.treestyletab.';
|
||||
const TST_PREF_VERSION = 10;
|
||||
|
||||
|
||||
let TreeStyleTabUtils = {
|
||||
|
||||
get prefs () {
|
||||
return prefs;
|
||||
},
|
||||
|
||||
/* Save/Load Prefs */
|
||||
|
||||
getTreePref : function TSTUtils_getTreePref(aPrefstring)
|
||||
{
|
||||
return prefs.getPref(TST_PREF_PREFIX + aPrefstring);
|
||||
},
|
||||
|
||||
setTreePref : function TSTUtils_setTreePref(aPrefstring, aNewValue)
|
||||
{
|
||||
return prefs.setPref(TST_PREF_PREFIX + aPrefstring, aNewValue);
|
||||
},
|
||||
|
||||
clearTreePref : function TSTUtils_clearTreePref(aPrefstring)
|
||||
{
|
||||
return prefs.clearPref(TST_PREF_PREFIX + aPrefstring);
|
||||
},
|
||||
|
||||
migratePrefs : function utils_migratePrefs()
|
||||
{
|
||||
// migrate old prefs
|
||||
var orientalPrefs = [];
|
||||
switch (this.getTreePref('prefsVersion'))
|
||||
{
|
||||
case 0:
|
||||
orientalPrefs = orientalPrefs.concat([
|
||||
'extensions.treestyletab.tabbar.fixed',
|
||||
'extensions.treestyletab.enableSubtreeIndent',
|
||||
'extensions.treestyletab.allowSubtreeCollapseExpand'
|
||||
]);
|
||||
case 1:
|
||||
case 2:
|
||||
if (this.getTreePref('urlbar.loadSameDomainToNewChildTab') !== null) {
|
||||
let value = this.getTreePref('urlbar.loadSameDomainToNewChildTab');
|
||||
this.setTreePref('urlbar.loadSameDomainToNewTab', value);
|
||||
this.setTreePref('urlbar.loadSameDomainToNewTab.asChild', value);
|
||||
if (value) {
|
||||
this.setTreePref('urlbar.loadDifferentDomainToNewTab', value);
|
||||
}
|
||||
this.clearTreePref('urlbar.loadSameDomainToNewChildTab');
|
||||
}
|
||||
case 3:
|
||||
if (this.getTreePref('loadDroppedLinkToNewChildTab') !== null) {
|
||||
this.setTreePref('dropLinksOnTab.behavior',
|
||||
this.getTreePref('loadDroppedLinkToNewChildTab.confirm') ?
|
||||
TreeStyleTabConstants.kDROPLINK_ASK :
|
||||
this.getTreePref('loadDroppedLinkToNewChildTab') ?
|
||||
TreeStyleTabConstants.kDROPLINK_NEWTAB :
|
||||
TreeStyleTabConstants.kDROPLINK_LOAD
|
||||
);
|
||||
this.clearTreePref('loadDroppedLinkToNewChildTab.confirm');
|
||||
this.clearTreePref('loadDroppedLinkToNewChildTab');
|
||||
}
|
||||
if (this.getTreePref('openGroupBookmarkAsTabSubTree') !== null) {
|
||||
let behavior = 0;
|
||||
if (this.getTreePref('openGroupBookmarkAsTabSubTree.underParent'))
|
||||
behavior += TreeStyleTabConstants.kGROUP_BOOKMARK_USE_DUMMY;
|
||||
if (!this.getTreePref('openGroupBookmarkBehavior.confirm')) {
|
||||
behavior += (
|
||||
this.getTreePref('openGroupBookmarkAsTabSubTree') ?
|
||||
TreeStyleTabConstants.kGROUP_BOOKMARK_SUBTREE :
|
||||
TreeStyleTabConstants.kGROUP_BOOKMARK_SEPARATE
|
||||
);
|
||||
}
|
||||
this.setTreePref('openGroupBookmark.behavior', behavior);
|
||||
this.clearTreePref('openGroupBookmarkBehavior.confirm');
|
||||
this.clearTreePref('openGroupBookmarkAsTabSubTree');
|
||||
this.clearTreePref('openGroupBookmarkAsTabSubTree.underParent');
|
||||
}
|
||||
case 4:
|
||||
let (subTreePrefs = [
|
||||
'extensions.treestyletab.autoCollapseExpandSubTreeOnSelect',
|
||||
'extensions.treestyletab.autoCollapseExpandSubTreeOnSelect.onCurrentTabRemove',
|
||||
'extensions.treestyletab.autoCollapseExpandSubTreeOnSelect.whileFocusMovingByShortcut',
|
||||
'extensions.treestyletab.autoExpandSubTreeOnAppendChild',
|
||||
'extensions.treestyletab.autoExpandSubTreeOnCollapsedChildFocused',
|
||||
'extensions.treestyletab.collapseExpandSubTree.dblclick',
|
||||
'extensions.treestyletab.createSubTree.underParent',
|
||||
'extensions.treestyletab.show.context-item-reloadTabSubTree',
|
||||
'extensions.treestyletab.show.context-item-removeTabSubTree',
|
||||
'extensions.treestyletab.show.context-item-bookmarkTabSubTree',
|
||||
'extensions.multipletab.show.multipletab-selection-item-removeTabSubTree',
|
||||
'extensions.multipletab.show.multipletab-selection-item-createSubTree'
|
||||
]) {
|
||||
for (let i = 0, maxi = subTreePrefs.length; i < maxi; i++)
|
||||
{
|
||||
let pref = subTreePrefs[i];
|
||||
let value = prefs.getPref(pref);
|
||||
if (value === null) {
|
||||
continue;
|
||||
}
|
||||
prefs.setPref(pref.replace('SubTree', 'Subtree'), value);
|
||||
prefs.clearPref(pref);
|
||||
}
|
||||
}
|
||||
case 5:
|
||||
let (behavior = this.getTreePref('openGroupBookmark.behavior')) {
|
||||
behavior = behavior | 2048;
|
||||
this.setTreePref('openGroupBookmark.behavior', behavior);
|
||||
}
|
||||
case 6:
|
||||
let (
|
||||
general = this.getTreePref('autoAttachNewTabsAsChildren'),
|
||||
search = this.getTreePref('autoAttachSearchResultAsChildren')
|
||||
) {
|
||||
if (general !== null)
|
||||
this.setTreePref('autoAttach', general);
|
||||
if (search !== null)
|
||||
this.setTreePref('autoAttach.searchResult', search);
|
||||
}
|
||||
case 7:
|
||||
let (
|
||||
enabled = this.getTreePref('autoCollapseExpandSubtreeOnSelect.whileFocusMovingByShortcut'),
|
||||
delay = this.getTreePref('autoCollapseExpandSubtreeOnSelect.whileFocusMovingByShortcut.delay')
|
||||
) {
|
||||
if (enabled !== null) {
|
||||
this.setTreePref('autoExpandSubtreeOnSelect.whileFocusMovingByShortcut', enabled);
|
||||
this.setTreePref('autoExpandSubtreeOnSelect.whileFocusMovingByShortcut.collapseOthers', enabled);
|
||||
}
|
||||
if (delay !== null)
|
||||
this.setTreePref('autoExpandSubtreeOnSelect.whileFocusMovingByShortcut.delay', delay);
|
||||
}
|
||||
case 8:
|
||||
orientalPrefs = orientalPrefs.concat([
|
||||
'extensions.treestyletab.indent',
|
||||
'extensions.treestyletab.indent.min'
|
||||
]);
|
||||
case 9:
|
||||
let (behavior = this.getTreePref('openGroupBookmark.behavior')) {
|
||||
if (behavior & 4) {
|
||||
behavior ^= 4;
|
||||
behavior |= 1;
|
||||
this.setTreePref('openGroupBookmark.behavior', behavior);
|
||||
}
|
||||
}
|
||||
default:
|
||||
for (let i = 0, maxi = orientalPrefs.length; i < maxi; i++)
|
||||
{
|
||||
let pref = orientalPrefs[i];
|
||||
let value = prefs.getPref(pref);
|
||||
if (value === null) {
|
||||
continue;
|
||||
}
|
||||
prefs.setPref(pref+'.horizontal', value);
|
||||
prefs.setPref(pref+'.vertical', value);
|
||||
prefs.clearPref(pref);
|
||||
}
|
||||
break;
|
||||
}
|
||||
this.setTreePref('prefsVersion', TST_PREF_VERSION);
|
||||
},
|
||||
|
||||
/* string bundle */
|
||||
get treeBundle () {
|
||||
return stringBundle.get('chrome://treestyletab/locale/treestyletab.properties');
|
||||
},
|
||||
get tabbrowserBundle () {
|
||||
return stringBundle.get('chrome://browser/locale/tabbrowser.properties');
|
||||
},
|
||||
|
||||
evalInSandbox : function utils_evalInSandbox(aCode, aOwner)
|
||||
{
|
||||
try {
|
||||
var sandbox = new Cu.Sandbox(aOwner || 'about:blank');
|
||||
return Cu.evalInSandbox(aCode, sandbox);
|
||||
}
|
||||
catch(e) {
|
||||
}
|
||||
return void(0);
|
||||
},
|
||||
|
||||
|
||||
isTabNotRestoredYet : function utils_isTabNotRestoredYet(aTab)
|
||||
{
|
||||
var browser = aTab.linkedBrowser;
|
||||
// Firefox 25 and later. See: https://bugzilla.mozilla.org/show_bug.cgi?id=867142
|
||||
if (this.TabRestoreStates &&
|
||||
this.TabRestoreStates.has(browser))
|
||||
return (
|
||||
this.TabRestoreStates.isNeedsRestore(browser) ||
|
||||
this.TabRestoreStates.isRestoring(browser)
|
||||
);
|
||||
|
||||
return !!browser.__SS_restoreState;
|
||||
},
|
||||
isTabNeedToBeRestored : function utils_isTabNeedToBeRestored(aTab)
|
||||
{
|
||||
var browser = aTab.linkedBrowser;
|
||||
// Firefox 25 and later. See: https://bugzilla.mozilla.org/show_bug.cgi?id=867142
|
||||
if (this.TabRestoreStates &&
|
||||
this.TabRestoreStates.has(browser))
|
||||
return this.TabRestoreStates.isNeedsRestore(browser);
|
||||
|
||||
return browser.__SS_restoreState == 1;
|
||||
},
|
||||
get SessionStoreInternal() {
|
||||
return this.SessionStoreNS.SessionStoreInternal;
|
||||
},
|
||||
get TabRestoreStates() {
|
||||
return this.SessionStoreNS.TabRestoreStates;
|
||||
},
|
||||
get SessionStoreNS() {
|
||||
if (!this._SessionStoreNS) {
|
||||
try {
|
||||
// resource://app/modules/sessionstore/SessionStore.jsm ?
|
||||
this._SessionStoreNS = Components.utils.import('resource:///modules/sessionstore/SessionStore.jsm', {});
|
||||
}
|
||||
catch(e) {
|
||||
this._SessionStoreNS = {};
|
||||
}
|
||||
}
|
||||
return this._SessionStoreNS;
|
||||
},
|
||||
|
||||
getShortcutOrURI : function utils_getShortcutOrURI(aBrowserWindow, aURI)
|
||||
{
|
||||
var done = false;
|
||||
aBrowserWindow.getShortcutOrURIAndPostData(aURI, function(aData) {
|
||||
aURI = aData.url;
|
||||
done = true;
|
||||
});
|
||||
|
||||
// this should be rewritten in asynchronous style...
|
||||
var thread = Cc['@mozilla.org/thread-manager;1'].getService().mainThread;
|
||||
while (!done)
|
||||
{
|
||||
thread.processNextEvent(true);
|
||||
}
|
||||
|
||||
return aURI;
|
||||
}
|
||||
};
|
||||
|
3544
modules/window.js
3544
modules/window.js
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user