Wexus2 0.20
|
00001 00002 /* 00003 * Copyright (c) 2011 Aleksander B. Demko 00004 * This source code is distributed under the MIT license. 00005 * See the accompanying file LICENSE.MIT.txt for details. 00006 */ 00007 00008 #ifndef __INCLUDED_WEXUS_REGISTRY_H__ 00009 #define __INCLUDED_WEXUS_REGISTRY_H__ 00010 00011 #include <typeinfo> 00012 00013 #include <wexus/TR1.h> 00014 00015 #include <wexus/MemberFunction.h> 00016 00017 #include <QString> 00018 #include <QMap> 00019 00020 namespace wexus 00021 { 00022 class Registry; 00023 00024 template <class T> class RegisterApp; 00025 template <class APPTYPE, class T> class RegisterController; 00026 template <class CONTROLLERTYPE, void (CONTROLLERTYPE::*MFN)(void)> class RegisterAction; 00027 00028 class Application; // fwd 00029 class Controller; //fwd 00030 00031 // convert this to return shared_ptr<>? 00032 typedef Application* (*ApplicationLoader)(void); 00033 template <class SUB> Application* ApplicationLoaderType(void) { return new SUB(); } // cant seem to nest this in ControllerInfo 00034 00035 // convert this to return shared_ptr<>? 00036 typedef Controller* (*ControllerLoader)(void); 00037 template <class SUB> Controller* ControllerLoaderType(void) { return new SUB(); } // cant seem to nest this in ControllerInfo 00038 00039 typedef void (*ActionFunc)(Controller *c); 00040 }; 00041 00042 /** 00043 * A type registry for applications, controllers and actions. 00044 * This is a singleton. 00045 * 00046 * @author Aleksander Demko 00047 */ 00048 class wexus::Registry 00049 { 00050 public: 00051 class ControllerInfo; 00052 class AppInfo 00053 { 00054 public: 00055 typedef QMap<QString, std::shared_ptr<ControllerInfo> > ControllerMap; // controllers by their name 00056 public: 00057 QString classtype; // the type string (from typeid) 00058 QString appname; // the application name 00059 00060 ApplicationLoader loader; 00061 00062 ControllerMap controllers; 00063 }; 00064 class ActionInfo; 00065 class ControllerInfo 00066 { 00067 public: 00068 // maps actionames to actions 00069 typedef QMap<QString, std::shared_ptr<ActionInfo> > ActionMap; 00070 public: 00071 QString classtype; // the type string (from typeid) 00072 QString name; // the controller name 00073 00074 ControllerLoader loader; 00075 00076 /// parent app 00077 std::shared_ptr<AppInfo> application; 00078 00079 /// maps actionames to actions 00080 ActionMap actions; 00081 }; 00082 class ActionInfo 00083 { 00084 public: 00085 MemberFunction mfn; 00086 QString actionname; 00087 00088 /// parent controller 00089 std::shared_ptr<ControllerInfo> controller; 00090 00091 ActionFunc func; 00092 }; 00093 00094 public: 00095 typedef QMap<QString, std::shared_ptr<AppInfo> > AppTypeMap; // apps by the typeinfo.name() 00096 typedef QMap<QString, std::shared_ptr<AppInfo> > AppNameMap; // apps by their name 00097 00098 typedef QMap<QString, std::shared_ptr<ControllerInfo> > ControllerTypeMap; // controllers by their typeinfo.name() 00099 00100 typedef QList<std::shared_ptr<ActionInfo> > ActionTypeList; // cant be a map cuz MemberFunction doesnt have operator< 00101 00102 static AppTypeMap & appsByType(void) { return instance()->dm_apptype; } 00103 static AppNameMap & appsByName(void) { return instance()->dm_appname; } 00104 00105 static ControllerTypeMap & controllersByType(void) { return instance()->dm_contype; } 00106 00107 static ActionTypeList & actionList(void) { return instance()->dm_actionlist; } 00108 00109 /// called by RegisterApp 00110 static std::shared_ptr<AppInfo> newAppInfo(const char *_appname, const char *_typename, ApplicationLoader loader); 00111 /// called by RegistrerController 00112 /// creates a app placeholder if needed 00113 static std::shared_ptr<AppInfo> linkAppInfo(const char *_apptype); 00114 00115 /// called by RegistrerController 00116 static std::shared_ptr<ControllerInfo> newControllerInfo(const char *_cname, const char *_typename, const char *_apptype, ControllerLoader loader); 00117 /// called b y RegisterAction 00118 /// createa a controllerinfo placeholder if needed 00119 static std::shared_ptr<ControllerInfo> linkControllerInfo(const char *_ctype); 00120 00121 /// called by RegisterAction 00122 static std::shared_ptr<ActionInfo> newActionInfo(wexus::MemberFunction mfn, const char *_actionname, const char *_ctype, ActionFunc func); 00123 00124 protected: 00125 /// never returns null, makes it if need be 00126 static Registry * instance(void); 00127 00128 protected: 00129 static Registry *dm_instance; 00130 00131 protected: 00132 AppTypeMap dm_apptype; 00133 AppNameMap dm_appname; 00134 00135 ControllerTypeMap dm_contype; 00136 00137 ActionTypeList dm_actionlist; 00138 }; 00139 00140 template <class T> class wexus::RegisterApp 00141 { 00142 public: 00143 RegisterApp(const char *appname); 00144 }; 00145 template <class T> wexus::RegisterApp<T>::RegisterApp(const char *appname) 00146 { 00147 /*std::shared_ptr<Registry::AppInfo> ai = */ Registry::newAppInfo(appname, typeid(T).name(), & ApplicationLoaderType<T> ); 00148 // nothing more to fill out, .name is filled by new 00149 } 00150 00151 template <class APPTYPE, class T> class wexus::RegisterController 00152 { 00153 public: 00154 RegisterController(const char *appname); 00155 }; 00156 template <class APPTYPE, class T> wexus::RegisterController<APPTYPE,T>::RegisterController(const char *appname) 00157 { 00158 /*std::shared_ptr<Registry::ControllerInfo> ci =*/ Registry::newControllerInfo(appname, typeid(T).name(), typeid(APPTYPE).name(), & ControllerLoaderType<T> ); 00159 // nothing more to fill out, .name is filled by new 00160 } 00161 00162 template <class CONTROLLERTYPE, void (CONTROLLERTYPE::*MFN)(void)> 00163 class wexus::RegisterAction 00164 { 00165 private: 00166 template <class C, void (C::*LMETH)(void)> 00167 static void methodToFunc(Controller *c) 00168 { 00169 // bounce the function call to a method call 00170 C *here = dynamic_cast<C*>(c); 00171 assert(here); 00172 00173 ((*here).*LMETH)(); 00174 } 00175 public: 00176 RegisterAction(const char *actionname);; 00177 }; 00178 00179 template <class CONTROLLERTYPE, void (CONTROLLERTYPE::*MFN)(void)> 00180 wexus::RegisterAction<CONTROLLERTYPE,MFN>::RegisterAction(const char *actionname) 00181 { 00182 Registry::newActionInfo(MemberFunction(MFN), actionname, 00183 typeid(CONTROLLERTYPE).name(), methodToFunc<CONTROLLERTYPE,MFN>); 00184 } 00185 00186 #endif 00187