/*  $Id: button_silver.cpp,v 1.16 2004/02/18 14:47:54 sphair Exp $
**
**  ClanLib Game SDK
**  Copyright (C) 2003  The ClanLib Team
**  For a total list of contributers see the file CREDITS.
**
**  This library is free software; you can redistribute it and/or
**  modify it under the terms of the GNU Lesser General Public
**  License as published by the Free Software Foundation; either
**  version 2.1 of the License, or (at your option) any later version.
**
**  This library is distributed in the hope that it will be useful,
**  but WITHOUT ANY WARRANTY; without even the implied warranty of
**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
**  Lesser General Public License for more details.
**
**  You should have received a copy of the GNU Lesser General Public
**  License along with this library; if not, write to the Free Software
**  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
**
*/

#include "API/Display/display.h"
#include "API/Display/surface.h"
#include "API/Display/font.h"
#include "API/GUI/gui_manager.h"
#include "API/GUIStyleSilver/stylemanager_silver.h"
#include "API/GUIStyleSilver/button_silver.h"
#include "API/Core/Resources/resource_manager.h"
#include "API/Core/Math/rect.h"
#include "API/Core/XML/dom_element.h"

/////////////////////////////////////////////////////////////////////////////
// Construction:

CL_Button_Silver::CL_Button_Silver(
	CL_Button *button,
	CL_StyleManager_Silver *style)
:
	CL_ComponentStyle(button),
	button(button),
	style(style),
	font(0),
	font_disabled(0),
	delete_font(false),
	delete_font_disabled(false),
	sur_up(0), 
	sur_down(0),
	sur_highlighted(0),
	sur_disabled(0), 
	delete_sur_up(false),
	delete_sur_down(false),
	delete_sur_highlighted(false),
	delete_sur_disabled(false)
{
	resources = style->get_resources();

	if(resources->exists("Button/surface_up"))
		set_surface_up(new CL_Surface("Button/surface_up", resources), true);
	if(resources->exists("Button/surface_down"))
		set_surface_down(new CL_Surface("Button/surface_down", resources), true);
	if(resources->exists("Button/surface_highlighted"))
		set_surface_highlighted(new CL_Surface("Button/surface_highlighted", resources), true);
	if(resources->exists("Button/surface_disabled"))
		set_surface_disabled(new CL_Surface("Button/surface_disabled", resources), true);
	if(resources->exists("Button/font"))
		set_font(new CL_Font("Button/font", resources), true);
	if(resources->exists("Button/font_disabled"))
		set_font_disabled(new CL_Font("Button/font_disabled", resources), true);

	slot_set_options = button->sig_set_options().connect(
		this, &CL_Button_Silver::on_set_options);
	slot_paint = button->sig_paint().connect(
		this, &CL_Button_Silver::on_paint);
	slot_get_preferred_size = button->sig_get_preferred_size().connect(
		this, &CL_Button_Silver::on_get_preferred_size);
}

CL_Button_Silver::~CL_Button_Silver()
{
	if(delete_font && font)
		delete font;
	if(delete_font_disabled && font_disabled)
		delete font_disabled;
	if(delete_sur_up && sur_up)
		delete sur_up;
	if(delete_sur_down && sur_down)
		delete sur_down;
	if(delete_sur_highlighted && sur_highlighted)
		delete sur_highlighted;
	if(delete_sur_disabled && sur_disabled)
		delete sur_disabled;
}

/////////////////////////////////////////////////////////////////////////////
// Operations:

void CL_Button_Silver::set_font(CL_Font *_font, bool _delete_font)
{
	if(delete_font && font)
		delete font;
	font = _font;
	delete_font = _delete_font;
}

void CL_Button_Silver::set_font_disabled(CL_Font *_font, bool _delete_font)
{
	if(delete_font_disabled && font_disabled)
		delete font_disabled;
	font_disabled = _font;
	delete_font_disabled = _delete_font;
}

void CL_Button_Silver::set_surface_up(CL_Surface *surface, bool delete_surface)
{
	if(delete_sur_up && sur_up)
		delete sur_up;
	sur_up = surface;
	delete_sur_up = delete_surface;
}

void CL_Button_Silver::set_surface_down(CL_Surface *surface, bool delete_surface)
{
	if(delete_sur_down && sur_down)
		delete sur_down;
	sur_down = surface;
	delete_sur_down = delete_surface;
}

void CL_Button_Silver::set_surface_highlighted(CL_Surface *surface, bool delete_surface)
{
	if(delete_sur_highlighted && sur_highlighted)
		delete sur_highlighted;
	sur_highlighted = surface;
	delete_sur_highlighted = delete_surface;
}

void CL_Button_Silver::set_surface_disabled(CL_Surface *surface, bool delete_surface)
{
	if(delete_sur_disabled && sur_disabled)
		delete sur_disabled;
	sur_disabled = surface;
	delete_sur_disabled = delete_surface;
}

void CL_Button_Silver::set_scrollbar_increase_mode()
{
}

void CL_Button_Silver::set_scrollbar_decrease_mode()
{
}

/////////////////////////////////////////////////////////////////////////////
// Callbacks:

void CL_Button_Silver::on_set_options(const CL_DomElement &options)
{
	if (options.has_attribute("surface_up"))
		set_surface_up(new CL_Surface(options.get_attribute("surface_up"), resources), true);
	if (options.has_attribute("surface_down"))
		set_surface_down(new CL_Surface(options.get_attribute("surface_down"), resources), true);
	if (options.has_attribute("surface_disabled"))
		set_surface_disabled(new CL_Surface(options.get_attribute("surface_disabled"), resources), true);
	if (options.has_attribute("surface_highlighted"))
		set_surface_highlighted(new CL_Surface(options.get_attribute("surface_highlighted"), resources), true);
	if (options.has_attribute("font"))
		set_font(new CL_Font(options.get_attribute("font"), resources), true);
	if (options.has_attribute("font_disabled"))
		set_font_disabled(new CL_Font(options.get_attribute("font_disabled"), resources), true);
}

void CL_Button_Silver::on_get_preferred_size(CL_Size &size)
{
	if(sur_up)
	{
		size.width = sur_up->get_width();
		size.height = sur_up->get_height();
	}
	else
	{
		if(font)
		{
			size.width = font->get_width(button->get_text()) + 8;
			size.height = font->get_height() + 4;
		}
	}
}

void CL_Button_Silver::on_paint()
{
	int text_width = 0;
	int text_height = 0;

	if(font)
	{
		text_width = font->get_width(button->get_text().c_str());
		text_height = font->get_height();
	}

	int button_width = button->get_width();
	int button_height = button->get_height();

	int x_pos = (button_width - text_width) / 2;
	int y_pos = (button_height - text_height) / 2;

	int width = button->get_width();
	int height = button->get_height();

	if(button->is_enabled() == false)
	{
		if(sur_disabled)
			sur_disabled->draw(0, 0);
		else
			CL_Display::draw_rect(CL_Rect(0, 0, width, height), CL_Color(128, 142, 159));

		if(font_disabled)
			font_disabled->draw(x_pos, y_pos, button->get_text());
		else if(font)
			font->draw(x_pos, y_pos, button->get_text());
	}
	else 
	{
		if(button->is_drawn_down())
		{
			if(sur_down)
				sur_down->draw(0, 0);
			else
			{
				CL_Display::fill_rect(
					CL_Rect(2, 2, width, height), 
					CL_Gradient(CL_Color::white, CL_Color::white, CL_Color(230, 235, 240), CL_Color(230, 235, 240)));

				CL_Display::fill_rect(
					CL_Rect(4, 4, width - 2, height - 2),
					CL_Gradient(CL_Color(212, 217, 222), CL_Color(212, 217, 222), CL_Color(250,250,250), CL_Color(250,250,250)));

				CL_Display::draw_rect(CL_Rect(1, 1, width, height), CL_Color(73, 94, 120));
				CL_Display::draw_rect(CL_Rect(0, 0, width, height), CL_Color(128, 142, 159));
			}

			if(font)
				font->draw(x_pos + 1, y_pos + 1, button->get_text());
		}
		else
		{
			bool need_highlight = false;
			if (button->has_mouse_over())
				if (!button->get_gui_manager() ||
					(!button->get_gui_manager()->get_modal_component() ||
					button->has_modal_parent()))
					need_highlight = true;

			if(sur_highlighted && need_highlight)
				sur_highlighted->draw(0, 0);
			else if(sur_up)
				sur_up->draw(0, 0);
			else
			{
				CL_Display::draw_rect(CL_Rect(0, 0, width, height), CL_Color(128, 142, 159));

				CL_Display::fill_rect(
					CL_Rect(1, 1, width - 1, height - 1), 
					CL_Gradient(CL_Color::white, CL_Color::white, CL_Color(230, 235, 240), CL_Color(230, 235, 240)));

				CL_Display::fill_rect(
					CL_Rect(3, 3, width - 3, height - 3),
					CL_Gradient(CL_Color(217, 222, 227), CL_Color(217, 222, 227), CL_Color::white, CL_Color::white));

				// Focus
				if(button->has_focus())
				{
					CL_Display::draw_rect(
						CL_Rect(2, 2, width - 2, height - 2), CL_Color(254, 207, 147));
					CL_Display::draw_rect(
						CL_Rect(3, 3, width - 3, height - 3), CL_Color(255, 147, 22));
				}
			}

			if(font)
				font->draw(x_pos, y_pos, button->get_text());
		}
	}
}
