diff options
Diffstat (limited to 'Map/Views')
| -rw-r--r-- | Map/Views/ContentView.swift | 116 | ||||
| -rw-r--r-- | Map/Views/DefaultMapView.swift | 23 | ||||
| -rw-r--r-- | Map/Views/EvolutionPicker.swift | 48 | ||||
| -rw-r--r-- | Map/Views/MapApp.swift | 23 | ||||
| -rw-r--r-- | Map/Views/MapDetail.swift | 103 | ||||
| -rw-r--r-- | Map/Views/MapRender.swift | 66 | ||||
| -rw-r--r-- | Map/Views/MapTextEditor.swift | 148 | ||||
| -rw-r--r-- | Map/Views/SlowMapRender.swift | 90 |
8 files changed, 0 insertions, 617 deletions
diff --git a/Map/Views/ContentView.swift b/Map/Views/ContentView.swift deleted file mode 100644 index 534c14c..0000000 --- a/Map/Views/ContentView.swift +++ /dev/null @@ -1,116 +0,0 @@ -// -// ContentView.swift -// Map -// -// Created by Ruben Beltran del Rio on 2/1/21. -// - -import CoreData -import SwiftUI - -struct ContentView: View { - @Environment(\.managedObjectContext) private var viewContext - - @EnvironmentObject var store: AppStore - - @FetchRequest( - sortDescriptors: [NSSortDescriptor(keyPath: \Map.createdAt, ascending: true)], - animation: .default) - private var maps: FetchedResults<Map> - - var body: some View { - NavigationView { - List { - if maps.count == 0 { - DefaultMapView() - } - ForEach(maps) { map in - NavigationLink( - destination: MapDetailView(map: map, title: map.title ?? "", content: map.content ?? "") - ) { - HStack { - Text(map.title ?? "Untitled Map") - Spacer() - Text(mapFormatter.string(from: (map.createdAt ?? Date()))) - .font(.caption) - .padding(.vertical, 2.0) - .padding(.horizontal, 4.0) - .background(Color.accentColor) - .foregroundColor(Color.black) - .cornerRadius(2.0) - }.padding(.leading, 8.0) - }.contextMenu { - Button( - action: { store.send(.deleteMap(map: map)) }, - label: { - Image(systemName: "trash") - Text("Delete") - }) - } - } - .onDelete(perform: deleteMaps) - }.frame(minWidth: 250.0, alignment: .leading) - .toolbar { - HStack { - Button(action: toggleSidebar) { - Label("Toggle Sidebar", systemImage: "sidebar.left") - } - Button(action: addMap) { - Label("Add Map", systemImage: "plus") - } - } - } - DefaultMapView() - } - } - - private func toggleSidebar() { - NSApp.keyWindow?.firstResponder?.tryToPerform( - #selector(NSSplitViewController.toggleSidebar(_:)), with: nil) - } - - private func addMap() { - withAnimation { - let newMap = Map(context: viewContext) - newMap.uuid = UUID() - newMap.createdAt = Date() - newMap.title = "Map \(newMap.createdAt!.format())" - newMap.content = "" - - do { - try viewContext.save() - } catch { - let nsError = error as NSError - fatalError("Unresolved error \(nsError), \(nsError.userInfo)") - } - } - } - - private func deleteMaps(offsets: IndexSet) { - - withAnimation { - offsets.map { maps[$0] }.forEach(viewContext.delete) - - do { - try viewContext.save() - } catch { - let nsError = error as NSError - fatalError("Unresolved error \(nsError), \(nsError.userInfo)") - } - } - } -} - -private let mapFormatter: DateFormatter = { - let formatter = DateFormatter() - formatter.dateStyle = .short - formatter.timeStyle = .none - return formatter -}() - -struct ContentView_Previews: PreviewProvider { - static var previews: some View { - ContentView().environment( - \.managedObjectContext, PersistenceController.preview.container.viewContext) - } -} diff --git a/Map/Views/DefaultMapView.swift b/Map/Views/DefaultMapView.swift deleted file mode 100644 index 1f624d2..0000000 --- a/Map/Views/DefaultMapView.swift +++ /dev/null @@ -1,23 +0,0 @@ -// -// ContentView.swift -// Map -// -// Created by Ruben Beltran del Rio on 2/1/21. -// - -import CoreData -import SwiftUI - -struct DefaultMapView: View { - - var body: some View { - Text("Select a map from the left hand side, or click on + to create one.") - } -} - -struct DefaultMapView_Previews: PreviewProvider { - static var previews: some View { - DefaultMapView().environment( - \.managedObjectContext, PersistenceController.preview.container.viewContext) - } -} diff --git a/Map/Views/EvolutionPicker.swift b/Map/Views/EvolutionPicker.swift deleted file mode 100644 index 815f575..0000000 --- a/Map/Views/EvolutionPicker.swift +++ /dev/null @@ -1,48 +0,0 @@ -// -// EvolutionPicker.swift -// Map -// -// Created by Ruben Beltran del Rio on 2/4/21. -// - -import SwiftUI - -struct EvolutionPicker: View { - - @EnvironmentObject private var store: AppStore - - private var selectedEvolution: Binding<StageType> { - Binding( - get: { store.state.selectedEvolution }, - set: { evolution in - store.send(.selectEvolution(evolution: evolution)) - } - ) - } - - var body: some View { - Picker("Evolution", selection: selectedEvolution) { - ForEach(StageType.types) { stage in - Text(Stage.title(stage)).tag(stage).padding(4.0) - } - Divider() - ForEach(StageType.characteristics) { stage in - Text(Stage.title(stage)).tag(stage).padding(4.0) - } - Divider() - ForEach(StageType.properties) { stage in - Text(Stage.title(stage)).tag(stage).padding(4.0) - } - Divider() - ForEach(StageType.custom) { stage in - Text(Stage.title(stage)).tag(stage).padding(4.0) - } - }.padding(.horizontal, 8.0).padding(.vertical, 4.0) - } -} - -struct EvolutionPicker_Previews: PreviewProvider { - static var previews: some View { - EvolutionPicker() - } -} diff --git a/Map/Views/MapApp.swift b/Map/Views/MapApp.swift deleted file mode 100644 index a0e2d60..0000000 --- a/Map/Views/MapApp.swift +++ /dev/null @@ -1,23 +0,0 @@ -// -// MapApp.swift -// Map -// -// Created by Ruben Beltran del Rio on 2/1/21. -// - -import SwiftUI - -@main -struct MapApp: App { - let persistenceController = PersistenceController.shared - - var body: some Scene { - WindowGroup { - ContentView() - .environment(\.managedObjectContext, persistenceController.container.viewContext) - .environmentObject(AppStore(initialState: AppState(), reducer: appStateReducer)) - }.windowStyle(HiddenTitleBarWindowStyle()).commands { - SidebarCommands() - } - } -} diff --git a/Map/Views/MapDetail.swift b/Map/Views/MapDetail.swift deleted file mode 100644 index bebe3a1..0000000 --- a/Map/Views/MapDetail.swift +++ /dev/null @@ -1,103 +0,0 @@ -// -// ContentView.swift -// Map -// -// Created by Ruben Beltran del Rio on 2/1/21. -// - -import Combine -import CoreData -import SwiftUI - -class SaveTimer { - let currentTimePublisher = Timer.TimerPublisher(interval: 1, runLoop: .main, mode: .default) - let cancellable: AnyCancellable? - - init() { - self.cancellable = currentTimePublisher.connect() as? AnyCancellable - } - - deinit { - self.cancellable?.cancel() - } -} - -let timer = SaveTimer() - -struct MapDetailView: View { - @Environment(\.managedObjectContext) private var viewContext - @Environment(\.colorScheme) var colorScheme - - @EnvironmentObject var store: AppStore - - @ObservedObject var map: Map - - private var mapColor: MapColor { - MapColor.colorForScheme(colorScheme) - } - - @State var title: String - @State var content: String - - var body: some View { - if map.uuid != nil { - VSplitView { - VStack { - HStack { - TextField( - "Title", text: $title - ).font(.title2).textFieldStyle(PlainTextFieldStyle()).padding(.vertical, 4.0).padding( - .leading, 4.0) - Button(action: saveText) { - Image(systemName: "doc.text") - }.padding(.vertical, 4.0).padding(.leading, 4.0) - Button(action: saveImage) { - Image(systemName: "photo") - }.padding(.vertical, 4.0).padding(.leading, 4.0).padding(.trailing, 8.0) - } - EvolutionPicker() - - ZStack(alignment: .topLeading) { - MapTextEditor(text: $content, colorScheme: colorScheme) - .background(mapColor.background) - .foregroundColor(mapColor.foreground) - .frame(minHeight: 96.0) - }.padding(.top, 8.0).padding(.leading, 8.0).background(mapColor.background).cornerRadius( - 5.0) - }.padding(.horizontal, 8.0) - ScrollView([.horizontal, .vertical]) { - SlowMapRender( - content: content, evolution: Stage.stages(store.state.selectedEvolution), - colorScheme: colorScheme) - }.background(mapColor.background) - }.onReceive(timer.currentTimePublisher) { _ in - saveModel() - }.onDisappear { - saveModel() - } - } else { - DefaultMapView() - } - } - - private func saveModel() { - map.content = content - map.title = title - try? viewContext.save() - } - - private func saveText() { - store.send(.exportMapAsText(map: map)) - } - - private func saveImage() { - store.send(.exportMapAsImage(map: map)) - } -} - -struct MapDetailView_Previews: PreviewProvider { - static var previews: some View { - MapDetailView(map: Map(), title: "", content: "").environment( - \.managedObjectContext, PersistenceController.preview.container.viewContext) - } -} diff --git a/Map/Views/MapRender.swift b/Map/Views/MapRender.swift deleted file mode 100644 index aa97e22..0000000 --- a/Map/Views/MapRender.swift +++ /dev/null @@ -1,66 +0,0 @@ -// -// ContentView.swift -// Map -// -// Created by Ruben Beltran del Rio on 2/1/21. -// - -import Combine -import CoreData -import CoreGraphics -import SwiftUI - -struct MapRenderView: View { - - @Environment(\.colorScheme) var colorScheme - - @Binding var content: String - @Binding var evolution: Stage - - @State var parsedMap: ParsedMap = ParsedMap.empty - - let mapSize = CGSize(width: 1300.0, height: 1000.0) - - let lineWidth = CGFloat(1.0) - let vertexSize = CGSize(width: 25.0, height: 25.0) - let padding = CGFloat(30.0) - - var body: some View { - ZStack(alignment: .topLeading) { - - Path { path in - path.addRect( - CGRect( - x: -padding, y: -padding, width: mapSize.width + padding * 2, - height: mapSize.height + padding * 4)) - }.fill(MapColor.colorForScheme(colorScheme).background) - - MapStages(mapSize: mapSize, lineWidth: lineWidth, stages: parsedMap.stages) - MapAxes( - mapSize: mapSize, lineWidth: lineWidth, evolution: evolution, stages: parsedMap.stages) - MapOpportunities( - mapSize: mapSize, lineWidth: lineWidth, vertexSize: vertexSize, - opportunities: parsedMap.opportunities) - MapBlockers(mapSize: mapSize, vertexSize: vertexSize, blockers: parsedMap.blockers) - MapVertices(mapSize: mapSize, vertexSize: vertexSize, vertices: parsedMap.vertices) - MapEdges( - mapSize: mapSize, lineWidth: lineWidth, vertexSize: vertexSize, edges: parsedMap.edges) - }.frame( - width: mapSize.width, - height: mapSize.height + 2 * padding, alignment: .topLeading - ).onAppear { - self.parsedMap = Map.parse(content: content) - }.padding(padding).onChange(of: content) { newState in - self.parsedMap = Map.parse(content: newState) - } - } -} - -struct MapRenderView_Previews: PreviewProvider { - static var previews: some View { - MapRenderView( - content: Binding.constant(""), evolution: Binding.constant(Stage.stages(.general)) - ).environment( - \.managedObjectContext, PersistenceController.preview.container.viewContext) - } -} diff --git a/Map/Views/MapTextEditor.swift b/Map/Views/MapTextEditor.swift deleted file mode 100644 index 4fbff82..0000000 --- a/Map/Views/MapTextEditor.swift +++ /dev/null @@ -1,148 +0,0 @@ -import Cocoa -import SwiftUI - -class MapTextEditorController: NSViewController { - - @Binding var text: String - var colorScheme: ColorScheme - - private let vertexRegex = MapParsingPatterns.vertex - private let edgeRegex = MapParsingPatterns.edge - private let blockerRegex = MapParsingPatterns.blocker - private let opportunityRegex = MapParsingPatterns.opportunity - private let stageRegex = MapParsingPatterns.stage - - private let debouncer: Debouncer = Debouncer(seconds: 0.2) - - init(text: Binding<String>, colorScheme: ColorScheme) { - self._text = text - self.colorScheme = colorScheme - super.init(nibName: nil, bundle: nil) - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - override func loadView() { - let scrollView = NSTextView.scrollableTextView() - let textView = scrollView.documentView as! NSTextView - - scrollView.translatesAutoresizingMaskIntoConstraints = false - - textView.allowsUndo = true - textView.delegate = self - textView.textStorage?.delegate = self - textView.string = self.text - textView.isEditable = true - textView.font = .monospacedSystemFont(ofSize: 16.0, weight: .regular) - self.view = scrollView - } - - override func viewDidAppear() { - self.view.window?.makeFirstResponder(self.view) - } - - func updateColorScheme(_ colorScheme: ColorScheme) { - self.colorScheme = colorScheme - } -} - -extension MapTextEditorController: NSTextViewDelegate { - - func textDidChange(_ obj: Notification) { - if let textField = obj.object as? NSTextView { - self.text = textField.string - } - } - - func textView(_ view: NSTextView, shouldChangeTextIn: NSRange, replacementString: String?) -> Bool - { - let range = Range(shouldChangeTextIn, in: view.string) - let target = view.string[range!] - - if target == "--" { - return false - } - - return true - } -} - -extension MapTextEditorController: NSTextStorageDelegate { - override func textStorageDidProcessEditing(_ obj: Notification) { - if let textStorage = obj.object as? NSTextStorage { - debouncer.debounce { - DispatchQueue.main.async { - self.colorizeText(textStorage: textStorage) - } - } - } - } - - private func colorizeText(textStorage: NSTextStorage) { - let range = NSMakeRange(0, textStorage.length) - var matches = vertexRegex.matches(in: textStorage.string, options: [], range: range) - let colors = MapColor.colorForScheme(colorScheme) - - for match in matches { - textStorage.addAttributes([.foregroundColor: colors.syntax.vertex], range: match.range(at: 1)) - textStorage.addAttributes([.foregroundColor: colors.syntax.number], range: match.range(at: 2)) - textStorage.addAttributes([.foregroundColor: colors.syntax.number], range: match.range(at: 3)) - textStorage.addAttributes([.foregroundColor: colors.syntax.option], range: match.range(at: 4)) - } - - matches = edgeRegex.matches(in: textStorage.string, options: [], range: range) - - for match in matches { - textStorage.addAttributes([.foregroundColor: colors.syntax.vertex], range: match.range(at: 1)) - let arrowRange = match.range(at: 2) - textStorage.addAttributes( - [.foregroundColor: colors.syntax.symbol], - range: NSMakeRange(arrowRange.lowerBound - 1, arrowRange.length + 1)) - textStorage.addAttributes([.foregroundColor: colors.syntax.vertex], range: match.range(at: 3)) - } - - matches = opportunityRegex.matches(in: textStorage.string, options: [], range: range) - - for match in matches { - textStorage.addAttributes([.foregroundColor: colors.syntax.option], range: match.range(at: 1)) - textStorage.addAttributes([.foregroundColor: colors.syntax.vertex], range: match.range(at: 2)) - textStorage.addAttributes([.foregroundColor: colors.syntax.symbol], range: match.range(at: 3)) - textStorage.addAttributes([.foregroundColor: colors.syntax.number], range: match.range(at: 4)) - } - - matches = blockerRegex.matches(in: textStorage.string, options: [], range: range) - - for match in matches { - textStorage.addAttributes([.foregroundColor: colors.syntax.option], range: match.range(at: 1)) - textStorage.addAttributes([.foregroundColor: colors.syntax.vertex], range: match.range(at: 2)) - } - - matches = stageRegex.matches(in: textStorage.string, options: [], range: range) - - for match in matches { - textStorage.addAttributes([.foregroundColor: colors.syntax.option], range: match.range(at: 1)) - textStorage.addAttributes([.foregroundColor: colors.syntax.number], range: match.range(at: 2)) - } - } -} - -struct MapTextEditor: NSViewControllerRepresentable { - - @Binding var text: String - let colorScheme: ColorScheme - - func makeNSViewController( - context: NSViewControllerRepresentableContext<MapTextEditor> - ) -> MapTextEditorController { - return MapTextEditorController(text: $text, colorScheme: colorScheme) - } - - func updateNSViewController( - _ nsViewController: MapTextEditorController, - context: NSViewControllerRepresentableContext<MapTextEditor> - ) { - nsViewController.updateColorScheme(context.environment.colorScheme) - } -} diff --git a/Map/Views/SlowMapRender.swift b/Map/Views/SlowMapRender.swift deleted file mode 100644 index b7cd842..0000000 --- a/Map/Views/SlowMapRender.swift +++ /dev/null @@ -1,90 +0,0 @@ -import Cocoa -import SwiftUI - -class SlowMapRenderController: NSViewController { - - var content: String - private var contentBinding: Binding<String> { - Binding( - get: { self.content }, - set: { content in - self.content = content - } - ) - } - - var evolution: Stage - private var evolutionBinding: Binding<Stage> { - Binding( - get: { self.evolution }, - set: { evolution in - self.evolution = evolution - } - ) - } - private var colorSchemeEnvironment: ObservableColorSchemeEnvironment - - private let debouncer: Debouncer = Debouncer(seconds: 0.1) - - init(content: String, evolution: Stage, colorScheme: ColorScheme) { - - self.content = content - self.evolution = evolution - self.colorSchemeEnvironment = ObservableColorSchemeEnvironment(colorScheme: colorScheme) - super.init(nibName: nil, bundle: nil) - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - override func loadView() { - - let renderView = MapRenderView(content: self.contentBinding, evolution: self.evolutionBinding) - .environmentObject(self.colorSchemeEnvironment) - let hostingView = NSHostingView(rootView: renderView) - - self.view = hostingView - } - - func update(content: String, evolution: Stage, colorScheme: ColorScheme) { - self.debouncer.debounce { - DispatchQueue.main.async { - print("Updating: START") - self.content = content - self.evolution = evolution - self.colorSchemeEnvironment.colorScheme = colorScheme - print("Updating: END") - } - } - } - - private class ObservableColorSchemeEnvironment: ObservableObject { - @Published var colorScheme: ColorScheme - - init(colorScheme: ColorScheme) { - self.colorScheme = colorScheme - } - } -} - -struct SlowMapRender: NSViewControllerRepresentable { - - var content: String - var evolution: Stage - let colorScheme: ColorScheme - - func makeNSViewController( - context: NSViewControllerRepresentableContext<SlowMapRender> - ) -> SlowMapRenderController { - return SlowMapRenderController(content: content, evolution: evolution, colorScheme: colorScheme) - } - - func updateNSViewController( - _ nsViewController: SlowMapRenderController, - context: NSViewControllerRepresentableContext<SlowMapRender> - ) { - nsViewController.update( - content: content, evolution: evolution, colorScheme: context.environment.colorScheme) - } -} |