[dali_1.0.39] Merge branch 'tizen'
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / controls / view / view-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 "view-impl.h"
20
21 // EXTERNAL INCLUDES
22 #include <cstring> // for strcmp
23 #include <dali/public-api/animation/constraints.h>
24 #include <dali/public-api/common/stage.h>
25 #include <dali/public-api/object/type-registry.h>
26 #include <dali/public-api/object/type-registry-helper.h>
27
28 namespace Dali
29 {
30
31 namespace Toolkit
32 {
33
34 namespace Internal
35 {
36
37 namespace
38 {
39
40 BaseHandle Create()
41 {
42   return Toolkit::View::New();
43 }
44
45 DALI_TYPE_REGISTRATION_BEGIN( Toolkit::View, Toolkit::Control, Create )
46
47 DALI_SIGNAL_REGISTRATION( Toolkit, View, "orientation-animation-start", SIGNAL_ORIENTATION_ANIMATION_START )
48
49 DALI_TYPE_REGISTRATION_END()
50
51 const float ROTATION_ANIMATION_DURATION = 0.5f;
52
53 }
54
55 Toolkit::View View::New( bool fullscreen )
56 {
57   // Create the implementation, temporarily owned by this handle on stack
58   IntrusivePtr< View > internalView = new View(fullscreen);
59
60   // Pass ownership to CustomActor handle
61   Toolkit::View view( *internalView );
62
63   // Second-phase init of the implementation
64   // This can only be done after the CustomActor connection has been made...
65   internalView->Initialize();
66
67   return view;
68 }
69
70 Layer View::GetContentLayer( unsigned int index ) const
71 {
72   // Returns the layer stored in the layer map.
73   Layer layer;
74
75   LayerConstIt it = mContentLayers.find( index );
76
77   if( it != mContentLayers.end() )
78   {
79     layer = it->second;
80   }
81
82   return layer;
83 }
84
85 unsigned int View::AddContentLayer( Layer layer )
86 {
87   // layer must exist.
88   DALI_ASSERT_ALWAYS( layer );
89
90   unsigned int index = mNextLayerIndex;
91   LayerIt it = FindLayer( layer );
92
93   if( it == mContentLayers.end() )
94   {
95     // Add layer to the custom actor.
96     Self().Add( layer );
97
98     // Store the layer.
99     mContentLayers[mNextLayerIndex] = layer;
100
101     // Increase the index.
102     ++mNextLayerIndex;
103   }
104
105   return index;
106 }
107
108 void View::RemoveContentLayer( Layer layer )
109 {
110   // Check if layer was added in this view.
111   LayerIt it = FindLayer( layer );
112   if( it != mContentLayers.end() )
113   {
114     // Remove layer from custom actor.
115     Self().Remove( layer );
116
117     // Remove layer from layer map.
118     mContentLayers.erase( it );
119   }
120 }
121
122 Layer View::GetBackgroundLayer() const
123 {
124   return mBackgroundLayer;
125 }
126
127 void View::SetBackground( ImageActor backgroundImage )
128 {
129   // Create background layer if doesn't exist.
130
131   if( !mBackgroundLayer )
132   {
133     mBackgroundLayer = Layer::New();
134
135     mBackgroundLayer.SetPositionInheritanceMode( Dali::USE_PARENT_POSITION );
136     mBackgroundLayer.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS );
137
138     // Add background layer to custom actor.
139     Self().Add( mBackgroundLayer );
140
141     // Drop the background layer
142
143     DALI_ASSERT_ALWAYS( mBackgroundLayer.OnStage() ); // We need to be on-stage to drop the layer
144     mBackgroundLayer.LowerToBottom();
145   }
146   else
147   {
148     // It removes the old background
149     if( 0 < mBackgroundLayer.GetChildCount() )
150     {
151       mBackgroundLayer.Remove( mBackgroundLayer.GetChildAt(0) );
152     }
153   }
154
155   backgroundImage.SetPositionInheritanceMode( Dali::USE_PARENT_POSITION );
156   backgroundImage.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS );
157   backgroundImage.SetSizeScalePolicy( SizeScalePolicy::FILL_WITH_ASPECT_RATIO );
158   mBackgroundLayer.Add( backgroundImage );
159
160   RelayoutRequest();
161 }
162
163 void View::SetOrientationFunction( Degree portrait, Degree landscale, Degree portraitInverse, Degree landscapeInverse )
164 {
165   mOrientationFunction[View::PORTRAIT] = portrait.degree;
166   mOrientationFunction[View::LANDSCAPE] = landscale.degree;
167   mOrientationFunction[View::PORTRAIT_INVERSE] = portraitInverse.degree;
168   mOrientationFunction[View::LANDSCAPE_INVERSE] = landscapeInverse.degree;
169 }
170
171 void View::OrientationChanged( Dali::Orientation orientation )
172 {
173   Actor self = Self();
174
175   // Nothing to do if orientation doesn't really change.
176   if ( orientation.GetDegrees() == mOrientation || !mAutoRotateEnabled )
177   {
178     return;
179   }
180
181   mOrientation = orientation.GetDegrees();
182
183   // has parent so we expect it to be on stage
184   mRotateAnimation = Animation::New( ROTATION_ANIMATION_DURATION );
185   mRotateAnimation.AnimateTo( Property( self, Actor::Property::ORIENTATION ), Quaternion( Radian( -orientation.GetRadians() ), Vector3::ZAXIS ), AlphaFunctions::EaseOut );
186
187   // Resize the view
188   if( mFullScreen )
189   {
190     const Vector2& stageSize( Stage::GetCurrent().GetSize() );
191     const Vector3& currentSize( self.GetCurrentSize() );
192
193     float minSize = std::min( stageSize.width, stageSize.height );
194     float maxSize = std::max( stageSize.width, stageSize.height );
195
196     Vector3 targetSize;
197     View::Orientation viewOrientation = DegreeToViewOrientation( Degree( orientation.GetDegrees() ) );
198     switch( viewOrientation )
199     {
200       case View::PORTRAIT:          // Fallthrough
201       case View::PORTRAIT_INVERSE:
202         targetSize = Vector3( minSize, maxSize, currentSize.depth );
203         break;
204       case View::LANDSCAPE:         // Fallthrough
205       case View::LANDSCAPE_INVERSE:
206         targetSize = Vector3( maxSize, minSize, currentSize.depth );
207         break;
208       default:
209         DALI_ASSERT_ALWAYS( false );
210     }
211
212     // if we linearly resize from portrait to landscape halfway through the animation
213     // we get size which is square between the both. This would cause a square image to grow
214     // if it is fitted to be 100% of view size. Therefore we do a nonlinear size animation
215     // where we shrink faster
216     // which one grows
217     if( targetSize.width > currentSize.width )
218     {
219       // width grows, shrink height faster
220       Vector3 shrink( currentSize );shrink.height = targetSize.height;
221       mRotateAnimation.AnimateTo( Property( self, Actor::Property::SIZE ), shrink, AlphaFunctions::EaseOut, TimePeriod( 0.0f, ROTATION_ANIMATION_DURATION * 0.5f ) );
222       mRotateAnimation.AnimateTo( Property( self, Actor::Property::SIZE ), targetSize, AlphaFunctions::EaseIn, TimePeriod( 0.0f, ROTATION_ANIMATION_DURATION ) );
223     }
224     else
225     {
226       // height grows, shrink width faster
227       Vector3 shrink( currentSize );shrink.width = targetSize.width;
228       mRotateAnimation.AnimateTo( Property( self, Actor::Property::SIZE ), shrink, AlphaFunctions::EaseOut, TimePeriod( 0.0f, ROTATION_ANIMATION_DURATION * 0.5f ) );
229       mRotateAnimation.AnimateTo( Property( self, Actor::Property::SIZE ), targetSize, AlphaFunctions::EaseIn, TimePeriod( 0.0f, ROTATION_ANIMATION_DURATION ) );
230     }
231   }
232
233   Toolkit::View handle( GetOwner() );
234   mOrientationAnimationStartedSignal.Emit( handle, mRotateAnimation, orientation );
235
236   mRotateAnimation.Play();
237 }
238
239 void View::SetAutoRotate( bool enabled )
240 {
241   mAutoRotateEnabled = enabled;
242 }
243
244 Toolkit::View::OrientationAnimationStartedSignalType& View::OrientationAnimationStartedSignal()
245 {
246   return mOrientationAnimationStartedSignal;
247 }
248
249 bool View::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
250 {
251   Dali::BaseHandle handle( object );
252
253   bool connected( true );
254   Toolkit::View view = Toolkit::View::DownCast(handle);
255
256   if( 0 == strcmp( signalName.c_str(), SIGNAL_ORIENTATION_ANIMATION_START ) )
257   {
258     view.OrientationAnimationStartedSignal().Connect( tracker, functor );
259   }
260   else
261   {
262     // signalName does not match any signal
263     connected = false;
264   }
265
266   return connected;
267 }
268
269 View::View(bool fullscreen)
270 : Control( ControlBehaviour( ACTOR_BEHAVIOUR_NONE ) ),
271   mOrientation( -1 ),
272   mFullScreen(fullscreen),
273   mContentLayers(),
274   mNextLayerIndex( 0 ),
275   mOrientationFunction(),
276   mAutoRotateEnabled( true )
277 {
278   mOrientationFunction[View::PORTRAIT] = 0.f;
279   mOrientationFunction[View::LANDSCAPE] = 90.f;
280   mOrientationFunction[View::PORTRAIT_INVERSE] = 180.f;
281   mOrientationFunction[View::LANDSCAPE_INVERSE] =  270.f;
282 }
283
284 View::~View()
285 {
286 }
287
288 void View::OnInitialize()
289 {
290   Self().SetAnchorPoint( AnchorPoint::CENTER );
291   Self().SetParentOrigin( ParentOrigin::CENTER );
292
293   if( mFullScreen )
294   {
295     Self().SetSize( Stage::GetCurrent().GetSize() );
296   }
297 }
298
299 View::Orientation View::DegreeToViewOrientation( Degree degree )
300 {
301   View::Orientation orientation = PORTRAIT;
302
303   if( fabsf( mOrientationFunction[PORTRAIT] - degree.degree ) <= GetRangedEpsilon( mOrientationFunction[PORTRAIT], degree.degree ) )
304   {
305     orientation =  PORTRAIT;
306   }
307   else if( fabsf( mOrientationFunction[LANDSCAPE] - degree.degree ) <= GetRangedEpsilon( mOrientationFunction[LANDSCAPE], degree.degree ) )
308   {
309     orientation = LANDSCAPE;
310   }
311   else if( fabsf( mOrientationFunction[PORTRAIT_INVERSE] - degree.degree ) <= GetRangedEpsilon( mOrientationFunction[PORTRAIT_INVERSE], degree.degree ) )
312   {
313     orientation = PORTRAIT_INVERSE;
314   }
315   else if( fabsf( mOrientationFunction[LANDSCAPE_INVERSE] - degree.degree ) <= GetRangedEpsilon( mOrientationFunction[LANDSCAPE_INVERSE], degree.degree ) )
316   {
317     orientation = LANDSCAPE_INVERSE;
318   }
319
320   return orientation;
321 }
322
323 View::LayerIt View::FindLayer( Layer layer )
324 {
325   for( LayerIt it = mContentLayers.begin(); it != mContentLayers.end(); ++it )
326   {
327     if(layer == it->second)
328     {
329       return it;
330     }
331   }
332
333   return mContentLayers.end();
334 }
335
336 } // namespace Internal
337
338 } // namespace Toolkit
339
340 } // namespace Dali