0521bec1f2380e7d85743bb0b311db2e438d7740
[platform/core/uifw/dali-toolkit.git] / optional / dali-toolkit / internal / controls / selectors / rotating-selector-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/selectors/rotating-selector-impl.h>
20
21 // EXTERNAL INCLUDES
22 #include <algorithm>
23 #include <dali/public-api/animation/constraints.h>
24 #include <dali/public-api/events/touch-event.h>
25 #include <dali/public-api/object/type-registry.h>
26
27 // INTERNAL INCLUDES
28 #include <dali-toolkit/public-api/controls/selectors/rotating-selector.h>
29
30 using namespace std;
31
32 namespace
33 {
34 const float TOUCH_OPACITY_THRESHOLD = 0.1f;
35 } // namespace
36
37 namespace Dali
38 {
39
40 namespace Toolkit
41 {
42
43 namespace Internal
44 {
45 namespace
46 {
47 //Type registration
48 BaseHandle Create()
49 {
50   // empty handle, as RotatingSelector takes children during construction
51   return Toolkit::RotatingSelector();
52 }
53 TypeRegistration mType( typeid(Toolkit::RotatingSelector), typeid(Toolkit::Control), Create );
54
55 const Quaternion ROTATION_ANGLE(0.0f, Vector3(1.0f, 0.0f, 0.0f));
56 }
57
58 Dali::Toolkit::RotatingSelector RotatingSelector::New(Actor& unSelectedActor, Actor& selectedActor)
59 {
60   // Create the implementation, temporarily owned on stack
61   IntrusivePtr< RotatingSelector > customCheckActor = new RotatingSelector;
62
63   // Pass ownership to CustomActor
64   Dali::Toolkit::RotatingSelector handle( *customCheckActor );
65
66   // Second-phase init of the implementation
67   // This can only be done after the CustomActor connection has been made...
68   customCheckActor->Initialize();
69
70   customCheckActor->SetSelectedActor(selectedActor);
71   customCheckActor->SetUnSelectedActor(unSelectedActor);
72
73   return handle;
74 }
75
76 void RotatingSelector::OnInitialize()
77 {
78   mContainer = Actor::New();
79   mContainer.SetName("Selector Container");
80   mUnSelectedActor = Actor::New();
81   mSelectedActor = Actor::New();
82
83   mRotateAnimation = Animation::New(0.5f);
84   mRotateAnimation.FinishedSignal().Connect(this, &RotatingSelector::AnimationCompleted);
85
86   mUnSelectedActor.SetParentOrigin(ParentOrigin::CENTER);
87   mUnSelectedActor.SetAnchorPoint(AnchorPoint::CENTER);
88
89   mSelectedActor.SetParentOrigin(ParentOrigin::CENTER);
90   mSelectedActor.SetAnchorPoint(AnchorPoint::CENTER);
91
92   mContainer.SetPositionInheritanceMode( Dali::USE_PARENT_POSITION_PLUS_LOCAL_POSITION );
93
94   Constraint constraint = Constraint::New<Vector3>( Actor::SIZE, ParentSource( Actor::SIZE ), EqualToConstraint() );
95   mSelectedActor.ApplyConstraint(constraint);
96   mUnSelectedActor.ApplyConstraint(constraint);
97   mContainer.ApplyConstraint(constraint);
98
99   mContainer.Add(mUnSelectedActor);
100   mSelectedActor.SetRotation(Radian(Math::PI), Vector3::XAXIS );
101
102   mUnSelectedActor.SetName("RotatingSelector : UnSelectedActor");
103   mSelectedActor.SetName("RotatingSelector : SelectedActor");
104
105   Self().Add(mContainer);
106   Self().SetLeaveRequired(true);
107
108   mRotateAnimation.RotateBy(mContainer, Radian(Math::PI), Vector3(1.0f, 0.0f, 0.0f));
109 }
110
111 RotatingSelector::RotatingSelector()
112 : Control( REQUIRES_TOUCH_EVENTS ),
113   mSelected(false),
114   mSelectable(true),
115   mIsAnimating(false)
116 {
117 }
118
119 RotatingSelector::~RotatingSelector()
120 {
121   mRotateAnimation.Reset();
122 }
123
124 void RotatingSelector::SetSelected( bool toggle )
125 {
126   if(toggle != mSelected)
127   {
128     if( mSelectable )
129     {
130       ToggleAndAnimateSelection();
131     }
132   }
133 }
134
135 void RotatingSelector::SetSelectedActor( Actor& selectedActor )
136 {
137   unsigned int numChildren = mSelectedActor.GetChildCount();
138   for( unsigned int i=0; i<numChildren; ++i )
139   {
140     Actor actor = mSelectedActor.GetChildAt(i);
141     mSelectedActor.Remove(actor);
142   }
143
144   mSelectedActor.Add(selectedActor);
145 }
146
147 Actor RotatingSelector::GetSelectedActor()
148 {
149   return mSelectedActor.GetChildAt(0);
150 }
151
152 void RotatingSelector::SetUnSelectedActor( Actor& unSelectedActor )
153 {
154   unsigned int numChildren = mUnSelectedActor.GetChildCount();
155
156   for(unsigned int i=0; i<numChildren; ++i)
157   {
158     mUnSelectedActor.Remove(mUnSelectedActor.GetChildAt(0));
159   }
160
161   mUnSelectedActor.Add(unSelectedActor);
162 }
163
164 Actor RotatingSelector::GetUnSelectedActor()
165 {
166   return mUnSelectedActor.GetChildAt(0);
167 }
168
169 void RotatingSelector::SetSelectable( bool selectable )
170 {
171   mSelectable = selectable;
172 }
173
174 Toolkit::RotatingSelector::SelectedSignalV2& RotatingSelector::SelectedSignal()
175 {
176   return mCheckedSignalV2;
177 }
178
179 bool RotatingSelector::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
180 {
181   Dali::BaseHandle handle( object );
182
183   bool connected( true );
184   Toolkit::RotatingSelector selector = Toolkit::RotatingSelector::DownCast(handle);
185
186   if( Toolkit::RotatingSelector::SIGNAL_CHECKED == signalName )
187   {
188     selector.SelectedSignal().Connect( tracker, functor );
189   }
190   else
191   {
192     // signalName does not match any signal
193     connected = false;
194   }
195
196   return connected;
197 }
198
199 bool RotatingSelector::OnTouchEvent(const TouchEvent& event)
200 {
201   if( 1 == event.GetPointCount() )
202   {
203     switch( event.GetPoint(0).state )
204     {
205       case TouchPoint::Down:
206         if(Self().GetCurrentOpacity() > TOUCH_OPACITY_THRESHOLD)
207         {
208           mPressed = true;
209         }
210         break;
211       case TouchPoint::Leave:
212         mPressed = false;
213         break;
214       case TouchPoint::Up:
215       {
216         if(mSelectable && mPressed)
217         {
218           ToggleAndAnimateSelection();
219         }
220         mPressed = false;
221         break;
222       }
223       default:
224         break;
225     }
226   }
227
228  return false; // dont consume
229 }
230
231 void RotatingSelector::ToggleAndAnimateSelection()
232 {
233   if(!mIsAnimating)
234   {
235     mSelected = !mSelected;
236     if(mSelected)
237     {
238       //The checked image (i.e mSelectedActor should be in front)
239       mSelectedActor.SetPosition(0.0f, 0.0f, -1.0f);
240       mContainer.Add(mSelectedActor);
241     }
242     else
243     {
244       //The un checked image (i.e mUnSelectedActor should be in front)
245       mUnSelectedActor.SetPosition(0.0f, 0.0f, 1.0f);
246       mContainer.Add(mUnSelectedActor);
247     }
248
249     mIsAnimating = true;
250     mRotateAnimation.Play();
251   }
252 }
253
254 void RotatingSelector::AnimationCompleted( Animation& animation )
255 {
256   if(mSelected)
257   {
258     //The checked image (i.e mSelectedActor should be in front)
259     mSelectedActor.SetPosition(0.0f, 0.0f, 0.0f);
260     mContainer.Remove(mUnSelectedActor);
261
262   }
263   else
264   {
265     //The un checked image (i.e mUnSelectedActor should be in front)
266     mContainer.Remove(mSelectedActor);
267     mUnSelectedActor.SetPosition(0.0f, 0.0f, 0.0f);
268   }
269
270   mIsAnimating = false;
271
272   //Emit signal.
273   Dali::Toolkit::RotatingSelector handle( GetOwner() );
274   mCheckedSignalV2.Emit( handle, mSelected );
275 }
276
277 } // namespace Internal
278
279 } // namespace Toolkit
280
281 } // namespace Dali