111 lines
5.4 KiB
Swift
111 lines
5.4 KiB
Swift
import AppKit
|
|||
|
|
|
||
|
|
/**
|
||
|
|
ProdDash Viewer: one window showing a ProdDash dashboard, a tab per
|
||
|
|
installation when there's more than one, and Settings to say which.
|
||
|
|
|
||
|
|
The menus are deliberately short — Back, Forward, Reload Page and Settings,
|
||
|
|
plus what every Mac app has: the app menu, Edit (without which Copy and
|
||
|
|
Paste do nothing in the dashboard's text fields), Window and Help.
|
||
|
|
*/
|
||
|
|
final class AppDelegate: NSObject, NSApplicationDelegate {
|
||
|
|
|
||
|
|
static var version: String {
|
||
|
|
Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ?? "dev"
|
||
|
|
}
|
||
|
|
|
||
|
|
private var viewer: ViewerWindowController!
|
||
|
|
private lazy var settingsWindow = SettingsWindowController()
|
||
|
|
private lazy var helpWindow = HelpWindowController()
|
||
|
|
|
||
|
|
func applicationWillFinishLaunching(_ notification: Notification) {
|
||
|
|
NSWindow.allowsAutomaticWindowTabbing = false
|
||
|
|
NSApp.mainMenu = makeMainMenu()
|
||
|
|
}
|
||
|
|
|
||
|
|
func applicationDidFinishLaunching(_ notification: Notification) {
|
||
|
|
viewer = ViewerWindowController()
|
||
|
|
viewer.onAddConnection = { [weak self] in self?.settingsWindow.show(addingConnection: true) }
|
||
|
|
viewer.showWindow(nil)
|
||
|
|
if ViewerSettings.shared.reopenInFullScreen {
|
||
|
|
DispatchQueue.main.async { self.viewer.window?.toggleFullScreen(nil) }
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func applicationShouldHandleReopen(_ sender: NSApplication, hasVisibleWindows flag: Bool) -> Bool {
|
||
|
|
if !flag { viewer.showWindow(nil) }
|
||
|
|
return true
|
||
|
|
}
|
||
|
|
|
||
|
|
func applicationWillTerminate(_ notification: Notification) {
|
||
|
|
viewer?.rememberFullScreen()
|
||
|
|
}
|
||
|
|
|
||
|
|
func applicationSupportsSecureRestorableState(_ app: NSApplication) -> Bool { true }
|
||
|
|
|
||
|
|
@objc func showSettings(_ sender: Any?) { settingsWindow.show() }
|
||
|
|
@objc func showViewerHelp(_ sender: Any?) { helpWindow.show() }
|
||
|
|
|
||
|
|
// MARK: - Menus
|
||
|
|
|
||
|
|
private func makeMainMenu() -> NSMenu {
|
||
|
|
let name = "ProdDash Viewer"
|
||
|
|
let main = NSMenu()
|
||
|
|
|
||
|
|
let app = submenu(of: main, title: name)
|
||
|
|
app.addItem(withTitle: "About \(name)",
|
||
|
|
action: #selector(NSApplication.orderFrontStandardAboutPanel(_:)), keyEquivalent: "")
|
||
|
|
app.addItem(.separator())
|
||
|
|
app.addItem(withTitle: "Settings…", action: #selector(showSettings(_:)), keyEquivalent: ",")
|
||
|
|
app.addItem(.separator())
|
||
|
|
let services = submenu(of: app, title: "Services")
|
||
|
|
NSApp.servicesMenu = services
|
||
|
|
app.addItem(.separator())
|
||
|
|
app.addItem(withTitle: "Hide \(name)", action: #selector(NSApplication.hide(_:)), keyEquivalent: "h")
|
||
|
|
app.addItem(withTitle: "Hide Others", action: #selector(NSApplication.hideOtherApplications(_:)),
|
||
|
|
keyEquivalent: "h").keyEquivalentModifierMask = [.command, .option]
|
||
|
|
app.addItem(withTitle: "Show All", action: #selector(NSApplication.unhideAllApplications(_:)), keyEquivalent: "")
|
||
|
|
app.addItem(.separator())
|
||
|
|
app.addItem(withTitle: "Quit \(name)", action: #selector(NSApplication.terminate(_:)), keyEquivalent: "q")
|
||
|
|
|
||
|
|
let edit = submenu(of: main, title: "Edit")
|
||
|
|
edit.addItem(withTitle: "Undo", action: Selector(("undo:")), keyEquivalent: "z")
|
||
|
|
edit.addItem(withTitle: "Redo", action: Selector(("redo:")), keyEquivalent: "Z")
|
||
|
|
edit.addItem(.separator())
|
||
|
|
edit.addItem(withTitle: "Cut", action: #selector(NSText.cut(_:)), keyEquivalent: "x")
|
||
|
|
edit.addItem(withTitle: "Copy", action: #selector(NSText.copy(_:)), keyEquivalent: "c")
|
||
|
|
edit.addItem(withTitle: "Paste", action: #selector(NSText.paste(_:)), keyEquivalent: "v")
|
||
|
|
edit.addItem(withTitle: "Select All", action: #selector(NSText.selectAll(_:)), keyEquivalent: "a")
|
||
|
|
|
||
|
|
let view = submenu(of: main, title: "View")
|
||
|
|
view.addItem(withTitle: "Back", action: #selector(ViewerWindowController.goBackInPage(_:)), keyEquivalent: "[")
|
||
|
|
view.addItem(withTitle: "Forward", action: #selector(ViewerWindowController.goForwardInPage(_:)), keyEquivalent: "]")
|
||
|
|
view.addItem(withTitle: "Reload Page", action: #selector(ViewerWindowController.reloadPage(_:)), keyEquivalent: "r")
|
||
|
|
view.addItem(.separator())
|
||
|
|
// AppKit retitles this "Exit Full Screen" while the window is in full screen.
|
||
|
|
view.addItem(withTitle: "Enter Full Screen", action: #selector(NSWindow.toggleFullScreen(_:)),
|
||
|
|
keyEquivalent: "f").keyEquivalentModifierMask = [.command, .control]
|
||
|
|
|
||
|
|
let window = submenu(of: main, title: "Window")
|
||
|
|
window.addItem(withTitle: "Close", action: #selector(NSWindow.performClose(_:)), keyEquivalent: "w")
|
||
|
|
window.addItem(withTitle: "Minimize", action: #selector(NSWindow.performMiniaturize(_:)), keyEquivalent: "m")
|
||
|
|
window.addItem(withTitle: "Zoom", action: #selector(NSWindow.performZoom(_:)), keyEquivalent: "")
|
||
|
|
window.addItem(.separator())
|
||
|
|
window.addItem(withTitle: "Bring All to Front", action: #selector(NSApplication.arrangeInFront(_:)), keyEquivalent: "")
|
||
|
|
NSApp.windowsMenu = window
|
||
|
|
|
||
|
|
let help = submenu(of: main, title: "Help")
|
||
|
|
help.addItem(withTitle: "\(name) Help", action: #selector(showViewerHelp(_:)), keyEquivalent: "?")
|
||
|
|
NSApp.helpMenu = help
|
||
|
|
|
||
|
|
return main
|
||
|
|
}
|
||
|
|
|
||
|
|
@discardableResult
|
||
|
|
private func submenu(of parent: NSMenu, title: String) -> NSMenu {
|
||
|
|
let menu = NSMenu(title: title)
|
||
|
|
parent.addItem(withTitle: title, action: nil, keyEquivalent: "").submenu = menu
|
||
|
|
return menu
|
||
|
|
}
|
||
|
|
}
|