/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2023 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.
DALI_TEST_EQUALS(textureCallStack.CountMethod("GenTextures"), 0, TEST_LOCATION);
END_TEST;
-}
\ No newline at end of file
+}
+
+int UtcDaliImageViewPlaceholderImage(void)
+{
+ tet_infoline("Test imageView use placeholder image");
+
+ ToolkitTestApplication application;
+ Property::Map map;
+ map[Toolkit::ImageVisual::Property::URL] = gImage_600_RGB;
+
+ ImageView imageView = ImageView::New();
+ imageView.SetProperty(Toolkit::ImageView::Property::IMAGE, map);
+ imageView.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 200.0f));
+ application.GetScene().Add(imageView);
+
+ Property::Value value = imageView.GetProperty(ImageView::Property::PLACEHOLDER_IMAGE);
+ std::string url;
+ DALI_TEST_CHECK(value.Get(url));
+ DALI_TEST_CHECK(url.empty());
+ imageView.SetProperty(Toolkit::ImageView::Property::PLACEHOLDER_IMAGE, gImage_34_RGBA);
+
+ application.SendNotification();
+ application.Render();
+
+ value = imageView.GetProperty(ImageView::Property::PLACEHOLDER_IMAGE);
+ DALI_TEST_CHECK(value.Get(url));
+ DALI_TEST_CHECK(url == gImage_34_RGBA);
+
+ imageView.SetProperty(Toolkit::ImageView::Property::IMAGE, map);
+ application.SendNotification();
+ application.Render();
+
+ // Replace Image test
+ map[Toolkit::ImageVisual::Property::URL] = TEST_IMAGE_1;
+ map[ImageView::Property::PLACEHOLDER_IMAGE] = gImage_34_RGBA;
+ imageView.SetProperty(Toolkit::ImageView::Property::IMAGE, map);
+ application.SendNotification();
+ application.Render();
+
+ map[Toolkit::ImageVisual::Property::URL] = "";
+ imageView.SetProperty(Toolkit::ImageView::Property::IMAGE, map);
+ application.SendNotification();
+ application.Render();
+
+ map[Toolkit::ImageVisual::Property::URL] = TEST_IMAGE_2;
+ imageView.SetProperty(Toolkit::ImageView::Property::IMAGE, map);
+ application.SendNotification();
+ application.Render();
+
+ // Replace Image test2
+ map[Toolkit::ImageVisual::Property::URL] = TEST_IMAGE_1;
+ imageView.SetProperty(Toolkit::ImageView::Property::IMAGE, map);
+ application.SendNotification();
+ application.Render();
+
+ map[Toolkit::ImageVisual::Property::URL] = TEST_IMAGE_2;
+ imageView.SetProperty(Toolkit::ImageView::Property::IMAGE, map);
+ application.SendNotification();
+ application.Render();
+
+ map[Toolkit::ImageVisual::Property::URL] = gImage_600_RGB;
+ imageView.SetProperty(Toolkit::ImageView::Property::IMAGE, map);
+ application.SendNotification();
+ application.Render(900);
+
+ map[Toolkit::ImageVisual::Property::URL] = "";
+ imageView.SetProperty(Toolkit::ImageView::Property::IMAGE, map);
+ application.SendNotification();
+ application.Render();
+
+ map[Toolkit::ImageVisual::Property::URL] = TEST_IMAGE_1;
+ imageView.SetProperty(Toolkit::ImageView::Property::IMAGE, map);
+ application.SendNotification();
+ application.Render();
+
+ END_TEST;
+}
+
+int UtcDaliImageViewTransitionEffect01(void)
+{
+ tet_infoline("Test imageView use transition effect");
+
+ ToolkitTestApplication application;
+ Property::Map map;
+ map[Toolkit::ImageVisual::Property::URL] = gImage_600_RGB;
+ map[Toolkit::Visual::Property::OPACITY] = 0.9f;
+
+ ImageView imageView = ImageView::New();
+ imageView.SetProperty(Toolkit::ImageView::Property::IMAGE, map);
+ imageView.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 200.0f));
+ application.GetScene().Add(imageView);
+
+ Property::Value value = imageView.GetProperty(ImageView::Property::ENABLE_TRANSITION_EFFECT);
+ bool transition;
+ DALI_TEST_CHECK(value.Get(transition));
+ DALI_TEST_CHECK(transition == false);
+ imageView.SetProperty(Toolkit::ImageView::Property::ENABLE_TRANSITION_EFFECT, true);
+
+ application.SendNotification();
+ application.Render();
+
+ value = imageView.GetProperty(ImageView::Property::ENABLE_TRANSITION_EFFECT);
+ DALI_TEST_CHECK(value.Get(transition));
+ DALI_TEST_CHECK(transition == true);
+
+ imageView.SetProperty(Toolkit::ImageView::Property::IMAGE, map);
+ DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION);
+ application.SendNotification();
+ application.Render();
+
+ // Test transition effect with placeholder
+ map[Toolkit::ImageVisual::Property::URL] = TEST_IMAGE_1;
+ imageView.SetProperty(Toolkit::ImageView::Property::IMAGE, map);
+ imageView.SetProperty(Toolkit::ImageView::Property::PLACEHOLDER_IMAGE, gImage_34_RGBA);
+ DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION);
+ application.SendNotification();
+ application.Render();
+
+ map[Toolkit::ImageVisual::Property::URL] = "";
+ imageView.SetProperty(Toolkit::ImageView::Property::IMAGE, map);
+ imageView.SetProperty(Toolkit::ImageView::Property::PLACEHOLDER_IMAGE, gImage_34_RGBA);
+ application.SendNotification();
+ application.Render();
+
+ map[Toolkit::ImageVisual::Property::URL] = gImage_600_RGB;
+ imageView.SetProperty(Toolkit::ImageView::Property::IMAGE, map);
+ imageView.SetProperty(Toolkit::ImageView::Property::PLACEHOLDER_IMAGE, gImage_34_RGBA);
+ application.SendNotification();
+ application.Render();
+
+ map[Toolkit::ImageVisual::Property::URL] = TEST_IMAGE_1;
+ imageView.SetProperty(Toolkit::ImageView::Property::IMAGE, map);
+ imageView.SetProperty(Toolkit::ImageView::Property::PLACEHOLDER_IMAGE, gImage_34_RGBA);
+ application.SendNotification();
+
+ map[Toolkit::ImageVisual::Property::URL] = "";
+ imageView.SetProperty(Toolkit::ImageView::Property::IMAGE, map);
+ imageView.SetProperty(Toolkit::ImageView::Property::PLACEHOLDER_IMAGE, gImage_34_RGBA);
+ application.SendNotification();
+ application.Render();
+
+ map[Toolkit::ImageVisual::Property::URL] = gImage_600_RGB;
+ imageView.SetProperty(Toolkit::ImageView::Property::IMAGE, map);
+ imageView.SetProperty(Toolkit::ImageView::Property::PLACEHOLDER_IMAGE, "");
+ application.SendNotification();
+ application.Render();
+
+ map[Toolkit::ImageVisual::Property::URL] = gImage_600_RGB;
+ imageView.SetProperty(Toolkit::ImageView::Property::IMAGE, map);
+ application.SendNotification();
+ application.Render();
+
+ map[Toolkit::ImageVisual::Property::URL] = "";
+ imageView.SetProperty(Toolkit::ImageView::Property::IMAGE, map);
+ application.SendNotification();
+ application.Render();
+
+ // Test transition effect without placeholder
+ map[Toolkit::ImageVisual::Property::URL] = TEST_IMAGE_1;
+ imageView.SetProperty(Toolkit::ImageView::Property::IMAGE, map);
+ application.SendNotification();
+ application.Render();
+
+ map[Toolkit::ImageVisual::Property::URL] = gImage_600_RGB;
+ imageView.SetProperty(Toolkit::ImageView::Property::IMAGE, map);
+ application.SendNotification();
+ application.Render();
+
+ map[Toolkit::ImageVisual::Property::URL] = "";
+ imageView.SetProperty(Toolkit::ImageView::Property::IMAGE, map);
+ application.SendNotification();
+ application.Render();
+
+ map[Toolkit::ImageVisual::Property::URL] = gImage_600_RGB;
+ imageView.SetProperty(Toolkit::ImageView::Property::IMAGE, map);
+ application.SendNotification();
+ application.Render();
+
+ imageView.SetImage(TEST_IMAGE_1);
+ application.SendNotification();
+ application.Render();
+
+ imageView.SetImage(gImage_600_RGB);
+ application.SendNotification();
+ application.Render(9000);
+
+ imageView.SetImage("");
+ application.SendNotification();
+ application.Render();
+
+ imageView.SetImage(TEST_IMAGE_1);
+ application.SendNotification();
+ application.Render();
+
+ // Clear all cached
+ imageView.Unparent();
+ imageView.Reset();
+
+ END_TEST;
+}
+
+int UtcDaliImageViewTransitionEffect02(void)
+{
+ tet_infoline("Test imageView use transition effect with replace image");
+
+ ToolkitTestApplication application;
+
+ Property::Map map;
+
+ ImageView imageView = ImageView::New();
+ imageView.SetProperty(Toolkit::ImageView::Property::IMAGE, map);
+ imageView.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 200.0f));
+ application.GetScene().Add(imageView);
+
+ Property::Value value;
+ value = imageView.GetProperty(ImageView::Property::ENABLE_TRANSITION_EFFECT);
+ bool transition;
+ DALI_TEST_CHECK(value.Get(transition));
+ DALI_TEST_CHECK(transition == false);
+ imageView.SetProperty(Toolkit::ImageView::Property::ENABLE_TRANSITION_EFFECT, true);
+
+ value = imageView.GetProperty(ImageView::Property::PLACEHOLDER_IMAGE);
+ std::string url;
+ DALI_TEST_CHECK(value.Get(url));
+ DALI_TEST_CHECK(url.empty());
+ imageView.SetProperty(Toolkit::ImageView::Property::PLACEHOLDER_IMAGE, gImage_34_RGBA);
+ application.SendNotification();
+ application.Render();
+
+ imageView.SetProperty(Toolkit::ImageView::Property::PLACEHOLDER_IMAGE, "");
+ application.SendNotification();
+ application.Render();
+
+ imageView.SetProperty(Toolkit::ImageView::Property::PLACEHOLDER_IMAGE, gImage_34_RGBA);
+ application.SendNotification();
+ application.Render();
+
+ value = imageView.GetProperty(ImageView::Property::ENABLE_TRANSITION_EFFECT);
+ DALI_TEST_CHECK(value.Get(transition));
+ DALI_TEST_CHECK(transition == true);
+
+ value = imageView.GetProperty(ImageView::Property::PLACEHOLDER_IMAGE);
+ DALI_TEST_CHECK(value.Get(url));
+ DALI_TEST_CHECK(url == gImage_34_RGBA);
+
+ imageView.SetProperty(Toolkit::ImageView::Property::IMAGE, map);
+ application.SendNotification();
+ application.Render();
+
+ // Clear all cached
+ imageView.Unparent();
+ imageView.Reset();
+
+ END_TEST;
+}
+
+int UtcDaliImageViewTransitionEffect03(void)
+{
+ tet_infoline("Test imageView use transition effect with placeholder");
+
+ ToolkitTestApplication application;
+ Property::Map map;
+
+ ImageView imageView = ImageView::New();
+ imageView.SetImage("");
+ imageView.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 200.0f));
+ imageView.SetProperty(ImageView::Property::PLACEHOLDER_IMAGE, gImage_34_RGBA);
+ imageView.SetProperty(ImageView::Property::ENABLE_TRANSITION_EFFECT, true);
+ application.GetScene().Add(imageView);
+
+ //DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION);
+
+ application.SendNotification();
+ application.Render(16);
+
+ tet_infoline("(1)");
+ imageView.SetImage(gImage_600_RGB);
+ imageView.SetProperty(ImageView::Property::PLACEHOLDER_IMAGE, gImage_34_RGBA);
+ DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(2), true, TEST_LOCATION);
+ application.SendNotification();
+ application.Render(16);
+
+ Property::Value value;
+ value = imageView.GetProperty(ImageView::Property::ENABLE_TRANSITION_EFFECT);
+ bool transition;
+ DALI_TEST_CHECK(value.Get(transition));
+ DALI_TEST_CHECK(transition == true);
+
+ value = imageView.GetProperty(ImageView::Property::PLACEHOLDER_IMAGE);
+ std::string url;
+ DALI_TEST_CHECK(value.Get(url));
+ DALI_TEST_CHECK(url == gImage_34_RGBA);
+
+ imageView.SetImage("");
+ application.SendNotification();
+ application.Render(16);
+
+ imageView.SetImage(TEST_IMAGE_1);
+ imageView.SetProperty(ImageView::Property::PLACEHOLDER_IMAGE, gImage_34_RGBA);
+ DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION);
+ application.SendNotification();
+ application.Render(16);
+
+ // Clear all cached
+ imageView.Unparent();
+ imageView.Reset();
+
+ END_TEST;
+}
/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2023 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.
#define DALI_TOOLKIT_CONTROL_DEVEL_H
/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2023 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.
return false;
}
+/**
+ * Finds visual in given array, returning true if found along with the iterator for that visual as a out parameter
+ */
+bool FindVisual(const Toolkit::Visual::Base findVisual , const RegisteredVisualContainer& visuals, RegisteredVisualContainer::Iterator& iter)
+{
+ for(iter = visuals.Begin(); iter != visuals.End(); iter++)
+ {
+ Toolkit::Visual::Base visual = (*iter)->visual;
+ if(visual && visual == findVisual)
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
void FindChangableVisuals(Dictionary<Property::Map>& stateVisualsToAdd,
Dictionary<Property::Map>& stateVisualsToChange,
DictionaryKeys& stateVisualsToRemove)
return false;
}
+void Control::Impl::EnableReadyTransitionOverriden(Toolkit::Visual::Base& visual, bool enable)
+{
+ DALI_LOG_INFO(gLogFilter, Debug::General, "Control::EnableReadyTransitionOverriden(%p, %s)\n", visual, enable ? "T" : "F");
+
+ RegisteredVisualContainer::Iterator iter;
+ if(FindVisual(visual, mVisuals, iter))
+ {
+ if((*iter)->overideReadyTransition == enable)
+ {
+ DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Control::EnableReadyTransitionOverriden Visual %s(%p) already %s\n", (*iter)->visual.GetName().c_str(), visual, enable ? "enabled" : "disabled");
+ return;
+ }
+
+ (*iter)->overideReadyTransition = enable;
+ }
+}
+
void Control::Impl::StopObservingVisual(Toolkit::Visual::Base& visual)
{
Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
if(FindVisual((*registeredIter)->index, mRemoveVisuals, visualToRemoveIter))
{
(*registeredIter)->pending = false;
- Toolkit::GetImplementation((*visualToRemoveIter)->visual).SetOffScene(self);
+ if(!((*visualToRemoveIter)->overideReadyTransition))
+ {
+ Toolkit::GetImplementation((*visualToRemoveIter)->visual).SetOffScene(self);
+ }
mRemoveVisuals.Erase(visualToRemoveIter);
}
break;
#define DALI_TOOLKIT_CONTROL_DATA_IMPL_H
/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2023 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.
Toolkit::Visual::Base visual;
bool enabled : 1;
bool pending : 1;
+ bool overideReadyTransition : 1;
RegisteredVisual(Property::Index aIndex, Toolkit::Visual::Base& aVisual, bool aEnabled, bool aPendingReplacement)
: index(aIndex),
visual(aVisual),
enabled(aEnabled),
- pending(aPendingReplacement)
+ pending(aPendingReplacement),
+ overideReadyTransition(false)
{
}
};
*/
bool IsVisualEnabled(Property::Index index) const;
+ /**
+ * @brief Sets the given visual to be ready transition
+ *
+ * @param[in] control The control
+ * @param[in] visual The visual to ready transition overriden
+ * @param[in] enable flag to set enabled or disabled.
+ */
+ void EnableReadyTransitionOverriden(Toolkit::Visual::Base& visual, bool enable);
+
/**
* @brief Stops observing the given visual.
* @param[in] visual The visual to stop observing
{
const Vector4 FULL_TEXTURE_RECT(0.f, 0.f, 1.f, 1.f);
+constexpr float FULL_OPACITY = 1.0f;
+constexpr float LOW_OPACITY = 0.2f;
+
BaseHandle Create()
{
return Toolkit::ImageView::New();
DALI_TYPE_REGISTRATION_BEGIN(Toolkit::ImageView, Toolkit::Control, Create);
DALI_PROPERTY_REGISTRATION(Toolkit, ImageView, "image", MAP, IMAGE)
DALI_PROPERTY_REGISTRATION(Toolkit, ImageView, "preMultipliedAlpha", BOOLEAN, PRE_MULTIPLIED_ALPHA)
-
+DALI_PROPERTY_REGISTRATION(Toolkit, ImageView, "placeholderImage", STRING, PLACEHOLDER_IMAGE)
+DALI_PROPERTY_REGISTRATION(Toolkit, ImageView, "enableTransitionEffect", BOOLEAN, ENABLE_TRANSITION_EFFECT)
DALI_ANIMATABLE_PROPERTY_REGISTRATION_WITH_DEFAULT(Toolkit, ImageView, "pixelArea", Vector4(0.f, 0.f, 1.f, 1.f), PIXEL_AREA)
DALI_TYPE_REGISTRATION_END()
ImageView::ImageView(ControlBehaviour additionalBehaviour)
: Control(ControlBehaviour(CONTROL_BEHAVIOUR_DEFAULT | additionalBehaviour)),
mImageSize(),
+ mTransitionTargetAlpha(FULL_OPACITY),
mImageVisualPaddingSetByTransform(false),
- mImageViewPixelAreaSetByFittingMode(false)
+ mImageViewPixelAreaSetByFittingMode(false),
+ mTransitionEffect(false)
{
}
void ImageView::SetImage(const Property::Map& map)
{
+ DALI_LOG_ERROR("tscholb : SetImage(map) !!! \n");
+ if(mTransitionEffect && mVisual)
+ {
+ // Clear previous transition effect if it is playing
+ if(mPreviousVisual)
+ {
+ if(mTransitionAnimation)
+ {
+ if(mTransitionAnimation.GetState() == Animation::PLAYING)
+ {
+ mTransitionAnimation.Stop();
+ ClearTransitionAnimation();
+ }
+ }
+ }
+
+ // Enable transition effect for previous visual.
+ // This previous visual will be deleted when transition effect is done.
+ Internal::Control::Impl& controlDataImpl = Internal::Control::Impl::Get(*this);
+ controlDataImpl.EnableReadyTransitionOverriden(mVisual, true);
+ mPreviousVisual = mVisual;
+ }
+
// Comparing a property map is too expensive so just creating a new visual
mPropertyMap = map;
mUrl.clear();
+ // keep alpha for transition effect
+ if(mTransitionEffect)
+ {
+ float alpha = FULL_OPACITY;
+ Property::Value* alphaValue = map.Find(Toolkit::Visual::Property::OPACITY);
+ if(alphaValue && alphaValue->Get(alpha))
+ {
+ mTransitionTargetAlpha = alpha;
+ }
+ }
+
+ if(!mVisual)
+ {
+ ShowPlaceholderImage();
+ }
+
Toolkit::Visual::Base visual = Toolkit::VisualFactory::Get().CreateVisual(mPropertyMap);
if(visual)
{
void ImageView::SetImage(const std::string& url, ImageDimensions size)
{
+ DALI_LOG_ERROR("tscholb : SetImage !!! \n");
+ if(mTransitionEffect && mVisual)
+ {
+ // Clear previous transition effect if it is playing
+ if(mPreviousVisual)
+ {
+ if(mTransitionAnimation)
+ {
+ if(mTransitionAnimation.GetState() == Animation::PLAYING)
+ {
+ mTransitionAnimation.Stop();
+ ClearTransitionAnimation();
+ }
+ }
+ }
+
+ // Enable transition effect for previous visual.
+ // This previous visual will be deleted when transition effect is done.
+ Internal::Control::Impl& controlDataImpl = Internal::Control::Impl::Get(*this);
+ controlDataImpl.EnableReadyTransitionOverriden(mVisual, true);
+ mPreviousVisual = mVisual;
+ }
+
// Don't bother comparing if we had a visual previously, just drop old visual and create new one
mUrl = url;
mImageSize = size;
mPropertyMap.Clear();
+ if(!mVisual)
+ {
+ ShowPlaceholderImage();
+ }
+
// Don't set mVisual until it is ready and shown. Getters will still use current visual.
Toolkit::Visual::Base visual = Toolkit::VisualFactory::Get().CreateVisual(url, size);
if(visual)
RelayoutRequest();
}
+ //tscholb DEBUG
+ Dali::Toolkit::Control handle(GetOwner());
+ auto check1 = handle.GetVisualResourceStatus(Toolkit::ImageView::Property::IMAGE);
+ auto check2 = handle.GetVisualResourceStatus(Toolkit::ImageView::Property::PLACEHOLDER_IMAGE);
+ DALI_LOG_ERROR("tscholb : Resource status check >> %d,%d \n", check1, check2);
+
// Signal that a Relayout may be needed
}
// Clear cached properties
mPropertyMap.Clear();
mUrl.clear();
+ mVisual.Reset();
// Unregister the exsiting visual
DevelControl::UnregisterVisual(*this, Toolkit::ImageView::Property::IMAGE);
}
}
+void ImageView::SetPlaceholderUrl(const std::string& url)
+{
+ mPlaceholderUrl = url;
+ if(!url.empty())
+ {
+ mPlaceholderVisual.Reset();
+ CreatePlaceholderImage();
+ }
+ else
+ {
+ // Clear current placeholder image
+ Toolkit::Visual::Base visual = DevelControl::GetVisual(*this, Toolkit::ImageView::Property::PLACEHOLDER_IMAGE);
+ if(visual)
+ {
+ DevelControl::UnregisterVisual(*this, Toolkit::ImageView::Property::PLACEHOLDER_IMAGE);
+ }
+
+ mPlaceholderVisual.Reset();
+ mPlaceholderUrl = url;
+ }
+}
+
+std::string ImageView::GetPlaceholderUrl() const
+{
+ return mPlaceholderUrl;
+}
+
+void ImageView::EnableTransitionEffect(bool effectEnable)
+{
+ mTransitionEffect = effectEnable;
+}
+
+bool ImageView::IsTransitionEffectEnabled() const
+{
+ return mTransitionEffect;
+}
+
Vector3 ImageView::GetNaturalSize()
{
if(mVisual)
void ImageView::OnResourceReady(Toolkit::Control control)
{
+ DALI_LOG_ERROR("tscholb : OnResourceReady !!! \n");
+ // In case of placeholder, we need to skip this call.
+ // TODO: In case of placeholder, it needs to be modified not to call OnResourceReady()
+ if(control.GetVisualResourceStatus(Toolkit::ImageView::Property::IMAGE) != Toolkit::Visual::ResourceStatus::READY)
+ {
+ DALI_LOG_ERROR("tscholb : OnResourceReady() is called, but SKIP \n");
+ return;
+ }
+
+ // Do transition effect if need.
+ if(mTransitionEffect)
+ {
+ // TODO: Consider about placeholder image is loaded failed
+ Toolkit::Visual::Base placeholderVisual = DevelControl::GetVisual(*this, Toolkit::ImageView::Property::PLACEHOLDER_IMAGE);
+ if(!placeholderVisual || control.GetVisualResourceStatus(Toolkit::ImageView::Property::PLACEHOLDER_IMAGE) == Toolkit::Visual::ResourceStatus::READY)
+ {
+ // when placeholder is disabled or ready placeholder and image, we need to transition effect
+ DALI_LOG_ERROR("tscholb : Call TransitionEffect \n");
+ TransitionImageWithEffect();
+ }
+ else
+ {
+ DALI_LOG_ERROR("tscholb : Call ClearTransitionAnimation \n");
+ ClearTransitionAnimation();
+ }
+ }
+ else
+ {
+ // we don't need placeholder anymore because visual is replaced. so hide placeholder.
+ DALI_LOG_ERROR("tscholb : transition effect is DISABLE \n");
+ HidePlaceholderImage();
+ }
+
// Visual ready so update visual attached to this ImageView, following call to RelayoutRequest will use this visual.
mVisual = DevelControl::GetVisual(*this, Toolkit::ImageView::Property::IMAGE);
// Signal that a Relayout may be needed
}
}
+void ImageView::CreatePlaceholderImage()
+{
+ Property::Map propertyMap;
+ propertyMap.Insert(Toolkit::Visual::Property::TYPE, Toolkit::Visual::IMAGE);
+ propertyMap.Insert(Toolkit::ImageVisual::Property::URL, mPlaceholderUrl);
+ //propertyMap.Insert(Toolkit::ImageVisual::Property::LOAD_POLICY, Toolkit::ImageVisual::LoadPolicy::IMMEDIATE); // TODO: need to enable this property
+ propertyMap.Insert(Toolkit::ImageVisual::Property::RELEASE_POLICY, Toolkit::ImageVisual::ReleasePolicy::DESTROYED);
+ mPlaceholderVisual = Toolkit::VisualFactory::Get().CreateVisual(propertyMap);
+ if(mPlaceholderVisual)
+ {
+ mPlaceholderVisual.SetName("placeholder");
+ }
+ else
+ {
+ DevelControl::UnregisterVisual(*this, Toolkit::ImageView::Property::PLACEHOLDER_IMAGE);
+ mPlaceholderVisual.Reset();
+ }
+}
+
+void ImageView::ShowPlaceholderImage()
+{
+ if(mPlaceholderVisual)
+ {
+ DevelControl::RegisterVisual(*this, Toolkit::ImageView::Property::PLACEHOLDER_IMAGE, mPlaceholderVisual, false);
+ Actor self = Self();
+ Toolkit::GetImplementation(mPlaceholderVisual).SetOnScene(self);
+ }
+}
+
+void ImageView::HidePlaceholderImage()
+{
+ if(mPlaceholderVisual)
+ {
+ DevelControl::UnregisterVisual(*this, Toolkit::ImageView::Property::PLACEHOLDER_IMAGE);
+
+ // Hide placeholder
+ Actor self = Self();
+ Toolkit::GetImplementation(mPlaceholderVisual).SetOffScene(self);
+ }
+}
+
+void ImageView::TransitionImageWithEffect()
+{
+ Toolkit::ImageView handle = Toolkit::ImageView(GetOwner());
+
+ if(handle)
+ {
+ mTransitionAnimation = Animation::New(1.5f);
+ mTransitionAnimation.SetEndAction(Animation::EndAction::DISCARD);
+ float destinationAlpha = (mTransitionTargetAlpha > LOW_OPACITY) ? mTransitionTargetAlpha : LOW_OPACITY;
+
+ if(mPreviousVisual) // Transition previous image
+ {
+ DALI_LOG_ERROR("tscholb : mPreviousVisual !!! \n");
+ Dali::KeyFrames fadeoutKeyFrames = Dali::KeyFrames::New();
+ fadeoutKeyFrames.Add(0.0f, destinationAlpha);
+ fadeoutKeyFrames.Add(1.0f, LOW_OPACITY);
+ Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(mPreviousVisual);
+ mTransitionAnimation.AnimateBetween(visualImpl.GetPropertyObject(Toolkit::Visual::Property::OPACITY), fadeoutKeyFrames);
+ }
+ else if(mPlaceholderVisual) // Transition placeholder
+ {
+ DALI_LOG_ERROR("tscholb : mPlaceholderVisual !!! \n");
+ Dali::KeyFrames fadeoutKeyFrames = Dali::KeyFrames::New();
+ fadeoutKeyFrames.Add(0.0f, destinationAlpha);
+ fadeoutKeyFrames.Add(1.0f, LOW_OPACITY);
+ Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(mPlaceholderVisual);
+ mTransitionAnimation.AnimateBetween(visualImpl.GetPropertyObject(Toolkit::Visual::Property::OPACITY), fadeoutKeyFrames);
+ }
+
+ // Transition current image
+ Toolkit::Visual::Base imageVisual = DevelControl::GetVisual(*this, Toolkit::ImageView::Property::IMAGE);
+ if(imageVisual)
+ {
+ DALI_LOG_ERROR("tscholb : imageVisual !!! \n");
+ Dali::KeyFrames fadeinKeyFrames = Dali::KeyFrames::New();
+ fadeinKeyFrames.Add(0.0f, LOW_OPACITY);
+ fadeinKeyFrames.Add(1.0f, destinationAlpha);
+ mTransitionAnimation.AnimateBetween(DevelControl::GetVisualProperty(handle, Toolkit::ImageView::Property::IMAGE, Toolkit::Visual::Property::OPACITY), fadeinKeyFrames);
+ }
+
+ // Play transition animation
+ mTransitionAnimation.FinishedSignal().Connect(this, &ImageView::OnTransitionAnimationFinishedCallback);
+ mTransitionAnimation.Play();
+ }
+}
+
+void ImageView::ClearTransitionAnimation()
+{
+ // Hide placeholder
+ HidePlaceholderImage();
+
+ // Clear PreviousVisual
+ if(mPreviousVisual)
+ {
+ Actor self = Self();
+ Internal::Control::Impl& controlDataImpl = Internal::Control::Impl::Get(*this);
+ controlDataImpl.EnableReadyTransitionOverriden(mVisual, false);
+ Toolkit::GetImplementation(mPreviousVisual).SetOffScene(self);
+ mPreviousVisual.Reset();
+ }
+
+ if(mTransitionAnimation)
+ {
+ mTransitionAnimation.FinishedSignal().Disconnect(this, &ImageView::OnTransitionAnimationFinishedCallback);
+ mTransitionAnimation.Clear();
+ }
+}
+
///////////////////////////////////////////////////////////
//
// Properties
}
break;
}
+
+ case Toolkit::ImageView::Property::PLACEHOLDER_IMAGE:
+ {
+ std::string placeholderUrl;
+ if(value.Get(placeholderUrl))
+ {
+ impl.SetPlaceholderUrl(placeholderUrl);
+ }
+ break;
+ }
+
+ case Toolkit::ImageView::Property::ENABLE_TRANSITION_EFFECT:
+ {
+ bool transitionEffect;
+ if(value.Get(transitionEffect))
+ {
+ impl.EnableTransitionEffect(transitionEffect);
+ }
+ break;
+ }
}
}
}
value = impl.IsPreMultipliedAlphaEnabled();
break;
}
+
+ case Toolkit::ImageView::Property::PLACEHOLDER_IMAGE:
+ {
+ value = impl.GetPlaceholderUrl();
+ break;
+ }
+
+ case Toolkit::ImageView::Property::ENABLE_TRANSITION_EFFECT:
+ {
+ value = impl.IsTransitionEffectEnabled();
+ break;
+ }
}
}
return value;
}
+void ImageView::OnTransitionAnimationFinishedCallback(Animation& animation)
+{
+ ClearTransitionAnimation();
+}
+
} // namespace Internal
} // namespace Toolkit
} // namespace Dali
*/
void SetDepthIndex(int depthIndex);
+ /**
+ * @brief Set the placeholder url
+ */
+ void SetPlaceholderUrl(const std::string& url);
+
+ /**
+ * @brief Get the placeholder url
+ */
+ std::string GetPlaceholderUrl() const;
+
+ /**
+ * @brief Enable the transition effect
+ */
+ void EnableTransitionEffect(bool effectEnable);
+
+ /**
+ * @brief Query whether transition effect is enabled
+ */
+ bool IsTransitionEffectEnabled() const;
+
+ /**
+ * @brief callback when animation for placeholder or previous visual transition effect is finished
+ */
+ void OnTransitionAnimationFinishedCallback(Animation& animation);
+
private: // From Control
/**
* @copydoc Toolkit::Control::OnInitialize
*/
void ApplyFittingMode(Vector2 finalSize, Vector2 offset, bool zeroPadding, Property::Map& transformMap);
+ /**
+ * @brief Create placeholder image if it set. placeholder image is shown when image view is waiting for the image to load.
+ */
+ void CreatePlaceholderImage();
+
+ /**
+ * @brief Show placeholder image if it set. placeholder image is shown when image view is waiting for the image to load.
+ */
+ void ShowPlaceholderImage();
+
+ /**
+ * @brief Hide placeholder image if it set.
+ */
+ void HidePlaceholderImage();
+
+ /**
+ * @brief Transition image with effect when image is replaced.
+ */
+ void TransitionImageWithEffect();
+
+ /**
+ * @brief Clear the transition animation
+ */
+ void ClearTransitionAnimation();
+
private:
// Undefined
ImageView(const ImageView&);
private:
Toolkit::Visual::Base mVisual;
-
- std::string mUrl; ///< the url for the image if the image came from a URL, empty otherwise
- Property::Map mPropertyMap; ///< the Property::Map if the image came from a Property::Map, empty otherwise
- Property::Map mShaderMap; ///< the Property::Map if the custom shader is set, empty otherwise
- ImageDimensions mImageSize; ///< the image size
-
- bool mImageVisualPaddingSetByTransform : 1; //< Flag to indicate Padding was set using a transform.
- bool mImageViewPixelAreaSetByFittingMode : 1; //< Flag to indicate pixel area was set by fitting Mode
+ Toolkit::Visual::Base mPreviousVisual;
+ Toolkit::Visual::Base mPlaceholderVisual;
+
+ std::string mUrl; ///< the url for the image if the image came from a URL, empty otherwise
+ std::string mPlaceholderUrl; ///< the url for the placeholder image if the image came from a PLACEHOLDER_IMAGE, empty otherwise
+ Property::Map mPropertyMap; ///< the Property::Map if the image came from a Property::Map, empty otherwise
+ Property::Map mShaderMap; ///< the Property::Map if the custom shader is set, empty otherwise
+ ImageDimensions mImageSize; ///< the image size
+
+ Animation mTransitionAnimation; ///< the animation for transition effect
+ float mTransitionTargetAlpha; ///< Keep image's alpha value
+ bool mImageVisualPaddingSetByTransform : 1; ///< Flag to indicate Padding was set using a transform.
+ bool mImageViewPixelAreaSetByFittingMode : 1; ///< Flag to indicate pixel area was set by fitting Mode
+ bool mTransitionEffect :1; ///< Flag to indicate TransitionEffect is enabled
};
} // namespace Internal
enum Flags
{
- IS_ON_SCENE = 1,
- IS_ATLASING_APPLIED = 1 << 1,
- IS_PREMULTIPLIED_ALPHA = 1 << 2,
- IS_SYNCHRONOUS_RESOURCE_LOADING = 1 << 3
+ IS_ON_SCENE = 1,
+ IS_ATLASING_APPLIED = 1 << 1,
+ IS_PREMULTIPLIED_ALPHA = 1 << 2,
+ IS_SYNCHRONOUS_RESOURCE_LOADING = 1 << 3,
};
struct CustomShader
int mFlags;
Toolkit::Visual::ResourceStatus mResourceStatus;
const Toolkit::Visual::Type mType;
- bool mAlwaysUsingBorderline : 1; ///< Whether we need the borderline in shader always.
- bool mAlwaysUsingCornerRadius : 1; ///< Whether we need the corner radius in shader always.
+ bool mAlwaysUsingBorderline : 1; ///< Whether we need the borderline in shader always.
+ bool mAlwaysUsingCornerRadius : 1; ///< Whether we need the corner radius in shader always.
};
} // namespace Visual
#define DALI_TOOLKIT_IMAGE_VIEW_H
/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2023 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.
*/
PRE_MULTIPLIED_ALPHA,
+ /**
+ * @brief name "placeholderImage", type string.
+ *
+ * placeholder image is shown when image view is waiting for the image to load.
+ * @SINCE_2_2.24
+ */
+ PLACEHOLDER_IMAGE,
+
+ /**
+ * @brief name "enableTransitionEffect", type Boolean
+ *
+ * This effect is a crossfade effect when the image is replaced.
+ * the default duration of the crossfade effect is 1.5 seconds.
+ * if the placeholder is enabled, the cross effect applies when the image is changed from a placeholder image to a new image.
+ * if not, the cross effect applies when a new image is shown or is changed from the previous image to a new image.
+ * @SINCE_2_2.24
+ */
+ ENABLE_TRANSITION_EFFECT,
+
// Animatable properties
/**