When creating an application, you'll want to put more than one widget inside a window. Our first helloworld example only used one widget so we could simply use Add call to "pack" the widget into the window. But when you want to put more than one widget into a window, it it becomes important to control how each widget is positioned and sized. This is where packing comes in.
GtkAda comes with a large variety of layout containers whose purpose it is to control the layout of the child widgets that are added to them. You could see the Gtk+ Layout Containers for an overview. GtkAda has all the containers and normally has the form of Gtk_<Container_Name>
The following example shows how the Gtk_Grid container lets you arrange several buttons. It follows the same directory structure in the helloworld example.
with Gtk.Main; with Gtk.Window; use Gtk.Window; with Gtk.Grid; use Gtk.Grid; with Gtk.Button; use Gtk.Button; with Gtkada.Handlers; use Gtkada.Handlers; with grid_cb; use grid_cb; procedure Grid is Win : Gtk_Window; Grid : Gtk_Grid; Button : Gtk_Button; begin -- Initialize GtkAda. Gtk.Main.Init; -- create a top level window Gtk_New (Win); Win.Set_Title ("Grid"); -- set the border width of the window Win.Set_Border_Width (10); -- connect the "destroy" signal Win.On_Destroy (main_quit'Access); -- Here we construct the container that is going pack our buttons Gtk_New (Grid); -- Packed the container in the Window Win.Add (Grid); -- create a button with label Gtk_New (Button, "Button 1"); -- connect the click signal Button.On_Clicked (button_clicked'Access); -- Place the first button in the grid cell (0, 0), and make it fill -- just 1 cell horizontally and vertically (ie no spanning) Grid.Attach (Button, 0, 0, 1, 1); -- create another button with label Gtk_New (Button, "Button 2"); Button.On_Clicked (button_clicked'Access); -- Place the second button in the grid cell (1, 0), and make it fill -- just 1 cell horizontally and vertically (ie no spanning) Grid.Attach (Button, 1, 0, 1, 1); -- create the quit button Gtk_New (Button, "Quit"); -- connect the "clicked" signal of the button to destroy function Widget_Callback.Object_Connect (Button, "clicked", Widget_Callback.To_Marshaller (button_quit'Access), Win); -- Place the Quit button in the grid cell (0, 1), and make it -- span 2 columns. Grid.Attach (Button, 0, 1, 2, 1); -- Now that we are done packing our widgets, we show them all -- in one go, by calling Win.Show_All. -- This call recursively calls Show on all widgets -- that are contained in the window, directly or indirectly. Win.Show_All; -- All GTK applications must have a Gtk.Main.Main. Control ends here -- and waits for an event to occur (like a key press or a mouse event), -- until Gtk.Main.Main_Quit is called. Gtk.Main.Main; end Grid;src/grid_cb.ads:
with Gtk.Widget; use Gtk.Widget; with Gtk.Button; use Gtk.Button; with Glib.Object; with Gdk.Event; package grid_cb is function main_del (Self : access Gtk_Widget_Record'Class; Event : Gdk.Event.Gdk_Event) return Boolean; procedure main_quit (Self : access Gtk_Widget_Record'Class); procedure button_clicked (Self : access Gtk_Button_Record'Class); procedure button_quit (Self : access Gtk_Widget_Record'Class); end grid_cb;src/grid_cb.adb:
with Ada.Text_IO; use Ada.Text_IO; with Gtk.Main; package body grid_cb is -- If you return false in the "delete_event" signal handler, -- GTK will emit the "destroy" signal. Returning true means -- you don't want the window to be destroyed. -- -- This is useful for popping up 'are you sure you want to quit?' -- type dialogs. function main_del (Self : access Gtk_Widget_Record'Class; Event : Gdk.Event.Gdk_Event) return Boolean is begin Put_Line ("Delete event encounter."); return True; end main_del; procedure main_quit (Self : access Gtk_Widget_Record'Class) is begin Gtk.Main.Main_Quit; end main_quit; procedure button_clicked (Self : access Gtk_Button_Record'Class) is begin Put_Line ("Hello clicked"); end button_clicked; procedure button_quit (Self : access Gtk_Widget_Record'Class) is begin Put_Line ("buttion_quit is called"); Destroy (Self); end button_quit; end grid_cb;grid.gpr
with "gtkada"; project Grid is for Source_Dirs use ("src"); for Object_Dir use "obj"; for Main use ("grid.adb"); -- Enable Ada 2005. package Compiler is for Default_Switches ("ada") use ("-gnat05"); end Compiler; end GridTo compile the program:
gprbuild -P grid
You may notice the callback functions are exactly the same as helloworld, you could reuse it by just rename the packages or simple using the same hello_cb package and in grid.adb with and use it with hello_cb; use hello_cb;, then you don't need to change anything on the call backs.