[gtkada] Contribution: using GtkAda from Ada tasks

Dmitry A. Kazakov mailbox at dmitry-kazakov.de
Mon Jul 17 09:51:02 CEST 2006


On Sun, 16 Jul 2006 17:00:40 -0700, you wrote:

> Dmitry A. Kazakov wrote:
> 
>>To whom interest. This package (see attachment) provides a simple
>>synchronization mechanism to use GtkAda with Ada tasks. No locking is used,
>>instead GTK+ requests are executed on the context of the main thread. The
>>package works both under Windows and Linux. It was tested with GtkAda
>>2.4.0.
>>  
> Would it be possible to provide a small example?

with Ada.Exceptions;   use Ada.Exceptions;
with Gdk.Event;        use Gdk.Event;
with Gtk.Main.Router;  use Gtk.Main.Router; 
with Gtk.Window;       use Gtk.Window;
with Gtk.Widget;       use Gtk.Widget;
with Gtk.Table;        use Gtk.Table;
with Gtk.Label;        use Gtk.Label;

with Ada.Unchecked_Conversion;
with Gtk.Handlers;

procedure Test_Gtk is
   --
   -- All data are global, for the sake of  simplicity.  Otherwise,  the
   -- test were impossible to keep in  just  one  body  due  to  Ada  95
   -- restriction on controlled types. 
   --
   Window  : Gtk_Window;
   Grid    : Gtk_Table;
   Label   : Gtk_Label;
   Counter : Integer;
   
   -- Standard GTK stuff
   package Handlers is new Gtk.Handlers.Callback (Gtk_Widget_Record);

   package Return_Handlers is
      new Gtk.Handlers.Return_Callback
          (  Widget_Type => Gtk_Widget_Record,
             Return_Type => Boolean
          );
   function Delete_Event
            (  Widget : access Gtk_Widget_Record'Class;
               Event  : Gdk_Event
            )  return Boolean is
   begin
      return False;
   end Delete_Event;

   -- Destroy  handler  is  standard  for  GTK.   Normally   it   should
   -- communicate with the tasks if the window is closed prematurely.  I
   -- have omitted that stuff. Therefore, if you close  the  application
   -- window, the process will hang. 
   procedure Destroy (Widget : access Gtk_Widget_Record'Class) is
   begin
      Gtk.Main.Main_Quit;
   end Destroy;

   -- Circumvention of access rules, don't do it, it  is  here  only  to
   -- simplify the test 
   type Local_Callback is access procedure;
   function "+" is
      new Ada.Unchecked_Conversion (Local_Callback, Gtk_Callback);
   
   task type Process;

   -- Update will write the label
   procedure Update is
   begin
      Set_Text (Label, "Counter" & Integer'Image (Counter));
   end Update;

   -- The task that calls to Update
   task body Process is
   begin
      for Index in 1..10 loop
         Counter := Index;
         Request (+Update'Access); -- Request execution of Update
         delay 0.5;
      end loop;
   exception
      when Error : others =>
         Say (Exception_Information (Error)); -- This is safe
   end Process;

begin
   Gtk.Main.Init;
   Gtk.Main.Router.Init; -- This must be called once
   Gtk.Window.Gtk_New (Window);
   Set_Title (Window, "Test");
   Return_Handlers.Connect
   (  Window,
      "delete_event",
      Return_Handlers.To_Marshaller (Delete_Event'Access)
   );
   Handlers.Connect
   (  Window,
      "destroy",
      Handlers.To_Marshaller (Destroy'Access)
   );
   Gtk_New (Grid, 1, 1, False);
   Add (Window, Grid);
   Gtk_New (Label, "label");
   Attach (Grid, Label, 0, 1, 0, 1);

   Show (Label);
   Show (Grid);
   Show (Window);
   declare
      Worker : Process; -- Now the task is on
   begin
      --
      -- Enter the events processing loop
      --
      Gtk.Main.Main;
   end;
exception
   when Error : others =>
      Say (Exception_Information (Error)); -- This is safe
end Test_Gtk;



More information about the gtkada mailing list