Jim
Jim

Reputation: 5960

Getting Event Source Pointer from Ada Event Handler Parameters

With GtkAda, I want to identify which radio button was toggled.

The best I have come up with is this not very pretty code, which iterates over all of the buttons to find which ones toggled:

   procedure On_Pgm_Btn_Click
      (Button : access Gtk.Widget.Gtk_Widget_Record'Class) is

     Button_Array : array (Positive range <>) of Gtk_Radio_Button := (Pgm_Bit, Pgm_1, Pgm_2, Pgm_3, Pgm_4);

   begin
     for Index In Button_Array'range loop
        if Button_Array(Index).Get_Active then
           Selected_Program_Button := Button_Array(Index);
           exit; 
        end if;
     end loop;
  end On_Pgm_Btn_Click;   

This is called with this handler connection code:

   Gtkada.Handlers.Widget_Callback.Connect (Pgm_Bit, "toggled", On_Pgm_Btn_Click'Unrestricted_Access);   
   Gtkada.Handlers.Widget_Callback.Connect (Pgm_1, "toggled", On_Pgm_Btn_Click'Unrestricted_Access);   
   Gtkada.Handlers.Widget_Callback.Connect (Pgm_2, "toggled", On_Pgm_Btn_Click'Unrestricted_Access);   
   Gtkada.Handlers.Widget_Callback.Connect (Pgm_3, "toggled", On_Pgm_Btn_Click'Unrestricted_Access);   
   Gtkada.Handlers.Widget_Callback.Connect (Pgm_4, "toggled", On_Pgm_Btn_Click'Unrestricted_Access);   

I can see in the debugger that the value of the parameter Button has the same address as the button that generated the event, but I don't know the conventional way that this parameter is used. It's type is Gtk.Widget.Gtk_Widget_Record'Class, which suggests to me that I might be hacking the code if I did an unchecked conversion to a radio button;

How to I get the Radio Button from the parameter Button?

(Also, if there is a better way to get the state of a radio button group, I would like to know. I haven't been able to find any good examples.)

UPDATE with Solution
From the accepted answer below, I understand that a view conversion is implemented simply like a function call, as shown in the examples of ARM 4.6. The handler became this:

procedure On_Pgm_Btn_Click
  (Button : access Gtk.Widget.Gtk_Widget_Record'Class) is

  This_Button : Gtk_Radio_Button;

begin
  This_Button := Gtk_Radio_Button(Button);
  if This_Button.Get_Active then
     Selected_Program_Button := This_Button;
  end if;
end On_Pgm_Btn_Click;

The types involved are already defined in gtk-radio-button.ads as:

   type Gtk_Radio_Button_Record is new Gtk_Check_Button_Record with null record;
   type Gtk_Radio_Button is access all Gtk_Radio_Button_Record'Class;

and in gtk_widget.ads as:

   type Gtk_Widget_Record is new GObject_Record with null record;
   type Gtk_Widget is access all Gtk_Widget_Record'Class;

so there was no reason to redefine them or use the packages and sample code provided in the accepted answer.

The important line in the modified code is:

This_Button := Gtk_Radio_Button(Button);

which performs the view conversion.

Upvotes: 0

Views: 157

Answers (1)

Simon Wright
Simon Wright

Reputation: 25491

This should be handled by a view conversion (ARM 4.6(5)), not an unchecked conversion.

I don’t have Gtk installed, so I wrote this (after some research at AdaCore’s documentation), which is I believe a self-contained equivalent, and which compiled successfully with GCC 5.1.0.

package View_Conversions is

   type Widget_Record is tagged null record;
   --  Represents Gtk.Widget.Gtk_Widget_Record

   type Button_Record is new Widget_Record with null record;
   type Button is access all Button_Record'Class;
   --  Represents Gtk.Radio_Button.Gtk_Radio_Button

   procedure On_Click (Widget : access Widget_Record'Class);

end View_Conversions;

with body

package body View_Conversions is

   Selected : Button;
   --  Records the selected button

   procedure On_Click (Widget : access Widget_Record'Class) is
   begin

      Selected := Button (Widget);
      --  If the Widget is a Button, save it; if not, raise CE

   end On_Click;

end View_Conversions;

The advantage over unchecked conversion is that this is a checked conversion, and if the passed Widget isn’t in fact a Button you’ll get a Constraint_Error at the point of the conversion.

Upvotes: 1

Related Questions