diff --git a/VimR.xcodeproj/project.pbxproj b/VimR.xcodeproj/project.pbxproj index 62bf2f54..47fd1b77 100644 --- a/VimR.xcodeproj/project.pbxproj +++ b/VimR.xcodeproj/project.pbxproj @@ -12,6 +12,7 @@ 1929BF81A40B4154D3EA33CE /* server_ui.m in Sources */ = {isa = PBXBuildFile; fileRef = 1929B93013228985F509C8F6 /* server_ui.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; 4B1BB3531D16C5E500CA4FEF /* InputTestView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B1BB3521D16C5E500CA4FEF /* InputTestView.swift */; }; 4B238BE11D3BF24200CBDD98 /* Application.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B238BE01D3BF24200CBDD98 /* Application.swift */; }; + 4B238BEC1D3ED54D00CBDD98 /* AppearancePrefPane.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B238BEB1D3ED54D00CBDD98 /* AppearancePrefPane.swift */; }; 4B2A2BEC1D02261F0074CE9A /* RxCocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4B2A2BE21D0225800074CE9A /* RxCocoa.framework */; }; 4B2A2BED1D02261F0074CE9A /* RxCocoa.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 4B2A2BE21D0225800074CE9A /* RxCocoa.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 4B2A2BEE1D02261F0074CE9A /* RxSwift.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4B2A2BE31D0225800074CE9A /* RxSwift.framework */; }; @@ -25,9 +26,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 */; }; - 4B4FC8E41D3E86EB009352C3 /* PrefWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4B4FC8E31D3E86EB009352C3 /* PrefWindow.xib */; }; 4B4FC8E61D3E8739009352C3 /* PrefWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B4FC8E51D3E8739009352C3 /* PrefWindowController.swift */; }; - 4B4FC8E81D3E8933009352C3 /* PrefManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B4FC8E71D3E8933009352C3 /* PrefManager.swift */; }; 4B56F2931D29903F00C1F92E /* SwiftNeoVimTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B56F2921D29903F00C1F92E /* SwiftNeoVimTests.swift */; }; 4B56F2951D29903F00C1F92E /* SwiftNeoVim.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4B2A2BF71D0351810074CE9A /* SwiftNeoVim.framework */; }; 4B56F29D1D29926600C1F92E /* Nimble.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4B56F29B1D29926600C1F92E /* Nimble.framework */; }; @@ -153,6 +152,7 @@ 1929BF00B466B40629C2AABE /* NeoVimView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NeoVimView.swift; sourceTree = ""; }; 4B1BB3521D16C5E500CA4FEF /* InputTestView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InputTestView.swift; sourceTree = ""; }; 4B238BE01D3BF24200CBDD98 /* Application.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Application.swift; sourceTree = ""; }; + 4B238BEB1D3ED54D00CBDD98 /* AppearancePrefPane.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppearancePrefPane.swift; sourceTree = ""; }; 4B2A2BE21D0225800074CE9A /* RxCocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = RxCocoa.framework; path = Carthage/Build/Mac/RxCocoa.framework; sourceTree = SOURCE_ROOT; }; 4B2A2BE31D0225800074CE9A /* RxSwift.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = RxSwift.framework; path = Carthage/Build/Mac/RxSwift.framework; sourceTree = SOURCE_ROOT; }; 4B2A2BF71D0351810074CE9A /* SwiftNeoVim.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SwiftNeoVim.framework; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -164,9 +164,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 = ""; }; - 4B4FC8E31D3E86EB009352C3 /* PrefWindow.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = PrefWindow.xib; sourceTree = ""; }; 4B4FC8E51D3E8739009352C3 /* PrefWindowController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PrefWindowController.swift; sourceTree = ""; }; - 4B4FC8E71D3E8933009352C3 /* PrefManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PrefManager.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 = ""; }; 4B56F2941D29903F00C1F92E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; @@ -265,6 +263,15 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 4B238BED1D3ED55300CBDD98 /* Preferences */ = { + isa = PBXGroup; + children = ( + 4B4FC8E51D3E8739009352C3 /* PrefWindowController.swift */, + 4B238BEB1D3ED54D00CBDD98 /* AppearancePrefPane.swift */, + ); + name = Preferences; + sourceTree = ""; + }; 4B2A2BE61D0225840074CE9A /* Frameworks */ = { isa = PBXGroup; children = ( @@ -340,7 +347,6 @@ children = ( 4BEBA50C1CFF374B00673FDF /* MainMenu.xib */, 4B97E2CE1D33F53D00FC0660 /* MainWindow.xib */, - 4B4FC8E31D3E86EB009352C3 /* PrefWindow.xib */, 4BEBA50A1CFF374B00673FDF /* Assets.xcassets */, 4BEBA50F1CFF374B00673FDF /* Info.plist */, ); @@ -394,8 +400,7 @@ 4BEBA5081CFF374B00673FDF /* AppDelegate.swift */, 4BD3BF961D32B0DB00082605 /* MainWindowManager.swift */, 4BD3BF921D32A95800082605 /* MainWindowController.swift */, - 4B4FC8E71D3E8933009352C3 /* PrefManager.swift */, - 4B4FC8E51D3E8739009352C3 /* PrefWindowController.swift */, + 4B238BED1D3ED55300CBDD98 /* Preferences */, 4B97E2CF1D33F92200FC0660 /* resources */, 4B2A2C0D1D0353750074CE9A /* Bridge.h */, ); @@ -607,7 +612,6 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - 4B4FC8E41D3E86EB009352C3 /* PrefWindow.xib in Resources */, 4BEBA50B1CFF374B00673FDF /* Assets.xcassets in Resources */, 4BEBA50E1CFF374B00673FDF /* MainMenu.xib in Resources */, 4B97E2CC1D33F53D00FC0660 /* MainWindow.xib in Resources */, @@ -682,9 +686,9 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 4B4FC8E81D3E8933009352C3 /* PrefManager.swift in Sources */, 4B238BE11D3BF24200CBDD98 /* Application.swift in Sources */, 4BD3BF971D32B0DB00082605 /* MainWindowManager.swift in Sources */, + 4B238BEC1D3ED54D00CBDD98 /* AppearancePrefPane.swift in Sources */, 4BD3BF931D32A95800082605 /* MainWindowController.swift in Sources */, 4B4FC8E61D3E8739009352C3 /* PrefWindowController.swift in Sources */, 4BEBA5091CFF374B00673FDF /* AppDelegate.swift in Sources */, diff --git a/VimR/AppDelegate.swift b/VimR/AppDelegate.swift index 04c806b9..ba5a7ffb 100644 --- a/VimR/AppDelegate.swift +++ b/VimR/AppDelegate.swift @@ -4,6 +4,7 @@ */ import Cocoa +import RxSwift import PureLayout @NSApplicationMain @@ -12,6 +13,7 @@ class AppDelegate: NSObject, NSApplicationDelegate { @IBOutlet weak var window: NSWindow! private let mainWindowManager = MainWindowManager() + private let prefWindowController = PrefWindowController(source: Observable.empty()) @IBAction func debugSomething(sender: AnyObject!) { NSLog("debug sth...") @@ -26,7 +28,8 @@ class AppDelegate: NSObject, NSApplicationDelegate { // self.window.contentView?.addSubview(testView) // self.window.makeFirstResponder(testView) - self.mainWindowManager.newMainWindow() +// self.mainWindowManager.newMainWindow() + self.prefWindowController.showWindow(self) } func applicationShouldTerminate(sender: NSApplication) -> NSApplicationTerminateReply { diff --git a/VimR/AppearancePrefPane.swift b/VimR/AppearancePrefPane.swift new file mode 100644 index 00000000..96782d18 --- /dev/null +++ b/VimR/AppearancePrefPane.swift @@ -0,0 +1,92 @@ +/** + * Tae Won Ha - http://taewon.de - @hataewon + * See LICENSE + */ + +import Cocoa +import PureLayout + +class AppearancePrefPane: NSView, NSComboBoxDelegate, NSControlTextEditingDelegate { + + private let sizeCombo = NSComboBox(forAutoLayout: ()) + + // Return true to place this to the upper left corner when the scroll view is bigger than this view. + override var flipped: Bool { + return true + } + + override init(frame: NSRect) { + super.init(frame: frame) + + self.wantsLayer = true + self.layer?.backgroundColor = NSColor.yellowColor().CGColor + self.addViews() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + func sizeComboAction(sender: NSComboBox) { + NSLog("JO") + } + + private func addViews() { + let fontTitle = NSTextField(forAutoLayout: ()) + fontTitle.backgroundColor = NSColor.clearColor(); + fontTitle.stringValue = "Default Font:"; + fontTitle.editable = false; + fontTitle.bordered = false; + fontTitle.alignment = .Right; + + let fontManager = NSFontManager.sharedFontManager() + let fontPopup = NSPopUpButton(frame: CGRect.zero, pullsDown: false) + fontPopup.translatesAutoresizingMaskIntoConstraints = false + fontPopup.target = self + fontPopup.addItemsWithTitles(fontManager.availableFontNamesWithTraits(.FixedPitchFontMask)!) + + let sizeCombo = self.sizeCombo + sizeCombo.target = self + sizeCombo.action = #selector(AppearancePrefPane.sizeComboAction(_:)) + sizeCombo.setDelegate(self) + sizeCombo.addItemWithObjectValue("12") + sizeCombo.addItemWithObjectValue("16") + sizeCombo.addItemWithObjectValue("24") + + self.addSubview(fontTitle) + self.addSubview(fontPopup) + self.addSubview(sizeCombo) + + fontTitle.autoPinEdgeToSuperviewEdge(.Left, withInset: 18) + fontTitle.autoAlignAxis(.Baseline, toSameAxisOfView: fontPopup) + + fontPopup.autoPinEdgeToSuperviewEdge(.Top, withInset: 18) + fontPopup.autoPinEdge(.Left, toEdge: .Right, ofView: fontTitle, withOffset: 5) + fontPopup.autoSetDimension(.Width, toSize: 180) + + sizeCombo.autoSetDimension(.Width, toSize: 75) + sizeCombo.autoAlignAxis(.Horizontal, toSameAxisOfView: fontPopup) // .Baseline won't do... + sizeCombo.autoPinEdgeToSuperviewEdge(.Right, withInset: 18) + sizeCombo.autoPinEdgeToSuperviewEdge(.Bottom, withInset: 18) + sizeCombo.autoPinEdge(.Left, toEdge: .Right, ofView: fontPopup, withOffset: 5) + } +} + +// MARK: - NSComboBoxDelegate +extension AppearancePrefPane { + func comboBoxSelectionDidChange(notification: NSNotification) { + guard notification.object! === self.sizeCombo else { + return + } + + NSLog("selection changed by menu") + } + + override func controlTextDidChange(notification: NSNotification) { + guard notification.object! === self.sizeCombo else { + return + } + + NSLog("text did changed") + } +} diff --git a/VimR/PrefWindowController.swift b/VimR/PrefWindowController.swift new file mode 100644 index 00000000..6b2a9914 --- /dev/null +++ b/VimR/PrefWindowController.swift @@ -0,0 +1,121 @@ +/** + * Tae Won Ha - http://taewon.de - @hataewon + * See LICENSE + */ + +import Cocoa +import RxSwift +import PureLayout + +enum PrefAction { + case PrefChanged(prefs: [String: Any]) +} + +class PrefWindowController: NSWindowController, NSTableViewDataSource, NSTableViewDelegate { + + private let windowMask = NSTitledWindowMask + | NSResizableWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask + + private let source: Observable + private let disposeBag = DisposeBag() + let sink = PublishSubject().asObserver() + + private let categoryView = NSTableView(frame: CGRect.zero) + private let categoryScrollView = NSScrollView(forAutoLayout: ()) + private let paneScrollView = NSScrollView(forAutoLayout: ()) + + private let paneNames = [ "Appearance" ] + private let panes = [ AppearancePrefPane(forAutoLayout: ()) ] + + init(source: Observable) { + self.source = source + + let window = NSWindow( + contentRect: CGRect(x: 100, y: 100, width: 640, height: 480), + styleMask: self.windowMask, + backing: .Buffered, + defer: true + ) + window.title = "Preferences" + window.releasedWhenClosed = false + window.center() + + super.init(window: window) + + self.addViews() + } + + private func addViews() { + let tableColumn = NSTableColumn(identifier: "name") + let textFieldCell = NSTextFieldCell() + textFieldCell.allowsEditingTextAttributes = false + textFieldCell.lineBreakMode = .ByTruncatingTail + tableColumn.dataCell = textFieldCell + + let categoryView = self.categoryView + categoryView.addTableColumn(tableColumn) + categoryView.rowSizeStyle = .Default + categoryView.sizeLastColumnToFit() + categoryView.allowsEmptySelection = false + categoryView.allowsMultipleSelection = false + categoryView.headerView = nil + categoryView.focusRingType = .None + categoryView.selectionHighlightStyle = .SourceList + categoryView.setDataSource(self) + categoryView.setDelegate(self) + + let categoryScrollView = self.categoryScrollView + categoryScrollView.hasVerticalScroller = true + categoryScrollView.hasHorizontalScroller = true + categoryScrollView.autohidesScrollers = true + categoryScrollView.borderType = .BezelBorder + categoryScrollView.documentView = categoryView + + let paneScrollView = self.paneScrollView + paneScrollView.hasVerticalScroller = true; + paneScrollView.hasHorizontalScroller = true; + paneScrollView.borderType = .NoBorder; + paneScrollView.autohidesScrollers = true; + paneScrollView.autoresizesSubviews = true; + paneScrollView.backgroundColor = NSColor.windowBackgroundColor(); + paneScrollView.autohidesScrollers = true; + + self.window?.contentView?.addSubview(categoryScrollView) + self.window?.contentView?.addSubview(paneScrollView) + + categoryScrollView.autoSetDimension(.Width, toSize: 150) + categoryScrollView.autoPinEdgeToSuperviewEdge(.Top, withInset: -1) + categoryScrollView.autoPinEdgeToSuperviewEdge(.Bottom, withInset: -1) + categoryScrollView.autoPinEdgeToSuperviewEdge(.Left, withInset: -1) + paneScrollView.autoSetDimension(.Width, toSize: 200, relation: .GreaterThanOrEqual) + paneScrollView.autoPinEdgeToSuperviewEdge(.Top) + paneScrollView.autoPinEdgeToSuperviewEdge(.Right) + paneScrollView.autoPinEdgeToSuperviewEdge(.Bottom) + paneScrollView.autoPinEdge(.Left, toEdge: .Right, ofView: categoryScrollView) + + self.paneScrollView.documentView = self.panes[0] + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } +} + +// MARK: - NSTableViewDataSource +extension PrefWindowController { + func numberOfRowsInTableView(tableView: NSTableView) -> Int { + return self.paneNames.count + } + + /* This method is required for the "Cell Based" TableView, and is optional for the "View Based" TableView. If implemented in the latter case, the value will be set to the view at a given row/column if the view responds to -setObjectValue: (such as NSControl and NSTableCellView). + */ + func tableView(tableView: NSTableView, objectValueForTableColumn tableColumn: NSTableColumn?, row: Int) -> AnyObject? { + return self.paneNames[row] + } +} + +// MARK: - NSTableViewDelegate +extension PrefWindowController { + func tableViewSelectionDidChange(notification: NSNotification) { + } +}