diff --git a/Package.swift b/Package.swift
index 88e4ddfc..dd6ee33a 100644
--- a/Package.swift
+++ b/Package.swift
@@ -1,17 +1,25 @@
-// swift-tools-version:4.0
+// swift-tools-version:5.3
// The swift-tools-version declares the minimum version of Swift required to build this package.
import PackageDescription
let package = Package(
name: "JTAppleCalendar",
+ platforms: [
+ .iOS(.v12),
+ ],
products: [
- .library(name: "JTAppleCalendar", targets: ["JTAppleCalendar"])
- ],
- targets: [
- .target(
- name: "JTAppleCalendar",
- path: "Sources"
- )
- ]
+ .library(
+ name: "JTAppleCalendar",
+ targets: ["JTAppleCalendar"]),
+ ],
+ targets: [
+ .target(
+ name: "JTAppleCalendar",
+ dependencies: [],
+ resources: [.copy("PrivacyInfo.xcprivacy")]),
+ .testTarget(
+ name: "JTAppleCalendarTests",
+ dependencies: ["JTAppleCalendar"]),
+ ]
)
diff --git a/README.md b/README.md
index be640740..7ac9c899 100644
--- a/README.md
+++ b/README.md
@@ -1,8 +1,9 @@
[](https://github.com/patchthecode/JTAppleCalendar)
-[](https://patchthecode.com/) [](http://cocoapods.org/pods/JTAppleCalendar) [](https://github.com/Carthage/Carthage) [](http://cocoapods.org/pods/JTAppleCalendar) [](http://cocoapods.org/pods/JTAppleCalendar) [](https://github.com/patchthecode/JTAppleCalendar/wiki/Support) [](#backers) [](#sponsors)
+[](http://cocoapods.org/pods/JTAppleCalendar) [](https://github.com/Carthage/Carthage) [](http://cocoapods.org/pods/JTAppleCalendar) [](http://cocoapods.org/pods/JTAppleCalendar) [](https://github.com/patchthecode/JTAppleCalendar/wiki/Support) [](#backers) [](#sponsors) [](https://www.codetriage.com/patchthecode/jtapplecalendar)
#### Q: How will my calendar dateCells look with this library?
+
**A**: However you want them to look.
@@ -14,55 +15,52 @@
More Images
-
## Features
+
---
- [x] Range selection - select dates in a range. The design is entirely up to you.
- [x] Boundary dates - limit the calendar date range
-- [x] Week/month mode - show 1 row of weekdays. Or 2, 3 or 6
+- [x] [Week/month mode](./docs/switch-month-to-week-view/Switch%20between%20month-view%20and%20week-view.md) - show 1 row of weekdays. Or 2, 3 or 6
- [x] Custom cells - make your day-cells look however you want, with any functionality you want
- [x] Custom calendar view - make your calendar look however you want, with what ever functionality you want
- [x] First Day of week - pick anyday to be first day of the week
- [x] Horizontal or vertical mode
-- [x] Ability to add month headers in varying sizes/styles of your liking
+- [x] Ability to add [month headers](./docs/headers/Headers.md) in varying sizes/styles of your liking
- [x] Ability to scroll to any month by simply using the date
- [x] Ability to design your calendar [however you want.](https://github.com/patchthecode/JTAppleCalendar/issues/2) You want it, you build it
-___
-
-## How do I use this library?
-### >> [Read the wiki](https://github.com/patchthecode/JTAppleCalendar/wiki/Tutorials) for Tutorials and example code to download. Or visit [PatchTheCode.com](https://patchthecode.com).
-___
-
-## Contributors
-This project exists thanks to all the people who contribute. [[Contribute](CONTRIBUTING.md)].
-
+---
+## How do I use this library?
-## Backers
+> [!WARNING]
+> The wiki currently links to an external site that is down. It is recommended to [view the docs](./docs/get-started/Get%20Started.md) at this time, but be aware they may not be up to date currently
-Thank you to all our backers! 🙏 [[Become a backer](https://opencollective.com/JTAppleCalendar#backer)]
+### >> [Read the wiki](https://github.com/patchthecode/JTAppleCalendar/wiki/Tutorials) for Tutorials and example code to download or [view the docs](./docs/get-started/Get%20Started.md)
-
+## [Version 8.0.0 migration guide](./docs/migration-guide/v8%20Migration%20Guide.md)
+---
## Sponsors
-Support this project by becoming a sponsor. Your logo will show up here with a link to your website. [[Become a sponsor](https://opencollective.com/JTAppleCalendar#sponsor)]
+Support this project by becoming a sponsor. Your logo will show up here with a link to your website.
+Want to become a sponsor? Send an email to patchthecode@gmail.com
-
-
-
-
-
-
-
-
+## Contributors
+
+This project exists thanks to all the people who contribute. [[Contribute](CONTRIBUTING.md)].
+
+## Backers
+
+Thank you to all our backers! 🙏 [[Become a backer](https://opencollective.com/JTAppleCalendar#backer)]
+
+
## License
diff --git a/SampleJTAppleCalendar.xcodeproj/project.pbxproj b/SampleJTAppleCalendar.xcodeproj/project.pbxproj
new file mode 100644
index 00000000..d2dd99ef
--- /dev/null
+++ b/SampleJTAppleCalendar.xcodeproj/project.pbxproj
@@ -0,0 +1,611 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 52;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ 6B4E465422C202DD00D0F78E /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6B4E465322C202DD00D0F78E /* AppDelegate.swift */; };
+ 6B4E465622C202DD00D0F78E /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6B4E465522C202DD00D0F78E /* SceneDelegate.swift */; };
+ 6B4E465D22C202DF00D0F78E /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6B4E465C22C202DF00D0F78E /* Assets.xcassets */; };
+ 6B4E466022C202DF00D0F78E /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6B4E465E22C202DF00D0F78E /* LaunchScreen.storyboard */; };
+ 6B4E468822C2150100D0F78E /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6B4E468222C2150100D0F78E /* ViewController.swift */; };
+ 6B4E468922C2150100D0F78E /* TestRangeSelectionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6B4E468322C2150100D0F78E /* TestRangeSelectionViewController.swift */; };
+ 6B4E468A22C2150100D0F78E /* TestViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6B4E468422C2150100D0F78E /* TestViewController.swift */; };
+ 6B4E468B22C2150100D0F78E /* TestOrientationChanges.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6B4E468522C2150100D0F78E /* TestOrientationChanges.swift */; };
+ 6B4E468C22C2150100D0F78E /* TestYearViewViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6B4E468622C2150100D0F78E /* TestYearViewViewController.swift */; };
+ 6B4E468D22C2150100D0F78E /* TestPersianCalendar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6B4E468722C2150100D0F78E /* TestPersianCalendar.swift */; };
+ 6B4E469422C2151500D0F78E /* CodeCellView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6B4E469022C2151500D0F78E /* CodeCellView.swift */; };
+ 6B4E469522C2151500D0F78E /* CellView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6B4E469222C2151500D0F78E /* CellView.swift */; };
+ 6B4E469622C2151500D0F78E /* CellView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6B4E469322C2151500D0F78E /* CellView.xib */; };
+ 6B4E46A022C2151E00D0F78E /* CodeWhiteSectionHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6B4E469922C2151E00D0F78E /* CodeWhiteSectionHeaderView.swift */; };
+ 6B4E46A122C2151E00D0F78E /* CodePinkSectionHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6B4E469A22C2151E00D0F78E /* CodePinkSectionHeaderView.swift */; };
+ 6B4E46A222C2151E00D0F78E /* WhiteSectionHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6B4E469C22C2151E00D0F78E /* WhiteSectionHeaderView.swift */; };
+ 6B4E46A322C2151E00D0F78E /* PinkSectionHeaderView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6B4E469D22C2151E00D0F78E /* PinkSectionHeaderView.xib */; };
+ 6B4E46A422C2151E00D0F78E /* PinkSectionHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6B4E469E22C2151E00D0F78E /* PinkSectionHeaderView.swift */; };
+ 6B4E46A522C2151E00D0F78E /* WhiteSectionHeaderView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6B4E469F22C2151E00D0F78E /* WhiteSectionHeaderView.xib */; };
+ 6B4E46E622C2174C00D0F78E /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6B4E46E522C2174C00D0F78E /* Main.storyboard */; };
+ 6BBDD4DF22E3E7FF001BE4E0 /* JTAppleCalendar in Frameworks */ = {isa = PBXBuildFile; productRef = 6BBDD4DE22E3E7FF001BE4E0 /* JTAppleCalendar */; };
+ 6BE6BE5C23807BA600148D6E /* SampleJTAppleCalendarUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6BE6BE5B23807BA600148D6E /* SampleJTAppleCalendarUITests.swift */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXContainerItemProxy section */
+ 6BE6BE5E23807BA600148D6E /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 6B4E464822C202DD00D0F78E /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 6B4E464F22C202DD00D0F78E;
+ remoteInfo = SampleJTAppleCalendar;
+ };
+/* End PBXContainerItemProxy section */
+
+/* Begin PBXFileReference section */
+ 6B4E465022C202DD00D0F78E /* SampleJTAppleCalendar.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SampleJTAppleCalendar.app; sourceTree = BUILT_PRODUCTS_DIR; };
+ 6B4E465322C202DD00D0F78E /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
+ 6B4E465522C202DD00D0F78E /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; };
+ 6B4E465C22C202DF00D0F78E /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
+ 6B4E465F22C202DF00D0F78E /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
+ 6B4E466122C202DF00D0F78E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
+ 6B4E466722C202FB00D0F78E /* JTAppleCalendar */ = {isa = PBXFileReference; lastKnownFileType = folder; name = JTAppleCalendar; path = ../JTAppleCalendar; sourceTree = ""; };
+ 6B4E468222C2150100D0F78E /* ViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; };
+ 6B4E468322C2150100D0F78E /* TestRangeSelectionViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestRangeSelectionViewController.swift; sourceTree = ""; };
+ 6B4E468422C2150100D0F78E /* TestViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestViewController.swift; sourceTree = ""; };
+ 6B4E468522C2150100D0F78E /* TestOrientationChanges.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestOrientationChanges.swift; sourceTree = ""; };
+ 6B4E468622C2150100D0F78E /* TestYearViewViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestYearViewViewController.swift; sourceTree = ""; };
+ 6B4E468722C2150100D0F78E /* TestPersianCalendar.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestPersianCalendar.swift; sourceTree = ""; };
+ 6B4E469022C2151500D0F78E /* CodeCellView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CodeCellView.swift; sourceTree = ""; };
+ 6B4E469222C2151500D0F78E /* CellView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CellView.swift; sourceTree = ""; };
+ 6B4E469322C2151500D0F78E /* CellView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = CellView.xib; sourceTree = ""; };
+ 6B4E469922C2151E00D0F78E /* CodeWhiteSectionHeaderView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CodeWhiteSectionHeaderView.swift; sourceTree = ""; };
+ 6B4E469A22C2151E00D0F78E /* CodePinkSectionHeaderView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CodePinkSectionHeaderView.swift; sourceTree = ""; };
+ 6B4E469C22C2151E00D0F78E /* WhiteSectionHeaderView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WhiteSectionHeaderView.swift; sourceTree = ""; };
+ 6B4E469D22C2151E00D0F78E /* PinkSectionHeaderView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = PinkSectionHeaderView.xib; sourceTree = ""; };
+ 6B4E469E22C2151E00D0F78E /* PinkSectionHeaderView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PinkSectionHeaderView.swift; sourceTree = ""; };
+ 6B4E469F22C2151E00D0F78E /* WhiteSectionHeaderView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = WhiteSectionHeaderView.xib; sourceTree = ""; };
+ 6B4E46E522C2174C00D0F78E /* Main.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = Main.storyboard; sourceTree = ""; };
+ 6BE6BE5923807BA600148D6E /* SampleJTAppleCalendarUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SampleJTAppleCalendarUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
+ 6BE6BE5B23807BA600148D6E /* SampleJTAppleCalendarUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SampleJTAppleCalendarUITests.swift; sourceTree = ""; };
+ 6BE6BE5D23807BA600148D6E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ 6B4E464D22C202DD00D0F78E /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 6BBDD4DF22E3E7FF001BE4E0 /* JTAppleCalendar in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 6BE6BE5623807BA600148D6E /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 6B4E464722C202DD00D0F78E = {
+ isa = PBXGroup;
+ children = (
+ 6B4E466722C202FB00D0F78E /* JTAppleCalendar */,
+ 6B4E465222C202DD00D0F78E /* SampleJTAppleCalendar */,
+ 6BE6BE5A23807BA600148D6E /* SampleJTAppleCalendarUITests */,
+ 6B4E465122C202DD00D0F78E /* Products */,
+ 6B4E466822C2032B00D0F78E /* Frameworks */,
+ );
+ sourceTree = "";
+ };
+ 6B4E465122C202DD00D0F78E /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 6B4E465022C202DD00D0F78E /* SampleJTAppleCalendar.app */,
+ 6BE6BE5923807BA600148D6E /* SampleJTAppleCalendarUITests.xctest */,
+ );
+ name = Products;
+ sourceTree = "";
+ };
+ 6B4E465222C202DD00D0F78E /* SampleJTAppleCalendar */ = {
+ isa = PBXGroup;
+ children = (
+ 6B4E46E522C2174C00D0F78E /* Main.storyboard */,
+ 6B4E468122C2150100D0F78E /* Example Calendars */,
+ 6B4E468E22C2151500D0F78E /* ExampleDateCells */,
+ 6B4E469722C2151E00D0F78E /* ExampleSectionHeaders */,
+ 6B4E465322C202DD00D0F78E /* AppDelegate.swift */,
+ 6B4E465522C202DD00D0F78E /* SceneDelegate.swift */,
+ 6B4E465C22C202DF00D0F78E /* Assets.xcassets */,
+ 6B4E465E22C202DF00D0F78E /* LaunchScreen.storyboard */,
+ 6B4E466122C202DF00D0F78E /* Info.plist */,
+ );
+ path = SampleJTAppleCalendar;
+ sourceTree = "";
+ };
+ 6B4E466822C2032B00D0F78E /* Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ );
+ name = Frameworks;
+ sourceTree = "";
+ };
+ 6B4E468122C2150100D0F78E /* Example Calendars */ = {
+ isa = PBXGroup;
+ children = (
+ 6B4E468222C2150100D0F78E /* ViewController.swift */,
+ 6B4E468322C2150100D0F78E /* TestRangeSelectionViewController.swift */,
+ 6B4E468422C2150100D0F78E /* TestViewController.swift */,
+ 6B4E468522C2150100D0F78E /* TestOrientationChanges.swift */,
+ 6B4E468622C2150100D0F78E /* TestYearViewViewController.swift */,
+ 6B4E468722C2150100D0F78E /* TestPersianCalendar.swift */,
+ );
+ path = "Example Calendars";
+ sourceTree = "";
+ };
+ 6B4E468E22C2151500D0F78E /* ExampleDateCells */ = {
+ isa = PBXGroup;
+ children = (
+ 6B4E468F22C2151500D0F78E /* DateCellCreatedWithCode */,
+ 6B4E469122C2151500D0F78E /* DateCellCreatedWithXIB */,
+ );
+ path = ExampleDateCells;
+ sourceTree = "";
+ };
+ 6B4E468F22C2151500D0F78E /* DateCellCreatedWithCode */ = {
+ isa = PBXGroup;
+ children = (
+ 6B4E469022C2151500D0F78E /* CodeCellView.swift */,
+ );
+ path = DateCellCreatedWithCode;
+ sourceTree = "";
+ };
+ 6B4E469122C2151500D0F78E /* DateCellCreatedWithXIB */ = {
+ isa = PBXGroup;
+ children = (
+ 6B4E469222C2151500D0F78E /* CellView.swift */,
+ 6B4E469322C2151500D0F78E /* CellView.xib */,
+ );
+ path = DateCellCreatedWithXIB;
+ sourceTree = "";
+ };
+ 6B4E469722C2151E00D0F78E /* ExampleSectionHeaders */ = {
+ isa = PBXGroup;
+ children = (
+ 6B4E469822C2151E00D0F78E /* HeaderAsClass */,
+ 6B4E469B22C2151E00D0F78E /* HeaderAsXibs */,
+ );
+ path = ExampleSectionHeaders;
+ sourceTree = "";
+ };
+ 6B4E469822C2151E00D0F78E /* HeaderAsClass */ = {
+ isa = PBXGroup;
+ children = (
+ 6B4E469922C2151E00D0F78E /* CodeWhiteSectionHeaderView.swift */,
+ 6B4E469A22C2151E00D0F78E /* CodePinkSectionHeaderView.swift */,
+ );
+ path = HeaderAsClass;
+ sourceTree = "";
+ };
+ 6B4E469B22C2151E00D0F78E /* HeaderAsXibs */ = {
+ isa = PBXGroup;
+ children = (
+ 6B4E469C22C2151E00D0F78E /* WhiteSectionHeaderView.swift */,
+ 6B4E469D22C2151E00D0F78E /* PinkSectionHeaderView.xib */,
+ 6B4E469E22C2151E00D0F78E /* PinkSectionHeaderView.swift */,
+ 6B4E469F22C2151E00D0F78E /* WhiteSectionHeaderView.xib */,
+ );
+ path = HeaderAsXibs;
+ sourceTree = "";
+ };
+ 6BE6BE5A23807BA600148D6E /* SampleJTAppleCalendarUITests */ = {
+ isa = PBXGroup;
+ children = (
+ 6BE6BE5B23807BA600148D6E /* SampleJTAppleCalendarUITests.swift */,
+ 6BE6BE5D23807BA600148D6E /* Info.plist */,
+ );
+ path = SampleJTAppleCalendarUITests;
+ sourceTree = "";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+ 6B4E464F22C202DD00D0F78E /* SampleJTAppleCalendar */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 6B4E466422C202DF00D0F78E /* Build configuration list for PBXNativeTarget "SampleJTAppleCalendar" */;
+ buildPhases = (
+ 6B4E464C22C202DD00D0F78E /* Sources */,
+ 6B4E464D22C202DD00D0F78E /* Frameworks */,
+ 6B4E464E22C202DD00D0F78E /* Resources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = SampleJTAppleCalendar;
+ packageProductDependencies = (
+ 6BBDD4DE22E3E7FF001BE4E0 /* JTAppleCalendar */,
+ );
+ productName = SampleJTAppleCalendar;
+ productReference = 6B4E465022C202DD00D0F78E /* SampleJTAppleCalendar.app */;
+ productType = "com.apple.product-type.application";
+ };
+ 6BE6BE5823807BA600148D6E /* SampleJTAppleCalendarUITests */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 6BE6BE6223807BA600148D6E /* Build configuration list for PBXNativeTarget "SampleJTAppleCalendarUITests" */;
+ buildPhases = (
+ 6BE6BE5523807BA600148D6E /* Sources */,
+ 6BE6BE5623807BA600148D6E /* Frameworks */,
+ 6BE6BE5723807BA600148D6E /* Resources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ 6BE6BE5F23807BA600148D6E /* PBXTargetDependency */,
+ );
+ name = SampleJTAppleCalendarUITests;
+ productName = SampleJTAppleCalendarUITests;
+ productReference = 6BE6BE5923807BA600148D6E /* SampleJTAppleCalendarUITests.xctest */;
+ productType = "com.apple.product-type.bundle.ui-testing";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ 6B4E464822C202DD00D0F78E /* Project object */ = {
+ isa = PBXProject;
+ attributes = {
+ LastSwiftUpdateCheck = 1110;
+ LastUpgradeCheck = 1100;
+ ORGANIZATIONNAME = OsTech;
+ TargetAttributes = {
+ 6B4E464F22C202DD00D0F78E = {
+ CreatedOnToolsVersion = 11.0;
+ };
+ 6BE6BE5823807BA600148D6E = {
+ CreatedOnToolsVersion = 11.1;
+ TestTargetID = 6B4E464F22C202DD00D0F78E;
+ };
+ };
+ };
+ buildConfigurationList = 6B4E464B22C202DD00D0F78E /* Build configuration list for PBXProject "SampleJTAppleCalendar" */;
+ compatibilityVersion = "Xcode 9.3";
+ developmentRegion = en;
+ hasScannedForEncodings = 0;
+ knownRegions = (
+ en,
+ Base,
+ );
+ mainGroup = 6B4E464722C202DD00D0F78E;
+ packageReferences = (
+ 6BBDD4DD22E3E7FF001BE4E0 /* XCRemoteSwiftPackageReference "JTAppleCalendar" */,
+ );
+ productRefGroup = 6B4E465122C202DD00D0F78E /* Products */;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ 6B4E464F22C202DD00D0F78E /* SampleJTAppleCalendar */,
+ 6BE6BE5823807BA600148D6E /* SampleJTAppleCalendarUITests */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+ 6B4E464E22C202DD00D0F78E /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 6B4E46E622C2174C00D0F78E /* Main.storyboard in Resources */,
+ 6B4E469622C2151500D0F78E /* CellView.xib in Resources */,
+ 6B4E46A522C2151E00D0F78E /* WhiteSectionHeaderView.xib in Resources */,
+ 6B4E466022C202DF00D0F78E /* LaunchScreen.storyboard in Resources */,
+ 6B4E465D22C202DF00D0F78E /* Assets.xcassets in Resources */,
+ 6B4E46A322C2151E00D0F78E /* PinkSectionHeaderView.xib in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 6BE6BE5723807BA600148D6E /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+ 6B4E464C22C202DD00D0F78E /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 6B4E469422C2151500D0F78E /* CodeCellView.swift in Sources */,
+ 6B4E46A222C2151E00D0F78E /* WhiteSectionHeaderView.swift in Sources */,
+ 6B4E468D22C2150100D0F78E /* TestPersianCalendar.swift in Sources */,
+ 6B4E468B22C2150100D0F78E /* TestOrientationChanges.swift in Sources */,
+ 6B4E468C22C2150100D0F78E /* TestYearViewViewController.swift in Sources */,
+ 6B4E46A422C2151E00D0F78E /* PinkSectionHeaderView.swift in Sources */,
+ 6B4E468A22C2150100D0F78E /* TestViewController.swift in Sources */,
+ 6B4E468822C2150100D0F78E /* ViewController.swift in Sources */,
+ 6B4E46A022C2151E00D0F78E /* CodeWhiteSectionHeaderView.swift in Sources */,
+ 6B4E469522C2151500D0F78E /* CellView.swift in Sources */,
+ 6B4E46A122C2151E00D0F78E /* CodePinkSectionHeaderView.swift in Sources */,
+ 6B4E465422C202DD00D0F78E /* AppDelegate.swift in Sources */,
+ 6B4E465622C202DD00D0F78E /* SceneDelegate.swift in Sources */,
+ 6B4E468922C2150100D0F78E /* TestRangeSelectionViewController.swift in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 6BE6BE5523807BA600148D6E /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 6BE6BE5C23807BA600148D6E /* SampleJTAppleCalendarUITests.swift in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXTargetDependency section */
+ 6BE6BE5F23807BA600148D6E /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 6B4E464F22C202DD00D0F78E /* SampleJTAppleCalendar */;
+ targetProxy = 6BE6BE5E23807BA600148D6E /* PBXContainerItemProxy */;
+ };
+/* End PBXTargetDependency section */
+
+/* Begin PBXVariantGroup section */
+ 6B4E465E22C202DF00D0F78E /* LaunchScreen.storyboard */ = {
+ isa = PBXVariantGroup;
+ children = (
+ 6B4E465F22C202DF00D0F78E /* Base */,
+ );
+ name = LaunchScreen.storyboard;
+ sourceTree = "";
+ };
+/* End PBXVariantGroup section */
+
+/* Begin XCBuildConfiguration section */
+ 6B4E466222C202DF00D0F78E /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ 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_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 = (
+ "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 = 13.0;
+ MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
+ MTL_FAST_MATH = YES;
+ ONLY_ACTIVE_ARCH = YES;
+ SDKROOT = iphoneos;
+ SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
+ SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+ };
+ name = Debug;
+ };
+ 6B4E466322C202DF00D0F78E /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ 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_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_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 = 13.0;
+ MTL_ENABLE_DEBUG_INFO = NO;
+ MTL_FAST_MATH = YES;
+ SDKROOT = iphoneos;
+ SWIFT_COMPILATION_MODE = wholemodule;
+ SWIFT_OPTIMIZATION_LEVEL = "-O";
+ VALIDATE_PRODUCT = YES;
+ };
+ name = Release;
+ };
+ 6B4E466522C202DF00D0F78E /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CODE_SIGN_STYLE = Automatic;
+ DEVELOPMENT_TEAM = WE23L742P8;
+ INFOPLIST_FILE = SampleJTAppleCalendar/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = com.Ostech.SampleJTAppleCalendar;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SWIFT_VERSION = 5.0;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Debug;
+ };
+ 6B4E466622C202DF00D0F78E /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CODE_SIGN_STYLE = Automatic;
+ DEVELOPMENT_TEAM = WE23L742P8;
+ INFOPLIST_FILE = SampleJTAppleCalendar/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = com.Ostech.SampleJTAppleCalendar;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SWIFT_VERSION = 5.0;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Release;
+ };
+ 6BE6BE6023807BA600148D6E /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CODE_SIGN_STYLE = Automatic;
+ DEVELOPMENT_TEAM = WE23L742P8;
+ INFOPLIST_FILE = SampleJTAppleCalendarUITests/Info.plist;
+ IPHONEOS_DEPLOYMENT_TARGET = 13.1;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ "@loader_path/Frameworks",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = NoneInc.SampleJTAppleCalendarUITests;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SWIFT_VERSION = 5.0;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ TEST_TARGET_NAME = SampleJTAppleCalendar;
+ };
+ name = Debug;
+ };
+ 6BE6BE6123807BA600148D6E /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CODE_SIGN_STYLE = Automatic;
+ DEVELOPMENT_TEAM = WE23L742P8;
+ INFOPLIST_FILE = SampleJTAppleCalendarUITests/Info.plist;
+ IPHONEOS_DEPLOYMENT_TARGET = 13.1;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ "@loader_path/Frameworks",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = NoneInc.SampleJTAppleCalendarUITests;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SWIFT_VERSION = 5.0;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ TEST_TARGET_NAME = SampleJTAppleCalendar;
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ 6B4E464B22C202DD00D0F78E /* Build configuration list for PBXProject "SampleJTAppleCalendar" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 6B4E466222C202DF00D0F78E /* Debug */,
+ 6B4E466322C202DF00D0F78E /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 6B4E466422C202DF00D0F78E /* Build configuration list for PBXNativeTarget "SampleJTAppleCalendar" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 6B4E466522C202DF00D0F78E /* Debug */,
+ 6B4E466622C202DF00D0F78E /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 6BE6BE6223807BA600148D6E /* Build configuration list for PBXNativeTarget "SampleJTAppleCalendarUITests" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 6BE6BE6023807BA600148D6E /* Debug */,
+ 6BE6BE6123807BA600148D6E /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+
+/* Begin XCRemoteSwiftPackageReference section */
+ 6BBDD4DD22E3E7FF001BE4E0 /* XCRemoteSwiftPackageReference "JTAppleCalendar" */ = {
+ isa = XCRemoteSwiftPackageReference;
+ repositoryURL = "https://github.com/patchthecode/JTAppleCalendar";
+ requirement = {
+ kind = upToNextMajorVersion;
+ minimumVersion = 8.0.1;
+ };
+ };
+/* End XCRemoteSwiftPackageReference section */
+
+/* Begin XCSwiftPackageProductDependency section */
+ 6BBDD4DE22E3E7FF001BE4E0 /* JTAppleCalendar */ = {
+ isa = XCSwiftPackageProductDependency;
+ package = 6BBDD4DD22E3E7FF001BE4E0 /* XCRemoteSwiftPackageReference "JTAppleCalendar" */;
+ productName = JTAppleCalendar;
+ };
+/* End XCSwiftPackageProductDependency section */
+ };
+ rootObject = 6B4E464822C202DD00D0F78E /* Project object */;
+}
diff --git a/SampleJTAppleCalendar.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/SampleJTAppleCalendar.xcodeproj/project.xcworkspace/contents.xcworkspacedata
new file mode 100644
index 00000000..919434a6
--- /dev/null
+++ b/SampleJTAppleCalendar.xcodeproj/project.xcworkspace/contents.xcworkspacedata
@@ -0,0 +1,7 @@
+
+
+
+
+
diff --git a/SampleJTAppleCalendar.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/SampleJTAppleCalendar.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
new file mode 100644
index 00000000..18d98100
--- /dev/null
+++ b/SampleJTAppleCalendar.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
@@ -0,0 +1,8 @@
+
+
+
+
+ IDEDidComputeMac32BitWarning
+
+
+
diff --git a/JTAppleCalendar.xcodeproj/xcshareddata/xcschemes/JTAppleCalendar tvOS Example.xcscheme b/SampleJTAppleCalendar.xcodeproj/xcshareddata/xcschemes/SampleJTAppleCalendar.xcscheme
similarity index 58%
rename from JTAppleCalendar.xcodeproj/xcshareddata/xcschemes/JTAppleCalendar tvOS Example.xcscheme
rename to SampleJTAppleCalendar.xcodeproj/xcshareddata/xcschemes/SampleJTAppleCalendar.xcscheme
index eb311a52..fe6da97d 100644
--- a/JTAppleCalendar.xcodeproj/xcshareddata/xcschemes/JTAppleCalendar tvOS Example.xcscheme
+++ b/SampleJTAppleCalendar.xcodeproj/xcshareddata/xcschemes/SampleJTAppleCalendar.xcscheme
@@ -1,6 +1,6 @@
+ BlueprintIdentifier = "6B4E464F22C202DD00D0F78E"
+ BuildableName = "SampleJTAppleCalendar.app"
+ BlueprintName = "SampleJTAppleCalendar"
+ ReferencedContainer = "container:SampleJTAppleCalendar.xcodeproj">
@@ -28,18 +28,17 @@
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
+
+
+
+
-
-
-
-
-
-
+ BlueprintIdentifier = "6B4E464F22C202DD00D0F78E"
+ BuildableName = "SampleJTAppleCalendar.app"
+ BlueprintName = "SampleJTAppleCalendar"
+ ReferencedContainer = "container:SampleJTAppleCalendar.xcodeproj">
-
-
-
-
-
-
+ BlueprintIdentifier = "6B4E464F22C202DD00D0F78E"
+ BuildableName = "SampleJTAppleCalendar.app"
+ BlueprintName = "SampleJTAppleCalendar"
+ ReferencedContainer = "container:SampleJTAppleCalendar.xcodeproj">
diff --git a/SampleJTAppleCalendar/AppDelegate.swift b/SampleJTAppleCalendar/AppDelegate.swift
new file mode 100644
index 00000000..ac0abfae
--- /dev/null
+++ b/SampleJTAppleCalendar/AppDelegate.swift
@@ -0,0 +1,41 @@
+//
+// AppDelegate.swift
+// SampleJTAppleCalendar
+//
+// Created by Jeron Thomas on 2019-06-25.
+// Copyright © 2019 OsTech. All rights reserved.
+//
+
+import UIKit
+
+@UIApplicationMain
+class AppDelegate: UIResponder, UIApplicationDelegate {
+
+
+
+ func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
+ // Override point for customization after application launch.
+ return true
+ }
+
+ func applicationWillTerminate(_ application: UIApplication) {
+ // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
+ }
+
+ // MARK: UISceneSession Lifecycle
+
+ func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
+ // Called when a new scene session is being created.
+ // Use this method to select a configuration to create the new scene with.
+ return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
+ }
+
+ func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set) {
+ // Called when the user discards a scene session.
+ // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
+ // Use this method to release any resources that were specific to the discarded scenes, as they will not return.
+ }
+
+
+}
+
diff --git a/SampleJTAppleCalendar/Assets.xcassets/AppIcon.appiconset/Contents.json b/SampleJTAppleCalendar/Assets.xcassets/AppIcon.appiconset/Contents.json
new file mode 100644
index 00000000..d8db8d65
--- /dev/null
+++ b/SampleJTAppleCalendar/Assets.xcassets/AppIcon.appiconset/Contents.json
@@ -0,0 +1,98 @@
+{
+ "images" : [
+ {
+ "idiom" : "iphone",
+ "size" : "20x20",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "20x20",
+ "scale" : "3x"
+ },
+ {
+ "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" : "20x20",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "20x20",
+ "scale" : "2x"
+ },
+ {
+ "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"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "83.5x83.5",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "ios-marketing",
+ "size" : "1024x1024",
+ "scale" : "1x"
+ }
+ ],
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+}
\ No newline at end of file
diff --git a/Example/JTAppleCalendar tvOS Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Back.imagestacklayer/Contents.json b/SampleJTAppleCalendar/Assets.xcassets/Contents.json
similarity index 100%
rename from Example/JTAppleCalendar tvOS Example/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Back.imagestacklayer/Contents.json
rename to SampleJTAppleCalendar/Assets.xcassets/Contents.json
diff --git a/SampleJTAppleCalendar/Assets.xcassets/cube.imageset/Contents.json b/SampleJTAppleCalendar/Assets.xcassets/cube.imageset/Contents.json
new file mode 100644
index 00000000..883a2587
--- /dev/null
+++ b/SampleJTAppleCalendar/Assets.xcassets/cube.imageset/Contents.json
@@ -0,0 +1,21 @@
+{
+ "images" : [
+ {
+ "idiom" : "universal",
+ "filename" : "cube.png",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "universal",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "universal",
+ "scale" : "3x"
+ }
+ ],
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+}
\ No newline at end of file
diff --git a/SampleJTAppleCalendar/Assets.xcassets/cube.imageset/cube.png b/SampleJTAppleCalendar/Assets.xcassets/cube.imageset/cube.png
new file mode 100644
index 00000000..473d0ce7
Binary files /dev/null and b/SampleJTAppleCalendar/Assets.xcassets/cube.imageset/cube.png differ
diff --git a/SampleJTAppleCalendar/Base.lproj/LaunchScreen.storyboard b/SampleJTAppleCalendar/Base.lproj/LaunchScreen.storyboard
new file mode 100644
index 00000000..865e9329
--- /dev/null
+++ b/SampleJTAppleCalendar/Base.lproj/LaunchScreen.storyboard
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Example/JTAppleCalendar iOS Example/Example Calendars/TestOrientationChanges.swift b/SampleJTAppleCalendar/Example Calendars/TestOrientationChanges.swift
similarity index 100%
rename from Example/JTAppleCalendar iOS Example/Example Calendars/TestOrientationChanges.swift
rename to SampleJTAppleCalendar/Example Calendars/TestOrientationChanges.swift
diff --git a/Example/JTAppleCalendar iOS Example/Example Calendars/TestPersianCalendar.swift b/SampleJTAppleCalendar/Example Calendars/TestPersianCalendar.swift
similarity index 100%
rename from Example/JTAppleCalendar iOS Example/Example Calendars/TestPersianCalendar.swift
rename to SampleJTAppleCalendar/Example Calendars/TestPersianCalendar.swift
diff --git a/Example/JTAppleCalendar iOS Example/Example Calendars/TestRangeSelectionViewController.swift b/SampleJTAppleCalendar/Example Calendars/TestRangeSelectionViewController.swift
similarity index 96%
rename from Example/JTAppleCalendar iOS Example/Example Calendars/TestRangeSelectionViewController.swift
rename to SampleJTAppleCalendar/Example Calendars/TestRangeSelectionViewController.swift
index d54c6289..423527e0 100644
--- a/Example/JTAppleCalendar iOS Example/Example Calendars/TestRangeSelectionViewController.swift
+++ b/SampleJTAppleCalendar/Example Calendars/TestRangeSelectionViewController.swift
@@ -47,7 +47,7 @@ class TestRangeSelectionViewController: UIViewController {
func handleCellSelection(cell: TestRangeSelectionViewControllerCell, cellState: CellState) {
cell.selectedView.isHidden = !cellState.isSelected
- if #available(iOS 11.0, *) {
+
switch cellState.selectedPosition() {
case .left:
cell.selectedView.layer.cornerRadius = 20
@@ -64,7 +64,7 @@ class TestRangeSelectionViewController: UIViewController {
default: break
}
- }
+
}
@@ -87,11 +87,11 @@ extension TestRangeSelectionViewController: JTACMonthViewDelegate, JTACMonthView
setupMonthLabel(date: visibleDates.monthDates.first!.date)
}
- func calendar(_ calendar: JTACMonthView, didSelectDate date: Date, cell: JTACDayCell?, cellState: CellState) {
+ func calendar(_ calendar: JTACMonthView, didSelectDate date: Date, cell: JTACDayCell?, cellState: CellState, indexPath: IndexPath) {
handleConfiguration(cell: cell, cellState: cellState)
}
- func calendar(_ calendar: JTACMonthView, didDeselectDate date: Date, cell: JTACDayCell?, cellState: CellState) {
+ func calendar(_ calendar: JTACMonthView, didDeselectDate date: Date, cell: JTACDayCell?, cellState: CellState, indexPath: IndexPath) {
handleConfiguration(cell: cell, cellState: cellState)
}
diff --git a/Example/JTAppleCalendar iOS Example/Example Calendars/TestViewController.swift b/SampleJTAppleCalendar/Example Calendars/TestViewController.swift
similarity index 100%
rename from Example/JTAppleCalendar iOS Example/Example Calendars/TestViewController.swift
rename to SampleJTAppleCalendar/Example Calendars/TestViewController.swift
diff --git a/Example/JTAppleCalendar iOS Example/Example Calendars/TestYearViewViewController.swift b/SampleJTAppleCalendar/Example Calendars/TestYearViewViewController.swift
similarity index 69%
rename from Example/JTAppleCalendar iOS Example/Example Calendars/TestYearViewViewController.swift
rename to SampleJTAppleCalendar/Example Calendars/TestYearViewViewController.swift
index d1b79396..af4d79f0 100644
--- a/Example/JTAppleCalendar iOS Example/Example Calendars/TestYearViewViewController.swift
+++ b/SampleJTAppleCalendar/Example Calendars/TestYearViewViewController.swift
@@ -6,19 +6,23 @@
//
import UIKit
+import JTAppleCalendar
class TestYearViewViewController: UIViewController {
@IBOutlet var calendarView: JTACYearView!
let f = DateFormatter()
override func viewDidLoad() {
+ calendarView.calendarDataSource = self
+ calendarView.calendarDelegate = self
super.viewDidLoad()
}
}
extension TestYearViewViewController: JTACYearViewDelegate, JTACYearViewDataSource {
- func calendar(_ calendar: JTACYearView, cellFor item: Any, at date: Date, indexPath: IndexPath) -> JTAppleMonthCell {
+ // Drawing for a whole month cell
+ func calendar(_ calendar: JTACYearView, cellFor item: Any, at date: Date, indexPath: IndexPath) -> JTACMonthCell {
if item is Month {
let cell = calendar.dequeueReusableJTAppleMonthCell(withReuseIdentifier: "kkk", for: indexPath) as! MyCell
f.dateFormat = "MMM"
@@ -64,13 +68,20 @@ extension TestYearViewViewController: JTACYearViewDelegate, JTACYearViewDataSour
return (configParams, modifiedDataSource)
}
-
- func calendar(_ calendar: JTACYearView, monthView: JTAppleMonthView, drawingFor rect: CGRect, with date: Date, dateOwner: DateOwner, monthIndex index: Int) -> (UIImage, CGRect)? {
+ // Drawing for individual item in a month cell.
+ func calendar(_ calendar: JTACYearView, monthView: JTACCellMonthView, drawingFor rect: CGRect, with date: Date, dateOwner: DateOwner, monthIndex index: Int) {
f.dateFormat = "d"
let dateString = f.string(from: date)
- let retval = (UIImage.text(dateString, rect: rect), rect)
- return retval
+
+ let paragraphStyle = NSMutableParagraphStyle()
+ let font = UIFont(name: "HelveticaNeue", size: 8)!
+
+ paragraphStyle.alignment = .center
+ dateString.draw(in: rect, withAttributes: [
+ NSAttributedString.Key.font : font,
+ NSAttributedString.Key.paragraphStyle: paragraphStyle
+ ])
}
func calendar(_ calendar: JTACYearView, sizeFor item: Any) -> CGSize {
@@ -87,35 +98,10 @@ extension TestYearViewViewController: JTACYearViewDelegate, JTACYearViewDataSour
}
-class MyCell: JTAppleMonthCell {
+class MyCell: JTACMonthCell {
@IBOutlet var monthLabel: UILabel!
}
-class YearHeaderCell: JTAppleMonthCell {
+class YearHeaderCell: JTACMonthCell {
@IBOutlet var yearLabel: UILabel!
}
-
-extension UIImage {
- class func text(_ text: String, rect: CGRect) -> UIImage {
- let renderer = UIGraphicsImageRenderer(bounds: rect)
- let img = renderer.image { ctx in
- // Draw a box around the cells.
- ctx.cgContext.addRect(rect)
- ctx.cgContext.drawPath(using: .stroke)
-
- // Draw text on the cell
- let fontSize: CGFloat
- if rect.width >= 17.0 { fontSize = 11.0 }
- else if rect.width >= 16.0 { fontSize = 10.0 }
- else { fontSize = 8.0 }
- let font = UIFont(name: "HelveticaNeue", size: fontSize)!
- let paragraphStyle = NSMutableParagraphStyle()
- paragraphStyle.alignment = .center
- text.draw(in: rect, withAttributes: [
- NSAttributedString.Key.font : font,
- NSAttributedString.Key.paragraphStyle: paragraphStyle
- ])
- }
- return img
- }
-}
diff --git a/Example/JTAppleCalendar iOS Example/Example Calendars/ViewController.swift b/SampleJTAppleCalendar/Example Calendars/ViewController.swift
similarity index 96%
rename from Example/JTAppleCalendar iOS Example/Example Calendars/ViewController.swift
rename to SampleJTAppleCalendar/Example Calendars/ViewController.swift
index 05a9c0d3..52102392 100644
--- a/Example/JTAppleCalendar iOS Example/Example Calendars/ViewController.swift
+++ b/SampleJTAppleCalendar/Example Calendars/ViewController.swift
@@ -6,10 +6,12 @@
//
//
+import UIKit
import JTAppleCalendar
class ViewController: UIViewController {
+ @IBOutlet weak var customColumn: UITextField!
@IBOutlet weak var calendarView: JTACMonthView!
@IBOutlet weak var monthLabel: UILabel!
@IBOutlet weak var weekViewStack: UIStackView!
@@ -32,7 +34,8 @@ class ViewController: UIViewController {
var insideHeaderVisibilityIsOn = false
var currentScrollModeIndex = 0
- let allScrollModes: [ScrollingMode] = [
+ var hhh: CGFloat?
+ var allScrollModes: [ScrollingMode] = [
.none,
.nonStopTo(customInterval: 374, withResistance: 0.5),
.nonStopToCell(withResistance: 0.5),
@@ -199,7 +202,8 @@ class ViewController: UIViewController {
withReuseIdentifier: "PinkSectionHeaderView")
// calendarView.allowsMultipleSelection = true
-// calendarView.allowsMultipleSelection = true
+ calendarView.scrollToDate(Date())
+ calendarView.selectDates([Date()])
self.calendarView.visibleDates {[unowned self] (visibleDates: DateSegmentInfo) in
self.setupViewsOfCalendar(from: visibleDates)
@@ -254,12 +258,12 @@ class ViewController: UIViewController {
)
let date = calendarView.visibleDates().monthDates.first!.date
- calendarView.reloadData(withanchor: date)
+ calendarView.reloadData(withAnchor: date)
}
@IBAction func reloadCalendar(_ sender: UIButton) {
let date = Date()
- calendarView.reloadData(withanchor: date)
+ calendarView.reloadData(withAnchor: date)
}
@IBAction func next(_ sender: UIButton) {
@@ -287,21 +291,21 @@ class ViewController: UIViewController {
prePostVisibility?(cellState, cell as? CellView)
}
+
// Function to handle the text color of the calendar
func handleCellTextColor(view: JTACDayCell?, cellState: CellState) {
guard let myCustomCell = view as? CellView else {
return
}
-
+
if cellState.isSelected {
myCustomCell.dayLabel.textColor = .white
} else {
- if cellState.dateBelongsTo == .thisMonth {
- myCustomCell.dayLabel.textColor = .black
- } else {
- myCustomCell.dayLabel.textColor = .gray
- }
+ myCustomCell.dayLabel.textColor = .black
}
+
+ myCustomCell.isHidden = cellState.dateBelongsTo != .thisMonth
+
}
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
@@ -368,7 +372,7 @@ extension ViewController: JTACMonthViewDelegate, JTACMonthViewDataSource {
let startDate = formatter.date(from: "2018 01 01")!
- let endDate = formatter.date(from: "2018 12 01")!
+ let endDate = formatter.date(from: "2020 12 01")!
let parameters = ConfigurationParameters(startDate: startDate,
endDate: endDate,
@@ -376,7 +380,7 @@ extension ViewController: JTACMonthViewDelegate, JTACMonthViewDataSource {
calendar: testCalendar,
generateInDates: generateInDates,
generateOutDates: generateOutDates,
- firstDayOfWeek: .monday,
+ firstDayOfWeek: .sunday,
hasStrictBoundaries: hasStrictBoundaries)
return parameters
}
@@ -414,11 +418,11 @@ extension ViewController: JTACMonthViewDelegate, JTACMonthViewDataSource {
return myCustomCell
}
- func calendar(_ calendar: JTACMonthView, didDeselectDate date: Date, cell: JTACDayCell?, cellState: CellState) {
+ func calendar(_ calendar: JTACMonthView, didDeselectDate date: Date, cell: JTACDayCell?, cellState: CellState, indexPath: IndexPath) {
handleCellConfiguration(cell: cell, cellState: cellState)
}
- func calendar(_ calendar: JTACMonthView, didSelectDate date: Date, cell: JTACDayCell?, cellState: CellState) {
+ func calendar(_ calendar: JTACMonthView, didSelectDate date: Date, cell: JTACDayCell?, cellState: CellState, indexPath: IndexPath) {
handleCellConfiguration(cell: cell, cellState: cellState)
}
diff --git a/Example/JTAppleCalendar iOS Example/ExampleDateCells/DateCellCreatedWithCode/CodeCellView.swift b/SampleJTAppleCalendar/ExampleDateCells/DateCellCreatedWithCode/CodeCellView.swift
similarity index 100%
rename from Example/JTAppleCalendar iOS Example/ExampleDateCells/DateCellCreatedWithCode/CodeCellView.swift
rename to SampleJTAppleCalendar/ExampleDateCells/DateCellCreatedWithCode/CodeCellView.swift
diff --git a/Example/JTAppleCalendar iOS Example/ExampleDateCells/DateCellCreatedWithXIB/CellView.swift b/SampleJTAppleCalendar/ExampleDateCells/DateCellCreatedWithXIB/CellView.swift
similarity index 96%
rename from Example/JTAppleCalendar iOS Example/ExampleDateCells/DateCellCreatedWithXIB/CellView.swift
rename to SampleJTAppleCalendar/ExampleDateCells/DateCellCreatedWithXIB/CellView.swift
index 3645b861..47ffe23a 100644
--- a/Example/JTAppleCalendar iOS Example/ExampleDateCells/DateCellCreatedWithXIB/CellView.swift
+++ b/SampleJTAppleCalendar/ExampleDateCells/DateCellCreatedWithXIB/CellView.swift
@@ -6,7 +6,7 @@
// Copyright © 2016 OS-Tech. All rights reserved.
//
-
+import UIKit
import JTAppleCalendar
class CellView: JTACDayCell {
diff --git a/Example/JTAppleCalendar iOS Example/ExampleDateCells/DateCellCreatedWithXIB/CellView.xib b/SampleJTAppleCalendar/ExampleDateCells/DateCellCreatedWithXIB/CellView.xib
similarity index 100%
rename from Example/JTAppleCalendar iOS Example/ExampleDateCells/DateCellCreatedWithXIB/CellView.xib
rename to SampleJTAppleCalendar/ExampleDateCells/DateCellCreatedWithXIB/CellView.xib
diff --git a/Example/JTAppleCalendar iOS Example/ExampleSectionHeaders/HeaderAsClass/CodePinkSectionHeaderView.swift b/SampleJTAppleCalendar/ExampleSectionHeaders/HeaderAsClass/CodePinkSectionHeaderView.swift
similarity index 98%
rename from Example/JTAppleCalendar iOS Example/ExampleSectionHeaders/HeaderAsClass/CodePinkSectionHeaderView.swift
rename to SampleJTAppleCalendar/ExampleSectionHeaders/HeaderAsClass/CodePinkSectionHeaderView.swift
index 67f59c4f..0ced984f 100644
--- a/Example/JTAppleCalendar iOS Example/ExampleSectionHeaders/HeaderAsClass/CodePinkSectionHeaderView.swift
+++ b/SampleJTAppleCalendar/ExampleSectionHeaders/HeaderAsClass/CodePinkSectionHeaderView.swift
@@ -6,6 +6,7 @@
// Copyright © 2016 CocoaPods. All rights reserved.
//
+import UIKit
import JTAppleCalendar
class CodePinkSectionHeaderView: JTACMonthReusableView {
diff --git a/Example/JTAppleCalendar iOS Example/ExampleSectionHeaders/HeaderAsClass/CodeWhiteSectionHeaderView.swift b/SampleJTAppleCalendar/ExampleSectionHeaders/HeaderAsClass/CodeWhiteSectionHeaderView.swift
similarity index 98%
rename from Example/JTAppleCalendar iOS Example/ExampleSectionHeaders/HeaderAsClass/CodeWhiteSectionHeaderView.swift
rename to SampleJTAppleCalendar/ExampleSectionHeaders/HeaderAsClass/CodeWhiteSectionHeaderView.swift
index 430b621f..570af386 100644
--- a/Example/JTAppleCalendar iOS Example/ExampleSectionHeaders/HeaderAsClass/CodeWhiteSectionHeaderView.swift
+++ b/SampleJTAppleCalendar/ExampleSectionHeaders/HeaderAsClass/CodeWhiteSectionHeaderView.swift
@@ -6,6 +6,7 @@
// Copyright © 2016 CocoaPods. All rights reserved.
//
+import UIKit
import JTAppleCalendar
class CodeWhiteSectionHeaderView: JTACMonthReusableView {
diff --git a/Example/JTAppleCalendar iOS Example/ExampleSectionHeaders/HeaderAsXibs/PinkSectionHeaderView.swift b/SampleJTAppleCalendar/ExampleSectionHeaders/HeaderAsXibs/PinkSectionHeaderView.swift
similarity index 95%
rename from Example/JTAppleCalendar iOS Example/ExampleSectionHeaders/HeaderAsXibs/PinkSectionHeaderView.swift
rename to SampleJTAppleCalendar/ExampleSectionHeaders/HeaderAsXibs/PinkSectionHeaderView.swift
index d4b5af3f..6e274ea5 100644
--- a/Example/JTAppleCalendar iOS Example/ExampleSectionHeaders/HeaderAsXibs/PinkSectionHeaderView.swift
+++ b/SampleJTAppleCalendar/ExampleSectionHeaders/HeaderAsXibs/PinkSectionHeaderView.swift
@@ -6,6 +6,7 @@
// Copyright © 2016 CocoaPods. All rights reserved.
//
+import UIKit
import JTAppleCalendar
class PinkSectionHeaderView: JTACMonthReusableView {
diff --git a/Example/JTAppleCalendar iOS Example/ExampleSectionHeaders/HeaderAsXibs/PinkSectionHeaderView.xib b/SampleJTAppleCalendar/ExampleSectionHeaders/HeaderAsXibs/PinkSectionHeaderView.xib
similarity index 100%
rename from Example/JTAppleCalendar iOS Example/ExampleSectionHeaders/HeaderAsXibs/PinkSectionHeaderView.xib
rename to SampleJTAppleCalendar/ExampleSectionHeaders/HeaderAsXibs/PinkSectionHeaderView.xib
diff --git a/Example/JTAppleCalendar iOS Example/ExampleSectionHeaders/HeaderAsXibs/WhiteSectionHeaderView.swift b/SampleJTAppleCalendar/ExampleSectionHeaders/HeaderAsXibs/WhiteSectionHeaderView.swift
similarity index 95%
rename from Example/JTAppleCalendar iOS Example/ExampleSectionHeaders/HeaderAsXibs/WhiteSectionHeaderView.swift
rename to SampleJTAppleCalendar/ExampleSectionHeaders/HeaderAsXibs/WhiteSectionHeaderView.swift
index 225faead..046ad917 100644
--- a/Example/JTAppleCalendar iOS Example/ExampleSectionHeaders/HeaderAsXibs/WhiteSectionHeaderView.swift
+++ b/SampleJTAppleCalendar/ExampleSectionHeaders/HeaderAsXibs/WhiteSectionHeaderView.swift
@@ -5,6 +5,7 @@
// Created by JayT on 2016-05-16.
// Copyright © 2016 CocoaPods. All rights reserved.
//
+import UIKit
import JTAppleCalendar
class WhiteSectionHeaderView: JTACMonthReusableView {
diff --git a/Example/JTAppleCalendar iOS Example/ExampleSectionHeaders/HeaderAsXibs/WhiteSectionHeaderView.xib b/SampleJTAppleCalendar/ExampleSectionHeaders/HeaderAsXibs/WhiteSectionHeaderView.xib
similarity index 100%
rename from Example/JTAppleCalendar iOS Example/ExampleSectionHeaders/HeaderAsXibs/WhiteSectionHeaderView.xib
rename to SampleJTAppleCalendar/ExampleSectionHeaders/HeaderAsXibs/WhiteSectionHeaderView.xib
diff --git a/Example/JTAppleCalendar iOS Example/Info.plist b/SampleJTAppleCalendar/Info.plist
similarity index 53%
rename from Example/JTAppleCalendar iOS Example/Info.plist
rename to SampleJTAppleCalendar/Info.plist
index 6905cc67..a20b6a3f 100644
--- a/Example/JTAppleCalendar iOS Example/Info.plist
+++ b/SampleJTAppleCalendar/Info.plist
@@ -3,7 +3,7 @@
CFBundleDevelopmentRegion
- en
+ $(DEVELOPMENT_LANGUAGE)
CFBundleExecutable
$(EXECUTABLE_NAME)
CFBundleIdentifier
@@ -13,15 +13,34 @@
CFBundleName
$(PRODUCT_NAME)
CFBundlePackageType
- APPL
+ $(PRODUCT_BUNDLE_PACKAGE_TYPE)
CFBundleShortVersionString
1.0
- CFBundleSignature
- ????
CFBundleVersion
1
LSRequiresIPhoneOS
+ UIApplicationSceneManifest
+
+ UIApplicationSupportsMultipleScenes
+
+ UISceneConfigurations
+
+ UIWindowSceneSessionRoleApplication
+
+
+ UILaunchStoryboardName
+ LaunchScreen
+ UISceneConfigurationName
+ Default Configuration
+ UISceneDelegateClassName
+ $(PRODUCT_MODULE_NAME).SceneDelegate
+ UISceneStoryboardFile
+ Main
+
+
+
+
UILaunchStoryboardName
LaunchScreen
UIMainStoryboardFile
@@ -36,5 +55,12 @@
UIInterfaceOrientationLandscapeLeft
UIInterfaceOrientationLandscapeRight
+ UISupportedInterfaceOrientations~ipad
+
+ UIInterfaceOrientationPortrait
+ UIInterfaceOrientationPortraitUpsideDown
+ UIInterfaceOrientationLandscapeLeft
+ UIInterfaceOrientationLandscapeRight
+
diff --git a/Example/JTAppleCalendar iOS Example/Base.lproj/Main.storyboard b/SampleJTAppleCalendar/Main.storyboard
similarity index 89%
rename from Example/JTAppleCalendar iOS Example/Base.lproj/Main.storyboard
rename to SampleJTAppleCalendar/Main.storyboard
index dddc9946..5ea2a0af 100644
--- a/Example/JTAppleCalendar iOS Example/Base.lproj/Main.storyboard
+++ b/SampleJTAppleCalendar/Main.storyboard
@@ -1,18 +1,16 @@
-
-
-
-
+
+
-
+
-
+
-
+
@@ -22,9 +20,9 @@
-
+
-
-
+
@@ -67,14 +65,14 @@
-
+
-
+
@@ -85,19 +83,19 @@
-
+
-
+
-
+
@@ -159,7 +157,7 @@
-
+
@@ -167,7 +165,7 @@
-
+
@@ -177,7 +175,7 @@
-
+
@@ -190,7 +188,7 @@
-
+
@@ -203,7 +201,7 @@
-
+
@@ -216,7 +214,7 @@
-
+
@@ -237,7 +235,7 @@
-
+
@@ -250,7 +248,7 @@
-
+
@@ -268,7 +266,7 @@
-
+
@@ -281,7 +279,7 @@
-
+
@@ -305,7 +303,7 @@
-
+
@@ -318,7 +316,7 @@
-
+
@@ -331,7 +329,7 @@
-
+
@@ -350,7 +348,7 @@
-
+
@@ -363,7 +361,7 @@
-
+
@@ -376,7 +374,7 @@
-
+
@@ -392,9 +390,9 @@
-
+
-
+
@@ -407,7 +405,7 @@
-
+
@@ -420,8 +418,8 @@
-
-
+
+
@@ -433,8 +431,8 @@
-
-
+
+
@@ -446,8 +444,8 @@
-
-
+
+
@@ -459,8 +457,8 @@
-
-
+
+
@@ -477,7 +475,7 @@
-
+
@@ -490,7 +488,7 @@
-
+
@@ -503,7 +501,7 @@
-
+
@@ -516,7 +514,7 @@
-
+
@@ -532,9 +530,9 @@
-
+
-
+
@@ -547,12 +545,17 @@
+
+
+
+
+
-
+
@@ -579,51 +582,51 @@
-
+
-
-
+
-
+
-
+
-
+
-
+
-
+
@@ -737,7 +741,7 @@
-
+
@@ -745,11 +749,11 @@
-
+
-
-
+
+
@@ -798,20 +802,20 @@
-
+
-
+
-
+
-
+
@@ -823,14 +827,14 @@
-
-
+
+
-
+
@@ -855,15 +859,15 @@
-
-
+
+
-
+
@@ -876,13 +880,13 @@
-
+
-
-
+
+
@@ -894,12 +898,12 @@
-
+
-
+
@@ -910,41 +914,41 @@
-
+
-
+
-
+
-
+
-
+
-
+
-
+
@@ -966,23 +970,23 @@
-
+
-
+
-
+
-
+
-
+
@@ -991,7 +995,7 @@
-
+
@@ -999,7 +1003,7 @@
-
+
@@ -1037,24 +1041,24 @@
-
+
-
-
+
+
-
-
+
+
-
-
+
+
@@ -1063,24 +1067,24 @@
-
+
-
-
+
+
-
-
+
+
-
-
+
+
@@ -1089,52 +1093,52 @@
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
@@ -1143,30 +1147,30 @@
-
+
-
+
-
-
+
+
-
-
+
+
-
-
+
+
@@ -1175,24 +1179,24 @@
-
+
-
-
+
+
-
-
+
+
-
-
+
+
@@ -1201,24 +1205,24 @@
-
+
-
-
+
+
-
-
+
+
-
-
+
+
@@ -1274,11 +1278,11 @@
-
+
-
+
@@ -1296,7 +1300,7 @@
-
+
@@ -1307,7 +1311,7 @@
-
+
@@ -1338,17 +1342,17 @@
-
+
-
+
-
+
@@ -1360,7 +1364,7 @@
-
+
@@ -1385,8 +1389,8 @@
-
-
+
+
diff --git a/SampleJTAppleCalendar/SceneDelegate.swift b/SampleJTAppleCalendar/SceneDelegate.swift
new file mode 100644
index 00000000..82743c59
--- /dev/null
+++ b/SampleJTAppleCalendar/SceneDelegate.swift
@@ -0,0 +1,53 @@
+//
+// SceneDelegate.swift
+// SampleJTAppleCalendar
+//
+// Created by Jeron Thomas on 2019-06-25.
+// Copyright © 2019 OsTech. All rights reserved.
+//
+
+import UIKit
+
+class SceneDelegate: UIResponder, UIWindowSceneDelegate {
+
+ var window: UIWindow?
+
+
+ func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
+ // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
+ // If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
+ // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
+ guard let _ = (scene as? UIWindowScene) else { return }
+ }
+
+ func sceneDidDisconnect(_ scene: UIScene) {
+ // Called as the scene is being released by the system.
+ // This occurs shortly after the scene enters the background, or when its session is discarded.
+ // Release any resources associated with this scene that can be re-created the next time the scene connects.
+ // The scene may re-connect later, as its session was not neccessarily discarded (see `application:didDiscardSceneSessions` instead).
+ }
+
+ func sceneDidBecomeActive(_ scene: UIScene) {
+ // Called when the scene has moved from an inactive state to an active state.
+ // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive.
+ }
+
+ func sceneWillResignActive(_ scene: UIScene) {
+ // Called when the scene will move from an active state to an inactive state.
+ // This may occur due to temporary interruptions (ex. an incoming phone call).
+ }
+
+ func sceneWillEnterForeground(_ scene: UIScene) {
+ // Called as the scene transitions from the background to the foreground.
+ // Use this method to undo the changes made on entering the background.
+ }
+
+ func sceneDidEnterBackground(_ scene: UIScene) {
+ // Called as the scene transitions from the foreground to the background.
+ // Use this method to save data, release shared resources, and store enough scene-specific state information
+ // to restore the scene back to its current state.
+ }
+
+
+}
+
diff --git a/UITests/Info.plist b/SampleJTAppleCalendarUITests/Info.plist
similarity index 93%
rename from UITests/Info.plist
rename to SampleJTAppleCalendarUITests/Info.plist
index 6c40a6cd..64d65ca4 100644
--- a/UITests/Info.plist
+++ b/SampleJTAppleCalendarUITests/Info.plist
@@ -13,7 +13,7 @@
CFBundleName
$(PRODUCT_NAME)
CFBundlePackageType
- BNDL
+ $(PRODUCT_BUNDLE_PACKAGE_TYPE)
CFBundleShortVersionString
1.0
CFBundleVersion
diff --git a/SampleJTAppleCalendarUITests/SampleJTAppleCalendarUITests.swift b/SampleJTAppleCalendarUITests/SampleJTAppleCalendarUITests.swift
new file mode 100644
index 00000000..266c21d9
--- /dev/null
+++ b/SampleJTAppleCalendarUITests/SampleJTAppleCalendarUITests.swift
@@ -0,0 +1,46 @@
+//
+// SampleJTAppleCalendarUITests.swift
+// SampleJTAppleCalendarUITests
+//
+// Created by Jeron Thomas on 2019-11-16.
+// Copyright © 2019 OsTech. All rights reserved.
+//
+
+import XCTest
+
+class SampleJTAppleCalendarUITests: XCTestCase {
+
+ override func setUp() {
+ // Put setup code here. This method is called before the invocation of each test method in the class.
+
+ // In UI tests it is usually best to stop immediately when a failure occurs.
+ continueAfterFailure = false
+
+ // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this.
+ }
+
+ override func tearDown() {
+ // Put teardown code here. This method is called after the invocation of each test method in the class.
+ }
+
+ func testExample() {
+ // UI tests must launch the application that they test.
+ let app = XCUIApplication()
+ app.launch()
+ print("")
+
+
+
+ // Use recording to get started writing UI tests.
+ // Use XCTAssert and related functions to verify your tests produce the correct results.
+ }
+
+ func testLaunchPerformance() {
+ if #available(macOS 10.15, iOS 13.0, tvOS 13.0, *) {
+ // This measures how long it takes to launch your application.
+ measure(metrics: [XCTOSSignpostMetric.applicationLaunch]) {
+ XCUIApplication().launch()
+ }
+ }
+ }
+}
diff --git a/Sources/Info-iOS.plist b/Sources/Info-iOS.plist
deleted file mode 100644
index d3de8eef..00000000
--- a/Sources/Info-iOS.plist
+++ /dev/null
@@ -1,26 +0,0 @@
-
-
-
-
- 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/Sources/CalendarEnums.swift b/Sources/JTAppleCalendar/CalendarEnums.swift
similarity index 92%
rename from Sources/CalendarEnums.swift
rename to Sources/JTAppleCalendar/CalendarEnums.swift
index eaf1ace7..b2febda2 100644
--- a/Sources/CalendarEnums.swift
+++ b/Sources/JTAppleCalendar/CalendarEnums.swift
@@ -1,7 +1,7 @@
//
// CalendarEnums.swift
//
-// Copyright (c) 2016-2017 JTAppleCalendar (https://github.com/patchthecode/JTAppleCalendar)
+// Copyright (c) 2016-2020 JTAppleCalendar (https://github.com/patchthecode/JTAppleCalendar)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
@@ -22,6 +22,8 @@
// THE SOFTWARE.
//
+import UIKit
+
/// Describes a scroll destination
public enum SegmentDestination {
/// next the destination is the following segment
@@ -70,7 +72,7 @@ public enum ScrollingMode: Equatable {
case nonStopToSection(withResistance: CGFloat)
/// nonStopToCell - continuous scrolling that will stop at a cell
case nonStopToCell(withResistance: CGFloat)
- /// nonStopTo - continuous scrolling that will stop at acustom interval
+ /// nonStopTo - continuous scrolling that will stop at acustom interval, do not use 0 as custom interval
case nonStopTo(customInterval: CGFloat, withResistance: CGFloat)
/// none - continuous scrolling that will eventually stop at a point
case none
@@ -106,7 +108,7 @@ public enum DateOwner: Int {
followingMonthOutsideBoundary
}
/// Months of the year
-public enum MonthsOfYear: Int {
+public enum MonthsOfYear: Int, CaseIterable {
case jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec
}
@@ -116,15 +118,20 @@ public enum SelectionRangePosition: Int {
case left = 1, middle, right, full, none
}
+/// Between month segments, the range selection can either be visually disconnected or connected
+public enum RangeSelectionMode {
+ case segmented, continuous
+}
+
/// Signifies whether or not a selection was done programatically or by the user
public enum SelectionType: String {
/// Selection type
case programatic, userInitiated
}
-/// Days of the week. By setting you calandar's first day of week,
-/// you can change which day is the first for the week. Sunday is by default.
-public enum DaysOfWeek: Int {
+/// Days of the week. By setting your calendar's first day of the week,
+/// you can change which day is the first for the week. Sunday is the default value.
+public enum DaysOfWeek: Int, CaseIterable {
/// Days of the week.
case sunday = 1, monday, tuesday, wednesday, thursday, friday, saturday
}
diff --git a/Sources/CalendarStructs.swift b/Sources/JTAppleCalendar/CalendarStructs.swift
similarity index 98%
rename from Sources/CalendarStructs.swift
rename to Sources/JTAppleCalendar/CalendarStructs.swift
index 5ed69093..5697d809 100644
--- a/Sources/CalendarStructs.swift
+++ b/Sources/JTAppleCalendar/CalendarStructs.swift
@@ -1,7 +1,7 @@
//
// CalendarStructs.swift
//
-// Copyright (c) 2016-2017 JTAppleCalendar (https://github.com/patchthecode/JTAppleCalendar)
+// Copyright (c) 2016-2020 JTAppleCalendar (https://github.com/patchthecode/JTAppleCalendar)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
@@ -23,6 +23,8 @@
//
+import UIKit
+
/// Describes which month the cell belongs to
/// - ThisMonth: Cell belongs to the current month
/// - PreviousMonthWithinBoundary: Cell belongs to the previous month.
@@ -273,7 +275,7 @@ class JTAppleDateConfigGenerator {
// Track the month name index
var monthNameIndex = parameters.calendar.component(.month, from: parameters.startDate) - 1
- let allMonthsOfYear: [MonthsOfYear] = [.jan, .feb, .mar, .apr, .may, .jun, .jul, .aug, .sep, .oct, .nov, .dec]
+ let allMonthsOfYear = MonthsOfYear.allCases
for monthIndex in 0 ..< numberOfMonths {
if let currentMonthDate = parameters.calendar.date(byAdding: .month, value: monthIndex, to: parameters.startDate) {
diff --git a/Sources/GlobalFunctionsAndExtensions.swift b/Sources/JTAppleCalendar/GlobalFunctionsAndExtensions.swift
similarity index 96%
rename from Sources/GlobalFunctionsAndExtensions.swift
rename to Sources/JTAppleCalendar/GlobalFunctionsAndExtensions.swift
index 9184483c..9b5eb0a1 100644
--- a/Sources/GlobalFunctionsAndExtensions.swift
+++ b/Sources/JTAppleCalendar/GlobalFunctionsAndExtensions.swift
@@ -1,7 +1,7 @@
//
// GlobalFunctionsAndExtensions.swift
//
-// Copyright (c) 2016-2017 JTAppleCalendar (https://github.com/patchthecode/JTAppleCalendar)
+// Copyright (c) 2016-2020 JTAppleCalendar (https://github.com/patchthecode/JTAppleCalendar)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
@@ -22,6 +22,8 @@
// THE SOFTWARE.
//
+import Foundation
+
extension Calendar {
static let formatter: DateFormatter = {
let dateFormatter = DateFormatter()
diff --git a/Sources/Info-tvOS.plist b/Sources/JTAppleCalendar/Info.plist
similarity index 82%
rename from Sources/Info-tvOS.plist
rename to Sources/JTAppleCalendar/Info.plist
index d3de8eef..9bcb2444 100644
--- a/Sources/Info-tvOS.plist
+++ b/Sources/JTAppleCalendar/Info.plist
@@ -3,7 +3,7 @@
CFBundleDevelopmentRegion
- en
+ $(DEVELOPMENT_LANGUAGE)
CFBundleExecutable
$(EXECUTABLE_NAME)
CFBundleIdentifier
@@ -13,14 +13,10 @@
CFBundleName
$(PRODUCT_NAME)
CFBundlePackageType
- FMWK
+ $(PRODUCT_BUNDLE_PACKAGE_TYPE)
CFBundleShortVersionString
1.0
- CFBundleSignature
- ????
CFBundleVersion
$(CURRENT_PROJECT_VERSION)
- NSPrincipalClass
-
diff --git a/Sources/JTACCollectionMonthViewDelegates.swift b/Sources/JTAppleCalendar/JTACCollectionMonthViewDelegates.swift
similarity index 89%
rename from Sources/JTACCollectionMonthViewDelegates.swift
rename to Sources/JTAppleCalendar/JTACCollectionMonthViewDelegates.swift
index b3a8d4fa..f3563b3e 100644
--- a/Sources/JTACCollectionMonthViewDelegates.swift
+++ b/Sources/JTAppleCalendar/JTACCollectionMonthViewDelegates.swift
@@ -1,7 +1,7 @@
//
// JTACCollectionViewDelegates.swift
//
-// Copyright (c) 2016-2017 JTAppleCalendar (https://github.com/patchthecode/JTAppleCalendar)
+// Copyright (c) 2016-2020 JTAppleCalendar (https://github.com/patchthecode/JTAppleCalendar)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
@@ -22,6 +22,8 @@
// THE SOFTWARE.
//
+import UIKit
+
extension JTACMonthView: UICollectionViewDelegate, UICollectionViewDataSource {
/// Asks your data source object to provide a
/// supplementary view to display in the collection view.
@@ -60,7 +62,7 @@ extension JTACMonthView: UICollectionViewDelegate, UICollectionViewDataSource {
}
let cell = collectionView.cellForItem(at: indexPath) as? JTACDayCell
let cellState = cellStateFromIndexPath(indexPath, withDateInfo: infoOfDate, selectionType: .userInitiated)
- delegate.calendar(self, didHighlightDate: cellState.date, cell: cell, cellState: cellState)
+ delegate.calendar(self, didHighlightDate: cellState.date, cell: cell, cellState: cellState, indexPath: indexPath)
}
/// Tells the delegate that the item at the specified index path was unhighlighted.
@@ -72,7 +74,7 @@ extension JTACMonthView: UICollectionViewDelegate, UICollectionViewDataSource {
}
let cell = collectionView.cellForItem(at: indexPath) as? JTACDayCell
let cellState = cellStateFromIndexPath(indexPath, withDateInfo: infoOfDate, selectionType: .userInitiated)
- delegate.calendar(self, didUnhighlightDate: cellState.date, cell: cell, cellState: cellState)
+ delegate.calendar(self, didUnhighlightDate: cellState.date, cell: cell, cellState: cellState, indexPath: indexPath)
}
/// Asks your data source object for the cell that corresponds
@@ -189,11 +191,13 @@ extension JTACMonthView: UICollectionViewDelegate, UICollectionViewDataSource {
localPathsToReload.formUnion(counterPathsToReload)
}
+ setMinMaxDate()
+
if shouldTriggerSelectionDelegate {
if action == .didSelect {
- delegate.calendar(self, didSelectDate: infoOfDate.date, cell: cell, cellState: cellState)
+ delegate.calendar(self, didSelectDate: infoOfDate.date, cell: cell, cellState: cellState, indexPath: indexPath)
} else {
- delegate.calendar(self, didDeselectDate: infoOfDate.date, cell: cell, cellState: cellState)
+ delegate.calendar(self, didDeselectDate: infoOfDate.date, cell: cell, cellState: cellState, indexPath: indexPath)
}
}
@@ -202,6 +206,21 @@ extension JTACMonthView: UICollectionViewDelegate, UICollectionViewDataSource {
}
}
+ func setMinMaxDate() {
+ let selectedCellData = self.selectedCellData
+ let sortedKeys = selectedCellData.keys.sorted()
+ guard
+ let firstIndex = sortedKeys.first,
+ let lastIndex = sortedKeys.last else {
+ selectedCells.first = nil
+ selectedCells.last = nil
+ return
+ }
+ let date = selectedCellData[firstIndex]!.date
+ selectedCells.first = (date, firstIndex)
+ selectedCells.last = (date, lastIndex)
+ }
+
func handleShouldSelectionValueChange(_ collectionView: UICollectionView, action: ShouldSelectionAction, indexPath: IndexPath, selectionType: SelectionType) -> Bool {
if let
delegate = calendarDelegate,
@@ -212,11 +231,18 @@ extension JTACMonthView: UICollectionViewDelegate, UICollectionViewDataSource {
selectionType: selectionType)
switch action {
case .shouldSelect:
- return delegate.calendar(self, shouldSelectDate: infoOfDate.date, cell: cell, cellState: cellState)
+ return delegate.calendar(self, shouldSelectDate: infoOfDate.date, cell: cell, cellState: cellState, indexPath: indexPath)
case .shouldDeselect:
- return delegate.calendar(self, shouldDeselectDate: infoOfDate.date, cell: cell, cellState: cellState)
+ return delegate.calendar(self, shouldDeselectDate: infoOfDate.date, cell: cell, cellState: cellState, indexPath: indexPath)
}
}
return false
}
+
+ public func indexPathForPreferredFocusedView(in collectionView: UICollectionView) -> IndexPath? {
+ if let delegate = calendarDelegate {
+ return delegate.indexPathForPreferredFocusedView(in: collectionView)
+ }
+ return nil
+ }
}
diff --git a/Sources/JTACCollectionYearViewDelegates.swift b/Sources/JTAppleCalendar/JTACCollectionYearViewDelegates.swift
similarity index 96%
rename from Sources/JTACCollectionYearViewDelegates.swift
rename to Sources/JTAppleCalendar/JTACCollectionYearViewDelegates.swift
index eba715cf..c8bd4144 100644
--- a/Sources/JTACCollectionYearViewDelegates.swift
+++ b/Sources/JTAppleCalendar/JTACCollectionYearViewDelegates.swift
@@ -1,7 +1,7 @@
//
// JTACCollectionYearViewDelegates.swift
//
-// Copyright (c) 2016-2017 JTAppleCalendar (https://github.com/patchthecode/JTAppleCalendar)
+// Copyright (c) 2016-2020 JTAppleCalendar (https://github.com/patchthecode/JTAppleCalendar)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
@@ -22,6 +22,9 @@
// THE SOFTWARE.
//
+import UIKit
+import Foundation
+
extension JTACYearView: UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
public func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return monthData.count
@@ -43,12 +46,9 @@ extension JTACYearView: UICollectionViewDelegate, UICollectionViewDataSource, UI
return UICollectionViewCell()
}
-
-
let cell = delegate.calendar(self, cellFor: self.monthData[indexPath.item], at: date, indexPath: indexPath)
cell.setupWith(configurationParameters: configurationParameters,
month: monthData,
- date: date,
delegate: self)
return cell
} else {
diff --git a/Sources/JTACDayCell.swift b/Sources/JTAppleCalendar/JTACDayCell.swift
similarity index 96%
rename from Sources/JTACDayCell.swift
rename to Sources/JTAppleCalendar/JTACDayCell.swift
index 2babfd55..8365d70f 100644
--- a/Sources/JTACDayCell.swift
+++ b/Sources/JTAppleCalendar/JTACDayCell.swift
@@ -1,7 +1,7 @@
//
// JTACDayCell.swift
//
-// Copyright (c) 2016-2017 JTAppleCalendar (https://github.com/patchthecode/JTAppleCalendar)
+// Copyright (c) 2016-2020 JTAppleCalendar (https://github.com/patchthecode/JTAppleCalendar)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
@@ -22,6 +22,8 @@
// THE SOFTWARE.
//
+import UIKit
+
/// The JTAppleDayCell class defines the attributes and
/// behavior of the cells that appear in JTAppleCalendarMonthView objects.
@available(*, unavailable, renamed: "JTACDayCell")
diff --git a/Sources/JTACInteractionMonthFunctions.swift b/Sources/JTAppleCalendar/JTACInteractionMonthFunctions.swift
similarity index 90%
rename from Sources/JTACInteractionMonthFunctions.swift
rename to Sources/JTAppleCalendar/JTACInteractionMonthFunctions.swift
index cab8b843..5e1a9607 100644
--- a/Sources/JTACInteractionMonthFunctions.swift
+++ b/Sources/JTAppleCalendar/JTACInteractionMonthFunctions.swift
@@ -1,7 +1,7 @@
//
// JTACInteractionMonthFunctions.swift
//
-// Copyright (c) 2016-2017 JTAppleCalendar (https://github.com/patchthecode/JTAppleCalendar)
+// Copyright (c) 2016-2020 JTAppleCalendar (https://github.com/patchthecode/JTAppleCalendar)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
@@ -22,6 +22,7 @@
// THE SOFTWARE.
//
+import UIKit
extension JTACMonthView {
@@ -112,6 +113,9 @@ extension JTACMonthView {
/// Deselect all selected dates
/// - Parameter: this funciton triggers a delegate call by default. Set this to false if you do not want this
+ /// - Parameter keepDeselectionIfMultiSelectionAllowed:
+ /// if (in range selection) there are 4 dates. -> selected, unselected, selected, selected. (S | U | S | S)
+ /// Deselecting those 4 dates again would give U | S | U | U. With KeepDeselection, this becomes U | U | U | U
public func deselectAllDates(triggerSelectionDelegate: Bool = true) {
deselect(dates: selectedDates, triggerSelectionDelegate: triggerSelectionDelegate)
}
@@ -119,9 +123,16 @@ extension JTACMonthView {
/// Deselect dates
/// - Parameter: Dates - The dates to deselect
/// - Parameter: triggerSelectionDelegate - this funciton triggers a delegate call by default. Set this to false if you do not want this
- public func deselect(dates: [Date], triggerSelectionDelegate: Bool = true) {
+ /// - Parameter keepDeselectionIfMultiSelectionAllowed:
+ /// if (in range selection) there are 4 dates. -> selected, unselected, selected, selected. (S | U | S | S)
+ /// Deselecting those 4 dates again would give U | S | U | U. With KeepDeselection, this becomes U | U | U | U
+ public func deselect(dates: [Date], triggerSelectionDelegate: Bool = true, keepDeselectionIfMultiSelectionAllowed: Bool = false) {
if allowsMultipleSelection {
- selectDates(dates, triggerSelectionDelegate: triggerSelectionDelegate)
+ var filteredDates: [Date] = dates
+ if keepDeselectionIfMultiSelectionAllowed {
+ filteredDates = dates.filter { self.selectedDatesSet.contains(calendar.startOfDay(for: $0)) }
+ }
+ selectDates(filteredDates, triggerSelectionDelegate: triggerSelectionDelegate, keepSelectionIfMultiSelectionAllowed: false)
} else {
let paths = pathsFromDates(dates)
guard !paths.isEmpty else { return }
@@ -134,7 +145,7 @@ extension JTACMonthView {
public func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator, anchorDate: Date?) {
DispatchQueue.main.async { [weak self] in
guard let _self = self else { return }
- _self.reloadData(withanchor: anchorDate)
+ _self.reloadData(withAnchor: anchorDate)
}
}
@@ -203,8 +214,14 @@ extension JTACMonthView {
/// - Parameter animation: Scroll is animated if this is set to true
/// - Parameter completionHandler: This closure will run after
/// the reload is complete
- public func reloadData(withanchor date: Date? = nil, completionHandler: (() -> Void)? = nil) {
- if isReloadDataInProgress { return }
+ public func reloadData(withAnchor date: Date? = nil, completionHandler: (() -> Void)? = nil) {
+ if isReloadDataInProgress {
+ calendarViewLayout.delayedExecutionClosure.append {[weak self] in
+ guard let _ = self else { return }
+ completionHandler?()
+ }
+ return
+ }
if isScrollInProgress {
scrollDelayedExecutionClosure.append {[unowned self] in
self.reloadData(completionHandler: completionHandler)
@@ -282,11 +299,16 @@ extension JTACMonthView {
}
/// Deselect all selected dates within a range
- public func deselectDates(from start: Date, to end: Date? = nil, triggerSelectionDelegate: Bool = true) {
+ /// - Parameter: start - Start of date range to deselect
+ /// - Parameter: end of date range to deselect
+ /// - Parameter keepDeselectionIfMultiSelectionAllowed:
+ /// if (in range selection) there are 4 dates. -> selected, unselected, selected, selected. (S | U | S | S)
+ /// Deselecting those 4 dates again would give U | S | U | U. With KeepDeselection, this becomes U | U | U | U
+ public func deselectDates(from start: Date, to end: Date? = nil, triggerSelectionDelegate: Bool = true, keepDeselectionIfMultiSelectionAllowed: Bool = false) {
if selectedDates.isEmpty { return }
let end = end ?? selectedDates.last!
let dates = selectedDates.filter { $0 >= start && $0 <= end }
- deselect(dates: dates, triggerSelectionDelegate: triggerSelectionDelegate)
+ deselect(dates: dates, triggerSelectionDelegate: triggerSelectionDelegate, keepDeselectionIfMultiSelectionAllowed: keepDeselectionIfMultiSelectionAllowed)
}
@@ -417,7 +439,7 @@ extension JTACMonthView {
switch scrollDirection {
case .horizontal:
- if calendarViewLayout.thereAreHeaders || _cachedConfiguration.generateOutDates == .tillEndOfGrid {
+ if calendarViewLayout.thereAreHeaders || _cachedConfiguration?.generateOutDates == .tillEndOfGrid {
fixedScrollSize = calendarViewLayout.sizeOfContentForSection(0)
} else {
fixedScrollSize = frame.width
@@ -512,6 +534,7 @@ extension JTACMonthView {
self.scrollToDate(date,
triggerScrollToDateDelegate: triggerScrollToDateDelegate,
animateScroll: animateScroll,
+ preferredScrollPosition: preferredScrollPosition,
extraAddedOffset: extraAddedOffset,
completionHandler: completionHandler)
}
@@ -531,16 +554,21 @@ extension JTACMonthView {
if retrievedPathsFromDates.isEmpty { return }
let sectionIndexPath = pathsFromDates([date])[0]
- guard let point = targetPointForItemAt(indexPath: sectionIndexPath) else {
- assert(false, "Could not determine CGPoint. This is an error. contact developer on github. In production, there will not be a crash, but scrolling will not occur")
- return
+ if scrollingMode == .none {
+ self.scrollToItem(at: sectionIndexPath,
+ at: preferredScrollPosition ?? (scrollDirection == .horizontal ? .left : .top),
+ animated: animateScroll)
+ } else {
+ guard let point = targetPointForItemAt(indexPath: sectionIndexPath) else {
+ assert(false, "Could not determine CGPoint. This is an error. contact developer on github. In production, there will not be a crash, but scrolling will not occur")
+ return
+ }
+ scrollTo(point: point,
+ triggerScrollToDateDelegate: triggerScrollToDateDelegate,
+ isAnimationEnabled: animateScroll,
+ extraAddedOffset: extraAddedOffset,
+ completionHandler: completionHandler)
}
-
- scrollTo(point: point,
- triggerScrollToDateDelegate: triggerScrollToDateDelegate,
- isAnimationEnabled: animateScroll,
- extraAddedOffset: extraAddedOffset,
- completionHandler: completionHandler)
}
/// Scrolls the calendar view to the start of a section view header.
diff --git a/Sources/JTACInteractionYearFunctions.swift b/Sources/JTAppleCalendar/JTACInteractionYearFunctions.swift
similarity index 86%
rename from Sources/JTACInteractionYearFunctions.swift
rename to Sources/JTAppleCalendar/JTACInteractionYearFunctions.swift
index af169999..7db844e9 100644
--- a/Sources/JTACInteractionYearFunctions.swift
+++ b/Sources/JTAppleCalendar/JTACInteractionYearFunctions.swift
@@ -1,7 +1,7 @@
//
// UserInteractionYearFunctions.swift
//
-// Copyright (c) 2016-2017 JTAppleCalendar (https://github.com/patchthecode/JTAppleCalendar)
+// Copyright (c) 2016-2020 JTAppleCalendar (https://github.com/patchthecode/JTAppleCalendar)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
@@ -22,14 +22,15 @@
// THE SOFTWARE.
//
+import Foundation
extension JTACYearView {
/// Dequeues a reuable calendar cell
- public func dequeueReusableJTAppleMonthCell(withReuseIdentifier identifier: String, for indexPath: IndexPath) -> JTAppleMonthCell {
- guard let cell = dequeueReusableCell(withReuseIdentifier: identifier, for: indexPath) as? JTAppleMonthCell else {
+ public func dequeueReusableJTAppleMonthCell(withReuseIdentifier identifier: String, for indexPath: IndexPath) -> JTACMonthCell {
+ guard let cell = dequeueReusableCell(withReuseIdentifier: identifier, for: indexPath) as? JTACMonthCell else {
assert(false, "Error initializing Cell View with identifier: '\(identifier)'")
- return JTAppleMonthCell()
+ return JTACMonthCell()
}
return cell
}
diff --git a/Sources/JTACMonthActionFunctions.swift b/Sources/JTAppleCalendar/JTACMonthActionFunctions.swift
similarity index 81%
rename from Sources/JTACMonthActionFunctions.swift
rename to Sources/JTAppleCalendar/JTACMonthActionFunctions.swift
index 26d9172e..0c61d3d6 100644
--- a/Sources/JTACMonthActionFunctions.swift
+++ b/Sources/JTAppleCalendar/JTACMonthActionFunctions.swift
@@ -1,7 +1,7 @@
//
// JTACMonthActionFunctions.swift
//
-// Copyright (c) 2016-2017 JTAppleCalendar (https://github.com/patchthecode/JTAppleCalendar)
+// Copyright (c) 2016-2020 JTAppleCalendar (https://github.com/patchthecode/JTAppleCalendar)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
@@ -22,6 +22,8 @@
// THE SOFTWARE.
//
+import UIKit
+
extension JTACMonthView {
/// Lays out subviews.
override open func layoutSubviews() {
@@ -119,46 +121,56 @@ extension JTACMonthView {
}
}
- func setupMonthInfoDataForStartAndEndDate(with config: ConfigurationParameters? = nil) -> CalendarData {
+ func setupMonthInfoDataForStartAndEndDate(with optionalConfig: ConfigurationParameters? = nil) -> CalendarData {
var months = [Month]()
var monthMap = [Int: Int]()
var totalSections = 0
var totalDays = 0
- var validConfig = config
- if validConfig == nil { validConfig = calendarDataSource?.configureCalendar(self) }
- if let validConfig = validConfig {
- let comparison = validConfig.calendar.compare(validConfig.startDate, to: validConfig.endDate, toGranularity: .nanosecond)
- if comparison == ComparisonResult.orderedDescending {
- assert(false, "Error, your start date cannot be greater than your end date\n")
- return (CalendarData(months: [], totalSections: 0, sectionToMonthMap: [:], totalDays: 0))
- }
-
- // Set the new cache
- _cachedConfiguration = validConfig
+
+ // first use the config passed in
+ // If nil, fetch the config from the datasource
+ let possibleConfig = optionalConfig ?? calendarDataSource?.configureCalendar(self)
+
+ let validConfig: ConfigurationParameters
+ if let valid = possibleConfig {
+ validConfig = valid
+ } else {
+ assert(false, "Using default parameters. Your config should not have been nil here. In production, your dates will be an incorrect default date")
+ validConfig = ConfigurationParameters(startDate: Date(), endDate: Date().addingTimeInterval(1))
+ }
+
+ let comparison = validConfig.calendar.compare(validConfig.startDate, to: validConfig.endDate, toGranularity: .nanosecond)
+ if comparison == ComparisonResult.orderedDescending {
+ assert(false, "Error, your start date cannot be greater than your end date\n")
+ return (CalendarData(months: [], totalSections: 0, sectionToMonthMap: [:], totalDays: 0))
+ }
+
+ // Set the new cache
+ _cachedConfiguration = validConfig
+
+ if let
+ startMonth = calendar.startOfMonth(for: validConfig.startDate),
+ let endMonth = calendar.endOfMonth(for: validConfig.endDate) {
+ startOfMonthCache = startMonth
+ endOfMonthCache = endMonth
+ // Create the parameters for the date format generator
+ let parameters = ConfigurationParameters(startDate: startOfMonthCache,
+ endDate: endOfMonthCache,
+ numberOfRows: validConfig.numberOfRows,
+ calendar: calendar,
+ generateInDates: validConfig.generateInDates,
+ generateOutDates: validConfig.generateOutDates,
+ firstDayOfWeek: validConfig.firstDayOfWeek,
+ hasStrictBoundaries: validConfig.hasStrictBoundaries)
- if let
- startMonth = calendar.startOfMonth(for: validConfig.startDate),
- let endMonth = calendar.endOfMonth(for: validConfig.endDate) {
- startOfMonthCache = startMonth
- endOfMonthCache = endMonth
- // Create the parameters for the date format generator
- let parameters = ConfigurationParameters(startDate: startOfMonthCache,
- endDate: endOfMonthCache,
- numberOfRows: validConfig.numberOfRows,
- calendar: calendar,
- generateInDates: validConfig.generateInDates,
- generateOutDates: validConfig.generateOutDates,
- firstDayOfWeek: validConfig.firstDayOfWeek,
- hasStrictBoundaries: validConfig.hasStrictBoundaries)
-
- let generatedData = dateGenerator.setupMonthInfoDataForStartAndEndDate(parameters)
- months = generatedData.months
- monthMap = generatedData.monthMap
- totalSections = generatedData.totalSections
- totalDays = generatedData.totalDays
- }
+ let generatedData = dateGenerator.setupMonthInfoDataForStartAndEndDate(parameters)
+ months = generatedData.months
+ monthMap = generatedData.monthMap
+ totalSections = generatedData.totalSections
+ totalDays = generatedData.totalDays
}
+
let data = CalendarData(months: months, totalSections: totalSections, sectionToMonthMap: monthMap, totalDays: totalDays)
return data
}
@@ -247,12 +259,12 @@ extension JTACMonthView {
// ConfigParameters were changed
newStartOfMonth != oldStartOfMonth ||
newEndOfMonth != oldEndOfMonth ||
- newDateBoundary.calendar != _cachedConfiguration.calendar ||
- newDateBoundary.numberOfRows != _cachedConfiguration.numberOfRows ||
- newDateBoundary.generateInDates != _cachedConfiguration.generateInDates ||
- newDateBoundary.generateOutDates != _cachedConfiguration.generateOutDates ||
- newDateBoundary.firstDayOfWeek != _cachedConfiguration.firstDayOfWeek ||
- newDateBoundary.hasStrictBoundaries != _cachedConfiguration.hasStrictBoundaries ||
+ newDateBoundary.calendar != _cachedConfiguration?.calendar ||
+ newDateBoundary.numberOfRows != _cachedConfiguration?.numberOfRows ||
+ newDateBoundary.generateInDates != _cachedConfiguration?.generateInDates ||
+ newDateBoundary.generateOutDates != _cachedConfiguration?.generateOutDates ||
+ newDateBoundary.firstDayOfWeek != _cachedConfiguration?.firstDayOfWeek ||
+ newDateBoundary.hasStrictBoundaries != _cachedConfiguration?.hasStrictBoundaries ||
// Other layout information were changed
minimumInteritemSpacing != calendarLayout.minimumInteritemSpacing ||
minimumLineSpacing != calendarLayout.minimumLineSpacing ||
diff --git a/Sources/JTAppleCalendar/JTACMonthCell.swift b/Sources/JTAppleCalendar/JTACMonthCell.swift
new file mode 100644
index 00000000..cd0a2daf
--- /dev/null
+++ b/Sources/JTAppleCalendar/JTACMonthCell.swift
@@ -0,0 +1,143 @@
+//
+// JTACMonthCell.swift
+//
+// Copyright (c) 2016-2020 JTAppleCalendar (https://github.com/patchthecode/JTAppleCalendar)
+//
+// 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.
+//
+
+import Foundation
+import UIKit
+
+public protocol JTACCellMonthViewDelegate: AnyObject {
+ func monthView(_ monthView: JTACCellMonthView,
+ drawingFor segmentRect: CGRect,
+ with date: Date,
+ dateOwner: DateOwner,
+ monthIndex: Int)
+}
+
+open class JTACMonthCell: UICollectionViewCell {
+ @IBOutlet var monthView: JTACCellMonthView?
+ weak var delegate: JTACCellMonthViewDelegate?
+
+ func setupWith(configurationParameters: ConfigurationParameters,
+ month: Month,
+ delegate: JTACCellMonthViewDelegate) {
+ guard let monthView = monthView else { assert(false); return }
+ self.delegate = delegate
+ monthView.setupWith(configurationParameters: configurationParameters,
+ month: month,
+ delegate: self)
+ }
+}
+
+extension JTACMonthCell: JTACCellMonthViewDelegate {
+ public func monthView(_ monthView: JTACCellMonthView,
+ drawingFor segmentRect: CGRect,
+ with date: Date,
+ dateOwner: DateOwner,
+ monthIndex: Int) {
+ delegate?.monthView(monthView, drawingFor: segmentRect, with: date, dateOwner: dateOwner, monthIndex: monthIndex)
+ }
+}
+
+
+
+
+open class JTACCellMonthView: UIView {
+ var sectionInset = UIEdgeInsets.zero
+ var month: Month!
+ var configurationParameters: ConfigurationParameters!
+ weak var delegate: JTACCellMonthViewDelegate?
+ var scrollDirection: UICollectionView.ScrollDirection = .horizontal
+
+ func setupWith(configurationParameters: ConfigurationParameters, month: Month, delegate: JTACCellMonthViewDelegate? = nil) {
+ self.configurationParameters = configurationParameters
+ self.delegate = delegate
+ self.month = month
+
+ setNeedsDisplay() // force reloading of the drawRect code to update the view.
+ }
+
+ override open func draw(_ rect: CGRect) {
+ super.draw(rect)
+
+ var xCellOffset: CGFloat = 0
+ var yCellOffset: CGFloat = 0
+
+ let numberOfDaysInCurrentSection = month.sections.first!
+ for dayCounter in 1...numberOfDaysInCurrentSection {
+
+ let width = (frame.width - ((sectionInset.left / 7) + (sectionInset.right / 7))) / 7
+ let height = (frame.height - sectionInset.top - sectionInset.bottom) / 6
+
+ let rect = CGRect(x: xCellOffset, y: yCellOffset, width: width, height: height)
+ guard let dateWithOwner = dateFromIndex(dayCounter - 1, month: month,
+ startOfMonthCache: configurationParameters.startDate,
+ endOfMonthCache: configurationParameters.endDate) else { continue }
+
+
+ delegate?.monthView(self,
+ drawingFor: rect,
+ with: dateWithOwner.date,
+ dateOwner: dateWithOwner.owner,
+ monthIndex: month.index)
+
+ xCellOffset += width
+
+ if dayCounter == numberOfDaysInCurrentSection || dayCounter % maxNumberOfDaysInWeek == 0 {
+ // We are at the last item in the section
+ // && if we have headers
+ xCellOffset = sectionInset.left
+ yCellOffset += height
+ }
+ }
+ }
+
+ private func dateFromIndex(_ index: Int, month: Month, startOfMonthCache: Date, endOfMonthCache: Date) -> (date: Date, owner: DateOwner)? { // Returns nil if date is out of scope
+ // Calculate the offset
+ let offSet = month.inDates
+
+ let dayIndex = month.startDayIndex + index - offSet
+ var dateOwner: DateOwner
+
+ guard let validDate = configurationParameters.calendar.date(byAdding: .day, value: dayIndex, to: startOfMonthCache) else { return nil }
+
+ if index >= offSet && index < month.numberOfDaysInMonth + offSet {
+ dateOwner = .thisMonth
+ } else if index < offSet {
+ // This is a preDate
+
+ if validDate < startOfMonthCache {
+ dateOwner = .previousMonthOutsideBoundary
+ } else {
+ dateOwner = .previousMonthWithinBoundary
+ }
+ } else {
+ // This is a postDate
+ if validDate > endOfMonthCache {
+ dateOwner = .followingMonthOutsideBoundary
+ } else {
+ dateOwner = .followingMonthWithinBoundary
+ }
+ }
+ return (validDate, dateOwner)
+ }
+}
diff --git a/Sources/JTACMonthDelegateProtocol.swift b/Sources/JTAppleCalendar/JTACMonthDelegateProtocol.swift
similarity index 91%
rename from Sources/JTACMonthDelegateProtocol.swift
rename to Sources/JTAppleCalendar/JTACMonthDelegateProtocol.swift
index 00cc6d9e..f410f0cd 100644
--- a/Sources/JTACMonthDelegateProtocol.swift
+++ b/Sources/JTAppleCalendar/JTACMonthDelegateProtocol.swift
@@ -1,7 +1,7 @@
//
// JTACMonthDelegateProtocol.swift
//
-// Copyright (c) 2016-2017 JTAppleCalendar (https://github.com/patchthecode/JTAppleCalendar)
+// Copyright (c) 2016-2020 JTAppleCalendar (https://github.com/patchthecode/JTAppleCalendar)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
@@ -21,11 +21,13 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
+import Foundation
+import UIKit
-protocol JTACMonthDelegateProtocol: class {
+protocol JTACMonthDelegateProtocol: AnyObject {
// Variables
var allowsDateCellStretching: Bool {get set}
- var _cachedConfiguration: ConfigurationParameters! {get set}
+ var _cachedConfiguration: ConfigurationParameters? {get set}
var calendarDataSource: JTACMonthViewDataSource? {get set}
var cellSize: CGFloat {get set}
var anchorDate: Date? {get set}
diff --git a/Sources/JTACMonthLayout.swift b/Sources/JTAppleCalendar/JTACMonthLayout.swift
similarity index 76%
rename from Sources/JTACMonthLayout.swift
rename to Sources/JTAppleCalendar/JTACMonthLayout.swift
index a2f1d58b..dfb66430 100644
--- a/Sources/JTACMonthLayout.swift
+++ b/Sources/JTAppleCalendar/JTACMonthLayout.swift
@@ -1,7 +1,7 @@
//
// JTACMonthLayout.swift
//
-// Copyright (c) 2016-2017 JTAppleCalendar (https://github.com/patchthecode/JTAppleCalendar)
+// Copyright (c) 2016-2020 JTAppleCalendar (https://github.com/patchthecode/JTAppleCalendar)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
@@ -22,6 +22,9 @@
// THE SOFTWARE.
//
+import Foundation
+import UIKit
+
/// Methods in this class are meant to be overridden and will be called by its collection view to gather layout information.
class JTACMonthLayout: UICollectionViewLayout, JTACMonthLayoutProtocol {
@@ -31,7 +34,7 @@ class JTACMonthLayout: UICollectionViewLayout, JTACMonthLayoutProtocol {
var lastSetCollectionViewSize: CGRect = .zero
var cellSize: CGSize = CGSize.zero
- var shouldUseUserItemSizeInsteadOfDefault: Bool { return delegate.cellSize == 0 ? false: true }
+ var shouldUseUserItemSizeInsteadOfDefault: Bool { return (delegate?.cellSize ?? 0) == 0 ? false: true }
var scrollDirection: UICollectionView.ScrollDirection = .horizontal
var maxMissCount: Int = 0
var cellCache: [Int: [(item: Int, section: Int, xOffset: CGFloat, yOffset: CGFloat, width: CGFloat, height: CGFloat)]] = [:]
@@ -46,7 +49,10 @@ class JTACMonthLayout: UICollectionViewLayout, JTACMonthLayoutProtocol {
var headerSizes: [AnyHashable:CGFloat] = [:]
var focusIndexPath: IndexPath?
var isCalendarLayoutLoaded: Bool { return !cellCache.isEmpty }
- var layoutIsReadyToBePrepared: Bool { return !(!cellCache.isEmpty || delegate.calendarDataSource == nil) }
+ var layoutIsReadyToBePrepared: Bool {
+ guard let delegate = delegate else { return false }
+ return !(!cellCache.isEmpty || delegate.calendarDataSource == nil)
+ }
var monthMap: [Int: Int] = [:]
var numberOfRows: Int = 0
@@ -54,7 +60,7 @@ class JTACMonthLayout: UICollectionViewLayout, JTACMonthLayoutProtocol {
var thereAreHeaders: Bool { return !headerSizes.isEmpty }
var thereAreDecorationViews = false
- weak var delegate: JTACMonthDelegateProtocol!
+ weak var delegate: JTACMonthDelegateProtocol?
var currentHeader: (section: Int, size: CGSize)? // Tracks the current header size
var currentCell: (section: Int, width: CGFloat, height: CGFloat)? // Tracks the current cell size
@@ -63,6 +69,7 @@ class JTACMonthLayout: UICollectionViewLayout, JTACMonthLayoutProtocol {
var xCellOffset: CGFloat = 0
var yCellOffset: CGFloat = 0
var endSeparator: CGFloat = 0
+ override var flipsHorizontallyInOppositeLayoutDirection: Bool { return true }
var delayedExecutionClosure: [(() -> Void)] = []
func executeDelayedTasks() {
@@ -85,7 +92,7 @@ class JTACMonthLayout: UICollectionViewLayout, JTACMonthLayoutProtocol {
}
var updatedLayoutCellSize: CGSize {
- guard let cachedConfiguration = delegate._cachedConfiguration else { return .zero }
+ guard let delegate = delegate, let cachedConfiguration = delegate._cachedConfiguration else { return .zero }
// Default Item height and width
var height: CGFloat = collectionView!.bounds.size.height / CGFloat(cachedConfiguration.numberOfRows)
@@ -124,8 +131,8 @@ class JTACMonthLayout: UICollectionViewLayout, JTACMonthLayoutProtocol {
lastSetCollectionViewSize = collectionView!.frame
if !layoutIsReadyToBePrepared {
- // Layoout may not be ready, but user might have reloaded with an anchor date
- let requestedOffset = delegate.requestedContentOffset
+ // Layout may not be ready, but user might have reloaded with an anchor date
+ let requestedOffset = delegate?.requestedContentOffset ?? .zero
if requestedOffset != .zero { collectionView!.setContentOffset(requestedOffset, animated: false) }
// execute any other delayed tasks
@@ -148,7 +155,7 @@ class JTACMonthLayout: UICollectionViewLayout, JTACMonthLayoutProtocol {
}
// Set the first content offset only once. This will prevent scrolling animation on viewDidload.
- if !firstContentOffsetWasSet {
+ if !firstContentOffsetWasSet, let delegate = delegate {
firstContentOffsetWasSet = true
let firstContentOffset = delegate.requestedContentOffset
collectionView!.setContentOffset(firstContentOffset, animated: false)
@@ -159,10 +166,11 @@ class JTACMonthLayout: UICollectionViewLayout, JTACMonthLayoutProtocol {
}
func setupDataFromDelegate() {
+ guard let delegate = delegate, let cachedConfiguration = delegate._cachedConfiguration else { return }
// get information from the delegate
headerSizes = delegate.sizesForMonthSection() // update first. Other variables below depend on it
- strictBoundaryRulesShouldApply = thereAreHeaders || delegate._cachedConfiguration.hasStrictBoundaries
- numberOfRows = delegate._cachedConfiguration.numberOfRows
+ strictBoundaryRulesShouldApply = thereAreHeaders || cachedConfiguration.hasStrictBoundaries
+ numberOfRows = cachedConfiguration.numberOfRows
monthMap = delegate.monthMap
allowsDateCellStretching = delegate.allowsDateCellStretching
monthInfo = delegate.monthInfo
@@ -194,144 +202,6 @@ class JTACMonthLayout: UICollectionViewLayout, JTACMonthLayoutProtocol {
}
return retval
}
-
- func configureHorizontalLayout() {
- var virtualSection = 0
- var totalDayCounter = 0
- let fullSection = numberOfRows * maxNumberOfDaysInWeek
-
- xCellOffset = sectionInset.left
- endSeparator = sectionInset.left + sectionInset.right
-
- for aMonth in monthInfo {
- for numberOfDaysInCurrentSection in aMonth.sections {
- // Generate and cache the headers
- if let aHeaderAttr = determineToApplySupplementaryAttribs(0, section: virtualSection) {
- headerCache[virtualSection] = aHeaderAttr
- if strictBoundaryRulesShouldApply {
- contentWidth += aHeaderAttr.width
- yCellOffset = aHeaderAttr.height
- }
- }
- // Generate and cache the cells
- for dayCounter in 1...numberOfDaysInCurrentSection {
- guard let attribute = determineToApplyAttribs(dayCounter - 1, section: virtualSection) else { continue }
- if cellCache[virtualSection] == nil { cellCache[virtualSection] = [] }
- cellCache[virtualSection]!.append(attribute)
- lastWrittenCellAttribute = attribute
- xCellOffset += attribute.width
-
- if strictBoundaryRulesShouldApply {
- if dayCounter == numberOfDaysInCurrentSection || dayCounter % maxNumberOfDaysInWeek == 0 {
- // We are at the last item in the section
- // && if we have headers
- xCellOffset = sectionInset.left
- yCellOffset += attribute.height
- }
- } else {
- totalDayCounter += 1
- if totalDayCounter % fullSection == 0 {
- yCellOffset = 0
- xCellOffset = sectionInset.left
- contentWidth += (attribute.width * 7) + endSeparator
- xStride = contentWidth
- endOfSectionOffsets.append(contentWidth)
- } else {
- if totalDayCounter >= delegate.totalDays {
- contentWidth += (attribute.width * 7) + endSeparator
- endOfSectionOffsets.append(contentWidth)
- }
- if totalDayCounter % maxNumberOfDaysInWeek == 0 {
- xCellOffset = sectionInset.left
- yCellOffset += attribute.height
- }
- }
- }
- }
-
- // Save the content size for each section
- if strictBoundaryRulesShouldApply {
- contentWidth += endSeparator
- endOfSectionOffsets.append(contentWidth)
- xStride = endOfSectionOffsets[virtualSection]
- }
- virtualSection += 1
- }
- }
- contentHeight = self.collectionView!.bounds.size.height
- }
-
- func configureVerticalLayout() {
- var virtualSection = 0
- var totalDayCounter = 0
- let fullSection = numberOfRows * maxNumberOfDaysInWeek
-
- xCellOffset = sectionInset.left
- yCellOffset = sectionInset.top
- contentHeight = sectionInset.top
- endSeparator = sectionInset.top + sectionInset.bottom
-
- for aMonth in monthInfo {
- for numberOfDaysInCurrentSection in aMonth.sections {
- // Generate and cache the headers
- if let aHeaderAttr = determineToApplySupplementaryAttribs(0, section: virtualSection) {
- headerCache[virtualSection] = aHeaderAttr
- if strictBoundaryRulesShouldApply {
- contentHeight += aHeaderAttr.height
- yCellOffset += aHeaderAttr.height
- }
- }
- // Generate and cache the cells
- for dayCounter in 1...numberOfDaysInCurrentSection {
- totalDayCounter += 1
- guard let attribute = determineToApplyAttribs(dayCounter - 1, section: virtualSection) else { continue }
- if cellCache[virtualSection] == nil { cellCache[virtualSection] = [] }
- cellCache[virtualSection]!.append(attribute)
- lastWrittenCellAttribute = attribute
- xCellOffset += attribute.width
-
- if strictBoundaryRulesShouldApply {
- if dayCounter == numberOfDaysInCurrentSection || dayCounter % maxNumberOfDaysInWeek == 0 {
- // We are at the last item in the
- // section && if we have headers
-
- xCellOffset = sectionInset.left
- yCellOffset += attribute.height
- contentHeight += attribute.height
-
- if dayCounter == numberOfDaysInCurrentSection {
- yCellOffset += sectionInset.top
- contentHeight += sectionInset.top
- endOfSectionOffsets.append(contentHeight - sectionInset.top)
- }
- }
- } else {
- if totalDayCounter % fullSection == 0 {
-
- yCellOffset += attribute.height + sectionInset.top
- xCellOffset = sectionInset.left
- contentHeight = yCellOffset
- endOfSectionOffsets.append(contentHeight - sectionInset.top)
-
- } else {
- if totalDayCounter >= delegate.totalDays {
- yCellOffset += attribute.height + sectionInset.top
- contentHeight = yCellOffset
- endOfSectionOffsets.append(contentHeight - sectionInset.top)
- }
-
- if totalDayCounter % maxNumberOfDaysInWeek == 0 {
- xCellOffset = sectionInset.left
- yCellOffset += attribute.height
- }
- }
- }
- }
- virtualSection += 1
- }
- }
- contentWidth = self.collectionView!.bounds.size.width
- }
/// Returns the width and height of the collection view’s contents.
/// The width and height of the collection view’s contents.
@@ -440,9 +310,6 @@ class JTACMonthLayout: UICollectionViewLayout, JTACMonthLayoutProtocol {
}
}
-
-
-
let startOfSection = endOfSectionOffsets[section]
let endOfSection = endOfSectionOffsets[section + 1]
return endOfSection - startOfSection
@@ -453,8 +320,8 @@ class JTACMonthLayout: UICollectionViewLayout, JTACMonthLayoutProtocol {
let attrib = UICollectionViewLayoutAttributes(forCellWith: IndexPath(item: item, section: section))
attrib.frame = CGRect(x: cachedValue.xOffset, y: cachedValue.yOffset, width: cachedValue.width, height: cachedValue.height)
- if minimumInteritemSpacing > -1, minimumLineSpacing > -1 {
- var frame = attrib.frame.insetBy(dx: minimumInteritemSpacing, dy: minimumLineSpacing)
+ if minimumInteritemSpacing > 0, minimumLineSpacing > 0 {
+ var frame = attrib.frame.insetBy(dx: minimumInteritemSpacing / 2, dy: minimumLineSpacing / 2)
if frame == .null { frame = attrib.frame.insetBy(dx: 0, dy: 0) }
attrib.frame = frame
}
@@ -506,7 +373,7 @@ class JTACMonthLayout: UICollectionViewLayout, JTACMonthLayoutProtocol {
let retval = UICollectionViewLayoutAttributes(forDecorationViewOfKind: decorationViewID, with: indexPath)
decorationCache[indexPath] = retval
- retval.frame = delegate.sizeOfDecorationView(indexPath: indexPath)
+ retval.frame = delegate?.sizeOfDecorationView(indexPath: indexPath) ?? .zero
retval.zIndex = -1
return retval
}
diff --git a/Sources/JTAppleCalendar/JTACMonthLayoutHorizontalCalendar.swift b/Sources/JTAppleCalendar/JTACMonthLayoutHorizontalCalendar.swift
new file mode 100644
index 00000000..76e2a0b7
--- /dev/null
+++ b/Sources/JTAppleCalendar/JTACMonthLayoutHorizontalCalendar.swift
@@ -0,0 +1,91 @@
+//
+// JTACMonthLayoutHorizontalCalendar.swift
+//
+// Copyright (c) 2016-2020 JTAppleCalendar (https://github.com/patchthecode/JTAppleCalendar)
+//
+// 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.
+//
+
+extension JTACMonthLayout {
+ func configureHorizontalLayout() {
+ var virtualSection = 0
+ var totalDayCounter = 0
+ let fullSection = numberOfRows * maxNumberOfDaysInWeek
+
+ xCellOffset = sectionInset.left
+ endSeparator = sectionInset.left + sectionInset.right
+
+ for aMonth in monthInfo {
+ for numberOfDaysInCurrentSection in aMonth.sections {
+ // Generate and cache the headers
+ if let aHeaderAttr = determineToApplySupplementaryAttribs(0, section: virtualSection) {
+ headerCache[virtualSection] = aHeaderAttr
+ if strictBoundaryRulesShouldApply {
+ contentWidth += aHeaderAttr.width
+ yCellOffset = aHeaderAttr.height
+ }
+ }
+ // Generate and cache the cells
+ for dayCounter in 1...numberOfDaysInCurrentSection {
+ guard let attribute = determineToApplyAttribs(dayCounter - 1, section: virtualSection) else { continue }
+ if cellCache[virtualSection] == nil { cellCache[virtualSection] = [] }
+ cellCache[virtualSection]!.append(attribute)
+ lastWrittenCellAttribute = attribute
+ xCellOffset += attribute.width
+
+ if strictBoundaryRulesShouldApply {
+ if dayCounter == numberOfDaysInCurrentSection || dayCounter % maxNumberOfDaysInWeek == 0 {
+ // We are at the last item in the section
+ // && if we have headers
+ xCellOffset = sectionInset.left
+ yCellOffset += attribute.height
+ }
+ } else {
+ totalDayCounter += 1
+ if totalDayCounter % fullSection == 0 {
+ yCellOffset = 0
+ xCellOffset = sectionInset.left
+ contentWidth += (attribute.width * 7) + endSeparator
+ xStride = contentWidth
+ endOfSectionOffsets.append(contentWidth)
+ } else {
+ if totalDayCounter >= delegate?.totalDays ?? 0 {
+ contentWidth += (attribute.width * 7) + endSeparator
+ endOfSectionOffsets.append(contentWidth)
+ }
+ if totalDayCounter % maxNumberOfDaysInWeek == 0 {
+ xCellOffset = sectionInset.left
+ yCellOffset += attribute.height
+ }
+ }
+ }
+ }
+
+ // Save the content size for each section
+ if strictBoundaryRulesShouldApply {
+ contentWidth += endSeparator
+ endOfSectionOffsets.append(contentWidth)
+ xStride = endOfSectionOffsets[virtualSection]
+ }
+ virtualSection += 1
+ }
+ }
+ contentHeight = self.collectionView!.bounds.size.height
+ }
+}
diff --git a/Sources/JTACMonthLayoutProtocol.swift b/Sources/JTAppleCalendar/JTACMonthLayoutProtocol.swift
similarity index 92%
rename from Sources/JTACMonthLayoutProtocol.swift
rename to Sources/JTAppleCalendar/JTACMonthLayoutProtocol.swift
index badc2bd6..be8fd09b 100644
--- a/Sources/JTACMonthLayoutProtocol.swift
+++ b/Sources/JTAppleCalendar/JTACMonthLayoutProtocol.swift
@@ -1,7 +1,7 @@
//
// JTACMonthLayoutProtocol.swift
//
-// Copyright (c) 2016-2017 JTAppleCalendar (https://github.com/patchthecode/JTAppleCalendar)
+// Copyright (c) 2016-2020 JTAppleCalendar (https://github.com/patchthecode/JTAppleCalendar)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
@@ -22,8 +22,9 @@
// THE SOFTWARE.
//
+import UIKit
-protocol JTACMonthLayoutProtocol: class {
+protocol JTACMonthLayoutProtocol: AnyObject {
var minimumInteritemSpacing: CGFloat {get set}
var minimumLineSpacing: CGFloat {get set}
var sectionInset: UIEdgeInsets {get set}
diff --git a/Sources/JTAppleCalendar/JTACMonthLayoutVerticalCalendar.swift b/Sources/JTAppleCalendar/JTACMonthLayoutVerticalCalendar.swift
new file mode 100644
index 00000000..0c341d44
--- /dev/null
+++ b/Sources/JTAppleCalendar/JTACMonthLayoutVerticalCalendar.swift
@@ -0,0 +1,98 @@
+//
+// JTACMonthLayoutVerticalCalendar.swift
+//
+// Copyright (c) 2016-2020 JTAppleCalendar (https://github.com/patchthecode/JTAppleCalendar)
+//
+// 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.
+//
+
+extension JTACMonthLayout {
+
+ func configureVerticalLayout() {
+ var virtualSection = 0
+ var totalDayCounter = 0
+ let fullSection = numberOfRows * maxNumberOfDaysInWeek
+
+ xCellOffset = sectionInset.left
+ yCellOffset = sectionInset.top
+ contentHeight = sectionInset.top
+ endSeparator = sectionInset.top + sectionInset.bottom
+
+ for aMonth in monthInfo {
+ for numberOfDaysInCurrentSection in aMonth.sections {
+ // Generate and cache the headers
+ if let aHeaderAttr = determineToApplySupplementaryAttribs(0, section: virtualSection) {
+ headerCache[virtualSection] = aHeaderAttr
+ if strictBoundaryRulesShouldApply {
+ contentHeight += aHeaderAttr.height
+ yCellOffset += aHeaderAttr.height
+ }
+ }
+ // Generate and cache the cells
+ for dayCounter in 1...numberOfDaysInCurrentSection {
+ totalDayCounter += 1
+ guard let attribute = determineToApplyAttribs(dayCounter - 1, section: virtualSection) else { continue }
+ if cellCache[virtualSection] == nil { cellCache[virtualSection] = [] }
+ cellCache[virtualSection]!.append(attribute)
+ lastWrittenCellAttribute = attribute
+ xCellOffset += attribute.width
+
+ if strictBoundaryRulesShouldApply {
+ if dayCounter == numberOfDaysInCurrentSection || dayCounter % maxNumberOfDaysInWeek == 0 {
+ // We are at the last item in the
+ // section && if we have headers
+
+ xCellOffset = sectionInset.left
+ yCellOffset += attribute.height
+ contentHeight += attribute.height
+
+ if dayCounter == numberOfDaysInCurrentSection {
+ yCellOffset += sectionInset.top
+ contentHeight += sectionInset.top
+ endOfSectionOffsets.append(contentHeight - sectionInset.top)
+ }
+ }
+ } else {
+ if totalDayCounter % fullSection == 0 {
+
+ yCellOffset += attribute.height + sectionInset.top
+ xCellOffset = sectionInset.left
+ contentHeight = yCellOffset
+ endOfSectionOffsets.append(contentHeight - sectionInset.top)
+
+ } else {
+ if totalDayCounter >= delegate?.totalDays ?? 0 {
+ yCellOffset += attribute.height + sectionInset.top
+ contentHeight = yCellOffset
+ endOfSectionOffsets.append(contentHeight - sectionInset.top)
+ }
+
+ if totalDayCounter % maxNumberOfDaysInWeek == 0 {
+ xCellOffset = sectionInset.left
+ yCellOffset += attribute.height
+ }
+ }
+ }
+ }
+ virtualSection += 1
+ }
+ }
+ contentWidth = self.collectionView!.bounds.size.width
+ }
+}
diff --git a/Sources/JTACMonthQueryFunctions.swift b/Sources/JTAppleCalendar/JTACMonthQueryFunctions.swift
similarity index 96%
rename from Sources/JTACMonthQueryFunctions.swift
rename to Sources/JTAppleCalendar/JTACMonthQueryFunctions.swift
index ec867781..8792a36b 100644
--- a/Sources/JTACMonthQueryFunctions.swift
+++ b/Sources/JTAppleCalendar/JTACMonthQueryFunctions.swift
@@ -1,7 +1,7 @@
//
// JTACMonthQueryFunctions.swift
//
-// Copyright (c) 2016-2017 JTAppleCalendar (https://github.com/patchthecode/JTAppleCalendar)
+// Copyright (c) 2016-2020 JTAppleCalendar (https://github.com/patchthecode/JTAppleCalendar)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
@@ -22,6 +22,8 @@
// THE SOFTWARE.
//
+import UIKit
+
extension JTACMonthView {
func validForwardAndBackwordSelectedIndexes(forIndexPath indexPath: IndexPath, restrictToSection: Bool = true) -> (forwardIndex: IndexPath?, backIndex: IndexPath?, set: Set) {
var retval: (forwardIndex: IndexPath?, backIndex: IndexPath?, set: Set) = (forwardIndex: nil, backIndex: nil, set: [])
@@ -61,6 +63,7 @@ extension JTACMonthView {
switch scrollingMode {
case .stopAtEachCalendarFrame, .stopAtEach, .nonStopTo:
+ assert(fixedScrollSize != 0, "You should not try to divide by zero.")
let frameSection = theTargetContentOffset / fixedScrollSize
let roundedFrameSection = floor(frameSection)
if scrollDirection == .horizontal {
@@ -132,9 +135,9 @@ extension JTACMonthView {
}
func indexPathOfdateCellCounterPath(_ date: Date, dateOwner: DateOwner) -> IndexPath? {
- if (_cachedConfiguration.generateInDates == .off ||
- _cachedConfiguration.generateInDates == .forFirstMonthOnly) &&
- _cachedConfiguration.generateOutDates == .off {
+ if (_cachedConfiguration?.generateInDates == .off ||
+ _cachedConfiguration?.generateInDates == .forFirstMonthOnly) &&
+ _cachedConfiguration?.generateOutDates == .off {
return nil
}
var retval: IndexPath?
@@ -311,8 +314,11 @@ extension JTACMonthView {
let selectedPosition = { [unowned self] () -> SelectionRangePosition in
let selectedDates = self.selectedDatesSet
if !selectedDates.contains(date) || selectedDates.isEmpty { return .none }
-
- let validSelectedIndexes = self.validForwardAndBackwordSelectedIndexes(forIndexPath: indexPath)
+
+ let isLTRDirection = UIView.userInterfaceLayoutDirection(
+ for: self.semanticContentAttribute) == .leftToRight
+ let restrictToSection = self.rangeSelectionMode == .segmented
+ let validSelectedIndexes = self.validForwardAndBackwordSelectedIndexes(forIndexPath: indexPath, restrictToSection: restrictToSection)
let dateBeforeIsSelected = validSelectedIndexes.backIndex != nil
let dateAfterIsSelected = validSelectedIndexes.forwardIndex != nil
@@ -321,9 +327,9 @@ extension JTACMonthView {
if dateBeforeIsSelected, dateAfterIsSelected {
position = .middle
} else if !dateBeforeIsSelected, dateAfterIsSelected {
- position = .left
+ position = isLTRDirection ? .left : .right
} else if dateBeforeIsSelected, !dateAfterIsSelected {
- position = .right
+ position = isLTRDirection ? .right : .left
} else if !dateBeforeIsSelected, !dateAfterIsSelected {
position = .full
} else {
@@ -371,7 +377,7 @@ extension JTACMonthView {
}
if let monthDate = calendar.date(byAdding: .month, value: monthIndex, to: startDateCache) {
let monthNumber = calendar.dateComponents([.month], from: monthDate)
- let numberOfRowsForSection = monthData.numberOfRows(for: section, developerSetRows: _cachedConfiguration.numberOfRows)
+ let numberOfRowsForSection = monthData.numberOfRows(for: section, developerSetRows: _cachedConfiguration?.numberOfRows ?? 0)
return ((startDate, endDate), monthNumber.month!, numberOfRowsForSection)
}
return nil
diff --git a/Sources/JTACMonthReusableView.swift b/Sources/JTAppleCalendar/JTACMonthReusableView.swift
similarity index 94%
rename from Sources/JTACMonthReusableView.swift
rename to Sources/JTAppleCalendar/JTACMonthReusableView.swift
index a9791a97..92254ccc 100644
--- a/Sources/JTACMonthReusableView.swift
+++ b/Sources/JTAppleCalendar/JTACMonthReusableView.swift
@@ -1,7 +1,7 @@
//
// JTACMonthReusableView.swift
//
-// Copyright (c) 2016-2017 JTAppleCalendar (https://github.com/patchthecode/JTAppleCalendar)
+// Copyright (c) 2016-2020 JTAppleCalendar (https://github.com/patchthecode/JTAppleCalendar)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
@@ -22,6 +22,9 @@
// THE SOFTWARE.
//
+import Foundation
+import UIKit
+
/// The header view class of the calendar
@available(*, unavailable, renamed: "JTACMonthReusableView")
open class JTAppleCollectionReusableView: UICollectionReusableView {}
diff --git a/Sources/JTACMonthView.swift b/Sources/JTAppleCalendar/JTACMonthView.swift
similarity index 87%
rename from Sources/JTACMonthView.swift
rename to Sources/JTAppleCalendar/JTACMonthView.swift
index d47053bf..7b1ab1a6 100644
--- a/Sources/JTACMonthView.swift
+++ b/Sources/JTAppleCalendar/JTACMonthView.swift
@@ -1,7 +1,7 @@
//
// JTACMonthView.swift
//
-// Copyright (c) 2016-2017 JTAppleCalendar (https://github.com/patchthecode/JTAppleCalendar)
+// Copyright (c) 2016-2020 JTAppleCalendar (https://github.com/patchthecode/JTAppleCalendar)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
@@ -22,6 +22,9 @@
// THE SOFTWARE.
//
+import Foundation
+import UIKit
+
let maxNumberOfDaysInWeek = 7 // Should not be changed
let maxNumberOfRowsPerMonth = 6 // Should not be changed
let developerErrorMessage = "There was an error in this code section. Please contact the developer on GitHub"
@@ -43,6 +46,9 @@ open class JTACMonthView: UICollectionView {
}
}
+ /// Stores the first and last selected date cel
+ open var selectedCells: (first: (date: Date, indexPath: IndexPath)?, last: (date: Date, indexPath: IndexPath)?)
+
/// The scroll direction of the sections in JTAppleCalendar.
open var scrollDirection: UICollectionView.ScrollDirection = .horizontal
@@ -57,12 +63,10 @@ open class JTACMonthView: UICollectionView {
/// then whenever you click on a datecell, you may notice a very fast
/// refreshing of the date-cells both left and right of the cell you
/// just selected.
- @available(*, unavailable, renamed: "allowsRangedSelection")
- open var isRangeSelectionUsed: Bool = false
- open var allowsRangedSelection: Bool = false {
- didSet { allowsMultipleSelection = true }
- }
-
+ open var allowsRangedSelection: Bool = false
+
+ open var rangeSelectionMode: RangeSelectionMode = .segmented
+
/// The object that acts as the delegate of the calendar view.
weak open var calendarDelegate: JTACMonthViewDelegate? {
didSet { lastMonthSize = sizesForMonthSection() }
@@ -106,7 +110,7 @@ open class JTACMonthView: UICollectionView {
}
// Configuration parameters from the dataSource
- var _cachedConfiguration: ConfigurationParameters!
+ var _cachedConfiguration: ConfigurationParameters?
// Set the start of the month
var startOfMonthCache: Date!
// Set the end of month
@@ -155,9 +159,28 @@ open class JTACMonthView: UICollectionView {
return retval
}
- open var sectionInset: UIEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
- open var minimumInteritemSpacing: CGFloat = 0
- open var minimumLineSpacing: CGFloat = 0
+ var _sectionInset: UIEdgeInsets = .zero
+ open var sectionInset: UIEdgeInsets {
+ set {
+ _sectionInset.top = newValue.top < 0 ? 0 : newValue.top
+ _sectionInset.bottom = newValue.bottom < 0 ? 0 : newValue.bottom
+ _sectionInset.left = newValue.left < 0 ? 0 : newValue.left
+ _sectionInset.right = newValue.right < 0 ? 0 : newValue.right
+ }
+ get { return _sectionInset }
+ }
+
+ var _minimumInteritemSpacing: CGFloat = 0
+ open var minimumInteritemSpacing: CGFloat {
+ set { _minimumInteritemSpacing = newValue < 0 ? 0 : newValue }
+ get { return _minimumInteritemSpacing }
+ }
+
+ var _minimumLineSpacing: CGFloat = 0
+ open var minimumLineSpacing: CGFloat {
+ set { _minimumLineSpacing = newValue < 0 ? 0 : newValue }
+ get { return _minimumLineSpacing }
+ }
lazy var theData: CalendarData = {
return self.setupMonthInfoDataForStartAndEndDate()
@@ -167,7 +190,7 @@ open class JTACMonthView: UICollectionView {
var monthMap: [Int: Int] {
get { return theData.sectionToMonthMap }
- set { theData.sectionToMonthMap = monthMap }
+ set { theData.sectionToMonthMap = newValue }
}
var decelerationRateMatchingScrollingMode: CGFloat {
@@ -194,7 +217,6 @@ open class JTACMonthView: UICollectionView {
}
}
-@available(iOS 9.0, *)
extension JTACMonthView {
/// A semantic description of the view’s contents, used to determine whether the view should be flipped when switching between left-to-right and right-to-left layouts.
open override var semanticContentAttribute: UISemanticContentAttribute {
diff --git a/Sources/JTACMonthViewProtocols.swift b/Sources/JTAppleCalendar/JTACMonthViewProtocols.swift
similarity index 86%
rename from Sources/JTACMonthViewProtocols.swift
rename to Sources/JTAppleCalendar/JTACMonthViewProtocols.swift
index 3f400772..00718dea 100644
--- a/Sources/JTACMonthViewProtocols.swift
+++ b/Sources/JTAppleCalendar/JTACMonthViewProtocols.swift
@@ -1,7 +1,7 @@
//
// JTACMonthViewProtocols.swift
//
-// Copyright (c) 2016-2017 JTAppleCalendar (https://github.com/patchthecode/JTAppleCalendar)
+// Copyright (c) 2016-2020 JTAppleCalendar (https://github.com/patchthecode/JTAppleCalendar)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
@@ -22,14 +22,17 @@
// THE SOFTWARE.
//
+import Foundation
+import UIKit
+
/// The JTAppleCalendarMonthViewDataSource protocol is adopted by an
/// object that mediates the application’s data model for a
/// the JTAppleCalendarMonthViewDataSource object. data source provides the
/// the calendar-view object with the information it needs to construct and
/// then modify it self
@available(*, unavailable, renamed: "JTACMonthViewDataSource")
-public protocol JTAppleCalendarViewDataSource{}
-public protocol JTACMonthViewDataSource: class {
+public protocol JTAppleCalendarViewDataSource: AnyObject {}
+public protocol JTACMonthViewDataSource: AnyObject {
/// Asks the data source to return the start and end boundary dates
/// as well as the calendar to use. You should properly configure
/// your calendar at this point.
@@ -44,8 +47,8 @@ public protocol JTACMonthViewDataSource: class {
/// JTAppleCalendarMonthViewDelegate protocol Optional methods of the protocol
/// allow the delegate to manage selections, and configure the cells
@available(*, unavailable, renamed: "JTACMonthViewDelegate")
-public protocol JTAppleCalendarViewDelegate: class {}
-public protocol JTACMonthViewDelegate: class {
+public protocol JTAppleCalendarViewDelegate: AnyObject {}
+public protocol JTACMonthViewDelegate: AnyObject {
/// Asks the delegate if selecting the date-cell with a specified date is
/// allowed
/// - Parameters:
@@ -54,7 +57,7 @@ public protocol JTACMonthViewDelegate: class {
/// - cell: The date-cell view. This can be customized at this point.
/// - cellState: The month the date-cell belongs to.
/// - returns: A Bool value indicating if the operation can be done.
- func calendar(_ calendar: JTACMonthView, shouldSelectDate date: Date, cell: JTACDayCell?, cellState: CellState) -> Bool
+ func calendar(_ calendar: JTACMonthView, shouldSelectDate date: Date, cell: JTACDayCell?, cellState: CellState, indexPath: IndexPath) -> Bool
/// Asks the delegate if de-selecting the
/// date-cell with a specified date is allowed
@@ -64,7 +67,7 @@ public protocol JTACMonthViewDelegate: class {
/// - cell: The date-cell view. This can be customized at this point.
/// - cellState: The month the date-cell belongs to.
/// - returns: A Bool value indicating if the operation can be done.
- func calendar(_ calendar: JTACMonthView, shouldDeselectDate date: Date, cell: JTACDayCell?, cellState: CellState) -> Bool
+ func calendar(_ calendar: JTACMonthView, shouldDeselectDate date: Date, cell: JTACDayCell?, cellState: CellState, indexPath: IndexPath) -> Bool
/// Tells the delegate that a date-cell with a specified date was selected
/// - Parameters:
@@ -73,7 +76,7 @@ public protocol JTACMonthViewDelegate: class {
/// - cell: The date-cell view. This can be customized at this point.
/// This may be nil if the selected cell is off the screen
/// - cellState: The month the date-cell belongs to.
- func calendar(_ calendar: JTACMonthView, didSelectDate date: Date, cell: JTACDayCell?, cellState: CellState)
+ func calendar(_ calendar: JTACMonthView, didSelectDate date: Date, cell: JTACDayCell?, cellState: CellState, indexPath: IndexPath)
/// Tells the delegate that a date-cell
/// with a specified date was de-selected
@@ -83,21 +86,21 @@ public protocol JTACMonthViewDelegate: class {
/// - cell: The date-cell view. This can be customized at this point.
/// This may be nil if the selected cell is off the screen
/// - cellState: The month the date-cell belongs to.
- func calendar(_ calendar: JTACMonthView, didDeselectDate date: Date, cell: JTACDayCell?, cellState: CellState)
+ func calendar(_ calendar: JTACMonthView, didDeselectDate date: Date, cell: JTACDayCell?, cellState: CellState, indexPath: IndexPath)
/// Tells the delegate that the item at the specified index path was highlighted.
/// - Parameters:
/// - calendar: The JTAppleCalendar view giving this information.
/// - date: The date attached to the date-cell.
/// - cellState: The month the date-cell belongs to.
- func calendar(_ calendar: JTACMonthView, didHighlightDate date: Date, cell: JTACDayCell?, cellState: CellState)
+ func calendar(_ calendar: JTACMonthView, didHighlightDate date: Date, cell: JTACDayCell?, cellState: CellState, indexPath: IndexPath)
/// Tells the delegate that the item at the specified index path was un-highlighted.
/// - Parameters:
/// - calendar: The JTAppleCalendar view giving this information.
/// - date: The date attached to the date-cell.
/// - cellState: The month the date-cell belongs to.
- func calendar(_ calendar: JTACMonthView, didUnhighlightDate date: Date, cell: JTACDayCell?, cellState: CellState)
+ func calendar(_ calendar: JTACMonthView, didUnhighlightDate date: Date, cell: JTACDayCell?, cellState: CellState, indexPath: IndexPath)
/// Tells the delegate that the JTAppleCalendar view
/// scrolled to a segment beginning and ending with a particular date
@@ -155,16 +158,19 @@ public protocol JTACMonthViewDelegate: class {
/// Called to retrieve the size to be used for decoration views
func sizeOfDecorationView(indexPath: IndexPath) -> CGRect
+
+ /// Called in case of tvOS
+ func indexPathForPreferredFocusedView(in: UICollectionView) -> IndexPath?
}
/// Default delegate functions
public extension JTACMonthViewDelegate {
- func calendar(_ calendar: JTACMonthView, shouldSelectDate date: Date, cell: JTACDayCell?, cellState: CellState) -> Bool { return true }
- func calendar(_ calendar: JTACMonthView, shouldDeselectDate date: Date, cell: JTACDayCell?, cellState: CellState) -> Bool { return true }
- func calendar(_ calendar: JTACMonthView, didSelectDate date: Date, cell: JTACDayCell?, cellState: CellState) {}
- func calendar(_ calendar: JTACMonthView, didDeselectDate date: Date, cell: JTACDayCell?, cellState: CellState) {}
- func calendar(_ calendar: JTACMonthView, didHighlightDate date: Date, cell: JTACDayCell?, cellState: CellState) {}
- func calendar(_ calendar: JTACMonthView, didUnhighlightDate date: Date, cell: JTACDayCell?, cellState: CellState) {}
+ func calendar(_ calendar: JTACMonthView, shouldSelectDate date: Date, cell: JTACDayCell?, cellState: CellState, indexPath: IndexPath) -> Bool { return true }
+ func calendar(_ calendar: JTACMonthView, shouldDeselectDate date: Date, cell: JTACDayCell?, cellState: CellState, indexPath: IndexPath) -> Bool { return true }
+ func calendar(_ calendar: JTACMonthView, didSelectDate date: Date, cell: JTACDayCell?, cellState: CellState, indexPath: IndexPath) {}
+ func calendar(_ calendar: JTACMonthView, didDeselectDate date: Date, cell: JTACDayCell?, cellState: CellState, indexPath: IndexPath) {}
+ func calendar(_ calendar: JTACMonthView, didHighlightDate date: Date, cell: JTACDayCell?, cellState: CellState, indexPath: IndexPath) {}
+ func calendar(_ calendar: JTACMonthView, didUnhighlightDate date: Date, cell: JTACDayCell?, cellState: CellState, indexPath: IndexPath) {}
func calendar(_ calendar: JTACMonthView, willScrollToDateSegmentWith visibleDates: DateSegmentInfo) {}
func calendar(_ calendar: JTACMonthView, didScrollToDateSegmentWith visibleDates: DateSegmentInfo) {}
func calendar(_ calendar: JTACMonthView, headerViewForDateRange range: (start: Date, end: Date), at indexPath: IndexPath) -> JTACMonthReusableView {
@@ -175,4 +181,6 @@ public extension JTACMonthViewDelegate {
func calendarSizeForMonths(_ calendar: JTACMonthView?) -> MonthSize? { return nil }
func sizeOfDecorationView(indexPath: IndexPath) -> CGRect { return .zero }
func scrollDidEndDecelerating(for calendar: JTACMonthView) {}
+ func indexPathForPreferredFocusedView(in: UICollectionView) -> IndexPath? { return nil }
+
}
diff --git a/Sources/JTACScrollViewDelegates.swift b/Sources/JTAppleCalendar/JTACScrollViewDelegates.swift
similarity index 81%
rename from Sources/JTACScrollViewDelegates.swift
rename to Sources/JTAppleCalendar/JTACScrollViewDelegates.swift
index 79e388fd..e044790f 100644
--- a/Sources/JTACScrollViewDelegates.swift
+++ b/Sources/JTAppleCalendar/JTACScrollViewDelegates.swift
@@ -1,7 +1,7 @@
//
// JTACScrollViewDelegates.swift
//
-// Copyright (c) 2016-2017 JTAppleCalendar (https://github.com/patchthecode/JTAppleCalendar)
+// Copyright (c) 2016-2020 JTAppleCalendar (https://github.com/patchthecode/JTAppleCalendar)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
@@ -21,6 +21,9 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
+
+import UIKit
+
extension JTACMonthView: UIScrollViewDelegate {
/// Inform the scrollViewDidEndDecelerating
/// function that scrolling just occurred
@@ -77,7 +80,6 @@ extension JTACMonthView: UIScrollViewDelegate {
previousScrollDirectionValue: lastMovedScrollDirection,
forward: { () -> CGFloat in return ceil(theCurrentContentOffset / interval) * interval },
backward: { () -> CGFloat in return floor(theCurrentContentOffset / interval) * interval})
- print("Before: \(offset)")
setTargetContentOffset(offset)
case let .stopAtEach(customInterval: interval):
@@ -94,72 +96,32 @@ extension JTACMonthView: UIScrollViewDelegate {
fixed: { return theCurrentSection})
guard section >= 0, section < calendarLayout.endOfSectionOffsets.count else {setTargetContentOffset(0); return}
-
-
- let x = calendarLayout.endOfSectionOffsets[theCurrentSection]
- let pp = theCurrentSection - 1 < 0 ? 0 : theCurrentSection - 1
- let y = calendarLayout.endOfSectionOffsets[pp]
- let midPoint = (x+y)/2
+ let endOfCurrentSectionOffset = calendarLayout.endOfSectionOffsets[theCurrentSection]
+ let endOfPreviousSectionOffset = calendarLayout.endOfSectionOffsets[theCurrentSection - 1 < 0 ? 0 : theCurrentSection - 1]
+ let midPoint = (endOfCurrentSectionOffset + endOfPreviousSectionOffset) / 2
let maxSnap = calendarLayout.endOfSectionOffsets[section]
- let xp: CGFloat = 20
- let userPercentage = CGFloat((100 - xp) / 100.0)
-
- let snapForward = midPoint - ((maxSnap - midPoint) * userPercentage)
-
+ let userPercentage: CGFloat = 20
+ let modifiedPercentage = CGFloat((100 - userPercentage) / 100.0)
+ let snapForward = midPoint - ((maxSnap - midPoint) * modifiedPercentage)
scrollDecision(currentScrollDirectionValue: translation,
previousScrollDirectionValue: lastMovedScrollDirection,
forward: {
-
-
- print("midPoint = \(midPoint)")
- print("CurrentContentOffset = \(theCurrentContentOffset)")
- print("CurrentSection = \(theCurrentSection)")
- print("snapForward = \(snapForward)")
-// print("snapBack = \(snapBack)")
- print("x = \(x)")
- print("y = \(y)\n\n\n")
-
- if theCurrentContentOffset >= snapForward {
- setTargetContentOffset(x)
- } else {
- setTargetContentOffset(y)
- }
- },
+ if theCurrentContentOffset >= snapForward || directionVelocity > 0 {
+ setTargetContentOffset(endOfCurrentSectionOffset)
+ } else {
+ setTargetContentOffset(endOfPreviousSectionOffset)
+ }
+ },
backward: {
- if theCurrentContentOffset <= snapForward {
- setTargetContentOffset(y)
- } else {
- setTargetContentOffset(x)
- }
- })
-// if isForward {
-//
-// print("isScrollingFowrard = \(isForward)")
-// print("midPoint = \(midPoint)")
-// print("CurrentContentOffset = \(theCurrentContentOffset)")
-// print("CurrentSection = \(theCurrentSection)")
-// print("snapForward = \(snapForward)")
-// print("snapBack = \(snapBack)")
-// print("x = \(x)")
-// print("y = \(y)\n\n\n")
-//
-// if theCurrentContentOffset >= snapForward {
-// setTargetContentOffset(x)
-// } else {
-// setTargetContentOffset(y)
-// }
-// } else {
-// if theCurrentContentOffset <= snapForward {
-// setTargetContentOffset(y)
-// } else {
-// setTargetContentOffset(x)
-// }
-// }
-
-
+ if theCurrentContentOffset <= snapForward || directionVelocity < 0 {
+ setTargetContentOffset(endOfPreviousSectionOffset)
+ } else {
+ setTargetContentOffset(endOfCurrentSectionOffset)
+ }
+ })
case let .nonStopToCell(withResistance: resistance), let .nonStopToSection(withResistance: resistance):
let (recalculatedOffset, elementProperties) = rectAfterApplying(resistance: resistance,
@@ -183,8 +145,8 @@ extension JTACMonthView: UIScrollViewDelegate {
case .nonStopToSection:
let stopSection = scrollDecision(currentScrollDirectionValue: translation,
previousScrollDirectionValue: lastMovedScrollDirection,
- forward: { () -> Int in return validElementProperties.section },
- backward: {() -> Int in return validElementProperties.section - 1})
+ forward: { validElementProperties.section },
+ backward: {validElementProperties.section - 1})
let calculatedOffSet = (stopSection < 0 || stopSection > calendarLayout.endOfSectionOffsets.count - 1) ? 0 : calendarLayout.endOfSectionOffsets[stopSection]
setTargetContentOffset(calculatedOffSet)
@@ -195,13 +157,13 @@ extension JTACMonthView: UIScrollViewDelegate {
let diffResist = diffResistance(targetOffset: theTargetContentOffset, currentOffset: theCurrentContentOffset, resistance: resistance)
let recalculatedOffsetAfterResistance = scrollDecision(currentScrollDirectionValue: translation,
previousScrollDirectionValue: lastMovedScrollDirection,
- forward: { () -> CGFloat in return theTargetContentOffset - diffResist },
- backward: { () -> CGFloat in return theTargetContentOffset + diffResist })
+ forward: { theTargetContentOffset - diffResist },
+ backward: { theTargetContentOffset + diffResist })
let offset = scrollDecision(currentScrollDirectionValue: translation,
previousScrollDirectionValue: lastMovedScrollDirection,
- forward: { () -> CGFloat in return ceil(recalculatedOffsetAfterResistance / interval) * interval },
- backward: { () -> CGFloat in floor(recalculatedOffsetAfterResistance / interval) * interval })
+ forward: { ceil(recalculatedOffsetAfterResistance / interval) * interval },
+ backward: { floor(recalculatedOffsetAfterResistance / interval) * interval })
setTargetContentOffset(offset)
case .none: break
@@ -216,9 +178,13 @@ extension JTACMonthView: UIScrollViewDelegate {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.7) {
self.decelerationRate = UIScrollView.DecelerationRate(rawValue: self.decelerationRateMatchingScrollingMode)
}
-
- DispatchQueue.main.async {
- self.calendarDelegate?.scrollDidEndDecelerating(for: self)
+ }
+
+ public func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
+ if decelerate {
+ DispatchQueue.main.async {
+ self.calendarDelegate?.scrollDidEndDecelerating(for: self)
+ }
}
}
@@ -240,7 +206,7 @@ extension JTACMonthView: UIScrollViewDelegate {
/// Tells the delegate that the scroll view has
/// ended decelerating the scrolling movement.
- public func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
+ open func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
visibleDates {[unowned self] dates in
self.calendarDelegate?.calendar(self, didScrollToDateSegmentWith: dates)
}
diff --git a/Sources/JTACVariables.swift b/Sources/JTAppleCalendar/JTACVariables.swift
similarity index 64%
rename from Sources/JTACVariables.swift
rename to Sources/JTAppleCalendar/JTACVariables.swift
index 381dd43c..2ecc4683 100644
--- a/Sources/JTACVariables.swift
+++ b/Sources/JTAppleCalendar/JTACVariables.swift
@@ -1,7 +1,7 @@
//
// JTACVariables.swift
//
-// Copyright (c) 2016-2017 JTAppleCalendar (https://github.com/patchthecode/JTAppleCalendar)
+// Copyright (c) 2016-2020 JTAppleCalendar (https://github.com/patchthecode/JTAppleCalendar)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
@@ -22,20 +22,33 @@
// THE SOFTWARE.
//
+import Foundation
+import UIKit
+
// Calculated Variables
extension JTACMonthView {
/// Workaround for Xcode bug that prevents you from connecting the delegate in the storyboard.
/// Remove this extra property once Xcode gets fixed.
@IBOutlet public var ibCalendarDelegate: AnyObject? {
- get { return calendarDelegate }
- set { calendarDelegate = newValue as? JTACMonthViewDelegate }
+ get { return calendarDelegate as AnyObject? }
+ set {
+ if (newValue != nil) {
+ assert(newValue as? JTACMonthViewDelegate != nil, "Error, your delegate is not of type JTACMonthViewDelegate.")
+ }
+ calendarDelegate = newValue as? JTACMonthViewDelegate
+ }
}
/// Workaround for Xcode bug that prevents you from connecting the delegate in the storyboard.
/// Remove this extra property once Xcode gets fixed.
@IBOutlet public var ibCalendarDataSource: AnyObject? {
- get { return calendarDataSource }
- set { calendarDataSource = newValue as? JTACMonthViewDataSource }
+ get { return calendarDataSource as AnyObject? }
+ set {
+ if (newValue != nil) {
+ assert(newValue as? JTACMonthViewDataSource != nil, "Error, your dataSource is not of type JTACMonthViewDataSource.")
+ }
+ calendarDataSource = newValue as? JTACMonthViewDataSource
+ }
}
@available(*, unavailable)
@@ -53,7 +66,7 @@ extension JTACMonthView {
}
/// Returns all selected dates
- open var selectedDates: [Date] {
+ public var selectedDates: [Date] {
return selectedDatesSet.sorted()
}
@@ -63,7 +76,7 @@ extension JTACMonthView {
var monthInfo: [Month] {
get { return theData.months }
- set { theData.months = monthInfo }
+ set { theData.months = newValue }
}
var numberOfMonths: Int {
@@ -73,7 +86,7 @@ extension JTACMonthView {
var totalDays: Int {
return theData.totalDays
}
-
+
var calendarViewLayout: JTACMonthLayout {
guard let layout = collectionViewLayout as? JTACMonthLayout else {
developerError(string: "Calendar layout is not of type JTAppleCalendarMonthLayout.")
@@ -87,10 +100,25 @@ extension JTACMonthView {
}
var calendarLayoutIsLoaded: Bool { return calendarViewLayout.isCalendarLayoutLoaded }
- var startDateCache: Date { return _cachedConfiguration.startDate }
- var endDateCache: Date { return _cachedConfiguration.endDate }
- var calendar: Calendar { return _cachedConfiguration.calendar }
-
-
-
+ var startDateCache: Date {
+ guard let date = _cachedConfiguration?.startDate else {
+ assert(false, "Attemped to access startDate when Datasource/delegate is not set yet. Returning todays's date")
+ return Date()
+ }
+ return date
+ }
+ var endDateCache: Date {
+ guard let date = _cachedConfiguration?.endDate else {
+ assert(false, "Attemped to access endDate when Datasource/delegate is not set yet. Returning todays's date")
+ return Date()
+ }
+ return date
+ }
+ var calendar: Calendar {
+ guard let calendar = _cachedConfiguration?.calendar else {
+ assert(false, "Attemped to access calendar when Datasource/delegate is not set yet. Returning default value")
+ return Calendar.current
+ }
+ return calendar
+ }
}
diff --git a/Sources/JTACYearView.swift b/Sources/JTAppleCalendar/JTACYearView.swift
similarity index 84%
rename from Sources/JTACYearView.swift
rename to Sources/JTAppleCalendar/JTACYearView.swift
index 5ef98d0d..1181e620 100644
--- a/Sources/JTACYearView.swift
+++ b/Sources/JTAppleCalendar/JTACYearView.swift
@@ -1,7 +1,7 @@
//
// JTAppleCalendarYearView.swift
//
-// Copyright (c) 2016-2017 JTAppleCalendar (https://github.com/patchthecode/JTAppleCalendar)
+// Copyright (c) 2016-2020 JTAppleCalendar (https://github.com/patchthecode/JTAppleCalendar)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
@@ -22,6 +22,9 @@
// THE SOFTWARE.
//
+import Foundation
+import UIKit
+
open class JTACYearView: UICollectionView {
var configurationParameters = ConfigurationParameters(startDate: Date(), endDate: Date())
var monthData: [Any] = []
@@ -47,7 +50,7 @@ open class JTACYearView: UICollectionView {
set { calendarDataSource = newValue as? JTACYearViewDataSource }
}
- func dataSourcefrom(configurationParameters: ConfigurationParameters) -> [Any] {
+ open func dataSourcefrom(configurationParameters: ConfigurationParameters) -> [Any] {
return JTAppleDateConfigGenerator.shared.setupMonthInfoDataForStartAndEndDate(configurationParameters).months
}
@@ -65,10 +68,8 @@ open class JTACYearView: UICollectionView {
}
-
-
-extension JTACYearView: JTAppleMonthCellDelegate {
- public func monthView(_ monthView: JTAppleMonthView, drawingFor segmentRect: CGRect, with date: Date, dateOwner: DateOwner, monthIndex: Int) -> (UIImage, CGRect)? {
- return calendarDelegate?.calendar(self, monthView: monthView, drawingFor: segmentRect, with: date, dateOwner: dateOwner, monthIndex: monthIndex)
+extension JTACYearView: JTACCellMonthViewDelegate {
+ public func monthView(_ monthView: JTACCellMonthView, drawingFor segmentRect: CGRect, with date: Date, dateOwner: DateOwner, monthIndex: Int) {
+ calendarDelegate?.calendar(self, monthView: monthView, drawingFor: segmentRect, with: date, dateOwner: dateOwner, monthIndex: monthIndex)
}
}
diff --git a/Sources/JTACYearViewProtocols.swift b/Sources/JTAppleCalendar/JTACYearViewProtocols.swift
similarity index 79%
rename from Sources/JTACYearViewProtocols.swift
rename to Sources/JTAppleCalendar/JTACYearViewProtocols.swift
index 3ff5d171..15a41b9a 100644
--- a/Sources/JTACYearViewProtocols.swift
+++ b/Sources/JTAppleCalendar/JTACYearViewProtocols.swift
@@ -1,7 +1,7 @@
//
// JTACYearViewProtocols.swift
//
-// Copyright (c) 2016-2017 JTAppleCalendar (https://github.com/patchthecode/JTAppleCalendar)
+// Copyright (c) 2016-2020 JTAppleCalendar (https://github.com/patchthecode/JTAppleCalendar)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
@@ -22,30 +22,31 @@
// THE SOFTWARE.
//
-public protocol JTACYearViewDelegate: class {
- func calendar(_ calendar: JTACYearView, cellFor item: Any, at date: Date, indexPath: IndexPath) -> JTAppleMonthCell
+import Foundation
+import UIKit
+
+public protocol JTACYearViewDelegate: AnyObject {
+ func calendar(_ calendar: JTACYearView, cellFor item: Any, at date: Date, indexPath: IndexPath) -> JTACMonthCell
func calendar(_ calendar: JTACYearView,
- monthView: JTAppleMonthView,
+ monthView: JTACCellMonthView,
drawingFor segmentRect: CGRect,
with date: Date,
dateOwner: DateOwner,
- monthIndex index: Int) -> (UIImage, CGRect)?
+ monthIndex index: Int)
func calendar(_ calendar: JTACYearView, sizeFor item: Any) -> CGSize
}
extension JTACYearViewDelegate {
func calendar(_ calendar: JTACYearView,
- monthView: JTAppleMonthView,
+ monthView: JTACCellMonthView,
drawingFor segmentRect: CGRect,
with date: Date,
dateOwner: DateOwner,
- monthIndex index: Int) -> (UIImage, CGRect)? {
- return (UIImage(), .zero)
- }
+ monthIndex index: Int){}
func calendar(_ calendar: JTACYearView, sizeFor item: Any) -> CGSize { return .zero }
}
-public protocol JTACYearViewDataSource: class {
+public protocol JTACYearViewDataSource: AnyObject {
func configureCalendar(_ calendar: JTACYearView) -> (configurationParameters: ConfigurationParameters, months: [Any])
}
diff --git a/Sources/JTAppleCalendar.h b/Sources/JTAppleCalendar/JTAppleCalendar.h
similarity index 81%
rename from Sources/JTAppleCalendar.h
rename to Sources/JTAppleCalendar/JTAppleCalendar.h
index 2c7a2db9..8f1acc15 100644
--- a/Sources/JTAppleCalendar.h
+++ b/Sources/JTAppleCalendar/JTAppleCalendar.h
@@ -1,7 +1,7 @@
//
-// JTAppleCalendar.swift
+// JTACMonthView.swift
//
-// Copyright (c) 2016-2017 JTAppleCalendar (https://github.com/patchthecode/JTAppleCalendar)
+// Copyright (c) 2016-2020 JTAppleCalendar (https://github.com/patchthecode/JTAppleCalendar)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
@@ -22,14 +22,14 @@
// THE SOFTWARE.
//
-#import
+#import
-//! Project version number for JTAppleCalendar iOS.
+//! Project version number for JTAppleCalendar.
FOUNDATION_EXPORT double JTAppleCalendarVersionNumber;
-//! Project version string for JTAppleCalendar iOS.
+//! Project version string for JTAppleCalendar.
FOUNDATION_EXPORT const unsigned char JTAppleCalendarVersionString[];
-// In this header, you should import all the public headers of your framework using statements like #import
+// In this header, you should import all the public headers of your framework using statements like #import
diff --git a/Sources/JTAppleCalendar/PrivacyInfo.xcprivacy b/Sources/JTAppleCalendar/PrivacyInfo.xcprivacy
new file mode 100644
index 00000000..987771fa
--- /dev/null
+++ b/Sources/JTAppleCalendar/PrivacyInfo.xcprivacy
@@ -0,0 +1,14 @@
+
+
+
+
+ NSPrivacyTrackingDomains
+
+ NSPrivacyCollectedDataTypes
+
+ NSPrivacyAccessedAPITypes
+
+ NSPrivacyTracking
+
+
+
diff --git a/Sources/JTAppleMonthView.swift b/Sources/JTAppleMonthView.swift
deleted file mode 100644
index d7e1e3f0..00000000
--- a/Sources/JTAppleMonthView.swift
+++ /dev/null
@@ -1,194 +0,0 @@
-//
-// JTAppleDayCell.swift
-//
-// Copyright (c) 2016-2017 JTAppleCalendar (https://github.com/patchthecode/JTAppleCalendar)
-//
-// 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.
-//
-public protocol JTAppleMonthViewDelegate: class {
- func monthView(_ monthView: JTAppleMonthView,
- drawingFor segmentRect: CGRect,
- with date: Date,
- dateOwner: DateOwner,
- monthIndex: Int) -> (UIImage, CGRect)?
-}
-
-public protocol JTAppleMonthCellDelegate: class {
- func monthView(_ monthView: JTAppleMonthView,
- drawingFor segmentRect: CGRect,
- with date: Date,
- dateOwner: DateOwner,
- monthIndex: Int) -> (UIImage, CGRect)?
-}
-
-open class JTAppleMonthCell: UICollectionViewCell {
- @IBOutlet var monthView: JTAppleMonthView?
- weak var delegate: JTAppleMonthCellDelegate?
-
- func setupWith(configurationParameters: ConfigurationParameters,
- month: Month,
- date: Date,
- delegate: JTAppleMonthCellDelegate) {
- guard let monthView = monthView else { assert(false); return }
- self.delegate = delegate
- monthView.setupWith(configurationParameters: configurationParameters,
- month: month,
- date: date,
- delegate: self)
- }
-}
-
-extension JTAppleMonthCell: JTAppleMonthViewDelegate {
- public func monthView(_ monthView: JTAppleMonthView,
- drawingFor segmentRect: CGRect,
- with date: Date,
- dateOwner: DateOwner,
- monthIndex: Int) -> (UIImage, CGRect)? {
- return delegate?.monthView(monthView, drawingFor: segmentRect, with: date, dateOwner: dateOwner, monthIndex: monthIndex)
- }
-}
-
-
-
-
-open class JTAppleMonthView: UIView {
- var daysInSection: [Int: Int] = [:] // temporary caching
- var sectionInset = UIEdgeInsets.zero
- var month: Month!
- var monthDate: Date!
- var configurationParameters: ConfigurationParameters!
-
- var yCellOffset:CGFloat = 0
- var xCellOffset:CGFloat = 0
- var xStride:CGFloat = 0
-
- weak var delegate: JTAppleMonthViewDelegate?
- var scrollDirection: UICollectionView.ScrollDirection = .horizontal
-
- func setupWith(configurationParameters: ConfigurationParameters, month: Month, date: Date, delegate: JTAppleMonthViewDelegate? = nil) {
- self.configurationParameters = configurationParameters
- self.delegate = delegate
- self.month = month
- self.monthDate = date
-
- yCellOffset = 0
- xCellOffset = 0
- xStride = 0
-
- setNeedsDisplay()
- }
-
- func determineToApplyAttribs(month: Month) -> (xOffset: CGFloat, yOffset: CGFloat, width: CGFloat, height: CGFloat)? {
-
- let numberOfRowsForSection = month.maxNumberOfRowsForFull(developerSetRows: 6)
- let width = (frame.width - ((sectionInset.left / 7) + (sectionInset.right / 7))) / 7
- let height = (frame.height - sectionInset.top - sectionInset.bottom) / CGFloat(numberOfRowsForSection)
-
- let y = scrollDirection == .horizontal ? yCellOffset + sectionInset.top : yCellOffset
- return (xCellOffset + xStride, y, width, height)
- }
-
- override open func draw(_ rect: CGRect) {
- super.draw(rect)
-
-
- for numberOfDaysInCurrentSection in month.sections {
-
- for dayCounter in 1...numberOfDaysInCurrentSection {
- guard let attribute = determineToApplyAttribs(month: month) else { continue }
-
- let rect = CGRect(x: attribute.xOffset, y: attribute.yOffset, width: attribute.width, height: attribute.height)
-
- guard let dateWithOwner = dateFromIndex(dayCounter - 1, month: month,
- startOfMonthCache: configurationParameters.startDate,
- endOfMonthCache: configurationParameters.endDate) else { continue }
-
-
- if let data = delegate?.monthView(self,
- drawingFor: rect,
- with: dateWithOwner.date,
- dateOwner: dateWithOwner.owner,
- monthIndex: month.index) {
- data.0.draw(in: data.1)
- }
-
- xCellOffset += attribute.width
-
- if dayCounter == numberOfDaysInCurrentSection || dayCounter % maxNumberOfDaysInWeek == 0 {
- // We are at the last item in the section
- // && if we have headers
- xCellOffset = sectionInset.left
- yCellOffset += attribute.height
- }
- }
- }
- }
-
- func fontSizeFor(radius: CGFloat) -> CGFloat {
- if radius >= 17.0 {
- return 11.0
- } else if radius >= 16.0 {
- return 10.0
- } else {
- return 8.0
- }
- }
-
- private func dateFromIndex(_ index: Int, month: Month, startOfMonthCache: Date, endOfMonthCache: Date) -> (date: Date, owner: DateOwner)? { // Returns nil if date is out of scope
- let calendar = Calendar(identifier: .gregorian)
- // Calculate the offset
- let offSet = month.inDates
-
- let dayIndex = month.startDayIndex + index - offSet
- var dateOwner: DateOwner = .thisMonth
- let date: Date? = calendar.date(byAdding: .day, value: dayIndex, to: startOfMonthCache)
-
-
-
- if index >= offSet && index < month.numberOfDaysInMonth + offSet {
- // This is a month date
- } else if index < offSet {
- // This is a preDate
-
- if date! < startOfMonthCache {
- dateOwner = .previousMonthOutsideBoundary
- } else {
- dateOwner = .previousMonthWithinBoundary
- }
- } else {
- // This is a postDate
-
-
- if date! > endOfMonthCache {
- dateOwner = .followingMonthOutsideBoundary
- } else {
- dateOwner = .followingMonthWithinBoundary
- }
- }
- guard let validDate = date else { return nil }
- return (validDate, dateOwner)
- }
-}
-
-
-extension CGRect {
- var midPoint: CGPoint {
- return CGPoint(x: midX, y: midY)
- }
-}
diff --git a/Tests/Info.plist b/Tests/Info.plist
deleted file mode 100644
index ba72822e..00000000
--- a/Tests/Info.plist
+++ /dev/null
@@ -1,24 +0,0 @@
-
-
-
-
- CFBundleDevelopmentRegion
- en
- CFBundleExecutable
- $(EXECUTABLE_NAME)
- CFBundleIdentifier
- $(PRODUCT_BUNDLE_IDENTIFIER)
- CFBundleInfoDictionaryVersion
- 6.0
- CFBundleName
- $(PRODUCT_NAME)
- CFBundlePackageType
- BNDL
- CFBundleShortVersionString
- 1.0
- CFBundleSignature
- ????
- CFBundleVersion
- 1
-
-
diff --git a/Tests/JTAppleCalendarTests/JTAppleCalendarTests.swift b/Tests/JTAppleCalendarTests/JTAppleCalendarTests.swift
new file mode 100644
index 00000000..f1b8d77c
--- /dev/null
+++ b/Tests/JTAppleCalendarTests/JTAppleCalendarTests.swift
@@ -0,0 +1,15 @@
+import XCTest
+@testable import JTAppleCalendar
+
+final class JTAppleCalendarTests: XCTestCase {
+ func testExample() {
+ // This is an example of a functional test case.
+ // Use XCTAssert and related functions to verify your tests produce the correct
+ // results.
+// XCTAssertEqual(JTAppleCalendar().text, "Hello, World!")
+ }
+
+ static var allTests = [
+ ("testExample", testExample),
+ ]
+}
diff --git a/Tests/JTAppleCalendarTests/XCTestManifests.swift b/Tests/JTAppleCalendarTests/XCTestManifests.swift
new file mode 100644
index 00000000..6723652e
--- /dev/null
+++ b/Tests/JTAppleCalendarTests/XCTestManifests.swift
@@ -0,0 +1,9 @@
+import XCTest
+
+#if !canImport(ObjectiveC)
+public func allTests() -> [XCTestCaseEntry] {
+ return [
+ testCase(JTAppleCalendarTests.allTests),
+ ]
+}
+#endif
diff --git a/Tests/JTAppleCalendar_iOSTests.swift b/Tests/JTAppleCalendar_iOSTests.swift
deleted file mode 100644
index 7920c615..00000000
--- a/Tests/JTAppleCalendar_iOSTests.swift
+++ /dev/null
@@ -1,102 +0,0 @@
-//
-// JTAppleCalendar_iOSTests.swift
-// JTAppleCalendar iOSTests
-//
-// Created by JayT on 2016-08-10.
-//
-//
-
-import XCTest
-@testable import JTAppleCalendar
-
-class JTAppleCalendar_iOSTests: XCTestCas(width, cellSize.height)e {
- let calendarView = JTACMonthView()
- let formatter: DateFormatter = {
- let aFormatter = DateFormatter()
- aFormatter.dateFormat = "yyyy MM dd"
- return aFormatter
- }()
-
- var startDate = Date()
- var endDate = Date()
-
- override func setUp() {
- startDate = formatter.date(from: "2016 01 01")!
- endDate = formatter.date(from: "2017 12 01")!
- }
-
- func testVisibleDates() {
- let calendarView = JTACMonthView()
- calendarView.scrollDirection = .vertical
- calendarView.scrollingMode = .none
- calendarView.allowsMultipleSelection = true
- calendarView.minimumLineSpacing = 0
- calendarView.minimumInteritemSpacing = 0
-
- let calendar = Calendar(identifier: Calendar.Identifier.gregorian)
-
- let controller = CalendarViewTestingController()
- controller.calendar = calendar
- controller.calendarView = calendarView
- _ = controller.view // init viewDidLoad()
- }
-}
-
-public class CalendarViewTestingController: UIViewController {
- var calendar: Calendar!
- var calendarView: JTACMonthView!
-
- override open func viewDidLoad() {
- super.viewDidLoad()
-
- calendarView.ibCalendarDelegate = self
- calendarView.ibCalendarDataSource = self
- let myNib = UINib(nibName: "CellView", bundle: Bundle.main)
- calendarView.register(TestCellView.self, forCellWithReuseIdentifier: "Cell")
-
- // a MUST to make calendarView believe it is already loaded
- calendarView.cellSize = 10
- calendarView.frame = view.frame
-
- view.addSubview(calendarView)
-
-
-
- calendarView.layoutSubviews()
- calendarView.visibleDates { segInfo in
- print(segInfo.monthDates)
- }
- print("finished before done")
- }
-}
-
-extension CalendarViewTestingController: JTACMonthViewDataSource {
- public func configureCalendar(_ calendar: JTACMonthView) -> ConfigurationParameters {
- let formatter = DateFormatter()
- formatter.dateFormat = "yyyy MM dd"
- let startDate = formatter.date(from: "2017 01 01")!
- let endDate = Date()
-
- return ConfigurationParameters(startDate: startDate, endDate: endDate)
- }
-}
-
-extension CalendarViewTestingController: JTACMonthViewDelegate {
- public func calendar(_ calendar: JTACMonthView, cellForItemAt date: Date, cellState: CellState, indexPath: IndexPath) -> JTACDayCell {
- let cell = calendar.dequeueReusableJTAppleCell(withReuseIdentifier: "Cell", for: indexPath) as! TestCellView
- return cell
- }
-}
-
-class TestCellView: JTACDayCell {
-}
-
-
-
-
-
-
-
-
-
-
diff --git a/Tests/JTAppleCalendar_tvOSTests.swift b/Tests/JTAppleCalendar_tvOSTests.swift
deleted file mode 100644
index 1701ffa7..00000000
--- a/Tests/JTAppleCalendar_tvOSTests.swift
+++ /dev/null
@@ -1,312 +0,0 @@
-//
-// JTAppleCalendar_tvOSTests.swift
-// JTAppleCalendar tvOSTests
-//
-// Created by JayT on 2016-08-10.
-//
-//
-
-import XCTest
-@testable import JTAppleCalendar
-
-class JTAppleCalendar_tvOSTests: XCTestCase {
- let calendarView = JTAppleCalendarMonthView()
- let formatter: DateFormatter = {
- let aFormatter = DateFormatter()
- aFormatter.dateFormat = "yyyy MM dd"
- return aFormatter
- }()
-
- var startDate = Date()
- var endDate = Date()
-
-
- override func setUp() {
- startDate = formatter.date(from: "2016 01 01")!
- endDate = formatter.date(from: "2017 12 01")!
- }
-
- func testConfigurationParametersDefaultBehavior() {
- print("testing default parameters")
- var params = ConfigurationParameters(startDate: Date(), endDate: Date())
- print("All months should be default")
- XCTAssertEqual(params.generateInDates, .forAllMonths)
- print("Till Grid should be default should be default")
- XCTAssertEqual(params.generateOutDates, .tillEndOfGrid)
- print("Rows should be 6")
- XCTAssertEqual(params.numberOfRows, 6)
- print("First day should be sunday")
- XCTAssertEqual(params.firstDayOfWeek, .sunday)
- print("strict should be true")
- XCTAssertEqual(params.hasStrictBoundaries, true)
- params = ConfigurationParameters(startDate: Date(), endDate: Date(), numberOfRows: 1)
- print("Rows should be 1")
- XCTAssertEqual(params.numberOfRows, 1)
- print("strict should be false")
- XCTAssertEqual(params.hasStrictBoundaries, false)
- }
-
- func testLayoutGeneratorOnDefaults() {
- let params = ConfigurationParameters(startDate: startDate, endDate: endDate)
- let layoutGenerator = JTAppleDateConfigGenerator()
- let val = layoutGenerator.setupMonthInfoDataForStartAndEndDate(params)
- XCTAssertEqual(val.months.count, 24)
- XCTAssertEqual(val.totalSections, 24)
- for index in 0...23 {
- XCTAssertEqual(val.monthMap[index], index)
- }
- XCTAssertEqual(val.totalDays, 42 * 24)
- }
-
- func testLayoutGeneratorOnThreeRow() {
- let params = ConfigurationParameters(startDate: startDate, endDate: endDate, numberOfRows: 3)
- let layoutGenerator = JTAppleDateConfigGenerator()
- let val = layoutGenerator.setupMonthInfoDataForStartAndEndDate(params)
- XCTAssertEqual(val.months.count, 24)
- XCTAssertEqual(val.totalSections, 48)
- XCTAssertEqual(val.monthMap[22], 11)
- XCTAssertEqual(val.monthMap[23], 11)
- }
- func testLayoutGeneratorOnTwoRow() {
- let params = ConfigurationParameters(startDate: startDate, endDate: endDate, numberOfRows: 2)
- let layoutGenerator = JTAppleDateConfigGenerator()
- let val = layoutGenerator.setupMonthInfoDataForStartAndEndDate(params)
- XCTAssertEqual(val.months.count, 24)
- XCTAssertEqual(val.monthMap[71], 23)
- XCTAssertEqual(val.totalSections, 72)
- }
- func testLayoutGeneratorWithOffInAndOffOut() {
- let params = ConfigurationParameters(startDate: startDate, endDate: endDate, numberOfRows: 2, generateInDates: .off, generateOutDates: .off)
- let layoutGenerator = JTAppleDateConfigGenerator()
- let val = layoutGenerator.setupMonthInfoDataForStartAndEndDate(params)
- XCTAssertEqual(val.months.count, 24)
- XCTAssertEqual(val.monthMap[70], 23)
- XCTAssertEqual(val.totalSections, 71)
- }
- func testLayoutGeneratorOnDefaultsFirst() {
- let params = ConfigurationParameters(startDate: startDate, endDate: endDate)
- let layoutGenerator = JTAppleDateConfigGenerator()
- let val = layoutGenerator.setupMonthInfoDataForStartAndEndDate(params)
- XCTAssertEqual(val.months.count, 24)
- XCTAssertEqual(val.totalSections, 24)
- for index in 0...23 {
- XCTAssertEqual(val.monthMap[index], index)
- }
- XCTAssertEqual(val.totalDays, 42 * 24)
- }
-
- func testLayoutGeneratorOnThreeRowFirst() {
- let params = ConfigurationParameters(startDate: startDate, endDate: endDate, numberOfRows: 3)
- let layoutGenerator = JTAppleDateConfigGenerator()
- let val = layoutGenerator.setupMonthInfoDataForStartAndEndDate(params)
- XCTAssertEqual(val.months.count, 24)
- XCTAssertEqual(val.totalSections, 48)
- XCTAssertEqual(val.monthMap[22], 11)
- XCTAssertEqual(val.monthMap[23], 11)
- }
- func testLayoutGeneratorOnTwoRowFirst() {
- let params = ConfigurationParameters(startDate: startDate, endDate: endDate, numberOfRows: 2)
- let layoutGenerator = JTAppleDateConfigGenerator()
- let val = layoutGenerator.setupMonthInfoDataForStartAndEndDate(params)
- XCTAssertEqual(val.months.count, 24)
- XCTAssertEqual(val.monthMap[71], 23)
- XCTAssertEqual(val.totalSections, 72)
- }
- func testLayoutGeneratorWithOffInAndOffOutFirst() {
- let params = ConfigurationParameters(startDate: startDate, endDate: endDate, numberOfRows: 2, generateInDates: .off, generateOutDates: .off)
- let layoutGenerator = JTAppleDateConfigGenerator()
- let val = layoutGenerator.setupMonthInfoDataForStartAndEndDate(params)
- XCTAssertEqual(val.months.count, 24)
- XCTAssertEqual(val.monthMap[70], 23)
- XCTAssertEqual(val.totalSections, 71)
- }
- func testConfigurationParametersDefaultBehaviorFirst() {
- var params = ConfigurationParameters(startDate: Date(), endDate: Date())
- XCTAssertEqual(params.generateInDates, .forAllMonths)
- XCTAssertEqual(params.generateOutDates, .tillEndOfGrid)
- XCTAssertEqual(params.numberOfRows, 6)
- XCTAssertEqual(params.firstDayOfWeek, .sunday)
- XCTAssertEqual(params.hasStrictBoundaries, true)
- params = ConfigurationParameters(startDate: Date(), endDate: Date(), numberOfRows: 1)
- XCTAssertEqual(params.numberOfRows, 1)
- XCTAssertEqual(params.hasStrictBoundaries, false)
- }
- func testConfigurationParametersDefaultBehaviorsFirst() {
- var params = ConfigurationParameters(startDate: Date(), endDate: Date())
- XCTAssertEqual(params.generateInDates, .forAllMonths)
- XCTAssertEqual(params.generateOutDates, .tillEndOfGrid)
- XCTAssertEqual(params.numberOfRows, 6)
- XCTAssertEqual(params.firstDayOfWeek, .sunday)
- XCTAssertEqual(params.hasStrictBoundaries, true)
- params = ConfigurationParameters(startDate: Date(), endDate: Date(), numberOfRows: 1)
- XCTAssertEqual(params.numberOfRows, 1)
- XCTAssertEqual(params.hasStrictBoundaries, false)
- }
- func testConfigurationParametersDefaultBehaviorssFirst() {
- print("testing default parameters")
- var params = ConfigurationParameters(startDate: Date(), endDate: Date())
- XCTAssertEqual(params.generateInDates, .forAllMonths)
- XCTAssertEqual(params.generateOutDates, .tillEndOfGrid)
- XCTAssertEqual(params.numberOfRows, 6)
- XCTAssertEqual(params.firstDayOfWeek, .sunday)
- XCTAssertEqual(params.hasStrictBoundaries, true)
- params = ConfigurationParameters(startDate: Date(), endDate: Date(), numberOfRows: 1)
- XCTAssertEqual(params.numberOfRows, 1)
- XCTAssertEqual(params.hasStrictBoundaries, false)
-
- // first
- params = ConfigurationParameters(startDate: Date(), endDate: Date())
- XCTAssertEqual(params.generateInDates, .forAllMonths)
- XCTAssertEqual(params.generateOutDates, .tillEndOfGrid)
- XCTAssertEqual(params.numberOfRows, 6)
- XCTAssertEqual(params.firstDayOfWeek, .sunday)
- XCTAssertEqual(params.hasStrictBoundaries, true)
- params = ConfigurationParameters(startDate: Date(), endDate: Date(), numberOfRows: 1)
- XCTAssertEqual(params.numberOfRows, 1)
- XCTAssertEqual(params.hasStrictBoundaries, false)
-
- //second
- params = ConfigurationParameters(startDate: Date(), endDate: Date())
- XCTAssertEqual(params.generateInDates, .forAllMonths)
- XCTAssertEqual(params.generateOutDates, .tillEndOfGrid)
- XCTAssertEqual(params.numberOfRows, 6)
- XCTAssertEqual(params.firstDayOfWeek, .sunday)
- XCTAssertEqual(params.hasStrictBoundaries, true)
- params = ConfigurationParameters(startDate: Date(), endDate: Date(), numberOfRows: 1)
- XCTAssertEqual(params.numberOfRows, 1)
- XCTAssertEqual(params.hasStrictBoundaries, false)
-
- // third
- params = ConfigurationParameters(startDate: Date(), endDate: Date())
- XCTAssertEqual(params.generateInDates, .forAllMonths)
- XCTAssertEqual(params.generateOutDates, .tillEndOfGrid)
- XCTAssertEqual(params.numberOfRows, 6)
- XCTAssertEqual(params.firstDayOfWeek, .sunday)
- XCTAssertEqual(params.hasStrictBoundaries, true)
- params = ConfigurationParameters(startDate: Date(), endDate: Date(), numberOfRows: 1)
- XCTAssertEqual(params.numberOfRows, 1)
- XCTAssertEqual(params.hasStrictBoundaries, false)
-
- // 4
- params = ConfigurationParameters(startDate: Date(), endDate: Date())
- XCTAssertEqual(params.generateInDates, .forAllMonths)
- XCTAssertEqual(params.generateOutDates, .tillEndOfGrid)
- XCTAssertNotEqual(params.numberOfRows, 9)
- XCTAssertEqual(params.firstDayOfWeek, .sunday)
- XCTAssertEqual(params.hasStrictBoundaries, true)
- params = ConfigurationParameters(startDate: Date(), endDate: Date(), numberOfRows: 1)
- XCTAssertNotEqual(params.numberOfRows, 100)
- XCTAssertEqual(params.hasStrictBoundaries, false)
-
- //5
- params = ConfigurationParameters(startDate: Date(), endDate: Date())
- XCTAssertEqual(params.generateInDates, .forAllMonths)
- XCTAssertEqual(params.generateOutDates, .tillEndOfGrid)
- XCTAssertNotEqual(params.numberOfRows, 10)
- XCTAssertEqual(params.firstDayOfWeek, .sunday)
- XCTAssertEqual(params.hasStrictBoundaries, true)
- params = ConfigurationParameters(startDate: Date(), endDate: Date(), numberOfRows: 1)
- XCTAssertNotEqual(params.numberOfRows, 80)
- XCTAssertEqual(params.hasStrictBoundaries, false)
-
- // 6
- params = ConfigurationParameters(startDate: Date(), endDate: Date())
- XCTAssertEqual(params.generateInDates, .forAllMonths)
- XCTAssertEqual(params.generateOutDates, .tillEndOfGrid)
- XCTAssertNotEqual(params.numberOfRows, 100)
- XCTAssertEqual(params.firstDayOfWeek, .sunday)
- XCTAssertEqual(params.hasStrictBoundaries, true)
- params = ConfigurationParameters(startDate: Date(), endDate: Date(), numberOfRows: 1)
- XCTAssertNotEqual(params.numberOfRows, 20)
- XCTAssertEqual(params.hasStrictBoundaries, false)
-
- // 7
- params = ConfigurationParameters(startDate: Date(), endDate: Date())
- XCTAssertEqual(params.generateInDates, .forAllMonths)
- XCTAssertEqual(params.generateOutDates, .tillEndOfGrid)
- XCTAssertNotEqual(params.numberOfRows, 9)
- XCTAssertEqual(params.firstDayOfWeek, .sunday)
- XCTAssertEqual(params.hasStrictBoundaries, true)
- params = ConfigurationParameters(startDate: Date(), endDate: Date(), numberOfRows: 1)
- XCTAssertNotEqual(params.numberOfRows, 100)
- XCTAssertEqual(params.hasStrictBoundaries, false)
-
- // 8
- params = ConfigurationParameters(startDate: Date(), endDate: Date())
- XCTAssertEqual(params.generateInDates, .forAllMonths)
- XCTAssertEqual(params.generateOutDates, .tillEndOfGrid)
- XCTAssertNotEqual(params.numberOfRows, 10)
- XCTAssertEqual(params.firstDayOfWeek, .sunday)
- XCTAssertEqual(params.hasStrictBoundaries, true)
- params = ConfigurationParameters(startDate: Date(), endDate: Date(), numberOfRows: 1)
- XCTAssertNotEqual(params.numberOfRows, 80)
- XCTAssertEqual(params.hasStrictBoundaries, false)
-
- // 9
- params = ConfigurationParameters(startDate: Date(), endDate: Date())
- XCTAssertEqual(params.generateInDates, .forAllMonths)
- XCTAssertEqual(params.generateOutDates, .tillEndOfGrid)
- XCTAssertNotEqual(params.numberOfRows, 100)
- XCTAssertEqual(params.firstDayOfWeek, .sunday)
- XCTAssertEqual(params.hasStrictBoundaries, true)
- params = ConfigurationParameters(startDate: Date(), endDate: Date(), numberOfRows: 1)
- XCTAssertNotEqual(params.numberOfRows, 20)
- XCTAssertEqual(params.hasStrictBoundaries, false)
-
- // 10
- params = ConfigurationParameters(startDate: Date(), endDate: Date())
- XCTAssertEqual(params.generateInDates, .forAllMonths)
- XCTAssertEqual(params.generateOutDates, .tillEndOfGrid)
- XCTAssertNotEqual(params.numberOfRows, 9)
- XCTAssertEqual(params.firstDayOfWeek, .sunday)
- XCTAssertEqual(params.hasStrictBoundaries, true)
- params = ConfigurationParameters(startDate: Date(), endDate: Date(), numberOfRows: 1)
- XCTAssertNotEqual(params.numberOfRows, 100)
- XCTAssertEqual(params.hasStrictBoundaries, false)
-
- //11
- params = ConfigurationParameters(startDate: Date(), endDate: Date())
- XCTAssertEqual(params.generateInDates, .forAllMonths)
- XCTAssertEqual(params.generateOutDates, .tillEndOfGrid)
- XCTAssertNotEqual(params.numberOfRows, 10)
- XCTAssertEqual(params.firstDayOfWeek, .sunday)
- XCTAssertEqual(params.hasStrictBoundaries, true)
- params = ConfigurationParameters(startDate: Date(), endDate: Date(), numberOfRows: 1)
- XCTAssertNotEqual(params.numberOfRows, 80)
- XCTAssertEqual(params.hasStrictBoundaries, false)
-
- // 12
- params = ConfigurationParameters(startDate: Date(), endDate: Date())
- XCTAssertEqual(params.generateInDates, .forAllMonths)
- XCTAssertEqual(params.generateOutDates, .tillEndOfGrid)
- XCTAssertNotEqual(params.numberOfRows, 100)
- XCTAssertEqual(params.firstDayOfWeek, .sunday)
- XCTAssertEqual(params.hasStrictBoundaries, true)
- params = ConfigurationParameters(startDate: Date(), endDate: Date(), numberOfRows: 1)
- XCTAssertNotEqual(params.numberOfRows, 20)
- XCTAssertEqual(params.hasStrictBoundaries, false)
-
-
- // 13
- params = ConfigurationParameters(startDate: Date(), endDate: Date())
- XCTAssertEqual(params.generateInDates, .forAllMonths)
- XCTAssertEqual(params.generateOutDates, .tillEndOfGrid)
- XCTAssertNotEqual(params.numberOfRows, 9)
- XCTAssertEqual(params.firstDayOfWeek, .sunday)
- XCTAssertEqual(params.hasStrictBoundaries, true)
- params = ConfigurationParameters(startDate: Date(), endDate: Date(), numberOfRows: 1)
- XCTAssertNotEqual(params.numberOfRows, 100)
- XCTAssertEqual(params.hasStrictBoundaries, false)
-
- // 14
- params = ConfigurationParameters(startDate: Date(), endDate: Date())
- XCTAssertEqual(params.generateInDates, .forAllMonths)
- XCTAssertEqual(params.generateOutDates, .tillEndOfGrid)
- XCTAssertNotEqual(params.numberOfRows, 200)
- XCTAssertEqual(params.firstDayOfWeek, .sunday)
- XCTAssertEqual(params.hasStrictBoundaries, true)
- params = ConfigurationParameters(startDate: Date(), endDate: Date(), numberOfRows: 1)
- XCTAssertNotEqual(params.numberOfRows, 300)
- XCTAssertEqual(params.hasStrictBoundaries, false)
- }
-}
diff --git a/Tests/LinuxMain.swift b/Tests/LinuxMain.swift
new file mode 100644
index 00000000..2126e573
--- /dev/null
+++ b/Tests/LinuxMain.swift
@@ -0,0 +1,7 @@
+import XCTest
+
+import JTAppleCalendarTests
+
+var tests = [XCTestCaseEntry]()
+tests += JTAppleCalendarTests.allTests()
+XCTMain(tests)
diff --git a/UITests/UITests.swift b/UITests/UITests.swift
deleted file mode 100644
index 71dc91cd..00000000
--- a/UITests/UITests.swift
+++ /dev/null
@@ -1,33 +0,0 @@
-//
-// UITests.swift
-// UITests
-//
-// Created by Jay Thomas on 2017-09-20.
-//
-
-import XCTest
-
-class UITests: XCTestCase {
-
- override func setUp() {
- super.setUp()
-
- // Put setup code here. This method is called before the invocation of each test method in the class.
-
- // In UI tests it is usually best to stop immediately when a failure occurs.
- continueAfterFailure = false
- // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method.
- XCUIApplication().launch()
-
- // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this.
- }
-
- override func tearDown() {
- // Put teardown code here. This method is called after the invocation of each test method in the class.
- super.tearDown()
- }
-
- func testExample() {
- }
-
-}
diff --git a/docs/adding-events/Adding Events.md b/docs/adding-events/Adding Events.md
new file mode 100644
index 00000000..411c1311
--- /dev/null
+++ b/docs/adding-events/Adding Events.md
@@ -0,0 +1,136 @@
+# Adding Events
+
+> [!WARNING]
+> This documentation requires assistance, particularly updating to SwiftUI. If possible, please submit a PR to help improve the documentation
+
+Adding events – or adding a dot-view to signify an event on a date cell – is exactly the same as you would add a custom view to a UITableView or UICollectionView cell.
+
+In the case of UICollectionView/UITableView, you would design the cell in the cellForItemAtIndexPath function based on the cell’s index, in relation the the dataSource’s index.
+
+In the case of this library, it is exactly the same. The only difference is that instead of using a cell’s associated index, we use a cell’s associated date.
+
+# Creating the dot view
+
+First, for better viewing, increase the constraint height of the calendar to 450.
+
+
+
+Next, create the red `dotView` as seen below. Take note of the constraints used.
+
+
+
+The dotView needs to look round, therefore set a cornerRadius for it. I use storyboard for simplicity, but code may be preferred.
+
+
+
+Add an IBOutlet for the the dotView. Go to the DateCell class and add this code.
+
+```swift
+import JTAppleCalendar
+import UIKit
+
+class DateCell: JTAppleCell {
+ @IBOutlet var dateLabel: UILabel!
+ @IBOutlet var dotView: UIView!
+}
+```
+
+Now connect your dotView IBOutlet on storyboard as seen below.
+
+
+
+Run your app. It should look like this
+
+
+
+## Attaching events to your dotView
+
+Now we only want the dot view to be visible for specific dates in our dataSource. The calendar library operates on dates and not indexes, therefore the dataSource should relate every cell to dates.
+
+Lets add a DateFormatter to be used globally for events & the dataSource dictionary. DataSource will be explained below.
+
+```swift
+class ViewController: UIViewController {
+ @IBOutlet var calendarView: JTAppleCalendarView!
+
+ var calendarDataSource: [String:String] = [:]
+ var formatter: DateFormatter {
+ let formatter = DateFormatter()
+ formatter.dateFormat = "dd-MMM-yyyy"
+ return formatter
+ }
+```
+
+Modify the `configureCalendar` function
+
+```swift
+extension ViewController: JTAppleCalendarViewDataSource {
+ func configureCalendar(_ calendar: JTAppleCalendarView) ->; ConfigurationParameters {
+ let startDate = formatter.date(from: "01-jan-2018")!
+ let endDate = Date()
+ return ConfigurationParameters(startDate: startDate, endDate: endDate)
+ }
+}
+```
+
+Add this line of code
+
+```swift
+func configureCell(view: JTAppleCell?, cellState: CellState) {
+ guard let cell = view as? DateCell else { return }
+ cell.dateLabel.text = cellState.text
+ handleCellTextColor(cell: cell, cellState: cellState)
+ handleCellEvents(cell: cell, cellState: cellState)
+}
+```
+
+## The dataSource
+
+Finally, let’s talk about population of the dataSource. Add the following code.
+
+```swift
+func populateDataSource() {
+ // You can get the data from a server.
+ // Then convert that data into a form that can be used by the calendar.
+ calendarDataSource = [
+ "07-Jan-2018": "SomeData",
+ "15-Jan-2018": "SomeMoreData",
+ "15-Feb-2018": "MoreData",
+ "21-Feb-2018": "onlyData",
+ ]
+ // update the calendar
+ calendarView.reloadData()
+}
+```
+
+We need some way to associate the dateCells with the datasource. The best way to identify a cell is by Date, therefore I chose a dataSource with a date string as the key.
+
+Now create the following function. It is responsible for determining the visibility of the dotView. If the date has an event, it will be visible, else it will be hidden.
+
+```swift
+func handleCellEvents(cell: DateCell, cellState: CellState) {
+ let dateString = formatter.string(from: cellState.date)
+ if calendarDataSource[dateString] == nil {
+ cell.dotView.isHidden = true
+ } else {
+ cell.dotView.isHidden = false
+ }
+}
+```
+
+To test this code, finally add this line of code and run the app.
+
+```swift
+override func viewDidLoad() {
+ super.viewDidLoad()
+ calendarView.scrollDirection = .horizontal
+ calendarView.scrollingMode = .stopAtEachCalendarFrame
+ calendarView.showsHorizontalScrollIndicator = false
+
+ populateDataSource()
+}
+```
+
+## Next Steps
+
+Learn more about [implementing week numbers](../implementing-week-numbers/Implementing%20week%20numbers.md)
diff --git a/docs/adding-events/images/image1.png b/docs/adding-events/images/image1.png
new file mode 100644
index 00000000..faff14dd
Binary files /dev/null and b/docs/adding-events/images/image1.png differ
diff --git a/docs/adding-events/images/image2.png b/docs/adding-events/images/image2.png
new file mode 100644
index 00000000..4315da6e
Binary files /dev/null and b/docs/adding-events/images/image2.png differ
diff --git a/docs/adding-events/images/image3.png b/docs/adding-events/images/image3.png
new file mode 100644
index 00000000..1318597c
Binary files /dev/null and b/docs/adding-events/images/image3.png differ
diff --git a/docs/adding-events/images/image4.png b/docs/adding-events/images/image4.png
new file mode 100644
index 00000000..bbed1af1
Binary files /dev/null and b/docs/adding-events/images/image4.png differ
diff --git a/docs/adding-events/images/image5.png b/docs/adding-events/images/image5.png
new file mode 100644
index 00000000..394566d2
Binary files /dev/null and b/docs/adding-events/images/image5.png differ
diff --git a/docs/build-calendar/Build A Calendar From Scratch.md b/docs/build-calendar/Build A Calendar From Scratch.md
new file mode 100644
index 00000000..78932b54
--- /dev/null
+++ b/docs/build-calendar/Build A Calendar From Scratch.md
@@ -0,0 +1,110 @@
+# Build a Calendar from scratch
+
+## HELP REQUIRED - Using SwiftUI
+
+> [!WARNING]
+> This section is incomplete, please help update it by submitting a PR
+
+## Using story board
+
+1. Drag a UICollectionView unto the screen. Change its class and module to JTAppleCalendarView and JTAppleCalendar respectively.
+
+Correctly set both the height and width constraints. Constraints are needed for the library to determine cell size.
+
+
+
+2. UICollectionView may come with default minimum-cell-spacing and minimum-line-spacing. Unless your design requires it, please set both to zero as shown below.
+
+
+
+3. Design the cell. This example uses a single UILabel. But this design can be anything (example images, rounded selections, dot-views for events etc).
+
+Be sure to set correct constraints for the label (typically center the label in the cell both vertically and horizontally). Improper constraints results in bugged views. Also remember to set the cell’s `reusableIdentifier` to `dateCell`.
+
+
+
+4. Create a new cell class.
+
+```swift
+import JTAppleCalendar
+import UIKit
+class DateCell: JTAppleCell {
+ @IBOutlet var dateLabel: UILabel!
+}
+```
+
+Now head back to Storyboard. The cell’s class is already set, so just connect the IBOutlet to the UILabel of the cell.
+
+
+
+
+5. Now lets write some more code.
+
+The following is self explanatory.
+
+```swift
+import UIKit
+import JTAppleCalendar
+class ViewController: UIViewController {
+ override func viewDidLoad() {
+ super.viewDidLoad()
+ }
+}
+```
+
+6. Go back to Storyboard and set the calendar’s ibCalendarDataSource and ibCalendarDelegate to be the ViewController subclass.
+
+
+
+Write some more code.
+
+This is the first required delegate.
+
+```swift
+extension ViewController: JTAppleCalendarViewDataSource {
+ func configureCalendar(\_ calendar: JTAppleCalendarView) -> ConfigurationParameters {
+ let formatter = DateFormatter()
+ formatter.dateFormat = "yyyy MM dd"
+ let startDate = formatter.date(from: "2018 01 01")!
+ let endDate = Date()
+ return ConfigurationParameters(startDate: startDate, endDate: endDate)
+ }
+}
+```
+
+This library is a ranged calendar. It has no infinite scrolling out-of-the-box (although some creative developers have accomplished it). There are 2 mandatory parameters, `startDate` for `startMonth`, and `endDate` for `endMonth`.
+
+ConfigurationParameters full parameter list is:
+
+- **startDate** – start boundary for calendar
+- **endDate** – end boundary for calendar
+- **numberOfRows** – default is 6
+- **calendar** – this calendar() instance is responsible for region/timezones and the way your calendar will look in case you want an Arabic calendar for example. If none is given, the default iOS Calendar instance is provided.
+- **generateInDates** – control the generation of inDates.
+- **generateOutDates** – control the generation of outDates.
+- **firstDayOfWeek** – set any day to be the first day of the week. Sunday is default.
+- **hasStrictBoundaries** – controls the strictness of month boundaries.
+
+These are the final 2 delegate functions.
+
+```swift
+extension ViewController: JTAppleCalendarViewDelegate {
+ func calendar(_ calendar: JTAppleCalendarView, cellForItemAt date: Date, cellState: CellState, indexPath: IndexPath) -> JTAppleCell {
+ let cell = calendar.dequeueReusableJTAppleCell(withReuseIdentifier: "dateCell", for: indexPath) as! DateCell
+ cell.dateLabel.text = cellState.text
+ return cell
+ }
+ func calendar(_ calendar: JTAppleCalendarView, willDisplay cell: JTAppleCell, forItemAt date: Date, cellState: CellState, indexPath: IndexPath) {
+ let cell = cell as! DateCell
+ cell.dateLabel.text = cellState.text
+ }
+}
+```
+
+These 2 functions should contain the same code, therefore it is wise to have a shared function to reduce code duplication. The only difference between these two functions should be the first line of code (the dequeuing code). Reasons for the 2 functions having the same code are found [here](https://github.com/patchthecode/JTAppleCalendar/issues/553) under problem#1.
+
+Now run your test app and you should have a simple calendar going. If you wish to have paging enabled or have the scrollBar be invisible etc etc, then just remember that this library is a UICollectionView. Therefore enabling and hiding these are done the exact same way as a UICollectionView.
+
+## Next Steps
+
+Where to go from here? Learn about [common elements](../common-elements/Common%20Elements.md)
diff --git a/docs/build-calendar/images/image1.png b/docs/build-calendar/images/image1.png
new file mode 100644
index 00000000..6f9cff07
Binary files /dev/null and b/docs/build-calendar/images/image1.png differ
diff --git a/docs/build-calendar/images/image2.png b/docs/build-calendar/images/image2.png
new file mode 100644
index 00000000..14a3a273
Binary files /dev/null and b/docs/build-calendar/images/image2.png differ
diff --git a/docs/build-calendar/images/image3.png b/docs/build-calendar/images/image3.png
new file mode 100644
index 00000000..6a07ec83
Binary files /dev/null and b/docs/build-calendar/images/image3.png differ
diff --git a/docs/build-calendar/images/image4.png b/docs/build-calendar/images/image4.png
new file mode 100644
index 00000000..a4fec204
Binary files /dev/null and b/docs/build-calendar/images/image4.png differ
diff --git a/docs/build-calendar/images/image5.png b/docs/build-calendar/images/image5.png
new file mode 100644
index 00000000..00b18165
Binary files /dev/null and b/docs/build-calendar/images/image5.png differ
diff --git a/docs/build-calendar/images/image6.png b/docs/build-calendar/images/image6.png
new file mode 100644
index 00000000..6ad16c47
Binary files /dev/null and b/docs/build-calendar/images/image6.png differ
diff --git a/docs/common-elements/Common Elements.md b/docs/common-elements/Common Elements.md
new file mode 100644
index 00000000..4139c734
--- /dev/null
+++ b/docs/common-elements/Common Elements.md
@@ -0,0 +1,14 @@
+# Common elements of every calendar
+
+> [!WARNING]
+> This section requires assistance. Please submit a PR if possible to help improve documentation
+
+Each calendar has a set of common elements. Configuration for these elements can be found here:
+
+- [Configuring inDates/monthDates/outDates](./configure-in-out-month-dates/Configuring%20inDates%20monthDates%20outDates.md)
+- [Regular selection](./regular-selection/Regular%20Selection.md)
+- [Handle device rotation](./device-rotation/Handling%20Device%20Rotation.md)
+
+# Next Steps
+
+Learn more about [scrolling modes](../scrolling-modes/Scrolling%20Modes.md)
diff --git a/docs/common-elements/configure-in-out-month-dates/Configuring inDates monthDates outDates.md b/docs/common-elements/configure-in-out-month-dates/Configuring inDates monthDates outDates.md
new file mode 100644
index 00000000..49ec07fb
--- /dev/null
+++ b/docs/common-elements/configure-in-out-month-dates/Configuring inDates monthDates outDates.md
@@ -0,0 +1,120 @@
+# Configuring inDates monthDates outDates
+
+> [!WARNING]
+> This documentation requires assistance, particularly updating to SwiftUI. If possible, please submit a PR to help improve the documentation
+
+If you followed the [building from scratch tutorial](../../build-calendar/Build%20A%20Calendar%20From%20Scratch.md), your calendar should look like this. You would also know what inDates/outDates are.
+
+
+
+## Set fixed inDates/outDates/monthDates
+
+The calendar is difficult to read with inDates/outDates/monthDates the same color. Lets change that. Create the following 2 functions.
+
+```swift
+func configureCell(view: JTAppleCell?, cellState: CellState) {
+ guard let cell = view as? DateCell else { return }
+ cell.dateLabel.text = cellState.text
+ handleCellTextColor(cell: cell, cellState: cellState)
+}
+
+func handleCellTextColor(cell: DateCell, cellState: CellState) {
+ if cellState.dateBelongsTo == .thisMonth {
+ cell.dateLabel.textColor = UIColor.black
+ } else {
+ cell.dateLabel.textColor = UIColor.gray
+ }
+}
+```
+
+
+
+- Blue indicates `thisMonth`
+- Red indicates `previousMonthWithinBoundary`
+- Green indicates `followingMonthWithinBoundary`
+
+Rewrite the following functions
+
+```swift
+func calendar(_ calendar: JTAppleCalendarView, cellForItemAt date: Date, cellState: CellState, indexPath: IndexPath) -> JTAppleCell {
+ let cell = calendar.dequeueReusableJTAppleCell(withReuseIdentifier: "dateCell", for: indexPath) as! DateCell
+ self.calendar(calendar, willDisplay: cell, forItemAt: date, cellState: cellState, indexPath: indexPath)
+ return cell
+}
+
+func calendar(_ calendar: JTAppleCalendarView, willDisplay cell: JTAppleCell, forItemAt date: Date, cellState: CellState, indexPath: IndexPath) {
+ configureCell(view: cell, cellState: cellState)
+}
+```
+
+The `cellForItemAtDate` function calls the `willDisplayCell` function so that code can be reused. This is done because both functions have to [contain the same code](https://github.com/patchthecode/JTAppleCalendar/issues/553)
+
+Finally, get rid of the UIScrollView (either through code or InterfaceBuilder), and enable paging. This is done exactly the same way as would be done for a UICollectionView.
+
+Now run your app. It should look like this.
+
+
+
+## Other design considerations
+
+### Hidden inDates/outDates
+
+Apart from making the changing the color of inDates/outDates you can also make them hidden.
+
+```swift
+if cellState.dateBelongsTo == .thisMonth {
+ cell.isHidden = false
+} else {
+ cell.isHidden = true
+}
+```
+
+To give the following effect
+
+
+
+You can hide inDates, but leave outDates visible or vice-versa. Any combination is possible. This is done by changing the if condition.
+
+The full list of `dateBelongsTo`:
+
+- thisMonth
+- previousMonthWithinBoundary
+- previousMonthOutsideBoundary
+- followingMonthWithinBoundary
+- followingMonthOutsideBoundary
+
+### Generating inDates/outDates. What are they?
+
+It is important to note that generating in/out dates is different from hiding them as shown above. Hidden ones are still generated. The difference affects how your calendar looks.
+
+Heading back to the `configureCalendar` delegate introduced in the [calendar from scratch tutorial](../../build-calendar/Build%20A%20Calendar%20From%20Scratch.md). Lets modify the ConfigurationParameters to configure the generation of inDates/outDates
+
+```swift
+func configureCalendar(_ calendar: JTAppleCalendarView) -> ConfigurationParameters {
+ let formatter = DateFormatter()
+ formatter.dateFormat = "yyyy MM dd"
+
+ let startDate = formatter.date(from: "2018 01 01")!
+ let endDate = Date()
+ return ConfigurationParameters(startDate: startDate,
+ endDate: endDate,
+ generateInDates: .forAllMonths,
+ generateOutDates: .tillEndOfGrid)
+}
+```
+
+#### generateInDates
+
+- `forFirstMonthOnly` – Only your first month will generate inDates/offsets. All the other months will start with no inDates/offsets.
+- `forAllMonths` – All months will have inDates/offsets
+- `off` – No months will have any inDates/offsets.
+
+#### generateOutDates
+
+- `tillEndOfRow` – This will generate outDates till it reaches the first end of a row. In short – if your calendar month has 6 rows, then it will display 6 rows. If your calendar month has 5 rows, then it will display 5 rows.
+- `tillEndOfGrid` – This will generate outDates until it reaches the end of a 6 x 7 grid (42 cells). In Short, it will always display a 6 row calendar month.
+- `off` – Your calendar month will not generate any outDates.
+
+## Next Steps
+
+Learn more about [regular selection of dates](../regular-selection/Regular%20Selection.md)
diff --git a/docs/common-elements/configure-in-out-month-dates/images/image1.png b/docs/common-elements/configure-in-out-month-dates/images/image1.png
new file mode 100644
index 00000000..3dcdbd79
Binary files /dev/null and b/docs/common-elements/configure-in-out-month-dates/images/image1.png differ
diff --git a/docs/common-elements/configure-in-out-month-dates/images/image2.png b/docs/common-elements/configure-in-out-month-dates/images/image2.png
new file mode 100644
index 00000000..038e0d36
Binary files /dev/null and b/docs/common-elements/configure-in-out-month-dates/images/image2.png differ
diff --git a/docs/common-elements/configure-in-out-month-dates/images/image3.png b/docs/common-elements/configure-in-out-month-dates/images/image3.png
new file mode 100644
index 00000000..08dc3c4c
Binary files /dev/null and b/docs/common-elements/configure-in-out-month-dates/images/image3.png differ
diff --git a/docs/common-elements/configure-in-out-month-dates/images/image4.png b/docs/common-elements/configure-in-out-month-dates/images/image4.png
new file mode 100644
index 00000000..052fcf4d
Binary files /dev/null and b/docs/common-elements/configure-in-out-month-dates/images/image4.png differ
diff --git a/docs/common-elements/device-rotation/Handling Device Rotation.md b/docs/common-elements/device-rotation/Handling Device Rotation.md
new file mode 100644
index 00000000..c085c48a
--- /dev/null
+++ b/docs/common-elements/device-rotation/Handling Device Rotation.md
@@ -0,0 +1,26 @@
+# Handling device rotation
+
+Whenever the device orientation changes, you need to let the library know about it by calling this function
+
+```swift
+public func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator, anchorDate: Date?)
+```
+
+Typically, developers should add it to the `viewWillTransition` delegate function of their ViewController SubClass.
+
+Here is an example of the usage:
+
+```swift
+override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
+ let visibleDates = calendarView.visibleDates()
+ calendarView.viewWillTransition(to: .zero, with: coordinator, anchorDate: visibleDates.monthDates.first?.date)
+}
+```
+
+The library needs to know what date should be focused on the screen when the orientation changes. In the above code, the first visible `monthDate` was captured and used as the anchor focus date.
+
+When the orientation change completes, that month’s date will be focused on the screen.
+
+## Next Steps
+
+Learn more about [scrolling modes](../../scrolling-modes/Scrolling%20Modes.md)
diff --git a/docs/common-elements/regular-selection/Regular Selection.md b/docs/common-elements/regular-selection/Regular Selection.md
new file mode 100644
index 00000000..f04d397f
--- /dev/null
+++ b/docs/common-elements/regular-selection/Regular Selection.md
@@ -0,0 +1,71 @@
+# Regular selection
+
+> [!WARNING]
+> This section requires assistance, particularly updating to SwiftUI. Please submit a PR if possible to help improve documentation
+
+When user taps a date cell, you’ll need a highlighted UIView to show the user that the cell was selected.
+
+We need to create a `selectedView` in the DateCell class. We’ll use this to display a red-color selection to the user.
+
+Modify the DateCell to include the highlighted code below
+
+```swift
+class DateCell: JTAppleCell {
+ @IBOutlet var dateLabel: UILabel!
+ @IBOutlet var selectedView: UIView!
+}
+```
+
+On storyboard, create a UIView and place it behind the UILabel so that it will not hide the label. Set color to red. It is important that you set valid constraints else it will not display correctly. I have set both width and height to be 50. I have also set the view to be centered both vertical and horizontal inside the cell.
+
+
+
+Next, connect this UIView to the `selectedView` IBOutlet variable in the DateCell class. The `selectedView` should now be connected to the cell.
+
+Next, Add the following highlighted code to the ViewController class
+
+```swift
+func configureCell(view: JTAppleCell?, cellState: CellState) {
+ guard let cell = view as? DateCell else { return }
+ cell.dateLabel.text = cellState.text
+ handleCellTextColor(cell: cell, cellState: cellState)
+ handleCellSelected(cell: cell, cellState: cellState)
+ }
+
+func handleCellSelected(cell: DateCell, cellState: CellState) {
+ if cellState.isSelected {
+ cell.selectedView.layer.cornerRadius = 13
+ cell.selectedView.isHidden = false
+ } else {
+ cell.selectedView.isHidden = true
+ }
+}
+```
+
+The code is now ready to handle both selections and de-selections.
+
+The final step is to call this function both when a cell is selected and deselected. Add the following code to the ViewController class.
+
+```swift
+func calendar(\_ calendar: JTAppleCalendarView, didSelectDate date: Date, cell: JTAppleCell?, cellState: CellState) {
+ configureCell(view: cell, cellState: cellState)
+}
+
+func calendar(\_ calendar: JTAppleCalendarView, didDeselectDate date: Date, cell: JTAppleCell?, cellState: CellState) {
+ configureCell(view: cell, cellState: cellState)
+}
+```
+
+Other delegate functions that may be of interest are:
+
+```swift
+func calendar(\_ calendar: JTAppleCalendarView, shouldSelectDate date: Date, cell: JTAppleCell?, cellState: CellState) -> Bool {
+ return true // Based on a criteria, return true or false
+}
+```
+
+Very useful if you want to prevent selection.
+
+## Next Steps
+
+Learn more about [device rotation](../device-rotation/Handling%20Device%20Rotation.md)
diff --git a/docs/common-elements/regular-selection/images/image1.png b/docs/common-elements/regular-selection/images/image1.png
new file mode 100644
index 00000000..c090ae65
Binary files /dev/null and b/docs/common-elements/regular-selection/images/image1.png differ
diff --git a/docs/get-started/Get Started.md b/docs/get-started/Get Started.md
new file mode 100644
index 00000000..ac326a5f
--- /dev/null
+++ b/docs/get-started/Get Started.md
@@ -0,0 +1,42 @@
+# JTAppleCalendar Tutorials and Examples [V 7.1.7]
+
+> [!CAUTION]
+> This documentation comes from [this zipped version of the old docs site](https://github.com/patchthecode/JTAppleCalendar/issues/1397#issuecomment-2054113374) in the repo, and may be out of date with respect to the latest changes. Please submit an issue (or better yet a PR) to resolve any issues in the documentation
+
+## [Version 8.0.0 migration guide](../migration-guide/v8%20Migration%20Guide.md)
+
+## Why use this library?
+
+
+
+- **Total customization of all views** – This lib does not design anything. It only provides a layout (7 columns and 1-6 rows). Therefore any visual design of both cells and calendar is possible.
+- **Horizontal or vertical mode** – Ability to switch from a vertical scrolling to horizontal scrolling calendar.
+- **Range selection** – Select dates in a range.
+- **Week/Month mode** – 7 columns (Sunday to Saturday). But you decide how many rows to display. Number of rows are limited to the range 1 to 6.
+- **Custom first day of week** – First day of week does not have to be Sunday. You can pick any day.
+- Headers – Ability to add headers of varying sizes for each month.
+
+These are a fraction of many more features. Here are [calendar styles](https://github.com/patchthecode/JTAppleCalendar/issues/2) created by developers using this lib.
+
+## Repetitive questions / delayed answers
+
+Familiarity with the following non-calendar pointers, helps avoid repetitive questions and delayed answers.
+
+- How to use UITableView or UICollectionView and understand how delegate functions work. Knowledge that cells are reused in these controls.
+- Questions about this library asked on Github, will get a faster response than contacting me by email.
+- Knowledge about the iOS Calendar() class and how time zones work in iOS to avoid questions such as [this one](https://github.com/patchthecode/JTAppleCalendar/issues/252) (2nd most repeated question)
+
+Lets Begin!
+
+1. [Installation](../installation/Installation.md)
+2. [Build calendar from scratch](../build-calendar/Build%20A%20Calendar%20From%20Scratch.md)
+3. [Common elements of every calendar](../common-elements/Common%20Elements.md)
+ - [Configuring inDates/monthDates/outDates](../common-elements/configure-in-out-month-dates/Configuring%20inDates%20monthDates%20outDates.md)
+ - [Regular selection](../common-elements//regular-selection/Regular%20Selection.md)
+ - [Handle device rotation](../common-elements/device-rotation/Handling%20Device%20Rotation.md)
+4. [Scrolling modes](../scrolling-modes/Scrolling%20Modes.md)
+5. [Switch between month-view and week-view](../switch-month-to-week-view/Switch%20between%20month-view%20and%20week-view.md)
+6. [Headers](../headers/Headers.md)
+7. [Range selection styles](../range-selection-styles/Range%20selection%20styles.md)
+8. [Events and loading information from a server](../adding-events/Adding%20Events.md)
+9. [How to add a week number column](../implementing-week-numbers/Implementing%20week%20numbers.md)
diff --git a/docs/get-started/image1.gif b/docs/get-started/image1.gif
new file mode 100644
index 00000000..fb2251b7
Binary files /dev/null and b/docs/get-started/image1.gif differ
diff --git a/docs/headers/Headers.md b/docs/headers/Headers.md
new file mode 100644
index 00000000..0436e4ba
--- /dev/null
+++ b/docs/headers/Headers.md
@@ -0,0 +1,112 @@
+# Headers
+
+## Outside Headers
+
+The easiest header you can create is with a UIStackView containing 7 UILabels for the days and another label for the month.
+
+
+
+These headers will not scroll with calendar-view (seen below) and have nothing to do with the calendar as they are created by yourself.
+
+
+
+## Inside Headers
+
+These are generated by the calendar. They will scroll as the user scrolls.
+
+
+
+> [!WARNING]
+> This documentation requires assistance getting up to date, especially with SwiftUI. Please submit a PR if possible to help out
+
+### Step 1
+
+We will use storyboard mixed with some code, but this can also be done with xibs or pure code only.
+
+Let’s make the calendar both horizontally scrolled and paged. To do that we need a calendar IBOutlet. Add the following to the ViewController class.
+
+```swift
+class ViewController: UIViewController {
+@IBOutlet var calendarView: JTAppleCalendarView!
+ override func viewDidLoad() {
+ super.viewDidLoad()
+ }
+}
+```
+
+Next, let’s connect this outlet with the calendar on storyboard.
+
+
+
+Now, write the following code to make the calendar horizontal and paged. Keep in mind that everything in code can also be done direct via xibs/storyboard.
+
+```swift
+class ViewController: UIViewController {
+@IBOutlet var calendarView: JTAppleCalendarView!
+ override func viewDidLoad() {
+ super.viewDidLoad()
+ calendarView.scrollDirection = .horizontal
+ calendarView.scrollingMode = .stopAtEachCalendarFrame
+ calendarView.showsHorizontalScrollIndicator = false
+ }
+}
+```
+
+If you run your project, the calendar should look better visually.
+
+Now head back to storyboard, and let’s create the header.
+
+### Step 2
+
+In storyboard, click on the CollectionView and add the section header. Set the color to green and then add a UILabel. Using constraints, center the UILabel both vertically and horizontally inside of the green header.
+
+
+
+Note, these parts should already be familiar to you because it is exactly the same as a regular UICollectionView.
+
+Set the header’s reusable identifier to `DateHeader`
+
+
+
+### Step 3
+
+Now we need to create a class for the header, then set it on storyboard. Create the following class.
+
+```swift
+import UIKit
+import JTAppleCalendar
+
+class DateHeader: JTAppleCollectionReusableView {
+@IBOutlet var monthTitle: UILabel!
+}
+```
+
+Head to storyboard and set the header’s class to be `DateHeader`
+
+
+
+Now connect the IBOutlet `monthTitle` to the UILabel within the header on storyboard.
+
+
+
+4. Finally, let’s write the header delegates. You notice this entire process is almost exactly the way headers are done in a UICollectionView.
+
+```swift
+func calendar(\_ calendar: JTAppleCalendarView, headerViewForDateRange range: (start: Date, end: Date), at indexPath: IndexPath) -> JTAppleCollectionReusableView {
+ let formatter = DateFormatter() // Declare this outside, to avoid instancing this heavy class multiple times.
+ formatter.dateFormat = "MMM"
+ let header = calendar.dequeueReusableJTAppleSupplementaryView(withReuseIdentifier: "DateHeader", for: indexPath) as! DateHeader
+ header.monthTitle.text = formatter.string(from: range.start)
+ return header
+}
+
+func calendarSizeForMonths(\_ calendar: JTAppleCalendarView?) -> MonthSize? {
+ return MonthSize(defaultSize: 50)
+}
+```
+
+Now run your app. You should have a working calendar with an implemented header.
+
+## Next Steps
+
+Find out more about [range selection style](../range-selection-styles/Range%20selection%20styles.md)
diff --git a/docs/headers/images/image1.png b/docs/headers/images/image1.png
new file mode 100644
index 00000000..0ee09aae
Binary files /dev/null and b/docs/headers/images/image1.png differ
diff --git a/docs/headers/images/image2.gif b/docs/headers/images/image2.gif
new file mode 100644
index 00000000..0d272a32
Binary files /dev/null and b/docs/headers/images/image2.gif differ
diff --git a/docs/headers/images/image3.gif b/docs/headers/images/image3.gif
new file mode 100644
index 00000000..49381b59
Binary files /dev/null and b/docs/headers/images/image3.gif differ
diff --git a/docs/headers/images/image4.png b/docs/headers/images/image4.png
new file mode 100644
index 00000000..c07e90e4
Binary files /dev/null and b/docs/headers/images/image4.png differ
diff --git a/docs/headers/images/image5.png b/docs/headers/images/image5.png
new file mode 100644
index 00000000..fab52db8
Binary files /dev/null and b/docs/headers/images/image5.png differ
diff --git a/docs/headers/images/image6.png b/docs/headers/images/image6.png
new file mode 100644
index 00000000..ee50096b
Binary files /dev/null and b/docs/headers/images/image6.png differ
diff --git a/docs/headers/images/image7.png b/docs/headers/images/image7.png
new file mode 100644
index 00000000..fad5a635
Binary files /dev/null and b/docs/headers/images/image7.png differ
diff --git a/docs/headers/images/image8.png b/docs/headers/images/image8.png
new file mode 100644
index 00000000..56a788d3
Binary files /dev/null and b/docs/headers/images/image8.png differ
diff --git a/docs/implementing-week-numbers/Implementing week numbers.md b/docs/implementing-week-numbers/Implementing week numbers.md
new file mode 100644
index 00000000..1adc1fc6
--- /dev/null
+++ b/docs/implementing-week-numbers/Implementing week numbers.md
@@ -0,0 +1,88 @@
+# Implementing week numbers
+
+> [!WARNING]
+> This documentation requires assistance, particularly updating to SwiftUI. If possible, please submit a PR to help improve the documentation
+
+This library does not come with week numbers built in. However building one is easy.
+
+## Design the views
+
+First we need to design the week number views. Head to storyboard and modify it to be similar to the image below.
+
+
+
+A UILabel for the week number was added on top. A UICollectionView added below to hold the week numbers. Finally a UILabel was centered inside the UICollectionViewCell. Add proper constraints so that it appears visually as shown.
+
+## Setup week-number cells
+
+Create a week number cell class to display the numbers.
+
+```swift
+import UIKit
+
+class WeekCountCell: UICollectionViewCell {
+ @IBOutlet var countLabel: UILabel!
+}
+```
+
+Now that we have our cell class, head to storyboard and set the class of the cell inside the UICollectionView to be `WeekCountCell`
+
+
+
+Now that the class is set, connect the label IBOutlet to `countLabel`
+
+## Setup the UICollectionView
+
+With the cell setup complete, let’s configure the collectionView. Create an IBOutlet for it in the ViewController subclass.
+
+> [!WARNING]
+> The old documentation includes the following section verbatim, but the code may be incomplete. Please use caution when following, and if it is incorrect, submit an issue or PR to improve this documentation
+
+```swift
+class ViewController: UIViewController {
+ @IBOutlet var calendarView: JTAppleCalendarView!
+ @IBOutlet var weekCount: UICollectionView!
+
+ override func viewDidLoad() {
+```
+
+Connect the UICollectionView’s reference outlet to `weekCount`. Also set its `dataSource` and delegate to be ViewController as seen below.
+
+
+
+## Final Setup code
+
+Head to the ViewController class and add the following code. We will assume that a year does not have more than 55 weeks.
+
+```swift
+extension ViewController: UICollectionViewDataSource, UICollectionViewDelegate {
+ func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
+ return 55
+ }
+
+ func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
+ let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "WeekCountCell", for: indexPath) as! WeekCountCell
+ cell.countLabel.text = "\(indexPath.item + 1)"
+ return cell
+ }
+}
+```
+
+Finally, we need this code to be run every time the user swipes the calendar. Therefore we will put in the willScroll delegate function. It will look better visually if placed there than if it were placed in the didScroll delegate function. Place the following code after the willDisplay function as shown below.
+
+> [!WARNING]
+> The old documentation includes the following section verbatim, but the code may be incomplete. Please use caution when following, and if it is incorrect, submit an issue or PR to improve this documentation
+
+```swift
+func calendar(_ calendar: JTAppleCalendarView, willDisplay cell: JTAppleCell, forItemAt date: Date, cellState: CellState, indexPath: IndexPath) {
+ configureCell(view: cell, cellState: cellState)
+}
+
+func calendar(_ calendar: JTAppleCalendarView, willScrollToDateSegmentWith visibleDates: DateSegmentInfo) {
+ let date: Date = visibleDates.monthDates.first!.date
+ let weekNumber = Calendar.current.component(.weekOfYear, from: date)
+ weekCount.scrollToItem(at: IndexPath(item: weekNumber - 1, section: 0), at: .top, animated: true)
+}
+
+func calendar(_ calendar: JTAppleCalendarView, headerViewForDateRange range: (start: Date, end: Date), at indexPath: IndexPath) ->; JTAppleCollectionReusableView {
+```
diff --git a/docs/implementing-week-numbers/images/image1.png b/docs/implementing-week-numbers/images/image1.png
new file mode 100644
index 00000000..b1adaf18
Binary files /dev/null and b/docs/implementing-week-numbers/images/image1.png differ
diff --git a/docs/implementing-week-numbers/images/image2.png b/docs/implementing-week-numbers/images/image2.png
new file mode 100644
index 00000000..402cf4de
Binary files /dev/null and b/docs/implementing-week-numbers/images/image2.png differ
diff --git a/docs/implementing-week-numbers/images/image3.png b/docs/implementing-week-numbers/images/image3.png
new file mode 100644
index 00000000..f23db888
Binary files /dev/null and b/docs/implementing-week-numbers/images/image3.png differ
diff --git a/docs/implementing-week-numbers/images/image4.png b/docs/implementing-week-numbers/images/image4.png
new file mode 100644
index 00000000..3b986a09
Binary files /dev/null and b/docs/implementing-week-numbers/images/image4.png differ
diff --git a/docs/installation/Installation.md b/docs/installation/Installation.md
new file mode 100644
index 00000000..29ef133b
--- /dev/null
+++ b/docs/installation/Installation.md
@@ -0,0 +1,89 @@
+# Installation
+
+This library can be installed in 3 ways; Cocoapods, Carthage, or manually.
+
+## Via Cocoapods
+
+CocoaPods is a dependency manager for Cocoa projects. You can install it with the following command:
+
+```
+gem install cocoapods
+```
+
+> [!NOTE]
+> CocoaPods 1.1.0+ is required to build JTApplecalendar.
+
+To integrate JTAppleCalendar into your Xcode project using CocoaPods, specify it in your Podfile:
+
+```
+source 'https://github.com/CocoaPods/Specs.git'
+platform :ios, '10.0'
+use_frameworks!
+
+target '' do
+ pod 'JTAppleCalendar', '~>; 7.1'
+end
+```
+
+Then, run the following command:
+
+```
+pod install
+```
+
+Once installation is complete, JTAppleCalendar should be installed
+
+## Troubleshooting
+
+If you’re new to CocoaPods, search how to integrate Cocoapods into your project. CocoaPods is one of the top dependency managers for integrating 3rd party frameworks into your project. But in a nut-shell, here is how to complete installation with a sample project called `test`
+
+1. Install Cocoapods
+2. Create a new xcode project. Save the name as: `test`
+3. Go to your console in the directory location where your project is located
+4. Type and run the command: `pod init`
+
+This will create a `Podfile` in that same location
+
+Edit `Podfile` so that it looks like the following:
+
+```
+# Uncomment the next line to define a global platform for your project
+
+# platform :ios, '9.0'
+
+target 'test' do
+ use_frameworks!
+ pod 'JTAppleCalendar'
+end
+```
+
+Save, and head back to terminal and run: `pod install`
+
+If all went well, installation should be complete. Close the XCodeproject, and instead reopen it using the workspace file which was generated when installation was completed
+
+## Via Carthage
+
+Carthage is a decentralized dependency manager that builds your dependencies and provides you with binary frameworks.
+
+You can install Carthage with Homebrew using the following commands:
+
+```
+brew update
+brew install carthage
+```
+
+To integrate JTAppleCalendar into your Xcode project using Carthage, specify it in your `Cartfile`
+
+```
+github "patchthecode/JTAppleCalendar" ~> 7.1
+```
+
+Run `carthage update` to build the framework and drag the built `JTApplecalendar.framework` into your Xcode project.
+
+## Manually install
+
+Simply drag the source files into your project. Make sure you remove the unnecessary import statements where needed.
+
+## Next steps
+
+Once installed, learn how to [build a calendar from scratch](../build-calendar/Build%20A%20Calendar%20From%20Scratch.md)
diff --git a/docs/migration-guide/v8 Migration Guide.md b/docs/migration-guide/v8 Migration Guide.md
new file mode 100644
index 00000000..abf5a797
--- /dev/null
+++ b/docs/migration-guide/v8 Migration Guide.md
@@ -0,0 +1,37 @@
+# JTAppleCalendar Version 8.0.0 Migration guide
+
+Changes in version 8.0.0 are mainly that the function names are changed. why? We now support YearView. because of this, distiction has to be made between yearView and monthView.
+
+**Important**: Because the names of some function have changed, if you forget to change their names you might notice things like “my functions are not being called”. If you are experiencing this, changes are you did not change the names.
+
+## Renamed Delegate Function Names
+
+```swift
+func calendar(_ calendar: JTACMonthView, shouldSelectDate date: Date, cell: JTACDayCell?, cellState: CellState, indexPath: IndexPath) -> Bool
+func calendar(_ calendar: JTACMonthView, shouldDeselectDate date: Date, cell: JTACDayCell?, cellState: CellState, indexPath: IndexPath) -> Bool
+func calendar(_ calendar: JTACMonthView, didSelectDate date: Date, cell: JTACDayCell?, cellState: CellState, indexPath: IndexPath)
+func calendar(_ calendar: JTACMonthView, didDeselectDate date: Date, cell: JTACDayCell?, cellState: CellState, indexPath: IndexPath)
+func calendar(_ calendar: JTACMonthView, didHighlightDate date: Date, cell: JTACDayCell?, cellState: CellState, indexPath: IndexPath)
+func calendar(_ calendar: JTACMonthView, didUnhighlightDate date: Date, cell: JTACDayCell?, cellState: CellState, indexPath: IndexPath)
+func calendar(_ calendar: JTACMonthView, willScrollToDateSegmentWith visibleDates: DateSegmentInfo)
+func calendar(_ calendar: JTACMonthView, didScrollToDateSegmentWith visibleDates: DateSegmentInfo)
+func calendar(_ calendar: JTACMonthView, headerViewForDateRange range: (start: Date, end: Date), at indexPath: IndexPath) -> JTACMonthReusableView
+func calendarDidScroll(_ calendar: JTACMonthView)
+func calendarSizeForMonths(_ calendar: JTACMonthView?) -> MonthSize?
+func sizeOfDecorationView(indexPath: IndexPath) -> CGRect
+func scrollDidEndDecelerating(for calendar: JTACMonthView)
+```
+
+## New Object Names
+
+```swift
+JTApplecalendarView --> JTACMonthView
+JTAppleCalendarViewDelegate --> JTACMonthViewDelegate
+JTAppleCalendarViewDataSource --> JTACMonthViewDataSource
+JTAppleDayCell --> JTACMonthCell
+JTAppleCollectionReusableView --> JTACMonthReusableView
+```
+
+## REPORTING / NOTES
+
+If you used storyboards/xibs, remember to change the name of the classes in there as well. If we missed out any thing that caused the transition experience to be complicated, then open an issue and let us know right away. It will be fixed.
diff --git a/docs/range-selection-styles/Range selection styles.md b/docs/range-selection-styles/Range selection styles.md
new file mode 100644
index 00000000..3b0e0ebe
--- /dev/null
+++ b/docs/range-selection-styles/Range selection styles.md
@@ -0,0 +1,119 @@
+# Range selection styles
+
+> [!WARNING]
+> This documentation requires assistance, particularly updating to SwiftUI. If possible, please submit a PR to help improve the documentation
+
+## Single tap range selection
+
+
+
+First let’s create an outlet for the calendarView. Add the following line and connect the IBOutlet to the calendarView on Storyboard.
+
+```swift
+import UIKit
+import JTAppleCalendar
+
+class ViewController: UIViewController {
+ @IBOutlet var calendarView: JTAppleCalendarView!
+}
+```
+
+
+
+Now add the following code.
+
+```swift
+override func viewDidLoad() {
+ super.viewDidLoad()
+ calendarView.allowsMultipleSelection = true
+ calendarView.isRangeSelectionUsed = true
+}
+```
+
+Multiple selection is needed to multi-select. Informing that range-selection will be used makes the calendar refresh cells both to the left and right of a selected cell to update its selectedView.
+
+The final code needed for range selection is below. Modify the function to the following.
+
+```swift
+func handleCellSelected(cell: DateCell, cellState: CellState) {
+ cell.selectedView.isHidden = !cellState.isSelected
+ switch cellState.selectedPosition() {
+ case .left:
+ cell.selectedView.layer.cornerRadius = 20
+ cell.selectedView.layer.maskedCorners = [.layerMinXMaxYCorner, .layerMinXMinYCorner]
+ case .middle:
+ cell.selectedView.layer.cornerRadius = 0
+ cell.selectedView.layer.maskedCorners = []
+ case .right:
+ cell.selectedView.layer.cornerRadius = 20
+ cell.selectedView.layer.maskedCorners = [.layerMaxXMaxYCorner, .layerMaxXMinYCorner]
+ case .full:
+ cell.selectedView.layer.cornerRadius = 20
+ cell.selectedView.layer.maskedCorners = [.layerMaxXMaxYCorner, .layerMaxXMinYCorner, .layerMinXMaxYCorner, .layerMinXMinYCorner]
+ default: break
+ }
+}
+```
+
+The selected view was morphed in this example for simplicity, but you can customize your view to anything.
+
+This library determines a reasonable setting for what each cell’s selectedPosition should be. If your app needs something other than this default, then, you will have to implement it your self based on your own criteria.
+
+## Drag to select range
+
+
+
+This example requires the `UITapGestureRecornizer` in order to work. We’ll start by modifying the following code:
+
+```swift
+class ViewController: UIViewController {
+
+ @IBOutlet var calendarView: JTAppleCalendarView!
+ let testCalendar = Calendar(identifier: .gregorian)
+
+ override func viewDidLoad() {
+ super.viewDidLoad()
+
+ calendarView.allowsMultipleSelection = true
+ calendarView.isRangeSelectionUsed = true
+
+ let panGensture = UILongPressGestureRecognizer(target: self, action: #selector(didStartRangeSelecting(gesture:)))
+ panGensture.minimumPressDuration = 0.5
+ calendarView.addGestureRecognizer(panGensture)
+ }
+}
+```
+
+Note that we set the minimum press duration to 0.5 seconds. This means you need to press the cell for at least 0.5 seconds before drag-selection can begin. Also note the need for the `testCalendar` instance. We use this variable for date calculations in the function below.
+
+Finally, add the following function.
+
+```swift
+@objc func didStartRangeSelecting(gesture: UILongPressGestureRecognizer) {
+ let point = gesture.location(in: gesture.view!)
+ let rangeSelectedDates = calendarView.selectedDates
+
+ guard let cellState = calendarView.cellStatus(at: point) else { return }
+
+ if !rangeSelectedDates.contains(cellState.date) {
+ let dateRange = calendarView.generateDateRange(from: rangeSelectedDates.first ?? cellState.date, to: cellState.date)
+ calendarView.selectDates(dateRange, keepSelectionIfMultiSelectionAllowed: true)
+ } else {
+ let followingDay = testCalendar.date(byAdding: .day, value: 1, to: cellState.date)!
+ calendarView.selectDates(from: followingDay, to: rangeSelectedDates.last!, keepSelectionIfMultiSelectionAllowed: false)
+ }
+}
+```
+
+The code above is just an example. If your drag-selection needs to behave differently, then please modify to suite your needs.
+
+## Select range via multiple taps
+
+
+
+> [!CAUTION]
+> This section is not available from the original docs source. If you can, please submit a PR to update this section
+
+## Next Steps
+
+Learn more about [events and loading information from a server](../adding-events/Adding%20Events.md)
diff --git a/docs/range-selection-styles/images/image1.gif b/docs/range-selection-styles/images/image1.gif
new file mode 100644
index 00000000..a7e97a60
Binary files /dev/null and b/docs/range-selection-styles/images/image1.gif differ
diff --git a/docs/range-selection-styles/images/image2.png b/docs/range-selection-styles/images/image2.png
new file mode 100644
index 00000000..a66fce50
Binary files /dev/null and b/docs/range-selection-styles/images/image2.png differ
diff --git a/docs/range-selection-styles/images/image3.gif b/docs/range-selection-styles/images/image3.gif
new file mode 100644
index 00000000..a5bcd9d1
Binary files /dev/null and b/docs/range-selection-styles/images/image3.gif differ
diff --git a/docs/range-selection-styles/images/image4.gif b/docs/range-selection-styles/images/image4.gif
new file mode 100644
index 00000000..c1166111
Binary files /dev/null and b/docs/range-selection-styles/images/image4.gif differ
diff --git a/docs/scrolling-modes/Scrolling Modes.md b/docs/scrolling-modes/Scrolling Modes.md
new file mode 100644
index 00000000..84b8305f
--- /dev/null
+++ b/docs/scrolling-modes/Scrolling Modes.md
@@ -0,0 +1,48 @@
+# Scrolling modes
+
+> [!WARNING]
+> This section requires assistance. Please submit a PR if possible to help improve documentation
+
+There are 7 modes.
+
+calendarView.scrollingMode =
+
+1. stopAtEachCalendarFrame
+
+Non-continuous scrolling. Calendar will stop scrolling when it has scrolled a distance of frame.width, before accepting another scroll.
+
+
+
+2. stopAtEachSection
+
+Non-continuous scrolling. Calendar will stop scrolling when it has scrolled a distance of a section’s width, before accepting another scroll. Months can be divided into sections depending on how many rows per month you chose to display.
+
+
+
+3. stopAtEach(customInterval: CGFloat)
+
+Non-continuous scrolling. Calendar will stop scrolling at every point where your set interval has been reached.
+
+4. nonStopToSection(withResistance: CGFloat)
+
+Continuous scrolling. Calendar will smoothly scroll and gradually decelerate. When stopped, it will snap to a section. Deceleration rate is based on resistance value (from 0.0 to 1.0)
+
+
+
+5. nonStopToCell(withResistance: CGFloat)
+
+Continuous scrolling. Calendar will smoothly scroll and gradually decelerate. When stopped, it will snap to a cell. Deceleration rate is based on resistance value (from 0.0 to 1.0)
+
+
+
+6. nonStopTo(customInterval: CGFloat, withResistance: CGFloat)
+
+Continuous scrolling. Calendar will smoothly scroll and gradually decelerate. When stopped, it will snap to your set custom interval. Deceleration rate is based on resistance value (from 0.0 to 1.0)
+
+7. none
+
+Continuous scrolling. Calendar will smoothly scroll and gradually decelerate till it stops.
+
+# Next Steps
+
+Learn how to [switch between month-view and week-view](../switch-month-to-week-view/Switch%20between%20month-view%20and%20week-view.md)
diff --git a/docs/scrolling-modes/images/image1.gif b/docs/scrolling-modes/images/image1.gif
new file mode 100644
index 00000000..49381b59
Binary files /dev/null and b/docs/scrolling-modes/images/image1.gif differ
diff --git a/docs/scrolling-modes/images/image2.gif b/docs/scrolling-modes/images/image2.gif
new file mode 100644
index 00000000..7d74a535
Binary files /dev/null and b/docs/scrolling-modes/images/image2.gif differ
diff --git a/docs/scrolling-modes/images/image3.gif b/docs/scrolling-modes/images/image3.gif
new file mode 100644
index 00000000..1e54671a
Binary files /dev/null and b/docs/scrolling-modes/images/image3.gif differ
diff --git a/docs/scrolling-modes/images/image4.gif b/docs/scrolling-modes/images/image4.gif
new file mode 100644
index 00000000..6d57d860
Binary files /dev/null and b/docs/scrolling-modes/images/image4.gif differ
diff --git a/docs/switch-month-to-week-view/Switch between month-view and week-view.md b/docs/switch-month-to-week-view/Switch between month-view and week-view.md
new file mode 100644
index 00000000..5a0f4b2b
--- /dev/null
+++ b/docs/switch-month-to-week-view/Switch between month-view and week-view.md
@@ -0,0 +1,120 @@
+# Switch between month-view and week-view
+
+> [!WARNING]
+> This documentation requires assistance, particularly updating to SwiftUI. If possible, please submit a PR to help improve the documentation
+
+This library has no concept of week/month view. You as the developer will need to define this. For this example, we will change state between a 6-row calendar and a 1-row calendar.
+
+Switching between a 6-row and 1-row calendar is pretty simple. First we’ll look at the configuration. Then we’ll look at the animation.
+
+## Configuration
+
+
+
+It is important to remember that if you switch your calendar from 6 rows to 1, the inDates/outDates will make your 1 row calendar look as if dates are being repeated.
+
+Although you can make your 1-row calendar with what ever design you want, the regular 6 row configuration will not work on a 1 row calendar for 90% of developers. This is because of the inDates/outDates shown above.
+
+Here is a proper configuration for a 1 row calendar
+
+```swift
+let parameters = ConfigurationParameters(
+ startDate: startDate,
+ endDate: endDate,
+ numberOfRows: 1,
+ generateInDates: .forFirstMonthOnly,
+ generateOutDates: .off,
+ hasStrictBoundaries: false
+ )
+```
+
+Therefore, modify your `configureCalendar` function to have the following code
+
+```swift
+func configureCalendar(_ calendar: JTAppleCalendarView) -> ConfigurationParameters {
+ let formatter = DateFormatter()
+ formatter.dateFormat = "yyyy MM dd"
+
+ let startDate = formatter.date(from: "2018 01 01")!
+ let endDate = Date()
+
+ if numberOfRows == 6 {
+ return ConfigurationParameters(startDate: startDate, endDate: endDate, numberOfRows: numberOfRows)
+ } else {
+ return ConfigurationParameters(startDate: startDate,
+ endDate: endDate,
+ numberOfRows: numberOfRows,
+ generateInDates: .forFirstMonthOnly,
+ generateOutDates: .off,
+ hasStrictBoundaries: false)
+ }
+}
+```
+
+## Animation
+
+It all has to do with constraints.
+
+Go to storyboard and modify the height constraint of the calendar to 350.
+
+
+
+Next create a blue colored view at the bottom of the calendar. Make its left, right and bottom constraints fixed. But make it’s top constraint to sit right below the collectionView with zero (0) space. This view represents the view below the calendarView that you will build in your real app. See its completed constraints below.
+
+
+
+The views are now ready. What we now need is an outlet to the hight-constraint for the calendar. Click on the height constraint of the CollectionView and create an IBOutlet for it in your view controller class.
+
+
+
+The created IBOutlet should be called constraint in your ViewController subclass. Also add a new variable called numberOfRows. We will use this to change the row number. Below shows both added code.
+
+```swift
+class ViewController: UIViewController {
+ @IBOutlet var calendarView: JTAppleCalendarView!
+ @IBOutlet weak var constraint: NSLayoutConstraint!
+
+ var numberOfRows = 6
+}
+```
+
+Finally create a toggle button on storyboard
+
+
+
+and connect its IBAction to the following code
+
+```swift
+@IBAction func toggle(_ sender: Any) {
+ if numberOfRows == 6 {
+ self.constraint.constant = 58.33
+ self.numberOfRows = 1
+ UIView.animate(withDuration: 0.2, animations: {
+ self.view.layoutIfNeeded()
+ }) { completed in
+ self.calendarView.reloadData(withanchor: Date())
+ }
+ } else {
+ self.constraint.constant = 350
+ self.numberOfRows = 6
+
+ UIView.animate(withDuration: 0.2, animations: {
+ self.view.layoutIfNeeded()
+ self.calendarView.reloadData(withanchor: Date())
+ })
+ }
+}
+```
+
+In the code above we set the `anchorDate` to be the current date, but you can set it to what ever date you wish. `anchorDate` is the date the calendar will focus on once the number of rows change. This parameter is optional. Remove if not needed.
+
+Finally delete the following 2 functions and run the app. These header functions are removed for simplicity. A new tutorial will be created on how headers affect 1 row calendars
+
+```swift
+func calendar(_ calendar: JTAppleCalendarView, headerViewForDateRange range: (start: Date, end: Date), at indexPath: IndexPath) -> JTAppleCollectionReusableView {}
+func calendarSizeForMonths(_ calendar: JTAppleCalendarView?) -> MonthSize? {}
+```
+
+## Next Steps
+
+Find out more about [headers](../headers/Headers.md)
diff --git a/docs/switch-month-to-week-view/images/image1.png b/docs/switch-month-to-week-view/images/image1.png
new file mode 100644
index 00000000..8cc45fb2
Binary files /dev/null and b/docs/switch-month-to-week-view/images/image1.png differ
diff --git a/docs/switch-month-to-week-view/images/image2.png b/docs/switch-month-to-week-view/images/image2.png
new file mode 100644
index 00000000..75d4bebc
Binary files /dev/null and b/docs/switch-month-to-week-view/images/image2.png differ
diff --git a/docs/switch-month-to-week-view/images/image3.png b/docs/switch-month-to-week-view/images/image3.png
new file mode 100644
index 00000000..0bc57bab
Binary files /dev/null and b/docs/switch-month-to-week-view/images/image3.png differ
diff --git a/docs/switch-month-to-week-view/images/image4.png b/docs/switch-month-to-week-view/images/image4.png
new file mode 100644
index 00000000..11fe7e09
Binary files /dev/null and b/docs/switch-month-to-week-view/images/image4.png differ
diff --git a/docs/switch-month-to-week-view/images/image5.png b/docs/switch-month-to-week-view/images/image5.png
new file mode 100644
index 00000000..501f718d
Binary files /dev/null and b/docs/switch-month-to-week-view/images/image5.png differ