int EventDispatcher::addEventListener(eventType et, EventCallback cb)
	{
		__doCheck();

		if (!_listeners)
			_listeners = new listeners;

		_lastID++;

		/*
#ifdef OX_DEBUG
		for (listeners::iterator i = _listeners->begin(); i != _listeners->end(); ++i)
		{
			const listener& ls = *i;
			if (ls.type == et && cb == ls.cb)
			{
				OX_ASSERT(!"you are already added this event listener");
			}
		}
#endif
		*/

		listener ls;
		ls.type = et;
		ls.cb = cb;
		ls.id = _lastID;
		_listeners->push_back(ls);

		return ls.id;
	}
    bool EventDispatcher::hasEventListeners(void* CallbackThis)
    {
        __doCheck();
        if (!_listeners)
            return false;

        for (size_t size = _listeners->size(), i = 0; i != size; ++i)
        {
            const listener& ls = _listeners->at(i);
            if (ls.cb.p_this == CallbackThis)
                return true;
        }
        return false;
    }
    bool EventDispatcher::hasEventListeners(eventType et, const EventCallback& cb)
    {
        __doCheck();
        if (!_listeners)
            return false;

        for (size_t size = _listeners->size(), i = 0; i != size; ++i)
        {
            const listener& ls = _listeners->at(i);
            if (ls.type == et && cb == ls.cb)
                return true;
        }
        return false;
    }
    void EventDispatcher::removeEventListeners(void* CallbackThis)
    {
        __doCheck();
        if (!_listeners)
            return;

        for (size_t i = 0; i < _listeners->size(); ++i)
        {
            const listener& ls = _listeners->at(i);
            if (ls.cb.p_this == CallbackThis)
            {
                _listeners->erase(_listeners->begin() + i);
                //OX_ASSERT(hasEventListeners(CallbackThis) == false);
                --i;
            }
        }
    }
	void EventDispatcher::removeEventListeners(void *CallbackThis)
	{
		__doCheck();
		//OX_ASSERT(_listeners);
		if (!_listeners)
			return;

		for (listeners::iterator i = _listeners->begin(); i != _listeners->end(); )
		{
			listener ls = *i;
			if (ls.cb.p_this == CallbackThis)
			{
				i = _listeners->erase(i);
			}
			else
				++i;
		}
	}
    void EventDispatcher::removeEventListener(int id)
    {
        __doCheck();

        OX_ASSERT(_listeners);
        if (!_listeners)
            return;

        for (size_t size = _listeners->size(), i = 0; i != size; ++i)
        {
            const listener& ls = _listeners->at(i);
            if (ls.id == id)
            {
                _listeners->erase(_listeners->begin() + i);
                break;
            }
        }
    }
	void EventDispatcher::removeEventListener(eventType et, EventCallback cb)
	{
		__doCheck();

		//OX_ASSERT(_listeners);
		if (!_listeners)
			return;

		for (listeners::iterator i = _listeners->begin(); i != _listeners->end(); )
		{
			listener ls = *i;
			if (ls.type == et && cb == ls.cb)
			{
				i = _listeners->erase(i);
			}
			else
				++i;
		}
	}
	void EventDispatcher::dispatchEvent(Event *event_)
	{
		__doCheck();
		if (!_listeners)
			return;

		Event *ev = event_;
		ev->currentTarget = this;

		listeners copy = *_listeners;//todo, do something!
		for (listeners::iterator i = copy.begin(); i != copy.end(); ++i)
		{
			listener ls = *i;
			if (ls.type != ev->type)
				continue;
			//todo!

			/*
			bool found = false;
			for (listeners::iterator n = _listeners->begin(); n != _listeners->end(); ++n)
			{
				const listener &ols= *n;
				if (ols.type == ls.type && ols.id == ls.id && ols.cb == ls.cb)
				{
					found = true;
					break;
				}
			}

			if (!found)
				continue;

			*/

			//OX_ASSERT(ls.type < 20);
			//log::messageln("cb: %d %x", ls.type, ls.cb.p_this);
			ls.cb(ev);
			if (ev->stopsImmediatePropagation)
			{
				break;
			}
		}
	}
	void EventDispatcher::removeEventListener(int id)
	{
		__doCheck();

		OX_ASSERT(_listeners);
		if (!_listeners)
			return;

		for (listeners::iterator i = _listeners->begin(); i != _listeners->end(); )
		{
			const listener &ls = *i;
			if (ls.id == id)
			{
				i = _listeners->erase(i);
				break;
			}
			else
				++i;
		}
	}
    void EventDispatcher::removeEventListener(eventType et, const EventCallback& cb)
    {
        __doCheck();

        //OX_ASSERT(_listeners);
        if (!_listeners)
            return;

        for (size_t size = _listeners->size(), i = 0; i != size; ++i)
        {
            const listener& ls = _listeners->at(i);
            if (ls.type == et && cb == ls.cb)
            {
                _listeners->erase(_listeners->begin() + i);
                break;
                //OX_ASSERT(hasEventListeners(et, cb) == false);
                //--i;
            }
        }
    }
    void EventDispatcher::dispatchEvent(Event* event)
    {
        if (!event->target)
            event->target = this;

        __doCheck();
        if (!_listeners)
            return;


        size_t size = _listeners->size();
        listenerbase* copy = (listenerbase*)alloca(sizeof(listenerbase) * size);

        size_t num = 0;
        for (size_t i = 0; i != size; ++i)
        {
            listener& ls = _listeners->at(i);
            if (ls.type != event->type)
                continue;

            new(copy + num) listenerbase(ls);
            ++num;
        }

        for (size_t i = 0; i != num; ++i)
        {
            listenerbase& ls = copy[i];
            event->currentTarget = this;
            event->listenerID = ls.id;
            ls.cb(event);
            if (event->stopsImmediatePropagation)
                break;
        }

        for (size_t i = 0; i != num; ++i)
        {
            listenerbase& ls = copy[i];
            ls.~listenerbase();
        }
    }
	EventDispatcher::~EventDispatcher()
	{
		__doCheck();
		delete _listeners;
	}