diff --git a/AVRsack/ASProjDoc.swift b/AVRsack/ASProjDoc.swift index c93b43f..fb6a9eb 100644 --- a/AVRsack/ASProjDoc.swift +++ b/AVRsack/ASProjDoc.swift @@ -39,6 +39,7 @@ class ASProjDoc: NSDocument, NSOutlineViewDelegate, NSMenuDelegate { var currentTheme : UInt = 0 var fontSize : UInt = 12 var themeObserver : AnyObject? + var serialObserver : AnyObject? var board = "uno" var programmer = "arduino" dynamic var port : String = "" { @@ -85,22 +86,28 @@ class ASProjDoc: NSDocument, NSOutlineViewDelegate, NSMenuDelegate { } } } + fontSize = UInt(userDefaults.integerForKey(kFontSizeKey)) - themeObserver = NSNotificationCenter.defaultCenter().addObserverForName(kBindingsKey, object: nil, queue: nil, usingBlock: { (NSNotification) in - self.editor.setKeyboardHandler(keyboardHandler) - }) board = userDefaults.stringForKey(kBoardKey)! programmer = userDefaults.stringForKey(kProgrammerKey)! port = userDefaults.stringForKey(kPortKey)! recentBoards = userDefaults.objectForKey(kRecentBoardsKey) as [String] recentProgrammers = userDefaults.objectForKey(kRecentProgrammersKey) as [String] + var nc = NSNotificationCenter.defaultCenter() + themeObserver = nc.addObserverForName(kBindingsKey, object: nil, queue: nil, usingBlock: { (NSNotification) in + self.editor.setKeyboardHandler(keyboardHandler) + }) + serialObserver = nc.addObserverForName(kASSerialPortsChanged, object: nil, queue: nil, usingBlock: { (NSNotification) in + self.rebuildPortMenu() + }) updateLogTimer = NSTimer.scheduledTimerWithTimeInterval(1.0, target: self, selector: "updateLog:", userInfo: nil, repeats: true) } override func finalize() { saveCurEditor() NSNotificationCenter.defaultCenter().removeObserver(themeObserver!) + NSNotificationCenter.defaultCenter().removeObserver(serialObserver!) } override func windowControllerDidLoadNib(aController: NSWindowController) { @@ -120,10 +127,7 @@ class ASProjDoc: NSDocument, NSOutlineViewDelegate, NSMenuDelegate { outlineViewSelectionDidChange(NSNotification(name: "", object: nil)) menuNeedsUpdate(boardTool.menu!) menuNeedsUpdate(progTool.menu!) - portTool.removeAllItems() - portTool.addItemWithTitle("Title") - portTool.addItemsWithTitles(ASSerial.ports()) - portTool.setTitle(port) + rebuildPortMenu() updateChangeCount(.ChangeCleared) } @@ -348,6 +352,15 @@ class ASProjDoc: NSDocument, NSOutlineViewDelegate, NSMenuDelegate { selectNodeInOutline(files.buildLog) } + func rebuildPortMenu() { + willChangeValueForKey("hasValidPort") + portTool.removeAllItems() + portTool.addItemWithTitle("Title") + portTool.addItemsWithTitles(ASSerial.instance().ports()) + portTool.setTitle(port) + didChangeValueForKey("hasValidPort") + } + func menuNeedsUpdate(menu: NSMenu) { switch menu.title { case "Boards": @@ -442,13 +455,19 @@ class ASProjDoc: NSDocument, NSOutlineViewDelegate, NSMenuDelegate { return NSSet(object: "board") } + var hasValidPort : Bool { + get { + return (ASSerial.instance().ports() as NSArray).containsObject(port) + } + } + var canUpload : Bool { get { - return port != "" && (hasUploadProtocol || programmer != "") + return hasValidPort && (hasUploadProtocol || programmer != "") } } class func keyPathsForValuesAffectingCanUpload() -> NSSet { - return NSSet(objects: "port", "board", "programmer") + return NSSet(objects: "hasValidPort", "hasUploadProtocol", "programmer") } @IBAction func uploadProject(sender: AnyObject) { diff --git a/AVRsack/ASSerial.swift b/AVRsack/ASSerial.swift index ffd9d8a..feef296 100644 --- a/AVRsack/ASSerial.swift +++ b/AVRsack/ASSerial.swift @@ -8,8 +8,27 @@ import Foundation +let kASSerialPortsChanged = "PortsChanged" + +class ASSerialWatcher { +} + +private let serialInstance = ASSerial() + class ASSerial { - class func ports() -> [String] { + class func instance() -> ASSerial { return serialInstance } + + let watchSlashDev : dispatch_source_t + init() { + let fd = open("/dev", O_EVTONLY) + watchSlashDev = dispatch_source_create(DISPATCH_SOURCE_TYPE_VNODE, UInt(fd), DISPATCH_VNODE_WRITE, dispatch_get_main_queue()) + dispatch_source_set_event_handler(watchSlashDev) { () -> Void in + NSNotificationCenter.defaultCenter().postNotificationName(kASSerialPortsChanged, object: nil) + } + dispatch_resume(watchSlashDev) + } + + func ports() -> [String] { let devices = NSFileManager.defaultManager().contentsOfDirectoryAtPath("/dev", error: nil)! var cuDevs = [String]() for dev in devices as [String] { diff --git a/AVRsack/Base.lproj/ASProjDoc.xib b/AVRsack/Base.lproj/ASProjDoc.xib index c504d01..bc6447e 100644 --- a/AVRsack/Base.lproj/ASProjDoc.xib +++ b/AVRsack/Base.lproj/ASProjDoc.xib @@ -183,6 +183,11 @@ + + + NSNegateBoolean + +