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