Change layout item list order according to the actor's child list
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / devel-api / layouting / layout-group-impl.cpp
1 /*
2  * Copyright (c) 2018 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 // CLASS HEADER
18 #include <dali-toolkit/devel-api/layouting/layout-group-impl.h>
19
20 // EXTERNAL INCLUDES
21 #include <dali/public-api/object/type-registry-helper.h>
22 #include <dali/devel-api/actors/actor-devel.h>
23 #include <dali/devel-api/object/handle-devel.h>
24 #include <dali/integration-api/debug.h>
25
26 // INTERNAL INCLUDES
27 #include <dali-toolkit/internal/layouting/layout-group-data-impl.h>
28 #include <dali-toolkit/public-api/controls/control-impl.h>
29 #include <dali-toolkit/internal/controls/control/control-data-impl.h>
30
31 namespace
32 {
33 #if defined(DEBUG_ENABLED)
34 Debug::Filter* gLogFilter = Debug::Filter::New( Debug::NoLogging, false, "LOG_LAYOUT" );
35 #endif
36 }
37
38 namespace Dali
39 {
40 namespace Toolkit
41 {
42 namespace Internal
43 {
44
45 LayoutGroup::LayoutGroup()
46 : mImpl( new LayoutGroup::Impl() ),
47   mSlotDelegate(this)
48 {
49 }
50
51 LayoutGroup::~LayoutGroup()
52 {
53   // An object with a unique_ptr to an opaque structure must define it's destructor in the translation unit
54   // where the opaque structure is defined. It cannot use the default method in the header file.
55 }
56
57 Toolkit::LayoutGroup::LayoutId LayoutGroup::Add( LayoutItem& child )
58 {
59   LayoutParent* oldParent = child.GetParent();
60   if( oldParent )
61   {
62     LayoutGroupPtr parentGroup( dynamic_cast< LayoutGroup* >( oldParent ) );
63     if( parentGroup )
64     {
65       parentGroup->Remove( child );
66     }
67   }
68
69   Impl::ChildLayout childLayout;
70   childLayout.layoutId = mImpl->mNextLayoutId++;
71   childLayout.child = &child;
72   mImpl->mChildren.emplace_back( childLayout );
73
74   child.SetParent( this );
75
76   auto owner = child.GetOwner();
77
78   // If the owner does not have any LayoutItem child properties, add them
79   if( ! DevelHandle::DoesCustomPropertyExist( owner, Toolkit::LayoutItem::ChildProperty::WIDTH_SPECIFICATION ) )
80   {
81     // Set default properties for LayoutGroup and LayoutItem.
82     // Deriving classes can override OnChildAdd() to add their own default properties
83     GenerateDefaultChildPropertyValues( owner );
84   }
85
86   // Inform deriving classes that this child has been added
87   OnChildAdd( *childLayout.child.Get() );
88
89   // Now listen to future changes to the child properties.
90   DevelHandle::PropertySetSignal(owner).Connect( this, &LayoutGroup::OnSetChildProperties );
91
92   RequestLayout();
93
94   return childLayout.layoutId;
95 }
96
97 void LayoutGroup::Remove( Toolkit::LayoutGroup::LayoutId childId )
98 {
99   for( auto iter = mImpl->mChildren.begin() ; iter != mImpl->mChildren.end() ; ++iter )
100   {
101     if( iter->layoutId == childId )
102     {
103       RemoveChild( *iter->child.Get() );
104       mImpl->mChildren.erase(iter);
105       break;
106     }
107   }
108   RequestLayout();
109 }
110
111 void LayoutGroup::Remove( LayoutItem& child )
112 {
113   for( auto iter = mImpl->mChildren.begin() ; iter != mImpl->mChildren.end() ; ++iter )
114   {
115     if( iter->child.Get() == &child )
116     {
117       RemoveChild( *iter->child.Get() );
118       mImpl->mChildren.erase(iter);
119       break;
120     }
121   }
122   RequestLayout();
123 }
124
125 Toolkit::LayoutGroup::LayoutId LayoutGroup::Insert( LayoutItem& target, LayoutItem& child )
126 {
127   LayoutParent* oldParent = child.GetParent();
128   if( oldParent )
129   {
130     LayoutGroupPtr parentGroup( dynamic_cast< LayoutGroup* >( oldParent ) );
131     if( parentGroup )
132     {
133       parentGroup->Remove( child );
134     }
135   }
136
137   // Find target position
138   std::vector< Impl::ChildLayout >::iterator position;
139   for( auto iter = mImpl->mChildren.begin(); iter != mImpl->mChildren.end(); ++iter )
140   {
141     if( iter->child.Get() == &target )
142     {
143       position = iter;
144       break;
145     }
146   }
147
148   Impl::ChildLayout childLayout;
149   childLayout.layoutId = mImpl->mNextLayoutId++;
150   childLayout.child = &child;
151   mImpl->mChildren.insert( position, childLayout );
152
153   child.SetParent( this );
154
155   auto owner = child.GetOwner();
156
157   // Inform deriving classes that this child has been added
158   OnChildAdd( *childLayout.child.Get() );
159
160   // Now listen to future changes to the child properties.
161   DevelHandle::PropertySetSignal(owner).Connect( this, &LayoutGroup::OnSetChildProperties );
162
163   RequestLayout();
164
165   return childLayout.layoutId;
166 }
167
168 Toolkit::LayoutGroup::LayoutId LayoutGroup::Move( LayoutItem& target, LayoutItem& child )
169 {
170   // Remove child from the previous position
171   for( auto iter = mImpl->mChildren.begin() ; iter != mImpl->mChildren.end() ; ++iter )
172   {
173     if( iter->child.Get() == &child )
174     {
175       mImpl->mChildren.erase( iter );
176       break;
177     }
178   }
179
180   // Find target position
181   std::vector< Impl::ChildLayout >::iterator position;
182   for( auto iter = mImpl->mChildren.begin(); iter != mImpl->mChildren.end(); ++iter )
183   {
184     if( iter->child.Get() == &target )
185     {
186       position = iter;
187       break;
188     }
189   }
190
191   Impl::ChildLayout childLayout;
192   childLayout.layoutId = mImpl->mNextLayoutId++;
193   childLayout.child = &child;
194   mImpl->mChildren.insert( position, childLayout );
195
196   RequestLayout();
197
198   return childLayout.layoutId;
199 }
200
201 Toolkit::LayoutGroup::LayoutId LayoutGroup::MoveBack( LayoutItem& child )
202 {
203   // Remove child from the previous position
204   for( auto iter = mImpl->mChildren.begin() ; iter != mImpl->mChildren.end() ; ++iter )
205   {
206     if( iter->child.Get() == &child )
207     {
208       mImpl->mChildren.erase( iter );
209       break;
210     }
211   }
212
213   Impl::ChildLayout childLayout;
214   childLayout.layoutId = mImpl->mNextLayoutId++;
215   childLayout.child = &child;
216   mImpl->mChildren.emplace_back( childLayout );
217
218   RequestLayout();
219
220   return childLayout.layoutId;
221 }
222
223 void LayoutGroup::RemoveAll()
224 {
225   for( auto iter = mImpl->mChildren.begin() ; iter != mImpl->mChildren.end() ; )
226   {
227     RemoveChild( *iter->child.Get() );
228     iter = mImpl->mChildren.erase(iter);
229   }
230 }
231
232 unsigned int LayoutGroup::GetChildCount() const
233 {
234   return mImpl->mChildren.size();
235 }
236
237 LayoutItemPtr LayoutGroup::GetChildAt( unsigned int index ) const
238 {
239   DALI_ASSERT_ALWAYS( index < mImpl->mChildren.size() );
240   return mImpl->mChildren[ index ].child;
241 }
242
243 LayoutItemPtr LayoutGroup::GetChild( Toolkit::LayoutGroup::LayoutId childId ) const
244 {
245   for( auto&& childLayout : mImpl->mChildren )
246   {
247     if( childLayout.layoutId == childId )
248     {
249       return childLayout.child;
250     }
251   }
252   return NULL;
253 }
254
255 Toolkit::LayoutGroup::LayoutId LayoutGroup::GetChildId( LayoutItem& child ) const
256 {
257   for( auto&& childLayout : mImpl->mChildren )
258   {
259     if( childLayout.child.Get() == &child )
260     {
261       return childLayout.layoutId;
262     }
263   }
264   return Toolkit::LayoutGroup::UNKNOWN_ID;
265 }
266
267 void LayoutGroup::OnChildAdd( LayoutItem& child )
268 {
269 }
270
271 void LayoutGroup::OnChildRemove( LayoutItem& child )
272 {
273 }
274
275 void LayoutGroup::DoInitialize()
276 {
277 }
278
279 void LayoutGroup::DoRegisterChildProperties( const std::string& containerType )
280 {
281 }
282
283 void LayoutGroup::OnSetChildProperties( Handle& handle, Property::Index index, Property::Value value )
284 {
285   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "LayoutGroup::OnSetChildProperties property(%s)\n", handle.GetPropertyName(index).c_str());
286
287   if ( ( ( index >= CHILD_PROPERTY_REGISTRATION_START_INDEX ) &&
288          ( index <= CHILD_PROPERTY_REGISTRATION_MAX_INDEX ) )
289        ||
290        ( index == Toolkit::Control::Property::MARGIN || index == Toolkit::Control::Property::PADDING ) )
291   {
292     // If any child properties are set, must perform relayout
293     for( auto&& child : mImpl->mChildren )
294     {
295       if( child.child->GetOwner() == handle )
296       {
297         child.child->RequestLayout();
298         break;
299       }
300     }
301   }
302 }
303
304 void LayoutGroup::GenerateDefaultChildPropertyValues( Handle child )
305 {
306   child.SetProperty( Toolkit::LayoutItem::ChildProperty::WIDTH_SPECIFICATION,
307                      Toolkit::ChildLayoutData::WRAP_CONTENT );
308   child.SetProperty( Toolkit::LayoutItem::ChildProperty::HEIGHT_SPECIFICATION,
309                      Toolkit::ChildLayoutData::WRAP_CONTENT );
310 }
311
312 void LayoutGroup::MeasureChildren( MeasureSpec widthMeasureSpec, MeasureSpec heightMeasureSpec)
313 {
314   for( auto&& child : mImpl->mChildren )
315   {
316     //if( (child.mViewFlags & Impl::VISIBILITY_MASK) != Impl::GONE ) // Use owner visibility/enabled/ready
317     {
318       MeasureChild( child.child, widthMeasureSpec, heightMeasureSpec );
319     }
320   }
321 }
322
323 void LayoutGroup::MeasureChild( LayoutItemPtr child,
324                                 MeasureSpec parentWidthMeasureSpec,
325                                 MeasureSpec parentHeightMeasureSpec )
326 {
327   DALI_LOG_TRACE_METHOD( gLogFilter );
328
329   auto childOwner = child->GetOwner();
330
331   auto control = Toolkit::Control::DownCast( childOwner );
332
333 #if defined( DEBUG_ENABLED )
334   if ( control )
335   {
336     DALI_LOG_INFO( gLogFilter, Debug::Verbose, "LayoutGroup::MeasureChild natural size(%f, %f)\n",  control.GetNaturalSize().width, control.GetNaturalSize().height );
337   }
338 #endif
339
340   // Get last stored width and height specifications for the child
341   auto desiredWidth = childOwner.GetProperty<int>( Toolkit::LayoutItem::ChildProperty::WIDTH_SPECIFICATION );
342   auto desiredHeight = childOwner.GetProperty<int>( Toolkit::LayoutItem::ChildProperty::HEIGHT_SPECIFICATION );
343   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "LayoutGroup::MeasureChild desiredWidth(%d) desiredHeight(%d)\n", desiredWidth, desiredHeight );
344
345   auto padding = GetPadding(); // Padding of this layout's owner, not of the child being measured.
346
347   const MeasureSpec childWidthMeasureSpec = GetChildMeasureSpec( parentWidthMeasureSpec,
348                                                                  padding.start + padding.end,
349                                                                  desiredWidth);
350   const MeasureSpec childHeightMeasureSpec = GetChildMeasureSpec( parentHeightMeasureSpec,
351                                                                   padding.top + padding.bottom,
352                                                                   desiredHeight);
353
354   child->Measure( childWidthMeasureSpec, childHeightMeasureSpec );
355 }
356
357 void LayoutGroup::MeasureChildWithMargins( LayoutItemPtr child,
358                                            MeasureSpec parentWidthMeasureSpec, LayoutLength widthUsed,
359                                            MeasureSpec parentHeightMeasureSpec, LayoutLength heightUsed)
360 {
361   auto childOwner = child->GetOwner();
362   auto desiredWidth = childOwner.GetProperty<int>( Toolkit::LayoutItem::ChildProperty::WIDTH_SPECIFICATION );
363   auto desiredHeight = childOwner.GetProperty<int>( Toolkit::LayoutItem::ChildProperty::HEIGHT_SPECIFICATION );
364
365   auto padding = GetPadding(); // Padding of this layout's owner, not of the child being measured.
366
367   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "LayoutGroup::MeasureChildWithMargins desiredWidth(%d)\n",  desiredWidth );
368
369   MeasureSpec childWidthMeasureSpec = GetChildMeasureSpec( parentWidthMeasureSpec,
370                                                            padding.start + padding.end +
371                                                            widthUsed, desiredWidth );
372
373   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "LayoutGroup::MeasureChildWithMargins desiredHeight(%d)\n",  desiredHeight );
374
375   MeasureSpec childHeightMeasureSpec = GetChildMeasureSpec( parentHeightMeasureSpec,
376                                                             padding.top + padding.bottom +
377                                                             heightUsed, desiredHeight );
378
379   child->Measure( childWidthMeasureSpec, childHeightMeasureSpec );
380 }
381
382
383 MeasureSpec LayoutGroup::GetChildMeasureSpec(
384   MeasureSpec  measureSpec,
385   LayoutLength padding,
386   LayoutLength childDimension )
387 {
388   auto specMode = measureSpec.GetMode();
389   LayoutLength specSize = measureSpec.GetSize();
390
391   auto size = std::max( LayoutLength(0), specSize - padding ); // reduce available size by the owners padding
392
393   MeasureSpec::IntType resultSize = 0;
394   MeasureSpec::Mode resultMode = MeasureSpec::Mode::UNSPECIFIED;
395
396   switch( specMode )
397   {
398     // Parent has imposed an exact size on us
399     case MeasureSpec::Mode::EXACTLY:
400     {
401       DALI_LOG_INFO( gLogFilter, Debug::Verbose, "LayoutGroup::GetChildMeasureSpec MeasureSpec::Mode::EXACTLY\n");
402       if (childDimension == Toolkit::ChildLayoutData::MATCH_PARENT)
403       {
404         DALI_LOG_INFO( gLogFilter, Debug::Verbose, "LayoutGroup::GetChildMeasureSpec childDimension MATCH_PARENT\n");
405
406         // Child wants to be our size. So be it.
407         resultSize = size;
408         resultMode = MeasureSpec::Mode::EXACTLY;
409       }
410       else if (childDimension == Toolkit::ChildLayoutData::WRAP_CONTENT)
411       {
412         DALI_LOG_INFO( gLogFilter, Debug::Verbose, "LayoutGroup::GetChildMeasureSpec childDimension WRAP_CONTENT\n");
413
414         // Child wants to determine its own size. It can't be
415         // bigger than us.
416         resultSize = size;
417         resultMode = MeasureSpec::Mode::AT_MOST;
418       }
419       else
420       {
421         DALI_LOG_INFO( gLogFilter, Debug::Verbose, "LayoutGroup::GetChildMeasureSpec childDimension UNSPECIFIED\n");
422         resultSize = childDimension;
423         resultMode = MeasureSpec::Mode::EXACTLY;
424       }
425
426       break;
427     }
428
429       // Parent has imposed a maximum size on us
430     case MeasureSpec::Mode::AT_MOST:
431     {
432       DALI_LOG_INFO( gLogFilter, Debug::Verbose, "LayoutGroup::GetChildMeasureSpec MeasureSpec::Mode::AT_MOST\n");
433       if (childDimension == Toolkit::ChildLayoutData::MATCH_PARENT)
434       {
435         // Child wants to be our size, but our size is not fixed.
436         // Constrain child to not be bigger than us.
437         resultSize = size;
438         resultMode = MeasureSpec::Mode::AT_MOST;
439       }
440       else if (childDimension == Toolkit::ChildLayoutData::WRAP_CONTENT)
441       {
442         // Child wants to determine its own size. It can't be
443         // bigger than us.
444         resultSize = size;
445         resultMode = MeasureSpec::Mode::AT_MOST;
446       }
447       else
448       {
449         // Child wants a specific size... so be it
450         resultSize = childDimension + padding;
451         resultMode = MeasureSpec::Mode::EXACTLY;
452       }
453
454       break;
455     }
456
457       // Parent asked to see how big we want to be
458     case MeasureSpec::Mode::UNSPECIFIED:
459     {
460       DALI_LOG_INFO( gLogFilter, Debug::Verbose, "LayoutGroup::GetChildMeasureSpec MeasureSpec::Mode::UNSPECIFIED\n");
461
462       if (childDimension == Toolkit::ChildLayoutData::MATCH_PARENT)
463       {
464         // Child wants to be our size... find out how big it should be
465         resultSize = LayoutItem::Impl::sUseZeroUnspecifiedMeasureSpec ? LayoutLength(0) : size;
466         resultMode = MeasureSpec::Mode::UNSPECIFIED;
467       }
468       else if (childDimension == Toolkit::ChildLayoutData::WRAP_CONTENT)
469       {
470         // Child wants to determine its own size.... find out how big
471         // it should be
472         resultSize = LayoutItem::Impl::sUseZeroUnspecifiedMeasureSpec ? LayoutLength(0) : size;
473         resultMode = MeasureSpec::Mode::UNSPECIFIED;
474       }
475       else
476       {
477         // Child wants a specific size... let him have it
478         resultSize = childDimension + padding;
479         resultMode = MeasureSpec::Mode::EXACTLY;
480       }
481       break;
482     }
483   }
484
485   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "LayoutGroup::GetChildMeasureSpec resultSize(%u)\n", resultSize );
486
487
488   //noinspection ResourceType
489   return MeasureSpec( resultSize, resultMode );
490 }
491
492
493 void LayoutGroup::OnInitialize()
494 {
495   auto control = Toolkit::Control::DownCast( GetOwner() );
496
497   if( control )
498   {
499     // Take ownership of existing children
500     for( unsigned int childIndex = 0 ; childIndex < control.GetChildCount(); ++childIndex )
501     {
502       ChildAddedToOwner( control.GetChildAt( childIndex ) );
503     }
504
505     DevelActor::ChildAddedSignal( control ).Connect( mSlotDelegate, &LayoutGroup::ChildAddedToOwner );
506     DevelActor::ChildRemovedSignal( control ).Connect( mSlotDelegate, &LayoutGroup::ChildRemovedFromOwner );
507     DevelActor::ChildOrderChangedSignal( control ).Connect( mSlotDelegate, &LayoutGroup::ChildOrderChanged );
508     DevelHandle::PropertySetSignal( control ).Connect( mSlotDelegate, &LayoutGroup::OnOwnerPropertySet );
509
510     if( control.GetParent() )
511     {
512       auto parent = Toolkit::Control::DownCast( control.GetParent() );
513       if( parent )
514       {
515         auto parentLayout = Toolkit::LayoutGroup::DownCast( DevelControl::GetLayout( parent ) );
516         if( parentLayout )
517         {
518           Internal::LayoutGroup& parentLayoutImpl = GetImplementation( parentLayout );
519
520           unsigned int count = parent.GetChildCount();
521           unsigned int index = static_cast< unsigned int >( control.GetProperty< int >( DevelActor::Property::SIBLING_ORDER ) );
522
523           // Find insertion position
524           while( ++index < count )
525           {
526             auto sibling = Toolkit::Control::DownCast( parent.GetChildAt( index ) );
527             if( sibling )
528             {
529               auto siblingLayout = DevelControl::GetLayout( sibling );
530               if( siblingLayout )
531               {
532                 Internal::LayoutItem& siblingLayoutImpl = GetImplementation( siblingLayout );
533                 parentLayoutImpl.Insert( siblingLayoutImpl, *this );
534                 break;
535               }
536             }
537           }
538
539           if( index >= count )
540           {
541             parentLayoutImpl.Add( *this );
542           }
543         }
544       }
545     }
546   }
547 }
548
549 void LayoutGroup::OnRegisterChildProperties( const std::string& containerType )
550 {
551   DoRegisterChildProperties( containerType );
552 }
553
554 void LayoutGroup::OnUnparent()
555 {
556   // Remove children
557   RemoveAll();
558 }
559
560 void LayoutGroup::RemoveChild( LayoutItem& item )
561 {
562   item.SetParent( nullptr );
563   OnChildRemove( item );
564 }
565
566 void LayoutGroup::ChildAddedToOwner( Actor child )
567 {
568   LayoutItemPtr childLayout;
569   Toolkit::Control control = Toolkit::Control::DownCast( child );
570
571   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "LayoutGroup::ChildAddedToOwner control(%s)\n", control?control.GetName().c_str():"Invalid" );
572
573   if( control ) // Can only support adding Controls, not Actors to layout
574   {
575     Internal::Control& childControlImpl = GetImplementation( control );
576     Internal::Control::Impl& childControlDataImpl = Internal::Control::Impl::Get( childControlImpl );
577     childLayout = childControlDataImpl.GetLayout();
578
579     if( ! childLayout )
580     {
581       // If the child doesn't already have a layout, then create a LayoutItem for it.
582       childLayout = LayoutItem::New( control );
583       childLayout->SetAnimateLayout( IsLayoutAnimated() ); // @todo this essentially forces animation inheritance. Bad?
584 #if defined(DEBUG_ENABLED)
585       auto desiredSize = control.GetNaturalSize();
586       DALI_LOG_INFO( gLogFilter, Debug::Verbose, "LayoutGroup::ChildAddedToOwner desiredSize(%f,%f) (naturalSize)\n", desiredSize.width, desiredSize.height );
587 #endif
588       childControlDataImpl.SetLayout( *childLayout.Get() );
589
590       Vector3 size = child.GetTargetSize();
591       // If the size of the control is set explicitly make sure that the control size
592       // stays the same after the layout except it is over written with match parent specs.
593       if ( size.x != 0 )
594       {
595         childLayout->SetMinimumWidth( size.x );
596       }
597
598       if ( size.y != 0 )
599       {
600         childLayout->SetMinimumHeight( size.y );
601       }
602       // Default layout data will be generated by Add().
603     }
604     else
605     {
606       LayoutGroupPtr layoutGroup( dynamic_cast< LayoutGroup* >( childLayout.Get() ) );
607       if( !layoutGroup )
608       {
609         // Set only in case of leaf children
610         childLayout->SetAnimateLayout( IsLayoutAnimated() );
611       }
612     }
613
614     Add( *childLayout.Get() );
615   }
616 }
617
618 void LayoutGroup::ChildRemovedFromOwner( Actor child )
619 {
620   Toolkit::Control control = Toolkit::Control::DownCast( child );
621   if( control )
622   {
623     Internal::Control& childControlImpl = GetImplementation( control );
624     Internal::Control::Impl& childControlDataImpl = Internal::Control::Impl::Get( childControlImpl );
625     auto childLayout = childControlDataImpl.GetLayout();
626     if( childLayout )
627     {
628       Remove( *childLayout.Get() );
629     }
630   }
631 }
632
633 void LayoutGroup::ChildOrderChanged( Actor child )
634 {
635   Toolkit::Control childControl = Toolkit::Control::DownCast( child );
636   if( childControl )
637   {
638     Internal::Control& childControlImpl = GetImplementation( childControl );
639     Internal::Control::Impl& childControlDataImpl = Internal::Control::Impl::Get( childControlImpl );
640
641     auto childLayout = childControlDataImpl.GetLayout();
642     if( childLayout )
643     {
644       Toolkit::Control control = Toolkit::Control::DownCast( GetOwner() );
645       unsigned int count = control.GetChildCount();
646       unsigned int index = static_cast< unsigned int >( childControl.GetProperty< int >( DevelActor::Property::SIBLING_ORDER ) );
647
648       // Find insertion position
649       while( ++index < count )
650       {
651         auto sibling = Toolkit::Control::DownCast( control.GetChildAt( index ) );
652         if( sibling )
653         {
654           auto siblingLayout = DevelControl::GetLayout( sibling );
655           if( siblingLayout )
656           {
657             Internal::LayoutItem& siblingLayoutImpl = GetImplementation( siblingLayout );
658             Move( siblingLayoutImpl, *childLayout );
659             return;
660           }
661         }
662       }
663
664       MoveBack( *childLayout );
665     }
666   }
667 }
668
669 void LayoutGroup::OnOwnerPropertySet( Handle& handle, Property::Index index, Property::Value value )
670 {
671   DALI_LOG_INFO( gLogFilter, Debug::Concise, "LayoutGroup::OnOwnerPropertySet\n");
672   auto actor = Actor::DownCast( handle );
673   if( actor &&
674       (
675         index == Actor::Property::LAYOUT_DIRECTION  ||
676         index == Toolkit::Control::Property::PADDING  ||
677         index == Toolkit::Control::Property::MARGIN
678       )
679     )
680   {
681     RequestLayout();
682   }
683 }
684
685 void LayoutGroup::OnAnimationStateChanged( bool animateLayout )
686 {
687   // Change children's animation state
688   for( auto&& child : mImpl->mChildren )
689   {
690     LayoutGroupPtr parentGroup( dynamic_cast< LayoutGroup* >( child.child.Get() ) );
691     if( !parentGroup )
692     {
693       // Change state only in case of leaf children
694       child.child->SetAnimateLayout( animateLayout );
695     }
696   }
697 }
698
699 } // namespace Internal
700 } // namespace Toolkit
701 } // namespace Dali