From: Heeyong Song Date: Wed, 26 Dec 2018 09:31:20 +0000 (+0900) Subject: [4.0] Add VisualEventSignal to Control and a property to AnimatedVectorImageVisual X-Git-Tag: accepted/tizen/4.0/unified/20190112.120436~3 X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git;a=commitdiff_plain;h=refs%2Fchanges%2F72%2F196372%2F3 [4.0] Add VisualEventSignal to Control and a property to AnimatedVectorImageVisual - Add VisualEventSignal to Control - Add DevelImageVisual::Property::PLAY_STATE - Add DevelAnimatedVectorImageVisual::Signal::ANIMATION_FINISHED - Remove DevelAnimatedVectorImageVisual::Action::RESUME Change-Id: Ic3b75971e58bab8b6f9d97d3220041ead22a2f86 --- diff --git a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/dummy-control.cpp b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/dummy-control.cpp index 96699ec..d665b3a 100644 --- a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/dummy-control.cpp +++ b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/dummy-control.cpp @@ -188,7 +188,17 @@ void DummyControlImpl::SetProperty( BaseObject* object, Dali::Property::Index in Property::Value DummyControlImpl::GetProperty( BaseObject* object, Dali::Property::Index propertyIndex ) { - Dali::Property::Value value; + Toolkit::DummyControl control = Toolkit::DummyControl::DownCast( Dali::BaseHandle( object ) ); + DummyControlImpl& dummyImpl = static_cast( control.GetImplementation() ); + + Visual::Base visual = dummyImpl.GetVisual( propertyIndex ); + Property::Map map; + if( visual ) + { + visual.CreatePropertyMap( map ); + } + Dali::Property::Value value = map; + return value; } diff --git a/automated-tests/src/dali-toolkit/utc-Dali-AnimatedVectorImageVisual.cpp b/automated-tests/src/dali-toolkit/utc-Dali-AnimatedVectorImageVisual.cpp index c0fee41..4c80bf2 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-AnimatedVectorImageVisual.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-AnimatedVectorImageVisual.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include "dummy-control.h" using namespace Dali; @@ -45,6 +46,16 @@ namespace const char* TEST_VECTOR_IMAGE_FILE_NAME = TEST_RESOURCE_DIR "/insta_camera.json"; +bool gAnimationFinishedSignalFired = false; + +void VisualEventSignal( Control control, Dali::Property::Index visualIndex, Dali::Property::Index signalId ) +{ + if( visualIndex == DummyControl::Property::TEST_VISUAL && signalId == DevelAnimatedVectorImageVisual::Signal::ANIMATION_FINISHED ) + { + gAnimationFinishedSignalFired = true; + } +} + } int UtcDaliVisualFactoryGetAnimatedVectorImageVisual01(void) @@ -273,7 +284,9 @@ int UtcDaliAnimatedVectorImageVisualPlayback(void) DALI_TEST_EQUALS( Test::WaitForEventThreadTrigger( 1 ), true, TEST_LOCATION ); - // test + Property::Map map = dummyControl.GetProperty< Property::Map >( DummyControl::Property::TEST_VISUAL ); + Property::Value* value = map.Find( DevelImageVisual::Property::PLAY_STATE ); + DALI_TEST_CHECK( value->Get< int >() == static_cast< int >( DevelImageVisual::PlayState::PLAYING ) ); tet_infoline( "Test Pause action" ); DevelControl::DoAction( dummyControl, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedVectorImageVisual::Action::PAUSE, attributes ); @@ -281,15 +294,19 @@ int UtcDaliAnimatedVectorImageVisualPlayback(void) application.SendNotification(); application.Render(16); - // test + map = dummyControl.GetProperty< Property::Map >( DummyControl::Property::TEST_VISUAL ); + value = map.Find( DevelImageVisual::Property::PLAY_STATE ); + DALI_TEST_CHECK( value->Get< int >() == static_cast< int >( DevelImageVisual::PlayState::PAUSED ) ); - tet_infoline( "Test Resume action" ); - DevelControl::DoAction( dummyControl, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedVectorImageVisual::Action::RESUME, attributes ); + tet_infoline( "Test Play action" ); + DevelControl::DoAction( dummyControl, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedVectorImageVisual::Action::PLAY, attributes ); application.SendNotification(); application.Render(16); - // test + map = dummyControl.GetProperty< Property::Map >( DummyControl::Property::TEST_VISUAL ); + value = map.Find( DevelImageVisual::Property::PLAY_STATE ); + DALI_TEST_CHECK( value->Get< int >() == static_cast< int >( DevelImageVisual::PlayState::PLAYING ) ); tet_infoline( "Test Stop action" ); DevelControl::DoAction( dummyControl, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedVectorImageVisual::Action::STOP, attributes ); @@ -297,7 +314,9 @@ int UtcDaliAnimatedVectorImageVisualPlayback(void) application.SendNotification(); application.Render(16); - // test + map = dummyControl.GetProperty< Property::Map >( DummyControl::Property::TEST_VISUAL ); + value = map.Find( DevelImageVisual::Property::PLAY_STATE ); + DALI_TEST_CHECK( value->Get< int >() == static_cast< int >( DevelImageVisual::PlayState::STOPPED ) ); tet_infoline( "Test Stop action again" ); DevelControl::DoAction( dummyControl, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedVectorImageVisual::Action::STOP, attributes ); @@ -305,7 +324,9 @@ int UtcDaliAnimatedVectorImageVisualPlayback(void) application.SendNotification(); application.Render(16); - // test + map = dummyControl.GetProperty< Property::Map >( DummyControl::Property::TEST_VISUAL ); + value = map.Find( DevelImageVisual::Property::PLAY_STATE ); + DALI_TEST_CHECK( value->Get< int >() == static_cast< int >( DevelImageVisual::PlayState::STOPPED ) ); tet_infoline( "Test Play action" ); DevelControl::DoAction( dummyControl, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedVectorImageVisual::Action::PLAY, attributes ); @@ -313,15 +334,20 @@ int UtcDaliAnimatedVectorImageVisualPlayback(void) application.SendNotification(); application.Render(16); - // test + map = dummyControl.GetProperty< Property::Map >( DummyControl::Property::TEST_VISUAL ); + value = map.Find( DevelImageVisual::Property::PLAY_STATE ); + DALI_TEST_CHECK( value->Get< int >() == static_cast< int >( DevelImageVisual::PlayState::PLAYING ) ); - dummyControl.SetSize( 100.0f, 100.0f ); + // Change Size + Vector3 newSize( 100.0f, 100.0f, 0.0f ); + dummyControl.SetSize( newSize ); application.SendNotification(); application.Render(16); - // test // Size should be changed + Vector3 naturalSize = dummyControl.GetNaturalSize(); + DALI_TEST_CHECK( naturalSize == newSize ); dummyControl.Unparent(); } @@ -439,7 +465,8 @@ int UtcDaliAnimatedVectorImageVisualLoopCount(void) application.SendNotification(); application.Render(); - DALI_TEST_EQUALS( Test::WaitForEventThreadTrigger( 1 ), true, TEST_LOCATION ); + // Trigger count is 2 - resource ready and animation finished + DALI_TEST_EQUALS( Test::WaitForEventThreadTrigger( 2 ), true, TEST_LOCATION ); // renderer is added to actor DALI_TEST_CHECK( actor.GetRendererCount() == 1u ); @@ -488,3 +515,45 @@ int UtcDaliAnimatedVectorImageVisualPlayRange(void) END_TEST; } + +int UtcDaliAnimatedVectorImageVisualAnimationFinishedSignal(void) +{ + ToolkitTestApplication application; + tet_infoline( "UtcDaliAnimatedVectorImageVisualAnimationFinishedSignal" ); + + Property::Map propertyMap; + propertyMap.Add( Toolkit::Visual::Property::TYPE, DevelVisual::ANIMATED_VECTOR_IMAGE ) + .Add( ImageVisual::Property::URL, TEST_VECTOR_IMAGE_FILE_NAME ) + .Add( DevelImageVisual::Property::LOOP_COUNT, 3 ); + + Visual::Base visual = VisualFactory::Get().CreateVisual( propertyMap ); + DALI_TEST_CHECK( visual ); + + DummyControl actor = DummyControl::New( true ); + DummyControlImpl& dummyImpl = static_cast< DummyControlImpl& >( actor.GetImplementation() ); + dummyImpl.RegisterVisual( DummyControl::Property::TEST_VISUAL, visual ); + + DevelControl::VisualEventSignal( actor ).Connect( &VisualEventSignal ); + + Vector2 controlSize( 20.f, 30.f ); + actor.SetSize( controlSize ); + + Stage::GetCurrent().Add( actor ); + + Property::Map attributes; + DevelControl::DoAction( actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedVectorImageVisual::Action::PLAY, attributes ); + + application.SendNotification(); + application.Render(); + + // Wait for animation finish + DALI_TEST_EQUALS( Test::WaitForEventThreadTrigger( 2 ), true, TEST_LOCATION ); + + Property::Map map = actor.GetProperty< Property::Map >( DummyControl::Property::TEST_VISUAL ); + Property::Value* value = map.Find( DevelImageVisual::Property::PLAY_STATE ); + DALI_TEST_CHECK( value->Get< int >() == static_cast< int >( DevelImageVisual::PlayState::STOPPED ) ); + + DALI_TEST_EQUALS( gAnimationFinishedSignalFired, true, TEST_LOCATION ); + + END_TEST; +} diff --git a/automated-tests/src/dali-toolkit/utc-Dali-ImageView.cpp b/automated-tests/src/dali-toolkit/utc-Dali-ImageView.cpp index 1257060..7f82a15 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-ImageView.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-ImageView.cpp @@ -835,7 +835,8 @@ int UtcDaliImageViewSetImageOnstageN(void) DALI_TEST_CHECK( !value.Get( url ) ); Property::Map map; - DALI_TEST_CHECK( !value.Get( map ) ); + value.Get( map ); + DALI_TEST_CHECK( map.Empty() ); END_TEST; } @@ -930,7 +931,8 @@ int UtcDaliImageViewSetImageOffstageN(void) DALI_TEST_CHECK( !value.Get( url ) ); Property::Map map; - DALI_TEST_CHECK( !value.Get( map ) ); + value.Get( map ); + DALI_TEST_CHECK( map.Empty() ); END_TEST; } @@ -950,7 +952,8 @@ int UtcDaliImageViewSetImageN(void) DALI_TEST_CHECK( !value.Get( url ) ); Property::Map map; - DALI_TEST_CHECK( !value.Get( map ) ); + value.Get( map ); + DALI_TEST_CHECK( map.Empty() ); std::string resource_url; Property::Value val = imageView.GetProperty( imageView.GetPropertyIndex( "image" ) ); @@ -979,7 +982,8 @@ int UtcDaliImageViewSetImageTypeChangesP(void) application.Render( 16 ); DALI_TEST_CHECK( ! value.Get( url ) ); // Value should be empty - DALI_TEST_CHECK( ! value.Get( map ) ); // Value should be empty + value.Get( map ); + DALI_TEST_CHECK( map.Empty() ); // Value should be empty DALI_TEST_CHECK( ! visual ); // Visual should be invalid // Set a URL @@ -1005,7 +1009,8 @@ int UtcDaliImageViewSetImageTypeChangesP(void) visual = DevelControl::GetVisual( controlImpl, ImageView::Property::IMAGE ); DALI_TEST_CHECK( ! value.Get( url ) ); // Value should be empty - DALI_TEST_CHECK( ! value.Get( map ) ); // Value should be empty + value.Get( map ); + DALI_TEST_CHECK( map.Empty() ); // Value should be empty DALI_TEST_CHECK( ! visual ); // Visual should be invalid // Set an Image @@ -1032,7 +1037,8 @@ int UtcDaliImageViewSetImageTypeChangesP(void) visual = DevelControl::GetVisual( controlImpl, ImageView::Property::IMAGE ); DALI_TEST_CHECK( ! value.Get( url ) ); // Value should be empty - DALI_TEST_CHECK( ! value.Get( map ) ); // Value should be empty + value.Get( map ); + DALI_TEST_CHECK( map.Empty() ); // Value should be empty DALI_TEST_CHECK( ! visual ); // Visual should be invalid // Set a URL in property map diff --git a/dali-toolkit/devel-api/controls/control-devel.cpp b/dali-toolkit/devel-api/controls/control-devel.cpp index 116f69a..66b9916 100644 --- a/dali-toolkit/devel-api/controls/control-devel.cpp +++ b/dali-toolkit/devel-api/controls/control-devel.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * Copyright (c) 2018 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -96,6 +96,13 @@ void DoAction( Control& control, Dali::Property::Index visualIndex, Dali::Proper controlDataImpl.DoAction( visualIndex, actionId, attributes ); } +VisualEventSignalType& VisualEventSignal( Control control ) +{ + Internal::Control& internalControl = Toolkit::Internal::GetImplementation( control ); + Internal::Control::Impl& controlDataImpl = Internal::Control::Impl::Get( internalControl ); + return controlDataImpl.VisualEventSignal(); +} + } // namespace DevelControl } // namespace Toolkit diff --git a/dali-toolkit/devel-api/controls/control-devel.h b/dali-toolkit/devel-api/controls/control-devel.h index ae90f4d..12d8be9 100644 --- a/dali-toolkit/devel-api/controls/control-devel.h +++ b/dali-toolkit/devel-api/controls/control-devel.h @@ -2,7 +2,7 @@ #define DALI_TOOLKIT_CONTROL_DEVEL_H /* - * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * Copyright (c) 2018 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -241,6 +241,22 @@ DALI_IMPORT_API Dali::Animation CreateTransition( Internal::Control& control, co */ DALI_IMPORT_API void DoAction( Control& control, Dali::Property::Index visualIndex, Dali::Property::Index actionId, const Dali::Property::Value attributes ); +/** + * @brief Visual Event signal type + */ +using VisualEventSignalType = Signal< void ( Control, Dali::Property::Index, Dali::Property::Index ) >; + +/** + * @brief This signal is emitted when a visual has an event to notify. + * + * A callback of the following type may be connected: + * @code + * void YourCallbackName( Control control, Dali::Property::Index visualIndex, Dali::Property::Index signalId ); + * @endcode + * @return The signal to connect to + */ +DALI_IMPORT_API VisualEventSignalType& VisualEventSignal( Control control ); + } // namespace DevelControl } // namespace Toolkit diff --git a/dali-toolkit/devel-api/file.list b/dali-toolkit/devel-api/file.list index f111d5f..76b4e65 100644 --- a/dali-toolkit/devel-api/file.list +++ b/dali-toolkit/devel-api/file.list @@ -95,6 +95,7 @@ devel_api_visuals_header_files = \ $(devel_api_src_dir)/visuals/animated-gradient-visual-properties-devel.h \ $(devel_api_src_dir)/visuals/animated-image-visual-actions-devel.h \ $(devel_api_src_dir)/visuals/animated-vector-image-visual-actions-devel.h \ + $(devel_api_src_dir)/visuals/animated-vector-image-visual-signals-devel.h \ $(devel_api_src_dir)/visuals/color-visual-properties-devel.h \ $(devel_api_src_dir)/visuals/image-visual-properties-devel.h \ $(devel_api_src_dir)/visuals/image-visual-actions-devel.h \ diff --git a/dali-toolkit/devel-api/visuals/animated-vector-image-visual-actions-devel.h b/dali-toolkit/devel-api/visuals/animated-vector-image-visual-actions-devel.h index 6e40c69..1f05bd7 100644 --- a/dali-toolkit/devel-api/visuals/animated-vector-image-visual-actions-devel.h +++ b/dali-toolkit/devel-api/visuals/animated-vector-image-visual-actions-devel.h @@ -39,7 +39,6 @@ enum Type { PLAY, ///< Play the animated vector image. PAUSE, ///< Pause the animated vector image. - RESUME, ///< Resume the animated vector image. STOP ///< Stop the animated vector image. This is also Default playback mode. }; diff --git a/dali-toolkit/devel-api/visuals/animated-vector-image-visual-signals-devel.h b/dali-toolkit/devel-api/visuals/animated-vector-image-visual-signals-devel.h new file mode 100644 index 0000000..3ab14e1 --- /dev/null +++ b/dali-toolkit/devel-api/visuals/animated-vector-image-visual-signals-devel.h @@ -0,0 +1,51 @@ +#ifndef DALI_TOOLKIT_DEVEL_API_VISUALS_ANIMATED_VECTOR_IMAGE_VISUAL_SIGNALS_DEVEL_H +#define DALI_TOOLKIT_DEVEL_API_VISUALS_ANIMATED_VECTOR_IMAGE_VISUAL_SIGNALS_DEVEL_H + +/* + * Copyright (c) 2018 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +namespace Dali +{ + +namespace Toolkit +{ + +namespace DevelAnimatedVectorImageVisual +{ + +/** + * @brief Signal that the animated vector image visual can emit. + */ +namespace Signal +{ +/** + * @brief The available signals for this visual + */ +enum Type +{ + ANIMATION_FINISHED ///< Animation has finished. +}; + +} // namespace Signal + +} // namespace DevelAnimatedVectorImageVisual + +} // namespace Toolkit + +} // namespace Dali + +#endif // DALI_TOOLKIT_DEVEL_API_VISUALS_ANIMATED_VECTOR_IMAGE_VISUAL_SIGNALS_DEVEL_H diff --git a/dali-toolkit/devel-api/visuals/image-visual-properties-devel.h b/dali-toolkit/devel-api/visuals/image-visual-properties-devel.h index eb39aa6..2ae2726 100644 --- a/dali-toolkit/devel-api/visuals/image-visual-properties-devel.h +++ b/dali-toolkit/devel-api/visuals/image-visual-properties-devel.h @@ -92,12 +92,29 @@ enum Type * @details Name "playRange", Type Property::VECTOR2, between 0 and 1 * @note Default 0 and 1 */ - PLAY_RANGE = ORIENTATION_CORRECTION + 4 + PLAY_RANGE = ORIENTATION_CORRECTION + 4, + + /** + * @brief The playing state the AnimatedVectorImageVisual will use. + * @details Name "playState", type PlayState (Property::INTEGER) + * @note This property is read-only. + */ + PLAY_STATE = ORIENTATION_CORRECTION + 5 }; } //namespace Property +/** + * @brief Enumeration for what state the animation is in. + */ +enum class PlayState +{ + STOPPED, ///< Animation has stopped + PLAYING, ///< The animation is playing + PAUSED ///< The animation is paused +}; + } // namespace DevelImageVisual } // namespace Toolkit diff --git a/dali-toolkit/internal/controls/control/control-data-impl.cpp b/dali-toolkit/internal/controls/control/control-data-impl.cpp index b061268..31c8846 100644 --- a/dali-toolkit/internal/controls/control/control-data-impl.cpp +++ b/dali-toolkit/internal/controls/control/control-data-impl.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * Copyright (c) 2018 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -327,6 +327,8 @@ Control::Impl::Impl( Control& controlImpl ) mMargin( 0, 0, 0, 0 ), mPadding( 0, 0, 0, 0 ), mKeyEventSignal(), + mResourceReadySignal(), + mVisualEventSignal(), mPinchGestureDetector(), mPanGestureDetector(), mTapGestureDetector(), @@ -619,15 +621,15 @@ void Control::Impl::StopObservingVisual( Toolkit::Visual::Base& visual ) Internal::Visual::Base& visualImpl = Toolkit::GetImplementation( visual ); // Stop observing the visual - visualImpl.RemoveResourceObserver( *this ); + visualImpl.RemoveEventObserver( *this ); } void Control::Impl::StartObservingVisual( Toolkit::Visual::Base& visual) { Internal::Visual::Base& visualImpl = Toolkit::GetImplementation( visual ); - // start observing the visual for resource ready - visualImpl.AddResourceObserver( *this ); + // start observing the visual for events + visualImpl.AddEventObserver( *this ); } // Called by a Visual when it's resource is ready @@ -673,6 +675,20 @@ void Control::Impl::ResourceReady( Visual::Base& object) } } +void Control::Impl::NotifyVisualEvent( Visual::Base& object, Property::Index signalId ) +{ + for( auto registeredIter = mVisuals.Begin(), end = mVisuals.End(); registeredIter != end; ++registeredIter ) + { + Internal::Visual::Base& registeredVisualImpl = Toolkit::GetImplementation( (*registeredIter)->visual ); + if( &object == ®isteredVisualImpl ) + { + Dali::Toolkit::Control handle( mControlImpl.GetOwner() ); + mVisualEventSignal.Emit( handle, (*registeredIter)->index, signalId ); + break; + } + } +} + bool Control::Impl::IsResourceReady() const { // Iterate through and check all the enabled visuals are ready @@ -1389,6 +1405,11 @@ Extents Control::Impl::GetPadding() const return mControlImpl.mImpl->mPadding; } +DevelControl::VisualEventSignalType& Control::Impl::VisualEventSignal() +{ + return mVisualEventSignal; +} + } // namespace Internal } // namespace Toolkit diff --git a/dali-toolkit/internal/controls/control/control-data-impl.h b/dali-toolkit/internal/controls/control/control-data-impl.h index ddd7506..7d9b74d 100644 --- a/dali-toolkit/internal/controls/control/control-data-impl.h +++ b/dali-toolkit/internal/controls/control/control-data-impl.h @@ -2,7 +2,7 @@ #define DALI_TOOLKIT_CONTROL_DATA_IMPL_H /* - * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * Copyright (c) 2018 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,7 +24,7 @@ #include // INTERNAL INCLUDES -#include +#include #include #include #include @@ -64,7 +64,7 @@ typedef Dali::OwnerContainer< RegisteredVisual* > RegisteredVisualContainer; /** * @brief Holds the Implementation for the internal control class */ -class Control::Impl : public ConnectionTracker, public Visual::ResourceObserver +class Control::Impl : public ConnectionTracker, public Visual::EventObserver { public: @@ -123,11 +123,19 @@ public: /** * @brief Called when a resource is ready. * @param[in] object The visual whose resources are ready - * @note Overriding method in Visual::ResourceObserver. + * @note Overriding method in Visual::EventObserver. */ virtual void ResourceReady( Visual::Base& object ); /** + * @brief Called when an event occurs. + * @param[in] object The visual whose events occur + * @param[in] signalId The signal to emit. See Visual to find supported signals + * @note Overriding method in Visual::EventObserver. + */ + virtual void NotifyVisualEvent( Visual::Base& object, Property::Index signalId ) override; + + /** * @copydoc Dali::Toolkit::DevelControl::RegisterVisual() */ void RegisterVisual( Property::Index index, Toolkit::Visual::Base& visual ); @@ -300,6 +308,11 @@ public: */ Extents GetPadding() const; + /** + * @copydoc DevelControl::VisualEventSignal() + */ + DevelControl::VisualEventSignalType& VisualEventSignal(); + private: /** @@ -360,6 +373,7 @@ public: Toolkit::Control::KeyInputFocusSignalType mKeyInputFocusGainedSignal; Toolkit::Control::KeyInputFocusSignalType mKeyInputFocusLostSignal; Toolkit::Control::ResourceReadySignalType mResourceReadySignal; + DevelControl::VisualEventSignalType mVisualEventSignal; // Gesture Detection PinchGestureDetector mPinchGestureDetector; diff --git a/dali-toolkit/internal/controls/image-view/image-view-impl.cpp b/dali-toolkit/internal/controls/image-view/image-view-impl.cpp index dcf7e3e..5f5cef5 100755 --- a/dali-toolkit/internal/controls/image-view/image-view-impl.cpp +++ b/dali-toolkit/internal/controls/image-view/image-view-impl.cpp @@ -441,9 +441,15 @@ Property::Value ImageView::GetProperty( BaseObject* object, Property::Index prop Scripting::CreatePropertyMap( impl.mImage, map ); value = map; } - else if( !impl.mPropertyMap.Empty() ) + else { - value = impl.mPropertyMap; + Property::Map map; + Toolkit::Visual::Base visual = DevelControl::GetVisual( impl, Toolkit::ImageView::Property::IMAGE ); + if( visual ) + { + visual.CreatePropertyMap( map ); + } + value = map; } break; } diff --git a/dali-toolkit/internal/visuals/animated-vector-image/animated-vector-image-visual.cpp b/dali-toolkit/internal/visuals/animated-vector-image/animated-vector-image-visual.cpp index a266fad..0a7b0c6 100644 --- a/dali-toolkit/internal/visuals/animated-vector-image/animated-vector-image-visual.cpp +++ b/dali-toolkit/internal/visuals/animated-vector-image/animated-vector-image-visual.cpp @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -100,6 +101,15 @@ void AnimatedVectorImageVisual::DoCreatePropertyMap( Property::Map& map ) const } map.Insert( Toolkit::DevelImageVisual::Property::LOOP_COUNT, static_cast< int >( mLoopCount ) ); map.Insert( Toolkit::DevelImageVisual::Property::PLAY_RANGE, static_cast< Vector2 >( mPlayRange ) ); + + if( mVectorRasterizeThread ) + { + map.Insert( Toolkit::DevelImageVisual::Property::PLAY_STATE, static_cast< int >( mVectorRasterizeThread->GetPlayState() ) ); + } + else + { + map.Insert( Toolkit::DevelImageVisual::Property::PLAY_STATE, static_cast< int >( DevelImageVisual::PlayState::STOPPED ) ); + } } void AnimatedVectorImageVisual::DoCreateInstancePropertyMap( Property::Map& map ) const @@ -251,6 +261,7 @@ void AnimatedVectorImageVisual::OnSetTransform() mVectorRasterizeThread = std::unique_ptr< VectorRasterizeThread >( new VectorRasterizeThread( mUrl.GetUrl(), mImpl->mRenderer, width, height ) ); mVectorRasterizeThread->SetResourceReadyCallback( new EventThreadCallback( MakeCallback( this, &AnimatedVectorImageVisual::OnResourceReady ) ) ); + mVectorRasterizeThread->SetAnimationFinishedCallback( new EventThreadCallback( MakeCallback( this, &AnimatedVectorImageVisual::OnAnimationFinished ) ) ); mVectorRasterizeThread->SetLoopCount( mLoopCount ); mVectorRasterizeThread->SetPlayRange( mPlayRange ); @@ -280,11 +291,6 @@ void AnimatedVectorImageVisual::OnSetTransform() void AnimatedVectorImageVisual::OnDoAction( const Property::Index actionId, const Property::Value& attributes ) { - if( actionId == mActionStatus ) - { - return; - } - // Check if action is valid for this visual type and perform action if possible switch( actionId ) { @@ -311,22 +317,23 @@ void AnimatedVectorImageVisual::OnDoAction( const Property::Index actionId, cons mActionStatus = DevelAnimatedVectorImageVisual::Action::PAUSE; break; } - case DevelAnimatedVectorImageVisual::Action::RESUME: - { - if( mVectorRasterizeThread ) - { - mVectorRasterizeThread->ResumeAnimation(); - DevelStage::SetRenderingBehavior( Stage::GetCurrent(), DevelStage::Rendering::CONTINUOUSLY ); - } - mActionStatus = DevelAnimatedVectorImageVisual::Action::RESUME; - break; - } case DevelAnimatedVectorImageVisual::Action::STOP: { if( mVectorRasterizeThread ) { + bool emitSignal = false; + if( mVectorRasterizeThread->GetPlayState() != DevelImageVisual::PlayState::STOPPED ) + { + emitSignal = true; + } + mVectorRasterizeThread->StopAnimation(); DevelStage::SetRenderingBehavior( Stage::GetCurrent(), DevelStage::Rendering::IF_REQUIRED ); + + if( emitSignal ) + { + OnAnimationFinished(); + } } mActionStatus = DevelAnimatedVectorImageVisual::Action::STOP; break; @@ -348,6 +355,14 @@ void AnimatedVectorImageVisual::OnResourceReady() } } +void AnimatedVectorImageVisual::OnAnimationFinished() +{ + if( mImpl->mEventObserver ) + { + mImpl->mEventObserver->NotifyVisualEvent( *this, DevelAnimatedVectorImageVisual::Signal::ANIMATION_FINISHED ); + } +} + } // namespace Internal } // namespace Toolkit diff --git a/dali-toolkit/internal/visuals/animated-vector-image/animated-vector-image-visual.h b/dali-toolkit/internal/visuals/animated-vector-image/animated-vector-image-visual.h index 268cb06..28d79a4 100644 --- a/dali-toolkit/internal/visuals/animated-vector-image/animated-vector-image-visual.h +++ b/dali-toolkit/internal/visuals/animated-vector-image/animated-vector-image-visual.h @@ -150,6 +150,11 @@ private: */ void OnResourceReady(); + /** + * @brief Event callback from rasterize thread. This is called after the animation is finished. + */ + void OnAnimationFinished(); + // Undefined AnimatedVectorImageVisual( const AnimatedVectorImageVisual& visual ) = delete; diff --git a/dali-toolkit/internal/visuals/animated-vector-image/vector-rasterize-thread.cpp b/dali-toolkit/internal/visuals/animated-vector-image/vector-rasterize-thread.cpp index fc4a1f2..6bbb264 100644 --- a/dali-toolkit/internal/visuals/animated-vector-image/vector-rasterize-thread.cpp +++ b/dali-toolkit/internal/visuals/animated-vector-image/vector-rasterize-thread.cpp @@ -50,7 +50,9 @@ VectorRasterizeThread::VectorRasterizeThread( const std::string& url, Renderer r mConditionalWait(), mMutex(), mResourceReadyTrigger( NULL ), + mAnimationFinishedTrigger( NULL ), mPlayRange( 0.0f, 1.0f ), + mPlayState( DevelImageVisual::PlayState::STOPPED ), mCurrentFrame( 0 ), mTotalFrame( 0 ), mStartFrame( 0 ), @@ -60,8 +62,6 @@ VectorRasterizeThread::VectorRasterizeThread( const std::string& url, Renderer r mLoopCount( LOOP_FOREVER ), mCurrentLoop( 0 ), mNeedRender( false ), - mPlaying( false ), - mPaused( false ), mDestroyThread( false ), mResourceReady( false ), mLogFactory( Dali::Adaptor::Get().GetLogFactory() ) @@ -86,6 +86,7 @@ VectorRasterizeThread::~VectorRasterizeThread() Join(); delete mResourceReadyTrigger; + delete mAnimationFinishedTrigger; } void VectorRasterizeThread::Run() @@ -112,10 +113,16 @@ void VectorRasterizeThread::SetSize( uint32_t width, uint32_t height ) void VectorRasterizeThread::StartAnimation() { ConditionalWait::ScopedLock lock( mConditionalWait ); - if( !mPlaying ) + if( mPlayState != DevelImageVisual::PlayState::PLAYING ) { - mPlaying = true; - mPaused = false; + if( mPlayState == DevelImageVisual::PlayState::STOPPED ) + { + // Reset the current frame and the current loop + mCurrentFrame = mStartFrame; + mCurrentLoop = 0; + } + + mPlayState = DevelImageVisual::PlayState::PLAYING; mConditionalWait.Notify( lock ); DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::StartAnimation: Start\n" ); @@ -125,10 +132,9 @@ void VectorRasterizeThread::StartAnimation() void VectorRasterizeThread::StopAnimation() { ConditionalWait::ScopedLock lock( mConditionalWait ); - if( mPlaying ) + if( mPlayState != DevelImageVisual::PlayState::STOPPED ) { - mPlaying = false; - mPaused = false; + mPlayState = DevelImageVisual::PlayState::STOPPED; DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::StopAnimation: Stop\n" ); } @@ -137,26 +143,14 @@ void VectorRasterizeThread::StopAnimation() void VectorRasterizeThread::PauseAnimation() { ConditionalWait::ScopedLock lock( mConditionalWait ); - if( mPlaying && !mPaused ) + if( mPlayState == DevelImageVisual::PlayState::PLAYING ) { - mPaused = true; + mPlayState = DevelImageVisual::PlayState::PAUSED; DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::PauseAnimation: Pause\n" ); } } -void VectorRasterizeThread::ResumeAnimation() -{ - ConditionalWait::ScopedLock lock( mConditionalWait ); - if( mPlaying && mPaused ) - { - mPaused = false; - mConditionalWait.Notify( lock ); - - DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::ResumeAnimation: Resume\n" ); - } -} - void VectorRasterizeThread::RenderFrame() { ConditionalWait::ScopedLock lock( mConditionalWait ); @@ -172,6 +166,12 @@ void VectorRasterizeThread::SetResourceReadyCallback( EventThreadCallback* callb mResourceReadyTrigger = callback; } +void VectorRasterizeThread::SetAnimationFinishedCallback( EventThreadCallback* callback ) +{ + ConditionalWait::ScopedLock lock( mConditionalWait ); + mAnimationFinishedTrigger = callback; +} + void VectorRasterizeThread::SetLoopCount( int16_t count ) { ConditionalWait::ScopedLock lock( mConditionalWait ); @@ -196,20 +196,19 @@ void VectorRasterizeThread::SetPlayRange( Vector2 range ) } } +DevelImageVisual::PlayState VectorRasterizeThread::GetPlayState() +{ + return mPlayState; +} + bool VectorRasterizeThread::IsThreadReady() { ConditionalWait::ScopedLock lock( mConditionalWait ); - if( ( !mPlaying || mPaused ) && !mNeedRender && !mDestroyThread ) + if( mPlayState != DevelImageVisual::PlayState::PLAYING && !mNeedRender && !mDestroyThread ) { DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::IsThreadReady: Wait\n" ); - if( !mPlaying ) - { - mCurrentFrame = mStartFrame; - mCurrentLoop = 0; - } - mConditionalWait.Wait( lock ); } @@ -241,7 +240,7 @@ void VectorRasterizeThread::Rasterize() // Rasterize mVectorRenderer.Render( mCurrentFrame ); - if( mPlaying && !mPaused ) + if( mPlayState == DevelImageVisual::PlayState::PLAYING ) { if( ++mCurrentFrame >= mEndFrame ) { @@ -256,7 +255,11 @@ void VectorRasterizeThread::Rasterize() if( mCurrentLoop >= mLoopCount ) { // Animation is finished - mPlaying = false; + mPlayState = DevelImageVisual::PlayState::STOPPED; + + mAnimationFinishedTrigger->Trigger(); + + DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::Rasterize: Animation is finished\n" ); } else { diff --git a/dali-toolkit/internal/visuals/animated-vector-image/vector-rasterize-thread.h b/dali-toolkit/internal/visuals/animated-vector-image/vector-rasterize-thread.h index f05f8b6..daa8058 100644 --- a/dali-toolkit/internal/visuals/animated-vector-image/vector-rasterize-thread.h +++ b/dali-toolkit/internal/visuals/animated-vector-image/vector-rasterize-thread.h @@ -26,6 +26,9 @@ #include #include +// INTERNAL INCLUDES +#include + namespace Dali { @@ -81,11 +84,6 @@ public: void PauseAnimation(); /** - * @brief Resume the vector animation. - */ - void ResumeAnimation(); - - /** * @brief Render one frame. The current frame number will be increased. */ void RenderFrame(); @@ -97,6 +95,12 @@ public: void SetResourceReadyCallback( EventThreadCallback* callback ); /** + * @brief This callback is called after the animation is finished. + * @param[in] callback The animation finished callback + */ + void SetAnimationFinishedCallback( EventThreadCallback* callback ); + + /** * @brief Enable looping for 'count' repeats. -1 means to repeat forever. * @param[in] count The number of times to loop */ @@ -109,6 +113,12 @@ public: */ void SetPlayRange( Vector2 range ); + /** + * @brief Get the play state + * @return The play state + */ + DevelImageVisual::PlayState GetPlayState(); + protected: /** @@ -143,25 +153,25 @@ private: private: - std::string mUrl; - VectorAnimationRenderer mVectorRenderer; - ConditionalWait mConditionalWait; - Dali::Mutex mMutex; - EventThreadCallback* mResourceReadyTrigger; - Vector2 mPlayRange; - uint32_t mCurrentFrame; - uint32_t mTotalFrame; - uint32_t mStartFrame; - uint32_t mEndFrame; - uint32_t mWidth; - uint32_t mHeight; - int16_t mLoopCount; - int16_t mCurrentLoop; - bool mNeedRender; - bool mPlaying; - bool mPaused; - bool mDestroyThread; ///< Whether the thread be destroyed - bool mResourceReady; + std::string mUrl; + VectorAnimationRenderer mVectorRenderer; + ConditionalWait mConditionalWait; + Dali::Mutex mMutex; + EventThreadCallback* mResourceReadyTrigger; + EventThreadCallback* mAnimationFinishedTrigger; + Vector2 mPlayRange; + DevelImageVisual::PlayState mPlayState; + uint32_t mCurrentFrame; + uint32_t mTotalFrame; + uint32_t mStartFrame; + uint32_t mEndFrame; + uint32_t mWidth; + uint32_t mHeight; + int16_t mLoopCount; + int16_t mCurrentLoop; + bool mNeedRender; + bool mDestroyThread; ///< Whether the thread be destroyed + bool mResourceReady; const Dali::LogFactoryInterface& mLogFactory; ///< The log factory }; diff --git a/dali-toolkit/internal/visuals/visual-base-data-impl.cpp b/dali-toolkit/internal/visuals/visual-base-data-impl.cpp index 374ff68..0b25570 100644 --- a/dali-toolkit/internal/visuals/visual-base-data-impl.cpp +++ b/dali-toolkit/internal/visuals/visual-base-data-impl.cpp @@ -117,7 +117,7 @@ bool GetPolicyFromValue( const Property::Value& value, Vector2& policy ) Internal::Visual::Base::Impl::Impl() : mCustomShader( NULL ), mBlendSlotDelegate( NULL ), - mResourceObserver( NULL ), + mEventObserver( NULL ), mTransform(), mMixColor( Color::WHITE ), mControlSize( Vector2::ZERO ), diff --git a/dali-toolkit/internal/visuals/visual-base-data-impl.h b/dali-toolkit/internal/visuals/visual-base-data-impl.h index fd24205..72c7ce5 100644 --- a/dali-toolkit/internal/visuals/visual-base-data-impl.h +++ b/dali-toolkit/internal/visuals/visual-base-data-impl.h @@ -24,7 +24,7 @@ // INTERNAL INCLUDES #include -#include +#include #include #include @@ -117,7 +117,7 @@ struct Base::Impl Renderer mRenderer; CustomShader* mCustomShader; SlotDelegate* mBlendSlotDelegate; ///< Used to own mix color animation connection - ResourceObserver* mResourceObserver; ///< Allows controls to observe when the visual resources are loaded and ready + EventObserver* mEventObserver; ///< Allows controls to observe when the visual has events to notify std::string mName; Transform mTransform; Vector4 mMixColor; diff --git a/dali-toolkit/internal/visuals/visual-base-impl.cpp b/dali-toolkit/internal/visuals/visual-base-impl.cpp index e4f12c8..4aadb49 100755 --- a/dali-toolkit/internal/visuals/visual-base-impl.cpp +++ b/dali-toolkit/internal/visuals/visual-base-impl.cpp @@ -414,14 +414,14 @@ const Vector4& Visual::Base::GetMixColor() const return mImpl->mMixColor; } -void Visual::Base::AddResourceObserver( Visual::ResourceObserver& observer) +void Visual::Base::AddEventObserver( Visual::EventObserver& observer) { - mImpl->mResourceObserver = &observer; + mImpl->mEventObserver = &observer; } -void Visual::Base::RemoveResourceObserver( Visual::ResourceObserver& observer ) +void Visual::Base::RemoveEventObserver( Visual::EventObserver& observer ) { - mImpl->mResourceObserver = NULL; + mImpl->mEventObserver = NULL; } void Visual::Base::ResourceReady(Toolkit::Visual::ResourceStatus resourceStatus) @@ -430,10 +430,10 @@ void Visual::Base::ResourceReady(Toolkit::Visual::ResourceStatus resourceStatus) { mImpl->mResourceStatus = resourceStatus; - if( mImpl->mResourceObserver ) + if( mImpl->mEventObserver ) { // observer is currently a control impl - mImpl->mResourceObserver->ResourceReady( *this ); + mImpl->mEventObserver->ResourceReady( *this ); } } } diff --git a/dali-toolkit/internal/visuals/visual-base-impl.h b/dali-toolkit/internal/visuals/visual-base-impl.h index b9cf7e9..06cc25e 100644 --- a/dali-toolkit/internal/visuals/visual-base-impl.h +++ b/dali-toolkit/internal/visuals/visual-base-impl.h @@ -46,7 +46,7 @@ namespace Internal namespace Visual { -class ResourceObserver; +class EventObserver; /** * Base class for all Control rendering logic. A control may have multiple visuals. @@ -221,16 +221,15 @@ public: Internal::TransitionData::Animator& animator ); /** - * @brief Add an observer to watch for when the Visuals resources are loaded. + * @brief Add an observer to watch for when the Visuals have events to notify * Currently only supports a single observer - * */ - void AddResourceObserver( Visual::ResourceObserver& observer ); + void AddEventObserver( Visual::EventObserver& observer ); /** * @brief Remove an observer */ - void RemoveResourceObserver( Visual::ResourceObserver& observer ); + void RemoveEventObserver( Visual::EventObserver& observer ); /** * @brief Called when the visuals resources are loaded / ready diff --git a/dali-toolkit/internal/visuals/visual-event-observer.h b/dali-toolkit/internal/visuals/visual-event-observer.h new file mode 100644 index 0000000..d816c34 --- /dev/null +++ b/dali-toolkit/internal/visuals/visual-event-observer.h @@ -0,0 +1,82 @@ +#ifndef DALI_INTERNAL_TOOLKIT_VISUAL_EVENT_OBSERVER_H +#define DALI_INTERNAL_TOOLKIT_VISUAL_EVENT_OBSERVER_H + +/* + * Copyright (c) 2018 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// EXTERNAL INCLUDES +#include + +namespace Dali +{ +namespace Toolkit +{ +namespace Internal +{ +namespace Visual +{ + +class Base; + +/** + * Observer to be informed when visuals have events. + */ +class EventObserver +{ +public: + + /** + * Inform the observer of the object when a resource is ready. + * @param[in] object The connection owner + */ + virtual void ResourceReady( Visual::Base& object ) = 0; + + /** + * Inform the observer of the object when an event occurs. + * @param[in] object The connection owner + * @param[in] signalId The signal to emit. See Visual to find supported signals + */ + virtual void NotifyVisualEvent( Visual::Base& object, Property::Index signalId ) = 0; + +protected: + + /** + * constructor + */ + EventObserver() + { + } + + /** + * virtual destructor + */ + virtual ~EventObserver() + { + } + + // Undefined copy constructor. + EventObserver( const EventObserver& ) = delete; + + // Undefined assignment operator. + EventObserver& operator=( const EventObserver& ) = delete; +}; + +} // Visual +} // Internal +} // Toolkit +} // Dali + +#endif // DALI_INTERNAL_TOOLKIT_VISUAL_EVENT_OBSERVER_H diff --git a/dali-toolkit/internal/visuals/visual-resource-observer.h b/dali-toolkit/internal/visuals/visual-resource-observer.h deleted file mode 100644 index f671adc..0000000 --- a/dali-toolkit/internal/visuals/visual-resource-observer.h +++ /dev/null @@ -1,74 +0,0 @@ -#ifndef DALI_INTERNAL_TOOLKIT_VISUAL_RESOURCE_OBSERVER_H -#define DALI_INTERNAL_TOOLKIT_VISUAL_RESOURCE_OBSERVER_H - -/* - * Copyright (c) 2017 Samsung Electronics Co., Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - - -namespace Dali -{ -namespace Toolkit -{ -namespace Internal -{ -namespace Visual -{ - -class Base; - - -/** - * Observer to be informed when a visuals resources are ready. - */ -class ResourceObserver -{ - public: - - /** - * Inform the observer of the object that it's connections have changed - * @param[in] object The connection owner - */ - virtual void ResourceReady( Visual::Base& object) = 0; - - protected: - - /** - * constructor - */ - ResourceObserver() - { - }; - - /** - * virtual destructor - */ - virtual ~ResourceObserver() - { - }; - - // Undefined copy constructor. - ResourceObserver( const ResourceObserver& ); - - // Undefined assignment operator. - ResourceObserver& operator=( const ResourceObserver& ); -}; -} // Visual -} // Internal -} // Toolkit -} // Dali - -#endif // DALI_INTERNAL_TOOLKIT_VISUAL_RESOURCE_OBSERVER_H