From 0ad346e739c54e4c7dc3e0adce171a42071191e6 Mon Sep 17 00:00:00 2001 From: Martin Rechsteiner Date: Sun, 14 Feb 2016 17:16:58 +0100 Subject: [PATCH] Initial commit --- .gitignore | 21 + Cartfile | 1 + Cartfile.resolved | 1 + Error.swift | 5 + Example/AppDelegate.swift | 6 + .../AppIcon.appiconset/Contents.json | 68 ++ Example/Base.lproj/LaunchScreen.storyboard | 27 + Example/Base.lproj/Main.storyboard | 26 + Example/ExampleViewController.swift | 30 + Example/Info.plist | 47 ++ Example/ViewController.swift | 23 + PagingDirection.swift | 18 + PagingState.swift | 50 ++ Parchment.xcodeproj/project.pbxproj | 615 ++++++++++++++++++ .../contents.xcworkspacedata | 7 + Parchment/ArithmeticType.swift | 11 + Parchment/Extensions/UICollectionView.swift | 16 + .../Extensions/UICollectionViewLayout.swift | 23 + Parchment/Info.plist | 26 + Parchment/PagingCell.swift | 54 ++ Parchment/PagingCollectionViewLayout.swift | 79 +++ Parchment/PagingContentViewController.swift | 105 +++ Parchment/PagingDataSource.swift | 43 ++ Parchment/PagingIndicator.swift | 19 + .../PagingIndicatorLayoutAttributes.swift | 27 + Parchment/PagingViewController.swift | 115 ++++ Parchment/Parchment.h | 19 + Parchment/Protocols/ReusableView.swift | 13 + Parchment/Tween.swift | 5 + Parchment/UIViewController.swift | 11 + 30 files changed, 1511 insertions(+) create mode 100644 .gitignore create mode 100644 Cartfile create mode 100644 Cartfile.resolved create mode 100644 Error.swift create mode 100644 Example/AppDelegate.swift create mode 100644 Example/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 Example/Base.lproj/LaunchScreen.storyboard create mode 100644 Example/Base.lproj/Main.storyboard create mode 100644 Example/ExampleViewController.swift create mode 100644 Example/Info.plist create mode 100644 Example/ViewController.swift create mode 100644 PagingDirection.swift create mode 100644 PagingState.swift create mode 100644 Parchment.xcodeproj/project.pbxproj create mode 100644 Parchment.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 Parchment/ArithmeticType.swift create mode 100644 Parchment/Extensions/UICollectionView.swift create mode 100644 Parchment/Extensions/UICollectionViewLayout.swift create mode 100644 Parchment/Info.plist create mode 100644 Parchment/PagingCell.swift create mode 100644 Parchment/PagingCollectionViewLayout.swift create mode 100644 Parchment/PagingContentViewController.swift create mode 100644 Parchment/PagingDataSource.swift create mode 100644 Parchment/PagingIndicator.swift create mode 100644 Parchment/PagingIndicatorLayoutAttributes.swift create mode 100644 Parchment/PagingViewController.swift create mode 100644 Parchment/Parchment.h create mode 100644 Parchment/Protocols/ReusableView.swift create mode 100644 Parchment/Tween.swift create mode 100644 Parchment/UIViewController.swift diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..1e13f563 --- /dev/null +++ b/.gitignore @@ -0,0 +1,21 @@ +# Xcode +# +build/ +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 +xcuserdata +*.xccheckout +*.moved-aside +DerivedData +*.hmap +*.ipa +*.xcuserstate + +Carthage/Checkouts +Carthage/Build diff --git a/Cartfile b/Cartfile new file mode 100644 index 00000000..04d557a4 --- /dev/null +++ b/Cartfile @@ -0,0 +1 @@ +github "robb/Cartography" \ No newline at end of file diff --git a/Cartfile.resolved b/Cartfile.resolved new file mode 100644 index 00000000..d92afb00 --- /dev/null +++ b/Cartfile.resolved @@ -0,0 +1 @@ +github "robb/Cartography" "0.6.0" diff --git a/Error.swift b/Error.swift new file mode 100644 index 00000000..851f55c8 --- /dev/null +++ b/Error.swift @@ -0,0 +1,5 @@ +import Foundation + +enum Error: String { + case InitCoder = "init(coder:) has not been implemented" +} diff --git a/Example/AppDelegate.swift b/Example/AppDelegate.swift new file mode 100644 index 00000000..c1a82671 --- /dev/null +++ b/Example/AppDelegate.swift @@ -0,0 +1,6 @@ +import UIKit + +@UIApplicationMain +class AppDelegate: UIResponder, UIApplicationDelegate { + var window: UIWindow? +} diff --git a/Example/Assets.xcassets/AppIcon.appiconset/Contents.json b/Example/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 00000000..36d2c80d --- /dev/null +++ b/Example/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,68 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "60x60", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "60x60", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "76x76", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "76x76", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Example/Base.lproj/LaunchScreen.storyboard b/Example/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 00000000..2e721e18 --- /dev/null +++ b/Example/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Example/Base.lproj/Main.storyboard b/Example/Base.lproj/Main.storyboard new file mode 100644 index 00000000..32b4e8c6 --- /dev/null +++ b/Example/Base.lproj/Main.storyboard @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Example/ExampleViewController.swift b/Example/ExampleViewController.swift new file mode 100644 index 00000000..9741deb2 --- /dev/null +++ b/Example/ExampleViewController.swift @@ -0,0 +1,30 @@ +import UIKit +import Cartography + +class ExampleViewController: UIViewController { + + init(index: Int) { + super.init(nibName: nil, bundle: nil) + title = "View \(index)" + label.text = "\(index)" + label.sizeToFit() + view.addSubview(label) + view.backgroundColor = UIColor.whiteColor() + constrain(view, label) { view, label in + label.centerX == view.centerX + label.centerY == view.centerY + } + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + private lazy var label: UILabel = { + let label = UILabel(frame: .zero) + label.font = UIFont(name: "HelveticaNeue-Thin", size: 70) + label.textColor = UIColor.lightGrayColor() + return label + }() + +} \ No newline at end of file diff --git a/Example/Info.plist b/Example/Info.plist new file mode 100644 index 00000000..40c6215d --- /dev/null +++ b/Example/Info.plist @@ -0,0 +1,47 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/Example/ViewController.swift b/Example/ViewController.swift new file mode 100644 index 00000000..d77fdb12 --- /dev/null +++ b/Example/ViewController.swift @@ -0,0 +1,23 @@ +import UIKit +import Parchment +import Cartography + +class ViewController: UIViewController { + + override func viewDidLoad() { + super.viewDidLoad() + + let pagingViewController = PagingViewController(viewControllers: (0...10).map { + return ExampleViewController(index: $0) + }) + + addChildViewController(pagingViewController) + view.addSubview(pagingViewController.view) + pagingViewController.didMoveToParentViewController(self) + + constrain(view, pagingViewController.view) { view, pagingView in + view.edges == pagingView.edges + } + } + +} diff --git a/PagingDirection.swift b/PagingDirection.swift new file mode 100644 index 00000000..c009bfb9 --- /dev/null +++ b/PagingDirection.swift @@ -0,0 +1,18 @@ +import Foundation + +enum PagingDirection { + case Reverse, Forward +} + +extension PagingDirection { + + var pageViewControllerNavigationDirection: UIPageViewControllerNavigationDirection { + switch self { + case .Forward: + return .Forward + case .Reverse: + return .Reverse + } + } + +} diff --git a/PagingState.swift b/PagingState.swift new file mode 100644 index 00000000..15861225 --- /dev/null +++ b/PagingState.swift @@ -0,0 +1,50 @@ +import Foundation + +enum PagingState { + + case Previous(Int, Int, CGFloat) + case Current(Int, PagingDirection) + case Next(Int, Int, CGFloat) + + var offset: CGFloat { + switch self { + case let .Previous(_, _, offset): + return offset + case let .Next(_, _,offset): + return offset + case .Current: + return 0 + } + } + + var currentIndex: Int { + switch self { + case let .Previous(index, _, _): + return index + case let .Next(index, _, _): + return index + case let .Current(index, _): + return index + } + } + + var upcomingIndex: Int? { + switch self { + case let .Previous(_, index, _): + return index + case let .Next(_, index, _): + return index + case .Current: + return nil + } + } + + func directionForUpcomingIndex(index: Int) -> PagingDirection { + if self.currentIndex > index { + return .Reverse + } else { + return .Forward + } + } + +} diff --git a/Parchment.xcodeproj/project.pbxproj b/Parchment.xcodeproj/project.pbxproj new file mode 100644 index 00000000..0b4e2b83 --- /dev/null +++ b/Parchment.xcodeproj/project.pbxproj @@ -0,0 +1,615 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 3E9E8D041C70C68500F265A4 /* PagingState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E9E8D021C70C68500F265A4 /* PagingState.swift */; }; + 3E9E8D051C70C68500F265A4 /* PagingDirection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E9E8D031C70C68500F265A4 /* PagingDirection.swift */; }; + 3E9E8D071C70C6E600F265A4 /* Error.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E9E8D061C70C6E600F265A4 /* Error.swift */; }; + 3E9E8D0B1C70CDA900F265A4 /* UIViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E9E8D0A1C70CDA900F265A4 /* UIViewController.swift */; }; + 3E9E8D0D1C70CEA600F265A4 /* ExampleViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E9E8D0C1C70CEA600F265A4 /* ExampleViewController.swift */; }; + 3E9E8D0F1C70D3D900F265A4 /* PagingContentViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E9E8D0E1C70D3D900F265A4 /* PagingContentViewController.swift */; }; + 3E9E8D141C70FDF900F265A4 /* Parchment.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3EA04A4B1C53BFE40054E5E0 /* Parchment.framework */; }; + 3E9E8D151C70FDF900F265A4 /* Parchment.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3EA04A4B1C53BFE40054E5E0 /* Parchment.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 3EA04A5D1C53BFF40054E5E0 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3EA04A5C1C53BFF40054E5E0 /* AppDelegate.swift */; }; + 3EA04A5F1C53BFF40054E5E0 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3EA04A5E1C53BFF40054E5E0 /* ViewController.swift */; }; + 3EA04A621C53BFF40054E5E0 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 3EA04A601C53BFF40054E5E0 /* Main.storyboard */; }; + 3EA04A641C53BFF40054E5E0 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 3EA04A631C53BFF40054E5E0 /* Assets.xcassets */; }; + 3EA04A671C53BFF40054E5E0 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 3EA04A651C53BFF40054E5E0 /* LaunchScreen.storyboard */; }; + 3EA04A6F1C53C0610054E5E0 /* UICollectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3EA04A6E1C53C0610054E5E0 /* UICollectionView.swift */; }; + 3EA04A781C53C0B20054E5E0 /* ReusableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3EA04A771C53C0B20054E5E0 /* ReusableView.swift */; }; + 3EA04A7A1C53C1170054E5E0 /* PagingViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3EA04A791C53C1170054E5E0 /* PagingViewController.swift */; }; + 3EA04A801C53C3570054E5E0 /* Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3EA04A7E1C53C3570054E5E0 /* Info.plist */; }; + 3EA04A811C53C3570054E5E0 /* Parchment.h in Headers */ = {isa = PBXBuildFile; fileRef = 3EA04A7F1C53C3570054E5E0 /* Parchment.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 3EA04A831C53C3860054E5E0 /* Cartography.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3EA04A821C53C3860054E5E0 /* Cartography.framework */; }; + 3EA04A871C53C48E0054E5E0 /* Cartography.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3EA04A821C53C3860054E5E0 /* Cartography.framework */; }; + 3EA04A8B1C53C9B80054E5E0 /* UICollectionViewLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3EA04A8A1C53C9B80054E5E0 /* UICollectionViewLayout.swift */; }; + 3EA04A8D1C53D5070054E5E0 /* PagingCollectionViewLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3EA04A8C1C53D5070054E5E0 /* PagingCollectionViewLayout.swift */; }; + 3EA04A8F1C53D53B0054E5E0 /* PagingDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3EA04A8E1C53D53B0054E5E0 /* PagingDataSource.swift */; }; + 3EA04A911C53D55E0054E5E0 /* PagingIndicator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3EA04A901C53D55E0054E5E0 /* PagingIndicator.swift */; }; + 3EA04A931C53D58B0054E5E0 /* PagingCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3EA04A921C53D58B0054E5E0 /* PagingCell.swift */; }; + 3EA04A951C53E0960054E5E0 /* PagingIndicatorLayoutAttributes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3EA04A941C53E0960054E5E0 /* PagingIndicatorLayoutAttributes.swift */; }; + 3EA04A971C53E1160054E5E0 /* Tween.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3EA04A961C53E1160054E5E0 /* Tween.swift */; }; + 3EA04A991C53E1260054E5E0 /* ArithmeticType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3EA04A981C53E1260054E5E0 /* ArithmeticType.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 3EA04A881C53C6F70054E5E0 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 3EA04A421C53BFE40054E5E0 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 3EA04A4A1C53BFE40054E5E0; + remoteInfo = Parchment; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 3E9E8D161C70FDF900F265A4 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + 3E9E8D151C70FDF900F265A4 /* Parchment.framework in Embed Frameworks */, + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 3E9E8D021C70C68500F265A4 /* PagingState.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = PagingState.swift; path = ../PagingState.swift; sourceTree = ""; }; + 3E9E8D031C70C68500F265A4 /* PagingDirection.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = PagingDirection.swift; path = ../PagingDirection.swift; sourceTree = ""; }; + 3E9E8D061C70C6E600F265A4 /* Error.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Error.swift; path = ../Error.swift; sourceTree = ""; }; + 3E9E8D0A1C70CDA900F265A4 /* UIViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIViewController.swift; sourceTree = ""; }; + 3E9E8D0C1C70CEA600F265A4 /* ExampleViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExampleViewController.swift; sourceTree = ""; }; + 3E9E8D0E1C70D3D900F265A4 /* PagingContentViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PagingContentViewController.swift; sourceTree = ""; }; + 3EA04A4B1C53BFE40054E5E0 /* Parchment.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Parchment.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 3EA04A5A1C53BFF40054E5E0 /* Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Example.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 3EA04A5C1C53BFF40054E5E0 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 3EA04A5E1C53BFF40054E5E0 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; + 3EA04A611C53BFF40054E5E0 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 3EA04A631C53BFF40054E5E0 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 3EA04A661C53BFF40054E5E0 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 3EA04A681C53BFF40054E5E0 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 3EA04A6E1C53C0610054E5E0 /* UICollectionView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = UICollectionView.swift; path = Extensions/UICollectionView.swift; sourceTree = ""; }; + 3EA04A771C53C0B20054E5E0 /* ReusableView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ReusableView.swift; path = Protocols/ReusableView.swift; sourceTree = ""; }; + 3EA04A791C53C1170054E5E0 /* PagingViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PagingViewController.swift; sourceTree = ""; }; + 3EA04A7E1C53C3570054E5E0 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 3EA04A7F1C53C3570054E5E0 /* Parchment.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Parchment.h; sourceTree = ""; }; + 3EA04A821C53C3860054E5E0 /* Cartography.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cartography.framework; path = Carthage/Build/iOS/Cartography.framework; sourceTree = ""; }; + 3EA04A8A1C53C9B80054E5E0 /* UICollectionViewLayout.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = UICollectionViewLayout.swift; path = Extensions/UICollectionViewLayout.swift; sourceTree = ""; }; + 3EA04A8C1C53D5070054E5E0 /* PagingCollectionViewLayout.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PagingCollectionViewLayout.swift; sourceTree = ""; }; + 3EA04A8E1C53D53B0054E5E0 /* PagingDataSource.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PagingDataSource.swift; sourceTree = ""; }; + 3EA04A901C53D55E0054E5E0 /* PagingIndicator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PagingIndicator.swift; sourceTree = ""; }; + 3EA04A921C53D58B0054E5E0 /* PagingCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PagingCell.swift; sourceTree = ""; }; + 3EA04A941C53E0960054E5E0 /* PagingIndicatorLayoutAttributes.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PagingIndicatorLayoutAttributes.swift; sourceTree = ""; }; + 3EA04A961C53E1160054E5E0 /* Tween.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Tween.swift; sourceTree = ""; }; + 3EA04A981C53E1260054E5E0 /* ArithmeticType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ArithmeticType.swift; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 3EA04A471C53BFE40054E5E0 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 3EA04A831C53C3860054E5E0 /* Cartography.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 3EA04A571C53BFF40054E5E0 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 3EA04A871C53C48E0054E5E0 /* Cartography.framework in Frameworks */, + 3E9E8D141C70FDF900F265A4 /* Parchment.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 3EA04A411C53BFE40054E5E0 = { + isa = PBXGroup; + children = ( + 3EA04A4D1C53BFE40054E5E0 /* Parchment */, + 3EA04A5B1C53BFF40054E5E0 /* Example */, + 3EA04A841C53C3960054E5E0 /* Frameworks */, + 3EA04A4C1C53BFE40054E5E0 /* Products */, + ); + sourceTree = ""; + }; + 3EA04A4C1C53BFE40054E5E0 /* Products */ = { + isa = PBXGroup; + children = ( + 3EA04A4B1C53BFE40054E5E0 /* Parchment.framework */, + 3EA04A5A1C53BFF40054E5E0 /* Example.app */, + ); + name = Products; + sourceTree = ""; + }; + 3EA04A4D1C53BFE40054E5E0 /* Parchment */ = { + isa = PBXGroup; + children = ( + 3EA04A851C53C3E80054E5E0 /* Resources */, + 3EA04A701C53C0640054E5E0 /* Extensions */, + 3EA04A961C53E1160054E5E0 /* Tween.swift */, + 3E9E8D061C70C6E600F265A4 /* Error.swift */, + 3EA04A981C53E1260054E5E0 /* ArithmeticType.swift */, + 3E9E8D021C70C68500F265A4 /* PagingState.swift */, + 3E9E8D031C70C68500F265A4 /* PagingDirection.swift */, + 3EA04A791C53C1170054E5E0 /* PagingViewController.swift */, + 3E9E8D0E1C70D3D900F265A4 /* PagingContentViewController.swift */, + 3EA04A8C1C53D5070054E5E0 /* PagingCollectionViewLayout.swift */, + 3EA04A8E1C53D53B0054E5E0 /* PagingDataSource.swift */, + 3EA04A901C53D55E0054E5E0 /* PagingIndicator.swift */, + 3EA04A941C53E0960054E5E0 /* PagingIndicatorLayoutAttributes.swift */, + 3EA04A921C53D58B0054E5E0 /* PagingCell.swift */, + 3EA04A711C53C0760054E5E0 /* Protocols */, + ); + path = Parchment; + sourceTree = ""; + }; + 3EA04A5B1C53BFF40054E5E0 /* Example */ = { + isa = PBXGroup; + children = ( + 3EA04A5C1C53BFF40054E5E0 /* AppDelegate.swift */, + 3EA04A5E1C53BFF40054E5E0 /* ViewController.swift */, + 3E9E8D0C1C70CEA600F265A4 /* ExampleViewController.swift */, + 3EA04A601C53BFF40054E5E0 /* Main.storyboard */, + 3EA04A631C53BFF40054E5E0 /* Assets.xcassets */, + 3EA04A651C53BFF40054E5E0 /* LaunchScreen.storyboard */, + 3EA04A681C53BFF40054E5E0 /* Info.plist */, + ); + path = Example; + sourceTree = ""; + }; + 3EA04A701C53C0640054E5E0 /* Extensions */ = { + isa = PBXGroup; + children = ( + 3EA04A6E1C53C0610054E5E0 /* UICollectionView.swift */, + 3EA04A8A1C53C9B80054E5E0 /* UICollectionViewLayout.swift */, + 3E9E8D0A1C70CDA900F265A4 /* UIViewController.swift */, + ); + name = Extensions; + sourceTree = ""; + }; + 3EA04A711C53C0760054E5E0 /* Protocols */ = { + isa = PBXGroup; + children = ( + 3EA04A771C53C0B20054E5E0 /* ReusableView.swift */, + ); + name = Protocols; + sourceTree = ""; + }; + 3EA04A841C53C3960054E5E0 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 3EA04A821C53C3860054E5E0 /* Cartography.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + 3EA04A851C53C3E80054E5E0 /* Resources */ = { + isa = PBXGroup; + children = ( + 3EA04A7E1C53C3570054E5E0 /* Info.plist */, + 3EA04A7F1C53C3570054E5E0 /* Parchment.h */, + ); + name = Resources; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 3EA04A481C53BFE40054E5E0 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 3EA04A811C53C3570054E5E0 /* Parchment.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 3EA04A4A1C53BFE40054E5E0 /* Parchment */ = { + isa = PBXNativeTarget; + buildConfigurationList = 3EA04A531C53BFE40054E5E0 /* Build configuration list for PBXNativeTarget "Parchment" */; + buildPhases = ( + 3EA04A461C53BFE40054E5E0 /* Sources */, + 3EA04A471C53BFE40054E5E0 /* Frameworks */, + 3EA04A481C53BFE40054E5E0 /* Headers */, + 3EA04A491C53BFE40054E5E0 /* Resources */, + 3EA04A7D1C53C31E0054E5E0 /* ShellScript */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Parchment; + productName = Parchment; + productReference = 3EA04A4B1C53BFE40054E5E0 /* Parchment.framework */; + productType = "com.apple.product-type.framework"; + }; + 3EA04A591C53BFF40054E5E0 /* Example */ = { + isa = PBXNativeTarget; + buildConfigurationList = 3EA04A691C53BFF40054E5E0 /* Build configuration list for PBXNativeTarget "Example" */; + buildPhases = ( + 3EA04A561C53BFF40054E5E0 /* Sources */, + 3EA04A571C53BFF40054E5E0 /* Frameworks */, + 3EA04A581C53BFF40054E5E0 /* Resources */, + 3EA04A861C53C4770054E5E0 /* ShellScript */, + 3E9E8D161C70FDF900F265A4 /* Embed Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + 3EA04A891C53C6F70054E5E0 /* PBXTargetDependency */, + ); + name = Example; + productName = Example; + productReference = 3EA04A5A1C53BFF40054E5E0 /* Example.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 3EA04A421C53BFE40054E5E0 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0720; + LastUpgradeCheck = 0720; + ORGANIZATIONNAME = "Martin Rechsteiner"; + TargetAttributes = { + 3EA04A4A1C53BFE40054E5E0 = { + CreatedOnToolsVersion = 7.2; + DevelopmentTeam = C48GZ8PUTA; + }; + 3EA04A591C53BFF40054E5E0 = { + CreatedOnToolsVersion = 7.2; + DevelopmentTeam = C48GZ8PUTA; + }; + }; + }; + buildConfigurationList = 3EA04A451C53BFE40054E5E0 /* Build configuration list for PBXProject "Parchment" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 3EA04A411C53BFE40054E5E0; + productRefGroup = 3EA04A4C1C53BFE40054E5E0 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 3EA04A4A1C53BFE40054E5E0 /* Parchment */, + 3EA04A591C53BFF40054E5E0 /* Example */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 3EA04A491C53BFE40054E5E0 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 3EA04A801C53C3570054E5E0 /* Info.plist in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 3EA04A581C53BFF40054E5E0 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 3EA04A671C53BFF40054E5E0 /* LaunchScreen.storyboard in Resources */, + 3EA04A641C53BFF40054E5E0 /* Assets.xcassets in Resources */, + 3EA04A621C53BFF40054E5E0 /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 3EA04A7D1C53C31E0054E5E0 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "$(SRCROOT)/Carthage/Build/iOS/Cartography.framework", + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/usr/local/bin/carthage copy-frameworks\n"; + }; + 3EA04A861C53C4770054E5E0 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "$(SRCROOT)/Carthage/Build/iOS/Cartography.framework", + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/usr/local/bin/carthage copy-frameworks\n"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 3EA04A461C53BFE40054E5E0 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 3EA04A7A1C53C1170054E5E0 /* PagingViewController.swift in Sources */, + 3EA04A971C53E1160054E5E0 /* Tween.swift in Sources */, + 3EA04A991C53E1260054E5E0 /* ArithmeticType.swift in Sources */, + 3E9E8D051C70C68500F265A4 /* PagingDirection.swift in Sources */, + 3E9E8D0F1C70D3D900F265A4 /* PagingContentViewController.swift in Sources */, + 3EA04A931C53D58B0054E5E0 /* PagingCell.swift in Sources */, + 3EA04A6F1C53C0610054E5E0 /* UICollectionView.swift in Sources */, + 3E9E8D071C70C6E600F265A4 /* Error.swift in Sources */, + 3EA04A911C53D55E0054E5E0 /* PagingIndicator.swift in Sources */, + 3EA04A8B1C53C9B80054E5E0 /* UICollectionViewLayout.swift in Sources */, + 3E9E8D041C70C68500F265A4 /* PagingState.swift in Sources */, + 3EA04A951C53E0960054E5E0 /* PagingIndicatorLayoutAttributes.swift in Sources */, + 3EA04A8D1C53D5070054E5E0 /* PagingCollectionViewLayout.swift in Sources */, + 3EA04A8F1C53D53B0054E5E0 /* PagingDataSource.swift in Sources */, + 3EA04A781C53C0B20054E5E0 /* ReusableView.swift in Sources */, + 3E9E8D0B1C70CDA900F265A4 /* UIViewController.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 3EA04A561C53BFF40054E5E0 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 3EA04A5F1C53BFF40054E5E0 /* ViewController.swift in Sources */, + 3EA04A5D1C53BFF40054E5E0 /* AppDelegate.swift in Sources */, + 3E9E8D0D1C70CEA600F265A4 /* ExampleViewController.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 3EA04A891C53C6F70054E5E0 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 3EA04A4A1C53BFE40054E5E0 /* Parchment */; + targetProxy = 3EA04A881C53C6F70054E5E0 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 3EA04A601C53BFF40054E5E0 /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 3EA04A611C53BFF40054E5E0 /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 3EA04A651C53BFF40054E5E0 /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 3EA04A661C53BFF40054E5E0 /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 3EA04A511C53BFE40054E5E0 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "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 = 9.2; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 3EA04A521C53BFE40054E5E0 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + 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 = 9.2; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 3EA04A541C53BFE40054E5E0 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_IDENTITY = "iPhone Developer"; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Carthage/Build/iOS", + ); + INFOPLIST_FILE = Parchment/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = com.martinrechsteiner.Parchment; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 3EA04A551C53BFE40054E5E0 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_IDENTITY = "iPhone Developer"; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Carthage/Build/iOS", + ); + INFOPLIST_FILE = Parchment/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = com.martinrechsteiner.Parchment; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + }; + name = Release; + }; + 3EA04A6A1C53BFF40054E5E0 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + EMBEDDED_CONTENT_CONTAINS_SWIFT = YES; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Carthage/Build/iOS", + ); + INFOPLIST_FILE = Example/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = com.martinrechsteiner.Example; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 3EA04A6B1C53BFF40054E5E0 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + EMBEDDED_CONTENT_CONTAINS_SWIFT = YES; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Carthage/Build/iOS", + ); + INFOPLIST_FILE = Example/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = com.martinrechsteiner.Example; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 3EA04A451C53BFE40054E5E0 /* Build configuration list for PBXProject "Parchment" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 3EA04A511C53BFE40054E5E0 /* Debug */, + 3EA04A521C53BFE40054E5E0 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 3EA04A531C53BFE40054E5E0 /* Build configuration list for PBXNativeTarget "Parchment" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 3EA04A541C53BFE40054E5E0 /* Debug */, + 3EA04A551C53BFE40054E5E0 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 3EA04A691C53BFF40054E5E0 /* Build configuration list for PBXNativeTarget "Example" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 3EA04A6A1C53BFF40054E5E0 /* Debug */, + 3EA04A6B1C53BFF40054E5E0 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 3EA04A421C53BFE40054E5E0 /* Project object */; +} diff --git a/Parchment.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Parchment.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..cda68809 --- /dev/null +++ b/Parchment.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Parchment/ArithmeticType.swift b/Parchment/ArithmeticType.swift new file mode 100644 index 00000000..44e6cfb3 --- /dev/null +++ b/Parchment/ArithmeticType.swift @@ -0,0 +1,11 @@ +import Foundation + +protocol ArithmeticType { + func +(lhs: Self, rhs: Self) -> Self + func -(lhs: Self, rhs: Self) -> Self + func /(lhs: Self, rhs: Self) -> Self + func *(lhs: Self, rhs: Self) -> Self + func %(lhs: Self, rhs: Self) -> Self +} + +extension CGFloat: ArithmeticType {} diff --git a/Parchment/Extensions/UICollectionView.swift b/Parchment/Extensions/UICollectionView.swift new file mode 100644 index 00000000..dd811dfc --- /dev/null +++ b/Parchment/Extensions/UICollectionView.swift @@ -0,0 +1,16 @@ +import UIKit + +extension UICollectionView { + + func register(_: T.Type) { + registerClass(T.self, forCellWithReuseIdentifier: T.defaultReuseIdentifier) + } + + func dequeueReusableCell(forIndexPath indexPath: NSIndexPath) -> T { + guard let cell = dequeueReusableCellWithReuseIdentifier(T.defaultReuseIdentifier, forIndexPath: indexPath) as? T else { + fatalError("Could not dequeue cell with identifier: \(T.defaultReuseIdentifier)") + } + + return cell + } +} diff --git a/Parchment/Extensions/UICollectionViewLayout.swift b/Parchment/Extensions/UICollectionViewLayout.swift new file mode 100644 index 00000000..af68b94b --- /dev/null +++ b/Parchment/Extensions/UICollectionViewLayout.swift @@ -0,0 +1,23 @@ +import UIKit + +extension UICollectionViewLayout { + + var collection: UICollectionView { + guard let collectionView = self.collectionView else { + fatalError("collection view layout is missing collection view") + } + return collectionView + } + + func register(_: T.Type) { + registerClass(T.self, forDecorationViewOfKind: T.defaultReuseIdentifier) + } + + func copyLayoutAttributes(layoutAttributes: UICollectionViewLayoutAttributes) -> UICollectionViewLayoutAttributes { + guard let layoutAttributes = layoutAttributes.copy() as? UICollectionViewLayoutAttributes else { + fatalError("failed to copy layout attributes") + } + return layoutAttributes + } + +} diff --git a/Parchment/Info.plist b/Parchment/Info.plist new file mode 100644 index 00000000..d3de8eef --- /dev/null +++ b/Parchment/Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + NSPrincipalClass + + + diff --git a/Parchment/PagingCell.swift b/Parchment/PagingCell.swift new file mode 100644 index 00000000..96490ff7 --- /dev/null +++ b/Parchment/PagingCell.swift @@ -0,0 +1,54 @@ +import UIKit +import Cartography + +class PagingCell: UICollectionViewCell { + + var title: String? { + didSet { + self.titleLabel.text = self.title + } + } + + override init(frame: CGRect) { + super.init(frame: frame) + configure() + } + + required init?(coder: NSCoder) { + super.init(coder: coder) + configure() + } + + private func configure() { + contentView.backgroundColor = UIColor.redColor() + contentView.addSubview(titleLabel) + constrain(contentView, titleLabel) { contentView, titleLabel in + titleLabel.centerX == contentView.centerX + titleLabel.centerY == contentView.centerY + } + } + + override func preferredLayoutAttributesFittingAttributes(layoutAttributes: UICollectionViewLayoutAttributes) -> UICollectionViewLayoutAttributes { + guard let attributes = layoutAttributes.copy() as? UICollectionViewLayoutAttributes else { return layoutAttributes } + + frame = attributes.frame + setNeedsLayout() + layoutIfNeeded() + + let size = contentView.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize) + attributes.frame.size.width = size.width + attributes.frame.size.height = 50 + + return attributes + } + + // MARK: Lazy Getters + + private lazy var titleLabel: UILabel = { + let titleLabel = UILabel(frame: .zero) + titleLabel.font = UIFont.systemFontOfSize(17) + titleLabel.textColor = UIColor.blackColor() + return titleLabel + }() + +} diff --git a/Parchment/PagingCollectionViewLayout.swift b/Parchment/PagingCollectionViewLayout.swift new file mode 100644 index 00000000..1303bb38 --- /dev/null +++ b/Parchment/PagingCollectionViewLayout.swift @@ -0,0 +1,79 @@ +import UIKit + +class PagingCollectionViewLayout: UICollectionViewFlowLayout { + + var pagingState: PagingState + var pagingIndicatorLayoutAttributes: PagingIndicatorLayoutAttributes + + init(pagingState: PagingState) { + self.pagingState = pagingState + self.pagingIndicatorLayoutAttributes = PagingIndicatorLayoutAttributes( + forDecorationViewOfKind: PagingIndicator.defaultReuseIdentifier, + withIndexPath: NSIndexPath(forItem: 0, inSection: 0)) + super.init() + configure() + } + + required init?(coder: NSCoder) { + fatalError(Error.InitCoder.rawValue) + } + + private func configure() { + minimumLineSpacing = 0 + minimumInteritemSpacing = 0 + scrollDirection = .Horizontal + register(PagingIndicator.self) + } + + override func shouldInvalidateLayoutForBoundsChange(newBounds: CGRect) -> Bool { + return true + } + + override func layoutAttributesForElementsInRect(rect: CGRect) -> [UICollectionViewLayoutAttributes]? { + var layoutAttributes = super.layoutAttributesForElementsInRect(rect)! + layoutAttributes.append(layoutAttributesForDecorationViewOfKind(PagingIndicator.defaultReuseIdentifier, atIndexPath: NSIndexPath(forItem: 0, inSection: 0))!) + return layoutAttributes + } + + override func layoutAttributesForDecorationViewOfKind(elementKind: String, atIndexPath indexPath: NSIndexPath) -> UICollectionViewLayoutAttributes? { + if elementKind == PagingIndicator.defaultReuseIdentifier { + + let from = PagingIndicatorMetric(frame: indicatorFrameForIndex(pagingState.currentIndex)) + let to = PagingIndicatorMetric(frame: indicatorFrameForIndex(pagingState.upcomingIndex ?? pagingState.currentIndex)) + + pagingIndicatorLayoutAttributes.configure(from: from, to: to, progress: pagingState.offset) + return pagingIndicatorLayoutAttributes + } + return super.layoutAttributesForDecorationViewOfKind(elementKind, atIndexPath: indexPath) + } + + // MARK: Private + + private func indicatorFrameForIndex(index: Int) -> CGRect { + + if index < 0 { + let currentIndexPath = NSIndexPath(forItem: pagingState.currentIndex, inSection: 0) + let layoutAttributes = layoutAttributesForItemAtIndexPath(currentIndexPath)! + var frame = layoutAttributes.frame + frame.origin.x -= frame.size.width + return frame + } + + // When the selected item is the last item in the collection + // view, there is no upcoming layout attribute. Instead, we + // copy the selected item's layout attributes and update its + // frame to match where the indicator should go next + if index >= collection.numberOfItemsInSection(0) { + let currentIndexPath = NSIndexPath(forItem: pagingState.currentIndex, inSection: 0) + let layoutAttributes = layoutAttributesForItemAtIndexPath(currentIndexPath)! + var frame = layoutAttributes.frame + frame.origin.x += frame.size.width + return frame + } + + let indexPath = NSIndexPath(forItem: index, inSection: 0) + return layoutAttributesForItemAtIndexPath(indexPath)!.frame + + } + +} diff --git a/Parchment/PagingContentViewController.swift b/Parchment/PagingContentViewController.swift new file mode 100644 index 00000000..8b2f797e --- /dev/null +++ b/Parchment/PagingContentViewController.swift @@ -0,0 +1,105 @@ +import UIKit +import Cartography + +protocol PagingContentViewControllerDelegate: class { + func pagingContentViewController(pagingContentViewController: PagingContentViewController, didChangeOffset: CGFloat, towardsIndex: Int) + func pagingContentViewController(pagingContentViewController: PagingContentViewController, didMoveToIndex: Int) +} + +class PagingContentViewController: UIViewController { + + var pagingState: PagingState + weak var delegate: PagingContentViewControllerDelegate? + private let dataSource: PagingDataSource + private let pageViewController: UIPageViewController + + private var pendingViewController: UIViewController? + private var upcomingViewController: UIViewController? + + init(dataSource: PagingDataSource, pagingState: PagingState) { + + self.pagingState = pagingState + self.dataSource = dataSource + self.pageViewController = UIPageViewController( + transitionStyle: .Scroll, + navigationOrientation: .Horizontal, + options: nil) + + super.init(nibName: nil, bundle: nil) + + pageViewController.dataSource = dataSource + pageViewController.delegate = self + pageViewController.view.subviews.forEach { + if let scrollView = $0 as? UIScrollView { + scrollView.delegate = self + } + } + } + + required init?(coder: NSCoder) { + fatalError(Error.InitCoder.rawValue) + } + + override func viewDidLoad() { + super.viewDidLoad() + addViewController(pageViewController) + constrain(pageViewController.view, view) { pageView, view in + pageView.edges == view.edges + } + } + + func setViewControllerForIndex(index: Int, direction: PagingDirection, animated: Bool) { + let viewController = dataSource.viewControllers[index] + upcomingViewController = viewController + pageViewController.setViewControllers([viewController], + direction: direction.pageViewControllerNavigationDirection, + animated: animated, + completion: { completed in + if completed { + self.delegate?.pagingContentViewController(self, didMoveToIndex: index) + self.upcomingViewController = nil + } + }) + } + +} + +extension PagingContentViewController: UIScrollViewDelegate { + + func scrollViewDidScroll(scrollView: UIScrollView) { + let offset = CGFloat(scrollView.contentOffset.x / scrollView.bounds.width) - 1 + + if let upcomingViewController = self.upcomingViewController { + if let upcomingIndex = dataSource.viewControllers.indexOf(upcomingViewController) { + delegate?.pagingContentViewController(self, didChangeOffset: offset, towardsIndex: upcomingIndex) + } + } else if offset < 0 { + delegate?.pagingContentViewController(self, didChangeOffset: offset, towardsIndex: pagingState.currentIndex - 1) + } else if offset > 0 { + delegate?.pagingContentViewController(self, didChangeOffset: offset, towardsIndex: pagingState.currentIndex + 1) + } + } + +} + +extension PagingContentViewController: UIPageViewControllerDelegate { + + func pageViewController(pageViewController: UIPageViewController, willTransitionToViewControllers pendingViewControllers: [UIViewController]) { + if let viewController = pendingViewControllers.first { + pendingViewController = viewController + } + } + + func pageViewController(pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) { + guard + let viewController = self.pendingViewController, + let index = dataSource.viewControllers.indexOf(viewController) else { return } + + if completed { + delegate?.pagingContentViewController(self, didMoveToIndex: index) + } + + pendingViewController = nil + } + +} diff --git a/Parchment/PagingDataSource.swift b/Parchment/PagingDataSource.swift new file mode 100644 index 00000000..25516576 --- /dev/null +++ b/Parchment/PagingDataSource.swift @@ -0,0 +1,43 @@ +import UIKit + +class PagingDataSource: NSObject { + + var viewControllers: [UIViewController] + + init(viewControllers: [UIViewController]) { + self.viewControllers = viewControllers + } + +} + +extension PagingDataSource: UICollectionViewDataSource { + + func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell { + let cell: PagingCell = collectionView.dequeueReusableCell(forIndexPath: indexPath) + cell.title = viewControllers[indexPath.row].title + return cell + } + + func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { + return viewControllers.count + } + +} + +extension PagingDataSource: UIPageViewControllerDataSource { + + func pageViewController(pageViewController: UIPageViewController, viewControllerBeforeViewController viewController: UIViewController) -> UIViewController? { + if let index = self.viewControllers.indexOf(viewController) where index > 0 { + return self.viewControllers[index - 1] + } + return nil + } + + func pageViewController(pageViewController: UIPageViewController, viewControllerAfterViewController viewController: UIViewController) -> UIViewController? { + if let index = self.viewControllers.indexOf(viewController) where index < self.viewControllers.count - 1 { + return self.viewControllers[index + 1] + } + return nil + } + +} \ No newline at end of file diff --git a/Parchment/PagingIndicator.swift b/Parchment/PagingIndicator.swift new file mode 100644 index 00000000..61bdd54d --- /dev/null +++ b/Parchment/PagingIndicator.swift @@ -0,0 +1,19 @@ +import UIKit + +class PagingIndicator: UICollectionReusableView { + + override init(frame: CGRect) { + super.init(frame: frame) + configure() + } + + required init?(coder: NSCoder) { + super.init(coder: coder) + configure() + } + + private func configure() { + backgroundColor = UIColor.blueColor() + } + +} diff --git a/Parchment/PagingIndicatorLayoutAttributes.swift b/Parchment/PagingIndicatorLayoutAttributes.swift new file mode 100644 index 00000000..2dd441e3 --- /dev/null +++ b/Parchment/PagingIndicatorLayoutAttributes.swift @@ -0,0 +1,27 @@ +import UIKit + +struct PagingIndicatorMetric { + let frame: CGRect +} + +class PagingIndicatorLayoutAttributes: UICollectionViewLayoutAttributes { + + func configure(from from: PagingIndicatorMetric, to: PagingIndicatorMetric, progress: CGFloat) { + + frame.origin.x = tween( + from: from.frame.origin.x, + to: to.frame.origin.x, + progress: progress) + + frame.size.width = tween( + from: from.frame.width, + to: to.frame.width, + progress: progress) + + frame.size.height = 4 + frame.origin.y = 46 + zIndex = 100 + } + + +} diff --git a/Parchment/PagingViewController.swift b/Parchment/PagingViewController.swift new file mode 100644 index 00000000..80f8dc51 --- /dev/null +++ b/Parchment/PagingViewController.swift @@ -0,0 +1,115 @@ +import UIKit +import Cartography + +public class PagingViewController: UIViewController { + + private let dataSource: PagingDataSource + private var pagingState: PagingState = .Current(0, PagingDirection.Forward) { + didSet { + switch pagingState { + case let .Current(index, _): + let indexPath = NSIndexPath(forItem: index, inSection: 0) + collectionView.selectItemAtIndexPath(indexPath, + animated: true, + scrollPosition: .CenteredHorizontally) + default: + collectionViewLayout.pagingState = pagingState + collectionViewLayout.invalidateLayout() + } + pagingContentViewController.pagingState = pagingState + } + } + + public init(viewControllers: [UIViewController]) { + self.dataSource = PagingDataSource(viewControllers: viewControllers) + super.init(nibName: nil, bundle: nil) + } + + required public init?(coder: NSCoder) { + fatalError(Error.InitCoder.rawValue) + } + + public override func viewDidLoad() { + super.viewDidLoad() + view.addSubview(collectionView) + addViewController(pagingContentViewController) + setupConstraints() + pagingContentViewController.setViewControllerForIndex(pagingState.currentIndex, + direction: .Forward, + animated: false) + } + + // MARK: Private + + private func setupConstraints() { + constrain(view, collectionView, pagingContentViewController.view) { view, collectionView, pagingContentViewController in + collectionView.height == 50 + collectionView.left == view.left + collectionView.right == view.right + collectionView.top == view.top + 20 + + pagingContentViewController.top == collectionView.bottom + pagingContentViewController.left == view.left + pagingContentViewController.right == view.right + pagingContentViewController.bottom == view.bottom + } + } + + + + // MARK: Lazy Getters + + private lazy var collectionViewLayout: PagingCollectionViewLayout = { + return PagingCollectionViewLayout(pagingState: self.pagingState) + }() + + private lazy var collectionView: UICollectionView = { + let collectionView = UICollectionView(frame: .zero, collectionViewLayout: self.collectionViewLayout) + collectionView.register(PagingCell.self) + collectionView.dataSource = self.dataSource + collectionView.delegate = self + collectionView.backgroundColor = UIColor.greenColor() + return collectionView + }() + + private lazy var pagingContentViewController: PagingContentViewController = { + let pagingContentViewController = PagingContentViewController(dataSource: self.dataSource, pagingState: self.pagingState) + pagingContentViewController.delegate = self + return pagingContentViewController + }() + +} + +extension PagingViewController: UICollectionViewDelegateFlowLayout { + + public func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) { + let direction = pagingState.directionForUpcomingIndex(indexPath.row) + pagingContentViewController.setViewControllerForIndex(indexPath.row, direction: direction, animated: true) + } + + public func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize { + if indexPath.row % 2 == 0 { + return CGSize(width: 100, height: 50) + } else { + return CGSize(width: 150, height: 50) + } + } + +} + +extension PagingViewController: PagingContentViewControllerDelegate { + + func pagingContentViewController(pagingContentViewController: PagingContentViewController, didChangeOffset offset: CGFloat, towardsIndex upcomingIndex: Int) { + let currentIndex = self.pagingState.currentIndex + if upcomingIndex > currentIndex { + self.pagingState = .Next(currentIndex, upcomingIndex, offset) + } else if upcomingIndex < currentIndex { + self.pagingState = .Previous(currentIndex, upcomingIndex, fabs(offset)) + } + } + + func pagingContentViewController(pagingContentViewController: PagingContentViewController, didMoveToIndex index: Int) { + pagingState = .Current(index, self.pagingState.directionForUpcomingIndex(index)) + } + +} diff --git a/Parchment/Parchment.h b/Parchment/Parchment.h new file mode 100644 index 00000000..1e8d2d83 --- /dev/null +++ b/Parchment/Parchment.h @@ -0,0 +1,19 @@ +// +// Parchment.h +// Parchment +// +// Created by Martin on 2016-01-23. +// Copyright © 2016 Martin Rechsteiner. All rights reserved. +// + +#import + +//! Project version number for Parchment. +FOUNDATION_EXPORT double ParchmentVersionNumber; + +//! Project version string for Parchment. +FOUNDATION_EXPORT const unsigned char ParchmentVersionString[]; + +// In this header, you should import all the public headers of your framework using statements like #import + + diff --git a/Parchment/Protocols/ReusableView.swift b/Parchment/Protocols/ReusableView.swift new file mode 100644 index 00000000..28ef23e5 --- /dev/null +++ b/Parchment/Protocols/ReusableView.swift @@ -0,0 +1,13 @@ +import UIKit + +protocol ReusableView: class { + static var defaultReuseIdentifier: String { get } +} + +extension ReusableView where Self: UIView { + static var defaultReuseIdentifier: String { + return NSStringFromClass(self) + } +} + +extension UICollectionReusableView: ReusableView {} diff --git a/Parchment/Tween.swift b/Parchment/Tween.swift new file mode 100644 index 00000000..f7804d07 --- /dev/null +++ b/Parchment/Tween.swift @@ -0,0 +1,5 @@ +import Foundation + +func tween(from from: T, to: T, progress: T) -> T { + return ((to - from) * progress) + from +} diff --git a/Parchment/UIViewController.swift b/Parchment/UIViewController.swift new file mode 100644 index 00000000..358b706e --- /dev/null +++ b/Parchment/UIViewController.swift @@ -0,0 +1,11 @@ +import UIKit + +extension UIViewController { + + func addViewController(viewController: UIViewController) { + addChildViewController(viewController) + view.addSubview(viewController.view) + viewController.didMoveToParentViewController(self) + } + +}