My goal is to make a view that is similar to the Goole Docs text editor, with comment highlighting behind the text where there are comments.
My solution is to have an NSScrollView
containing an NSView
(set as the document view) that scrolls and contains both an NSTextView
of the text, and other NSView
s that will be the highlights.
For this to work, the NSTextView
has to size as if it belongs directly to the NSScrollView
. However, I cannot make the NSTextView
have this behavior.
The code I have for the layout is:
LatinViewController:loadView()
...
let latinView = LatinView()
latinView.autoresizingMask = [.ViewWidthSizable]
latinView.wantsLayer = true
latinView.layer?.backgroundColor = Theme.greenColor().CGColor
self.latinView = latinView
scrollView.documentView = latinView
...
LatinView:init()
...
let textView = LatinTextView()
textView.translatesAutoresizingMaskIntoConstraints = false
textView.string = "Long string..."
self.addSubview(textView)
self.textView = textView
self.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|[text]|", options: NSLayoutFormatOptions(), metrics: nil, views: ["text": textView]))
self.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|[text]|", options: NSLayoutFormatOptions(), metrics: nil, views: ["text": textView]))
...
LatinTextView:init()
...
self.minSize = NSMakeSize(0, 0)
self.maxSize = NSMakeSize(0, CGFloat(FLT_MAX))
self.verticallyResizable = true
self.horizontallyResizable = false
self.textContainer?.heightTracksTextView = false
...
Can this be done?
From your requirements it appears you can achieve the functionality simply by using NSAttributedString and a NSTextView. Following is the sample code A NSTextView already comes with rich text editing functionality and format storage can be achieved through a NSAttributedString
import Cocoa
@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {
@IBOutlet weak var window: NSWindow!
@IBOutlet var textView:NSTextView!
func applicationDidFinishLaunching(aNotification: NSNotification) {
let singleAttribute1 = [ NSForegroundColorAttributeName: NSColor.purpleColor() , NSBackgroundColorAttributeName: NSColor.yellowColor() ]
let multipleAttributes = [
NSForegroundColorAttributeName: NSColor.redColor(),
NSUnderlineStyleAttributeName: NSUnderlineStyle.StyleDouble.rawValue ]
var string1 = NSAttributedString(string: "Hello World", attributes: singleAttribute1)
var string2 = NSAttributedString(string: " This is knowstack", attributes: multipleAttributes)
var finalString = NSMutableAttributedString(attributedString: string1)
finalString.appendAttributedString(string2)
self.textView.textStorage?.setAttributedString(finalString)
}
func applicationWillTerminate(aNotification: NSNotification) {
// Insert code here to tear down your application
}
@IBAction func getAttributedString(sender:AnyObject){
var attributedString = self.textView.attributedString()
print(attributedString)
}
}
NSLayoutManager
(which is used by NSTextView
, and NSAttributedString
in general) has a special feature designed for altering text before displaying it on screen without changing the source: temporary attributes.
Look up NSLayoutManager
docs for methods that have "TemporaryAttribute" in their names:
- (void)addTemporaryAttribute:(NSString *)attrName value:(id)value forCharacterRange:(NSRange)charRange
They are supposed to be used for instance as green/red underlining of words during spellcheck, or to simply highlight a portion of text temporarily. They allow you to modify appearance of portions of text for mere display purposes without modifying the original attributed text source.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With