From 1e77bb4900fbcee305d6204461123f62a937dc49 Mon Sep 17 00:00:00 2001 From: viktorstrate Date: Sun, 20 Mar 2022 19:47:19 +0100 Subject: [PATCH 1/3] Refactor TabBarItems --- CodeEdit/TabBar/TabBar.swift | 47 +++-------------------------- CodeEdit/TabBar/TabBarItem.swift | 52 ++++++++++++++++++++++++++++++-- 2 files changed, 54 insertions(+), 45 deletions(-) diff --git a/CodeEdit/TabBar/TabBar.swift b/CodeEdit/TabBar/TabBar.swift index 9a7aad6a96..38153972d6 100644 --- a/CodeEdit/TabBar/TabBar.swift +++ b/CodeEdit/TabBar/TabBar.swift @@ -31,38 +31,10 @@ struct TabBar: View { ScrollViewReader { value in HStack(alignment: .center, spacing: 0.0) { ForEach(workspace.openFileItems, id: \.id) { item in - let isActive = workspace.selectedId == item.id - - Button( - action: { workspace.selectedId = item.id }, - label: { - if isActive { - TabBarItem( - item: item, - windowController: windowController, - workspace: workspace - ) - .background( - BlurView( - material: NSVisualEffectView.Material.titlebar, - blendingMode: NSVisualEffectView.BlendingMode.withinWindow - ) - ) - } else { - TabBarItem( - item: item, - windowController: windowController, - workspace: workspace - ) - } - } - ) - .animation(.easeOut(duration: 0.2), value: workspace.openFileItems) - .buttonStyle(.plain) - .id(item.id) - .keyboardShortcut( - self.getTabId(fileName: item.fileName), - modifiers: [.command] + TabBarItem( + item: item, + windowController: windowController, + workspace: workspace ) } } @@ -75,15 +47,4 @@ struct TabBar: View { .background(BlurView(material: NSVisualEffectView.Material.windowBackground, blendingMode: NSVisualEffectView.BlendingMode.withinWindow)) } - - func getTabId(fileName: String) -> KeyEquivalent { - for counter in 0..<9 where workspace.openFileItems.count > counter && - workspace.openFileItems[counter].fileName == fileName { - return KeyEquivalent.init( - Character.init("\(counter + 1)") - ) - } - - return "0" - } } diff --git a/CodeEdit/TabBar/TabBarItem.swift b/CodeEdit/TabBar/TabBarItem.swift index 647f3949fa..7b1a9c1323 100644 --- a/CodeEdit/TabBar/TabBarItem.swift +++ b/CodeEdit/TabBar/TabBarItem.swift @@ -14,8 +14,13 @@ struct TabBarItem: View { var windowController: NSWindowController @ObservedObject var workspace: WorkspaceDocument var tabBarHeight: Double = 28.0 - var body: some View { - let isActive = item.id == workspace.selectedId + + var isActive: Bool { + item.id == workspace.selectedId + } + + @ViewBuilder + var content: some View { HStack(spacing: 0.0) { FileTabRow(fileItem: item, isSelected: isActive, isHovering: isHovering) { withAnimation { @@ -42,4 +47,47 @@ struct TabBarItem: View { } } } + + var body: some View { + Button(action: { workspace.selectedId = item.id }) { + content + .background( + isActive ? AnyView(BlurView( + material: NSVisualEffectView.Material.titlebar, + blendingMode: NSVisualEffectView.BlendingMode.withinWindow + )) : AnyView(EmptyView()) + ) + } + .animation(.easeOut(duration: 0.2), value: workspace.openFileItems) + .buttonStyle(.plain) + .id(item.id) + .keyboardShortcut( + workspace.getTabId(fileName: item.fileName), + modifiers: [.command] + ) + .contextMenu { + Button("Close Tab") { + + } + Button("Close Other Tab") { + + } + Button("Close Tabs to the Right") { + + } + } + } +} + +extension WorkspaceDocument { + func getTabId(fileName: String) -> KeyEquivalent { + for counter in 0..<9 where self.openFileItems.count > counter && + self.openFileItems[counter].fileName == fileName { + return KeyEquivalent.init( + Character.init("\(counter + 1)") + ) + } + + return "0" + } } From 1ecc2296c21ee53685deeb4bc840b15f11306efc Mon Sep 17 00:00:00 2001 From: viktorstrate Date: Sun, 20 Mar 2022 20:39:58 +0100 Subject: [PATCH 2/3] Add context menu to tabs --- CodeEdit/Documents/WorkspaceDocument.swift | 29 ++++++++++++++++++++++ CodeEdit/TabBar/TabBarItem.swift | 20 +++++++++------ 2 files changed, 42 insertions(+), 7 deletions(-) diff --git a/CodeEdit/Documents/WorkspaceDocument.swift b/CodeEdit/Documents/WorkspaceDocument.swift index ed7418b195..cd79d3cbad 100644 --- a/CodeEdit/Documents/WorkspaceDocument.swift +++ b/CodeEdit/Documents/WorkspaceDocument.swift @@ -20,6 +20,14 @@ class WorkspaceDocument: NSDocument, ObservableObject, NSToolbarDelegate { @Published var openFileItems: [WorkspaceClient.FileItem] = [] @Published var sortFoldersOnTop: Bool = true @Published var fileItems: [WorkspaceClient.FileItem] = [] + + var selected: WorkspaceClient.FileItem? { + guard let selectedId = selectedId else { + return nil + } + + return fileItems.first(where: { $0.id == selectedId }) + } var quickOpenState: QuickOpenState? @@ -48,6 +56,27 @@ class WorkspaceDocument: NSDocument, ObservableObject, NSToolbarDelegate { selectedId = openFileItems[idx - 1].id } } + + func closeFileTabs(items: Items) where Items: Collection, Items.Element == WorkspaceClient.FileItem { + // TODO: Could potentially be optimized + for item in items { + closeFileTab(item: item) + } + } + + func closeFileTab(where predicate: (WorkspaceClient.FileItem) -> Bool) { + closeFileTabs(items: openFileItems.filter(predicate)) + } + + func closeFileTabs(after item: WorkspaceClient.FileItem) { + guard let startIdx = openFileItems.firstIndex(where: { $0.id == item.id }) else { + assert(false, "Expected file item to be present in openFileItems") + return + } + + let range = openFileItems[(startIdx+1)...] + closeFileTabs(items: range) + } func openFile(item: WorkspaceClient.FileItem) { do { diff --git a/CodeEdit/TabBar/TabBarItem.swift b/CodeEdit/TabBar/TabBarItem.swift index 7b1a9c1323..cf30f9238d 100644 --- a/CodeEdit/TabBar/TabBarItem.swift +++ b/CodeEdit/TabBar/TabBarItem.swift @@ -62,27 +62,33 @@ struct TabBarItem: View { .buttonStyle(.plain) .id(item.id) .keyboardShortcut( - workspace.getTabId(fileName: item.fileName), + workspace.getTabKeyEquivalent(item: item), modifiers: [.command] ) .contextMenu { Button("Close Tab") { - + withAnimation { + workspace.closeFileTab(item: item) + } } Button("Close Other Tab") { - + withAnimation { + workspace.closeFileTab(where: { $0.id != item.id }) + } } Button("Close Tabs to the Right") { - + withAnimation { + workspace.closeFileTabs(after: item) + } } } } } -extension WorkspaceDocument { - func getTabId(fileName: String) -> KeyEquivalent { +fileprivate extension WorkspaceDocument { + func getTabKeyEquivalent(item: WorkspaceClient.FileItem) -> KeyEquivalent { for counter in 0..<9 where self.openFileItems.count > counter && - self.openFileItems[counter].fileName == fileName { + self.openFileItems[counter].fileName == item.fileName { return KeyEquivalent.init( Character.init("\(counter + 1)") ) From a7e797b8f36983df272ec3b317d4685de9be4672 Mon Sep 17 00:00:00 2001 From: viktorstrate Date: Sun, 20 Mar 2022 22:16:42 +0100 Subject: [PATCH 3/3] Fix Swiftlint warnings --- CodeEdit/Documents/WorkspaceDocument.swift | 17 ++++++------- CodeEdit/TabBar/TabBarItem.swift | 28 ++++++++++++---------- 2 files changed, 22 insertions(+), 23 deletions(-) diff --git a/CodeEdit/Documents/WorkspaceDocument.swift b/CodeEdit/Documents/WorkspaceDocument.swift index cd79d3cbad..8d0744e5dd 100644 --- a/CodeEdit/Documents/WorkspaceDocument.swift +++ b/CodeEdit/Documents/WorkspaceDocument.swift @@ -18,14 +18,11 @@ class WorkspaceDocument: NSDocument, ObservableObject, NSToolbarDelegate { @Published var selectedId: String? @Published var openFileItems: [WorkspaceClient.FileItem] = [] - @Published var sortFoldersOnTop: Bool = true + @Published var sortFoldersOnTop: Bool = true @Published var fileItems: [WorkspaceClient.FileItem] = [] - - var selected: WorkspaceClient.FileItem? { - guard let selectedId = selectedId else { - return nil - } + var selected: WorkspaceClient.FileItem? { + guard let selectedId = selectedId else { return nil } return fileItems.first(where: { $0.id == selectedId }) } @@ -56,24 +53,24 @@ class WorkspaceDocument: NSDocument, ObservableObject, NSToolbarDelegate { selectedId = openFileItems[idx - 1].id } } - + func closeFileTabs(items: Items) where Items: Collection, Items.Element == WorkspaceClient.FileItem { // TODO: Could potentially be optimized for item in items { closeFileTab(item: item) } } - + func closeFileTab(where predicate: (WorkspaceClient.FileItem) -> Bool) { closeFileTabs(items: openFileItems.filter(predicate)) } - + func closeFileTabs(after item: WorkspaceClient.FileItem) { guard let startIdx = openFileItems.firstIndex(where: { $0.id == item.id }) else { assert(false, "Expected file item to be present in openFileItems") return } - + let range = openFileItems[(startIdx+1)...] closeFileTabs(items: range) } diff --git a/CodeEdit/TabBar/TabBarItem.swift b/CodeEdit/TabBar/TabBarItem.swift index cf30f9238d..13c22fb869 100644 --- a/CodeEdit/TabBar/TabBarItem.swift +++ b/CodeEdit/TabBar/TabBarItem.swift @@ -10,15 +10,15 @@ import WorkspaceClient struct TabBarItem: View { @State var isHovering: Bool = false - var item: WorkspaceClient.FileItem + var item: WorkspaceClient.FileItem var windowController: NSWindowController @ObservedObject var workspace: WorkspaceDocument var tabBarHeight: Double = 28.0 - + var isActive: Bool { item.id == workspace.selectedId } - + @ViewBuilder var content: some View { HStack(spacing: 0.0) { @@ -47,17 +47,19 @@ struct TabBarItem: View { } } } - + var body: some View { - Button(action: { workspace.selectedId = item.id }) { - content - .background( - isActive ? AnyView(BlurView( - material: NSVisualEffectView.Material.titlebar, - blendingMode: NSVisualEffectView.BlendingMode.withinWindow - )) : AnyView(EmptyView()) - ) - } + Button( + action: { workspace.selectedId = item.id }, + label: { + content + .background( + isActive ? AnyView(BlurView( + material: NSVisualEffectView.Material.titlebar, + blendingMode: NSVisualEffectView.BlendingMode.withinWindow + )) : AnyView(EmptyView()) + ) + }) .animation(.easeOut(duration: 0.2), value: workspace.openFileItems) .buttonStyle(.plain) .id(item.id)