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