lllistenerwrapper.h
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:7k
源码类别:

游戏引擎

开发平台:

C++ Builder

  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=viewergpl$
  8.  * 
  9.  * Copyright (c) 2009-2010, Linden Research, Inc.
  10.  * 
  11.  * Second Life Viewer Source Code
  12.  * The source code in this file ("Source Code") is provided by Linden Lab
  13.  * to you under the terms of the GNU General Public License, version 2.0
  14.  * ("GPL"), unless you have obtained a separate licensing agreement
  15.  * ("Other License"), formally executed by you and Linden Lab.  Terms of
  16.  * the GPL can be found in doc/GPL-license.txt in this distribution, or
  17.  * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  18.  * 
  19.  * There are special exceptions to the terms and conditions of the GPL as
  20.  * it is applied to this Source Code. View the full text of the exception
  21.  * in the file doc/FLOSS-exception.txt in this software distribution, or
  22.  * online at
  23.  * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  24.  * 
  25.  * By copying, modifying or distributing this software, you acknowledge
  26.  * that you have read and understood your obligations described above,
  27.  * and agree to abide by those obligations.
  28.  * 
  29.  * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  30.  * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  31.  * COMPLETENESS OR PERFORMANCE.
  32.  * $/LicenseInfo$
  33.  */
  34. #if ! defined(LL_LLLISTENERWRAPPER_H)
  35. #define LL_LLLISTENERWRAPPER_H
  36. #include "llevents.h"               // LLListenerWrapperBase
  37. #include <boost/visit_each.hpp>
  38. /**
  39.  * Template base class for coding wrappers for LLEventPump listeners.
  40.  *
  41.  * Derive your listener wrapper from LLListenerWrapper. You must use
  42.  * LLLISTENER_WRAPPER_SUBCLASS() so your subclass will play nicely with
  43.  * boost::visit_each (q.v.). That way boost::signals2 can still detect
  44.  * derivation from LLEventTrackable, and so forth.
  45.  */
  46. template <typename LISTENER>
  47. class LLListenerWrapper: public LLListenerWrapperBase
  48. {
  49. public:
  50.     /// Wrap an arbitrary listener object
  51.     LLListenerWrapper(const LISTENER& listener):
  52.         mListener(listener)
  53.     {}
  54.     /// call
  55.     virtual bool operator()(const LLSD& event)
  56.     {
  57.         return mListener(event);
  58.     }
  59.     /// Allow boost::visit_each() to peek at our mListener.
  60.     template <class V>
  61.     void accept_visitor(V& visitor) const
  62.     {
  63.         using boost::visit_each;
  64.         visit_each(visitor, mListener, 0);
  65.     }
  66. private:
  67.     LISTENER mListener;
  68. };
  69. /**
  70.  * Specialize boost::visit_each() (leveraging ADL) to peek inside an
  71.  * LLListenerWrapper<T> to traverse its LISTENER. We borrow the
  72.  * accept_visitor() pattern from boost::bind(), avoiding the need to make
  73.  * mListener public.
  74.  */
  75. template <class V, typename T>
  76. void visit_each(V& visitor, const LLListenerWrapper<T>& wrapper, int)
  77. {
  78.     wrapper.accept_visitor(visitor);
  79. }
  80. /// use this (sigh!) for each subclass of LLListenerWrapper<T> you write
  81. #define LLLISTENER_WRAPPER_SUBCLASS(CLASS)                              
  82. template <class V, typename T>                                          
  83. void visit_each(V& visitor, const CLASS<T>& wrapper, int)               
  84. {                                                                       
  85.     visit_each(visitor, static_cast<const LLListenerWrapper<T>&>(wrapper), 0); 
  86. }                                                                       
  87.                                                                         
  88. /* Have to state this explicitly, rather than using LL_TEMPLATE_CONVERTIBLE, */ 
  89. /* because the source type is itself a template. */                     
  90. template <typename T>                                                   
  91. struct ll_template_cast_impl<const LLListenerWrapperBase*, const CLASS<T>*> 
  92. {                                                                       
  93.     const LLListenerWrapperBase* operator()(const CLASS<T>* wrapper)    
  94.     {                                                                   
  95.         return wrapper;                                                 
  96.     }                                                                   
  97. }
  98. /**
  99.  * Make an instance of a listener wrapper. Every wrapper class must be a
  100.  * template accepting a listener object of arbitrary type. In particular, the
  101.  * type of a boost::bind() expression is deliberately undocumented. So we
  102.  * can't just write Wrapper<CorrectType>(boost::bind(...)). Instead we must
  103.  * write llwrap<Wrapper>(boost::bind(...)).
  104.  */
  105. template <template<typename> class WRAPPER, typename T>
  106. WRAPPER<T> llwrap(const T& listener)
  107. {
  108.     return WRAPPER<T>(listener);
  109. }
  110. /**
  111.  * This LLListenerWrapper template subclass is used to report entry/exit to an
  112.  * event listener, by changing this:
  113.  * @code
  114.  * someEventPump.listen("MyClass",
  115.  *                      boost::bind(&MyClass::method, ptr, _1));
  116.  * @endcode
  117.  * to this:
  118.  * @code
  119.  * someEventPump.listen("MyClass",
  120.  *                      llwrap<LLCoutListener>(
  121.  *                      boost::bind(&MyClass::method, ptr, _1)));
  122.  * @endcode
  123.  */
  124. template <class LISTENER>
  125. class LLCoutListener: public LLListenerWrapper<LISTENER>
  126. {
  127.     typedef LLListenerWrapper<LISTENER> super;
  128. public:
  129.     /// Wrap an arbitrary listener object
  130.     LLCoutListener(const LISTENER& listener):
  131.         super(listener)
  132.     {}
  133.     /// call
  134.     virtual bool operator()(const LLSD& event)
  135.     {
  136.         std::cout << "Entering listener " << *super::mName << " with " << event << std::endl;
  137.         bool handled = super::operator()(event);
  138.         std::cout << "Leaving  listener " << *super::mName;
  139.         if (handled)
  140.         {
  141.             std::cout << " (handled)";
  142.         }
  143.         std::cout << std::endl;
  144.         return handled;
  145.     }
  146. };
  147. LLLISTENER_WRAPPER_SUBCLASS(LLCoutListener);
  148. /**
  149.  * This LLListenerWrapper template subclass is used to log entry/exit to an
  150.  * event listener, by changing this:
  151.  * @code
  152.  * someEventPump.listen("MyClass",
  153.  *                      boost::bind(&MyClass::method, ptr, _1));
  154.  * @endcode
  155.  * to this:
  156.  * @code
  157.  * someEventPump.listen("MyClass",
  158.  *                      llwrap<LLLogListener>(
  159.  *                      boost::bind(&MyClass::method, ptr, _1)));
  160.  * @endcode
  161.  */
  162. template <class LISTENER>
  163. class LLLogListener: public LLListenerWrapper<LISTENER>
  164. {
  165.     typedef LLListenerWrapper<LISTENER> super;
  166. public:
  167.     /// Wrap an arbitrary listener object
  168.     LLLogListener(const LISTENER& listener):
  169.         super(listener)
  170.     {}
  171.     /// call
  172.     virtual bool operator()(const LLSD& event)
  173.     {
  174.         LL_DEBUGS("LLLogListener") << "Entering listener " << *super::mName << " with " << event << LL_ENDL;
  175.         bool handled = super::operator()(event);
  176.         LL_DEBUGS("LLLogListener") << "Leaving  listener " << *super::mName;
  177.         if (handled)
  178.         {
  179.             LL_CONT << " (handled)";
  180.         }
  181.         LL_CONT << LL_ENDL;
  182.         return handled;
  183.     }
  184. };
  185. LLLISTENER_WRAPPER_SUBCLASS(LLLogListener);
  186. #endif /* ! defined(LL_LLLISTENERWRAPPER_H) */