-
-
Notifications
You must be signed in to change notification settings - Fork 101
/
SegmentedControlStyleViewController.swift
143 lines (116 loc) · 4.4 KB
/
SegmentedControlStyleViewController.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
import Cocoa
extension NSToolbarItem.Identifier {
static var toolbarSegmentedControlItem: NSToolbarItem.Identifier {
NSToolbarItem.Identifier("toolbarSegmentedControlItem")
}
}
extension NSUserInterfaceItemIdentifier {
static var toolbarSegmentedControl: NSUserInterfaceItemIdentifier {
NSUserInterfaceItemIdentifier("toolbarSegmentedControl")
}
}
final class SegmentedControlStyleViewController: NSViewController, PreferencesStyleController {
var segmentedControl: NSSegmentedControl! {
get { view as? NSSegmentedControl }
set {
view = newValue
}
}
var isKeepingWindowCentered: Bool { true }
weak var delegate: PreferencesStyleControllerDelegate?
private var preferencePanes: [PreferencePane]!
required init(preferencePanes: [PreferencePane]) {
super.init(nibName: nil, bundle: nil)
self.preferencePanes = preferencePanes
}
@available(*, unavailable)
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func loadView() {
view = createSegmentedControl(preferencePanes: preferencePanes)
}
fileprivate func createSegmentedControl(preferencePanes: [PreferencePane]) -> NSSegmentedControl {
let segmentedControl = NSSegmentedControl()
segmentedControl.segmentCount = preferencePanes.count
segmentedControl.segmentStyle = .texturedSquare
segmentedControl.target = self
segmentedControl.action = #selector(segmentedControlAction)
segmentedControl.identifier = .toolbarSegmentedControl
if let cell = segmentedControl.cell as? NSSegmentedCell {
cell.controlSize = .regular
cell.trackingMode = .selectOne
}
let segmentSize: CGSize = {
let insets = CGSize(width: 36, height: 12)
var maxSize = CGSize.zero
for preferencePane in preferencePanes {
let title = preferencePane.preferencePaneTitle
let titleSize = title.size(
withAttributes: [
.font: NSFont.systemFont(ofSize: NSFont.systemFontSize(for: .regular))
]
)
maxSize = CGSize(
width: max(titleSize.width, maxSize.width),
height: max(titleSize.height, maxSize.height)
)
}
return CGSize(
width: maxSize.width + insets.width,
height: maxSize.height + insets.height
)
}()
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, 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)
}
}
return segmentedControl
}
@IBAction private func segmentedControlAction(_ control: NSSegmentedControl) {
delegate?.activateTab(index: control.selectedSegment, animated: true)
}
func selectTab(index: Int) {
segmentedControl.selectedSegment = index
}
func toolbarItemIdentifiers() -> [NSToolbarItem.Identifier] {
[
.flexibleSpace,
.toolbarSegmentedControlItem,
.flexibleSpace
]
}
func toolbarItem(preferenceIdentifier: PreferencePane.Identifier) -> NSToolbarItem? {
let toolbarItemIdentifier = preferenceIdentifier.toolbarItemIdentifier
precondition(toolbarItemIdentifier == .toolbarSegmentedControlItem)
// When the segments outgrow the window, we need to provide a group of
// NSToolbarItems with custom menu item labels and action handling for the
// context menu that pops up at the right edge of the window.
let toolbarItemGroup = NSToolbarItemGroup(itemIdentifier: toolbarItemIdentifier)
toolbarItemGroup.view = segmentedControl
toolbarItemGroup.subitems = preferencePanes.enumerated().map { index, preferenceable -> NSToolbarItem in
let item = NSToolbarItem(itemIdentifier: .init("segment-\(preferenceable.preferencePaneTitle)"))
item.label = preferenceable.preferencePaneTitle
let menuItem = NSMenuItem(
title: preferenceable.preferencePaneTitle,
action: #selector(segmentedControlMenuAction),
keyEquivalent: ""
)
menuItem.tag = index
menuItem.target = self
item.menuFormRepresentation = menuItem
return item
}
return toolbarItemGroup
}
@IBAction private func segmentedControlMenuAction(_ menuItem: NSMenuItem) {
delegate?.activateTab(index: menuItem.tag, animated: true)
}
}