number of rows for an attributed string

  • Hello,

    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. I looked into NSString's
    boundingRectWithSize:options:attributes:, but that didn't seem to
    work. Any help would be appreciated.

    Thanks,
    Mitchell Livingston
  • 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) ;
    }
  • On Nov 20, 2007, at 7:13 PM, Mitchell Livingston wrote:

    > Hello,
    >
    > 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. I looked into
    > NSString's boundingRectWithSize:options:attributes:, but that
    > didn't seem to work. Any help would be appreciated.

    If you're just needing to get the size of the attributed string, you
    can say

    [attributedString size]

    (the size method is documented in NSAttributedString Application Kit
    Additions Reference, in the Application Kit Framework Reference).

    Best,

    __jayson

    Circus Ponies NoteBook - Organization for a Creative Mind
    www.circusponies.com
  • This works to determine the height and width, but I want to know what the height is when the width is restricted to a certain value.

    Thanks,
    Mitch

    On Wednesday, November 21, 2007, at 01:37PM, "Jayson Adams" <jayson...> wrote:
    >
    > On Nov 20, 2007, at 7:13 PM, Mitchell Livingston wrote:
    >
    >> Hello,
    >>
    >> 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. I looked into
    >> NSString's boundingRectWithSize:options:attributes:, but that
    >> didn't seem to work. Any help would be appreciated.
    >
    > If you're just needing to get the size of the attributed string, you
    > can say
    >
    > [attributedString size]
    >
    > (the size method is documented in NSAttributedString Application Kit
    > Additions Reference, in the Application Kit Framework Reference).
    >
    > Best,
    >
    >
    > __jayson
    >
    > Circus Ponies NoteBook - Organization for a Creative Mind
    > www.circusponies.com
    >
    >
    >
    >
  • On Nov 21, 2007, at 10:53 AM, Mitchell Livingston wrote:

    > This works to determine the height and width, but I want to know
    > what the height is when the width is restricted to a certain value.

    For that, I would use an NSTextView to compute the height.  Something
    like:

        [[tmpTextView textContainer] setContainerSize:NSMakeSize
    (theWidth, 1e7)];

        [tmpTextView setMinSize:NSMakeSize(theWidth, 1.0)];
        [tmpTextView setMaxSize:NSMakeSize(theWidth, 1e7)];
        [tmpTextView setHorizontallyResizable:YES];
        [tmpTextView setVerticallyResizable:YES];

        [tmpTextView sizeToFit];

        theHeight = [tmpTextView bounds].size.height;

    Best,

    __jayson

    Circus Ponies NoteBook - Organization for a Creative Mind
    www.circusponies.com
previous month november 2007 next month
MTWTFSS
      1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30    
Go to today