Search code examples
cocoaswiftquartz-graphicsappkitdrawing2d

Appkit / Quartz / CG Nesting NSTextView within a custom view correctly


Trying to teach myself how to do custom drawing in OS X. I am trying to nest a NSTextView within a NSView.

Got top, want bottom

I can't seem to figure out the step I am missing to get the NSTextView to behave as if it wasn't embedded in another custom view (I.e., text should begin redering from top-left in the frame provided to the NSTextView, left-to-right and top-to-bottom).

import Cocoa
import AppKit
import XCPlayground

class MyView : NSView {
    let lipsum = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."

    override init(frame: NSRect) {
        super.init(frame:frame)
        self.wantsLayer = true
    }

    required init(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    override func drawRect(dirtyRect: NSRect) {
        super.drawRect(dirtyRect)

        let grey = NSColor.grayColor()
        self.layer?.backgroundColor = grey.CGColor

        let boundaryRect = NSInsetRect(dirtyRect, 10, 10)
        let textRect = NSInsetRect(boundaryRect, 10, 10)

        let path = NSBezierPath(roundedRect: boundaryRect, xRadius: 5, yRadius: 5)
        path.stroke()


        let text = NSTextView(frame: textRect)

        text.backgroundColor = grey
        text.insertText(lipsum)

        text.drawRect(textRect)
    }
}

var frame = NSRect(x: 0, y: 0, width: 400, height: 400)

let myView = MyView(frame: frame)

let textView = NSTextView(frame:frame)
textView.insertText(myView.lipsum)

XCPShowView("my view", myView)
XCPShowView("text view", textView)

Solution

  • You haven't actually embedded the text view inside the parent view. You can do that with addSubview().

        let text = NSTextView(frame: textRect)
    
        text.backgroundColor = grey
        text.insertText(lipsum)
    
        self.addSubview(text) // <---------
    }