notifier.h 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  1. /*
  2. ** Command & Conquer Generals Zero Hour(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/wwNotify.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. * 06/28/02 KM Notify name change to avoid MAX conflicts *
  35. ******************************************************************************/
  36. #ifndef __NOTIFY_H__
  37. #define __NOTIFY_H__
  38. // Reduce warning level for STL
  39. #if defined(_MSC_VER)
  40. #pragma warning(push, 3)
  41. #endif
  42. #include <vector>
  43. #include <algorithm>
  44. #if defined(_MSC_VER)
  45. #pragma warning(pop)
  46. #endif
  47. #include <assert.h>
  48. template<typename Event> class Notifier;
  49. template<typename Event> class Observer;
  50. template<typename Event> class Observer
  51. {
  52. public:
  53. typedef std::vector< Notifier<Event>* > NotifierColl;
  54. Observer() :
  55. mNotifiers(NULL)
  56. {}
  57. virtual ~Observer()
  58. {StopObserving();}
  59. //! Handle event notification
  60. virtual void HandleNotification(Event&) = 0;
  61. //! Notifier has ended notification of this event
  62. virtual void NotificationEnded(const Notifier<Event>& notifier)
  63. {
  64. NotifierColl::iterator pos = std::find(mNotifiers.begin(),
  65. mNotifiers.end(), &notifier);
  66. if (pos != mNotifiers.end())
  67. {
  68. mNotifiers.erase(pos);
  69. }
  70. }
  71. //! Request notification of this event
  72. virtual void NotifyMe(Notifier<Event>& notifier)
  73. {notifier.AddObserver(*this);}
  74. //! Stop observing event
  75. void StopObserving()
  76. {
  77. while (mNotifiers.size() > 0)
  78. {
  79. Notifier<Event>* notifier = mNotifiers.back();
  80. assert(notifier && "ERROR: NULL pointer in collection.");
  81. notifier->RemoveObserver(*this);
  82. }
  83. }
  84. protected:
  85. Observer(const Observer<Event>& observer);
  86. const Observer<Event>& operator=(const Observer<Event>&);
  87. private:
  88. friend class Notifier<Event>;
  89. NotifierColl mNotifiers;
  90. };
  91. #define DECLARE_OBSERVER(Event) \
  92. virtual void NotifyMe(Notifier<Event>& observer) \
  93. {Notifier<Event>::AddObserver(observer);}
  94. template<typename Event> class Notifier
  95. {
  96. public:
  97. typedef std::vector< Observer<Event>* > ObserverColl;
  98. Notifier()
  99. {}
  100. virtual ~Notifier()
  101. {
  102. for (int index = mObservers.size(); index--;)
  103. {
  104. mObservers[index]->NotificationEnded(*this);
  105. }
  106. }
  107. //! Send event notification to all observers of this event.
  108. virtual void NotifyObservers(Event& event)
  109. {
  110. for (unsigned int index = 0; index < mObservers.size(); index++)
  111. {
  112. mObservers[index]->HandleNotification(event);
  113. }
  114. }
  115. //! Add an observer of this event
  116. virtual void AddObserver(Observer<Event>& observer)
  117. {
  118. ObserverColl::iterator pos = std::find(mObservers.begin(),
  119. mObservers.end(), &observer);
  120. if (pos == mObservers.end())
  121. {
  122. observer.mNotifiers.push_back(this);
  123. mObservers.push_back(&observer);
  124. }
  125. }
  126. //! Remove an observer of this event
  127. virtual void RemoveObserver(Observer<Event>& observer)
  128. {
  129. ObserverColl::iterator pos = std::find(mObservers.begin(),
  130. mObservers.end(), &observer);
  131. if (pos != mObservers.end())
  132. {
  133. observer.NotificationEnded(*this);
  134. mObservers.erase(pos);
  135. }
  136. }
  137. virtual bool HasObservers(void) const
  138. {return !mObservers.empty();}
  139. private:
  140. //! Observer collection
  141. ObserverColl mObservers;
  142. };
  143. #define DECLARE_NOTIFIER(Event) \
  144. virtual void NotifyObservers(Event& event) \
  145. {Notifier<Event>::NotifyObservers(event);} \
  146. virtual void AddObserver(Observer<Event>& observer) \
  147. {Notifier<Event>::AddObserver(observer);} \
  148. virtual void RemoveObserver(Observer<Event>& observer) \
  149. {Notifier<Event>::RemoveObserver(observer);}
  150. /*-----------------------------------------------------------------------------
  151. * The following templates are useful for defining unique types to use as
  152. * Events from types such as strings or integers.
  153. *---------------------------------------------------------------------------*/
  154. /* TypedEvent<T. V>
  155. *
  156. * The first type (T) must be a class or other unique type. This need not
  157. * be a "real" class. It could be a forward declared class, which is enough
  158. * to make the template class unique.
  159. *
  160. * The second type (V) is the event data. "UString" and "int" are obvious
  161. * choices.
  162. *
  163. * Typedef'ing the template class is a good thing to do.
  164. */
  165. template<typename T, typename V>
  166. class TypedEvent
  167. {
  168. public:
  169. TypedEvent(V& value) :
  170. mValue(value)
  171. {}
  172. inline V& operator()()
  173. {return mValue;}
  174. inline V& Subject(void)
  175. {return mValue;}
  176. protected:
  177. V& mValue;
  178. };
  179. template<typename T, typename O>
  180. class TypedEventPtr
  181. {
  182. public:
  183. TypedEventPtr(O* subject) :
  184. mSubject(subject)
  185. {}
  186. inline O* Subject(void)
  187. {return mSubject;}
  188. inline O* operator()()
  189. {return mSubject;}
  190. protected:
  191. O* mSubject;
  192. };
  193. template<typename A, typename O>
  194. class TypedActionPtr :
  195. public TypedEventPtr<A, O>
  196. {
  197. public:
  198. A GetAction(void) const
  199. {return mAction;}
  200. TypedActionPtr(A action, O* data) :
  201. TypedEventPtr<A, O>(data),
  202. mAction(action)
  203. {}
  204. ~TypedActionPtr()
  205. {}
  206. protected:
  207. A mAction;
  208. };
  209. template<typename A, typename B>
  210. class TypedEventPair
  211. {
  212. public:
  213. TypedEventPair(A itemA, B itemB) :
  214. mItemA(itemA),
  215. mItemB(itemB)
  216. {}
  217. inline A GetItemA(void)
  218. {return mItemA;}
  219. inline B GetItemB(void)
  220. {return mItemB;}
  221. protected:
  222. A mItemA;
  223. B mItemB;
  224. };
  225. #endif // __NOTIFY_H__