在 Swift 的 NSToolbar 上下文菜单中仅显示 "Customize Toolbar..."
Display Only "Customize Toolbar..." in NSToolbar's Context Menu in Swift
我知道这个问题已经被问过很多次了,但似乎没有更好的解决方案。
更改 allowsUserCustomization
属性 没有帮助。似乎没有 API 自定义工具栏上下文菜单中的项目。
Finder 应用程序没有 "Use Small Size" 而 Notes 应用程序只有 "Customize Toolbar.."
我想知道是否有任何方法可以对 NSToolbar 进行子类化或扩展或做任何事情来达到目的?
更新 1:
根据@Khundragpan 和 this post,问题 1 可以通过以下方式解决:
if let contextMenu = window?.contentView?.superview?.menu {
for item in contextMenu.items {
if item.title != "Customize Toolbar…" {
contextMenu.removeItem(item)
}
}
}
但我认为这不是最好的方法。
更新 2:
解决问题1的另一种方法(感谢@1024jp指出this file):
if let contextMenu = window?.contentView?.superview?.menu {
contextMenu.items.forEach({ (item) in
if let action = item.action,
NSStringFromSelector(action) != "runToolbarCustomizationPalette:" {
contextMenu.removeItem(item)
}
})
}
更新 3:
非常感谢 @1024jp 帮助我。我可以通过他的一些提示和技巧来删除这些东西。检查下面的答案。
3天后,我终于搞定了。这是结果。
源代码在Swift3
您可以实现并制作自己的 class,但在这里我只想将所有内容保存在一个文件中。
这是 WindowController.swift
文件。您可以设置 window 控制器和 运行 的自定义 class。再次感谢 @1024jp 的提示。
//
// WindowController.swift
// The Toolbar
//
// Created by João Oliveira on 22/09/2016.
// Copyright © 2016 João Oliveira. All rights reserved.
//
import Cocoa
class WindowController: NSWindowController {
override func windowDidLoad() {
super.windowDidLoad()
guard let window = window else { return }
window.delegate = self
window.toolbar = NSToolbar(identifier: "RestrictedToolbar")
window.toolbar?.allowsUserCustomization = true
window.toolbar?.displayMode = .iconOnly
window.toolbar?.delegate = self
keepOnlyCustomizableMenu()
}
// PROBLEM 1: Solution
func keepOnlyCustomizableMenu() {
if let contextMenu = window?.contentView?.superview?.menu {
contextMenu.items.forEach({ (item) in
if let action = item.action,
NSStringFromSelector(action) != "runToolbarCustomizationPalette:" {
contextMenu.removeItem(item)
}
})
}
}
}
// MARK: Window Delegate
// A ton of thanks to genius @1024jp
extension MyWindowController: NSWindowDelegate {
// PROBLEM 2: Solution
func window(_ window: NSWindow, willPositionSheet sheet: NSWindow, using rect: NSRect) -> NSRect {
if sheet.className == "NSToolbarConfigPanel" {
removeSizeAndDisplayMode(in: sheet)
}
return rect
}
func removeSizeAndDisplayMode(in sheet: NSWindow) {
guard let views = sheet.contentView?.subviews else { return }
// Hide Small Size Option
views.lazy
.flatMap { [=10=] as? NSButton }
.filter { button -> Bool in
guard let buttonTypeValue = button.cell?.value(forKey: "buttonType") as? UInt,
let buttonType = NSButtonType(rawValue: buttonTypeValue)
else { return false }
return buttonType == .switch
}
.first?.isHidden = true
// Hide Display Mode Option
views.lazy
.filter { view -> Bool in
return view.subviews.count == 2
}
.first?.isHidden = true
sheet.contentView?.needsDisplay = true
}
}
// MARK: Toolbar Delegate
extension MyWindowController: NSToolbarDelegate {
func toolbarAllowedItemIdentifiers(_ toolbar: NSToolbar) -> [String] {
return [
NSToolbarFlexibleSpaceItemIdentifier,
NSToolbarSpaceItemIdentifier,
NSToolbarToggleSidebarItemIdentifier
]
}
func toolbarDefaultItemIdentifiers(_ toolbar: NSToolbar) -> [String] {
return [NSToolbarToggleSidebarItemIdentifier]
}
func toolbar(_ toolbar: NSToolbar, itemForItemIdentifier itemIdentifier: String, willBeInsertedIntoToolbar flag: Bool) -> NSToolbarItem? {
return nil
}
}
我知道这个问题已经被问过很多次了,但似乎没有更好的解决方案。
更改 allowsUserCustomization
属性 没有帮助。似乎没有 API 自定义工具栏上下文菜单中的项目。
Finder 应用程序没有 "Use Small Size" 而 Notes 应用程序只有 "Customize Toolbar.."
我想知道是否有任何方法可以对 NSToolbar 进行子类化或扩展或做任何事情来达到目的?
更新 1:
根据@Khundragpan 和 this post,问题 1 可以通过以下方式解决:
if let contextMenu = window?.contentView?.superview?.menu {
for item in contextMenu.items {
if item.title != "Customize Toolbar…" {
contextMenu.removeItem(item)
}
}
}
但我认为这不是最好的方法。
更新 2:
解决问题1的另一种方法(感谢@1024jp指出this file):
if let contextMenu = window?.contentView?.superview?.menu {
contextMenu.items.forEach({ (item) in
if let action = item.action,
NSStringFromSelector(action) != "runToolbarCustomizationPalette:" {
contextMenu.removeItem(item)
}
})
}
更新 3:
非常感谢 @1024jp 帮助我。我可以通过他的一些提示和技巧来删除这些东西。检查下面的答案。
3天后,我终于搞定了。这是结果。
源代码在Swift3
您可以实现并制作自己的 class,但在这里我只想将所有内容保存在一个文件中。
这是 WindowController.swift
文件。您可以设置 window 控制器和 运行 的自定义 class。再次感谢 @1024jp 的提示。
//
// WindowController.swift
// The Toolbar
//
// Created by João Oliveira on 22/09/2016.
// Copyright © 2016 João Oliveira. All rights reserved.
//
import Cocoa
class WindowController: NSWindowController {
override func windowDidLoad() {
super.windowDidLoad()
guard let window = window else { return }
window.delegate = self
window.toolbar = NSToolbar(identifier: "RestrictedToolbar")
window.toolbar?.allowsUserCustomization = true
window.toolbar?.displayMode = .iconOnly
window.toolbar?.delegate = self
keepOnlyCustomizableMenu()
}
// PROBLEM 1: Solution
func keepOnlyCustomizableMenu() {
if let contextMenu = window?.contentView?.superview?.menu {
contextMenu.items.forEach({ (item) in
if let action = item.action,
NSStringFromSelector(action) != "runToolbarCustomizationPalette:" {
contextMenu.removeItem(item)
}
})
}
}
}
// MARK: Window Delegate
// A ton of thanks to genius @1024jp
extension MyWindowController: NSWindowDelegate {
// PROBLEM 2: Solution
func window(_ window: NSWindow, willPositionSheet sheet: NSWindow, using rect: NSRect) -> NSRect {
if sheet.className == "NSToolbarConfigPanel" {
removeSizeAndDisplayMode(in: sheet)
}
return rect
}
func removeSizeAndDisplayMode(in sheet: NSWindow) {
guard let views = sheet.contentView?.subviews else { return }
// Hide Small Size Option
views.lazy
.flatMap { [=10=] as? NSButton }
.filter { button -> Bool in
guard let buttonTypeValue = button.cell?.value(forKey: "buttonType") as? UInt,
let buttonType = NSButtonType(rawValue: buttonTypeValue)
else { return false }
return buttonType == .switch
}
.first?.isHidden = true
// Hide Display Mode Option
views.lazy
.filter { view -> Bool in
return view.subviews.count == 2
}
.first?.isHidden = true
sheet.contentView?.needsDisplay = true
}
}
// MARK: Toolbar Delegate
extension MyWindowController: NSToolbarDelegate {
func toolbarAllowedItemIdentifiers(_ toolbar: NSToolbar) -> [String] {
return [
NSToolbarFlexibleSpaceItemIdentifier,
NSToolbarSpaceItemIdentifier,
NSToolbarToggleSidebarItemIdentifier
]
}
func toolbarDefaultItemIdentifiers(_ toolbar: NSToolbar) -> [String] {
return [NSToolbarToggleSidebarItemIdentifier]
}
func toolbar(_ toolbar: NSToolbar, itemForItemIdentifier itemIdentifier: String, willBeInsertedIntoToolbar flag: Bool) -> NSToolbarItem? {
return nil
}
}