Fix compile errors after removing boost function include from dali-core
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / controls / cluster / cluster-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-toolkit/internal/controls/cluster/cluster-impl.h>
20
21 // EXTERNAL INCLUDES
22 #include <algorithm>
23 #include <cstring> // for strcmp
24 #include <dali/public-api/animation/animation.h>
25 #include <dali/public-api/object/type-registry.h>
26 #include <dali/public-api/object/type-registry-helper.h>
27 #include <dali/integration-api/debug.h>
28
29 // INTERNAL INCLUDES
30 #include <dali-toolkit/public-api/controls/cluster/cluster-style.h>
31 #include <dali-toolkit/internal/controls/cluster/cluster-style-impl.h>
32
33 using namespace Dali;
34
35 namespace Dali
36 {
37
38 namespace Toolkit
39 {
40
41 namespace Internal
42 {
43
44 namespace
45 {
46
47 BaseHandle Create()
48 {
49   Toolkit::ClusterStyleStandard s = Toolkit::ClusterStyleStandard::New( Toolkit::ClusterStyleStandard::ClusterStyle1 );
50   return Toolkit::Cluster::New( s );
51 }
52
53 DALI_TYPE_REGISTRATION_BEGIN( Toolkit::Cluster, Toolkit::Control, Create )
54
55 DALI_ACTION_REGISTRATION( Cluster, "expand",    ACTION_EXPAND    )
56 DALI_ACTION_REGISTRATION( Cluster, "collapse",  ACTION_COLLAPSE  )
57 DALI_ACTION_REGISTRATION( Cluster, "transform", ACTION_TRANSFORM )
58
59 DALI_TYPE_REGISTRATION_END()
60
61 const float CLUSTER_STYLE_CONSTRAINT_DURATION = 1.0f;
62
63 }
64
65 ///////////////////////////////////////////////////////////////////////////////////////////////////
66 // Cluster
67 ///////////////////////////////////////////////////////////////////////////////////////////////////
68
69 Dali::Toolkit::Cluster Cluster::New(Toolkit::ClusterStyle& style)
70 {
71   // Create the implementation
72   ClusterPtr cluster(new Cluster(style));
73
74   // Pass ownership to CustomActor via derived handle
75   Dali::Toolkit::Cluster handle(*cluster);
76
77   // Second-phase init of the implementation
78   // This can only be done after the CustomActor connection has been made...
79   cluster->Initialize();
80
81   return handle;
82 }
83
84 Cluster::Cluster(Toolkit::ClusterStyle& style)
85 : Control( ControlBehaviour( REQUIRES_TOUCH_EVENTS | REQUIRES_STYLE_CHANGE_SIGNALS ) ),
86   mClusterStyle(style),
87   mExpandedCount(0)
88 {
89 }
90
91 void Cluster::OnInitialize()
92 {
93 }
94
95 void Cluster::OnControlSizeSet( const Vector3& targetSize )
96 {
97   mClusterSize = targetSize;
98   GetImpl(mClusterStyle).SetClusterSize(targetSize);
99
100   for(ChildInfoIter iter = mChildren.begin(); iter != mChildren.end(); ++iter)
101   {
102
103     if((*iter).mActor)
104     {
105       mClusterStyle.ApplyStyle( (*iter).mActor,
106                                 (*iter).mPositionIndex,
107                                 AlphaFunctions::EaseOut,
108                                 0.f );
109     }
110   }
111
112   UpdateBackground(0.f);
113   UpdateTitle(0.f);
114 }
115
116 Cluster::~Cluster()
117 {
118 }
119
120 void Cluster::AddChild( Actor child )
121 {
122   // automatically add child with a position at end.
123   AddChild( child, mChildren.size() );
124 }
125
126 void Cluster::AddChild( Actor child, unsigned int positionIndex )
127 {
128   AddChildInfo( ChildInfo(child, positionIndex) );
129 }
130
131 void Cluster::AddChildAt( Actor child, unsigned int index )
132 {
133   // automatically add child with a position at end.
134   AddChild( child, mChildren.size() );
135 }
136
137 void Cluster::AddChildAt( Actor child, unsigned int positionIndex, unsigned int index )
138 {
139   AddChildInfoAt( ChildInfo(child, positionIndex), index );
140 }
141
142 void Cluster::AddChildInfo( ChildInfo childInfo )
143 {
144   AddChildInfoAt(childInfo, mChildren.size());
145 }
146
147 void Cluster::AddChildInfoAt( ChildInfo childInfo, unsigned int index )
148 {
149   // check that the child is valid
150   DALI_ASSERT_ALWAYS( childInfo.mActor );
151
152   ChildInfoIter offset = index < mChildren.size() ? (mChildren.begin() + index) : mChildren.end();
153   // now perform customization on this child.
154
155   // adopt the child
156   if(childInfo.mActor.GetParent() != Self())
157   {
158     Actor& child = childInfo.mActor;
159     const float depth = std::distance(mChildren.begin(), offset);
160
161     Property::Index depthProperty = child.GetPropertyIndex(Toolkit::Cluster::CLUSTER_ACTOR_DEPTH);
162     if(depthProperty == Property::INVALID_INDEX)
163     {
164       child.RegisterProperty(Toolkit::Cluster::CLUSTER_ACTOR_DEPTH, depth);
165     }
166
167     // not added prior
168     Self().Add( childInfo.mActor );
169     mChildren.insert( offset, childInfo );
170
171     // Use parent position plus relative position.
172     child.SetPositionInheritanceMode( Dali::USE_PARENT_POSITION_PLUS_LOCAL_POSITION );
173
174     // remove old constraints
175     child.RemoveConstraints();
176
177     // apply new constraints to the child
178     mClusterStyle.ApplyStyle(child, childInfo.mPositionIndex, AlphaFunctions::EaseOut, 0.0f);
179   }
180   else
181   {
182     // already added.
183     ChildInfoContainer mNewChildren;
184     ChildInfoIter iter = mChildren.begin();
185     float depth = 0.0f;
186
187     for( ; iter != mChildren.end(); ++iter)
188     {
189       if(iter == offset)
190       {
191         SetDepth(childInfo, depth);
192         depth++;
193         // insert the new childInfo before offset.
194         mNewChildren.push_back(childInfo);
195       }
196       // copy all children except the one that we wish to move.
197       if((*iter).mActor != childInfo.mActor)
198       {
199         SetDepth(*iter, depth);
200         depth++;
201         mNewChildren.push_back(*iter);
202       }
203     } // end for.
204
205     if(iter == offset)
206     {
207       SetDepth(childInfo, depth);
208       // insert the new childInfo before offset (end).
209       mNewChildren.push_back(childInfo);
210     }
211
212     mChildren = mNewChildren;
213
214     // Todo somehow adjust their perceived depth.
215   }
216 }
217
218 void Cluster::SetDepth( ChildInfo& childInfo, float depth )
219 {
220   Property::Index depthProperty = childInfo.mActor.GetPropertyIndex(Toolkit::Cluster::CLUSTER_ACTOR_DEPTH);
221   childInfo.mActor.SetProperty( depthProperty, depth );
222 }
223
224 ChildInfo Cluster::GetChildInfoAt( unsigned int index )
225 {
226   // check if we have this position in the cluster
227   if( index < mChildren.size() )
228   {
229     // return the child handle
230     return mChildren[ index ];
231   }
232
233   // return an empty handle
234   return ChildInfo();
235 }
236
237 Actor Cluster::GetChildAt( unsigned int index )
238 {
239   // check if we have this position in the cluster
240   if( index < mChildren.size() )
241   {
242     // return the child handle
243     return mChildren[ index ].mActor;
244   }
245
246   // return an empty handle
247   return Actor();
248 }
249
250 Actor Cluster::RemoveChildAt( unsigned int index )
251 {
252   DALI_ASSERT_ALWAYS( index < mChildren.size() );
253
254   ChildInfoIter iter = mChildren.begin() + index;
255   Actor child = (*iter).mActor;
256   mChildren.erase( iter );
257   Self().Remove(child);
258   // note: constraints will automatically be removed in OnControlChildRemove
259
260   // update depths.
261   float depth = 0.0f;
262
263   for(ChildInfoIter iter = mChildren.begin(); iter != mChildren.end(); ++iter)
264   {
265     SetDepth(*iter, depth);
266     depth++;
267   } // end for.
268
269   return child;
270 }
271
272 void Cluster::ExpandChild( unsigned int index )
273 {
274   if( index < mChildren.size() )
275   {
276     ChildInfo& childInfo = mChildren[ index ];
277     DALI_ASSERT_ALWAYS(childInfo.mActor);
278
279     if(!childInfo.mExpanded)
280     {
281       // expand child to a random position/angle.
282       const Vector3 clusterSize = Self().GetCurrentSize();
283       const float length = clusterSize.Length() * 0.1f;
284       const float zOffset = 50.0f;
285       const float angle = (rand()%360) * Math::PI / 180.0f;
286       Vector3 position(sin(angle) * length, -cos(angle) * length, zOffset);
287       const float scale(1.2f);
288       const float rotate = ((rand()%30) - 15) * Math::PI / 180.0f;
289
290       position += childInfo.mActor.GetCurrentPosition();
291
292       TransformChild(index,
293                      position,
294                      Vector3::ONE * scale,
295                      Quaternion(rotate, Vector3::ZAXIS),
296                      AlphaFunctions::EaseOut,
297                      0.5f);
298     }
299   }
300 }
301
302 void Cluster::ExpandAllChildren()
303 {
304   for(unsigned int index = 0;index < mChildren.size(); index++)
305   {
306     ExpandChild( index );
307   }
308 }
309
310 void Cluster::CollapseChild( unsigned int index, bool front )
311 {
312   if( index < mChildren.size() )
313   {
314     RestoreChild(index,
315                  AlphaFunctions::EaseOut,
316                  0.25f,
317                  front);
318   }
319 }
320
321 void Cluster::CollapseAllChildren( bool front )
322 {
323   for(unsigned int index = 0;index < mChildren.size(); index++)
324   {
325     RestoreChild(index,
326                  AlphaFunctions::EaseOut,
327                  0.25f,
328                  front);
329   }
330 }
331
332 void Cluster::TransformChild( unsigned int index, const Vector3& position, const Vector3& scale, const Quaternion& rotation, AlphaFunction alpha, const TimePeriod& period )
333 {
334   if( index < mChildren.size() )
335   {
336     ChildInfo& childInfo = mChildren[ index ];
337     DALI_ASSERT_ALWAYS(childInfo.mActor);
338
339     if(!childInfo.mExpanded)
340     {
341       Actor child = childInfo.mActor;
342       childInfo.mExpanded = true;
343       mExpandedCount++;
344
345       child.RemoveConstraints();
346       Animation animation = Animation::New(period.delaySeconds + period.durationSeconds);
347       animation.AnimateTo( Property(child, Actor::Property::POSITION), position, AlphaFunctions::EaseOut, period);
348       animation.AnimateTo( Property(child, Actor::Property::SCALE), scale, AlphaFunctions::EaseOut, period);
349       animation.AnimateTo( Property(child, Actor::Property::ORIENTATION), rotation, AlphaFunctions::EaseOut, period);
350       animation.Play();
351     }
352   }
353 }
354
355 void Cluster::RestoreChild( unsigned int index, AlphaFunction alpha, const TimePeriod& period, bool front )
356 {
357   if( index < mChildren.size() )
358   {
359     ChildInfo& childInfo = mChildren[ index ];
360     DALI_ASSERT_ALWAYS(childInfo.mActor);
361
362     if(childInfo.mExpanded)
363     {
364       Actor child = childInfo.mActor;
365       childInfo.mExpanded = false;
366       mExpandedCount--;
367       mClusterStyle.ApplyStyle( child, childInfo.mPositionIndex, alpha, period );
368
369       const unsigned int hideIndex = front ? mChildren.size() : 0;
370       AddChildInfoAt(childInfo, hideIndex); // move child info to the back or front of the pack.
371     }
372   }
373 }
374
375 void Cluster::SetBackgroundImage( Actor image )
376 {
377   // Replaces the background image.
378   if(mBackgroundImage && mBackgroundImage.GetParent())
379   {
380     mBackgroundImage.GetParent().Remove(mBackgroundImage);
381   }
382
383   mBackgroundImage = image;
384   Self().Add(mBackgroundImage);
385
386   mBackgroundImage.SetAnchorPoint( AnchorPoint::TOP_LEFT );
387   mBackgroundImage.SetParentOrigin( ParentOrigin::TOP_LEFT );
388
389   UpdateBackground(0.0f);
390 }
391
392 void Cluster::SetTitle( Actor text )
393 {
394   // Replaces the title actor.
395   if(mTitle && mTitle.GetParent())
396   {
397     mTitle.GetParent().Remove( mTitle );
398   }
399
400   mTitle = text;
401   Self().Add( mTitle );
402
403   mTitle.SetAnchorPoint( AnchorPoint::TOP_LEFT );
404   mTitle.SetParentOrigin( ParentOrigin::TOP_LEFT );
405
406   UpdateTitle(0.0f);
407 }
408
409 void Cluster::SetStyle(Toolkit::ClusterStyle style)
410 {
411   unsigned int previousChildrenNum = mChildren.size();
412   mClusterStyle = style;
413   GetImpl(mClusterStyle).SetClusterSize(mClusterSize);
414   unsigned int newChildrenNum = mClusterStyle.GetMaximumNumberOfChildren();
415
416   // New style supports less children (remove those that no longer belong)
417   if(newChildrenNum < previousChildrenNum)
418   {
419     ChildInfoIter removeStart = mChildren.begin() + newChildrenNum;
420
421     for(ChildInfoIter iter = removeStart; iter != mChildren.end(); ++iter)
422     {
423       Actor child = (*iter).mActor;
424       child.RemoveConstraints();
425       Self().Remove(child);
426     }
427
428     mChildren.erase( removeStart, mChildren.end() );
429   }
430
431   for(ChildInfoIter iter = mChildren.begin(); iter != mChildren.end(); ++iter)
432   {
433
434     if((*iter).mActor)
435     {
436       mClusterStyle.ApplyStyle( (*iter).mActor,
437                         (*iter).mPositionIndex,
438                         AlphaFunctions::EaseOut,
439                         CLUSTER_STYLE_CONSTRAINT_DURATION );
440     }
441   }
442
443   UpdateBackground(CLUSTER_STYLE_CONSTRAINT_DURATION);
444   UpdateTitle(CLUSTER_STYLE_CONSTRAINT_DURATION);
445 }
446
447 Toolkit::ClusterStyle Cluster::GetStyle() const
448 {
449   return mClusterStyle;
450 }
451
452 unsigned int Cluster::GetExpandedCount() const
453 {
454   return mExpandedCount;
455 }
456
457 unsigned int Cluster::GetTotalCount() const
458 {
459   return mChildren.size();
460 }
461
462 void Cluster::UpdateBackground(float duration)
463 {
464   if (mBackgroundImage)
465   {
466     mClusterStyle.ApplyStyleToBackground(mBackgroundImage, AlphaFunctions::EaseOut, duration);
467   }
468 }
469
470 void Cluster::UpdateTitle(float duration)
471 {
472   if (mTitle)
473   {
474     mClusterStyle.ApplyStyleToTitle(mTitle, AlphaFunctions::EaseOut, duration);
475   }
476 }
477
478 void Cluster::DoExpandAction(const PropertyValueContainer& attributes)
479 {
480   if(attributes.size() >= 1)
481   {
482     for(PropertyValueConstIter iter = attributes.begin(); iter != attributes.end(); ++iter)
483     {
484       const Property::Value& value = *iter;
485
486       DALI_ASSERT_ALWAYS(value.GetType() == Property::FLOAT);
487       unsigned int index = value.Get<float>();
488       ExpandChild( index );
489     }
490   }
491   else
492   {
493     ExpandAllChildren();
494   }
495 }
496
497 void Cluster::DoCollapseAction(const PropertyValueContainer& attributes)
498 {
499   if(attributes.size() >= 1)
500   {
501     for(PropertyValueConstIter iter = attributes.begin(); iter != attributes.end(); ++iter)
502     {
503       const Property::Value& value = *iter;
504
505       DALI_ASSERT_ALWAYS(value.GetType() == Property::FLOAT);
506       unsigned int index = value.Get<float>();
507       CollapseChild( index, false );
508     }
509   }
510   else
511   {
512     CollapseAllChildren( false );
513   }
514 }
515
516 void Cluster::DoTransformAction(const PropertyValueContainer& attributes)
517 {
518   DALI_ASSERT_ALWAYS(attributes.size() >= 2);
519
520   DALI_ASSERT_ALWAYS(attributes[0].GetType() == Property::FLOAT);
521   unsigned int index = attributes[0].Get<float>();
522   Vector3 position;
523   Vector3 scale(Vector3::ONE);
524   Quaternion rotation(0.0f, Vector3::ZAXIS);
525
526   DALI_ASSERT_ALWAYS(attributes[1].GetType() == Property::VECTOR3);
527   attributes[1].Get(position);
528
529   if(attributes.size()>2)
530   {
531     attributes[2].Get(scale);
532   }
533
534   if(attributes.size()>3)
535   {
536     attributes[3].Get(rotation);
537   }
538
539   // wrap index around -1 => size - 1
540   index%= mChildren.size();
541
542   TransformChild(index, position, scale, rotation, AlphaFunctions::EaseOut, 0.5f);
543 }
544
545 void Cluster::OnControlChildRemove(Actor& child)
546 {
547   child.RemoveConstraints();
548 }
549
550 bool Cluster::DoAction(BaseObject* object, const std::string& actionName, const PropertyValueContainer& attributes)
551 {
552   bool ret = false;
553
554   Dali::BaseHandle handle( object );
555
556   Toolkit::Cluster cluster = Toolkit::Cluster::DownCast( handle );
557
558   DALI_ASSERT_ALWAYS( cluster );
559
560   if( 0 == strcmp( actionName.c_str(), ACTION_EXPAND ) )
561   {
562     GetImpl( cluster ).DoExpandAction( attributes );
563     ret = true;
564   }
565   else if( 0 == strcmp( actionName.c_str(), ACTION_COLLAPSE ) )
566   {
567     GetImpl( cluster ).DoCollapseAction( attributes );
568     ret = true;
569   }
570   else if( 0 == strcmp( actionName.c_str(), ACTION_TRANSFORM ) )
571   {
572     GetImpl( cluster ).DoTransformAction( attributes );
573     ret = true;
574   }
575
576   return ret;
577 }
578
579 } // namespace Internal
580
581 } // namespace Toolkit
582
583 } // namespace Dali