├── .gitignore
├── .travis.yml
├── Carthage Support
└── Info.plist
├── Example
├── Example.xcodeproj
│ ├── project.pbxproj
│ ├── project.xcworkspace
│ │ └── contents.xcworkspacedata
│ └── xcshareddata
│ │ └── xcschemes
│ │ └── Example.xcscheme
├── Example.xcworkspace
│ └── contents.xcworkspacedata
├── Example
│ ├── AppDelegate.h
│ ├── AppDelegate.m
│ ├── Base.lproj
│ │ └── LaunchScreen.xib
│ ├── BasicViewController.h
│ ├── BasicViewController.m
│ ├── BasicViewController.xib
│ ├── CustomViewController.h
│ ├── CustomViewController.m
│ ├── CustomViewController.xib
│ ├── Images.xcassets
│ │ ├── AppIcon.appiconset
│ │ │ └── Contents.json
│ │ └── Contents.json
│ ├── Info.plist
│ ├── SelectionViewController.h
│ ├── SelectionViewController.m
│ ├── SelectionViewController.xib
│ ├── VerticalViewController.h
│ ├── VerticalViewController.m
│ ├── VerticalViewController.xib
│ └── main.m
├── Podfile
├── Podfile.lock
└── Pods
│ ├── Headers
│ ├── Private
│ │ └── JTCalendar
│ │ │ ├── JTCalendar.h
│ │ │ ├── JTCalendarDay.h
│ │ │ ├── JTCalendarDayView.h
│ │ │ ├── JTCalendarDelegate.h
│ │ │ ├── JTCalendarDelegateManager.h
│ │ │ ├── JTCalendarManager.h
│ │ │ ├── JTCalendarMenuView.h
│ │ │ ├── JTCalendarPage.h
│ │ │ ├── JTCalendarPageView.h
│ │ │ ├── JTCalendarScrollManager.h
│ │ │ ├── JTCalendarSettings.h
│ │ │ ├── JTCalendarWeek.h
│ │ │ ├── JTCalendarWeekDay.h
│ │ │ ├── JTCalendarWeekDayView.h
│ │ │ ├── JTCalendarWeekView.h
│ │ │ ├── JTContent.h
│ │ │ ├── JTDateHelper.h
│ │ │ ├── JTHorizontalCalendarView.h
│ │ │ ├── JTMenu.h
│ │ │ └── JTVerticalCalendarView.h
│ └── Public
│ │ └── JTCalendar
│ │ ├── JTCalendar.h
│ │ ├── JTCalendarDay.h
│ │ ├── JTCalendarDayView.h
│ │ ├── JTCalendarDelegate.h
│ │ ├── JTCalendarDelegateManager.h
│ │ ├── JTCalendarManager.h
│ │ ├── JTCalendarMenuView.h
│ │ ├── JTCalendarPage.h
│ │ ├── JTCalendarPageView.h
│ │ ├── JTCalendarScrollManager.h
│ │ ├── JTCalendarSettings.h
│ │ ├── JTCalendarWeek.h
│ │ ├── JTCalendarWeekDay.h
│ │ ├── JTCalendarWeekDayView.h
│ │ ├── JTCalendarWeekView.h
│ │ ├── JTContent.h
│ │ ├── JTDateHelper.h
│ │ ├── JTHorizontalCalendarView.h
│ │ ├── JTMenu.h
│ │ └── JTVerticalCalendarView.h
│ ├── Local Podspecs
│ └── JTCalendar.podspec.json
│ ├── Manifest.lock
│ ├── Pods.xcodeproj
│ ├── project.pbxproj
│ └── xcshareddata
│ │ └── xcschemes
│ │ └── JTCalendar.xcscheme
│ └── Target Support Files
│ ├── JTCalendar
│ ├── JTCalendar-dummy.m
│ ├── JTCalendar-prefix.pch
│ └── JTCalendar.xcconfig
│ └── Pods
│ ├── Pods-acknowledgements.markdown
│ ├── Pods-acknowledgements.plist
│ ├── Pods-dummy.m
│ ├── Pods-frameworks.sh
│ ├── Pods-resources.sh
│ ├── Pods.debug.xcconfig
│ └── Pods.release.xcconfig
├── JTCalendar.podspec
├── JTCalendar.xcodeproj
├── project.pbxproj
├── project.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ │ └── IDEWorkspaceChecks.plist
└── xcshareddata
│ └── xcschemes
│ └── JTCalendar.xcscheme
├── JTCalendar
├── Info.plist
├── JTCalendar.h
├── JTCalendarDelegate.h
├── JTCalendarManager.h
├── JTCalendarManager.m
├── JTCalendarSettings.h
├── JTCalendarSettings.m
├── JTDateHelper.h
├── JTDateHelper.m
├── Managers
│ ├── JTCalendarDelegateManager.h
│ ├── JTCalendarDelegateManager.m
│ ├── JTCalendarScrollManager.h
│ └── JTCalendarScrollManager.m
├── Protocols
│ ├── JTCalendarDay.h
│ ├── JTCalendarPage.h
│ ├── JTCalendarWeek.h
│ ├── JTCalendarWeekDay.h
│ ├── JTContent.h
│ └── JTMenu.h
└── Views
│ ├── JTCalendarDayView.h
│ ├── JTCalendarDayView.m
│ ├── JTCalendarMenuView.h
│ ├── JTCalendarMenuView.m
│ ├── JTCalendarPageView.h
│ ├── JTCalendarPageView.m
│ ├── JTCalendarWeekDayView.h
│ ├── JTCalendarWeekDayView.m
│ ├── JTCalendarWeekView.h
│ ├── JTCalendarWeekView.m
│ ├── JTHorizontalCalendarView.h
│ ├── JTHorizontalCalendarView.m
│ ├── JTVerticalCalendarView.h
│ └── JTVerticalCalendarView.m
├── LICENSE
├── README.md
└── Screens
├── example.gif
└── example.png
/.gitignore:
--------------------------------------------------------------------------------
1 | # Mac OS
2 | #
3 | .DS_Store
4 |
5 | # Xcode
6 | #
7 | build/
8 | *.pbxuser
9 | !default.pbxuser
10 | *.mode1v3
11 | !default.mode1v3
12 | *.mode2v3
13 | !default.mode2v3
14 | *.perspectivev3
15 | !default.perspectivev3
16 | xcuserdata
17 | *.xccheckout
18 | *.moved-aside
19 | DerivedData
20 | *.hmap
21 | *.ipa
22 | *.xcuserstate
23 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: objective-c
2 | xcode_workspace: Example/Example.xcworkspace
3 | xcode_scheme: Example
4 | xcode_sdk: iphonesimulator
5 | env: CODE_SIGN_IDENTITY=- CODE_SIGNING_REQUIRED=NO
6 | notifications:
7 | email: false
--------------------------------------------------------------------------------
/Carthage Support/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | $(CURRENT_PROJECT_VERSION)
21 | NSPrincipalClass
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/Example/Example.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | A478836B7E6915F6A886DADD /* libPods.a in Frameworks */ = {isa = PBXBuildFile; fileRef = A32EECC3DD04D628CA764863 /* libPods.a */; };
11 | AB21D7A11B55570E006BC9D1 /* BasicViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = AB21D79F1B55570E006BC9D1 /* BasicViewController.m */; };
12 | AB21D7A21B55570E006BC9D1 /* BasicViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = AB21D7A01B55570E006BC9D1 /* BasicViewController.xib */; };
13 | AB21D7A91B55572D006BC9D1 /* CustomViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = AB21D7A71B55572D006BC9D1 /* CustomViewController.m */; };
14 | AB21D7AA1B55572D006BC9D1 /* CustomViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = AB21D7A81B55572D006BC9D1 /* CustomViewController.xib */; };
15 | AB21D7AE1B555738006BC9D1 /* SelectionViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = AB21D7AC1B555738006BC9D1 /* SelectionViewController.m */; };
16 | AB21D7AF1B555738006BC9D1 /* SelectionViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = AB21D7AD1B555738006BC9D1 /* SelectionViewController.xib */; };
17 | AB21D7B41B55694B006BC9D1 /* VerticalViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = AB21D7B21B55694B006BC9D1 /* VerticalViewController.m */; };
18 | AB21D7B51B55694B006BC9D1 /* VerticalViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = AB21D7B31B55694B006BC9D1 /* VerticalViewController.xib */; };
19 | AB6843E51A06FCE2000ADE68 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = AB6843E41A06FCE2000ADE68 /* main.m */; };
20 | AB6843E81A06FCE2000ADE68 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = AB6843E71A06FCE2000ADE68 /* AppDelegate.m */; };
21 | AB6843F01A06FCE2000ADE68 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = AB6843EF1A06FCE2000ADE68 /* Images.xcassets */; };
22 | AB6843F31A06FCE2000ADE68 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = AB6843F11A06FCE2000ADE68 /* LaunchScreen.xib */; };
23 | /* End PBXBuildFile section */
24 |
25 | /* Begin PBXFileReference section */
26 | A32EECC3DD04D628CA764863 /* libPods.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libPods.a; sourceTree = BUILT_PRODUCTS_DIR; };
27 | AB21D79E1B55570E006BC9D1 /* BasicViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BasicViewController.h; sourceTree = ""; };
28 | AB21D79F1B55570E006BC9D1 /* BasicViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BasicViewController.m; sourceTree = ""; };
29 | AB21D7A01B55570E006BC9D1 /* BasicViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = BasicViewController.xib; sourceTree = ""; };
30 | AB21D7A61B55572D006BC9D1 /* CustomViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CustomViewController.h; sourceTree = ""; };
31 | AB21D7A71B55572D006BC9D1 /* CustomViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CustomViewController.m; sourceTree = ""; };
32 | AB21D7A81B55572D006BC9D1 /* CustomViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = CustomViewController.xib; sourceTree = ""; };
33 | AB21D7AB1B555738006BC9D1 /* SelectionViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SelectionViewController.h; sourceTree = ""; };
34 | AB21D7AC1B555738006BC9D1 /* SelectionViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SelectionViewController.m; sourceTree = ""; };
35 | AB21D7AD1B555738006BC9D1 /* SelectionViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = SelectionViewController.xib; sourceTree = ""; };
36 | AB21D7B11B55694B006BC9D1 /* VerticalViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VerticalViewController.h; sourceTree = ""; };
37 | AB21D7B21B55694B006BC9D1 /* VerticalViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VerticalViewController.m; sourceTree = ""; };
38 | AB21D7B31B55694B006BC9D1 /* VerticalViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = VerticalViewController.xib; sourceTree = ""; };
39 | AB6843DF1A06FCE2000ADE68 /* Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Example.app; sourceTree = BUILT_PRODUCTS_DIR; };
40 | AB6843E31A06FCE2000ADE68 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
41 | AB6843E41A06FCE2000ADE68 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; };
42 | AB6843E61A06FCE2000ADE68 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; };
43 | AB6843E71A06FCE2000ADE68 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; };
44 | AB6843EF1A06FCE2000ADE68 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; };
45 | AB6843F21A06FCE2000ADE68 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; };
46 | ACB1558A205302184CDC8B78 /* Pods.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.release.xcconfig; path = "Pods/Target Support Files/Pods/Pods.release.xcconfig"; sourceTree = ""; };
47 | EA29A33B12777736F86B89BA /* Pods.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.debug.xcconfig; path = "Pods/Target Support Files/Pods/Pods.debug.xcconfig"; sourceTree = ""; };
48 | /* End PBXFileReference section */
49 |
50 | /* Begin PBXFrameworksBuildPhase section */
51 | AB6843DC1A06FCE2000ADE68 /* Frameworks */ = {
52 | isa = PBXFrameworksBuildPhase;
53 | buildActionMask = 2147483647;
54 | files = (
55 | A478836B7E6915F6A886DADD /* libPods.a in Frameworks */,
56 | );
57 | runOnlyForDeploymentPostprocessing = 0;
58 | };
59 | /* End PBXFrameworksBuildPhase section */
60 |
61 | /* Begin PBXGroup section */
62 | 614C882AD7264084D149FA72 /* Pods */ = {
63 | isa = PBXGroup;
64 | children = (
65 | EA29A33B12777736F86B89BA /* Pods.debug.xcconfig */,
66 | ACB1558A205302184CDC8B78 /* Pods.release.xcconfig */,
67 | );
68 | name = Pods;
69 | sourceTree = "";
70 | };
71 | AB21D7B01B555839006BC9D1 /* Controllers */ = {
72 | isa = PBXGroup;
73 | children = (
74 | AB21D79E1B55570E006BC9D1 /* BasicViewController.h */,
75 | AB21D79F1B55570E006BC9D1 /* BasicViewController.m */,
76 | AB21D7A01B55570E006BC9D1 /* BasicViewController.xib */,
77 | AB21D7A61B55572D006BC9D1 /* CustomViewController.h */,
78 | AB21D7A71B55572D006BC9D1 /* CustomViewController.m */,
79 | AB21D7A81B55572D006BC9D1 /* CustomViewController.xib */,
80 | AB21D7AB1B555738006BC9D1 /* SelectionViewController.h */,
81 | AB21D7AC1B555738006BC9D1 /* SelectionViewController.m */,
82 | AB21D7AD1B555738006BC9D1 /* SelectionViewController.xib */,
83 | AB21D7B11B55694B006BC9D1 /* VerticalViewController.h */,
84 | AB21D7B21B55694B006BC9D1 /* VerticalViewController.m */,
85 | AB21D7B31B55694B006BC9D1 /* VerticalViewController.xib */,
86 | );
87 | name = Controllers;
88 | sourceTree = "";
89 | };
90 | AB6843D61A06FCE2000ADE68 = {
91 | isa = PBXGroup;
92 | children = (
93 | AB6843E11A06FCE2000ADE68 /* Example */,
94 | AB6843E01A06FCE2000ADE68 /* Products */,
95 | 614C882AD7264084D149FA72 /* Pods */,
96 | AF6935C573AD6FA5BBD10BEC /* Frameworks */,
97 | );
98 | sourceTree = "";
99 | };
100 | AB6843E01A06FCE2000ADE68 /* Products */ = {
101 | isa = PBXGroup;
102 | children = (
103 | AB6843DF1A06FCE2000ADE68 /* Example.app */,
104 | );
105 | name = Products;
106 | sourceTree = "";
107 | };
108 | AB6843E11A06FCE2000ADE68 /* Example */ = {
109 | isa = PBXGroup;
110 | children = (
111 | AB21D7B01B555839006BC9D1 /* Controllers */,
112 | AB6843E61A06FCE2000ADE68 /* AppDelegate.h */,
113 | AB6843E71A06FCE2000ADE68 /* AppDelegate.m */,
114 | AB6843EF1A06FCE2000ADE68 /* Images.xcassets */,
115 | AB6843F11A06FCE2000ADE68 /* LaunchScreen.xib */,
116 | AB6843E21A06FCE2000ADE68 /* Supporting Files */,
117 | );
118 | path = Example;
119 | sourceTree = "";
120 | };
121 | AB6843E21A06FCE2000ADE68 /* Supporting Files */ = {
122 | isa = PBXGroup;
123 | children = (
124 | AB6843E31A06FCE2000ADE68 /* Info.plist */,
125 | AB6843E41A06FCE2000ADE68 /* main.m */,
126 | );
127 | name = "Supporting Files";
128 | sourceTree = "";
129 | };
130 | AF6935C573AD6FA5BBD10BEC /* Frameworks */ = {
131 | isa = PBXGroup;
132 | children = (
133 | A32EECC3DD04D628CA764863 /* libPods.a */,
134 | );
135 | name = Frameworks;
136 | sourceTree = "";
137 | };
138 | /* End PBXGroup section */
139 |
140 | /* Begin PBXNativeTarget section */
141 | AB6843DE1A06FCE2000ADE68 /* Example */ = {
142 | isa = PBXNativeTarget;
143 | buildConfigurationList = AB6844021A06FCE3000ADE68 /* Build configuration list for PBXNativeTarget "Example" */;
144 | buildPhases = (
145 | E0E39738925637B9A2BEAEA2 /* Check Pods Manifest.lock */,
146 | AB6843DB1A06FCE2000ADE68 /* Sources */,
147 | AB6843DC1A06FCE2000ADE68 /* Frameworks */,
148 | AB6843DD1A06FCE2000ADE68 /* Resources */,
149 | DAEE24CF4026663FE0755656 /* Copy Pods Resources */,
150 | AD2C6F32B39EFC52F28F2F53 /* Embed Pods Frameworks */,
151 | );
152 | buildRules = (
153 | );
154 | dependencies = (
155 | );
156 | name = Example;
157 | productName = Example;
158 | productReference = AB6843DF1A06FCE2000ADE68 /* Example.app */;
159 | productType = "com.apple.product-type.application";
160 | };
161 | /* End PBXNativeTarget section */
162 |
163 | /* Begin PBXProject section */
164 | AB6843D71A06FCE2000ADE68 /* Project object */ = {
165 | isa = PBXProject;
166 | attributes = {
167 | LastUpgradeCheck = 0720;
168 | ORGANIZATIONNAME = "Jonathan Tribouharet";
169 | TargetAttributes = {
170 | AB6843DE1A06FCE2000ADE68 = {
171 | CreatedOnToolsVersion = 6.1;
172 | };
173 | };
174 | };
175 | buildConfigurationList = AB6843DA1A06FCE2000ADE68 /* Build configuration list for PBXProject "Example" */;
176 | compatibilityVersion = "Xcode 3.2";
177 | developmentRegion = English;
178 | hasScannedForEncodings = 0;
179 | knownRegions = (
180 | en,
181 | Base,
182 | );
183 | mainGroup = AB6843D61A06FCE2000ADE68;
184 | productRefGroup = AB6843E01A06FCE2000ADE68 /* Products */;
185 | projectDirPath = "";
186 | projectRoot = "";
187 | targets = (
188 | AB6843DE1A06FCE2000ADE68 /* Example */,
189 | );
190 | };
191 | /* End PBXProject section */
192 |
193 | /* Begin PBXResourcesBuildPhase section */
194 | AB6843DD1A06FCE2000ADE68 /* Resources */ = {
195 | isa = PBXResourcesBuildPhase;
196 | buildActionMask = 2147483647;
197 | files = (
198 | AB21D7AA1B55572D006BC9D1 /* CustomViewController.xib in Resources */,
199 | AB21D7A21B55570E006BC9D1 /* BasicViewController.xib in Resources */,
200 | AB21D7B51B55694B006BC9D1 /* VerticalViewController.xib in Resources */,
201 | AB21D7AF1B555738006BC9D1 /* SelectionViewController.xib in Resources */,
202 | AB6843F31A06FCE2000ADE68 /* LaunchScreen.xib in Resources */,
203 | AB6843F01A06FCE2000ADE68 /* Images.xcassets in Resources */,
204 | );
205 | runOnlyForDeploymentPostprocessing = 0;
206 | };
207 | /* End PBXResourcesBuildPhase section */
208 |
209 | /* Begin PBXShellScriptBuildPhase section */
210 | AD2C6F32B39EFC52F28F2F53 /* Embed Pods Frameworks */ = {
211 | isa = PBXShellScriptBuildPhase;
212 | buildActionMask = 2147483647;
213 | files = (
214 | );
215 | inputPaths = (
216 | );
217 | name = "Embed Pods Frameworks";
218 | outputPaths = (
219 | );
220 | runOnlyForDeploymentPostprocessing = 0;
221 | shellPath = /bin/sh;
222 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods/Pods-frameworks.sh\"\n";
223 | showEnvVarsInLog = 0;
224 | };
225 | DAEE24CF4026663FE0755656 /* Copy Pods Resources */ = {
226 | isa = PBXShellScriptBuildPhase;
227 | buildActionMask = 2147483647;
228 | files = (
229 | );
230 | inputPaths = (
231 | );
232 | name = "Copy Pods Resources";
233 | outputPaths = (
234 | );
235 | runOnlyForDeploymentPostprocessing = 0;
236 | shellPath = /bin/sh;
237 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods/Pods-resources.sh\"\n";
238 | showEnvVarsInLog = 0;
239 | };
240 | E0E39738925637B9A2BEAEA2 /* Check Pods Manifest.lock */ = {
241 | isa = PBXShellScriptBuildPhase;
242 | buildActionMask = 2147483647;
243 | files = (
244 | );
245 | inputPaths = (
246 | );
247 | name = "Check Pods Manifest.lock";
248 | outputPaths = (
249 | );
250 | runOnlyForDeploymentPostprocessing = 0;
251 | shellPath = /bin/sh;
252 | shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n";
253 | showEnvVarsInLog = 0;
254 | };
255 | /* End PBXShellScriptBuildPhase section */
256 |
257 | /* Begin PBXSourcesBuildPhase section */
258 | AB6843DB1A06FCE2000ADE68 /* Sources */ = {
259 | isa = PBXSourcesBuildPhase;
260 | buildActionMask = 2147483647;
261 | files = (
262 | AB21D7A91B55572D006BC9D1 /* CustomViewController.m in Sources */,
263 | AB21D7A11B55570E006BC9D1 /* BasicViewController.m in Sources */,
264 | AB21D7B41B55694B006BC9D1 /* VerticalViewController.m in Sources */,
265 | AB6843E81A06FCE2000ADE68 /* AppDelegate.m in Sources */,
266 | AB6843E51A06FCE2000ADE68 /* main.m in Sources */,
267 | AB21D7AE1B555738006BC9D1 /* SelectionViewController.m in Sources */,
268 | );
269 | runOnlyForDeploymentPostprocessing = 0;
270 | };
271 | /* End PBXSourcesBuildPhase section */
272 |
273 | /* Begin PBXVariantGroup section */
274 | AB6843F11A06FCE2000ADE68 /* LaunchScreen.xib */ = {
275 | isa = PBXVariantGroup;
276 | children = (
277 | AB6843F21A06FCE2000ADE68 /* Base */,
278 | );
279 | name = LaunchScreen.xib;
280 | sourceTree = "";
281 | };
282 | /* End PBXVariantGroup section */
283 |
284 | /* Begin XCBuildConfiguration section */
285 | AB6844001A06FCE3000ADE68 /* Debug */ = {
286 | isa = XCBuildConfiguration;
287 | buildSettings = {
288 | ALWAYS_SEARCH_USER_PATHS = NO;
289 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
290 | CLANG_CXX_LIBRARY = "libc++";
291 | CLANG_ENABLE_MODULES = YES;
292 | CLANG_ENABLE_OBJC_ARC = YES;
293 | CLANG_WARN_BOOL_CONVERSION = YES;
294 | CLANG_WARN_CONSTANT_CONVERSION = YES;
295 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
296 | CLANG_WARN_EMPTY_BODY = YES;
297 | CLANG_WARN_ENUM_CONVERSION = YES;
298 | CLANG_WARN_INT_CONVERSION = YES;
299 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
300 | CLANG_WARN_UNREACHABLE_CODE = YES;
301 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
302 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
303 | COPY_PHASE_STRIP = NO;
304 | ENABLE_STRICT_OBJC_MSGSEND = YES;
305 | ENABLE_TESTABILITY = YES;
306 | GCC_C_LANGUAGE_STANDARD = gnu99;
307 | GCC_DYNAMIC_NO_PIC = NO;
308 | GCC_OPTIMIZATION_LEVEL = 0;
309 | GCC_PREPROCESSOR_DEFINITIONS = (
310 | "DEBUG=1",
311 | "$(inherited)",
312 | );
313 | GCC_SYMBOLS_PRIVATE_EXTERN = NO;
314 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
315 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
316 | GCC_WARN_UNDECLARED_SELECTOR = YES;
317 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
318 | GCC_WARN_UNUSED_FUNCTION = YES;
319 | GCC_WARN_UNUSED_VARIABLE = YES;
320 | IPHONEOS_DEPLOYMENT_TARGET = 8.1;
321 | MTL_ENABLE_DEBUG_INFO = YES;
322 | ONLY_ACTIVE_ARCH = YES;
323 | SDKROOT = iphoneos;
324 | };
325 | name = Debug;
326 | };
327 | AB6844011A06FCE3000ADE68 /* Release */ = {
328 | isa = XCBuildConfiguration;
329 | buildSettings = {
330 | ALWAYS_SEARCH_USER_PATHS = NO;
331 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
332 | CLANG_CXX_LIBRARY = "libc++";
333 | CLANG_ENABLE_MODULES = YES;
334 | CLANG_ENABLE_OBJC_ARC = YES;
335 | CLANG_WARN_BOOL_CONVERSION = YES;
336 | CLANG_WARN_CONSTANT_CONVERSION = YES;
337 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
338 | CLANG_WARN_EMPTY_BODY = YES;
339 | CLANG_WARN_ENUM_CONVERSION = YES;
340 | CLANG_WARN_INT_CONVERSION = YES;
341 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
342 | CLANG_WARN_UNREACHABLE_CODE = YES;
343 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
344 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
345 | COPY_PHASE_STRIP = YES;
346 | ENABLE_NS_ASSERTIONS = NO;
347 | ENABLE_STRICT_OBJC_MSGSEND = YES;
348 | GCC_C_LANGUAGE_STANDARD = gnu99;
349 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
350 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
351 | GCC_WARN_UNDECLARED_SELECTOR = YES;
352 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
353 | GCC_WARN_UNUSED_FUNCTION = YES;
354 | GCC_WARN_UNUSED_VARIABLE = YES;
355 | IPHONEOS_DEPLOYMENT_TARGET = 8.1;
356 | MTL_ENABLE_DEBUG_INFO = NO;
357 | SDKROOT = iphoneos;
358 | VALIDATE_PRODUCT = YES;
359 | };
360 | name = Release;
361 | };
362 | AB6844031A06FCE3000ADE68 /* Debug */ = {
363 | isa = XCBuildConfiguration;
364 | baseConfigurationReference = EA29A33B12777736F86B89BA /* Pods.debug.xcconfig */;
365 | buildSettings = {
366 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
367 | INFOPLIST_FILE = Example/Info.plist;
368 | IPHONEOS_DEPLOYMENT_TARGET = 7.1;
369 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
370 | PRODUCT_BUNDLE_IDENTIFIER = "fr.eivo.$(PRODUCT_NAME:rfc1034identifier)";
371 | PRODUCT_NAME = "$(TARGET_NAME)";
372 | };
373 | name = Debug;
374 | };
375 | AB6844041A06FCE3000ADE68 /* Release */ = {
376 | isa = XCBuildConfiguration;
377 | baseConfigurationReference = ACB1558A205302184CDC8B78 /* Pods.release.xcconfig */;
378 | buildSettings = {
379 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
380 | INFOPLIST_FILE = Example/Info.plist;
381 | IPHONEOS_DEPLOYMENT_TARGET = 7.1;
382 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
383 | PRODUCT_BUNDLE_IDENTIFIER = "fr.eivo.$(PRODUCT_NAME:rfc1034identifier)";
384 | PRODUCT_NAME = "$(TARGET_NAME)";
385 | };
386 | name = Release;
387 | };
388 | /* End XCBuildConfiguration section */
389 |
390 | /* Begin XCConfigurationList section */
391 | AB6843DA1A06FCE2000ADE68 /* Build configuration list for PBXProject "Example" */ = {
392 | isa = XCConfigurationList;
393 | buildConfigurations = (
394 | AB6844001A06FCE3000ADE68 /* Debug */,
395 | AB6844011A06FCE3000ADE68 /* Release */,
396 | );
397 | defaultConfigurationIsVisible = 0;
398 | defaultConfigurationName = Release;
399 | };
400 | AB6844021A06FCE3000ADE68 /* Build configuration list for PBXNativeTarget "Example" */ = {
401 | isa = XCConfigurationList;
402 | buildConfigurations = (
403 | AB6844031A06FCE3000ADE68 /* Debug */,
404 | AB6844041A06FCE3000ADE68 /* Release */,
405 | );
406 | defaultConfigurationIsVisible = 0;
407 | defaultConfigurationName = Release;
408 | };
409 | /* End XCConfigurationList section */
410 | };
411 | rootObject = AB6843D71A06FCE2000ADE68 /* Project object */;
412 | }
413 |
--------------------------------------------------------------------------------
/Example/Example.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Example/Example.xcodeproj/xcshareddata/xcschemes/Example.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
29 |
35 |
36 |
37 |
38 |
39 |
44 |
45 |
46 |
47 |
53 |
54 |
55 |
56 |
57 |
58 |
68 |
70 |
76 |
77 |
78 |
79 |
80 |
81 |
87 |
89 |
95 |
96 |
97 |
98 |
100 |
101 |
104 |
105 |
106 |
--------------------------------------------------------------------------------
/Example/Example.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/Example/Example/AppDelegate.h:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.h
3 | // Example
4 | //
5 | // Created by Jonathan Tribouharet.
6 | //
7 |
8 | #import
9 |
10 | @interface AppDelegate : UIResponder
11 |
12 | @property (strong, nonatomic) UIWindow *window;
13 |
14 |
15 | @end
16 |
17 |
--------------------------------------------------------------------------------
/Example/Example/AppDelegate.m:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.m
3 | // Example
4 | //
5 | // Created by Jonathan Tribouharet.
6 | //
7 |
8 | #import "AppDelegate.h"
9 |
10 | #import "BasicViewController.h"
11 | #import "CustomViewController.h"
12 | #import "SelectionViewController.h"
13 | #import "VerticalViewController.h"
14 |
15 | @interface AppDelegate ()
16 |
17 | @end
18 |
19 | @implementation AppDelegate
20 |
21 |
22 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
23 | self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
24 | [self.window makeKeyAndVisible];
25 |
26 | UITabBarController *controller = [UITabBarController new];
27 | self.window.rootViewController = controller;
28 |
29 | controller.viewControllers = @[
30 | [BasicViewController new],
31 | [CustomViewController new],
32 | [SelectionViewController new],
33 | [VerticalViewController new]
34 | ];
35 |
36 | return YES;
37 | }
38 |
39 | - (void)applicationWillResignActive:(UIApplication *)application {
40 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
41 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
42 | }
43 |
44 | - (void)applicationDidEnterBackground:(UIApplication *)application {
45 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
46 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
47 | }
48 |
49 | - (void)applicationWillEnterForeground:(UIApplication *)application {
50 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
51 | }
52 |
53 | - (void)applicationDidBecomeActive:(UIApplication *)application {
54 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
55 | }
56 |
57 | - (void)applicationWillTerminate:(UIApplication *)application {
58 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
59 | }
60 |
61 | @end
62 |
--------------------------------------------------------------------------------
/Example/Example/Base.lproj/LaunchScreen.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/Example/Example/BasicViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // BasicViewController.h
3 | // Example
4 | //
5 | // Created by Jonathan Tribouharet.
6 | //
7 |
8 | #import
9 |
10 | #import
11 |
12 | @interface BasicViewController : UIViewController
13 |
14 | @property (weak, nonatomic) IBOutlet JTCalendarMenuView *calendarMenuView;
15 | @property (weak, nonatomic) IBOutlet JTHorizontalCalendarView *calendarContentView;
16 |
17 | @property (strong, nonatomic) JTCalendarManager *calendarManager;
18 |
19 | @property (weak, nonatomic) IBOutlet NSLayoutConstraint *calendarContentViewHeight;
20 |
21 | @end
22 |
--------------------------------------------------------------------------------
/Example/Example/BasicViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // BasicViewController.m
3 | // Example
4 | //
5 | // Created by Jonathan Tribouharet.
6 | //
7 |
8 | #import "BasicViewController.h"
9 |
10 |
11 | @interface BasicViewController (){
12 | NSMutableDictionary *_eventsByDate;
13 |
14 | NSDate *_todayDate;
15 | NSDate *_minDate;
16 | NSDate *_maxDate;
17 |
18 | NSDate *_dateSelected;
19 | }
20 |
21 | @end
22 |
23 | @implementation BasicViewController
24 |
25 | - (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
26 | {
27 | self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
28 | if(!self){
29 | return nil;
30 | }
31 |
32 | self.title = @"Basic";
33 |
34 | return self;
35 | }
36 |
37 | - (void)viewDidLoad
38 | {
39 | [super viewDidLoad];
40 |
41 | _calendarManager = [JTCalendarManager new];
42 | _calendarManager.delegate = self;
43 |
44 | // Generate random events sort by date using a dateformatter for the demonstration
45 | [self createRandomEvents];
46 |
47 | // Create a min and max date for limit the calendar, optional
48 | [self createMinAndMaxDate];
49 |
50 | [_calendarManager setMenuView:_calendarMenuView];
51 | [_calendarManager setContentView:_calendarContentView];
52 | [_calendarManager setDate:_todayDate];
53 | }
54 |
55 | #pragma mark - Buttons callback
56 |
57 | - (IBAction)didGoTodayTouch
58 | {
59 | [_calendarManager setDate:_todayDate];
60 | }
61 |
62 | - (IBAction)didChangeModeTouch
63 | {
64 | _calendarManager.settings.weekModeEnabled = !_calendarManager.settings.weekModeEnabled;
65 | [_calendarManager reload];
66 |
67 | CGFloat newHeight = 300;
68 | if(_calendarManager.settings.weekModeEnabled){
69 | newHeight = 85.;
70 | }
71 |
72 | self.calendarContentViewHeight.constant = newHeight;
73 | [self.view layoutIfNeeded];
74 | }
75 |
76 | #pragma mark - CalendarManager delegate
77 |
78 | // Exemple of implementation of prepareDayView method
79 | // Used to customize the appearance of dayView
80 | - (void)calendar:(JTCalendarManager *)calendar prepareDayView:(JTCalendarDayView *)dayView
81 | {
82 | // Today
83 | if([_calendarManager.dateHelper date:[NSDate date] isTheSameDayThan:dayView.date]){
84 | dayView.circleView.hidden = NO;
85 | dayView.circleView.backgroundColor = [UIColor blueColor];
86 | dayView.dotView.backgroundColor = [UIColor whiteColor];
87 | dayView.textLabel.textColor = [UIColor whiteColor];
88 | }
89 | // Selected date
90 | else if(_dateSelected && [_calendarManager.dateHelper date:_dateSelected isTheSameDayThan:dayView.date]){
91 | dayView.circleView.hidden = NO;
92 | dayView.circleView.backgroundColor = [UIColor redColor];
93 | dayView.dotView.backgroundColor = [UIColor whiteColor];
94 | dayView.textLabel.textColor = [UIColor whiteColor];
95 | }
96 | // Other month
97 | else if(![_calendarManager.dateHelper date:_calendarContentView.date isTheSameMonthThan:dayView.date]){
98 | dayView.circleView.hidden = YES;
99 | dayView.dotView.backgroundColor = [UIColor redColor];
100 | dayView.textLabel.textColor = [UIColor lightGrayColor];
101 | }
102 | // Another day of the current month
103 | else{
104 | dayView.circleView.hidden = YES;
105 | dayView.dotView.backgroundColor = [UIColor redColor];
106 | dayView.textLabel.textColor = [UIColor blackColor];
107 | }
108 |
109 | if([self haveEventForDay:dayView.date]){
110 | dayView.dotView.hidden = NO;
111 | }
112 | else{
113 | dayView.dotView.hidden = YES;
114 | }
115 | }
116 |
117 | - (void)calendar:(JTCalendarManager *)calendar didTouchDayView:(JTCalendarDayView *)dayView
118 | {
119 | _dateSelected = dayView.date;
120 |
121 | // Animation for the circleView
122 | dayView.circleView.transform = CGAffineTransformScale(CGAffineTransformIdentity, 0.1, 0.1);
123 | [UIView transitionWithView:dayView
124 | duration:.3
125 | options:0
126 | animations:^{
127 | dayView.circleView.transform = CGAffineTransformIdentity;
128 | [_calendarManager reload];
129 | } completion:nil];
130 |
131 |
132 | // Don't change page in week mode because block the selection of days in first and last weeks of the month
133 | if(_calendarManager.settings.weekModeEnabled){
134 | return;
135 | }
136 |
137 | // Load the previous or next page if touch a day from another month
138 |
139 | if(![_calendarManager.dateHelper date:_calendarContentView.date isTheSameMonthThan:dayView.date]){
140 | if([_calendarContentView.date compare:dayView.date] == NSOrderedAscending){
141 | [_calendarContentView loadNextPageWithAnimation];
142 | }
143 | else{
144 | [_calendarContentView loadPreviousPageWithAnimation];
145 | }
146 | }
147 | }
148 |
149 | #pragma mark - CalendarManager delegate - Page mangement
150 |
151 | // Used to limit the date for the calendar, optional
152 | - (BOOL)calendar:(JTCalendarManager *)calendar canDisplayPageWithDate:(NSDate *)date
153 | {
154 | return [_calendarManager.dateHelper date:date isEqualOrAfter:_minDate andEqualOrBefore:_maxDate];
155 | }
156 |
157 | - (void)calendarDidLoadNextPage:(JTCalendarManager *)calendar
158 | {
159 | // NSLog(@"Next page loaded");
160 | }
161 |
162 | - (void)calendarDidLoadPreviousPage:(JTCalendarManager *)calendar
163 | {
164 | // NSLog(@"Previous page loaded");
165 | }
166 |
167 | #pragma mark - Fake data
168 |
169 | - (void)createMinAndMaxDate
170 | {
171 | _todayDate = [NSDate date];
172 |
173 | // Min date will be 2 month before today
174 | _minDate = [_calendarManager.dateHelper addToDate:_todayDate months:-2];
175 |
176 | // Max date will be 2 month after today
177 | _maxDate = [_calendarManager.dateHelper addToDate:_todayDate months:2];
178 | }
179 |
180 | // Used only to have a key for _eventsByDate
181 | - (NSDateFormatter *)dateFormatter
182 | {
183 | static NSDateFormatter *dateFormatter;
184 | if(!dateFormatter){
185 | dateFormatter = [NSDateFormatter new];
186 | dateFormatter.dateFormat = @"dd-MM-yyyy";
187 | }
188 |
189 | return dateFormatter;
190 | }
191 |
192 | - (BOOL)haveEventForDay:(NSDate *)date
193 | {
194 | NSString *key = [[self dateFormatter] stringFromDate:date];
195 |
196 | if(_eventsByDate[key] && [_eventsByDate[key] count] > 0){
197 | return YES;
198 | }
199 |
200 | return NO;
201 |
202 | }
203 |
204 | - (void)createRandomEvents
205 | {
206 | _eventsByDate = [NSMutableDictionary new];
207 |
208 | for(int i = 0; i < 30; ++i){
209 | // Generate 30 random dates between now and 60 days later
210 | NSDate *randomDate = [NSDate dateWithTimeInterval:(rand() % (3600 * 24 * 60)) sinceDate:[NSDate date]];
211 |
212 | // Use the date as key for eventsByDate
213 | NSString *key = [[self dateFormatter] stringFromDate:randomDate];
214 |
215 | if(!_eventsByDate[key]){
216 | _eventsByDate[key] = [NSMutableArray new];
217 | }
218 |
219 | [_eventsByDate[key] addObject:randomDate];
220 | }
221 | }
222 |
223 | @end
224 |
--------------------------------------------------------------------------------
/Example/Example/BasicViewController.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
48 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
--------------------------------------------------------------------------------
/Example/Example/CustomViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // CustomViewController.h
3 | // Example
4 | //
5 | // Created by Jonathan Tribouharet.
6 | //
7 |
8 | #import
9 |
10 | #import
11 |
12 | @interface CustomViewController : UIViewController
13 |
14 | @property (weak, nonatomic) IBOutlet JTCalendarMenuView *calendarMenuView;
15 | @property (weak, nonatomic) IBOutlet JTHorizontalCalendarView *calendarContentView;
16 |
17 | @property (strong, nonatomic) JTCalendarManager *calendarManager;
18 |
19 | @end
20 |
--------------------------------------------------------------------------------
/Example/Example/CustomViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // CustomViewController.m
3 | // Example
4 | //
5 | // Created by Jonathan Tribouharet.
6 | //
7 |
8 | #import "CustomViewController.h"
9 |
10 | @interface CustomViewController (){
11 | NSMutableDictionary *_eventsByDate;
12 |
13 | NSDate *_dateSelected;
14 | }
15 |
16 | @end
17 |
18 | @implementation CustomViewController
19 |
20 | - (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
21 | {
22 | self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
23 | if(!self){
24 | return nil;
25 | }
26 |
27 | self.title = @"Custom";
28 |
29 | return self;
30 | }
31 |
32 | - (void)viewDidLoad
33 | {
34 | [super viewDidLoad];
35 |
36 | _calendarManager = [[JTCalendarManager alloc] initWithLocale:[NSLocale localeWithLocaleIdentifier:@"fr_FR"] andTimeZone:[NSTimeZone localTimeZone]];
37 | _calendarManager.delegate = self;
38 |
39 | // Generate random events sort by date using a dateformatter for the demonstration
40 | [self createRandomEvents];
41 |
42 | _calendarMenuView.contentRatio = .75;
43 | _calendarManager.settings.weekDayFormat = JTCalendarWeekDayFormatSingle;
44 |
45 | [_calendarManager setMenuView:_calendarMenuView];
46 | [_calendarManager setContentView:_calendarContentView];
47 | [_calendarManager setDate:[NSDate date]];
48 | }
49 |
50 | #pragma mark - CalendarManager delegate
51 |
52 | // Exemple of implementation of prepareDayView method
53 | // Used to customize the appearance of dayView
54 | - (void)calendar:(JTCalendarManager *)calendar prepareDayView:(JTCalendarDayView *)dayView
55 | {
56 | dayView.hidden = NO;
57 |
58 | // Other month
59 | if([dayView isFromAnotherMonth]){
60 | dayView.hidden = YES;
61 | }
62 | // Today
63 | else if([_calendarManager.dateHelper date:[NSDate date] isTheSameDayThan:dayView.date]){
64 | dayView.circleView.hidden = NO;
65 | dayView.circleView.backgroundColor = [UIColor blueColor];
66 | dayView.dotView.backgroundColor = [UIColor whiteColor];
67 | dayView.textLabel.textColor = [UIColor whiteColor];
68 | }
69 | // Selected date
70 | else if(_dateSelected && [_calendarManager.dateHelper date:_dateSelected isTheSameDayThan:dayView.date]){
71 | dayView.circleView.hidden = NO;
72 | dayView.circleView.backgroundColor = [UIColor redColor];
73 | dayView.dotView.backgroundColor = [UIColor whiteColor];
74 | dayView.textLabel.textColor = [UIColor whiteColor];
75 | }
76 | // Another day of the current month
77 | else{
78 | dayView.circleView.hidden = YES;
79 | dayView.dotView.backgroundColor = [UIColor redColor];
80 | dayView.textLabel.textColor = [UIColor blackColor];
81 | }
82 |
83 | if([self haveEventForDay:dayView.date]){
84 | dayView.dotView.hidden = NO;
85 | }
86 | else{
87 | dayView.dotView.hidden = YES;
88 | }
89 | }
90 |
91 | - (void)calendar:(JTCalendarManager *)calendar didTouchDayView:(JTCalendarDayView *)dayView
92 | {
93 | _dateSelected = dayView.date;
94 |
95 | // Animation for the circleView
96 | dayView.circleView.transform = CGAffineTransformScale(CGAffineTransformIdentity, 0.1, 0.1);
97 | [UIView transitionWithView:dayView
98 | duration:.3
99 | options:0
100 | animations:^{
101 | dayView.circleView.transform = CGAffineTransformIdentity;
102 | [_calendarManager reload];
103 | } completion:nil];
104 |
105 |
106 | // Don't change page in week mode because block the selection of days in first and last weeks of the month
107 | if(_calendarManager.settings.weekModeEnabled){
108 | return;
109 | }
110 |
111 | // Load the previous or next page if touch a day from another month
112 |
113 | if(![_calendarManager.dateHelper date:_calendarContentView.date isTheSameMonthThan:dayView.date]){
114 | if([_calendarContentView.date compare:dayView.date] == NSOrderedAscending){
115 | [_calendarContentView loadNextPageWithAnimation];
116 | }
117 | else{
118 | [_calendarContentView loadPreviousPageWithAnimation];
119 | }
120 | }
121 | }
122 |
123 | #pragma mark - Views customization
124 |
125 | - (UIView *)calendarBuildMenuItemView:(JTCalendarManager *)calendar
126 | {
127 | UILabel *label = [UILabel new];
128 |
129 | label.textAlignment = NSTextAlignmentCenter;
130 | label.font = [UIFont fontWithName:@"Avenir-Medium" size:16];
131 |
132 | return label;
133 | }
134 |
135 | - (void)calendar:(JTCalendarManager *)calendar prepareMenuItemView:(UILabel *)menuItemView date:(NSDate *)date
136 | {
137 | static NSDateFormatter *dateFormatter;
138 | if(!dateFormatter){
139 | dateFormatter = [NSDateFormatter new];
140 | dateFormatter.dateFormat = @"MMMM yyyy";
141 |
142 | dateFormatter.locale = _calendarManager.dateHelper.calendar.locale;
143 | dateFormatter.timeZone = _calendarManager.dateHelper.calendar.timeZone;
144 | }
145 |
146 | menuItemView.text = [dateFormatter stringFromDate:date];
147 | }
148 |
149 | - (UIView *)calendarBuildWeekDayView:(JTCalendarManager *)calendar
150 | {
151 | JTCalendarWeekDayView *view = [JTCalendarWeekDayView new];
152 |
153 | for(UILabel *label in view.dayViews){
154 | label.textColor = [UIColor blackColor];
155 | label.font = [UIFont fontWithName:@"Avenir-Light" size:14];
156 | }
157 |
158 | return view;
159 | }
160 |
161 | - (UIView *)calendarBuildDayView:(JTCalendarManager *)calendar
162 | {
163 | JTCalendarDayView *view = [JTCalendarDayView new];
164 |
165 | view.textLabel.font = [UIFont fontWithName:@"Avenir-Light" size:13];
166 |
167 | view.circleRatio = .8;
168 | view.dotRatio = 1. / .9;
169 |
170 | return view;
171 | }
172 |
173 | #pragma mark - Fake data
174 |
175 | // Used only to have a key for _eventsByDate
176 | - (NSDateFormatter *)dateFormatter
177 | {
178 | static NSDateFormatter *dateFormatter;
179 | if(!dateFormatter){
180 | dateFormatter = [NSDateFormatter new];
181 | dateFormatter.dateFormat = @"dd-MM-yyyy";
182 | }
183 |
184 | return dateFormatter;
185 | }
186 |
187 | - (BOOL)haveEventForDay:(NSDate *)date
188 | {
189 | NSString *key = [[self dateFormatter] stringFromDate:date];
190 |
191 | if(_eventsByDate[key] && [_eventsByDate[key] count] > 0){
192 | return YES;
193 | }
194 |
195 | return NO;
196 |
197 | }
198 |
199 | - (void)createRandomEvents
200 | {
201 | _eventsByDate = [NSMutableDictionary new];
202 |
203 | for(int i = 0; i < 30; ++i){
204 | // Generate 30 random dates between now and 60 days later
205 | NSDate *randomDate = [NSDate dateWithTimeInterval:(rand() % (3600 * 24 * 60)) sinceDate:[NSDate date]];
206 |
207 | // Use the date as key for eventsByDate
208 | NSString *key = [[self dateFormatter] stringFromDate:randomDate];
209 |
210 | if(!_eventsByDate[key]){
211 | _eventsByDate[key] = [NSMutableArray new];
212 | }
213 |
214 | [_eventsByDate[key] addObject:randomDate];
215 | }
216 | }
217 |
218 | @end
219 |
--------------------------------------------------------------------------------
/Example/Example/CustomViewController.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/Example/Example/Images.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "29x29",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "29x29",
11 | "scale" : "3x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "40x40",
16 | "scale" : "2x"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "size" : "40x40",
21 | "scale" : "3x"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "size" : "60x60",
26 | "scale" : "2x"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "size" : "60x60",
31 | "scale" : "3x"
32 | }
33 | ],
34 | "info" : {
35 | "version" : 1,
36 | "author" : "xcode"
37 | }
38 | }
--------------------------------------------------------------------------------
/Example/Example/Images.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/Example/Example/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 | LSRequiresIPhoneOS
24 |
25 | UILaunchStoryboardName
26 | LaunchScreen
27 | UIRequiredDeviceCapabilities
28 |
29 | armv7
30 |
31 | UISupportedInterfaceOrientations
32 |
33 | UIInterfaceOrientationPortrait
34 | UIInterfaceOrientationLandscapeLeft
35 | UIInterfaceOrientationLandscapeRight
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/Example/Example/SelectionViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // SelectionViewController.h
3 | // Example
4 | //
5 | // Created by Jonathan Tribouharet.
6 | //
7 |
8 | #import
9 |
10 | #import
11 |
12 | @interface SelectionViewController : UIViewController
13 |
14 | @property (weak, nonatomic) IBOutlet JTCalendarMenuView *calendarMenuView;
15 | @property (weak, nonatomic) IBOutlet JTHorizontalCalendarView *calendarContentView;
16 |
17 | @property (strong, nonatomic) JTCalendarManager *calendarManager;
18 |
19 | @end
20 |
--------------------------------------------------------------------------------
/Example/Example/SelectionViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // SelectionViewController.m
3 | // Example
4 | //
5 | // Created by Jonathan Tribouharet.
6 | //
7 |
8 | #import "SelectionViewController.h"
9 |
10 | @interface SelectionViewController (){
11 | NSMutableDictionary *_eventsByDate;
12 |
13 | NSMutableArray *_datesSelected;
14 | BOOL _selectionMode;
15 | }
16 |
17 | @end
18 |
19 | @implementation SelectionViewController
20 |
21 | - (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
22 | {
23 | self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
24 | if(!self){
25 | return nil;
26 | }
27 |
28 | self.title = @"Selection";
29 |
30 | return self;
31 | }
32 |
33 | - (void)viewDidLoad
34 | {
35 | [super viewDidLoad];
36 |
37 | _calendarManager = [JTCalendarManager new];
38 | _calendarManager.delegate = self;
39 |
40 | // Generate random events sort by date using a dateformatter for the demonstration
41 | [self createRandomEvents];
42 |
43 | [_calendarManager setMenuView:_calendarMenuView];
44 | [_calendarManager setContentView:_calendarContentView];
45 | [_calendarManager setDate:[NSDate date]];
46 |
47 | _datesSelected = [NSMutableArray new];
48 | _selectionMode = NO;
49 | }
50 |
51 | #pragma mark - Buttons callback
52 |
53 | - (IBAction)didSelectionModeTouch
54 | {
55 | _selectionMode = !_selectionMode;
56 |
57 | if(_selectionMode){
58 | [_datesSelected removeAllObjects];
59 | [_calendarManager reload];
60 | }
61 | }
62 |
63 | #pragma mark - CalendarManager delegate
64 |
65 | // Exemple of implementation of prepareDayView method
66 | // Used to customize the appearance of dayView
67 | - (void)calendar:(JTCalendarManager *)calendar prepareDayView:(JTCalendarDayView *)dayView
68 | {
69 | // Today
70 | if([_calendarManager.dateHelper date:[NSDate date] isTheSameDayThan:dayView.date]){
71 | dayView.circleView.hidden = NO;
72 | dayView.circleView.backgroundColor = [UIColor blueColor];
73 | dayView.dotView.backgroundColor = [UIColor whiteColor];
74 | dayView.textLabel.textColor = [UIColor whiteColor];
75 | }
76 | // Selected date
77 | else if([self isInDatesSelected:dayView.date]){
78 | dayView.circleView.hidden = NO;
79 | dayView.circleView.backgroundColor = [UIColor redColor];
80 | dayView.dotView.backgroundColor = [UIColor whiteColor];
81 | dayView.textLabel.textColor = [UIColor whiteColor];
82 | }
83 | // Other month
84 | else if(![_calendarManager.dateHelper date:_calendarContentView.date isTheSameMonthThan:dayView.date]){
85 | dayView.circleView.hidden = YES;
86 | dayView.dotView.backgroundColor = [UIColor redColor];
87 | dayView.textLabel.textColor = [UIColor lightGrayColor];
88 | }
89 | // Another day of the current month
90 | else{
91 | dayView.circleView.hidden = YES;
92 | dayView.dotView.backgroundColor = [UIColor redColor];
93 | dayView.textLabel.textColor = [UIColor blackColor];
94 | }
95 |
96 | if([self haveEventForDay:dayView.date]){
97 | dayView.dotView.hidden = NO;
98 | }
99 | else{
100 | dayView.dotView.hidden = YES;
101 | }
102 | }
103 |
104 | - (void)calendar:(JTCalendarManager *)calendar didTouchDayView:(JTCalendarDayView *)dayView
105 | {
106 | if(_selectionMode && _datesSelected.count == 1 && ![_calendarManager.dateHelper date:[_datesSelected firstObject] isTheSameDayThan:dayView.date]){
107 | [_datesSelected addObject:dayView.date];
108 | [self selectDates];
109 | _selectionMode = NO;
110 | [_calendarManager reload];
111 | return;
112 | }
113 |
114 |
115 | if([self isInDatesSelected:dayView.date]){
116 | [_datesSelected removeObject:dayView.date];
117 |
118 | [UIView transitionWithView:dayView
119 | duration:.3
120 | options:0
121 | animations:^{
122 | [_calendarManager reload];
123 | dayView.circleView.transform = CGAffineTransformScale(CGAffineTransformIdentity, 0.1, 0.1);
124 | } completion:nil];
125 | }
126 | else{
127 | [_datesSelected addObject:dayView.date];
128 |
129 | dayView.circleView.transform = CGAffineTransformScale(CGAffineTransformIdentity, 0.1, 0.1);
130 | [UIView transitionWithView:dayView
131 | duration:.3
132 | options:0
133 | animations:^{
134 | [_calendarManager reload];
135 | dayView.circleView.transform = CGAffineTransformIdentity;
136 | } completion:nil];
137 | }
138 |
139 | if(_selectionMode) {
140 | return;
141 | }
142 |
143 | // Don't change page in week mode because block the selection of days in first and last weeks of the month
144 | if(_calendarManager.settings.weekModeEnabled){
145 | return;
146 | }
147 |
148 | // Load the previous or next page if touch a day from another month
149 |
150 | if(![_calendarManager.dateHelper date:_calendarContentView.date isTheSameMonthThan:dayView.date]){
151 | if([_calendarContentView.date compare:dayView.date] == NSOrderedAscending){
152 | [_calendarContentView loadNextPageWithAnimation];
153 | }
154 | else{
155 | [_calendarContentView loadPreviousPageWithAnimation];
156 | }
157 | }
158 | }
159 |
160 | #pragma mark - Date selection
161 |
162 | - (BOOL)isInDatesSelected:(NSDate *)date
163 | {
164 | for(NSDate *dateSelected in _datesSelected){
165 | if([_calendarManager.dateHelper date:dateSelected isTheSameDayThan:date]){
166 | return YES;
167 | }
168 | }
169 |
170 | return NO;
171 | }
172 |
173 | - (void)selectDates
174 | {
175 | NSDate * startDate = [_datesSelected firstObject];
176 | NSDate * endDate = [_datesSelected lastObject];
177 |
178 | if([_calendarManager.dateHelper date:startDate isEqualOrAfter:endDate]){
179 | NSDate *nextDate = endDate;
180 | while ([nextDate compare:startDate] == NSOrderedAscending) {
181 | [_datesSelected addObject:nextDate];
182 | nextDate = [_calendarManager.dateHelper addToDate:nextDate days:1];
183 | }
184 | }
185 | else {
186 | NSDate *nextDate = startDate;
187 | while ([nextDate compare:endDate] == NSOrderedAscending) {
188 | [_datesSelected addObject:nextDate];
189 | nextDate = [_calendarManager.dateHelper addToDate:nextDate days:1];
190 | }
191 | }
192 | }
193 |
194 | #pragma mark - Fake data
195 |
196 | // Used only to have a key for _eventsByDate
197 | - (NSDateFormatter *)dateFormatter
198 | {
199 | static NSDateFormatter *dateFormatter;
200 | if(!dateFormatter){
201 | dateFormatter = [NSDateFormatter new];
202 | dateFormatter.dateFormat = @"dd-MM-yyyy";
203 | }
204 |
205 | return dateFormatter;
206 | }
207 |
208 | - (BOOL)haveEventForDay:(NSDate *)date
209 | {
210 | NSString *key = [[self dateFormatter] stringFromDate:date];
211 |
212 | if(_eventsByDate[key] && [_eventsByDate[key] count] > 0){
213 | return YES;
214 | }
215 |
216 | return NO;
217 |
218 | }
219 |
220 | - (void)createRandomEvents
221 | {
222 | _eventsByDate = [NSMutableDictionary new];
223 |
224 | for(int i = 0; i < 30; ++i){
225 | // Generate 30 random dates between now and 60 days later
226 | NSDate *randomDate = [NSDate dateWithTimeInterval:(rand() % (3600 * 24 * 60)) sinceDate:[NSDate date]];
227 |
228 | // Use the date as key for eventsByDate
229 | NSString *key = [[self dateFormatter] stringFromDate:randomDate];
230 |
231 | if(!_eventsByDate[key]){
232 | _eventsByDate[key] = [NSMutableArray new];
233 | }
234 |
235 | [_eventsByDate[key] addObject:randomDate];
236 | }
237 | }
238 |
239 | @end
240 |
--------------------------------------------------------------------------------
/Example/Example/SelectionViewController.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
--------------------------------------------------------------------------------
/Example/Example/VerticalViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // VerticalViewController.h
3 | // Example
4 | //
5 | // Created by Jonathan Tribouharet.
6 | //
7 |
8 | #import
9 |
10 | #import
11 |
12 | @interface VerticalViewController : UIViewController
13 |
14 | @property (weak, nonatomic) IBOutlet JTCalendarMenuView *calendarMenuView;
15 | @property (weak, nonatomic) IBOutlet JTCalendarWeekDayView *weekDayView;
16 | @property (weak, nonatomic) IBOutlet JTVerticalCalendarView *calendarContentView;
17 |
18 | @property (strong, nonatomic) JTCalendarManager *calendarManager;
19 |
20 | @end
21 |
--------------------------------------------------------------------------------
/Example/Example/VerticalViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // VerticalViewController.m
3 | // Example
4 | //
5 | // Created by Jonathan Tribouharet.
6 | //
7 |
8 | #import "VerticalViewController.h"
9 |
10 | @interface VerticalViewController (){
11 | NSMutableDictionary *_eventsByDate;
12 |
13 | NSDate *_dateSelected;
14 | }
15 |
16 | @end
17 |
18 | @implementation VerticalViewController
19 |
20 | - (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
21 | {
22 | self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
23 | if(!self){
24 | return nil;
25 | }
26 |
27 | self.title = @"Vertical";
28 |
29 | return self;
30 | }
31 |
32 | - (void)viewDidLoad
33 | {
34 | [super viewDidLoad];
35 |
36 | _calendarManager = [JTCalendarManager new];
37 | _calendarManager.delegate = self;
38 |
39 | _calendarManager.settings.pageViewHaveWeekDaysView = NO;
40 | _calendarManager.settings.pageViewNumberOfWeeks = 0; // Automatic
41 |
42 | _weekDayView.manager = _calendarManager;
43 | [_weekDayView reload];
44 |
45 | // Generate random events sort by date using a dateformatter for the demonstration
46 | [self createRandomEvents];
47 |
48 | [_calendarManager setMenuView:_calendarMenuView];
49 | [_calendarManager setContentView:_calendarContentView];
50 | [_calendarManager setDate:[NSDate date]];
51 |
52 | _calendarMenuView.scrollView.scrollEnabled = NO; // Scroll not supported with JTVerticalCalendarView
53 | }
54 |
55 | #pragma mark - CalendarManager delegate
56 |
57 | // Exemple of implementation of prepareDayView method
58 | // Used to customize the appearance of dayView
59 | - (void)calendar:(JTCalendarManager *)calendar prepareDayView:(JTCalendarDayView *)dayView
60 | {
61 | dayView.hidden = NO;
62 |
63 | // Hide if from another month
64 | if([dayView isFromAnotherMonth]){
65 | dayView.hidden = YES;
66 | }
67 | // Today
68 | else if([_calendarManager.dateHelper date:[NSDate date] isTheSameDayThan:dayView.date]){
69 | dayView.circleView.hidden = NO;
70 | dayView.circleView.backgroundColor = [UIColor blueColor];
71 | dayView.dotView.backgroundColor = [UIColor whiteColor];
72 | dayView.textLabel.textColor = [UIColor whiteColor];
73 | }
74 | // Selected date
75 | else if(_dateSelected && [_calendarManager.dateHelper date:_dateSelected isTheSameDayThan:dayView.date]){
76 | dayView.circleView.hidden = NO;
77 | dayView.circleView.backgroundColor = [UIColor redColor];
78 | dayView.dotView.backgroundColor = [UIColor whiteColor];
79 | dayView.textLabel.textColor = [UIColor whiteColor];
80 | }
81 | // Other month
82 | else if(![_calendarManager.dateHelper date:_calendarContentView.date isTheSameMonthThan:dayView.date]){
83 | dayView.circleView.hidden = YES;
84 | dayView.dotView.backgroundColor = [UIColor redColor];
85 | dayView.textLabel.textColor = [UIColor lightGrayColor];
86 | }
87 | // Another day of the current month
88 | else{
89 | dayView.circleView.hidden = YES;
90 | dayView.dotView.backgroundColor = [UIColor redColor];
91 | dayView.textLabel.textColor = [UIColor blackColor];
92 | }
93 |
94 | if([self haveEventForDay:dayView.date]){
95 | dayView.dotView.hidden = NO;
96 | }
97 | else{
98 | dayView.dotView.hidden = YES;
99 | }
100 | }
101 |
102 | - (void)calendar:(JTCalendarManager *)calendar didTouchDayView:(JTCalendarDayView *)dayView
103 | {
104 | _dateSelected = dayView.date;
105 |
106 | // Animation for the circleView
107 | dayView.circleView.transform = CGAffineTransformScale(CGAffineTransformIdentity, 0.1, 0.1);
108 | [UIView transitionWithView:dayView
109 | duration:.3
110 | options:0
111 | animations:^{
112 | dayView.circleView.transform = CGAffineTransformIdentity;
113 | [_calendarManager reload];
114 | } completion:nil];
115 |
116 |
117 | // Don't change page in week mode because block the selection of days in first and last weeks of the month
118 | if(_calendarManager.settings.weekModeEnabled){
119 | return;
120 | }
121 |
122 | // Load the previous or next page if touch a day from another month
123 |
124 | if(![_calendarManager.dateHelper date:_calendarContentView.date isTheSameMonthThan:dayView.date]){
125 | if([_calendarContentView.date compare:dayView.date] == NSOrderedAscending){
126 | [_calendarContentView loadNextPageWithAnimation];
127 | }
128 | else{
129 | [_calendarContentView loadPreviousPageWithAnimation];
130 | }
131 | }
132 | }
133 |
134 | #pragma mark - Fake data
135 |
136 | // Used only to have a key for _eventsByDate
137 | - (NSDateFormatter *)dateFormatter
138 | {
139 | static NSDateFormatter *dateFormatter;
140 | if(!dateFormatter){
141 | dateFormatter = [NSDateFormatter new];
142 | dateFormatter.dateFormat = @"dd-MM-yyyy";
143 | }
144 |
145 | return dateFormatter;
146 | }
147 |
148 | - (BOOL)haveEventForDay:(NSDate *)date
149 | {
150 | NSString *key = [[self dateFormatter] stringFromDate:date];
151 |
152 | if(_eventsByDate[key] && [_eventsByDate[key] count] > 0){
153 | return YES;
154 | }
155 |
156 | return NO;
157 |
158 | }
159 |
160 | - (void)createRandomEvents
161 | {
162 | _eventsByDate = [NSMutableDictionary new];
163 |
164 | for(int i = 0; i < 30; ++i){
165 | // Generate 30 random dates between now and 60 days later
166 | NSDate *randomDate = [NSDate dateWithTimeInterval:(rand() % (3600 * 24 * 60)) sinceDate:[NSDate date]];
167 |
168 | // Use the date as key for eventsByDate
169 | NSString *key = [[self dateFormatter] stringFromDate:randomDate];
170 |
171 | if(!_eventsByDate[key]){
172 | _eventsByDate[key] = [NSMutableArray new];
173 | }
174 |
175 | [_eventsByDate[key] addObject:randomDate];
176 | }
177 | }
178 |
179 | @end
180 |
--------------------------------------------------------------------------------
/Example/Example/VerticalViewController.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
--------------------------------------------------------------------------------
/Example/Example/main.m:
--------------------------------------------------------------------------------
1 | //
2 | // main.m
3 | // Example
4 | //
5 | // Created by Jonathan Tribouharet.
6 | //
7 |
8 | #import
9 | #import "AppDelegate.h"
10 |
11 | int main(int argc, char * argv[]) {
12 | @autoreleasepool {
13 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Example/Podfile:
--------------------------------------------------------------------------------
1 | source 'https://github.com/CocoaPods/Specs.git'
2 |
3 | platform :ios, '7.0'
4 |
5 | pod 'JTCalendar', path: '..'
6 |
--------------------------------------------------------------------------------
/Example/Podfile.lock:
--------------------------------------------------------------------------------
1 | PODS:
2 | - JTCalendar (2.1.9)
3 |
4 | DEPENDENCIES:
5 | - JTCalendar (from `..`)
6 |
7 | EXTERNAL SOURCES:
8 | JTCalendar:
9 | :path: ..
10 |
11 | SPEC CHECKSUMS:
12 | JTCalendar: beb2f4c1b639bf6880f680b4858227acf83a049c
13 |
14 | COCOAPODS: 0.39.0
15 |
--------------------------------------------------------------------------------
/Example/Pods/Headers/Private/JTCalendar/JTCalendar.h:
--------------------------------------------------------------------------------
1 | ../../../../../JTCalendar/JTCalendar.h
--------------------------------------------------------------------------------
/Example/Pods/Headers/Private/JTCalendar/JTCalendarDay.h:
--------------------------------------------------------------------------------
1 | ../../../../../JTCalendar/Protocols/JTCalendarDay.h
--------------------------------------------------------------------------------
/Example/Pods/Headers/Private/JTCalendar/JTCalendarDayView.h:
--------------------------------------------------------------------------------
1 | ../../../../../JTCalendar/Views/JTCalendarDayView.h
--------------------------------------------------------------------------------
/Example/Pods/Headers/Private/JTCalendar/JTCalendarDelegate.h:
--------------------------------------------------------------------------------
1 | ../../../../../JTCalendar/JTCalendarDelegate.h
--------------------------------------------------------------------------------
/Example/Pods/Headers/Private/JTCalendar/JTCalendarDelegateManager.h:
--------------------------------------------------------------------------------
1 | ../../../../../JTCalendar/Managers/JTCalendarDelegateManager.h
--------------------------------------------------------------------------------
/Example/Pods/Headers/Private/JTCalendar/JTCalendarManager.h:
--------------------------------------------------------------------------------
1 | ../../../../../JTCalendar/JTCalendarManager.h
--------------------------------------------------------------------------------
/Example/Pods/Headers/Private/JTCalendar/JTCalendarMenuView.h:
--------------------------------------------------------------------------------
1 | ../../../../../JTCalendar/Views/JTCalendarMenuView.h
--------------------------------------------------------------------------------
/Example/Pods/Headers/Private/JTCalendar/JTCalendarPage.h:
--------------------------------------------------------------------------------
1 | ../../../../../JTCalendar/Protocols/JTCalendarPage.h
--------------------------------------------------------------------------------
/Example/Pods/Headers/Private/JTCalendar/JTCalendarPageView.h:
--------------------------------------------------------------------------------
1 | ../../../../../JTCalendar/Views/JTCalendarPageView.h
--------------------------------------------------------------------------------
/Example/Pods/Headers/Private/JTCalendar/JTCalendarScrollManager.h:
--------------------------------------------------------------------------------
1 | ../../../../../JTCalendar/Managers/JTCalendarScrollManager.h
--------------------------------------------------------------------------------
/Example/Pods/Headers/Private/JTCalendar/JTCalendarSettings.h:
--------------------------------------------------------------------------------
1 | ../../../../../JTCalendar/JTCalendarSettings.h
--------------------------------------------------------------------------------
/Example/Pods/Headers/Private/JTCalendar/JTCalendarWeek.h:
--------------------------------------------------------------------------------
1 | ../../../../../JTCalendar/Protocols/JTCalendarWeek.h
--------------------------------------------------------------------------------
/Example/Pods/Headers/Private/JTCalendar/JTCalendarWeekDay.h:
--------------------------------------------------------------------------------
1 | ../../../../../JTCalendar/Protocols/JTCalendarWeekDay.h
--------------------------------------------------------------------------------
/Example/Pods/Headers/Private/JTCalendar/JTCalendarWeekDayView.h:
--------------------------------------------------------------------------------
1 | ../../../../../JTCalendar/Views/JTCalendarWeekDayView.h
--------------------------------------------------------------------------------
/Example/Pods/Headers/Private/JTCalendar/JTCalendarWeekView.h:
--------------------------------------------------------------------------------
1 | ../../../../../JTCalendar/Views/JTCalendarWeekView.h
--------------------------------------------------------------------------------
/Example/Pods/Headers/Private/JTCalendar/JTContent.h:
--------------------------------------------------------------------------------
1 | ../../../../../JTCalendar/Protocols/JTContent.h
--------------------------------------------------------------------------------
/Example/Pods/Headers/Private/JTCalendar/JTDateHelper.h:
--------------------------------------------------------------------------------
1 | ../../../../../JTCalendar/JTDateHelper.h
--------------------------------------------------------------------------------
/Example/Pods/Headers/Private/JTCalendar/JTHorizontalCalendarView.h:
--------------------------------------------------------------------------------
1 | ../../../../../JTCalendar/Views/JTHorizontalCalendarView.h
--------------------------------------------------------------------------------
/Example/Pods/Headers/Private/JTCalendar/JTMenu.h:
--------------------------------------------------------------------------------
1 | ../../../../../JTCalendar/Protocols/JTMenu.h
--------------------------------------------------------------------------------
/Example/Pods/Headers/Private/JTCalendar/JTVerticalCalendarView.h:
--------------------------------------------------------------------------------
1 | ../../../../../JTCalendar/Views/JTVerticalCalendarView.h
--------------------------------------------------------------------------------
/Example/Pods/Headers/Public/JTCalendar/JTCalendar.h:
--------------------------------------------------------------------------------
1 | ../../../../../JTCalendar/JTCalendar.h
--------------------------------------------------------------------------------
/Example/Pods/Headers/Public/JTCalendar/JTCalendarDay.h:
--------------------------------------------------------------------------------
1 | ../../../../../JTCalendar/Protocols/JTCalendarDay.h
--------------------------------------------------------------------------------
/Example/Pods/Headers/Public/JTCalendar/JTCalendarDayView.h:
--------------------------------------------------------------------------------
1 | ../../../../../JTCalendar/Views/JTCalendarDayView.h
--------------------------------------------------------------------------------
/Example/Pods/Headers/Public/JTCalendar/JTCalendarDelegate.h:
--------------------------------------------------------------------------------
1 | ../../../../../JTCalendar/JTCalendarDelegate.h
--------------------------------------------------------------------------------
/Example/Pods/Headers/Public/JTCalendar/JTCalendarDelegateManager.h:
--------------------------------------------------------------------------------
1 | ../../../../../JTCalendar/Managers/JTCalendarDelegateManager.h
--------------------------------------------------------------------------------
/Example/Pods/Headers/Public/JTCalendar/JTCalendarManager.h:
--------------------------------------------------------------------------------
1 | ../../../../../JTCalendar/JTCalendarManager.h
--------------------------------------------------------------------------------
/Example/Pods/Headers/Public/JTCalendar/JTCalendarMenuView.h:
--------------------------------------------------------------------------------
1 | ../../../../../JTCalendar/Views/JTCalendarMenuView.h
--------------------------------------------------------------------------------
/Example/Pods/Headers/Public/JTCalendar/JTCalendarPage.h:
--------------------------------------------------------------------------------
1 | ../../../../../JTCalendar/Protocols/JTCalendarPage.h
--------------------------------------------------------------------------------
/Example/Pods/Headers/Public/JTCalendar/JTCalendarPageView.h:
--------------------------------------------------------------------------------
1 | ../../../../../JTCalendar/Views/JTCalendarPageView.h
--------------------------------------------------------------------------------
/Example/Pods/Headers/Public/JTCalendar/JTCalendarScrollManager.h:
--------------------------------------------------------------------------------
1 | ../../../../../JTCalendar/Managers/JTCalendarScrollManager.h
--------------------------------------------------------------------------------
/Example/Pods/Headers/Public/JTCalendar/JTCalendarSettings.h:
--------------------------------------------------------------------------------
1 | ../../../../../JTCalendar/JTCalendarSettings.h
--------------------------------------------------------------------------------
/Example/Pods/Headers/Public/JTCalendar/JTCalendarWeek.h:
--------------------------------------------------------------------------------
1 | ../../../../../JTCalendar/Protocols/JTCalendarWeek.h
--------------------------------------------------------------------------------
/Example/Pods/Headers/Public/JTCalendar/JTCalendarWeekDay.h:
--------------------------------------------------------------------------------
1 | ../../../../../JTCalendar/Protocols/JTCalendarWeekDay.h
--------------------------------------------------------------------------------
/Example/Pods/Headers/Public/JTCalendar/JTCalendarWeekDayView.h:
--------------------------------------------------------------------------------
1 | ../../../../../JTCalendar/Views/JTCalendarWeekDayView.h
--------------------------------------------------------------------------------
/Example/Pods/Headers/Public/JTCalendar/JTCalendarWeekView.h:
--------------------------------------------------------------------------------
1 | ../../../../../JTCalendar/Views/JTCalendarWeekView.h
--------------------------------------------------------------------------------
/Example/Pods/Headers/Public/JTCalendar/JTContent.h:
--------------------------------------------------------------------------------
1 | ../../../../../JTCalendar/Protocols/JTContent.h
--------------------------------------------------------------------------------
/Example/Pods/Headers/Public/JTCalendar/JTDateHelper.h:
--------------------------------------------------------------------------------
1 | ../../../../../JTCalendar/JTDateHelper.h
--------------------------------------------------------------------------------
/Example/Pods/Headers/Public/JTCalendar/JTHorizontalCalendarView.h:
--------------------------------------------------------------------------------
1 | ../../../../../JTCalendar/Views/JTHorizontalCalendarView.h
--------------------------------------------------------------------------------
/Example/Pods/Headers/Public/JTCalendar/JTMenu.h:
--------------------------------------------------------------------------------
1 | ../../../../../JTCalendar/Protocols/JTMenu.h
--------------------------------------------------------------------------------
/Example/Pods/Headers/Public/JTCalendar/JTVerticalCalendarView.h:
--------------------------------------------------------------------------------
1 | ../../../../../JTCalendar/Views/JTVerticalCalendarView.h
--------------------------------------------------------------------------------
/Example/Pods/Local Podspecs/JTCalendar.podspec.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "JTCalendar",
3 | "version": "2.1.9",
4 | "summary": "A customizable calendar view for iOS.",
5 | "homepage": "https://github.com/jonathantribouharet/JTCalendar",
6 | "license": {
7 | "type": "MIT"
8 | },
9 | "authors": {
10 | "Jonathan Tribouharet": "jonathan.tribouharet@gmail.com"
11 | },
12 | "platforms": {
13 | "ios": "7.0"
14 | },
15 | "source": {
16 | "git": "https://github.com/jonathantribouharet/JTCalendar.git",
17 | "tag": "2.1.9"
18 | },
19 | "source_files": "JTCalendar/**/*",
20 | "requires_arc": true,
21 | "screenshots": [
22 | "https://raw.githubusercontent.com/jonathantribouharet/JTCalendar/master/Screens/example.gif"
23 | ]
24 | }
25 |
--------------------------------------------------------------------------------
/Example/Pods/Manifest.lock:
--------------------------------------------------------------------------------
1 | PODS:
2 | - JTCalendar (2.1.9)
3 |
4 | DEPENDENCIES:
5 | - JTCalendar (from `..`)
6 |
7 | EXTERNAL SOURCES:
8 | JTCalendar:
9 | :path: ..
10 |
11 | SPEC CHECKSUMS:
12 | JTCalendar: beb2f4c1b639bf6880f680b4858227acf83a049c
13 |
14 | COCOAPODS: 0.39.0
15 |
--------------------------------------------------------------------------------
/Example/Pods/Pods.xcodeproj/xcshareddata/xcschemes/JTCalendar.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
43 |
44 |
45 |
46 |
52 |
53 |
55 |
56 |
59 |
60 |
61 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/JTCalendar/JTCalendar-dummy.m:
--------------------------------------------------------------------------------
1 | #import
2 | @interface PodsDummy_JTCalendar : NSObject
3 | @end
4 | @implementation PodsDummy_JTCalendar
5 | @end
6 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/JTCalendar/JTCalendar-prefix.pch:
--------------------------------------------------------------------------------
1 | #ifdef __OBJC__
2 | #import
3 | #endif
4 |
5 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/JTCalendar/JTCalendar.xcconfig:
--------------------------------------------------------------------------------
1 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
2 | HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/JTCalendar" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/JTCalendar"
3 | PODS_ROOT = ${SRCROOT}
4 | SKIP_INSTALL = YES
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Pods/Pods-acknowledgements.markdown:
--------------------------------------------------------------------------------
1 | # Acknowledgements
2 | This application makes use of the following third party libraries:
3 |
4 | ## JTCalendar
5 |
6 | Copyright (c) 2015 Jonathan Tribouharet
7 |
8 | Permission is hereby granted, free of charge, to any person obtaining a copy
9 | of this software and associated documentation files (the "Software"), to deal
10 | in the Software without restriction, including without limitation the rights
11 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | copies of the Software, and to permit persons to whom the Software is
13 | furnished to do so, subject to the following conditions:
14 |
15 | The above copyright notice and this permission notice shall be included in
16 | all copies or substantial portions of the Software.
17 |
18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 | THE SOFTWARE.
25 | Generated by CocoaPods - http://cocoapods.org
26 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Pods/Pods-acknowledgements.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PreferenceSpecifiers
6 |
7 |
8 | FooterText
9 | This application makes use of the following third party libraries:
10 | Title
11 | Acknowledgements
12 | Type
13 | PSGroupSpecifier
14 |
15 |
16 | FooterText
17 | Copyright (c) 2015 Jonathan Tribouharet
18 |
19 | Permission is hereby granted, free of charge, to any person obtaining a copy
20 | of this software and associated documentation files (the "Software"), to deal
21 | in the Software without restriction, including without limitation the rights
22 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
23 | copies of the Software, and to permit persons to whom the Software is
24 | furnished to do so, subject to the following conditions:
25 |
26 | The above copyright notice and this permission notice shall be included in
27 | all copies or substantial portions of the Software.
28 |
29 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
30 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
31 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
32 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
33 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
34 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
35 | THE SOFTWARE.
36 | Title
37 | JTCalendar
38 | Type
39 | PSGroupSpecifier
40 |
41 |
42 | FooterText
43 | Generated by CocoaPods - http://cocoapods.org
44 | Title
45 |
46 | Type
47 | PSGroupSpecifier
48 |
49 |
50 | StringsTable
51 | Acknowledgements
52 | Title
53 | Acknowledgements
54 |
55 |
56 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Pods/Pods-dummy.m:
--------------------------------------------------------------------------------
1 | #import
2 | @interface PodsDummy_Pods : NSObject
3 | @end
4 | @implementation PodsDummy_Pods
5 | @end
6 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Pods/Pods-frameworks.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | set -e
3 |
4 | echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
5 | mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
6 |
7 | SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}"
8 |
9 | install_framework()
10 | {
11 | if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then
12 | local source="${BUILT_PRODUCTS_DIR}/$1"
13 | elif [ -r "${BUILT_PRODUCTS_DIR}/$(basename "$1")" ]; then
14 | local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")"
15 | elif [ -r "$1" ]; then
16 | local source="$1"
17 | fi
18 |
19 | local destination="${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
20 |
21 | if [ -L "${source}" ]; then
22 | echo "Symlinked..."
23 | source="$(readlink "${source}")"
24 | fi
25 |
26 | # use filter instead of exclude so missing patterns dont' throw errors
27 | echo "rsync -av --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\""
28 | rsync -av --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}"
29 |
30 | local basename
31 | basename="$(basename -s .framework "$1")"
32 | binary="${destination}/${basename}.framework/${basename}"
33 | if ! [ -r "$binary" ]; then
34 | binary="${destination}/${basename}"
35 | fi
36 |
37 | # Strip invalid architectures so "fat" simulator / device frameworks work on device
38 | if [[ "$(file "$binary")" == *"dynamically linked shared library"* ]]; then
39 | strip_invalid_archs "$binary"
40 | fi
41 |
42 | # Resign the code if required by the build settings to avoid unstable apps
43 | code_sign_if_enabled "${destination}/$(basename "$1")"
44 |
45 | # Embed linked Swift runtime libraries. No longer necessary as of Xcode 7.
46 | if [ "${XCODE_VERSION_MAJOR}" -lt 7 ]; then
47 | local swift_runtime_libs
48 | swift_runtime_libs=$(xcrun otool -LX "$binary" | grep --color=never @rpath/libswift | sed -E s/@rpath\\/\(.+dylib\).*/\\1/g | uniq -u && exit ${PIPESTATUS[0]})
49 | for lib in $swift_runtime_libs; do
50 | echo "rsync -auv \"${SWIFT_STDLIB_PATH}/${lib}\" \"${destination}\""
51 | rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}"
52 | code_sign_if_enabled "${destination}/${lib}"
53 | done
54 | fi
55 | }
56 |
57 | # Signs a framework with the provided identity
58 | code_sign_if_enabled() {
59 | if [ -n "${EXPANDED_CODE_SIGN_IDENTITY}" -a "${CODE_SIGNING_REQUIRED}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then
60 | # Use the current code_sign_identitiy
61 | echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}"
62 | echo "/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} --preserve-metadata=identifier,entitlements \"$1\""
63 | /usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} --preserve-metadata=identifier,entitlements "$1"
64 | fi
65 | }
66 |
67 | # Strip invalid architectures
68 | strip_invalid_archs() {
69 | binary="$1"
70 | # Get architectures for current file
71 | archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | rev)"
72 | stripped=""
73 | for arch in $archs; do
74 | if ! [[ "${VALID_ARCHS}" == *"$arch"* ]]; then
75 | # Strip non-valid architectures in-place
76 | lipo -remove "$arch" -output "$binary" "$binary" || exit 1
77 | stripped="$stripped $arch"
78 | fi
79 | done
80 | if [[ "$stripped" ]]; then
81 | echo "Stripped $binary of architectures:$stripped"
82 | fi
83 | }
84 |
85 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Pods/Pods-resources.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | set -e
3 |
4 | mkdir -p "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
5 |
6 | RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt
7 | > "$RESOURCES_TO_COPY"
8 |
9 | XCASSET_FILES=()
10 |
11 | realpath() {
12 | DIRECTORY="$(cd "${1%/*}" && pwd)"
13 | FILENAME="${1##*/}"
14 | echo "$DIRECTORY/$FILENAME"
15 | }
16 |
17 | install_resource()
18 | {
19 | case $1 in
20 | *.storyboard)
21 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --output-format human-readable-text --compile ${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$1\" .storyboard`.storyboardc ${PODS_ROOT}/$1 --sdk ${SDKROOT}"
22 | ibtool --reference-external-strings-file --errors --warnings --notices --output-format human-readable-text --compile "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$1\" .storyboard`.storyboardc" "${PODS_ROOT}/$1" --sdk "${SDKROOT}"
23 | ;;
24 | *.xib)
25 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --output-format human-readable-text --compile ${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$1\" .xib`.nib ${PODS_ROOT}/$1 --sdk ${SDKROOT}"
26 | ibtool --reference-external-strings-file --errors --warnings --notices --output-format human-readable-text --compile "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$1\" .xib`.nib" "${PODS_ROOT}/$1" --sdk "${SDKROOT}"
27 | ;;
28 | *.framework)
29 | echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
30 | mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
31 | echo "rsync -av ${PODS_ROOT}/$1 ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
32 | rsync -av "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
33 | ;;
34 | *.xcdatamodel)
35 | echo "xcrun momc \"${PODS_ROOT}/$1\" \"${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1"`.mom\""
36 | xcrun momc "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcdatamodel`.mom"
37 | ;;
38 | *.xcdatamodeld)
39 | echo "xcrun momc \"${PODS_ROOT}/$1\" \"${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcdatamodeld`.momd\""
40 | xcrun momc "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcdatamodeld`.momd"
41 | ;;
42 | *.xcmappingmodel)
43 | echo "xcrun mapc \"${PODS_ROOT}/$1\" \"${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcmappingmodel`.cdm\""
44 | xcrun mapc "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcmappingmodel`.cdm"
45 | ;;
46 | *.xcassets)
47 | ABSOLUTE_XCASSET_FILE=$(realpath "${PODS_ROOT}/$1")
48 | XCASSET_FILES+=("$ABSOLUTE_XCASSET_FILE")
49 | ;;
50 | /*)
51 | echo "$1"
52 | echo "$1" >> "$RESOURCES_TO_COPY"
53 | ;;
54 | *)
55 | echo "${PODS_ROOT}/$1"
56 | echo "${PODS_ROOT}/$1" >> "$RESOURCES_TO_COPY"
57 | ;;
58 | esac
59 | }
60 |
61 | mkdir -p "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
62 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
63 | if [[ "${ACTION}" == "install" ]] && [[ "${SKIP_INSTALL}" == "NO" ]]; then
64 | mkdir -p "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
65 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
66 | fi
67 | rm -f "$RESOURCES_TO_COPY"
68 |
69 | if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ -n "$XCASSET_FILES" ]
70 | then
71 | case "${TARGETED_DEVICE_FAMILY}" in
72 | 1,2)
73 | TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone"
74 | ;;
75 | 1)
76 | TARGET_DEVICE_ARGS="--target-device iphone"
77 | ;;
78 | 2)
79 | TARGET_DEVICE_ARGS="--target-device ipad"
80 | ;;
81 | *)
82 | TARGET_DEVICE_ARGS="--target-device mac"
83 | ;;
84 | esac
85 |
86 | # Find all other xcassets (this unfortunately includes those of path pods and other targets).
87 | OTHER_XCASSETS=$(find "$PWD" -iname "*.xcassets" -type d)
88 | while read line; do
89 | if [[ $line != "`realpath $PODS_ROOT`*" ]]; then
90 | XCASSET_FILES+=("$line")
91 | fi
92 | done <<<"$OTHER_XCASSETS"
93 |
94 | printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${IPHONEOS_DEPLOYMENT_TARGET}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
95 | fi
96 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Pods/Pods.debug.xcconfig:
--------------------------------------------------------------------------------
1 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
2 | HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/JTCalendar"
3 | OTHER_CFLAGS = $(inherited) -isystem "${PODS_ROOT}/Headers/Public" -isystem "${PODS_ROOT}/Headers/Public/JTCalendar"
4 | OTHER_LDFLAGS = $(inherited) -ObjC -l"JTCalendar"
5 | PODS_ROOT = ${SRCROOT}/Pods
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Pods/Pods.release.xcconfig:
--------------------------------------------------------------------------------
1 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
2 | HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/JTCalendar"
3 | OTHER_CFLAGS = $(inherited) -isystem "${PODS_ROOT}/Headers/Public" -isystem "${PODS_ROOT}/Headers/Public/JTCalendar"
4 | OTHER_LDFLAGS = $(inherited) -ObjC -l"JTCalendar"
5 | PODS_ROOT = ${SRCROOT}/Pods
--------------------------------------------------------------------------------
/JTCalendar.podspec:
--------------------------------------------------------------------------------
1 | Pod::Spec.new do |s|
2 | s.name = "JTCalendar"
3 | s.version = "2.2.6"
4 | s.summary = "A customizable calendar view for iOS."
5 | s.homepage = "https://github.com/jonathantribouharet/JTCalendar"
6 | s.license = { :type => 'MIT' }
7 | s.author = { "Jonathan VUKOVICH TRIBOUHARET" => "jonathan.tribouharet@gmail.com" }
8 | s.platform = :ios, '7.0'
9 | s.source = { :git => "https://github.com/jonathantribouharet/JTCalendar.git", :tag => s.version.to_s }
10 | s.source_files = 'JTCalendar/**/*.{h,m}'
11 | s.requires_arc = true
12 | s.screenshots = ["https://raw.githubusercontent.com/jonathantribouharet/JTCalendar/master/Screens/example.gif"]
13 | end
14 |
--------------------------------------------------------------------------------
/JTCalendar.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/JTCalendar.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/JTCalendar.xcodeproj/xcshareddata/xcschemes/JTCalendar.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
31 |
32 |
33 |
34 |
35 |
36 |
47 |
48 |
54 |
55 |
56 |
57 |
58 |
59 |
65 |
66 |
72 |
73 |
74 |
75 |
77 |
78 |
81 |
82 |
83 |
--------------------------------------------------------------------------------
/JTCalendar/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | $(CURRENT_PROJECT_VERSION)
21 | NSPrincipalClass
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/JTCalendar/JTCalendar.h:
--------------------------------------------------------------------------------
1 | //
2 | // JTCalendar.h
3 | // JTCalendar
4 | //
5 | // Created by Created by Jonathan Tribouharet
6 | //
7 |
8 | #import
9 |
10 | //! Project version number for JTCalendar.
11 | FOUNDATION_EXPORT double JTCalendarVersionNumber;
12 |
13 | //! Project version string for JTCalendar.
14 | FOUNDATION_EXPORT const unsigned char JTCalendarVersionString[];
15 |
16 | // In this header, you should import all the public headers of your framework using statements
17 | #import "JTCalendarManager.h"
18 |
19 | #import "JTHorizontalCalendarView.h"
20 | #import "JTVerticalCalendarView.h"
21 |
22 | #import "JTCalendarMenuView.h"
23 |
24 | #import "JTCalendarPageView.h"
25 | #import "JTCalendarWeekDayView.h"
26 | #import "JTCalendarWeekView.h"
27 | #import "JTCalendarDayView.h"
28 |
29 |
30 |
--------------------------------------------------------------------------------
/JTCalendar/JTCalendarDelegate.h:
--------------------------------------------------------------------------------
1 | //
2 | // JTCalendarDelegate.h
3 | // JTCalendar
4 | //
5 | // Created by Jonathan Tribouharet
6 | //
7 |
8 | #import
9 |
10 | #import "JTCalendarPage.h"
11 | #import "JTCalendarWeek.h"
12 | #import "JTCalendarWeekDay.h"
13 | #import "JTCalendarDay.h"
14 |
15 | @class JTCalendarManager;
16 |
17 | @protocol JTCalendarDelegate
18 |
19 | @optional
20 |
21 |
22 | // Menu view
23 |
24 |
25 | /*!
26 | * Provide a UIView, used as page for the menuView.
27 | * Return an instance of `UILabel` by default.
28 | */
29 | - (UIView *_Nullable)calendarBuildMenuItemView:(JTCalendarManager *_Nullable)calendar;
30 |
31 | /*!
32 | * Used to customize the menuItemView.
33 | * Set text attribute to the name of the month by default.
34 | */
35 | - (void)calendar:(JTCalendarManager *_Nullable)calendar prepareMenuItemView:(UIView *_Nullable)menuItemView date:(NSDate *_Nullable)date;
36 |
37 |
38 | // Content view
39 |
40 |
41 | /*!
42 | * Indicate if the calendar can go to this date.
43 | * Return `YES` by default.
44 | */
45 | - (BOOL)calendar:(JTCalendarManager *_Nullable)calendar canDisplayPageWithDate:(NSDate *_Nullable)date;
46 |
47 | /*!
48 | * Provide the date for the previous page.
49 | * Return 1 month before the current date by default.
50 | */
51 | - (NSDate *_Nullable)calendar:(JTCalendarManager *_Nullable)calendar dateForPreviousPageWithCurrentDate:(NSDate *_Nullable)currentDate;
52 |
53 | /*!
54 | * Provide the date for the next page.
55 | * Return 1 month after the current date by default.
56 | */
57 | - (NSDate *_Nullable)calendar:(JTCalendarManager *_Nullable)calendar dateForNextPageWithCurrentDate:(NSDate *_Nullable)currentDate;
58 |
59 | /*!
60 | * Indicate the previous page became the current page.
61 | */
62 | - (void)calendarDidLoadPreviousPage:(JTCalendarManager *_Nullable)calendar;
63 |
64 | /*!
65 | * Indicate the next page became the current page.
66 | */
67 | - (void)calendarDidLoadNextPage:(JTCalendarManager *_Nullable)calendar;
68 |
69 | /*!
70 | * Provide a view conforming to `JTCalendarPage` protocol, used as page for the contentView.
71 | * Return an instance of `JTCalendarPageView` by default.
72 | */
73 | - (UIView *_Nullable)calendarBuildPageView:(JTCalendarManager *_Nullable)calendar;
74 |
75 |
76 | // Page view
77 |
78 |
79 | /*!
80 | * Provide a view conforming to `JTCalendarWeekDay` protocol.
81 | * Return an instance of `JTCalendarWeekDayView` by default.
82 | */
83 | - (UIView *_Nullable)calendarBuildWeekDayView:(JTCalendarManager *_Nullable)calendar;
84 |
85 | /*!
86 | * Provide a view conforming to `JTCalendarWeek` protocol.
87 | * Return an instance of `JTCalendarWeekView` by default.
88 | */
89 | - (UIView *_Nullable)calendarBuildWeekView:(JTCalendarManager *_Nullable)calendar;
90 |
91 |
92 | // Week view
93 |
94 |
95 | /*!
96 | * Provide a view conforming to `JTCalendarDay` protocol.
97 | * Return an instance of `JTCalendarDayView` by default.
98 | */
99 | - (UIView *_Nullable)calendarBuildDayView:(JTCalendarManager *_Nullable)calendar;
100 |
101 |
102 | // Day view
103 |
104 |
105 | /*!
106 | * Used to customize the dayView.
107 | */
108 | - (void)calendar:(JTCalendarManager *_Nullable)calendar prepareDayView:(UIView *_Nullable)dayView;
109 |
110 | /*!
111 | * Indicate the dayView just get touched.
112 | */
113 | - (void)calendar:(JTCalendarManager *_Nullable)calendar didTouchDayView:(UIView *_Nullable)dayView;
114 |
115 | @end
116 |
--------------------------------------------------------------------------------
/JTCalendar/JTCalendarManager.h:
--------------------------------------------------------------------------------
1 | //
2 | // JTCalendarManager.h
3 | // JTCalendar
4 | //
5 | // Created by Jonathan Tribouharet
6 | //
7 |
8 | #import
9 |
10 | #import "JTCalendarDelegate.h"
11 |
12 | #import "JTContent.h"
13 | #import "JTMenu.h"
14 |
15 | #import "JTDateHelper.h"
16 | #import "JTCalendarSettings.h"
17 |
18 | #import "JTCalendarDelegateManager.h"
19 | #import "JTCalendarScrollManager.h"
20 |
21 | @interface JTCalendarManager : NSObject
22 |
23 | @property (nonatomic, weak, nullable) id delegate;
24 |
25 | @property (nonatomic, weak) UIView * _Nullable menuView;
26 | @property (nonatomic, weak) UIScrollView * _Nullable contentView;
27 |
28 | @property (nonatomic, readonly) JTDateHelper * _Nullable dateHelper;
29 | @property (nonatomic, readonly) JTCalendarSettings * _Nullable settings;
30 |
31 | // Intern methods
32 |
33 | @property (nonatomic, readonly) JTCalendarDelegateManager * _Nullable delegateManager;
34 | @property (nonatomic, readonly) JTCalendarScrollManager * _Nullable scrollManager;
35 |
36 | - (instancetype _Nullable )initWithLocale:(NSLocale *_Nullable)locale andTimeZone:(NSTimeZone *_Nullable)timeZone;
37 |
38 | - (NSDate *_Nonnull)date;
39 | - (void)setDate:(NSDate *_Nullable)date;
40 | - (void)reload;
41 |
42 |
43 | @end
44 |
--------------------------------------------------------------------------------
/JTCalendar/JTCalendarManager.m:
--------------------------------------------------------------------------------
1 | //
2 | // JTCalendarManager.m
3 | // JTCalendar
4 | //
5 | // Created by Jonathan Tribouharet
6 | //
7 |
8 | #import "JTCalendarManager.h"
9 |
10 | #import "JTHorizontalCalendarView.h"
11 |
12 | @implementation JTCalendarManager
13 |
14 | - (instancetype)init
15 | {
16 | return [self initWithLocale:[NSLocale currentLocale] andTimeZone:[NSTimeZone localTimeZone]];
17 | }
18 |
19 | - (instancetype)initWithLocale:(NSLocale *)locale andTimeZone:(NSTimeZone *)timeZone
20 | {
21 | self = [super init];
22 | if(!self){
23 | return nil;
24 | }
25 | [self commonInit:locale andTimeZone:timeZone];
26 |
27 | return self;
28 | }
29 |
30 | - (void)commonInit:(NSLocale *)locale andTimeZone:(NSTimeZone *)timeZone
31 | {
32 | _dateHelper = [[JTDateHelper alloc] initWithLocale:locale andTimeZone:timeZone];
33 | _settings = [JTCalendarSettings new];
34 |
35 | _delegateManager = [JTCalendarDelegateManager new];
36 | _delegateManager.manager = self;
37 |
38 | _scrollManager = [JTCalendarScrollManager new];
39 | _scrollManager.manager = self;
40 | }
41 |
42 | - (void)setContentView:(UIScrollView *)contentView
43 | {
44 | [_contentView setManager:nil];
45 | self->_contentView = contentView;
46 | [_contentView setManager:self];
47 |
48 | // Can only synchronise JTHorizontalCalendarView
49 | if([_contentView isKindOfClass:[JTHorizontalCalendarView class]]){
50 | _scrollManager.horizontalContentView = _contentView;
51 | }
52 | else{
53 | _scrollManager.horizontalContentView = nil;
54 | }
55 | }
56 |
57 | - (void)setMenuView:(UIScrollView *)menuView
58 | {
59 | [_menuView setManager:nil];
60 | self->_menuView = menuView;
61 | [_menuView setManager:self];
62 |
63 | _scrollManager.menuView = _menuView;
64 | }
65 |
66 | - (NSDate *)date
67 | {
68 | return _contentView.date;
69 | }
70 |
71 | - (void)setDate:(NSDate *)date
72 | {
73 | [_contentView setDate:date];
74 | }
75 |
76 | - (void)reload
77 | {
78 | [_contentView setDate:_contentView.date];
79 | }
80 |
81 | @end
82 |
--------------------------------------------------------------------------------
/JTCalendar/JTCalendarSettings.h:
--------------------------------------------------------------------------------
1 | //
2 | // JTCalendarSettings.h
3 | // JTCalendar
4 | //
5 | // Created by Jonathan Tribouharet
6 | //
7 |
8 | #import
9 |
10 | typedef NS_ENUM(NSInteger, JTCalendarWeekDayFormat) {
11 | JTCalendarWeekDayFormatSingle,
12 | JTCalendarWeekDayFormatShort,
13 | JTCalendarWeekDayFormatFull
14 | };
15 |
16 | @interface JTCalendarSettings : NSObject
17 |
18 |
19 | // Content view
20 |
21 | @property (nonatomic) BOOL pageViewHideWhenPossible;
22 | @property (nonatomic) BOOL weekModeEnabled;
23 |
24 |
25 | // Page view
26 |
27 | // Must be less or equalt to 6, 0 for automatic
28 | @property (nonatomic) NSUInteger pageViewNumberOfWeeks;
29 | @property (nonatomic) BOOL pageViewHaveWeekDaysView;
30 | @property (nonatomic) NSUInteger pageViewWeekModeNumberOfWeeks;
31 | @property (nonatomic) BOOL pageViewWeekDaysViewAutomaticHeight;
32 |
33 | // WeekDay view
34 |
35 | @property (nonatomic) JTCalendarWeekDayFormat weekDayFormat;
36 |
37 |
38 | // Day view
39 |
40 | @property (nonatomic) BOOL zeroPaddedDayFormat;
41 |
42 |
43 | // Use for override
44 | - (void)commonInit;
45 |
46 | @end
47 |
--------------------------------------------------------------------------------
/JTCalendar/JTCalendarSettings.m:
--------------------------------------------------------------------------------
1 | //
2 | // JTCalendarSettings.m
3 | // JTCalendar
4 | //
5 | // Created by Jonathan Tribouharet
6 | //
7 |
8 | #import "JTCalendarSettings.h"
9 |
10 | @implementation JTCalendarSettings
11 |
12 | - (instancetype)init
13 | {
14 | self = [super init];
15 | if(!self){
16 | return nil;
17 | }
18 |
19 | [self commonInit];
20 |
21 | return self;
22 | }
23 |
24 | - (void)commonInit
25 | {
26 | _pageViewHideWhenPossible = NO;
27 | _pageViewNumberOfWeeks = 6;
28 | _pageViewHaveWeekDaysView = YES;
29 | _pageViewWeekDaysViewAutomaticHeight = NO;
30 | _weekDayFormat = JTCalendarWeekDayFormatShort;
31 | _zeroPaddedDayFormat = YES;
32 | _weekModeEnabled = NO;
33 | _pageViewWeekModeNumberOfWeeks = 1;
34 | }
35 |
36 | @end
37 |
--------------------------------------------------------------------------------
/JTCalendar/JTDateHelper.h:
--------------------------------------------------------------------------------
1 | //
2 | // JTDateHelper.h
3 | // JTCalendar
4 | //
5 | // Created by Jonathan Tribouharet
6 | //
7 |
8 | #import
9 |
10 | @interface JTDateHelper : NSObject
11 |
12 | - initWithLocale:(NSLocale *)locale andTimeZone:(NSTimeZone *)timeZone;
13 |
14 | - (NSCalendar *)calendar;
15 | - (NSDateFormatter *)createDateFormatter;
16 |
17 | - (NSDate *)addToDate:(NSDate *)date months:(NSInteger)months;
18 | - (NSDate *)addToDate:(NSDate *)date weeks:(NSInteger)weeks;
19 | - (NSDate *)addToDate:(NSDate *)date days:(NSInteger)days;
20 |
21 | // Must be less or equal to 6
22 | - (NSUInteger)numberOfWeeks:(NSDate *)date;
23 |
24 | - (NSDate *)firstDayOfMonth:(NSDate *)date;
25 | - (NSDate *)firstWeekDayOfMonth:(NSDate *)date;
26 | - (NSDate *)firstWeekDayOfWeek:(NSDate *)date;
27 |
28 | - (BOOL)date:(NSDate *)dateA isTheSameMonthThan:(NSDate *)dateB;
29 | - (BOOL)date:(NSDate *)dateA isTheSameWeekThan:(NSDate *)dateB;
30 | - (BOOL)date:(NSDate *)dateA isTheSameDayThan:(NSDate *)dateB;
31 |
32 | - (BOOL)date:(NSDate *)dateA isEqualOrBefore:(NSDate *)dateB;
33 | - (BOOL)date:(NSDate *)dateA isEqualOrAfter:(NSDate *)dateB;
34 | - (BOOL)date:(NSDate *)date isEqualOrAfter:(NSDate *)startDate andEqualOrBefore:(NSDate *)endDate;
35 |
36 | @end
37 |
--------------------------------------------------------------------------------
/JTCalendar/JTDateHelper.m:
--------------------------------------------------------------------------------
1 | //
2 | // JTDateHelper.m
3 | // JTCalendar
4 | //
5 | // Created by Jonathan Tribouharet
6 | //
7 |
8 | #import "JTDateHelper.h"
9 |
10 | @interface JTDateHelper (){
11 | NSCalendar *_calendar;
12 | NSLocale *_locale;
13 | NSTimeZone *_timeZone;
14 | }
15 |
16 | @end
17 |
18 | @implementation JTDateHelper
19 |
20 | - (instancetype)initWithLocale:(NSLocale *)locale andTimeZone:(NSTimeZone *)timeZone
21 | {
22 | self = [super init];
23 | if (self) {
24 | _locale = locale;
25 | _timeZone = timeZone;
26 | }
27 | return self;
28 | }
29 |
30 | - (NSCalendar *)calendar
31 | {
32 | if(!_calendar){
33 | #ifdef __IPHONE_8_0
34 | _calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
35 | #else
36 | _calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
37 | #endif
38 | _calendar.timeZone = _timeZone;
39 | _calendar.locale = _locale;
40 | }
41 |
42 | return _calendar;
43 | }
44 |
45 | - (NSDateFormatter *)createDateFormatter
46 | {
47 | NSDateFormatter *dateFormatter = [NSDateFormatter new];
48 |
49 | dateFormatter.timeZone = self.calendar.timeZone;
50 | dateFormatter.locale = self.calendar.locale;
51 |
52 | return dateFormatter;
53 | }
54 |
55 | #pragma mark - Operations
56 |
57 | - (NSDate *)addToDate:(NSDate *)date months:(NSInteger)months
58 | {
59 | NSDateComponents *components = [NSDateComponents new];
60 | components.month = months;
61 | return [self.calendar dateByAddingComponents:components toDate:date options:0];
62 | }
63 |
64 | - (NSDate *)addToDate:(NSDate *)date weeks:(NSInteger)weeks
65 | {
66 | NSDateComponents *components = [NSDateComponents new];
67 | components.day = 7 * weeks;
68 | return [self.calendar dateByAddingComponents:components toDate:date options:0];
69 | }
70 |
71 | - (NSDate *)addToDate:(NSDate *)date days:(NSInteger)days
72 | {
73 | NSDateComponents *components = [NSDateComponents new];
74 | components.day = days;
75 | return [self.calendar dateByAddingComponents:components toDate:date options:0];
76 | }
77 |
78 | #pragma mark - Helpers
79 |
80 | - (NSUInteger)numberOfWeeks:(NSDate *)date
81 | {
82 | NSDate *firstDay = [self firstDayOfMonth:date];
83 | NSDate *lastDay = [self lastDayOfMonth:date];
84 |
85 | NSDateComponents *componentsA = [self.calendar components:NSCalendarUnitWeekOfMonth fromDate:firstDay];
86 | NSDateComponents *componentsB = [self.calendar components:NSCalendarUnitWeekOfMonth fromDate:lastDay];
87 |
88 | return (componentsB.weekOfMonth - componentsA.weekOfMonth + 1);
89 | }
90 |
91 | - (NSDate *)firstDayOfMonth:(NSDate *)date
92 | {
93 | NSDateComponents *componentsCurrentDate = [self.calendar components:NSCalendarUnitYear|NSCalendarUnitMonth|NSCalendarUnitDay|NSCalendarUnitWeekday|NSCalendarUnitWeekOfMonth fromDate:date];
94 |
95 | NSDateComponents *componentsNewDate = [NSDateComponents new];
96 |
97 | componentsNewDate.year = componentsCurrentDate.year;
98 | componentsNewDate.month = componentsCurrentDate.month;
99 | componentsNewDate.weekOfMonth = 1;
100 | componentsNewDate.day = 1;
101 |
102 | return [self.calendar dateFromComponents:componentsNewDate];
103 | }
104 |
105 | - (NSDate *)lastDayOfMonth:(NSDate *)date
106 | {
107 | NSDateComponents *componentsCurrentDate = [self.calendar components:NSCalendarUnitYear|NSCalendarUnitMonth|NSCalendarUnitDay|NSCalendarUnitWeekday|NSCalendarUnitWeekOfMonth fromDate:date];
108 |
109 | NSDateComponents *componentsNewDate = [NSDateComponents new];
110 |
111 | componentsNewDate.year = componentsCurrentDate.year;
112 | componentsNewDate.month = componentsCurrentDate.month + 1;
113 | componentsNewDate.day = 0;
114 |
115 | return [self.calendar dateFromComponents:componentsNewDate];
116 | }
117 |
118 | - (NSDate *)firstWeekDayOfMonth:(NSDate *)date
119 | {
120 | NSDate *firstDayOfMonth = [self firstDayOfMonth:date];
121 | return [self firstWeekDayOfWeek:firstDayOfMonth];
122 | }
123 |
124 | - (NSDate *)firstWeekDayOfWeek:(NSDate *)date
125 | {
126 | NSDateComponents *componentsCurrentDate = [self.calendar components:NSCalendarUnitYear|NSCalendarUnitMonth|NSCalendarUnitDay|NSCalendarUnitWeekday|NSCalendarUnitWeekOfMonth fromDate:date];
127 |
128 | NSDateComponents *componentsNewDate = [NSDateComponents new];
129 |
130 | componentsNewDate.year = componentsCurrentDate.year;
131 | componentsNewDate.month = componentsCurrentDate.month;
132 | componentsNewDate.weekOfMonth = componentsCurrentDate.weekOfMonth;
133 | componentsNewDate.weekday = self.calendar.firstWeekday;
134 |
135 | return [self.calendar dateFromComponents:componentsNewDate];
136 | }
137 |
138 | #pragma mark - Comparaison
139 |
140 | - (BOOL)date:(NSDate *)dateA isTheSameMonthThan:(NSDate *)dateB
141 | {
142 | NSDateComponents *componentsA = [self.calendar components:NSCalendarUnitYear|NSCalendarUnitMonth fromDate:dateA];
143 | NSDateComponents *componentsB = [self.calendar components:NSCalendarUnitYear|NSCalendarUnitMonth fromDate:dateB];
144 |
145 | return componentsA.year == componentsB.year && componentsA.month == componentsB.month;
146 | }
147 |
148 | - (BOOL)date:(NSDate *)dateA isTheSameWeekThan:(NSDate *)dateB
149 | {
150 | NSDateComponents *componentsA = [self.calendar components:NSCalendarUnitYear|NSCalendarUnitWeekOfYear fromDate:dateA];
151 | NSDateComponents *componentsB = [self.calendar components:NSCalendarUnitYear|NSCalendarUnitWeekOfYear fromDate:dateB];
152 |
153 | return componentsA.year == componentsB.year && componentsA.weekOfYear == componentsB.weekOfYear;
154 | }
155 |
156 | - (BOOL)date:(NSDate *)dateA isTheSameDayThan:(NSDate *)dateB
157 | {
158 | NSDateComponents *componentsA = [self.calendar components:NSCalendarUnitYear|NSCalendarUnitMonth|NSCalendarUnitDay fromDate:dateA];
159 | NSDateComponents *componentsB = [self.calendar components:NSCalendarUnitYear|NSCalendarUnitMonth|NSCalendarUnitDay fromDate:dateB];
160 |
161 | return componentsA.year == componentsB.year && componentsA.month == componentsB.month && componentsA.day == componentsB.day;
162 | }
163 |
164 | - (BOOL)date:(NSDate *)dateA isEqualOrBefore:(NSDate *)dateB
165 | {
166 | if([dateA compare:dateB] == NSOrderedAscending || [self date:dateA isTheSameDayThan:dateB]){
167 | return YES;
168 | }
169 |
170 | return NO;
171 | }
172 |
173 | - (BOOL)date:(NSDate *)dateA isEqualOrAfter:(NSDate *)dateB
174 | {
175 | if([dateA compare:dateB] == NSOrderedDescending || [self date:dateA isTheSameDayThan:dateB]){
176 | return YES;
177 | }
178 |
179 | return NO;
180 | }
181 |
182 | - (BOOL)date:(NSDate *)date isEqualOrAfter:(NSDate *)startDate andEqualOrBefore:(NSDate *)endDate
183 | {
184 | if([self date:date isEqualOrAfter:startDate] && [self date:date isEqualOrBefore:endDate]){
185 | return YES;
186 | }
187 |
188 | return NO;
189 | }
190 |
191 | @end
192 |
193 |
--------------------------------------------------------------------------------
/JTCalendar/Managers/JTCalendarDelegateManager.h:
--------------------------------------------------------------------------------
1 | //
2 | // JTCalendarDelegateManager.h
3 | // JTCalendar
4 | //
5 | // Created by Jonathan Tribouharet
6 | //
7 |
8 | #import
9 |
10 | #import "JTCalendarDelegate.h"
11 |
12 | // Provide a default behavior when no delegate are provided
13 |
14 | @interface JTCalendarDelegateManager : NSObject
15 |
16 | @property (nonatomic, weak) JTCalendarManager *manager;
17 |
18 | // Menu view
19 |
20 | - (UIView *)buildMenuItemView;
21 | - (void)prepareMenuItemView:(UIView *)menuItemView date:(NSDate *)date;
22 |
23 | // Content view
24 |
25 | - (UIView *)buildPageView;
26 |
27 | - (BOOL)canDisplayPageWithDate:(NSDate *)currentDate;
28 |
29 | - (NSDate *)dateForPreviousPageWithCurrentDate:(NSDate *)currentDate;
30 | - (NSDate *)dateForNextPageWithCurrentDate:(NSDate *)currentDate;
31 |
32 | // Page view
33 |
34 | - (UIView *)buildWeekDayView;
35 | - (UIView *)buildWeekView;
36 |
37 |
38 | // Week view
39 |
40 | - (UIView *)buildDayView;
41 |
42 |
43 | // Day view
44 |
45 | - (void)prepareDayView:(UIView *)dayView;
46 | - (void)didTouchDayView:(UIView *)dayView;
47 |
48 | @end
49 |
--------------------------------------------------------------------------------
/JTCalendar/Managers/JTCalendarDelegateManager.m:
--------------------------------------------------------------------------------
1 | //
2 | // JTCalendarDelegateManager.m
3 | // JTCalendar
4 | //
5 | // Created by Jonathan Tribouharet
6 | //
7 |
8 | #import "JTCalendarDelegateManager.h"
9 |
10 | #import "JTCalendarManager.h"
11 |
12 | #import "JTCalendarPageView.h"
13 | #import "JTCalendarWeekDayView.h"
14 | #import "JTCalendarWeekView.h"
15 | #import "JTCalendarDayView.h"
16 |
17 | @implementation JTCalendarDelegateManager
18 |
19 | #pragma mark - Menu view
20 |
21 | - (UIView *)buildMenuItemView
22 | {
23 | if(_manager.delegate && [_manager.delegate respondsToSelector:@selector(calendarBuildMenuItemView:)]){
24 | return [_manager.delegate calendarBuildMenuItemView:self.manager];
25 | }
26 |
27 | UILabel *label = [UILabel new];
28 | label.textAlignment = NSTextAlignmentCenter;
29 |
30 | return label;
31 | }
32 |
33 | - (void)prepareMenuItemView:(UIView *)menuItemView date:(NSDate *)date
34 | {
35 | if(_manager.delegate && [_manager.delegate respondsToSelector:@selector(calendar:prepareMenuItemView:date:)]){
36 | [_manager.delegate calendar:self.manager prepareMenuItemView:menuItemView date:date];
37 | return;
38 | }
39 |
40 | NSString *text = nil;
41 |
42 | if(date){
43 | NSCalendar *calendar = _manager.dateHelper.calendar;
44 | NSDateComponents *comps = [calendar components:NSCalendarUnitYear|NSCalendarUnitMonth fromDate:date];
45 | NSInteger currentMonthIndex = comps.month;
46 |
47 | static NSDateFormatter *dateFormatter = nil;
48 | if(!dateFormatter){
49 | dateFormatter = [_manager.dateHelper createDateFormatter];
50 | }
51 |
52 | dateFormatter.timeZone = _manager.dateHelper.calendar.timeZone;
53 | dateFormatter.locale = _manager.dateHelper.calendar.locale;
54 |
55 | while(currentMonthIndex <= 0){
56 | currentMonthIndex += 12;
57 | }
58 |
59 | text = [[dateFormatter standaloneMonthSymbols][currentMonthIndex - 1] capitalizedString];
60 | }
61 |
62 | [(UILabel *)menuItemView setText:text];
63 | }
64 |
65 | #pragma mark - Content view
66 |
67 | - (UIView *)buildPageView
68 | {
69 | if(_manager.delegate && [_manager.delegate respondsToSelector:@selector(calendarBuildPageView:)]){
70 | return [_manager.delegate calendarBuildPageView:self.manager];
71 | }
72 |
73 | return [JTCalendarPageView new];
74 | }
75 |
76 | - (BOOL)canDisplayPageWithDate:(NSDate *)date
77 | {
78 | if(_manager.delegate && [_manager.delegate respondsToSelector:@selector(calendar:canDisplayPageWithDate:)]){
79 | return [_manager.delegate calendar:self.manager canDisplayPageWithDate:date];
80 | }
81 |
82 | return YES;
83 | }
84 |
85 | - (NSDate *)dateForPreviousPageWithCurrentDate:(NSDate *)currentDate
86 | {
87 | NSAssert(currentDate != nil, @"currentDate cannot be nil");
88 |
89 | if(_manager.delegate && [_manager.delegate respondsToSelector:@selector(calendar:dateForPreviousPageWithCurrentDate:)]){
90 | return [_manager.delegate calendar:self.manager dateForPreviousPageWithCurrentDate:currentDate];
91 | }
92 |
93 | if(_manager.settings.weekModeEnabled){
94 | return [_manager.dateHelper addToDate:currentDate weeks:-1];
95 | }
96 | else{
97 | return [_manager.dateHelper addToDate:currentDate months:-1];
98 | }
99 | }
100 |
101 | - (NSDate *)dateForNextPageWithCurrentDate:(NSDate *)currentDate
102 | {
103 | NSAssert(currentDate != nil, @"currentDate cannot be nil");
104 |
105 | if(_manager.delegate && [_manager.delegate respondsToSelector:@selector(calendar:dateForNextPageWithCurrentDate:)]){
106 | return [_manager.delegate calendar:self.manager dateForNextPageWithCurrentDate:currentDate];
107 | }
108 |
109 | if(_manager.settings.weekModeEnabled){
110 | return [_manager.dateHelper addToDate:currentDate weeks:1];
111 | }
112 | else{
113 | return [_manager.dateHelper addToDate:currentDate months:1];
114 | }
115 | }
116 |
117 | #pragma mark - Page view
118 |
119 | - (UIView *)buildWeekDayView
120 | {
121 | if(_manager.delegate && [_manager.delegate respondsToSelector:@selector(calendarBuildWeekDayView:)]){
122 | return [_manager.delegate calendarBuildWeekDayView:self.manager];
123 | }
124 |
125 | return [JTCalendarWeekDayView new];
126 | }
127 |
128 | - (UIView *)buildWeekView
129 | {
130 | if(_manager.delegate && [_manager.delegate respondsToSelector:@selector(calendarBuildWeekView:)]){
131 | return [_manager.delegate calendarBuildWeekView:self.manager];
132 | }
133 |
134 | return [JTCalendarWeekView new];
135 | }
136 |
137 | #pragma mark - Week view
138 |
139 | - (UIView *)buildDayView
140 | {
141 | if(_manager.delegate && [_manager.delegate respondsToSelector:@selector(calendarBuildDayView:)]){
142 | return [_manager.delegate calendarBuildDayView:self.manager];
143 | }
144 |
145 | return [JTCalendarDayView new];
146 | }
147 |
148 | #pragma mark - Day view
149 |
150 | - (void)prepareDayView:(UIView *)dayView
151 | {
152 | if(_manager.delegate && [_manager.delegate respondsToSelector:@selector(calendar:prepareDayView:)]){
153 | [_manager.delegate calendar:self.manager prepareDayView:dayView];
154 | }
155 | }
156 |
157 | - (void)didTouchDayView:(UIView *)dayView
158 | {
159 | if(_manager.delegate && [_manager.delegate respondsToSelector:@selector(calendar:didTouchDayView:)]){
160 | [_manager.delegate calendar:self.manager didTouchDayView:dayView];
161 | }
162 | }
163 |
164 | @end
165 |
--------------------------------------------------------------------------------
/JTCalendar/Managers/JTCalendarScrollManager.h:
--------------------------------------------------------------------------------
1 | //
2 | // JTCalendarScrollManager.h
3 | // JTCalendar
4 | //
5 | // Created by Jonathan Tribouharet
6 | //
7 |
8 | #import
9 |
10 | #import "JTCalendarDelegate.h"
11 |
12 | #import "JTMenu.h"
13 | #import "JTContent.h"
14 |
15 | // Synchronize JTHorizontalCalendarView and JTCalendarMenuView
16 |
17 | @interface JTCalendarScrollManager : NSObject
18 |
19 | @property (nonatomic, weak) JTCalendarManager *manager;
20 |
21 | @property (nonatomic, weak) UIView *menuView;
22 | @property (nonatomic, weak) UIScrollView *horizontalContentView;
23 |
24 | - (void)setMenuPreviousDate:(NSDate *)previousDate
25 | currentDate:(NSDate *)currentDate
26 | nextDate:(NSDate *)nextDate;
27 |
28 | - (void)updateMenuContentOffset:(CGFloat)percentage pageMode:(NSUInteger)pageMode;
29 | - (void)updateHorizontalContentOffset:(CGFloat)percentage;
30 |
31 | @end
32 |
--------------------------------------------------------------------------------
/JTCalendar/Managers/JTCalendarScrollManager.m:
--------------------------------------------------------------------------------
1 | //
2 | // JTCalendarScrollManager.m
3 | // JTCalendar
4 | //
5 | // Created by Jonathan Tribouharet
6 | //
7 |
8 | #import "JTCalendarScrollManager.h"
9 |
10 | @implementation JTCalendarScrollManager
11 |
12 | - (void)setMenuPreviousDate:(NSDate *)previousDate
13 | currentDate:(NSDate *)currentDate
14 | nextDate:(NSDate *)nextDate
15 | {
16 | if(!_menuView){
17 | return;
18 | }
19 |
20 | [_menuView setPreviousDate:previousDate currentDate:currentDate nextDate:nextDate];
21 | }
22 |
23 | - (void)updateMenuContentOffset:(CGFloat)percentage pageMode:(NSUInteger)pageMode
24 | {
25 | if(!_menuView){
26 | return;
27 | }
28 |
29 | [_menuView updatePageMode:pageMode];
30 | _menuView.scrollView.contentOffset = CGPointMake(percentage * _menuView.scrollView.contentSize.width, 0);
31 | }
32 |
33 | - (void)updateHorizontalContentOffset:(CGFloat)percentage
34 | {
35 | if(!_horizontalContentView){
36 | return;
37 | }
38 |
39 | _horizontalContentView.contentOffset = CGPointMake(percentage * _horizontalContentView.contentSize.width, 0);
40 | }
41 |
42 | @end
43 |
--------------------------------------------------------------------------------
/JTCalendar/Protocols/JTCalendarDay.h:
--------------------------------------------------------------------------------
1 | //
2 | // JTCalendarDay.h
3 | // JTCalendar
4 | //
5 | // Created by Jonathan Tribouharet
6 | //
7 |
8 | #import
9 |
10 | @class JTCalendarManager;
11 |
12 | @protocol JTCalendarDay
13 |
14 | - (void)setManager:(JTCalendarManager *)manager;
15 |
16 | - (NSDate *)date;
17 | - (void)setDate:(NSDate *)date;
18 |
19 | - (BOOL)isFromAnotherMonth;
20 | - (void)setIsFromAnotherMonth:(BOOL)isFromAnotherMonth;
21 |
22 | @end
23 |
--------------------------------------------------------------------------------
/JTCalendar/Protocols/JTCalendarPage.h:
--------------------------------------------------------------------------------
1 | //
2 | // JTCalendarPage.h
3 | // JTCalendar
4 | //
5 | // Created by Jonathan Tribouharet
6 | //
7 |
8 | #import
9 |
10 | @class JTCalendarManager;
11 |
12 | @protocol JTCalendarPage
13 |
14 | - (void)setManager:(JTCalendarManager *)manager;
15 |
16 | - (NSDate *)date;
17 | - (void)setDate:(NSDate *)date;
18 |
19 | - (void)reload;
20 |
21 | @end
22 |
--------------------------------------------------------------------------------
/JTCalendar/Protocols/JTCalendarWeek.h:
--------------------------------------------------------------------------------
1 | //
2 | // JTCalendarWeek.h
3 | // JTCalendar
4 | //
5 | // Created by Jonathan Tribouharet
6 | //
7 |
8 | #import
9 |
10 | @class JTCalendarManager;
11 |
12 | @protocol JTCalendarWeek
13 |
14 | - (void)setManager:(JTCalendarManager *)manager;
15 |
16 | - (NSDate *)startDate;
17 | - (void)setStartDate:(NSDate *)startDate updateAnotherMonth:(BOOL)enable monthDate:(NSDate *)monthDate;
18 |
19 | @end
20 |
--------------------------------------------------------------------------------
/JTCalendar/Protocols/JTCalendarWeekDay.h:
--------------------------------------------------------------------------------
1 | //
2 | // JTCalendarWeekDay.h
3 | // JTCalendar
4 | //
5 | // Created by Jonathan Tribouharet
6 | //
7 |
8 | #import
9 |
10 | @class JTCalendarManager;
11 |
12 | @protocol JTCalendarWeekDay
13 |
14 | - (void)setManager:(JTCalendarManager *)manager;
15 |
16 | - (void)reload;
17 |
18 | @end
19 |
--------------------------------------------------------------------------------
/JTCalendar/Protocols/JTContent.h:
--------------------------------------------------------------------------------
1 | //
2 | // JTContent.h
3 | // JTCalendar
4 | //
5 | // Created by Jonathan Tribouharet
6 | //
7 |
8 | #import
9 |
10 | @class JTCalendarManager;
11 |
12 | @protocol JTContent
13 |
14 | - (void)setManager:(JTCalendarManager *)manager;
15 |
16 | - (NSDate *)date;
17 | - (void)setDate:(NSDate *)date;
18 |
19 | - (void)loadPreviousPage;
20 | - (void)loadNextPage;
21 |
22 | - (void)loadPreviousPageWithAnimation;
23 | - (void)loadNextPageWithAnimation;
24 |
25 | @end
26 |
--------------------------------------------------------------------------------
/JTCalendar/Protocols/JTMenu.h:
--------------------------------------------------------------------------------
1 | //
2 | // JTMenu.h
3 | // JTCalendar
4 | //
5 | // Created by Jonathan Tribouharet
6 | //
7 |
8 | #import
9 |
10 | @class JTCalendarManager;
11 |
12 | @protocol JTMenu
13 |
14 | - (void)setManager:(JTCalendarManager *)manager;
15 |
16 | - (void)setPreviousDate:(NSDate *)previousDate
17 | currentDate:(NSDate *)currentDate
18 | nextDate:(NSDate *)nextDate;
19 |
20 | - (void)updatePageMode:(NSUInteger)pageMode;
21 |
22 | - (UIScrollView *)scrollView;
23 |
24 | @end
25 |
--------------------------------------------------------------------------------
/JTCalendar/Views/JTCalendarDayView.h:
--------------------------------------------------------------------------------
1 | //
2 | // JTCalendarDayView.h
3 | // JTCalendar
4 | //
5 | // Created by Jonathan Tribouharet
6 | //
7 |
8 | #import
9 |
10 | #import "JTCalendarDay.h"
11 |
12 | @interface JTCalendarDayView : UIView
13 |
14 | @property (nonatomic, weak) JTCalendarManager *manager;
15 |
16 | @property (nonatomic) NSDate *date;
17 |
18 | @property (nonatomic, readonly) UIView *circleView;
19 | @property (nonatomic, readonly) UIView *dotView;
20 | @property (nonatomic, readonly) UILabel *textLabel;
21 |
22 | @property (nonatomic) CGFloat circleRatio;
23 | @property (nonatomic) CGFloat dotRatio;
24 |
25 | @property (nonatomic) BOOL isFromAnotherMonth;
26 |
27 | /*!
28 | * Must be call if override the class
29 | */
30 | - (void)commonInit;
31 |
32 | @end
33 |
--------------------------------------------------------------------------------
/JTCalendar/Views/JTCalendarDayView.m:
--------------------------------------------------------------------------------
1 | //
2 | // JTCalendarDayView.m
3 | // JTCalendar
4 | //
5 | // Created by Jonathan Tribouharet
6 | //
7 |
8 | #import "JTCalendarDayView.h"
9 |
10 | #import "JTCalendarManager.h"
11 |
12 | @implementation JTCalendarDayView
13 |
14 | - (instancetype)initWithFrame:(CGRect)frame
15 | {
16 | self = [super initWithFrame:frame];
17 | if(!self){
18 | return nil;
19 | }
20 |
21 | [self commonInit];
22 |
23 | return self;
24 | }
25 |
26 | - (instancetype)initWithCoder:(NSCoder *)aDecoder
27 | {
28 | self = [super initWithCoder:aDecoder];
29 | if(!self){
30 | return nil;
31 | }
32 |
33 | [self commonInit];
34 |
35 | return self;
36 | }
37 |
38 | - (void)commonInit
39 | {
40 | self.clipsToBounds = YES;
41 |
42 | _circleRatio = .9;
43 | _dotRatio = 1. / 9.;
44 |
45 | {
46 | _circleView = [UIView new];
47 | [self addSubview:_circleView];
48 |
49 | _circleView.backgroundColor = [UIColor colorWithRed:0x33/256. green:0xB3/256. blue:0xEC/256. alpha:.5];
50 | _circleView.hidden = YES;
51 |
52 | _circleView.layer.rasterizationScale = [UIScreen mainScreen].scale;
53 | _circleView.layer.shouldRasterize = YES;
54 | }
55 |
56 | {
57 | _dotView = [UIView new];
58 | [self addSubview:_dotView];
59 |
60 | _dotView.backgroundColor = [UIColor redColor];
61 | _dotView.hidden = YES;
62 |
63 | _dotView.layer.rasterizationScale = [UIScreen mainScreen].scale;
64 | _dotView.layer.shouldRasterize = YES;
65 | }
66 |
67 | {
68 | _textLabel = [UILabel new];
69 | [self addSubview:_textLabel];
70 |
71 | _textLabel.textColor = [UIColor blackColor];
72 | _textLabel.textAlignment = NSTextAlignmentCenter;
73 | _textLabel.font = [UIFont systemFontOfSize:[UIFont systemFontSize]];
74 | }
75 |
76 | {
77 | UITapGestureRecognizer *gesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(didTouch)];
78 |
79 | self.userInteractionEnabled = YES;
80 | [self addGestureRecognizer:gesture];
81 | }
82 | }
83 |
84 | - (void)layoutSubviews
85 | {
86 | [super layoutSubviews];
87 |
88 | _textLabel.frame = self.bounds;
89 |
90 | CGFloat sizeCircle = MIN(self.frame.size.width, self.frame.size.height);
91 | CGFloat sizeDot = sizeCircle;
92 |
93 | sizeCircle = sizeCircle * _circleRatio;
94 | sizeDot = sizeDot * _dotRatio;
95 |
96 | sizeCircle = roundf(sizeCircle);
97 | sizeDot = roundf(sizeDot);
98 |
99 | _circleView.frame = CGRectMake(0, 0, sizeCircle, sizeCircle);
100 | _circleView.center = CGPointMake(self.frame.size.width / 2., self.frame.size.height / 2.);
101 | _circleView.layer.cornerRadius = sizeCircle / 2.;
102 |
103 | _dotView.frame = CGRectMake(0, 0, sizeDot, sizeDot);
104 | _dotView.center = CGPointMake(self.frame.size.width / 2., (self.frame.size.height / 2.) +sizeDot * 2.5);
105 | _dotView.layer.cornerRadius = sizeDot / 2.;
106 | }
107 |
108 | - (void)setDate:(NSDate *)date
109 | {
110 | NSAssert(date != nil, @"date cannot be nil");
111 | NSAssert(_manager != nil, @"manager cannot be nil");
112 |
113 | self->_date = date;
114 | [self reload];
115 | }
116 |
117 | - (void)reload
118 | {
119 | static NSDateFormatter *dateFormatter = nil;
120 | if(!dateFormatter){
121 | dateFormatter = [_manager.dateHelper createDateFormatter];
122 | }
123 | [dateFormatter setDateFormat:self.dayFormat];
124 |
125 | _textLabel.text = [ dateFormatter stringFromDate:_date];
126 | [_manager.delegateManager prepareDayView:self];
127 | }
128 |
129 | - (void)didTouch
130 | {
131 | [_manager.delegateManager didTouchDayView:self];
132 | }
133 |
134 | - (NSString *)dayFormat
135 | {
136 | return self.manager.settings.zeroPaddedDayFormat ? @"dd" : @"d";
137 | }
138 |
139 | @end
140 |
--------------------------------------------------------------------------------
/JTCalendar/Views/JTCalendarMenuView.h:
--------------------------------------------------------------------------------
1 | //
2 | // JTCalendarMenuView.h
3 | // JTCalendar
4 | //
5 | // Created by Jonathan Tribouharet
6 | //
7 |
8 | #import
9 |
10 | #import "JTMenu.h"
11 |
12 | @interface JTCalendarMenuView : UIView
13 |
14 | @property (nonatomic, weak) JTCalendarManager *manager;
15 |
16 | @property (nonatomic) CGFloat contentRatio;
17 |
18 | @property (nonatomic, readonly) UIScrollView *scrollView;
19 |
20 | /*!
21 | * Must be call if override the class
22 | */
23 | - (void)commonInit;
24 |
25 | @end
26 |
--------------------------------------------------------------------------------
/JTCalendar/Views/JTCalendarMenuView.m:
--------------------------------------------------------------------------------
1 | //
2 | // JTCalendarMenuView.m
3 | // JTCalendar
4 | //
5 | // Created by Jonathan Tribouharet
6 | //
7 |
8 | #import "JTCalendarMenuView.h"
9 |
10 | #import "JTCalendarManager.h"
11 |
12 | typedef NS_ENUM(NSInteger, JTCalendarPageMode) {
13 | JTCalendarPageModeFull,
14 | JTCalendarPageModeCenter,
15 | JTCalendarPageModeCenterLeft,
16 | JTCalendarPageModeCenterRight
17 | };
18 |
19 | @interface JTCalendarMenuView (){
20 | CGSize _lastSize;
21 |
22 | UIView *_leftView;
23 | UIView *_centerView;
24 | UIView *_rightView;
25 |
26 | JTCalendarPageMode _pageMode;
27 | }
28 |
29 | @end
30 |
31 | @implementation JTCalendarMenuView
32 |
33 | - (instancetype)initWithFrame:(CGRect)frame
34 | {
35 | self = [super initWithFrame:frame];
36 | if(!self){
37 | return nil;
38 | }
39 |
40 | [self commonInit];
41 |
42 | return self;
43 | }
44 |
45 | - (instancetype)initWithCoder:(NSCoder *)aDecoder
46 | {
47 | self = [super initWithCoder:aDecoder];
48 | if(!self){
49 | return nil;
50 | }
51 |
52 | [self commonInit];
53 |
54 | return self;
55 | }
56 |
57 | - (void)commonInit
58 | {
59 | self.clipsToBounds = YES;
60 |
61 | _contentRatio = 1.;
62 |
63 | {
64 | _scrollView = [UIScrollView new];
65 | [self addSubview:_scrollView];
66 |
67 | _scrollView.showsHorizontalScrollIndicator = NO;
68 | _scrollView.showsVerticalScrollIndicator = NO;
69 | _scrollView.pagingEnabled = YES;
70 | _scrollView.delegate = self;
71 |
72 | _scrollView.clipsToBounds = NO;
73 | }
74 | }
75 |
76 | - (void)layoutSubviews
77 | {
78 | [super layoutSubviews];
79 | [self resizeViewsIfWidthChanged];
80 | }
81 |
82 | - (void)scrollViewDidScroll:(UIScrollView *)scrollView
83 | {
84 | if(_scrollView.contentSize.width <= 0){
85 | return;
86 | }
87 |
88 | [_manager.scrollManager updateHorizontalContentOffset:(_scrollView.contentOffset.x / _scrollView.contentSize.width)];
89 | }
90 |
91 | - (void)resizeViewsIfWidthChanged
92 | {
93 | CGSize size = self.frame.size;
94 | if(size.width != _lastSize.width){
95 | _lastSize = size;
96 |
97 | [self repositionViews];
98 | }
99 | else if(size.height != _lastSize.height){
100 | _lastSize = size;
101 |
102 | _scrollView.frame = CGRectMake(_scrollView.frame.origin.x, 0, _scrollView.frame.size.width, size.height);
103 | _scrollView.contentSize = CGSizeMake(_scrollView.contentSize.width, size.height);
104 |
105 | _leftView.frame = CGRectMake(_leftView.frame.origin.x, 0, _scrollView.frame.size.width, size.height);
106 | _centerView.frame = CGRectMake(_centerView.frame.origin.x, 0, _scrollView.frame.size.width, size.height);
107 | _rightView.frame = CGRectMake(_rightView.frame.origin.x, 0, _scrollView.frame.size.width, size.height);
108 | }
109 | }
110 |
111 | - (void)repositionViews
112 | {
113 | // Avoid vertical scrolling when the view is in a UINavigationController
114 | _scrollView.contentInset = UIEdgeInsetsZero;
115 |
116 | {
117 | CGFloat width = self.frame.size.width * _contentRatio;
118 | CGFloat x = (self.frame.size.width - width) / 2.;
119 | CGFloat height = self.frame.size.height;
120 |
121 | _scrollView.frame = CGRectMake(x, 0, width, height);
122 | _scrollView.contentSize = CGSizeMake(width, height);
123 | }
124 |
125 | CGSize size = _scrollView.frame.size;
126 |
127 | switch (_pageMode) {
128 | case JTCalendarPageModeFull:
129 | _scrollView.contentSize = CGSizeMake(size.width * 3, size.height);
130 |
131 | _leftView.frame = CGRectMake(0, 0, size.width, size.height);
132 | _centerView.frame = CGRectMake(size.width, 0, size.width, size.height);
133 | _rightView.frame = CGRectMake(size.width * 2, 0, size.width, size.height);
134 |
135 | _scrollView.contentOffset = CGPointMake(size.width, 0);
136 | break;
137 | case JTCalendarPageModeCenter:
138 | _scrollView.contentSize = size;
139 |
140 | _leftView.frame = CGRectMake(- size.width, 0, size.width, size.height);
141 | _centerView.frame = CGRectMake(0, 0, size.width, size.height);
142 | _rightView.frame = CGRectMake(size.width, 0, size.width, size.height);
143 |
144 | _scrollView.contentOffset = CGPointZero;
145 | break;
146 | case JTCalendarPageModeCenterLeft:
147 | _scrollView.contentSize = CGSizeMake(size.width * 2, size.height);
148 |
149 | _leftView.frame = CGRectMake(0, 0, size.width, size.height);
150 | _centerView.frame = CGRectMake(size.width, 0, size.width, size.height);
151 | _rightView.frame = CGRectMake(size.width * 2, 0, size.width, size.height);
152 |
153 | _scrollView.contentOffset = CGPointMake(size.width, 0);
154 | break;
155 | case JTCalendarPageModeCenterRight:
156 | _scrollView.contentSize = CGSizeMake(size.width * 2, size.height);
157 |
158 | _leftView.frame = CGRectMake(- size.width, 0, size.width, size.height);
159 | _centerView.frame = CGRectMake(0, 0, size.width, size.height);
160 | _rightView.frame = CGRectMake(size.width, 0, size.width, size.height);
161 |
162 | _scrollView.contentOffset = CGPointZero;
163 | break;
164 | }
165 | }
166 |
167 | - (void)setPreviousDate:(NSDate *)previousDate
168 | currentDate:(NSDate *)currentDate
169 | nextDate:(NSDate *)nextDate
170 | {
171 | NSAssert(currentDate != nil, @"currentDate cannot be nil");
172 | NSAssert(_manager != nil, @"manager cannot be nil");
173 |
174 | if(!_leftView){
175 | _leftView = [_manager.delegateManager buildMenuItemView];
176 | [_scrollView addSubview:_leftView];
177 |
178 | _centerView = [_manager.delegateManager buildMenuItemView];
179 | [_scrollView addSubview:_centerView];
180 |
181 | _rightView = [_manager.delegateManager buildMenuItemView];
182 | [_scrollView addSubview:_rightView];
183 | }
184 |
185 | [_manager.delegateManager prepareMenuItemView:_leftView date:previousDate];
186 | [_manager.delegateManager prepareMenuItemView:_centerView date:currentDate];
187 | [_manager.delegateManager prepareMenuItemView:_rightView date:nextDate];
188 |
189 | BOOL haveLeftPage = [_manager.delegateManager canDisplayPageWithDate:previousDate];
190 | BOOL haveRightPage = [_manager.delegateManager canDisplayPageWithDate:nextDate];
191 |
192 | if(_manager.settings.pageViewHideWhenPossible){
193 | _leftView.hidden = !haveLeftPage;
194 | _rightView.hidden = !haveRightPage;
195 | }
196 | else{
197 | _leftView.hidden = NO;
198 | _rightView.hidden = NO;
199 | }
200 | }
201 |
202 | - (void)updatePageMode:(NSUInteger)pageMode
203 | {
204 | if(_pageMode == pageMode){
205 | return;
206 | }
207 |
208 | _pageMode = pageMode;
209 | [self repositionViews];
210 | }
211 |
212 | @end
213 |
--------------------------------------------------------------------------------
/JTCalendar/Views/JTCalendarPageView.h:
--------------------------------------------------------------------------------
1 | //
2 | // JTCalendarPageView.h
3 | // JTCalendar
4 | //
5 | // Created by Jonathan Tribouharet
6 | //
7 |
8 | #import
9 |
10 | #import "JTCalendarPage.h"
11 |
12 | @interface JTCalendarPageView : UIView
13 |
14 | @property (nonatomic, weak) JTCalendarManager *manager;
15 |
16 | @property (nonatomic) NSDate *date;
17 |
18 | /*!
19 | * Must be call if override the class
20 | */
21 | - (void)commonInit;
22 |
23 | @end
24 |
--------------------------------------------------------------------------------
/JTCalendar/Views/JTCalendarPageView.m:
--------------------------------------------------------------------------------
1 | //
2 | // JTCalendarPageView.m
3 | // JTCalendar
4 | //
5 | // Created by Jonathan Tribouharet
6 | //
7 |
8 | #import "JTCalendarPageView.h"
9 |
10 | #import "JTCalendarManager.h"
11 |
12 | #define MAX_WEEKS_BY_MONTH 6
13 |
14 | @interface JTCalendarPageView (){
15 | UIView *_weekDayView;
16 | NSMutableArray *_weeksViews;
17 | NSUInteger _numberOfWeeksDisplayed;
18 | }
19 |
20 | @end
21 |
22 | @implementation JTCalendarPageView
23 |
24 | - (instancetype)initWithFrame:(CGRect)frame
25 | {
26 | self = [super initWithFrame:frame];
27 | if(!self){
28 | return nil;
29 | }
30 |
31 | [self commonInit];
32 |
33 | return self;
34 | }
35 |
36 | - (instancetype)initWithCoder:(NSCoder *)aDecoder
37 | {
38 | self = [super initWithCoder:aDecoder];
39 | if(!self){
40 | return nil;
41 | }
42 |
43 | [self commonInit];
44 |
45 | return self;
46 | }
47 |
48 | - (void)commonInit
49 | {
50 | // Maybe used in future
51 | }
52 |
53 | - (void)setDate:(NSDate *)date
54 | {
55 | NSAssert(_manager != nil, @"manager cannot be nil");
56 | NSAssert(date != nil, @"date cannot be nil");
57 |
58 | self->_date = date;
59 |
60 | [self reload];
61 | }
62 |
63 | - (void)reload
64 | {
65 | if(_manager.settings.pageViewHaveWeekDaysView && !_weekDayView){
66 | _weekDayView = [_manager.delegateManager buildWeekDayView];
67 | [self addSubview:_weekDayView];
68 | }
69 | _weekDayView.manager = _manager;
70 | [_weekDayView reload];
71 |
72 | if(!_weeksViews){
73 | _weeksViews = [NSMutableArray new];
74 |
75 | for(int i = 0; i < MAX_WEEKS_BY_MONTH; ++i){
76 | UIView *weekView = [_manager.delegateManager buildWeekView];
77 | [_weeksViews addObject:weekView];
78 | [self addSubview:weekView];
79 |
80 | weekView.manager = _manager;
81 | }
82 | }
83 |
84 | NSDate *weekDate = nil;
85 |
86 | if(_manager.settings.weekModeEnabled){
87 | _numberOfWeeksDisplayed = MIN(MAX(_manager.settings.pageViewWeekModeNumberOfWeeks, 1), MAX_WEEKS_BY_MONTH);
88 | weekDate = [_manager.dateHelper firstWeekDayOfWeek:_date];
89 | }
90 | else{
91 | _numberOfWeeksDisplayed = MIN(_manager.settings.pageViewNumberOfWeeks, MAX_WEEKS_BY_MONTH);
92 | if(_numberOfWeeksDisplayed == 0){
93 | _numberOfWeeksDisplayed = [_manager.dateHelper numberOfWeeks:_date];
94 | }
95 |
96 | weekDate = [_manager.dateHelper firstWeekDayOfMonth:_date];
97 | }
98 |
99 | for(NSUInteger i = 0; i < _numberOfWeeksDisplayed; i++){
100 | UIView *weekView = _weeksViews[i];
101 |
102 | weekView.hidden = NO;
103 |
104 | // Process the check on another month for the 1st, 4th and 5th weeks
105 | if(i == 0 || i >= 4){
106 | [weekView setStartDate:weekDate updateAnotherMonth:YES monthDate:_date];
107 | }
108 | else{
109 | [weekView setStartDate:weekDate updateAnotherMonth:NO monthDate:_date];
110 | }
111 |
112 | weekDate = [_manager.dateHelper addToDate:weekDate weeks:1];
113 | }
114 |
115 | for(NSUInteger i = _numberOfWeeksDisplayed; i < MAX_WEEKS_BY_MONTH; i++){
116 | UIView *weekView = _weeksViews[i];
117 |
118 | weekView.hidden = YES;
119 | }
120 |
121 | /*
122 | * Forces the view to re-render the height of each weekView
123 | * adjusted for the new `_numberOfWeeksDisplayed`
124 | */
125 | [self setNeedsLayout];
126 | }
127 |
128 | - (void)layoutSubviews
129 | {
130 | [super layoutSubviews];
131 |
132 | if(!_weeksViews){
133 | return;
134 | }
135 |
136 | CGFloat y = 0;
137 | CGFloat weekWidth = self.frame.size.width;
138 |
139 | if(_manager.settings.pageViewHaveWeekDaysView){
140 | CGFloat weekDayHeight = _weekDayView.frame.size.height; // Force use default height
141 |
142 | // Or use the same height than weeksViews
143 | if(weekDayHeight == 0 || _manager.settings.pageViewWeekDaysViewAutomaticHeight){
144 | weekDayHeight = self.frame.size.height / (_numberOfWeeksDisplayed + 1);
145 | }
146 |
147 | _weekDayView.frame = CGRectMake(0, 0, weekWidth, weekDayHeight);
148 | y = weekDayHeight;
149 | }
150 |
151 | CGFloat weekHeight = (self.frame.size.height - y) / _numberOfWeeksDisplayed;
152 |
153 | for(UIView *weekView in _weeksViews){
154 | weekView.frame = CGRectMake(0, y, weekWidth, weekHeight);
155 | y += weekHeight;
156 | }
157 | }
158 |
159 | @end
160 |
--------------------------------------------------------------------------------
/JTCalendar/Views/JTCalendarWeekDayView.h:
--------------------------------------------------------------------------------
1 | //
2 | // JTCalendarWeekDayView.h
3 | // JTCalendar
4 | //
5 | // Created by Jonathan Tribouharet
6 | //
7 |
8 | #import
9 |
10 | #import "JTCalendarWeekDay.h"
11 |
12 | @interface JTCalendarWeekDayView : UIView
13 |
14 | @property (nonatomic, weak) JTCalendarManager *manager;
15 |
16 | @property (nonatomic, readonly) NSArray *dayViews;
17 |
18 | /*!
19 | * Must be call if override the class
20 | */
21 | - (void)commonInit;
22 |
23 | /*!
24 | * Rebuild the view, must be call if you change `weekDayFormat` or `firstWeekday`
25 | */
26 | - (void)reload;
27 |
28 | @end
29 |
--------------------------------------------------------------------------------
/JTCalendar/Views/JTCalendarWeekDayView.m:
--------------------------------------------------------------------------------
1 | //
2 | // JTCalendarWeekDayView.m
3 | // JTCalendar
4 | //
5 | // Created by Jonathan Tribouharet
6 | //
7 |
8 | #import "JTCalendarWeekDayView.h"
9 |
10 | #import "JTCalendarManager.h"
11 |
12 | #define NUMBER_OF_DAY_BY_WEEK 7.
13 |
14 | @implementation JTCalendarWeekDayView
15 |
16 | - (instancetype)initWithFrame:(CGRect)frame
17 | {
18 | self = [super initWithFrame:frame];
19 | if(!self){
20 | return nil;
21 | }
22 |
23 | [self commonInit];
24 |
25 | return self;
26 | }
27 |
28 | - (instancetype)initWithCoder:(NSCoder *)aDecoder
29 | {
30 | self = [super initWithCoder:aDecoder];
31 | if(!self){
32 | return nil;
33 | }
34 |
35 | [self commonInit];
36 |
37 | return self;
38 | }
39 |
40 | - (void)commonInit
41 | {
42 | NSMutableArray *dayViews = [NSMutableArray new];
43 |
44 | for(int i = 0; i < NUMBER_OF_DAY_BY_WEEK; ++i){
45 | UILabel *label = [UILabel new];
46 | [self addSubview:label];
47 | [dayViews addObject:label];
48 |
49 | label.textAlignment = NSTextAlignmentCenter;
50 | label.textColor = [UIColor colorWithRed:152./256. green:147./256. blue:157./256. alpha:1.];
51 | label.font = [UIFont systemFontOfSize:11];
52 | }
53 |
54 | _dayViews = dayViews;
55 | }
56 |
57 | - (void)reload
58 | {
59 | NSAssert(_manager != nil, @"manager cannot be nil");
60 |
61 | NSDateFormatter *dateFormatter = [_manager.dateHelper createDateFormatter];
62 | NSMutableArray *days = nil;
63 |
64 | dateFormatter.timeZone = _manager.dateHelper.calendar.timeZone;
65 | dateFormatter.locale = _manager.dateHelper.calendar.locale;
66 |
67 | switch(_manager.settings.weekDayFormat) {
68 | case JTCalendarWeekDayFormatSingle:
69 | days = [[dateFormatter veryShortStandaloneWeekdaySymbols] mutableCopy];
70 | break;
71 | case JTCalendarWeekDayFormatShort:
72 | days = [[dateFormatter shortStandaloneWeekdaySymbols] mutableCopy];
73 | break;
74 | case JTCalendarWeekDayFormatFull:
75 | days = [[dateFormatter standaloneWeekdaySymbols] mutableCopy];
76 | break;
77 | }
78 |
79 | for(NSInteger i = 0; i < days.count; ++i){
80 | NSString *day = days[i];
81 | [days replaceObjectAtIndex:i withObject:[day uppercaseString]];
82 | }
83 |
84 | // Redorder days for be conform to calendar
85 | {
86 | NSCalendar *calendar = [_manager.dateHelper calendar];
87 | NSUInteger firstWeekday = (calendar.firstWeekday + 6) % 7; // Sunday == 1, Saturday == 7
88 |
89 | for(int i = 0; i < firstWeekday; ++i){
90 | id day = [days firstObject];
91 | [days removeObjectAtIndex:0];
92 | [days addObject:day];
93 | }
94 | }
95 |
96 | for(int i = 0; i < NUMBER_OF_DAY_BY_WEEK; ++i){
97 | UILabel *label = _dayViews[i];
98 | label.text = days[i];
99 | }
100 | }
101 |
102 | - (void)layoutSubviews
103 | {
104 | [super layoutSubviews];
105 |
106 | if(!_dayViews){
107 | return;
108 | }
109 |
110 | CGFloat x = 0;
111 | CGFloat dayWidth = self.frame.size.width / NUMBER_OF_DAY_BY_WEEK;
112 | CGFloat dayHeight = self.frame.size.height;
113 |
114 | for(UIView *dayView in _dayViews){
115 | dayView.frame = CGRectMake(x, 0, ceil(dayWidth), ceil(dayHeight));
116 | x += dayWidth;
117 | }
118 | }
119 |
120 | @end
121 |
--------------------------------------------------------------------------------
/JTCalendar/Views/JTCalendarWeekView.h:
--------------------------------------------------------------------------------
1 | //
2 | // JTCalendarWeekView.h
3 | // JTCalendar
4 | //
5 | // Created by Jonathan Tribouharet
6 | //
7 |
8 | #import
9 |
10 | #import "JTCalendarWeek.h"
11 |
12 | @interface JTCalendarWeekView : UIView
13 |
14 | @property (nonatomic, weak) JTCalendarManager *manager;
15 |
16 | @property (nonatomic, readonly) NSDate *startDate;
17 |
18 | /*!
19 | * Must be call if override the class
20 | */
21 | - (void)commonInit;
22 |
23 | @end
24 |
--------------------------------------------------------------------------------
/JTCalendar/Views/JTCalendarWeekView.m:
--------------------------------------------------------------------------------
1 | //
2 | // JTCalendarWeekView.m
3 | // JTCalendar
4 | //
5 | // Created by Jonathan Tribouharet
6 | //
7 |
8 | #import "JTCalendarWeekView.h"
9 |
10 | #import "JTCalendarManager.h"
11 |
12 | #define NUMBER_OF_DAY_BY_WEEK 7.
13 |
14 | @interface JTCalendarWeekView (){
15 | NSMutableArray *_daysViews;
16 | }
17 |
18 | @end
19 |
20 | @implementation JTCalendarWeekView
21 |
22 | - (instancetype)initWithFrame:(CGRect)frame
23 | {
24 | self = [super initWithFrame:frame];
25 | if(!self){
26 | return nil;
27 | }
28 |
29 | [self commonInit];
30 |
31 | return self;
32 | }
33 |
34 | - (instancetype)initWithCoder:(NSCoder *)aDecoder
35 | {
36 | self = [super initWithCoder:aDecoder];
37 | if(!self){
38 | return nil;
39 | }
40 |
41 | [self commonInit];
42 |
43 | return self;
44 | }
45 |
46 | - (void)commonInit
47 | {
48 | // Maybe used in future
49 | }
50 |
51 | - (void)setStartDate:(NSDate *)startDate updateAnotherMonth:(BOOL)enable monthDate:(NSDate *)monthDate
52 | {
53 | NSAssert(startDate != nil, @"startDate cannot be nil");
54 | NSAssert(_manager != nil, @"manager cannot be nil");
55 | if(enable){
56 | NSAssert(monthDate != nil, @"monthDate cannot be nil");
57 | }
58 |
59 | self->_startDate = startDate;
60 |
61 | [self createDayViews];
62 | [self reloadAndUpdateAnotherMonth:enable monthDate:monthDate];
63 | }
64 |
65 | - (void)reloadAndUpdateAnotherMonth:(BOOL)enable monthDate:(NSDate *)monthDate
66 | {
67 | NSDate *dayDate = _startDate;
68 |
69 | for(UIView *dayView in _daysViews){
70 | // Must done before setDate to dayView for `prepareDayView` method
71 | if(!enable){
72 | [dayView setIsFromAnotherMonth:NO];
73 | }
74 | else{
75 | if([_manager.dateHelper date:dayDate isTheSameMonthThan:monthDate]){
76 | [dayView setIsFromAnotherMonth:NO];
77 | }
78 | else{
79 | [dayView setIsFromAnotherMonth:YES];
80 | }
81 | }
82 |
83 | dayView.date = dayDate;
84 | dayDate = [_manager.dateHelper addToDate:dayDate days:1];
85 | }
86 | }
87 |
88 | - (void)createDayViews
89 | {
90 | if(!_daysViews){
91 | _daysViews = [NSMutableArray new];
92 |
93 | for(int i = 0; i < NUMBER_OF_DAY_BY_WEEK; ++i){
94 | UIView *dayView = [_manager.delegateManager buildDayView];
95 | [_daysViews addObject:dayView];
96 | [self addSubview:dayView];
97 |
98 | dayView.manager = _manager;
99 | }
100 | }
101 | }
102 |
103 | - (void)layoutSubviews
104 | {
105 | [super layoutSubviews];
106 |
107 | if(!_daysViews){
108 | return;
109 | }
110 |
111 | CGFloat x = 0;
112 | CGFloat dayWidth = self.frame.size.width / NUMBER_OF_DAY_BY_WEEK;
113 | CGFloat dayHeight = self.frame.size.height;
114 |
115 | for(UIView *dayView in _daysViews){
116 | dayView.frame = CGRectMake(x, 0, dayWidth, dayHeight);
117 | x += dayWidth;
118 | }
119 | }
120 |
121 | @end
122 |
--------------------------------------------------------------------------------
/JTCalendar/Views/JTHorizontalCalendarView.h:
--------------------------------------------------------------------------------
1 | //
2 | // JTHorizontalCalendar.h
3 | // JTCalendar
4 | //
5 | // Created by Jonathan Tribouharet
6 | //
7 |
8 | #import
9 |
10 | #import "JTContent.h"
11 |
12 | @interface JTHorizontalCalendarView : UIScrollView
13 |
14 | @property (nonatomic, weak) JTCalendarManager *manager;
15 |
16 | @property (nonatomic) NSDate *date;
17 |
18 | /*!
19 | * Must be call if override the class
20 | */
21 | - (void)commonInit;
22 |
23 | @end
24 |
--------------------------------------------------------------------------------
/JTCalendar/Views/JTHorizontalCalendarView.m:
--------------------------------------------------------------------------------
1 | //
2 | // JTHorizontalCalendar.m
3 | // JTCalendar
4 | //
5 | // Created by Jonathan Tribouharet
6 | //
7 |
8 | #import "JTHorizontalCalendarView.h"
9 |
10 | #import "JTCalendarManager.h"
11 |
12 | typedef NS_ENUM(NSInteger, JTCalendarPageMode) {
13 | JTCalendarPageModeFull,
14 | JTCalendarPageModeCenter,
15 | JTCalendarPageModeCenterLeft,
16 | JTCalendarPageModeCenterRight
17 | };
18 |
19 | @interface JTHorizontalCalendarView (){
20 | CGSize _lastSize;
21 |
22 | UIView *_leftView;
23 | UIView *_centerView;
24 | UIView *_rightView;
25 |
26 | JTCalendarPageMode _pageMode;
27 | }
28 |
29 | @end
30 |
31 | @implementation JTHorizontalCalendarView
32 |
33 | - (instancetype)initWithFrame:(CGRect)frame
34 | {
35 | self = [super initWithFrame:frame];
36 | if(!self){
37 | return nil;
38 | }
39 |
40 | [self commonInit];
41 |
42 | return self;
43 | }
44 |
45 | - (instancetype)initWithCoder:(NSCoder *)aDecoder
46 | {
47 | self = [super initWithCoder:aDecoder];
48 | if(!self){
49 | return nil;
50 | }
51 |
52 | [self commonInit];
53 |
54 | return self;
55 | }
56 |
57 | - (void)commonInit
58 | {
59 | self.showsHorizontalScrollIndicator = NO;
60 | self.showsVerticalScrollIndicator = NO;
61 | self.pagingEnabled = YES;
62 | self.clipsToBounds = YES;
63 | }
64 |
65 | - (void)layoutSubviews
66 | {
67 | [self resizeViewsIfWidthChanged];
68 | [self viewDidScroll];
69 | }
70 |
71 | - (void)resizeViewsIfWidthChanged
72 | {
73 | CGSize size = self.frame.size;
74 | if(size.width != _lastSize.width){
75 | _lastSize = size;
76 |
77 | [self repositionViews];
78 | }
79 | else if(size.height != _lastSize.height){
80 | _lastSize = size;
81 |
82 | _leftView.frame = CGRectMake(_leftView.frame.origin.x, 0, size.width, size.height);
83 | _centerView.frame = CGRectMake(_centerView.frame.origin.x, 0, size.width, size.height);
84 | _rightView.frame = CGRectMake(_rightView.frame.origin.x, 0, size.width, size.height);
85 |
86 | self.contentSize = CGSizeMake(self.contentSize.width, size.height);
87 | }
88 | }
89 |
90 | - (void)viewDidScroll
91 | {
92 | if(self.contentSize.width <= 0){
93 | return;
94 | }
95 |
96 | CGSize size = self.frame.size;
97 |
98 | switch (_pageMode) {
99 | case JTCalendarPageModeFull:
100 |
101 | if(self.contentOffset.x < size.width / 2.){
102 | [self loadPreviousPage];
103 | }
104 | else if(self.contentOffset.x > size.width * 1.5){
105 | [self loadNextPage];
106 | }
107 |
108 | break;
109 | case JTCalendarPageModeCenter:
110 |
111 | break;
112 | case JTCalendarPageModeCenterLeft:
113 |
114 | if(self.contentOffset.x < size.width / 2.){
115 | [self loadPreviousPage];
116 | }
117 |
118 | break;
119 | case JTCalendarPageModeCenterRight:
120 |
121 | if(self.contentOffset.x > size.width / 2.){
122 | [self loadNextPage];
123 | }
124 |
125 | break;
126 | }
127 |
128 | [_manager.scrollManager updateMenuContentOffset:(self.contentOffset.x / self.contentSize.width) pageMode:_pageMode];
129 | }
130 |
131 | - (void)loadPreviousPageWithAnimation
132 | {
133 | switch (_pageMode) {
134 | case JTCalendarPageModeCenterRight:
135 | case JTCalendarPageModeCenter:
136 | return;
137 | default:
138 | break;
139 | }
140 |
141 | CGSize size = self.frame.size;
142 | CGPoint point = CGPointMake(self.contentOffset.x - size.width, 0);
143 | [self setContentOffset:point animated:YES];
144 | }
145 |
146 | - (void)loadNextPageWithAnimation
147 | {
148 | switch (_pageMode) {
149 | case JTCalendarPageModeCenterLeft:
150 | case JTCalendarPageModeCenter:
151 | return;
152 | default:
153 | break;
154 | }
155 |
156 | CGSize size = self.frame.size;
157 | CGPoint point = CGPointMake(self.contentOffset.x + size.width, 0);
158 | [self setContentOffset:point animated:YES];
159 | }
160 |
161 | - (void)loadPreviousPage
162 | {
163 | NSDate *nextDate = [_manager.delegateManager dateForPreviousPageWithCurrentDate:_leftView.date];
164 |
165 | // Must be set before chaging date for PageView for updating day views
166 | self->_date = _leftView.date;
167 |
168 | UIView *tmpView = _rightView;
169 |
170 | _rightView = _centerView;
171 | _centerView = _leftView;
172 |
173 | _leftView = tmpView;
174 | _leftView.date = nextDate;
175 |
176 | [self updateMenuDates];
177 |
178 | JTCalendarPageMode previousPageMode = _pageMode;
179 |
180 | [self updatePageMode];
181 |
182 | CGSize size = self.frame.size;
183 |
184 | switch (_pageMode) {
185 | case JTCalendarPageModeFull:
186 |
187 | _leftView.frame = CGRectMake(0, 0, size.width, size.height);
188 | _centerView.frame = CGRectMake(size.width, 0, size.width, size.height);
189 | _rightView.frame = CGRectMake(size.width * 2, 0, size.width, size.height);
190 |
191 | if(previousPageMode == JTCalendarPageModeFull){
192 | self.contentOffset = CGPointMake(self.contentOffset.x + size.width, 0);
193 | }
194 | else if(previousPageMode == JTCalendarPageModeCenterLeft){
195 | self.contentOffset = CGPointMake(self.contentOffset.x + size.width, 0);
196 | }
197 |
198 | self.contentSize = CGSizeMake(size.width * 3, size.height);
199 |
200 | break;
201 | case JTCalendarPageModeCenter:
202 | // Not tested
203 |
204 | _leftView.frame = CGRectMake(- size.width, 0, size.width, size.height);
205 | _centerView.frame = CGRectMake(0, 0, size.width, size.height);
206 | _rightView.frame = CGRectMake(size.width, 0, size.width, size.height);
207 |
208 | self.contentSize = size;
209 |
210 | break;
211 | case JTCalendarPageModeCenterLeft:
212 |
213 | _leftView.frame = CGRectMake(0, 0, size.width, size.height);
214 | _centerView.frame = CGRectMake(size.width, 0, size.width, size.height);
215 | _rightView.frame = CGRectMake(size.width * 2, 0, size.width, size.height);
216 |
217 | self.contentOffset = CGPointMake(self.contentOffset.x + size.width, 0);
218 | self.contentSize = CGSizeMake(size.width * 2, size.height);
219 |
220 | break;
221 | case JTCalendarPageModeCenterRight:
222 |
223 | _leftView.frame = CGRectMake(- size.width, 0, size.width, size.height);
224 | _centerView.frame = CGRectMake(0, 0, size.width, size.height);
225 | _rightView.frame = CGRectMake(size.width, 0, size.width, size.height);
226 |
227 | self.contentSize = CGSizeMake(size.width * 2, size.height);
228 |
229 | break;
230 | }
231 |
232 | // Update dayViews becuase current month changed
233 | [_rightView reload];
234 | [_centerView reload];
235 |
236 | if(_manager.delegate && [_manager.delegate respondsToSelector:@selector(calendarDidLoadPreviousPage:)]){
237 | [_manager.delegate calendarDidLoadPreviousPage:_manager];
238 | }
239 | }
240 |
241 | - (void)loadNextPage
242 | {
243 | NSDate *nextDate = [_manager.delegateManager dateForNextPageWithCurrentDate:_rightView.date];
244 |
245 | // Must be set before chaging date for PageView for updating day views
246 | self->_date = _rightView.date;
247 |
248 | UIView *tmpView = _leftView;
249 |
250 | _leftView = _centerView;
251 | _centerView = _rightView;
252 |
253 | _rightView = tmpView;
254 | _rightView.date = nextDate;
255 |
256 | [self updateMenuDates];
257 |
258 | JTCalendarPageMode previousPageMode = _pageMode;
259 |
260 | [self updatePageMode];
261 |
262 | CGSize size = self.frame.size;
263 |
264 | switch (_pageMode) {
265 | case JTCalendarPageModeFull:
266 |
267 | _leftView.frame = CGRectMake(0, 0, size.width, size.height);
268 | _centerView.frame = CGRectMake(size.width, 0, size.width, size.height);
269 | _rightView.frame = CGRectMake(size.width * 2, 0, size.width, size.height);
270 |
271 | if(previousPageMode == JTCalendarPageModeFull){
272 | self.contentOffset = CGPointMake(self.contentOffset.x - size.width, 0);
273 | }
274 | self.contentSize = CGSizeMake(size.width * 3, size.height);
275 |
276 | break;
277 | case JTCalendarPageModeCenter:
278 | // Not tested
279 |
280 | _leftView.frame = CGRectMake(- size.width, 0, size.width, size.height);
281 | _centerView.frame = CGRectMake(0, 0, size.width, size.height);
282 | _rightView.frame = CGRectMake(size.width, 0, size.width, size.height);
283 |
284 | self.contentSize = size;
285 |
286 | break;
287 | case JTCalendarPageModeCenterLeft:
288 |
289 | _leftView.frame = CGRectMake(0, 0, size.width, size.height);
290 | _centerView.frame = CGRectMake(size.width, 0, size.width, size.height);
291 | _rightView.frame = CGRectMake(size.width * 2, 0, size.width, size.height);
292 |
293 | if(previousPageMode != JTCalendarPageModeCenterRight){
294 | self.contentOffset = CGPointMake(self.contentOffset.x - size.width, 0);
295 | }
296 |
297 | // Must be set a the end else the scroll freeze
298 | self.contentSize = CGSizeMake(size.width * 2, size.height);
299 |
300 | break;
301 | case JTCalendarPageModeCenterRight:
302 | // Not tested
303 |
304 | _leftView.frame = CGRectMake(- size.width, 0, size.width, size.height);
305 | _centerView.frame = CGRectMake(0, 0, size.width, size.height);
306 | _rightView.frame = CGRectMake(size.width, 0, size.width, size.height);
307 |
308 | self.contentSize = CGSizeMake(size.width * 2, size.height);
309 |
310 | break;
311 | }
312 |
313 | // Update dayViews becuase current month changed
314 | [_leftView reload];
315 | [_centerView reload];
316 |
317 | if(_manager.delegate && [_manager.delegate respondsToSelector:@selector(calendarDidLoadNextPage:)]){
318 | [_manager.delegate calendarDidLoadNextPage:_manager];
319 | }
320 | }
321 |
322 | - (void)setDate:(NSDate *)date
323 | {
324 | NSAssert(date != nil, @"date cannot be nil");
325 | NSAssert(_manager != nil, @"manager cannot be nil");
326 |
327 | self->_date = date;
328 |
329 | if(!_leftView){
330 | _leftView = [_manager.delegateManager buildPageView];
331 | [self addSubview:_leftView];
332 |
333 | _centerView = [_manager.delegateManager buildPageView];
334 | [self addSubview:_centerView];
335 |
336 | _rightView = [_manager.delegateManager buildPageView];
337 | [self addSubview:_rightView];
338 |
339 | [self updateManagerForViews];
340 | }
341 |
342 | _leftView.date = [_manager.delegateManager dateForPreviousPageWithCurrentDate:date];
343 | _centerView.date = date;
344 | _rightView.date = [_manager.delegateManager dateForNextPageWithCurrentDate:date];
345 |
346 | [self updateMenuDates];
347 |
348 | [self updatePageMode];
349 | [self repositionViews];
350 | }
351 |
352 | - (void)setManager:(JTCalendarManager *)manager
353 | {
354 | self->_manager = manager;
355 | [self updateManagerForViews];
356 | }
357 |
358 | - (void)updateManagerForViews
359 | {
360 | if(!_manager || !_leftView){
361 | return;
362 | }
363 |
364 | _leftView.manager = _manager;
365 | _centerView.manager = _manager;
366 | _rightView.manager = _manager;
367 | }
368 |
369 | - (void)updatePageMode
370 | {
371 | BOOL haveLeftPage = [_manager.delegateManager canDisplayPageWithDate:_leftView.date];
372 | BOOL haveRightPage = [_manager.delegateManager canDisplayPageWithDate:_rightView.date];
373 |
374 | if(haveLeftPage && haveRightPage){
375 | _pageMode = JTCalendarPageModeFull;
376 | }
377 | else if(!haveLeftPage && !haveRightPage){
378 | _pageMode = JTCalendarPageModeCenter;
379 | }
380 | else if(!haveLeftPage){
381 | _pageMode = JTCalendarPageModeCenterRight;
382 | }
383 | else{
384 | _pageMode = JTCalendarPageModeCenterLeft;
385 | }
386 |
387 | if(_manager.settings.pageViewHideWhenPossible){
388 | _leftView.hidden = !haveLeftPage;
389 | _rightView.hidden = !haveRightPage;
390 | }
391 | else{
392 | _leftView.hidden = NO;
393 | _rightView.hidden = NO;
394 | }
395 | }
396 |
397 | - (void)repositionViews
398 | {
399 | CGSize size = self.frame.size;
400 | self.contentInset = UIEdgeInsetsZero;
401 |
402 | switch (_pageMode) {
403 | case JTCalendarPageModeFull:
404 | self.contentSize = CGSizeMake(size.width * 3, size.height);
405 |
406 | _leftView.frame = CGRectMake(0, 0, size.width, size.height);
407 | _centerView.frame = CGRectMake(size.width, 0, size.width, size.height);
408 | _rightView.frame = CGRectMake(size.width * 2, 0, size.width, size.height);
409 |
410 | self.contentOffset = CGPointMake(size.width, 0);
411 | break;
412 | case JTCalendarPageModeCenter:
413 | self.contentSize = size;
414 |
415 | _leftView.frame = CGRectMake(- size.width, 0, size.width, size.height);
416 | _centerView.frame = CGRectMake(0, 0, size.width, size.height);
417 | _rightView.frame = CGRectMake(size.width, 0, size.width, size.height);
418 |
419 | self.contentOffset = CGPointZero;
420 | break;
421 | case JTCalendarPageModeCenterLeft:
422 | self.contentSize = CGSizeMake(size.width * 2, size.height);
423 |
424 | _leftView.frame = CGRectMake(0, 0, size.width, size.height);
425 | _centerView.frame = CGRectMake(size.width, 0, size.width, size.height);
426 | _rightView.frame = CGRectMake(size.width * 2, 0, size.width, size.height);
427 |
428 | self.contentOffset = CGPointMake(size.width, 0);
429 | break;
430 | case JTCalendarPageModeCenterRight:
431 | self.contentSize = CGSizeMake(size.width * 2, size.height);
432 |
433 | _leftView.frame = CGRectMake(- size.width, 0, size.width, size.height);
434 | _centerView.frame = CGRectMake(0, 0, size.width, size.height);
435 | _rightView.frame = CGRectMake(size.width, 0, size.width, size.height);
436 |
437 | self.contentOffset = CGPointZero;
438 | break;
439 | }
440 | }
441 |
442 | - (void)updateMenuDates
443 | {
444 | [_manager.scrollManager setMenuPreviousDate:_leftView.date
445 | currentDate:_centerView.date
446 | nextDate:_rightView.date];
447 | }
448 |
449 | @end
450 |
--------------------------------------------------------------------------------
/JTCalendar/Views/JTVerticalCalendarView.h:
--------------------------------------------------------------------------------
1 | //
2 | // JTVerticalCalendarView.h
3 | // JTCalendar
4 | //
5 | // Created by Jonathan Tribouharet
6 | //
7 |
8 | #import
9 |
10 | #import "JTContent.h"
11 |
12 | @interface JTVerticalCalendarView : UIScrollView
13 |
14 | @property (nonatomic, weak) JTCalendarManager *manager;
15 |
16 | @property (nonatomic) NSDate *date;
17 |
18 | /*!
19 | * Must be call if override the class
20 | */
21 | - (void)commonInit;
22 |
23 | @end
24 |
--------------------------------------------------------------------------------
/JTCalendar/Views/JTVerticalCalendarView.m:
--------------------------------------------------------------------------------
1 | //
2 | // JTVerticalCalendarView.m
3 | // JTCalendar
4 | //
5 | // Created by Jonathan Tribouharet
6 | //
7 |
8 | #import "JTVerticalCalendarView.h"
9 |
10 | #import "JTCalendarManager.h"
11 |
12 | typedef NS_ENUM(NSInteger, JTCalendarPageMode) {
13 | JTCalendarPageModeFull,
14 | JTCalendarPageModeCenter,
15 | JTCalendarPageModeCenterLeft,
16 | JTCalendarPageModeCenterRight
17 | };
18 |
19 | @interface JTVerticalCalendarView (){
20 | CGSize _lastSize;
21 |
22 | UIView *_leftView;
23 | UIView *_centerView;
24 | UIView *_rightView;
25 |
26 | JTCalendarPageMode _pageMode;
27 | }
28 |
29 | @end
30 |
31 | @implementation JTVerticalCalendarView
32 |
33 | - (instancetype)initWithFrame:(CGRect)frame
34 | {
35 | self = [super initWithFrame:frame];
36 | if(!self){
37 | return nil;
38 | }
39 |
40 | [self commonInit];
41 |
42 | return self;
43 | }
44 |
45 | - (instancetype)initWithCoder:(NSCoder *)aDecoder
46 | {
47 | self = [super initWithCoder:aDecoder];
48 | if(!self){
49 | return nil;
50 | }
51 |
52 | [self commonInit];
53 |
54 | return self;
55 | }
56 |
57 | - (void)commonInit
58 | {
59 | self.showsHorizontalScrollIndicator = NO;
60 | self.showsVerticalScrollIndicator = NO;
61 | self.pagingEnabled = YES;
62 | self.clipsToBounds = YES;
63 | }
64 |
65 | - (void)layoutSubviews
66 | {
67 | [self resizeViewsIfWidthChanged];
68 | [self viewDidScroll];
69 | }
70 |
71 | - (void)resizeViewsIfWidthChanged
72 | {
73 | CGSize size = self.frame.size;
74 | if(size.height != _lastSize.height){
75 | _lastSize = size;
76 |
77 | [self repositionViews];
78 | }
79 | else if(size.width != _lastSize.width){
80 | _lastSize = size;
81 |
82 | _leftView.frame = CGRectMake(0, _leftView.frame.origin.y, size.width, size.height);
83 | _centerView.frame = CGRectMake(0, _centerView.frame.origin.y, size.width, size.height);
84 | _rightView.frame = CGRectMake(0, _rightView.frame.origin.y, size.width, size.height);
85 |
86 | self.contentSize = CGSizeMake(size.width, self.contentSize.height);
87 | }
88 | }
89 |
90 | - (void)viewDidScroll
91 | {
92 | if(self.contentSize.height <= 0){
93 | return;
94 | }
95 |
96 | CGSize size = self.frame.size;
97 |
98 | switch (_pageMode) {
99 | case JTCalendarPageModeFull:
100 |
101 | if(self.contentOffset.y < size.height / 2.){
102 | [self loadPreviousPage];
103 | }
104 | else if(self.contentOffset.y > size.height * 1.5){
105 | [self loadNextPage];
106 | }
107 |
108 | break;
109 | case JTCalendarPageModeCenter:
110 |
111 | break;
112 | case JTCalendarPageModeCenterLeft:
113 |
114 | if(self.contentOffset.y < size.height / 2.){
115 | [self loadPreviousPage];
116 | }
117 |
118 | break;
119 | case JTCalendarPageModeCenterRight:
120 |
121 | if(self.contentOffset.y > size.height / 2.){
122 | [self loadNextPage];
123 | }
124 |
125 | break;
126 | }
127 |
128 | [_manager.scrollManager updateMenuContentOffset:(self.contentOffset.y / self.contentSize.height) pageMode:_pageMode];
129 | }
130 |
131 | - (void)loadPreviousPageWithAnimation
132 | {
133 | switch (_pageMode) {
134 | case JTCalendarPageModeCenterRight:
135 | case JTCalendarPageModeCenter:
136 | return;
137 | default:
138 | break;
139 | }
140 |
141 | CGSize size = self.frame.size;
142 | CGPoint point = CGPointMake(0, self.contentOffset.y - size.height);
143 | [self setContentOffset:point animated:YES];
144 | }
145 |
146 | - (void)loadNextPageWithAnimation
147 | {
148 | switch (_pageMode) {
149 | case JTCalendarPageModeCenterLeft:
150 | case JTCalendarPageModeCenter:
151 | return;
152 | default:
153 | break;
154 | }
155 |
156 | CGSize size = self.frame.size;
157 | CGPoint point = CGPointMake(0, self.contentOffset.y + size.height);
158 | [self setContentOffset:point animated:YES];
159 | }
160 |
161 | - (void)loadPreviousPage
162 | {
163 | NSDate *nextDate = [_manager.delegateManager dateForPreviousPageWithCurrentDate:_leftView.date];
164 |
165 | // Must be set before chaging date for PageView for updating day views
166 | self->_date = _leftView.date;
167 |
168 | UIView *tmpView = _rightView;
169 |
170 | _rightView = _centerView;
171 | _centerView = _leftView;
172 |
173 | _leftView = tmpView;
174 | _leftView.date = nextDate;
175 |
176 | [self updateMenuDates];
177 |
178 | JTCalendarPageMode previousPageMode = _pageMode;
179 |
180 | [self updatePageMode];
181 |
182 | CGSize size = self.frame.size;
183 |
184 | switch (_pageMode) {
185 | case JTCalendarPageModeFull:
186 |
187 | _leftView.frame = CGRectMake(0, 0, size.width, size.height);
188 | _centerView.frame = CGRectMake(0, size.height, size.width, size.height);
189 | _rightView.frame = CGRectMake(0, size.height * 2, size.width, size.height);
190 |
191 | if(previousPageMode == JTCalendarPageModeFull){
192 | self.contentOffset = CGPointMake(0, self.contentOffset.y + size.height);
193 | }
194 | else if(previousPageMode == JTCalendarPageModeCenterLeft){
195 | self.contentOffset = CGPointMake(0, self.contentOffset.y + size.height);
196 | }
197 |
198 | self.contentSize = CGSizeMake(size.width, size.height * 3);
199 |
200 | break;
201 | case JTCalendarPageModeCenter:
202 | // Not tested
203 |
204 | _leftView.frame = CGRectMake(0, - size.height, size.width, size.height);
205 | _centerView.frame = CGRectMake(0, 0, size.width, size.height);
206 | _rightView.frame = CGRectMake(0, size.height, size.width, size.height);
207 |
208 | self.contentSize = size;
209 |
210 | break;
211 | case JTCalendarPageModeCenterLeft:
212 |
213 | _leftView.frame = CGRectMake(0, 0, size.width, size.height);
214 | _centerView.frame = CGRectMake(0, size.height, size.width, size.height);
215 | _rightView.frame = CGRectMake(0, size.height * 2, size.width, size.height);
216 |
217 | self.contentOffset = CGPointMake(0, self.contentOffset.y + size.height);
218 | self.contentSize = CGSizeMake(size.width, size.height * 2);
219 |
220 | break;
221 | case JTCalendarPageModeCenterRight:
222 |
223 | _leftView.frame = CGRectMake(0, - size.height, size.width, size.height);
224 | _centerView.frame = CGRectMake(0, 0, size.width, size.height);
225 | _rightView.frame = CGRectMake(0, size.height, size.width, size.height);
226 |
227 | self.contentSize = CGSizeMake(size.width, size.height * 2);
228 |
229 | break;
230 | }
231 |
232 | // Update subviews
233 | [_rightView reload];
234 | [_centerView reload];
235 |
236 | if(_manager.delegate && [_manager.delegate respondsToSelector:@selector(calendarDidLoadPreviousPage:)]){
237 | [_manager.delegate calendarDidLoadPreviousPage:_manager];
238 | }
239 | }
240 |
241 | - (void)loadNextPage
242 | {
243 | NSDate *nextDate = [_manager.delegateManager dateForNextPageWithCurrentDate:_rightView.date];
244 |
245 | // Must be set before chaging date for PageView for updating day views
246 | self->_date = _rightView.date;
247 |
248 | UIView *tmpView = _leftView;
249 |
250 | _leftView = _centerView;
251 | _centerView = _rightView;
252 |
253 | _rightView = tmpView;
254 | _rightView.date = nextDate;
255 |
256 | [self updateMenuDates];
257 |
258 | JTCalendarPageMode previousPageMode = _pageMode;
259 |
260 | [self updatePageMode];
261 |
262 | CGSize size = self.frame.size;
263 |
264 | switch (_pageMode) {
265 | case JTCalendarPageModeFull:
266 |
267 | _leftView.frame = CGRectMake(0, 0, size.width, size.height);
268 | _centerView.frame = CGRectMake(0, size.height, size.width, size.height);
269 | _rightView.frame = CGRectMake(0, size.height * 2, size.width, size.height);
270 |
271 | if(previousPageMode == JTCalendarPageModeFull){
272 | self.contentOffset = CGPointMake(0, self.contentOffset.y - size.height);
273 | }
274 | self.contentSize = CGSizeMake(size.width, size.height * 3);
275 |
276 | break;
277 | case JTCalendarPageModeCenter:
278 | // Not tested
279 |
280 | _leftView.frame = CGRectMake(0, - size.height, size.width, size.height);
281 | _centerView.frame = CGRectMake(0, 0, size.width, size.height);
282 | _rightView.frame = CGRectMake(0, size.height, size.width, size.height);
283 |
284 | self.contentSize = size;
285 |
286 | break;
287 | case JTCalendarPageModeCenterLeft:
288 |
289 | _leftView.frame = CGRectMake(0, 0, size.width, size.height);
290 | _centerView.frame = CGRectMake(0, size.height, size.width, size.height);
291 | _rightView.frame = CGRectMake(0, size.height * 2, size.width, size.height);
292 |
293 | if(previousPageMode != JTCalendarPageModeCenterRight){
294 | // self.contentOffset = CGPointMake(0, self.contentOffset.x - size.width);
295 | }
296 |
297 | // Must be set a the end else the scroll freeze
298 | self.contentSize = CGSizeMake(size.width, size.height * 2);
299 |
300 | break;
301 | case JTCalendarPageModeCenterRight:
302 | // Not tested
303 |
304 | _leftView.frame = CGRectMake(0, - size.height, size.width, size.height);
305 | _centerView.frame = CGRectMake(0, 0, size.width, size.height);
306 | _rightView.frame = CGRectMake(0, size.height, size.width, size.height);
307 |
308 | self.contentSize = CGSizeMake(size.width, size.height * 2);
309 |
310 | break;
311 | }
312 |
313 | // Update subviews
314 | [_leftView reload];
315 | [_centerView reload];
316 |
317 | if(_manager.delegate && [_manager.delegate respondsToSelector:@selector(calendarDidLoadNextPage:)]){
318 | [_manager.delegate calendarDidLoadNextPage:_manager];
319 | }
320 | }
321 |
322 | - (void)setDate:(NSDate *)date
323 | {
324 | NSAssert(date != nil, @"date cannot be nil");
325 | NSAssert(_manager != nil, @"manager cannot be nil");
326 |
327 | self->_date = date;
328 |
329 | if(!_leftView){
330 | _leftView = [_manager.delegateManager buildPageView];
331 | [self addSubview:_leftView];
332 |
333 | _centerView = [_manager.delegateManager buildPageView];
334 | [self addSubview:_centerView];
335 |
336 | _rightView = [_manager.delegateManager buildPageView];
337 | [self addSubview:_rightView];
338 |
339 | [self updateManagerForViews];
340 | }
341 |
342 | _leftView.date = [_manager.delegateManager dateForPreviousPageWithCurrentDate:date];
343 | _centerView.date = date;
344 | _rightView.date = [_manager.delegateManager dateForNextPageWithCurrentDate:date];
345 |
346 | [self updateMenuDates];
347 |
348 | [self updatePageMode];
349 | [self repositionViews];
350 | }
351 |
352 | - (void)setManager:(JTCalendarManager *)manager
353 | {
354 | self->_manager = manager;
355 | [self updateManagerForViews];
356 | }
357 |
358 | - (void)updateManagerForViews
359 | {
360 | if(!_manager || !_leftView){
361 | return;
362 | }
363 |
364 | _leftView.manager = _manager;
365 | _centerView.manager = _manager;
366 | _rightView.manager = _manager;
367 | }
368 |
369 | - (void)updatePageMode
370 | {
371 | BOOL haveLeftPage = [_manager.delegateManager canDisplayPageWithDate:_leftView.date];
372 | BOOL haveRightPage = [_manager.delegateManager canDisplayPageWithDate:_rightView.date];
373 |
374 | if(haveLeftPage && haveRightPage){
375 | _pageMode = JTCalendarPageModeFull;
376 | }
377 | else if(!haveLeftPage && !haveRightPage){
378 | _pageMode = JTCalendarPageModeCenter;
379 | }
380 | else if(!haveLeftPage){
381 | _pageMode = JTCalendarPageModeCenterRight;
382 | }
383 | else{
384 | _pageMode = JTCalendarPageModeCenterLeft;
385 | }
386 |
387 | if(_manager.settings.pageViewHideWhenPossible){
388 | _leftView.hidden = !haveLeftPage;
389 | _rightView.hidden = !haveRightPage;
390 | }
391 | else{
392 | _leftView.hidden = NO;
393 | _rightView.hidden = NO;
394 | }
395 | }
396 |
397 | - (void)repositionViews
398 | {
399 | CGSize size = self.frame.size;
400 | self.contentInset = UIEdgeInsetsZero;
401 |
402 | switch (_pageMode) {
403 | case JTCalendarPageModeFull:
404 | self.contentSize = CGSizeMake(size.width, size.height * 3);
405 |
406 | _leftView.frame = CGRectMake(0, 0, size.width, size.height);
407 | _centerView.frame = CGRectMake(0, size.height, size.width, size.height);
408 | _rightView.frame = CGRectMake(0, size.height * 2, size.width, size.height);
409 |
410 | self.contentOffset = CGPointMake(0, size.height);
411 | break;
412 | case JTCalendarPageModeCenter:
413 | self.contentSize = size;
414 |
415 | _leftView.frame = CGRectMake(0, - size.height, size.width, size.height);
416 | _centerView.frame = CGRectMake(0, 0, size.width, size.height);
417 | _rightView.frame = CGRectMake(0, size.height, size.width, size.height);
418 |
419 | self.contentOffset = CGPointZero;
420 | break;
421 | case JTCalendarPageModeCenterLeft:
422 | self.contentSize = CGSizeMake(size.width, size.height * 2);
423 |
424 | _leftView.frame = CGRectMake(0, 0, size.width, size.height);
425 | _centerView.frame = CGRectMake(0, size.height, size.width, size.height);
426 | _rightView.frame = CGRectMake(0, size.height * 2, size.width, size.height);
427 |
428 | self.contentOffset = CGPointMake(0, size.height);
429 | break;
430 | case JTCalendarPageModeCenterRight:
431 | self.contentSize = CGSizeMake(size.width, size.height * 2);
432 |
433 | _leftView.frame = CGRectMake(0, - size.height, size.width, size.height);
434 | _centerView.frame = CGRectMake(0, 0, size.width, size.height);
435 | _rightView.frame = CGRectMake(0, size.height, size.width, size.height);
436 |
437 | self.contentOffset = CGPointZero;
438 | break;
439 | }
440 | }
441 |
442 | - (void)updateMenuDates
443 | {
444 | [_manager.scrollManager setMenuPreviousDate:_leftView.date
445 | currentDate:_centerView.date
446 | nextDate:_rightView.date];
447 | }
448 | @end
449 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2015 Jonathan VUKOVICH TRIBOUHARET
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy
4 | of this software and associated documentation files (the "Software"), to deal
5 | in the Software without restriction, including without limitation the rights
6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | copies of the Software, and to permit persons to whom the Software is
8 | furnished to do so, subject to the following conditions:
9 |
10 | The above copyright notice and this permission notice shall be included in
11 | all copies or substantial portions of the Software.
12 |
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | THE SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # JTCalendar
2 |
3 | [](https://travis-ci.org/jonathantribouharet/JTCalendar)
4 | 
5 | [](https://github.com/Carthage/Carthage)
6 | 
7 | 
8 |
9 | JTCalendar is an easily customizable calendar control for iOS.
10 |
11 | ## Installation
12 |
13 | With [CocoaPods](http://cocoapods.org), add this line to your Podfile.
14 |
15 | pod 'JTCalendar', '~> 2.0'
16 |
17 | ### Carthage
18 |
19 | To use this project with [Carthage](https://github.com/Carthage/Carthage), add this line to your Cartfile.
20 |
21 | github "jonathantribouharet/JTCalendar" ~> 2.2
22 |
23 | ## Screenshots
24 |
25 | 
26 | 
27 |
28 | ### Warning
29 |
30 | The part below the calendar in the 2nd screenshot is not provided.
31 |
32 | ## Features
33 |
34 | - horizontal and vertical calendar
35 | - highly customizable either by subclassing default class provided or by creating your own class implementing a protocol
36 | - support internationalization
37 | - week view mode
38 | - limited range, you can define a start and an end to you calendar
39 |
40 | ## Usage
41 |
42 | ### Basic usage
43 |
44 | You have to create two views in your `UIViewController`:
45 |
46 | - The first view is `JTCalendarMenuView` and it represents the part with the months names. This view is optional.
47 | - The second view is `JTHorizontalCalendarView` or `JTVerticalCalendarView`, it represents the calendar itself.
48 |
49 | Your `UIViewController` have to implement `JTCalendarDelegate`, all methods are optional.
50 |
51 | ```objective-c
52 | #import
53 |
54 | #import
55 |
56 | @interface ViewController : UIViewController
57 |
58 | @property (weak, nonatomic) IBOutlet JTCalendarMenuView *calendarMenuView;
59 | @property (weak, nonatomic) IBOutlet JTHorizontalCalendarView *calendarContentView;
60 |
61 | @property (strong, nonatomic) JTCalendarManager *calendarManager;
62 |
63 | @end
64 | ```
65 |
66 | `JTCalendarManager` is used to coordinate `calendarMenuView` and `calendarContentView` and provide a default behavior.
67 |
68 | ```objective-c
69 | @implementation ViewController
70 |
71 | - (void)viewDidLoad
72 | {
73 | [super viewDidLoad];
74 |
75 | _calendarManager = [JTCalendarManager new];
76 | _calendarManager.delegate = self;
77 |
78 | [_calendarManager setMenuView:_calendarMenuView];
79 | [_calendarManager setContentView:_calendarContentView];
80 | [_calendarManager setDate:[NSDate date]];
81 | }
82 |
83 | @end
84 |
85 | ```
86 |
87 | The Example project contains some use cases you may check before asking questions.
88 |
89 | ### Advanced usage
90 |
91 | Even if all methods of `JTCalendarManager` are optional you won't get far without implementing at least the two next methods:
92 | - `calendar:prepareDayView:` this method is used to customize the design of the day view for a specific date. This method is called each time a new date is set in a dayView or each time the current page change. You can force the call to this method by calling `[_calendarManager reload];`.
93 |
94 |
95 | ```objective-c
96 | - (void)calendar:(JTCalendarManager *)calendar prepareDayView:(JTCalendarDayView *)dayView
97 | {
98 | dayView.hidden = NO;
99 |
100 | // Test if the dayView is from another month than the page
101 | // Use only in month mode for indicate the day of the previous or next month
102 | if([dayView isFromAnotherMonth]){
103 | dayView.hidden = YES;
104 | }
105 | // Today
106 | else if([_calendarManager.dateHelper date:[NSDate date] isTheSameDayThan:dayView.date]){
107 | dayView.circleView.hidden = NO;
108 | dayView.circleView.backgroundColor = [UIColor blueColor];
109 | dayView.dotView.backgroundColor = [UIColor whiteColor];
110 | dayView.textLabel.textColor = [UIColor whiteColor];
111 | }
112 | // Selected date
113 | else if(_dateSelected && [_calendarManager.dateHelper date:_dateSelected isTheSameDayThan:dayView.date]){
114 | dayView.circleView.hidden = NO;
115 | dayView.circleView.backgroundColor = [UIColor redColor];
116 | dayView.dotView.backgroundColor = [UIColor whiteColor];
117 | dayView.textLabel.textColor = [UIColor whiteColor];
118 | }
119 | // Another day of the current month
120 | else{
121 | dayView.circleView.hidden = YES;
122 | dayView.dotView.backgroundColor = [UIColor redColor];
123 | dayView.textLabel.textColor = [UIColor blackColor];
124 | }
125 |
126 | // Your method to test if a date have an event for example
127 | if([self haveEventForDay:dayView.date]){
128 | dayView.dotView.hidden = NO;
129 | }
130 | else{
131 | dayView.dotView.hidden = YES;
132 | }
133 | }
134 | ```
135 |
136 | - `calendar:didTouchDayView:` this method is used to respond to a touch on a dayView. For example you can indicate to display another month if dayView is from another month.
137 |
138 | ```objective-c
139 | - (void)calendar:(JTCalendarManager *)calendar didTouchDayView:(JTCalendarDayView *)dayView
140 | {
141 | // Use to indicate the selected date
142 | _dateSelected = dayView.date;
143 |
144 | // Animation for the circleView
145 | dayView.circleView.transform = CGAffineTransformScale(CGAffineTransformIdentity, 0.1, 0.1);
146 | [UIView transitionWithView:dayView
147 | duration:.3
148 | options:0
149 | animations:^{
150 | dayView.circleView.transform = CGAffineTransformIdentity;
151 | [_calendarManager reload];
152 | } completion:nil];
153 |
154 | // Load the previous or next page if touch a day from another month
155 | if(![_calendarManager.dateHelper date:_calendarContentView.date isTheSameMonthThan:dayView.date]){
156 | if([_calendarContentView.date compare:dayView.date] == NSOrderedAscending){
157 | [_calendarContentView loadNextPageWithAnimation];
158 | }
159 | else{
160 | [_calendarContentView loadPreviousPageWithAnimation];
161 | }
162 | }
163 | }
164 | ```
165 |
166 | ### Switch to week view
167 |
168 | If you want see just one week at a time, you have to set the `isWeekMode` to `YES` and reload the calendar.
169 |
170 | ```objective-c
171 | _calendarManager.settings.weekModeEnabled = YES;
172 | [_calendarManager reload];
173 | ```
174 |
175 | #### WARNING
176 |
177 | When you change the mode, it doesn't change the height of `calendarContentView`, you have to do it yourself.
178 | See the Example project for more details.
179 |
180 | ### Customize the design
181 |
182 | For customize the design you have to implement some methods depending of what parts you want to custom. Check the [JTCalendarDelegate](JTCalendar/JTCalendarDelegate.h) file and the Example project.
183 |
184 | For example:
185 |
186 | ```objective-c
187 | // This method is independent from the date, it's call only at the creation of the dayView.
188 | // For customize the dayView depending of the date use `prepareDayView` method
189 | - (UIView *)calendarBuildDayView:(JTCalendarManager *)calendar
190 | {
191 | JTCalendarDayView *view = [JTCalendarDayView new];
192 | view.textLabel.font = [UIFont fontWithName:@"Avenir-Light" size:13];
193 | view.textLabel.textColor = [UIColor blackColor];
194 |
195 | return view;
196 | }
197 | ```
198 |
199 | ### Pagination
200 |
201 | The content views (`JTHorizontalCalendarView` and `JTVerticalCalendarView`) are just subclass of `UIScrollView`.
202 | Each time the current page change, `calendarDidLoadNextPage` or `calendarDidLoadPreviousPage` is called.
203 | The content views provide two method for display the previous or next page with an animation `loadNextPageWithAnimation` and `loadPreviousPageWithAnimation`.
204 | You can limit the range of the calendar by implementing `canDisplayPageWithDate` method.
205 |
206 | ```objective-c
207 | // Used to limit the date for the calendar
208 | - (BOOL)calendar:(JTCalendarManager *)calendar canDisplayPageWithDate:(NSDate *)date
209 | {
210 | return [_calendarManager.dateHelper date:date isEqualOrAfter:_minDate andEqualOrBefore:_maxDate];
211 | }
212 | ```
213 |
214 | ### Vertical calendar
215 |
216 | If you use `JTVerticalCalendarView` for having a vertical calendar, you have some settings you have to set.
217 |
218 | ```objective-c
219 | - (void)viewDidLoad
220 | {
221 | [super viewDidLoad];
222 |
223 | _calendarManager = [JTCalendarManager new];
224 | _calendarManager.delegate = self;
225 |
226 | _calendarManager.settings.pageViewHaveWeekDaysView = NO; // You don't want WeekDaysView in the contentView
227 | _calendarManager.settings.pageViewNumberOfWeeks = 0; // Automatic number of weeks
228 |
229 | _weekDayView.manager = _calendarManager; // You set the manager for WeekDaysView
230 | [_weekDayView reload]; // You load WeekDaysView manually
231 |
232 | [_calendarManager setMenuView:_calendarMenuView];
233 | [_calendarManager setContentView:_calendarContentView];
234 | [_calendarManager setDate:[NSDate date]];
235 |
236 | _calendarMenuView.scrollView.scrollEnabled = NO; // The scroll is not supported with JTVerticalCalendarView
237 | }
238 | ```
239 |
240 | ### Internationalization / Localization (change first weekday)
241 |
242 | For changing the locale and the timeZone just do:
243 |
244 | ```objective-c
245 | _calendarManager.dateHelper.calendar.timeZone = [NSTimeZone timeZoneWithAbbreviation:@"CDT"];
246 | _calendarManager.dateHelper.calendar.locale = [NSLocale localeWithLocaleIdentifier:@"fr_FR"];
247 | [_calendarManager reload];
248 | ```
249 | For changing locale and timeZone in Swift use:
250 |
251 | ```swift
252 | let locale = Locale(identifier: "fr_FR")
253 | let timeZone = TimeZone.init(abbreviation: "CDT")
254 | calendarManager = JTCalendarManager(locale: locale, andTimeZone: timeZone)
255 | ```
256 |
257 | ### Date comparaison
258 |
259 | Be careful when you compare two different dates, you have to take care of the time zone.
260 | An helper is provided for some basic operations:
261 |
262 | ```objective-c
263 | [_calendarManager.dateHelper date:dateA isTheSameMonthThan:dateB];
264 | [_calendarManager.dateHelper date:dateA isTheSameWeekThan:dateB];
265 | [_calendarManager.dateHelper date:dateA isTheSameDayThan:dateB];
266 |
267 | // Use to limit the calendar range
268 | [_calendarManager.dateHelper date:date isEqualOrAfter:minDate andEqualOrBefore:maxDate];
269 |
270 | ```
271 |
272 | ### Optimization
273 |
274 | Every methods in the delegate are called in the main thread, you have to be really careful, in particular in the `prepareDayView` method which is called very often.
275 |
276 | If you have to fetch some data from something slow, I recommend to create a cache and query this cache in `prepareDayView` method.
277 | You have to cache the data from the next pages and update this cache asynchronously (in another thread via `dispatch_async`) when a new page is loaded (via `calendarDidLoadNextPage` and `calendarDidLoadPreviousPage` methods).
278 |
279 | ## Questions
280 |
281 | Before asking any questions be sure to explore the Example project.
282 | Check also [JTCalendarDelegate](JTCalendar/JTCalendarDelegate.h) and [JTCalendarSettings](JTCalendar/JTCalendarSettings.h) files.
283 |
284 | Don't use `NSLog` to print date use a `NSDateFormatter`, `NSLog`doesn't take care of the timezone.
285 |
286 | ```objective-c
287 | NSDateFormatter *dateFormatter = [_calendarManager.dateHelper createDateFormatter];
288 | dateFormatter.dateFormat = @"yyyy'-'MM'-'dd' 'HH':'mm':'ss";
289 | NSLog(@"%@", [dateFormatter stringFromDate:yourDate]);
290 | ```
291 |
292 | ## Requirements
293 |
294 | - iOS 7 or higher
295 | - Automatic Reference Counting (ARC)
296 |
297 | ## Author
298 |
299 | - [Jonathan VUKOVICH TRIBOUHARET](https://github.com/jonathantribouharet) ([@johnvuko](https://twitter.com/johnvuko))
300 |
301 | ## License
302 |
303 | JTCalendar is released under the MIT license. See the LICENSE file for more info.
304 |
--------------------------------------------------------------------------------
/Screens/example.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/johnvuko/JTCalendar/238fa1ddfa8f3744bebab6e93aecd3d1f5905875/Screens/example.gif
--------------------------------------------------------------------------------
/Screens/example.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/johnvuko/JTCalendar/238fa1ddfa8f3744bebab6e93aecd3d1f5905875/Screens/example.png
--------------------------------------------------------------------------------