2 * Copyright (c) 2019 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 <dali-toolkit/dali-toolkit.h>
23 using namespace Dali::Toolkit;
27 const Vector4 BACKGROUND_GRADIENT_1 = Vector4( 167.0f, 207.0f, 223.0f, 255.0f ) / 255.0f;
28 const Vector4 BACKGROUND_GRADIENT_2 = Vector4( 0.0f, 64.0f, 137.0f, 255.0f ) / 255.0f;
29 const Vector2 BACKGROUND_GRADIENT_START_POSITION( 0.0f, -0.5f );
30 const Vector2 BACKGROUND_GRADIENT_END_POSITION( 0.0f, 0.5f );
32 const Vector4 CONTROL_GRADIENT_1 = Vector4( 234.0f, 185.0f, 45.0f, 255.0f ) / 255.0f;
33 const Vector4 CONTROL_GRADIENT_2 = Vector4( 199.0f, 152.0f, 16.0f, 255.0f ) / 255.0f;
34 const Vector2 CONTROL_GRADIENT_CENTER( Vector2::ZERO );
35 const float CONTROL_GRADIENT_RADIUS( 0.5f );
37 const float HELP_ANIMATION_DURATION( 25.0f );
38 const float HELP_ANIMATION_SEGMENT_TIME( 5.0f );
39 const float HELP_ANIMATION_TRANSITION_DURATION( 0.75f );
40 const Vector2 HELP_TEXT_POSITION_MULTIPLIER( 0.25f, 0.13f );
42 const float SHAKY_ANIMATION_DURATION( 0.1f );
43 const float SHAKY_ANIMATION_SEGMENT_TIME( 0.05f );
44 const float SHAKY_ANIMATION_ANGLE( 1.0f );
46 const float TOUCH_MODE_ANIMATION_DURATION( 0.1f );
47 const Vector4 TOUCH_MODE_COLOR( 1.0f, 0.7f, 0.7f, 1.0f );
49 const float PAN_MODE_CHANGE_ANIMATION_DURATION( 0.25f );
50 const Vector3 PAN_MODE_START_ANIMATION_SCALE( 1.2f, 1.2f, 1.0f );
51 const Vector3 PAN_MODE_END_ANIMATION_SCALE( 0.8f, 0.8f, 1.0f );
53 const float TAP_ANIMATION_DURATON( 0.5f );
54 const Vector4 TAP_ANIMATION_COLOR( 0.8f, 0.5, 0.2f, 0.6f );
56 const Vector3 MINIMUM_SCALE( Vector3::ONE );
57 const Vector3 MAXIMUM_SCALE( Vector3::ONE * 2.0f );
58 const float SCALE_BACK_ANIMATION_DURATION( 0.25f );
61 * @brief Creates a background with a linear gradient which matches parent size & is placed in the center.
63 Actor CreateBackground()
65 Actor background = Control::New();
66 background.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS );
67 background.SetParentOrigin( ParentOrigin::CENTER );
68 background.SetProperty(
69 Control::Property::BACKGROUND,
70 Property::Map().Add( Toolkit::Visual::Property::TYPE, Visual::GRADIENT )
71 .Add( GradientVisual::Property::STOP_COLOR, Property::Array().Add( BACKGROUND_GRADIENT_1 )
72 .Add( BACKGROUND_GRADIENT_2 ) )
73 .Add( GradientVisual::Property::START_POSITION, BACKGROUND_GRADIENT_START_POSITION )
74 .Add( GradientVisual::Property::END_POSITION, BACKGROUND_GRADIENT_END_POSITION ) );
79 * @brief Create a control with a circular gradient & a specific size & is placed in the center of its parent.
81 * @param[in] size The size we want the control to be.
83 Actor CreateTouchControl( const Vector2& size )
85 Actor touchControl = Control::New();
86 touchControl.SetSize( size );
87 touchControl.SetParentOrigin( ParentOrigin::CENTER );
88 touchControl.SetProperty(
89 Control::Property::BACKGROUND,
90 Property::Map().Add( Toolkit::Visual::Property::TYPE, Visual::GRADIENT )
91 .Add( GradientVisual::Property::STOP_COLOR, Property::Array().Add( CONTROL_GRADIENT_1 )
92 .Add( CONTROL_GRADIENT_2 ) )
93 .Add( GradientVisual::Property::CENTER, CONTROL_GRADIENT_CENTER )
94 .Add( GradientVisual::Property::RADIUS, CONTROL_GRADIENT_RADIUS )
100 * @brief Shows the given string between the given start and end times.
102 * Appropriately animates the string into and out of the scene.
104 * @param[in] string The label to display, this is an rvalue reference & will be moved
105 * @param[in] parent The parent to add the label to
106 * @param[in] animation The animation to add the animators created in this function
107 * @param[in] startTime When to start the animators
108 * @param[in] endTime When to end the animators
110 void AddHelpInfo( const std::string&& string, Actor parent, Animation animation, float startTime, float endTime )
112 Actor text = TextLabel::New( std::move( string ) );
113 Vector3 position( Stage::GetCurrent().GetSize() * HELP_TEXT_POSITION_MULTIPLIER );
115 text.SetAnchorPoint( AnchorPoint::TOP_CENTER );
116 text.SetParentOrigin( ParentOrigin::TOP_CENTER );
117 text.SetPosition( position );
118 text.SetOpacity( 0.0f );
119 text.SetProperty( TextLabel::Property::HORIZONTAL_ALIGNMENT, Text::HorizontalAlignment::CENTER );
123 TimePeriod timePeriod( startTime, HELP_ANIMATION_TRANSITION_DURATION );
124 animation.AnimateTo( Property( text, Actor::Property::COLOR_ALPHA ), 1.0f, timePeriod );
125 animation.AnimateBy( Property( text, Actor::Property::POSITION_X ), -position.x, timePeriod );
128 timePeriod.delaySeconds = endTime;
129 animation.AnimateTo( Property( text, Actor::Property::COLOR_ALPHA ), 0.0f, timePeriod );
130 animation.AnimateBy( Property( text, Actor::Property::POSITION_X ), -position.x, timePeriod );
133 } // unnamed namespace
136 * @brief This example shows how to use the different gesture detectors available.
138 * - Tapping on the control shows a small rotation animation.
139 * - A Long press on the control puts it into Pan Mode.
140 * - When in Pan mode, the control can be panned (moved).
141 * - When the pan ends, we exit the Pan mode via an animation.
142 * - Pinching the control changes the scale of the control.
144 class GestureExample : public ConnectionTracker
149 * @brief Constructor.
151 * @param[in] application Reference to the application
153 GestureExample( Application &application )
154 : mApplication( application )
156 // Connect to the Application's Init signal
157 application.InitSignal().Connect( this, &GestureExample::Create );
163 * @brief Creates the scene as described in this class' description.
165 * @param[in] application Reference to the application class
167 void Create( Application& application )
169 // Get a handle to the stage & connect to the key event signal
170 Stage stage = Stage::GetCurrent();
171 stage.KeyEventSignal().Connect(this, &GestureExample::OnKeyEvent);
173 // Create a background with a gradient
174 Actor background = CreateBackground();
175 stage.Add( background );
177 // Create a control that we'll use for the gestures to be a quarter of the size of the stage
178 Actor touchControl = CreateTouchControl( stage.GetSize() * 0.25f );
179 background.Add( touchControl );
181 // Connect to the touch signal
182 touchControl.TouchSignal().Connect( this, &GestureExample::OnTouch );
183 touchControl.SetLeaveRequired( true );
185 // Create a long press gesture detector, attach the actor & connect
186 mLongPressDetector = LongPressGestureDetector::New();
187 mLongPressDetector.Attach( touchControl );
188 mLongPressDetector.DetectedSignal().Connect( this, &GestureExample::OnLongPress );
190 // Create a pan gesture detector, attach the actor & connect
191 mPanDetector = PanGestureDetector::New();
192 mPanDetector.Attach( touchControl );
193 mPanDetector.DetectedSignal().Connect( this, &GestureExample::OnPan );
195 // Create a tap gesture detector, attach the actor & connect
196 mTapDetector = TapGestureDetector::New();
197 mTapDetector.Attach( touchControl );
198 mTapDetector.DetectedSignal().Connect( this, &GestureExample::OnTap );
200 // Create a pinch gesture detector, attach the actor & connect
201 mPinchDetector = PinchGestureDetector::New();
202 mPinchDetector.Attach( touchControl );
203 mPinchDetector.DetectedSignal().Connect( this, &GestureExample::OnPinch );
205 // Create an animation which shakes the actor when in Pan mode
206 mShakeAnimation = Animation::New( SHAKY_ANIMATION_DURATION );
207 mShakeAnimation.AnimateBy( Property( touchControl, Actor::Property::ORIENTATION ),
208 Quaternion( Degree( SHAKY_ANIMATION_ANGLE ), Vector3::ZAXIS ),
209 AlphaFunction::BOUNCE,
210 TimePeriod( 0.0f, SHAKY_ANIMATION_SEGMENT_TIME ) );
211 mShakeAnimation.AnimateBy( Property( touchControl, Actor::Property::ORIENTATION ),
212 Quaternion( Degree( -SHAKY_ANIMATION_ANGLE ), Vector3::ZAXIS ),
213 AlphaFunction::BOUNCE,
214 TimePeriod( SHAKY_ANIMATION_SEGMENT_TIME, SHAKY_ANIMATION_SEGMENT_TIME ) );
216 // Animate help information
217 // Here we just animate some text on the screen to show tips on how to use this example
218 // The help animation loops
219 Animation helpAnimation = Animation::New( HELP_ANIMATION_DURATION );
221 float startTime( 0.0f );
222 float endTime( startTime + HELP_ANIMATION_SEGMENT_TIME );
224 AddHelpInfo( "Tap image for animation", background, helpAnimation, startTime, endTime );
225 AddHelpInfo( "Press & Hold image to drag", background, helpAnimation, startTime += HELP_ANIMATION_SEGMENT_TIME, endTime += HELP_ANIMATION_SEGMENT_TIME );
226 AddHelpInfo( "Pinch image to resize", background, helpAnimation, startTime += HELP_ANIMATION_SEGMENT_TIME, endTime += HELP_ANIMATION_SEGMENT_TIME );
227 helpAnimation.SetLooping( true );
228 helpAnimation.Play();
232 * @brief Called when our actor is touched.
234 * @param[in] actor The touched actor
235 * @param[in] touch The touch event
237 bool OnTouch( Actor actor, const TouchData& touch )
239 switch( touch.GetState( 0 ) )
241 case PointState::DOWN:
243 // When we get a touch point, change the color of the actor.
245 Animation anim = Animation::New( TOUCH_MODE_ANIMATION_DURATION );
246 anim.AnimateTo( Property( actor, Actor::Property::COLOR ), TOUCH_MODE_COLOR );
251 case PointState::LEAVE:
253 case PointState::INTERRUPTED:
257 // If we're not panning, change the color back to normal.
259 Animation anim = Animation::New( TOUCH_MODE_ANIMATION_DURATION );
260 anim.AnimateTo( Property( actor, Actor::Property::COLOR ), Vector4::ONE );
263 // Stop the shake animation from looping.
264 mShakeAnimation.SetLooping( false );
278 * @brief Called when a long-press gesture is detected on our control.
280 * @param[in] actor The actor that's been long-pressed
281 * @param[in] longPress The long-press gesture information
283 void OnLongPress( Actor actor, const LongPressGesture& longPress )
285 switch( longPress.state )
287 case Gesture::Started:
289 // When we first receive a long press, change state to pan mode.
291 // Do a small animation to indicate to the user that we are in pan mode.
292 Animation anim = Animation::New( PAN_MODE_CHANGE_ANIMATION_DURATION );
293 anim.AnimateTo( Property( actor, Actor::Property::SCALE ), actor.GetCurrentScale() * PAN_MODE_START_ANIMATION_SCALE, AlphaFunction::BOUNCE );
297 // Start the shake animation so the user knows when they are in pan mode.
298 mShakeAnimation.SetLooping( true );
299 mShakeAnimation.Play();
303 case Gesture::Finished:
304 case Gesture::Cancelled:
306 // We get this state when all touches are released after a long press. We end pan mode...
319 * @brief Called when a pan gesture is detected on our control.
321 * @param[in] actor The actor that's been panned
322 * @param[in] pan The pan gesture information
324 void OnPan( Actor actor, const PanGesture& pan )
326 if( mPanMode || mPanStarted )
328 // When we are in Pan mode, just move the actor by the displacement.
330 // As the displacement is in local actor coords, we will have to multiply the displacement by the
331 // actor's scale so that it moves the correct amount in the parent's coordinate system.
332 Vector3 scaledDisplacement( pan.displacement );
333 scaledDisplacement *= actor.GetCurrentScale();
335 Vector3 currentPosition;
336 actor.GetProperty( Actor::Property::POSITION ).Get( currentPosition );
338 Vector3 newPosition = currentPosition + scaledDisplacement;
339 actor.SetPosition( newPosition );
343 case Gesture::Started:
349 case Gesture::Finished:
350 case Gesture::Cancelled:
352 // If we cancel or finish the pan, do an animation to indicate this and stop the shake animation.
354 Animation anim = Animation::New( PAN_MODE_CHANGE_ANIMATION_DURATION );
355 anim.AnimateTo( Property( actor, Actor::Property::COLOR ), Vector4::ONE );
356 anim.AnimateTo( Property( actor, Actor::Property::SCALE ), actor.GetCurrentScale() * PAN_MODE_END_ANIMATION_SCALE, AlphaFunction::BOUNCE );
358 // Move actor back to center if we're out of bounds
359 Vector2 halfStageSize = Stage::GetCurrent().GetSize() * 0.5f;
360 if( ( std::abs( newPosition.x ) > halfStageSize.width ) ||
361 ( std::abs( newPosition.y ) > halfStageSize.height ) )
363 anim.AnimateTo( Property( actor, Actor::Property::POSITION ), Vector3::ZERO, AlphaFunction::EASE_IN );
367 mShakeAnimation.SetLooping( false );
381 * @brief Called when a tap gesture is detected on our control.
383 * @param[in] actor The actor that's been tapped
384 * @param[in] tap The tap gesture information
386 void OnTap( Actor actor, const TapGesture& tap )
388 // Do a short animation to show a tap has happened.
390 Animation anim = Animation::New( TAP_ANIMATION_DURATON );
391 anim.AnimateBy( Property( actor, Actor::Property::ORIENTATION ), Quaternion( Degree( 360.0f ), Vector3::ZAXIS ) );
392 anim.AnimateTo( Property( actor, Actor::Property::SCALE ), Vector3::ONE, AlphaFunction::LINEAR );
393 anim.AnimateTo( Property( actor, Actor::Property::COLOR ), TAP_ANIMATION_COLOR, AlphaFunction::BOUNCE );
398 * @brief Called when a pinch gesture is detected on our control.
400 * @param[in] actor The actor that's been pinched
401 * @param[in] pinch The pinch gesture information
403 void OnPinch( Actor actor, const PinchGesture& pinch )
405 switch( pinch.state )
407 case Gesture::Started:
409 // Starting scale is required so that we know what to multiply the pinch.scale by.
410 mStartingScale = actor.GetCurrentScale();
414 case Gesture::Finished:
415 case Gesture::Cancelled:
417 Vector3 scale( actor.GetCurrentScale() );
419 // Ensure the actor sizes itself to be within the limits defined.
420 if ( scale.x < MINIMUM_SCALE.x )
422 scale = MINIMUM_SCALE;
424 else if ( scale.x > MAXIMUM_SCALE.x )
426 scale = MAXIMUM_SCALE;
429 // Do an animation to come back to go back to the limits.
430 Animation anim = Animation::New( SCALE_BACK_ANIMATION_DURATION );
431 anim.AnimateTo( Property( actor, Actor::Property::SCALE ), scale, AlphaFunction::LINEAR );
442 actor.SetScale( mStartingScale * pinch.scale );
446 * @brief Called when any key event is received.
448 * Will use this to quit the application if Back or the Escape key is received.
449 * @param[in] event The key event information
451 void OnKeyEvent( const KeyEvent& event )
453 if( event.state == KeyEvent::Down )
455 if( IsKey( event, Dali::DALI_KEY_ESCAPE ) || IsKey( event, Dali::DALI_KEY_BACK ) )
463 Application& mApplication;
465 PanGestureDetector mPanDetector;
466 LongPressGestureDetector mLongPressDetector;
467 TapGestureDetector mTapDetector;
468 PinchGestureDetector mPinchDetector;
470 Vector3 mStartingScale; ///< Set to the scale of the control when pinch starts.
471 Animation mShakeAnimation; ///< "Shake" animation to show when we are in panning mode.
472 bool mPanMode = false; ///< Set to true when we have long-pressed to put us into panning mode.
473 bool mPanStarted = false; ///< Set to true to state that panning has started.
476 int DALI_EXPORT_API main( int argc, char **argv )
478 Application application = Application::New( &argc, &argv );
479 GestureExample controller( application );
480 application.MainLoop();