jyet
jyet

Reputation: 845

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.

Upvotes: 0

Views: 119

Answers (1)

Florian Burel
Florian Burel

Reputation: 3456

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.

Upvotes: 1

Related Questions