import SwiftUI @main struct WorkbenchReplacementApp: App { @StateObject private var model = DatabaseModel() var body: some Scene { WindowGroup("Workbench Replacement") { MainView() .environmentObject(model) .frame(minWidth: 1000, minHeight: 650) } .commands { CommandGroup(replacing: .newItem) {} } Settings { WorkbenchSettingsView() } } } // MARK: - Application Preferences @MainActor final class WorkbenchPreferences: ObservableObject { static let shared = WorkbenchPreferences() @AppStorage("preferences.editorFontSize") var editorFontSize = 13.0 @AppStorage("preferences.uppercaseKeywords") var uppercaseKeywords = true @AppStorage("preferences.showLineNumbers") var showLineNumbers = true @AppStorage("preferences.tabWidth") var tabWidth = 4 @AppStorage("preferences.resultRowHeight") var resultRowHeight = 24.0 @AppStorage("preferences.resultColumnWidth") var resultColumnWidth = 170.0 @AppStorage("preferences.alternatingRows") var alternatingRows = true @AppStorage("preferences.appearance") var appearance = "light" @AppStorage("preferences.autoExpandTables") var autoExpandTables = true } // MARK: - Workbench Settings struct WorkbenchSettingsView: View { @AppStorage("preferences.editorFontSize") private var editorFontSize = 13.0 @AppStorage("preferences.uppercaseKeywords") private var uppercaseKeywords = true @AppStorage("preferences.showLineNumbers") private var showLineNumbers = true @AppStorage("preferences.tabWidth") private var tabWidth = 4 @AppStorage("preferences.defaultRowLimit") private var defaultRowLimit = 500 @AppStorage("preferences.resultRowHeight") private var resultRowHeight = 24.0 @AppStorage("preferences.resultColumnWidth") private var resultColumnWidth = 170.0 @AppStorage("preferences.alternatingRows") private var alternatingRows = true @AppStorage("preferences.autoExpandTables") private var autoExpandTables = true var body: some View { TabView { editorSettings .tabItem { Label( "SQL Editor", systemImage: "chevron.left.forwardslash.chevron.right" ) } executionSettings .tabItem { Label( "Query Execution", systemImage: "bolt" ) } resultSettings .tabItem { Label( "Result Grid", systemImage: "tablecells" ) } generalSettings .tabItem { Label( "General", systemImage: "gearshape" ) } } .frame(width: 620, height: 390) .preferredColorScheme(.light) } private var editorSettings: some View { settingsPage("SQL Editor") { settingsRow("Font Size") { Stepper( "\(Int(editorFontSize)) pt", value: $editorFontSize, in: 10...24, step: 1 ) .frame(width: 130) } settingsRow("Tab Width") { Picker("", selection: $tabWidth) { Text("2 spaces").tag(2) Text("4 spaces").tag(4) Text("8 spaces").tag(8) } .labelsHidden() .frame(width: 150) } settingsRow("SQL Formatting") { Toggle( "Automatically uppercase SQL keywords", isOn: $uppercaseKeywords ) } settingsRow("Editor Display") { Toggle( "Show line numbers", isOn: $showLineNumbers ) } } } private var executionSettings: some View { settingsPage("Query Execution") { settingsRow("Default Row Limit") { HStack(spacing: 12) { TextField( "", value: $defaultRowLimit, format: .number ) .textFieldStyle(.roundedBorder) .frame(width: 110) Stepper( "", value: $defaultRowLimit, in: 50...100000, step: 50 ) .labelsHidden() } } Text( "Controls the number of rows retrieved when opening a table from the schema navigator." ) .font(.system(size: 12)) .foregroundStyle(.secondary) .frame(maxWidth: .infinity, alignment: .leading) .padding(.leading, 190) Divider() .padding(.vertical, 12) Text("Examples") .font(.headline) Text( "500 rows: Faster browsing and lower memory usage.\n" + "5,000 rows: Useful for larger datasets.\n" + "50,000 rows: May take longer to retrieve." ) .font(.system(size: 12)) .foregroundStyle(.secondary) .frame(maxWidth: .infinity, alignment: .leading) } } private var resultSettings: some View { settingsPage("Result Grid") { settingsRow("Row Height") { Stepper( "\(Int(resultRowHeight)) px", value: $resultRowHeight, in: 18...40, step: 1 ) .frame(width: 130) } settingsRow("Column Width") { Stepper( "\(Int(resultColumnWidth)) px", value: $resultColumnWidth, in: 80...400, step: 10 ) .frame(width: 140) } settingsRow("Appearance") { Toggle( "Alternating row colours", isOn: $alternatingRows ) } } } private var generalSettings: some View { settingsPage("General") { settingsRow("Navigator") { Toggle( "Automatically expand table folders", isOn: $autoExpandTables ) } } } private func settingsPage( _ title: String, @ViewBuilder content: () -> Content ) -> some View { VStack(alignment: .leading, spacing: 18) { Text(title) .font(.system(size: 20, weight: .semibold)) Divider() content() Spacer(minLength: 0) } .padding(26) .frame(maxWidth: .infinity, maxHeight: .infinity) .background(Color(nsColor: .windowBackgroundColor)) } private func settingsRow( _ title: String, @ViewBuilder content: () -> Content ) -> some View { HStack(alignment: .center, spacing: 16) { Text(title) .font(.system(size: 13)) .frame(width: 170, alignment: .trailing) content() Spacer(minLength: 0) } .frame(height: 30) } }