[gtkada] Signal handler

Dmitry A. Kazakov mailbox at dmitry-kazakov.de
Wed Aug 3 20:34:43 CEST 2011


On Wed, 03 Aug 2011 14:06:25 +0200, you wrote:

>> Maybe the names Connect and Handle should rather include the event name.
>> E.g. Connect_To_Clicked and Handle_Clicked. That would ease adding handler
>> interfaces to the composite widgets.
> 
> I'd rather use names like On_Clicked, or something.

Yes, I used "Handle" because it is how it is described in the
documentation. On_<event> is a better name.

> By the way, since we would be generating the code, we could indeed generate a 
> "not null access" if the user passes a -gnat05 switch. Currently, we do not 
> expect users to generate the sources on their machine, since that requires a 
> python installation which might not always be available.

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;
 
>>     Window      : Gtk_Window;
>>     On_Destroy : Destroy_Main;
>>     On_Delete  : Delete_Main;
>> begin
>>     Gtk_New (Window);
>>     Window.Connect_To_Destroy_Event (On_Destroy);
>>     Window.Connect_To_Delete_Event (On_Delete);
> 
> This code is very dangerous.

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;

or with interfaces:

   type My_Main_Window is
       new Gtk_Window_Record
       and Delete_Event_Handler
       and Destroy_Event_Handler with null record;

> The approach taken (and now abandoned) by Java was to subclass:
> 
>    type My_Window is new Gtk_Window_Record with private;
>    overriding procedure On_Delete_Event (Self : My_Window) return Boolean;

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.

But a much more common case is like a window handling an event from one of
its buttons:

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

> At least that solves the lifetime issue (the callback exists as long as the 
> window).

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.

>> BTW, did you consider possible impact of turning GObject_Record limited? It
>> would make life much easier when developing user and composite widgets.
> 
> I don't think we have looked at this approach. Since we are mostly manipulating 
> pointers in GtkAda, it might be a simple matter of adding "limited" in the 
> declaration. Can you check whether it works ?

Glib.Type_Conversion_Hooks uses aggregates in Hook_Registrator.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



More information about the gtkada mailing list