タブのインデントや折り畳みをCSSOMで制御するようにした

git-svn-id: http://www.cozmixng.org/repos/piro/treestyletab/trunk@7074 599a83e7-65a4-db11-8015-0010dcdd6dc2
This commit is contained in:
piro 2010-08-13 17:14:46 +00:00
parent f525e948c4
commit 206b44f945
2 changed files with 66 additions and 110 deletions

View File

@ -23,26 +23,13 @@ TreeStyleTabBrowser.prototype = {
indent : -1, indent : -1,
indentProp : 'margin', indentProp : 'margin',
indentTarget : 'left', indentTarget : 'left',
indentCSSProp : 'margin-left',
collapseTarget : 'top', collapseTarget : 'top',
collapseCSSProp : 'margin-top',
positionProp : 'screenY', positionProp : 'screenY',
sizeProp : 'height', sizeProp : 'height',
invertedPositionProp : 'screenX', invertedPositionProp : 'screenX',
invertedSizeProp : 'width', 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 ;
},
get browser() get browser()
{ {
@ -1140,9 +1127,17 @@ TreeStyleTabBrowser.prototype = {
} }
} }
this.indentProp = this.getTreePref('indent.property'); var tabs = this.getTabsArray(b);
tabs.forEach(function(aTab) {
aTab.style.removeProperty(this.indentCSSProp);
aTab.style.removeProperty(this.collapseCSSProp);
}, this);
this.getTabsArray(b).forEach(function(aTab) { this.indentProp = this.getTreePref('indent.property');
this.indentCSSProp = this.indentProp+'-'+this.indentTarget;
this.collapseCSSProp = 'margin-'+this.collapseTarget;
tabs.forEach(function(aTab) {
this.updateTabCollapsed(aTab, aTab.getAttribute(this.kCOLLAPSED) == 'true', true); this.updateTabCollapsed(aTab, aTab.getAttribute(this.kCOLLAPSED) == 'true', true);
}, this); }, this);
@ -2645,7 +2640,7 @@ TreeStyleTabBrowser.prototype = {
dontUpdateIndent : true, dontUpdateIndent : true,
dontAnimate : restoringMultipleTabs dontAnimate : restoringMultipleTabs
}); });
this.updateTabsIndent([tab], undefined, undefined, restoringMultipleTabs); this.updateTabsIndent([tab], undefined, restoringMultipleTabs);
this.checkTabsIndentOverflow(); this.checkTabsIndentOverflow();
if (parent.getAttribute(this.kCHILDREN_RESTORING)) if (parent.getAttribute(this.kCHILDREN_RESTORING))
@ -2656,7 +2651,7 @@ TreeStyleTabBrowser.prototype = {
} }
} }
else if (children) { else if (children) {
this.updateTabsIndent(tabs, undefined, undefined, restoringMultipleTabs); this.updateTabsIndent(tabs, undefined, restoringMultipleTabs);
this.checkTabsIndentOverflow(); this.checkTabsIndentOverflow();
} }
@ -3716,7 +3711,7 @@ TreeStyleTabBrowser.prototype = {
aTab.removeAttribute(this.kCOLLAPSED); aTab.removeAttribute(this.kCOLLAPSED);
aTab.removeAttribute(this.kCOLLAPSED_DONE); aTab.removeAttribute(this.kCOLLAPSED_DONE);
aTab.removeAttribute(this.kNEST); aTab.removeAttribute(this.kNEST);
this.updateTabsIndent([aTab], undefined, undefined, true); this.updateTabsIndent([aTab], undefined, true);
}, },
resetAllTabs : function TSTBrowser_resetAllTabs(aPartChildren) resetAllTabs : function TSTBrowser_resetAllTabs(aPartChildren)
@ -3737,12 +3732,12 @@ TreeStyleTabBrowser.prototype = {
let orient = this.isVertical ? 'vertical' : 'horizontal' ; let orient = this.isVertical ? 'vertical' : 'horizontal' ;
if (this.getTreePref('allowSubtreeCollapseExpand.'+orient)) if (this.getTreePref('allowSubtreeCollapseExpand.'+orient))
this.setTabbrowserAttribute(this.kALLOW_COLLAPSE, true); this.setTabbrowserAttribute(this.kALLOW_COLLAPSE, true);
this.updateTabsIndent(this.rootTabs, undefined, undefined, true); this.updateTabsIndent(this.rootTabs, undefined, true);
} }
else { else {
this.removeTabbrowserAttribute(this.kALLOW_COLLAPSE); this.removeTabbrowserAttribute(this.kALLOW_COLLAPSE);
this.getTabsArray(this.browser).forEach(function(aTab) { this.getTabsArray(this.browser).forEach(function(aTab) {
this.updateTabIndent(aTab, 0, this.indentTarget, true); this.updateTabIndent(aTab, 0, true);
}, this); }, this);
} }
return aValue; return aValue;
@ -3869,7 +3864,7 @@ TreeStyleTabBrowser.prototype = {
} }
if (!aInfo.dontUpdateIndent) { if (!aInfo.dontUpdateIndent) {
this.updateTabsIndent([aChild], undefined, undefined, aInfo.dontAnimate); this.updateTabsIndent([aChild], undefined, aInfo.dontAnimate);
this.checkTabsIndentOverflow(); this.checkTabsIndentOverflow();
} }
@ -3917,7 +3912,7 @@ TreeStyleTabBrowser.prototype = {
this.updateTabsCount(parentTab); this.updateTabsCount(parentTab);
if (!aInfo.dontUpdateIndent) { if (!aInfo.dontUpdateIndent) {
this.updateTabsIndent([aChild], undefined, undefined, aInfo.dontAnimate); this.updateTabsIndent([aChild], undefined, aInfo.dontAnimate);
this.checkTabsIndentOverflow(); this.checkTabsIndentOverflow();
} }
@ -3947,7 +3942,7 @@ TreeStyleTabBrowser.prototype = {
}, this); }, this);
}, },
updateTabsIndent : function TSTBrowser_updateTabsIndent(aTabs, aLevel, aTarget, aJustNow) updateTabsIndent : function TSTBrowser_updateTabsIndent(aTabs, aLevel, aJustNow)
{ {
if (!aTabs || !aTabs.length || !this._treeViewEnabled) return; if (!aTabs || !aTabs.length || !this._treeViewEnabled) return;
@ -3962,10 +3957,6 @@ TreeStyleTabBrowser.prototype = {
} }
var b = this.mTabBrowser; var b = this.mTabBrowser;
if (!aTarget) {
let orient = this.isVertical ? 'vertical' : 'horizontal' ;
aTarget = this.getTreePref('enableSubtreeIndent.'+orient) ? this.indentTarget : null ;
}
var margin = this.indent < 0 ? this.baseIndent : this.indent ; var margin = this.indent < 0 ? this.baseIndent : this.indent ;
var indent = margin * aLevel; var indent = margin * aLevel;
@ -3977,9 +3968,9 @@ TreeStyleTabBrowser.prototype = {
Array.slice(aTabs).forEach(function(aTab) { Array.slice(aTabs).forEach(function(aTab) {
if (!aTab.parentNode) return; // ignore removed tabs if (!aTab.parentNode) return; // ignore removed tabs
this.updateTabIndent(aTab, indent, aTarget, aJustNow); this.updateTabIndent(aTab, indent, aJustNow);
aTab.setAttribute(this.kNEST, aLevel); aTab.setAttribute(this.kNEST, aLevel);
this.updateTabsIndent(this.getChildTabs(aTab), aLevel+1, aTarget, aJustNow); this.updateTabsIndent(this.getChildTabs(aTab), aLevel+1, aJustNow);
}, this); }, this);
}, },
updateTabsIndentWithDelay : function TSTBrowser_updateTabsIndentWithDelay(aTabs) updateTabsIndentWithDelay : function TSTBrowser_updateTabsIndentWithDelay(aTabs)
@ -4003,12 +3994,12 @@ TreeStyleTabBrowser.prototype = {
updateTabsIndentWithDelayTabs : [], updateTabsIndentWithDelayTabs : [],
updateTabsIndentWithDelayTimer : null, updateTabsIndentWithDelayTimer : null,
updateTabIndent : function TSTBrowser_updateTabIndent(aTab, aIndent, aTarget, aJustNow) updateTabIndent : function TSTBrowser_updateTabIndent(aTab, aIndent, aJustNow)
{ {
this.stopTabIndentAnimation(aTab); this.stopTabIndentAnimation(aTab);
if (this.isMultiRow()) { if (this.isMultiRow()) {
let colors = '-moz-border-'+aTarget+'-colors:'+(function() { let colors = '-moz-border-'+this.indentTarget+'-colors:'+(function() {
var retVal = []; var retVal = [];
for (var i = 1; i < aIndent; i++) for (var i = 1; i < aIndent; i++)
{ {
@ -4022,40 +4013,28 @@ TreeStyleTabBrowser.prototype = {
aBox.setAttribute( aBox.setAttribute(
'style', 'style',
aBox.getAttribute('style').replace(/(-moz-)?border-(top|bottom)(-[^:]*)?.*:[^;]+;?/g, '') + aBox.getAttribute('style').replace(/(-moz-)?border-(top|bottom)(-[^:]*)?.*:[^;]+;?/g, '') +
'; border-'+aTarget+': solid transparent '+aIndent+'px !important;'+colors '; border-'+this.indentTarget+': solid transparent '+aIndent+'px !important;'+colors
); );
}, this); }, this);
return; return;
} }
var regexp = this.indentRulesRegExp;
var property = this.indentProp+'-'+aTarget;
if ( if (
!this.animationEnabled || !this.animationEnabled ||
aJustNow || aJustNow ||
this.indentDuration < 1 || this.indentDuration < 1 ||
!aTarget ||
this.isCollapsed(aTab) this.isCollapsed(aTab)
) { ) {
aTab.setAttribute( aTab.style.setProperty(this.indentCSSProp, aIndent+'px', 'important');
'style',
aTab.getAttribute('style')
.replace(regexp, '')+';'+
(aTarget ? property+':'+aIndent+'px !important;' : '' )
);
return; return;
} }
var self = this;
var CSSTransitionEnabled = ('Transition' in aTab.style || 'MozTransition' in aTab.style); var CSSTransitionEnabled = ('Transition' in aTab.style || 'MozTransition' in aTab.style);
if (CSSTransitionEnabled) { if (CSSTransitionEnabled) {
aTab.__treestyletab__updateTabIndentTask = function(aTime, aBeginning, aChange, aDuration) { aTab.__treestyletab__updateTabIndentTask = function(aTime, aBeginning, aChange, aDuration) {
aTab.setAttribute( aTab.style.setProperty(self.indentCSSProp, aIndent+'px', 'important');
'style',
aTab.getAttribute('style')
.replace(regexp, '')+';'+
property+':'+aIndent+'px !important;'
);
return true; return true;
}; };
this.animationManager.addTask( this.animationManager.addTask(
@ -4065,10 +4044,9 @@ TreeStyleTabBrowser.prototype = {
return; return;
} }
var startIndent = this.getPropertyPixelValue(aTab, property); var startIndent = this.getPropertyPixelValue(aTab, this.indentCSSProp);
var delta = aIndent - startIndent; var delta = aIndent - startIndent;
var radian = 90 * Math.PI / 180; var radian = 90 * Math.PI / 180;
var self = this;
aTab.__treestyletab__updateTabIndentTask = function(aTime, aBeginning, aChange, aDuration) { aTab.__treestyletab__updateTabIndentTask = function(aTime, aBeginning, aChange, aDuration) {
var indent, finished; var indent, finished;
if (aTime >= aDuration) { if (aTime >= aDuration) {
@ -4080,11 +4058,7 @@ TreeStyleTabBrowser.prototype = {
indent = startIndent + (delta * Math.sin(aTime / aDuration * radian)); indent = startIndent + (delta * Math.sin(aTime / aDuration * radian));
finished = false; finished = false;
} }
aTab.setAttribute( aTab.style.setProperty(self.indentCSSProp, indent+'px', 'important');
'style',
aTab.getAttribute('style').replace(regexp, '')+';'+
property+':'+indent+'px !important;'
);
if (finished) { if (finished) {
startIndent = null; startIndent = null;
delta = null; delta = null;
@ -4108,13 +4082,11 @@ TreeStyleTabBrowser.prototype = {
inheritTabIndent : function TSTBrowser_inheritTabIndent(aNewTab, aExistingTab) inheritTabIndent : function TSTBrowser_inheritTabIndent(aNewTab, aExistingTab)
{ {
var regexp = this.indentRulesRegExp; var indent = this.getPropertyPixelValue(aExistingTab, this.indentCSSProp);
var indents = (aExistingTab.getAttribute('style') || '').match(regexp) || []; if (indent)
aNewTab.setAttribute( aNewTab.style.setProperty(this.indentCSSProp, indent+'px', 'important');
'style', else
aNewTab.getAttribute('style') aNewTab.style.removeProperty(this.indentCSSProp);
.replace(regexp, '')+';'+indents.join(';')
);
}, },
updateAllTabsIndent : function TSTBrowser_updateAllTabsIndent() updateAllTabsIndent : function TSTBrowser_updateAllTabsIndent()
@ -4323,8 +4295,7 @@ TreeStyleTabBrowser.prototype = {
var maxMargin; var maxMargin;
var offsetAttr; var offsetAttr;
var collapseProp = 'margin-'+this.collapseTarget; var collapseProp = 'margin-'+this.collapseTarget;
let (firstTab) { let (firstTab = this.getFirstNormalTab(this.mTabBrowser)) {
firstTab = this.getFirstNormalTab(this.mTabBrowser);
if (this.isVertical) { if (this.isVertical) {
maxMargin = firstTab.boxObject.height; maxMargin = firstTab.boxObject.height;
offsetAttr = this.kY_OFFSET; offsetAttr = this.kY_OFFSET;
@ -4365,31 +4336,25 @@ TreeStyleTabBrowser.prototype = {
else else
aTab.removeAttribute(this.kCOLLAPSED_DONE); aTab.removeAttribute(this.kCOLLAPSED_DONE);
aTab.setAttribute( if (CSSTransitionEnabled) {
'style', aTab.style.setProperty(this.collapseCSSProp, '-'+endMargin+'px', 'important');
aTab.getAttribute('style') if (endOpacity == 0)
.replace(this.collapseRulesRegExp, '') aTab.style.setProperty('opacity', endOpacity, 'important');
.replace(this.kOPACITY_RULE_REGEXP, '') + else
(CSSTransitionEnabled ? aTab.style.removeProperty('opacity');
( }
collapseProp+': -'+endMargin+'px !important;'+ else {
(endOpacity == 0 ? 'opacity: '+endOpacity+' !important;' : '' ) aTab.style.removeProperty(this.collapseCSSProp);
) : aTab.style.removeProperty('opacity');
'' ) }
);
return; return;
} }
var deltaMargin = endMargin - startMargin; var deltaMargin = endMargin - startMargin;
var deltaOpacity = endOpacity - startOpacity; var deltaOpacity = endOpacity - startOpacity;
aTab.setAttribute( aTab.style.setProperty(this.collapseCSSProp, '-'+startMargin+'px', 'important');
'style', aTab.style.setProperty('opacity', startOpacity, 'important');
aTab.getAttribute('style')
.replace(this.collapseRulesRegExp, '')+';'+
collapseProp+': -'+startMargin+'px !important;'+
'opacity: '+startOpacity+' !important;'
);
if (!aCollapsed) { if (!aCollapsed) {
aTab.setAttribute(offsetAttr, maxMargin); aTab.setAttribute(offsetAttr, maxMargin);
@ -4401,13 +4366,8 @@ TreeStyleTabBrowser.prototype = {
var firstFrame = true; var firstFrame = true;
aTab.__treestyletab__updateTabCollapsedTask = function(aTime, aBeginning, aChange, aDuration) { aTab.__treestyletab__updateTabCollapsedTask = function(aTime, aBeginning, aChange, aDuration) {
if (firstFrame && CSSTransitionEnabled) { if (firstFrame && CSSTransitionEnabled) {
aTab.setAttribute( aTab.style.setProperty(self.collapseCSSProp, '-'+endMargin+'px', 'important');
'style', aTab.style.setProperty('opacity', endOpacity, 'important');
aTab.getAttribute('style')
.replace(this.collapseRulesRegExp, '')+';'+
collapseProp+': -'+endMargin+'px !important;'+
'opacity: '+endOpacity+' !important;'
);
} }
firstFrame = false; firstFrame = false;
// If this is the last tab, negative scroll happens. // If this is the last tab, negative scroll happens.
@ -4426,14 +4386,9 @@ TreeStyleTabBrowser.prototype = {
if (aTime >= aDuration || stopAnimation) { if (aTime >= aDuration || stopAnimation) {
delete aTab.__treestyletab__updateTabCollapsedTask; delete aTab.__treestyletab__updateTabCollapsedTask;
if (aCollapsed) aTab.setAttribute(self.kCOLLAPSED_DONE, true); if (aCollapsed) aTab.setAttribute(self.kCOLLAPSED_DONE, true);
if (!CSSTransitionEnabled) { if (!CSSTransitionEnabled)
aTab.setAttribute( aTab.style.removeProperty(self.collapseCSSProp);
'style', aTab.style.removeProperty('opacity');
aTab.getAttribute('style')
.replace(self.collapseRulesRegExp, '')
.replace(self.kOPACITY_RULE_REGEXP, '')
);
}
aTab.removeAttribute(offsetAttr); aTab.removeAttribute(offsetAttr);
maxMargin = null; maxMargin = null;
@ -4456,13 +4411,8 @@ TreeStyleTabBrowser.prototype = {
let power = Math.sin(aTime / aDuration * radian); let power = Math.sin(aTime / aDuration * radian);
let margin = startMargin + (deltaMargin * power); let margin = startMargin + (deltaMargin * power);
let opacity = startOpacity + (deltaOpacity * power); let opacity = startOpacity + (deltaOpacity * power);
aTab.setAttribute( aTab.style.setProperty(self.collapseCSSProp, '-'+margin+'px', 'important');
'style', aTab.style.setProperty('opacity', opacity, 'important');
aTab.getAttribute('style')
.replace(self.collapseRulesRegExp, '')+';'+
collapseProp+': -'+margin+'px !important;'+
'opacity: '+opacity+' !important;'
);
} }
aTab.setAttribute(offsetAttr, maxMargin); aTab.setAttribute(offsetAttr, maxMargin);
return false; return false;

View File

@ -1018,7 +1018,11 @@ var TreeStyleTabUtils = {
getFirstNormalTab : function TSTUtils_getFirstNormalTab(aTabBrowserChild) getFirstNormalTab : function TSTUtils_getFirstNormalTab(aTabBrowserChild)
{ {
var b = this.getTabBrowserFromChild(aTabBrowserChild); var b = this.getTabBrowserFromChild(aTabBrowserChild);
return b.mTabContainer.childNodes[b._numPinnedTabs || 0]; return this.evaluateXPath(
'descendant::xul:tab[not(@pinned="true") and not(@hidden="true")]',
b.mTabContainer,
Ci.nsIDOMXPathResult.FIRST_ORDERED_NODE_TYPE
).singleNodeValue;
}, },
getLastTab : function TSTUtils_getLastTab(aTabBrowserChild) getLastTab : function TSTUtils_getLastTab(aTabBrowserChild)
@ -1095,7 +1099,7 @@ var TreeStyleTabUtils = {
return this.getTabs(b); return this.getTabs(b);
var XPathResult = this.evaluateXPath( var XPathResult = this.evaluateXPath(
'child::xul:tab[not(@'+this.kCOLLAPSED+'="true")]', 'child::xul:tab[not(@'+this.kCOLLAPSED+'="true") and not(@hidden="true")]',
b.mTabContainer b.mTabContainer
); );
return XPathResult; return XPathResult;
@ -1694,7 +1698,8 @@ var TreeStyleTabUtils = {
'' ; '' ;
return this.evaluateXPath( return this.evaluateXPath(
'sum((self::* | preceding-sibling::xul:tab'+extraCondition+')/attribute::'+this.kX_OFFSET+')', 'sum((self::* | preceding-sibling::xul:tab[not(@hidden="true")]'+extraCondition+')'+
'/attribute::'+this.kX_OFFSET+')',
aTab, aTab,
Ci.nsIDOMXPathResult.NUMBER_TYPE Ci.nsIDOMXPathResult.NUMBER_TYPE
).numberValue; ).numberValue;
@ -1706,7 +1711,8 @@ var TreeStyleTabUtils = {
''; '';
return this.evaluateXPath( return this.evaluateXPath(
'sum((self::* | preceding-sibling::xul:tab'+extraCondition+')/attribute::'+this.kY_OFFSET+')', 'sum((self::* | preceding-sibling::xul:tab[not(@hidden="true")]'+extraCondition+')'+
'/attribute::'+this.kY_OFFSET+')',
aTab, aTab,
Ci.nsIDOMXPathResult.NUMBER_TYPE Ci.nsIDOMXPathResult.NUMBER_TYPE
).numberValue; ).numberValue;