Skip to content

Instantly share code, notes, and snippets.

@bencochran
Last active December 22, 2015 05:58
Show Gist options
  • Save bencochran/6427385 to your computer and use it in GitHub Desktop.
Save bencochran/6427385 to your computer and use it in GitHub Desktop.

Revisions

  1. bencochran revised this gist Sep 6, 2013. 2 changed files with 70 additions and 0 deletions.
    54 changes: 54 additions & 0 deletions MOAnnotatedCalendarView.h
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,54 @@
    //
    // MOAnnotatedCalendarView.h
    // MOKit
    //
    // Created by Ben Cochran on 9/4/13.
    // Copyright (c) 2013 Ben Cochran. All rights reserved.
    //

    #import "MOCalendarView.h"

    @class MOAnnotatedCalendarView;
    @class MOCalendarAnnotation;

    @protocol MOAnnotatedCalendarViewDelegate <MOCalendarViewDelegate>
    @optional

    - (MOCalendarAnnotation *)annotatedCalendarView:(MOAnnotatedCalendarView *)annotatedCalendarView annotationForSelectedRange:(MOCalendarRange *)selection;

    /**
    * Called before an annotation is displayed.
    *
    * @param annotatedCalendarView
    * The calendar in which the tool tip will be displayed
    * @param annotation
    * The annotation that will be displayed
    * @param day
    * The day on which the annotation will be displayed
    *
    * @return
    * An annotation to be displayed. Return an `MOCalendarAnnotation` other
    * than the one provided to modify the annotation content. Return `nil` to
    * prevent any annotation from being displayed.
    */
    - (MOCalendarAnnotation *)annotatedCalendarView:(MOAnnotatedCalendarView *)annotatedCalendarView shouldDisplayAnnotation:(MOCalendarAnnotation *)annotation fromDay:(NSDateComponents *)day;


    - (void)annotatedCalendarView:(MOAnnotatedCalendarView *)annotatedCalendarView willDisplayAnnotation:(MOCalendarAnnotation *)annotation fromDay:(NSDateComponents *)day;

    - (void)annotatedCalendarView:(MOAnnotatedCalendarView *)annotatedCalendarView didDisplayAnnotation:(MOCalendarAnnotation *)annotation fromDay:(NSDateComponents *)day;

    //- (void)annotatedCalendarView:(MOAnnotatedCalendarView *)annotatedCalendarView willRemoveAnnotation:(MOCalendarAnnotation *)annotation fromDay:(NSDateComponents *)day

    @end

    @interface MOAnnotatedCalendarView : MOCalendarView

    @property (nonatomic, weak) id<MOAnnotatedCalendarViewDelegate> delegate;

    - (void)displayAnnotation:(MOCalendarAnnotation *)annotation fromDay:(NSDateComponents *)day animated:(BOOL)animated;

    - (void)removeAnnotationAnimated:(BOOL)animated;
    - (void)hideAnnotationAnimated:(BOOL)animated;

    @end
    16 changes: 16 additions & 0 deletions MOCalendarAnnotation.h
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,16 @@
    //
    // MOCalendarAnnotation.h
    // MOKit
    //
    // Created by Ben Cochran on 9/4/13.
    // Copyright (c) 2013 Ben Cochran. All rights reserved.
    //

    @interface MOCalendarAnnotation : NSObject

    - (id)initWithTitle:(NSString *)title subtitle:(NSString *)subtitle;

    @property (nonatomic, copy, readonly) NSString *title;
    @property (nonatomic, copy, readonly) NSString *subtitle;

    @end
  2. bencochran revised this gist Sep 6, 2013. 2 changed files with 178 additions and 6 deletions.
    16 changes: 14 additions & 2 deletions MOCalendarRange.h
    Original file line number Diff line number Diff line change
    @@ -1,7 +1,17 @@
    //
    // MOCalendarRange.h
    // MOKit
    //
    // Created by Ben Cochran on 8/30/13.
    // Copyright (c) 2013 Ben Cochran. All rights reserved.
    //

    @interface MOCalendarRange : NSObject <NSCopying, NSMutableCopying>

    + (instancetype)rangeWithCalendar:(NSCalendar *)calendar startDay:(NSDateComponents *)startDay endDay:(NSDateComponents *)endDay;

    - (id)initWithCalendar:(NSCalendar *)calendar startDay:(NSDateComponents *)startDay endDay:(NSDateComponents *)endDay;
    @property (nonatomic, copy, readonly) NSCalendar *calendar;
    @property (nonatomic, strong, readonly) NSCalendar *calendar;

    /**
    * The starting day of the selection.
    @@ -17,6 +27,8 @@

    /**
    * The ending day of the selection.
    *
    * @see Note on `startDay` for information about `startDay` and `endDay` ordering
    */
    @property (nonatomic, copy, readonly) NSDateComponents *endDay;

    @@ -55,6 +67,6 @@
    * Returns the current length (number of days) of the range. If `startDay` or
    * `endDay` or both are nil, the length is defined as 0.
    */
    @property (nonatomic, readonly) NSUInteger length;
    @property (nonatomic, readonly) NSInteger length;

    @end
    168 changes: 164 additions & 4 deletions MOCalendarView.h
    Original file line number Diff line number Diff line change
    @@ -1,21 +1,43 @@
    //
    // MOCalendarView.h
    // MOKit
    //
    // Created by Ben Cochran on 8/30/13.
    // Copyright (c) 2013 Ben Cochran. All rights reserved.
    //

    @class MOMutableCalendarRange;
    @class MOCalendarScrollView;
    @class MOCalendarRange;
    @class MOCalendarView;

    extern NSCalendarUnit const MOCalendarUnitsDMY;
    extern NSCalendarUnit const MOCalendarUnitsMY;

    typedef NS_ENUM(NSUInteger, MOCalendarSelectionStyle) {
    MOCalendarSelectionStyleSingleDay,
    MOCalendarSelectionStyleMultiDay
    };

    @protocol MOCalendarViewDelegate <NSObject>
    @optional
    - (void)calendarView:(MOCalendarView *)calendarView willBeginChangingSelection:(MOCalendarRange *)newSelection;
    - (void)calendarViewDidBeginChangingSelection:(MOCalendarView *)calendarView;
    - (void)calendarView:(MOCalendarView *)calendarView willChangeSelection:(MOCalendarRange *)newSelection;
    - (void)calendarViewDidChangeSelection:(MOCalendarView *)calendarView;
    - (void)calendarView:(MOCalendarView *)calendarView willFinishChangingSelection:(MOCalendarRange *)newSelection;
    - (void)calendarViewDidFinishChangingSelection:(MOCalendarView *)calendarView;

    - (void)calendarView:(MOCalendarView *)calendarView willChangeToVisibleMonth:(NSDateComponents *)month;
    - (void)calendarView:(MOCalendarView *)calendarView didChangeToVisibleMonth:(NSDateComponents *)month;
    @end


    @interface MOCalendarView : UIView

    - (id)initWithCalendar:(NSCalendar *)calendar;
    - (id)initWithFrame:(CGRect)frame calendar:(NSCalendar *)calendar;

    @property (nonatomic, copy, readonly) NSCalendar *calendar;

    @property (nonatomic, weak) id<MOCalendarViewDelegate> delegate;

    /**
    @@ -28,12 +50,32 @@
    * The range of dates to allow for selection. Additionally, the calendar will
    * not allow the user to navigate to a month outside this range. If either
    * the selection `startDay` or `endDay` are `nil` that direction will be
    * unbounded
    * unbounded.
    */
    @property (nonatomic, copy) MOCalendarRange *validRange;

    /**
    * The currently-selected date range.
    * The selection style (single or multi-day).
    */
    @property (nonatomic, assign) MOCalendarSelectionStyle selectionStyle;

    /**
    * The minimum length to allow for selection. The calendar will prevent
    * dragging a selection shorter than this. Defaults to 0 (no minimum).
    */
    @property (nonatomic, assign) NSInteger minimumSelectionLength;

    /**
    * The maximum length to allow for selection. The calendar will prevent
    * dragging a selection longer than this. Defaults to `NSIntegerMax` (no
    * maximum).
    */
    @property (nonatomic, assign) NSInteger maximumSelectionLength;

    /**
    * The selected date range. This value is updated live while data selection is
    * being dragged. Setting this value will update the display and call
    * appropriate delegate methods.
    */
    @property (nonatomic, copy) MOCalendarRange *selectedRange;

    @@ -46,6 +88,7 @@
    @property (nonatomic, copy) NSDateComponents *visibleMonth;
    - (void)setVisibleMonth:(NSDateComponents *)visibleMonth animated:(BOOL)animated;


    /**
    * A subclass of `MOCalendarHeaderView` (or `MOCalendarHeaderView` itself) to
    * be used to draw the calendar header.
    @@ -58,4 +101,121 @@
    */
    @property (nonatomic, strong) Class dayViewClass;

    /**
    * The `NSDateFormatter` to be used to create weekday labels in the calendar
    * header. Defaults to localized single-day labels (S, M, T, etc.).
    */
    @property (nonatomic, strong) NSDateFormatter *weekdayLabelFormatter;

    /**
    * The `NSDateFormatter` to be used to display the current month in the
    * calendar header. Defaults to localized month name and full year (e.g.
    * “October 2013” in US_en).
    */
    @property (nonatomic, strong) NSDateFormatter *currentMonthFormatter;

    /**
    * Returns the frame of given day in the receiver's coorinate space.
    *
    * @note This frame may be outside of the receiver's visible bounds
    *
    * @param day The day to find the frame of.
    *
    * @return
    * The day's frame in the receiver's coorinate space or `CGRectZero` if the
    * given day is not loaded in the calendar.
    */
    - (CGRect)frameForDay:(NSDateComponents *)day;


    // Methods for subclasses.

    /**
    * The `MOCalendarScrollView` being used internally to draw the calendar.
    */
    @property (nonatomic, strong, readonly) MOCalendarScrollView *calendarScrollView;

    /**
    * Called before the calendar will change the visible month.
    *
    * @note Subclasses overriding the method must call super.
    *
    * @param month The month that will be displayed
    */
    - (void)willChangeToVisibleMonth:(NSDateComponents *)month;

    /**
    * Called after the calendar has changed the visible month.
    *
    * @note Subclasses overriding the method must call super.
    *
    * @param month The month that was displayed
    */
    - (void)didChangeToVisibleMonth:(NSDateComponents *)month;


    /**
    * Called when the user begins dragging a new selection. Subclasses may modify
    * the selection by changing the properties of the provided
    * `MOMutableCalendarRange`.
    *
    * @note Subclasses overriding the method must call super.
    *
    * @param month
    * The selection that is beginning. Modifying the properties of the range
    * will modify the selection.
    */
    - (void)willBeginChangingSelection:(MOMutableCalendarRange *)newSelection;

    /**
    * Called after the user has begun dragging a new selection (after the
    * selection has been modified and displayed).
    *
    * @note Subclasses overriding the method must call super.
    */
    - (void)didBeginChangingSelection;

    /**
    * Called before the selection is changed either as a result of the user
    * dragging the selection or when setting the selection programmatically.
    * Subclasses may modify the selection by changing the properties of the
    * provided `MOMutableCalendarRange`.
    *
    * @note Subclasses overriding the method must call super.
    *
    * @param month
    * The selection that will be applied. Modifying the properties of the
    * range will modify the selection.
    */
    - (void)willChangeSelection:(MOMutableCalendarRange *)newSelection;

    /**
    * Called after the selection has changed either as a result of the user
    * dragging or when setting the selection programmatically.
    *
    * @note Subclasses overriding the method must call super.
    */
    - (void)didChangeSelection;

    /**
    * Called when the user finished dragging a selection. Subclasses may modify
    * the selection by changing the properties of the provided
    * `MOMutableCalendarRange`.
    *
    * @note Subclasses overriding the method must call super.
    *
    * @param month
    * The selection that is finishing. Modifying the properties of the range
    * will modify the selection.
    */
    - (void)willFinishChangingSelection:(MOMutableCalendarRange *)newSelection;

    /**
    * Called after the user has finished dragging a new selection, after the
    * selection has been modified and displayed.
    *
    * @note Subclasses overriding the method must call super.
    */
    - (void)didFinishChangingSelection;

    @end
  3. bencochran revised this gist Sep 3, 2013. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions MOCalendarView.h
    Original file line number Diff line number Diff line change
    @@ -2,8 +2,8 @@
    @optional
    - (void)calendarView:(MOCalendarView *)calendarView willBeginChangingSelection:(MOCalendarRange *)newSelection;
    - (void)calendarView:(MOCalendarView *)calendarView willChangeSelection:(MOCalendarRange *)newSelection;
    - (void)calendarViewDidChangeSelection:(MOCalendarRange *)calendarView;
    - (void)calendarViewDidFinishChangingSelection:(MOCalendarRange *)calendarView;
    - (void)calendarViewDidChangeSelection:(MOCalendarView *)calendarView;
    - (void)calendarViewDidFinishChangingSelection:(MOCalendarView *)calendarView;

    - (void)calendarView:(MOCalendarView *)calendarView willChangeToVisibleMonth:(NSDateComponents *)month;
    - (void)calendarView:(MOCalendarView *)calendarView didChangeToVisibleMonth:(NSDateComponents *)month;
  4. bencochran revised this gist Sep 3, 2013. 1 changed file with 4 additions and 4 deletions.
    8 changes: 4 additions & 4 deletions MOCalendarView.h
    Original file line number Diff line number Diff line change
    @@ -1,9 +1,9 @@
    @protocol MOCalendarViewDelegate <NSObject>
    @optional
    - (void)calendarView:(MOCalendarView *)calendarView willBeginChangingSelection:(MOCalendarView *)newSelection;
    - (void)calendarView:(MOCalendarView *)calendarView willChangeSelection:(MOCalendarView *)newSelection;
    - (void)calendarViewDidChangeSelection:(MOCalendarView *)calendarView;
    - (void)calendarViewDidFinishChangingSelection:(MOCalendarView *)calendarView;
    - (void)calendarView:(MOCalendarView *)calendarView willBeginChangingSelection:(MOCalendarRange *)newSelection;
    - (void)calendarView:(MOCalendarView *)calendarView willChangeSelection:(MOCalendarRange *)newSelection;
    - (void)calendarViewDidChangeSelection:(MOCalendarRange *)calendarView;
    - (void)calendarViewDidFinishChangingSelection:(MOCalendarRange *)calendarView;

    - (void)calendarView:(MOCalendarView *)calendarView willChangeToVisibleMonth:(NSDateComponents *)month;
    - (void)calendarView:(MOCalendarView *)calendarView didChangeToVisibleMonth:(NSDateComponents *)month;
  5. bencochran revised this gist Sep 3, 2013. 1 changed file with 0 additions and 7 deletions.
    7 changes: 0 additions & 7 deletions MOCalendarView.h
    Original file line number Diff line number Diff line change
    @@ -18,13 +18,6 @@

    @property (nonatomic, weak) id<MOCalendarViewDelegate> delegate;

    /**
    * The index of the weekday to use as the first column in the calendar view.
    *
    * Defaults to the calendar's `firstWeekday`
    */
    @property (nonatomic, assign) NSUInteger firstWeekday;

    /**
    * The day to display highlighted as today. Defaults to the day returned by
    * [NSDate date]
  6. bencochran revised this gist Sep 3, 2013. 1 changed file with 60 additions and 0 deletions.
    60 changes: 60 additions & 0 deletions MOCalendarRange.h
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,60 @@
    @interface MOCalendarRange : NSObject <NSCopying, NSMutableCopying>

    - (id)initWithCalendar:(NSCalendar *)calendar startDay:(NSDateComponents *)startDay endDay:(NSDateComponents *)endDay;
    @property (nonatomic, copy, readonly) NSCalendar *calendar;

    /**
    * The starting day of the selection.
    *
    * ## Note
    *
    * `startDay` does not necessarily come before `endDay` in time. If you need
    * that guarantee you should obtain a normalized copy of the range with
    * `normalizedRange`
    *
    */
    @property (nonatomic, copy, readonly) NSDateComponents *startDay;

    /**
    * The ending day of the selection.
    */
    @property (nonatomic, copy, readonly) NSDateComponents *endDay;

    /**
    * Checks to see if the provided day is contained in the range.
    *
    * @param day The day to check. Must contain `NSCalendarUnitDay`, `NSCalendarUnitMonth` and `NSCalendarUnitYear`
    * @param openEnded If `YES`, the check will treat `nil` `startDay` or `endDay` as a range with an infinite length in that direction.
    *
    * @return `YES` if the range contains the day, otherwise `NO`
    */
    - (BOOL)containsDay:(NSDateComponents *)day openEnded:(BOOL)openEnded;


    /**
    * Checks to see if the provided month is valid for the range. This will return
    * `YES` for any month that that overlaps with the selection at all. (e.g. a
    * selection of 02-14-2013 to 12-01-2014 will return `YES` for `02-2013` and
    * `12-2014` and every month in between, but no others)
    *
    * @param month The month to check. Must contain `NSCalendarUnitMonth` and `NSCalendarUnitYear`
    * @param openEnded If `YES`, the check will treat `nil` `startDay` or `endDay` as a range with an infinite length in that direction.
    *
    * @return `YES` if the month contains any part of the range, otherwise `NO`
    */
    - (BOOL)containsMonth:(NSDateComponents *)month openEnded:(BOOL)openEnded;

    /**
    * Returns a copy of the range where startDay and endDay are ordered temporally
    *
    * @return A copy of the range with startDay and endDay in order
    */
    - (MOCalendarRange *)normalizedRange;

    /**
    * Returns the current length (number of days) of the range. If `startDay` or
    * `endDay` or both are nil, the length is defined as 0.
    */
    @property (nonatomic, readonly) NSUInteger length;

    @end
  7. bencochran created this gist Sep 3, 2013.
    68 changes: 68 additions & 0 deletions MOCalendarView.h
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,68 @@
    @protocol MOCalendarViewDelegate <NSObject>
    @optional
    - (void)calendarView:(MOCalendarView *)calendarView willBeginChangingSelection:(MOCalendarView *)newSelection;
    - (void)calendarView:(MOCalendarView *)calendarView willChangeSelection:(MOCalendarView *)newSelection;
    - (void)calendarViewDidChangeSelection:(MOCalendarView *)calendarView;
    - (void)calendarViewDidFinishChangingSelection:(MOCalendarView *)calendarView;

    - (void)calendarView:(MOCalendarView *)calendarView willChangeToVisibleMonth:(NSDateComponents *)month;
    - (void)calendarView:(MOCalendarView *)calendarView didChangeToVisibleMonth:(NSDateComponents *)month;
    @end


    @interface MOCalendarView : UIView

    - (id)initWithFrame:(CGRect)frame calendar:(NSCalendar *)calendar;

    @property (nonatomic, copy, readonly) NSCalendar *calendar;

    @property (nonatomic, weak) id<MOCalendarViewDelegate> delegate;

    /**
    * The index of the weekday to use as the first column in the calendar view.
    *
    * Defaults to the calendar's `firstWeekday`
    */
    @property (nonatomic, assign) NSUInteger firstWeekday;

    /**
    * The day to display highlighted as today. Defaults to the day returned by
    * [NSDate date]
    */
    @property (nonatomic, copy) NSDateComponents *today;

    /**
    * The range of dates to allow for selection. Additionally, the calendar will
    * not allow the user to navigate to a month outside this range. If either
    * the selection `startDay` or `endDay` are `nil` that direction will be
    * unbounded
    */
    @property (nonatomic, copy) MOCalendarRange *validRange;

    /**
    * The currently-selected date range.
    */
    @property (nonatomic, copy) MOCalendarRange *selectedRange;

    /**
    * The currently-visible month.
    *
    * Setting this property to a date outside of `validRange` will cause no change
    * to the calendar.
    */
    @property (nonatomic, copy) NSDateComponents *visibleMonth;
    - (void)setVisibleMonth:(NSDateComponents *)visibleMonth animated:(BOOL)animated;

    /**
    * A subclass of `MOCalendarHeaderView` (or `MOCalendarHeaderView` itself) to
    * be used to draw the calendar header.
    */
    @property (nonatomic, strong) Class headerClass;

    /**
    * A subclass of `MOCalendarDayView` (or `MOCalendarDayView` itself) to be used
    * to draw the individual calendar days.
    */
    @property (nonatomic, strong) Class dayViewClass;

    @end