]> git.r.bdr.sh - rbdr/map/blobdiff - Map/Presentation/Commands/MapCommands.swift
Add some debouncing
[rbdr/map] / Map / Presentation / Commands / MapCommands.swift
index 32b49584da1cbd4f947176bd06a3df582d32047e..35250e26b76124009f5b35aa77c80592cfd197b0 100644 (file)
@@ -1,12 +1,78 @@
+// 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 SwiftUI
 
 struct MapCommands: Commands {
 
   @AppStorage("viewStyle") var viewStyle: ViewStyle = .horizontal
   @AppStorage("zoom") var zoom = 1.0
+  @FocusedBinding(\.document) var document: MapDocument?
+  @FocusedValue(\.fileURL) var url: URL?
+  @FocusedBinding(\.selectedEvolution) var selectedEvolution: StageType?
+  @FocusedBinding(\.isSearching) var isSearching
 
   var body: some Commands {
 
+    // File
+
+    CommandGroup(after: CommandGroupPlacement.saveItem) {
+      Divider()
+      Button("Export...") {
+        if let selectedEvolution, let document {
+          if let image = document.exportAsImage(withEvolution: selectedEvolution) {
+
+            let filename = url?.deletingPathExtension().lastPathComponent ?? "Untitled"
+
+            let savePanel = NSSavePanel()
+            savePanel.allowedContentTypes = [.png]
+            savePanel.canCreateDirectories = true
+            savePanel.isExtensionHidden = false
+            savePanel.title = "Save \(filename) as image"
+            savePanel.message = "Choose a location to save the image"
+            savePanel.nameFieldStringValue = "\(filename).png"
+            savePanel.begin { result in
+              if result == .OK, let url = savePanel.url {
+                if let tiffRepresentation = image.tiffRepresentation {
+                  let bitmapImage = NSBitmapImageRep(data: tiffRepresentation)
+                  let pngData = bitmapImage?.representation(using: .png, properties: [:])
+                  do {
+                    try pngData?.write(to: url)
+                  } catch {
+                    return
+                  }
+                }
+              }
+            }
+          }
+        }
+      }.keyboardShortcut(
+        "e", modifiers: EventModifiers([.command])
+      ).disabled(document == nil)
+    }
+
+    // Edit
+
+    CommandGroup(after: CommandGroupPlacement.pasteboard) {
+      Divider()
+      Button("Find...") {
+        isSearching = isSearching != nil ? !isSearching! : true
+      }.keyboardShortcut(
+        "f", modifiers: EventModifiers([.command])
+      ).disabled(document == nil)
+    }
+
     // View
 
     CommandGroup(after: CommandGroupPlacement.toolbar) {
@@ -15,25 +81,25 @@ struct MapCommands: Commands {
           viewStyle = .vertical
         }.keyboardShortcut(
           "l", modifiers: EventModifiers([.command])
-        )
+        ).disabled(document == nil)
       } else {
         Button("Use Horizontal Layout") {
           viewStyle = .horizontal
         }.keyboardShortcut(
           "l", modifiers: EventModifiers([.command])
-        )
+        ).disabled(document == nil)
       }
       Divider()
       Button("Zoom In") {
         zoom = min(Constants.kMaxZoom, zoom + 0.1)
       }.keyboardShortcut(
         "+", modifiers: EventModifiers([.command])
-      )
+      ).disabled(document == nil)
       Button("Zoom Out") {
         zoom = max(Constants.kMinZoom, zoom - 0.1)
       }.keyboardShortcut(
         "-", modifiers: EventModifiers([.command])
-      )
+      ).disabled(document == nil)
       Divider()
     }