aboutsummaryrefslogtreecommitdiff
path: root/Map/Data
diff options
context:
space:
mode:
Diffstat (limited to 'Map/Data')
-rw-r--r--Map/Data/UserPreferences.swift322
1 files changed, 322 insertions, 0 deletions
diff --git a/Map/Data/UserPreferences.swift b/Map/Data/UserPreferences.swift
new file mode 100644
index 0000000..cf9dd7e
--- /dev/null
+++ b/Map/Data/UserPreferences.swift
@@ -0,0 +1,322 @@
+// Copyright (C) 2024 Rubén Beltrán del Río
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see https://map.tranquil.systems.
+
+import Foundation
+
+// MARK: - JSON Export/Import Structures
+struct UserPreferencesJSON: Codable {
+ // MARK: - Map Preferences
+ var showMapBackground: Bool?
+ var useCustomFont: Bool?
+ var customFontName: String?
+ var defaultExportFormat: String?
+ var useSmartLabelPositioning: Bool?
+
+ // MARK: - Editor Preferences
+ var useSmartEditor: Bool?
+ var useCustomEditorFont: Bool?
+ var customEditorFontName: String?
+ var editorFontSize: Double?
+
+ // MARK: - Templates (as actual objects)
+ var mapTemplates: [Template]?
+
+ // MARK: - Stages (as actual objects)
+ var customStages: [CustomStage]?
+
+ // MARK: - UI Preferences
+ var viewStyle: String?
+ var zoom: Double?
+}
+
+struct UserPreferences: Codable {
+
+ // MARK: - Map Preferences
+ var showMapBackground: Bool
+ var useCustomFont: Bool
+ var customFontName: String
+ var defaultExportFormat: String
+ var useSmartLabelPositioning: Bool
+
+ // MARK: - Editor Preferences
+ var useSmartEditor: Bool
+ var useCustomEditorFont: Bool
+ var customEditorFontName: String
+ var editorFontSize: Double
+
+ // MARK: - Templates
+ var mapTemplates: Data
+
+ // MARK: - Stages
+ var customStages: Data
+
+ // MARK: - UI Preferences
+ var viewStyle: String
+ var zoom: Double
+
+ // MARK: - Default Values
+ struct Defaults {
+ static let showMapBackground = true
+ static let useCustomFont = false
+ static let customFontName = "Helvetica"
+ static let defaultExportFormat = "png"
+ static let useSmartLabelPositioning = true
+
+ static let useSmartEditor = false
+ static let useCustomEditorFont = false
+ static let customEditorFontName = "Menlo"
+ static let editorFontSize = 14.0
+
+ static let viewStyle = "horizontal"
+ static let zoom = 1.0
+
+ // Computed properties for complex defaults
+ static var mapTemplates: Data {
+ let defaultTemplate = Template(
+ name: String(localized: "map_template.default.title"),
+ content: String(localized: "map_template.default.content"),
+ isDefault: true
+ )
+
+ let emptyTemplate = Template(
+ name: String(localized: "map_template.empty.title"),
+ content: "",
+ isDefault: false
+ )
+
+ let templates = [defaultTemplate, emptyTemplate]
+ return (try? JSONEncoder().encode(templates)) ?? Data()
+ }
+
+ static var customStages: Data {
+ let defaultStage = CustomStage.cynefinDefault()
+ let stages = [defaultStage]
+ return (try? JSONEncoder().encode(stages)) ?? Data()
+ }
+ }
+
+ // MARK: - Initialization
+ init() {
+ self.showMapBackground = Defaults.showMapBackground
+ self.useCustomFont = Defaults.useCustomFont
+ self.customFontName = Defaults.customFontName
+ self.defaultExportFormat = Defaults.defaultExportFormat
+ self.useSmartLabelPositioning = Defaults.useSmartLabelPositioning
+
+ self.useSmartEditor = Defaults.useSmartEditor
+ self.useCustomEditorFont = Defaults.useCustomEditorFont
+ self.customEditorFontName = Defaults.customEditorFontName
+ self.editorFontSize = Defaults.editorFontSize
+
+ self.mapTemplates = Defaults.mapTemplates
+ self.customStages = Defaults.customStages
+
+ self.viewStyle = Defaults.viewStyle
+ self.zoom = Defaults.zoom
+ }
+
+ // MARK: - JSON Methods
+ func toJSON() -> String? {
+ let encoder = JSONEncoder()
+ encoder.outputFormatting = .prettyPrinted
+
+ do {
+ // Convert to JSON-friendly format
+ let jsonPrefs = UserPreferencesJSON(
+ showMapBackground: showMapBackground,
+ useCustomFont: useCustomFont,
+ customFontName: customFontName,
+ defaultExportFormat: defaultExportFormat,
+ useSmartLabelPositioning: useSmartLabelPositioning,
+ useSmartEditor: useSmartEditor,
+ useCustomEditorFont: useCustomEditorFont,
+ customEditorFontName: customEditorFontName,
+ editorFontSize: editorFontSize,
+ mapTemplates: templatesFromData(mapTemplates),
+ customStages: stagesFromData(customStages),
+ viewStyle: viewStyle,
+ zoom: zoom
+ )
+
+ let data = try encoder.encode(jsonPrefs)
+ return String(data: data, encoding: .utf8)
+ } catch {
+ return nil
+ }
+ }
+
+ mutating func updateFromJSON(_ json: String) -> Bool {
+ guard let data = json.data(using: .utf8) else { return false }
+ do {
+ let decoder = JSONDecoder()
+ let jsonPrefs = try decoder.decode(UserPreferencesJSON.self, from: data)
+
+ // Convert from JSON format back to UserPreferences
+ // Only update values that are present in the JSON (partial updates)
+ if let value = jsonPrefs.showMapBackground {
+ self.showMapBackground = value
+ }
+ if let value = jsonPrefs.useCustomFont {
+ self.useCustomFont = value
+ }
+ if let value = jsonPrefs.customFontName {
+ self.customFontName = value
+ }
+ if let value = jsonPrefs.defaultExportFormat {
+ self.defaultExportFormat = value
+ }
+ if let value = jsonPrefs.useSmartLabelPositioning {
+ self.useSmartLabelPositioning = value
+ }
+ if let value = jsonPrefs.useSmartEditor {
+ self.useSmartEditor = value
+ }
+ if let value = jsonPrefs.useCustomEditorFont {
+ self.useCustomEditorFont = value
+ }
+ if let value = jsonPrefs.customEditorFontName {
+ self.customEditorFontName = value
+ }
+ if let value = jsonPrefs.editorFontSize {
+ self.editorFontSize = value
+ }
+ if let value = jsonPrefs.mapTemplates {
+ self.mapTemplates = dataFromTemplates(value)
+ }
+ if let value = jsonPrefs.customStages {
+ self.customStages = dataFromStages(value)
+ }
+ if let value = jsonPrefs.viewStyle {
+ self.viewStyle = value
+ }
+ if let value = jsonPrefs.zoom {
+ self.zoom = value
+ }
+
+ apply()
+ return true
+ } catch {
+ print("JSON import error: \(error)")
+ return false
+ }
+ }
+
+ // MARK: - Helper Methods for Data/Object Conversion
+ private func templatesFromData(_ data: Data) -> [Template] {
+ guard let templates = try? JSONDecoder().decode([Template].self, from: data) else {
+ return []
+ }
+ return templates
+ }
+
+ private func dataFromTemplates(_ templates: [Template]) -> Data {
+ guard let data = try? JSONEncoder().encode(templates) else {
+ return Data()
+ }
+ return data
+ }
+
+ private func stagesFromData(_ data: Data) -> [CustomStage] {
+ guard let stages = try? JSONDecoder().decode([CustomStage].self, from: data) else {
+ return []
+ }
+ return stages
+ }
+
+ private func dataFromStages(_ stages: [CustomStage]) -> Data {
+ guard let data = try? JSONEncoder().encode(stages) else {
+ return Data()
+ }
+ return data
+ }
+
+ // MARK: - Reset to Defaults
+ mutating func resetToDefaults() {
+ self = UserPreferences()
+ apply()
+ }
+
+ // MARK: - Apply to UserDefaults
+ private func apply() {
+ let defaults = UserDefaults.standard
+
+ // Map Preferences
+ defaults.set(showMapBackground, forKey: "showMapBackground")
+ defaults.set(useCustomFont, forKey: "useCustomFont")
+ defaults.set(customFontName, forKey: "customFontName")
+ defaults.set(defaultExportFormat, forKey: "defaultExportFormat")
+ defaults.set(useSmartLabelPositioning, forKey: "useSmartLabelPositioning")
+
+ // Editor Preferences
+ defaults.set(useSmartEditor, forKey: "useSmartEditor")
+ defaults.set(useCustomEditorFont, forKey: "useCustomEditorFont")
+ defaults.set(customEditorFontName, forKey: "customEditorFontName")
+ defaults.set(editorFontSize, forKey: "editorFontSize")
+
+ // Templates
+ defaults.set(mapTemplates, forKey: "mapTemplates")
+
+ // Stages
+ defaults.set(customStages, forKey: "customStages")
+
+ // UI Preferences
+ defaults.set(viewStyle, forKey: "viewStyle")
+ defaults.set(zoom, forKey: "zoom")
+ }
+
+ // MARK: - Load from UserDefaults
+ static func loadFromUserDefaults() -> UserPreferences {
+ let defaults = UserDefaults.standard
+
+ var preferences = UserPreferences()
+
+ // Map Preferences
+ preferences.showMapBackground =
+ defaults.object(forKey: "showMapBackground") as? Bool ?? Defaults.showMapBackground
+ preferences.useCustomFont =
+ defaults.object(forKey: "useCustomFont") as? Bool ?? Defaults.useCustomFont
+ preferences.customFontName =
+ defaults.object(forKey: "customFontName") as? String ?? Defaults.customFontName
+ preferences.defaultExportFormat =
+ defaults.object(forKey: "defaultExportFormat") as? String ?? Defaults.defaultExportFormat
+ preferences.useSmartLabelPositioning =
+ defaults.object(forKey: "useSmartLabelPositioning") as? Bool
+ ?? Defaults.useSmartLabelPositioning
+
+ // Editor Preferences
+ preferences.useSmartEditor =
+ defaults.object(forKey: "useSmartEditor") as? Bool ?? Defaults.useSmartEditor
+ preferences.useCustomEditorFont =
+ defaults.object(forKey: "useCustomEditorFont") as? Bool ?? Defaults.useCustomEditorFont
+ preferences.customEditorFontName =
+ defaults.object(forKey: "customEditorFontName") as? String ?? Defaults.customEditorFontName
+ preferences.editorFontSize =
+ defaults.object(forKey: "editorFontSize") as? Double ?? Defaults.editorFontSize
+
+ // Templates
+ preferences.mapTemplates =
+ defaults.object(forKey: "mapTemplates") as? Data ?? Defaults.mapTemplates
+
+ // Stages
+ preferences.customStages =
+ defaults.object(forKey: "customStages") as? Data ?? Defaults.customStages
+
+ // UI Preferences
+ preferences.viewStyle = defaults.object(forKey: "viewStyle") as? String ?? Defaults.viewStyle
+ preferences.zoom = defaults.object(forKey: "zoom") as? Double ?? Defaults.zoom
+
+ return preferences
+ }
+}