• On_Button_Press_Event in Text_View

    From Gavin McCord@gavind.mccord@gmail.com to comp.lang.ada on Tue Aug 13 11:37:09 2024
    From Newsgroup: comp.lang.ada

    Using gtkada (gtk3), is it possible to use a custom handler to
    deal with a button-press-event (or other events if necessary)
    inside a widget such as a Text_View?

    For example I create a Text_View with buffer. To process a
    button-press within that view I have this code in my main
    procedure:

    The_View.On_Button_Press_Event (Press_CB'Access);
    The_View.Set_Events (The_View.Get_Events or Button_Press_Mask);

    The callback looks like this:

    function Press_CB (Self : access Gtk_Widget_Record'Class;
    Event : Gdk_Event_Button)
    return Boolean is
    begin
    Put_Line ("Mouse click in text view");
    return True;
    end Press_CB;

    So far, so good.

    But I'd like to pass additional data to the callback,
    without using global variables/records if it can be
    avoided.

    I have a custom handler used when I update the Text_Buffer:

    Button_Callback.Connect
    (Update_Button, "clicked", Update_Clicked'Access,
    Buffer_To_Pass);

    That works fine so I was imagining something similar might
    be possible, but I've run through various permuations of
    records and access types but not yet got a working callback.

    Any help gratefully received (I can post the full code if
    that's useful).

    Kind regards,

    Gavin McCord
    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Dmitry A. Kazakov@mailbox@dmitry-kazakov.de to comp.lang.ada on Tue Aug 13 22:29:59 2024
    From Newsgroup: comp.lang.ada

    On 2024-08-13 13:37, Gavin McCord wrote:

    I have a custom handler used when I update the Text_Buffer:

    Button_Callback.Connect
    (Update_Button, "clicked", Update_Clicked'Access,
    Buffer_To_Pass);

    That works fine so I was imagining something similar might
    be possible, but I've run through various permuations of
    records and access types but not yet got a working callback.

    Any help gratefully received (I can post the full code if
    that's useful).

    Something like this:

    package Event_Handlers is
    new Gtk.Handlers.User_Return_Callback
    ( GObject_Record,
    Boolean,
    User_Data_Type
    );


    function On_Button_Press
    ( Object : access GObject_Record'Class;
    Event : Gdk_Event;
    Data : User_Data_Type
    ) return Boolean;


    View.Set_Events (View.Get_Events or Button_Press_Mask);
    Event_Handlers.Connect
    ( View,
    "button-press-event",
    Event_Handlers.To_Marshaller (On_Button_Press'Access),
    Data
    );
    --
    Regards,
    Dmitry A. Kazakov
    http://www.dmitry-kazakov.de

    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Gavin McCord@gavind.mccord@gmail.com to comp.lang.ada on Wed Aug 14 11:42:14 2024
    From Newsgroup: comp.lang.ada

    On Tue, 13 Aug 2024 22:29:59 +0200, Dmitry A. Kazakov wrote:

    On 2024-08-13 13:37, Gavin McCord wrote:

    I have a custom handler used when I update the Text_Buffer:

    Button_Callback.Connect
    (Update_Button, "clicked", Update_Clicked'Access,
    Buffer_To_Pass);

    That works fine so I was imagining something similar might be possible,
    but I've run through various permuations of records and access types
    but not yet got a working callback.

    Any help gratefully received (I can post the full code if that's
    useful).

    Something like this:

    package Event_Handlers is
    new Gtk.Handlers.User_Return_Callback
    ( GObject_Record,
    Boolean, User_Data_Type
    );


    function On_Button_Press
    ( Object : access GObject_Record'Class;
    Event : Gdk_Event; Data : User_Data_Type
    ) return Boolean;


    View.Set_Events (View.Get_Events or Button_Press_Mask);
    Event_Handlers.Connect ( View,
    "button-press-event",
    Event_Handlers.To_Marshaller (On_Button_Press'Access),
    Data
    );

    Thank you. That allows me to pass a record of the buffer.

    There's only one other thing.

    If I try to check the Event I get another error, such as

    function On_Button_Press
    [skipped lines]

    if Event.The_Type = Gdk_2button_Press then
    Put_Line ("double-click");
    end if;

    Attempting to compile that gives me

    error: cannot reference discriminant of unchecked union


    Gavin McCord
    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Dmitry A. Kazakov@mailbox@dmitry-kazakov.de to comp.lang.ada on Wed Aug 14 14:03:24 2024
    From Newsgroup: comp.lang.ada

    On 2024-08-14 13:42, Gavin McCord wrote:
    On Tue, 13 Aug 2024 22:29:59 +0200, Dmitry A. Kazakov wrote:

    On 2024-08-13 13:37, Gavin McCord wrote:

    I have a custom handler used when I update the Text_Buffer:

    Button_Callback.Connect
    (Update_Button, "clicked", Update_Clicked'Access,
    Buffer_To_Pass);

    That works fine so I was imagining something similar might be possible,
    but I've run through various permuations of records and access types
    but not yet got a working callback.

    Any help gratefully received (I can post the full code if that's
    useful).

    Something like this:

    package Event_Handlers is
    new Gtk.Handlers.User_Return_Callback
    ( GObject_Record,
    Boolean, User_Data_Type
    );


    function On_Button_Press
    ( Object : access GObject_Record'Class;
    Event : Gdk_Event; Data : User_Data_Type
    ) return Boolean;


    View.Set_Events (View.Get_Events or Button_Press_Mask);
    Event_Handlers.Connect ( View,
    "button-press-event",
    Event_Handlers.To_Marshaller (On_Button_Press'Access),
    Data
    );

    Thank you. That allows me to pass a record of the buffer.

    As a general advice. Usually you have a custom widget derived from Gtk_Grid_Record servicing as the main window.

    type Main_Window_Record is new Gtk_Grid_Record with record
    Button : Gtk_Button;
    Text_View : Gtk_Text_View;
    Buffer : Gtk_Text_Buffer;
    ...
    type Main_Window is access all Main_Window_Record'Class;

    Main_Window you pass to all handlers, so that you always have a full
    context in any of them.

    There's only one other thing.

    If I try to check the Event I get another error, such as

    function On_Button_Press
    [skipped lines]

    if Event.The_Type = Gdk_2button_Press then
    Put_Line ("double-click");
    end if;

    Attempting to compile that gives me

    error: cannot reference discriminant of unchecked union

    case Get_Event_Type (Event) is
    when Button_Press =>
    ...
    when Gdk_2Button_Press | Gdk_3Button_Press =>
    ...
    when Key_Press =>
    case Get_Key_Val (Event) is
    when GDK_Up | GDK_KP_Up =>
    ...
    when GDK_Down | GDK_KP_Down =>
    ...
    end case;
    ...
    when others =>
    ...
    end case;
    --
    Regards,
    Dmitry A. Kazakov
    http://www.dmitry-kazakov.de

    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Gavin McCord@gavind.mccord@gmail.com to comp.lang.ada on Wed Aug 14 14:34:13 2024
    From Newsgroup: comp.lang.ada

    On Wed, 14 Aug 2024 14:03:24 +0200, Dmitry A. Kazakov wrote:

    On 2024-08-14 13:42, Gavin McCord wrote:
    On Tue, 13 Aug 2024 22:29:59 +0200, Dmitry A. Kazakov wrote:

    On 2024-08-13 13:37, Gavin McCord wrote:

    I have a custom handler used when I update the Text_Buffer:

    Button_Callback.Connect
    (Update_Button, "clicked", Update_Clicked'Access,
    Buffer_To_Pass);

    That works fine so I was imagining something similar might be
    possible,
    but I've run through various permuations of records and access types
    but not yet got a working callback.

    Any help gratefully received (I can post the full code if that's
    useful).

    Something like this:

    package Event_Handlers is
    new Gtk.Handlers.User_Return_Callback
    ( GObject_Record,
    Boolean, User_Data_Type
    );


    function On_Button_Press
    ( Object : access GObject_Record'Class;
    Event : Gdk_Event; Data : User_Data_Type
    ) return Boolean;


    View.Set_Events (View.Get_Events or Button_Press_Mask);
    Event_Handlers.Connect ( View,
    "button-press-event",
    Event_Handlers.To_Marshaller (On_Button_Press'Access),
    Data
    );

    Thank you. That allows me to pass a record of the buffer.

    As a general advice. Usually you have a custom widget derived from Gtk_Grid_Record servicing as the main window.

    type Main_Window_Record is new Gtk_Grid_Record with record
    Button : Gtk_Button;
    Text_View : Gtk_Text_View;
    Buffer : Gtk_Text_Buffer;
    ...
    type Main_Window is access all Main_Window_Record'Class;

    Main_Window you pass to all handlers, so that you always have a full
    context in any of them.

    There's only one other thing.

    If I try to check the Event I get another error, such as

    function On_Button_Press [skipped lines]

    if Event.The_Type = Gdk_2button_Press then
    Put_Line ("double-click");
    end if;

    Attempting to compile that gives me

    error: cannot reference discriminant of unchecked union

    case Get_Event_Type (Event) is
    when Button_Press =>
    ...
    when Gdk_2Button_Press | Gdk_3Button_Press =>
    ...
    when Key_Press =>
    case Get_Key_Val (Event) is
    when GDK_Up | GDK_KP_Up =>
    ...
    when GDK_Down | GDK_KP_Down =>
    ...
    end case;
    ...
    when others =>
    ...
    end case;

    I've got it working now. Get_Event_Type (Event) is what I needed.

    Thank you again for all your help.

    Gavin
    --- Synchronet 3.20a-Linux NewsLink 1.114