Deleting multiple components with a single mouse stroke


I have a parent component which have several child components. If you left click on any of these child components they do an action. If you right click on them, you delete them.

The objetive is to do MouseDown on a child component, delete it, and continue dragging, deleting all those child component under mouse path. It works right if you start the mouseDown on the parent component (because its mouseDrag is called). But if you do the mouseDown in any child component, the mouseDrag of the parent won’t be called (which has logic) since the child object was deleted. How could I solve this?

I tried adding listeners, and calling directly to the mouse functions of the parent component, but they didnt work (and I think the last method can have some problems)

Thanks you

Have you considered using a transparent overlay component in front of all of them? You can forward events to the children behind it as necessary, but handle the drag there instead.

You can have it as a child of the container if you like (and make sure it’s always in front), but I usually prefer to do this kind of thing with the overlay as a sibling of the container (and put it in front of that), so I never have to worry about the ordering within the container (or the overlay considering itself when walking the children).

e.g. the following kind of hierarchy…

\- ContentComponent
   |- CellContainer
   |   |- Cell
   |   |- Cell
   |   \- Cell
   \- MouseOverlay

It would need to keep a reference to the container, and be able to access the ‘cells’ within it in order to update/notify them, naturally. You can also make it automatically take the bounds of the target container (if it’s a sibling, the bounds are in the same space); this way the x/y coords of the mouse events are exactly the same, too.

It can be pretty fiddly, but it might help.

I thought about it in the past, but i had to discard it because using a simple setInterceptsMouseClicks(false, false) in the childs give me that overlay in the same parent component, avoiding extra components, and I couldnt see any advantage. Independently if I use the transparent overlay or the setInterceptsMouseClicks, i must perform a manual search in the parent component to discover all of these child components that were falsely clicked (or mousewheeled), which is something I dont like too much, because it doesnt seems too efficient.

Anyway I appreciate a lot your effort, thanks! :slight_smile: If you have another idea or comment about this, please lets me know.

It seems that setInterceptsMouseClicks(false, false) works with mousewheel, mouse move, and all mouse events, right?

More ideas or tips, please?

A Component is not an Adobe Illustrator layer.

If you want to do things like click to select objects, rectangular selection, deleting, moving, etc… of shapes on the screen you should do it within a single Component and doing all of the hit testing, and maintenance of the parent/child hierarchy yourself.

I agree with the other two posters here - you need a component just to manage the other components.

If the component being dragged is self-managing, then you run into issues in not getting that last message, no matter what you do. The only way to handle it is to have a separate manager. This would be true in almost any other GUI programming system, not just JUCE.

I also disagree that it will make your code much more complex. JUCE’s Components are very feature-rich - all the things you want to do, translating coordinate from or to child components or locating a hit, each can be accomplished in a single line.

In fact, it’ll probably make your code simpler - it might well be that your child classes don’t even need to override any methods and can vanish in favor of using the Juce base class unchanged. This happened to me when I did something like that…

Ok, i’ll try the approach you suggest. :slight_smile:

Anyway, is there any advantage of using an overlay component instead a setInterceptsMouseClicks(false, false) in all childs components (doing the parent the component-manager)?

And how could you continue using something like to mouseEnter/mouseExit/mouseMove of the child components with any of those approaches? Doing constant search every time you move the mouse cursor on the parent component?

I guess it basically amounts to the same thing in this situation!

Excuse me again, I edited my post before your answer, how would you manage childs mouseMove/mouseEnter with that solution? I ask this because I want they repaint on mouse activity depending if mouse is over or down, and since isMouseOver() is always false, they’re not painting as they should.

I solved the puzzle. I’m gonna test it next week (hey, its my birthday, i deserve a rest :))and I’ll write what I did here, someone could find it useful. Basically i followed your overlay component theory. Thanks you! :wink:

Well, not solved at all :evil:

With the overlay solution my child components arent informed when the mouse is over them, or mouse has moved into them, i’m not able to inform them with mouseListeners.
The same using the setInterceptsMouseClicks(false, false).

What am I missing?

Edit: It’s the same unsolved problem: