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