1
1
mirror of https://github.com/qvacua/vimr.git synced 2024-12-22 13:11:55 +03:00
vimr/VimR/OpenQuicklyWindowComponent.swift

186 lines
6.2 KiB
Swift
Raw Normal View History

/**
* Tae Won Ha - http://taewon.de - @hataewon
* See LICENSE
*/
import Cocoa
import PureLayout
import RxSwift
import RxCocoa
2016-09-01 21:10:40 +03:00
class OpenQuicklyWindowComponent: WindowComponent, NSWindowDelegate, NSTableViewDelegate, NSTableViewDataSource {
private let searchField = NSTextField(forAutoLayout: ())
2016-09-03 00:35:18 +03:00
private let cwdControl = NSPathControl(forAutoLayout: ())
private let countField = NSTextField(forAutoLayout: ())
private let fileView = NSTableView.standardSourceListTableView()
private let fileItemService: FileItemService
private var count = 0
private var flatFiles = Observable<[FileItem]>.empty()
private var flatFilesDisposeBag = DisposeBag()
private let userInitiatedScheduler = ConcurrentDispatchQueueScheduler(globalConcurrentQueueQOS: .UserInitiated)
private var scoredItems = [ScoredFileItem]()
private var sortedScoredItems = [ScoredFileItem]()
private var cwd = NSURL(fileURLWithPath: NSHomeDirectory(), isDirectory: true) {
didSet {
self.cwdControl.URL = self.cwd
}
}
init(source: Observable<Any>, fileItemService: FileItemService) {
self.fileItemService = fileItemService
super.init(source: source, nibName: "OpenQuicklyWindow")
2016-09-01 21:10:40 +03:00
self.window.delegate = self
self.searchField.rx_text
.throttle(0.2, scheduler: MainScheduler.instance)
.distinctUntilChanged()
.subscribeOn(self.userInitiatedScheduler)
.doOnNext { _ in
self.scoredItems = []
self.sortedScoredItems = []
}
.flatMapLatest { [unowned self] pattern -> Observable<[ScoredFileItem]> in
if pattern.characters.count == 0 {
return self.flatFiles
.map { fileItems in
return fileItems.concurrentChunkMap(50) { item in
return ScoredFileItem(score: 0, url: item.url)
}
}
}
let useFullPath = pattern.containsString("/")
return self.flatFiles
.map { fileItems in
return fileItems.concurrentChunkMap(50) { item in
let url = item.url
let target = useFullPath ? url.path! : url.lastPathComponent!
return ScoredFileItem(score: Scorer.score(target, pattern: pattern), url: url)
}
}
}
.observeOn(MainScheduler.instance)
.subscribeNext { [unowned self] items in
self.scoredItems.appendContentsOf(items)
self.sortedScoredItems = Array(self.scoredItems.sort(>)[0...min(500, self.scoredItems.count - 1)])
self.fileView.reloadData()
}
.addDisposableTo(self.disposeBag)
}
override func addViews() {
2016-09-03 00:44:05 +03:00
let searchField = self.searchField
let fileView = self.fileView
2016-09-03 00:44:05 +03:00
fileView.setDataSource(self)
fileView.setDelegate(self)
2016-09-03 00:55:19 +03:00
let fileScrollView = NSScrollView.standardScrollView()
fileScrollView.autoresizesSubviews = true
2016-09-03 00:44:05 +03:00
fileScrollView.documentView = fileView
2016-09-03 00:35:18 +03:00
let cwdControl = self.cwdControl
cwdControl.pathStyle = .Standard
cwdControl.backgroundColor = NSColor.clearColor()
cwdControl.refusesFirstResponder = true
cwdControl.cell?.controlSize = .SmallControlSize
cwdControl.cell?.font = NSFont.systemFontOfSize(NSFont.smallSystemFontSize())
cwdControl.setContentCompressionResistancePriority(NSLayoutPriorityDefaultLow, forOrientation:.Horizontal)
let countField = self.countField
countField.editable = false
countField.bordered = false
countField.alignment = .Right
countField.backgroundColor = NSColor.clearColor()
countField.stringValue = "0 items"
2016-09-03 00:44:05 +03:00
let contentView = self.window.contentView!
contentView.addSubview(searchField)
contentView.addSubview(fileScrollView)
contentView.addSubview(cwdControl)
contentView.addSubview(countField)
2016-09-01 21:10:40 +03:00
2016-09-03 00:35:18 +03:00
searchField.autoPinEdgeToSuperviewEdge(.Top, withInset: 18)
searchField.autoPinEdgeToSuperviewEdge(.Right, withInset: 18)
searchField.autoPinEdgeToSuperviewEdge(.Left, withInset: 18)
2016-09-03 00:44:05 +03:00
fileScrollView.autoPinEdge(.Top, toEdge: .Bottom, ofView: searchField, withOffset: 18)
fileScrollView.autoPinEdge(.Right, toEdge: .Right, ofView: searchField)
fileScrollView.autoPinEdge(.Left, toEdge: .Left, ofView: searchField)
fileScrollView.autoSetDimension(.Height, toSize: 300)
cwdControl.autoPinEdge(.Top, toEdge: .Bottom, ofView: fileScrollView, withOffset: 18)
cwdControl.autoPinEdgeToSuperviewEdge(.Left, withInset: 18)
2016-09-03 00:35:18 +03:00
cwdControl.autoPinEdgeToSuperviewEdge(.Bottom, withInset: 18)
countField.autoPinEdge(.Top, toEdge: .Bottom, ofView: fileScrollView, withOffset: 18)
countField.autoPinEdgeToSuperviewEdge(.Right, withInset: 18)
countField.autoPinEdge(.Left, toEdge: .Right, ofView: cwdControl)
}
override func subscription(source source: Observable<Any>) -> Disposable {
return NopDisposable.instance
}
2016-09-03 00:35:18 +03:00
func show(forMainWindow mainWindow: MainWindowComponent) {
self.cwd = mainWindow.cwd
let flatFiles = self.fileItemService.flatFileItems(ofUrl: self.cwd)
.subscribeOn(self.userInitiatedScheduler)
.replayAll()
flatFiles.connect()
flatFiles
.observeOn(MainScheduler.instance)
.subscribeNext { [unowned self] items in
self.count += items.count
self.countField.stringValue = "\(self.count) items"
}
.addDisposableTo(self.flatFilesDisposeBag)
self.flatFiles = flatFiles
2016-09-03 00:35:18 +03:00
self.show()
self.searchField.becomeFirstResponder()
}
}
2016-09-03 00:44:05 +03:00
// MARK: - NSTableViewDataSource
extension OpenQuicklyWindowComponent {
func numberOfRowsInTableView(_: NSTableView) -> Int {
return self.sortedScoredItems.count
2016-09-03 00:44:05 +03:00
}
func tableView(_: NSTableView, objectValueForTableColumn _: NSTableColumn?, row: Int) -> AnyObject? {
return self.sortedScoredItems[row].url.lastPathComponent!
2016-09-03 00:44:05 +03:00
}
}
// MARK: - NSTableViewDelegate
extension OpenQuicklyWindowComponent {
func tableViewSelectionDidChange(_: NSNotification) {
Swift.print("selection changed")
}
}
// MARK: - NSWindowDelegate
extension OpenQuicklyWindowComponent {
func windowDidClose(notification: NSNotification) {
self.searchField.stringValue = ""
self.countField.stringValue = "0 items"
self.count = 0
self.scoredItems = []
self.sortedScoredItems = []
self.flatFiles = Observable.empty()
self.flatFilesDisposeBag = DisposeBag()
}
}