PageRenderTime 25ms CodeModel.GetById 1ms RepoModel.GetById 0ms app.codeStats 0ms

/indra/llcommon/lllistenerwrapper.h

https://bitbucket.org/lindenlab/viewer-beta/
C++ Header | 198 lines | 96 code | 18 blank | 84 comment | 2 complexity | e286efc55950535cfd85de1808687d51 MD5 | raw file
Possible License(s): LGPL-2.1
  1. /**
  2. * @file lllistenerwrapper.h
  3. * @author Nat Goodspeed
  4. * @date 2009-11-30
  5. * @brief Introduce LLListenerWrapper template
  6. *
  7. * $LicenseInfo:firstyear=2009&license=viewerlgpl$
  8. * Second Life Viewer Source Code
  9. * Copyright (C) 2010, Linden Research, Inc.
  10. *
  11. * This library is free software; you can redistribute it and/or
  12. * modify it under the terms of the GNU Lesser General Public
  13. * License as published by the Free Software Foundation;
  14. * version 2.1 of the License only.
  15. *
  16. * This library is distributed in the hope that it will be useful,
  17. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  19. * Lesser General Public License for more details.
  20. *
  21. * You should have received a copy of the GNU Lesser General Public
  22. * License along with this library; if not, write to the Free Software
  23. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  24. *
  25. * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
  26. * $/LicenseInfo$
  27. */
  28. #if ! defined(LL_LLLISTENERWRAPPER_H)
  29. #define LL_LLLISTENERWRAPPER_H
  30. #include "llevents.h" // LLListenerWrapperBase
  31. #include <boost/visit_each.hpp>
  32. /**
  33. * Template base class for coding wrappers for LLEventPump listeners.
  34. *
  35. * Derive your listener wrapper from LLListenerWrapper. You must use
  36. * LLLISTENER_WRAPPER_SUBCLASS() so your subclass will play nicely with
  37. * boost::visit_each (q.v.). That way boost::signals2 can still detect
  38. * derivation from LLEventTrackable, and so forth.
  39. */
  40. template <typename LISTENER>
  41. class LLListenerWrapper: public LLListenerWrapperBase
  42. {
  43. public:
  44. /// Wrap an arbitrary listener object
  45. LLListenerWrapper(const LISTENER& listener):
  46. mListener(listener)
  47. {}
  48. /// call
  49. virtual bool operator()(const LLSD& event)
  50. {
  51. return mListener(event);
  52. }
  53. /// Allow boost::visit_each() to peek at our mListener.
  54. template <class V>
  55. void accept_visitor(V& visitor) const
  56. {
  57. using boost::visit_each;
  58. visit_each(visitor, mListener, 0);
  59. }
  60. private:
  61. LISTENER mListener;
  62. };
  63. /**
  64. * Specialize boost::visit_each() (leveraging ADL) to peek inside an
  65. * LLListenerWrapper<T> to traverse its LISTENER. We borrow the
  66. * accept_visitor() pattern from boost::bind(), avoiding the need to make
  67. * mListener public.
  68. */
  69. template <class V, typename T>
  70. void visit_each(V& visitor, const LLListenerWrapper<T>& wrapper, int)
  71. {
  72. wrapper.accept_visitor(visitor);
  73. }
  74. /// use this (sigh!) for each subclass of LLListenerWrapper<T> you write
  75. #define LLLISTENER_WRAPPER_SUBCLASS(CLASS) \
  76. template <class V, typename T> \
  77. void visit_each(V& visitor, const CLASS<T>& wrapper, int) \
  78. { \
  79. visit_each(visitor, static_cast<const LLListenerWrapper<T>&>(wrapper), 0); \
  80. } \
  81. \
  82. /* Have to state this explicitly, rather than using LL_TEMPLATE_CONVERTIBLE, */ \
  83. /* because the source type is itself a template. */ \
  84. template <typename T> \
  85. struct ll_template_cast_impl<const LLListenerWrapperBase*, const CLASS<T>*> \
  86. { \
  87. const LLListenerWrapperBase* operator()(const CLASS<T>* wrapper) \
  88. { \
  89. return wrapper; \
  90. } \
  91. }
  92. /**
  93. * Make an instance of a listener wrapper. Every wrapper class must be a
  94. * template accepting a listener object of arbitrary type. In particular, the
  95. * type of a boost::bind() expression is deliberately undocumented. So we
  96. * can't just write Wrapper<CorrectType>(boost::bind(...)). Instead we must
  97. * write llwrap<Wrapper>(boost::bind(...)).
  98. */
  99. template <template<typename> class WRAPPER, typename T>
  100. WRAPPER<T> llwrap(const T& listener)
  101. {
  102. return WRAPPER<T>(listener);
  103. }
  104. /**
  105. * This LLListenerWrapper template subclass is used to report entry/exit to an
  106. * event listener, by changing this:
  107. * @code
  108. * someEventPump.listen("MyClass",
  109. * boost::bind(&MyClass::method, ptr, _1));
  110. * @endcode
  111. * to this:
  112. * @code
  113. * someEventPump.listen("MyClass",
  114. * llwrap<LLCoutListener>(
  115. * boost::bind(&MyClass::method, ptr, _1)));
  116. * @endcode
  117. */
  118. template <class LISTENER>
  119. class LLCoutListener: public LLListenerWrapper<LISTENER>
  120. {
  121. typedef LLListenerWrapper<LISTENER> super;
  122. public:
  123. /// Wrap an arbitrary listener object
  124. LLCoutListener(const LISTENER& listener):
  125. super(listener)
  126. {}
  127. /// call
  128. virtual bool operator()(const LLSD& event)
  129. {
  130. std::cout << "Entering listener " << *super::mName << " with " << event << std::endl;
  131. bool handled = super::operator()(event);
  132. std::cout << "Leaving listener " << *super::mName;
  133. if (handled)
  134. {
  135. std::cout << " (handled)";
  136. }
  137. std::cout << std::endl;
  138. return handled;
  139. }
  140. };
  141. LLLISTENER_WRAPPER_SUBCLASS(LLCoutListener);
  142. /**
  143. * This LLListenerWrapper template subclass is used to log entry/exit to an
  144. * event listener, by changing this:
  145. * @code
  146. * someEventPump.listen("MyClass",
  147. * boost::bind(&MyClass::method, ptr, _1));
  148. * @endcode
  149. * to this:
  150. * @code
  151. * someEventPump.listen("MyClass",
  152. * llwrap<LLLogListener>(
  153. * boost::bind(&MyClass::method, ptr, _1)));
  154. * @endcode
  155. */
  156. template <class LISTENER>
  157. class LLLogListener: public LLListenerWrapper<LISTENER>
  158. {
  159. typedef LLListenerWrapper<LISTENER> super;
  160. public:
  161. /// Wrap an arbitrary listener object
  162. LLLogListener(const LISTENER& listener):
  163. super(listener)
  164. {}
  165. /// call
  166. virtual bool operator()(const LLSD& event)
  167. {
  168. LL_DEBUGS("LLLogListener") << "Entering listener " << *super::mName << " with " << event << LL_ENDL;
  169. bool handled = super::operator()(event);
  170. LL_DEBUGS("LLLogListener") << "Leaving listener " << *super::mName;
  171. if (handled)
  172. {
  173. LL_CONT << " (handled)";
  174. }
  175. LL_CONT << LL_ENDL;
  176. return handled;
  177. }
  178. };
  179. LLLISTENER_WRAPPER_SUBCLASS(LLLogListener);
  180. #endif /* ! defined(LL_LLLISTENERWRAPPER_H) */