├── .gitignore ├── LICENSE ├── Podfile ├── Podfile.lock ├── README.md ├── RVCalendarWeekView.podspec.json ├── RVCalendarWeekView.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ └── contents.xcworkspacedata └── xcuserdata │ └── badchoice.xcuserdatad │ └── xcschemes │ ├── RVCalendarWeekView.xcscheme │ └── xcschememanagement.plist ├── RVCalendarWeekView.xcworkspace ├── contents.xcworkspacedata ├── xcshareddata │ └── IDEWorkspaceChecks.plist └── xcuserdata │ └── badchoice.xcuserdatad │ └── xcdebugger │ └── Expressions.xcexplist ├── RVCalendarWeekView ├── AppDelegate.h ├── AppDelegate.m ├── Assets.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard ├── Info.plist ├── Lib │ ├── MSCollectionViewCalendarLayout │ │ ├── MSCollectionViewCalendarLayout.h │ │ └── MSCollectionViewCalendarLayout.m │ ├── MSWeekView.h │ ├── MSWeekView.m │ ├── Views │ │ ├── MSCurrentTimeGridline.h │ │ ├── MSCurrentTimeGridline.m │ │ ├── MSCurrentTimeIndicator.h │ │ ├── MSCurrentTimeIndicator.m │ │ ├── MSDayColumnHeader.h │ │ ├── MSDayColumnHeader.m │ │ ├── MSDayColumnHeaderBackground.h │ │ ├── MSDayColumnHeaderBackground.m │ │ ├── MSDragableEvent.h │ │ ├── MSDragableEvent.m │ │ ├── MSDurationChangeIndicator.h │ │ ├── MSDurationChangeIndicator.m │ │ ├── MSEvent.h │ │ ├── MSEvent.m │ │ ├── MSEventCell.h │ │ ├── MSEventCell.m │ │ ├── MSGridline.h │ │ ├── MSGridline.m │ │ ├── MSTimeRowHeader.h │ │ ├── MSTimeRowHeader.m │ │ ├── MSTimeRowHeaderBackground.h │ │ ├── MSTimeRowHeaderBackground.m │ │ ├── MSUnavailableHour.h │ │ ├── MSUnavailableHour.m │ │ ├── MSWeekendBackground.h │ │ └── MSWeekendBackground.m │ └── WeekView │ │ └── Decorators │ │ ├── MSHourPerdiod.h │ │ ├── MSHourPerdiod.m │ │ ├── MSWeekViewDecorator.h │ │ ├── MSWeekViewDecorator.m │ │ ├── MSWeekViewDecoratorChangeDuration.h │ │ ├── MSWeekViewDecoratorChangeDuration.m │ │ ├── MSWeekViewDecoratorChangeDurationAndDragable.h │ │ ├── MSWeekViewDecoratorChangeDurationAndDragable.m │ │ ├── MSWeekViewDecoratorDragable.h │ │ ├── MSWeekViewDecoratorDragable.m │ │ ├── MSWeekViewDecoratorFactory.h │ │ ├── MSWeekViewDecoratorFactory.m │ │ ├── MSWeekViewDecoratorInfinite.h │ │ ├── MSWeekViewDecoratorInfinite.m │ │ ├── MSWeekViewDecoratorNewEvent.h │ │ ├── MSWeekViewDecoratorNewEvent.m │ │ ├── MSWeekViewDecoratorPinchable.h │ │ └── MSWeekViewDecoratorPinchable.m ├── ViewController.h ├── ViewController.m └── main.m ├── RVCalendarWeekViewTests ├── Info.plist └── RVCalendarWeekViewTests.m └── readme_images ├── complex.png ├── full_demo.gif └── iphone.png /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 4 | 5 | ## Build generated 6 | build/ 7 | DerivedData/ 8 | 9 | ## Various settings 10 | *.pbxuser 11 | !default.pbxuser 12 | *.mode1v3 13 | !default.mode1v3 14 | *.mode2v3 15 | !default.mode2v3 16 | *.perspectivev3 17 | !default.perspectivev3 18 | xcuserdata/ 19 | 20 | ## Other 21 | *.moved-aside 22 | *.xcuserstate 23 | 24 | ## Obj-C/Swift specific 25 | *.hmap 26 | *.ipa 27 | *.dSYM.zip 28 | *.dSYM 29 | 30 | # CocoaPods 31 | # 32 | # We recommend against adding the Pods directory to your .gitignore. However 33 | # you should judge for yourself, the pros and cons are mentioned at: 34 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 35 | 36 | Pods/ 37 | 38 | # Code Injection 39 | # 40 | # After new code Injection tools there's a generated folder /iOSInjectionProject 41 | # https://github.com/johnno1962/injectionforxcode 42 | 43 | iOSInjectionProject/ -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | Copyright (c) 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 5 | 6 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 7 | 8 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 9 | -------------------------------------------------------------------------------- /Podfile: -------------------------------------------------------------------------------- 1 | source 'https://github.com/CocoaPods/Specs.git' 2 | source 'git@bitbucket.org:revo-pos/rvpods.git' 3 | 4 | platform :ios, '9.3' 5 | 6 | target 'RVCalendarWeekView' do 7 | 8 | pod 'Collection' 9 | pod 'EasyDate' 10 | pod 'UIColor-HexString' 11 | pod 'Masonry' 12 | pod 'RVUtils' 13 | 14 | end 15 | 16 | #To fix the masonry preprocessor definition 17 | post_install do |installer| 18 | installer.pods_project.targets.each do |target| 19 | target.build_configurations.each do |config| 20 | config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= ['$(inherited)'] 21 | config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] << 'MAS_SHORTHAND=1' 22 | end 23 | end 24 | end 25 | 26 | -------------------------------------------------------------------------------- /Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - AESCrypt (0.0.1) 3 | - Collection (1.10.7) 4 | - DateTools (2.0.0) 5 | - EasyDate (0.12): 6 | - DateTools 7 | - Masonry (1.1.0) 8 | - RVHttp (1.2.3): 9 | - Collection 10 | - RVUtils (1.9.17): 11 | - AESCrypt 12 | - Collection 13 | - RVHttp 14 | - UIColor-HexString (1.3.0) 15 | 16 | DEPENDENCIES: 17 | - Collection 18 | - EasyDate 19 | - Masonry 20 | - RVUtils 21 | - UIColor-HexString 22 | 23 | SPEC REPOS: 24 | "git@bitbucket.org:revo-pos/rvpods.git": 25 | - RVUtils 26 | https://github.com/cocoapods/specs.git: 27 | - AESCrypt 28 | - Collection 29 | - DateTools 30 | - EasyDate 31 | - Masonry 32 | - RVHttp 33 | - UIColor-HexString 34 | 35 | SPEC CHECKSUMS: 36 | AESCrypt: 1d89bf8b0789cf274ab2205ea461adbe9321d5f8 37 | Collection: c6419803329856444936176aba0b9a158811088f 38 | DateTools: 933ac9c490f21f92127cf690ccd8c397e0126caf 39 | EasyDate: ae4fe5df42a810d2bf1aa40d96cb40e7618e7d77 40 | Masonry: 678fab65091a9290e40e2832a55e7ab731aad201 41 | RVHttp: c5089fea436cc827083032d8beda293e49f21e51 42 | RVUtils: 9fc2e0276c42a7cff514f787b29c8b7129b84f7c 43 | UIColor-HexString: fadc2e1389db19147ac99dee92222d3bd8bfec4a 44 | 45 | PODFILE CHECKSUM: 939a803e4134c9dda9f32e58dc9be78bdcb99799 46 | 47 | COCOAPODS: 1.5.3 48 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # RVCalendarWeekView 2 | Simple but powerful Calendar Week View for iOS With dragable events, infinte scroll and pinchable hours size 3 | 4 | 5 | Following the work from [MSCollectionView](https://github.com/erichoracek/MSCollectionViewCalendarLayout) 6 | 7 | I created this library simplifing its usage and adding some interesting features 8 | 9 | ### Installation 10 | 11 | `pod 'RVCalendarWeekView'` 12 | 13 | or just copy the files inside the `lib` folder by now 14 | 15 | 16 | ### Usage 17 | you can now use storyboard to create a simple UIView extending the MSWeekView and then just do this: 18 | 19 | 20 | ``` 21 | -(void)viewDidLoad{ 22 | MSEvent* event1 = [MSEvent make:NSDate.now 23 | title:@"Title" 24 | location:@"Central perk"]; 25 | 26 | MSEvent* event2 = [MSEvent make:[NSDate.now addMinutes:10] //AddMinutes comes from EasyDate pod 27 | duration:60*3 28 | title:@"Title 2" 29 | location:@"Central perk"]; 30 | 31 | _weekView.events = @[event1,event2]; 32 | } 33 | ``` 34 | 35 | Easy right? 36 | 37 | ### Features 38 | To add features to the WeekView I'm using a decorator pattern, this way we can extend the `weekView` with diferent features without the need of multiple inhertance and to have a expressive modular design 39 | However, this adds the need to have a `strong` reference to the `decorator` that will hold the features. 40 | 41 | So we can add features to the `weekView` with the following code: 42 | 43 | ``` 44 | self.decoratedWeekView = [MSWeekViewDecoratorFactory make:self.weekView 45 | features:(MSDragableEventFeature|MSNewEventFeature|MSInfiniteFeature|MSChangeDurationFeature) 46 | andDelegate:self]; 47 | ``` 48 | 49 | This is the fast way where the delegate should have all the methods for each feature delegate (see below). 50 | 51 | The long way is something more like the standard `decorator` pattern in case you need more flexibility. 52 | 53 | ``` 54 | MSWeekView* decoratedView = baseView; 55 | decoratedView = [MSWeekViewDecoratorInfinite makeWith:decoratedView andDelegate:infiniteDelegate]; 56 | decoratedView = [MSWeekViewDecoratorNewEvent makeWith:decoratedView andDelegate:newEventDelegate]; 57 | decoratedView = [MSWeekViewDecoratorDragable makeWith:decoratedView andDelegate:dragableDelegate]; 58 | decoratedView = [MSWeekViewDecoratorChangeDuration makeWith:decoratedView andDelegate:durationDelegate]; 59 | 60 | ``` 61 | 62 | There is a function to easily set the minutes precision to all decorators in case you need something diferent than the default 5 minutes. 63 | 64 | ``` 65 | [MSWeekViewDecoratorFactory setMinutesPrecisionToAllDecorators:decoratedView minutesPrecision:15]; 66 | ``` 67 | 68 | #### Drag and drop 69 | You can get the feature to change the event duration with `MSDragableEventFeature` 70 | 71 | It will fire the following functions on your `dragDelegate` 72 | 73 | ``` 74 | -(BOOL)weekView:(MSWeekView*)weekView canMoveEvent:(MSEvent*)event to:(NSDate*)date; 75 | 76 | -(void)weekView:(MSWeekView*)weekView event:(MSEvent*)event moved:(NSDate*)date; 77 | 78 | ``` 79 | 80 | #### Change duration 81 | You can get the feature to change the event duration with `MSChangeDurationFeature` 82 | 83 | ``` 84 | -(BOOL)weekView:(MSWeekView*)weekView canChangeDuration:(MSEvent*)event startDate:(NSDate*)startDate endDate:(NSDate*)endDate; 85 | 86 | -(void)weekView:(MSWeekView*)weekView event:(MSEvent*)event durationChanged:(NSDate*)startDate endDate:(NSDate*)endDate; 87 | ``` 88 | 89 | #### Create new event on long press 90 | it will fire the following functions on your `createEventDelegate` 91 | 92 | ``` 93 | -(void)weekView:(MSWeekView*)weekView onLongPressAt:(NSDate*)date 94 | ``` 95 | 96 | #### Infinite scroll 97 | It will fire the following functions on your `infiniteDelegate` 98 | 99 | ``` 100 | -(BOOL)weekView:(MSWeekView*)weekView newDaysLoaded:(NSDate*)startDate to:(NSDate*)endDate; 101 | ``` 102 | 103 | #### Unavailable Hours 104 | The standard `weekView` comes with an optional delegate function to display unavailable hours in gray (customizable class of course) 105 | 106 | just do something like this: 107 | 108 | 109 | ``` 110 | //This one is optional 111 | -(NSArray*)weekView:(id)sender unavailableHoursPeriods:(NSDate*)date{ 112 | if(!unavailableHours){ 113 | unavailableHours = @[ 114 | [MSHourPerdiod make:@"00:00" end:@"09:00"], 115 | [MSHourPerdiod make:@"18:30" end:@"21:00"], 116 | ]; 117 | } 118 | return unavailableHours; 119 | } 120 | ``` 121 | 122 | 123 | #### Pinchable 124 | **This doesn't work really well yet** 125 | You just need to add the `MSPinchableFeature` in the `[MSWeekViewDecoratorFactory make:...]` 126 | 127 | 128 | #### Options 129 | You can even customize some options (they all have defaults values so you just need to modify them if you want to work differently) 130 | 131 | ``` 132 | _weekView.weekFlowLayout.show24Hours = YES; //Show All hours or just the min to cover all events 133 | _weekView.weekFlowLayout.hourHeight = 50; //Define the hour height 134 | _weekView.daysToShowOnScreen = 7; //How many days visible at the same time 135 | _weekView.daysToShow = 31; //How many days to display (Ininite scroll feature pending) 136 | _weekView.weekFlowLayout.hourGridDivisionValue = MSHourGridDivision_15_Minutes; // Show hour division lines (at lower alpha) each X minutes, by default its NONE so they are not shown. 137 | ``` 138 | 139 | ![full demo](https://github.com/BadChoice/RVCalendarWeekView/blob/master/readme_images/full_demo.gif?raw=true) 140 | 141 | ![iPhone](https://github.com/BadChoice/RVCalendarWeekView/blob/master/readme_images/iphone.png?raw=true) 142 | 143 | This is a complex example on how you can customize it. 144 | - In this one we are displaying just one day, with each employee as worker. 145 | - Unavailable hours class with pattern image background. 146 | - Custom Event Cell. 147 | - Custom header section view 148 | - Custom header background 149 | 150 | ![complex](https://github.com/BadChoice/RVCalendarWeekView/blob/master/readme_images/complex.png?raw=true) 151 | 152 | 153 | ### Issues 154 | Feel free to report any issue you find in github issues 155 | 156 | #### Masonry pod error 157 | 158 | looks like this can solve it in your pods file 159 | 160 | ``` 161 | #To fix the masonry preprocessor definition 162 | post_install do |installer| 163 | installer.pods_project.targets.each do |target| 164 | target.build_configurations.each do |config| 165 | config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= ['$(inherited)'] 166 | config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] << 'MAS_SHORTHAND=1' 167 | end 168 | end 169 | end 170 | ``` 171 | 172 | ### Contributors 173 | · Jordi Puigdellívol - https://github.com/badchoice 174 | · Eric Horacek - https://github.com/erichoracek 175 | · Kyle Fleming - https://github.com/kylefleming 176 | 177 | -------------------------------------------------------------------------------- /RVCalendarWeekView.podspec.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "RVCalendarWeekView", 3 | "version": "0.5.3", 4 | "summary": "Utils used along all revo products", 5 | "license": "MIT", 6 | "platforms": { 7 | "ios": "6.0" 8 | }, 9 | "source": { 10 | "git": "https://github.com/BadChoice/RVCalendarWeekView.git", 11 | "tag": "0.5.3" 12 | }, 13 | "dependencies":{ 14 | "Collection": [ 15 | 16 | ], 17 | "EasyDate": [ 18 | "~> 0.9" 19 | ], 20 | "UIColor-HexString": [ 21 | 22 | ], 23 | "Masonry": [ 24 | 25 | ] 26 | }, 27 | 28 | "description": "A very very useful classes to be used used along all revo products", 29 | "homepage": "http://github.com/BadChoice/RVCalendarWeekView", 30 | "license": "MIT", 31 | "authors": { 32 | "Jordi Puigdellívol": "jordo@gloobus.net" 33 | }, 34 | "source_files": [ 35 | "RVCalendarWeekView/Lib/**/*" 36 | ], 37 | "requires_arc": true 38 | } 39 | -------------------------------------------------------------------------------- /RVCalendarWeekView.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 609E91FDC500BF0231C2C658 /* MSWeekViewDecoratorChangeDurationAndDragable.m in Sources */ = {isa = PBXBuildFile; fileRef = 609E90F40B98F26B08CE45F4 /* MSWeekViewDecoratorChangeDurationAndDragable.m */; }; 11 | 76276EB71D6B81D4002C1D39 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 76276EB61D6B81D4002C1D39 /* main.m */; }; 12 | 76276EBA1D6B81D4002C1D39 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 76276EB91D6B81D4002C1D39 /* AppDelegate.m */; }; 13 | 76276EBD1D6B81D4002C1D39 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 76276EBC1D6B81D4002C1D39 /* ViewController.m */; }; 14 | 76276EC01D6B81D4002C1D39 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 76276EBE1D6B81D4002C1D39 /* Main.storyboard */; }; 15 | 76276EC21D6B81D4002C1D39 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 76276EC11D6B81D4002C1D39 /* Assets.xcassets */; }; 16 | 76276EC51D6B81D4002C1D39 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 76276EC31D6B81D4002C1D39 /* LaunchScreen.storyboard */; }; 17 | 76276ED01D6B81D4002C1D39 /* RVCalendarWeekViewTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 76276ECF1D6B81D4002C1D39 /* RVCalendarWeekViewTests.m */; }; 18 | 76276EF51D6B826B002C1D39 /* MSCollectionViewCalendarLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 76276EE01D6B826B002C1D39 /* MSCollectionViewCalendarLayout.m */; }; 19 | 76276EF61D6B826B002C1D39 /* MSCurrentTimeGridline.m in Sources */ = {isa = PBXBuildFile; fileRef = 76276EE31D6B826B002C1D39 /* MSCurrentTimeGridline.m */; }; 20 | 76276EF71D6B826B002C1D39 /* MSCurrentTimeIndicator.m in Sources */ = {isa = PBXBuildFile; fileRef = 76276EE51D6B826B002C1D39 /* MSCurrentTimeIndicator.m */; }; 21 | 76276EF81D6B826B002C1D39 /* MSDayColumnHeader.m in Sources */ = {isa = PBXBuildFile; fileRef = 76276EE71D6B826B002C1D39 /* MSDayColumnHeader.m */; }; 22 | 76276EF91D6B826B002C1D39 /* MSDayColumnHeaderBackground.m in Sources */ = {isa = PBXBuildFile; fileRef = 76276EE91D6B826B002C1D39 /* MSDayColumnHeaderBackground.m */; }; 23 | 76276EFB1D6B826B002C1D39 /* MSEventCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 76276EED1D6B826B002C1D39 /* MSEventCell.m */; }; 24 | 76276EFC1D6B826B002C1D39 /* MSGridline.m in Sources */ = {isa = PBXBuildFile; fileRef = 76276EEF1D6B826B002C1D39 /* MSGridline.m */; }; 25 | 76276EFD1D6B826B002C1D39 /* MSTimeRowHeader.m in Sources */ = {isa = PBXBuildFile; fileRef = 76276EF11D6B826B002C1D39 /* MSTimeRowHeader.m */; }; 26 | 76276EFE1D6B826B002C1D39 /* MSTimeRowHeaderBackground.m in Sources */ = {isa = PBXBuildFile; fileRef = 76276EF31D6B826B002C1D39 /* MSTimeRowHeaderBackground.m */; }; 27 | 76276F051D6B8759002C1D39 /* MSEvent.m in Sources */ = {isa = PBXBuildFile; fileRef = 76276F041D6B8759002C1D39 /* MSEvent.m */; }; 28 | 7630AD5A1DA3FA80006D8FDC /* MSHourPerdiod.m in Sources */ = {isa = PBXBuildFile; fileRef = 7630AD591DA3FA80006D8FDC /* MSHourPerdiod.m */; }; 29 | 7630AD5D1DA4018A006D8FDC /* MSUnavailableHour.m in Sources */ = {isa = PBXBuildFile; fileRef = 7630AD5C1DA4018A006D8FDC /* MSUnavailableHour.m */; }; 30 | 763A802A1D6C4488002E0CBF /* MSDragableEvent.m in Sources */ = {isa = PBXBuildFile; fileRef = 763A80291D6C4488002E0CBF /* MSDragableEvent.m */; }; 31 | 7646D59E1DA68FC7001B8379 /* MSWeekendBackground.m in Sources */ = {isa = PBXBuildFile; fileRef = 7646D59D1DA68FC7001B8379 /* MSWeekendBackground.m */; }; 32 | 7657ACDF1DA7A5F300C4FA68 /* MSWeekViewDecoratorChangeDuration.m in Sources */ = {isa = PBXBuildFile; fileRef = 7657ACDE1DA7A5F300C4FA68 /* MSWeekViewDecoratorChangeDuration.m */; }; 33 | 7657ACE21DA7B20500C4FA68 /* MSDurationChangeIndicator.m in Sources */ = {isa = PBXBuildFile; fileRef = 7657ACE11DA7B20500C4FA68 /* MSDurationChangeIndicator.m */; }; 34 | 766E7E1D1D6B9C9F007A410C /* MSWeekView.m in Sources */ = {isa = PBXBuildFile; fileRef = 766E7E1C1D6B9C9F007A410C /* MSWeekView.m */; }; 35 | 768458251D7847080080A27A /* MSWeekViewDecorator.m in Sources */ = {isa = PBXBuildFile; fileRef = 768458241D7847080080A27A /* MSWeekViewDecorator.m */; }; 36 | 768458281D7847D80080A27A /* MSWeekViewDecoratorDragable.m in Sources */ = {isa = PBXBuildFile; fileRef = 768458271D7847D80080A27A /* MSWeekViewDecoratorDragable.m */; }; 37 | 7684582C1D7961350080A27A /* MSWeekViewDecoratorPinchable.m in Sources */ = {isa = PBXBuildFile; fileRef = 7684582B1D7961350080A27A /* MSWeekViewDecoratorPinchable.m */; }; 38 | 768458301D7996C70080A27A /* Podfile in Resources */ = {isa = PBXBuildFile; fileRef = 7684582F1D7996C70080A27A /* Podfile */; }; 39 | 768458321D7997BE0080A27A /* RVCalendarWeekView.podspec.json in Resources */ = {isa = PBXBuildFile; fileRef = 768458311D7997BE0080A27A /* RVCalendarWeekView.podspec.json */; }; 40 | 76FC4A001D7865BB004CF995 /* MSWeekViewDecoratorInfinite.m in Sources */ = {isa = PBXBuildFile; fileRef = 76FC49FF1D7865BB004CF995 /* MSWeekViewDecoratorInfinite.m */; }; 41 | 76FC4A061D78678C004CF995 /* MSWeekViewDecoratorNewEvent.m in Sources */ = {isa = PBXBuildFile; fileRef = 76FC4A051D78678C004CF995 /* MSWeekViewDecoratorNewEvent.m */; }; 42 | 76FC4A091D786E7F004CF995 /* MSWeekViewDecoratorFactory.m in Sources */ = {isa = PBXBuildFile; fileRef = 76FC4A081D786E7F004CF995 /* MSWeekViewDecoratorFactory.m */; }; 43 | 819ED74187A2A0C0B39AEB2B /* libPods-RVCalendarWeekView.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A43A252421A63E1655B8A38 /* libPods-RVCalendarWeekView.a */; }; 44 | /* End PBXBuildFile section */ 45 | 46 | /* Begin PBXContainerItemProxy section */ 47 | 76276ECC1D6B81D4002C1D39 /* PBXContainerItemProxy */ = { 48 | isa = PBXContainerItemProxy; 49 | containerPortal = 76276EAA1D6B81D4002C1D39 /* Project object */; 50 | proxyType = 1; 51 | remoteGlobalIDString = 76276EB11D6B81D4002C1D39; 52 | remoteInfo = RVCalendarWeekView; 53 | }; 54 | /* End PBXContainerItemProxy section */ 55 | 56 | /* Begin PBXFileReference section */ 57 | 016043077DD4C904B6A3A6BE /* Pods-RVCalendarWeekView.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RVCalendarWeekView.release.xcconfig"; path = "Pods/Target Support Files/Pods-RVCalendarWeekView/Pods-RVCalendarWeekView.release.xcconfig"; sourceTree = ""; }; 58 | 1A43A252421A63E1655B8A38 /* libPods-RVCalendarWeekView.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-RVCalendarWeekView.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 59 | 55A9198AF6C016D51B48E4CB /* Pods-RVCalendarWeekView.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RVCalendarWeekView.debug.xcconfig"; path = "Pods/Target Support Files/Pods-RVCalendarWeekView/Pods-RVCalendarWeekView.debug.xcconfig"; sourceTree = ""; }; 60 | 609E90F40B98F26B08CE45F4 /* MSWeekViewDecoratorChangeDurationAndDragable.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MSWeekViewDecoratorChangeDurationAndDragable.m; path = Lib/WeekView/Decorators/MSWeekViewDecoratorChangeDurationAndDragable.m; sourceTree = ""; }; 61 | 609E9ECB1435CA79CB6CCF28 /* MSWeekViewDecoratorChangeDurationAndDragable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MSWeekViewDecoratorChangeDurationAndDragable.h; path = Lib/WeekView/Decorators/MSWeekViewDecoratorChangeDurationAndDragable.h; sourceTree = ""; }; 62 | 76276EB21D6B81D4002C1D39 /* RVCalendarWeekView.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = RVCalendarWeekView.app; sourceTree = BUILT_PRODUCTS_DIR; }; 63 | 76276EB61D6B81D4002C1D39 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 64 | 76276EB81D6B81D4002C1D39 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 65 | 76276EB91D6B81D4002C1D39 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 66 | 76276EBB1D6B81D4002C1D39 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 67 | 76276EBC1D6B81D4002C1D39 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 68 | 76276EBF1D6B81D4002C1D39 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 69 | 76276EC11D6B81D4002C1D39 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 70 | 76276EC41D6B81D4002C1D39 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 71 | 76276EC61D6B81D4002C1D39 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 72 | 76276ECB1D6B81D4002C1D39 /* RVCalendarWeekViewTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RVCalendarWeekViewTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 73 | 76276ECF1D6B81D4002C1D39 /* RVCalendarWeekViewTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RVCalendarWeekViewTests.m; sourceTree = ""; }; 74 | 76276ED11D6B81D4002C1D39 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 75 | 76276EDF1D6B826B002C1D39 /* MSCollectionViewCalendarLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MSCollectionViewCalendarLayout.h; sourceTree = ""; }; 76 | 76276EE01D6B826B002C1D39 /* MSCollectionViewCalendarLayout.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MSCollectionViewCalendarLayout.m; sourceTree = ""; }; 77 | 76276EE21D6B826B002C1D39 /* MSCurrentTimeGridline.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MSCurrentTimeGridline.h; sourceTree = ""; }; 78 | 76276EE31D6B826B002C1D39 /* MSCurrentTimeGridline.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MSCurrentTimeGridline.m; sourceTree = ""; }; 79 | 76276EE41D6B826B002C1D39 /* MSCurrentTimeIndicator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MSCurrentTimeIndicator.h; sourceTree = ""; }; 80 | 76276EE51D6B826B002C1D39 /* MSCurrentTimeIndicator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MSCurrentTimeIndicator.m; sourceTree = ""; }; 81 | 76276EE61D6B826B002C1D39 /* MSDayColumnHeader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MSDayColumnHeader.h; sourceTree = ""; }; 82 | 76276EE71D6B826B002C1D39 /* MSDayColumnHeader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MSDayColumnHeader.m; sourceTree = ""; }; 83 | 76276EE81D6B826B002C1D39 /* MSDayColumnHeaderBackground.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MSDayColumnHeaderBackground.h; sourceTree = ""; }; 84 | 76276EE91D6B826B002C1D39 /* MSDayColumnHeaderBackground.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MSDayColumnHeaderBackground.m; sourceTree = ""; }; 85 | 76276EEC1D6B826B002C1D39 /* MSEventCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MSEventCell.h; sourceTree = ""; }; 86 | 76276EED1D6B826B002C1D39 /* MSEventCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MSEventCell.m; sourceTree = ""; }; 87 | 76276EEE1D6B826B002C1D39 /* MSGridline.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MSGridline.h; sourceTree = ""; }; 88 | 76276EEF1D6B826B002C1D39 /* MSGridline.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MSGridline.m; sourceTree = ""; }; 89 | 76276EF01D6B826B002C1D39 /* MSTimeRowHeader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MSTimeRowHeader.h; sourceTree = ""; }; 90 | 76276EF11D6B826B002C1D39 /* MSTimeRowHeader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MSTimeRowHeader.m; sourceTree = ""; }; 91 | 76276EF21D6B826B002C1D39 /* MSTimeRowHeaderBackground.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MSTimeRowHeaderBackground.h; sourceTree = ""; }; 92 | 76276EF31D6B826B002C1D39 /* MSTimeRowHeaderBackground.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MSTimeRowHeaderBackground.m; sourceTree = ""; }; 93 | 76276F031D6B8759002C1D39 /* MSEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MSEvent.h; path = Lib/Views/MSEvent.h; sourceTree = ""; }; 94 | 76276F041D6B8759002C1D39 /* MSEvent.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MSEvent.m; path = Lib/Views/MSEvent.m; sourceTree = ""; }; 95 | 7630AD581DA3FA80006D8FDC /* MSHourPerdiod.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MSHourPerdiod.h; path = Lib/WeekView/Decorators/MSHourPerdiod.h; sourceTree = ""; }; 96 | 7630AD591DA3FA80006D8FDC /* MSHourPerdiod.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MSHourPerdiod.m; path = Lib/WeekView/Decorators/MSHourPerdiod.m; sourceTree = ""; }; 97 | 7630AD5B1DA4018A006D8FDC /* MSUnavailableHour.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MSUnavailableHour.h; sourceTree = ""; }; 98 | 7630AD5C1DA4018A006D8FDC /* MSUnavailableHour.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MSUnavailableHour.m; sourceTree = ""; }; 99 | 763857F31D6BA4DF008D1328 /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = SOURCE_ROOT; }; 100 | 763A80281D6C4488002E0CBF /* MSDragableEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MSDragableEvent.h; sourceTree = ""; }; 101 | 763A80291D6C4488002E0CBF /* MSDragableEvent.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MSDragableEvent.m; sourceTree = ""; }; 102 | 7646D59C1DA68FC7001B8379 /* MSWeekendBackground.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MSWeekendBackground.h; sourceTree = ""; }; 103 | 7646D59D1DA68FC7001B8379 /* MSWeekendBackground.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MSWeekendBackground.m; sourceTree = ""; }; 104 | 7657ACDD1DA7A5F300C4FA68 /* MSWeekViewDecoratorChangeDuration.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MSWeekViewDecoratorChangeDuration.h; path = Lib/WeekView/Decorators/MSWeekViewDecoratorChangeDuration.h; sourceTree = ""; }; 105 | 7657ACDE1DA7A5F300C4FA68 /* MSWeekViewDecoratorChangeDuration.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MSWeekViewDecoratorChangeDuration.m; path = Lib/WeekView/Decorators/MSWeekViewDecoratorChangeDuration.m; sourceTree = ""; }; 106 | 7657ACE01DA7B20500C4FA68 /* MSDurationChangeIndicator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MSDurationChangeIndicator.h; sourceTree = ""; }; 107 | 7657ACE11DA7B20500C4FA68 /* MSDurationChangeIndicator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MSDurationChangeIndicator.m; sourceTree = ""; }; 108 | 766E7E1B1D6B9C9F007A410C /* MSWeekView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MSWeekView.h; path = Lib/MSWeekView.h; sourceTree = ""; }; 109 | 766E7E1C1D6B9C9F007A410C /* MSWeekView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MSWeekView.m; path = Lib/MSWeekView.m; sourceTree = ""; }; 110 | 768458231D7847080080A27A /* MSWeekViewDecorator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MSWeekViewDecorator.h; path = Lib/WeekView/Decorators/MSWeekViewDecorator.h; sourceTree = ""; }; 111 | 768458241D7847080080A27A /* MSWeekViewDecorator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MSWeekViewDecorator.m; path = Lib/WeekView/Decorators/MSWeekViewDecorator.m; sourceTree = ""; }; 112 | 768458261D7847D80080A27A /* MSWeekViewDecoratorDragable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MSWeekViewDecoratorDragable.h; path = Lib/WeekView/Decorators/MSWeekViewDecoratorDragable.h; sourceTree = ""; }; 113 | 768458271D7847D80080A27A /* MSWeekViewDecoratorDragable.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MSWeekViewDecoratorDragable.m; path = Lib/WeekView/Decorators/MSWeekViewDecoratorDragable.m; sourceTree = ""; }; 114 | 7684582A1D7961350080A27A /* MSWeekViewDecoratorPinchable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MSWeekViewDecoratorPinchable.h; path = Lib/WeekView/Decorators/MSWeekViewDecoratorPinchable.h; sourceTree = ""; }; 115 | 7684582B1D7961350080A27A /* MSWeekViewDecoratorPinchable.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MSWeekViewDecoratorPinchable.m; path = Lib/WeekView/Decorators/MSWeekViewDecoratorPinchable.m; sourceTree = ""; }; 116 | 7684582F1D7996C70080A27A /* Podfile */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Podfile; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; 117 | 768458311D7997BE0080A27A /* RVCalendarWeekView.podspec.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = RVCalendarWeekView.podspec.json; sourceTree = SOURCE_ROOT; }; 118 | 76FC49FE1D7865BB004CF995 /* MSWeekViewDecoratorInfinite.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MSWeekViewDecoratorInfinite.h; path = Lib/WeekView/Decorators/MSWeekViewDecoratorInfinite.h; sourceTree = ""; }; 119 | 76FC49FF1D7865BB004CF995 /* MSWeekViewDecoratorInfinite.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MSWeekViewDecoratorInfinite.m; path = Lib/WeekView/Decorators/MSWeekViewDecoratorInfinite.m; sourceTree = ""; }; 120 | 76FC4A041D78678C004CF995 /* MSWeekViewDecoratorNewEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MSWeekViewDecoratorNewEvent.h; path = Lib/WeekView/Decorators/MSWeekViewDecoratorNewEvent.h; sourceTree = ""; }; 121 | 76FC4A051D78678C004CF995 /* MSWeekViewDecoratorNewEvent.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MSWeekViewDecoratorNewEvent.m; path = Lib/WeekView/Decorators/MSWeekViewDecoratorNewEvent.m; sourceTree = ""; }; 122 | 76FC4A071D786E7F004CF995 /* MSWeekViewDecoratorFactory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MSWeekViewDecoratorFactory.h; path = Lib/WeekView/Decorators/MSWeekViewDecoratorFactory.h; sourceTree = ""; }; 123 | 76FC4A081D786E7F004CF995 /* MSWeekViewDecoratorFactory.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MSWeekViewDecoratorFactory.m; path = Lib/WeekView/Decorators/MSWeekViewDecoratorFactory.m; sourceTree = ""; }; 124 | /* End PBXFileReference section */ 125 | 126 | /* Begin PBXFrameworksBuildPhase section */ 127 | 76276EAF1D6B81D4002C1D39 /* Frameworks */ = { 128 | isa = PBXFrameworksBuildPhase; 129 | buildActionMask = 2147483647; 130 | files = ( 131 | 819ED74187A2A0C0B39AEB2B /* libPods-RVCalendarWeekView.a in Frameworks */, 132 | ); 133 | runOnlyForDeploymentPostprocessing = 0; 134 | }; 135 | 76276EC81D6B81D4002C1D39 /* Frameworks */ = { 136 | isa = PBXFrameworksBuildPhase; 137 | buildActionMask = 2147483647; 138 | files = ( 139 | ); 140 | runOnlyForDeploymentPostprocessing = 0; 141 | }; 142 | /* End PBXFrameworksBuildPhase section */ 143 | 144 | /* Begin PBXGroup section */ 145 | 0241F19EAD6E623E5EB9DC2C /* Frameworks */ = { 146 | isa = PBXGroup; 147 | children = ( 148 | 1A43A252421A63E1655B8A38 /* libPods-RVCalendarWeekView.a */, 149 | ); 150 | name = Frameworks; 151 | sourceTree = ""; 152 | }; 153 | 609E9C0A7253BDE145B7D87B /* ChangeDurationAndDragable */ = { 154 | isa = PBXGroup; 155 | children = ( 156 | 609E9ECB1435CA79CB6CCF28 /* MSWeekViewDecoratorChangeDurationAndDragable.h */, 157 | 609E90F40B98F26B08CE45F4 /* MSWeekViewDecoratorChangeDurationAndDragable.m */, 158 | ); 159 | name = ChangeDurationAndDragable; 160 | sourceTree = ""; 161 | }; 162 | 76276EA91D6B81D4002C1D39 = { 163 | isa = PBXGroup; 164 | children = ( 165 | 76276EB41D6B81D4002C1D39 /* RVCalendarWeekView */, 166 | 76276ECE1D6B81D4002C1D39 /* RVCalendarWeekViewTests */, 167 | 76276EB31D6B81D4002C1D39 /* Products */, 168 | C8C01CCD2324837475AD4513 /* Pods */, 169 | 0241F19EAD6E623E5EB9DC2C /* Frameworks */, 170 | ); 171 | sourceTree = ""; 172 | }; 173 | 76276EB31D6B81D4002C1D39 /* Products */ = { 174 | isa = PBXGroup; 175 | children = ( 176 | 76276EB21D6B81D4002C1D39 /* RVCalendarWeekView.app */, 177 | 76276ECB1D6B81D4002C1D39 /* RVCalendarWeekViewTests.xctest */, 178 | ); 179 | name = Products; 180 | sourceTree = ""; 181 | }; 182 | 76276EB41D6B81D4002C1D39 /* RVCalendarWeekView */ = { 183 | isa = PBXGroup; 184 | children = ( 185 | 768458311D7997BE0080A27A /* RVCalendarWeekView.podspec.json */, 186 | 763857F31D6BA4DF008D1328 /* README.md */, 187 | 7684582F1D7996C70080A27A /* Podfile */, 188 | 76276EBE1D6B81D4002C1D39 /* Main.storyboard */, 189 | 76276EB81D6B81D4002C1D39 /* AppDelegate.h */, 190 | 76276EB91D6B81D4002C1D39 /* AppDelegate.m */, 191 | 76276EBB1D6B81D4002C1D39 /* ViewController.h */, 192 | 76276EBC1D6B81D4002C1D39 /* ViewController.m */, 193 | 76276EDA1D6B81D9002C1D39 /* lib */, 194 | 76276EB51D6B81D4002C1D39 /* Supporting Files */, 195 | ); 196 | path = RVCalendarWeekView; 197 | sourceTree = ""; 198 | }; 199 | 76276EB51D6B81D4002C1D39 /* Supporting Files */ = { 200 | isa = PBXGroup; 201 | children = ( 202 | 76276EC11D6B81D4002C1D39 /* Assets.xcassets */, 203 | 76276EC31D6B81D4002C1D39 /* LaunchScreen.storyboard */, 204 | 76276EC61D6B81D4002C1D39 /* Info.plist */, 205 | 76276EB61D6B81D4002C1D39 /* main.m */, 206 | ); 207 | name = "Supporting Files"; 208 | sourceTree = ""; 209 | }; 210 | 76276ECE1D6B81D4002C1D39 /* RVCalendarWeekViewTests */ = { 211 | isa = PBXGroup; 212 | children = ( 213 | 76276ECF1D6B81D4002C1D39 /* RVCalendarWeekViewTests.m */, 214 | 76276ED11D6B81D4002C1D39 /* Info.plist */, 215 | ); 216 | path = RVCalendarWeekViewTests; 217 | sourceTree = ""; 218 | }; 219 | 76276EDA1D6B81D9002C1D39 /* lib */ = { 220 | isa = PBXGroup; 221 | children = ( 222 | 7657ACDB1DA7A5C100C4FA68 /* Helpers */, 223 | 768458211D7846DC0080A27A /* WeekView */, 224 | 76276EFF1D6B8637002C1D39 /* Event */, 225 | 76276EDE1D6B826B002C1D39 /* FlowLayout */, 226 | 76276EE11D6B826B002C1D39 /* Views */, 227 | ); 228 | name = lib; 229 | sourceTree = ""; 230 | }; 231 | 76276EDE1D6B826B002C1D39 /* FlowLayout */ = { 232 | isa = PBXGroup; 233 | children = ( 234 | 76276EDF1D6B826B002C1D39 /* MSCollectionViewCalendarLayout.h */, 235 | 76276EE01D6B826B002C1D39 /* MSCollectionViewCalendarLayout.m */, 236 | ); 237 | name = FlowLayout; 238 | path = Lib/MSCollectionViewCalendarLayout; 239 | sourceTree = ""; 240 | }; 241 | 76276EE11D6B826B002C1D39 /* Views */ = { 242 | isa = PBXGroup; 243 | children = ( 244 | 76276F001D6B8649002C1D39 /* Decorations */, 245 | 76276F021D6B867E002C1D39 /* Grid */, 246 | 76276F011D6B8675002C1D39 /* Event */, 247 | ); 248 | name = Views; 249 | path = Lib/Views; 250 | sourceTree = ""; 251 | }; 252 | 76276EFF1D6B8637002C1D39 /* Event */ = { 253 | isa = PBXGroup; 254 | children = ( 255 | 76276F031D6B8759002C1D39 /* MSEvent.h */, 256 | 76276F041D6B8759002C1D39 /* MSEvent.m */, 257 | ); 258 | name = Event; 259 | sourceTree = ""; 260 | }; 261 | 76276F001D6B8649002C1D39 /* Decorations */ = { 262 | isa = PBXGroup; 263 | children = ( 264 | 76276EE61D6B826B002C1D39 /* MSDayColumnHeader.h */, 265 | 76276EE71D6B826B002C1D39 /* MSDayColumnHeader.m */, 266 | 76276EE81D6B826B002C1D39 /* MSDayColumnHeaderBackground.h */, 267 | 76276EE91D6B826B002C1D39 /* MSDayColumnHeaderBackground.m */, 268 | 76276EF01D6B826B002C1D39 /* MSTimeRowHeader.h */, 269 | 76276EF11D6B826B002C1D39 /* MSTimeRowHeader.m */, 270 | 76276EF21D6B826B002C1D39 /* MSTimeRowHeaderBackground.h */, 271 | 76276EF31D6B826B002C1D39 /* MSTimeRowHeaderBackground.m */, 272 | 7630AD5B1DA4018A006D8FDC /* MSUnavailableHour.h */, 273 | 7630AD5C1DA4018A006D8FDC /* MSUnavailableHour.m */, 274 | 7646D59C1DA68FC7001B8379 /* MSWeekendBackground.h */, 275 | 7646D59D1DA68FC7001B8379 /* MSWeekendBackground.m */, 276 | ); 277 | name = Decorations; 278 | sourceTree = ""; 279 | }; 280 | 76276F011D6B8675002C1D39 /* Event */ = { 281 | isa = PBXGroup; 282 | children = ( 283 | 7657ACE31DA7DF6C00C4FA68 /* Indicators */, 284 | 76276EEC1D6B826B002C1D39 /* MSEventCell.h */, 285 | 76276EED1D6B826B002C1D39 /* MSEventCell.m */, 286 | 763A80281D6C4488002E0CBF /* MSDragableEvent.h */, 287 | 763A80291D6C4488002E0CBF /* MSDragableEvent.m */, 288 | ); 289 | name = Event; 290 | sourceTree = ""; 291 | }; 292 | 76276F021D6B867E002C1D39 /* Grid */ = { 293 | isa = PBXGroup; 294 | children = ( 295 | 76276EE21D6B826B002C1D39 /* MSCurrentTimeGridline.h */, 296 | 76276EE31D6B826B002C1D39 /* MSCurrentTimeGridline.m */, 297 | 76276EE41D6B826B002C1D39 /* MSCurrentTimeIndicator.h */, 298 | 76276EE51D6B826B002C1D39 /* MSCurrentTimeIndicator.m */, 299 | 76276EEE1D6B826B002C1D39 /* MSGridline.h */, 300 | 76276EEF1D6B826B002C1D39 /* MSGridline.m */, 301 | ); 302 | name = Grid; 303 | sourceTree = ""; 304 | }; 305 | 7630AD541DA3F890006D8FDC /* UnavailableHours */ = { 306 | isa = PBXGroup; 307 | children = ( 308 | 7630AD581DA3FA80006D8FDC /* MSHourPerdiod.h */, 309 | 7630AD591DA3FA80006D8FDC /* MSHourPerdiod.m */, 310 | ); 311 | name = UnavailableHours; 312 | sourceTree = ""; 313 | }; 314 | 7657ACDB1DA7A5C100C4FA68 /* Helpers */ = { 315 | isa = PBXGroup; 316 | children = ( 317 | 7630AD541DA3F890006D8FDC /* UnavailableHours */, 318 | ); 319 | name = Helpers; 320 | sourceTree = ""; 321 | }; 322 | 7657ACDC1DA7A5D300C4FA68 /* ChangeDuration */ = { 323 | isa = PBXGroup; 324 | children = ( 325 | 7657ACDD1DA7A5F300C4FA68 /* MSWeekViewDecoratorChangeDuration.h */, 326 | 7657ACDE1DA7A5F300C4FA68 /* MSWeekViewDecoratorChangeDuration.m */, 327 | ); 328 | name = ChangeDuration; 329 | sourceTree = ""; 330 | }; 331 | 7657ACE31DA7DF6C00C4FA68 /* Indicators */ = { 332 | isa = PBXGroup; 333 | children = ( 334 | 7657ACE01DA7B20500C4FA68 /* MSDurationChangeIndicator.h */, 335 | 7657ACE11DA7B20500C4FA68 /* MSDurationChangeIndicator.m */, 336 | ); 337 | name = Indicators; 338 | sourceTree = ""; 339 | }; 340 | 768458211D7846DC0080A27A /* WeekView */ = { 341 | isa = PBXGroup; 342 | children = ( 343 | 766E7E1B1D6B9C9F007A410C /* MSWeekView.h */, 344 | 766E7E1C1D6B9C9F007A410C /* MSWeekView.m */, 345 | 768458221D7846E60080A27A /* Decorators */, 346 | ); 347 | name = WeekView; 348 | sourceTree = ""; 349 | }; 350 | 768458221D7846E60080A27A /* Decorators */ = { 351 | isa = PBXGroup; 352 | children = ( 353 | 76FC4A071D786E7F004CF995 /* MSWeekViewDecoratorFactory.h */, 354 | 76FC4A081D786E7F004CF995 /* MSWeekViewDecoratorFactory.m */, 355 | 768458231D7847080080A27A /* MSWeekViewDecorator.h */, 356 | 768458241D7847080080A27A /* MSWeekViewDecorator.m */, 357 | 76FC4A031D7865DE004CF995 /* NewEvent */, 358 | 76FC4A011D7865CD004CF995 /* Dragable */, 359 | 768458291D7961140080A27A /* Pinchable */, 360 | 76FC4A021D7865D5004CF995 /* Infinite */, 361 | 7657ACDC1DA7A5D300C4FA68 /* ChangeDuration */, 362 | 609E9C0A7253BDE145B7D87B /* ChangeDurationAndDragable */, 363 | ); 364 | name = Decorators; 365 | sourceTree = ""; 366 | }; 367 | 768458291D7961140080A27A /* Pinchable */ = { 368 | isa = PBXGroup; 369 | children = ( 370 | 7684582A1D7961350080A27A /* MSWeekViewDecoratorPinchable.h */, 371 | 7684582B1D7961350080A27A /* MSWeekViewDecoratorPinchable.m */, 372 | ); 373 | name = Pinchable; 374 | sourceTree = ""; 375 | }; 376 | 76FC4A011D7865CD004CF995 /* Dragable */ = { 377 | isa = PBXGroup; 378 | children = ( 379 | 768458261D7847D80080A27A /* MSWeekViewDecoratorDragable.h */, 380 | 768458271D7847D80080A27A /* MSWeekViewDecoratorDragable.m */, 381 | ); 382 | name = Dragable; 383 | sourceTree = ""; 384 | }; 385 | 76FC4A021D7865D5004CF995 /* Infinite */ = { 386 | isa = PBXGroup; 387 | children = ( 388 | 76FC49FE1D7865BB004CF995 /* MSWeekViewDecoratorInfinite.h */, 389 | 76FC49FF1D7865BB004CF995 /* MSWeekViewDecoratorInfinite.m */, 390 | ); 391 | name = Infinite; 392 | sourceTree = ""; 393 | }; 394 | 76FC4A031D7865DE004CF995 /* NewEvent */ = { 395 | isa = PBXGroup; 396 | children = ( 397 | 76FC4A041D78678C004CF995 /* MSWeekViewDecoratorNewEvent.h */, 398 | 76FC4A051D78678C004CF995 /* MSWeekViewDecoratorNewEvent.m */, 399 | ); 400 | name = NewEvent; 401 | sourceTree = ""; 402 | }; 403 | C8C01CCD2324837475AD4513 /* Pods */ = { 404 | isa = PBXGroup; 405 | children = ( 406 | 55A9198AF6C016D51B48E4CB /* Pods-RVCalendarWeekView.debug.xcconfig */, 407 | 016043077DD4C904B6A3A6BE /* Pods-RVCalendarWeekView.release.xcconfig */, 408 | ); 409 | name = Pods; 410 | sourceTree = ""; 411 | }; 412 | /* End PBXGroup section */ 413 | 414 | /* Begin PBXNativeTarget section */ 415 | 76276EB11D6B81D4002C1D39 /* RVCalendarWeekView */ = { 416 | isa = PBXNativeTarget; 417 | buildConfigurationList = 76276ED41D6B81D4002C1D39 /* Build configuration list for PBXNativeTarget "RVCalendarWeekView" */; 418 | buildPhases = ( 419 | 190AB3F50BB3DB5A2BD3C011 /* [CP] Check Pods Manifest.lock */, 420 | 76276EAE1D6B81D4002C1D39 /* Sources */, 421 | 76276EAF1D6B81D4002C1D39 /* Frameworks */, 422 | 76276EB01D6B81D4002C1D39 /* Resources */, 423 | 5A14EB676F95966CC7FC0790 /* [CP] Copy Pods Resources */, 424 | ); 425 | buildRules = ( 426 | ); 427 | dependencies = ( 428 | ); 429 | name = RVCalendarWeekView; 430 | productName = RVCalendarWeekView; 431 | productReference = 76276EB21D6B81D4002C1D39 /* RVCalendarWeekView.app */; 432 | productType = "com.apple.product-type.application"; 433 | }; 434 | 76276ECA1D6B81D4002C1D39 /* RVCalendarWeekViewTests */ = { 435 | isa = PBXNativeTarget; 436 | buildConfigurationList = 76276ED71D6B81D4002C1D39 /* Build configuration list for PBXNativeTarget "RVCalendarWeekViewTests" */; 437 | buildPhases = ( 438 | 76276EC71D6B81D4002C1D39 /* Sources */, 439 | 76276EC81D6B81D4002C1D39 /* Frameworks */, 440 | 76276EC91D6B81D4002C1D39 /* Resources */, 441 | ); 442 | buildRules = ( 443 | ); 444 | dependencies = ( 445 | 76276ECD1D6B81D4002C1D39 /* PBXTargetDependency */, 446 | ); 447 | name = RVCalendarWeekViewTests; 448 | productName = RVCalendarWeekViewTests; 449 | productReference = 76276ECB1D6B81D4002C1D39 /* RVCalendarWeekViewTests.xctest */; 450 | productType = "com.apple.product-type.bundle.unit-test"; 451 | }; 452 | /* End PBXNativeTarget section */ 453 | 454 | /* Begin PBXProject section */ 455 | 76276EAA1D6B81D4002C1D39 /* Project object */ = { 456 | isa = PBXProject; 457 | attributes = { 458 | LastUpgradeCheck = 0800; 459 | ORGANIZATIONNAME = revo; 460 | TargetAttributes = { 461 | 76276EB11D6B81D4002C1D39 = { 462 | CreatedOnToolsVersion = 7.3.1; 463 | DevelopmentTeam = F2VSE3YKKD; 464 | }; 465 | 76276ECA1D6B81D4002C1D39 = { 466 | CreatedOnToolsVersion = 7.3.1; 467 | TestTargetID = 76276EB11D6B81D4002C1D39; 468 | }; 469 | }; 470 | }; 471 | buildConfigurationList = 76276EAD1D6B81D4002C1D39 /* Build configuration list for PBXProject "RVCalendarWeekView" */; 472 | compatibilityVersion = "Xcode 3.2"; 473 | developmentRegion = English; 474 | hasScannedForEncodings = 0; 475 | knownRegions = ( 476 | en, 477 | Base, 478 | ); 479 | mainGroup = 76276EA91D6B81D4002C1D39; 480 | productRefGroup = 76276EB31D6B81D4002C1D39 /* Products */; 481 | projectDirPath = ""; 482 | projectRoot = ""; 483 | targets = ( 484 | 76276EB11D6B81D4002C1D39 /* RVCalendarWeekView */, 485 | 76276ECA1D6B81D4002C1D39 /* RVCalendarWeekViewTests */, 486 | ); 487 | }; 488 | /* End PBXProject section */ 489 | 490 | /* Begin PBXResourcesBuildPhase section */ 491 | 76276EB01D6B81D4002C1D39 /* Resources */ = { 492 | isa = PBXResourcesBuildPhase; 493 | buildActionMask = 2147483647; 494 | files = ( 495 | 768458321D7997BE0080A27A /* RVCalendarWeekView.podspec.json in Resources */, 496 | 768458301D7996C70080A27A /* Podfile in Resources */, 497 | 76276EC51D6B81D4002C1D39 /* LaunchScreen.storyboard in Resources */, 498 | 76276EC21D6B81D4002C1D39 /* Assets.xcassets in Resources */, 499 | 76276EC01D6B81D4002C1D39 /* Main.storyboard in Resources */, 500 | ); 501 | runOnlyForDeploymentPostprocessing = 0; 502 | }; 503 | 76276EC91D6B81D4002C1D39 /* Resources */ = { 504 | isa = PBXResourcesBuildPhase; 505 | buildActionMask = 2147483647; 506 | files = ( 507 | ); 508 | runOnlyForDeploymentPostprocessing = 0; 509 | }; 510 | /* End PBXResourcesBuildPhase section */ 511 | 512 | /* Begin PBXShellScriptBuildPhase section */ 513 | 190AB3F50BB3DB5A2BD3C011 /* [CP] Check Pods Manifest.lock */ = { 514 | isa = PBXShellScriptBuildPhase; 515 | buildActionMask = 2147483647; 516 | files = ( 517 | ); 518 | inputPaths = ( 519 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock", 520 | "${PODS_ROOT}/Manifest.lock", 521 | ); 522 | name = "[CP] Check Pods Manifest.lock"; 523 | outputPaths = ( 524 | "$(DERIVED_FILE_DIR)/Pods-RVCalendarWeekView-checkManifestLockResult.txt", 525 | ); 526 | runOnlyForDeploymentPostprocessing = 0; 527 | shellPath = /bin/sh; 528 | shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; 529 | showEnvVarsInLog = 0; 530 | }; 531 | 5A14EB676F95966CC7FC0790 /* [CP] Copy Pods Resources */ = { 532 | isa = PBXShellScriptBuildPhase; 533 | buildActionMask = 2147483647; 534 | files = ( 535 | ); 536 | inputPaths = ( 537 | "${SRCROOT}/Pods/Target Support Files/Pods-RVCalendarWeekView/Pods-RVCalendarWeekView-resources.sh", 538 | "${PODS_ROOT}/DateTools/DateTools/DateTools/DateTools.bundle", 539 | "${PODS_ROOT}/RVUtils/RVUtils/storyboards/RVPin.storyboard", 540 | ); 541 | name = "[CP] Copy Pods Resources"; 542 | outputPaths = ( 543 | "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/DateTools.bundle", 544 | "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/RVPin.storyboardc", 545 | ); 546 | runOnlyForDeploymentPostprocessing = 0; 547 | shellPath = /bin/sh; 548 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-RVCalendarWeekView/Pods-RVCalendarWeekView-resources.sh\"\n"; 549 | showEnvVarsInLog = 0; 550 | }; 551 | /* End PBXShellScriptBuildPhase section */ 552 | 553 | /* Begin PBXSourcesBuildPhase section */ 554 | 76276EAE1D6B81D4002C1D39 /* Sources */ = { 555 | isa = PBXSourcesBuildPhase; 556 | buildActionMask = 2147483647; 557 | files = ( 558 | 763A802A1D6C4488002E0CBF /* MSDragableEvent.m in Sources */, 559 | 76276EF51D6B826B002C1D39 /* MSCollectionViewCalendarLayout.m in Sources */, 560 | 76FC4A001D7865BB004CF995 /* MSWeekViewDecoratorInfinite.m in Sources */, 561 | 7646D59E1DA68FC7001B8379 /* MSWeekendBackground.m in Sources */, 562 | 768458251D7847080080A27A /* MSWeekViewDecorator.m in Sources */, 563 | 76276F051D6B8759002C1D39 /* MSEvent.m in Sources */, 564 | 7630AD5A1DA3FA80006D8FDC /* MSHourPerdiod.m in Sources */, 565 | 76276EFB1D6B826B002C1D39 /* MSEventCell.m in Sources */, 566 | 76276EBD1D6B81D4002C1D39 /* ViewController.m in Sources */, 567 | 768458281D7847D80080A27A /* MSWeekViewDecoratorDragable.m in Sources */, 568 | 76276EFD1D6B826B002C1D39 /* MSTimeRowHeader.m in Sources */, 569 | 76276EF71D6B826B002C1D39 /* MSCurrentTimeIndicator.m in Sources */, 570 | 766E7E1D1D6B9C9F007A410C /* MSWeekView.m in Sources */, 571 | 76276EF81D6B826B002C1D39 /* MSDayColumnHeader.m in Sources */, 572 | 76276EBA1D6B81D4002C1D39 /* AppDelegate.m in Sources */, 573 | 76FC4A061D78678C004CF995 /* MSWeekViewDecoratorNewEvent.m in Sources */, 574 | 7630AD5D1DA4018A006D8FDC /* MSUnavailableHour.m in Sources */, 575 | 7657ACDF1DA7A5F300C4FA68 /* MSWeekViewDecoratorChangeDuration.m in Sources */, 576 | 76FC4A091D786E7F004CF995 /* MSWeekViewDecoratorFactory.m in Sources */, 577 | 7657ACE21DA7B20500C4FA68 /* MSDurationChangeIndicator.m in Sources */, 578 | 76276EF61D6B826B002C1D39 /* MSCurrentTimeGridline.m in Sources */, 579 | 76276EFC1D6B826B002C1D39 /* MSGridline.m in Sources */, 580 | 76276EB71D6B81D4002C1D39 /* main.m in Sources */, 581 | 76276EFE1D6B826B002C1D39 /* MSTimeRowHeaderBackground.m in Sources */, 582 | 76276EF91D6B826B002C1D39 /* MSDayColumnHeaderBackground.m in Sources */, 583 | 7684582C1D7961350080A27A /* MSWeekViewDecoratorPinchable.m in Sources */, 584 | 609E91FDC500BF0231C2C658 /* MSWeekViewDecoratorChangeDurationAndDragable.m in Sources */, 585 | ); 586 | runOnlyForDeploymentPostprocessing = 0; 587 | }; 588 | 76276EC71D6B81D4002C1D39 /* Sources */ = { 589 | isa = PBXSourcesBuildPhase; 590 | buildActionMask = 2147483647; 591 | files = ( 592 | 76276ED01D6B81D4002C1D39 /* RVCalendarWeekViewTests.m in Sources */, 593 | ); 594 | runOnlyForDeploymentPostprocessing = 0; 595 | }; 596 | /* End PBXSourcesBuildPhase section */ 597 | 598 | /* Begin PBXTargetDependency section */ 599 | 76276ECD1D6B81D4002C1D39 /* PBXTargetDependency */ = { 600 | isa = PBXTargetDependency; 601 | target = 76276EB11D6B81D4002C1D39 /* RVCalendarWeekView */; 602 | targetProxy = 76276ECC1D6B81D4002C1D39 /* PBXContainerItemProxy */; 603 | }; 604 | /* End PBXTargetDependency section */ 605 | 606 | /* Begin PBXVariantGroup section */ 607 | 76276EBE1D6B81D4002C1D39 /* Main.storyboard */ = { 608 | isa = PBXVariantGroup; 609 | children = ( 610 | 76276EBF1D6B81D4002C1D39 /* Base */, 611 | ); 612 | name = Main.storyboard; 613 | sourceTree = ""; 614 | }; 615 | 76276EC31D6B81D4002C1D39 /* LaunchScreen.storyboard */ = { 616 | isa = PBXVariantGroup; 617 | children = ( 618 | 76276EC41D6B81D4002C1D39 /* Base */, 619 | ); 620 | name = LaunchScreen.storyboard; 621 | sourceTree = ""; 622 | }; 623 | /* End PBXVariantGroup section */ 624 | 625 | /* Begin XCBuildConfiguration section */ 626 | 76276ED21D6B81D4002C1D39 /* Debug */ = { 627 | isa = XCBuildConfiguration; 628 | buildSettings = { 629 | ALWAYS_SEARCH_USER_PATHS = NO; 630 | CLANG_ANALYZER_NONNULL = YES; 631 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 632 | CLANG_CXX_LIBRARY = "libc++"; 633 | CLANG_ENABLE_MODULES = YES; 634 | CLANG_ENABLE_OBJC_ARC = YES; 635 | CLANG_WARN_BOOL_CONVERSION = YES; 636 | CLANG_WARN_CONSTANT_CONVERSION = YES; 637 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 638 | CLANG_WARN_EMPTY_BODY = YES; 639 | CLANG_WARN_ENUM_CONVERSION = YES; 640 | CLANG_WARN_INFINITE_RECURSION = YES; 641 | CLANG_WARN_INT_CONVERSION = YES; 642 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 643 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 644 | CLANG_WARN_UNREACHABLE_CODE = YES; 645 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 646 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 647 | COPY_PHASE_STRIP = NO; 648 | DEBUG_INFORMATION_FORMAT = dwarf; 649 | ENABLE_STRICT_OBJC_MSGSEND = YES; 650 | ENABLE_TESTABILITY = YES; 651 | GCC_C_LANGUAGE_STANDARD = gnu99; 652 | GCC_DYNAMIC_NO_PIC = NO; 653 | GCC_NO_COMMON_BLOCKS = YES; 654 | GCC_OPTIMIZATION_LEVEL = 0; 655 | GCC_PREPROCESSOR_DEFINITIONS = ( 656 | "DEBUG=1", 657 | "$(inherited)", 658 | ); 659 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 660 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 661 | GCC_WARN_UNDECLARED_SELECTOR = YES; 662 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 663 | GCC_WARN_UNUSED_FUNCTION = YES; 664 | GCC_WARN_UNUSED_VARIABLE = YES; 665 | IPHONEOS_DEPLOYMENT_TARGET = 9.3; 666 | MTL_ENABLE_DEBUG_INFO = YES; 667 | ONLY_ACTIVE_ARCH = YES; 668 | SDKROOT = iphoneos; 669 | TARGETED_DEVICE_FAMILY = "1,2"; 670 | }; 671 | name = Debug; 672 | }; 673 | 76276ED31D6B81D4002C1D39 /* Release */ = { 674 | isa = XCBuildConfiguration; 675 | buildSettings = { 676 | ALWAYS_SEARCH_USER_PATHS = NO; 677 | CLANG_ANALYZER_NONNULL = YES; 678 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 679 | CLANG_CXX_LIBRARY = "libc++"; 680 | CLANG_ENABLE_MODULES = YES; 681 | CLANG_ENABLE_OBJC_ARC = YES; 682 | CLANG_WARN_BOOL_CONVERSION = YES; 683 | CLANG_WARN_CONSTANT_CONVERSION = YES; 684 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 685 | CLANG_WARN_EMPTY_BODY = YES; 686 | CLANG_WARN_ENUM_CONVERSION = YES; 687 | CLANG_WARN_INFINITE_RECURSION = YES; 688 | CLANG_WARN_INT_CONVERSION = YES; 689 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 690 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 691 | CLANG_WARN_UNREACHABLE_CODE = YES; 692 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 693 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 694 | COPY_PHASE_STRIP = NO; 695 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 696 | ENABLE_NS_ASSERTIONS = NO; 697 | ENABLE_STRICT_OBJC_MSGSEND = YES; 698 | GCC_C_LANGUAGE_STANDARD = gnu99; 699 | GCC_NO_COMMON_BLOCKS = YES; 700 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 701 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 702 | GCC_WARN_UNDECLARED_SELECTOR = YES; 703 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 704 | GCC_WARN_UNUSED_FUNCTION = YES; 705 | GCC_WARN_UNUSED_VARIABLE = YES; 706 | IPHONEOS_DEPLOYMENT_TARGET = 9.3; 707 | MTL_ENABLE_DEBUG_INFO = NO; 708 | SDKROOT = iphoneos; 709 | TARGETED_DEVICE_FAMILY = "1,2"; 710 | VALIDATE_PRODUCT = YES; 711 | }; 712 | name = Release; 713 | }; 714 | 76276ED51D6B81D4002C1D39 /* Debug */ = { 715 | isa = XCBuildConfiguration; 716 | baseConfigurationReference = 55A9198AF6C016D51B48E4CB /* Pods-RVCalendarWeekView.debug.xcconfig */; 717 | buildSettings = { 718 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 719 | DEVELOPMENT_TEAM = F2VSE3YKKD; 720 | INFOPLIST_FILE = RVCalendarWeekView/Info.plist; 721 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 722 | PRODUCT_BUNDLE_IDENTIFIER = works.revo.RVCalendarWeekView; 723 | PRODUCT_NAME = "$(TARGET_NAME)"; 724 | USER_HEADER_SEARCH_PATHS = "\"${PROJECT_DIR}/../Pods\"/** \"${PROJECT_DIR}/../Pods\"/**"; 725 | }; 726 | name = Debug; 727 | }; 728 | 76276ED61D6B81D4002C1D39 /* Release */ = { 729 | isa = XCBuildConfiguration; 730 | baseConfigurationReference = 016043077DD4C904B6A3A6BE /* Pods-RVCalendarWeekView.release.xcconfig */; 731 | buildSettings = { 732 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 733 | DEVELOPMENT_TEAM = F2VSE3YKKD; 734 | INFOPLIST_FILE = RVCalendarWeekView/Info.plist; 735 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 736 | PRODUCT_BUNDLE_IDENTIFIER = works.revo.RVCalendarWeekView; 737 | PRODUCT_NAME = "$(TARGET_NAME)"; 738 | USER_HEADER_SEARCH_PATHS = "\"${PROJECT_DIR}/../Pods\"/** \"${PROJECT_DIR}/../Pods\"/**"; 739 | }; 740 | name = Release; 741 | }; 742 | 76276ED81D6B81D4002C1D39 /* Debug */ = { 743 | isa = XCBuildConfiguration; 744 | buildSettings = { 745 | BUNDLE_LOADER = "$(TEST_HOST)"; 746 | INFOPLIST_FILE = RVCalendarWeekViewTests/Info.plist; 747 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 748 | PRODUCT_BUNDLE_IDENTIFIER = works.revo.RVCalendarWeekViewTests; 749 | PRODUCT_NAME = "$(TARGET_NAME)"; 750 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/RVCalendarWeekView.app/RVCalendarWeekView"; 751 | }; 752 | name = Debug; 753 | }; 754 | 76276ED91D6B81D4002C1D39 /* Release */ = { 755 | isa = XCBuildConfiguration; 756 | buildSettings = { 757 | BUNDLE_LOADER = "$(TEST_HOST)"; 758 | INFOPLIST_FILE = RVCalendarWeekViewTests/Info.plist; 759 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 760 | PRODUCT_BUNDLE_IDENTIFIER = works.revo.RVCalendarWeekViewTests; 761 | PRODUCT_NAME = "$(TARGET_NAME)"; 762 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/RVCalendarWeekView.app/RVCalendarWeekView"; 763 | }; 764 | name = Release; 765 | }; 766 | /* End XCBuildConfiguration section */ 767 | 768 | /* Begin XCConfigurationList section */ 769 | 76276EAD1D6B81D4002C1D39 /* Build configuration list for PBXProject "RVCalendarWeekView" */ = { 770 | isa = XCConfigurationList; 771 | buildConfigurations = ( 772 | 76276ED21D6B81D4002C1D39 /* Debug */, 773 | 76276ED31D6B81D4002C1D39 /* Release */, 774 | ); 775 | defaultConfigurationIsVisible = 0; 776 | defaultConfigurationName = Release; 777 | }; 778 | 76276ED41D6B81D4002C1D39 /* Build configuration list for PBXNativeTarget "RVCalendarWeekView" */ = { 779 | isa = XCConfigurationList; 780 | buildConfigurations = ( 781 | 76276ED51D6B81D4002C1D39 /* Debug */, 782 | 76276ED61D6B81D4002C1D39 /* Release */, 783 | ); 784 | defaultConfigurationIsVisible = 0; 785 | defaultConfigurationName = Release; 786 | }; 787 | 76276ED71D6B81D4002C1D39 /* Build configuration list for PBXNativeTarget "RVCalendarWeekViewTests" */ = { 788 | isa = XCConfigurationList; 789 | buildConfigurations = ( 790 | 76276ED81D6B81D4002C1D39 /* Debug */, 791 | 76276ED91D6B81D4002C1D39 /* Release */, 792 | ); 793 | defaultConfigurationIsVisible = 0; 794 | defaultConfigurationName = Release; 795 | }; 796 | /* End XCConfigurationList section */ 797 | }; 798 | rootObject = 76276EAA1D6B81D4002C1D39 /* Project object */; 799 | } 800 | -------------------------------------------------------------------------------- /RVCalendarWeekView.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /RVCalendarWeekView.xcodeproj/xcuserdata/badchoice.xcuserdatad/xcschemes/RVCalendarWeekView.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 49 | 50 | 51 | 52 | 53 | 54 | 64 | 66 | 72 | 73 | 74 | 75 | 76 | 77 | 83 | 85 | 91 | 92 | 93 | 94 | 96 | 97 | 100 | 101 | 102 | -------------------------------------------------------------------------------- /RVCalendarWeekView.xcodeproj/xcuserdata/badchoice.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | RVCalendarWeekView.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 76276EB11D6B81D4002C1D39 16 | 17 | primary 18 | 19 | 20 | 76276ECA1D6B81D4002C1D39 21 | 22 | primary 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /RVCalendarWeekView.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /RVCalendarWeekView.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /RVCalendarWeekView.xcworkspace/xcuserdata/badchoice.xcuserdatad/xcdebugger/Expressions.xcexplist: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 7 | 8 | 10 | 11 | 12 | 13 | 15 | 16 | 18 | 19 | 21 | 22 | 24 | 25 | 27 | 28 | 30 | 31 | 33 | 34 | 36 | 37 | 39 | 40 | 41 | 42 | 44 | 45 | 47 | 48 | 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /RVCalendarWeekView/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // RVCalendarWeekView 4 | // 5 | // Created by Jordi Puigdellívol on 22/8/16. 6 | // Copyright © 2016 revo. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | 16 | @end 17 | 18 | -------------------------------------------------------------------------------- /RVCalendarWeekView/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // RVCalendarWeekView 4 | // 5 | // Created by Jordi Puigdellívol on 22/8/16. 6 | // Copyright © 2016 revo. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @interface AppDelegate () 12 | 13 | @end 14 | 15 | @implementation AppDelegate 16 | 17 | 18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 19 | // Override point for customization after application launch. 20 | return YES; 21 | } 22 | 23 | - (void)applicationWillResignActive:(UIApplication *)application { 24 | // 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. 25 | // 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. 26 | } 27 | 28 | - (void)applicationDidEnterBackground:(UIApplication *)application { 29 | // 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. 30 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 31 | } 32 | 33 | - (void)applicationWillEnterForeground:(UIApplication *)application { 34 | // 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. 35 | } 36 | 37 | - (void)applicationDidBecomeActive:(UIApplication *)application { 38 | // 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. 39 | } 40 | 41 | - (void)applicationWillTerminate:(UIApplication *)application { 42 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 43 | } 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /RVCalendarWeekView/Assets.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 | "idiom" : "ipad", 35 | "size" : "29x29", 36 | "scale" : "1x" 37 | }, 38 | { 39 | "idiom" : "ipad", 40 | "size" : "29x29", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "40x40", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "40x40", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "76x76", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "76x76", 61 | "scale" : "2x" 62 | } 63 | ], 64 | "info" : { 65 | "version" : 1, 66 | "author" : "xcode" 67 | } 68 | } -------------------------------------------------------------------------------- /RVCalendarWeekView/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /RVCalendarWeekView/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /RVCalendarWeekView/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 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | UISupportedInterfaceOrientations~ipad 40 | 41 | UIInterfaceOrientationPortrait 42 | UIInterfaceOrientationPortraitUpsideDown 43 | UIInterfaceOrientationLandscapeLeft 44 | UIInterfaceOrientationLandscapeRight 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /RVCalendarWeekView/Lib/MSCollectionViewCalendarLayout/MSCollectionViewCalendarLayout.h: -------------------------------------------------------------------------------- 1 | // 2 | // MSCollectionViewCalendarLayout.h 3 | // MSCollectionViewCalendarLayout 4 | // 5 | // Created by Eric Horacek on 2/18/13. 6 | // Copyright (c) 2015 Eric Horacek. All rights reserved. 7 | // 8 | // This code is distributed under the terms and conditions of the MIT license. 9 | // 10 | // Permission is hereby granted, free of charge, to any person obtaining a copy 11 | // of this software and associated documentation files (the "Software"), to deal 12 | // in the Software without restriction, including without limitation the rights 13 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | // copies of the Software, and to permit persons to whom the Software is 15 | // furnished to do so, subject to the following conditions: 16 | // 17 | // The above copyright notice and this permission notice shall be included in 18 | // all copies or substantial portions of the Software. 19 | // 20 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 26 | // THE SOFTWARE. 27 | // 28 | 29 | #import 30 | 31 | extern NSString * const MSCollectionElementKindTimeRowHeader; 32 | extern NSString * const MSCollectionElementKindDayColumnHeader; 33 | extern NSString * const MSCollectionElementKindTimeRowHeaderBackground; 34 | extern NSString * const MSCollectionElementKindDayColumnHeaderBackground; 35 | extern NSString * const MSCollectionElementKindCurrentTimeIndicator; 36 | extern NSString * const MSCollectionElementKindCurrentTimeHorizontalGridline; 37 | extern NSString * const MSCollectionElementKindVerticalGridline; 38 | extern NSString * const MSCollectionElementKindHorizontalGridline; 39 | extern NSString * const MSCollectionElementKindUnavailableHour; 40 | extern NSString * const MSCollectionElementKindWeekendBackground; 41 | 42 | typedef NS_ENUM(NSUInteger, MSSectionLayoutType) { 43 | MSSectionLayoutTypeHorizontalTile, 44 | MSSectionLayoutTypeVerticalTile 45 | }; 46 | 47 | typedef NS_ENUM(NSUInteger, MSHeaderLayoutType) { 48 | MSHeaderLayoutTypeTimeRowAboveDayColumn, 49 | MSHeaderLayoutTypeDayColumnAboveTimeRow 50 | }; 51 | 52 | typedef NS_ENUM(NSUInteger, MSHourGridDivision) { 53 | MSHourGridDivision_NONE = 0, 54 | MSHourGridDivision_05_Minutes = 5, 55 | MSHourGridDivision_10_Minutes = 10, 56 | MSHourGridDivision_15_Minutes = 15, 57 | MSHourGridDivision_20_Minutes = 20, 58 | MSHourGridDivision_30_Minutes = 30, 59 | }; 60 | 61 | @class MSCollectionViewCalendarLayout; 62 | @protocol MSCollectionViewDelegateCalendarLayout; 63 | 64 | @interface MSCollectionViewCalendarLayout : UICollectionViewLayout 65 | 66 | @property (nonatomic, weak) id delegate; 67 | 68 | @property (nonatomic) BOOL show24Hours; 69 | @property (nonatomic) CGFloat sectionWidth; 70 | @property (nonatomic) CGFloat hourHeight; 71 | @property (nonatomic) CGFloat dayColumnHeaderHeight; 72 | @property (nonatomic) CGFloat timeRowHeaderWidth; 73 | @property (nonatomic) CGSize currentTimeIndicatorSize; 74 | @property (nonatomic) CGFloat horizontalGridlineHeight; 75 | @property (nonatomic) CGFloat verticalGridlineWidth; 76 | @property (nonatomic) CGFloat currentTimeHorizontalGridlineHeight; 77 | @property (nonatomic) MSHourGridDivision hourGridDivisionValue; 78 | @property (nonatomic) UIEdgeInsets sectionMargin; 79 | @property (nonatomic) UIEdgeInsets contentMargin; 80 | @property (nonatomic) UIEdgeInsets cellMargin; 81 | @property (nonatomic) MSSectionLayoutType sectionLayoutType; 82 | @property (nonatomic) MSHeaderLayoutType headerLayoutType; 83 | @property (nonatomic) BOOL displayHeaderBackgroundAtOrigin; 84 | 85 | 86 | - (NSInteger)earliestHour; 87 | - (NSInteger)latestHour; 88 | 89 | - (NSDate *)dateForTimeRowHeaderAtIndexPath:(NSIndexPath *)indexPath; 90 | - (NSDate *)dateForDayColumnHeaderAtIndexPath:(NSIndexPath *)indexPath; 91 | 92 | - (void)scrollCollectionViewToClosetSectionToCurrentTimeAnimated:(BOOL)animated; 93 | - (void)scrollCollectionViewToClosetSectionToTime:(NSDate*)time animated:(BOOL)animated; 94 | - (void)scrollCollectionViewToCurrentTime:(BOOL)animated; 95 | 96 | // Since a "reloadData" on the UICollectionView doesn't call "prepareForCollectionViewUpdates:", this method must be called first to flush the internal caches 97 | - (void)invalidateLayoutCache; 98 | 99 | @end 100 | 101 | @protocol MSCollectionViewDelegateCalendarLayout 102 | 103 | @required 104 | 105 | - (NSDate *)collectionView:(UICollectionView *)collectionView layout:(MSCollectionViewCalendarLayout *)collectionViewLayout dayForSection:(NSInteger)section; 106 | - (NSDate *)collectionView:(UICollectionView *)collectionView layout:(MSCollectionViewCalendarLayout *)collectionViewLayout startTimeForItemAtIndexPath:(NSIndexPath *)indexPath; 107 | - (NSDate *)collectionView:(UICollectionView *)collectionView layout:(MSCollectionViewCalendarLayout *)collectionViewLayout endTimeForItemAtIndexPath:(NSIndexPath *)indexPath; 108 | - (NSDate *)currentTimeComponentsForCollectionView:(UICollectionView *)collectionView layout:(MSCollectionViewCalendarLayout *)collectionViewLayout; 109 | -(NSArray*)unavailableHoursPeriods:(UICollectionView *)collectionView layout:(MSCollectionViewCalendarLayout *)collectionViewLayout section:(int)section; 110 | 111 | @end 112 | -------------------------------------------------------------------------------- /RVCalendarWeekView/Lib/MSWeekView.h: -------------------------------------------------------------------------------- 1 | // 2 | // RVWeekView.h 3 | // RVCalendarWeekView 4 | // 5 | // Created by Badchoice on 22/8/16. 6 | // Copyright © 2016 revo. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "MSCollectionViewCalendarLayout.h" 11 | #import "MSDragableEvent.h" 12 | #import "MSEvent.h" 13 | 14 | 15 | @protocol MSWeekViewDelegate 16 | -(void)weekView:(id)sender eventSelected:(MSEventCell*)eventCell; 17 | 18 | @optional 19 | /** 20 | * Should Return an array of MSHourPerdiod ex:(00:00,10:00) 21 | */ 22 | -(NSArray*)weekView:(id)sender unavailableHoursPeriods:(NSDate*)date; 23 | @end 24 | 25 | @interface MSWeekView : UIView 26 | { 27 | NSArray * mEvents; 28 | } 29 | 30 | @property(strong,nonatomic) UICollectionView* collectionView; 31 | @property(strong,nonatomic) MSCollectionViewCalendarLayout* weekFlowLayout; 32 | 33 | @property(nonatomic) int daysToShowOnScreen; 34 | @property(nonatomic) int daysToShow; 35 | @property(strong,nonatomic) NSArray* events; 36 | 37 | @property(weak,nonatomic) id delegate; 38 | 39 | 40 | /** Base property for storing each even on its sections, by default the key is the day 41 | but you can customize to put anything there*/ 42 | @property(strong,nonatomic) NSMutableDictionary* eventsBySection; 43 | 44 | /** 45 | * Changes these in subclass's registerClasses before calling [super registerClasses]; 46 | */ 47 | @property(nonatomic) Class eventCellClass; 48 | @property(nonatomic) Class dayColumnHeaderClass; 49 | @property(nonatomic) Class timeRowHeaderClass; 50 | 51 | /** 52 | * These are optional. If you don't want any of the decoration views, just set them to nil. 53 | */ 54 | @property(nonatomic) Class currentTimeIndicatorClass; 55 | @property(nonatomic) Class currentTimeGridlineClass; 56 | @property(nonatomic) Class verticalGridlineClass; 57 | @property(nonatomic) Class horizontalGridlineClass; 58 | @property(nonatomic) Class timeRowHeaderBackgroundClass; 59 | @property(nonatomic) Class dayColumnHeaderBackgroundClass; 60 | @property(nonatomic) Class unavailableHourClass; 61 | @property(nonatomic) Class weekendBackgroundClass; 62 | 63 | /** 64 | * Override this function to customize the views you want to use 65 | * Just change the classes that you will use 66 | */ 67 | -(void)setupSupplementaryViewClasses; 68 | 69 | /** 70 | * Call this function to reload (when 71 | */ 72 | -(void)forceReload:(BOOL)reloadEvents; 73 | 74 | -(void)addEvent :(MSEvent*)event; 75 | -(void)addEvents :(NSArray*)events; 76 | -(void)removeEvent:(MSEvent*)event; 77 | 78 | -(NSDate*)firstDay; 79 | 80 | @end 81 | -------------------------------------------------------------------------------- /RVCalendarWeekView/Lib/MSWeekView.m: -------------------------------------------------------------------------------- 1 | // 2 | // RVWeekView.m 3 | // RVCalendarWeekView 4 | // 5 | // Created by Badchoice on 22/8/16. 6 | // Copyright © 2016 revo. All rights reserved. 7 | // 8 | 9 | #import "MSWeekView.h" 10 | 11 | #import "NSDate+Easy.h" 12 | #import "RVCollection.h" 13 | 14 | #define MAS_SHORTHAND 15 | #import "Masonry.h" 16 | 17 | // Collection View Reusable Views 18 | #import "MSGridline.h" 19 | #import "MSTimeRowHeaderBackground.h" 20 | #import "MSDayColumnHeaderBackground.h" 21 | #import "MSEventCell.h" 22 | #import "MSDayColumnHeader.h" 23 | #import "MSTimeRowHeader.h" 24 | #import "MSCurrentTimeIndicator.h" 25 | #import "MSCurrentTimeGridline.h" 26 | #import "MSUnavailableHour.h" 27 | #import "MSWeekendBackground.h" 28 | 29 | #define MSEventCellReuseIdentifier @"MSEventCellReuseIdentifier" 30 | #define MSDayColumnHeaderReuseIdentifier @"MSDayColumnHeaderReuseIdentifier" 31 | #define MSTimeRowHeaderReuseIdentifier @"MSTimeRowHeaderReuseIdentifier" 32 | 33 | @implementation MSWeekView 34 | 35 | //================================================ 36 | #pragma mark - Init 37 | //================================================ 38 | -(id)initWithCoder:(NSCoder *)aDecoder{ 39 | if(self = [super initWithCoder:aDecoder]) { 40 | [self setup]; 41 | } 42 | return self; 43 | } 44 | 45 | -(id)initWithFrame:(CGRect)frame{ 46 | if(self = [super initWithFrame:frame]) { 47 | [self setup]; 48 | } 49 | return self; 50 | } 51 | 52 | -(void)setup{ 53 | self.daysToShowOnScreen = 6; 54 | self.daysToShow = 30; 55 | self.weekFlowLayout = [MSCollectionViewCalendarLayout new]; 56 | self.weekFlowLayout.delegate = self; 57 | self.collectionView = [[UICollectionView alloc] initWithFrame:self.bounds collectionViewLayout:self.weekFlowLayout]; 58 | self.collectionView.dataSource = self; 59 | self.collectionView.delegate = self; 60 | self.collectionView.directionalLockEnabled = YES; 61 | self.collectionView.showsVerticalScrollIndicator = NO; 62 | self.collectionView.showsHorizontalScrollIndicator = NO; 63 | /*if (UI_USER_INTERFACE_IDIOM() != UIUserInterfaceIdiomPad) { 64 | self.collectionView.pagingEnabled = YES; 65 | }*/ 66 | 67 | [self addSubview:self.collectionView]; 68 | [self.collectionView mas_makeConstraints:^(MASConstraintMaker *make) { 69 | make.height.equalTo(self.mas_height); 70 | make.width.equalTo(self.mas_width); 71 | make.left.equalTo(self.mas_left); 72 | make.top.equalTo(self.mas_top); 73 | }]; 74 | 75 | self.weekFlowLayout.sectionLayoutType = MSSectionLayoutTypeHorizontalTile; 76 | self.collectionView.backgroundColor = [UIColor whiteColor]; 77 | 78 | [self setupSupplementaryViewClasses]; 79 | [self registerSupplementaryViewClasses]; 80 | } 81 | 82 | -(void)setupSupplementaryViewClasses{ 83 | self.eventCellClass = MSEventCell.class; 84 | self.dayColumnHeaderClass = MSDayColumnHeader.class; 85 | self.timeRowHeaderClass = MSTimeRowHeader.class; 86 | 87 | self.currentTimeIndicatorClass = MSCurrentTimeIndicator.class; 88 | self.currentTimeGridlineClass = MSCurrentTimeGridline.class; 89 | self.verticalGridlineClass = MSGridline.class; 90 | self.horizontalGridlineClass = MSGridline.class; 91 | self.timeRowHeaderBackgroundClass = MSTimeRowHeaderBackground.class; 92 | self.dayColumnHeaderBackgroundClass = MSDayColumnHeaderBackground.class; 93 | self.unavailableHourClass = MSUnavailableHour.class; 94 | self.weekendBackgroundClass = MSWeekendBackground.class; 95 | } 96 | 97 | -(void)registerSupplementaryViewClasses{ 98 | [self.collectionView registerClass:self.eventCellClass forCellWithReuseIdentifier:MSEventCellReuseIdentifier]; 99 | [self.collectionView registerClass:self.dayColumnHeaderClass forSupplementaryViewOfKind:MSCollectionElementKindDayColumnHeader withReuseIdentifier:MSDayColumnHeaderReuseIdentifier]; 100 | [self.collectionView registerClass:self.timeRowHeaderClass forSupplementaryViewOfKind:MSCollectionElementKindTimeRowHeader withReuseIdentifier:MSTimeRowHeaderReuseIdentifier]; 101 | 102 | // These are optional. If you don't want any of the decoration views, just don't register a class for them. 103 | [self.weekFlowLayout registerClass:self.currentTimeIndicatorClass forDecorationViewOfKind:MSCollectionElementKindCurrentTimeIndicator]; 104 | [self.weekFlowLayout registerClass:self.currentTimeGridlineClass forDecorationViewOfKind:MSCollectionElementKindCurrentTimeHorizontalGridline]; 105 | [self.weekFlowLayout registerClass:self.verticalGridlineClass forDecorationViewOfKind:MSCollectionElementKindVerticalGridline]; 106 | [self.weekFlowLayout registerClass:self.horizontalGridlineClass forDecorationViewOfKind:MSCollectionElementKindHorizontalGridline]; 107 | [self.weekFlowLayout registerClass:self.timeRowHeaderBackgroundClass forDecorationViewOfKind:MSCollectionElementKindTimeRowHeaderBackground]; 108 | [self.weekFlowLayout registerClass:self.dayColumnHeaderBackgroundClass forDecorationViewOfKind:MSCollectionElementKindDayColumnHeaderBackground]; 109 | 110 | [self.weekFlowLayout registerClass:self.unavailableHourClass forDecorationViewOfKind:MSCollectionElementKindUnavailableHour]; 111 | [self.weekFlowLayout registerClass:self.weekendBackgroundClass forDecorationViewOfKind:MSCollectionElementKindWeekendBackground]; 112 | } 113 | 114 | 115 | -(void)layoutSubviews{ 116 | [super layoutSubviews]; 117 | self.weekFlowLayout.sectionWidth = self.layoutSectionWidth; 118 | } 119 | 120 | -(void)forceReload:(BOOL)reloadEvents{ 121 | dispatch_async(dispatch_get_main_queue(), ^{ 122 | if (reloadEvents) 123 | [self groupEventsBySection]; 124 | [self.weekFlowLayout invalidateLayoutCache]; 125 | [self.collectionView reloadData]; 126 | }); 127 | } 128 | 129 | - (CGFloat)layoutSectionWidth{ 130 | return (self.frame.size.width - 50) / self.daysToShowOnScreen; 131 | } 132 | 133 | -(NSDate*)firstDay{ 134 | return [self.weekFlowLayout dateForDayColumnHeaderAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]]; 135 | } 136 | 137 | //================================================ 138 | #pragma mark - Set Events 139 | //================================================ 140 | -(void)setEvents:(NSArray *)events{ 141 | mEvents = events; 142 | [self forceReload:YES]; 143 | } 144 | 145 | -(void)addEvent:(MSEvent *)event{ 146 | [self addEvents:@[event]]; 147 | } 148 | 149 | -(void)addEvents:(NSArray*)events{ 150 | self.events = [mEvents arrayByAddingObjectsFromArray:events]; 151 | [self forceReload:YES]; 152 | } 153 | 154 | -(void)removeEvent:(MSEvent*)event{ 155 | self.events = [mEvents reject:^BOOL(MSEvent* arrayEvent) { 156 | return [arrayEvent isEqual:event];; 157 | }]; 158 | [self forceReload:YES]; 159 | } 160 | 161 | /** 162 | * Note that in the standard calendar, each section is a day" 163 | */ 164 | - (void)groupEventsBySection { 165 | // NSDate* date = [NSDate today:@"device"]; //Why does it crash on some configurations? 166 | NSDate *date = [NSDate parse:NSDate.today.toDateTimeString timezone:@"device"]; //If it crashes here, comment the previous line and uncomment this one 167 | 168 | _eventsBySection = NSMutableDictionary.new; 169 | 170 | for (int i = 0; i < self.daysToShow; i++) { 171 | _eventsBySection[date.toDeviceTimezoneDateString] = [self eventsByDate:date]; 172 | date = [date addDay]; 173 | } 174 | } 175 | 176 | - (NSArray *)eventsByDate:(NSDate *)date { 177 | return [mEvents filter_:@selector(isInDay:) withObject:date]; 178 | } 179 | 180 | //================================================ 181 | #pragma mark - CollectionView Datasource 182 | //================================================ 183 | - (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView { 184 | return _eventsBySection.count; 185 | } 186 | 187 | - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section { 188 | NSString* day = _eventsBySection.allKeys.sort[section]; 189 | return [_eventsBySection[day] count]; 190 | } 191 | 192 | - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { 193 | MSEventCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:MSEventCellReuseIdentifier forIndexPath:indexPath]; 194 | NSString* day = _eventsBySection.allKeys.sort[indexPath.section]; 195 | cell.event = _eventsBySection[day][indexPath.row]; 196 | 197 | return cell; 198 | } 199 | 200 | - (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath { 201 | UICollectionReusableView *view; 202 | if (kind == MSCollectionElementKindDayColumnHeader) { 203 | MSDayColumnHeader *dayColumnHeader = [collectionView dequeueReusableSupplementaryViewOfKind:kind withReuseIdentifier:MSDayColumnHeaderReuseIdentifier forIndexPath:indexPath]; 204 | NSDate *day = [self.weekFlowLayout dateForDayColumnHeaderAtIndexPath:indexPath]; 205 | NSDate *currentDay = [self currentTimeComponentsForCollectionView:self.collectionView layout:self.weekFlowLayout]; 206 | 207 | NSDate *startOfDay = [NSCalendar.currentCalendar startOfDayForDate:day]; 208 | NSDate *startOfCurrentDay = [NSCalendar.currentCalendar startOfDayForDate:currentDay]; 209 | 210 | dayColumnHeader.day = day; 211 | dayColumnHeader.currentDay = [startOfDay isEqualToDate:startOfCurrentDay]; 212 | 213 | view = dayColumnHeader; 214 | } else if (kind == MSCollectionElementKindTimeRowHeader) { 215 | MSTimeRowHeader *timeRowHeader = [collectionView dequeueReusableSupplementaryViewOfKind:kind withReuseIdentifier:MSTimeRowHeaderReuseIdentifier forIndexPath:indexPath]; 216 | timeRowHeader.time = [self.weekFlowLayout dateForTimeRowHeaderAtIndexPath:indexPath]; 217 | view = timeRowHeader; 218 | } 219 | return view; 220 | } 221 | 222 | 223 | //================================================ 224 | #pragma mark - Week Flow Delegate 225 | //================================================ 226 | - (NSDate *)collectionView:(UICollectionView *)collectionView layout:(MSCollectionViewCalendarLayout *)collectionViewCalendarLayout dayForSection:(NSInteger)section { 227 | NSString* day = _eventsBySection.allKeys.sort[section]; 228 | return [NSDate parse:day timezone:@"device"]; 229 | } 230 | 231 | - (NSDate *)collectionView:(UICollectionView *)collectionView layout:(MSCollectionViewCalendarLayout *)collectionViewCalendarLayout startTimeForItemAtIndexPath:(NSIndexPath *)indexPath { 232 | NSString *day = _eventsBySection.allKeys.sort[indexPath.section]; 233 | MSEvent *ev = _eventsBySection[day][indexPath.row]; 234 | 235 | if ([ev.StartDate.toDeviceTimezoneDateString isEqualToString:day]) 236 | return ev.StartDate; 237 | 238 | else return [NSDate parse:str(@"%@ 00:00:00", day) timezone:@"device"]; 239 | } 240 | 241 | - (NSDate *)collectionView:(UICollectionView *)collectionView layout:(MSCollectionViewCalendarLayout *)collectionViewCalendarLayout endTimeForItemAtIndexPath:(NSIndexPath *)indexPath { 242 | NSString *day = _eventsBySection.allKeys.sort[indexPath.section]; 243 | MSEvent *ev = _eventsBySection[day][indexPath.row]; 244 | 245 | if ([ev.EndDate.toDeviceTimezoneDateString isEqualToString:day]) 246 | return ev.EndDate; 247 | 248 | else return [NSDate parse:str(@"%@ 23:59:59", day) timezone:@"device"]; 249 | } 250 | 251 | -(NSArray*)unavailableHoursPeriods:(UICollectionView *)collectionView layout:(MSCollectionViewCalendarLayout *)collectionViewLayout section:(int)section{ 252 | if ([self.delegate respondsToSelector:@selector(weekView:unavailableHoursPeriods:)]) { 253 | NSDate* date = [self collectionView:collectionView layout:collectionViewLayout dayForSection:section]; 254 | return [self.delegate weekView:self unavailableHoursPeriods:date]; 255 | } 256 | return @[]; 257 | } 258 | 259 | - (NSDate *)currentTimeComponentsForCollectionView:(UICollectionView *)collectionView layout:(MSCollectionViewCalendarLayout *)collectionViewCalendarLayout { 260 | return NSDate.date; 261 | } 262 | 263 | //================================================ 264 | #pragma mark - Collection view delegate 265 | //================================================ 266 | -(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{ 267 | if (self.delegate) { 268 | MSEventCell* cell = (MSEventCell*)[collectionView cellForItemAtIndexPath:indexPath]; 269 | [self.delegate weekView:self eventSelected:cell]; 270 | } 271 | } 272 | 273 | - (void)scrollViewDidScroll:(UIScrollView *)scrollView{ 274 | 275 | } 276 | 277 | //================================================ 278 | #pragma mark - Dealloc 279 | //================================================ 280 | -(void)dealloc{ 281 | self.collectionView.dataSource = nil; 282 | self.collectionView.delegate = nil; 283 | self.collectionView = nil; 284 | self.weekFlowLayout.delegate = nil; 285 | self.weekFlowLayout = nil; 286 | _eventsBySection = nil; 287 | } 288 | 289 | @end 290 | -------------------------------------------------------------------------------- /RVCalendarWeekView/Lib/Views/MSCurrentTimeGridline.h: -------------------------------------------------------------------------------- 1 | // 2 | // MSCurrentTimeGridline.h 3 | // Example 4 | // 5 | // Created by Eric Horacek on 2/27/13. 6 | // Copyright (c) 2015 Eric Horacek. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface MSCurrentTimeGridline : UICollectionReusableView 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /RVCalendarWeekView/Lib/Views/MSCurrentTimeGridline.m: -------------------------------------------------------------------------------- 1 | // 2 | // MSCurrentTimeGridline.m 3 | // Example 4 | // 5 | // Created by Eric Horacek on 2/27/13. 6 | // Copyright (c) 2015 Eric Horacek. All rights reserved. 7 | // 8 | 9 | #import "MSCurrentTimeGridline.h" 10 | #import "UIColor+HexString.h" 11 | 12 | @implementation MSCurrentTimeGridline 13 | 14 | - (id)initWithFrame:(CGRect)frame 15 | { 16 | self = [super initWithFrame:frame]; 17 | if (self) { 18 | self.backgroundColor = [UIColor colorWithHexString:@"fd3935"]; 19 | } 20 | return self; 21 | } 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /RVCalendarWeekView/Lib/Views/MSCurrentTimeIndicator.h: -------------------------------------------------------------------------------- 1 | // 2 | // MSCurrentTimeIndicator.h 3 | // Example 4 | // 5 | // Created by Eric Horacek on 2/27/13. 6 | // Copyright (c) 2015 Eric Horacek. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface MSCurrentTimeIndicator : UICollectionReusableView 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /RVCalendarWeekView/Lib/Views/MSCurrentTimeIndicator.m: -------------------------------------------------------------------------------- 1 | // 2 | // MSCurrentTimeIndicator.m 3 | // Example 4 | // 5 | // Created by Eric Horacek on 2/27/13. 6 | // Copyright (c) 2015 Eric Horacek. All rights reserved. 7 | // 8 | 9 | #import "MSCurrentTimeIndicator.h" 10 | 11 | #define MAS_SHORTHAND 12 | #import "Masonry.h" 13 | #import "UIColor+HexString.h" 14 | 15 | #import "NSDate+Easy.h" 16 | 17 | @interface MSCurrentTimeIndicator () 18 | 19 | @property (nonatomic, strong) UILabel *time; 20 | @property (nonatomic, retain) NSTimer *minuteTimer; 21 | 22 | @end 23 | 24 | @implementation MSCurrentTimeIndicator 25 | 26 | - (id)initWithFrame:(CGRect)frame 27 | { 28 | self = [super initWithFrame:frame]; 29 | if (self) { 30 | 31 | self.backgroundColor = [UIColor whiteColor]; 32 | self.time = [UILabel new]; 33 | self.time.font = [UIFont boldSystemFontOfSize:10.0]; 34 | self.time.textColor = [UIColor colorWithHexString:@"fd3935"]; 35 | [self addSubview:self.time]; 36 | 37 | [self.time mas_makeConstraints:^(MASConstraintMaker *make) { 38 | make.centerY.equalTo(self.mas_centerY); 39 | make.right .equalTo(self.mas_right).offset(-5.0); 40 | }]; 41 | 42 | self.minuteTimer = [[NSTimer alloc] initWithFireDate:NSDate.nextMinute interval:60 43 | target:self 44 | selector:@selector(minuteTick:) 45 | userInfo:nil 46 | repeats:YES]; 47 | [NSRunLoop.currentRunLoop addTimer:self.minuteTimer forMode:NSDefaultRunLoopMode]; 48 | 49 | [self updateTime]; 50 | } 51 | return self; 52 | } 53 | 54 | #pragma mark - MSCurrentTimeIndicator 55 | - (void)minuteTick:(id)sender{ 56 | [self updateTime]; 57 | } 58 | 59 | - (void)updateTime 60 | { 61 | self.time.text = [NSDate.now format:@"h:mm aa" timezone:@"device"]; 62 | [self.time sizeToFit]; 63 | } 64 | 65 | @end 66 | -------------------------------------------------------------------------------- /RVCalendarWeekView/Lib/Views/MSDayColumnHeader.h: -------------------------------------------------------------------------------- 1 | // 2 | // MSDayColumnHeader.h 3 | // Example 4 | // 5 | // Created by Eric Horacek on 2/26/13. 6 | // Copyright (c) 2015 Eric Horacek. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface MSDayColumnHeader : UICollectionReusableView 12 | 13 | @property (nonatomic, strong) NSDate *day; 14 | @property (nonatomic, assign) BOOL currentDay; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /RVCalendarWeekView/Lib/Views/MSDayColumnHeader.m: -------------------------------------------------------------------------------- 1 | // 2 | // MSDayColumnHeader.m 3 | // Example 4 | // 5 | // Created by Eric Horacek on 2/26/13. 6 | // Copyright (c) 2015 Eric Horacek. All rights reserved. 7 | // 8 | 9 | #import "MSDayColumnHeader.h" 10 | #define MAS_SHORTHAND 11 | #import "Masonry.h" 12 | #import "UIColor+HexString.h" 13 | 14 | @interface MSDayColumnHeader () 15 | 16 | @property (nonatomic, strong) UILabel *title; 17 | @property (nonatomic, strong) UIView *titleBackground; 18 | 19 | @end 20 | 21 | @implementation MSDayColumnHeader 22 | 23 | - (id)initWithFrame:(CGRect)frame 24 | { 25 | self = [super initWithFrame:frame]; 26 | if (self) { 27 | 28 | self.titleBackground = [UIView new]; 29 | self.titleBackground.layer.cornerRadius = nearbyintf(15.0); 30 | [self addSubview:self.titleBackground]; 31 | 32 | self.backgroundColor = [UIColor clearColor]; 33 | self.title = [UILabel new]; 34 | self.title.backgroundColor = [UIColor clearColor]; 35 | [self addSubview:self.title]; 36 | 37 | [self.titleBackground mas_makeConstraints:^(MASConstraintMaker *make) { 38 | make.edges.equalTo(self).with.insets(UIEdgeInsetsMake(8.0, 4.0, 8.0, 4.0)); 39 | }]; 40 | 41 | [self.title mas_makeConstraints:^(MASConstraintMaker *make) { 42 | make.edges.equalTo(self.titleBackground).with.insets(UIEdgeInsetsMake(4.0, 4.0, 4.0, 4.0)); 43 | }]; 44 | } 45 | return self; 46 | } 47 | 48 | - (void)setDay:(NSDate *)day 49 | { 50 | _day = day; 51 | 52 | static NSDateFormatter *dateFormatter; 53 | if (!dateFormatter) { 54 | dateFormatter = [NSDateFormatter new]; 55 | dateFormatter.dateFormat = ((UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) ? @"EEE MMMM d, YYYY" : @"EEE d"); 56 | } 57 | self.title.text = [dateFormatter stringFromDate:day]; 58 | self.title.adjustsFontSizeToFitWidth = YES; 59 | [self setNeedsLayout]; 60 | } 61 | 62 | - (void)setCurrentDay:(BOOL)currentDay 63 | { 64 | _currentDay = currentDay; 65 | 66 | if (currentDay) { 67 | self.title.textColor = [UIColor whiteColor]; 68 | self.title.font = [UIFont boldSystemFontOfSize:16.0]; 69 | self.titleBackground.backgroundColor = [UIColor colorWithHexString:@"fd3935"]; 70 | } else { 71 | self.title.font = [UIFont systemFontOfSize:16.0]; 72 | self.title.textColor = [UIColor blackColor]; 73 | self.titleBackground.backgroundColor = [UIColor clearColor]; 74 | } 75 | } 76 | 77 | @end 78 | -------------------------------------------------------------------------------- /RVCalendarWeekView/Lib/Views/MSDayColumnHeaderBackground.h: -------------------------------------------------------------------------------- 1 | // 2 | // MSDayColumnHeaderBackground.h 3 | // Example 4 | // 5 | // Created by Eric Horacek on 2/28/13. 6 | // Copyright (c) 2015 Eric Horacek. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface MSDayColumnHeaderBackground : UICollectionReusableView 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /RVCalendarWeekView/Lib/Views/MSDayColumnHeaderBackground.m: -------------------------------------------------------------------------------- 1 | // 2 | // MSDayColumnHeaderBackground.m 3 | // Example 4 | // 5 | // Created by Eric Horacek on 2/28/13. 6 | // Copyright (c) 2015 Eric Horacek. All rights reserved. 7 | // 8 | 9 | #import "MSDayColumnHeaderBackground.h" 10 | #import "UIColor+HexString.h" 11 | 12 | #define BOTTOM_BORDER_WIDTH 4 13 | 14 | @implementation MSDayColumnHeaderBackground 15 | 16 | - (id)initWithFrame:(CGRect)frame 17 | { 18 | self = [super initWithFrame:frame]; 19 | if (self) { 20 | self.backgroundColor = [UIColor colorWithHexString:@"f7f7f7"]; 21 | 22 | //Until sticky headers without bounce.. we can't to that 23 | /*self.backgroundColor = UIColor.whiteColor; 24 | UIView* bottomBorder = [[UIView alloc] initWithFrame:CGRectMake(0, self.frame.size.height-BOTTOM_BORDER_WIDTH, self.frame.size.width, BOTTOM_BORDER_WIDTH)]; 25 | bottomBorder.backgroundColor = [UIColor colorWithHexString:@"d7d7d7"]; 26 | [self addSubview:bottomBorder];*/ 27 | 28 | } 29 | return self; 30 | } 31 | 32 | @end 33 | -------------------------------------------------------------------------------- /RVCalendarWeekView/Lib/Views/MSDragableEvent.h: -------------------------------------------------------------------------------- 1 | // 2 | // MSDragableEvent.h 3 | // RVCalendarWeekView 4 | // 5 | // Created by Jordi Puigdellívol on 23/8/16. 6 | // Copyright © 2016 revo. All rights reserved. 7 | // 8 | 9 | #import "MSEventCell.h" 10 | 11 | @interface MSDragableEvent : MSEventCell{ 12 | CGPoint _originalPosition; 13 | CGPoint _touchOffset; 14 | } 15 | 16 | +(MSDragableEvent*)makeWithEventCell:(MSEventCell*)eventCell andOffset:(CGPoint)offset touchOffset:(CGPoint)touchOffset; 17 | 18 | @property (strong,nonatomic) UILabel* timeLabel; 19 | 20 | @property(nonatomic) CGPoint touchOffset; 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /RVCalendarWeekView/Lib/Views/MSDragableEvent.m: -------------------------------------------------------------------------------- 1 | // 2 | // MSDragableEvent.m 3 | // RVCalendarWeekView 4 | // 5 | // Created by Jordi Puigdellívol on 23/8/16. 6 | // Copyright © 2016 revo. All rights reserved. 7 | // 8 | 9 | #import "MSDragableEvent.h" 10 | 11 | #define MAS_SHORTHAND 12 | #import "Masonry.h" 13 | 14 | 15 | @interface MSEventCell () 16 | - (UIColor *)textColorHighlighted:(BOOL)selected; 17 | @end 18 | 19 | 20 | @implementation MSDragableEvent 21 | 22 | +(MSDragableEvent*)makeWithEventCell:(MSEventCell*)eventCell andOffset:(CGPoint)offset touchOffset:(CGPoint)touchOffset{ 23 | 24 | CGRect newFrame = CGRectMake(eventCell.frame.origin.x - offset.x, 25 | eventCell.frame.origin.y - offset.y, 26 | eventCell.frame.size.width, eventCell.frame.size.height); 27 | 28 | MSDragableEvent *dragCell = [[MSDragableEvent alloc] initWithFrame:newFrame]; 29 | dragCell.touchOffset = touchOffset; 30 | dragCell.event = eventCell.event; 31 | dragCell.backgroundColor = [eventCell backgroundColorHighlighted:YES]; 32 | dragCell.title.textColor = [eventCell textColorHighlighted:YES]; 33 | dragCell.location.textColor = [eventCell textColorHighlighted:YES]; 34 | 35 | return dragCell; 36 | } 37 | 38 | -(id)initWithFrame:(CGRect)frame{ 39 | if(self = [super initWithFrame:frame]){ 40 | 41 | CGFloat borderWidth = 2.0; 42 | UIEdgeInsets contentPadding = UIEdgeInsetsMake(1.0, (borderWidth + 4.0), 1.0, 4.0); 43 | 44 | self.timeLabel = [UILabel new]; 45 | self.timeLabel.font = [UIFont systemFontOfSize:12]; 46 | self.timeLabel.textColor = UIColor.blackColor; 47 | self.timeLabel.textAlignment = NSTextAlignmentRight; 48 | [self addSubview:self.timeLabel]; 49 | 50 | [self.timeLabel mas_makeConstraints:^(MASConstraintMaker *make) { 51 | make.top.equalTo (self.mas_top) .offset(-15); 52 | make.left.equalTo (self.mas_left) .offset(contentPadding.left); 53 | make.right.equalTo (self.mas_right).offset(-contentPadding.right); 54 | }]; 55 | 56 | self.timeLabel.text = @"--"; 57 | } 58 | return self; 59 | } 60 | 61 | 62 | @end 63 | -------------------------------------------------------------------------------- /RVCalendarWeekView/Lib/Views/MSDurationChangeIndicator.h: -------------------------------------------------------------------------------- 1 | // 2 | // MSDurationChangeIndicator.h 3 | // RVCalendarWeekView 4 | // 5 | // Created by Jordi Puigdellívol on 7/10/16. 6 | // Copyright © 2016 revo. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "MSEventCell.h" 11 | 12 | @protocol MSDurationIndicatorDelegate 13 | -(void)durationIndicatorStartUpdated:(id)sender y:(int)y; 14 | -(void)durationIndicatorEndUpdated:(id)sender y:(int)y; 15 | -(void)durationIndicatorEnded:(id)sender; 16 | @end 17 | 18 | @interface MSDurationChangeIndicator : UIView{ 19 | BOOL mIsStart; 20 | } 21 | 22 | 23 | @property(weak,nonatomic) iddelegate; 24 | @property(weak,nonatomic) MSEventCell* eventCell; 25 | @property(strong,nonatomic) UILabel* timeLabel; 26 | 27 | +(MSDurationChangeIndicator*)makeForStartWithCell:(MSEventCell*)cell andDelegate:(id)delegate; 28 | +(MSDurationChangeIndicator*)makeForEndWithCell:(MSEventCell*)cell andDelegate:(id)delegate; 29 | 30 | -(void)updatePosition; 31 | 32 | 33 | @end 34 | -------------------------------------------------------------------------------- /RVCalendarWeekView/Lib/Views/MSDurationChangeIndicator.m: -------------------------------------------------------------------------------- 1 | // 2 | // MSDurationChangeIndicator.m 3 | // RVCalendarWeekView 4 | // 5 | // Created by Jordi Puigdellívol on 7/10/16. 6 | // Copyright © 2016 revo. All rights reserved. 7 | // 8 | 9 | #import "MSDurationChangeIndicator.h" 10 | #define INDICATOR_TOUCH_SIZE 30 11 | #define INDICATOR_SIZE 10 12 | #define Y_MARGIN 5 13 | 14 | @implementation MSDurationChangeIndicator 15 | 16 | +(MSDurationChangeIndicator*)makeForStartWithCell:(MSEventCell*)eventCell andDelegate:(id)delegate{ 17 | MSDurationChangeIndicator* durationChange = [[MSDurationChangeIndicator alloc] initWithFrame:[self.class getFrameFor:eventCell start:YES]]; 18 | [durationChange setup:YES eventCell:eventCell andDelegate:delegate]; 19 | return durationChange; 20 | } 21 | 22 | +(MSDurationChangeIndicator*)makeForEndWithCell:(MSEventCell*)eventCell andDelegate:(id)delegate{ 23 | MSDurationChangeIndicator* durationChange = [[MSDurationChangeIndicator alloc] initWithFrame:[self.class getFrameFor:eventCell start:NO]]; 24 | [durationChange setup:NO eventCell:eventCell andDelegate:delegate]; 25 | return durationChange; 26 | } 27 | 28 | +(CGRect)getFrameFor:(MSEventCell*)cell start:(BOOL)start{ 29 | if(start){ 30 | return CGRectMake(cell.frame.size.width - INDICATOR_TOUCH_SIZE - Y_MARGIN * 2, 31 | Y_MARGIN, 32 | INDICATOR_TOUCH_SIZE, 33 | INDICATOR_TOUCH_SIZE); 34 | } 35 | else{ 36 | return CGRectMake(Y_MARGIN, 37 | cell.frame.size.height - INDICATOR_TOUCH_SIZE - Y_MARGIN, 38 | INDICATOR_TOUCH_SIZE, 39 | INDICATOR_TOUCH_SIZE); 40 | } 41 | } 42 | 43 | -(void)updatePosition{ 44 | self.frame = [self.class getFrameFor:self.eventCell start:mIsStart]; 45 | } 46 | 47 | -(void)setup:(BOOL)isStart eventCell:(MSEventCell*)eventCell andDelegate:(id)delegate{ 48 | mIsStart = isStart; 49 | self.backgroundColor = [UIColor clearColor]; 50 | self.delegate = delegate; 51 | self.eventCell = eventCell; 52 | [eventCell addSubview:self]; 53 | [self addWhiteBall]; 54 | [self addDragGestureRecognizer]; 55 | [self addTimeLabel]; 56 | } 57 | 58 | -(void)addWhiteBall{ 59 | UIView* ball; 60 | if(mIsStart){ ball = [[UIView alloc] initWithFrame:CGRectMake(20, 0, INDICATOR_SIZE, INDICATOR_SIZE)]; 61 | }else{ 62 | ball = [[UIView alloc] initWithFrame:CGRectMake(0, 16, INDICATOR_SIZE, INDICATOR_SIZE)]; 63 | } 64 | ball.backgroundColor = [UIColor whiteColor]; 65 | ball.layer.masksToBounds = YES; 66 | ball.layer.cornerRadius = ball.frame.size.width * 0.5; 67 | ball.layer.borderColor = [UIColor darkGrayColor].CGColor; 68 | ball.layer.borderWidth = 1.0; 69 | [self addSubview:ball]; 70 | } 71 | 72 | -(void)addTimeLabel{ 73 | if(mIsStart){ 74 | self.timeLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, -25, 80, 20)]; 75 | } 76 | else{ 77 | self.timeLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 35, 80, 20)]; 78 | } 79 | self.timeLabel.text = @""; 80 | self.timeLabel.font = [UIFont systemFontOfSize:12]; 81 | self.timeLabel.textColor = [UIColor blackColor]; 82 | [self addSubview:_timeLabel]; 83 | } 84 | 85 | -(void)addDragGestureRecognizer{ 86 | UILongPressGestureRecognizer* lpgr = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(onPress:)]; 87 | lpgr.minimumPressDuration = 0.01; 88 | [self addGestureRecognizer:lpgr]; 89 | } 90 | 91 | -(void)onPress:(UIGestureRecognizer*)gestureRecognizer{ 92 | if(!self.delegate) return; 93 | 94 | if(gestureRecognizer.state == UIGestureRecognizerStateChanged){ 95 | if(mIsStart){ 96 | CGPoint cp = [gestureRecognizer locationInView:self]; 97 | [self.delegate durationIndicatorStartUpdated:self y:cp.y]; 98 | } 99 | else{ 100 | CGPoint cp = [gestureRecognizer locationInView:self.superview]; 101 | self.frame = CGRectMake(self.frame.origin.x, cp.y - INDICATOR_TOUCH_SIZE - Y_MARGIN, INDICATOR_TOUCH_SIZE, INDICATOR_TOUCH_SIZE); 102 | [self.delegate durationIndicatorEndUpdated:self y:cp.y]; 103 | } 104 | } 105 | else if(gestureRecognizer.state == UIGestureRecognizerStateEnded){ 106 | [self.delegate durationIndicatorEnded:self]; 107 | } 108 | } 109 | @end 110 | -------------------------------------------------------------------------------- /RVCalendarWeekView/Lib/Views/MSEvent.h: -------------------------------------------------------------------------------- 1 | // 2 | // AKEvent.h 3 | // Example 4 | // 5 | // Created by ak on 18.01.2016. 6 | // Copyright © 2016 Eric Horacek. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface MSEvent : DTTimePeriod 13 | 14 | 15 | @property (nonatomic, strong) NSString *title; 16 | @property (nonatomic, strong) NSString *location; 17 | 18 | +(instancetype)make:(NSDate*)start title:(NSString*)title subtitle:(NSString*)subtitle; 19 | +(instancetype)make:(NSDate*)start end:(NSDate*)end title:(NSString*)title subtitle:(NSString*)subtitle; 20 | 21 | +(instancetype)make:(NSDate*)start duration:(int)minutes title:(NSString*)title subtitle:(NSString*)subtitle; 22 | 23 | - (NSDate *)day; 24 | - (BOOL)isInDay:(NSDate *)date; 25 | 26 | @end 27 | -------------------------------------------------------------------------------- /RVCalendarWeekView/Lib/Views/MSEvent.m: -------------------------------------------------------------------------------- 1 | // 2 | // AKEvent.m 3 | // Example 4 | // 5 | // Created by ak on 18.01.2016. 6 | // Copyright © 2016 Eric Horacek. All rights reserved. 7 | // 8 | 9 | #import "MSEvent.h" 10 | #import "NSDate+Easy.h" 11 | 12 | @implementation MSEvent 13 | 14 | +(instancetype)make:(NSDate*)start title:(NSString*)title subtitle:(NSString*)subtitle{ 15 | return [self.class make:start duration:60 title:title subtitle:subtitle]; 16 | } 17 | 18 | +(instancetype)make:(NSDate*)start end:(NSDate*)end title:(NSString*)title subtitle:(NSString*)subtitle{ 19 | MSEvent* event = [self.class new]; 20 | event.StartDate = start; 21 | event.EndDate = end; 22 | event.title = title; 23 | event.location = subtitle; 24 | return event; 25 | } 26 | 27 | +(instancetype)make:(NSDate*)start duration:(int)minutes title:(NSString*)title subtitle:(NSString*)subtitle{ 28 | MSEvent* event = [self.class new]; 29 | event.StartDate = start; 30 | event.EndDate = [start addMinutes:minutes]; 31 | event.title = title; 32 | event.location = subtitle; 33 | return event; 34 | } 35 | 36 | - (NSDate *)day{ 37 | return [NSCalendar.currentCalendar startOfDayForDate:self.StartDate]; 38 | } 39 | 40 | - (BOOL)isInDay:(NSDate *)date { 41 | return [self containsDate:[date setTime:[self.EndDate format:@"HH:mm:ss"]] interval:DTTimePeriodIntervalClosed]; 42 | } 43 | 44 | @end -------------------------------------------------------------------------------- /RVCalendarWeekView/Lib/Views/MSEventCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // MSEventCell.h 3 | // Example 4 | // 5 | // Created by Eric Horacek on 2/26/13. 6 | // Copyright (c) 2015 Eric Horacek. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "MSEvent.h" 11 | 12 | @class MSEvent; 13 | 14 | @interface MSEventCell : UICollectionViewCell 15 | 16 | @property (nonatomic, strong) MSEvent *event; 17 | @property (nonatomic, strong) UILabel *title; 18 | @property (nonatomic, strong) UILabel *location; 19 | 20 | - (void)updateColors; 21 | 22 | - (NSDictionary *)titleAttributesHighlighted:(BOOL)highlighted; 23 | - (NSDictionary *)subtitleAttributesHighlighted:(BOOL)highlighted; 24 | - (UIColor *)backgroundColorHighlighted:(BOOL)selected; 25 | - (UIColor *)textColorHighlighted:(BOOL)selected; 26 | - (UIColor *)borderColor; 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /RVCalendarWeekView/Lib/Views/MSEventCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // MSEventCell.m 3 | // Example 4 | // 5 | // Created by Eric Horacek on 2/26/13. 6 | // Copyright (c) 2015 Eric Horacek. All rights reserved. 7 | // 8 | 9 | #import "MSEventCell.h" 10 | 11 | #define MAS_SHORTHAND 12 | #import "Masonry.h" 13 | #import "UIColor+HexString.h" 14 | #import "RVCollection.h" 15 | #import "MSDurationChangeIndicator.h" 16 | 17 | @interface MSEventCell () 18 | 19 | @property (nonatomic, strong) UIView *borderView; 20 | @property (nonatomic, strong) UIView *topBorderView; 21 | 22 | @end 23 | 24 | @implementation MSEventCell 25 | 26 | #pragma mark - UIView 27 | 28 | - (id)initWithFrame:(CGRect)frame 29 | { 30 | self = [super initWithFrame:frame]; 31 | if (self) { 32 | 33 | self.layer.rasterizationScale = [[UIScreen mainScreen] scale]; 34 | self.layer.shouldRasterize = YES; 35 | 36 | self.layer.shadowColor = [[UIColor blackColor] CGColor]; 37 | self.layer.shadowOffset = CGSizeMake(0.0, 4.0); 38 | self.layer.shadowRadius = 5.0; 39 | self.layer.shadowOpacity = 0.0; 40 | 41 | self.borderView = [UIView new]; 42 | [self.contentView addSubview:self.borderView]; 43 | 44 | self.topBorderView = [UIView new]; 45 | self.topBorderView.backgroundColor = [UIColor whiteColor]; 46 | [self.contentView addSubview:self.topBorderView]; 47 | 48 | self.title = [UILabel new]; 49 | self.title.numberOfLines = 0; 50 | self.title.backgroundColor = [UIColor clearColor]; 51 | [self.contentView addSubview:self.title]; 52 | 53 | self.location = [UILabel new]; 54 | self.location.numberOfLines = 0; 55 | self.location.backgroundColor = [UIColor clearColor]; 56 | [self.contentView addSubview:self.location]; 57 | 58 | [self updateColors]; 59 | 60 | CGFloat borderWidth = 2.0; 61 | CGFloat contentMargin = 2.0; 62 | UIEdgeInsets contentPadding = UIEdgeInsetsMake(8.0, (borderWidth + 4.0), 1.0, 4.0); 63 | 64 | [self.borderView mas_makeConstraints:^(MASConstraintMaker *make) { 65 | make.height.equalTo(self.mas_height); 66 | make.width.equalTo(@(borderWidth)); 67 | make.left.equalTo(self.mas_left); 68 | make.top.equalTo(self.mas_top); 69 | }]; 70 | 71 | [self.topBorderView mas_makeConstraints:^(MASConstraintMaker *make) { 72 | make.height.equalTo(@(borderWidth)); 73 | make.width.equalTo(self.mas_width); 74 | make.top.equalTo(self.mas_top); 75 | make.left.equalTo(self.mas_left); 76 | make.right.equalTo(self.mas_right); 77 | }]; 78 | 79 | [self.title mas_makeConstraints:^(MASConstraintMaker *make) { 80 | make.top.equalTo(self.mas_top).offset(contentPadding.top); 81 | make.left.equalTo(self.mas_left).offset(contentPadding.left); 82 | make.right.equalTo(self.mas_right).offset(-contentPadding.right); 83 | }]; 84 | 85 | [self.location mas_makeConstraints:^(MASConstraintMaker *make) { 86 | make.top.equalTo(self.title.mas_bottom).offset(contentMargin); 87 | make.left.equalTo(self.mas_left).offset(contentPadding.left); 88 | make.right.equalTo(self.mas_right).offset(-contentPadding.right); 89 | make.bottom.lessThanOrEqualTo(self.mas_bottom).offset(-contentPadding.bottom); 90 | }]; 91 | 92 | [self.contentView mas_makeConstraints:^(MASConstraintMaker *make) { 93 | make.top.equalTo(self.mas_top); 94 | make.bottom.equalTo(self.mas_bottom); 95 | make.left.equalTo(self.mas_left); 96 | make.right.equalTo(self.mas_right); 97 | }]; 98 | } 99 | return self; 100 | } 101 | 102 | 103 | #pragma mark - UICollectionViewCell 104 | - (void)setSelected:(BOOL)selected 105 | { 106 | if (selected && (self.selected != selected)) { 107 | [UIView animateWithDuration:0.1 animations:^{ 108 | self.transform = CGAffineTransformMakeScale(1.025, 1.025); 109 | self.layer.shadowOpacity = 0.2; 110 | } completion:^(BOOL finished) { 111 | [UIView animateWithDuration:0.1 animations:^{ 112 | self.transform = CGAffineTransformIdentity; 113 | }]; 114 | }]; 115 | } else if (selected) { 116 | self.layer.shadowOpacity = 0.2; 117 | } else { 118 | self.layer.shadowOpacity = 0.0; 119 | } 120 | [super setSelected:selected]; // Must be here for animation to fire 121 | [self updateColors]; 122 | [self removeIndicators]; 123 | } 124 | 125 | 126 | #pragma mark - MSEventCell 127 | - (void)setEvent:(MSEvent *)event 128 | { 129 | _event = event; 130 | self.title.attributedText = [[NSAttributedString alloc] initWithString:_event.title attributes:[self titleAttributesHighlighted:self.selected]]; 131 | self.location.attributedText = [[NSAttributedString alloc] initWithString:_event.location attributes:[self subtitleAttributesHighlighted:self.selected]]; 132 | [self updateColors]; 133 | } 134 | 135 | 136 | - (void)updateColors 137 | { 138 | [self performSelectorOnMainThread:@selector(updateColorsSelector) withObject:nil waitUntilDone:true]; 139 | } 140 | 141 | - (void)updateColorsSelector 142 | { 143 | self.contentView.backgroundColor = [self backgroundColorHighlighted:self.selected]; 144 | self.borderView.backgroundColor = [self borderColor]; 145 | self.title.textColor = [self textColorHighlighted:self.selected]; 146 | self.location.textColor = [self textColorHighlighted:self.selected]; 147 | } 148 | 149 | -(void)removeIndicators{ 150 | [self.subviews each:^(UIView* subview) { 151 | if([subview isKindOfClass:MSDurationChangeIndicator.class]){ 152 | [subview removeFromSuperview]; 153 | } 154 | }]; 155 | } 156 | 157 | - (NSDictionary *)titleAttributesHighlighted:(BOOL)highlighted 158 | { 159 | NSMutableParagraphStyle *paragraphStyle = [NSMutableParagraphStyle new]; 160 | paragraphStyle.alignment = NSTextAlignmentLeft; 161 | paragraphStyle.hyphenationFactor = 1.0; 162 | paragraphStyle.lineBreakMode = NSLineBreakByTruncatingTail; 163 | return @{ 164 | NSFontAttributeName : [UIFont boldSystemFontOfSize:12.0], 165 | NSForegroundColorAttributeName : [self textColorHighlighted:highlighted], 166 | NSParagraphStyleAttributeName : paragraphStyle 167 | }; 168 | } 169 | 170 | - (NSDictionary *)subtitleAttributesHighlighted:(BOOL)highlighted 171 | { 172 | NSMutableParagraphStyle *paragraphStyle = [NSMutableParagraphStyle new]; 173 | paragraphStyle.alignment = NSTextAlignmentLeft; 174 | paragraphStyle.hyphenationFactor = 1.0; 175 | paragraphStyle.lineBreakMode = NSLineBreakByTruncatingTail; 176 | return @{ 177 | NSFontAttributeName : [UIFont systemFontOfSize:12.0], 178 | NSForegroundColorAttributeName : [self textColorHighlighted:highlighted], 179 | NSParagraphStyleAttributeName : paragraphStyle 180 | }; 181 | } 182 | 183 | - (UIColor *)backgroundColorHighlighted:(BOOL)selected 184 | { 185 | return selected ? [UIColor colorWithHexString:@"35b1f1"] : [[UIColor colorWithHexString:@"35b1f1"] colorWithAlphaComponent:0.2]; 186 | } 187 | 188 | - (UIColor *)textColorHighlighted:(BOOL)selected 189 | { 190 | return selected ? [UIColor whiteColor] : [UIColor colorWithHexString:@"21729c"]; 191 | } 192 | 193 | - (UIColor *)borderColor 194 | { 195 | return [[self backgroundColorHighlighted:NO] colorWithAlphaComponent:1.0]; 196 | } 197 | 198 | @end 199 | -------------------------------------------------------------------------------- /RVCalendarWeekView/Lib/Views/MSGridline.h: -------------------------------------------------------------------------------- 1 | // 2 | // MSGridlineCollectionReusableView.h 3 | // Example 4 | // 5 | // Created by Eric Horacek on 2/26/13. 6 | // Copyright (c) 2015 Eric Horacek. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface MSGridline : UICollectionReusableView 12 | 13 | @property (strong,nonatomic) UIView* border; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /RVCalendarWeekView/Lib/Views/MSGridline.m: -------------------------------------------------------------------------------- 1 | // 2 | // MSGridlineCollectionReusableView.m 3 | // Example 4 | // 5 | // Created by Eric Horacek on 2/26/13. 6 | // Copyright (c) 2015 Eric Horacek. All rights reserved. 7 | // 8 | 9 | #import "MSGridline.h" 10 | #import "UIColor+HexString.h" 11 | @implementation MSGridline 12 | 13 | - (id)initWithFrame:(CGRect)frame 14 | { 15 | self = [super initWithFrame:frame]; 16 | if (self) { 17 | self.backgroundColor = [UIColor colorWithHexString:@"dddddd"]; 18 | } 19 | return self; 20 | } 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /RVCalendarWeekView/Lib/Views/MSTimeRowHeader.h: -------------------------------------------------------------------------------- 1 | // 2 | // MSTimeRowHeader.h 3 | // Example 4 | // 5 | // Created by Eric Horacek on 2/26/13. 6 | // Copyright (c) 2015 Eric Horacek. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface MSTimeRowHeader : UICollectionReusableView 12 | 13 | @property (nonatomic, strong) UILabel *title; 14 | @property (nonatomic, strong) NSDate *time; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /RVCalendarWeekView/Lib/Views/MSTimeRowHeader.m: -------------------------------------------------------------------------------- 1 | // 2 | // MSTimeRowHeader.m 3 | // Example 4 | // 5 | // Created by Eric Horacek on 2/26/13. 6 | // Copyright (c) 2015 Eric Horacek. All rights reserved. 7 | // 8 | 9 | #import "MSTimeRowHeader.h" 10 | #import "UIColor+HexString.h" 11 | #define MAS_SHORTHAND 12 | #import "Masonry.h" 13 | 14 | @implementation MSTimeRowHeader 15 | 16 | - (id)initWithFrame:(CGRect)frame 17 | { 18 | self = [super initWithFrame:frame]; 19 | if (self) { 20 | self.backgroundColor = [UIColor clearColor]; 21 | self.title = [UILabel new]; 22 | self.title.backgroundColor = [UIColor clearColor]; 23 | self.title.font = [UIFont systemFontOfSize:12.0]; 24 | self.title.textColor = [UIColor colorWithHexString:@"a7a7a7"]; 25 | [self addSubview:self.title]; 26 | 27 | [self.title mas_makeConstraints:^(MASConstraintMaker *make) { 28 | make.centerY.equalTo(self.mas_centerY); 29 | make.right.equalTo(self.mas_right).offset(-5.0); 30 | }]; 31 | } 32 | return self; 33 | } 34 | 35 | #pragma mark - MSTimeRowHeader 36 | 37 | - (void)setTime:(NSDate *)time 38 | { 39 | _time = time; 40 | 41 | static NSDateFormatter *dateFormatter; 42 | if (!dateFormatter) { 43 | dateFormatter = [NSDateFormatter new]; 44 | dateFormatter.dateFormat = @"h a"; 45 | } 46 | self.title.text = [dateFormatter stringFromDate:time]; 47 | [self setNeedsLayout]; 48 | } 49 | 50 | @end 51 | -------------------------------------------------------------------------------- /RVCalendarWeekView/Lib/Views/MSTimeRowHeaderBackground.h: -------------------------------------------------------------------------------- 1 | // 2 | // MSTimeRowHeaderBackground.h 3 | // Example 4 | // 5 | // Created by Eric Horacek on 2/26/13. 6 | // Copyright (c) 2015 Eric Horacek. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface MSTimeRowHeaderBackground : UICollectionReusableView 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /RVCalendarWeekView/Lib/Views/MSTimeRowHeaderBackground.m: -------------------------------------------------------------------------------- 1 | // 2 | // MSTimeRowHeaderBackground.m 3 | // Example 4 | // 5 | // Created by Eric Horacek on 2/26/13. 6 | // Copyright (c) 2015 Eric Horacek. All rights reserved. 7 | // 8 | 9 | #import "MSTimeRowHeaderBackground.h" 10 | 11 | @implementation MSTimeRowHeaderBackground 12 | 13 | - (id)initWithFrame:(CGRect)frame 14 | { 15 | self = [super initWithFrame:frame]; 16 | if (self) { 17 | self.backgroundColor = [UIColor whiteColor]; 18 | } 19 | return self; 20 | } 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /RVCalendarWeekView/Lib/Views/MSUnavailableHour.h: -------------------------------------------------------------------------------- 1 | // 2 | // MSUnavailableHour.h 3 | // RVCalendarWeekView 4 | // 5 | // Created by Badchoice on 4/10/16. 6 | // Copyright © 2016 revo. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | 12 | /** 13 | * Calendar flow layout will draw this class (or any used as unavailable hour) with a 0.7 alpha value 14 | * 15 | */ 16 | @interface MSUnavailableHour : UICollectionReusableView 17 | 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /RVCalendarWeekView/Lib/Views/MSUnavailableHour.m: -------------------------------------------------------------------------------- 1 | // 2 | // MSUnavailableHour.m 3 | // RVCalendarWeekView 4 | // 5 | // Created by Badchoice on 4/10/16. 6 | // Copyright © 2016 revo. All rights reserved. 7 | // 8 | 9 | #import "MSUnavailableHour.h" 10 | #import "UIColor+HexString.h" 11 | 12 | @implementation MSUnavailableHour 13 | 14 | - (id)initWithFrame:(CGRect)frame 15 | { 16 | self = [super initWithFrame:frame]; 17 | if (self) { 18 | self.backgroundColor = [UIColor colorWithHexString:@"FaFaFa"]; 19 | } 20 | return self; 21 | } 22 | 23 | //http://stackoverflow.com/questions/39182041/how-to-fill-a-uiview-with-an-alternating-stripe-pattern-programmatically-using-s 24 | /*-(void)drawRect:(CGRect)rect{ 25 | 26 | //// Set pattern tile colors width and height; adjust the color width to adjust pattern. 27 | UIColor* color1 = [UIColor colorWithRed:0/255.0f green:0/255.0f blue:0/255.0f alpha:0.2f]; 28 | CGFloat color1Width = 5; 29 | CGFloat color1Height = 5; 30 | 31 | UIColor* color2 = [UIColor colorWithRed:0/255.0f green:0/255.0f blue:254/255.0f alpha:0]; 32 | CGFloat color2Width = 10; 33 | CGFloat color2Height = 10; 34 | 35 | //// Set pattern tile orientation vertical. 36 | CGFloat patternWidth = color1Width + color2Width; 37 | CGFloat patternHeight = MIN(color1Height, color2Height); 38 | 39 | //// Set pattern tile size. 40 | CGSize patternSize = CGSizeMake(patternWidth, patternHeight); 41 | 42 | //// Draw pattern tile 43 | CGContextRef context = UIGraphicsGetCurrentContext(); 44 | UIGraphicsBeginImageContextWithOptions(patternSize, false, 0.0); 45 | 46 | UIBezierPath* color1Path = [UIBezierPath bezierPathWithRect:CGRectMake(0,0,color1Width,color1Height)]; 47 | [color1 setFill]; 48 | [color1Path fill]; 49 | 50 | UIBezierPath* color2Path = [UIBezierPath bezierPathWithRect:CGRectMake(color1Width,0,color2Width,color2Height)]; 51 | [color2 setFill]; 52 | [color2Path fill]; 53 | 54 | UIImage* image = UIGraphicsGetImageFromCurrentImageContext(); 55 | UIGraphicsEndImageContext(); 56 | 57 | //// Draw pattern in view 58 | [[UIColor colorWithPatternImage:image] setFill]; 59 | CGContextFillRect(context, rect); 60 | }*/ 61 | 62 | 63 | @end 64 | -------------------------------------------------------------------------------- /RVCalendarWeekView/Lib/Views/MSWeekendBackground.h: -------------------------------------------------------------------------------- 1 | // 2 | // MSWeekendBackground.h 3 | // RVCalendarWeekView 4 | // 5 | // Created by Badchoice on 6/10/16. 6 | // Copyright © 2016 revo. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface MSWeekendBackground : UICollectionReusableView 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /RVCalendarWeekView/Lib/Views/MSWeekendBackground.m: -------------------------------------------------------------------------------- 1 | // 2 | // MSWeekendBackground.m 3 | // RVCalendarWeekView 4 | // 5 | // Created by Badchoice on 6/10/16. 6 | // Copyright © 2016 revo. All rights reserved. 7 | // 8 | 9 | #import "MSWeekendBackground.h" 10 | #import "UIColor+HexString.h" 11 | 12 | @implementation MSWeekendBackground 13 | 14 | - (id)initWithFrame:(CGRect)frame 15 | { 16 | self = [super initWithFrame:frame]; 17 | if (self) { 18 | self.backgroundColor = [UIColor colorWithHexString:@"F5F5F5"]; 19 | } 20 | return self; 21 | } 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /RVCalendarWeekView/Lib/WeekView/Decorators/MSHourPerdiod.h: -------------------------------------------------------------------------------- 1 | // 2 | // MSHourPerdiod.h 3 | // RVCalendarWeekView 4 | // 5 | // Created by Badchoice on 4/10/16. 6 | // Copyright © 2016 revo. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface MSHourPerdiod : NSObject{ 12 | NSNumber *mDuration; 13 | NSNumber *mStartHour; 14 | NSNumber *mStartTimeWithPercentage; 15 | } 16 | 17 | @property(strong, nonatomic) NSString* start; 18 | @property(strong, nonatomic) NSString* end; 19 | 20 | 21 | /** 22 | * Create with time strings like @"9:99" ,@"18:25".. 23 | */ 24 | +(MSHourPerdiod*)make:(NSString*)start end:(NSString*)end; 25 | 26 | -(int)startHour; 27 | -(int)startMinute; 28 | -(float)duration; 29 | -(float)startTimeWithMinutesPercentage; 30 | 31 | 32 | @end 33 | -------------------------------------------------------------------------------- /RVCalendarWeekView/Lib/WeekView/Decorators/MSHourPerdiod.m: -------------------------------------------------------------------------------- 1 | // 2 | // MSHourPerdiod.m 3 | // RVCalendarWeekView 4 | // 5 | // Created by Badchoice on 4/10/16. 6 | // Copyright © 2016 revo. All rights reserved. 7 | // 8 | 9 | #import "MSHourPerdiod.h" 10 | #import "NSString+Collection.h" 11 | 12 | @implementation MSHourPerdiod 13 | 14 | +(MSHourPerdiod*)make:(NSString*)start end:(NSString*)end{ 15 | MSHourPerdiod* hourPerdiod = [self.class new]; 16 | hourPerdiod.start = start; 17 | hourPerdiod.end = end; 18 | return hourPerdiod; 19 | } 20 | 21 | -(int)startHour{ 22 | if(!mStartHour){ 23 | mStartHour = @([[self.start explode:@":"].firstObject intValue]); 24 | } 25 | return mStartHour.intValue; 26 | } 27 | 28 | -(int)endHour{ 29 | return [[self.end explode:@":"].firstObject intValue]; 30 | } 31 | 32 | -(int)startMinute{ 33 | return [[self.start explode:@":"].lastObject intValue]; 34 | } 35 | 36 | -(int)endMinute{ 37 | return [[self.start explode:@":"].lastObject intValue]; 38 | } 39 | 40 | -(float)startTimeWithMinutesPercentage{ 41 | if(!mStartTimeWithPercentage){ 42 | int hour = self.startHour; 43 | float percentage = self.startMinute / 60.f; 44 | mStartTimeWithPercentage = @( hour + percentage ); 45 | } 46 | return mStartTimeWithPercentage.floatValue; 47 | } 48 | 49 | -(float)duration{ 50 | if(!mDuration){ 51 | float endTimeInMinutes = self.endHour * 60 + self.endMinute; 52 | float startTimeInMinutes = self.startHour * 60 + self.startMinute; 53 | mDuration = @((endTimeInMinutes - startTimeInMinutes) / 60); 54 | } 55 | return mDuration.floatValue; 56 | } 57 | @end 58 | -------------------------------------------------------------------------------- /RVCalendarWeekView/Lib/WeekView/Decorators/MSWeekViewDecorator.h: -------------------------------------------------------------------------------- 1 | // 2 | // MSWeekViewDecorator.h 3 | // RVCalendarWeekView 4 | // 5 | // Created by Jordi Puigdellívol on 1/9/16. 6 | // Copyright © 2016 revo. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "MSWeekView.h" 11 | 12 | @interface MSWeekViewDecorator : MSWeekView{ 13 | } 14 | 15 | @property(strong,nonatomic) MSWeekView* weekView; 16 | 17 | +(__kindof MSWeekView*)makeWith:(MSWeekView*)weekView; 18 | -(void)setup; 19 | 20 | -(MSWeekView*)baseWeekView; 21 | 22 | - (MSEventCell *)cellForEvent:(MSEvent *)event; 23 | 24 | /** 25 | * Use this variable to change the minutes precision when 26 | * dragging or creating new event 27 | * use values from 0 to 60 28 | * default is 5 minutes 29 | */ 30 | @property(nonatomic) int minutesPrecision; 31 | 32 | //========================================================= 33 | #pragma mark - Get XX for Point 34 | //========================================================= 35 | -(NSDate*)dateForPoint:(CGPoint)point; 36 | -(int)getHourForY:(float)y; 37 | -(int)getMinuteForY:(float)y; 38 | -(int)getDayIndexForX:(float)x; 39 | -(CGFloat)round:(float)number toNearest:(float)pivot; 40 | -(CGFloat)round:(float)number toLowest:(float)pivot; 41 | 42 | //========================================================= 43 | #pragma mark - 44 | //========================================================= 45 | /** 46 | * Checks if there is any GR using as delegate the class itself 47 | */ 48 | -(BOOL)isGestureAlreadyAdded:(UIView*)cell; 49 | @end 50 | -------------------------------------------------------------------------------- /RVCalendarWeekView/Lib/WeekView/Decorators/MSWeekViewDecorator.m: -------------------------------------------------------------------------------- 1 | // 2 | // MSWeekViewDecorator.m 3 | // RVCalendarWeekView 4 | // 5 | // Created by Jordi Puigdellívol on 1/9/16. 6 | // Copyright © 2016 revo. All rights reserved. 7 | // 8 | 9 | #import "MSWeekViewDecorator.h" 10 | #import "NSDate+Easy.h" 11 | #import "NSDate+DateTools.h" 12 | #import "RVCollection.h" 13 | 14 | @implementation MSWeekViewDecorator 15 | 16 | //========================================================= 17 | #pragma mark - Init 18 | //========================================================= 19 | +(__kindof MSWeekView*)makeWith:(MSWeekView*)weekView{ 20 | MSWeekViewDecorator* weekViewDecorator = [self.class new]; 21 | weekViewDecorator.weekView = weekView; 22 | weekViewDecorator.minutesPrecision = 5; 23 | weekView.collectionView.dataSource = weekViewDecorator; 24 | weekView.collectionView.delegate = weekViewDecorator; 25 | weekView.weekFlowLayout.delegate = weekViewDecorator; 26 | [weekViewDecorator setup]; 27 | return weekViewDecorator; 28 | } 29 | 30 | -(void)setup{ 31 | 32 | } 33 | 34 | -(MSWeekView*)baseWeekView{ 35 | if ([self.weekView isKindOfClass:MSWeekViewDecorator.class]) 36 | return [(MSWeekViewDecorator*)self.weekView baseWeekView]; 37 | else 38 | return self.weekView; 39 | } 40 | 41 | //========================================================= 42 | #pragma mark - Get Overrides 43 | //========================================================= 44 | -(UICollectionView*)collectionView{ 45 | return self.baseWeekView.collectionView; 46 | } 47 | 48 | -(MSCollectionViewCalendarLayout*)weekFlowLayout{ 49 | return self.baseWeekView.weekFlowLayout; 50 | } 51 | 52 | -(MSEventCell *)cellForEvent:(MSEvent*)event{ 53 | //This does add more cells.. :( 54 | int sections = [self.weekView numberOfSectionsInCollectionView:self.collectionView]; 55 | for (int i = 0; i < sections; i++) { 56 | int rows = [self.weekView collectionView:self.collectionView numberOfItemsInSection:i]; 57 | for (int j = 0; j < rows; j++) { 58 | MSEventCell * cell = [self.collectionView cellForItemAtIndexPath:[NSIndexPath indexPathForItem:j inSection:i]]; 59 | if (cell.event == event) { 60 | return cell; 61 | } 62 | } 63 | } 64 | return nil; 65 | } 66 | 67 | //========================================================= 68 | #pragma mark - Collection view datasource 69 | //========================================================= 70 | -(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{ 71 | return [_weekView collectionView:collectionView numberOfItemsInSection:section]; 72 | } 73 | 74 | - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{ 75 | return [_weekView collectionView:collectionView cellForItemAtIndexPath:indexPath]; 76 | } 77 | 78 | - (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView{ 79 | return [_weekView numberOfSectionsInCollectionView:collectionView]; 80 | } 81 | 82 | - (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath 83 | { 84 | return [_weekView collectionView:collectionView viewForSupplementaryElementOfKind:kind atIndexPath:indexPath]; 85 | } 86 | 87 | //========================================================= 88 | #pragma mark - Collection view delegate 89 | //========================================================= 90 | -(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{ 91 | [_weekView collectionView:collectionView didSelectItemAtIndexPath:indexPath]; 92 | } 93 | 94 | - (void)scrollViewDidScroll:(UIScrollView *)scrollView{ 95 | [_weekView scrollViewDidScroll:scrollView]; 96 | } 97 | 98 | //================================================ 99 | #pragma mark - Week Flow Delegate 100 | //================================================ 101 | - (NSDate *)collectionView:(UICollectionView *)collectionView layout:(MSCollectionViewCalendarLayout *)collectionViewCalendarLayout dayForSection:(NSInteger)section{ 102 | return [_weekView collectionView:collectionView layout:collectionViewCalendarLayout dayForSection:section]; 103 | } 104 | 105 | - (NSDate *)collectionView:(UICollectionView *)collectionView layout:(MSCollectionViewCalendarLayout *)collectionViewCalendarLayout startTimeForItemAtIndexPath:(NSIndexPath *)indexPath{ 106 | return [_weekView collectionView:collectionView layout:collectionViewCalendarLayout startTimeForItemAtIndexPath:indexPath]; 107 | } 108 | 109 | - (NSDate *)collectionView:(UICollectionView *)collectionView layout:(MSCollectionViewCalendarLayout *)collectionViewCalendarLayout endTimeForItemAtIndexPath:(NSIndexPath *)indexPath{ 110 | return [_weekView collectionView:collectionView layout:collectionViewCalendarLayout endTimeForItemAtIndexPath:indexPath]; 111 | } 112 | 113 | -(NSArray*)unavailableHoursPeriods:(UICollectionView *)collectionView layout:(MSCollectionViewCalendarLayout *)collectionViewLayout section:(int)section{ 114 | return [_weekView unavailableHoursPeriods:collectionView layout:collectionViewLayout section:section]; 115 | } 116 | 117 | //========================================================= 118 | #pragma mark - Get XX for Point 119 | //========================================================= 120 | -(NSDate*)dateForPoint:(CGPoint)point{ 121 | NSDate* firstDay = [self.baseWeekView firstDay]; 122 | NSDate* date = [firstDay addDays :[self getDayIndexForX:point.x] ]; 123 | date = [date withHour :[self getHourForY :point.y] timezone:@"device"]; 124 | date = [date withMinute :[self getMinuteForY :point.y] ]; 125 | return date; 126 | } 127 | 128 | -(int)getHourForY:(float)y{ 129 | y = [self viewYToContentY:y]; 130 | int earliestHour = (int)self.weekFlowLayout.earliestHour; 131 | int hour = y/self.weekFlowLayout.hourHeight; 132 | return MAX(0, MIN(23, hour + earliestHour)); 133 | } 134 | 135 | -(int)getMinuteForY:(float)y{ 136 | y = [self viewYToContentY:y]; 137 | int hours = (y / self.weekFlowLayout.hourHeight); 138 | int minute = (y / self.weekFlowLayout.hourHeight - hours ) * 60; 139 | int minuteRounded = [self round:minute toNearest:self.minutesPrecision]; 140 | return MAX(0, minuteRounded == 60 ? 60-self.minutesPrecision : minuteRounded); 141 | } 142 | 143 | -(int)getDayIndexForX:(float)x{ 144 | x = [self viewXToContentX:x]; 145 | return x / (self.weekFlowLayout.sectionMargin.left + self.weekFlowLayout.sectionWidth + self.weekFlowLayout.sectionMargin.right); 146 | } 147 | 148 | -(float)viewXToContentX:(float)x{ 149 | return x - self.weekFlowLayout.timeRowHeaderWidth + self.collectionView.contentOffset.x - self.weekFlowLayout.contentMargin.left; 150 | } 151 | 152 | -(float)viewYToContentY:(float)y{ 153 | return y - self.weekFlowLayout.dayColumnHeaderHeight + self.collectionView.contentOffset.y - self.weekFlowLayout.contentMargin.top - self.weekFlowLayout.sectionMargin.top; 154 | } 155 | 156 | -(CGFloat)round:(float)number toNearest:(float)pivot{ 157 | return pivot * floor((number/pivot)+0.5); 158 | } 159 | 160 | -(CGFloat)round:(float)number toLowest:(float)pivot{ 161 | return pivot * floor(number/pivot); 162 | } 163 | 164 | -(BOOL)isGestureAlreadyAdded:(UIView*)cell{ 165 | return [cell.gestureRecognizers contains:^BOOL(UIGestureRecognizer* recognizer) { 166 | return recognizer.delegate == (id)self; 167 | }]; 168 | } 169 | 170 | 171 | @end 172 | -------------------------------------------------------------------------------- /RVCalendarWeekView/Lib/WeekView/Decorators/MSWeekViewDecoratorChangeDuration.h: -------------------------------------------------------------------------------- 1 | // 2 | // MSWeekViewDecoratorChangeDuration.h 3 | // RVCalendarWeekView 4 | // 5 | // Created by Jordi Puigdellívol on 7/10/16. 6 | // Copyright © 2016 revo. All rights reserved. 7 | // 8 | 9 | #import "MSWeekViewDecorator.h" 10 | #import "MSDurationChangeIndicator.h" 11 | 12 | @protocol MSWeekViewChangeDurationDelegate 13 | -(BOOL)weekView:(MSWeekView*)weekView canChangeDuration:(MSEvent*)event startDate:(NSDate*)startDate endDate:(NSDate*)endDate; 14 | -(void)weekView:(MSWeekView*)weekView event:(MSEvent*)event durationChanged:(NSDate*)startDate endDate:(NSDate*)endDate; 15 | @end 16 | 17 | @interface MSWeekViewDecoratorChangeDuration : MSWeekViewDecorator { 18 | CGFloat mStartY; 19 | CGFloat mStartHeight; 20 | 21 | MSDurationChangeIndicator* mStartIndicator; 22 | MSDurationChangeIndicator* mEndIndicator; 23 | } 24 | 25 | 26 | @property(weak,nonatomic) id changeDurationDelegate; 27 | 28 | +(__kindof MSWeekView*)makeWith:(MSWeekView*)weekView andDelegate:(id)delegate; 29 | 30 | @end 31 | -------------------------------------------------------------------------------- /RVCalendarWeekView/Lib/WeekView/Decorators/MSWeekViewDecoratorChangeDuration.m: -------------------------------------------------------------------------------- 1 | // 2 | // MSWeekViewDecoratorChangeDuration.m 3 | // RVCalendarWeekView 4 | // 5 | // Created by Jordi Puigdellívol on 7/10/16. 6 | // Copyright © 2016 revo. All rights reserved. 7 | // 8 | 9 | #import "MSWeekViewDecoratorChangeDuration.h" 10 | #import "MSEventCell.h" 11 | #import "RVCollection.h" 12 | #import "NSDate+Easy.h" 13 | 14 | @interface MSWeekViewDecoratorChangeDuration () 15 | 16 | @end 17 | 18 | @implementation MSWeekViewDecoratorChangeDuration 19 | 20 | +(__kindof MSWeekView*)makeWith:(MSWeekView*)weekView andDelegate:(id)delegate{ 21 | MSWeekViewDecoratorChangeDuration * weekViewDecorator = [super makeWith:weekView]; 22 | weekViewDecorator.changeDurationDelegate = delegate; 23 | return weekViewDecorator; 24 | } 25 | 26 | //========================================================= 27 | #pragma mark - Add long press gesture recognizer 28 | //========================================================= 29 | - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { 30 | MSEventCell *cell = (MSEventCell*)[super collectionView:collectionView cellForItemAtIndexPath:indexPath]; 31 | 32 | if (! [self isGestureAlreadyAdded:cell]) { 33 | UILongPressGestureRecognizer* lpgr = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(onEventCellLongPress:)]; 34 | lpgr.minimumPressDuration = 0.2; 35 | lpgr.delegate = self; 36 | [cell addGestureRecognizer:lpgr]; 37 | } 38 | 39 | return cell; 40 | } 41 | 42 | -(void)onEventCellLongPress:(UIGestureRecognizer*)gestureRecognizer{ 43 | if(gestureRecognizer.state == UIGestureRecognizerStateBegan){ 44 | NSLog(@"Change Duration start"); 45 | MSEventCell* cell = (MSEventCell*)gestureRecognizer.view; 46 | [self addDurationIndicators:cell]; 47 | } 48 | } 49 | 50 | - (void)addDurationIndicators:(MSEventCell *)cell { 51 | mStartY = cell.frame.origin.y; 52 | mStartHeight = cell.frame.size.height; 53 | mStartIndicator = [MSDurationChangeIndicator makeForStartWithCell:cell andDelegate:self]; 54 | mEndIndicator = [MSDurationChangeIndicator makeForEndWithCell:cell andDelegate:self]; 55 | } 56 | 57 | //========================================================= 58 | #pragma mark - On indicators dragged 59 | //========================================================= 60 | -(void)durationIndicatorStartUpdated:(MSDurationChangeIndicator*)sender y:(int)y{ 61 | sender.eventCell.frame = CGRectMake( 62 | sender.eventCell.frame.origin.x, 63 | sender.eventCell.frame.origin.y + y, 64 | sender.eventCell.frame.size.width, 65 | sender.eventCell.frame.size.height - y); 66 | [mEndIndicator updatePosition]; 67 | mStartIndicator.timeLabel.text = [[self startDateFor:sender.eventCell] format:@"HH:mm" timezone:@"device"]; 68 | } 69 | 70 | -(void)durationIndicatorEndUpdated:(MSDurationChangeIndicator*)sender y:(int)y{ 71 | sender.eventCell.frame = CGRectMake( 72 | sender.eventCell.frame.origin.x, 73 | sender.eventCell.frame.origin.y, 74 | sender.eventCell.frame.size.width, 75 | y); 76 | 77 | mEndIndicator.timeLabel.text = [[self endDateFor:sender.eventCell] format:@"HH:mm" timezone:@"device"]; 78 | } 79 | 80 | -(void)durationIndicatorEnded:(MSDurationChangeIndicator*)sender{ 81 | NSDate* startDate = [self startDateFor:sender.eventCell]; 82 | NSDate* endDate = [self endDateFor:sender.eventCell]; 83 | 84 | if([self canChangeDuration:sender.eventCell.event startDate:startDate endDate:endDate]){ 85 | sender.eventCell.event.StartDate = startDate; 86 | sender.eventCell.event.EndDate = endDate; 87 | if(self.changeDurationDelegate){ 88 | [self.changeDurationDelegate weekView:self.weekView event:sender.eventCell.event durationChanged:startDate endDate:endDate]; 89 | } 90 | } 91 | [self.baseWeekView forceReload:YES]; 92 | } 93 | 94 | -(NSDate*)startDateFor:(MSEventCell*)eventCell{ 95 | return [self dateForPoint:CGPointMake( 96 | eventCell.frame.origin.x - self.collectionView.contentOffset.x + 5, 97 | eventCell.frame.origin.y - self.collectionView.contentOffset.y)]; 98 | } 99 | 100 | -(NSDate*)endDateFor:(MSEventCell*)eventCell{ 101 | return [self dateForPoint:CGPointMake( 102 | eventCell.frame.origin.x - self.collectionView.contentOffset.x + 5, 103 | eventCell.frame.origin.y - self.collectionView.contentOffset.y + eventCell.frame.size.height )]; 104 | } 105 | 106 | //========================================================= 107 | #pragma mark - Can move to new date? 108 | //========================================================= 109 | -(BOOL)canChangeDuration:(MSEvent*)event startDate:(NSDate*)startDate endDate:(NSDate*)endDate{ 110 | if (! self.changeDurationDelegate) return true; 111 | return [self.changeDurationDelegate weekView:self canChangeDuration:event startDate:startDate endDate:endDate]; 112 | } 113 | 114 | //========================================================= 115 | #pragma mark - Indicator stop dragged 116 | //========================================================= 117 | - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer 118 | { 119 | return otherGestureRecognizer.view == gestureRecognizer.view; 120 | } 121 | 122 | @end 123 | -------------------------------------------------------------------------------- /RVCalendarWeekView/Lib/WeekView/Decorators/MSWeekViewDecoratorChangeDurationAndDragable.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import "MSWeekView.h" 3 | #import "MSWeekViewDecorator.h" 4 | @protocol MSWeekViewChangeDurationDelegate; 5 | @protocol MSWeekViewDragableDelegate; 6 | 7 | #import "MSDurationChangeIndicator.h"; 8 | 9 | @interface MSWeekViewDecoratorChangeDurationAndDragable : MSWeekViewDecorator { 10 | MSDragableEvent * mDragableEvent; 11 | 12 | CGFloat mStartY; 13 | CGFloat mStartHeight; 14 | 15 | MSDurationChangeIndicator* mStartIndicator; 16 | MSDurationChangeIndicator* mEndIndicator; 17 | } 18 | 19 | + (__kindof MSWeekView *)makeWith:(MSWeekView *)weekView andDelegate:(id)delegate; 20 | 21 | @property(weak,nonatomic) id changeDurationDelegate; 22 | @property(weak,nonatomic) id dragDelegate; 23 | @end -------------------------------------------------------------------------------- /RVCalendarWeekView/Lib/WeekView/Decorators/MSWeekViewDecoratorChangeDurationAndDragable.m: -------------------------------------------------------------------------------- 1 | #import "MSWeekViewDecoratorChangeDurationAndDragable.h" 2 | #import "MSWeekViewDecoratorChangeDuration.h" 3 | #import "NSDate+Easy.h" 4 | #import "MSWeekViewDecoratorDragable.h" 5 | 6 | @implementation MSWeekViewDecoratorChangeDurationAndDragable 7 | 8 | +(__kindof MSWeekView*)makeWith:(MSWeekView*)weekView andDelegate:(id)delegate{ 9 | MSWeekViewDecoratorChangeDurationAndDragable * weekViewDecorator = [super makeWith:weekView]; 10 | weekViewDecorator.changeDurationDelegate = delegate; 11 | weekViewDecorator.dragDelegate = delegate; 12 | return weekViewDecorator; 13 | } 14 | 15 | - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { 16 | MSEventCell *cell = (MSEventCell*)[super collectionView:collectionView cellForItemAtIndexPath:indexPath]; 17 | 18 | if (! [self isGestureAlreadyAdded:cell]){ 19 | UILongPressGestureRecognizer* lpgr = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(onEventCellLongPress:)]; 20 | lpgr.delegate = self; 21 | [cell addGestureRecognizer:lpgr]; 22 | } 23 | 24 | return cell; 25 | } 26 | 27 | - (void)onEventCellLongPress:(UILongPressGestureRecognizer*)gestureRecognizer{ 28 | MSEventCell* eventCell = (MSEventCell*)gestureRecognizer.view; 29 | if (gestureRecognizer.state == UIGestureRecognizerStateBegan) { 30 | [self startDrag:eventCell touchOffset:[gestureRecognizer locationInView:gestureRecognizer.view]]; 31 | [self addChangeDurationIndicators:mDragableEvent]; 32 | } 33 | else if(gestureRecognizer.state == UIGestureRecognizerStateChanged){ 34 | [self dragEvent:gestureRecognizer]; 35 | 36 | } 37 | 38 | else if(gestureRecognizer.state == UIGestureRecognizerStateEnded){ 39 | //NSLog(@"Long press ended: %@",eventCell.akEvent.title); 40 | [self onDragEnded:eventCell]; 41 | } 42 | } 43 | 44 | -(void)startDrag:(MSEventCell*)eventCell touchOffset:(CGPoint)touchOffset{ 45 | NSLog(@"Star drag: %@", eventCell.event.title); 46 | mDragableEvent = [MSDragableEvent makeWithEventCell:eventCell andOffset:self.weekView.collectionView.contentOffset touchOffset:touchOffset]; 47 | [self.baseWeekView addSubview:mDragableEvent]; 48 | } 49 | 50 | - (void)dragEvent:(UILongPressGestureRecognizer *)gestureRecognizer { 51 | CGPoint cp = [gestureRecognizer locationInView:self.baseWeekView]; 52 | 53 | CGPoint newOrigin; 54 | float xOffset = ((int) self.collectionView.contentOffset.x % (int) self.weekFlowLayout.sectionWidth) - self.weekFlowLayout.timeRowHeaderWidth; 55 | cp.x += xOffset; 56 | float x = [self round:cp.x toLowest:self.weekFlowLayout.sectionWidth] - xOffset; 57 | newOrigin = CGPointMake(x, cp.y); 58 | newOrigin = CGPointMake(newOrigin.x /*+ mDragableEvent.touchOffset.x*/, 59 | newOrigin.y - mDragableEvent.touchOffset.y); 60 | 61 | [UIView animateWithDuration:0.1 animations:^{ 62 | mDragableEvent.frame = (CGRect) { .origin = newOrigin, .size = mDragableEvent.frame.size }; 63 | }]; 64 | 65 | NSDate* date = [self dateForDragable]; 66 | mDragableEvent.timeLabel.text = [date format:@"HH:mm" timezone:@"device"]; 67 | } 68 | 69 | -(void)onDragEnded:(MSEventCell*)eventCell{ 70 | NSDate* newStartDate = [self dateForDragable]; 71 | if ([self canMoveToNewDate:eventCell.event newDate:newStartDate]){ 72 | int duration = eventCell.event.durationInSeconds; 73 | eventCell.event.StartDate = newStartDate; 74 | eventCell.event.EndDate = [eventCell.event.StartDate dateByAddingSeconds:duration]; 75 | [self.baseWeekView forceReload:YES]; 76 | if (self.dragDelegate){ 77 | [self.dragDelegate weekView:self.baseWeekView event:eventCell.event moved:newStartDate]; 78 | } 79 | } 80 | 81 | [mDragableEvent removeFromSuperview]; 82 | mDragableEvent = nil; 83 | [self readdChangeDurationIndicators:eventCell.event]; 84 | } 85 | 86 | - (void)readdChangeDurationIndicators:(MSEvent *)event { 87 | double delayInSeconds = 0.1; 88 | dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC)); 89 | dispatch_after(popTime, dispatch_get_main_queue(), ^(void){ 90 | MSEventCell* cell = [self cellForEvent:event]; 91 | [cell setSelected:YES]; 92 | [self addChangeDurationIndicators:cell]; 93 | }); 94 | } 95 | 96 | 97 | - (void)addChangeDurationIndicators:(MSEventCell*)cell{ 98 | mStartY = cell.frame.origin.y; 99 | mStartHeight = cell.frame.size.height; 100 | mStartIndicator = [MSDurationChangeIndicator makeForStartWithCell:cell andDelegate:self]; 101 | mEndIndicator = [MSDurationChangeIndicator makeForEndWithCell:cell andDelegate:self]; 102 | } 103 | 104 | -(NSDate*)dateForDragable{ 105 | CGPoint dropPoint = CGPointMake(mDragableEvent.frame.origin.x + mDragableEvent.touchOffset.x, mDragableEvent.frame.origin.y); 106 | return [self dateForPoint:dropPoint]; 107 | } 108 | 109 | -(BOOL)canMoveToNewDate:(MSEvent*)event newDate:(NSDate*)newDate{ 110 | if (! self.dragDelegate) return true; 111 | return [self.dragDelegate weekView:self canMoveEvent:event to:newDate]; 112 | } 113 | //========================================================= 114 | #pragma mark - On indicators dragged 115 | //========================================================= 116 | -(void)durationIndicatorStartUpdated:(MSDurationChangeIndicator*)sender y:(int)y{ 117 | sender.eventCell.frame = CGRectMake( 118 | sender.eventCell.frame.origin.x, 119 | sender.eventCell.frame.origin.y + y, 120 | sender.eventCell.frame.size.width, 121 | sender.eventCell.frame.size.height - y); 122 | [mEndIndicator updatePosition]; 123 | mStartIndicator.timeLabel.text = [[self startDateFor:sender.eventCell] format:@"HH:mm" timezone:@"device"]; 124 | } 125 | 126 | -(void)durationIndicatorEndUpdated:(MSDurationChangeIndicator*)sender y:(int)y{ 127 | sender.eventCell.frame = CGRectMake( 128 | sender.eventCell.frame.origin.x, 129 | sender.eventCell.frame.origin.y, 130 | sender.eventCell.frame.size.width, 131 | y); 132 | 133 | mEndIndicator.timeLabel.text = [[self endDateFor:sender.eventCell] format:@"HH:mm" timezone:@"device"]; 134 | } 135 | 136 | -(void)durationIndicatorEnded:(MSDurationChangeIndicator*)sender{ 137 | NSDate* startDate = [self startDateFor:sender.eventCell]; 138 | NSDate* endDate = [self endDateFor:sender.eventCell]; 139 | 140 | if([self canChangeDuration:sender.eventCell.event startDate:startDate endDate:endDate]){ 141 | sender.eventCell.event.StartDate = startDate; 142 | sender.eventCell.event.EndDate = endDate; 143 | if (self.changeDurationDelegate){ 144 | [self.changeDurationDelegate weekView:self.weekView event:sender.eventCell.event durationChanged:startDate endDate:endDate]; 145 | } 146 | } 147 | [self.baseWeekView forceReload:YES]; 148 | [self readdChangeDurationIndicators:sender.eventCell.event]; 149 | } 150 | 151 | -(NSDate*)startDateFor:(MSEventCell*)eventCell{ 152 | return [self dateForPoint:CGPointMake( 153 | eventCell.frame.origin.x - self.collectionView.contentOffset.x + 5, 154 | eventCell.frame.origin.y - self.collectionView.contentOffset.y)]; 155 | } 156 | 157 | -(NSDate*)endDateFor:(MSEventCell*)eventCell{ 158 | return [self dateForPoint:CGPointMake( 159 | eventCell.frame.origin.x - self.collectionView.contentOffset.x + 5, 160 | eventCell.frame.origin.y - self.collectionView.contentOffset.y + eventCell.frame.size.height )]; 161 | } 162 | 163 | //========================================================= 164 | #pragma mark - Can move to new date? 165 | //========================================================= 166 | -(BOOL)canChangeDuration:(MSEvent*)event startDate:(NSDate*)startDate endDate:(NSDate*)endDate{ 167 | if (! self.changeDurationDelegate) return true; 168 | return [self.changeDurationDelegate weekView:self canChangeDuration:event startDate:startDate endDate:endDate]; 169 | } 170 | 171 | //========================================================= 172 | #pragma mark - Indicator stop dragged 173 | //========================================================= 174 | - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer 175 | { 176 | return otherGestureRecognizer.view == gestureRecognizer.view; 177 | } 178 | @end -------------------------------------------------------------------------------- /RVCalendarWeekView/Lib/WeekView/Decorators/MSWeekViewDecoratorDragable.h: -------------------------------------------------------------------------------- 1 | // 2 | // MSWeekViewDecoratorDragable.h 3 | // RVCalendarWeekView 4 | // 5 | // Created by Jordi Puigdellívol on 1/9/16. 6 | // Copyright © 2016 revo. All rights reserved. 7 | // 8 | 9 | #import "MSWeekViewDecorator.h" 10 | #import "MSDragableEvent.h" 11 | 12 | @protocol MSWeekViewDragableDelegate 13 | -(BOOL)weekView:(MSWeekView*)weekView canMoveEvent:(MSEvent*)event to:(NSDate*)date; 14 | -(void)weekView:(MSWeekView*)weekView event:(MSEvent*)event moved:(NSDate*)date; 15 | @optional 16 | -(BOOL)weekView:(MSWeekView*)weekView canStartMovingEvent:(MSEvent*)event; 17 | @end 18 | 19 | 20 | @interface MSWeekViewDecoratorDragable : MSWeekViewDecorator{ 21 | MSDragableEvent * mDragableEvent; 22 | } 23 | 24 | @property(weak,nonatomic) id dragDelegate; 25 | 26 | +(__kindof MSWeekView*)makeWith:(MSWeekView*)weekView andDelegate:(id)delegate; 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /RVCalendarWeekView/Lib/WeekView/Decorators/MSWeekViewDecoratorDragable.m: -------------------------------------------------------------------------------- 1 | // 2 | // MSWeekViewDecoratorDragable.m 3 | // RVCalendarWeekView 4 | // 5 | // Created by Jordi Puigdellívol on 1/9/16. 6 | // Copyright © 2016 revo. All rights reserved. 7 | // 8 | 9 | #import "MSWeekViewDecoratorDragable.h" 10 | #import "NSDate+Easy.h" 11 | #import "RVCollection.h" 12 | #import "NSDate+DateTools.h" 13 | 14 | @interface MSWeekViewDecoratorDragable () 15 | 16 | @end 17 | 18 | @implementation MSWeekViewDecoratorDragable 19 | 20 | +(__kindof MSWeekView*)makeWith:(MSWeekView*)weekView andDelegate:(id)delegate{ 21 | MSWeekViewDecoratorDragable * weekViewDecorator = [super makeWith:weekView]; 22 | weekViewDecorator.dragDelegate = delegate; 23 | return weekViewDecorator; 24 | } 25 | 26 | //========================================================= 27 | #pragma mark - Collection view datasource 28 | //========================================================= 29 | - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { 30 | MSEventCell *cell = (MSEventCell*)[super collectionView:collectionView cellForItemAtIndexPath:indexPath]; 31 | 32 | if(![self isGestureAlreadyAdded:cell]){ 33 | UILongPressGestureRecognizer* lpgr = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(onEventCellLongPress:)]; 34 | lpgr.delegate = self; 35 | [cell addGestureRecognizer:lpgr]; 36 | } 37 | 38 | return cell; 39 | } 40 | 41 | //========================================================= 42 | #pragma mark - Gesture recognizer delegate 43 | //========================================================= 44 | - (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer{ 45 | MSEventCell* eventCell = (MSEventCell*)gestureRecognizer.view; 46 | return [self.dragDelegate weekView:self.weekView canStartMovingEvent:eventCell.event]; 47 | } 48 | 49 | //========================================================= 50 | #pragma mark - Drag & Drop 51 | //========================================================= 52 | -(void)onEventCellLongPress:(UILongPressGestureRecognizer*)gestureRecognizer{ 53 | MSEventCell* eventCell = (MSEventCell*)gestureRecognizer.view; 54 | 55 | if (gestureRecognizer.state == UIGestureRecognizerStateBegan) { 56 | NSLog(@"Star drag: %@",eventCell.event.title); 57 | CGPoint touchOffsetInCell = [gestureRecognizer locationInView:gestureRecognizer.view]; 58 | mDragableEvent = [MSDragableEvent makeWithEventCell:eventCell andOffset:self.weekView.collectionView.contentOffset touchOffset:touchOffsetInCell]; 59 | [self.baseWeekView addSubview:mDragableEvent]; 60 | } 61 | else if(gestureRecognizer.state == UIGestureRecognizerStateChanged){ 62 | CGPoint cp = [gestureRecognizer locationInView:self.baseWeekView]; 63 | 64 | CGPoint newOrigin; 65 | float xOffset = ((int)self.collectionView.contentOffset.x % (int)self.weekFlowLayout.sectionWidth) - self.weekFlowLayout.timeRowHeaderWidth; 66 | cp.x += xOffset; 67 | float x = [self round:cp.x toLowest:self.weekFlowLayout.sectionWidth] - xOffset; 68 | newOrigin = CGPointMake(x, cp.y); 69 | newOrigin = CGPointMake(newOrigin.x /*+ mDragableEvent.touchOffset.x*/, 70 | newOrigin.y - mDragableEvent.touchOffset.y); 71 | 72 | [UIView animateWithDuration:0.1 animations:^{ 73 | mDragableEvent.frame = (CGRect) { .origin = newOrigin, .size = mDragableEvent.frame.size }; 74 | }]; 75 | 76 | NSDate* date = [self dateForDragable]; 77 | mDragableEvent.timeLabel.text = [date format:@"HH:mm" timezone:@"device"]; 78 | 79 | } 80 | else if(gestureRecognizer.state == UIGestureRecognizerStateEnded){ 81 | //NSLog(@"Long press ended: %@",eventCell.akEvent.title); 82 | [self onDragEnded:eventCell]; 83 | } 84 | } 85 | 86 | -(void)onDragEnded:(MSEventCell*)eventCell{ 87 | NSDate* newStartDate = [self dateForDragable]; 88 | if ([self canMoveToNewDate:eventCell.event newDate:newStartDate]){ 89 | int duration = eventCell.event.durationInSeconds; 90 | eventCell.event.StartDate = newStartDate; 91 | eventCell.event.EndDate = [eventCell.event.StartDate dateByAddingSeconds:duration]; 92 | [self.baseWeekView forceReload:YES]; 93 | if (self.dragDelegate){ 94 | [self.dragDelegate weekView:self.baseWeekView event:eventCell.event moved:newStartDate]; 95 | } 96 | } 97 | 98 | [mDragableEvent removeFromSuperview]; 99 | mDragableEvent = nil; 100 | } 101 | 102 | 103 | -(NSDate*)dateForDragable{ 104 | CGPoint dropPoint = CGPointMake(mDragableEvent.frame.origin.x + mDragableEvent.touchOffset.x, 105 | mDragableEvent.frame.origin.y); 106 | return [self dateForPoint:dropPoint]; 107 | } 108 | 109 | //========================================================= 110 | #pragma mark - Can move to new date? 111 | //========================================================= 112 | -(BOOL)canMoveToNewDate:(MSEvent*)event newDate:(NSDate*)newDate{ 113 | if (! self.dragDelegate) return true; 114 | return [self.dragDelegate weekView:self canMoveEvent:event to:newDate]; 115 | } 116 | 117 | -(BOOL)isPortrait{ 118 | return (UIDevice.currentDevice.orientation == UIDeviceOrientationPortrait || UIDevice.currentDevice.orientation == UIDeviceOrientationFaceUp); 119 | } 120 | 121 | //========================================================= 122 | #pragma mark - Gesture Recongnizer Delegate 123 | //========================================================= 124 | - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer { 125 | return otherGestureRecognizer.view == gestureRecognizer.view; 126 | } 127 | 128 | @end 129 | -------------------------------------------------------------------------------- /RVCalendarWeekView/Lib/WeekView/Decorators/MSWeekViewDecoratorFactory.h: -------------------------------------------------------------------------------- 1 | // 2 | // MSWeekViewDecoratorFactory.h 3 | // RVCalendarWeekView 4 | // 5 | // Created by Badchoice on 1/9/16. 6 | // Copyright © 2016 revo. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "MSWeekViewDecoratorDragable.h" 11 | #import "MSWeekViewDecoratorNewEvent.h" 12 | #import "MSWeekViewDecoratorInfinite.h" 13 | #import "MSWeekViewDecoratorPinchable.h" 14 | #import "MSWeekViewDecoratorChangeDuration.h" 15 | 16 | 17 | typedef NS_OPTIONS(NSUInteger, MSWeekViewFeatures) { 18 | MSDragableEventFeature = (1 << 0), // => 00000001 19 | MSNewEventFeature = (1 << 1), // => 00000010 20 | MSInfiniteFeature = (1 << 2), // => 00000100 21 | MSPinchableFeature = (1 << 3), // => 00001000 22 | MSShortPressNewEventFeature = (1 << 4), // => 00010000 23 | MSChangeDurationFeature = (1 << 5), // => 00100000 24 | MSChangeDurationAndDragableFeature = (1 << 6), // => 01000000 25 | }; 26 | 27 | @interface MSWeekViewDecoratorFactory : NSObject 28 | 29 | 30 | /** 31 | * This adds the decorations to the baseView 32 | * Using this constructor the delegate should implement all the protocols fore each feature defined in `features` 33 | */ 34 | +(MSWeekView*)make:(MSWeekView*)baseView features:(NSUInteger)features andDelegate:(id)delegate; 35 | 36 | 37 | /** 38 | * Recursive function to set minutesPrecision to all decorators 39 | */ 40 | +(void)setMinutesPrecisionToAllDecorators:(MSWeekView*)weekViewWithDecorators minutesPrecision:(int)minutesPrecision; 41 | @end 42 | -------------------------------------------------------------------------------- /RVCalendarWeekView/Lib/WeekView/Decorators/MSWeekViewDecoratorFactory.m: -------------------------------------------------------------------------------- 1 | // 2 | // MSWeekViewDecoratorFactory.m 3 | // RVCalendarWeekView 4 | // 5 | // Created by Badchoice on 1/9/16. 6 | // Copyright © 2016 revo. All rights reserved. 7 | // 8 | 9 | #import "MSWeekViewDecoratorFactory.h" 10 | #import "MSWeekViewDecoratorChangeDurationAndDragable.h" 11 | 12 | @implementation MSWeekViewDecoratorFactory 13 | 14 | +(MSWeekView*)make:(MSWeekView*)baseView features:(NSUInteger)features andDelegate:(id)delegate{ 15 | 16 | MSWeekView* decoratedView = baseView; 17 | 18 | if ( (features & MSInfiniteFeature) != 0 ){ // => true 19 | decoratedView = [MSWeekViewDecoratorInfinite makeWith:decoratedView andDelegate:delegate]; 20 | } 21 | 22 | if ( (features & MSNewEventFeature) != 0 ){ // => true 23 | decoratedView = [MSWeekViewDecoratorNewEvent makeWith:decoratedView andDelegate:delegate shortPress:NO]; 24 | } 25 | 26 | if ( (features & MSDragableEventFeature) != 0 ){ // => true 27 | decoratedView = [MSWeekViewDecoratorDragable makeWith:decoratedView andDelegate:delegate]; 28 | } 29 | 30 | if ( (features & MSPinchableFeature) != 0 ){ // => true 31 | decoratedView = [MSWeekViewDecoratorPinchable makeWith:decoratedView]; 32 | } 33 | 34 | if ( (features & MSShortPressNewEventFeature) != 0 ){ // => true 35 | decoratedView = [MSWeekViewDecoratorNewEvent makeWith:decoratedView andDelegate:delegate shortPress:YES]; 36 | } 37 | 38 | if ( (features & MSChangeDurationFeature) != 0 ){ // => true 39 | decoratedView = [MSWeekViewDecoratorChangeDuration makeWith:decoratedView andDelegate:delegate]; 40 | } 41 | 42 | if ( (features & MSChangeDurationAndDragableFeature) != 0 ){ // => true 43 | decoratedView = [MSWeekViewDecoratorChangeDurationAndDragable makeWith:decoratedView andDelegate:delegate]; 44 | } 45 | 46 | return decoratedView; 47 | } 48 | 49 | +(void)setMinutesPrecisionToAllDecorators:(MSWeekView*)weekViewWithDecorators minutesPrecision:(int)minutesPrecision{ 50 | if ([weekViewWithDecorators isKindOfClass:MSWeekViewDecorator.class]) { 51 | MSWeekViewDecorator* decorator = (MSWeekViewDecorator*)weekViewWithDecorators; 52 | decorator.minutesPrecision= minutesPrecision; 53 | [self.class setMinutesPrecisionToAllDecorators:decorator.weekView minutesPrecision:minutesPrecision]; 54 | } 55 | } 56 | 57 | @end 58 | -------------------------------------------------------------------------------- /RVCalendarWeekView/Lib/WeekView/Decorators/MSWeekViewDecoratorInfinite.h: -------------------------------------------------------------------------------- 1 | // 2 | // MSWeekViewDecoratorInfinite.h 3 | // RVCalendarWeekView 4 | // 5 | // Created by Badchoice on 1/9/16. 6 | // Copyright © 2016 revo. All rights reserved. 7 | // 8 | 9 | #import "MSWeekViewDecorator.h" 10 | 11 | 12 | @protocol MSWeekViewInfiniteDelegate 13 | 14 | /** 15 | * Return YES if new events are added, or NO if not to improve performance 16 | */ 17 | -(BOOL)weekView:(MSWeekView*)weekView newDaysLoaded:(NSDate*)startDate to:(NSDate*)endDate; 18 | @end 19 | 20 | @interface MSWeekViewDecoratorInfinite : MSWeekViewDecorator{ 21 | BOOL mLoading; 22 | } 23 | 24 | +(__kindof MSWeekView*)makeWith:(MSWeekView*)weekView andDelegate:(id)delegate; 25 | 26 | @property(weak,nonatomic) id infiniteDelegate; 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /RVCalendarWeekView/Lib/WeekView/Decorators/MSWeekViewDecoratorInfinite.m: -------------------------------------------------------------------------------- 1 | // 2 | // MSWeekViewDecoratorInfinite.m 3 | // RVCalendarWeekView 4 | // 5 | // Created by Badchoice on 1/9/16. 6 | // Copyright © 2016 revo. All rights reserved. 7 | // 8 | 9 | #import "MSWeekViewDecoratorInfinite.h" 10 | #import "NSDate+Easy.h" 11 | 12 | #define DAYS_TO_LOAD 30 13 | @interface MSWeekView() 14 | -(void)groupEventsByDays; 15 | @end 16 | 17 | @implementation MSWeekViewDecoratorInfinite 18 | 19 | +(__kindof MSWeekView*)makeWith:(MSWeekView*)weekView andDelegate:(id)delegate{ 20 | MSWeekViewDecoratorInfinite * weekViewDecorator = [super makeWith:weekView]; 21 | weekViewDecorator.infiniteDelegate = delegate; 22 | return weekViewDecorator; 23 | } 24 | 25 | //====================================================== 26 | #pragma mark - INFINITE SCROLL 27 | //====================================================== 28 | - (void)scrollViewDidScroll:(UIScrollView *)scrollView 29 | { 30 | [super scrollViewDidScroll:scrollView]; 31 | 32 | NSInteger currentOffset = scrollView.contentOffset.x; 33 | NSInteger maximumOffset = scrollView.contentSize.width - scrollView.frame.size.width; 34 | 35 | // Change 10.0 to adjust the distance from side 36 | if (maximumOffset - currentOffset <= 10.0 && !mLoading /*&& mShouldLoadMore*/) { 37 | //NSLog(@"Load more if necessary"); 38 | [self loadNextDays]; 39 | } 40 | } 41 | 42 | -(void)loadNextDays{ 43 | mLoading = true; 44 | dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 45 | 46 | NSDate * startDate = [self.baseWeekView.firstDay addDays:self.baseWeekView.daysToShow + 1]; 47 | NSDate * endDate = [startDate addDays:DAYS_TO_LOAD - 1]; 48 | 49 | self.baseWeekView.daysToShow += DAYS_TO_LOAD; 50 | if(self.infiniteDelegate){ 51 | if(![self.infiniteDelegate weekView:self.baseWeekView newDaysLoaded:startDate to:endDate]){ 52 | [self.baseWeekView forceReload:YES]; 53 | } 54 | } 55 | else{ 56 | [self.baseWeekView forceReload:YES]; 57 | } 58 | 59 | mLoading = false; 60 | }); 61 | } 62 | 63 | 64 | @end 65 | -------------------------------------------------------------------------------- /RVCalendarWeekView/Lib/WeekView/Decorators/MSWeekViewDecoratorNewEvent.h: -------------------------------------------------------------------------------- 1 | // 2 | // MSWeekViewDecoratorNewEvent.h 3 | // RVCalendarWeekView 4 | // 5 | // Created by Badchoice on 1/9/16. 6 | // Copyright © 2016 revo. All rights reserved. 7 | // 8 | 9 | #import "MSWeekViewDecorator.h" 10 | 11 | @protocol MSWeekViewNewEventDelegate 12 | @optional 13 | -(void)weekView:(MSWeekView*)weekView onLongPressAt:(NSDate*)date; 14 | -(void)weekView:(MSWeekView*)weekView onTapAt:(NSDate*)date; 15 | @end 16 | 17 | @interface MSWeekViewDecoratorNewEvent : MSWeekViewDecorator 18 | 19 | @property(weak,nonatomic) id createEventDelegate; 20 | @property(nonatomic) BOOL shortPress; 21 | 22 | +(__kindof MSWeekView*)makeWith:(MSWeekView*)weekView andDelegate:(id)delegate shortPress:(BOOL)shortPress; 23 | @end 24 | -------------------------------------------------------------------------------- /RVCalendarWeekView/Lib/WeekView/Decorators/MSWeekViewDecoratorNewEvent.m: -------------------------------------------------------------------------------- 1 | // 2 | // MSWeekViewDecoratorNewEvent.m 3 | // RVCalendarWeekView 4 | // 5 | // Created by Badchoice on 1/9/16. 6 | // Copyright © 2016 revo. All rights reserved. 7 | // 8 | 9 | #import "MSWeekViewDecoratorNewEvent.h" 10 | #import "NSDate+DateTools.h" 11 | #import "NSDate+Easy.h" 12 | 13 | @implementation MSWeekViewDecoratorNewEvent 14 | 15 | +(__kindof MSWeekView*)makeWith:(MSWeekView*)weekView andDelegate:(id)delegate shortPress:(BOOL)shortPress{ 16 | MSWeekViewDecoratorNewEvent * weekViewDecorator = [super makeWith:weekView]; 17 | weekViewDecorator.shortPress = shortPress; 18 | weekViewDecorator.createEventDelegate = delegate; 19 | return weekViewDecorator; 20 | } 21 | 22 | -(void)setShortPress:(BOOL)shortPress{ 23 | _shortPress = shortPress; 24 | UIGestureRecognizer* gr; 25 | if (self.shortPress) { 26 | gr = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onTap:)]; 27 | } else { 28 | gr = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(onLongPress:)]; 29 | } 30 | [gr setCancelsTouchesInView:NO]; //To didSelectCell still works 31 | [self.collectionView addGestureRecognizer:gr]; 32 | } 33 | 34 | -(void)onTap:(UIGestureRecognizer*)gestureRecognizer{ 35 | if (gestureRecognizer.state == UIGestureRecognizerStateRecognized) { 36 | NSDate* date = [self dateForGesture:gestureRecognizer]; 37 | 38 | if(self.createEventDelegate) 39 | [self.createEventDelegate weekView:self.baseWeekView onTapAt:date]; 40 | } 41 | } 42 | 43 | -(void)onLongPress:(UIGestureRecognizer*)gestureRecognizer{ 44 | if (gestureRecognizer.state == UIGestureRecognizerStateBegan) { 45 | NSDate* date = [self dateForGesture:gestureRecognizer]; 46 | 47 | if(self.createEventDelegate) 48 | [self.createEventDelegate weekView:self.baseWeekView onLongPressAt:date]; 49 | } 50 | } 51 | 52 | -(NSDate*)dateForGesture:(UIGestureRecognizer*)gestureRecognizer{ 53 | CGPoint cp = [gestureRecognizer locationInView:self.baseWeekView]; 54 | NSDate* date = [self dateForPoint:cp]; 55 | 56 | if(date.minute > 15 && date.minute < 45) date = [date withMinute:30]; 57 | else if(date.minute > 45) date = [[date addHour] withMinute:0]; 58 | else date = [date withMinute:0]; 59 | 60 | return date; 61 | } 62 | 63 | 64 | @end 65 | -------------------------------------------------------------------------------- /RVCalendarWeekView/Lib/WeekView/Decorators/MSWeekViewDecoratorPinchable.h: -------------------------------------------------------------------------------- 1 | // 2 | // MSWeekViewDecoratorPinchable.h 3 | // RVCalendarWeekView 4 | // 5 | // Created by Jordi Puigdellívol on 2/9/16. 6 | // Copyright © 2016 revo. All rights reserved. 7 | // 8 | 9 | #import "MSWeekViewDecorator.h" 10 | 11 | @interface MSWeekViewDecoratorPinchable : MSWeekViewDecorator 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /RVCalendarWeekView/Lib/WeekView/Decorators/MSWeekViewDecoratorPinchable.m: -------------------------------------------------------------------------------- 1 | // 2 | // MSWeekViewDecoratorPinchable.m 3 | // RVCalendarWeekView 4 | // 5 | // Created by Jordi Puigdellívol on 2/9/16. 6 | // Copyright © 2016 revo. All rights reserved. 7 | // 8 | 9 | #import "NSDate+Easy.h" 10 | #import "MSWeekViewDecoratorPinchable.h" 11 | #define MAX_HOUR_HEIGHT 250 12 | #define MIN_HOUR_HEIGHT 20 13 | 14 | @implementation MSWeekViewDecoratorPinchable 15 | 16 | 17 | -(void)setup{ 18 | [super setup]; 19 | 20 | UIGestureRecognizer* lpgr = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(onPinch:)]; 21 | [lpgr setCancelsTouchesInView:NO]; //To didSelectCell still works 22 | [self.collectionView addGestureRecognizer:lpgr]; 23 | } 24 | 25 | -(void)onPinch:(UIPinchGestureRecognizer*)gestureRecognizer{ 26 | //if (gestureRecognizer.state == UIGestureRecognizerStateEnded) { 27 | if (gestureRecognizer.state == UIGestureRecognizerStateChanged) { 28 | 29 | CGFloat newHourHeight = MIN(50* gestureRecognizer.scale, MAX_HOUR_HEIGHT); 30 | newHourHeight = MAX(newHourHeight, MIN_HOUR_HEIGHT); 31 | 32 | self.baseWeekView.weekFlowLayout.hourHeight = newHourHeight; 33 | [self.baseWeekView forceReload:NO]; 34 | 35 | //[self.baseWeekView.weekFlowLayout scrollCollectionViewToClosetSectionToTime:[NSDate parse:@"2018-10-10 20:00:00"] animated:YES]; 36 | } 37 | } 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /RVCalendarWeekView/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // RVCalendarWeekView 4 | // 5 | // Created by Jordi Puigdellívol on 22/8/16. 6 | // Copyright © 2016 revo. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "MSWeekViewDecoratorFactory.h" 11 | 12 | @interface ViewController : UIViewController { 13 | NSArray* unavailableHours; 14 | } 15 | 16 | /** 17 | * Base weekView with only selected event feature 18 | */ 19 | @property (weak, nonatomic) IBOutlet MSWeekView *weekView; 20 | 21 | /** 22 | * Strong reference since it is what adds the features to the weekView 23 | */ 24 | @property (strong, nonatomic) MSWeekView *decoratedWeekView; 25 | 26 | @end 27 | 28 | -------------------------------------------------------------------------------- /RVCalendarWeekView/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // RVCalendarWeekView 4 | // 5 | // Created by Jordi Puigdellívol on 22/8/16. 6 | // Copyright © 2016 revo. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | #import "MSEvent.h" 11 | #import "NSDate+Easy.h" 12 | #import "NSArray+Collection.h" 13 | #import "MSHourPerdiod.h" 14 | #import "RVHelpers.h" 15 | 16 | 17 | @interface ViewController () 18 | 19 | @end 20 | 21 | @implementation ViewController 22 | 23 | - (void)viewDidLoad { 24 | [super viewDidLoad]; 25 | [self setupWeekData]; 26 | } 27 | 28 | -(void)viewWillAppear:(BOOL)animated { 29 | [super viewWillAppear:animated]; 30 | run_on_ui(^{ 31 | [self.weekView.weekFlowLayout invalidateLayout]; 32 | }); 33 | } 34 | 35 | -(void)viewDidAppear:(BOOL)animated{ 36 | [super viewDidAppear:animated]; 37 | // [self.weekView.weekFlowLayout scrollCollectionViewToCurrentTime:YES]; 38 | [self.weekView.weekFlowLayout invalidateLayout]; 39 | } 40 | 41 | - (void)setupWeekData{ 42 | 43 | self.decoratedWeekView = [MSWeekViewDecoratorFactory make:self.weekView 44 | features:(/*MSDragableEventFeature |*/ MSChangeDurationAndDragableFeature | MSNewEventFeature | MSInfiniteFeature | MSPinchableFeature |MSShortPressNewEventFeature /*| MSChangeDurationFeature*/) 45 | andDelegate:self]; 46 | 47 | //Optional, set minutes precision for drag and new event (by default it is already set to 5) 48 | [MSWeekViewDecoratorFactory setMinutesPrecisionToAllDecorators:self.decoratedWeekView minutesPrecision:5]; 49 | 50 | 51 | //Create the events 52 | MSEvent* event1 = [MSEvent make:NSDate.now 53 | title:@"Title" 54 | subtitle:@"Central perk"]; 55 | 56 | MSEvent* event2 = [MSEvent make:[NSDate.now addMinutes:10] 57 | duration:60*3 58 | title:@"Title 2" 59 | subtitle:@"Central perk"]; 60 | 61 | MSEvent* event3 = [MSEvent make:[NSDate.tomorrow addMinutes:10] 62 | duration:60*26 63 | title:@"Title 3" 64 | subtitle:@"Central perk"]; 65 | 66 | MSEvent* event4 = [MSEvent make:[NSDate.nextWeek addHours:7] 67 | duration:60*3 68 | title:@"Title 4" 69 | subtitle:@"Central perk"]; 70 | 71 | _weekView.delegate = self; 72 | _weekView.weekFlowLayout.show24Hours = YES; 73 | _weekView.weekFlowLayout.hourGridDivisionValue = MSHourGridDivision_15_Minutes; 74 | 75 | if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { 76 | _weekView.daysToShowOnScreen = 7; 77 | } 78 | else{ 79 | _weekView.daysToShowOnScreen = 2; 80 | } 81 | _weekView.daysToShow = 30; 82 | _weekView.weekFlowLayout.hourHeight = 50; 83 | _weekView.events = @[event1,event2,event3,event4]; 84 | } 85 | 86 | //========================================= 87 | #pragma mark - Week View delegate 88 | //========================================= 89 | -(void)weekView:(id)sender eventSelected:(MSEventCell*)eventCell{ 90 | NSLog(@"Event selected: %@",eventCell.event.title); 91 | //[_weekView removeEvent:event]; 92 | } 93 | 94 | //This one is optional 95 | -(NSArray*)weekView:(id)sender unavailableHoursPeriods:(NSDate*)date{ 96 | if(!unavailableHours){ 97 | unavailableHours = @[ 98 | [MSHourPerdiod make:@"00:00" end:@"09:00"], 99 | [MSHourPerdiod make:@"18:30" end:@"21:00"], 100 | ]; 101 | } 102 | return unavailableHours; 103 | } 104 | 105 | //========================================= 106 | #pragma mark - Week View Decorator Dragable delegate 107 | //========================================= 108 | -(void)weekView:(MSWeekView *)weekView event:(MSEvent *)event moved:(NSDate *)date{ 109 | NSLog(@"Event moved"); 110 | } 111 | 112 | -(BOOL)weekView:(MSWeekView*)weekView canStartMovingEvent:(MSEvent*)event{ 113 | return YES; 114 | } 115 | 116 | -(BOOL)weekView:(MSWeekView *)weekView canMoveEvent:(MSEvent *)event to:(NSDate *)date{ 117 | return YES; 118 | 119 | //Example on how to return YES/NO from an async function (for example an alert) 120 | /*NSCondition* condition = [NSCondition new]; 121 | BOOL __block shouldMove; 122 | 123 | RVAlertController* a = [RVAlertController alert:@"Move" 124 | message:@"Do you want to move"; 125 | 126 | 127 | [a showAlertWithCompletion:^(NSInteger buttonIndex) { 128 | shouldMove = (buttonIndex == RVALERT_OK); 129 | [condition signal]; 130 | }]; 131 | 132 | [condition lock]; 133 | [condition wait]; 134 | [condition unlock]; 135 | 136 | return shouldMove;*/ 137 | } 138 | 139 | //========================================= 140 | #pragma mark - Week View Decorator New event delegate 141 | //========================================= 142 | -(void)weekView:(MSWeekView*)weekView onLongPressAt:(NSDate*)date{ 143 | NSLog(@"Long pressed at: %@", date); 144 | MSEvent *newEvent = [MSEvent make:date title:@"New Event" subtitle:@"Platinium stadium"]; 145 | [_weekView addEvent:newEvent]; 146 | } 147 | 148 | -(void)weekView:(MSWeekView*)weekView onTapAt:(NSDate*)date{ 149 | NSLog(@"Short pressed at: %@", date); 150 | } 151 | 152 | 153 | //========================================= 154 | #pragma mark - Week View Decorator Infinite delegate 155 | //========================================= 156 | -(BOOL)weekView:(MSWeekView*)weekView newDaysLoaded:(NSDate*)startDate to:(NSDate*)endDate{ 157 | NSLog(@"New days loaded: %@ - %@", startDate, endDate); 158 | 159 | MSEvent* newEvent = [MSEvent make:[startDate addHours:7] 160 | duration:60*3 161 | title:@"New event" 162 | subtitle:@"Batcave"]; 163 | 164 | MSEvent* lastEvent = [MSEvent make:[endDate addHours:-7] 165 | duration:60*3 166 | title:@"Last event" 167 | subtitle:@"Fantastic tower"]; 168 | 169 | [weekView addEvents:@[newEvent,lastEvent]]; 170 | return YES; 171 | } 172 | 173 | //========================================= 174 | #pragma mark - Week View Decorator Change duration delegate 175 | //========================================= 176 | -(BOOL)weekView:(MSWeekView*)weekView canChangeDuration:(MSEvent*)event startDate:(NSDate*)startDate endDate:(NSDate*)endDate{ 177 | return YES; 178 | } 179 | -(void)weekView:(MSWeekView*)weekView event:(MSEvent*)event durationChanged:(NSDate*)startDate endDate:(NSDate*)endDate{ 180 | NSLog(@"Changed event duration"); 181 | } 182 | 183 | @end 184 | -------------------------------------------------------------------------------- /RVCalendarWeekView/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // RVCalendarWeekView 4 | // 5 | // Created by Jordi Puigdellívol on 22/8/16. 6 | // Copyright © 2016 revo. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /RVCalendarWeekViewTests/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 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /RVCalendarWeekViewTests/RVCalendarWeekViewTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // RVCalendarWeekViewTests.m 3 | // RVCalendarWeekViewTests 4 | // 5 | // Created by Jordi Puigdellívol on 22/8/16. 6 | // Copyright © 2016 revo. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface RVCalendarWeekViewTests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation RVCalendarWeekViewTests 16 | 17 | - (void)setUp { 18 | [super setUp]; 19 | // Put setup code here. This method is called before the invocation of each test method in the class. 20 | } 21 | 22 | - (void)tearDown { 23 | // Put teardown code here. This method is called after the invocation of each test method in the class. 24 | [super tearDown]; 25 | } 26 | 27 | - (void)testExample { 28 | // This is an example of a functional test case. 29 | // Use XCTAssert and related functions to verify your tests produce the correct results. 30 | } 31 | 32 | - (void)testPerformanceExample { 33 | // This is an example of a performance test case. 34 | [self measureBlock:^{ 35 | // Put the code you want to measure the time of here. 36 | }]; 37 | } 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /readme_images/complex.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BadChoice/RVCalendarWeekView/86594399419abaf0e0bdf6f816cefe67f92da39f/readme_images/complex.png -------------------------------------------------------------------------------- /readme_images/full_demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BadChoice/RVCalendarWeekView/86594399419abaf0e0bdf6f816cefe67f92da39f/readme_images/full_demo.gif -------------------------------------------------------------------------------- /readme_images/iphone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BadChoice/RVCalendarWeekView/86594399419abaf0e0bdf6f816cefe67f92da39f/readme_images/iphone.png --------------------------------------------------------------------------------