2 * Copyright (c) 2014 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 #include "view-impl.h"
22 #include <dali/public-api/animation/constraints.h>
23 #include <dali/public-api/common/stage.h>
24 #include <dali/public-api/object/type-registry.h>
37 namespace // to register type
42 const char* const SIGNAL_ORIENTATION_ANIMATION_START = "orientation-animation-start";
46 return Toolkit::View::New();
49 TypeRegistration typeRegistration( typeid( Toolkit::View ), typeid( Toolkit::Control ), Create );
51 SignalConnectorType signalConnector1( typeRegistration, SIGNAL_ORIENTATION_ANIMATION_START , &View::DoConnectSignal );
58 const float ROTATION_ANIMATION_DURATION = 0.5f;
62 Toolkit::View View::New( bool fullscreen )
64 // Create the implementation, temporarily owned by this handle on stack
65 IntrusivePtr< View > internalView = new View(fullscreen);
67 // Pass ownership to CustomActor handle
68 Toolkit::View view( *internalView );
70 // Second-phase init of the implementation
71 // This can only be done after the CustomActor connection has been made...
72 internalView->Initialize();
77 Layer View::GetContentLayer( unsigned int index ) const
79 // Returns the layer stored in the layer map.
82 LayerConstIt it = mContentLayers.find( index );
84 if( it != mContentLayers.end() )
92 unsigned int View::AddContentLayer( Layer layer )
95 DALI_ASSERT_ALWAYS( layer );
97 unsigned int index = mNextLayerIndex;
98 LayerIt it = FindLayer( layer );
100 if( it == mContentLayers.end() )
102 // Add layer to the custom actor.
106 mContentLayers[mNextLayerIndex] = layer;
108 // Increase the index.
115 void View::RemoveContentLayer( Layer layer )
117 // Check if layer was added in this view.
118 LayerIt it = FindLayer( layer );
119 if( it != mContentLayers.end() )
121 // Remove layer from custom actor.
122 Self().Remove( layer );
124 // Remove layer from layer map.
125 mContentLayers.erase( it );
129 Layer View::GetBackgroundLayer() const
131 return mBackgroundLayer;
134 void View::SetBackground( ImageActor backgroundImage )
136 // Create background layer if doesn't exist.
138 if( !mBackgroundLayer )
140 mBackgroundLayer = Layer::New();
142 mBackgroundLayer.SetPositionInheritanceMode( Dali::USE_PARENT_POSITION );
143 mBackgroundLayer.SetSize( mViewSize );
145 // Add background layer to custom actor.
146 Self().Add( mBackgroundLayer );
148 // Drop the background layer
150 DALI_ASSERT_ALWAYS( mBackgroundLayer.OnStage() ); // We need to be on-stage to drop the layer
151 mBackgroundLayer.LowerToBottom();
155 // It removes the old background
156 if( 0 < mBackgroundLayer.GetChildCount() )
158 mBackgroundLayer.Remove( mBackgroundLayer.GetChildAt(0) );
162 backgroundImage.SetPositionInheritanceMode( Dali::USE_PARENT_POSITION );
163 backgroundImage.SetScale( FillXYKeepAspectRatio( mViewSize, backgroundImage.GetSize() ) );
164 mBackgroundLayer.Add( backgroundImage );
167 void View::SetOrientationFunction( Degree portrait, Degree landscale, Degree portraitInverse, Degree landscapeInverse )
169 mOrientationFunction[View::PORTRAIT] = portrait;
170 mOrientationFunction[View::LANDSCAPE] = landscale;
171 mOrientationFunction[View::PORTRAIT_INVERSE] = portraitInverse;
172 mOrientationFunction[View::LANDSCAPE_INVERSE] = landscapeInverse;
175 void View::OrientationChanged( Dali::Orientation orientation )
177 // Nothing to do if orientation doesn't really change.
178 if ( orientation.GetDegrees() == mOrientation || !mAutoRotateEnabled )
183 mOrientation = orientation.GetDegrees();
185 // has parent so we expect it to be on stage
186 mRotateAnimation = Animation::New( ROTATION_ANIMATION_DURATION );
187 mRotateAnimation.RotateTo( Self(), Degree( -orientation.GetDegrees() ), Vector3::ZAXIS, AlphaFunctions::EaseOut );
192 const Vector2& stageSize( Stage::GetCurrent().GetSize() );
193 const Vector3& currentSize( Self().GetCurrentSize() );
195 float minSize = std::min( stageSize.width, stageSize.height );
196 float maxSize = std::max( stageSize.width, stageSize.height );
199 View::Orientation viewOrientation = DegreeToViewOrientation( Degree( orientation.GetDegrees() ) );
200 switch( viewOrientation )
202 case View::PORTRAIT: // Fallthrough
203 case View::PORTRAIT_INVERSE:
204 targetSize = Vector3( minSize, maxSize, currentSize.depth );
206 case View::LANDSCAPE: // Fallthrough
207 case View::LANDSCAPE_INVERSE:
208 targetSize = Vector3( maxSize, minSize, currentSize.depth );
211 DALI_ASSERT_ALWAYS( false );
214 // if we linearly resize from portrait to landscape halfway through the animation
215 // we get size which is square between the both. This would cause a square image to grow
216 // if it is fitted to be 100% of view size. Therefore we do a nonlinear size animation
217 // where we shrink faster
219 if( targetSize.width > currentSize.width )
221 // width grows, shrink height faster
222 Vector3 shrink( currentSize );shrink.height = targetSize.height;
223 mRotateAnimation.Resize( Self(), shrink, AlphaFunctions::EaseOut, 0.0f, ROTATION_ANIMATION_DURATION * 0.5f );
224 mRotateAnimation.Resize( Self(), targetSize, AlphaFunctions::EaseIn, 0.0f, ROTATION_ANIMATION_DURATION );
228 // height grows, shrink width faster
229 Vector3 shrink( currentSize );shrink.width = targetSize.width;
230 mRotateAnimation.Resize( Self(), shrink, AlphaFunctions::EaseOut, 0.0f, ROTATION_ANIMATION_DURATION * 0.5f );
231 mRotateAnimation.Resize( Self(), targetSize, AlphaFunctions::EaseIn, 0.0f, ROTATION_ANIMATION_DURATION );
235 Toolkit::View handle( GetOwner() );
236 mOrientationAnimationStartedSignal.Emit( handle, mRotateAnimation, orientation );
238 mRotateAnimation.Play();
241 void View::SetAutoRotate( bool enabled )
243 mAutoRotateEnabled = enabled;
246 Toolkit::View::OrientationAnimationStartedSignalType& View::OrientationAnimationStartedSignal()
248 return mOrientationAnimationStartedSignal;
251 bool View::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
253 Dali::BaseHandle handle( object );
255 bool connected( true );
256 Toolkit::View view = Toolkit::View::DownCast(handle);
258 if( 0 == strcmp( signalName.c_str(), SIGNAL_ORIENTATION_ANIMATION_START ) )
260 view.OrientationAnimationStartedSignal().Connect( tracker, functor );
264 // signalName does not match any signal
271 View::View(bool fullscreen)
272 : Control( CONTROL_BEHAVIOUR_NONE ),
274 mFullScreen(fullscreen),
276 mNextLayerIndex( 0 ),
277 mOrientationFunction(),
278 mAutoRotateEnabled( true )
280 mOrientationFunction[View::PORTRAIT] = 0.f;
281 mOrientationFunction[View::LANDSCAPE] = 90.f;
282 mOrientationFunction[View::PORTRAIT_INVERSE] = 180.f;
283 mOrientationFunction[View::LANDSCAPE_INVERSE] = 270.f;
290 void View::OnInitialize()
292 Self().SetAnchorPoint( AnchorPoint::CENTER );
293 Self().SetParentOrigin( ParentOrigin::CENTER );
297 Self().SetSize( Stage::GetCurrent().GetSize() );
301 void View::OnControlSizeSet( const Vector3& targetSize )
303 mViewSize = targetSize;
304 if( mBackgroundLayer )
306 mBackgroundLayer.SetSize( mViewSize );
307 if( mBackgroundLayer.GetChildCount() > 0 )
309 Actor background = mBackgroundLayer.GetChildAt(0);
310 background.SetScale( FillXYKeepAspectRatio( mViewSize, background.GetSize() ) );
315 View::Orientation View::DegreeToViewOrientation( Degree degree )
317 View::Orientation orientation = PORTRAIT;
319 if( fabsf( mOrientationFunction[PORTRAIT] - degree ) <= GetRangedEpsilon( mOrientationFunction[PORTRAIT], degree ) )
321 orientation = PORTRAIT;
323 else if( fabsf( mOrientationFunction[LANDSCAPE] - degree ) <= GetRangedEpsilon( mOrientationFunction[LANDSCAPE], degree ) )
325 orientation = LANDSCAPE;
327 else if( fabsf( mOrientationFunction[PORTRAIT_INVERSE] - degree ) <= GetRangedEpsilon( mOrientationFunction[PORTRAIT_INVERSE], degree ) )
329 orientation = PORTRAIT_INVERSE;
331 else if( fabsf( mOrientationFunction[LANDSCAPE_INVERSE] - degree ) <= GetRangedEpsilon( mOrientationFunction[LANDSCAPE_INVERSE], degree ) )
333 orientation = LANDSCAPE_INVERSE;
339 View::LayerIt View::FindLayer( Layer layer )
341 for( LayerIt it = mContentLayers.begin(); it != mContentLayers.end(); ++it )
343 if(layer == it->second)
349 return mContentLayers.end();
352 } // namespace Internal
354 } // namespace Toolkit