Refactor: remove redundant height AND widthInParent from splitNode, fix weird splitTabs behaviour

This commit is contained in:
brahim 2024-10-05 14:10:13 +02:00
parent cde3c6a48b
commit 694cbc9d89

View file

@ -1,13 +1,10 @@
class SplitNode { class SplitLeafNode {
/**
* @type {number}
* @type
*/
widthInParent ;
/** /**
* The percentage of the size of the parent the node takes up, dependent on parent direction this is either
* width or height.
* @type {number} * @type {number}
*/ */
heightInParent ; sizeInParent;
/** /**
* @type {Object} * @type {Object}
*/ */
@ -16,16 +13,31 @@ class SplitNode {
* @type {SplitNode} * @type {SplitNode}
*/ */
parent; parent;
constructor(tab, sizeInParent) {
this.tab = tab;
this.sizeInParent = sizeInParent;
}
get heightInParent() {
return this.parent.direction === 'column' ? this.sizeInParent : 100;
}
get widthInParent() {
return this.parent.direction === 'row' ? this.sizeInParent : 100;
}
}
class SplitNode extends SplitLeafNode {
/** /**
* @type {string} * @type {string}
*/ */
direction; direction;
_children = [];
constructor(direction, widthInParent = 100, heightInParent = 100) { constructor(direction, sizeInParent) {
this.widthInParent = widthInParent; super(null, sizeInParent);
this.heightInParent = heightInParent; this.sizeInParent = sizeInParent;
this.direction = direction; // row or column this.direction = direction; // row or column
this._children = [];
} }
set children(children) { set children(children) {
@ -42,13 +54,6 @@ class SplitNode {
this._children.push(child); this._children.push(child);
} }
} }
class SplitLeafNode {
constructor(tab, widthInParent = 100, heightInParent = 100) {
this.tab = tab;
this.widthInParent = widthInParent;
this.heightInParent = heightInParent;
}
}
class ZenViewSplitter extends ZenDOMOperatedFeature { class ZenViewSplitter extends ZenDOMOperatedFeature {
currentView = -1; currentView = -1;
@ -143,16 +148,14 @@ class ZenViewSplitter extends ZenDOMOperatedFeature {
parent.children.splice(childIndex, 1); parent.children.splice(childIndex, 1);
if (parent.children.length !== 1) { if (parent.children.length !== 1) {
const nodeToResize = parent.children[Math.max(0, childIndex - 1)]; const nodeToResize = parent.children[Math.max(0, childIndex - 1)];
if (parent.direction === 'column') nodeToResize.heightInParent += toRemove.heightInParent; nodeToResize.sizeInParent += toRemove.sizeInParent;
else nodeToResize.widthInParent += toRemove.widthInParent;
this.applyGridLayout(parent); this.applyGridLayout(parent);
return; return;
} }
// node that is not a leaf cannot have less than 2 children, this makes for better resizing // node that is not a leaf cannot have less than 2 children, this makes for better resizing
// node takes place of parent // node takes place of parent
const leftOverChild = parent.children[0]; const leftOverChild = parent.children[0];
leftOverChild.widthInParent = parent.widthInParent; leftOverChild.sizeInParent = parent.sizeInParent;
leftOverChild.heightInParent = parent.heightInParent;
if (parent.parent) { if (parent.parent) {
leftOverChild.parent = parent.parent; leftOverChild.parent = parent.parent;
parent.parent.children[parent.parent.children.indexOf(parent)] = leftOverChild; parent.parent.children[parent.parent.children.indexOf(parent)] = leftOverChild;
@ -510,7 +513,7 @@ class ZenViewSplitter extends ZenDOMOperatedFeature {
* @param {Tab[]} tabs - The tabs to split. * @param {Tab[]} tabs - The tabs to split.
* @param {string} gridType - The type of grid layout. * @param {string} gridType - The type of grid layout.
*/ */
splitTabs(tabs, gridType = 'grid') { splitTabs(tabs, gridType) {
if (tabs.length < 2) { if (tabs.length < 2) {
return; return;
} }
@ -519,7 +522,7 @@ class ZenViewSplitter extends ZenDOMOperatedFeature {
if (existingSplitTab) { if (existingSplitTab) {
const groupIndex = this._data.findIndex((group) => group.tabs.includes(existingSplitTab)); const groupIndex = this._data.findIndex((group) => group.tabs.includes(existingSplitTab));
const group = this._data[groupIndex]; const group = this._data[groupIndex];
if (group.gridType !== gridType || tabs.length !== tabs.length) { if (gridType && (group.gridType !== gridType)) {
// reset layout // reset layout
group.gridType = gridType; group.gridType = gridType;
group.layoutTree = this.calculateLayoutTree([...new Set(group.tabs.concat(tabs))], gridType); group.layoutTree = this.calculateLayoutTree([...new Set(group.tabs.concat(tabs))], gridType);
@ -535,6 +538,7 @@ class ZenViewSplitter extends ZenDOMOperatedFeature {
this.activateSplitView(group, true); this.activateSplitView(group, true);
return; return;
} }
gridType ??= 'grid';
const splitData = { const splitData = {
tabs, tabs,
@ -547,15 +551,9 @@ class ZenViewSplitter extends ZenDOMOperatedFeature {
} }
addTabToSplit(tab, splitNode) { addTabToSplit(tab, splitNode) {
if (splitNode.direction === 'row') { const reduce = splitNode.children.length / (splitNode.children.length + 1);
const reduce = splitNode.children.length / (splitNode.children.length + 1); splitNode.children.forEach(c => c.sizeInParent *= reduce);
splitNode.children.forEach(c => c.widthInParent *= reduce); splitNode.addChild(new SplitLeafNode(tab, (1 - reduce) * 100));
splitNode.addChild(new SplitLeafNode(tab, (1 - reduce) * 100, 100));
} else if (splitNode.direction === 'column') {
const reduce = splitNode.children.length / (splitNode.children.length + 1);
splitNode.children.forEach(c => c.heightInParent *= reduce);
splitNode.addChild(new SplitLeafNode(tab, (1 - reduce) * 100, 100));
}
} }
/** /**
@ -620,20 +618,20 @@ class ZenViewSplitter extends ZenDOMOperatedFeature {
let rootNode; let rootNode;
if (gridType === 'vsep' || (tabs.length === 2 && gridType === 'grid')) { if (gridType === 'vsep' || (tabs.length === 2 && gridType === 'grid')) {
rootNode = new SplitNode('row'); rootNode = new SplitNode('row');
rootNode.children = tabs.map(tab => new SplitLeafNode(tab, 100 / tabs.length, 100)); rootNode.children = tabs.map(tab => new SplitLeafNode(tab, 100 / tabs.length));
} else if (gridType === 'hsep') { } else if (gridType === 'hsep') {
rootNode = new SplitNode('column'); rootNode = new SplitNode('column');
rootNode.children = tabs.map(tab => new SplitLeafNode(tab, 100, 100 / tabs.length)); rootNode.children = tabs.map(tab => new SplitLeafNode(tab, 100 / tabs.length));
} else if (gridType === 'grid') { } else if (gridType === 'grid') {
rootNode = new SplitNode('row'); rootNode = new SplitNode('row');
const rowWidth = 100 / Math.ceil(tabs.length / 2); const rowWidth = 100 / Math.ceil(tabs.length / 2);
for (let i = 0; i < tabs.length - 1; i += 2) { for (let i = 0; i < tabs.length - 1; i += 2) {
const columnNode = new SplitNode('column', rowWidth, 100); const columnNode = new SplitNode('column', rowWidth, 100);
columnNode.children = [new SplitLeafNode(tabs[i], 100, 50), new SplitLeafNode(tabs[i + 1], 100, 50)]; columnNode.children = [new SplitLeafNode(tabs[i], 50), new SplitLeafNode(tabs[i + 1], 50)];
rootNode.addChild(columnNode); rootNode.addChild(columnNode);
} }
if (tabs.length % 2 !== 0) { if (tabs.length % 2 !== 0) {
rootNode.addChild(new SplitLeafNode(tabs[tabs.length - 1], rowWidth, 100)); rootNode.addChild(new SplitLeafNode(tabs[tabs.length - 1], rowWidth));
} }
} }
@ -685,9 +683,9 @@ class ZenViewSplitter extends ZenDOMOperatedFeature {
this.applyGridLayout(childNode); this.applyGridLayout(childNode);
if (splitNode.direction === 'column') { if (splitNode.direction === 'column') {
topOffset += childNode.heightInParent * rootToNodeHeightRatio; topOffset += childNode.sizeInParent * rootToNodeHeightRatio;
} else { } else {
leftOffset += childNode.widthInParent * rootToNodeWidthRatio; leftOffset += childNode.sizeInParent * rootToNodeWidthRatio;
} }
if (i < splittersNeeded) { if (i < splittersNeeded) {
@ -783,7 +781,6 @@ class ZenViewSplitter extends ZenDOMOperatedFeature {
this.tabBrowserPanel.setAttribute('zen-split-resizing', true); this.tabBrowserPanel.setAttribute('zen-split-resizing', true);
const isVertical = event.target.getAttribute('orient') === 'vertical'; const isVertical = event.target.getAttribute('orient') === 'vertical';
const dimension = isVertical ? 'width' : 'height'; const dimension = isVertical ? 'width' : 'height';
const dimensionInParent = dimension + 'InParent';
const clientAxis = isVertical ? 'screenX' : 'screenY'; const clientAxis = isVertical ? 'screenX' : 'screenY';
const gridIdx = parseInt(event.target.getAttribute('gridIdx')); const gridIdx = parseInt(event.target.getAttribute('gridIdx'));
@ -792,11 +789,11 @@ class ZenViewSplitter extends ZenDOMOperatedFeature {
let rootToNodeSize; let rootToNodeSize;
if (isVertical) rootToNodeSize = 100 / (100 - splitNode.positionToRoot.right - splitNode.positionToRoot.left); if (isVertical) rootToNodeSize = 100 / (100 - splitNode.positionToRoot.right - splitNode.positionToRoot.left);
else rootToNodeSize = 100 / (100 - splitNode.positionToRoot.bottom - splitNode.positionToRoot.top); else rootToNodeSize = 100 / (100 - splitNode.positionToRoot.bottom - splitNode.positionToRoot.top);
const originalSizes = splitNode.children.map(c => c[dimensionInParent]); const originalSizes = splitNode.children.map(c => c.sizeInParent);
const dragFunc = (dEvent) => { const dragFunc = (dEvent) => {
requestAnimationFrame(() => { requestAnimationFrame(() => {
originalSizes.forEach((s, i) => splitNode.children[i][dimensionInParent] = s); // reset changes originalSizes.forEach((s, i) => splitNode.children[i].sizeInParent = s); // reset changes
const movement = dEvent[clientAxis] - startPosition; const movement = dEvent[clientAxis] - startPosition;
let movementPercent = (movement / this.tabBrowserPanel.getBoundingClientRect()[dimension] * rootToNodeSize) * 100; let movementPercent = (movement / this.tabBrowserPanel.getBoundingClientRect()[dimension] * rootToNodeSize) * 100;
@ -805,14 +802,14 @@ class ZenViewSplitter extends ZenDOMOperatedFeature {
for (let i = gridIdx + (movementPercent < 0 ? 0 : 1); 0 <= i && i < originalSizes.length; i += movementPercent < 0 ? -1 : 1) { for (let i = gridIdx + (movementPercent < 0 ? 0 : 1); 0 <= i && i < originalSizes.length; i += movementPercent < 0 ? -1 : 1) {
const current = originalSizes[i]; const current = originalSizes[i];
const newSize = Math.max(this.minResizeWidth, current - reducingMovement); const newSize = Math.max(this.minResizeWidth, current - reducingMovement);
splitNode.children[i][dimensionInParent] = newSize; splitNode.children[i].sizeInParent = newSize;
const amountReduced = current - newSize; const amountReduced = current - newSize;
reducingMovement -= amountReduced; reducingMovement -= amountReduced;
if (reducingMovement <= 0) break; if (reducingMovement <= 0) break;
} }
const increasingMovement = Math.max(movementPercent, - movementPercent) - reducingMovement; const increasingMovement = Math.max(movementPercent, - movementPercent) - reducingMovement;
const increaseIndex = gridIdx + (movementPercent < 0 ? 1 : 0); const increaseIndex = gridIdx + (movementPercent < 0 ? 1 : 0);
splitNode.children[increaseIndex][dimensionInParent] = originalSizes[increaseIndex] + increasingMovement; splitNode.children[increaseIndex].sizeInParent = originalSizes[increaseIndex] + increasingMovement;
this.applyGridLayout(splitNode); this.applyGridLayout(splitNode);
}); });
} }