• GtkAda callback and event

    From DrPi@21:1/5 to All on Sat Sep 4 23:39:29 2021
    Hi,

    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 ?

    Regards,
    Nicolas

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dmitry A. Kazakov@21:1/5 to DrPi on Sun Sep 5 00:29:58 2021
    On 2021-09-04 23:39, DrPi wrote:

    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.

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

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From DrPi@21:1/5 to All on Sun Sep 5 15:50:28 2021
    Le 05/09/2021 à 00:29, Dmitry A. Kazakov a écrit :
    On 2021-09-04 23:39, DrPi wrote:

    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.
    I suppose it doesn't crash because I don't use any callback parameter in
    the callback itself. Just a Put_Line() to check the callback is called.


    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;

    So I have to use a callback with Handler profile, not Simple_Handler
    profile.
    I missed that.

    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)

    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


    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.

    Thanks for the tip.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From DrPi@21:1/5 to All on Sun Sep 5 16:58:57 2021
    Le 05/09/2021 à 16:48, Dmitry A. Kazakov a écrit :
    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 ?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dmitry A. Kazakov@21:1/5 to DrPi on Sun Sep 5 16:48:02 2021
    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;

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

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From DrPi@21:1/5 to All on Sun Sep 5 17:04:15 2021
    Le 05/09/2021 à 16:58, DrPi a écrit :
    Le 05/09/2021 à 16:48, Dmitry A. Kazakov a écrit :
    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 ?
    Like all subprograms accepting C_GValues as a parameter ?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dmitry A. Kazakov@21:1/5 to DrPi on Sun Sep 5 17:12:44 2021
    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 :
    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 ?
    Like all subprograms accepting C_GValues as a parameter ?

    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.

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

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From DrPi@21:1/5 to All on Sun Sep 5 17:20:27 2021
    Le 05/09/2021 à 17:12, Dmitry A. Kazakov a écrit :
    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 :
    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 ?
    Like all subprograms accepting C_GValues as a parameter ?

    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.

    I didn't know I can create a child Package of a GtkAda Package myself.

    Thanks for all these explanations Dmitry.

    Regards,
    Nicolas

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dmitry A. Kazakov@21:1/5 to DrPi on Sun Sep 5 17:53:39 2021
    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 package
    that would have access to the internals of GValue and get access to
    C_GValues in GValue.

    I didn't know I can create a  child Package of a GtkAda Package myself.

    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;

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

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From DrPi@21:1/5 to All on Sun Sep 5 22:49:03 2021
    Le 05/09/2021 à 17:53, Dmitry A. Kazakov a écrit :
    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 package
    that would have access to the internals of GValue and get access to
    C_GValues in GValue.

    I didn't know I can create a  child Package of a GtkAda Package myself.

    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;

    That's what I did after you told me it's possible.

    My first attempt was with an expression function like the following :

    package Glib.Values.User is
    function Get_C_GValues (Val : GValues) return C_GValues is
    (Val.Arr);
    end Glib.Values.User;

    But that didn't work. The compiler complained about something I don't
    remember.
    I then used the classical function implementation and all went well.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Emmanuel Briot@21:1/5 to All on Wed Sep 8 23:56:58 2021
    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.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From DrPi@21:1/5 to All on Thu Sep 9 09:57:29 2021
    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:

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

    The problem with these functions is that you can't pass a user record to
    the callback.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Jere@21:1/5 to DrPi on Thu Sep 9 11:41:50 2021
    On Thursday, September 9, 2021 at 3:57:37 AM UTC-4, DrPi wrote:
    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.

    Otherwise I'm not sure what you mean. The GUI work loop doesn't generally pass user data to a callback, just the event and the listener to the event. All
    user data in most GUI frameworks is handled on the listener side, which is
    why a lot of them rely on type extension of the listener type.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dmitry A. Kazakov@21:1/5 to Jere on Thu Sep 9 21:58:03 2021
    On 2021-09-09 20:41, Jere wrote:

    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.

    The problem is that GtkAda uses generics instead of tagged types. And,
    as I frequently say, generics are lousy.

    Here is the design, very simplified:

    generic
    type Widget_Type is new Glib.Object.GObject_Record with private; -
    type User_Type (<>) is private;
    package User_Callback is
    type Int_Handler is access procedure
    ( Widget : access Widget_Type'Class;
    Param : GInt;
    User_Data : User_Type
    );
    procedure Connect
    ( ...,
    Int_Handler
    ...
    );
    type GUInt_Handler is access procedure
    ( Widget : access Widget_Type'Class;
    Param : GUInt;
    User_Data : User_Type
    );
    procedure Connect
    ( ...,
    Int_Handler
    ...
    );
    ... -- An so on for each parameter type

    In reality it is much messier because handlers are created per generic instances. But you see the problem. For each combination of parameters
    you need a handler type and a connect procedure.

    Furthermore, observe, that this is inherently type unsafe as you could
    attach any handler from a generic instance to any event regardless the parameters of the event.

    Welcome to generics, enjoy.

    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.

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

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Jere@21:1/5 to Dmitry A. Kazakov on Thu Sep 9 14:01:51 2021
    On Thursday, September 9, 2021 at 3:58:06 PM UTC-4, Dmitry A. Kazakov wrote:
    On 2021-09-09 20:41, Jere wrote:

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


    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.

    This is the design I see most often in GUI frameworks (though usually an interface (if you like OO) or a trait object (if you don't care for OO) instead of an abstract class, but about the same). I was hoping the GtkAda
    framework offered this as well so the OP could have something to work with.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Emmanuel Briot@21:1/5 to All on Thu Sep 9 23:56:21 2021
    type 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
    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-level
    approach in GtkAda, where there are no possible errors in the type of parameters for callbacks.

    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.

    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 GtkAda
    are much easier to use.

    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 a
    case, 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.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dmitry A. Kazakov@21:1/5 to Jere on Fri Sep 10 08:38:02 2021
    On 2021-09-09 23:01, 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
    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;

    type My_Button is new Get_Button_Record 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).

    This works perfectly well in GtkAda. Unfortunately is not what is needed
    in most cases.

    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.

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

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dmitry A. Kazakov@21:1/5 to Emmanuel Briot on Fri Sep 10 22:46:45 2021
    On 2021-09-10 08:56, Emmanuel Briot wrote:

    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
    GtkAda are much easier to use.

    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 a
    case, 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.

    These are rather unrealistic examples. For a real example take an
    application with a tree view. There are lots of events you would need to process by the in widget derived from Get_Tree_View.

    Almost none of them will be emitted by the tree view!

    1. The tree view refers/contain other objects like selection. These
    objects emit events, not the tree view.

    2. The buttons, menus etc having effect on the tree view, e.g. a button
    to collapse the tree view. These will emit events for the tree view
    unrelated to it from the GTK point of view.

    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.

    An OO alternative to Gtk.Handlers.User_Callback would be for example,
    taking Button for simplicity:

    type Gtk_Button_Record is new Gtk_Bin_Record with null record;
    type Gtk_Button is access all Gtk_Button_Record'Class;

    ...

    type Button_Void_Handler is limited interface;
    procedure Handle
    ( Handler : in out Button_Void_Handler ;
    Button : access Gtk_Button_Record'Class
    ) is abstract;

    procedure On_Clicked
    ( Self : not null access Gtk_Button_Record;
    Handler : not null access Button_Void_Handler'Class;
    After : Boolean := False
    );
    procedure On_Enter
    ( Self : not null access Gtk_Button_Record;
    Handler : not null access Button_Void_Handler'Class;
    After : Boolean := False
    );
    ...

    This is type-safe and can be generated the way On_Clicked with Cb_Gtk_Button_Void is generated.

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

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From DrPi@21:1/5 to All on Fri Sep 10 22:42:19 2021
    Le 10/09/2021 à 08:56, Emmanuel Briot a écrit :
    type 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
    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-level
    approach in GtkAda, where there are no possible errors in the type of parameters for callbacks.

    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.

    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
    GtkAda are much easier to use.

    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 a
    case, 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.


    That's very interesting.
    I didn't think I can extend the widget type to add my own parameters.
    Thanks all for your help.

    Nicolas

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dmitry A. Kazakov@21:1/5 to DrPi on Fri Sep 10 22:58:06 2021
    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. The
    styles can be set via CSS.

    It is a very powerful and versatile mechanism GtkAda offers.

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

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Emmanuel Briot@21:1/5 to All on Sat Sep 11 00:38:07 2021
    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.

    I agree this is exactly the right design and the way we intended GtkAda to be used (supporting this was not completely trivial at first, though later versions of gtk+
    made that simpler).

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Emmanuel Briot@21:1/5 to All on Sat Sep 11 00:36:20 2021
    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.

    I haven't done any GtkAda in almost five years now, so I had a bit forgotten. The scenario you describe would be something like:
    - click on the [expand] button to expand the currently selected node in a tree view.

    To implement this, I would have a function that "expends current node" and receive
    a tree view widget.

    I would then connect the button `click` callback to that function, using the `Slot`
    parameter of the high-level callbacks, rather than the user_data.

    In most cases, you do not need access to the button itself. Using user_data is really
    when you need both the widget and additional information. Here the callback only needs
    access to one widget (The tree view), so using Slot is definitely easier. And will properly
    manage the life time of the widget, too, which might not be trivial to do with a user
    callback (need to call Ref and Unref).

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From DrPi@21:1/5 to All on Sat Sep 11 17:24:41 2021
    Le 10/09/2021 à 22:58, Dmitry A. Kazakov a écrit :
    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.

    I already do this.
    I don't know why I didn't think to apply this to my own parameters.


    Moreover, you can create a new class for your derived widget and add new events, properties and styles for external parametrization etc. The
    styles can be set via CSS.
    Interesting.
    Any pointer on how to use CSS styles ?


    It is a very powerful and versatile mechanism GtkAda offers.


    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.
    I found a tutorial in French which is very helpful for starting but it
    is outdated.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dmitry A. Kazakov@21:1/5 to DrPi on Sat Sep 11 17:56:02 2021
    On 2021-09-11 17:24, DrPi wrote:

    Interesting.
    Any pointer on how to use CSS styles ?

    This is GTK documentation of CSS:

    https://docs.gtk.org/gtk3/css-overview.html

    Here is an example of a custom button that uses CSS for label, icon,
    tool tip etc.


    http://www.dmitry-kazakov.de/ada/gtkada_contributions.htm#Gtk.Generic_Style_Button

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

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From AdaMagica@21:1/5 to DrPi on Sun Sep 12 00:08:59 2021
    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.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dmitry A. Kazakov@21:1/5 to AdaMagica on Sun Sep 12 10:52:34 2021
    On 2021-09-12 09:08, AdaMagica wrote:
    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. There are few advanced topics of interplay between GtkAda
    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...

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

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From DrPi@21:1/5 to All on Sun Sep 12 15:00:52 2021
    Le 12/09/2021 à 10:52, Dmitry A. Kazakov a écrit :
    On 2021-09-12 09:08, AdaMagica wrote:
    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 don't fully agree with you.
    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.


    There are few advanced topics of interplay between GtkAda
    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.

    They may be not perfect but they have the merit to exist.

    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.
    When you create a basic GtkAda project with GPS, you get an application
    with such a behavior. At first, I thought I did something wrong when
    installing GtkAda. I then found the tutorial and discovered this
    behavior is the correct one.


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

    I tried Glade once and quickly changed my mind. I don't say it's a bad
    tool. Just that, like you said, things are more obscure using it. As I
    like to understand what I do, this is not the way to go for me right now.
    I did the same thing with WxPython. I learned to construct my GUI programmatically. Then, when I've been comfortable with it I switched to wxFormBuilder for some of my projects.



    URL to the French tutorial I use : https://zestedesavoir.com/tutoriels/645/apprenez-a-programmer-avec-ada/555_ada-et-gtk-la-programmation-evenementielle/2676_gtkada-introduction-et-installation/

    One problem with this tutorial is that it is outdated.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dmitry A. Kazakov@21:1/5 to DrPi on Sun Sep 12 15:57:55 2021
    On 2021-09-12 15:00, DrPi wrote:
    Le 12/09/2021 à 10:52, Dmitry A. Kazakov a écrit :
    On 2021-09-12 09:08, AdaMagica wrote:
    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 don't fully agree with you.
    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.

    Well, you are supposed to use GValues in GTK. GtkAda just makes life
    much easier for you by adding a typed layer to connect and handle the
    events. How it works is well explained in the documentation. E.g.

    https://docs.adacore.com/live/wave/gtkada/html/gtkada_ug/signals.html

    The problem is that you started with that, skipped reading for later
    because it was too much reading. If you had started the GTK's way first,
    namely with GValues, then after pulling much hairs, read the stuff more carefully, then you would rather say, "Aha, that is a much better way to
    do this. Thanks."

    Mostly due to the GtkAda OO implementation. Events and
    customized widgets are good examples.

    Right, because when you begin with GtkAda with no prior knowledge of
    GTK, you are at a complete loss.

    Luckily, you do not yet understand how deep is the abyss! (:-))

    I also loose big amount of time searching for how to do things.

    Because GTK is a mess. Nobody ever knows how to do this or that in GTK.
    I keep the GTK sources at hand to consult to just to understand what is
    going on. [ It was a lot easier a decade ago, when Google was a search
    engine and GTK topics were not spammed into oblivion by Python and C#
    garbage sites. ]

    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.

    Then the tutorial is broken. If you look at GtkAda samples and tests
    they all contain the basic GTK frame with On_Delete_Event and On_Destroy.

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

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)