27 @global CPLocaleLanguageCode
28 @global CPDateFormatterShortStyle
30 var CPDatePicker_validateProposedDateValue_timeInterval = 1 << 1;
35 CPTextFieldAndStepperDatePickerStyle = 0;
36 CPClockAndCalendarDatePickerStyle = 1;
37 CPTextFieldDatePickerStyle = 2;
39 CPHourMinuteDatePickerElementFlag = 0x000c;
40 CPHourMinuteSecondDatePickerElementFlag = 0x000e;
41 CPTimeZoneDatePickerElementFlag = 0x0010;
42 CPYearMonthDatePickerElementFlag = 0x00c0;
43 CPYearMonthDayDatePickerElementFlag = 0x00e0;
44 CPEraDatePickerElementFlag = 0x0100;
54 BOOL _drawsBackground;
63 CPInteger _datePickerElements;
64 CPInteger _datePickerMode;
65 CPInteger _datePickerStyle;
66 CPInteger _timeInterval;
68 _CPDatePickerTextField _datePickerTextfield;
69 _CPDatePickerCalendar _datePickerCalendar;
70 unsigned _implementedCDatePickerDelegateMethods;
75 #pragma mark Theme methods
86 @"border-width" : 1.0,
88 @"content-inset": CGInsetMakeZero(),
89 @"bezel-inset": CGInsetMakeZero(),
91 @"min-size-datepicker-textfield": CGSizeMakeZero(),
92 @"content-inset-datepicker-textfield": CGInsetMakeZero(),
93 @"content-inset-datepicker-textfield-separator": CGInsetMakeZero(),
94 @"separator-content-inset": CGInsetMakeZero(),
95 @"date-hour-margin": 5.0,
96 @"stepper-margin": 5.0,
100 @"title-text-shadow-offset": CGSizeMakeZero(),
104 @"weekday-text-shadow-offset": CGSizeMakeZero(),
108 @"arrow-image-left-highlighted": [
CPNull null],
109 @"arrow-image-right-highlighted": [
CPNull null],
110 @"arrow-inset": CGInsetMakeZero(),
115 @"tile-text-shadow-offset": CGSizeMakeZero(),
117 @"size-tile": CGSizeMakeZero(),
118 @"size-calendar": CGSizeMakeZero(),
119 @"size-header": CGSizeMakeZero(),
120 @"min-size-calendar": CGSizeMakeZero(),
121 @"max-size-calendar": CGSizeMakeZero(),
125 @"clock-text-shadow-offset": CGSizeMakeZero(),
131 @"size-clock": CGSizeMakeZero(),
132 @"second-hand-size": CGSizeMakeZero(),
133 @"hour-hand-size": CGSizeMakeZero(),
134 @"middle-hand-size": CGSizeMakeZero(),
135 @"minute-hand-size": CGSizeMakeZero(),
141 #pragma mark Binding methods
143 + (Class)_binderClassForBinding:(
CPString)theBinding
145 if (theBinding == CPValueBinding || theBinding == CPMinValueBinding || theBinding == CPMaxValueBinding)
146 return [_CPDatePickerValueBinder class];
148 return [
super _binderClassForBinding:theBinding];
153 if (aBinding == CPValueBinding)
156 if (aBinding == CPMinValueBinding)
159 if (aBinding == CPMaxValueBinding)
162 return [
super _replacementKeyPathForBinding:aBinding];
167 #pragma mark Init methods
169 - (id)initWithFrame:(CGRect)aFrame
171 if (
self = [super initWithFrame:aFrame])
173 _drawsBackground = YES;
174 _datePickerStyle = CPTextFieldAndStepperDatePickerStyle;
175 _datePickerMode = CPSingleDateMode;
176 _datePickerElements = CPYearMonthDayDatePickerElementFlag | CPHourMinuteSecondDatePickerElementFlag;
178 _implementedCDatePickerDelegateMethods = 0;
184 [
self setBezeled:YES];
185 [
self setBordered:YES];
201 _datePickerTextfield = [[_CPDatePickerTextField alloc] initWithFrame:[
self bounds] withDatePicker:self];
203 [_datePickerTextfield setDateValue:_dateValue];
204 [
self addSubview:_datePickerTextfield];
206 _datePickerCalendar = [[_CPDatePickerCalendar alloc] initWithFrame:[
self bounds] withDatePicker:self];
207 [_datePickerCalendar setDateValue:_dateValue];
208 [_datePickerCalendar setHidden:YES];
209 [
self addSubview:_datePickerCalendar];
211 [
self setNeedsDisplay:YES];
212 [
self setNeedsLayout];
217 #pragma mark Delegate methods
222 - (void)setDelegate:(
id)aDelegate
224 _delegate = aDelegate;
225 _implementedCDatePickerDelegateMethods = 0;
228 if ([_delegate respondsToSelector:
@selector(datePicker:validateProposedDateValue:timeInterval:)])
229 _implementedCDatePickerDelegateMethods |= CPDatePicker_validateProposedDateValue_timeInterval;
234 #pragma mark Layout method
238 - (void)layoutSubviews
240 [
super layoutSubviews];
242 if (_datePickerStyle == CPTextFieldAndStepperDatePickerStyle || _datePickerStyle == CPTextFieldDatePickerStyle)
244 [_datePickerTextfield setHidden:NO];
245 [_datePickerCalendar setHidden:YES];
246 [_datePickerTextfield setNeedsLayout];
250 [_datePickerCalendar setHidden:NO];
251 [_datePickerTextfield setHidden:YES];
252 [_datePickerCalendar setNeedsLayout];
270 - (void)setObjectValue:(
CPDate)aValue
272 [
self setDateValue:aValue];
278 - (void)setDateValue:(
CPDate)aDateValue
280 if (aDateValue == nil)
283 [
self _setDateValue:aDateValue timeInterval:_timeInterval];
290 - (void)_setDateValue:(
CPDate)aDateValue timeInterval:(CPTimeInterval)aTimeInterval
293 aDateValue =
new Date (MAX(aDateValue, _minDate));
296 aDateValue =
new Date (MIN(aDateValue, _maxDate));
298 aTimeInterval = MAX(MIN(aTimeInterval, [_maxDate timeIntervalSinceDate:aDateValue]), [_minDate timeIntervalSinceDate:aDateValue]);
300 if ([aDateValue isEqualToDate:_dateValue] && aTimeInterval == _timeInterval)
303 if (_implementedCDatePickerDelegateMethods & CPDatePicker_validateProposedDateValue_timeInterval)
306 var aStartDateRef =
function(x){
if (typeof x ==
'undefined')
return aDateValue; aDateValue = x;}
307 var aTimeIntervalRef =
function(x){
if (typeof x ==
'undefined')
return aTimeInterval; aTimeInterval = x;}
309 [_delegate datePicker:self validateProposedDateValue:aStartDateRef timeInterval:aTimeIntervalRef];
312 [
self willChangeValueForKey:@"objectValue"];
313 [
self willChangeValueForKey:@"dateValue"];
314 _dateValue = aDateValue;
315 [
super setObjectValue:_dateValue];
316 [
self didChangeValueForKey:@"objectValue"];
317 [
self didChangeValueForKey:@"dateValue"];
319 [
self willChangeValueForKey:@"timeInterval"];
320 _timeInterval = (_datePickerMode == CPSingleDateMode)? 0 : aTimeInterval;
321 [
self didChangeValueForKey:@"timeInterval"];
323 [
self sendAction:[
self action] to:[
self target]];
325 if (_datePickerStyle == CPTextFieldAndStepperDatePickerStyle || _datePickerStyle == CPTextFieldDatePickerStyle)
326 [_datePickerTextfield setDateValue:_dateValue];
328 [_datePickerCalendar setDateValue:_dateValue];
334 - (void)setMinDate:(
CPDate)aMinDate
336 [
self willChangeValueForKey:@"minDate"];
338 [
self didChangeValueForKey:@"minDate"];
340 [
self _setDateValue:_dateValue timeInterval:_timeInterval];
346 - (void)setMaxDate:(
CPDate)aMaxDate
348 [
self willChangeValueForKey:@"maxDate"];
350 [
self didChangeValueForKey:@"maxDate"];
352 [
self _setDateValue:_dateValue timeInterval:_timeInterval];
358 - (void)setDatePickerStyle:(CPInteger)aDatePickerStyle
360 _datePickerStyle = aDatePickerStyle;
362 [
self setNeedsDisplay:YES];
363 [
self setNeedsLayout];
369 - (void)setDatePickerElements:(CPInteger)aDatePickerElements
371 _datePickerElements = aDatePickerElements;
373 [
self setNeedsDisplay:YES];
374 [
self setNeedsLayout];
380 - (void)setDatePickerMode:(CPInteger)aDatePickerMode
382 _datePickerMode = aDatePickerMode;
384 if (_datePickerMode == CPSingleDateMode)
385 [
self _setDateValue:[
self dateValue] timeInterval:0];
387 [
self setNeedsDisplay:YES];
388 [
self setNeedsLayout];
394 - (void)setTimeInterval:(CPInteger)aTimeInterval
396 if (_datePickerMode == CPSingleDateMode)
399 [
self _setDateValue:[
self dateValue] timeInterval:aTimeInterval];
411 [
self willChangeValueForKey:@"locale"];
412 [_formatter setLocale:_locale];
413 [
self didChangeValueForKey:@"locale"];
417 [_datePickerTextfield setDateValue:_dateValue];
418 [
self setNeedsDisplay:YES];
419 [
self setNeedsLayout];
426 - (void)setBezeled:(BOOL)shouldBeBezeled
428 _isBezeled = shouldBeBezeled;
431 [
self setThemeState:CPThemeStateBezeled];
433 [
self unsetThemeState:CPThemeStateBezeled];
440 - (void)setBordered:(BOOL)shouldBeBordered
442 _isBordered = shouldBeBordered;
444 if (shouldBeBordered)
445 [
self setThemeState:CPThemeStateBordered];
447 [
self unsetThemeState:CPThemeStateBordered];
454 - (void)setTextFont:(
CPFont)aFont
456 [
self setFont:aFont];
462 - (void)setEnabled:(BOOL)aBoolean
464 [
super setEnabled:aBoolean];
466 [_datePickerTextfield setEnabled:aBoolean];
467 [_datePickerCalendar setEnabled:aBoolean];
473 - (void)setBackgroundColor:(
CPColor)aColor
475 _backgroundColor = aColor;
476 [
self setNeedsLayout];
482 - (void)setDrawsBackground:(BOOL)aBoolean
484 [
self willChangeValueForKey:@"drawsBackground"];
485 _drawsBackground = aBoolean;
486 [
self didChangeValueForKey:@"drawsBackground"];
488 [
self setNeedsLayout];
496 [
self willChangeValueForKey:@"timeZone"];
497 _timeZone = aTimeZone;
498 [
self didChangeValueForKey:@"timeZone"];
500 [
self setNeedsLayout];
505 #pragma mark First responder methods
509 - (BOOL)becomeFirstResponder
511 if (_datePickerStyle == CPTextFieldAndStepperDatePickerStyle || _datePickerStyle == CPTextFieldDatePickerStyle)
512 [_datePickerTextfield _selecteTextFieldWithFlags:[[CPApp currentEvent] modifierFlags]];
521 - (BOOL)acceptsFirstResponder
528 - (BOOL)resignFirstResponder
530 if (_datePickerStyle == CPTextFieldAndStepperDatePickerStyle || _datePickerStyle == CPTextFieldDatePickerStyle)
531 [_datePickerTextfield resignFirstResponder];
545 return [
self hasThemeState:CPThemeStateBezeled];
553 return [
self hasThemeState:CPThemeStateBordered];
566 - (BOOL)_isAmericanFormat
568 return [[_locale objectForKey:CPLocaleCountryCode] isEqualToString:@"US"];
573 - (BOOL)_isEnglishFormat
575 return [[_locale objectForKey:CPLocaleLanguageCode] isEqualToString:@"en"];
580 #pragma mark Key event
585 - (void)keyDown:(
CPEvent)anEvent
587 if (_datePickerStyle == CPTextFieldAndStepperDatePickerStyle || _datePickerStyle == CPTextFieldDatePickerStyle)
588 [_datePickerTextfield keyDown:anEvent];
593 var CPDatePickerModeKey =
@"CPDatePickerModeKey",
594 CPIntervalKey =
@"CPIntervalKey",
595 CPMinDateKey =
@"CPMinDateKey",
596 CPMaxDateKey =
@"CPMaxDateKey",
597 CPBackgroundColorKey =
@"CPBackgroundColorKey",
598 CPDrawsBackgroundKey =
@"CPDrawsBackgroundKey",
599 CPTextFontKey =
@"CPTextFontKey",
600 CPDatePickerElementsKey =
@"CPDatePickerElementsKey",
601 CPDatePickerStyleKey =
@"CPDatePickerStyleKey",
602 CPLocaleKey =
@"CPLocaleKey",
603 CPBorderedKey =
@"CPBorderedKey",
604 CPDateValueKey =
@"CPDateValueKey";
606 @implementation CPDatePicker (CPCoding)
608 - (id)initWithCoder:(
CPCoder)aCoder
610 self = [
super initWithCoder:aCoder];
614 _textFont = [aCoder decodeObjectForKey:CPTextFontKey];
617 _timeInterval = [aCoder decodeDoubleForKey:CPIntervalKey];
618 _datePickerMode = [aCoder decodeIntForKey:CPDatePickerModeKey];
619 _datePickerElements = [aCoder decodeIntForKey:CPDatePickerElementsKey];
620 _datePickerStyle = [aCoder decodeIntForKey:CPDatePickerStyleKey];
621 _locale = [aCoder decodeObjectForKey:CPLocaleKey];
622 _dateValue = [aCoder decodeObjectForKey:CPDateValueKey];
623 _backgroundColor = [aCoder decodeObjectForKey:CPBackgroundColorKey];
624 _drawsBackground = [aCoder decodeBoolForKey:CPDrawsBackgroundKey];
625 _isBordered = [aCoder decodeBoolForKey:CPBorderedKey];
632 - (void)encodeWithCoder:(
CPCoder)aCoder
634 [
super encodeWithCoder:aCoder];
635 [aCoder encodeDouble:_timeInterval forKey:CPIntervalKey];
636 [aCoder encodeInt:_datePickerMode forKey:CPDatePickerModeKey];
637 [aCoder encodeInt:_datePickerStyle forKey:CPDatePickerStyleKey];
638 [aCoder encodeInt:_datePickerElements forKey:CPDatePickerElementsKey];
639 [aCoder encodeObject:_minDate forKey:CPMinDateKey];
640 [aCoder encodeObject:_maxDate forKey:CPMaxDateKey]
641 [aCoder encodeObject:_dateValue forKey:CPDateValueKey];;
642 [aCoder encodeObject:_textFont forKey:CPTextFontKey];
643 [aCoder encodeObject:_locale forKey:CPLocaleKey];
644 [aCoder encodeObject:_backgroundColor forKey:CPBackgroundColorKey];
645 [aCoder encodeObject:_drawsBackground forKey:CPDrawsBackgroundKey];
646 [aCoder encodeObject:_isBordered forKey:CPBorderedKey];
650 @implementation _CPDatePickerValueBinder :
CPBinder
657 @implementation CPDate (CPDatePickerAdditions)
661 return 32 - new Date(self.getFullYear(), self.getMonth(), 32).getDate();
664 - (void)_resetToMidnight
669 self.setMilliseconds(0);
672 - (void)_resetToLastSeconds
677 self.setMilliseconds(99);
682 @implementation CPDatePicker (CPSynthesizedAccessors)
695 - (void)setBordered:(BOOL)aValue
697 _isBordered = aValue;
711 - (void)setBezeled:(BOOL)aValue
719 - (BOOL)drawsBackground
721 return _drawsBackground;
727 - (void)setDrawsBackground:(BOOL)aValue
729 _drawsBackground = aValue;
743 - (void)setDateValue:(
CPDate)aValue
759 - (void)setMinDate:(
CPDate)aValue
775 - (void)setMaxDate:(
CPDate)aValue
791 - (void)setTextFont:(
CPFont)aValue
815 - (CPCalendar)calendar
823 - (void)setCalendar:(CPCalendar)aValue
855 - (void)setDelegate:(
id)aValue
863 - (CPInteger)datePickerElements
865 return _datePickerElements;
871 - (void)setDatePickerElements:(CPInteger)aValue
873 _datePickerElements = aValue;
879 - (CPInteger)datePickerMode
881 return _datePickerMode;
887 - (void)setDatePickerMode:(CPInteger)aValue
889 _datePickerMode = aValue;
895 - (CPInteger)datePickerStyle
897 return _datePickerStyle;
903 - (void)setDatePickerStyle:(CPInteger)aValue
905 _datePickerStyle = aValue;
911 - (CPInteger)timeInterval
913 return _timeInterval;
919 - (void)setTimeInterval:(CPInteger)aValue
921 _timeInterval = aValue;