280bd24e37a7dfaaf6e11d44471d088098d9fd7a
[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( 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   /*
174   Actor self = Self();
175
176   // Nothing to do if orientation doesn't really change.
177   if ( orientation.GetDegrees() == mOrientation || !mAutoRotateEnabled )
178   {
179     return;
180   }
181
182   mOrientation = orientation.GetDegrees();
183
184   // has parent so we expect it to be on stage
185   mRotateAnimation = Animation::New( ROTATION_ANIMATION_DURATION );
186   mRotateAnimation.AnimateTo( Property( self, Actor::Property::ORIENTATION ), Quaternion( Radian( -orientation.GetRadians() ), Vector3::ZAXIS ), AlphaFunctions::EaseOut );
187
188   // Resize the view
189   if( mFullScreen )
190   {
191     const Vector2& stageSize( Stage::GetCurrent().GetSize() );
192     const Vector3& currentSize( self.GetCurrentSize() );
193
194     float minSize = std::min( stageSize.width, stageSize.height );
195     float maxSize = std::max( stageSize.width, stageSize.height );
196
197     Vector3 targetSize;
198     View::Orientation viewOrientation = DegreeToViewOrientation( Degree( orientation.GetDegrees() ) );
199     switch( viewOrientation )
200     {
201       case View::PORTRAIT:          // Fallthrough
202       case View::PORTRAIT_INVERSE:
203         targetSize = Vector3( minSize, maxSize, currentSize.depth );
204         break;
205       case View::LANDSCAPE:         // Fallthrough
206       case View::LANDSCAPE_INVERSE:
207         targetSize = Vector3( maxSize, minSize, currentSize.depth );
208         break;
209       default:
210         DALI_ASSERT_ALWAYS( false );
211     }
212
213     // if we linearly resize from portrait to landscape halfway through the animation
214     // we get size which is square between the both. This would cause a square image to grow
215     // if it is fitted to be 100% of view size. Therefore we do a nonlinear size animation
216     // where we shrink faster
217     // which one grows
218     if( targetSize.width > currentSize.width )
219     {
220       // width grows, shrink height faster
221       Vector3 shrink( currentSize );shrink.height = targetSize.height;
222       mRotateAnimation.AnimateTo( Property( self, Actor::Property::SIZE ), shrink, AlphaFunctions::EaseOut, TimePeriod( 0.0f, ROTATION_ANIMATION_DURATION * 0.5f ) );
223       mRotateAnimation.AnimateTo( Property( self, Actor::Property::SIZE ), targetSize, AlphaFunctions::EaseIn, TimePeriod( 0.0f, ROTATION_ANIMATION_DURATION ) );
224     }
225     else
226     {
227       // height grows, shrink width faster
228       Vector3 shrink( currentSize );shrink.width = targetSize.width;
229       mRotateAnimation.AnimateTo( Property( self, Actor::Property::SIZE ), shrink, AlphaFunctions::EaseOut, TimePeriod( 0.0f, ROTATION_ANIMATION_DURATION * 0.5f ) );
230       mRotateAnimation.AnimateTo( Property( self, Actor::Property::SIZE ), targetSize, AlphaFunctions::EaseIn, TimePeriod( 0.0f, ROTATION_ANIMATION_DURATION ) );
231     }
232   }
233
234   Toolkit::View handle( GetOwner() );
235   mOrientationAnimationStartedSignal.Emit( handle, mRotateAnimation, orientation );
236
237   mRotateAnimation.Play();
238   */
239 }
240
241 void View::SetAutoRotate( bool enabled )
242 {
243   mAutoRotateEnabled = enabled;
244 }
245
246 Toolkit::View::OrientationAnimationStartedSignalType& View::OrientationAnimationStartedSignal()
247 {
248   return mOrientationAnimationStartedSignal;
249 }
250
251 bool View::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
252 {
253   return true;
254
255   /*
256   Dali::BaseHandle handle( object );
257
258   bool connected( true );
259   Toolkit::View view = Toolkit::View::DownCast(handle);
260
261   if( 0 == strcmp( signalName.c_str(), SIGNAL_ORIENTATION_ANIMATION_START ) )
262   {
263     view.OrientationAnimationStartedSignal().Connect( tracker, functor );
264   }
265   else
266   {
267     // signalName does not match any signal
268     connected = false;
269   }
270
271   return connected;
272   */
273 }
274
275 View::View(bool fullscreen)
276 : Control( ControlBehaviour( ACTOR_BEHAVIOUR_NONE ) ),
277   mOrientation( -1 ),
278   mFullScreen(fullscreen),
279   mContentLayers(),
280   mNextLayerIndex( 0 ),
281   mOrientationFunction(),
282   mAutoRotateEnabled( true )
283 {
284   mOrientationFunction[View::PORTRAIT] = 0.f;
285   mOrientationFunction[View::LANDSCAPE] = 90.f;
286   mOrientationFunction[View::PORTRAIT_INVERSE] = 180.f;
287   mOrientationFunction[View::LANDSCAPE_INVERSE] =  270.f;
288 }
289
290 View::~View()
291 {
292 }
293
294 void View::OnInitialize()
295 {
296   Self().SetAnchorPoint( AnchorPoint::CENTER );
297   Self().SetParentOrigin( ParentOrigin::CENTER );
298
299   if( mFullScreen )
300   {
301     Self().SetSize( Stage::GetCurrent().GetSize() );
302   }
303 }
304
305 View::Orientation View::DegreeToViewOrientation( Degree degree )
306 {
307   View::Orientation orientation = PORTRAIT;
308
309   if( fabsf( mOrientationFunction[PORTRAIT] - degree.degree ) <= GetRangedEpsilon( mOrientationFunction[PORTRAIT], degree.degree ) )
310   {
311     orientation =  PORTRAIT;
312   }
313   else if( fabsf( mOrientationFunction[LANDSCAPE] - degree.degree ) <= GetRangedEpsilon( mOrientationFunction[LANDSCAPE], degree.degree ) )
314   {
315     orientation = LANDSCAPE;
316   }
317   else if( fabsf( mOrientationFunction[PORTRAIT_INVERSE] - degree.degree ) <= GetRangedEpsilon( mOrientationFunction[PORTRAIT_INVERSE], degree.degree ) )
318   {
319     orientation = PORTRAIT_INVERSE;
320   }
321   else if( fabsf( mOrientationFunction[LANDSCAPE_INVERSE] - degree.degree ) <= GetRangedEpsilon( mOrientationFunction[LANDSCAPE_INVERSE], degree.degree ) )
322   {
323     orientation = LANDSCAPE_INVERSE;
324   }
325
326   return orientation;
327 }
328
329 View::LayerIt View::FindLayer( Layer layer )
330 {
331   for( LayerIt it = mContentLayers.begin(); it != mContentLayers.end(); ++it )
332   {
333     if(layer == it->second)
334     {
335       return it;
336     }
337   }
338
339   return mContentLayers.end();
340 }
341
342 } // namespace Internal
343
344 } // namespace Toolkit
345
346 } // namespace Dali