Re: number of rows for an attributed string
Re: number of rows for an attributed string
- Subject: Re: number of rows for an attributed string
- From: Jerry Krinock <email@hidden>
- Date: Wed, 21 Nov 2007 10:31:45 -0800
On 2007 Nov, 20, at 19:13, Mitchell Livingston wrote:
I want to display an attributed string in a table row, simulating
10.5's Console where the row expands to allow multiple text rows in
a single table cell. I am having trouble determining the number of
rows the attributed string will take, however.
As you can see from the dearth of answers, this is not an easy question.
I looked into NSString's boundingRectWithSize:options:attributes:,
but that didn't seem to work.
Looks interesting, but I've never tried that.
Do a full-text search in Xcode Documentation for "Calculating Text
Height", and read the article with that title which is the first hit
in my Xcode 2.5. Below, I have pasted in functions that I use, based
on that article, to calculate height and width for NSStrings with a
given NSFont. I suppose it could be modified for attributed strings.
You see from the "fudge factors" I use that it doesn't come out quite
right. When I couldn't get this resolved at WWDC last summer I
submitted a bug report 5291163 with a sample project, but no one has
touched it.
I'm hoping the reason it hasn't been touched is that Apple has long
term plans to implement some string-measuring methods. It seems to me
like a big missing piece in Cocoa that the solution to such a common
problem should be so painful.
// Fudge numbers needed, from reverse-engineering experience
// Test with file /Users/jk/Projects/Bookdog/
StringDrawingFudgeTest.plist
// These fudge factors are used in SSMeasureStringDrawing,
// for fields that are only measured for width OR height
#define LAYOUT_MANAGER_WIDTH_FUDGE_FACTOR 1.15
#define LAYOUT_MANAGER_HEIGHT_FUDGE_FACTOR 1.15
// A possible reason why the height fudge factor is needed is
// because, when I read Apple's document "Font Handling"
// document, it seems that the line height would be:
// ascender - descender + leading
// (Note: descender is negative)
// But when I send -leading to one of my NSSystemFontOfSize...,
// I get 0.0
// These fudge numbers are used in SSResizeTextFieldForSuperview,
// for fields that are resized in BOTH width AND height
#define SIZE_TO_FIT_WIDTH_FUDGE_FACTOR 1.0
#define SIZE_TO_FIT_HEIGHT_FUDGE_FACTOR 1.10
float SSMeasureStringDrawing(NSString *myString, NSFont *desiredFont,
float desiredWidth, float desiredHeight) {
// One of desiredHeight or desiredWidth must be set to 0.
// The size of the one set to 0 will be returned.
// Operation of this function is explained in:
// ADC Home > Reference Library > Documentation > Cocoa > Text &
Fonts > Text Layout Programming Guide > Calculating Text Height
float output = 0.0 ;
// The Layout Manager likes to give a height of nominally one
line for an empty string
// That's pretty stupid, so if there are no characters we leave
output at 0.0 and bail out
if ([myString length] > 0) {
BOOL wantWidth ;
if (desiredWidth == 0)
{
desiredWidth = 1e7 ;
wantWidth = YES ;
}
else if (desiredHeight == 0)
{
desiredHeight = 1e7 ;
wantWidth = NO ;
}
else
NSLog(@"Internal error calling HeightForStringDrawing") ;
NSTextStorage *textStorage = [[[NSTextStorage alloc]
initWithString:myString] autorelease];
NSTextContainer *textContainer = [[[NSTextContainer alloc]
initWithContainerSize:NSMakeSize(desiredWidth /
LAYOUT_MANAGER_WIDTH_FUDGE_FACTOR, desiredHeight /
LAYOUT_MANAGER_HEIGHT_FUDGE_FACTOR)] autorelease];
NSLayoutManager *layoutManager = [[[NSLayoutManager alloc]
init] autorelease];
[textStorage addAttribute:NSFontAttributeName
value:desiredFont range:NSMakeRange(0, [textStorage length])];
[textContainer setLineFragmentPadding:0.0]; // padding
usually is not appropriate for string drawing
[layoutManager addTextContainer:textContainer];
[textStorage addLayoutManager:layoutManager];
(void)[layoutManager
glyphRangeForTextContainer:textContainer]; // force layout
if (wantWidth) {
output = [layoutManager
usedRectForTextContainer:textContainer].size.width *
LAYOUT_MANAGER_WIDTH_FUDGE_FACTOR ;
}
else {
output = [layoutManager
usedRectForTextContainer:textContainer].size.height *
LAYOUT_MANAGER_HEIGHT_FUDGE_FACTOR ;
}
}
return output ;
}
float SSMeasureStringWidth(NSString* string, NSFont* font, float
desiredHeight) {
if (desiredHeight == 0.0) {
desiredHeight = 1.0e8 ;
}
return SSMeasureStringDrawing(string, font, 0.0, desiredHeight) ;
}
float SSMeasureStringHeight(NSString* string, NSFont* font, float
desiredWidth) {
if (desiredWidth == 0.0) {
desiredWidth = 1.0e8 ;
}
return SSMeasureStringDrawing(string, font, desiredWidth, 0.0) ;
}
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden