diff --git a/VimR.xcodeproj/project.pbxproj b/VimR.xcodeproj/project.pbxproj index 75f06d19..229ad8ac 100644 --- a/VimR.xcodeproj/project.pbxproj +++ b/VimR.xcodeproj/project.pbxproj @@ -28,6 +28,7 @@ 4B401B161D0454E900D99EDC /* PureLayout.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 4B401B131D0454DC00D99EDC /* PureLayout.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 4B401B1A1D046E0600D99EDC /* NeoVimViewDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B401B191D046E0600D99EDC /* NeoVimViewDelegate.swift */; }; 4B4192181D0C52D700A0BEB2 /* Grid.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B4192171D0C52D700A0BEB2 /* Grid.swift */; }; + 4B4546871D468CEC00A1E27F /* PrefStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B4546861D468CEC00A1E27F /* PrefStore.swift */; }; 4B4FC8E61D3E8739009352C3 /* PrefWindowComponent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B4FC8E51D3E8739009352C3 /* PrefWindowComponent.swift */; }; 4B56F2931D29903F00C1F92E /* SwiftNeoVimTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B56F2921D29903F00C1F92E /* SwiftNeoVimTests.swift */; }; 4B56F2951D29903F00C1F92E /* SwiftNeoVim.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4B2A2BF71D0351810074CE9A /* SwiftNeoVim.framework */; }; @@ -168,6 +169,7 @@ 4B401B131D0454DC00D99EDC /* PureLayout.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = PureLayout.framework; path = Carthage/Build/Mac/PureLayout.framework; sourceTree = SOURCE_ROOT; }; 4B401B191D046E0600D99EDC /* NeoVimViewDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NeoVimViewDelegate.swift; sourceTree = ""; }; 4B4192171D0C52D700A0BEB2 /* Grid.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Grid.swift; sourceTree = ""; }; + 4B4546861D468CEC00A1E27F /* PrefStore.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PrefStore.swift; sourceTree = ""; }; 4B4FC8E51D3E8739009352C3 /* PrefWindowComponent.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PrefWindowComponent.swift; sourceTree = ""; }; 4B56F2901D29903F00C1F92E /* SwiftNeoVimTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SwiftNeoVimTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 4B56F2921D29903F00C1F92E /* SwiftNeoVimTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwiftNeoVimTests.swift; sourceTree = ""; }; @@ -270,6 +272,7 @@ 4B238BED1D3ED55300CBDD98 /* Preferences */ = { isa = PBXGroup; children = ( + 4B4546861D468CEC00A1E27F /* PrefStore.swift */, 4B4FC8E51D3E8739009352C3 /* PrefWindowComponent.swift */, 4B238BEB1D3ED54D00CBDD98 /* AppearancePrefPane.swift */, ); @@ -697,6 +700,7 @@ 4BD3BF971D32B0DB00082605 /* MainWindowManager.swift in Sources */, 4B238BEC1D3ED54D00CBDD98 /* AppearancePrefPane.swift in Sources */, 4BD3BF931D32A95800082605 /* MainWindowComponent.swift in Sources */, + 4B4546871D468CEC00A1E27F /* PrefStore.swift in Sources */, 4B4FC8E61D3E8739009352C3 /* PrefWindowComponent.swift in Sources */, 4BEBA5091CFF374B00673FDF /* AppDelegate.swift in Sources */, 1929B165820D7177743B537A /* Component.swift in Sources */, diff --git a/VimR/AppDelegate.swift b/VimR/AppDelegate.swift index 0e36b002..a3686eb7 100644 --- a/VimR/AppDelegate.swift +++ b/VimR/AppDelegate.swift @@ -10,10 +10,15 @@ import PureLayout @NSApplicationMain class AppDelegate: NSObject, NSApplicationDelegate { - @IBOutlet weak var window: NSWindow! + private let prefStore = PrefStore(source: Observable.empty()) - private let prefWindowComponent = PrefWindowComponent(source: Observable.empty()) private let mainWindowManager: MainWindowManager + private let prefWindowComponent = PrefWindowComponent(source: Observable.empty()) + + override init() { + self.mainWindowManager = MainWindowManager(prefWindowComponent: self.prefWindowComponent) + super.init() + } @IBAction func debugSomething(sender: AnyObject!) { NSLog("debug sth...") @@ -27,11 +32,6 @@ class AppDelegate: NSObject, NSApplicationDelegate { self.prefWindowComponent.show() } - override init() { - self.mainWindowManager = MainWindowManager(prefWindowComponent: self.prefWindowComponent) - super.init() - } - func applicationDidFinishLaunching(aNotification: NSNotification) { // let testView = InputTestView(frame: CGRect(x: 0, y: 0, width: 300, height: 300)) // self.window.contentView?.addSubview(testView) diff --git a/VimR/Component.swift b/VimR/Component.swift index 65fa2fac..566b102d 100644 --- a/VimR/Component.swift +++ b/VimR/Component.swift @@ -6,10 +6,14 @@ import Foundation import RxSwift -protocol Component { +protocol Flow { var sink: Observable { get } } +protocol Store: Flow {} + +protocol Component: Flow {} + protocol ViewComponent: Component { var view: NSView { get } } diff --git a/VimR/PrefStore.swift b/VimR/PrefStore.swift new file mode 100644 index 00000000..01028e9b --- /dev/null +++ b/VimR/PrefStore.swift @@ -0,0 +1,86 @@ +/** + * Tae Won Ha - http://taewon.de - @hataewon + * See LICENSE + */ + +import Foundation +import RxSwift + +private class PrefKeys { + + static let editorFontName = "editor-font-name" + static let editorFontSize = "editor-font-size" +} + +class PrefStore: Store { + + private static let compatibleVersion = "38" + private static let defaultEditorFont = NSFont(name: "Menlo", size: 13)! + private static let minimumEditorFontSize = CGFloat(4) + private static let maximumEditorFontSize = CGFloat(128) + + private let source: Observable + private let disposeBag = DisposeBag() + + private let subject = PublishSubject() + var sink: Observable { + return self.subject.asObservable() + } + + private let userDefaults = NSUserDefaults.standardUserDefaults() + private let fontManager = NSFontManager.sharedFontManager() + + private var data = PrefData(appearance: AppearancePrefData(editorFont: PrefStore.defaultEditorFont)) + + init(source: Observable) { + self.source = source + + if let prefs = self.userDefaults.dictionaryForKey(PrefStore.compatibleVersion) { + self.data = self.prefDataFromDict(prefs) + } else { + self.userDefaults.setValue(self.prefsDict(self.data), forKey: PrefStore.compatibleVersion) + } + + self.subject.onNext(self.data) + } + + private func prefDataFromDict(prefs: [String: AnyObject]) -> PrefData { + let defaultFontSize = NSNumber(float: Float(PrefStore.defaultEditorFont.pointSize)) + + let editorFontName = prefs[PrefKeys.editorFontName] as? String ?? PrefStore.defaultEditorFont.fontName + let editorFontSizeFromPref = prefs[PrefKeys.editorFontSize] as? NSNumber ?? defaultFontSize + let editorFontSize: CGFloat = CGFloat(editorFontSizeFromPref.floatValue) ?? CGFloat(defaultFontSize) + + var editorFont = NSFont(name: editorFontName, size: editorFontSize) ?? PrefStore.defaultEditorFont + if !editorFont.fixedPitch { + editorFont = fontManager.convertFont(PrefStore.defaultEditorFont, toSize: editorFont.pointSize) + } + if editorFont.pointSize < PrefStore.minimumEditorFontSize + || editorFont.pointSize > PrefStore.maximumEditorFontSize { + editorFont = fontManager.convertFont(editorFont, toSize: CGFloat(defaultFontSize)) + } + + return PrefData(appearance: AppearancePrefData(editorFont: editorFont)) + } + + private func prefsDict(prefData: PrefData) -> [String: AnyObject] { + let appearanceData = prefData.appearance + let prefs: [String: AnyObject] = [ + PrefKeys.editorFontName: appearanceData.editorFont.fontName, + PrefKeys.editorFontSize: appearanceData.editorFont.pointSize + ] + return prefs + } + + private func addReactions() { + self.source + .filter { $0 is PrefData } + .map { $0 as! PrefData } + .subscribeNext { [unowned self] prefData in + self.data = prefData + self.userDefaults.setValue(self.prefsDict(prefData), forKey: PrefStore.compatibleVersion) + self.subject.onNext(prefData) + } + .addDisposableTo(self.disposeBag) + } +}