diff --git a/AVRsack.xcodeproj/project.pbxproj b/AVRsack.xcodeproj/project.pbxproj index 3fe0bdc..3bc172e 100644 --- a/AVRsack.xcodeproj/project.pbxproj +++ b/AVRsack.xcodeproj/project.pbxproj @@ -22,6 +22,7 @@ 95A7C6401A38914300EF1963 /* ASPreferences.xib in Resources */ = {isa = PBXBuildFile; fileRef = 95A7C63E1A38914300EF1963 /* ASPreferences.xib */; }; 95A7C6461A3894C900EF1963 /* ASPreferences.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95A7C6451A3894C900EF1963 /* ASPreferences.swift */; }; 95BF80EB1A185C9E0004A693 /* ASFileTree.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95BF80EA1A185C9E0004A693 /* ASFileTree.swift */; }; + 95DF20671A45A6090013D1B5 /* ASSketchBook.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95DF20661A45A6090013D1B5 /* ASSketchBook.swift */; }; 95EA32621A17B90600F66EB0 /* ACEView.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 95EA325B1A17B8DA00F66EB0 /* ACEView.framework */; }; 95EA32651A17BA8C00F66EB0 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 95EA32631A17BA8C00F66EB0 /* Cocoa.framework */; }; /* End PBXBuildFile section */ @@ -86,6 +87,7 @@ 95A7C63F1A38914300EF1963 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/ASPreferences.xib; sourceTree = ""; }; 95A7C6451A3894C900EF1963 /* ASPreferences.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ASPreferences.swift; sourceTree = ""; }; 95BF80EA1A185C9E0004A693 /* ASFileTree.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ASFileTree.swift; sourceTree = ""; }; + 95DF20661A45A6090013D1B5 /* ASSketchBook.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ASSketchBook.swift; sourceTree = ""; }; 95EA32541A17B8DA00F66EB0 /* ACEView.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = ACEView.xcodeproj; path = ../ACEView/ACEView.xcodeproj; sourceTree = ""; }; 95EA32631A17BA8C00F66EB0 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; }; 95EA32641A17BA8C00F66EB0 /* WebKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebKit.framework; path = System/Library/Frameworks/WebKit.framework; sourceTree = SDKROOT; }; @@ -179,6 +181,7 @@ 951CD1761A2615000066C1A1 /* BuildProject */, 95539B661A3E7EAF00D8595C /* ASSerial.h */, 95539B671A3E7EAF00D8595C /* ASSerial.mm */, + 95DF20661A45A6090013D1B5 /* ASSketchBook.swift */, ); name = Source; sourceTree = ""; @@ -356,6 +359,7 @@ 951CD1741A23C9FC0066C1A1 /* ASBuilder.swift in Sources */, 9501D8021A17025C0034C530 /* ASApplication.swift in Sources */, 95BF80EB1A185C9E0004A693 /* ASFileTree.swift in Sources */, + 95DF20671A45A6090013D1B5 /* ASSketchBook.swift in Sources */, 95A7C6461A3894C900EF1963 /* ASPreferences.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/AVRsack/ASApplication.swift b/AVRsack/ASApplication.swift index ba80cae..b89f6be 100644 --- a/AVRsack/ASApplication.swift +++ b/AVRsack/ASApplication.swift @@ -9,10 +9,12 @@ import Cocoa @NSApplicationMain -class ASApplication: NSObject, NSApplicationDelegate { +class ASApplication: NSObject, NSApplicationDelegate, NSMenuDelegate { @IBOutlet weak var themeMenu : NSMenu! @IBOutlet weak var keyboardMenu : NSMenu! @IBOutlet weak var preferences : ASPreferences! + var sketches = [String]() + var examples = [String]() func applicationWillFinishLaunching(notification: NSNotification) { // @@ -59,5 +61,42 @@ class ASApplication: NSObject, NSApplicationDelegate { func applicationWillTerminate(aNotification: NSNotification) { // Insert code here to tear down your application } + + func menuNeedsUpdate(menu: NSMenu) { + switch menu.title { + case "Sketchbook": + menu.removeAllItems() + sketches = [String]() + for sketchBook in NSUserDefaults.standardUserDefaults().objectForKey("Sketchbooks") as [NSString] { + if NSFileManager.defaultManager().fileExistsAtPath(sketchBook) { + ASSketchBook.addSketches(menu, target: self, action: "openSketch:", path: sketchBook, sketches: &sketches) + } + } + case "Examples": + menu.removeAllItems() + examples = [String]() + if let arduinoPath = NSWorkspace.sharedWorkspace().URLForApplicationWithBundleIdentifier("cc.arduino.Arduino")?.path { + let examplePath = arduinoPath.stringByAppendingPathComponent("Contents/Resources/Java/examples") + ASSketchBook.addSketches(menu, target: self, action: "openExample:", path: examplePath, sketches: &examples) + } + + default: + break + } + } + + @IBAction func openSketch(item: NSMenuItem) { + let url = NSURL(fileURLWithPath: sketches[item.tag])! + let doc = NSDocumentController.sharedDocumentController() as NSDocumentController + doc.openDocumentWithContentsOfURL(url, display: true) { (doc, alreadyOpen, error) -> Void in + } + } + + @IBAction func openExample(item: NSMenuItem) { + let url = NSURL(fileURLWithPath: examples[item.tag])! + let doc = NSDocumentController.sharedDocumentController() as NSDocumentController + doc.openDocumentWithContentsOfURL(url, display: true) { (doc, alreadyOpen, error) -> Void in + } + } } diff --git a/AVRsack/ASSketchBook.swift b/AVRsack/ASSketchBook.swift new file mode 100644 index 0000000..b823800 --- /dev/null +++ b/AVRsack/ASSketchBook.swift @@ -0,0 +1,93 @@ +// +// ASSketchBook.swift +// AVRsack +// +// Created by Matthias Neeracher on 12/20/14. +// Copyright © 2014 Aere Perennius. All rights reserved. +// + +import Foundation + +class ASSketchBook { + enum SketchBookItem { + case Nothing + case Sketch(String, String) + case SketchDir(String, [SketchBookItem]) + } + + private class func enumerateSketches(path: NSString) -> SketchBookItem { + let fileManager = NSFileManager.defaultManager() + let contents = fileManager.contentsOfDirectoryAtPath(path, error: nil) as [String] + for item in contents { + switch item.pathExtension { + case "ino", "avrsackproj": + return .Sketch(path.lastPathComponent, path.stringByAppendingPathComponent(item)) + default: + break + } + } + var sketches = [SketchBookItem]() + for item in contents { + let subpath = path.stringByAppendingPathComponent(item) + var isDir : ObjCBool = false + if fileManager.fileExistsAtPath(subpath, isDirectory: &isDir) && isDir { + let subEnum = enumerateSketches(subpath) + switch subEnum { + case .Nothing: + break + default: + sketches.append(subEnum) + } + } + } + sketches.sort({ (a: SketchBookItem, b: SketchBookItem) -> Bool in + var itemA : String = "" + switch a { + case .Sketch(let item, _): + itemA = item + case .SketchDir(let item, _): + itemA = item + default: + break + } + switch b { + case .Sketch(let item, _): + return itemA < item + case .SketchDir(let item, _): + return itemA < item + default: + return itemA < "" + } + }) + return sketches.count > 0 ? .SketchDir(path.lastPathComponent, sketches) : .Nothing + } + + class func appendSketchesToMenu(menu: NSMenu, target: AnyObject, action: Selector, sketchList: [SketchBookItem], inout sketches: [String]) { + for sketch in sketchList { + switch (sketch) { + case .Sketch(let item, let path): + let menuItem = menu.addItemWithTitle(item, action: action, keyEquivalent: "") + menuItem?.target = target + menuItem?.tag = sketches.count + sketches.append(path) + case .SketchDir(let item, let subSketches): + let menuItem = menu.addItemWithTitle(item, action: nil, keyEquivalent: "") + let submenu = NSMenu() + submenu.autoenablesItems = false + appendSketchesToMenu(submenu, target: target, action: action, sketchList: subSketches, sketches: &sketches) + menu.setSubmenu(submenu, forItem: menuItem!) + default: + break + } + } + } + + class func addSketches(menu: NSMenu, target: AnyObject, action: Selector, path: NSString, inout sketches: [String]) { + switch enumerateSketches(path) { + case .SketchDir(let item, let sketchList): + appendSketchesToMenu(menu, target: target, action: action, sketchList: sketchList, sketches: &sketches) + default: + break + } + } +} \ No newline at end of file diff --git a/AVRsack/Base.lproj/MainMenu.xib b/AVRsack/Base.lproj/MainMenu.xib index c717916..01f411f 100644 --- a/AVRsack/Base.lproj/MainMenu.xib +++ b/AVRsack/Base.lproj/MainMenu.xib @@ -98,6 +98,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + +