Skip to content

Commit 95f7061

Browse files
author
Vladimir Enchev
committed
Merge pull request NativeScript#1128 from NativeScript/time-picker-min-max
time picker minHour, maxHour, minMinute and maxMinute properties added
2 parents fabe0ba + c2fc36b commit 95f7061

File tree

5 files changed

+315
-52
lines changed

5 files changed

+315
-52
lines changed

apps/tests/ui/time-picker/time-picker-tests.ts

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,24 @@ export function test_WhenCreated_HourIsUndefined() {
6767
});
6868
}
6969

70+
export function test_WhenCreated_MinHourIs1() {
71+
helper.buildUIAndRunTest(_createTimePicker(), function (views: Array<viewModule.View>) {
72+
var timePicker = <timePickerModule.TimePicker>views[0];
73+
var actualValue = timePicker.minHour;
74+
var expectedValue = 1;
75+
TKUnit.assert(actualValue === expectedValue, "Actual: " + actualValue + "; Expected: " + expectedValue);
76+
});
77+
}
78+
79+
export function test_WhenCreated_MaxHourIs23() {
80+
helper.buildUIAndRunTest(_createTimePicker(), function (views: Array<viewModule.View>) {
81+
var timePicker = <timePickerModule.TimePicker>views[0];
82+
var actualValue = timePicker.maxHour;
83+
var expectedValue = 23;
84+
TKUnit.assert(actualValue === expectedValue, "Actual: " + actualValue + "; Expected: " + expectedValue);
85+
});
86+
}
87+
7088
export function test_WhenCreated_MinuteIsUndefined() {
7189
helper.buildUIAndRunTest(_createTimePicker(), function (views: Array<viewModule.View>) {
7290
var timePicker = <timePickerModule.TimePicker>views[0];
@@ -76,6 +94,108 @@ export function test_WhenCreated_MinuteIsUndefined() {
7694
});
7795
}
7896

97+
export function test_WhenCreated_MinMinuteIs0() {
98+
helper.buildUIAndRunTest(_createTimePicker(), function (views: Array<viewModule.View>) {
99+
var timePicker = <timePickerModule.TimePicker>views[0];
100+
var actualValue = timePicker.minMinute;
101+
var expectedValue = 0;
102+
TKUnit.assert(actualValue === expectedValue, "Actual: " + actualValue + "; Expected: " + expectedValue);
103+
});
104+
}
105+
106+
export function test_WhenCreated_MaxMinuteIs59() {
107+
helper.buildUIAndRunTest(_createTimePicker(), function (views: Array<viewModule.View>) {
108+
var timePicker = <timePickerModule.TimePicker>views[0];
109+
var actualValue = timePicker.maxMinute;
110+
var expectedValue = 59;
111+
TKUnit.assert(actualValue === expectedValue, "Actual: " + actualValue + "; Expected: " + expectedValue);
112+
});
113+
}
114+
115+
export function testHourThrowExceptionWhenLessThanMinHour() {
116+
helper.buildUIAndRunTest(_createTimePicker(), function (views: Array<viewModule.View>) {
117+
var timePicker = <timePickerModule.TimePicker>views[0];
118+
timePicker.minHour = 13;
119+
TKUnit.assertThrows(function () {
120+
timePicker.hour = timePicker.minHour - 1;
121+
}, "Setting hour property to a value less than minHour property value should throw.");
122+
});
123+
}
124+
125+
export function testHourThrowExceptionWhenGreaterThanMaxHour() {
126+
helper.buildUIAndRunTest(_createTimePicker(), function (views: Array<viewModule.View>) {
127+
var timePicker = <timePickerModule.TimePicker>views[0];
128+
timePicker.maxHour = 13;
129+
TKUnit.assertThrows(function () {
130+
timePicker.hour = timePicker.maxHour + 1;;
131+
}, "Setting hour property to a value greater than maxHour property value should throw.");
132+
});
133+
}
134+
135+
export function testMinuteThrowExceptionWhenLessThanMinMinute() {
136+
helper.buildUIAndRunTest(_createTimePicker(), function (views: Array<viewModule.View>) {
137+
var timePicker = <timePickerModule.TimePicker>views[0];
138+
timePicker.minMinute = 13;
139+
TKUnit.assertThrows(function () {
140+
timePicker.minute = timePicker.minMinute - 1;
141+
}, "Setting hour property to a value less than minHour property value should throw.");
142+
});
143+
}
144+
145+
export function testMinuteThrowExceptionWhenGreaterThanMaxMinute() {
146+
helper.buildUIAndRunTest(_createTimePicker(), function (views: Array<viewModule.View>) {
147+
var timePicker = <timePickerModule.TimePicker>views[0];
148+
timePicker.maxMinute = 13;
149+
TKUnit.assertThrows(function () {
150+
timePicker.minute = timePicker.maxMinute + 1;;
151+
}, "Setting hour property to a value greater than maxHour property value should throw.");
152+
});
153+
}
154+
155+
export function testHourFromNativeEqualToMinHourWhenLessThanMinHour() {
156+
helper.buildUIAndRunTest(_createTimePicker(), function (views: Array<viewModule.View>) {
157+
var timePicker = <timePickerModule.TimePicker>views[0];
158+
var expectedValue = 13;
159+
timePicker.minHour = expectedValue;
160+
timePickerTestsNative.setNativeHour(timePicker, expectedValue - 1);
161+
var actualValue = timePickerTestsNative.getNativeHour(timePicker);
162+
TKUnit.assert(actualValue === expectedValue, "Actual: " + actualValue + "; Expected: " + expectedValue);
163+
});
164+
}
165+
166+
export function testHourFromNativeEqualToMaxHourWhenGreaterThanMaxHour() {
167+
helper.buildUIAndRunTest(_createTimePicker(), function (views: Array<viewModule.View>) {
168+
var timePicker = <timePickerModule.TimePicker>views[0];
169+
var expectedValue = 13;
170+
timePicker.maxHour = expectedValue;
171+
timePickerTestsNative.setNativeHour(timePicker, expectedValue + 1);
172+
var actualValue = timePickerTestsNative.getNativeHour(timePicker);
173+
TKUnit.assert(actualValue === expectedValue, "Actual: " + actualValue + "; Expected: " + expectedValue);
174+
});
175+
}
176+
177+
export function testMinuteFromNativeEqualToMinMinuteWhenLessThanMinMinute() {
178+
helper.buildUIAndRunTest(_createTimePicker(), function (views: Array<viewModule.View>) {
179+
var timePicker = <timePickerModule.TimePicker>views[0];
180+
var expectedValue = 13;
181+
timePicker.minMinute = expectedValue;
182+
timePickerTestsNative.setNativeMinute(timePicker, expectedValue - 1);
183+
var actualValue = timePickerTestsNative.getNativeMinute(timePicker);
184+
TKUnit.assert(actualValue === expectedValue, "Actual: " + actualValue + "; Expected: " + expectedValue);
185+
});
186+
}
187+
188+
export function testMinuteFromNativeEqualToMaxMinuteWhenGreaterThanMaxMinute() {
189+
helper.buildUIAndRunTest(_createTimePicker(), function (views: Array<viewModule.View>) {
190+
var timePicker = <timePickerModule.TimePicker>views[0];
191+
var expectedValue = 13;
192+
timePicker.maxMinute = expectedValue;
193+
timePickerTestsNative.setNativeMinute(timePicker, expectedValue + 1);
194+
var actualValue = timePickerTestsNative.getNativeMinute(timePicker);
195+
TKUnit.assert(actualValue === expectedValue, "Actual: " + actualValue + "; Expected: " + expectedValue);
196+
});
197+
}
198+
79199
export function testHourFromLocalToNative() {
80200
helper.buildUIAndRunTest(_createTimePicker(), function (views: Array<viewModule.View>) {
81201
var timePicker = <timePickerModule.TimePicker>views[0];

ui/time-picker/time-picker-common.ts

Lines changed: 82 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,62 @@
22
import dependencyObservable = require("ui/core/dependency-observable");
33
import proxy = require("ui/core/proxy");
44
import view = require("ui/core/view");
5+
import types = require("utils/types");
6+
7+
function isHourValid(value: number): boolean {
8+
return types.isNumber(value) && value >= 1 && value <= 23;
9+
}
10+
11+
function isMinuteValid(value: number): boolean {
12+
return types.isNumber(value) && value >= 0 && value <= 59;
13+
}
14+
15+
export function getValidHour(hour: number, minHour: number, maxHour: number): number {
16+
let hourValue = hour;
17+
18+
if (minHour && hour < minHour) {
19+
hourValue = minHour
20+
}
21+
22+
if (maxHour && hour > maxHour) {
23+
hourValue = maxHour
24+
}
25+
26+
return hourValue;
27+
}
28+
29+
export function getValidMinute(minute: number, minMinute: number, maxMinute: number): number {
30+
let minuteValue = minute;
31+
32+
if (minMinute && minute < minMinute) {
33+
minuteValue = minMinute
34+
}
35+
36+
if (maxMinute && minute > maxMinute) {
37+
minuteValue = maxMinute
38+
}
39+
40+
return minuteValue;
41+
}
542

643
export class TimePicker extends view.View implements definition.TimePicker {
7-
public static hourProperty = new dependencyObservable.Property("hour", "TimePicker", new proxy.PropertyMetadata(undefined));
8-
public static minuteProperty = new dependencyObservable.Property("minute", "TimePicker", new proxy.PropertyMetadata(undefined));
44+
public static hourProperty = new dependencyObservable.Property("hour", "TimePicker",
45+
new proxy.PropertyMetadata(undefined, dependencyObservable.PropertyMetadataSettings.None, undefined, isHourValid));
46+
47+
public static minHourProperty = new dependencyObservable.Property("minHour", "TimePicker",
48+
new proxy.PropertyMetadata(1, dependencyObservable.PropertyMetadataSettings.None, undefined, isHourValid));
49+
50+
public static maxHourProperty = new dependencyObservable.Property("maxHour", "TimePicker",
51+
new proxy.PropertyMetadata(23, dependencyObservable.PropertyMetadataSettings.None, undefined, isHourValid));
52+
53+
public static minuteProperty = new dependencyObservable.Property("minute", "TimePicker",
54+
new proxy.PropertyMetadata(undefined, dependencyObservable.PropertyMetadataSettings.None, undefined, isMinuteValid));
55+
56+
public static minMinuteProperty = new dependencyObservable.Property("minMinute", "TimePicker",
57+
new proxy.PropertyMetadata(0, dependencyObservable.PropertyMetadataSettings.None, undefined, isMinuteValid));
58+
59+
public static maxMinuteProperty = new dependencyObservable.Property("maxMinute", "TimePicker",
60+
new proxy.PropertyMetadata(59, dependencyObservable.PropertyMetadataSettings.None, undefined, isMinuteValid));
961

1062
constructor() {
1163
super();
@@ -24,4 +76,32 @@ export class TimePicker extends view.View implements definition.TimePicker {
2476
set minute(value: number) {
2577
this._setValue(TimePicker.minuteProperty, value);
2678
}
79+
80+
get maxHour(): number {
81+
return this._getValue(TimePicker.maxHourProperty);
82+
}
83+
set maxHour(value: number) {
84+
this._setValue(TimePicker.maxHourProperty, value);
85+
}
86+
87+
get maxMinute(): number {
88+
return this._getValue(TimePicker.maxMinuteProperty);
89+
}
90+
set maxMinute(value: number) {
91+
this._setValue(TimePicker.maxMinuteProperty, value);
92+
}
93+
94+
get minHour(): number {
95+
return this._getValue(TimePicker.minHourProperty);
96+
}
97+
set minHour(value: number) {
98+
this._setValue(TimePicker.minHourProperty, value);
99+
}
100+
101+
get minMinute(): number {
102+
return this._getValue(TimePicker.minMinuteProperty);
103+
}
104+
set minMinute(value: number) {
105+
this._setValue(TimePicker.minMinuteProperty, value);
106+
}
27107
}

ui/time-picker/time-picker.android.ts

Lines changed: 51 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -2,27 +2,41 @@
22
import dependencyObservable = require("ui/core/dependency-observable");
33
import proxy = require("ui/core/proxy");
44
import utils = require("utils/utils")
5+
import types = require("utils/types")
56

67
function onHourPropertyChanged(data: dependencyObservable.PropertyChangeData) {
78
var picker = <TimePicker>data.object;
8-
picker._setNativeHourSilently(data.newValue);
9+
10+
var validValue = common.getValidHour(data.newValue, picker.minHour, picker.maxHour);
11+
if (validValue === data.newValue) {
12+
picker._setNativeValueSilently(data.newValue, picker.minute);
13+
} else {
14+
throw new Error(`Hour property value (${data.newValue}) is not valid. Min value: (${picker.minHour} ), max value: (${picker.maxHour} ).`);
15+
}
916
}
1017

1118
(<proxy.PropertyMetadata>common.TimePicker.hourProperty.metadata).onSetNativeValue = onHourPropertyChanged;
1219

1320
function onMinutePropertyChanged(data: dependencyObservable.PropertyChangeData) {
1421
var picker = <TimePicker>data.object;
15-
picker._setNativeMinuteSilently(data.newValue);
22+
23+
var validValue = common.getValidMinute(data.newValue, picker.minMinute, picker.maxMinute);
24+
if (validValue === data.newValue) {
25+
picker._setNativeValueSilently(picker.hour, data.newValue);
26+
} else {
27+
throw new Error(`Minute property value (${data.newValue}) is not valid. Min value: (${picker.minMinute} ), max value: (${picker.maxMinute} ).`);
28+
}
1629
}
1730

1831
(<proxy.PropertyMetadata>common.TimePicker.minuteProperty.metadata).onSetNativeValue = onMinutePropertyChanged;
1932

2033
global.moduleMerge(common, exports);
2134

35+
var SDK = android.os.Build.VERSION.SDK_INT;
36+
2237
export class TimePicker extends common.TimePicker {
2338
private _android: android.widget.TimePicker;
2439
private _listener: android.widget.TimePicker.OnTimeChangedListener;
25-
private _isSettingTime: boolean = false;
2640

2741
get android(): android.widget.TimePicker {
2842
return this._android;
@@ -35,51 +49,51 @@ export class TimePicker extends common.TimePicker {
3549

3650
this._listener = new android.widget.TimePicker.OnTimeChangedListener(
3751
<utils.Owned & android.widget.TimePicker.IOnTimeChangedListener>{
38-
get owner() {
39-
return that.get();
40-
},
52+
get owner() {
53+
return that.get();
54+
},
4155

42-
onTimeChanged: function (picker: android.widget.TimePicker, hour: number, minute: number) {
43-
if (this.owner && !this.owner._isSettingTime) {
56+
onTimeChanged: function (picker: android.widget.TimePicker, hour: number, minute: number) {
57+
if (this.owner) {
4458

45-
if (hour !== this.owner.hour) {
46-
this.owner._onPropertyChangedFromNative(common.TimePicker.hourProperty, hour);
47-
}
59+
this.owner._setNativeValueSilently(hour, minute);
60+
61+
if (hour !== this.owner.hour) {
62+
this.owner._onPropertyChangedFromNative(common.TimePicker.hourProperty, hour);
63+
}
4864

49-
if (minute !== this.owner.minute) {
50-
this.owner._onPropertyChangedFromNative(common.TimePicker.minuteProperty, minute);
65+
if (minute !== this.owner.minute) {
66+
this.owner._onPropertyChangedFromNative(common.TimePicker.minuteProperty, minute);
67+
}
5168
}
5269
}
53-
}
54-
});
70+
});
5571
this._android.setOnTimeChangedListener(this._listener);
5672
}
5773

58-
public _setNativeHourSilently(newValue: number) {
59-
if (!this.android) {
60-
return;
61-
}
74+
public _setNativeValueSilently(hour: number, minute: number) {
75+
if (this.android) {
76+
this.android.setOnTimeChangedListener(null);
6277

63-
this._isSettingTime = true;
64-
try {
65-
this.android.setCurrentHour(new java.lang.Integer(newValue));
66-
}
67-
finally {
68-
this._isSettingTime = false;
69-
}
70-
}
78+
if (types.isNumber(hour)) {
79+
var h = new java.lang.Integer(common.getValidHour(hour, this.minHour, this.maxHour));
80+
if (SDK >= 23) {
81+
(<any>this.android).setHour(h);
82+
} else {
83+
this.android.setCurrentHour(h);
84+
}
85+
}
7186

72-
public _setNativeMinuteSilently(newValue: number) {
73-
if (!this.android) {
74-
return;
75-
}
87+
if (types.isNumber(minute)) {
88+
var m = new java.lang.Integer(common.getValidMinute(minute, this.minMinute, this.maxMinute));
89+
if (SDK >= 23) {
90+
(<any>this.android).setMinute(m);
91+
} else {
92+
this.android.setCurrentMinute(m);
93+
}
94+
}
7695

77-
this._isSettingTime = true;
78-
try {
79-
this.android.setCurrentMinute(new java.lang.Integer(newValue));
80-
}
81-
finally {
82-
this._isSettingTime = false;
96+
this.android.setOnTimeChangedListener(this._listener);
8397
}
8498
}
8599
}

ui/time-picker/time-picker.d.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,5 +33,25 @@ declare module "ui/time-picker" {
3333
* Gets or sets the time minute.
3434
*/
3535
minute: number;
36+
37+
/**
38+
* Gets or sets the max time hour.
39+
*/
40+
maxHour: number;
41+
42+
/**
43+
* Gets or sets the max time minute.
44+
*/
45+
maxMinute: number;
46+
47+
/**
48+
* Gets or sets the min time hour.
49+
*/
50+
minHour: number;
51+
52+
/**
53+
* Gets or sets the min time minute.
54+
*/
55+
minMinute: number;
3656
}
3757
}

0 commit comments

Comments
 (0)