Thinking in Swift: Click handling


(Rick M) #1

I'm still just learning Swift, after decades of C++ and Objective-C(++). I've written entire apps in Swift, but I don't "think in Swift" very well yet. So I'm looking for advice on what classes, protocols, and extensions might be "swifty" in this example.

Background

···

----------
I'm working on a new little app, a graphical 2D spline editor (mostly an experiment), written in Swift (for macOS, but the answer to this question need not be macOS-specific).

One of the things I have to do is handle the mouse in my drawing canvas. I have a View, and a Path. The Path contains all the information about the set of spline curves (anchor points and two control points per anchor, except on open ends where there is only one control point).

Let's say you can click and drag any anchor point or control point to move it. Releasing the mouse completes the operation. A click on any other part of a Path would move the entire Path. The curve should update in real time as the drag happens.

One Approach
------------
A naive implementation would let the Path do all the heavy lifting:

• View gets a mouse-down event, passes it to each Path until one says it got the hit (the click occurred on the path, in an anchor point, or a control point).
• View marks that Path as "active."
• Path marks the hit point (or entire self) as "active."
• View gets mouse-moved event, passes it to active Path.
• Path adjusts active Point, or all points, based on event coordinates.
• View gets mouse-up event, passes it to active Path.
• Path completes moving points.
• View clears active Path.

I don't like this approach because it imbues the Path with a lot of knowledge about mouse events. Is there a better way? It's not quite enough to put it all in an extension, because there is state that must be kept for the drag operations.

I could make a separate object that handles all that state, but it would need to know a fair bit about the Path. That smells better to me, in that the relationship is one-way (the PathMouseHandler knows about the Path, but not vice-versa).

Now, what if I had more than just Path objects? Now I don't know what kind of MouseHandler I need until after the first click is processed.

Anyway, I'm just curious about the best way to implement this *in Swift* (as opposed to say, C++).

Thanks!

--
Rick Mann
rmann@latencyzero.com


(Dave Abrahams) #2

As someone who's used both languages extensively, there's nothing in
about this problem that suggests I'd approach it particularly
differently in the two languages. I think a fairly direct translation
of the most natural C++ approach would work out just fine.

···

on Thu Nov 10 2016, Rick Mann <swift-users-AT-swift.org> wrote:

Anyway, I'm just curious about the best way to implement this *in Swift* (as opposed to say, C++).

--
-Dave