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