Merge "Remove use of boost thread local storage from debug" into tizen
[platform/core/uifw/dali-core.git] / dali / internal / event / actors / layer-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/actors/layer-impl.h>
20
21 // INTERNAL INCLUDES
22 #include <dali/public-api/common/dali-common.h>
23 #include <dali/public-api/object/type-registry.h>
24 #include <dali/internal/event/common/property-index-ranges.h>
25 #include <dali/internal/event/common/stage-impl.h>
26 #include <dali/internal/event/actors/layer-list.h>
27
28 using Dali::Internal::SceneGraph::UpdateManager;
29
30 namespace Dali
31 {
32
33 const Property::Index Layer::CLIPPING_ENABLE = Internal::DEFAULT_ACTOR_PROPERTY_MAX_COUNT;
34 const Property::Index Layer::CLIPPING_BOX    = Internal::DEFAULT_ACTOR_PROPERTY_MAX_COUNT + 1;
35
36 namespace Internal
37 {
38
39 namespace
40 {
41
42 // Actions
43
44 const char* const ACTION_RAISE =           "raise";
45 const char* const ACTION_LOWER =           "lower";
46 const char* const ACTION_RAISE_TO_TOP =    "raise-to-top";
47 const char* const ACTION_LOWER_TO_BOTTOM = "lower-to-bottom";
48
49 BaseHandle Create()
50 {
51   return Dali::Layer::New();
52 }
53
54 TypeRegistration mType( typeid( Dali::Layer ), typeid( Dali::Actor ), Create );
55
56 TypeAction a1( mType, ACTION_RAISE, &Layer::DoAction );
57 TypeAction a2( mType, ACTION_LOWER, &Layer::DoAction );
58 TypeAction a3( mType, ACTION_RAISE_TO_TOP, &Layer::DoAction );
59 TypeAction a4( mType, ACTION_LOWER_TO_BOTTOM, &Layer::DoAction );
60
61 const PropertyDetails DEFAULT_PROPERTY_DETAILS[] =
62 {
63  // Name                     Type              writable animatable constraint-input
64  { "clipping-enable",     Property::BOOLEAN,    true,    false,   true  },  // CLIPPING_ENABLE
65  { "clipping-box",        Property::RECTANGLE,  true,    false,   true  },  // CLIPPING_BOX
66 };
67 const int DEFAULT_LAYER_PROPERTY_COUNT = sizeof( DEFAULT_PROPERTY_DETAILS ) / sizeof( DEFAULT_PROPERTY_DETAILS[0] );
68
69 } // unnamed namespace
70
71 LayerPtr Layer::New()
72 {
73   LayerPtr layer( new Layer( Actor::LAYER ) );
74
75   // Second-phase construction
76   layer->Initialize();
77
78   return layer;
79 }
80
81 LayerPtr Layer::NewRoot( Stage& stage, LayerList& layerList, UpdateManager& manager, bool systemLevel )
82 {
83   LayerPtr root( new Layer( Actor::ROOT_LAYER ) );
84
85   // Second-phase construction
86   SceneGraph::Layer* layer = static_cast<SceneGraph::Layer*>( root->CreateNode() );
87   InstallRootMessage( manager, *layer, systemLevel ); // Transfer ownership to scene-graph
88
89   // Keep a raw pointer to the layer node.
90   root->mNode = layer;
91
92   // stage must be set for the root layer
93   root->mStage = &stage;
94
95   // root actor is immediately considered to be on-stage
96   root->mIsOnStage = true;
97
98   // The root actor will not emit a stage connection signal so set the signalled flag here as well
99   root->mOnStageSignalled = true;
100
101   // layer-list must be set for the root layer
102   root->mLayerList = &layerList;
103   layerList.RegisterLayer( *root );
104
105   return root;
106 }
107
108 Layer::Layer( Actor::DerivedType type )
109 : Actor( type ),
110   mLayerList(NULL),
111   mClippingBox(0,0,0,0),
112   mSortFunction(Dali::Layer::ZValue),
113   mIsClipping(false),
114   mDepthTestDisabled(false),
115   mTouchConsumed(false),
116   mHoverConsumed(false)
117 {
118 }
119
120 void Layer::OnInitialize()
121 {
122 }
123
124 Layer::~Layer()
125 {
126 }
127
128 unsigned int Layer::GetDepth() const
129 {
130   return mLayerList ? mLayerList->GetDepth( this ) : 0u;
131 }
132
133 void Layer::Raise()
134 {
135   if ( mLayerList )
136   {
137     mLayerList->RaiseLayer(*this);
138   }
139 }
140
141 void Layer::Lower()
142 {
143   if ( mLayerList )
144   {
145     mLayerList->LowerLayer(*this);
146   }
147 }
148
149 void Layer::RaiseAbove( const Internal::Layer& target )
150 {
151   // cannot raise above ourself, both have to be on stage
152   if( ( this != &target ) && OnStage() && target.OnStage() )
153   {
154     // get parameters depth
155     const unsigned int targetDepth = target.GetDepth();
156     if( GetDepth() < targetDepth )
157     {
158       MoveAbove( target );
159     }
160   }
161 }
162
163 void Layer::LowerBelow( const Internal::Layer& target )
164 {
165   // cannot lower below ourself, both have to be on stage
166   if( ( this != &target ) && OnStage() && target.OnStage() )
167   {
168     // get parameters depth
169     const unsigned int targetDepth = target.GetDepth();
170     if( GetDepth() > targetDepth )
171     {
172       MoveBelow( target );
173     }
174   }
175 }
176
177 void Layer::RaiseToTop()
178 {
179   if ( mLayerList )
180   {
181     mLayerList->RaiseLayerToTop(*this);
182   }
183 }
184
185 void Layer::LowerToBottom()
186 {
187   if ( mLayerList )
188   {
189     mLayerList->LowerLayerToBottom(*this);
190   }
191 }
192
193 void Layer::MoveAbove( const Internal::Layer& target )
194 {
195   // cannot raise above ourself, both have to be on stage
196   if( ( this != &target ) && mLayerList && target.OnStage() )
197   {
198     mLayerList->MoveLayerAbove(*this, target );
199   }
200 }
201
202 void Layer::MoveBelow( const Internal::Layer& target )
203 {
204   // cannot lower below ourself, both have to be on stage
205   if( ( this != &target ) && mLayerList && target.OnStage() )
206   {
207     mLayerList->MoveLayerBelow(*this, target );
208   }
209 }
210
211 void Layer::SetClipping(bool enabled)
212 {
213   if (enabled != mIsClipping)
214   {
215     mIsClipping = enabled;
216
217     // layerNode is being used in a separate thread; queue a message to set the value
218     SetClippingMessage( mStage->GetUpdateInterface(), GetSceneLayerOnStage(), mIsClipping );
219   }
220 }
221
222 void Layer::SetClippingBox(int x, int y, int width, int height)
223 {
224   if( ( x != mClippingBox.x ) ||
225       ( y != mClippingBox.y ) ||
226       ( width != mClippingBox.width ) ||
227       ( height != mClippingBox.height ) )
228   {
229     // Clipping box is not animatable; this is the most up-to-date value
230     mClippingBox.Set(x, y, width, height);
231
232     // Convert mClippingBox to GL based coordinates (from bottom-left)
233     ClippingBox clippingBox( mClippingBox );
234     clippingBox.y = mStage->GetSize().height - clippingBox.y - clippingBox.height;
235
236     // layerNode is being used in a separate thread; queue a message to set the value
237     SetClippingBoxMessage( mStage->GetUpdateInterface(), GetSceneLayerOnStage(), clippingBox );
238   }
239 }
240
241 void Layer::SetDepthTestDisabled( bool disable )
242 {
243   if( disable != mDepthTestDisabled )
244   {
245     mDepthTestDisabled = disable;
246
247     // Send message .....
248     // layerNode is being used in a separate thread; queue a message to set the value
249     SetDepthTestDisabledMessage( mStage->GetUpdateInterface(), GetSceneLayerOnStage(), mDepthTestDisabled );
250   }
251 }
252
253 bool Layer::IsDepthTestDisabled() const
254 {
255   return mDepthTestDisabled;
256 }
257
258 void Layer::SetSortFunction(Dali::Layer::SortFunctionType function)
259 {
260   if( function != mSortFunction )
261   {
262     mSortFunction = function;
263
264     // layerNode is being used in a separate thread; queue a message to set the value
265     SetSortFunctionMessage( mStage->GetUpdateInterface(), GetSceneLayerOnStage(), mSortFunction );
266   }
267 }
268
269 void Layer::SetTouchConsumed( bool consume )
270 {
271   mTouchConsumed = consume;
272 }
273
274 bool Layer::IsTouchConsumed() const
275 {
276   return mTouchConsumed;
277 }
278
279 void Layer::SetHoverConsumed( bool consume )
280 {
281   mHoverConsumed = consume;
282 }
283
284 bool Layer::IsHoverConsumed() const
285 {
286   return mHoverConsumed;
287 }
288
289 SceneGraph::Node* Layer::CreateNode() const
290 {
291   return SceneGraph::Layer::New();
292 }
293
294 void Layer::OnStageConnectionInternal()
295 {
296   if ( !mIsRoot )
297   {
298     DALI_ASSERT_DEBUG( NULL == mLayerList );
299
300     // Find the ordered layer-list
301     // This is different for Layers added via Integration::GetSystemOverlay()
302     for ( Actor* parent = mParent; parent != NULL; parent = parent->GetParent() )
303     {
304       if( parent->IsLayer() )
305       {
306         Layer* parentLayer = static_cast< Layer* >( parent ); // cheaper than dynamic_cast
307         mLayerList = parentLayer->mLayerList;
308       }
309     }
310   }
311
312   DALI_ASSERT_DEBUG( NULL != mLayerList );
313   mLayerList->RegisterLayer( *this );
314 }
315
316 void Layer::OnStageDisconnectionInternal()
317 {
318   mLayerList->UnregisterLayer(*this);
319
320   // mLayerList is only valid when on-stage
321   mLayerList = NULL;
322 }
323
324 const SceneGraph::Layer& Layer::GetSceneLayerOnStage() const
325 {
326   DALI_ASSERT_DEBUG( mNode != NULL );
327   return dynamic_cast< const SceneGraph::Layer& >( *mNode );
328 }
329
330 unsigned int Layer::GetDefaultPropertyCount() const
331 {
332   return Actor::GetDefaultPropertyCount() + DEFAULT_LAYER_PROPERTY_COUNT;
333 }
334
335 void Layer::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
336 {
337   Actor::GetDefaultPropertyIndices( indices ); // Actor class properties
338   indices.reserve( indices.size() + DEFAULT_LAYER_PROPERTY_COUNT );
339
340   int index = DEFAULT_ACTOR_PROPERTY_MAX_COUNT;
341   for ( int i = 0; i < DEFAULT_LAYER_PROPERTY_COUNT; ++i, ++index )
342   {
343     indices.push_back( index );
344   }
345 }
346
347 bool Layer::IsDefaultPropertyWritable( Property::Index index ) const
348 {
349   if(index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT)
350   {
351     return Actor::IsDefaultPropertyWritable(index);
352   }
353   else
354   {
355     return true; // all properties writable, no need to lookup the table
356   }
357 }
358
359 bool Layer::IsDefaultPropertyAnimatable( Property::Index index ) const
360 {
361   if(index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT)
362   {
363     return Actor::IsDefaultPropertyAnimatable(index);
364   }
365   else
366   {
367     return false; // all properties non animateable, no need to lookup the table
368   }
369 }
370
371 bool Layer::IsDefaultPropertyAConstraintInput( Property::Index index ) const
372 {
373   if(index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT)
374   {
375     return Actor::IsDefaultPropertyAConstraintInput(index);
376   }
377   return true; // our properties can be used as an input to a constraint, no need to lookup the table
378 }
379
380 Property::Type Layer::GetDefaultPropertyType( Property::Index index ) const
381 {
382   if(index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT)
383   {
384     return Actor::GetDefaultPropertyType(index);
385   }
386   else
387   {
388     index -= DEFAULT_ACTOR_PROPERTY_MAX_COUNT;
389
390     if ( ( index >= 0 ) && ( index < DEFAULT_LAYER_PROPERTY_COUNT ) )
391     {
392       return DEFAULT_PROPERTY_DETAILS[index].type;
393     }
394     else
395     {
396       // index out-of-bounds
397       return Property::NONE;
398     }
399   }
400 }
401
402 const char* Layer::GetDefaultPropertyName( Property::Index index ) const
403 {
404   if(index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT)
405   {
406     return Actor::GetDefaultPropertyName(index);
407   }
408   else
409   {
410     index -= DEFAULT_ACTOR_PROPERTY_MAX_COUNT;
411
412     if ( ( index >= 0 ) && ( index < DEFAULT_LAYER_PROPERTY_COUNT ) )
413     {
414       return DEFAULT_PROPERTY_DETAILS[index].name;
415     }
416     else
417     {
418       return NULL;
419     }
420   }
421 }
422
423 Property::Index Layer::GetDefaultPropertyIndex(const std::string& name) const
424 {
425   Property::Index index = Property::INVALID_INDEX;
426
427   // Look for name in current class' default properties
428   for( int i = 0; i < DEFAULT_LAYER_PROPERTY_COUNT; ++i )
429   {
430     const Internal::PropertyDetails* property = &DEFAULT_PROPERTY_DETAILS[ i ];
431     if( 0 == strcmp( name.c_str(), property->name ) ) // dont want to convert rhs to string
432     {
433       index = i + DEFAULT_ACTOR_PROPERTY_MAX_COUNT;
434       break;
435     }
436   }
437   if( Property::INVALID_INDEX == index )
438   {
439     // If not found, check in base class
440     index = Actor::GetDefaultPropertyIndex( name );
441   }
442
443   return index;
444 }
445
446 void Layer::SetDefaultProperty( Property::Index index, const Property::Value& propertyValue )
447 {
448   if(index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT)
449   {
450     Actor::SetDefaultProperty(index, propertyValue);
451   }
452   else
453   {
454     switch(index)
455     {
456       case Dali::Layer::CLIPPING_ENABLE:
457       {
458         SetClipping( propertyValue.Get<bool>() );
459         break;
460       }
461       case Dali::Layer::CLIPPING_BOX:
462       {
463         Rect<int> clippingBox( propertyValue.Get<Rect<int> >() );
464         SetClippingBox( clippingBox.x, clippingBox.y, clippingBox.width, clippingBox.height );
465         break;
466       }
467       default:
468       {
469         DALI_LOG_WARNING("Unknown property (%d)\n", index);
470         break;
471       }
472     } // switch(index)
473
474   } // else
475 }
476
477 Property::Value Layer::GetDefaultProperty( Property::Index index ) const
478 {
479   Property::Value ret;
480   if(index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT)
481   {
482     ret = Actor::GetDefaultProperty(index);
483   }
484   else
485   {
486     switch(index)
487     {
488       case Dali::Layer::CLIPPING_ENABLE:
489       {
490         ret = mIsClipping;
491         break;
492       }
493       case Dali::Layer::CLIPPING_BOX:
494       {
495         ret = mClippingBox;
496         break;
497       }
498       default:
499       {
500         DALI_LOG_WARNING("Unknown property (%d)\n", index);
501         break;
502       }
503     } // switch(index)
504   }
505
506   return ret;
507 }
508
509 bool Layer::DoAction( BaseObject* object, const std::string& actionName, const std::vector<Property::Value>& attributes )
510 {
511   bool done = false;
512   Layer* layer = dynamic_cast<Layer*>( object );
513
514   if( layer )
515   {
516     if( 0 == strcmp( actionName.c_str(), ACTION_RAISE ) )
517     {
518       layer->Raise();
519       done = true;
520     }
521     else if( 0 == strcmp( actionName.c_str(), ACTION_LOWER ) )
522     {
523       layer->Lower();
524       done = true;
525     }
526     else if( 0 == strcmp( actionName.c_str(), ACTION_RAISE_TO_TOP ) )
527     {
528       layer->RaiseToTop();
529       done = true;
530     }
531     else if( 0 == strcmp( actionName.c_str(), ACTION_LOWER_TO_BOTTOM ) )
532     {
533       layer->LowerToBottom();
534       done = true;
535     }
536   }
537
538   return done;
539 }
540
541 } // namespace Internal
542
543 } // namespace Dali
544