[gtkada] Signal handler
Dmitry A. Kazakov
mailbox at dmitry-kazakov.de
Thu Aug 4 11:23:42 CEST 2011
On Thu, 04 Aug 2011 09:22:05 +0200, you wrote:
>> If you do, do not forget to add "constant" for the getters. E.g.
>>
>> function Get_Label
>> ( Button : not null access constant Gtk_Button_Record
>> ) return UTF8_String;
>
> Why not indeed. However, if I derive Gtk_Button_Record, that prevents me from
> implementing a local cache for instance, so I am not sure what benefits this
> really brings.
Making it more Ada-like. (:-))
>> But a much more common case is like a window handling an event from one of
>> its buttons:
>
> I'd be interested to have the impact of more people on this list. I think the
> style of using objects for callbacks really heavy. I might not be used to it,
> but I find it much heavier than simple functions, at least when we do not have
> to pass user_data.
As my experience shows user data is needed almost always.
BTW, regarding free functions, they should follow the same type/event-safe
schema. I.e. if provided then:
package Gtk.Button is
...
-- Simple signal handlers:
-- Clicked event
type Simple_Clicked_Handler is access
procedure Handle (Button : access Gtk_Button_Record'Class);
procedure On_Clicked
( Button : access Gtk_Button_Record;
Handler : Simple_Clicked_Handler
);
>> type My_Main_Window_Record;
>> type My_Main_Window is access all My_Main_Window_Record;
>>
>> type My_Window_Clicked_Handler is new Clicked_Handler with
>> Window : My_Main_Window_Ptr;
>> end record;
>> overriding procedure On_Clicked ...;
>>
>> type My_Main_Window_Record is new Gtk_Window_Record with record
>> Box : Gtk_VBox;
>> Button : Gtk_Button;
>> Button_Clicked : My_Window_Clicked_Handler;
>> end record;
>>
>> [ Button_Clicked : Clicked_Handler (My_Main_Window'Access); would not work
>> because objects are not limited. ]
>
> You did not show the initialization of an object of type My_Main_Window, but it
> isn't so simple: to initialize Button_Clicked, you need to have already
> allocated the window, so that requires quite a few steps (assuming you have
> several callbacks):
>
> Win := new My_Main_Window_Record;
> Initialize (Win); -- standard GtkAda so far
> Win.Button_Clicked.Window := Win;
>
> Gtk_New (Win.Button);
> Win.Button.On_Clicked (Win.Button_Clicked);
Yes, the initialization is not different from how it is usually done.
> At this stage, I am not sure either of memory management. For instance, it is
> possible (although unlikely, but we don't want the scheme to be fragile) that
> the button is not in the same window (for instance because the button is a
> toggle button used to show the window). When the window is destroyed, the button
> still exists, and its callback is referencing an object that has been fragile.
> That's dangerous.
Not different from free functions and actually unrelated to the callbacks
themselves. If an alien button wants an explicit reference to the emitter
(or any other object), it has to deploy one of the standard GTK+ schemes:
1. A strong reference: Ref (Button.Window) upon construction, Unref upon
finalization (upon self emitted "destroy").
[This scheme is exposed to deadlocks.]
2. A weak reference: Ref (Button.Window) upon construction, Unref upon
window finalization ("destroy" emitted by Window) + zeroing the component
and conditional Unref when destroyed itself.
[This one is deadlock-safe, but requires consistent checking against null.]
There is no solution for safe referencing any possible object. It can be
the emitter, the recipient, some third object or multiple objects.
Solutions vary from case to case.
In any case I think it should not be conflated with handlers. One can
provide some controlled wrappers around messy GTK stuff, but as independent
packages, e.g.:
http://www.dmitry-kazakov.de/ada/gtkada_contributions.htm#5.2
--
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de
More information about the gtkada
mailing list