mirror of
https://github.com/cappuccino/cappuccino.git
synced 2026-09-29 21:57:41 +00:00
New: minimum/maximum support for CPNumberFormatter
Previously, minimum and maximum were not supported in CPNumberFormatter. This commit adds support for these in IB and via code. Updated unit tests included. Fixes #1829
This commit is contained in:
committed by
Aparajita Fishman
parent
72c277d9ee
commit
5fac631f6f
@@ -63,6 +63,8 @@ var NumberRegex = new RegExp('(-)?(\\d*)(\\.(\\d*))?');
|
||||
CPNumberFormatterRoundingMode _roundingMode @accessors(property=roundingMode);
|
||||
CPUInteger _minimumFractionDigits @accessors(property=minimumFractionDigits);
|
||||
CPUInteger _maximumFractionDigits @accessors(property=maximumFractionDigits);
|
||||
CPUInteger _minimum @accessors(property=minimum);
|
||||
CPUInteger _maximum @accessors(property=maximum);
|
||||
CPString _currencyCode @accessors(property=currencyCode);
|
||||
CPString _currencySymbol @accessors(property=currencySymbol);
|
||||
BOOL _generatesDecimalNumbers @accessors(property=generatesDecimalNumbers);
|
||||
@@ -81,6 +83,8 @@ var NumberRegex = new RegExp('(-)?(\\d*)(\\.(\\d*))?');
|
||||
_maximumFractionDigits = 0;
|
||||
_groupingSeparator = @",";
|
||||
_generatesDecimalNumbers = YES;
|
||||
_minimum = nil;
|
||||
_maximum = nil;
|
||||
|
||||
// FIXME Add locale support.
|
||||
_currencyCode = @"USD";
|
||||
@@ -181,8 +185,29 @@ var NumberRegex = new RegExp('(-)?(\\d*)(\\.(\\d*))?');
|
||||
|
||||
- (BOOL)getObjectValue:(id)anObject forString:(CPString)aString errorDescription:(CPString)anError
|
||||
{
|
||||
// TODO Error handling.
|
||||
var value = [self numberFromString:aString];
|
||||
// allows an empty string to pass without validation
|
||||
if (aString === @"")
|
||||
return YES;
|
||||
|
||||
var value = [self numberFromString:aString],
|
||||
error = @"";
|
||||
|
||||
// this will return false if we've received anything but a number, most likely NaN
|
||||
if (!isFinite(value))
|
||||
error = @"Value is not a number";
|
||||
else if (_minimum !== nil && value < _minimum)
|
||||
error = @"Value is less than the minimum allowed value";
|
||||
else if (_maximum !== nil && value > _maximum)
|
||||
error = @"Value is greater than the maximum allowed value";
|
||||
|
||||
if (error)
|
||||
{
|
||||
if (anError)
|
||||
AT_DEREF(anError, error);
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
AT_DEREF(anObject, value);
|
||||
|
||||
return YES;
|
||||
@@ -226,12 +251,29 @@ var NumberRegex = new RegExp('(-)?(\\d*)(\\.(\\d*))?');
|
||||
SET_NEEDS_NUMBER_HANDLER_UPDATE();
|
||||
}
|
||||
|
||||
- (void)setMinimum:(CPUInteger)aNumber
|
||||
{
|
||||
_minimum = aNumber;
|
||||
SET_NEEDS_NUMBER_HANDLER_UPDATE();
|
||||
}
|
||||
|
||||
- (void)setMaximum:(CPUInteger)aNumber
|
||||
{
|
||||
_maximum = aNumber;
|
||||
SET_NEEDS_NUMBER_HANDLER_UPDATE();
|
||||
}
|
||||
|
||||
#pragma mark Private
|
||||
|
||||
- (void)_updateNumberHandlerIfNecessary
|
||||
{
|
||||
if (!_numberHandler)
|
||||
_numberHandler = [CPDecimalNumberHandler decimalNumberHandlerWithRoundingMode:_roundingMode scale:_maximumFractionDigits raiseOnExactness:NO raiseOnOverflow:NO raiseOnUnderflow:NO raiseOnDivideByZero:YES];
|
||||
_numberHandler = [CPDecimalNumberHandler decimalNumberHandlerWithRoundingMode:_roundingMode
|
||||
scale:_maximumFractionDigits
|
||||
raiseOnExactness:NO
|
||||
raiseOnOverflow:NO
|
||||
raiseOnUnderflow:NO
|
||||
raiseOnDivideByZero:YES];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -239,6 +281,8 @@ var NumberRegex = new RegExp('(-)?(\\d*)(\\.(\\d*))?');
|
||||
var CPNumberFormatterStyleKey = @"CPNumberFormatterStyleKey",
|
||||
CPNumberFormatterMinimumFractionDigitsKey = @"CPNumberFormatterMinimumFractionDigitsKey",
|
||||
CPNumberFormatterMaximumFractionDigitsKey = @"CPNumberFormatterMaximumFractionDigitsKey",
|
||||
CPNumberFormatterMinimumKey = @"CPNumberFormatterMinimumKey",
|
||||
CPNumberFormatterMaximumKey = @"CPNumberFormatterMaximumKey",
|
||||
CPNumberFormatterRoundingModeKey = @"CPNumberFormatterRoundingModeKey",
|
||||
CPNumberFormatterGroupingSeparatorKey = @"CPNumberFormatterGroupingSeparatorKey",
|
||||
CPNumberFormatterCurrencyCodeKey = @"CPNumberFormatterCurrencyCodeKey",
|
||||
@@ -256,6 +300,8 @@ var CPNumberFormatterStyleKey = @"CPNumberFormatterStyleKey",
|
||||
_numberStyle = [aCoder decodeIntForKey:CPNumberFormatterStyleKey];
|
||||
_minimumFractionDigits = [aCoder decodeIntForKey:CPNumberFormatterMinimumFractionDigitsKey];
|
||||
_maximumFractionDigits = [aCoder decodeIntForKey:CPNumberFormatterMaximumFractionDigitsKey];
|
||||
_minimum = [aCoder decodeIntForKey:CPNumberFormatterMinimumKey];
|
||||
_maximum = [aCoder decodeIntForKey:CPNumberFormatterMaximumKey];
|
||||
_roundingMode = [aCoder decodeIntForKey:CPNumberFormatterRoundingModeKey];
|
||||
_groupingSeparator = [aCoder decodeObjectForKey:CPNumberFormatterGroupingSeparatorKey];
|
||||
_currencyCode = [aCoder decodeObjectForKey:CPNumberFormatterCurrencyCodeKey];
|
||||
@@ -273,6 +319,8 @@ var CPNumberFormatterStyleKey = @"CPNumberFormatterStyleKey",
|
||||
[aCoder encodeInt:_numberStyle forKey:CPNumberFormatterStyleKey];
|
||||
[aCoder encodeInt:_minimumFractionDigits forKey:CPNumberFormatterMinimumFractionDigitsKey];
|
||||
[aCoder encodeInt:_maximumFractionDigits forKey:CPNumberFormatterMaximumFractionDigitsKey];
|
||||
[aCoder encodeInt:_minimum forKey:CPNumberFormatterMinimumKey];
|
||||
[aCoder encodeInt:_maximum forKey:CPNumberFormatterMaximumKey];
|
||||
[aCoder encodeInt:_roundingMode forKey:CPNumberFormatterRoundingModeKey];
|
||||
[aCoder encodeObject:_groupingSeparator forKey:CPNumberFormatterGroupingSeparatorKey];
|
||||
[aCoder encodeObject:_currencyCode forKey:CPNumberFormatterCurrencyCodeKey];
|
||||
|
||||
@@ -48,6 +48,52 @@
|
||||
[self assert:@"1 234 567" equals:[numberFormatter stringFromNumber:[CPNumber numberWithInt:1234567]]];
|
||||
}
|
||||
|
||||
- (void)testMinimumMaximumValues
|
||||
{
|
||||
var numberFormatter = [CPNumberFormatter new],
|
||||
noneFunction = function() {};
|
||||
|
||||
[numberFormatter setMinimum:10];
|
||||
[numberFormatter setMaximum:20];
|
||||
|
||||
[self assertTrue:[numberFormatter getObjectValue:noneFunction forString:@"10" errorDescription:nil]
|
||||
message:@"MinMax T1: Expected True."];
|
||||
[self assertTrue:[numberFormatter getObjectValue:noneFunction forString:@"15" errorDescription:nil]
|
||||
message:@"MinMax T2: Expected True."];
|
||||
[self assertTrue:[numberFormatter getObjectValue:noneFunction forString:@"20" errorDescription:nil]
|
||||
message:@"MinMax T3: Expected True."];
|
||||
[self assertTrue:[numberFormatter getObjectValue:noneFunction forString:@"020" errorDescription:nil]
|
||||
message:@"MinMax T4: Expected True."];
|
||||
|
||||
// check if this formatter behaves like Cocoa, which allows a blank string to pass
|
||||
[self assertTrue:[numberFormatter getObjectValue:noneFunction forString:@"" errorDescription:nil]
|
||||
message:@"MinMax T5: Expected True."];
|
||||
|
||||
[self assertFalse:[numberFormatter getObjectValue:noneFunction forString:@"-1" errorDescription:nil]
|
||||
message:@"MinMax T6: Expected False."];
|
||||
[self assertFalse:[numberFormatter getObjectValue:noneFunction forString:@"1" errorDescription:nil]
|
||||
message:@"MinMax T7: Expected False."];
|
||||
[self assertFalse:[numberFormatter getObjectValue:noneFunction forString:@"100" errorDescription:nil]
|
||||
message:@"MinMax T8: Expected False."];
|
||||
|
||||
var testErrorDescription = @"",
|
||||
testWithString = [numberFormatter getObjectValue:noneFunction
|
||||
forString:@"Cappuccino"
|
||||
errorDescription:function(value)
|
||||
{
|
||||
if (arguments.length)
|
||||
return testErrorDescription = value;
|
||||
|
||||
return testErrorDescription;
|
||||
}];
|
||||
[self assertFalse:testWithString
|
||||
message:@"MinMax T9: Expected False."];
|
||||
[self assert:testErrorDescription
|
||||
equals:@"Value is not a number"
|
||||
message:@"MinMax T10: Error string does not match."];
|
||||
}
|
||||
|
||||
|
||||
- (void)testRoundingMode
|
||||
{
|
||||
var numberFormatter = [[CPNumberFormatter alloc] init],
|
||||
|
||||
@@ -35,11 +35,11 @@
|
||||
|
||||
[self setNumberStyle:[attributes valueForKey:@"numberStyle"] || CPNumberFormatterNoStyle];
|
||||
|
||||
// if ([attributes containsKey:@"minimum"])
|
||||
// [self setMinimum:[attributes valueForKey:@"minimum"]];
|
||||
if ([attributes containsKey:@"minimum"])
|
||||
[self setMinimum:[attributes valueForKey:@"minimum"]];
|
||||
|
||||
// if ([attributes containsKey:@"maximum"])
|
||||
// [self setMaximum:[attributes valueForKey:@"maximum"]];
|
||||
if ([attributes containsKey:@"maximum"])
|
||||
[self setMaximum:[attributes valueForKey:@"maximum"]];
|
||||
}
|
||||
|
||||
return self;
|
||||
|
||||
Reference in New Issue
Block a user