[gtkada] GtkAda signal handlers interface proposal

Dmitry A. Kazakov mailbox at dmitry-kazakov.de
Wed Apr 27 21:48:35 CEST 2016


The use case is a widget (or GObject) handling signals from other 
widgets, usually its children. Presently this requires instantiation of 
a Gtk.Handlers.* package because it requires passing the widget as a 
signal parameter. This quite difficult to get right, especially the 
Connect call.

The proposal is to have a method similar to already provided 
parameterless handlers. As an example let's take Gkt.Button. It has 
On_Clicked declared as a primitive operation.

    procedure On_Clicked
       (Self  : not null access Gtk_Button_Record;
        Call  : Cb_Gtk_Button_Void;
        After : Boolean := False);

Here the handler procedure is Cb_Gtk_Button_Void:

    type Cb_Gtk_Button_Void is not null access
       procedure (Self : access Gtk_Button_Record'Class);

Now the package Gtk.Button will also have an interface declaration:

    type Clicked_Handler is interface;
    procedure On_Clicked
              (  Emitter : not null access Gtk_Button_Record'Class;
                        -- Additional signal-specific parameters go here
                 Handler : not null access Clicked_Handler
              )  is abstract;

The Gtk_Button_Record type will get yet another primitive operation

    procedure Handle_Clicked
              (  Self    : not null access Gtk_Button_Record;
                 Handler : not null access Clicked_Handler'Class;
                 After   : Boolean := False
              );

Since GtkAda is generated, it should be relatively easy to do. The 
implementation of Handle_Clicked is straightforward. Gtk.Button will 
have an instance Gtk.Handlers.User_Callback with

    type Clicked_Handler_Ptr is access all Clicked_Handler'Class;

 From the procedure called on signal it will dispatch to On_Clicked.

The client code will look like this:

    type My_Widget_Record is new Gtk.Grid.Gtk_Grid_Record
                             and Clicked_Handler with
    record
       Button1 : Gtk_Button;
       Button2 : Gtk_Button;
       ...
    end record;
    overriding
       procedure On_Clicked
                 (  Emitter : not null access Gtk_Button_Record'Class;
                    Widget  : not null access My_Widget_Record
                 );

Connecting signals in Initialize:

    procedure Initialize
              (  Widget : not null access My_Widget_Record'Class
              )  is
    begin
       ...
       Widget.Button1.Handle_Clicked (Widget);
       Widget.Button2.Handle_Clicked (Widget);
    end Initialize;

The handler:

    procedure On_Clicked
              (  Emitter : not null access Gtk_Button_Record'Class;
                 Widget  : not null access My_Widget_Record
              )  is
    begin
       if Emitter = Widget.Button1 then
          ... -- This is from Button1
       elsif Emitter = Widget.Button2 then
          ... -- This is from Button2
       end if;
    end On_Clicked;

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

-------------- next part --------------
An HTML attachment was scrubbed...
URL: </pipermail/gtkada/attachments/20160427/ce852c08/attachment.html>


More information about the gtkada mailing list