/*
 *  psychlops_figure_prototype.cpp
 *  Psychlops Standard Library (Universal)
 *
 *  Last Modified 2009/02/15 by Kenchi HOSOKAWA
 *  (C) 2009 Kenchi HOSOKAWA, Kazushi MARUYA, Takao SATO
 */

#include "psychlops_widget.h"

namespace Psychlops {


namespace Widgets {



	// WidgetBase
	WidgetBase::WidgetBase() { parent_ = 0; }
	Rectangle WidgetBase::getArea() { return area; }
	Events::Container& WidgetBase::getParent() { return *parent_; }
	Events::Container& WidgetBase::setParent(Events::Container &par) { parent_ = &par; return *parent_; }
	Events::Dispatcher& WidgetBase::getSlots() { return slots_; }
	void WidgetBase::distribute(Event &ev) { getSlots().emit(ev); }
	void WidgetBase::distribute(Events::PointerDeviceEvent &ev) { getSlots().emit(ev); }
	void WidgetBase::tabStop(bool on_off)
	{
		Events::AddToTabstopList list(this);
		bubble(list);
	}





	// Deplecated Widgets

	Theme Theme::current;
	bool Theme::initialized__ = false;
	Image Theme::default_button, Theme::default_horiz_grad;
	/*
	Theme::Theme(Color c1, Color c2, Stroke s1, Stroke s2)
	{
		normal_background = c1;
		over_background = c2;
		normal_stroke = s1;
		active_stroke = s2;
	}
	*/
	void Theme::initialize()
	{
		if(!initialized__) {
			for(int i=0; i<2; i++) {
				Theme::current.normal_foreground[i] = Color::black;
				Theme::current.active_foreground[i] = Color::black;
				Theme::current.normal_background[i] = Color(.85,.85,.85,.5);
				Theme::current.active_background[i] = Color(.70,1.0,.85,.65);
				Theme::current.over_background[i] = Color(.5,.5,1.0,.5);
				Theme::current.normal_stroke[i] = Stroke(Color(.35,.35,.35,.75), 1, Stroke::SOLID);
				Theme::current.active_stroke[i] = Stroke(Color(.35,.35,.35,.75), 2, Stroke::SOLID);
			}
			Theme::current.normal_background[ALERT] = Color(.8,.2,.1,.5);
			Theme::current.over_background[ALERT] = Color(1,.25,0,.5);

			default_button.set(1,20, Image::RGBA);
			for(int y= 0; y< 5; y++) { double level = 0.5-y*0.1; default_button.pix(0,y,Color::white); default_button.alpha(0,y,level); }
			for(int y= 5; y<15; y++) { default_button.pix(0,y,Color::white); default_button.alpha(0,y,0.1); }
			for(int y=15; y<20; y++) { double level = (y-14)*0.075; default_button.pix(0,y,Color(.8,.8,.8)); default_button.alpha(0,y,level); }
			Theme::current.button_back = &Theme::default_button;
			default_horiz_grad.set(40,1, Image::RGBA);
			for(int x= 0; x<15; x++) { double level = 0.25-x*0.01; default_horiz_grad.pix(x,0,Color::white); default_horiz_grad.alpha(x,0,level); }
			for(int x=15; x<35; x++) { default_horiz_grad.pix(x,0,Color::white); default_horiz_grad.alpha(x,0,0.1); }
			for(int x=35; x<40; x++) { double level = (x-33)*0.075; default_horiz_grad.pix(x,0,Color(.8,.8,.8)); default_horiz_grad.alpha(x,0,level); }
			Theme::current.horiz_grad = &Theme::default_horiz_grad;
			initialized__ = true;
		}
	}

	Point drawableMouse(Drawable &d){
		Canvas *cnvs = dynamic_cast<Canvas*>(&d);
		return (cnvs!=0) ? cnvs->mouse() : (Point)Mouse::uniPosition;
	}



	WidgetDatum::WidgetDatum() : datum(0,0,0) {}
	WidgetDatum::~WidgetDatum() {}
	const Point WidgetDatum::getDatum() const {
		return datum;
	}
	WidgetDatum& WidgetDatum::setDatum(const Point& p) {
		datum = p;
		return *this;
	}
	WidgetDatum& WidgetDatum::centering(const Point & p) {
		datum = p;
		return *this;
	}

	WidgetRect::WidgetRect()
	: mleft(Mouse::left), pressFrame(-1), tabStopRegistered(false)
	{
Theme::initialize();
		theme = &Theme::current;
		theme_type = Theme::NORMAL;
		pushed_ = false;
	}
	const Point WidgetRect::getDatum() const { return area.getDatum(); }
	WidgetRect& WidgetRect::setDatum(const Point& p) { area.setDatum(p); return *this; }
	WidgetRect& WidgetRect::centering(const Point& p) { area.centering(p); return *this; }

	double WidgetRect::getWidth() const { return area.getWidth(); }
	double WidgetRect::getHeight() const { return area.getHeight(); }
	double WidgetRect::getLeft() const { return area.getLeft(); }
	double WidgetRect::getTop() const { return area.getTop(); }
	double WidgetRect::getRight() const { return area.getRight(); }
	double WidgetRect::getBottom() const { return area.getBottom(); }
	WidgetRect& WidgetRect::alignLeft(const double lef) { area.alignLeft(lef); return *this; }
	WidgetRect& WidgetRect::alignTop(const double to_) { area.alignTop(to_); return *this; }
	WidgetRect& WidgetRect::alignRight(const double rig) { area.alignRight(rig); return *this; }
	WidgetRect& WidgetRect::alignBottom(const double bot) { area.alignBottom(bot); return *this; }

	WidgetRect& WidgetRect::set(double wid, double hei)
	{
		area.set(wid, hei);
		double size = hei-4;
		label.font.size = (size>0) ? size : Font::default_font.size;
		return *this;
	}
	WidgetRect& WidgetRect::set(std::wstring name)
	{
		return set(name, Font::default_font.size);
	}
	WidgetRect& WidgetRect::set(std::wstring name, double hei)
	{
		double size = hei-4;
		label.font.size = (size>0) ? size : Font::default_font.size;
		label.setString(name);
		area.set(hei*label.str.length(), hei);
		return *this;
	}
	WidgetRect& WidgetRect::setLabel(std::wstring s)
	{
		double size = area.getHeight()-4;
		label.font.size = (size>5 && size<40) ? size : Font::default_font.size;
		label.setString(s);
		label.fill = theme->normal_foreground[theme_type];
		return *this;
	}
	WidgetRect& WidgetRect::draw(Drawable &target)
	{
		return *this;
	}
	bool WidgetRect::pushed()
	{
		bool v = pushed_;
		pushed_ = false;
		return v;
	}
	WidgetRect& WidgetRect::pushThis()
	{
		pushed_ = true;
		return *this;
	}
	
	int  WidgetRect::__LAST_TOTAL_REFRESH = 0;
	double WidgetRect::__autoAlign_ = 10.0;
	void WidgetRect::__autoAlign(WidgetRect &target)
	{
		/*
		if(Display::the_canvas!=0) {
			if(__LAST_TOTAL_REFRESH!=Display::the_canvas->TOTAL_REFRESH) {
				__LAST_TOTAL_REFRESH = Display::the_canvas->TOTAL_REFRESH;
				__autoAlign_ = 0.0;
			}
		}*/
		
		target.area.shift(10, __autoAlign_);
		__autoAlign_ += target.area.getHeight() + 10;
	}

	

	StackPanel::StackPanel()
	{
		orientation = VERTICAL;
		pitch = 2;
	}
	StackPanel& StackPanel::setWidth(double wid)
	{
		area.set(wid, area.getHeight());
		forceBase = true;
		return *this;
	}
	StackPanel& StackPanel::setHeight(double hei)
	{
		area.set(area.getWidth(), hei);
		forceBase = true;
		return *this;
	}
	StackPanel& StackPanel::append(WidgetRect *target1, WidgetRect *target2, WidgetRect *target3, WidgetRect *target4, WidgetRect *target5)
	{
		if(target1!=0) { content.push_back(target1); }
		if(target2!=0) { content.push_back(target2); }
		if(target3!=0) { content.push_back(target3); }
		if(target4!=0) { content.push_back(target4); }
		if(target5!=0) { content.push_back(target5); }
		return *this;
	}
	StackPanel& StackPanel::remove(WidgetRect *target)
	{
		for(std::deque<WidgetRect *>::iterator i = content.begin(); i != content.end(); i++) {
			if( *i == target ) {
				content.erase(i);
				break;
			}
		}
		return *this;
	}
	void StackPanel::align(Orientation ori)
	{
		orientation = ori;
		double dleft = getLeft(), dtop = getTop();
		switch(orientation) {
		case VERTICAL:
			if(!content.empty()) {
				for(int i=0; i<content.size(); i++) {
					content[i]->area.set(area.getWidth(), content[i]->area.getHeight());
					content[i]->alignLeft(dleft);
					content[i]->alignTop(dtop);
					dtop += content[i]->getHeight() + pitch;
				}
			}
			break;
		case HORIZONTAL:
		default:
			if(!content.empty()) {
				for(int i=0; i<content.size(); i++) {
					content[i]->alignLeft(dleft);
					content[i]->alignTop(dtop);
					dleft += content[i]->getWidth() + pitch;
				}
			}
			break;
		}
	}

	StackPanel& StackPanel::draw(Drawable &target)
	{
		double dleft = getLeft(), dtop = getTop();
		switch(orientation) {
		case VERTICAL:
			if(!content.empty()) {
				for(int i=0; i<content.size(); i++) {
					content[i]->area.set(area.getWidth(), content[i]->area.getHeight());
					content[i]->alignLeft(dleft);
					content[i]->alignTop(dtop);
					content[i]->draw(target);
					dtop += content[i]->getHeight() + pitch;
				}
			}
			break;
		case HORIZONTAL:
		default:
			if(!content.empty()) {
				for(int i=0; i<content.size(); i++) {
					content[i]->alignLeft(dleft);
					content[i]->alignTop(dtop);
					content[i]->draw(target);
					dleft += content[i]->getWidth() + pitch;
				}
			}
			break;
		}
		return *this;
	}


	StackPanel StackPanel::default_stack;


}	/*	<- namespace Widgets 	*/
}	/*	<- namespace Psycholops 	*/


