spb/focale Public
Swift 100%
1//2// GestureMap.swift3// Focale4//5// Author: Simon-Pierre Boucher6// Contact: contact@spboucher.ai7//8// Fully reassignable gesture → control mapping (CLAUDE.md §6):9// left vertical drag = ISO, horizontal = exposure, etc.10//1112import Foundation1314/// A gesture slot on the capture screen that can drive a control.15enum GestureSlot: String, Codable, Sendable, CaseIterable, Identifiable {16 case leftVerticalDrag17 case rightVerticalDrag18 case horizontalDrag19 case pinch2021 var id: String { rawValue }2223 /// User-facing label, in French.24 var displayName: String {25 switch self {26 case .leftVerticalDrag: "Glissement vertical gauche"27 case .rightVerticalDrag: "Glissement vertical droit"28 case .horizontalDrag: "Glissement horizontal"29 case .pinch: "Pincement"30 }31 }32}3334struct GestureMap: Codable, Sendable {35 private var assignments: [GestureSlot.RawValue: CaptureControl.RawValue]3637 init(_ assignments: [GestureSlot: CaptureControl]) {38 self.assignments = Dictionary(39 uniqueKeysWithValues: assignments.map { ($0.key.rawValue, $0.value.rawValue) }40 )41 }4243 func control(for slot: GestureSlot) -> CaptureControl? {44 assignments[slot.rawValue].flatMap(CaptureControl.init(rawValue:))45 }4647 mutating func assign(_ control: CaptureControl?, to slot: GestureSlot) {48 assignments[slot.rawValue] = control?.rawValue49 }5051 static let standard = GestureMap([52 .leftVerticalDrag: .iso,53 .rightVerticalDrag: .shutterSpeed,54 .horizontalDrag: .exposureBias,55 .pinch: .zoom,56 ])57}58