From c9c78adf7cba0eb5441d68a59219d9f013a809bc Mon Sep 17 00:00:00 2001 From: neon443 <69979447+neon443@users.noreply.github.com> Date: Mon, 7 Jul 2025 17:21:51 +0100 Subject: [PATCH] added a functional theme editor added a long ass subscript to get/set ansi as swiftui.color from a subscript added an init from rgb, and init from SwiftUI.Color to colorcodable added a computed suiColor property to colorcodable more guardrails to swifterm.Color.init(_ colorCodable) themecodable colorcodable conform to hashable and equatable --- ShhShell/Themes/ColorCodable.swift | 40 +++++++++++++++-- ShhShell/Themes/ThemeCodable.swift | 50 ++++++++++++++++++++- ShhShell/Views/Themes/ThemeEditorView.swift | 44 ++++++++++++------ 3 files changed, 116 insertions(+), 18 deletions(-) diff --git a/ShhShell/Themes/ColorCodable.swift b/ShhShell/Themes/ColorCodable.swift index e661f78..85b5069 100644 --- a/ShhShell/Themes/ColorCodable.swift +++ b/ShhShell/Themes/ColorCodable.swift @@ -9,7 +9,7 @@ import Foundation import SwiftTerm import SwiftUI -struct ColorCodable: Codable { +struct ColorCodable: Codable, Hashable, Equatable { var red: Double var green: Double var blue: Double @@ -19,12 +19,36 @@ struct ColorCodable: Codable { case green = "Green Component" case blue = "Blue Component" } + + init(red: Double, green: Double, blue: Double) { + self.red = red + self.green = green + self.blue = blue + } + + init(color: SwiftUI.Color) { + let uiColor = UIColor(color) + var r: CGFloat = 0 + var g: CGFloat = 0 + var b: CGFloat = 0 + uiColor.getRed(&r, green: &g, blue: &b, alpha: nil) + self.red = r + self.green = g + self.blue = b + } } extension ColorCodable { var stColor: SwiftTerm.Color { return SwiftTerm.Color(self) } + + var suiColor: SwiftUI.Color { + let red = CGFloat(self.red)/65535 + let green = CGFloat(self.green)/65535 + let blue = CGFloat(self.blue)/65535 + return Color(UIColor(red: red, green: green, blue: blue, alpha: 1)) + } } extension SwiftTerm.Color { @@ -37,9 +61,17 @@ extension SwiftTerm.Color { } convenience init(_ colorCodable: ColorCodable) { - let red = UInt16(colorCodable.red * 65535) - let green = UInt16(colorCodable.green * 65535) - let blue = UInt16(colorCodable.blue * 65535) + var cc = colorCodable + if cc.red < 0 { cc.red.negate() } + if cc.green < 0 { cc.green.negate() } + if cc.blue < 0 { cc.blue.negate() } + if cc.red > 1 { cc.red = 1 } + if cc.green > 1 { cc.green = 1 } + if cc.blue > 1 { cc.blue = 1 } + + let red = UInt16(cc.red * 65535) + let green = UInt16(cc.green * 65535) + let blue = UInt16(cc.blue * 65535) self.init(red: red, green: green, blue: blue) } diff --git a/ShhShell/Themes/ThemeCodable.swift b/ShhShell/Themes/ThemeCodable.swift index 01dead3..a1a248a 100644 --- a/ShhShell/Themes/ThemeCodable.swift +++ b/ShhShell/Themes/ThemeCodable.swift @@ -7,8 +7,9 @@ import Foundation import SwiftTerm +import SwiftUI -struct ThemeCodable: Codable { +struct ThemeCodable: Codable, Hashable, Equatable { var id: String? var name: String? var ansi0: ColorCodable @@ -87,3 +88,50 @@ extension ThemeCodable { ) } } + +extension ThemeCodable { + subscript(ansiIndex index: Int) -> SwiftUI.Color { + get { + switch index { + case 0: return ansi0.stColor.suiColor + case 1: return ansi1.stColor.suiColor + case 2: return ansi2.stColor.suiColor + case 3: return ansi3.stColor.suiColor + case 4: return ansi4.stColor.suiColor + case 5: return ansi5.stColor.suiColor + case 6: return ansi6.stColor.suiColor + case 7: return ansi7.stColor.suiColor + case 8: return ansi8.stColor.suiColor + case 9: return ansi9.stColor.suiColor + case 10: return ansi10.stColor.suiColor + case 11: return ansi11.stColor.suiColor + case 12: return ansi12.stColor.suiColor + case 13: return ansi13.stColor.suiColor + case 14: return ansi14.stColor.suiColor + case 15: return ansi15.stColor.suiColor + default: fatalError() + } + } + set { + switch index { + case 0: ansi0 = ColorCodable(color: newValue) + case 1: ansi1 = ColorCodable(color: newValue) + case 2: ansi2 = ColorCodable(color: newValue) + case 3: ansi3 = ColorCodable(color: newValue) + case 4: ansi4 = ColorCodable(color: newValue) + case 5: ansi5 = ColorCodable(color: newValue) + case 6: ansi6 = ColorCodable(color: newValue) + case 7: ansi7 = ColorCodable(color: newValue) + case 8: ansi8 = ColorCodable(color: newValue) + case 9: ansi9 = ColorCodable(color: newValue) + case 10: ansi10 = ColorCodable(color: newValue) + case 11: ansi11 = ColorCodable(color: newValue) + case 12: ansi12 = ColorCodable(color: newValue) + case 13: ansi13 = ColorCodable(color: newValue) + case 14: ansi14 = ColorCodable(color: newValue) + case 15: ansi15 = ColorCodable(color: newValue) + default: fatalError() + } + } + } +} diff --git a/ShhShell/Views/Themes/ThemeEditorView.swift b/ShhShell/Views/Themes/ThemeEditorView.swift index a5a0d61..a1f7f8b 100644 --- a/ShhShell/Views/Themes/ThemeEditorView.swift +++ b/ShhShell/Views/Themes/ThemeEditorView.swift @@ -9,27 +9,45 @@ import SwiftUI import SwiftTerm struct ThemeEditorView: View { - @State var theme: Theme +// @State var theme: Theme + @State var themeCodable: ThemeCodable + + init(theme: Theme) { +// self.theme = theme + self.themeCodable = theme.themeCodable + } var body: some View { NavigationStack { // List { +// TextField("Name", text: $themeCodable.name) + + ThemePreview(hostsManager: HostsManager(), theme: themeCodable.toTheme(), canModify: false) + .id(themeCodable) + + Group { + Rectangle() + .fill(themeCodable.foreground.stColor.suiColor) + Rectangle() + .fill(themeCodable.background.stColor.suiColor) + Rectangle() + .fill(themeCodable.bold.stColor.suiColor) + Rectangle() + .fill(themeCodable.cursor.stColor.suiColor) + Rectangle() + .fill(themeCodable.cursorText.stColor.suiColor) + Rectangle() + .fill(themeCodable.selection.stColor.suiColor) + Rectangle() + .fill(themeCodable.selectedText.stColor.suiColor) + } + .frame(width: 100) + ForEach(0...1, id: \.self) { row in HStack { ForEach(1...8, id: \.self) { col in let index = (col + (row * 8)) - 1 - ColorPicker( - selection: Binding( - get: { theme.ansi[index].suiColor }, - set: { newValue in - let cc = SwiftTerm.Color(newValue).colorCodable - theme.ansi[index] = cc.stColor - } - ) - ) { - RoundedRectangle(cornerRadius: 5) - .fill(theme.ansi[index].suiColor) - } + ColorPicker("Ansi \(index+1)", selection: $themeCodable[ansiIndex: index]) } } }