Skip to content

Commit dabc17b

Browse files
Add A Minimap (#2032)
### Description Adds a minimap to CodeEdit's editor, as well as a new trailing editor accessory (that only appears when the selected document is a code document), a command to toggle the minimap, and a setting to toggle the minimap. ### Related Issues * CodeEditApp/CodeEditSourceEditor#33 ### Checklist - [x] I read and understood the [contributing guide](https://github.com/CodeEditApp/CodeEdit/blob/main/CONTRIBUTING.md) as well as the [code of conduct](https://github.com/CodeEditApp/CodeEdit/blob/main/CODE_OF_CONDUCT.md) - [x] The issues this PR addresses are related to each other - [x] My changes generate no new warnings - [x] My code builds and runs on my machine - [x] My changes are all related to the related issue above - [x] I documented my code ### Screenshots https://github.com/user-attachments/assets/07f21d48-23cf-42dc-b39a-02ba395956cb
1 parent 9989d2e commit dabc17b

File tree

9 files changed

+86
-20
lines changed

9 files changed

+86
-20
lines changed

CodeEdit.xcodeproj/project.pbxproj

+3-3
Original file line numberDiff line numberDiff line change
@@ -419,7 +419,7 @@
419419
303E88462C276FD600EEA8D9 /* XCRemoteSwiftPackageReference "LanguageServerProtocol" */,
420420
6C4E37FA2C73E00700AEE7B5 /* XCRemoteSwiftPackageReference "SwiftTerm" */,
421421
6CB94D012CA1205100E8651C /* XCRemoteSwiftPackageReference "swift-async-algorithms" */,
422-
6CFE18222DA59C9F00A7B796 /* XCRemoteSwiftPackageReference "CodeEditSourceEditor" */,
422+
6CF368562DBBD274006A77FD /* XCRemoteSwiftPackageReference "CodeEditSourceEditor" */,
423423
);
424424
preferredProjectObjectVersion = 55;
425425
productRefGroup = B658FB2D27DA9E0F00EA4DBD /* Products */;
@@ -1745,12 +1745,12 @@
17451745
version = 1.0.1;
17461746
};
17471747
};
1748-
6CFE18222DA59C9F00A7B796 /* XCRemoteSwiftPackageReference "CodeEditSourceEditor" */ = {
1748+
6CF368562DBBD274006A77FD /* XCRemoteSwiftPackageReference "CodeEditSourceEditor" */ = {
17491749
isa = XCRemoteSwiftPackageReference;
17501750
repositoryURL = "https://github.com/CodeEditApp/CodeEditSourceEditor";
17511751
requirement = {
17521752
kind = upToNextMajorVersion;
1753-
minimumVersion = 0.11.0;
1753+
minimumVersion = 0.12.0;
17541754
};
17551755
};
17561756
/* End XCRemoteSwiftPackageReference section */

CodeEdit.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved

+4-4
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,8 @@
3333
"kind" : "remoteSourceControl",
3434
"location" : "https://github.com/CodeEditApp/CodeEditSourceEditor",
3535
"state" : {
36-
"revision" : "f444927ab70015f4b76f119f6fc5d0e358fcd77a",
37-
"version" : "0.11.0"
36+
"revision" : "412b0a26cbeb3f3148a1933dd598c976defe92a6",
37+
"version" : "0.12.0"
3838
}
3939
},
4040
{
@@ -51,8 +51,8 @@
5151
"kind" : "remoteSourceControl",
5252
"location" : "https://github.com/CodeEditApp/CodeEditTextView.git",
5353
"state" : {
54-
"revision" : "47faec9fb571c9c695897e69f0a4f08512ae682e",
55-
"version" : "0.8.2"
54+
"revision" : "a5912e60f6bac25cd1cdf8bb532e1125b21cf7f7",
55+
"version" : "0.10.1"
5656
}
5757
},
5858
{

CodeEdit/Features/Editor/JumpBar/Views/EditorJumpBarView.swift

+5-1
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,19 @@ struct EditorJumpBarView: View {
2121
@Environment(\.controlActiveState)
2222
private var activeState
2323

24+
@Binding var codeFile: CodeFileDocument?
25+
2426
static let height = 28.0
2527

2628
init(
2729
file: CEWorkspaceFile?,
2830
shouldShowTabBar: Bool,
31+
codeFile: Binding<CodeFileDocument?>,
2932
tappedOpenFile: @escaping (CEWorkspaceFile) -> Void
3033
) {
3134
self.file = file ?? nil
3235
self.shouldShowTabBar = shouldShowTabBar
36+
self._codeFile = codeFile
3337
self.tappedOpenFile = tappedOpenFile
3438
}
3539

@@ -75,7 +79,7 @@ struct EditorJumpBarView: View {
7579
}
7680
.safeAreaInset(edge: .trailing, spacing: 0) {
7781
if !shouldShowTabBar {
78-
EditorTabBarTrailingAccessories()
82+
EditorTabBarTrailingAccessories(codeFile: $codeFile)
7983
}
8084
}
8185
.frame(height: Self.height, alignment: .center)

CodeEdit/Features/Editor/TabBar/Views/EditorTabBarTrailingAccessories.swift

+41-5
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,11 @@
88
import SwiftUI
99

1010
struct EditorTabBarTrailingAccessories: View {
11+
@AppSettings(\.textEditing.wrapLinesToEditorWidth)
12+
var wrapLinesToEditorWidth
13+
@AppSettings(\.textEditing.showMinimap)
14+
var showMinimap
15+
1116
@Environment(\.splitEditor)
1217
var splitEditor
1318

@@ -21,15 +26,49 @@ struct EditorTabBarTrailingAccessories: View {
2126

2227
@EnvironmentObject private var editor: Editor
2328

29+
@Binding var codeFile: CodeFileDocument?
30+
2431
var body: some View {
25-
HStack(spacing: 0) {
32+
HStack(spacing: 6) {
33+
// Once more options are implemented that are available for non-code documents, remove this if statement
34+
if let codeFile {
35+
editorOptionsMenu(codeFile: codeFile)
36+
Divider()
37+
.padding(.vertical, 10)
38+
}
2639
splitviewButton
2740
}
41+
.buttonStyle(.icon)
42+
.disabled(editorManager.isFocusingActiveEditor)
43+
.opacity(editorManager.isFocusingActiveEditor ? 0.5 : 1)
2844
.padding(.horizontal, 7)
2945
.opacity(activeState != .inactive ? 1.0 : 0.5)
3046
.frame(maxHeight: .infinity) // Fill out vertical spaces.
3147
}
3248

49+
func editorOptionsMenu(codeFile: CodeFileDocument) -> some View {
50+
// This is a button so it gets the same styling from the Group in `body`.
51+
Button(action: {}, label: { Image(systemName: "slider.horizontal.3") })
52+
.overlay {
53+
Menu {
54+
Toggle("Show Minimap", isOn: $showMinimap)
55+
.keyboardShortcut("M", modifiers: [.command, .shift, .control])
56+
Divider()
57+
Toggle(
58+
"Wrap Lines",
59+
isOn: Binding(
60+
get: { codeFile.wrapLines ?? wrapLinesToEditorWidth },
61+
set: {
62+
codeFile.wrapLines = $0
63+
}
64+
)
65+
)
66+
} label: {}
67+
.menuStyle(.borderlessButton)
68+
.menuIndicator(.hidden)
69+
}
70+
}
71+
3372
var splitviewButton: some View {
3473
Group {
3574
switch (editor.parent?.axis, modifierKeys.contains(.option)) {
@@ -53,9 +92,6 @@ struct EditorTabBarTrailingAccessories: View {
5392
EmptyView()
5493
}
5594
}
56-
.buttonStyle(.icon)
57-
.disabled(editorManager.isFocusingActiveEditor)
58-
.opacity(editorManager.isFocusingActiveEditor ? 0.5 : 1)
5995
}
6096

6197
func split(edge: Edge) {
@@ -73,6 +109,6 @@ struct EditorTabBarTrailingAccessories: View {
73109

74110
struct TabBarTrailingAccessories_Previews: PreviewProvider {
75111
static var previews: some View {
76-
EditorTabBarTrailingAccessories()
112+
EditorTabBarTrailingAccessories(codeFile: .constant(nil))
77113
}
78114
}

CodeEdit/Features/Editor/TabBar/Views/EditorTabBarView.swift

+2-1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import SwiftUI
99

1010
struct EditorTabBarView: View {
1111
let hasTopInsets: Bool
12+
@Binding var codeFile: CodeFileDocument?
1213
/// The height of tab bar.
1314
/// I am not making it a private variable because it may need to be used in outside views.
1415
static let height = 28.0
@@ -21,7 +22,7 @@ struct EditorTabBarView: View {
2122
.accessibilityElement(children: .contain)
2223
.accessibilityLabel("Tab Bar")
2324
.accessibilityIdentifier("TabBar")
24-
EditorTabBarTrailingAccessories()
25+
EditorTabBarTrailingAccessories(codeFile: $codeFile)
2526
.padding(.top, hasTopInsets ? -1 : 0)
2627
}
2728
.frame(height: EditorTabBarView.height - (hasTopInsets ? 1 : 0))

CodeEdit/Features/Editor/Views/CodeFileView.swift

+4-1
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ struct CodeFileView: View {
4444
var bracketEmphasis
4545
@AppSettings(\.textEditing.useSystemCursor)
4646
var useSystemCursor
47+
@AppSettings(\.textEditing.showMinimap)
48+
var showMinimap
4749

4850
@Environment(\.colorScheme)
4951
private var colorScheme
@@ -125,7 +127,8 @@ struct CodeFileView: View {
125127
bracketPairEmphasis: getBracketPairEmphasis(),
126128
useSystemCursor: useSystemCursor,
127129
undoManager: undoManager,
128-
coordinators: textViewCoordinators
130+
coordinators: textViewCoordinators,
131+
showMinimap: showMinimap
129132
)
130133
.id(codeFile.fileURL)
131134
.background {

CodeEdit/Features/Editor/Views/EditorAreaView.swift

+3-2
Original file line numberDiff line numberDiff line change
@@ -104,15 +104,16 @@ struct EditorAreaView: View {
104104
.background(.clear)
105105
}
106106
if shouldShowTabBar {
107-
EditorTabBarView(hasTopInsets: topSafeArea > 0)
107+
EditorTabBarView(hasTopInsets: topSafeArea > 0, codeFile: $codeFile)
108108
.id("TabBarView" + editor.id.uuidString)
109109
.environmentObject(editor)
110110
Divider()
111111
}
112112
if showEditorJumpBar {
113113
EditorJumpBarView(
114114
file: editor.selectedTab?.file,
115-
shouldShowTabBar: shouldShowTabBar
115+
shouldShowTabBar: shouldShowTabBar,
116+
codeFile: $codeFile
116117
) { [weak editor] newFile in
117118
if let file = editor?.selectedTab, let index = editor?.tabs.firstIndex(of: file) {
118119
editor?.openTab(file: newFile, at: index)

CodeEdit/Features/Settings/Pages/TextEditingSettings/Models/TextEditingSettings.swift

+17-3
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@ extension SettingsData {
2727
"Autocomplete braces",
2828
"Enable type-over completion",
2929
"Bracket Pair Emphasis",
30-
"Bracket Pair Highlight"
30+
"Bracket Pair Highlight",
31+
"Show Minimap",
3132
]
3233
if #available(macOS 14.0, *) {
3334
keys.append("System Cursor")
@@ -70,6 +71,9 @@ extension SettingsData {
7071
/// Use the system cursor for the source editor.
7172
var useSystemCursor: Bool = true
7273

74+
/// Toggle the minimap in the editor.
75+
var showMinimap: Bool = true
76+
7377
/// Default initializer
7478
init() {
7579
self.populateCommands()
@@ -118,6 +122,8 @@ extension SettingsData {
118122
self.useSystemCursor = false
119123
}
120124

125+
self.showMinimap = try container.decodeIfPresent(Bool.self, forKey: .showMinimap) ?? true
126+
121127
self.populateCommands()
122128
}
123129

@@ -130,7 +136,7 @@ extension SettingsData {
130136
title: "Toggle Type-Over Completion",
131137
id: "prefs.text_editing.type_over_completion",
132138
command: {
133-
Settings.shared.preferences.textEditing.enableTypeOverCompletion.toggle()
139+
Settings[\.textEditing].enableTypeOverCompletion.toggle()
134140
}
135141
)
136142

@@ -139,7 +145,7 @@ extension SettingsData {
139145
title: "Toggle Autocomplete Braces",
140146
id: "prefs.text_editing.autocomplete_braces",
141147
command: {
142-
Settings.shared.preferences.textEditing.autocompleteBraces.toggle()
148+
Settings[\.textEditing].autocompleteBraces.toggle()
143149
}
144150
)
145151

@@ -151,6 +157,14 @@ extension SettingsData {
151157
Settings[\.textEditing].wrapLinesToEditorWidth.toggle()
152158
}
153159
)
160+
161+
mgr.addCommand(
162+
name: "Toggle Minimap",
163+
title: "Toggle Minimap",
164+
id: "prefs.text_editing.toggle_minimap"
165+
) {
166+
Settings[\.textEditing].showMinimap.toggle()
167+
}
154168
}
155169

156170
struct IndentOption: Codable, Hashable {

CodeEdit/Features/Settings/Pages/TextEditingSettings/TextEditingSettingsView.swift

+7
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ struct TextEditingSettingsView: View {
2020
wrapLinesToEditorWidth
2121
useSystemCursor
2222
overscroll
23+
showMinimap
2324
}
2425
Section {
2526
fontSelector
@@ -199,4 +200,10 @@ private extension TextEditingSettingsView {
199200
}
200201
}
201202
}
203+
204+
@ViewBuilder private var showMinimap: some View {
205+
Toggle("Show Minimap", isOn: $textEditing.showMinimap)
206+
// swiftlint:disable:next line_length
207+
.help("The minimap gives you a high-level summary of your source code, with controls to quickly navigate your document.")
208+
}
202209
}

0 commit comments

Comments
 (0)