Skip to content

Commit

Permalink
Draft moveOut
Browse files Browse the repository at this point in the history
  • Loading branch information
nikitabobko committed Oct 3, 2023
1 parent 2c77f09 commit db77875
Show file tree
Hide file tree
Showing 6 changed files with 97 additions and 25 deletions.
7 changes: 4 additions & 3 deletions src/command/FocusCommand.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,16 @@ struct FocusCommand: Command { // todo speed up. Now it's slightly slow (probabl
precondition(Thread.current.isMainThread)
guard let currentWindow = focusedWindowOrEffectivelyFocused else { return }
if let direction = direction.cardinalOrNil {
guard let topMostChild = currentWindow.parentsWithSelf.first(where: {
let topMostChild = currentWindow.parentsWithSelf.first(where: {
// todo rewrite "is Workspace" part once "sticky" is introduced
$0.parent is Workspace || ($0.parent as? TilingContainer)?.orientation == direction.orientation
}) else { return }
})!
guard let parent = topMostChild.parent as? TilingContainer else { return }
precondition(parent.orientation == direction.orientation)
guard let index = topMostChild.ownIndexOrNil else { return }
let mruIndexMap = currentWindow.workspace.mruWindows.mruIndexMap
let windowToFocus: Window? = parent.children
.getOrNil(atIndex: direction.isPositive ? index + 1 : index - 1)?
.getOrNil(atIndex: index + direction.offset)?
.allLeafWindowsRecursive(snappedTo: direction.opposite)
.minBy { mruIndexMap[$0] ?? Int.max }
windowToFocus?.focus()
Expand Down
43 changes: 38 additions & 5 deletions src/command/MoveThroughCommand.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,27 +6,60 @@ struct MoveThroughCommand: Command {
guard let currentWindow = focusedWindowOrEffectivelyFocused else { return }
if let parent = currentWindow.parent as? TilingContainer {
let indexOfCurrent = currentWindow.ownIndex
let indexOfSiblingTarget = direction.isPositive ? indexOfCurrent + 1 : indexOfCurrent - 1
let indexOfSiblingTarget = indexOfCurrent + direction.offset
if parent.orientation == direction.orientation && parent.children.indices.contains(indexOfSiblingTarget) {
switch parent.children[indexOfSiblingTarget].kind {
case .tilingContainer(let topLevelSiblingTargetContainer):
deepMove(window: currentWindow, into: topLevelSiblingTargetContainer, moveDirection: direction)
deepMoveIn(window: currentWindow, into: topLevelSiblingTargetContainer, moveDirection: direction)
case .window: // "swap windows"
let prevBinding = currentWindow.unbindFromParent()
currentWindow.bindTo(parent: parent, adaptiveWeight: prevBinding.adaptiveWeight, index: indexOfSiblingTarget)
case .workspace:
error("Impossible")
}
} else { // "move out"

} else {
moveOut(window: currentWindow, direction: direction)
}
} else if let _ = currentWindow.parent as? Workspace { // floating window
// todo
}
}
}

private func deepMove(window: Window, into container: TilingContainer, moveDirection: CardinalDirection) {
private func moveOut(window: Window, direction: CardinalDirection) {
let topMostChild = window.parents.first(where: {
// todo rewrite "is Workspace" part once "sticky" is introduced
$0.parent is Workspace || ($0.parent as? TilingContainer)?.orientation == direction.orientation
}) as! TilingContainer
let bindTo: TilingContainer
let bindToIndex: Int
switch topMostChild.parent.kind {
case .tilingContainer(let parent):
precondition(parent.orientation == direction.orientation)
bindTo = parent
bindToIndex = topMostChild.ownIndex + direction.insertionOffset
case .workspace(let parent): // create implicit container
let prevRoot = parent.rootTilingContainer
prevRoot.unbindFromParent()
precondition(prevRoot != parent.rootTilingContainer)
parent.rootTilingContainer.orientation = direction.orientation
prevRoot.bindTo(parent: parent.rootTilingContainer, adaptiveWeight: WEIGHT_AUTO)

bindTo = parent.rootTilingContainer
bindToIndex = direction.insertionOffset
case .window:
error("Window can't contain children nodes")
}

window.unbindFromParent()
window.bindTo(
parent: bindTo,
adaptiveWeight: WEIGHT_AUTO,
index: bindToIndex
)
}

private func deepMoveIn(window: Window, into container: TilingContainer, moveDirection: CardinalDirection) {
let mruIndexMap = window.workspace.mruWindows.mruIndexMap
let preferredPath: [TreeNode] = container.allLeafWindowsRecursive
.minBy { mruIndexMap[$0] ?? Int.max }!
Expand Down
1 change: 1 addition & 0 deletions src/tree/TilingContainer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ extension TilingContainer {
}
}

var ownIndex: Int { parent.children.firstIndex(of: self)! }
var isRootContainer: Bool { parent is Workspace }
}

Expand Down
9 changes: 8 additions & 1 deletion src/tree/TreeNode.swift
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,14 @@ class TreeNode: Equatable {
.div(newParent.children.count)
?? 1
case .workspace:
self.adaptiveWeight = WEIGHT_FLOATING
switch self.kind {
case .window:
self.adaptiveWeight = WEIGHT_FLOATING
case .tilingContainer:
self.adaptiveWeight = 1
case .workspace:
error("Binding workspace to workspace is illegal")
}
case .window:
error("Windows can't have children")
}
Expand Down
2 changes: 2 additions & 0 deletions src/util/CardinalDirection.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,6 @@ extension CardinalDirection {
return .left
}
}
var offset: Int { isPositive ? 1 : -1 }
var insertionOffset: Int { isPositive ? 1 : 0 }
}
60 changes: 44 additions & 16 deletions test/command/MoveThroughCommandTest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -103,22 +103,50 @@ final class MoveThroughCommandTest: XCTestCase {
XCTAssertEqual(window1.hWeight, 1)
}

//func testCreateImplicitContainer() async {
// let root = Workspace.get(byName: name).rootTilingContainer.apply {
// TestWindow(id: 1, parent: $0).focus()
// TestWindow(id: 2, parent: $0)
// TestWindow(id: 3, parent: $0)
// }
//
// await MoveThroughCommand(direction: .up).runWithoutRefresh()
// XCTAssertEqual(
// root.layoutDescription,
// .v_list([
// .window(1),
// .h_list([.window(2), .window(3)])
// ])
// )
//}
func testCreateImplicitContainer() async {
let workspace = Workspace.get(byName: name).apply { // Don't cache root
($0 as! Workspace).rootTilingContainer.apply {
TestWindow(id: 1, parent: $0)
TestWindow(id: 2, parent: $0).focus()
TestWindow(id: 3, parent: $0)
}
}

await MoveThroughCommand(direction: .up).runWithoutRefresh()
XCTAssertEqual(
workspace.layoutDescription,
.workspace([
.v_list([
.window(2),
.h_list([.window(1), .window(3)])
])
])
)
}

func testMoveOut() async {
let root = Workspace.get(byName: name).rootTilingContainer.apply {
TestWindow(id: 1, parent: $0)
TilingContainer.newVList(parent: $0, adaptiveWeight: 1).apply {
TestWindow(id: 2, parent: $0).focus()
TestWindow(id: 3, parent: $0)
TestWindow(id: 4, parent: $0)
}
}

await MoveThroughCommand(direction: .left).runWithoutRefresh()
XCTAssertEqual(
root.layoutDescription,
.h_list([
.window(1),
.window(2),
.v_list([
.window(3),
.window(4),
])
])
)
}
}

extension TreeNode {
Expand Down

0 comments on commit db77875

Please sign in to comment.