2017-05-27 19:43:27 +02:00
|
|
|
//
|
|
|
|
// PreferencesWindowController.swift
|
2018-08-29 07:18:24 +02:00
|
|
|
// NetNewsWire
|
2017-05-27 19:43:27 +02:00
|
|
|
//
|
|
|
|
// Created by Brent Simmons on 8/1/15.
|
|
|
|
// Copyright © 2015 Ranchero Software, LLC. All rights reserved.
|
|
|
|
//
|
|
|
|
|
2018-02-03 07:51:32 +01:00
|
|
|
import AppKit
|
2017-05-27 19:43:27 +02:00
|
|
|
|
|
|
|
private struct PreferencesToolbarItemSpec {
|
|
|
|
|
2017-09-19 07:00:35 +02:00
|
|
|
let identifier: NSToolbarItem.Identifier
|
2017-05-27 19:43:27 +02:00
|
|
|
let name: String
|
2017-09-19 07:00:35 +02:00
|
|
|
let imageName: NSImage.Name
|
|
|
|
|
|
|
|
init(identifierRawValue: String, name: String, imageName: NSImage.Name) {
|
2019-01-12 08:19:19 +01:00
|
|
|
self.identifier = NSToolbarItem.Identifier(identifierRawValue)
|
2017-09-19 07:00:35 +02:00
|
|
|
self.name = name
|
|
|
|
self.imageName = imageName
|
|
|
|
}
|
2017-05-27 19:43:27 +02:00
|
|
|
}
|
|
|
|
|
2019-01-12 08:19:19 +01:00
|
|
|
private struct ToolbarItemIdentifier {
|
|
|
|
static let General = "General"
|
2019-03-18 03:01:28 +01:00
|
|
|
static let Accounts = "Accounts"
|
2019-01-12 08:19:19 +01:00
|
|
|
static let Advanced = "Advanced"
|
|
|
|
}
|
2017-05-27 19:43:27 +02:00
|
|
|
|
|
|
|
class PreferencesWindowController : NSWindowController, NSToolbarDelegate {
|
|
|
|
|
|
|
|
private let windowFrameName = "Preferences"
|
2019-01-27 07:01:38 +01:00
|
|
|
private let windowWidth = CGFloat(512.0) // Width is constant for all views; only the height changes
|
2019-01-12 08:19:19 +01:00
|
|
|
private var viewControllers = [String: NSViewController]()
|
|
|
|
private let toolbarItemSpecs: [PreferencesToolbarItemSpec] = {
|
2017-05-27 19:43:27 +02:00
|
|
|
var specs = [PreferencesToolbarItemSpec]()
|
2019-01-12 08:19:19 +01:00
|
|
|
specs += [PreferencesToolbarItemSpec(identifierRawValue: ToolbarItemIdentifier.General, name: NSLocalizedString("General", comment: "Preferences"), imageName: NSImage.preferencesGeneralName)]
|
2019-03-18 03:01:28 +01:00
|
|
|
specs += [PreferencesToolbarItemSpec(identifierRawValue: ToolbarItemIdentifier.Accounts, name: NSLocalizedString("Accounts", comment: "Preferences"), imageName: NSImage.userAccountsName)]
|
2019-01-12 08:19:19 +01:00
|
|
|
specs += [PreferencesToolbarItemSpec(identifierRawValue: ToolbarItemIdentifier.Advanced, name: NSLocalizedString("Advanced", comment: "Preferences"), imageName: NSImage.advancedName)]
|
2017-05-27 19:43:27 +02:00
|
|
|
return specs
|
|
|
|
}()
|
|
|
|
|
|
|
|
override func windowDidLoad() {
|
2018-12-09 21:32:33 +01:00
|
|
|
let toolbar = NSToolbar(identifier: NSToolbar.Identifier("PreferencesToolbar"))
|
2017-05-27 19:43:27 +02:00
|
|
|
toolbar.delegate = self
|
|
|
|
toolbar.autosavesConfiguration = false
|
|
|
|
toolbar.allowsUserCustomization = false
|
|
|
|
toolbar.displayMode = .iconAndLabel
|
|
|
|
toolbar.selectedItemIdentifier = toolbarItemSpecs.first!.identifier
|
|
|
|
|
|
|
|
window?.showsToolbarButton = false
|
|
|
|
window?.toolbar = toolbar
|
|
|
|
|
2018-12-09 21:32:33 +01:00
|
|
|
window?.setFrameAutosaveName(NSWindow.FrameAutosaveName(windowFrameName))
|
2017-05-27 19:43:27 +02:00
|
|
|
|
|
|
|
switchToViewAtIndex(0)
|
|
|
|
}
|
|
|
|
|
|
|
|
// MARK: Actions
|
|
|
|
|
2018-02-12 03:58:50 +01:00
|
|
|
@objc func toolbarItemClicked(_ sender: Any?) {
|
2019-01-27 06:45:22 +01:00
|
|
|
guard let toolbarItem = sender as? NSToolbarItem else {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
switchToView(identifier: toolbarItem.itemIdentifier.rawValue)
|
2017-05-27 19:43:27 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// MARK: NSToolbarDelegate
|
|
|
|
|
2017-09-24 21:24:44 +02:00
|
|
|
func toolbar(_ toolbar: NSToolbar, itemForItemIdentifier itemIdentifier: NSToolbarItem.Identifier, willBeInsertedIntoToolbar flag: Bool) -> NSToolbarItem? {
|
2017-05-27 19:43:27 +02:00
|
|
|
|
2017-09-27 06:43:40 +02:00
|
|
|
guard let toolbarItemSpec = toolbarItemSpecs.first(where: { $0.identifier.rawValue == itemIdentifier.rawValue }) else {
|
2017-05-27 19:43:27 +02:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
let toolbarItem = NSToolbarItem(itemIdentifier: toolbarItemSpec.identifier)
|
|
|
|
toolbarItem.action = #selector(toolbarItemClicked(_:))
|
|
|
|
toolbarItem.target = self
|
|
|
|
toolbarItem.label = toolbarItemSpec.name
|
|
|
|
toolbarItem.paletteLabel = toolbarItem.label
|
|
|
|
toolbarItem.image = NSImage(named: toolbarItemSpec.imageName)
|
|
|
|
|
|
|
|
return toolbarItem
|
|
|
|
}
|
|
|
|
|
2017-09-19 07:00:35 +02:00
|
|
|
func toolbarDefaultItemIdentifiers(_ toolbar: NSToolbar) -> [NSToolbarItem.Identifier] {
|
2017-05-27 19:43:27 +02:00
|
|
|
return toolbarItemSpecs.map { $0.identifier }
|
|
|
|
}
|
|
|
|
|
2017-09-19 07:00:35 +02:00
|
|
|
func toolbarAllowedItemIdentifiers(_ toolbar: NSToolbar) -> [NSToolbarItem.Identifier] {
|
2017-05-27 19:43:27 +02:00
|
|
|
return toolbarDefaultItemIdentifiers(toolbar)
|
|
|
|
}
|
|
|
|
|
2017-09-19 07:00:35 +02:00
|
|
|
func toolbarSelectableItemIdentifiers(_ toolbar: NSToolbar) -> [NSToolbarItem.Identifier] {
|
2017-05-27 19:43:27 +02:00
|
|
|
return toolbarDefaultItemIdentifiers(toolbar)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private extension PreferencesWindowController {
|
|
|
|
|
|
|
|
var currentView: NSView? {
|
2018-02-14 22:14:25 +01:00
|
|
|
return window?.contentView?.subviews.first
|
2017-05-27 19:43:27 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
func toolbarItemSpec(for identifier: String) -> PreferencesToolbarItemSpec? {
|
2017-10-02 22:15:07 +02:00
|
|
|
return toolbarItemSpecs.first(where: { $0.identifier.rawValue == identifier })
|
2017-05-27 19:43:27 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
func switchToViewAtIndex(_ index: Int) {
|
|
|
|
let identifier = toolbarItemSpecs[index].identifier
|
2017-10-02 22:15:07 +02:00
|
|
|
switchToView(identifier: identifier.rawValue)
|
2017-05-27 19:43:27 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
func switchToView(identifier: String) {
|
|
|
|
guard let toolbarItemSpec = toolbarItemSpec(for: identifier) else {
|
|
|
|
assertionFailure("Preferences window: no toolbarItemSpec matching \(identifier).")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
guard let newViewController = viewController(identifier: identifier) else {
|
|
|
|
assertionFailure("Preferences window: no view controller matching \(identifier).")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if newViewController.view == currentView {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
newViewController.view.nextResponder = newViewController
|
|
|
|
newViewController.nextResponder = window!.contentView
|
|
|
|
|
|
|
|
window!.title = toolbarItemSpec.name
|
|
|
|
|
|
|
|
resizeWindow(toFitView: newViewController.view)
|
|
|
|
|
|
|
|
if let currentView = currentView {
|
|
|
|
window!.contentView?.replaceSubview(currentView, with: newViewController.view)
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
window!.contentView?.addSubview(newViewController.view)
|
|
|
|
}
|
|
|
|
|
|
|
|
window!.makeFirstResponder(newViewController.view)
|
|
|
|
}
|
|
|
|
|
|
|
|
func viewController(identifier: String) -> NSViewController? {
|
|
|
|
if let cachedViewController = viewControllers[identifier] {
|
|
|
|
return cachedViewController
|
|
|
|
}
|
|
|
|
|
2018-12-09 21:32:33 +01:00
|
|
|
let storyboard = NSStoryboard(name: NSStoryboard.Name("Preferences"), bundle: nil)
|
|
|
|
guard let viewController = storyboard.instantiateController(withIdentifier: NSStoryboard.SceneIdentifier(identifier)) as? NSViewController else {
|
2017-05-27 19:43:27 +02:00
|
|
|
assertionFailure("Unknown preferences view controller: \(identifier)")
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
viewControllers[identifier] = viewController
|
|
|
|
return viewController
|
|
|
|
}
|
2019-01-27 07:01:38 +01:00
|
|
|
|
2017-05-27 19:43:27 +02:00
|
|
|
func resizeWindow(toFitView view: NSView) {
|
|
|
|
let viewFrame = view.frame
|
|
|
|
let windowFrame = window!.frame
|
|
|
|
let contentViewFrame = window!.contentView!.frame
|
|
|
|
|
|
|
|
let deltaHeight = NSHeight(contentViewFrame) - NSHeight(viewFrame)
|
|
|
|
let heightForWindow = NSHeight(windowFrame) - deltaHeight
|
2019-01-27 07:01:38 +01:00
|
|
|
let windowOriginY = NSMinY(windowFrame) + deltaHeight
|
2017-05-27 19:43:27 +02:00
|
|
|
|
|
|
|
var updatedWindowFrame = windowFrame
|
|
|
|
updatedWindowFrame.size.height = heightForWindow
|
|
|
|
updatedWindowFrame.origin.y = windowOriginY
|
2019-01-27 07:01:38 +01:00
|
|
|
updatedWindowFrame.size.width = windowWidth //NSWidth(viewFrame)
|
2017-05-27 19:43:27 +02:00
|
|
|
|
|
|
|
var updatedViewFrame = viewFrame
|
|
|
|
updatedViewFrame.origin = NSZeroPoint
|
2019-01-27 07:01:38 +01:00
|
|
|
updatedViewFrame.size.width = windowWidth
|
2017-05-27 19:43:27 +02:00
|
|
|
if viewFrame != updatedViewFrame {
|
|
|
|
view.frame = updatedViewFrame
|
|
|
|
}
|
|
|
|
|
|
|
|
if windowFrame != updatedWindowFrame {
|
2019-03-18 05:51:41 +01:00
|
|
|
window!.contentView?.alphaValue = 0.0
|
2017-05-27 19:43:27 +02:00
|
|
|
window!.setFrame(updatedWindowFrame, display: true, animate: true)
|
2019-03-18 05:51:41 +01:00
|
|
|
window!.contentView?.alphaValue = 1.0
|
2017-05-27 19:43:27 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|