Skip to content

Commit

Permalink
Add option to hide the toolbar when there's one or less items (#25)
Browse files Browse the repository at this point in the history
Fixes #23
  • Loading branch information
DivineDominion authored and sindresorhus committed Apr 16, 2019
1 parent 891d9df commit 27f4b3e
Show file tree
Hide file tree
Showing 8 changed files with 66 additions and 52 deletions.
3 changes: 2 additions & 1 deletion Example/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ final class AppDelegate: NSObject, NSApplicationDelegate {
lazy var preferencesWindowController = PreferencesWindowController(
preferencePanes: preferences,
style: preferencesStyle,
animated: true
animated: true,
hidesToolbarForSingleItem: true
)

func applicationWillFinishLaunching(_ notification: Notification) {
Expand Down
11 changes: 0 additions & 11 deletions Sources/Preferences/PreferencesStyle.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,3 @@ public enum PreferencesStyle {
case toolbarItems
case segmentedControl
}

extension PreferencesStyle {
var windowTitleVisibility: NSWindow.TitleVisibility {
switch self {
case .toolbarItems:
return .visible
case .segmentedControl:
return .hidden
}
}
}
19 changes: 8 additions & 11 deletions Sources/Preferences/PreferencesTabViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ import Cocoa
final class PreferencesTabViewController: NSViewController, PreferencesStyleControllerDelegate {
private var activeTab: Int!
private var preferencePanes = [PreferencePane]()
internal var preferencePanesCount: Int {
return preferencePanes.count
}

private var preferencesStyleController: PreferencesStyleController!

Expand All @@ -25,16 +28,10 @@ final class PreferencesTabViewController: NSViewController, PreferencesStyleCont
self.view.translatesAutoresizingMaskIntoConstraints = false
}

func configure(preferencePanes: [PreferencePane]) {
func configure(preferencePanes: [PreferencePane], style: PreferencesStyle) {
self.preferencePanes = preferencePanes
self.children = preferencePanes.map { $0.viewController }
}

func changePreferencesStyle(to newStyle: PreferencesStyle) {
changePreferencesStyleController(preferences: self.preferencePanes, style: newStyle)
}

private func changePreferencesStyleController(preferences: [PreferencePane], style: PreferencesStyle) {
let toolbar = NSToolbar(identifier: "PreferencesToolbar")
toolbar.allowsUserCustomization = false
toolbar.displayMode = .iconAndLabel
Expand All @@ -43,10 +40,10 @@ final class PreferencesTabViewController: NSViewController, PreferencesStyleCont

switch style {
case .segmentedControl:
preferencesStyleController = SegmentedControlStyleViewController(preferences: preferences)
preferencesStyleController = SegmentedControlStyleViewController(preferencePanes: preferencePanes)
case .toolbarItems:
preferencesStyleController = ToolbarItemStyleViewController(
preferences: preferences,
preferencePanes: preferencePanes,
toolbar: toolbar,
centerToolbarItems: false
)
Expand All @@ -57,8 +54,8 @@ final class PreferencesTabViewController: NSViewController, PreferencesStyleCont
window.toolbar = toolbar
}

func activateTab(preference: PreferencePane?, animated: Bool) {
guard let preference = preference else {
func activateTab(preferencePane: PreferencePane?, animated: Bool) {
guard let preference = preferencePane else {
return activateTab(index: 0, animated: animated)
}

Expand Down
31 changes: 24 additions & 7 deletions Sources/Preferences/PreferencesWindowController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,22 @@ public final class PreferencesWindowController: NSWindowController {
}
}

public var hidesToolbarForSingleItem: Bool {
didSet {
updateToolbarVisibility()
}
}

private func updateToolbarVisibility() {
window?.toolbar?.isVisible = (hidesToolbarForSingleItem == false)
|| (tabViewController.preferencePanesCount > 1)
}

public init(
preferencePanes: [PreferencePane],
style: PreferencesStyle = .toolbarItems,
animated: Bool = true
animated: Bool = true,
hidesToolbarForSingleItem: Bool = true
) {
precondition(!preferencePanes.isEmpty, "You need to set at least one view controller")

Expand All @@ -28,12 +40,21 @@ public final class PreferencesWindowController: NSWindowController {
backing: .buffered,
defer: true
)
self.hidesToolbarForSingleItem = hidesToolbarForSingleItem
super.init(window: window)

window.contentViewController = tabViewController
window.titleVisibility = {
switch style {
case .toolbarItems:
return .visible
case .segmentedControl:
return (preferencePanes.count <= 1) ? .visible : .hidden
}
}()
tabViewController.isAnimated = animated
tabViewController.configure(preferencePanes: preferencePanes)
changePreferencesStyle(to: style)
tabViewController.configure(preferencePanes: preferencePanes, style: style)
updateToolbarVisibility()
}

@available(*, unavailable)
Expand All @@ -46,10 +67,6 @@ public final class PreferencesWindowController: NSWindowController {
fatalError("init(coder:) is not supported, use init(preferences:style:animated:)")
}

private func changePreferencesStyle(to newStyle: PreferencesStyle) {
window?.titleVisibility = newStyle.windowTitleVisibility
tabViewController.changePreferencesStyle(to: newStyle)
}

/// Show the preferences window and brings it to front.
///
Expand Down
26 changes: 13 additions & 13 deletions Sources/Preferences/SegmentedControlStyleViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,11 @@ final class SegmentedControlStyleViewController: NSViewController, PreferencesSt

weak var delegate: PreferencesStyleControllerDelegate?

private var preferences: [PreferencePane]!
private var preferencePanes: [PreferencePane]!

required init(preferences: [PreferencePane]) {
required init(preferencePanes: [PreferencePane]) {
super.init(nibName: nil, bundle: nil)
self.preferences = preferences
self.preferencePanes = preferencePanes
}

@available(*, unavailable)
Expand All @@ -41,12 +41,12 @@ final class SegmentedControlStyleViewController: NSViewController, PreferencesSt
}

override func loadView() {
view = createSegmentedControl(preferences: preferences)
view = createSegmentedControl(preferencePanes: preferencePanes)
}

fileprivate func createSegmentedControl(preferences: [PreferencePane]) -> NSSegmentedControl {
fileprivate func createSegmentedControl(preferencePanes: [PreferencePane]) -> NSSegmentedControl {
let segmentedControl = NSSegmentedControl()
segmentedControl.segmentCount = preferences.count
segmentedControl.segmentCount = preferencePanes.count
segmentedControl.segmentStyle = .texturedSquare
segmentedControl.target = self
segmentedControl.action = #selector(segmentedControlAction)
Expand All @@ -61,8 +61,8 @@ final class SegmentedControlStyleViewController: NSViewController, PreferencesSt
let insets = CGSize(width: 36, height: 12)
var maxSize = CGSize.zero

for preference in preferences {
let title = preference.preferencePaneTitle
for preferencePane in preferencePanes {
let title = preferencePane.preferencePaneTitle
let titleSize = title.size(
withAttributes: [
.font: NSFont.systemFont(ofSize: NSFont.systemFontSize(for: .regular))
Expand All @@ -81,13 +81,13 @@ final class SegmentedControlStyleViewController: NSViewController, PreferencesSt
)
}()

let segmentBorderWidth = CGFloat(preferences.count) + 1
let segmentWidth = segmentSize.width * CGFloat(preferences.count) + segmentBorderWidth
let segmentBorderWidth = CGFloat(preferencePanes.count) + 1
let segmentWidth = segmentSize.width * CGFloat(preferencePanes.count) + segmentBorderWidth
let segmentHeight = segmentSize.height
segmentedControl.frame = CGRect(x: 0, y: 0, width: segmentWidth, height: segmentHeight)

for (index, preference) in preferences.enumerated() {
segmentedControl.setLabel(preference.preferencePaneTitle, forSegment: index)
for (index, preferencePane) in preferencePanes.enumerated() {
segmentedControl.setLabel(preferencePane.preferencePaneTitle, forSegment: index)
segmentedControl.setWidth(segmentSize.width, forSegment: index)
if let cell = segmentedControl.cell as? NSSegmentedCell {
cell.setTag(index, forSegment: index)
Expand Down Expand Up @@ -122,7 +122,7 @@ final class SegmentedControlStyleViewController: NSViewController, PreferencesSt
// context menu that pops up at the right edge of the window.
let toolbarItemGroup = NSToolbarItemGroup(itemIdentifier: toolbarItemIdentifier)
toolbarItemGroup.view = segmentedControl
toolbarItemGroup.subitems = preferences.enumerated().map { index, preferenceable -> NSToolbarItem in
toolbarItemGroup.subitems = preferencePanes.enumerated().map { index, preferenceable -> NSToolbarItem in
let item = NSToolbarItem(itemIdentifier: .init("segment-\(preferenceable.preferencePaneTitle)"))
item.label = preferenceable.preferencePaneTitle

Expand Down
14 changes: 7 additions & 7 deletions Sources/Preferences/ToolbarItemStyleViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,16 @@ import Cocoa
final class ToolbarItemStyleViewController: NSObject, PreferencesStyleController {
let toolbar: NSToolbar
let centerToolbarItems: Bool
let preferences: [PreferencePane]
let preferencePanes: [PreferencePane]

var isKeepingWindowCentered: Bool {
return centerToolbarItems
}

weak var delegate: PreferencesStyleControllerDelegate?

init(preferences: [PreferencePane], toolbar: NSToolbar, centerToolbarItems: Bool) {
self.preferences = preferences
init(preferencePanes: [PreferencePane], toolbar: NSToolbar, centerToolbarItems: Bool) {
self.preferencePanes = preferencePanes
self.toolbar = toolbar
self.centerToolbarItems = centerToolbarItems
}
Expand All @@ -24,8 +24,8 @@ final class ToolbarItemStyleViewController: NSObject, PreferencesStyleController
toolbarItemIdentifiers.append(.flexibleSpace)
}

for preference in preferences {
toolbarItemIdentifiers.append(preference.toolbarItemIdentifier)
for preferencePane in preferencePanes {
toolbarItemIdentifiers.append(preferencePane.toolbarItemIdentifier)
}

if centerToolbarItems {
Expand All @@ -36,7 +36,7 @@ final class ToolbarItemStyleViewController: NSObject, PreferencesStyleController
}

func toolbarItem(preferenceIdentifier: PreferencePaneIdentifier) -> NSToolbarItem? {
guard let preference = (preferences.first { $0.preferencePaneIdentifier == preferenceIdentifier }) else {
guard let preference = (preferencePanes.first { $0.preferencePaneIdentifier == preferenceIdentifier }) else {
preconditionFailure()
}

Expand All @@ -56,6 +56,6 @@ final class ToolbarItemStyleViewController: NSObject, PreferencesStyleController
}

func selectTab(index: Int) {
toolbar.selectedItemIdentifier = preferences[index].toolbarItemIdentifier
toolbar.selectedItemIdentifier = preferencePanes[index].toolbarItemIdentifier
}
}
9 changes: 9 additions & 0 deletions Sources/Preferences/UserInteractionPausableWindow.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,13 @@ class UserInteractionPausableWindow: NSWindow {

super.sendEvent(event)
}

override func responds(to selector: Selector!) -> Bool {
// Deactivate toolbar interactions from the Main Menu.
if selector == #selector(NSWindow.toggleToolbarShown(_:)) {
return false
}

return super.responds(to: selector)
}
}
5 changes: 3 additions & 2 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,8 @@ public final class PreferencesWindowController: NSWindowController {
init(
preferencePanes: [PreferencePane],
style: PreferencesStyle = .toolbarItems,
animated: Bool = true
animated: Bool = true,
hidesToolbarForSingleItem: Bool = true
)

func show(preferencePane: PreferencePaneIdentifier? = nil)
Expand Down Expand Up @@ -212,7 +213,7 @@ The `PreferencesWindowController` adheres to the [Apple HIG](https://developer.a
- [DockProgress](https://github.com/sindresorhus/DockProgress) - Show progress in your app's Dock icon
- [More…](https://github.com/search?q=user%3Asindresorhus+language%3Aswift)

You might also like my [apps](https://sindresorhus.com/apps).
You might also like Sindre's [apps](https://sindresorhus.com/apps).


## Maintainers
Expand Down

0 comments on commit 27f4b3e

Please sign in to comment.