-------------------------------------------------------------------
--           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 MSSyst.Windows.Forms;
use MSSyst.Windows.Forms;
with MSSyst.String;
use MSSyst.String;
with MSSyst.Windows.Forms.Form;
with MSSyst.Object;
with MSSyst.Drawing;
use MSSyst.Drawing;
with MSSyst.Drawing.Point;
with MSSyst.Drawing.Size;
with MSSyst.Windows.Forms.Application;
with MSSyst.ComponentModel;
use MSSyst.ComponentModel;
with MSSyst.ComponentModel.CancelEventHandler;
with MSSyst.ComponentModel.CancelEventArgs;
with MSSyst.Windows.Forms.LayoutEventArgs;
with MSSyst.Windows.Forms.LayoutEventHandler;
with Ada.Unchecked_Conversion;
with MSSyst.Drawing.Rectangle;
with Mcc.Common_Dialogs;
package body Mcc.Gui.Container.Window is
   function Convert is new Ada.Unchecked_Conversion(
      MSSyst.Object.Ref, Window_Pointer);
   function Convert is new Ada.Unchecked_Conversion(
      Window_Pointer, MSSyst.Object.Ref);
   function To_Form is new Ada.Unchecked_Conversion(
      MSSyst.Object.Ref, Form.Ref);
   function To_Object is new Ada.Unchecked_Conversion(
      Form.Ref, MSSyst.Object.Ref);

   procedure Null_Resize_Handler(
         Obj    : in out Window'Class;
         Width  : in     Integer;
         Height : in     Integer) is
   begin
      null;
   end Null_Resize_Handler;
   
   procedure Null_Close_Handler(
         Obj   : in out Window'Class) is
   begin
      Obj.My_Peer := null;
   end Null_Close_Handler;

   In_Close_Callback : Boolean := False;
   procedure Dotnet_Close(
         Sender : MSSyst.Object.Ref;
         E      : CancelEventArgs.Ref) is
      The_Peer : Form.Ref := To_Form(Sender);
      Rapid_Pointer : Window_Pointer;
      Tag : MSSyst.Object.Ref := MSSyst.Object.Ref(The_Peer.Get_Tag);
   begin
      -- we ensure here that we don't get into an infinite loop
      -- also, for reasons I don't quite get, it seems like this
      -- gets called twice for the X in the upper right, so it forces
      -- the second time not to do anything
      if In_Close_Callback then
         E.Set_Cancel(True);
         In_Close_Callback := False;
         return;
      else
         In_Close_Callback := True;
      end if;
      Rapid_Pointer := Convert(Tag);
      if Rapid_Pointer.Close_Callback = null then
         return;
      end if;
      Rapid_Pointer.Close_Callback (Rapid_Pointer.all);
      E.Set_Cancel(True);
   end Dotnet_Close;

   procedure Dotnet_Resize(
         Sender : MSSyst.Object.Ref;
         E      : LayoutEventArgs.Ref) is
      The_Peer : Form.Ref := To_Form(Sender);
      Rapid_Pointer : Window_Pointer;
      Tag : MSSyst.Object.Ref := MSSyst.Object.Ref(The_Peer.Get_Tag);
      Bounds : Rectangle.Valuetype;   
   begin
      Rapid_Pointer := Convert(Tag);
      if Rapid_Pointer.Resize_Callback = null then
         return;
      end if;
      Bounds := The_Peer.Get_Bounds;
      Rapid_Pointer.Resize_Callback (
         Obj    => Rapid_Pointer.all,
         Width  => Bounds.Get_Width,
         Height => Bounds.Get_Height-Peer.Title_Bar_Size);
   end Dotnet_Resize;

   The_Main_Window : Form.Ref;
   
   function Is_Open(Obj : in Window) return Boolean is
      The_Peer : Form.Ref := To_Form(Get_Peer(Obj));
      use type Form.Ref;
   begin
      if The_Peer=null then
         return False;
      else
         return True;
      end if;
   end Is_Open;
   
   ------------
   -- Create --
   ------------

   procedure Create
     (Obj    : in out Main_Window;
      X      : in     Natural;
      Y      : in     Natural;
      Width  : in     Natural;
      Height : in     Natural)
   is
      The_Peer : Form.Ref;     
      Where    : Point.Valuetype;
      How_Big  : Size.Valuetype;
   begin
      -- ok, so it might seem odd to do this, but since we reuse 
      -- variables, it is important to renull these on create   
      Obj.Mouse_Handler := null;   
      Obj.Key_Handler := null;   
      The_Peer := Form.New_Form;
      Obj.My_Peer := To_Object(The_Peer);
      Where := Point.New_Point(X,Y);
      How_Big := Size.New_Size(Width => Width,
         Height => Height+Peer.Title_Bar_Size);
        
      The_Peer.Set_Size(How_Big);
      The_Peer.Set_DesktopLocation(Where);
      The_Peer.set_Visible(True);
      The_Main_Window := The_Peer;
      Set_Close_Handler(Obj'unchecked_access,null);
   end Create;

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

   procedure Create
     (Obj    : in out Subwindow;
      X      : in     Natural;
      Y      : in     Natural;
      Width  : in     Natural;
      Height : in     Natural)
   is
      The_Peer : Form.Ref;     
      Where    : Point.Valuetype;
      How_Big  : Size.Valuetype;
   begin
      -- ok, so it might seem odd to do this, but since we reuse 
      -- variables, it is important to renull these on create   
      Obj.Mouse_Handler := null;   
      Obj.Key_Handler := null;   
      The_Peer := Form.New_Form;
      Obj.My_Peer := To_Object(The_Peer);
      Where := Point.New_Point(X,Y);
      How_Big := Size.New_Size(Width => Width,
         Height => Height+Peer.Title_Bar_Size);
      The_Peer.Set_Size(How_Big);
      The_Peer.Set_DesktopLocation(Where);
      The_Peer.Set_Visible(True);
      Set_Close_Handler(Obj'unchecked_access,null);
   end Create;

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

   procedure Event_Loop is
   begin
      Application.Run(The_Main_Window);
   end Event_Loop;

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

   function Get_Close_Handler
     (Obj : in Window'Class)
      return Close_Handler
   is
   begin
      if Obj.Close_Callback = Null_Close_Handler'access then
         return null;
      else
         return Obj.Close_Callback;
      end if;
   end Get_Close_Handler;

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

   function Get_Resize_Handler
     (Obj : in Window'Class)
      return Resize_Handler
   is
   begin
      if Obj.Resize_Callback = Null_Resize_Handler'access then
         return null;
      else
         return Obj.Resize_Callback;
      end if;
   end Get_Resize_Handler;

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

   procedure Hide (Obj : in Window) is
      Ref : Form.Ref := To_Form(Get_Peer(Obj));         
   begin
      Ref.set_Visible(False);
   end Hide;

   -----------------------
   -- Set_Close_Handler --
   -----------------------

   procedure Set_Close_Handler
     (Obj     : in Window_Pointer;
      Handler : in Close_Handler)
   is
     The_Peer : Form.Ref := To_Form(Obj.My_Peer);         
   begin
      if Obj.Close_Callback = null then
         The_Peer.Set_Tag(Convert(Obj));
         The_Peer.Add_Closing(
            CancelEventHandler.New_CancelEventHandler(
               Object => To_Object(The_Peer),
               Method => Dotnet_Close'address));
      end if;
      if Handler = null then
         Obj.Close_Callback := Null_Close_Handler'access;
      else
         Obj.Close_Callback := Handler;
      end if;
      Obj.Close_Callback := Handler;
   end Set_Close_Handler;

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

   procedure Set_Resize_Handler
     (Obj     : in Window_Pointer;
      Handler : in Resize_Handler)
   is
     The_Peer : Form.Ref := To_Form(Obj.My_Peer);         
   begin
      if Obj.Resize_Callback = null then
         The_Peer.Set_Tag(Convert(Obj));
         The_Peer.Add_Layout(
            LayoutEventHandler.New_LayoutEventHandler(
               Object => To_Object(The_Peer),
               Method => Dotnet_Resize'address));
      end if;
      if Handler = null then
         Obj.Resize_Callback := Null_Resize_Handler'access;
      else
         Obj.Resize_Callback := Handler;
      end if;
   end Set_Resize_Handler;

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

   procedure Set_Title
     (Obj   : in out Window;
      Title : in     String)
   is
      Ref : Form.Ref := To_Form(Get_Peer(Obj));         
   begin
      Ref.set_Text(+Title);
   end Set_Title;

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

   procedure Show (Obj : in Window) is
      Ref : Form.Ref := To_Form(Get_Peer(Obj));         
   begin
      Ref.set_Visible(True);
   end Show;

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

   procedure To_Top (Obj : in Window) is
      Ref : Form.Ref := To_Form(Get_Peer(Obj));         
   begin
      Ref.BringToFront;
   end To_Top;

end Mcc.Gui.Container.Window;

