Reimplement splitview resize for treelayout splitview.

This commit is contained in:
brahim 2024-10-03 10:00:37 +02:00
parent a102dd4c37
commit 28baa2f9d4

View file

@ -6,6 +6,7 @@ class SplitNode {
this.splitters = []; this.splitters = [];
this.widthInParent = widthInParent; this.widthInParent = widthInParent;
this.heightInParent = heightInParent; this.heightInParent = heightInParent;
this.positionToRoot = null; // position relative to root node
} }
} }
class SplitLeafNode { class SplitLeafNode {
@ -33,6 +34,13 @@ var gZenViewSplitter = new class {
false false
); );
XPCOMUtils.defineLazyPreferenceGetter(
this,
'minResizeWidth',
'zen.splitView.min-resize-width',
7
);
ChromeUtils.defineLazyGetter( ChromeUtils.defineLazyGetter(
this, this,
'splitterBox', 'splitterBox',
@ -338,10 +346,6 @@ var gZenViewSplitter = new class {
return this._tabBrowserPanel; return this._tabBrowserPanel;
} }
get minResizeWidth() {
return Services.prefs.getIntPref('zen.splitView.min-resize-width');
}
get splitViewActive() { get splitViewActive() {
return this.currentView >= 0; return this.currentView >= 0;
} }
@ -541,9 +545,12 @@ var gZenViewSplitter = new class {
* Apply grid layout to tabBrowserPanel * Apply grid layout to tabBrowserPanel
* *
* @param {SplitNode} splitNode SplitNode * @param {SplitNode} splitNode SplitNode
* @param {{top, bottom, left, right}} nodeRootPosition position of node relative to root of split
*/ */
applyGridLayout(splitNode, nodeRootPosition = {top: 0, bottom: 0, left: 0, right: 0}) { applyGridLayout(splitNode) {
if (!splitNode.positionToRoot) {
splitNode.positionToRoot = {top: 0, bottom: 0, left: 0, right: 0};
}
const nodeRootPosition = splitNode.positionToRoot;
if (!splitNode.children) { if (!splitNode.children) {
const browserContainer = document.getElementById(splitNode.id); const browserContainer = document.getElementById(splitNode.id);
browserContainer.style.inset = `${nodeRootPosition.top}% ${nodeRootPosition.right}% ${nodeRootPosition.bottom}% ${nodeRootPosition.left}%`; browserContainer.style.inset = `${nodeRootPosition.top}% ${nodeRootPosition.right}% ${nodeRootPosition.bottom}% ${nodeRootPosition.left}%`;
@ -559,7 +566,8 @@ var gZenViewSplitter = new class {
let topOffset = nodeRootPosition.top; let topOffset = nodeRootPosition.top;
splitNode.children.forEach((childNode, i) => { splitNode.children.forEach((childNode, i) => {
const childRootPosition = {top: topOffset, right: 100 - (leftOffset + childNode.widthInParent * rootToNodeWidthRatio), bottom: 100 - (topOffset + childNode.heightInParent * rootToNodeHeightRatio), left: leftOffset}; const childRootPosition = {top: topOffset, right: 100 - (leftOffset + childNode.widthInParent * rootToNodeWidthRatio), bottom: 100 - (topOffset + childNode.heightInParent * rootToNodeHeightRatio), left: leftOffset};
this.applyGridLayout(childNode, childRootPosition); childNode.positionToRoot = childRootPosition;
this.applyGridLayout(childNode);
if (splitNode.direction === 'column') { if (splitNode.direction === 'column') {
topOffset += childNode.heightInParent * rootToNodeHeightRatio; topOffset += childNode.heightInParent * rootToNodeHeightRatio;
@ -572,7 +580,7 @@ var gZenViewSplitter = new class {
if (!isLastNode) { if (!isLastNode) {
let splitter = currentSplitters?.[i]; let splitter = currentSplitters?.[i];
if (!splitter) { if (!splitter) {
splitter = this.createSplitter(splitNode.direction === 'column' ? 'horizontal' : 'vertical', childNode, i); splitter = this.createSplitter(splitNode.direction === 'column' ? 'horizontal' : 'vertical', splitNode, i);
} }
if (splitNode.direction === 'column') { if (splitNode.direction === 'column') {
splitter.style.inset = `${100 - childRootPosition.bottom}% ${childRootPosition.right}% 0% ${childRootPosition.left}%`; splitter.style.inset = `${100 - childRootPosition.bottom}% ${childRootPosition.right}% 0% ${childRootPosition.left}%`;
@ -610,9 +618,10 @@ var gZenViewSplitter = new class {
} }
removeSplitters() { removeSplitters() {
[...gZenViewSplitter.tabBrowserPanel.children] Array.from(this._splitNodeToSplitters.values()).forEach(s => {
.filter(e => e.classList.contains('zen-split-view-splitter')) s.remove;
.forEach(s => s.remove()); });
this._splitNodeToSplitters.clear();
} }
/** /**
@ -649,36 +658,38 @@ var gZenViewSplitter = new class {
}; };
handleSplitterMouseDown = (event) => { handleSplitterMouseDown = (event) => {
const splitData = this._data[this.currentView];
const isVertical = event.target.getAttribute('orient') === 'vertical'; const isVertical = event.target.getAttribute('orient') === 'vertical';
const dimension = isVertical ? 'widths' : 'heights'; const dimension = isVertical ? 'width' : 'height';
const dimensionInParent = dimension + 'InParent';
const clientAxis = isVertical ? 'screenX' : 'screenY'; const clientAxis = isVertical ? 'screenX' : 'screenY';
const gridIdx = event.target.getAttribute('gridIdx'); const gridIdx = parseInt(event.target.getAttribute('gridIdx'));
let prevPosition = event[clientAxis]; const startPosition = event[clientAxis];
const splitNode = event.target.parentSplitNode;
let rootToNodeSize;
if (isVertical) rootToNodeSize = 100 / (100 - splitNode.positionToRoot.right - splitNode.positionToRoot.left);
else rootToNodeSize = 100 / (100 - splitNode.positionToRoot.bottom - splitNode.positionToRoot.top);
const originalSizes = splitNode.children.map(c => c[dimensionInParent]);
const dragFunc = (dEvent) => { const dragFunc = (dEvent) => {
requestAnimationFrame(() => { requestAnimationFrame(() => {
const movementX = dEvent[clientAxis] - prevPosition;
let percentageChange = (movementX / this.tabBrowserPanel.getBoundingClientRect()[isVertical ? 'width' : 'height']) * 100;
const currentSize = splitData[dimension][gridIdx - 1]; const movement = dEvent[clientAxis] - startPosition;
const neighborSize = splitData[dimension][gridIdx]; let movementPercent = (movement / this.tabBrowserPanel.getBoundingClientRect()[dimension] * rootToNodeSize) * 100;
if (currentSize < this.minResizeWidth && neighborSize < this.minResizeWidth) {
return; let reducingMovement = Math.max(movementPercent, -movementPercent);
for (let i = gridIdx + (movementPercent < 0 ? 0 : 1); 0 <= i && i < originalSizes.length; i += movementPercent < 0 ? -1 : 1) {
const current = originalSizes[i];
const newSize = Math.max(this.minResizeWidth, current - reducingMovement);
splitNode.children[i][dimensionInParent] = newSize;
const amountReduced = current - newSize;
reducingMovement -= amountReduced;
if (reducingMovement <= 0) break;
} }
let max = false; const increasingMovement = Math.max(movementPercent, - movementPercent) - reducingMovement;
if (currentSize + percentageChange < this.minResizeWidth) { const increaseIndex = gridIdx + (movementPercent < 0 ? 1 : 0);
percentageChange = this.minResizeWidth - currentSize; splitNode.children[increaseIndex][dimensionInParent] = originalSizes[increaseIndex] + increasingMovement;
max = true; this.applyGridLayout(splitNode);
} else if (neighborSize - percentageChange < this.minResizeWidth) {
percentageChange = neighborSize - this.minResizeWidth;
max = true;
}
splitData[dimension][gridIdx - 1] += percentageChange;
splitData[dimension][gridIdx] -= percentageChange;
this.applyGridSizes();
if (!max) prevPosition = dEvent[clientAxis];
}); });
} }
const stopListeners = () => { const stopListeners = () => {
@ -691,23 +702,6 @@ var gZenViewSplitter = new class {
setCursor(isVertical ? 'ew-resize' : 'n-resize'); setCursor(isVertical ? 'ew-resize' : 'n-resize');
} }
/**
* Applies the grid column and row sizes
*/
applyGridSizes() {
const splitData = this._data[this.currentView];
const columnGap = 'var(--zen-split-column-gap)';
const rowGap = 'var(--zen-split-row-gap)';
this.tabBrowserPanel.style.gridTemplateColumns = splitData.widths.slice(0, -1).map(
(w) => `calc(${w}% - ${columnGap} * ${splitData.widths.length - 1}/${splitData.widths.length}) ${columnGap}`
).join(' ');
this.tabBrowserPanel.style.gridTemplateRows = splitData.heights.slice(0, -1).map(
(h) => `calc(${h}% - ${rowGap} * ${splitData.heights.length - 1}/${splitData.heights.length}) ${rowGap}`
).join(' ');
}
/** /**
* Sets the docshell state for the tabs. * Sets the docshell state for the tabs.
* *