Reputation: 416
I want to create a canvas that draws diagrams.
For that I've created custom class derived from NSView
where I've drown two rectangles and connected them with two lines.
I am using NSView.addTrackingArea
functionality in order to move and resize rectangles.
The issue I am facing with, How to create tracking areas to track mouse events for lines? (NSTrackingArea
accepts NSRect
shapes.)
The second question is more about approach. How do you think, this approach is okay to manipulate with graphic objects?
Upvotes: 3
Views: 721
Reputation: 6918
I don't think the approach you outline in your question is appropriate. As you've seen already tracking areas can't represent non-rectangular shapes, and if you're creating a graphics app you're going to need to represent a variety of shapes that aren't rectangular, not just lines. Fortunately help is at hand from Apple itself in the form Sketch, a sample drawing app that answers some fundamental questions about the basic setup of any program that wants to draw lots of different shapes to the screen.
Here's a quick overview of how they get shapes onto the canvas and how they hit-test those shapes:
NSView
with a single array containing Graphic
objects.Graphic
is an abstract base class that inherits from NSObject
. It exposes a number of empty methods:
Graphic: NSObject
- isContentUnderPoint(point: CGPoint) -> Bool
- frame: CGRect
- drawInRect(rect: CGPoint)
There are a number of concrete Graphic
subclasses (Line
, Rectangle
, Circle
, Square
, etc), each of which implements the above methods, as required.
Getting the shapes to the screen occurs in the canvas's drawRect:
// In MyCanvas (an NSView subclass)
func drawRect(dirtyRect: CGRect) {
for shape in self.graphics {
shape.drawInRect(dirtyRect)
}
}
Hit testing is much the same principle...
// in MyCanvas (an NSView subclass)
func mouseDown(theEvent: NSEvent {
let canvasPoint = convertPoint(theEvent.locationInWindow, fromView: nil)
for shape in self.graphics {
if shape.isContentUnderPoint(canvasPoint) {
// do something!
}
}
}
In the case of a Line
shape, a isContentUnderPoint
implementation would maybe calculate the equation of the line (using its start- and end- point) and then plug in the mouse-down point to see if it fits the equation. All in all it would take no more than a handful of lines of code, and it completely avoids any Cocoa drawing gymnastics.
Upvotes: 3