From 544b334d156faff1a219bdf48e08e4c2ce339f62 Mon Sep 17 00:00:00 2001 From: Jon Manning Date: Thu, 23 Aug 2012 12:26:09 +1000 Subject: [PATCH 01/26] Update gitignore. --- .gitignore | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index debc8a9..edc082c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,15 @@ -.DS_Store -.svn/ -build/ +# Xcode +build/* *.pbxuser +!default.pbxuser *.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 +*.xcworkspace +!default.xcworkspace +xcuserdata +profile +*.moved-aside From 387b026a4e4da6de235a37fe2fe632dd52e35190 Mon Sep 17 00:00:00 2001 From: Jon Manning Date: Thu, 23 Aug 2012 12:26:42 +1000 Subject: [PATCH 02/26] Update base SDK to latest iOS. Convert to ARC and modern ObjC syntax. --- Calendar.xcodeproj/project.pbxproj | 10 ++++++++-- Classes/CalendarAppDelegate.m | 12 +++--------- GCCalendar/GCCalendar.m | 2 +- GCCalendar/GCCalendarDayView.h | 2 +- GCCalendar/GCCalendarDayView.m | 23 ++++------------------- GCCalendar/GCCalendarEvent.h | 2 +- GCCalendar/GCCalendarEvent.m | 9 --------- GCCalendar/GCCalendarPortraitView.m | 20 ++++++-------------- GCCalendar/GCCalendarTile.h | 2 +- GCCalendar/GCCalendarTile.m | 3 --- GCCalendar/GCCalendarView.h | 8 ++++---- GCCalendar/GCDatePickerControl.h | 2 +- GCCalendar/GCDatePickerControl.m | 9 --------- main.m | 8 ++++---- 14 files changed, 34 insertions(+), 78 deletions(-) diff --git a/Calendar.xcodeproj/project.pbxproj b/Calendar.xcodeproj/project.pbxproj index 1122282..5dd0f26 100755 --- a/Calendar.xcodeproj/project.pbxproj +++ b/Calendar.xcodeproj/project.pbxproj @@ -208,7 +208,11 @@ isa = PBXProject; buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "Calendar" */; compatibilityVersion = "Xcode 3.1"; + developmentRegion = English; hasScannedForEncodings = 1; + knownRegions = ( + en, + ); mainGroup = 29B97314FDCFA39411CA2CEA /* CustomTemplate */; projectDirPath = ""; projectRoot = ""; @@ -277,6 +281,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ENABLE_OBJC_ARC = YES; COPY_PHASE_STRIP = NO; GCC_DYNAMIC_NO_PIC = NO; GCC_OPTIMIZATION_LEVEL = 0; @@ -291,6 +296,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ENABLE_OBJC_ARC = YES; COPY_PHASE_STRIP = YES; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = Calendar_Prefix.pch; @@ -308,7 +314,7 @@ GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; PREBINDING = NO; - SDKROOT = iphoneos3.1.2; + SDKROOT = iphoneos; }; name = Debug; }; @@ -321,7 +327,7 @@ GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; PREBINDING = NO; - SDKROOT = iphoneos3.1.2; + SDKROOT = iphoneos; }; name = Release; }; diff --git a/Classes/CalendarAppDelegate.m b/Classes/CalendarAppDelegate.m index a3eda47..438161d 100644 --- a/Classes/CalendarAppDelegate.m +++ b/Classes/CalendarAppDelegate.m @@ -12,17 +12,17 @@ @implementation CalendarAppDelegate - (void)applicationDidFinishLaunching:(UIApplication *)application { // create calendar view - GCCalendarPortraitView *calendar = [[[GCCalendarPortraitView alloc] init] autorelease]; + GCCalendarPortraitView *calendar = [[GCCalendarPortraitView alloc] init]; calendar.dataSource = self; calendar.delegate = self; calendar.hasAddButton = YES; // create navigation view - UINavigationController *nav = [[[UINavigationController alloc] initWithRootViewController:calendar] autorelease]; + UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:calendar]; // create tab controller tabController = [[UITabBarController alloc] init]; - tabController.viewControllers = [NSArray arrayWithObject:nav]; + tabController.viewControllers = @[nav]; // setup window window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; @@ -32,13 +32,10 @@ - (void)applicationDidFinishLaunching:(UIApplication *)application { - (void)dealloc { - [window release]; window = nil; - [tabController release]; tabController = nil; - [super dealloc]; } #pragma mark GCCalendarDataSource @@ -68,7 +65,6 @@ - (NSArray *)calendarEventsForDate:(NSDate *)date { event.endDate = [[NSCalendar currentCalendar] dateFromComponents:components]; [events addObject:event]; - [event release]; } @@ -83,14 +79,12 @@ - (NSArray *)calendarEventsForDate:(NSDate *)date { [components setHour:20]; evt.endDate = [[NSCalendar currentCalendar] dateFromComponents:components]; [events addObject:evt]; - [evt release]; // create an all day event GCCalendarEvent *event = [[GCCalendarEvent alloc] init]; event.allDayEvent = YES; event.eventName = @"All Day Event"; [events addObject:event]; - [event release]; return events; } diff --git a/GCCalendar/GCCalendar.m b/GCCalendar/GCCalendar.m index 76a17ff..35f4d78 100644 --- a/GCCalendar/GCCalendar.m +++ b/GCCalendar/GCCalendar.m @@ -65,7 +65,7 @@ + (NSDateFormatter *)timeFormatter { #pragma mark color list + (NSArray *)colors { if (colors == nil) { - colors = [[NSArray arrayWithObjects:@"BLUE", @"GREEN", @"ORANGE", @"MAGENTA", @"PURPLE", @"RED", @"YELLOW", nil] retain]; + colors = @[@"BLUE", @"GREEN", @"ORANGE", @"MAGENTA", @"PURPLE", @"RED", @"YELLOW"]; } return colors; diff --git a/GCCalendar/GCCalendarDayView.h b/GCCalendar/GCCalendarDayView.h index 22155dd..d1bbe9c 100644 --- a/GCCalendar/GCCalendarDayView.h +++ b/GCCalendar/GCCalendarDayView.h @@ -33,7 +33,7 @@ id dataSource; } -@property (nonatomic, retain) NSDate *date; +@property (nonatomic, strong) NSDate *date; /* accessor methods for accessing the contentOffset of the scroll view. this is used to keep the scroll position the same from one day view diff --git a/GCCalendar/GCCalendarDayView.m b/GCCalendar/GCCalendarDayView.m index 7168abd..6705f26 100644 --- a/GCCalendar/GCCalendarDayView.m +++ b/GCCalendar/GCCalendarDayView.m @@ -36,7 +36,7 @@ @implementation GCCalendarAllDayView - (id)initWithEvents:(NSArray *)a { if (self = [super init]) { NSPredicate *pred = [NSPredicate predicateWithFormat:@"allDayEvent == YES"]; - events = [[a filteredArrayUsingPredicate:pred] retain]; + events = [a filteredArrayUsingPredicate:pred]; NSInteger eventCount = 0; for (GCCalendarEvent *e in events) { @@ -44,7 +44,6 @@ - (id)initWithEvents:(NSArray *)a { GCCalendarTile *tile = [[GCCalendarTile alloc] init]; tile.event = e; [self addSubview:tile]; - [tile release]; eventCount++; } @@ -54,10 +53,8 @@ - (id)initWithEvents:(NSArray *)a { return self; } - (void)dealloc { - [events release]; events = nil; - [super dealloc]; } - (BOOL)hasEvents { return ([events count] != 0); @@ -126,13 +123,12 @@ @implementation GCCalendarTodayView - (id)initWithEvents:(NSArray *)a { if (self = [super init]) { NSPredicate *pred = [NSPredicate predicateWithFormat:@"allDayEvent == NO"]; - events = [[a filteredArrayUsingPredicate:pred] retain]; + events = [a filteredArrayUsingPredicate:pred]; for (GCCalendarEvent *e in events) { GCCalendarTile *tile = [[GCCalendarTile alloc] init]; tile.event = e; [self addSubview:tile]; - [tile release]; } } @@ -142,10 +138,8 @@ - (BOOL)hasEvents { return ([events count] != 0); } - (void)dealloc { - [events release]; events = nil; - [super dealloc]; } - (void)layoutSubviews { for (UIView *view in self.subviews) { @@ -287,11 +281,10 @@ @implementation GCCalendarDayView #pragma mark create and destroy view + (void)initialize { if(self == [GCCalendarDayView class]) { - timeStrings = [[NSArray arrayWithObjects:@"12", + timeStrings = @[@"12", @"1", @"2", @"3", @"4", @"5", @"6", @"7", @"8", @"9", @"10", @"11", [[NSBundle mainBundle] localizedStringForKey:@"NOON" value:@"" table:@"GCCalendar"], - @"1", @"2", @"3", @"4", @"5", @"6", @"7", @"8", @"9", @"10", @"11", @"12", nil] - retain]; + @"1", @"2", @"3", @"4", @"5", @"6", @"7", @"8", @"9", @"10", @"11", @"12"]; } } - (id)initWithCalendarView:(GCCalendarView *)view { @@ -301,20 +294,12 @@ - (id)initWithCalendarView:(GCCalendarView *)view { return self; } -- (void)dealloc { - self.date = nil; - - [super dealloc]; -} - (void)reloadData { // get new events for date events = [dataSource calendarEventsForDate:date]; // drop all subviews [self.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)]; - [allDayView release]; - [todayView release]; - [scrollView release]; // create all day view allDayView = [[GCCalendarAllDayView alloc] initWithEvents:events]; diff --git a/GCCalendar/GCCalendarEvent.h b/GCCalendar/GCCalendarEvent.h index f970dc1..23bd288 100644 --- a/GCCalendar/GCCalendarEvent.h +++ b/GCCalendar/GCCalendarEvent.h @@ -47,7 +47,7 @@ @property (nonatomic, copy) NSDate *startDate; @property (nonatomic, copy) NSDate *endDate; @property (nonatomic, copy) NSString *color; -@property (nonatomic, retain) id userInfo; +@property (nonatomic, strong) id userInfo; @property (nonatomic) BOOL allDayEvent; @end diff --git a/GCCalendar/GCCalendarEvent.m b/GCCalendar/GCCalendarEvent.m index a40685b..1927f2c 100644 --- a/GCCalendar/GCCalendarEvent.m +++ b/GCCalendar/GCCalendarEvent.m @@ -28,14 +28,5 @@ - (id)init { return self; } -- (void)dealloc { - self.eventName = nil; - self.eventDescription = nil; - self.startDate = nil; - self.endDate = nil; - self.color = nil; - - [super dealloc]; -} @end diff --git a/GCCalendar/GCCalendarPortraitView.m b/GCCalendar/GCCalendarPortraitView.m index d3eaae1..ce6257e 100644 --- a/GCCalendar/GCCalendarPortraitView.m +++ b/GCCalendar/GCCalendarPortraitView.m @@ -17,8 +17,8 @@ #define kAnimationDuration 0.3f @interface GCCalendarPortraitView () -@property (nonatomic, retain) NSDate *date; -@property (nonatomic, retain) GCCalendarDayView *dayView; +@property (nonatomic, strong) NSDate *date; +@property (nonatomic, strong) GCCalendarDayView *dayView; - (void)reloadDayAnimated:(BOOL)animated context:(void *)context; @end @@ -51,12 +51,8 @@ - (id)init { - (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; - self.date = nil; - self.dayView = nil; - [dayPicker release]; - [super dealloc]; } #pragma mark calendar actions @@ -78,7 +74,7 @@ - (void)datePickerDidChangeDate:(GCDatePickerControl *)picker { [[NSUserDefaults standardUserDefaults] setObject:date forKey:@"GCCalendarDate"]; - [self reloadDayAnimated:YES context:[NSNumber numberWithInt:interval]]; + [self reloadDayAnimated:YES context:(__bridge void *)([NSNumber numberWithInt:interval])]; } #pragma mark button actions @@ -106,7 +102,6 @@ - (void)setHasAddButton:(BOOL)b { target:self action:@selector(add)]; self.navigationItem.rightBarButtonItem = button; - [button release]; } else { self.navigationItem.rightBarButtonItem = nil; @@ -145,7 +140,6 @@ - (void)loadView { target:self action:@selector(today)]; self.navigationItem.leftBarButtonItem = button; - [button release]; } - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; @@ -166,7 +160,7 @@ - (void)viewDidDisappear:(BOOL)animated { #pragma mark view animation functions - (void)reloadDayAnimated:(BOOL)animated context:(void *)context { if (animated) { - NSTimeInterval interval = [(NSNumber *)context doubleValue]; + NSTimeInterval interval = [(__bridge NSNumber *)context doubleValue]; // block user interaction dayPicker.userInteractionEnabled = NO; @@ -181,7 +175,6 @@ - (void)reloadDayAnimated:(BOOL)animated context:(void *)context { initialFrame.origin.x = 0 - initialFrame.size.width; } else { - [nextDayView release]; return; } nextDayView.frame = initialFrame; @@ -191,7 +184,7 @@ - (void)reloadDayAnimated:(BOOL)animated context:(void *)context { [self.view addSubview:nextDayView]; - [UIView beginAnimations:nil context:nextDayView]; + [UIView beginAnimations:nil context:(__bridge void *)(nextDayView)]; [UIView setAnimationDuration:kAnimationDuration]; [UIView setAnimationDelegate:self]; [UIView setAnimationDidStopSelector:@selector(animationDidStop:finished:context:)]; @@ -216,7 +209,7 @@ - (void)animationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context { - GCCalendarDayView *nextDayView = (GCCalendarDayView *)context; + GCCalendarDayView *nextDayView = (__bridge GCCalendarDayView *)context; // cut variables [dayView removeFromSuperview]; @@ -225,7 +218,6 @@ - (void)animationDidStop:(NSString *)animationID self.dayView = nextDayView; // release pointers - [nextDayView release]; // reset pickers dayPicker.userInteractionEnabled = YES; diff --git a/GCCalendar/GCCalendarTile.h b/GCCalendar/GCCalendarTile.h index f498f8a..00b8d9f 100644 --- a/GCCalendar/GCCalendarTile.h +++ b/GCCalendar/GCCalendarTile.h @@ -30,6 +30,6 @@ GCCalendarEvent *event; } -@property (nonatomic, retain) GCCalendarEvent *event; +@property (nonatomic, strong) GCCalendarEvent *event; @end diff --git a/GCCalendar/GCCalendarTile.m b/GCCalendar/GCCalendarTile.m index 8371444..c676bb1 100644 --- a/GCCalendar/GCCalendarTile.m +++ b/GCCalendar/GCCalendarTile.m @@ -49,12 +49,9 @@ - (id)init { - (void)dealloc { self.event = nil; - [super dealloc]; } - (void)setEvent:(GCCalendarEvent *)e { - [event release]; event = e; - [event retain]; // set bg image NSString *colorString = [event.color capitalizedString]; diff --git a/GCCalendar/GCCalendarView.h b/GCCalendar/GCCalendarView.h index d2840d3..1fbe01d 100644 --- a/GCCalendar/GCCalendarView.h +++ b/GCCalendar/GCCalendarView.h @@ -12,13 +12,13 @@ @interface GCCalendarView : UIViewController { // data source - id dataSource; + id __unsafe_unretained dataSource; // delegate - id delegate; + id __unsafe_unretained delegate; } -@property (nonatomic, assign) id dataSource; -@property (nonatomic, assign) id delegate; +@property (nonatomic, unsafe_unretained) id dataSource; +@property (nonatomic, unsafe_unretained) id delegate; @end diff --git a/GCCalendar/GCDatePickerControl.h b/GCCalendar/GCDatePickerControl.h index 56e5957..13be0d8 100644 --- a/GCCalendar/GCDatePickerControl.h +++ b/GCCalendar/GCDatePickerControl.h @@ -30,6 +30,6 @@ BOOL today; } -@property (nonatomic, retain) NSDate *date; +@property (nonatomic, strong) NSDate *date; @end diff --git a/GCCalendar/GCDatePickerControl.m b/GCCalendar/GCDatePickerControl.m index 49ce02f..49cfa26 100644 --- a/GCCalendar/GCDatePickerControl.m +++ b/GCCalendar/GCDatePickerControl.m @@ -57,18 +57,13 @@ - (id)init { return self; } - (void)dealloc { - [backButton release]; backButton = nil; - [forwardButton release]; forwardButton = nil; - [titleLabel release]; titleLabel = nil; - self.date = nil; - [super dealloc]; } #pragma mark view notifications @@ -93,9 +88,7 @@ - (void)layoutSubviews { #pragma mark setters - (void)setDate:(NSDate *)newDate { - [date release]; date = newDate; - [date retain]; self.today = [GCCalendar dateIsToday:date]; @@ -145,11 +138,9 @@ - (void)buttonPressed:(UIButton *)sender { if(sender == backButton) { NSDate *newDate = [[NSDate alloc] initWithTimeInterval:-kSecondsInDay sinceDate:date]; self.date = newDate; - [newDate release]; } else if(sender == forwardButton) { NSDate *newDate = [[NSDate alloc] initWithTimeInterval:kSecondsInDay sinceDate:date]; self.date = newDate; - [newDate release]; } [self sendActionsForControlEvents:UIControlEventValueChanged]; diff --git a/main.m b/main.m index 0415e1f..7491e2e 100644 --- a/main.m +++ b/main.m @@ -10,8 +10,8 @@ int main(int argc, char *argv[]) { - NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; - int retVal = UIApplicationMain(argc, argv, nil, @"CalendarAppDelegate"); - [pool release]; - return retVal; + @autoreleasepool { + int retVal = UIApplicationMain(argc, argv, nil, @"CalendarAppDelegate"); + return retVal; + } } From 15165a69faacfa7f18e11626105736198fb12222 Mon Sep 17 00:00:00 2001 From: Jon Manning Date: Thu, 23 Aug 2012 12:41:50 +1000 Subject: [PATCH 03/26] If events intersect, lay them out side-by-side. --- Classes/CalendarAppDelegate.m | 20 ++++++++++++++++++++ GCCalendar/GCCalendarDayView.m | 27 ++++++++++++++++++++++++--- GCCalendar/GCCalendarEvent.h | 25 ++++++------------------- GCCalendar/GCCalendarEvent.m | 27 +++++++++++++++++++-------- 4 files changed, 69 insertions(+), 30 deletions(-) diff --git a/Classes/CalendarAppDelegate.m b/Classes/CalendarAppDelegate.m index 438161d..e580dcc 100644 --- a/Classes/CalendarAppDelegate.m +++ b/Classes/CalendarAppDelegate.m @@ -79,7 +79,27 @@ - (NSArray *)calendarEventsForDate:(NSDate *)date { [components setHour:20]; evt.endDate = [[NSCalendar currentCalendar] dateFromComponents:components]; [events addObject:evt]; + + evt = [[GCCalendarEvent alloc] init]; + evt.eventName = @"Test event"; + evt.eventDescription = @"Description for test event. This is intentionnaly too long to stay on a single line."; + [components setHour:17]; + [components setMinute:0]; + evt.startDate = [[NSCalendar currentCalendar] dateFromComponents:components]; + [components setHour:20]; + evt.endDate = [[NSCalendar currentCalendar] dateFromComponents:components]; + [events addObject:evt]; + evt = [[GCCalendarEvent alloc] init]; + evt.eventName = @"Test event"; + [components setHour:19]; + [components setMinute:0]; + evt.startDate = [[NSCalendar currentCalendar] dateFromComponents:components]; + [components setHour:20]; + [components setMinute:30]; + evt.endDate = [[NSCalendar currentCalendar] dateFromComponents:components]; + [events addObject:evt]; + // create an all day event GCCalendarEvent *event = [[GCCalendarEvent alloc] init]; event.allDayEvent = YES; diff --git a/GCCalendar/GCCalendarDayView.m b/GCCalendar/GCCalendarDayView.m index 6705f26..4341247 100644 --- a/GCCalendar/GCCalendarDayView.m +++ b/GCCalendar/GCCalendarDayView.m @@ -166,10 +166,15 @@ - (void)layoutSubviews { CGFloat endPos = kTopLineBuffer + endHour * 2 * kHalfHourDiff + 3; endPos += (endMinute / 60.0) * (kHalfHourDiff * 2.0); endPos = floor(endPos); + + NSLog(@"%@ has %i intersecting events", tile.event, tile.event.intersectingEvents.count); + + NSInteger columnWidth = (self.bounds.size.width - kTileLeftSide - kTileRightSide) / tile.event.intersectingEvents.count; + NSInteger columnNumber = tile.event.column; - tile.frame = CGRectMake(kTileLeftSide, + tile.frame = CGRectMake(kTileLeftSide + (columnWidth * columnNumber), startPos, - self.bounds.size.width - kTileLeftSide - kTileRightSide, + columnWidth, endPos - startPos); } } @@ -297,7 +302,23 @@ - (id)initWithCalendarView:(GCCalendarView *)view { - (void)reloadData { // get new events for date events = [dataSource calendarEventsForDate:date]; - + + // sort the events by start date + events = [events sortedArrayUsingDescriptors:@[[NSSortDescriptor sortDescriptorWithKey:@"startDate" ascending:YES]]]; + + // figure out which events intersect (yay, O(n^2)) + for (GCCalendarEvent* event in events) { + + NSMutableArray* intersectingEvents = [NSMutableArray array]; + + for (GCCalendarEvent* otherEvent in events) { + if ([event intersectsEvent:otherEvent]) + [intersectingEvents addObject:otherEvent]; + } + + event.intersectingEvents = intersectingEvents; + } + // drop all subviews [self.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)]; diff --git a/GCCalendar/GCCalendarEvent.h b/GCCalendar/GCCalendarEvent.h index 23bd288..aac3d34 100644 --- a/GCCalendar/GCCalendarEvent.h +++ b/GCCalendar/GCCalendarEvent.h @@ -22,25 +22,7 @@ represents. Ex. in CoreData based applications, userInfo could be the objectID of a managed object. */ -@interface GCCalendarEvent : NSObject { - // name of the event - NSString *eventName; - // event description - NSString *eventDescription; - - // start date - NSDate *startDate; - // end date - NSDate *endDate; - - // color - NSString *color; - // is this an all day event - BOOL allDayEvent; - - // contextual information - id userInfo; -} +@interface GCCalendarEvent : NSObject @property (nonatomic, copy) NSString *eventName; @property (nonatomic, copy) NSString *eventDescription; @@ -50,4 +32,9 @@ @property (nonatomic, strong) id userInfo; @property (nonatomic) BOOL allDayEvent; +@property (nonatomic, copy) NSArray* intersectingEvents; +@property (readonly) NSInteger column; + +- (BOOL) intersectsEvent:(GCCalendarEvent*)otherEvent; + @end diff --git a/GCCalendar/GCCalendarEvent.m b/GCCalendar/GCCalendarEvent.m index 1927f2c..4125c59 100644 --- a/GCCalendar/GCCalendarEvent.m +++ b/GCCalendar/GCCalendarEvent.m @@ -12,14 +12,6 @@ @implementation GCCalendarEvent -@synthesize eventName; -@synthesize eventDescription; -@synthesize startDate; -@synthesize endDate; -@synthesize allDayEvent; -@synthesize color; -@synthesize userInfo; - - (id)init { if (self = [super init]) { self.color = @"GREY"; @@ -28,5 +20,24 @@ - (id)init { return self; } +- (BOOL) intersectsEvent:(GCCalendarEvent*)otherEvent { + + NSTimeInterval myStartDateTime = self.startDate.timeIntervalSinceReferenceDate; + NSTimeInterval myEndDateTime = self.endDate.timeIntervalSinceReferenceDate; + + + NSTimeInterval theirStartDateTime = otherEvent.startDate.timeIntervalSinceReferenceDate; + NSTimeInterval theirEndDateTime = otherEvent.endDate.timeIntervalSinceReferenceDate; + + + return (myStartDateTime <= theirEndDateTime) && (myEndDateTime >= theirStartDateTime); +} + +- (NSInteger)column { + + return [self.intersectingEvents indexOfObject:self]; + +} + @end From f88dadaadae29e6f6245675c06df2e3abaf85e48 Mon Sep 17 00:00:00 2001 From: Jon Manning Date: Thu, 23 Aug 2012 15:31:19 +1000 Subject: [PATCH 04/26] Rename GCCalendarView to GCCalendarViewController. --- Calendar.xcodeproj/project.pbxproj | 12 ++++++------ Classes/CalendarAppDelegate.m | 4 ++-- GCCalendar/GCCalendar.h | 2 +- GCCalendar/GCCalendarDayView.h | 2 +- GCCalendar/GCCalendarDayView.m | 4 ++-- GCCalendar/GCCalendarPortraitView.h | 4 ++-- GCCalendar/GCCalendarProtocols.h | 6 +++--- .../{GCCalendarView.h => GCCalendarViewController.h} | 2 +- .../{GCCalendarView.m => GCCalendarViewController.m} | 4 ++-- 9 files changed, 20 insertions(+), 20 deletions(-) rename GCCalendar/{GCCalendarView.h => GCCalendarViewController.h} (89%) rename GCCalendar/{GCCalendarView.m => GCCalendarViewController.m} (70%) diff --git a/Calendar.xcodeproj/project.pbxproj b/Calendar.xcodeproj/project.pbxproj index 5dd0f26..0e56427 100755 --- a/Calendar.xcodeproj/project.pbxproj +++ b/Calendar.xcodeproj/project.pbxproj @@ -27,7 +27,7 @@ 3B96AA7F1139BC99003FF405 /* GCCalendarEvent.m in Sources */ = {isa = PBXBuildFile; fileRef = 3B96AA661139BC99003FF405 /* GCCalendarEvent.m */; }; 3B96AA801139BC99003FF405 /* GCCalendarPortraitView.m in Sources */ = {isa = PBXBuildFile; fileRef = 3B96AA681139BC99003FF405 /* GCCalendarPortraitView.m */; }; 3B96AA811139BC99003FF405 /* GCCalendarTile.m in Sources */ = {isa = PBXBuildFile; fileRef = 3B96AA6B1139BC99003FF405 /* GCCalendarTile.m */; }; - 3B96AA821139BC99003FF405 /* GCCalendarView.m in Sources */ = {isa = PBXBuildFile; fileRef = 3B96AA6D1139BC99003FF405 /* GCCalendarView.m */; }; + 3B96AA821139BC99003FF405 /* GCCalendarViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 3B96AA6D1139BC99003FF405 /* GCCalendarViewController.m */; }; 3B96AA831139BC99003FF405 /* GCDatePickerControl.m in Sources */ = {isa = PBXBuildFile; fileRef = 3B96AA6F1139BC99003FF405 /* GCDatePickerControl.m */; }; 3B96AA841139BC99003FF405 /* GCDatePickerControlBackground.png in Resources */ = {isa = PBXBuildFile; fileRef = 3B96AA701139BC99003FF405 /* GCDatePickerControlBackground.png */; }; 3B96AA851139BC99003FF405 /* GCDatePickerControlLeft.png in Resources */ = {isa = PBXBuildFile; fileRef = 3B96AA711139BC99003FF405 /* GCDatePickerControlLeft.png */; }; @@ -64,8 +64,8 @@ 3B96AA691139BC99003FF405 /* GCCalendarProtocols.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GCCalendarProtocols.h; sourceTree = ""; }; 3B96AA6A1139BC99003FF405 /* GCCalendarTile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GCCalendarTile.h; sourceTree = ""; }; 3B96AA6B1139BC99003FF405 /* GCCalendarTile.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GCCalendarTile.m; sourceTree = ""; }; - 3B96AA6C1139BC99003FF405 /* GCCalendarView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GCCalendarView.h; sourceTree = ""; }; - 3B96AA6D1139BC99003FF405 /* GCCalendarView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GCCalendarView.m; sourceTree = ""; }; + 3B96AA6C1139BC99003FF405 /* GCCalendarViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GCCalendarViewController.h; sourceTree = ""; }; + 3B96AA6D1139BC99003FF405 /* GCCalendarViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GCCalendarViewController.m; sourceTree = ""; }; 3B96AA6E1139BC99003FF405 /* GCDatePickerControl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GCDatePickerControl.h; sourceTree = ""; }; 3B96AA6F1139BC99003FF405 /* GCDatePickerControl.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GCDatePickerControl.m; sourceTree = ""; }; 3B96AA701139BC99003FF405 /* GCDatePickerControlBackground.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = GCDatePickerControlBackground.png; sourceTree = ""; }; @@ -170,8 +170,8 @@ 3B96AA691139BC99003FF405 /* GCCalendarProtocols.h */, 3B96AA6A1139BC99003FF405 /* GCCalendarTile.h */, 3B96AA6B1139BC99003FF405 /* GCCalendarTile.m */, - 3B96AA6C1139BC99003FF405 /* GCCalendarView.h */, - 3B96AA6D1139BC99003FF405 /* GCCalendarView.m */, + 3B96AA6C1139BC99003FF405 /* GCCalendarViewController.h */, + 3B96AA6D1139BC99003FF405 /* GCCalendarViewController.m */, 3B96AA6E1139BC99003FF405 /* GCDatePickerControl.h */, 3B96AA6F1139BC99003FF405 /* GCDatePickerControl.m */, 3B96AA701139BC99003FF405 /* GCDatePickerControlBackground.png */, @@ -257,7 +257,7 @@ 3B96AA7F1139BC99003FF405 /* GCCalendarEvent.m in Sources */, 3B96AA801139BC99003FF405 /* GCCalendarPortraitView.m in Sources */, 3B96AA811139BC99003FF405 /* GCCalendarTile.m in Sources */, - 3B96AA821139BC99003FF405 /* GCCalendarView.m in Sources */, + 3B96AA821139BC99003FF405 /* GCCalendarViewController.m in Sources */, 3B96AA831139BC99003FF405 /* GCDatePickerControl.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/Classes/CalendarAppDelegate.m b/Classes/CalendarAppDelegate.m index e580dcc..ab150f3 100644 --- a/Classes/CalendarAppDelegate.m +++ b/Classes/CalendarAppDelegate.m @@ -110,10 +110,10 @@ - (NSArray *)calendarEventsForDate:(NSDate *)date { } #pragma mark GCCalendarDelegate -- (void)calendarTileTouchedInView:(GCCalendarView *)view withEvent:(GCCalendarEvent *)event { +- (void)calendarTileTouchedInView:(GCCalendarViewController *)view withEvent:(GCCalendarEvent *)event { NSLog(@"Touch event %@", event.eventName); } -- (void)calendarViewAddButtonPressed:(GCCalendarView *)view { +- (void)calendarViewAddButtonPressed:(GCCalendarViewController *)view { NSLog(@"%s", __PRETTY_FUNCTION__); } diff --git a/GCCalendar/GCCalendar.h b/GCCalendar/GCCalendar.h index 7966955..c35dd0a 100644 --- a/GCCalendar/GCCalendar.h +++ b/GCCalendar/GCCalendar.h @@ -10,7 +10,7 @@ #import -#import "GCCalendarView.h" +#import "GCCalendarViewController.h" #import "GCCalendarEvent.h" #import "GCCalendarProtocols.h" #import "GCCalendarPortraitView.h" diff --git a/GCCalendar/GCCalendarDayView.h b/GCCalendar/GCCalendarDayView.h index d1bbe9c..55db030 100644 --- a/GCCalendar/GCCalendarDayView.h +++ b/GCCalendar/GCCalendarDayView.h @@ -41,7 +41,7 @@ */ @property (nonatomic) CGPoint contentOffset; -- (id)initWithCalendarView:(GCCalendarView *)view; +- (id)initWithCalendarView:(GCCalendarViewController *)view; - (void)reloadData; @end diff --git a/GCCalendar/GCCalendarDayView.m b/GCCalendar/GCCalendarDayView.m index 4341247..7a540bc 100644 --- a/GCCalendar/GCCalendarDayView.m +++ b/GCCalendar/GCCalendarDayView.m @@ -10,7 +10,7 @@ #import "GCCalendarDayView.h" #import "GCCalendarTile.h" -#import "GCCalendarView.h" +#import "GCCalendarViewController.h" #import "GCCalendarEvent.h" #import "GCCalendar.h" @@ -292,7 +292,7 @@ + (void)initialize { @"1", @"2", @"3", @"4", @"5", @"6", @"7", @"8", @"9", @"10", @"11", @"12"]; } } -- (id)initWithCalendarView:(GCCalendarView *)view { +- (id)initWithCalendarView:(GCCalendarViewController *)view { if (self = [super init]) { dataSource = view.dataSource; } diff --git a/GCCalendar/GCCalendarPortraitView.h b/GCCalendar/GCCalendarPortraitView.h index 1af3a18..9564fbb 100644 --- a/GCCalendar/GCCalendarPortraitView.h +++ b/GCCalendar/GCCalendarPortraitView.h @@ -10,7 +10,7 @@ #import -#import "GCCalendarView.h" +#import "GCCalendarViewController.h" @class GCDatePickerControl; @class GCCalendarDayView; @@ -27,7 +27,7 @@ push a detailed view controller onto the stack with more information about the event (currently unimplemnted) */ -@interface GCCalendarPortraitView : GCCalendarView { +@interface GCCalendarPortraitView : GCCalendarViewController { // date the view will display NSDate *date; diff --git a/GCCalendar/GCCalendarProtocols.h b/GCCalendar/GCCalendarProtocols.h index 1d60618..1ebf2dc 100644 --- a/GCCalendar/GCCalendarProtocols.h +++ b/GCCalendar/GCCalendarProtocols.h @@ -15,8 +15,8 @@ @end @class GCCalendarEvent; -@class GCCalendarView; +@class GCCalendarViewController; @protocol GCCalendarDelegate -- (void)calendarTileTouchedInView:(GCCalendarView *)view withEvent:(GCCalendarEvent *)event; -- (void)calendarViewAddButtonPressed:(GCCalendarView *)view; +- (void)calendarTileTouchedInView:(GCCalendarViewController *)view withEvent:(GCCalendarEvent *)event; +- (void)calendarViewAddButtonPressed:(GCCalendarViewController *)view; @end \ No newline at end of file diff --git a/GCCalendar/GCCalendarView.h b/GCCalendar/GCCalendarViewController.h similarity index 89% rename from GCCalendar/GCCalendarView.h rename to GCCalendar/GCCalendarViewController.h index 1fbe01d..6b423f9 100644 --- a/GCCalendar/GCCalendarView.h +++ b/GCCalendar/GCCalendarViewController.h @@ -10,7 +10,7 @@ #import "GCCalendarProtocols.h" -@interface GCCalendarView : UIViewController { +@interface GCCalendarViewController : UIViewController { // data source id __unsafe_unretained dataSource; diff --git a/GCCalendar/GCCalendarView.m b/GCCalendar/GCCalendarViewController.m similarity index 70% rename from GCCalendar/GCCalendarView.m rename to GCCalendar/GCCalendarViewController.m index 53886de..57bb66f 100644 --- a/GCCalendar/GCCalendarView.m +++ b/GCCalendar/GCCalendarViewController.m @@ -6,9 +6,9 @@ // Copyright 2010 GUI Cocoa Software. All rights reserved. // -#import "GCCalendarView.h" +#import "GCCalendarViewController.h" -@implementation GCCalendarView +@implementation GCCalendarViewController @synthesize delegate, dataSource; From 5b5f677843a6471ee09ff9277c38e48a78f90e97 Mon Sep 17 00:00:00 2001 From: Jon Manning Date: Thu, 23 Aug 2012 15:33:25 +1000 Subject: [PATCH 05/26] Rename GCCalendarPortraitView to GCCalendarPortraitViewController. --- Calendar.xcodeproj/project.pbxproj | 12 ++++++------ Classes/CalendarAppDelegate.m | 2 +- GCCalendar/GCCalendar.h | 2 +- ...raitView.h => GCCalendarPortraitViewController.h} | 2 +- ...raitView.m => GCCalendarPortraitViewController.m} | 6 +++--- 5 files changed, 12 insertions(+), 12 deletions(-) rename GCCalendar/{GCCalendarPortraitView.h => GCCalendarPortraitViewController.h} (94%) rename GCCalendar/{GCCalendarPortraitView.m => GCCalendarPortraitViewController.m} (97%) diff --git a/Calendar.xcodeproj/project.pbxproj b/Calendar.xcodeproj/project.pbxproj index 0e56427..fa762a3 100755 --- a/Calendar.xcodeproj/project.pbxproj +++ b/Calendar.xcodeproj/project.pbxproj @@ -25,7 +25,7 @@ 3B96AA7D1139BC99003FF405 /* GCCalendar.m in Sources */ = {isa = PBXBuildFile; fileRef = 3B96AA621139BC99003FF405 /* GCCalendar.m */; }; 3B96AA7E1139BC99003FF405 /* GCCalendarDayView.m in Sources */ = {isa = PBXBuildFile; fileRef = 3B96AA641139BC99003FF405 /* GCCalendarDayView.m */; }; 3B96AA7F1139BC99003FF405 /* GCCalendarEvent.m in Sources */ = {isa = PBXBuildFile; fileRef = 3B96AA661139BC99003FF405 /* GCCalendarEvent.m */; }; - 3B96AA801139BC99003FF405 /* GCCalendarPortraitView.m in Sources */ = {isa = PBXBuildFile; fileRef = 3B96AA681139BC99003FF405 /* GCCalendarPortraitView.m */; }; + 3B96AA801139BC99003FF405 /* GCCalendarPortraitViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 3B96AA681139BC99003FF405 /* GCCalendarPortraitViewController.m */; }; 3B96AA811139BC99003FF405 /* GCCalendarTile.m in Sources */ = {isa = PBXBuildFile; fileRef = 3B96AA6B1139BC99003FF405 /* GCCalendarTile.m */; }; 3B96AA821139BC99003FF405 /* GCCalendarViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 3B96AA6D1139BC99003FF405 /* GCCalendarViewController.m */; }; 3B96AA831139BC99003FF405 /* GCDatePickerControl.m in Sources */ = {isa = PBXBuildFile; fileRef = 3B96AA6F1139BC99003FF405 /* GCDatePickerControl.m */; }; @@ -59,8 +59,8 @@ 3B96AA641139BC99003FF405 /* GCCalendarDayView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GCCalendarDayView.m; sourceTree = ""; }; 3B96AA651139BC99003FF405 /* GCCalendarEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GCCalendarEvent.h; sourceTree = ""; }; 3B96AA661139BC99003FF405 /* GCCalendarEvent.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GCCalendarEvent.m; sourceTree = ""; }; - 3B96AA671139BC99003FF405 /* GCCalendarPortraitView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GCCalendarPortraitView.h; sourceTree = ""; }; - 3B96AA681139BC99003FF405 /* GCCalendarPortraitView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GCCalendarPortraitView.m; sourceTree = ""; }; + 3B96AA671139BC99003FF405 /* GCCalendarPortraitViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GCCalendarPortraitViewController.h; sourceTree = ""; }; + 3B96AA681139BC99003FF405 /* GCCalendarPortraitViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GCCalendarPortraitViewController.m; sourceTree = ""; }; 3B96AA691139BC99003FF405 /* GCCalendarProtocols.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GCCalendarProtocols.h; sourceTree = ""; }; 3B96AA6A1139BC99003FF405 /* GCCalendarTile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GCCalendarTile.h; sourceTree = ""; }; 3B96AA6B1139BC99003FF405 /* GCCalendarTile.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GCCalendarTile.m; sourceTree = ""; }; @@ -165,8 +165,8 @@ 3B96AA641139BC99003FF405 /* GCCalendarDayView.m */, 3B96AA651139BC99003FF405 /* GCCalendarEvent.h */, 3B96AA661139BC99003FF405 /* GCCalendarEvent.m */, - 3B96AA671139BC99003FF405 /* GCCalendarPortraitView.h */, - 3B96AA681139BC99003FF405 /* GCCalendarPortraitView.m */, + 3B96AA671139BC99003FF405 /* GCCalendarPortraitViewController.h */, + 3B96AA681139BC99003FF405 /* GCCalendarPortraitViewController.m */, 3B96AA691139BC99003FF405 /* GCCalendarProtocols.h */, 3B96AA6A1139BC99003FF405 /* GCCalendarTile.h */, 3B96AA6B1139BC99003FF405 /* GCCalendarTile.m */, @@ -255,7 +255,7 @@ 3B96AA7D1139BC99003FF405 /* GCCalendar.m in Sources */, 3B96AA7E1139BC99003FF405 /* GCCalendarDayView.m in Sources */, 3B96AA7F1139BC99003FF405 /* GCCalendarEvent.m in Sources */, - 3B96AA801139BC99003FF405 /* GCCalendarPortraitView.m in Sources */, + 3B96AA801139BC99003FF405 /* GCCalendarPortraitViewController.m in Sources */, 3B96AA811139BC99003FF405 /* GCCalendarTile.m in Sources */, 3B96AA821139BC99003FF405 /* GCCalendarViewController.m in Sources */, 3B96AA831139BC99003FF405 /* GCDatePickerControl.m in Sources */, diff --git a/Classes/CalendarAppDelegate.m b/Classes/CalendarAppDelegate.m index ab150f3..6b382a7 100644 --- a/Classes/CalendarAppDelegate.m +++ b/Classes/CalendarAppDelegate.m @@ -12,7 +12,7 @@ @implementation CalendarAppDelegate - (void)applicationDidFinishLaunching:(UIApplication *)application { // create calendar view - GCCalendarPortraitView *calendar = [[GCCalendarPortraitView alloc] init]; + GCCalendarPortraitViewController *calendar = [[GCCalendarPortraitViewController alloc] init]; calendar.dataSource = self; calendar.delegate = self; calendar.hasAddButton = YES; diff --git a/GCCalendar/GCCalendar.h b/GCCalendar/GCCalendar.h index c35dd0a..15cbead 100644 --- a/GCCalendar/GCCalendar.h +++ b/GCCalendar/GCCalendar.h @@ -13,7 +13,7 @@ #import "GCCalendarViewController.h" #import "GCCalendarEvent.h" #import "GCCalendarProtocols.h" -#import "GCCalendarPortraitView.h" +#import "GCCalendarPortraitViewController.h" // calendar notificaions static NSString * const GCCalendarShouldReloadNotification = @"GCCalendarShouldReload"; diff --git a/GCCalendar/GCCalendarPortraitView.h b/GCCalendar/GCCalendarPortraitViewController.h similarity index 94% rename from GCCalendar/GCCalendarPortraitView.h rename to GCCalendar/GCCalendarPortraitViewController.h index 9564fbb..74b11b7 100644 --- a/GCCalendar/GCCalendarPortraitView.h +++ b/GCCalendar/GCCalendarPortraitViewController.h @@ -27,7 +27,7 @@ push a detailed view controller onto the stack with more information about the event (currently unimplemnted) */ -@interface GCCalendarPortraitView : GCCalendarViewController { +@interface GCCalendarPortraitViewController : GCCalendarViewController { // date the view will display NSDate *date; diff --git a/GCCalendar/GCCalendarPortraitView.m b/GCCalendar/GCCalendarPortraitViewController.m similarity index 97% rename from GCCalendar/GCCalendarPortraitView.m rename to GCCalendar/GCCalendarPortraitViewController.m index ce6257e..90708b9 100644 --- a/GCCalendar/GCCalendarPortraitView.m +++ b/GCCalendar/GCCalendarPortraitViewController.m @@ -8,7 +8,7 @@ // Copyright GUI Cocoa Software 2010. All rights reserved. // -#import "GCCalendarPortraitView.h" +#import "GCCalendarPortraitViewController.h" #import "GCCalendarDayView.h" #import "GCCalendarTile.h" #import "GCDatePickerControl.h" @@ -16,14 +16,14 @@ #define kAnimationDuration 0.3f -@interface GCCalendarPortraitView () +@interface GCCalendarPortraitViewController () @property (nonatomic, strong) NSDate *date; @property (nonatomic, strong) GCCalendarDayView *dayView; - (void)reloadDayAnimated:(BOOL)animated context:(void *)context; @end -@implementation GCCalendarPortraitView +@implementation GCCalendarPortraitViewController @synthesize date, dayView, hasAddButton; From c3deb635330bb3338096feed2cb984fe49c69b2f Mon Sep 17 00:00:00 2001 From: Jon Manning Date: Thu, 23 Aug 2012 15:33:37 +1000 Subject: [PATCH 06/26] Update .gitignore. --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index edc082c..15335e7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ # Xcode +*.DS_Store build/* *.pbxuser !default.pbxuser From e7324cd248efd980fccf05207a4934e211e80426 Mon Sep 17 00:00:00 2001 From: Jon Manning Date: Thu, 23 Aug 2012 15:34:46 +1000 Subject: [PATCH 07/26] Rename GCCalendarTile to GCCalendarTileView --- Calendar.xcodeproj/project.pbxproj | 12 ++++++------ GCCalendar/GCCalendarDayView.m | 10 +++++----- .../{GCCalendarTile.h => GCCalendarTileView.h} | 2 +- .../{GCCalendarTile.m => GCCalendarTileView.m} | 4 ++-- 4 files changed, 14 insertions(+), 14 deletions(-) rename GCCalendar/{GCCalendarTile.h => GCCalendarTileView.h} (94%) rename GCCalendar/{GCCalendarTile.m => GCCalendarTileView.m} (97%) diff --git a/Calendar.xcodeproj/project.pbxproj b/Calendar.xcodeproj/project.pbxproj index fa762a3..09c065f 100755 --- a/Calendar.xcodeproj/project.pbxproj +++ b/Calendar.xcodeproj/project.pbxproj @@ -26,7 +26,7 @@ 3B96AA7E1139BC99003FF405 /* GCCalendarDayView.m in Sources */ = {isa = PBXBuildFile; fileRef = 3B96AA641139BC99003FF405 /* GCCalendarDayView.m */; }; 3B96AA7F1139BC99003FF405 /* GCCalendarEvent.m in Sources */ = {isa = PBXBuildFile; fileRef = 3B96AA661139BC99003FF405 /* GCCalendarEvent.m */; }; 3B96AA801139BC99003FF405 /* GCCalendarPortraitViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 3B96AA681139BC99003FF405 /* GCCalendarPortraitViewController.m */; }; - 3B96AA811139BC99003FF405 /* GCCalendarTile.m in Sources */ = {isa = PBXBuildFile; fileRef = 3B96AA6B1139BC99003FF405 /* GCCalendarTile.m */; }; + 3B96AA811139BC99003FF405 /* GCCalendarTileView.m in Sources */ = {isa = PBXBuildFile; fileRef = 3B96AA6B1139BC99003FF405 /* GCCalendarTileView.m */; }; 3B96AA821139BC99003FF405 /* GCCalendarViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 3B96AA6D1139BC99003FF405 /* GCCalendarViewController.m */; }; 3B96AA831139BC99003FF405 /* GCDatePickerControl.m in Sources */ = {isa = PBXBuildFile; fileRef = 3B96AA6F1139BC99003FF405 /* GCDatePickerControl.m */; }; 3B96AA841139BC99003FF405 /* GCDatePickerControlBackground.png in Resources */ = {isa = PBXBuildFile; fileRef = 3B96AA701139BC99003FF405 /* GCDatePickerControlBackground.png */; }; @@ -62,8 +62,8 @@ 3B96AA671139BC99003FF405 /* GCCalendarPortraitViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GCCalendarPortraitViewController.h; sourceTree = ""; }; 3B96AA681139BC99003FF405 /* GCCalendarPortraitViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GCCalendarPortraitViewController.m; sourceTree = ""; }; 3B96AA691139BC99003FF405 /* GCCalendarProtocols.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GCCalendarProtocols.h; sourceTree = ""; }; - 3B96AA6A1139BC99003FF405 /* GCCalendarTile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GCCalendarTile.h; sourceTree = ""; }; - 3B96AA6B1139BC99003FF405 /* GCCalendarTile.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GCCalendarTile.m; sourceTree = ""; }; + 3B96AA6A1139BC99003FF405 /* GCCalendarTileView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GCCalendarTileView.h; sourceTree = ""; }; + 3B96AA6B1139BC99003FF405 /* GCCalendarTileView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GCCalendarTileView.m; sourceTree = ""; }; 3B96AA6C1139BC99003FF405 /* GCCalendarViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GCCalendarViewController.h; sourceTree = ""; }; 3B96AA6D1139BC99003FF405 /* GCCalendarViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GCCalendarViewController.m; sourceTree = ""; }; 3B96AA6E1139BC99003FF405 /* GCDatePickerControl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GCDatePickerControl.h; sourceTree = ""; }; @@ -168,8 +168,8 @@ 3B96AA671139BC99003FF405 /* GCCalendarPortraitViewController.h */, 3B96AA681139BC99003FF405 /* GCCalendarPortraitViewController.m */, 3B96AA691139BC99003FF405 /* GCCalendarProtocols.h */, - 3B96AA6A1139BC99003FF405 /* GCCalendarTile.h */, - 3B96AA6B1139BC99003FF405 /* GCCalendarTile.m */, + 3B96AA6A1139BC99003FF405 /* GCCalendarTileView.h */, + 3B96AA6B1139BC99003FF405 /* GCCalendarTileView.m */, 3B96AA6C1139BC99003FF405 /* GCCalendarViewController.h */, 3B96AA6D1139BC99003FF405 /* GCCalendarViewController.m */, 3B96AA6E1139BC99003FF405 /* GCDatePickerControl.h */, @@ -256,7 +256,7 @@ 3B96AA7E1139BC99003FF405 /* GCCalendarDayView.m in Sources */, 3B96AA7F1139BC99003FF405 /* GCCalendarEvent.m in Sources */, 3B96AA801139BC99003FF405 /* GCCalendarPortraitViewController.m in Sources */, - 3B96AA811139BC99003FF405 /* GCCalendarTile.m in Sources */, + 3B96AA811139BC99003FF405 /* GCCalendarTileView.m in Sources */, 3B96AA821139BC99003FF405 /* GCCalendarViewController.m in Sources */, 3B96AA831139BC99003FF405 /* GCDatePickerControl.m in Sources */, ); diff --git a/GCCalendar/GCCalendarDayView.m b/GCCalendar/GCCalendarDayView.m index 7a540bc..d28a0f6 100644 --- a/GCCalendar/GCCalendarDayView.m +++ b/GCCalendar/GCCalendarDayView.m @@ -9,7 +9,7 @@ // #import "GCCalendarDayView.h" -#import "GCCalendarTile.h" +#import "GCCalendarTileView.h" #import "GCCalendarViewController.h" #import "GCCalendarEvent.h" #import "GCCalendar.h" @@ -41,7 +41,7 @@ - (id)initWithEvents:(NSArray *)a { NSInteger eventCount = 0; for (GCCalendarEvent *e in events) { if (eventCount < 5) { - GCCalendarTile *tile = [[GCCalendarTile alloc] init]; + GCCalendarTileView *tile = [[GCCalendarTileView alloc] init]; tile.event = e; [self addSubview:tile]; @@ -75,7 +75,7 @@ - (void)layoutSubviews { for (UIView *view in self.subviews) { // get calendar tile and associated event - GCCalendarTile *tile = (GCCalendarTile *)view; + GCCalendarTileView *tile = (GCCalendarTileView *)view; tile.frame = CGRectMake(kTileLeftSide, start_y, @@ -126,7 +126,7 @@ - (id)initWithEvents:(NSArray *)a { events = [a filteredArrayUsingPredicate:pred]; for (GCCalendarEvent *e in events) { - GCCalendarTile *tile = [[GCCalendarTile alloc] init]; + GCCalendarTileView *tile = [[GCCalendarTileView alloc] init]; tile.event = e; [self addSubview:tile]; } @@ -144,7 +144,7 @@ - (void)dealloc { - (void)layoutSubviews { for (UIView *view in self.subviews) { // get calendar tile and associated event - GCCalendarTile *tile = (GCCalendarTile *)view; + GCCalendarTileView *tile = (GCCalendarTileView *)view; NSDateComponents *components; components = [[NSCalendar currentCalendar] components:(NSHourCalendarUnit | diff --git a/GCCalendar/GCCalendarTile.h b/GCCalendar/GCCalendarTileView.h similarity index 94% rename from GCCalendar/GCCalendarTile.h rename to GCCalendar/GCCalendarTileView.h index 00b8d9f..edb029b 100644 --- a/GCCalendar/GCCalendarTile.h +++ b/GCCalendar/GCCalendarTileView.h @@ -17,7 +17,7 @@ Each tile posts a notification whenever a touch ends inside its frame. */ -@interface GCCalendarTile : UIView { +@interface GCCalendarTileView : UIView { // event title label UILabel *titleLabel; // event description label diff --git a/GCCalendar/GCCalendarTile.m b/GCCalendar/GCCalendarTileView.m similarity index 97% rename from GCCalendar/GCCalendarTile.m rename to GCCalendar/GCCalendarTileView.m index c676bb1..79b5bb2 100644 --- a/GCCalendar/GCCalendarTile.m +++ b/GCCalendar/GCCalendarTileView.m @@ -8,11 +8,11 @@ // Copyright GUI Cocoa Software 2010. All rights reserved. // -#import "GCCalendarTile.h" +#import "GCCalendarTileView.h" #import "GCCalendarEvent.h" #import "GCCalendar.h" -@implementation GCCalendarTile +@implementation GCCalendarTileView @synthesize event; From 888503cb1037e7480ad20ef05cd40cb09a82213f Mon Sep 17 00:00:00 2001 From: Jon Manning Date: Thu, 23 Aug 2012 15:38:00 +1000 Subject: [PATCH 08/26] Fix a compile error --- GCCalendar/GCCalendarPortraitViewController.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/GCCalendar/GCCalendarPortraitViewController.m b/GCCalendar/GCCalendarPortraitViewController.m index 90708b9..28f1f2e 100644 --- a/GCCalendar/GCCalendarPortraitViewController.m +++ b/GCCalendar/GCCalendarPortraitViewController.m @@ -10,7 +10,7 @@ #import "GCCalendarPortraitViewController.h" #import "GCCalendarDayView.h" -#import "GCCalendarTile.h" +#import "GCCalendarTileView.h" #import "GCDatePickerControl.h" #import "GCCalendar.h" @@ -61,7 +61,7 @@ - (void)calendarShouldReload:(NSNotification *)notif { } - (void)calendarTileTouch:(NSNotification *)notif { if (delegate != nil) { - GCCalendarTile *tile = [notif object]; + GCCalendarTileView *tile = [notif object]; [delegate calendarTileTouchedInView:self withEvent:[tile event]]; } } From 23d6417f3f6225c6452cb40e9e699d0a8f7a5b14 Mon Sep 17 00:00:00 2001 From: Jon Manning Date: Thu, 23 Aug 2012 15:54:40 +1000 Subject: [PATCH 09/26] Update view controller to work better in a nib-based workflow. --- GCCalendar/GCCalendarPortraitViewController.m | 64 +++++++++---------- 1 file changed, 31 insertions(+), 33 deletions(-) diff --git a/GCCalendar/GCCalendarPortraitViewController.m b/GCCalendar/GCCalendarPortraitViewController.m index 28f1f2e..2138914 100644 --- a/GCCalendar/GCCalendarPortraitViewController.m +++ b/GCCalendar/GCCalendarPortraitViewController.m @@ -27,34 +27,6 @@ @implementation GCCalendarPortraitViewController @synthesize date, dayView, hasAddButton; -#pragma mark create and destroy view -- (id)init { - if(self = [super init]) { - self.title = [[NSBundle mainBundle] localizedStringForKey:@"CALENDAR" value:@"" table:@"GCCalendar"]; - self.tabBarItem.image = [UIImage imageNamed:@"Calendar.png"]; - - viewDirty = YES; - viewVisible = NO; - - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(calendarTileTouch:) - name:__GCCalendarTileTouchNotification - object:nil]; - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(calendarShouldReload:) - name:GCCalendarShouldReloadNotification - object:nil]; - } - - return self; -} -- (void)dealloc { - [[NSNotificationCenter defaultCenter] removeObserver:self]; - - - -} - #pragma mark calendar actions - (void)calendarShouldReload:(NSNotification *)notif { viewDirty = YES; @@ -109,10 +81,18 @@ - (void)setHasAddButton:(BOOL)b { } #pragma mark view notifications -- (void)loadView { - [super loadView]; - - self.date = [[NSUserDefaults standardUserDefaults] objectForKey:@"GCCalendarDate"]; + +- (void)viewDidLoad { + + self.title = [[NSBundle mainBundle] localizedStringForKey:@"CALENDAR" value:@"" table:@"GCCalendar"]; + self.tabBarItem.image = [UIImage imageNamed:@"Calendar.png"]; + + viewDirty = YES; + viewVisible = NO; + + + + self.date = [[NSUserDefaults standardUserDefaults] objectForKey:@"GCCalendarDate"]; if (date == nil) { self.date = [NSDate date]; } @@ -137,12 +117,27 @@ - (void)loadView { // setup today button UIBarButtonItem *button = [[UIBarButtonItem alloc] initWithTitle:[[NSBundle mainBundle] localizedStringForKey:@"TODAY" value:@"" table:@"GCCalendar"] style:UIBarButtonItemStylePlain - target:self + target:self action:@selector(today)]; self.navigationItem.leftBarButtonItem = button; } + +- (void)loadView { + [super loadView]; + + +} - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; + + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(calendarTileTouch:) + name:__GCCalendarTileTouchNotification + object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(calendarShouldReload:) + name:GCCalendarShouldReloadNotification + object:nil]; if (viewDirty) { [self reloadDayAnimated:NO context:NULL]; @@ -155,6 +150,9 @@ - (void)viewDidDisappear:(BOOL)animated { [super viewDidDisappear:animated]; viewVisible = NO; + + [[NSNotificationCenter defaultCenter] removeObserver:self]; + } #pragma mark view animation functions From ef8ad8ffd89d6385af446924cb4a4be8a61ff514 Mon Sep 17 00:00:00 2001 From: Jon Manning Date: Thu, 23 Aug 2012 16:31:08 +1000 Subject: [PATCH 10/26] Make GCCalendarPortraitViewController able to reload its data --- GCCalendar/GCCalendarEvent.m | 4 ---- GCCalendar/GCCalendarPortraitViewController.h | 2 ++ GCCalendar/GCCalendarPortraitViewController.m | 4 ++++ 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/GCCalendar/GCCalendarEvent.m b/GCCalendar/GCCalendarEvent.m index 4125c59..6ebbf87 100644 --- a/GCCalendar/GCCalendarEvent.m +++ b/GCCalendar/GCCalendarEvent.m @@ -25,18 +25,14 @@ - (BOOL) intersectsEvent:(GCCalendarEvent*)otherEvent { NSTimeInterval myStartDateTime = self.startDate.timeIntervalSinceReferenceDate; NSTimeInterval myEndDateTime = self.endDate.timeIntervalSinceReferenceDate; - NSTimeInterval theirStartDateTime = otherEvent.startDate.timeIntervalSinceReferenceDate; NSTimeInterval theirEndDateTime = otherEvent.endDate.timeIntervalSinceReferenceDate; - return (myStartDateTime <= theirEndDateTime) && (myEndDateTime >= theirStartDateTime); } - (NSInteger)column { - return [self.intersectingEvents indexOfObject:self]; - } diff --git a/GCCalendar/GCCalendarPortraitViewController.h b/GCCalendar/GCCalendarPortraitViewController.h index 74b11b7..6e23070 100644 --- a/GCCalendar/GCCalendarPortraitViewController.h +++ b/GCCalendar/GCCalendarPortraitViewController.h @@ -49,4 +49,6 @@ @property (nonatomic, assign) BOOL hasAddButton; +- (void) reloadData; + @end diff --git a/GCCalendar/GCCalendarPortraitViewController.m b/GCCalendar/GCCalendarPortraitViewController.m index 2138914..ab5b306 100644 --- a/GCCalendar/GCCalendarPortraitViewController.m +++ b/GCCalendar/GCCalendarPortraitViewController.m @@ -221,4 +221,8 @@ - (void)animationDidStop:(NSString *)animationID dayPicker.userInteractionEnabled = YES; } +- (void)reloadData { + [self reloadDayAnimated:NO context:NULL]; +} + @end From d9a69b9048a5759adecc7ee256ce090258a0f48e Mon Sep 17 00:00:00 2001 From: Jon Manning Date: Fri, 24 Aug 2012 21:33:03 +1000 Subject: [PATCH 11/26] Don't set the view controller's title. Leave that up to the host app. --- GCCalendar/GCCalendarPortraitViewController.m | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/GCCalendar/GCCalendarPortraitViewController.m b/GCCalendar/GCCalendarPortraitViewController.m index ab5b306..6380b46 100644 --- a/GCCalendar/GCCalendarPortraitViewController.m +++ b/GCCalendar/GCCalendarPortraitViewController.m @@ -83,15 +83,10 @@ - (void)setHasAddButton:(BOOL)b { #pragma mark view notifications - (void)viewDidLoad { - - self.title = [[NSBundle mainBundle] localizedStringForKey:@"CALENDAR" value:@"" table:@"GCCalendar"]; - self.tabBarItem.image = [UIImage imageNamed:@"Calendar.png"]; - + viewDirty = YES; viewVisible = NO; - - self.date = [[NSUserDefaults standardUserDefaults] objectForKey:@"GCCalendarDate"]; if (date == nil) { self.date = [NSDate date]; From 5b0d0e4c0e48efac4fc70cbbcfe3ca0f57bbee1c Mon Sep 17 00:00:00 2001 From: Jon Manning Date: Sun, 26 Aug 2012 14:56:13 +1000 Subject: [PATCH 12/26] Events can now display an image. --- GCCalendar/GCCalendarEvent.h | 3 +++ GCCalendar/GCCalendarTileView.h | 3 +++ GCCalendar/GCCalendarTileView.m | 28 +++++++++++++++++++++++----- 3 files changed, 29 insertions(+), 5 deletions(-) diff --git a/GCCalendar/GCCalendarEvent.h b/GCCalendar/GCCalendarEvent.h index aac3d34..6c85808 100644 --- a/GCCalendar/GCCalendarEvent.h +++ b/GCCalendar/GCCalendarEvent.h @@ -32,6 +32,9 @@ @property (nonatomic, strong) id userInfo; @property (nonatomic) BOOL allDayEvent; +// If set, this image will be displayed at the right of the title. +@property (nonatomic, strong) UIImage* image; + @property (nonatomic, copy) NSArray* intersectingEvents; @property (readonly) NSInteger column; diff --git a/GCCalendar/GCCalendarTileView.h b/GCCalendar/GCCalendarTileView.h index edb029b..3f920ae 100644 --- a/GCCalendar/GCCalendarTileView.h +++ b/GCCalendar/GCCalendarTileView.h @@ -25,6 +25,9 @@ // view containing stretchable image UIImageView *backgroundView; + + // view containing the event's badge image + UIImageView* badgeImageView; // event from which to draw tile GCCalendarEvent *event; diff --git a/GCCalendar/GCCalendarTileView.m b/GCCalendar/GCCalendarTileView.m index 79b5bb2..28d5208 100644 --- a/GCCalendar/GCCalendarTileView.m +++ b/GCCalendar/GCCalendarTileView.m @@ -12,6 +12,8 @@ #import "GCCalendarEvent.h" #import "GCCalendar.h" +#define TILE_SIDE_PADDING 6 + @implementation GCCalendarTileView @synthesize event; @@ -35,11 +37,14 @@ - (id)init { descriptionLabel.font = [UIFont systemFontOfSize:12.0f]; descriptionLabel.lineBreakMode = UILineBreakModeWordWrap; descriptionLabel.numberOfLines = 0; + + badgeImageView = [[UIImageView alloc] init]; backgroundView = [[UIImageView alloc] init]; backgroundView.alpha = 0.90f; [self addSubview:backgroundView]; + [self addSubview:badgeImageView]; [self addSubview:titleLabel]; [self addSubview:descriptionLabel]; } @@ -62,27 +67,40 @@ - (void)setEvent:(GCCalendarEvent *)e { // set title titleLabel.text = event.eventName; descriptionLabel.text = event.eventDescription; + + if (event.image) { + badgeImageView.image = event.image; + } [self setNeedsDisplay]; } - (void)layoutSubviews { CGRect myBounds = self.bounds; - + + backgroundView.frame = myBounds; + + [badgeImageView sizeToFit]; + badgeImageView.frame = CGRectMake(myBounds.size.width - badgeImageView.bounds.size.width - TILE_SIDE_PADDING, 3, badgeImageView.bounds.size.width, badgeImageView.bounds.size.height); + + NSInteger titleWidth = titleWidth = myBounds.size.width - TILE_SIDE_PADDING * 2; + if (event.image) + titleWidth -= (myBounds.size.width - badgeImageView.frame.origin.x); + CGSize stringSize = [titleLabel.text sizeWithFont:titleLabel.font]; - titleLabel.frame = CGRectMake(6, + titleLabel.frame = CGRectMake(TILE_SIDE_PADDING, 3, - myBounds.size.width - 12, + titleWidth, stringSize.height); if (event.allDayEvent) { descriptionLabel.frame = CGRectZero; } else { - descriptionLabel.frame = CGRectMake(6, + descriptionLabel.frame = CGRectMake(TILE_SIDE_PADDING, titleLabel.frame.size.height + 2, - myBounds.size.width - 12, + myBounds.size.width - TILE_SIDE_PADDING * 2, myBounds.size.height - 14 - titleLabel.frame.size.height); } } From 06e6bb74b1b7b789f918c09c3813c05e2ad87930 Mon Sep 17 00:00:00 2001 From: Jon Manning Date: Sun, 26 Aug 2012 15:01:42 +1000 Subject: [PATCH 13/26] Improve the spacing between the event image and title. --- GCCalendar/GCCalendarTileView.m | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/GCCalendar/GCCalendarTileView.m b/GCCalendar/GCCalendarTileView.m index 28d5208..d9fc5c1 100644 --- a/GCCalendar/GCCalendarTileView.m +++ b/GCCalendar/GCCalendarTileView.m @@ -83,11 +83,11 @@ - (void)layoutSubviews { [badgeImageView sizeToFit]; badgeImageView.frame = CGRectMake(myBounds.size.width - badgeImageView.bounds.size.width - TILE_SIDE_PADDING, 3, badgeImageView.bounds.size.width, badgeImageView.bounds.size.height); - NSInteger titleWidth = titleWidth = myBounds.size.width - TILE_SIDE_PADDING * 2; + NSInteger titleWidth = myBounds.size.width - TILE_SIDE_PADDING * 2; + if (event.image) - titleWidth -= (myBounds.size.width - badgeImageView.frame.origin.x); - - + titleWidth -= (badgeImageView.bounds.size.width + 3); + CGSize stringSize = [titleLabel.text sizeWithFont:titleLabel.font]; titleLabel.frame = CGRectMake(TILE_SIDE_PADDING, 3, From 1ea733fef5cc1befb8960aa78967320cd64e7a5f Mon Sep 17 00:00:00 2001 From: Jon Manning Date: Sun, 26 Aug 2012 17:47:34 +1000 Subject: [PATCH 14/26] Remove unnecessary logging --- GCCalendar/GCCalendarDayView.m | 2 -- 1 file changed, 2 deletions(-) diff --git a/GCCalendar/GCCalendarDayView.m b/GCCalendar/GCCalendarDayView.m index d28a0f6..a07ee91 100644 --- a/GCCalendar/GCCalendarDayView.m +++ b/GCCalendar/GCCalendarDayView.m @@ -167,8 +167,6 @@ - (void)layoutSubviews { endPos += (endMinute / 60.0) * (kHalfHourDiff * 2.0); endPos = floor(endPos); - NSLog(@"%@ has %i intersecting events", tile.event, tile.event.intersectingEvents.count); - NSInteger columnWidth = (self.bounds.size.width - kTileLeftSide - kTileRightSide) / tile.event.intersectingEvents.count; NSInteger columnNumber = tile.event.column; From 47d1a9b589634087d6f88d5967e3430bc972d0f3 Mon Sep 17 00:00:00 2001 From: Jon Manning Date: Mon, 27 Aug 2012 22:42:36 +1000 Subject: [PATCH 15/26] Make (most of) the calendar view themable through the use of delegate methods. --- GCCalendar/GCCalendarDayView.h | 6 ++ GCCalendar/GCCalendarDayView.m | 65 +++++++++++++++---- GCCalendar/GCCalendarPortraitViewController.m | 22 ++++++- GCCalendar/GCCalendarProtocols.h | 15 +++++ GCCalendar/GCCalendarTileView.m | 2 +- GCCalendar/GCDatePickerControl.h | 8 +++ GCCalendar/GCDatePickerControl.m | 25 ++++++- 7 files changed, 126 insertions(+), 17 deletions(-) diff --git a/GCCalendar/GCCalendarDayView.h b/GCCalendar/GCCalendarDayView.h index 55db030..92a8254 100644 --- a/GCCalendar/GCCalendarDayView.h +++ b/GCCalendar/GCCalendarDayView.h @@ -44,4 +44,10 @@ - (id)initWithCalendarView:(GCCalendarViewController *)view; - (void)reloadData; +@property (retain) UIColor* outsideHoursColor; +@property (retain) UIColor* officeHoursColor; +@property (retain) UIColor* hourMarkerColor; +@property (retain) UIColor* timeColor; +@property (retain) UIColor* AMPMColor; + @end diff --git a/GCCalendar/GCCalendarDayView.m b/GCCalendar/GCCalendarDayView.m index a07ee91..09dbac3 100644 --- a/GCCalendar/GCCalendarDayView.m +++ b/GCCalendar/GCCalendarDayView.m @@ -111,17 +111,21 @@ - (void)drawRect:(CGRect)rect { @interface GCCalendarTodayView : UIView { NSArray *events; + __weak GCCalendarDayView *_dayView; } -- (id)initWithEvents:(NSArray *)a; +- (id)initWithEvents:(NSArray *)a dayView:(GCCalendarDayView*)dayView; - (BOOL)hasEvents; + (CGFloat)yValueForTime:(CGFloat)time; @end @implementation GCCalendarTodayView -- (id)initWithEvents:(NSArray *)a { +- (id)initWithEvents:(NSArray *)a dayView:(GCCalendarDayView *)dayView { if (self = [super init]) { + + _dayView = dayView; + NSPredicate *pred = [NSPredicate predicateWithFormat:@"allDayEvent == NO"]; events = [a filteredArrayUsingPredicate:pred]; @@ -130,6 +134,8 @@ - (id)initWithEvents:(NSArray *)a { tile.event = e; [self addSubview:tile]; } + + self.backgroundColor = [UIColor clearColor]; } return self; @@ -179,8 +185,8 @@ - (void)layoutSubviews { - (void)drawRect:(CGRect)rect { // grab current graphics context CGContextRef g = UIGraphicsGetCurrentContext(); - - CGContextSetRGBFillColor(g, (242.0 / 255.0), (242.0 / 255.0), (242.0 / 255.0), 1.0); + + CGContextSetFillColorWithColor(g, _dayView.outsideHoursColor.CGColor); // fill morning hours light grey CGFloat morningHourMax = [GCCalendarTodayView yValueForTime:(CGFloat)8]; @@ -193,14 +199,16 @@ - (void)drawRect:(CGRect)rect { CGContextFillRect(g, eveningHours); // fill day hours white - CGContextSetRGBFillColor(g, 1.0, 1.0, 1.0, 1.0); + + CGContextSetFillColorWithColor(g, _dayView.officeHoursColor.CGColor); + CGRect dayHours = CGRectMake(0, morningHourMax - 1, self.frame.size.width, eveningHourMax - morningHourMax); CGContextFillRect(g, dayHours); // draw hour lines CGContextSetShouldAntialias(g, NO); const CGFloat solidPattern[2] = {1.0, 0.0}; - CGContextSetRGBStrokeColor(g, 0.0, 0.0, 0.0, .3); + CGContextSetStrokeColorWithColor(g, _dayView.hourMarkerColor.CGColor); CGContextSetLineDash(g, 0, solidPattern, 2); for (NSInteger i = 0; i < 25; i++) { CGFloat yVal = [GCCalendarTodayView yValueForTime:(CGFloat)i]; @@ -212,8 +220,10 @@ - (void)drawRect:(CGRect)rect { // draw half hour lines CGContextSetShouldAntialias(g, NO); const CGFloat dashPattern[2] = {1.0, 1.0}; - CGContextSetRGBStrokeColor(g, 0.0, 0.0, 0.0, .2); - CGContextSetLineDash(g, 0, dashPattern, 2); + + CGContextSetStrokeColorWithColor(g, _dayView.hourMarkerColor.CGColor); + + CGContextSetLineDash(g, 0, dashPattern, 2); for (NSInteger i = 0; i < 24; i++) { CGFloat time = (CGFloat)i + 0.5f; CGFloat yVal = [GCCalendarTodayView yValueForTime:time]; @@ -224,7 +234,7 @@ - (void)drawRect:(CGRect)rect { // draw hour numbers CGContextSetShouldAntialias(g, YES); - [[UIColor blackColor] set]; + [_dayView.timeColor set]; UIFont *numberFont = [UIFont boldSystemFontOfSize:14.0]; for (NSInteger i = 0; i < 25; i++) { CGFloat yVal = [GCCalendarTodayView yValueForTime:(CGFloat)i]; @@ -251,7 +261,7 @@ - (void)drawRect:(CGRect)rect { // draw am / pm text CGContextSetShouldAntialias(g, YES); - [[UIColor grayColor] set]; + [_dayView.AMPMColor set]; UIFont *textFont = [UIFont systemFontOfSize:12.0]; for (NSInteger i = 0; i < 25; i++) { NSString *text = nil; @@ -286,13 +296,24 @@ + (void)initialize { if(self == [GCCalendarDayView class]) { timeStrings = @[@"12", @"1", @"2", @"3", @"4", @"5", @"6", @"7", @"8", @"9", @"10", @"11", - [[NSBundle mainBundle] localizedStringForKey:@"NOON" value:@"" table:@"GCCalendar"], + @"Noon", @"1", @"2", @"3", @"4", @"5", @"6", @"7", @"8", @"9", @"10", @"11", @"12"]; } } - (id)initWithCalendarView:(GCCalendarViewController *)view { if (self = [super init]) { dataSource = view.dataSource; + + self.outsideHoursColor = [UIColor colorWithRed:(242.0 / 255.0) green:(242.0 / 255.0) blue:(242.0 / 255.0) alpha:1.0]; + + self.officeHoursColor = [UIColor whiteColor]; + self.hourMarkerColor = [[UIColor blackColor] colorWithAlphaComponent:0.2]; + + self.timeColor = [UIColor blackColor]; + self.AMPMColor = [UIColor darkGrayColor]; + + self.backgroundColor = [UIColor clearColor]; + self.opaque = NO; } return self; @@ -317,6 +338,24 @@ - (void)reloadData { event.intersectingEvents = intersectingEvents; } + // Reload theming info + if ([dataSource respondsToSelector:@selector(outsideHoursColor)]) + self.outsideHoursColor = [dataSource outsideHoursColor]; + + if ([dataSource respondsToSelector:@selector(hourMarkerColor)]) + self.hourMarkerColor = [dataSource hourMarkerColor]; + + if ([dataSource respondsToSelector:@selector(timeColor)]) + self.timeColor = [dataSource timeColor]; + + if ([dataSource respondsToSelector:@selector(hourMarkerColor)]) + self.AMPMColor = [dataSource AMPMColor]; + + if ([dataSource respondsToSelector:@selector(officeHoursColor)]) + self.officeHoursColor = [dataSource officeHoursColor]; + + + // drop all subviews [self.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)]; @@ -329,15 +368,15 @@ - (void)reloadData { // create scroll view scrollView = [[UIScrollView alloc] init]; - scrollView.backgroundColor = [UIColor colorWithRed:(242.0 / 255.0) green:(242.0 / 255.0) blue:(242.0 / 255.0) alpha:1.0]; scrollView.frame = CGRectMake(0, allDayView.frame.size.height, self.frame.size.width, self.frame.size.height - allDayView.frame.size.height); scrollView.contentSize = CGSizeMake(self.frame.size.width, 1078); scrollView.autoresizingMask = (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight); [self addSubview:scrollView]; + scrollView.backgroundColor = [UIColor clearColor]; // create today view - todayView = [[GCCalendarTodayView alloc] initWithEvents:events]; + todayView = [[GCCalendarTodayView alloc] initWithEvents:events dayView:self]; todayView.frame = CGRectMake(0, 0, self.frame.size.width, 1078); todayView.autoresizingMask = UIViewAutoresizingFlexibleWidth; [scrollView addSubview:todayView]; diff --git a/GCCalendar/GCCalendarPortraitViewController.m b/GCCalendar/GCCalendarPortraitViewController.m index 6380b46..3153373 100644 --- a/GCCalendar/GCCalendarPortraitViewController.m +++ b/GCCalendar/GCCalendarPortraitViewController.m @@ -110,11 +110,31 @@ - (void)viewDidLoad { [self.view addSubview:dayView]; // setup today button - UIBarButtonItem *button = [[UIBarButtonItem alloc] initWithTitle:[[NSBundle mainBundle] localizedStringForKey:@"TODAY" value:@"" table:@"GCCalendar"] + UIBarButtonItem *button = [[UIBarButtonItem alloc] initWithTitle:@"Today" style:UIBarButtonItemStylePlain target:self action:@selector(today)]; self.navigationItem.leftBarButtonItem = button; + + if ([dataSource respondsToSelector:@selector(datePickerLeftButtonImage)]) + [dayPicker setLeftButtonImage:[dataSource datePickerLeftButtonImage]]; + + if ([dataSource respondsToSelector:@selector(datePickerLeftButtonImage)]) + [dayPicker setRightButtonImage:[dataSource datePickerRightButtonImage]]; + + if ([dataSource respondsToSelector:@selector(datePickerBackgroundImage)]) + [dayPicker setBackgroundImage:[dataSource datePickerBackgroundImage]]; + + if ([dataSource respondsToSelector:@selector(datePickerTextColor)]) + [dayPicker setTextColor:[dataSource datePickerTextColor]]; + + if ([dataSource respondsToSelector:@selector(datePickerTextShadowColor)]) + [dayPicker setTextShadowColor:[dataSource datePickerTextShadowColor]]; + + + + + } - (void)loadView { diff --git a/GCCalendar/GCCalendarProtocols.h b/GCCalendar/GCCalendarProtocols.h index 1ebf2dc..119dff1 100644 --- a/GCCalendar/GCCalendarProtocols.h +++ b/GCCalendar/GCCalendarProtocols.h @@ -12,6 +12,21 @@ @protocol GCCalendarDataSource @required - (NSArray *)calendarEventsForDate:(NSDate *)date; + +@optional + +@property (retain) UIColor* outsideHoursColor; +@property (retain) UIColor* officeHoursColor; +@property (retain) UIColor* hourMarkerColor; +@property (retain) UIColor* timeColor; +@property (retain) UIColor* AMPMColor; + +@property (strong) UIImage* datePickerLeftButtonImage; +@property (strong) UIImage* datePickerRightButtonImage; +@property (strong) UIImage* datePickerBackgroundImage; +@property (strong) UIColor* datePickerTextColor; +@property (strong) UIColor* datePickerTextShadowColor; + @end @class GCCalendarEvent; diff --git a/GCCalendar/GCCalendarTileView.m b/GCCalendar/GCCalendarTileView.m index d9fc5c1..2e133af 100644 --- a/GCCalendar/GCCalendarTileView.m +++ b/GCCalendar/GCCalendarTileView.m @@ -53,8 +53,8 @@ - (id)init { } - (void)dealloc { self.event = nil; - } + - (void)setEvent:(GCCalendarEvent *)e { event = e; diff --git a/GCCalendar/GCDatePickerControl.h b/GCCalendar/GCDatePickerControl.h index 13be0d8..455d360 100644 --- a/GCCalendar/GCDatePickerControl.h +++ b/GCCalendar/GCDatePickerControl.h @@ -32,4 +32,12 @@ @property (nonatomic, strong) NSDate *date; +- (void) setLeftButtonImage:(UIImage*)image; +- (void) setRightButtonImage:(UIImage*)image; +- (void) setBackgroundImage:(UIImage*)image; +- (void) setTextColor:(UIColor*)color; +- (void) setTextShadowColor:(UIColor*)color; + + + @end diff --git a/GCCalendar/GCDatePickerControl.m b/GCCalendar/GCDatePickerControl.m index 49cfa26..bd69d39 100644 --- a/GCCalendar/GCDatePickerControl.m +++ b/GCCalendar/GCDatePickerControl.m @@ -20,6 +20,27 @@ @implementation GCDatePickerControl @synthesize date, today; #pragma mark create and destroy view + +- (void)setLeftButtonImage:(UIImage *)leftButtonImage { + [backButton setImage:leftButtonImage forState:UIControlStateNormal]; +} + +- (void)setRightButtonImage:(UIImage *)rightButtonImage { + [forwardButton setImage:rightButtonImage forState:UIControlStateNormal]; +} + +- (void)setTextColor:(UIColor *)color { + titleLabel.textColor = color; +} + +- (void)setTextShadowColor:(UIColor *)color{ + titleLabel.shadowColor = color; +} + +- (void)setBackgroundImage:(UIImage *)image { + self.backgroundColor = [UIColor colorWithPatternImage:image]; +} + - (id)init { if(self = [super init]) { self.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"GCDatePickerControlBackground.png"]]; @@ -119,7 +140,7 @@ - (void)setFrame:(CGRect)newFrame { - (void)setToday:(BOOL)newToday { today = newToday; - if(today) { + /*if(today) { titleLabel.textColor = [UIColor colorWithRed:0 green:(88.0/255.0) blue:(238.0/255.0) @@ -129,7 +150,7 @@ - (void)setToday:(BOOL)newToday { green:(65.0/255.0) blue:(84.0/255.0) alpha:1.0]; - } + }*/ } #pragma mark button actions From e16b6cfe074572db6a2385be040cc85520f57a55 Mon Sep 17 00:00:00 2001 From: Jon Manning Date: Wed, 29 Aug 2012 11:01:50 +1000 Subject: [PATCH 16/26] Numerous look and feel enhancements --- GCCalendar/CalendarBubbleBlue.png | Bin 3219 -> 0 bytes GCCalendar/CalendarBubbleGreen.png | Bin 3224 -> 0 bytes GCCalendar/CalendarBubbleGrey.png | Bin 3212 -> 0 bytes GCCalendar/CalendarBubbleMagenta.png | Bin 3256 -> 0 bytes GCCalendar/CalendarBubbleOrange.png | Bin 3264 -> 0 bytes GCCalendar/CalendarBubblePurple.png | Bin 3220 -> 0 bytes GCCalendar/CalendarBubbleRed.png | Bin 3259 -> 0 bytes GCCalendar/CalendarBubbleYellow.png | Bin 3266 -> 0 bytes GCCalendar/GCCalendarDayView.h | 2 + GCCalendar/GCCalendarDayView.m | 12 ++++-- GCCalendar/GCCalendarEvent.h | 2 +- GCCalendar/GCCalendarEvent.m | 2 +- GCCalendar/GCCalendarPortraitViewController.h | 3 +- GCCalendar/GCCalendarPortraitViewController.m | 28 ++++++++++-- GCCalendar/GCCalendarTileView.h | 3 +- GCCalendar/GCCalendarTileView.m | 40 ++++++++++++------ GCCalendar/GCDatePickerControl.h | 10 ++++- GCCalendar/GCDatePickerControl.m | 12 ++++-- 18 files changed, 85 insertions(+), 29 deletions(-) delete mode 100644 GCCalendar/CalendarBubbleBlue.png delete mode 100644 GCCalendar/CalendarBubbleGreen.png delete mode 100644 GCCalendar/CalendarBubbleGrey.png delete mode 100644 GCCalendar/CalendarBubbleMagenta.png delete mode 100644 GCCalendar/CalendarBubbleOrange.png delete mode 100644 GCCalendar/CalendarBubblePurple.png delete mode 100644 GCCalendar/CalendarBubbleRed.png delete mode 100644 GCCalendar/CalendarBubbleYellow.png diff --git a/GCCalendar/CalendarBubbleBlue.png b/GCCalendar/CalendarBubbleBlue.png deleted file mode 100644 index c62ce214ced6ae8659a80f665379341740cbbb22..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3219 zcmV;E3~cj>P)4Tx0C)kNmUmQBSrfqTdoR7v5<-y@dJRoV0Fe@UkzPe5BmqJR7!t5oLbpCc6HqI?@={d8%D5al;0(=!Cz zYydD6nO!2_rJ!tuGDRE_#zA==00c_%EKZ!o62USwPXIWXSj`sE}8w<4jU*%sHzk2;U z$a?$5<7MdQoaVsz{O95^ejS$UX;36cb2fe1Y+3Y{{cC>d?Hh%b}~Geu0H=$|_LAH!zl zAj2Q0Uf9TEuaUC0Snjw2jC3cfEVxw!5{*}g2jLb zQa}a}gIur*tOxm^5bOYZKsl%aHJ}bOfD@nvoCX)bWpEwb1byH>7z88W8JGmG!3+dJ zc!&zoAT>xEGJwn=8;A|fhrFObC=7~)5};&A1WBP)&_<{bDu&9TgHRpxBXkP709}Q8 zpu5lzG!Fdvqf1r2MCzX|yZIz>xmnl~$ zpHUuUAPhr>A0wSn#5lp|XS`F#WweHcflJworSw_BrjROl77!Go4w=>|jpnXz2LrNOcbC zbnDFM8tF#rZqRMieW*v$W9ud9?bd78o7C6V57J+yU$1}9fM~!rNHN%J&}lGjXk-{| zxY@A9aLh>6$j@knQN7UvW2&*M@lxYz|7l}t!?UTdxjmOU*L&{Txvg_w*qYf2Z1>yVv7^}q*=@FKxBFo4U@x|B zupf8OcSvxkbQoaM*&*z0>?@8~M-Rufj;9^pI@vo(oK86X;mmSQb3W=kHqU6DU|!9< zVHaH&uFFA}!THSj3G)xkA9U4m<+@h8K6cY{%Av^?0i=GocG202Kesu9q`liwb@Yi zqU=@)9sQZ=k{U}lNr!Ug=Tzjp$&JcAxlD1HXj#{C)8$*2kFM}u@%>87O5V!$RXVHI zuNqqIzWU%AXiegp_O*Iz^VW{6^I3OfJ!yT~`d>C!Z7AOGYGd@qwmi+eb$P>^d^XkR z%jJvn2R1uzuG)gxBHYrwb?(-(tse{c1=k9#3QG##Z{uyd_MP>2rQdzpp0vHY$i8U* z4%`mWj{cplJC77A7OyBC-W9Z~c{g)+!R}Xkmh8D&Vp~$Rm$X;9cd#_Dw6#pXY)9Gq z@|5zv3Xh7$N{z~`mDBt9`+E1g?Qf{ktSYQ}cR+aH&Ox7p&DDn0C5Lc_at=MIiK^-R zp8b7Yt$J-??T5pn!-Ge{j&#&H)YTo;I9gN>*GucikHsIm`Ge;VtqrV(gN=;F!sFn$ z^!U>s6MpPJ5pbgYB>QB;PX<3#Hqn|2nxW?9&66!DErYGGtv#pwPqnu>w>AB2@$=!+ zI;ShnD4!`hOFEl(_S3l)=cdkQou9and||kKN&EeaF&A%lgm!da3b=ITviIeSo$j6I zuDDz|ebwpescYO08?84TZ?^T!>p9!&+I!)a=dH`P z{cd0HThQ0jAK8CrAbw!*4*$;B-SoRJ?&aK@xxelK_Cdizg@+}NG#*v|YVvF2p#9*P zAK5^Wa`oDjMp>M1#i^e9C^!r+xaf~-RMm2 zd;I&-4<;YlJ_dYz@G0Zdr@sILoAdna&gY5%000SaNLh0L01FcU01FcV0GgZ_0005@ zNklt5daGspG>dj|KlZR+QQQbM0ShgE_rhpDt&f%v|9s>0+ zEknhjDiW~-!LMuJp<{|PI4EtBMUhe@##+&%On;V=M+>5o4o5b@0&gs`$f7Px;#e7Z zv{)WQC&(0gisc!WH#t*D-Z)e9OG|1=Cj^drjKHJuWBs-L7sZir5IjG?q+=BJ1D7J> z?dZMhwc~q!zi^*C@>4u=*Z;Pa0MYgdcXrb#}$HKkf{g>ks|G_pkh0 zo(ATmlFjE=?%da`v7~8b4%I>}&Rf&+!_M1-cQ2lb8E%8yq9_BVfmz@T&;X_YR>8wI z0C>js0QS(Oh<#N75>ElRzk<&=PjLzKfqj54DD_`%*dLbC?9g?X>v8}9002ovPDHLk FV1m;9KF9z7 diff --git a/GCCalendar/CalendarBubbleGreen.png b/GCCalendar/CalendarBubbleGreen.png deleted file mode 100644 index 5208efe578576ecb6b334d473db0f2bd70092ccb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3224 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 KMNUMnLSTXb8aq+| diff --git a/GCCalendar/CalendarBubbleGrey.png b/GCCalendar/CalendarBubbleGrey.png deleted file mode 100644 index 88166660c7d652507321e60e32f7acb365e71fca..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3212 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 diff --git a/GCCalendar/CalendarBubbleYellow.png b/GCCalendar/CalendarBubbleYellow.png deleted file mode 100644 index 0a2f14fee17a044dd63cab43b55dd9ed36b70f9d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3266 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 #import "GCCalendarViewController.h" +#import "GCDatePickerControl.h" @class GCDatePickerControl; @class GCCalendarDayView; @@ -27,7 +28,7 @@ push a detailed view controller onto the stack with more information about the event (currently unimplemnted) */ -@interface GCCalendarPortraitViewController : GCCalendarViewController { +@interface GCCalendarPortraitViewController : GCCalendarViewController { // date the view will display NSDate *date; diff --git a/GCCalendar/GCCalendarPortraitViewController.m b/GCCalendar/GCCalendarPortraitViewController.m index 3153373..9ce7e9e 100644 --- a/GCCalendar/GCCalendarPortraitViewController.m +++ b/GCCalendar/GCCalendarPortraitViewController.m @@ -51,13 +51,24 @@ - (void)datePickerDidChangeDate:(GCDatePickerControl *)picker { #pragma mark button actions - (void)today { - dayPicker.date = [NSDate date]; + if (dayPicker.delegate && [dayPicker.delegate datePickerControl:dayPicker willChangeToDate:[NSDate date]] == NO) { + + } else { + dayPicker.date = [NSDate date]; + } + self.date = dayPicker.date; [[NSUserDefaults standardUserDefaults] setObject:date forKey:@"GCCalendarDate"]; [self reloadDayAnimated:NO context:NULL]; + + NSCalendar* calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar]; + NSDateComponents* components = [calendar components:NSHourCalendarUnit fromDate:[NSDate date]]; + + [self.dayView scrollToHour:[components hour] - 1]; + } - (void)add { if (delegate != nil) { @@ -97,6 +108,7 @@ - (void)viewDidLoad { dayPicker.frame = CGRectMake(0, 0, self.view.frame.size.width, 0); dayPicker.autoresizingMask = UIViewAutoresizingNone; dayPicker.date = date; + dayPicker.delegate = self; [dayPicker addTarget:self action:@selector(datePickerDidChangeDate:) forControlEvents:UIControlEventValueChanged]; [self.view addSubview:dayPicker]; @@ -110,7 +122,7 @@ - (void)viewDidLoad { [self.view addSubview:dayView]; // setup today button - UIBarButtonItem *button = [[UIBarButtonItem alloc] initWithTitle:@"Today" + UIBarButtonItem *button = [[UIBarButtonItem alloc] initWithTitle:@"Now" style:UIBarButtonItemStylePlain target:self action:@selector(today)]; @@ -132,7 +144,7 @@ - (void)viewDidLoad { [dayPicker setTextShadowColor:[dataSource datePickerTextShadowColor]]; - + } @@ -160,6 +172,12 @@ - (void)viewWillAppear:(BOOL)animated { } viewVisible = YES; + + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + [self.dayView scrollToHour:[[NSUserDefaults standardUserDefaults] floatForKey:@"start_time"]]; + }); + } - (void)viewDidDisappear:(BOOL)animated { [super viewDidDisappear:animated]; @@ -240,4 +258,8 @@ - (void)reloadData { [self reloadDayAnimated:NO context:NULL]; } +- (BOOL)datePickerControl:(GCDatePickerControl *)picker willChangeToDate:(NSDate *)date { + return YES; +} + @end diff --git a/GCCalendar/GCCalendarTileView.h b/GCCalendar/GCCalendarTileView.h index 3f920ae..57b92bc 100644 --- a/GCCalendar/GCCalendarTileView.h +++ b/GCCalendar/GCCalendarTileView.h @@ -11,6 +11,7 @@ #import @class GCCalendarEvent; +@class EAGlossyBox; /* A GCCalendarTile draws itself using data in the event passed to it. @@ -24,7 +25,7 @@ UILabel *descriptionLabel; // view containing stretchable image - UIImageView *backgroundView; + EAGlossyBox *backgroundView; // view containing the event's badge image UIImageView* badgeImageView; diff --git a/GCCalendar/GCCalendarTileView.m b/GCCalendar/GCCalendarTileView.m index 2e133af..504d0c3 100644 --- a/GCCalendar/GCCalendarTileView.m +++ b/GCCalendar/GCCalendarTileView.m @@ -11,6 +11,7 @@ #import "GCCalendarTileView.h" #import "GCCalendarEvent.h" #import "GCCalendar.h" +#import "EAGlossyBox.h" #define TILE_SIDE_PADDING 6 @@ -29,6 +30,7 @@ - (id)init { titleLabel.textColor = [UIColor whiteColor]; titleLabel.shadowColor = [UIColor colorWithWhite:0.0f alpha:0.5f]; titleLabel.font = [UIFont boldSystemFontOfSize:14.0f]; + titleLabel.numberOfLines = 0; descriptionLabel = [[UILabel alloc] init]; descriptionLabel.backgroundColor = [UIColor clearColor]; @@ -40,7 +42,7 @@ - (id)init { badgeImageView = [[UIImageView alloc] init]; - backgroundView = [[UIImageView alloc] init]; + backgroundView = [[EAGlossyBox alloc] initWithFrame:CGRectZero]; backgroundView.alpha = 0.90f; [self addSubview:backgroundView]; @@ -58,16 +60,19 @@ - (void)dealloc { - (void)setEvent:(GCCalendarEvent *)e { event = e; + // set bg image - NSString *colorString = [event.color capitalizedString]; - NSString *colorImageName = [NSString stringWithFormat:@"CalendarBubble%@.png", colorString]; - UIImage *bgImage = [UIImage imageNamed:colorImageName]; - backgroundView.image = [bgImage stretchableImageWithLeftCapWidth:6 topCapHeight:13]; + backgroundView.color = event.color; // set title titleLabel.text = event.eventName; descriptionLabel.text = event.eventDescription; + if (event.eventDescription == nil) + descriptionLabel.hidden = YES; + else + descriptionLabel.hidden = NO; + if (event.image) { badgeImageView.image = event.image; } @@ -78,21 +83,30 @@ - (void)layoutSubviews { CGRect myBounds = self.bounds; - backgroundView.frame = myBounds; + backgroundView.frame = CGRectInset(myBounds, 1, 1); [badgeImageView sizeToFit]; badgeImageView.frame = CGRectMake(myBounds.size.width - badgeImageView.bounds.size.width - TILE_SIDE_PADDING, 3, badgeImageView.bounds.size.width, badgeImageView.bounds.size.height); - + NSInteger titleWidth = myBounds.size.width - TILE_SIDE_PADDING * 2; + CGSize stringSize = CGSizeZero; + + CGRect titleRect = CGRectMake(TILE_SIDE_PADDING, 3, titleWidth, myBounds.size.height); if (event.image) - titleWidth -= (badgeImageView.bounds.size.width + 3); + titleRect.size.width -= (badgeImageView.bounds.size.width + 3); + + + if (event.eventDescription) { + stringSize = [titleLabel.text sizeWithFont:titleLabel.font]; + } else { + stringSize = [titleLabel.text sizeWithFont:titleLabel.font constrainedToSize:titleRect.size]; + } + + + titleRect.size = stringSize; - CGSize stringSize = [titleLabel.text sizeWithFont:titleLabel.font]; - titleLabel.frame = CGRectMake(TILE_SIDE_PADDING, - 3, - titleWidth, - stringSize.height); + titleLabel.frame = titleRect; if (event.allDayEvent) { descriptionLabel.frame = CGRectZero; diff --git a/GCCalendar/GCDatePickerControl.h b/GCCalendar/GCDatePickerControl.h index 455d360..f09ae58 100644 --- a/GCCalendar/GCDatePickerControl.h +++ b/GCCalendar/GCDatePickerControl.h @@ -10,6 +10,14 @@ #import +@class GCDatePickerControl; + +@protocol GCDatePickerControlDelegate + +- (BOOL) datePickerControl:(GCDatePickerControl*)picker willChangeToDate:(NSDate*)date; + +@end + /* This UIControl subclass displays the mechanism for changing the currently displayed date. When the date is changed by the user, an action is posted @@ -38,6 +46,6 @@ - (void) setTextColor:(UIColor*)color; - (void) setTextShadowColor:(UIColor*)color; - +@property (weak) id delegate; @end diff --git a/GCCalendar/GCDatePickerControl.m b/GCCalendar/GCDatePickerControl.m index bd69d39..ba9f4b4 100644 --- a/GCCalendar/GCDatePickerControl.m +++ b/GCCalendar/GCDatePickerControl.m @@ -48,14 +48,14 @@ - (id)init { // left button backButton = [[UIButton alloc] init]; [backButton setImage:[UIImage imageNamed:@"GCDatePickerControlLeft.png"] forState:UIControlStateNormal]; - backButton.showsTouchWhenHighlighted = NO; + backButton.showsTouchWhenHighlighted = YES; backButton.adjustsImageWhenHighlighted = NO; [backButton addTarget:self action:@selector(buttonPressed:) forControlEvents:UIControlEventTouchUpInside]; // right button forwardButton = [[UIButton alloc] init]; [forwardButton setImage:[UIImage imageNamed:@"GCDatePickerControlRight.png"] forState:UIControlStateNormal]; - forwardButton.showsTouchWhenHighlighted = NO; + forwardButton.showsTouchWhenHighlighted = YES; forwardButton.adjustsImageWhenHighlighted = NO; [forwardButton addTarget:self action:@selector(buttonPressed:) forControlEvents:UIControlEventTouchUpInside]; @@ -158,10 +158,14 @@ - (void)buttonPressed:(UIButton *)sender { #define kSecondsInDay (60 * 60 * 24) if(sender == backButton) { NSDate *newDate = [[NSDate alloc] initWithTimeInterval:-kSecondsInDay sinceDate:date]; - self.date = newDate; + if (self.delegate && [self.delegate datePickerControl:self willChangeToDate:newDate] == NO) + return; + self.date = newDate; } else if(sender == forwardButton) { NSDate *newDate = [[NSDate alloc] initWithTimeInterval:kSecondsInDay sinceDate:date]; - self.date = newDate; + if (self.delegate && [self.delegate datePickerControl:self willChangeToDate:newDate] == NO) + return; + self.date = newDate; } [self sendActionsForControlEvents:UIControlEventValueChanged]; From 11a00a7b80add74c35dcf27c2a2ac20c0f4f9e1b Mon Sep 17 00:00:00 2001 From: Jon Manning Date: Wed, 29 Aug 2012 11:02:26 +1000 Subject: [PATCH 17/26] Add some files that were missing from last commit --- GCCalendar/Calendar-Tile-Base.png | Bin 0 -> 3154 bytes GCCalendar/Calendar-Tile-Base@2x.png | Bin 0 -> 3742 bytes GCCalendar/EAGlossyBox.h | 17 +++++++++ GCCalendar/EAGlossyBox.m | 54 +++++++++++++++++++++++++++ GCCalendar/EATintedImageView.h | 16 ++++++++ GCCalendar/EATintedImageView.m | 46 +++++++++++++++++++++++ 6 files changed, 133 insertions(+) create mode 100644 GCCalendar/Calendar-Tile-Base.png create mode 100644 GCCalendar/Calendar-Tile-Base@2x.png create mode 100644 GCCalendar/EAGlossyBox.h create mode 100644 GCCalendar/EAGlossyBox.m create mode 100644 GCCalendar/EATintedImageView.h create mode 100644 GCCalendar/EATintedImageView.m diff --git a/GCCalendar/Calendar-Tile-Base.png b/GCCalendar/Calendar-Tile-Base.png new file mode 100644 index 0000000000000000000000000000000000000000..4202b19353b4cdc8357f1eb1fb9f2e17a5db0edc GIT binary patch literal 3154 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 literal 0 HcmV?d00001 diff --git a/GCCalendar/EAGlossyBox.h b/GCCalendar/EAGlossyBox.h new file mode 100644 index 0000000..f50daf7 --- /dev/null +++ b/GCCalendar/EAGlossyBox.h @@ -0,0 +1,17 @@ +// +// EAGlossyBox.h +// EventApp +// +// Created by Jon Manning on 29/08/12. +// Copyright (c) 2012 Secret Lab. All rights reserved. +// + +#import + +@interface EAGlossyBox : UIView + +@property (assign) CGFloat radius; + +- (void) setColor:(UIColor*)color; + +@end diff --git a/GCCalendar/EAGlossyBox.m b/GCCalendar/EAGlossyBox.m new file mode 100644 index 0000000..980ac2a --- /dev/null +++ b/GCCalendar/EAGlossyBox.m @@ -0,0 +1,54 @@ +// +// EAGlossyBox.m +// EventApp +// +// Created by Jon Manning on 29/08/12. +// Copyright (c) 2012 Secret Lab. All rights reserved. +// + +#import "EAGlossyBox.h" +#import + +@interface EAGlossyBox () { + UIImageView* _glossImage; +} + +@end + +@implementation EAGlossyBox + +- (id)initWithFrame:(CGRect)frame +{ + self = [super initWithFrame:frame]; + if (self) { + self.layer.cornerRadius = 5; + self.layer.borderColor = [UIColor colorWithWhite:0 alpha:0.2].CGColor; + self.layer.borderWidth = 1; + + + _glossImage = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"Calendar-Tile-Gloss-Pattern"]]; + [self addSubview:_glossImage]; + self.clipsToBounds = YES; + + } + return self; +} + +- (void)setColor:(UIColor *)color { + self.backgroundColor = color; +} + +- (void)layoutSubviews { + _glossImage.frame = CGRectMake(0, 0, CGRectGetWidth(self.frame), CGRectGetHeight(_glossImage.bounds)); +} + +/* +// Only override drawRect: if you perform custom drawing. +// An empty implementation adversely affects performance during animation. +- (void)drawRect:(CGRect)rect +{ + // Drawing code +} +*/ + +@end diff --git a/GCCalendar/EATintedImageView.h b/GCCalendar/EATintedImageView.h new file mode 100644 index 0000000..eb93492 --- /dev/null +++ b/GCCalendar/EATintedImageView.h @@ -0,0 +1,16 @@ +// +// EATintedImageView.h +// EventApp +// +// Created by Jon Manning on 28/08/12. +// Copyright (c) 2012 Secret Lab. All rights reserved. +// + +#import + +@interface EATintedImageView : UIView + +@property (strong) UIImage* image; +@property (strong) UIColor* overlayColor; + +@end diff --git a/GCCalendar/EATintedImageView.m b/GCCalendar/EATintedImageView.m new file mode 100644 index 0000000..8b8bc8e --- /dev/null +++ b/GCCalendar/EATintedImageView.m @@ -0,0 +1,46 @@ +// +// EATintedImageView.m +// EventApp +// +// Created by Jon Manning on 28/08/12. +// Copyright (c) 2012 Secret Lab. All rights reserved. +// + +#import "EATintedImageView.h" + +@implementation EATintedImageView + +- (id)initWithFrame:(CGRect)frame +{ + self = [super initWithFrame:frame]; + if (self) { + // Initialization code + } + return self; +} + +- (void) drawRect:(CGRect)area +{ + CGContextRef context = UIGraphicsGetCurrentContext(); + CGContextSaveGState(context); + + [self.image drawInRect:self.bounds]; + + if (self.overlayColor) { + CGContextSetBlendMode (context, kCGBlendModeHue); + CGContextSetFillColor(context, CGColorGetComponents(self.overlayColor.CGColor)); + CGContextFillRect (context, self.bounds); + } + CGContextRestoreGState(context); +} + +/* +// Only override drawRect: if you perform custom drawing. +// An empty implementation adversely affects performance during animation. +- (void)drawRect:(CGRect)rect +{ + // Drawing code +} +*/ + +@end From 5b2ce43775b6adb4010bc226bb5d453b2123691c Mon Sep 17 00:00:00 2001 From: Jon Manning Date: Wed, 29 Aug 2012 18:15:32 +1000 Subject: [PATCH 18/26] Adjust some details. --- GCCalendar/GCCalendarDayView.m | 1 + GCCalendar/GCCalendarPortraitViewController.m | 2 +- GCCalendar/GCCalendarTileView.m | 4 +--- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/GCCalendar/GCCalendarDayView.m b/GCCalendar/GCCalendarDayView.m index fc144dc..3ccc196 100644 --- a/GCCalendar/GCCalendarDayView.m +++ b/GCCalendar/GCCalendarDayView.m @@ -373,6 +373,7 @@ - (void)reloadData { scrollView.contentSize = CGSizeMake(self.frame.size.width, 2156); scrollView.autoresizingMask = (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight); [self addSubview:scrollView]; + scrollView.indicatorStyle = UIScrollViewIndicatorStyleWhite; scrollView.backgroundColor = [UIColor clearColor]; // create today view diff --git a/GCCalendar/GCCalendarPortraitViewController.m b/GCCalendar/GCCalendarPortraitViewController.m index 9ce7e9e..dee691c 100644 --- a/GCCalendar/GCCalendarPortraitViewController.m +++ b/GCCalendar/GCCalendarPortraitViewController.m @@ -67,7 +67,7 @@ - (void)today { NSCalendar* calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar]; NSDateComponents* components = [calendar components:NSHourCalendarUnit fromDate:[NSDate date]]; - [self.dayView scrollToHour:[components hour] - 1]; + [self.dayView scrollToHour:[components hour] - 0.5]; } - (void)add { diff --git a/GCCalendar/GCCalendarTileView.m b/GCCalendar/GCCalendarTileView.m index 504d0c3..92fa3ae 100644 --- a/GCCalendar/GCCalendarTileView.m +++ b/GCCalendar/GCCalendarTileView.m @@ -92,18 +92,16 @@ - (void)layoutSubviews { CGSize stringSize = CGSizeZero; - CGRect titleRect = CGRectMake(TILE_SIDE_PADDING, 3, titleWidth, myBounds.size.height); + CGRect titleRect = CGRectMake(TILE_SIDE_PADDING, 3, titleWidth, myBounds.size.height-6); if (event.image) titleRect.size.width -= (badgeImageView.bounds.size.width + 3); - if (event.eventDescription) { stringSize = [titleLabel.text sizeWithFont:titleLabel.font]; } else { stringSize = [titleLabel.text sizeWithFont:titleLabel.font constrainedToSize:titleRect.size]; } - titleRect.size = stringSize; titleLabel.frame = titleRect; From 5d3c77c1b2193712918e24a40f560561e49d5f8e Mon Sep 17 00:00:00 2001 From: Jon Manning Date: Wed, 29 Aug 2012 22:01:52 +1000 Subject: [PATCH 19/26] Don't make EAGlossyBoxes go weird when they're inside a UITableViewCell and that cell is selected. WTF. --- GCCalendar/EAGlossyBox.m | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/GCCalendar/EAGlossyBox.m b/GCCalendar/EAGlossyBox.m index 980ac2a..5cf60af 100644 --- a/GCCalendar/EAGlossyBox.m +++ b/GCCalendar/EAGlossyBox.m @@ -34,8 +34,16 @@ - (id)initWithFrame:(CGRect)frame return self; } +// If we're in a UITableViewCell, when selected we appear to receive +// a call to setBackgroundColor: that sets our color to clear. +// We only want to do this when the 'color' property is set, +// so ignore this call. +- (void)setBackgroundColor:(UIColor *)backgroundColor { + +} + - (void)setColor:(UIColor *)color { - self.backgroundColor = color; + [super setBackgroundColor:color]; } - (void)layoutSubviews { From 6bfb128214f27bf96a4e39145e2fbb67d6c9bf36 Mon Sep 17 00:00:00 2001 From: Jon Manning Date: Sat, 1 Sep 2012 14:22:26 +1000 Subject: [PATCH 20/26] Events that are immediately following each other do not count as intersecting --- GCCalendar/GCCalendarEvent.m | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/GCCalendar/GCCalendarEvent.m b/GCCalendar/GCCalendarEvent.m index f5fc2fc..dda1e36 100644 --- a/GCCalendar/GCCalendarEvent.m +++ b/GCCalendar/GCCalendarEvent.m @@ -27,7 +27,10 @@ - (BOOL) intersectsEvent:(GCCalendarEvent*)otherEvent { NSTimeInterval theirStartDateTime = otherEvent.startDate.timeIntervalSinceReferenceDate; NSTimeInterval theirEndDateTime = otherEvent.endDate.timeIntervalSinceReferenceDate; - + + if (myEndDateTime == theirStartDateTime || myStartDateTime == theirEndDateTime) + return NO; + return (myStartDateTime <= theirEndDateTime) && (myEndDateTime >= theirStartDateTime); } From 7ec78c09ac3a1aa8f7e7e58e89f640c0317d175b Mon Sep 17 00:00:00 2001 From: Jon Manning Date: Sat, 1 Sep 2012 14:49:40 +1000 Subject: [PATCH 21/26] Add spacing between events. --- GCCalendar/GCCalendarTileView.m | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/GCCalendar/GCCalendarTileView.m b/GCCalendar/GCCalendarTileView.m index 92fa3ae..a9286d3 100644 --- a/GCCalendar/GCCalendarTileView.m +++ b/GCCalendar/GCCalendarTileView.m @@ -29,7 +29,7 @@ - (id)init { titleLabel.backgroundColor = [UIColor clearColor]; titleLabel.textColor = [UIColor whiteColor]; titleLabel.shadowColor = [UIColor colorWithWhite:0.0f alpha:0.5f]; - titleLabel.font = [UIFont boldSystemFontOfSize:14.0f]; + titleLabel.font = [UIFont boldSystemFontOfSize:12.0f]; titleLabel.numberOfLines = 0; descriptionLabel = [[UILabel alloc] init]; @@ -80,19 +80,19 @@ - (void)setEvent:(GCCalendarEvent *)e { [self setNeedsDisplay]; } - (void)layoutSubviews { - CGRect myBounds = self.bounds; + CGRect myBounds = CGRectInset(self.bounds, 0, 3); backgroundView.frame = CGRectInset(myBounds, 1, 1); [badgeImageView sizeToFit]; - badgeImageView.frame = CGRectMake(myBounds.size.width - badgeImageView.bounds.size.width - TILE_SIDE_PADDING, 3, badgeImageView.bounds.size.width, badgeImageView.bounds.size.height); + badgeImageView.frame = CGRectMake(myBounds.size.width - badgeImageView.bounds.size.width - TILE_SIDE_PADDING, myBounds.origin.y+3, badgeImageView.bounds.size.width, badgeImageView.bounds.size.height); NSInteger titleWidth = myBounds.size.width - TILE_SIDE_PADDING * 2; CGSize stringSize = CGSizeZero; - CGRect titleRect = CGRectMake(TILE_SIDE_PADDING, 3, titleWidth, myBounds.size.height-6); + CGRect titleRect = CGRectMake(TILE_SIDE_PADDING, myBounds.origin.y+3, titleWidth, myBounds.size.height-10); if (event.image) titleRect.size.width -= (badgeImageView.bounds.size.width + 3); From df3f8aad105ea13ec8a89c5e64d1a8e7e68d0a1b Mon Sep 17 00:00:00 2001 From: Jon Manning Date: Tue, 4 Sep 2012 12:03:22 +1000 Subject: [PATCH 22/26] Mondo chango --- GCCalendar/GCCalendarDayView.m | 60 ++++++++++++++++++++++++++++---- GCCalendar/GCCalendarEvent.h | 3 ++ GCCalendar/GCCalendarEvent.m | 30 ++++++++++++++++ GCCalendar/GCCalendarTileView.m | 9 +++-- GCCalendar/GCDatePickerControl.m | 30 +++++++++++++++- 5 files changed, 122 insertions(+), 10 deletions(-) diff --git a/GCCalendar/GCCalendarDayView.m b/GCCalendar/GCCalendarDayView.m index 3ccc196..7992bec 100644 --- a/GCCalendar/GCCalendarDayView.m +++ b/GCCalendar/GCCalendarDayView.m @@ -152,16 +152,12 @@ - (void)layoutSubviews { // get calendar tile and associated event GCCalendarTileView *tile = (GCCalendarTileView *)view; - NSDateComponents *components; - components = [[NSCalendar currentCalendar] components:(NSHourCalendarUnit | - NSMinuteCalendarUnit) - fromDate:tile.event.startDate]; + NSDateComponents *components; + components = tile.event.startDateComponents; NSInteger startHour = [components hour]; NSInteger startMinute = [components minute]; - components = [[NSCalendar currentCalendar] components:(NSHourCalendarUnit | - NSMinuteCalendarUnit) - fromDate:tile.event.endDate]; + components = tile.event.endDateComponents; NSInteger endHour = [components hour]; NSInteger endMinute = [components minute]; @@ -335,9 +331,56 @@ - (void)reloadData { [intersectingEvents addObject:otherEvent]; } + + event.intersectingEvents = intersectingEvents; + } + + for (GCCalendarEvent* event in events){ + NSMutableArray* intersectingEvents = [NSMutableArray arrayWithArray:event.intersectingEvents]; + NSMutableArray* intersectingEventsToRemove = [NSMutableArray array]; + + for (GCCalendarEvent* otherEvent in intersectingEvents) { + BOOL intersecting = YES; + for (GCCalendarEvent* intersectingOtherEvent in intersectingEvents) { + if ([otherEvent intersectsEvent:intersectingOtherEvent] == NO) { + intersecting = NO; + break; + } + } + if (intersecting == NO) { + [intersectingEventsToRemove addObject:otherEvent]; + break; + } + + } + + [intersectingEvents removeObjectsInArray:intersectingEventsToRemove]; + event.intersectingEvents = intersectingEvents; } + // Remove intersecting events from the list if two events do not intersect with each other + + + // Now events get the maximum value of intersecting events + /*for (GCCalendarEvent* event in events) { + + NSMutableArray* newEvents = [NSMutableArray array]; + + for (GCCalendarEvent* otherEvent in event.intersectingEvents) { + for (GCCalendarEvent* otherIntersectingEvent in otherEvent.intersectingEvents) { + if (otherIntersectingEvent == event) + continue; + if ([event.intersectingEvents containsObject:otherIntersectingEvent]) + continue; + + [newEvents addObject:otherIntersectingEvent]; + } + } + NSLog(@"Added %i new events", newEvents.count); + event.intersectingEvents = [event.intersectingEvents arrayByAddingObjectsFromArray:newEvents]; + }*/ + // Reload theming info if ([dataSource respondsToSelector:@selector(outsideHoursColor)]) self.outsideHoursColor = [dataSource outsideHoursColor]; @@ -375,6 +418,9 @@ - (void)reloadData { [self addSubview:scrollView]; scrollView.indicatorStyle = UIScrollViewIndicatorStyleWhite; scrollView.backgroundColor = [UIColor clearColor]; + + + scrollView.contentInset = UIEdgeInsetsMake(-[GCCalendarTodayView yValueForTime:7.9], 0, -[GCCalendarTodayView yValueForTime:2], 0); // create today view todayView = [[GCCalendarTodayView alloc] initWithEvents:events dayView:self]; diff --git a/GCCalendar/GCCalendarEvent.h b/GCCalendar/GCCalendarEvent.h index 4d0933b..b85a4ea 100644 --- a/GCCalendar/GCCalendarEvent.h +++ b/GCCalendar/GCCalendarEvent.h @@ -31,6 +31,9 @@ @property (nonatomic, strong) id userInfo; @property (nonatomic) BOOL allDayEvent; +@property (readonly) NSDateComponents* startDateComponents; +@property (readonly) NSDateComponents* endDateComponents; + // If set, this image will be displayed at the right of the title. @property (nonatomic, strong) UIImage* image; diff --git a/GCCalendar/GCCalendarEvent.m b/GCCalendar/GCCalendarEvent.m index dda1e36..a315c4b 100644 --- a/GCCalendar/GCCalendarEvent.m +++ b/GCCalendar/GCCalendarEvent.m @@ -12,6 +12,9 @@ @implementation GCCalendarEvent +@synthesize startDateComponents = _startDateComponents; +@synthesize endDateComponents = _endDateComponents; + - (id)init { if (self = [super init]) { @@ -38,5 +41,32 @@ - (NSInteger)column { return [self.intersectingEvents indexOfObject:self]; } +- (void)setStartDate:(NSDate *)startDate { + _startDate = startDate; + _startDateComponents = nil; +} + +- (void)setEndDate:(NSDate *)endDate { + _endDate = endDate; + _endDateComponents = nil; +} + +- (NSDateComponents *)startDateComponents { + if (_startDateComponents == nil) { + _startDateComponents = [[NSCalendar currentCalendar] components:(NSHourCalendarUnit | + NSMinuteCalendarUnit) + fromDate:self.startDate]; + } + return _startDateComponents; +} + +- (NSDateComponents *)endDateComponents { + if (_endDateComponents == nil) { + _endDateComponents = [[NSCalendar currentCalendar] components:(NSHourCalendarUnit | + NSMinuteCalendarUnit) + fromDate:self.endDate]; + } + return _endDateComponents; +} @end diff --git a/GCCalendar/GCCalendarTileView.m b/GCCalendar/GCCalendarTileView.m index a9286d3..399260e 100644 --- a/GCCalendar/GCCalendarTileView.m +++ b/GCCalendar/GCCalendarTileView.m @@ -12,6 +12,7 @@ #import "GCCalendarEvent.h" #import "GCCalendar.h" #import "EAGlossyBox.h" +#import #define TILE_SIDE_PADDING 6 @@ -29,7 +30,7 @@ - (id)init { titleLabel.backgroundColor = [UIColor clearColor]; titleLabel.textColor = [UIColor whiteColor]; titleLabel.shadowColor = [UIColor colorWithWhite:0.0f alpha:0.5f]; - titleLabel.font = [UIFont boldSystemFontOfSize:12.0f]; + titleLabel.font = [UIFont systemFontOfSize:13.0f]; titleLabel.numberOfLines = 0; descriptionLabel = [[UILabel alloc] init]; @@ -49,6 +50,9 @@ - (id)init { [self addSubview:badgeImageView]; [self addSubview:titleLabel]; [self addSubview:descriptionLabel]; + + self.layer.shouldRasterize = YES; + self.layer.rasterizationScale = [UIScreen mainScreen].scale; } return self; @@ -65,7 +69,8 @@ - (void)setEvent:(GCCalendarEvent *)e { backgroundView.color = event.color; // set title - titleLabel.text = event.eventName; + titleLabel.text = event.eventName; + descriptionLabel.text = event.eventDescription; if (event.eventDescription == nil) diff --git a/GCCalendar/GCDatePickerControl.m b/GCCalendar/GCDatePickerControl.m index ba9f4b4..3e92b89 100644 --- a/GCCalendar/GCDatePickerControl.m +++ b/GCCalendar/GCDatePickerControl.m @@ -11,6 +11,8 @@ #import "GCDatePickerControl.h" #import "GCCalendar.h" +#define kSecondsInDay (60 * 60 * 24) + @interface GCDatePickerControl () @property (nonatomic) BOOL today; @end @@ -130,6 +132,23 @@ - (void)setDate:(NSDate *)newDate { [monthStrings objectAtIndex:month - 1], day, year]; titleLabel.text = toDisplay; + + NSDate *dayBefore = [[NSDate alloc] initWithTimeInterval:-kSecondsInDay sinceDate:date]; + NSDate *dayAfter = [[NSDate alloc] initWithTimeInterval:kSecondsInDay sinceDate:date]; + + if (self.delegate && [self.delegate datePickerControl:self willChangeToDate:dayBefore] == NO) { + [self setButton:backButton enabled:NO]; + } else { + [self setButton:backButton enabled:YES]; + } + + if (self.delegate && [self.delegate datePickerControl:self willChangeToDate:dayAfter] == NO) { + [self setButton:forwardButton enabled:NO]; + } else { + [self setButton:forwardButton enabled:YES]; + } + + } - (void)setFrame:(CGRect)newFrame { newFrame.size.height = 45; @@ -153,9 +172,18 @@ - (void)setToday:(BOOL)newToday { }*/ } +- (void) setButton:(UIButton*)button enabled:(BOOL)enabled { + if (enabled) { + button.enabled = YES; + button.alpha = 1.0; + } else { + button.enabled = NO; + button.alpha = 0.5; + } +} + #pragma mark button actions - (void)buttonPressed:(UIButton *)sender { -#define kSecondsInDay (60 * 60 * 24) if(sender == backButton) { NSDate *newDate = [[NSDate alloc] initWithTimeInterval:-kSecondsInDay sinceDate:date]; if (self.delegate && [self.delegate datePickerControl:self willChangeToDate:newDate] == NO) From e592a1b00177f9b41714af6a6adf3736957f70c9 Mon Sep 17 00:00:00 2001 From: Jon Manning Date: Tue, 4 Sep 2012 21:21:33 +1000 Subject: [PATCH 23/26] Animated scrolling when moving to now --- GCCalendar/GCCalendarDayView.h | 1 + GCCalendar/GCCalendarDayView.m | 11 +++++++---- GCCalendar/GCCalendarPortraitViewController.m | 2 +- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/GCCalendar/GCCalendarDayView.h b/GCCalendar/GCCalendarDayView.h index 94ea9da..0e98dae 100644 --- a/GCCalendar/GCCalendarDayView.h +++ b/GCCalendar/GCCalendarDayView.h @@ -51,5 +51,6 @@ @property (retain) UIColor* AMPMColor; - (void) scrollToHour:(CGFloat)hour; +- (void) scrollToHour:(CGFloat)hour animated:(BOOL)animated; @end diff --git a/GCCalendar/GCCalendarDayView.m b/GCCalendar/GCCalendarDayView.m index 7992bec..510f4a6 100644 --- a/GCCalendar/GCCalendarDayView.m +++ b/GCCalendar/GCCalendarDayView.m @@ -428,15 +428,18 @@ - (void)reloadData { todayView.autoresizingMask = UIViewAutoresizingFlexibleWidth; [scrollView addSubview:todayView]; } -- (void)setContentOffset:(CGPoint)p { - scrollView.contentOffset = p; -} + + - (CGPoint)contentOffset { return scrollView.contentOffset; } +- (void) scrollToHour:(CGFloat)hour animated:(BOOL)animated { + [scrollView setContentOffset:CGPointMake(0, [GCCalendarTodayView yValueForTime:hour]) animated:animated]; +} + -(void)scrollToHour:(CGFloat)hour { - [self setContentOffset:CGPointMake(0, [GCCalendarTodayView yValueForTime:hour])]; + [self scrollToHour:hour animated:NO]; } @end \ No newline at end of file diff --git a/GCCalendar/GCCalendarPortraitViewController.m b/GCCalendar/GCCalendarPortraitViewController.m index dee691c..9702d57 100644 --- a/GCCalendar/GCCalendarPortraitViewController.m +++ b/GCCalendar/GCCalendarPortraitViewController.m @@ -67,7 +67,7 @@ - (void)today { NSCalendar* calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar]; NSDateComponents* components = [calendar components:NSHourCalendarUnit fromDate:[NSDate date]]; - [self.dayView scrollToHour:[components hour] - 0.5]; + [self.dayView scrollToHour:[components hour] - 0.5 animated:YES]; } - (void)add { From 538464fad6a7fe0934acc84b99daaf0f3b6410c8 Mon Sep 17 00:00:00 2001 From: Jon Manning Date: Tue, 4 Sep 2012 22:23:30 +1000 Subject: [PATCH 24/26] Improve the behaviour of the Now button --- GCCalendar/GCCalendarDayView.m | 23 +------------------ GCCalendar/GCCalendarPortraitViewController.m | 13 ++++++++--- 2 files changed, 11 insertions(+), 25 deletions(-) diff --git a/GCCalendar/GCCalendarDayView.m b/GCCalendar/GCCalendarDayView.m index 510f4a6..4e15141 100644 --- a/GCCalendar/GCCalendarDayView.m +++ b/GCCalendar/GCCalendarDayView.m @@ -335,6 +335,7 @@ - (void)reloadData { event.intersectingEvents = intersectingEvents; } + // Remove intersecting events from the list if two events do not intersect with each other for (GCCalendarEvent* event in events){ NSMutableArray* intersectingEvents = [NSMutableArray arrayWithArray:event.intersectingEvents]; NSMutableArray* intersectingEventsToRemove = [NSMutableArray array]; @@ -359,28 +360,6 @@ - (void)reloadData { event.intersectingEvents = intersectingEvents; } - // Remove intersecting events from the list if two events do not intersect with each other - - - // Now events get the maximum value of intersecting events - /*for (GCCalendarEvent* event in events) { - - NSMutableArray* newEvents = [NSMutableArray array]; - - for (GCCalendarEvent* otherEvent in event.intersectingEvents) { - for (GCCalendarEvent* otherIntersectingEvent in otherEvent.intersectingEvents) { - if (otherIntersectingEvent == event) - continue; - if ([event.intersectingEvents containsObject:otherIntersectingEvent]) - continue; - - [newEvents addObject:otherIntersectingEvent]; - } - } - NSLog(@"Added %i new events", newEvents.count); - event.intersectingEvents = [event.intersectingEvents arrayByAddingObjectsFromArray:newEvents]; - }*/ - // Reload theming info if ([dataSource respondsToSelector:@selector(outsideHoursColor)]) self.outsideHoursColor = [dataSource outsideHoursColor]; diff --git a/GCCalendar/GCCalendarPortraitViewController.m b/GCCalendar/GCCalendarPortraitViewController.m index 9702d57..a25e181 100644 --- a/GCCalendar/GCCalendarPortraitViewController.m +++ b/GCCalendar/GCCalendarPortraitViewController.m @@ -51,11 +51,20 @@ - (void)datePickerDidChangeDate:(GCDatePickerControl *)picker { #pragma mark button actions - (void)today { + + CGFloat hour; if (dayPicker.delegate && [dayPicker.delegate datePickerControl:dayPicker willChangeToDate:[NSDate date]] == NO) { + dayPicker.date = [[NSUserDefaults standardUserDefaults] objectForKey:@"start_date"]; + hour = 9; } else { dayPicker.date = [NSDate date]; + NSCalendar* calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar]; + NSDateComponents* components = [calendar components:NSHourCalendarUnit fromDate:[NSDate date]]; + hour = [components hour]; + + } self.date = dayPicker.date; @@ -64,10 +73,8 @@ - (void)today { [self reloadDayAnimated:NO context:NULL]; - NSCalendar* calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar]; - NSDateComponents* components = [calendar components:NSHourCalendarUnit fromDate:[NSDate date]]; - [self.dayView scrollToHour:[components hour] - 0.5 animated:YES]; + [self.dayView scrollToHour:hour - 0.5 animated:YES]; } - (void)add { From 4bb458bd863bb8b877bdfa8cbe4b1c7b5b030ed4 Mon Sep 17 00:00:00 2001 From: Jon Manning Date: Tue, 4 Sep 2012 22:56:23 +1000 Subject: [PATCH 25/26] Even nicer behaviour for the Now button --- GCCalendar/GCCalendarDayView.m | 3 +++ GCCalendar/GCCalendarPortraitViewController.m | 8 +++++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/GCCalendar/GCCalendarDayView.m b/GCCalendar/GCCalendarDayView.m index 4e15141..ad4a58a 100644 --- a/GCCalendar/GCCalendarDayView.m +++ b/GCCalendar/GCCalendarDayView.m @@ -408,6 +408,9 @@ - (void)reloadData { [scrollView addSubview:todayView]; } +- (void)setContentOffset:(CGPoint)contentOffset { + scrollView.contentOffset = contentOffset; +} - (CGPoint)contentOffset { return scrollView.contentOffset; diff --git a/GCCalendar/GCCalendarPortraitViewController.m b/GCCalendar/GCCalendarPortraitViewController.m index a25e181..46f18a6 100644 --- a/GCCalendar/GCCalendarPortraitViewController.m +++ b/GCCalendar/GCCalendarPortraitViewController.m @@ -53,11 +53,12 @@ - (void)datePickerDidChangeDate:(GCDatePickerControl *)picker { - (void)today { CGFloat hour; + + CGPoint currentContentOffset = self.dayView.contentOffset; if (dayPicker.delegate && [dayPicker.delegate datePickerControl:dayPicker willChangeToDate:[NSDate date]] == NO) { dayPicker.date = [[NSUserDefaults standardUserDefaults] objectForKey:@"start_date"]; hour = 9; - } else { dayPicker.date = [NSDate date]; NSCalendar* calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar]; @@ -68,12 +69,13 @@ - (void)today { } self.date = dayPicker.date; - + [[NSUserDefaults standardUserDefaults] setObject:date forKey:@"GCCalendarDate"]; [self reloadDayAnimated:NO context:NULL]; - + [self.dayView setContentOffset:currentContentOffset]; + [self.dayView scrollToHour:hour - 0.5 animated:YES]; } From 477c3c1399065421c68babdd20a1745be8b2c301 Mon Sep 17 00:00:00 2001 From: Jon Manning Date: Wed, 5 Sep 2012 18:38:11 +1000 Subject: [PATCH 26/26] Don't enable the back/next buttons unnecessarily when the calendar is created. --- GCCalendar/GCCalendarPortraitViewController.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GCCalendar/GCCalendarPortraitViewController.m b/GCCalendar/GCCalendarPortraitViewController.m index 46f18a6..208b924 100644 --- a/GCCalendar/GCCalendarPortraitViewController.m +++ b/GCCalendar/GCCalendarPortraitViewController.m @@ -116,8 +116,8 @@ - (void)viewDidLoad { dayPicker = [[GCDatePickerControl alloc] init]; dayPicker.frame = CGRectMake(0, 0, self.view.frame.size.width, 0); dayPicker.autoresizingMask = UIViewAutoresizingNone; - dayPicker.date = date; dayPicker.delegate = self; + dayPicker.date = date; [dayPicker addTarget:self action:@selector(datePickerDidChangeDate:) forControlEvents:UIControlEventValueChanged]; [self.view addSubview:dayPicker];