3

I made an NSTextField subclass which adjusts its width with its content length. The idea (of overriding intrinsicContentSize) is from this question.

override var intrinsicContentSize: NSSize {
    if isEditing {
        if let fieldEditor =
            self.window?.fieldEditor(false, for: self) as?
                NSTextView
        {
            let rect = fieldEditor.layoutManager!.usedRect(
                for: fieldEditor.textContainer!
            )

            let size = rect.size

            return size
        }
    }

    let size = self.cell!.cellSize
    return size
}

However, there's an extra blank area after the last character. If I set the size.width manually (size.width -= 3.5, for example), the text will offset back and forth (horizontally) during editing.

I don't see this quirk in macOS's Finder when renaming its sidebar items. How to get rid of the extra space without making the text "jumping"?

extra space after text

Update 1:

I added a demo on GitHub.

Update 2:

Tried setting NSTextView's textContainerInset to a size of 0, 0, which doesn't solve the problem.

Update 3:

Updated the repo with @Михаил Масло 's answer. The text still jiggles during editing. The original implementation can be viewed by checking out the initial commit.

LShi
  • 1,500
  • 16
  • 29
  • I tried your code (implemented my own `isEditing`) but I see lack of space at top, left and bottom. – Willeke Oct 28 '17 at 21:34
  • Hi @Willeke, thank you! Mine is in a source list. I've put a demo [here on github](https://github.com/liushigit/TextFieldDemo) I also saw the effect you mentioned. A magic `size.height += 5.0` will fix it partially. You can see in my demo, besides the issue being discussed, a dot is added if you press the spacebar a few times when editing. – LShi Oct 29 '17 at 06:22
  • The appended period may be related to this http://www.idownloadblog.com/2016/12/19/how-to-stop-your-mac-from-inserting-a-period-when-you-double-press-the-space-bar/ – LShi Oct 29 '17 at 09:35

1 Answers1

1

You can calculate size of the string with defined font directly try this (I've used your code in TableTextField.swift):

class TableTextField: NSTextField {
  ...
  override var intrinsicContentSize: NSSize {
    return stringValue.size(withConstraintedHeight: 1000, font: fieldEditor.font!)
  }
  ...
}


extension String {
  func size(withConstraintedHeight height: CGFloat, font: NSFont) -> CGSize {
    let constraintRect = CGSize(width: .greatestFiniteMagnitude, height: height)
    let boundingBox = self.boundingRect(with: constraintRect, options: .usesLineFragmentOrigin,
                                        attributes: [NSAttributedStringKey.font: font], context: nil)
    let size = boundingBox.size
    return CGSize(width: size.width + 0.5, height: size.height)
  }
}

I didn't tend to make it safe so probably you can make it better and exclude force-unwrap and following errors

Mikhail Maslo
  • 616
  • 6
  • 13
  • Hi thanks! I tried your answer and updated the repo. This is still not a perfect solution since the text will jiggle a little bit during editing. I extended `NSAttributedString` since the `boundingRect(with:)` method of `NSString` is deprecated. – LShi Nov 04 '17 at 03:26
  • @LShi I changed text calculator in the following way return `CGSize(width: size.width + 1.0, height: size.height)` and intrinsicContentSize: `return attributedStringValue.size(withConstrainedHeight: 1000, font: font!)`. After it I didn't notice any shrinking – Mikhail Maslo Nov 04 '17 at 08:49
  • Hi! not shrinking. Will the text jiggle when you add more characters or simply add trailing spaces? – LShi Nov 04 '17 at 09:23
  • @LShi With usual characters it works ok but with trailing spaces - yeah there are some problems. I didn't noticed it when've tested the code. So I can only say the problem not in size now (it's correct) but in something that makes this strange text offset. I experimented a bit and found that `alignmentRectInsets` has offsets 2 from both sides. If you play around this values and additional width in size function you will get not jiggle smooth text. I tried `NSEdgeInsets(top: 0, left: 2.5, bottom: 0, right: 2.5)` for `alignmentRectInsets` and `1.5 additional space for size func` and it worked! – Mikhail Maslo Nov 04 '17 at 10:15
  • Yes, even the usual characters cause a weak "offset effect". – LShi Nov 04 '17 at 10:18
  • Thanks! I will try it and comment later. – LShi Nov 04 '17 at 10:20
  • Hi Михаил, I tried your `alignmentRectInsets` idea, the jiggling is gone when `left` and `right` are both set to `4.0` on my machine. However the extra blank space is still there, which means it's not better than my original implementation. – LShi Nov 04 '17 at 10:37