/*!
  \file
  \brief 描画レイヤー

  \author Satofumi KAMIMURA

  $Id: Layer.cpp 1811 2010-04-30 16:12:05Z satofumi $
*/

#include "Layer.h"
#include "Component.h"
#include "Screen.h"
#include <boost/bind.hpp>
#include <algorithm>
#include <list>

using namespace qrk;
using namespace std;


namespace
{
    typedef list<Component*> Components;
}


struct Layer::pImpl
{
    Components components_;
    Rect<long> draw_area_;
    float alpha_;


    pImpl(void) : alpha_(1.0)
    {
        Screen screen;
        draw_area_ = screen.rect();
    }


    void setAlpha(float alpha)
    {
        for_each(components_.begin(), components_.end(),
                 bind(&Component::setAlpha, _1, alpha));
        alpha_ = alpha;
    }


    float alpha(void) const
    {
        return alpha_;
    }


    void draw(void)
    {
        for_each(components_.begin(), components_.end(),
                 bind(&Component::draw, _1, draw_area_));
    }
};


Layer::Layer(void) : pimpl(new pImpl)
{
}


Layer::~Layer(void)
{
}


void Layer::clear(void)
{
    pimpl->components_.clear();
}


void Layer::push_front(Component* component)
{
    const Components::iterator it =
        find(pimpl->components_.begin(), pimpl->components_.end(), component);
    if (it == pimpl->components_.end()) {
        pimpl->components_.push_back(component);
    }
}


void Layer::push_back(Component* component)
{
    const Components::iterator it =
        find(pimpl->components_.begin(), pimpl->components_.end(), component);
    if (it == pimpl->components_.end()) {
        pimpl->components_.push_front(component);
    }
}


void Layer::remove(Component* component)
{
    pimpl->components_.remove(component);
}


void Layer::setAlpha(float alpha)
{
    float adjusted_alpha = min(alpha, 1.0f);
    pimpl->setAlpha(adjusted_alpha);
}


float Layer::alpha(void) const
{
    return pimpl->alpha();
}


void Layer::draw(void)
{
    pimpl->draw();
}
