Skip to content

Commit 04f56c8

Browse files
committed
Converted project to use Swift Package Manager and updated to Swift 5.3
1 parent 9339866 commit 04f56c8

20 files changed

+351
-780
lines changed

.gitignore

+5-1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@ DerivedData
1616
*.hmap
1717
*.ipa
1818

19+
# Swift Package Manager
20+
.build
21+
Package.resolved
22+
1923
# CocoaPods
2024
#
2125
# We recommend against adding the Pods directory to your .gitignore. However
@@ -27,7 +31,7 @@ Pods/
2731
# Sublime Text
2832
*.sublime-workspace
2933

30-
# OS X
34+
# macOS
3135
.DS_Store
3236
Icon?
3337

ModernAppKit.xcodeproj/project.xcworkspace/contents.xcworkspacedata .swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

LICENSE.md

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# MIT License
2+
3+
Copyright © 2016–2020 Darren Mo.
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6+
7+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8+
9+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

ModernAppKit.xcodeproj/project.pbxproj

-500
This file was deleted.

ModernAppKit.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist

-8
This file was deleted.

ModernAppKit.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings

-8
This file was deleted.

Package.swift

+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
// swift-tools-version:5.3
2+
3+
import PackageDescription
4+
5+
let package = Package(
6+
name: "ModernAppKit",
7+
platforms: [
8+
.macOS(.v10_11),
9+
],
10+
products: [
11+
.library(
12+
name: "MAKAutoLayoutTextView",
13+
targets: [
14+
"MAKAutoLayoutTextView",
15+
]
16+
),
17+
.library(
18+
name: "MAKLayerView",
19+
targets: [
20+
"MAKLayerView",
21+
]
22+
),
23+
.library(
24+
name: "MAKShadowView",
25+
targets: [
26+
"MAKShadowView",
27+
]
28+
),
29+
],
30+
targets: [
31+
.target(
32+
name: "MAKAutoLayoutTextView",
33+
dependencies: [
34+
"MAKEagerTextStorage",
35+
]
36+
),
37+
.target(
38+
name: "MAKEagerTextStorage"
39+
),
40+
.target(
41+
name: "MAKLayerView"
42+
),
43+
.target(
44+
name: "MAKShadowView"
45+
),
46+
]
47+
)

README.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# ModernAppKit
22
An assortment of enhancements to AppKit to support modern app development. Addresses deficiencies in Auto Layout support, layer-backed views, and shadows.
33

4-
Requires Swift 4.2. Tested on macOS 10.14. MIT license.
4+
Requires Swift 5.3+. Tested on macOS 11. MIT license.
55

66
## AutoLayoutTextView
77
An `NSTextView` subclass that implements `intrinsicContentSize` so that the text view can participate in layout outside of a scroll view.
@@ -13,4 +13,4 @@ An `AutoLayoutTextView` subclass that acts like a label. Specifically, it is non
1313
A layer-backed view with additional APIs for setting background color, border width, border color, and corner radius. Use if you do not need to do custom drawing. Supports animations.
1414

1515
## ShadowView
16-
A container view that draws a rectangular shadow underneath its content view in a performant manner.
16+
A container view that draws a rectangular shadow underneath its content view in a performant manner.

Sources/Info.plist

-26
This file was deleted.

Sources/AutoLayoutTextView/AutoLayoutTextView.swift Sources/MAKAutoLayoutTextView/AutoLayoutTextView.swift

+77-66
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// MIT License
22
//
3-
// Copyright © 2016-2019 Darren Mo.
3+
// Copyright © 2016-2020 Darren Mo.
44
//
55
// Permission is hereby granted, free of charge, to any person obtaining a copy
66
// of this software and associated documentation files (the "Software"), to deal
@@ -21,9 +21,13 @@
2121
// SOFTWARE.
2222

2323
import Cocoa
24+
import MAKEagerTextStorage
2425

2526
/// An `NSTextView` subclass that implements `intrinsicContentSize` so that the text view
2627
/// can participate in layout outside of a scroll view.
28+
///
29+
/// - Attention: The text storage must be an instance of `EagerTextStorage`.
30+
/// - Attention: The layout manager must be an instance of `EagerLayoutManager`.
2731
open class AutoLayoutTextView: NSTextView {
2832
// MARK: Text Components
2933

@@ -46,37 +50,49 @@ open class AutoLayoutTextView: NSTextView {
4650
willSet {
4751
if let layoutManager = _layoutManager {
4852
NotificationCenter.default.removeObserver(self,
49-
name: EagerLayoutManager.didCompleteLayout,
53+
name: EagerLayoutManager.didCompleteLayoutNotification,
5054
object: layoutManager)
5155
}
56+
57+
_textStorage = nil
58+
_layoutManager = nil
5259
}
5360

5461
didSet {
5562
if let textContainer = textContainer {
56-
if let layoutManager = textContainer.layoutManager {
57-
precondition(layoutManager is EagerLayoutManager, "AutoLayoutTextView requires the layout manager to be an instance of EagerLayoutManager.")
58-
self._layoutManager = layoutManager as? EagerLayoutManager
59-
60-
if let textStorage = layoutManager.textStorage {
61-
precondition(textStorage is EagerTextStorage, "AutoLayoutTextView requires the text storage to be an instance of EagerTextStorage.")
62-
self._textStorage = textStorage as? EagerTextStorage
63-
}
64-
}
63+
AutoLayoutTextView.setTextComponents(layoutManager: &_layoutManager,
64+
textStorage: &_textStorage,
65+
from: textContainer)
6566
}
6667

6768
if let layoutManager = _layoutManager {
6869
NotificationCenter.default.addObserver(self,
6970
selector: #selector(didCompleteLayout(_:)),
70-
name: EagerLayoutManager.didCompleteLayout,
71+
name: EagerLayoutManager.didCompleteLayoutNotification,
7172
object: layoutManager)
7273
}
7374
}
7475
}
7576

76-
// MARK: Initialization
77+
private static func setTextComponents(layoutManager layoutManagerOut: inout EagerLayoutManager?,
78+
textStorage textStorageOut: inout EagerTextStorage?,
79+
from textContainer: NSTextContainer) {
80+
if let layoutManager = textContainer.layoutManager {
81+
guard let eagerLayoutManager = layoutManager as? EagerLayoutManager else {
82+
preconditionFailure("AutoLayoutTextView requires the layout manager to be an instance of EagerLayoutManager.")
83+
}
84+
layoutManagerOut = eagerLayoutManager
7785

78-
private static let textStorageCoderKey = "mo.darren.ModernAppKit.AutoLayoutTextView._textStorage"
79-
private static let layoutManagerCoderKey = "mo.darren.ModernAppKit.AutoLayoutTextView._layoutManager"
86+
if let textStorage = eagerLayoutManager.textStorage {
87+
guard let eagerTextStorage = textStorage as? EagerTextStorage else {
88+
preconditionFailure("AutoLayoutTextView requires the text storage to be an instance of EagerTextStorage.")
89+
}
90+
textStorageOut = eagerTextStorage
91+
}
92+
}
93+
}
94+
95+
// MARK: Initialization/Deinitialization
8096

8197
public override convenience init(frame frameRect: NSRect) {
8298
let textContainer = AutoLayoutTextView.makeDefaultTextContainer(withTextViewWidth: frameRect.width)
@@ -92,53 +108,16 @@ open class AutoLayoutTextView: NSTextView {
92108

93109
public override init(frame frameRect: NSRect, textContainer container: NSTextContainer?) {
94110
if let textContainer = container {
95-
if let layoutManager = textContainer.layoutManager {
96-
precondition(layoutManager is EagerLayoutManager, "AutoLayoutTextView requires the layout manager to be an instance of EagerLayoutManager.")
97-
self._layoutManager = layoutManager as? EagerLayoutManager
98-
99-
if let textStorage = layoutManager.textStorage {
100-
precondition(textStorage is EagerTextStorage, "AutoLayoutTextView requires the text storage to be an instance of EagerTextStorage.")
101-
self._textStorage = textStorage as? EagerTextStorage
102-
}
103-
}
111+
AutoLayoutTextView.setTextComponents(layoutManager: &_layoutManager,
112+
textStorage: &_textStorage,
113+
from: textContainer)
104114
}
105115

106116
super.init(frame: frameRect, textContainer: container)
107117

108118
commonInit()
109119
}
110120

111-
public required init?(coder: NSCoder) {
112-
if let textStorage = coder.decodeObject(forKey: AutoLayoutTextView.textStorageCoderKey) as? EagerTextStorage {
113-
self._textStorage = textStorage
114-
} else {
115-
self._textStorage = EagerTextStorage()
116-
}
117-
if let layoutManager = coder.decodeObject(forKey: AutoLayoutTextView.layoutManagerCoderKey) as? EagerLayoutManager {
118-
self._layoutManager = layoutManager
119-
} else {
120-
self._layoutManager = EagerLayoutManager()
121-
}
122-
123-
super.init(coder: coder)
124-
125-
if let layoutManager = _layoutManager {
126-
_textStorage?.addLayoutManager(layoutManager)
127-
128-
if let textContainer = textContainer {
129-
layoutManager.addTextContainer(textContainer)
130-
} else {
131-
let textContainer = AutoLayoutTextView.makeDefaultTextContainer(withTextViewWidth: frame.width)
132-
layoutManager.addTextContainer(textContainer)
133-
134-
textContainer.textView = self
135-
self.textContainer = textContainer
136-
}
137-
}
138-
139-
commonInit()
140-
}
141-
142121
private func commonInit() {
143122
minSize = NSSize.zero
144123
maxSize = NSSize(width: CGFloat.infinity, height: CGFloat.infinity)
@@ -148,24 +127,17 @@ open class AutoLayoutTextView: NSTextView {
148127
if let layoutManager = _layoutManager {
149128
NotificationCenter.default.addObserver(self,
150129
selector: #selector(didCompleteLayout(_:)),
151-
name: EagerLayoutManager.didCompleteLayout,
130+
name: EagerLayoutManager.didCompleteLayoutNotification,
152131
object: layoutManager)
153132
}
154133
}
155134

156-
open override func encode(with aCoder: NSCoder) {
157-
super.encode(with: aCoder)
158-
159-
aCoder.encode(_textStorage, forKey: AutoLayoutTextView.textStorageCoderKey)
160-
aCoder.encode(_layoutManager, forKey: AutoLayoutTextView.layoutManagerCoderKey)
161-
}
162-
163135
deinit {
164136
if let layoutManager = _layoutManager {
165137
// Because NSTextView does not support weak references, NotificationCenter will not
166138
// automatically remove the observer for us.
167139
NotificationCenter.default.removeObserver(self,
168-
name: EagerLayoutManager.didCompleteLayout,
140+
name: EagerLayoutManager.didCompleteLayoutNotification,
169141
object: layoutManager)
170142
}
171143
}
@@ -179,6 +151,45 @@ open class AutoLayoutTextView: NSTextView {
179151
return textContainer
180152
}
181153

154+
// MARK: Serialization/Deserialization
155+
156+
private enum CoderKey {
157+
static let textStorage = "mo.darren.ModernAppKit.AutoLayoutTextView._textStorage"
158+
static let layoutManager = "mo.darren.ModernAppKit.AutoLayoutTextView._layoutManager"
159+
}
160+
161+
public required init?(coder: NSCoder) {
162+
if let textStorage = coder.decodeObject(forKey: CoderKey.textStorage) as? EagerTextStorage {
163+
self._textStorage = textStorage
164+
} else {
165+
self._textStorage = EagerTextStorage()
166+
}
167+
if let layoutManager = coder.decodeObject(forKey: CoderKey.layoutManager) as? EagerLayoutManager {
168+
self._layoutManager = layoutManager
169+
} else {
170+
self._layoutManager = EagerLayoutManager()
171+
}
172+
173+
super.init(coder: coder)
174+
175+
if let layoutManager = _layoutManager {
176+
_textStorage?.addLayoutManager(layoutManager)
177+
}
178+
179+
let textContainer = self.textContainer ?? AutoLayoutTextView.makeDefaultTextContainer(withTextViewWidth: frame.width)
180+
_layoutManager?.addTextContainer(textContainer)
181+
textContainer.textView = self
182+
183+
commonInit()
184+
}
185+
186+
open override func encode(with aCoder: NSCoder) {
187+
super.encode(with: aCoder)
188+
189+
aCoder.encode(_textStorage, forKey: CoderKey.textStorage)
190+
aCoder.encode(_layoutManager, forKey: CoderKey.layoutManager)
191+
}
192+
182193
// MARK: Intrinsic Content Size
183194

184195
/// Called when the layout manager completes layout.
@@ -213,8 +224,8 @@ open class AutoLayoutTextView: NSTextView {
213224
let textHeight = layoutManager.usedRect(for: textContainer).height
214225

215226
// The layout manager’s `usedRect(for:)` method returns (width of container, height of text).
216-
// We want to use the width of the text for the intrinsic content size, so we need to calculate
217-
// it ourselves.
227+
// We want to use the width of the text for the intrinsic content size instead of the width
228+
// of the container, so we need to calculate it ourselves.
218229
let textWidth = calculateTextWidth()
219230

220231
let unitSquareSize = self.unitSquareSize

0 commit comments

Comments
 (0)