Skip to content

Commit c537b3f

Browse files
committed
Add the builder.
1 parent 9886525 commit c537b3f

File tree

7 files changed

+217
-20
lines changed

7 files changed

+217
-20
lines changed

Cartfile.resolved

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
github "krzyzanowskim/CryptoSwift" "1.3.0"
2-
github "weichsel/ZIPFoundation" "0.9.10"
2+
github "weichsel/ZIPFoundation" "0.9.11"

Demo/Public/Sources/ContentView.swift

Lines changed: 51 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,9 @@ struct TopicCell: View {
5151
}
5252
}
5353

54-
struct ContentView: View {
54+
struct WorkbookView: View {
55+
56+
let loadedWorkbook: Workbook
5557

5658
private func makeRows(from topic: Topic, indentLevel: Int) -> [Row] {
5759
var rows = [Row]()
@@ -70,34 +72,68 @@ struct ContentView: View {
7072
rows.append(contentsOf: makeRows(from: sheet.rootTopic, indentLevel: 1))
7173
return rows
7274
}
73-
75+
7476
private func makeRows() -> [Row] {
75-
guard let filePath = Bundle.main.path(forResource: "example0", ofType: "xmind") else { return [] }
77+
var rows = [Row]()
78+
79+
for sheet in loadedWorkbook.allSheets {
80+
rows.append(contentsOf: makeRows(from: sheet))
81+
}
7682

83+
return rows
84+
}
85+
86+
var body: some View {
87+
List(makeRows()) {
88+
TopicCell(row: $0)
89+
}
90+
}
91+
}
92+
93+
struct ContentView: View {
94+
95+
private var example0Workbook: Workbook {
96+
guard let filePath = Bundle.main.path(forResource: "example0", ofType: "xmind") else { fatalError() }
7797
do {
7898
let wb = try Workbook.open(filePath: filePath)
7999
try wb.loadManifest()
80100
try wb.loadContent()
81-
82-
var rows = [Row]()
83-
84-
for sheet in wb.allSheets {
85-
rows.append(contentsOf: makeRows(from: sheet))
86-
}
87-
88-
return rows
101+
102+
return wb
89103

90104
} catch let error {
91105
print(error)
92-
return []
106+
fatalError()
93107
}
94108
}
95109

110+
private var builtWorkbook: Workbook {
111+
return try! workbook {
112+
topic(title: "Apple") {
113+
topic(title: "Hardware") {
114+
topic(title: "iPhone") {
115+
topic(title: "iPhone 6")
116+
topic(title: "iPhone 7 Plus")
117+
topic(title: "iPhone 8")
118+
topic(title: "iPhone XS Max")
119+
}
120+
topic(title: "Mac") {
121+
topic(title: "MacBook Pro")
122+
topic(title: "Mac mini")
123+
topic(title: "Mac Pro")
124+
}
125+
}
126+
127+
topic(title: "Software") {
128+
topic(title: "Xcode")
129+
topic(title: "Siri")
130+
}
131+
}
132+
}
133+
}
96134

97135
var body: some View {
98-
List(makeRows()) {
99-
TopicCell(row: $0)
100-
}
136+
WorkbookView(loadedWorkbook: builtWorkbook)
101137
}
102138
}
103139

Sources/Builder/Builders.swift

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
//
2+
// Builders.swift
3+
// XMindSDK
4+
//
5+
// Created by h on 2020/4/4.
6+
//
7+
// Copyright © 2020 XMind.
8+
//
9+
// Permission is hereby granted, free of charge, to any person obtaining a copy
10+
// of this software and associated documentation files (the "Software"), to deal
11+
// in the Software without restriction, including without limitation the rights
12+
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13+
// copies of the Software, and to permit persons to whom the Software is
14+
// furnished to do so, subject to the following conditions:
15+
//
16+
// The above copyright notice and this permission notice shall be included in
17+
// all copies or substantial portions of the Software.
18+
//
19+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25+
// THE SOFTWARE.
26+
27+
import Foundation
28+
29+
/// Create a new topic with the title.
30+
public func topic(title: String) -> Elements<Topic> {
31+
return Elements<Topic>(Topic(title: title))
32+
}
33+
34+
/// Create a new topic with the title and the childen.
35+
public func topic(title: String, @ElementsBuilder<Topic> childen: () -> Elements<Topic>) -> Elements<Topic> {
36+
let topic = Topic(title: title)
37+
childen().forEach { topic.addSubTopic($0) }
38+
return Elements<Topic>(topic)
39+
}
40+
41+
/// Create a new sheet by a root topic.
42+
public func sheet(title: String, rootTopic: () -> Elements<Topic>) -> Elements<Sheet> {
43+
guard let first = rootTopic().first else { return Elements<Sheet>() }
44+
return Elements<Sheet>(Sheet(title: title, rootTopic: first))
45+
}
46+
47+
/// Create a new Workbook object by sheets.
48+
public func workbook(@ElementsBuilder<Sheet> sheets: () -> Elements<Sheet>) throws -> Workbook {
49+
let workbook = try Workbook.new()
50+
sheets().forEach { workbook.add(sheet: $0) }
51+
return workbook
52+
}
53+
54+
/// Create a new Workbook object by topics.
55+
/// This function will make sheets for each root topics.
56+
public func workbook(@ElementsBuilder<Topic> childen: () -> Elements<Topic>) throws -> Workbook {
57+
try workbook {
58+
Elements<Sheet>(childen().map { Elements<Sheet>(Sheet(title: "Sheet", rootTopic: $0)) })
59+
}
60+
}

Sources/Builder/ElementsBuilder.swift

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
//
2+
// ElementsBuilder.swift
3+
// XMindSDK
4+
//
5+
// Created by h on 2020/4/4.
6+
//
7+
// Copyright © 2020 XMind.
8+
//
9+
// Permission is hereby granted, free of charge, to any person obtaining a copy
10+
// of this software and associated documentation files (the "Software"), to deal
11+
// in the Software without restriction, including without limitation the rights
12+
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13+
// copies of the Software, and to permit persons to whom the Software is
14+
// furnished to do so, subject to the following conditions:
15+
//
16+
// The above copyright notice and this permission notice shall be included in
17+
// all copies or substantial portions of the Software.
18+
//
19+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25+
// THE SOFTWARE.
26+
27+
import Foundation
28+
29+
public struct Elements<Element>: Sequence {
30+
31+
public func makeIterator() -> IndexingIterator<[Element]> {
32+
return elements.makeIterator()
33+
}
34+
35+
private var elements: [Element]
36+
37+
internal var first: Element? {
38+
elements.first
39+
}
40+
41+
internal init(_ elements: [Elements<Element>]) {
42+
self.elements = elements.flatMap { $0.elements }
43+
}
44+
45+
internal init(_ element: Element) {
46+
elements = [element]
47+
}
48+
49+
internal init() {
50+
elements = []
51+
}
52+
53+
}
54+
55+
@_functionBuilder
56+
public struct ElementsBuilder<Element> {
57+
58+
public static func buildBlock() -> Elements<Element> {
59+
return Elements<Element>()
60+
}
61+
62+
public static func buildBlock(_ elements: Elements<Element>) -> Elements<Element> {
63+
return elements
64+
}
65+
66+
public static func buildBlock(_ elements: Elements<Element>...) -> Elements<Element> {
67+
return Elements<Element>(elements)
68+
}
69+
70+
public static func buildIf(_ elements: Elements<Element>?) -> Elements<Element> {
71+
if let elements = elements {
72+
return buildBlock(elements)
73+
} else {
74+
return buildBlock()
75+
}
76+
}
77+
78+
public static func buildEither(first: Elements<Element>) -> Elements<Element> {
79+
return first
80+
}
81+
82+
public static func buildEither(second: Elements<Element>) -> Elements<Element> {
83+
return second
84+
}
85+
}

Sources/XMind/Topic.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ public class Topic: Codable {
4949
internal private(set) weak var superTopic: Topic? = nil
5050

5151

52-
public init(title: String) {
52+
public init(title: String? = nil) {
5353
self.id = UUID().uuidString
5454
self.class = "topic"
5555
self.title = title

Sources/XMind/Workbook.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ public final class Workbook {
4343

4444
private lazy var manifest: Manifest = Manifest.makeDefault()
4545

46-
private lazy var sheets: [Sheet] = [Sheet(title: "Sheet 1", rootTopic: Topic(title: "Topic 1"))]
46+
private lazy var sheets: [Sheet] = []
4747

4848
private lazy var metadata: Metadata = Metadata.makeDefault(activeSheetId: sheets.last?.id ?? "")
4949

XMindSDK.xcodeproj/project.pbxproj

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
07637CA3237BCE4200E05FE9 /* Theme.swift in Sources */ = {isa = PBXBuildFile; fileRef = 07637CA2237BCE4200E05FE9 /* Theme.swift */; };
1414
07637CA5237BD16600E05FE9 /* Point.swift in Sources */ = {isa = PBXBuildFile; fileRef = 07637CA4237BD16600E05FE9 /* Point.swift */; };
1515
07637CA7237BD27E00E05FE9 /* Marker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 07637CA6237BD27E00E05FE9 /* Marker.swift */; };
16+
0791AF4A2437BD1C00F5ECDC /* Builders.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0791AF492437BD1C00F5ECDC /* Builders.swift */; };
17+
0791AF522437E38900F5ECDC /* ElementsBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0791AF512437E38900F5ECDC /* ElementsBuilder.swift */; };
1618
07B6604023700BE4000FE35A /* Workbook.swift in Sources */ = {isa = PBXBuildFile; fileRef = 07B6603F23700BE4000FE35A /* Workbook.swift */; };
1719
07B6604223700C9B000FE35A /* Topic.swift in Sources */ = {isa = PBXBuildFile; fileRef = 07B6604123700C9B000FE35A /* Topic.swift */; };
1820
07B6604423701739000FE35A /* Error.swift in Sources */ = {isa = PBXBuildFile; fileRef = 07B6604323701739000FE35A /* Error.swift */; };
@@ -31,6 +33,8 @@
3133
07637CA2237BCE4200E05FE9 /* Theme.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Theme.swift; sourceTree = "<group>"; };
3234
07637CA4237BD16600E05FE9 /* Point.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Point.swift; sourceTree = "<group>"; };
3335
07637CA6237BD27E00E05FE9 /* Marker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Marker.swift; sourceTree = "<group>"; };
36+
0791AF492437BD1C00F5ECDC /* Builders.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Builders.swift; sourceTree = "<group>"; };
37+
0791AF512437E38900F5ECDC /* ElementsBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ElementsBuilder.swift; sourceTree = "<group>"; };
3438
07B6603F23700BE4000FE35A /* Workbook.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Workbook.swift; sourceTree = "<group>"; };
3539
07B6604123700C9B000FE35A /* Topic.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Topic.swift; sourceTree = "<group>"; };
3640
07B6604323701739000FE35A /* Error.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Error.swift; sourceTree = "<group>"; };
@@ -83,6 +87,15 @@
8387
path = XMind;
8488
sourceTree = "<group>";
8589
};
90+
0791AF482437BCEF00F5ECDC /* Builder */ = {
91+
isa = PBXGroup;
92+
children = (
93+
0791AF492437BD1C00F5ECDC /* Builders.swift */,
94+
0791AF512437E38900F5ECDC /* ElementsBuilder.swift */,
95+
);
96+
path = Builder;
97+
sourceTree = "<group>";
98+
};
8699
07CABF32236FF2D900A50B58 = {
87100
isa = PBXGroup;
88101
children = (
@@ -103,6 +116,7 @@
103116
07CABF40236FF35C00A50B58 /* Sources */ = {
104117
isa = PBXGroup;
105118
children = (
119+
0791AF482437BCEF00F5ECDC /* Builder */,
106120
075072FC237D2F1A00DC2A3C /* XMind */,
107121
075072FB237D2EFD00DC2A3C /* Internal */,
108122
07CABF41236FF35C00A50B58 /* XMindSDK.h */,
@@ -203,6 +217,7 @@
203217
07637C9D237BAA4400E05FE9 /* Manifest.swift in Sources */,
204218
07637CA1237BCD3300E05FE9 /* Relationship.swift in Sources */,
205219
07E117372398A77B0042C083 /* TemporaryStorge.swift in Sources */,
220+
0791AF522437E38900F5ECDC /* ElementsBuilder.swift in Sources */,
206221
07B6604423701739000FE35A /* Error.swift in Sources */,
207222
07E1173B2398B3E50042C083 /* EncryptionData.swift in Sources */,
208223
07637CA5237BD16600E05FE9 /* Point.swift in Sources */,
@@ -211,6 +226,7 @@
211226
07FE404B23754B300070DE70 /* Sheet.swift in Sources */,
212227
07637CA7237BD27E00E05FE9 /* Marker.swift in Sources */,
213228
07E117392398B0EC0042C083 /* Crypto.swift in Sources */,
229+
0791AF4A2437BD1C00F5ECDC /* Builders.swift in Sources */,
214230
);
215231
runOnlyForDeploymentPostprocessing = 0;
216232
};
@@ -361,7 +377,7 @@
361377
"@loader_path/Frameworks",
362378
);
363379
MACOSX_DEPLOYMENT_TARGET = 10.11;
364-
MARKETING_VERSION = 1.0.0;
380+
MARKETING_VERSION = 1.1.0;
365381
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
366382
MTL_FAST_MATH = YES;
367383
ONLY_ACTIVE_ARCH = YES;
@@ -452,7 +468,7 @@
452468
"@loader_path/Frameworks",
453469
);
454470
MACOSX_DEPLOYMENT_TARGET = 10.11;
455-
MARKETING_VERSION = 1.0.0;
471+
MARKETING_VERSION = 1.1.0;
456472
MTL_ENABLE_DEBUG_INFO = NO;
457473
MTL_FAST_MATH = YES;
458474
PRODUCT_BUNDLE_IDENTIFIER = net.xmind.XMindSDK;

0 commit comments

Comments
 (0)