28 January 2009

Awesome Truncation for (nearly) Free!

Sometimes you need to shorten a string to make it fit within certain bounds. using the NSString - (void)drawAtPoint:(NSPoint)aPoint withAttributes:(NSDictionary *)attributes method will draw the string, but won't perform any truncation. The - (void)drawInRect:(NSRect)aRect withAttributes:(NSDictionary *)attributesmethod will truncate, but just clips at the end. Sometimes what we really want is the behavior that window titles show, an ellipsis at the end. Here's an example:

This behavior can be selected using the Inspector in Interface Builder for NSTextFields. But what do we do if we are drawing text in a custom view? It turns out that it is very simple to get automatic truncation, in at the head, in the middle, or at the tail of the string. Here's how:

  1. Add a paragraph style to the attributes dictionary. In this example, we do this in theinit method.
      // Set the paragraph style attribute to truncate the tail.
      NSMutableParagraphStyle* style = [[[NSParagraphStyle defaultParagraphStyle] mutableCopy] autorelease];
      // Here we specify the truncation location with a constant.
      [style setLineBreakMode:NSLineBreakByTruncatingTail];
      // Make an attribute dictionary for the attributed string
      NSDictionary _textAttributes = [[NSDictionary dictionaryWithObjectsAndKeys:
            [NSFont systemFontOfSize:[NSFont labelFontSize]], NSFontAttributeName,
            style, NSParagraphStyleAttributeName,
            nil] retain];
  2. Calculate the rectangle in which you want to draw the string.
  3. Then draw the string using the NSString drawInRect:withAttributes:. Here's an example from our custom view's drawRect: method.
      [_text drawInRect:textRect withAttributes:_textAttributes];

There are actually three kinds of truncation that you can specify in this method, NSLineBreakByTruncatingHead NSLineBreakByTruncatingMiddle, and as observed, NSLineBreakByTruncatingTail. It is that easy.


Bad Base said...

Thanks for posting this - at times it can be hard to find what you want in the Apple docs and this was what I was looking for. BadBase.

Preston Jackson said...

Bad Base: Glad it was helpful!