タブの折りたたみをアニメーションするようにした
git-svn-id: http://www.cozmixng.org/repos/piro/treestyletab/trunk@4067 599a83e7-65a4-db11-8015-0010dcdd6dc2
This commit is contained in:
parent
192634fcb2
commit
ec1fb499e3
@ -16,7 +16,7 @@ tabbrowser[treestyletab-allow-subtree-collapse="true"] .tabbrowser-tab[treestyle
|
||||
display: -moz-box;
|
||||
}
|
||||
|
||||
tabbrowser[treestyletab-allow-subtree-collapse="true"] .tabbrowser-tab[treestyletab-collapsed="true"],
|
||||
tabbrowser[treestyletab-allow-subtree-collapse="true"] .tabbrowser-tab[treestyletab-collapsed-done="true"],
|
||||
.tabbrowser-strip[collapsed="true"]+splitter:not([state="collapsed"]),
|
||||
tabbrowser[treestyletab-tabbar-autohide="hidden"] .tabbrowser-strip,
|
||||
tabbrowser[treestyletab-tabbar-autohide="hidden"] .tabbrowser-strip+splitter,
|
||||
@ -26,6 +26,7 @@ tabbrowser[treestyletab-tabbar-fixed="true"] .tabbrowser-strip+splitter {
|
||||
visibility: collapse;
|
||||
}
|
||||
|
||||
|
||||
tabbrowser:not([treestyletab-mode="horizontal"]) .tabbrowser-arrowscrollbox > .scrollbutton-up,
|
||||
tabbrowser:not([treestyletab-mode="horizontal"]) .tabbrowser-arrowscrollbox > .scrollbutton-down-stack,
|
||||
tabbrowser:not([treestyletab-mode="horizontal"]) .tabbrowser-arrowscrollbox > .scrollbutton-down, /* Firefox 3 */
|
||||
|
@ -6,6 +6,8 @@ var TreeStyleTabService = {
|
||||
kINSERT_BEFORE : 'treestyletab-insert-before',
|
||||
kSUBTREE_COLLAPSED : 'treestyletab-subtree-collapsed',
|
||||
kCOLLAPSED : 'treestyletab-collapsed',
|
||||
kCOLLAPSED_DONE : 'treestyletab-collapsed-done',
|
||||
kCOLLAPSING : 'treestyletab-collapsing',
|
||||
kTWISTY_HOVER : 'treestyletab-twisty-hover',
|
||||
kNEST : 'treestyletab-nest',
|
||||
kDROP_POSITION : 'treestyletab-drop-position',
|
||||
@ -93,9 +95,12 @@ var TreeStyleTabService = {
|
||||
kINSERT_FISRT : 0,
|
||||
kINSERT_LAST : 1,
|
||||
|
||||
baseLebelMargin : 12,
|
||||
baseIndent : 12,
|
||||
shouldDetectClickOnIndentSpaces : true,
|
||||
|
||||
animationEnabled : true,
|
||||
indentDelay : 200,
|
||||
collapseDelay : 150,
|
||||
|
||||
NSResolver : {
|
||||
lookupNamespaceURI : function(aPrefix)
|
||||
@ -1032,13 +1037,15 @@ var TreeStyleTabService = {
|
||||
|
||||
this.processRestoredTabs();
|
||||
|
||||
this.observe(null, 'nsPref:changed', 'extensions.treestyletab.levelMargin');
|
||||
this.observe(null, 'nsPref:changed', 'extensions.treestyletab.indent');
|
||||
this.observe(null, 'nsPref:changed', 'extensions.treestyletab.tabbar.autoHide.mode');
|
||||
this.observe(null, 'nsPref:changed', 'extensions.treestyletab.clickOnIndentSpaces.enabled');
|
||||
this.observe(null, 'nsPref:changed', 'browser.link.open_newwindow.restriction.override');
|
||||
this.observe(null, 'nsPref:changed', 'browser.tabs.loadFolderAndReplace.override');
|
||||
this.observe(null, 'nsPref:changed', 'extensions.treestyletab.tabbar.style');
|
||||
this.observe(null, 'nsPref:changed', 'extensions.treestyletab.animation.enabled');
|
||||
this.observe(null, 'nsPref:changed', 'extensions.treestyletab.animation.indent.delay');
|
||||
this.observe(null, 'nsPref:changed', 'extensions.treestyletab.animation.collapse.delay');
|
||||
},
|
||||
initialized : false,
|
||||
|
||||
@ -2093,9 +2100,9 @@ catch(e) {
|
||||
var value = this.getPref(aPrefName);
|
||||
switch (aPrefName)
|
||||
{
|
||||
case 'extensions.treestyletab.levelMargin':
|
||||
this.baseLebelMargin = value;
|
||||
this.ObserverService.notifyObservers(null, 'TreeStyleTab:levelMarginModified', value);
|
||||
case 'extensions.treestyletab.indent':
|
||||
this.baseIndent = value;
|
||||
this.ObserverService.notifyObservers(null, 'TreeStyleTab:indentModified', value);
|
||||
break;
|
||||
|
||||
case 'extensions.treestyletab.tabbar.autoHide.mode':
|
||||
@ -2148,6 +2155,12 @@ catch(e) {
|
||||
case 'extensions.treestyletab.animation.enabled':
|
||||
this.animationEnabled = value;
|
||||
break;
|
||||
case 'extensions.treestyletab.animation.indent.delay':
|
||||
this.indentDelay = value;
|
||||
break;
|
||||
case 'extensions.treestyletab.animation.collapse.delay':
|
||||
this.collapseDelay = value;
|
||||
break;
|
||||
|
||||
case 'extensions.treestyletab.tabbar.style':
|
||||
case 'extensions.treestyletab.tabbar.position':
|
||||
|
@ -24,13 +24,29 @@ TreeStyleTabBrowser.prototype = {
|
||||
|
||||
tabbarResizing : false,
|
||||
|
||||
levelMargin : -1,
|
||||
levelMarginProp : 'margin-left',
|
||||
indent : -1,
|
||||
indentProp : 'margin-left',
|
||||
collapseProp : 'margin-top',
|
||||
positionProp : 'screenY',
|
||||
sizeProp : 'height',
|
||||
invertedPositionProp : 'screenX',
|
||||
invertedSizeProp : 'width',
|
||||
|
||||
kVERTICAL_MARGIN_RULES_PATTERN : /margin-(top|bottom):[^;]+;?/g,
|
||||
kHORIZONTAL_MARGIN_RULES_PATTERN : /margin-(left|right):[^;]+;?/g,
|
||||
get indentRulesRegExp()
|
||||
{
|
||||
return this.isVertical ?
|
||||
this.kHORIZONTAL_MARGIN_RULES_PATTERN :
|
||||
this.kVERTICAL_MARGIN_RULES_PATTERN ;
|
||||
},
|
||||
get collapseRulesRegExp()
|
||||
{
|
||||
return this.isVertical ?
|
||||
this.kVERTICAL_MARGIN_RULES_PATTERN :
|
||||
this.kHORIZONTAL_MARGIN_RULES_PATTERN ;
|
||||
},
|
||||
|
||||
togglerSize : 0,
|
||||
sensitiveArea : 7,
|
||||
|
||||
@ -542,7 +558,7 @@ TreeStyleTabBrowser.prototype = {
|
||||
this.clearTabbarCanvas();
|
||||
}
|
||||
|
||||
this.ObserverService.addObserver(this, 'TreeStyleTab:levelMarginModified', false);
|
||||
this.ObserverService.addObserver(this, 'TreeStyleTab:indentModified', false);
|
||||
this.ObserverService.addObserver(this, 'TreeStyleTab:collapseExpandAllSubtree', false);
|
||||
this.addPrefListener(this);
|
||||
},
|
||||
@ -738,6 +754,7 @@ TreeStyleTabBrowser.prototype = {
|
||||
b.removeAttribute(this.kRESIZING);
|
||||
|
||||
if (pos & this.kTABBAR_VERTICAL) {
|
||||
this.collapseProp = 'margin-top';
|
||||
this.positionProp = 'screenY';
|
||||
this.sizeProp = 'height';
|
||||
this.invertedPositionProp = 'screenX';
|
||||
@ -778,11 +795,11 @@ TreeStyleTabBrowser.prototype = {
|
||||
b.setAttribute(this.kTABBAR_POSITION, 'right');
|
||||
if (this.getTreePref('tabbar.invertUI')) {
|
||||
b.setAttribute(this.kUI_INVERTED, 'true');
|
||||
this.levelMarginProp = 'margin-right';
|
||||
this.indentProp = 'margin-right';
|
||||
}
|
||||
else {
|
||||
b.removeAttribute(this.kUI_INVERTED);
|
||||
this.levelMarginProp = 'margin-left';
|
||||
this.indentProp = 'margin-left';
|
||||
}
|
||||
window.setTimeout(function(aWidth) {
|
||||
/* in Firefox 3, the width of the rightside tab bar
|
||||
@ -800,7 +817,7 @@ TreeStyleTabBrowser.prototype = {
|
||||
else {
|
||||
b.setAttribute(this.kTABBAR_POSITION, 'left');
|
||||
b.removeAttribute(this.kUI_INVERTED);
|
||||
this.levelMarginProp = 'margin-left';
|
||||
this.indentProp = 'margin-left';
|
||||
window.setTimeout(function() {
|
||||
b.mTabDropIndicatorBar.setAttribute('ordinal', 1);
|
||||
b.mStrip.setAttribute('ordinal', 10);
|
||||
@ -812,6 +829,7 @@ TreeStyleTabBrowser.prototype = {
|
||||
}
|
||||
}
|
||||
else {
|
||||
this.collapseProp = 'margin-left';
|
||||
this.positionProp = 'screenX';
|
||||
this.sizeProp = 'width';
|
||||
this.invertedPositionProp = 'screenY';
|
||||
@ -849,7 +867,7 @@ TreeStyleTabBrowser.prototype = {
|
||||
b.removeAttribute(this.kUI_INVERTED);
|
||||
if (pos == this.kTABBAR_BOTTOM) {
|
||||
b.setAttribute(this.kTABBAR_POSITION, 'bottom');
|
||||
this.levelMarginProp = 'margin-bottom';
|
||||
this.indentProp = 'margin-bottom';
|
||||
window.setTimeout(function() {
|
||||
b.mTabDropIndicatorBar.setAttribute('ordinal', 1);
|
||||
b.mStrip.setAttribute('ordinal', 30);
|
||||
@ -860,7 +878,7 @@ TreeStyleTabBrowser.prototype = {
|
||||
}
|
||||
else {
|
||||
b.setAttribute(this.kTABBAR_POSITION, 'top');
|
||||
this.levelMarginProp = 'margin-top';
|
||||
this.indentProp = 'margin-top';
|
||||
window.setTimeout(function() {
|
||||
b.mTabDropIndicatorBar.setAttribute('ordinal', 1);
|
||||
b.mStrip.setAttribute('ordinal', 10);
|
||||
@ -915,7 +933,7 @@ TreeStyleTabBrowser.prototype = {
|
||||
this.tabbarCanvas = null;
|
||||
}
|
||||
|
||||
this.ObserverService.removeObserver(this, 'TreeStyleTab:levelMarginModified');
|
||||
this.ObserverService.removeObserver(this, 'TreeStyleTab:indentModified');
|
||||
this.ObserverService.removeObserver(this, 'TreeStyleTab:collapseExpandAllSubtree');
|
||||
this.removePrefListener(this);
|
||||
|
||||
@ -937,8 +955,8 @@ TreeStyleTabBrowser.prototype = {
|
||||
var b = this.mTabBrowser;
|
||||
switch (aTopic)
|
||||
{
|
||||
case 'TreeStyleTab:levelMarginModified':
|
||||
if (this.levelMargin > -1) {
|
||||
case 'TreeStyleTab:indentModified':
|
||||
if (this.indent > -1) {
|
||||
this.updateAllTabsIndent();
|
||||
}
|
||||
break;
|
||||
@ -1376,6 +1394,7 @@ TreeStyleTabBrowser.prototype = {
|
||||
var b = this.mTabBrowser;
|
||||
|
||||
this.stopTabIndentAnimation(tab);
|
||||
this.stopTabCollapseAnimation(tab);
|
||||
this.destroyTab(tab);
|
||||
|
||||
var closeParentBehavior = this.getTreePref('closeParentBehavior');
|
||||
@ -2728,13 +2747,13 @@ TreeStyleTabBrowser.prototype = {
|
||||
|
||||
var b = this.mTabBrowser;
|
||||
if (!aProp) {
|
||||
aProp = this.getTreePref('enableSubtreeIndent') ? this.levelMarginProp : null ;
|
||||
aProp = this.getTreePref('enableSubtreeIndent') ? this.indentProp : null ;
|
||||
}
|
||||
var margin = this.levelMargin < 0 ? this.baseLebelMargin : this.levelMargin ;
|
||||
var margin = this.indent < 0 ? this.baseIndent : this.indent ;
|
||||
var indent = margin * aLevel;
|
||||
|
||||
var multirow = this.isMultiRow();
|
||||
var topBottom = this.levelMarginProp.match(/top|bottom/);
|
||||
var topBottom = this.indentProp.match(/top|bottom/);
|
||||
var innerBoxes,
|
||||
j,
|
||||
colors,
|
||||
@ -2772,6 +2791,7 @@ TreeStyleTabBrowser.prototype = {
|
||||
{
|
||||
this.stopTabIndentAnimation(aTab);
|
||||
|
||||
var regexp = this.indentRulesRegExp;
|
||||
if (
|
||||
!this.animationEnabled ||
|
||||
!aProp ||
|
||||
@ -2780,7 +2800,7 @@ TreeStyleTabBrowser.prototype = {
|
||||
aTab.setAttribute(
|
||||
'style',
|
||||
aTab.getAttribute('style')
|
||||
.replace(this.kMARGIN_RULES_PATTERN, '')+';'+
|
||||
.replace(regexp, '')+';'+
|
||||
(aProp ? aProp+':'+aIndent+'px !important;' : '' )
|
||||
);
|
||||
return;
|
||||
@ -2788,7 +2808,7 @@ TreeStyleTabBrowser.prototype = {
|
||||
|
||||
var startIndent = this.getPropertyPixelValue(aTab, aProp);
|
||||
var delta = aIndent - startIndent;
|
||||
var delay = 200;
|
||||
var delay = this.indentDelay;
|
||||
var startTime = Date.now();
|
||||
aTab.__treestyletab__updateTabIndentTimer = window.setInterval(function(aSelf) {
|
||||
var power = Math.min(1, (Date.now() - startTime) / delay);
|
||||
@ -2798,7 +2818,7 @@ TreeStyleTabBrowser.prototype = {
|
||||
aTab.setAttribute(
|
||||
'style',
|
||||
aTab.getAttribute('style')
|
||||
.replace(aSelf.kMARGIN_RULES_PATTERN, '')+';'+
|
||||
.replace(regexp, '')+';'+
|
||||
aProp+':'+indent+'px !important;'
|
||||
);
|
||||
|
||||
@ -2811,15 +2831,15 @@ TreeStyleTabBrowser.prototype = {
|
||||
window.clearInterval(aTab.__treestyletab__updateTabIndentTimer);
|
||||
aTab.__treestyletab__updateTabIndentTimer = null;
|
||||
},
|
||||
kMARGIN_RULES_PATTERN : /margin(-[^:]+):[^;]+;?/g,
|
||||
|
||||
inheritTabIndent : function(aNewTab, aExistingTab)
|
||||
{
|
||||
var margins = (aExistingTab.getAttribute('style') || '').match(this.kMARGIN_RULES_PATTERN);
|
||||
var regexp = this.indentRulesRegExp;
|
||||
var indents = (aExistingTab.getAttribute('style') || '').match(regexp) || [];
|
||||
aNewTab.setAttribute(
|
||||
'style',
|
||||
aNewTab.getAttribute('style')
|
||||
.replace(this.kMARGIN_RULES_PATTERN, '')+';'+margins.join(';')
|
||||
.replace(regexp, '')+';'+indents.join(';')
|
||||
);
|
||||
},
|
||||
|
||||
@ -2854,24 +2874,24 @@ TreeStyleTabBrowser.prototype = {
|
||||
var nest = tabs[tabs.length-1].getAttribute(this.kNEST);
|
||||
if (!nest) return;
|
||||
|
||||
var oldMargin = this.levelMargin;
|
||||
var indent = (oldMargin < 0 ? this.baseLebelMargin : oldMargin ) * nest;
|
||||
var oldIndent = this.indent;
|
||||
var indent = (oldIndent < 0 ? this.baseIndent : oldIndent ) * nest;
|
||||
var maxIndent = (
|
||||
this.getFirstTab(b).boxObject[this.invertedSizeProp] ||
|
||||
b.mTabContainer.boxObject[this.invertedSizeProp]
|
||||
) * 0.33;
|
||||
|
||||
var marginUnit = Math.max(Math.floor(maxIndent / nest), 1);
|
||||
var indentUnit = Math.max(Math.floor(maxIndent / nest), 1);
|
||||
if (indent > maxIndent) {
|
||||
this.levelMargin = marginUnit;
|
||||
this.indent = indentUnit;
|
||||
}
|
||||
else {
|
||||
this.levelMargin = -1;
|
||||
if ((this.baseLebelMargin * nest) > maxIndent)
|
||||
this.levelMargin = marginUnit;
|
||||
this.indent = -1;
|
||||
if ((this.baseIndent * nest) > maxIndent)
|
||||
this.indent = indentUnit;
|
||||
}
|
||||
|
||||
if (oldMargin != this.levelMargin) {
|
||||
if (oldIndent != this.indent) {
|
||||
this.updateAllTabsIndent();
|
||||
}
|
||||
},
|
||||
@ -2983,6 +3003,7 @@ TreeStyleTabBrowser.prototype = {
|
||||
if (!aTab || !this.getParentTab(aTab)) return;
|
||||
|
||||
this.setTabValue(aTab, this.kCOLLAPSED, aCollapse);
|
||||
this.updateTabCollapsed(aTab, aCollapse);
|
||||
|
||||
var event = document.createEvent('Events');
|
||||
event.initEvent('TreeStyleTabCollapsedStateChange', true, true);
|
||||
@ -3010,6 +3031,85 @@ TreeStyleTabBrowser.prototype = {
|
||||
this.collapseExpandTab(tabs[i], aCollapse);
|
||||
}
|
||||
},
|
||||
updateTabCollapsed : function(aTab, aCollapsed)
|
||||
{
|
||||
this.stopTabCollapseAnimation(aTab);
|
||||
|
||||
var regexp = this.collapseRulesRegExp;
|
||||
if (!this.isVertical || !this.animationEnabled) {
|
||||
aTab.setAttribute(
|
||||
'style',
|
||||
aTab.getAttribute('style')
|
||||
.replace(regexp, '')
|
||||
.replace(this.kOPACITY_RULE_REGEXP, '')
|
||||
);
|
||||
aTab.removeAttribute(this.kCOLLAPSING);
|
||||
if (aCollapsed)
|
||||
aTab.setAttribute(this.kCOLLAPSED_DONE, true);
|
||||
else
|
||||
aTab.removeAttribute(this.kCOLLAPSED_DONE);
|
||||
return;
|
||||
}
|
||||
|
||||
var height = this.getFirstTab(this.mTabBrowser).boxObject.height;
|
||||
var startMargin = aCollapsed ? 0 : height ;
|
||||
var endMargin = aCollapsed ? height : 0 ;
|
||||
var deltaMargin = endMargin - startMargin;
|
||||
var startOpacity = aCollapsed ? 1 : 0 ;
|
||||
var endOpacity = aCollapsed ? 0 : 1 ;
|
||||
var deltaOpacity = endOpacity - startOpacity;
|
||||
var delay = this.collapseDelay;
|
||||
var startTime = Date.now();
|
||||
var collapseProp = this.collapseProp;
|
||||
|
||||
aTab.setAttribute(this.kCOLLAPSING, true);
|
||||
aTab.setAttribute(
|
||||
'style',
|
||||
aTab.getAttribute('style')
|
||||
.replace(regexp, '')+';'+
|
||||
collapseProp+': -'+startMargin+'px !important;'+
|
||||
'opacity: '+startOpacity+' !important;'
|
||||
);
|
||||
if (!aCollapsed) aTab.removeAttribute(this.kCOLLAPSED_DONE);
|
||||
|
||||
aTab.__treestyletab__updateTabCollapsedTimer = window.setInterval(function(aSelf) {
|
||||
var power = Math.min(1, (Date.now() - startTime) / delay);
|
||||
var powerForStyle = Math.sin(power * 90 * Math.PI / 180);
|
||||
var margin = (power == 1) ?
|
||||
endMargin :
|
||||
startMargin + (deltaMargin * powerForStyle);
|
||||
var opacity = (power == 1) ?
|
||||
endOpacity :
|
||||
startOpacity + (deltaOpacity * powerForStyle);
|
||||
aTab.setAttribute(
|
||||
'style',
|
||||
aTab.getAttribute('style')
|
||||
.replace(regexp, '')+';'+
|
||||
collapseProp+': -'+margin+'px !important;'+
|
||||
'opacity: '+opacity+' !important;'
|
||||
);
|
||||
|
||||
if (power == 1) {
|
||||
aSelf.stopTabCollapseAnimation(aTab);
|
||||
aTab.removeAttribute(aSelf.kCOLLAPSING);
|
||||
aTab.setAttribute(
|
||||
'style',
|
||||
aTab.getAttribute('style')
|
||||
.replace(regexp, '')
|
||||
.replace(aSelf.kOPACITY_RULE_REGEXP, '')
|
||||
);
|
||||
if (aCollapsed)
|
||||
aTab.setAttribute(aSelf.kCOLLAPSED_DONE, true);
|
||||
}
|
||||
}, 10, this);
|
||||
},
|
||||
kOPACITY_RULE_REGEXP : /opacity\s*:[^;]+;?/,
|
||||
stopTabCollapseAnimation : function(aTab)
|
||||
{
|
||||
if (!aTab.__treestyletab__updateTabCollapsedTimer) return;
|
||||
window.clearInterval(aTab.__treestyletab__updateTabCollapsedTimer);
|
||||
aTab.__treestyletab__updateTabCollapsedTimer = null;
|
||||
},
|
||||
|
||||
collapseExpandTreesIntelligentlyFor : function(aTab)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user