jyet jyet - 3 months ago 22
Objective-C Question

How to draw bezierPath inside NSCollectionView?

I have sub-classed

NSCollectionView
to listen to mouse down and mouse event. I want to draw a line whenever mouse is clicked inside collection view.

This is my drawing code block.

public func drawLine() {

//// Bezier Drawing
let bezierPath = NSBezierPath()
bezierPath.move(to: NSMakePoint(50.0, 60.0))
bezierPath.line(to: NSMakePoint(65.5, 72.5))
bezierPath.line(to: NSMakePoint(65.5, 93.5))
bezierPath.line(to: NSMakePoint(97.5, 87.5))
bezierPath.line(to: NSMakePoint(97.5, 56.5))
NSColor.black.setStroke()
bezierPath.lineWidth = 10
bezierPath.stroke()
}


Inside
NSCollectionView
Sub-Class I call this method in
draw(_ dirtyRect: NSRect)
, it correctly shows line when app loads up. But to make it draw only when mouse is clicked, I moved it to
mouseDown(with event: NSEvent)
method:

override func mouseDown(with event: NSEvent) {
func drawLine()
}


But when I mouse click on the collection view, I get following error:


: CGContextSetStrokeColorWithColor: invalid context 0x0. If you want to see the backtrace, please set CG_CONTEXT_SHOW_BACKTRACE environmental variable.
: CGContextSaveGState: invalid context 0x0. If you want to see the backtrace, please set CG_CONTEXT_SHOW_BACKTRACE environmental variable.


My aim is to draw line from center of collectionViewItem to another item on mouse click, for that I have subclassed
NSCollectionViewItem
and added a custom
NSView
to
addTrackingArea()
. I have set a delegate which passes the current selected item.

I need help to know where should I put my drawing code inside
NSCollectionView
to not get error like above.

Answer

Yep,

You cannot do as such.

What you will want to do is :

  • Add in your class a boolean that you will pass to true in mouseDown: and to false in mouseUp:

  • In your draw: method, check for that bool to knwow if you are to draw the line or not

  • In mouseUp: and mouseDown:, after setting the boolean, call self.setNeedDisplay() (that will prepare a context for you and call draw automatically.)

Point is: You cannot call draw: on your own. When you are drawing, you are drawing inside a Graphic Context, and it has to be laid out for you.