12

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

DarkDust
  • 90,870
  • 19
  • 190
  • 224
refulgentis
  • 2,624
  • 23
  • 37
  • I answered this for someone else. You can see my answer [here](http://stackoverflow.com/questions/2908704/get-nstextfield-contents-to-scale/2911982#2911982). – regulus6633 Jul 24 '10 at 20:06

3 Answers3

6

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];
}
DarkDust
  • 90,870
  • 19
  • 190
  • 224
  • To make the font correctly center vertically, the following line is needed right before the `while`: `[mutableAttributedString removeAttribute:@"NSOriginalFont" range:NSMakeRange(0, [mutableAttributedString length])];` – DarkDust Mar 04 '14 at 10:11
2

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

Peter Hosey
  • 95,783
  • 15
  • 211
  • 370
1

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];
}
refulgentis
  • 2,624
  • 23
  • 37