How to verify that NSTextfield already truncates text (... at the end)

I searched around how to do this, but I can not find the answer.
I would like to know if my NSTextfield already truncates the text (... at the end) without checking the length of its stringValue . I need to do this to find out if I should set a tooltip on my NSTextfield (acting as a simple label). The reason I don't want to check the length of my stringValue text box is because there are some characters taking up more space than others, so it’s not very accurate Thanks!

+7
source share
4 answers

It is best to use NSTextView instead of NSTextField . If you use NSTextView , you can get NSTextContainer NSTextView using the textContainer property. A container can tell you containerSize (a space into which the text is inserted).

NSString objects respond to the sizeWithAttributes: method. You can use the resulting NSSize structure to capture the width of the text if you draw using the specified attributes. See the “Constants” section of the NSAttributedString application set reference for a list of attributes that are relevant.

If the containerSize less than the width of sizeWithAttributes: text will be truncated.

EDIT: Sorry, this is only true in the absence of lineFragmentPadding , but by default lineFragmentPadding is nonzero. Either subtract textContainer.lineFragmentPadding from containerSize.width , or use the NSTextContainer setLineFragmentPadding: method to set it to 0 .

I suppose you could also make some assumptions regarding the text area with respect to the size of the NSTextField and use the sizeWithAttributes: NSString method in conjunction with this, but it is not so clean.

EDIT 2: I realized that I did not pay attention to the OP's interest in breaking text with ellipses. The following code example uses truncation in an NSTextView . I also thought that I could also add code that makes NSTextView little more similar in appearance to NSTextField , putting it inside an NSBox . Adding a size check to determine whether a tooltip should be displayed will be a simple addition to the code below using the information already mentioned above.

 NSString* string = @"Hello World."; // get the size the text will take up using the default font NSSize textBounds = [string sizeWithAttributes:@{}]; // Create a border view that looks more or less like the border used around // text fields NSBox* borderView = [[NSBox alloc] initWithFrame:NSMakeRect(10, 10, 60, textBounds.height+4)]; [borderView setBoxType:NSBoxCustom]; [borderView setBorderType:NSBezelBorder]; [borderView setContentViewMargins:NSMakeSize(0, 0)]; [borderView setFillColor:[NSColor whiteColor]]; // Create the text view NSTextView* textView = [[NSTextView alloc] initWithFrame:NSMakeRect(0, 0, 60, textBounds.height)]; [textView setTextContainerInset:NSMakeSize(2, 0)]; [textView.textContainer setLineFragmentPadding:0]; [textView setEditable:YES]; // Set the default paragraph style so the text is truncated rather than // wrapped NSMutableParagraphStyle* parStyle = [[NSMutableParagraphStyle alloc] init]; [parStyle setLineBreakMode:NSLineBreakByTruncatingTail]; // Do not let text get squashed to fit [parStyle setTighteningFactorForTruncation:0.0]; [textView setDefaultParagraphStyle:parStyle]; [parStyle release]; // Set text [textView setString:string]; // add NSTextView to border view [borderView addSubview:textView]; [textView release]; // add NSBox to view you want text view displayed in [self addSubview:borderView]; [borderView release]; 
+4
source

For future visitors, you can use the method -[NSCell expansionFrameWithFrame:inView:] to determine if truncation is occurring. From the title:

Allows the cell to return the frame of the extension cell if the cellFrame is too small for all the content in the view .... <snip> ... If the frame is not too small, return an empty rectangle and no tooltip with the tooltip of the extension tool will be shown. By default, NSCell returns NSZeroRect, and some subclasses (for example, NSTextFieldCell) will return the correct frame if necessary.

In short, you can determine if NSTextField trims the following:

  NSRect expansionRect = [[self cell] expansionFrameWithFrame: self.frame inView: self]; BOOL truncating = !NSEqualRects(NSZeroRect, expansionRect); 
+9
source

I think you can do this by looking at the border of the text field's field editor. You check its width in controlTextDidBeginEditing, and then again in controlTextDidEndEditing. If the last value is greater, the text is truncated. The following is implemented in the text field delegate (I created ivar for initialWidth):

 - (void)controlTextDidBeginEditing:(NSNotification *)aNotification { if (! initialWidth) initialWidth = ((NSTextView *)aNotification.userInfo[@"NSFieldEditor"]).frame.size.width; } - (void)controlTextDidEndEditing:(NSNotification *)aNotification { if (initialWidth) { //Make sure that beginEditing is called first NSInteger finalWidth = ((NSTextView *)aNotification.userInfo[@"NSFieldEditor"]).frame.size.width; if (finalWidth - initialWidth > 1) NSLog(@"We have truncation"); NSLog(@"Final: %ld Initial: %ld", finalWidth,initialWidth); } } 

This seems to work most of the time, including if you enter a long string and then delete until it gets up again. On several occasions, he gave me a log message when I was a single character, which was located at the end of the text box, but when editing was completed I did not receive an ellipsis.

0
source

Swift 4 solution using ipmcc as a base

It will resize one by one until it matches or fontsize = 3

 var size_not_ok = true var conter = 0 let mininum_font_size = 3 // will resize ultil 3 while size_not_ok || conter < 15 { // will try 15 times maximun let expansionRect = le_nstextfield.expansionFrame(withFrame: le_nstextfield.frame) let truncated = !NSEqualRects(NSRect.zero, expansionRect) if truncated { if let actual_font_size : CGFloat = le_nstextfield.font?.fontDescriptor.object(forKey: NSFontDescriptor.AttributeName.size) as? CGFloat { le_nstextfield.font = NSFont.systemFont(ofSize: actual_font_size - 1) if actual_font_size < mininum_font_size { break } } } else { size_not_ok = false } conter = conter + 1 } 
-one
source

All Articles