VMConfigConstantPicker.swift 2.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. //
  2. // Copyright © 2022 osy. All rights reserved.
  3. //
  4. // Licensed under the Apache License, Version 2.0 (the "License");
  5. // you may not use this file except in compliance with the License.
  6. // You may obtain a copy of the License at
  7. //
  8. // http://www.apache.org/licenses/LICENSE-2.0
  9. //
  10. // Unless required by applicable law or agreed to in writing, software
  11. // distributed under the License is distributed on an "AS IS" BASIS,
  12. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. // See the License for the specific language governing permissions and
  14. // limitations under the License.
  15. //
  16. import SwiftUI
  17. struct VMConfigConstantPicker: View {
  18. private struct Identifier: Hashable {
  19. let string: String
  20. init(_ string: String) {
  21. self.string = string
  22. }
  23. func hash(into hasher: inout Hasher) {
  24. string.hash(into: &hasher)
  25. }
  26. }
  27. @Binding private var selection: Identifier
  28. private let titleKey: LocalizedStringKey?
  29. private let type: any QEMUConstant.Type
  30. init<T: QEMUConstant>(_ titleKey: LocalizedStringKey? = nil, selection: Binding<T>) {
  31. self._selection = Binding(get: {
  32. Identifier(selection.wrappedValue.rawValue)
  33. }, set: { newValue in
  34. selection.wrappedValue = T(rawValue: newValue.string)!
  35. })
  36. self.titleKey = titleKey
  37. self.type = T.self
  38. }
  39. init<S>(_ titleKey: LocalizedStringKey? = nil, selection: Binding<S>, type: any QEMUConstant.Type) {
  40. self._selection = Binding(get: {
  41. Identifier((selection.wrappedValue as! any QEMUConstant).rawValue)
  42. }, set: { newValue in
  43. selection.wrappedValue = type.init(rawValue: newValue.string)! as! S
  44. })
  45. self.titleKey = titleKey
  46. self.type = type
  47. }
  48. var body: some View {
  49. Picker(titleKey ?? "", selection: $selection) {
  50. ForEach(type.shownPrettyValues) { displayValue in
  51. Text(displayValue).tag(identifier(for: displayValue))
  52. }
  53. }
  54. }
  55. private nonmutating func identifier(for displayValue: String) -> Identifier {
  56. let index = type.allPrettyValues.firstIndex(of: displayValue)!
  57. return Identifier(type.allRawValues[index])
  58. }
  59. }
  60. struct VMConfigConstantPicker_Previews: PreviewProvider {
  61. @State static private var fixedType: QEMUArchitecture = .aarch64
  62. @State static private var dynamicType: any QEMUCPU = QEMUCPU_aarch64.default
  63. static var previews: some View {
  64. VStack {
  65. HStack {
  66. Text("Selected:")
  67. Spacer()
  68. Text(fixedType.prettyValue)
  69. Text(dynamicType.prettyValue)
  70. }
  71. VMConfigConstantPicker("Text", selection: $fixedType)
  72. VMConfigConstantPicker(selection: $dynamicType, type: QEMUCPU_aarch64.self)
  73. }
  74. }
  75. }