Skip to content

Commit

Permalink
Cleanup: TreeNodeKind + MoveThroughCommand cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
nikitabobko committed Oct 1, 2023
1 parent 69ca64b commit f3a4d9e
Show file tree
Hide file tree
Showing 10 changed files with 83 additions and 44 deletions.
4 changes: 4 additions & 0 deletions AeroSpace.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
A2CBF9674964F9083BB198D2 /* ArrayEx.swift in Sources */ = {isa = PBXBuildFile; fileRef = 883D7F7F87FBE7D0BDE4E87F /* ArrayEx.swift */; };
A55F31B0CC357B37108B8F54 /* MoveContainerToWorkspaceCommandTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7DBD002C4A68AED07BB63EFA /* MoveContainerToWorkspaceCommandTest.swift */; };
A5BFF75CF8021A585BC1F9D5 /* parseCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB03A4736BC3F6D19E4E69F3 /* parseCommand.swift */; };
AC439551A737C73168CC5BF9 /* TreeNodeKind.swift in Sources */ = {isa = PBXBuildFile; fileRef = A60709210745C60D64F82D53 /* TreeNodeKind.swift */; };
AC47DF43EFF42358F033C87C /* WorkspaceBackAndForthCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = EED7EE20910D7BE4D0150CED /* WorkspaceBackAndForthCommand.swift */; };
AE76A183D0454E4C8ADCE380 /* SequenceEx.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAE5DCAEC5EE619CE33859E7 /* SequenceEx.swift */; };
B0D0C37BAE7E7F0D0FF1E9FC /* GlobalObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3C2E5977331398421A4FC168 /* GlobalObserver.swift */; };
Expand Down Expand Up @@ -118,6 +119,7 @@
99853C505D93E41F6531C324 /* CloseAllWindowsButCurrentCommand.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CloseAllWindowsButCurrentCommand.swift; sourceTree = "<group>"; };
9D31BF26EAFA96F675D2C14B /* accessibility.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = accessibility.swift; sourceTree = "<group>"; };
9F6B8A501483ACBB62560101 /* TreeNodeEx.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TreeNodeEx.swift; sourceTree = "<group>"; };
A60709210745C60D64F82D53 /* TreeNodeKind.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TreeNodeKind.swift; sourceTree = "<group>"; };
A9EDFD4A9F45182CA6E0BD7B /* OptionalEx.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OptionalEx.swift; sourceTree = "<group>"; };
AAE5DCAEC5EE619CE33859E7 /* SequenceEx.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SequenceEx.swift; sourceTree = "<group>"; };
AD1645D9939F3F896EF21393 /* TreeNodeTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TreeNodeTest.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -184,6 +186,7 @@
C848D6E57FDF22AAF0FB45E6 /* TilingContainer.swift */,
3A262B442A94C1964509B691 /* TreeNode.swift */,
9F6B8A501483ACBB62560101 /* TreeNodeEx.swift */,
A60709210745C60D64F82D53 /* TreeNodeKind.swift */,
6352ADEE6625D9703CFCA99A /* Window.swift */,
C3F068BCC50ED846DCBFDE57 /* Workspace.swift */,
);
Expand Down Expand Up @@ -445,6 +448,7 @@
56E72B24303F5F337B31B776 /* TrayMenuModel.swift in Sources */,
F892B5DCB4F731B3E173FF4C /* TreeNode.swift in Sources */,
03D8ABD4597EDB00D79807E1 /* TreeNodeEx.swift in Sources */,
AC439551A737C73168CC5BF9 /* TreeNodeKind.swift in Sources */,
2CC46A952773F148AC398144 /* Window.swift in Sources */,
BF16873111EEDE60A8AACD6B /* Workspace.swift in Sources */,
AC47DF43EFF42358F033C87C /* WorkspaceBackAndForthCommand.swift in Sources */,
Expand Down
9 changes: 1 addition & 8 deletions src/command/MoveContainerToWorkspaceCommand.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,7 @@ struct MoveContainerToWorkspaceCommand: Command {
let targetWorkspace = Workspace.get(byName: targetWorkspaceName)
let targetContainer = focused.isFloating ? targetWorkspace : targetWorkspace.rootTilingContainer
focused.unbindFromParent()
let weight: CGFloat
if let targetContainer = targetContainer as? TilingContainer {
weight = targetContainer.children.sumOf { $0.getWeight(targetContainer.orientation) }
.div(targetContainer.children.count) ?? 1
} else {
weight = 1
}
focused.bindTo(parent: targetContainer, adaptiveWeight: weight) // todo different monitor
focused.bindTo(parent: targetContainer, adaptiveWeight: EVEN_ADAPTIVE_WEIGHT) // todo different monitor

WorkspaceCommand(workspaceName: preserveWorkspace.name).runWithoutRefresh()
}
Expand Down
38 changes: 22 additions & 16 deletions src/command/MoveThroughCommand.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,25 +8,30 @@ struct MoveThroughCommand: Command {
let indexOfCurrent = parent.children.firstIndex(of: currentWindow) ?? errorT("Can't find child")
let indexOfTarget = direction.isPositive ? indexOfCurrent + 1 : indexOfCurrent - 1
if parent.orientation == direction.orientation && parent.children.indices.contains(indexOfTarget) {
if let targetContainer = parent.children[indexOfTarget] as? TilingContainer { // "move in"
if let toplevelSiblingTargetContainer = parent.children[indexOfTarget] as? TilingContainer { // "move into container"
let mruIndexMap = currentWindow.workspace.mruWindows.mruIndexMap
let recursive = targetContainer.allLeafWindowsRecursive
let reversed = recursive.minBy { mruIndexMap[$0] ?? Int.max }!
let preferredPath: [TreeNode] = toplevelSiblingTargetContainer.allLeafWindowsRecursive
.minBy { mruIndexMap[$0] ?? Int.max }!
.parentsWithSelf
.reversed()
let preferredPath: [TreeNode] = Array(Array(Array(reversed).drop(while: { $0 != targetContainer })).dropFirst())
let pizdets = targetContainer.findNodeOrientRecursive(direction.orientation, preferredPath)
if pizdets is TilingContainer {
.drop(while: { $0 != toplevelSiblingTargetContainer })
.dropFirst()
.toArray()
let target = toplevelSiblingTargetContainer.findNodeOrientRecursive(direction.orientation, preferredPath)
if target is TilingContainer {
currentWindow.unbindFromParent()
currentWindow.bindTo(parent: pizdets, adaptiveWeight: 1, index: 0) // todo adaptiveWeight
} else if pizdets is Window {
currentWindow.bindTo(parent: target, adaptiveWeight: EVEN_ADAPTIVE_WEIGHT, index: 0) // todo adaptiveWeight
} else if target is Window {
currentWindow.unbindFromParent()
currentWindow.bindTo(parent: (pizdets.parent as! TilingContainer), adaptiveWeight: 1,
index: pizdets.parent!.children.firstIndex(of: pizdets)! + 1) // todo mess
currentWindow.bindTo(
parent: (target.parent as! TilingContainer),
adaptiveWeight: EVEN_ADAPTIVE_WEIGHT,
index: target.parent!.children.firstIndex(of: target)! + 1
) // todo mess
} else {
error("Impossible")
}
} else if parent.children[indexOfTarget] is Window {
} else if parent.children[indexOfTarget] is Window { // "swap windows"
let prevBinding = currentWindow.unbindFromParent()
currentWindow.bindTo(parent: parent, adaptiveWeight: prevBinding.adaptiveWeight, index: indexOfTarget)
} else {
Expand All @@ -43,18 +48,19 @@ struct MoveThroughCommand: Command {

private extension TreeNode {
func findNodeOrientRecursive(_ orientation: Orientation, _ preferredPath: [TreeNode]) -> TreeNode {
if let window = self as? Window {
return window
} else if let container = self as? TilingContainer {
switch kind {
case .window:
return self
case .tilingContainer(let container):
if container.orientation == orientation {
return container
} else {
assert(children.contains(preferredPath.first!))
return preferredPath.first!
.findNodeOrientRecursive(orientation, Array(preferredPath.dropFirst()))
}
} else {
case .workspace:
error("Impossible")
}
}
}
}
5 changes: 3 additions & 2 deletions src/tree/MacWindow.swift
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ final class MacWindow: Window {
return prevUnhiddenEmulationPositionRelativeToWorkspaceAssignedRect != nil
}

func setSize(_ size: CGSize) {
override func setSize(_ size: CGSize) {
previousSize = getSize()
axWindow.set(Ax.sizeAttr, size)
}
Expand All @@ -148,7 +148,7 @@ final class MacWindow: Window {
axWindow.get(Ax.sizeAttr)
}

func setTopLeftCorner(_ point: CGPoint) {
override func setTopLeftCorner(_ point: CGPoint) {
axWindow.set(Ax.topLeftCornerAttr, point)
}

Expand Down Expand Up @@ -176,3 +176,4 @@ func shouldFloat(_ axWindow: AXUIElement) -> Bool { // todo
}

let FLOATING_ADAPTIVE_WEIGHT = CGFloat(-1)
let EVEN_ADAPTIVE_WEIGHT = CGFloat(-2)
21 changes: 17 additions & 4 deletions src/tree/TreeNode.swift
Original file line number Diff line number Diff line change
Expand Up @@ -45,20 +45,33 @@ class TreeNode: Equatable {

@discardableResult
func bindTo(parent newParent: TreeNode, adaptiveWeight: CGFloat, index: Int = -1) -> PreviousBindingData? {
if newParent is Window {
error("Windows can't have children")
}
if _parent === newParent {
error("Binding to the same parent doesn't make sense")
}
if newParent is Window {
error("Windows can't have children")
}
let result = unbindIfPossible()

if newParent === NilTreeNode.instance {
return result
}
newParent._children.insert(self, at: index == -1 ? newParent._children.count : index)
_parent = newParent
self.adaptiveWeight = adaptiveWeight
if adaptiveWeight == EVEN_ADAPTIVE_WEIGHT {
switch newParent.kind {
case .tilingContainer(let container):
self.adaptiveWeight = container.children.sumOf { $0.getWeight(container.orientation) }
.div(container.children.count)
?? 1
case .workspace:
self.adaptiveWeight = FLOATING_ADAPTIVE_WEIGHT
case .window:
error("Windows can't have children")
}
} else {
self.adaptiveWeight = adaptiveWeight
}
if let window = self as? Window {
let newParentWorkspace = newParent.workspace
newParentWorkspace.mruWindows.pushOrRaise(window)
Expand Down
28 changes: 19 additions & 9 deletions src/tree/TreeNodeEx.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,19 +21,18 @@ extension TreeNode {
}

func allLeafWindowsRecursive(snappedTo direction: CardinalDirection) -> [Window] {
if let workspace = self as? Workspace {
switch kind {
case .workspace(let workspace):
return workspace.rootTilingContainer.allLeafWindowsRecursive(snappedTo: direction)
} else if let window = self as? Window {
case .window(let window):
return [window]
} else if let container = self as? TilingContainer {
case .tilingContainer(let container):
if direction.orientation == container.orientation {
return (direction.isPositive ? container.children.last : container.children.first)?
.allLeafWindowsRecursive(snappedTo: direction) ?? []
} else {
return children.flatMap { $0.allLeafWindowsRecursive(snappedTo: direction) }
}
} else {
error("Not supported TreeNode type: \(Self.self)")
}
}

Expand Down Expand Up @@ -68,12 +67,13 @@ extension TreeNode {

/// Containers' weights must be normalized before calling this function
func layoutRecursive(_ _point: CGPoint, width: CGFloat, height: CGFloat) {
if let workspace = self as? Workspace {
switch kind {
case .workspace(let workspace):
workspace.rootTilingContainer.layoutRecursive(_point, width: width, height: height)
} else if let window = self as? MacWindow {
case .window(let window):
window.setTopLeftCorner(_point)
window.setSize(CGSize(width: width, height: height))
} else if let container = self as? TilingContainer {
case .tilingContainer(let container):
var point = _point
for child in container.children {
switch container.layout {
Expand All @@ -89,8 +89,18 @@ extension TreeNode {
}
}
}
}
}

var kind: TreeNodeKind {
if let window = self as? Window {
return .window(window)
} else if let workspace = self as? Workspace {
return .workspace(workspace)
} else if let tilingContainer = self as? TilingContainer {
return .tilingContainer(tilingContainer)
} else {
error("Not supported TreeNode type: \(Self.self)")
error("Unknown tree")
}
}
}
5 changes: 5 additions & 0 deletions src/tree/TreeNodeKind.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
enum TreeNodeKind {
case window(Window)
case tilingContainer(TilingContainer)
case workspace(Workspace)
}
4 changes: 4 additions & 0 deletions src/tree/Window.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ class Window: TreeNode, Hashable {
}

var title: String? { error("Not implemented") }

func setSize(_ size: CGSize) { error("Not implemented") }

func setTopLeftCorner(_ point: CGPoint) { error("Not implemented") }
}

extension Window {
Expand Down
4 changes: 4 additions & 0 deletions src/util/util.swift
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ extension Double {
var squared: Double { self * self }
}

extension Slice {
func toArray() -> [Base.Element] { Array(self) }
}

func -(a: CGPoint, b: CGPoint) -> CGPoint {
CGPoint(x: a.x - b.x, y: a.y - b.y)
}
Expand Down
9 changes: 4 additions & 5 deletions test/command/MoveThroughCommandTest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,10 @@ final class MoveThroughCommandTest: XCTestCase {

extension TreeNode {
var layoutDescription: LayoutDescription {
if let window = self as? Window {
switch kind {
case .window(let window):
return .window(window.windowId)
} else if let container = self as? TilingContainer {
case .tilingContainer(let container):
switch container.layout {
case .List:
switch container.orientation {
Expand All @@ -80,10 +81,8 @@ extension TreeNode {
return .v_accordion(container.children.map { $0.layoutDescription })
}
}
} else if let workspace = self as? Workspace {
case .workspace:
return .workspace(workspace.children.map { $0.layoutDescription })
} else {
error("Unknown type: \(Self.self)")
}
}
}
Expand Down

0 comments on commit f3a4d9e

Please sign in to comment.