Merge branch 'master' of github.com:piroor/treestyletab

Conflicts:
	history.en.md
	history.ja.md
This commit is contained in:
YUKI Hiroshi 2016-03-10 16:44:18 +09:00
commit 4adc6803f9
6 changed files with 82 additions and 114 deletions

View File

@ -346,6 +346,7 @@ pref("extensions.treestyletab.tooltip.fullTooltipDelay", 2000);
* If true, too many items are shown in multiple columns. * If true, too many items are shown in multiple columns.
*/ */
pref("extensions.treestyletab.tooltip.columnize", true); pref("extensions.treestyletab.tooltip.columnize", true);
pref("extensions.treestyletab.tooltip.columnize.width", "20em");
/** /**
* Visibility of extra menu items for the context menu on tabs, inserted by TST. * Visibility of extra menu items for the context menu on tabs, inserted by TST.
@ -662,6 +663,7 @@ pref("extensions.treestyletab.pinnedTab.faviconized", true);
* If true, too many items are shown in multiple columns in a dummy (group) tab. * If true, too many items are shown in multiple columns in a dummy (group) tab.
*/ */
pref("extensions.treestyletab.groupTab.columnize", true); pref("extensions.treestyletab.groupTab.columnize", true);
pref("extensions.treestyletab.groupTab.columnize.width", "20em");
/** /**
* Compatibility hack flags for other addons. They can be disabled by each * Compatibility hack flags for other addons. They can be disabled by each

View File

@ -2,6 +2,7 @@
- master/HEAD - master/HEAD
* Implement pseudo tree in `about:treestyletab-group` tabs and the rich tooltip without XHTML. (We don't need to mix XHTML and XUL to apply multi-column properties of CSS.) * Implement pseudo tree in `about:treestyletab-group` tabs and the rich tooltip without XHTML. (We don't need to mix XHTML and XUL to apply multi-column properties of CSS.)
* Activate multi-column layout only when it is required, at tooltip of tabs and dummy group tabs.
- 0.17.2016030402 - 0.17.2016030402
* Show rich tooltip with multiple columns even if there are only short title tabs. * Show rich tooltip with multiple columns even if there are only short title tabs.
* Avoid initialization error on newly opened group tabs. * Avoid initialization error on newly opened group tabs.

View File

@ -2,6 +2,7 @@
- master/HEAD - master/HEAD
* `about:treestyletab-group`のタブとツールチップにおけるツリーをXHTML無しで実装するようにしたCSSのマルチカラムレイアウトを使うためだけにXHTMLとXULを混在させる必要はない事が分かったため * `about:treestyletab-group`のタブとツールチップにおけるツリーをXHTML無しで実装するようにしたCSSのマルチカラムレイアウトを使うためだけにXHTMLとXULを混在させる必要はない事が分かったため
* タブのツールチップとダミーのグループ化用のタブにおいて、内容が1列に収まらないときだけマルチカラム表示するようにした
- 0.17.2016030402 - 0.17.2016030402
* 短いタイトルのタブしかない場合にツールチップの内容が段組表示されない問題を修正 * 短いタイトルのタブしかない場合にツールチップの内容が段組表示されない問題を修正
* 新しく開かれた空のグループ化用のタブの初期化処理が失敗するようになっていたのを修正 * 新しく開かれた空のグループ化用のタブの初期化処理が失敗するようになっていたのを修正

View File

@ -145,38 +145,6 @@ FullTooltipManager.prototype = inherit(TreeStyleTabBase, {
}; };
}, },
getTotalContentSize : function FTM_getTotalContentSize(aContainer)
{
var total = {
width : 0,
height : 0
};
var totalHeight = 0;
var orient = this.window.getComputedStyle(aContainer, null).getPropertyValue('orient');
var isVertical = orient == 'vertical';
Array.forEach(aContainer.childNodes, function(aNode) {
var width, height;
var box = aNode.boxObject;
if (box) {
width = box.width;
height = box.height;
}
else {
width = aNode.clientWidth;
height = aNode.clientHeight;
}
if (isVertical) {
total.width = Math.max(total.width, width);
total.height += height;
}
else {
total.width += width;
total.height = Math.max(total.height, height);
}
});
return total;
},
get currentTooltipMargins() get currentTooltipMargins()
{ {
var tooltip = this.tabFullTooltip; var tooltip = this.tabFullTooltip;
@ -560,11 +528,6 @@ FullTooltipManager.prototype = inherit(TreeStyleTabBase, {
root.appendChild(container); root.appendChild(container);
this.tabFullTooltip.appendChild(root); this.tabFullTooltip.appendChild(root);
log(' => tree size: ', {
width : tree.clientWidth,
height : tree.clientHeight
});
}, },
clear : function FTM_clear() clear : function FTM_clear()
@ -580,36 +543,61 @@ FullTooltipManager.prototype = inherit(TreeStyleTabBase, {
{ {
log('expandTooltip'); log('expandTooltip');
var tooltip = this.tabFullTooltip; var tooltip = this.tabFullTooltip;
var tree = this.tree;
{ {
let tree = this.tree;
let basePosition = this.windowBasePosition; let basePosition = this.windowBasePosition;
let tooltipBox = tooltip.boxObject; let tooltipBox = tooltip.boxObject;
log(' => current tooltip position: ', { log(' => initial dimension: ', {
screenX : tooltipBox.screenX, screenX : tooltipBox.screenX,
screenY : tooltipBox.screenY, screenY : tooltipBox.screenY,
x : tooltipBox.screenX - basePosition.x, x : tooltipBox.screenX - basePosition.x,
y : tooltipBox.screenY - basePosition.y, y : tooltipBox.screenY - basePosition.y,
width : tooltipBox.width, width : tooltipBox.width,
height : tooltipBox.height height : tooltipBox.height,
}); tree : {
}
log(' => tree: ', {
width : tree.clientWidth, width : tree.clientWidth,
height : tree.clientHeight height : tree.clientHeight
}
}); });
}
this.lastScreen = this.getCurrentScreen(tooltip.boxObject); this.lastScreen = this.getCurrentScreen(tooltip.boxObject);
if (utils.getTreePref('tooltip.columnize')) { this.determineTreeSize();
this.expandTooltipInternal();
},
determineTreeSize : function FTM_determineTreeSize()
{
var tree = this.tree;
var columnize = utils.getTreePref('tooltip.columnize');
if (columnize) {
PseudoTreeBuilder.columnizeTree(tree, { PseudoTreeBuilder.columnizeTree(tree, {
columnWidth : utils.getTreePref('tooltip.columnize.width'),
containerBox : {
width : this.lastScreen.allowedWidth, width : this.lastScreen.allowedWidth,
height : this.lastScreen.allowedHeight height : this.lastScreen.allowedHeight
},
calculateCount : true
}); });
this.window.setTimeout(this.expandTooltipInternal.bind(this), 0);
}
else {
this.expandTooltipInternal();
} }
var range = this.document.createRange();
range.selectNodeContents(tree);
if (tree.previousSibling)
range.setStartBefore(tree.previousSibling);
var rect = range.getBoundingClientRect();
range.detach();
var container = this.container;
var arrowScrollBox = container.parentNode;
var scrollButtonsMargin = (arrowScrollBox.boxObject.width - arrowScrollBox._scrollbox.boxObject.width);
scrollButtonsMargin *= 2; // enough width to deactivate scroll buttons.
var containerStyle = container.style;
containerStyle.width = (container.width = rect.width + scrollButtonsMargin)+'px';
containerStyle.height = (container.height = rect.height)+'px';
}, },
expandTooltipInternal : function FTM_expandTooltipInternal() expandTooltipInternal : function FTM_expandTooltipInternal()
{ {
@ -619,30 +607,24 @@ FullTooltipManager.prototype = inherit(TreeStyleTabBase, {
var tooltip = this.tabFullTooltip; var tooltip = this.tabFullTooltip;
tooltip.setAttribute('popup-shown', true); tooltip.setAttribute('popup-shown', true);
var requiredSize = this.getTotalContentSize(this.tree.parentNode);
{
// Let's maximize the container box enough to show the tree.
// If the tree is larger thant the tooltip,
// it becomes scrollable by arrowscrollbox.
let containerStyle = this.container.style;
containerStyle.width = requiredSize.width+'px';
containerStyle.height = requiredSize.height+'px';
}
var currentScreen = this.lastScreen || this.getCurrentScreen(box); var currentScreen = this.lastScreen || this.getCurrentScreen(box);
var box = tooltip.boxObject; var box = tooltip.boxObject;
var currentX = box.screenX - currentScreen.left; var currentX = box.screenX - currentScreen.left;
var currentY = box.screenY - currentScreen.top; var currentY = box.screenY - currentScreen.top;
var container = this.container;
var maxWidth = Math.min(container.width, currentScreen.allowedWidth);
var maxHeight = Math.min(container.height, currentScreen.allowedHeight);
var style = tooltip.style; var style = tooltip.style;
style.maxWidth = currentScreen.allowedWidth+'px'; style.maxWidth = maxWidth+'px';
style.maxHeight = currentScreen.allowedHeight+'px'; style.maxHeight = currentScreen.allowedHeight+'px';
style.minWidth = 0; style.minWidth = 0;
style.minHeight = 0; style.minHeight = 0;
var margins = this.currentTooltipMargins; var margins = this.currentTooltipMargins;
var maxX = currentScreen.width - Math.min(requiredSize.width, currentScreen.allowedWidth); var maxX = currentScreen.width - maxWidth;
var maxY = currentScreen.height - Math.min(requiredSize.height, currentScreen.allowedHeight); var maxY = currentScreen.height - maxHeight;
log(' => current dimension: ', { log(' => current dimension: ', {
margins : margins, margins : margins,
@ -650,7 +632,12 @@ FullTooltipManager.prototype = inherit(TreeStyleTabBase, {
y : currentY, y : currentY,
maxX : maxX, maxX : maxX,
maxY : maxY, maxY : maxY,
required : requiredSize container : {
width : container.width,
height : container.height
},
screen : currentScreen,
columnCount : this.tree.columnCount
}); });
if (currentX > maxX) if (currentX > maxX)

View File

@ -411,7 +411,9 @@ GroupTab.prototype = inherit(TreeStyleTabBase, {
return; return;
var container = this.document.getElementById('tree'); var container = this.document.getElementById('tree');
var tree = container.firstChild; var tree = container.firstChild;
PseudoTreeBuilder.columnizeTree(tree); PseudoTreeBuilder.columnizeTree(tree, {
columnWidth : utils.getTreePref('groupTab.columnize.width')
});
}, },
onTabAttached : function GT_onTabAttached(aEvent) onTabAttached : function GT_onTabAttached(aEvent)

View File

@ -146,45 +146,34 @@ var PseudoTreeBuilder = {
return container; return container;
}, },
columnizeTree : function TB_columnizeTree(aTree, aContainerBox) columnizeTree : function TB_columnizeTree(aTree, aOptions)
{ {
if (!aTree) if (!aTree)
return; return;
aContainerBox = aContainerBox || aTree.parentNode.boxObject; aOptions = aOptions || {};
aOptions.columnWidth = aOptions.columnWidth || '20em';
var style = aTree.style; var style = aTree.style;
var height = aTree.clientHeight * (aTree.columnCount || 1);
if (height > aContainerBox.height && style.columnWidth = style.MozColumnWidth = 'calc(' + aOptions.columnWidth + ')';
aContainerBox.height < aContainerBox.width) { {
let maxWidth = aContainerBox.width; let computedStyle = aTree.ownerDocument.defaultView.getComputedStyle(aTree, null)
aTree.columnWidth = Math.floor(maxWidth * 0.9 / 2.5); aTree.columnWidth = Number((computedStyle.MozColumnWidth || computedStyle.columnWidth).replace(/px/, ''));
let count = Math.ceil( }
(Math.max(aTree.clientWidth, maxWidth) * aTree.clientHeight) /
(aTree.columnWidth * aTree.clientHeight)
);
aTree.columnCount = style.columnCount = style.MozColumnCount = count;
style.columnWidth = style.MozColumnWidth = aTree.columnWidth+'px';
style.columnGap = style.MozColumnGap = '0'; style.columnGap = style.MozColumnGap = '0';
style.columnFill = style.MozColumnFill = 'auto'; style.columnFill = style.MozColumnFill = 'auto';
style.columnCount = style.MozColumnCount = 'auto';
aTree.ownerDocument.defaultView.setTimeout((function() { var containerBox = aOptions.containerBox || aTree.parentNode.boxObject;
let columnCount = this.getActualColumnCount(aTree); var maxWidth = containerBox.width;
aTree.columnCount = style.columnCount = if (aTree.columnWidth * 2 <= maxWidth ||
style.MozColumnCount = columnCount; aOptions.calculateCount) {
}).bind(this), 0);
}
else {
aTree.columnCount = 1;
style.columnCount = style.MozColumnCount =
style.columnWidth = style.MozColumnWidth =
style.columnGap = style.MozColumnGap =
style.columnFill = style.MozColumnFill;
}
if (aTree.columnCount > 1) {
style.height = style.maxHeight = style.height = style.maxHeight =
Math.floor(aContainerBox.height * 0.9) + 'px'; Math.floor(containerBox.height * 0.9) + 'px';
if (this.getActualColumnCount(aTree) == 1)
style.columnWidth = style.MozColumnWidth = '';
} }
else { else {
style.height = style.maxHeight = ''; style.height = style.maxHeight = '';
@ -192,24 +181,10 @@ var PseudoTreeBuilder = {
}, },
getActualColumnCount : function TB_getActualColumnCount(aTree) getActualColumnCount : function TB_getActualColumnCount(aTree)
{ {
var rows = aTree.querySelectorAll('*|*.' + this.kTREEROW); var range = aTree.ownerDocument.createRange();
if (rows.length <= 1) range.selectNodeContents(aTree);
return 0; var rect = range.getBoundingClientRect();
range.detach();
var firstRow = rows[0]; return Math.floor(rect.width / aTree.columnWidth);
if (rows[0].clientWidth === 0) // ignore hidden item!
firstRow = rows[1];
var lastRow = rows[rows.length - 1];
var firstWidth = firstRow.clientWidth;
var lastWidth = lastRow.clientWidth;
// We have to see XUL box object's x instead of HTML element's clientLeft
// to get actual position of elements in a multi-column box.
var firstX = firstRow.querySelector('label').boxObject.x;
var lastX = lastRow.querySelector('label').boxObject.x;
var totalWidth = lastX + lastWidth - firstX;
return Math.floor(totalWidth / firstWidth);
} }
}; };