diff --git a/CodeEdit.xcodeproj/project.pbxproj b/CodeEdit.xcodeproj/project.pbxproj index 667d25541b..bf61b140f5 100644 --- a/CodeEdit.xcodeproj/project.pbxproj +++ b/CodeEdit.xcodeproj/project.pbxproj @@ -32,7 +32,7 @@ 2806E9022979588B000040F4 /* Contributor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2806E9012979588B000040F4 /* Contributor.swift */; }; 2806E904297958B9000040F4 /* ContributorRowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2806E903297958B9000040F4 /* ContributorRowView.swift */; }; 2813F93827ECC4AA00E305E4 /* FindNavigatorResultList.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7E201B327E9989900CB86D0 /* FindNavigatorResultList.swift */; }; - 2813F93927ECC4C300E305E4 /* NavigatorSidebarView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 287776E627E3413200D46668 /* NavigatorSidebarView.swift */; }; + 2813F93927ECC4C300E305E4 /* NavigatorAreaView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 287776E627E3413200D46668 /* NavigatorAreaView.swift */; }; 2816F594280CF50500DD548B /* CodeEditSymbols in Frameworks */ = {isa = PBXBuildFile; productRef = 2816F593280CF50500DD548B /* CodeEditSymbols */; }; 283BDCBD2972EEBD002AFF81 /* Package.resolved in Resources */ = {isa = PBXBuildFile; fileRef = 283BDCBC2972EEBD002AFF81 /* Package.resolved */; }; 283BDCC52972F236002AFF81 /* AcknowledgementsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 283BDCC42972F236002AFF81 /* AcknowledgementsTests.swift */; }; @@ -92,9 +92,9 @@ 5878DAA6291AE76700DD95A3 /* QuickOpenPreviewView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5878DAA2291AE76700DD95A3 /* QuickOpenPreviewView.swift */; }; 5878DAA7291AE76700DD95A3 /* QuickOpenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5878DAA3291AE76700DD95A3 /* QuickOpenViewModel.swift */; }; 5878DAA8291AE76700DD95A3 /* QuickOpenItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5878DAA4291AE76700DD95A3 /* QuickOpenItem.swift */; }; - 5878DAB0291D627C00DD95A3 /* PathBarMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5878DAAD291D627C00DD95A3 /* PathBarMenu.swift */; }; - 5878DAB1291D627C00DD95A3 /* PathBarComponent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5878DAAE291D627C00DD95A3 /* PathBarComponent.swift */; }; - 5878DAB2291D627C00DD95A3 /* PathBarView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5878DAAF291D627C00DD95A3 /* PathBarView.swift */; }; + 5878DAB0291D627C00DD95A3 /* EditorPathBarMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5878DAAD291D627C00DD95A3 /* EditorPathBarMenu.swift */; }; + 5878DAB1291D627C00DD95A3 /* EditorPathBarComponent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5878DAAE291D627C00DD95A3 /* EditorPathBarComponent.swift */; }; + 5878DAB2291D627C00DD95A3 /* EditorPathBarView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5878DAAF291D627C00DD95A3 /* EditorPathBarView.swift */; }; 58798218292D92370085B254 /* String+SafeOffset.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58798213292D92370085B254 /* String+SafeOffset.swift */; }; 58798219292D92370085B254 /* SearchModeModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58798215292D92370085B254 /* SearchModeModel.swift */; }; 5879821A292D92370085B254 /* SearchResultModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58798216292D92370085B254 /* SearchResultModel.swift */; }; @@ -189,7 +189,7 @@ 587B9E9829301D8F00AC7927 /* GitCommit.swift in Sources */ = {isa = PBXBuildFile; fileRef = 587B9E5329301D8F00AC7927 /* GitCommit.swift */; }; 587B9E9929301D8F00AC7927 /* GitChangedFile.swift in Sources */ = {isa = PBXBuildFile; fileRef = 587B9E5429301D8F00AC7927 /* GitChangedFile.swift */; }; 587B9E9A29301D8F00AC7927 /* GitType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 587B9E5529301D8F00AC7927 /* GitType.swift */; }; - 587FB99029C1246400B519DD /* TabBarItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 587FB98F29C1246400B519DD /* TabBarItemView.swift */; }; + 587FB99029C1246400B519DD /* EditorTabView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 587FB98F29C1246400B519DD /* EditorTabView.swift */; }; 58822524292C280D00E83CDE /* StatusBarView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58822509292C280D00E83CDE /* StatusBarView.swift */; }; 58822525292C280D00E83CDE /* StatusBarMenuStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5882250B292C280D00E83CDE /* StatusBarMenuStyle.swift */; }; 58822526292C280D00E83CDE /* StatusBarBreakpointButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5882250C292C280D00E83CDE /* StatusBarBreakpointButton.swift */; }; @@ -198,13 +198,13 @@ 58822529292C280D00E83CDE /* StatusBarLineEndSelector.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5882250F292C280D00E83CDE /* StatusBarLineEndSelector.swift */; }; 5882252A292C280D00E83CDE /* StatusBarToggleDrawerButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58822510292C280D00E83CDE /* StatusBarToggleDrawerButton.swift */; }; 5882252B292C280D00E83CDE /* StatusBarCursorLocationLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58822511292C280D00E83CDE /* StatusBarCursorLocationLabel.swift */; }; - 5882252C292C280D00E83CDE /* DebugAreaView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58822513292C280D00E83CDE /* DebugAreaView.swift */; }; + 5882252C292C280D00E83CDE /* UtilityAreaView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58822513292C280D00E83CDE /* UtilityAreaView.swift */; }; 5882252D292C280D00E83CDE /* StatusBarSplitTerminalButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58822515292C280D00E83CDE /* StatusBarSplitTerminalButton.swift */; }; 5882252E292C280D00E83CDE /* StatusBarMaximizeButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58822516292C280D00E83CDE /* StatusBarMaximizeButton.swift */; }; 5882252F292C280D00E83CDE /* StatusBarClearButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58822517292C280D00E83CDE /* StatusBarClearButton.swift */; }; 58822530292C280D00E83CDE /* FilterTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58822518292C280D00E83CDE /* FilterTextField.swift */; }; 58822531292C280D00E83CDE /* View+isHovering.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5882251A292C280D00E83CDE /* View+isHovering.swift */; }; - 58822532292C280D00E83CDE /* DebugAreaViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5882251C292C280D00E83CDE /* DebugAreaViewModel.swift */; }; + 58822532292C280D00E83CDE /* UtilityAreaViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5882251C292C280D00E83CDE /* UtilityAreaViewModel.swift */; }; 58822534292C280D00E83CDE /* CursorLocation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5882251E292C280D00E83CDE /* CursorLocation.swift */; }; 588847632992A2A200996D95 /* CEWorkspaceFile.swift in Sources */ = {isa = PBXBuildFile; fileRef = 588847622992A2A200996D95 /* CEWorkspaceFile.swift */; }; 588847692992ABCA00996D95 /* Array+CEWorkspaceFile.swift in Sources */ = {isa = PBXBuildFile; fileRef = 588847682992ABCA00996D95 /* Array+CEWorkspaceFile.swift */; }; @@ -215,8 +215,8 @@ 58A5DFA229339F6400D1BD5D /* KeybindingManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58A5DF9E29339F6400D1BD5D /* KeybindingManager.swift */; }; 58A5DFA329339F6400D1BD5D /* CommandManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58A5DF9F29339F6400D1BD5D /* CommandManager.swift */; }; 58A5DFA529339F6400D1BD5D /* default_keybindings.json in Resources */ = {isa = PBXBuildFile; fileRef = 58A5DFA129339F6400D1BD5D /* default_keybindings.json */; }; - 58AFAA2E2933C69E00482B53 /* TabBarItemRepresentable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58AFAA2C2933C69E00482B53 /* TabBarItemRepresentable.swift */; }; - 58AFAA2F2933C69E00482B53 /* TabBarItemID.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58AFAA2D2933C69E00482B53 /* TabBarItemID.swift */; }; + 58AFAA2E2933C69E00482B53 /* EditorTabRepresentable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58AFAA2C2933C69E00482B53 /* EditorTabRepresentable.swift */; }; + 58AFAA2F2933C69E00482B53 /* EditorItemID.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58AFAA2D2933C69E00482B53 /* EditorItemID.swift */; }; 58D01C94293167DC00C5B6B4 /* Color+HEX.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58D01C88293167DC00C5B6B4 /* Color+HEX.swift */; }; 58D01C95293167DC00C5B6B4 /* Bundle+Info.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58D01C89293167DC00C5B6B4 /* Bundle+Info.swift */; }; 58D01C96293167DC00C5B6B4 /* Date+Formatted.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58D01C8A293167DC00C5B6B4 /* Date+Formatted.swift */; }; @@ -247,17 +247,17 @@ 6C049A372A49E2DB00D42923 /* DirectoryEventStream.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C049A362A49E2DB00D42923 /* DirectoryEventStream.swift */; }; 6C05A8AF284D0CA3007F4EAA /* WorkspaceDocument+Listeners.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C05A8AE284D0CA3007F4EAA /* WorkspaceDocument+Listeners.swift */; }; 6C092EC62A4E803300489202 /* CodeEditTextView in Frameworks */ = {isa = PBXBuildFile; productRef = 6C092EC52A4E803300489202 /* CodeEditTextView */; }; - 6C092EDA2A53A58600489202 /* TabGroup+StateRestoration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C092ED92A53A58600489202 /* TabGroup+StateRestoration.swift */; }; + 6C092EDA2A53A58600489202 /* EditorLayout+StateRestoration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C092ED92A53A58600489202 /* EditorLayout+StateRestoration.swift */; }; 6C092EE02A53BFCF00489202 /* WorkspaceStateKey.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C092EDF2A53BFCF00489202 /* WorkspaceStateKey.swift */; }; 6C0D0C6829E861B000AE4D3F /* SettingsSidebarFix.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C0D0C6729E861B000AE4D3F /* SettingsSidebarFix.swift */; }; 6C0F3A3C2A1D0D5000223D19 /* CodeEditKit in Frameworks */ = {isa = PBXBuildFile; productRef = 6C0F3A3B2A1D0D5000223D19 /* CodeEditKit */; }; 6C147C4029A328BC0089B630 /* SplitViewData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C147C3F29A328560089B630 /* SplitViewData.swift */; }; - 6C147C4129A328BF0089B630 /* TabGroup.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C147C3E29A3281D0089B630 /* TabGroup.swift */; }; - 6C147C4229A328C10089B630 /* TabGroupData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C147C3D29A3281D0089B630 /* TabGroupData.swift */; }; + 6C147C4129A328BF0089B630 /* EditorLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C147C3E29A3281D0089B630 /* EditorLayout.swift */; }; + 6C147C4229A328C10089B630 /* Editor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C147C3D29A3281D0089B630 /* Editor.swift */; }; 6C147C4529A329350089B630 /* OrderedCollections in Frameworks */ = {isa = PBXBuildFile; productRef = 6C147C4429A329350089B630 /* OrderedCollections */; }; - 6C147C4929A32A080089B630 /* EditorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C147C4829A32A080089B630 /* EditorView.swift */; }; + 6C147C4929A32A080089B630 /* EditorLayoutView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C147C4829A32A080089B630 /* EditorLayoutView.swift */; }; 6C147C4B29A32A7B0089B630 /* Environment+SplitEditor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C147C4A29A32A7B0089B630 /* Environment+SplitEditor.swift */; }; - 6C147C4D29A32AA30089B630 /* WorkspaceTabGroupView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C147C4C29A32AA30089B630 /* WorkspaceTabGroupView.swift */; }; + 6C147C4D29A32AA30089B630 /* EditorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C147C4C29A32AA30089B630 /* EditorView.swift */; }; 6C14CEB028777D3C001468FE /* FindNavigatorListViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C14CEAF28777D3C001468FE /* FindNavigatorListViewController.swift */; }; 6C14CEB32877A68F001468FE /* FindNavigatorMatchListCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C14CEB22877A68F001468FE /* FindNavigatorMatchListCell.swift */; }; 6C18620A298BF5A800C663EA /* RecentProjectsListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C186209298BF5A800C663EA /* RecentProjectsListView.swift */; }; @@ -306,7 +306,7 @@ 6C82D6B929BFE34900495C54 /* HelpCommands.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C82D6B829BFE34900495C54 /* HelpCommands.swift */; }; 6C82D6BC29C00CD900495C54 /* FirstResponderPropertyWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C82D6BB29C00CD900495C54 /* FirstResponderPropertyWrapper.swift */; }; 6C82D6C629C012AD00495C54 /* NSApp+openWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C82D6C529C012AD00495C54 /* NSApp+openWindow.swift */; }; - 6C91D57229B176FF0059A90D /* TabManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C91D57129B176FF0059A90D /* TabManager.swift */; }; + 6C91D57229B176FF0059A90D /* EditorManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C91D57129B176FF0059A90D /* EditorManager.swift */; }; 6C97EBCC2978760400302F95 /* AcknowledgementsWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C97EBCB2978760400302F95 /* AcknowledgementsWindowController.swift */; }; 6CAAF68A29BC9C2300A1F48A /* (null) in Sources */ = {isa = PBXBuildFile; }; 6CAAF69229BCC71C00A1F48A /* (null) in Sources */ = {isa = PBXBuildFile; }; @@ -316,13 +316,13 @@ 6CB9144B29BEC7F100BC47F2 /* (null) in Sources */ = {isa = PBXBuildFile; }; 6CBA0D512A1BF524002C6FAA /* SegmentedControlImproved.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CBA0D502A1BF524002C6FAA /* SegmentedControlImproved.swift */; }; 6CBD1BC62978DE53006639D5 /* Font+Caption3.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CBD1BC52978DE53006639D5 /* Font+Caption3.swift */; }; - 6CC9E4B229B5669900C97388 /* Environment+ActiveTabGroup.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CC9E4B129B5669900C97388 /* Environment+ActiveTabGroup.swift */; }; + 6CC9E4B229B5669900C97388 /* Environment+ActiveEditor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CC9E4B129B5669900C97388 /* Environment+ActiveEditor.swift */; }; 6CD0375F2A3504540071C4DA /* FuzzySearch.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CD0375E2A3504540071C4DA /* FuzzySearch.swift */; }; 6CD03B6A29FC773F001BD1D0 /* SettingsInjector.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CD03B6929FC773F001BD1D0 /* SettingsInjector.swift */; }; 6CDA84AD284C1BA000C1CC3A /* TabBarContextMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CDA84AC284C1BA000C1CC3A /* TabBarContextMenu.swift */; }; 6CDEFC9629E22C2700B7C684 /* Introspect in Frameworks */ = {isa = PBXBuildFile; productRef = 6CDEFC9529E22C2700B7C684 /* Introspect */; }; 6CE622692A2A174A0013085C /* InspectorTab.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CE622682A2A174A0013085C /* InspectorTab.swift */; }; - 6CE6226B2A2A1C730013085C /* DebugAreaTab.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CE6226A2A2A1C730013085C /* DebugAreaTab.swift */; }; + 6CE6226B2A2A1C730013085C /* UtilityAreaTab.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CE6226A2A2A1C730013085C /* UtilityAreaTab.swift */; }; 6CE6226E2A2A1CDE0013085C /* NavigatorTab.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CE6226D2A2A1CDE0013085C /* NavigatorTab.swift */; }; 6CED16E42A3E660D000EC962 /* String+Lines.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CED16E32A3E660D000EC962 /* String+Lines.swift */; }; 6CFF967429BEBCC300182D6F /* FindCommands.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CFF967329BEBCC300182D6F /* FindCommands.swift */; }; @@ -340,14 +340,14 @@ B61A606929F4481A009B43F9 /* MonospacedFontPicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = B61A606829F4481A009B43F9 /* MonospacedFontPicker.swift */; }; B61DA9DF29D929E100BF4A43 /* GeneralSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B61DA9DE29D929E100BF4A43 /* GeneralSettingsView.swift */; }; B62AEDAA2A1FCBE5009A9F52 /* AreaTabBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = B62AEDA92A1FCBE5009A9F52 /* AreaTabBar.swift */; }; - B62AEDB32A1FD95B009A9F52 /* DebugAreaTerminalView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B62AEDB22A1FD95B009A9F52 /* DebugAreaTerminalView.swift */; }; - B62AEDB52A1FE295009A9F52 /* DebugAreaDebugView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B62AEDB42A1FE295009A9F52 /* DebugAreaDebugView.swift */; }; - B62AEDB82A1FE2DC009A9F52 /* DebugAreaOutputView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B62AEDB72A1FE2DC009A9F52 /* DebugAreaOutputView.swift */; }; - B62AEDBC2A210DBB009A9F52 /* DebugAreaTerminalTab.swift in Sources */ = {isa = PBXBuildFile; fileRef = B62AEDBB2A210DBB009A9F52 /* DebugAreaTerminalTab.swift */; }; - B62AEDC92A2704F3009A9F52 /* DebugAreaTabView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B62AEDC82A2704F3009A9F52 /* DebugAreaTabView.swift */; }; + B62AEDB32A1FD95B009A9F52 /* UtilityAreaTerminalView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B62AEDB22A1FD95B009A9F52 /* UtilityAreaTerminalView.swift */; }; + B62AEDB52A1FE295009A9F52 /* UtilityAreaDebugView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B62AEDB42A1FE295009A9F52 /* UtilityAreaDebugView.swift */; }; + B62AEDB82A1FE2DC009A9F52 /* UtilityAreaOutputView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B62AEDB72A1FE2DC009A9F52 /* UtilityAreaOutputView.swift */; }; + B62AEDBC2A210DBB009A9F52 /* UtilityAreaTerminalTab.swift in Sources */ = {isa = PBXBuildFile; fileRef = B62AEDBB2A210DBB009A9F52 /* UtilityAreaTerminalTab.swift */; }; + B62AEDC92A2704F3009A9F52 /* UtilityAreaTabView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B62AEDC82A2704F3009A9F52 /* UtilityAreaTabView.swift */; }; B62AEDD12A27B264009A9F52 /* View+paneToolbar.swift in Sources */ = {isa = PBXBuildFile; fileRef = B62AEDD02A27B264009A9F52 /* View+paneToolbar.swift */; }; B62AEDD42A27B29F009A9F52 /* PaneToolbar.swift in Sources */ = {isa = PBXBuildFile; fileRef = B62AEDD32A27B29F009A9F52 /* PaneToolbar.swift */; }; - B62AEDD72A27B3D0009A9F52 /* DebugAreaTabViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B62AEDD62A27B3D0009A9F52 /* DebugAreaTabViewModel.swift */; }; + B62AEDD72A27B3D0009A9F52 /* UtilityAreaTabViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B62AEDD62A27B3D0009A9F52 /* UtilityAreaTabViewModel.swift */; }; B62AEDDC2A27C1B3009A9F52 /* OSLogType+Color.swift in Sources */ = {isa = PBXBuildFile; fileRef = B62AEDDA2A27C1B3009A9F52 /* OSLogType+Color.swift */; }; B640A99E29E2184700715F20 /* SettingsForm.swift in Sources */ = {isa = PBXBuildFile; fileRef = B640A99D29E2184700715F20 /* SettingsForm.swift */; }; B640A9A129E2188F00715F20 /* View+NavigationBarBackButtonVisible.swift in Sources */ = {isa = PBXBuildFile; fileRef = B640A9A029E2188F00715F20 /* View+NavigationBarBackButtonVisible.swift */; }; @@ -363,9 +363,9 @@ B68C7C212A01DEFE004EA6D6 /* GitHubComment.swift in Sources */ = {isa = PBXBuildFile; fileRef = B68C7C202A01DEFE004EA6D6 /* GitHubComment.swift */; }; B697937A29FF5668002027EC /* AccountsSettingsAccountLink.swift in Sources */ = {isa = PBXBuildFile; fileRef = B697937929FF5668002027EC /* AccountsSettingsAccountLink.swift */; }; B6A43C5D29FC4AF00027E0E0 /* CreateSSHKeyView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6A43C5C29FC4AF00027E0E0 /* CreateSSHKeyView.swift */; }; - B6C6A42A297716A500A3D28F /* TabBarItemCloseButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6C6A429297716A500A3D28F /* TabBarItemCloseButton.swift */; }; - B6C6A42E29771A8D00A3D28F /* TabBarItemButtonStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6C6A42D29771A8D00A3D28F /* TabBarItemButtonStyle.swift */; }; - B6C6A43029771F7100A3D28F /* TabBarItemBackground.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6C6A42F29771F7100A3D28F /* TabBarItemBackground.swift */; }; + B6C6A42A297716A500A3D28F /* EditorTabCloseButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6C6A429297716A500A3D28F /* EditorTabCloseButton.swift */; }; + B6C6A42E29771A8D00A3D28F /* EditorTabButtonStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6C6A42D29771A8D00A3D28F /* EditorTabButtonStyle.swift */; }; + B6C6A43029771F7100A3D28F /* EditorTabBackground.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6C6A42F29771F7100A3D28F /* EditorTabBackground.swift */; }; B6D7EA592971078500301FAC /* InspectorSection.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6D7EA582971078500301FAC /* InspectorSection.swift */; }; B6D7EA5C297107DD00301FAC /* InspectorField.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6D7EA5B297107DD00301FAC /* InspectorField.swift */; }; B6E41C7029DD157F0088F9F4 /* AccountsSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6E41C6F29DD157F0088F9F4 /* AccountsSettingsView.swift */; }; @@ -384,7 +384,7 @@ B6EA1FFD29DB792C001BF195 /* ThemeSettingsColorPreview.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6EA1FFC29DB792C001BF195 /* ThemeSettingsColorPreview.swift */; }; B6EA200029DB7966001BF195 /* SettingsColorPicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6EA1FFF29DB7966001BF195 /* SettingsColorPicker.swift */; }; B6EA200229DB7F81001BF195 /* View+ConstrainHeightToWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6EA200129DB7F81001BF195 /* View+ConstrainHeightToWindow.swift */; }; - B6EE989027E8879A00CDD8AB /* InspectorSidebarView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6EE988F27E8879A00CDD8AB /* InspectorSidebarView.swift */; }; + B6EE989027E8879A00CDD8AB /* InspectorAreaView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6EE988F27E8879A00CDD8AB /* InspectorAreaView.swift */; }; B6F0517029D9E36800D72287 /* LocationsSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6F0516F29D9E36800D72287 /* LocationsSettingsView.swift */; }; B6F0517729D9E3AD00D72287 /* SourceControlGeneralView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6F0517629D9E3AD00D72287 /* SourceControlGeneralView.swift */; }; B6F0517929D9E3C900D72287 /* SourceControlGitView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6F0517829D9E3C900D72287 /* SourceControlGitView.swift */; }; @@ -501,7 +501,7 @@ 285FEC6F27FE4B9800E57D53 /* ProjectNavigatorTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProjectNavigatorTableViewCell.swift; sourceTree = ""; }; 285FEC7127FE4EEF00E57D53 /* ProjectNavigatorMenu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProjectNavigatorMenu.swift; sourceTree = ""; }; 286471AA27ED51FD0039369D /* ProjectNavigatorView.swift */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.swift; path = ProjectNavigatorView.swift; sourceTree = ""; tabWidth = 4; }; - 287776E627E3413200D46668 /* NavigatorSidebarView.swift */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.swift; path = NavigatorSidebarView.swift; sourceTree = ""; tabWidth = 4; }; + 287776E627E3413200D46668 /* NavigatorAreaView.swift */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.swift; path = NavigatorAreaView.swift; sourceTree = ""; tabWidth = 4; }; 287776E827E34BC700D46668 /* TabBarView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabBarView.swift; sourceTree = ""; }; 2897E1C62979A29200741E32 /* TrackableScrollView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrackableScrollView.swift; sourceTree = ""; }; 28A50FFF281673530087B0CC /* codeedit-xcode-dark.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "codeedit-xcode-dark.json"; sourceTree = ""; }; @@ -554,9 +554,9 @@ 5878DAA2291AE76700DD95A3 /* QuickOpenPreviewView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QuickOpenPreviewView.swift; sourceTree = ""; }; 5878DAA3291AE76700DD95A3 /* QuickOpenViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QuickOpenViewModel.swift; sourceTree = ""; }; 5878DAA4291AE76700DD95A3 /* QuickOpenItem.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QuickOpenItem.swift; sourceTree = ""; }; - 5878DAAD291D627C00DD95A3 /* PathBarMenu.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PathBarMenu.swift; sourceTree = ""; }; - 5878DAAE291D627C00DD95A3 /* PathBarComponent.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PathBarComponent.swift; sourceTree = ""; }; - 5878DAAF291D627C00DD95A3 /* PathBarView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PathBarView.swift; sourceTree = ""; }; + 5878DAAD291D627C00DD95A3 /* EditorPathBarMenu.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EditorPathBarMenu.swift; sourceTree = ""; }; + 5878DAAE291D627C00DD95A3 /* EditorPathBarComponent.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EditorPathBarComponent.swift; sourceTree = ""; }; + 5878DAAF291D627C00DD95A3 /* EditorPathBarView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EditorPathBarView.swift; sourceTree = ""; }; 58798213292D92370085B254 /* String+SafeOffset.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "String+SafeOffset.swift"; sourceTree = ""; }; 58798215292D92370085B254 /* SearchModeModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SearchModeModel.swift; sourceTree = ""; }; 58798216292D92370085B254 /* SearchResultModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SearchResultModel.swift; sourceTree = ""; }; @@ -651,7 +651,7 @@ 587B9E5329301D8F00AC7927 /* GitCommit.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GitCommit.swift; sourceTree = ""; }; 587B9E5429301D8F00AC7927 /* GitChangedFile.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GitChangedFile.swift; sourceTree = ""; }; 587B9E5529301D8F00AC7927 /* GitType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GitType.swift; sourceTree = ""; }; - 587FB98F29C1246400B519DD /* TabBarItemView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TabBarItemView.swift; sourceTree = ""; }; + 587FB98F29C1246400B519DD /* EditorTabView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EditorTabView.swift; sourceTree = ""; }; 58822509292C280D00E83CDE /* StatusBarView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StatusBarView.swift; sourceTree = ""; }; 5882250B292C280D00E83CDE /* StatusBarMenuStyle.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StatusBarMenuStyle.swift; sourceTree = ""; }; 5882250C292C280D00E83CDE /* StatusBarBreakpointButton.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StatusBarBreakpointButton.swift; sourceTree = ""; }; @@ -660,13 +660,13 @@ 5882250F292C280D00E83CDE /* StatusBarLineEndSelector.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StatusBarLineEndSelector.swift; sourceTree = ""; }; 58822510292C280D00E83CDE /* StatusBarToggleDrawerButton.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StatusBarToggleDrawerButton.swift; sourceTree = ""; }; 58822511292C280D00E83CDE /* StatusBarCursorLocationLabel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StatusBarCursorLocationLabel.swift; sourceTree = ""; }; - 58822513292C280D00E83CDE /* DebugAreaView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DebugAreaView.swift; sourceTree = ""; }; + 58822513292C280D00E83CDE /* UtilityAreaView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UtilityAreaView.swift; sourceTree = ""; }; 58822515292C280D00E83CDE /* StatusBarSplitTerminalButton.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StatusBarSplitTerminalButton.swift; sourceTree = ""; }; 58822516292C280D00E83CDE /* StatusBarMaximizeButton.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StatusBarMaximizeButton.swift; sourceTree = ""; }; 58822517292C280D00E83CDE /* StatusBarClearButton.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StatusBarClearButton.swift; sourceTree = ""; }; 58822518292C280D00E83CDE /* FilterTextField.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FilterTextField.swift; sourceTree = ""; }; 5882251A292C280D00E83CDE /* View+isHovering.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "View+isHovering.swift"; sourceTree = ""; }; - 5882251C292C280D00E83CDE /* DebugAreaViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DebugAreaViewModel.swift; sourceTree = ""; }; + 5882251C292C280D00E83CDE /* UtilityAreaViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UtilityAreaViewModel.swift; sourceTree = ""; }; 5882251E292C280D00E83CDE /* CursorLocation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CursorLocation.swift; sourceTree = ""; }; 588847622992A2A200996D95 /* CEWorkspaceFile.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CEWorkspaceFile.swift; sourceTree = ""; }; 588847682992ABCA00996D95 /* Array+CEWorkspaceFile.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Array+CEWorkspaceFile.swift"; sourceTree = ""; }; @@ -678,8 +678,8 @@ 58A5DF9E29339F6400D1BD5D /* KeybindingManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KeybindingManager.swift; sourceTree = ""; }; 58A5DF9F29339F6400D1BD5D /* CommandManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CommandManager.swift; sourceTree = ""; }; 58A5DFA129339F6400D1BD5D /* default_keybindings.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = default_keybindings.json; sourceTree = ""; }; - 58AFAA2C2933C69E00482B53 /* TabBarItemRepresentable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TabBarItemRepresentable.swift; sourceTree = ""; }; - 58AFAA2D2933C69E00482B53 /* TabBarItemID.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TabBarItemID.swift; sourceTree = ""; }; + 58AFAA2C2933C69E00482B53 /* EditorTabRepresentable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EditorTabRepresentable.swift; sourceTree = ""; }; + 58AFAA2D2933C69E00482B53 /* EditorItemID.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EditorItemID.swift; sourceTree = ""; }; 58D01C88293167DC00C5B6B4 /* Color+HEX.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Color+HEX.swift"; sourceTree = ""; }; 58D01C89293167DC00C5B6B4 /* Bundle+Info.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Bundle+Info.swift"; sourceTree = ""; }; 58D01C8A293167DC00C5B6B4 /* Date+Formatted.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Date+Formatted.swift"; sourceTree = ""; }; @@ -708,15 +708,15 @@ 5C4BB1E028212B1E00A92FB2 /* World.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = World.swift; sourceTree = ""; }; 6C049A362A49E2DB00D42923 /* DirectoryEventStream.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DirectoryEventStream.swift; sourceTree = ""; }; 6C05A8AE284D0CA3007F4EAA /* WorkspaceDocument+Listeners.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "WorkspaceDocument+Listeners.swift"; sourceTree = ""; }; - 6C092ED92A53A58600489202 /* TabGroup+StateRestoration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "TabGroup+StateRestoration.swift"; sourceTree = ""; }; + 6C092ED92A53A58600489202 /* EditorLayout+StateRestoration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "EditorLayout+StateRestoration.swift"; sourceTree = ""; }; 6C092EDF2A53BFCF00489202 /* WorkspaceStateKey.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WorkspaceStateKey.swift; sourceTree = ""; }; 6C0D0C6729E861B000AE4D3F /* SettingsSidebarFix.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsSidebarFix.swift; sourceTree = ""; }; - 6C147C3D29A3281D0089B630 /* TabGroupData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabGroupData.swift; sourceTree = ""; }; - 6C147C3E29A3281D0089B630 /* TabGroup.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabGroup.swift; sourceTree = ""; }; + 6C147C3D29A3281D0089B630 /* Editor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Editor.swift; sourceTree = ""; }; + 6C147C3E29A3281D0089B630 /* EditorLayout.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditorLayout.swift; sourceTree = ""; }; 6C147C3F29A328560089B630 /* SplitViewData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SplitViewData.swift; sourceTree = ""; }; - 6C147C4829A32A080089B630 /* EditorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditorView.swift; sourceTree = ""; }; + 6C147C4829A32A080089B630 /* EditorLayoutView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditorLayoutView.swift; sourceTree = ""; }; 6C147C4A29A32A7B0089B630 /* Environment+SplitEditor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Environment+SplitEditor.swift"; sourceTree = ""; }; - 6C147C4C29A32AA30089B630 /* WorkspaceTabGroupView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WorkspaceTabGroupView.swift; sourceTree = ""; }; + 6C147C4C29A32AA30089B630 /* EditorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditorView.swift; sourceTree = ""; }; 6C14CEAF28777D3C001468FE /* FindNavigatorListViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FindNavigatorListViewController.swift; sourceTree = ""; }; 6C14CEB22877A68F001468FE /* FindNavigatorMatchListCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FindNavigatorMatchListCell.swift; sourceTree = ""; }; 6C186209298BF5A800C663EA /* RecentProjectsListView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RecentProjectsListView.swift; sourceTree = ""; }; @@ -737,7 +737,6 @@ 6C578D8629CD345900DC73B2 /* ExtensionSceneView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExtensionSceneView.swift; sourceTree = ""; }; 6C578D8829CD36E400DC73B2 /* Commands+ForEach.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Commands+ForEach.swift"; sourceTree = ""; }; 6C578D8B29CD372700DC73B2 /* ExtensionCommands.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExtensionCommands.swift; sourceTree = ""; }; - 6C5AB9D629C1496E003B5F96 /* SceneID.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneID.swift; sourceTree = ""; }; 6C5B63DD29C76213005454BA /* WindowCodeFileView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WindowCodeFileView.swift; sourceTree = ""; }; 6C5BE51B2A3D542B002DA0FC /* FeatureFlagsSettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FeatureFlagsSettingsView.swift; sourceTree = ""; }; 6C5BE51D2A3D545F002DA0FC /* FeatureFlagsSettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FeatureFlagsSettings.swift; sourceTree = ""; }; @@ -757,18 +756,18 @@ 6C82D6B829BFE34900495C54 /* HelpCommands.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HelpCommands.swift; sourceTree = ""; }; 6C82D6BB29C00CD900495C54 /* FirstResponderPropertyWrapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FirstResponderPropertyWrapper.swift; sourceTree = ""; }; 6C82D6C529C012AD00495C54 /* NSApp+openWindow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSApp+openWindow.swift"; sourceTree = ""; }; - 6C91D57129B176FF0059A90D /* TabManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabManager.swift; sourceTree = ""; }; + 6C91D57129B176FF0059A90D /* EditorManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditorManager.swift; sourceTree = ""; }; 6C97EBCB2978760400302F95 /* AcknowledgementsWindowController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AcknowledgementsWindowController.swift; sourceTree = ""; }; 6CABB19C29C5591D00340467 /* NSTableViewWrapper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = NSTableViewWrapper.swift; path = CodeEdit/Features/QuickOpen/Views/NSTableViewWrapper.swift; sourceTree = SOURCE_ROOT; }; 6CABB1A029C5593800340467 /* OverlayView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OverlayView.swift; sourceTree = ""; }; 6CBA0D502A1BF524002C6FAA /* SegmentedControlImproved.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SegmentedControlImproved.swift; sourceTree = ""; }; 6CBD1BC52978DE53006639D5 /* Font+Caption3.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Font+Caption3.swift"; sourceTree = ""; }; - 6CC9E4B129B5669900C97388 /* Environment+ActiveTabGroup.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Environment+ActiveTabGroup.swift"; sourceTree = ""; }; + 6CC9E4B129B5669900C97388 /* Environment+ActiveEditor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Environment+ActiveEditor.swift"; sourceTree = ""; }; 6CD0375E2A3504540071C4DA /* FuzzySearch.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FuzzySearch.swift; sourceTree = ""; }; 6CD03B6929FC773F001BD1D0 /* SettingsInjector.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsInjector.swift; sourceTree = ""; }; 6CDA84AC284C1BA000C1CC3A /* TabBarContextMenu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabBarContextMenu.swift; sourceTree = ""; }; 6CE622682A2A174A0013085C /* InspectorTab.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InspectorTab.swift; sourceTree = ""; }; - 6CE6226A2A2A1C730013085C /* DebugAreaTab.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DebugAreaTab.swift; sourceTree = ""; }; + 6CE6226A2A2A1C730013085C /* UtilityAreaTab.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UtilityAreaTab.swift; sourceTree = ""; }; 6CE6226D2A2A1CDE0013085C /* NavigatorTab.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigatorTab.swift; sourceTree = ""; }; 6CED16E32A3E660D000EC962 /* String+Lines.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+Lines.swift"; sourceTree = ""; }; 6CFF967329BEBCC300182D6F /* FindCommands.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FindCommands.swift; sourceTree = ""; }; @@ -786,14 +785,14 @@ B61A606829F4481A009B43F9 /* MonospacedFontPicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MonospacedFontPicker.swift; sourceTree = ""; }; B61DA9DE29D929E100BF4A43 /* GeneralSettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GeneralSettingsView.swift; sourceTree = ""; }; B62AEDA92A1FCBE5009A9F52 /* AreaTabBar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AreaTabBar.swift; sourceTree = ""; }; - B62AEDB22A1FD95B009A9F52 /* DebugAreaTerminalView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DebugAreaTerminalView.swift; sourceTree = ""; }; - B62AEDB42A1FE295009A9F52 /* DebugAreaDebugView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DebugAreaDebugView.swift; sourceTree = ""; }; - B62AEDB72A1FE2DC009A9F52 /* DebugAreaOutputView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DebugAreaOutputView.swift; sourceTree = ""; }; - B62AEDBB2A210DBB009A9F52 /* DebugAreaTerminalTab.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DebugAreaTerminalTab.swift; sourceTree = ""; }; - B62AEDC82A2704F3009A9F52 /* DebugAreaTabView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DebugAreaTabView.swift; sourceTree = ""; }; + B62AEDB22A1FD95B009A9F52 /* UtilityAreaTerminalView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UtilityAreaTerminalView.swift; sourceTree = ""; }; + B62AEDB42A1FE295009A9F52 /* UtilityAreaDebugView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UtilityAreaDebugView.swift; sourceTree = ""; }; + B62AEDB72A1FE2DC009A9F52 /* UtilityAreaOutputView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UtilityAreaOutputView.swift; sourceTree = ""; }; + B62AEDBB2A210DBB009A9F52 /* UtilityAreaTerminalTab.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UtilityAreaTerminalTab.swift; sourceTree = ""; }; + B62AEDC82A2704F3009A9F52 /* UtilityAreaTabView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UtilityAreaTabView.swift; sourceTree = ""; }; B62AEDD02A27B264009A9F52 /* View+paneToolbar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "View+paneToolbar.swift"; sourceTree = ""; }; B62AEDD32A27B29F009A9F52 /* PaneToolbar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PaneToolbar.swift; sourceTree = ""; }; - B62AEDD62A27B3D0009A9F52 /* DebugAreaTabViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DebugAreaTabViewModel.swift; sourceTree = ""; }; + B62AEDD62A27B3D0009A9F52 /* UtilityAreaTabViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UtilityAreaTabViewModel.swift; sourceTree = ""; }; B62AEDDA2A27C1B3009A9F52 /* OSLogType+Color.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "OSLogType+Color.swift"; sourceTree = ""; }; B640A99D29E2184700715F20 /* SettingsForm.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsForm.swift; sourceTree = ""; }; B640A9A029E2188F00715F20 /* View+NavigationBarBackButtonVisible.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "View+NavigationBarBackButtonVisible.swift"; sourceTree = ""; }; @@ -814,9 +813,9 @@ B68C7C202A01DEFE004EA6D6 /* GitHubComment.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GitHubComment.swift; sourceTree = ""; }; B697937929FF5668002027EC /* AccountsSettingsAccountLink.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountsSettingsAccountLink.swift; sourceTree = ""; }; B6A43C5C29FC4AF00027E0E0 /* CreateSSHKeyView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreateSSHKeyView.swift; sourceTree = ""; }; - B6C6A429297716A500A3D28F /* TabBarItemCloseButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabBarItemCloseButton.swift; sourceTree = ""; }; - B6C6A42D29771A8D00A3D28F /* TabBarItemButtonStyle.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TabBarItemButtonStyle.swift; sourceTree = ""; }; - B6C6A42F29771F7100A3D28F /* TabBarItemBackground.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabBarItemBackground.swift; sourceTree = ""; }; + B6C6A429297716A500A3D28F /* EditorTabCloseButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditorTabCloseButton.swift; sourceTree = ""; }; + B6C6A42D29771A8D00A3D28F /* EditorTabButtonStyle.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EditorTabButtonStyle.swift; sourceTree = ""; }; + B6C6A42F29771F7100A3D28F /* EditorTabBackground.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditorTabBackground.swift; sourceTree = ""; }; B6D7EA582971078500301FAC /* InspectorSection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InspectorSection.swift; sourceTree = ""; }; B6D7EA5B297107DD00301FAC /* InspectorField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InspectorField.swift; sourceTree = ""; }; B6E41C6F29DD157F0088F9F4 /* AccountsSettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountsSettingsView.swift; sourceTree = ""; }; @@ -835,7 +834,7 @@ B6EA1FFC29DB792C001BF195 /* ThemeSettingsColorPreview.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThemeSettingsColorPreview.swift; sourceTree = ""; }; B6EA1FFF29DB7966001BF195 /* SettingsColorPicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsColorPicker.swift; sourceTree = ""; }; B6EA200129DB7F81001BF195 /* View+ConstrainHeightToWindow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "View+ConstrainHeightToWindow.swift"; sourceTree = ""; }; - B6EE988F27E8879A00CDD8AB /* InspectorSidebarView.swift */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.swift; path = InspectorSidebarView.swift; sourceTree = ""; tabWidth = 4; }; + B6EE988F27E8879A00CDD8AB /* InspectorAreaView.swift */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.swift; path = InspectorAreaView.swift; sourceTree = ""; tabWidth = 4; }; B6F0516F29D9E36800D72287 /* LocationsSettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationsSettingsView.swift; sourceTree = ""; }; B6F0517629D9E3AD00D72287 /* SourceControlGeneralView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SourceControlGeneralView.swift; sourceTree = ""; }; B6F0517829D9E3C900D72287 /* SourceControlGitView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SourceControlGitView.swift; sourceTree = ""; }; @@ -962,22 +961,12 @@ path = Repositories; sourceTree = ""; }; - 20D839AC280E0C9400B27357 /* Popover */ = { - isa = PBXGroup; - children = ( - 20D839AD280E0CA700B27357 /* HistoryPopoverView.swift */, - ); - path = Popover; - sourceTree = ""; - }; 20EBB4FF280C325000F3A5DA /* Views */ = { isa = PBXGroup; children = ( - 20D839AC280E0C9400B27357 /* Popover */, - 20EBB500280C325D00F3A5DA /* FileInspectorView.swift */, - 20EBB502280C327C00F3A5DA /* HistoryInspectorView.swift */, - 20EBB504280C329800F3A5DA /* HistoryInspectorItemView.swift */, - 200412EE280F3EAC00BCAF5C /* HistoryInspectorNoHistoryView.swift */, + B6EE988F27E8879A00CDD8AB /* InspectorAreaView.swift */, + B6D7EA582971078500301FAC /* InspectorSection.swift */, + B6D7EA5B297107DD00301FAC /* InspectorField.swift */, 20D839AA280DEB2900B27357 /* NoSelectionInspectorView.swift */, ); path = Views; @@ -986,7 +975,7 @@ 20EBB50B280C382800F3A5DA /* Models */ = { isa = PBXGroup; children = ( - 2072FA12280D74ED00C7F8D4 /* HistoryInspectorModel.swift */, + 6CE622682A2A174A0013085C /* InspectorTab.swift */, ); path = Models; sourceTree = ""; @@ -1065,7 +1054,7 @@ path = ProjectNavigator; sourceTree = ""; }; - 287776EA27E350A100D46668 /* NavigatorSidebar */ = { + 287776EA27E350A100D46668 /* NavigatorArea */ = { isa = PBXGroup; children = ( D7012EE627E757660001E1EF /* FindNavigator */, @@ -1076,17 +1065,15 @@ 6CE6226D2A2A1CDE0013085C /* NavigatorTab.swift */, 30E6D0002A6E505200A58B20 /* NavigatorSidebarViewModel.swift */, ); - path = NavigatorSidebar; + path = NavigatorArea; sourceTree = ""; }; - 287776EB27E350BA00D46668 /* Tabs */ = { + 287776EB27E350BA00D46668 /* TabBar */ = { isa = PBXGroup; children = ( - 6C147C3C29A328020089B630 /* TabGroup */, - 58AFAA272933C65C00482B53 /* Models */, 58AFAA262933C65000482B53 /* Views */, ); - path = Tabs; + path = TabBar; sourceTree = ""; }; 2BE487ED28245162003F3F64 /* OpenWithCodeEdit */ = { @@ -1188,21 +1175,20 @@ 58FD7603291EA1CB0051D6E4 /* Commands */, 284DC84B2978B5EB00BF2770 /* Contributors */, 043C321227E31FE8006AE443 /* Documents */, + 6C147C3C29A328020089B630 /* Editor */, 6C6BD6ED29CD123000235D17 /* Extensions */, 58798228292E30B90085B254 /* Feedback */, 587B9E0129301D8F00AC7927 /* Git */, + B6EE988E27E8877C00CDD8AB /* InspectorArea */, 58A5DF9D29339F6400D1BD5D /* Keybindings */, - 287776EA27E350A100D46668 /* NavigatorSidebar */, - B6EE988E27E8877C00CDD8AB /* InspectorSidebar */, - 58822512292C280D00E83CDE /* DebugArea */, - 5878DAAB291D627C00DD95A3 /* PathBar */, + 287776EA27E350A100D46668 /* NavigatorArea */, 5878DAA0291AE76700DD95A3 /* QuickOpen */, 58798210292D92370085B254 /* Search */, B67B270029D7868000FB9301 /* Settings */, 6C147C4729A329E50089B630 /* SplitView */, 588224FF292C280D00E83CDE /* StatusBar */, - 287776EB27E350BA00D46668 /* Tabs */, 5879827E292ED0FB0085B254 /* TerminalEmulator */, + 58822512292C280D00E83CDE /* UtilityArea */, 581BFB4B2926431000D251EC /* Welcome */, 6CAAF68F29BCC6F900A1F48A /* WindowCommands */, ); @@ -1405,9 +1391,9 @@ 5878DAAC291D627C00DD95A3 /* Views */ = { isa = PBXGroup; children = ( - 5878DAAD291D627C00DD95A3 /* PathBarMenu.swift */, - 5878DAAE291D627C00DD95A3 /* PathBarComponent.swift */, - 5878DAAF291D627C00DD95A3 /* PathBarView.swift */, + 5878DAAD291D627C00DD95A3 /* EditorPathBarMenu.swift */, + 5878DAAE291D627C00DD95A3 /* EditorPathBarComponent.swift */, + 5878DAAF291D627C00DD95A3 /* EditorPathBarView.swift */, ); path = Views; sourceTree = ""; @@ -1812,17 +1798,18 @@ path = StatusBarItems; sourceTree = ""; }; - 58822512292C280D00E83CDE /* DebugArea */ = { + 58822512292C280D00E83CDE /* UtilityArea */ = { isa = PBXGroup; children = ( + B676606A2AA973A500CD56B0 /* TerminalUtility */, + B676606B2AA973B200CD56B0 /* DebugUtility */, + B676606C2AA973C000CD56B0 /* OutputUtility */, + 58822514292C280D00E83CDE /* Toolbar */, + B676606D2AA9741900CD56B0 /* Models */, 58822539292C333600E83CDE /* ViewModels */, B62AEDB12A1FD7F0009A9F52 /* Views */, - 58822513292C280D00E83CDE /* DebugAreaView.swift */, - 6CE6226A2A2A1C730013085C /* DebugAreaTab.swift */, - B62AEDD02A27B264009A9F52 /* View+paneToolbar.swift */, - B62AEDD32A27B29F009A9F52 /* PaneToolbar.swift */, ); - path = DebugArea; + path = UtilityArea; sourceTree = ""; }; 58822514292C280D00E83CDE /* Toolbar */ = { @@ -1847,8 +1834,8 @@ 58822539292C333600E83CDE /* ViewModels */ = { isa = PBXGroup; children = ( - 5882251C292C280D00E83CDE /* DebugAreaViewModel.swift */, - B62AEDD62A27B3D0009A9F52 /* DebugAreaTabViewModel.swift */, + 5882251C292C280D00E83CDE /* UtilityAreaViewModel.swift */, + B62AEDD62A27B3D0009A9F52 /* UtilityAreaTabViewModel.swift */, ); path = ViewModels; sourceTree = ""; @@ -1903,17 +1890,13 @@ 58AFAA262933C65000482B53 /* Views */ = { isa = PBXGroup; children = ( - 287776E827E34BC700D46668 /* TabBarView.swift */, - B6C6A429297716A500A3D28F /* TabBarItemCloseButton.swift */, + DE513F51281B672D002260B9 /* TabBarAccessory.swift */, 6CDA84AC284C1BA000C1CC3A /* TabBarContextMenu.swift */, - B6C6A42D29771A8D00A3D28F /* TabBarItemButtonStyle.swift */, DE6F77862813625500D00A76 /* TabBarDivider.swift */, - 587FB98F29C1246400B519DD /* TabBarItemView.swift */, DE6405A52817734700881FDF /* TabBarNative.swift */, - DE513F51281B672D002260B9 /* TabBarAccessory.swift */, - DE513F53281DE5D0002260B9 /* TabBarXcode.swift */, - B6C6A42F29771F7100A3D28F /* TabBarItemBackground.swift */, B6E55C3A2A95368E003ECC7D /* TabBarShadow.swift */, + 287776E827E34BC700D46668 /* TabBarView.swift */, + DE513F53281DE5D0002260B9 /* TabBarXcode.swift */, ); path = Views; sourceTree = ""; @@ -1921,9 +1904,8 @@ 58AFAA272933C65C00482B53 /* Models */ = { isa = PBXGroup; children = ( - 6C91D57129B176FF0059A90D /* TabManager.swift */, - 58AFAA2D2933C69E00482B53 /* TabBarItemID.swift */, - 58AFAA2C2933C69E00482B53 /* TabBarItemRepresentable.swift */, + 58AFAA2D2933C69E00482B53 /* EditorItemID.swift */, + 58AFAA2C2933C69E00482B53 /* EditorTabRepresentable.swift */, ); path = Models; sourceTree = ""; @@ -1931,13 +1913,13 @@ 58D01C85293167DC00C5B6B4 /* Utils */ = { isa = PBXGroup; children = ( - 6C5C891A2A3F736500A94FE1 /* FocusedValues.swift */, - 587B9D54292FC27A00AC7927 /* FolderMonitor.swift */, 6C48D8EF2972DAC300D6D205 /* Environment */, 58D01C87293167DC00C5B6B4 /* Extensions */, 58D01C8F293167DC00C5B6B4 /* KeyChain */, 5831E3C92933E83400D5A6D2 /* Protocols */, 5875680E29316BDC00C965A3 /* ShellClient */, + 6C5C891A2A3F736500A94FE1 /* FocusedValues.swift */, + 587B9D54292FC27A00AC7927 /* FolderMonitor.swift */, ); path = Utils; sourceTree = ""; @@ -2039,7 +2021,6 @@ 6C092EDC2A53A63E00489202 /* Views */ = { isa = PBXGroup; children = ( - 6C147C4829A32A080089B630 /* EditorView.swift */, 6C53AAD729A6C4FD00EE9ED6 /* SplitView.swift */, 6C2C156029B4F52F00EA60A5 /* SplitViewModifiers.swift */, 6C2C155C29B4F4E500EA60A5 /* SplitViewReader.swift */, @@ -2060,16 +2041,16 @@ path = Model; sourceTree = ""; }; - 6C147C3C29A328020089B630 /* TabGroup */ = { + 6C147C3C29A328020089B630 /* Editor */ = { isa = PBXGroup; children = ( - 6C147C4C29A32AA30089B630 /* WorkspaceTabGroupView.swift */, - 6CC9E4B129B5669900C97388 /* Environment+ActiveTabGroup.swift */, - 6C147C3E29A3281D0089B630 /* TabGroup.swift */, - 6C147C3D29A3281D0089B630 /* TabGroupData.swift */, - 6C092ED92A53A58600489202 /* TabGroup+StateRestoration.swift */, + 5878DAAB291D627C00DD95A3 /* PathBar */, + 287776EB27E350BA00D46668 /* TabBar */, + B67660622AA961E900CD56B0 /* Tab */, + B67660642AA970ED00CD56B0 /* Models */, + B67660632AA970E300CD56B0 /* Views */, ); - path = TabGroup; + path = Editor; sourceTree = ""; }; 6C147C4729A329E50089B630 /* SplitView */ = { @@ -2204,13 +2185,11 @@ B62AEDB12A1FD7F0009A9F52 /* Views */ = { isa = PBXGroup; children = ( - 58822514292C280D00E83CDE /* Toolbar */, - B62AEDC82A2704F3009A9F52 /* DebugAreaTabView.swift */, - B62AEDB22A1FD95B009A9F52 /* DebugAreaTerminalView.swift */, - B62AEDBB2A210DBB009A9F52 /* DebugAreaTerminalTab.swift */, - B62AEDB42A1FE295009A9F52 /* DebugAreaDebugView.swift */, - B62AEDB72A1FE2DC009A9F52 /* DebugAreaOutputView.swift */, + B62AEDD32A27B29F009A9F52 /* PaneToolbar.swift */, + 58822513292C280D00E83CDE /* UtilityAreaView.swift */, + B62AEDC82A2704F3009A9F52 /* UtilityAreaTabView.swift */, B62AEDDA2A27C1B3009A9F52 /* OSLogType+Color.swift */, + B62AEDD02A27B264009A9F52 /* View+paneToolbar.swift */, ); path = Views; sourceTree = ""; @@ -2259,23 +2238,22 @@ B658FB2E27DA9E0F00EA4DBD /* CodeEdit */ = { isa = PBXGroup; children = ( - 3E0196712A392170002648D8 /* ShellIntegration */, + 28069DA527F5BD320016BC47 /* DefaultThemes */, 5831E3C52933E6CB00D5A6D2 /* Features */, D7211D4427E066D4008F2ED7 /* Localization */, B658FB3527DA9E1000EA4DBD /* Preview Content */, + 3E0196712A392170002648D8 /* ShellIntegration */, 58D01C85293167DC00C5B6B4 /* Utils */, - 6C5AB9D629C1496E003B5F96 /* SceneID.swift */, + B66A4E5529C918A0004573B4 /* SceneID.swift */, 0468438427DC76E200F8E88E /* AppDelegate.swift */, - 5C4BB1E028212B1E00A92FB2 /* World.swift */, B658FB3327DA9E1000EA4DBD /* Assets.xcassets */, B658FB3827DA9E1000EA4DBD /* CodeEdit.entitlements */, B66A4E4B29C9179B004573B4 /* CodeEditApp.swift */, - 6C7F38002A3EA71400217B83 /* WindowSplitView.swift */, 04660F6027E3A68A00477777 /* Info.plist */, - B66A4E5529C918A0004573B4 /* SceneID.swift */, - B658FB3127DA9E0F00EA4DBD /* WorkspaceView.swift */, 6C48D8F62972E5F300D6D205 /* WindowObserver.swift */, - 28069DA527F5BD320016BC47 /* DefaultThemes */, + 6C7F38002A3EA71400217B83 /* WindowSplitView.swift */, + B658FB3127DA9E0F00EA4DBD /* WorkspaceView.swift */, + 5C4BB1E028212B1E00A92FB2 /* World.swift */, ); path = CodeEdit; sourceTree = ""; @@ -2288,6 +2266,108 @@ path = "Preview Content"; sourceTree = ""; }; + B67660622AA961E900CD56B0 /* Tab */ = { + isa = PBXGroup; + children = ( + 58AFAA272933C65C00482B53 /* Models */, + B6C6A42F29771F7100A3D28F /* EditorTabBackground.swift */, + B6C6A42D29771A8D00A3D28F /* EditorTabButtonStyle.swift */, + B6C6A429297716A500A3D28F /* EditorTabCloseButton.swift */, + 587FB98F29C1246400B519DD /* EditorTabView.swift */, + ); + path = Tab; + sourceTree = ""; + }; + B67660632AA970E300CD56B0 /* Views */ = { + isa = PBXGroup; + children = ( + 6C147C4C29A32AA30089B630 /* EditorView.swift */, + 6C147C4829A32A080089B630 /* EditorLayoutView.swift */, + ); + path = Views; + sourceTree = ""; + }; + B67660642AA970ED00CD56B0 /* Models */ = { + isa = PBXGroup; + children = ( + 6C91D57129B176FF0059A90D /* EditorManager.swift */, + 6C147C3E29A3281D0089B630 /* EditorLayout.swift */, + 6C147C3D29A3281D0089B630 /* Editor.swift */, + 6CC9E4B129B5669900C97388 /* Environment+ActiveEditor.swift */, + 6C092ED92A53A58600489202 /* EditorLayout+StateRestoration.swift */, + ); + path = Models; + sourceTree = ""; + }; + B67660662AA9726F00CD56B0 /* HistoryInspector */ = { + isa = PBXGroup; + children = ( + 2072FA12280D74ED00C7F8D4 /* HistoryInspectorModel.swift */, + 20D839AD280E0CA700B27357 /* HistoryPopoverView.swift */, + 20EBB502280C327C00F3A5DA /* HistoryInspectorView.swift */, + 20EBB504280C329800F3A5DA /* HistoryInspectorItemView.swift */, + 200412EE280F3EAC00BCAF5C /* HistoryInspectorNoHistoryView.swift */, + ); + path = HistoryInspector; + sourceTree = ""; + }; + B67660672AA972B000CD56B0 /* FileInspector */ = { + isa = PBXGroup; + children = ( + 20EBB500280C325D00F3A5DA /* FileInspectorView.swift */, + ); + path = FileInspector; + sourceTree = ""; + }; + B67660682AA972D400CD56B0 /* Models */ = { + isa = PBXGroup; + children = ( + 6CE6226D2A2A1CDE0013085C /* NavigatorTab.swift */, + ); + path = Models; + sourceTree = ""; + }; + B67660692AA972DC00CD56B0 /* Views */ = { + isa = PBXGroup; + children = ( + 287776E627E3413200D46668 /* NavigatorAreaView.swift */, + ); + path = Views; + sourceTree = ""; + }; + B676606A2AA973A500CD56B0 /* TerminalUtility */ = { + isa = PBXGroup; + children = ( + B62AEDB22A1FD95B009A9F52 /* UtilityAreaTerminalView.swift */, + B62AEDBB2A210DBB009A9F52 /* UtilityAreaTerminalTab.swift */, + ); + path = TerminalUtility; + sourceTree = ""; + }; + B676606B2AA973B200CD56B0 /* DebugUtility */ = { + isa = PBXGroup; + children = ( + B62AEDB42A1FE295009A9F52 /* UtilityAreaDebugView.swift */, + ); + path = DebugUtility; + sourceTree = ""; + }; + B676606C2AA973C000CD56B0 /* OutputUtility */ = { + isa = PBXGroup; + children = ( + B62AEDB72A1FE2DC009A9F52 /* UtilityAreaOutputView.swift */, + ); + path = OutputUtility; + sourceTree = ""; + }; + B676606D2AA9741900CD56B0 /* Models */ = { + isa = PBXGroup; + children = ( + 6CE6226A2A2A1C730013085C /* UtilityAreaTab.swift */, + ); + path = Models; + sourceTree = ""; + }; B67B270029D7868000FB9301 /* Settings */ = { isa = PBXGroup; children = ( @@ -2389,17 +2469,15 @@ path = TextEditingSettings; sourceTree = ""; }; - B6EE988E27E8877C00CDD8AB /* InspectorSidebar */ = { + B6EE988E27E8877C00CDD8AB /* InspectorArea */ = { isa = PBXGroup; children = ( + B67660672AA972B000CD56B0 /* FileInspector */, + B67660662AA9726F00CD56B0 /* HistoryInspector */, 20EBB50B280C382800F3A5DA /* Models */, 20EBB4FF280C325000F3A5DA /* Views */, - B6EE988F27E8879A00CDD8AB /* InspectorSidebarView.swift */, - B6D7EA582971078500301FAC /* InspectorSection.swift */, - B6D7EA5B297107DD00301FAC /* InspectorField.swift */, - 6CE622682A2A174A0013085C /* InspectorTab.swift */, ); - path = InspectorSidebar; + path = InspectorArea; sourceTree = ""; }; B6F0516C29D9E32700D72287 /* TerminalSettings */ = { @@ -2752,7 +2830,7 @@ D7DC4B76298FFBE900D6C83D /* ProjectNavigatorViewController+OutlineTableViewCellDelegate.swift in Sources */, 587B9E9229301D8F00AC7927 /* BitBucketAccount.swift in Sources */, DE513F52281B672D002260B9 /* TabBarAccessory.swift in Sources */, - 2813F93927ECC4C300E305E4 /* NavigatorSidebarView.swift in Sources */, + 2813F93927ECC4C300E305E4 /* NavigatorAreaView.swift in Sources */, 587B9E8A29301D8F00AC7927 /* GitHubIssue.swift in Sources */, EC0870F72A455F6400EB8692 /* ProjectNavigatorViewController+NSMenuDelegate.swift in Sources */, 6CAAF69429BCD78600A1F48A /* (null) in Sources */, @@ -2760,7 +2838,7 @@ 6C82D6C629C012AD00495C54 /* NSApp+openWindow.swift in Sources */, 6C14CEB028777D3C001468FE /* FindNavigatorListViewController.swift in Sources */, 587B9E7F29301D8F00AC7927 /* GitHubUserRouter.swift in Sources */, - B62AEDBC2A210DBB009A9F52 /* DebugAreaTerminalTab.swift in Sources */, + B62AEDBC2A210DBB009A9F52 /* UtilityAreaTerminalTab.swift in Sources */, B61A606129F188AB009B43F9 /* ExternalLink.swift in Sources */, 587B9E9729301D8F00AC7927 /* BitBucketAccount+Token.swift in Sources */, 587B9E7729301D8F00AC7927 /* String+PercentEncoding.swift in Sources */, @@ -2803,12 +2881,12 @@ 5878DAA7291AE76700DD95A3 /* QuickOpenViewModel.swift in Sources */, 6CFF967429BEBCC300182D6F /* FindCommands.swift in Sources */, 587B9E6529301D8F00AC7927 /* GitLabGroupAccess.swift in Sources */, - 6C91D57229B176FF0059A90D /* TabManager.swift in Sources */, + 6C91D57229B176FF0059A90D /* EditorManager.swift in Sources */, 6C82D6BC29C00CD900495C54 /* FirstResponderPropertyWrapper.swift in Sources */, 58D01C9B293167DC00C5B6B4 /* CodeEditKeychainConstants.swift in Sources */, B640A99E29E2184700715F20 /* SettingsForm.swift in Sources */, B62AEDD12A27B264009A9F52 /* View+paneToolbar.swift in Sources */, - 5878DAB1291D627C00DD95A3 /* PathBarComponent.swift in Sources */, + 5878DAB1291D627C00DD95A3 /* EditorPathBarComponent.swift in Sources */, 587B9E6E29301D8F00AC7927 /* GitLabProject.swift in Sources */, 58798234292E30B90085B254 /* FeedbackIssueArea.swift in Sources */, 587B9E5F29301D8F00AC7927 /* GitLabProjectRouter.swift in Sources */, @@ -2831,7 +2909,7 @@ 201169E72837B5CA00F92B46 /* SourceControlModel.swift in Sources */, 58822528292C280D00E83CDE /* StatusBarEncodingSelector.swift in Sources */, 6C7F37FE2A3EA6FA00217B83 /* View+focusedValue.swift in Sources */, - B6C6A43029771F7100A3D28F /* TabBarItemBackground.swift in Sources */, + B6C6A43029771F7100A3D28F /* EditorTabBackground.swift in Sources */, 6C578D8129CD294800DC73B2 /* ExtensionActivatorView.swift in Sources */, B6F0517D29D9E4B100D72287 /* TerminalSettingsView.swift in Sources */, 587B9E8C29301D8F00AC7927 /* GitHubOpenness.swift in Sources */, @@ -2859,7 +2937,7 @@ 587B9E7529301D8F00AC7927 /* String+QueryParameters.swift in Sources */, 58798219292D92370085B254 /* SearchModeModel.swift in Sources */, 6C5C891B2A3F736500A94FE1 /* FocusedValues.swift in Sources */, - B62AEDD72A27B3D0009A9F52 /* DebugAreaTabViewModel.swift in Sources */, + B62AEDD72A27B3D0009A9F52 /* UtilityAreaTabViewModel.swift in Sources */, B66A4E4F29C917B8004573B4 /* WelcomeWindow.swift in Sources */, 58D01C9D293167DC00C5B6B4 /* KeychainSwiftAccessOptions.swift in Sources */, B6E41C8B29DE7AE80088F9F4 /* AccountsSettingsSigninView.swift in Sources */, @@ -2873,24 +2951,24 @@ 587B9E6C29301D8F00AC7927 /* GitLabNamespace.swift in Sources */, 6C48D8F22972DAFC00D6D205 /* Env+IsFullscreen.swift in Sources */, 587B9E8729301D8F00AC7927 /* GitHubRepositories.swift in Sources */, - 6CE6226B2A2A1C730013085C /* DebugAreaTab.swift in Sources */, + 6CE6226B2A2A1C730013085C /* UtilityAreaTab.swift in Sources */, 587B9DA329300ABD00AC7927 /* SettingsTextEditor.swift in Sources */, B6F0517B29D9E46400D72287 /* SourceControlSettingsView.swift in Sources */, - 6C147C4D29A32AA30089B630 /* WorkspaceTabGroupView.swift in Sources */, + 6C147C4D29A32AA30089B630 /* EditorView.swift in Sources */, 587B9E7B29301D8F00AC7927 /* GitHubRouter.swift in Sources */, 201169E22837B3D800F92B46 /* SourceControlNavigatorChangesView.swift in Sources */, 850C631029D6B01D00E1444C /* SettingsView.swift in Sources */, DE6405A62817734700881FDF /* TabBarNative.swift in Sources */, 581550CF29FBD30400684881 /* StandardTableViewCell.swift in Sources */, - B62AEDB82A1FE2DC009A9F52 /* DebugAreaOutputView.swift in Sources */, + B62AEDB82A1FE2DC009A9F52 /* UtilityAreaOutputView.swift in Sources */, 587B9E5C29301D8F00AC7927 /* Parameters.swift in Sources */, 58798235292E30B90085B254 /* FeedbackModel.swift in Sources */, 04C3255C2801F86900C8DA2D /* ProjectNavigatorMenu.swift in Sources */, 587B9E6429301D8F00AC7927 /* GitLabCommit.swift in Sources */, B6E55C3B2A95368E003ECC7D /* TabBarShadow.swift in Sources */, 58A5DFA229339F6400D1BD5D /* KeybindingManager.swift in Sources */, - B62AEDB32A1FD95B009A9F52 /* DebugAreaTerminalView.swift in Sources */, - 58AFAA2E2933C69E00482B53 /* TabBarItemRepresentable.swift in Sources */, + B62AEDB32A1FD95B009A9F52 /* UtilityAreaTerminalView.swift in Sources */, + 58AFAA2E2933C69E00482B53 /* EditorTabRepresentable.swift in Sources */, 6C4104E6297C884F00F472BA /* AboutDetailView.swift in Sources */, 6C6BD6F129CD13FA00235D17 /* ExtensionDiscovery.swift in Sources */, 587B9E7A29301D8F00AC7927 /* GitHubReviewsRouter.swift in Sources */, @@ -2910,7 +2988,7 @@ 58F2EB04292FB2B0004A9BDE /* SourceControlSettings.swift in Sources */, 58710159298EB80000951BA4 /* CEWorkspaceFileManager.swift in Sources */, 582213F0291834A500EFE361 /* AboutView.swift in Sources */, - 6CC9E4B229B5669900C97388 /* Environment+ActiveTabGroup.swift in Sources */, + 6CC9E4B229B5669900C97388 /* Environment+ActiveEditor.swift in Sources */, 58822526292C280D00E83CDE /* StatusBarBreakpointButton.swift in Sources */, 58D01C96293167DC00C5B6B4 /* Date+Formatted.swift in Sources */, B66A4E5629C918A0004573B4 /* SceneID.swift in Sources */, @@ -2931,16 +3009,16 @@ 587B9E7429301D8F00AC7927 /* URL+URLParameters.swift in Sources */, 6C5BE51C2A3D542B002DA0FC /* FeatureFlagsSettingsView.swift in Sources */, 581BFB6B2926431000D251EC /* RecentProjectItem.swift in Sources */, - 587FB99029C1246400B519DD /* TabBarItemView.swift in Sources */, + 587FB99029C1246400B519DD /* EditorTabView.swift in Sources */, 587B9DA429300ABD00AC7927 /* OverlayPanel.swift in Sources */, 58D01C95293167DC00C5B6B4 /* Bundle+Info.swift in Sources */, - B6C6A42A297716A500A3D28F /* TabBarItemCloseButton.swift in Sources */, + B6C6A42A297716A500A3D28F /* EditorTabCloseButton.swift in Sources */, 58A5DF7D2931787A00D1BD5D /* ShellClient.swift in Sources */, 5879821A292D92370085B254 /* SearchResultModel.swift in Sources */, B6F0517729D9E3AD00D72287 /* SourceControlGeneralView.swift in Sources */, 587B9E8929301D8F00AC7927 /* GitHubGist.swift in Sources */, 0485EB1F27E7458B00138301 /* WorkspaceCodeFileView.swift in Sources */, - 6C092EDA2A53A58600489202 /* TabGroup+StateRestoration.swift in Sources */, + 6C092EDA2A53A58600489202 /* EditorLayout+StateRestoration.swift in Sources */, 6C092EE02A53BFCF00489202 /* WorkspaceStateKey.swift in Sources */, 58D01C94293167DC00C5B6B4 /* Color+HEX.swift in Sources */, 6C578D8729CD345900DC73B2 /* ExtensionSceneView.swift in Sources */, @@ -2955,7 +3033,7 @@ 581BFB682926431000D251EC /* WelcomeView.swift in Sources */, 6CFF967829BEBCF600182D6F /* MainCommands.swift in Sources */, 587B9E7129301D8F00AC7927 /* GitURLSession.swift in Sources */, - 5882252C292C280D00E83CDE /* DebugAreaView.swift in Sources */, + 5882252C292C280D00E83CDE /* UtilityAreaView.swift in Sources */, 2847019E27FDDF7600F87B6B /* ProjectNavigatorOutlineView.swift in Sources */, 6C14CEB32877A68F001468FE /* FindNavigatorMatchListCell.swift in Sources */, 20EBB501280C325D00F3A5DA /* FileInspectorView.swift in Sources */, @@ -2968,7 +3046,7 @@ 587B9E7C29301D8F00AC7927 /* GitHubRepositoryRouter.swift in Sources */, 286471AB27ED51FD0039369D /* ProjectNavigatorView.swift in Sources */, B6E41C7C29DE2B110088F9F4 /* AccountsSettingsProviderRow.swift in Sources */, - B62AEDB52A1FE295009A9F52 /* DebugAreaDebugView.swift in Sources */, + B62AEDB52A1FE295009A9F52 /* UtilityAreaDebugView.swift in Sources */, 6C049A372A49E2DB00D42923 /* DirectoryEventStream.swift in Sources */, 6CAAF68A29BC9C2300A1F48A /* (null) in Sources */, 6C6BD6EF29CD12E900235D17 /* ExtensionManagerWindow.swift in Sources */, @@ -3018,15 +3096,15 @@ 588847692992ABCA00996D95 /* Array+CEWorkspaceFile.swift in Sources */, 58822530292C280D00E83CDE /* FilterTextField.swift in Sources */, 6C82D6B929BFE34900495C54 /* HelpCommands.swift in Sources */, - 6C147C4929A32A080089B630 /* EditorView.swift in Sources */, - 6C147C4129A328BF0089B630 /* TabGroup.swift in Sources */, + 6C147C4929A32A080089B630 /* EditorLayoutView.swift in Sources */, + 6C147C4129A328BF0089B630 /* EditorLayout.swift in Sources */, B6D7EA592971078500301FAC /* InspectorSection.swift in Sources */, 58F2EAEF292FB2B0004A9BDE /* ThemeSettingsView.swift in Sources */, - B6EE989027E8879A00CDD8AB /* InspectorSidebarView.swift in Sources */, + B6EE989027E8879A00CDD8AB /* InspectorAreaView.swift in Sources */, 587B9DA229300ABD00AC7927 /* EffectView.swift in Sources */, 6C97EBCC2978760400302F95 /* AcknowledgementsWindowController.swift in Sources */, 284DC84F2978B7B400BF2770 /* ContributorsView.swift in Sources */, - B62AEDC92A2704F3009A9F52 /* DebugAreaTabView.swift in Sources */, + B62AEDC92A2704F3009A9F52 /* UtilityAreaTabView.swift in Sources */, 58798250292E78D80085B254 /* CodeFile.swift in Sources */, 5878DAA5291AE76700DD95A3 /* QuickOpenView.swift in Sources */, 201169D72837B2E300F92B46 /* SourceControlNavigatorView.swift in Sources */, @@ -3040,7 +3118,7 @@ 587B9E5A29301D8F00AC7927 /* GitCloneView.swift in Sources */, 58D01C99293167DC00C5B6B4 /* String+MD5.swift in Sources */, 20EBB505280C329800F3A5DA /* HistoryInspectorItemView.swift in Sources */, - 5878DAB2291D627C00DD95A3 /* PathBarView.swift in Sources */, + 5878DAB2291D627C00DD95A3 /* EditorPathBarView.swift in Sources */, 6C6BD70129CD172700235D17 /* ExtensionsListView.swift in Sources */, 043C321627E3201F006AE443 /* WorkspaceDocument.swift in Sources */, 58F2EAEC292FB2B0004A9BDE /* IgnoredFiles.swift in Sources */, @@ -3049,7 +3127,7 @@ 587B9E6D29301D8F00AC7927 /* GitLabEventNote.swift in Sources */, 587B9E9129301D8F00AC7927 /* BitBucketOAuthRouter.swift in Sources */, B6E41C7429DD40010088F9F4 /* View+HideSidebarToggle.swift in Sources */, - 58822532292C280D00E83CDE /* DebugAreaViewModel.swift in Sources */, + 58822532292C280D00E83CDE /* UtilityAreaViewModel.swift in Sources */, 043BCF03281DA18A000AC47C /* WorkspaceDocument+Search.swift in Sources */, 58822527292C280D00E83CDE /* StatusBarIndentSelector.swift in Sources */, 587B9E9629301D8F00AC7927 /* BitBucketRepositories.swift in Sources */, @@ -3057,13 +3135,13 @@ 58798286292ED0FB0085B254 /* SwiftTerm+Color+Init.swift in Sources */, 6CFF967C29BEBD5200182D6F /* WindowCommands.swift in Sources */, 587B9E7229301D8F00AC7927 /* GitJSONPostRouter.swift in Sources */, - 5878DAB0291D627C00DD95A3 /* PathBarMenu.swift in Sources */, + 5878DAB0291D627C00DD95A3 /* EditorPathBarMenu.swift in Sources */, 587B9DA529300ABD00AC7927 /* PressActionsModifier.swift in Sources */, 6C147C4029A328BC0089B630 /* SplitViewData.swift in Sources */, 587B9E9029301D8F00AC7927 /* BitBucketTokenRouter.swift in Sources */, - B6C6A42E29771A8D00A3D28F /* TabBarItemButtonStyle.swift in Sources */, + B6C6A42E29771A8D00A3D28F /* EditorTabButtonStyle.swift in Sources */, 58822525292C280D00E83CDE /* StatusBarMenuStyle.swift in Sources */, - 6C147C4229A328C10089B630 /* TabGroupData.swift in Sources */, + 6C147C4229A328C10089B630 /* Editor.swift in Sources */, 6C2C155829B4F49100EA60A5 /* SplitViewItem.swift in Sources */, 6CDA84AD284C1BA000C1CC3A /* TabBarContextMenu.swift in Sources */, 6C81916729B3E80700B75C92 /* ModifierKeysObserver.swift in Sources */, @@ -3075,7 +3153,7 @@ 6C05A8AF284D0CA3007F4EAA /* WorkspaceDocument+Listeners.swift in Sources */, 588847632992A2A200996D95 /* CEWorkspaceFile.swift in Sources */, 6C2C155D29B4F4E500EA60A5 /* SplitViewReader.swift in Sources */, - 58AFAA2F2933C69E00482B53 /* TabBarItemID.swift in Sources */, + 58AFAA2F2933C69E00482B53 /* EditorItemID.swift in Sources */, 6C4104E3297C87A000F472BA /* BlurButtonStyle.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/CodeEdit/Features/CEWorkspace/Models/CEWorkspaceFile.swift b/CodeEdit/Features/CEWorkspace/Models/CEWorkspaceFile.swift index 782b1504b0..cf252f759f 100644 --- a/CodeEdit/Features/CEWorkspace/Models/CEWorkspaceFile.swift +++ b/CodeEdit/Features/CEWorkspace/Models/CEWorkspaceFile.swift @@ -17,7 +17,7 @@ enum FileItemCodingKeys: String, CodingKey { } /// An object containing all necessary information and actions for a specific file in the workspace -final class CEWorkspaceFile: Codable, Comparable, Hashable, Identifiable, TabBarItemRepresentable { +final class CEWorkspaceFile: Codable, Comparable, Hashable, Identifiable, EditorTabRepresentable { /// The id of the ``FileSystemClient/FileSystemClient/FileItem``. /// @@ -54,8 +54,8 @@ final class CEWorkspaceFile: Codable, Comparable, Hashable, Identifiable, TabBar /// Returns the Git status of a file as ``GitType`` var gitStatus: GitType? - /// Returns the `id` in ``TabBarItemID`` enum form - var tabID: TabBarItemID { .codeEditor(id) } + /// Returns the `id` in ``EditorTabID`` enum form + var tabID: EditorTabID { .codeEditor(id) } /// Returns a boolean that is true if ``children`` is not `nil` var isFolder: Bool { url.hasDirectoryPath } diff --git a/CodeEdit/Features/CodeEditUI/Views/AreaTabBar.swift b/CodeEdit/Features/CodeEditUI/Views/AreaTabBar.swift index 0bd5e77ef8..ec7be9aa70 100644 --- a/CodeEdit/Features/CodeEditUI/Views/AreaTabBar.swift +++ b/CodeEdit/Features/CodeEditUI/Views/AreaTabBar.swift @@ -84,6 +84,9 @@ struct AreaTabBar: View { ) .background(makeTabItemGeometryReader(tab: icon)) .simultaneousGesture(makeAreaTabDragGesture(tab: icon)) + .opacity(draggingItem?.imageName == icon.systemImage && + hasChangedLocation && + drugItemLocation != nil ? 0.0 : 1.0) } if position == .side { Spacer() diff --git a/CodeEdit/Features/CodeFile/CodeFileView.swift b/CodeEdit/Features/CodeFile/CodeFileView.swift index 9d9d7abb52..3c3ecc3b5c 100644 --- a/CodeEdit/Features/CodeFile/CodeFileView.swift +++ b/CodeEdit/Features/CodeFile/CodeFileView.swift @@ -97,7 +97,7 @@ struct CodeFileView: View { @Environment(\.edgeInsets) private var edgeInsets - @EnvironmentObject private var tabgroup: TabGroupData + @EnvironmentObject private var editor: Editor var body: some View { CodeEditTextView( diff --git a/CodeEdit/Features/Documents/Controllers/CodeEditWindowController.swift b/CodeEdit/Features/Documents/Controllers/CodeEditWindowController.swift index c3121fdf98..a18f6311cb 100644 --- a/CodeEdit/Features/Documents/Controllers/CodeEditWindowController.swift +++ b/CodeEdit/Features/Documents/Controllers/CodeEditWindowController.swift @@ -83,10 +83,10 @@ final class CodeEditWindowController: NSWindowController, NSToolbarDelegate, Obs let navigatorViewModel = NavigatorSidebarViewModel() navigatorSidebarViewModel = navigatorViewModel - let settingsView = SettingsInjector { - NavigatorSidebarView(workspace: workspace, viewModel: navigatorViewModel) + let navigatorView = SettingsInjector { + NavigatorAreaView(workspace: workspace, viewModel: navigatorViewModel) .environmentObject(workspace) - .environmentObject(workspace.tabManager) + .environmentObject(workspace.editorManager) } let navigator = NSSplitViewItem( @@ -102,8 +102,8 @@ final class CodeEditWindowController: NSWindowController, NSToolbarDelegate, Obs WindowObserver(window: window!) { WorkspaceView() .environmentObject(workspace) - .environmentObject(workspace.tabManager) - .environmentObject(workspace.debugAreaModel) + .environmentObject(workspace.editorManager) + .environmentObject(workspace.utilityAreaModel) } } @@ -114,9 +114,9 @@ final class CodeEditWindowController: NSWindowController, NSToolbarDelegate, Obs splitVC.addSplitViewItem(mainContent) let inspectorView = SettingsInjector { - InspectorSidebarView() + InspectorAreaView() .environmentObject(workspace) - .environmentObject(workspace.tabManager) + .environmentObject(workspace.editorManager) } let inspector = NSSplitViewItem(viewController: NSHostingController(rootView: inspectorView)) @@ -236,12 +236,12 @@ final class CodeEditWindowController: NSWindowController, NSToolbarDelegate, Obs } private func getSelectedCodeFile() -> CodeFileDocument? { - workspace?.tabManager.activeTabGroup.selected?.fileDocument + workspace?.editorManager.activeEditor.selectedTab?.fileDocument } @IBAction func saveDocument(_ sender: Any) { getSelectedCodeFile()?.save(sender) - workspace?.tabManager.activeTabGroup.temporaryTab = nil + workspace?.editorManager.activeEditor.temporaryTab = nil } @IBAction func openCommandPalette(_ sender: Any) { @@ -284,7 +284,7 @@ final class CodeEditWindowController: NSWindowController, NSToolbarDelegate, Obs let contentView = QuickOpenView(state: state) { panel.close() } openFile: { file in - workspace.tabManager.openTab(item: file) + workspace.editorManager.openTab(item: file) } panel.contentView = NSHostingView(rootView: SettingsInjector { contentView }) @@ -295,18 +295,18 @@ final class CodeEditWindowController: NSWindowController, NSToolbarDelegate, Obs } @IBAction func closeCurrentTab(_ sender: Any) { - if (workspace?.tabManager.activeTabGroup.tabs ?? []).isEmpty { - self.closeActiveTabGroup(self) + if (workspace?.editorManager.activeEditor.tabs ?? []).isEmpty { + self.closeActiveEditor(self) } else { - workspace?.tabManager.activeTabGroup.closeCurrentTab() + workspace?.editorManager.activeEditor.closeSelectedTab() } } - @IBAction func closeActiveTabGroup(_ sender: Any) { - if workspace?.tabManager.tabGroups.findSomeTabGroup(except: workspace?.tabManager.activeTabGroup) == nil { + @IBAction func closeActiveEditor(_ sender: Any) { + if workspace?.editorManager.editorLayout.findSomeEditor(except: workspace?.editorManager.activeEditor) == nil { NSApp.sendAction(#selector(NSWindow.close), to: nil, from: nil) } else { - workspace?.tabManager.activeTabGroup.close() + workspace?.editorManager.activeEditor.close() } } } diff --git a/CodeEdit/Features/Documents/Views/WorkspaceCodeFileView.swift b/CodeEdit/Features/Documents/Views/WorkspaceCodeFileView.swift index cce9efc321..e33ad332c2 100644 --- a/CodeEdit/Features/Documents/Views/WorkspaceCodeFileView.swift +++ b/CodeEdit/Features/Documents/Views/WorkspaceCodeFileView.swift @@ -10,9 +10,9 @@ import UniformTypeIdentifiers struct WorkspaceCodeFileView: View { - @EnvironmentObject private var tabManager: TabManager + @EnvironmentObject private var editorManager: EditorManager - @EnvironmentObject private var tabgroup: TabGroupData + @EnvironmentObject private var editor: Editor var file: CEWorkspaceFile diff --git a/CodeEdit/Features/Documents/WorkspaceDocument.swift b/CodeEdit/Features/Documents/WorkspaceDocument.swift index 17df2df370..f0bf7d28f7 100644 --- a/CodeEdit/Features/Documents/WorkspaceDocument.swift +++ b/CodeEdit/Features/Documents/WorkspaceDocument.swift @@ -18,7 +18,7 @@ final class WorkspaceDocument: NSDocument, ObservableObject, NSToolbarDelegate { var workspaceFileManager: CEWorkspaceFileManager? - var tabManager = TabManager() + var editorManager = EditorManager() private var workspaceState: [String: Any] { get { @@ -35,7 +35,7 @@ final class WorkspaceDocument: NSDocument, ObservableObject, NSToolbarDelegate { didSet { workspaceFileManager?.notifyObservers() } } - var debugAreaModel = DebugAreaViewModel() + var utilityAreaModel = UtilityAreaViewModel() var searchState: SearchState? var quickOpenViewModel: QuickOpenViewModel? var commandsPaletteState: CommandPaletteViewModel? @@ -122,8 +122,8 @@ final class WorkspaceDocument: NSDocument, ObservableObject, NSToolbarDelegate { self.quickOpenViewModel = .init(fileURL: url) self.commandsPaletteState = .init() - tabManager.restoreFromState(self) - debugAreaModel.restoreFromState(self) + editorManager.restoreFromState(self) + utilityAreaModel.restoreFromState(self) } override func read(from url: URL, ofType typeName: String) throws { @@ -135,8 +135,8 @@ final class WorkspaceDocument: NSDocument, ObservableObject, NSToolbarDelegate { // MARK: Close Workspace override func close() { - tabManager.saveRestorationState(self) - debugAreaModel.saveRestorationState(self) + editorManager.saveRestorationState(self) + utilityAreaModel.saveRestorationState(self) super.close() } @@ -174,7 +174,7 @@ final class WorkspaceDocument: NSDocument, ObservableObject, NSToolbarDelegate { return } // Save unsaved changes before closing - let editedCodeFiles = tabManager.tabGroups + let editedCodeFiles = editorManager.editorLayout .gatherOpenFiles() .compactMap(\.fileDocument) .filter(\.isDocumentEdited) @@ -203,7 +203,7 @@ final class WorkspaceDocument: NSDocument, ObservableObject, NSToolbarDelegate { implementation, to: (@convention(c)(Any, Selector, Any, Bool, UnsafeMutableRawPointer?) -> Void).self ) - let areAllOpenedCodeFilesClean = tabManager.tabGroups.gatherOpenFiles() + let areAllOpenedCodeFilesClean = editorManager.editorLayout.gatherOpenFiles() .compactMap(\.fileDocument) .allSatisfy { !$0.isDocumentEdited } function(object, shouldCloseSelector, self, areAllOpenedCodeFilesClean, contextInfo) diff --git a/CodeEdit/Features/Documents/WorkspaceStateKey.swift b/CodeEdit/Features/Documents/WorkspaceStateKey.swift index ffbe9c3969..67aedd6909 100644 --- a/CodeEdit/Features/Documents/WorkspaceStateKey.swift +++ b/CodeEdit/Features/Documents/WorkspaceStateKey.swift @@ -6,9 +6,9 @@ // enum WorkspaceStateKey: String { - case debugAreaCollapsed - case debugAreaMaximized - case debugAreaHeight + case utilityAreaCollapsed + case utilityAreaMaximized + case utilityAreaHeight case openTabs case workspaceWindowSize case splitViewWidth diff --git a/CodeEdit/Features/Tabs/TabGroup/TabGroupData.swift b/CodeEdit/Features/Editor/Models/Editor.swift similarity index 81% rename from CodeEdit/Features/Tabs/TabGroup/TabGroupData.swift rename to CodeEdit/Features/Editor/Models/Editor.swift index cadc8ad2e6..2f6aa04325 100644 --- a/CodeEdit/Features/Tabs/TabGroup/TabGroupData.swift +++ b/CodeEdit/Features/Editor/Models/Editor.swift @@ -1,5 +1,5 @@ // -// TabGroupData.swift +// Editor.swift // CodeEdit // // Created by Wouter Hennen on 16/02/2023. @@ -9,7 +9,7 @@ import Foundation import OrderedCollections import DequeModule -final class TabGroupData: ObservableObject, Identifiable { +final class Editor: ObservableObject, Identifiable { typealias Tab = CEWorkspaceFile /// Set of open tabs. @@ -19,14 +19,14 @@ final class TabGroupData: ObservableObject, Identifiable { if tabs.count > oldValue.count { // Amount of tabs grew, so set the first new as selected. - selected = change.first + selectedTab = change.first } else { // Selected file was removed - if let selected, change.contains(selected) { - if let oldIndex = oldValue.firstIndex(of: selected), oldIndex - 1 < tabs.count, !tabs.isEmpty { - self.selected = tabs[max(0, oldIndex-1)] + if let selectedTab, change.contains(selectedTab) { + if let oldIndex = oldValue.firstIndex(of: selectedTab), oldIndex - 1 < tabs.count, !tabs.isEmpty { + self.selectedTab = tabs[max(0, oldIndex-1)] } else { - self.selected = nil + self.selectedTab = nil } } } @@ -39,13 +39,13 @@ final class TabGroupData: ObservableObject, Identifiable { let tab = history[historyOffset] if !tabs.contains(tab) { - if let selected { - openTab(item: tab, at: tabs.firstIndex(of: selected), fromHistory: true) + if let selectedTab { + openTab(item: tab, at: tabs.firstIndex(of: selectedTab), fromHistory: true) } else { openTab(item: tab, fromHistory: true) } } - selected = tab + selectedTab = tab } } @@ -53,7 +53,7 @@ final class TabGroupData: ObservableObject, Identifiable { @Published var history: Deque = [] /// Currently selected tab. - @Published var selected: Tab? + @Published var selectedTab: Tab? @Published var temporaryTab: Tab? @@ -63,21 +63,26 @@ final class TabGroupData: ObservableObject, Identifiable { init( files: OrderedSet = [], - selected: Tab? = nil, + selectedTab: Tab? = nil, parent: SplitViewData? = nil ) { self.tabs = [] self.parent = parent files.forEach { openTab(item: $0) } - self.selected = selected ?? files.first + self.selectedTab = selectedTab ?? files.first } - /// Closes the tabgroup. + /// Closes the editor. func close() { - parent?.closeTabGroup(with: id) + parent?.closeEditor(with: id) } - /// Closes a tab in the tabgroup. + /// Gets the editor layout. + func getEditorLayout() -> EditorLayout? { + return parent?.getEditorLayout(with: id) + } + + /// Closes a tab in the editor. /// This will also write any changes to the file on disk and will add the tab to the tab history. /// - Parameter item: the tab to close. func closeTab(item: Tab) { @@ -86,12 +91,12 @@ final class TabGroupData: ObservableObject, Identifiable { } historyOffset = 0 - if item != selected { + if item != selectedTab { history.prepend(item) } tabs.remove(item) - if let selected { - history.prepend(selected) + if let selectedTab { + history.prepend(selectedTab) } guard let file = item.fileDocument else { return } @@ -115,15 +120,15 @@ final class TabGroupData: ObservableObject, Identifiable { } /// Closes the currently opened tab in the tab group. - func closeCurrentTab() { - guard let selectedTab = selected else { + func closeSelectedTab() { + guard let tab = selectedTab else { return } - closeTab(item: selectedTab) + closeTab(item: tab) } - /// Opens a tab in the tabgroup. + /// Opens a tab in the editor. /// If a tab for the item already exists, it is used instead. /// - Parameters: /// - item: the tab to open. @@ -131,7 +136,7 @@ final class TabGroupData: ObservableObject, Identifiable { func openTab(item: Tab, asTemporary: Bool) { // Item is already opened in a tab. guard !tabs.contains(item) || !asTemporary else { - selected = item + selectedTab = item history.prepend(item) return } @@ -142,7 +147,7 @@ final class TabGroupData: ObservableObject, Identifiable { history.prepend(item) tabs.remove(tab) tabs.insert(item, at: index) - self.selected = item + self.selectedTab = item temporaryTab = item } @@ -167,7 +172,7 @@ final class TabGroupData: ObservableObject, Identifiable { } } - /// Opens a tab in the tabgroup. + /// Opens a tab in the editor. /// - Parameters: /// - item: The tab to open. /// - index: Index where the tab needs to be added. If nil, it is added to the back. @@ -178,7 +183,7 @@ final class TabGroupData: ObservableObject, Identifiable { } else { tabs.append(item) } - selected = item + selectedTab = item if !fromHistory { history.removeFirst(historyOffset) history.prepend(item) @@ -231,8 +236,8 @@ final class TabGroupData: ObservableObject, Identifiable { } } -extension TabGroupData: Equatable, Hashable { - static func == (lhs: TabGroupData, rhs: TabGroupData) -> Bool { +extension Editor: Equatable, Hashable { + static func == (lhs: Editor, rhs: Editor) -> Bool { lhs.id == rhs.id } diff --git a/CodeEdit/Features/Tabs/TabGroup/TabGroup+StateRestoration.swift b/CodeEdit/Features/Editor/Models/EditorLayout+StateRestoration.swift similarity index 65% rename from CodeEdit/Features/Tabs/TabGroup/TabGroup+StateRestoration.swift rename to CodeEdit/Features/Editor/Models/EditorLayout+StateRestoration.swift index 3b4ec45df5..31adaf9149 100644 --- a/CodeEdit/Features/Tabs/TabGroup/TabGroup+StateRestoration.swift +++ b/CodeEdit/Features/Editor/Models/EditorLayout+StateRestoration.swift @@ -1,5 +1,5 @@ // -// TabGroup+StateRestoration.swift +// Editor+StateRestoration.swift // CodeEdit // // Created by Khan Winter on 7/3/23. @@ -9,13 +9,13 @@ import Foundation import SwiftUI import OrderedCollections -struct TabRestorationState: Codable { - var focus: TabGroupData - var groups: TabGroup +struct EditorRestorationState: Codable { + var focus: Editor + var groups: EditorLayout } -extension TabGroup: Codable { - fileprivate enum TabGroupType: String, Codable { +extension EditorLayout: Codable { + fileprivate enum EditorLayoutType: String, Codable { case one case vertical case horizontal @@ -28,17 +28,17 @@ extension TabGroup: Codable { init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) - let type = try container.decode(TabGroupType.self, forKey: .type) + let type = try container.decode(EditorLayoutType.self, forKey: .type) switch type { case .one: - let tabGroupData = try container.decode(TabGroupData.self, forKey: .tabs) - self = .one(tabGroupData) + let editor = try container.decode(Editor.self, forKey: .tabs) + self = .one(editor) case .vertical: - let splitViewData = try container.decode(SplitViewData.self, forKey: .tabs) - self = .vertical(splitViewData) + let editor = try container.decode(SplitViewData.self, forKey: .tabs) + self = .vertical(editor) case .horizontal: - let splitViewData = try container.decode(SplitViewData.self, forKey: .tabs) - self = .horizontal(splitViewData) + let editor = try container.decode(SplitViewData.self, forKey: .tabs) + self = .horizontal(editor) } } @@ -46,13 +46,13 @@ extension TabGroup: Codable { var container = encoder.container(keyedBy: CodingKeys.self) switch self { case let .one(data): - try container.encode(TabGroupType.one, forKey: .type) + try container.encode(EditorLayoutType.one, forKey: .type) try container.encode(data, forKey: .tabs) case let .vertical(data): - try container.encode(TabGroupType.vertical, forKey: .type) + try container.encode(EditorLayoutType.vertical, forKey: .type) try container.encode(data, forKey: .tabs) case let .horizontal(data): - try container.encode(TabGroupType.horizontal, forKey: .type) + try container.encode(EditorLayoutType.horizontal, forKey: .type) try container.encode(data, forKey: .tabs) } } @@ -78,39 +78,39 @@ extension SplitViewData: Codable { } enum CodingKeys: String, CodingKey { - case tabgroups + case editorLayouts case axis } convenience init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) let axis = try container.decode(SplitViewAxis.self, forKey: .axis).swiftUI - let tabgroups = try container.decode([TabGroup].self, forKey: .tabgroups) - self.init(axis, tabgroups: tabgroups) + let editorLayouts = try container.decode([EditorLayout].self, forKey: .editorLayouts) + self.init(axis, editorLayouts: editorLayouts) } func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) - try container.encode(tabgroups, forKey: .tabgroups) + try container.encode(editorLayouts, forKey: .editorLayouts) try container.encode(SplitViewAxis(axis), forKey: .axis) } } -extension TabGroupData: Codable { +extension Editor: Codable { enum CodingKeys: String, CodingKey { case tabs - case selected + case selectedTab case id } convenience init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) let fileURLs = try container.decode([URL].self, forKey: .tabs) - let selected = try? container.decode(URL.self, forKey: .selected) + let selectedTab = try? container.decode(URL.self, forKey: .selectedTab) let id = try container.decode(UUID.self, forKey: .id) self.init( files: OrderedSet(fileURLs.map { CEWorkspaceFile(url: $0) }), - selected: selected == nil ? nil : CEWorkspaceFile(url: selected!), + selectedTab: selectedTab == nil ? nil : CEWorkspaceFile(url: selectedTab!), parent: nil ) self.id = id @@ -119,7 +119,7 @@ extension TabGroupData: Codable { func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(tabs.map { $0.url }, forKey: .tabs) - try container.encode(selected?.url, forKey: .selected) + try container.encode(selectedTab?.url, forKey: .selectedTab) try container.encode(id, forKey: .id) } } diff --git a/CodeEdit/Features/Tabs/TabGroup/TabGroup.swift b/CodeEdit/Features/Editor/Models/EditorLayout.swift similarity index 55% rename from CodeEdit/Features/Tabs/TabGroup/TabGroup.swift rename to CodeEdit/Features/Editor/Models/EditorLayout.swift index 25b627017d..6fa75de65f 100644 --- a/CodeEdit/Features/Tabs/TabGroup/TabGroup.swift +++ b/CodeEdit/Features/Editor/Models/EditorLayout.swift @@ -1,5 +1,5 @@ // -// TabGroup.swift +// EditorLayout.swift // CodeEdit // // Created by Wouter Hennen on 06/02/2023. @@ -7,8 +7,8 @@ import Foundation -enum TabGroup { - case one(TabGroupData) +enum EditorLayout { + case one(Editor) case vertical(SplitViewData) case horizontal(SplitViewData) @@ -16,25 +16,25 @@ enum TabGroup { /// - Parameter file: a file. func closeAllTabs(of file: CEWorkspaceFile) { switch self { - case .one(let tabGroupData): - tabGroupData.tabs.remove(file) + case .one(let editor): + editor.tabs.remove(file) case .vertical(let data), .horizontal(let data): - data.tabgroups.forEach { + data.editorLayouts.forEach { $0.closeAllTabs(of: file) } } } - /// Returns some tabgroup, except the given tabgroup. - /// - Parameter except: the search will exclude this tabgroup. - /// - Returns: Some tabgroup. - func findSomeTabGroup(except: TabGroupData? = nil) -> TabGroupData? { + /// Returns some editor, except the given editor. + /// - Parameter except: the search will exclude this editor. + /// - Returns: Some editor. + func findSomeEditor(except: Editor? = nil) -> Editor? { switch self { - case .one(let tabGroupData) where tabGroupData != except: - return tabGroupData + case .one(let editor) where editor != except: + return editor case .vertical(let data), .horizontal(let data): - for tabgroup in data.tabgroups { - if let result = tabgroup.findSomeTabGroup(except: except), result != except { + for editorLayout in data.editorLayouts { + if let result = editorLayout.findSomeEditor(except: except), result != except { return result } } @@ -47,10 +47,10 @@ enum TabGroup { /// Forms a set of all files currently represented by tabs. func gatherOpenFiles() -> Set { switch self { - case .one(let tabGroupData): - return Set(tabGroupData.tabs) + case .one(let editor): + return Set(editor.tabs) case .vertical(let data), .horizontal(let data): - return data.tabgroups.map { $0.gatherOpenFiles() }.reduce(into: []) { $0.formUnion($1) } + return data.editorLayouts.map { $0.gatherOpenFiles() }.reduce(into: []) { $0.formUnion($1) } } } @@ -60,10 +60,10 @@ enum TabGroup { case .one: break case .horizontal(let data), .vertical(let data): - if data.tabgroups.count == 1 { - let one = data.tabgroups[0] - if case .one(let tabGroupData) = one { - tabGroupData.parent = parent + if data.editorLayouts.count == 1 { + let one = data.editorLayouts[0] + if case .one(let editor) = one { + editor.parent = parent } self = one } else { diff --git a/CodeEdit/Features/Editor/Models/EditorManager.swift b/CodeEdit/Features/Editor/Models/EditorManager.swift new file mode 100644 index 0000000000..9f67601eb0 --- /dev/null +++ b/CodeEdit/Features/Editor/Models/EditorManager.swift @@ -0,0 +1,141 @@ +// +// TabManager.swift +// CodeEdit +// +// Created by Wouter Hennen on 03/03/2023. +// + +import Combine +import Foundation +import DequeModule +import OrderedCollections + +class EditorManager: ObservableObject { + /// The complete editor layout. + @Published var editorLayout: EditorLayout + + @Published var isFocusingActiveEditor: Bool + + /// The Editor with active focus. + @Published var activeEditor: Editor { + didSet { + activeEditorHistory.prepend { [weak oldValue] in oldValue } + switchToActiveEditor() + } + } + + /// History of last-used editors. + var activeEditorHistory: Deque<() -> Editor?> = [] + + var fileDocuments: [CEWorkspaceFile: CodeFileDocument] = [:] + + /// notify listeners whenever tab selection changes on the active editor. + var tabBarTabIdSubject = PassthroughSubject() + var cancellable: AnyCancellable? + + init() { + let tab = Editor() + self.activeEditor = tab + self.activeEditorHistory.prepend { [weak tab] in tab } + self.editorLayout = .horizontal(.init(.horizontal, editorLayouts: [.one(tab)])) + self.isFocusingActiveEditor = false + switchToActiveEditor() + } + + /// Flattens the splitviews. + func flatten() { + if case .horizontal(let data) = editorLayout { + data.flatten() + } + } + + /// Opens a new tab in a editor. + /// - Parameters: + /// - item: The tab to open. + /// - editor: The editor to add the tab to. If nil, it is added to the active tab group. + func openTab(item: CEWorkspaceFile, in editor: Editor? = nil) { + let editor = editor ?? activeEditor + editor.openTab(item: item) + } + + /// bind active tap group to listen to file selection changes. + func switchToActiveEditor() { + cancellable?.cancel() + cancellable = nil + cancellable = activeEditor.$selectedTab + .sink { [weak self] tab in + self?.tabBarTabIdSubject.send(tab?.id) + } + } + + /// Restores the tab manager from a captured state obtained using `saveRestorationState` + /// - Parameter workspace: The workspace to retrieve state from. + func restoreFromState(_ workspace: WorkspaceDocument) { + guard let fileManager = workspace.workspaceFileManager, + let data = workspace.getFromWorkspaceState(.openTabs) as? Data, + let state = try? JSONDecoder().decode(EditorRestorationState.self, from: data) else { + return + } + fixRestoredEditorLayout(state.groups, fileManager: fileManager) + self.editorLayout = state.groups + self.activeEditor = findEditorLayout( + group: state.groups, + searchFor: state.focus.id + ) ?? editorLayout.findSomeEditor()! + switchToActiveEditor() + } + + /// Fix any hanging files after restoring from saved state. + /// + /// After decoding the state, we're left with `CEWorkspaceFile`s that don't exist in the file manager + /// so this function maps all those to 'real' files. Works recursively on all the tab groups. + /// - Parameters: + /// - group: The tab group to fix. + /// - fileManager: The file manager to use to map files. + private func fixRestoredEditorLayout(_ group: EditorLayout, fileManager: CEWorkspaceFileManager) { + switch group { + case let .one(data): + fixEditor(data, fileManager: fileManager) + case let .vertical(splitData): + splitData.editorLayouts.forEach { group in + fixRestoredEditorLayout(group, fileManager: fileManager) + } + case let .horizontal(splitData): + splitData.editorLayouts.forEach { group in + fixRestoredEditorLayout(group, fileManager: fileManager) + } + } + } + + private func findEditorLayout(group: EditorLayout, searchFor id: UUID) -> Editor? { + switch group { + case let .one(data): + return data.id == id ? data : nil + case let .vertical(splitData): + return splitData.editorLayouts.compactMap { findEditorLayout(group: $0, searchFor: id) }.first + case let .horizontal(splitData): + return splitData.editorLayouts.compactMap { findEditorLayout(group: $0, searchFor: id) }.first + } + } + + /// Fixes any hanging files after restoring from saved state. + /// - Parameters: + /// - data: The tab group to fix. + /// - fileManager: The file manager to use to map files.a + private func fixEditor(_ editor: Editor, fileManager: CEWorkspaceFileManager) { + editor.tabs = OrderedSet(editor.tabs.compactMap { fileManager.getFile($0.url.path) }) + if let selectedTab = editor.selectedTab { + editor.selectedTab = fileManager.getFile(selectedTab.url.path) + } + } + + func saveRestorationState(_ workspace: WorkspaceDocument) { + if let data = try? JSONEncoder().encode( + EditorRestorationState(focus: activeEditor, groups: editorLayout) + ) { + workspace.addToWorkspaceState(key: .openTabs, value: data) + } else { + workspace.addToWorkspaceState(key: .openTabs, value: nil) + } + } +} diff --git a/CodeEdit/Features/Editor/Models/Environment+ActiveEditor.swift b/CodeEdit/Features/Editor/Models/Environment+ActiveEditor.swift new file mode 100644 index 0000000000..6e400e3e90 --- /dev/null +++ b/CodeEdit/Features/Editor/Models/Environment+ActiveEditor.swift @@ -0,0 +1,19 @@ +// +// Environment+ActiveEditor.swift +// CodeEdit +// +// Created by Wouter Hennen on 06/03/2023. +// + +import SwiftUI + +struct ActiveEditorEnvironmentKey: EnvironmentKey { + static var defaultValue = false +} + +extension EnvironmentValues { + var isActiveEditor: Bool { + get { self[ActiveEditorEnvironmentKey.self] } + set { self[ActiveEditorEnvironmentKey.self] = newValue } + } +} diff --git a/CodeEdit/Features/PathBar/Views/PathBarComponent.swift b/CodeEdit/Features/Editor/PathBar/Views/EditorPathBarComponent.swift similarity index 96% rename from CodeEdit/Features/PathBar/Views/PathBarComponent.swift rename to CodeEdit/Features/Editor/PathBar/Views/EditorPathBarComponent.swift index 525e2b6fa4..a1e2977d32 100644 --- a/CodeEdit/Features/PathBar/Views/PathBarComponent.swift +++ b/CodeEdit/Features/Editor/PathBar/Views/EditorPathBarComponent.swift @@ -8,7 +8,7 @@ import SwiftUI import Combine -struct PathBarComponent: View { +struct EditorPathBarComponent: View { private let fileItem: CEWorkspaceFile private let tappedOpenFile: (CEWorkspaceFile) -> Void @@ -43,7 +43,7 @@ struct PathBarComponent: View { var body: some View { NSPopUpButtonView(selection: $selection) { let button = NSPopUpButton() - button.menu = PathBarMenu(fileItems: siblings, tappedOpenFile: tappedOpenFile) + button.menu = EditorPathBarMenu(fileItems: siblings, tappedOpenFile: tappedOpenFile) button.font = .systemFont(ofSize: NSFont.systemFontSize(for: .small)) button.isBordered = false (button.cell as? NSPopUpButtonCell)?.arrowPosition = .noArrow diff --git a/CodeEdit/Features/PathBar/Views/PathBarMenu.swift b/CodeEdit/Features/Editor/PathBar/Views/EditorPathBarMenu.swift similarity index 95% rename from CodeEdit/Features/PathBar/Views/PathBarMenu.swift rename to CodeEdit/Features/Editor/PathBar/Views/EditorPathBarMenu.swift index 1452283d42..7793dad075 100644 --- a/CodeEdit/Features/PathBar/Views/PathBarMenu.swift +++ b/CodeEdit/Features/Editor/PathBar/Views/EditorPathBarMenu.swift @@ -1,5 +1,5 @@ // -// PathBarMenu.swift +// EditorPathBarMenu.swift // CodeEditModules/PathBar // // Created by Ziyuan Zhao on 2022/3/29. @@ -7,7 +7,7 @@ import AppKit -final class PathBarMenu: NSMenu, NSMenuDelegate { +final class EditorPathBarMenu: NSMenu, NSMenuDelegate { private let fileItems: [CEWorkspaceFile] private let tappedOpenFile: (CEWorkspaceFile) -> Void @@ -44,9 +44,9 @@ final class PathBarMenu: NSMenu, NSMenuDelegate { } } - private func generateSubmenu(_ fileItem: CEWorkspaceFile) -> PathBarMenu? { + private func generateSubmenu(_ fileItem: CEWorkspaceFile) -> EditorPathBarMenu? { if let children = fileItem.children { - let menu = PathBarMenu( + let menu = EditorPathBarMenu( fileItems: children, tappedOpenFile: tappedOpenFile ) diff --git a/CodeEdit/Features/PathBar/Views/PathBarView.swift b/CodeEdit/Features/Editor/PathBar/Views/EditorPathBarView.swift similarity index 59% rename from CodeEdit/Features/PathBar/Views/PathBarView.swift rename to CodeEdit/Features/Editor/PathBar/Views/EditorPathBarView.swift index 0576c9a02c..06407f21de 100644 --- a/CodeEdit/Features/PathBar/Views/PathBarView.swift +++ b/CodeEdit/Features/Editor/PathBar/Views/EditorPathBarView.swift @@ -1,5 +1,5 @@ // -// PathBarView.swift +// EditorPathBarView.swift // CodeEditModules/PathBar // // Created by Lukas Pistrol on 17.03.22. @@ -7,16 +7,16 @@ import SwiftUI -struct PathBarView: View { +struct EditorPathBarView: View { - private let file: CEWorkspaceFile + private let file: CEWorkspaceFile? private let tappedOpenFile: (CEWorkspaceFile) -> Void @Environment(\.colorScheme) private var colorScheme - @Environment(\.isActiveTabGroup) - private var isActiveTabGroup + @Environment(\.isActiveEditor) + private var isActiveEditor @Environment(\.controlActiveState) private var activeState @@ -24,10 +24,10 @@ struct PathBarView: View { static let height = 27.0 init( - file: CEWorkspaceFile, + file: CEWorkspaceFile?, tappedOpenFile: @escaping (CEWorkspaceFile) -> Void ) { - self.file = file + self.file = file ?? nil self.tappedOpenFile = tappedOpenFile } @@ -46,19 +46,29 @@ struct PathBarView: View { var body: some View { ScrollView(.horizontal, showsIndicators: false) { HStack(spacing: 1.5) { - ForEach(fileItems, id: \.self) { fileItem in - if fileItem.parent != nil { - chevron + if file == nil { + Text("No Selection") + .font(.system(size: 11, weight: .regular)) + .foregroundColor( + activeState != .inactive + ? isActiveEditor ? .primary : .secondary + : Color(nsColor: .tertiaryLabelColor) + ) + } else { + ForEach(fileItems, id: \.self) { fileItem in + if fileItem.parent != nil { + chevron + } + EditorPathBarComponent(fileItem: fileItem, tappedOpenFile: tappedOpenFile) + .padding(.leading, 2.5) } - PathBarComponent(fileItem: fileItem, tappedOpenFile: tappedOpenFile) - .padding(.leading, 2.5) } } .padding(.horizontal, 10) } .frame(height: Self.height, alignment: .center) .opacity(activeState == .inactive ? 0.8 : 1.0) - .grayscale(isActiveTabGroup ? 0.0 : 1.0) + .grayscale(isActiveEditor ? 0.0 : 1.0) .background(EffectView(.headerView).frame(height: Self.height)) } diff --git a/CodeEdit/Features/Tabs/Views/TabBarItemBackground.swift b/CodeEdit/Features/Editor/Tab/EditorTabBackground.swift similarity index 83% rename from CodeEdit/Features/Tabs/Views/TabBarItemBackground.swift rename to CodeEdit/Features/Editor/Tab/EditorTabBackground.swift index 143afde2e5..7e922db1a5 100644 --- a/CodeEdit/Features/Tabs/Views/TabBarItemBackground.swift +++ b/CodeEdit/Features/Editor/Tab/EditorTabBackground.swift @@ -1,5 +1,5 @@ // -// TabBarItemBackground.swift +// EditorTabBackground.swift // CodeEdit // // Created by Austin Condiff on 1/17/23. @@ -7,7 +7,7 @@ import SwiftUI -struct TabBarItemBackground: View { +struct EditorTabBackground: View { var isActive: Bool var isPressing: Bool var isDragging: Bool @@ -18,8 +18,8 @@ struct TabBarItemBackground: View { @Environment(\.controlActiveState) private var activeState - @Environment(\.isActiveTabGroup) - private var isActiveTabGroup + @Environment(\.isActiveEditor) + private var isActiveEditor private var inHoldingState: Bool { isPressing || isDragging @@ -41,7 +41,7 @@ struct TabBarItemBackground: View { : activeState == .inactive ? 0.1 : inHoldingState ? 0.27 : 0.2 : 0 ) - .saturation(isActiveTabGroup ? 1.0 : 0.0) + .saturation(isActiveEditor ? 1.0 : 0.0) // Highlight (if in dark mode) Color(.white) @@ -61,8 +61,8 @@ struct TabBarItemBackground: View { } } -struct TabBarItemBackground_Previews: PreviewProvider { +struct EditorTabBackground_Previews: PreviewProvider { static var previews: some View { - TabBarItemBackground(isActive: false, isPressing: false, isDragging: false) + EditorTabBackground(isActive: false, isPressing: false, isDragging: false) } } diff --git a/CodeEdit/Features/Tabs/Views/TabBarItemButtonStyle.swift b/CodeEdit/Features/Editor/Tab/EditorTabButtonStyle.swift similarity index 86% rename from CodeEdit/Features/Tabs/Views/TabBarItemButtonStyle.swift rename to CodeEdit/Features/Editor/Tab/EditorTabButtonStyle.swift index 73b3b52d33..6ecd2a964b 100644 --- a/CodeEdit/Features/Tabs/Views/TabBarItemButtonStyle.swift +++ b/CodeEdit/Features/Editor/Tab/EditorTabButtonStyle.swift @@ -1,5 +1,5 @@ // -// TabBarItemButtonStyle.swift +// EditorTabButtonStyle.swift // CodeEdit // // Created by Khan Winter on 6/4/22. @@ -7,7 +7,7 @@ import SwiftUI -struct TabBarItemButtonStyle: ButtonStyle { +struct EditorTabButtonStyle: ButtonStyle { @Environment(\.colorScheme) var colorScheme diff --git a/CodeEdit/Features/Tabs/Views/TabBarItemCloseButton.swift b/CodeEdit/Features/Editor/Tab/EditorTabCloseButton.swift similarity index 95% rename from CodeEdit/Features/Tabs/Views/TabBarItemCloseButton.swift rename to CodeEdit/Features/Editor/Tab/EditorTabCloseButton.swift index 0c364bae38..e84e0559ec 100644 --- a/CodeEdit/Features/Tabs/Views/TabBarItemCloseButton.swift +++ b/CodeEdit/Features/Editor/Tab/EditorTabCloseButton.swift @@ -1,5 +1,5 @@ // -// TabBarItemCloseButton.swift +// EditorTabCloseButton.swift // CodeEdit // // Created by Austin Condiff on 1/17/23. @@ -7,7 +7,7 @@ import SwiftUI -struct TabBarItemCloseButton: View { +struct EditorTabCloseButton: View { var isActive: Bool var isHoveringTab: Bool var isDragging: Bool @@ -93,11 +93,11 @@ struct TabBarItemCloseButton: View { } } -struct TabBarItemCloseButton_Previews: PreviewProvider { +struct EditorTabCloseButton_Previews: PreviewProvider { @State static var closeButtonGestureActive = true static var previews: some View { - TabBarItemCloseButton( + EditorTabCloseButton( isActive: false, isHoveringTab: false, isDragging: false, diff --git a/CodeEdit/Features/Tabs/Views/TabBarItemView.swift b/CodeEdit/Features/Editor/Tab/EditorTabView.swift similarity index 90% rename from CodeEdit/Features/Tabs/Views/TabBarItemView.swift rename to CodeEdit/Features/Editor/Tab/EditorTabView.swift index fb5dacaa56..c793ebcf67 100644 --- a/CodeEdit/Features/Tabs/Views/TabBarItemView.swift +++ b/CodeEdit/Features/Editor/Tab/EditorTabView.swift @@ -1,5 +1,5 @@ // -// TabBarItemView.swift +// EditorTabView.swift // CodeEdit // // Created by Lukas Pistrol on 17.03.22. @@ -7,7 +7,7 @@ import SwiftUI -struct TabBarItemView: View { +struct EditorTabView: View { @Environment(\.colorScheme) private var colorScheme @@ -15,13 +15,13 @@ struct TabBarItemView: View { @Environment(\.controlActiveState) private var activeState - @Environment(\.isActiveTabGroup) - private var isActiveTabGroup + @Environment(\.isActiveEditor) + private var isActiveEditor @Environment(\.isFullscreen) private var isFullscreen - @EnvironmentObject private var tabManager: TabManager + @EnvironmentObject private var editorManager: EditorManager @AppSettings(\.general.tabBarStyle) var tabBarStyle @@ -58,7 +58,7 @@ struct TabBarItemView: View { @Binding private var closeButtonGestureActive: Bool - @EnvironmentObject private var tabgroup: TabGroupData + @EnvironmentObject private var editor: Editor /// The item associated with the current tab. /// @@ -68,12 +68,12 @@ struct TabBarItemView: View { var index: Int private var isTemporary: Bool { - tabgroup.temporaryTab == item + editor.temporaryTab == item } /// Is the current tab the active tab. private var isActive: Bool { - item == tabgroup.selected + item == editor.selectedTab } /// Is the current tab being dragged. @@ -91,19 +91,19 @@ struct TabBarItemView: View { /// Switch the active tab to current tab. private func switchAction() { // Only set the `selectedId` when they are not equal to avoid performance issue for now. - tabManager.activeTabGroup = tabgroup - if tabgroup.selected != item { - tabgroup.selected = item - tabgroup.history.removeFirst(tabgroup.historyOffset) - tabgroup.history.prepend(item) - tabgroup.historyOffset = 0 + editorManager.activeEditor = editor + if editor.selectedTab != item { + editor.selectedTab = item + editor.history.removeFirst(editor.historyOffset) + editor.history.prepend(item) + editor.historyOffset = 0 } } /// Close the current tab. func closeAction() { isAppeared = false - tabgroup.closeTab(item: item) + editor.closeTab(item: item) } init( @@ -137,7 +137,7 @@ struct TabBarItemView: View { .aspectRatio(contentMode: .fit) .foregroundColor( fileIconStyle == .color - && activeState != .inactive && isActiveTabGroup + && activeState != .inactive && isActiveEditor ? item.iconColor : .secondary ) @@ -160,7 +160,7 @@ struct TabBarItemView: View { .overlay { ZStack { // Close Button - TabBarItemCloseButton( + EditorTabCloseButton( isActive: isActive, isHoveringTab: isHovering, isDragging: draggingTabId != nil || onDragTabId != nil, @@ -193,7 +193,7 @@ struct TabBarItemView: View { .opacity(tabBarStyle == .native && !isActive ? 1 : 0) } .foregroundColor( - isActive && isActiveTabGroup + isActive && isActiveEditor ? ( tabBarStyle == .xcode && colorScheme != .dark ? Color(nsColor: .controlAccentColor) @@ -226,7 +226,7 @@ struct TabBarItemView: View { } .background { if tabBarStyle == .xcode { - TabBarItemBackground(isActive: isActive, isPressing: isPressing, isDragging: isDragging) + EditorTabBackground(isActive: isActive, isPressing: isPressing, isDragging: isDragging) .animation(.easeInOut(duration: 0.08), value: isHovering) } else { if isFullscreen && isActive { @@ -253,12 +253,12 @@ struct TabBarItemView: View { // return .init(object: NSString(string: "\(item.tabID)")) // }) } - .buttonStyle(TabBarItemButtonStyle(isPressing: $isPressing)) + .buttonStyle(EditorTabButtonStyle(isPressing: $isPressing)) .simultaneousGesture( TapGesture(count: 2) .onEnded { _ in if isTemporary { - tabgroup.temporaryTab = nil + editor.temporaryTab = nil } } ) diff --git a/CodeEdit/Features/Tabs/Models/TabBarItemID.swift b/CodeEdit/Features/Editor/Tab/Models/EditorItemID.swift similarity index 86% rename from CodeEdit/Features/Tabs/Models/TabBarItemID.swift rename to CodeEdit/Features/Editor/Tab/Models/EditorItemID.swift index 6e58c1763e..27cff36941 100644 --- a/CodeEdit/Features/Tabs/Models/TabBarItemID.swift +++ b/CodeEdit/Features/Editor/Tab/Models/EditorItemID.swift @@ -1,5 +1,5 @@ // -// TabBarItemID.swift +// EditorTabID.swift // // // Created by Pavel Kasila on 30.04.22. @@ -8,7 +8,7 @@ import Foundation /// Enum to represent item's ID to tab bar -enum TabBarItemID: Codable, Identifiable, Hashable { +enum EditorTabID: Codable, Identifiable, Hashable { var id: String { switch self { case .codeEditor(let path): diff --git a/CodeEdit/Features/Tabs/Models/TabBarItemRepresentable.swift b/CodeEdit/Features/Editor/Tab/Models/EditorTabRepresentable.swift similarity index 64% rename from CodeEdit/Features/Tabs/Models/TabBarItemRepresentable.swift rename to CodeEdit/Features/Editor/Tab/Models/EditorTabRepresentable.swift index 4c7ca8a08c..771de2067d 100644 --- a/CodeEdit/Features/Tabs/Models/TabBarItemRepresentable.swift +++ b/CodeEdit/Features/Editor/Tab/Models/EditorTabRepresentable.swift @@ -1,5 +1,5 @@ // -// TabBarItemRepresentable.swift +// EditorTabRepresentable.swift // // // Created by Pavel Kasila on 30.04.22. @@ -7,10 +7,10 @@ import SwiftUI -/// Protocol for data passed to TabBarItemView to conform to -protocol TabBarItemRepresentable { +/// Protocol for data passed to EditorTabView to conform to +protocol EditorTabRepresentable { /// Unique tab identifier - var tabID: TabBarItemID { get } + var tabID: EditorTabID { get } /// String to be shown as tab's title var name: String { get } /// Image to be shown as tab's icon diff --git a/CodeEdit/Features/Tabs/Views/TabBarAccessory.swift b/CodeEdit/Features/Editor/TabBar/Views/TabBarAccessory.swift similarity index 87% rename from CodeEdit/Features/Tabs/Views/TabBarAccessory.swift rename to CodeEdit/Features/Editor/TabBar/Views/TabBarAccessory.swift index 6cbf3cbd8a..488e83c582 100644 --- a/CodeEdit/Features/Tabs/Views/TabBarAccessory.swift +++ b/CodeEdit/Features/Editor/TabBar/Views/TabBarAccessory.swift @@ -13,19 +13,23 @@ struct TabBarAccessoryIcon: View { static let iconFont = Font.system(size: 14, weight: .regular, design: .default) private let icon: Image + private let isActive: Bool private let action: () -> Void - init(icon: Image, action: @escaping () -> Void) { + init(icon: Image, isActive: Bool = false, action: @escaping () -> Void) { self.icon = icon + self.isActive = isActive self.action = action } var body: some View { Button( action: action, - label: { icon } + label: { + icon + } ) - .buttonStyle(.icon(size: 24)) + .buttonStyle(.icon(isActive: isActive, size: 24)) } } diff --git a/CodeEdit/Features/Tabs/Views/TabBarContextMenu.swift b/CodeEdit/Features/Editor/TabBar/Views/TabBarContextMenu.swift similarity index 96% rename from CodeEdit/Features/Tabs/Views/TabBarContextMenu.swift rename to CodeEdit/Features/Editor/TabBar/Views/TabBarContextMenu.swift index 75b2124372..35791b9805 100644 --- a/CodeEdit/Features/Tabs/Views/TabBarContextMenu.swift +++ b/CodeEdit/Features/Editor/TabBar/Views/TabBarContextMenu.swift @@ -25,7 +25,7 @@ struct TabBarContextMenu: ViewModifier { @EnvironmentObject var workspace: WorkspaceDocument - @EnvironmentObject var tabs: TabGroupData + @EnvironmentObject var tabs: Editor @Environment(\.splitEditor) var splitEditor @@ -136,10 +136,10 @@ struct TabBarContextMenu: ViewModifier { } func moveToNewSplit(_ edge: Edge) { - let newTabGroup = TabGroupData(files: [item]) - splitEditor(edge, newTabGroup) + let newEditor = Editor(files: [item]) + splitEditor(edge, newEditor) tabs.closeTab(item: item) - workspace.tabManager.activeTabGroup = newTabGroup + workspace.editorManager.activeEditor = newEditor } /// Copies the relative path from the workspace folder to the given file item to the pasteboard. diff --git a/CodeEdit/Features/Tabs/Views/TabBarDivider.swift b/CodeEdit/Features/Editor/TabBar/Views/TabBarDivider.swift similarity index 100% rename from CodeEdit/Features/Tabs/Views/TabBarDivider.swift rename to CodeEdit/Features/Editor/TabBar/Views/TabBarDivider.swift diff --git a/CodeEdit/Features/Tabs/Views/TabBarNative.swift b/CodeEdit/Features/Editor/TabBar/Views/TabBarNative.swift similarity index 100% rename from CodeEdit/Features/Tabs/Views/TabBarNative.swift rename to CodeEdit/Features/Editor/TabBar/Views/TabBarNative.swift diff --git a/CodeEdit/Features/Tabs/Views/TabBarShadow.swift b/CodeEdit/Features/Editor/TabBar/Views/TabBarShadow.swift similarity index 100% rename from CodeEdit/Features/Tabs/Views/TabBarShadow.swift rename to CodeEdit/Features/Editor/TabBar/Views/TabBarShadow.swift diff --git a/CodeEdit/Features/Tabs/Views/TabBarView.swift b/CodeEdit/Features/Editor/TabBar/Views/TabBarView.swift similarity index 85% rename from CodeEdit/Features/Tabs/Views/TabBarView.swift rename to CodeEdit/Features/Editor/TabBar/Views/TabBarView.swift index 30aa8417ad..b840bf309f 100644 --- a/CodeEdit/Features/Tabs/Views/TabBarView.swift +++ b/CodeEdit/Features/Editor/TabBar/Views/TabBarView.swift @@ -11,7 +11,7 @@ import SwiftUI // It has the gesture implementation and its animations. // I am now also disabling `file_length` rule because the dragging algorithm (with UX) is complex. // swiftlint:disable file_length type_body_length -// - TODO: TabBarItemView drop-outside event handler. +// - TODO: EditorTabView drop-outside event handler. struct TabBarView: View { typealias TabID = CEWorkspaceFile.ID @@ -35,9 +35,9 @@ struct TabBarView: View { /// The workspace document. @EnvironmentObject private var workspace: WorkspaceDocument - @EnvironmentObject private var tabManager: TabManager + @EnvironmentObject private var editorManager: EditorManager - @EnvironmentObject private var tabgroup: TabGroupData + @EnvironmentObject private var editor: Editor @AppSettings(\.general.tabBarStyle) var tabBarStyle @@ -124,7 +124,7 @@ struct TabBarView: View { private func updateExpectedTabWidth(proxy: GeometryProxy) { expectedTabWidth = max( // Equally divided size of a native tab. - (proxy.size.width + 1) / CGFloat(tabgroup.tabs.count) + 1, + (proxy.size.width + 1) / CGFloat(editor.tabs.count) + 1, // Min size of a native tab. CGFloat(140) ) @@ -238,8 +238,8 @@ struct TabBarView: View { // In order to avoid the lag due to the update of workspace state. DispatchQueue.main.asyncAfter(deadline: .now() + 0.40) { if draggingStartLocation == nil { - tabgroup.tabs = .init(openedTabs.compactMap { id in - tabgroup.tabs.first { $0.id == id } + editor.tabs = .init(openedTabs.compactMap { id in + editor.tabs.first { $0.id == id } }) // workspace.reorderedTabs(openedTabs: openedTabs) // TODO: Fix save state @@ -277,7 +277,7 @@ struct TabBarView: View { /// Called when the tab count changes or the temporary tab changes. /// - Parameter geometryProxy: The geometry proxy to calculate the new width using. private func updateForTabCountChange(geometryProxy: GeometryProxy) { - openedTabs = tabgroup.tabs.map(\.id) + openedTabs = editor.tabs.map(\.id) // Only update the expected width when user is not hovering over tabs. // This should give users a better experience on closing multiple tabs continuously. @@ -319,8 +319,8 @@ struct TabBarView: View { spacing: -1 // Negative spacing for overlapping the divider. ) { ForEach(Array(openedTabs.enumerated()), id: \.element) { index, id in - if let item = tabgroup.tabs.first(where: { $0.id == id }) { - TabBarItemView( + if let item = editor.tabs.first(where: { $0.id == id }) { + EditorTabView( expectedWidth: expectedTabWidth, item: item, index: index, @@ -345,7 +345,7 @@ struct TabBarView: View { // Detect the drop action of each tab. .onDrop( of: [.utf8PlainText], // TODO: Make a unique type for it. - delegate: TabBarItemOnDropDelegate( + delegate: EditorTabOnDropDelegate( currentTabId: id, openedTabs: $openedTabs, onDragTabId: $onDragTabId, @@ -360,13 +360,13 @@ struct TabBarView: View { // This padding is to hide dividers at two ends under the accessory view divider. .padding(.horizontal, tabBarStyle == .native ? -1 : 0) .onAppear { - openedTabs = tabgroup.tabs.map(\.id) + openedTabs = editor.tabs.map(\.id) // On view appeared, compute the initial expected width for tabs. updateExpectedTabWidth(proxy: geometryProxy) // On first tab appeared, jump to the corresponding position. - scrollReader.scrollTo(tabgroup.selected) + scrollReader.scrollTo(editor.selectedTab) } - .onChange(of: tabgroup.tabs) { [tabs = tabgroup.tabs] newValue in + .onChange(of: editor.tabs) { [tabs = editor.tabs] newValue in if tabs.count == newValue.count { updateForTabCountChange(geometryProxy: geometryProxy) } else { @@ -379,12 +379,12 @@ struct TabBarView: View { Task { try? await Task.sleep(for: .milliseconds(300)) withAnimation { - scrollReader.scrollTo(tabgroup.selected?.id) + scrollReader.scrollTo(editor.selectedTab?.id) } } } // When selected tab is changed, scroll to it if possible. - .onChange(of: tabgroup.selected) { newValue in + .onChange(of: editor.selectedTab) { newValue in withAnimation { scrollReader.scrollTo(newValue?.id) } @@ -394,7 +394,7 @@ struct TabBarView: View { .onChange(of: geometryProxy.size.width) { _ in updateExpectedTabWidth(proxy: geometryProxy) withAnimation { - scrollReader.scrollTo(tabgroup.selected?.id) + scrollReader.scrollTo(editor.selectedTab?.id) } } // When user is not hovering anymore, re-compute the expected tab width immediately. @@ -459,24 +459,46 @@ struct TabBarView: View { // MARK: Accessories private var leadingAccessories: some View { - HStack(spacing: 2) { - if let otherGroup = tabManager.tabGroups.findSomeTabGroup(except: tabgroup) { + HStack(spacing: 0) { + if let otherGroup = editorManager.editorLayout.findSomeEditor(except: editor) { TabBarAccessoryIcon( icon: .init(systemName: "multiply"), - action: { [weak tabgroup] in - tabgroup?.close() - if tabManager.activeTabGroup == tabgroup { - tabManager.activeTabGroupHistory.removeAll { $0() == nil || $0() == tabgroup } - if tabManager.activeTabGroupHistory.isEmpty { - tabManager.activeTabGroup = otherGroup + action: { [weak editor] in + editor?.close() + if editorManager.activeEditor == editor { + editorManager.activeEditorHistory.removeAll { $0() == nil || $0() == editor } + if editorManager.activeEditorHistory.isEmpty { + editorManager.activeEditor = otherGroup } else { - tabManager.activeTabGroup = tabManager.activeTabGroupHistory.removeFirst()()! + editorManager.activeEditor = editorManager.activeEditorHistory.removeFirst()()! } } - tabManager.flatten() + editorManager.flatten() } ) .help("Close this Editor") + .disabled(editorManager.isFocusingActiveEditor) + .opacity(editorManager.isFocusingActiveEditor ? 0.5 : 1) + + TabBarAccessoryIcon( + icon: .init( + systemName: editorManager.isFocusingActiveEditor + ? "arrow.down.forward.and.arrow.up.backward" + : "arrow.up.left.and.arrow.down.right" + ), + isActive: editorManager.isFocusingActiveEditor, + action: { + if !editorManager.isFocusingActiveEditor { + editorManager.activeEditor = editor + } + editorManager.isFocusingActiveEditor.toggle() + } + ) + .help( + editorManager.isFocusingActiveEditor + ? "Unfocus this Editor" + : "Focus this Editor" + ) Divider() .frame(height: 10) @@ -486,12 +508,12 @@ struct TabBarView: View { Group { Menu { ForEach( - Array(tabgroup.history.dropFirst(tabgroup.historyOffset+1).enumerated()), + Array(editor.history.dropFirst(editor.historyOffset+1).enumerated()), id: \.offset ) { index, tab in Button { - tabManager.activeTabGroup = tabgroup - tabgroup.historyOffset += index + 1 + editorManager.activeEditor = editor + editor.historyOffset += index + 1 } label: { HStack { tab.icon @@ -503,24 +525,24 @@ struct TabBarView: View { Image(systemName: "chevron.left") .controlSize(.regular) .opacity( - tabgroup.historyOffset == tabgroup.history.count-1 || tabgroup.history.isEmpty + editor.historyOffset == editor.history.count-1 || editor.history.isEmpty ? 0.5 : 1.0 ) } primaryAction: { - tabManager.activeTabGroup = tabgroup - tabgroup.goBackInHistory() + editorManager.activeEditor = editor + editor.goBackInHistory() } - .disabled(tabgroup.historyOffset == tabgroup.history.count-1 || tabgroup.history.isEmpty) + .disabled(editor.historyOffset == editor.history.count-1 || editor.history.isEmpty) .help("Navigate back") Menu { ForEach( - Array(tabgroup.history.prefix(tabgroup.historyOffset).reversed().enumerated()), + Array(editor.history.prefix(editor.historyOffset).reversed().enumerated()), id: \.offset ) { index, tab in Button { - tabManager.activeTabGroup = tabgroup - tabgroup.historyOffset -= index + 1 + editorManager.activeEditor = editor + editor.historyOffset -= index + 1 } label: { HStack { tab.icon @@ -531,12 +553,12 @@ struct TabBarView: View { } label: { Image(systemName: "chevron.right") .controlSize(.regular) - .opacity(tabgroup.historyOffset == 0 ? 0.5 : 1.0) + .opacity(editor.historyOffset == 0 ? 0.5 : 1.0) } primaryAction: { - tabManager.activeTabGroup = tabgroup - tabgroup.goForwardInHistory() + editorManager.activeEditor = editor + editor.goForwardInHistory() } - .disabled(tabgroup.historyOffset == 0) + .disabled(editor.historyOffset == 0) .help("Navigate forward") } .controlSize(.small) @@ -547,7 +569,7 @@ struct TabBarView: View { } .foregroundColor(.secondary) .buttonStyle(.plain) - .padding(.horizontal, 7) + .padding(.horizontal, 5) .opacity(activeState != .inactive ? 1.0 : 0.5) .frame(maxHeight: .infinity) // Fill out vertical spaces. .background { @@ -558,10 +580,10 @@ struct TabBarView: View { } private var trailingAccessories: some View { - HStack(spacing: 2) { + HStack(spacing: 0) { splitviewButton } - .padding(.horizontal, 10) + .padding(.horizontal, 7) .opacity(activeState != .inactive ? 1.0 : 0.5) .frame(maxHeight: .infinity) // Fill out vertical spaces. .background { @@ -573,7 +595,7 @@ struct TabBarView: View { var splitviewButton: some View { Group { - switch (tabgroup.parent?.axis, modifierKeys.contains(.option)) { + switch (editor.parent?.axis, modifierKeys.contains(.option)) { case (.horizontal, true), (.vertical, false): Button { split(edge: .bottom) @@ -595,20 +617,22 @@ struct TabBarView: View { } } .buttonStyle(.icon) + .disabled(editorManager.isFocusingActiveEditor) + .opacity(editorManager.isFocusingActiveEditor ? 0.5 : 1) } func split(edge: Edge) { - let newTabgroup: TabGroupData - if let tab = tabgroup.selected { - newTabgroup = .init(files: [tab]) + let newEditor: Editor + if let tab = editor.selectedTab { + newEditor = .init(files: [tab]) } else { - newTabgroup = .init() + newEditor = .init() } - splitEditor(edge, newTabgroup) - tabManager.activeTabGroup = newTabgroup + splitEditor(edge, newEditor) + editorManager.activeEditor = newEditor } - private struct TabBarItemOnDropDelegate: DropDelegate { + private struct EditorTabOnDropDelegate: DropDelegate { private let currentTabId: TabID @Binding private var openedTabs: [TabID] @Binding private var onDragTabId: TabID? diff --git a/CodeEdit/Features/Tabs/Views/TabBarXcode.swift b/CodeEdit/Features/Editor/TabBar/Views/TabBarXcode.swift similarity index 100% rename from CodeEdit/Features/Tabs/Views/TabBarXcode.swift rename to CodeEdit/Features/Editor/TabBar/Views/TabBarXcode.swift diff --git a/CodeEdit/Features/SplitView/Views/EditorView.swift b/CodeEdit/Features/Editor/Views/EditorLayoutView.swift similarity index 74% rename from CodeEdit/Features/SplitView/Views/EditorView.swift rename to CodeEdit/Features/Editor/Views/EditorLayoutView.swift index 9694e8b102..408bf476a7 100644 --- a/CodeEdit/Features/SplitView/Views/EditorView.swift +++ b/CodeEdit/Features/Editor/Views/EditorLayoutView.swift @@ -1,5 +1,5 @@ // -// EditorView.swift +// EditorLayoutView.swift // CodeEdit // // Created by Wouter Hennen on 20/02/2023. @@ -7,10 +7,10 @@ import SwiftUI -struct EditorView: View { - var tabgroup: TabGroup +struct EditorLayoutView: View { + var layout: EditorLayout - @FocusState.Binding var focus: TabGroupData? + @FocusState.Binding var focus: Editor? @Environment(\.window) private var window @@ -24,9 +24,9 @@ struct EditorView: View { var body: some View { VStack { - switch tabgroup { - case .one(let detailTabGroup): - WorkspaceTabGroupView(tabgroup: detailTabGroup, focus: $focus) + switch layout { + case .one(let detailEditor): + EditorView(editor: detailEditor, focus: $focus) .transformEnvironment(\.edgeInsets) { insets in switch isAtEdge { case .all: @@ -41,15 +41,15 @@ struct EditorView: View { } } case .vertical(let data), .horizontal(let data): - SubEditorView(data: data, focus: $focus) + SubEditorLayoutView(data: data, focus: $focus) } } } - struct SubEditorView: View { + struct SubEditorLayoutView: View { @ObservedObject var data: SplitViewData - @FocusState.Binding var focus: TabGroupData? + @FocusState.Binding var focus: Editor? var body: some View { SplitView(axis: data.axis) { @@ -59,21 +59,21 @@ struct EditorView: View { } var splitView: some View { - ForEach(Array(data.tabgroups.enumerated()), id: \.offset) { index, item in - EditorView(tabgroup: item, focus: $focus) + ForEach(Array(data.editorLayouts.enumerated()), id: \.offset) { index, item in + EditorLayoutView(layout: item, focus: $focus) .transformEnvironment(\.isAtEdge) { belowToolbar in calcIsAtEdge(current: &belowToolbar, index: index) } - .environment(\.splitEditor) { [weak data] edge, newTabGroup in - data?.split(edge, at: index, new: newTabGroup) + .environment(\.splitEditor) { [weak data] edge, newEditor in + data?.split(edge, at: index, new: newEditor) } } } func calcIsAtEdge(current: inout VerticalEdge.Set, index: Int) { if case .vertical = data.axis { - guard data.tabgroups.count != 1 else { return } - if index == data.tabgroups.count - 1 { + guard data.editorLayouts.count != 1 else { return } + if index == data.editorLayouts.count - 1 { current.remove(.top) } else if index == 0 { current.remove(.bottom) diff --git a/CodeEdit/Features/Tabs/TabGroup/WorkspaceTabGroupView.swift b/CodeEdit/Features/Editor/Views/EditorView.swift similarity index 55% rename from CodeEdit/Features/Tabs/TabGroup/WorkspaceTabGroupView.swift rename to CodeEdit/Features/Editor/Views/EditorView.swift index 7a4a69f756..57fcdb5dd4 100644 --- a/CodeEdit/Features/Tabs/TabGroup/WorkspaceTabGroupView.swift +++ b/CodeEdit/Features/Editor/Views/EditorView.swift @@ -1,5 +1,5 @@ // -// WorkspaceTabGroupView.swift +// EditorView.swift // CodeEdit // // Created by Wouter Hennen on 16/02/2023. @@ -7,20 +7,20 @@ import SwiftUI -struct WorkspaceTabGroupView: View { - @ObservedObject var tabgroup: TabGroupData +struct EditorView: View { + @ObservedObject var editor: Editor - @FocusState.Binding var focus: TabGroupData? + @FocusState.Binding var focus: Editor? - @EnvironmentObject private var tabManager: TabManager + @EnvironmentObject private var editorManager: EditorManager var body: some View { VStack { - if let selected = tabgroup.selected { + if let selected = editor.selectedTab { WorkspaceCodeFileView(file: selected) - .focusedObject(tabgroup) + .focusedObject(editor) .transformEnvironment(\.edgeInsets) { insets in - insets.top += TabBarView.height + PathBarView.height + 1 + 1 + insets.top += TabBarView.height + EditorPathBarView.height + 1 + 1 } } else { VStack { @@ -35,7 +35,7 @@ struct WorkspaceTabGroupView: View { .frame(maxWidth: .infinity, maxHeight: .infinity) .contentShape(Rectangle()) .onTapGesture { - tabManager.activeTabGroup = tabgroup + editorManager.activeEditor = editor } } } @@ -44,25 +44,22 @@ struct WorkspaceTabGroupView: View { .safeAreaInset(edge: .top, spacing: 0) { VStack(spacing: 0) { TabBarView() - .id("TabBarView" + tabgroup.id.uuidString) - .environmentObject(tabgroup) - + .id("TabBarView" + editor.id.uuidString) + .environmentObject(editor) Divider() - if let file = tabgroup.selected { - PathBarView(file: file) { [weak tabgroup] newFile in - if let index = tabgroup?.tabs.firstIndex(of: file) { - tabgroup?.openTab(item: newFile, at: index) - } + EditorPathBarView(file: editor.selectedTab) { [weak editor] newFile in + if let file = editor?.selectedTab, let index = editor?.tabs.firstIndex(of: file) { + editor?.openTab(item: newFile, at: index) } - Divider() } + Divider() } - .environment(\.isActiveTabGroup, tabgroup == tabManager.activeTabGroup) + .environment(\.isActiveEditor, editor == editorManager.activeEditor) .background(EffectView(.titlebar, blendingMode: .withinWindow, emphasized: false)) } - .focused($focus, equals: tabgroup) + .focused($focus, equals: editor) .onReceive(NotificationCenter.default.publisher(for: NSNotification.Name("CodeEditor.didBeginEditing"))) { _ in - tabgroup.temporaryTab = nil + editor.temporaryTab = nil } } } diff --git a/CodeEdit/Features/InspectorSidebar/Views/FileInspectorView.swift b/CodeEdit/Features/InspectorArea/FileInspector/FileInspectorView.swift similarity index 83% rename from CodeEdit/Features/InspectorSidebar/Views/FileInspectorView.swift rename to CodeEdit/Features/InspectorArea/FileInspector/FileInspectorView.swift index e84533cc05..925523717b 100644 --- a/CodeEdit/Features/InspectorSidebar/Views/FileInspectorView.swift +++ b/CodeEdit/Features/InspectorArea/FileInspector/FileInspectorView.swift @@ -10,7 +10,7 @@ import CodeEditLanguages struct FileInspectorView: View { @EnvironmentObject private var workspace: WorkspaceDocument - @EnvironmentObject private var tabManager: TabManager + @EnvironmentObject private var editorManager: EditorManager @AppSettings(\.textEditing) private var textEditing @@ -29,6 +29,20 @@ struct FileInspectorView: View { @State var wrapLines: Bool = false + func updateFileOptions(_ textEditingOverride: SettingsData.TextEditingSettings? = nil) { + let textEditingSettings = textEditingOverride ?? textEditing + indentOption = file?.fileDocument?.indentOption ?? textEditingSettings.indentOption + defaultTabWidth = file?.fileDocument?.defaultTabWidth ?? textEditingSettings.defaultTabWidth + wrapLines = file?.fileDocument?.wrapLines ?? textEditingSettings.wrapLinesToEditorWidth + } + + func updateInspectorSource() { + file = editorManager.activeEditor.selectedTab + fileName = file?.name ?? "" + language = file?.fileDocument?.language + updateFileOptions() + } + var body: some View { Group { if file != nil { @@ -50,26 +64,20 @@ struct FileInspectorView: View { NoSelectionInspectorView() } } - .onReceive(tabManager.activeTabGroup.objectWillChange) { _ in - file = tabManager.activeTabGroup.selected - fileName = file?.name ?? "" - language = file?.fileDocument?.language - indentOption = file?.fileDocument?.indentOption ?? textEditing.indentOption - defaultTabWidth = file?.fileDocument?.defaultTabWidth ?? textEditing.defaultTabWidth - wrapLines = file?.fileDocument?.wrapLines ?? textEditing.wrapLinesToEditorWidth - } .onAppear { - file = tabManager.activeTabGroup.selected - fileName = file?.name ?? "" - language = file?.fileDocument?.language - indentOption = file?.fileDocument?.indentOption ?? textEditing.indentOption - defaultTabWidth = file?.fileDocument?.defaultTabWidth ?? textEditing.defaultTabWidth - wrapLines = file?.fileDocument?.wrapLines ?? textEditing.wrapLinesToEditorWidth + updateInspectorSource() + } + .onReceive(editorManager.activeEditor.objectWillChange) { _ in + updateInspectorSource() + } + .onChange(of: editorManager.activeEditor) { _ in + updateInspectorSource() + } + .onChange(of: editorManager.activeEditor.selectedTab) { _ in + updateInspectorSource() } .onChange(of: textEditing) { newValue in - indentOption = file?.fileDocument?.indentOption ?? newValue.indentOption - defaultTabWidth = file?.fileDocument?.defaultTabWidth ?? newValue.defaultTabWidth - wrapLines = file?.fileDocument?.wrapLines ?? newValue.wrapLinesToEditorWidth + updateFileOptions(newValue) } } @@ -85,14 +93,14 @@ struct FileInspectorView: View { .deletingLastPathComponent() .appendingPathComponent(fileName) if !file.isFolder { - tabManager.tabGroups.closeAllTabs(of: file) + editorManager.editorLayout.closeAllTabs(of: file) } DispatchQueue.main.async { file.move(to: destinationURL) let newItem = CEWorkspaceFile(url: destinationURL) newItem.parent = file.parent if !newItem.isFolder { - tabManager.openTab(item: newItem) + editorManager.openTab(item: newItem) } } } else { @@ -127,7 +135,7 @@ struct FileInspectorView: View { return } if !file.isFolder { - tabManager.tabGroups.closeAllTabs(of: file) + editorManager.editorLayout.closeAllTabs(of: file) } // This is ugly but if the tab is opened at the same time as closing the others, it doesn't open // And if the files are re-built at the same time as the tab is opened, it causes a memory error @@ -140,7 +148,7 @@ struct FileInspectorView: View { let newItem = CEWorkspaceFile(url: newURL) newItem.parent = newParent if !file.isFolder { - tabManager.openTab(item: newItem) + editorManager.openTab(item: newItem) } DispatchQueue.main.async { _ = try? workspace.workspaceFileManager?.rebuildFiles(fromItem: newParent) diff --git a/CodeEdit/Features/InspectorSidebar/Views/HistoryInspectorItemView.swift b/CodeEdit/Features/InspectorArea/HistoryInspector/HistoryInspectorItemView.swift similarity index 100% rename from CodeEdit/Features/InspectorSidebar/Views/HistoryInspectorItemView.swift rename to CodeEdit/Features/InspectorArea/HistoryInspector/HistoryInspectorItemView.swift diff --git a/CodeEdit/Features/InspectorSidebar/Models/HistoryInspectorModel.swift b/CodeEdit/Features/InspectorArea/HistoryInspector/HistoryInspectorModel.swift similarity index 100% rename from CodeEdit/Features/InspectorSidebar/Models/HistoryInspectorModel.swift rename to CodeEdit/Features/InspectorArea/HistoryInspector/HistoryInspectorModel.swift diff --git a/CodeEdit/Features/InspectorSidebar/Views/HistoryInspectorNoHistoryView.swift b/CodeEdit/Features/InspectorArea/HistoryInspector/HistoryInspectorNoHistoryView.swift similarity index 100% rename from CodeEdit/Features/InspectorSidebar/Views/HistoryInspectorNoHistoryView.swift rename to CodeEdit/Features/InspectorArea/HistoryInspector/HistoryInspectorNoHistoryView.swift diff --git a/CodeEdit/Features/InspectorSidebar/Views/HistoryInspectorView.swift b/CodeEdit/Features/InspectorArea/HistoryInspector/HistoryInspectorView.swift similarity index 82% rename from CodeEdit/Features/InspectorSidebar/Views/HistoryInspectorView.swift rename to CodeEdit/Features/InspectorArea/HistoryInspector/HistoryInspectorView.swift index 9acbb19d4f..81be86f95a 100644 --- a/CodeEdit/Features/InspectorSidebar/Views/HistoryInspectorView.swift +++ b/CodeEdit/Features/InspectorArea/HistoryInspector/HistoryInspectorView.swift @@ -9,7 +9,7 @@ import SwiftUI struct HistoryInspectorView: View { @EnvironmentObject private var workspace: WorkspaceDocument - @EnvironmentObject private var tabManager: TabManager + @EnvironmentObject private var editorManager: EditorManager @ObservedObject private var model: HistoryInspectorModel @@ -42,12 +42,12 @@ struct HistoryInspectorView: View { NoSelectionInspectorView() } } - .onReceive(tabManager.activeTabGroup.objectWillChange) { _ in - model.setFile(url: tabManager.activeTabGroup.selected?.url.path) + .onReceive(editorManager.activeEditor.objectWillChange) { _ in + model.setFile(url: editorManager.activeEditor.selectedTab?.url.path) } .onAppear { model.setWorkspace(url: workspace.fileURL) - model.setFile(url: tabManager.activeTabGroup.selected?.url.path) + model.setFile(url: editorManager.activeEditor.selectedTab?.url.path) } } } diff --git a/CodeEdit/Features/InspectorSidebar/Views/Popover/HistoryPopoverView.swift b/CodeEdit/Features/InspectorArea/HistoryInspector/HistoryPopoverView.swift similarity index 100% rename from CodeEdit/Features/InspectorSidebar/Views/Popover/HistoryPopoverView.swift rename to CodeEdit/Features/InspectorArea/HistoryInspector/HistoryPopoverView.swift diff --git a/CodeEdit/Features/InspectorSidebar/InspectorSidebarToolbarTop.swift b/CodeEdit/Features/InspectorArea/InspectorSidebarToolbarTop.swift similarity index 100% rename from CodeEdit/Features/InspectorSidebar/InspectorSidebarToolbarTop.swift rename to CodeEdit/Features/InspectorArea/InspectorSidebarToolbarTop.swift diff --git a/CodeEdit/Features/InspectorSidebar/InspectorTab.swift b/CodeEdit/Features/InspectorArea/Models/InspectorTab.swift similarity index 100% rename from CodeEdit/Features/InspectorSidebar/InspectorTab.swift rename to CodeEdit/Features/InspectorArea/Models/InspectorTab.swift diff --git a/CodeEdit/Features/InspectorSidebar/InspectorSidebarView.swift b/CodeEdit/Features/InspectorArea/Views/InspectorAreaView.swift similarity index 94% rename from CodeEdit/Features/InspectorSidebar/InspectorSidebarView.swift rename to CodeEdit/Features/InspectorArea/Views/InspectorAreaView.swift index 2137b0c88f..3e83bdf383 100644 --- a/CodeEdit/Features/InspectorSidebar/InspectorSidebarView.swift +++ b/CodeEdit/Features/InspectorArea/Views/InspectorAreaView.swift @@ -1,5 +1,5 @@ // -// InspectorSidebarView.swift +// InspectorAreaView.swift // CodeEdit // // Created by Austin Condiff on 3/21/22. @@ -7,12 +7,12 @@ import SwiftUI -struct InspectorSidebarView: View { +struct InspectorAreaView: View { @EnvironmentObject private var workspace: WorkspaceDocument @ObservedObject private var extensionManager = ExtensionManager.shared - @EnvironmentObject private var tabManager: TabManager + @EnvironmentObject private var editorManager: EditorManager @AppSettings(\.general.inspectorTabBarPosition) var sidebarPosition: SettingsData.SidebarTabBarPosition diff --git a/CodeEdit/Features/InspectorSidebar/InspectorField.swift b/CodeEdit/Features/InspectorArea/Views/InspectorField.swift similarity index 100% rename from CodeEdit/Features/InspectorSidebar/InspectorField.swift rename to CodeEdit/Features/InspectorArea/Views/InspectorField.swift diff --git a/CodeEdit/Features/InspectorSidebar/InspectorSection.swift b/CodeEdit/Features/InspectorArea/Views/InspectorSection.swift similarity index 100% rename from CodeEdit/Features/InspectorSidebar/InspectorSection.swift rename to CodeEdit/Features/InspectorArea/Views/InspectorSection.swift diff --git a/CodeEdit/Features/InspectorSidebar/Views/NoSelectionInspectorView.swift b/CodeEdit/Features/InspectorArea/Views/NoSelectionInspectorView.swift similarity index 100% rename from CodeEdit/Features/InspectorSidebar/Views/NoSelectionInspectorView.swift rename to CodeEdit/Features/InspectorArea/Views/NoSelectionInspectorView.swift diff --git a/CodeEdit/Features/NavigatorSidebar/FindNavigator/FindNavigatorModeSelector.swift b/CodeEdit/Features/NavigatorArea/FindNavigator/FindNavigatorModeSelector.swift similarity index 100% rename from CodeEdit/Features/NavigatorSidebar/FindNavigator/FindNavigatorModeSelector.swift rename to CodeEdit/Features/NavigatorArea/FindNavigator/FindNavigatorModeSelector.swift diff --git a/CodeEdit/Features/NavigatorSidebar/FindNavigator/FindNavigatorResultFileItem.swift b/CodeEdit/Features/NavigatorArea/FindNavigator/FindNavigatorResultFileItem.swift similarity index 100% rename from CodeEdit/Features/NavigatorSidebar/FindNavigator/FindNavigatorResultFileItem.swift rename to CodeEdit/Features/NavigatorArea/FindNavigator/FindNavigatorResultFileItem.swift diff --git a/CodeEdit/Features/NavigatorSidebar/FindNavigator/FindNavigatorResultList/FindNavigatorListViewController.swift b/CodeEdit/Features/NavigatorArea/FindNavigator/FindNavigatorResultList/FindNavigatorListViewController.swift similarity index 98% rename from CodeEdit/Features/NavigatorSidebar/FindNavigator/FindNavigatorResultList/FindNavigatorListViewController.swift rename to CodeEdit/Features/NavigatorArea/FindNavigator/FindNavigatorResultList/FindNavigatorListViewController.swift index f31b03f8bf..501686b721 100644 --- a/CodeEdit/Features/NavigatorSidebar/FindNavigator/FindNavigatorResultList/FindNavigatorListViewController.swift +++ b/CodeEdit/Features/NavigatorArea/FindNavigator/FindNavigatorResultList/FindNavigatorListViewController.swift @@ -197,13 +197,13 @@ extension FindNavigatorListViewController: NSOutlineViewDelegate { let selectedMatch = self.selectedItem as? SearchResultMatchModel if selectedItem == nil || selectedMatch != item { self.selectedItem = item - workspace.tabManager.openTab(item: item.file) + workspace.editorManager.openTab(item: item.file) } } else if let item = outlineView.item(atRow: selectedIndex) as? SearchResultModel { let selectedFile = self.selectedItem as? SearchResultModel if selectedItem == nil || selectedFile != item { self.selectedItem = item - workspace.tabManager.openTab(item: item.file) + workspace.editorManager.openTab(item: item.file) } } } diff --git a/CodeEdit/Features/NavigatorSidebar/FindNavigator/FindNavigatorResultList/FindNavigatorMatchListCell.swift b/CodeEdit/Features/NavigatorArea/FindNavigator/FindNavigatorResultList/FindNavigatorMatchListCell.swift similarity index 100% rename from CodeEdit/Features/NavigatorSidebar/FindNavigator/FindNavigatorResultList/FindNavigatorMatchListCell.swift rename to CodeEdit/Features/NavigatorArea/FindNavigator/FindNavigatorResultList/FindNavigatorMatchListCell.swift diff --git a/CodeEdit/Features/NavigatorSidebar/FindNavigator/FindNavigatorResultList/FindNavigatorResultList.swift b/CodeEdit/Features/NavigatorArea/FindNavigator/FindNavigatorResultList/FindNavigatorResultList.swift similarity index 100% rename from CodeEdit/Features/NavigatorSidebar/FindNavigator/FindNavigatorResultList/FindNavigatorResultList.swift rename to CodeEdit/Features/NavigatorArea/FindNavigator/FindNavigatorResultList/FindNavigatorResultList.swift diff --git a/CodeEdit/Features/NavigatorSidebar/FindNavigator/FindNavigatorSearchBar.swift b/CodeEdit/Features/NavigatorArea/FindNavigator/FindNavigatorSearchBar.swift similarity index 100% rename from CodeEdit/Features/NavigatorSidebar/FindNavigator/FindNavigatorSearchBar.swift rename to CodeEdit/Features/NavigatorArea/FindNavigator/FindNavigatorSearchBar.swift diff --git a/CodeEdit/Features/NavigatorSidebar/FindNavigator/FindNavigatorView.swift b/CodeEdit/Features/NavigatorArea/FindNavigator/FindNavigatorView.swift similarity index 100% rename from CodeEdit/Features/NavigatorSidebar/FindNavigator/FindNavigatorView.swift rename to CodeEdit/Features/NavigatorArea/FindNavigator/FindNavigatorView.swift diff --git a/CodeEdit/Features/NavigatorSidebar/NavigatorTab.swift b/CodeEdit/Features/NavigatorArea/Models/NavigatorTab.swift similarity index 100% rename from CodeEdit/Features/NavigatorSidebar/NavigatorTab.swift rename to CodeEdit/Features/NavigatorArea/Models/NavigatorTab.swift diff --git a/CodeEdit/Features/NavigatorSidebar/NavigatorSidebarToolbar.swift b/CodeEdit/Features/NavigatorArea/NavigatorSidebarToolbar.swift similarity index 100% rename from CodeEdit/Features/NavigatorSidebar/NavigatorSidebarToolbar.swift rename to CodeEdit/Features/NavigatorArea/NavigatorSidebarToolbar.swift diff --git a/CodeEdit/Features/NavigatorSidebar/NavigatorSidebarViewModel.swift b/CodeEdit/Features/NavigatorArea/NavigatorSidebarViewModel.swift similarity index 100% rename from CodeEdit/Features/NavigatorSidebar/NavigatorSidebarViewModel.swift rename to CodeEdit/Features/NavigatorArea/NavigatorSidebarViewModel.swift diff --git a/CodeEdit/Features/NavigatorSidebar/OutlineView/FileSystemTableViewCell.swift b/CodeEdit/Features/NavigatorArea/OutlineView/FileSystemTableViewCell.swift similarity index 100% rename from CodeEdit/Features/NavigatorSidebar/OutlineView/FileSystemTableViewCell.swift rename to CodeEdit/Features/NavigatorArea/OutlineView/FileSystemTableViewCell.swift diff --git a/CodeEdit/Features/NavigatorSidebar/OutlineView/StandardTableViewCell.swift b/CodeEdit/Features/NavigatorArea/OutlineView/StandardTableViewCell.swift similarity index 100% rename from CodeEdit/Features/NavigatorSidebar/OutlineView/StandardTableViewCell.swift rename to CodeEdit/Features/NavigatorArea/OutlineView/StandardTableViewCell.swift diff --git a/CodeEdit/Features/NavigatorSidebar/OutlineView/TextTableViewCell.swift b/CodeEdit/Features/NavigatorArea/OutlineView/TextTableViewCell.swift similarity index 100% rename from CodeEdit/Features/NavigatorSidebar/OutlineView/TextTableViewCell.swift rename to CodeEdit/Features/NavigatorArea/OutlineView/TextTableViewCell.swift diff --git a/CodeEdit/Features/NavigatorSidebar/ProjectNavigator/OutlineView/ProjectNavigatorMenu.swift b/CodeEdit/Features/NavigatorArea/ProjectNavigator/OutlineView/ProjectNavigatorMenu.swift similarity index 99% rename from CodeEdit/Features/NavigatorSidebar/ProjectNavigator/OutlineView/ProjectNavigatorMenu.swift rename to CodeEdit/Features/NavigatorArea/ProjectNavigator/OutlineView/ProjectNavigatorMenu.swift index a55af9df91..c8e42d0dfb 100644 --- a/CodeEdit/Features/NavigatorSidebar/ProjectNavigator/OutlineView/ProjectNavigatorMenu.swift +++ b/CodeEdit/Features/NavigatorArea/ProjectNavigator/OutlineView/ProjectNavigatorMenu.swift @@ -185,7 +185,7 @@ final class ProjectNavigatorMenu: NSMenu { @objc private func openInTab() { if let item { - workspace?.tabManager.openTab(item: item) + workspace?.editorManager.openTab(item: item) } } diff --git a/CodeEdit/Features/NavigatorSidebar/ProjectNavigator/OutlineView/ProjectNavigatorOutlineView.swift b/CodeEdit/Features/NavigatorArea/ProjectNavigator/OutlineView/ProjectNavigatorOutlineView.swift similarity index 91% rename from CodeEdit/Features/NavigatorSidebar/ProjectNavigator/OutlineView/ProjectNavigatorOutlineView.swift rename to CodeEdit/Features/NavigatorArea/ProjectNavigator/OutlineView/ProjectNavigatorOutlineView.swift index b5cc585ef9..62acad32f1 100644 --- a/CodeEdit/Features/NavigatorSidebar/ProjectNavigator/OutlineView/ProjectNavigatorOutlineView.swift +++ b/CodeEdit/Features/NavigatorArea/ProjectNavigator/OutlineView/ProjectNavigatorOutlineView.swift @@ -35,7 +35,7 @@ struct ProjectNavigatorOutlineView: NSViewControllerRepresentable { nsViewController.shownFileExtensions = prefs.preferences.general.shownFileExtensions nsViewController.hiddenFileExtensions = prefs.preferences.general.hiddenFileExtensions /// if the window becomes active from background, it will restore the selection to outline view. - nsViewController.updateSelection(itemID: workspace.tabManager.activeTabGroup.selected?.id) + nsViewController.updateSelection(itemID: workspace.editorManager.activeEditor.selectedTab?.id) return } @@ -56,7 +56,7 @@ struct ProjectNavigatorOutlineView: NSViewControllerRepresentable { self?.controller?.reveal(fileItem) }) .store(in: &cancellables) - workspace.tabManager.tabBarItemIdSubject + workspace.editorManager.tabBarTabIdSubject .sink { [weak self] itemID in self?.controller?.updateSelection(itemID: itemID) } @@ -69,7 +69,7 @@ struct ProjectNavigatorOutlineView: NSViewControllerRepresentable { func fileManagerUpdated() { controller?.outlineView.reloadData() - controller?.updateSelection(itemID: workspace.tabManager.activeTabGroup.selected?.id) + controller?.updateSelection(itemID: workspace.editorManager.activeEditor.selectedTab?.id) } deinit { diff --git a/CodeEdit/Features/NavigatorSidebar/ProjectNavigator/OutlineView/ProjectNavigatorTableViewCell.swift b/CodeEdit/Features/NavigatorArea/ProjectNavigator/OutlineView/ProjectNavigatorTableViewCell.swift similarity index 100% rename from CodeEdit/Features/NavigatorSidebar/ProjectNavigator/OutlineView/ProjectNavigatorTableViewCell.swift rename to CodeEdit/Features/NavigatorArea/ProjectNavigator/OutlineView/ProjectNavigatorTableViewCell.swift diff --git a/CodeEdit/Features/NavigatorSidebar/ProjectNavigator/OutlineView/ProjectNavigatorViewController+NSMenuDelegate.swift b/CodeEdit/Features/NavigatorArea/ProjectNavigator/OutlineView/ProjectNavigatorViewController+NSMenuDelegate.swift similarity index 100% rename from CodeEdit/Features/NavigatorSidebar/ProjectNavigator/OutlineView/ProjectNavigatorViewController+NSMenuDelegate.swift rename to CodeEdit/Features/NavigatorArea/ProjectNavigator/OutlineView/ProjectNavigatorViewController+NSMenuDelegate.swift diff --git a/CodeEdit/Features/NavigatorSidebar/ProjectNavigator/OutlineView/ProjectNavigatorViewController+OutlineTableViewCellDelegate.swift b/CodeEdit/Features/NavigatorArea/ProjectNavigator/OutlineView/ProjectNavigatorViewController+OutlineTableViewCellDelegate.swift similarity index 78% rename from CodeEdit/Features/NavigatorSidebar/ProjectNavigator/OutlineView/ProjectNavigatorViewController+OutlineTableViewCellDelegate.swift rename to CodeEdit/Features/NavigatorArea/ProjectNavigator/OutlineView/ProjectNavigatorViewController+OutlineTableViewCellDelegate.swift index 4f2a4ab6f5..852facc25e 100644 --- a/CodeEdit/Features/NavigatorSidebar/ProjectNavigator/OutlineView/ProjectNavigatorViewController+OutlineTableViewCellDelegate.swift +++ b/CodeEdit/Features/NavigatorArea/ProjectNavigator/OutlineView/ProjectNavigatorViewController+OutlineTableViewCellDelegate.swift @@ -12,11 +12,11 @@ import Foundation extension ProjectNavigatorViewController: OutlineTableViewCellDelegate { func moveFile(file: CEWorkspaceFile, to destination: URL) { if !file.isFolder { - workspace?.tabManager.tabGroups.closeAllTabs(of: file) + workspace?.editorManager.editorLayout.closeAllTabs(of: file) } file.move(to: destination) if !file.isFolder { - workspace?.tabManager.openTab(item: .init(url: destination)) + workspace?.editorManager.openTab(item: .init(url: destination)) } } diff --git a/CodeEdit/Features/NavigatorSidebar/ProjectNavigator/OutlineView/ProjectNavigatorViewController.swift b/CodeEdit/Features/NavigatorArea/ProjectNavigator/OutlineView/ProjectNavigatorViewController.swift similarity index 96% rename from CodeEdit/Features/NavigatorSidebar/ProjectNavigator/OutlineView/ProjectNavigatorViewController.swift rename to CodeEdit/Features/NavigatorArea/ProjectNavigator/OutlineView/ProjectNavigatorViewController.swift index ea8af0c651..bb23f82839 100644 --- a/CodeEdit/Features/NavigatorSidebar/ProjectNavigator/OutlineView/ProjectNavigatorViewController.swift +++ b/CodeEdit/Features/NavigatorArea/ProjectNavigator/OutlineView/ProjectNavigatorViewController.swift @@ -89,7 +89,7 @@ final class ProjectNavigatorViewController: NSViewController { /// Forces to reveal the selected file through the command regardless of the auto reveal setting @objc func revealFile(_ sender: Any) { - updateSelection(itemID: workspace?.tabManager.activeTabGroup.selected?.id, forcesReveal: true) + updateSelection(itemID: workspace?.editorManager.activeEditor.selectedTab?.id, forcesReveal: true) } /// Updates the selection of the ``outlineView`` whenever it changes. @@ -117,7 +117,7 @@ final class ProjectNavigatorViewController: NSViewController { outlineView.expandItem(item) } } else { - workspace?.tabManager.activeTabGroup.openTab(item: item, asTemporary: false) + workspace?.editorManager.activeEditor.openTab(item: item, asTemporary: false) } } @@ -281,7 +281,7 @@ extension ProjectNavigatorViewController: NSOutlineViewDelegate { if item.children == nil && shouldSendSelectionUpdate { DispatchQueue.main.async { - self.workspace?.tabManager.activeTabGroup.openTab(item: item, asTemporary: true) + self.workspace?.editorManager.activeEditor.openTab(item: item, asTemporary: true) } } } @@ -292,7 +292,7 @@ extension ProjectNavigatorViewController: NSOutlineViewDelegate { func outlineViewItemDidExpand(_ notification: Notification) { guard - let id = workspace?.tabManager.activeTabGroup.selected?.id, + let id = workspace?.editorManager.activeEditor.selectedTab?.id, let item = content.find(by: .codeEditor(id)) else { return @@ -325,7 +325,7 @@ extension ProjectNavigatorViewController: NSOutlineViewDelegate { /// - id: the id of the item item /// - collection: the array to search for /// - forcesReveal: The boolean to indicates whether or not it should force to reveal the selected file. - private func select(by id: TabBarItemID, from collection: [CEWorkspaceFile], forcesReveal: Bool) { + private func select(by id: EditorTabID, from collection: [CEWorkspaceFile], forcesReveal: Bool) { guard let item = collection.find(by: id) else { return } diff --git a/CodeEdit/Features/NavigatorSidebar/ProjectNavigator/ProjectNavigatorToolbarBottom.swift b/CodeEdit/Features/NavigatorArea/ProjectNavigator/ProjectNavigatorToolbarBottom.swift similarity index 100% rename from CodeEdit/Features/NavigatorSidebar/ProjectNavigator/ProjectNavigatorToolbarBottom.swift rename to CodeEdit/Features/NavigatorArea/ProjectNavigator/ProjectNavigatorToolbarBottom.swift diff --git a/CodeEdit/Features/NavigatorSidebar/ProjectNavigator/ProjectNavigatorView.swift b/CodeEdit/Features/NavigatorArea/ProjectNavigator/ProjectNavigatorView.swift similarity index 100% rename from CodeEdit/Features/NavigatorSidebar/ProjectNavigator/ProjectNavigatorView.swift rename to CodeEdit/Features/NavigatorArea/ProjectNavigator/ProjectNavigatorView.swift diff --git a/CodeEdit/Features/NavigatorSidebar/SourceControlNavigator/Model/SourceControlModel.swift b/CodeEdit/Features/NavigatorArea/SourceControlNavigator/Model/SourceControlModel.swift similarity index 100% rename from CodeEdit/Features/NavigatorSidebar/SourceControlNavigator/Model/SourceControlModel.swift rename to CodeEdit/Features/NavigatorArea/SourceControlNavigator/Model/SourceControlModel.swift diff --git a/CodeEdit/Features/NavigatorSidebar/SourceControlNavigator/SourceControlNavigatorView.swift b/CodeEdit/Features/NavigatorArea/SourceControlNavigator/SourceControlNavigatorView.swift similarity index 100% rename from CodeEdit/Features/NavigatorSidebar/SourceControlNavigator/SourceControlNavigatorView.swift rename to CodeEdit/Features/NavigatorArea/SourceControlNavigator/SourceControlNavigatorView.swift diff --git a/CodeEdit/Features/NavigatorSidebar/SourceControlNavigator/SourceControlSearchToolbar.swift b/CodeEdit/Features/NavigatorArea/SourceControlNavigator/SourceControlSearchToolbar.swift similarity index 100% rename from CodeEdit/Features/NavigatorSidebar/SourceControlNavigator/SourceControlSearchToolbar.swift rename to CodeEdit/Features/NavigatorArea/SourceControlNavigator/SourceControlSearchToolbar.swift diff --git a/CodeEdit/Features/NavigatorSidebar/SourceControlNavigator/SourceControlToolbarBottom.swift b/CodeEdit/Features/NavigatorArea/SourceControlNavigator/SourceControlToolbarBottom.swift similarity index 100% rename from CodeEdit/Features/NavigatorSidebar/SourceControlNavigator/SourceControlToolbarBottom.swift rename to CodeEdit/Features/NavigatorArea/SourceControlNavigator/SourceControlToolbarBottom.swift diff --git a/CodeEdit/Features/NavigatorSidebar/SourceControlNavigator/Views/Changes/SourceControlNavigatorChangedFileView.swift b/CodeEdit/Features/NavigatorArea/SourceControlNavigator/Views/Changes/SourceControlNavigatorChangedFileView.swift similarity index 100% rename from CodeEdit/Features/NavigatorSidebar/SourceControlNavigator/Views/Changes/SourceControlNavigatorChangedFileView.swift rename to CodeEdit/Features/NavigatorArea/SourceControlNavigator/Views/Changes/SourceControlNavigatorChangedFileView.swift diff --git a/CodeEdit/Features/NavigatorSidebar/SourceControlNavigator/Views/Changes/SourceControlNavigatorChangesView.swift b/CodeEdit/Features/NavigatorArea/SourceControlNavigator/Views/Changes/SourceControlNavigatorChangesView.swift similarity index 100% rename from CodeEdit/Features/NavigatorSidebar/SourceControlNavigator/Views/Changes/SourceControlNavigatorChangesView.swift rename to CodeEdit/Features/NavigatorArea/SourceControlNavigator/Views/Changes/SourceControlNavigatorChangesView.swift diff --git a/CodeEdit/Features/NavigatorSidebar/SourceControlNavigator/Views/Repositories/SourceControlNavigatorRepositoriesView.swift b/CodeEdit/Features/NavigatorArea/SourceControlNavigator/Views/Repositories/SourceControlNavigatorRepositoriesView.swift similarity index 100% rename from CodeEdit/Features/NavigatorSidebar/SourceControlNavigator/Views/Repositories/SourceControlNavigatorRepositoriesView.swift rename to CodeEdit/Features/NavigatorArea/SourceControlNavigator/Views/Repositories/SourceControlNavigatorRepositoriesView.swift diff --git a/CodeEdit/Features/NavigatorSidebar/NavigatorSidebarView.swift b/CodeEdit/Features/NavigatorArea/Views/NavigatorAreaView.swift similarity index 96% rename from CodeEdit/Features/NavigatorSidebar/NavigatorSidebarView.swift rename to CodeEdit/Features/NavigatorArea/Views/NavigatorAreaView.swift index 83327a4245..445890d9f7 100644 --- a/CodeEdit/Features/NavigatorSidebar/NavigatorSidebarView.swift +++ b/CodeEdit/Features/NavigatorArea/Views/NavigatorAreaView.swift @@ -1,5 +1,5 @@ // -// NavigatorSidebarView.swift +// NavigatorAreaView.swift // CodeEdit // // Created by Lukas Pistrol on 17.03.22. @@ -7,7 +7,7 @@ import SwiftUI -struct NavigatorSidebarView: View { +struct NavigatorAreaView: View { @ObservedObject private var workspace: WorkspaceDocument @ObservedObject private var extensionManager = ExtensionManager.shared @ObservedObject public var viewModel: NavigatorSidebarViewModel diff --git a/CodeEdit/Features/SplitView/Model/Environment+SplitEditor.swift b/CodeEdit/Features/SplitView/Model/Environment+SplitEditor.swift index a96c0fab56..1fd3eb14ac 100644 --- a/CodeEdit/Features/SplitView/Model/Environment+SplitEditor.swift +++ b/CodeEdit/Features/SplitView/Model/Environment+SplitEditor.swift @@ -8,7 +8,7 @@ import SwiftUI struct SplitEditorEnvironmentKey: EnvironmentKey { - static var defaultValue: (Edge, TabGroupData) -> Void = { _, _ in } + static var defaultValue: (Edge, Editor) -> Void = { _, _ in } } extension EnvironmentValues { diff --git a/CodeEdit/Features/SplitView/Model/SplitViewData.swift b/CodeEdit/Features/SplitView/Model/SplitViewData.swift index d87c425d27..5eb8275edb 100644 --- a/CodeEdit/Features/SplitView/Model/SplitViewData.swift +++ b/CodeEdit/Features/SplitView/Model/SplitViewData.swift @@ -8,17 +8,17 @@ import SwiftUI final class SplitViewData: ObservableObject { - @Published var tabgroups: [TabGroup] + @Published var editorLayouts: [EditorLayout] var axis: Axis - init(_ axis: Axis, tabgroups: [TabGroup] = []) { - self.tabgroups = tabgroups + init(_ axis: Axis, editorLayouts: [EditorLayout] = []) { + self.editorLayouts = editorLayouts self.axis = axis - tabgroups.forEach { - if case .one(let tabGroupData) = $0 { - tabGroupData.parent = self + editorLayouts.forEach { + if case .one(let editor) = $0 { + editor.parent = self } } } @@ -29,47 +29,60 @@ final class SplitViewData: ObservableObject { /// If the direction is the same as the ancestor direction, /// the editor is added to the ancestor instead of creating a new split container. /// - index: index where the divider will be added. - /// - tabgroup: new tabgroup class that will be used for the editor. - func split(_ direction: Edge, at index: Int, new tabgroup: TabGroupData) { - tabgroup.parent = self + /// - editor: new editor class that will be used for the editor. + func split(_ direction: Edge, at index: Int, new editor: Editor) { + editor.parent = self switch (axis, direction) { case (.horizontal, .trailing), (.vertical, .bottom): - tabgroups.insert(.one(tabgroup), at: index+1) + editorLayouts.insert(.one(editor), at: index+1) case (.horizontal, .leading), (.vertical, .top): - tabgroups.insert(.one(tabgroup), at: index) + editorLayouts.insert(.one(editor), at: index) case (.horizontal, .top): - tabgroups[index] = .vertical(.init(.vertical, tabgroups: [.one(tabgroup), tabgroups[index]])) + editorLayouts[index] = .vertical(.init(.vertical, editorLayouts: [.one(editor), editorLayouts[index]])) case (.horizontal, .bottom): - tabgroups[index] = .vertical(.init(.vertical, tabgroups: [tabgroups[index], .one(tabgroup)])) + editorLayouts[index] = .vertical(.init(.vertical, editorLayouts: [editorLayouts[index], .one(editor)])) case (.vertical, .leading): - tabgroups[index] = .horizontal(.init(.horizontal, tabgroups: [.one(tabgroup), tabgroups[index]])) + editorLayouts[index] = .horizontal(.init(.horizontal, editorLayouts: [.one(editor), editorLayouts[index]])) case (.vertical, .trailing): - tabgroups[index] = .horizontal(.init(.horizontal, tabgroups: [tabgroups[index], .one(tabgroup)])) + editorLayouts[index] = .horizontal(.init(.horizontal, editorLayouts: [editorLayouts[index], .one(editor)])) } } - /// Closes a TabGroup. - /// - Parameter id: ID of the TabGroup. - func closeTabGroup(with id: TabGroupData.ID) { - tabgroups.removeAll { tabgroup in - if case .one(let tabGroupData) = tabgroup { - if tabGroupData.id == id { + /// Closes an Editor. + /// - Parameter id: ID of the Editor. + func closeEditor(with id: Editor.ID) { + editorLayouts.removeAll { editorLayout in + if case .one(let editor) = editorLayout { + if editor.id == id { return true } } + return false } } + func getEditorLayout(with id: Editor.ID) -> EditorLayout? { + for editorLayout in editorLayouts { + if case .one(let editor) = editorLayout { + if editor.id == id { + return editorLayout + } + } + } + + return nil + } + /// Flattens the splitviews. func flatten() { - for index in tabgroups.indices { - tabgroups[index].flatten(parent: self) + for index in editorLayouts.indices { + editorLayouts[index].flatten(parent: self) } } } diff --git a/CodeEdit/Features/StatusBar/Views/StatusBarItems/StatusBarBreakpointButton.swift b/CodeEdit/Features/StatusBar/Views/StatusBarItems/StatusBarBreakpointButton.swift index fb269d0fc3..770fd8bdd5 100644 --- a/CodeEdit/Features/StatusBar/Views/StatusBarItems/StatusBarBreakpointButton.swift +++ b/CodeEdit/Features/StatusBar/Views/StatusBarItems/StatusBarBreakpointButton.swift @@ -9,7 +9,7 @@ import SwiftUI import CodeEditSymbols struct StatusBarBreakpointButton: View { - @EnvironmentObject private var model: DebugAreaViewModel + @EnvironmentObject private var model: UtilityAreaViewModel var body: some View { Button { diff --git a/CodeEdit/Features/StatusBar/Views/StatusBarItems/StatusBarCursorLocationLabel.swift b/CodeEdit/Features/StatusBar/Views/StatusBarItems/StatusBarCursorLocationLabel.swift index 76325bcc94..e5f6968ecd 100644 --- a/CodeEdit/Features/StatusBar/Views/StatusBarItems/StatusBarCursorLocationLabel.swift +++ b/CodeEdit/Features/StatusBar/Views/StatusBarItems/StatusBarCursorLocationLabel.swift @@ -11,7 +11,7 @@ struct StatusBarCursorLocationLabel: View { @Environment(\.controlActiveState) private var controlActive - @EnvironmentObject private var model: DebugAreaViewModel + @EnvironmentObject private var model: UtilityAreaViewModel var body: some View { Text("Line: \(model.cursorLocation.line) Col: \(model.cursorLocation.column)") diff --git a/CodeEdit/Features/StatusBar/Views/StatusBarItems/StatusBarToggleDrawerButton.swift b/CodeEdit/Features/StatusBar/Views/StatusBarItems/StatusBarToggleDrawerButton.swift index 0863e8695c..33b2a8cb7b 100644 --- a/CodeEdit/Features/StatusBar/Views/StatusBarItems/StatusBarToggleDrawerButton.swift +++ b/CodeEdit/Features/StatusBar/Views/StatusBarItems/StatusBarToggleDrawerButton.swift @@ -8,7 +8,7 @@ import SwiftUI internal struct StatusBarToggleDrawerButton: View { - @EnvironmentObject private var model: DebugAreaViewModel + @EnvironmentObject private var model: UtilityAreaViewModel init() { CommandManager.shared.addCommand( @@ -33,6 +33,7 @@ internal struct StatusBarToggleDrawerButton: View { } .buttonStyle(.icon) .keyboardShortcut("Y", modifiers: [.command, .shift]) + .help(model.isCollapsed ? "Show the Utility area" : "Hide the Utility area") .onHover { isHovering($0) } } } diff --git a/CodeEdit/Features/StatusBar/Views/StatusBarView.swift b/CodeEdit/Features/StatusBar/Views/StatusBarView.swift index 04cdfaf6f5..e8da472b69 100644 --- a/CodeEdit/Features/StatusBar/Views/StatusBarView.swift +++ b/CodeEdit/Features/StatusBar/Views/StatusBarView.swift @@ -20,7 +20,7 @@ struct StatusBarView: View { @Environment(\.controlActiveState) private var controlActive - @EnvironmentObject private var model: DebugAreaViewModel + @EnvironmentObject private var model: UtilityAreaViewModel static let height = 28.0 diff --git a/CodeEdit/Features/Tabs/Models/TabManager.swift b/CodeEdit/Features/Tabs/Models/TabManager.swift deleted file mode 100644 index 2562b61c58..0000000000 --- a/CodeEdit/Features/Tabs/Models/TabManager.swift +++ /dev/null @@ -1,138 +0,0 @@ -// -// TabManager.swift -// CodeEdit -// -// Created by Wouter Hennen on 03/03/2023. -// - -import Combine -import Foundation -import DequeModule -import OrderedCollections - -class TabManager: ObservableObject { - /// Collection of all the tabgroups. - @Published var tabGroups: TabGroup - - /// The TabGroup with active focus. - @Published var activeTabGroup: TabGroupData { - didSet { - activeTabGroupHistory.prepend { [weak oldValue] in oldValue } - switchToActiveTabGroup() - } - } - - /// History of last-used tab groups. - var activeTabGroupHistory: Deque<() -> TabGroupData?> = [] - - var fileDocuments: [CEWorkspaceFile: CodeFileDocument] = [:] - - /// notify listeners whenever tab selection changes on the active tab group. - var tabBarItemIdSubject = PassthroughSubject() - var cancellable: AnyCancellable? - - init() { - let tab = TabGroupData() - self.activeTabGroup = tab - self.activeTabGroupHistory.prepend { [weak tab] in tab } - self.tabGroups = .horizontal(.init(.horizontal, tabgroups: [.one(tab)])) - switchToActiveTabGroup() - } - - /// Flattens the splitviews. - func flatten() { - if case .horizontal(let data) = tabGroups { - data.flatten() - } - } - - /// Opens a new tab in a tabgroup. - /// - Parameters: - /// - item: The tab to open. - /// - tabgroup: The tabgroup to add the tab to. If nil, it is added to the active tab group. - func openTab(item: CEWorkspaceFile, in tabgroup: TabGroupData? = nil) { - let tabgroup = tabgroup ?? activeTabGroup - tabgroup.openTab(item: item) - } - - /// bind active tap group to listen to file selection changes. - func switchToActiveTabGroup() { - cancellable?.cancel() - cancellable = nil - cancellable = activeTabGroup.$selected - .sink { [weak self] tab in - self?.tabBarItemIdSubject.send(tab?.id) - } - } - - /// Restores the tab manager from a captured state obtained using `saveRestorationState` - /// - Parameter workspace: The workspace to retrieve state from. - func restoreFromState(_ workspace: WorkspaceDocument) { - guard let fileManager = workspace.workspaceFileManager, - let data = workspace.getFromWorkspaceState(.openTabs) as? Data, - let state = try? JSONDecoder().decode(TabRestorationState.self, from: data) else { - return - } - fixRestoredTabGroup(state.groups, fileManager: fileManager) - self.tabGroups = state.groups - self.activeTabGroup = findTabGroup( - group: state.groups, - searchFor: state.focus.id - ) ?? tabGroups.findSomeTabGroup()! - switchToActiveTabGroup() - } - - /// Fix any hanging files after restoring from saved state. - /// - /// After decoding the state, we're left with `CEWorkspaceFile`s that don't exist in the file manager - /// so this function maps all those to 'real' files. Works recursively on all the tab groups. - /// - Parameters: - /// - group: The tab group to fix. - /// - fileManager: The file manager to use to map files. - private func fixRestoredTabGroup(_ group: TabGroup, fileManager: CEWorkspaceFileManager) { - switch group { - case let .one(data): - fixTabGroupData(data, fileManager: fileManager) - case let .vertical(splitData): - splitData.tabgroups.forEach { group in - fixRestoredTabGroup(group, fileManager: fileManager) - } - case let .horizontal(splitData): - splitData.tabgroups.forEach { group in - fixRestoredTabGroup(group, fileManager: fileManager) - } - } - } - - private func findTabGroup(group: TabGroup, searchFor id: UUID) -> TabGroupData? { - switch group { - case let .one(data): - return data.id == id ? data : nil - case let .vertical(splitData): - return splitData.tabgroups.compactMap { findTabGroup(group: $0, searchFor: id) }.first - case let .horizontal(splitData): - return splitData.tabgroups.compactMap { findTabGroup(group: $0, searchFor: id) }.first - } - } - - /// Fixes any hanging files after restoring from saved state. - /// - Parameters: - /// - data: The tab group to fix. - /// - fileManager: The file manager to use to map files.a - private func fixTabGroupData(_ data: TabGroupData, fileManager: CEWorkspaceFileManager) { - data.tabs = OrderedSet(data.tabs.compactMap { fileManager.getFile($0.url.path) }) - if let selected = data.selected { - data.selected = fileManager.getFile(selected.url.path) - } - } - - func saveRestorationState(_ workspace: WorkspaceDocument) { - if let data = try? JSONEncoder().encode( - TabRestorationState(focus: activeTabGroup, groups: tabGroups) - ) { - workspace.addToWorkspaceState(key: .openTabs, value: data) - } else { - workspace.addToWorkspaceState(key: .openTabs, value: nil) - } - } -} diff --git a/CodeEdit/Features/Tabs/TabGroup/Environment+ActiveTabGroup.swift b/CodeEdit/Features/Tabs/TabGroup/Environment+ActiveTabGroup.swift deleted file mode 100644 index fa63f2e38f..0000000000 --- a/CodeEdit/Features/Tabs/TabGroup/Environment+ActiveTabGroup.swift +++ /dev/null @@ -1,19 +0,0 @@ -// -// Environment+ActiveTabGroup.swift -// CodeEdit -// -// Created by Wouter Hennen on 06/03/2023. -// - -import SwiftUI - -struct ActiveTabGroupEnvironmentKey: EnvironmentKey { - static var defaultValue = false -} - -extension EnvironmentValues { - var isActiveTabGroup: Bool { - get { self[ActiveTabGroupEnvironmentKey.self] } - set { self[ActiveTabGroupEnvironmentKey.self] = newValue } - } -} diff --git a/CodeEdit/Features/DebugArea/Views/DebugAreaDebugView.swift b/CodeEdit/Features/UtilityArea/DebugUtility/UtilityAreaDebugView.swift similarity index 90% rename from CodeEdit/Features/DebugArea/Views/DebugAreaDebugView.swift rename to CodeEdit/Features/UtilityArea/DebugUtility/UtilityAreaDebugView.swift index 4f341c563d..3ef1900bab 100644 --- a/CodeEdit/Features/DebugArea/Views/DebugAreaDebugView.swift +++ b/CodeEdit/Features/UtilityArea/DebugUtility/UtilityAreaDebugView.swift @@ -1,5 +1,5 @@ // -// DebugAreaDebugView.swift +// UtilityAreaDebugView.swift // CodeEdit // // Created by Austin Condiff on 5/25/23. @@ -7,11 +7,11 @@ import SwiftUI -struct DebugAreaDebugView: View { +struct UtilityAreaDebugView: View { @State var tabSelection = 0 var body: some View { - DebugAreaTabView { _ in + UtilityAreaTabView { _ in Text("Nothing to debug") .font(.system(size: 16)) .foregroundColor(.secondary) diff --git a/CodeEdit/Features/DebugArea/DebugAreaTab.swift b/CodeEdit/Features/UtilityArea/Models/UtilityAreaTab.swift similarity index 81% rename from CodeEdit/Features/DebugArea/DebugAreaTab.swift rename to CodeEdit/Features/UtilityArea/Models/UtilityAreaTab.swift index 7961be2c37..ff3248161e 100644 --- a/CodeEdit/Features/DebugArea/DebugAreaTab.swift +++ b/CodeEdit/Features/UtilityArea/Models/UtilityAreaTab.swift @@ -1,5 +1,5 @@ // -// DebugAreaTab.swift +// UtilityAreaTab.swift // CodeEdit // // Created by Wouter Hennen on 02/06/2023. @@ -7,7 +7,7 @@ import SwiftUI -enum DebugAreaTab: AreaTab, CaseIterable { +enum UtilityAreaTab: AreaTab, CaseIterable { var id: Self { self } case terminal @@ -39,11 +39,11 @@ enum DebugAreaTab: AreaTab, CaseIterable { var body: some View { switch self { case .terminal: - DebugAreaTerminalView() + UtilityAreaTerminalView() case .debugConsole: - DebugAreaDebugView() + UtilityAreaDebugView() case .output: - DebugAreaOutputView() + UtilityAreaOutputView() } } } diff --git a/CodeEdit/Features/DebugArea/Views/DebugAreaOutputView.swift b/CodeEdit/Features/UtilityArea/OutputUtility/UtilityAreaOutputView.swift similarity index 94% rename from CodeEdit/Features/DebugArea/Views/DebugAreaOutputView.swift rename to CodeEdit/Features/UtilityArea/OutputUtility/UtilityAreaOutputView.swift index 38119772dd..3d98bc1d34 100644 --- a/CodeEdit/Features/DebugArea/Views/DebugAreaOutputView.swift +++ b/CodeEdit/Features/UtilityArea/OutputUtility/UtilityAreaOutputView.swift @@ -1,5 +1,5 @@ // -// DebugAreaDebugView.swift +// UtilityAreaDebugView.swift // CodeEdit // // Created by Austin Condiff on 5/25/23. @@ -8,8 +8,8 @@ import SwiftUI import LogStream -struct DebugAreaOutputView: View { - @EnvironmentObject private var model: DebugAreaViewModel +struct UtilityAreaOutputView: View { + @EnvironmentObject private var model: UtilityAreaViewModel @ObservedObject var extensionManager = ExtensionManager.shared @@ -26,7 +26,7 @@ struct DebugAreaOutputView: View { } var body: some View { - DebugAreaTabView { _ in + UtilityAreaTabView { _ in Group { if selectedOutputSource == nil { Text("No output") diff --git a/CodeEdit/Features/DebugArea/Views/DebugAreaTerminalTab.swift b/CodeEdit/Features/UtilityArea/TerminalUtility/UtilityAreaTerminalTab.swift similarity index 91% rename from CodeEdit/Features/DebugArea/Views/DebugAreaTerminalTab.swift rename to CodeEdit/Features/UtilityArea/TerminalUtility/UtilityAreaTerminalTab.swift index 1d4de20a32..26c8e8dda4 100644 --- a/CodeEdit/Features/DebugArea/Views/DebugAreaTerminalTab.swift +++ b/CodeEdit/Features/UtilityArea/TerminalUtility/UtilityAreaTerminalTab.swift @@ -1,5 +1,5 @@ // -// DebugAreaTerminalTab.swift +// UtilityAreaTerminalTab.swift // CodeEdit // // Created by Austin Condiff on 5/26/23. @@ -7,8 +7,8 @@ import SwiftUI -struct DebugAreaTerminalTab: View { - @Binding var terminal: DebugAreaTerminal +struct UtilityAreaTerminalTab: View { + @Binding var terminal: UtilityAreaTerminal var removeTerminals: (_ ids: Set) -> Void diff --git a/CodeEdit/Features/DebugArea/Views/DebugAreaTerminalView.swift b/CodeEdit/Features/UtilityArea/TerminalUtility/UtilityAreaTerminalView.swift similarity index 93% rename from CodeEdit/Features/DebugArea/Views/DebugAreaTerminalView.swift rename to CodeEdit/Features/UtilityArea/TerminalUtility/UtilityAreaTerminalView.swift index 90bb7020f6..971ae5edb2 100644 --- a/CodeEdit/Features/DebugArea/Views/DebugAreaTerminalView.swift +++ b/CodeEdit/Features/UtilityArea/TerminalUtility/UtilityAreaTerminalView.swift @@ -7,7 +7,7 @@ import SwiftUI -struct DebugAreaTerminal: Identifiable, Equatable { +struct UtilityAreaTerminal: Identifiable, Equatable { var id: UUID var url: URL? var title: String @@ -25,7 +25,7 @@ struct DebugAreaTerminal: Identifiable, Equatable { } } -struct DebugAreaTerminalView: View { +struct UtilityAreaTerminalView: View { @AppSettings(\.theme.matchAppearance) private var matchAppearance @AppSettings(\.terminal.darkAppearance) @@ -38,7 +38,7 @@ struct DebugAreaTerminalView: View { @EnvironmentObject private var workspace: WorkspaceDocument - @EnvironmentObject private var model: DebugAreaViewModel + @EnvironmentObject private var model: UtilityAreaViewModel @State private var sidebarIsCollapsed = false @@ -52,7 +52,7 @@ struct DebugAreaTerminalView: View { let id = UUID() model.terminals = [ - DebugAreaTerminal( + UtilityAreaTerminal( id: id, url: workspace.workspaceFileManager?.folderUrl ?? URL(filePath: "/"), title: "terminal", @@ -67,7 +67,7 @@ struct DebugAreaTerminalView: View { let id = UUID() model.terminals.append( - DebugAreaTerminal( + UtilityAreaTerminal( id: id, url: URL(filePath: "\(id)"), title: "terminal", @@ -78,7 +78,7 @@ struct DebugAreaTerminalView: View { model.selectedTerminals = [id] } - private func getTerminal(_ id: UUID) -> DebugAreaTerminal? { + private func getTerminal(_ id: UUID) -> UtilityAreaTerminal? { return model.terminals.first(where: { $0.id == id }) ?? nil } @@ -90,7 +90,7 @@ struct DebugAreaTerminalView: View { } func updateTerminalByReference( - of terminal: inout DebugAreaTerminal, + of terminal: inout UtilityAreaTerminal, title: String? = nil ) { if let newTitle = title { @@ -121,7 +121,7 @@ struct DebugAreaTerminalView: View { } var body: some View { - DebugAreaTabView { tabState in + UtilityAreaTabView { tabState in ZStack { if model.selectedTerminals.isEmpty { Text("No Selection") @@ -149,7 +149,7 @@ struct DebugAreaTerminalView: View { } .paneToolbar { PaneToolbarSection { - DebugAreaTerminalPicker(selectedIDs: $model.selectedTerminals, terminals: model.terminals) + UtilityAreaTerminalPicker(selectedIDs: $model.selectedTerminals, terminals: model.terminals) .opacity(tabState.leadingSidebarIsCollapsed ? 1 : 0) } Spacer() @@ -189,7 +189,7 @@ struct DebugAreaTerminalView: View { } leadingSidebar: { _ in List(selection: $model.selectedTerminals) { ForEach($model.terminals, id: \.self.id) { $terminal in - DebugAreaTerminalTab( + UtilityAreaTerminalTab( terminal: $terminal, removeTerminals: model.removeTerminals, isSelected: model.selectedTerminals.contains(terminal.id), @@ -246,9 +246,9 @@ struct DebugAreaTerminalView: View { } } -struct DebugAreaTerminalPicker: View { +struct UtilityAreaTerminalPicker: View { @Binding var selectedIDs: Set - var terminals: [DebugAreaTerminal] + var terminals: [UtilityAreaTerminal] var selectedID: Binding { Binding( diff --git a/CodeEdit/Features/DebugArea/Views/Toolbar/FilterTextField.swift b/CodeEdit/Features/UtilityArea/Toolbar/FilterTextField.swift similarity index 100% rename from CodeEdit/Features/DebugArea/Views/Toolbar/FilterTextField.swift rename to CodeEdit/Features/UtilityArea/Toolbar/FilterTextField.swift diff --git a/CodeEdit/Features/DebugArea/Views/Toolbar/StatusBarClearButton.swift b/CodeEdit/Features/UtilityArea/Toolbar/StatusBarClearButton.swift similarity index 86% rename from CodeEdit/Features/DebugArea/Views/Toolbar/StatusBarClearButton.swift rename to CodeEdit/Features/UtilityArea/Toolbar/StatusBarClearButton.swift index f8577e18f6..74e174d24f 100644 --- a/CodeEdit/Features/DebugArea/Views/Toolbar/StatusBarClearButton.swift +++ b/CodeEdit/Features/UtilityArea/Toolbar/StatusBarClearButton.swift @@ -8,7 +8,7 @@ import SwiftUI struct StatusBarClearButton: View { - @EnvironmentObject private var model: DebugAreaViewModel + @EnvironmentObject private var model: UtilityAreaViewModel var body: some View { Button { diff --git a/CodeEdit/Features/DebugArea/Views/Toolbar/StatusBarMaximizeButton.swift b/CodeEdit/Features/UtilityArea/Toolbar/StatusBarMaximizeButton.swift similarity index 87% rename from CodeEdit/Features/DebugArea/Views/Toolbar/StatusBarMaximizeButton.swift rename to CodeEdit/Features/UtilityArea/Toolbar/StatusBarMaximizeButton.swift index 907aaf0f82..ac87eeb894 100644 --- a/CodeEdit/Features/DebugArea/Views/Toolbar/StatusBarMaximizeButton.swift +++ b/CodeEdit/Features/UtilityArea/Toolbar/StatusBarMaximizeButton.swift @@ -8,7 +8,7 @@ import SwiftUI struct StatusBarMaximizeButton: View { - @EnvironmentObject private var model: DebugAreaViewModel + @EnvironmentObject private var model: UtilityAreaViewModel var body: some View { Button { diff --git a/CodeEdit/Features/DebugArea/Views/Toolbar/StatusBarSplitTerminalButton.swift b/CodeEdit/Features/UtilityArea/Toolbar/StatusBarSplitTerminalButton.swift similarity index 86% rename from CodeEdit/Features/DebugArea/Views/Toolbar/StatusBarSplitTerminalButton.swift rename to CodeEdit/Features/UtilityArea/Toolbar/StatusBarSplitTerminalButton.swift index 48c90758b7..71e1288410 100644 --- a/CodeEdit/Features/DebugArea/Views/Toolbar/StatusBarSplitTerminalButton.swift +++ b/CodeEdit/Features/UtilityArea/Toolbar/StatusBarSplitTerminalButton.swift @@ -8,7 +8,7 @@ import SwiftUI struct StatusBarSplitTerminalButton: View { - @EnvironmentObject private var model: DebugAreaViewModel + @EnvironmentObject private var model: UtilityAreaViewModel var body: some View { Button { diff --git a/CodeEdit/Features/DebugArea/ViewModels/DebugAreaTabViewModel.swift b/CodeEdit/Features/UtilityArea/ViewModels/UtilityAreaTabViewModel.swift similarity index 67% rename from CodeEdit/Features/DebugArea/ViewModels/DebugAreaTabViewModel.swift rename to CodeEdit/Features/UtilityArea/ViewModels/UtilityAreaTabViewModel.swift index 2a16b52ba9..104918628f 100644 --- a/CodeEdit/Features/DebugArea/ViewModels/DebugAreaTabViewModel.swift +++ b/CodeEdit/Features/UtilityArea/ViewModels/UtilityAreaTabViewModel.swift @@ -1,5 +1,5 @@ // -// DebugAreaTabViewModel.swift +// UtilityAreaTabViewModel.swift // CodeEdit // // Created by Austin Condiff on 5/31/23. @@ -7,7 +7,7 @@ import SwiftUI -class DebugAreaTabViewModel: ObservableObject { +class UtilityAreaTabViewModel: ObservableObject { @Published var leadingSidebarIsCollapsed: Bool = false @Published var trailingSidebarIsCollapsed: Bool = false @@ -16,5 +16,5 @@ class DebugAreaTabViewModel: ObservableObject { @Published var hasTrailingSidebar: Bool = false - public static let shared: DebugAreaTabViewModel = .init() + public static let shared: UtilityAreaTabViewModel = .init() } diff --git a/CodeEdit/Features/DebugArea/ViewModels/DebugAreaViewModel.swift b/CodeEdit/Features/UtilityArea/ViewModels/UtilityAreaViewModel.swift similarity index 63% rename from CodeEdit/Features/DebugArea/ViewModels/DebugAreaViewModel.swift rename to CodeEdit/Features/UtilityArea/ViewModels/UtilityAreaViewModel.swift index f8b39f955e..919f4d7168 100644 --- a/CodeEdit/Features/DebugArea/ViewModels/DebugAreaViewModel.swift +++ b/CodeEdit/Features/UtilityArea/ViewModels/UtilityAreaViewModel.swift @@ -1,5 +1,5 @@ // -// DebugAreaViewModel.swift +// UtilityAreaViewModel.swift // CodeEdit // // Created by Lukas Pistrol on 20.03.22. @@ -7,17 +7,17 @@ import SwiftUI -/// # DebugAreaViewModel +/// # UtilityAreaViewModel /// /// A model class to host and manage data for the ``StatusBarView`` /// -class DebugAreaViewModel: ObservableObject { +class UtilityAreaViewModel: ObservableObject { /// Returns the current location of the cursor in an editing view @Published var cursorLocation: CursorLocation = .init(line: 1, column: 1) // Implementation needed!! - @Published var terminals: [DebugAreaTerminal] = [] + @Published var terminals: [UtilityAreaTerminal] = [] - @Published var selectedTerminals: Set = [] + @Published var selectedTerminals: Set = [] /// Indicates whether debugger is collapse or not @Published var isCollapsed: Bool = false @@ -38,7 +38,7 @@ class DebugAreaViewModel: ObservableObject { @Published var searchText: String = "" /// The tab bar items for the DebugAreaView - @Published var tabItems: [DebugAreaTab] = DebugAreaTab.allCases + @Published var tabItems: [UtilityAreaTab] = UtilityAreaTab.allCases /// Returns the font for status bar items to use private(set) var toolbarFont: Font = .system(size: 11, weight: .medium) @@ -52,14 +52,14 @@ class DebugAreaViewModel: ObservableObject { } func restoreFromState(_ workspace: WorkspaceDocument) { - isCollapsed = workspace.getFromWorkspaceState(.debugAreaCollapsed) as? Bool ?? false - currentHeight = workspace.getFromWorkspaceState(.debugAreaHeight) as? Double ?? 300.0 - isMaximized = workspace.getFromWorkspaceState(.debugAreaMaximized) as? Bool ?? false + isCollapsed = workspace.getFromWorkspaceState(.utilityAreaCollapsed) as? Bool ?? false + currentHeight = workspace.getFromWorkspaceState(.utilityAreaHeight) as? Double ?? 300.0 + isMaximized = workspace.getFromWorkspaceState(.utilityAreaMaximized) as? Bool ?? false } func saveRestorationState(_ workspace: WorkspaceDocument) { - workspace.addToWorkspaceState(key: .debugAreaCollapsed, value: isCollapsed) - workspace.addToWorkspaceState(key: .debugAreaHeight, value: currentHeight) - workspace.addToWorkspaceState(key: .debugAreaMaximized, value: isMaximized) + workspace.addToWorkspaceState(key: .utilityAreaCollapsed, value: isCollapsed) + workspace.addToWorkspaceState(key: .utilityAreaHeight, value: currentHeight) + workspace.addToWorkspaceState(key: .utilityAreaMaximized, value: isMaximized) } } diff --git a/CodeEdit/Features/DebugArea/Views/OSLogType+Color.swift b/CodeEdit/Features/UtilityArea/Views/OSLogType+Color.swift similarity index 100% rename from CodeEdit/Features/DebugArea/Views/OSLogType+Color.swift rename to CodeEdit/Features/UtilityArea/Views/OSLogType+Color.swift diff --git a/CodeEdit/Features/DebugArea/PaneToolbar.swift b/CodeEdit/Features/UtilityArea/Views/PaneToolbar.swift similarity index 96% rename from CodeEdit/Features/DebugArea/PaneToolbar.swift rename to CodeEdit/Features/UtilityArea/Views/PaneToolbar.swift index 31d82a3692..3ea22fd54a 100644 --- a/CodeEdit/Features/DebugArea/PaneToolbar.swift +++ b/CodeEdit/Features/UtilityArea/Views/PaneToolbar.swift @@ -9,7 +9,7 @@ import SwiftUI struct PaneToolbar: View { @ViewBuilder var content: Content - @EnvironmentObject var model: DebugAreaTabViewModel + @EnvironmentObject var model: UtilityAreaTabViewModel @Environment(\.paneArea) var paneArea: PaneArea? diff --git a/CodeEdit/Features/DebugArea/Views/DebugAreaTabView.swift b/CodeEdit/Features/UtilityArea/Views/UtilityAreaTabView.swift similarity index 80% rename from CodeEdit/Features/DebugArea/Views/DebugAreaTabView.swift rename to CodeEdit/Features/UtilityArea/Views/UtilityAreaTabView.swift index afff55661a..6a46849318 100644 --- a/CodeEdit/Features/DebugArea/Views/DebugAreaTabView.swift +++ b/CodeEdit/Features/UtilityArea/Views/UtilityAreaTabView.swift @@ -1,5 +1,5 @@ // -// DebugAreaTabView.swift +// UtilityAreaTabView.swift // CodeEdit // // Created by Austin Condiff on 5/30/23. @@ -7,20 +7,20 @@ import SwiftUI -struct DebugAreaTabView: View { - @ObservedObject var model: DebugAreaTabViewModel = DebugAreaTabViewModel.shared +struct UtilityAreaTabView: View { + @ObservedObject var model: UtilityAreaTabViewModel = UtilityAreaTabViewModel.shared - let content: (DebugAreaTabViewModel) -> Content - let leadingSidebar: (DebugAreaTabViewModel) -> LeadingSidebar? - let trailingSidebar: (DebugAreaTabViewModel) -> TrailingSidebar? + let content: (UtilityAreaTabViewModel) -> Content + let leadingSidebar: (UtilityAreaTabViewModel) -> LeadingSidebar? + let trailingSidebar: (UtilityAreaTabViewModel) -> TrailingSidebar? let hasLeadingSidebar: Bool let hasTrailingSidebar: Bool init( - @ViewBuilder content: @escaping (DebugAreaTabViewModel) -> Content, - @ViewBuilder leadingSidebar: @escaping (DebugAreaTabViewModel) -> LeadingSidebar, - @ViewBuilder trailingSidebar: @escaping (DebugAreaTabViewModel) -> TrailingSidebar, + @ViewBuilder content: @escaping (UtilityAreaTabViewModel) -> Content, + @ViewBuilder leadingSidebar: @escaping (UtilityAreaTabViewModel) -> LeadingSidebar, + @ViewBuilder trailingSidebar: @escaping (UtilityAreaTabViewModel) -> TrailingSidebar, hasLeadingSidebar: Bool = true, hasTrailingSidebar: Bool = true ) { @@ -32,7 +32,7 @@ struct DebugAreaTabView Content) where + init(@ViewBuilder content: @escaping (UtilityAreaTabViewModel) -> Content) where LeadingSidebar == EmptyView, TrailingSidebar == EmptyView { self.init( @@ -45,8 +45,8 @@ struct DebugAreaTabView Content, - @ViewBuilder leadingSidebar: @escaping (DebugAreaTabViewModel) -> LeadingSidebar + @ViewBuilder content: @escaping (UtilityAreaTabViewModel) -> Content, + @ViewBuilder leadingSidebar: @escaping (UtilityAreaTabViewModel) -> LeadingSidebar ) where TrailingSidebar == EmptyView { self.init( content: content, @@ -57,8 +57,8 @@ struct DebugAreaTabView Content, - @ViewBuilder trailingSidebar: @escaping (DebugAreaTabViewModel) -> TrailingSidebar + @ViewBuilder content: @escaping (UtilityAreaTabViewModel) -> Content, + @ViewBuilder trailingSidebar: @escaping (UtilityAreaTabViewModel) -> TrailingSidebar ) where LeadingSidebar == EmptyView { self.init( content: content, diff --git a/CodeEdit/Features/DebugArea/DebugAreaView.swift b/CodeEdit/Features/UtilityArea/Views/UtilityAreaView.swift similarity index 88% rename from CodeEdit/Features/DebugArea/DebugAreaView.swift rename to CodeEdit/Features/UtilityArea/Views/UtilityAreaView.swift index 65db917bfa..2886f7afa9 100644 --- a/CodeEdit/Features/DebugArea/DebugAreaView.swift +++ b/CodeEdit/Features/UtilityArea/Views/UtilityAreaView.swift @@ -1,5 +1,5 @@ // -// DebugAreaView.swift +// UtilityAreaView.swift // CodeEditModules/StatusBar // // Created by Lukas Pistrol on 22.03.22. @@ -7,13 +7,13 @@ import SwiftUI -struct DebugAreaView: View { +struct UtilityAreaView: View { @Environment(\.colorScheme) private var colorScheme - @EnvironmentObject private var model: DebugAreaViewModel + @EnvironmentObject private var model: UtilityAreaViewModel - @State var selection: DebugAreaTab? = .terminal + @State var selection: UtilityAreaTab? = .terminal var body: some View { VStack(spacing: 0) { diff --git a/CodeEdit/Features/DebugArea/View+paneToolbar.swift b/CodeEdit/Features/UtilityArea/Views/View+paneToolbar.swift similarity index 100% rename from CodeEdit/Features/DebugArea/View+paneToolbar.swift rename to CodeEdit/Features/UtilityArea/Views/View+paneToolbar.swift diff --git a/CodeEdit/Features/WindowCommands/FileCommands.swift b/CodeEdit/Features/WindowCommands/FileCommands.swift index df88668d81..6cb452aec0 100644 --- a/CodeEdit/Features/WindowCommands/FileCommands.swift +++ b/CodeEdit/Features/WindowCommands/FileCommands.swift @@ -9,7 +9,7 @@ import SwiftUI struct FileCommands: Commands { - @FocusedObject var debugAreaViewModel: DebugAreaViewModel? + @FocusedObject var utilityAreaViewModel: UtilityAreaViewModel? var body: some Commands { CommandGroup(replacing: .newItem) { @@ -42,7 +42,7 @@ struct FileCommands: Commands { .keyboardShortcut("w") Button("Close Editor") { - NSApp.sendAction(#selector(CodeEditWindowController.closeActiveTabGroup(_:)), to: nil, from: nil) + NSApp.sendAction(#selector(CodeEditWindowController.closeActiveEditor(_:)), to: nil, from: nil) } .keyboardShortcut("w", modifiers: [.control, .shift, .command]) @@ -57,9 +57,9 @@ struct FileCommands: Commands { } .keyboardShortcut("w", modifiers: [.control, .option, .command]) - if let debugAreaViewModel { + if let utilityAreaViewModel { Button("Close Terminal") { - debugAreaViewModel.removeTerminals(debugAreaViewModel.selectedTerminals) + utilityAreaViewModel.removeTerminals(utilityAreaViewModel.selectedTerminals) } .keyboardShortcut(.delete) } diff --git a/CodeEdit/Features/WindowCommands/NavigateCommands.swift b/CodeEdit/Features/WindowCommands/NavigateCommands.swift index b095e34022..4757ece15c 100644 --- a/CodeEdit/Features/WindowCommands/NavigateCommands.swift +++ b/CodeEdit/Features/WindowCommands/NavigateCommands.swift @@ -9,7 +9,7 @@ import SwiftUI struct NavigateCommands: Commands { - @FocusedObject var tabGroup: TabGroupData? + @FocusedObject var editor: Editor? var body: some Commands { CommandMenu("Navigate") { @@ -54,16 +54,16 @@ struct NavigateCommands: Commands { Divider() Button("Go Forward") { - tabGroup?.goForwardInHistory() + editor?.goForwardInHistory() } - .disabled(!(tabGroup?.canGoForwardInHistory ?? false)) + .disabled(!(editor?.canGoForwardInHistory ?? false)) Button("Go Back") { - tabGroup?.goBackInHistory() + editor?.goBackInHistory() } - .disabled(!(tabGroup?.canGoBackInHistory ?? false)) + .disabled(!(editor?.canGoBackInHistory ?? false)) } - .disabled(tabGroup == nil) + .disabled(editor == nil) } } } diff --git a/CodeEdit/Features/WindowCommands/ViewCommands.swift b/CodeEdit/Features/WindowCommands/ViewCommands.swift index 240543090c..653eeab323 100644 --- a/CodeEdit/Features/WindowCommands/ViewCommands.swift +++ b/CodeEdit/Features/WindowCommands/ViewCommands.swift @@ -18,7 +18,7 @@ struct ViewCommands: Commands { @State var windowController: CodeEditWindowController? private let documentController: CodeEditDocumentController = CodeEditDocumentController() - private let statusBarViewModel: DebugAreaViewModel = DebugAreaViewModel() + private let statusBarViewModel: UtilityAreaViewModel = UtilityAreaViewModel() @FocusedBinding(\.navigationSplitViewVisibility) var navigationSplitViewVisibility diff --git a/CodeEdit/Utils/Extensions/Array/Array+CEWorkspaceFile.swift b/CodeEdit/Utils/Extensions/Array/Array+CEWorkspaceFile.swift index af85343d3d..777c78eeb0 100644 --- a/CodeEdit/Utils/Extensions/Array/Array+CEWorkspaceFile.swift +++ b/CodeEdit/Utils/Extensions/Array/Array+CEWorkspaceFile.swift @@ -30,7 +30,7 @@ extension Array where Element == CEWorkspaceFile { /// Search for the `CEWorkspaceFile` element that matches the specified `tabID`. /// - Parameter tabID: A `tabID` to search for. /// - Returns: The `CEWorkspaceFile` element with a matching `tabID` if available. - func find(by tabID: TabBarItemID) -> CEWorkspaceFile? { + func find(by tabID: EditorTabID) -> CEWorkspaceFile? { guard let item = first(where: { $0.tabID == tabID }) else { for element in self { if let item = element.children?.find(by: tabID) { diff --git a/CodeEdit/WindowSplitView.swift b/CodeEdit/WindowSplitView.swift index 1fcc654afc..9956071835 100644 --- a/CodeEdit/WindowSplitView.swift +++ b/CodeEdit/WindowSplitView.swift @@ -16,7 +16,7 @@ struct WindowSplitView: View { var body: some View { WindowObserver(window: window) { NavigationSplitView(columnVisibility: $visibility) { - NavigatorSidebarView(workspace: workspace, viewModel: NavigatorSidebarViewModel()) + NavigatorAreaView(workspace: workspace, viewModel: NavigatorSidebarViewModel()) .toolbar { ToolbarItem { Button { @@ -47,7 +47,7 @@ struct WindowSplitView: View { } #if swift(>=5.9) // Fix build on Xcode 14 .inspector(isPresented: $showInspector) { - InspectorSidebarView() + InspectorAreaView() .inspectorColumnWidth(min: 100, ideal: 200, max: 400) .toolbar { Spacer() @@ -68,8 +68,8 @@ struct WindowSplitView: View { .focusedSceneValue(\.navigationSplitViewVisibility, $visibility) .focusedSceneValue(\.inspectorVisibility, $showInspector) .environmentObject(workspace) - .environmentObject(workspace.tabManager) - .environmentObject(workspace.debugAreaModel) + .environmentObject(workspace.editorManager) + .environmentObject(workspace.utilityAreaModel) .task { if let newWindow = workspace.windowControllers.first?.window { window = newWindow diff --git a/CodeEdit/WorkspaceView.swift b/CodeEdit/WorkspaceView.swift index d0a93cb7ad..94f4db792b 100644 --- a/CodeEdit/WorkspaceView.swift +++ b/CodeEdit/WorkspaceView.swift @@ -6,54 +6,53 @@ // import SwiftUI -import AppKit struct WorkspaceView: View { - - let tabBarHeight = 28.0 - private var path: String = "" - - @EnvironmentObject private var workspace: WorkspaceDocument - @EnvironmentObject private var tabManager: TabManager - @EnvironmentObject private var debugAreaModel: DebugAreaViewModel @Environment(\.window) private var window: NSWindow - private var keybindings: KeybindingManager = .shared - - @State private var showingAlert = false - @Environment(\.colorScheme) private var colorScheme + @FocusState var focusedEditor: Editor? + @AppSettings(\.theme.matchAppearance) var matchAppearance + @EnvironmentObject private var workspace: WorkspaceDocument + @EnvironmentObject private var editorManager: EditorManager + @EnvironmentObject private var utilityAreaModel: UtilityAreaViewModel + @StateObject private var themeModel: ThemeModel = .shared + @State private var showingAlert = false @State private var terminalCollapsed = true - @State private var editorCollapsed = false - @FocusState var focusedEditor: TabGroupData? + private var keybindings: KeybindingManager = .shared var body: some View { if workspace.workspaceFileManager != nil { VStack { SplitViewReader { proxy in SplitView(axis: .vertical) { - EditorView(tabgroup: tabManager.tabGroups, focus: $focusedEditor) - .collapsable() - .collapsed($debugAreaModel.isMaximized) - .frame(minHeight: 170 + 29 + 29) - .frame(maxWidth: .infinity, maxHeight: .infinity) - .holdingPriority(.init(1)) - .safeAreaInset(edge: .bottom, spacing: 0) { - StatusBarView(proxy: proxy) - } - DebugAreaView() + EditorLayoutView( + layout: editorManager.isFocusingActiveEditor + ? editorManager.activeEditor.getEditorLayout() ?? editorManager.editorLayout + : editorManager.editorLayout, + focus: $focusedEditor + ) + .collapsable() + .collapsed($utilityAreaModel.isMaximized) + .frame(minHeight: 170 + 29 + 29) + .frame(maxWidth: .infinity, maxHeight: .infinity) + .holdingPriority(.init(1)) + .safeAreaInset(edge: .bottom, spacing: 0) { + StatusBarView(proxy: proxy) + } + UtilityAreaView() .collapsable() - .collapsed($debugAreaModel.isCollapsed) + .collapsed($utilityAreaModel.isCollapsed) .frame(idealHeight: 260) .frame(minHeight: 100) } @@ -61,11 +60,11 @@ struct WorkspaceView: View { .frame(maxWidth: .infinity, maxHeight: .infinity) .onChange(of: focusedEditor) { newValue in /// update active tab group only if the new one is not the same with it. - if let newValue, tabManager.activeTabGroup != newValue { - tabManager.activeTabGroup = newValue + if let newValue, editorManager.activeEditor != newValue { + editorManager.activeEditor = newValue } } - .onChange(of: tabManager.activeTabGroup) { newValue in + .onChange(of: editorManager.activeEditor) { newValue in if newValue != focusedEditor { focusedEditor = newValue } diff --git a/Documentation.docc/App Window/Adding New Tab Type.md b/Documentation.docc/App Window/Adding New Tab Type.md index 056f0f2977..6541ddc178 100644 --- a/Documentation.docc/App Window/Adding New Tab Type.md +++ b/Documentation.docc/App Window/Adding New Tab Type.md @@ -5,12 +5,12 @@ This article is about how to add a new tab type to `TabBar` ## Overview First of all, each data type to be represented as tab in the UI should conform to -``TabBarItemRepresentable`` protocol. For example, this is how it is done for +``EditorTabRepresentable`` protocol. For example, this is how it is done for `FileItem`: ```swift -final class FileItem: Identifiable, Codable, TabBarItemRepresentable { - public var tabID: TabBarItemID { +final class FileItem: Identifiable, Codable, EditorTabRepresentable { + public var tabID: EditorTabID { .codeEditor(id) } @@ -34,7 +34,7 @@ final class FileItem: Identifiable, Codable, TabBarItemRepresentable { Each new tab type must have new identifier case, for example: ```swift -public enum TabBarItemID: Codable, Identifiable, Hashable { +public enum EditorTabID: Codable, Identifiable, Hashable { public var id: String { switch self { ... @@ -51,8 +51,8 @@ public enum TabBarItemID: Codable, Identifiable, Hashable { ### Opening and closing new tab types Tabs are opened using ``WorkspaceDocument/openTab(item:)`` method. It does a set of common -things for all tabs. But also it calls a private method based on the ``TabBarItemID`` of the -item. The private method for your ``TabBarItemRepresentable`` MUST persist this item +things for all tabs. But also it calls a private method based on the ``EditorTabID`` of the +item. The private method for your ``EditorTabRepresentable`` MUST persist this item somewhere (I recommend persisting them in ``WorkspaceSelectionState``). The same is for closing tabs using ``WorkspaceDocument/closeTab(item:)`` method. diff --git a/Documentation.docc/App Window/App Window.md b/Documentation.docc/App Window/App Window.md index 2a1bb1e4af..9996089981 100644 --- a/Documentation.docc/App Window/App Window.md +++ b/Documentation.docc/App Window/App Window.md @@ -28,7 +28,7 @@ A collection of all the views that make up the main app window. ### Inspector Sidebar -- ``InspectorSidebarView`` +- ``InspectorAreaView`` ### Status Bar diff --git a/Documentation.docc/App Window/InspectorSidebarView.md b/Documentation.docc/App Window/InspectorSidebarView.md index 4bd1d6716d..6665c26317 100644 --- a/Documentation.docc/App Window/InspectorSidebarView.md +++ b/Documentation.docc/App Window/InspectorSidebarView.md @@ -1,10 +1,10 @@ -# ``CodeEdit/InspectorSidebarView`` +# ``CodeEdit/InspectorAreaView`` ## Topics ### Toolbars -- ``InspectorSidebarToolbarTop`` +- ``InspectorAreaToolbarTop`` ### File Inspector diff --git a/Documentation.docc/App Window/StatusBarView.md b/Documentation.docc/App Window/StatusBarView.md index efcfecb90b..2582bd2e14 100644 --- a/Documentation.docc/App Window/StatusBarView.md +++ b/Documentation.docc/App Window/StatusBarView.md @@ -20,7 +20,7 @@ ### Drawer -- ``DebugAreaView`` +- ``UtilityAreaView`` - ``StatusBarSplitTerminalButton`` - ``StatusBarMaximizeButton`` - ``StatusBarClearButton`` diff --git a/Documentation.docc/App Window/TabBarView.md b/Documentation.docc/App Window/TabBarView.md index 4a041fb842..52825ceba4 100644 --- a/Documentation.docc/App Window/TabBarView.md +++ b/Documentation.docc/App Window/TabBarView.md @@ -8,14 +8,14 @@ ### Model -- ``TabBarItemID`` -- ``TabBarItemRepresentable`` +- ``EditorTabID`` +- ``EditorTabRepresentable`` ### Components -- ``TabBarItemView`` +- ``EditorTabView`` - ``TabBarContextMenu`` -- ``TabBarItemButtonStyle`` +- ``EditorTabButtonStyle`` - ``TabDivider`` - ``TabBarTopDivider`` - ``TabBarBottomDivider``