1

I can't make my callback function work. I have created a button which when clicked removes the first button and displays the second button. When I click the button, it removes the first button but does not show the second button. here is the complete code:

File.ads

With Gtk.Widget;         Use Gtk.Widget;
With Gtk.Main;           Use Gtk.Main;
With Gtk.Window;         Use Gtk.Window;
With Gtk.Button;         Use Gtk.Button;
With Gtk.Table;          Use Gtk.Table;
With Gtk.Handlers;       Use Gtk.Handlers;

Package File is
   Type T_Test_Record is record

      Table : Gtk_Table;
      Button_2 : Gtk_Button;

   end record;

   Type T_Test is access T_Test_Record;

   Procedure Init_Button ( Self : access Gtk_Widget_Record'Class; Button : T_Test);
   --   Callback for create the second button

   Procedure Init_Table ( Table : access T_Test_Record );
   --   Initialize the table.

   Procedure Exit_Window (Self : access Gtk_Widget_Record'Class);
   --   Stop Gtk.Main.Main loop when wen close the window.

   Package P is new Gtk.handlers.User_Callback (Gtk_Widget_Record,T_Test);
   Use P;

   Package P2 is new Gtk.Handlers.Callback (Gtk_Window_Record);
   Use P2;

end File;

File.adb

With Gtk.Widget;  Use Gtk.Widget;
With Gtk.Table;   Use Gtk.Table;
With Gtk.Button;  Use Gtk.Button;

Package body File is

   Procedure Init_Table (Table : access T_Test_Record ) is
   begin

      Gtk_New (Table.Table,0,0,False);

   end Init_Table;

   Procedure Init_Button (Self : access Gtk_Widget_Record'Class;
                          Button : T_Test) is
  
   begin
      Self.Destroy;

      Init_Table (Button);

      Gtk_New (Button.Button_2);
      
      Button.Button_2.Set_Label ("Bouton 2");

      Button.Table.Add (Button.Button_2);
   end Init_Button;

   Procedure Exit_Window (Self : access Gtk_Widget_Record'Class) is
   begin
      Gtk.Main.Main_Quit;

   end Exit_Window;
end File;

Main.adb

With Gtk.Main;         Use Gtk.Main;
With Gtk.Enums;        Use Gtk.Enums;
With Gtk.Button;       Use Gtk.Button;
With Gtk.Window;       Use Gtk.Window;
With Gtk.Grid;         Use Gtk.Grid;
With test2;            Use Test2;

Procedure Main is

   Win : Gtk_Window;
   Button : Gtk_Button;
   Test : T_Test;
begin
   Init;
   Test := New T_Test_Record;

   Init_Table (Test);

   --   Initialize the window
   
   Gtk_New (Win);
   Win.Set_Default_Size (600,400);

   Win.On_Destroy (test2.Exit_Window'Access);
   
   --   Initialize the Button

   Gtk_New (Button,"Bouton 1");
   
   --   Add the Table in the window

   Win.Add (Test.Table);

   --   Add button in the table
   
   Test.Table.Add (Button);
   
   --   Connect the calllback in the button

   Test2.P.Connect (Widget    => Button,
                    Name      => Signal_Clicked,
                    Marsh     => Test2.P.To_Marshaller (Init_Button'Access),
                    User_Data => Test,
                    After     => False);

   --   Show the window
   
   Win.Show_All;
   Gtk.Main.Main;
end Main;

How can I make my callback function show the second button?

BobMorane
  • 3,870
  • 3
  • 20
  • 42

1 Answers1

2

To toggle the visibility of a widget, you can use the Show and Hide procedures (or Set_Visibility procedure as used in an earlier example). Here's an annotated example:

app.ads

package App is

end App;

app-main_window.ads

with Gtk.Window; use Gtk.Window;
with Gtk.Grid;   use Gtk.Grid;
with Gtk.Button; use Gtk.Button;
with Gtk.Frame;  use Gtk.Frame;

package App.Main_Window is

   type App_Main_Window_Record is new Gtk_Window_Record with private;
   type App_Main_Window is access all App_Main_Window_Record'Class;

   ------------------
   -- Constructors --
   ------------------

   procedure Gtk_New
     (Main_Window : out App_Main_Window);
   procedure Initialize
     (Main_Window : not null access App_Main_Window_Record'Class);

private
   
   Window_Width  : constant := 300;
   Window_Height : constant := 100;     
   
   type App_Main_Window_Record is
     new Gtk.Window.Gtk_Window_Record with
      record
         Grid     : Gtk_Grid;  
         Frame_1  : Gtk_Frame;
         Frame_2  : Gtk_Frame;
         Button_1 : Gtk_Button;         
         Button_2 : Gtk_Button;
      end record;

end App.Main_Window;

app-main_window.adb

with Gtk.Main;
with Gtk.Widget;
with Gtk.Window;
with Gdk.Event;

package body App.Main_Window is

   procedure Destroy_Event_Callback
     (Widget : access Gtk.Widget.Gtk_Widget_Record'Class);

   function On_Button_1_Pressed_Callback
     (Self  : access Gtk.Widget.Gtk_Widget_Record'Class;
      Event : Gdk.Event.Gdk_Event_Button) return Boolean;
   
   function On_Button_2_Pressed_Callback
     (Self  : access Gtk.Widget.Gtk_Widget_Record'Class;
      Event : Gdk.Event.Gdk_Event_Button) return Boolean;

   -------------
   -- Gtk_New --
   -------------

   procedure Gtk_New (Main_Window : out App_Main_Window) is
   begin
      Main_Window := new App_Main_Window_Record;
      App.Main_Window.Initialize (Main_Window);
   end Gtk_New;

   ----------------
   -- Initialize --
   ----------------

   procedure Initialize
     (Main_Window : not null access App_Main_Window_Record'Class)
   is
   begin

      --  Initialize and setup the window.
      Gtk.Window.Initialize (Main_Window);
      
      Main_Window.Set_Title ("Demo Window");
      Main_Window.Set_Size_Request (Window_Width, Window_Height);
      Main_Window.Set_Resizable (False);

      --  Attach callback: properly end the GTK application when requested.
      Main_Window.On_Destroy
        (Call => Destroy_Event_Callback'Access);

      --  Add a grid.
      Gtk_New (Main_Window.Grid);      
      Main_Window.Grid.Set_Hexpand (True);
      Main_Window.Grid.Set_Vexpand (True);
      Main_Window.Grid.Set_Column_Homogeneous (True);
      Main_Window.Grid.Set_Row_Homogeneous (True);
      
      Main_Window.Add (Main_Window.Grid);
      
      --  Create two frames and two buttons. The frames are needed to
      --  ensure that the position and size are retrained if either buttons
      --  are hidden (layout containers like grid and box recompute the
      --  expansions when the visibility of their child wigeds change).
      --
      --  The object hierchy is as follows:
      --
      --     +------------------------+
      --     |         Window         |
      --     +-----------+------------+
      --                 |
      --     +-----------+------------+
      --     |          Grid          |
      --     |  (0,0)         (1,0)   |
      --     +----+-------------+-----+
      --          |             |
      --     +----+-----+  +----+-----+
      --     | Frame_1  |  | Frame_2  |
      --     +----+-----+  +----+-----+
      --          |             |
      --     +----+-----+  +----+-----+
      --     | Button_1 |  | Button_2 |
      --     +----------+  +----------+      
      
      Gtk_New (Main_Window.Frame_1);
      Gtk_New (Main_Window.Frame_2);
      
      Gtk_New (Main_Window.Button_1, Label => "Button 1");
      Gtk_New (Main_Window.Button_2, Label => "Button 2");
      
      --  Add the buttons to their respective frame.
      Main_Window.Frame_1.Add (Main_Window.Button_1);
      Main_Window.Frame_2.Add (Main_Window.Button_2);
            
      --  Insert both frames into the grid.      
      Main_Window.Grid.Attach
        (Child => Main_Window.Frame_1,
         Left  => 0,
         Top   => 0);
      
      Main_Window.Grid.Attach
        (Child => Main_Window.Frame_2,
         Left  => 1,
         Top   => 0);
      
      --  Attach "button pressed" callbacks.
      Main_Window.Button_1.On_Button_Press_Event
        (Call => On_Button_1_Pressed_Callback'Access);
      Main_Window.Button_2.On_Button_Press_Event
        (Call => On_Button_2_Pressed_Callback'Access);      
      
      --  Show everything ...
      Main_Window.Show_All;
      
      --  ... and then hide button 2 initially.
      Main_Window.Button_2.Hide;

   end Initialize;

   ----------------------------
   -- Destroy_Event_Callback --
   ----------------------------

   procedure Destroy_Event_Callback
     (Widget : access Gtk.Widget.Gtk_Widget_Record'Class)
   is
   begin
      Gtk.Main.Main_Quit;
   end Destroy_Event_Callback;

   ----------------------------------
   -- On_Button_1_Pressed_Callback --
   ----------------------------------

   function On_Button_1_Pressed_Callback
     (Self  : access Gtk.Widget.Gtk_Widget_Record'Class;
      Event : Gdk.Event.Gdk_Event_Button) return Boolean
   is
      --                (parent)       (parent)      (parent)
      --  Button (Self) -------> Frame -------> Grid -------> Window
      
      Frame  : Gtk_Frame := Gtk_Frame (Self.Get_Parent);
      Grid   : Gtk_Grid := Gtk_Grid (Frame.Get_Parent);
      Window : App_Main_Window := App_Main_Window (Grid.Get_Parent);
      
   begin
      --  Just toggle visibility.      
      Window.Button_1.Hide;
      Window.Button_2.Show;
      return True;   --  GDK_EVENT_STOP, do not propagate event to parent.

   end On_Button_1_Pressed_Callback;

   ----------------------------------
   -- On_Button_2_Pressed_Callback --
   ----------------------------------

   function On_Button_2_Pressed_Callback
     (Self  : access Gtk.Widget.Gtk_Widget_Record'Class;
      Event : Gdk.Event.Gdk_Event_Button) return Boolean
   is
      Frame  : Gtk_Frame := Gtk_Frame (Self.Get_Parent);
      Grid   : Gtk_Grid := Gtk_Grid (Frame.Get_Parent);
      Window : App_Main_Window := App_Main_Window (Grid.Get_Parent);

   begin
      Window.Button_1.Show;
      Window.Button_2.Hide;
      return True;   --  GDK_EVENT_STOP, do not propagate event to parent.

   end On_Button_2_Pressed_Callback;   
   
end App.Main_Window;

main.adb

with Gtk.Main;
with App.Main_Window;

procedure Main is
   use App.Main_Window;
   Main_Window : App_Main_Window;
begin
   Gtk.Main.Init;
   Gtk_New (Main_Window);
   Gtk.Main.Main;
end Main;
DeeDee
  • 5,654
  • 7
  • 14