From: David Steele Date: Fri, 30 Oct 2020 13:19:09 +0000 (+0000) Subject: Merge changes I2df640e0,Ia1188305,I7fae506e,I7967a7cc,Ib0fdcdf4, ... into devel/master X-Git-Tag: dali_2.0.0~6 X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git;a=commitdiff_plain;h=ed11499452da1ccd5fdfa36324881dc66a5281bc;hp=0a7241e813fbfd78d2dc0d2d8c75ec65484b4c47 Merge changes I2df640e0,Ia1188305,I7fae506e,I7967a7cc,Ib0fdcdf4, ... into devel/master * changes: [AT-SPI] MERGING MARKER [AT-SPI] Correct VISIBLE and SHOWING states [AT-SPI] Windows fixes [AT-SPI] Fixed uint underflow risk [AT-SPI] Guard added for potential null pointer dereference [AT-SPI] Implemented reading popup description [AT-SPI] Improving utc coverage ToggleButton tests [AT-SPI] More coverage [AT-SPI] Improving utc coverage [AT-SPI] Set both ScreenReaderEnabled and IsEnabled in TestEnableSC [AT-SPI] Rewritten UtcDaliControlAccessibilityModal [AT-SPI] Pass correct object to dynamic_cast [AT-SPI] UTC correction [AT-SPI] More UTC fixes [AT-SPI] Execute tct under dbus-launch [AT-SPI] UTC fixes [AT-SPI] Add TestDBusWrapper and bypass compilation problems [AT-SPI] Implement accessibility for Popup [AT-SPI] Fix cmake cmp0004 error [AT-SPI] Catch exception by reference [AT-SPI] Migrate Accessibility tests to dali-toolkit-internal [AT-SPI] Add notification for a11y name/description change [AT-SPI] TextController: emit characters before delete [AT-SPI] EmitStateChanged for togglable PushButton [AT-SPI] Add FOCUSABLE state to TextField and TextEditor [AT-SPI] Add Pause and Resume signals [AT-SPI] Let MarkFilter find the closest mark [AT-SPI] Emit ObjectPropertyChangeEvent::VALUE [AT-SPI] Implement proper accessibility for Slider [AT-SPI] Try auto-scrolling in GrabHighlight [AT-SPI] Override IsScrollable for Scrollable [AT-SPI] Support reading states and tooltips of ToggleButton [AT-SPI] Support gaining keyboard focus in TextField, TextEditor [AT-SPI] Allow two finger pan gesture [AT-SPI] Move setting highlightability property for controls to inheriting classes [AT-SPI] Make Accessible::GetName() fall back to actor name [AT-SPI] Fix role setting [AT-SPI] Squashed implementation --- diff --git a/automated-tests/README.md b/automated-tests/README.md index 590571d..f256435 100644 --- a/automated-tests/README.md +++ b/automated-tests/README.md @@ -150,7 +150,7 @@ a refspec to the latest commit, or uses the index/working tree. Testing on target ================= -To build for target, first build and install dali-core, dali-adaptor and dali-toolkit, then build dali-capi without --keep-packs option. +To build for target, first build and install dali-core, dali-adaptor and dali-toolkit. You will need to install libconfig-tiny-perl: diff --git a/automated-tests/patch-coverage.pl b/automated-tests/patch-coverage.pl index 702dc0b..3a97dac 100755 --- a/automated-tests/patch-coverage.pl +++ b/automated-tests/patch-coverage.pl @@ -54,7 +54,7 @@ sub add_counts($$); sub info(@); our $repo = Git->repository(); -our $debug=1; +our $debug=0; our $pd_debug=0; our $root; our %info_data; # Hash containing all data from .info files @@ -1316,7 +1316,7 @@ my $cwd = getcwd(); # expect this to be automated-tests folder # execute coverage.sh, generating build/tizen/dali.info from lib, and # *.dir/dali.info. Don't generate html -`coverage.sh -n`; +print `./coverage.sh -n`; chdir ".."; $root = getcwd(); @@ -1338,12 +1338,7 @@ foreach (@info_files) my @cmd=('--no-pager','diff','--no-ext-diff','-U0','--no-color'); my $status = $repo->command("status", "-s"); -if(scalar(@ARGV)) # REMOVE ME -{ - # REMOVE ME - temp to get past modifying this script in place. - push @cmd, @ARGV; -} -elsif( $status eq "" && !scalar(@ARGV)) +if( $status eq "" && !scalar(@ARGV)) { # There are no changes in the index or working tree, and # no diff arguments to append. Use the last patch instead. diff --git a/automated-tests/src/dali-toolkit/utc-Dali-TextEditor.cpp b/automated-tests/src/dali-toolkit/utc-Dali-TextEditor.cpp index 7a3ce4c..49e630d 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-TextEditor.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-TextEditor.cpp @@ -2172,6 +2172,54 @@ int utcDaliTextEditorEvent07(void) //text is "c" DALI_TEST_EQUALS( "c", editor.GetProperty( TextEditor::Property::TEXT ), TEST_LOCATION ); + // select all text + DevelTextEditor::SelectWholeText(editor); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Copy the selected text using logical keys + application.ProcessEvent( GenerateKey( "", "", "", Dali::DevelKey::DALI_KEY_CONTROL_LEFT, 0, 0, Integration::KeyEvent::DOWN, "", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE ) ); + application.ProcessEvent( GenerateKey( "ؤ", "c", "ؤ", KEY_C_CODE, KEY_CONTROL_MODIFIER, 0, Integration::KeyEvent::DOWN, "c", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE ) ); + + // Render and notify + application.SendNotification(); + application.Render(); + + // select none + DevelTextEditor::SelectNone(editor); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Paste the selected using logical keys + application.ProcessEvent( GenerateKey( "", "", "", Dali::DevelKey::DALI_KEY_CONTROL_LEFT, 0, 0, Integration::KeyEvent::DOWN, "", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE ) ); + application.ProcessEvent( GenerateKey( "ر", "v", "ر", KEY_V_CODE, KEY_CONTROL_MODIFIER, 0, Integration::KeyEvent::DOWN, "v", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE ) ); + + //text is "cc" + DALI_TEST_EQUALS( "cc", editor.GetProperty( TextEditor::Property::TEXT ), TEST_LOCATION ); + + // select all using logical keys + application.ProcessEvent( GenerateKey( "", "", "", Dali::DevelKey::DALI_KEY_CONTROL_LEFT, 0, 0, Integration::KeyEvent::DOWN, "", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE ) ); + application.ProcessEvent( GenerateKey( "ش", "a", "ش", KEY_A_CODE, KEY_CONTROL_MODIFIER, 0, Integration::KeyEvent::DOWN, "a", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE ) ); + + // Render and notify + application.SendNotification(); + application.Render(); + + // cut text using logical keys + application.ProcessEvent( GenerateKey( "", "", "", Dali::DevelKey::DALI_KEY_CONTROL_LEFT, 0, 0, Integration::KeyEvent::DOWN, "", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE ) ); + application.ProcessEvent( GenerateKey( "ء", "x", "ء", KEY_X_CODE, KEY_CONTROL_MODIFIER, 0, Integration::KeyEvent::DOWN, "x", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE ) ); + + // Render and notify + application.SendNotification(); + application.Render(); + + //text is "" + DALI_TEST_EQUALS( "", editor.GetProperty( TextEditor::Property::TEXT ), TEST_LOCATION ); + END_TEST; } @@ -3036,3 +3084,50 @@ int UtcDaliTextEditorEnableEditing(void) END_TEST; } + +int UtcDaliTextEditorScrolling(void) +{ + ToolkitTestApplication application; + tet_infoline(" UtcDaliTextEditorScrolling "); + + TextEditor textEditor = TextEditor::New(); + DALI_TEST_CHECK( textEditor ); + + application.GetScene().Add( textEditor ); + + // Avoid a crash when core load gl resources. + application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE ); + + application.SendNotification(); + application.Render(); + + textEditor.SetProperty(TextEditor::Property::TEXT, "Tex1\nTex2\nTex3\nTex4\nTex5\nTex6\nTex7\nTex8"); + textEditor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_CENTER); + textEditor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_CENTER); + textEditor.SetProperty(Actor::Property::SIZE, Vector2(60.0f, 160.0f)); + + application.SendNotification(); + application.Render(); + + DALI_TEST_EQUALS( textEditor.GetProperty( DevelTextEditor::Property::VERTICAL_SCROLL_POSITION ).Get(), 0.0f, TEST_LOCATION ); + DALI_TEST_EQUALS( textEditor.GetProperty( DevelTextEditor::Property::HORIZONTAL_SCROLL_POSITION ).Get(), 0.0f, TEST_LOCATION ); + + + DevelTextEditor::ScrollBy(textEditor, Vector2(1.0f, 1.0f)); + + DALI_TEST_EQUALS( textEditor.GetProperty( DevelTextEditor::Property::VERTICAL_SCROLL_POSITION ).Get(), 1.0f, TEST_LOCATION ); + DALI_TEST_EQUALS( textEditor.GetProperty( DevelTextEditor::Property::HORIZONTAL_SCROLL_POSITION ).Get(), 0.0f, TEST_LOCATION ); + + DevelTextEditor::ScrollBy(textEditor, Vector2(0.0f, 1000.0f)); + + DALI_TEST_NOT_EQUALS( textEditor.GetProperty( DevelTextEditor::Property::VERTICAL_SCROLL_POSITION ).Get(), 1.0f, 0.1f, TEST_LOCATION ); + DALI_TEST_EQUALS( textEditor.GetProperty( DevelTextEditor::Property::HORIZONTAL_SCROLL_POSITION ).Get(), 0.0f, TEST_LOCATION ); + + textEditor.SetProperty(DevelTextEditor::Property::VERTICAL_SCROLL_POSITION , 0.0f); + textEditor.SetProperty(DevelTextEditor::Property::HORIZONTAL_SCROLL_POSITION , 0.0f); + + DALI_TEST_EQUALS( textEditor.GetProperty( DevelTextEditor::Property::VERTICAL_SCROLL_POSITION ).Get(), 0.0f, TEST_LOCATION ); + DALI_TEST_EQUALS( textEditor.GetProperty( DevelTextEditor::Property::HORIZONTAL_SCROLL_POSITION ).Get(), 0.0f, TEST_LOCATION ); + + END_TEST; +} diff --git a/dali-toolkit/devel-api/controls/text-controls/text-editor-devel.cpp b/dali-toolkit/devel-api/controls/text-controls/text-editor-devel.cpp index adcff4c..abe3389 100644 --- a/dali-toolkit/devel-api/controls/text-controls/text-editor-devel.cpp +++ b/dali-toolkit/devel-api/controls/text-controls/text-editor-devel.cpp @@ -45,6 +45,11 @@ void SelectNone(TextEditor textEditor) GetImpl(textEditor).SelectNone(); } +void ScrollBy(TextEditor textEditor, Vector2 scroll) +{ + GetImpl(textEditor).ScrollBy(scroll); +} + } // namespace DevelTextEditor } // namespace Toolkit diff --git a/dali-toolkit/devel-api/controls/text-controls/text-editor-devel.h b/dali-toolkit/devel-api/controls/text-controls/text-editor-devel.h index 0db66e5..6cb473c 100644 --- a/dali-toolkit/devel-api/controls/text-controls/text-editor-devel.h +++ b/dali-toolkit/devel-api/controls/text-controls/text-editor-devel.h @@ -140,6 +140,18 @@ enum Type SELECTED_TEXT_END, /** + * @brief The horizontal scroll position in pixels. + * @details Name "horizontalScrollPosition", type Property::FLOAT. + */ + HORIZONTAL_SCROLL_POSITION, + + /** + * @brief The vertical scroll position in pixels. + * @details Name "verticalScrollPosition", type Property::FLOAT. + */ + VERTICAL_SCROLL_POSITION, + + /** * @brief The Editable state of control. * @details Name "enableEditing", type Property::BOOLEAN. */ @@ -194,6 +206,14 @@ DALI_TOOLKIT_API void SelectWholeText(TextEditor textEditor); */ DALI_TOOLKIT_API void SelectNone(TextEditor textEditor); +/** + * @brief Scroll the TextEditor by specific amount. + * + * @param[in] textEditor The instance of TextEditor. + * @param[in] scroll amount (in pixels) of scrolling in horizontal & vectical directions. + */ +DALI_TOOLKIT_API void ScrollBy(TextEditor textEditor, Vector2 scroll); + } // namespace DevelTextEditor } // namespace Toolkit diff --git a/dali-toolkit/internal/controls/text-controls/text-editor-impl.cpp b/dali-toolkit/internal/controls/text-controls/text-editor-impl.cpp index 4650a6d..dc82c36 100644 --- a/dali-toolkit/internal/controls/text-controls/text-editor-impl.cpp +++ b/dali-toolkit/internal/controls/text-controls/text-editor-impl.cpp @@ -143,6 +143,8 @@ DALI_DEVEL_PROPERTY_REGISTRATION( Toolkit, TextEditor, "renderingBackend", DALI_DEVEL_PROPERTY_REGISTRATION( Toolkit, TextEditor, "maxLength", INTEGER, MAX_LENGTH ) DALI_DEVEL_PROPERTY_REGISTRATION( Toolkit, TextEditor, "selectedTextStart", INTEGER, SELECTED_TEXT_START ) DALI_DEVEL_PROPERTY_REGISTRATION( Toolkit, TextEditor, "selectedTextEnd", INTEGER, SELECTED_TEXT_END ) +DALI_DEVEL_PROPERTY_REGISTRATION( Toolkit, TextEditor, "horizontalScrollPosition", FLOAT, HORIZONTAL_SCROLL_POSITION ) +DALI_DEVEL_PROPERTY_REGISTRATION( Toolkit, TextEditor, "verticalScrollPosition", INTEGER, VERTICAL_SCROLL_POSITION ) DALI_DEVEL_PROPERTY_REGISTRATION( Toolkit, TextEditor, "enableEditing", BOOLEAN, ENABLE_EDITING ) DALI_DEVEL_PROPERTY_REGISTRATION_READ_ONLY( Toolkit, TextEditor, "selectedText", STRING, SELECTED_TEXT ) @@ -722,6 +724,26 @@ void TextEditor::SetProperty( BaseObject* object, Property::Index index, const P impl.SetEditable( editable ); break; } + case Toolkit::DevelTextEditor::Property::HORIZONTAL_SCROLL_POSITION: + { + float horizontalScroll = value.Get< float >(); + DALI_LOG_INFO( gLogFilter, Debug::General, "TextEditor %p HORIZONTAL_SCROLL_POSITION %d\n", impl.mController.Get(), horizontalScroll ); + if (horizontalScroll >= 0.0f) + { + impl.ScrollBy( Vector2(horizontalScroll - impl.GetHorizontalScrollPosition(), 0 )); + } + break; + } + case Toolkit::DevelTextEditor::Property::VERTICAL_SCROLL_POSITION: + { + float verticalScroll = value.Get< float >(); + DALI_LOG_INFO( gLogFilter, Debug::General, "TextEditor %p VERTICAL_SCROLL_POSITION %d\n", impl.mController.Get(), verticalScroll ); + if (verticalScroll >= 0.0f) + { + impl.ScrollBy( Vector2(0, verticalScroll - impl.GetVerticalScrollPosition() )); + } + break; + } } // switch } // texteditor } @@ -1058,6 +1080,16 @@ Property::Value TextEditor::GetProperty( BaseObject* object, Property::Index ind value = impl.IsEditable(); break; } + case Toolkit::DevelTextEditor::Property::HORIZONTAL_SCROLL_POSITION: + { + value = impl.GetHorizontalScrollPosition(); + break; + } + case Toolkit::DevelTextEditor::Property::VERTICAL_SCROLL_POSITION: + { + value = impl.GetVerticalScrollPosition(); + break; + } } //switch } @@ -1081,6 +1113,32 @@ void TextEditor::SelectNone() } } +void TextEditor::ScrollBy(Vector2 scroll) +{ + if( mController && mController->IsShowingRealText() ) + { + mController->ScrollBy(scroll); + } +} + +float TextEditor::GetHorizontalScrollPosition() +{ + if( mController && mController->IsShowingRealText() ) + { + return mController->GetHorizontalScrollPosition(); + } + return 0; +} + +float TextEditor::GetVerticalScrollPosition() +{ + if( mController && mController->IsShowingRealText() ) + { + return mController->GetVerticalScrollPosition(); + } + return 0; +} + string TextEditor::GetSelectedText() const { string selectedText = ""; diff --git a/dali-toolkit/internal/controls/text-controls/text-editor-impl.h b/dali-toolkit/internal/controls/text-controls/text-editor-impl.h index 5d0df97..c2385a2 100755 --- a/dali-toolkit/internal/controls/text-controls/text-editor-impl.h +++ b/dali-toolkit/internal/controls/text-controls/text-editor-impl.h @@ -248,6 +248,25 @@ public: void SelectNone() override; /** + * @copydoc Dali::Toolkit::DevelTextEditor::ScrollBy() + */ + void ScrollBy(Vector2 Scroll); + + /** + * @brief Get Horizontal scroll position of TextEditor. + * + * @return Horizontal scroll position (in pixels) of TextEditor. + */ + float GetHorizontalScrollPosition(); + + /** + * @brief Get Vertical scroll position of TextEditor. + * + * @return Vertical scroll position (in pixels) of TextEditor. + */ + float GetVerticalScrollPosition(); + + /** * @copydoc Text::SelectableControlInterface::GetSelectedText() */ string GetSelectedText() const override; diff --git a/dali-toolkit/internal/text/text-controller-event-handler.cpp b/dali-toolkit/internal/text/text-controller-event-handler.cpp index b9b260b..89ff0f9 100644 --- a/dali-toolkit/internal/text/text-controller-event-handler.cpp +++ b/dali-toolkit/internal/text/text-controller-event-handler.cpp @@ -109,6 +109,9 @@ bool Controller::EventHandler::KeyEvent(Controller& controller, const Dali::KeyE int keyCode = keyEvent.GetKeyCode(); const std::string& keyString = keyEvent.GetKeyString(); const std::string keyName = keyEvent.GetKeyName(); + // Key will produce same logical-key value when ctrl + // is down, regardless of language layout + const std::string logicalKey = keyEvent.GetLogicalKey(); const bool isNullKey = ( 0 == keyCode ) && ( keyString.empty() ); @@ -182,25 +185,25 @@ bool Controller::EventHandler::KeyEvent(Controller& controller, const Dali::KeyE else if ( keyEvent.IsCtrlModifier() && !keyEvent.IsShiftModifier()) { bool consumed = false; - if (keyName == KEY_C_NAME || keyName == KEY_INSERT_NAME) + if (keyName == KEY_C_NAME || keyName == KEY_INSERT_NAME || logicalKey == KEY_C_NAME || logicalKey == KEY_INSERT_NAME) { // Ctrl-C or Ctrl+Insert to copy the selected text controller.TextPopupButtonTouched( Toolkit::TextSelectionPopup::COPY ); consumed = true; } - else if (keyName == KEY_V_NAME) + else if (keyName == KEY_V_NAME || logicalKey == KEY_V_NAME) { // Ctrl-V to paste the copied text controller.TextPopupButtonTouched( Toolkit::TextSelectionPopup::PASTE ); consumed = true; } - else if (keyName == KEY_X_NAME) + else if (keyName == KEY_X_NAME || logicalKey == KEY_X_NAME) { // Ctrl-X to cut the selected text controller.TextPopupButtonTouched( Toolkit::TextSelectionPopup::CUT ); consumed = true; } - else if (keyName == KEY_A_NAME) + else if (keyName == KEY_A_NAME || logicalKey == KEY_A_NAME) { // Ctrl-A to select All the text controller.TextPopupButtonTouched( Toolkit::TextSelectionPopup::SELECT_ALL ); diff --git a/dali-toolkit/internal/text/text-controller.cpp b/dali-toolkit/internal/text/text-controller.cpp index 3035062..aed8d32 100644 --- a/dali-toolkit/internal/text/text-controller.cpp +++ b/dali-toolkit/internal/text/text-controller.cpp @@ -2264,6 +2264,56 @@ void Controller::SetEditable( bool editable ) } } +void Controller::ScrollBy( Vector2 scroll ) +{ + if( mImpl->mEventData && (fabs(scroll.x) > Math::MACHINE_EPSILON_0 || fabs(scroll.y) > Math::MACHINE_EPSILON_0)) + { + const Vector2& layoutSize = mImpl->mModel->mVisualModel->GetLayoutSize(); + const Vector2 currentScroll = mImpl->mModel->mScrollPosition; + + scroll.x = -scroll.x; + scroll.y = -scroll.y; + + if( fabs(scroll.x) > Math::MACHINE_EPSILON_0 ) + { + mImpl->mModel->mScrollPosition.x += scroll.x; + mImpl->ClampHorizontalScroll( layoutSize ); + } + + if( fabs(scroll.y) > Math::MACHINE_EPSILON_0 ) + { + mImpl->mModel->mScrollPosition.y += scroll.y; + mImpl->ClampVerticalScroll( layoutSize ); + } + + if (mImpl->mModel->mScrollPosition != currentScroll) + { + mImpl->mEventData->mDecorator->UpdatePositions( mImpl->mModel->mScrollPosition - currentScroll ); + mImpl->RequestRelayout(); + } + } +} + +float Controller::GetHorizontalScrollPosition() +{ + if( mImpl->mEventData ) + { + //scroll values are negative internally so we convert them to positive numbers + return -mImpl->mModel->mScrollPosition.x; + } + return 0; +} + +float Controller::GetVerticalScrollPosition() +{ + if( mImpl->mEventData ) + { + //scroll values are negative internally so we convert them to positive numbers + return -mImpl->mModel->mScrollPosition.y; + } + return 0; +} + void Controller::DecorationEvent( HandleType handleType, HandleState state, float x, float y ) { EventHandler::DecorationEvent(*this, handleType, state, x, y); diff --git a/dali-toolkit/internal/text/text-controller.h b/dali-toolkit/internal/text/text-controller.h index f600f84..d627324 100644 --- a/dali-toolkit/internal/text/text-controller.h +++ b/dali-toolkit/internal/text/text-controller.h @@ -1563,6 +1563,21 @@ public: // Text-input Event Queuing. virtual void SetEditable( bool editable ); /** + * @copydoc Dali::Toolkit::Internal::TextEditor::ScrollBy() + */ + virtual void ScrollBy( Vector2 scroll ); + + /** + * @copydoc Dali::Toolkit::Internal::TextEditor::GetHorizontalScrollPosition() + */ + float GetHorizontalScrollPosition(); + + /** + * @copydoc Dali::Toolkit::Internal::TextEditor::GetVerticalScrollPosition() + */ + float GetVerticalScrollPosition(); + + /** * @brief Event received from input method context * * @param[in] inputMethodContext The input method context. 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 ea097e1..fead0e6 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 @@ -94,25 +94,41 @@ AnimatedVectorImageVisual::AnimatedVectorImageVisual( VisualFactoryCache& factor mPlacementActor(), mPlayState( DevelImageVisual::PlayState::STOPPED ), mEventCallback( nullptr ), - mRendererAdded( false ) + mRendererAdded( false ), + mCoreShutdown(false) { // the rasterized image is with pre-multiplied alpha format mImpl->mFlags |= Impl::IS_PREMULTIPLIED_ALPHA; mVectorAnimationTask->UploadCompletedSignal().Connect( this, &AnimatedVectorImageVisual::OnUploadCompleted ); mVectorAnimationTask->SetAnimationFinishedCallback( new EventThreadCallback( MakeCallback( this, &AnimatedVectorImageVisual::OnAnimationFinished ) ) ); + + auto& vectorAnimationManager = mFactoryCache.GetVectorAnimationManager(); + vectorAnimationManager.AddObserver(*this); } AnimatedVectorImageVisual::~AnimatedVectorImageVisual() { - if( mEventCallback ) + if( ! mCoreShutdown ) { - mFactoryCache.GetVectorAnimationManager().UnregisterEventCallback( mEventCallback ); + auto& vectorAnimationManager = mFactoryCache.GetVectorAnimationManager(); + vectorAnimationManager.RemoveObserver(*this); + + if( mEventCallback ) + { + mFactoryCache.GetVectorAnimationManager().UnregisterEventCallback( mEventCallback ); + } + + // Finalize animation task and disconnect the signal in the main thread + mVectorAnimationTask->UploadCompletedSignal().Disconnect( this, &AnimatedVectorImageVisual::OnUploadCompleted ); + mVectorAnimationTask->Finalize(); } +} - // Finalize animation task and disconnect the signal in the main thread - mVectorAnimationTask->UploadCompletedSignal().Disconnect( this, &AnimatedVectorImageVisual::OnUploadCompleted ); - mVectorAnimationTask->Finalize(); +void AnimatedVectorImageVisual::VectorAnimationManagerDestroyed() +{ + // Core is shutting down. Don't talk to the plugin any more. + mCoreShutdown = true; } void AnimatedVectorImageVisual::GetNaturalSize( Vector2& naturalSize ) @@ -500,10 +516,11 @@ void AnimatedVectorImageVisual::StopAnimation() void AnimatedVectorImageVisual::TriggerVectorRasterization() { - if( !mEventCallback ) + if( !mEventCallback && !mCoreShutdown ) { mEventCallback = MakeCallback( this, &AnimatedVectorImageVisual::OnProcessEvents ); - mFactoryCache.GetVectorAnimationManager().RegisterEventCallback( mEventCallback ); + auto& vectorAnimationManager = mFactoryCache.GetVectorAnimationManager(); + vectorAnimationManager.RegisterEventCallback( mEventCallback ); Stage::GetCurrent().KeepRendering( 0.0f ); // Trigger event processing } } 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 e09527a..6196e39 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 @@ -30,6 +30,7 @@ #include #include #include +#include namespace Dali { @@ -55,7 +56,7 @@ using AnimatedVectorImageVisualPtr = IntrusivePtr< AnimatedVectorImageVisual >; * | url | STRING | * */ -class AnimatedVectorImageVisual: public Visual::Base, public ConnectionTracker +class AnimatedVectorImageVisual: public Visual::Base, public ConnectionTracker, public VectorAnimationManager::LifecycleObserver { public: @@ -97,6 +98,12 @@ public: // from Visual */ void DoCreateInstancePropertyMap( Property::Map& map ) const override; +protected: // From VectorAnimationManager::LifecycleObserver: + /** + * @copydoc VectorAnimationManager::LifecycleObserver::VectorAnimationManagerDestroyed() + */ + void VectorAnimationManagerDestroyed() override; + protected: /** @@ -221,6 +228,7 @@ private: DevelImageVisual::PlayState::Type mPlayState; CallbackBase* mEventCallback; // Not owned bool mRendererAdded; + bool mCoreShutdown; }; } // namespace Internal diff --git a/dali-toolkit/internal/visuals/animated-vector-image/vector-animation-manager.cpp b/dali-toolkit/internal/visuals/animated-vector-image/vector-animation-manager.cpp index 8e47d81..ad56227 100644 --- a/dali-toolkit/internal/visuals/animated-vector-image/vector-animation-manager.cpp +++ b/dali-toolkit/internal/visuals/animated-vector-image/vector-animation-manager.cpp @@ -45,6 +45,7 @@ Debug::Filter* gVectorAnimationLogFilter = Debug::Filter::New( Debug::NoLogging, VectorAnimationManager::VectorAnimationManager() : mEventCallbacks(), + mLifecycleObservers(), mVectorAnimationThread( nullptr ), mProcessorRegistered( false ) { @@ -62,6 +63,26 @@ VectorAnimationManager::~VectorAnimationManager() { Adaptor::Get().UnregisterProcessor( *this ); } + + for( auto observer : mLifecycleObservers ) + { + observer->VectorAnimationManagerDestroyed(); + } +} + +void VectorAnimationManager::AddObserver( VectorAnimationManager::LifecycleObserver& observer ) +{ + DALI_ASSERT_DEBUG( mLifecycleObservers.end() == std::find( mLifecycleObservers.begin(), mLifecycleObservers.end(), &observer)); + mLifecycleObservers.push_back( &observer ); +} + +void VectorAnimationManager::RemoveObserver( VectorAnimationManager::LifecycleObserver& observer) +{ + auto iterator=std::find(mLifecycleObservers.begin(), mLifecycleObservers.end(), &observer); + if( iterator != mLifecycleObservers.end() ) + { + mLifecycleObservers.erase(iterator); + } } VectorAnimationThread& VectorAnimationManager::GetVectorAnimationThread() diff --git a/dali-toolkit/internal/visuals/animated-vector-image/vector-animation-manager.h b/dali-toolkit/internal/visuals/animated-vector-image/vector-animation-manager.h index 510c07e..7fbc3ca 100644 --- a/dali-toolkit/internal/visuals/animated-vector-image/vector-animation-manager.h +++ b/dali-toolkit/internal/visuals/animated-vector-image/vector-animation-manager.h @@ -43,6 +43,10 @@ class VectorAnimationThread; class VectorAnimationManager: public Integration::Processor { public: + struct LifecycleObserver + { + virtual void VectorAnimationManagerDestroyed() = 0; + }; /** * @brief Constructor. @@ -55,6 +59,18 @@ public: ~VectorAnimationManager() override; /** + * Add a lifecycle observer + * @param[in] observer The object watching this one + */ + void AddObserver( LifecycleObserver& observer ); + + /** + * Remove a lifecycle observer + * @param[in] observer The object watching this one + */ + void RemoveObserver( LifecycleObserver& observer ); + + /** * Get the vector animation thread. * @return A raw pointer pointing to the vector animation thread. */ @@ -93,6 +109,7 @@ private: private: std::vector< CallbackBase* > mEventCallbacks; + std::vector mLifecycleObservers; std::unique_ptr< VectorAnimationThread > mVectorAnimationThread; bool mProcessorRegistered; };