// test harness headers before dali headers.
#include <dali-toolkit-test-suite-utils.h>
-#include <dali.h>
#include <dali-toolkit/dali-toolkit.h>
#include <dali-toolkit/devel-api/controls/control-devel.h>
+#include <dali-toolkit/devel-api/visuals/image-visual-properties-devel.h>
+#include <dali.h>
-#include <dali/devel-api/adaptor-framework/accessibility.h>
#include <dali/devel-api/adaptor-framework/accessibility-bridge.h>
+#include <dali/devel-api/adaptor-framework/accessibility.h>
#include <dali/devel-api/atspi-interfaces/accessible.h>
#include <automated-tests/src/dali-toolkit-internal/dali-toolkit-test-utils/dbus-wrapper.h>
ToolkitTestApplication application;
auto check_box_button = Toolkit::CheckBoxButton::New();
- auto q = Dali::Accessibility::Accessible::Get( check_box_button );
- DALI_TEST_CHECK( q );
+ auto q = Dali::Accessibility::Accessible::Get(check_box_button);
+ DALI_TEST_CHECK(q);
auto states = q->GetStates();
- DALI_TEST_EQUALS( (int) states[ Dali::Accessibility::State::SELECTABLE ], (int) true, TEST_LOCATION );
+ DALI_TEST_EQUALS((int)states[Dali::Accessibility::State::SELECTABLE], (int)true, TEST_LOCATION);
END_TEST;
}
auto check_box_button = Toolkit::CheckBoxButton::New();
//check_box_button.SetLabelText( "button" );
check_box_button.SetProperty(Toolkit::Button::Property::LABEL, "button");
- auto q = Dali::Accessibility::Accessible::Get( check_box_button );
- DALI_TEST_CHECK( q );
- DALI_TEST_EQUALS( q->GetName(), "button", TEST_LOCATION );
+ auto q = Dali::Accessibility::Accessible::Get(check_box_button);
+ DALI_TEST_CHECK(q);
+ DALI_TEST_EQUALS(q->GetName(), "button", TEST_LOCATION);
END_TEST;
}
parentButton.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
parentButton.SetProperty(Actor::Property::POSITION, Dali::Vector2(0.0f, 0.0f));
parentButton.SetProperty(Actor::Property::SIZE, Dali::Vector2(200.0f, 200.0f));
- application.GetScene().Add( parentButton );
+ application.GetScene().Add(parentButton);
// Toatally inside of parent
auto buttonA = Toolkit::PushButton::New();
auto buttonC = Toolkit::PushButton::New();
buttonC.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT);
buttonC.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
- buttonC.SetProperty(Actor::Property::POSITION, Dali::Vector2(100.0f,100.0f));
+ buttonC.SetProperty(Actor::Property::POSITION, Dali::Vector2(100.0f, 100.0f));
buttonC.SetProperty(Actor::Property::SIZE, Dali::Vector2(200.0f, 200.0f));
parentButton.Add(buttonC);
auto q = Dali::Accessibility::Accessible::Get(buttonA);
DALI_TEST_CHECK(q);
auto states = q->GetStates();
- DALI_TEST_EQUALS((int) states[Dali::Accessibility::State::SHOWING], (int) true, TEST_LOCATION);
+ DALI_TEST_EQUALS((int)states[Dali::Accessibility::State::SHOWING], (int)true, TEST_LOCATION);
q = Dali::Accessibility::Accessible::Get(buttonB);
DALI_TEST_CHECK(q);
states = q->GetStates();
- DALI_TEST_EQUALS((int) states[Dali::Accessibility::State::SHOWING], (int) true, TEST_LOCATION);
+ DALI_TEST_EQUALS((int)states[Dali::Accessibility::State::SHOWING], (int)true, TEST_LOCATION);
q = Dali::Accessibility::Accessible::Get(buttonC);
DALI_TEST_CHECK(q);
states = q->GetStates();
- DALI_TEST_EQUALS((int) states[Dali::Accessibility::State::SHOWING], (int) true, TEST_LOCATION);
+ DALI_TEST_EQUALS((int)states[Dali::Accessibility::State::SHOWING], (int)true, TEST_LOCATION);
// Make SHOWING object invisible
buttonC.SetProperty(Actor::Property::VISIBLE, false);
application.Render(16);
states = q->GetStates();
- DALI_TEST_EQUALS((int) states[Dali::Accessibility::State::SHOWING], (int) false, TEST_LOCATION);
+ DALI_TEST_EQUALS((int)states[Dali::Accessibility::State::SHOWING], (int)false, TEST_LOCATION);
// Make SHOWING parent invisible
parentButton.SetProperty(Actor::Property::VISIBLE, false);
q = Dali::Accessibility::Accessible::Get(buttonA);
DALI_TEST_CHECK(q);
states = q->GetStates();
- DALI_TEST_EQUALS((int) states[Dali::Accessibility::State::SHOWING], (int) false, TEST_LOCATION);
+ DALI_TEST_EQUALS((int)states[Dali::Accessibility::State::SHOWING], (int)false, TEST_LOCATION);
END_TEST;
}
END_TEST;
}
+
+int utcDaliImgSrc(void)
+{
+ ToolkitTestApplication application;
+ const std::string imageSrcKey = "imgSrc";
+ // Check that imgSrc is NOT added for non-image view w/ no additional property
+ {
+ const auto checkBoxButton = Toolkit::CheckBoxButton::New();
+ const auto controlAccessible = Dali::Accessibility::Accessible::Get(checkBoxButton);
+ auto attributes = controlAccessible->GetAttributes();
+ DALI_TEST_CHECK(attributes.find(imageSrcKey) == attributes.end());
+ }
+
+ // Check that imgSrc is NOT added for non-image view w/ additional properties
+ {
+ const auto textLabel = Toolkit::TextLabel::New("Hello");
+ const auto controlAccessible = Dali::Accessibility::Accessible::Get(textLabel);
+ auto attributes = controlAccessible->GetAttributes();
+ DALI_TEST_CHECK(attributes.find(imageSrcKey) == attributes.end());
+ }
+
+ // Check that imgSrc is added for image view w/ Url
+ {
+ const std::string imagePath = "gallery-small-1.jpg";
+ const auto imageView = Toolkit::ImageView::New(imagePath);
+ const auto controlAccessible = Dali::Accessibility::Accessible::Get(imageView);
+ auto attributes = controlAccessible->GetAttributes();
+ DALI_TEST_CHECK(attributes.find(imageSrcKey) != attributes.end());
+ DALI_TEST_EQUALS(attributes[imageSrcKey], imagePath, TEST_LOCATION);
+ }
+
+ // Check that imgSrc is added for image view w/ imageMap; single url case
+ {
+ const std::string imagePathForImageMap = "icon-edit.png";
+ Property::Map imageMap;
+ imageMap[Toolkit::ImageVisual::Property::URL] = imagePathForImageMap;
+ imageMap[Toolkit::ImageVisual::Property::RELEASE_POLICY] = Toolkit::ImageVisual::ReleasePolicy::DETACHED;
+
+ auto imageView = Toolkit::ImageView::New();
+ imageView.SetProperty(Toolkit::ImageView::Property::IMAGE, imageMap);
+
+ const auto controlAccessible = Dali::Accessibility::Accessible::Get(imageView);
+ auto attributes = controlAccessible->GetAttributes();
+ DALI_TEST_CHECK(attributes.find(imageSrcKey) != attributes.end());
+ DALI_TEST_EQUALS(attributes[imageSrcKey], imagePathForImageMap, TEST_LOCATION);
+ }
+
+ // Check that imgSrc is added for image view w/ imageMap; url array returns first element
+ {
+ const std::string image1 = "application-icon-20.png";
+ const std::string image2 = "application-icon-21.png";
+ Property::Map imageMap;
+ Property::Array urls{image1, image2};
+ imageMap[Toolkit::ImageVisual::Property::URL] = urls;
+ imageMap[Toolkit::ImageVisual::Property::RELEASE_POLICY] = Toolkit::ImageVisual::ReleasePolicy::DETACHED;
+
+ auto imageView = Toolkit::ImageView::New();
+ imageView.SetProperty(Toolkit::ImageView::Property::IMAGE, imageMap);
+
+ const auto controlAccessible = Dali::Accessibility::Accessible::Get(imageView);
+ auto attributes = controlAccessible->GetAttributes();
+ DALI_TEST_CHECK(attributes.find(imageSrcKey) != attributes.end());
+ DALI_TEST_EQUALS(attributes[imageSrcKey], image1, TEST_LOCATION);
+ }
+
+ END_TEST;
+}
#include <dali/devel-api/adaptor-framework/accessibility.h>
#include <dali/devel-api/adaptor-framework/accessibility-bridge.h>
#include <dali/devel-api/atspi-interfaces/accessible.h>
+#include <dali/devel-api/atspi-interfaces/component.h>
#include <dali/devel-api/atspi-interfaces/value.h>
#include <dali-toolkit/devel-api/controls/scroll-bar/scroll-bar.h>
+#include <automated-tests/src/dali-toolkit-internal/dali-toolkit-test-utils/accessibility-test-utils.h>
#include <automated-tests/src/dali-toolkit-internal/dali-toolkit-test-utils/dbus-wrapper.h>
using namespace Dali::Accessibility;
int utcDaliAccessibilityProgressBarGetSetCurrent(void)
{
ToolkitTestApplication application;
+ Dali::Accessibility::TestEnableSC(true);
Toolkit::ProgressBar progress_bar = Toolkit::ProgressBar::New();
auto q = Dali::Accessibility::Accessible::Get(progress_bar);
auto x = dynamic_cast< Dali::Accessibility::Value* >( q );
DALI_TEST_CHECK( x );
+ DALI_TEST_CHECK(Dali::Accessibility::Component::DownCast(q)->GrabHighlight());
DALI_TEST_EQUALS( x->GetCurrent(), 0.0, TEST_LOCATION );
DALI_TEST_EQUALS( x->SetCurrent( 2.0 ), false, TEST_LOCATION );
DALI_TEST_EQUALS( x->SetCurrent( 0.25 ), true, TEST_LOCATION );
DALI_TEST_EQUALS( x->GetCurrent(), 0.25, TEST_LOCATION );
DALI_TEST_EQUALS( x->GetValueText().empty(), true, TEST_LOCATION ); // not implemented
+ Dali::Accessibility::TestEnableSC(false);
END_TEST;
}
int utcDaliAccessibilityScrollBarGetSetCurrent(void)
{
ToolkitTestApplication application;
+ Dali::Accessibility::TestEnableSC(true);
// Create a source actor that owns the scroll properties required by the scroll bar
Actor sourceActor = Actor::New();
auto q = Dali::Accessibility::Accessible::Get(scroll_bar);
auto x = dynamic_cast< Dali::Accessibility::Value* >( q );
DALI_TEST_CHECK( x );
+ DALI_TEST_CHECK(Dali::Accessibility::Component::DownCast(q)->GrabHighlight());
DALI_TEST_EQUALS( x->GetCurrent(), 0.0, TEST_LOCATION );
DALI_TEST_EQUALS( x->SetCurrent( 1000.0 ), false, TEST_LOCATION );
DALI_TEST_EQUALS( x->SetCurrent( 50.0 ), false, TEST_LOCATION );
DALI_TEST_EQUALS( x->GetCurrent(), 0.0, TEST_LOCATION );
DALI_TEST_EQUALS( x->GetValueText().empty(), true, TEST_LOCATION ); // not implemented
+ Dali::Accessibility::TestEnableSC(false);
END_TEST;
}
int utcDaliAccessibilitySliderGetSetCurrent(void)
{
ToolkitTestApplication application;
+ Dali::Accessibility::TestEnableSC(true);
Toolkit::Slider slider = Toolkit::Slider::New();
auto q = Dali::Accessibility::Accessible::Get(slider);
auto x = dynamic_cast< Dali::Accessibility::Value* >( q );
DALI_TEST_CHECK( x );
+ DALI_TEST_CHECK(Dali::Accessibility::Component::DownCast(q)->GrabHighlight());
DALI_TEST_EQUALS( x->GetCurrent(), 0.0, TEST_LOCATION );
DALI_TEST_EQUALS( x->SetCurrent( 2.0 ), false, TEST_LOCATION );
DALI_TEST_EQUALS( x->SetCurrent( 0.25 ), true, TEST_LOCATION );
// depending if the new value is greater/less than current value
DALI_TEST_CHECK( x->SetCurrent( 0.2f ) );
DALI_TEST_EQUALS( static_cast<float>( x->GetCurrent() ), marks[2].Get<float>(), TEST_LOCATION );
+
+ Dali::Accessibility::TestEnableSC(false);
END_TEST;
}
END_TEST;
}
+
+int UtcDaliTextControllerMultipleInsert(void)
+{
+ tet_infoline(" UtcDaliTextControllerMultipleInsert");
+ ToolkitTestApplication application;
+
+ // Creates a text controller.
+ ControllerPtr controller = Controller::New();
+
+ ConfigureTextField(controller);
+
+ // Get the implementation of the text controller
+ Controller::Impl& mImpl = Controller::Impl::GetImplementation(*controller.Get());
+
+ DALI_TEST_EQUALS(EventData::INACTIVE, mImpl.mEventData->mState, TEST_LOCATION);
+
+ InputMethodContext inputMethodContext = InputMethodContext::New();
+
+ // When maid thread is busy, multiple event might be executed.
+ InputMethodContext::EventData imfEvent1 = InputMethodContext::EventData(InputMethodContext::PRE_EDIT, "A", 0, 1);
+ InputMethodContext::EventData imfEvent2 = InputMethodContext::EventData(InputMethodContext::PRE_EDIT, "AAAAA", 0, 5);
+ controller->OnInputMethodContextEvent(inputMethodContext, imfEvent1);
+ controller->OnInputMethodContextEvent(inputMethodContext, imfEvent2);
+
+ // Perform a relayout
+ const Size size(application.GetScene().GetSize());
+
+ application.SendNotification();
+ application.Render();
+
+ controller->Relayout(size);
+
+ std::string text;
+ controller->GetText(text);
+
+ DALI_TEST_EQUALS("AAAAA", text, TEST_LOCATION);
+
+ tet_result(TET_PASS);
+
+ END_TEST;
+}
/*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2024 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.
#include "dummy-control.h"
#include <dali-toolkit/dali-toolkit.h>
-#include <dali-toolkit/devel-api/visual-factory/visual-factory.h>
#include <dali-toolkit/devel-api/controls/control-devel.h>
+#include <dali-toolkit/devel-api/visual-factory/visual-factory.h>
namespace Dali
{
-
namespace Toolkit
{
-
DummyControl::DummyControl()
{
}
DummyControl::DummyControl(const DummyControl& control)
-: Control( control )
+: Control(control)
{
}
{
}
-DummyControl DummyControl::DownCast( BaseHandle handle )
+DummyControl DummyControl::DownCast(BaseHandle handle)
{
return Control::DownCast<DummyControl, DummyControlImpl>(handle);
}
DummyControl& DummyControl::operator=(const DummyControl& control)
{
- Control::operator=( control );
+ Control::operator=(control);
return *this;
}
// Used to test signal connections
-void DummyControlImpl::CustomSlot1( Actor actor )
+void DummyControlImpl::CustomSlot1(Actor actor)
{
mCustomSlot1Called = true;
}
-namespace {
-
+namespace
+{
BaseHandle Create()
{
return DummyControlImpl::New();
}
-DALI_TYPE_REGISTRATION_BEGIN( Toolkit::DummyControl, Toolkit::Control, Create );
+DALI_TYPE_REGISTRATION_BEGIN(Toolkit::DummyControl, Toolkit::Control, Create);
DALI_TYPE_REGISTRATION_END()
Dali::PropertyRegistration dummyControlVisualProperty01(
- typeRegistration, "testVisual", Dali::Toolkit::DummyControl::Property::TEST_VISUAL, Dali::Property::MAP, &Dali::Toolkit::DummyControlImpl::SetProperty, &Dali::Toolkit::DummyControlImpl::GetProperty );
+ typeRegistration, "testVisual", Dali::Toolkit::DummyControl::Property::TEST_VISUAL, Dali::Property::MAP, &Dali::Toolkit::DummyControlImpl::SetProperty, &Dali::Toolkit::DummyControlImpl::GetProperty);
Dali::PropertyRegistration dummyControlVisualProperty02(
- typeRegistration, "testVisual2", Dali::Toolkit::DummyControl::Property::TEST_VISUAL2, Dali::Property::MAP, &Dali::Toolkit::DummyControlImpl::SetProperty, &Dali::Toolkit::DummyControlImpl::GetProperty );
+ typeRegistration, "testVisual2", Dali::Toolkit::DummyControl::Property::TEST_VISUAL2, Dali::Property::MAP, &Dali::Toolkit::DummyControlImpl::SetProperty, &Dali::Toolkit::DummyControlImpl::GetProperty);
Dali::PropertyRegistration dummyControlVisualProperty03(
- typeRegistration, "foregroundVisual", Dali::Toolkit::DummyControl::Property::FOREGROUND_VISUAL, Dali::Property::MAP, &Dali::Toolkit::DummyControlImpl::SetProperty, &Dali::Toolkit::DummyControlImpl::GetProperty );
+ typeRegistration, "foregroundVisual", Dali::Toolkit::DummyControl::Property::FOREGROUND_VISUAL, Dali::Property::MAP, &Dali::Toolkit::DummyControlImpl::SetProperty, &Dali::Toolkit::DummyControlImpl::GetProperty);
Dali::PropertyRegistration dummyControlVisualProperty04(
- typeRegistration, "focusVisual", Dali::Toolkit::DummyControl::Property::FOCUS_VISUAL, Dali::Property::MAP, &Dali::Toolkit::DummyControlImpl::SetProperty, &Dali::Toolkit::DummyControlImpl::GetProperty );
+ typeRegistration, "focusVisual", Dali::Toolkit::DummyControl::Property::FOCUS_VISUAL, Dali::Property::MAP, &Dali::Toolkit::DummyControlImpl::SetProperty, &Dali::Toolkit::DummyControlImpl::GetProperty);
Dali::PropertyRegistration dummyControlVisualProperty05(
- typeRegistration, "labelVisual", Dali::Toolkit::DummyControl::Property::LABEL_VISUAL, Dali::Property::MAP, &Dali::Toolkit::DummyControlImpl::SetProperty, &Dali::Toolkit::DummyControlImpl::GetProperty );
+ typeRegistration, "labelVisual", Dali::Toolkit::DummyControl::Property::LABEL_VISUAL, Dali::Property::MAP, &Dali::Toolkit::DummyControlImpl::SetProperty, &Dali::Toolkit::DummyControlImpl::GetProperty);
-}
+} // namespace
DummyControl DummyControlImpl::New()
{
- IntrusivePtr< DummyControlImpl > impl = new DummyControlImpl;
- DummyControl control( *impl );
+ IntrusivePtr<DummyControlImpl> impl = new DummyControlImpl;
+ DummyControl control(*impl);
impl->Initialize();
return control;
}
DummyControlImpl::DummyControlImpl()
-: Control( ControlBehaviour() ),
+: Control(ControlBehaviour()),
mCustomSlot1Called(false)
{
}
{
}
-void DummyControlImpl::RegisterVisual( Property::Index index, Toolkit::Visual::Base visual )
+void DummyControlImpl::RegisterVisual(Property::Index index, Toolkit::Visual::Base visual)
+{
+ DevelControl::RegisterVisual(*this, index, visual);
+
+ VisualIndices::iterator iter = std::find(mRegisteredVisualIndices.begin(), mRegisteredVisualIndices.end(), index);
+ if(iter == mRegisteredVisualIndices.end())
+ {
+ mRegisteredVisualIndices.push_back(index);
+ }
+}
+
+void DummyControlImpl::RegisterVisual(Property::Index index, Toolkit::Visual::Base visual, bool enabled)
{
- DevelControl::RegisterVisual( *this, index, visual );
+ DevelControl::RegisterVisual(*this, index, visual, enabled);
- VisualIndices::iterator iter = std::find( mRegisteredVisualIndices.begin(), mRegisteredVisualIndices.end(), index );
- if( iter == mRegisteredVisualIndices.end() )
+ VisualIndices::iterator iter = std::find(mRegisteredVisualIndices.begin(), mRegisteredVisualIndices.end(), index);
+ if(iter == mRegisteredVisualIndices.end())
{
mRegisteredVisualIndices.push_back(index);
}
}
-void DummyControlImpl::RegisterVisual( Property::Index index, Toolkit::Visual::Base visual, bool enabled )
+void DummyControlImpl::RegisterVisual(Property::Index index, Toolkit::Visual::Base visual, int depthIndex)
{
- DevelControl::RegisterVisual( *this, index, visual, enabled );
+ DevelControl::RegisterVisual(*this, index, visual, depthIndex);
- VisualIndices::iterator iter = std::find( mRegisteredVisualIndices.begin(), mRegisteredVisualIndices.end(), index );
- if( iter == mRegisteredVisualIndices.end() )
+ VisualIndices::iterator iter = std::find(mRegisteredVisualIndices.begin(), mRegisteredVisualIndices.end(), index);
+ if(iter == mRegisteredVisualIndices.end())
{
mRegisteredVisualIndices.push_back(index);
}
}
-void DummyControlImpl::UnregisterVisual( Property::Index index )
+void DummyControlImpl::UnregisterVisual(Property::Index index)
{
- DevelControl::UnregisterVisual( *this, index );
+ DevelControl::UnregisterVisual(*this, index);
- VisualIndices::iterator iter = std::find( mRegisteredVisualIndices.begin(), mRegisteredVisualIndices.end(), index );
- if( iter != mRegisteredVisualIndices.end() )
+ VisualIndices::iterator iter = std::find(mRegisteredVisualIndices.begin(), mRegisteredVisualIndices.end(), index);
+ if(iter != mRegisteredVisualIndices.end())
{
mRegisteredVisualIndices.erase(iter);
}
}
-Toolkit::Visual::Base DummyControlImpl::GetVisual( Property::Index index )
+Toolkit::Visual::Base DummyControlImpl::GetVisual(Property::Index index)
{
- return DevelControl::GetVisual( *this, index );
+ return DevelControl::GetVisual(*this, index);
}
-void DummyControlImpl::EnableVisual( Property::Index index, bool enabled )
+void DummyControlImpl::EnableVisual(Property::Index index, bool enabled)
{
- DevelControl::EnableVisual( *this, index, enabled );
+ DevelControl::EnableVisual(*this, index, enabled);
}
-bool DummyControlImpl::IsVisualEnabled( Property::Index index )
+bool DummyControlImpl::IsVisualEnabled(Property::Index index)
{
- return DevelControl::IsVisualEnabled( *this, index );
+ return DevelControl::IsVisualEnabled(*this, index);
}
-Animation DummyControlImpl::CreateTransition( const Toolkit::TransitionData& transition )
+Animation DummyControlImpl::CreateTransition(const Toolkit::TransitionData& transition)
{
- return DevelControl::CreateTransition( *this, transition );
+ return DevelControl::CreateTransition(*this, transition);
}
-void DummyControlImpl::DoAction( Dali::Property::Index index, Dali::Property::Index action, const Dali::Property::Value attributes )
+void DummyControlImpl::DoAction(Dali::Property::Index index, Dali::Property::Index action, const Dali::Property::Value attributes)
{
- DummyControl control( *this );
- DevelControl::DoAction( control, index, action, attributes);
+ DummyControl control(*this);
+ DevelControl::DoAction(control, index, action, attributes);
}
-void DummyControlImpl::SetProperty( BaseObject* object, Dali::Property::Index index, const Dali::Property::Value& value )
+void DummyControlImpl::SetProperty(BaseObject* object, Dali::Property::Index index, const Dali::Property::Value& value)
{
- Toolkit::DummyControl control = Toolkit::DummyControl::DownCast( Dali::BaseHandle( object ) );
- DummyControlImpl& dummyImpl = static_cast<DummyControlImpl&>(control.GetImplementation());
+ Toolkit::DummyControl control = Toolkit::DummyControl::DownCast(Dali::BaseHandle(object));
+ DummyControlImpl& dummyImpl = static_cast<DummyControlImpl&>(control.GetImplementation());
switch(index)
{
case Toolkit::DummyControl::Property::LABEL_VISUAL:
{
const Property::Map* map = value.GetMap();
- if( map != NULL )
+ if(map != NULL)
{
VisualFactory visualFactory = VisualFactory::Get();
- Visual::Base visual = visualFactory.CreateVisual(*map);
+ Visual::Base visual = visualFactory.CreateVisual(*map);
dummyImpl.RegisterVisual(index, visual);
}
break;
}
}
-Property::Value DummyControlImpl::GetProperty( BaseObject* object, Dali::Property::Index propertyIndex )
+Property::Value DummyControlImpl::GetProperty(BaseObject* object, Dali::Property::Index propertyIndex)
{
- Toolkit::DummyControl control = Toolkit::DummyControl::DownCast( Dali::BaseHandle( object ) );
- DummyControlImpl& dummyImpl = static_cast<DummyControlImpl&>( control.GetImplementation() );
+ Toolkit::DummyControl control = Toolkit::DummyControl::DownCast(Dali::BaseHandle(object));
+ DummyControlImpl& dummyImpl = static_cast<DummyControlImpl&>(control.GetImplementation());
- Visual::Base visual = dummyImpl.GetVisual( propertyIndex );
+ Visual::Base visual = dummyImpl.GetVisual(propertyIndex);
Property::Map map;
- if( visual )
+ if(visual)
{
- visual.CreatePropertyMap( map );
+ visual.CreatePropertyMap(map);
}
Dali::Property::Value value = map;
return value;
}
-
Toolkit::DummyControl Impl::DummyControl::New()
{
- IntrusivePtr< Toolkit::Impl::DummyControl > impl = new Toolkit::Impl::DummyControl;
- Toolkit::DummyControl control( *impl );
+ IntrusivePtr<Toolkit::Impl::DummyControl> impl = new Toolkit::Impl::DummyControl;
+ Toolkit::DummyControl control(*impl);
impl->Initialize();
return control;
}
++destructorCount;
}
-void Impl::DummyControl::OnInitialize() { initializeCalled = true; }
-bool Impl::DummyControl::OnAccessibilityActivated() { activatedCalled = true; return true; }
-bool Impl::DummyControl::OnAccessibilityValueChange( bool isIncrease )
+void Impl::DummyControl::OnInitialize()
+{
+ initializeCalled = true;
+}
+bool Impl::DummyControl::OnAccessibilityActivated()
{
- onAccValueChangeCalled = true; return true;
+ activatedCalled = true;
+ return true;
+}
+bool Impl::DummyControl::OnAccessibilityValueChange(bool isIncrease)
+{
+ onAccValueChangeCalled = true;
+ return true;
}
-void Impl::DummyControl::OnStyleChange( Toolkit::StyleManager styleManager, StyleChange::Type change )
+void Impl::DummyControl::OnStyleChange(Toolkit::StyleManager styleManager, StyleChange::Type change)
{
themeChangeCalled = change == StyleChange::THEME_CHANGE;
- fontChangeCalled = change == StyleChange::DEFAULT_FONT_SIZE_CHANGE;
-}
-void Impl::DummyControl::OnPinch(const PinchGesture& pinch) { pinchCalled = true; }
-void Impl::DummyControl::OnPan(const PanGesture& pan) { panCalled = true; }
-void Impl::DummyControl::OnTap(const TapGesture& tap) { tapCalled = true; }
-void Impl::DummyControl::OnLongPress(const LongPressGesture& longPress) { longPressCalled = true; }
-void Impl::DummyControl::OnSceneConnection( int depth ) { Control::OnSceneConnection( depth ); stageConnectionCalled = true; }
-void Impl::DummyControl::OnSceneDisconnection() { stageDisconnectionCalled = true; Control::OnSceneDisconnection(); }
-void Impl::DummyControl::OnChildAdd(Actor& child) { childAddCalled = true; }
-void Impl::DummyControl::OnChildRemove(Actor& child) { childRemoveCalled = true; }
-void Impl::DummyControl::OnSizeSet(const Vector3& targetSize) { Control::OnSizeSet( targetSize ); sizeSetCalled = true; }
-void Impl::DummyControl::OnSizeAnimation(Animation& animation, const Vector3& targetSize) { Control::OnSizeAnimation( animation, targetSize ); sizeAnimationCalled = true; }
-bool Impl::DummyControl::OnKeyEvent(const KeyEvent& event) { keyEventCalled = true; return false;}
+ fontChangeCalled = change == StyleChange::DEFAULT_FONT_SIZE_CHANGE;
+}
+void Impl::DummyControl::OnPinch(const PinchGesture& pinch)
+{
+ pinchCalled = true;
+}
+void Impl::DummyControl::OnPan(const PanGesture& pan)
+{
+ panCalled = true;
+}
+void Impl::DummyControl::OnTap(const TapGesture& tap)
+{
+ tapCalled = true;
+}
+void Impl::DummyControl::OnLongPress(const LongPressGesture& longPress)
+{
+ longPressCalled = true;
+}
+void Impl::DummyControl::OnSceneConnection(int depth)
+{
+ Control::OnSceneConnection(depth);
+ stageConnectionCalled = true;
+}
+void Impl::DummyControl::OnSceneDisconnection()
+{
+ stageDisconnectionCalled = true;
+ Control::OnSceneDisconnection();
+}
+void Impl::DummyControl::OnChildAdd(Actor& child)
+{
+ childAddCalled = true;
+}
+void Impl::DummyControl::OnChildRemove(Actor& child)
+{
+ childRemoveCalled = true;
+}
+void Impl::DummyControl::OnSizeSet(const Vector3& targetSize)
+{
+ Control::OnSizeSet(targetSize);
+ sizeSetCalled = true;
+}
+void Impl::DummyControl::OnSizeAnimation(Animation& animation, const Vector3& targetSize)
+{
+ Control::OnSizeAnimation(animation, targetSize);
+ sizeAnimationCalled = true;
+}
+bool Impl::DummyControl::OnKeyEvent(const KeyEvent& event)
+{
+ keyEventCalled = true;
+ return false;
+}
void Impl::DummyControl::OnKeyInputFocusGained()
{
if(this->HasKeyInputFocus())
}
}
-void Impl::DummyControl::SetLayout( Property::Index visualIndex, Property::Map& map )
+void Impl::DummyControl::SetLayout(Property::Index visualIndex, Property::Map& map)
{
- Property::Value value( map );
+ Property::Value value(map);
mLayouts[visualIndex] = value;
}
-void Impl::DummyControl::OnRelayout( const Vector2& size, RelayoutContainer& container )
+void Impl::DummyControl::OnRelayout(const Vector2& size, RelayoutContainer& container)
{
- if ( mRelayoutCallback )
+ if(mRelayoutCallback)
{
- mRelayoutCallback( size ); // Execute callback if set
+ mRelayoutCallback(size); // Execute callback if set
}
Property::Map emptyMap;
- for( VisualIndices::iterator iter = mRegisteredVisualIndices.begin(); iter != mRegisteredVisualIndices.end() ; ++iter )
+ for(VisualIndices::iterator iter = mRegisteredVisualIndices.begin(); iter != mRegisteredVisualIndices.end(); ++iter)
{
- Visual::Base visual = GetVisual(*iter);
- Property::Value value = mLayouts[*iter];
- Property::Map* map = NULL;
+ Visual::Base visual = GetVisual(*iter);
+ Property::Value value = mLayouts[*iter];
+ Property::Map* map = NULL;
- if( value.GetType() != Property::NONE )
+ if(value.GetType() != Property::NONE)
{
map = value.GetMap();
}
- if( map == NULL )
+ if(map == NULL)
{
map = &emptyMap;
}
- visual.SetTransformAndSize( *map, size );
+ visual.SetTransformAndSize(*map, size);
}
}
-void Impl::DummyControl::SetRelayoutCallback( RelayoutCallbackFunc callback )
+void Impl::DummyControl::SetRelayoutCallback(RelayoutCallbackFunc callback)
{
mRelayoutCallback = callback;
}
{
Vector2 currentSize;
- for( auto elem : mRegisteredVisualIndices )
+ for(auto elem : mRegisteredVisualIndices)
{
- Vector2 naturalSize;
+ Vector2 naturalSize;
Visual::Base visual = GetVisual(elem);
- visual.GetNaturalSize( naturalSize );
- currentSize.width = std::max( naturalSize.width, currentSize.width );
- currentSize.height = std::max( naturalSize.height, currentSize.height );
+ visual.GetNaturalSize(naturalSize);
+ currentSize.width = std::max(naturalSize.width, currentSize.width);
+ currentSize.height = std::max(naturalSize.height, currentSize.height);
}
- return Vector3( currentSize );
+ return Vector3(currentSize);
}
-
-
-DummyControl DummyControl::New( bool override )
+DummyControl DummyControl::New(bool override)
{
DummyControl control;
- if (override)
+ if(override)
{
control = Impl::DummyControl::New();
}
return control;
}
-DummyControl::DummyControl( DummyControlImpl& implementation )
-: Control( implementation )
+DummyControl::DummyControl(DummyControlImpl& implementation)
+: Control(implementation)
{
}
-DummyControl::DummyControl( Dali::Internal::CustomActor* internal )
-: Control( internal )
+DummyControl::DummyControl(Dali::Internal::CustomActor* internal)
+: Control(internal)
{
VerifyCustomActorPointer<DummyControlImpl>(internal);
}
#define DALI_TOOLKIT_TEST_DUMMY_CONTROL_H
/*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2024 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.
namespace Dali
{
-
namespace Toolkit
{
-
class DummyControlImpl;
class TransitionData;
enum PropertyRange
{
PROPERTY_START_INDEX = Control::CONTROL_PROPERTY_END_INDEX + 1, ///< @SINCE_1_0.0
- PROPERTY_END_INDEX = PROPERTY_START_INDEX + 1000 ///< Reserve property index
+ PROPERTY_END_INDEX = PROPERTY_START_INDEX + 1000 ///< Reserve property index
};
struct Property
DummyControl(const DummyControl& control);
~DummyControl();
- static DummyControl New( bool override = false );
-
- static DummyControl DownCast( BaseHandle handle );
+ static DummyControl New(bool override = false);
+ static DummyControl DownCast(BaseHandle handle);
DummyControl& operator=(const DummyControl& control);
public: // Not intended for application developers
-
- DummyControl( DummyControlImpl& implementation );
- DummyControl( Dali::Internal::CustomActor* internal );
+ DummyControl(DummyControlImpl& implementation);
+ DummyControl(Dali::Internal::CustomActor* internal);
};
/**
class DummyControlImpl : public Toolkit::Internal::Control
{
public:
-
static DummyControl New();
public:
- inline void EnableGestureDetection(GestureType::Value type) { Internal::Control::EnableGestureDetection(type); }
- inline void DisableGestureDetection(GestureType::Value type) { Internal::Control::DisableGestureDetection(type); }
- inline PinchGestureDetector GetPinchGestureDetector() const { return Internal::Control::GetPinchGestureDetector(); }
- inline PanGestureDetector GetPanGestureDetector() const { return Internal::Control::GetPanGestureDetector(); }
- inline TapGestureDetector GetTapGestureDetector() const { return Internal::Control::GetTapGestureDetector(); }
- inline LongPressGestureDetector GetLongPressGestureDetector() const { return Internal::Control::GetLongPressGestureDetector(); }
-
- void RegisterVisual( Property::Index index, Toolkit::Visual::Base visual);
- void RegisterVisual( Property::Index index, Toolkit::Visual::Base visual, bool enabled );
- void UnregisterVisual( Property::Index index );
- void EnableVisual( Property::Index index, bool enabled );
- bool IsVisualEnabled( Property::Index index );
- int GetVisualCount();
- Toolkit::Visual::Base GetVisual( Property::Index index );
- Animation CreateTransition( const Toolkit::TransitionData& transition );
- void DoAction( Dali::Property::Index index, Dali::Property::Index action, const Dali::Property::Value attributes );
-
- static void SetProperty( BaseObject* object, Dali::Property::Index index, const Dali::Property::Value& value );
-
- static Property::Value GetProperty( BaseObject* object, Dali::Property::Index propertyIndex );
+ inline void EnableGestureDetection(GestureType::Value type)
+ {
+ Internal::Control::EnableGestureDetection(type);
+ }
+ inline void DisableGestureDetection(GestureType::Value type)
+ {
+ Internal::Control::DisableGestureDetection(type);
+ }
+ inline PinchGestureDetector GetPinchGestureDetector() const
+ {
+ return Internal::Control::GetPinchGestureDetector();
+ }
+ inline PanGestureDetector GetPanGestureDetector() const
+ {
+ return Internal::Control::GetPanGestureDetector();
+ }
+ inline TapGestureDetector GetTapGestureDetector() const
+ {
+ return Internal::Control::GetTapGestureDetector();
+ }
+ inline LongPressGestureDetector GetLongPressGestureDetector() const
+ {
+ return Internal::Control::GetLongPressGestureDetector();
+ }
+
+ void RegisterVisual(Property::Index index, Toolkit::Visual::Base visual);
+ void RegisterVisual(Property::Index index, Toolkit::Visual::Base visual, bool enabled);
+ void RegisterVisual(Property::Index index, Toolkit::Visual::Base visual, int depthIndex);
+ void UnregisterVisual(Property::Index index);
+ void EnableVisual(Property::Index index, bool enabled);
+ bool IsVisualEnabled(Property::Index index);
+ int GetVisualCount();
+ Toolkit::Visual::Base GetVisual(Property::Index index);
+ Animation CreateTransition(const Toolkit::TransitionData& transition);
+ void DoAction(Dali::Property::Index index, Dali::Property::Index action, const Dali::Property::Value attributes);
+
+ static void SetProperty(BaseObject* object, Dali::Property::Index index, const Dali::Property::Value& value);
+
+ static Property::Value GetProperty(BaseObject* object, Dali::Property::Index propertyIndex);
// Used to test signal connections
- void CustomSlot1( Actor actor );
+ void CustomSlot1(Actor actor);
- bool mCustomSlot1Called;
+ bool mCustomSlot1Called;
typedef std::vector<Property::Index> VisualIndices;
- VisualIndices mRegisteredVisualIndices;
+ VisualIndices mRegisteredVisualIndices;
protected:
-
DummyControlImpl();
~DummyControlImpl() override;
namespace Impl
{
-
/**
* Cannot create an instance of Internal::Control, so use this dummy class for the implementation.
* This class DOES override Internal::Control's behaviour.
class DummyControl : public Toolkit::DummyControlImpl
{
public:
-
- typedef std::function<void( Size )> RelayoutCallbackFunc;
+ typedef std::function<void(Size)> RelayoutCallbackFunc;
static Toolkit::DummyControl New();
- void SetLayout( Property::Index visualIndex, Property::Map& map );
+ void SetLayout(Property::Index visualIndex, Property::Map& map);
- void SetRelayoutCallback( RelayoutCallbackFunc callback );
+ void SetRelayoutCallback(RelayoutCallbackFunc callback);
private:
-
DummyControl();
~DummyControl() override;
private: // From Internal::Control
-
void OnInitialize() override;
bool OnAccessibilityActivated() override;
- bool OnAccessibilityValueChange( bool isIncrease ) override;
+ bool OnAccessibilityValueChange(bool isIncrease) override;
- void OnStyleChange( Toolkit::StyleManager styleManager, StyleChange::Type change ) override;
- void OnPinch(const PinchGesture& pinch) override;
- void OnPan(const PanGesture& pan) override;
- void OnTap(const TapGesture& tap) override;
- void OnLongPress(const LongPressGesture& longPress) override;
+ void OnStyleChange(Toolkit::StyleManager styleManager, StyleChange::Type change) override;
+ void OnPinch(const PinchGesture& pinch) override;
+ void OnPan(const PanGesture& pan) override;
+ void OnTap(const TapGesture& tap) override;
+ void OnLongPress(const LongPressGesture& longPress) override;
Vector3 GetNaturalSize() override;
- bool OnKeyEvent(const KeyEvent& event) override;
+ bool OnKeyEvent(const KeyEvent& event) override;
private: // From CustomActorImpl
-
- void OnSceneConnection( int depth ) override;
+ void OnSceneConnection(int depth) override;
void OnSceneDisconnection() override;
void OnChildAdd(Actor& child) override;
void OnChildRemove(Actor& child) override;
void OnSizeAnimation(Animation& animation, const Vector3& targetSize) override;
void OnKeyInputFocusGained() override;
void OnKeyInputFocusLost() override;
- void OnRelayout( const Vector2& size, RelayoutContainer& container ) override;
+ void OnRelayout(const Vector2& size, RelayoutContainer& container) override;
- DALI_INTERNAL DummyControl( const DummyControl& );
- DALI_INTERNAL DummyControl& operator=( const DummyControl& );
+ DALI_INTERNAL DummyControl(const DummyControl&);
+ DALI_INTERNAL DummyControl& operator=(const DummyControl&);
public:
-
- bool initializeCalled;
- bool activatedCalled;
- bool onAccValueChangeCalled;
- bool themeChangeCalled;
- bool fontChangeCalled;
- bool pinchCalled;
- bool panCalled;
- bool tapCalled;
- bool longPressCalled;
- bool stageConnectionCalled;
- bool stageDisconnectionCalled;
- bool childAddCalled;
- bool childRemoveCalled;
- bool sizeSetCalled;
- bool sizeAnimationCalled;
- bool hoverEventCalled;
- bool wheelEventCalled;
- bool keyEventCalled;
- bool keyInputFocusGained;
- bool keyInputFocusLost;
+ bool initializeCalled;
+ bool activatedCalled;
+ bool onAccValueChangeCalled;
+ bool themeChangeCalled;
+ bool fontChangeCalled;
+ bool pinchCalled;
+ bool panCalled;
+ bool tapCalled;
+ bool longPressCalled;
+ bool stageConnectionCalled;
+ bool stageDisconnectionCalled;
+ bool childAddCalled;
+ bool childRemoveCalled;
+ bool sizeSetCalled;
+ bool sizeAnimationCalled;
+ bool hoverEventCalled;
+ bool wheelEventCalled;
+ bool keyEventCalled;
+ bool keyInputFocusGained;
+ bool keyInputFocusLost;
static int constructorCount;
static int destructorCount;
- Property::Map mLayouts;
+ Property::Map mLayouts;
RelayoutCallbackFunc mRelayoutCallback;
-
};
} // namespace Impl
void RemoveIdle(CallbackBase* callback);
void RunIdles();
+ void RequestUpdateOnce();
+
static Integration::Scene GetScene(Dali::Window window);
Dali::RenderSurfaceInterface& GetSurface();
mReturnCallbacks.Swap(reusedCallbacks);
}
+void Adaptor::RequestUpdateOnce()
+{
+ if(mTestApplication)
+ {
+ auto scene = mTestApplication->GetScene();
+ if(scene)
+ {
+ tet_printf("Adaptor::RequestUpdateOnce()\n");
+ scene.KeepRendering(0.0f);
+ }
+ }
+}
+
Dali::RenderSurfaceInterface& Adaptor::GetSurface()
{
DALI_ASSERT_ALWAYS(!mWindows.empty());
Dali::Clipboard::DataReceivedSignalType& DataReceivedSignal();
/**
+ * @copydoc Dali::Clipboard::HasType()
+ */
+ bool HasType(const std::string& mimeType);
+
+ /**
* @copydoc Dali::Clipboard::SetData()
*/
bool SetData(const Dali::Clipboard::ClipData& clipData);
return mDataReceivedSignal;
}
+bool Clipboard::HasType(const std::string& mimeType)
+{
+ return mMimeType == mimeType ? true : false;
+}
+
bool Clipboard::SetData(const Dali::Clipboard::ClipData& clipData)
{
mMimeType = clipData.GetMimeType();
DataReceivedSignalType& DataReceivedSignal();
/**
+ * @brief Check if there is data in the clipboard with a given mime type.
+ * @param[in] mimeType mime type to search for.
+ * @return bool true if there is data, otherwise false.
+ */
+ bool HasType(const std::string& mimeType);
+
+ /**
* @brief Send the given data to the clipboard.
* @param[in] clipData data to send to the clipboard
* @return bool true if the internal clipboard sending was successful.
value = resultMap.Find(Toolkit::DevelImageVisual::Property::TOTAL_FRAME_NUMBER, "totalFrameNumber");
DALI_TEST_CHECK(value);
- DALI_TEST_EQUALS(value->Get<int>(), 4, TEST_LOCATION);
+ DALI_TEST_EQUALS(value->Get<int>(), -1, TEST_LOCATION);
value = resultMap.Find(Toolkit::DevelVisual::Property::BORDERLINE_WIDTH, "borderlineWidth");
DALI_TEST_CHECK(value);
END_TEST;
}
-
int UtcDaliAnimatedImageVisualControlVisibilityChanged(void)
{
ToolkitTestApplication application;
DALI_TEST_EQUALS(value->Get<int>(), 0, TEST_LOCATION);
END_TEST;
-}
\ No newline at end of file
+}
+
+int UtcDaliAnimatedImageVisualFrameCountBeforeLoadingFinished(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline("UtcDaliAnimatedImageVisualFrameCountBeforeLoadingFinished");
+
+ Property::Map propertyMap;
+ propertyMap.Add(Toolkit::Visual::Property::TYPE, DevelVisual::ANIMATED_IMAGE)
+ .Add(ImageVisual::Property::URL, TEST_GIF_FILE_NAME)
+ .Add(ImageVisual::Property::SYNCHRONOUS_LOADING, false);
+
+ Visual::Base visual = VisualFactory::Get().CreateVisual(propertyMap);
+ DALI_TEST_CHECK(visual);
+
+ Property::Map resultMap1;
+ visual.CreatePropertyMap(resultMap1);
+ Property::Value* value1 = resultMap1.Find(DevelImageVisual::Property::TOTAL_FRAME_NUMBER);
+ DALI_TEST_CHECK(value1);
+ DALI_TEST_EQUALS(value1->Get<int>(), -1, Math::MACHINE_EPSILON_100, TEST_LOCATION);
+
+ DummyControl actor = DummyControl::New(true);
+ DummyControlImpl& dummyImpl = static_cast<DummyControlImpl&>(actor.GetImplementation());
+ dummyImpl.RegisterVisual(DummyControl::Property::TEST_VISUAL, visual);
+
+ Property::Map resultMap2;
+ visual.CreatePropertyMap(resultMap2);
+ Property::Value* value2 = resultMap2.Find(DevelImageVisual::Property::TOTAL_FRAME_NUMBER);
+ DALI_TEST_CHECK(value2);
+ DALI_TEST_EQUALS(value2->Get<int>(), -1, Math::MACHINE_EPSILON_100, TEST_LOCATION);
+
+ Vector2 controlSize(20.f, 30.f);
+ actor.SetProperty(Actor::Property::SIZE, controlSize);
+
+ application.GetScene().Add(actor);
+
+ application.SendNotification();
+ application.Render();
+
+ // Trigger count is 2 - load & render a frame
+ DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(2), true, TEST_LOCATION);
+
+ Property::Map resultMap3;
+ visual.CreatePropertyMap(resultMap3);
+ Property::Value* value3 = resultMap3.Find(DevelImageVisual::Property::TOTAL_FRAME_NUMBER);
+ DALI_TEST_CHECK(value3);
+ DALI_TEST_EQUALS(value3->Get<int>(), 4, Math::MACHINE_EPSILON_100, TEST_LOCATION);
+
+ END_TEST;
+}
}
}
+/**
+ * @brief Retry function to get playrange until expect values comes.
+ * @note This function might consume EventThreadTrigger.
+ *
+ * @param[in] dummyControl The control for test.
+ * @param[in] expectStartFrame Expect start frame.
+ * @param[in] expectEndFrame Expect end frame.
+ * @param[in] retrialFrames Retry required frame value list.
+ * @param[in] testLocation Location info of UTC. It will be used when UTC failed.
+ */
+void CheckAndRetryPlayRange(DummyControl dummyControl, int expectStartFrame, int expectEndFrame, std::vector<std::pair<int, int>> retrialFrames, const char* testLocation)
+{
+ int tryCount = 0;
+ int tryCountMax = 25;
+ while(++tryCount <= tryCountMax)
+ {
+ Property::Map resultMap = dummyControl.GetProperty<Property::Map>(DummyControl::Property::TEST_VISUAL);
+
+ Property::Value* value = resultMap.Find(DevelImageVisual::Property::PLAY_RANGE, Property::ARRAY);
+ DALI_TEST_CHECK(value);
+
+ Property::Array* result = value->GetArray();
+ DALI_TEST_CHECK(result);
+ DALI_TEST_EQUALS(result->Count(), 2, TEST_LOCATION);
+
+ bool tryAgain = false;
+ for(auto& framePair : retrialFrames)
+ {
+ if(result->GetElementAt(0).Get<int>() == framePair.first && result->GetElementAt(1).Get<int>() == framePair.second)
+ {
+ tryAgain = true;
+ break;
+ }
+ }
+ if(tryAgain)
+ {
+ tet_printf("Retry to get value again! [%d]\n", tryCount);
+ // Dummy sleep 1 second.
+ Test::WaitForEventThreadTrigger(1, 1);
+ continue;
+ }
+
+ DALI_TEST_EQUALS(result->GetElementAt(0).Get<int>(), expectStartFrame, testLocation);
+ DALI_TEST_EQUALS(result->GetElementAt(1).Get<int>(), expectEndFrame, testLocation);
+ break;
+ }
+ DALI_TEST_CHECK(tryCount <= tryCountMax);
+}
+
+/**
+ * @brief Retry function to get current frame until expect values comes.
+ * @note This function might consume EventThreadTrigger.
+ *
+ * @param[in] dummyControl The control for test.
+ * @param[in] expectCurrentFrame Expect current frame.
+ * @param[in] retrialFrames Retry required frame value list.
+ * @param[in] testLocation Location info of UTC. It will be used when UTC failed.
+ */
+void CheckAndRetryCurrentFrame(DummyControl dummyControl, int expectCurrentFrame, std::vector<int> retrialFrames, const char* testLocation)
+{
+ int tryCount = 0;
+ int tryCountMax = 25;
+ while(++tryCount <= tryCountMax)
+ {
+ Property::Map resultMap = dummyControl.GetProperty<Property::Map>(DummyControl::Property::TEST_VISUAL);
+
+ Property::Value* value = resultMap.Find(DevelImageVisual::Property::CURRENT_FRAME_NUMBER, Property::INTEGER);
+ DALI_TEST_CHECK(value);
+
+ int32_t result = value->Get<int32_t>();
+
+ bool tryAgain = false;
+ for(auto& frame : retrialFrames)
+ {
+ if(result == frame)
+ {
+ tryAgain = true;
+ break;
+ }
+ }
+ if(tryAgain)
+ {
+ tet_printf("Retry to get value again! [%d]\n", tryCount);
+ // Dummy sleep 1 second.
+ Test::WaitForEventThreadTrigger(1, 1);
+ continue;
+ }
+
+ DALI_TEST_EQUALS(result, expectCurrentFrame, testLocation);
+ break;
+ }
+ DALI_TEST_CHECK(tryCount <= tryCountMax);
+}
+
} // namespace
int UtcDaliVisualFactoryGetAnimatedVectorImageVisual01(void)
// Trigger count is 2 - load & render a frame
DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(2), true, TEST_LOCATION);
+ // There might be 1 event triggered if start frame is not 0, and render frame spend long time.
+ // if ForceRenderOnce triggered before render complete, renderer count could be zero.
+ // Consume it if required.
+ if(actor.GetRendererCount() == 0)
+ {
+ tet_printf("Warning! render frame trigger not comes yet. Let we wait one more time.\n");
+ Test::WaitForEventThreadTrigger(1, 1);
+ }
+
// renderer is added to actor
- DALI_TEST_CHECK(actor.GetRendererCount() == 1u);
+ DALI_TEST_EQUALS(actor.GetRendererCount(), 1u, TEST_LOCATION);
Renderer renderer = actor.GetRendererAt(0u);
DALI_TEST_CHECK(renderer);
.Add("stopBehavior", DevelImageVisual::StopBehavior::FIRST_FRAME)
.Add("loopingMode", DevelImageVisual::LoopingMode::AUTO_REVERSE)
.Add("redrawInScalingDown", false)
+ .Add("enableFrameCache", false)
+ .Add("notifyAfterRasterization", false)
.Add("cornerRadius", cornerRadius)
.Add("borderlineWidth", borderlineWidth)
.Add("borderlineColor", borderlineColor)
.Add("borderlineOffset", borderlineOffset)
.Add("desiredWidth", desiredWidth)
- .Add("desiredHeight", desiredHeight)
- .Add("useFixedCache", false);
+ .Add("desiredHeight", desiredHeight);
Visual::Base visual = VisualFactory::Get().CreateVisual(propertyMap);
DALI_TEST_CHECK(visual);
// Trigger count is 1 - render a frame
DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION);
+ // There might be 1 event triggered if start frame is not 0, and render frame spend long time.
+ // if ForceRenderOnce triggered before render complete, renderer count could be zero.
+ // Consume it if required.
+ if(actor.GetRendererCount() == 0)
+ {
+ tet_printf("Warning! render frame trigger not comes yet. Let we wait one more time.\n");
+ Test::WaitForEventThreadTrigger(1, 1);
+ }
+
// renderer is added to actor
- DALI_TEST_CHECK(actor.GetRendererCount() == 1u);
+ DALI_TEST_EQUALS(actor.GetRendererCount(), 1u, TEST_LOCATION);
Renderer renderer = actor.GetRendererAt(0u);
DALI_TEST_CHECK(renderer);
DALI_TEST_CHECK(value);
DALI_TEST_CHECK(value->Get<bool>() == false);
+ value = resultMap.Find(DevelImageVisual::Property::ENABLE_FRAME_CACHE, Property::BOOLEAN);
+ DALI_TEST_CHECK(value);
+ DALI_TEST_CHECK(value->Get<bool>() == false);
+
+ value = resultMap.Find(DevelImageVisual::Property::NOTIFY_AFTER_RASTERIZATION, Property::BOOLEAN);
+ DALI_TEST_CHECK(value);
+ DALI_TEST_CHECK(value->Get<bool>() == false);
+
value = resultMap.Find(DevelVisual::Property::CORNER_RADIUS, Property::VECTOR4);
DALI_TEST_CHECK(value);
DALI_TEST_EQUALS(value->Get<Vector4>(), Vector4(cornerRadius, cornerRadius, cornerRadius, cornerRadius), TEST_LOCATION);
DALI_TEST_CHECK(value);
DALI_TEST_CHECK(value->Get<bool>() == false); // Check default value
+ value = resultMap.Find(DevelImageVisual::Property::NOTIFY_AFTER_RASTERIZATION, Property::BOOLEAN);
+ DALI_TEST_CHECK(value);
+ DALI_TEST_CHECK(value->Get<bool>() == false); // Check default value
+
value = resultMap.Find(DevelImageVisual::Property::REDRAW_IN_SCALING_DOWN, Property::BOOLEAN);
DALI_TEST_CHECK(value);
DALI_TEST_CHECK(value->Get<bool>() == true); // Check default value
DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(2), true, TEST_LOCATION);
// renderer is added to actor
- DALI_TEST_CHECK(actor.GetRendererCount() == 1u);
+ DALI_TEST_EQUALS(actor.GetRendererCount(), 1u, TEST_LOCATION);
Renderer renderer = actor.GetRendererAt(0u);
DALI_TEST_CHECK(renderer);
// Trigger count is 2 - load & render a frame
DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(2), true, TEST_LOCATION);
+ // There might be 1 event triggered if start frame is not 0, and render frame spend long time.
+ // if ForceRenderOnce triggered before render complete, renderer count could be zero.
+ // Consume it if required.
+ if(actor.GetRendererCount() == 0)
+ {
+ tet_printf("Warning! render frame trigger not comes yet. Let we wait one more time.\n");
+ Test::WaitForEventThreadTrigger(1, 1);
+ }
+
// renderer is added to actor
- DALI_TEST_CHECK(actor.GetRendererCount() == 1u);
+ DALI_TEST_EQUALS(actor.GetRendererCount(), 1u, TEST_LOCATION);
Renderer renderer = actor.GetRendererAt(0u);
DALI_TEST_CHECK(renderer);
// Set invalid play range
array.Clear();
array.PushBack(1);
- array.PushBack(100);
+ array.PushBack(totalFrameNumber + 100);
attributes.Clear();
attributes.Add(DevelImageVisual::Property::PLAY_RANGE, array);
DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION);
- map = actor.GetProperty<Property::Map>(DummyControl::Property::TEST_VISUAL);
- value = map.Find(DevelImageVisual::Property::PLAY_RANGE);
-
- result = value->GetArray();
- result->GetElementAt(0).Get(resultStartFrame);
- result->GetElementAt(1).Get(resultEndFrame);
-
- DALI_TEST_EQUALS(resultStartFrame, 1, TEST_LOCATION);
- DALI_TEST_EQUALS(resultEndFrame, totalFrameNumber - 1, TEST_LOCATION); // Should be clamped
+ // Should be clamped.
+ CheckAndRetryPlayRange(actor, 1, totalFrameNumber - 1, {{startFrame, endFrame}}, TEST_LOCATION);
DevelControl::DoAction(actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedVectorImageVisual::Action::PAUSE, Property::Map());
DevelControl::DoAction(actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedVectorImageVisual::Action::JUMP_TO, 3);
- // To make event trigger
- actor.SetProperty(Actor::Property::SIZE, Vector2(20.0f, 20.0f));
-
application.SendNotification();
application.Render();
+ // Jump to action when paused, will make one or more event trigger
DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION);
- map = actor.GetProperty<Property::Map>(DummyControl::Property::TEST_VISUAL);
- value = map.Find(DevelImageVisual::Property::CURRENT_FRAME_NUMBER);
- DALI_TEST_EQUALS(value->Get<int>(), 3, TEST_LOCATION);
+ // Test whether current frame is 3.
+ CheckAndRetryCurrentFrame(actor, 3, {0, 1}, TEST_LOCATION);
array.Clear();
array.PushBack(0);
DevelControl::DoAction(actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelVisual::Action::UPDATE_PROPERTY, attributes);
// To make event trigger
- actor.SetProperty(Actor::Property::SIZE, Vector2(10.0f, 10.0f));
+ actor.SetProperty(Actor::Property::SIZE, Vector2(20.0f, 20.0f));
application.SendNotification();
application.Render();
DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION);
- map = actor.GetProperty<Property::Map>(DummyControl::Property::TEST_VISUAL);
- value = map.Find(DevelImageVisual::Property::PLAY_RANGE);
-
- result = value->GetArray();
- result->GetElementAt(0).Get(resultStartFrame);
- result->GetElementAt(1).Get(resultEndFrame);
-
- DALI_TEST_EQUALS(0, resultStartFrame, TEST_LOCATION);
- DALI_TEST_EQUALS(2, resultEndFrame, TEST_LOCATION);
+ CheckAndRetryPlayRange(actor, 0, 2, {{1, totalFrameNumber - 1}}, TEST_LOCATION);
+ map = actor.GetProperty<Property::Map>(DummyControl::Property::TEST_VISUAL);
value = map.Find(DevelImageVisual::Property::CURRENT_FRAME_NUMBER);
DALI_TEST_EQUALS(value->Get<int>(), 2, TEST_LOCATION); // CURRENT_FRAME_NUMBER should be changed also.
// Trigger count is 2 - load & render a frame
DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(2), true, TEST_LOCATION);
+ // There might be 1 event triggered if start frame is not 0, and render frame spend long time.
+ // if ForceRenderOnce triggered before render complete, renderer count could be zero.
+ // Consume it if required.
+ if(actor.GetRendererCount() == 0)
+ {
+ tet_printf("Warning! render frame trigger not comes yet. Let we wait one more time.\n");
+ Test::WaitForEventThreadTrigger(1, 1);
+ }
+
// renderer is added to actor
- DALI_TEST_CHECK(actor.GetRendererCount() == 1u);
+ DALI_TEST_EQUALS(actor.GetRendererCount(), 1u, TEST_LOCATION);
Renderer renderer = actor.GetRendererAt(0u);
DALI_TEST_CHECK(renderer);
DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(2), true, TEST_LOCATION);
// renderer is added to actor
- DALI_TEST_CHECK(actor.GetRendererCount() == 1u);
+ DALI_TEST_EQUALS(actor.GetRendererCount(), 1u, TEST_LOCATION);
Renderer renderer = actor.GetRendererAt(0u);
DALI_TEST_CHECK(renderer);
END_TEST;
}
-int UtcDaliAnimatedVectorImageVisualUsedFixedCache(void)
+int UtcDaliAnimatedVectorImageVisualEnableFrameCache(void)
{
ToolkitTestApplication application;
- tet_infoline("UtcDaliAnimatedVectorImageVisualUsedFixedCache");
+ tet_infoline("UtcDaliAnimatedVectorImageVisualEnableFrameCache");
Property::Map propertyMap;
propertyMap.Add(Toolkit::Visual::Property::TYPE, DevelVisual::ANIMATED_VECTOR_IMAGE)
DummyControl actor = DummyControl::New(true);
DummyControlImpl& dummyImpl = static_cast<DummyControlImpl&>(actor.GetImplementation());
dummyImpl.RegisterVisual(DummyControl::Property::TEST_VISUAL, visual);
- //actor.SetProperty(Actor::Property::SIZE, Vector2(10.0f, 10.0f));
application.GetScene().Add(actor);
application.SendNotification();
application.Render();
- // Trigger count is 1 - render a frame
+ // Trigger count is 1 - load
DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION);
Vector2 controlSize(200.f, 200.f);
application.SendNotification();
application.Render();
- // Trigger count is 1 - load
+ // Trigger count is 1 - render a frame
DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION);
// renderer is added to actor
END_TEST;
}
-int UtcDaliAnimatedVectorImageVisualUsedFixedCacheFailed(void)
+int UtcDaliAnimatedVectorImageVisualEnableFrameCacheFailed(void)
{
ToolkitTestApplication application;
- tet_infoline("UtcDaliAnimatedVectorImageVisualUsedFixedCacheFailed");
+ tet_infoline("UtcDaliAnimatedVectorImageVisualEnableFrameCacheFailed");
Property::Map propertyMap;
propertyMap.Add(Toolkit::Visual::Property::TYPE, DevelVisual::ANIMATED_VECTOR_IMAGE)
END_TEST;
}
+int UtcDaliAnimatedVectorImageVisualNotifyAfterRasterization(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline("UtcDaliAnimatedVectorImageVisualNotifyAfterRasterization");
+
+ 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::NOTIFY_AFTER_RASTERIZATION, true)
+ .Add(ImageVisual::Property::SYNCHRONOUS_LOADING, false);
+
+ 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);
+
+ application.GetScene().Add(actor);
+
+ application.SendNotification();
+ application.Render();
+
+ // Trigger count is 1 - load
+ DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION);
+
+ Vector2 controlSize(200.f, 200.f);
+ actor.SetProperty(Actor::Property::SIZE, controlSize);
+
+ application.SendNotification();
+ application.Render();
+
+ // Trigger count is 1 - render a frame
+ DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION);
+
+ // Play animation
+ Property::Map attributes;
+ DevelControl::DoAction(actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedVectorImageVisual::Action::PLAY, attributes);
+
+ application.SendNotification();
+ application.Render();
+
+ // There might be 1 event triggered if render frame spend long time.
+ // if ForceRenderOnce triggered before render complete, renderer count could be zero.
+ // Consume it if required.
+ if(actor.GetRendererCount() == 0)
+ {
+ tet_printf("Warning! render frame trigger not comes yet. Let we wait one more time.\n");
+ Test::WaitForEventThreadTrigger(1, 1);
+ }
+
+ // renderer is added to actor
+ DALI_TEST_CHECK(actor.GetRendererCount() == 1u);
+ Renderer renderer = actor.GetRendererAt(0u);
+ DALI_TEST_CHECK(renderer);
+
+ // Check renderer behavior
+ DALI_TEST_CHECK(renderer.GetProperty<int>(DevelRenderer::Property::RENDERING_BEHAVIOR) == DevelRenderer::Rendering::IF_REQUIRED);
+
+ Property::Map map = actor.GetProperty<Property::Map>(DummyControl::Property::TEST_VISUAL);
+ Property::Value* value = map.Find(DevelImageVisual::Property::NOTIFY_AFTER_RASTERIZATION);
+ DALI_TEST_CHECK(value->Get<bool>() == true);
+
+ propertyMap.Clear();
+ propertyMap.Add(DevelImageVisual::Property::NOTIFY_AFTER_RASTERIZATION, false);
+ DevelControl::DoAction(actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelVisual::Action::UPDATE_PROPERTY, propertyMap);
+
+ application.SendNotification();
+ application.Render();
+
+ // Check renderer behavior again
+ DALI_TEST_CHECK(renderer.GetProperty<int>(DevelRenderer::Property::RENDERING_BEHAVIOR) == DevelRenderer::Rendering::CONTINUOUSLY);
+
+ map = actor.GetProperty<Property::Map>(DummyControl::Property::TEST_VISUAL);
+ value = map.Find(DevelImageVisual::Property::NOTIFY_AFTER_RASTERIZATION);
+ DALI_TEST_CHECK(value->Get<bool>() == false);
+
+ propertyMap.Clear();
+ propertyMap.Add(DevelImageVisual::Property::NOTIFY_AFTER_RASTERIZATION, true);
+ DevelControl::DoAction(actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelVisual::Action::UPDATE_PROPERTY, propertyMap);
+
+ application.SendNotification();
+ application.Render();
+
+ // Check renderer behavior again
+ DALI_TEST_CHECK(renderer.GetProperty<int>(DevelRenderer::Property::RENDERING_BEHAVIOR) == DevelRenderer::Rendering::IF_REQUIRED);
+
+ map = actor.GetProperty<Property::Map>(DummyControl::Property::TEST_VISUAL);
+ value = map.Find(DevelImageVisual::Property::NOTIFY_AFTER_RASTERIZATION);
+ DALI_TEST_CHECK(value->Get<bool>() == true);
+
+ END_TEST;
+}
+
int UtcDaliAnimatedVectorImageVisualAnimationFinishedSignal(void)
{
ToolkitTestApplication application;
DevelControl::DoAction(actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedVectorImageVisual::Action::JUMP_TO, 2);
- // To make event trigger
- actor.SetProperty(Actor::Property::SIZE, Vector2(10.0f, 10.0f));
-
application.SendNotification();
application.Render();
+ // Trigger count is 1 - Jump to during stopped
DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION);
Property::Map map = actor.GetProperty<Property::Map>(DummyControl::Property::TEST_VISUAL);
DevelControl::DoAction(actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedVectorImageVisual::Action::JUMP_TO, 3);
// To make event trigger
- actor.SetProperty(Actor::Property::SIZE, Vector2(20.0f, 20.0f));
+ actor.SetProperty(Actor::Property::SIZE, Vector2(10.0f, 10.0f));
application.SendNotification();
application.Render();
// Wait for animation finish
DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION);
+ // Note : AnimationFinished will occure force-render, and it might required another trigger. Test one more trigger now.
+ Test::WaitForEventThreadTrigger(1, 1);
// Jump to 3
DevelControl::DoAction(actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedVectorImageVisual::Action::JUMP_TO, 3);
- // To make event trigger
- actor.SetProperty(Actor::Property::SIZE, Vector2(10.0f, 10.0f));
-
application.SendNotification();
application.Render();
+ // Trigger count is 1 - Jump to during stopped.
DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION);
map = actor.GetProperty<Property::Map>(DummyControl::Property::TEST_VISUAL);
Property::Array* result = value->GetArray();
DALI_TEST_CHECK(result);
- DALI_TEST_CHECK(result->GetElementAt(0).Get<int>() == startFrame);
- DALI_TEST_CHECK(result->GetElementAt(1).Get<int>() == endFrame);
+ DALI_TEST_EQUALS(result->GetElementAt(0).Get<int>(), startFrame, TEST_LOCATION);
+ DALI_TEST_EQUALS(result->GetElementAt(1).Get<int>(), endFrame, TEST_LOCATION);
playRange.Clear();
playRange.PushBack(0);
result = value->GetArray();
DALI_TEST_CHECK(result);
- DALI_TEST_CHECK(result->GetElementAt(0).Get<int>() == 0);
- DALI_TEST_CHECK(result->GetElementAt(1).Get<int>() == 2);
+ // Ensure that vector data sended well.
+ CheckAndRetryPlayRange(actor, 0, 2, {{startFrame, endFrame}}, TEST_LOCATION);
attributes.Clear();
result = value->GetArray();
DALI_TEST_CHECK(result);
- DALI_TEST_CHECK(result->GetElementAt(0).Get<int>() == startFrame);
- DALI_TEST_CHECK(result->GetElementAt(1).Get<int>() == endFrame);
+ // Ensure that vector data sended well.
+ CheckAndRetryPlayRange(actor, startFrame, endFrame, {{0, 2}}, TEST_LOCATION);
// Play and update property
attributes.Clear();
application.GetScene().Add(dummyControl);
- // Retry function to get playrange until expect values comes.
- auto CheckAndRetryPlayRange = [&](int expectStartFrame, int expectEndFrame, std::vector<std::pair<int, int>> retrialFrames) {
- int tryCount = 0;
- int tryCountMax = 30;
- while(++tryCount <= tryCountMax)
- {
- Property::Map resultMap = dummyControl.GetProperty<Property::Map>(DummyControl::Property::TEST_VISUAL);
-
- Property::Value* value = resultMap.Find(DevelImageVisual::Property::PLAY_RANGE, Property::ARRAY);
- DALI_TEST_CHECK(value);
-
- Property::Array* result = value->GetArray();
- DALI_TEST_CHECK(result);
- DALI_TEST_EQUALS(result->Count(), 2, TEST_LOCATION);
-
- bool tryAgain = false;
- for(auto& framePair : retrialFrames)
- {
- if(result->GetElementAt(0).Get<int>() == framePair.first && result->GetElementAt(1).Get<int>() == framePair.second)
- {
- tryAgain = true;
- break;
- }
- }
- if(tryAgain)
- {
- tet_printf("Retry to get value again! [%d]\n", tryCount);
- // Dummy sleep 1 second.
- Test::WaitForEventThreadTrigger(1, 1);
- continue;
- }
-
- DALI_TEST_EQUALS(result->GetElementAt(0).Get<int>(), expectStartFrame, TEST_LOCATION);
- DALI_TEST_EQUALS(result->GetElementAt(1).Get<int>(), expectEndFrame, TEST_LOCATION);
- break;
- }
- DALI_TEST_CHECK(tryCount <= tryCountMax);
- };
-
tet_printf("Pause lottie first.\n");
Property::Map attributes;
} while(totalFrameCount == 0);
// Ensure that vector data sended well.
- CheckAndRetryPlayRange(startFrame, endFrame, {{0, 0}, {0, totalFrameCount - 1}});
+ CheckAndRetryPlayRange(dummyControl, startFrame, endFrame, {{0, 0}, {0, totalFrameCount - 1}}, TEST_LOCATION);
resultMap = dummyControl.GetProperty<Property::Map>(DummyControl::Property::TEST_VISUAL);
application.Render(16);
// Ensure that vector data sended well.
- CheckAndRetryPlayRange(changedStartFrame2, changedEndFrame2, {{changedStartFrame1, changedEndFrame1}, {startFrame, endFrame}});
+ CheckAndRetryPlayRange(dummyControl, changedStartFrame2, changedEndFrame2, {{changedStartFrame1, changedEndFrame1}, {startFrame, endFrame}}, TEST_LOCATION);
resultMap = dummyControl.GetProperty<Property::Map>(DummyControl::Property::TEST_VISUAL);
END_TEST;
}
+
+int UtcDaliImageVisualCustomWrapModePixelArea02(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline("Request image visual with a Property::Map, test custom wrap mode and pixel area");
+
+ static std::vector<UniformData> customUniforms =
+ {
+ UniformData("pixelArea", Property::Type::VECTOR4),
+ UniformData("wrapMode", Property::Type::VECTOR2),
+ };
+
+ TestGraphicsController& graphics = application.GetGraphicsController();
+ graphics.AddCustomUniforms(customUniforms);
+
+ VisualFactory factory = VisualFactory::Get();
+ DALI_TEST_CHECK(factory);
+
+ // Test wrap mode with atlasing. Image with a size smaller than 512*512 will be uploaded as a part of the atlas.
+ const int width = 34;
+ const int height = 34;
+ const Vector4 pixelArea(-0.5f, -0.5f, 2.f, 2.f);
+
+ Property::Map propertyMap;
+ propertyMap.Insert(Toolkit::Visual::Property::TYPE, Visual::IMAGE);
+ propertyMap.Insert(ImageVisual::Property::URL, TEST_SMALL_IMAGE_FILE_NAME);
+ propertyMap.Insert(ImageVisual::Property::DESIRED_WIDTH, width);
+ propertyMap.Insert(ImageVisual::Property::DESIRED_HEIGHT, height);
+ propertyMap.Insert(ImageVisual::Property::SYNCHRONOUS_LOADING, false);
+ propertyMap.Insert(ImageVisual::Property::PIXEL_AREA, pixelArea);
+ propertyMap.Insert(ImageVisual::Property::WRAP_MODE_U, WrapMode::MIRRORED_REPEAT);
+ propertyMap.Insert(ImageVisual::Property::WRAP_MODE_V, WrapMode::CLAMP_TO_EDGE);
+
+ Visual::Base visual = factory.CreateVisual(propertyMap);
+ DALI_TEST_CHECK(visual);
+
+ TestGlAbstraction& gl = application.GetGlAbstraction();
+ TraceCallStack& textureTrace = gl.GetTextureTrace();
+ textureTrace.Enable(true);
+ TraceCallStack& texParameterTrace = gl.GetTexParameterTrace();
+ texParameterTrace.Enable(true);
+
+ DummyControl actor = DummyControl::New();
+ DummyControlImpl& dummyImpl = static_cast<DummyControlImpl&>(actor.GetImplementation());
+ dummyImpl.RegisterVisual(Control::CONTROL_PROPERTY_END_INDEX + 1, visual);
+ actor.SetProperty(Actor::Property::SIZE, Vector2(2000, 2000));
+ actor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+ application.GetScene().Add(actor);
+
+ // loading started
+ application.SendNotification();
+ application.Render();
+
+ // Wait image load complete.
+ DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION);
+
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_CHECK(actor.GetRendererCount() == 1u);
+
+ DALI_TEST_EQUALS(textureTrace.FindMethod("BindTexture"), true, TEST_LOCATION);
+
+ // Following gl function should not be called
+ std::stringstream out;
+ out << std::hex << GL_TEXTURE_2D << ", " << GL_TEXTURE_WRAP_S << ", " << GL_MIRRORED_REPEAT;
+ DALI_TEST_CHECK(texParameterTrace.FindMethodAndParams("TexParameteri", out.str()));
+ out.str("");
+ out << std::hex << GL_TEXTURE_2D << ", " << GL_TEXTURE_WRAP_T << ", " << GL_CLAMP_TO_EDGE;
+ DALI_TEST_CHECK(texParameterTrace.FindMethodAndParams("TexParameteri", out.str()));
+
+ // test the uniforms which used to handle the wrap mode
+ Renderer renderer = actor.GetRendererAt(0u);
+ DALI_TEST_CHECK(renderer);
+
+ Property::Value pixelAreaValue = renderer.GetProperty(renderer.GetPropertyIndex("pixelArea"));
+ DALI_TEST_EQUALS(pixelAreaValue.Get<Vector4>(), pixelArea, TEST_LOCATION);
+ Vector4 pixelAreaUniform;
+ DALI_TEST_CHECK(gl.GetUniformValue<Vector4>("pixelArea", pixelAreaUniform));
+ DALI_TEST_EQUALS(pixelArea, pixelAreaUniform, Math::MACHINE_EPSILON_100, TEST_LOCATION);
+
+ actor.Unparent();
+ DALI_TEST_CHECK(actor.GetRendererCount() == 0u);
+
+ END_TEST;
+}
+
int UtcDaliImageVisualCustomWrapModeNoAtlas(void)
{
ToolkitTestApplication application;
const char* const PROPERTY_NAME_INPUT_METHOD_SETTINGS = "inputMethodSettings";
const char* const PROPERTY_NAME_INPUT_FILTER = "inputFilter";
+const char* const PROPERTY_NAME_REMOVE_FRONT_INSET = "removeFrontInset";
+const char* const PROPERTY_NAME_REMOVE_BACK_INSET = "removeBackInset";
+
const Vector4 PLACEHOLDER_TEXT_COLOR(0.8f, 0.8f, 0.8f, 0.8f);
const Dali::Vector4 LIGHT_BLUE(0.75f, 0.96f, 1.f, 1.f); // The text highlight color.
DALI_TEST_CHECK(editor.GetPropertyIndex(PROPERTY_NAME_STRIKETHROUGH) == DevelTextEditor::Property::STRIKETHROUGH);
DALI_TEST_CHECK(editor.GetPropertyIndex(PROPERTY_NAME_INPUT_STRIKETHROUGH) == DevelTextEditor::Property::INPUT_STRIKETHROUGH);
DALI_TEST_CHECK(editor.GetPropertyIndex(PROPERTY_NAME_SELECTION_POPUP_STYLE) == DevelTextEditor::Property::SELECTION_POPUP_STYLE);
+ DALI_TEST_CHECK(editor.GetPropertyIndex(PROPERTY_NAME_REMOVE_FRONT_INSET) == DevelTextEditor::Property::REMOVE_FRONT_INSET);
+ DALI_TEST_CHECK(editor.GetPropertyIndex(PROPERTY_NAME_REMOVE_BACK_INSET) == DevelTextEditor::Property::REMOVE_BACK_INSET);
END_TEST;
}
outlineMapSet["color"] = Color::RED;
outlineMapSet["width"] = 2.0f;
+ outlineMapSet["offset"] = Vector2(0.0f, 0.0f);
+ outlineMapSet["blurRadius"] = 0.0f;
editor.SetProperty(TextEditor::Property::OUTLINE, outlineMapSet);
editor.SetProperty(DevelTextEditor::Property::MIN_LINE_SIZE, 50.f);
DALI_TEST_EQUALS(editor.GetProperty<float>(DevelTextEditor::Property::MIN_LINE_SIZE), 50.0f, Math::MACHINE_EPSILON_1000, TEST_LOCATION);
+ // Check Remove Front/Back Inset Property
+ DALI_TEST_CHECK(editor.GetProperty<bool>(DevelTextEditor::Property::REMOVE_FRONT_INSET));
+ editor.SetProperty(DevelTextEditor::Property::REMOVE_FRONT_INSET, false);
+ DALI_TEST_CHECK(!editor.GetProperty<bool>(DevelTextEditor::Property::REMOVE_FRONT_INSET));
+
+ DALI_TEST_CHECK(editor.GetProperty<bool>(DevelTextEditor::Property::REMOVE_BACK_INSET));
+ editor.SetProperty(DevelTextEditor::Property::REMOVE_BACK_INSET, false);
+ DALI_TEST_CHECK(!editor.GetProperty<bool>(DevelTextEditor::Property::REMOVE_BACK_INSET));
+
+ application.SendNotification();
+ application.Render();
+
END_TEST;
}
TestTextGeometryUtils::CheckRectGeometryResult(textBoundingRectangle, expectedTextBoundingRectangle);
END_TEST;
-}
\ No newline at end of file
+}
+
+int utcDaliTextEditorRemoveFrontInset(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline(" utcDaliTextEditorRemoveFrontInset");
+ TextEditor editor = TextEditor::New();
+ DALI_TEST_CHECK(editor);
+ application.GetScene().Add(editor);
+ application.SendNotification();
+ application.Render();
+ DevelTextEditor::SetRemoveFrontInset(editor, false);
+ DALI_TEST_CHECK(!DevelTextEditor::IsRemoveFrontInset(editor));
+ END_TEST;
+}
+int utcDaliTextEditorRemoveBackInset(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline(" utcDaliTextEditorRemoveBackInset");
+ TextEditor editor = TextEditor::New();
+ DALI_TEST_CHECK(editor);
+ application.GetScene().Add(editor);
+ application.SendNotification();
+ application.Render();
+ DevelTextEditor::SetRemoveBackInset(editor, false);
+ DALI_TEST_CHECK(!DevelTextEditor::IsRemoveBackInset(editor));
+ END_TEST;
+}
const char* const PROPERTY_NAME_GRAB_HANDLE_COLOR = "grabHandleColor";
const char* const PROPERTY_NAME_INPUT_FILTER = "inputFilter";
+const char* const PROPERTY_NAME_REMOVE_FRONT_INSET = "removeFrontInset";
+const char* const PROPERTY_NAME_REMOVE_BACK_INSET = "removeBackInset";
+
const Vector4 PLACEHOLDER_TEXT_COLOR(0.8f, 0.8f, 0.8f, 0.8f);
const Dali::Vector4 LIGHT_BLUE(0.75f, 0.96f, 1.f, 1.f); // The text highlight color.
DALI_TEST_CHECK(field.GetPropertyIndex(PROPERTY_NAME_STRIKETHROUGH) == DevelTextField::Property::STRIKETHROUGH);
DALI_TEST_CHECK(field.GetPropertyIndex(PROPERTY_NAME_INPUT_STRIKETHROUGH) == DevelTextField::Property::INPUT_STRIKETHROUGH);
DALI_TEST_CHECK(field.GetPropertyIndex(PROPERTY_NAME_SELECTION_POPUP_STYLE) == DevelTextField::Property::SELECTION_POPUP_STYLE);
+ DALI_TEST_CHECK(field.GetPropertyIndex(PROPERTY_NAME_REMOVE_FRONT_INSET) == DevelTextField::Property::REMOVE_FRONT_INSET);
+ DALI_TEST_CHECK(field.GetPropertyIndex(PROPERTY_NAME_REMOVE_BACK_INSET) == DevelTextField::Property::REMOVE_BACK_INSET);
END_TEST;
}
outlineMapSet["color"] = Color::RED;
outlineMapSet["width"] = 2.0f;
+ outlineMapSet["offset"] = Vector2(0.0f, 0.0f);
+ outlineMapSet["blurRadius"] = 0.0f;
field.SetProperty(TextField::Property::OUTLINE, outlineMapSet);
application.SendNotification();
application.Render();
+ // Check Remove Front/Back Inset Property
+ DALI_TEST_CHECK(field.GetProperty<bool>(DevelTextField::Property::REMOVE_FRONT_INSET));
+ field.SetProperty(DevelTextField::Property::REMOVE_FRONT_INSET, false);
+ DALI_TEST_CHECK(!field.GetProperty<bool>(DevelTextField::Property::REMOVE_FRONT_INSET));
+
+ DALI_TEST_CHECK(field.GetProperty<bool>(DevelTextField::Property::REMOVE_BACK_INSET));
+ field.SetProperty(DevelTextField::Property::REMOVE_BACK_INSET, false);
+ DALI_TEST_CHECK(!field.GetProperty<bool>(DevelTextField::Property::REMOVE_BACK_INSET));
+
+ application.SendNotification();
+ application.Render();
+
+
END_TEST;
}
event.AddPoint(GetPointUpInside(position));
application.ProcessEvent(event);
}
- DALI_TEST_EQUALS(field.GetProperty<std::string>(TextEditor::Property::TEXT), std::string("testTextFieldEvent"), TEST_LOCATION);
+ DALI_TEST_EQUALS(field.GetProperty<std::string>(TextField::Property::TEXT), std::string("testTextFieldEvent"), TEST_LOCATION);
+
+ Dali::Clipboard::ClipData htmlData("application/xhtml+xml", "testTextFieldEventHtml");
+ clipboard.SetData(htmlData);
+
+ field.SetProperty(TextField::Property::TEXT, "");
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Long Press
+ TestGenerateLongPress(application, 1.0f, 25.0f, 20);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ Wait(application, 500);
+
+ TestEndLongPress(application, 1.0f, 25.0f, 520);
+
+ // Long Press
+ TestGenerateLongPress(application, 1.0f, 25.0f, 600);
+
+ // Render and notify
+ application.Render();
+
+ Wait(application, 500);
+
+ stage = application.GetScene();
+ layer = stage.GetRootLayer();
+ actor = layer.FindChildByName("optionPaste");
+
+ if(actor)
+ {
+ Vector3 worldPosition = actor.GetCurrentProperty<Vector3>(Actor::Property::WORLD_POSITION);
+ Vector2 halfStageSize = stage.GetSize() / 2.0f;
+ Vector2 position(worldPosition.x + halfStageSize.width, worldPosition.y + halfStageSize.height);
+
+ Dali::Integration::TouchEvent event;
+ event = Dali::Integration::TouchEvent();
+ event.AddPoint(GetPointDownInside(position));
+ application.ProcessEvent(event);
+
+ event = Dali::Integration::TouchEvent();
+ event.AddPoint(GetPointUpInside(position));
+ application.ProcessEvent(event);
+ }
+ DALI_TEST_EQUALS(field.GetProperty<std::string>(TextField::Property::TEXT), std::string("testTextFieldEventHtml"), TEST_LOCATION);
END_TEST;
}
application.Render();
END_TEST;
-}
\ No newline at end of file
+}
+
+int utcDaliTextFieldRemoveFrontInset(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline(" utcDaliTextFieldRemoveFrontInset");
+
+ TextField field = TextField::New();
+ DALI_TEST_CHECK(field);
+
+ application.GetScene().Add(field);
+ application.SendNotification();
+ application.Render();
+
+ DevelTextField::SetRemoveFrontInset(field, false);
+ DALI_TEST_CHECK(!DevelTextField::IsRemoveFrontInset(field));
+
+ END_TEST;
+}
+
+int utcDaliTextFieldRemoveBackInset(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline(" utcDaliTextFieldRemoveBackInset");
+
+ TextField field = TextField::New();
+ DALI_TEST_CHECK(field);
+
+ application.GetScene().Add(field);
+ application.SendNotification();
+ application.Render();
+
+ DevelTextField::SetRemoveBackInset(field, false);
+ DALI_TEST_CHECK(!DevelTextField::IsRemoveBackInset(field));
+
+ END_TEST;
+}
outlineMapSet["color"] = Color::RED;
outlineMapSet["width"] = 2.0f;
+ outlineMapSet["offset"] = Vector2(2.0f, 2.0f);
+ outlineMapSet["blurRadius"] = 3.0f;
label.SetProperty(TextLabel::Property::OUTLINE, outlineMapSet);
outlineMapGet = label.GetProperty<Property::Map>(TextLabel::Property::OUTLINE);
outlineMapSet.Clear();
outlineMapSet[Toolkit::DevelText::Outline::Property::COLOR] = Color::BLUE;
outlineMapSet[Toolkit::DevelText::Outline::Property::WIDTH] = 3.0f;
+ outlineMapSet[Toolkit::DevelText::Outline::Property::OFFSET] = Vector2(3.0f, 3.0f);
+ outlineMapSet[Toolkit::DevelText::Outline::Property::BLUR_RADIUS] = 4.0f;
+
label.SetProperty(TextLabel::Property::OUTLINE, outlineMapSet);
outlineMapGet = label.GetProperty<Property::Map>(TextLabel::Property::OUTLINE);
DALI_TEST_EQUALS(outlineMapGet.Count(), outlineMapSet.Count(), TEST_LOCATION);
- std::vector<std::string> outlineIndicesConversionTable = {"color", "width"};
+ std::vector<std::string> outlineIndicesConversionTable = {"color", "width", "offset", "blurRadius"};
DALI_TEST_EQUALS(DaliTestCheckMaps(outlineMapGet, outlineMapSet, outlineIndicesConversionTable), true, TEST_LOCATION);
// Check the background property
outlineMapSet["color"] = Color::BLUE;
outlineMapSet["width"] = 2.0f;
+ outlineMapSet["offset"] = "2 2";
+ outlineMapSet["blurRadius"] = "3";
label.SetProperty(TextLabel::Property::OUTLINE, outlineMapSet);
application.SendNotification();
propertyMap.Insert("underline", underlineMapSet.Add("enable", true).Add("color", Color::GREEN).Add("height", 1).Add("type", Text::Underline::Type::SOLID).Add("dashWidth", 2).Add("dashGap", 1));
Property::Map outlineMapSet;
- propertyMap.Insert("outline", outlineMapSet.Add("color", Color::YELLOW).Add("width", 1));
+ propertyMap.Insert("outline", outlineMapSet.Add("color", Color::YELLOW).Add("width", 1).Add("offset", Vector2(2.0f, 2.0f)).Add("blurRadius", 3.0f));
Property::Map backgroundMapSet;
propertyMap.Insert("textBackground", backgroundMapSet.Add("enable", true).Add("color", Color::CYAN));
dummyImpl.RegisterVisual(DummyControl::Property::FOCUS_VISUAL, focusVisual);
DALI_TEST_CHECK(focusVisual.GetDepthIndex() > foregroundVisual.GetDepthIndex());
- tet_infoline("Set depth index on a new visual before registering, the depth index should not have been changed");
+ tet_infoline("Set depth index on a new visual before registering, the depth index should not have been changed, and be clampled");
Visual::Base labelVisual = factory.CreateVisual(propertyMap);
- labelVisual.SetDepthIndex(-2000);
+ labelVisual.SetDepthIndex(static_cast<int>(Toolkit::DepthIndex::MINIMUM_DEPTH_INDEX) - 100);
dummyImpl.RegisterVisual(DummyControl::Property::LABEL_VISUAL, labelVisual);
- DALI_TEST_EQUALS(labelVisual.GetDepthIndex(), -2000, TEST_LOCATION);
+ DALI_TEST_EQUALS(labelVisual.GetDepthIndex(), static_cast<int>(Toolkit::DepthIndex::MINIMUM_DEPTH_INDEX), TEST_LOCATION);
tet_infoline("Replace visual, the depth index should be the same as what was previously set");
const int testVisual2DepthIndex = testVisual2.GetDepthIndex();
dummyImpl.RegisterVisual(DummyControl::Property::TEST_VISUAL2, testVisual2Replacement);
DALI_TEST_EQUALS(testVisual2Replacement.GetDepthIndex(), testVisual2DepthIndex, TEST_LOCATION);
- tet_infoline("Replace visual and set a depth index on the replacement, the depth index of the replacement should be honoured");
+ tet_infoline("Replace visual and set a depth index on the replacement, the depth index of the replacement should be honoured, and be clampled");
Visual::Base anotherTestVisual2Replacement = factory.CreateVisual(propertyMap);
- anotherTestVisual2Replacement.SetDepthIndex(2000);
+ anotherTestVisual2Replacement.SetDepthIndex(static_cast<int>(Toolkit::DepthIndex::MAXIMUM_DEPTH_INDEX) + 100);
dummyImpl.RegisterVisual(DummyControl::Property::TEST_VISUAL2, anotherTestVisual2Replacement);
- DALI_TEST_EQUALS(anotherTestVisual2Replacement.GetDepthIndex(), 2000, TEST_LOCATION);
+ DALI_TEST_EQUALS(anotherTestVisual2Replacement.GetDepthIndex(), static_cast<int>(Toolkit::DepthIndex::MAXIMUM_DEPTH_INDEX), TEST_LOCATION);
dummyControl.SetProperty(Actor::Property::SIZE, Vector2(200.f, 200.f));
application.GetScene().Add(dummyControl);
dummyControl.SetProperty(Control::Property::BACKGROUND, propertyMap);
- const int TEST_VISUAL_1_DEPTH_INDEX = 0;
+ const int TEST_VISUAL_1_DEPTH_INDEX = static_cast<int>(Toolkit::DepthIndex::CONTENT);
tet_printf("Register visual, should have depth index of %d\n", TEST_VISUAL_1_DEPTH_INDEX);
Visual::Base testVisual1 = factory.CreateVisual(propertyMap);
dummyImpl.RegisterVisual(DummyControl::Property::TEST_VISUAL, testVisual1);
tet_printf("Register another visual, should have a depth index greater than previous(%d)\n", TEST_VISUAL_1_DEPTH_INDEX);
Visual::Base testVisual2 = factory.CreateVisual(propertyMap);
dummyImpl.RegisterVisual(DummyControl::Property::TEST_VISUAL2, testVisual2);
- DALI_TEST_CHECK(testVisual2.GetDepthIndex() > testVisual1.GetDepthIndex());
+ DALI_TEST_GREATER(testVisual2.GetDepthIndex(), testVisual1.GetDepthIndex(), TEST_LOCATION);
+
+ const int TEST_VISUAL_2_DEPTH_INDEX = testVisual2.GetDepthIndex();
+
+ tet_printf("Register other visual, should have a depth index greater than previous(%d)\n", TEST_VISUAL_2_DEPTH_INDEX);
+ Visual::Base testVisual3 = factory.CreateVisual(propertyMap);
+ dummyImpl.RegisterVisual(DummyControl::Property::FOREGROUND_VISUAL, testVisual3, Toolkit::DepthIndex::AUTO_INDEX);
+ DALI_TEST_GREATER(testVisual3.GetDepthIndex(), testVisual2.GetDepthIndex(), TEST_LOCATION);
dummyControl.SetProperty(Actor::Property::SIZE, Vector2(200.f, 200.f));
application.GetScene().Add(dummyControl);
mSkybox(),
mSkyboxOrientation(Quaternion()),
mSkyboxIntensity(1.0f),
+ mLightObservers(),
mShaderManager(new Scene3D::Loader::ShaderManager())
{
}
{
item->NotifyImageBasedLightTexture(mDiffuseTexture, mSpecularTexture, mIblScaleFactor, mSpecularMipmapLevels);
item->NotifyShadowMapTexture(mShadowTexture);
- mItems.push_back(item);
+ mLightObservers.PushBack(item);
}
}
{
if(item)
{
- for(uint32_t i = 0; i < mItems.size(); ++i)
+ auto iter = mLightObservers.Find(item);
+ if(iter != mLightObservers.End())
{
- if(mItems[i] == item)
- {
- mItems.erase(mItems.begin() + i);
- break;
- }
+ mLightObservers.Erase(iter);
}
}
}
void SceneView::SetImageBasedLightScaleFactor(float scaleFactor)
{
mIblScaleFactor = scaleFactor;
- for(auto&& item : mItems)
+ for(auto&& item : mLightObservers)
{
if(item)
{
mShadowLight.Reset();
mShadowTexture.Reset();
- for(auto&& item : mItems)
+ for(auto&& item : mLightObservers)
{
if(item)
{
void SceneView::OnSceneDisconnection()
{
- mItems.clear();
+ mLightObservers.Clear();
Window window = mWindow.GetHandle();
if(window)
void SceneView::NotifyImageBasedLightTextureChange()
{
- for(auto&& item : mItems)
+ for(auto&& item : mLightObservers)
{
if(item)
{
DevelFrameBuffer::AttachDepthTexture(mShadowFrameBuffer, mShadowTexture);
mShadowMapRenderTask.SetFrameBuffer(mShadowFrameBuffer);
- for(auto&& item : mItems)
+ for(auto&& item : mLightObservers)
{
if(item)
{
#include <dali-toolkit/internal/visuals/image/image-visual.h>
#include <dali-toolkit/public-api/controls/control-impl.h>
#include <dali/integration-api/adaptor-framework/scene-holder.h>
+#include <dali/integration-api/ordered-set.h>
#include <dali/public-api/actors/camera-actor.h>
#include <dali/public-api/actors/layer.h>
#include <dali/public-api/adaptor-framework/window.h>
/////////////////////////////////////////////////////////////
// FrameBuffer and Rendertask to render child objects as a 3D Scene
- Dali::WeakHandle<Dali::Window> mWindow;
- Integration::SceneHolder mSceneHolder;
- CameraActor mDefaultCamera;
- CameraActor mSelectedCamera;
- std::vector<CameraActor> mCameras;
- std::vector<Scene3D::Internal::LightObserver*> mItems;
- Dali::FrameBuffer mFrameBuffer;
- Dali::Texture mTexture;
- Dali::RenderTask mRenderTask;
- Layer mRootLayer;
- int32_t mWindowOrientation;
- Dali::Actor mSkybox;
- Quaternion mSkyboxOrientation;
- float mSkyboxIntensity{1.0f};
- uint8_t mFrameBufferMultiSamplingLevel{0u};
+ Dali::WeakHandle<Dali::Window> mWindow;
+ Integration::SceneHolder mSceneHolder;
+ CameraActor mDefaultCamera;
+ CameraActor mSelectedCamera;
+ std::vector<CameraActor> mCameras;
+ Dali::FrameBuffer mFrameBuffer;
+ Dali::Texture mTexture;
+ Dali::RenderTask mRenderTask;
+ Layer mRootLayer;
+ int32_t mWindowOrientation;
+ Dali::Actor mSkybox;
+ Quaternion mSkyboxOrientation;
+ float mSkyboxIntensity{1.0f};
+ uint8_t mFrameBufferMultiSamplingLevel{0u};
+
+ Dali::Integration::OrderedSet<Scene3D::Internal::LightObserver, false> mLightObservers; ///< The set of items to be notified when light properties change. (not owned)
bool mWindowSizeChanged{false};
uint32_t mWindowWidth{0};
+#define MORPH defined(MORPH_POSITION) || defined(MORPH_NORMAL) || defined(MORPH_TANGENT)
#define ADD_EXTRA_SKINNING_ATTRIBUTES
#define ADD_EXTRA_WEIGHTS
#include <dali/devel-api/actors/actor-devel.h>
#include <dali/devel-api/adaptor-framework/window-devel.h>
+#include <dali/public-api/object/property-map.h>
#include <dali/public-api/object/type-info.h>
// INTERNAL INCLUDES
#include <dali-toolkit/devel-api/asset-manager/asset-manager.h>
#include <dali-toolkit/internal/controls/control/control-data-impl.h>
+#include <dali-toolkit/internal/visuals/image/image-visual.h>
#include <dali-toolkit/public-api/controls/control-impl.h>
#include <dali-toolkit/public-api/controls/control.h>
#include <dali-toolkit/public-api/controls/image-view/image-view.h>
{
namespace
{
-static std::string GetLocaleText(std::string string, const char* domain = "dali-toolkit")
+constexpr const char* ATTR_IMG_SRC_KEY = "imgSrc";
+
+std::string GetLocaleText(std::string string, const char* domain = "dali-toolkit")
{
#ifdef DGETTEXT_ENABLED
/*TODO: currently non-localized string is used as a key for translation lookup. In case the lookup key formatting is forced
#endif
}
-static Dali::Actor CreateHighlightIndicatorActor()
+Dali::Actor CreateHighlightIndicatorActor()
{
std::string focusBorderImagePath(AssetManager::GetDaliImagePath());
focusBorderImagePath += "/keyboard_focus.9.png";
return actor;
}
+
+std::string FetchImageSrcFromMap(const Dali::Property::Map& imageMap)
+{
+ auto urlVal = imageMap.Find(Toolkit::ImageVisual::Property::URL);
+ if(urlVal)
+ {
+ if(urlVal->GetType() == Dali::Property::STRING)
+ {
+ return urlVal->Get<std::string>();
+ }
+ else if(urlVal->GetType() == Dali::Property::ARRAY)
+ {
+ auto urlArray = urlVal->GetArray();
+ if(urlArray && !urlArray->Empty())
+ {
+ // Returns first element if url is an array
+ return (*urlArray)[0].Get<std::string>();
+ }
+ }
+ }
+ return {};
+}
+
+std::string FetchImageSrc(const Toolkit::ImageView& imageView)
+{
+ const auto imageUrl = imageView.GetProperty<std::string>(Toolkit::ImageView::Property::IMAGE);
+ if(!imageUrl.empty())
+ {
+ return imageUrl;
+ }
+
+ const auto imageMap = imageView.GetProperty<Dali::Property::Map>(Toolkit::ImageView::Property::IMAGE);
+ if(!imageMap.Empty())
+ {
+ return FetchImageSrcFromMap(imageMap);
+ }
+ return {};
+}
+
} // unnamed namespace
ControlAccessible::ControlAccessible(Dali::Actor self)
states[State::FOCUSABLE] = self.GetProperty<bool>(Actor::Property::KEYBOARD_FOCUSABLE);
states[State::FOCUSED] = Toolkit::KeyboardFocusManager::Get().GetCurrentFocusActor() == self;
states[State::HIGHLIGHTABLE] = self.GetProperty<bool>(Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE);
- states[State::HIGHLIGHTED] = GetCurrentlyHighlightedActor() == self;
+ states[State::HIGHLIGHTED] = IsHighlighted();
states[State::ENABLED] = true;
states[State::SENSITIVE] = (Dali::DevelActor::IsHittable(self) && Dali::DevelActor::GetTouchRequired(self));
states[State::VISIBLE] = self.GetProperty<bool>(Actor::Property::VISIBLE);
result.emplace(automationIdKey, std::move(automationId));
}
+ if(auto imageView = Toolkit::ImageView::DownCast(Self()))
+ {
+ auto imageSrc = FetchImageSrc(imageView);
+ if(!imageSrc.empty())
+ {
+ result.emplace(ATTR_IMG_SRC_KEY, std::move(imageSrc));
+ }
+ }
+
// Add "class" if not present already
if(result.find(classKey) == result.end())
{
bool ControlAccessible::ClearHighlight()
{
- Dali::Actor self = Self();
-
if(!Dali::Accessibility::IsUp())
{
return false;
}
- if(GetCurrentlyHighlightedActor() == self)
+ if(IsHighlighted())
{
UnregisterPropertySetSignal();
UnregisterPositionPropertyNotification();
- self.Remove(mCurrentHighlightActor.GetHandle());
+ Self().Remove(mCurrentHighlightActor.GetHandle());
mCurrentHighlightActor = {};
SetCurrentlyHighlightedActor({});
EmitHighlighted(false);
#define DALI_TOOLKIT_DEVEL_CONTROL_DEPTH_INDEX_RANGES_H
/*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2024 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.
// The negative value for background effect and background has been
// chosen so that newer controls can have content without setting
// depth index, and go in front of native controls with a background.
-// This backround negative value means that the highest possible value
-// is SIBLING_ORDER_MULTIPLIER-BACKGROUND_EFFECT-1. The divisor of
-// 100 ensures the range fits within the sibling order range, and has
-// enough gaps to allow Control Authors to use other intermediate depths.
+// The lowest possible value is MINIMUM_DEPTH_INDEX, and highest possible
+// value is MAXIMUM_DEPTH_INDEX. The divisor of 10 ensures the range fits
+// within the sibling order range, and has enough gaps to allow Control
+// Authors to use other intermediate depths.
+//
+// Note : AUTO_INDEX is special value. It means that the depth index will be
+// automatically assigned when we register visual into the control.
+// Other values will be clamped to the range.
enum Ranges
{
- BACKGROUND_EFFECT = -2 * DevelLayer::SIBLING_ORDER_MULTIPLIER / 100,
- BACKGROUND = -1 * DevelLayer::SIBLING_ORDER_MULTIPLIER / 100,
- CONTENT = 0,
- DECORATION = 1 * DevelLayer::SIBLING_ORDER_MULTIPLIER / 100,
- FOREGROUND_EFFECT = 2 * DevelLayer::SIBLING_ORDER_MULTIPLIER / 100
+ MINIMUM_DEPTH_INDEX = -5 * DevelLayer::SIBLING_ORDER_MULTIPLIER / 10 + 1,
+ BACKGROUND_EFFECT = -2 * DevelLayer::SIBLING_ORDER_MULTIPLIER / 10,
+ BACKGROUND = -1 * DevelLayer::SIBLING_ORDER_MULTIPLIER / 10,
+ CONTENT = 0,
+ DECORATION = 1 * DevelLayer::SIBLING_ORDER_MULTIPLIER / 10,
+ FOREGROUND_EFFECT = 2 * DevelLayer::SIBLING_ORDER_MULTIPLIER / 10,
+ MAXIMUM_DEPTH_INDEX = 5 * DevelLayer::SIBLING_ORDER_MULTIPLIER / 10,
+
+ AUTO_INDEX = MINIMUM_DEPTH_INDEX - 1, ///< Special value to indicate that the depth index should be automatically calculated.
+ /// If visual replaced by another visual, the depth index of the new visual will be set to previous visual.
+ /// Otherwise, depth index will be set as the maximum depth index + 1
+ /// what given control already has, or CONTENT if no visuals.
};
static_assert((unsigned int)DevelLayer::ACTOR_DEPTH_MULTIPLIER > (unsigned int)DevelLayer::SIBLING_ORDER_MULTIPLIER);
+static_assert(MINIMUM_DEPTH_INDEX < BACKGROUND_EFFECT);
static_assert(BACKGROUND_EFFECT < BACKGROUND);
static_assert(BACKGROUND < CONTENT);
static_assert(CONTENT < DECORATION);
static_assert(DECORATION < FOREGROUND_EFFECT);
+static_assert(FOREGROUND_EFFECT < MAXIMUM_DEPTH_INDEX);
+
+// AUTO_INDEX should not be inside of the valid range.
+static_assert(!(MINIMUM_DEPTH_INDEX <= AUTO_INDEX && AUTO_INDEX <= MAXIMUM_DEPTH_INDEX));
} // namespace DepthIndex
#define DALI_TOOLKIT_CONTROL_DEVEL_H
/*
- * Copyright (c) 2023 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2024 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.
*
* @note Derived class should not call visual.SetOnScene(actor). It is the responsibility of the base class to connect/disconnect registered visual to stage.
* Use below API with enabled set to false if derived class wishes to control when visual is staged.
- * @note If the depth-index is not set on the visual, then it is set to be above the currently registered visuals.
- * @note If replacing a visual, then the depth-index of the visual being replaced is used for the visual.
+ * @note depth-index be used to Dali::Toolkit::DepthIndex::Ranges::AUTO_INDEX.
*/
DALI_TOOLKIT_API void RegisterVisual(Internal::Control& control, Dali::Property::Index index, Toolkit::Visual::Base& visual);
* @param[in] control The control
* @param[in] index The Property index of the visual, used to reference visual
* @param[in] visual The visual to register
- * @param[in] depthIndex The visual's depth-index is set to this
+ * @param[in] depthIndex The visual's depth-index is set to this. If the depth-index is set to DepthIndex::Ranges::AUTO_INDEX,
+ * the actual depth-index of visual will be determind automatically (Use previous visuals depth-index, or placed on top of all other visuals.)
+ * Otherwise, the visual's depth-index is set to clamped value, between DepthIndex::Ranges::MINIMUM_DEPTH_INDEX and DepthIndex::Ranges::MAXIMUM_DEPTH_INDEX.
*
* @note Derived class should not call visual.SetOnScene(actor). It is the responsibility of the base class to connect/disconnect registered visual to stage.
* Use below API with enabled set to false if derived class wishes to control when visual is staged.
* @param[in] visual The visual to register
* @param[in] enabled false if derived class wants to control when visual is set on stage.
*
- * @note If the depth-index is not set on the visual, then it is set to be above the currently registered visuals.
- * @note If replacing a visual, then the depth-index of the visual being replaced is used for the visual.
+ * @note depth-index be used to Dali::Toolkit::DepthIndex::Ranges::AUTO_INDEX.
*
* @see EnableVisual()
*/
* @param[in] index The Property index of the visual, used to reference visual
* @param[in] visual The visual to register
* @param[in] enabled false if derived class wants to control when visual is set on stage.
- * @param[in] depthIndex The visual's depth-index is set to this
+ * @param[in] depthIndex The visual's depth-index is set to this. If the depth-index is set to DepthIndex::Ranges::AUTO_INDEX,
+ * the actual depth-index of visual will be determind automatically (Use previous visuals depth-index, or placed on top of all other visuals.)
+ * Otherwise, the visual's depth-index is set to clamped value, between DepthIndex::Ranges::MINIMUM_DEPTH_INDEX and DepthIndex::Ranges::MAXIMUM_DEPTH_INDEX.
*
* @see EnableVisual()
* @see Visual::Base::GetDepthIndex()
GetImpl(textEditor).PasteText();
}
+void SetRemoveFrontInset(TextEditor textEditor, const bool remove)
+{
+ GetImpl(textEditor).SetRemoveFrontInset(remove);
+}
+
+bool IsRemoveFrontInset(TextEditor textEditor)
+{
+ return GetImpl(textEditor).IsRemoveFrontInset();
+}
+
+void SetRemoveBackInset(TextEditor textEditor, const bool remove)
+{
+ GetImpl(textEditor).SetRemoveBackInset(remove);
+}
+
+bool IsRemoveBackInset(TextEditor textEditor)
+{
+ return GetImpl(textEditor).IsRemoveBackInset();
+}
+
} // namespace DevelTextEditor
} // namespace Toolkit
* @see Dali::Toolkit::TextSelectionPopup::Property
*/
SELECTION_POPUP_STYLE,
+
+ /**
+ * @brief Whether to trim the xBearing of first glyph of the text.
+ * @details Name "removeFrontInset", type Property::BOOLEAN.
+ */
+ REMOVE_FRONT_INSET,
+
+ /**
+ * @brief Whether to trim the advance of last glyph of the text.
+ * @details Name "removeBackInset", type Property::BOOLEAN.
+ */
+ REMOVE_BACK_INSET,
};
} // namespace Property
*/
DALI_TOOLKIT_API void PasteText(TextEditor textEditor);
+/**
+ * @brief Set removing front inset to text label.
+ *
+ * @param[in] textEditor The instance of TextLabel.
+ * @param[in] remove Whether front inset of text label has to be removed or not.
+ */
+DALI_TOOLKIT_API void SetRemoveFrontInset(TextEditor textEditor, const bool remove);
+
+/**
+ * @brief Whether front inset of text label is removed or not.
+ *
+ * @param[in] textEditor The instance of TextLabel.
+ * @return True if the front inset of text label is removed.
+ */
+DALI_TOOLKIT_API bool IsRemoveFrontInset(TextEditor textEditor);
+
+/**
+ * @brief Set removing back inset to text label.
+ *
+ * @param[in] textEditor The instance of TextLabel.
+ * @param[in] remove Whether back inset of text label has to be removed or not.
+ */
+DALI_TOOLKIT_API void SetRemoveBackInset(TextEditor textEditor, const bool remove);
+
+/**
+ * @brief Whether back inset of text label is removed or not.
+ *
+ * @param[in] textEditor The instance of TextLabel.
+ * @return True if the back inset of text label is removed.
+ */
+DALI_TOOLKIT_API bool IsRemoveBackInset(TextEditor textEditor);
+
+
} // namespace DevelTextEditor
} // namespace Toolkit
GetImpl(textField).PasteText();
}
+void SetRemoveFrontInset(TextField textField, const bool remove)
+{
+ GetImpl(textField).SetRemoveFrontInset(remove);
+}
+
+bool IsRemoveFrontInset(TextField textField)
+{
+ return GetImpl(textField).IsRemoveFrontInset();
+}
+
+void SetRemoveBackInset(TextField textField, const bool remove)
+{
+ GetImpl(textField).SetRemoveBackInset(remove);
+}
+
+bool IsRemoveBackInset(TextField textField)
+{
+ return GetImpl(textField).IsRemoveBackInset();
+}
+
} // namespace DevelTextField
} // namespace Toolkit
* @see Dali::Toolkit::TextSelectionPopup::Property
*/
SELECTION_POPUP_STYLE,
+
+ /**
+ * @brief Whether to trim the xBearing of first glyph of the text.
+ * @details Name "removeFrontInset", type Property::BOOLEAN.
+ */
+ REMOVE_FRONT_INSET,
+
+ /**
+ * @brief Whether to trim the advance of last glyph of the text.
+ * @details Name "removeBackInset", type Property::BOOLEAN.
+ */
+ REMOVE_BACK_INSET,
};
} // namespace Property
*/
DALI_TOOLKIT_API void PasteText(TextField textField);
+/**
+ * @brief Set removing front inset to TextField.
+ *
+ * @param[in] textField The instance of TextField.
+ * @param[in] remove Whether front inset of TextField has to be removed or not.
+ */
+DALI_TOOLKIT_API void SetRemoveFrontInset(TextField textField, const bool remove);
+
+/**
+ * @brief Whether front inset of TextField is removed or not.
+ *
+ * @param[in] textField The instance of TextField.
+ * @return True if the front inset of TextField is removed.
+ */
+DALI_TOOLKIT_API bool IsRemoveFrontInset(TextField textField);
+
+/**
+ * @brief Set removing back inset to TextField.
+ *
+ * @param[in] textField The instance of TextField.
+ * @param[in] remove Whether back inset of TextField has to be removed or not.
+ */
+DALI_TOOLKIT_API void SetRemoveBackInset(TextField textField, const bool remove);
+
+/**
+ * @brief Whether back inset of TextField is removed or not.
+ *
+ * @param[in] textField The instance of TextField.
+ * @return True if the back inset of TextField is removed.
+ */
+DALI_TOOLKIT_API bool IsRemoveBackInset(TextField textField);
+
} // namespace DevelTextField
} // namespace Toolkit
* @details Name "width", type Property::STRING or Property::FLOAT i.e. "1.0" or 1.f
* @note Optional. If not provided then the outline is not enabled.
*/
- WIDTH
+ WIDTH,
+
+ /**
+ * @brief The offset in pixels of the outline.
+ * @details Name "offset", type Property::STRING or Property::VECTOR2. i.e "3.0 3.0" or Vector2( 3.f, 3.f )
+ * @note Optional. If not provided then the outline is not enabled.
+ */
+ OFFSET,
+
+ /**
+ * @brief The radius of the Gaussian blur for the outline.
+ * @details Name "blurRadius", type Property::STRING or Property::FLOAT. i.e "5.0" or 5.f
+ * @note Optional. If not provided then the outline is not enabled.
+ */
+ BLUR_RADIUS
};
} // namespace Property
#define DALI_TOOLKIT_TEXT_RANGE_H
/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2024 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.
} // namespace Toolkit
-// Allow Range to be treated as a POD type
-template<>
-struct TypeTraits<Dali::Toolkit::Text::Range> : public BasicTypes<Dali::Toolkit::Text::Range>
-{
- enum
- {
- IS_TRIVIAL_TYPE = true
- };
-};
-
} // namespace Dali
#endif // DALI_TOOLKIT_TEXT_RANGE_H
#define DALI_TOOLKIT_TEXT_BASE_SPAN_H
/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2024 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.
} // namespace Toolkit
-// Allow BaseSpan to be treated as a POD type
-template<>
-struct TypeTraits<Dali::Toolkit::Text::BaseSpan> : public BasicTypes<Dali::Toolkit::Text::BaseSpan>
-{
- enum
- {
- IS_TRIVIAL_TYPE = true
- };
-};
-
} // namespace Dali
#endif // DALI_TOOLKIT_TEXT_BASE_SPAN_H
#ifndef DALI_TOOLKIT_VISUAL_BASE_H
#define DALI_TOOLKIT_VISUAL_BASE_H
/*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2024 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.
* @brief Set the depth index of this visual.
*
* Depth-index controls draw-order for overlapping visuals.
- * Visuals with higher depth indices are rendered in front of other visual with smaller values
+ * Visuals with higher depth indices are rendered in front of other visual with smaller values.
+ *
+ * @note The value of index will be clamped between DepthIndex::Ranges::MINIMUM_DEPTH_INDEX and
+ * DepthIndex::Ranges::MAXIMUM_DEPTH_INDEX.
+ * @note If we call this API at least 1 time, we cannot set as DepthIndex::AUTO_INDEX after.
*
* @param[in] index The depth index of this visual.
*/
void SetDepthIndex(int index);
/**
- * @brief Get the depth index of this visual
+ * @brief Get the depth index of this visual which clamped between
+ * DepthIndex::Ranges::MINIMUM_DEPTH_INDEX and DepthIndex::Ranges::MAXIMUM_DEPTH_INDEX.
+ * Or DepthIndex::Ranges::AUTO_INDEX if we never set depth index before.
*
* @return The depth index of this visual.
*/
#define DALI_TOOLKIT_DEVEL_API_VISUALS_IMAGE_VISUAL_PROPERTIES_DEVEL_H
/*
- * Copyright (c) 2023 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2024 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.
/**
* @brief Whether to AnimatedVectorImageVisual fixed cache or not.
- * @details Name "EnableFrameCache", type Property::BOOLEAN.
+ * @details Name "enableFrameCache", type Property::BOOLEAN.
* If this property is true, AnimatedVectorImageVisual enable frame cache for loading and keeps loaded frame
* until the visual is removed. It reduces CPU cost when the animated image will be looping.
* But it can spend a lot of memory if the resource has high resolution image or many frame count.
- * @note It is used in the AnimatedImageVisual. The default is false
+ * @note It is used in the AnimatedVectorImageVisual. The default is false
*/
- ENABLE_FRAME_CACHE = ORIENTATION_CORRECTION + 16
+ ENABLE_FRAME_CACHE = ORIENTATION_CORRECTION + 16,
+
+ /**
+ * @brief Whether notify AnimatedVectorImageVisual to render thread after every rasterization or not.
+ * @details Name "notifyAfterRasterization", type Property::BOOLEAN.
+ * If this property is true, AnimatedVectorImageVisual send notify to render thread after every rasterization.
+ * If false, AnimatedVectorImageVisual set Renderer's Behaviour as Continouly (mean, always update the render thread.)
+ *
+ * This flag is useful if given resource has low fps, so we don't need to render every frame.
+ * @note It is used in the AnimatedVectorImageVisual. The default is false.
+ */
+ NOTIFY_AFTER_RASTERIZATION = ORIENTATION_CORRECTION + 17
};
} //namespace Property
{
DALI_ASSERT_DEBUG(mNode && "Operation on NULL JSON node");
- DeleteNodesWithoutSelf otherDeletor(mNode);
+ CollectNodes collector;
- DepthFirst(mNode, otherDeletor);
+ DepthFirst(mNode, collector);
+
+ for(CollectNodes::iterator iter = collector.nodes.begin(); iter != collector.nodes.end(); ++iter)
+ {
+ if(*iter != mNode)
+ {
+ delete *iter;
+ }
+ }
mNode->mFirstChild = NULL;
mNode->mLastChild = NULL;
};
/*
- * Delete nodes immediately, instead of self
- */
-struct DeleteNodesWithoutSelf
-{
- DeleteNodesWithoutSelf(TreeNode* self)
- : mSelf(self){};
-
- /*
- * Call operator to delete object if given node is not self
- */
- void operator()(TreeNode*& n)
- {
- DALI_ASSERT_DEBUG(n && "Operation on NULL JSON node");
- if(mSelf != n)
- {
- delete n;
- }
- }
-
- const TreeNode* mSelf; ///< self node what we should not remove.
-};
-
-/*
* Depth first walk of nodes applying given operation (unary_function)
*/
template<typename Operation>
void CheckBoxButton::OnStateChange(State newState)
{
// TODO: replace it with OnPropertySet hook once Button::Property::SELECTED will be consistently used
- if((Dali::Accessibility::Accessible::GetCurrentlyHighlightedActor() == Self()) && (newState == SELECTED_STATE || newState == UNSELECTED_STATE))
+ if(newState == SELECTED_STATE || newState == UNSELECTED_STATE)
{
auto* accessible = GetAccessibleObject();
- if(DALI_LIKELY(accessible))
+ if(DALI_LIKELY(accessible) && accessible->IsHighlighted())
{
accessible->EmitStateChanged(Dali::Accessibility::State::CHECKED, newState == SELECTED_STATE ? 1 : 0, 0);
}
void PushButton::OnStateChange(State newState)
{
// TODO: replace it with OnPropertySet hook once Button::Property::SELECTED will be consistently used
- if((Dali::Accessibility::Accessible::GetCurrentlyHighlightedActor() == Self()) && (newState == SELECTED_STATE || newState == UNSELECTED_STATE))
+ if(newState == SELECTED_STATE || newState == UNSELECTED_STATE)
{
auto* accessible = GetAccessibleObject();
- if(DALI_LIKELY(accessible))
+ if(DALI_LIKELY(accessible) && accessible->IsHighlighted())
{
accessible->EmitStateChanged(Dali::Accessibility::State::PRESSED, newState == SELECTED_STATE ? 1 : 0, 0);
}
// TODO: replace it with OnPropertySet hook once Button::Property::SELECTED will be consistently used
- if((Dali::Accessibility::Accessible::GetCurrentlyHighlightedActor() == Self()) && (newState == SELECTED_STATE || newState == UNSELECTED_STATE))
+ if(newState == SELECTED_STATE || newState == UNSELECTED_STATE)
{
auto* accessible = GetAccessibleObject();
- if(DALI_LIKELY(accessible))
+ if(DALI_LIKELY(accessible) && accessible->IsHighlighted())
{
accessible->EmitStateChanged(Dali::Accessibility::State::CHECKED, newState == SELECTED_STATE ? 1 : 0, 0);
}
DevelControl::UnregisterVisual(*this, index);
}
- DevelControl::RegisterVisual(*this, index, visual, enabled);
+ DevelControl::RegisterVisual(*this, index, visual, enabled, DepthIndex::CONTENT);
}
void ToggleButton::RelayoutVisual(Property::Index index, const Vector2& size)
void ToggleButton::OnStateChange(State newState)
{
// TODO: replace it with OnPropertySet hook once Button::Property::SELECTED will be consistently used
- if((Self() == Dali::Accessibility::Accessible::GetCurrentlyHighlightedActor()) && (newState == SELECTED_STATE || newState == UNSELECTED_STATE))
+ if(newState == SELECTED_STATE || newState == UNSELECTED_STATE)
{
auto* accessible = GetAccessibleObject();
- if(DALI_LIKELY(accessible))
+ if(DALI_LIKELY(accessible) && accessible->IsHighlighted())
{
accessible->EmitStateChanged(Dali::Accessibility::State::CHECKED, mCurrentToggleIndex ? 1 : 0, 0);
accessible->Emit(Dali::Accessibility::ObjectPropertyChangeEvent::DESCRIPTION);
requiredDepthIndex = depthIndex;
}
+ // Change the depth index value automatically if the visual has DepthIndex to AUTO_INDEX
+ // or if RegisterVisual set DepthIndex to AUTO_INDEX.
+ const bool requiredDepthIndexChanged = (requiredDepthIndex == DepthIndex::AUTO_INDEX);
+
// Visual replacement, existing visual should only be removed from stage when replacement ready.
if(!mVisuals.Empty())
{
mVisuals.Erase(registeredVisualsiter);
}
- // If we've not set the depth-index value and the new visual does not have a depth index applied to it, then use the previously set depth-index for this index
- if((depthIndexValueSet == DepthIndexValue::NOT_SET) &&
- (visual.GetDepthIndex() == 0))
+ // If the visual have a depth index as AUTO_INDEX and the new visual does not have a depth index applied to it, then use the previously set depth-index for this index
+ if(requiredDepthIndexChanged)
{
requiredDepthIndex = currentDepthIndex;
+ DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Use replaced visual index. VisualDepthIndex AUTO_INDEX set as: %d\n", requiredDepthIndex);
}
}
if(!visualReplaced) // New registration entry
{
- // If we've not set the depth-index value, we have more than one visual and the visual does not have a depth index, then set it to be the highest
- if((depthIndexValueSet == DepthIndexValue::NOT_SET) &&
- (mVisuals.Size() > 0) &&
- (visual.GetDepthIndex() == 0))
+ // If we have more than one visual and the visual have a depth index as AUTO_INDEX, then set it to be the highest
+ if((mVisuals.Size() > 0) && requiredDepthIndexChanged)
{
- int maxDepthIndex = std::numeric_limits<int>::min();
+ int maxDepthIndex = static_cast<int>(DepthIndex::CONTENT) - 1; // Start at DepthIndex::CONTENT if maxDepth index belongs to a background or no visuals have been added yet.
RegisteredVisualContainer::ConstIterator iter;
const RegisteredVisualContainer::ConstIterator endIter = mVisuals.End();
maxDepthIndex = visualDepthIndex;
}
}
- ++maxDepthIndex; // Add one to the current maximum depth index so that our added visual appears on top
- requiredDepthIndex = std::max(0, maxDepthIndex); // Start at zero if maxDepth index belongs to a background
+ requiredDepthIndex = ++maxDepthIndex; // Add one to the current maximum depth index so that our added visual appears on top.
+ DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Use top of all visuals. VisualDepthIndex AUTO_INDEX set as: %d\n", requiredDepthIndex);
}
}
if(visual)
{
+ // If required depth index still DepthIndex::AUTO_INDEX, Make it as DepthIndex::CONTENT now
+ if(requiredDepthIndex == static_cast<int>(DepthIndex::AUTO_INDEX))
+ {
+ requiredDepthIndex = static_cast<int>(DepthIndex::CONTENT);
+ DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Some strange cases. VisualDepthIndex AUTO_INDEX set as: %d\n", requiredDepthIndex);
+ }
+
// Set determined depth index
visual.SetDepthIndex(requiredDepthIndex);
#define DALI_TOOLKIT_CONTROL_DATA_IMPL_H
/*
- * Copyright (c) 2023 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2024 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.
*/
// EXTERNAL INCLUDES
-#include <dali-toolkit/devel-api/controls/control-devel.h>
#include <dali/devel-api/adaptor-framework/accessibility.h>
#include <dali/public-api/object/property-notification.h>
#include <dali/public-api/object/type-registry.h>
#include <string>
// INTERNAL INCLUDES
+#include <dali-toolkit/devel-api/controls/control-depth-index-ranges.h>
+#include <dali-toolkit/devel-api/controls/control-devel.h>
#include <dali-toolkit/devel-api/visual-factory/visual-base.h>
#include <dali-toolkit/internal/builder/dictionary.h>
#include <dali-toolkit/internal/builder/style.h>
* @param[in,out] visual The visual to register, which can be altered in this function
* @param[in] enabled false if derived class wants to control when visual is set on stage
* @param[in] depthIndexValueSet Set to true if the depthIndex has actually been set manually
- * @param[in] depthIndex The visual's depth-index is set to this
+ * @param[in] depthIndex The visual's depth-index is set to this. If the depth-index is set to DepthIndex::Ranges::AUTO_INDEX,
+ * the actual depth-index of visual will be determind automatically (Use previous visuals depth-index, or placed on top of all other visuals.)
+ * Otherwise, the visual's depth-index is set to clamped value, between DepthIndex::Ranges::MINIMUM_DEPTH_INDEX and DepthIndex::Ranges::MAXIMUM_DEPTH_INDEX.
*
* @note Registering a visual with an index that already has a registered visual will replace it. The replacement will
* occur once the replacement visual is ready (loaded).
*/
- void RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, VisualState::Type enabled, DepthIndexValue::Type depthIndexValueSet, int depthIndex = 0);
+ void RegisterVisual(Property::Index index, Toolkit::Visual::Base& visual, VisualState::Type enabled, DepthIndexValue::Type depthIndexValueSet, int depthIndex = static_cast<int>(Toolkit::DepthIndex::AUTO_INDEX));
/**
* @brief Emits the resource ready signal.
// the designed behaviour of GlView so signal is connected regardless
if(window)
{
+ mPlacementWindow = window;
DevelWindow::VisibilityChangedSignal(window).Connect(this, &DrawableView::OnWindowVisibilityChanged);
}
}
Control::OnSceneDisconnection();
mNativeRenderer->Terminate();
+
+ Window window = mPlacementWindow.GetHandle();
+ if(window)
+ {
+ DevelWindow::VisibilityChangedSignal(window).Disconnect(this, &DrawableView::OnWindowVisibilityChanged);
+ mPlacementWindow.Reset();
+ }
}
void DrawableView::AddRenderer()
#include <dali/devel-api/actors/actor-devel.h>
#include <dali/devel-api/adaptor-framework/native-image-source-queue.h>
#include <dali/public-api/adaptor-framework/window.h>
+#include <dali/public-api/object/weak-handle.h>
#include <dali/public-api/rendering/geometry.h>
#include <dali/public-api/rendering/shader.h>
#include <dali/public-api/signals/render-callback.h>
bool OnRenderCallback(const RenderCallbackInput& renderCallbackInput);
private:
+ WeakHandle<Window> mPlacementWindow;
Dali::Toolkit::GlView::RenderingMode mRenderingMode;
bool mDepth;
}
//Adding VisibilityChange Signal.
- Dali::DevelActor::VisibilityChangedSignal(self).Connect(this, &GlView::OnControlVisibilityChanged);
+ self.InheritedVisibilityChangedSignal().Connect(this, &GlView::OnControlInheritedVisibilityChanged);
}
void GlView::OnSizeSet(const Vector3& targetSize)
return Shader::New(SHADER_GL_VIEW_VERT, fragmentShader, Shader::Hint::NONE, "GL_VIEW");
}
-void GlView::OnControlVisibilityChanged(Dali::Actor actor, bool visible, Dali::DevelActor::VisibilityChange::Type type)
+void GlView::OnControlInheritedVisibilityChanged(Dali::Actor actor, bool visible)
{
Actor self = Self();
- if(self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
+ if(mRenderThread)
{
- if(mRenderThread)
+ if(visible && DevelWindow::Get(self).IsVisible())
+ {
+ mRenderThread->Resume();
+ }
+ else
{
- if(visible && DevelWindow::Get(self).IsVisible())
- {
- mRenderThread->Resume();
- }
- else
- {
- mRenderThread->Pause();
- }
+ mRenderThread->Pause();
}
}
}
if(window)
{
+ mPlacementWindow = window;
DevelWindow::VisibilityChangedSignal(window).Connect(this, &GlView::OnWindowVisibilityChanged);
}
-
- if(mRenderThread)
- {
- if(self.GetProperty<bool>(Actor::Property::VISIBLE) && window.IsVisible())
- {
- mRenderThread->Resume();
- }
- }
}
void GlView::OnSceneDisconnection()
{
Control::OnSceneDisconnection();
- if(mRenderThread)
+ Window window = mPlacementWindow.GetHandle();
+ if(window)
{
- mRenderThread->Pause();
+ DevelWindow::VisibilityChangedSignal(window).Disconnect(this, &GlView::OnWindowVisibilityChanged);
+ mPlacementWindow.Reset();
}
}
#include <dali/devel-api/actors/actor-devel.h>
#include <dali/devel-api/adaptor-framework/native-image-source-queue.h>
#include <dali/public-api/adaptor-framework/window.h>
+#include <dali/public-api/object/weak-handle.h>
#include <dali/public-api/rendering/geometry.h>
#include <dali/public-api/rendering/shader.h>
GlView& operator=(const GlView& GlView);
/**
- * Callback when the visibility of the GlView is changed
+ * Callback when the inherited visibility of the GlView is changed
*/
- void OnControlVisibilityChanged(Dali::Actor actor, bool visible, Dali::DevelActor::VisibilityChange::Type type);
+ void OnControlInheritedVisibilityChanged(Dali::Actor actor, bool visible);
/**
* Callback when the visibility of the window is changed
Dali::NativeImageSourceQueue::ColorFormat GetColorFormat(Dali::Toolkit::GlView::ColorFormat format);
private:
+ WeakHandle<Window> mPlacementWindow;
std::unique_ptr<GlViewRenderThread> mRenderThread;
Dali::NativeImageSourceQueuePtr mNativeImageQueue;
Dali::Toolkit::GlView::RenderingMode mRenderingMode;
/*
- * Copyright (c) 2023 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2024 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.
#include <dali/public-api/object/type-registry.h>
// INTERNAL INCLUDES
+#include <dali-toolkit/devel-api/controls/control-depth-index-ranges.h>
#include <dali-toolkit/devel-api/controls/control-devel.h>
#include <dali-toolkit/devel-api/visual-factory/visual-factory.h>
#include <dali-toolkit/devel-api/visuals/visual-actions-devel.h>
{
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;
+constexpr float FULL_OPACITY = 1.0f;
+constexpr float LOW_OPACITY = 0.2f;
constexpr float TRANSITION_EFFECT_SPEED = 0.3f;
-constexpr int PLACEHOLDER_DEPTH_INDEX = -2;
-constexpr int PREVIOUS_VISUAL_DEPTH_INDEX = -1;
-constexpr int CURRENT_VISUAL_DEPTH_INDEX = 0;
+constexpr int PLACEHOLDER_DEPTH_INDEX = -2;
+constexpr int PREVIOUS_VISUAL_DEPTH_INDEX = -1;
+constexpr int CURRENT_VISUAL_DEPTH_INDEX = 0;
BaseHandle Create()
{
visualImpl.SetCustomShader(mShaderMap);
}
- DevelControl::RegisterVisual(*this, Toolkit::ImageView::Property::IMAGE, visual);
+ DevelControl::RegisterVisual(*this, Toolkit::ImageView::Property::IMAGE, visual, DepthIndex::CONTENT);
}
else
{
mPreviousVisual = mVisual;
}
-
-
// Don't bother comparing if we had a visual previously, just drop old visual and create new one
mUrl = url;
mImageSize = size;
visualImpl.SetCustomShader(mShaderMap);
}
- DevelControl::RegisterVisual(*this, Toolkit::ImageView::Property::IMAGE, visual);
+ DevelControl::RegisterVisual(*this, Toolkit::ImageView::Property::IMAGE, visual, DepthIndex::CONTENT);
}
else
{
bool zeroPadding = (padding == Extents());
Dali::LayoutDirection::Type layoutDirection = static_cast<Dali::LayoutDirection::Type>(
- Self().GetProperty(Dali::Actor::Property::LAYOUT_DIRECTION).Get<int>());
+ Self().GetProperty(Dali::Actor::Property::LAYOUT_DIRECTION).Get<int>());
if(Dali::LayoutDirection::RIGHT_TO_LEFT == layoutDirection)
{
std::swap(padding.start, padding.end);
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, AlphaFunction::EASE_IN_OUT);
+ mTransitionAnimation.AnimateBetween(DevelControl::GetVisualProperty(handle, Toolkit::ImageView::Property::IMAGE, Toolkit::Visual::Property::OPACITY), fadeinKeyFrames, AlphaFunction::EASE_IN_OUT);
imageVisual.SetDepthIndex(imageVisual.GetDepthIndex() + CURRENT_VISUAL_DEPTH_INDEX);
}
/*
- * Copyright (c) 2023 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2024 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.
#include <dali-toolkit/internal/controls/progress-bar/progress-bar-impl.h>
// EXTERNAL INCLUDES
+#include <dali-toolkit/devel-api/controls/control-depth-index-ranges.h>
#include <dali-toolkit/devel-api/controls/control-devel.h>
#include <dali-toolkit/devel-api/visual-factory/visual-base.h>
#include <dali-toolkit/devel-api/visual-factory/visual-factory.h>
// Enum to make sure the visual order
enum
{
- TRACK_VISUAL,
+ TRACK_VISUAL = Toolkit::DepthIndex::CONTENT,
SECONDARY_PROGRESS_VISUAL,
PROGRESS_VISUAL,
LABEL_VISUAL,
Toolkit::ProgressBar self = Toolkit::ProgressBar::DownCast(Self());
mValueChangedSignal.Emit(self, mProgressValue, mSecondaryProgressValue);
- if(Self() == Dali::Accessibility::Accessible::GetCurrentlyHighlightedActor())
+
+ auto accessible = GetAccessibleObject();
+ if(DALI_LIKELY(accessible) && accessible->IsHighlighted())
{
- auto accessible = GetAccessibleObject();
- if(DALI_LIKELY(accessible))
- {
- accessible->Emit(Dali::Accessibility::ObjectPropertyChangeEvent::VALUE);
- }
+ accessible->Emit(Dali::Accessibility::ObjectPropertyChangeEvent::VALUE);
}
RelayoutRequest();
}
if(scrollableHandle)
{
mScrollPositionIntervalReachedSignal.Emit(scrollableHandle.GetCurrentProperty<float>(mPropertyScrollPosition));
- if(Self() == Dali::Accessibility::Accessible::GetCurrentlyHighlightedActor())
+
+ auto accessible = GetAccessibleObject();
+ if(DALI_LIKELY(accessible) && accessible->IsHighlighted())
{
- auto accessible = GetAccessibleObject();
- if(DALI_LIKELY(accessible))
- {
- accessible->Emit(Dali::Accessibility::ObjectPropertyChangeEvent::VALUE);
- }
+ accessible->Emit(Dali::Accessibility::ObjectPropertyChangeEvent::VALUE);
}
}
}
{
mValue = value;
DisplayValue(mValue, true);
- if(Self() == Dali::Accessibility::Accessible::GetCurrentlyHighlightedActor())
+
+ auto accessible = GetAccessibleObject();
+ if(DALI_LIKELY(accessible) && accessible->IsHighlighted())
{
- auto accessible = GetAccessibleObject();
- if(DALI_LIKELY(accessible))
- {
- accessible->Emit(Dali::Accessibility::ObjectPropertyChangeEvent::VALUE);
- }
+ accessible->Emit(Dali::Accessibility::ObjectPropertyChangeEvent::VALUE);
}
}
DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit, TextEditor, "relativeLineSize", FLOAT, RELATIVE_LINE_SIZE )
DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit, TextEditor, "verticalAlignment", STRING, VERTICAL_ALIGNMENT )
DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit, TextEditor, "selectionPopupStyle", MAP, SELECTION_POPUP_STYLE )
+DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit, TextEditor, "removeFrontInset", BOOLEAN, REMOVE_FRONT_INSET )
+DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit, TextEditor, "removeBackInset", BOOLEAN, REMOVE_BACK_INSET )
DALI_SIGNAL_REGISTRATION(Toolkit, TextEditor, "textChanged", SIGNAL_TEXT_CHANGED )
DALI_SIGNAL_REGISTRATION(Toolkit, TextEditor, "inputStyleChanged", SIGNAL_INPUT_STYLE_CHANGED )
void TextEditor::TextInserted(unsigned int position, unsigned int length, const std::string& content)
{
auto accessible = GetAccessibleObject();
- if(DALI_LIKELY(accessible))
+ if(DALI_LIKELY(accessible) && accessible->IsHighlighted())
{
accessible->EmitTextInserted(position, length, content);
}
void TextEditor::TextDeleted(unsigned int position, unsigned int length, const std::string& content)
{
auto accessible = GetAccessibleObject();
- if(DALI_LIKELY(accessible))
+ if(DALI_LIKELY(accessible) && accessible->IsHighlighted())
{
accessible->EmitTextDeleted(position, length, content);
}
void TextEditor::CursorPositionChanged(unsigned int oldPosition, unsigned int newPosition)
{
auto accessible = GetAccessibleObject();
- if(DALI_LIKELY(accessible))
+ if(DALI_LIKELY(accessible) && accessible->IsHighlighted())
{
accessible->EmitTextCursorMoved(newPosition);
}
mController->ChangedLayoutDirection();
}
+void TextEditor::SetRemoveFrontInset(bool remove)
+{
+ mController->SetRemoveFrontInset(remove);
+}
+
+bool TextEditor::IsRemoveFrontInset() const
+{
+ return mController->IsRemoveFrontInset();
+}
+
+void TextEditor::SetRemoveBackInset(bool remove)
+{
+ mController->SetRemoveBackInset(remove);
+}
+
+bool TextEditor::IsRemoveBackInset() const
+{
+ return mController->IsRemoveBackInset();
+}
+
TextEditor::TextEditor(ControlBehaviour additionalBehaviour)
: Control(ControlBehaviour(CONTROL_BEHAVIOUR_DEFAULT | additionalBehaviour)),
mAnimationPeriod(0.0f, 0.0f),
*/
void AnchorClicked(const std::string& href) override;
+ /**
+ * @brief Set removing front inset to TextEditor.
+ *
+ * @param[in] remove Whether front inset of TextEditor has to be removed or not.
+ */
+ void SetRemoveFrontInset(const bool remove);
+
+ /**
+ * @brief Whether front inset of TextEditor is removed or not.
+ *
+ * @return True if the front inset of TextEditor is removed.
+ */
+ bool IsRemoveFrontInset() const;
+
+ /**
+ * @brief Set removing back inset to TextEditor.
+ *
+ * @param[in] remove Whether back inset of TextEditor has to be removed or not.
+ */
+ void SetRemoveBackInset(const bool remove);
+
+ /**
+ * @brief Whether back inset of TextEditor is removed or not.
+ *
+ * @return True if the back inset of TextEditor is removed.
+ */
+ bool IsRemoveBackInset() const;
+
private: // Implementation
/**
* @copydoc Dali::Toolkit::Text::Controller::(InputMethodContext& inputMethodContext, const InputMethodContext::EventData& inputMethodContextEvent)
}
break;
}
+ case Toolkit::DevelTextEditor::Property::REMOVE_FRONT_INSET:
+ {
+ const bool remove = value.Get<bool>();
+ impl.mController->SetRemoveFrontInset(remove);
+ break;
+ }
+ case Toolkit::DevelTextEditor::Property::REMOVE_BACK_INSET:
+ {
+ const bool remove = value.Get<bool>();
+ impl.mController->SetRemoveBackInset(remove);
+ break;
+ }
}
}
value = map;
break;
}
+ case Toolkit::DevelTextEditor::Property::REMOVE_FRONT_INSET:
+ {
+ value = impl.mController->IsRemoveFrontInset();
+ break;
+ }
+ case Toolkit::DevelTextEditor::Property::REMOVE_BACK_INSET:
+ {
+ value = impl.mController->IsRemoveBackInset();
+ break;
+ }
} //switch
return value;
}
DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit, TextField, "inputStrikethrough", MAP, INPUT_STRIKETHROUGH )
DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit, TextField, "characterSpacing", FLOAT, CHARACTER_SPACING )
DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit, TextField, "selectionPopupStyle", MAP, SELECTION_POPUP_STYLE )
+DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit, TextField, "removeFrontInset", BOOLEAN, REMOVE_FRONT_INSET )
+DALI_DEVEL_PROPERTY_REGISTRATION(Toolkit, TextField, "removeBackInset", BOOLEAN, REMOVE_BACK_INSET )
DALI_SIGNAL_REGISTRATION(Toolkit, TextField, "textChanged", SIGNAL_TEXT_CHANGED )
DALI_SIGNAL_REGISTRATION(Toolkit, TextField, "maxLengthReached", SIGNAL_MAX_LENGTH_REACHED )
void TextField::TextInserted(unsigned int position, unsigned int length, const std::string& content)
{
auto accessible = GetAccessibleObject();
- if(DALI_LIKELY(accessible))
+ if(DALI_LIKELY(accessible) && accessible->IsHighlighted())
{
accessible->EmitTextInserted(position, length, content);
}
void TextField::TextDeleted(unsigned int position, unsigned int length, const std::string& content)
{
auto accessible = GetAccessibleObject();
- if(DALI_LIKELY(accessible))
+ if(DALI_LIKELY(accessible) && accessible->IsHighlighted())
{
accessible->EmitTextDeleted(position, length, content);
}
void TextField::CursorPositionChanged(unsigned int oldPosition, unsigned int newPosition)
{
auto accessible = GetAccessibleObject();
- if(DALI_LIKELY(accessible))
+ if(DALI_LIKELY(accessible) && accessible->IsHighlighted())
{
accessible->EmitTextCursorMoved(newPosition);
}
mController->SetSpannedText(spannedText);
}
+void TextField::SetRemoveFrontInset(bool remove)
+{
+ mController->SetRemoveFrontInset(remove);
+}
+
+bool TextField::IsRemoveFrontInset() const
+{
+ return mController->IsRemoveFrontInset();
+}
+
+void TextField::SetRemoveBackInset(bool remove)
+{
+ mController->SetRemoveBackInset(remove);
+}
+
+bool TextField::IsRemoveBackInset() const
+{
+ return mController->IsRemoveBackInset();
+}
+
std::string TextField::TextFieldAccessible::GetName() const
{
if(IsHiddenInput())
*/
void SetSpannedText(const Text::Spanned& spannedText);
+ /**
+ * @brief Set removing front inset to TextField.
+ *
+ * @param[in] remove Whether front inset of TextField has to be removed or not.
+ */
+ void SetRemoveFrontInset(const bool remove);
+
+ /**
+ * @brief Whether front inset of TextField is removed or not.
+ *
+ * @return True if the front inset of TextField is removed.
+ */
+ bool IsRemoveFrontInset() const;
+
+ /**
+ * @brief Set removing back inset to TextField.
+ *
+ * @param[in] remove Whether back inset of TextField has to be removed or not.
+ */
+ void SetRemoveBackInset(const bool remove);
+
+ /**
+ * @brief Whether back inset of TextField is removed or not.
+ *
+ * @return True if the back inset of TextField is removed.
+ */
+ bool IsRemoveBackInset() const;
+
private: // Implementation
/**
* @copydoc Dali::Toolkit::Text::Controller::(InputMethodContext& inputMethodContext, const InputMethodContext::EventData& inputMethodContextEvent)
}
break;
}
+ case Toolkit::DevelTextField::Property::REMOVE_FRONT_INSET:
+ {
+ const bool remove = value.Get<bool>();
+ impl.mController->SetRemoveFrontInset(remove);
+ break;
+ }
+ case Toolkit::DevelTextField::Property::REMOVE_BACK_INSET:
+ {
+ const bool remove = value.Get<bool>();
+ impl.mController->SetRemoveBackInset(remove);
+ break;
+ }
}
}
value = map;
break;
}
+ case Toolkit::DevelTextField::Property::REMOVE_FRONT_INSET:
+ {
+ value = impl.mController->IsRemoveFrontInset();
+ break;
+ }
+ case Toolkit::DevelTextField::Property::REMOVE_BACK_INSET:
+ {
+ value = impl.mController->IsRemoveBackInset();
+ break;
+ }
+
} //switch
return value;
}
/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2024 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.
* The alignment depends on the alignment value of the text label (Use Text::VerticalAlignment enumerations).
*/
const float VERTICAL_ALIGNMENT_TABLE[Text::VerticalAlignment::BOTTOM + 1] =
-{
+ {
0.0f, // VerticalAlignment::TOP
0.5f, // VerticalAlignment::CENTER
1.0f // VerticalAlignment::BOTTOM
#endif
const Scripting::StringEnum AUTO_SCROLL_STOP_MODE_TABLE[] =
-{
+ {
{"IMMEDIATE", Toolkit::TextLabel::AutoScrollStopMode::IMMEDIATE},
{"FINISH_LOOP", Toolkit::TextLabel::AutoScrollStopMode::FINISH_LOOP},
};
propertyMap.Add(Toolkit::Visual::Property::TYPE, Toolkit::Visual::TEXT);
mVisual = Toolkit::VisualFactory::Get().CreateVisual(propertyMap);
- DevelControl::RegisterVisual(*this, Toolkit::TextLabel::Property::TEXT, mVisual);
+ DevelControl::RegisterVisual(*this, Toolkit::TextLabel::Property::TEXT, mVisual, DepthIndex::CONTENT);
TextVisual::SetAnimatableTextColorProperty(mVisual, Toolkit::TextLabel::Property::TEXT_COLOR);
mLastAutoScrollEnabled = false;
}
- const Toolkit::TextLabel::AutoScrollStopMode::Type stopMode = mTextScroller->GetStopMode();
- mTextScroller->SetStopMode(Toolkit::TextLabel::AutoScrollStopMode::IMMEDIATE);
- mTextScroller->StopScrolling();
- mTextScroller->SetStopMode(stopMode);
+ if(mTextScroller->IsScrolling())
+ {
+ const Toolkit::TextLabel::AutoScrollStopMode::Type stopMode = mTextScroller->GetStopMode();
+ mTextScroller->SetStopMode(Toolkit::TextLabel::AutoScrollStopMode::IMMEDIATE);
+ mTextScroller->StopScrolling();
+ mTextScroller->SetStopMode(stopMode);
+ }
}
Control::OnSceneDisconnection();
}
{
DALI_LOG_INFO(gLogFilter, Debug::General, "TextLabel::OnRelayout\n");
+ if(mTextScroller && mTextScroller->IsStop())
+ {
+ // When auto scroll is playing, it triggers a relayout only when an update is absolutely necessary.
+ return;
+ }
+
Actor self = Self();
Extents padding;
{
// Pure Virtual from TextScroller Interface
DALI_LOG_INFO(gLogFilter, Debug::General, "TextLabel::ScrollingFinished\n");
-
- if(mController->IsAutoScrollEnabled() || !mController->IsMultiLineEnabled())
- {
- mController->SetAutoScrollEnabled(false);
- RequestTextRelayout();
- }
+ mController->SetAutoScrollEnabled(false);
+ RequestTextRelayout();
}
void TextLabel::OnLayoutDirectionChanged(Actor actor, LayoutDirection::Type type)
#include <dali/public-api/object/type-registry.h>
// INTERNAL INCLUDES
+#include <dali-toolkit/devel-api/controls/control-depth-index-ranges.h>
#include <dali-toolkit/devel-api/controls/control-devel.h>
#include <dali-toolkit/devel-api/controls/web-view/web-back-forward-list.h>
#include <dali-toolkit/devel-api/controls/web-view/web-settings.h>
if(mVisual)
{
- DevelControl::RegisterVisual(*this, Toolkit::WebView::Property::URL, mVisual);
+ DevelControl::RegisterVisual(*this, Toolkit::WebView::Property::URL, mVisual, DepthIndex::CONTENT);
EnableBlendMode(!mVideoHoleEnabled);
}
}
else if((controller.mImpl->mEventData->mPrimaryCursorPosition > 0) && (keyCode == Dali::DALI_KEY_BACKSPACE))
{
// Remove the character before the current cursor position
- removed = TextUpdater::RemoveText(controller, -1, 1, UPDATE_INPUT_STYLE);
+ removed = TextUpdater::RemoveText(controller, -1, 1, UPDATE_INPUT_STYLE, false);
}
else if((controller.mImpl->mEventData->mPrimaryCursorPosition < controller.mImpl->mModel->mLogicalModel->mText.Count()) &&
(keyCode == Dali::DevelKey::DALI_KEY_DELETE))
{
// Remove the character after the current cursor position
- removed = TextUpdater::RemoveText(controller, 0, 1, UPDATE_INPUT_STYLE);
+ removed = TextUpdater::RemoveText(controller, 0, 1, UPDATE_INPUT_STYLE, false);
}
if(removed)
const bool textDeleted = TextUpdater::RemoveText(controller,
inputMethodContextEvent.cursorOffset,
inputMethodContextEvent.numberOfChars,
- DONT_UPDATE_INPUT_STYLE);
+ DONT_UPDATE_INPUT_STYLE,
+ false);
if(textDeleted)
{
const char* EMPTY_STRING = "";
const char* MIME_TYPE_TEXT_PLAIN = "text/plain;charset=utf-8";
+const char* MIME_TYPE_HTML = "application/xhtml+xml";
} // namespace
return false;
}
+bool Controller::Impl::IsClipboardEmpty()
+{
+ bool result(Clipboard::IsAvailable() && EnsureClipboardCreated() && (mClipboard.HasType(MIME_TYPE_TEXT_PLAIN) || mClipboard.HasType(MIME_TYPE_HTML)));
+ return !result;
+}
+
void Controller::Impl::SendSelectionToClipboard(bool deleteAfterSending)
{
std::string selectedText;
return mClipboard != nullptr ? true : false;
}
- bool IsClipboardEmpty()
- {
- bool result(Clipboard::IsAvailable() && EnsureClipboardCreated() && mClipboard.NumberOfItems());
- return !result; // If NumberOfItems greater than 0, return false
- }
-
bool IsClipboardVisible()
{
bool result(Clipboard::IsAvailable() && EnsureClipboardCreated() && mClipboard.IsVisible());
}
/**
+ * @brief Whether the clipboard is empty or not.
+ * Checks the types that the text controller can paste and returns the result.
+ *
+ * @return Return whether or not the clipboard is empty.
+ */
+ bool IsClipboardEmpty();
+
+ /**
* @copydoc Controller::GetLayoutDirection()
*/
Dali::LayoutDirection::Type GetLayoutDirection(Dali::Actor& actor) const;
removedPrevious = RemoveText(controller,
-static_cast<int>(eventData->mPrimaryCursorPosition - eventData->mPreEditStartPosition),
eventData->mPreEditLength,
- DONT_UPDATE_INPUT_STYLE);
+ DONT_UPDATE_INPUT_STYLE,
+ true);
eventData->mPrimaryCursorPosition = eventData->mPreEditStartPosition;
eventData->mPreEditLength = 0u;
Controller& controller,
int cursorOffset,
int numberOfCharacters,
- UpdateInputStyleType type)
+ UpdateInputStyleType type,
+ bool isDeletingPreEdit)
{
bool removed = false;
bool removeAll = false;
if(removeAll)
{
impl.ClearPreEditFlag();
- textUpdateInfo.mNumberOfCharactersToAdd = 0;
+ if(!isDeletingPreEdit)
+ {
+ textUpdateInfo.mNumberOfCharactersToAdd = 0;
+ }
}
// Updates the text style runs by removing characters. Runs with no characters are removed.
* @param[in] cursorOffset Start position from the current cursor position to start deleting characters.
* @param[in] numberOfCharacters The number of characters to delete from the cursorOffset.
* @param[in] type Whether to update the input style.
+ * @param[in] isDeletingPreEdit Whether to remove pre-edit when inserting text.
* @return True if the remove was successful.
*/
- static bool RemoveText(Controller& controller, int cursorOffset, int numberOfCharacters, UpdateInputStyleType type);
+ static bool RemoveText(Controller& controller, int cursorOffset, int numberOfCharacters, UpdateInputStyleType type, bool isDeletingPreEdit);
/**
* @brief Checks if text is selected and if so removes it.
const char* EMPTY_STRING = "";
const char* MIME_TYPE_TEXT_PLAIN = "text/plain;charset=utf-8";
+const char* MIME_TYPE_HTML = "application/xhtml+xml";
template<typename Type>
void EnsureCreated(Type*& object)
return mImpl->mModel->mVisualModel->GetDashedUnderlineGap();
}
+void Controller::SetOutlineOffset(const Vector2& outlineOffset)
+{
+ mImpl->mModel->mVisualModel->SetOutlineOffset(outlineOffset);
+ mImpl->RequestRelayout();
+}
+
+const Vector2& Controller::GetOutlineOffset() const
+{
+ return mImpl->mModel->mVisualModel->GetOutlineOffset();
+}
+
void Controller::SetOutlineColor(const Vector4& color)
{
mImpl->mModel->mVisualModel->SetOutlineColor(color);
return mImpl->mModel->mVisualModel->GetOutlineWidth();
}
+void Controller::SetOutlineBlurRadius(const float& outlineBlurRadius)
+{
+ if(fabsf(GetOutlineBlurRadius() - outlineBlurRadius) > Math::MACHINE_EPSILON_1)
+ {
+ mImpl->mModel->mVisualModel->SetOutlineBlurRadius(outlineBlurRadius);
+ mImpl->RequestRelayout();
+ }
+}
+
+const float& Controller::GetOutlineBlurRadius() const
+{
+ return mImpl->mModel->mVisualModel->GetOutlineBlurRadius();
+}
+
void Controller::SetBackgroundColor(const Vector4& color)
{
mImpl->mModel->mVisualModel->SetBackgroundColor(color);
mImpl->mClipboard.DataReceivedSignal().Disconnect(this, &Controller::PasteClipboardItemEvent);
// If the id is 0u, it is an invalid response.
+ if(id == 0u)
+ {
+ return;
+ }
+
// text-controller allows only plain text type.
- if(id != 0u && !strncmp(mimeType, MIME_TYPE_TEXT_PLAIN, strlen(MIME_TYPE_TEXT_PLAIN)))
+ if(!strncmp(mimeType, MIME_TYPE_TEXT_PLAIN, strlen(MIME_TYPE_TEXT_PLAIN)))
{
EventHandler::PasteClipboardItemEvent(*this, data);
}
+ else if(!strncmp(mimeType, MIME_TYPE_HTML, strlen(MIME_TYPE_HTML)))
+ {
+ // This does not mean that text controls can parse html.
+ // This is temporary code, as text controls do not support html type data.
+ // Simply remove the tags inside the angle brackets.
+ // Once multiple types and data can be stored in the clipboard, this code should be removed.
+ std::regex reg("<[^>]*>");
+ std::string result = regex_replace(data, reg, "");
+
+ EventHandler::PasteClipboardItemEvent(*this, result.c_str());
+ }
}
void Controller::PasteText()
// Connect the signal before calling GetData() of the clipboard.
mImpl->mClipboard.DataReceivedSignal().Connect(this, &Controller::PasteClipboardItemEvent);
+ // If there is no plain text type data on the clipboard, request html type data.
+ std::string mimeType = mImpl->mClipboard.HasType(MIME_TYPE_TEXT_PLAIN) ? MIME_TYPE_TEXT_PLAIN : MIME_TYPE_HTML;
+
// Request clipboard service to retrieve an item.
- uint id = mImpl->mClipboard.GetData(MIME_TYPE_TEXT_PLAIN);
+ uint id = mImpl->mClipboard.GetData(mimeType);
if(id == 0u)
{
// If the return id is 0u, the signal is not emitted, we must disconnect signal here.
float GetDashedUnderlineGap() const;
/**
+ * @brief Set the outline offset.
+ *
+ * @param[in] outlineOffset The outline offset.
+ */
+ void SetOutlineOffset(const Vector2& outlineOffset);
+
+ /**
+ * @brief Retrieve the outline offset.
+ *
+ * @return The outline offset.
+ */
+ const Vector2& GetOutlineOffset() const;
+
+ /**
* @brief Set the outline color.
*
* @param[in] color color of outline.
uint16_t GetOutlineWidth() const;
/**
+ * @brief Set the outline blur radius.
+ *
+ * @param[in] outlineBlurRadius The outline blur radius, 0,0 indicates no blur.
+ */
+ void SetOutlineBlurRadius(const float& outlineBlurRadius);
+
+ /**
+ * @brief Retrieve the outline blur radius.
+ *
+ * @return The outline blur radius.
+ */
+ const float& GetOutlineBlurRadius() const;
+
+ /**
* @brief Set the background color.
*
* @param[in] color color of background.
const bool underlineEnabled = view.IsUnderlineEnabled();
const uint16_t outlineWidth = view.GetOutlineWidth();
const Vector4& outlineColor(view.GetOutlineColor());
+ const Vector2& outlineOffset(view.GetOutlineOffset());
const bool isOutline = 0u != outlineWidth;
const GlyphInfo* hyphens = view.GetHyphens();
const Length* hyphenIndices = view.GetHyphenIndices();
if(0u != slot.mImageId) // invalid slot id, glyph has failed to be added to atlas
{
- Vector2 positionPlusOutlineOffset = position;
+ Vector2 positionPlusOutlineOffset = position + outlineOffset;
if(isOutline)
{
// Add an offset to the text.
// Create the image buffer for outline
Devel::PixelBuffer outlineImageBuffer = CreateImageBuffer(bufferWidth, bufferHeight, Typesetter::STYLE_OUTLINE, ignoreHorizontalAlignment, pixelFormat, penX, penY, startIndexOfGlyphs, endIndexOfGlyphs);
+ const float& blurRadius = mModel->GetOutlineBlurRadius();
+
+ if(blurRadius > Math::MACHINE_EPSILON_1)
+ {
+ outlineImageBuffer.ApplyGaussianBlur(blurRadius);
+ }
+
// Combine the two buffers
CombineImageBuffer(imageBuffer, outlineImageBuffer, bufferWidth, bufferHeight, true);
}
if(style == Typesetter::STYLE_OUTLINE)
{
+ const Vector2& outlineOffset = mModel->GetOutlineOffset();
+
glyphData.horizontalOffset -= outlineWidth;
+ glyphData.horizontalOffset += outlineOffset.x;
if(lineIndex == 0u)
{
// Only need to add the vertical outline offset for the first line
glyphData.verticalOffset -= outlineWidth;
+ glyphData.verticalOffset += outlineOffset.y;
}
}
else if(style == Typesetter::STYLE_SHADOW)
mModel->GetUnderlineRuns(underlineRuns, index, numberOfRuns);
}
+const Vector2& ViewModel::GetOutlineOffset() const
+{
+ return mModel->GetOutlineOffset();
+}
+
const Vector4& ViewModel::GetOutlineColor() const
{
return mModel->GetOutlineColor();
return mModel->GetOutlineWidth();
}
+const float& ViewModel::GetOutlineBlurRadius() const
+{
+ return mModel->GetOutlineBlurRadius();
+}
+
const Vector4& ViewModel::GetBackgroundColor() const
{
return mModel->GetBackgroundColor();
void GetUnderlineRuns(UnderlinedGlyphRun* underlineRuns, UnderlineRunIndex index, Length numberOfRuns) const override;
/**
+ * @copydoc ModelInterface::GetOutlineOffset()
+ */
+ const Vector2& GetOutlineOffset() const override;
+
+ /**
* @copydoc ModelInterface::GetOutlineColor()
*/
const Vector4& GetOutlineColor() const override;
uint16_t GetOutlineWidth() const override;
/**
+ * @copydoc ModelInterface::GetOutlineBlurRadius()
+ */
+ const float& GetOutlineBlurRadius() const override;
+
+ /**
* @copydoc ModelInterface::GetBackgroundColor()
*/
const Vector4& GetBackgroundColor() const override;
#define DALI_TOOLKIT_INTERNAL_TEXT_SPANS_CONTAINER_IMPL_H
/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2024 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.
} // namespace Toolkit
-// Allow SpanRangesContainer to be treated as a POD type
-template<>
-struct TypeTraits<Dali::Toolkit::Text::Internal::SpanRangesContainer> : public Dali::BasicTypes<Dali::Toolkit::Text::Internal::SpanRangesContainer>
-{
- enum
- {
- IS_TRIVIAL_TYPE = true
- };
-};
-
} // namespace Dali
#endif // DALI_TOOLKIT_INTERNAL_TEXT_SPANS_CONTAINER_IMPL_H
#define DALI_TOOLKIT_INTERNAL_TEXT_SPANNABLE_IMPL_H
/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2024 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.
} // namespace Toolkit
-// Allow Spannable to be treated as a POD type
-template<>
-struct TypeTraits<Dali::Toolkit::Text::Internal::Spannable> : public Dali::BasicTypes<Dali::Toolkit::Text::Internal::Spannable>
-{
- enum
- {
- IS_TRIVIAL_TYPE = true
- };
-};
-
} // namespace Dali
#endif // DALI_TOOLKIT_INTERNAL_TEXT_SPANNABLE_IMPL_H
#define DALI_TOOLKIT_INTERNAL_TEXT_SPANNABLE_STRING_IMPL_H
/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2024 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.
} // namespace Toolkit
-// Allow SpannableString to be treated as a POD type
-template<>
-struct TypeTraits<Dali::Toolkit::Text::Internal::SpannableString> : public Dali::BasicTypes<Dali::Toolkit::Text::Internal::SpannableString>
-{
- enum
- {
- IS_TRIVIAL_TYPE = true
- };
-};
-
} // namespace Dali
#endif // DALI_TOOLKIT_INTERNAL_TEXT_SPANNABLE_STRING_IMPL_H
#define DALI_TOOLKIT_INTERNAL_TEXT_SPANNED_IMPL_H
/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2024 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.
} // namespace Toolkit
-// Allow Spanned to be treated as a POD type
-template<>
-struct TypeTraits<Dali::Toolkit::Text::Internal::Spanned> : public Dali::BasicTypes<Dali::Toolkit::Text::Internal::Spanned>
-{
- enum
- {
- IS_TRIVIAL_TYPE = true
- };
-};
-
} // namespace Dali
#endif // DALI_TOOLKIT_INTERNAL_TEXT_SPANNED_IMPL_H
#define DALI_TOOLKIT_INTERNAL_TEXT_BASE_SPAN_IMPL_H
/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2024 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.
} // namespace Toolkit
-// Allow BaseSpan to be treated as a POD type
-template<>
-struct TypeTraits<Dali::Toolkit::Text::Internal::BaseSpan> : public Dali::BasicTypes<Dali::Toolkit::Text::Internal::BaseSpan>
-{
- enum
- {
- IS_TRIVIAL_TYPE = true
- };
-};
-
} // namespace Dali
#endif // DALI_TOOLKIT_INTERNAL_TEXT_BASE_SPAN_IMPL_H
#define DALI_TOOLKIT_INTERNAL_TEXT_CHARACTER_SEQUENCE_IMPL_H
/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2024 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.
} // namespace Toolkit
-// Allow AbstractStyleSpan to be treated as a POD type
-template<>
-struct TypeTraits<Dali::Toolkit::Text::Internal::CharacterSequence> : public Dali::BasicTypes<Dali::Toolkit::Text::Internal::CharacterSequence>
-{
- enum
- {
- IS_TRIVIAL_TYPE = true
- };
-};
-
} // namespace Dali
#endif // DALI_TOOLKIT_INTERNAL_TEXT_CHARACTER_SEQUENCE_IMPL_H
#define DALI_TOOLKIT_INTERNAL_TEXT_RANGE_IMPL_H
/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2024 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.
} // namespace Toolkit
-// Allow Range to be treated as a POD type
-template<>
-struct TypeTraits<Dali::Toolkit::Text::Internal::Range> : public Dali::BasicTypes<Dali::Toolkit::Text::Internal::Range>
-{
- enum
- {
- IS_TRIVIAL_TYPE = true
- };
-};
-
} // namespace Dali
#endif // DALI_TOOLKIT_INTERNAL_TEXT_RANGE_IMPL_H
bool& colorDefined,
Vector4& color,
bool& widthDefined,
- uint16_t& width)
+ uint16_t& width,
+ bool& offsetDefined,
+ Vector2& offset,
+ bool& blurRadiusDefined,
+ float& blurRadius)
{
const unsigned int numberOfItems = underlinePropertiesMap.Count();
widthDefined = true;
width = static_cast<uint16_t>(valueGet.second.Get<float>());
}
+ else if((DevelText::Outline::Property::OFFSET == valueGet.first.indexKey) || (OFFSET_KEY == valueGet.first.stringKey))
+ {
+ /// Offset key.
+ offsetDefined = true;
+
+ if(valueGet.second.GetType() == Dali::Property::STRING)
+ {
+ const std::string offsetStr = valueGet.second.Get<std::string>();
+ StringToVector2(offsetStr.c_str(), offsetStr.size(), offset);
+ }
+ else
+ {
+ offset = valueGet.second.Get<Vector2>();
+ }
+ }
+ else if((DevelText::Outline::Property::BLUR_RADIUS == valueGet.first.indexKey) || (BLUR_RADIUS_KEY == valueGet.first.stringKey))
+ {
+ /// Blur radius key.
+ blurRadiusDefined = true;
+
+ if(valueGet.second.GetType() == Dali::Property::STRING)
+ {
+ const std::string blurRadiusStr = valueGet.second.Get<std::string>();
+ blurRadius = StringToFloat(blurRadiusStr.c_str());
+ }
+ else
+ {
+ blurRadius = valueGet.second.Get<float>();
+ }
+ }
}
return 0u == numberOfItems;
{
const Property::Map& propertiesMap = value.Get<Property::Map>();
- bool colorDefined = false;
+ bool colorDefined = false;
Vector4 color;
- bool widthDefined = false;
- uint16_t width = 0u;
+ bool widthDefined = false;
+ uint16_t width = 0u;
+ bool offsetDefined = false;
+ Vector2 offset;
+ bool blurRadiusDefined = false;
+ float blurRadius;
bool empty = true;
colorDefined,
color,
widthDefined,
- width);
+ width,
+ offsetDefined,
+ offset,
+ blurRadiusDefined,
+ blurRadius);
controller->OutlineSetByString(false);
}
controller->SetOutlineWidth(width);
update = true;
}
+
+ if(offsetDefined && (controller->GetOutlineOffset() != offset))
+ {
+ controller->SetOutlineOffset(offset);
+ update = true;
+ }
+
+ if(blurRadiusDefined && (!Dali::Equals(controller->GetOutlineBlurRadius(), blurRadius)))
+ {
+ controller->SetOutlineBlurRadius(blurRadius);
+ update = true;
+ }
}
else
{
}
else
{
- const Vector4& color = controller->GetOutlineColor();
- const uint16_t width = controller->GetOutlineWidth();
+ const Vector4& color = controller->GetOutlineColor();
+ const uint16_t width = controller->GetOutlineWidth();
+ const Vector2& offset = controller->GetOutlineOffset();
+ const float& blurRadius = controller->GetOutlineBlurRadius();
Property::Map map;
map.Insert(COLOR_KEY, color);
map.Insert(WIDTH_KEY, static_cast<int>(width));
+ map.Insert(OFFSET_KEY, offset);
+ map.Insert(BLUR_RADIUS_KEY, blurRadius);
value = map;
virtual void GetUnderlineRuns(UnderlinedGlyphRun* underlineRuns, UnderlineRunIndex index, Length numberOfRuns) const = 0;
/**
+ * @brief Retrieves the outline offset.
+ *
+ * @return The outline offset.
+ */
+ virtual const Vector2& GetOutlineOffset() const = 0;
+
+ /**
* @brief Retrieve the outline color.
*
* @return The outline color.
virtual uint16_t GetOutlineWidth() const = 0;
/**
+ * @brief Retrieve the outline blur radius.
+ *
+ * @return The outline blur radius.
+ */
+ virtual const float& GetOutlineBlurRadius() const = 0;
+
+ /**
* @brief Retrieves the background color.
*
* @return The background color.
mVisualModel->GetUnderlineRuns(underlineRuns, index, numberOfRuns);
}
+const Vector2& Model::GetOutlineOffset() const
+{
+ return mVisualModel->GetOutlineOffset();
+}
+
const Vector4& Model::GetOutlineColor() const
{
return mVisualModel->GetOutlineColor();
return mVisualModel->GetOutlineWidth();
}
+const float& Model::GetOutlineBlurRadius() const
+{
+ return mVisualModel->mOutlineBlurRadius;
+}
+
const Vector4& Model::GetBackgroundColor() const
{
return mVisualModel->GetBackgroundColor();
void GetUnderlineRuns(UnderlinedGlyphRun* underlineRuns, UnderlineRunIndex index, Length numberOfRuns) const override;
/**
+ * @copydoc ModelInterface::GetOutlineOffset()
+ */
+ const Vector2& GetOutlineOffset() const override;
+
+ /**
* @copydoc ModelInterface::GetOutlineColor()
*/
const Vector4& GetOutlineColor() const override;
uint16_t GetOutlineWidth() const override;
/**
+ * @copydoc ModelInterface::GetOutlineBlurRadius()
+ */
+ const float& GetOutlineBlurRadius() const override;
+
+ /**
* @copydoc ModelInterface::GetBackgroundColor()
*/
const Vector4& GetBackgroundColor() const override;
void TextScroller::StopScrolling()
{
- if(mScrollAnimation && mScrollAnimation.GetState() == Animation::PLAYING)
+ if(IsScrolling())
{
switch(mStopMode)
{
case TextLabel::AutoScrollStopMode::IMMEDIATE:
{
+ mIsStop = true;
mScrollAnimation.Stop();
- mScrollerInterface.ScrollingFinished();
break;
}
case TextLabel::AutoScrollStopMode::FINISH_LOOP:
{
+ mIsStop = true;
mScrollAnimation.SetLoopCount(1); // As animation already playing this allows the current animation to finish instead of trying to stop mid-way
break;
}
}
}
+bool TextScroller::IsStop()
+{
+ return mIsStop;
+}
+
+bool TextScroller::IsScrolling()
+{
+ return (mScrollAnimation && mScrollAnimation.GetState() == Animation::PLAYING);
+}
+
TextLabel::AutoScrollStopMode::Type TextScroller::GetStopMode() const
{
return mStopMode;
mLoopCount(1),
mLoopDelay(0.0f),
mWrapGap(0.0f),
- mStopMode(TextLabel::AutoScrollStopMode::FINISH_LOOP)
+ mStopMode(TextLabel::AutoScrollStopMode::FINISH_LOOP),
+ mIsStop(false)
{
DALI_LOG_INFO(gLogFilter, Debug::Verbose, "TextScroller Default Constructor\n");
}
void TextScroller::SetParameters(Actor scrollingTextActor, Renderer renderer, TextureSet textureSet, const Size& controlSize, const Size& textureSize, const float wrapGap, CharacterDirection direction, HorizontalAlignment::Type horizontalAlignment, VerticalAlignment::Type verticalAlignment)
{
DALI_LOG_INFO(gLogFilter, Debug::Verbose, "TextScroller::SetParameters controlSize[%f,%f] textureSize[%f,%f] direction[%d]\n", controlSize.x, controlSize.y, textureSize.x, textureSize.y, direction);
-
mRenderer = renderer;
float animationProgress = 0.0f;
if(mLoopCount > 0) // If not a ininity loop, then calculate remained loop
{
remainedLoop = mLoopCount - (mScrollAnimation.GetCurrentLoop());
- remainedLoop = (remainedLoop <= 0 ? 1 : remainedLoop);
+ remainedLoop = mIsStop ? 1 : (remainedLoop <= 0 ? 1 : remainedLoop);
}
}
mScrollAnimation.Clear();
void TextScroller::AutoScrollAnimationFinished(Dali::Animation& animation)
{
DALI_LOG_INFO(gLogFilter, Debug::Verbose, "TextScroller::AutoScrollAnimationFinished\n");
+ mIsStop = false;
mScrollerInterface.ScrollingFinished();
// Revert to the original shader and texture after scrolling
void TextScroller::StartScrolling(Actor scrollingTextActor, float scrollAmount, float scrollDuration, int loopCount)
{
DALI_LOG_INFO(gLogFilter, Debug::Verbose, "TextScroller::StartScrolling scrollAmount[%f] scrollDuration[%f], loop[%d] speed[%d]\n", scrollAmount, scrollDuration, loopCount, mScrollSpeed);
-
Shader shader = mRenderer.GetShader();
mScrollAnimation = Animation::New(scrollDuration);
mScrollAnimation.AnimateTo(Property(shader, mScrollDeltaIndex), scrollAmount, TimePeriod(mLoopDelay, scrollDuration));
mScrollAnimation.SetLoopCount(loopCount);
mScrollAnimation.FinishedSignal().Connect(this, &TextScroller::AutoScrollAnimationFinished);
mScrollAnimation.Play();
+
+ mIsStop = false;
}
} // namespace Text
void StopScrolling();
/**
+ * @brief Whether the stop scrolling has been triggered or not.
+ */
+ bool IsStop();
+
+ /**
+ * @brief Whether the scroll animation is playing or not.
+ */
+ bool IsScrolling();
+
+ /**
* @brief Get the mode of scrolling stop
* @return stopMode type when text scrolling is stoped.
*/
float mLoopDelay; ///< Time delay of loop start
float mWrapGap; ///< Gap before text wraps around when scrolling
TextLabel::AutoScrollStopMode::Type mStopMode; ///< Stop mode of scrolling text, when loop count is 0.
+ bool mIsStop : 1; ///< Whether the stop scrolling has been triggered or not.
}; // TextScroller class
Length numberOfRuns) const = 0;
/**
+ * @brief Retrieves the outline offset.
+ *
+ * @return The outline offset.
+ */
+ virtual const Vector2& GetOutlineOffset() const = 0;
+
+ /**
* @brief Retrieve the outline color.
*
* @return The outline color.
}
}
+const Vector2& View::GetOutlineOffset() const
+{
+// TODO : We should support outline offset to editable text.
+/*
+ if(mImpl->mVisualModel)
+ {
+ return mImpl->mVisualModel->GetOutlineOffset();
+ }
+*/
+ return Vector2::ZERO;
+}
+
const Vector4& View::GetOutlineColor() const
{
if(mImpl->mVisualModel)
Length numberOfRuns) const;
/**
+ * @copydoc Dali::Toolkit::Text::ViewInterface::GetOutlineOffset()
+ */
+ const Vector2& GetOutlineOffset() const override;
+
+ /**
* @copydoc Dali::Toolkit::Text::ViewInterface::GetOutlineColor()
*/
const Vector4& GetOutlineColor() const override;
mUnderlineColorSet = true;
}
+void VisualModel::SetOutlineOffset(const Vector2& outlineOffset)
+{
+ mOutlineOffset = outlineOffset;
+}
+
void VisualModel::SetOutlineColor(const Vector4& color)
{
mOutlineColor = color;
}
+void VisualModel::SetOutlineBlurRadius(const float& outlineBlurRadius)
+{
+ mOutlineBlurRadius = outlineBlurRadius;
+}
+
void VisualModel::SetUnderlineEnabled(bool enabled)
{
mUnderlineEnabled = enabled;
return mUnderlineColor;
}
+const Vector2& VisualModel::GetOutlineOffset() const
+{
+ return mOutlineOffset;
+}
+
const Vector4& VisualModel::GetOutlineColor() const
{
return mOutlineColor;
}
+const float& VisualModel::GetOutlineBlurRadius() const
+{
+ return mOutlineBlurRadius;
+}
+
bool VisualModel::IsUnderlineEnabled() const
{
return mUnderlineEnabled;
mStrikethroughColor(Color::BLACK),
mControlSize(),
mShadowOffset(),
+ mOutlineOffset(),
mUnderlineHeight(0.0f),
mStrikethroughHeight(0.0f),
mUnderlineType(Text::Underline::SOLID),
mDashedUnderlineWidth(2.0f),
mDashedUnderlineGap(1.0f),
mShadowBlurRadius(0.0f),
+ mOutlineBlurRadius(0.0f),
mOutlineWidth(0u),
mNaturalSize(),
mLayoutSize(),
Length GetNumberOfUnderlineRuns() const;
/**
+ * @brief Sets the text's outline offset.
+ *
+ * @param[in] outlineOffset The outline offset.
+ */
+ void SetOutlineOffset(const Vector2& outlineOffset);
+
+ /**
* @brief Set the outline color.
*
* @param[in] color color of outline.
void SetOutlineColor(const Vector4& color);
/**
+ * @brief Retrieves the text's outline offset.
+ *
+ * @return The text's outline offset.
+ */
+ const Vector2& GetOutlineOffset() const;
+
+ /**
* @brief Retrieve the outline color.
*
* @return The outline color.
uint16_t GetOutlineWidth() const;
/**
+ * @brief Set the outline blur radius.
+ *
+ * @param[in] outlineBlurRadius The outline blur radius, 0,0 indicates no blur.
+ */
+ void SetOutlineBlurRadius(const float& outlineBlurRadius);
+
+ /**
+ * @brief Retrieve the outline blur radius.
+ *
+ * @return The outline blur radius.
+ */
+ const float& GetOutlineBlurRadius() const;
+
+ /**
* @brief Sets the text's background color.
*
* @param[in] color The text's background color.
Vector4 mStrikethroughColor; ///< Color of text background
Size mControlSize; ///< The size of the UI control.
Vector2 mShadowOffset; ///< Offset for drop shadow, 0 indicates no shadow
+ Vector2 mOutlineOffset; ///< Offset for outline
float mUnderlineHeight; ///< Fixed height for underline to override font metrics.
float mStrikethroughHeight; ///< Fixed height for strikethrough to override font metrics.
Text::Underline::Type mUnderlineType; ///< The type of the underline.
float mDashedUnderlineWidth; ///< The width of the dashes of the dashed underline.
float mDashedUnderlineGap; ///< The gap between the dashes of the dashed underline.
float mShadowBlurRadius; ///< Blur radius of shadow, 0 indicates no blur.
+ float mOutlineBlurRadius; ///< Blur radius of outline, 0 indicates no blur.
uint16_t mOutlineWidth; ///< Width of outline.
Vector<StrikethroughGlyphRun> mStrikethroughRuns; ///< Runs of glyphs that have strikethrough.
Vector<CharacterSpacingGlyphRun> mCharacterSpacingRuns; ///< Runs of glyphs that have character-spacing.
/*
- * Copyright (c) 2023 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2024 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.
TextureManager::TextureManager(bool loadYuvPlanes)
: mTextureCacheManager(),
mAsyncLoader(std::unique_ptr<TextureAsyncLoadingHelper>(new TextureAsyncLoadingHelper(*this))),
- mLifecycleObservers(),
mLoadQueue(),
mLoadingQueueTextureId(INVALID_TEXTURE_ID),
mRemoveQueue(),
Adaptor::Get().UnregisterProcessor(*this, true);
mRemoveProcessorRegistered = false;
}
-
- for(auto iter = mLifecycleObservers.Begin(), endIter = mLifecycleObservers.End(); iter != endIter; ++iter)
- {
- (*iter)->TextureManagerDestroyed();
- }
}
TextureSet TextureManager::LoadAnimatedImageTexture(
}
}
-void TextureManager::AddObserver(TextureManager::LifecycleObserver& observer)
-{
- // make sure an observer doesn't observe the same object twice
- // otherwise it will get multiple calls to ObjectDestroyed()
- DALI_ASSERT_DEBUG(mLifecycleObservers.End() == std::find(mLifecycleObservers.Begin(), mLifecycleObservers.End(), &observer));
- mLifecycleObservers.PushBack(&observer);
-}
-
-void TextureManager::RemoveObserver(TextureManager::LifecycleObserver& observer)
-{
- // Find the observer...
- auto endIter = mLifecycleObservers.End();
- for(auto iter = mLifecycleObservers.Begin(); iter != endIter; ++iter)
- {
- if((*iter) == &observer)
- {
- mLifecycleObservers.Erase(iter);
- break;
- }
- }
- DALI_ASSERT_DEBUG(endIter != mLifecycleObservers.End());
-}
-
void TextureManager::LoadOrQueueTexture(TextureManager::TextureInfo& textureInfo, TextureUploadObserver* observer)
{
switch(textureInfo.loadState)
#define DALI_TOOLKIT_TEXTURE_MANAGER_IMPL_H
/*
- * Copyright (c) 2023 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2024 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.
using MaskingDataPointer = std::unique_ptr<MaskingData>;
/**
- * Class to provide lifecycle event on destruction of texture manager.
- */
- struct LifecycleObserver
- {
- /**
- * Called shortly before the texture manager is destroyed.
- */
- virtual void TextureManagerDestroyed() = 0;
- };
-
- /**
* Constructor.
*
* @param[in] loadYuvPlanes Whether we allow to load YuvPlanes or not. Default is false.
TextureManager::MultiplyOnLoad& preMultiplyOnLoad);
/**
- * Add an observer to the object.
- * @param[in] observer The observer to add.
- */
- void AddObserver(TextureManager::LifecycleObserver& observer);
-
- /**
- * Remove an observer from the object
- * @pre The observer has already been added.
- * @param[in] observer The observer to remove.
- */
- void RemoveObserver(TextureManager::LifecycleObserver& observer);
-
- /**
* @brief Returns the geometry associated with texture.
* @param[in] textureId Id of the texture
* @param[out] frontElements number of front elements
private: // Member Variables:
TextureCacheManager mTextureCacheManager; ///< Manager the life-cycle and caching of Textures
- std::unique_ptr<TextureAsyncLoadingHelper> mAsyncLoader; ///< The Asynchronous image loader used to provide all local async loads
- Dali::Vector<LifecycleObserver*> mLifecycleObservers; ///< Lifecycle observers of texture manager
+ std::unique_ptr<TextureAsyncLoadingHelper> mAsyncLoader; ///< The Asynchronous image loader used to provide all local async loads
Dali::Vector<QueueElement> mLoadQueue; ///< Queue of textures to load after NotifyObservers
TextureManager::TextureId mLoadingQueueTextureId; ///< TextureId when it is loading. it causes Load Textures to be queued.
/*
- * Copyright (c) 2023 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2024 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.
#include <dali-toolkit/internal/visuals/animated-image/animated-image-visual.h>
// EXTERNAL INCLUDES
-#include <dali/devel-api/adaptor-framework/window-devel.h>
#include <dali/devel-api/adaptor-framework/image-loading.h>
+#include <dali/devel-api/adaptor-framework/window-devel.h>
#include <dali/integration-api/debug.h>
#include <dali/public-api/rendering/decorated-visual-renderer.h>
#include <memory>
map.Insert(Toolkit::ImageVisual::Property::FRAME_DELAY, static_cast<int>(mFrameDelay));
map.Insert(Toolkit::DevelImageVisual::Property::LOOP_COUNT, static_cast<int>(mLoopCount));
map.Insert(Toolkit::DevelImageVisual::Property::CURRENT_FRAME_NUMBER, (mImageCache) ? static_cast<int32_t>(mImageCache->GetCurrentFrameIndex()) : -1);
- map.Insert(Toolkit::DevelImageVisual::Property::TOTAL_FRAME_NUMBER, (mImageCache) ? static_cast<int32_t>((mAnimatedImageLoading) ? mAnimatedImageLoading.GetImageCount() : mImageCache->GetTotalFrameCount()) : -1);
+
+ // This returns -1 until the loading is finished.
+ int32_t frameCount = mFrameCount;
+ if(mImageCache && frameCount == 0)
+ {
+ frameCount = mImageCache->GetTotalFrameCount();
+
+ if(frameCount <= SINGLE_IMAGE_COUNT && mAnimatedImageLoading && mAnimatedImageLoading.HasLoadingSucceeded())
+ {
+ frameCount = mAnimatedImageLoading.GetImageCount();
+ }
+ else
+ {
+ frameCount = -1;
+ }
+ }
+
+ map.Insert(Toolkit::DevelImageVisual::Property::TOTAL_FRAME_NUMBER, static_cast<int>(frameCount));
map.Insert(Toolkit::DevelImageVisual::Property::STOP_BEHAVIOR, mStopBehavior);
mPlacementActor = actor;
PrepareTextureSet();
- DevelActor::VisibilityChangedSignal(actor).Connect(this, &AnimatedImageVisual::OnControlVisibilityChanged);
+ actor.InheritedVisibilityChangedSignal().Connect(this, &AnimatedImageVisual::OnControlInheritedVisibilityChanged);
Window window = DevelWindow::Get(actor);
if(window)
{
+ mPlacementWindow = window;
DevelWindow::VisibilityChangedSignal(window).Connect(this, &AnimatedImageVisual::OnWindowVisibilityChanged);
}
}
mCurrentFrameIndex = FIRST_FRAME_INDEX;
mCurrentLoopIndex = FIRST_LOOP;
- DevelActor::VisibilityChangedSignal(actor).Disconnect(this, &AnimatedImageVisual::OnControlVisibilityChanged);
+ actor.InheritedVisibilityChangedSignal().Disconnect(this, &AnimatedImageVisual::OnControlInheritedVisibilityChanged);
- Window window = DevelWindow::Get(actor);
+ Window window = mPlacementWindow.GetHandle();
if(window)
{
DevelWindow::VisibilityChangedSignal(window).Disconnect(this, &AnimatedImageVisual::OnWindowVisibilityChanged);
+ mPlacementWindow.Reset();
}
}
}
}
-void AnimatedImageVisual::OnControlVisibilityChanged(Actor actor, bool visible, DevelActor::VisibilityChange::Type type)
+void AnimatedImageVisual::OnControlInheritedVisibilityChanged(Actor actor, bool visible)
{
if(!visible && mActionStatus != DevelAnimatedImageVisual::Action::STOP)
{
mActionStatus = DevelAnimatedImageVisual::Action::STOP;
DisplayNextFrame();
- DALI_LOG_INFO(gAnimImgLogFilter, Debug::Verbose, "AnimatedImageVisual::OnControlVisibilityChanged: invisibile. Pause animation [%p]\n", this);
+ DALI_LOG_INFO(gAnimImgLogFilter, Debug::Verbose, "AnimatedImageVisual::OnControlInheritedVisibilityChanged: invisibile. Pause animation [%p]\n", this);
}
}
void CheckMaskTexture();
/**
- * @brief Callback when the visibility of the actor is changed.
+ * @brief Callback when the inherited visibility of the actor is changed.
*/
- void OnControlVisibilityChanged(Actor actor, bool visible, DevelActor::VisibilityChange::Type type);
+ void OnControlInheritedVisibilityChanged(Actor actor, bool visible);
/**
* @brief Callback when the visibility of the window is changed.
private:
Timer mFrameDelayTimer;
+ WeakHandle<Window> mPlacementWindow;
WeakHandle<Actor> mPlacementActor;
ImageVisualShaderFactory& mImageVisualShaderFactory;
/*
- * Copyright (c) 2023 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2024 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.
#include <dali-toolkit/internal/visuals/image-atlas-manager.h> // For ImageAtlasManagerPtr
// EXTERNAL HEADERS
+#include <dali/integration-api/adaptor-framework/adaptor.h>
#include <dali/integration-api/debug.h>
namespace Dali
TextureSet FixedImageCache::GetTextureSet(uint32_t frameIndex) const
{
TextureSet textureSet = mTextureManager.GetTextureSet(mImageUrls[frameIndex].mTextureId);
- if(textureSet)
- {
- Sampler sampler = Sampler::New();
- sampler.SetWrapMode(Dali::WrapMode::Type::DEFAULT, Dali::WrapMode::Type::DEFAULT);
- textureSet.SetSampler(0u, sampler);
- }
return textureSet;
}
void FixedImageCache::ClearCache()
{
- if(mTextureManagerAlive)
+ if(Dali::Adaptor::IsAvailable())
{
for(std::size_t i = 0; i < mImageUrls.size(); ++i)
{
{
if(loadSuccess)
{
- mLoadState = TextureManager::LoadState::LOAD_FINISHED;
+ mLoadState = TextureManager::LoadState::LOAD_FINISHED;
bool isCurrentFrameReady = IsFrameReady(mCurrentFrameIndex);
if(!mRequestingLoad)
{
/*
- * Copyright (c) 2023 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2024 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.
mInterval(interval),
mLoadState(TextureManager::LoadState::NOT_STARTED),
mRequestingLoad(false),
- mPreMultiplyOnLoad(preMultiplyOnLoad),
- mTextureManagerAlive(true)
+ mPreMultiplyOnLoad(preMultiplyOnLoad)
{
- mTextureManager.AddObserver(*this);
}
ImageCache::~ImageCache()
{
- if(mTextureManagerAlive)
- {
- mTextureManager.RemoveObserver(*this);
- }
-}
-
-void ImageCache::TextureManagerDestroyed()
-{
- mTextureManagerAlive = false;
}
void ImageCache::SetInterval(uint32_t interval)
#define DALI_TOOLKIT_INTERNAL_IMAGE_CACHE_H
/*
- * Copyright (c) 2023 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2024 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.
{
namespace Internal
{
-class ImageCache : public TextureManager::LifecycleObserver
+class ImageCache
{
public:
/**
virtual void SetInterval(uint32_t interval);
private:
- /**
- * @brief Called before the texture manager is destroyed.
- */
- void TextureManagerDestroyed() final;
-
void AllocateMaskData();
protected:
TextureManager::LoadState mLoadState;
bool mRequestingLoad : 1;
bool mPreMultiplyOnLoad : 1;
- bool mTextureManagerAlive : 1;
};
} // namespace Internal
/*
- * Copyright (c) 2023 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2024 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.
// INTERNAL HEADERS
#include <dali-toolkit/devel-api/image-loader/texture-manager.h>
#include <dali-toolkit/internal/visuals/image-atlas-manager.h> // For ImageAtlasManagerPtr
+#include <dali/integration-api/adaptor-framework/adaptor.h>
#include <dali/integration-api/debug.h>
namespace
synchronouslyLoaded = true;
interval = mAnimatedImageLoading.GetFrameInterval(mQueue.Back().mFrameNumber);
}
- MakeFrameReady(synchronouslyLoaded, textureSet, interval, preMultiplyOnLoading == TextureManager::MultiplyOnLoad::MULTIPLY_ON_LOAD);
+ MakeFrameReady(synchronouslyLoaded, textureSet, mAnimatedImageLoading.GetImageCount(), interval, preMultiplyOnLoading == TextureManager::MultiplyOnLoad::MULTIPLY_ON_LOAD);
}
if(popExist || mQueue.IsEmpty() || synchronouslyLoaded)
synchronousLoading,
this,
preMultiplyOnLoading);
- if(textureSet)
+ if(textureSet && (mWrapModeU != Dali::WrapMode::DEFAULT || mWrapModeV != Dali::WrapMode::DEFAULT))
{
Sampler sampler = Sampler::New();
sampler.SetWrapMode(mWrapModeU, mWrapModeV);
TextureManager::TextureId textureId = GetCachedTextureId(0);
TextureSet textureSet = mTextureManager.GetTextureSet(textureId);
- if(textureSet)
+ if(textureSet && (mWrapModeU != Dali::WrapMode::DEFAULT || mWrapModeV != Dali::WrapMode::DEFAULT))
{
Sampler sampler = Sampler::New();
sampler.SetWrapMode(mWrapModeU, mWrapModeV);
void RollingAnimatedImageCache::ClearCache()
{
- while(mTextureManagerAlive && !mQueue.IsEmpty())
+ while(Dali::Adaptor::IsAvailable() && !mQueue.IsEmpty())
{
PopFrontCache();
}
mLoadState = TextureManager::LoadState::NOT_STARTED;
}
-void RollingAnimatedImageCache::MakeFrameReady(bool loadSuccess, TextureSet textureSet, uint32_t interval, bool preMultiplied)
+void RollingAnimatedImageCache::MakeFrameReady(bool loadSuccess, TextureSet textureSet, uint32_t frameCount, uint32_t interval, bool preMultiplied)
{
if(!loadSuccess)
{
mLoadState = TextureManager::LoadState::LOAD_FINISHED;
// Reset size of Queue according to the real frame count.
- if(mFrameCount != mAnimatedImageLoading.GetImageCount())
+ if(mFrameCount != frameCount)
{
- mFrameCount = mAnimatedImageLoading.GetImageCount();
+ mFrameCount = frameCount;
mTextureIds.resize(mFrameCount);
mIntervals.assign(mFrameCount, 0u);
}
DALI_LOG_INFO(gAnimImgLogFilter, Debug::Concise, "AnimatedImageVisual::LoadComplete(textureId:%d) start\n", textureInformation.textureId);
LOG_CACHE;
- if(textureInformation.textureSet)
+ if(textureInformation.textureSet && (mWrapModeU != Dali::WrapMode::DEFAULT || mWrapModeV != Dali::WrapMode::DEFAULT))
{
Sampler sampler = Sampler::New();
sampler.SetWrapMode(mWrapModeU, mWrapModeV);
textureInformation.textureSet.SetSampler(0u, sampler);
}
- MakeFrameReady(loadSuccess, textureInformation.textureSet, textureInformation.interval, textureInformation.preMultiplied);
+ MakeFrameReady(loadSuccess, textureInformation.textureSet, textureInformation.frameCount, textureInformation.interval, textureInformation.preMultiplied);
// TODO : We need to remove some below logics, since user can remove Visual during ResourceReady callback.
#define DALI_TOOLKIT_INTERNAL_ROLLING_ANIMATED_IMAGE_CACHE_H
/*
- * Copyright (c) 2023 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2024 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.
*
* @param[in] loadSuccess whether the loading is succeded or not.
* @param[in] textureSet textureSet for this frame.
+ * @param[in] frameCount Total frame count for this image.
* @param[in] interval interval between this frame and next frame.
* @param[in] preMultiplied whether the texture is premultied alpha or not.
*/
- void MakeFrameReady(bool loadSuccess, TextureSet textureSet, uint32_t interval, bool preMultiplied);
+ void MakeFrameReady(bool loadSuccess, TextureSet textureSet, uint32_t frameCount, uint32_t interval, bool preMultiplied);
/**
* @brief Pop front entity of Cache.
/*
- * Copyright (c) 2023 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2024 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.
// INTERNAL HEADERS
#include <dali-toolkit/internal/visuals/image-atlas-manager.h> // For ImageAtlasManagerPtr
-#include <dali/integration-api/debug.h>
// EXTERNAL HEADERS
+#include <dali/integration-api/adaptor-framework/adaptor.h>
+#include <dali/integration-api/debug.h>
namespace
{
void RollingImageCache::ClearCache()
{
- while(mTextureManagerAlive && !mQueue.IsEmpty())
+ while(Dali::Adaptor::IsAvailable() && !mQueue.IsEmpty())
{
PopFrontCache();
}
if(!frontFrameReady && IsFrontReady())
{
- if(textureInformation.textureSet)
- {
- Sampler sampler = Sampler::New();
- sampler.SetWrapMode(Dali::WrapMode::Type::DEFAULT, Dali::WrapMode::Type::DEFAULT);
- textureInformation.textureSet.SetSampler(0u, sampler);
- }
mObserver.FrameReady(textureInformation.textureSet, mInterval, textureInformation.preMultiplied);
}
}
#include <dali/devel-api/adaptor-framework/window-devel.h>
#include <dali/devel-api/common/stage.h>
#include <dali/devel-api/rendering/renderer-devel.h>
+#include <dali/integration-api/adaptor-framework/adaptor.h>
#include <dali/integration-api/debug.h>
#include <dali/public-api/math/math-utils.h>
#include <dali/public-api/rendering/decorated-visual-renderer.h>
mLastSentPlayStateId(0u),
mLoadFailed(false),
mRendererAdded(false),
- mCoreShutdown(false),
mRedrawInScalingDown(true),
mEnableFrameCache(false),
- mUseNativeImage(false)
+ mUseNativeImage(false),
+ mNotifyAfterRasterization(false)
{
// the rasterized image is with pre-multiplied alpha format
mImpl->mFlags |= Visual::Base::Impl::IS_PREMULTIPLIED_ALPHA;
AnimatedVectorImageVisual::~AnimatedVectorImageVisual()
{
- if(!mCoreShutdown)
+ if(Dali::Adaptor::IsAvailable())
{
if(mImageUrl.IsBufferResource())
{
textureManager.RemoveEncodedImageBuffer(mImageUrl.GetUrl());
}
- auto& vectorAnimationManager = mFactoryCache.GetVectorAnimationManager();
- vectorAnimationManager.RemoveObserver(*this);
-
if(mEventCallback)
{
mFactoryCache.GetVectorAnimationManager().UnregisterEventCallback(mEventCallback);
}
}
-void AnimatedVectorImageVisual::VectorAnimationManagerDestroyed()
-{
- // Core is shutting down. Don't talk to the plugin any more.
- mCoreShutdown = true;
-}
-
void AnimatedVectorImageVisual::GetNaturalSize(Vector2& naturalSize)
{
if(mDesiredSize.GetWidth() > 0 && mDesiredSize.GetHeight() > 0)
map.Insert(Toolkit::ImageVisual::Property::DESIRED_WIDTH, mDesiredSize.GetWidth());
map.Insert(Toolkit::ImageVisual::Property::DESIRED_HEIGHT, mDesiredSize.GetHeight());
map.Insert(Toolkit::DevelImageVisual::Property::ENABLE_FRAME_CACHE, mEnableFrameCache);
+ map.Insert(Toolkit::DevelImageVisual::Property::NOTIFY_AFTER_RASTERIZATION, mNotifyAfterRasterization);
}
void AnimatedVectorImageVisual::DoCreateInstancePropertyMap(Property::Map& map) const
{
DoSetProperty(Toolkit::DevelImageVisual::Property::ENABLE_FRAME_CACHE, keyValue.second);
}
+ else if(keyValue.first == NOTIFY_AFTER_RASTERIZATION)
+ {
+ DoSetProperty(Toolkit::DevelImageVisual::Property::NOTIFY_AFTER_RASTERIZATION, keyValue.second);
+ }
}
}
}
break;
}
+
+ case Toolkit::DevelImageVisual::Property::NOTIFY_AFTER_RASTERIZATION:
+ {
+ bool notifyAfterRasterization = false;
+ if(value.Get(notifyAfterRasterization))
+ {
+ if(mNotifyAfterRasterization != notifyAfterRasterization)
+ {
+ mNotifyAfterRasterization = notifyAfterRasterization;
+
+ mAnimationData.notifyAfterRasterization = mNotifyAfterRasterization;
+ mAnimationData.resendFlag |= VectorAnimationTask::RESEND_NOTIFY_AFTER_RASTERIZATION;
+ }
+ }
+ break;
+ }
}
}
mVectorAnimationTask->KeepRasterizedBuffer(mEnableFrameCache);
mVectorAnimationTask->RequestLoad(mImageUrl, encodedImageBuffer, IsSynchronousLoadingRequired());
- auto& vectorAnimationManager = mFactoryCache.GetVectorAnimationManager();
- vectorAnimationManager.AddObserver(*this);
-
Shader shader = GenerateShader();
Geometry geometry = mFactoryCache.GetGeometry(VisualFactoryCache::QUAD_GEOMETRY);
mSizeNotification = actor.AddPropertyNotification(Actor::Property::SIZE, StepCondition(3.0f));
mSizeNotification.NotifySignal().Connect(this, &AnimatedVectorImageVisual::OnSizeNotification);
- DevelActor::VisibilityChangedSignal(actor).Connect(this, &AnimatedVectorImageVisual::OnControlVisibilityChanged);
+ actor.InheritedVisibilityChangedSignal().Connect(this, &AnimatedVectorImageVisual::OnControlInheritedVisibilityChanged);
Window window = DevelWindow::Get(actor);
if(window)
{
+ mPlacementWindow = window;
DevelWindow::VisibilityChangedSignal(window).Connect(this, &AnimatedVectorImageVisual::OnWindowVisibilityChanged);
}
actor.RemovePropertyNotification(mScaleNotification);
actor.RemovePropertyNotification(mSizeNotification);
- DevelActor::VisibilityChangedSignal(actor).Disconnect(this, &AnimatedVectorImageVisual::OnControlVisibilityChanged);
+ actor.InheritedVisibilityChangedSignal().Disconnect(this, &AnimatedVectorImageVisual::OnControlInheritedVisibilityChanged);
- Window window = DevelWindow::Get(actor);
+ Window window = mPlacementWindow.GetHandle();
if(window)
{
DevelWindow::VisibilityChangedSignal(window).Disconnect(this, &AnimatedVectorImageVisual::OnWindowVisibilityChanged);
+ mPlacementWindow.Reset();
}
mPlacementActor.Reset();
}
case DevelAnimatedVectorImageVisual::Action::FLUSH:
{
- if(DALI_LIKELY(!mCoreShutdown))
+ if(DALI_LIKELY(Dali::Adaptor::IsAvailable()))
{
SendAnimationData();
}
}
}
- if(mImpl->mRenderer)
+ if(!mNotifyAfterRasterization && mImpl->mRenderer)
{
mImpl->mRenderer.SetProperty(DevelRenderer::Property::RENDERING_BEHAVIOR, DevelRenderer::Rendering::IF_REQUIRED);
}
}
mVectorAnimationTask->SetAnimationData(mAnimationData);
- if(mImpl->mRenderer)
+ if(mImpl->mRenderer &&
+ ((mAnimationData.resendFlag & VectorAnimationTask::RESEND_PLAY_STATE) ||
+ (mAnimationData.resendFlag & VectorAnimationTask::RESEND_NOTIFY_AFTER_RASTERIZATION)))
{
- if(mAnimationData.playState == DevelImageVisual::PlayState::PLAYING)
+ if(!mNotifyAfterRasterization && mPlayState == DevelImageVisual::PlayState::PLAYING)
{
+ // Make rendering behaviour if we don't notify after rasterization, but animation playing.
mImpl->mRenderer.SetProperty(DevelRenderer::Property::RENDERING_BEHAVIOR, DevelRenderer::Rendering::CONTINUOUSLY);
}
else
{
+ // Otherwise, notify will be sended after rasterization. Make behaviour as required.
mImpl->mRenderer.SetProperty(DevelRenderer::Property::RENDERING_BEHAVIOR, DevelRenderer::Rendering::IF_REQUIRED);
}
}
void AnimatedVectorImageVisual::TriggerVectorRasterization()
{
- if(!mEventCallback && !mCoreShutdown)
+ if(!mEventCallback && Dali::Adaptor::IsAvailable())
{
mEventCallback = MakeCallback(this, &AnimatedVectorImageVisual::OnProcessEvents);
auto& vectorAnimationManager = mFactoryCache.GetVectorAnimationManager();
}
}
-void AnimatedVectorImageVisual::OnControlVisibilityChanged(Actor actor, bool visible, DevelActor::VisibilityChange::Type type)
+void AnimatedVectorImageVisual::OnControlInheritedVisibilityChanged(Actor actor, bool visible)
{
if(!visible)
{
StopAnimation();
TriggerVectorRasterization();
- DALI_LOG_INFO(gVectorAnimationLogFilter, Debug::Verbose, "AnimatedVectorImageVisual::OnControlVisibilityChanged: invisibile. Pause animation [%p]\n", this);
+ DALI_LOG_INFO(gVectorAnimationLogFilter, Debug::Verbose, "AnimatedVectorImageVisual::OnControlInheritedVisibilityChanged: invisibile. Pause animation [%p]\n", this);
}
}
* | url | STRING |
*
*/
-class AnimatedVectorImageVisual : public Visual::Base, public ConnectionTracker, public VectorAnimationManager::LifecycleObserver
+class AnimatedVectorImageVisual : public Visual::Base, public ConnectionTracker
{
public:
/**
*/
void EnablePreMultipliedAlpha(bool preMultiplied) override;
-protected: // From VectorAnimationManager::LifecycleObserver:
- /**
- * @copydoc VectorAnimationManager::LifecycleObserver::VectorAnimationManagerDestroyed()
- */
- void VectorAnimationManagerDestroyed() override;
-
protected:
/**
* @brief Constructor.
/**
* @brief Callback when the visibility of the actor is changed.
*/
- void OnControlVisibilityChanged(Actor actor, bool visible, DevelActor::VisibilityChange::Type type);
+ void OnControlInheritedVisibilityChanged(Actor actor, bool visible);
/**
* @brief Callback when the visibility of the window is changed.
AnimatedVectorImageVisual& operator=(const AnimatedVectorImageVisual& visual) = delete;
private:
+ WeakHandle<Window> mPlacementWindow;
VisualUrl mImageUrl;
VectorAnimationTask::AnimationData mAnimationData;
VectorAnimationTaskPtr mVectorAnimationTask;
bool mLoadFailed : 1;
bool mRendererAdded : 1;
- bool mCoreShutdown : 1;
bool mRedrawInScalingDown : 1;
bool mEnableFrameCache : 1;
bool mUseNativeImage : 1;
+ bool mNotifyAfterRasterization : 1;
};
} // namespace Internal
/*
- * Copyright (c) 2023 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2024 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.
VectorAnimationManager::VectorAnimationManager()
: mEventCallbacks(),
- mLifecycleObservers(),
mVectorAnimationThread(nullptr),
mProcessorRegistered(false)
{
VectorAnimationManager::~VectorAnimationManager()
{
- mEventCallbacks.clear();
+ mEventCallbacks.Clear();
if(mProcessorRegistered && Adaptor::IsAvailable())
{
Adaptor::Get().UnregisterProcessor(*this, true);
}
-
- 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()
void VectorAnimationManager::RegisterEventCallback(CallbackBase* callback)
{
- mEventCallbacks.emplace_back(std::unique_ptr<Dali::CallbackBase>(callback));
+ mEventCallbacks.PushBack(callback); ///< Take ownership of callback.
if(!mProcessorRegistered)
{
void VectorAnimationManager::UnregisterEventCallback(CallbackBase* callback)
{
- auto iter = std::find_if(mEventCallbacks.begin(),
- mEventCallbacks.end(),
- [callback](const std::unique_ptr<CallbackBase>& element) {
- return element.get() == callback;
- });
- if(iter != mEventCallbacks.end())
+ auto iter = mEventCallbacks.Find(callback);
+ if(iter != mEventCallbacks.End())
{
- mEventCallbacks.erase(iter);
+ mEventCallbacks.Erase(iter);
- if(mEventCallbacks.empty())
+ if(mEventCallbacks.Count() == 0u)
{
if(Adaptor::IsAvailable())
{
#ifdef TRACE_ENABLED
if(gTraceFilter && gTraceFilter->IsTraceEnabled())
{
- if(mEventCallbacks.size() > 0u)
+ if(mEventCallbacks.Count() > 0u)
{
std::ostringstream oss;
- oss << "[" << mEventCallbacks.size() << "]";
+ oss << "[" << mEventCallbacks.Count() << "]";
DALI_TRACE_BEGIN_WITH_MESSAGE(gTraceFilter, "DALI_VECTOR_ANIMATION_MANAGER_PROCESS", oss.str().c_str());
}
}
#ifdef TRACE_ENABLED
if(gTraceFilter && gTraceFilter->IsTraceEnabled())
{
- if(mEventCallbacks.size() > 0u)
+ if(mEventCallbacks.Count() > 0u)
{
std::ostringstream oss;
- oss << "[" << mEventCallbacks.size() << "]";
+ oss << "[" << mEventCallbacks.Count() << "]";
DALI_TRACE_END_WITH_MESSAGE(gTraceFilter, "DALI_VECTOR_ANIMATION_MANAGER_PROCESS", oss.str().c_str());
}
}
#endif
- mEventCallbacks.clear();
+ mEventCallbacks.Clear();
Adaptor::Get().UnregisterProcessor(*this, true);
mProcessorRegistered = false;
#define DALI_TOOLKIT_INTERNAL_VECTOR_ANIMATION_MANAGER_H
/*
- * Copyright (c) 2023 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2024 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.
*/
// EXTERNAL INCLUDES
+#include <dali/integration-api/ordered-set.h>
#include <dali/integration-api/processor-interface.h>
#include <dali/public-api/common/vector-wrapper.h>
#include <dali/public-api/signals/callback.h>
class VectorAnimationManager : public Integration::Processor
{
public:
- struct LifecycleObserver
- {
- virtual void VectorAnimationManagerDestroyed() = 0;
- };
-
/**
* @brief Constructor.
*/
~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.
*/
VectorAnimationManager& operator=(const VectorAnimationManager& manager) = delete;
private:
- std::vector<std::unique_ptr<CallbackBase>> mEventCallbacks;
- std::vector<LifecycleObserver*> mLifecycleObservers;
- std::unique_ptr<VectorAnimationThread> mVectorAnimationThread;
- bool mProcessorRegistered;
+ Dali::Integration::OrderedSet<CallbackBase> mEventCallbacks; ///< Event triggered callback lists (owned)
+
+ std::unique_ptr<VectorAnimationThread> mVectorAnimationThread;
+ bool mProcessorRegistered : 1;
};
} // namespace Internal
mForward(true),
mUpdateFrameNumber(false),
mNeedAnimationFinishedTrigger(true),
+ mNeedForceRenderOnceTrigger(false),
mAnimationDataUpdated(false),
mDestroyTask(false),
mLoadRequest(false),
mLayerInfoCached(false),
mMarkerInfoCached(false),
mEnableFrameCache(false),
+ mNotifyAfterRasterization(false),
mSizeUpdated(false)
{
mVectorRenderer.UploadCompletedSignal().Connect(this, &VectorAnimationTask::OnUploadCompleted);
{
mPlayState = PlayState::PAUSED;
+ // Ensure to render paused frame.
+ mNeedForceRenderOnceTrigger = true;
+
DALI_LOG_INFO(gVectorAnimationLogFilter, Debug::Verbose, "VectorAnimationTask::PauseAnimation: Pause [%p]\n", this);
}
}
if(mStartFrame > mCurrentFrame)
{
mCurrentFrame = mStartFrame;
+
+ if(mPlayState != PlayState::PLAYING)
+ {
+ // Ensure to render current frame.
+ mNeedForceRenderOnceTrigger = true;
+ }
}
else if(mEndFrame < mCurrentFrame)
{
mCurrentFrame = mEndFrame;
+
+ if(mPlayState != PlayState::PLAYING)
+ {
+ // Ensure to render current frame.
+ mNeedForceRenderOnceTrigger = true;
+ }
}
DALI_LOG_INFO(gVectorAnimationLogFilter, Debug::Verbose, "VectorAnimationTask::SetPlayRange: [%d, %d] [%s] [%p]\n", mStartFrame, mEndFrame, mImageUrl.GetUrl().c_str(), this);
mCurrentFrame = frameNumber;
mUpdateFrameNumber = false;
+ if(mPlayState != PlayState::PLAYING)
+ {
+ // Ensure to render current frame.
+ mNeedForceRenderOnceTrigger = true;
+ }
+
DALI_LOG_INFO(gVectorAnimationLogFilter, Debug::Verbose, "VectorAnimationTask::SetCurrentFrameNumber: frame number = %d [%p]\n", mCurrentFrame, this);
}
else
mForward = true;
mCurrentLoop = 0;
+ mNeedForceRenderOnceTrigger = true;
+
if(mVectorRenderer)
{
// Notify the Renderer that rendering is stopped.
DALI_LOG_INFO(gVectorAnimationLogFilter, Debug::Verbose, "VectorAnimationTask::Rasterize: Animation is finished [current = %d] [%p]\n", currentFrame, this);
}
+ // Forcely trigger render once if need.
+ if(mNotifyAfterRasterization || mNeedForceRenderOnceTrigger)
+ {
+ Mutex::ScopedLock lock(mMutex);
+ mVectorAnimationThread.RequestForceRenderOnce();
+ mNeedForceRenderOnceTrigger = false;
+ }
+
if(mPlayState != PlayState::PAUSED && mPlayState != PlayState::STOPPED)
{
mKeepAnimation = true;
SetCurrentFrameNumber(animationData.currentFrame);
}
+ if(animationData.resendFlag & VectorAnimationTask::RESEND_NOTIFY_AFTER_RASTERIZATION)
+ {
+ mNotifyAfterRasterization = animationData.notifyAfterRasterization;
+ }
+
if(animationData.resendFlag & VectorAnimationTask::RESEND_NEED_RESOURCE_READY)
{
mVectorRenderer.InvalidateBuffer();
*/
enum ResendFlags
{
- RESEND_PLAY_RANGE = 1 << 0,
- RESEND_LOOP_COUNT = 1 << 1,
- RESEND_STOP_BEHAVIOR = 1 << 2,
- RESEND_LOOPING_MODE = 1 << 3,
- RESEND_CURRENT_FRAME = 1 << 4,
- RESEND_SIZE = 1 << 5,
- RESEND_PLAY_STATE = 1 << 6,
- RESEND_NEED_RESOURCE_READY = 1 << 7,
- RESEND_DYNAMIC_PROPERTY = 1 << 8
+ RESEND_PLAY_RANGE = 1 << 0,
+ RESEND_LOOP_COUNT = 1 << 1,
+ RESEND_STOP_BEHAVIOR = 1 << 2,
+ RESEND_LOOPING_MODE = 1 << 3,
+ RESEND_CURRENT_FRAME = 1 << 4,
+ RESEND_SIZE = 1 << 5,
+ RESEND_PLAY_STATE = 1 << 6,
+ RESEND_NEED_RESOURCE_READY = 1 << 7,
+ RESEND_DYNAMIC_PROPERTY = 1 << 8,
+ RESEND_NOTIFY_AFTER_RASTERIZATION = 1 << 9,
};
/**
width(0),
height(0),
loopCount(-1),
- playStateId(0)
+ playStateId(0),
+ notifyAfterRasterization(false)
{
}
AnimationData& operator=(const AnimationData& rhs)
{
resendFlag |= rhs.resendFlag; // OR resend flag
- playRange = rhs.playRange;
- playState = rhs.playState;
- stopBehavior = rhs.stopBehavior;
- loopingMode = rhs.loopingMode;
- currentFrame = rhs.currentFrame;
- width = rhs.width;
- height = rhs.height;
- loopCount = rhs.loopCount;
- playStateId = rhs.playStateId;
+ playRange = rhs.playRange;
+ playState = rhs.playState;
+ stopBehavior = rhs.stopBehavior;
+ loopingMode = rhs.loopingMode;
+ currentFrame = rhs.currentFrame;
+ width = rhs.width;
+ height = rhs.height;
+ loopCount = rhs.loopCount;
+ playStateId = rhs.playStateId;
+ notifyAfterRasterization = rhs.notifyAfterRasterization;
dynamicProperties.insert(dynamicProperties.end(), rhs.dynamicProperties.begin(), rhs.dynamicProperties.end());
return *this;
}
uint32_t height;
int32_t loopCount;
uint32_t playStateId;
+ bool notifyAfterRasterization;
};
/**
*/
bool IsAnimating();
+ void KeepRasterizedBuffer(bool enableFrameCache)
+ {
+ mEnableFrameCache = enableFrameCache;
+ }
+
+ bool IsKeptRasterizedBuffer() const
+ {
+ return mEnableFrameCache;
+ }
+
public: // Implementation of AsyncTask
/**
* @copydoc Dali::AsyncTask::Process()
return "VectorAnimationTask";
}
- void KeepRasterizedBuffer(bool enableFrameCache)
- {
- mEnableFrameCache = enableFrameCache;
- }
-
- bool IsKeptRasterizedBuffer()
- {
- return mEnableFrameCache;
- }
-
private:
/**
* @brief Loads the animation file.
bool mForward : 1;
bool mUpdateFrameNumber : 1;
bool mNeedAnimationFinishedTrigger : 1;
+ bool mNeedForceRenderOnceTrigger : 1;
bool mAnimationDataUpdated : 1;
bool mDestroyTask : 1;
bool mLoadRequest : 1;
mutable bool mLayerInfoCached : 1;
mutable bool mMarkerInfoCached : 1;
bool mEnableFrameCache : 1;
+ bool mNotifyAfterRasterization : 1;
bool mSizeUpdated : 1;
};
mSleepThread(MakeCallback(this, &VectorAnimationThread::OnAwakeFromSleep)),
mConditionalWait(),
mEventTriggerMutex(),
+ mLogFactory(Dali::Adaptor::Get().GetLogFactory()),
+ mTraceFactory(Dali::Adaptor::Get().GetTraceFactory()),
mNeedToSleep(false),
mDestroyThread(false),
- mLogFactory(Dali::Adaptor::Get().GetLogFactory()),
- mTraceFactory(Dali::Adaptor::Get().GetTraceFactory())
+ mEventTriggered(false),
+ mForceRenderOnce(false)
{
mAsyncTaskManager = Dali::AsyncTaskManager::Get();
mSleepThread.Start();
}
}
+void VectorAnimationThread::RequestForceRenderOnce()
+{
+ Mutex::ScopedLock lock(mEventTriggerMutex);
+ if(!mDestroyThread)
+ {
+ mForceRenderOnce = true;
+
+ if(!mEventTriggered)
+ {
+ mEventTrigger->Trigger();
+ mEventTriggered = true;
+ }
+ }
+}
+
void VectorAnimationThread::Run()
{
SetThreadName("VectorAnimationThread");
}
CallbackBase::Execute(*callbackPair.first, callbackPair.second);
}
+ // Request update once if we need.
+ {
+ Mutex::ScopedLock lock(mEventTriggerMutex);
+ if(!mDestroyThread && mForceRenderOnce)
+ {
+ mForceRenderOnce = false;
+ if(Dali::Adaptor::IsAvailable())
+ {
+ Dali::Adaptor::Get().UpdateOnce();
+ }
+ }
+ }
}
std::pair<CallbackBase*, uint32_t> VectorAnimationThread::GetNextEventCallback()
*/
void RemoveEventTriggerCallbacks(CallbackBase* callback);
+ /**
+ * @brief Request to event callback from rasterize thread. This is called when we want to ensure rendering next frame.
+ */
+ void RequestForceRenderOnce();
+
protected:
/**
* @brief The entry function of the animation thread.
std::chrono::time_point<std::chrono::steady_clock> mSleepTimePoint;
const Dali::LogFactoryInterface& mLogFactory;
const Dali::TraceFactoryInterface& mTraceFactory;
- bool mNeedToSleep;
- bool mDestroyThread;
+
+ bool mNeedToSleep : 1;
+ bool mDestroyThread : 1;
};
private:
ConditionalWait mConditionalWait;
Mutex mEventTriggerMutex;
std::unique_ptr<EventThreadCallback> mEventTrigger{};
- bool mNeedToSleep;
- bool mDestroyThread;
- bool mEventTriggered{false};
const Dali::LogFactoryInterface& mLogFactory;
const Dali::TraceFactoryInterface& mTraceFactory;
Dali::AsyncTaskManager mAsyncTaskManager;
+
+ bool mNeedToSleep : 1;
+ bool mDestroyThread : 1;
+ bool mEventTriggered : 1;
+ bool mForceRenderOnce : 1;
};
} // namespace Internal
TextureSet textureSet = TextureSet::New();
Dali::Texture lookupTexture = mGradient->GenerateLookupTexture();
textureSet.SetTexture(0u, lookupTexture);
- Dali::WrapMode::Type wrap = GetWrapMode(mGradient->GetSpreadMethod());
- Sampler sampler = Sampler::New();
- sampler.SetWrapMode(wrap, wrap);
- textureSet.SetSampler(0u, sampler);
+ Dali::WrapMode::Type wrap = GetWrapMode(mGradient->GetSpreadMethod());
+ if(wrap != Dali::WrapMode::DEFAULT)
+ {
+ Sampler sampler = Sampler::New();
+ sampler.SetWrapMode(wrap, wrap);
+ textureSet.SetSampler(0u, sampler);
+ }
mImpl->mRenderer = DecoratedVisualRenderer::New(geometry, shader);
mImpl->mRenderer.ReserveCustomProperties(CUSTOM_PROPERTY_COUNT);
}
EnablePreMultipliedAlpha(preMultiplyOnLoad == TextureManager::MultiplyOnLoad::MULTIPLY_ON_LOAD);
- if(!atlasing)
+ if(!atlasing && (mWrapModeU != Dali::WrapMode::DEFAULT || mWrapModeV != Dali::WrapMode::DEFAULT))
{
Sampler sampler = Sampler::New();
sampler.SetWrapMode(mWrapModeU, mWrapModeV);
else
{
mTextures = mFactoryCache.GetTextureManager().GetTextureSet(mTextureId);
- if(!(mImpl->mFlags & Visual::Base::Impl::IS_ATLASING_APPLIED) && mTextures)
+ if(!(mImpl->mFlags & Visual::Base::Impl::IS_ATLASING_APPLIED) &&
+ mTextures &&
+ (mWrapModeU != Dali::WrapMode::DEFAULT || mWrapModeV != Dali::WrapMode::DEFAULT))
{
Sampler sampler = Sampler::New();
sampler.SetWrapMode(mWrapModeU, mWrapModeV);
}
else
{
- Sampler sampler = Sampler::New();
- sampler.SetWrapMode(mWrapModeU, mWrapModeV);
- textureInformation.textureSet.SetSampler(0u, sampler);
+ if(mWrapModeU != Dali::WrapMode::DEFAULT || mWrapModeV != Dali::WrapMode::DEFAULT)
+ {
+ Sampler sampler = Sampler::New();
+ sampler.SetWrapMode(mWrapModeU, mWrapModeV);
+ textureInformation.textureSet.SetSampler(0u, sampler);
+ }
mImpl->mRenderer.SetTextures(textureInformation.textureSet);
ComputeTextureSize();
// Load the auxiliary image
mAuxiliaryTextureSet = textureManager.LoadTexture(mAuxiliaryUrl, Dali::ImageDimensions(), FittingMode::DEFAULT, SamplingMode::BOX_THEN_LINEAR, maskingDataPtr, synchronousLoading, mAuxiliaryTextureId, atlasRect, atlasRectSize, atlasing, loadingStatus, this, nullptr, imageAtlasManagerPtr, true, TextureManager::ReloadPolicy::CACHED, preMultiplyOnLoad);
- if(mAuxiliaryTextureSet)
- {
- Sampler sampler = Sampler::New();
- sampler.SetWrapMode(WrapMode::DEFAULT, WrapMode::DEFAULT);
- mAuxiliaryTextureSet.SetSampler(0u, sampler);
- }
-
// If synchronousLoading is true, we can check the auxiliaryResource's status now.
if(synchronousLoading)
{
}
if(loadSuccess)
{
- mAuxiliaryTextureSet = textureInformation.textureSet;
- if(mAuxiliaryTextureSet)
- {
- Sampler sampler = Sampler::New();
- sampler.SetWrapMode(WrapMode::DEFAULT, WrapMode::DEFAULT);
- mAuxiliaryTextureSet.SetSampler(0u, sampler);
- }
-
+ mAuxiliaryTextureSet = textureInformation.textureSet;
mAuxiliaryResourceStatus = Toolkit::Visual::ResourceStatus::READY;
}
else
/*
- * Copyright (c) 2023 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2024 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.
UpdateRenderer();
}
-void TextVisual::RemoveRenderer(Actor& actor)
+void TextVisual::RemoveRenderer(Actor& actor, bool removeDefaultRenderer)
{
for(RendererContainer::iterator iter = mRendererList.begin(); iter != mRendererList.end(); ++iter)
{
Renderer renderer = (*iter);
- if(renderer)
+ if(renderer &&
+ (removeDefaultRenderer || (renderer != mImpl->mRenderer)))
{
// Removes the renderer from the actor.
actor.RemoveRenderer(renderer);
mOpacityConstraint.Remove();
}
- RemoveRenderer(actor);
+ RemoveRenderer(actor, true);
// Resets the control handle.
mControl.Reset();
if((fabsf(relayoutSize.width) < Math::MACHINE_EPSILON_1000) || (fabsf(relayoutSize.height) < Math::MACHINE_EPSILON_1000) || textLengthUtf32 == 0u)
{
// Remove the texture set and any renderer previously set.
- RemoveRenderer(control);
+ RemoveRenderer(control, true);
// Nothing else to do if the relayout size is zero.
ResourceReady(Toolkit::Visual::ResourceStatus::READY);
mRendererUpdateNeeded = false;
// Remove the texture set and any renderer previously set.
- RemoveRenderer(control);
+ // Note, we don't need to remove the mImpl->Renderer, since it will be added again after AddRenderer call.
+ RemoveRenderer(control, false);
if((relayoutSize.width > Math::MACHINE_EPSILON_1000) &&
(relayoutSize.height > Math::MACHINE_EPSILON_1000))
Renderer renderer = (*iter);
if(renderer)
{
+ // Note, AddRenderer will ignore renderer if it is already added. @SINCE 2_3.22
actor.AddRenderer(renderer);
if(renderer != mImpl->mRenderer)
#define DALI_TOOLKIT_INTERNAL_TEXT_VISUAL_H
/*
- * Copyright (c) 2023 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2024 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.
/**
* @brief Removes the text's renderer.
*/
- void RemoveRenderer(Actor& actor);
+ void RemoveRenderer(Actor& actor, bool removeDefaultRenderer);
/**
* @brief Create a texture in textureSet and add it.
/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2024 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.
#include <dali/integration-api/debug.h>
// INTERNAL INCLUDES
+#include <dali-toolkit/devel-api/controls/control-depth-index-ranges.h>
#include <dali-toolkit/devel-api/visuals/visual-properties-devel.h>
#include <dali-toolkit/internal/helpers/property-helper.h>
#include <dali-toolkit/internal/visuals/visual-string-constants.h>
mMixColor(Color::WHITE),
mControlSize(Vector2::ZERO),
mDecorationData(nullptr),
- mDepthIndex(0.0f),
+ mDepthIndex(Toolkit::DepthIndex::AUTO_INDEX),
mFittingMode(fittingMode),
mFlags(0),
mResourceStatus(Toolkit::Visual::ResourceStatus::PREPARING),
#include <dali/public-api/rendering/visual-renderer.h>
//INTERNAL HEARDER
+#include <dali-toolkit/devel-api/controls/control-depth-index-ranges.h>
#include <dali-toolkit/devel-api/visuals/color-visual-properties-devel.h>
#include <dali-toolkit/devel-api/visuals/visual-actions-devel.h>
#include <dali-toolkit/devel-api/visuals/visual-properties-devel.h>
void Visual::Base::SetDepthIndex(int index)
{
- mImpl->mDepthIndex = index;
- if(mImpl->mRenderer)
+ // Clamp input value as valid range.
+ Dali::ClampInPlace(index, static_cast<int>(Toolkit::DepthIndex::MINIMUM_DEPTH_INDEX), static_cast<int>(Toolkit::DepthIndex::MAXIMUM_DEPTH_INDEX));
+
+ if(mImpl->mDepthIndex != index)
{
- mImpl->mRenderer.SetProperty(Renderer::Property::DEPTH_INDEX, mImpl->mDepthIndex);
+ mImpl->mDepthIndex = index;
+ if(mImpl->mRenderer)
+ {
+ mImpl->mRenderer.SetProperty(Renderer::Property::DEPTH_INDEX, mImpl->mDepthIndex);
+ }
}
}
if(mImpl->mRenderer)
{
mImpl->mRenderer.SetProperty(Renderer::Property::BLEND_PRE_MULTIPLIED_ALPHA, IsPreMultipliedAlphaEnabled());
- mImpl->mRenderer.SetProperty(Renderer::Property::DEPTH_INDEX, mImpl->mDepthIndex);
+ if(mImpl->mDepthIndex == static_cast<int>(DepthIndex::AUTO_INDEX))
+ {
+ mImpl->mRenderer.SetProperty(Renderer::Property::DEPTH_INDEX, static_cast<int>(DepthIndex::CONTENT));
+ }
+ else
+ {
+ mImpl->mRenderer.SetProperty(Renderer::Property::DEPTH_INDEX, mImpl->mDepthIndex);
+ }
}
mImpl->mFlags |= Impl::IS_ON_SCENE;
const char* const FAST_TRACK_UPLOADING_NAME("fastTrackUploading");
const char* const ENABLE_BROKEN_IMAGE("enableBrokenImage");
const char* const ENABLE_FRAME_CACHE("enableFrameCache");
+const char* const NOTIFY_AFTER_RASTERIZATION("notifyAfterRasterization");
// Text visual
const char* const TEXT_PROPERTY("text");
extern const char* const FAST_TRACK_UPLOADING_NAME;
extern const char* const ENABLE_BROKEN_IMAGE;
extern const char* const ENABLE_FRAME_CACHE;
+extern const char* const NOTIFY_AFTER_RASTERIZATION;
// Text visual
extern const char* const TEXT_PROPERTY;
case Actor::Property::VISIBLE:
{
auto* accessible = GetAccessibleObject();
- if(DALI_LIKELY(accessible))
+ if(DALI_LIKELY(accessible) && accessible->IsHighlighted())
{
accessible->EmitVisible(Self().GetProperty<bool>(Actor::Property::VISIBLE));
}
{
const unsigned int TOOLKIT_MAJOR_VERSION = 2;
const unsigned int TOOLKIT_MINOR_VERSION = 3;
-const unsigned int TOOLKIT_MICRO_VERSION = 18;
+const unsigned int TOOLKIT_MICRO_VERSION = 23;
const char* const TOOLKIT_BUILD_DATE = __DATE__ " " __TIME__;
#ifdef DEBUG_ENABLED
Name: dali2-toolkit
Summary: Dali 3D engine Toolkit
-Version: 2.3.18
+Version: 2.3.23
Release: 1
Group: System/Libraries
License: Apache-2.0 and BSD-3-Clause and MIT