Skip to content

Commit f347442

Browse files
committed
Refactor. Rename module to STAnnotationsPlugin
1 parent b80a135 commit f347442

13 files changed

+159
-132
lines changed

DemoApp/DemoApp.xcodeproj/project.pbxproj

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
objects = {
88

99
/* Begin PBXBuildFile section */
10-
752C90732AB1AF12006C835E /* LabelView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 752C90722AB1AF12006C835E /* LabelView.swift */; };
10+
752C90732AB1AF12006C835E /* AnnotationLabelView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 752C90722AB1AF12006C835E /* AnnotationLabelView.swift */; };
1111
752C90752AB1FA5F006C835E /* MessageLineAnnotation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 752C90742AB1FA5F006C835E /* MessageLineAnnotation.swift */; };
1212
7565EBBE2A9BE09D0005B170 /* EditorViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7565EBBD2A9BE09D0005B170 /* EditorViewController.swift */; };
1313
7565EBC12A9BE0B10005B170 /* STTextView in Frameworks */ = {isa = PBXBuildFile; productRef = 7565EBC02A9BE0B10005B170 /* STTextView */; };
@@ -18,7 +18,7 @@
1818
/* End PBXBuildFile section */
1919

2020
/* Begin PBXFileReference section */
21-
752C90722AB1AF12006C835E /* LabelView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LabelView.swift; sourceTree = "<group>"; };
21+
752C90722AB1AF12006C835E /* AnnotationLabelView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AnnotationLabelView.swift; sourceTree = "<group>"; };
2222
752C90742AB1FA5F006C835E /* MessageLineAnnotation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageLineAnnotation.swift; sourceTree = "<group>"; };
2323
7565EBBD2A9BE09D0005B170 /* EditorViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EditorViewController.swift; sourceTree = "<group>"; };
2424
7576EDCA2AB0627D00540BF5 /* STTextView-Plugin-Annotations */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = "STTextView-Plugin-Annotations"; path = ..; sourceTree = "<group>"; };
@@ -27,6 +27,7 @@
2727
758BAB542A9BDFC300D840BF /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
2828
758BAB572A9BDFC300D840BF /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = "<group>"; };
2929
758BAB592A9BDFC300D840BF /* DemoApp.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DemoApp.entitlements; sourceTree = "<group>"; };
30+
75E3BF172B6305B800680EE4 /* STTextView */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = STTextView; path = ../../STTextView; sourceTree = "<group>"; };
3031
/* End PBXFileReference section */
3132

3233
/* Begin PBXFrameworksBuildPhase section */
@@ -52,10 +53,11 @@
5253
758BAB462A9BDFC200D840BF = {
5354
isa = PBXGroup;
5455
children = (
56+
75E3BF172B6305B800680EE4 /* STTextView */,
5557
7576EDCA2AB0627D00540BF5 /* STTextView-Plugin-Annotations */,
58+
7590AFEA2B64617E00947F82 /* View */,
59+
7590AFE92B64617300947F82 /* Model */,
5660
7565EBBD2A9BE09D0005B170 /* EditorViewController.swift */,
57-
752C90722AB1AF12006C835E /* LabelView.swift */,
58-
752C90742AB1FA5F006C835E /* MessageLineAnnotation.swift */,
5961
758BAB522A9BDFC200D840BF /* AppDelegate.swift */,
6062
758BAB542A9BDFC300D840BF /* Assets.xcassets */,
6163
758BAB562A9BDFC300D840BF /* MainMenu.xib */,
@@ -73,6 +75,22 @@
7375
name = Products;
7476
sourceTree = "<group>";
7577
};
78+
7590AFE92B64617300947F82 /* Model */ = {
79+
isa = PBXGroup;
80+
children = (
81+
752C90742AB1FA5F006C835E /* MessageLineAnnotation.swift */,
82+
);
83+
path = Model;
84+
sourceTree = "<group>";
85+
};
86+
7590AFEA2B64617E00947F82 /* View */ = {
87+
isa = PBXGroup;
88+
children = (
89+
752C90722AB1AF12006C835E /* AnnotationLabelView.swift */,
90+
);
91+
path = View;
92+
sourceTree = "<group>";
93+
};
7694
/* End PBXGroup section */
7795

7896
/* Begin PBXNativeTarget section */
@@ -151,7 +169,7 @@
151169
buildActionMask = 2147483647;
152170
files = (
153171
758BAB532A9BDFC200D840BF /* AppDelegate.swift in Sources */,
154-
752C90732AB1AF12006C835E /* LabelView.swift in Sources */,
172+
752C90732AB1AF12006C835E /* AnnotationLabelView.swift in Sources */,
155173
752C90752AB1FA5F006C835E /* MessageLineAnnotation.swift in Sources */,
156174
7565EBBE2A9BE09D0005B170 /* EditorViewController.swift in Sources */,
157175
);

DemoApp/EditorViewController.swift

Lines changed: 35 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
import AppKit
22
import STTextView
33

4-
import AnnotationsPlugin
4+
import STAnnotationsPlugin
55

66
final class EditorViewController: NSViewController {
77

8-
private var annotationsPlugin: AnnotationsPlugin!
8+
private var annotationsPlugin: STAnnotationsPlugin!
99
private var textView: STTextView!
1010
private var annotations: [MessageLineAnnotation] = [] {
1111
didSet {
@@ -23,7 +23,7 @@ final class EditorViewController: NSViewController {
2323
super.viewDidLoad()
2424
view.frame.size = CGSize(width: 500, height: 500)
2525

26-
annotationsPlugin = AnnotationsPlugin(dataSource: self)
26+
annotationsPlugin = STAnnotationsPlugin(dataSource: self)
2727

2828
textView.addPlugin(
2929
annotationsPlugin
@@ -32,72 +32,57 @@ final class EditorViewController: NSViewController {
3232
textView.backgroundColor = .controlBackgroundColor
3333
textView.font = .monospacedSystemFont(ofSize: 0, weight: .regular)
3434

35+
let defaultParagraphStyle = NSParagraphStyle.default.mutableCopy() as! NSMutableParagraphStyle
36+
// defaultParagraphStyle.lineHeightMultiple = 1.5
37+
38+
textView.defaultParagraphStyle = defaultParagraphStyle
39+
3540
textView.string = """
3641
import Foundation
3742
38-
func hello() {
39-
print("Hello World!")
43+
func main() {
44+
print("Hello World!)
4045
}
4146
"""
4247

4348
// add annotation
44-
do {
45-
let stringRange = textView.string.startIndex..<textView.string.endIndex
46-
if let ocurrenceRange = textView.string.range(of: "Foundation", range: stringRange) {
47-
let characterLocationOffset = textView.string.distance(from: textView.string.startIndex, to: ocurrenceRange.upperBound)
48-
let annotation = try! MessageLineAnnotation(
49-
message: AttributedString(markdown: "**TODO**: to cry _or_ not to cry"),
50-
location: textView.textLayoutManager.location(textView.textLayoutManager.documentRange.location, offsetBy: characterLocationOffset)!
51-
)
52-
annotations.append(annotation)
53-
}
54-
}
49+
let annotation1 = try! MessageLineAnnotation(
50+
message: AttributedString(markdown: "Swift Foundation framework"),
51+
kind: .info,
52+
location: textView.textLayoutManager.location(textView.textLayoutManager.documentRange.location, offsetBy: 17)!
53+
)
54+
55+
let annotation2 = try! MessageLineAnnotation(
56+
message: AttributedString(markdown: "**ERROR**: Missing \" at the end of the string literal"),
57+
kind: .error,
58+
location: textView.textLayoutManager.location(textView.textLayoutManager.documentRange.location, offsetBy: 56)!
59+
)
60+
61+
annotations += [annotation1, annotation2]
5562
}
5663
}
5764

5865
import SwiftUI
5966

60-
extension EditorViewController: AnnotationsDataSource {
61-
62-
private func removeAnnotation(_ annotation: MessageLineAnnotation) {
63-
annotations.removeAll(where: { $0.id == annotation.id })
64-
}
67+
extension EditorViewController: STAnnotationsDataSource {
6568

66-
func textView(_ textView: STTextView, viewForLineAnnotation lineAnnotation: any LineAnnotation, textLineFragment: NSTextLineFragment) -> NSView? {
67-
guard let myLineAnnotation = lineAnnotation as? MessageLineAnnotation else {
69+
func textView(_ textView: STTextView, viewForLineAnnotation lineAnnotation: any STLineAnnotation, textLineFragment: NSTextLineFragment, proposedViewFrame: CGRect) -> NSView? {
70+
guard let lineAnnotation = lineAnnotation as? MessageLineAnnotation else {
6871
assertionFailure()
6972
return nil
7073
}
7174

72-
let messageFont = NSFont.preferredFont(forTextStyle: .body)
73-
74-
let decorationView = AnnotationView(
75-
LabelView(
76-
message: myLineAnnotation.message,
77-
action: { [weak self] annotation in
78-
self?.removeAnnotation(annotation)
79-
},
80-
lineAnnotation: myLineAnnotation
81-
)
82-
.font(Font(messageFont))
83-
)
84-
85-
// Position
86-
87-
let segmentFrame = textView.textLayoutManager.textSegmentFrame(at: myLineAnnotation.location, type: .standard)!
88-
let annotationHeight = min(textLineFragment.typographicBounds.height, textView.font?.boundingRectForFont.height ?? 24)
89-
90-
decorationView.frame = CGRect(
91-
x: segmentFrame.maxX,
92-
y: segmentFrame.minY + (segmentFrame.height - annotationHeight),
93-
width: textView.visibleRect.maxX - segmentFrame.maxX,
94-
height: annotationHeight
95-
)
96-
return decorationView
75+
return STAnnotationView(frame: proposedViewFrame) {
76+
AnnotationLabelView(Text(lineAnnotation.message), annotation: lineAnnotation) { [weak self] annotation in
77+
// Remove annotation
78+
self?.annotations.removeAll(where: { $0.id == annotation.id })
79+
}
80+
.font(.body)
81+
}
9782
}
9883

99-
func textViewAnnotations() -> [any LineAnnotation] {
84+
85+
func textViewAnnotations() -> [any STLineAnnotation] {
10086
annotations
10187
}
102-
10388
}

DemoApp/MessageLineAnnotation.swift

Lines changed: 0 additions & 12 deletions
This file was deleted.
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import Cocoa
2+
import STAnnotationsPlugin
3+
4+
enum AnnotationKind {
5+
case info
6+
case warning
7+
case error
8+
}
9+
10+
final class MessageLineAnnotation: NSObject, STLineAnnotation {
11+
var location: NSTextLocation
12+
let message: AttributedString
13+
let kind: AnnotationKind
14+
15+
init(message: AttributedString, kind: AnnotationKind, location: NSTextLocation) {
16+
self.message = message
17+
self.kind = kind
18+
self.location = location
19+
}
20+
}

DemoApp/LabelView.swift renamed to DemoApp/View/AnnotationLabelView.swift

Lines changed: 34 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,29 @@
44
import SwiftUI
55
import Foundation
66
import STTextView
7-
import AnnotationsPlugin
7+
import STAnnotationsPlugin
88

9-
struct LabelView<T: LineAnnotation>: View {
10-
let message: AttributedString
11-
let action: (T) -> Void
12-
let lineAnnotation: T
9+
struct AnnotationLabelView : View {
10+
@Environment(\.colorScheme) private var colorScheme
11+
12+
private let text: Text
13+
private let annotation: MessageLineAnnotation
14+
private let action: (MessageLineAnnotation) -> Void
15+
16+
init(_ text: Text, annotation: MessageLineAnnotation, action: @escaping (MessageLineAnnotation) -> Void) {
17+
self.text = text
18+
self.action = action
19+
self.annotation = annotation
20+
}
1321

1422
var body: some View {
1523
Label {
16-
Text(message)
24+
text
1725
.foregroundColor(.primary)
1826
.frame(maxWidth: .infinity, alignment: .leading)
1927
} icon: {
2028
Button {
21-
action(lineAnnotation)
29+
action(annotation)
2230
} label: {
2331
ZStack {
2432
// the way it draws bothers me
@@ -34,9 +42,12 @@ struct LabelView<T: LineAnnotation>: View {
3442
}
3543
.buttonStyle(.plain)
3644
}
37-
.background(Color.yellow)
38-
.clipShape(UnevenRoundedRectangle(cornerRadii: RectangleCornerRadii(topLeading: 4, bottomLeading: 4, bottomTrailing: 0, topTrailing: 0), style: .circular))
45+
.background(
46+
annotation.kind.color.background(Color.white)
47+
)
48+
.clipShape(UnevenRoundedRectangle(cornerRadii: RectangleCornerRadii(topLeading: 2, bottomLeading: 2), style: .circular))
3949
.labelStyle(AnnotationLabelStyle())
50+
.shadow(radius: 1, x: 0.3, y: 0.5)
4051
}
4152
}
4253

@@ -64,3 +75,17 @@ private struct AnnotationLabelStyle: LabelStyle {
6475
}
6576
}
6677
}
78+
79+
private extension AnnotationKind {
80+
var color: Color {
81+
switch self {
82+
case .info:
83+
Color.accentColor.opacity(0.2)
84+
case .warning:
85+
Color.yellow.opacity(0.2)
86+
case .error:
87+
Color.red.opacity(0.2)
88+
}
89+
}
90+
91+
}

Package.swift

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,24 +2,21 @@
22

33
import PackageDescription
44

5-
let pluginName = "Annotations"
6-
let pluginTargetName = "\(pluginName)Plugin"
7-
85
let package = Package(
9-
name: "STTextView-Plugin-\(pluginName)",
6+
name: "STTextView-Plugin-Annotations",
107
platforms: [.macOS(.v12)],
118
products: [
129
.library(
13-
name: "STTextView\(pluginName)Plugin",
14-
targets: [pluginTargetName]
10+
name: "STTextViewAnnotationsPlugin",
11+
targets: ["STAnnotationsPlugin"]
1512
)
1613
],
1714
dependencies: [
18-
.package(url: "https://github.com/krzyzanowskim/STTextView", from: "0.8.22")
15+
.package(url: "https://github.com/krzyzanowskim/STTextView", from: "0.8.23")
1916
],
2017
targets: [
2118
.target(
22-
name: pluginTargetName,
19+
name: "STAnnotationsPlugin",
2320
dependencies: [
2421
.product(name: "STTextView", package: "STTextView")
2522
]

README.md

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,15 @@
55
Add the plugin package as a dependency of your application, then register/add it to the STTextView instance:
66

77
```swift
8-
import AnnotationsPlugin
8+
import STAnnotationsPlugin
99

1010
// Implement AnnotationsDataSource protocol to provide annotations
11-
annotationsPlugin = AnnotationsPlugin(dataSource: self)
11+
let plugin = STAnnotationsPlugin(dataSource: self)
1212

13-
textView.addPlugin(
14-
annotationsPlugin
15-
)
13+
// Add/register plugin in the STTextView instance
14+
textView.addPlugin(plugin)
1615
```
1716

1817
Check DemoApp for reference implementation
1918

20-
<img width="499" alt="Screenshot 2023-09-13 at 19 00 09" src="https://github.com/krzyzanowskim/STTextView-Plugin-Annotations/assets/758033/49f6392b-fbce-47e9-a6ee-f4828c095cbd">
19+
<img width="499" alt="Demo9" src="https://github.com/krzyzanowskim/STTextView-Plugin-Annotations/assets/758033/ce1e2050-977e-4be9-b78c-81023d66b4f2">

Sources/AnnotationsPlugin/AnnotationsDataSource.swift

Lines changed: 0 additions & 14 deletions
This file was deleted.
File renamed without changes.

0 commit comments

Comments
 (0)