-------------------------------------------------------------------
--           RAPID - RAPID ADA PORTABLE INTERFACE DESIGNER         
--           MCC GUI PACKAGE LIBRARY                               
--           Copyright (C) 1999 Martin C. Carlisle.                
--                                                                 
-- RAPID 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 2,  or (at your
-- option) any later version.  RAPID is distributed in the hope that 
-- it will be useful, but WITHOUT ANY WARRANTY;  without even the 
-- implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
-- PURPOSE.  See the GNU General Public License for more details.  
-- You should have  received  a copy of the GNU General Public License
-- distributed with RAPID; see file COPYING.  If not, write to the 
-- Free Software Foundation,  59 Temple Place - Suite 330,  Boston, 
-- MA 02111-1307, USA.                                                 
--                                                                     
-- As a special exception, if other files instantiate generics from
-- this unit, or you link this unit with other files to produce an 
-- executable, this unit does not by itself cause the resulting 
-- executable to be covered by the GNU General Public License.  
-- This exception does not however invalidate any other reasons 
-- why the executable file might be covered by the GNU Public 
-- License.  This exception does not apply to executables which
-- are GUI design tools, or that could act as a replacement
-- for RAPID.
------------------------------------------------------------------------------
with Glib;
use Glib;
with Gdk;
with Gtk.Box;
with Gtk.Enums;
with Gtk.Widget;
with Gtk.Window;
with Gtk.Fixed;
with Gtk.Main;
with Gtk.Signal;
with mcc.Gtk_Signals;
with Mcc.Gui.Window_Peer;
with System;
with ada.text_io;
with Gdk.Event;
with Gdk.Types;
with Ada.Unchecked_Conversion;
with Gtk.Type_Conversion;
package body Mcc.Gui.Container.Window is
   package Mcc_Window_Callback is new Mcc.Gtk_Signals.Event_Object_Callback_Return(
      Base_Type    => Window);

   function Mcc_Resize_Callback(
      Widget : System.Address;
      Event  : System.Address; 
      Object : access Window) return Glib.Guint;
   pragma Convention(C, Mcc_Resize_Callback);
   function Mcc_Resize_Callback(
      Widget : System.Address;
      Event  : System.Address; 
      Object : access Window) return Glib.Guint is
      Configure_Event : Gdk.Event.Gdk_Event_Configure;
      Width : Integer;
      Height : Integer;
      function Convert is new Ada.Unchecked_Conversion(
         System.Address,Gdk.Event.Gdk_Event_Configure);
   begin
      if Object.Resize_Callback /= null then
         Configure_Event := Convert(Event);
         Width := Mcc.Gtk_Signals.Mask(
            Gdk.Event.Get_Width(Configure_Event));
         Height := Mcc.Gtk_Signals.Mask(
            Gdk.Event.Get_Height(Configure_Event));
         if Mcc.Gui.Window_Peer.Has_Menu(Object.all) then
            Height := Height - Mcc.Gui.Window_Peer.Menubar_Height;
         end if;
         
         -- don't do callback if window is getting
         -- minimized!
         if Width > 0 or Height > 0 then
            Object.Resize_Callback.all(Object.all,
               Height => Height, 
               Width  => Width);
         end if;
      end if;
      return 0;
   end Mcc_Resize_Callback;

   function Mcc_Close_Callback(
      Widget : System.Address;
      Event  : System.Address; 
      Object : access Window) return Glib.Guint;
   pragma Convention(C, Mcc_Close_Callback);
   
   function Mcc_Close_Callback(
      Widget : System.Address;
      Event  : System.Address; 
      Object : access Window) return Glib.Guint is
   begin
      if Object.Close_Callback /= null then
         Object.Close_Callback.all(Object.all);
         return 1;
      elsif Window'Class(Object.all) in Main_Window'Class then
         Gtk.Window.Destroy(
            Gtk.Window.Gtk_Window(
               Mcc.Gui.Window_Peer.Get_Window(Window => Object.all)));
         Gtk.Main.Main_Quit;
         return 1;
      else 
         return 0;
      end if;
   end Mcc_Close_Callback;
   

   ------------
   -- Create --
   ------------

   --Each window is a window with a fixed frame inside.  Obj.My_Peer points
   --to the frame.  To access the window, must return frame's parent.
   procedure Common_Create (
         Obj    : in out Window'Class; 
         X      : in     Natural;      
         Y      : in     Natural;      
         Width  : in     Natural;      
         Height : in     Natural       ) is 

      Window : Gtk.Window.Gtk_Window;  
      Frame  : Gtk.Fixed.Gtk_Fixed;  
      Vbox   : Gtk.Box.Gtk_Vbox;
      Cb_Id  : Glib.Guint;  

   begin --Common_Create
      Obj.Resize_Callback := null;
      Obj.Close_Callback := null;
      Obj.Key_Handler := null;
      Obj.Mouse_Handler := null;

      Gtk.Window.Gtk_New(
        Window   => Window,                   
        The_Type => Gtk.Enums.Window_Toplevel);
      Gtk.Box.Gtk_New_Vbox(
         Box         => Vbox,
         Homogeneous => False,
         Spacing     => 0);
      Gtk.Window.Add(
        Container => Window, 
        Widget    => Vbox);
      Gtk.Box.Show(Vbox);

      Gtk.Window.Set_Uposition(
        Widget => Window,   
        X      => Gint (X), 
        Y      => Gint (Y));

      Gtk.Window.Set_Default_Size (
        Window => Window,       
        Width  => Gint (Width), 
        Height => Gint (Height));
      --Create Frame inside of window
      Gtk.Fixed.Gtk_New(Fixed => Frame);

      --Add Frame to window
      Gtk.Box.Pack_End(
        In_Box  => Vbox, 
        Child   => Frame,
        Expand  => True,
        Fill    => True,
        Padding => 0);
      Gtk.Fixed.Show(Frame);
      Gtk.Fixed.Set_Events(
         Widget => Frame,
         Events => Gdk.Types.All_Events_Mask);
      --Set object to point to window
      Obj.My_Peer := Gtk.Root_Type_Access(Frame);
      Show(Obj);
      Cb_Id  := Mcc_Window_Callback.Connect(
        Obj  => Gtk.Window.Gtk_Window (Window), 
        Name => "delete_event",                      
        Func => Mcc_Close_Callback'access,
        Slot_Object => Obj'unchecked_access,
        After  => False);
   end Common_Create;

   procedure Create (
         Obj    : in out Main_Window; 
         X      : in     Natural;     
         Y      : in     Natural;     
         Width  : in     Natural;     
         Height : in     Natural      ) is 

   begin
      Common_Create(
        Obj    => Obj,   
        X      => X,     
        Y      => Y,     
        Width  => Width, 
        Height => Height);
   end Create;

   ------------
   -- Create --
   ------------

   procedure Create (
         Obj    : in out Subwindow; 
         X      : in     Natural;   
         Y      : in     Natural;   
         Width  : in     Natural;   
         Height : in     Natural    ) is 
   begin
      Common_Create(
        Obj    => Obj,   
        X      => X,     
        Y      => Y,     
        Width  => Width, 
        Height => Height);
   end Create;

   ----------------
   -- Event_Loop --
   ----------------

   procedure Event_Loop is 
   begin
      Gtk.Main.Main;
   end Event_Loop;

   -----------------------
   -- Get_Close_Handler --
   -----------------------

   function Get_Close_Handler (
         Obj : in     Window'Class ) 
     return Close_Handler is 
   begin
      return Obj.Close_Callback;
   end Get_Close_Handler;

   ------------------------
   -- Get_Resize_Handler --
   ------------------------

   function Get_Resize_Handler (
         Obj : in     Window'Class ) 
     return Resize_Handler is 
   begin
      return Obj.Resize_Callback;
   end Get_Resize_Handler;

   ----------
   -- Hide --
   ----------

   procedure Hide (
         Obj : in     Window ) is 
      Window : Gtk.Widget.Gtk_Widget;  
   begin
      Window := Mcc.Gui.Window_Peer.Get_Window(Window => Obj);
      Gtk.Widget.Hide(Widget => Window);
   end Hide;

   function Is_Open(Obj : in Window) return Boolean is
      use type Gtk.Root_Type_Access;
   begin
      if Obj.My_Peer /= null then
         return Gtk.Is_Created(Obj.My_Peer.all);
      else
         return False;
      end if;
   end Is_Open;
   
   -----------------------
   -- Set_Close_Handler --
   -----------------------

   procedure Set_Close_Handler (
         Obj     : in     Window_Pointer; 
         Handler : in     Close_Handler   ) is 
   begin
      Obj.Close_Callback := Handler;
   end Set_Close_Handler;

   ------------------------
   -- Set_Resize_Handler --
   ------------------------

   procedure Set_Resize_Handler (
         Obj     : in     Window_Pointer; 
         Handler : in     Resize_Handler  ) is 
      Cb_Id  : Glib.Guint;  
      Window : Gtk.Widget.Gtk_Widget;  
   begin
      if Obj.Resize_Callback = null then
         Window := Mcc.Gui.Window_Peer.Get_Window(Window => Obj.all);
         Cb_Id  := Mcc_Window_Callback.Connect(
           Obj  => Gtk.Window.Gtk_Window (Window), 
           Name => "configure_event",                      
           Func => Mcc_Resize_Callback'access,
           Slot_Object => Obj,
           After  => False);
      end if;
      Obj.Resize_Callback := Handler;
   end Set_Resize_Handler;

   ---------------
   -- Set_Title --
   ---------------

   procedure Set_Title (
         Obj   : in out Window; 
         Title : in     String  ) is 
      Window : Gtk.Widget.Gtk_Widget;  
   begin
      Window := Mcc.Gui.Window_Peer.Get_Window(Window => Obj);
      Gtk.Window.Set_Title(
        Window => Gtk.Window.Gtk_Window (Window), 
        Title  => Title);
   end Set_Title;

   ----------
   -- Show --
   ----------

   procedure Show (
         Obj : in     Window ) is 
      Window : Gtk.Widget.Gtk_Widget;  
   begin
      Window := Mcc.Gui.Window_Peer.Get_Window(Window => Obj);
      Gtk.Widget.Show(Widget => Window);
   end Show;

   ------------
   -- To_Top --
   ------------

   procedure To_Top (
         Obj : in     Window ) is 
      Window : Gtk.Widget.Gtk_Widget;  
   begin
      Window := Mcc.Gui.Window_Peer.Get_Window(Window => Obj);
      Gtk.Widget.Hide(Widget => Window);
      Gtk.Widget.Show(Widget => Window);
   end To_Top;
begin
   Gtk.Main.Set_Locale;
   Gtk.Main.Init;
   Gtk.Type_Conversion.Init;
end Mcc.Gui.Container.Window;