1
1
mirror of https://github.com/qvacua/vimr.git synced 2024-11-28 11:35:35 +03:00

GH-264 Extract superclasses for components

This commit is contained in:
Tae Won Ha 2016-08-30 22:25:34 +02:00
parent e5aae0b346
commit ec94566ba9
No known key found for this signature in database
GPG Key ID: E40743465B5B8B44
10 changed files with 202 additions and 99 deletions

View File

@ -93,6 +93,9 @@
4BDF500D1D760A6D00D8FBC3 /* RxSwift.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4B2A2BE31D0225800074CE9A /* RxSwift.framework */; };
4BDF500E1D760A7500D8FBC3 /* RxSwift.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4B2A2BE31D0225800074CE9A /* RxSwift.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
4BDF50121D760B7200D8FBC3 /* EonilFileSystemEvents.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 4BDF50071D7607BF00D8FBC3 /* EonilFileSystemEvents.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
4BDF50141D7617EA00D8FBC3 /* OpenQuicklyWindowComponent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BDF50131D7617EA00D8FBC3 /* OpenQuicklyWindowComponent.swift */; };
4BDF50171D77540900D8FBC3 /* OpenQuicklyWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4BDF50191D77540900D8FBC3 /* OpenQuicklyWindow.xib */; };
4BDF501B1D77596500D8FBC3 /* OpenQuicklyWindowService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BDF501A1D77596500D8FBC3 /* OpenQuicklyWindowService.swift */; };
4BDF641C1D0887C100D47E1D /* TextDrawer.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BDF641A1D0887C100D47E1D /* TextDrawer.h */; settings = {ATTRIBUTES = (Public, ); }; };
4BDF641D1D0887C100D47E1D /* TextDrawer.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BDF641B1D0887C100D47E1D /* TextDrawer.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
4BDF64241D08CAB000D47E1D /* MMCoreTextView.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BDF64221D08CAB000D47E1D /* MMCoreTextView.h */; settings = {ATTRIBUTES = (Private, ); }; };
@ -270,6 +273,9 @@
4BDCFAE91D3147A300F62670 /* NeoVimMsgIds.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NeoVimMsgIds.h; sourceTree = "<group>"; };
4BDF50071D7607BF00D8FBC3 /* EonilFileSystemEvents.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = EonilFileSystemEvents.framework; path = Carthage/Build/Mac/EonilFileSystemEvents.framework; sourceTree = SOURCE_ROOT; };
4BDF500B1D760A3500D8FBC3 /* FileUtilsTest */ = {isa = PBXFileReference; lastKnownFileType = folder; path = FileUtilsTest; sourceTree = "<group>"; };
4BDF50131D7617EA00D8FBC3 /* OpenQuicklyWindowComponent.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OpenQuicklyWindowComponent.swift; sourceTree = "<group>"; };
4BDF50181D77540900D8FBC3 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/OpenQuicklyWindow.xib; sourceTree = "<group>"; };
4BDF501A1D77596500D8FBC3 /* OpenQuicklyWindowService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OpenQuicklyWindowService.swift; sourceTree = "<group>"; };
4BDF641A1D0887C100D47E1D /* TextDrawer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TextDrawer.h; sourceTree = "<group>"; };
4BDF641B1D0887C100D47E1D /* TextDrawer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TextDrawer.m; sourceTree = "<group>"; };
4BDF64221D08CAB000D47E1D /* MMCoreTextView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MMCoreTextView.h; sourceTree = "<group>"; };
@ -444,6 +450,7 @@
4BEBA50C1CFF374B00673FDF /* MainMenu.xib */,
4B97E2CE1D33F53D00FC0660 /* MainWindow.xib */,
4B029F1C1D45E349004EE0D3 /* PrefWindow.xib */,
4BDF50191D77540900D8FBC3 /* OpenQuicklyWindow.xib */,
4BEBA50A1CFF374B00673FDF /* Assets.xcassets */,
4BF07EE61D51326A009BECEB /* Credits.rtf */,
4BEBA50F1CFF374B00673FDF /* Info.plist */,
@ -473,6 +480,8 @@
1929B39DA7AC4A9B62D7CD39 /* Component.swift */,
4BD3BF961D32B0DB00082605 /* MainWindowManager.swift */,
4BD3BF921D32A95800082605 /* MainWindowComponent.swift */,
4BDF501A1D77596500D8FBC3 /* OpenQuicklyWindowService.swift */,
4BDF50131D7617EA00D8FBC3 /* OpenQuicklyWindowComponent.swift */,
4B238BED1D3ED55300CBDD98 /* Preferences */,
);
name = UI;
@ -757,6 +766,7 @@
files = (
4BF07EE41D51326A009BECEB /* Credits.rtf in Resources */,
4BEBA50B1CFF374B00673FDF /* Assets.xcassets in Resources */,
4BDF50171D77540900D8FBC3 /* OpenQuicklyWindow.xib in Resources */,
4B37ADB91D6E471B00970D55 /* vimr in Resources */,
4BEBA50E1CFF374B00673FDF /* MainMenu.xib in Resources */,
4B97E2CC1D33F53D00FC0660 /* MainWindow.xib in Resources */,
@ -835,6 +845,7 @@
buildActionMask = 2147483647;
files = (
4B238BE11D3BF24200CBDD98 /* Application.swift in Sources */,
4BDF50141D7617EA00D8FBC3 /* OpenQuicklyWindowComponent.swift in Sources */,
4B6A70941D60E04200E12030 /* AppKitCommons.swift in Sources */,
4BD3BF971D32B0DB00082605 /* MainWindowManager.swift in Sources */,
4B238BEC1D3ED54D00CBDD98 /* AppearancePrefPane.swift in Sources */,
@ -847,6 +858,7 @@
4BEBA5091CFF374B00673FDF /* AppDelegate.swift in Sources */,
1929B165820D7177743B537A /* Component.swift in Sources */,
1929B93DBAD09835E428F610 /* PrefPane.swift in Sources */,
4BDF501B1D77596500D8FBC3 /* OpenQuicklyWindowService.swift in Sources */,
1929B2ADD407219BADBD5A70 /* CwlUtils.swift in Sources */,
1929B462CD4935AFF6D69457 /* FileItem.swift in Sources */,
1929B6388EAF16C190B82955 /* FileItemIgnorePattern.swift in Sources */,
@ -920,6 +932,14 @@
name = MainWindow.xib;
sourceTree = "<group>";
};
4BDF50191D77540900D8FBC3 /* OpenQuicklyWindow.xib */ = {
isa = PBXVariantGroup;
children = (
4BDF50181D77540900D8FBC3 /* Base */,
);
name = OpenQuicklyWindow.xib;
sourceTree = "<group>";
};
4BEBA50C1CFF374B00673FDF /* MainMenu.xib */ = {
isa = PBXVariantGroup;
children = (

View File

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="10117" systemVersion="15G31" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<dependencies>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="10117"/>
</dependencies>
<objects>
<customObject id="-2" userLabel="File's Owner"/>
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
<window title="Open Quickly" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" oneShot="NO" releasedWhenClosed="NO" visibleAtLaunch="NO" animationBehavior="default" id="QvC-M9-y7g">
<windowStyleMask key="styleMask" titled="YES" closable="YES"/>
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
<rect key="contentRect" x="196" y="240" width="365" height="255"/>
<rect key="screenRect" x="0.0" y="0.0" width="2560" height="1417"/>
<view key="contentView" id="EiT-Mj-1SZ">
<rect key="frame" x="0.0" y="0.0" width="365" height="255"/>
<autoresizingMask key="autoresizingMask"/>
</view>
<point key="canvasLocation" x="371.5" y="649.5"/>
</window>
</objects>
</document>

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="10117" systemVersion="15F34" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="10117" systemVersion="15G31" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<dependencies>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="10117"/>

View File

@ -7,6 +7,7 @@ import Cocoa
import RxSwift
protocol Flow {
var sink: Observable<Any> { get }
}
@ -14,6 +15,82 @@ protocol Store: Flow {}
protocol Component: Flow {}
protocol ViewComponent: Component {
var view: NSView { get }
class StandardFlow: Flow {
var sink: Observable<Any> {
return self.subject.asObservable()
}
let subject = PublishSubject<Any>()
let source: Observable<Any>
let disposeBag = DisposeBag()
init(source: Observable<Any>) {
self.source = source
self.subscription(source: source).addDisposableTo(self.disposeBag)
}
deinit {
self.subject.onCompleted()
}
func subscription(source source: Observable<Any>) -> Disposable {
preconditionFailure("Please override")
}
func publish(event event: Any) {
self.subject.onNext(event)
}
}
class StandardComponent: NSObject, Component {
var sink: Observable<Any> {
return self.subject.asObservable()
}
let subject = PublishSubject<Any>()
let source: Observable<Any>
let disposeBag = DisposeBag()
init(source: Observable<Any>) {
self.source = source
super.init()
self.addViews()
self.subscription(source: source).addDisposableTo(self.disposeBag)
}
deinit {
self.subject.onCompleted()
}
func addViews() {
preconditionFailure("Please override")
}
func subscription(source source: Observable<Any>) -> Disposable {
preconditionFailure("Please override")
}
func publish(event event: Any) {
self.subject.onNext(event)
}
}
class WindowComponent: StandardComponent {
let windowController: NSWindowController
var window: NSWindow {
return self.windowController.window!
}
init(source: Observable<Any>, nibName: String) {
self.windowController = NSWindowController(windowNibName: nibName)
super.init(source: source)
}
func show() {
self.windowController.showWindow(self)
}
}

View File

@ -7,22 +7,12 @@ import Cocoa
import PureLayout
import RxSwift
class MainWindowComponent: NSObject, NSWindowDelegate, NeoVimViewDelegate, Component {
private let source: Observable<Any>
private let disposeBag = DisposeBag()
private let subject = PublishSubject<Any>()
var sink: Observable<Any> {
return self.subject.asObservable()
}
class MainWindowComponent: WindowComponent, NSWindowDelegate, NeoVimViewDelegate {
// TODO: Use a delegate here!
private weak var mainWindowManager: MainWindowManager?
private let fontManager = NSFontManager.sharedFontManager()
private let windowController = NSWindowController(windowNibName: "MainWindow")
private let window: NSWindow
private var defaultEditorFont: NSFont
private var usesLigatures: Bool
@ -33,32 +23,23 @@ class MainWindowComponent: NSObject, NSWindowDelegate, NeoVimViewDelegate, Compo
private let neoVimView = NeoVimView(forAutoLayout: ())
init(source: Observable<Any>, manager: MainWindowManager, urls: [NSURL] = [], initialData: PrefData) {
self.source = source
self.mainWindowManager = manager
self.window = self.windowController.window!
self.defaultEditorFont = initialData.appearance.editorFont
self.usesLigatures = initialData.appearance.editorUsesLigatures
super.init()
super.init(source: source, nibName: "MainWindow")
self.window.delegate = self
self.neoVimView.delegate = self
self.addViews()
self.addReactions()
self.neoVimView.font = self.defaultEditorFont
self.neoVimView.usesLigatures = self.usesLigatures
self.neoVimView.open(urls: urls)
self.window.makeFirstResponder(self.neoVimView)
self.windowController.showWindow(self)
self.show()
}
deinit {
self.subject.onCompleted()
}
func open(urls urls: [NSURL]) {
self.neoVimView.open(urls: urls)
}
@ -79,13 +60,13 @@ class MainWindowComponent: NSObject, NSWindowDelegate, NeoVimViewDelegate, Compo
self.neoVimView.closeAllWindowsWithoutSaving()
}
private func addViews() {
override func addViews() {
self.window.contentView?.addSubview(self.neoVimView)
self.neoVimView.autoPinEdgesToSuperviewEdges()
}
private func addReactions() {
self.source
override func subscription(source source: Observable<Any>) -> Disposable {
return source
.filter { $0 is PrefData }
.map { ($0 as! PrefData).appearance }
.filter { [unowned self] appearanceData in
@ -95,8 +76,7 @@ class MainWindowComponent: NSObject, NSWindowDelegate, NeoVimViewDelegate, Compo
.subscribeNext { [unowned self] appearance in
self.neoVimView.usesLigatures = appearance.editorUsesLigatures
self.neoVimView.font = appearance.editorFont
}
.addDisposableTo(self.disposeBag)
}
}
}

View File

@ -10,28 +10,19 @@ enum MainWindowEvent {
case allWindowsClosed
}
class MainWindowManager {
class MainWindowManager: StandardFlow {
static private let userHomeUrl = NSURL(fileURLWithPath: NSHomeDirectory(), isDirectory: true)
private let source: Observable<Any>
private let disposeBag = DisposeBag()
private let subject = PublishSubject<Any>()
var sink: Observable<Any> {
return self.subject.asObservable()
}
private var mainWindowComponents = [String:MainWindowComponent]()
private var keyMainWindow: MainWindowComponent?
private var data: PrefData
init(source: Observable<Any>, initialData: PrefData) {
self.source = source
self.data = initialData
self.addReactions()
super.init(source: source)
}
func newMainWindow(urls urls: [NSURL] = [], cwd: NSURL = MainWindowManager.userHomeUrl) -> MainWindowComponent {
@ -52,7 +43,7 @@ class MainWindowManager {
self.mainWindowComponents.removeValueForKey(mainWindowComponent.uuid)
if self.mainWindowComponents.isEmpty {
self.subject.onNext(MainWindowEvent.allWindowsClosed)
self.publish(event: MainWindowEvent.allWindowsClosed)
}
}
@ -92,13 +83,12 @@ class MainWindowManager {
return !self.mainWindowComponents.isEmpty
}
private func addReactions() {
self.source
override func subscription(source source: Observable<Any>) -> Disposable {
return source
.filter { $0 is PrefData }
.map { $0 as! PrefData }
.subscribeNext { [unowned self] prefData in
self.data = prefData
}
.addDisposableTo(self.disposeBag)
}
}
}

View File

@ -0,0 +1,26 @@
/**
* Tae Won Ha - http://taewon.de - @hataewon
* See LICENSE
*/
import Cocoa
import PureLayout
import RxSwift
class OpenQuicklyWindowComponent: WindowComponent, NSWindowDelegate {
init(source: Observable<Any>) {
super.init(source: source, nibName: "OpenQuicklyWindow")
}
override func addViews() {
let searchField = NSTextField(forAutoLayout: ())
self.window.contentView?.addSubview(searchField)
searchField.autoPinEdgesToSuperviewEdgesWithInsets(NSEdgeInsets(top: 18, left: 18, bottom: 18, right: 18))
}
override func subscription(source source: Observable<Any>) -> Disposable {
return NopDisposable.instance
}
}

View File

@ -0,0 +1,13 @@
/**
* Tae Won Ha - http://taewon.de - @hataewon
* See LICENSE
*/
import Cocoa
import RxSwift
class OpenQuicklyWindowService {
// private let openQuicklyWindow: OpenQuicklyWindowComponent
}

View File

@ -6,7 +6,7 @@
import Cocoa
import RxSwift
class PrefPane: NSView, ViewComponent {
class PrefPane: NSView, Component {
private let source: Observable<Any>
private let disposeBag = DisposeBag()
@ -16,10 +16,6 @@ class PrefPane: NSView, ViewComponent {
return self.subject.asObservable()
}
var view: NSView {
return self
}
// 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

View File

@ -12,21 +12,10 @@ struct PrefData {
var appearance: AppearancePrefData
}
class PrefWindowComponent: NSObject, NSTableViewDataSource, NSTableViewDelegate, Component {
private let source: Observable<Any>
private let disposeBag = DisposeBag()
private let subject = PublishSubject<Any>()
var sink: Observable<Any> {
return self.subject.asObservable()
}
class PrefWindowComponent: WindowComponent, NSTableViewDataSource, NSTableViewDelegate {
private var data: PrefData
private let windowController = NSWindowController(windowNibName: "PrefWindow")
private let window: NSWindow
private let categoryView = NSTableView(frame: CGRect.zero)
private let categoryScrollView = NSScrollView(forAutoLayout: ())
private let paneContainer = NSScrollView(forAutoLayout: ())
@ -50,7 +39,6 @@ class PrefWindowComponent: NSObject, NSTableViewDataSource, NSTableViewDelegate,
}
init(source: Observable<Any>, initialData: PrefData) {
self.source = source
self.data = initialData
self.panes = [
@ -58,24 +46,13 @@ class PrefWindowComponent: NSObject, NSTableViewDataSource, NSTableViewDelegate,
AppearancePrefPane(source: source, initialData: self.data.appearance)
]
self.window = self.windowController.window!
super.init(source: source, nibName: "PrefWindow")
super.init()
self.addViews()
self.addReactions()
}
deinit {
self.subject.onCompleted()
}
func show() {
self.windowController.showWindow(self)
}
private func addReactions() {
self.source
override func subscription(source source: Observable<Any>) -> Disposable {
return source
.filter { $0 is PrefData }
.map { $0 as! PrefData }
.subscribeNext { [unowned self] prefData in
@ -86,28 +63,9 @@ class PrefWindowComponent: NSObject, NSTableViewDataSource, NSTableViewDelegate,
self.data = prefData
}
.addDisposableTo(self.disposeBag)
self.panes
.map { $0.sink }
.toMergedObservables()
.map { [unowned self] action in
switch action {
case let data as AppearancePrefData:
self.data.appearance = data
case let data as GeneralPrefData:
self.data.general = data
default:
NSLog("nothing to see here")
}
return self.data
}
.subscribeNext { [unowned self] action in self.subject.onNext(action) }
.addDisposableTo(self.disposeBag)
}
private func addViews() {
override func addViews() {
let tableColumn = NSTableColumn(identifier: "name")
let textFieldCell = NSTextFieldCell()
textFieldCell.allowsEditingTextAttributes = false
@ -157,6 +115,26 @@ class PrefWindowComponent: NSObject, NSTableViewDataSource, NSTableViewDelegate,
self.currentPane = self.panes[0]
}
private func addReactions() {
self.panes
.map { $0.sink }
.toMergedObservables()
.map { [unowned self] action in
switch action {
case let data as AppearancePrefData:
self.data.appearance = data
case let data as GeneralPrefData:
self.data.general = data
default:
NSLog("nothing to see here")
}
return self.data
}
.subscribeNext { [unowned self] action in self.publish(event: action) }
.addDisposableTo(self.disposeBag)
}
}
// MARK: - NSTableViewDataSource