Cleanup.
This commit is contained in:
@@ -19,6 +19,21 @@ class ProgramsTableViewCell: NSTableCellView {
|
|||||||
|
|
||||||
private(set) var isEditing = false
|
private(set) var isEditing = false
|
||||||
|
|
||||||
|
public var indexLabel: NSTextField = {
|
||||||
|
let field = NSTextField(labelWithString: "-")
|
||||||
|
field.alignment = .center
|
||||||
|
|
||||||
|
// field.drawsBackground = true
|
||||||
|
// field.backgroundColor = NSColor.green.withAlphaComponent(0.2)
|
||||||
|
|
||||||
|
field.textColor = NSColor.secondaryLabelColor
|
||||||
|
field.cell?.lineBreakMode = .byTruncatingTail
|
||||||
|
field.font = NSFont.systemFont(ofSize: NSFontDescriptor.preferredFontDescriptor(forTextStyle: .caption1).pointSize, weight: .bold)
|
||||||
|
field.translatesAutoresizingMaskIntoConstraints = false
|
||||||
|
return field
|
||||||
|
}()
|
||||||
|
|
||||||
|
|
||||||
public var appIconImage: NSImageView = {
|
public var appIconImage: NSImageView = {
|
||||||
let image = NSImageView()
|
let image = NSImageView()
|
||||||
image.image = NSWorkspace.shared.icon(forFile: Bundle.main.bundlePath)
|
image.image = NSWorkspace.shared.icon(forFile: Bundle.main.bundlePath)
|
||||||
@@ -28,38 +43,51 @@ class ProgramsTableViewCell: NSTableCellView {
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
public var titleField: NSTextField = {
|
public var titleField: NSTextField = {
|
||||||
let field = NSTextField(labelWithString: "")
|
let field = NSTextField()
|
||||||
field.textColor = NSColor.secondaryLabelColor
|
field.isBordered = false
|
||||||
|
field.drawsBackground = false
|
||||||
field.lineBreakMode = .byTruncatingTail
|
field.lineBreakMode = .byTruncatingTail
|
||||||
|
field.textColor = NSColor.secondaryLabelColor
|
||||||
field.translatesAutoresizingMaskIntoConstraints = false
|
field.translatesAutoresizingMaskIntoConstraints = false
|
||||||
return field
|
return field
|
||||||
}()
|
}()
|
||||||
|
|
||||||
public var progPathLabel: NSTextField = {
|
public var progPathLabel: NSTextField = {
|
||||||
let textField = NSTextField(labelWithString: "")
|
let field = NSTextField()
|
||||||
textField.cell?.lineBreakMode = .byTruncatingTail
|
field.isBordered = false
|
||||||
textField.font = NSFont.systemFont(ofSize: NSFontDescriptor.preferredFontDescriptor(forTextStyle: .caption1).pointSize, weight: .medium)
|
field.drawsBackground = false
|
||||||
textField.translatesAutoresizingMaskIntoConstraints = false
|
field.lineBreakMode = .byTruncatingTail
|
||||||
return textField
|
field.font = NSFont.systemFont(ofSize: NSFontDescriptor.preferredFontDescriptor(forTextStyle: .caption1).pointSize, weight: .medium)
|
||||||
|
field.translatesAutoresizingMaskIntoConstraints = false
|
||||||
|
return field
|
||||||
}()
|
}()
|
||||||
|
|
||||||
override init(frame frameRect: NSRect) {
|
override init(frame frameRect: NSRect) {
|
||||||
super.init(frame: frameRect)
|
super.init(frame: frameRect)
|
||||||
|
|
||||||
|
// wantsLayer = true
|
||||||
|
// layer?.backgroundColor = NSColor.yellow.withAlphaComponent(0.2).cgColor
|
||||||
|
|
||||||
|
addSubview(indexLabel)
|
||||||
addSubview(appIconImage)
|
addSubview(appIconImage)
|
||||||
addSubview(titleField)
|
addSubview(titleField)
|
||||||
addSubview(progPathLabel)
|
addSubview(progPathLabel)
|
||||||
|
|
||||||
|
// indexLabel.setContentHuggingPriority(.required, for: .horizontal)
|
||||||
NSLayoutConstraint.activate([
|
NSLayoutConstraint.activate([
|
||||||
|
indexLabel.widthAnchor.constraint(equalToConstant: 25),
|
||||||
|
indexLabel.centerYAnchor.constraint(equalTo: centerYAnchor),
|
||||||
|
indexLabel.leadingAnchor.constraint(equalTo: leadingAnchor, constant: ViewConstants.spacing5),
|
||||||
|
|
||||||
appIconImage.widthAnchor.constraint(equalToConstant: 40),
|
appIconImage.widthAnchor.constraint(equalToConstant: 40),
|
||||||
appIconImage.heightAnchor.constraint(equalToConstant: 40),
|
appIconImage.heightAnchor.constraint(equalToConstant: 40),
|
||||||
appIconImage.topAnchor.constraint(equalTo: topAnchor),
|
appIconImage.topAnchor.constraint(equalTo: topAnchor),
|
||||||
appIconImage.bottomAnchor.constraint(equalTo: bottomAnchor),
|
appIconImage.bottomAnchor.constraint(equalTo: bottomAnchor),
|
||||||
appIconImage.leadingAnchor.constraint(equalTo: leadingAnchor, constant: ViewConstants.spacing5),
|
appIconImage.leadingAnchor.constraint(equalTo: indexLabel.trailingAnchor),
|
||||||
|
|
||||||
titleField.topAnchor.constraint(equalTo: appIconImage.topAnchor, constant: ViewConstants.spacing2),
|
titleField.topAnchor.constraint(equalTo: appIconImage.topAnchor, constant: ViewConstants.spacing2),
|
||||||
titleField.leadingAnchor.constraint(equalTo: appIconImage.trailingAnchor, constant: ViewConstants.spacing5),
|
titleField.leadingAnchor.constraint(equalTo: appIconImage.trailingAnchor, constant: ViewConstants.spacing5),
|
||||||
titleField.trailingAnchor.constraint(equalTo: trailingAnchor),
|
titleField.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -ViewConstants.spacing5),
|
||||||
|
|
||||||
progPathLabel.topAnchor.constraint(equalTo: titleField.bottomAnchor),
|
progPathLabel.topAnchor.constraint(equalTo: titleField.bottomAnchor),
|
||||||
progPathLabel.leadingAnchor.constraint(equalTo: titleField.leadingAnchor),
|
progPathLabel.leadingAnchor.constraint(equalTo: titleField.leadingAnchor),
|
||||||
|
|||||||
@@ -1,23 +1,17 @@
|
|||||||
import AppKit
|
import AppKit
|
||||||
import Carbon
|
import Carbon
|
||||||
|
|
||||||
// NOTE: This is the corner radius of the backgrounView view that acts as
|
// NOTE: This is the corner radius of the backgrounView view that acts as a window frame and an NSViewController's view that clips all
|
||||||
// a window frame and an NSViewController's view that clips all
|
|
||||||
// elements inside of it.
|
// elements inside of it.
|
||||||
fileprivate let windowCornerRadius = 15.0
|
fileprivate let windowCornerRadius = 15.0
|
||||||
|
|
||||||
struct ProgramWeighted {
|
fileprivate let maxItems = 20
|
||||||
let program: Program
|
|
||||||
let weight: Int
|
|
||||||
}
|
|
||||||
|
|
||||||
fileprivate let maxItems = 10
|
|
||||||
|
|
||||||
class SearchViewController: NSViewController, NSTextFieldDelegate, NSPopoverDelegate, NSTableViewDataSource, NSTableViewDelegate {
|
class SearchViewController: NSViewController, NSTextFieldDelegate, NSPopoverDelegate, NSTableViewDataSource, NSTableViewDelegate {
|
||||||
private var keyboardEvents: EventMonitor?
|
private var keyboardEvents: EventMonitor?
|
||||||
|
|
||||||
private var listIndex = 0
|
private var listIndex = 0
|
||||||
private var programsList: [Program] = Array(repeating: Program(), count: maxItems)
|
private var programsList: [Program] = []
|
||||||
private var programsListCells: [ProgramsTableViewCell] = []
|
private var programsListCells: [ProgramsTableViewCell] = []
|
||||||
|
|
||||||
private var programsTableViewSelection = 0
|
private var programsTableViewSelection = 0
|
||||||
@@ -99,7 +93,8 @@ class SearchViewController: NSViewController, NSTextFieldDelegate, NSPopoverDele
|
|||||||
private var programsTableView: ProgramsTableView = {
|
private var programsTableView: ProgramsTableView = {
|
||||||
let table = ProgramsTableView()
|
let table = ProgramsTableView()
|
||||||
|
|
||||||
table.style = NSTableView.Style.plain
|
table.style = .plain
|
||||||
|
table.intercellSpacing = NSSize.zero
|
||||||
table.backgroundColor = .clear
|
table.backgroundColor = .clear
|
||||||
table.usesAutomaticRowHeights = true
|
table.usesAutomaticRowHeights = true
|
||||||
|
|
||||||
@@ -166,15 +161,20 @@ class SearchViewController: NSViewController, NSTextFieldDelegate, NSPopoverDele
|
|||||||
override func viewDidLoad() {
|
override func viewDidLoad() {
|
||||||
super.viewDidLoad()
|
super.viewDidLoad()
|
||||||
|
|
||||||
// NOTE: This needs removeObserver on deinit?
|
// NOTE: This needs removeObserver on deinit? Well, technically we don't care because this view controller will exist throughout
|
||||||
|
// the whole life of the program. When the program gets killed, the OS will clear this.
|
||||||
DistributedNotificationCenter.default.addObserver(self, selector: #selector(osThemeChanged(sender:)), name: NSNotification.Name(rawValue: "AppleInterfaceThemeChangedNotification"), object: nil)
|
DistributedNotificationCenter.default.addObserver(self, selector: #selector(osThemeChanged(sender:)), name: NSNotification.Name(rawValue: "AppleInterfaceThemeChangedNotification"), object: nil)
|
||||||
|
|
||||||
// Initialize an array of reusable cells.
|
// Initialize an array of programs and reusable cells.
|
||||||
for _ in 0..<maxItems {
|
for i in 0..<maxItems {
|
||||||
programsListCells.append(ProgramsTableViewCell())
|
programsList.append(Program())
|
||||||
|
|
||||||
|
let cell = ProgramsTableViewCell()
|
||||||
|
cell.indexLabel.stringValue = "\(i+1)"
|
||||||
|
programsListCells.append(cell)
|
||||||
}
|
}
|
||||||
|
|
||||||
updateViewsBasedOnTheme()
|
updateViewsBasedOnOSTheme()
|
||||||
|
|
||||||
view.wantsLayer = true
|
view.wantsLayer = true
|
||||||
view.layer?.backgroundColor = NSColor.clear.cgColor
|
view.layer?.backgroundColor = NSColor.clear.cgColor
|
||||||
@@ -192,6 +192,14 @@ class SearchViewController: NSViewController, NSTextFieldDelegate, NSPopoverDele
|
|||||||
modsContainsNone(in: modifiers) && key == kVK_DownArrow
|
modsContainsNone(in: modifiers) && key == kVK_DownArrow
|
||||||
{
|
{
|
||||||
controller.programsTableViewSelection += 1
|
controller.programsTableViewSelection += 1
|
||||||
|
} else if modsContains(keys: OSCtrl | OSCmd, in: modifiers) && key == kVK_ANSI_P ||
|
||||||
|
modsContains(keys: OSCmd, in: modifiers) && key == kVK_UpArrow
|
||||||
|
{
|
||||||
|
controller.programsTableViewSelection = 0
|
||||||
|
} else if modsContains(keys: OSCtrl | OSCmd, in: modifiers) && key == kVK_ANSI_N ||
|
||||||
|
modsContains(keys: OSCmd, in: modifiers) && key == kVK_DownArrow
|
||||||
|
{
|
||||||
|
controller.programsTableViewSelection = controller.listIndex-1
|
||||||
} else if modsContains(keys: OSCmd, in: modifiers) && isNumericalCode(key) {
|
} else if modsContains(keys: OSCmd, in: modifiers) && isNumericalCode(key) {
|
||||||
if key == kVK_ANSI_1 { controller.programsTableViewSelection = 0 }
|
if key == kVK_ANSI_1 { controller.programsTableViewSelection = 0 }
|
||||||
if key == kVK_ANSI_2 { controller.programsTableViewSelection = 1 }
|
if key == kVK_ANSI_2 { controller.programsTableViewSelection = 1 }
|
||||||
@@ -333,6 +341,9 @@ class SearchViewController: NSViewController, NSTextFieldDelegate, NSPopoverDele
|
|||||||
} else if commandSelector == #selector(NSResponder.moveUp(_:)) || commandSelector == #selector(NSResponder.moveDown(_:)) {
|
} else if commandSelector == #selector(NSResponder.moveUp(_:)) || commandSelector == #selector(NSResponder.moveDown(_:)) {
|
||||||
// Ignore arrows up and down because we use those to navigate the programs list.
|
// Ignore arrows up and down because we use those to navigate the programs list.
|
||||||
return true
|
return true
|
||||||
|
} else if commandSelector == #selector(NSResponder.moveToBeginningOfDocument(_:)) {
|
||||||
|
// Ignore command plus up and down arrows because we use those to move to the beginning and end of the list.
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
return false
|
return false
|
||||||
@@ -378,10 +389,10 @@ class SearchViewController: NSViewController, NSTextFieldDelegate, NSPopoverDele
|
|||||||
}
|
}
|
||||||
|
|
||||||
@objc func osThemeChanged(sender: NSNotification) {
|
@objc func osThemeChanged(sender: NSNotification) {
|
||||||
updateViewsBasedOnTheme()
|
updateViewsBasedOnOSTheme()
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc func updateViewsBasedOnTheme() {
|
@objc func updateViewsBasedOnOSTheme() {
|
||||||
if NSApp.windows.first?.effectiveAppearance.bestMatch(from: [.darkAqua, .vibrantDark]) == .darkAqua { // dark
|
if NSApp.windows.first?.effectiveAppearance.bestMatch(from: [.darkAqua, .vibrantDark]) == .darkAqua { // dark
|
||||||
backgroundView.layer?.borderColor = NSColor.white.withAlphaComponent(0.2).cgColor
|
backgroundView.layer?.borderColor = NSColor.white.withAlphaComponent(0.2).cgColor
|
||||||
} else { // light
|
} else { // light
|
||||||
|
|||||||
Reference in New Issue
Block a user