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