Reputation: 105
General idea: highlight groups of characters in a text paragraph in NSScrollView
(that contains NSTextView
). I am getting bounding rectangle of the chosen characters from NSLayoutManager.boundingRect()
and create CAShapeLayer
with its coordinates/size in place of the characters.
The problem is that if the character range in question spans two lines, the bounding rectangle would cover both of them in height and width, so I need to do it for every line of the text in the text view.
Issue in question: string properties in NSTextView
, NSTextStorage
and NSTextContainer
return strings without line breaks ("\n"
). How can I:
1) find the actual text value of the text view with line breaks?
2) use other techniques to iterate through lines of a text view?
3) use other libraries to accomplish my general idea?
Code of my View Controller:
import Cocoa
class ViewController: NSViewController {
@IBOutlet weak var textView: NSTextView!
@IBOutlet weak var shapeView: NSView!
override func viewDidLoad() {
super.viewDidLoad()
shapeView.wantsLayer = true
textView.string = "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."
}
@IBAction func checkButtonPressed(sender: NSButton) {
let range = NSMakeRange(2, 5) //Creating a makeshift range for testing purposes
let layoutManager = textView.layoutManager
var textRect = NSRect()
//Accessing bounding rectangle of the chosen characters
textRect = (layoutManager?.boundingRect(forGlyphRange: range, in: textView.textContainer!))!
//Creating a parent layer and assigning it as the main layer of the shape view
let parentShapeLayer = CAShapeLayer()
shapeView.layer = parentShapeLayer
//Creating an actual rectangle - CAShapeLayer
let shapeLayer = CAShapeLayer()
parentShapeLayer.addSublayer(shapeLayer)
parentShapeLayer.isGeometryFlipped = true
shapeLayer.frame = textRect
shapeLayer.backgroundColor = NSColor.yellow.cgColor
if let string = textView.textStorage?.string {
for var char in string {
if (char == "\n") {
print(char) //Does not print anything
}
}
}
}
override var representedObject: Any? {
didSet {
// Update the view, if already loaded.
}
}
}
P.S. I know that NSLayoutManager
has method drawBackground()
and I was not able to find what context it needs, but it is a different question.
Upvotes: 3
Views: 452
Reputation: 105
I have found a conceptual workaround: I resorted to drawing rectangles for individual characters, rather than groups of characters, so line break detection was avoided. Not optimal, but works.
Upvotes: 1