How to disable word-wrap of NSTextView?
NSTextView开发者_JAVA百科 does word-wrap by default. How can I disable this? I'm making a JSON code viewer, so I have to disable this.
First, this document explains why and how -- https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/TextStorageLayer/Tasks/TrackingSize.html#//apple_ref/doc/uid/20000927-CJBBIAAF
I got solution from: http://lists.apple.com/archives/cocoa-dev/2008/May/msg02396.html
You have to set NSTextView's maximum width to very large number to make this work correctly. (Just copy maximum height) And enable horizontal scrolling of NSScrollView which is superview of the NSTextView. See these pictures:
http://www.flickr.com/photos/47601728@N06/4759470529/
http://www.flickr.com/photos/47601728@N06/4759470533/
Update
I discovered my old sample code was insufficient to make it fully work correctly. (because of SDK version?) Also Here's my full source code snippet which disables word-wrap in OSX 10.8 SDK.
[self setMaxSize:CGSizeMake(FLT_MAX, FLT_MAX)];
[self setHorizontallyResizable:YES];
[[self textContainer] setWidthTracksTextView:NO];
[[self textContainer] setContainerSize:CGSizeMake(FLT_MAX, FLT_MAX)];
Update 2
Now Apple is providing an official guide to create NSTextView
correctly. I hope this helps.
Update 3
I posted an example project on Github. See this page for specific implementation: https://github.com/Eonil/CocoaProgrammaticHowtoCollection/blob/master/ComponentUsages/TextView/ExampleApplicationController.swift?ts=4
Here's a code snippet from the sample project.
if wordWrap {
/// Matching width is also important here.
let sz = scrollView.contentSize
textView.frame = CGRect(x: 0, y: 0, width: sz.width, height: 0)
textView.textContainer?.containerSize = CGSize(width: sz.width, height: CGFloat.greatestFiniteMagnitude)
textView.textContainer?.widthTracksTextView = true
}
else {
textView.textContainer?.widthTracksTextView = false
textView.textContainer?.containerSize = CGSize(width: CGFloat.greatestFiniteMagnitude, height: CGFloat.greatestFiniteMagnitude)
}
The three lines given in the accepted answer by Eonil alone did not work for me, the resulting text view did not scroll horizontally and therefore there was no way to see the clipped part of the long lines.
The full code snippet from the referenced cocoa-dev thread did produce the correct results. Specifically, this set of steps:
NSSize layoutSize = [textView maxSize];
layoutSize.width = layoutSize.height;
[textView setMaxSize:layoutSize];
[[textView textContainer] setWidthTracksTextView:NO];
[[textView textContainer] setContainerSize:layoutSize];
I have written an extension on NSTextView
.
extension NSTextView {
var wrapsLines: Bool {
get {
return self.textContainer?.widthTracksTextView ?? false
}
set {
guard
newValue != self.wrapsLines,
let scrollView = enclosingScrollView,
let textContainer = self.textContainer
else { return }
scrollView.hasHorizontalScroller = !newValue
isHorizontallyResizable = !newValue
textContainer.widthTracksTextView = newValue
if newValue {
self.frame.size[keyPath: \NSSize.width] = scrollView.contentSize.width
maxSize = NSSize(width: scrollView.contentSize.width, height: CGFloat.greatestFiniteMagnitude)
textContainer.size.width = scrollView.contentSize.width
} else {
let infiniteSize = CGSize(width: CGFloat.greatestFiniteMagnitude, height: CGFloat.greatestFiniteMagnitude)
maxSize = infiniteSize
textContainer.size = infiniteSize
}
}
}
}
I found this solution did prevent line wrapping, but had some unfortunate drawing consequences for the NSTextView. The problem was that when the NSPanel containing the text views was dragged to be wider than the lines of text, the NSView's bounds rect was adjusted (by the underlying layout manager) to just be slightly longer than the text - revealing the NSPanel's background. Not what I had in mind ...
My solutions was to enable resizing in the NSPanel, constrain it to the horizontal by setting of min and max sizes and turn off horizontal resizing for the text view itself:
// some fragments from the creation of the NSPanel
// resizable NSPanel created
mMonitorPanel = [[NSPanel alloc] initWithContentRect: monitorRect
styleMask: (NSTitledWindowMask| NSMiniaturizableWindowMask | NSResizableWindowMask)
backing: NSBackingStoreBuffered defer: NO];
// constrain resizing to horizontal only, with obvious limits ...
[mMonitorPanel setContentMaxSize: NSMakeSize(1000, 600)];
[mMonitorPanel setContentMinSize: NSMakeSize(300, 600)];
// a fragment from the init that creates an instance of a subclass of NSTextView ...
[self setVerticallyResizable: NO];
[self setHorizontallyResizable: NO]; // rather than YES as prior code snippet
// the rest is the same as above
[[self textContainer] setContainerSize: NSMakeSize(FLT_MAX, FLT_MAX)];
[[self textContainer] setWidthTracksTextView: NO];
This results in a monitor panel that can be horizontally resized, does not wrap lines, and draws properly in it's enclosing NSPanel.
Hope this helps someone - don't know where I'd be without all the good fixes I've found on this site!
Easiest way is in Interface Builder, in the inspector just change the drop-down menu.
精彩评论