Merge "Implement CameraView." into devel/master
authorjoogab yun <joogab.yun@samsung.com>
Mon, 22 Mar 2021 05:09:27 +0000 (05:09 +0000)
committerGerrit Code Review <gerrit@review>
Mon, 22 Mar 2021 05:09:27 +0000 (05:09 +0000)
14 files changed:
automated-tests/src/dali-toolkit/utc-Dali-AnimatedImageVisual.cpp
automated-tests/src/dali-toolkit/utc-Dali-TextEditor.cpp
automated-tests/src/dali-toolkit/utc-Dali-TextField.cpp
dali-toolkit/devel-api/controls/accessible-impl.cpp
dali-toolkit/devel-api/controls/accessible-impl.h
dali-toolkit/internal/accessibility-manager/accessibility-manager-impl.cpp
dali-toolkit/internal/controls/text-controls/text-editor-impl.cpp
dali-toolkit/internal/controls/text-controls/text-editor-impl.h
dali-toolkit/internal/controls/text-controls/text-field-impl.cpp
dali-toolkit/internal/controls/text-controls/text-field-impl.h
dali-toolkit/internal/visuals/animated-image/animated-image-visual.cpp
dali-toolkit/internal/visuals/animated-image/animated-image-visual.h
dali-toolkit/public-api/dali-toolkit-version.cpp
packaging/dali-toolkit.spec

index 243a73b..c77b4ac 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2021 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.
@@ -293,6 +293,52 @@ int UtcDaliAnimatedImageVisualGetPropertyMap04(void)
   END_TEST;
 }
 
+int UtcDaliAnimatedImageVisualImageLoadingFail01(void)
+{
+  ToolkitTestApplication application;
+  TestGlAbstraction& gl = application.GetGlAbstraction();
+
+  {
+    Property::Map propertyMap;
+    propertyMap.Insert( Visual::Property::TYPE, Visual::ANIMATED_IMAGE );
+    propertyMap.Insert( ImageVisual::Property::URL, "dummy.gif" );
+    propertyMap.Insert( ImageVisual::Property::BATCH_SIZE, 2 );
+    propertyMap.Insert( ImageVisual::Property::CACHE_SIZE, 2 );
+    propertyMap.Insert( ImageVisual::Property::FRAME_DELAY, 20 );
+    propertyMap.Insert( ImageVisual::Property::SYNCHRONOUS_LOADING, true );
+    propertyMap.Insert( DevelVisual::Property::CORNER_RADIUS, 0.23f );
+    propertyMap.Insert( DevelVisual::Property::CORNER_RADIUS_POLICY, Visual::Transform::Policy::ABSOLUTE );
+
+    VisualFactory factory = VisualFactory::Get();
+    Visual::Base visual = factory.CreateVisual( propertyMap );
+
+    DummyControl dummyControl = DummyControl::New(true);
+    Impl::DummyControl& dummyImpl = static_cast<Impl::DummyControl&>(dummyControl.GetImplementation());
+    dummyImpl.RegisterVisual( DummyControl::Property::TEST_VISUAL, visual );
+
+    dummyControl.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS );
+    application.GetScene().Add( dummyControl );
+
+    TraceCallStack& textureTrace = gl.GetTextureTrace();
+    textureTrace.Enable(true);
+
+    application.SendNotification();
+    application.Render(20);
+
+    DALI_TEST_EQUALS( gl.GetNumGeneratedTextures(), 1, TEST_LOCATION );
+
+    DevelControl::DoAction( dummyControl, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedImageVisual::Action::JUMP_TO, 6 );
+
+    application.SendNotification();
+    application.Render(20);
+
+    DALI_TEST_EQUALS( gl.GetNumGeneratedTextures(), 1, TEST_LOCATION );
+
+    dummyControl.Unparent();
+  }
+
+  END_TEST;
+}
 
 int UtcDaliAnimatedImageVisualSynchronousLoading(void)
 {
index d5a243c..06d3307 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2021 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.
@@ -964,33 +964,113 @@ int utcDaliTextEditorTextChangedP(void)
 
   gTextChangedCallBackCalled = false;
   editor.SetProperty( TextEditor::Property::TEXT, "ABC" );
+  application.SendNotification();
+  application.Render();
   DALI_TEST_CHECK( gTextChangedCallBackCalled );
   DALI_TEST_CHECK( textChangedSignal );
 
-  application.SendNotification();
-
   editor.SetKeyInputFocus();
 
   gTextChangedCallBackCalled = false;
   application.ProcessEvent( GenerateKey( "D", "", "D", KEY_D_CODE, 0, 0, Integration::KeyEvent::DOWN, "D", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE ) );
+  application.SendNotification();
+  application.Render();
   DALI_TEST_CHECK( gTextChangedCallBackCalled );
 
   // Remove all text
   editor.SetProperty( TextField::Property::TEXT, "" );
+  application.SendNotification();
+  application.Render();
 
   // Pressing backspace key: TextChangedCallback should not be called when there is no text in texteditor.
   gTextChangedCallBackCalled = false;
   application.ProcessEvent( GenerateKey( "", "", "", DALI_KEY_BACKSPACE, 0, 0, Integration::KeyEvent::DOWN, "", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE ) );
+  application.SendNotification();
+  application.Render();
   DALI_TEST_CHECK( !gTextChangedCallBackCalled );
 
   // Pressing delete key: TextChangedCallback should not be called when there is no text in texteditor.
   gTextChangedCallBackCalled = false;
   application.ProcessEvent( GenerateKey( "", "", "", Dali::DevelKey::DALI_KEY_DELETE, 0, 0, Integration::KeyEvent::DOWN, "Delete", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE ) );
+  application.SendNotification();
+  application.Render();
   DALI_TEST_CHECK( !gTextChangedCallBackCalled );
 
   END_TEST;
 }
 
+int utcDaliTextEditorTextChangedWithInputMethodContext(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" utcDaliTextEditorTextChangedWithInputMethodContext");
+  TextEditor editor = TextEditor::New();
+  DALI_TEST_CHECK( editor );
+
+
+  application.GetScene().Add( editor );
+
+  // connect to the text changed signal.
+  ConnectionTracker* testTracker = new ConnectionTracker();
+  editor.TextChangedSignal().Connect(&TestTextChangedCallback);
+  bool textChangedSignal = false;
+  editor.ConnectSignal( testTracker, "textChanged",   CallbackFunctor(&textChangedSignal) );
+
+
+  // get InputMethodContext
+  std::string text;
+  InputMethodContext::EventData imfEvent;
+  InputMethodContext inputMethodContext = DevelTextEditor::GetInputMethodContext( editor );
+
+  editor.SetKeyInputFocus();
+  editor.SetProperty( DevelTextEditor::Property::ENABLE_EDITING, true );
+
+  // input text
+  gTextChangedCallBackCalled = false;
+  imfEvent = InputMethodContext::EventData( InputMethodContext::PRE_EDIT, "ㅎ", 0, 1 );
+  inputMethodContext.EventReceivedSignal().Emit(inputMethodContext, imfEvent);
+  application.SendNotification();
+  application.Render();
+  DALI_TEST_CHECK( gTextChangedCallBackCalled );
+  DALI_TEST_EQUALS( editor.GetProperty<std::string>( TextEditor::Property::TEXT ), std::string("ㅎ"), TEST_LOCATION );
+
+  gTextChangedCallBackCalled = false;
+  imfEvent = InputMethodContext::EventData( InputMethodContext::PRE_EDIT, "호", 0, 1 );
+  inputMethodContext.EventReceivedSignal().Emit(inputMethodContext, imfEvent);
+  application.SendNotification();
+  application.Render();
+  DALI_TEST_CHECK( gTextChangedCallBackCalled );
+  DALI_TEST_EQUALS( editor.GetProperty<std::string>( TextEditor::Property::TEXT ), std::string("호"), TEST_LOCATION );
+
+  gTextChangedCallBackCalled = false;
+  imfEvent = InputMethodContext::EventData( InputMethodContext::PRE_EDIT, "혿", 0, 1 );
+  inputMethodContext.EventReceivedSignal().Emit(inputMethodContext, imfEvent);
+  application.SendNotification();
+  application.Render();
+  DALI_TEST_CHECK( gTextChangedCallBackCalled );
+  DALI_TEST_EQUALS( editor.GetProperty<std::string>( TextEditor::Property::TEXT ), std::string("혿"), TEST_LOCATION );
+
+  gTextChangedCallBackCalled = false;
+  imfEvent = InputMethodContext::EventData( InputMethodContext::PRE_EDIT, "", 0, 1 );
+  inputMethodContext.EventReceivedSignal().Emit(inputMethodContext, imfEvent);
+  DALI_TEST_CHECK( !gTextChangedCallBackCalled );
+
+  imfEvent = InputMethodContext::EventData( InputMethodContext::COMMIT, "호", 0, 1 );
+  inputMethodContext.EventReceivedSignal().Emit(inputMethodContext, imfEvent);
+  DALI_TEST_CHECK( !gTextChangedCallBackCalled );
+
+  imfEvent = InputMethodContext::EventData( InputMethodContext::PRE_EDIT, "두", 1, 2 );
+  inputMethodContext.EventReceivedSignal().Emit(inputMethodContext, imfEvent);
+  DALI_TEST_CHECK( !gTextChangedCallBackCalled );
+
+  application.SendNotification();
+  application.Render();
+  DALI_TEST_CHECK( gTextChangedCallBackCalled );
+  DALI_TEST_EQUALS( editor.GetProperty<std::string>( TextEditor::Property::TEXT ), std::string("호두"), TEST_LOCATION );
+
+  END_TEST;
+}
+
+
 int utcDaliTextEditorInputStyleChanged01(void)
 {
   // The text-editor emits signals when the input style changes. These changes of style are
index b535059..0795816 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2021 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.
@@ -1034,33 +1034,113 @@ int utcDaliTextFieldTextChangedP(void)
 
   gTextChangedCallBackCalled = false;
   field.SetProperty( TextField::Property::TEXT, "ABC" );
+  application.SendNotification();
+  application.Render();
   DALI_TEST_CHECK( gTextChangedCallBackCalled );
   DALI_TEST_CHECK( textChangedSignal );
 
-  application.SendNotification();
-
   field.SetKeyInputFocus();
 
   gTextChangedCallBackCalled = false;
   application.ProcessEvent( GenerateKey( "D", "", "D", KEY_D_CODE, 0, 0, Integration::KeyEvent::DOWN, "D", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE ) );
+  application.SendNotification();
+  application.Render();
   DALI_TEST_CHECK( gTextChangedCallBackCalled );
 
   // Remove all text
   field.SetProperty( TextField::Property::TEXT, "" );
+  application.SendNotification();
+  application.Render();
 
   // Pressing backspace key: TextChangedCallback should not be called when there is no text in textfield.
   gTextChangedCallBackCalled = false;
   application.ProcessEvent( GenerateKey( "", "", "", DALI_KEY_BACKSPACE, 0, 0, Integration::KeyEvent::DOWN, "", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE ) );
+  application.SendNotification();
+  application.Render();
   DALI_TEST_CHECK( !gTextChangedCallBackCalled );
 
   // Pressing delete key: TextChangedCallback should not be called when there is no text in textfield.
   gTextChangedCallBackCalled = false;
   application.ProcessEvent( GenerateKey( "", "", "", Dali::DevelKey::DALI_KEY_DELETE, 0, 0, Integration::KeyEvent::DOWN, "Delete", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE ) );
+  application.SendNotification();
+  application.Render();
+  DALI_TEST_CHECK( !gTextChangedCallBackCalled );
+
+  END_TEST;
+}
+
+int utcDaliTextFieldTextChangedWithInputMethodContext(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" utcDaliTextFieldTextChangedWithInputMethodContext");
+  TextField field = TextField::New();
+  DALI_TEST_CHECK( field );
+
+
+  application.GetScene().Add( field );
+
+  // connect to the text changed signal.
+  ConnectionTracker* testTracker = new ConnectionTracker();
+  field.TextChangedSignal().Connect(&TestTextChangedCallback);
+  bool textChangedSignal = false;
+  field.ConnectSignal( testTracker, "textChanged",   CallbackFunctor(&textChangedSignal) );
+
+
+  // get InputMethodContext
+  std::string text;
+  InputMethodContext::EventData imfEvent;
+  InputMethodContext inputMethodContext = DevelTextField::GetInputMethodContext( field );
+
+  field.SetKeyInputFocus();
+  field.SetProperty( DevelTextField::Property::ENABLE_EDITING, true );
+
+  // input text
+  gTextChangedCallBackCalled = false;
+  imfEvent = InputMethodContext::EventData( InputMethodContext::PRE_EDIT, "ㅎ", 0, 1 );
+  inputMethodContext.EventReceivedSignal().Emit(inputMethodContext, imfEvent);
+  application.SendNotification();
+  application.Render();
+  DALI_TEST_CHECK( gTextChangedCallBackCalled );
+  DALI_TEST_EQUALS( field.GetProperty<std::string>( TextField::Property::TEXT ), std::string("ㅎ"), TEST_LOCATION );
+
+  gTextChangedCallBackCalled = false;
+  imfEvent = InputMethodContext::EventData( InputMethodContext::PRE_EDIT, "호", 0, 1 );
+  inputMethodContext.EventReceivedSignal().Emit(inputMethodContext, imfEvent);
+  application.SendNotification();
+  application.Render();
+  DALI_TEST_CHECK( gTextChangedCallBackCalled );
+  DALI_TEST_EQUALS( field.GetProperty<std::string>( TextField::Property::TEXT ), std::string("호"), TEST_LOCATION );
+
+  gTextChangedCallBackCalled = false;
+  imfEvent = InputMethodContext::EventData( InputMethodContext::PRE_EDIT, "혿", 0, 1 );
+  inputMethodContext.EventReceivedSignal().Emit(inputMethodContext, imfEvent);
+  application.SendNotification();
+  application.Render();
+  DALI_TEST_CHECK( gTextChangedCallBackCalled );
+  DALI_TEST_EQUALS( field.GetProperty<std::string>( TextField::Property::TEXT ), std::string("혿"), TEST_LOCATION );
+
+  gTextChangedCallBackCalled = false;
+  imfEvent = InputMethodContext::EventData( InputMethodContext::PRE_EDIT, "", 0, 1 );
+  inputMethodContext.EventReceivedSignal().Emit(inputMethodContext, imfEvent);
+  DALI_TEST_CHECK( !gTextChangedCallBackCalled );
+
+  imfEvent = InputMethodContext::EventData( InputMethodContext::COMMIT, "호", 0, 1 );
+  inputMethodContext.EventReceivedSignal().Emit(inputMethodContext, imfEvent);
+  DALI_TEST_CHECK( !gTextChangedCallBackCalled );
+
+  imfEvent = InputMethodContext::EventData( InputMethodContext::PRE_EDIT, "두", 1, 2 );
+  inputMethodContext.EventReceivedSignal().Emit(inputMethodContext, imfEvent);
   DALI_TEST_CHECK( !gTextChangedCallBackCalled );
 
+  application.SendNotification();
+  application.Render();
+  DALI_TEST_CHECK( gTextChangedCallBackCalled );
+  DALI_TEST_EQUALS( field.GetProperty<std::string>( TextField::Property::TEXT ), std::string("호두"), TEST_LOCATION );
+
   END_TEST;
 }
 
+
 // Negative test for the textChanged signal.
 int utcDaliTextFieldTextChangedN(void)
 {
@@ -1079,6 +1159,8 @@ int utcDaliTextFieldTextChangedN(void)
 
   gTextChangedCallBackCalled = false;
   field.SetProperty( TextField::Property::PLACEHOLDER_TEXT, "ABC" ); // Setting placeholder, not TEXT
+  application.SendNotification();
+  application.Render();
   DALI_TEST_CHECK( !gTextChangedCallBackCalled );
   DALI_TEST_CHECK( !textChangedSignal );
 
index f986bd4..be4735b 100644 (file)
@@ -291,6 +291,9 @@ bool AccessibleImpl::GrabHighlight()
   highlight.SetProperty(Actor::Property::POSITION_Z, 1.0f);
   highlight.SetProperty(Actor::Property::POSITION, Vector2(0.0f, 0.0f));
 
+  // Remember the highlight actor, so that when the default is changed with
+  // SetHighlightActor(), the currently displayed highlight can still be cleared.
+  currentHighlightActor = highlight;
   EnsureSelfVisible();
   self.Add(highlight);
   SetCurrentlyHighlightedActor(self);
@@ -305,7 +308,8 @@ bool AccessibleImpl::ClearHighlight()
     return false;
   if(GetCurrentlyHighlightedActor() == self)
   {
-    self.Remove(GetHighlightActor());
+    self.Remove(currentHighlightActor.GetHandle());
+    currentHighlightActor = {};
     SetCurrentlyHighlightedActor({});
     EmitHighlighted(false);
     return true;
index feffe75..ff31c1e 100644 (file)
@@ -19,6 +19,7 @@
 // EXTERNAL INCLUDES
 #include <dali/devel-api/adaptor-framework/accessibility-impl.h>
 #include <dali/devel-api/adaptor-framework/accessibility.h>
+#include <dali/public-api/object/weak-handle.h>
 
 // INTERNAL INCLUDES
 #include <dali-toolkit/public-api/dali-toolkit-common.h>
@@ -46,6 +47,7 @@ struct DALI_TOOLKIT_API AccessibleImpl : public virtual Dali::Accessibility::Acc
                                          public virtual Dali::Accessibility::Action
 {
   Dali::Actor self;
+  Dali::WeakHandle<Dali::Actor> currentHighlightActor;
   bool        modal = false, root = false;
 
   AccessibleImpl(Dali::Actor self, Dali::Accessibility::Role role, bool modal = false);
index e3f4209..3a20928 100644 (file)
@@ -132,9 +132,7 @@ Actor AccessibilityManager::GetActorByFocusOrder(const unsigned int order)
 
 bool AccessibilityManager::SetCurrentFocusActor(Actor actor)
 {
-  Dali::Accessibility::Accessible::SetCurrentlyHighlightedActor(actor);
-
-  return true;
+  return Toolkit::DevelControl::GrabAccessibilityHighlight(actor);
 }
 
 Actor AccessibilityManager::GetCurrentFocusActor()
index 4e7d3f0..3d48333 100644 (file)
@@ -1384,7 +1384,7 @@ float TextEditor::GetHeightForWidth(float width)
 
 void TextEditor::ResizeActor(Actor& actor, const Vector2& size)
 {
-  if (actor.GetProperty<Vector3>(Dali::Actor::Property::SIZE).GetVectorXY() != size)
+  if(actor.GetProperty<Vector3>(Dali::Actor::Property::SIZE).GetVectorXY() != size)
   {
     actor.SetProperty(Actor::Property::SIZE, size);
   }
@@ -1446,6 +1446,14 @@ void TextEditor::OnRelayout(const Vector2& size, RelayoutContainer& container)
     }
 
     RenderText(updateTextType);
+
+    // If there is text changed, callback is called.
+    if(mTextChanged)
+    {
+      Dali::Toolkit::TextEditor handle(GetOwner());
+      mTextChangedSignal.Emit(handle);
+      mTextChanged = false;
+    }
   }
 
   // The text-editor emits signals when the input style changes. These changes of style are
@@ -1661,8 +1669,7 @@ void TextEditor::CaretMoved(unsigned int position)
 
 void TextEditor::TextChanged()
 {
-  Dali::Toolkit::TextEditor handle(GetOwner());
-  mTextChangedSignal.Emit(handle);
+  mTextChanged = true;
 }
 
 void TextEditor::MaxLengthReached()
@@ -1984,7 +1991,8 @@ TextEditor::TextEditor()
   mHasBeenStaged(false),
   mScrollAnimationEnabled(false),
   mScrollBarEnabled(false),
-  mScrollStarted(false)
+  mScrollStarted(false),
+  mTextChanged(false)
 {
 }
 
index 866c444..4c408ca 100644 (file)
@@ -362,7 +362,7 @@ private: // Implementation
    * @param[in] actor The actor to be resized.
    * @param[in] size Size to change.
    */
-  void ResizeActor( Actor& actor, const Vector2& size );
+  void ResizeActor(Actor& actor, const Vector2& size);
 
   /**
    * @brief Render view, create and attach actor(s) to this text editor.
@@ -402,6 +402,7 @@ private: // Data
   bool  mScrollAnimationEnabled : 1;
   bool  mScrollBarEnabled : 1;
   bool  mScrollStarted : 1;
+  bool  mTextChanged : 1;
 
   struct AccessibleImpl : public DevelControl::AccessibleImpl,
                           public virtual Dali::Accessibility::Text,
index 8b60fbe..47b32e9 100644 (file)
@@ -1335,7 +1335,7 @@ float TextField::GetHeightForWidth(float width)
 
 void TextField::ResizeActor(Actor& actor, const Vector2& size)
 {
-  if (actor.GetProperty<Vector3>(Dali::Actor::Property::SIZE).GetVectorXY() != size)
+  if(actor.GetProperty<Vector3>(Dali::Actor::Property::SIZE).GetVectorXY() != size)
   {
     actor.SetProperty(Actor::Property::SIZE, size);
   }
@@ -1397,6 +1397,14 @@ void TextField::OnRelayout(const Vector2& size, RelayoutContainer& container)
     }
 
     RenderText(updateTextType);
+
+    // If there is text changed, callback is called.
+    if(mTextChanged)
+    {
+      Dali::Toolkit::TextField handle(GetOwner());
+      mTextChangedSignal.Emit(handle);
+      mTextChanged = false;
+    }
   }
 
   // The text-field emits signals when the input style changes. These changes of style are
@@ -1689,8 +1697,7 @@ void TextField::CaretMoved(unsigned int position)
 
 void TextField::TextChanged()
 {
-  Dali::Toolkit::TextField handle(GetOwner());
-  mTextChangedSignal.Emit(handle);
+  mTextChanged = true;
 }
 
 void TextField::MaxLengthReached()
@@ -1867,7 +1874,8 @@ TextField::TextField()
   mAlignmentOffset(0.f),
   mRenderingBackend(DEFAULT_RENDERING_BACKEND),
   mExceedPolicy(Dali::Toolkit::TextField::EXCEED_POLICY_CLIP),
-  mHasBeenStaged(false)
+  mHasBeenStaged(false),
+  mTextChanged(false)
 {
 }
 
index 2fae0bb..07a7a37 100644 (file)
@@ -318,7 +318,7 @@ private: // Implementation
    * @param[in] actor The actor to be resized.
    * @param[in] size Size to change.
    */
-  void ResizeActor( Actor& actor, const Vector2& size );
+  void ResizeActor(Actor& actor, const Vector2& size);
 
   /**
    * @brief Render view, create and attach actor(s) to this Text Field.
@@ -357,6 +357,7 @@ private: // Data
   int   mRenderingBackend;
   int   mExceedPolicy;
   bool  mHasBeenStaged : 1;
+  bool  mTextChanged : 1;
 
 protected:
   struct AccessibleImpl : public DevelControl::AccessibleImpl,
index 9952c55..c9623a6 100644 (file)
@@ -265,8 +265,13 @@ void AnimatedImageVisual::DoCreateInstancePropertyMap(Property::Map& map) const
 
 void AnimatedImageVisual::OnDoAction(const Dali::Property::Index actionId, const Dali::Property::Value& attributes)
 {
-  // Check if action is valid for this visual type and perform action if possible
+  // Make not set any action when the resource status is already failed.
+  if(mImpl->mResourceStatus == Toolkit::Visual::ResourceStatus::FAILED)
+  {
+    return;
+  }
 
+  // Check if action is valid for this visual type and perform action if possible
   switch(actionId)
   {
     case DevelAnimatedImageVisual::Action::PAUSE:
@@ -322,7 +327,6 @@ void AnimatedImageVisual::OnDoAction(const Dali::Property::Index actionId, const
 void AnimatedImageVisual::DoSetProperties(const Property::Map& propertyMap)
 {
   // url[s] already passed in from constructor
-
   for(Property::Map::SizeType iter = 0; iter < propertyMap.Count(); ++iter)
   {
     KeyValuePair keyValue = propertyMap.GetKeyValue(iter);
@@ -491,6 +495,13 @@ void AnimatedImageVisual::DoSetOnScene(Actor& actor)
   mPlacementActor       = actor;
   TextureSet textureSet = PrepareTextureSet();
 
+  // Loading animated image file is failed.
+  if(!mImageCache ||
+     (mAnimatedImageLoading && !mAnimatedImageLoading.HasLoadingSucceeded()))
+  {
+    textureSet = SetLoadingFailed();
+  }
+
   if(textureSet) // if the image loading is successful
   {
     StartFirstFrame(textureSet);
@@ -632,8 +643,12 @@ void AnimatedImageVisual::StartFirstFrame(TextureSet& textureSet)
     mFrameDelayTimer.TickSignal().Connect(this, &AnimatedImageVisual::DisplayNextFrame);
     mFrameDelayTimer.Start();
   }
-  DALI_LOG_INFO(gAnimImgLogFilter, Debug::Concise, "ResourceReady(ResourceStatus::READY)\n");
-  ResourceReady(Toolkit::Visual::ResourceStatus::READY);
+
+  if(mImpl->mResourceStatus != Toolkit::Visual::ResourceStatus::FAILED)
+  {
+    DALI_LOG_INFO(gAnimImgLogFilter, Debug::Concise, "ResourceReady(ResourceStatus::READY)\n");
+    ResourceReady(Toolkit::Visual::ResourceStatus::READY);
+  }
 }
 
 TextureSet AnimatedImageVisual::PrepareTextureSet()
@@ -667,32 +682,31 @@ void AnimatedImageVisual::SetImageSize(TextureSet& textureSet)
 
 void AnimatedImageVisual::FrameReady(TextureSet textureSet)
 {
-  if(textureSet)
+  // When image visual requested to load new frame to mImageCache and it is failed.
+  if(!textureSet)
   {
-    SetImageSize(textureSet);
+    textureSet = SetLoadingFailed();
+  }
 
-    if(mStartFirstFrame)
-    {
-      StartFirstFrame(textureSet);
-    }
-    else
-    {
-      if(mImpl->mRenderer)
-      {
-        mImpl->mRenderer.SetTextures(textureSet);
-      }
-    }
+  SetImageSize(textureSet);
+
+  if(mStartFirstFrame)
+  {
+    StartFirstFrame(textureSet);
   }
   else
   {
-    DALI_LOG_INFO(gAnimImgLogFilter, Debug::Concise, "ResourceReady(ResourceStatus::FAILED)\n");
-    ResourceReady(Toolkit::Visual::ResourceStatus::FAILED);
+    if(mImpl->mRenderer)
+    {
+      mImpl->mRenderer.SetTextures(textureSet);
+    }
   }
 }
 
 bool AnimatedImageVisual::DisplayNextFrame()
 {
-  bool continueTimer = false;
+  TextureSet textureSet;
+  bool       continueTimer = false;
 
   if(mImageCache)
   {
@@ -756,7 +770,6 @@ bool AnimatedImageVisual::DisplayNextFrame()
 
     DALI_LOG_INFO(gAnimImgLogFilter, Debug::Concise, "AnimatedImageVisual::DisplayNextFrame(this:%p) CurrentFrameIndex:%d\n", this, frameIndex);
 
-    TextureSet textureSet;
     if(nextFrame)
     {
       textureSet = mImageCache->NextFrame();
@@ -766,21 +779,41 @@ bool AnimatedImageVisual::DisplayNextFrame()
       textureSet = mImageCache->Frame(frameIndex);
     }
 
-    if(textureSet)
+    continueTimer = (mActionStatus == DevelAnimatedImageVisual::Action::PLAY) ? true : false;
+  }
+
+  if(textureSet)
+  {
+    SetImageSize(textureSet);
+    if(mImpl->mRenderer)
     {
-      SetImageSize(textureSet);
-      if(mImpl->mRenderer)
-      {
-        mImpl->mRenderer.SetTextures(textureSet);
-      }
+      mImpl->mRenderer.SetTextures(textureSet);
     }
-
-    continueTimer = (mActionStatus == DevelAnimatedImageVisual::Action::PLAY) ? true : false;
   }
 
   return continueTimer;
 }
 
+TextureSet AnimatedImageVisual::SetLoadingFailed()
+{
+  DALI_LOG_INFO(gAnimImgLogFilter, Debug::Concise, "ResourceReady(ResourceStatus::FAILED)\n");
+  ResourceReady(Toolkit::Visual::ResourceStatus::FAILED);
+
+  TextureSet textureSet  = TextureSet::New();
+  Texture    brokenImage = mFactoryCache.GetBrokenVisualImage();
+  textureSet.SetTexture(0u, brokenImage);
+
+  if(mFrameDelayTimer)
+  {
+    mFrameDelayTimer.Stop();
+    mFrameDelayTimer.Reset();
+  }
+
+  SetImageSize(textureSet);
+
+  return textureSet;
+}
+
 } // namespace Internal
 
 } // namespace Toolkit
index 6ccdcbb..608b43f 100644 (file)
@@ -228,6 +228,12 @@ private:
    */
   void InitializeAnimatedImage(const VisualUrl& imageUrl);
 
+  /**
+   * Set the state of loading fail of an image or a frame.
+   * Returns TextureSet of broken image.
+   */
+  TextureSet SetLoadingFailed();
+
   // Undefined
   AnimatedImageVisual(const AnimatedImageVisual& animatedImageVisual);
 
index 0f69e0d..5a75711 100644 (file)
@@ -29,7 +29,7 @@ namespace Toolkit
 {
 const unsigned int TOOLKIT_MAJOR_VERSION = 2;
 const unsigned int TOOLKIT_MINOR_VERSION = 0;
-const unsigned int TOOLKIT_MICRO_VERSION = 17;
+const unsigned int TOOLKIT_MICRO_VERSION = 18;
 const char* const  TOOLKIT_BUILD_DATE    = __DATE__ " " __TIME__;
 
 #ifdef DEBUG_ENABLED
index 81bf0b7..12787c2 100644 (file)
@@ -1,6 +1,6 @@
 Name:       dali2-toolkit
 Summary:    Dali 3D engine Toolkit
-Version:    2.0.17
+Version:    2.0.18
 Release:    1
 Group:      System/Libraries
 License:    Apache-2.0 and BSD-3-Clause and MIT
@@ -87,8 +87,7 @@ Application development package for Dali 3D engine toolkit - headers and package
 Summary:    DLI scene loading library
 Group:      System/Libraries
 License:    Apache-2.0
-
-BuildRequires:  pkgconfig(dali2-toolkit)
+Requires:   dali2-toolkit
 
 %description -n %{dali2_scene_loader}
 Provides functionality for loading and displaying DLI format scenes. See README.md for more details.