Skip to content

Commit 462c00f

Browse files
committed
refactor: rewrite Layout and Colors panes to use native macOS Form patterns
1 parent 1a1599a commit 462c00f

2 files changed

Lines changed: 408 additions & 0 deletions

File tree

Lines changed: 261 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,261 @@
1+
//
2+
// ThemeEditorColorsSection.swift
3+
// TablePro
4+
//
5+
6+
import AppKit
7+
import SwiftUI
8+
9+
// MARK: - HexColorPicker
10+
11+
struct HexColorPicker: View {
12+
let label: String
13+
@Binding var hex: String
14+
15+
var body: some View {
16+
let colorBinding = Binding<Color>(
17+
get: { hex.swiftUIColor },
18+
set: { newColor in
19+
if let converted = NSColor(newColor).usingColorSpace(.sRGB) {
20+
hex = converted.hexString
21+
}
22+
}
23+
)
24+
ColorPicker(label, selection: colorBinding, supportsOpacity: true)
25+
}
26+
}
27+
28+
// MARK: - ThemeEditorColorsSection
29+
30+
internal struct ThemeEditorColorsSection: View {
31+
private var engine: ThemeEngine { ThemeEngine.shared }
32+
private var theme: ThemeDefinition { engine.activeTheme }
33+
34+
var body: some View {
35+
Form {
36+
editorSection
37+
syntaxSection
38+
dataGridSection
39+
interfaceSection
40+
statusSection
41+
badgesSection
42+
sidebarSection
43+
toolbarSection
44+
}
45+
.formStyle(.grouped)
46+
.scrollContentBackground(.hidden)
47+
}
48+
49+
// MARK: - Editor
50+
51+
private var editorSection: some View {
52+
Section(String(localized: "Editor")) {
53+
LabeledContent(String(localized: "Background")) {
54+
HexColorPicker(label: "", hex: colorBinding(for: \.editor.background))
55+
}
56+
LabeledContent(String(localized: "Text")) {
57+
HexColorPicker(label: "", hex: colorBinding(for: \.editor.text))
58+
}
59+
LabeledContent(String(localized: "Cursor")) {
60+
HexColorPicker(label: "", hex: colorBinding(for: \.editor.cursor))
61+
}
62+
LabeledContent(String(localized: "Current Line")) {
63+
HexColorPicker(label: "", hex: colorBinding(for: \.editor.currentLineHighlight))
64+
}
65+
LabeledContent(String(localized: "Selection")) {
66+
HexColorPicker(label: "", hex: colorBinding(for: \.editor.selection))
67+
}
68+
LabeledContent(String(localized: "Line Number")) {
69+
HexColorPicker(label: "", hex: colorBinding(for: \.editor.lineNumber))
70+
}
71+
LabeledContent(String(localized: "Invisibles")) {
72+
HexColorPicker(label: "", hex: colorBinding(for: \.editor.invisibles))
73+
}
74+
}
75+
}
76+
77+
private var syntaxSection: some View {
78+
Section(String(localized: "Syntax Colors")) {
79+
LabeledContent(String(localized: "Keyword")) {
80+
HexColorPicker(label: "", hex: colorBinding(for: \.editor.syntax.keyword))
81+
}
82+
LabeledContent(String(localized: "String")) {
83+
HexColorPicker(label: "", hex: colorBinding(for: \.editor.syntax.string))
84+
}
85+
LabeledContent(String(localized: "Number")) {
86+
HexColorPicker(label: "", hex: colorBinding(for: \.editor.syntax.number))
87+
}
88+
LabeledContent(String(localized: "Comment")) {
89+
HexColorPicker(label: "", hex: colorBinding(for: \.editor.syntax.comment))
90+
}
91+
LabeledContent(String(localized: "NULL")) {
92+
HexColorPicker(label: "", hex: colorBinding(for: \.editor.syntax.null))
93+
}
94+
LabeledContent(String(localized: "Operator")) {
95+
HexColorPicker(label: "", hex: colorBinding(for: \.editor.syntax.operator))
96+
}
97+
LabeledContent(String(localized: "Function")) {
98+
HexColorPicker(label: "", hex: colorBinding(for: \.editor.syntax.function))
99+
}
100+
LabeledContent(String(localized: "Type")) {
101+
HexColorPicker(label: "", hex: colorBinding(for: \.editor.syntax.type))
102+
}
103+
}
104+
}
105+
106+
// MARK: - Data Grid
107+
108+
private var dataGridSection: some View {
109+
Section(String(localized: "Data Grid")) {
110+
LabeledContent(String(localized: "Background")) {
111+
HexColorPicker(label: "", hex: colorBinding(for: \.dataGrid.background))
112+
}
113+
LabeledContent(String(localized: "Text")) {
114+
HexColorPicker(label: "", hex: colorBinding(for: \.dataGrid.text))
115+
}
116+
LabeledContent(String(localized: "Alternate Row")) {
117+
HexColorPicker(label: "", hex: colorBinding(for: \.dataGrid.alternateRow))
118+
}
119+
LabeledContent(String(localized: "NULL Value")) {
120+
HexColorPicker(label: "", hex: colorBinding(for: \.dataGrid.nullValue))
121+
}
122+
LabeledContent(String(localized: "Bool True")) {
123+
HexColorPicker(label: "", hex: colorBinding(for: \.dataGrid.boolTrue))
124+
}
125+
LabeledContent(String(localized: "Bool False")) {
126+
HexColorPicker(label: "", hex: colorBinding(for: \.dataGrid.boolFalse))
127+
}
128+
LabeledContent(String(localized: "Row Number")) {
129+
HexColorPicker(label: "", hex: colorBinding(for: \.dataGrid.rowNumber))
130+
}
131+
LabeledContent(String(localized: "Modified")) {
132+
HexColorPicker(label: "", hex: colorBinding(for: \.dataGrid.modified))
133+
}
134+
LabeledContent(String(localized: "Inserted")) {
135+
HexColorPicker(label: "", hex: colorBinding(for: \.dataGrid.inserted))
136+
}
137+
LabeledContent(String(localized: "Deleted")) {
138+
HexColorPicker(label: "", hex: colorBinding(for: \.dataGrid.deleted))
139+
}
140+
LabeledContent(String(localized: "Deleted Text")) {
141+
HexColorPicker(label: "", hex: colorBinding(for: \.dataGrid.deletedText))
142+
}
143+
LabeledContent(String(localized: "Focus Border")) {
144+
HexColorPicker(label: "", hex: colorBinding(for: \.dataGrid.focusBorder))
145+
}
146+
}
147+
}
148+
149+
// MARK: - Interface
150+
151+
private var interfaceSection: some View {
152+
Section(String(localized: "Interface")) {
153+
LabeledContent(String(localized: "Window Background")) {
154+
HexColorPicker(label: "", hex: colorBinding(for: \.ui.windowBackground))
155+
}
156+
LabeledContent(String(localized: "Control Background")) {
157+
HexColorPicker(label: "", hex: colorBinding(for: \.ui.controlBackground))
158+
}
159+
LabeledContent(String(localized: "Card Background")) {
160+
HexColorPicker(label: "", hex: colorBinding(for: \.ui.cardBackground))
161+
}
162+
LabeledContent(String(localized: "Border")) {
163+
HexColorPicker(label: "", hex: colorBinding(for: \.ui.border))
164+
}
165+
LabeledContent(String(localized: "Primary Text")) {
166+
HexColorPicker(label: "", hex: colorBinding(for: \.ui.primaryText))
167+
}
168+
LabeledContent(String(localized: "Secondary Text")) {
169+
HexColorPicker(label: "", hex: colorBinding(for: \.ui.secondaryText))
170+
}
171+
LabeledContent(String(localized: "Tertiary Text")) {
172+
HexColorPicker(label: "", hex: colorBinding(for: \.ui.tertiaryText))
173+
}
174+
LabeledContent(String(localized: "Selection")) {
175+
HexColorPicker(label: "", hex: colorBinding(for: \.ui.selectionBackground))
176+
}
177+
LabeledContent(String(localized: "Hover")) {
178+
HexColorPicker(label: "", hex: colorBinding(for: \.ui.hoverBackground))
179+
}
180+
}
181+
}
182+
183+
private var statusSection: some View {
184+
Section(String(localized: "Status Colors")) {
185+
LabeledContent(String(localized: "Success")) {
186+
HexColorPicker(label: "", hex: colorBinding(for: \.ui.status.success))
187+
}
188+
LabeledContent(String(localized: "Warning")) {
189+
HexColorPicker(label: "", hex: colorBinding(for: \.ui.status.warning))
190+
}
191+
LabeledContent(String(localized: "Error")) {
192+
HexColorPicker(label: "", hex: colorBinding(for: \.ui.status.error))
193+
}
194+
LabeledContent(String(localized: "Info")) {
195+
HexColorPicker(label: "", hex: colorBinding(for: \.ui.status.info))
196+
}
197+
}
198+
}
199+
200+
private var badgesSection: some View {
201+
Section(String(localized: "Badges")) {
202+
LabeledContent(String(localized: "Badge Background")) {
203+
HexColorPicker(label: "", hex: colorBinding(for: \.ui.badges.background))
204+
}
205+
LabeledContent(String(localized: "Primary Key")) {
206+
HexColorPicker(label: "", hex: colorBinding(for: \.ui.badges.primaryKey))
207+
}
208+
LabeledContent(String(localized: "Auto Increment")) {
209+
HexColorPicker(label: "", hex: colorBinding(for: \.ui.badges.autoIncrement))
210+
}
211+
}
212+
}
213+
214+
// MARK: - Sidebar
215+
216+
private var sidebarSection: some View {
217+
Section(String(localized: "Sidebar")) {
218+
LabeledContent(String(localized: "Background")) {
219+
HexColorPicker(label: "", hex: colorBinding(for: \.sidebar.background))
220+
}
221+
LabeledContent(String(localized: "Text")) {
222+
HexColorPicker(label: "", hex: colorBinding(for: \.sidebar.text))
223+
}
224+
LabeledContent(String(localized: "Selected Item")) {
225+
HexColorPicker(label: "", hex: colorBinding(for: \.sidebar.selectedItem))
226+
}
227+
LabeledContent(String(localized: "Hover")) {
228+
HexColorPicker(label: "", hex: colorBinding(for: \.sidebar.hover))
229+
}
230+
LabeledContent(String(localized: "Section Header")) {
231+
HexColorPicker(label: "", hex: colorBinding(for: \.sidebar.sectionHeader))
232+
}
233+
}
234+
}
235+
236+
// MARK: - Toolbar
237+
238+
private var toolbarSection: some View {
239+
Section(String(localized: "Toolbar")) {
240+
LabeledContent(String(localized: "Secondary Text")) {
241+
HexColorPicker(label: "", hex: colorBinding(for: \.toolbar.secondaryText))
242+
}
243+
LabeledContent(String(localized: "Tertiary Text")) {
244+
HexColorPicker(label: "", hex: colorBinding(for: \.toolbar.tertiaryText))
245+
}
246+
}
247+
}
248+
249+
// MARK: - Helpers
250+
251+
private func colorBinding(for keyPath: WritableKeyPath<ThemeDefinition, String>) -> Binding<String> {
252+
Binding(
253+
get: { theme[keyPath: keyPath] },
254+
set: { newValue in
255+
var updated = theme
256+
updated[keyPath: keyPath] = newValue
257+
try? engine.saveUserTheme(updated)
258+
}
259+
)
260+
}
261+
}

0 commit comments

Comments
 (0)