Mouse events dropping through components


#1

Hello, this should be a trivial one:

I have a component with a child-component. The child is a Button, so it implements paintButton. Sadly, it intercepts all mouse events, so the parenting component doesn’t “get it”. I want the parent to get the exact same mouse events the child does. I have tried passing the event explicitly, but it seems like some of them get lost (esp. the very first click, although after a short delay, holding the mousebutton is registered with the parent). Is there any easy way of propagating all mouseevents to immediate parents?

  • Thanks in advance!

-A


#2

Yes, check out Component::addMouseListener - you can add a listener to the parent comp that also receives all the events in child comps.

But why would you need to spy on a button’s mouse events? Sounds to me like you’re doing something a bit hacky…


#3

Why do you need to have these events? If you want the outer component to do all the logic for buttons (button presses, highlights etc…) then you don’t need a child component; you’d draw the buttons appearance on the main component, and then respond to the main component’s mouse events. This is, however, stupid.

The button component base handles all the logic (and can make the button highlight etc…), but crucially it sends a button message to any registered listener. Your outer component wants to know if the button is clicked, i presume? You make it a ButtonListener, and you define the buttonClicked() function to respond.

e.g.

class OuterComponent : public Component,
                                    public ButtonListener
{
public:

   OuterComponent ()
   {
      button = new MyButton ();
      button->addListener (this);
      ...
   }

   ...
  
   void buttonClicked (Button* source)
   {
      if (source == button)
      {
         // respond here
      }
   }

   ...

};

#4

Yes, it might sound like a slight hack, but here’s the reason:

The outer component is a generic component, that opens a popup list component to select from. It needs a component to be the one the user presses to open the nemu - the child component. This should be as generic as possible, so that I can both use a Button, an ImageComponent, and even an “empty” one, where I just override the parent’s paintButton method in the inherited parent component, and leave the child NULL.

Buttonclicks are not enough, since I also want the mouseEnter etc. to be passed to the parent.

  • Thanks for you advice :slight_smile:

-A


#5

Yeeesh. If I had an employee who wrote code like that they’d be sacked on the spot! (Not that I actually have any employees… maybe it’s just as well…)

Make the parent class implement an interface with a pure virtual method like showPopupMenu(), so that the child components can try to dynamically cast their parent to this class, and call the method when it’s appropriate.


#6

That’s a good idea, If I only want my own child components (written by me, or someone with knowledge of said interface) to sit in my parent. That’s not the case, though, so no cigar.

Anyway, the addMouseListener did the trick. I never thought of them that way - only for listening “directly” to the event source. But of course… :slight_smile:

  • Thanks!

#7

Well I don’t know exactly what you’re trying to do, but am sure there must be a cleaner way that spying on mouse messages - that just seems very hacky.


#8

why? why? WHY??

You want to have a generic component to be able to provide this ability? an image display… a button… these are Components that have a specific ability that you want. Do you realise what this looks like? It looks like a class.

You could make a class called ‘MySpecialInternalTypeThatINeed’ which just has a set of functions/behaviours to interact with the outer component. You can then just inherit this class into whatever contained class type that you wish to host. If you were just using a button, this sort of thing is already covered, but you could get the button to use this class behaviour (in the button’s virtual click function, call the response function inherited from your class). Your base class will know a function it can call from the (registered) owning Component to trigger your menu, so you can call that from clicking the button (or the image, or the rotating cogmouse etc…).

At the end of the day, you want a system that attributes a particular behaviour to ‘an item’ that is contained within. Thus, the simplest solution is you want whatever it is inside to have a particular quality, rather than try to get a particular behaviour out of whatever is inside.


#9

That’s all very true.

Imagine, then, that I can’t inherit from whatever object I wish to contain - or for some reason do not wish to. In this case it will be impossible to make it “signal” it’s container into whatever behavior I wish.

One such case might be if I need a lot of different (types of) objects inside the containing component, and can’t be bothered to extend every single one of them with a new inheriting class. I am a big fan of clean paradigmatic implementation, but at the end of the day, I need to get work done. I’ll make sure to test :wink:

  • what’s a cogmouse?

#10

you don’t know what a cogmouse is?? i don’t see how you’re going to find an effective solution without that sort of thing covered…


#11

I understand, but Sod’s Law of Hacking says that all the time you save in the short term gets wasted:
a) by having to test much more carefully
b) when it all mysteriously crashes later on
c) when you come back to the code in a few months, can’t remember what the hell is going on, and end up re-writing it all because that’s quicker than trying to understand it.


#12

Sounds like a highly informed individual, this Sod character.


#13

Hehe, valid points all around. I’m not worried though. The container thingy is very light code-wise, and well commented. Regarding test and stuff, the code I would have to write to use the container in the “paradigmatic” way would be more error-prone and tedious to write - doing it this way requires no additional code (because no contained components are required to implement a certain interface) - and another (excellent) rule of thumb: less code, less errors. Writing tedious trivial code is when one makes the most mistakes in my experience.

Thanks for caring though - it’s nice to know that us juce-users are in good hands. Code discipline is important, I agree - but rules can certainly become obstacles, and this is (for me) such a case.

-A


#14

Not to beat a dead horse, but maybe I could expand upon what I think Jules is saying - partly for my own confirmation?

In more current OOP languages, there’s a mechanism called an interface. C++ doesn’t have that. It came about because inheritance is too strong a bond for many situations - as you rightly worry. The ‘best’ solution in C++ is a very light multiple inheritance, and Jules has used it heavily in Juce, so you might want to not fear it.

In short:

class fooListener // hopefully little to no inheritance itself
{

    virtual void bodgeMouseClicks();
}

class yourBehemothComponent: public fooListener
{
    void bodgeMouseClicks()
    {
        doShowPopupMenu();
    }

    // reams O'Code
}

Then in your sub-components, cast the parent to fooListener and call bodgeMouseClicks. I would dynamic cast, then if the parent isn’t a foolistener we can skip it.

It may seem like more code, but that’s the way everything else in Juce works [and Jules patently knows more than me] so I would tend to use it.

Bruce


#15

Beat away :slight_smile:

I’m beginning to suspect that you guys think I don’t understand what you’re syaing :D. I do, and I strongly believe that’s why I am turning hardheaded. I actually did a solution like this at first, but the other way is much easier - and therefore (to me) less error-prone. Keep in mind that buttonClicks are not the only mouse events I need to trigger on, and I might not have the advantage of inheriting the “interface”.

So let’s leave the horse for now :slight_smile: - but thanks for your input.

-A


#16