From 108c43db76cffaedee858f844cd35c8c2b9cd42b Mon Sep 17 00:00:00 2001 From: Dzmitry Antonenka Date: Tue, 14 May 2024 17:01:16 +0300 Subject: [PATCH] feat(main): add swiftui example project --- Examples/TreeView/Podfile.lock | 2 +- Examples/TreeView/Pods/Manifest.lock | 16 + .../Pods/Pods.xcodeproj/project.pbxproj | 725 ++++++++++++++++++ Examples/TreeView/Pods/RATreeView/LICENCE.md | 20 + .../Private Files/RABatchChangeEntity.h | 31 + .../Private Files/RABatchChangeEntity.m | 62 ++ .../RATreeView/Private Files/RABatchChanges.h | 37 + .../RATreeView/Private Files/RABatchChanges.m | 124 +++ .../RATreeView/Private Files/RATableView.h | 18 + .../RATreeView/Private Files/RATableView.m | 183 +++++ .../RATreeView/Private Files/RATreeNode.h | 34 + .../RATreeView/Private Files/RATreeNode.m | 75 ++ .../RATreeNodeCollectionController.h | 53 ++ .../RATreeNodeCollectionController.m | 301 ++++++++ .../Private Files/RATreeNodeController.h | 51 ++ .../Private Files/RATreeNodeController.m | 306 ++++++++ .../RATreeNodeItem+ClassExtension.h | 31 + .../Private Files/RATreeNodeItem+Private.h | 37 + .../Private Files/RATreeNodeItem+Private.m | 29 + .../RATreeView/Private Files/RATreeNodeItem.h | 30 + .../RATreeView/Private Files/RATreeNodeItem.m | 48 ++ .../Private Files/RATreeNode_ClassExtension.h | 27 + .../Private Files/RATreeView+Enums.h | 41 + .../Private Files/RATreeView+Enums.m | 128 ++++ .../Private Files/RATreeView+Private.h | 43 ++ .../Private Files/RATreeView+Private.m | 192 +++++ ...RATreeNodeCollectionControllerDataSource.h | 26 + ...RATreeNodeCollectionControllerDataSource.m | 35 + .../RATreeView+TableViewDataSource.h | 25 + .../RATreeView+TableViewDataSource.m | 70 ++ .../RATreeView+TableViewDelegate.h | 25 + .../RATreeView+TableViewDelegate.m | 318 ++++++++ .../Private Files/RATreeView_ClassExtension.h | 33 + .../RATreeView/RATreeView/RATreeView.h | 604 +++++++++++++++ .../RATreeView/RATreeView/RATreeView.m | 619 +++++++++++++++ Examples/TreeView/Pods/RATreeView/README.md | 190 +++++ .../Pods-TreeView/Pods-TreeView-Info.plist | 26 + .../Pods-TreeView-acknowledgements.markdown | 26 + .../Pods-TreeView-acknowledgements.plist | 58 ++ .../Pods-TreeView/Pods-TreeView-dummy.m | 5 + ...ew-frameworks-Debug-input-files.xcfilelist | 2 + ...w-frameworks-Debug-output-files.xcfilelist | 1 + ...-frameworks-Release-input-files.xcfilelist | 2 + ...frameworks-Release-output-files.xcfilelist | 1 + .../Pods-TreeView/Pods-TreeView-frameworks.sh | 186 +++++ .../Pods-TreeView/Pods-TreeView-umbrella.h | 16 + .../Pods-TreeView.debug.xcconfig | 12 + .../Pods-TreeView/Pods-TreeView.modulemap | 6 + .../Pods-TreeView.release.xcconfig | 12 + .../RATreeView/RATreeView-Info.plist | 26 + .../RATreeView/RATreeView-dummy.m | 5 + .../RATreeView/RATreeView-prefix.pch | 12 + .../RATreeView/RATreeView-umbrella.h | 17 + .../RATreeView/RATreeView.debug.xcconfig | 12 + .../RATreeView/RATreeView.modulemap | 6 + .../RATreeView/RATreeView.release.xcconfig | 12 + .../TreeView.xcodeproj/project.pbxproj | 22 +- .../xcshareddata/swiftpm/Package.resolved | 16 - .../contents.xcworkspacedata | 10 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../xcshareddata/swiftpm/Package.resolved | 15 + .../TreeView/Base.lproj/Main.storyboard | 57 +- .../SwiftUI/SwiftListTreeDataStore.swift | 70 ++ .../SwiftUI/SwiftUIListWithSearch.swift | 94 +++ 64 files changed, 5293 insertions(+), 31 deletions(-) create mode 100644 Examples/TreeView/Pods/Manifest.lock create mode 100644 Examples/TreeView/Pods/Pods.xcodeproj/project.pbxproj create mode 100644 Examples/TreeView/Pods/RATreeView/LICENCE.md create mode 100644 Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RABatchChangeEntity.h create mode 100644 Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RABatchChangeEntity.m create mode 100644 Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RABatchChanges.h create mode 100644 Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RABatchChanges.m create mode 100644 Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RATableView.h create mode 100644 Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RATableView.m create mode 100644 Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RATreeNode.h create mode 100644 Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RATreeNode.m create mode 100644 Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RATreeNodeCollectionController.h create mode 100644 Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RATreeNodeCollectionController.m create mode 100644 Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RATreeNodeController.h create mode 100644 Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RATreeNodeController.m create mode 100644 Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RATreeNodeItem+ClassExtension.h create mode 100644 Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RATreeNodeItem+Private.h create mode 100644 Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RATreeNodeItem+Private.m create mode 100644 Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RATreeNodeItem.h create mode 100644 Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RATreeNodeItem.m create mode 100644 Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RATreeNode_ClassExtension.h create mode 100644 Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RATreeView+Enums.h create mode 100644 Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RATreeView+Enums.m create mode 100644 Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RATreeView+Private.h create mode 100644 Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RATreeView+Private.m create mode 100644 Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RATreeView+RATreeNodeCollectionControllerDataSource.h create mode 100644 Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RATreeView+RATreeNodeCollectionControllerDataSource.m create mode 100644 Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RATreeView+TableViewDataSource.h create mode 100644 Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RATreeView+TableViewDataSource.m create mode 100644 Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RATreeView+TableViewDelegate.h create mode 100644 Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RATreeView+TableViewDelegate.m create mode 100644 Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RATreeView_ClassExtension.h create mode 100644 Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/RATreeView.h create mode 100644 Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/RATreeView.m create mode 100644 Examples/TreeView/Pods/RATreeView/README.md create mode 100644 Examples/TreeView/Pods/Target Support Files/Pods-TreeView/Pods-TreeView-Info.plist create mode 100644 Examples/TreeView/Pods/Target Support Files/Pods-TreeView/Pods-TreeView-acknowledgements.markdown create mode 100644 Examples/TreeView/Pods/Target Support Files/Pods-TreeView/Pods-TreeView-acknowledgements.plist create mode 100644 Examples/TreeView/Pods/Target Support Files/Pods-TreeView/Pods-TreeView-dummy.m create mode 100644 Examples/TreeView/Pods/Target Support Files/Pods-TreeView/Pods-TreeView-frameworks-Debug-input-files.xcfilelist create mode 100644 Examples/TreeView/Pods/Target Support Files/Pods-TreeView/Pods-TreeView-frameworks-Debug-output-files.xcfilelist create mode 100644 Examples/TreeView/Pods/Target Support Files/Pods-TreeView/Pods-TreeView-frameworks-Release-input-files.xcfilelist create mode 100644 Examples/TreeView/Pods/Target Support Files/Pods-TreeView/Pods-TreeView-frameworks-Release-output-files.xcfilelist create mode 100755 Examples/TreeView/Pods/Target Support Files/Pods-TreeView/Pods-TreeView-frameworks.sh create mode 100644 Examples/TreeView/Pods/Target Support Files/Pods-TreeView/Pods-TreeView-umbrella.h create mode 100644 Examples/TreeView/Pods/Target Support Files/Pods-TreeView/Pods-TreeView.debug.xcconfig create mode 100644 Examples/TreeView/Pods/Target Support Files/Pods-TreeView/Pods-TreeView.modulemap create mode 100644 Examples/TreeView/Pods/Target Support Files/Pods-TreeView/Pods-TreeView.release.xcconfig create mode 100644 Examples/TreeView/Pods/Target Support Files/RATreeView/RATreeView-Info.plist create mode 100644 Examples/TreeView/Pods/Target Support Files/RATreeView/RATreeView-dummy.m create mode 100644 Examples/TreeView/Pods/Target Support Files/RATreeView/RATreeView-prefix.pch create mode 100644 Examples/TreeView/Pods/Target Support Files/RATreeView/RATreeView-umbrella.h create mode 100644 Examples/TreeView/Pods/Target Support Files/RATreeView/RATreeView.debug.xcconfig create mode 100644 Examples/TreeView/Pods/Target Support Files/RATreeView/RATreeView.modulemap create mode 100644 Examples/TreeView/Pods/Target Support Files/RATreeView/RATreeView.release.xcconfig delete mode 100644 Examples/TreeView/TreeView.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved create mode 100644 Examples/TreeView/TreeView.xcworkspace/contents.xcworkspacedata create mode 100644 Examples/TreeView/TreeView.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 Examples/TreeView/TreeView.xcworkspace/xcshareddata/swiftpm/Package.resolved create mode 100644 Examples/TreeView/TreeView/SwiftListTreeDataSource/SwiftUI/SwiftListTreeDataStore.swift create mode 100644 Examples/TreeView/TreeView/SwiftListTreeDataSource/SwiftUI/SwiftUIListWithSearch.swift diff --git a/Examples/TreeView/Podfile.lock b/Examples/TreeView/Podfile.lock index 1064ac2..e5f834c 100644 --- a/Examples/TreeView/Podfile.lock +++ b/Examples/TreeView/Podfile.lock @@ -13,4 +13,4 @@ SPEC CHECKSUMS: PODFILE CHECKSUM: 610578a2fce157c0d62d75c1dde0415ea5a54a1c -COCOAPODS: 1.10.1 +COCOAPODS: 1.15.2 diff --git a/Examples/TreeView/Pods/Manifest.lock b/Examples/TreeView/Pods/Manifest.lock new file mode 100644 index 0000000..e5f834c --- /dev/null +++ b/Examples/TreeView/Pods/Manifest.lock @@ -0,0 +1,16 @@ +PODS: + - RATreeView (2.1.2) + +DEPENDENCIES: + - RATreeView + +SPEC REPOS: + trunk: + - RATreeView + +SPEC CHECKSUMS: + RATreeView: 380cde0090cfde21dc6ac29137f49d3b768fdd28 + +PODFILE CHECKSUM: 610578a2fce157c0d62d75c1dde0415ea5a54a1c + +COCOAPODS: 1.15.2 diff --git a/Examples/TreeView/Pods/Pods.xcodeproj/project.pbxproj b/Examples/TreeView/Pods/Pods.xcodeproj/project.pbxproj new file mode 100644 index 0000000..f724259 --- /dev/null +++ b/Examples/TreeView/Pods/Pods.xcodeproj/project.pbxproj @@ -0,0 +1,725 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 54; + objects = { + +/* Begin PBXBuildFile section */ + 027CC81C93663A1F093597B6D53DF955 /* RATreeView_ClassExtension.h in Headers */ = {isa = PBXBuildFile; fileRef = 365988BE81B3B772A9A4592E66779786 /* RATreeView_ClassExtension.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 0413551DA0A831514AA8DC444234C6B6 /* RABatchChangeEntity.m in Sources */ = {isa = PBXBuildFile; fileRef = 6B3946C68E1C9F7FB3E64DBBB98FB5C2 /* RABatchChangeEntity.m */; }; + 0899E5A9D39BF2B6FDB7F9A36F556A38 /* RATreeView+TableViewDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = AFFD0D7C47158CBFA609A6024478FF8F /* RATreeView+TableViewDelegate.m */; }; + 10AA998B9BCED171A757B357A389332E /* RATreeView+RATreeNodeCollectionControllerDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = C683A62DBB7317770020D6AA68F1D457 /* RATreeView+RATreeNodeCollectionControllerDataSource.m */; }; + 196C7852DB3CD588A286567029E9B2C6 /* RABatchChangeEntity.h in Headers */ = {isa = PBXBuildFile; fileRef = 440AEE0EA10CDBEFE1C5460ABBE79655 /* RABatchChangeEntity.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 1B7F512D94CF59C56AC8A6BD9CE51A3E /* RABatchChanges.h in Headers */ = {isa = PBXBuildFile; fileRef = 9A4373B0D375E216B3157AFF4B0379A7 /* RABatchChanges.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 2D8EEFD81F46BF1B871B77D884997FF6 /* RATreeNode.h in Headers */ = {isa = PBXBuildFile; fileRef = 1EFAF0578787AC55EAFDE8CA068B7001 /* RATreeNode.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 2E018C1CDAC0FE77D5B68218B89975E9 /* RATreeNodeItem+Private.m in Sources */ = {isa = PBXBuildFile; fileRef = A9C183D63C839391BB52E1E72C025914 /* RATreeNodeItem+Private.m */; }; + 315D208D64854E81943A093AB38CF116 /* RATreeView-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 7611597ACB1B8552D4CDA39BF2D1837F /* RATreeView-dummy.m */; }; + 325F457814E95EFD64BC61EA72AF4D38 /* RATreeView+TableViewDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = DBD7FADD073FEA3FEF0B6A6EE0DB2405 /* RATreeView+TableViewDataSource.m */; }; + 36D942B47937D9BD909052B62236D3CC /* RATreeView+RATreeNodeCollectionControllerDataSource.h in Headers */ = {isa = PBXBuildFile; fileRef = A6EF3923097AEC92FCF23423A9310E0C /* RATreeView+RATreeNodeCollectionControllerDataSource.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 3708EE7B00C3BCE54A983271133577FA /* RATreeNodeItem+ClassExtension.h in Headers */ = {isa = PBXBuildFile; fileRef = ADC6CFCC881057F18247AEA5B71B97C1 /* RATreeNodeItem+ClassExtension.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 41E74CDF999F518FE19F663DA484BEB4 /* RATreeView+TableViewDataSource.h in Headers */ = {isa = PBXBuildFile; fileRef = 2BDACD56411CAB2FD940AE0D1FC5B099 /* RATreeView+TableViewDataSource.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 4403BB49C6EA4257D489B26D1FA49B2B /* RATreeView.m in Sources */ = {isa = PBXBuildFile; fileRef = 064921D01467903C7424442CCBA94BA9 /* RATreeView.m */; }; + 472A58B3CCBD367C66193F588CA5FA46 /* RATreeView+Private.m in Sources */ = {isa = PBXBuildFile; fileRef = A8B74E81EE2451D3F3F937E723F5FA03 /* RATreeView+Private.m */; }; + 4CF2CD1E8F04FA6A37F45ED8FE0BCB36 /* RATreeView+Enums.m in Sources */ = {isa = PBXBuildFile; fileRef = A6185652BF1C3C5036C7E83FF054A97B /* RATreeView+Enums.m */; }; + 518AFA3858513CBF6080E60B2BFBDCDC /* RATreeView+TableViewDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 8B503EF3C846EAA64FC212B96A0E2E9B /* RATreeView+TableViewDelegate.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 524EF058C14BE8A7B286808DB5FD9B7E /* RATreeView-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 9EC2A2B12EE206BA27269A60C168CC34 /* RATreeView-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 5334D79F4AC2A6A3D8D266CD680AE337 /* Pods-TreeView-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 48A62E87D9D3D5842B4D84C76AF4EE2C /* Pods-TreeView-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 597D456EE0C5E5AF21510FF3282CD972 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 73010CC983E3809BECEE5348DA1BB8C6 /* Foundation.framework */; }; + 5A4327804057BD4A8FE66AB53FA6959C /* RABatchChanges.m in Sources */ = {isa = PBXBuildFile; fileRef = D7C113904DD9BDA322E42939A0ABBFBC /* RABatchChanges.m */; }; + 5C21AB70A20DC9E89DAFF435B5C2F4EF /* RATreeView+Enums.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C19684A8ADBD6EC64159C795F9F8FA6 /* RATreeView+Enums.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 7DA87C93A6FDBFE4DBFA7A63E39C3699 /* RATreeView.h in Headers */ = {isa = PBXBuildFile; fileRef = EDE1A200C30F437CFFAB8A5E4E532978 /* RATreeView.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 96D87A7696351AEADC5D780F751D2FEB /* RATreeNodeItem.h in Headers */ = {isa = PBXBuildFile; fileRef = 5334D97919026802647EF4EB59ABC0C0 /* RATreeNodeItem.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 983DC4E423A425B8FEAF0EFEBC9317F5 /* RATreeNodeItem.m in Sources */ = {isa = PBXBuildFile; fileRef = 8974B5D6FC661AC17196C09E8D23308B /* RATreeNodeItem.m */; }; + A435307D2F2BFDB77F98B1B99B21F505 /* RATreeNodeItem+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = B5E59A510AD65230F60FC4298F04C11D /* RATreeNodeItem+Private.h */; settings = {ATTRIBUTES = (Project, ); }; }; + A5A6F5DC5376319AE20CEBA0A5DC7E99 /* RATableView.m in Sources */ = {isa = PBXBuildFile; fileRef = DA3A3F875450D8F88445DDAC6C8AD7A3 /* RATableView.m */; }; + A91FB4F41AF1EE8B1AC4A773E66C7A6B /* RATreeNodeController.h in Headers */ = {isa = PBXBuildFile; fileRef = 87E36EC6045FDEEAB1101D0606DAF82C /* RATreeNodeController.h */; settings = {ATTRIBUTES = (Project, ); }; }; + BDEAA8EEA322514B5240AC52567D872E /* RATreeNodeController.m in Sources */ = {isa = PBXBuildFile; fileRef = 915DF68BECBC8CA6AEBB9D8F8B1170AC /* RATreeNodeController.m */; }; + C4149F0BB9353528944425B818EFFB4E /* RATreeNodeCollectionController.m in Sources */ = {isa = PBXBuildFile; fileRef = 97F112E2AEBEDD248F27056D0AFAB14B /* RATreeNodeCollectionController.m */; }; + D2C5B10927B14353996EFDDC51A50F32 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 73010CC983E3809BECEE5348DA1BB8C6 /* Foundation.framework */; }; + E01C7F30A6AAA91921BDE0374C53B84F /* RATreeNode_ClassExtension.h in Headers */ = {isa = PBXBuildFile; fileRef = 465B9941CE1BF444BD66D2069BA128E5 /* RATreeNode_ClassExtension.h */; settings = {ATTRIBUTES = (Project, ); }; }; + E7454B21485F5B38D51399000B01DB59 /* RATreeView+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = B12167346499552543D5069051931986 /* RATreeView+Private.h */; settings = {ATTRIBUTES = (Project, ); }; }; + E8C099261FA009AB8121046D81C8DA4F /* RATreeNode.m in Sources */ = {isa = PBXBuildFile; fileRef = 5EAC97F9AA28E7675A1255683F6CB10F /* RATreeNode.m */; }; + F47580C942CE645E715F8D24B0755D1C /* RATableView.h in Headers */ = {isa = PBXBuildFile; fileRef = 3A4F6ED8794C4835AC0A2A1F6F3A089E /* RATableView.h */; settings = {ATTRIBUTES = (Project, ); }; }; + F8496BA92122605D6BD582256651DD91 /* Pods-TreeView-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D07F7D043C17526741965A264FDDC6D /* Pods-TreeView-dummy.m */; }; + FFF4C34A3CC253CBE9CFABF0743F1C66 /* RATreeNodeCollectionController.h in Headers */ = {isa = PBXBuildFile; fileRef = 4F5EBAD6DAA577032216F5A2877FDF33 /* RATreeNodeCollectionController.h */; settings = {ATTRIBUTES = (Project, ); }; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + F42F9ED173E3B6D9B633C65CCFE0F998 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 68F0AAE2125542D37A3D74D0D3932309; + remoteInfo = RATreeView; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + 0436151E13BB158B04C1D55C3B3D2193 /* Pods-TreeView-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-TreeView-Info.plist"; sourceTree = ""; }; + 064921D01467903C7424442CCBA94BA9 /* RATreeView.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = RATreeView.m; path = RATreeView/RATreeView/RATreeView.m; sourceTree = ""; }; + 109078CE1A90F3E204F3E4BF71422010 /* Pods_TreeView.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_TreeView.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 1EFAF0578787AC55EAFDE8CA068B7001 /* RATreeNode.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RATreeNode.h; path = "RATreeView/RATreeView/Private Files/RATreeNode.h"; sourceTree = ""; }; + 2044FDCC4171D2AE40E26138885C6F90 /* Pods-TreeView-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-TreeView-acknowledgements.plist"; sourceTree = ""; }; + 2BDACD56411CAB2FD940AE0D1FC5B099 /* RATreeView+TableViewDataSource.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "RATreeView+TableViewDataSource.h"; path = "RATreeView/RATreeView/Private Files/RATreeView+TableViewDataSource.h"; sourceTree = ""; }; + 2F3207660223BB50F3C21BD82105DD2A /* RATreeView.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = RATreeView.release.xcconfig; sourceTree = ""; }; + 365988BE81B3B772A9A4592E66779786 /* RATreeView_ClassExtension.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RATreeView_ClassExtension.h; path = "RATreeView/RATreeView/Private Files/RATreeView_ClassExtension.h"; sourceTree = ""; }; + 3A4F6ED8794C4835AC0A2A1F6F3A089E /* RATableView.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RATableView.h; path = "RATreeView/RATreeView/Private Files/RATableView.h"; sourceTree = ""; }; + 440AEE0EA10CDBEFE1C5460ABBE79655 /* RABatchChangeEntity.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RABatchChangeEntity.h; path = "RATreeView/RATreeView/Private Files/RABatchChangeEntity.h"; sourceTree = ""; }; + 465B9941CE1BF444BD66D2069BA128E5 /* RATreeNode_ClassExtension.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RATreeNode_ClassExtension.h; path = "RATreeView/RATreeView/Private Files/RATreeNode_ClassExtension.h"; sourceTree = ""; }; + 48A62E87D9D3D5842B4D84C76AF4EE2C /* Pods-TreeView-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-TreeView-umbrella.h"; sourceTree = ""; }; + 4B2C12367C4E528E6314DED9D3692076 /* Pods-TreeView.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "Pods-TreeView.modulemap"; sourceTree = ""; }; + 4C19684A8ADBD6EC64159C795F9F8FA6 /* RATreeView+Enums.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "RATreeView+Enums.h"; path = "RATreeView/RATreeView/Private Files/RATreeView+Enums.h"; sourceTree = ""; }; + 4F5EBAD6DAA577032216F5A2877FDF33 /* RATreeNodeCollectionController.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RATreeNodeCollectionController.h; path = "RATreeView/RATreeView/Private Files/RATreeNodeCollectionController.h"; sourceTree = ""; }; + 5334D97919026802647EF4EB59ABC0C0 /* RATreeNodeItem.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RATreeNodeItem.h; path = "RATreeView/RATreeView/Private Files/RATreeNodeItem.h"; sourceTree = ""; }; + 5B4CCE945DA52B68861D70271B3A9267 /* RATreeView.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = RATreeView.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 5B59386160ACA955C27724558B2494D7 /* Pods-TreeView-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-TreeView-frameworks.sh"; sourceTree = ""; }; + 5C562050EB27A7FC4C84F6135D9FFB1E /* Pods-TreeView-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-TreeView-acknowledgements.markdown"; sourceTree = ""; }; + 5EAC97F9AA28E7675A1255683F6CB10F /* RATreeNode.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = RATreeNode.m; path = "RATreeView/RATreeView/Private Files/RATreeNode.m"; sourceTree = ""; }; + 6B3946C68E1C9F7FB3E64DBBB98FB5C2 /* RABatchChangeEntity.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = RABatchChangeEntity.m; path = "RATreeView/RATreeView/Private Files/RABatchChangeEntity.m"; sourceTree = ""; }; + 6E2564860B64EB044BDBE693BA57245C /* Pods-TreeView.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-TreeView.debug.xcconfig"; sourceTree = ""; }; + 6E39A36574A4198AB136576070257DE0 /* RATreeView.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = RATreeView.debug.xcconfig; sourceTree = ""; }; + 73010CC983E3809BECEE5348DA1BB8C6 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS14.0.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; + 7611597ACB1B8552D4CDA39BF2D1837F /* RATreeView-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "RATreeView-dummy.m"; sourceTree = ""; }; + 87E36EC6045FDEEAB1101D0606DAF82C /* RATreeNodeController.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RATreeNodeController.h; path = "RATreeView/RATreeView/Private Files/RATreeNodeController.h"; sourceTree = ""; }; + 88AD32BB45694FB9721D493F855463F2 /* RATreeView.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = RATreeView.modulemap; sourceTree = ""; }; + 8974B5D6FC661AC17196C09E8D23308B /* RATreeNodeItem.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = RATreeNodeItem.m; path = "RATreeView/RATreeView/Private Files/RATreeNodeItem.m"; sourceTree = ""; }; + 8B1240C5DD3764D9815DE1871278938B /* RATreeView-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "RATreeView-Info.plist"; sourceTree = ""; }; + 8B503EF3C846EAA64FC212B96A0E2E9B /* RATreeView+TableViewDelegate.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "RATreeView+TableViewDelegate.h"; path = "RATreeView/RATreeView/Private Files/RATreeView+TableViewDelegate.h"; sourceTree = ""; }; + 915DF68BECBC8CA6AEBB9D8F8B1170AC /* RATreeNodeController.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = RATreeNodeController.m; path = "RATreeView/RATreeView/Private Files/RATreeNodeController.m"; sourceTree = ""; }; + 97F112E2AEBEDD248F27056D0AFAB14B /* RATreeNodeCollectionController.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = RATreeNodeCollectionController.m; path = "RATreeView/RATreeView/Private Files/RATreeNodeCollectionController.m"; sourceTree = ""; }; + 9A4373B0D375E216B3157AFF4B0379A7 /* RABatchChanges.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RABatchChanges.h; path = "RATreeView/RATreeView/Private Files/RABatchChanges.h"; sourceTree = ""; }; + 9D07F7D043C17526741965A264FDDC6D /* Pods-TreeView-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-TreeView-dummy.m"; sourceTree = ""; }; + 9D940727FF8FB9C785EB98E56350EF41 /* Podfile */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; indentWidth = 2; name = Podfile; path = ../Podfile; sourceTree = SOURCE_ROOT; tabWidth = 2; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; + 9EC2A2B12EE206BA27269A60C168CC34 /* RATreeView-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "RATreeView-umbrella.h"; sourceTree = ""; }; + A6185652BF1C3C5036C7E83FF054A97B /* RATreeView+Enums.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "RATreeView+Enums.m"; path = "RATreeView/RATreeView/Private Files/RATreeView+Enums.m"; sourceTree = ""; }; + A6EF3923097AEC92FCF23423A9310E0C /* RATreeView+RATreeNodeCollectionControllerDataSource.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "RATreeView+RATreeNodeCollectionControllerDataSource.h"; path = "RATreeView/RATreeView/Private Files/RATreeView+RATreeNodeCollectionControllerDataSource.h"; sourceTree = ""; }; + A8B74E81EE2451D3F3F937E723F5FA03 /* RATreeView+Private.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "RATreeView+Private.m"; path = "RATreeView/RATreeView/Private Files/RATreeView+Private.m"; sourceTree = ""; }; + A9C183D63C839391BB52E1E72C025914 /* RATreeNodeItem+Private.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "RATreeNodeItem+Private.m"; path = "RATreeView/RATreeView/Private Files/RATreeNodeItem+Private.m"; sourceTree = ""; }; + ADC6CFCC881057F18247AEA5B71B97C1 /* RATreeNodeItem+ClassExtension.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "RATreeNodeItem+ClassExtension.h"; path = "RATreeView/RATreeView/Private Files/RATreeNodeItem+ClassExtension.h"; sourceTree = ""; }; + AFFD0D7C47158CBFA609A6024478FF8F /* RATreeView+TableViewDelegate.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "RATreeView+TableViewDelegate.m"; path = "RATreeView/RATreeView/Private Files/RATreeView+TableViewDelegate.m"; sourceTree = ""; }; + B12167346499552543D5069051931986 /* RATreeView+Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "RATreeView+Private.h"; path = "RATreeView/RATreeView/Private Files/RATreeView+Private.h"; sourceTree = ""; }; + B5E59A510AD65230F60FC4298F04C11D /* RATreeNodeItem+Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "RATreeNodeItem+Private.h"; path = "RATreeView/RATreeView/Private Files/RATreeNodeItem+Private.h"; sourceTree = ""; }; + C683A62DBB7317770020D6AA68F1D457 /* RATreeView+RATreeNodeCollectionControllerDataSource.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "RATreeView+RATreeNodeCollectionControllerDataSource.m"; path = "RATreeView/RATreeView/Private Files/RATreeView+RATreeNodeCollectionControllerDataSource.m"; sourceTree = ""; }; + D7C113904DD9BDA322E42939A0ABBFBC /* RABatchChanges.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = RABatchChanges.m; path = "RATreeView/RATreeView/Private Files/RABatchChanges.m"; sourceTree = ""; }; + DA3A3F875450D8F88445DDAC6C8AD7A3 /* RATableView.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = RATableView.m; path = "RATreeView/RATreeView/Private Files/RATableView.m"; sourceTree = ""; }; + DBD7FADD073FEA3FEF0B6A6EE0DB2405 /* RATreeView+TableViewDataSource.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "RATreeView+TableViewDataSource.m"; path = "RATreeView/RATreeView/Private Files/RATreeView+TableViewDataSource.m"; sourceTree = ""; }; + DC88413D6FF68933722E14A1E6305A72 /* Pods-TreeView.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-TreeView.release.xcconfig"; sourceTree = ""; }; + E8C599D8F958D66B4872C139EE0952E5 /* RATreeView-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "RATreeView-prefix.pch"; sourceTree = ""; }; + EDE1A200C30F437CFFAB8A5E4E532978 /* RATreeView.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = RATreeView.h; path = RATreeView/RATreeView/RATreeView.h; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 8736384D669671049DA39FBE1F9A28CF /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + D2C5B10927B14353996EFDDC51A50F32 /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + BF13BBB2B1E2F2D4EE59111AEC367263 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 597D456EE0C5E5AF21510FF3282CD972 /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 0875119F43F9A0C38147D247361FC005 /* RATreeView */ = { + isa = PBXGroup; + children = ( + 440AEE0EA10CDBEFE1C5460ABBE79655 /* RABatchChangeEntity.h */, + 6B3946C68E1C9F7FB3E64DBBB98FB5C2 /* RABatchChangeEntity.m */, + 9A4373B0D375E216B3157AFF4B0379A7 /* RABatchChanges.h */, + D7C113904DD9BDA322E42939A0ABBFBC /* RABatchChanges.m */, + 3A4F6ED8794C4835AC0A2A1F6F3A089E /* RATableView.h */, + DA3A3F875450D8F88445DDAC6C8AD7A3 /* RATableView.m */, + 1EFAF0578787AC55EAFDE8CA068B7001 /* RATreeNode.h */, + 5EAC97F9AA28E7675A1255683F6CB10F /* RATreeNode.m */, + 465B9941CE1BF444BD66D2069BA128E5 /* RATreeNode_ClassExtension.h */, + 4F5EBAD6DAA577032216F5A2877FDF33 /* RATreeNodeCollectionController.h */, + 97F112E2AEBEDD248F27056D0AFAB14B /* RATreeNodeCollectionController.m */, + 87E36EC6045FDEEAB1101D0606DAF82C /* RATreeNodeController.h */, + 915DF68BECBC8CA6AEBB9D8F8B1170AC /* RATreeNodeController.m */, + 5334D97919026802647EF4EB59ABC0C0 /* RATreeNodeItem.h */, + 8974B5D6FC661AC17196C09E8D23308B /* RATreeNodeItem.m */, + ADC6CFCC881057F18247AEA5B71B97C1 /* RATreeNodeItem+ClassExtension.h */, + B5E59A510AD65230F60FC4298F04C11D /* RATreeNodeItem+Private.h */, + A9C183D63C839391BB52E1E72C025914 /* RATreeNodeItem+Private.m */, + EDE1A200C30F437CFFAB8A5E4E532978 /* RATreeView.h */, + 064921D01467903C7424442CCBA94BA9 /* RATreeView.m */, + 4C19684A8ADBD6EC64159C795F9F8FA6 /* RATreeView+Enums.h */, + A6185652BF1C3C5036C7E83FF054A97B /* RATreeView+Enums.m */, + B12167346499552543D5069051931986 /* RATreeView+Private.h */, + A8B74E81EE2451D3F3F937E723F5FA03 /* RATreeView+Private.m */, + A6EF3923097AEC92FCF23423A9310E0C /* RATreeView+RATreeNodeCollectionControllerDataSource.h */, + C683A62DBB7317770020D6AA68F1D457 /* RATreeView+RATreeNodeCollectionControllerDataSource.m */, + 2BDACD56411CAB2FD940AE0D1FC5B099 /* RATreeView+TableViewDataSource.h */, + DBD7FADD073FEA3FEF0B6A6EE0DB2405 /* RATreeView+TableViewDataSource.m */, + 8B503EF3C846EAA64FC212B96A0E2E9B /* RATreeView+TableViewDelegate.h */, + AFFD0D7C47158CBFA609A6024478FF8F /* RATreeView+TableViewDelegate.m */, + 365988BE81B3B772A9A4592E66779786 /* RATreeView_ClassExtension.h */, + A01E8767235DB2BA05A24C0AC1A81E16 /* Support Files */, + ); + path = RATreeView; + sourceTree = ""; + }; + 48B6D24BF77B2A47DE071EF9C6381373 /* Targets Support Files */ = { + isa = PBXGroup; + children = ( + EFC684956FEF94D3A631650B1EEFC760 /* Pods-TreeView */, + ); + name = "Targets Support Files"; + sourceTree = ""; + }; + 578452D2E740E91742655AC8F1636D1F /* iOS */ = { + isa = PBXGroup; + children = ( + 73010CC983E3809BECEE5348DA1BB8C6 /* Foundation.framework */, + ); + name = iOS; + sourceTree = ""; + }; + 7076CE2195DFB16958B3F8DE07FDCE63 /* Products */ = { + isa = PBXGroup; + children = ( + 109078CE1A90F3E204F3E4BF71422010 /* Pods_TreeView.framework */, + 5B4CCE945DA52B68861D70271B3A9267 /* RATreeView.framework */, + ); + name = Products; + sourceTree = ""; + }; + 9D0BFCA2A28B6EF2240458F6AE62D6FF /* Pods */ = { + isa = PBXGroup; + children = ( + 0875119F43F9A0C38147D247361FC005 /* RATreeView */, + ); + name = Pods; + sourceTree = ""; + }; + A01E8767235DB2BA05A24C0AC1A81E16 /* Support Files */ = { + isa = PBXGroup; + children = ( + 88AD32BB45694FB9721D493F855463F2 /* RATreeView.modulemap */, + 7611597ACB1B8552D4CDA39BF2D1837F /* RATreeView-dummy.m */, + 8B1240C5DD3764D9815DE1871278938B /* RATreeView-Info.plist */, + E8C599D8F958D66B4872C139EE0952E5 /* RATreeView-prefix.pch */, + 9EC2A2B12EE206BA27269A60C168CC34 /* RATreeView-umbrella.h */, + 6E39A36574A4198AB136576070257DE0 /* RATreeView.debug.xcconfig */, + 2F3207660223BB50F3C21BD82105DD2A /* RATreeView.release.xcconfig */, + ); + name = "Support Files"; + path = "../Target Support Files/RATreeView"; + sourceTree = ""; + }; + CF1408CF629C7361332E53B88F7BD30C = { + isa = PBXGroup; + children = ( + 9D940727FF8FB9C785EB98E56350EF41 /* Podfile */, + D210D550F4EA176C3123ED886F8F87F5 /* Frameworks */, + 9D0BFCA2A28B6EF2240458F6AE62D6FF /* Pods */, + 7076CE2195DFB16958B3F8DE07FDCE63 /* Products */, + 48B6D24BF77B2A47DE071EF9C6381373 /* Targets Support Files */, + ); + sourceTree = ""; + }; + D210D550F4EA176C3123ED886F8F87F5 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 578452D2E740E91742655AC8F1636D1F /* iOS */, + ); + name = Frameworks; + sourceTree = ""; + }; + EFC684956FEF94D3A631650B1EEFC760 /* Pods-TreeView */ = { + isa = PBXGroup; + children = ( + 4B2C12367C4E528E6314DED9D3692076 /* Pods-TreeView.modulemap */, + 5C562050EB27A7FC4C84F6135D9FFB1E /* Pods-TreeView-acknowledgements.markdown */, + 2044FDCC4171D2AE40E26138885C6F90 /* Pods-TreeView-acknowledgements.plist */, + 9D07F7D043C17526741965A264FDDC6D /* Pods-TreeView-dummy.m */, + 5B59386160ACA955C27724558B2494D7 /* Pods-TreeView-frameworks.sh */, + 0436151E13BB158B04C1D55C3B3D2193 /* Pods-TreeView-Info.plist */, + 48A62E87D9D3D5842B4D84C76AF4EE2C /* Pods-TreeView-umbrella.h */, + 6E2564860B64EB044BDBE693BA57245C /* Pods-TreeView.debug.xcconfig */, + DC88413D6FF68933722E14A1E6305A72 /* Pods-TreeView.release.xcconfig */, + ); + name = "Pods-TreeView"; + path = "Target Support Files/Pods-TreeView"; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 11C0012027EA79466FC3F35F8702895D /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 196C7852DB3CD588A286567029E9B2C6 /* RABatchChangeEntity.h in Headers */, + 1B7F512D94CF59C56AC8A6BD9CE51A3E /* RABatchChanges.h in Headers */, + F47580C942CE645E715F8D24B0755D1C /* RATableView.h in Headers */, + 2D8EEFD81F46BF1B871B77D884997FF6 /* RATreeNode.h in Headers */, + E01C7F30A6AAA91921BDE0374C53B84F /* RATreeNode_ClassExtension.h in Headers */, + FFF4C34A3CC253CBE9CFABF0743F1C66 /* RATreeNodeCollectionController.h in Headers */, + A91FB4F41AF1EE8B1AC4A773E66C7A6B /* RATreeNodeController.h in Headers */, + 96D87A7696351AEADC5D780F751D2FEB /* RATreeNodeItem.h in Headers */, + 3708EE7B00C3BCE54A983271133577FA /* RATreeNodeItem+ClassExtension.h in Headers */, + A435307D2F2BFDB77F98B1B99B21F505 /* RATreeNodeItem+Private.h in Headers */, + 7DA87C93A6FDBFE4DBFA7A63E39C3699 /* RATreeView.h in Headers */, + 5C21AB70A20DC9E89DAFF435B5C2F4EF /* RATreeView+Enums.h in Headers */, + E7454B21485F5B38D51399000B01DB59 /* RATreeView+Private.h in Headers */, + 36D942B47937D9BD909052B62236D3CC /* RATreeView+RATreeNodeCollectionControllerDataSource.h in Headers */, + 41E74CDF999F518FE19F663DA484BEB4 /* RATreeView+TableViewDataSource.h in Headers */, + 518AFA3858513CBF6080E60B2BFBDCDC /* RATreeView+TableViewDelegate.h in Headers */, + 524EF058C14BE8A7B286808DB5FD9B7E /* RATreeView-umbrella.h in Headers */, + 027CC81C93663A1F093597B6D53DF955 /* RATreeView_ClassExtension.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + EDDE8AD09D992B84DE0AC8C53E40DD3D /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 5334D79F4AC2A6A3D8D266CD680AE337 /* Pods-TreeView-umbrella.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 68F0AAE2125542D37A3D74D0D3932309 /* RATreeView */ = { + isa = PBXNativeTarget; + buildConfigurationList = D21C9174B397F38DFD34B15C753D2865 /* Build configuration list for PBXNativeTarget "RATreeView" */; + buildPhases = ( + 11C0012027EA79466FC3F35F8702895D /* Headers */, + FA023DD900DBA280C297FC0986B6FA70 /* Sources */, + 8736384D669671049DA39FBE1F9A28CF /* Frameworks */, + E2D0981E9F670BF049168F78297B5F8D /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = RATreeView; + productName = RATreeView; + productReference = 5B4CCE945DA52B68861D70271B3A9267 /* RATreeView.framework */; + productType = "com.apple.product-type.framework"; + }; + 97A324CA88D27A3640B633E9251EA597 /* Pods-TreeView */ = { + isa = PBXNativeTarget; + buildConfigurationList = 15D37C58D227FD2A66EEB737021684A7 /* Build configuration list for PBXNativeTarget "Pods-TreeView" */; + buildPhases = ( + EDDE8AD09D992B84DE0AC8C53E40DD3D /* Headers */, + 9BEC0B727EE500B8679ED3694D5A1CC5 /* Sources */, + BF13BBB2B1E2F2D4EE59111AEC367263 /* Frameworks */, + 56DCCE4C08A603B4C65B577D2DE040B2 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 15DCA8B1EAE7A7F02183EB302E399A78 /* PBXTargetDependency */, + ); + name = "Pods-TreeView"; + productName = Pods_TreeView; + productReference = 109078CE1A90F3E204F3E4BF71422010 /* Pods_TreeView.framework */; + productType = "com.apple.product-type.framework"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + BFDFE7DC352907FC980B868725387E98 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 1500; + LastUpgradeCheck = 1500; + }; + buildConfigurationList = 4821239608C13582E20E6DA73FD5F1F9 /* Build configuration list for PBXProject "Pods" */; + compatibilityVersion = "Xcode 12.0"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + Base, + en, + ); + mainGroup = CF1408CF629C7361332E53B88F7BD30C; + productRefGroup = 7076CE2195DFB16958B3F8DE07FDCE63 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 97A324CA88D27A3640B633E9251EA597 /* Pods-TreeView */, + 68F0AAE2125542D37A3D74D0D3932309 /* RATreeView */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 56DCCE4C08A603B4C65B577D2DE040B2 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + E2D0981E9F670BF049168F78297B5F8D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 9BEC0B727EE500B8679ED3694D5A1CC5 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + F8496BA92122605D6BD582256651DD91 /* Pods-TreeView-dummy.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + FA023DD900DBA280C297FC0986B6FA70 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 0413551DA0A831514AA8DC444234C6B6 /* RABatchChangeEntity.m in Sources */, + 5A4327804057BD4A8FE66AB53FA6959C /* RABatchChanges.m in Sources */, + A5A6F5DC5376319AE20CEBA0A5DC7E99 /* RATableView.m in Sources */, + E8C099261FA009AB8121046D81C8DA4F /* RATreeNode.m in Sources */, + C4149F0BB9353528944425B818EFFB4E /* RATreeNodeCollectionController.m in Sources */, + BDEAA8EEA322514B5240AC52567D872E /* RATreeNodeController.m in Sources */, + 983DC4E423A425B8FEAF0EFEBC9317F5 /* RATreeNodeItem.m in Sources */, + 2E018C1CDAC0FE77D5B68218B89975E9 /* RATreeNodeItem+Private.m in Sources */, + 4403BB49C6EA4257D489B26D1FA49B2B /* RATreeView.m in Sources */, + 4CF2CD1E8F04FA6A37F45ED8FE0BCB36 /* RATreeView+Enums.m in Sources */, + 472A58B3CCBD367C66193F588CA5FA46 /* RATreeView+Private.m in Sources */, + 10AA998B9BCED171A757B357A389332E /* RATreeView+RATreeNodeCollectionControllerDataSource.m in Sources */, + 325F457814E95EFD64BC61EA72AF4D38 /* RATreeView+TableViewDataSource.m in Sources */, + 0899E5A9D39BF2B6FDB7F9A36F556A38 /* RATreeView+TableViewDelegate.m in Sources */, + 315D208D64854E81943A093AB38CF116 /* RATreeView-dummy.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 15DCA8B1EAE7A7F02183EB302E399A78 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = RATreeView; + target = 68F0AAE2125542D37A3D74D0D3932309 /* RATreeView */; + targetProxy = F42F9ED173E3B6D9B633C65CCFE0F998 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + 32C4E61543F5DB5A06BAB544D47BEFBA /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 2F3207660223BB50F3C21BD82105DD2A /* RATreeView.release.xcconfig */; + buildSettings = { + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/RATreeView/RATreeView-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/RATreeView/RATreeView-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULEMAP_FILE = "Target Support Files/RATreeView/RATreeView.modulemap"; + PRODUCT_MODULE_NAME = RATreeView; + PRODUCT_NAME = RATreeView; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 43217D488A0C472FE8940A1150ADB934 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 6E2564860B64EB044BDBE693BA57245C /* Pods-TreeView.debug.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; + CLANG_ENABLE_OBJC_WEAK = NO; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/Pods-TreeView/Pods-TreeView-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-TreeView/Pods-TreeView.modulemap"; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PODS_ROOT = "$(SRCROOT)"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 4BC7450F9457737EE3E637BA155B56F7 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "POD_CONFIGURATION_DEBUG=1", + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 14.0; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + STRIP_INSTALLED_PRODUCT = NO; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + SYMROOT = "${SRCROOT}/../build"; + }; + name = Debug; + }; + 8B5A46FF8D3C1289CDEE3BAFACABCD2A /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_PREPROCESSOR_DEFINITIONS = ( + "POD_CONFIGURATION_RELEASE=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 14.0; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + STRIP_INSTALLED_PRODUCT = NO; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + SWIFT_VERSION = 5.0; + SYMROOT = "${SRCROOT}/../build"; + }; + name = Release; + }; + BAC10473754B5880EA50E78BF19FE558 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = DC88413D6FF68933722E14A1E6305A72 /* Pods-TreeView.release.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; + CLANG_ENABLE_OBJC_WEAK = NO; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/Pods-TreeView/Pods-TreeView-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-TreeView/Pods-TreeView.modulemap"; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PODS_ROOT = "$(SRCROOT)"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + C5749DF6317C3552734D6323EBF4488A /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 6E39A36574A4198AB136576070257DE0 /* RATreeView.debug.xcconfig */; + buildSettings = { + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/RATreeView/RATreeView-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/RATreeView/RATreeView-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULEMAP_FILE = "Target Support Files/RATreeView/RATreeView.modulemap"; + PRODUCT_MODULE_NAME = RATreeView; + PRODUCT_NAME = RATreeView; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 15D37C58D227FD2A66EEB737021684A7 /* Build configuration list for PBXNativeTarget "Pods-TreeView" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 43217D488A0C472FE8940A1150ADB934 /* Debug */, + BAC10473754B5880EA50E78BF19FE558 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 4821239608C13582E20E6DA73FD5F1F9 /* Build configuration list for PBXProject "Pods" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4BC7450F9457737EE3E637BA155B56F7 /* Debug */, + 8B5A46FF8D3C1289CDEE3BAFACABCD2A /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + D21C9174B397F38DFD34B15C753D2865 /* Build configuration list for PBXNativeTarget "RATreeView" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C5749DF6317C3552734D6323EBF4488A /* Debug */, + 32C4E61543F5DB5A06BAB544D47BEFBA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = BFDFE7DC352907FC980B868725387E98 /* Project object */; +} diff --git a/Examples/TreeView/Pods/RATreeView/LICENCE.md b/Examples/TreeView/Pods/RATreeView/LICENCE.md new file mode 100644 index 0000000..23c3d5b --- /dev/null +++ b/Examples/TreeView/Pods/RATreeView/LICENCE.md @@ -0,0 +1,20 @@ +The MIT License (MIT) + +Copyright (c) 2013 Rafał Augustyniak + +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: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +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. \ No newline at end of file diff --git a/Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RABatchChangeEntity.h b/Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RABatchChangeEntity.h new file mode 100644 index 0000000..41b4601 --- /dev/null +++ b/Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RABatchChangeEntity.h @@ -0,0 +1,31 @@ +// +// RABatchChangesEntity.h +// RATreeView +// +// Created by Rafal Augustyniak on 17/11/15. +// Copyright © 2015 Rafal Augustyniak. All rights reserved. +// + + +#import + + +typedef NS_ENUM(NSInteger, RABatchChangeType) { + RABatchChangeTypeItemRowInsertion = 0, + RABatchChangeTypeItemRowExpansion, + RABatchChangeTypeItemRowDeletion, + RABatchChangeTypeItemRowCollapse, + RABatchChangeTypeItemMove +}; + + +@interface RABatchChangeEntity : NSObject + +@property (nonatomic) RABatchChangeType type; +@property (nonatomic) NSInteger ranking; +@property (nonatomic, copy) void(^updatesBlock)(); + ++ (instancetype)batchChangeEntityWithBlock:(void(^)())updates type:(RABatchChangeType)type ranking:(NSInteger)ranking; + +@end + diff --git a/Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RABatchChangeEntity.m b/Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RABatchChangeEntity.m new file mode 100644 index 0000000..96c6228 --- /dev/null +++ b/Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RABatchChangeEntity.m @@ -0,0 +1,62 @@ +// +// RABatchChangesEntity.m +// RATreeView +// +// Created by Rafal Augustyniak on 17/11/15. +// Copyright © 2015 Rafal Augustyniak. All rights reserved. +// + + +#import "RABatchChangeEntity.h" + + +@implementation RABatchChangeEntity + ++ (instancetype)batchChangeEntityWithBlock:(void (^)())updates type:(RABatchChangeType)type ranking:(NSInteger)ranking +{ + NSParameterAssert(updates); + RABatchChangeEntity *entity = [RABatchChangeEntity new]; + entity.type = type; + entity.ranking = ranking; + entity.updatesBlock = updates; + + return entity; +} + +- (NSComparisonResult)compare:(RABatchChangeEntity *)otherEntity +{ + if ([self destructiveOperation]) { + if (![otherEntity destructiveOperation]) { + return NSOrderedAscending; + } else { + return [@(otherEntity.ranking) compare:@(self.ranking)]; + } + } else if (self.type == RABatchChangeTypeItemMove && otherEntity.type != RABatchChangeTypeItemMove) { + return [otherEntity destructiveOperation] ? NSOrderedAscending : NSOrderedDescending; + + } else if ([self constructiveOperation]) { + if (![otherEntity constructiveOperation]) { + return NSOrderedDescending; + } else { + return [@(self.ranking) compare:@(otherEntity.ranking)]; + } + + } else { + return NSOrderedSame; + } +} + +- (BOOL)constructiveOperation +{ + return self.type == RABatchChangeTypeItemRowExpansion + || self.type == RABatchChangeTypeItemRowInsertion; +} + +- (BOOL)destructiveOperation +{ + return self.type == RABatchChangeTypeItemRowCollapse + || self.type == RABatchChangeTypeItemRowDeletion; +} + +@end + diff --git a/Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RABatchChanges.h b/Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RABatchChanges.h new file mode 100644 index 0000000..495674b --- /dev/null +++ b/Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RABatchChanges.h @@ -0,0 +1,37 @@ + +//The MIT License (MIT) +// +//Copyright (c) 2014 Rafał Augustyniak +// +//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: +// +//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. +// + +#import + + +@interface RABatchChanges : NSObject + +- (void)beginUpdates; +- (void)endUpdates; + +- (void)expandItemWithBlock:(void(^)())update atIndex:(NSInteger)index; +- (void)insertItemWithBlock:(void(^)())update atIndex:(NSInteger)index; + +- (void)collapseItemWithBlock:(void(^)())update lastIndex:(NSInteger)index; +- (void)deleteItemWithBlock:(void(^)())update lastIndex:(NSInteger)index; + +- (void)moveItemWithDeletionBlock:(void (^)())deletionUpdate fromLastIndex:(NSInteger)lastIndex additionBlock:(void (^)())additionUpdate toIndex:(NSInteger)index; + +@end diff --git a/Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RABatchChanges.m b/Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RABatchChanges.m new file mode 100644 index 0000000..e2e88ad --- /dev/null +++ b/Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RABatchChanges.m @@ -0,0 +1,124 @@ + +//The MIT License (MIT) +// +//Copyright (c) 2014 Rafał Augustyniak +// +//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: +// +//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. +// + +#import "RABatchChanges.h" +#import "RABatchChangeEntity.h" + + +@interface RABatchChanges () + +@property (nonatomic, strong) NSMutableArray *operationsStorage; +@property (nonatomic) NSInteger batchChangesCounter; + +@end + + + +@implementation RABatchChanges + +- (id)init +{ + self = [super init]; + if (self) { + _batchChangesCounter = 0; + } + + return self; +} + +- (void)beginUpdates +{ + if (self.batchChangesCounter++ == 0) { + self.operationsStorage = [NSMutableArray array]; + } +} + +- (void)endUpdates +{ + self.batchChangesCounter--; + if (self.batchChangesCounter == 0) { + [self.operationsStorage sortUsingSelector:@selector(compare:)]; + + for (RABatchChangeEntity *entity in self.operationsStorage) { + entity.updatesBlock(); + } + self.operationsStorage = nil; + } +} + +- (void)insertItemWithBlock:(void (^)())update atIndex:(NSInteger)index +{ + RABatchChangeEntity *entity = [RABatchChangeEntity batchChangeEntityWithBlock:update + type:RABatchChangeTypeItemRowInsertion + ranking:index]; + [self addBatchChangeEntity:entity]; +} + +- (void)expandItemWithBlock:(void (^)())update atIndex:(NSInteger)index +{ + RABatchChangeEntity *entity= [RABatchChangeEntity batchChangeEntityWithBlock:update + type:RABatchChangeTypeItemRowExpansion + ranking:index]; + [self addBatchChangeEntity:entity]; +} + +- (void)deleteItemWithBlock:(void (^)())update lastIndex:(NSInteger)lastIndex +{ + RABatchChangeEntity *entity = [RABatchChangeEntity batchChangeEntityWithBlock:update + type:RABatchChangeTypeItemRowDeletion + ranking:lastIndex]; + [self addBatchChangeEntity:entity]; +} + +- (void)collapseItemWithBlock:(void (^)())update lastIndex:(NSInteger)lastIndex +{ + RABatchChangeEntity *entity = [RABatchChangeEntity batchChangeEntityWithBlock:update + type:RABatchChangeTypeItemRowCollapse + ranking:lastIndex]; + [self addBatchChangeEntity:entity]; +} + +- (void)moveItemWithDeletionBlock:(void (^)())deletionUpdate fromLastIndex:(NSInteger)lastIndex additionBlock:(void (^)())additionUpdate toIndex:(NSInteger)index +{ + RABatchChangeEntity *firstEntity = [RABatchChangeEntity batchChangeEntityWithBlock:deletionUpdate + type:RABatchChangeTypeItemRowDeletion + ranking:lastIndex]; + + RABatchChangeEntity *secondEntity = [RABatchChangeEntity batchChangeEntityWithBlock:additionUpdate + type:RABatchChangeTypeItemRowInsertion + ranking:index]; + [self addBatchChangeEntity:firstEntity]; + [self addBatchChangeEntity:secondEntity]; +} + +#pragma mark - + +- (void)addBatchChangeEntity:(RABatchChangeEntity *)entity +{ + if (self.batchChangesCounter > 0) { + [self.operationsStorage addObject:entity]; + } else { + entity.updatesBlock(); + } +} + + + +@end diff --git a/Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RATableView.h b/Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RATableView.h new file mode 100644 index 0000000..d907afd --- /dev/null +++ b/Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RATableView.h @@ -0,0 +1,18 @@ +// +// RATableView.h +// Pods +// +// Created by Rafal Augustyniak on 15/11/15. +// +// + + +#import + + +@interface RATableView : UITableView + +@property (nonatomic, nullable, weak) id tableViewDelegate; +@property (nonatomic, nullable, weak) id scrollViewDelegate; + +@end diff --git a/Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RATableView.m b/Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RATableView.m new file mode 100644 index 0000000..2c41ede --- /dev/null +++ b/Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RATableView.m @@ -0,0 +1,183 @@ +// +// RATableView.m +// Pods +// +// Created by Rafal Augustyniak on 15/11/15. +// +// + + +#import "RATableView.h" +#import + + +@interface RATableView () + +@end + + +@implementation RATableView + +- (instancetype)initWithFrame:(CGRect)frame style:(UITableViewStyle)style +{ + self = [super initWithFrame:frame style:style]; + if (self) { + [self commonInit]; + } + + return self; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder +{ + self = [super initWithCoder:aDecoder]; + if (self) { + [self commonInit]; + } + + return self; +} + +- (void)commonInit +{ + [super setDelegate:self]; +} + +- (void)setTableViewDelegate:(id)tableViewDelegate +{ + if (_tableViewDelegate == tableViewDelegate) { + return; + } + [super setDelegate:nil]; + _tableViewDelegate = tableViewDelegate; + [super setDelegate:self]; +} + +- (void)setDelegate:(id)delegate +{ + if (self.scrollViewDelegate == delegate) { + return; + } + [super setDelegate:nil]; + self.scrollViewDelegate = delegate; + [super setDelegate:self]; +} + +- (BOOL)respondsToSelector:(SEL)aSelector +{ + return [super respondsToSelector:aSelector] + || (SelectorBelongsToProtocol(@protocol(UIScrollViewDelegate), aSelector) && [self.scrollViewDelegate respondsToSelector:aSelector]) + || (SelectorBelongsToProtocol(@protocol(UITableViewDelegate), aSelector) && [self.tableViewDelegate respondsToSelector:aSelector]); +} + +- (id)forwardingTargetForSelector:(SEL)aSelector +{ + if (SelectorBelongsToProtocol(@protocol(UIScrollViewDelegate), aSelector)) { + return self.scrollViewDelegate; + } else if (SelectorBelongsToProtocol(@protocol(UITableViewDelegate), aSelector)) { + return self.tableViewDelegate; + } else { + return nil; + } +} + + +#pragma mark - ScrollView delegate + +- (void)scrollViewDidScroll:(UIScrollView *)scrollView +{ + if ([self.scrollViewDelegate respondsToSelector:@selector(scrollViewDidScroll:)]) { + [self.scrollViewDelegate scrollViewDidScroll:scrollView]; + } +} + +- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView +{ + if ([self.scrollViewDelegate respondsToSelector:@selector(scrollViewWillBeginDragging:)]) { + [self.scrollViewDelegate scrollViewWillBeginDragging:scrollView]; + } +} + +- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset +{ + if ([self.scrollViewDelegate respondsToSelector:@selector(scrollViewWillEndDragging:withVelocity:targetContentOffset:)]) { + [self.scrollViewDelegate scrollViewWillEndDragging:scrollView withVelocity:velocity targetContentOffset:targetContentOffset]; + } +} + +- (BOOL)scrollViewShouldScrollToTop:(UIScrollView *)scrollView +{ + if ([self.scrollViewDelegate respondsToSelector:@selector(scrollViewShouldScrollToTop:)]) { + return [self.scrollViewDelegate scrollViewShouldScrollToTop:scrollView]; + } + return YES; +} + +- (void)scrollViewDidScrollToTop:(UIScrollView *)scrollView +{ + if ([self.scrollViewDelegate respondsToSelector:@selector(scrollViewDidScroll:)]) { + [self.scrollViewDelegate scrollViewDidScroll:scrollView]; + } +} + +- (void)scrollViewWillBeginDecelerating:(UIScrollView *)scrollView +{ + if ([self.scrollViewDelegate respondsToSelector:@selector(scrollViewWillBeginDecelerating:)]) { + [self.scrollViewDelegate scrollViewWillBeginDecelerating:scrollView]; + } +} + +- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView +{ + if ([self.scrollViewDelegate respondsToSelector:@selector(scrollViewDidEndDecelerating:)]) { + [self.scrollViewDelegate scrollViewDidEndDecelerating:scrollView]; + } +} + +- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView +{ + if ([self.scrollViewDelegate respondsToSelector:@selector(viewForZoomingInScrollView:)]) { + return [self.scrollViewDelegate viewForZoomingInScrollView:scrollView]; + } + return nil; +} + +- (void)scrollViewWillBeginZooming:(UIScrollView *)scrollView withView:(UIView *)view +{ + if ([self.scrollViewDelegate respondsToSelector:@selector(scrollViewWillBeginZooming:withView:)]) { + [self.scrollViewDelegate scrollViewWillBeginZooming:scrollView withView:view]; + } +} + +- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(CGFloat)scale +{ + if ([self.scrollViewDelegate respondsToSelector:@selector(scrollViewDidEndZooming:withView:atScale:)]) { + [self.scrollViewDelegate scrollViewDidEndZooming:scrollView withView:view atScale:scale]; + } +} + +- (void)scrollViewDidZoom:(UIScrollView *)scrollView +{ + if ([self.scrollViewDelegate respondsToSelector:@selector(scrollViewDidZoom:)]) { + [self.scrollViewDelegate scrollViewDidZoom:scrollView]; + } +} + +- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView +{ + if ([self.scrollViewDelegate respondsToSelector:@selector(scrollViewDidEndScrollingAnimation:)]) { + [self.scrollViewDelegate scrollViewDidEndScrollingAnimation:scrollView]; + } +} + + +#pragma mark - + +static BOOL SelectorBelongsToProtocol(Protocol *protocol, SEL selector) +{ + struct objc_method_description methodDescription = protocol_getMethodDescription(protocol, selector, NO, YES); + + return NULL != methodDescription.name; +} + +@end diff --git a/Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RATreeNode.h b/Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RATreeNode.h new file mode 100644 index 0000000..59a687d --- /dev/null +++ b/Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RATreeNode.h @@ -0,0 +1,34 @@ + +//The MIT License (MIT) +// +//Copyright (c) 2014 Rafał Augustyniak +// +//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: +// +//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. +// + + +#import + +@class RATreeNodeItem; + + +@interface RATreeNode : NSObject + +@property (nonatomic, readonly) BOOL expanded; +@property (strong, nonatomic, readonly) id item; + +- (id)initWithLazyItem:(RATreeNodeItem *)item expandedBlock:(BOOL (^)(id))expandedBlock; + +@end diff --git a/Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RATreeNode.m b/Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RATreeNode.m new file mode 100644 index 0000000..0658f9b --- /dev/null +++ b/Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RATreeNode.m @@ -0,0 +1,75 @@ + +//The MIT License (MIT) +// +//Copyright (c) 2014 Rafał Augustyniak +// +//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: +// +//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. +// + + +#import "RATreeNode.h" + +#import "RATreeNodeItem.h" + + +@interface RATreeNode () { + BOOL _expanded; +} + +@property (nonatomic) BOOL expanded; +@property (nonatomic, strong) RATreeNodeItem *lazyItem; +@property (nonatomic, copy) BOOL (^expandedBlock)(id); + +@end + + +@implementation RATreeNode + +- (id)initWithLazyItem:(RATreeNodeItem *)item expandedBlock:(BOOL (^)(id))expandedBlock; +{ + self = [super init]; + if (self) { + _lazyItem = item; + _expandedBlock = expandedBlock; + } + + return self; +} + + +#pragma mark - + +- (RATreeNodeItem *)item +{ + return self.lazyItem.item; +} + +- (BOOL)expanded +{ + if (self.expandedBlock) { + _expanded = self.expandedBlock(self.item); + self.expandedBlock = nil; + } + + return _expanded; +} + +- (void)setExpanded:(BOOL)expanded +{ + self.expandedBlock = nil; + _expanded = expanded; +} + +@end diff --git a/Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RATreeNodeCollectionController.h b/Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RATreeNodeCollectionController.h new file mode 100644 index 0000000..fa0e683 --- /dev/null +++ b/Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RATreeNodeCollectionController.h @@ -0,0 +1,53 @@ + +//The MIT License (MIT) +// +//Copyright (c) 2014 Rafał Augustyniak +// +//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: +// +//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. +// + +#import + +@class RATreeNodeController, RATreeNode, RATreeNodeCollectionController; + +@protocol RATreeNodeCollectionControllerDataSource + +- (NSInteger)treeNodeCollectionController:(RATreeNodeCollectionController *)controller numberOfChildrenForItem:(id)item; +- (id)treeNodeCollectionController:(RATreeNodeCollectionController *)controller child:(NSInteger)childIndex ofItem:(id)item; + +@end + + +@interface RATreeNodeCollectionController : NSObject + +@property (nonatomic, weak) id dataSource; +@property (nonatomic, readonly) NSInteger numberOfVisibleRowsForItems; + +- (RATreeNode *)treeNodeForIndex:(NSInteger)index; +- (NSInteger)levelForItem:(id)item; +- (id)parentForItem:(id)item; +- (id)childInParent:(id)parent atIndex:(NSInteger)index; + +- (NSInteger)indexForItem:(id)item; +- (NSInteger)lastVisibleDescendantIndexForItem:(id)item; + +- (void)collapseRowForItem:(id)item collapseChildren:(BOOL)collapseChildren updates:(void(^)(NSIndexSet *))updates; +- (void)expandRowForItem:(id)item expandChildren:(BOOL)expandChildren updates:(void (^)(NSIndexSet *))updates; + +- (void)insertItemsAtIndexes:(NSIndexSet *)indexes inParent:(id)item; +- (void)moveItemAtIndex:(NSInteger)index inParent:(id)parent toIndex:(NSInteger)newIndex inParent:(id)newParent updates:(void(^)(NSIndexSet *deletions, NSIndexSet *additions))updates; +- (void)removeItemsAtIndexes:(NSIndexSet *)indexes inParent:(id)item updates:(void(^)(NSIndexSet *))updates; + +@end diff --git a/Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RATreeNodeCollectionController.m b/Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RATreeNodeCollectionController.m new file mode 100644 index 0000000..d357604 --- /dev/null +++ b/Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RATreeNodeCollectionController.m @@ -0,0 +1,301 @@ + +//The MIT License (MIT) +// +//Copyright (c) 2014 Rafał Augustyniak +// +//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: +// +//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. +// + + +#import "RATreeNodeCollectionController.h" +#import "RATreeNodeController.h" + +#import "RATreeNode.h" +#import "RATreeNodeItem+Private.h" + +#import "RABatchChanges.h" + + +@interface RATreeNodeCollectionController () + +@property (nonatomic, strong) RATreeNodeController *rootController; + +@end + + +@implementation RATreeNodeCollectionController + +- (NSInteger)numberOfVisibleRowsForItems +{ + return self.rootController.numberOfVisibleDescendants; +} + +- (RATreeNode *)treeNodeForIndex:(NSInteger)index +{ + return [self.rootController controllerForIndex:index].treeNode; +} + +- (NSInteger)indexForItem:(id)item +{ + return [self.rootController indexForItem:item]; +} + +- (NSInteger)lastVisibleDescendantIndexForItem:(id)item +{ + return [self.rootController lastVisibleDescendatIndexForItem:item]; +} + +- (id)parentForItem:(id)item +{ + RATreeNodeController *controller = [self.rootController controllerForItem:item]; + return controller.parentController.treeNode.item; +} + +- (NSInteger)levelForItem:(id)item +{ + return [self.rootController controllerForItem:item].level; +} + +- (id)childInParent:(id)parent atIndex:(NSInteger)index +{ + RATreeNodeController *controller = [self.rootController controllerForItem:parent].childControllers[index]; + return controller.treeNode.item; +} + +- (void)expandRowForItem:(id)item updates:(void (^)(NSIndexSet *))updates +{ + [self expandRowForItem:item expandChildren:YES updates:updates]; +} + +- (void)expandRowForItem:(id)item expandChildren:(BOOL)expandChildren updates:(void (^)(NSIndexSet *))updates +{ + NSParameterAssert(updates); + + RATreeNodeController *parentController = [self.rootController controllerForItem:item]; + NSMutableArray *items = [@[item] mutableCopy]; + + while ([items count] > 0) { + id currentItem = [items firstObject]; + [items removeObject:currentItem]; + + RATreeNodeController *controller = [self.rootController controllerForItem:currentItem]; + NSMutableArray *oldChildItems = [NSMutableArray array]; + for (RATreeNodeController *nodeController in controller.childControllers) { + [oldChildItems addObject:nodeController.treeNode.item]; + } + + NSInteger numberOfChildren = [self.dataSource treeNodeCollectionController:self numberOfChildrenForItem:controller.treeNode.item]; + NSIndexSet *allIndexes = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, numberOfChildren)]; + + NSArray *currentChildControllersAndIndexes = [self controllersAndIndexesForNodesWithIndexes:allIndexes inParentController:controller]; + NSArray *currentChildControllers = [currentChildControllersAndIndexes valueForKey:@"controller"]; + + NSMutableArray *childControllersToInsert = [NSMutableArray array]; + NSMutableIndexSet *indexesForInsertions = [NSMutableIndexSet indexSet]; + NSMutableArray *childControllersToRemove = [NSMutableArray array]; + NSMutableIndexSet *indexesForDeletions = [NSMutableIndexSet indexSet]; + + for (RATreeNodeController *loopNodeController in currentChildControllers) { + if (![controller.childControllers containsObject:loopNodeController] + && ![oldChildItems containsObject:controller.treeNode.item]) { + [childControllersToInsert addObject:loopNodeController]; + NSInteger index = [currentChildControllers indexOfObject:loopNodeController]; + NSAssert(index != NSNotFound, nil); + [indexesForInsertions addIndex:index]; + } + } + + for (RATreeNodeController *loopNodeController in controller.childControllers) { + if (![currentChildControllers containsObject:loopNodeController] + && ![childControllersToInsert containsObject:loopNodeController]) { + [childControllersToRemove addObject:loopNodeController]; + NSInteger index = [controller.childControllers indexOfObject:loopNodeController]; + NSAssert(index != NSNotFound, nil); + [indexesForDeletions addIndex:index]; + } + } + + [controller removeChildControllersAtIndexes:indexesForDeletions]; + [controller insertChildControllers:childControllersToInsert atIndexes:indexesForInsertions]; + + if (expandChildren) { + for (RATreeNodeController *nodeController in controller.childControllers) { + [items addObject:nodeController.treeNode.item]; + } + } + + [controller expandAndExpandChildren:expandChildren]; + } + + updates(parentController.descendantsIndexes); +} + +- (void)collapseRowForItem:(id)item collapseChildren:(BOOL)collapseChildren updates:(void (^)(NSIndexSet *))updates +{ + NSParameterAssert(updates); + + RATreeNodeController *controller = [self.rootController controllerForItem:item]; + NSIndexSet *deletions = controller.descendantsIndexes; + [controller collapseAndCollapseChildren:collapseChildren]; + + updates(deletions); +} + +- (void)insertItemsAtIndexes:(NSIndexSet *)indexes inParent:(id)item +{ + RATreeNodeController *parentController = [self.rootController controllerForItem:item]; + NSArray *newControllers = [self controllersForNodesWithIndexes:indexes inParentController:parentController]; + [parentController insertChildControllers:newControllers atIndexes:indexes]; +} + +- (void)moveItemAtIndex:(NSInteger)index inParent:(id)parent toIndex:(NSInteger)newIndex inParent:(id)newParent updates:(void (^)(NSIndexSet *, NSIndexSet *))updates +{ + NSParameterAssert(updates); + + NSMutableIndexSet *removedIndexes = [NSMutableIndexSet indexSet]; + NSMutableIndexSet *addedIndexes = [NSMutableIndexSet indexSet]; + + RATreeNodeController *parentController = [self.rootController controllerForItem:parent]; + + if (parent == newParent) { + [parentController moveChildControllerAtIndex:index toIndex:newIndex]; + + } else { + RATreeNodeController *childController = parentController.childControllers[index]; + + [removedIndexes addIndex:childController.index]; + [removedIndexes addIndexes:childController.descendantsIndexes]; + + RATreeNodeController *newParentController = [self.rootController controllerForItem:parent]; + [parentController removeChildControllersAtIndexes:[NSIndexSet indexSetWithIndex:index]]; + [newParentController insertChildControllers:@[childController] atIndexes:[NSIndexSet indexSetWithIndex:newIndex]]; + + [addedIndexes addIndex:childController.index]; + [addedIndexes addIndexes:childController.descendantsIndexes]; + } + + updates(removedIndexes, addedIndexes); +} + +- (void)removeItemsAtIndexes:(NSIndexSet *)indexes inParent:(id)item updates:(void (^)(NSIndexSet *))updates +{ + RATreeNodeController *parentController = [self.rootController controllerForItem:item]; + + NSMutableIndexSet *indexesToRemoval = [NSMutableIndexSet indexSet]; + [indexes enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL *stop) { + RATreeNodeController *controller = parentController.childControllers[idx]; + [indexesToRemoval addIndex:controller.index]; + [indexesToRemoval addIndexes:controller.descendantsIndexes]; + }]; + + [parentController removeChildControllersAtIndexes:indexes]; + + updates(indexesToRemoval); +} + +- (NSArray *)controllersAndIndexesForNodesWithIndexes:(NSIndexSet *)indexes inParentController:(RATreeNodeController *)parentController +{ + NSMutableArray *childControllers = [parentController.childControllers mutableCopy]; + NSMutableArray *currentControllers = [NSMutableArray array]; + + NSMutableArray *invalidItems = [NSMutableArray array]; + for (RATreeNodeController *nodeController in parentController.childControllers) { + [invalidItems addObject:nodeController.treeNode.item]; + } + + [indexes enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL *stop) { + + RATreeNodeController *controller; + RATreeNodeController *oldControllerForCurrentIndex = nil; + + + RATreeNodeItem *lazyItem = [[RATreeNodeItem alloc] initWithParent:parentController.treeNode.item index:idx]; + lazyItem.dataSource = self; + + + for (RATreeNodeController *controller in parentController.childControllers) { + if ([controller.treeNode.item isEqual:lazyItem.item]) { + oldControllerForCurrentIndex = controller; + } + } + if (oldControllerForCurrentIndex != nil) { + controller = oldControllerForCurrentIndex; + + } else { + controller = [[RATreeNodeController alloc] initWithParent:parentController item:lazyItem expandedBlock:^BOOL(id item) { + return [childControllers indexOfObjectPassingTest:^BOOL(RATreeNodeController *controller, NSUInteger idx, BOOL *stop) { + return [controller.treeNode.item isEqual:item]; + }] != NSNotFound; + }]; + } + + [currentControllers addObject:@{ @"index" : @(idx), + @"controller" : controller }]; + }]; + + return [currentControllers copy]; +} + +- (NSArray *)controllersForNodesWithIndexes:(NSIndexSet *)indexes inParentController:(RATreeNodeController *)parentController +{ + return [[self controllersAndIndexesForNodesWithIndexes:indexes inParentController:parentController] valueForKey:@"controller"]; +} + +- (NSArray *)controllersForNodes:(NSInteger)nodesNumber inParentController:(RATreeNodeController *)parentController +{ + NSIndexSet *indexSet = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, nodesNumber)]; + return [self controllersForNodesWithIndexes:indexSet inParentController:parentController]; +} + +#pragma mark - RATreeNodeController delegate + +- (id)treeNodeController:(RATreeNodeController *)controller child:(NSInteger)childIndex +{ + return [self.dataSource treeNodeCollectionController:self child:childIndex ofItem:controller.treeNode.item]; +} + +- (NSInteger)numberOfChildrenForTreeNodeController:(RATreeNodeController *)controller +{ + return [self.dataSource treeNodeCollectionController:self numberOfChildrenForItem:controller.treeNode.item]; +} + + +#pragma mark - RATreeNodeItem data source + +- (id)itemForTreeNodeItem:(RATreeNodeItem *)treeNodeItem +{ + return [self.dataSource treeNodeCollectionController:self child:treeNodeItem.index ofItem:treeNodeItem.parent]; +} + + +#pragma mark - Properties + +- (RATreeNodeController *)rootController +{ + if (!_rootController) { + _rootController = [[RATreeNodeController alloc] initWithParent:nil item:nil expandedBlock:^BOOL(id _) { + return YES; + }]; + + NSInteger numberOfChildren = [self.dataSource treeNodeCollectionController:self numberOfChildrenForItem:nil]; + NSIndexSet *indexSet = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, numberOfChildren)]; + NSArray *childControllers = [self controllersForNodesWithIndexes:indexSet inParentController:_rootController]; + [_rootController insertChildControllers:childControllers atIndexes:indexSet]; + } + + return _rootController; +} + +@end diff --git a/Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RATreeNodeController.h b/Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RATreeNodeController.h new file mode 100644 index 0000000..7b6fbf9 --- /dev/null +++ b/Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RATreeNodeController.h @@ -0,0 +1,51 @@ + +//The MIT License (MIT) +// +//Copyright (c) 2014 Rafał Augustyniak +// +//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: +// +//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. +// + +#import + +@class RATreeNodeController, RATreeNode, RATreeNodeItem; + + +@interface RATreeNodeController : NSObject + +@property (nonatomic, weak, readonly) RATreeNodeController *parentController; +@property (nonatomic, strong, readonly) NSArray *childControllers; + +@property (nonatomic, strong, readonly) RATreeNode *treeNode; +@property (nonatomic, readonly) NSInteger index; +@property (nonatomic, readonly) NSInteger numberOfVisibleDescendants; +@property (nonatomic, strong, readonly) NSIndexSet *descendantsIndexes; +@property (nonatomic, readonly) NSInteger level; + +- (instancetype)initWithParent:(RATreeNodeController *)parentController item:(RATreeNodeItem *)item expandedBlock:(BOOL (^)(id))expanded; + +- (void)collapseAndCollapseChildren:(BOOL)collapseChildren; +- (void)expandAndExpandChildren:(BOOL)expandChildren; + +- (void)insertChildControllers:(NSArray *)controllers atIndexes:(NSIndexSet *)indexes; +- (void)moveChildControllerAtIndex:(NSInteger)index toIndex:(NSInteger)newIndex; +- (void)removeChildControllersAtIndexes:(NSIndexSet *)indexes; + +- (NSInteger)indexForItem:(id)item; +- (NSInteger)lastVisibleDescendatIndexForItem:(id)item; +- (RATreeNodeController *)controllerForIndex:(NSInteger)index; +- (RATreeNodeController *)controllerForItem:(id)item; + +@end diff --git a/Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RATreeNodeController.m b/Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RATreeNodeController.m new file mode 100644 index 0000000..4d21be0 --- /dev/null +++ b/Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RATreeNodeController.m @@ -0,0 +1,306 @@ + +//The MIT License (MIT) +// +//Copyright (c) 2014 Rafał Augustyniak +// +//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: +// +//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. +// + + +#import "RATreeNodeController.h" + +#import "RATreeNode.h" +#import "RATreeNode_ClassExtension.h" + + +@interface RATreeNodeController () + +@property (nonatomic, strong) RATreeNode *treeNode; + +@property (nonatomic) NSInteger index; +@property (nonatomic) NSInteger numberOfVisibleDescendants; +@property (nonatomic) NSInteger level; +@property (nonatomic, weak) RATreeNodeController *parentController; +@property (nonatomic, strong) NSMutableArray *mutablechildControllers; + +@end + + +@implementation RATreeNodeController + +- (instancetype)initWithParent:(RATreeNodeController *)parentController item:(RATreeNodeItem *)item expandedBlock:(BOOL (^)(id))expandedBlock +{ + self = [super init]; + if (self) { + [self invalidate]; + _level = NSIntegerMin; + _parentController = parentController; + _treeNode = [[RATreeNode alloc] initWithLazyItem:item expandedBlock:expandedBlock]; + _mutablechildControllers = [NSMutableArray array]; + } + + return self; +} + +- (void)insertChildControllers:(NSArray *)controllers atIndexes:(NSIndexSet *)indexes +{ + if (indexes.count == 0) { + return; + } + [self.mutablechildControllers insertObjects:controllers atIndexes:indexes]; + [self invalidateTreeNodesAfterChildAtIndex:[indexes firstIndex] - 1]; +} + +- (void)removeChildControllersAtIndexes:(NSIndexSet *)indexes +{ + if (indexes.count == 0) { + return; + } + [self.mutablechildControllers removeObjectsAtIndexes:indexes]; + [self invalidateTreeNodesAfterChildAtIndex:[indexes firstIndex] - 1]; +} + +- (void)moveChildControllerAtIndex:(NSInteger)index toIndex:(NSInteger)newIndex +{ + if (index == newIndex) { + return; + } + id controller = self.mutablechildControllers[index]; + [self.mutablechildControllers removeObjectAtIndex:index]; + [self.mutablechildControllers insertObject:controller atIndex:index]; + [self invalidateTreeNodesAfterChildAtIndex:MIN(index, newIndex)-1]; +} + +- (RATreeNodeController *)controllerForItem:(id)item +{ + if (item == self.treeNode.item) { + return self; + } + + for (RATreeNodeController *controller in self.childControllers) { + RATreeNodeController *result = [controller controllerForItem:item]; + if (result) { + return result; + } + } + + return nil; +} + +- (RATreeNodeController *)controllerForIndex:(NSInteger)index +{ + if (self.index == index) { + return self; + } + + if (!self.treeNode.expanded) { + return nil; + } + + for (RATreeNodeController *controller in self.childControllers) { + RATreeNodeController *result = [controller controllerForIndex:index]; + if (result) { + return result; + } + } + + return nil; +} + +- (NSInteger)indexForItem:(id)item +{ + RATreeNodeController *controller = [self controllerForItem:item]; + return controller ? controller.index : NSNotFound; +} + +- (NSInteger)lastVisibleDescendatIndexForItem:(id)item +{ + if (self.treeNode.item == item) { + return [self lastVisibleDescendatIndex]; + } + + for (RATreeNodeController *nodeController in self.childControllers) { + NSInteger lastIndex = [nodeController lastVisibleDescendatIndexForItem:item]; + if (lastIndex != NSNotFound) { + return lastIndex; + } + } + + return NSNotFound; +} + + +#pragma mark - Collapsing and expanding + +- (void)expandAndExpandChildren:(BOOL)expandChildren +{ + for (RATreeNodeController *nodeController in self.childControllers) { + [nodeController invalidate]; + } + [self privateExpandAndExpandChildren:expandChildren]; +} + +- (void)privateExpandAndExpandChildren:(BOOL)expandChildren +{ + [self.treeNode setExpanded:YES]; + [self invalidate]; + + for (RATreeNodeController *nodeController in self.childControllers) { + if (nodeController.treeNode.expanded || expandChildren) { + [nodeController expandAndExpandChildren:expandChildren]; + } + } + + [self.parentController invalidateTreeNodesAfterChildAtIndex:[self.parentController.childControllers indexOfObject:self]]; +} + +- (void)collapseAndCollapseChildren:(BOOL)collapseChildren +{ + [self privateCollapseAndCollapseChildren:collapseChildren]; +} + +- (void)privateCollapseAndCollapseChildren:(BOOL)collapseChildren +{ + [self.treeNode setExpanded:NO]; + [self invalidate]; + + if (collapseChildren) { + for (RATreeNodeController *controller in self.childControllers) { + [controller collapseAndCollapseChildren:collapseChildren]; + } + } + + [self.parentController invalidateTreeNodesAfterChildAtIndex:[self.parentController.childControllers indexOfObject:self]]; +} + + +#pragma mark - + +- (void)invalidate +{ + [self invalidateNumberOfVisibleDescendants]; + [self invalideIndex]; +} + +- (void)invalidateNumberOfVisibleDescendants +{ + self.numberOfVisibleDescendants = NSIntegerMin; +} + +- (void)invalideIndex +{ + self.index = NSIntegerMin; +} + +- (void)invalidateTreeNodesAfterChildAtIndex:(NSInteger)index +{ + NSInteger selfIndex = [self.parentController.childControllers indexOfObject:self]; + [self.parentController invalidateTreeNodesAfterChildAtIndex:selfIndex]; + + [self invalidate]; + [self invalidateDescendantsNodesAfterChildAtIndex:index]; +} + +- (void)invalidateDescendantsNodesAfterChildAtIndex:(NSInteger)index +{ + if (!self.treeNode.expanded) { + return; + } + for (NSInteger i = index + 1; i < self.childControllers.count; i++) { + RATreeNodeController *controller = self.childControllers[i]; + [controller invalidate]; + [controller invalidateDescendantsNodesAfterChildAtIndex:-1]; + } +} + + +#pragma mark - Properties + +- (NSArray *)childControllers +{ + return self.mutablechildControllers; +} + +- (NSInteger)index +{ + if (_index != NSIntegerMin) { + return _index; + } + if (!self.parentController) { + _index = -1; + + } else if (!self.parentController.treeNode.expanded) { + _index = NSNotFound; + + } else { + NSInteger indexInParent = [self.parentController.childControllers indexOfObject:self]; + if (indexInParent != 0) { + RATreeNodeController *controller = self.parentController.childControllers[indexInParent-1]; + _index = [controller lastVisibleDescendatIndex] + 1; + + } else { + _index = self.parentController.index + 1; + } + } + return _index; +} + +- (NSInteger)lastVisibleDescendatIndex +{ + return self.index + self.numberOfVisibleDescendants; +} + +- (NSIndexSet *)descendantsIndexes +{ + NSInteger numberOfVisibleDescendants = self.numberOfVisibleDescendants; + NSInteger startIndex = self.index + 1; + + NSMutableIndexSet *indexSet = [NSMutableIndexSet indexSet]; + for (NSInteger i = startIndex; i < startIndex + numberOfVisibleDescendants; i++) { + [indexSet addIndex:i]; + } + return [indexSet copy]; +} + +- (NSInteger)numberOfVisibleDescendants +{ + if (_numberOfVisibleDescendants == NSIntegerMin) { + if (self.treeNode.expanded) { + NSInteger numberOfVisibleDescendants = [self.childControllers count]; + for (RATreeNodeController *controller in self.childControllers) { + numberOfVisibleDescendants += controller.numberOfVisibleDescendants; + } + _numberOfVisibleDescendants = numberOfVisibleDescendants; + } else { + _numberOfVisibleDescendants = 0; + } + } + return _numberOfVisibleDescendants; +} + +- (NSInteger)level +{ + if (self.treeNode.item == nil) { + return -1; + } + + if (_level == NSIntegerMin) { + _level = self.parentController.level + 1; + } + + return _level; +} + +@end diff --git a/Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RATreeNodeItem+ClassExtension.h b/Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RATreeNodeItem+ClassExtension.h new file mode 100644 index 0000000..11ed970 --- /dev/null +++ b/Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RATreeNodeItem+ClassExtension.h @@ -0,0 +1,31 @@ + +//The MIT License (MIT) +// +//Copyright (c) 2014 Rafał Augustyniak +// +//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: +// +//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. +// + +#import "RATreeNodeItem.h" + +@interface RATreeNodeItem () + +@property (nonatomic, strong) id item; +@property (nonatomic, weak) id parent; +@property (nonatomic) NSInteger index; + +@property (nonatomic, weak) id dataSource; + +@end diff --git a/Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RATreeNodeItem+Private.h b/Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RATreeNodeItem+Private.h new file mode 100644 index 0000000..785d8e7 --- /dev/null +++ b/Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RATreeNodeItem+Private.h @@ -0,0 +1,37 @@ + +//The MIT License (MIT) +// +//Copyright (c) 2014 Rafał Augustyniak +// +//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: +// +//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. +// + + +#import "RATreeNodeItem.h" + +@protocol RATreeNodeItemDataSource + +- (id)itemForTreeNodeItem:(RATreeNodeItem *)treeNodeItem; + +@end + + +@interface RATreeNodeItem (Private) + +@property (nonatomic, strong, readonly) id parent; +@property (nonatomic, readonly) NSInteger index; +@property (nonatomic, weak) id dataSource; + +@end diff --git a/Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RATreeNodeItem+Private.m b/Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RATreeNodeItem+Private.m new file mode 100644 index 0000000..aa7dabb --- /dev/null +++ b/Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RATreeNodeItem+Private.m @@ -0,0 +1,29 @@ + +//The MIT License (MIT) +// +//Copyright (c) 2014 Rafał Augustyniak +// +//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: +// +//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. +// + +#import "RATreeNodeItem+Private.h" + +@implementation RATreeNodeItem (Private) + +@dynamic dataSource; +@dynamic index; +@dynamic parent; + +@end diff --git a/Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RATreeNodeItem.h b/Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RATreeNodeItem.h new file mode 100644 index 0000000..2ded82d --- /dev/null +++ b/Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RATreeNodeItem.h @@ -0,0 +1,30 @@ + +//The MIT License (MIT) +// +//Copyright (c) 2014 Rafał Augustyniak +// +//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: +// +//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. +// + + +#import + +@interface RATreeNodeItem : NSObject + +@property (nonatomic, strong, readonly) id item; + +- (instancetype)initWithParent:(id)parent index:(NSInteger)index; + +@end diff --git a/Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RATreeNodeItem.m b/Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RATreeNodeItem.m new file mode 100644 index 0000000..ea45e04 --- /dev/null +++ b/Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RATreeNodeItem.m @@ -0,0 +1,48 @@ + +//The MIT License (MIT) +// +//Copyright (c) 2014 Rafał Augustyniak +// +//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: +// +//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. +// + + +#import "RATreeNodeItem.h" +#import "RATreeNodeItem+Private.h" +#import "RATreeNodeItem+ClassExtension.h" + + +@implementation RATreeNodeItem + +- (instancetype)initWithParent:(id)parent index:(NSInteger)index +{ + self = [super init]; + if (self) { + _parent = parent; + _index = index; + } + + return self; +} + +- (id)item +{ + if (!_item) { + _item = [self.dataSource itemForTreeNodeItem:self]; + } + return _item; +} + +@end diff --git a/Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RATreeNode_ClassExtension.h b/Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RATreeNode_ClassExtension.h new file mode 100644 index 0000000..ee6cfc7 --- /dev/null +++ b/Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RATreeNode_ClassExtension.h @@ -0,0 +1,27 @@ + +//The MIT License (MIT) +// +//Copyright (c) 2014 Rafał Augustyniak +// +//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: +// +//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. +// + +#import "RATreeNode.h" + +@interface RATreeNode () + +@property (nonatomic) BOOL expanded; + +@end diff --git a/Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RATreeView+Enums.h b/Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RATreeView+Enums.h new file mode 100644 index 0000000..6aa20d9 --- /dev/null +++ b/Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RATreeView+Enums.h @@ -0,0 +1,41 @@ + +//The MIT License (MIT) +// +//Copyright (c) 2014 Rafał Augustyniak +// +//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: +// +//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. +// + +#import "RATreeView.h" + +@interface RATreeView (Enums) + +//Row Animations ++ (UITableViewRowAnimation)tableViewRowAnimationForTreeViewRowAnimation:(RATreeViewRowAnimation)rowAnimation; + +#if TARGET_OS_IOS +//Cell Separator Styles ++ (RATreeViewCellSeparatorStyle)treeViewCellSeparatorStyleForTableViewSeparatorStyle:(UITableViewCellSeparatorStyle)style; ++ (UITableViewCellSeparatorStyle)tableViewCellSeparatorStyleForTreeViewCellSeparatorStyle:(RATreeViewCellSeparatorStyle)style; +#endif + +//Tree View Style ++ (UITableViewStyle)tableViewStyleForTreeViewStyle:(RATreeViewStyle)treeViewStyle; ++ (RATreeViewStyle)treeViewStyleForTableViewStyle:(UITableViewStyle)tableViewStyle; + +//Scroll Positions ++ (UITableViewScrollPosition)tableViewScrollPositionForTreeViewScrollPosition:(RATreeViewScrollPosition)scrollPosition; + +@end diff --git a/Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RATreeView+Enums.m b/Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RATreeView+Enums.m new file mode 100644 index 0000000..80563d9 --- /dev/null +++ b/Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RATreeView+Enums.m @@ -0,0 +1,128 @@ + +//The MIT License (MIT) +// +//Copyright (c) 2014 Rafał Augustyniak +// +//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: +// +//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. +// + +#import "RATreeView+Enums.h" +#import "RATreeView.h" + +@implementation RATreeView (Enums) + +#pragma mark Row Animations + ++ (UITableViewRowAnimation)tableViewRowAnimationForTreeViewRowAnimation:(RATreeViewRowAnimation)rowAnimation +{ + switch (rowAnimation) { + case RATreeViewRowAnimationFade: + return UITableViewRowAnimationFade; + case RATreeViewRowAnimationNone: + return UITableViewRowAnimationNone; + case RATreeViewRowAnimationAutomatic: + return UITableViewRowAnimationAutomatic; + case RATreeViewRowAnimationBottom: + return UITableViewRowAnimationBottom; + case RATreeViewRowAnimationLeft: + return UITableViewRowAnimationLeft; + case RATreeViewRowAnimationMiddle: + return UITableViewRowAnimationMiddle; + case RATreeViewRowAnimationRight: + return UITableViewRowAnimationRight; + case RATreeViewRowAnimationTop: + return UITableViewRowAnimationTop; + default: + return UITableViewRowAnimationNone; + } +} + +#if TARGET_OS_IOS + +#pragma mark Cell Separator Styles + ++ (RATreeViewCellSeparatorStyle)treeViewCellSeparatorStyleForTableViewSeparatorStyle:(UITableViewCellSeparatorStyle)style +{ + switch (style) { + case UITableViewCellSeparatorStyleNone: + return RATreeViewCellSeparatorStyleNone; + case UITableViewCellSeparatorStyleSingleLine: + return RATreeViewCellSeparatorStyleSingleLine; + case UITableViewCellSeparatorStyleSingleLineEtched: + return RATreeViewCellSeparatorStyleSingleLineEtched; + default: + return RATreeViewCellSeparatorStyleNone; + } +} + ++ (UITableViewCellSeparatorStyle)tableViewCellSeparatorStyleForTreeViewCellSeparatorStyle:(RATreeViewCellSeparatorStyle)style +{ + switch (style) { + case RATreeViewCellSeparatorStyleNone: + return UITableViewCellSeparatorStyleNone; + case RATreeViewCellSeparatorStyleSingleLine: + return UITableViewCellSeparatorStyleSingleLine; + case RATreeViewCellSeparatorStyleSingleLineEtched: + return UITableViewCellSeparatorStyleSingleLineEtched; + default: + return UITableViewCellSeparatorStyleNone; + } +} + +#endif + +#pragma mark Tree View Style + ++ (UITableViewStyle)tableViewStyleForTreeViewStyle:(RATreeViewStyle)treeViewStyle +{ + switch (treeViewStyle) { + case RATreeViewStylePlain: + return UITableViewStylePlain; + case RATreeViewStyleGrouped: + return UITableViewStyleGrouped; + } +} + ++ (RATreeViewStyle)treeViewStyleForTableViewStyle:(UITableViewStyle)tableViewStyle +{ + switch (tableViewStyle) { + case UITableViewStylePlain: + return RATreeViewStylePlain; + case UITableViewStyleGrouped: + return RATreeViewStyleGrouped; + default: + return RATreeViewStylePlain; + } +} +#pragma mark Scroll Positions + ++ (UITableViewScrollPosition)tableViewScrollPositionForTreeViewScrollPosition:(RATreeViewScrollPosition)scrollPosition +{ + switch (scrollPosition) { + case RATreeViewScrollPositionNone: + return UITableViewScrollPositionNone; + case RATreeViewScrollPositionTop: + return UITableViewScrollPositionTop; + case RATreeViewScrollPositionMiddle: + return UITableViewScrollPositionMiddle; + case RATreeViewScrollPositionBottom: + return UITableViewScrollPositionBottom; + default: + return UITableViewScrollPositionNone; + } +} + + +@end diff --git a/Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RATreeView+Private.h b/Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RATreeView+Private.h new file mode 100644 index 0000000..9476c9d --- /dev/null +++ b/Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RATreeView+Private.h @@ -0,0 +1,43 @@ + +//The MIT License (MIT) +// +//Copyright (c) 2014 Rafał Augustyniak +// +//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: +// +//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. +// + + +#import "RATreeView.h" + + +@class RATreeNode; + + +@interface RATreeView (Private) + +- (RATreeNode *)treeNodeForIndexPath:(NSIndexPath *)indexPath; +- (NSIndexPath *)indexPathForItem:(id)item; + +- (void)setupTreeStructure; + +- (void)collapseCellForTreeNode:(RATreeNode *)treeNode; +- (void)collapseCellForTreeNode:(RATreeNode *)treeNode collapseChildren:(BOOL)collapseChildren withRowAnimation:(RATreeViewRowAnimation)rowAnimation; +- (void)expandCellForTreeNode:(RATreeNode *)treeNode; +- (void)expandCellForTreeNode:(RATreeNode *)treeNode expandChildren:(BOOL)expandChildren withRowAnimation:(RATreeViewRowAnimation)rowAnimation; + +- (void)insertItemAtIndex:(NSInteger)index inParent:(id)parent withAnimation:(RATreeViewRowAnimation)animation; +- (void)removeItemAtIndex:(NSInteger)indexe inParent:(id)parent withAnimation:(RATreeViewRowAnimation)animation; + +@end diff --git a/Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RATreeView+Private.m b/Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RATreeView+Private.m new file mode 100644 index 0000000..556be52 --- /dev/null +++ b/Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RATreeView+Private.m @@ -0,0 +1,192 @@ + +//The MIT License (MIT) +// +//Copyright (c) 2014 Rafał Augustyniak +// +//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: +// +//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. +// + +#import "RATreeView+Private.h" +#import "RATreeView+Enums.h" +#import "RATreeView+RATreeNodeCollectionControllerDataSource.h" +#import "RATreeView_ClassExtension.h" + +#import "RABatchChanges.h" + +#import "RATreeNode.h" +#import "RATreeNodeController.h" +#import "RATreeNodeCollectionController.h" + + + +@implementation RATreeView (Private) + +- (void)setupTreeStructure +{ + self.treeNodeCollectionController = [[RATreeNodeCollectionController alloc] init]; + self.treeNodeCollectionController.dataSource = self; + self.batchChanges = [[RABatchChanges alloc] init]; +} + +- (NSArray *)childrenForItem:(id)item +{ + NSParameterAssert(item); + + NSMutableArray *children = [NSMutableArray array]; + NSInteger numberOfChildren = [self.dataSource treeView:self numberOfChildrenOfItem:item]; + + for (int i = 0; i < numberOfChildren; i++) { + [children addObject:[self.dataSource treeView:self child:i ofItem:item]]; + } + + return [NSArray arrayWithArray:children]; +} + +- (RATreeNode *)treeNodeForIndexPath:(NSIndexPath *)indexPath +{ + NSParameterAssert(indexPath.section == 0); + return [self.treeNodeCollectionController treeNodeForIndex:indexPath.row]; +} + +- (NSIndexPath *)indexPathForItem:(id)item +{ + return [NSIndexPath indexPathForRow:[self.treeNodeCollectionController indexForItem:item] inSection:0]; +} + + +#pragma mark Collapsing and Expanding Rows + +- (void)collapseCellForTreeNode:(RATreeNode *)treeNode +{ + [self collapseCellForTreeNode:treeNode collapseChildren:self.collapsesChildRowsWhenRowCollapses withRowAnimation:self.rowsCollapsingAnimation]; +} + +- (void)collapseCellForTreeNode:(RATreeNode *)treeNode collapseChildren:(BOOL)collapseChildren withRowAnimation:(RATreeViewRowAnimation)rowAnimation +{ + [self.tableView beginUpdates]; + [self.batchChanges beginUpdates]; + + NSInteger index = [self.treeNodeCollectionController lastVisibleDescendantIndexForItem:treeNode.item]; + + __weak __typeof(self) weakSelf = self; + [self.batchChanges collapseItemWithBlock:^{ + UITableViewRowAnimation tableViewRowAnimation = [RATreeView tableViewRowAnimationForTreeViewRowAnimation:rowAnimation]; + [weakSelf.treeNodeCollectionController collapseRowForItem:treeNode.item collapseChildren:collapseChildren updates:^(NSIndexSet *deletions) { + [weakSelf.tableView deleteRowsAtIndexPaths:IndexesToIndexPaths(deletions) withRowAnimation:tableViewRowAnimation]; + }]; + } lastIndex:index]; + + [self.batchChanges endUpdates]; + [self.tableView endUpdates]; +} + +- (void)expandCellForTreeNode:(RATreeNode *)treeNode +{ + [self expandCellForTreeNode:treeNode expandChildren:self.expandsChildRowsWhenRowExpands withRowAnimation:self.rowsExpandingAnimation]; +} + +- (void)expandCellForTreeNode:(RATreeNode *)treeNode expandChildren:(BOOL)expandChildren withRowAnimation:(RATreeViewRowAnimation)rowAnimation +{ + [self.tableView beginUpdates]; + [self.batchChanges beginUpdates]; + + NSInteger index = [self.treeNodeCollectionController indexForItem:treeNode.item]; + __weak __typeof(self) weakSelf = self; + [self.batchChanges expandItemWithBlock:^{ + UITableViewRowAnimation tableViewRowAnimation = [RATreeView tableViewRowAnimationForTreeViewRowAnimation:rowAnimation]; + [weakSelf.treeNodeCollectionController expandRowForItem:treeNode.item expandChildren:expandChildren updates:^(NSIndexSet *insertions) { + [weakSelf.tableView insertRowsAtIndexPaths:IndexesToIndexPaths(insertions) withRowAnimation:tableViewRowAnimation]; + }]; + } atIndex:index]; + + + [self.batchChanges endUpdates]; + [self.tableView endUpdates]; +} + +- (void)insertItemAtIndex:(NSInteger)index inParent:(id)parent withAnimation:(RATreeViewRowAnimation)animation +{ + NSInteger idx = [self.treeNodeCollectionController indexForItem:parent]; + if (idx == NSNotFound) { + return; + } + idx += index + 1; + + __weak __typeof(self) weakSelf = self; + [self.batchChanges insertItemWithBlock:^{ + [weakSelf.treeNodeCollectionController insertItemsAtIndexes:[NSIndexSet indexSetWithIndex:index] inParent:parent]; + + NSIndexPath *indexPath = [NSIndexPath indexPathForRow:idx inSection:0]; + UITableViewRowAnimation tableViewRowAnimation = [RATreeView tableViewRowAnimationForTreeViewRowAnimation:animation]; + [weakSelf.tableView insertRowsAtIndexPaths:@[indexPath] withRowAnimation:tableViewRowAnimation]; + + } atIndex:idx]; +} + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wobjc-protocol-method-implementation" +- (void)moveItemAtIndex:(NSInteger)index inParent:(id)parent toIndex:(NSInteger)newIndex inParent:(id)newParent +#pragma clang diagnostic pop +{ + NSInteger idx = [self.treeNodeCollectionController indexForItem:parent]; + if (idx == NSNotFound) { + return; + } + + idx += index + 1; + __weak __typeof(self) weakSelf = self; + [self.batchChanges insertItemWithBlock:^{ + [weakSelf.treeNodeCollectionController moveItemAtIndex:index inParent:parent toIndex:newIndex inParent:newParent updates:^(NSIndexSet *deletions, NSIndexSet *additions) { + NSArray *deletionsArray = IndexesToIndexPaths(deletions); + NSArray *additionsArray = IndexesToIndexPaths(additions); + + NSInteger i = 0; + for (NSIndexPath *deletedIndexPath in deletionsArray) { + [weakSelf.tableView moveRowAtIndexPath:deletedIndexPath toIndexPath:additionsArray[i]]; + i++; + } + }]; + } atIndex:idx]; +} + +- (void)removeItemAtIndex:(NSInteger)index inParent:(id)parent withAnimation:(RATreeViewRowAnimation)animation +{ + id child = [self.treeNodeCollectionController childInParent:parent atIndex:index]; + NSInteger idx = [self.treeNodeCollectionController lastVisibleDescendantIndexForItem:child]; + if (idx == NSNotFound) { + return; + } + + __weak __typeof(self) weakSelf = self; + [self.batchChanges insertItemWithBlock:^{ + [weakSelf.treeNodeCollectionController removeItemsAtIndexes:[NSIndexSet indexSetWithIndex:index] inParent:parent updates:^(NSIndexSet *removedIndexes) { + UITableViewRowAnimation tableViewRowAnimation = [RATreeView tableViewRowAnimationForTreeViewRowAnimation:animation]; + [weakSelf.tableView deleteRowsAtIndexPaths:IndexesToIndexPaths(removedIndexes) withRowAnimation:tableViewRowAnimation]; + }]; + } atIndex:idx]; +} + +#pragma mark - + +static NSArray * IndexesToIndexPaths(NSIndexSet *indexes) +{ + NSMutableArray *indexPaths = [NSMutableArray array]; + [indexes enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL *stop) { + [indexPaths addObject:[NSIndexPath indexPathForRow:idx inSection:0]]; + }]; + return [indexPaths copy]; +} + +@end diff --git a/Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RATreeView+RATreeNodeCollectionControllerDataSource.h b/Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RATreeView+RATreeNodeCollectionControllerDataSource.h new file mode 100644 index 0000000..d7d837b --- /dev/null +++ b/Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RATreeView+RATreeNodeCollectionControllerDataSource.h @@ -0,0 +1,26 @@ + +//The MIT License (MIT) +// +//Copyright (c) 2014 Rafał Augustyniak +// +//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: +// +//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. +// + +#import "RATreeView.h" +#import "RATreeNodeCollectionController.h" + +@interface RATreeView (RATreeNodeCollectionControllerDataSource) + +@end diff --git a/Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RATreeView+RATreeNodeCollectionControllerDataSource.m b/Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RATreeView+RATreeNodeCollectionControllerDataSource.m new file mode 100644 index 0000000..a714a47 --- /dev/null +++ b/Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RATreeView+RATreeNodeCollectionControllerDataSource.m @@ -0,0 +1,35 @@ + +//The MIT License (MIT) +// +//Copyright (c) 2014 Rafał Augustyniak +// +//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: +// +//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. +// + +#import "RATreeView+RATreeNodeCollectionControllerDataSource.h" + +@implementation RATreeView (RATreeNodeCollectionControllerDataSource) + +- (NSInteger)treeNodeCollectionController:(RATreeNodeCollectionController *)controller numberOfChildrenForItem:(id)item +{ + return [self.dataSource treeView:self numberOfChildrenOfItem:item]; +} + +- (id)treeNodeCollectionController:(RATreeNodeCollectionController *)controller child:(NSInteger)childIndex ofItem:(id)item +{ + return [self.dataSource treeView:self child:childIndex ofItem:item]; +} + +@end diff --git a/Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RATreeView+TableViewDataSource.h b/Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RATreeView+TableViewDataSource.h new file mode 100644 index 0000000..52cec06 --- /dev/null +++ b/Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RATreeView+TableViewDataSource.h @@ -0,0 +1,25 @@ + +//The MIT License (MIT) +// +//Copyright (c) 2014 Rafał Augustyniak +// +//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: +// +//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. +// + +#import "RATreeView.h" + +@interface RATreeView (TableViewDataSource) + +@end diff --git a/Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RATreeView+TableViewDataSource.m b/Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RATreeView+TableViewDataSource.m new file mode 100644 index 0000000..d1bc67d --- /dev/null +++ b/Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RATreeView+TableViewDataSource.m @@ -0,0 +1,70 @@ + +//The MIT License (MIT) +// +//Copyright (c) 2014 Rafał Augustyniak +// +//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: +// +//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. +// + +#import "RATreeView+TableViewDataSource.h" +#import "RATreeView+Private.h" +#import "RATreeView_ClassExtension.h" + +#import "RATreeNodeCollectionController.h" +#import "RATreeNodeController.h" +#import "RATreeNode.h" + +@implementation RATreeView (TableViewDataSource) + +- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView +{ + return 1; +} + +- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section +{ + if (self.treeNodeCollectionController == nil) { + [self setupTreeStructure]; + } + return self.treeNodeCollectionController.numberOfVisibleRowsForItems; +} + +- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath +{ + RATreeNode *treeNode = [self treeNodeForIndexPath:indexPath]; + return [self.dataSource treeView:self cellForItem:treeNode.item]; +} + + +#pragma mark - Inserting or Deleting Table Rows + +- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath +{ + if ([self.dataSource respondsToSelector:@selector(treeView:commitEditingStyle:forRowForItem:)]) { + RATreeNode *treeNode = [self treeNodeForIndexPath:indexPath]; + [self.dataSource treeView:self commitEditingStyle:editingStyle forRowForItem:treeNode.item]; + } +} + +- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath +{ + if ([self.dataSource respondsToSelector:@selector(treeView:canEditRowForItem:)]) { + RATreeNode *treeNode = [self treeNodeForIndexPath:indexPath]; + return [self.dataSource treeView:self canEditRowForItem:treeNode.item]; + } + return YES; +} + +@end diff --git a/Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RATreeView+TableViewDelegate.h b/Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RATreeView+TableViewDelegate.h new file mode 100644 index 0000000..3ae682b --- /dev/null +++ b/Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RATreeView+TableViewDelegate.h @@ -0,0 +1,25 @@ + +//The MIT License (MIT) +// +//Copyright (c) 2014 Rafał Augustyniak +// +//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: +// +//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. +// + +#import "RATreeView.h" + +@interface RATreeView (TableViewDelegate) + +@end diff --git a/Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RATreeView+TableViewDelegate.m b/Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RATreeView+TableViewDelegate.m new file mode 100644 index 0000000..776419b --- /dev/null +++ b/Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RATreeView+TableViewDelegate.m @@ -0,0 +1,318 @@ + +//The MIT License (MIT) +// +//Copyright (c) 2014 Rafał Augustyniak +// +//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: +// +//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. +// + +#import + +#import "RATreeView+TableViewDelegate.h" +#import "RATreeView_ClassExtension.h" +#import "RATreeView+Private.h" + +#import "RATreeView.h" +#import "RATreeNodeCollectionController.h" +#import "RATreeNode.h" + +@implementation RATreeView (TableViewDelegate) + +#pragma mark - Configuring Rows for the Table View + +- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath +{ + if ([self.delegate respondsToSelector:@selector(treeView:heightForRowForItem:)]) { + RATreeNode *treeNode = [self treeNodeForIndexPath:indexPath]; + return [self.delegate treeView:self heightForRowForItem:treeNode.item]; + } + return self.tableView.rowHeight; +} + +- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath +{ + if ([self.delegate respondsToSelector:@selector(treeView:estimatedHeightForRowForItem:)]) { + RATreeNode *treeNode = [self treeNodeForIndexPath:indexPath]; + return [self.delegate treeView:self estimatedHeightForRowForItem:treeNode.item]; + } + return UITableViewAutomaticDimension; +} + +- (NSInteger)tableView:(UITableView *)tableView indentationLevelForRowAtIndexPath:(NSIndexPath *)indexPath +{ + if ([self.delegate respondsToSelector:@selector(treeView:indentationLevelForRowForItem:)]) { + RATreeNode *treeNode = [self treeNodeForIndexPath:indexPath]; + return [self.delegate treeView:self indentationLevelForRowForItem:treeNode.item]; + } + return 0; +} + +- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath +{ + if ([self.delegate respondsToSelector:@selector(treeView:willDisplayCell:forItem:)]) { + RATreeNode *treeNode = [self treeNodeForIndexPath:indexPath]; + [self.delegate treeView:self willDisplayCell:cell forItem:treeNode.item]; + } +} + + +#pragma mark - Managing Accessory Views + +- (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath +{ + if ([self.delegate respondsToSelector:@selector(treeView:accessoryButtonTappedForRowForItem:)]) { + RATreeNode *treeNode = [self treeNodeForIndexPath:indexPath]; + [self.delegate treeView:self accessoryButtonTappedForRowForItem:treeNode.item]; + } +} + + +#pragma mark - Managing Selection + +- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath +{ + if ([self.delegate respondsToSelector:@selector(treeView:willSelectRowForItem:)]) { + RATreeNode *treeNode = [self treeNodeForIndexPath:indexPath]; + id item = [self.delegate treeView:self willSelectRowForItem:treeNode.item]; + if (item) { + NSIndexPath *newIndexPath = [self indexPathForItem:item]; + return (newIndexPath.row == NSNotFound) ? indexPath : newIndexPath; + } else { + return nil; + } + } + return indexPath; +} + +- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath +{ + RATreeNode *treeNode = [self treeNodeForIndexPath:indexPath]; + if ([self.delegate respondsToSelector:@selector(treeView:didSelectRowForItem:)]) { + [self.delegate treeView:self didSelectRowForItem:treeNode.item]; + } + + if (treeNode.expanded) { + if ([self.delegate respondsToSelector:@selector(treeView:shouldCollapaseRowForItem:)]) { + if ([self.delegate treeView:self shouldCollapaseRowForItem:treeNode.item]) { + [self collapseCellForTreeNode:treeNode informDelegate:YES]; + } + } else { + [self collapseCellForTreeNode:treeNode informDelegate:YES]; + } + } else { + if ([self.delegate respondsToSelector:@selector(treeView:shouldExpandRowForItem:)]) { + if ([self.delegate treeView:self shouldExpandRowForItem:treeNode.item]) { + [self expandCellForTreeNode:treeNode informDelegate:YES]; + } + } else { + [self expandCellForTreeNode:treeNode informDelegate:YES]; + } + } +} + +- (NSIndexPath *)tableView:(UITableView *)tableView willDeselectRowAtIndexPath:(NSIndexPath *)indexPath +{ + if ([self.delegate respondsToSelector:@selector(treeView:willDeselectRowForItem:)]) { + RATreeNode *treeNode = [self treeNodeForIndexPath:indexPath]; + id item = [self.delegate treeView:self willDeselectRowForItem:treeNode.item]; + NSIndexPath *delegateIndexPath = [self indexPathForItem:item]; + return delegateIndexPath.row == NSNotFound ? indexPath : delegateIndexPath; + } else { + return indexPath; + } +} + +- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath +{ + if ([self.delegate respondsToSelector:@selector(treeView:didDeselectRowForItem:)]) { + RATreeNode *treeNode = [self treeNodeForIndexPath:indexPath]; + [self.delegate treeView:self didDeselectRowForItem:treeNode.item]; + } +} + +- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath +{ + if ([self.delegate respondsToSelector:@selector(treeView:editingStyleForRowForItem:)]) { + RATreeNode *treeNode = [self treeNodeForIndexPath:indexPath]; + return [self.delegate treeView:self editingStyleForRowForItem:treeNode.item]; + } + return UITableViewCellEditingStyleDelete; +} + +- (NSString *)tableView:(UITableView *)tableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath +{ + if ([self.delegate respondsToSelector:@selector(treeView:titleForDeleteConfirmationButtonForRowForItem:)]) { + RATreeNode *treeNode = [self treeNodeForIndexPath:indexPath]; + return [self.delegate treeView:self titleForDeleteConfirmationButtonForRowForItem:treeNode.item]; + } + return @"Delete"; +} + +- (BOOL)tableView:(UITableView *)tableView shouldIndentWhileEditingRowAtIndexPath:(NSIndexPath *)indexPath +{ + if ([self.delegate respondsToSelector:@selector(treeView:shouldIndentWhileEditingRowForItem:)]) { + RATreeNode *treeNode = [self treeNodeForIndexPath:indexPath]; + return [self.delegate treeView:self shouldIndentWhileEditingRowForItem:treeNode.item]; + } + return YES; +} + + +#pragma mark - Editing Table Rows + +- (void)tableView:(UITableView *)tableView willBeginEditingRowAtIndexPath:(NSIndexPath *)indexPath +{ + if ([self.delegate respondsToSelector:@selector(treeView:willBeginEditingRowForItem:)]) { + RATreeNode *treeNode = [self treeNodeForIndexPath:indexPath]; + [self.delegate treeView:self willBeginEditingRowForItem:treeNode.item]; + } +} + +- (void)tableView:(UITableView *)tableView didEndEditingRowAtIndexPath:(NSIndexPath *)indexPath +{ + if ([self.delegate respondsToSelector:@selector(treeView:didEndEditingRowForItem:)]) { + RATreeNode *treeNode = [self treeNodeForIndexPath:indexPath]; + [self.delegate treeView:self didEndEditingRowForItem:treeNode.item]; + } +} + +- (NSArray *)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath +{ + if ([self.delegate respondsToSelector:@selector(treeView:editActionsForItem:)]) { + RATreeNode *treeNode = [self treeNodeForIndexPath:indexPath]; + return [self.delegate treeView:self editActionsForItem:treeNode.item]; + } + return nil; +} + + +#pragma mark - Tracking the Removal of Views + +- (void)tableView:(UITableView *)tableView didEndDisplayingCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath +{ + if ([self.delegate respondsToSelector:@selector(treeView:didEndDisplayingCell:forItem:)]) { + RATreeNode *treeNode = [self treeNodeForIndexPath:indexPath]; + [self.delegate treeView:self didEndDisplayingCell:cell forItem:treeNode.item]; + } +} + + +#pragma mark - Copying and Pasting Row Content + +- (BOOL)tableView:(UITableView *)tableView shouldShowMenuForRowAtIndexPath:(NSIndexPath *)indexPath +{ + if ([self.delegate respondsToSelector:@selector(treeView:shouldShowMenuForRowForItem:)]) { + RATreeNode *treeNode = [self treeNodeForIndexPath:indexPath]; + return [self.delegate treeView:self shouldShowMenuForRowForItem:treeNode.item]; + } + return NO; +} + +- (BOOL)tableView:(UITableView *)tableView canPerformAction:(SEL)action forRowAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender +{ + if ([self.delegate respondsToSelector:@selector(treeView:canPerformAction:forRowForItem:withSender:)]) { + RATreeNode *treeNode = [self treeNodeForIndexPath:indexPath]; + return [self.delegate treeView:self canPerformAction:action forRowForItem:treeNode.item withSender:sender]; + } + return NO; +} + +- (void)tableView:(UITableView *)tableView performAction:(SEL)action forRowAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender +{ + if ([self.delegate respondsToSelector:@selector(treeView:performAction:forRowForItem:withSender:)]) { + RATreeNode *treeNode = [self treeNodeForIndexPath:indexPath]; + return [self.delegate treeView:self performAction:action forRowForItem:treeNode.item withSender:sender]; + } +} + + +#pragma mark - Managing Table View Highlighting + +- (BOOL)tableView:(UITableView *)tableView shouldHighlightRowAtIndexPath:(NSIndexPath *)indexPath +{ + if ([self.delegate respondsToSelector:@selector(treeView:shouldHighlightRowForItem:)]) { + RATreeNode *treeNode = [self treeNodeForIndexPath:indexPath]; + return [self.delegate treeView:self shouldHighlightRowForItem:treeNode.item]; + } + return YES; +} + +- (void)tableView:(UITableView *)tableView didHighlightRowAtIndexPath:(NSIndexPath *)indexPath +{ + if ([self.delegate respondsToSelector:@selector(treeView:didHighlightRowForItem:)]) { + RATreeNode *treeNode = [self treeNodeForIndexPath:indexPath]; + [self.delegate treeView:self didHighlightRowForItem:treeNode.item]; + } +} + +- (void)tableView:(UITableView *)tableView didUnhighlightRowAtIndexPath:(NSIndexPath *)indexPath +{ + if ([self.delegate respondsToSelector:@selector(treeView:didUnhighlightRowForItem:)]) { + RATreeNode *treeNode = [self treeNodeForIndexPath:indexPath]; + [self.delegate treeView:self didUnhighlightRowForItem:treeNode.item]; + } +} + + +#pragma mark - Private Helpers + +- (void)collapseCellForTreeNode:(RATreeNode *)treeNode informDelegate:(BOOL)informDelegate +{ + if (informDelegate) { + if ([self.delegate respondsToSelector:@selector(treeView:willCollapseRowForItem:)]) { + [self.delegate treeView:self willCollapseRowForItem:treeNode.item]; + } + } + + [CATransaction begin]; + [CATransaction setCompletionBlock:^{ + if ([self.delegate respondsToSelector:@selector(treeView:didCollapseRowForItem:)] && + informDelegate) { + dispatch_async(dispatch_get_main_queue(), ^{ + //Content size of the UITableView isn't updates when completion block of the CATransaction is called. To make it possible for the user of the RATreeView to get a correct content size in the implementation of the 'treeView:didCollapseRowForItem' RATreeView calls this method in the next run loop. + [self.delegate treeView:self didCollapseRowForItem:treeNode.item]; + }); + } + }]; + + [self collapseCellForTreeNode:treeNode]; + [CATransaction commit]; +} + +- (void)expandCellForTreeNode:(RATreeNode *)treeNode informDelegate:(BOOL)informDelegate +{ + if (informDelegate) { + if ([self.delegate respondsToSelector:@selector(treeView:willExpandRowForItem:)]) { + [self.delegate treeView:self willExpandRowForItem:treeNode.item]; + } + } + + [CATransaction begin]; + [CATransaction setCompletionBlock:^{ + if ([self.delegate respondsToSelector:@selector(treeView:didExpandRowForItem:)] && + informDelegate) { + dispatch_async(dispatch_get_main_queue(), ^{ + //Content size of the UITableView isn't updates when completion block of the CATransaction is called. To make it possible for the user of the RATreeView to get a correct content size in the implementation of the 'treeView:didExpandRowForItem' RATreeView calls this method in the next run loop. + [self.delegate treeView:self didExpandRowForItem:treeNode.item]; + }); + } + }]; + + [self expandCellForTreeNode:treeNode]; + [CATransaction commit]; +} + + +@end diff --git a/Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RATreeView_ClassExtension.h b/Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RATreeView_ClassExtension.h new file mode 100644 index 0000000..c3bb536 --- /dev/null +++ b/Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/Private Files/RATreeView_ClassExtension.h @@ -0,0 +1,33 @@ + +//The MIT License (MIT) +// +//Copyright (c) 2014 Rafał Augustyniak +// +//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: +// +//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. +// + +#import "RATreeView.h" + +@class RABatchChanges; + + +@interface RATreeView () + +@property (nonatomic, strong) UITableView *tableView; +@property (nonatomic, strong) RATreeNodeCollectionController *treeNodeCollectionController; + +@property (nonatomic, strong) RABatchChanges *batchChanges; + +@end diff --git a/Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/RATreeView.h b/Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/RATreeView.h new file mode 100644 index 0000000..5b95eaf --- /dev/null +++ b/Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/RATreeView.h @@ -0,0 +1,604 @@ +//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: +// +//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. +// + + +#import + +NS_ASSUME_NONNULL_BEGIN + +@class RATreeView, RATreeNodeCollectionController, RATreeNode; + + +typedef enum { + RATreeViewStylePlain = 0, + RATreeViewStyleGrouped +} RATreeViewStyle; + +typedef enum RATreeViewCellSeparatorStyle { + RATreeViewCellSeparatorStyleNone = 0, + RATreeViewCellSeparatorStyleSingleLine, + RATreeViewCellSeparatorStyleSingleLineEtched +} RATreeViewCellSeparatorStyle; + +typedef enum RATreeViewScrollPosition { + RATreeViewScrollPositionNone = 0, + RATreeViewScrollPositionTop, + RATreeViewScrollPositionMiddle, + RATreeViewScrollPositionBottom +} RATreeViewScrollPosition; + +typedef enum RATreeViewRowAnimation { + RATreeViewRowAnimationFade = 0, + RATreeViewRowAnimationRight, + RATreeViewRowAnimationLeft, + RATreeViewRowAnimationTop, + RATreeViewRowAnimationBottom, + RATreeViewRowAnimationNone, + RATreeViewRowAnimationMiddle, + RATreeViewRowAnimationAutomatic = UITableViewRowAnimationAutomatic +} RATreeViewRowAnimation; + + +/** + * The data source of the RATreeView object must conform to RATreeVIewDataSource protocol. It is implemented by an object with metdiates the application's data model for RATreeView object. + */ +@protocol RATreeViewDataSource + +///------------------------------------------------ +/// Configuring a Tree View +///------------------------------------------------ + +/** + * Ask the data source to return the number of child items encompassed by a given item. (required) + * + * @param treeView The tree-view that sent the message. + * @param item An item identifying a cell in tree view. + * @param treeNodeInfo Object including additional information about item. + * + * @return The number of child items encompassed by item. If item is nil, this method should return the number of children for the top-level item. + */ +- (NSInteger)treeView:(RATreeView *)treeView numberOfChildrenOfItem:(nullable id)item; + + +/** + * Asks the data source for a cell to insert for a specified item. (required) + * + * @param treeView A tree-view object requesting the cell. + * @param item An item identifying a cell in tree view. + * + * @return An object inheriting from UITableViewCell that the tree view can use for the specified row. An assertion is raised if you return nil. + */ +- (UITableViewCell *)treeView:(RATreeView *)treeView cellForItem:(nullable id)item; + +/** + * Ask the data source to return the child item at the specified index of a given item. (required) + * + * @param treeView The tree-view object requesting child of the item at the specified index. + * @param index The index of the child item from item to return. + * @param item An item identifying a cell in tree view. + * + * @return The child item at index of a item. If item is nil, returns the appropriate child item of the root object. + */ +- (id)treeView:(RATreeView *)treeView child:(NSInteger)index ofItem:(nullable id)item; + +@optional + +///------------------------------------------------ +/// Inserting or Deleting Tree Rows +///------------------------------------------------ + +/** + * Asks the data source to commit the insertion or deletion of a row for specified item in the receiver. + * + * @param treeView The tree-view object requesting the insertion or deletion. + * @param editingStyle The cell editing style corresponding to a insertion or deletion requested for the row specified by item. Possible editing styles are `UITableViewCellEditingStyleInsert` or `UITableViewCellEditingStyleDelete`. + * @param item An item identifying a cell in tree view. + * @param treeNodeInfo Object including additional information about item. + */ +- (void)treeView:(RATreeView *)treeView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowForItem:(id)item; + +/** + * Asks the data source to verify that row for given item is editable. + * + * @param treeView The tree-view object requesting this information. + * @param item An item identifying a cell in tree view. + * + * @return `YES` if the row indicated by indexPath is editable; otherwise, `NO`. + */ +- (BOOL)treeView:(RATreeView *)treeView canEditRowForItem:(id)item; + +@end + + +/** + * The delegate of a RATreeView object must adopt the RATreeViewDelegate protocol. Optional methods of the protocol allow the delegate to manage selections, help to delete and reorder cells, and perform other actions. + */ +@protocol RATreeViewDelegate + +@optional + + +///------------------------------------------------ +/// Configuring Rows for the Tree View +///------------------------------------------------ + +/** + * Asks the delegate for the height to use for a row for a specified item. + * + * @param treeView The tree-view object requesting this information. + * @param item An item identifying a cell in tree view. + * + * @return A nonnegative floating-point value that specifies the height (in points) that row should be. + */ +- (CGFloat)treeView:(RATreeView *)treeView heightForRowForItem:(id)item; + +/** + * Asks the delegate for the estimated height of a row for a specified item. + * + * @param treeView The tree-view object requesting this information. + * @param item An item identifying a cell in tree view. + * + * @return A nonnegative floating-point value that specifies the height (in points) of the header for section. + */ +- (CGFloat)treeView:(RATreeView *)treeView estimatedHeightForRowForItem:(id)item NS_AVAILABLE_IOS(7_0); + +/** + * Asks the delegate to return the level of indentation for a row for a specified item. + * + * @param treeView The tree-view object requesting this information. + * @param item An item identifying a cell in tree view. + * + * @return Returns the depth of the specified row to show its hierarchical position. + */ +- (NSInteger)treeView:(RATreeView *)treeView indentationLevelForRowForItem:(id)item; + +/** + * Tells the delegate the tree view is about to draw a cell for a particular item. + * + * @param treeView The tree-view object informing the delegate of this impending event. + * @param cell A table-view cell object that tableView is going to use when drawing the row. + * @param item An item identifying a cell in tree view. + */ +- (void)treeView:(RATreeView *)treeView willDisplayCell:(UITableViewCell *)cell forItem:(id)item; + +///------------------------------------------------ +/// @name Managing Accessory Views +///------------------------------------------------ + +/** + * Tells the delegate that the user tapped the accessory (disclosure) view associated with a row for a given item. + * + * @param treeView The tree-view object informing the delegate of this event. + * @param item An item identifying a cell in tree view. + */ +- (void)treeView:(RATreeView *)treeView accessoryButtonTappedForRowForItem:(id)item; + + +///------------------------------------------------ +/// @name Expanding and Collapsing Tree View rows +///------------------------------------------------ + + +/** + * Asks delegate whether a row for a specified item should be expanded. + * + * @param treeView The tree-view object requesting this information. + * @param item An item identifying a row in tree view. + * + * @return YES if the background of the row should be expanded, otherwise NO. + * @discussion If the delegate does not implement this method, the default is YES. + */ +- (BOOL)treeView:(RATreeView *)treeView shouldExpandRowForItem:(id)item; + +/** + * Asks delegate whether a row for a specified item should be collapsed. + * + * @param treeView The tree-view object requesting this information. + * @param item An item identifying a row in tree view. + * + * @return YES if the background of the row should be expanded, otherwise NO. + * @discussion If the delegate does not implement this method, the default is YES. + */ +- (BOOL)treeView:(RATreeView *)treeView shouldCollapaseRowForItem:(id)item; + +/** + * Tells the delegate that a row for a specified item is about to be expanded. + * + * @param treeView A tree-view object informing the delegate about the impending expansion. + * @param item An item identifying a row in tree view. + */ +- (void)treeView:(RATreeView *)treeView willExpandRowForItem:(id)item; + +/** + * Tells the delegate that a row for a specified item is about to be collapsed. + * + * @param treeView A tree-view object informing the delegate about the impending collapse. + * @param item An item identifying a row in tree view. + */ +- (void)treeView:(RATreeView *)treeView willCollapseRowForItem:(id)item; + +/** + * Tells the delegate that the row for a specified item is now expanded. + * + * @param treeView A tree-view object informing the delegate that new row is expanded. + * @param item An item identifying a row in tree view. + */ +- (void)treeView:(RATreeView *)treeView didExpandRowForItem:(id)item; + +/** + * Tells the delegate that the row for a specified item is now collapsed. + * + * @param treeView A tree-view object informing the delegate that new row is collapsed. + * @param item An item identifying a row in tree view. + */ +- (void)treeView:(RATreeView *)treeView didCollapseRowForItem:(id)item; + + +///------------------------------------------------ +/// @name Managing Selections +///------------------------------------------------ + +/** + * Tells the delegate that a row for a specified item is about to be selected. + * + * @param treeView A tree-view object informing the delegate about the impending selection. + * @param item An item identifying a row in tree view. + * + * @return An id object that confirms or alters the selected row. Return an id object other than item if you want another cell to be selected. Return nil if you don't want the row selected. + */ +- (id)treeView:(RATreeView *)treeView willSelectRowForItem:(id)item; + +/** + * Tells the delegate that the row for a specified item is now selected. + * + * @param treeView A tree-view object informing the delegate about the new row selection. + * @param item An item identifying a row in tree view. + */ +- (void)treeView:(RATreeView *)treeView didSelectRowForItem:(id)item; + +/** + * Tells the delegate that a row for a specified item is about to be deselected. + * + * @param treeView A tree-view object informing the delegate about the impending deselection. + * @param item An item identifying a row in tree view. + * + * @return An id object that confirms or alters the deselected row. Return an id object other than item if you want another cell to be deselected. Return nil if you don’t want the row deselected. + */ +- (id)treeView:(RATreeView *)treeView willDeselectRowForItem:(id)item; + +/** + * Tells the delegate that the row for a specified item is now deselected. + * + * @param treeView A tree-view object informing the delegate about the row deselection. + * @param item An item identifying a row in tree view. + */ +- (void)treeView:(RATreeView *)treeView didDeselectRowForItem:(id)item; + + +///------------------------------------------------ +/// @name Editing Tree Rows +///------------------------------------------------ + +/** + * Tells the delegate that the tree view is about to go into editing mode. + * + * @param treeView The tree-view object providing this information. + * @param item An item identifying a row in tree view. + */ +- (void)treeView:(RATreeView *)treeView willBeginEditingRowForItem:(id)item; + +/** + * Tells the delegate that the tree view has left editing mode. + * + * @param treeView The tree-view object providing this information. + * @param item AAn item identifying a row in tree view. + */ +- (void)treeView:(RATreeView *)treeView didEndEditingRowForItem:(id)item; + +/** + * Asks the delegate for the editing style of a row for a specified item. + * + * @param treeView The tree-view object requesting this information. + * @param item An item identifying a row in tree view. + * + * @return The editing style of the cell for the row identified by item. + * @discussion This method allows the delegate to customize the editing style of the cell for specified item. If the delegate does not implement this method and the UITableViewCell object is editable (that is, it has its editing property set to YES), the cell has the UITableViewCellEditingStyleDelete style set for it. + */ + +- (UITableViewCellEditingStyle)treeView:(RATreeView *)treeView editingStyleForRowForItem:(id)item; + +/** + * Changes the default title of the delete-confirmation button. + * + * @param treeView The tree-view object requesting this information. + * @param item An item identifying a row in tree view. + * + * @return A localized string to used as the title of the delete-confirmation button. + * @discussion By default, the delete-confirmation button, which appears on the right side of the cell, has the title of “Delete”. The tree view displays this button when the user attempts to delete a row, either by swiping the row or tapping the red minus icon in editing mode. You can implement this method to return an alternative title, which should be localized. Default title string ("Delete") isn't localized. + */ +- (NSString *)treeView:(RATreeView *)treeView titleForDeleteConfirmationButtonForRowForItem:(id)item; + +/** + * Asks the delegate whether the background of the row for a specified item should be indented while the tree view is in editing mode. + * + * @param treeView The tree-view object requesting this information. + * @param item An item identifying a row in tree view. + * + * @return YES if the background of the row should be indented, otherwise NO. + * @discussion If the delegate does not implement this method, the default is YES. + */ +- (BOOL)treeView:(RATreeView *)treeView shouldIndentWhileEditingRowForItem:(id)item; + + +/** + * Asks the data source for the edit actions for an item. This is an iOS 8 only method. + * + * @praram treeView The tree-view object requesting this information. + * @param item An item identifying a cell in the tree view. + * + * @return An NSArray of `UITableViewRowAction` objects to show for editing. + */ +- (NSArray *)treeView:(RATreeView *)treeView editActionsForItem:(id)item; + + +///------------------------------------------------ +/// @name Tracking the Removal of Views +///------------------------------------------------ + +/** + * Tells the delegate that the cell for a specified item was removed from the tree. + * + * @param treeView The tree-view object that removed the view. + * @param cell The cell that was removed. + * @param item An item identifying a cell in tree view. + */ +- (void)treeView:(RATreeView *)treeView didEndDisplayingCell:(UITableViewCell *)cell forItem:(id)item; + + +///------------------------------------------------ +/// @name Copying and Pasting Row Content +///------------------------------------------------ + +/** + * Asks the delegate if the editing menu should be shown for a row for a specified item. + * + * @param treeView The tree-view object that is making this request. + * @param item An item identifying a row in tree view. + * + * @return YES if the editing menu should be shown positioned near the row and pointing to it, otherwise NO. The default value is NO. + */ +- (BOOL)treeView:(RATreeView *)treeView shouldShowMenuForRowForItem:(id)item; + +/** + * Asks the delegate if the editing menu should omit the Copy or Paste command for a row for a specified item. + * + * @param treeView The tree-view object that is making this request. + * @param action A selector type identifying the copy: or paste: method of the UIResponderStandardEditActions informal protocol. + * @param item An item identifying a row in tree view. + * @param sender The object that initially sent the copy: or paste: message. + * + * @return YES if the command corresponding to action should appear in the editing menu, otherwise NO. The default value is NO. + */ +- (BOOL)treeView:(RATreeView *)treeView canPerformAction:(SEL)action forRowForItem:(id)item withSender:(id)sender; + +/** + * Tells the delegate to perform a copy or paste operation on the content of a row for a specified item. + * + * @param treeView The tree-view object that is making this request. + * @param action A selector type identifying the copy: or paste: method of the UIResponderStandardEditActions informal protocol. + * @param item An item identifying a row in tree view. + * @param sender The object that initially sent the copy: or paste: message. + * @discussion The tree view invokes this method for a given action if the user taps Copy or Paste in the editing menu. + */ +- (void)treeView:(RATreeView *)treeView performAction:(SEL)action forRowForItem:(id)item withSender:(id)sender; + + +///------------------------------------------------ +/// @name Managing Tree View Highlighting +///------------------------------------------------ + +/** + * Asks the delegate if the row for a specified item should be highlighted. + * + * @param treeView The tree-view object that is making this request. + * @param treeNodeInfo Object including additional information about item. + * + * @return YES if the row should be highlighted or NO if it should not. + */ +- (BOOL)treeView:(RATreeView *)treeView shouldHighlightRowForItem:(id)item; + +/** + * Tells the delegate that the row for a specified item was highlighted. + * + * @param treeView The tree-view object that highlighted the cell. + * @param item An item identifying a row in tree view. + */ +- (void)treeView:(RATreeView *)treeView didHighlightRowForItem:(id)item; + +/** + * Tells the delegate that the highlight was removed from the row for a specified item. + * + * @param treeView The tree-view object that removed the highlight from the cell. + * @param item An item identifying a row in tree view. + */ +- (void)treeView:(RATreeView *)treeView didUnhighlightRowForItem:(id)item; + +@end + + +@interface RATreeView : UIView + +///------------------------------------------------ +/// @name Initializing a RATreeView Object +///------------------------------------------------ + +- (id)initWithFrame:(CGRect)frame style:(RATreeViewStyle)style; + + +///------------------------------------------------ +/// @name Managing the Delegate and the Data Source +///------------------------------------------------ + +@property (nonatomic, nullable, weak) id dataSource; +@property (nonatomic, nullable, weak) id delegate; + + +///------------------------------------------------ +/// @name Configuring the Tree View +///------------------------------------------------ + +- (NSInteger)numberOfRows; +@property (nonatomic, readonly) RATreeViewStyle style; +@property (nonatomic) RATreeViewCellSeparatorStyle separatorStyle; +@property (nonatomic, nullable, strong) UIColor *separatorColor; +@property (nonatomic) CGFloat rowHeight; +@property (nonatomic) CGFloat estimatedRowHeight NS_AVAILABLE_IOS(7_0); +@property (nonatomic) UIEdgeInsets separatorInset NS_AVAILABLE_IOS(7_0); +@property (nonatomic, nullable, copy) UIVisualEffect *separatorEffect NS_AVAILABLE_IOS(8_0) UI_APPEARANCE_SELECTOR; + +@property (nonatomic) BOOL cellLayoutMarginsFollowReadableWidth NS_AVAILABLE_IOS(9_0); +@property (nonatomic, nullable, strong) UIView *backgroundView; + + +///------------------------------------------------ +/// @name Expanding and Collapsing Rows +///------------------------------------------------ + +- (void)expandRowForItem:(nullable id)item expandChildren:(BOOL)expandChildren withRowAnimation:(RATreeViewRowAnimation)animation; +- (void)expandRowForItem:(nullable id)item withRowAnimation:(RATreeViewRowAnimation)animation; +- (void)expandRowForItem:(nullable id)item; +- (void)collapseRowForItem:(nullable id)item collapseChildren:(BOOL)collapseChildren withRowAnimation:(RATreeViewRowAnimation)animation; +- (void)collapseRowForItem:(nullable id)item withRowAnimation:(RATreeViewRowAnimation)animation; +- (void)collapseRowForItem:(nullable id)item; +@property (nonatomic) BOOL expandsChildRowsWhenRowExpands; +@property (nonatomic) BOOL collapsesChildRowsWhenRowCollapses; +@property (nonatomic) RATreeViewRowAnimation rowsExpandingAnimation; +@property (nonatomic) RATreeViewRowAnimation rowsCollapsingAnimation; + + +///------------------------------------------------ +/// @name Inserting, Deleting, and Moving Rows +///------------------------------------------------ + +- (void)beginUpdates; +- (void)endUpdates; +- (void)insertItemsAtIndexes:(NSIndexSet *)indexes inParent:(nullable id)parent withAnimation:(RATreeViewRowAnimation)animation; +- (void)moveItemAtIndex:(NSInteger)oldIndex inParent:(nullable id)oldParent toIndex:(NSInteger)newIndex inParent:(nullable id)newParent; +- (void)deleteItemsAtIndexes:(NSIndexSet *)indexes inParent:(nullable id)parent withAnimation:(RATreeViewRowAnimation)animation; + + +///------------------------------------------------ +/// @name Creating Tree View Cells +///------------------------------------------------ + +- (void)registerClass:(nullable Class)cellClass forCellReuseIdentifier:(NSString *)identifier NS_AVAILABLE_IOS(6_0); +- (void)registerNib:(nullable UINib *)nib forCellReuseIdentifier:(NSString *)identifier; +- (nullable id)dequeueReusableCellWithIdentifier:(NSString *)identifier; + + +///------------------------------------------------ +/// @name Accessing Header and Footer Views +///------------------------------------------------ + +- (void)registerNib:(UINib *)nib forHeaderFooterViewReuseIdentifier:(NSString *)identifier NS_AVAILABLE_IOS(6_0); +- (void)registerClass:(Class)aClass forHeaderFooterViewReuseIdentifier:(NSString *)identifier NS_AVAILABLE_IOS(6_0); +- (id)dequeueReusableHeaderFooterViewWithIdentifier:(NSString *)identifier NS_AVAILABLE_IOS(6_0); +@property (nonatomic, nullable, strong) UIView *treeHeaderView; +@property (nonatomic, nullable, strong) UIView *treeFooterView; + + +///------------------------------------------------ +/// @name Working with Expandability +///------------------------------------------------ + +- (BOOL)isCellForItemExpanded:(id)item; +- (BOOL)isCellExpanded:(UITableViewCell *)cell; + + +///------------------------------------------------ +/// @name Working with Indentation +///------------------------------------------------ + +- (NSInteger)levelForCellForItem:(id)item; +- (NSInteger)levelForCell:(UITableViewCell *)cell; + + +///------------------------------------------------ +/// @name Getting the Parent for an Item +///------------------------------------------------ + +- (nullable id)parentForItem:(id)parent; + + +///------------------------------------------------ +/// @name Accessing Cells +///------------------------------------------------ + +- (nullable UITableViewCell *)cellForItem:(id)item; +- (nullable NSArray *)visibleCells; +- (nullable id)itemForCell:(UITableViewCell *)cell; +- (nullable id)itemForRowAtPoint:(CGPoint)point; +- (nullable id)itemsForRowsInRect:(CGRect)rect; +@property (nonatomic, nullable, copy, readonly) NSArray *itemsForVisibleRows; + + +///------------------------------------------------ +/// @name Scrolling the TreeView +///------------------------------------------------ + +- (void)scrollToRowForItem:(id)item atScrollPosition:(RATreeViewScrollPosition)scrollPosition animated:(BOOL)animated; +- (void)scrollToNearestSelectedRowAtScrollPosition:(RATreeViewScrollPosition)scrollPosition animated:(BOOL)animated; + + +///------------------------------------------------ +/// @name Managing Selections +///------------------------------------------------ + +- (nullable id)itemForSelectedRow; +- (nullable NSArray *)itemsForSelectedRows; +- (void)selectRowForItem:(nullable id)item animated:(BOOL)animated scrollPosition:(RATreeViewScrollPosition)scrollPosition; +- (void)deselectRowForItem:(id)item animated:(BOOL)animated; +@property (nonatomic) BOOL allowsSelection; +@property (nonatomic) BOOL allowsMultipleSelection; +@property (nonatomic) BOOL allowsSelectionDuringEditing; +@property (nonatomic) BOOL allowsMultipleSelectionDuringEditing; + + +///------------------------------------------------ +/// @name Managing the Editing of Tree Cells +///------------------------------------------------ + +- (void)setEditing:(BOOL)editing animated:(BOOL)animated; +@property (nonatomic, getter = isEditing) BOOL editing; + + +///------------------------------------------------ +/// @name Reloading the Tree View +///------------------------------------------------ + +- (void)reloadData; +- (void)reloadRowsForItems:(NSArray *)items withRowAnimation:(RATreeViewRowAnimation)animation; +- (void)reloadRows; + + +///------------------------------------------------ +/// UIScrollView Staff +///------------------------------------------------ + +@property (nonatomic, strong, readonly) UIScrollView *scrollView; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/RATreeView.m b/Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/RATreeView.m new file mode 100644 index 0000000..58b2497 --- /dev/null +++ b/Examples/TreeView/Pods/RATreeView/RATreeView/RATreeView/RATreeView.m @@ -0,0 +1,619 @@ + +//The MIT License (MIT) +// +//Copyright (c) 2014 Rafał Augustyniak +// +//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: +// +//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. +// + + +#import "RATreeView.h" +#import "RATreeView_ClassExtension.h" +#import "RATreeView+Enums.h" +#import "RATreeView+Private.h" + +#import "RABatchChanges.h" + +#import "RATreeNodeCollectionController.h" +#import "RATreeNode.h" + +#import "RATableView.h" + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wincomplete-implementation" +@implementation RATreeView +#pragma clang diagnostic pop + + +#pragma mark Initializing a TreeView Object + +- (id)init +{ + return [self initWithFrame:CGRectMake(0, 0, 100, 100) style:RATreeViewStylePlain]; +} + +- (id)initWithFrame:(CGRect)frame +{ + return [self initWithFrame:frame style:RATreeViewStylePlain]; +} + +- (id)initWithFrame:(CGRect)frame style:(RATreeViewStyle)style +{ + self = [super initWithFrame:frame]; + if (self) { + CGRect innerFrame = CGRectMake(0, 0, CGRectGetWidth(self.bounds), CGRectGetHeight(self.bounds)); + [self commonInitWithFrame:innerFrame style:style]; + } + return self; +} + +- (id)initWithCoder:(NSCoder *)aDecoder +{ + self = [super initWithCoder:aDecoder]; + if (self) { + CGRect innerFrame = CGRectMake(0, 0, CGRectGetWidth(self.bounds), CGRectGetHeight(self.bounds)); + [self commonInitWithFrame:innerFrame style:RATreeViewStylePlain]; + } + return self; +} + +- (void)commonInitWithFrame:(CGRect)frame style:(RATreeViewStyle)style +{ + UITableViewStyle tableViewStyle = [RATreeView tableViewStyleForTreeViewStyle:style]; + + RATableView *tableView = [[RATableView alloc] initWithFrame:frame style:tableViewStyle]; + tableView.tableViewDelegate = (id)self; + tableView.dataSource = (id)self; + tableView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; + tableView.backgroundColor = [UIColor clearColor]; + + [self addSubview:tableView]; + [self setTableView:tableView]; + + self.expandsChildRowsWhenRowExpands = NO; + self.collapsesChildRowsWhenRowCollapses = NO; + self.rowsExpandingAnimation = RATreeViewRowAnimationTop; + self.rowsCollapsingAnimation = RATreeViewRowAnimationBottom; +} + +- (void)awakeFromNib +{ + [super awakeFromNib]; + + self.tableView.backgroundColor = [UIColor clearColor]; +} + +#pragma mark Scroll View + +- (UIScrollView *)scrollView +{ + return self.tableView; +} + + +#pragma mark Configuring a Tree View + +- (NSInteger)numberOfRows +{ + return [self.tableView numberOfRowsInSection:0]; +} + +- (RATreeViewStyle)style +{ + UITableViewStyle tableViewStyle = self.tableView.style; + return [RATreeView treeViewStyleForTableViewStyle:tableViewStyle]; +} + +#if TARGET_OS_IOS + +- (RATreeViewCellSeparatorStyle)separatorStyle +{ + RATreeViewCellSeparatorStyle style = [RATreeView treeViewCellSeparatorStyleForTableViewSeparatorStyle:self.tableView.separatorStyle]; + return style; +} + +- (void)setSeparatorStyle:(RATreeViewCellSeparatorStyle)separatorStyle +{ + UITableViewCellSeparatorStyle tableViewSeparatorStyle = [RATreeView tableViewCellSeparatorStyleForTreeViewCellSeparatorStyle:separatorStyle]; + self.tableView.separatorStyle = tableViewSeparatorStyle; +} + +- (UIColor *)separatorColor +{ + return self.tableView.separatorColor; +} + +- (void)setSeparatorColor:(UIColor *)separatorColor +{ + self.tableView.separatorColor = separatorColor; +} + +#endif + +- (CGFloat)rowHeight +{ + return self.tableView.rowHeight; +} + +- (void)setRowHeight:(CGFloat)rowHeight +{ + self.tableView.rowHeight = rowHeight; +} + +- (CGFloat)estimatedRowHeight +{ + if ([self.tableView respondsToSelector:@selector(estimatedRowHeight)]) { + return self.tableView.estimatedRowHeight; + } else { + return 0; + } +} + +- (void)setEstimatedRowHeight:(CGFloat)estimatedRowHeight +{ + if ([self.tableView respondsToSelector:@selector(estimatedRowHeight)]) { + self.tableView.estimatedRowHeight = estimatedRowHeight; + } +} + +- (UIEdgeInsets)separatorInset +{ + if ([self.tableView respondsToSelector:@selector(separatorInset)]) { + return self.tableView.separatorInset; + } else { + return UIEdgeInsetsZero; + } +} + +- (void)setSeparatorInset:(UIEdgeInsets)separatorInset +{ + if ([self.tableView respondsToSelector:@selector(separatorInset)]) { + self.tableView.separatorInset = separatorInset; + } +} + +#if TARGET_OS_IOS + +- (UIVisualEffect *)separatorEffect +{ + if ([self.tableView respondsToSelector:@selector(separatorEffect)]) { + return self.tableView.separatorEffect; + } else { + return nil; + } +} + +- (void)setSeparatorEffect:(UIVisualEffect *)separatorEffect +{ + if ([self.tableView respondsToSelector:@selector(separatorEffect)]) { + self.tableView.separatorEffect = separatorEffect; + } +} + +#endif + +- (BOOL)cellLayoutMarginsFollowReadableWidth +{ + if ([self.tableView respondsToSelector:@selector(cellLayoutMarginsFollowReadableWidth)]) { + return self.tableView.cellLayoutMarginsFollowReadableWidth; + } else { + return NO; + } +} + +- (void)setCellLayoutMarginsFollowReadableWidth:(BOOL)cellLayoutMarginsFollowReadableWidth +{ + if ([self.tableView respondsToSelector:@selector(cellLayoutMarginsFollowReadableWidth)]) { + self.tableView.cellLayoutMarginsFollowReadableWidth = cellLayoutMarginsFollowReadableWidth; + } +} + +- (UIView *)backgroundView +{ + return self.tableView.backgroundView; +} + +- (void)setBackgroundView:(UIView *)backgroundView +{ + self.tableView.backgroundView = backgroundView; +} + + +#pragma mark Expanding and Collapsing Rows + +- (void)expandRowForItem:(id)item +{ + [self expandRowForItem:item withRowAnimation:self.rowsExpandingAnimation]; +} + +- (void)expandRowForItem:(id)item withRowAnimation:(RATreeViewRowAnimation)animation +{ + [self expandRowForItem:item expandChildren:NO withRowAnimation:animation]; +} + +- (void)expandRowForItem:(id)item expandChildren:(BOOL)expandChildren withRowAnimation:(RATreeViewRowAnimation)animation +{ + NSIndexPath *indexPath = [self indexPathForItem:item]; + RATreeNode *treeNode = [self treeNodeForIndexPath:indexPath]; + if (!treeNode || treeNode.expanded) { + return; + } + [self expandCellForTreeNode:treeNode expandChildren:expandChildren withRowAnimation:animation]; +} + +- (void)collapseRowForItem:(id)item +{ + [self collapseRowForItem:item withRowAnimation:self.rowsCollapsingAnimation]; +} + +- (void)collapseRowForItem:(id)item withRowAnimation:(RATreeViewRowAnimation)animation +{ + [self collapseRowForItem:item collapseChildren:NO withRowAnimation:animation]; +} + +- (void)collapseRowForItem:(id)item collapseChildren:(BOOL)collapseChildren withRowAnimation:(RATreeViewRowAnimation)animation +{ + NSIndexPath *indexPath = [self indexPathForItem:item]; + RATreeNode *treeNode = [self treeNodeForIndexPath:indexPath]; + if (!treeNode) { + return; + } + [self collapseCellForTreeNode:treeNode collapseChildren:collapseChildren withRowAnimation:animation]; +} + + +#pragma mark - Changing tree's structure + +- (void)beginUpdates +{ + [self.tableView beginUpdates]; + [self.batchChanges beginUpdates]; +} + +- (void)endUpdates +{ + [self.batchChanges endUpdates]; + [self.tableView endUpdates]; +} + +- (void)insertItemsAtIndexes:(NSIndexSet *)indexes inParent:(id)parent withAnimation:(RATreeViewRowAnimation)animation +{ + if (parent && ![self isCellForItemExpanded:parent]) { + return; + } + __weak __typeof(self) weakSelf = self; + [indexes enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL *stop) { + [weakSelf insertItemAtIndex:idx inParent:parent withAnimation:animation]; + }]; +} + +- (void)deleteItemsAtIndexes:(NSIndexSet *)indexes inParent:(id)parent withAnimation:(RATreeViewRowAnimation)animation +{ + if (parent && ![self isCellForItemExpanded:parent]) { + return; + } + __weak __typeof(self) weakSelf = self; + [indexes enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL *stop) { + [weakSelf removeItemAtIndex:idx inParent:parent withAnimation:animation]; + }]; +} + + +#pragma mark - Creating Table View Cells + +- (void)registerNib:(UINib *)nib forCellReuseIdentifier:(NSString *)identifier +{ + [self.tableView registerNib:nib forCellReuseIdentifier:identifier]; +} + +- (void)registerClass:(Class)cellClass forCellReuseIdentifier:(NSString *)identifier +{ + [self.tableView registerClass:cellClass forCellReuseIdentifier:identifier]; +} + +- (id)dequeueReusableCellWithIdentifier:(NSString *)identifier +{ + return [self.tableView dequeueReusableCellWithIdentifier:identifier]; +} + + +#pragma mark - Accessing Header and Footer Views + +- (void)registerNib:(UINib *)nib forHeaderFooterViewReuseIdentifier:(NSString *)identifier +{ + [self.tableView registerNib:nib forHeaderFooterViewReuseIdentifier:identifier]; +} + +- (void)registerClass:(Class)aClass forHeaderFooterViewReuseIdentifier:(NSString *)identifier +{ + [self.tableView registerClass:aClass forHeaderFooterViewReuseIdentifier:identifier]; +} + +- (id)dequeueReusableHeaderFooterViewWithIdentifier:(NSString *)identifier +{ + return [self.tableView dequeueReusableHeaderFooterViewWithIdentifier:identifier]; +} + +- (UIView *)treeHeaderView +{ + return self.tableView.tableHeaderView; +} + +- (void)setTreeHeaderView:(UIView *)treeHeaderView +{ + self.tableView.tableHeaderView = treeHeaderView; +} + +- (UIView *)treeFooterView +{ + return self.tableView.tableFooterView; +} + +- (void)setTreeFooterView:(UIView *)treeFooterView +{ + self.tableView.tableFooterView = treeFooterView; +} + + +#pragma mark - Working with Expandability + +- (BOOL)isCellForItemExpanded:(id)item +{ + NSIndexPath *indexPath = [self indexPathForItem:item]; + return [self treeNodeForIndexPath:indexPath].expanded; +} + +- (BOOL)isCellExpanded:(UITableViewCell *)cell +{ + id item = [self itemForCell:cell]; + return [self isCellForItemExpanded:item]; +} + +#pragma mark - Working with Indentation + +- (NSInteger)levelForCellForItem:(id)item +{ + return [self.treeNodeCollectionController levelForItem:item]; +} + +- (NSInteger)levelForCell:(UITableViewCell *)cell +{ + id item = [self itemForCell:cell]; + return [self levelForCellForItem:item]; +} + +#pragma mark - Getting the Parent for an Item + +- (id)parentForItem:(id)item +{ + return [self.treeNodeCollectionController parentForItem:item]; +} + + +#pragma mark - Accessing Cells + +- (UITableViewCell *)cellForItem:(id)item +{ + NSIndexPath *indexPath = [self indexPathForItem:item]; + return [self.tableView cellForRowAtIndexPath:indexPath]; +} + +- (NSArray *)visibleCells +{ + return [self.tableView visibleCells]; +} + +- (id)itemForCell:(UITableViewCell *)cell +{ + NSIndexPath *indexPath = [self.tableView indexPathForCell:cell]; + return [self treeNodeForIndexPath:indexPath].item; +} + +- (id)itemForRowAtPoint:(CGPoint)point +{ + NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:point]; + return !indexPath ? nil : [self treeNodeForIndexPath:indexPath].item; +} + +- (id)itemsForRowsInRect:(CGRect)rect +{ + NSArray *indexPaths = [self.tableView indexPathsForRowsInRect:rect]; + return [self itemsForIndexPaths:indexPaths]; +} + +- (NSArray *)itemsForVisibleRows +{ + NSArray *indexPaths = [self.tableView indexPathsForVisibleRows]; + return [self itemsForIndexPaths:indexPaths]; +} + + +#pragma mark - Scrolling the TreeView + +- (void)scrollToRowForItem:(id)item atScrollPosition:(RATreeViewScrollPosition)scrollPosition animated:(BOOL)animated +{ + NSIndexPath *indexPath = [self indexPathForItem:item]; + UITableViewScrollPosition tableViewScrollPosition = [RATreeView tableViewScrollPositionForTreeViewScrollPosition:scrollPosition]; + [self.tableView scrollToRowAtIndexPath:indexPath atScrollPosition:tableViewScrollPosition animated:animated]; +} + +- (void)scrollToNearestSelectedRowAtScrollPosition:(RATreeViewScrollPosition)scrollPosition animated:(BOOL)animated +{ + UITableViewScrollPosition tableViewScrollPosition = [RATreeView tableViewScrollPositionForTreeViewScrollPosition:scrollPosition]; + [self.tableView scrollToNearestSelectedRowAtScrollPosition:tableViewScrollPosition animated:animated]; +} + + +#pragma mark - Managing Selections + +- (id)itemForSelectedRow +{ + NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow]; + return [self treeNodeForIndexPath:indexPath].item; +} + +- (NSArray *)itemsForSelectedRows +{ + NSArray *selectedRows = [self.tableView indexPathsForSelectedRows]; + return [self itemsForIndexPaths:selectedRows]; +} + +- (void)selectRowForItem:(id)item animated:(BOOL)animated scrollPosition:(RATreeViewScrollPosition)scrollPosition +{ + if ([self isCellForItemExpanded:[self parentForItem:item]]) { + NSIndexPath *indexPath = [self indexPathForItem:item]; + UITableViewScrollPosition tableViewScrollPosition = [RATreeView tableViewScrollPositionForTreeViewScrollPosition:scrollPosition]; + [self.tableView selectRowAtIndexPath:indexPath animated:animated scrollPosition:tableViewScrollPosition]; + } +} + +- (void)deselectRowForItem:(id)item animated:(BOOL)animated +{ + if ([self isCellForItemExpanded:[self parentForItem:item]]) { + NSIndexPath *indexPath = [self indexPathForItem:item]; + [self.tableView deselectRowAtIndexPath:indexPath animated:animated]; + } +} + +- (BOOL)allowsSelection +{ + return self.tableView.allowsSelection; +} + +- (void)setAllowsSelection:(BOOL)allowsSelection +{ + self.tableView.allowsSelection = allowsSelection; +} + +- (BOOL)allowsMultipleSelection +{ + return self.tableView.allowsMultipleSelection; +} + +- (void)setAllowsMultipleSelection:(BOOL)allowsMultipleSelection +{ + self.tableView.allowsMultipleSelection = allowsMultipleSelection; +} + +- (BOOL)allowsSelectionDuringEditing +{ + return self.tableView.allowsSelectionDuringEditing; +} + +- (void)setAllowsSelectionDuringEditing:(BOOL)allowsSelectionDuringEditing +{ + self.tableView.allowsSelectionDuringEditing = allowsSelectionDuringEditing; +} + +- (BOOL)allowsMultipleSelectionDuringEditing +{ + return self.tableView.allowsMultipleSelectionDuringEditing; +} + +- (void)setAllowsMultipleSelectionDuringEditing:(BOOL)allowsMultipleSelectionDuringEditing +{ + self.tableView.allowsMultipleSelectionDuringEditing = allowsMultipleSelectionDuringEditing; +} + + +#pragma mark - Managing the Editing of Tree Cells + +- (BOOL)isEditing +{ + return self.tableView.isEditing; +} + +- (void)setEditing:(BOOL)editing +{ + self.tableView.editing = editing; +} + +- (void)setEditing:(BOOL)editing animated:(BOOL)animated +{ + [self.tableView setEditing:editing animated:animated]; +} + + +#pragma mark - Reloading the Tree View + +- (void)reloadData +{ + [self setupTreeStructure]; + [self.tableView reloadData]; +} + +- (void)reloadRowsForItems:(NSArray *)items withRowAnimation:(RATreeViewRowAnimation)animation +{ + NSMutableArray *indexes = [NSMutableArray array]; + UITableViewRowAnimation tableViewRowAnimation = [RATreeView tableViewRowAnimationForTreeViewRowAnimation:animation]; + for (id item in items) { + NSIndexPath *indexPath = [self indexPathForItem:item]; + [indexes addObject:indexPath]; + } + + [self.tableView reloadRowsAtIndexPaths:indexes withRowAnimation:tableViewRowAnimation]; +} + +- (void)reloadRows +{ + NSIndexSet *indexSet = [NSIndexSet indexSetWithIndex:0]; + [self.tableView reloadSections:indexSet withRowAnimation:UITableViewRowAnimationNone]; +} + + +#pragma mark - UIScrollView's properties + +- (void)setContentOffset:(CGPoint)contentOffset animated:(BOOL)animated +{ + [self.tableView setContentOffset:contentOffset animated:animated]; +} + +- (void)scrollRectToVisible:(CGRect)visible animated:(BOOL)animated +{ + [self.tableView scrollRectToVisible:visible animated:animated]; +} + +- (void)setZoomScale:(CGFloat)zoomScale animated:(BOOL)animated +{ + [self.tableView setZoomScale:zoomScale animated:animated]; +} + +- (void)flashScrollIndicators +{ + [self.tableView flashScrollIndicators]; +} + +- (void)zoomToRect:(CGRect)rect animated:(BOOL)animated +{ + [self.tableView zoomToRect:rect animated:animated]; +} + + +#pragma mark - + +- (NSArray *)itemsForIndexPaths:(NSArray *)indexPaths +{ + if (!indexPaths) { + return nil; + } + NSMutableArray *items = [NSMutableArray array]; + for (NSIndexPath *indexPath in indexPaths) { + [items addObject:[self treeNodeForIndexPath:indexPath].item]; + } + + return [items copy]; +} + +@end diff --git a/Examples/TreeView/Pods/RATreeView/README.md b/Examples/TreeView/Pods/RATreeView/README.md new file mode 100644 index 0000000..cb03673 --- /dev/null +++ b/Examples/TreeView/Pods/RATreeView/README.md @@ -0,0 +1,190 @@ +RATreeView (iOS 7.0+, tvOS 9.0+) +============== + +👷 Project created and maintained by [Rafał Augustyniak](http://augustyniak.me). You can find me on twitter ([@RaAugustyniak](https://twitter.com/RaAugustyniak)). + + +Introduction +----------------- + +[![Twitter: @raaugustyniak](https://img.shields.io/badge/contact-@raaugustyniak-blue.svg?style=flat)](https://twitter.com/raaugustyniak) +[![Build Status](https://img.shields.io/travis/Augustyniak/RATreeView/master.svg?style=flat)](https://travis-ci.org/Augustyniak/RATreeView) +[![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) +[![CocoaPods](https://img.shields.io/cocoapods/v/RATreeView.svg?style=flat)](https://github.com/Augustyniak/RATreeView) +[![Platform](https://img.shields.io/cocoapods/p/RATreeView.svg?style=flat)](http://cocoadocs.org/docsets/RATreeView) +[![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg?style=flat)](https://github.com/Augustyniak/RATreeView/blob/master/LICENCE.md) + +iOS | tvOS +:-------------------------:|:-------------------------: +[![](https://raw.github.com/Augustyniak/RATreeView/master/Screens/animation.gif)](https://raw.github.com/Augustyniak/RATreeView/master/Screens/animation.gif) | [![](https://raw.github.com/Augustyniak/RATreeView/master/Screens/tvos_animation.gif)](https://raw.github.com/Augustyniak/RATreeView/master/Screens/tvos_animation.gif) + + + + + +RATreeView is a class designed to provide easy and pleasant way to work with tree views on iOS and tvOS. It works as a wrapper for the UITableView, defining its own delegate and data source methods which make working with tree data structures really easy. + +RATreeView is highly customizable and has a lot of features. + + +Installation +----------------- + +### CocoaPods + +[CocoaPods](http://www.cocoapods.org) is the recommended way to add RATreeView to your project. + +1. Add additional entry to your Podfile. + + ```ruby + pod "RATreeView", "~> 2.1.2" + ``` + +2. Install Pod(s) running `pod install` command. +3. Include RATreeView using `#import `. + +###Source files + +1. Downloaded the latest version of the library using [link](https://github.com/Augustyniak/RATreeView/archive/master.zip). +2. Copy content of the downloaded (and unzipped) zip file into your project by dragging it into Project's navigator files structure. + + + +Requirements +----------------- + + +* Xcode 5 +* iOS 7 or newer/tvOS 9 or newer + + +Usage +----------------- + + +Check out the demo for example usage of library. Make sure you read the [RATreeView documentation on Cocoa Docs](http://cocoadocs.org/docsets/RATreeView/2.1.2). + + +### Basics + +1. Add following import in file of your project when you want to use RATreeView: + + ```objc + // In case you are using RATreeView with CocoaPods + #import + ``` + + ```objc + // In case you are using RATreeView by simply copying + // source files of the RATreeView into your project + #import "RATreeView.h" + ``` + +2. Simplest way to initialize and configure RATreeView: + + ```objc + RATreeView *treeView = [[RATreeView alloc] initWithFrame:self.view.bounds]; + treeView.delegate = self; + treeView.dataSource = self; + [self.view addSubview:treeView]; + [treeView reloadData]; + ``` + +3. Implement required methods of the RATreeView's data source: + + ```objc + - (NSInteger)treeView:(RATreeView *)treeView numberOfChildrenOfItem:(id)item + { + return item ? 3 : 0; + } + ``` + + ```objc + - (UITableViewCell *)treeView:(RATreeView *)treeView cellForItem:(id)item treeNodeInfo:(RATreeNodeInfo *)treeNodeInfo + { + // create and configure cell for *item* + return cell + } + ``` + + ```objc + - (id)treeView:(RATreeView *)treeView child:(NSInteger)index ofItem:(id)item + { + return @(index); + } + ``` + +###Adding Pull to Refresh control + +Adding pull to refresh gesture is really easy using `RATreeView` and standard `UIRefreshControl` control. + +[![](https://raw.github.com/Augustyniak/RATreeView/master/Screens/PullToRefresh.png)](https://raw.github.com/Augustyniak/RATreeView/master/Screens/PullToRefresh.png) + + ```objc +UIRefreshControl *refreshControl = [UIRefreshControl new]; +[refreshControl addTarget:self action:@selector(refreshControlChanged:) forControlEvents:UIControlEventValueChanged]; +[treeView.scrollView addSubview:refreshControl]; + ``` + +Documentation +----------------- + +Documentation is available on [CocoaPods](http://cocoadocs.org/docsets/RATreeView/2.1.2). + +TODO +----------------- + +- Better delegate callbacks in case of recursive collapse and expand operations. +- Improved documentation. +- Unit tests. +- Re-order rows feature. + +Author +----------------- + +RATreeView was created by Rafał Augustyniak. You can find me on twitter ([@RaAugustyniak](https://twitter.com/RaAugustyniak)). + + +Release Notes +----------------- + +Information about newer versions of the library can be found in the [releases section](https://github.com/Augustyniak/RATreeView/releases) of the repository. + +Version 1.0.2 +- Fixed bug in select and deselect operations. +- Fixed bug in recursive expand operation (via @Arrnas). + +Version 1.0.1 +- Fixed bug in recursive expand operation. + +Version 1.0.0 + +- Improved performance. +- Added recursive expand operation. It can be performed by using `expandRowForItem: expandChildren:withRowAnimation:` method. Default behavior is non recursive expand. +- Added recursive collapse operation. It can be performed by using `collapseRowForItem: expandChildren:withRowAnimation:` method. Default behavior is non recursive collapse. +- Fixed bug in `itemForRowAtPoint:` method when passed point isn't inside any cell. + +Version 0.9.2 + +- Fixed bug in `endUpdates` method. + +Version 0.9.1 + +- Fixed behaviour of treeView:willSelectRowForItem: delegate method. + +Version 0.9.0 + +- Added possiblity to change content of the RATreeView dynamically. Possible row operations: + - additions + - deletions + - repositions +- Added additional 'cell accessing' methods. +- Removed `RATreeNodeInfo` class. +- Added additional instance methods in RATreeView which substitute functionality provided by `RATreeNodeInfo` class. +- Bug fixes. + +License +----------------- + +MIT licensed, Copyright (c) 2014 Rafał Augustyniak, [@RaAugustyniak](http://twitter.com/RaAugustyniak) + diff --git a/Examples/TreeView/Pods/Target Support Files/Pods-TreeView/Pods-TreeView-Info.plist b/Examples/TreeView/Pods/Target Support Files/Pods-TreeView/Pods-TreeView-Info.plist new file mode 100644 index 0000000..19cf209 --- /dev/null +++ b/Examples/TreeView/Pods/Target Support Files/Pods-TreeView/Pods-TreeView-Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + ${PODS_DEVELOPMENT_LANGUAGE} + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0.0 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/Examples/TreeView/Pods/Target Support Files/Pods-TreeView/Pods-TreeView-acknowledgements.markdown b/Examples/TreeView/Pods/Target Support Files/Pods-TreeView/Pods-TreeView-acknowledgements.markdown new file mode 100644 index 0000000..1ec0963 --- /dev/null +++ b/Examples/TreeView/Pods/Target Support Files/Pods-TreeView/Pods-TreeView-acknowledgements.markdown @@ -0,0 +1,26 @@ +# Acknowledgements +This application makes use of the following third party libraries: + +## RATreeView + +The MIT License (MIT) + +Copyright (c) 2013 Rafał Augustyniak + +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: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +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. +Generated by CocoaPods - https://cocoapods.org diff --git a/Examples/TreeView/Pods/Target Support Files/Pods-TreeView/Pods-TreeView-acknowledgements.plist b/Examples/TreeView/Pods/Target Support Files/Pods-TreeView/Pods-TreeView-acknowledgements.plist new file mode 100644 index 0000000..497b3db --- /dev/null +++ b/Examples/TreeView/Pods/Target Support Files/Pods-TreeView/Pods-TreeView-acknowledgements.plist @@ -0,0 +1,58 @@ + + + + + PreferenceSpecifiers + + + FooterText + This application makes use of the following third party libraries: + Title + Acknowledgements + Type + PSGroupSpecifier + + + FooterText + The MIT License (MIT) + +Copyright (c) 2013 Rafał Augustyniak + +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: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +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. + License + MIT + Title + RATreeView + Type + PSGroupSpecifier + + + FooterText + Generated by CocoaPods - https://cocoapods.org + Title + + Type + PSGroupSpecifier + + + StringsTable + Acknowledgements + Title + Acknowledgements + + diff --git a/Examples/TreeView/Pods/Target Support Files/Pods-TreeView/Pods-TreeView-dummy.m b/Examples/TreeView/Pods/Target Support Files/Pods-TreeView/Pods-TreeView-dummy.m new file mode 100644 index 0000000..ee8ba0e --- /dev/null +++ b/Examples/TreeView/Pods/Target Support Files/Pods-TreeView/Pods-TreeView-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_Pods_TreeView : NSObject +@end +@implementation PodsDummy_Pods_TreeView +@end diff --git a/Examples/TreeView/Pods/Target Support Files/Pods-TreeView/Pods-TreeView-frameworks-Debug-input-files.xcfilelist b/Examples/TreeView/Pods/Target Support Files/Pods-TreeView/Pods-TreeView-frameworks-Debug-input-files.xcfilelist new file mode 100644 index 0000000..c6f4d71 --- /dev/null +++ b/Examples/TreeView/Pods/Target Support Files/Pods-TreeView/Pods-TreeView-frameworks-Debug-input-files.xcfilelist @@ -0,0 +1,2 @@ +${PODS_ROOT}/Target Support Files/Pods-TreeView/Pods-TreeView-frameworks.sh +${BUILT_PRODUCTS_DIR}/RATreeView/RATreeView.framework \ No newline at end of file diff --git a/Examples/TreeView/Pods/Target Support Files/Pods-TreeView/Pods-TreeView-frameworks-Debug-output-files.xcfilelist b/Examples/TreeView/Pods/Target Support Files/Pods-TreeView/Pods-TreeView-frameworks-Debug-output-files.xcfilelist new file mode 100644 index 0000000..69c8f88 --- /dev/null +++ b/Examples/TreeView/Pods/Target Support Files/Pods-TreeView/Pods-TreeView-frameworks-Debug-output-files.xcfilelist @@ -0,0 +1 @@ +${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RATreeView.framework \ No newline at end of file diff --git a/Examples/TreeView/Pods/Target Support Files/Pods-TreeView/Pods-TreeView-frameworks-Release-input-files.xcfilelist b/Examples/TreeView/Pods/Target Support Files/Pods-TreeView/Pods-TreeView-frameworks-Release-input-files.xcfilelist new file mode 100644 index 0000000..c6f4d71 --- /dev/null +++ b/Examples/TreeView/Pods/Target Support Files/Pods-TreeView/Pods-TreeView-frameworks-Release-input-files.xcfilelist @@ -0,0 +1,2 @@ +${PODS_ROOT}/Target Support Files/Pods-TreeView/Pods-TreeView-frameworks.sh +${BUILT_PRODUCTS_DIR}/RATreeView/RATreeView.framework \ No newline at end of file diff --git a/Examples/TreeView/Pods/Target Support Files/Pods-TreeView/Pods-TreeView-frameworks-Release-output-files.xcfilelist b/Examples/TreeView/Pods/Target Support Files/Pods-TreeView/Pods-TreeView-frameworks-Release-output-files.xcfilelist new file mode 100644 index 0000000..69c8f88 --- /dev/null +++ b/Examples/TreeView/Pods/Target Support Files/Pods-TreeView/Pods-TreeView-frameworks-Release-output-files.xcfilelist @@ -0,0 +1 @@ +${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RATreeView.framework \ No newline at end of file diff --git a/Examples/TreeView/Pods/Target Support Files/Pods-TreeView/Pods-TreeView-frameworks.sh b/Examples/TreeView/Pods/Target Support Files/Pods-TreeView/Pods-TreeView-frameworks.sh new file mode 100755 index 0000000..2dfe848 --- /dev/null +++ b/Examples/TreeView/Pods/Target Support Files/Pods-TreeView/Pods-TreeView-frameworks.sh @@ -0,0 +1,186 @@ +#!/bin/sh +set -e +set -u +set -o pipefail + +function on_error { + echo "$(realpath -mq "${0}"):$1: error: Unexpected failure" +} +trap 'on_error $LINENO' ERR + +if [ -z ${FRAMEWORKS_FOLDER_PATH+x} ]; then + # If FRAMEWORKS_FOLDER_PATH is not set, then there's nowhere for us to copy + # frameworks to, so exit 0 (signalling the script phase was successful). + exit 0 +fi + +echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" +mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" + +COCOAPODS_PARALLEL_CODE_SIGN="${COCOAPODS_PARALLEL_CODE_SIGN:-false}" +SWIFT_STDLIB_PATH="${TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" +BCSYMBOLMAP_DIR="BCSymbolMaps" + + +# This protects against multiple targets copying the same framework dependency at the same time. The solution +# was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html +RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????") + +# Copies and strips a vendored framework +install_framework() +{ + if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then + local source="${BUILT_PRODUCTS_DIR}/$1" + elif [ -r "${BUILT_PRODUCTS_DIR}/$(basename "$1")" ]; then + local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")" + elif [ -r "$1" ]; then + local source="$1" + fi + + local destination="${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" + + if [ -L "${source}" ]; then + echo "Symlinked..." + source="$(readlink -f "${source}")" + fi + + if [ -d "${source}/${BCSYMBOLMAP_DIR}" ]; then + # Locate and install any .bcsymbolmaps if present, and remove them from the .framework before the framework is copied + find "${source}/${BCSYMBOLMAP_DIR}" -name "*.bcsymbolmap"|while read f; do + echo "Installing $f" + install_bcsymbolmap "$f" "$destination" + rm "$f" + done + rmdir "${source}/${BCSYMBOLMAP_DIR}" + fi + + # Use filter instead of exclude so missing patterns don't throw errors. + echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --links --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\"" + rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --links --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}" + + local basename + basename="$(basename -s .framework "$1")" + binary="${destination}/${basename}.framework/${basename}" + + if ! [ -r "$binary" ]; then + binary="${destination}/${basename}" + elif [ -L "${binary}" ]; then + echo "Destination binary is symlinked..." + dirname="$(dirname "${binary}")" + binary="${dirname}/$(readlink "${binary}")" + fi + + # Strip invalid architectures so "fat" simulator / device frameworks work on device + if [[ "$(file "$binary")" == *"dynamically linked shared library"* ]]; then + strip_invalid_archs "$binary" + fi + + # Resign the code if required by the build settings to avoid unstable apps + code_sign_if_enabled "${destination}/$(basename "$1")" + + # Embed linked Swift runtime libraries. No longer necessary as of Xcode 7. + if [ "${XCODE_VERSION_MAJOR}" -lt 7 ]; then + local swift_runtime_libs + swift_runtime_libs=$(xcrun otool -LX "$binary" | grep --color=never @rpath/libswift | sed -E s/@rpath\\/\(.+dylib\).*/\\1/g | uniq -u) + for lib in $swift_runtime_libs; do + echo "rsync -auv \"${SWIFT_STDLIB_PATH}/${lib}\" \"${destination}\"" + rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}" + code_sign_if_enabled "${destination}/${lib}" + done + fi +} +# Copies and strips a vendored dSYM +install_dsym() { + local source="$1" + warn_missing_arch=${2:-true} + if [ -r "$source" ]; then + # Copy the dSYM into the targets temp dir. + echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${DERIVED_FILES_DIR}\"" + rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${DERIVED_FILES_DIR}" + + local basename + basename="$(basename -s .dSYM "$source")" + binary_name="$(ls "$source/Contents/Resources/DWARF")" + binary="${DERIVED_FILES_DIR}/${basename}.dSYM/Contents/Resources/DWARF/${binary_name}" + + # Strip invalid architectures from the dSYM. + if [[ "$(file "$binary")" == *"Mach-O "*"dSYM companion"* ]]; then + strip_invalid_archs "$binary" "$warn_missing_arch" + fi + if [[ $STRIP_BINARY_RETVAL == 0 ]]; then + # Move the stripped file into its final destination. + echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --links --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${DERIVED_FILES_DIR}/${basename}.framework.dSYM\" \"${DWARF_DSYM_FOLDER_PATH}\"" + rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --links --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${DERIVED_FILES_DIR}/${basename}.dSYM" "${DWARF_DSYM_FOLDER_PATH}" + else + # The dSYM was not stripped at all, in this case touch a fake folder so the input/output paths from Xcode do not reexecute this script because the file is missing. + mkdir -p "${DWARF_DSYM_FOLDER_PATH}" + touch "${DWARF_DSYM_FOLDER_PATH}/${basename}.dSYM" + fi + fi +} + +# Used as a return value for each invocation of `strip_invalid_archs` function. +STRIP_BINARY_RETVAL=0 + +# Strip invalid architectures +strip_invalid_archs() { + binary="$1" + warn_missing_arch=${2:-true} + # Get architectures for current target binary + binary_archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | awk '{$1=$1;print}' | rev)" + # Intersect them with the architectures we are building for + intersected_archs="$(echo ${ARCHS[@]} ${binary_archs[@]} | tr ' ' '\n' | sort | uniq -d)" + # If there are no archs supported by this binary then warn the user + if [[ -z "$intersected_archs" ]]; then + if [[ "$warn_missing_arch" == "true" ]]; then + echo "warning: [CP] Vendored binary '$binary' contains architectures ($binary_archs) none of which match the current build architectures ($ARCHS)." + fi + STRIP_BINARY_RETVAL=1 + return + fi + stripped="" + for arch in $binary_archs; do + if ! [[ "${ARCHS}" == *"$arch"* ]]; then + # Strip non-valid architectures in-place + lipo -remove "$arch" -output "$binary" "$binary" + stripped="$stripped $arch" + fi + done + if [[ "$stripped" ]]; then + echo "Stripped $binary of architectures:$stripped" + fi + STRIP_BINARY_RETVAL=0 +} + +# Copies the bcsymbolmap files of a vendored framework +install_bcsymbolmap() { + local bcsymbolmap_path="$1" + local destination="${BUILT_PRODUCTS_DIR}" + echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${bcsymbolmap_path}" "${destination}"" + rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${bcsymbolmap_path}" "${destination}" +} + +# Signs a framework with the provided identity +code_sign_if_enabled() { + if [ -n "${EXPANDED_CODE_SIGN_IDENTITY:-}" -a "${CODE_SIGNING_REQUIRED:-}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then + # Use the current code_sign_identity + echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}" + local code_sign_cmd="/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS:-} --preserve-metadata=identifier,entitlements '$1'" + + if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then + code_sign_cmd="$code_sign_cmd &" + fi + echo "$code_sign_cmd" + eval "$code_sign_cmd" + fi +} + +if [[ "$CONFIGURATION" == "Debug" ]]; then + install_framework "${BUILT_PRODUCTS_DIR}/RATreeView/RATreeView.framework" +fi +if [[ "$CONFIGURATION" == "Release" ]]; then + install_framework "${BUILT_PRODUCTS_DIR}/RATreeView/RATreeView.framework" +fi +if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then + wait +fi diff --git a/Examples/TreeView/Pods/Target Support Files/Pods-TreeView/Pods-TreeView-umbrella.h b/Examples/TreeView/Pods/Target Support Files/Pods-TreeView/Pods-TreeView-umbrella.h new file mode 100644 index 0000000..dc24151 --- /dev/null +++ b/Examples/TreeView/Pods/Target Support Files/Pods-TreeView/Pods-TreeView-umbrella.h @@ -0,0 +1,16 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + + +FOUNDATION_EXPORT double Pods_TreeViewVersionNumber; +FOUNDATION_EXPORT const unsigned char Pods_TreeViewVersionString[]; + diff --git a/Examples/TreeView/Pods/Target Support Files/Pods-TreeView/Pods-TreeView.debug.xcconfig b/Examples/TreeView/Pods/Target Support Files/Pods-TreeView/Pods-TreeView.debug.xcconfig new file mode 100644 index 0000000..15aa4e3 --- /dev/null +++ b/Examples/TreeView/Pods/Target Support Files/Pods-TreeView/Pods-TreeView.debug.xcconfig @@ -0,0 +1,12 @@ +CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/RATreeView" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/RATreeView/RATreeView.framework/Headers" +LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' +OTHER_LDFLAGS = $(inherited) -framework "RATreeView" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_PODFILE_DIR_PATH = ${SRCROOT}/. +PODS_ROOT = ${SRCROOT}/Pods +PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/Examples/TreeView/Pods/Target Support Files/Pods-TreeView/Pods-TreeView.modulemap b/Examples/TreeView/Pods/Target Support Files/Pods-TreeView/Pods-TreeView.modulemap new file mode 100644 index 0000000..5f6658c --- /dev/null +++ b/Examples/TreeView/Pods/Target Support Files/Pods-TreeView/Pods-TreeView.modulemap @@ -0,0 +1,6 @@ +framework module Pods_TreeView { + umbrella header "Pods-TreeView-umbrella.h" + + export * + module * { export * } +} diff --git a/Examples/TreeView/Pods/Target Support Files/Pods-TreeView/Pods-TreeView.release.xcconfig b/Examples/TreeView/Pods/Target Support Files/Pods-TreeView/Pods-TreeView.release.xcconfig new file mode 100644 index 0000000..15aa4e3 --- /dev/null +++ b/Examples/TreeView/Pods/Target Support Files/Pods-TreeView/Pods-TreeView.release.xcconfig @@ -0,0 +1,12 @@ +CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/RATreeView" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/RATreeView/RATreeView.framework/Headers" +LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' +OTHER_LDFLAGS = $(inherited) -framework "RATreeView" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_PODFILE_DIR_PATH = ${SRCROOT}/. +PODS_ROOT = ${SRCROOT}/Pods +PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/Examples/TreeView/Pods/Target Support Files/RATreeView/RATreeView-Info.plist b/Examples/TreeView/Pods/Target Support Files/RATreeView/RATreeView-Info.plist new file mode 100644 index 0000000..19ed883 --- /dev/null +++ b/Examples/TreeView/Pods/Target Support Files/RATreeView/RATreeView-Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + ${PODS_DEVELOPMENT_LANGUAGE} + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 2.1.2 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/Examples/TreeView/Pods/Target Support Files/RATreeView/RATreeView-dummy.m b/Examples/TreeView/Pods/Target Support Files/RATreeView/RATreeView-dummy.m new file mode 100644 index 0000000..b0bc09d --- /dev/null +++ b/Examples/TreeView/Pods/Target Support Files/RATreeView/RATreeView-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_RATreeView : NSObject +@end +@implementation PodsDummy_RATreeView +@end diff --git a/Examples/TreeView/Pods/Target Support Files/RATreeView/RATreeView-prefix.pch b/Examples/TreeView/Pods/Target Support Files/RATreeView/RATreeView-prefix.pch new file mode 100644 index 0000000..beb2a24 --- /dev/null +++ b/Examples/TreeView/Pods/Target Support Files/RATreeView/RATreeView-prefix.pch @@ -0,0 +1,12 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + diff --git a/Examples/TreeView/Pods/Target Support Files/RATreeView/RATreeView-umbrella.h b/Examples/TreeView/Pods/Target Support Files/RATreeView/RATreeView-umbrella.h new file mode 100644 index 0000000..e72a976 --- /dev/null +++ b/Examples/TreeView/Pods/Target Support Files/RATreeView/RATreeView-umbrella.h @@ -0,0 +1,17 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + +#import "RATreeView.h" + +FOUNDATION_EXPORT double RATreeViewVersionNumber; +FOUNDATION_EXPORT const unsigned char RATreeViewVersionString[]; + diff --git a/Examples/TreeView/Pods/Target Support Files/RATreeView/RATreeView.debug.xcconfig b/Examples/TreeView/Pods/Target Support Files/RATreeView/RATreeView.debug.xcconfig new file mode 100644 index 0000000..733d160 --- /dev/null +++ b/Examples/TreeView/Pods/Target Support Files/RATreeView/RATreeView.debug.xcconfig @@ -0,0 +1,12 @@ +CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/RATreeView +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_DEVELOPMENT_LANGUAGE = ${DEVELOPMENT_LANGUAGE} +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/RATreeView +PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/Examples/TreeView/Pods/Target Support Files/RATreeView/RATreeView.modulemap b/Examples/TreeView/Pods/Target Support Files/RATreeView/RATreeView.modulemap new file mode 100644 index 0000000..67acd57 --- /dev/null +++ b/Examples/TreeView/Pods/Target Support Files/RATreeView/RATreeView.modulemap @@ -0,0 +1,6 @@ +framework module RATreeView { + umbrella header "RATreeView-umbrella.h" + + export * + module * { export * } +} diff --git a/Examples/TreeView/Pods/Target Support Files/RATreeView/RATreeView.release.xcconfig b/Examples/TreeView/Pods/Target Support Files/RATreeView/RATreeView.release.xcconfig new file mode 100644 index 0000000..733d160 --- /dev/null +++ b/Examples/TreeView/Pods/Target Support Files/RATreeView/RATreeView.release.xcconfig @@ -0,0 +1,12 @@ +CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/RATreeView +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_DEVELOPMENT_LANGUAGE = ${DEVELOPMENT_LANGUAGE} +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/RATreeView +PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/Examples/TreeView/TreeView.xcodeproj/project.pbxproj b/Examples/TreeView/TreeView.xcodeproj/project.pbxproj index 17cf639..8753315 100644 --- a/Examples/TreeView/TreeView.xcodeproj/project.pbxproj +++ b/Examples/TreeView/TreeView.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 52; + objectVersion = 54; objects = { /* Begin PBXBuildFile section */ @@ -13,6 +13,8 @@ 089A27232607D85A00F907DA /* OutlineItemDataSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 089A27222607D85A00F907DA /* OutlineItemDataSet.swift */; }; 08FD01D526E01B6400902DD3 /* SwiftListTreeDataSource in Frameworks */ = {isa = PBXBuildFile; productRef = 08FD01D426E01B6400902DD3 /* SwiftListTreeDataSource */; }; C14ABAA32913568C5599EFDC /* Pods_TreeView.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0F0E7D30A446750D518E9158 /* Pods_TreeView.framework */; }; + D81696802BF39C25009E72D6 /* SwiftListTreeDataStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = D816967D2BF39C25009E72D6 /* SwiftListTreeDataStore.swift */; }; + D81696812BF39C25009E72D6 /* SwiftUIListWithSearch.swift in Sources */ = {isa = PBXBuildFile; fileRef = D816967E2BF39C25009E72D6 /* SwiftUIListWithSearch.swift */; }; D8334087253842DD00AE6894 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8334086253842DD00AE6894 /* AppDelegate.swift */; }; D8334089253842DD00AE6894 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8334088253842DD00AE6894 /* SceneDelegate.swift */; }; D833408B253842DD00AE6894 /* TableController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D833408A253842DD00AE6894 /* TableController.swift */; }; @@ -39,6 +41,8 @@ 118780C5A4BC1E8A19A6C46C /* Pods-TreeView.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-TreeView.debug.xcconfig"; path = "Target Support Files/Pods-TreeView/Pods-TreeView.debug.xcconfig"; sourceTree = ""; }; B75FFCE4889C0CB4B68C83A9 /* Pods-test.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-test.release.xcconfig"; path = "Target Support Files/Pods-test/Pods-test.release.xcconfig"; sourceTree = ""; }; CE453948DCB18D06CD0B5362 /* Pods-test.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-test.debug.xcconfig"; path = "Target Support Files/Pods-test/Pods-test.debug.xcconfig"; sourceTree = ""; }; + D816967D2BF39C25009E72D6 /* SwiftListTreeDataStore.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SwiftListTreeDataStore.swift; sourceTree = ""; }; + D816967E2BF39C25009E72D6 /* SwiftUIListWithSearch.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SwiftUIListWithSearch.swift; sourceTree = ""; }; D8334083253842DD00AE6894 /* TreeView.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = TreeView.app; sourceTree = BUILT_PRODUCTS_DIR; }; D8334086253842DD00AE6894 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; D8334088253842DD00AE6894 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; @@ -89,6 +93,15 @@ path = Pods; sourceTree = ""; }; + D816967F2BF39C25009E72D6 /* SwiftUI */ = { + isa = PBXGroup; + children = ( + D816967D2BF39C25009E72D6 /* SwiftListTreeDataStore.swift */, + D816967E2BF39C25009E72D6 /* SwiftUIListWithSearch.swift */, + ); + path = SwiftUI; + sourceTree = ""; + }; D833407A253842DD00AE6894 = { isa = PBXGroup; children = ( @@ -143,6 +156,7 @@ D8F452672539C99C00F10963 /* SwiftListTreeDataSource */ = { isa = PBXGroup; children = ( + D816967F2BF39C25009E72D6 /* SwiftUI */, D833408A253842DD00AE6894 /* TableController.swift */, D8F452F6253A44CE00F10963 /* TableWithSearchController.swift */, ); @@ -294,12 +308,14 @@ D8F452FA253A475400F10963 /* Debouncer.swift in Sources */, D8F45301253A669600F10963 /* UISearchBar+ActivityIndicator.swift in Sources */, 083930262618A7FF008E23A9 /* DataManager.swift in Sources */, + D81696802BF39C25009E72D6 /* SwiftListTreeDataStore.swift in Sources */, D8F4526F2539CCEE00F10963 /* Cell.swift in Sources */, 089A27232607D85A00F907DA /* OutlineItemDataSet.swift in Sources */, D8334087253842DD00AE6894 /* AppDelegate.swift in Sources */, D8F452CA2539DDAE00F10963 /* OutlineViewController.swift in Sources */, D8334089253842DD00AE6894 /* SceneDelegate.swift in Sources */, D8F4525C2539C8A500F10963 /* TreeViewController+RATreeView.swift in Sources */, + D81696812BF39C25009E72D6 /* SwiftUIListWithSearch.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -451,6 +467,7 @@ CODE_SIGN_STYLE = Manual; DEVELOPMENT_TEAM = 72S6RY2PDS; INFOPLIST_FILE = TreeView/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -473,6 +490,7 @@ CODE_SIGN_STYLE = Manual; DEVELOPMENT_TEAM = 72S6RY2PDS; INFOPLIST_FILE = TreeView/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -514,7 +532,7 @@ repositoryURL = "https://github.com/dzmitry-antonenka/SwiftListTreeDataSource"; requirement = { kind = upToNextMajorVersion; - minimumVersion = 1.0.0; + minimumVersion = 1.0.1; }; }; /* End XCRemoteSwiftPackageReference section */ diff --git a/Examples/TreeView/TreeView.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Examples/TreeView/TreeView.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved deleted file mode 100644 index 5bf8c3c..0000000 --- a/Examples/TreeView/TreeView.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ /dev/null @@ -1,16 +0,0 @@ -{ - "object": { - "pins": [ - { - "package": "SwiftListTreeDataSource", - "repositoryURL": "https://github.com/dzmitry-antonenka/SwiftListTreeDataSource", - "state": { - "branch": null, - "revision": "c659802268dbaf5b8116e88b30edfa3ade39cca2", - "version": "1.0.0" - } - } - ] - }, - "version": 1 -} diff --git a/Examples/TreeView/TreeView.xcworkspace/contents.xcworkspacedata b/Examples/TreeView/TreeView.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..8c433fa --- /dev/null +++ b/Examples/TreeView/TreeView.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/Examples/TreeView/TreeView.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/Examples/TreeView/TreeView.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/Examples/TreeView/TreeView.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/Examples/TreeView/TreeView.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Examples/TreeView/TreeView.xcworkspace/xcshareddata/swiftpm/Package.resolved new file mode 100644 index 0000000..9e78fb7 --- /dev/null +++ b/Examples/TreeView/TreeView.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -0,0 +1,15 @@ +{ + "originHash" : "d90efac5006e6cfc4f45128ec29308b20565b7e098329fa9ec76262ffef9fc26", + "pins" : [ + { + "identity" : "swiftlisttreedatasource", + "kind" : "remoteSourceControl", + "location" : "https://github.com/dzmitry-antonenka/SwiftListTreeDataSource", + "state" : { + "revision" : "9304960bf037df233be89a7e91e8fd062f352f49", + "version" : "1.0.1" + } + } + ], + "version" : 3 +} diff --git a/Examples/TreeView/TreeView/Base.lproj/Main.storyboard b/Examples/TreeView/TreeView/Base.lproj/Main.storyboard index 917a510..f3023b0 100644 --- a/Examples/TreeView/TreeView/Base.lproj/Main.storyboard +++ b/Examples/TreeView/TreeView/Base.lproj/Main.storyboard @@ -1,8 +1,9 @@ - + - + + @@ -48,7 +49,7 @@ - + @@ -63,7 +64,7 @@ - + @@ -130,7 +131,7 @@ - + @@ -155,6 +156,7 @@ + @@ -170,7 +172,7 @@ - + @@ -209,7 +211,7 @@ - + @@ -220,7 +222,7 @@ - + @@ -239,7 +241,7 @@ - + @@ -251,12 +253,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - + + + diff --git a/Examples/TreeView/TreeView/SwiftListTreeDataSource/SwiftUI/SwiftListTreeDataStore.swift b/Examples/TreeView/TreeView/SwiftListTreeDataSource/SwiftUI/SwiftListTreeDataStore.swift new file mode 100644 index 0000000..035785f --- /dev/null +++ b/Examples/TreeView/TreeView/SwiftListTreeDataSource/SwiftUI/SwiftListTreeDataStore.swift @@ -0,0 +1,70 @@ +// +// SwiftListTreeDataStore.swift +// TreeView +// +// Created by Dzmitry Antonenka on 5/14/24. +// + +import SwiftUI +import SwiftListTreeDataSource + +class SwiftListTreeDataStore: ObservableObject { + typealias ItemType = ListTreeDataSource.TreeItemType + + enum DisplayMode { + case standard + case filtering(text: String) + } + + private lazy var originalItems: [OutlineItem] = DataManager.shared.mockData.items + private var debouncer = Debouncer() + + @Published var isLoading: Bool = false + @Published var displayMode: DisplayMode = .standard + @Published var items: [ItemType] = [] + + private lazy var source: FilterableListTreeDataSource = { + var dataSource = FilterableListTreeDataSource() + addItems(originalItems, to: dataSource) + return dataSource + }() + + func performSearch(with searchText: String) { + if !searchText.isEmpty { + self.isLoading = true + self.displayMode = .filtering(text: searchText) + + self.source.filterItemsKeepingParents(by: { $0.title.lowercased().contains(searchText.lowercased()) }) { [weak self] in + self?.isLoading = false + self?.items = self?.source.items ?? [] + } + } else { + self.displayMode = .standard + self.isLoading = false + self.source.resetFiltering(collapsingAll: true) + + self.items = self.source.items + } + } + + func toggleExpand(item: ItemType) { + source.toggleExpand(item: item) + self.items = self.source.items + } + + var isSearching: Bool { + switch displayMode { + case .standard: + return false + case .filtering(_): + return true + } + } + + func searchBar(textDidChange searchText: String) { + debouncer.debounce { [weak self] in + guard let self = self else { return } + self.performSearch(with: searchText) + } + } +} diff --git a/Examples/TreeView/TreeView/SwiftListTreeDataSource/SwiftUI/SwiftUIListWithSearch.swift b/Examples/TreeView/TreeView/SwiftListTreeDataSource/SwiftUI/SwiftUIListWithSearch.swift new file mode 100644 index 0000000..31c28de --- /dev/null +++ b/Examples/TreeView/TreeView/SwiftListTreeDataSource/SwiftUI/SwiftUIListWithSearch.swift @@ -0,0 +1,94 @@ +// +// SwiftUIListWithSearch.swift +// TreeView +// +// Created by Dzmitry Antonenka on 5/14/24. +// + +import SwiftUI +import SwiftListTreeDataSource + +class SwiftUIListWithSearchHosting: UIHostingController { + init() { + super.init(rootView: SwiftUIListWithSearch()) + } + + @available(*, unavailable) + required init?(coder _: NSCoder) { + super.init(rootView: SwiftUIListWithSearch()) + } +} + +struct SwiftUIListWithSearch: View { + @StateObject private var store = SwiftListTreeDataStore() + @State private var searchText = "" + + var body: some View { + NavigationView { + List { + ForEach(store.items) { element in + Button(action: { + withAnimation { + store.toggleExpand(item: element) + } + }) { + HStack(spacing: 0) { + Spacer().frame(width: spaceForLevel(element.level)) + + Text(attributedTitle(element.value.title)) + + Spacer(minLength: 4) + + if !element.subitems.isEmpty { + Image(systemName: "chevron.right") + .font(Font.system(.footnote) + .weight(.semibold)) + .foregroundColor(.blue) + .rotationEffect(element.isExpanded ? .degrees(90) : .zero) + .animation(.default) + } + } + } + .buttonStyle(.automatic) + } + } + .listStyle(.plain) + } + .searchable(text: $searchText) + .onAppear(perform: runSearch) + .onSubmit(of: .search, runSearch) + .onChange(of: searchText) { _ in + runSearch() + } + } + + private func spaceForLevel(_ level: Int) -> CGFloat { + 11 + CGFloat(10 * level) + } + + private func attributedTitle(_ title: String) -> AttributedString { + let mattrString = NSMutableAttributedString(string: title, attributes: [ .foregroundColor: UIColor.black ]) + if !searchText.isEmpty { + let range = (title.lowercased() as NSString).range(of: searchText.lowercased()) + mattrString.addAttributes([ + .font: UIFont.systemFont(ofSize: 17, weight: .semibold) + ], range: range) + } + return AttributedString(mattrString) + } + + private func runSearch() { + store.searchBar(textDidChange: searchText) + } +} + +extension NavigationLink where Label == AnyView, Destination == EmptyView { + + /// Useful in cases where a `NavigationLink` is needed but there should not be + /// a destination. e.g. for programmatic navigation. + static var empty: NavigationLink { + self.init(destination: EmptyView(), label: { + AnyView(Image(systemName: "chevron.right").font(Font.system(.footnote).weight(.semibold))) + }) + } +}