-- $Date: 2004/03/08 10:42:42 $
-- $Revision: 1.9 $
-- $Author: jcrocholl $
-- $Hash: 4ec17940ab0e8c7cf67d2bf772cb4a1d $

-- This file was automatically created with ado.php.
-- Manual changes will be lost when it is updated.

with Gray_Images; use Gray_Images;
with Integer_Strings; use Integer_Strings;
with Enum_Strings; use Enum_Strings;
with Messages; use Messages;

package body Boxes.Measures is

   -- Constructor for instances.
   function Create
     return Measure_Box_Access -- The newly created measure box.
   is
      Result : Measure_Box_Access := new Measure_Box;
   begin
      Result.Times := Time_Lists.Create;
      Result.Chords := Chord_Lists.Create;
      return Result;
   end Create;

   -- Mutator to update the clef of a measure box.
   procedure Set_Clef
     (This : access Measure_Box;    -- The measure box to be updated.
      Clef : in Clef_Box_Access) is -- The new clef of that measure box.
   begin
      This.Clef := Clef;
   end Set_Clef;

   -- Accessor to read the clef of a measure box.
   function Get_Clef
     (This : access Measure_Box-- The measure box to read from.
     return Clef_Box_Access is   -- The clef of that measure box.
   begin
      return This.Clef;
   end Get_Clef;

   -- Mutator to update the key of a measure box.
   procedure Set_Key
     (This : access Measure_Box;   -- The measure box to be updated.
      Key  : in Key_Box_Access) is -- The new key of that measure box.
   begin
      This.Key := Key;
   end Set_Key;

   -- Accessor to read the key of a measure box.
   function Get_Key
     (This : access Measure_Box-- The measure box to read from.
     return Key_Box_Access is    -- The key of that measure box.
   begin
      return This.Key;
   end Get_Key;

   -- Accessor to read the times of a measure box.
   function Get_Times
     (This : access Measure_Box-- The measure box to read from.
     return Time_List_Access is  -- The times of that measure box.
   begin
      return This.Times;
   end Get_Times;

   -- Mutator to update the arc of a measure box.
   procedure Set_Arc
     (This : access Measure_Box;   -- The measure box to be updated.
      Arc  : in Arc_Box_Access) is -- The new arc of that measure box.
   begin
      This.Arc := Arc;
   end Set_Arc;

   -- Accessor to read the arc of a measure box.
   function Get_Arc
     (This : access Measure_Box-- The measure box to read from.
     return Arc_Box_Access is    -- The arc of that measure box.
   begin
      return This.Arc;
   end Get_Arc;

   -- Accessor to read the chords of a measure box.
   function Get_Chords
     (This : access Measure_Box-- The measure box to read from.
     return Chord_List_Access is -- The chords of that measure box.
   begin
      return This.Chords;
   end Get_Chords;

   -- Mutator to update the barline of a measure box.
   procedure Set_Barline
     (This    : access Measure_Box;   -- The measure box to be updated.
      Barline : in Bar_Style_Enum) is -- The new barline of that measure box.
   begin
      This.Barline := Barline;
   end Set_Barline;

   -- Accessor to read the barline of a measure box.
   function Get_Barline
     (This : access Measure_Box-- The measure box to read from.
     return Bar_Style_Enum is    -- The barline of that measure box.
   begin
      return This.Barline;
   end Get_Barline;

   procedure Add_Time
     (This : access Measure_Box-- The measure box object instance.
      Add  : access Time_Box) is -- Add this time signature.
   begin
      Time_Lists.Push(This.Times, Time_Box_Access(Add));
   end Add_Time;

   procedure Add_Chord
     (This : access Measure_Box;  -- The measure box object instance.
      Add  : access Chord_Box) is -- Add this chord.
   begin
      Chord_Lists.Push(This.Chords, Chord_Box_Access(Add));
   end Add_Chord;

   procedure Layout
     (This : access Measure_Box-- The measure box object instance.
      Font : access Font_Loader-- Use this font loader.
   is
      Space  : constant Real := 50.0;
      Cursor : Vector;

      use Time_Lists;
      Time : Time_Box_Access;

      use Chord_Lists;
      Chord : Chord_Box_Access;
   begin
      if not Quiet then Debug("preparing measure layout"); end if;

      Cursor := (0.0, 0.0);
      This.Minimum_Width := 0.0;
      This.Optimum_Width := 0.0;

      if This.Clef /= null then
         Layout(This.Clef, Font);

         Cursor.X := Cursor.X + Space;
         Cursor.X := Cursor.X - Get_Left(This.Clef);
         Set_Center(This.Clef, Cursor);
         Cursor.X := Cursor.X + Get_Right(This.Clef);
         Cursor.X := Cursor.X + Space;

         Add_Width(This, This.Clef);
         Max_Bounds(This, This.Clef);
      end if;

      if This.Key /= null then
         Layout(This.Key, Font);

         Cursor.X := Cursor.X + Space;
         Cursor.X := Cursor.X - Get_Left(This.Key);
         Set_Center(This.Key, Cursor);
         Cursor.X := Cursor.X + Get_Right(This.Key);
         Cursor.X := Cursor.X + Space;

         Add_Width(This, This.Key);
         Max_Bounds(This, This.Key);
      end if;

      Reset(This.Times);
      while Next(This.Times) loop
         Time := Current(This.Times);
         Layout(Time, Font);

         Cursor.X := Cursor.X + Space;
         Cursor.X := Cursor.X - Get_Left(Time);
         Set_Center(Time, Cursor);
         Cursor.X := Cursor.X + Get_Right(Time);
         Cursor.X := Cursor.X + Space;

         Add_Width(This, Time);
         Max_Bounds(This, Time);
      end loop;

      if This.Arc /= null then
         Layout(This.Arc, Font);
         Add_Width(This, This.Arc);
      end if;

      Reset(This.Chords);
      while Next(This.Chords) loop
         Chord := Current(This.Chords);
         Layout(Chord, Font);

         Cursor.X := Cursor.X + Space;
         Cursor.X := Cursor.X - Get_Left(Chord);
         Set_Center(Chord, Cursor);
         Cursor.X := Cursor.X + Get_Right(Chord);
         Cursor.X := Cursor.X + Space;

         Add_Width(This, Chord);
         Max_Bounds(This, Chord);
      end loop;

      case This.Barline is
      when Regular =>
         Cursor.X := Cursor.X + 100.0;
      when Light_Light =>
         Cursor.X := Cursor.X + 200.0;
      when others => null;
      end case;

      This.Bounds.Left := 0.0;
      This.Bounds.Right := Cursor.X;
      -- Debug("measure bounds: " & To_String(This.Bounds));
   end Layout;

   procedure Print
     (This   : access Measure_Box;        -- The measure box object instance.
      To     : access Printer'Class-- Write to this printer.
      Center : in Vector)                 -- Center of container.
   is
      use Chord_Lists;
      use Time_Lists;
   begin
      if This.Clef /= null then
         Print(This.Clef, To, Center + This.Center);
      end if;

      if This.Key /= null then
         Print(This.Key, To, Center + This.Center);
      end if;

      if not Quiet then Debug("printing times"); end if;
      Reset(This.Times);
      while Next(This.Times) loop
         Print(Current(This.Times), To, Center + This.Center);
      end loop;

      if This.Arc /= null then
         Print(This.Arc, To, Center + This.Center);
      end if;

      if not Quiet then Debug("printing chords"); end if;
      Reset(This.Chords);
      while Next(This.Chords) loop
         Print(Current(This.Chords), To, Center + This.Center);
      end loop;

      case This.Barline is
      when Regular =>
         Fill_Box(To, (
           This.Bounds.Right - Bar_Line_Width, -200.0,
           This.Bounds.Right, 200.0) + Center + This.Center, Black);
      when Light_Light =>
         -- Debug("printing light-light");
         Fill_Box(To, (
           This.Bounds.Right - Bar_Line_Width - 60.0, -200.0,
           This.Bounds.Right - 60.0, 200.0) + Center + This.Center, Black);
         Fill_Box(To, (
           This.Bounds.Right - Bar_Line_Width, -200.0,
           This.Bounds.Right, 200.0) + Center + This.Center, Black);
      when others => null;
      end case;

      -- Print_Bounds(To, This.Bounds + Center + This.Center);
   end Print;

end Boxes.Measures;