Equalize splits based on children oriented in the same direction (#7710)

This changes equalization so it only counts children oriented in the
same direction.

This makes splits a bit more aesthetic, and replicates how split
equalization works in neovim.

### This is how splits look before this change:

Notice how the left pane gets squeezed.

Before equalization
<img width="1440" alt="Screenshot 2025-06-28 at 8 47 40 AM"
src="https://github.com/user-attachments/assets/498d3026-cfde-4856-b88b-677b2e77b4a0"
/>

After equalization
<img width="1440" alt="Screenshot 2025-06-28 at 8 47 49 AM"
src="https://github.com/user-attachments/assets/2cf7bb60-62da-4d42-882c-d8324cc7bdb6"
/>



---

### And here's how the equalization works after this change:

Before equalization
<img width="1440" alt="Screenshot 2025-06-28 at 8 48 18 AM"
src="https://github.com/user-attachments/assets/39974948-573c-48e8-93a2-7504968f1418"
/>

After equalization
<img width="1440" alt="Screenshot 2025-06-28 at 8 48 24 AM"
src="https://github.com/user-attachments/assets/d97adccd-976e-45a5-b98e-6e5596cf89d3"
/>


For many splits it looks much more aesthetic:
<img width="1440" alt="Screenshot 2025-06-28 at 8 48 28 AM"
src="https://github.com/user-attachments/assets/012d84fc-400f-4864-b8d4-cf7ce53067fb"
/>
<img width="1440" alt="Screenshot 2025-06-28 at 8 48 35 AM"
src="https://github.com/user-attachments/assets/204583ad-66e6-4a1d-a3a0-d2805a8daded"
/>
pull/7718/head
Mitchell Hashimoto 2025-06-28 07:26:49 -07:00 committed by GitHub
commit 1607f761d2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 26 additions and 5 deletions

View File

@ -610,14 +610,18 @@ extension SplitTree.Node {
return (self, 1)
case .split(let split):
// Recursively equalize children
let (leftNode, leftWeight) = split.left.equalizeWithWeight()
let (rightNode, rightWeight) = split.right.equalizeWithWeight()
// Calculate weights based on split direction
let leftWeight = split.left.weightForDirection(split.direction)
let rightWeight = split.right.weightForDirection(split.direction)
// Calculate new ratio based on relative weights
let totalWeight = leftWeight + rightWeight
let newRatio = Double(leftWeight) / Double(totalWeight)
// Recursively equalize children
let (leftNode, _) = split.left.equalizeWithWeight()
let (rightNode, _) = split.right.equalizeWithWeight()
// Create new split with equalized ratio
let newSplit = Split(
direction: split.direction,
@ -630,6 +634,23 @@ extension SplitTree.Node {
}
}
/// Calculate weight for equalization based on split direction.
/// Children with the same direction contribute their full weight,
/// children with different directions count as 1.
private func weightForDirection(_ direction: SplitTree.Direction) -> Int {
switch self {
case .leaf:
return 1
case .split(let split):
if split.direction == direction {
return split.left.weightForDirection(direction) + split.right.weightForDirection(direction)
} else {
return 1
}
}
}
/// Calculate the bounds of all views in this subtree based on split ratios
func calculateViewBounds(in bounds: CGRect) -> [(view: ViewType, bounds: CGRect)] {
switch self {