time-picker min max logic fixed

This commit is contained in:
Vladimir Enchev
2015-11-25 10:22:12 +02:00
parent 79f009fb38
commit fd33f5144b
5 changed files with 243 additions and 173 deletions

View File

@ -29,7 +29,7 @@ function _createTimePicker(hour?: number, minute?: number): timePickerModule.Tim
if (minute) {
timePicker.minute = minute;
}
return timePicker;
}
@ -58,38 +58,38 @@ if (platform.device.os === platform.platformNames.ios) {
}
}
export function test_WhenCreated_HourIsUndefined() {
export function test_WhenCreated_HourIsCurrentHour() {
helper.buildUIAndRunTest(_createTimePicker(), function (views: Array<viewModule.View>) {
var timePicker = <timePickerModule.TimePicker>views[0];
var actualValue = timePicker.hour;
var expectedValue = undefined;
var expectedValue = timePickerTestsNative.getNativeHour(timePicker);
TKUnit.assert(actualValue === expectedValue, "Actual: " + actualValue + "; Expected: " + expectedValue);
});
}
export function test_WhenCreated_MinHourIs1() {
export function test_WhenCreated_MinHourIs0() {
helper.buildUIAndRunTest(_createTimePicker(), function (views: Array<viewModule.View>) {
var timePicker = <timePickerModule.TimePicker>views[0];
var actualValue = timePicker.minHour;
var expectedValue = 1;
var expectedValue = 0;
TKUnit.assert(actualValue === expectedValue, "Actual: " + actualValue + "; Expected: " + expectedValue);
});
}
export function test_WhenCreated_MaxHourIs24() {
export function test_WhenCreated_MaxHourIs23() {
helper.buildUIAndRunTest(_createTimePicker(), function (views: Array<viewModule.View>) {
var timePicker = <timePickerModule.TimePicker>views[0];
var actualValue = timePicker.maxHour;
var expectedValue = 24;
var expectedValue = 23;
TKUnit.assert(actualValue === expectedValue, "Actual: " + actualValue + "; Expected: " + expectedValue);
});
}
export function test_WhenCreated_MinuteIsUndefined() {
export function test_WhenCreated_MinuteIsCurrentMinute() {
helper.buildUIAndRunTest(_createTimePicker(), function (views: Array<viewModule.View>) {
var timePicker = <timePickerModule.TimePicker>views[0];
var actualValue = timePicker.minute;
var expectedValue = undefined;
var expectedValue = timePickerTestsNative.getNativeMinute(timePicker);
TKUnit.assert(actualValue === expectedValue, "Actual: " + actualValue + "; Expected: " + expectedValue);
});
}
@ -115,84 +115,96 @@ export function test_WhenCreated_MaxMinuteIs59() {
export function testHourThrowExceptionWhenLessThanMinHour() {
helper.buildUIAndRunTest(_createTimePicker(), function (views: Array<viewModule.View>) {
var timePicker = <timePickerModule.TimePicker>views[0];
timePicker.minHour = 13;
timePicker.hour = 14;
timePicker.minHour = timePicker.hour - 1;
TKUnit.assertThrows(function () {
timePicker.hour = timePicker.minHour - 1;
}, "Setting hour property to a value less than minHour property value should throw.");
});
}
export function testMinHourThrowExceptionWhenHourLessThanMinHour() {
helper.buildUIAndRunTest(_createTimePicker(), function (views: Array<viewModule.View>) {
var timePicker = <timePickerModule.TimePicker>views[0];
timePicker.hour = 14;
TKUnit.assertThrows(function () {
timePicker.minHour = timePicker.hour + 1;
}, "Setting minHour property to a greater than hour property value should throw.");
});
}
export function testHourThrowExceptionWhenGreaterThanMaxHour() {
helper.buildUIAndRunTest(_createTimePicker(), function (views: Array<viewModule.View>) {
var timePicker = <timePickerModule.TimePicker>views[0];
timePicker.maxHour = 13;
timePicker.hour = 14;
timePicker.maxHour = timePicker.hour + 1;
TKUnit.assertThrows(function () {
timePicker.hour = timePicker.maxHour + 1;;
}, "Setting hour property to a value greater than maxHour property value should throw.");
});
}
export function testMaxHourThrowExceptionWhenHourGreaterThanMaxHour() {
helper.buildUIAndRunTest(_createTimePicker(), function (views: Array<viewModule.View>) {
var timePicker = <timePickerModule.TimePicker>views[0];
timePicker.hour = 14;
TKUnit.assertThrows(function () {
timePicker.maxHour = timePicker.hour - 1;
}, "Setting maxHour property to a value less than hour property value should throw.");
});
}
export function testMinuteThrowExceptionWhenLessThanMinMinute() {
helper.buildUIAndRunTest(_createTimePicker(), function (views: Array<viewModule.View>) {
var timePicker = <timePickerModule.TimePicker>views[0];
timePicker.minMinute = 13;
timePicker.hour = 14;
timePicker.minute = 13;
timePicker.minHour = timePicker.hour;
timePicker.minMinute = timePicker.minute;
TKUnit.assertThrows(function () {
timePicker.minute = timePicker.minMinute - 1;
}, "Setting hour property to a value less than minHour property value should throw.");
}, "Setting minute property to a value less than minMinute property value should throw.");
});
}
export function testMinMinuteThrowExceptionWhenMinuteLessThanMinMinute() {
helper.buildUIAndRunTest(_createTimePicker(), function (views: Array<viewModule.View>) {
var timePicker = <timePickerModule.TimePicker>views[0];
timePicker.hour = 14;
timePicker.minute = 13;
timePicker.minHour = timePicker.hour;
TKUnit.assertThrows(function () {
timePicker.minMinute = timePicker.minute + 1;
}, "Setting minMinute property to a value greater than minute property value should throw.");
});
}
export function testMinuteThrowExceptionWhenGreaterThanMaxMinute() {
helper.buildUIAndRunTest(_createTimePicker(), function (views: Array<viewModule.View>) {
var timePicker = <timePickerModule.TimePicker>views[0];
timePicker.maxMinute = 13;
timePicker.hour = 14;
timePicker.minute = 13;
timePicker.maxHour = timePicker.hour;
timePicker.maxMinute = timePicker.minute;
TKUnit.assertThrows(function () {
timePicker.minute = timePicker.maxMinute + 1;;
}, "Setting hour property to a value greater than maxHour property value should throw.");
timePicker.minute = timePicker.maxMinute + 1;
}, "Setting minute property to a value greater than maxMinute property value should throw.");
});
}
export function testHourFromNativeEqualToMinHourWhenLessThanMinHour() {
export function testMaxMinuteThrowExceptionWhenMinuteGreaterThanMaxMinute() {
helper.buildUIAndRunTest(_createTimePicker(), function (views: Array<viewModule.View>) {
var timePicker = <timePickerModule.TimePicker>views[0];
var expectedValue = 13;
timePicker.minHour = expectedValue;
timePickerTestsNative.setNativeHour(timePicker, expectedValue - 1);
var actualValue = timePickerTestsNative.getNativeHour(timePicker);
TKUnit.assert(actualValue === expectedValue, "Actual: " + actualValue + "; Expected: " + expectedValue);
});
}
timePicker.hour = 14;
timePicker.minute = 13;
export function testHourFromNativeEqualToMaxHourWhenGreaterThanMaxHour() {
helper.buildUIAndRunTest(_createTimePicker(), function (views: Array<viewModule.View>) {
var timePicker = <timePickerModule.TimePicker>views[0];
var expectedValue = 13;
timePicker.maxHour = expectedValue;
timePickerTestsNative.setNativeHour(timePicker, expectedValue + 1);
var actualValue = timePickerTestsNative.getNativeHour(timePicker);
TKUnit.assert(actualValue === expectedValue, "Actual: " + actualValue + "; Expected: " + expectedValue);
});
}
export function testMinuteFromNativeEqualToMinMinuteWhenLessThanMinMinute() {
helper.buildUIAndRunTest(_createTimePicker(), function (views: Array<viewModule.View>) {
var timePicker = <timePickerModule.TimePicker>views[0];
var expectedValue = 13;
timePicker.minMinute = expectedValue;
timePickerTestsNative.setNativeMinute(timePicker, expectedValue - 1);
var actualValue = timePickerTestsNative.getNativeMinute(timePicker);
TKUnit.assert(actualValue === expectedValue, "Actual: " + actualValue + "; Expected: " + expectedValue);
});
}
export function testMinuteFromNativeEqualToMaxMinuteWhenGreaterThanMaxMinute() {
helper.buildUIAndRunTest(_createTimePicker(), function (views: Array<viewModule.View>) {
var timePicker = <timePickerModule.TimePicker>views[0];
var expectedValue = 13;
timePicker.maxMinute = expectedValue;
timePickerTestsNative.setNativeMinute(timePicker, expectedValue + 1);
var actualValue = timePickerTestsNative.getNativeMinute(timePicker);
TKUnit.assert(actualValue === expectedValue, "Actual: " + actualValue + "; Expected: " + expectedValue);
timePicker.maxHour = timePicker.hour;
TKUnit.assertThrows(function () {
timePicker.maxMinute = timePicker.minute - 1;
}, "Setting maxMinute property to a value less than minute property value should throw.");
});
}

View File

@ -5,59 +5,138 @@ import view = require("ui/core/view");
import types = require("utils/types");
function isHourValid(value: number): boolean {
return types.isNumber(value) && value >= 1 && value <= 24;
return types.isNumber(value) && value >= 0 && value <= 23;
}
function isMinuteValid(value: number): boolean {
return types.isNumber(value) && value >= 0 && value <= 59;
}
export function getValidHour(hour: number, minHour: number, maxHour: number): number {
let hourValue = hour;
if (minHour && hour < minHour) {
hourValue = minHour
}
if (maxHour && hour > maxHour) {
hourValue = maxHour
}
return hourValue;
export interface Time {
hour: number;
minute: number;
}
export function getValidMinute(minute: number, minMinute: number, maxMinute: number): number {
let minuteValue = minute;
function getMinutes(hour: number): number {
return hour * 60;
}
if (minMinute && minute < minMinute) {
minuteValue = minMinute
export function isGreaterThanMinTime(picker: definition.TimePicker, hour?: number, minute?: number): boolean {
return getMinutes(types.isDefined(hour) ? hour : picker.hour) + (types.isDefined(minute) ? minute : picker.minute) >= getMinutes(picker.minHour) + picker.minMinute;
}
export function isLessThanMaxTime(picker: definition.TimePicker, hour?: number, minute?: number): boolean {
return getMinutes(types.isDefined(hour) ? hour : picker.hour) + (types.isDefined(minute) ? minute : picker.minute) <= getMinutes(picker.maxHour) + picker.maxMinute;
}
export function isValidTime(picker: definition.TimePicker): boolean {
return isGreaterThanMinTime(picker) && isLessThanMaxTime(picker);
}
export function getValidTime(picker: definition.TimePicker, hour?: number, minute?: number): Time {
let time = { hour: hour, minute: minute };
if (!isGreaterThanMinTime(picker, hour, minute)) {
time = { hour: picker.minHour, minute: picker.minMinute };
}
if (maxMinute && minute > maxMinute) {
minuteValue = maxMinute
if (!isLessThanMaxTime(picker, hour, minute)) {
time = { hour: picker.maxHour, minute: picker.maxMinute };
}
return minuteValue;
return time;
}
function toString(value: number): string {
return value < 10 ? `0${value}` : `${value}`;
}
function getMinMaxTimeErrorMessage(picker: definition.TimePicker): string {
return `Min time: (${toString(picker.minHour) }:${toString(picker.minMinute) }), max time: (${toString(picker.maxHour) }:${toString(picker.maxMinute) })`;
}
function getErrorMessage(picker: definition.TimePicker, propertyName: string, newValue: number): string {
return `${propertyName} property value (${toString(newValue) }:${toString(picker.minute) }) is not valid. ${getMinMaxTimeErrorMessage(picker) }.`;
}
function onHourPropertyChanged(data: dependencyObservable.PropertyChangeData) {
var picker = <definition.TimePicker>data.object;
if (isValidTime(picker)) {
picker._setNativeTime();
} else {
throw new Error(getErrorMessage(picker, "Hour", data.newValue));
}
}
function onMinutePropertyChanged(data: dependencyObservable.PropertyChangeData) {
var picker = <definition.TimePicker>data.object;
if (isValidTime(picker)) {
picker._setNativeTime();
} else {
throw new Error(getErrorMessage(picker, "Minute", data.newValue));
}
}
function onMinMinutePropertyChanged(data: dependencyObservable.PropertyChangeData) {
var picker = <definition.TimePicker>data.object;
if (isValidTime(picker)) {
picker._setNativeMinTime();
} else {
throw new Error(getErrorMessage(picker, "Minute", data.newValue));
}
}
function onMaxMinutePropertyChanged(data: dependencyObservable.PropertyChangeData) {
var picker = <definition.TimePicker>data.object;
if (isValidTime(picker)) {
picker._setNativeMaxTime();
} else {
throw new Error(getErrorMessage(picker, "Minute", data.newValue));
}
}
function onMinHourPropertyChanged(data: dependencyObservable.PropertyChangeData) {
var picker = <definition.TimePicker>data.object;
if (isValidTime(picker)) {
picker._setNativeMinTime();
} else {
throw new Error(getErrorMessage(picker, "Hour", data.newValue));
}
}
function onMaxHourPropertyChanged(data: dependencyObservable.PropertyChangeData) {
var picker = <definition.TimePicker>data.object;
if (isValidTime(picker)) {
picker._setNativeMaxTime();
} else {
throw new Error(getErrorMessage(picker, "Hour", data.newValue));
}
}
export class TimePicker extends view.View implements definition.TimePicker {
public static hourProperty = new dependencyObservable.Property("hour", "TimePicker",
new proxy.PropertyMetadata(undefined, dependencyObservable.PropertyMetadataSettings.None, undefined, isHourValid));
new proxy.PropertyMetadata(0, dependencyObservable.PropertyMetadataSettings.None, onHourPropertyChanged, isHourValid));
public static minHourProperty = new dependencyObservable.Property("minHour", "TimePicker",
new proxy.PropertyMetadata(1, dependencyObservable.PropertyMetadataSettings.None, undefined, isHourValid));
new proxy.PropertyMetadata(0, dependencyObservable.PropertyMetadataSettings.None, onMinHourPropertyChanged, isHourValid));
public static maxHourProperty = new dependencyObservable.Property("maxHour", "TimePicker",
new proxy.PropertyMetadata(24, dependencyObservable.PropertyMetadataSettings.None, undefined, isHourValid));
new proxy.PropertyMetadata(23, dependencyObservable.PropertyMetadataSettings.None, onMaxHourPropertyChanged, isHourValid));
public static minuteProperty = new dependencyObservable.Property("minute", "TimePicker",
new proxy.PropertyMetadata(undefined, dependencyObservable.PropertyMetadataSettings.None, undefined, isMinuteValid));
new proxy.PropertyMetadata(0, dependencyObservable.PropertyMetadataSettings.None, onMinutePropertyChanged, isMinuteValid));
public static minMinuteProperty = new dependencyObservable.Property("minMinute", "TimePicker",
new proxy.PropertyMetadata(0, dependencyObservable.PropertyMetadataSettings.None, undefined, isMinuteValid));
new proxy.PropertyMetadata(0, dependencyObservable.PropertyMetadataSettings.None, onMinMinutePropertyChanged, isMinuteValid));
public static maxMinuteProperty = new dependencyObservable.Property("maxMinute", "TimePicker",
new proxy.PropertyMetadata(59, dependencyObservable.PropertyMetadataSettings.None, undefined, isMinuteValid));
new proxy.PropertyMetadata(59, dependencyObservable.PropertyMetadataSettings.None, onMaxMinutePropertyChanged, isMinuteValid));
constructor() {
super();
@ -104,4 +183,16 @@ export class TimePicker extends view.View implements definition.TimePicker {
set minMinute(value: number) {
this._setValue(TimePicker.minMinuteProperty, value);
}
public _setNativeTime() {
//
}
public _setNativeMinTime() {
//
}
public _setNativeMaxTime() {
//
}
}

View File

@ -4,32 +4,6 @@ import proxy = require("ui/core/proxy");
import utils = require("utils/utils")
import types = require("utils/types")
function onHourPropertyChanged(data: dependencyObservable.PropertyChangeData) {
var picker = <TimePicker>data.object;
var validValue = common.getValidHour(data.newValue, picker.minHour, picker.maxHour);
if (validValue === data.newValue) {
picker._setNativeValueSilently(data.newValue, picker.minute);
} else {
throw new Error(`Hour property value (${data.newValue}) is not valid. Min value: (${picker.minHour} ), max value: (${picker.maxHour} ).`);
}
}
(<proxy.PropertyMetadata>common.TimePicker.hourProperty.metadata).onSetNativeValue = onHourPropertyChanged;
function onMinutePropertyChanged(data: dependencyObservable.PropertyChangeData) {
var picker = <TimePicker>data.object;
var validValue = common.getValidMinute(data.newValue, picker.minMinute, picker.maxMinute);
if (validValue === data.newValue) {
picker._setNativeValueSilently(picker.hour, data.newValue);
} else {
throw new Error(`Minute property value (${data.newValue}) is not valid. Min value: (${picker.minMinute} ), max value: (${picker.maxMinute} ).`);
}
}
(<proxy.PropertyMetadata>common.TimePicker.minuteProperty.metadata).onSetNativeValue = onMinutePropertyChanged;
global.moduleMerge(common, exports);
var SDK = android.os.Build.VERSION.SDK_INT;
@ -55,45 +29,53 @@ export class TimePicker extends common.TimePicker {
onTimeChanged: function (picker: android.widget.TimePicker, hour: number, minute: number) {
if (this.owner) {
this.owner._setNativeValueSilently(hour, minute);
if (hour !== this.owner.hour) {
this.owner._onPropertyChangedFromNative(common.TimePicker.hourProperty, hour);
}
if (minute !== this.owner.minute) {
this.owner._onPropertyChangedFromNative(common.TimePicker.minuteProperty, minute);
}
var validTime = common.getValidTime(this.owner, hour, minute);
this.owner._setNativeValueSilently(validTime.hour, validTime.minute);
}
}
});
this._android.setOnTimeChangedListener(this._listener);
var c = java.util.Calendar.getInstance();
if (this.hour === common.TimePicker.hourProperty.metadata.defaultValue) {
this.hour = c.get(java.util.Calendar.HOUR_OF_DAY);
}
if (this.minute === common.TimePicker.minuteProperty.metadata.defaultValue) {
this.minute = c.get(java.util.Calendar.MINUTE);
}
var validTime = common.getValidTime(this, this.hour, this.minute);
this._setNativeValueSilently(validTime.hour, validTime.minute);
}
public _setNativeValueSilently(hour: number, minute: number) {
private _setNativeValueSilently(hour: number, minute: number) {
if (this.android) {
this.android.setOnTimeChangedListener(null);
if (types.isNumber(hour)) {
var h = new java.lang.Integer(common.getValidHour(hour, this.minHour, this.maxHour));
if (SDK >= 23) {
(<any>this.android).setHour(h);
} else {
this.android.setCurrentHour(h);
}
var h = new java.lang.Integer(hour);
if (SDK >= 23) {
(<any>this.android).setHour(h);
} else {
this.android.setCurrentHour(h);
}
if (types.isNumber(minute)) {
var m = new java.lang.Integer(common.getValidMinute(minute, this.minMinute, this.maxMinute));
if (SDK >= 23) {
(<any>this.android).setMinute(m);
} else {
this.android.setCurrentMinute(m);
}
var m = new java.lang.Integer(minute);
if (SDK >= 23) {
(<any>this.android).setMinute(m);
} else {
this.android.setCurrentMinute(m);
}
this.minute = minute;
this.hour = hour;
this.android.setOnTimeChangedListener(this._listener);
}
}
public _setNativeTime() {
this._setNativeValueSilently(this.hour, this.minute);
}
}

View File

@ -53,5 +53,9 @@ declare module "ui/time-picker" {
* Gets or sets the min time minute.
*/
minMinute: number;
_setNativeTime(): void;
_setNativeMinTime(): void;
_setNativeMaxTime(): void;
}
}

View File

@ -3,41 +3,16 @@ import dependencyObservable = require("ui/core/dependency-observable");
import proxy = require("ui/core/proxy");
import types = require("utils/types");
function getDate(date: NSDate, hour?: number, minute?: number): NSDate {
var comps = NSCalendar.currentCalendar().componentsFromDate(NSCalendarUnit.NSCalendarUnitHour | NSCalendarUnit.NSCalendarUnitMinute, date);
if (hour) {
comps.hour = hour;
}
if (minute) {
comps.minute = minute;
}
function getDate(hour: number, minute: number): NSDate {
var comps = NSDateComponents.alloc().init();
comps.hour = hour;
comps.minute = minute;
return NSCalendar.currentCalendar().dateFromComponents(comps);
}
function onHourPropertyChanged(data: dependencyObservable.PropertyChangeData) {
var picker = <TimePicker>data.object;
var validValue = common.getValidHour(data.newValue, picker.minHour, picker.maxHour);
if (validValue === data.newValue) {
picker.ios.setDateAnimated(getDate(picker.ios.date, data.newValue, picker.minute), false);
} else {
throw new Error(`Hour property value (${data.newValue}) is not valid. Min value: (${picker.minHour} ), max value: (${picker.maxHour} ).`);
}
function getComponents(date: NSDate): NSDateComponents {
return NSCalendar.currentCalendar().componentsFromDate(NSCalendarUnit.NSCalendarUnitHour | NSCalendarUnit.NSCalendarUnitMinute, date);
}
(<proxy.PropertyMetadata>common.TimePicker.hourProperty.metadata).onSetNativeValue = onHourPropertyChanged;
function onMinutePropertyChanged(data: dependencyObservable.PropertyChangeData) {
var picker = <TimePicker>data.object;
var validValue = common.getValidMinute(data.newValue, picker.minMinute, picker.maxMinute);
if (validValue === data.newValue) {
picker.ios.setDateAnimated(getDate(picker.ios.date, picker.hour, data.newValue), false);
} else {
throw new Error(`Minute property value (${data.newValue}) is not valid. Min value: (${picker.minMinute} ), max value: (${picker.maxMinute} ).`);
}
}
(<proxy.PropertyMetadata>common.TimePicker.minuteProperty.metadata).onSetNativeValue = onMinutePropertyChanged;
global.moduleMerge(common, exports);
@ -53,23 +28,31 @@ export class TimePicker extends common.TimePicker {
this._changeHandler = UITimePickerChangeHandlerImpl.initWithOwner(new WeakRef(this));
this._ios.addTargetActionForControlEvents(this._changeHandler, "valueChanged", UIControlEvents.UIControlEventValueChanged);
var comps = getComponents(NSDate.date());
this.hour = comps.hour;
this.minute = comps.minute;
}
get ios(): UIDatePicker {
return this._ios;
}
public _setNativeValueSilently(hour: number, minute: number) {
public _setNativeTime() {
if (this.ios) {
this.ios.removeTargetActionForControlEvents(this._changeHandler, "valueChanged", UIControlEvents.UIControlEventValueChanged)
this.ios.date = getDate(this.hour, this.minute);
}
}
if (types.isNumber(hour) && types.isNumber(minute)) {
this.ios.setDateAnimated(getDate(this.ios.date,
common.getValidHour(hour, this.minHour, this.maxHour),
common.getValidMinute(minute, this.minMinute, this.maxMinute)), false);
}
public _setNativeMinTime() {
if (this.ios) {
this.ios.minimumDate = getDate(this.minHour, this.minMinute);
}
}
this.ios.addTargetActionForControlEvents(this._changeHandler, "valueChanged", UIControlEvents.UIControlEventValueChanged);
public _setNativeMaxTime() {
if (this.ios) {
this.ios.maximumDate = getDate(this.maxHour, this.maxMinute);
}
}
}
@ -90,9 +73,7 @@ class UITimePickerChangeHandlerImpl extends NSObject {
return;
}
var comps = NSCalendar.currentCalendar().componentsFromDate(NSCalendarUnit.NSCalendarUnitHour | NSCalendarUnit.NSCalendarUnitMinute, sender.date);
owner._setNativeValueSilently(comps.hour, comps.minute);
comps = NSCalendar.currentCalendar().componentsFromDate(NSCalendarUnit.NSCalendarUnitHour | NSCalendarUnit.NSCalendarUnitMinute, sender.date);
var comps = getComponents(sender.date);
if (comps.hour !== owner.hour) {
owner._onPropertyChangedFromNative(common.TimePicker.hourProperty, comps.hour);