// // NSString-NJRExtensions.m // Pester // // Created by Nicholas Riley on Mon Dec 16 2002. // Copyright (c) 2002 Nicholas Riley. All rights reserved. // #import "NSString-NJRExtensions.h" @implementation NSString (NJRExtensions) - (NSAttributedString *)attributedStringWithFont:(NSFont *)font; { return [[[NSAttributedString alloc] initWithString: self attributes: [NSDictionary dictionaryWithObject: font forKey: NSFontAttributeName]] autorelease]; } - (NSAttributedString *)underlined; { return [[[NSAttributedString alloc] initWithString: self attributes: [NSDictionary dictionaryWithObject: [NSNumber numberWithInt: NSSingleUnderlineStyle] forKey: NSUnderlineStyleAttributeName]] autorelease]; } - (NSAttributedString *)small; { return [self attributedStringWithFont: [NSFont systemFontOfSize: [NSFont smallSystemFontSize]]]; } - (NSAttributedString *)smallBold; { return [self attributedStringWithFont: [NSFont boldSystemFontOfSize: [NSFont smallSystemFontSize]]]; } + (NSString *)ellipsisString; { static NSString *ellipsis = nil; if (ellipsis == nil) { const unichar ellipsisChar = 0x2026; ellipsis = [[NSString alloc] initWithCharacters: &ellipsisChar length: 1]; } return ellipsis; } @end @implementation NSMutableString (NJRExtensions) - (void)truncateToLength:(unsigned)maxLength by:(NSLineBreakMode)method; { if ([self length] > maxLength) { NSRange range = {0, [self length] - maxLength}; switch (method) { case NSLineBreakByTruncatingHead: range.location = 0; break; case NSLineBreakByTruncatingMiddle: range.location = maxLength / 2; break; case NSLineBreakByTruncatingTail: range.location = maxLength; break; default: range.location = maxLength; break; } [self replaceCharactersInRange: range withString: [NSString ellipsisString]]; } } - (void)truncateToWidth:(float)maxWidth by:(NSLineBreakMode)method withAttributes:(NSDictionary *)attributes; { if ([self sizeWithAttributes: attributes].width > maxWidth) { float width; int min = 0, max = [self length], avg; NSMutableString *original = [self mutableCopy]; while (max >= min) { avg = (max + min) / 2; [self truncateToLength: avg by: method]; width = [self sizeWithAttributes: attributes].width; if (width > maxWidth) { max = avg - 1; // too wide } else if (width == maxWidth) { break; } else { min = avg + 1; // too narrow [self setString: original]; } } if (width != maxWidth) [self truncateToLength: max by: method]; [original release]; } } @end