Don't use a toolbar for the traditional title/tab bar

I forgot I can use a `NSTitlebarAccessoryViewController` to house the
button
This commit is contained in:
Pete Schaffner
2024-02-25 21:47:15 +01:00
parent 55621c214c
commit b6bfb9dac5
4 changed files with 89 additions and 64 deletions

View File

@ -0,0 +1,15 @@
{
"images" : [
{
"filename" : "ResetZoom.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"template-rendering-intent" : "template"
}
}

Binary file not shown.

View File

@ -15,8 +15,6 @@ class TerminalToolbar: NSToolbar, NSToolbarDelegate {
}
}
var hasTitle: Bool = false
override init(identifier: NSToolbar.Identifier) {
super.init(identifier: identifier)
@ -54,24 +52,6 @@ class TerminalToolbar: NSToolbar, NSToolbarDelegate {
item.isEnabled = true
case .resetZoom:
item = NSToolbarItem(itemIdentifier: .resetZoom)
let view = NSView(frame: NSRect(x: 0, y: 0, width: 20, height: 20))
view.translatesAutoresizingMaskIntoConstraints = false
view.widthAnchor.constraint(equalToConstant: 20).isActive = true
view.heightAnchor.constraint(equalToConstant: 20).isActive = true
let button = NSButton(image: NSImage(systemSymbolName: "arrow.down.right.and.arrow.up.left.square.fill", accessibilityDescription: nil)!, target: nil, action: #selector(TerminalController.splitZoom(_:)))
button.frame = view.bounds
button.isBordered = false
button.contentTintColor = .controlAccentColor
button.state = .on
button.imageScaling = .scaleProportionallyUpOrDown
button.allowsExpansionToolTips = true
button.toolTip = "Reset Zoom"
view.addSubview(button)
item.view = view
default:
item = NSToolbarItem(itemIdentifier: itemIdentifier)
}
@ -88,11 +68,7 @@ class TerminalToolbar: NSToolbar, NSToolbarDelegate {
// getting smaller than the max size so starts clipping. Lucky for us, two of the
// built-in spacers plus the un-zoom button item seems to exactly match the space
// on the left that's reserved for the window buttons.
if hasTitle {
return [.titleText, .flexibleSpace, .space, .space, .resetZoom]
} else {
return [.flexibleSpace, .resetZoom]
}
}
}

View File

@ -15,29 +15,26 @@ class TerminalWindow: NSWindow {
}
}
private var resetZoomToolbarButton: NSButton? {
guard let button = toolbar?.items.first(where: { $0.itemIdentifier == .resetZoom })?.view?.subviews.first as? NSButton
else { return nil }
private lazy var resetZoomToolbarButton: NSButton = generateResetZoomButton()
return button
}
private lazy var resetZoomTabButton: NSButton = generateResetZoomButton()
private let resetZoomTabButton: NSButton = {
let button = NSButton()
button.target = nil
button.action = #selector(TerminalController.splitZoom(_:))
button.translatesAutoresizingMaskIntoConstraints = false
button.widthAnchor.constraint(equalToConstant: 20).isActive = true
button.heightAnchor.constraint(equalToConstant: 20).isActive = true
button.isBordered = false
button.allowsExpansionToolTips = true
button.toolTip = "Reset Zoom"
button.contentTintColor = .controlAccentColor
button.state = .on
button.image = NSImage(systemSymbolName: "arrow.down.right.and.arrow.up.left.square.fill", accessibilityDescription: nil)!
.withSymbolConfiguration(NSImage.SymbolConfiguration(scale: .large))
private lazy var resetZoomTitlebarAccessoryViewController: NSTitlebarAccessoryViewController? = {
guard let titlebarContainer = contentView?.superview?.subviews.first(where: { $0.className == "NSTitlebarContainerView" }) else { return nil }
return button
let size = NSSize(width: titlebarContainer.bounds.height, height: titlebarContainer.bounds.height)
let view = NSView(frame: NSRect(origin: .zero, size: size))
let button = generateResetZoomButton()
button.frame.origin.x = size.width/2 - button.bounds.width/2
button.frame.origin.y = size.height/2 - button.bounds.height/2
view.addSubview(button)
let titlebarAccessoryViewController = NSTitlebarAccessoryViewController()
titlebarAccessoryViewController.view = view
titlebarAccessoryViewController.layoutAttribute = .right
return titlebarAccessoryViewController
}()
private lazy var keyEquivalentLabel: NSTextField = {
@ -50,10 +47,10 @@ class TerminalWindow: NSWindow {
private lazy var bindings = [
observe(\.surfaceIsZoomed, options: [.initial, .new]) { [weak self] window, _ in
guard let resetZoomToolbarButton = self?.resetZoomToolbarButton, let tabGroup = self?.tabGroup else { return }
guard let tabGroup = self?.tabGroup else { return }
self?.resetZoomTabButton.isHidden = !window.surfaceIsZoomed
self?.updateResetZoomToolbarButtonVisibility()
self?.updateResetZoomTitlebarButtonVisibility()
},
observe(\.keyEquivalent, options: [.initial, .new]) { [weak self] window, _ in
@ -77,6 +74,8 @@ class TerminalWindow: NSWindow {
override func awakeFromNib() {
super.awakeFromNib()
_ = bindings
// By hiding the visual effect view, we allow the window's (or titlebar's in this case)
// background color to show through. If we were to set `titlebarAppearsTransparent` to true
// the selected tab would look fine, but the unselected ones and new tab button backgrounds
@ -95,9 +94,9 @@ class TerminalWindow: NSWindow {
stackView.spacing = 3
tab.accessoryView = stackView
if titlebarTabs {
generateToolbar()
_ = bindings
}
}
deinit {
@ -118,7 +117,7 @@ class TerminalWindow: NSWindow {
updateNewTabButtonOpacity()
resetZoomTabButton.isEnabled = true
resetZoomTabButton.contentTintColor = .controlAccentColor
resetZoomToolbarButton?.contentTintColor = .controlAccentColor
resetZoomToolbarButton.contentTintColor = .controlAccentColor
}
override func resignKey() {
@ -127,13 +126,13 @@ class TerminalWindow: NSWindow {
updateNewTabButtonOpacity()
resetZoomTabButton.isEnabled = false
resetZoomTabButton.contentTintColor = .labelColor
resetZoomToolbarButton?.contentTintColor = .tertiaryLabelColor
resetZoomToolbarButton.contentTintColor = .tertiaryLabelColor
}
override func update() {
super.update()
updateResetZoomToolbarButtonVisibility()
updateResetZoomTitlebarButtonVisibility()
titlebarSeparatorStyle = tabbedWindows != nil && !titlebarTabs ? .line : .none
@ -204,13 +203,23 @@ class TerminalWindow: NSWindow {
newTabButtonImageView.alphaValue = isKeyWindow ? 1 : 0.5
}
private func updateResetZoomToolbarButtonVisibility() {
guard let resetZoomToolbarButton = resetZoomToolbarButton, let tabGroup else { return }
private func updateResetZoomTitlebarButtonVisibility() {
guard let tabGroup, let resetZoomTitlebarAccessoryViewController else { return }
if tabGroup.isTabBarVisible {
resetZoomToolbarButton.isHidden = true
let isHidden = tabGroup.isTabBarVisible ? true : !surfaceIsZoomed
if titlebarTabs {
resetZoomToolbarButton.isHidden = isHidden
for (index, vc) in titlebarAccessoryViewControllers.enumerated() {
guard vc == resetZoomTitlebarAccessoryViewController else { return }
removeTitlebarAccessoryViewController(at: index)
}
} else {
resetZoomToolbarButton.isHidden = !surfaceIsZoomed
if !titlebarAccessoryViewControllers.contains(resetZoomTitlebarAccessoryViewController) {
addTitlebarAccessoryViewController(resetZoomTitlebarAccessoryViewController)
}
resetZoomTitlebarAccessoryViewController.view.isHidden = isHidden
}
}
@ -220,11 +229,34 @@ class TerminalWindow: NSWindow {
// isn't possible.
private func generateToolbar() {
let terminalToolbar = TerminalToolbar(identifier: "Toolbar")
terminalToolbar.hasTitle = titlebarTabs
toolbar = terminalToolbar
toolbarStyle = .unifiedCompact
updateResetZoomToolbarButtonVisibility()
if let resetZoomItem = terminalToolbar.items.first(where: { $0.itemIdentifier == .resetZoom }) {
resetZoomItem.view = resetZoomToolbarButton
resetZoomItem.view?.translatesAutoresizingMaskIntoConstraints = false
resetZoomItem.view?.widthAnchor.constraint(equalToConstant: 22).isActive = true
resetZoomItem.view?.heightAnchor.constraint(equalToConstant: 20).isActive = true
}
updateResetZoomTitlebarButtonVisibility()
}
private func generateResetZoomButton() -> NSButton {
let button = NSButton()
button.target = nil
button.action = #selector(TerminalController.splitZoom(_:))
button.isBordered = false
button.allowsExpansionToolTips = true
button.toolTip = "Reset Zoom"
button.contentTintColor = .controlAccentColor
button.state = .on
button.image = NSImage(named:"ResetZoom")
button.frame = NSRect(x: 0, y: 0, width: 20, height: 20)
button.translatesAutoresizingMaskIntoConstraints = false
button.widthAnchor.constraint(equalToConstant: 20).isActive = true
button.heightAnchor.constraint(equalToConstant: 20).isActive = true
return button
}
// MARK: - Titlebar Tabs
@ -233,9 +265,11 @@ class TerminalWindow: NSWindow {
var titlebarTabs = false {
didSet {
self.titleVisibility = titlebarTabs ? .hidden : .visible
if titlebarTabs {
generateToolbar()
}
}
}
private var windowButtonsBackdrop: WindowButtonsBackdropView? = nil
private var windowDragHandle: WindowDragView? = nil