diff --git a/VimR/AppearancePref.swift b/VimR/AppearancePref.swift index 76561b04..aa44374d 100644 --- a/VimR/AppearancePref.swift +++ b/VimR/AppearancePref.swift @@ -13,8 +13,9 @@ class AppearancePref: PrefPane, NSComboBoxDelegate, NSControlTextEditingDelegate enum Action { - case setUsesLigatures(Bool) case setUsesColorscheme(Bool) + case setShowsFileIcon(Bool) + case setUsesLigatures(Bool) case setFont(NSFont) case setLinespacing(CGFloat) } @@ -38,6 +39,7 @@ class AppearancePref: PrefPane, NSComboBoxDelegate, NSControlTextEditingDelegate self.linespacing = state.mainWindowTemplate.appearance.linespacing self.usesLigatures = state.mainWindowTemplate.appearance.usesLigatures self.usesColorscheme = state.mainWindowTemplate.appearance.usesTheme + self.showsFileIcon = state.mainWindowTemplate.appearance.showsFileIcon super.init(frame: .zero) @@ -49,16 +51,22 @@ class AppearancePref: PrefPane, NSComboBoxDelegate, NSControlTextEditingDelegate .subscribe(onNext: { state in let appearance = state.mainWindowTemplate.appearance - if self.font != appearance.font - || self.linespacing != appearance.linespacing - || self.usesLigatures != appearance.usesLigatures { - self.font = appearance.font - self.linespacing = appearance.linespacing - self.usesLigatures = appearance.usesLigatures - self.usesColorscheme = appearance.usesTheme + guard self.font != appearance.font + || self.linespacing != appearance.linespacing + || self.usesLigatures != appearance.usesLigatures + || self.usesColorscheme != appearance.usesTheme + || self.showsFileIcon != appearance.showsFileIcon else { - self.updateViews() + return } + + self.font = appearance.font + self.linespacing = appearance.linespacing + self.usesLigatures = appearance.usesLigatures + self.usesColorscheme = appearance.usesTheme + self.showsFileIcon = appearance.showsFileIcon + + self.updateViews() }) .disposed(by: self.disposeBag) } @@ -72,8 +80,10 @@ class AppearancePref: PrefPane, NSComboBoxDelegate, NSControlTextEditingDelegate fileprivate var linespacing: CGFloat fileprivate var usesLigatures: Bool fileprivate var usesColorscheme: Bool + fileprivate var showsFileIcon: Bool fileprivate let colorschemeCheckbox = NSButton(forAutoLayout: ()) + fileprivate let fileIconCheckbox = NSButton(forAutoLayout: ()) fileprivate let sizes = [9, 10, 11, 12, 13, 14, 16, 18, 24, 36, 48, 64] fileprivate let sizeCombo = NSComboBox(forAutoLayout: ()) @@ -107,6 +117,16 @@ class AppearancePref: PrefPane, NSComboBoxDelegate, NSControlTextEditingDelegate "used to render tools, e.g. the file browser." ) + let fileIcon = self.fileIconCheckbox + self.configureCheckbox(button: fileIcon, + title: "Show file icons", + action: #selector(AppearancePref.fileIconAction(_:))) + + let fileIconInfo = self.infoTextField( + markdown: "In case the selected `colorscheme` does not play well with the file icons \n" + + "in the file browser and the buffer list, you can turn them off." + ) + let fontTitle = self.titleTextField(title: "Default Font:") let fontPopup = self.fontPopup @@ -159,6 +179,8 @@ class AppearancePref: PrefPane, NSComboBoxDelegate, NSControlTextEditingDelegate self.addSubview(useColorscheme) self.addSubview(useColorschemeInfo) + self.addSubview(fileIcon) + self.addSubview(fileIconInfo) self.addSubview(fontTitle) self.addSubview(fontPopup) self.addSubview(sizeCombo) @@ -176,10 +198,16 @@ class AppearancePref: PrefPane, NSComboBoxDelegate, NSControlTextEditingDelegate useColorschemeInfo.autoPinEdge(.top, to: .bottom, of: useColorscheme, withOffset: 5) useColorschemeInfo.autoPinEdge(.left, to: .left, of: useColorscheme) + fileIcon.autoPinEdge(.left, to: .right, of: fontTitle, withOffset: 5) + fileIcon.autoPinEdge(.top, to: .bottom, of: useColorschemeInfo, withOffset: 18) + + fileIconInfo.autoPinEdge(.top, to: .bottom, of: fileIcon, withOffset: 5) + fileIconInfo.autoPinEdge(.left, to: .left, of: fileIcon) + fontTitle.autoPinEdge(toSuperviewEdge: .left, withInset: 18, relation: .greaterThanOrEqual) fontTitle.autoAlignAxis(.baseline, toSameAxisOf: fontPopup) - fontPopup.autoPinEdge(.top, to: .bottom, of: useColorschemeInfo, withOffset: 18) + fontPopup.autoPinEdge(.top, to: .bottom, of: fileIconInfo, withOffset: 18) fontPopup.autoPinEdge(.left, to: .right, of: fontTitle, withOffset: 5) fontPopup.autoSetDimension(.width, toSize: 240) @@ -218,6 +246,7 @@ class AppearancePref: PrefPane, NSComboBoxDelegate, NSControlTextEditingDelegate self.ligatureCheckbox.boolState = self.usesLigatures self.previewArea.font = self.font self.colorschemeCheckbox.boolState = self.usesColorscheme + self.fileIconCheckbox.boolState = self.showsFileIcon if self.usesLigatures { self.previewArea.useAllLigatures(self) @@ -234,6 +263,10 @@ extension AppearancePref { self.emit(.setUsesColorscheme(sender.boolState)) } + func fileIconAction(_ sender: NSButton) { + self.emit(.setShowsFileIcon(sender.boolState)) + } + func usesLigaturesAction(_ sender: NSButton) { self.emit(.setUsesLigatures(sender.boolState)) } diff --git a/VimR/AppearancePrefReducer.swift b/VimR/AppearancePrefReducer.swift index 57e775a7..8376069e 100644 --- a/VimR/AppearancePrefReducer.swift +++ b/VimR/AppearancePrefReducer.swift @@ -15,12 +15,15 @@ class AppearancePrefReducer { switch pair.action { - case let .setUsesLigatures(value): - appearance.usesLigatures = value - case let .setUsesColorscheme(value): appearance.usesTheme = value + case let .setShowsFileIcon(value): + appearance.showsFileIcon = value + + case let .setUsesLigatures(value): + appearance.usesLigatures = value + case let .setFont(font): appearance.font = font diff --git a/VimR/FileOutlineView.swift b/VimR/FileOutlineView.swift index eb5c5831..152794bf 100644 --- a/VimR/FileOutlineView.swift +++ b/VimR/FileOutlineView.swift @@ -26,6 +26,7 @@ class FileOutlineView: NSOutlineView, self.isShowHidden = state.fileBrowserShowHidden self.usesTheme = state.appearance.usesTheme + self.showsFileIcon = state.appearance.showsFileIcon super.init(frame: .zero) NSOutlineView.configure(toStandard: self) @@ -79,6 +80,7 @@ class FileOutlineView: NSOutlineView, return } + self.showsFileIcon = state.appearance.showsFileIcon self.isShowHidden = state.fileBrowserShowHidden self.lastFileSystemUpdateMark = state.lastFileSystemUpdate.mark self.root = FileBrowserItem(state.cwd) @@ -114,7 +116,7 @@ class FileOutlineView: NSOutlineView, fileprivate var lastFileSystemUpdateMark = Token() fileprivate var usesTheme: Bool fileprivate var lastThemeMark = Token() - + fileprivate var showsFileIcon: Bool fileprivate var cwd: URL { return self.root.url @@ -143,6 +145,10 @@ class FileOutlineView: NSOutlineView, return true } + if self.showsFileIcon != state.appearance.showsFileIcon { + return true + } + if state.cwd != self.cwd { return true } @@ -376,12 +382,16 @@ extension FileOutlineView { let cell = (self.make(withIdentifier: "file-cell-view", owner: self) as? ThemedTableCell)?.reset() ?? ThemedTableCell(withIdentifier: "file-cell-view") + cell.isDir = fileBrowserItem.isDir cell.text = fileBrowserItem.url.lastPathComponent + + guard self.showsFileIcon else { + return cell + } + let icon = FileUtils.icon(forUrl: fileBrowserItem.url) cell.image = fileBrowserItem.isHidden ? icon?.tinting(with: NSColor.white.withAlphaComponent(0.4)) : icon - cell.isDir = fileBrowserItem.isDir - return cell } diff --git a/VimR/OpenedFileList.swift b/VimR/OpenedFileList.swift index d82e62b8..07bf62fb 100644 --- a/VimR/OpenedFileList.swift +++ b/VimR/OpenedFileList.swift @@ -30,6 +30,7 @@ class OpenedFileList: NSView, self.genericIcon = FileUtils.icon(forType: "public.data") self.usesTheme = state.appearance.usesTheme + self.showsFileIcon = state.appearance.showsFileIcon super.init(frame: .zero) @@ -54,10 +55,11 @@ class OpenedFileList: NSView, self.usesTheme = state.appearance.usesTheme let buffers = state.buffers.removingDuplicatesPreservingFromBeginning() - if self.buffers == buffers && !themeChanged { + if self.buffers == buffers && !themeChanged && self.showsFileIcon == state.appearance.showsFileIcon { return } + self.showsFileIcon = state.appearance.showsFileIcon self.buffers = buffers self.bufferList.reloadData() self.adjustFileViewWidth() @@ -71,6 +73,7 @@ class OpenedFileList: NSView, fileprivate let uuid: String fileprivate var usesTheme: Bool fileprivate var lastThemeMark = Token() + fileprivate var showsFileIcon: Bool fileprivate let bufferList = NSTableView.standardTableView() fileprivate let genericIcon: NSImage @@ -144,6 +147,11 @@ extension OpenedFileList { let buffer = self.buffers[row] cell.attributedText = self.text(for: buffer) + + guard self.showsFileIcon else { + return cell + } + cell.image = self.icon(for: buffer) return cell diff --git a/VimR/States.swift b/VimR/States.swift index 0a78fe39..38dc84bf 100644 --- a/VimR/States.swift +++ b/VimR/States.swift @@ -168,6 +168,8 @@ struct AppearanceState: SerializableState { var usesTheme = true var theme = Marked(Theme.default) + var showsFileIcon = true + init() { } diff --git a/VimR/ThemedTableSubviews.swift b/VimR/ThemedTableSubviews.swift index ec600a12..5f885192 100644 --- a/VimR/ThemedTableSubviews.swift +++ b/VimR/ThemedTableSubviews.swift @@ -77,6 +77,7 @@ class ThemedTableCell: NSTableCellView { set { self.textField?.attributedStringValue = newValue + self.addTextField() } } @@ -87,6 +88,7 @@ class ThemedTableCell: NSTableCellView { set { self.textField?.stringValue = newValue + self.addTextField() } } @@ -97,6 +99,24 @@ class ThemedTableCell: NSTableCellView { set { self.imageView?.image = newValue + + self.removeAllSubviews() + + let textField = self._textField + let imageView = self._imageView + + self.addSubview(textField) + self.addSubview(imageView) + + imageView.autoPinEdge(toSuperviewEdge: .top, withInset: 2) + imageView.autoPinEdge(toSuperviewEdge: .left, withInset: 2) + imageView.autoSetDimension(.width, toSize: 16) + imageView.autoSetDimension(.height, toSize: 16) + + textField.autoPinEdge(toSuperviewEdge: .top, withInset: 2) + textField.autoPinEdge(toSuperviewEdge: .right, withInset: 2) + textField.autoPinEdge(toSuperviewEdge: .bottom, withInset: 2) + textField.autoPinEdge(.left, to: .right, of: imageView, withOffset: 4) } } @@ -116,21 +136,6 @@ class ThemedTableCell: NSTableCellView { textField.isEditable = false textField.usesSingleLineMode = true textField.drawsBackground = false - - let imageView = self._imageView - - self.addSubview(textField) - self.addSubview(imageView) - - imageView.autoPinEdge(toSuperviewEdge: .top, withInset: 2) - imageView.autoPinEdge(toSuperviewEdge: .left, withInset: 2) - imageView.autoSetDimension(.width, toSize: 16) - imageView.autoSetDimension(.height, toSize: 16) - - textField.autoPinEdge(toSuperviewEdge: .top, withInset: 2) - textField.autoPinEdge(toSuperviewEdge: .right, withInset: 2) - textField.autoPinEdge(toSuperviewEdge: .bottom, withInset: 2) - textField.autoPinEdge(.left, to: .right, of: imageView, withOffset: 4) } func reset() -> ThemedTableCell { @@ -138,9 +143,20 @@ class ThemedTableCell: NSTableCellView { self.image = nil self.isDir = false + self.removeAllSubviews() + return self } + fileprivate func addTextField() { + let textField = self._textField + + textField.removeFromSuperview() + self.addSubview(textField) + + textField.autoPinEdgesToSuperviewEdges(with: EdgeInsets(top: 2, left: 2, bottom: 2, right: 2)) + } + fileprivate let _textField = NSTextField(forAutoLayout: ()) fileprivate let _imageView = NSImageView(forAutoLayout: ())