// ------------------------------------------------------------------------
/*
	author: Jaap Suter
   
	Copyright (C) Electronic Arts Canada Inc. 2002.  All rights reserved.	
*/
// ------------------------------------------------------------------------

/*! \file */

#ifndef REVEAL_COLOR_CONTROL_H
#define REVEAL_COLOR_CONTROL_H

#include "reveal/renderer.h"
#include "reveal/color.h"
#include "reveal/input_state.h"

#include "reveal/impl/widget.h"
#include "reveal/impl/gui_metrics.h"
#include "reveal/impl/util.h"

#include "reveal/callback/callback_0.h"
#include "reveal/callback/callback_1.h"

namespace Reveal {

	namespace Impl {
		
		class Tree;	

// -------------------------------------------------------------------------------
/*!
	\brief Color control, gives the user three sliders for RGB or HSV (the user
		   can switch between RGB and HSV), a slider for alpha, and a preview area for the color;
*/
// -------------------------------------------------------------------------------
class ColorControl : public Widget
{
    typedef Callback::Callback1< void, const Color& > CallbackToGame;
	typedef Callback::Callback0< Color				> CallbackFromGame;

public:

	//! Constructor, simply sets the color control in default RGB mode (as opposed to HSV);
    ColorControl( const char* name, Tree& tree, const CallbackToGame& callbackToGame, const CallbackFromGame& callbackFromGame )
		: Widget( name, tree ), mCallbackToGame( callbackToGame ), mCallbackFromGame( callbackFromGame ), mColor(), mType( RGB ), mState( IDLE ) 
	{
		if ( mCallbackFromGame.Valid() ) mColor = mCallbackFromGame();
	}

	//! Returns the width of the control;
	virtual int Width() const { return Impl::GuiMetrics::GetWidgetWidth(); }

	//! Returns the height of the control;
	virtual int Height() const { return NUM_ROWS * Impl::GuiMetrics::GetRowHeight(); }    

private:

	// Copy ctor and assignment operator are disabled;
	ColorControl( const ColorControl& );
	ColorControl& operator = ( const ColorControl& );

	enum
	{
		NUM_ROWS = 5 // Title-bar and sliders for R(H), G(S), B(V) and alpha;
	};

    //! Implementation of pure base virtual;
	virtual void DoRender( const Renderer&, const GuiColors& guiColors ) const;

	//! Implementation of pure base virtual;
	virtual Widget* DoHandle( const InputState& inputState );

	//! Implementation of pure base virtual;
	virtual size_t DoToString( const char* path, char* buffer, size_t size ) const;

	//! Implementation of base virtual;
	virtual void DoFromString( const char* data );

	int LeftArrowX()		const { return X() + GuiMetrics::BORDER_WIDTH + GuiMetrics::GetCharacterWidth() + GuiMetrics::GetArrowBoxSize(); }
	int NumberX()			const { return X() + Width() - GuiMetrics::COLOR_NUMBER_WIDTH - GuiMetrics::BORDER_WIDTH; }
	int RightArrowX()		const { return NumberX() - GuiMetrics::GetArrowBoxSize() - GuiMetrics::BORDER_WIDTH; }
	int SliderY( int i )	const { return Y() + GuiMetrics::BORDER_HEIGHT + (1 + i) * GuiMetrics::GetRowHeight(); }
	int SliderBarX()		const { return LeftArrowX() + GuiMetrics::GetArrowBoxSize(); }
	int SliderBarWidth()	const { return RightArrowX() - SliderBarX(); }
	
	CallbackToGame	 mCallbackToGame;
	CallbackFromGame mCallbackFromGame;
	Color	 mColor;
	enum { RGB, HSV } mType;
    enum 
	{ 
		IDLE, 
		DRAGGING_ALPHA, 
		DRAGGING_RED, 
		DRAGGING_GREEN, 
		DRAGGING_BLUE, 
		NUM_STATES 
	} mState;			//! Important: keep the layout like this, the code depends on it;
};


	} // Namespace Impl;
} // Namespace Reveal;

#endif
