// ******************************************************
// *                                                    *
// *  container.C (MP3)                                 *
// *                                                    *
// *  Implementation for an abstract container class    * 
// *                                                    *
// *  Written 13 February 1999 by Jason Zych            *
// *                                                    *
// ******************************************************

#include <stddef.h>
#include "container.h"


// Container
//    - default constructor
//    - initializes object to have default values
Container::Container() : Component()
{
   compArray.SetBounds(1, 1);
   compArray[1] = NULL;  
   lastCompAdded = 0;
}


// Container
//    - copy constructor
//    - parameters : origVal - previously allocated Container object
//    - initializes object to be a copy of origVal
Container::Container(const Container& origVal)
{
   compArray.SetBounds(origVal.compArray.Lower(), origVal.compArray.Upper());
   for (int i = compArray.Lower(); i<=compArray.Upper(); i++)
   {
      if (origVal.compArray[i] != NULL)
         compArray[i] = origVal.compArray[i]->Clone();
      else
         compArray[i] = NULL;
   } 
   lastCompAdded = origVal.lastCompAdded;
}



// ~Container
//    - destructor
//    - deletes dynamically allocated memory
Container::~Container()
{
   for (int i = compArray.Lower(); i<=compArray.Upper(); i++)
      delete compArray[i]; 
}




// operator=
//    - parameters : origVal - previously allocated Container object
//    - return value : reference to this object
//    - sets object to be a copy of origVal
Container& Container::operator=(const Container& origVal)
{
   if (this!=&origVal)
   {
      for (int i = compArray.Lower(); i<=compArray.Upper(); i++)
         delete compArray[i]; 
      compArray.SetBounds(origVal.compArray.Lower(), origVal.compArray.Upper());
      for (i = compArray.Lower(); i<=compArray.Upper(); i++)
      {
         if (origVal.compArray[i] != NULL)
            compArray[i] = origVal.compArray[i]->Clone();
         else
            compArray[i] = NULL; 
      }
      lastCompAdded = origVal.lastCompAdded;
   }
   return *this;
}





// SetSize
//    - parameters : width - the width (x-range) this object should have
//                 : height - the height (y-range) this object should have
//    - sets interior data so that the appropriate width and height
//        are represented. Appropriately change size and location for
//        all interior components
void Container::SetSize(int width, int height)
{
   Component::SetSize(width, height);

   int componentWidth = width/compArray.Size();

   for (int i = compArray.Lower(); i<=lastCompAdded; i++)
   {
      compArray[i]->SetSize(componentWidth, height);
      compArray[i]->SetLocation(lowerLeftX + (i-compArray.Lower())*componentWidth,
				   lowerLeftY);
   }
}



// SetLocation
//    - parameters : xLoc - x-location of new point
//                 : yLoc - y-location of new point
//    - sets interior data so that lower-left-hand corner of component
//        is at parameter location. Appropriately change location of
//        all interior components.
void Container::SetLocation(int xLoc, int yLoc)
{
   Component::SetLocation(xLoc, yLoc);
   int componentWidth = (upperRightX - lowerLeftX)/compArray.Size();
   for (int i = compArray.Lower(); i<=lastCompAdded; i++)
   {
      compArray[i]->SetLocation(lowerLeftX + (i-compArray.Lower())*componentWidth,
                                   lowerLeftY);
   }
}



// SetNumComponents
//    - parameters : numComponents - the number of components
//                        you wish to add to this container
//    - container adjusted to have space for numComponents components
//       If this results in not enough space for all current components,
//       the extra components are deleted.
void Container::SetNumComponents(int numComponents)
{
   if (numComponents < compArray.Size())
   {
      for (int i = compArray.Lower() + numComponents; i<=compArray.Upper(); i++)
         delete compArray[i];
      compArray.SetBounds(compArray.Lower(), compArray.Lower() + numComponents - 1);
   }
   else if (numComponents > compArray.Size())
   {
      compArray.SetBounds(compArray.Lower(), compArray.Lower() + numComponents - 1);
      for (int i = lastCompAdded + 1; i <= compArray.Upper(); i++)
         compArray[i] = NULL;
   }
   SetSize(upperRightX - lowerLeftX, upperRightY - lowerLeftY);
}



// Add
//    - parameters : newestComp - a pointer to a component to add to 
//                                  the container
//    - adds component to container and returns 0; if container is 
//                full, component is deleted and -1 is returned
int Container::Add(Component* newestComp)
{
   if (compArray.Size() == lastCompAdded)
   {
      delete newestComp;
      return -1;
   }
   else
   {
      lastCompAdded++;
      compArray[lastCompAdded] = newestComp;

      int componentWidth = (upperRightX - lowerLeftX)/compArray.Size();
      int componentLength = upperRightY - lowerLeftY;
      compArray[lastCompAdded]->SetLocation(lowerLeftX + 
            (lastCompAdded-compArray.Lower())*componentWidth, lowerLeftY);
      compArray[lastCompAdded]->SetSize(componentWidth, componentLength); 
      return 1;
   }
}
  


// HandleMouseClick
//    - parameters : locationPoint - location of mouse click
//    - processes the "mouse click" event. If mouse click is on
//        an object that does not support any mouse-click-activated
//        operations, then nothing will happen.
void Container::HandleMouseClick(Point locationPoint)
{
   if (Contains(locationPoint))
   {
      int width = upperRightX - lowerLeftX;
      int componentWidth = width/compArray.Size();
      int offset = locationPoint.XCoord() - lowerLeftX; 
      int index = compArray.Lower();
      while ((index+1-compArray.Lower())*componentWidth < offset)
         index++;
      compArray[index]->HandleMouseClick(locationPoint);
   }
}



// DrawHelper()
//    - draws all components
void Container::DrawHelper()
{
   for (int i = compArray.Lower(); i<=compArray.Upper(); i++)
      if (compArray[i] != NULL)
         compArray[i]->Draw();
}
 


