-------------------------------------------------------------------
--           RAPID - RAPID ADA PORTABLE INTERFACE DESIGNER         
--           MCC-COMMON_DIALOGS
--           GWINDOWS PEER IMPLEMENTATION                               
--           Copyright (C) 2001 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 Gwindows.Common_Dialogs;
with Gwindows.GStrings;
with Gwindows.GStrings.Unbounded;
with Gwindows.Message_Boxes;
with Gwindows.Application;
with Peer;
with Ada.Strings.Fixed;
package body Mcc.Common_Dialogs is
   Have_Saved_Directory : Boolean := False;
   Saved_Directory : Gwindows.Gstrings.Unbounded.Unbounded_String;
   ------------
   -- Ok_Box --
   ------------

   procedure Ok_Box
     (Message       : in String)
   is
   begin
      Gwindows.Message_Boxes.Message_Box (
         Title       => GWindows.GStrings.To_GString_From_String(""),
         Text        => Gwindows.Gstrings.To_Gstring_From_String(Message),
         Style       => Gwindows.Message_Boxes.OK_Box,
         Icon        => Gwindows.Message_Boxes.Information_Icon);
   end Ok_Box;

   procedure Ok_Box (
         Message : in     String;                               
         Parent  : in     Mcc.Gui.Container.Window.Window'Class )
   is
   begin
      Gwindows.Message_Boxes.Message_Box (
         Window      => Mcc.Gui.Container.Window.Get_Peer(Parent).all,
         Title       => GWindows.GStrings.To_GString_From_String(""),
         Text        => Gwindows.Gstrings.To_Gstring_From_String(Message),
         Style       => Gwindows.Message_Boxes.OK_Box,
         Icon        => Gwindows.Message_Boxes.Information_Icon);
   end Ok_Box;


   function Get_Filters(File_Types : in String) 
      return Gwindows.Common_Dialogs.Filter_Array is
      Current : Natural := File_Types'First;
      Nested : Boolean := False;
      Counter : Integer := 0;
      Copy_File_Types : String := File_Types;
   begin
      -- this code works only because we don't nest more than
      -- one level.  It counts the number of non-nested {
      for i in File_Types'range loop
         if File_Types(i) = '{' then
            if not Nested then
               Nested := True;
               Counter := Counter + 1;
            end if;
         elsif File_Types(i) = '}' then
            Nested := False;
         end if;
      end loop;
      
      declare
         Result : Gwindows.Common_Dialogs.Filter_Array(1..Counter);
         Start_Description : Natural;
         End_Description   : Natural;
         Start_Extension   : Natural;
         End_Extension     : Natural;
         Done              : Boolean;
      begin
         Counter := 0;
               
         while Current < File_Types'Last loop
            -- loop until we either get a { marking a filter start, or
            -- the end of the string
            while File_Types(Current) /= '{' and Current < File_Types'Last loop
               Current := Current + 1;
            end loop;
         
            -- if we're not at the end yet, process this filter.
            exit when Current >= File_Types'Last;
            Counter := Counter + 1;
            
            -- look for a " to begin the description
            while File_Types(Current) /= '"' loop
               Current := Current + 1;
            end loop;
            
            Current := Current + 1;
            Start_Description := Current;
            
            -- look for a " to end the description
            while File_Types(Current) /= '"' loop
               Current := Current + 1;
            end loop;
            
            End_Description := Current - 1;
            Done := False;
            
            Result(Counter).Name := 
               Gwindows.GStrings.Unbounded.To_Unbounded_String(
                  File_Types(Start_Description..End_Description));
                  
            while File_Types(Current) /= '*' and
               File_Types(Current) /= '.' loop
               Current := Current + 1;
            end loop;
               
            Start_Extension := Current;
            while File_Types(Current) /= '*' and
               File_Types(Current) /= '}' loop
               Current := Current + 1;
            end loop;
            End_Extension := Current-1;
            
            -- change spaces to ;
            for i in Start_Extension..End_Extension loop
               if File_Types(i)=' ' then
                  Copy_File_Types(i) := ';';
               end if;
            end loop; 

            if File_Types(Start_Extension)='*' then
               Result(Counter).Name := 
                  Gwindows.GStrings.Unbounded.To_Unbounded_String(
                     "*.*");
            else
               Result(Counter).Name := 
                  Gwindows.GStrings.Unbounded.To_Unbounded_String(
                     Copy_File_Types(Start_Extension..End_Extension));
            end if;
         end loop;
         return Result;
      end;
   end Get_Filters;

   -----------------
   -- Open_Dialog --
   -----------------

   procedure Open_Dialog
     (File_Types        : in String;
      Filename          : out String;
      File_Last         : out Natural;
      Title             : in String := "Open";
      Initial_Directory : in String := ".";
      Default_Extension : in String := "";
      Change_Directory  : in Boolean := True)
   is
      Directory : String(1..1024);
      Dir_Last  : Integer;
   begin
      Open_Dialog
        (File_Types => File_Types,
         Filename   => Filename,
         File_Last  => File_Last,
         Directory  => Directory,
         Dir_Last   => Dir_Last,
         Title      => Title,
         Initial_Directory => Initial_Directory,
         Default_Extension => Default_Extension,
         Change_Directory  => Change_Directory);
   end Open_Dialog;

   -----------------
   -- Open_Dialog --
   -----------------

   procedure Open_Dialog
     (File_Types : in String;
      Filename   : out String;
      File_Last  : out Natural;
      Directory  : out String;
      Dir_Last   : out Natural;
      Title      : in String := "Open";
      Initial_Directory : in String := ".";
      Default_Extension : in String := "";
      Change_Directory  : in Boolean := True)
   is
      File_Name : Gwindows.Gstrings.Unbounded.Unbounded_String;
      File_Title: Gwindows.Gstrings.Unbounded.Unbounded_String;
      Success   : Boolean;
   begin
      if Have_Saved_Directory then
         File_Name := Gwindows.Gstrings.Unbounded.Null_Unbounded_String;
      else
         File_Name := Saved_Directory;
      end if;
      
      if Initial_Directory /= "." then
         File_Name := Gwindows.Gstrings.Unbounded.To_Unbounded_String(
            Initial_Directory);
      end if;
      
      Gwindows.Common_Dialogs.Open_File
        (Window            => Peer.Get_Main_Window_Peer.all,
         Dialog_Title      => GWindows.GStrings.To_GString_From_String(Title),
         File_Name         => File_Name,
         Filters           => Get_Filters(File_Types),
         Default_Extension => 
            Gwindows.Gstrings.To_Gstring_From_String(Default_Extension),
         File_Title        => File_Title,
         Success           => Success);
      if Success then   
         declare
            File_Result : String := Gwindows.Gstrings.Unbounded.
               To_String(File_Name);
            Separator : Natural;
         begin
            Separator := Ada.Strings.Fixed.Index(
               Source  => File_Result,
               Pattern => "\",
               Going   => Ada.Strings.Backward);
               
            File_Last := Filename'First+File_Result'Length-1;
            Filename(Filename'First..File_Last) := File_Result;

            Dir_Last := File_Result'First+Separator-File_Result'First-1;
            Directory(Directory'First..Dir_Last) :=
               File_Result(File_Result'First..Separator-1);
               
            if Change_Directory then
               Have_Saved_Directory := True;
               Saved_Directory := Gwindows.Gstrings.Unbounded.
                  To_Unbounded_String(Directory(Directory'First..Dir_Last));
            end if;
         end;
      end if;
   end Open_Dialog;

   -----------------
   -- Quit_Dialog --
   -----------------

   procedure Quit_Dialog
     (Verify : Boolean := True)
   is
      Result : Boolean;
   begin
      if Verify then
         Result := Yesno_Dialog(
            Message => "Are you sure you want to exit?",
            Title   => "Quit now?");
      else
         Result := True;
      end if;
      
      if Result then
         Gwindows.Application.End_Loop;
      end if;
   end Quit_Dialog;

   -----------------
   -- Save_Dialog --
   -----------------

   procedure Save_Dialog
     (File_Types : in String;
      Filename   : out String;
      File_Last  : out Natural;
      Title      : in String := "Save As";
      Initial_Directory : in String := ".";
      Default_Extension : in String := "";
      Change_Directory  : in Boolean := True)
   is
      Directory : String(1..1024);
      Dir_Last  : Integer;
   begin
      Save_Dialog
        (File_Types => File_Types,
         Filename   => Filename,
         File_Last  => File_Last,
         Directory  => Directory,
         Dir_Last   => Dir_Last,
         Title      => Title,
         Initial_Directory => Initial_Directory,
         Default_Extension => Default_Extension,
         Change_Directory  => Change_Directory);
   end Save_Dialog;

   -----------------
   -- Save_Dialog --
   -----------------

   procedure Save_Dialog
     (File_Types : in String;
      Filename   : out String;
      File_Last  : out Natural;
      Directory  : out String;
      Dir_Last   : out Natural;
      Title      : in String := "Save As";
      Initial_Directory : in String := ".";
      Default_Extension : in String := "";
      Change_Directory  : in Boolean := True)
   is
      File_Name : Gwindows.Gstrings.Unbounded.Unbounded_String;
      File_Title: Gwindows.Gstrings.Unbounded.Unbounded_String;
      Success   : Boolean;
   begin
      if Have_Saved_Directory then
         File_Name := Gwindows.Gstrings.Unbounded.Null_Unbounded_String;
      else
         File_Name := Saved_Directory;
      end if;
      
      if Initial_Directory /= "." then
         File_Name := Gwindows.Gstrings.Unbounded.To_Unbounded_String(
            Initial_Directory);
      end if;
      
      Gwindows.Common_Dialogs.Save_File
        (Window            => Peer.Get_Main_Window_Peer.all,
         Dialog_Title      => GWindows.GStrings.To_GString_From_String(Title),
         File_Name         => File_Name,
         Filters           => Get_Filters(File_Types),
         Default_Extension => 
            Gwindows.Gstrings.To_Gstring_From_String(Default_Extension),
         File_Title        => File_Title,
         Success           => Success);
      if Success then   
         declare
            File_Result : String := Gwindows.Gstrings.Unbounded.
               To_String(File_Name);
            Separator : Natural;
         begin
            Separator := Ada.Strings.Fixed.Index(
               Source  => File_Result,
               Pattern => "\",
               Going   => Ada.Strings.Backward);
               
            File_Last := Filename'First+File_Result'Length-1;
            Filename(Filename'First..File_Last) := File_Result;

            Dir_Last := File_Result'First+Separator-File_Result'First-1;
            Directory(Directory'First..Dir_Last) :=
               File_Result(File_Result'First..Separator-1);
               
            if Change_Directory then
               Have_Saved_Directory := True;
               Saved_Directory := Gwindows.Gstrings.Unbounded.
                  To_Unbounded_String(Directory(Directory'First..Dir_Last));
            end if;
         end;
      end if;
   end Save_Dialog;

   ------------------
   -- Yesno_Dialog --
   ------------------

   function Yesno_Dialog
     (Message       : in String;
      Title         : in String)
      return Boolean
   is
      Result : Gwindows.Message_Boxes.Message_Box_Result;
      use type Gwindows.Message_Boxes.Message_Box_Result;
   begin
      Result := Gwindows.Message_Boxes.Message_Box (
         Title       => Gwindows.Gstrings.To_Gstring_From_String(Title),
         Text        => Gwindows.Gstrings.To_Gstring_From_String(Message),
         Style       => Gwindows.Message_Boxes.Yes_No_Box,
         Icon        => Gwindows.Message_Boxes.Question_Icon);
      return Result = Gwindows.Message_Boxes.Yes;
   end Yesno_Dialog;

   function Yesno_Dialog(
      Message       : in String;
      Title         : in String;
      Parent        : in Mcc.Gui.Container.Window.Window'Class) return Boolean is
      Result : Gwindows.Message_Boxes.Message_Box_Result;
      use type Gwindows.Message_Boxes.Message_Box_Result;
   begin
      Result := Gwindows.Message_Boxes.Message_Box (
         Window      => Mcc.Gui.Container.Window.Get_Peer(Parent).all,
         Title       => Gwindows.Gstrings.To_Gstring_From_String(Title),
         Text        => Gwindows.Gstrings.To_Gstring_From_String(Message),
         Style       => Gwindows.Message_Boxes.Yes_No_Box,
         Icon        => Gwindows.Message_Boxes.Question_Icon);
      return Result = Gwindows.Message_Boxes.Yes;
   end Yesno_Dialog;

   function Yesno_Cancel_Dialog(
      Message       : in String;
      Title         : in String) return Yesno_Cancel is
      Result : Gwindows.Message_Boxes.Message_Box_Result;
      use type Gwindows.Message_Boxes.Message_Box_Result;
   begin
      Result := Gwindows.Message_Boxes.Message_Box (
         Title       => Gwindows.Gstrings.To_Gstring_From_String(Title),
         Text        => Gwindows.Gstrings.To_Gstring_From_String(Message),
         Style       => Gwindows.Message_Boxes.Yes_No_Cancel_Box,
         Icon        => Gwindows.Message_Boxes.Question_Icon);
      if Result=Gwindows.Message_Boxes.Yes then
         return Yes;
      elsif Result=Gwindows.Message_Boxes.No then
         return No;
      else
         return Cancel;
      end if;
   end Yesno_Cancel_Dialog;
   
   function Yesno_Cancel_Dialog(
      Message       : in String;
      Title         : in String;
      Parent        : in Mcc.Gui.Container.Window.Window'Class) return Yesno_Cancel is
      Result : Gwindows.Message_Boxes.Message_Box_Result;
      use type Gwindows.Message_Boxes.Message_Box_Result;
   begin
      Result := Gwindows.Message_Boxes.Message_Box (
         Window      => Mcc.Gui.Container.Window.Get_Peer(Parent).all,
         Title       => Gwindows.Gstrings.To_Gstring_From_String(Title),
         Text        => Gwindows.Gstrings.To_Gstring_From_String(Message),
         Style       => Gwindows.Message_Boxes.Yes_No_Cancel_Box,
         Icon        => Gwindows.Message_Boxes.Question_Icon);
      if Result=Gwindows.Message_Boxes.Yes then
         return Yes;
      elsif Result=Gwindows.Message_Boxes.No then
         return No;
      else
         return Cancel;
      end if;
   end Yesno_Cancel_Dialog;

end Mcc.Common_Dialogs;

