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