#include "tk_menu.h"

const char* TkMenuSeparator::type="TkMenuSeparator";
const char* TkMenuCommand::type="TkMenuCommand";

TkMenuSeparator TkMenu::separator;

TkMenu::t_menu_map TkMenu::menuMap;
int TkMenu::idGenerator;

const Ptr<TkOptionDef> TkMenu::OPT_ACTIVEBACKGROUND=new TkOptionDef("activebackground",TkColorOption::type);
const Ptr<TkOptionDef> TkMenu::OPT_ACTIVEBORDERWIDTH=new TkOptionDef("activeborderwidth",TkIntOption::type);
const Ptr<TkOptionDef> TkMenu::OPT_ACTIVEFOREGROUND=new TkOptionDef("activeforeground",TkColorOption::type);
const Ptr<TkOptionDef> TkMenu::OPT_BACKGROUND=new TkOptionDef("background",TkColorOption::type);
const Ptr<TkOptionDef> TkMenu::OPT_CURSOR=0;
const Ptr<TkOptionDef> TkMenu::OPT_FONT=0;
const Ptr<TkOptionDef> TkMenu::OPT_FOREGROUND=new TkOptionDef("foreground",TkColorOption::type);
const Ptr<TkOptionDef> TkMenu::OPT_RELIEF=new TkOptionDef("relief",TkReliefOption::type);
const Ptr<TkOptionDef> TkMenu::OPT_SELECTCOLOR=new TkOptionDef("selectcolor",TkColorOption::type);
const Ptr<TkOptionDef> TkMenu::OPT_TAKEFOCUS=0;
const Ptr<TkOptionDef> TkMenu::OPT_TEAROFF=new TkOptionDef("tearoff",TkBoolOption::type);
const Ptr<TkOptionDef> TkMenu::OPT_TEAROFFCOMMAND=0;
const Ptr<TkOptionDef> TkMenu::OPT_TITLE=0;
const Ptr<TkOptionDef> TkMenu::OPT_TYPE=0;

const Ptr<TkOptionDef> TkMenu::optAll[]=
{
	TkMenu::OPT_ACTIVEBACKGROUND,
	TkMenu::OPT_ACTIVEBORDERWIDTH,
	TkMenu::OPT_ACTIVEFOREGROUND,
	TkMenu::OPT_BACKGROUND,
	TkMenu::OPT_CURSOR,
	TkMenu::OPT_FONT,
	TkMenu::OPT_FOREGROUND,
	TkMenu::OPT_RELIEF,
	TkMenu::OPT_SELECTCOLOR,
	TkMenu::OPT_TAKEFOCUS,
	TkMenu::OPT_TEAROFF,
	TkMenu::OPT_TEAROFFCOMMAND,
	TkMenu::OPT_TITLE,
	TkMenu::OPT_TYPE
};

const char* TkMenu::type="TkMenu";
const char* TkMenu::tkClass="menu";

const Ptr<TkOptionDef>* TkMenu::getOptionAll() const
{
	return TkMenu::optAll;
}

const char* TkMenu::getType() const
{
	return TkMenu::type;
}

const char* TkMenu::getTkClass() const
{
	return TkMenu::tkClass;
}

void TkMenu::doSerialize(TiXmlElement& element) const
{
	TkBase::doSerialize(element);
}

void TkMenu::doDeserialize(const TiXmlElement& element)
{
	TkBase::doDeserialize(element);
}


TkMenu* TkMenu::getMenuById(int id)
{
	t_menu_map::const_iterator it=menuMap.find(id);
	if (it==menuMap.end()) return 0;
	return it->second;
}

TkMenu::TkMenu(Ptr<TclInterp>& interp):TkBase(interp)
{
	menuId=idGenerator++;
	menuMap[menuId]=this;
}
TkMenu::~TkMenu()
{
	t_menu_map::iterator it=menuMap.find(menuId);
	menuMap.erase(it);
}

void TkMenu::addMenuListener(TkMenuListener* listener)
{
	listeners.push_back(Ptr<TkMenuListener>(listener));
}

void TkMenu::fireMenuEvent(const string& commandId)
{
	for(t_listeners_vector::iterator it=listeners.begin();it!=listeners.end();it++)
	{
		(*it)->handleEvent(this,commandId);
	}
}

void TkMenu::addCommand(const string& miName,const string& miId)
{
	submenus.push_back(new TkMenuCommand(miName,miId));
}
	
void TkMenu::addSeparator()
{
	submenus.push_back(&separator);
}

void TkMenu::addSubmenu(const string& miName,TkMenu* subMenu)
{
	subMenu->miName=miName;
	submenus.push_back(subMenu);	
}

void TkMenu::create()
{
	TkBase::create();
	for(t_menu_vector::iterator it=submenus.begin();it!=submenus.end();it++)
	{
		if ((*it)->typeOf(TkMenuSeparator::type))
		{
			interp->eval(string(getUid())+" add separator");
			continue;
		}
		if ((*it)->typeOf(TkMenuCommand::type))
		{
			TkMenuCommand* mc=(TkMenuCommand*)((TObject*)(*it));
			char buf[128];
			sprintf(buf,"%d",menuId);
			interp->eval(string(getUid())+" add command -label \""+mc->getName()+"\" -command {onmenuevent "+buf+" \""+mc->getId()+"\"}");
			continue;
		}
		if ((*it)->typeOf(TkMenu::type))
		{
			TkMenu* mn=(TkMenu*)((TObject*)(*it));
			mn->create();
			interp->eval(string(getUid())+" add cascade -label \""+mn->miName+"\" -menu "+mn->getUid());
			continue;
		}
	}
}

TObject* TkMenu::clone()
{
	TkBase* obj=new TkMenu(interp);

	baseClone(obj);

	return obj;
}

void TkMenu::setBackgroundColor(TkColorOption* color)
{
	setOption(OPT_BACKGROUND,color);
}

Ptr<TkColorOption>& TkMenu::getBackgroundColor() const
{
	TkColorOption* colorOption=new TkColorOption();
	
	colorOption->fromObject(getOption(OPT_BACKGROUND));
	return *(new Ptr<TkColorOption>(colorOption));
}

