Browse files

New feature: show and select arbitrary dates

1) When creating a KalViewController, you can now specify the initial selected date (before it always just displayed and selected today's date)
2) You can now send a message to KalViewController to show and select an arbitrary date (before you could only tell it to show today's date).
  • Loading branch information...
1 parent 8fa33f4 commit a501cc4010ba8ff953e9f61b0fd71c8fa53ec454 @klazuka klazuka committed Mar 11, 2010
View
4 HolidaysDemo/HolidayAppDelegate.h
@@ -25,10 +25,14 @@
* the navigation stack.
*
*/
+
+@class KalViewController;
+
@interface HolidayAppDelegate : NSObject <UIApplicationDelegate, UITableViewDelegate>
{
UIWindow *window;
UINavigationController *navController;
+ KalViewController *kal;
id dataSource;
}
View
38 HolidaysDemo/HolidayAppDelegate.m
@@ -4,7 +4,6 @@
*/
#import "HolidayAppDelegate.h"
-#import "HolidayJSONDataSource.h"
#import "HolidaySqliteDataSource.h"
#import "HolidaysDetailViewController.h"
#import "Kal.h"
@@ -15,22 +14,44 @@ @implementation HolidayAppDelegate
- (void)applicationDidFinishLaunching:(UIApplication *)application
{
- // I provide several different dataSource examples. Pick one by commenting out the others.
- dataSource = [[HolidayJSONDataSource alloc] init];
-// dataSource = [[HolidaySqliteDataSource alloc] init];
- KalViewController *kal = [[KalViewController alloc] init];
+ /*
+ * Kal Initialization
+ *
+ * When the calendar is first displayed to the user, Kal will automatically select today's date.
+ * If your application requires an arbitrary starting date, use -[KalViewController initWithSelectedDate:]
+ * instead of -[KalViewController init].
+ */
+ kal = [[KalViewController alloc] init];
+
+ /*
+ * Kal Configuration
+ *
+ * This demo app includes 2 example datasources for the Kal component. Both datasources
+ * contain 2009 and 2010 world holidays, however, one datasource retrieves the data
+ * from a remote web server using JSON while the other datasource retrieves the data
+ * from a local Sqlite database. For this demo, I am going to set it up to just use
+ * the Sqlite database.
+ */
+ kal.navigationItem.rightBarButtonItem = [[[UIBarButtonItem alloc] initWithTitle:@"Today" style:UIBarButtonItemStyleBordered target:self action:@selector(showAndSelectToday)] autorelease];
kal.delegate = self;
+ dataSource = [[HolidaySqliteDataSource alloc] init];
kal.dataSource = dataSource;
- kal.navigationItem.rightBarButtonItem = [[[UIBarButtonItem alloc] initWithTitle:@"Today" style:UIBarButtonItemStyleBordered target:kal action:@selector(showAndSelectToday)] autorelease];
+
+ // Setup the navigation stack and display it.
navController = [[UINavigationController alloc] initWithRootViewController:kal];
- [kal release];
-
[window addSubview:navController.view];
[window makeKeyAndVisible];
}
+// Action handler for the navigation bar's right bar button item.
+- (void)showAndSelectToday
+{
+ [kal showAndSelectDate:[NSDate date]];
+}
+
#pragma mark UITableViewDelegate protocol conformance
+// Display a details screen for the selected holiday/row.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
Holiday *holiday = [dataSource holidayAtIndexPath:indexPath];
@@ -43,6 +64,7 @@ - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath
- (void)dealloc
{
+ [kal release];
[dataSource release];
[window release];
[navController release];
View
4 Kal/KalGridView.h
@@ -27,13 +27,11 @@
BOOL transitioning;
}
-@property (nonatomic, retain) KalTileView *selectedTile;
-@property (nonatomic, retain) KalTileView *highlightedTile;
@property (nonatomic, readonly) BOOL transitioning;
@property (nonatomic, readonly) KalDate *selectedDate;
- (id)initWithFrame:(CGRect)frame logic:(KalLogic *)logic delegate:(id<KalViewDelegate>)delegate;
-- (void)selectTodayIfVisible;
+- (void)selectDateIfVisible:(KalDate *)date;
- (void)markTilesForDates:(NSArray *)dates;
// These 3 methods should be called *after* the KalLogic
View
18 Kal/KalGridView.m
@@ -22,7 +22,8 @@
static NSString *kSlideAnimationId = @"KalSwitchMonths";
@interface KalGridView ()
-- (void)selectTodayIfVisible;
+@property (nonatomic, retain) KalTileView *selectedTile;
+@property (nonatomic, retain) KalTileView *highlightedTile;
- (void)swapMonthViews;
@end
@@ -55,7 +56,6 @@ - (id)initWithFrame:(CGRect)frame logic:(KalLogic *)theLogic delegate:(id<KalVie
[self addSubview:frontMonthView];
[self jumpToSelectedMonth];
- [self selectTodayIfVisible];
}
return self;
}
@@ -201,7 +201,7 @@ - (void)slide:(int)direction
// that is sliding offscreen.
BOOL keepOneRow = (direction == SLIDE_UP && [logic.daysInFinalWeekOfPreviousMonth count] > 0)
- || (direction == SLIDE_DOWN && [logic.daysInFirstWeekOfFollowingMonth count] > 0);
+ || (direction == SLIDE_DOWN && [logic.daysInFirstWeekOfFollowingMonth count] > 0);
[self swapMonthsAndSlide:direction keepOneRow:keepOneRow];
@@ -219,18 +219,18 @@ - (void)animationDidStop:(NSString *)animationID finished:(NSNumber *)finished c
#pragma mark -
-- (void)selectTodayIfVisible
+- (void)selectDateIfVisible:(KalDate *)date
{
- KalTileView *todayTile = [frontMonthView todaysTileIfVisible];
- if (todayTile)
- self.selectedTile = todayTile;
+ KalTileView *tile = [frontMonthView tileForDate:date];
+ if (tile)
+ self.selectedTile = tile;
}
- (void)swapMonthViews
{
KalMonthView *tmp = backMonthView;
- backMonthView = frontMonthView;
- frontMonthView = tmp;
+ backMonthView = frontMonthView;
+ frontMonthView = tmp;
[self exchangeSubviewAtIndex:[self.subviews indexOfObject:frontMonthView] withSubviewAtIndex:[self.subviews indexOfObject:backMonthView]];
}
View
5 Kal/KalLogic.h
@@ -16,6 +16,7 @@
* and provides the logic for switching between months and determining which days
* are in a month as well as which days are in partial weeks adjacent to the selected
* month.
+ *
*/
@interface KalLogic : NSObject
{
@@ -36,8 +37,10 @@
@property (nonatomic, retain, readonly) NSArray *daysInFirstWeekOfFollowingMonth; // array of KalDate
@property (nonatomic, readonly) NSString *selectedMonthNameAndYear; // localized (e.g. "September 2010" for USA locale)
+- (id)initForDate:(NSDate *)date; // designated initializer.
+
- (void)retreatToPreviousMonth;
- (void)advanceToFollowingMonth;
-- (void)moveToTodaysMonth;
+- (void)moveToMonthForDate:(NSDate *)date;
@end
View
16 Kal/KalLogic.m
@@ -30,19 +30,24 @@ + (NSSet *)keyPathsForValuesAffectingSelectedMonthNameAndYear
return [NSSet setWithObjects:@"baseDate", nil];
}
-- (id)init
+- (id)initForDate:(NSDate *)date
{
if ((self = [super init])) {
monthAndYearFormatter = [[NSDateFormatter alloc] init];
[monthAndYearFormatter setDateFormat:@"MMMM yyyy"];
- [self moveToMonthForDate:[[NSDate date] cc_dateByMovingToFirstDayOfTheMonth]];
+ [self moveToMonthForDate:date];
}
return self;
}
+- (id)init
+{
+ return [self initForDate:[NSDate date]];
+}
+
- (void)moveToMonthForDate:(NSDate *)date
{
- self.baseDate = date;
+ self.baseDate = [date cc_dateByMovingToFirstDayOfTheMonth];
[self recalculateVisibleDays];
}
@@ -56,11 +61,6 @@ - (void)advanceToFollowingMonth
[self moveToMonthForDate:[self.baseDate cc_dateByMovingToFirstDayOfTheFollowingMonth]];
}
-- (void)moveToTodaysMonth
-{
- [self moveToMonthForDate:[[NSDate date] cc_dateByMovingToFirstDayOfTheMonth]];
-}
-
- (NSString *)selectedMonthNameAndYear;
{
return [monthAndYearFormatter stringFromDate:self.baseDate];
View
1 Kal/KalMonthView.h
@@ -14,7 +14,6 @@
- (id)initWithFrame:(CGRect)rect; // designated initializer
- (void)showDates:(NSArray *)mainDates leadingAdjacentDates:(NSArray *)leadingAdjacentDates trailingAdjacentDates:(NSArray *)trailingAdjacentDates;
-- (KalTileView *)todaysTileIfVisible;
- (KalTileView *)firstTileOfMonth;
- (KalTileView *)tileForDate:(KalDate *)date;
- (void)markTilesForDates:(NSArray *)dates;
View
13 Kal/KalMonthView.m
@@ -59,19 +59,6 @@ - (void)drawRect:(CGRect)rect
CGContextDrawTiledImage(ctx, (CGRect){CGPointZero,kTileSize}, [[UIImage imageNamed:@"kal_tile.png"] CGImage]);
}
-- (KalTileView *)todaysTileIfVisible
-{
- KalTileView *tile = nil;
- for (KalTileView *t in self.subviews) {
- if ([t isToday]) {
- tile = t;
- break;
- }
- }
-
- return tile;
-}
-
- (KalTileView *)firstTileOfMonth
{
KalTileView *tile = nil;
View
2 Kal/KalView.h
@@ -51,7 +51,7 @@
- (id)initWithFrame:(CGRect)frame delegate:(id<KalViewDelegate>)delegate logic:(KalLogic *)logic;
- (BOOL)isSliding;
-- (void)selectTodayIfVisible;
+- (void)selectDateIfVisible:(KalDate *)date;
- (void)markTilesForDates:(NSArray *)dates;
// These 3 methods are exposed for the delegate. They should be called
View
2 Kal/KalView.m
@@ -205,7 +205,7 @@ - (void)setHeaderTitleText:(NSString *)text
- (void)jumpToSelectedMonth { [gridView jumpToSelectedMonth]; }
-- (void)selectTodayIfVisible { [gridView selectTodayIfVisible]; }
+- (void)selectDateIfVisible:(KalDate *)date { [gridView selectDateIfVisible:date]; }
- (BOOL)isSliding { return gridView.transitioning; }
View
4 Kal/KalViewController.h
@@ -25,12 +25,14 @@
UITableView *tableView;
id <UITableViewDelegate> delegate;
id <KalDataSource> dataSource;
+ NSDate *initialSelectedDate;
}
@property (nonatomic, assign) id<UITableViewDelegate> delegate;
@property (nonatomic, assign) id<KalDataSource> dataSource;
+- (id)initWithSelectedDate:(NSDate *)selectedDate; // designated initializer. When the calendar is first displayed to the user, the month that contains 'selectedDate' will be shown and the corresponding tile for 'selectedDate' will be automatically selected.
- (void)reloadData; // If you change the KalDataSource after the KalViewController has already been displayed to the user, you must call this method in order for the view to reflect the new data.
-- (void)showAndSelectToday; // Updates the state of the calendar to display today's month and selects the tile for today's date.
+- (void)showAndSelectDate:(NSDate *)date; // Updates the state of the calendar to display the specified date's month and selects the tile for that date.
@end
View
23 Kal/KalViewController.m
@@ -36,6 +36,20 @@ @implementation KalViewController
@synthesize dataSource, delegate;
+- (id)initWithSelectedDate:(NSDate *)selectedDate
+{
+ if ((self = [super init])) {
+ logic = [[KalLogic alloc] initForDate:selectedDate];
+ initialSelectedDate = [selectedDate retain];
+ }
+ return self;
+}
+
+- (id)init
+{
+ return [self initWithSelectedDate:[NSDate date]];
+}
+
- (KalView*)calendarView { return (KalView*)self.view; }
- (void)setDataSource:(id<KalDataSource>)aDataSource
@@ -115,12 +129,12 @@ - (void)loadedDataSource:(id<KalDataSource>)theDataSource;
// ---------------------------------------
#pragma mark -
-- (void)showAndSelectToday
+- (void)showAndSelectDate:(NSDate *)date
{
if ([[self calendarView] isSliding])
return;
- [logic moveToTodaysMonth];
+ [logic moveToMonthForDate:date];
#if PROFILER
uint64_t start, end;
@@ -136,7 +150,7 @@ - (void)showAndSelectToday
printf("[[self calendarView] jumpToSelectedMonth]: %.1f ms\n", tp.tv_nsec / 1e6);
#endif
- [[self calendarView] selectTodayIfVisible];
+ [[self calendarView] selectDateIfVisible:[KalDate dateFromNSDate:date]];
[self reloadData];
}
@@ -146,14 +160,14 @@ - (void)showAndSelectToday
- (void)loadView
{
self.title = @"Calendar";
- logic = [[KalLogic alloc] init];
KalView *kalView = [[KalView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame] delegate:self logic:logic];
self.view = kalView;
tableView = kalView.tableView;
tableView.dataSource = dataSource;
tableView.delegate = delegate;
[tableView retain];
+ [kalView selectDateIfVisible:[KalDate dateFromNSDate:initialSelectedDate]];
[kalView release];
[self reloadData];
}
@@ -174,6 +188,7 @@ - (void)viewDidAppear:(BOOL)animated
- (void)dealloc
{
+ [initialSelectedDate release];
[logic release];
[tableView release];
[super dealloc];

0 comments on commit a501cc4

Please sign in to comment.