------------------------------------------------------------------------------
--                                                                          --
--                An Ada2005 binding to the Qt C++ framework                --
--                                                                          --
------------------------------------------------------------------------------
--                                                                          --
-- Copyright © 2008 Vadim Godunko <vgodunko@gmail.com>                      --
--                                                                          --
-- QtAda is free software;  you can  redistribute it and/or modify it under --
-- terms of the  GNU General Public License as published  by the Free Soft- --
-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
-- sion. QtAda is distributed in the hope that it will be useful, but WITH- --
-- OUT 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 QtAda;  see file COPYING.  If not, write --
-- to  the  Free Software Foundation,  51  Franklin  Street,  Fifth  Floor, --
-- Boston, MA 02110-1301, USA.                                              --
--                                                                          --
------------------------------------------------------------------------------
--  $Revision: 3234 $ $Date: 2009-04-09 23:05:06 +0400 (Thu, 09 Apr 2009) $
------------------------------------------------------------------------------
with Qt4.Core_Applications;
with Qt4.Fonts;
with Qt4.Frames.Constructors;
with Qt4.Grid_Layouts.Constructors;
with Qt4.H_Box_Layouts.Constructors;
with Qt4.Labels.Constructors;
with Qt4.LCD_Numbers.Constructors;
with Qt4.Objects;
with Qt4.Push_Buttons.Constructors;
with Qt4.Strings;
with Qt4.V_Box_Layouts.Constructors;

with Game_Boards.MOC;
pragma Warnings (Off, Game_Boards.MOC);
--  Child package MOC must be included in the application.

with LCD_Ranges;

package body Game_Boards is

   use type Qt4.Q_Integer;

   ------------------
   -- Constructors --
   ------------------

   package body Constructors is

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

      function Create (Parent : access Qt4.Widgets.Q_Widget'Class := null)
        return not null Game_Board_Access
      is
         use type Qt4.Frames.Shape;

         Self             : constant not null Game_Board_Access
           := new Game_Board;
         Family           : constant Qt4.Strings.Q_String
           := Qt4.Strings.From_Utf_16 ("Times");
         Font             : constant Qt4.Fonts.Q_Font
           := Qt4.Fonts.Create (Family, 18, Qt4.Fonts.Weight_Bold);
         Quit             : constant not null
           Qt4.Push_Buttons.Q_Push_Button_Access
             := Qt4.Push_Buttons.Constructors.Create
                 (Qt4.Strings.From_Utf_16 ("&Quit"));
         Shoot            : constant not null
           Qt4.Push_Buttons.Q_Push_Button_Access
             := Qt4.Push_Buttons.Constructors.Create
                 (Qt4.Strings.From_Utf_16 ("&Shoot"));
         Restart          : constant not null
           Qt4.Push_Buttons.Q_Push_Button_Access
             := Qt4.Push_Buttons.Constructors.Create
                 (Qt4.Strings.From_Utf_16 ("&New Game"));
         Angle            : constant not null LCD_Ranges.LCD_Range_Access
           := LCD_Ranges.Constructors.Create
               (Qt4.Strings.From_Utf_16 ("ANGLE"));
         Force            : constant not null LCD_Ranges.LCD_Range_Access
           := LCD_Ranges.Constructors.Create
               (Qt4.Strings.From_Utf_16 ("FORCE"));
         Cannon_Box       : constant not null Qt4.Frames.Q_Frame_Access
           := Qt4.Frames.Constructors.Create;
         Hits_Label       : constant not null Qt4.Labels.Q_Label_Access
           := Qt4.Labels.Constructors.Create
               (Qt4.Strings.From_Utf_16 ("HITS"));
         Shots_Left_Label : constant not null Qt4.Labels.Q_Label_Access
           := Qt4.Labels.Constructors.Create
               (Qt4.Strings.From_Utf_16 ("SHOTS LEFT"));
         Top_Layout       : constant not null
           Qt4.H_Box_Layouts.Q_H_Box_Layout_Access
             := Qt4.H_Box_Layouts.Constructors.Create;
         Left_Layout      : constant not null
           Qt4.V_Box_Layouts.Q_V_Box_Layout_Access
             := Qt4.V_Box_Layouts.Constructors.Create;
         Cannon_Layout    : constant not null
           Qt4.V_Box_Layouts.Q_V_Box_Layout_Access
             := Qt4.V_Box_Layouts.Constructors.Create;
         Grid_Layout      : constant not null
           Qt4.Grid_Layouts.Q_Grid_Layout_Access
             := Qt4.Grid_Layouts.Constructors.Create;

      begin
         Qt4.Widgets.Directors.Constructors.Initialize (Self, Parent);

         Quit.Set_Font (Font);
         Shoot.Set_Font (Font);
         Restart.Set_Font (Font);
         Angle.Set_Range (5, 70);
         Force.Set_Range (10, 50);
         Cannon_Box.Set_Frame_Style (Qt4.Frames.Win_Panel + Qt4.Frames.Sunken);

         Self.Cannon_Field := Cannon_Fields.Constructors.Create;
         Self.Hits := Qt4.LCD_Numbers.Constructors.Create (2);
         Self.Hits.Set_Segment_Style (Qt4.LCD_Numbers.Filled);
         Self.Shots_Left := Qt4.LCD_Numbers.Constructors.Create (2);
         Self.Shots_Left.Set_Segment_Style (Qt4.LCD_Numbers.Filled);

         Qt4.Objects.Connect
          (Quit,
           Qt4.Signal ("clicked()"),
           Qt4.Core_Applications.Instance,
           Qt4.Slot ("quit()"));
         Qt4.Objects.Connect
          (Angle,
           Qt4.Signal ("valueChanged(int)"),
           Self.Cannon_Field,
           Qt4.Slot ("setAngle(int)"));
         Qt4.Objects.Connect
          (Self.Cannon_Field,
           Qt4.Signal ("angleChanged(int)"),
           Angle,
           Qt4.Slot ("setValue(int)"));
         Qt4.Objects.Connect
          (Force,
           Qt4.Signal ("valueChanged(int)"),
           Self.Cannon_Field,
           Qt4.Slot ("setForce(int)"));
         Qt4.Objects.Connect
          (Self.Cannon_Field,
           Qt4.Signal ("forceChanged(int)"),
           Force,
           Qt4.Slot ("setValue(int)"));

         Qt4.Objects.Connect
          (Self.Cannon_Field,
           Qt4.Signal ("hit()"),
           Self,
           Qt4.Slot ("hit()"));
         Qt4.Objects.Connect
          (Self.Cannon_Field,
           Qt4.Signal ("missed()"),
           Self,
           Qt4.Slot ("missed()"));
         Qt4.Objects.Connect
          (Shoot,
           Qt4.Signal ("clicked()"),
           Self,
           Qt4.Slot ("fire()"));
         Qt4.Objects.Connect
          (Self.Cannon_Field,
           Qt4.Signal ("canShoot(bool)"),
           Shoot,
           Qt4.Slot ("setEnabled(bool)"));
         Qt4.Objects.Connect
          (Restart,
           Qt4.Signal ("clicked()"),
           Self,
           Qt4.Slot ("newGame()"));

         Top_Layout.Add_Widget (Shoot);
         Top_Layout.Add_Widget (Self.Hits);
         Top_Layout.Add_Widget (Hits_Label);
         Top_Layout.Add_Widget (Self.Shots_Left);
         Top_Layout.Add_Widget (Shots_Left_Label);
         Top_Layout.Add_Stretch (1);
         Top_Layout.Add_Widget (Restart);

         Left_Layout.Add_Widget (Angle);
         Left_Layout.Add_Widget (Force);

         Cannon_Layout.Add_Widget (Self.Cannon_Field);
         Cannon_Box.Set_Layout (Cannon_Layout);

         Grid_Layout.Add_Widget (Quit, 0, 0);
         Grid_Layout.Add_Layout (Top_Layout, 0, 1);
         Grid_Layout.Add_Layout (Left_Layout, 1, 0);
         Grid_Layout.Add_Widget (Cannon_Box, 1, 1, 2, 1);
         Grid_Layout.Set_Column_Stretch (1, 10);
         Self.Set_Layout (Grid_Layout);

         Angle.Set_Value (60);
         Force.Set_Value (25);
         Angle.Set_Focus;

         Self.New_Game;

         return Self;
      end Create;

   end Constructors;

   ----------
   -- Fire --
   ----------

   procedure Fire (Self : not null access Game_Board'Class) is
   begin
      if Self.Cannon_Field.Game_Over or Self.Cannon_Field.Is_Shooting then
         return;
      end if;

      Self.Shots_Left.Display (Self.Shots_Left.Int_Value - 1);
      Self.Cannon_Field.Shoot;
   end Fire;

   ---------
   -- Hit --
   ---------

   procedure Hit (Self : not null access Game_Board'Class) is
   begin
      Self.Hits.Display (Self.Hits.Int_Value + 1);

      if Self.Shots_Left.Int_Value = 0 then
         Self.Cannon_Field.Set_Game_Over;

      else
         Self.Cannon_Field.New_Target;
      end if;
   end Hit;

   ------------
   -- Missed --
   ------------

   procedure Missed (Self : not null access Game_Board'Class) is
   begin
      if Self.Shots_Left.Int_Value = 0 then
         Self.Cannon_Field.Set_Game_Over;
      end if;
   end Missed;

   --------------
   -- New_Game --
   --------------

   procedure New_Game (Self : not null access Game_Board'Class) is
   begin
      Self.Shots_Left.Display (15);
      Self.Hits.Display (0);
      Self.Cannon_Field.Restart_Game;
      Self.Cannon_Field.New_Target;
   end New_Game;

end Game_Boards;
