diff --git a/Boop/Boop/AppDelegate.swift b/Boop/Boop/AppDelegate.swift index bff23474..94899a9e 100644 --- a/Boop/Boop/AppDelegate.swift +++ b/Boop/Boop/AppDelegate.swift @@ -17,8 +17,10 @@ class AppDelegate: NSObject, NSApplicationDelegate { @IBOutlet weak var closePickerMenuItem: NSMenuItem! @IBOutlet weak var popoverViewController: PopoverViewController! + @IBOutlet weak var mainViewController: MainViewController! @IBOutlet weak var scriptManager: ScriptManager! @IBOutlet weak var editor: SyntaxTextView! + @IBOutlet weak var statusView: StatusView! // Frame auto save name for app window frame restoration. private static let appWindowName = "boop.app.window" @@ -42,6 +44,18 @@ class AppDelegate: NSObject, NSApplicationDelegate { return true } + func application(_ sender: NSApplication, openFile filename: String) -> Bool { + + let text=try? String(contentsOf: URL(fileURLWithPath: filename)) + + if text == nil { + self.statusView.setStatus(.error("Failed to load file: '\(filename)'.")) + } else { + editor.text = text! + } + return true + } + @IBAction func showPreferencesWindow(_ sender: NSMenuItem) { let controller = NSStoryboard.init(name: "Preferences", bundle: nil).instantiateInitialController() as? NSWindowController diff --git a/Boop/Boop/Boop.entitlements b/Boop/Boop/Boop.entitlements index 6abec674..09dedc8e 100644 --- a/Boop/Boop/Boop.entitlements +++ b/Boop/Boop/Boop.entitlements @@ -10,5 +10,7 @@ com.apple.security.network.client + com.apple.security.files.user-selected.read-write + diff --git a/Boop/Boop/BoopRelease.entitlements b/Boop/Boop/BoopRelease.entitlements index 6abec674..09dedc8e 100644 --- a/Boop/Boop/BoopRelease.entitlements +++ b/Boop/Boop/BoopRelease.entitlements @@ -10,5 +10,7 @@ com.apple.security.network.client + com.apple.security.files.user-selected.read-write + diff --git a/Boop/Boop/Controllers/MainViewController.swift b/Boop/Boop/Controllers/MainViewController.swift index 762b7f49..48cb72dc 100644 --- a/Boop/Boop/Controllers/MainViewController.swift +++ b/Boop/Boop/Controllers/MainViewController.swift @@ -10,7 +10,8 @@ import Cocoa import SavannaKit class MainViewController: NSViewController { - + + @IBOutlet weak var statusView: StatusView! @IBOutlet weak var editorView: SyntaxTextView! @IBOutlet weak var updateBuddy: UpdateBuddy! @IBOutlet weak var checkUpdateMenuItem: NSMenuItem! @@ -67,6 +68,54 @@ class MainViewController: NSViewController { @IBAction func checkForUpdates(_ sender: Any) { updateBuddy.check() } + + @IBAction func openFile(sender: AnyObject) { + + let dialog = NSOpenPanel(); + + dialog.title = "Choose a file"; + dialog.showsResizeIndicator = true; + dialog.showsHiddenFiles = false; + dialog.canChooseDirectories = false; + dialog.canCreateDirectories = false; + dialog.allowsMultipleSelection = false; + + if (dialog.runModal() == NSApplication.ModalResponse.OK) { + if let pathUrl = dialog.url { // Pathname of the file + let text=try? String(contentsOf: pathUrl) + + if text == nil { + self.statusView.setStatus(.error("Failed to load file: '\(pathUrl.path)'.")) + } else { + editorView.text = text! + } + } + } + } + + @IBAction func saveFileAs(sender: AnyObject) { + + let dialog = NSSavePanel(); + + dialog.title = "Save content as…"; + dialog.showsResizeIndicator = true; + dialog.showsHiddenFiles = false; + dialog.showsTagField = false; + dialog.canCreateDirectories = true; + dialog.nameFieldStringValue = "Untitled.txt" + + if (dialog.runModal() == NSApplication.ModalResponse.OK) { + if let pathUrl = dialog.url { // Pathname of the file + let textView = editorView.contentTextView + let textData=textView.textStorage?.string.data(using: .utf8) + do { + try textData?.write(to: pathUrl) + } catch let error as NSError { + self.statusView.setStatus(.error("Failed to save content to file '\(pathUrl.path)'. (Reason: \(error.localizedFailureReason!))")) + } + } + } + } } extension MainViewController: SyntaxTextViewDelegate { diff --git a/Boop/Boop/Info.plist b/Boop/Boop/Info.plist index 5753c31a..82199edc 100644 --- a/Boop/Boop/Info.plist +++ b/Boop/Boop/Info.plist @@ -28,6 +28,17 @@ MainMenu NSPrincipalClass NSApplication + CFBundleDocumentTypes + + + CFBundleTypeRole + Viewer + CFBundleTypeExtensions + + * + + + NSServices diff --git a/Boop/Boop/System/Models/Script.swift b/Boop/Boop/System/Models/Script.swift index eaa3b1ba..8d00f492 100644 --- a/Boop/Boop/System/Models/Script.swift +++ b/Boop/Boop/System/Models/Script.swift @@ -97,7 +97,7 @@ extension Script: Fuseable { } } -protocol ScriptDelegate: class { +protocol ScriptDelegate: AnyObject { func onScriptError(message: String) func onScriptInfo(message: String) } diff --git a/Boop/UI/Base.lproj/MainMenu.xib b/Boop/UI/Base.lproj/MainMenu.xib index f132c070..20005497 100644 --- a/Boop/UI/Base.lproj/MainMenu.xib +++ b/Boop/UI/Base.lproj/MainMenu.xib @@ -1,8 +1,8 @@ - + - + @@ -27,6 +27,7 @@ + @@ -58,6 +59,7 @@ + @@ -123,14 +125,9 @@ - - - - - - - - - - - -