Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I tell NSTextField to autoresize it's font size to fit it's text? [duplicate]

Looking for essentially whatever the Cocoa equivalent of [UILabel adjustsFontSizeToFitWidth] is.

like image 443
refulgentis Avatar asked Jul 24 '10 08:07

refulgentis


3 Answers

I've solved it by creating a NSTextFieldCell subclass which overrides the string drawing. It looks whether the string fits and if it doesn't it decreases the font size until it does fit. This could be made more efficient and I have no idea how it'll behave when the cellFrame has a width of 0. Nevertheless it was Good Enough™ for my needs.

- (void)drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView *)controlView
{
    NSAttributedString *attributedString;
    NSMutableAttributedString *mutableAttributedString;
    NSSize stringSize;
    NSRect drawRect;

    attributedString = [self attributedStringValue];

    stringSize = [attributedString size];
    if (stringSize.width <= cellFrame.size.width) {
        // String is already small enough. Skip sizing.
        goto drawString;
    }

    mutableAttributedString = [attributedString mutableCopy];

    while (stringSize.width > cellFrame.size.width) {
        NSFont *font;

        font = [mutableAttributedString
            attribute:NSFontAttributeName
            atIndex:0
            effectiveRange:NULL
        ];
        font = [NSFont
            fontWithName:[font fontName]
            size:[[[font fontDescriptor] objectForKey:NSFontSizeAttribute] floatValue] - 0.5
        ];

        [mutableAttributedString
            addAttribute:NSFontAttributeName
            value:font
            range:NSMakeRange(0, [mutableAttributedString length])
        ];

        stringSize = [mutableAttributedString size];
    }

    attributedString = [mutableAttributedString autorelease];

drawString:
    drawRect = cellFrame;
    drawRect.size.height = stringSize.height;
    drawRect.origin.y += (cellFrame.size.height - stringSize.height) / 2;
    [attributedString drawInRect:drawRect];
}
like image 52
DarkDust Avatar answered Nov 01 '22 21:11

DarkDust


Don't forget to look in superclasses. An NSTextField is a kind of NSControl, and every NSControl responds to the sizeToFit message.

like image 37
Peter Hosey Avatar answered Nov 01 '22 19:11

Peter Hosey


I used Jerry Krinock's excellent NS(Attributed)String+Geometrics (located here) and a small method like the following. I'm still interested in a simpler way.

- (void) prepTextField:(NSTextField *)field withString:(NSString *)string
{   
    #define kMaxFontSize 32.0f
    #define kMinFontSize 6.0f
    float fontSize = kMaxFontSize;
    while (([string widthForHeight:[field frame].size.height font:[NSFont systemFontOfSize:fontSize]] > [field frame].size.width) && (fontSize > kMinFontSize))
    {
            fontSize--;
    }
    [field setFont:[NSFont systemFontOfSize:fontSize]];

    [field setStringValue:string];

    [self addSubview:field];
}
like image 1
refulgentis Avatar answered Nov 01 '22 19:11

refulgentis