mirror of
https://github.com/qvacua/vimr.git
synced 2024-11-28 11:35:35 +03:00
GH-264 Use NSOperation to filer
- Using NSOperation, we can cancel the filtering better
This commit is contained in:
parent
32e564cd3d
commit
923f07cba6
@ -72,6 +72,7 @@
|
||||
4B97E2CC1D33F53D00FC0660 /* MainWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4B97E2CE1D33F53D00FC0660 /* MainWindow.xib */; };
|
||||
4B9A15241D2993DA009F9F67 /* Nimble.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4B56F29B1D29926600C1F92E /* Nimble.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
4B9A15261D2993DF009F9F67 /* SwiftNeoVim.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4B2A2BF71D0351810074CE9A /* SwiftNeoVim.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
4BAD84E81D7CA8FC00A79CC3 /* OpenQuicklyFilterOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BAD84E71D7CA8FC00A79CC3 /* OpenQuicklyFilterOperation.swift */; };
|
||||
4BB1BEA91D48773200463C29 /* RxSwiftUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BB1BEA81D48773200463C29 /* RxSwiftUtils.swift */; };
|
||||
4BCADE081D11ED12004DAD0F /* CocoaExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BCADE071D11ED12004DAD0F /* CocoaExtensions.swift */; };
|
||||
4BD3BF931D32A95800082605 /* MainWindowComponent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BD3BF921D32A95800082605 /* MainWindowComponent.swift */; };
|
||||
@ -259,6 +260,7 @@
|
||||
4B854A1A1D31447C00E08DE1 /* NeoVimServer */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = NeoVimServer; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
4B854A1C1D31447C00E08DE1 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
|
||||
4B97E2CD1D33F53D00FC0660 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainWindow.xib; sourceTree = "<group>"; };
|
||||
4BAD84E71D7CA8FC00A79CC3 /* OpenQuicklyFilterOperation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OpenQuicklyFilterOperation.swift; sourceTree = "<group>"; };
|
||||
4BB1BEA81D48773200463C29 /* RxSwiftUtils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RxSwiftUtils.swift; sourceTree = "<group>"; };
|
||||
4BCADE071D11ED12004DAD0F /* CocoaExtensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CocoaExtensions.swift; sourceTree = "<group>"; };
|
||||
4BCF638F1D323CFD00F15CE4 /* nvim */ = {isa = PBXFileReference; lastKnownFileType = folder; name = nvim; path = neovim/src/nvim; sourceTree = SOURCE_ROOT; };
|
||||
@ -487,6 +489,7 @@
|
||||
4BDF501A1D77596500D8FBC3 /* OpenQuicklyWindowManager.swift */,
|
||||
4BDF50131D7617EA00D8FBC3 /* OpenQuicklyWindowComponent.swift */,
|
||||
4B22F7F11D7C6B9000929B0E /* ImageAndTextTableCell.swift */,
|
||||
4BAD84E71D7CA8FC00A79CC3 /* OpenQuicklyFilterOperation.swift */,
|
||||
4B238BED1D3ED55300CBDD98 /* Preferences */,
|
||||
);
|
||||
name = UI;
|
||||
@ -874,6 +877,7 @@
|
||||
1929B3F5743967125F357C9F /* Matcher.swift in Sources */,
|
||||
1929B53876E6952D378C2B30 /* ScoredFileItem.swift in Sources */,
|
||||
1929BD3F9E609BFADB27584B /* Scorer.swift in Sources */,
|
||||
4BAD84E81D7CA8FC00A79CC3 /* OpenQuicklyFilterOperation.swift in Sources */,
|
||||
1929B0E0C3BC59F52713D5A2 /* FoundationCommons.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
|
@ -16,7 +16,7 @@
|
||||
<windowStyleMask key="styleMask" titled="YES" closable="YES" resizable="YES"/>
|
||||
<windowPositionMask key="initialPositionMask" topStrut="YES"/>
|
||||
<rect key="contentRect" x="196" y="420" width="365" height="255"/>
|
||||
<rect key="screenRect" x="0.0" y="0.0" width="1920" height="1177"/>
|
||||
<rect key="screenRect" x="0.0" y="0.0" width="1440" height="877"/>
|
||||
<view key="contentView" id="EiT-Mj-1SZ">
|
||||
<rect key="frame" x="0.0" y="0.0" width="365" height="255"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
|
102
VimR/OpenQuicklyFilterOperation.swift
Normal file
102
VimR/OpenQuicklyFilterOperation.swift
Normal file
@ -0,0 +1,102 @@
|
||||
/**
|
||||
* Tae Won Ha - http://taewon.de - @hataewon
|
||||
* See LICENSE
|
||||
*/
|
||||
|
||||
import Cocoa
|
||||
|
||||
class OpenQuicklyFilterOperation: NSOperation {
|
||||
|
||||
private let chunkSize = 100
|
||||
private let maxResultCount = 500
|
||||
|
||||
private unowned let openQuicklyWindow: OpenQuicklyWindowComponent
|
||||
private let pattern: String
|
||||
private let flatFileItems: [FileItem]
|
||||
private let cwd: NSURL
|
||||
|
||||
private var spinLock: OSSpinLock = OS_SPINLOCK_INIT
|
||||
|
||||
init(forOpenQuicklyWindow openQuicklyWindow: OpenQuicklyWindowComponent) {
|
||||
self.openQuicklyWindow = openQuicklyWindow
|
||||
self.pattern = openQuicklyWindow.pattern
|
||||
self.cwd = openQuicklyWindow.cwd
|
||||
self.flatFileItems = openQuicklyWindow.flatFileItems
|
||||
|
||||
super.init()
|
||||
}
|
||||
|
||||
override func main() {
|
||||
self.openQuicklyWindow.scanCondition.lock()
|
||||
self.openQuicklyWindow.pauseScan = true
|
||||
defer {
|
||||
self.openQuicklyWindow.pauseScan = false
|
||||
self.openQuicklyWindow.scanCondition.broadcast()
|
||||
self.openQuicklyWindow.scanCondition.unlock()
|
||||
}
|
||||
|
||||
if self.cancelled {
|
||||
return
|
||||
}
|
||||
|
||||
let sorted: [ScoredFileItem]
|
||||
if pattern.characters.count == 0 {
|
||||
let truncatedItems = self.flatFileItems[0...min(self.maxResultCount, self.flatFileItems.count - 1)]
|
||||
sorted = truncatedItems.map { ScoredFileItem(score: 0, url: $0.url) }
|
||||
} else {
|
||||
DispatchUtils.gui { self.openQuicklyWindow.startProgress() }
|
||||
defer { DispatchUtils.gui { self.openQuicklyWindow.endProgress() } }
|
||||
|
||||
let count = self.flatFileItems.count
|
||||
let chunksCount = Int(ceil(Float(count) / Float(self.chunkSize)))
|
||||
let useFullPath = pattern.containsString("/")
|
||||
let cwdPath = self.cwd.path! + "/"
|
||||
|
||||
var result = [ScoredFileItem]()
|
||||
dispatch_apply(chunksCount, dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0)) { [unowned self] idx in
|
||||
if self.cancelled {
|
||||
return
|
||||
}
|
||||
|
||||
let startIndex = min(idx * self.chunkSize, count)
|
||||
let endIndex = min(startIndex + self.chunkSize, count)
|
||||
|
||||
let chunkedItems = self.flatFileItems[startIndex..<endIndex]
|
||||
let chunkedResult: [ScoredFileItem] = chunkedItems.flatMap {
|
||||
if self.cancelled {
|
||||
return nil
|
||||
}
|
||||
|
||||
let url = $0.url
|
||||
let target = useFullPath ? url.path!.stringByReplacingOccurrencesOfString(cwdPath, withString: "")
|
||||
: url.lastPathComponent!
|
||||
|
||||
return ScoredFileItem(score: Scorer.score(target, pattern: self.pattern), url: url)
|
||||
}
|
||||
|
||||
if self.cancelled {
|
||||
return
|
||||
}
|
||||
|
||||
OSSpinLockLock(&self.spinLock)
|
||||
result.appendContentsOf(chunkedResult)
|
||||
OSSpinLockUnlock(&self.spinLock)
|
||||
}
|
||||
|
||||
if self.cancelled {
|
||||
return
|
||||
}
|
||||
|
||||
sorted = result.sort(>)
|
||||
}
|
||||
|
||||
if self.cancelled {
|
||||
return
|
||||
}
|
||||
|
||||
DispatchUtils.gui {
|
||||
let result = Array(sorted[0...min(self.maxResultCount, sorted.count - 1)])
|
||||
self.openQuicklyWindow.reloadFileView(withScoredItems: result)
|
||||
}
|
||||
}
|
||||
}
|
@ -9,8 +9,24 @@ import RxSwift
|
||||
import RxCocoa
|
||||
|
||||
class OpenQuicklyWindowComponent: WindowComponent, NSWindowDelegate, NSTableViewDelegate, NSTableViewDataSource {
|
||||
|
||||
let scanCondition = NSCondition()
|
||||
var pauseScan = false
|
||||
|
||||
private(set) var pattern = ""
|
||||
private(set) var cwd = NSURL(fileURLWithPath: NSHomeDirectory(), isDirectory: true) {
|
||||
didSet {
|
||||
self.cwdPathCompsCount = self.cwd.pathComponents!.count
|
||||
self.cwdControl.URL = self.cwd
|
||||
}
|
||||
}
|
||||
private(set) var flatFileItems = [FileItem]()
|
||||
private(set) var fileViewItems = [ScoredFileItem]()
|
||||
|
||||
private let userInitiatedScheduler = ConcurrentDispatchQueueScheduler(globalConcurrentQueueQOS: .UserInitiated)
|
||||
|
||||
private let searchField = NSTextField(forAutoLayout: ())
|
||||
private let progressIndicator = NSProgressIndicator(forAutoLayout: ())
|
||||
private let cwdControl = NSPathControl(forAutoLayout: ())
|
||||
private let countField = NSTextField(forAutoLayout: ())
|
||||
private let fileView = NSTableView.standardSourceListTableView()
|
||||
@ -18,97 +34,32 @@ class OpenQuicklyWindowComponent: WindowComponent, NSWindowDelegate, NSTableView
|
||||
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 perSessionDisposeBag = DisposeBag()
|
||||
|
||||
private var cwdPathCompsCount = 0
|
||||
private var cwd = NSURL(fileURLWithPath: NSHomeDirectory(), isDirectory: true) {
|
||||
didSet {
|
||||
self.cwdPathCompsCount = self.cwd.pathComponents!.count
|
||||
self.cwdControl.URL = self.cwd
|
||||
}
|
||||
}
|
||||
|
||||
private let searchStream: Observable<String>
|
||||
private let filterOpQueue = NSOperationQueue()
|
||||
|
||||
init(source: Observable<Any>, fileItemService: FileItemService) {
|
||||
self.fileItemService = fileItemService
|
||||
self.searchStream = self.searchField.rx_text
|
||||
.throttle(0.2, scheduler: MainScheduler.instance)
|
||||
.distinctUntilChanged()
|
||||
|
||||
super.init(source: source, nibName: "OpenQuicklyWindow")
|
||||
|
||||
self.window.delegate = self
|
||||
self.filterOpQueue.qualityOfService = .UserInitiated
|
||||
self.filterOpQueue.name = "open-quickly-filter-operation-queue"
|
||||
|
||||
self.searchField.rx_text
|
||||
.throttle(0.2, scheduler: MainScheduler.instance)
|
||||
.distinctUntilChanged()
|
||||
.flatMapLatest { [unowned self] pattern in
|
||||
self.flatFiles.
|
||||
self.filterOpQueue.addOperationWithBlock {
|
||||
|
||||
}
|
||||
|
||||
return self.flatFiles
|
||||
}
|
||||
.subscribe(onNext: { [unowned self] pattern in
|
||||
NSLog("filtering \(pattern)")
|
||||
|
||||
})
|
||||
|
||||
// .subscribeOn(self.userInitiatedScheduler)
|
||||
// .doOnNext { _ in
|
||||
// self.scoredItems = []
|
||||
// self.sortedScoredItems = []
|
||||
// }
|
||||
// .subscribeOn(MainScheduler.instance)
|
||||
// .doOnNext { _ in
|
||||
// self.fileView.reloadData()
|
||||
// }
|
||||
// .subscribeOn(self.userInitiatedScheduler)
|
||||
// .flatMapLatest { [unowned self] pattern -> Observable<[ScoredFileItem]> in
|
||||
// NSLog("Flat map start: \(pattern)")
|
||||
// if pattern.characters.count == 0 {
|
||||
// return self.flatFiles
|
||||
// .map { fileItems in
|
||||
// return fileItems.concurrentChunkMap(200) { ScoredFileItem(score: 0, url: $0.url) }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// let useFullPath = pattern.containsString("/")
|
||||
// let cwdPath = self.cwd.path! + "/"
|
||||
//
|
||||
// let result: Observable<[ScoredFileItem]> = self.flatFiles
|
||||
// .map { fileItems in
|
||||
// return fileItems.concurrentChunkMap(200) { item in
|
||||
// let url = item.url
|
||||
// let target = useFullPath ? url.path!.stringByReplacingOccurrencesOfString(cwdPath, withString: "")
|
||||
// : url.lastPathComponent!
|
||||
//
|
||||
// return ScoredFileItem(score: Scorer.score(target, pattern: pattern), url: url)
|
||||
// }
|
||||
// }
|
||||
// NSLog("Flat map end: \(pattern)")
|
||||
//
|
||||
// return result
|
||||
// }
|
||||
// .doOnNext { [unowned self] items in
|
||||
// self.scoredItems.appendContentsOf(items)
|
||||
// self.sortedScoredItems = Array(self.scoredItems.sort(>)[0..<min(201, self.scoredItems.count)])
|
||||
// }
|
||||
// .observeOn(MainScheduler.instance)
|
||||
// .subscribe(onNext: { [unowned self] items in
|
||||
// self.fileView.reloadData()
|
||||
// })
|
||||
.addDisposableTo(self.disposeBag)
|
||||
}
|
||||
|
||||
override func addViews() {
|
||||
let searchField = self.searchField
|
||||
let progressIndicator = self.progressIndicator
|
||||
progressIndicator.indeterminate = true
|
||||
progressIndicator.displayedWhenStopped = false
|
||||
progressIndicator.style = .SpinningStyle
|
||||
progressIndicator.controlSize = .SmallControlSize
|
||||
|
||||
let fileView = self.fileView
|
||||
fileView.intercellSpacing = CGSize(width: 4, height: 4)
|
||||
@ -136,6 +87,7 @@ class OpenQuicklyWindowComponent: WindowComponent, NSWindowDelegate, NSTableView
|
||||
|
||||
let contentView = self.window.contentView!
|
||||
contentView.addSubview(searchField)
|
||||
contentView.addSubview(progressIndicator)
|
||||
contentView.addSubview(fileScrollView)
|
||||
contentView.addSubview(cwdControl)
|
||||
contentView.addSubview(countField)
|
||||
@ -144,6 +96,9 @@ class OpenQuicklyWindowComponent: WindowComponent, NSWindowDelegate, NSTableView
|
||||
searchField.autoPinEdgeToSuperviewEdge(.Right, withInset: 18)
|
||||
searchField.autoPinEdgeToSuperviewEdge(.Left, withInset: 18)
|
||||
|
||||
progressIndicator.autoAlignAxis(.Horizontal, toSameAxisOfView: searchField)
|
||||
progressIndicator.autoPinEdge(.Right, toEdge: .Right, ofView: searchField, withOffset: -4)
|
||||
|
||||
fileScrollView.autoPinEdge(.Top, toEdge: .Bottom, ofView: searchField, withOffset: 18)
|
||||
fileScrollView.autoPinEdge(.Right, toEdge: .Right, ofView: searchField)
|
||||
fileScrollView.autoPinEdge(.Left, toEdge: .Left, ofView: searchField)
|
||||
@ -161,73 +116,99 @@ class OpenQuicklyWindowComponent: WindowComponent, NSWindowDelegate, NSTableView
|
||||
override func subscription(source source: Observable<Any>) -> Disposable {
|
||||
return NopDisposable.instance
|
||||
}
|
||||
|
||||
func reloadFileView(withScoredItems items: [ScoredFileItem]) {
|
||||
self.fileViewItems = items
|
||||
self.fileView.reloadData()
|
||||
}
|
||||
|
||||
func startProgress() {
|
||||
self.progressIndicator.startAnimation(self)
|
||||
}
|
||||
|
||||
func endProgress() {
|
||||
self.progressIndicator.stopAnimation(self)
|
||||
}
|
||||
|
||||
func show(forMainWindow mainWindow: MainWindowComponent) {
|
||||
self.cwd = mainWindow.cwd
|
||||
let flatFiles = self.fileItemService.flatFileItems(ofUrl: self.cwd)
|
||||
.subscribeOn(self.userInitiatedScheduler)
|
||||
.replayAll()
|
||||
flatFiles.connect().addDisposableTo(self.flatFilesDisposeBag)
|
||||
|
||||
self.searchStream
|
||||
.subscribe(onNext: { [unowned self] pattern in
|
||||
self.pattern = pattern
|
||||
self.resetAndAddFilterOperation()
|
||||
})
|
||||
.addDisposableTo(self.perSessionDisposeBag)
|
||||
|
||||
flatFiles
|
||||
.subscribeOn(self.userInitiatedScheduler)
|
||||
.doOnNext{ [unowned self] items in
|
||||
self.scanCondition.lock()
|
||||
while self.pauseScan {
|
||||
self.scanCondition.wait()
|
||||
}
|
||||
self.scanCondition.unlock()
|
||||
|
||||
self.flatFileItems.appendContentsOf(items)
|
||||
self.resetAndAddFilterOperation()
|
||||
}
|
||||
.observeOn(MainScheduler.instance)
|
||||
.subscribe(onNext: { [unowned self] items in
|
||||
self.count += items.count
|
||||
self.countField.stringValue = "\(self.count) items"
|
||||
})
|
||||
.addDisposableTo(self.flatFilesDisposeBag)
|
||||
|
||||
self.flatFiles = flatFiles
|
||||
.addDisposableTo(self.perSessionDisposeBag)
|
||||
|
||||
self.show()
|
||||
self.searchField.becomeFirstResponder()
|
||||
}
|
||||
|
||||
private func resetAndAddFilterOperation() {
|
||||
self.filterOpQueue.cancelAllOperations()
|
||||
let op = OpenQuicklyFilterOperation(forOpenQuicklyWindow: self)
|
||||
self.filterOpQueue.addOperation(op)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - NSTableViewDataSource
|
||||
extension OpenQuicklyWindowComponent {
|
||||
|
||||
func numberOfRowsInTableView(_: NSTableView) -> Int {
|
||||
return self.sortedScoredItems.count
|
||||
return self.fileViewItems.count
|
||||
}
|
||||
|
||||
func tableView(tableView: NSTableView, viewForTableColumn tableColumn: NSTableColumn?, row: Int) -> NSView? {
|
||||
let url = self.sortedScoredItems[row].url
|
||||
let pathComps = url.pathComponents!
|
||||
let truncatedPathComps = pathComps[self.cwdPathCompsCount..<pathComps.count]
|
||||
let name = truncatedPathComps.last!
|
||||
let pathInfo = truncatedPathComps.dropLast().reverse().joinWithSeparator(" / ")
|
||||
|
||||
let result = NSMutableAttributedString(string: "\(name) — \(pathInfo)")
|
||||
result.addAttribute(NSForegroundColorAttributeName, value: NSColor.lightGrayColor(),
|
||||
range: NSRange(location:name.characters.count, length: pathInfo.characters.count + 3))
|
||||
|
||||
let cell = tableView.makeViewWithIdentifier("file-view-row", owner: self) as? ImageAndTextTableCell
|
||||
?? ImageAndTextTableCell(withIdentifier: "file-view-row")
|
||||
|
||||
cell.textField.attributedStringValue = result
|
||||
|
||||
func tableView(tableView: NSTableView, viewForTableColumn _: NSTableColumn?, row: Int) -> NSView? {
|
||||
let cachedCell = tableView.makeViewWithIdentifier("file-view-row", owner: self)
|
||||
let cell = cachedCell as? ImageAndTextTableCell ?? ImageAndTextTableCell(withIdentifier: "file-view-row")
|
||||
|
||||
let url = self.fileViewItems[row].url
|
||||
cell.textField.attributedStringValue = self.rowText(forUrl: url)
|
||||
cell.imageView.image = self.fileItemService.icon(forUrl: url)
|
||||
|
||||
return cell
|
||||
}
|
||||
|
||||
// func tableView(_: NSTableView, objectValueForTableColumn _: NSTableColumn?, row: Int) -> AnyObject? {
|
||||
// let url = self.sortedScoredItems[row].url
|
||||
// let pathComps = self.sortedScoredItems[row].url.pathComponents!
|
||||
// let truncatedPathComps = pathComps[self.cwdPathCompsCount..<pathComps.count]
|
||||
// let name = truncatedPathComps.last!
|
||||
// let pathInfo = truncatedPathComps.dropLast().reverse().joinWithSeparator("/")
|
||||
//
|
||||
// let textAttachment = NSTextAttachment()
|
||||
// textAttachment.image = self.fileItemService.icon(forUrl: url)
|
||||
//
|
||||
// let result: NSMutableAttributedString = NSAttributedString(attachment: textAttachment).mutableCopy() as! NSMutableAttributedString
|
||||
// result.mutableString.appendString("\(name) — \(pathInfo)")
|
||||
// result.addAttribute(NSForegroundColorAttributeName, value: NSColor.lightGrayColor(),
|
||||
// range: NSRange(location:name.characters.count, length: pathInfo.characters.count + 3))
|
||||
//
|
||||
// return result
|
||||
// }
|
||||
private func rowText(forUrl url: NSURL) -> NSAttributedString {
|
||||
let pathComps = url.pathComponents!
|
||||
let truncatedPathComps = pathComps[self.cwdPathCompsCount..<pathComps.count]
|
||||
let name = truncatedPathComps.last!
|
||||
|
||||
if truncatedPathComps.dropLast().isEmpty {
|
||||
return NSMutableAttributedString(string: name)
|
||||
}
|
||||
|
||||
let rowText: NSMutableAttributedString
|
||||
let pathInfo = truncatedPathComps.dropLast().reverse().joinWithSeparator(" / ")
|
||||
rowText = NSMutableAttributedString(string: "\(name) — \(pathInfo)")
|
||||
rowText.addAttribute(NSForegroundColorAttributeName,
|
||||
value: NSColor.lightGrayColor(),
|
||||
range: NSRange(location:name.characters.count,
|
||||
length: pathInfo.characters.count + 3))
|
||||
|
||||
return rowText
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - NSTableViewDelegate
|
||||
@ -236,22 +217,23 @@ extension OpenQuicklyWindowComponent {
|
||||
func tableViewSelectionDidChange(_: NSNotification) {
|
||||
// NSLog("\(#function): selection changed")
|
||||
}
|
||||
|
||||
// func tableView(tableView: NSTableView, heightOfRow row: Int) -> CGFloat {
|
||||
// return 34
|
||||
// }
|
||||
}
|
||||
|
||||
// MARK: - NSWindowDelegate
|
||||
extension OpenQuicklyWindowComponent {
|
||||
|
||||
func windowWillClose(notification: NSNotification) {
|
||||
self.flatFilesDisposeBag = DisposeBag()
|
||||
self.flatFiles = Observable.empty()
|
||||
self.filterOpQueue.cancelAllOperations()
|
||||
|
||||
self.endProgress()
|
||||
|
||||
self.perSessionDisposeBag = DisposeBag()
|
||||
self.pauseScan = false
|
||||
self.count = 0
|
||||
|
||||
self.scoredItems = []
|
||||
self.sortedScoredItems = []
|
||||
|
||||
self.pattern = ""
|
||||
self.flatFileItems = []
|
||||
self.fileViewItems = []
|
||||
|
||||
self.searchField.stringValue = ""
|
||||
self.countField.stringValue = "0 items"
|
||||
|
Loading…
Reference in New Issue
Block a user