Settings window is no longer a popover.
This commit is contained in:
@@ -6,9 +6,12 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate {
|
|||||||
let fileManager = FileManager.default
|
let fileManager = FileManager.default
|
||||||
|
|
||||||
let window = PopoverPanel(viewController: SearchViewController())
|
let window = PopoverPanel(viewController: SearchViewController())
|
||||||
|
let settingsWindow =
|
||||||
|
MenulessWindow(viewController: SettingsViewController())
|
||||||
let aboutWindow = MenulessWindow(viewController: AboutViewController())
|
let aboutWindow = MenulessWindow(viewController: AboutViewController())
|
||||||
|
|
||||||
func applicationDidFinishLaunching(_ notification: Notification) {
|
func applicationDidFinishLaunching(_ notification: Notification) {
|
||||||
|
settingsWindow.title = "Settings"
|
||||||
aboutWindow.level = .statusBar
|
aboutWindow.level = .statusBar
|
||||||
|
|
||||||
PathManager.shared.updateIndex()
|
PathManager.shared.updateIndex()
|
||||||
@@ -16,8 +19,8 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate {
|
|||||||
window.delegate = self
|
window.delegate = self
|
||||||
|
|
||||||
// NOTE: Here we check wether the program was launched by the
|
// NOTE: Here we check wether the program was launched by the
|
||||||
// system (e.g. launch-at-login). If it was not, then display
|
// system (e.g. launch-at-login). If it was not, then display the
|
||||||
// the window.
|
// window.
|
||||||
if let event = NSAppleEventManager.shared().currentAppleEvent,
|
if let event = NSAppleEventManager.shared().currentAppleEvent,
|
||||||
!(event.eventID == kAEOpenApplication &&
|
!(event.eventID == kAEOpenApplication &&
|
||||||
event.paramDescriptor(forKeyword: keyAEPropData)?
|
event.paramDescriptor(forKeyword: keyAEPropData)?
|
||||||
@@ -70,7 +73,9 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate {
|
|||||||
func applicationShouldHandleReopen(_ sender: NSApplication,
|
func applicationShouldHandleReopen(_ sender: NSApplication,
|
||||||
hasVisibleWindows: Bool) -> Bool {
|
hasVisibleWindows: Bool) -> Bool {
|
||||||
if !window.isKeyWindow {
|
if !window.isKeyWindow {
|
||||||
window.makeKeyAndOrderFront(nil)
|
if !settingsWindow.isVisible {
|
||||||
|
window.makeKeyAndOrderFront(nil)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true
|
return true
|
||||||
@@ -99,8 +104,12 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate {
|
|||||||
aboutWindow.makeKeyAndOrderFront(nil)
|
aboutWindow.makeKeyAndOrderFront(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: This function act like a callback is triggered by DirMonitor
|
public func showSettingsWindow() {
|
||||||
// when file system events occur.
|
settingsWindow.makeKeyAndOrderFront(nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE: This function act like a callback and is triggered by
|
||||||
|
// DirMonitor when file system events occur.
|
||||||
public func fsEventTriggered(_ path: String, _ flags: Int) {
|
public func fsEventTriggered(_ path: String, _ flags: Int) {
|
||||||
if containsFlags(key: kFSEventStreamEventFlagItemCreated, in: flags) ||
|
if containsFlags(key: kFSEventStreamEventFlagItemCreated, in: flags) ||
|
||||||
containsFlags(key: kFSEventStreamEventFlagItemRemoved, in: flags) ||
|
containsFlags(key: kFSEventStreamEventFlagItemRemoved, in: flags) ||
|
||||||
|
|||||||
@@ -13,8 +13,8 @@ final class PathManager {
|
|||||||
private var dirMonitor: DirMonitor?
|
private var dirMonitor: DirMonitor?
|
||||||
|
|
||||||
// NOTE: These are default paths where MacOS's default programs are
|
// NOTE: These are default paths where MacOS's default programs are
|
||||||
// stored. This list should be updated if something changes in
|
// stored. This list should be updated if something changes in newer
|
||||||
// newer MacOS version.
|
// MacOS versions.
|
||||||
static let defaultPaths = [
|
static let defaultPaths = [
|
||||||
"/Applications",
|
"/Applications",
|
||||||
"/System/Applications",
|
"/System/Applications",
|
||||||
@@ -102,8 +102,8 @@ final class PathManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// PERF: Optimize some more. Do not rebuild the entire array, instead
|
// PERF: Optimize some more. Do not rebuild the entire array, instead
|
||||||
// remove or add only needed programs. Thereby, limiting the
|
// remove or add only needed programs. Thereby, limiting the amount of
|
||||||
// amount of allocations.
|
// allocations.
|
||||||
public func rebuildIndex(at path: String) {
|
public func rebuildIndex(at path: String) {
|
||||||
paths[path] = []
|
paths[path] = []
|
||||||
paths[path] = indexDirs(at: path, deepness: 2)
|
paths[path] = indexDirs(at: path, deepness: 2)
|
||||||
@@ -141,7 +141,7 @@ final class PathManager {
|
|||||||
refreshFilesystemWatchers()
|
refreshFilesystemWatchers()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Touch paths to load them into CPUs cache.
|
// Touch paths to load them into CPU's cache for performance.
|
||||||
public func touchPaths() {
|
public func touchPaths() {
|
||||||
for path in paths {
|
for path in paths {
|
||||||
_ = path
|
_ = path
|
||||||
|
|||||||
@@ -9,8 +9,7 @@ fileprivate let windowCornerRadius = 15.0
|
|||||||
fileprivate let maxItems = 20
|
fileprivate let maxItems = 20
|
||||||
|
|
||||||
class SearchViewController: NSViewController, NSTextFieldDelegate,
|
class SearchViewController: NSViewController, NSTextFieldDelegate,
|
||||||
NSPopoverDelegate, NSTableViewDataSource,
|
NSTableViewDataSource, NSTableViewDelegate
|
||||||
NSTableViewDelegate
|
|
||||||
{
|
{
|
||||||
private var keyboardEvents: EventMonitor?
|
private var keyboardEvents: EventMonitor?
|
||||||
|
|
||||||
@@ -20,13 +19,6 @@ class SearchViewController: NSViewController, NSTextFieldDelegate,
|
|||||||
|
|
||||||
private var programsTableViewSelection = 0
|
private var programsTableViewSelection = 0
|
||||||
|
|
||||||
private var settingsPopover: NSPopover = {
|
|
||||||
let popover = NSPopover()
|
|
||||||
popover.contentViewController = SettingsViewController()
|
|
||||||
popover.behavior = .transient
|
|
||||||
return popover
|
|
||||||
}()
|
|
||||||
|
|
||||||
private var shadowView: ShadowView = {
|
private var shadowView: ShadowView = {
|
||||||
let view = ShadowView()
|
let view = ShadowView()
|
||||||
view.translatesAutoresizingMaskIntoConstraints = false
|
view.translatesAutoresizingMaskIntoConstraints = false
|
||||||
@@ -301,7 +293,6 @@ class SearchViewController: NSViewController, NSTextFieldDelegate,
|
|||||||
return event
|
return event
|
||||||
}
|
}
|
||||||
|
|
||||||
settingsPopover.delegate = self
|
|
||||||
searchInput.delegate = self
|
searchInput.delegate = self
|
||||||
|
|
||||||
tableScrollView.documentView = programsTableView
|
tableScrollView.documentView = programsTableView
|
||||||
@@ -364,8 +355,7 @@ class SearchViewController: NSViewController, NSTextFieldDelegate,
|
|||||||
|
|
||||||
@objc
|
@objc
|
||||||
func openSettings() {
|
func openSettings() {
|
||||||
settingsPopover.show(relativeTo: settingsButton.bounds,
|
delegate.showSettingsWindow()
|
||||||
of: settingsButton, preferredEdge: .maxY)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc
|
@objc
|
||||||
|
|||||||
@@ -2,11 +2,15 @@ import AppKit
|
|||||||
import Carbon
|
import Carbon
|
||||||
import ServiceManagement
|
import ServiceManagement
|
||||||
|
|
||||||
|
// TODO: Rework the paths table and selection. Right now, it is very
|
||||||
|
// disfunctional and error-prone.
|
||||||
class SettingsViewController: NSViewController,
|
class SettingsViewController: NSViewController,
|
||||||
NSTextFieldDelegate, KeyDetectorButtonDelegate,
|
NSTextFieldDelegate, KeyDetectorButtonDelegate,
|
||||||
NSTableViewDataSource, NSTableViewDelegate,
|
NSTableViewDataSource, NSTableViewDelegate,
|
||||||
PathsTableCellViewDelegate
|
PathsTableCellViewDelegate
|
||||||
{
|
{
|
||||||
|
private var keyboardEvents: EventMonitor?
|
||||||
|
|
||||||
private var recording = false
|
private var recording = false
|
||||||
|
|
||||||
// NOTE: This is the default shortcut. If you were to change it, don't
|
// NOTE: This is the default shortcut. If you were to change it, don't
|
||||||
@@ -346,6 +350,20 @@ class SettingsViewController: NSViewController,
|
|||||||
launchAtLoginToggle.target = self
|
launchAtLoginToggle.target = self
|
||||||
launchAtLoginToggle.action = #selector(affectLaunchAtLogin(_:))
|
launchAtLoginToggle.action = #selector(affectLaunchAtLogin(_:))
|
||||||
|
|
||||||
|
keyboardEvents = LocalEventMonitor(mask: [.keyDown])
|
||||||
|
{ [weak self] event in
|
||||||
|
let key = event.keyCode
|
||||||
|
let modifiers = event.modifierFlags.rawValue
|
||||||
|
|
||||||
|
if modsContains(keys: OSCmd, in: modifiers) &&
|
||||||
|
key == kVK_ANSI_Q || modsContainsNone(in: modifiers)
|
||||||
|
{
|
||||||
|
NSApplication.shared.terminate(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
return event
|
||||||
|
}
|
||||||
|
|
||||||
addSubviews()
|
addSubviews()
|
||||||
setConstraints()
|
setConstraints()
|
||||||
}
|
}
|
||||||
@@ -372,11 +390,18 @@ class SettingsViewController: NSViewController,
|
|||||||
|
|
||||||
override func viewDidAppear() {
|
override func viewDidAppear() {
|
||||||
super.viewDidAppear()
|
super.viewDidAppear()
|
||||||
|
|
||||||
|
keyboardEvents?.start()
|
||||||
|
|
||||||
|
NSApp.setActivationPolicy(.regular)
|
||||||
|
self.view.window?.center()
|
||||||
}
|
}
|
||||||
|
|
||||||
override func viewWillDisappear() {
|
override func viewWillDisappear() {
|
||||||
super.viewWillDisappear()
|
super.viewWillDisappear()
|
||||||
|
|
||||||
|
keyboardEvents?.stop()
|
||||||
|
|
||||||
HotKeyManager.shared.registerHotKey(key: keyCode,
|
HotKeyManager.shared.registerHotKey(key: keyCode,
|
||||||
modifiers: modifiers)
|
modifiers: modifiers)
|
||||||
|
|
||||||
@@ -399,6 +424,12 @@ class SettingsViewController: NSViewController,
|
|||||||
PathManager.shared.savePaths()
|
PathManager.shared.savePaths()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override func viewDidDisappear() {
|
||||||
|
super.viewDidDisappear()
|
||||||
|
|
||||||
|
NSApp.setActivationPolicy(.accessory)
|
||||||
|
}
|
||||||
|
|
||||||
override func loadView() {
|
override func loadView() {
|
||||||
self.view = NSView()
|
self.view = NSView()
|
||||||
}
|
}
|
||||||
@@ -578,9 +609,9 @@ class SettingsViewController: NSViewController,
|
|||||||
makeIfNecessary: false) as? PathsTableCellView
|
makeIfNecessary: false) as? PathsTableCellView
|
||||||
{
|
{
|
||||||
if isDirectory(text) {
|
if isDirectory(text) {
|
||||||
cell.titleField.textColor = NSColor.green
|
cell.titleField.textColor = NSColor.systemGreen
|
||||||
} else {
|
} else {
|
||||||
cell.titleField.textColor = NSColor.red
|
cell.titleField.textColor = NSColor.systemRed
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -599,7 +630,7 @@ class SettingsViewController: NSViewController,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// WARN:
|
// WARN:
|
||||||
// FIX: THere is a bug where the program crashes when adding a new
|
// FIX: There is a bug where the program crashes when adding a new
|
||||||
// path. This happens because the settings popup is closed before
|
// path. This happens because the settings popup is closed before
|
||||||
// displaying the selection modal, as a result the new path item
|
// displaying the selection modal, as a result the new path item
|
||||||
// is cleared (well, b/c it's empty) and the path gets set into
|
// is cleared (well, b/c it's empty) and the path gets set into
|
||||||
|
|||||||
Reference in New Issue
Block a user