Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Catalyst status menu item via NSPopover swizzle
//
// PSTLNativeStatusItemController.swift
// PastelIntegration
//
// Created by Steven Troughton-Smith on 09/06/2021.
// Copyright © 2021 Steven Troughton-Smith. All rights reserved.
//
import AppKit
extension NSPopover {
@objc func PSTL_showRelativeToRect(_ rect:CGRect, ofView:NSView?, preferredEdge:CGRectEdge) {
if ofView == nil {
if let sender = PSTLStatusItem.button {
if let sourceRect = sender.window?.convertToScreen(sender.frame) {
behavior = .transient
// animates = false
PSTL_showRelativeToRect(.zero, ofView: sender, preferredEdge: .maxYEdge)
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
self.contentSize = CGSize(width:246, height:380)
self.positioningRect = sender.bounds
}
}
}
}
else {
PSTL_showRelativeToRect(rect, ofView: ofView, preferredEdge: preferredEdge)
}
}
}
var PSTLStatusItem = NSStatusItem()
class PSTLNativeStatusItemController: NSObject {
static let shared = PSTLNativeStatusItemController()
@objc class func sharedInstance() -> PSTLNativeStatusItemController {
return PSTLNativeStatusItemController.shared
}
override init() {
super.init()
PSTLStatusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.squareLength)
let image = NSImage(named: "PickerWheel")
image?.isTemplate = true
PSTLStatusItem.button?.image = image
PSTLStatusItem.button?.target = self
PSTLStatusItem.button?.action = #selector(menuWillOpen(_:))
let m1 = class_getInstanceMethod(NSClassFromString("NSPopover"), NSSelectorFromString("PSTL_showRelativeToRect:ofView:preferredEdge:"))
let m2 = class_getInstanceMethod(NSClassFromString("NSPopover"), NSSelectorFromString("showRelativeToRect:ofView:preferredEdge:"))
if let m1 = m1, let m2 = m2 {
method_exchangeImplementations(m1, m2)
}
}
@objc func menuWillOpen(_ sender:NSStatusBarButton) {
NotificationCenter.default.post(name: NSNotification.Name("PSTLShowStandalonePicker"), object: nil)
}
}
@objc func showStandalonePicker(_ sender:Any) {
for scene in UIApplication.shared.connectedScenes {
if let sceneDelegate = scene.delegate as? PSTLSceneDelegate {
if sceneDelegate.window?.rootViewController?.presentedViewController != nil {
sceneDelegate.window?.rootViewController?.dismiss(animated: true, completion: nil)
} else {
if let window = sceneDelegate.window {
let v = UIView()
v.frame = CGRect(x: 0, y: 0, width: 40, height: 40)
menuBarColorPickerViewController.popoverPresentationController?.sourceView = v
menuBarColorPickerViewController.popoverPresentationController?.sourceRect = v.bounds
menuBarColorPickerViewController.popoverPresentationController?.permittedArrowDirections = [.any]
menuBarColorPickerViewController.popoverPresentationController?.canOverlapSourceViewRect = true
menuBarColorPickerViewController.view.setNeedsLayout()
window.rootViewController?.present(menuBarColorPickerViewController, animated: true, completion: nil)
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment