Reputation: 1071
There is a subclass of NSImageView and the instance of CALayer is created, so we see a rectangle on the image. Questions is how to move this rectangle when mouse is down (when mouse pointer inside of the rectangle) and dragged. When mouse is up this rectangle (CALayer) should stay in the new position on the image.
For instance
class ImageViewWithRectangle: NSImageView
{
var shape : CAShapeLayer!
func drawRectangle()
{
shape = CAShapeLayer()
shape.lineWidth = 1.0
shape.fillColor = NSColor.clear().cgColor
shape.strokeColor = NSColor.gray().cgColor
shape.lineDashPattern = [1,1]
self.layer?.addSublayer(shape)
let path = CGMutablePath()
path.moveTo(nil, x: 1, y: 1)
path.addLineTo(nil, x: 1, y: 50)
path.addLineTo(nil, x: 50, y: 50)
path.addLineTo(nil, x: 50, y: 1)
path.closeSubpath()
self.shape.path = path
}
}
Upvotes: 2
Views: 730
Reputation: 4282
You are very close to your goal, just implement the mouse events !
Here is a working snippet:
class ImageViewWithRectangle: NSImageView {
var shape : CAShapeLayer!
var shapeRect = NSMakeRect(10, 10, 100, 50)
var shouldMove = false;
var anchorPoint : NSPoint!
override func awakeFromNib() {
//We MUST implement layers! Otherwise nothing will work!!
//You could do it even through Interface Builder
self.wantsLayer = true;
}
override func drawRect(dirtyRect: NSRect) {
//Every time the view is drawn, remove the old layer
self.layer?.sublayers?.forEach({ $0.removeFromSuperlayer() })
//Draw the new one
self.drawRectangle()
}
func drawRectangle()
{
//Draw the layer
shape = CAShapeLayer()
shape.lineWidth = 1.0
shape.fillColor = NSColor(calibratedWhite: 1, alpha: 0).CGColor
shape.strokeColor = NSColor.grayColor().CGColor
shape.lineDashPattern = [1,1]
shape.backgroundColor = NSColor.greenColor().CGColor
//No need for CGPaths for a simple rect, just set the frame and fill it
shape.frame = self.shapeRect
self.layer?.addSublayer(shape)
}
//Implmenet mouse events
override func mouseDown(theEvent: NSEvent) {
//get coordinates
let pos = theEvent.locationInWindow
//Check if inside the rect
if ((pos.x >= self.shapeRect.origin.x) && (pos.x <= self.shapeRect.origin.x + self.shapeRect.size.width)) {
//X match, now check Y
if ((pos.y >= self.shapeRect.origin.y) && (pos.y <= self.shapeRect.origin.y + self.shapeRect.size.height)) {
//If we get here, then we're insisde the rect!
self.shouldMove = true;
//OPTIONAL : Set an anchor point
self.anchorPoint = NSMakePoint(pos.x - self.shapeRect.origin.x, pos.y - self.shapeRect.origin.y);
}
}
}
override func mouseDragged(theEvent: NSEvent) {
if (self.shouldMove) {
let pos = theEvent.locationInWindow
//Update rect origin, or whatever you want to use as anchor point
self.shapeRect.origin = NSMakePoint(pos.x - self.anchorPoint.x, pos.y - self.anchorPoint.y)
//Redraw the view
self.display()
}
}
override func mouseUp(theEvent: NSEvent) {
if (self.shouldMove) {
//Reset value
self.shouldMove = false;
}
}
}
The output will be something like this (No bg images have been set though)
You could even add transition effects, borders, gradients and lots more!
CALayers and more generally CoreAnimation is really powerful!
Please let me know if you need clarifications,
I hope this helped, if so mark this answer as correct so that others can use it!
Cheers.
Upvotes: 5