20a69b8dd7105c73a0997e2810455b9a0ea3eda1
[platform/core/uifw/dali-core.git] / dali / internal / event / common / type-registry-impl.cpp
1 /*
2  * Copyright (c) 2018 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 // INTERNAL INCLUDES
22 #include <dali/internal/event/common/thread-local-storage.h>
23 #include <dali/public-api/object/type-registry.h>
24 #include <dali/public-api/object/base-handle.h>
25 #include <dali/internal/event/actors/custom-actor-internal.h>
26 #include <dali/internal/event/common/demangler.h>
27
28 #include <dali/integration-api/debug.h>
29
30 namespace
31 {
32
33 #if defined(DEBUG_ENABLED)
34 Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_TYPE_REGISTRY");
35 #endif
36
37 } // namespace anon
38
39 namespace Dali
40 {
41
42 extern std::string Demangle(const char* symbol);
43
44 namespace Internal
45 {
46
47 TypeRegistry *TypeRegistry::Get()
48 {
49   static TypeRegistry *_reg(new TypeRegistry());
50   DALI_ASSERT_DEBUG(_reg);
51   return _reg;
52 }
53
54 TypeRegistry::TypeRegistry()
55 {
56
57 }
58
59 TypeRegistry::~TypeRegistry()
60 {
61   mRegistryLut.clear();
62 }
63
64 Dali::TypeInfo TypeRegistry::GetTypeInfo( const std::string& uniqueTypeName )
65 {
66   for( auto&& iter : mRegistryLut )
67   {
68     // Note! mRegistryLut contains Dali::TypeInfo handles, so cannot call GetTypeName()
69     // as it calls us back resulting in infinite loop (GetTypeName is in BaseHandle part)
70     if( GetImplementation( iter ).GetName() == uniqueTypeName )
71     {
72       return iter;
73     }
74   }
75   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Cannot find requested type '%s'\n", uniqueTypeName.c_str() );
76
77   return Dali::TypeInfo();
78 }
79
80 Dali::TypeInfo TypeRegistry::GetTypeInfo( const std::type_info& registerType )
81 {
82   std::string typeName = DemangleClassName( registerType.name() );
83
84   return GetTypeInfo( typeName );
85 }
86
87 size_t TypeRegistry::GetTypeNameCount() const
88 {
89   return mRegistryLut.size();
90 }
91
92 std::string TypeRegistry::GetTypeName( size_t index ) const
93 {
94   std::string name;
95
96   if( index < mRegistryLut.size() )
97   {
98     name = GetImplementation( mRegistryLut[ index ] ).GetName();
99   }
100
101   return name;
102 }
103
104 std::string TypeRegistry::Register( const std::type_info& theTypeInfo, const std::type_info& baseTypeInfo,
105                              Dali::TypeInfo::CreateFunction createInstance, bool callCreateOnInit )
106 {
107   std::string uniqueTypeName  = DemangleClassName( theTypeInfo.name() );
108
109   return Register( uniqueTypeName, baseTypeInfo, createInstance, callCreateOnInit );
110 }
111
112 std::string TypeRegistry::Register( const std::type_info& theTypeInfo, const std::type_info& baseTypeInfo,
113                              Dali::TypeInfo::CreateFunction createInstance, bool callCreateOnInit,
114                              const Dali::PropertyDetails* defaultProperties, Property::Index defaultPropertyCount )
115 {
116   std::string uniqueTypeName  = DemangleClassName( theTypeInfo.name() );
117
118   return Register( uniqueTypeName, baseTypeInfo, createInstance, callCreateOnInit, defaultProperties, defaultPropertyCount );
119 }
120
121 std::string TypeRegistry::Register( const std::string& uniqueTypeName, const std::type_info& baseTypeInfo,
122                              Dali::TypeInfo::CreateFunction createInstance, bool callCreateOnInit,
123                              const Dali::PropertyDetails* defaultProperties, Property::Index defaultPropertyCount )
124 {
125   std::string baseTypeName = DemangleClassName( baseTypeInfo.name() );
126
127   // check for duplicates using uniqueTypeName
128   for( auto&& iter : mRegistryLut )
129   {
130     if( GetImplementation( iter ).GetName() == uniqueTypeName )
131     {
132       DALI_LOG_WARNING( "Duplicate name in TypeRegistry for '%s'\n", + uniqueTypeName.c_str() );
133       DALI_ASSERT_ALWAYS( !"Duplicate type name in Type Registration" );
134       return uniqueTypeName; // never actually happening due to the assert
135     }
136   }
137
138   mRegistryLut.push_back( Dali::TypeInfo( new Internal::TypeInfo( uniqueTypeName, baseTypeName, createInstance, defaultProperties, defaultPropertyCount ) ) );
139   DALI_LOG_INFO( gLogFilter, Debug::Concise, "Type Registration %s(%s)\n", uniqueTypeName.c_str(), baseTypeName.c_str() );
140
141   if( callCreateOnInit )
142   {
143     mInitFunctions.push_back(createInstance);
144   }
145
146   return uniqueTypeName;
147 }
148
149 void TypeRegistry::Register( const std::string& uniqueTypeName, const std::type_info& baseTypeInfo,
150     Dali::CSharpTypeInfo::CreateFunction createInstance )
151 {
152   std::string baseTypeName = DemangleClassName( baseTypeInfo.name() );
153
154   // check for duplicates using uniqueTypeName
155   for( auto&& iter : mRegistryLut )
156   {
157     if( GetImplementation( iter ).GetName() == uniqueTypeName )
158     {
159       DALI_LOG_WARNING( "Duplicate name in TypeRegistry for '%s'\n", + uniqueTypeName.c_str() );
160       DALI_ASSERT_ALWAYS( !"Duplicate type name in Type Registration" );
161       return; // never actually happening due to the assert
162     }
163   }
164
165   mRegistryLut.push_back( Dali::TypeInfo( new Internal::TypeInfo( uniqueTypeName, baseTypeName, createInstance ) ) );
166   DALI_LOG_INFO( gLogFilter, Debug::Concise, "Type Registration %s(%s)\n", uniqueTypeName.c_str(), baseTypeName.c_str() );
167 }
168
169 void TypeRegistry::CallInitFunctions(void) const
170 {
171   for( auto&& iter : mInitFunctions )
172   {
173     (*iter)();
174   }
175 }
176
177 std::string TypeRegistry::RegistrationName( const std::type_info& registerType )
178 {
179   return DemangleClassName( registerType.name() );
180 }
181
182 void TypeRegistry::RegisterSignal( TypeRegistration& typeRegistration, const std::string& name, Dali::TypeInfo::SignalConnectorFunction func )
183 {
184   for( auto&& iter : mRegistryLut )
185   {
186     auto&& impl = GetImplementation( iter );
187     if( impl.GetName() == typeRegistration.RegisteredName() )
188     {
189       impl.AddConnectorFunction( name, func );
190       break;
191     }
192   }
193 }
194
195 bool TypeRegistry::RegisterAction( TypeRegistration& typeRegistration, const std::string &name, Dali::TypeInfo::ActionFunction f )
196 {
197   for( auto&& iter : mRegistryLut )
198   {
199     auto&& impl = GetImplementation( iter );
200     if( impl.GetName() == typeRegistration.RegisteredName() )
201     {
202       impl.AddActionFunction( name, f );
203       return true;
204     }
205   }
206   return false;
207 }
208
209 bool TypeRegistry::RegisterProperty( TypeRegistration& typeRegistration, const std::string& name, Property::Index index, Property::Type type, Dali::TypeInfo::SetPropertyFunction setFunc, Dali::TypeInfo::GetPropertyFunction getFunc )
210 {
211   for( auto&& iter : mRegistryLut )
212   {
213     auto&& impl = GetImplementation( iter );
214     if( impl.GetName() == typeRegistration.RegisteredName() )
215     {
216       impl.AddProperty( name, index, type, setFunc, getFunc );
217       return true;
218     }
219   }
220
221   return false;
222 }
223
224 bool TypeRegistry::RegisterProperty( const std::string& objectName, const std::string& name, Property::Index index, Property::Type type, Dali::CSharpTypeInfo::SetPropertyFunction setFunc, Dali::CSharpTypeInfo::GetPropertyFunction getFunc )
225 {
226   for( auto&& iter : mRegistryLut )
227   {
228     auto&& impl = GetImplementation( iter );
229     if( impl.GetName() == objectName )
230     {
231       impl.AddProperty( name, index, type, setFunc, getFunc );
232       return true;
233     }
234   }
235
236   return false;
237 }
238
239
240 bool TypeRegistry::RegisterAnimatableProperty( TypeRegistration& typeRegistration, const std::string& name, Property::Index index, Property::Type type )
241 {
242   for( auto&& iter : mRegistryLut )
243   {
244     auto&& impl = GetImplementation( iter );
245     if( impl.GetName() == typeRegistration.RegisteredName() )
246     {
247       impl.AddAnimatableProperty( name, index, type );
248       return true;
249     }
250   }
251
252   return false;
253 }
254
255 bool TypeRegistry::RegisterAnimatableProperty( TypeRegistration& typeRegistration, const std::string& name, Property::Index index, const Property::Value& value )
256 {
257   for( auto&& iter : mRegistryLut )
258   {
259     auto&& impl = GetImplementation( iter );
260     if( impl.GetName() == typeRegistration.RegisteredName() )
261     {
262       impl.AddAnimatableProperty( name, index, value );
263       return true;
264     }
265   }
266
267   return false;
268 }
269
270 bool TypeRegistry::RegisterAnimatablePropertyComponent( TypeRegistration& typeRegistration, const std::string& name, Property::Index index, Property::Index baseIndex, unsigned int componentIndex )
271 {
272   for( auto&& iter : mRegistryLut )
273   {
274     auto&& impl = GetImplementation( iter );
275     if( impl.GetName() == typeRegistration.RegisteredName() )
276     {
277       impl.AddAnimatablePropertyComponent( name, index, baseIndex, componentIndex );
278       return true;
279     }
280   }
281
282   return false;
283 }
284
285 bool TypeRegistry::RegisterChildProperty( const std::string& registeredType, const std::string& name, Property::Index index, Property::Type type )
286 {
287   for( auto&& iter : mRegistryLut )
288   {
289     auto&& impl = GetImplementation( iter );
290     if( impl.GetName() == registeredType )
291     {
292       impl.AddChildProperty( name, index, type );
293       return true;
294     }
295   }
296
297   return false;
298 }
299
300 bool TypeRegistry::RegisterChildProperty( TypeRegistration& typeRegistration, const std::string& name, Property::Index index, Property::Type type )
301 {
302   return RegisterChildProperty( typeRegistration.RegisteredName(), name, index, type );
303 }
304
305 bool TypeRegistry::DoActionTo( BaseObject * const object, const std::string& actionName, const Property::Map& properties )
306 {
307   bool done = false;
308
309   Dali::TypeInfo type = GetTypeInfo( object );
310
311   auto&& impl = GetImplementation( type );
312   // DoActionTo recurses through base classes
313   done = impl.DoActionTo( object, actionName, properties );
314
315   if( !done )
316   {
317     DALI_LOG_WARNING("Type '%s' cannot do action '%s'\n", type.GetName().c_str(), actionName.c_str());
318   }
319
320   return done;
321 }
322
323 bool TypeRegistry::ConnectSignal( BaseObject* object, ConnectionTrackerInterface* connectionTracker, const std::string& signalName, FunctorDelegate* functor )
324 {
325   bool connected( false );
326
327   Dali::TypeInfo type = GetTypeInfo( object );
328
329   while( type )
330   {
331     auto&& impl = GetImplementation( type );
332     connected = impl.ConnectSignal( object, connectionTracker, signalName, functor );
333     if( connected )
334     {
335       break;
336     }
337     type = GetTypeInfo( impl.GetBaseName() );
338   }
339
340   if( !connected )
341   {
342     // Ownership of functor was not passed to Dali::CallbackBase, so clean-up now
343     delete functor;
344   }
345
346   return connected;
347 }
348
349 Dali::TypeInfo TypeRegistry::GetTypeInfo(const Dali::BaseObject * const pBaseObject)
350 {
351   Dali::TypeInfo type;
352
353   // test for custom actor which has another indirection to get to the type hiearchy we're after
354   const Dali::Internal::CustomActor * const pCustom = dynamic_cast<const Dali::Internal::CustomActor*>(pBaseObject);
355
356   if(pCustom)
357   {
358     const Dali::CustomActorImpl& custom = pCustom->GetImplementation();
359     type = GetTypeInfo( typeid( custom ) );
360     if( !type )
361     {
362       // the most derived type is a descendant of custom actor but has not registered itself
363       // so we'll just treat it as a custom actor for now so it "inherits" all of actors properties, actions and signals
364       type = GetTypeInfo( typeid( Dali::Internal::CustomActor ) );
365     }
366   }
367   else
368   {
369     type = GetTypeInfo( typeid( *pBaseObject ) );
370   }
371
372   return type;
373 }
374
375 } // namespace Internal
376
377 } // namespace Dali