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