mirror of
https://github.com/cappuccino/cappuccino.git
synced 2026-08-27 22:17:03 +00:00
This PR fixes several issues with the timeZone. It also changes the way to "calculate" the date of the textual datePicker.
701 lines
21 KiB
Plaintext
701 lines
21 KiB
Plaintext
/* CPDatePicker.j
|
|
* AppKit
|
|
*
|
|
* Created by Alexandre Wilhelm
|
|
* Copyright 2012 <alexandre.wilhelmfr@gmail.com>
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
|
|
@import "CPControl.j"
|
|
@import "CPFont.j"
|
|
@import "CPTextField.j"
|
|
@import "_CPDatePickerTextField.j"
|
|
@import "_CPDatePickerCalendar.j"
|
|
|
|
@import <Foundation/CPArray.j>
|
|
@import <Foundation/CPObject.j>
|
|
@import <Foundation/CPDate.j>
|
|
@import <Foundation/CPDateFormatter.j>
|
|
@import <Foundation/CPLocale.j>
|
|
@import <Foundation/CPTimeZone.j>
|
|
|
|
@class CPStepper
|
|
@class CPApp
|
|
|
|
@global CPLocaleLanguageCode
|
|
@global CPDateFormatterShortStyle
|
|
|
|
var CPDatePicker_validateProposedDateValue_timeInterval = 1 << 1;
|
|
|
|
CPSingleDateMode = 0;
|
|
CPRangeDateMode = 1;
|
|
|
|
CPTextFieldAndStepperDatePickerStyle = 0;
|
|
CPClockAndCalendarDatePickerStyle = 1;
|
|
CPTextFieldDatePickerStyle = 2;
|
|
|
|
CPHourMinuteDatePickerElementFlag = 0x000c;
|
|
CPHourMinuteSecondDatePickerElementFlag = 0x000e;
|
|
CPTimeZoneDatePickerElementFlag = 0x0010;
|
|
CPYearMonthDatePickerElementFlag = 0x00c0;
|
|
CPYearMonthDayDatePickerElementFlag = 0x00e0;
|
|
CPEraDatePickerElementFlag = 0x0100;
|
|
|
|
/*!
|
|
@ingroup appkit
|
|
This control displays a datepicker in a Cappuccino application
|
|
*/
|
|
@implementation CPDatePicker : CPControl
|
|
{
|
|
BOOL _isBordered @accessors(getter=isBordered, setter=setBordered:);
|
|
BOOL _isBezeled @accessors(getter=isBezeled, setter=setBezeled:);
|
|
BOOL _drawsBackground @accessors(property=drawsBackground);
|
|
CPDate _dateValue @accessors(property=dateValue);
|
|
CPDate _minDate @accessors(property=minDate);
|
|
CPDate _maxDate @accessors(property=maxDate);
|
|
CPFont _textFont @accessors(property=textFont);
|
|
CPLocale _locale @accessors(property=locale);
|
|
//CPCalendar _calendar @accessors(property=calendar);
|
|
CPTimeZone _timeZone @accessors(property=timeZone);
|
|
id _delegate @accessors(property=delegate);
|
|
CPInteger _datePickerElements @accessors(property=datePickerElements);
|
|
CPInteger _datePickerMode @accessors(property=datePickerMode);
|
|
CPInteger _datePickerStyle @accessors(property=datePickerStyle);
|
|
CPInteger _timeInterval @accessors(property=timeInterval);
|
|
|
|
_CPDatePickerTextField _datePickerTextfield;
|
|
_CPDatePickerCalendar _datePickerCalendar;
|
|
unsigned _implementedCDatePickerDelegateMethods;
|
|
}
|
|
|
|
|
|
#pragma mark -
|
|
#pragma mark Theme methods
|
|
|
|
+ (CPString)defaultThemeClass
|
|
{
|
|
return @"datePicker";
|
|
}
|
|
|
|
+ (CPDictionary)themeAttributes
|
|
{
|
|
return @{
|
|
@"bezel-color": [CPColor clearColor],
|
|
@"border-width" : 1.0,
|
|
@"border-color": [CPColor clearColor],
|
|
@"content-inset": CGInsetMakeZero(),
|
|
@"bezel-inset": CGInsetMakeZero(),
|
|
@"datepicker-textfield-bezel-color": [CPColor clearColor],
|
|
@"min-size-datepicker-textfield": CGSizeMakeZero(),
|
|
@"content-inset-datepicker-textfield": CGInsetMakeZero(),
|
|
@"content-inset-datepicker-textfield-separator": CGInsetMakeZero(),
|
|
@"separator-content-inset": CGInsetMakeZero(),
|
|
@"date-hour-margin": 5.0,
|
|
@"stepper-margin": 5.0,
|
|
@"bezel-color-calendar": [CPColor clearColor],
|
|
@"title-text-color": [CPColor blackColor],
|
|
@"title-text-shadow-color": [CPColor clearColor],
|
|
@"title-text-shadow-offset": CGSizeMakeZero(),
|
|
@"title-font": [CPNull null],
|
|
@"weekday-text-color": [CPColor blackColor],
|
|
@"weekday-text-shadow-color": [CPColor clearColor],
|
|
@"weekday-text-shadow-offset": CGSizeMakeZero(),
|
|
@"weekday-font": [CPNull null],
|
|
@"arrow-image-left": [CPNull null],
|
|
@"arrow-image-right": [CPNull null],
|
|
@"arrow-image-left-highlighted": [CPNull null],
|
|
@"arrow-image-right-highlighted": [CPNull null],
|
|
@"arrow-inset": CGInsetMakeZero(),
|
|
@"circle-image": [CPNull null],
|
|
@"circle-image-highlighted": [CPNull null],
|
|
@"tile-text-color": [CPColor blackColor],
|
|
@"tile-text-shadow-color": [CPColor clearColor],
|
|
@"tile-text-shadow-offset": CGSizeMakeZero(),
|
|
@"tile-font": [CPNull null],
|
|
@"size-tile": CGSizeMakeZero(),
|
|
@"size-calendar": CGSizeMakeZero(),
|
|
@"size-header": CGSizeMakeZero(),
|
|
@"min-size-calendar": CGSizeMakeZero(),
|
|
@"max-size-calendar": CGSizeMakeZero(),
|
|
@"bezel-color-clock": [CPColor clearColor],
|
|
@"clock-text-color": [CPColor blackColor],
|
|
@"clock-text-shadow-color": [CPColor clearColor],
|
|
@"clock-text-shadow-offset": CGSizeMakeZero(),
|
|
@"clock-font": [CPNull null],
|
|
@"second-hand-image": [CPNull null],
|
|
@"hour-hand-image": [CPNull null],
|
|
@"middle-hand-image": [CPNull null],
|
|
@"minute-hand-image": [CPNull null],
|
|
@"size-clock": CGSizeMakeZero(),
|
|
@"second-hand-size": CGSizeMakeZero(),
|
|
@"hour-hand-size": CGSizeMakeZero(),
|
|
@"middle-hand-size": CGSizeMakeZero(),
|
|
@"minute-hand-size": CGSizeMakeZero(),
|
|
};
|
|
}
|
|
|
|
|
|
#pragma mark -
|
|
#pragma mark Binding methods
|
|
|
|
+ (Class)_binderClassForBinding:(CPString)theBinding
|
|
{
|
|
if (theBinding == CPValueBinding || theBinding == CPMinValueBinding || theBinding == CPMaxValueBinding)
|
|
return [_CPDatePickerValueBinder class];
|
|
|
|
return [super _binderClassForBinding:theBinding];
|
|
}
|
|
|
|
- (CPString)_replacementKeyPathForBinding:(CPString)aBinding
|
|
{
|
|
if (aBinding == CPValueBinding)
|
|
return @"dateValue";
|
|
|
|
if (aBinding == CPMinValueBinding)
|
|
return @"minDate";
|
|
|
|
if (aBinding == CPMaxValueBinding)
|
|
return @"maxDate";
|
|
|
|
return [super _replacementKeyPathForBinding:aBinding];
|
|
}
|
|
|
|
|
|
#pragma mark -
|
|
#pragma mark Init methods
|
|
|
|
- (id)initWithFrame:(CGRect)aFrame
|
|
{
|
|
if (self = [super initWithFrame:aFrame])
|
|
{
|
|
_drawsBackground = YES;
|
|
_datePickerStyle = CPTextFieldAndStepperDatePickerStyle;
|
|
_datePickerMode = CPSingleDateMode;
|
|
_datePickerElements = CPYearMonthDayDatePickerElementFlag | CPHourMinuteSecondDatePickerElementFlag;
|
|
_timeInterval = 0;
|
|
_implementedCDatePickerDelegateMethods = 0;
|
|
|
|
[self setObjectValue:[CPDate date]];
|
|
_minDate = [CPDate distantPast];
|
|
_maxDate = [CPDate distantFuture];
|
|
|
|
[self setBezeled:YES];
|
|
[self setBordered:YES];
|
|
|
|
[self _init];
|
|
}
|
|
|
|
return self
|
|
}
|
|
|
|
- (void)_init
|
|
{
|
|
if (!_locale)
|
|
_locale = [CPLocale currentLocale];
|
|
|
|
_datePickerTextfield = [[_CPDatePickerTextField alloc] initWithFrame:[self bounds] withDatePicker:self];
|
|
|
|
[_datePickerTextfield setDateValue:_dateValue];
|
|
[self addSubview:_datePickerTextfield];
|
|
|
|
_datePickerCalendar = [[_CPDatePickerCalendar alloc] initWithFrame:[self bounds] withDatePicker:self];
|
|
[_datePickerCalendar setDateValue:_dateValue];
|
|
[_datePickerCalendar setHidden:YES];
|
|
[self addSubview:_datePickerCalendar];
|
|
|
|
[self setNeedsDisplay:YES];
|
|
[self setNeedsLayout];
|
|
}
|
|
|
|
|
|
#pragma mark -
|
|
#pragma mark Delegate methods
|
|
|
|
/*! Set the delegate of the datePicker
|
|
@param aDelegate delegate of the datePicker
|
|
*/
|
|
- (void)setDelegate:(id)aDelegate
|
|
{
|
|
_delegate = aDelegate;
|
|
_implementedCDatePickerDelegateMethods = 0;
|
|
|
|
// Look if the delegate implements or not the delegate methods
|
|
if ([_delegate respondsToSelector:@selector(datePicker:validateProposedDateValue:timeInterval:)])
|
|
_implementedCDatePickerDelegateMethods |= CPDatePicker_validateProposedDateValue_timeInterval;
|
|
}
|
|
|
|
|
|
#pragma mark -
|
|
#pragma mark Layout method
|
|
|
|
/*! Layout the subviews
|
|
*/
|
|
- (void)layoutSubviews
|
|
{
|
|
[super layoutSubviews];
|
|
|
|
if (_datePickerStyle == CPTextFieldAndStepperDatePickerStyle || _datePickerStyle == CPTextFieldDatePickerStyle)
|
|
{
|
|
[_datePickerTextfield setHidden:NO];
|
|
[_datePickerCalendar setHidden:YES];
|
|
[_datePickerTextfield setNeedsLayout];
|
|
}
|
|
else
|
|
{
|
|
[_datePickerCalendar setHidden:NO];
|
|
[_datePickerTextfield setHidden:YES];
|
|
[_datePickerCalendar setNeedsLayout];
|
|
}
|
|
}
|
|
|
|
#pragma mark -
|
|
#pragma mark Setter
|
|
|
|
/*! Return the objectValue of the datePicker. The objectValue should take the timeZoneEffect
|
|
*/
|
|
- (id)objectValue
|
|
{
|
|
// TODO : add timeZone effect. How to do it because js ???
|
|
return _dateValue
|
|
}
|
|
|
|
/*! Set the objectValue ofhe datePier. It has to be a CPDate
|
|
@param aDateValue the dateValue
|
|
*/
|
|
- (void)setObjectValue:(CPDate)aValue
|
|
{
|
|
[self setDateValue:aValue];
|
|
}
|
|
|
|
/* Set the dateValue of the datePicker
|
|
@param aDateValue the dateValue
|
|
*/
|
|
- (void)setDateValue:(CPDate)aDateValue
|
|
{
|
|
if (aDateValue == nil)
|
|
return;
|
|
|
|
[self _setDateValue:aDateValue timeInterval:_timeInterval];
|
|
}
|
|
|
|
/*! Set the dateValue and the timeInterval. This method checks the min and max date of the datePicker also. It will call the delegate if possible.
|
|
@param aDateValue the dateValue
|
|
@param aTimeInterval the timeInterval
|
|
*/
|
|
- (void)_setDateValue:(CPDate)aDateValue timeInterval:(CPTimeInterval)aTimeInterval
|
|
{
|
|
if (_minDate)
|
|
aDateValue = new Date (MAX(aDateValue, _minDate));
|
|
|
|
if (_maxDate)
|
|
aDateValue = new Date (MIN(aDateValue, _maxDate));
|
|
|
|
aTimeInterval = MAX(MIN(aTimeInterval, [_maxDate timeIntervalSinceDate:aDateValue]), [_minDate timeIntervalSinceDate:aDateValue]);
|
|
|
|
if ([aDateValue isEqualToDate:_dateValue] && aTimeInterval == _timeInterval)
|
|
{
|
|
if (_datePickerStyle == CPTextFieldAndStepperDatePickerStyle || _datePickerStyle == CPTextFieldDatePickerStyle)
|
|
[_datePickerTextfield setDateValue:_dateValue];
|
|
else
|
|
[_datePickerCalendar setDateValue:_dateValue];
|
|
|
|
return;
|
|
}
|
|
|
|
if (_implementedCDatePickerDelegateMethods & CPDatePicker_validateProposedDateValue_timeInterval)
|
|
{
|
|
// constrain timeInterval also
|
|
var aStartDateRef = function(x){if (typeof x == 'undefined') return aDateValue; aDateValue = x;}
|
|
var aTimeIntervalRef = function(x){if (typeof x == 'undefined') return aTimeInterval; aTimeInterval = x;}
|
|
|
|
[_delegate datePicker:self validateProposedDateValue:aStartDateRef timeInterval:aTimeIntervalRef];
|
|
}
|
|
|
|
[self willChangeValueForKey:@"objectValue"];
|
|
[self willChangeValueForKey:@"dateValue"];
|
|
_dateValue = aDateValue;
|
|
[super setObjectValue:_dateValue];
|
|
[self didChangeValueForKey:@"objectValue"];
|
|
[self didChangeValueForKey:@"dateValue"];
|
|
|
|
[self willChangeValueForKey:@"timeInterval"];
|
|
_timeInterval = (_datePickerMode == CPSingleDateMode)? 0 : aTimeInterval;
|
|
[self didChangeValueForKey:@"timeInterval"];
|
|
|
|
[self sendAction:[self action] to:[self target]];
|
|
|
|
if (_datePickerStyle == CPTextFieldAndStepperDatePickerStyle || _datePickerStyle == CPTextFieldDatePickerStyle)
|
|
[_datePickerTextfield setDateValue:_dateValue];
|
|
else
|
|
[_datePickerCalendar setDateValue:_dateValue];
|
|
}
|
|
|
|
/*! Set the minDate of the datePicker
|
|
@param aMinDate the minDate
|
|
*/
|
|
- (void)setMinDate:(CPDate)aMinDate
|
|
{
|
|
[self willChangeValueForKey:@"minDate"];
|
|
_minDate = aMinDate;
|
|
[self didChangeValueForKey:@"minDate"];
|
|
|
|
[self _setDateValue:_dateValue timeInterval:_timeInterval];
|
|
}
|
|
|
|
/*! Set the maxDate of the datePicker
|
|
@param aMaxDate the maxDate
|
|
*/
|
|
- (void)setMaxDate:(CPDate)aMaxDate
|
|
{
|
|
[self willChangeValueForKey:@"maxDate"];
|
|
_maxDate = aMaxDate;
|
|
[self didChangeValueForKey:@"maxDate"];
|
|
|
|
[self _setDateValue:_dateValue timeInterval:_timeInterval];
|
|
}
|
|
|
|
/*! Set the syle of the datePicker
|
|
@param aDatePickerStyle the datePicker style
|
|
*/
|
|
- (void)setDatePickerStyle:(CPInteger)aDatePickerStyle
|
|
{
|
|
_datePickerStyle = aDatePickerStyle;
|
|
|
|
[self setNeedsDisplay:YES];
|
|
[self setNeedsLayout];
|
|
}
|
|
|
|
/*! Set the elements of the datePicker
|
|
@param aDatePickerElements the datePicker elements
|
|
*/
|
|
- (void)setDatePickerElements:(CPInteger)aDatePickerElements
|
|
{
|
|
_datePickerElements = aDatePickerElements;
|
|
|
|
[self setNeedsDisplay:YES];
|
|
[self setNeedsLayout];
|
|
}
|
|
|
|
/*! Set the mode of the datePicker
|
|
@param aDatePickerMode the datePicker mode
|
|
*/
|
|
- (void)setDatePickerMode:(CPInteger)aDatePickerMode
|
|
{
|
|
_datePickerMode = aDatePickerMode;
|
|
|
|
if (_datePickerMode == CPSingleDateMode)
|
|
[self _setDateValue:[self dateValue] timeInterval:0];
|
|
|
|
[self setNeedsDisplay:YES];
|
|
[self setNeedsLayout];
|
|
}
|
|
|
|
/*! Set the timeInterval of the datePicker
|
|
@param aTimeInterval the timeInterval of the datePicker
|
|
*/
|
|
- (void)setTimeInterval:(CPInteger)aTimeInterval
|
|
{
|
|
if (_datePickerMode == CPSingleDateMode)
|
|
return;
|
|
|
|
[self _setDateValue:[self dateValue] timeInterval:aTimeInterval];
|
|
}
|
|
|
|
/*! Set the locale of the datePicker. This update laso the locale of the formatter.
|
|
@param aLocale the locale
|
|
*/
|
|
- (void)setLocale:(CPLocale)aLocale
|
|
{
|
|
_locale = aLocale;
|
|
|
|
if (_formatter)
|
|
{
|
|
[self willChangeValueForKey:@"locale"];
|
|
[_formatter setLocale:_locale];
|
|
[self didChangeValueForKey:@"locale"];
|
|
}
|
|
|
|
// This will update the textFields (usefull when changing with a date with pm and am)
|
|
[_datePickerTextfield setDateValue:_dateValue];
|
|
[self setNeedsDisplay:YES];
|
|
[self setNeedsLayout];
|
|
}
|
|
|
|
/*!
|
|
Sets whether the datepicker will have a bezeled border.
|
|
@param shouldBeBezeled \c YES means the datepicker will draw a bezeled border
|
|
*/
|
|
- (void)setBezeled:(BOOL)shouldBeBezeled
|
|
{
|
|
_isBezeled = shouldBeBezeled;
|
|
|
|
if (shouldBeBezeled)
|
|
[self setThemeState:CPThemeStateBezeled];
|
|
else
|
|
[self unsetThemeState:CPThemeStateBezeled];
|
|
}
|
|
|
|
/*!
|
|
Sets whether the datepicker will have a border drawn. (actually it does nothing)
|
|
@param shouldBeBordered \c YES makes the datepicker draw a border
|
|
*/
|
|
- (void)setBordered:(BOOL)shouldBeBordered
|
|
{
|
|
_isBordered = shouldBeBordered;
|
|
|
|
if (shouldBeBordered)
|
|
[self setThemeState:CPThemeStateBordered];
|
|
else
|
|
[self unsetThemeState:CPThemeStateBordered];
|
|
}
|
|
|
|
/*!
|
|
Sets the font of the control.
|
|
@param aFont
|
|
*/
|
|
- (void)setTextFont:(CPFont)aFont
|
|
{
|
|
[self setFont:aFont];
|
|
}
|
|
|
|
/*! Sets the enabled status of the control. Controls that are not enabled can not be used by the user and obtain the CPThemeStateDisabled theme state.
|
|
@param a boolean. YES if the control should be enabled, otherwise NO.
|
|
*/
|
|
- (void)setEnabled:(BOOL)aBoolean
|
|
{
|
|
[super setEnabled:aBoolean];
|
|
|
|
[_datePickerTextfield setEnabled:aBoolean];
|
|
[_datePickerCalendar setEnabled:aBoolean];
|
|
}
|
|
|
|
/*! Set the background color of the datePicker
|
|
@param aColor
|
|
*/
|
|
- (void)setBackgroundColor:(CPColor)aColor
|
|
{
|
|
_backgroundColor = aColor;
|
|
[self setNeedsLayout];
|
|
}
|
|
|
|
/*! Set the boolean drawsBackgroundColor
|
|
@param aBoolean
|
|
*/
|
|
- (void)setDrawsBackground:(BOOL)aBoolean
|
|
{
|
|
[self willChangeValueForKey:@"drawsBackground"];
|
|
_drawsBackground = aBoolean;
|
|
[self didChangeValueForKey:@"drawsBackground"];
|
|
|
|
[self setNeedsLayout];
|
|
}
|
|
|
|
/*! Set the timeZone
|
|
@param aTimeZone
|
|
*/
|
|
- (void)setTimeZone:(CPTimeZone)aTimeZone
|
|
{
|
|
[self willChangeValueForKey:@"timeZone"];
|
|
_timeZone = aTimeZone;
|
|
[self didChangeValueForKey:@"timeZone"];
|
|
|
|
[self setNeedsLayout];
|
|
|
|
if (_datePickerStyle == CPTextFieldAndStepperDatePickerStyle || _datePickerStyle == CPTextFieldDatePickerStyle)
|
|
[_datePickerTextfield setDateValue:_dateValue];
|
|
else
|
|
[_datePickerCalendar setDateValue:_dateValue];
|
|
}
|
|
|
|
|
|
#pragma mark -
|
|
#pragma mark First responder methods
|
|
|
|
/*! Return YES if style is set to CPTextFieldAndStepperDatePickerStyle or CPTextFieldDatePickerStyle
|
|
*/
|
|
- (BOOL)becomeFirstResponder
|
|
{
|
|
if (_datePickerStyle == CPTextFieldAndStepperDatePickerStyle || _datePickerStyle == CPTextFieldDatePickerStyle)
|
|
[_datePickerTextfield _selecteTextFieldWithFlags:[[CPApp currentEvent] modifierFlags]];
|
|
else
|
|
return NO;
|
|
|
|
return YES;
|
|
}
|
|
|
|
/*! Return YES
|
|
*/
|
|
- (BOOL)acceptsFirstResponder
|
|
{
|
|
return YES;
|
|
}
|
|
|
|
/*! Return YES
|
|
*/
|
|
- (BOOL)resignFirstResponder
|
|
{
|
|
if (_datePickerStyle == CPTextFieldAndStepperDatePickerStyle || _datePickerStyle == CPTextFieldDatePickerStyle)
|
|
[_datePickerTextfield resignFirstResponder];
|
|
|
|
return YES;
|
|
}
|
|
|
|
|
|
#pragma mark -
|
|
#pragma mark getter
|
|
|
|
/*!
|
|
Returns \c YES if the textfield is bezeled.
|
|
*/
|
|
- (BOOL)isBezeled
|
|
{
|
|
return [self hasThemeState:CPThemeStateBezeled];
|
|
}
|
|
|
|
/*!
|
|
Returns \c YES if the textfield has a border.
|
|
*/
|
|
- (BOOL)isBordered
|
|
{
|
|
return [self hasThemeState:CPThemeStateBordered];
|
|
}
|
|
|
|
/*!
|
|
Returns the font of the control.
|
|
*/
|
|
- (CPFont)textFont
|
|
{
|
|
return [self font];
|
|
}
|
|
|
|
/*! Check if we are in the american format or not. Depending on the locale
|
|
*/
|
|
- (BOOL)_isAmericanFormat
|
|
{
|
|
return [[_locale objectForKey:CPLocaleCountryCode] isEqualToString:@"US"];
|
|
}
|
|
|
|
/*! Check if we are in the english format or not. Depending on the locale
|
|
*/
|
|
- (BOOL)_isEnglishFormat
|
|
{
|
|
return [[_locale objectForKey:CPLocaleLanguageCode] isEqualToString:@"en"];
|
|
}
|
|
|
|
|
|
#pragma mark -
|
|
#pragma mark Key event
|
|
|
|
/*! Key down event
|
|
@param anEvent
|
|
*/
|
|
- (void)keyDown:(CPEvent)anEvent
|
|
{
|
|
if (_datePickerStyle == CPTextFieldAndStepperDatePickerStyle || _datePickerStyle == CPTextFieldDatePickerStyle)
|
|
[_datePickerTextfield keyDown:anEvent];
|
|
}
|
|
|
|
@end
|
|
|
|
var CPDatePickerModeKey = @"CPDatePickerModeKey",
|
|
CPIntervalKey = @"CPIntervalKey",
|
|
CPMinDateKey = @"CPMinDateKey",
|
|
CPMaxDateKey = @"CPMaxDateKey",
|
|
CPBackgroundColorKey = @"CPBackgroundColorKey",
|
|
CPDrawsBackgroundKey = @"CPDrawsBackgroundKey",
|
|
CPTextFontKey = @"CPTextFontKey",
|
|
CPDatePickerElementsKey = @"CPDatePickerElementsKey",
|
|
CPDatePickerStyleKey = @"CPDatePickerStyleKey",
|
|
CPLocaleKey = @"CPLocaleKey",
|
|
CPBorderedKey = @"CPBorderedKey",
|
|
CPDateValueKey = @"CPDateValueKey";
|
|
|
|
@implementation CPDatePicker (CPCoding)
|
|
|
|
- (id)initWithCoder:(CPCoder)aCoder
|
|
{
|
|
self = [super initWithCoder:aCoder];
|
|
|
|
if (self)
|
|
{
|
|
_textFont = [aCoder decodeObjectForKey:CPTextFontKey];
|
|
_minDate = [aCoder decodeObjectForKey:CPMinDateKey] || [CPDate distantPast];
|
|
_maxDate = [aCoder decodeObjectForKey:CPMaxDateKey] || [CPDate distantFuture];
|
|
_timeInterval = [aCoder decodeDoubleForKey:CPIntervalKey];
|
|
_datePickerMode = [aCoder decodeIntForKey:CPDatePickerModeKey];
|
|
_datePickerElements = [aCoder decodeIntForKey:CPDatePickerElementsKey];
|
|
_datePickerStyle = [aCoder decodeIntForKey:CPDatePickerStyleKey];
|
|
_locale = [aCoder decodeObjectForKey:CPLocaleKey];
|
|
_dateValue = [aCoder decodeObjectForKey:CPDateValueKey];
|
|
_backgroundColor = [aCoder decodeObjectForKey:CPBackgroundColorKey];
|
|
_drawsBackground = [aCoder decodeBoolForKey:CPDrawsBackgroundKey];
|
|
_isBordered = [aCoder decodeBoolForKey:CPBorderedKey];
|
|
[self _init];
|
|
}
|
|
|
|
return self
|
|
}
|
|
|
|
- (void)encodeWithCoder:(CPCoder)aCoder
|
|
{
|
|
[super encodeWithCoder:aCoder];
|
|
[aCoder encodeDouble:_timeInterval forKey:CPIntervalKey];
|
|
[aCoder encodeInt:_datePickerMode forKey:CPDatePickerModeKey];
|
|
[aCoder encodeInt:_datePickerStyle forKey:CPDatePickerStyleKey];
|
|
[aCoder encodeInt:_datePickerElements forKey:CPDatePickerElementsKey];
|
|
[aCoder encodeObject:_minDate forKey:CPMinDateKey];
|
|
[aCoder encodeObject:_maxDate forKey:CPMaxDateKey]
|
|
[aCoder encodeObject:_dateValue forKey:CPDateValueKey];;
|
|
[aCoder encodeObject:_textFont forKey:CPTextFontKey];
|
|
[aCoder encodeObject:_locale forKey:CPLocaleKey];
|
|
[aCoder encodeObject:_backgroundColor forKey:CPBackgroundColorKey];
|
|
[aCoder encodeObject:_drawsBackground forKey:CPDrawsBackgroundKey];
|
|
[aCoder encodeObject:_isBordered forKey:CPBorderedKey];
|
|
}
|
|
|
|
@end
|
|
|
|
@implementation _CPDatePickerValueBinder : CPBinder
|
|
{
|
|
}
|
|
|
|
@end
|
|
|
|
@implementation CPDate (CPDatePickerAdditions)
|
|
|
|
- (int)_daysInMonth
|
|
{
|
|
return 32 - new Date(self.getFullYear(), self.getMonth(), 32).getDate();
|
|
}
|
|
|
|
- (void)_resetToMidnight
|
|
{
|
|
self.setHours(0);
|
|
self.setMinutes(0);
|
|
self.setSeconds(0);
|
|
self.setMilliseconds(0);
|
|
}
|
|
|
|
- (void)_resetToLastSeconds
|
|
{
|
|
self.setHours(23);
|
|
self.setMinutes(59);
|
|
self.setSeconds(59);
|
|
self.setMilliseconds(99);
|
|
}
|
|
|
|
@end
|