Skip to content

Commit

Permalink
Fix for ruslanskorb#48, allow limiting dates in the calendar
Browse files Browse the repository at this point in the history
  • Loading branch information
aryaxt committed Jun 28, 2015
1 parent d2d6c14 commit 034938a
Show file tree
Hide file tree
Showing 4 changed files with 171 additions and 61 deletions.
12 changes: 12 additions & 0 deletions RSDayFlow/RSDFDatePickerDayCell.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,11 @@
*/
@property (nonatomic, getter = isMarked) BOOL marked;

/**
A Boolean value that determines whether the cell is enabled or not.
*/
@property (nonatomic, getter = isDisabled) BOOL disabled;

/**
The color of the default mark image for the cell of the day. Default value is [UIColor colorWithRed:184/255.0f green:184/255.0f blue:184/255.0f alpha:1.0f].
Expand Down Expand Up @@ -124,6 +129,13 @@
*/
- (UIColor *)dayOffLabelTextColor;

/**
The text color for the label of the disabled day (not in range of start/end date set on calendar). Default value is [UIColor colorWithRed:184/255.0f green:184/255.0f blue:184/255.0f alpha:1.0f].
@discussion Can be overridden in subclasses for customization.
*/
- (UIColor *)disabledDayLabelTextColor;

/**
The text color for the label of the day that's not this month. Default value is [UIColor clearColor].
Expand Down
52 changes: 32 additions & 20 deletions RSDayFlow/RSDFDatePickerDayCell.m
Original file line number Diff line number Diff line change
Expand Up @@ -213,31 +213,38 @@ - (void)updateSubviews
self.overlayImageView.hidden = !self.isHighlighted || self.isNotThisMonth;
self.markImageView.hidden = !self.isMarked || self.isNotThisMonth;
self.dividerImageView.hidden = self.isNotThisMonth;

self.userInteractionEnabled = YES;

if (self.isNotThisMonth) {
self.dateLabel.textColor = [self notThisMonthLabelTextColor];
self.dateLabel.font = [self dayLabelFont];
} else {
if (!self.isSelected) {
if (!self.isToday) {
self.dateLabel.font = [self dayLabelFont];
if (!self.dayOff) {
if (self.isPastDate) {
self.dateLabel.textColor = [self pastDayLabelTextColor];
} else {
self.dateLabel.textColor = [self dayLabelTextColor];
}
} else {
if (self.isPastDate) {
self.dateLabel.textColor = [self pastDayOffLabelTextColor];
} else {
self.dateLabel.textColor = [self dayOffLabelTextColor];
}
}
} else {
self.dateLabel.font = [self todayLabelFont];
self.dateLabel.textColor = [self todayLabelTextColor];
}
if (self.disabled) {
self.userInteractionEnabled = NO;
self.dateLabel.textColor = [self disabledDayLabelTextColor];
}
else {
if (!self.isToday) {
self.dateLabel.font = [self dayLabelFont];
if (!self.dayOff) {
if (self.isPastDate) {
self.dateLabel.textColor = [self pastDayLabelTextColor];
} else {
self.dateLabel.textColor = [self dayLabelTextColor];
}
} else {
if (self.isPastDate) {
self.dateLabel.textColor = [self pastDayOffLabelTextColor];
} else {
self.dateLabel.textColor = [self dayOffLabelTextColor];
}
}
} else {
self.dateLabel.font = [self todayLabelFont];
self.dateLabel.textColor = [self todayLabelTextColor];
}
}
} else {
if (!self.isToday) {
self.dateLabel.font = [self selectedDayLabelFont];
Expand Down Expand Up @@ -339,6 +346,11 @@ - (UIColor *)dayOffLabelTextColor
return [UIColor colorWithRed:184/255.0f green:184/255.0f blue:184/255.0f alpha:1.0f];
}

- (UIColor *)disabledDayLabelTextColor
{
return [UIColor colorWithRed:184/255.0f green:184/255.0f blue:184/255.0f alpha:1.0f];
}

- (UIColor *)notThisMonthLabelTextColor
{
return [UIColor clearColor];
Expand Down
11 changes: 11 additions & 0 deletions RSDayFlow/RSDFDatePickerView.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,17 @@
*/
- (instancetype)initWithFrame:(CGRect)frame calendar:(NSCalendar *)calendar;


/**
Designated initializer. Initializes and returns a newly allocated view object with the specified frame rectangle and the specified calendar.
@param frame The frame rectangle for the view, measured in points.
@param calendar The calendar for the date picker view.
@param startDate First selectable date
@param endDate Last selectable date
*/
- (instancetype)initWithFrame:(CGRect)frame calendar:(NSCalendar *)calendar startDate:(NSDate *)startDate endDate:(NSDate *)endDate;

///-----------------------------
/// @name Accessing the Delegate
///-----------------------------
Expand Down
157 changes: 116 additions & 41 deletions RSDayFlow/RSDFDatePickerView.m
Original file line number Diff line number Diff line change
Expand Up @@ -39,15 +39,22 @@
@interface RSDFDatePickerView () <RSDFDatePickerCollectionViewDelegate>

@property (nonatomic, readonly, strong) NSCalendar *calendar;
@property (nonatomic, readonly, assign) RSDFDatePickerDate fromDate;
@property (nonatomic, readonly, assign) RSDFDatePickerDate toDate;
@property (nonatomic, readonly, strong) RSDFDatePickerDaysOfWeekView *daysOfWeekView;
@property (nonatomic, readonly, strong) RSDFDatePickerCollectionView *collectionView;
@property (nonatomic, readonly, strong) RSDFDatePickerCollectionViewLayout *collectionViewLayout;
@property (nonatomic, readonly, strong) NSDate *today;
@property (nonatomic, readonly, assign) NSUInteger daysInWeek;
@property (nonatomic, readonly, strong) NSDate *selectedDate;

// From and to date are the currently displayed dates in the calendar
// These values change in infinite scrolling mode
@property (nonatomic, readonly, assign) RSDFDatePickerDate fromDate;
@property (nonatomic, readonly, assign) RSDFDatePickerDate toDate;

// start and end date are date limits displayed in the calendar (No infinite scrolling)
@property (nonatomic, readonly, strong) NSDate *startDate;
@property (nonatomic, readonly, strong) NSDate *endDate;

@end

@implementation RSDFDatePickerView
Expand Down Expand Up @@ -85,13 +92,20 @@ - (instancetype)initWithFrame:(CGRect)frame
return self;
}

- (instancetype)initWithFrame:(CGRect)frame calendar:(NSCalendar *)calendar startDate:(NSDate *)startDate endDate:(NSDate *)endDate {
self = [super initWithFrame:frame];
if (self) {
_startDate = startDate;
_endDate = endDate;
_calendar = calendar;
[self commonInitializer];
}
return self;
}

- (instancetype)initWithFrame:(CGRect)frame calendar:(NSCalendar *)calendar
{
self = [super initWithFrame:frame];
if (self) {
_calendar = calendar;
[self commonInitializer];
}
self = [self initWithFrame:frame calendar:calendar startDate:nil endDate:nil];
return self;
}

Expand Down Expand Up @@ -253,19 +267,25 @@ - (void)scrollToDate:(NSDate *)date animated:(BOOL)animated

NSDateComponents *dateYearMonthComponents = [self.calendar components:(NSCalendarUnitYear | NSCalendarUnitMonth) fromDate:date];
NSDate *month = [self.calendar dateFromComponents:dateYearMonthComponents];

_fromDate = [self pickerDateFromDate:[self.calendar dateByAddingComponents:((^{
NSDateComponents *components = [NSDateComponents new];
components.month = -6;
return components;
})()) toDate:month options:0]];

_toDate = [self pickerDateFromDate:[self.calendar dateByAddingComponents:((^{
NSDateComponents *components = [NSDateComponents new];
components.month = 6;
return components;
})()) toDate:month options:0]];


// If startDate exists don't try to update toDate because it was done on init, and date limit should remain
if (!self.startDate) {
_fromDate = [self pickerDateFromDate:[self.calendar dateByAddingComponents:((^{
NSDateComponents *components = [NSDateComponents new];
components.month = -6;
return components;
})()) toDate:month options:0]];
}

// If endDate exists don't try to update toDate because it was done on init, and date limit should remain
if (!self.endDate) {
_toDate = [self pickerDateFromDate:[self.calendar dateByAddingComponents:((^{
NSDateComponents *components = [NSDateComponents new];
components.month = 6;
return components;
})()) toDate:month options:0]];
}

[cv reloadData];
[cvLayout invalidateLayout];
[cvLayout prepareLayout];
Expand Down Expand Up @@ -324,23 +344,76 @@ - (void)reloadData

#pragma mark - Private

- (BOOL)isCellEnabledAtIndexPath:(RSDFDatePickerDayCell *)cell indexPath:(NSIndexPath *)indexPath {
if (cell.isNotThisMonth) {
return NO;
}

NSDate *date = cell ? [self dateFromPickerDate:cell.date] : nil;
NSDate *dateWithoutTime = date ? [self dateWithoutTimeComponents:date] : nil;

if (self.startDate &&
[dateWithoutTime compare:[self dateWithoutTimeComponents:self.startDate]] == NSOrderedAscending) {

return NO;
}

if (self.endDate &&
[dateWithoutTime compare:[self dateWithoutTimeComponents:self.endDate]] == NSOrderedDescending) {

return NO;
}

return YES;
}

- (NSDate *)dateWithoutTimeComponents:(NSDate *)date
{
NSDateComponents *dateComponents = [self.calendar components:NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit fromDate:date];
return [self.calendar dateFromComponents:dateComponents];
}

- (NSDate *)dateWithFirstDayOfMonth:(NSDate *)date
{
NSDateComponents *dateComponents = [self.calendar components:NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit fromDate:date];
dateComponents.day = 1;
return [self.calendar dateFromComponents:dateComponents];
}

- (NSDate *)dateByMovingToEndOfMonth:(NSDate *)date {
NSDateComponents *components = [self.calendar components:NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit fromDate:date];

components.month = components.month + 1;
return [self.calendar dateFromComponents:components];
}

- (void)commonInitializer
{
NSDateComponents *nowYearMonthComponents = [self.calendar components:(NSCalendarUnitYear | NSCalendarUnitMonth) fromDate:[NSDate date]];
NSDate *now = [self.calendar dateFromComponents:nowYearMonthComponents];

_fromDate = [self pickerDateFromDate:[self.calendar dateByAddingComponents:((^{
NSDateComponents *components = [NSDateComponents new];
components.month = -6;
return components;
})()) toDate:now options:0]];

_toDate = [self pickerDateFromDate:[self.calendar dateByAddingComponents:((^{
NSDateComponents *components = [NSDateComponents new];
components.month = 6;
return components;
})()) toDate:now options:0]];


if (self.startDate) {
_fromDate = [self pickerDateFromDate:[self dateWithFirstDayOfMonth:self.startDate]];
}
else {
_fromDate = [self pickerDateFromDate:[self.calendar dateByAddingComponents:((^{
NSDateComponents *components = [NSDateComponents new];
components.month = -6;
return components;
})()) toDate:now options:0]];
}

if (self.endDate) {
_toDate = [self pickerDateFromDate:[self dateByMovingToEndOfMonth:self.endDate]];
}
else {
_toDate = [self pickerDateFromDate:[self.calendar dateByAddingComponents:((^{
NSDateComponents *components = [NSDateComponents new];
components.month = 6;
return components;
})()) toDate:now options:0]];
}

NSDateComponents *todayYearMonthDayComponents = [self.calendar components:(NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay) fromDate:[NSDate date]];
_today = [self.calendar dateFromComponents:todayYearMonthDayComponents];

Expand Down Expand Up @@ -647,6 +720,7 @@ - (RSDFDatePickerDayCell *)collectionView:(UICollectionView *)collectionView cel
NSComparisonResult result = [_today compare:cellDate];
cell.today = (result == NSOrderedSame);
cell.pastDate = (result == NSOrderedDescending);
cell.disabled = ![self isCellEnabledAtIndexPath:cell indexPath:indexPath];
}

[cell setNeedsDisplay];
Expand Down Expand Up @@ -727,13 +801,14 @@ - (void)collectionView:(UICollectionView *)collectionView didUnhighlightItemAtIn

- (BOOL)collectionView:(UICollectionView *)collectionView shouldSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
if (((RSDFDatePickerDayCell *)[collectionView cellForItemAtIndexPath:indexPath]).isNotThisMonth) {
return NO;
}

RSDFDatePickerDayCell *cell = ((RSDFDatePickerDayCell *)[self.collectionView cellForItemAtIndexPath:indexPath]);

if (![self isCellEnabledAtIndexPath:cell indexPath:indexPath]) {
return NO;
}

if ([self.delegate respondsToSelector:@selector(datePickerView:shouldSelectDate:)]) {
RSDFDatePickerDayCell *cell = ((RSDFDatePickerDayCell *)[collectionView cellForItemAtIndexPath:indexPath]);
NSDate *date = cell ? [self dateFromPickerDate:cell.date] : nil;
NSDate *date = cell ? [self dateFromPickerDate:cell.date] : nil;
return [self.delegate datePickerView:self shouldSelectDate:date];
}

Expand Down Expand Up @@ -783,11 +858,11 @@ - (void)pickerCollectionViewWillLayoutSubviews:(RSDFDatePickerCollectionView *)p
// 118.0ms 1.7% 118.0 _objc_rootReleaseWasZero
// 105.0ms 1.5% 105.0 DYLD-STUB$$CFDictionarySetValue$shim

if (pickerCollectionView.contentOffset.y < 0.0f) {
if (!self.startDate && pickerCollectionView.contentOffset.y < 0.0f) {
[self appendPastDates];
}

if (pickerCollectionView.contentOffset.y > (pickerCollectionView.contentSize.height - CGRectGetHeight(pickerCollectionView.bounds))) {
if (!self.endDate && pickerCollectionView.contentOffset.y > (pickerCollectionView.contentSize.height - CGRectGetHeight(pickerCollectionView.bounds))) {
[self appendFutureDates];
}
}
Expand Down

0 comments on commit 034938a

Please sign in to comment.