[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