diff --git a/Amethyst.xcodeproj/project.pbxproj b/Amethyst.xcodeproj/project.pbxproj index 89dd349a..4e42d2d8 100644 --- a/Amethyst.xcodeproj/project.pbxproj +++ b/Amethyst.xcodeproj/project.pbxproj @@ -124,6 +124,8 @@ 4493EAA22139D9F000AA9623 /* ThreeColumnLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4493EAA12139D9EF00AA9623 /* ThreeColumnLayout.swift */; }; AA4AF40D26717DA900D2AE1B /* TwoPaneLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA4AF40C26717DA900D2AE1B /* TwoPaneLayout.swift */; }; AAAC6BAC2677DF7B00BEC1B0 /* TwoPaneLayoutTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAAC6BAB2677DF7B00BEC1B0 /* TwoPaneLayoutTests.swift */; }; + ED989E6BAE0E8D035277478A /* Pods_Amethyst.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6611384054CC1D59E32FC049 /* Pods_Amethyst.framework */; }; + F0B42E352A3CA45E00298E30 /* TwoPaneRightLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = F0B42E342A3CA45E00298E30 /* TwoPaneRightLayout.swift */; }; F46629C4272AD7A30040C275 /* FourColumnLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = F46629C3272AD7A30040C275 /* FourColumnLayout.swift */; }; /* End PBXBuildFile section */ @@ -251,6 +253,7 @@ 4493EAA12139D9EF00AA9623 /* ThreeColumnLayout.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ThreeColumnLayout.swift; sourceTree = ""; }; AA4AF40C26717DA900D2AE1B /* TwoPaneLayout.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TwoPaneLayout.swift; sourceTree = ""; }; AAAC6BAB2677DF7B00BEC1B0 /* TwoPaneLayoutTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TwoPaneLayoutTests.swift; sourceTree = ""; }; + F0B42E342A3CA45E00298E30 /* TwoPaneRightLayout.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TwoPaneRightLayout.swift; sourceTree = ""; }; F46629C3272AD7A30040C275 /* FourColumnLayout.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FourColumnLayout.swift; sourceTree = ""; }; /* End PBXFileReference section */ @@ -367,6 +370,7 @@ 4062AD341C1FA62500DB612B /* WideLayout.swift */, 4062AD3A1C206EA900DB612B /* WidescreenTallLayout.swift */, 4045416E268FFDA000861BE8 /* CustomLayout.swift */, + F0B42E342A3CA45E00298E30 /* TwoPaneRightLayout.swift */, ); path = Layouts; sourceTree = ""; @@ -796,6 +800,7 @@ 40A87FFD2404B1B4005EE9C6 /* DebugInfo.swift in Sources */, 4493EAA22139D9F000AA9623 /* ThreeColumnLayout.swift in Sources */, 40A7AEA7232ECF3000E79964 /* Windows.swift in Sources */, + F0B42E352A3CA45E00298E30 /* TwoPaneRightLayout.swift in Sources */, 404BE9CE1CFBB6E900D6C537 /* BinarySpacePartitioningLayout.swift in Sources */, 4062AD3B1C206EA900DB612B /* WidescreenTallLayout.swift in Sources */, 4058C46F1C4B119500B19D26 /* LayoutNameWindowController.swift in Sources */, diff --git a/Amethyst.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Amethyst.xcodeproj/project.xcworkspace/contents.xcworkspacedata index 919434a6..ebbb5e47 100644 --- a/Amethyst.xcodeproj/project.xcworkspace/contents.xcworkspacedata +++ b/Amethyst.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -2,6 +2,6 @@ + location = "self:Amethyst.xcodeproj"> diff --git a/Amethyst.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/Amethyst.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist deleted file mode 100644 index 18d98100..00000000 --- a/Amethyst.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +++ /dev/null @@ -1,8 +0,0 @@ - - - - - IDEDidComputeMac32BitWarning - - - diff --git a/Amethyst/Layout/Layouts/TwoPaneRightLayout.swift b/Amethyst/Layout/Layouts/TwoPaneRightLayout.swift new file mode 100644 index 00000000..9c2ff45c --- /dev/null +++ b/Amethyst/Layout/Layouts/TwoPaneRightLayout.swift @@ -0,0 +1,103 @@ +// +// TwoPaneRightLayout.swift +// Amethyst +// +// Created by Anja on 16.06.23. +// Copyright © 2023 Ian Ynda-Hummel. All rights reserved. +// + +import Silica + +class TwoPaneRightLayout: Layout, PanedLayout { + override static var layoutName: String { return "Two Pane Right" } + override static var layoutKey: String { return "two-pane-right" } + + enum CodingKeys: String, CodingKey { + case mainPaneCount + case mainPaneRatio + } + + override var layoutDescription: String { return "" } + + private(set) var mainPaneCount: Int = 1 + private(set) var mainPaneRatio: CGFloat = 0.5 + + required init() { + super.init() + } + + required init(from decoder: Decoder) throws { + let values = try decoder.container(keyedBy: CodingKeys.self) + self.mainPaneCount = try values.decode(Int.self, forKey: .mainPaneCount) + self.mainPaneRatio = try values.decode(CGFloat.self, forKey: .mainPaneRatio) + super.init() + } + + override func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(mainPaneCount, forKey: .mainPaneCount) + try container.encode(mainPaneRatio, forKey: .mainPaneRatio) + } + + func recommendMainPaneRawRatio(rawRatio: CGFloat) { + mainPaneRatio = rawRatio + } + + func increaseMainPaneCount() {} + + func decreaseMainPaneCount() {} + + override func frameAssignments(_ windowSet: WindowSet, on screen: Screen) -> [FrameAssignmentOperation]? { + let windows = windowSet.windows + + guard !windows.isEmpty else { + return [] + } + + let mainPaneCount = min(windows.count, self.mainPaneCount) + let secondaryPaneCount = windows.count > 1 ? 1 : 0 + let hasSecondaryPane = secondaryPaneCount > 0 + + let screenFrame = screen.adjustedFrame() + let isHorizontal = (screenFrame.size.width / screenFrame.size.height) >= 1 + + let mainPaneWindowHeight = screenFrame.size.height * (!isHorizontal && hasSecondaryPane ? mainPaneRatio : 1) + let secondaryPaneWindowHeight = isHorizontal ? mainPaneWindowHeight : screenFrame.size.height - mainPaneWindowHeight + + let mainPaneWindowWidth = screenFrame.size.width * (isHorizontal && hasSecondaryPane ? mainPaneRatio : 1) + let secondaryPaneWindowWidth = !isHorizontal ? mainPaneWindowWidth : screenFrame.size.width - mainPaneWindowWidth + + return windows.reduce([]) { acc, window -> [FrameAssignmentOperation] in + var assignments = acc + var windowFrame = CGRect.zero + let isMain = acc.count < mainPaneCount + var scaleFactor: CGFloat + + if isMain { + scaleFactor = screenFrame.size.width / mainPaneWindowWidth + windowFrame.origin.x = screenFrame.origin.x + (isHorizontal ? secondaryPaneWindowWidth : 0) + windowFrame.origin.y = screenFrame.origin.y + windowFrame.size.width = mainPaneWindowWidth + windowFrame.size.height = mainPaneWindowHeight + } else { + scaleFactor = screenFrame.size.width / secondaryPaneWindowWidth + windowFrame.origin.x = screenFrame.origin.x + windowFrame.origin.y = screenFrame.origin.y + (isHorizontal ? 0 : mainPaneWindowHeight) + windowFrame.size.width = secondaryPaneWindowWidth + windowFrame.size.height = secondaryPaneWindowHeight + } + + let resizeRules = ResizeRules(isMain: isMain, unconstrainedDimension: .horizontal, scaleFactor: scaleFactor) + let frameAssignment = FrameAssignment( + frame: windowFrame, + window: window, + screenFrame: screenFrame, + resizeRules: resizeRules + ) + + assignments.append(FrameAssignmentOperation(frameAssignment: frameAssignment, windowSet: windowSet)) + + return assignments + } + } +} diff --git a/Amethyst/Managers/LayoutType.swift b/Amethyst/Managers/LayoutType.swift index a143a7c0..e531a889 100644 --- a/Amethyst/Managers/LayoutType.swift +++ b/Amethyst/Managers/LayoutType.swift @@ -46,6 +46,7 @@ enum LayoutType { case tallRight case wide case twoPane + case twoPaneRight case threeColumnLeft case threeColumnMiddle case threeColumnRight @@ -67,6 +68,7 @@ enum LayoutType { .tallRight, .wide, .twoPane, + .twoPaneRight, .threeColumnLeft, .threeColumnMiddle, .threeColumnRight, @@ -92,6 +94,8 @@ enum LayoutType { return "wide" case .twoPane: return "two-pane" + case .twoPaneRight: + return "two-pane-right" case .threeColumnLeft: return "3column-left" case .threeColumnMiddle: @@ -131,6 +135,8 @@ enum LayoutType { return WideLayout.self case .twoPane: return TwoPaneLayout.self + case .twoPaneRight: + return TwoPaneRightLayout.self case .threeColumnLeft: return ThreeColumnLeftLayout.self case .threeColumnMiddle: @@ -170,6 +176,8 @@ enum LayoutType { return .wide case "two-pane": return .twoPane + case "two-pane-right": + return .twoPaneRight case "3column-left": return .threeColumnLeft case "middle-wide": diff --git a/README.md b/README.md index baa1d607..82cd2225 100644 --- a/README.md +++ b/README.md @@ -149,6 +149,10 @@ automatically adapts to horizontal/vertical tiling depending on your screen orientation. The main pane is on the left in the horizontal orientation and it's on the top in the vertical orientation. +#### Two Pane Right + +Exactly the same as *Two Pane*, but the main pane is on the right, with the other pane on the left. + #### 3Column-Left A three-column version of *Tall*, with one main pane on the left (extending the full height of the screen) and two other panes, one in the middle and one on the right. Like *Tall*, if any pane has more than one window, that pane will be split into rows. You can control how many windows are in the main pane as usual; other windows will be assigned as evenly as possible between the other two panes.