165 lines
5.1 KiB
Swift
165 lines
5.1 KiB
Swift
//
|
|
// MainViewController.swift
|
|
// DetachablePopover
|
|
//
|
|
// Created by Lukas Kubanek on 25.10.2014.
|
|
// Copyright (c) 2014 Lukas Kubanek. All rights reserved.
|
|
//
|
|
|
|
import AppKit
|
|
|
|
class MainViewController: NSViewController, NSPopoverDelegate {
|
|
|
|
// MARK: - Outlets
|
|
|
|
@IBOutlet weak var appearanceSelection: NSMatrix!
|
|
@IBOutlet weak var positionSelection: NSMatrix!
|
|
@IBOutlet weak var windowTypeSelection: NSMatrix!
|
|
|
|
@IBOutlet weak var showButton: NSButton!
|
|
@IBOutlet weak var hideButton: NSButton!
|
|
@IBOutlet weak var detachButton: NSButton!
|
|
|
|
// MARK: - Popover and Detached Window Controller
|
|
|
|
lazy var popover: NSPopover = {
|
|
let popover = NSPopover()
|
|
popover.behavior = .semitransient
|
|
popover.contentViewController = ContentViewController()
|
|
popover.delegate = self
|
|
return popover
|
|
}()
|
|
|
|
private var detachedWindowControllerLoaded = false
|
|
|
|
lazy var detachedWindowController: DetachedWindowController = {
|
|
let detachedWindowController = DetachedWindowController(windowNibName: NSNib.Name(rawValue: "DetachedWindowController"))
|
|
detachedWindowController.contentViewController = ContentViewController()
|
|
|
|
self.detachedWindowControllerLoaded = true
|
|
NotificationCenter.default.addObserver(self, selector: #selector(detachedWindowWillClose(notification:)), name: NSWindow.willCloseNotification, object: detachedWindowController.window)
|
|
|
|
return detachedWindowController
|
|
}()
|
|
|
|
// MARK: - Actions
|
|
|
|
@IBAction func show(sender: NSButton) {
|
|
if (customDetachedWindowVisible) {
|
|
detachedWindowController.window?.makeKeyAndOrderFront(nil)
|
|
} else {
|
|
popover.appearance = appearanceForSelectedRadioButton(radioButton: appearanceSelection.selectedRow)
|
|
|
|
let positioningView = sender
|
|
let positioningRect = NSZeroRect
|
|
let preferredEdge = preferredEdgeForSelectedRadioButton(radioButton: positionSelection.selectedRow)
|
|
|
|
popover.show(relativeTo: positioningRect, of: positioningView, preferredEdge: preferredEdge)
|
|
}
|
|
}
|
|
|
|
@IBAction func hide(sender: NSButton) {
|
|
if (popoverVisible) {
|
|
popover.performClose(nil)
|
|
} else if (customDetachedWindowVisible) {
|
|
detachedWindowController.close()
|
|
}
|
|
}
|
|
|
|
@IBAction func detach(_ sender: NSButton) {
|
|
let window = detachableWindow(for: popover)
|
|
window?.windowController?.showWindow(self)
|
|
}
|
|
|
|
// MARK: - Popover Delegate
|
|
|
|
func popoverShouldDetach(_ popover: NSPopover) -> Bool {
|
|
return true
|
|
}
|
|
|
|
func detachableWindow(for popover: NSPopover) -> NSWindow? {
|
|
disableDetachButton()
|
|
return customWindowSelected ? detachedWindowController.window : nil
|
|
}
|
|
|
|
func popoverDidShow(_ notification: Notification) {
|
|
enableHideButton()
|
|
if customWindowSelected {
|
|
enableDetachButton()
|
|
}
|
|
}
|
|
|
|
func popoverDidClose(_ notification: Notification) {
|
|
let closeReason = notification.userInfo![NSPopover.closeReasonUserInfoKey] as! String
|
|
if (closeReason == NSPopover.CloseReason.standard.rawValue) {
|
|
disableHideButton()
|
|
disableDetachButton()
|
|
}
|
|
}
|
|
|
|
// MARK: - Notifications Handling
|
|
|
|
@objc func detachedWindowWillClose(notification: NSNotification) {
|
|
disableHideButton()
|
|
}
|
|
|
|
// MARK: - Helpers
|
|
|
|
private var popoverVisible: Bool {
|
|
get { return popover.isShown }
|
|
}
|
|
|
|
private var customDetachedWindowVisible : Bool {
|
|
get { return detachedWindowControllerLoaded && detachedWindowController.window!.isVisible }
|
|
}
|
|
|
|
private var customWindowSelected : Bool {
|
|
get { return (windowTypeSelection.selectedRow == 1) }
|
|
}
|
|
|
|
private func enableHideButton() {
|
|
hideButton.isEnabled = true
|
|
}
|
|
|
|
private func disableHideButton() {
|
|
hideButton.isEnabled = false
|
|
}
|
|
|
|
private func enableDetachButton() {
|
|
detachButton.isEnabled = true
|
|
}
|
|
|
|
private func disableDetachButton() {
|
|
detachButton.isEnabled = false
|
|
}
|
|
|
|
|
|
private func appearanceForSelectedRadioButton(radioButton: Int) -> NSAppearance {
|
|
switch radioButton {
|
|
case 0: return NSAppearance(named: NSAppearance.Name.aqua)!
|
|
case 1: return NSAppearance(named: NSAppearance.Name.vibrantDark)!
|
|
case 2: return NSAppearance(named: NSAppearance.Name.vibrantLight)!
|
|
default: fatalError("Unsupported appearence selected")
|
|
}
|
|
}
|
|
|
|
private func preferredEdgeForSelectedRadioButton(radioButton: Int) -> NSRectEdge {
|
|
switch radioButton {
|
|
case 0: return .maxX
|
|
case 1: return .maxY
|
|
case 2: return .minX
|
|
case 3: return .minY
|
|
default: fatalError("Unsupported preferred edge selected")
|
|
}
|
|
}
|
|
|
|
// MARK: - Deinitialization
|
|
|
|
deinit {
|
|
if (detachedWindowControllerLoaded) {
|
|
NotificationCenter.default.removeObserver(self)
|
|
}
|
|
}
|
|
|
|
}
|