1
1
mirror of https://github.com/qvacua/vimr.git synced 2024-12-01 10:02:36 +03:00

Render items using bindings

This commit is contained in:
Tae Won Ha 2019-02-24 16:54:04 +01:00
parent bbf83c7856
commit 16c6eb8c86
No known key found for this signature in database
GPG Key ID: E40743465B5B8B44
3 changed files with 193 additions and 17 deletions

View File

@ -181,7 +181,9 @@ extension FileBrowser {
return return
} }
#if NOPE
self.fileView.select(url) self.fileView.select(url)
#endif
} }
@objc func refreshAction(_ sender: Any?) { @objc func refreshAction(_ sender: Any?) {

View File

@ -10,12 +10,186 @@ import RxSwift
class FileOutlineView: NSOutlineView, class FileOutlineView: NSOutlineView,
UiComponent, UiComponent,
NSOutlineViewDataSource,
NSOutlineViewDelegate, NSOutlineViewDelegate,
ThemedView { ThemedView {
typealias StateType = MainWindow.State typealias StateType = MainWindow.State
@objc dynamic var content = [Node]()
private(set) var theme = Theme.default
required init(
source: Observable<StateType>,
emitter: ActionEmitter,
state: StateType
) {
self.emit = emitter.typedEmit()
self.uuid = state.uuid
self.root = Node(url: state.cwd)
super.init(frame: .zero)
NSOutlineView.configure(toStandard: self)
self.delegate = self
guard Bundle.main.loadNibNamed(
NSNib.Name("FileBrowserMenu"),
owner: self,
topLevelObjects: nil
) else {
NSLog("WARN: FileBrowserMenu.xib could not be loaded")
return
}
self.treeController.childrenKeyPath = "children"
self.treeController.leafKeyPath = "isLeaf"
self.treeController.countKeyPath = "childrenCount"
self.treeController.objectClass = Node.self
self.treeController.avoidsEmptySelection = false
self.treeController.sortDescriptors = [
NSSortDescriptor(key: "isLeaf", ascending: true), // Folders first,
NSSortDescriptor(key: "displayName", ascending: true) // then, name
]
self.treeController.bind(.contentArray, to: self, withKeyPath: "content")
self.bind(.content, to: self.treeController, withKeyPath: "arrangedObjects")
self.bind(.selectionIndexPaths,
to: self.treeController,
withKeyPath: "selectionIndexPaths")
self.reloadRoot()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private let emit: (UuidAction<FileBrowser.Action>) -> Void
private let disposeBag = DisposeBag()
private let uuid: String
private var root: Node
private let treeController = NSTreeController()
private func childNodes(for node: Node) -> [Node] {
if node.isChildrenScanned {
return node.children ?? []
}
return FileUtils.directDescendants(of: node.url).map { Node(url: $0) }
}
private func reloadRoot() {
let children = self.childNodes(for: self.root)
self.root.children = children
self.content.append(contentsOf: children)
self.adjustColumnWidth()
}
private func adjustColumnWidth() {
let indent = self.indentationPerLevel
var maxRow = (0, CGFloat(20.0))
for i in (0..<self.numberOfRows) {
guard let width = (self.view(
atColumn: 0, row: i, makeIfNecessary: true
) as? ThemedTableCell)?.fittingSize.width else {
stdoutLog.error("Could not convert to ThemedTableCell!")
return
}
let level = CGFloat(self.level(forRow: i))
maxRow = (i, max(maxRow.1, level * indent + width))
}
self.tableColumns[0].width = maxRow.1 + CGFloat(30)
}
}
// MARK: - NSOutlineViewDelegate
extension FileOutlineView {
func outlineView(
_ outlineView: NSOutlineView,
rowViewForItem item: Any
) -> NSTableRowView? {
return self.makeView(
withIdentifier: NSUserInterfaceItemIdentifier("file-row-view"),
owner: self
) as? ThemedTableRow ?? ThemedTableRow(withIdentifier: "file-row-view",
themedView: self)
}
func outlineView(
_: NSOutlineView,
viewFor tableColumn: NSTableColumn?,
item: Any
) -> NSView? {
guard let treeNode = item as? NSTreeNode,
let node = treeNode.representedObject as? Node else {
return nil
}
let cellView = self.makeView(
withIdentifier: NSUserInterfaceItemIdentifier("file-cell-view"),
owner: self
) as? ThemedTableCell ?? ThemedTableCell(withIdentifier: "file-cell-view")
cellView.isDir = node.isDir
cellView.text = node.displayName
let icon = FileUtils.icon(forUrl: node.url)
cellView.image = node.isHidden
? icon?.tinting(with: NSColor.white.withAlphaComponent(0.4))
: icon
return cellView
}
func outlineView(_: NSOutlineView, heightOfRowByItem item: Any) -> CGFloat {
return 20
}
}
class Node: NSObject {
@objc dynamic var url: URL
@objc dynamic var isLeaf: Bool
@objc dynamic var isHidden: Bool
@objc dynamic var children: [Node]?
@objc dynamic var childrenCount: Int {
return self.children?.count ?? -1
}
@objc dynamic var displayName: String {
return self.url.lastPathComponent
}
var isDir: Bool {
return !self.isLeaf
}
var isChildrenScanned = false
override var hash: Int {
return self.url.hashValue
}
init(url: URL) {
self.url = url
self.isLeaf = !url.isDir
self.isHidden = url.isHidden
}
}
class FileOutlineViewOld: NSOutlineView,
UiComponent,
NSOutlineViewDataSource,
NSOutlineViewDelegate,
ThemedView {
typealias StateType = MainWindow.State
private(set) var theme = Theme.default private(set) var theme = Theme.default
required init( required init(
@ -53,7 +227,7 @@ class FileOutlineView: NSOutlineView,
// in the background... Dunno why it worked before the redesign... -_- // in the background... Dunno why it worked before the redesign... -_-
self.menu?.items.forEach { $0.target = self } self.menu?.items.forEach { $0.target = self }
self.doubleAction = #selector(FileOutlineView.doubleClickAction) self.doubleAction = #selector(FileOutlineViewOld.doubleClickAction)
source source
.filter { !self.shouldReloadData(for: $0) } .filter { !self.shouldReloadData(for: $0) }
@ -294,7 +468,7 @@ class FileOutlineView: NSOutlineView,
} }
// MARK: - NSOutlineViewDataSource // MARK: - NSOutlineViewDataSource
extension FileOutlineView { extension FileOutlineViewOld {
private func scanChildrenIfNecessary(_ fileBrowserItem: FileBrowserItem) { private func scanChildrenIfNecessary(_ fileBrowserItem: FileBrowserItem) {
guard fileBrowserItem.isChildrenScanned == false else { guard fileBrowserItem.isChildrenScanned == false else {
@ -413,7 +587,7 @@ extension FileOutlineView {
} }
// MARK: - NSOutlineViewDelegate // MARK: - NSOutlineViewDelegate
extension FileOutlineView { extension FileOutlineViewOld {
func outlineView( func outlineView(
_ outlineView: NSOutlineView, rowViewForItem item: Any _ outlineView: NSOutlineView, rowViewForItem item: Any
@ -441,7 +615,7 @@ extension FileOutlineView {
} }
// MARK: - Actions // MARK: - Actions
extension FileOutlineView { extension FileOutlineViewOld {
@IBAction func doubleClickAction(_: Any?) { @IBAction func doubleClickAction(_: Any?) {
guard let item = self.clickedItem as? FileBrowserItem else { guard let item = self.clickedItem as? FileBrowserItem else {
@ -517,7 +691,7 @@ extension FileOutlineView {
} }
// MARK: - NSUserInterfaceValidations // MARK: - NSUserInterfaceValidations
extension FileOutlineView { extension FileOutlineViewOld {
override func validateUserInterfaceItem( override func validateUserInterfaceItem(
_ item: NSValidatedUserInterfaceItem _ item: NSValidatedUserInterfaceItem
@ -535,7 +709,7 @@ extension FileOutlineView {
} }
// MARK: - NSView // MARK: - NSView
extension FileOutlineView { extension FileOutlineViewOld {
override func keyDown(with event: NSEvent) { override func keyDown(with event: NSEvent) {
guard let char = event.charactersIgnoringModifiers?.first else { guard let char = event.charactersIgnoringModifiers?.first else {

View File

@ -57,16 +57,16 @@ class ThemedTableCell: NSTableCellView {
static let font = NSFont.systemFont(ofSize: 12) static let font = NSFont.systemFont(ofSize: 12)
static let widthWithoutText = CGFloat(2 + 16 + 4 + 2) static let widthWithoutText = CGFloat(2 + 16 + 4 + 2)
static func width(with text: String) -> CGFloat { // static func width(with text: String) -> CGFloat {
let attrStr = NSAttributedString(string: text, attributes: [NSAttributedString.Key.font: ThemedTableCell.font]) // let attrStr = NSAttributedString(string: text, attributes: [NSAttributedString.Key.font: ThemedTableCell.font])
//
return self.widthWithoutText + attrStr.size().width // return self.widthWithoutText + attrStr.size().width
} // }
//
override var intrinsicContentSize: CGSize { // override var intrinsicContentSize: CGSize {
return CGSize(width: ThemedTableCell.widthWithoutText + self._textField.intrinsicContentSize.width, // return CGSize(width: ThemedTableCell.widthWithoutText + self._textField.intrinsicContentSize.width,
height: max(self._textField.intrinsicContentSize.height, 16)) // height: max(self._textField.intrinsicContentSize.height, 16))
} // }
var isDir = false var isDir = false