------------------------------------------------------------------------------
--                  GtkAda - Ada95 binding for Gtk+/Gnome                   --
--                                                                          --
--                     Copyright (C) 2011-2018, AdaCore                     --
--                                                                          --
-- This library is free software;  you can redistribute it and/or modify it --
-- under terms of the  GNU General Public License  as published by the Free --
-- Software  Foundation;  either version 3,  or (at your  option) any later --
-- version. This library is distributed in the hope that it will be useful, --
-- but WITHOUT ANY WARRANTY;  without even the implied warranty of MERCHAN- --
-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE.                            --
--                                                                          --
-- As a special exception under Section 7 of GPL version 3, you are granted --
-- additional permissions described in the GCC Runtime Library Exception,   --
-- version 3.1, as published by the Free Software Foundation.               --
--                                                                          --
-- You should have received a copy of the GNU General Public License and    --
-- a copy of the GCC Runtime Library Exception along with this program;     --
-- see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see    --
-- <http://www.gnu.org/licenses/>.                                          --
--                                                                          --
------------------------------------------------------------------------------

--  <description>
--
--  This package provides a high-level API for using Gtk.Builder and
--  user interface files produced with the GUI builder glade-3.
--
--  Here is how to use this package:
--
--     Step 1: create a Builder and add the XML data, just as you would a
--             standard Gtk.Builder:
--
--             declare
--                Builder : Gtkada_Builder;
--                Error   : GError;
--             begin
--                Gtk_New (Builder);
--                Error := Add_From_File (Builder, Default_Filename);
--
--     Step 2: add calls to "Register_Handler" to associate your handlers
--             with your callbacks.
--
--                Register_Handler
--                   (Builder      => Builder,
--                    Handler_Name => "my_handler_id",
--                    Handler      => My_Handler'Access);
--
--             Where:
--              - Builder is your Gtkada_Builder,
--              - "my_handler_id" is the name of the handler as specified in
--                  Glade-3, in the "Handler" column of the "Signals" tab for
--                  your object,
--              - Handler is your Ada subprogram.
--
--              You will need one call to "Register_Handler" per handler
--              declared in the Glade-3 interface. If there is one or more
--              handler declared in Glade-3 which does not have an associated
--              call to Register_Handler, an ASSERT_FAILURE will be raised by
--              the Gtk main loop.
--
--              There are multiple way to call Register_Handler, see below.
--
--     Step 3: call Do_Connect.
--
--     Step 4: when the application terminates or all Windows described through
--             your builder should be closed, call Unref to free memory
--             associated with the Builder.
--
--  </description>
--  <group>GUI Builder</group>

with Ada.Containers.Hashed_Maps;
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
with Ada.Strings.Unbounded.Hash;

with Glib.Object; use Glib.Object;
with Gtk.Builder;

package Gtkada.Builder is

   type Gtkada_Builder_Record is new
     Gtk.Builder.Gtk_Builder_Record with private;
   type Gtkada_Builder is access all Gtkada_Builder_Record'Class;

   procedure Gtk_New (Builder : out Gtkada_Builder);
   procedure Initialize (Builder : access Gtkada_Builder_Record'Class);
   --  Create a new Gtkada_Builder.

   procedure Do_Connect (Builder : access Gtkada_Builder_Record'Class);
   --  Activate in the builder callabacks that have been connected using
   --  calls to Register_Handler functions below.

   --------------------------------------
   -- Callbacks working on the Builder --
   --------------------------------------

   --  These callbacks take as parameter the Gtkada_Builder.
   --  If a "User data" is present in the Glade-3, it will be ignored.

   type Builder_Handler is access procedure
     (Builder : access Gtkada_Builder_Record'Class);

   type Builder_Return_Handler is access function
     (User_Data : access Gtkada_Builder_Record'Class) return Boolean;

   procedure Register_Handler
     (Builder      : access Gtkada_Builder_Record'Class;
      Handler_Name : String;
      Handler      : Builder_Handler);

   procedure Register_Handler
     (Builder      : access Gtkada_Builder_Record'Class;
      Handler_Name : String;
      Handler      : Builder_Return_Handler);

   --------------------------------------------------------------
   -- Callbacks working on user data specified through Glade-3 --
   --------------------------------------------------------------

   --  Use these registry functions if your signal handler was defined in
   --  the Glade-3 interface with a "User data". The parameter User_Data
   --  passed to the handlers corresponds to the object entered in the
   --  "User data" column in Glade-3.

   type Object_Handler is access procedure
     (User_Data : access GObject_Record'Class);

   type Object_Return_Handler is access function
     (User_Data : access GObject_Record'Class) return Boolean;

   procedure Register_Handler
     (Builder      : access Gtkada_Builder_Record'Class;
      Handler_Name : String;
      Handler      : Object_Handler);

   procedure Register_Handler
     (Builder      : access Gtkada_Builder_Record'Class;
      Handler_Name : String;
      Handler      : Object_Return_Handler);

private

   type Handler_Type is (Object, Object_Return, Builder, Builder_Return);
   type Universal_Marshaller (T : Handler_Type) is record
      case T is
         when Object =>
            The_Object_Handler : Object_Handler;
         when Object_Return =>
            The_Object_Return_Handler : Object_Return_Handler;
         when Builder =>
            The_Builder_Handler : Builder_Handler;
         when Builder_Return =>
            The_Builder_Return_Handler : Builder_Return_Handler;
      end case;
   end record;

   type Universal_Marshaller_Access is access Universal_Marshaller;

   package Handlers_Map is new Ada.Containers.Hashed_Maps
     (Key_Type        => Unbounded_String,
      Element_Type    => Universal_Marshaller_Access,
      Hash            => Ada.Strings.Unbounded.Hash,
      Equivalent_Keys => "=",
      "="             => "=");

   type Gtkada_Builder_Record is new
     Gtk.Builder.Gtk_Builder_Record
   with record
      Handlers : Handlers_Map.Map;
   end record;

end Gtkada.Builder;
