Observer.h 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. #ifndef ANKI_UTIL_OBSERVER_H
  2. #define ANKI_UTIL_OBSERVER_H
  3. #include <boost/ptr_container/ptr_vector.hpp>
  4. namespace anki {
  5. /// The observer interface template
  6. template<typename T>
  7. struct Observer
  8. {
  9. typedef T Value; ///< The type of the notification value
  10. virtual ~Observer()
  11. {}
  12. virtual void notify(Value notificationVal) = 0;
  13. };
  14. /// An over-qualified observer
  15. template<typename ObservingType, typename Value,
  16. void (ObservingType::*method)(Value)>
  17. struct SuperObserver: Observer<Value>
  18. {
  19. ObservingType* reveiver;
  20. SuperObserver(ObservingType* reveiver_)
  21. : reveiver(reveiver_)
  22. {}
  23. void notify(Value x)
  24. {
  25. (reveiver->*method)(x);
  26. }
  27. };
  28. /// Basically a container of observers
  29. template<typename T>
  30. class Observable
  31. {
  32. public:
  33. typedef T Value;
  34. typedef Observer<Value> ObserverType;
  35. typedef boost::ptr_vector<ObserverType> Container;
  36. /// Add a new observer. The Observable takes ownership of the
  37. /// pointer and its responsible of cleaning
  38. void addNewObserver(ObserverType* x)
  39. {
  40. observers.push_back(x);
  41. }
  42. /// Notify all observers
  43. void notifyAll(Value x)
  44. {
  45. for(typename Container::iterator it = observers.begin();
  46. it != observers.end(); ++it)
  47. {
  48. (*it).notify(x);
  49. }
  50. }
  51. /// Alias to notifyAll
  52. void operator()(Value x)
  53. {
  54. notifyAll(x);
  55. }
  56. private:
  57. Container observers;
  58. };
  59. /// If a class has slots it should include this
  60. /// @code
  61. /// class Foo {
  62. /// ANKI_HAS_SLOTS(Foo)
  63. /// };
  64. /// @endcode
  65. #define ANKI_HAS_SLOTS(_class) \
  66. typedef _class ObservingType;
  67. /// Define a slot. This should follow the method declaration
  68. /// @code
  69. /// class Foo {
  70. /// ANKI_HAS_SLOTS(Foo)
  71. ///
  72. /// void slot(const float&)
  73. /// {...}
  74. /// ANKI_SLOT(updateZFar, const float&)
  75. /// };
  76. /// @endcode
  77. #define ANKI_SLOT(_name, _type) \
  78. typedef SuperObserver<ObservingType, _type, &ObservingType::_name> \
  79. Observing_##_name;
  80. /// Define a signal
  81. #define ANKI_SIGNAL(_type, _name) \
  82. Observable<_type> _name;
  83. /// It doesn't do anything. Its purpose is to make the code more understandable
  84. #define ANKI_EMIT this->
  85. /// Connect a signal to a slot
  86. #define ANKI_CONNECT(_sender, _signal, _reveiver, _slot) \
  87. (_sender)->_signal.addNewObserver(new Observing_##_slot(_reveiver))
  88. } // namespace anki
  89. #endif