genesis-3d_engine/Engine/addons/myguiengine/include/MyGUI_DelegateImplement.h
zhongdaohuan 6e8fbca745 genesis-3d engine version 1.3.
match the genesis editor version 1.3.0.653.
2014-05-05 14:50:33 +08:00

417 lines
11 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*!
@file
@author Albert Semenov
@date 11/2007
*/
/*
This file is part of MyGUI.
MyGUI 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 3 of the License, or
(at your option) any later version.
MyGUI 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 MyGUI. If not, see <http://www.gnu.org/licenses/>.
*/
namespace delegates
{
#define MYGUI_COMBINE(a, b) MYGUI_COMBINE1(a, b)
#define MYGUI_COMBINE1(a, b) a##b
#define MYGUI_I_DELEGATE MYGUI_COMBINE(IDelegate, MYGUI_SUFFIX)
#define MYGUI_C_STATIC_DELEGATE MYGUI_COMBINE(CStaticDelegate, MYGUI_SUFFIX)
#define MYGUI_C_METHOD_DELEGATE MYGUI_COMBINE(CMethodDelegate, MYGUI_SUFFIX)
#define MYGUI_C_DELEGATE MYGUI_COMBINE(CDelegate, MYGUI_SUFFIX)
#define MYGUI_C_MULTI_DELEGATE MYGUI_COMBINE(CMultiDelegate, MYGUI_SUFFIX)
// базовый класс всех делегатов
MYGUI_TEMPLATE MYGUI_TEMPLATE_PARAMS
class MYGUI_I_DELEGATE
{
public:
virtual ~MYGUI_I_DELEGATE() { }
#ifndef MYGUI_RTTI_DISABLE_TYPE_INFO
virtual bool isType( const std::type_info& _type) = 0;
#endif
virtual void invoke( MYGUI_PARAMS ) = 0;
virtual bool compare( MYGUI_I_DELEGATE MYGUI_TEMPLATE_ARGS* _delegate) const = 0;
virtual bool compare(IDelegateUnlink* _unlink) const
{
return false;
}
};
// делегат для статической функции
MYGUI_TEMPLATE MYGUI_TEMPLATE_PARAMS
class MYGUI_C_STATIC_DELEGATE : public MYGUI_I_DELEGATE MYGUI_TEMPLATE_ARGS
{
public:
typedef void (*Func)( MYGUI_PARAMS );
MYGUI_C_STATIC_DELEGATE (Func _func) : mFunc(_func) { }
#ifndef MYGUI_RTTI_DISABLE_TYPE_INFO
virtual bool isType( const std::type_info& _type)
{
return typeid( MYGUI_C_STATIC_DELEGATE MYGUI_TEMPLATE_ARGS ) == _type;
}
#endif
virtual void invoke( MYGUI_PARAMS )
{
mFunc( MYGUI_ARGS );
}
virtual bool compare( MYGUI_I_DELEGATE MYGUI_TEMPLATE_ARGS* _delegate) const
{
#ifndef MYGUI_RTTI_DISABLE_TYPE_INFO
if (nullptr == _delegate || !_delegate->isType(typeid(MYGUI_C_STATIC_DELEGATE MYGUI_TEMPLATE_ARGS)) ) return false;
MYGUI_C_STATIC_DELEGATE MYGUI_TEMPLATE_ARGS* cast = static_cast<MYGUI_C_STATIC_DELEGATE MYGUI_TEMPLATE_ARGS*>(_delegate);
#else
MYGUI_C_STATIC_DELEGATE MYGUI_TEMPLATE_ARGS* cast = dynamic_cast<MYGUI_C_STATIC_DELEGATE MYGUI_TEMPLATE_ARGS*>(_delegate);
if (nullptr == cast) return false;
#endif
return cast->mFunc == mFunc;
}
virtual bool compare(IDelegateUnlink* _unlink) const
{
return false;
}
private:
Func mFunc;
};
// делегат для метода класса
template MYGUI_T_TEMPLATE_PARAMS
class MYGUI_C_METHOD_DELEGATE : public MYGUI_I_DELEGATE MYGUI_TEMPLATE_ARGS
{
public:
typedef void (T::*Method)( MYGUI_PARAMS );
MYGUI_C_METHOD_DELEGATE(IDelegateUnlink* _unlink, T* _object, Method _method) : mUnlink(_unlink), mObject(_object), mMethod(_method) { }
#ifndef MYGUI_RTTI_DISABLE_TYPE_INFO
virtual bool isType( const std::type_info& _type)
{
return typeid( MYGUI_C_METHOD_DELEGATE MYGUI_T_TEMPLATE_ARGS ) == _type;
}
#endif
virtual void invoke( MYGUI_PARAMS )
{
(mObject->*mMethod)( MYGUI_ARGS );
}
virtual bool compare( MYGUI_I_DELEGATE MYGUI_TEMPLATE_ARGS* _delegate) const
{
#ifndef MYGUI_RTTI_DISABLE_TYPE_INFO
if (nullptr == _delegate || !_delegate->isType(typeid(MYGUI_C_METHOD_DELEGATE MYGUI_T_TEMPLATE_ARGS)) ) return false;
MYGUI_C_METHOD_DELEGATE MYGUI_T_TEMPLATE_ARGS* cast = static_cast< MYGUI_C_METHOD_DELEGATE MYGUI_T_TEMPLATE_ARGS* >(_delegate);
#else
MYGUI_C_METHOD_DELEGATE MYGUI_T_TEMPLATE_ARGS* cast = dynamic_cast< MYGUI_C_METHOD_DELEGATE MYGUI_T_TEMPLATE_ARGS* >(_delegate);
if (nullptr == cast) return false;
#endif
return cast->mObject == mObject && cast->mMethod == mMethod;
}
virtual bool compare(IDelegateUnlink* _unlink) const
{
return mUnlink == _unlink;
}
private:
IDelegateUnlink* mUnlink;
T* mObject;
Method mMethod;
};
} // namespace delegates
// шаблон для создания делегата статической функции
// параметры : указатель на функцию
// пример : newDelegate(funk_name);
// пример : newDelegate(class_name::static_method_name);
MYGUI_TEMPLATE MYGUI_TEMPLATE_PARAMS
inline delegates::MYGUI_I_DELEGATE MYGUI_TEMPLATE_ARGS* newDelegate( void (*_func)( MYGUI_PARAMS ) )
{
return new delegates::MYGUI_C_STATIC_DELEGATE MYGUI_TEMPLATE_ARGS (_func);
}
// шаблон для создания делегата метода класса
// параметры : указатель на объект класса и указатель на метод класса
// пример : newDelegate(&object_name, &class_name::method_name);
template MYGUI_T_TEMPLATE_PARAMS
inline delegates::MYGUI_I_DELEGATE MYGUI_TEMPLATE_ARGS* newDelegate( T* _object, void (T::*_method)( MYGUI_PARAMS ) )
{
return new delegates::MYGUI_C_METHOD_DELEGATE MYGUI_T_TEMPLATE_ARGS (delegates::GetDelegateUnlink(_object), _object, _method);
}
namespace delegates
{
// шаблон класса делегата
MYGUI_TEMPLATE MYGUI_TEMPLATE_PARAMS
class MYGUI_C_DELEGATE
{
public:
typedef MYGUI_I_DELEGATE MYGUI_TEMPLATE_ARGS IDelegate;
MYGUI_C_DELEGATE () : mDelegate(nullptr) { }
MYGUI_C_DELEGATE (const MYGUI_C_DELEGATE MYGUI_TEMPLATE_ARGS& _event) : mDelegate(nullptr)
{
// забираем себе владение
IDelegate* del = _event.mDelegate;
const_cast< MYGUI_C_DELEGATE MYGUI_TEMPLATE_ARGS& >(_event).mDelegate = nullptr;
if (mDelegate != nullptr && !mDelegate->compare(del))
delete mDelegate;
mDelegate = del;
}
~MYGUI_C_DELEGATE ()
{
clear();
}
bool empty() const
{
return mDelegate == nullptr;
}
void clear()
{
if (mDelegate)
{
delete mDelegate;
mDelegate = nullptr;
}
}
MYGUI_C_DELEGATE MYGUI_TEMPLATE_ARGS& operator=(IDelegate* _delegate)
{
delete mDelegate;
mDelegate = _delegate;
return *this;
}
MYGUI_C_DELEGATE MYGUI_TEMPLATE_ARGS& operator=(const MYGUI_C_DELEGATE MYGUI_TEMPLATE_ARGS& _event)
{
// забираем себе владение
IDelegate* del = _event.mDelegate;
const_cast< MYGUI_C_DELEGATE MYGUI_TEMPLATE_ARGS& >(_event).mDelegate = nullptr;
if (mDelegate != nullptr && !mDelegate->compare(del))
delete mDelegate;
mDelegate = del;
return *this;
}
void operator()( MYGUI_PARAMS )
{
if (mDelegate == nullptr) return;
mDelegate->invoke( MYGUI_ARGS );
}
private:
IDelegate* mDelegate;
};
// шаблон класса мульти делегата
MYGUI_TEMPLATE MYGUI_TEMPLATE_PARAMS
class MYGUI_C_MULTI_DELEGATE
{
public:
typedef MYGUI_I_DELEGATE MYGUI_TEMPLATE_ARGS IDelegate;
typedef MYGUI_TYPENAME std::list<IDelegate* /*, Allocator<IDelegate*>*/ > ListDelegate;
typedef MYGUI_TYPENAME ListDelegate::iterator ListDelegateIterator;
typedef MYGUI_TYPENAME ListDelegate::const_iterator ConstListDelegateIterator;
MYGUI_C_MULTI_DELEGATE () { }
~MYGUI_C_MULTI_DELEGATE ()
{
clear();
}
bool empty() const
{
for (ConstListDelegateIterator iter = mListDelegates.begin(); iter != mListDelegates.end(); ++iter)
{
if (*iter) return false;
}
return true;
}
void clear()
{
for (ListDelegateIterator iter = mListDelegates.begin(); iter != mListDelegates.end(); ++iter)
{
if (*iter)
{
delete (*iter);
(*iter) = nullptr;
}
}
}
void clear(IDelegateUnlink* _unlink)
{
for (ListDelegateIterator iter = mListDelegates.begin(); iter != mListDelegates.end(); ++iter)
{
if ((*iter) && (*iter)->compare(_unlink))
{
delete (*iter);
(*iter) = nullptr;
}
}
}
MYGUI_C_MULTI_DELEGATE MYGUI_TEMPLATE_ARGS& operator+=(IDelegate* _delegate)
{
for (ListDelegateIterator iter = mListDelegates.begin(); iter != mListDelegates.end(); ++iter)
{
if ((*iter) && (*iter)->compare(_delegate))
{
MYGUI_EXCEPT("Trying to add same delegate twice.");
}
}
mListDelegates.push_back(_delegate);
return *this;
}
MYGUI_C_MULTI_DELEGATE MYGUI_TEMPLATE_ARGS& operator-=(IDelegate* _delegate)
{
for (ListDelegateIterator iter = mListDelegates.begin(); iter != mListDelegates.end(); ++iter)
{
if ((*iter) && (*iter)->compare(_delegate))
{
// проверяем на идентичность делегатов
if ((*iter) != _delegate) delete (*iter);
(*iter) = nullptr;
break;
}
}
delete _delegate;
return *this;
}
void operator()( MYGUI_PARAMS )
{
ListDelegateIterator iter = mListDelegates.begin();
while (iter != mListDelegates.end())
{
if (nullptr == (*iter))
{
iter = mListDelegates.erase(iter);
}
else
{
(*iter)->invoke( MYGUI_ARGS );
++iter;
}
}
}
MYGUI_C_MULTI_DELEGATE (const MYGUI_C_MULTI_DELEGATE MYGUI_TEMPLATE_ARGS& _event)
{
// забираем себе владение
ListDelegate del = _event.mListDelegates;
const_cast< MYGUI_C_MULTI_DELEGATE MYGUI_TEMPLATE_ARGS& >(_event).mListDelegates.clear();
safe_clear(del);
mListDelegates = del;
}
MYGUI_C_MULTI_DELEGATE MYGUI_TEMPLATE_ARGS& operator=(const MYGUI_C_MULTI_DELEGATE MYGUI_TEMPLATE_ARGS& _event)
{
// забираем себе владение
ListDelegate del = _event.mListDelegates;
const_cast< MYGUI_C_MULTI_DELEGATE MYGUI_TEMPLATE_ARGS& >(_event).mListDelegates.clear();
safe_clear(del);
mListDelegates = del;
return *this;
}
MYGUI_OBSOLETE("use : operator += ")
MYGUI_C_MULTI_DELEGATE MYGUI_TEMPLATE_ARGS& operator=(IDelegate* _delegate)
{
clear();
*this += _delegate;
return *this;
}
private:
void safe_clear(ListDelegate& _delegates)
{
for (ListDelegateIterator iter = mListDelegates.begin(); iter != mListDelegates.end(); ++iter)
{
if (*iter)
{
IDelegate* del = (*iter);
(*iter) = nullptr;
delete_is_not_found(del, _delegates);
}
}
}
void delete_is_not_found(IDelegate* _del, ListDelegate& _delegates)
{
for (ListDelegateIterator iter = _delegates.begin(); iter != _delegates.end(); ++iter)
{
if ((*iter) && (*iter)->compare(_del))
{
return;
}
}
delete _del;
}
private:
ListDelegate mListDelegates;
};
#undef MYGUI_COMBINE
#undef MYGUI_COMBINE1
#undef MYGUI_I_DELEGATE
#undef MYGUI_C_STATIC_DELEGATE
#undef MYGUI_C_METHOD_DELEGATE
#undef MYGUI_C_DELEGATE
#undef MYGUI_C_MULTI_DELEGATE
#undef MYGUI_SUFFIX
#undef MYGUI_TEMPLATE
#undef MYGUI_TEMPLATE_PARAMS
#undef MYGUI_TEMPLATE_ARGS
#undef MYGUI_T_TEMPLATE_PARAMS
#undef MYGUI_T_TEMPLATE_ARGS
#undef MYGUI_PARAMS
#undef MYGUI_ARGS
#undef MYGUI_TYPENAME
} // namespace delegates