[dali_1.0.35] Merge branch 'tizen'
[platform/core/uifw/dali-core.git] / dali / internal / event / common / type-registry-impl.cpp
1 /*
2  * Copyright (c) 2014 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 // CLASS HEADER
19 #include <dali/internal/event/common/type-registry-impl.h>
20
21 // EXTERNAL INCLUDES
22 #include <string.h>
23 #include <sstream>
24
25 // INTERNAL INCLUDES
26 #include <dali/internal/event/common/thread-local-storage.h>
27 #include <dali/public-api/object/type-registry.h>
28 #include <dali/public-api/object/base-handle.h>
29 #include <dali/internal/event/actors/custom-actor-internal.h>
30 #include <dali/internal/event/common/demangler.h>
31
32 #include <dali/integration-api/debug.h>
33
34 namespace
35 {
36
37 #if defined(DEBUG_ENABLED)
38 Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_TYPE_REGISTRY");
39 #endif
40
41 } // namespace anon
42
43 namespace Dali
44 {
45
46 extern std::string Demangle(const char* symbol);
47
48 namespace Internal
49 {
50
51 TypeRegistry *TypeRegistry::Get()
52 {
53   static TypeRegistry *_reg(new TypeRegistry());
54   DALI_ASSERT_DEBUG(_reg);
55   return _reg;
56 }
57
58 TypeRegistry::TypeRegistry()
59 {
60
61 }
62
63 TypeRegistry::~TypeRegistry()
64 {
65   mRegistryLut.clear();
66 }
67
68 Dali::TypeInfo TypeRegistry::GetTypeInfo( const std::string &uniqueTypeName )
69 {
70   Dali::TypeInfo ret;
71
72   RegistryMap::iterator iter = mRegistryLut.find(uniqueTypeName);
73
74   if( iter != mRegistryLut.end() )
75   {
76     ret = iter->second;
77   }
78   else
79   {
80     DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Cannot find requested type '%s'\n", uniqueTypeName.c_str());
81   }
82
83   return ret;
84 }
85
86 Dali::TypeInfo TypeRegistry::GetTypeInfo( const std::type_info& registerType )
87 {
88   Dali::TypeInfo ret;
89
90   std::string typeName = DemangleClassName(registerType.name());
91
92   RegistryMap::iterator iter = mRegistryLut.find(typeName);
93
94   if( iter != mRegistryLut.end() )
95   {
96     ret = iter->second;
97   }
98   else
99   {
100     DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Cannot find requested type '%s'\n", registerType.name());
101   }
102
103   return ret;
104 }
105
106 Dali::TypeRegistry::NameContainer TypeRegistry::GetTypeNames() const
107 {
108   Dali::TypeRegistry::NameContainer ret;
109
110   for(RegistryMap::const_iterator iter = mRegistryLut.begin(); iter != mRegistryLut.end(); ++iter)
111   {
112     ret.push_back(iter->first);
113   }
114
115   return ret;
116 }
117
118 bool TypeRegistry::Register( const std::type_info& theTypeInfo, const std::type_info& baseTypeInfo,
119                              Dali::TypeInfo::CreateFunction createInstance, bool callCreateOnInit )
120 {
121   std::string uniqueTypeName  = DemangleClassName(theTypeInfo.name());
122
123   return Register( uniqueTypeName, baseTypeInfo, createInstance, callCreateOnInit );
124 }
125
126 bool TypeRegistry::Register( const std::string& uniqueTypeName, const std::type_info& baseTypeInfo,
127                              Dali::TypeInfo::CreateFunction createInstance, bool callCreateOnInit )
128 {
129   bool ret = false;
130
131   std::string baseTypeName    = DemangleClassName(baseTypeInfo.name());
132
133   RegistryMap::iterator iter = mRegistryLut.find(uniqueTypeName);
134
135   if( iter == mRegistryLut.end() )
136   {
137     mRegistryLut[uniqueTypeName] = Dali::TypeInfo(new Internal::TypeInfo(uniqueTypeName, baseTypeName, createInstance));
138     ret = true;
139     DALI_LOG_INFO( gLogFilter, Debug::Concise, "Type Registration %s(%s)\n", uniqueTypeName.c_str(), baseTypeName.c_str());
140   }
141   else
142   {
143     DALI_LOG_WARNING("Duplicate name for TypeRegistry for '%s'\n", + uniqueTypeName.c_str());
144     DALI_ASSERT_ALWAYS(!"Duplicate type name for Type Registation");
145   }
146
147   if( callCreateOnInit )
148   {
149     mInitFunctions.push_back(createInstance);
150   }
151
152   return ret;
153 }
154
155 void TypeRegistry::CallInitFunctions(void) const
156 {
157   for( InitFunctions::const_iterator iter = mInitFunctions.begin(); iter != mInitFunctions.end(); ++iter)
158   {
159     (*iter)();
160   }
161 }
162
163 std::string TypeRegistry::RegistrationName( const std::type_info& registerType )
164 {
165   return DemangleClassName( registerType.name() );
166 }
167
168 void TypeRegistry::RegisterSignal( TypeRegistration& typeRegistration, const std::string& name, Dali::TypeInfo::SignalConnectorFunction func )
169 {
170   RegistryMap::iterator iter = mRegistryLut.find( typeRegistration.RegisteredName() );
171
172   if( iter != mRegistryLut.end() )
173   {
174     DALI_ASSERT_DEBUG(iter->second);
175
176     GetImplementation(iter->second).AddConnectorFunction( name, func );
177   }
178 }
179
180 bool TypeRegistry::RegisterAction( TypeRegistration &registered, const std::string &name, Dali::TypeInfo::ActionFunction f)
181 {
182   RegistryMap::iterator iter = mRegistryLut.find( registered.RegisteredName() );
183
184   if( iter != mRegistryLut.end() )
185   {
186     DALI_ASSERT_DEBUG(iter->second);
187
188     GetImplementation(iter->second).AddActionFunction( name, f );
189
190     return true;
191   }
192   else
193   {
194     return false;
195   }
196 }
197
198 bool TypeRegistry::RegisterProperty( TypeRegistration& registered, const std::string& name, Property::Index index, Property::Type type, Dali::TypeInfo::SetPropertyFunction setFunc, Dali::TypeInfo::GetPropertyFunction getFunc )
199 {
200   RegistryMap::iterator iter = mRegistryLut.find( registered.RegisteredName() );
201
202   if( iter != mRegistryLut.end() )
203   {
204     DALI_ASSERT_DEBUG(iter->second);
205
206     GetImplementation(iter->second).AddProperty( name, index, type, setFunc, getFunc );
207
208     return true;
209   }
210
211   return false;
212 }
213
214 bool TypeRegistry::RegisterAnimatableProperty( TypeRegistration& registered, const std::string& name, Property::Index index, Property::Type type )
215 {
216   RegistryMap::iterator iter = mRegistryLut.find( registered.RegisteredName() );
217
218   if( iter != mRegistryLut.end() )
219   {
220     DALI_ASSERT_DEBUG(iter->second);
221
222     GetImplementation(iter->second).AddAnimatableProperty( name, index, type );
223
224     return true;
225   }
226
227   return false;
228 }
229
230 bool TypeRegistry::DoActionTo( BaseObject * const object, const std::string &actionName, const std::vector<Property::Value> &properties)
231 {
232   bool done = false;
233
234   Dali::TypeInfo type = GetTypeInfo( object );
235
236   while( type )
237   {
238     if(GetImplementation(type).DoActionTo(object, actionName, properties))
239     {
240       done = true;
241       break;
242     }
243     type = GetTypeInfo( type.GetBaseName() );
244   }
245
246   return done;
247 }
248
249 bool TypeRegistry::ConnectSignal( BaseObject* object, ConnectionTrackerInterface* connectionTracker, const std::string& signalName, FunctorDelegate* functor )
250 {
251   bool connected( false );
252
253   Dali::TypeInfo type = GetTypeInfo( object );
254
255   while( type )
256   {
257     connected = GetImplementation(type).ConnectSignal( object, connectionTracker, signalName, functor );
258     if( connected )
259     {
260       break;
261     }
262     type = GetTypeInfo( type.GetBaseName() );
263   }
264
265   if( !connected )
266   {
267     // Ownership of functor was not passed to Dali::CallbackBase, so clean-up now
268     delete functor;
269   }
270
271   return connected;
272 }
273
274 Dali::TypeInfo TypeRegistry::GetTypeInfo(const Dali::BaseObject * const pBaseObject)
275 {
276   Dali::TypeInfo type;
277
278   // test for custom actor which has another indirection to get to the type hiearchy we're after
279   const Dali::Internal::CustomActor * const pCustom = dynamic_cast<const Dali::Internal::CustomActor*>(pBaseObject);
280
281   if(pCustom)
282   {
283     type = GetTypeInfo( typeid( pCustom->GetImplementation() ) );
284   }
285   else
286   {
287     type = GetTypeInfo( typeid( *pBaseObject ) );
288   }
289
290   return type;
291 }
292
293 } // namespace Internal
294
295 } // namespace Dali