AVRSack/AVRsack/ASApplication.swift

226 lines
9.2 KiB
Swift
Raw Normal View History

2014-11-15 03:39:10 +00:00
//
// AppDelegate.swift
// AVRsack
//
// Created by Matthias Neeracher on 11/15/14.
2015-07-10 22:48:39 +00:00
// Copyright (c) 2014-2015 Aere Perennius. All rights reserved.
2014-11-15 03:39:10 +00:00
//
import Cocoa
2015-07-10 22:48:39 +00:00
import Carbon
2014-11-15 03:39:10 +00:00
@NSApplicationMain
2014-12-21 03:05:51 +00:00
class ASApplication: NSObject, NSApplicationDelegate, NSMenuDelegate {
2014-12-31 09:03:30 +00:00
@IBOutlet var themeMenu : NSMenu!
@IBOutlet var keyboardMenu : NSMenu!
@IBOutlet var preferences : ASPreferences!
2014-12-21 03:05:51 +00:00
var sketches = [String]()
var examples = [String]()
2014-12-31 09:03:30 +00:00
func hasDocument() -> Bool {
2016-11-13 11:03:51 +00:00
return NSDocumentController.shared().currentDocument != nil
2014-12-31 09:03:30 +00:00
}
2016-11-13 11:03:51 +00:00
func applicationWillFinishLaunching(_ notification: Notification) {
//
// Retrieve static app defaults
//
2016-11-13 11:03:51 +00:00
let fileManager = FileManager.default
let workSpace = NSWorkspace.shared()
let userDefaults = UserDefaults.standard
let appDefaultsURL = Bundle.main.url(forResource: "Defaults", withExtension: "plist")!
2016-11-21 19:33:02 +00:00
var appDefaults = NSDictionary(contentsOf: appDefaultsURL) as! [String: Any]
//
// Add dynamic app defaults
//
2016-11-13 11:03:51 +00:00
if let arduinoPath = workSpace.urlForApplication(withBundleIdentifier: "cc.arduino.Arduino")?.path {
appDefaults["Arduino"] = arduinoPath
}
2016-11-21 19:33:02 +00:00
var sketchbooks = [String]()
2016-11-13 11:03:51 +00:00
for doc in fileManager.urls(for: .documentDirectory, in: .userDomainMask) {
2016-11-14 00:37:13 +00:00
sketchbooks.append(doc.appendingPathComponent("Arduino").path)
sketchbooks.append(doc.appendingPathComponent("AVRSack").path)
}
appDefaults["Sketchbooks"] = sketchbooks
2016-11-13 11:03:51 +00:00
if fileManager.fileExists(atPath: "/usr/local/CrossPack-AVR") {
appDefaults["Toolchain"] = "/usr/local/CrossPack-AVR"
} else {
appDefaults["Toolchain"] = ""
}
2016-11-13 11:03:51 +00:00
userDefaults.register(defaults: appDefaults)
}
2014-11-15 03:39:10 +00:00
func applicationDidFinishLaunching(aNotification: NSNotification) {
themeMenu.removeAllItems()
2016-11-13 11:03:51 +00:00
for (index, theme) in ACEThemeNames.humanThemeNames().enumerated() {
let menuItem = themeMenu.addItem(withTitle: theme, action: Selector(("changeTheme:")), keyEquivalent: "")
2015-03-17 23:17:55 +00:00
menuItem.tag = index
}
keyboardMenu.removeAllItems()
2016-11-13 11:03:51 +00:00
for (index, theme) in ACEKeyboardHandlerNames.humanKeyboardHandlerNames().enumerated() {
let menuItem = keyboardMenu.addItem(withTitle: theme, action: Selector(("changeKeyboardHandler:")), keyEquivalent: "")
2015-03-17 23:17:55 +00:00
menuItem.tag = index
}
2014-11-15 03:39:10 +00:00
}
2016-11-13 11:03:51 +00:00
func applicationShouldOpenUntitledFile(_ sender: NSApplication) -> Bool {
2014-12-27 01:21:25 +00:00
return false
}
2014-11-15 03:39:10 +00:00
func applicationWillTerminate(aNotification: NSNotification) {
}
2014-12-21 03:05:51 +00:00
2016-11-13 11:03:51 +00:00
func menuNeedsUpdate(_ menu: NSMenu) {
2014-12-21 03:05:51 +00:00
switch menu.title {
case "Sketchbook":
menu.removeAllItems()
sketches = [String]()
2016-11-13 11:03:51 +00:00
for sketchBook in UserDefaults.standard.object(forKey:"Sketchbooks") as! [String] {
if FileManager.default.fileExists(atPath: sketchBook) {
2016-11-14 00:58:22 +00:00
ASSketchBook.addSketches(menu: menu, target: self, action: #selector(ASApplication.openSketch(_:)), path: sketchBook, sketches: &sketches)
2014-12-21 03:05:51 +00:00
}
}
case "Examples":
menu.removeAllItems()
examples = [String]()
2016-11-13 11:03:51 +00:00
if let arduinoURL = NSWorkspace.shared().urlForApplication(withBundleIdentifier: "cc.arduino.Arduino") {
2016-11-14 00:37:13 +00:00
let examplePath = arduinoURL.appendingPathComponent("Contents/Resources/Java/examples", isDirectory:true).path
2016-11-14 00:58:22 +00:00
ASSketchBook.addSketches(menu: menu, target: self, action: #selector(ASApplication.openExample(_:)), path: examplePath, sketches: &examples)
2014-12-21 03:05:51 +00:00
}
2015-03-23 02:17:57 +00:00
case "Import Standard Library":
menu.removeAllItems()
2016-11-13 11:03:51 +00:00
ASLibraries.instance().addStandardLibrariesToMenu(menu: menu)
2015-03-23 02:17:57 +00:00
case "Import Contributed Library":
menu.removeAllItems()
2016-11-13 11:03:51 +00:00
ASLibraries.instance().addContribLibrariesToMenu(menu: menu)
2014-12-31 09:03:30 +00:00
case "Serial Monitor":
2016-11-13 11:03:51 +00:00
menu.item(at: 0)?.isHidden = !hasDocument()
2014-12-31 09:03:30 +00:00
while menu.numberOfItems > 2 {
2016-11-13 11:03:51 +00:00
menu.removeItem(at: 2)
2014-12-31 09:03:30 +00:00
}
2015-11-16 01:56:33 +00:00
for port in ASSerial.ports() {
2016-11-14 00:58:22 +00:00
menu.addItem(withTitle: port, action:#selector(ASApplication.serialConnectMenu(_:)), keyEquivalent:"")
2014-12-31 09:03:30 +00:00
}
2014-12-21 03:05:51 +00:00
default:
break
}
}
2014-12-31 09:03:30 +00:00
2016-11-14 00:58:22 +00:00
@IBAction func serialConnectMenu(_ port: NSMenuItem) {
2016-11-13 11:03:51 +00:00
ASSerialWin.showWindowWithPort(port: port.title)
2014-12-31 09:03:30 +00:00
}
2016-11-14 00:37:13 +00:00
func openTemplate(template: URL, fromReadOnly: Bool) {
let editable : String
if fromReadOnly {
editable = "editable "
} else {
editable = ""
}
2016-11-13 11:03:51 +00:00
ASApplication.newProjectLocation(documentWindow: nil,
2016-11-14 00:37:13 +00:00
message: "Save \(editable)copy of project \(template.lastPathComponent)")
2014-12-27 01:21:25 +00:00
{ (saveTo) -> Void in
2016-11-14 00:37:13 +00:00
let oldName = template.lastPathComponent
let newName = saveTo.lastPathComponent
2016-11-13 11:03:51 +00:00
let fileManager = FileManager.default
2015-11-16 01:56:33 +00:00
do {
2016-11-14 00:37:13 +00:00
try fileManager.copyItem(at: template, to: saveTo)
let contents = fileManager.enumerator(at: saveTo,
2016-11-13 11:03:51 +00:00
includingPropertiesForKeys: [URLResourceKey.nameKey, URLResourceKey.pathKey],
2016-11-14 00:37:13 +00:00
options: .skipsHiddenFiles, errorHandler: nil)
while let item = contents?.nextObject() as? URL {
let itemBase = item.deletingPathExtension().lastPathComponent
2015-11-16 01:56:33 +00:00
if itemBase == oldName {
2016-11-14 00:37:13 +00:00
let newItem = item.deletingLastPathComponent().appendingPathComponent(
newName).appendingPathExtension(item.pathExtension)
try fileManager.moveItem(at: item, to: newItem)
2015-11-16 01:56:33 +00:00
}
2014-12-27 01:21:25 +00:00
}
2015-11-16 01:56:33 +00:00
} catch (_) {
2014-12-27 01:21:25 +00:00
}
2016-11-14 00:37:13 +00:00
let sketch = ASSketchBook.findSketch(path: saveTo.path)
2014-12-27 01:21:25 +00:00
switch sketch {
case .Sketch(_, let path):
2016-11-13 11:03:51 +00:00
let doc = NSDocumentController.shared()
2016-11-14 00:37:13 +00:00
doc.openDocument(withContentsOf: URL(fileURLWithPath: path), display: true) { (doc, alreadyOpen, error) -> Void in
2014-12-27 01:21:25 +00:00
}
default:
break
}
}
}
2016-11-14 00:58:22 +00:00
@IBAction func openSketch(_ item: NSMenuItem) {
2016-11-14 00:37:13 +00:00
let url = URL(fileURLWithPath: sketches[item.tag])
2016-11-13 11:03:51 +00:00
let doc = NSDocumentController.shared()
2016-11-14 00:37:13 +00:00
doc.openDocument(withContentsOf: url, display: true) { (doc, alreadyOpen, error) -> Void in
2014-12-21 03:05:51 +00:00
}
}
2016-11-14 00:58:22 +00:00
@IBAction func openExample(_ item: NSMenuItem) {
2015-11-16 01:56:33 +00:00
let url = NSURL(fileURLWithPath: examples[item.tag])
2016-11-13 11:03:51 +00:00
openTemplate(template: url.deletingLastPathComponent!, fromReadOnly:true)
2014-12-27 01:21:25 +00:00
}
2015-01-12 03:24:29 +00:00
2015-11-16 01:56:33 +00:00
@IBAction func createSketch(_: AnyObject) {
2016-11-13 11:03:51 +00:00
ASApplication.newProjectLocation(documentWindow: nil,
2015-01-12 03:24:29 +00:00
message: "Create Project")
{ (saveTo) -> Void in
2016-11-14 00:37:13 +00:00
let fileManager = FileManager.default
2015-11-16 01:56:33 +00:00
do {
2016-11-14 00:37:13 +00:00
try fileManager.createDirectory(at: saveTo, withIntermediateDirectories:false, attributes:nil)
let proj = saveTo.appendingPathComponent(saveTo.lastPathComponent+".avrsackproj")
2016-11-13 11:03:51 +00:00
let docController = NSDocumentController.shared()
2015-11-16 01:56:33 +00:00
if let doc = try docController.openUntitledDocumentAndDisplay(true) as? ASProjDoc {
doc.fileURL = proj
doc.updateProjectURL()
2016-11-14 00:37:13 +00:00
doc.createFileAtURL(url: saveTo.appendingPathComponent(saveTo.lastPathComponent+".ino"))
try doc.write(to: proj, ofType: "Project", for: .saveAsOperation, originalContentsURL: nil)
2015-11-16 01:56:33 +00:00
}
} catch _ {
2015-01-12 03:24:29 +00:00
}
}
}
2014-12-27 01:21:25 +00:00
2016-11-21 19:33:02 +00:00
class func newProjectLocation(documentWindow: NSWindow?, message: String, completion: @escaping (URL) -> ()) {
2014-12-27 01:21:25 +00:00
let savePanel = NSSavePanel()
2015-11-16 01:56:33 +00:00
savePanel.allowedFileTypes = [kUTTypeFolder as String]
2014-12-27 01:21:25 +00:00
savePanel.message = message
if let window = documentWindow {
2016-11-13 11:03:51 +00:00
savePanel.beginSheetModal(for: window, completionHandler: { (returnCode) -> Void in
2014-12-27 01:21:25 +00:00
if returnCode == NSFileHandlingPanelOKButton {
2016-11-13 11:03:51 +00:00
completion(savePanel.url!)
2014-12-27 01:21:25 +00:00
}
})
} else {
2016-11-13 11:03:51 +00:00
savePanel.begin(completionHandler: { (returnCode) -> Void in
2014-12-27 01:21:25 +00:00
if returnCode == NSFileHandlingPanelOKButton {
2016-11-13 11:03:51 +00:00
completion(savePanel.url!)
2014-12-27 01:21:25 +00:00
}
})
2014-12-21 03:05:51 +00:00
}
}
2015-07-10 22:48:39 +00:00
2016-11-14 00:58:22 +00:00
@IBAction func goToHelpPage(_ sender: AnyObject) {
2016-11-21 19:33:02 +00:00
let helpString: CFString
2016-11-13 11:03:51 +00:00
switch sender.tag {
2015-07-10 22:48:39 +00:00
case 0:
2016-11-21 19:33:02 +00:00
helpString = "license.html" as CFString
2015-07-10 22:48:39 +00:00
default:
abort()
}
2016-11-21 19:33:02 +00:00
let locBookName = Bundle.main.object(forInfoDictionaryKey: "CFBundleHelpBookName") as! CFString
2015-07-10 22:48:39 +00:00
AHGotoPage(locBookName, helpString, nil)
}
2016-11-14 00:58:22 +00:00
@IBAction func goToHelpURL(_ sender: AnyObject) {
2015-07-10 22:48:39 +00:00
let helpString: String
2016-11-13 11:03:51 +00:00
switch sender.tag {
2015-07-10 22:48:39 +00:00
case 0:
helpString = "https://github.com/microtherion/AVRsack/issues"
default:
abort()
}
2016-11-14 00:37:13 +00:00
NSWorkspace.shared().open(URL(string: helpString)!)
2015-07-10 22:48:39 +00:00
}
2014-11-15 03:39:10 +00:00
}