tangled
alpha
login
or
join now
jonmsterling.com
/
AquaKit
4
fork
atom
A collection of user interface components and drawing routines for building tasteful apps using AppKit.
appkit
swift
aqua
ui
mac
4
fork
atom
overview
issues
1
pulls
pipelines
Orientation => Axis
jonmsterling.com
3 weeks ago
130d4999
ea138dc8
+184
-51
5 changed files
expand all
collapse all
unified
split
Sources
AquaKit
General Purpose
Geometry
Orientation.swift
ViewGeometry.swift
Scroll Views
AquaScrollState.swift
AquaScroller.swift
Web Views
AquaWebViewController.swift
-40
Sources/AquaKit/General Purpose/Geometry/Orientation.swift
···
1
-
import AppKit
2
-
3
-
public enum Orientation {
4
-
case vertical
5
-
case horizontal
6
-
}
7
-
8
-
extension NSSize {
9
-
public subscript(orientation: Orientation) -> CGFloat {
10
-
get {
11
-
switch orientation {
12
-
case .vertical: height
13
-
case .horizontal: width
14
-
}
15
-
}
16
-
set {
17
-
switch orientation {
18
-
case .vertical: height = newValue
19
-
case .horizontal: width = newValue
20
-
}
21
-
}
22
-
}
23
-
}
24
-
25
-
extension NSPoint {
26
-
public subscript(orientation: Orientation) -> CGFloat {
27
-
get {
28
-
switch orientation {
29
-
case .vertical: y
30
-
case .horizontal: x
31
-
}
32
-
}
33
-
set {
34
-
switch orientation {
35
-
case .vertical: y = newValue
36
-
case .horizontal: x = newValue
37
-
}
38
-
}
39
-
}
40
-
}
···
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
+173
Sources/AquaKit/General Purpose/Geometry/ViewGeometry.swift
···
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
···
1
+
import Cocoa
2
+
3
+
public enum Axis {
4
+
case horizontal
5
+
case vertical
6
+
}
7
+
8
+
public enum Extreme {
9
+
case min
10
+
case max
11
+
}
12
+
13
+
extension Axis {
14
+
public var opposite: Axis {
15
+
switch self {
16
+
case .horizontal: .vertical
17
+
case .vertical: .horizontal
18
+
}
19
+
}
20
+
}
21
+
22
+
extension NSRectEdge {
23
+
public var opposite: Self? {
24
+
switch self {
25
+
case .minX: .maxX
26
+
case .maxX: .minX
27
+
case .minY: .maxY
28
+
case .maxY: .minY
29
+
@unknown default: nil
30
+
}
31
+
}
32
+
33
+
public var axis: Axis? {
34
+
switch self {
35
+
case .minX, .maxX: .horizontal
36
+
case .minY, .maxY: .vertical
37
+
@unknown default: nil
38
+
}
39
+
}
40
+
41
+
public var extreme: Extreme? {
42
+
switch self {
43
+
case .minX, .minY: .min
44
+
case .maxX, .maxY: .max
45
+
@unknown default: nil
46
+
}
47
+
}
48
+
49
+
public var split: (axis: Axis, extreme: Extreme)? {
50
+
switch self {
51
+
case .minX: (.horizontal, .min)
52
+
case .minY: (.vertical, .min)
53
+
case .maxX: (.horizontal, .max)
54
+
case .maxY: (.vertical, .max)
55
+
@unknown default: nil
56
+
}
57
+
}
58
+
59
+
public var counterclockwiseNextEdge: Self? {
60
+
switch self {
61
+
case .minX: .minY
62
+
case .minY: .maxX
63
+
case .maxX: .maxY
64
+
case .maxY: .minX
65
+
@unknown default: nil
66
+
}
67
+
}
68
+
69
+
public var clockwiseNextEdge: Self? {
70
+
switch self {
71
+
case .minX: .maxY
72
+
case .maxY: .maxX
73
+
case .maxX: .minY
74
+
case .minY: .minX
75
+
@unknown default: nil
76
+
}
77
+
}
78
+
}
79
+
80
+
extension NSPoint {
81
+
public subscript(_ axis: Axis) -> CGFloat {
82
+
get {
83
+
switch axis {
84
+
case .horizontal: x
85
+
case .vertical: y
86
+
}
87
+
}
88
+
set {
89
+
switch axis {
90
+
case .horizontal: x = newValue
91
+
case .vertical: y = newValue
92
+
}
93
+
}
94
+
}
95
+
}
96
+
97
+
extension NSSize {
98
+
public init(extent: CGFloat, coextent: CGFloat, axis: Axis) {
99
+
self =
100
+
switch axis {
101
+
case .horizontal: NSSize(width: extent, height: coextent)
102
+
case .vertical: NSSize(width: coextent, height: extent)
103
+
}
104
+
}
105
+
106
+
public subscript(_ axis: Axis) -> CGFloat {
107
+
get {
108
+
switch axis {
109
+
case .horizontal: width
110
+
case .vertical: height
111
+
}
112
+
}
113
+
set {
114
+
switch axis {
115
+
case .horizontal: width = newValue
116
+
case .vertical: height = newValue
117
+
}
118
+
}
119
+
}
120
+
}
121
+
122
+
extension NSRectEdge {
123
+
public func spaceAvailable(from parentRect: CGRect, in screenRect: CGRect) -> CGFloat {
124
+
switch self {
125
+
case .minX: parentRect.minX - screenRect.minX
126
+
case .maxX: screenRect.maxX - parentRect.maxX
127
+
case .minY: parentRect.minY - screenRect.minY
128
+
case .maxY: screenRect.maxY - parentRect.maxY
129
+
@unknown default: 0
130
+
}
131
+
}
132
+
}
133
+
134
+
extension CGFloat {
135
+
public mutating func clamp(lowerBound: Self?, upperBound: Self?) {
136
+
if let lowerBound {
137
+
self = CGFloat.maximum(self, lowerBound)
138
+
}
139
+
if let upperBound {
140
+
self = CGFloat.minimum(self, upperBound)
141
+
}
142
+
}
143
+
144
+
public func clamped(lowerBound: Self?, upperBound: Self?) -> Self {
145
+
var copy = self
146
+
copy.clamp(lowerBound: lowerBound, upperBound: upperBound)
147
+
return copy
148
+
}
149
+
}
150
+
151
+
extension NSEdgeInsets {
152
+
public subscript(_ edge: NSRectEdge) -> CGFloat? {
153
+
get {
154
+
switch edge {
155
+
case .minX: left
156
+
case .maxX: right
157
+
case .minY: bottom
158
+
case .maxY: top
159
+
@unknown default: nil
160
+
}
161
+
}
162
+
set {
163
+
guard let newValue else { return }
164
+
switch edge {
165
+
case .minX: left = newValue
166
+
case .maxX: right = newValue
167
+
case .minY: bottom = newValue
168
+
case .maxY: top = newValue
169
+
@unknown default: break
170
+
}
171
+
}
172
+
}
173
+
}
+3
-3
Sources/AquaKit/Scroll Views/AquaScrollState.swift
···
1
-
import Foundation
2
import AppKit
0
3
4
public struct AquaScrollState {
5
public var scrollPosition: NSPoint
6
public var contentSize: NSSize
7
public var visibleSize: NSSize
8
-
9
public init(scrollPosition: NSPoint, contentSize: NSSize, visibleSize: NSSize) {
10
self.scrollPosition = scrollPosition
11
self.contentSize = contentSize
···
47
48
49
extension NSScroller {
50
-
public func adopt(state: AquaScrollState, orientation: Orientation) {
51
let maxOffset = state.maxOffset
52
let effectiveContentSize = state.effectiveContentSize
53
knobProportion = min(max(state.visibleSize[orientation] / effectiveContentSize[orientation], 0.0), 1.0)
···
0
1
import AppKit
2
+
import Foundation
3
4
public struct AquaScrollState {
5
public var scrollPosition: NSPoint
6
public var contentSize: NSSize
7
public var visibleSize: NSSize
8
+
9
public init(scrollPosition: NSPoint, contentSize: NSSize, visibleSize: NSSize) {
10
self.scrollPosition = scrollPosition
11
self.contentSize = contentSize
···
47
48
49
extension NSScroller {
50
+
public func adopt(state: AquaScrollState, orientation: Axis) {
51
let maxOffset = state.maxOffset
52
let effectiveContentSize = state.effectiveContentSize
53
knobProportion = min(max(state.visibleSize[orientation] / effectiveContentSize[orientation], 0.0), 1.0)
+7
-7
Sources/AquaKit/Scroll Views/AquaScroller.swift
···
2
import AquaKit
3
4
public class AquaScroller: NSScroller {
5
-
public let orientation: Orientation
6
7
public override var floatValue: Float {
8
didSet { setNeedsDisplay(bounds) }
···
12
didSet { setNeedsDisplay(bounds) }
13
}
14
15
-
public required init(orientation: Orientation) {
16
self.orientation = orientation
17
super.init(frame: .zero)
18
addSubview(WindowStateSentinelView())
···
221
222
let shineGradient = NSGradient(colors: [
223
.white,
224
-
.white.withAlphaComponent(isInKeyWindow ? 0.4 : 0.8),
225
])!
226
227
let shineRect = axis.rect(
···
243
let glowGradient = NSGradient(colors: [
244
.clear,
245
.clear,
246
-
baseColor.highlight(withLevel: 0.6)!,
247
])!
248
249
let glowPath = NSBezierPath(
···
263
let glowGradient = NSGradient(colors: [
264
baseColor.highlight(withLevel: 0.6)!,
265
.clear,
266
-
.clear,
267
])!
268
269
let glowPath = NSBezierPath(
···
309
}
310
}
311
312
-
extension Orientation {
313
/// The affine transform that maps between screen space and canonical (vertical)
314
/// coordinate space. For vertical this is the identity; for horizontal it swaps
315
/// the x and y axes. This transform is its own inverse.
···
355
let b = bounds.applying(transform)
356
return [
357
(NSPoint(x: b.minX, y: b.minY).applying(transform), NSPoint(x: b.minX, y: b.maxY).applying(transform)),
358
-
(NSPoint(x: b.maxX, y: b.minY).applying(transform), NSPoint(x: b.maxX, y: b.maxY).applying(transform)),
359
]
360
}
361
}
···
2
import AquaKit
3
4
public class AquaScroller: NSScroller {
5
+
public let orientation: Axis
6
7
public override var floatValue: Float {
8
didSet { setNeedsDisplay(bounds) }
···
12
didSet { setNeedsDisplay(bounds) }
13
}
14
15
+
public required init(orientation: Axis) {
16
self.orientation = orientation
17
super.init(frame: .zero)
18
addSubview(WindowStateSentinelView())
···
221
222
let shineGradient = NSGradient(colors: [
223
.white,
224
+
.white.withAlphaComponent(isInKeyWindow ? 0.4 : 0.8)
225
])!
226
227
let shineRect = axis.rect(
···
243
let glowGradient = NSGradient(colors: [
244
.clear,
245
.clear,
246
+
baseColor.highlight(withLevel: 0.6)!
247
])!
248
249
let glowPath = NSBezierPath(
···
263
let glowGradient = NSGradient(colors: [
264
baseColor.highlight(withLevel: 0.6)!,
265
.clear,
266
+
.clear
267
])!
268
269
let glowPath = NSBezierPath(
···
309
}
310
}
311
312
+
extension Axis {
313
/// The affine transform that maps between screen space and canonical (vertical)
314
/// coordinate space. For vertical this is the identity; for horizontal it swaps
315
/// the x and y axes. This transform is its own inverse.
···
355
let b = bounds.applying(transform)
356
return [
357
(NSPoint(x: b.minX, y: b.minY).applying(transform), NSPoint(x: b.minX, y: b.maxY).applying(transform)),
358
+
(NSPoint(x: b.maxX, y: b.minY).applying(transform), NSPoint(x: b.maxX, y: b.maxY).applying(transform))
359
]
360
}
361
}
+1
-1
Sources/AquaKit/Web Views/AquaWebViewController.swift
···
90
extension WKWebView {
91
fileprivate func scroll(
92
toFraction fraction: Double,
93
-
orientation: Orientation,
94
completionHandler: (@MainActor (Any?, (any Error)?) -> Void)? = nil
95
) {
96
let script =
···
90
extension WKWebView {
91
fileprivate func scroll(
92
toFraction fraction: Double,
93
+
orientation: Axis,
94
completionHandler: (@MainActor (Any?, (any Error)?) -> Void)? = nil
95
) {
96
let script =