なめらかスクロールを実装

git-svn-id: http://www.cozmixng.org/repos/piro/treestyletab/trunk@1251 599a83e7-65a4-db11-8015-0010dcdd6dc2
This commit is contained in:
piro 2007-10-20 16:47:08 +00:00
parent 0555a9c94d
commit 81e9155879
3 changed files with 188 additions and 4 deletions

View File

@ -33,11 +33,20 @@ tabbrowser[treestyletab-vertical="true"] > tabbox {
-moz-box-orient: horizontal !important;
}
tabbrowser[treestyletab-vertical="true"] .tabbrowser-strip {
tabbrowser[treestyletab-vertical="true"] .tabbrowser-arrowscrollbox > scrollbox {
overflow-x: hidden;
overflow-y: auto;
}
tabbrowser[treestyletab-vertical="true"] .tabs-stack > * + * > hbox {
-moz-box-flex: 1 !important;
}
/*
tabbrowser[treestyletab-vertical="true"] .tabbrowser-arrowscrollbox > scrollbox > .scrollbox-innerbox {
-moz-box-flex: 0 !important;
}
*/
tabbrowser[treestyletab-tabbar-position="right"] .tabbrowser-tab .tab-image-middle {

View File

@ -84,7 +84,7 @@ var TreeStyleTabService = {
_ObserverService : null,
/* Utilities */
isEventFiredOnTabIcon : function(aEvent)
{
var tab = this.getTabFromEvent(aEvent);
@ -204,6 +204,17 @@ var TreeStyleTabService = {
return (box.getAttribute('orient') || window.getComputedStyle(box, '').getPropertyValue('-moz-box-orient')) == 'vertical';
},
isTabVisible : function(aTab)
{
if (!aTab) return false;
var tabBox = aTab.boxObject;
var barBox = this.getTabBrowserFromChildren(aTab).mTabContainer.mTabstrip.boxObject;
return (tabBox.screenX >= barBox.screenX &&
tabBox.screenX + tabBox.width <= barBox.screenX + barBox.width &&
tabBox.screenY >= barBox.screenY &&
tabBox.screenY + tabBox.height <= barBox.screenY + barBox.height);
},
cleanUpTabsArray : function(aTabs)
{
var b = this.getTabBrowserFromChildren(aTabs[0]);
@ -358,6 +369,19 @@ var TreeStyleTabService = {
)
);
eval('aTabBrowser.mTabContainer._handleTabSelect = '+
aTabBrowser.mTabContainer._handleTabSelect.toSource().replace(
/\{/,
<><![CDATA[
{
if (!TreeStyleTabService.isTabVisible(this.selectedItem)) {
TreeStyleTabService.scrollToTab(this.selectedItem);
return;
}
]]></>
)
);
eval('aTabBrowser.mTabContainer._notifyBackgroundTab = '+
aTabBrowser.mTabContainer._notifyBackgroundTab.toSource().replace(
/\.screenX/g, '[TreeStyleTabService.positionProp]'
@ -733,7 +757,7 @@ catch(e) {
},
/* Event Handling */
handleEvent : function(aEvent)
{
switch (aEvent.type)
@ -1019,7 +1043,7 @@ catch(e) {
var b = this.getTabBrowserFromChildren(aEvent.originalTarget);
this.setPref('extensions.treestyletab.tabbar.width', b.mStrip.boxObject.width);
},
/* Tab Utilities */
getTabValue : function(aTab, aKey)
@ -1389,6 +1413,8 @@ catch(e) {
ref.parentNode.insertBefore(splitter, ref);
}
var scrollInnerBox = document.getAnonymousNodes(aTabBrowser.mTabContainer.mTabstrip._scrollbox)[0];
if (pos & this.kTABBAR_VERTICAL) {
this.positionProp = 'screenY';
this.sizeProp = 'height';
@ -1396,6 +1422,7 @@ catch(e) {
aTabBrowser.mTabBox.orient = 'horizontal';
aTabBrowser.mTabContainer.orient = aTabBrowser.mTabContainer.mTabstrip.orient = 'vertical';
scrollInnerBox.removeAttribute('flex');
aTabBrowser.mPanelContainer.removeAttribute('width');
aTabBrowser.mStrip.setAttribute('width', this.getPref('extensions.treestyletab.tabbar.width'));
@ -1427,6 +1454,7 @@ catch(e) {
aTabBrowser.mTabBox.orient = 'vertical';
aTabBrowser.mTabContainer.orient = aTabBrowser.mTabContainer.mTabstrip.orient = 'horizontal';
scrollInnerBox.setAttribute('flex', 1);
aTabBrowser.mStrip.removeAttribute('width');
aTabBrowser.mPanelContainer.removeAttribute('width');
@ -1733,6 +1761,9 @@ catch(e) {
this.collapseExpandTab(tabs[i], aCollapse);
}
if (!aCollapse)
this.scrollToTabSubTree(aTab);
b.__treestyletab__doingCollapseExpand = false;
},
@ -1802,6 +1833,148 @@ catch(e) {
this.collapseExpandTabSubTree(aTab, false);
},
/* scroll */
scrollTo : function(aTabBrowser, aEndX, aEndY)
{
if (this.getPref('extensions.treestyletab.tabbar.scroll.smooth'))
this.smoothScrollTo(aTabBrowser, aEndX, aEndY);
else
this.getTabBrowserFromChildren(aTabBrowser).mTabstrip.scrollBoxObject.scrollTo(aEndX, aEndY);
},
smoothScrollTo : function(aTabBrowser, aEndX, aEndY)
{
var b = this.getTabBrowserFromChildren(aTabBrowser);
if (b.__treestyletab__smoothScrollTimer) {
window.clearInterval(b.__treestyletab__smoothScrollTimer);
b.__treestyletab__smoothScrollTimer = null;
}
var scrollBoxObject = b.mTabContainer.mTabstrip.scrollBoxObject;
var x = {}, y = {};
scrollBoxObject.getPosition(x, y);
b.__treestyletab__smoothScrollTimer = window.setInterval(
this.smoothScrollToCallback,
10,
this,
b,
x.value,
y.value,
aEndX,
aEndY,
Date.now(),
this.getPref('extensions.treestyletab.tabbar.scroll.timeout')
);
},
smoothScrollToCallback : function(aSelf, aTabBrowser, aStartX, aStartY, aEndX, aEndY, aStartTime, aTimeout)
{
var newX = aStartX + parseInt(
(aEndX - aStartX) * ((Date.now() - aStartTime) / aTimeout)
);
var newY = aStartY + parseInt(
(aEndY - aStartY) * ((Date.now() - aStartTime) / aTimeout)
);
var scrollBoxObject = aTabBrowser.mTabContainer.mTabstrip.scrollBoxObject;
var x = {}, y = {};
scrollBoxObject.getPosition(x, y);
var w = {}, h = {};
scrollBoxObject.getScrolledSize(w, h);
var maxX = Math.max(0, w.value - scrollBoxObject.width);
var maxY = Math.max(0, h.value - scrollBoxObject.height);
if (
(
aEndX - aStartX > 0 ?
x.value >= Math.min(aEndX, maxX) :
x.value <= Math.min(aEndX, maxX)
) &&
(
aEndY - aStartY > 0 ?
y.value >= Math.min(aEndY, maxY) :
y.value <= Math.min(aEndY, maxY)
)
) {
if (aTabBrowser.__treestyletab__smoothScrollTimer) {
window.clearInterval(aTabBrowser.__treestyletab__smoothScrollTimer);
aTabBrowser.__treestyletab__smoothScrollTimer = null;
}
return;
}
scrollBoxObject.scrollTo(newX, newY);
},
scrollToTab : function(aTab)
{
if (!aTab || this.isTabVisible(aTab)) return;
var b = this.getTabBrowserFromChildren(aTab);
var scrollBoxObject = b.mTabContainer.mTabstrip.scrollBoxObject;
var w = {}, h = {};
scrollBoxObject.getScrolledSize(w, h);
var targetTabBox = aTab.boxObject;
var baseTabBox = aTab.parentNode.firstChild.boxObject;
var targetX = (aTab.boxObject.screenX < scrollBoxObject.screenX) ?
(targetTabBox.screenX - baseTabBox.screenX) - (targetTabBox.width * 0.5) :
(targetTabBox.screenX - baseTabBox.screenX) - scrollBoxObject.width + (targetTabBox.width * 1.5) ;
var targetY = (aTab.boxObject.screenY < scrollBoxObject.screenY) ?
(targetTabBox.screenY - baseTabBox.screenY) - (targetTabBox.height * 0.5) :
(targetTabBox.screenY - baseTabBox.screenY) - scrollBoxObject.height + (targetTabBox.height * 1.5) ;
this.scrollTo(b, targetX, targetY);
},
scrollToTabSubTree : function(aTab)
{
var b = this.getTabBrowserFromChildren(aTab);
var descendant = this.getDescendantTabs(aTab);
var lastVisible = aTab;
for (var i = descendant.length-1; i > -1; i--)
{
if (descendant[i].getAttribute(this.kCOLLAPSED) == 'true') continue;
lastVisible = descendant[i];
break;
}
var containerPosition = b.mStrip.boxObject[this.positionProp];
var containerSize = b.mStrip.boxObject[this.sizeProp];
var parentPosition = aTab.boxObject[this.positionProp];
var lastPosition = lastVisible.boxObject[this.positionProp];
var tabSize = lastVisible.boxObject[this.sizeProp];
if (this.isTabVisible(aTab) && this.isTabVisible(lastVisible)) {
return;
}
if (lastPosition - parentPosition + tabSize > containerSize - tabSize) { // out of screen
var endPos = parentPosition - b.mTabContainer.firstChild.boxObject[this.positionProp] - tabSize * 0.5;
var endX = this.isTabVertical(aTab) ? 0 : endPos ;
var endY = this.isTabVertical(aTab) ? endPos : 0 ;
this.scrollTo(b, endX, endY);
}
else if (!this.isTabVisible(aTab) && this.isTabVisible(lastVisible)) {
this.scrollToTab(aTab);
}
else if (this.isTabVisible(aTab) && !this.isTabVisible(lastVisible)) {
this.scrollToTab(lastVisible);
}
else if (parentPosition < containerPosition) {
this.scrollToTab(aTab);
}
else {
this.scrollToTab(lastVisible);
}
},
removeTabSubTree : function(aTabOrTabs)
{
var tabs = aTabOrTabs;

View File

@ -7,6 +7,8 @@ pref("extensions.treestyletab.focusMode", 1);
pref("extensions.treestyletab.levelMargin", 12);
pref("extensions.treestyletab.tabbar.width", 200);
pref("extensions.treestyletab.tabbar.position", "left");
pref("extensions.treestyletab.tabbar.scroll.smooth", true);
pref("extensions.treestyletab.tabbar.scroll.timeout", 250);
pref("browser.link.open_newwindow.restriction", 0);