AVRSack/AVRsack/ASProjDoc.swift

247 lines
9.7 KiB
Swift
Raw Normal View History

2014-11-15 03:39:10 +00:00
//
2014-11-15 22:47:46 +00:00
// ASProjDoc.swift
2014-11-15 03:39:10 +00:00
// AVRsack
//
// Created by Matthias Neeracher on 11/15/14.
// Copyright (c) 2014 Aere Perennius. All rights reserved.
//
import Cocoa
private var keyboardHandler : ACEKeyboardHandler = .Ace
2014-11-16 18:39:32 +00:00
class ASProjDoc: NSDocument, NSOutlineViewDelegate {
@IBOutlet weak var editor : ACEView!
@IBOutlet weak var outline : NSOutlineView!
2014-11-28 13:18:53 +00:00
let files = ASFileTree()
let builder = ASBuilder()
2014-11-16 18:39:32 +00:00
var mainEditor : ASFileNode?
var currentTheme : UInt = 0
var fontSize : UInt = 12
var themeObserver : AnyObject?
2014-11-28 13:18:53 +00:00
var board : String = "uno"
var programmer : String = ""
var port : String = ""
2014-11-15 22:47:46 +00:00
let kVersionKey = "Version"
let kCurVersion = 1.0
let kFilesKey = "Files"
let kThemeKey = "Theme"
let kFontSizeKey = "FontSize"
let kBindingsKey = "Bindings"
2014-11-28 13:18:53 +00:00
let kBoardKey = "Board"
let kProgrammerKey = "Programmer"
let kPortKey = "Port"
2014-11-17 01:29:55 +00:00
// MARK: Initialization / Finalization
2014-11-15 03:39:10 +00:00
override init() {
super.init()
let userDefaults = NSUserDefaults.standardUserDefaults()
if let themeName = userDefaults.stringForKey(kThemeKey) {
for (themeIdx, theme) in enumerate(ACEThemeNames.themeNames() as [NSString]) {
if themeName == theme {
currentTheme = UInt(themeIdx)
break
}
}
}
if let handlerName = userDefaults.stringForKey(kBindingsKey) {
for (handlerIdx, handler) in enumerate(ACEKeyboardHandlerNames.humanKeyboardHandlerNames() as [NSString]) {
if handlerName == handler {
keyboardHandler = ACEKeyboardHandler(rawValue: UInt(handlerIdx))!
break
}
}
}
fontSize = UInt(userDefaults.integerForKey(kFontSizeKey))
themeObserver = NSNotificationCenter.defaultCenter().addObserverForName(kBindingsKey, object: nil, queue: nil, usingBlock: { (NSNotification) in
self.editor.setKeyboardHandler(keyboardHandler)
})
2014-11-28 13:18:53 +00:00
board = userDefaults.stringForKey(kBoardKey)!
programmer = userDefaults.stringForKey(kProgrammerKey)!
port = userDefaults.stringForKey(kPortKey)!
2014-11-15 03:39:10 +00:00
}
override func finalize() {
saveCurEditor()
NSNotificationCenter.defaultCenter().removeObserver(themeObserver!)
}
2014-11-15 03:39:10 +00:00
override func windowControllerDidLoadNib(aController: NSWindowController) {
super.windowControllerDidLoadNib(aController)
editor.setShowPrintMargin(false)
editor.setTheme(currentTheme)
editor.setKeyboardHandler(keyboardHandler)
editor.setFontSize(fontSize)
2014-11-16 18:39:32 +00:00
outline.setDataSource(files)
files.apply() { node in
if let group = node as? ASFileGroup {
if group.expanded {
self.outline.expandItem(node)
}
}
}
updateChangeCount(.ChangeCleared)
outlineViewSelectionDidChange(NSNotification(name: "", object: nil))
2014-11-15 03:39:10 +00:00
}
override class func autosavesInPlace() -> Bool {
return true
}
override var windowNibName: String? {
// Returns the nib file name of the document
// If you need to use a subclass of NSWindowController or if your document supports multiple NSWindowControllers, you should remove this property and override -makeWindowControllers instead.
2014-11-15 22:47:46 +00:00
return "ASProjDoc"
2014-11-15 03:39:10 +00:00
}
2014-11-17 01:29:55 +00:00
// MARK: Load / Save
func saveCurEditor() {
if let file = (mainEditor as? ASFileItem) {
editor.string().writeToURL(file.url, atomically: true, encoding: NSUTF8StringEncoding, error: nil)
}
}
2014-11-15 03:39:10 +00:00
override func dataOfType(typeName: String, error outError: NSErrorPointer) -> NSData? {
let data = [kVersionKey: kCurVersion,
kThemeKey: ACEThemeNames.nameForTheme(currentTheme),
kFontSizeKey: fontSize,
kFilesKey: files.propertyList()]
2014-11-17 01:29:55 +00:00
return NSPropertyListSerialization.dataFromPropertyList(data, format: .XMLFormat_v1_0, errorDescription: nil)
2014-11-15 03:39:10 +00:00
}
2014-11-16 18:39:32 +00:00
func importProject(url: NSURL, error outError: NSErrorPointer) -> Bool {
let existingProject = url.URLByAppendingPathComponent(url.lastPathComponent+".avrsackproj")
if existingProject.checkResourceIsReachableAndReturnError(nil) {
fileURL = existingProject
return readFromURL(existingProject, ofType:"Project", error:outError)
}
let filesInProject =
NSFileManager.defaultManager().contentsOfDirectoryAtURL(url, includingPropertiesForKeys: nil,
options: .SkipsHiddenFiles, error: nil)!
for file in filesInProject {
files.addFileURL(file as NSURL)
}
return true
}
override func readFromURL(url: NSURL, ofType typeName: String, error outError: NSErrorPointer) -> Bool {
var success : Bool = false
if typeName == "Arduino Source File" {
let projectURL = url.URLByDeletingPathExtension!.URLByAppendingPathExtension("avrsackproj")
success = importProject(url.URLByDeletingLastPathComponent!, error: outError)
2014-11-17 01:29:55 +00:00
if success {
files.setProjectURL(fileURL!)
2014-11-28 13:18:53 +00:00
builder.setProjectURL(fileURL!)
2014-11-17 01:29:55 +00:00
fileURL = projectURL
success = writeToURL(projectURL, ofType: "Project", forSaveOperation: .SaveAsOperation, originalContentsURL: nil, error: outError)
}
2014-11-16 18:39:32 +00:00
} else {
2014-11-17 01:29:55 +00:00
success = super.readFromURL(url, ofType: typeName, error: outError)
}
2014-11-16 18:39:32 +00:00
return success
}
2014-11-17 01:29:55 +00:00
override func readFromData(data: NSData, ofType typeName: String, error outError: NSErrorPointer) -> Bool {
if typeName != "Project" {
return false
}
files.setProjectURL(fileURL!)
2014-11-28 13:18:53 +00:00
builder.setProjectURL(fileURL!)
2014-11-17 01:29:55 +00:00
let projectData : NSDictionary = NSPropertyListSerialization.propertyListFromData(data, mutabilityOption: .Immutable, format: nil, errorDescription: nil) as NSDictionary
let projectVersion = projectData[kVersionKey] as Double
assert(projectVersion <= floor(kCurVersion+1.0), "Project version too new for this app")
if let themeName = projectData[kThemeKey] as? NSString {
for (themeIdx, theme) in enumerate(ACEThemeNames.themeNames() as [NSString]) {
if themeName == theme {
currentTheme = UInt(themeIdx)
break
}
}
}
if let fontSz = projectData[kFontSizeKey] as? Int {
fontSize = UInt(fontSz)
}
2014-11-17 01:29:55 +00:00
files.readPropertyList(projectData[kFilesKey] as NSDictionary)
updateChangeCount(.ChangeCleared)
2014-11-17 01:29:55 +00:00
return true
}
// MARK: Outline View Delegate
2014-11-16 18:39:32 +00:00
func outlineViewSelectionDidChange(notification: NSNotification) {
let selection = outline.itemAtRow(outline.selectedRow) as ASFileNode?
if selection !== mainEditor {
saveCurEditor()
}
if let file = (selection as? ASFileItem) {
var enc : UInt = 0
editor.setString(NSString(contentsOfURL:file.url, usedEncoding:&enc, error:nil))
editor.setMode(UInt(file.type.aceMode))
editor.alphaValue = 1.0
} else {
editor.alphaValue = 0.0
2014-11-16 18:39:32 +00:00
}
}
func outlineViewItemDidExpand(notification: NSNotification) {
let group = notification.userInfo!["NSObject"] as ASFileGroup
group.expanded = true
updateChangeCount(.ChangeDone)
}
func outlineViewItemDidCollapse(notification: NSNotification) {
let group = notification.userInfo!["NSObject"] as ASFileGroup
group.expanded = false
updateChangeCount(.ChangeDone)
}
// MARK: Editor configuration
2014-11-17 04:53:33 +00:00
@IBAction func changeTheme(item: NSMenuItem) {
currentTheme = UInt(item.tag)
editor.setTheme(currentTheme)
NSUserDefaults.standardUserDefaults().setObject(
ACEThemeNames.humanNameForTheme(currentTheme), forKey: kThemeKey)
updateChangeCount(.ChangeDone)
}
@IBAction func changeKeyboardHandler(item: NSMenuItem) {
keyboardHandler = ACEKeyboardHandler(rawValue: UInt(item.tag))!
NSUserDefaults.standardUserDefaults().setObject(
ACEKeyboardHandlerNames.humanNameForKeyboardHandler(keyboardHandler), forKey: kBindingsKey)
NSNotificationCenter.defaultCenter().postNotificationName(kBindingsKey, object: item)
}
override func validateUserInterfaceItem(anItem: NSValidatedUserInterfaceItem) -> Bool {
if let menuItem = anItem as? NSMenuItem {
2014-11-17 04:53:33 +00:00
if menuItem.action == "changeTheme:" {
menuItem.state = (menuItem.tag == Int(currentTheme) ? NSOnState : NSOffState)
return true
} else if menuItem.action == "changeKeyboardHandler:" {
menuItem.state = (menuItem.tag == Int(keyboardHandler.rawValue) ? NSOnState : NSOffState)
return true
}
}
return super.validateUserInterfaceItem(anItem)
}
@IBAction func makeTextLarger(AnyObject) {
fontSize += 1
editor.setFontSize(fontSize)
updateChangeCount(.ChangeDone)
}
@IBAction func makeTextSmaller(AnyObject) {
if fontSize > 6 {
fontSize -= 1
editor.setFontSize(fontSize)
updateChangeCount(.ChangeDone)
}
2014-11-15 03:39:10 +00:00
}
2014-11-24 13:49:47 +00:00
// MARK: Build / Upload
@IBAction func buildProject(AnyObject) {
2014-11-28 13:18:53 +00:00
builder.buildProject(board, files: files)
2014-11-24 13:49:47 +00:00
}
2014-11-15 03:39:10 +00:00
}