mirror of
https://github.com/gnustep/libs-base.git
synced 2025-04-23 09:04:13 +00:00
Implemented -[NSNumberFormatter stringForObjectValue:]
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@24209 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
50c5c6b2d9
commit
55b13fb342
2 changed files with 201 additions and 14 deletions
|
@ -1,3 +1,7 @@
|
|||
2006-12-15 Graham J Lee <leeg@thaesofereode.info>
|
||||
* Source/NSNumberFormatter.m:
|
||||
Implement -stringForObjectValue:
|
||||
|
||||
2006-12-15 Richard Frith-Macdonald <rfm@gnu.org>
|
||||
|
||||
* Source/mframe.m:
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
#include "Foundation/NSNumberFormatter.h"
|
||||
#include "Foundation/NSString.h"
|
||||
#include "Foundation/NSUserDefaults.h"
|
||||
|
||||
#include "Foundation/NSCharacterSet.h"
|
||||
|
||||
@implementation NSNumberFormatter
|
||||
|
||||
|
@ -46,7 +46,8 @@
|
|||
- (NSAttributedString*) attributedStringForObjectValue: (id)anObject
|
||||
withDefaultAttributes: (NSDictionary*)attr
|
||||
{
|
||||
float val;
|
||||
NSDecimalNumber *zeroNumber = [NSDecimalNumber zero];
|
||||
NSDecimalNumber *nanNumber = [NSDecimalNumber notANumber];
|
||||
|
||||
if (anObject == nil)
|
||||
{
|
||||
|
@ -56,17 +57,20 @@
|
|||
{
|
||||
return [self attributedStringForNotANumber];
|
||||
}
|
||||
else if ([anObject intValue] == 0)
|
||||
else if ([anObject isEqual: nanNumber])
|
||||
{
|
||||
return [self attributedStringForNotANumber];
|
||||
}
|
||||
else if ([anObject isEqual: zeroNumber])
|
||||
{
|
||||
return [self attributedStringForZero];
|
||||
}
|
||||
|
||||
val = [anObject intValue];
|
||||
if ((val > 0) && (_attributesForPositiveValues))
|
||||
if (([anObject compare: zeroNumber] == NSOrderedDescending) && (_attributesForPositiveValues))
|
||||
{
|
||||
attr = _attributesForPositiveValues;
|
||||
}
|
||||
else if ((val < 0) && (_attributesForNegativeValues))
|
||||
else if (([anObject compare: zeroNumber] == NSOrderedAscending) && (_attributesForNegativeValues))
|
||||
{
|
||||
attr = _attributesForNegativeValues;
|
||||
}
|
||||
|
@ -224,6 +228,7 @@
|
|||
_allowsFloats = YES;
|
||||
_decimalSeparator = '.';
|
||||
_thousandSeparator = ',';
|
||||
_hasThousandSeparators = YES;
|
||||
o = [[NSAttributedString alloc] initWithString: @""];
|
||||
[self setAttributedStringForNil: o];
|
||||
RELEASE(o);
|
||||
|
@ -487,26 +492,204 @@
|
|||
- (NSString*) stringForObjectValue: (id)anObject
|
||||
{
|
||||
NSMutableDictionary *locale;
|
||||
NSCharacterSet *formattingCharacters = [NSCharacterSet
|
||||
characterSetWithCharactersInString: @"0123456789#.,_"],
|
||||
*placeHolders = [NSCharacterSet
|
||||
characterSetWithCharactersInString: @"0123456789#_"];
|
||||
NSString *prefix, *suffix, *wholeString, *fracPad;
|
||||
NSMutableString *formattedNumber, *intPartString, *fracPartString, *intPad;
|
||||
NSRange prefixRange, decimalPlaceRange, suffixRange, intPartRange;
|
||||
NSDecimal representativeDecimal, roundedDecimal;
|
||||
NSDecimalNumber *roundedNumber, *intPart, *fracPart;
|
||||
int decimalPlaces = 0;
|
||||
BOOL displayThousandsSeparators = NO,
|
||||
displayFractionalPart = NO,
|
||||
negativeNumber = NO;
|
||||
|
||||
if (nil == anObject)
|
||||
return [[self attributedStringForNil] string];
|
||||
if (![anObject isKindOfClass: [NSNumber class]])
|
||||
return [[self attributedStringForNotANumber] string];
|
||||
if ([anObject isEqual: [NSDecimalNumber notANumber]])
|
||||
return [[self attributedStringForNotANumber] string];
|
||||
if ([anObject isEqual: [NSDecimalNumber zero]])
|
||||
return [[self attributedStringForZero] string];
|
||||
|
||||
NSString *useFormat = _positiveFormat;
|
||||
if ([anObject compare: [NSDecimalNumber zero]] == NSOrderedAscending)
|
||||
{
|
||||
useFormat = _negativeFormat;
|
||||
negativeNumber = YES;
|
||||
}
|
||||
|
||||
/* FIXME: This is just a quick hack implementation. */
|
||||
NSLog(@"NSNumberFormatter-stringForObjectValue:... not fully implemented");
|
||||
// if no format specified, use the same default that Cocoa does
|
||||
if (nil == useFormat)
|
||||
useFormat = negativeNumber ? @"-#,###.##" : @"#,###.##";
|
||||
|
||||
prefixRange = [useFormat rangeOfCharacterFromSet: formattingCharacters];
|
||||
if (NSNotFound != prefixRange.location)
|
||||
{
|
||||
prefix = [useFormat substringToIndex: prefixRange.location];
|
||||
}
|
||||
else
|
||||
{
|
||||
prefix = @"";
|
||||
}
|
||||
|
||||
locale = [NSMutableDictionary dictionaryWithCapacity: 3];
|
||||
if ([self hasThousandSeparators])
|
||||
[locale setObject: @"" forKey: NSThousandsSeparator];
|
||||
[locale setObject: @"" forKey: NSDecimalSeparator];
|
||||
|
||||
//should also set NSDecimalDigits?
|
||||
|
||||
if ([self hasThousandSeparators]
|
||||
&& (0 != [useFormat rangeOfString:@","].length))
|
||||
{
|
||||
[locale setObject: [self thousandSeparator] forKey: NSThousandsSeparator];
|
||||
displayThousandsSeparators = YES;
|
||||
}
|
||||
|
||||
if ([self allowsFloats])
|
||||
if ([self allowsFloats]
|
||||
&& (NSNotFound != [useFormat rangeOfString:@"." ].location))
|
||||
{
|
||||
[locale setObject: [self decimalSeparator] forKey: NSDecimalSeparator];
|
||||
// Should also set: NSDecimalDigits
|
||||
decimalPlaceRange = [useFormat rangeOfString: @"."
|
||||
options: NSBackwardsSearch];
|
||||
if (NSMaxRange(decimalPlaceRange) == [useFormat length])
|
||||
{
|
||||
decimalPlaces = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
while ([placeHolders characterIsMember:
|
||||
[useFormat characterAtIndex:
|
||||
NSMaxRange(decimalPlaceRange)]])
|
||||
{
|
||||
decimalPlaceRange.length++;
|
||||
if (NSMaxRange(decimalPlaceRange) == [useFormat length])
|
||||
break;
|
||||
}
|
||||
decimalPlaces=decimalPlaceRange.length -= 1;
|
||||
decimalPlaceRange.location += 1;
|
||||
fracPad = [useFormat substringWithRange:decimalPlaceRange];
|
||||
}
|
||||
if (0 != decimalPlaces)
|
||||
displayFractionalPart = YES;
|
||||
}
|
||||
|
||||
return [anObject descriptionWithLocale: locale];
|
||||
representativeDecimal = [anObject decimalValue];
|
||||
NSDecimalRound(&roundedDecimal,
|
||||
&representativeDecimal,
|
||||
decimalPlaces,
|
||||
NSRoundPlain);
|
||||
roundedNumber = [NSDecimalNumber decimalNumberWithDecimal: roundedDecimal];
|
||||
|
||||
/* Arguably this fiddling could be done by GSDecimalString() but I
|
||||
* thought better to leave that behaviour as it is and provide the
|
||||
* desired prettification here
|
||||
*/
|
||||
if (negativeNumber)
|
||||
roundedNumber = [roundedNumber decimalNumberByMultiplyingBy:
|
||||
[NSDecimalNumber numberWithInt: -1]];
|
||||
intPart = [NSDecimalNumber numberWithInt: [roundedNumber intValue]];
|
||||
fracPart = [roundedNumber decimalNumberBySubtracting: intPart];
|
||||
intPartString = [intPart descriptionWithLocale:locale];
|
||||
|
||||
//sort out the padding for the integer part
|
||||
intPartRange = [useFormat rangeOfCharacterFromSet: placeHolders];
|
||||
while (([placeHolders characterIsMember:
|
||||
[useFormat characterAtIndex: NSMaxRange(intPartRange)]]
|
||||
|| [[useFormat substringFromRange:
|
||||
NSMakeRange(NSMaxRange(intPartRange),1)] isEqual: @","])
|
||||
&& NSMaxRange(intPartRange)<[useFormat length]-1)
|
||||
{
|
||||
intPartRange.length++;
|
||||
}
|
||||
intPad = [[useFormat substringWithRange:intPartRange] mutableCopy];
|
||||
[intPad replaceOccurrencesOfString: @","
|
||||
withString: @""
|
||||
options: 0
|
||||
range: NSMakeRange(0, [intPad length])];
|
||||
[intPad replaceOccurrencesOfString: @"#"
|
||||
withString: @""
|
||||
options: NSAnchoredSearch
|
||||
range: NSMakeRange(0, [intPad length])];
|
||||
if ([intPad length] > [intPartString length])
|
||||
{
|
||||
NSRange ipRange = NSMakeRange(0,
|
||||
[intPad length] - [intPartString length] + 1);
|
||||
intPartString = [[[intPad substringWithRange: ipRange]
|
||||
stringByAppendingString: intPartString] mutableCopy];
|
||||
[intPartString replaceOccurrencesOfString: @"_"
|
||||
withString: @" "
|
||||
options: nil
|
||||
range: NSMakeRange(0, [intPartString length])];
|
||||
[intPartString replaceOccurrencesOfString: @"#"
|
||||
withString: @"0"
|
||||
options: nil
|
||||
range: NSMakeRange(0, [intPartString length])];
|
||||
}
|
||||
// fix the thousands separators up
|
||||
if (displayThousandsSeparators && [intPartString length] > 3)
|
||||
{
|
||||
int index = [intPartString length];
|
||||
while (0 < (index-=3))
|
||||
{
|
||||
[intPartString insertString:[self thousandSeparator] atIndex: index];
|
||||
}
|
||||
}
|
||||
|
||||
formattedNumber = [intPartString mutableCopy];
|
||||
|
||||
//fix up the fractional part
|
||||
if (displayFractionalPart)
|
||||
{
|
||||
if (0 != decimalPlaces)
|
||||
{
|
||||
fracPart = [fracPart decimalNumberByMultiplyingByPowerOf10:
|
||||
decimalPlaces];
|
||||
fracPartString = [fracPart descriptionWithLocale: locale];
|
||||
[fracPartString replaceOccurrencesOfString: @"0"
|
||||
withString: @""
|
||||
options: (NSBackwardsSearch
|
||||
| NSAnchoredSearch)
|
||||
range: NSMakeRange(0, [fracPartString length])];
|
||||
if ([fracPad length] > [fracPartString length])
|
||||
{
|
||||
NSRange fpRange = NSMakeRange([fracPartString length],
|
||||
( [fracPad length] -
|
||||
[fracPartString length]));
|
||||
[fracPartString appendString:
|
||||
[fracPad substringWithRange: fpRange]];
|
||||
[fracPartString replaceOccurrencesOfString: @"#"
|
||||
withString: @""
|
||||
options: (NSBackwardsSearch
|
||||
| NSAnchoredSearch)
|
||||
range: NSMakeRange(0, [fracPartString length])];
|
||||
[fracPartString replaceOccurrencesOfString: @"#"
|
||||
withString: @"0"
|
||||
options: 0
|
||||
range: NSMakeRange(0, [fracPartString length])];
|
||||
[fracPartString replaceOccurrencesOfString: @"_"
|
||||
withString: @" "
|
||||
options: 0
|
||||
range: NSMakeRange(0, [fracPartString length])];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fracPartString=@"0";
|
||||
}
|
||||
[formattedNumber appendString:[self decimalSeparator]];
|
||||
[formattedNumber appendString:fracPartString];
|
||||
}
|
||||
/*FIXME - the suffix doesn't behave the same as on Mac OS X. Our suffix is everything which
|
||||
*follows the final formatting character. Cocoa's suffix is everything which isn't a formatting character
|
||||
*nor in the prefix
|
||||
*/
|
||||
suffixRange = [useFormat rangeOfCharacterFromSet: formattingCharacters options: NSBackwardsSearch];
|
||||
suffix = [useFormat substringFromIndex: NSMaxRange(suffixRange)];
|
||||
wholeString = [[prefix stringByAppendingString: formattedNumber] stringByAppendingString: suffix];
|
||||
[formattedNumber release];
|
||||
return wholeString;
|
||||
}
|
||||
|
||||
- (NSDictionary*) textAttributesForNegativeValues
|
||||
|
|
Loading…
Reference in a new issue