I am trying to limit the number of characters on each line in an NSTextView
to a multiple of 10.
Let's say the current width displays 40 characters. Now when the user makes the window wider, the first 10 characters on the second line shouldn't move to the end of the first line until the width to fit 50 characters has been reached.
This screams to use NSLayoutManager
but I have not yet found what method, maybe
optional func layoutManager(
_ layoutManager: NSLayoutManager,
shouldSetLineFragmentRect lineFragmentRect: UnsafeMutablePointer<NSRect>,
lineFragmentUsedRect: UnsafeMutablePointer<NSRect>,
baselineOffset: UnsafeMutablePointer<CGFloat>,
in textContainer: NSTextContainer,
forGlyphRange glyphRange: NSRange
) -> Bool
My text only has letters of the alphabet, using a monospaced font.
Any suggestions?
So, yes, adding an exclusionPath
did the trick (in MyTextView
):
override func setBoundsSize(_ newSize: NSSize) {
super.setBoundsSize(newSize)
textContainer?.exclusionPaths = exclusionPaths()
}
func exclusionPaths() -> [NSBezierPath] {
guard let tc = textContainer, let lm = tc.layoutManager else { return [] }
let groupInterval = 10
let groupGlyphRect = lm.boundingRect(forGlyphRange: NSMakeRange(0, groupInterval), in: tc)
let viewWidth = textContainer?.textView?.frame.width ?? 0
var currentX = 0.0
while currentX < viewWidth {
currentX += groupGlyphRect.width
let remainder = viewWidth - currentX
if remainder < groupGlyphRect.width {
let remainderRect = CGRect(x: currentX, y: 0, width: remainder, height: CGFloat.greatestFiniteMagnitude)
return [(NSBezierPath(rect: remainderRect))]
}
}
return []
}