From ecb04e983ef393d82a2b2e8f943bcedd22632e0e Mon Sep 17 00:00:00 2001 From: Alexander Ljungberg Date: Fri, 10 Jun 2011 11:23:36 -0700 Subject: [PATCH] Simple CPNumberFormatter stringFromNumber for CPNumberFormatterDecimalStyle. --- Foundation/CPNumberFormatter.j | 76 ++++++++++++++++++++++++ Tests/Foundation/CPNumberFormatterTest.j | 19 ++++++ 2 files changed, 95 insertions(+) create mode 100644 Tests/Foundation/CPNumberFormatterTest.j diff --git a/Foundation/CPNumberFormatter.j b/Foundation/CPNumberFormatter.j index aeb9ace71..89d46e7cc 100644 --- a/Foundation/CPNumberFormatter.j +++ b/Foundation/CPNumberFormatter.j @@ -24,12 +24,85 @@ @import @import +CPNumberFormatterNoStyle = 0; +CPNumberFormatterDecimalStyle = 1; +CPNumberFormatterCurrencyStyle = 2; +CPNumberFormatterPercentStyle = 3; +CPNumberFormatterScientificStyle = 4; +CPNumberFormatterSpellOutStyle = 5; + +/*! + @ingroup foundation + @class CPNumberFormatter + + CPNumberFormatter takes a numeric NSNumber value and formats it as text for + display. It also supports the converse, taking text and interpreting it as a + CPNumber by configurable formatting rules. +*/ @implementation CPNumberFormatter : CPFormatter { + CPNumberFormatterStyle _numberStyle @accessors(property=numberStyle); + CPString _perMillSymbol @accessors(property=perMillSymbol); +} + +- (CPString)stringFromNumber:(CPNumber)number +{ + // TODO Add locale support. + switch(_numberStyle) + { + case CPNumberFormatterDecimalStyle: + var dcmn = [CPDecimalNumber numberWithFloat:number], + numberHandler = [CPDecimalNumberHandler decimalNumberHandlerWithRoundingMode:CPRoundPlain scale:3 raiseOnExactness:NO raiseOnOverflow:NO raiseOnUnderflow:NO raiseOnDivideByZero:YES]; + + dcmn = [dcmn decimalNumberByRoundingAccordingToBehavior:numberHandler]; + + var output = [dcmn descriptionWithLocale:nil], + parts = [output componentsSeparatedByString:"."], // FIXME Locale specific. + preFraction = parts[0], + fraction = parts.length > 1 ? parts[1] : "", + preFractionLength = [preFraction length], + commaPosition = 3, + perMillSymbol = [self _effectivePerMillSymbol]; + + // TODO This is just a temporary solution. Should be generalised. + // Add in thousands separators. + if (perMillSymbol) + while(commaPosition < [preFraction length]) + { + preFraction = [preFraction stringByReplacingCharactersInRange:CPMakeRange(commaPosition, 0) withString:perMillSymbol]; + commaPosition += 4; + } + + if (fraction) + return preFraction + "." + fraction; + else + return preFraction; + default: + return [number description]; + } +} + +- (CPNumber)numberFromString:(CPString)string +{ + +} + + +/*! + @ignore + Return the perMillSymbol if set, otherwise the locale default. +*/ +- (CPString)_effectivePerMillSymbol +{ + if (_perMillSymbol === nil || _perMillSymbol === undefined) + return ","; // (FIXME US Locale specific.) + return _perMillSymbol; } @end +var CPNumberFormatterStyleKey = "CPNumberFormatterStyleKey"; + @implementation CPNumberFormatter (CPCoding) - (id)initWithCoder:(CPCoder)aCoder @@ -38,6 +111,7 @@ if (self) { + _numberStyle = [aCoder decodeIntForKey:CPNumberFormatterStyleKey]; } return self; @@ -46,6 +120,8 @@ - (void)encodeWithCoder:(CPCoder)aCoder { [super encodeWithCoder:aCoder]; + + [aCoder encodeInt:_numberStyle forKey:CPNumberFormatterStyleKey]; } @end diff --git a/Tests/Foundation/CPNumberFormatterTest.j b/Tests/Foundation/CPNumberFormatterTest.j new file mode 100644 index 000000000..d9ad0b89b --- /dev/null +++ b/Tests/Foundation/CPNumberFormatterTest.j @@ -0,0 +1,19 @@ +@import + +@implementation CPNumberFormatterTest : OJTestCase +{ +} + +- (void)testDecimalStyle +{ + var numberFormatter = [[CPNumberFormatter alloc] init]; + [numberFormatter setNumberStyle:CPNumberFormatterDecimalStyle]; + var formattedNumberString = [numberFormatter stringFromNumber:[CPNumber numberWithInt:123]]; + [self assert:@"123" equals:formattedNumberString]; + + formattedNumberString = [numberFormatter stringFromNumber:[CPNumber numberWithFloat:122344.4563]]; + // TODO Locale support. This test is sensitive to float precision. + [self assert:@"122,344.456" equals:formattedNumberString]; +} + +@end