mirror of
https://github.com/stablyai/orca.git
synced 2026-10-24 08:03:58 +00:00
Split pane tree equalization logic
This commit is contained in:
@@ -61,7 +61,6 @@ inline src/renderer/src/components/terminal-pane/remote-runtime-pty-transport.ts
|
||||
inline src/renderer/src/components/terminal-pane/use-terminal-pane-lifecycle.ts
|
||||
inline src/renderer/src/hooks/useAutomationDispatchEvents.ts
|
||||
inline src/renderer/src/hooks/useSettingsNavigationMetadata.ts
|
||||
inline src/renderer/src/lib/pane-manager/pane-tree-ops.ts
|
||||
inline src/renderer/src/runtime/remote-runtime-terminal-multiplexer.ts
|
||||
inline src/renderer/src/runtime/runtime-file-client.ts
|
||||
inline src/renderer/src/runtime/sync-runtime-graph.ts
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
/** Find non-divider children (panes and splits) of an element. */
|
||||
export function findPaneChildren(parent: HTMLElement): HTMLElement[] {
|
||||
return Array.from(parent.children).filter(
|
||||
(child): child is HTMLElement =>
|
||||
child instanceof HTMLElement &&
|
||||
(child.classList.contains('pane') || child.classList.contains('pane-split'))
|
||||
)
|
||||
}
|
||||
|
||||
function getSplitDirection(split: HTMLElement): 'vertical' | 'horizontal' {
|
||||
return split.classList.contains('is-horizontal') ? 'horizontal' : 'vertical'
|
||||
}
|
||||
|
||||
function getEqualizeWeight(el: HTMLElement, direction: 'vertical' | 'horizontal'): number {
|
||||
if (!el.classList.contains('pane-split') || getSplitDirection(el) !== direction) {
|
||||
return 1
|
||||
}
|
||||
|
||||
const children = findPaneChildren(el)
|
||||
return Math.max(
|
||||
1,
|
||||
children.reduce((sum, child) => sum + getEqualizeWeight(child, direction), 0)
|
||||
)
|
||||
}
|
||||
|
||||
export function equalizePaneSplitSizes(root: HTMLElement | null): boolean {
|
||||
if (!root) {
|
||||
return false
|
||||
}
|
||||
|
||||
let changed = false
|
||||
const visit = (el: HTMLElement): void => {
|
||||
if (!el.classList.contains('pane-split')) {
|
||||
return
|
||||
}
|
||||
|
||||
const direction = getSplitDirection(el)
|
||||
const children = findPaneChildren(el)
|
||||
if (children.length >= 2) {
|
||||
for (const child of children) {
|
||||
// Why: same-axis nested splits need pane-count weighting so three
|
||||
// side-by-side panes become thirds, not 50/25/25.
|
||||
const weight = getEqualizeWeight(child, direction)
|
||||
const nextFlex = `${weight} 1 0%`
|
||||
if (child.style.flex !== nextFlex) {
|
||||
child.style.flex = nextFlex
|
||||
changed = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const child of children) {
|
||||
visit(child)
|
||||
}
|
||||
}
|
||||
|
||||
visit(root)
|
||||
return changed
|
||||
}
|
||||
@@ -1,4 +1,3 @@
|
||||
/* eslint-disable max-lines -- Why: split-tree DOM reparent, promote, and equalize rules need one consistent owner. */
|
||||
import type {
|
||||
DropZone,
|
||||
ManagedPane,
|
||||
@@ -16,6 +15,7 @@ export {
|
||||
type SafeFitContinuationHandle
|
||||
} from './pane-fit'
|
||||
export { captureScrollState, restoreScrollState } from './pane-scroll'
|
||||
export { equalizePaneSplitSizes, findPaneChildren } from './pane-tree-equalization'
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Split-tree manipulation: detach, insert, promote sibling
|
||||
@@ -242,66 +242,6 @@ export function removeDividers(parent: HTMLElement): void {
|
||||
}
|
||||
}
|
||||
|
||||
/** Find non-divider children (panes and splits) of an element. */
|
||||
export function findPaneChildren(parent: HTMLElement): HTMLElement[] {
|
||||
return Array.from(parent.children).filter(
|
||||
(child): child is HTMLElement =>
|
||||
child instanceof HTMLElement &&
|
||||
(child.classList.contains('pane') || child.classList.contains('pane-split'))
|
||||
)
|
||||
}
|
||||
|
||||
function getSplitDirection(split: HTMLElement): 'vertical' | 'horizontal' {
|
||||
return split.classList.contains('is-horizontal') ? 'horizontal' : 'vertical'
|
||||
}
|
||||
|
||||
function getEqualizeWeight(el: HTMLElement, direction: 'vertical' | 'horizontal'): number {
|
||||
if (!el.classList.contains('pane-split') || getSplitDirection(el) !== direction) {
|
||||
return 1
|
||||
}
|
||||
|
||||
const children = findPaneChildren(el)
|
||||
return Math.max(
|
||||
1,
|
||||
children.reduce((sum, child) => sum + getEqualizeWeight(child, direction), 0)
|
||||
)
|
||||
}
|
||||
|
||||
export function equalizePaneSplitSizes(root: HTMLElement | null): boolean {
|
||||
if (!root) {
|
||||
return false
|
||||
}
|
||||
|
||||
let changed = false
|
||||
const visit = (el: HTMLElement): void => {
|
||||
if (!el.classList.contains('pane-split')) {
|
||||
return
|
||||
}
|
||||
|
||||
const direction = getSplitDirection(el)
|
||||
const children = findPaneChildren(el)
|
||||
if (children.length >= 2) {
|
||||
for (const child of children) {
|
||||
// Why: same-axis nested splits need pane-count weighting so three
|
||||
// side-by-side panes become thirds, not 50/25/25.
|
||||
const weight = getEqualizeWeight(child, direction)
|
||||
const nextFlex = `${weight} 1 0%`
|
||||
if (child.style.flex !== nextFlex) {
|
||||
child.style.flex = nextFlex
|
||||
changed = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const child of children) {
|
||||
visit(child)
|
||||
}
|
||||
}
|
||||
|
||||
visit(root)
|
||||
return changed
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a flex split wrapper that replaces `existingContainer` in the DOM,
|
||||
* then places [existing] [divider] [new] inside it.
|
||||
|
||||
Reference in New Issue
Block a user