3

I have two windows, each with a round NSView:

------------------     ------------
|X-+ Oscillator  |     |X-+ Mixer |
|----------------|     |----------|
|                |     |          |
|        O       |     |     O    |
|                |     |          |
|                |     |          |
------------------     ------------

Both windows are in a seperate NIB. I want to be able to draw a line between the two round NSViews at runtime, using drag'n'drop, just like connecting IBOutlets in Interface Builder:

------------------     ------------
|X-+ Oscillator  |     |X-+ Mixer |
|----------------|     |----------|
|                |     |          |
|        O-------+-----+-----O    |
|                |     |          |
|                |     |          |
------------------     ------------

I also want to be able to determine to which NSViews the NSViews are connected using the drawn lines. I need this to connect Oscillators to Mixers. I also want to be able to remove the connections by dragging into empty space.

Can anyone explain me how to do this? Thanks.

2 Answers2

2

The problem is having a view into which you can draw that spans the two windows' combined rects (or the screen or screens they're on). This is typically done with a borderless, transparent "overlay window." There are lots of examples of a borderless, transparent window available online.

On the start of the drag, the overlay window appears (but is invisible to the user) positioned over your drawing area. As the drag is updated, you draw your line, translating the overlay view coordinates to/from the source/target view coordinates. When the drag is complete, do some animation (like a fade or a blink) then order out the overlay window.

Joshua Nozzi
  • 60,946
  • 14
  • 140
  • 135
  • No code? That's not much help. Why the green checkmark? – johnrubythecat Oct 23 '14 at 18:10
  • The green checkmark is because I gave a possible approach to the problem the OP posted but the implementation details can vary quite a lot and since I don't have any ready-made solution laying around and I don't do others' homework for them. I answered the question regarding an approach; if the OP (or anyone else) gets stuck, let them ask a specific question (describing what they've tried and what went wrong) as expected on SO. – Joshua Nozzi Oct 23 '14 at 20:38
  • I see. I would have expected an example, given the question. – johnrubythecat Oct 25 '14 at 01:13
  • I'm sorry the free brownies didn't come with a free glass of milk. The OP seemed to have been satisfied enough with the answer to have marked it accepted over four years ago, but to each his own, I suppose. – Joshua Nozzi Oct 25 '14 at 15:28
0

I think the biggest problem with your approach is the fact that you have two separate windows, one with the oscillator view, and one with the mixer. If you could change your design so as to display all synthesizer components (or maybe radio frequency components - not sure what you're doing!) in a single window, then your problems will get much simpler.

As Joshua said, one approach is to use an invisible overlay window which just shows the link. But if you're really using two separate windows then you can't (as Joshua suggests) order out the overlay window at the end of the drag. If you do that, the link will disappear at the end of the drag. If you want the link to continue to be displayed (think of Interface Builder or - better yet - Quartz Composer) then you need some mechanism to persistently display the link. This is especially true if you want to, at a later point, allow the user to remove the link.

I'd strongly suggest building your interface around a single window. Also, consider using Core Animation to display each link as a layer.

Dave

Dave Jewell
  • 116
  • 1
  • 1
  • If the connection is intended to persist, then the overlay window would simply stay ... it's not that difficult to adapt. The only real challenge to an ever-present overlay is allowing clicks to fall through. – Joshua Nozzi Jun 13 '10 at 18:29
  • Yes, it would be possible to make the overlay window method work persistently. But as you say, that introduces issues with click throughs, and then what do you do in the general case where you have multiple entities with multiple connections between them? You've either got to use one overlay window per link (ughh), or add new links to an existing overlay window which might need to resize to span all linked entities. The more I think about this, the more I think that a cleaner solution is to just do it all in one window. This is just the sort of problem that CALayer solves beautifully. – Dave Jewell Jun 13 '10 at 18:38
  • In the case of a persistent window, it can remain the size of the screen (or all screens). The click-through problem really isn't that big a deal and there are already code samples floating around. As to the complexity, sure it's difficult, but not so difficult that a multi-window approach should be trashed because of it. If the OPs requirements are multiple windows and a solution is possible, then it's best to address the original requirements. – Joshua Nozzi Jun 13 '10 at 21:04