I use an event callback with user data.
I first declare a package :
package Handler_Motion_Notify is new
Gtk.Handlers.User_Return_Callback (Widget_Type => Gtk.Text_View.Gtk_Text_View_Record,
Return_Type => Boolean,
User_Type => t_Debug_Panel);
The function callback is declared like this :
function On_Motion_Notify (TextView : access Gtk.Text_View.Gtk_Text_View_Record'Class;
DebugPanel : t_Debug_Panel) return Boolean;
The connection is done like this :
Handler_Motion_Notify.Connect (Widget => Panel.TextView,
Name =>
Gtk.Widget.Signal_Motion_Notify_Event,
Cb => On_Motion_Notify'Access,
User_Data => t_Debug_Panel(Panel));
This works correctly. But... I need to have access to the event in the callback function.
How can I achieve this ?
On 2021-09-04 23:39, DrPi wrote:I suppose it doesn't crash because I don't use any callback parameter in
I use an event callback with user data.
I first declare a package :
package Handler_Motion_Notify is new
Gtk.Handlers.User_Return_Callback (Widget_Type =>
Gtk.Text_View.Gtk_Text_View_Record,
Return_Type => Boolean,
User_Type => t_Debug_Panel);
The function callback is declared like this :
function On_Motion_Notify (TextView : access
Gtk.Text_View.Gtk_Text_View_Record'Class;
DebugPanel : t_Debug_Panel) return
Boolean;
This is wrong. The motion-notify-event callback has the parameters:
1. Target
2. Gdk.Event.Gdk_Event_Motion
3. User data
The connection is done like this :
Handler_Motion_Notify.Connect (Widget => Panel.TextView,
Name =>
Gtk.Widget.Signal_Motion_Notify_Event,
Cb => On_Motion_Notify'Access,
User_Data => t_Debug_Panel(Panel));
This works correctly. But... I need to have access to the event in the
callback function.
Maybe it does not crash but it is incorrect.
How can I achieve this ?
There is no shortcut Connect and Callback defined in
User_Return_Callback. Therefore you have to use a general-case callback
with the parameter list:
function On_Motion_Notify
( Object : access Gtk_Text_View_Record'Class;
Params : Glib.Values.GValues;
Data : t_Debug_Panel
) return Boolean;
connected as:
Handler_Motion_Notify.Connect
( Panel.TextView,
"motion-notify-event", -- = Signal_Motion_Notify_Event
On_Motion_Notify'Access,
t_Debug_Panel (Panel)
);
The parameter is accessed using the function Nth or Gtk.Argument.Unchecked_To_Gdk_Event_Motion, e.g.
Gtk.Argument.Unchecked_To_Gdk_Event_Motion (Params, 1)
P.S. Since the target is practically never used in callbacks, you can instantiate Gtk.Handlers.User_Return_Callback with GObject_Record. This
way you could use it with all types of widgets. That reduces the number
of instantiations.
On 2021-09-05 15:50, DrPi wrote:
Le 05/09/2021 à 00:29, Dmitry A. Kazakov a écrit :
With "Gtk.Arguments.Unchecked_To_Gdk_Event_Motion (Params, 1);" , I
get an error :
expected private type "C_GValues" defined at glib-values.ads:53
found private type "GValues" defined at glib-values.ads:48
I see, then you must to implement it yourself. It could be something
like this (not tested):
package Conversions is
new System.Address_To_Access_Conversions (Gdk_Event_Motion);
Event : Gdk_Event_Motion renames
Conversions.To_Pointer (Get_Address (Nth (Params, 1))).all;
Le 05/09/2021 à 00:29, Dmitry A. Kazakov a écrit :
With "Gtk.Arguments.Unchecked_To_Gdk_Event_Motion (Params, 1);" , I get
an error :
expected private type "C_GValues" defined at glib-values.ads:53
found private type "GValues" defined at glib-values.ads:48
Le 05/09/2021 à 16:48, Dmitry A. Kazakov a écrit :Like all subprograms accepting C_GValues as a parameter ?
On 2021-09-05 15:50, DrPi wrote:
Le 05/09/2021 à 00:29, Dmitry A. Kazakov a écrit :
With "Gtk.Arguments.Unchecked_To_Gdk_Event_Motion (Params, 1);" , I
get an error :
expected private type "C_GValues" defined at glib-values.ads:53
found private type "GValues" defined at glib-values.ads:48
I see, then you must to implement it yourself. It could be something
like this (not tested):
package Conversions is
new System.Address_To_Access_Conversions (Gdk_Event_Motion);
Event : Gdk_Event_Motion renames
Conversions.To_Pointer (Get_Address (Nth (Params, 1))).all;
So, Gtk.Arguments.Unchecked_To_Gdk_Event_Motion is useless ?
Le 05/09/2021 à 16:58, DrPi a écrit :
Le 05/09/2021 à 16:48, Dmitry A. Kazakov a écrit :Like all subprograms accepting C_GValues as a parameter ?
On 2021-09-05 15:50, DrPi wrote:
Le 05/09/2021 à 00:29, Dmitry A. Kazakov a écrit :
With "Gtk.Arguments.Unchecked_To_Gdk_Event_Motion (Params, 1);" , I
get an error :
expected private type "C_GValues" defined at glib-values.ads:53
found private type "GValues" defined at glib-values.ads:48
I see, then you must to implement it yourself. It could be something
like this (not tested):
package Conversions is
new System.Address_To_Access_Conversions (Gdk_Event_Motion); >>>
Event : Gdk_Event_Motion renames
Conversions.To_Pointer (Get_Address (Nth (Params, 1))).all;
So, Gtk.Arguments.Unchecked_To_Gdk_Event_Motion is useless ?
On 2021-09-05 17:04, DrPi wrote:
Le 05/09/2021 à 16:58, DrPi a écrit :
Le 05/09/2021 à 16:48, Dmitry A. Kazakov a écrit :Like all subprograms accepting C_GValues as a parameter ?
On 2021-09-05 15:50, DrPi wrote:
Le 05/09/2021 à 00:29, Dmitry A. Kazakov a écrit :
With "Gtk.Arguments.Unchecked_To_Gdk_Event_Motion (Params, 1);" , I
get an error :
expected private type "C_GValues" defined at glib-values.ads:53
found private type "GValues" defined at glib-values.ads:48
I see, then you must to implement it yourself. It could be something
like this (not tested):
package Conversions is
new System.Address_To_Access_Conversions (Gdk_Event_Motion); >>>>
Event : Gdk_Event_Motion renames
Conversions.To_Pointer (Get_Address (Nth (Params, 1))).all;
So, Gtk.Arguments.Unchecked_To_Gdk_Event_Motion is useless ?
It is a part of GValues object. But you could create a child package
that would have access to the internals of GValue and get access to
C_GValues in GValue.
Le 05/09/2021 à 17:12, Dmitry A. Kazakov a écrit :
It is a part of GValues object. But you could create a child packageI didn't know I can create a child Package of a GtkAda Package myself.
that would have access to the internals of GValue and get access to
C_GValues in GValue.
On 2021-09-05 17:20, DrPi wrote:
Le 05/09/2021 à 17:12, Dmitry A. Kazakov a écrit :
It is a part of GValues object. But you could create a child packageI didn't know I can create a child Package of a GtkAda Package myself.
that would have access to the internals of GValue and get access to
C_GValues in GValue.
Of course you can:
package Glib.Values.My_Stuff is
function Get_C_Values (List : GValues) return C_GValues;
end Glib.Values.My_Stuff;
package body Glib.Values.My_Stuff is
function Get_C_Values (List : GValues) return C_GValues is
begin
return List.Arr;
end Get_C_Values;
end Glib.Values.My_Stuff;
You could perhaps consider using some of the higher-level event handling functions that
are generated as part of the binding. For instance, `gtk-widget.ads` has:
```
type Cb_Gtk_Widget_Gdk_Event_Motion_Boolean is not null access function
(Self : access Gtk_Widget_Record'Class;
Event : Gdk.Event.Gdk_Event_Motion) return Boolean;
type Cb_GObject_Gdk_Event_Motion_Boolean is not null access function
(Self : access Glib.Object.GObject_Record'Class;
Event : Gdk.Event.Gdk_Event_Motion) return Boolean;
Signal_Motion_Notify_Event : constant Glib.Signal_Name := "motion-notify-event";
procedure On_Motion_Notify_Event
(Self : not null access Gtk_Widget_Record;
Call : Cb_Gtk_Widget_Gdk_Event_Motion_Boolean;
After : Boolean := False);
procedure On_Motion_Notify_Event
(Self : not null access Gtk_Widget_Record;
Call : Cb_GObject_Gdk_Event_Motion_Boolean;
Slot : not null access Glib.Object.GObject_Record'Class;
After : Boolean := False);
```
This ensures the proper list of parameters for the callback, and automatically gets you
the Event, for instance.
Le 09/09/2021 à 08:56, Emmanuel Briot a écrit :
You could perhaps consider using some of the higher-level event handling functions that
are generated as part of the binding. For instance, `gtk-widget.ads` has:
```
<SNIPPED>
```
This ensures the proper list of parameters for the callback, and automatically gets you
the Event, for instance.
The problem with these functions is that you can't pass a user record to
the callback.
I'm not as versed in GtkAda, but it looks like those have 'Class types so if it is like most of the other GUI frameworks out there, you typically would extend the type that you are doing the handler for and your user data would be fields of the new record type. Since the handler uses 'Class you could just
cast the parameter to your new type and have access to the user data.
On 2021-09-09 20:41, Jere wrote:Okie dokie! After reading this chain I took a look at the GtkAda manual and saw that they had separate high level events for things like button clicks and such and that they used access to 'Class types so I was hoping that meant
I'm not as versed in GtkAda, but it looks like those have 'Class types so if
it is like most of the other GUI frameworks out there, you typically would extend the type that you are doing the handler for and your user data would be fields of the new record type. Since the handler uses 'Class you could just
cast the parameter to your new type and have access to the user data.
<SNIPPED>
Handlers without user data are non-generic and exist for each event
because GtkAda is generated. So, it is possible to generate a
non-generic handler/connect pair for each of hundreds of events per each widget. This is what Emmanuel suggested:
Cb_GObject_Gdk_Event_Motion_Boolean
But, no user data.
You could not do same and stuff thousands of cases in a single generic handler package! There is only one for all widgets-events.
There is much hatred towards OO design in Ada community which is
possibly was a motive behind this.
An OO design would be to create an abstract base type for each event
with a primitive operation handle the event. The target widget type
would be fixed class-wide, but since it is practically never used, that
is no problem.
type My_Button is new Gtk.Whatever_Path.Button_Type with record
User_Data : User_Data_Type;
end record;
User data is a property of the event not of the button. E.g. consider a button to save file. The user data would be some Ada object responsible
for dealing with the file. What about other buttons? What about
life-times of buttons? User data usually have a longer life span etc.
Okie dokie! After reading this chain I took a look at the GtkAda manual and saw that they had separate high level events for things like button clicks and
such and that they used access to 'Class types so I was hoping that meant
for the OP that they could, for example do something like:
type My_Button is new Gtk.Whatever_Path.Button_Type with record
User_Data : User_Data_Type;
end record;
procedure On_Button_Click(Self : access to Button_Type'Class) is
A_Button : My_Button renames My_Button(Self.all); -- forget if this is allowed or not
begin
-- use A_Button.User_Data.???
end On_Button_Click;
and attach that as the handler. But based on what you said it sounds like this is not
actually an option. (And of course the OP isn't using buttons, but just an example).
GtkAda are much easier to use.User data is a property of the event not of the button. E.g. consider a
button to save file. The user data would be some Ada object responsible
for dealing with the file. What about other buttons? What about
life-times of buttons? User data usually have a longer life span etc.
Presumably you would have one callback procedure to deal with the file, another one to exit the application, another one to ask the user's name and whatever else. For all of these, you do not need user data and the high-level callbacks provided by
One contrived example where user data might be used is for instance: we have one callback responsible for moving the cursor in an editor, and the user data is used to pass UP, DOWN, LEFT or RIGHT to indicate which direction to move. But even in such acase, I would argue it is better to have four small callbacks that call the same shared procedure, and still use the high-level callbacks of GtkAda.
this was my experience based on the GPS source code, which is a relatively extensive GUI application. I don't remember the stats exactly, but there were just a few cases where this approach did not work. And this is why we implemented the higher-leveltype My_Button is new Gtk.Whatever_Path.Button_Type with record
User_Data : User_Data_Type;
end record;
This is indeed the recommended approach. In practice, most widgets have a single callback per event type (so one for motion_notify, one for click, and so on). All that's needed is the `Self` parameter which contains all relevant information. At least
There are a few cases where you want to share the same callback subprogram for multiple events, or multiple types of widgets for instance. In these cases, you might have to fallback to using the generics to connect, along with specifying a user data.As much as possible, I would recommend not using this approach if you can avoid it.
I do not share Dmitry's distrust of generics, but for GUI applications I 100% agree that an OO approach works much better indeed. The performance cost is negligible in such contexts, and the flexibility is much needed.GtkAda are much easier to use.
User data is a property of the event not of the button. E.g. consider a
button to save file. The user data would be some Ada object responsible
for dealing with the file. What about other buttons? What about
life-times of buttons? User data usually have a longer life span etc.
Presumably you would have one callback procedure to deal with the file, another one to exit the application, another one to ask the user's name and whatever else. For all of these, you do not need user data and the high-level callbacks provided by
One contrived example where user data might be used is for instance: we have one callback responsible for moving the cursor in an editor, and the user data is used to pass UP, DOWN, LEFT or RIGHT to indicate which direction to move. But even in such acase, I would argue it is better to have four small callbacks that call the same shared procedure, and still use the high-level callbacks of GtkAda.
I didn't think I can extend the widget type to add my own parameters.
Even more frequent purpose is a composite widget. E.g. consider a text
edit widget with a scroll bar, a menu, some buttons etc. Typically, you
would take some existing widget and derive your widget from there.
In the Initialize you will create all other widgets and pack them into
the widget (if it is a container) or Ref them otherwise. In Gtk_New you
will have custom parameters.
My design is to instantiate Gtk.Handlers.User_Return_Callback (and parameterless handler) with GObject_Record and the user data set to the
tree view. Then I use this handler everywhere without caring what object emits the event. The emitter is irrelevant in 90% of cases.
On 2021-09-10 22:42, DrPi wrote:
I didn't think I can extend the widget type to add my own parameters.
Not only for parameters.
Even more frequent purpose is a composite widget. E.g. consider a text
edit widget with a scroll bar, a menu, some buttons etc. Typically, you
would take some existing widget and derive your widget from there.
In the Initialize you will create all other widgets and pack them into
the widget (if it is a container) or Ref them otherwise. In Gtk_New you
will have custom parameters.
This new widget you could use just as any built-in widget.
Moreover, you can create a new class for your derived widget and add new events, properties and styles for external parametrization etc. TheInteresting.
styles can be set via CSS.
It is a very powerful and versatile mechanism GtkAda offers.
Interesting.
Any pointer on how to use CSS styles ?
Even if I just started using GtkAda, I find it very powerful.
The big problem is documentation. Of course, there are the reference
manual and the (small) user guide but I miss a document explaining the
use of all these functionalities.
DrPi schrieb am Samstag, 11. September 2021 um 17:24:45 UTC+2:
Even if I just started using GtkAda, I find it very powerful.
The big problem is documentation. Of course, there are the reference
manual and the (small) user guide but I miss a document explaining the
use of all these functionalities.
A good introduction into GtkAda is direly needed. Trial and error cost me enormously much time.
The GtkAda UG and RM are a bad joke.
On 2021-09-12 09:08, AdaMagica wrote:I don't fully agree with you.
DrPi schrieb am Samstag, 11. September 2021 um 17:24:45 UTC+2:
Even if I just started using GtkAda, I find it very powerful.
The big problem is documentation. Of course, there are the reference
manual and the (small) user guide but I miss a document explaining the
use of all these functionalities.
A good introduction into GtkAda is direly needed. Trial and error cost me
enormously much time.
The GtkAda UG and RM are a bad joke.
I think you rather mean GTK introduction because GtkAda follows GTK to
the letter.
objects and GObject etc, but that is not required in the beginning. Basically, you know GTK, you know GtkAda.
Regarding GTK introduction, it would require a genius to write that. GTK
is incredibly messy and full of small details you must know before you started. I have no idea how anybody could summarize that in a compact
form. There exist various GTK "getting started." All of them, while describing important things, miss minor details essential to write an
actual application. There seems no such thing as overview in the case of
GTK.
And things are far worse for those who get lured by GLADE. GLADE further obscures what is going on, what has to be done. Be happy you did not
step into that...
Le 12/09/2021 à 10:52, Dmitry A. Kazakov a écrit :
On 2021-09-12 09:08, AdaMagica wrote:I don't fully agree with you.
DrPi schrieb am Samstag, 11. September 2021 um 17:24:45 UTC+2:
Even if I just started using GtkAda, I find it very powerful.
The big problem is documentation. Of course, there are the reference
manual and the (small) user guide but I miss a document explaining the >>>> use of all these functionalities.
A good introduction into GtkAda is direly needed. Trial and error
cost me
enormously much time.
The GtkAda UG and RM are a bad joke.
I think you rather mean GTK introduction because GtkAda follows GTK to
the letter.
I already found Gtk examples I've not been able to use directly with
GtkAda because of Ada implementation. Or at least, it was not the best
way to do things.
Mostly due to the GtkAda OO implementation. Events and
customized widgets are good examples.
I also loose big amount of time searching for how to do things.
I think the the tutorial I've found is a good one to start.
It starts from scratch which is not as easy as one could think it is : a basic application never ends. The main window closes but the exe never
stops. Quite disturbing.
Sysop: | Keyop |
---|---|
Location: | Huddersfield, West Yorkshire, UK |
Users: | 379 |
Nodes: | 16 (2 / 14) |
Uptime: | 44:01:27 |
Calls: | 8,141 |
Calls today: | 4 |
Files: | 13,085 |
Messages: | 5,857,952 |