Notify.h 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  1. /*
  2. ** Command & Conquer Renegade(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /******************************************************************************
  19. *
  20. * FILE
  21. * $Archive: /Commando/Code/wwlib/Notify.h $
  22. *
  23. * DESCRIPTION
  24. * These templates provide implementation of the Subject-Observer pattern.
  25. *
  26. * PROGRAMMER
  27. * Steve Clinard
  28. * $Author: Denzil_l $
  29. *
  30. * VERSION INFO
  31. * $Modtime: 11/13/01 10:49a $
  32. * $Revision: 8 $
  33. *
  34. ******************************************************************************/
  35. #ifndef __NOTIFY_H__
  36. #define __NOTIFY_H__
  37. // Reduce warning level for STL
  38. #if defined(_MSC_VER)
  39. #pragma warning(push, 3)
  40. #endif
  41. #include <vector>
  42. #include <algorithm>
  43. #if defined(_MSC_VER)
  44. #pragma warning(pop)
  45. #endif
  46. #include <assert.h>
  47. template<typename Event> class Notifier;
  48. template<typename Event> class Observer;
  49. template<typename Event> class Observer
  50. {
  51. public:
  52. typedef std::vector< Notifier<Event>* > NotifierColl;
  53. Observer() :
  54. mNotifiers(NULL)
  55. {}
  56. virtual ~Observer()
  57. {StopObserving();}
  58. //! Handle event notification
  59. virtual void HandleNotification(Event&) = 0;
  60. //! Notifier has ended notification of this event
  61. virtual void NotificationEnded(const Notifier<Event>& notifier)
  62. {
  63. NotifierColl::iterator pos = std::find(mNotifiers.begin(),
  64. mNotifiers.end(), &notifier);
  65. if (pos != mNotifiers.end())
  66. {
  67. mNotifiers.erase(pos);
  68. }
  69. }
  70. //! Request notification of this event
  71. virtual void NotifyMe(Notifier<Event>& notifier)
  72. {notifier.AddObserver(*this);}
  73. //! Stop observing event
  74. void StopObserving()
  75. {
  76. while (mNotifiers.size() > 0)
  77. {
  78. Notifier<Event>* notifier = mNotifiers.back();
  79. assert(notifier && "ERROR: NULL pointer in collection.");
  80. notifier->RemoveObserver(*this);
  81. }
  82. }
  83. protected:
  84. Observer(const Observer<Event>& observer);
  85. const Observer<Event>& operator=(const Observer<Event>&);
  86. private:
  87. friend class Notifier<Event>;
  88. NotifierColl mNotifiers;
  89. };
  90. #define DECLARE_OBSERVER(Event) \
  91. virtual void NotifyMe(Notifier<Event>& observer) \
  92. {Notifier<Event>::AddObserver(observer);}
  93. template<typename Event> class Notifier
  94. {
  95. public:
  96. typedef std::vector< Observer<Event>* > ObserverColl;
  97. Notifier()
  98. {}
  99. virtual ~Notifier()
  100. {
  101. for (int index = mObservers.size(); index--;)
  102. {
  103. mObservers[index]->NotificationEnded(*this);
  104. }
  105. }
  106. //! Send event notification to all observers of this event.
  107. virtual void NotifyObservers(Event& event)
  108. {
  109. for (unsigned int index = 0; index < mObservers.size(); index++)
  110. {
  111. mObservers[index]->HandleNotification(event);
  112. }
  113. }
  114. //! Add an observer of this event
  115. virtual void AddObserver(Observer<Event>& observer)
  116. {
  117. ObserverColl::iterator pos = std::find(mObservers.begin(),
  118. mObservers.end(), &observer);
  119. if (pos == mObservers.end())
  120. {
  121. observer.mNotifiers.push_back(this);
  122. mObservers.push_back(&observer);
  123. }
  124. }
  125. //! Remove an observer of this event
  126. virtual void RemoveObserver(Observer<Event>& observer)
  127. {
  128. ObserverColl::iterator pos = std::find(mObservers.begin(),
  129. mObservers.end(), &observer);
  130. if (pos != mObservers.end())
  131. {
  132. observer.NotificationEnded(*this);
  133. mObservers.erase(pos);
  134. }
  135. }
  136. virtual bool HasObservers(void) const
  137. {return !mObservers.empty();}
  138. private:
  139. //! Observer collection
  140. ObserverColl mObservers;
  141. };
  142. #define DECLARE_NOTIFIER(Event) \
  143. virtual void NotifyObservers(Event& event) \
  144. {Notifier<Event>::NotifyObservers(event);} \
  145. virtual void AddObserver(Observer<Event>& observer) \
  146. {Notifier<Event>::AddObserver(observer);} \
  147. virtual void RemoveObserver(Observer<Event>& observer) \
  148. {Notifier<Event>::RemoveObserver(observer);}
  149. /*-----------------------------------------------------------------------------
  150. * The following templates are useful for defining unique types to use as
  151. * Events from types such as strings or integers.
  152. *---------------------------------------------------------------------------*/
  153. /* TypedEvent<T. V>
  154. *
  155. * The first type (T) must be a class or other unique type. This need not
  156. * be a "real" class. It could be a forward declared class, which is enough
  157. * to make the template class unique.
  158. *
  159. * The second type (V) is the event data. "UString" and "int" are obvious
  160. * choices.
  161. *
  162. * Typedef'ing the template class is a good thing to do.
  163. */
  164. template<typename T, typename V>
  165. class TypedEvent
  166. {
  167. public:
  168. TypedEvent(V& value) :
  169. mValue(value)
  170. {}
  171. inline V& operator()()
  172. {return mValue;}
  173. inline V& Subject(void)
  174. {return mValue;}
  175. protected:
  176. V& mValue;
  177. };
  178. template<typename T, typename O>
  179. class TypedEventPtr
  180. {
  181. public:
  182. TypedEventPtr(O* subject) :
  183. mSubject(subject)
  184. {}
  185. inline O* Subject(void)
  186. {return mSubject;}
  187. inline O* operator()()
  188. {return mSubject;}
  189. protected:
  190. O* mSubject;
  191. };
  192. template<typename A, typename O>
  193. class TypedActionPtr :
  194. public TypedEventPtr<A, O>
  195. {
  196. public:
  197. A GetAction(void) const
  198. {return mAction;}
  199. TypedActionPtr(A action, O* data) :
  200. TypedEventPtr<A, O>(data),
  201. mAction(action)
  202. {}
  203. ~TypedActionPtr()
  204. {}
  205. protected:
  206. A mAction;
  207. };
  208. template<typename A, typename B>
  209. class TypedEventPair
  210. {
  211. public:
  212. TypedEventPair(A itemA, B itemB) :
  213. mItemA(itemA),
  214. mItemB(itemB)
  215. {}
  216. inline A GetItemA(void)
  217. {return mItemA;}
  218. inline B GetItemB(void)
  219. {return mItemB;}
  220. protected:
  221. A mItemA;
  222. B mItemB;
  223. };
  224. #endif // __NOTIFY_H__