Signals vs override of leftMousePressed

Started by CombatWombat, 06 July 2023, 19:40:11

CombatWombat

Roughly what I am trying to do:
I have a class which inherits from panel, it is just a big grid.
Inside are child widgets, they are boxes with text etc contained in them.  (They also inherit from panel).

What I want to happen:
When I click on a "box" (child panel) I want to set it as selected.
When I click an already selected box, I want to be able to hold the LMB and move it.
When I click elsewhere on the grid I want to deselect any boxes that are selected.

What I tried so far:
#1.  override leftMousePressed on both the grid, and the box.  In this case the parent "grid" responds and appears to "eat" the event.  The child's method never triggers even if it was under the cursor.

#2.  Do not override.  Both grid and box use "onClick" to call their own methods.  In this case, first the parent and then the child respond to the "onClick". 

So my actual question then, is what is the difference between overriding and signals?  I assume signals are preferred when using stock tgui::widgets, and the override is needed when doing custom functionality.  If I override, then I need to handle passing the event to the child widgets even if I inherited from a widget which normally has sub-widgets?

QuoteUnlike with the SubwidgetContainer which forwards all events to the correct subwidget, if you inherit from Widget directly then you will likely have to handle some events yourself.
So I see "panel" is a "container" but not a "SubWidgetContainer", so I guess it also "does not forward"?


texus

#1
Both overriding or using signals could work. I think of overriding as defining the behavior of the widget itself whereas signals are used to inform some external object that the event occurred, but you can use whichever looks easiest.

For the dragging I think it might be easier to work with overriding functions, as you can implement leftMouseButtonNoLongerDown() to know when the mouse was released anywhere on the screen (which you need to know after the mouse was previously pressed on top of the box).

QuoteI need to handle passing the event to the child widgets even if I inherited from a widget which normally has sub-widgets?
Yes, but this is easy to do. By overriding the leftMousePressed function you are replacing the existing implementation (which passes the events to the child widgets). You can simply add the following line inside your leftMousePressed implementation to execute the existing TGUI behavior (and then you have your own custom code before or after that line).
Code (cpp) Select
Panel::leftMousePressed(pos);
One of the things that get executed by calling that line is calling processMousePressEvent at Container.cpp#L901 which does the actual work of finding the child widget below the mouse and passing the event along.

QuoteSo I see "panel" is a "container" but not a "SubWidgetContainer", so I guess it also "does not forward"?
Any Container-based widget will forward events (unless you override its functions to do otherwise). The quote is about the difference between SubwidgetContainer and Widget, where Widget itself doesn't forward anything.

SubwidgetContainer is a special class, is uses a Container internally, but it acts like a regular widget (you don't get access to its children). It's purpose is hiding the Container implementation. If you don't care that the user of your custom widget can access it's internals then you are probably better off inheriting from a class that inherits from Container (like you are doing by inheriting from Panel, which falls in the "Approach 1: extending existing widget" category).

CombatWombat

Thanks, I got something that works well.

I ended up doing:
leftMousePressed override to toggle into a "moving" mode.
leftMouseReleased override to turn off moving mode.
and mouseMoved overloaded to update the position.