Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NSTextView inside NSView and NSScrollView

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. Highlight

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 NSViews 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?

like image 691
jamespick Avatar asked Feb 09 '16 18:02

jamespick


2 Answers

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)
    }
}

enter image description here

like image 82
Debasis Das Avatar answered Oct 11 '22 04:10

Debasis Das


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.

like image 44
hamstergene Avatar answered Oct 11 '22 04:10

hamstergene