[gtkada] Signal handler

Emmanuel Briot briot at adacore.com
Thu Aug 4 09:22:05 CEST 2011


> 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.

> Yes, actually I didn't want to make the example more complex than
> necessary. Practically it is always better to derive a new type:
>
>     type My_Main_Window is new Gtk_Window_Record with record
>         On_Destroy : Destroy_Main;
>         On_Delete  : Delete_Main;
>     end record;

Right, but as your example showed, there is nothing that prevents inexperienced 
used from using local variable, and that's very dangerous because gtk+ would 
then use a variable that has been freed when it finally executes the signal. So 
the scheme as proposed so far is fragile.

> or with interfaces:
>
>     type My_Main_Window is
>         new Gtk_Window_Record
>         and Delete_Event_Handler
>         and Destroy_Event_Handler with null record;

We will not use interfaces in GtkAda I believe.

> No wonder they have to abandon that because it is not very frequent for a
> widget to handle its own signals. That incidentally is the case for main
> window.

Agreed

> 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.

>
>     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);

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.


> Actually not fully. Sometimes you want a handler connected to several
> emitters. An automatically disconnecting handler object would need to
> maintain a list of emitters and keep track of them disappearing. Though
> technically possible, I had use that scheme once or twice, it might be to
> complex to implement as the default.

Remember we are not writing a GUI library here. The work you describe above is 
already done at the gtk+ level, so we do not want to add a heavy machinery on 
top of it, thus making things even slower.

> Glib.Type_Conversion_Hooks uses aggregates in Hook_Registrator.

Right, and indeed there are cases where we need to create "stubs" 
(Glib.Object.Get_User_Data) for instance, which would not work with a limited 
type. So that's not doable indeed.




More information about the gtkada mailing list