From a0dfc98401ed842dadf204cc002724919c6bc10b Mon Sep 17 00:00:00 2001 From: Matthias Neeracher Date: Wed, 31 Dec 2014 04:16:43 +0100 Subject: [PATCH] Handle themes in serial window --- AVRsack.xcodeproj/project.pbxproj | 4 ++ AVRsack/ACEViewExt.swift | 29 ++++++++ AVRsack/ASFileTree.swift | 2 +- AVRsack/ASProjDoc.swift | 23 ++---- AVRsack/ASSerialWin.swift | 112 +++++++++++++++++++++++++++++- AVRsack/ASSerialWin.xib | 5 +- AVRsack/Defaults.plist | 6 +- 7 files changed, 159 insertions(+), 22 deletions(-) create mode 100644 AVRsack/ACEViewExt.swift diff --git a/AVRsack.xcodeproj/project.pbxproj b/AVRsack.xcodeproj/project.pbxproj index 78c601a..8388fc9 100644 --- a/AVRsack.xcodeproj/project.pbxproj +++ b/AVRsack.xcodeproj/project.pbxproj @@ -24,6 +24,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 */; }; + 95DA9B161A515AF700DE018D /* ACEViewExt.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95DA9B151A515AF700DE018D /* ACEViewExt.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 */; }; @@ -91,6 +92,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 = ""; }; + 95DA9B151A515AF700DE018D /* ACEViewExt.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ACEViewExt.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; }; @@ -187,6 +189,7 @@ 95539B671A3E7EAF00D8595C /* ASSerial.mm */, 95DF20661A45A6090013D1B5 /* ASSketchBook.swift */, 956005F21A4EF79D00327007 /* ASSerialWin.swift */, + 95DA9B151A515AF700DE018D /* ACEViewExt.swift */, ); name = Source; sourceTree = ""; @@ -364,6 +367,7 @@ 9501D8041A17025C0034C530 /* ASProjDoc.swift in Sources */, 95539B681A3E7EAF00D8595C /* ASSerial.mm in Sources */, 95468DDF1A228BE600668EE2 /* ASHardware.swift in Sources */, + 95DA9B161A515AF700DE018D /* ACEViewExt.swift in Sources */, 951CD1741A23C9FC0066C1A1 /* ASBuilder.swift in Sources */, 9501D8021A17025C0034C530 /* ASApplication.swift in Sources */, 95BF80EB1A185C9E0004A693 /* ASFileTree.swift in Sources */, diff --git a/AVRsack/ACEViewExt.swift b/AVRsack/ACEViewExt.swift new file mode 100644 index 0000000..db38318 --- /dev/null +++ b/AVRsack/ACEViewExt.swift @@ -0,0 +1,29 @@ +// +// ACEViewExt.swift +// AVRsack +// +// Created by Matthias Neeracher on 29/12/14. +// Copyright (c) 2014 Aere Perennius. All rights reserved. +// + +import Foundation + +extension ACEView { + class func themeIdByName(themeName: String) -> UInt? { + for (themeIdx, theme) in enumerate(ACEThemeNames.themeNames() as [NSString]) { + if themeName == theme { + return UInt(themeIdx) + } + } + return nil + } + + class func handlerIdByName(handlerName: String) -> ACEKeyboardHandler? { + for (handlerIdx, handler) in enumerate(ACEKeyboardHandlerNames.humanKeyboardHandlerNames() as [NSString]) { + if handlerName == handler { + return ACEKeyboardHandler(rawValue: UInt(handlerIdx))! + } + } + return nil + } +} \ No newline at end of file diff --git a/AVRsack/ASFileTree.swift b/AVRsack/ASFileTree.swift index b68d6c5..2651874 100644 --- a/AVRsack/ASFileTree.swift +++ b/AVRsack/ASFileTree.swift @@ -43,7 +43,7 @@ enum ASFileType : String { case .Markdown: return ACEModeMarkdown default: - return ACEModeASCIIDoc + return ACEModeText } } } diff --git a/AVRsack/ASProjDoc.swift b/AVRsack/ASProjDoc.swift index 42360c7..fd2ed95 100644 --- a/AVRsack/ASProjDoc.swift +++ b/AVRsack/ASProjDoc.swift @@ -67,19 +67,13 @@ class ASProjDoc: NSDocument, NSOutlineViewDelegate, NSMenuDelegate { 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 themeId = ACEView.themeIdByName(themeName) { + currentTheme = themeId } } if let handlerName = userDefaults.stringForKey(kBindingsKey) { - for (handlerIdx, handler) in enumerate(ACEKeyboardHandlerNames.humanKeyboardHandlerNames() as [NSString]) { - if handlerName == handler { - keyboardHandler = ACEKeyboardHandler(rawValue: UInt(handlerIdx))! - break - } + if let handlerId = ACEView.handlerIdByName(handlerName) { + keyboardHandler = handlerId } } @@ -199,11 +193,8 @@ class ASProjDoc: NSDocument, NSOutlineViewDelegate, NSMenuDelegate { 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 themeId = ACEView.themeIdByName(themeName) { + currentTheme = themeId } } if let fontSz = projectData[kFontSizeKey] as? Int { @@ -257,7 +248,7 @@ class ASProjDoc: NSDocument, NSOutlineViewDelegate, NSMenuDelegate { mainEditor = selection } else if let log = (selection as? ASLogNode) { editor.setString("") - editor.setMode(UInt(ACEModeASCIIDoc)) + editor.setMode(UInt(ACEModeText)) editor.alphaValue = 0.8 logModified = NSDate.distantPast() as NSDate logSize = -1 diff --git a/AVRsack/ASSerialWin.swift b/AVRsack/ASSerialWin.swift index 3a1e4af..176fcc9 100644 --- a/AVRsack/ASSerialWin.swift +++ b/AVRsack/ASSerialWin.swift @@ -8,7 +8,8 @@ import Cocoa -private var serialInstances = [String : ASSerialWin]() +private var serialInstances = [String : ASSerialWin]() +private var keyboardHandler : ACEKeyboardHandler = .Ace class ASSerialWin: NSWindowController { @IBOutlet weak var portPopUp : NSPopUpButton! @@ -25,10 +26,20 @@ class ASSerialWin: NSWindowController { } var sendCR = false var sendLF = true + var scrollToBottom : Bool = true { + didSet(oldScroll) { + if scrollToBottom { + logView.gotoLine(1000000000, column: 0, animated: true) + } + } + } var port = "" var serialData = "" var serialObserver : AnyObject! dynamic var portHandle : NSFileHandle? + var currentTheme : UInt = 0 + var fontSize : UInt = 12 + var portDefaults = [String: AnyObject]() class func showWindowWithPort(port: String) { if let existing = serialInstances[port] { @@ -40,14 +51,48 @@ class ASSerialWin: NSWindowController { } } - convenience init(port: String) { - self.init(windowNibName:"ASSerialWin") + init(port: String) { + super.init() self.port = port + + let userDefaults = NSUserDefaults.standardUserDefaults() + + if let portDef = (userDefaults.objectForKey("SerialDefaults") as NSDictionary).objectForKey(port) as? [String: AnyObject] { + portDefaults = portDef + } else { + portDefaults["Theme"] = userDefaults.stringForKey("SerialTheme") + portDefaults["FontSize"] = userDefaults.objectForKey("FontSize") + portDefaults["SendCR"] = sendCR + portDefaults["SendLF"] = sendLF + } + if let themeId = ACEView.themeIdByName(portDefaults["Theme"] as String) { + currentTheme = themeId + } + fontSize = portDefaults["FontSize"] as UInt + sendCR = portDefaults["SendCR"] as Bool + sendLF = portDefaults["SendLF"] as Bool + + if let handlerName = userDefaults.stringForKey("Bindings") { + if let handlerId = ACEView.handlerIdByName(handlerName) { + keyboardHandler = handlerId + } + } + var nc = NSNotificationCenter.defaultCenter() serialObserver = nc.addObserverForName(kASSerialPortsChanged, object: nil, queue: nil, usingBlock: { (NSNotification) in self.rebuildPortMenu() }) } + + func windowNibName() -> String { + return "ASSerialWin" + } + required override init(window: NSWindow!) { + super.init(window:window) + } + required init?(coder: NSCoder) { + super.init(coder:coder) + } override func finalize() { NSNotificationCenter.defaultCenter().removeObserver(serialObserver) @@ -57,6 +102,11 @@ class ASSerialWin: NSWindowController { override func windowDidLoad() { logView.setReadOnly(true) logView.setShowPrintMargin(false) + logView.setTheme(currentTheme) + logView.setKeyboardHandler(keyboardHandler) + logView.setFontSize(fontSize) + logView.setMode(UInt(ACEModeText)) + logView.alphaValue = 0.8 rebuildPortMenu() window?.title = port connect(self) @@ -96,6 +146,9 @@ class ASSerialWin: NSWindowController { self.serialData += newString dispatch_async(dispatch_get_main_queue(), { () -> Void in self.logView.setString(self.serialData) + if self.scrollToBottom { + self.logView.gotoLine(1000000000, column: 0, animated: true) + } }) } } @@ -110,4 +163,57 @@ class ASSerialWin: NSWindowController { class func keyPathsForValuesAffectingConnectButtonTitle() -> NSSet { return NSSet(object: "portHandle") } + + // MARK: Editor configuration + + @IBAction func changeTheme(item: NSMenuItem) { + let userDefaults = NSUserDefaults.standardUserDefaults() + currentTheme = UInt(item.tag) + logView.setTheme(currentTheme) + let themeName = ACEThemeNames.humanNameForTheme(currentTheme) + userDefaults.setObject(themeName, forKey: "SerialTheme") + portDefaults["Theme"] = themeName + updatePortDefaults() + } + @IBAction func changeKeyboardHandler(item: NSMenuItem) { + keyboardHandler = ACEKeyboardHandler(rawValue: UInt(item.tag))! + NSUserDefaults.standardUserDefaults().setObject( + ACEKeyboardHandlerNames.humanNameForKeyboardHandler(keyboardHandler), forKey: "Bindings") + NSNotificationCenter.defaultCenter().postNotificationName("Bindings", object: item) + } + + func validateUserInterfaceItem(anItem: NSValidatedUserInterfaceItem) -> Bool { + if let menuItem = anItem as? NSMenuItem { + 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 true + } + + @IBAction func makeTextLarger(AnyObject) { + fontSize += 1 + logView.setFontSize(fontSize) + portDefaults["FontSize"] = fontSize + updatePortDefaults() + } + @IBAction func makeTextSmaller(AnyObject) { + if fontSize > 6 { + fontSize -= 1 + logView.setFontSize(fontSize) + portDefaults["FontSize"] = fontSize + updatePortDefaults() + } + } + + func updatePortDefaults() { + let userDefaults = NSUserDefaults.standardUserDefaults() + let serialDefaults = userDefaults.objectForKey("SerialDefaults") as NSDictionary + serialDefaults.setValue(portDefaults, forKey:port) + userDefaults.setObject(serialDefaults, forKey:"SerialDefaults") + } } diff --git a/AVRsack/ASSerialWin.xib b/AVRsack/ASSerialWin.xib index 591a06c..555426c 100644 --- a/AVRsack/ASSerialWin.xib +++ b/AVRsack/ASSerialWin.xib @@ -68,9 +68,12 @@ - + + + +