{
InstallLogFunction(TestLogFunction);
DefaultErrorCallback("Hello world!");
- DALI_TEST_EQUAL(std::string(sBuffer), "2: DefaultErrorCallback Hello world!");
+ DALI_TEST_EQUAL(std::string(sBuffer), "2: string-callback.cpp: DefaultErrorCallback(26) > Hello world!");
END_TEST;
}
namespace Dali
{
+const Rect<int> TestApplication::DEFAULT_SURFACE_RECT = Rect<int>(0, 0, TestApplication::DEFAULT_SURFACE_WIDTH, TestApplication::DEFAULT_SURFACE_HEIGHT);
+
bool TestApplication::mLoggingEnabled = true;
TestApplication::TestApplication(uint32_t surfaceWidth,
bool TestApplication::RenderWithPartialUpdate(std::vector<Rect<int>>& damagedRects, Rect<int>& clippingRect)
{
- mCore->RenderScene(mRenderStatus, mScene, true /*render the off-screen buffers*/, clippingRect);
+ mCore->RenderScene(mRenderStatus, mScene, true /*render the off-screen buffers*/);
mCore->RenderScene(mRenderStatus, mScene, false /*render the surface*/, clippingRect);
mCore->PostRender(false /*do not skip rendering*/);
static const uint32_t DEFAULT_SURFACE_WIDTH = 480;
static const uint32_t DEFAULT_SURFACE_HEIGHT = 800;
+ static const Rect<int> DEFAULT_SURFACE_RECT;
+
static constexpr uint32_t DEFAULT_HORIZONTAL_DPI = 220;
static constexpr uint32_t DEFAULT_VERTICAL_DPI = 217;
Dali::Vector<uint8_t> data;
data.Resize(size);
fseek(fp, 0, SEEK_SET);
- fread(data.Begin(), size, sizeof(uint8_t), fp);
+ size_t realSize = fread(data.Begin(), sizeof(uint8_t), size, fp);
fclose(fp);
+ data.Resize(realSize);
buffer = EncodedImageBuffer::New(data);
}
return buffer;
case Graphics::BlendOp::MAX:
op = GL_MAX;
break;
-
- // @todo Add advanced blend equations
+ case Graphics::BlendOp::MULTIPLY:
+ {
+ op = GL_MULTIPLY;
+ break;
+ }
+ case Graphics::BlendOp::SCREEN:
+ {
+ op = GL_SCREEN;
+ break;
+ }
+ case Graphics::BlendOp::OVERLAY:
+ {
+ op = GL_OVERLAY;
+ break;
+ }
+ case Graphics::BlendOp::DARKEN:
+ {
+ op = GL_DARKEN;
+ break;
+ }
+ case Graphics::BlendOp::LIGHTEN:
+ {
+ op = GL_LIGHTEN;
+ break;
+ }
+ case Graphics::BlendOp::COLOR_DODGE:
+ {
+ op = GL_COLORDODGE;
+ break;
+ }
+ case Graphics::BlendOp::COLOR_BURN:
+ {
+ op = GL_COLORBURN;
+ break;
+ }
+ case Graphics::BlendOp::HARD_LIGHT:
+ {
+ op = GL_HARDLIGHT;
+ break;
+ }
+ case Graphics::BlendOp::SOFT_LIGHT:
+ {
+ op = GL_SOFTLIGHT;
+ break;
+ }
+ case Graphics::BlendOp::DIFFERENCE:
+ {
+ op = GL_DIFFERENCE;
+ break;
+ }
+ case Graphics::BlendOp::EXCLUSION:
+ {
+ op = GL_EXCLUSION;
+ break;
+ }
+ case Graphics::BlendOp::HUE:
+ {
+ op = GL_HSL_HUE;
+ break;
+ }
+ case Graphics::BlendOp::SATURATION:
+ {
+ op = GL_HSL_SATURATION;
+ break;
+ }
+ case Graphics::BlendOp::COLOR:
+ {
+ op = GL_HSL_COLOR;
+ break;
+ }
+ case Graphics::BlendOp::LUMINOSITY:
+ {
+ op = GL_HSL_LUMINOSITY;
+ break;
+ }
}
return op;
}
public:
CanvasRenderer( const Vector2& size )
: mDrawable(nullptr),
- mPixelBuffer( Devel::PixelBuffer::New(size.width, size.height, Dali::Pixel::RGBA8888) ),
+ mTexture ( Dali::Texture::New( Dali::TextureType::TEXTURE_2D, Pixel::RGBA8888, size.width, size.height ) ),
mSize(size),
mViewBox(size)
{
return true;
}
+ Dali::Texture GetRasterizedTexture()
+ {
+ return mTexture;
+ }
+
bool Rasterize()
{
return true;
return false;
}
- Devel::PixelBuffer GetPixelBuffer()
- {
- return mPixelBuffer;
- }
-
-
bool SetSize(Vector2 size)
{
mSize = size;
public:
Dali::CanvasRenderer::Drawable* mDrawable;
- Devel::PixelBuffer mPixelBuffer;
+ Dali::Texture mTexture;
Vector2 mSize;
Vector2 mViewBox;
};
return Internal::Adaptor::GetImplementation(*this).Rasterize();
}
-Devel::PixelBuffer CanvasRenderer::GetPixelBuffer()
+Dali::Texture CanvasRenderer::GetRasterizedTexture()
{
- return Internal::Adaptor::GetImplementation(*this).GetPixelBuffer();
+ return Internal::Adaptor::GetImplementation(*this).GetRasterizedTexture();
}
bool CanvasRenderer::AddDrawable(Dali::CanvasRenderer::Drawable& drawable)
return Internal::Adaptor::GetImplementation( *this ).GetUrl();
}
-NativeImageInterfacePtr WebEngine::GetNativeImageSource()
+NativeImageSourcePtr WebEngine::GetNativeImageSource()
{
Any source;
Dali::NativeImageSourcePtr sourcePtr = Dali::NativeImageSource::New( source );
#include <dali-toolkit/devel-api/controls/control-devel.h>
#include <dali-toolkit/devel-api/visuals/visual-properties-devel.h>
#include <dali-toolkit/devel-api/visuals/image-visual-properties-devel.h>
+#include <dali-toolkit/devel-api/visuals/visual-actions-devel.h>
#include <dali-toolkit/devel-api/visuals/animated-vector-image-visual-actions-devel.h>
#include <dali-toolkit/devel-api/visuals/animated-vector-image-visual-signals-devel.h>
#include <dali/devel-api/rendering/renderer-devel.h>
attributes.Clear();
attributes.Add( DevelImageVisual::Property::PLAY_RANGE, array );
- DevelControl::DoAction( actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedVectorImageVisual::Action::UPDATE_PROPERTY, attributes );
+ DevelControl::DoAction( actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelVisual::Action::UPDATE_PROPERTY, attributes );
application.SendNotification();
application.Render();
attributes.Clear();
attributes.Add( DevelImageVisual::Property::PLAY_RANGE, array );
- DevelControl::DoAction( actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedVectorImageVisual::Action::UPDATE_PROPERTY, attributes );
+ DevelControl::DoAction( actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelVisual::Action::UPDATE_PROPERTY, attributes );
application.SendNotification();
application.Render();
attributes.Clear();
attributes.Add( DevelImageVisual::Property::PLAY_RANGE, array );
- DevelControl::DoAction( actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedVectorImageVisual::Action::UPDATE_PROPERTY, attributes );
+ DevelControl::DoAction( actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelVisual::Action::UPDATE_PROPERTY, attributes );
application.SendNotification();
application.Render();
attributes.Clear();
attributes.Add( DevelImageVisual::Property::PLAY_RANGE, array );
- DevelControl::DoAction( actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedVectorImageVisual::Action::UPDATE_PROPERTY, attributes );
+ DevelControl::DoAction( actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelVisual::Action::UPDATE_PROPERTY, attributes );
application.SendNotification();
application.Render();
Property::Map attributes;
attributes.Add( DevelImageVisual::Property::PLAY_RANGE, array );
- DevelControl::DoAction( actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedVectorImageVisual::Action::UPDATE_PROPERTY, attributes );
+ DevelControl::DoAction( actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelVisual::Action::UPDATE_PROPERTY, attributes );
DevelControl::DoAction( actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedVectorImageVisual::Action::JUMP_TO, 3 );
array.PushBack( 4 );
attributes.Add( DevelImageVisual::Property::PLAY_RANGE, array );
- DevelControl::DoAction( actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedVectorImageVisual::Action::UPDATE_PROPERTY, attributes );
+ DevelControl::DoAction( actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelVisual::Action::UPDATE_PROPERTY, attributes );
attributes.Clear();
DevelControl::DoAction( actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedVectorImageVisual::Action::PLAY, attributes );
attributes.Add( DevelImageVisual::Property::PLAY_RANGE, playRange );
attributes.Add( DevelImageVisual::Property::LOOP_COUNT, 5 );
- DevelControl::DoAction( actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedVectorImageVisual::Action::UPDATE_PROPERTY, attributes );
+ DevelControl::DoAction( actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelVisual::Action::UPDATE_PROPERTY, attributes );
application.SendNotification();
application.Render();
attributes.Add( DevelImageVisual::Property::PLAY_RANGE, playRange );
- DevelControl::DoAction( actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedVectorImageVisual::Action::UPDATE_PROPERTY, attributes );
+ DevelControl::DoAction( actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelVisual::Action::UPDATE_PROPERTY, attributes );
application.SendNotification();
application.Render();
attributes.Add( DevelImageVisual::Property::LOOP_COUNT, 10 );
- DevelControl::DoAction( actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedVectorImageVisual::Action::UPDATE_PROPERTY, attributes );
+ DevelControl::DoAction( actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelVisual::Action::UPDATE_PROPERTY, attributes );
application.SendNotification();
application.Render();
// Change stop behavior
attributes.Add( DevelImageVisual::Property::STOP_BEHAVIOR, DevelImageVisual::StopBehavior::LAST_FRAME );
- DevelControl::DoAction( actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedVectorImageVisual::Action::UPDATE_PROPERTY, attributes );
+ DevelControl::DoAction( actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelVisual::Action::UPDATE_PROPERTY, attributes );
attributes.Clear();
attributes.Add( DevelImageVisual::Property::STOP_BEHAVIOR, DevelImageVisual::StopBehavior::CURRENT_FRAME );
attributes.Add( DevelImageVisual::Property::LOOP_COUNT, -1 );
- DevelControl::DoAction( actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedVectorImageVisual::Action::UPDATE_PROPERTY, attributes );
+ DevelControl::DoAction( actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelVisual::Action::UPDATE_PROPERTY, attributes );
attributes.Clear();
// Change stop behavior
attributes.Add( DevelImageVisual::Property::STOP_BEHAVIOR, DevelImageVisual::StopBehavior::CURRENT_FRAME );
- DevelControl::DoAction( actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedVectorImageVisual::Action::UPDATE_PROPERTY, attributes );
+ DevelControl::DoAction( actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelVisual::Action::UPDATE_PROPERTY, attributes );
// Play again
DevelControl::DoAction( actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedVectorImageVisual::Action::PLAY, attributes );
// Change looping mode
attributes.Add( DevelImageVisual::Property::LOOPING_MODE, DevelImageVisual::LoopingMode::RESTART );
- DevelControl::DoAction( actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedVectorImageVisual::Action::UPDATE_PROPERTY, attributes );
+ DevelControl::DoAction( actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelVisual::Action::UPDATE_PROPERTY, attributes );
// Play again
DevelControl::DoAction( actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedVectorImageVisual::Action::PLAY, attributes );
Property::Map attributes;
attributes.Add( DevelImageVisual::Property::STOP_BEHAVIOR, DevelImageVisual::StopBehavior::LAST_FRAME );
- DevelControl::DoAction( actor1, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedVectorImageVisual::Action::UPDATE_PROPERTY, attributes );
- DevelControl::DoAction( actor2, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedVectorImageVisual::Action::UPDATE_PROPERTY, attributes );
+ DevelControl::DoAction( actor1, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelVisual::Action::UPDATE_PROPERTY, attributes );
+ DevelControl::DoAction( actor2, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelVisual::Action::UPDATE_PROPERTY, attributes );
DevelControl::DoAction( actor1, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedVectorImageVisual::Action::PLAY, Property::Map() );
#include <dali-toolkit/devel-api/controls/control-devel.h>
#include <dali-toolkit/devel-api/visuals/visual-properties-devel.h>
#include <dali-toolkit/devel-api/visuals/arc-visual-properties-devel.h>
-#include <dali-toolkit/devel-api/visuals/arc-visual-actions-devel.h>
+#include <dali-toolkit/devel-api/visuals/visual-actions-devel.h>
#include <dali/devel-api/rendering/renderer-devel.h>
#include "dummy-control.h"
.Add( DevelArcVisual::Property::START_ANGLE, startAngle )
.Add( DevelArcVisual::Property::SWEEP_ANGLE, sweepAngle );
- DevelControl::DoAction( actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelArcVisual::Action::UPDATE_PROPERTY, attributes );
+ DevelControl::DoAction( actor, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelVisual::Action::UPDATE_PROPERTY, attributes );
application.SendNotification();
application.Render();
END_TEST;
}
-int UtcDaliCanvasViewRasterizeTaskGetBufferSizeP(void)
-{
- ToolkitTestApplication application;
-
- Dali::Toolkit::Internal::CanvasView* dummyInternalCanvasView = new Dali::Toolkit::Internal::CanvasView(Vector2(100,100));
- DALI_TEST_CHECK( dummyInternalCanvasView );
-
- Dali::CanvasRenderer dummyCanvasRenderer = Dali::CanvasRenderer::New(Vector2(100, 100));
- DALI_TEST_CHECK( dummyCanvasRenderer );
-
- IntrusivePtr<Dali::Toolkit::Internal::CanvasRendererRasterizingTask> task = new Dali::Toolkit::Internal::CanvasRendererRasterizingTask(dummyInternalCanvasView, dummyCanvasRenderer);
- DALI_TEST_CHECK( task );
-
- //There is no rasterized buffer.
- DALI_TEST_EQUALS( task->GetBufferSize(), Vector2(0, 0), TEST_LOCATION );
-
- END_TEST;
-}
-
-int UtcDaliCanvasViewRasterizeTaskGetPixelDataP(void)
-{
-
- Dali::Toolkit::Internal::CanvasView* dummyInternalCanvasView = new Dali::Toolkit::Internal::CanvasView(Vector2(100,100));
- DALI_TEST_CHECK( dummyInternalCanvasView );
-
- Dali::CanvasRenderer dummyCanvasRenderer = Dali::CanvasRenderer::New(Vector2(100, 100));
- DALI_TEST_CHECK( dummyCanvasRenderer );
-
- IntrusivePtr<Dali::Toolkit::Internal::CanvasRendererRasterizingTask> task = new Dali::Toolkit::Internal::CanvasRendererRasterizingTask(dummyInternalCanvasView, dummyCanvasRenderer);
- DALI_TEST_CHECK( task );
-
- DALI_TEST_EQUALS( task->GetPixelData(), PixelData(), TEST_LOCATION );
-
- END_TEST;
-}
-
int UtcDaliCanvasViewRasterizeThreadP(void)
{
ToolkitTestApplication application;
{
ToolkitTestApplication application;
- Dali::Toolkit::Internal::CanvasView* dummyInternalCanvasView = new Dali::Toolkit::Internal::CanvasView(Vector2(100,100));
- DALI_TEST_CHECK( dummyInternalCanvasView );
+ Dali::Toolkit::CanvasView canvasView = Dali::Toolkit::CanvasView::New(Vector2(100, 100));
+ Dali::Toolkit::Internal::CanvasView& dummyInternalCanvasView = GetImpl(canvasView);
Dali::CanvasRenderer dummyCanvasRenderer = Dali::CanvasRenderer::New(Vector2(100, 100));
DALI_TEST_CHECK( dummyCanvasRenderer );
- IntrusivePtr<Dali::Toolkit::Internal::CanvasRendererRasterizingTask> task = new Dali::Toolkit::Internal::CanvasRendererRasterizingTask(dummyInternalCanvasView, dummyCanvasRenderer);
+ IntrusivePtr<Dali::Toolkit::Internal::CanvasRendererRasterizingTask> task = new Dali::Toolkit::Internal::CanvasRendererRasterizingTask(&dummyInternalCanvasView, dummyCanvasRenderer);
DALI_TEST_CHECK( task );
Dali::Toolkit::Internal::CanvasViewRasterizeThread *dummyThread = new Dali::Toolkit::Internal::CanvasViewRasterizeThread();
dummyThread->Process(false);
- PixelData pixelData = CreatePixelData( 100, 100 );
+ auto texture = Texture::New( Dali::TextureType::TEXTURE_2D, Pixel::RGBA8888, 100, 100 );
- dummyThread->RasterizationCompletedSignal().Connect(dummyInternalCanvasView, &Dali::Toolkit::Internal::CanvasView::ApplyRasterizedImage);
- dummyThread->RasterizationCompletedSignal().Emit(pixelData);
+ dummyThread->RasterizationCompletedSignal().Connect(&dummyInternalCanvasView, &Dali::Toolkit::Internal::CanvasView::ApplyRasterizedImage);
+ dummyThread->RasterizationCompletedSignal().Emit(texture);
application.SendNotification();
application.Render();
{
}
-int UtcDaliGlViewRegisterGlCallbackN(void)
+int UtcDaliGlViewRegisterGlCallbacksN(void)
{
ToolkitTestApplication application;
- tet_infoline("UtcDaliGlViewRegisterGlCallback");
+ tet_infoline("UtcDaliGlViewRegisterGlCallbacksN");
GlView view;
try
{
- view.RegisterGlCallback(Dali::MakeCallback(glInit), Dali::MakeCallback(glRenderFrame), Dali::MakeCallback(glTerminate));
+ view.RegisterGlCallbacks(Dali::MakeCallback(glInit), Dali::MakeCallback(glRenderFrame), Dali::MakeCallback(glTerminate));
DALI_TEST_CHECK(false);
}
catch(...)
application.GetScene().Add( view );
view.SetRenderingMode(GlView::RenderingMode::CONTINUOUS);
view.SetGraphicsConfig(true, true, 0, GlView::GraphicsApiVersion::GLES_VERSION_2_0);
- view.RegisterGlCallback(Dali::MakeCallback(glInit), Dali::MakeCallback(glRenderFrame), Dali::MakeCallback(glTerminate));
+ view.RegisterGlCallbacks(Dali::MakeCallback(glInit), Dali::MakeCallback(glRenderFrame), Dali::MakeCallback(glTerminate));
view.SetResizeCallback(Dali::MakeCallback(resizeCB));
application.SendNotification();
application.GetScene().Add( view );
view.SetRenderingMode(GlView::RenderingMode::CONTINUOUS);
view.SetGraphicsConfig(true, true, 0, GlView::GraphicsApiVersion::GLES_VERSION_2_0);
- view.RegisterGlCallback(Dali::MakeCallback(glInit), Dali::MakeCallback(glRenderFrame), Dali::MakeCallback(glTerminate));
+ view.RegisterGlCallbacks(Dali::MakeCallback(glInit), Dali::MakeCallback(glRenderFrame), Dali::MakeCallback(glTerminate));
application.SendNotification();
application.Render();
application.GetScene().Add( view );
view.SetGraphicsConfig(true, true, 0, GlView::GraphicsApiVersion::GLES_VERSION_2_0);
- view.RegisterGlCallback(Dali::MakeCallback(glInit), Dali::MakeCallback(glRenderFrame), Dali::MakeCallback(glTerminate));
+ view.RegisterGlCallbacks(Dali::MakeCallback(glInit), Dali::MakeCallback(glRenderFrame), Dali::MakeCallback(glTerminate));
view.SetResizeCallback(Dali::MakeCallback(resizeCB));
view.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
view.SetProperty(Actor::Property::SIZE, Vector2(360.0f, 360.0f));
#include <dali-toolkit/devel-api/visuals/visual-properties-devel.h>
#include <dali-toolkit/public-api/image-loader/image.h>
#include <dali-toolkit/public-api/image-loader/image-url.h>
+#include <dali-toolkit/devel-api/styling/style-manager-devel.h>
#include <test-native-image.h>
#include <test-encoded-image-buffer.h>
const char* TEST_IMAGE_1 = TEST_RESOURCE_DIR "/TB-gloss.png";
const char* TEST_IMAGE_2 = TEST_RESOURCE_DIR "/tb-norm.png";
+const char* TEST_BROKEN_IMAGE_DEFAULT = TEST_RESOURCE_DIR "/broken.png";
+const char* TEST_BROKEN_IMAGE_S = TEST_RESOURCE_DIR "/broken_s.9.png";
+const char* TEST_BROKEN_IMAGE_M = TEST_RESOURCE_DIR "/broken_m.9.png";
+const char* TEST_BROKEN_IMAGE_L = TEST_RESOURCE_DIR "/broken_l.9.png";
+const char* TEST_BROKEN_IMAGE_01 = TEST_RESOURCE_DIR "/button-up.9.png";
+const char* TEST_BROKEN_IMAGE_02 = TEST_RESOURCE_DIR "/heartsframe.9.png";
+
// resolution: 34*34, pixel format: RGBA8888
static const char* gImage_34_RGBA = TEST_RESOURCE_DIR "/icon-edit.png";
// resolution: 600*600, pixel format: RGB888
END_TEST;
}
+int UtcDaliImageViewTVGLoading(void)
+{
+ ToolkitTestApplication application;
+
+ tet_infoline("ImageView Testing TVG image loading");
+
+ {
+ ImageView imageView = ImageView::New( );
+
+ imageView.SetImage( TEST_RESOURCE_DIR "/test.tvg" );
+
+ application.GetScene().Add( imageView );
+ DALI_TEST_CHECK( imageView );
+ Vector3 naturalSize = imageView.GetNaturalSize();
+
+ DALI_TEST_EQUALS( naturalSize.width, 100.0f, TEST_LOCATION );
+ DALI_TEST_EQUALS( naturalSize.height, 100.0f, TEST_LOCATION );
+ }
+ END_TEST;
+}
+int UtcDaliImageViewImageLoadFailure01(void)
+{
+ ToolkitTestApplication application;
+
+ Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
+ DevelStyleManager::SetBrokenImageUrl(styleManager, DevelStyleManager::BrokenImageType::SMALL, TEST_BROKEN_IMAGE_S);
+ DevelStyleManager::SetBrokenImageUrl(styleManager, DevelStyleManager::BrokenImageType::NORMAL, TEST_BROKEN_IMAGE_M);
+ DevelStyleManager::SetBrokenImageUrl(styleManager, DevelStyleManager::BrokenImageType::LARGE, TEST_BROKEN_IMAGE_L);
+
+ std::string brokenUrl;
+ brokenUrl = DevelStyleManager::GetBrokenImageUrl(styleManager, DevelStyleManager::BrokenImageType::SMALL);
+ DALI_TEST_EQUALS( TEST_BROKEN_IMAGE_S, brokenUrl, TEST_LOCATION);
+
+ brokenUrl = DevelStyleManager::GetBrokenImageUrl(styleManager, DevelStyleManager::BrokenImageType::NORMAL);
+ DALI_TEST_EQUALS( TEST_BROKEN_IMAGE_M, brokenUrl, TEST_LOCATION);
+
+ brokenUrl = DevelStyleManager::GetBrokenImageUrl(styleManager, DevelStyleManager::BrokenImageType::LARGE);
+ DALI_TEST_EQUALS( TEST_BROKEN_IMAGE_L, brokenUrl, TEST_LOCATION);
+
+ ImageView imageView = ImageView::New("invalidUrl.png");
+ imageView.SetProperty( Actor::Property::SIZE, Vector2( 200.f, 200.f ) );
+
+ application.GetScene().Add( imageView );
+ application.SendNotification();
+ application.Render(16);
+
+ // loading started, this waits for the loader thread
+ DALI_TEST_EQUALS( Test::WaitForEventThreadTrigger( 1 ), true, TEST_LOCATION );
+
+ END_TEST;
+}
+
+int UtcDaliImageViewImageLoadFailure02(void)
+{
+ ToolkitTestApplication application;
+
+ Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
+ DevelStyleManager::SetBrokenImageUrl(styleManager, DevelStyleManager::BrokenImageType::SMALL, TEST_BROKEN_IMAGE_DEFAULT);
+ DevelStyleManager::SetBrokenImageUrl(styleManager, DevelStyleManager::BrokenImageType::NORMAL, TEST_BROKEN_IMAGE_M);
+ DevelStyleManager::SetBrokenImageUrl(styleManager, DevelStyleManager::BrokenImageType::LARGE, TEST_BROKEN_IMAGE_L);
+
+ std::string brokenUrl;
+ brokenUrl = DevelStyleManager::GetBrokenImageUrl(styleManager, DevelStyleManager::BrokenImageType::SMALL);
+ DALI_TEST_EQUALS( TEST_BROKEN_IMAGE_DEFAULT, brokenUrl, TEST_LOCATION);
+
+ brokenUrl = DevelStyleManager::GetBrokenImageUrl(styleManager, DevelStyleManager::BrokenImageType::NORMAL);
+ DALI_TEST_EQUALS( TEST_BROKEN_IMAGE_M, brokenUrl, TEST_LOCATION);
+
+ brokenUrl = DevelStyleManager::GetBrokenImageUrl(styleManager, DevelStyleManager::BrokenImageType::LARGE);
+ DALI_TEST_EQUALS( TEST_BROKEN_IMAGE_L, brokenUrl, TEST_LOCATION);
+
+ ImageView imageView = ImageView::New("invalidUrl.png");
+ imageView.SetProperty( Actor::Property::SIZE, Vector2( 30.f, 30.f ) );
+ application.GetScene().Add( imageView );
+ application.SendNotification();
+ application.Render(16);
+
+ // loading started, this waits for the loader thread
+ DALI_TEST_EQUALS( Test::WaitForEventThreadTrigger( 1 ), true, TEST_LOCATION );
+
+ END_TEST;
+}
+
+int UtcDaliImageViewImageLoadFailure03(void)
+{
+ ToolkitTestApplication application;
+
+ Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
+ DevelStyleManager::SetBrokenImageUrl(styleManager, DevelStyleManager::BrokenImageType::SMALL, TEST_BROKEN_IMAGE_01);
+ DevelStyleManager::SetBrokenImageUrl(styleManager, DevelStyleManager::BrokenImageType::NORMAL, TEST_BROKEN_IMAGE_02);
+
+ std::string brokenUrl;
+ brokenUrl = DevelStyleManager::GetBrokenImageUrl(styleManager, DevelStyleManager::BrokenImageType::SMALL);
+ DALI_TEST_EQUALS( TEST_BROKEN_IMAGE_01, brokenUrl, TEST_LOCATION);
+
+ brokenUrl = DevelStyleManager::GetBrokenImageUrl(styleManager, DevelStyleManager::BrokenImageType::NORMAL);
+ DALI_TEST_EQUALS( TEST_BROKEN_IMAGE_02, brokenUrl, TEST_LOCATION);
+
+ ImageView imageView = ImageView::New("invalidUrl.png");
+ imageView.SetProperty( Actor::Property::SIZE, Vector2( 100.f, 100.f ) );
+ application.GetScene().Add( imageView );
+ application.SendNotification();
+ application.Render(16);
+
+ // loading started, this waits for the loader thread
+ DALI_TEST_EQUALS( Test::WaitForEventThreadTrigger( 1 ), true, TEST_LOCATION );
+
+ END_TEST;
+}
+
namespace
{
application.SendNotification();
application.Render();
+ // EMOJI + ZWJ + EMOJI case for coverage.
+ const std::string emojiWithZWJ = "👩‍🔬";
+ label.SetProperty( TextLabel::Property::TEXT, emojiWithZWJ );
+
+ application.SendNotification();
+ application.Render();
+
END_TEST;
}
application.SendNotification();
application.Render(20);
- Transition transition = Transition::New(control1, control2, TimePeriod(-0.1f, -0.1f));
+ Transition transition = Transition::New(control1, control2, true, TimePeriod(-0.1f, -0.1f));
TimePeriod timePeriod = transition.GetTimePeriod();
DALI_TEST_EQUALS(0.0f, timePeriod.durationSeconds, TEST_LOCATION);
DALI_TEST_EQUALS(0.0f, timePeriod.delaySeconds, TEST_LOCATION);
application.SendNotification();
application.Render(20);
- Transition transition = Transition::New(control1, control2, TimePeriod(-0.1f));
+ Transition transition = Transition::New(control1, control2, true, TimePeriod(-0.1f));
TimePeriod timePeriod = transition.GetTimePeriod();
DALI_TEST_EQUALS(0.0f, timePeriod.durationSeconds, TEST_LOCATION);
DALI_TEST_EQUALS(0.0f, timePeriod.delaySeconds, TEST_LOCATION);
application.SendNotification();
application.Render(20);
- Transition transition = Transition::New(control1, control2, TimePeriod(0.5f));
+ Transition transition = Transition::New(control1, control2, true, TimePeriod(0.5f));
TransitionSet transitionSet = TransitionSet::New();
transitionSet.AddTransition(transition);
transitionSet.Play();
END_TEST;
}
+int UtcDaliTransitionBetweenControlPair2(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline(" UtcDaliTransitionBetweenControlPair2 - source target will be transitioned.");
+
+ Vector3 sourcePosition(100, 200, 0);
+ Vector3 sourceSize(150, 150, 0);
+ Vector3 sourceScale(1, 2, 0);
+ Vector4 sourceColor(1.0f, 1.0f, 1.0f, 0.5f);
+ float sourceOpacity(0.5f);
+ float sourceRadius(30.f);
+ float sourceBorderlineWidth(60.0f);
+ Vector4 sourceBorderlineColor(1.0f, 0.0f, 0.0f, 1.0f);
+ float sourceBorderlineOffset(1.f);
+ Vector4 sourceRadiusV4 = Vector4(sourceRadius, sourceRadius, sourceRadius, sourceRadius);
+
+ Vector3 destinationPosition(50, 50, 0);
+ Vector3 destinationSize(120, 120, 0);
+ Vector3 destinationScale(2, 1, 0);
+ Vector4 destinationColor(1.0f, 0.5f, 1.0f, 0.8f);
+ float destinationOpacity(0.8f);
+ float destinationRadius(50.f);
+ float destinationBorderlineWidth(80.0f);
+ Vector4 destinationBorderlineColor(0.5f, 1.0f, 0.5f, 0.3f);
+ float destinationBorderlineOffset(-1.0f);
+ Vector4 destinationRadiusV4 = Vector4(destinationRadius, destinationRadius, destinationRadius, destinationRadius);
+
+ Control control1 = Control::New();
+ control1.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+ control1.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
+ control1.SetProperty(Actor::Property::POSITION, sourcePosition);
+ control1.SetProperty(Actor::Property::SIZE, sourceSize);
+ control1.SetProperty(Actor::Property::SCALE, sourceScale);
+ control1.SetProperty(Actor::Property::COLOR, sourceColor);
+ control1.SetProperty(Actor::Property::OPACITY, sourceOpacity);
+ Property::Map controlProperty1;
+ controlProperty1.Insert(Toolkit::Visual::Property::TYPE, Toolkit::Visual::COLOR);
+ controlProperty1.Insert(Toolkit::ColorVisual::Property::MIX_COLOR, Vector4(1.0f, 0.0f, 0.0f, 1.0f));
+ controlProperty1.Insert(Toolkit::DevelVisual::Property::CORNER_RADIUS, sourceRadius);
+ controlProperty1.Insert(Toolkit::DevelVisual::Property::BORDERLINE_WIDTH, sourceBorderlineWidth);
+ controlProperty1.Insert(Toolkit::DevelVisual::Property::BORDERLINE_COLOR, sourceBorderlineColor);
+ controlProperty1.Insert(Toolkit::DevelVisual::Property::BORDERLINE_OFFSET, sourceBorderlineOffset);
+ control1.SetProperty(Toolkit::Control::Property::BACKGROUND, controlProperty1);
+
+ Control control2 = Control::New();
+ control2.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+ control2.SetProperty(Actor::Property::ANCHOR_POINT, ParentOrigin::CENTER);
+ control2.SetProperty(Actor::Property::POSITION, destinationPosition);
+ control2.SetProperty(Actor::Property::SIZE, destinationSize);
+ control2.SetProperty(Actor::Property::SCALE, destinationScale);
+ control2.SetProperty(Actor::Property::COLOR, destinationColor);
+ control2.SetProperty(Actor::Property::OPACITY, destinationOpacity);
+ Property::Map controlProperty2;
+ controlProperty2.Insert(Toolkit::Visual::Property::TYPE, Toolkit::Visual::COLOR);
+ controlProperty2.Insert(Toolkit::ColorVisual::Property::MIX_COLOR, Vector4(1.0f, 1.0f, 0.0f, 0.5f));
+ controlProperty2.Insert(Toolkit::DevelVisual::Property::CORNER_RADIUS, destinationRadius);
+ controlProperty2.Insert(Toolkit::DevelVisual::Property::BORDERLINE_WIDTH, destinationBorderlineWidth);
+ controlProperty2.Insert(Toolkit::DevelVisual::Property::BORDERLINE_COLOR, destinationBorderlineColor);
+ controlProperty2.Insert(Toolkit::DevelVisual::Property::BORDERLINE_OFFSET, destinationBorderlineOffset);
+ control2.SetProperty(Toolkit::Control::Property::BACKGROUND, controlProperty2);
+
+ DALI_TEST_EQUALS(destinationPosition, control2.GetProperty<Vector3>(Actor::Property::POSITION), TEST_LOCATION);
+ Property::Map backgroundMap = control2.GetProperty<Property::Map>(Toolkit::Control::Property::BACKGROUND);
+ Vector4 cornerRadius = backgroundMap.Find(Toolkit::DevelVisual::Property::CORNER_RADIUS)->Get<Vector4>();
+ DALI_TEST_EQUALS(destinationRadiusV4, cornerRadius, TEST_LOCATION);
+ float borderlineWidth = backgroundMap.Find(Toolkit::DevelVisual::Property::BORDERLINE_WIDTH)->Get<float>();
+ DALI_TEST_EQUALS(destinationBorderlineWidth, borderlineWidth, TEST_LOCATION);
+ Vector4 borderlineColor = backgroundMap.Find(Toolkit::DevelVisual::Property::BORDERLINE_COLOR)->Get<Vector4>();
+ DALI_TEST_EQUALS(destinationBorderlineColor, borderlineColor, TEST_LOCATION);
+ float borderlineOffset = backgroundMap.Find(Toolkit::DevelVisual::Property::BORDERLINE_OFFSET)->Get<float>();
+ DALI_TEST_EQUALS(destinationBorderlineOffset, borderlineOffset, TEST_LOCATION);
+
+ application.GetScene().Add(control1);
+ application.GetScene().Add(control2);
+
+ application.SendNotification();
+ application.Render(20);
+
+ Transition transition = Transition::New(control1, control2, false, TimePeriod(0.5f));
+ TransitionSet transitionSet = TransitionSet::New();
+ transitionSet.AddTransition(transition);
+ transitionSet.Play();
+
+ bool signalReceived(false);
+ TransitionFinishCheck finishCheck(signalReceived);
+ transitionSet.FinishedSignal().Connect(&application, finishCheck);
+
+ application.SendNotification();
+ application.Render(50);
+
+ // We didn't expect the animation to finish yet
+ application.SendNotification();
+ finishCheck.CheckSignalNotReceived();
+
+ DALI_TEST_NOT_EQUALS(destinationPosition, control1.GetCurrentProperty<Vector3>(Actor::Property::POSITION), 0.00001f, TEST_LOCATION);
+ DALI_TEST_EQUALS(1, control1.GetRendererCount(), TEST_LOCATION);
+
+ Dali::Renderer renderer = control1.GetRendererAt(0);
+ Property::Index index = renderer.GetPropertyIndex(DevelVisual::Property::CORNER_RADIUS);
+ cornerRadius = renderer.GetCurrentProperty<Vector4>(index);
+ DALI_TEST_NOT_EQUALS(destinationRadiusV4, cornerRadius, 0.00001f, TEST_LOCATION);
+
+ index = renderer.GetPropertyIndex(DevelVisual::Property::BORDERLINE_WIDTH);
+ borderlineWidth = renderer.GetCurrentProperty<float>(index);
+ DALI_TEST_NOT_EQUALS(destinationBorderlineWidth, borderlineWidth, 0.00001f, TEST_LOCATION);
+
+ index = renderer.GetPropertyIndex(DevelVisual::Property::BORDERLINE_COLOR);
+ borderlineColor = renderer.GetCurrentProperty<Vector4>(index);
+ DALI_TEST_NOT_EQUALS(destinationBorderlineColor, borderlineColor, 0.00001f, TEST_LOCATION);
+
+ index = renderer.GetPropertyIndex(DevelVisual::Property::BORDERLINE_OFFSET);
+ borderlineOffset = renderer.GetCurrentProperty<float>(index);
+ DALI_TEST_NOT_EQUALS(destinationBorderlineOffset, borderlineOffset, 0.00001f, TEST_LOCATION);
+
+ application.SendNotification();
+ application.Render(700);
+
+ // We did expect the animation to finish
+ application.SendNotification();
+ finishCheck.CheckSignalReceived();
+
+ // After the transition is finished,
+ // every current and renderer propeties of control1 are equal to destination properties.
+ DALI_TEST_EQUALS(destinationPosition, control1.GetCurrentProperty<Vector3>(Actor::Property::POSITION), TEST_LOCATION);
+ DALI_TEST_EQUALS(destinationSize, control1.GetCurrentProperty<Vector3>(Actor::Property::SIZE), TEST_LOCATION);
+ DALI_TEST_EQUALS(destinationScale, control1.GetCurrentProperty<Vector3>(Actor::Property::SCALE), TEST_LOCATION);
+ DALI_TEST_EQUALS(destinationColor, control1.GetCurrentProperty<Vector4>(Actor::Property::COLOR), TEST_LOCATION);
+ DALI_TEST_EQUALS(destinationOpacity, control1.GetCurrentProperty<float>(Actor::Property::OPACITY), TEST_LOCATION);
+
+ DALI_TEST_EQUALS(1, control1.GetRendererCount(), TEST_LOCATION);
+ renderer = control1.GetRendererAt(0);
+ index = renderer.GetPropertyIndex(DevelVisual::Property::CORNER_RADIUS);
+ cornerRadius = renderer.GetCurrentProperty<Vector4>(index);
+ DALI_TEST_EQUALS(destinationRadiusV4, cornerRadius, TEST_LOCATION);
+
+ index = renderer.GetPropertyIndex(DevelVisual::Property::BORDERLINE_WIDTH);
+ borderlineWidth = renderer.GetCurrentProperty<float>(index);
+ DALI_TEST_EQUALS(destinationBorderlineWidth, borderlineWidth, TEST_LOCATION);
+
+ index = renderer.GetPropertyIndex(DevelVisual::Property::BORDERLINE_COLOR);
+ borderlineColor = renderer.GetCurrentProperty<Vector4>(index);
+ DALI_TEST_EQUALS(destinationBorderlineColor, borderlineColor, TEST_LOCATION);
+
+ index = renderer.GetPropertyIndex(DevelVisual::Property::BORDERLINE_OFFSET);
+ borderlineOffset = renderer.GetCurrentProperty<float>(index);
+ DALI_TEST_EQUALS(destinationBorderlineOffset, borderlineOffset, TEST_LOCATION);
+
+ // every actor properties of control1 are returned to the source properties.
+ DALI_TEST_EQUALS(sourcePosition, control1.GetProperty<Vector3>(Actor::Property::POSITION), TEST_LOCATION);
+ DALI_TEST_EQUALS(sourceSize, control1.GetProperty<Vector3>(Actor::Property::SIZE), TEST_LOCATION);
+ DALI_TEST_EQUALS(sourceScale, control1.GetProperty<Vector3>(Actor::Property::SCALE), TEST_LOCATION);
+ DALI_TEST_EQUALS(sourceColor, control1.GetProperty<Vector4>(Actor::Property::COLOR), TEST_LOCATION);
+ DALI_TEST_EQUALS(sourceOpacity, control1.GetProperty<float>(Actor::Property::OPACITY), TEST_LOCATION);
+
+ application.SendNotification();
+ application.Render(20);
+
+ // after next update, renderer properties are returned to the source properties.
+ DALI_TEST_EQUALS(1, control1.GetRendererCount(), TEST_LOCATION);
+ renderer = control1.GetRendererAt(0);
+ index = renderer.GetPropertyIndex(DevelVisual::Property::CORNER_RADIUS);
+ cornerRadius = renderer.GetCurrentProperty<Vector4>(index);
+ DALI_TEST_EQUALS(sourceRadiusV4, cornerRadius, TEST_LOCATION);
+
+ index = renderer.GetPropertyIndex(DevelVisual::Property::BORDERLINE_WIDTH);
+ borderlineWidth = renderer.GetCurrentProperty<float>(index);
+ DALI_TEST_EQUALS(sourceBorderlineWidth, borderlineWidth, TEST_LOCATION);
+
+ index = renderer.GetPropertyIndex(DevelVisual::Property::BORDERLINE_COLOR);
+ borderlineColor = renderer.GetCurrentProperty<Vector4>(index);
+ DALI_TEST_EQUALS(sourceBorderlineColor, borderlineColor, TEST_LOCATION);
+
+ index = renderer.GetPropertyIndex(DevelVisual::Property::BORDERLINE_OFFSET);
+ borderlineOffset = renderer.GetCurrentProperty<float>(index);
+ DALI_TEST_EQUALS(sourceBorderlineOffset, borderlineOffset, TEST_LOCATION);
+
+ END_TEST;
+}
+
int UtcDaliTransitionBetweenControlPairWithoutEmptySourceBackground(void)
{
ToolkitTestApplication application;
application.SendNotification();
application.Render(20);
- Transition transition = Transition::New(control1, control2, TimePeriod(0.5f));
+ Transition transition = Transition::New(control1, control2, true, TimePeriod(0.5f));
TransitionSet transitionSet = TransitionSet::New();
transitionSet.AddTransition(transition);
transitionSet.Play();
Vector3 startWorldPosition = control1.GetProperty<Vector3>(Actor::Property::WORLD_POSITION);
Vector3 finishWorldPosition = control2.GetProperty<Vector3>(Actor::Property::WORLD_POSITION);
- Transition transition = Transition::New(control1, control2, TimePeriod(0.5f));
+ Transition transition = Transition::New(control1, control2, true, TimePeriod(0.5f));
TransitionSet transitionSet = TransitionSet::New();
transitionSet.AddTransition(transition);
transitionSet.Play();
Vector3 startWorldPosition = control1.GetProperty<Vector3>(Actor::Property::WORLD_POSITION);
Vector3 finishWorldPosition = control2.GetProperty<Vector3>(Actor::Property::WORLD_POSITION);
- Transition transition = Transition::New(control1, control2, TimePeriod(0.5f, 0.5f));
+ Transition transition = Transition::New(control1, control2, true, TimePeriod(0.5f, 0.5f));
TransitionSet transitionSet = TransitionSet::New();
transitionSet.AddTransition(transition);
transitionSet.Play();
application.SendNotification();
application.Render(20);
- Transition transition = Transition::New(control1, control2, TimePeriod(0.5f));
+ Transition transition = Transition::New(control1, control2, true, TimePeriod(0.5f));
TransitionSet transitionSet = TransitionSet::New();
transitionSet.AddTransition(transition);
transitionSet.Play();
application.SendNotification();
application.Render(20);
- Transition transition = Transition::New(control1, control2, TimePeriod(0.5f));
+ Transition transition = Transition::New(control1, control2, true, TimePeriod(0.5f));
transition.TransitionWithChild(true);
TransitionSet transitionSet = TransitionSet::New();
transitionSet.AddTransition(transition);
control3.SetProperty(Actor::Property::INHERIT_ORIENTATION, true);
control3.SetProperty(Actor::Property::INHERIT_SCALE, true);
- transition = Transition::New(control1, control3, TimePeriod(0.5f));
+ transition = Transition::New(control1, control3, true, TimePeriod(0.5f));
transitionSet = TransitionSet::New();
transitionSet.AddTransition(transition);
transitionSet.Play();
bool signalReceived(false);
TransitionFinishCheck finishCheck(signalReceived);
- transition = Transition::New(control1, control3, TimePeriod(0.5f));
+ transition = Transition::New(control1, control3, true, TimePeriod(0.5f));
transitionSet = TransitionSet::New();
transitionSet.AddTransition(transition);
transitionSet.Play();
bool signalReceived(false);
TransitionFinishCheck finishCheck(signalReceived);
- transition = Transition::New(control1, control3, TimePeriod(0.5f));
+ transition = Transition::New(control1, control3, true, TimePeriod(0.5f));
transitionSet = TransitionSet::New();
transitionSet.AddTransition(transition);
transitionSet.Play();
END_TEST;
}
+int UtcDaliVisualBorderlineBlendModeTest(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline( "UtcDaliVisualBorderlineBlendModeTest" );
+ VisualFactory factory = VisualFactory::Get();
+
+ // Case 1 : Test which doesn't support borderline feature.
+ {
+ tet_printf("Test Unsupported visual type\n");
+ Property::Map propertyMap;
+ propertyMap.Insert(Visual::Property::TYPE, Visual::BORDER);
+ propertyMap.Insert(BorderVisual::Property::COLOR, Color::BLUE);
+ propertyMap.Insert(DevelVisual::Property::BORDERLINE_WIDTH, 1.0f);
+ Visual::Base borderVisual = factory.CreateVisual( propertyMap );
+
+ DummyControl actor = DummyControl::New(true);
+ Impl::DummyControl& dummyImpl = static_cast<Impl::DummyControl&>(actor.GetImplementation());
+ dummyImpl.RegisterVisual( DummyControl::Property::TEST_VISUAL, borderVisual );
+ actor.SetProperty( Actor::Property::SIZE, Vector2( 2000.f, 2000.f ) );
+ actor.SetProperty( Actor::Property::PARENT_ORIGIN,ParentOrigin::CENTER);
+ application.GetScene().Add(actor);
+
+ DALI_TEST_EQUALS( actor.GetRendererCount(), 1u, TEST_LOCATION);
+
+ Renderer renderer = actor.GetRendererAt(0);
+
+ Property::Value blendModeValue = renderer.GetProperty( Renderer::Property::BLEND_MODE );
+ // Visual::BORDER doesn't support BORDERLINE. BlendMode is AUTO.
+ DALI_TEST_EQUALS( blendModeValue.Get<int>(), (int)BlendMode::AUTO, TEST_LOCATION );
+
+ application.GetScene().Remove(actor);
+ }
+
+ // Case 2 : Test which support borderline feature.
+ {
+ tet_printf("Test normal case\n");
+ Property::Map propertyMap;
+ propertyMap.Insert(Visual::Property::TYPE, Visual::COLOR);
+ propertyMap.Insert(ColorVisual::Property::MIX_COLOR, Color::BLUE);
+ propertyMap.Insert(DevelVisual::Property::BORDERLINE_WIDTH, 1.0f);
+ Visual::Base colorVisual = factory.CreateVisual( propertyMap );
+
+ DummyControl actor = DummyControl::New(true);
+ Impl::DummyControl& dummyImpl = static_cast<Impl::DummyControl&>(actor.GetImplementation());
+ dummyImpl.RegisterVisual( DummyControl::Property::TEST_VISUAL, colorVisual );
+ actor.SetProperty( Actor::Property::SIZE, Vector2( 2000.f, 2000.f ) );
+ actor.SetProperty( Actor::Property::PARENT_ORIGIN,ParentOrigin::CENTER);
+ application.GetScene().Add(actor);
+
+ DALI_TEST_EQUALS( actor.GetRendererCount(), 1u, TEST_LOCATION);
+
+ Renderer renderer = actor.GetRendererAt(0);
+
+ Property::Value blendModeValue = renderer.GetProperty( Renderer::Property::BLEND_MODE );
+ // Visual::COLOR support BORDERLINE. BlendMode is ON_WITHOUT_CULL.
+ DALI_TEST_EQUALS( blendModeValue.Get<int>(), (int)BlendMode::ON_WITHOUT_CULL, TEST_LOCATION );
+
+ application.GetScene().Remove(actor);
+ }
+
+ // Case 3 : Test which animated borderline.
+ {
+ tet_printf("Test borderline animate case\n");
+ Property::Map propertyMap;
+ propertyMap.Insert(Visual::Property::TYPE, Visual::COLOR);
+ propertyMap.Insert(ColorVisual::Property::MIX_COLOR, Color::BLUE);
+ Visual::Base colorVisual = factory.CreateVisual( propertyMap );
+
+ DummyControl actor = DummyControl::New(true);
+ Impl::DummyControl& dummyImpl = static_cast<Impl::DummyControl&>(actor.GetImplementation());
+ dummyImpl.RegisterVisual( DummyControl::Property::TEST_VISUAL, colorVisual );
+ actor.SetProperty( Actor::Property::SIZE, Vector2( 2000.f, 2000.f ) );
+ actor.SetProperty( Actor::Property::PARENT_ORIGIN,ParentOrigin::CENTER);
+ application.GetScene().Add(actor);
+
+ DALI_TEST_EQUALS( actor.GetRendererCount(), 1u, TEST_LOCATION);
+
+ Renderer renderer = actor.GetRendererAt(0);
+
+ Property::Value blendModeValue = renderer.GetProperty( Renderer::Property::BLEND_MODE );
+ // BlendMode is AUTO.
+ DALI_TEST_EQUALS( blendModeValue.Get<int>(), (int)BlendMode::AUTO, TEST_LOCATION );
+
+ Animation animation = Animation::New(0.1f);
+ animation.AnimateTo( DevelControl::GetVisualProperty(actor, DummyControl::Property::TEST_VISUAL, DevelVisual::Property::BORDERLINE_WIDTH), 1.0f );
+ animation.Play();
+
+ application.SendNotification();
+ application.Render();
+ application.Render(101u); // End of animation
+
+ blendModeValue = renderer.GetProperty( Renderer::Property::BLEND_MODE );
+ // BlendMode is ON_WITHOUT_CULL.
+ DALI_TEST_EQUALS( blendModeValue.Get<int>(), (int)BlendMode::ON_WITHOUT_CULL, TEST_LOCATION );
+
+ Animation revanimation = Animation::New(0.1f);
+ revanimation.AnimateTo( DevelControl::GetVisualProperty(actor, DummyControl::Property::TEST_VISUAL, DevelVisual::Property::BORDERLINE_WIDTH), 0.0f );
+ revanimation.Play();
+
+ application.SendNotification();
+ application.Render();
+ application.Render(101u); // End of animation
+
+ blendModeValue = renderer.GetProperty( Renderer::Property::BLEND_MODE );
+ // BlendMode is still ON_WITHOUT_CULL.
+ DALI_TEST_EQUALS( blendModeValue.Get<int>(), (int)BlendMode::ON_WITHOUT_CULL, TEST_LOCATION );
+
+ application.GetScene().Remove(actor);
+ }
+
+ // Case 4 : Test which animated corner radius occur.
+ {
+ tet_printf("Test borderline animate case\n");
+ Property::Map propertyMap;
+ propertyMap.Insert(Visual::Property::TYPE, Visual::COLOR);
+ propertyMap.Insert(ColorVisual::Property::MIX_COLOR, Color::BLUE);
+ propertyMap.Insert(DevelVisual::Property::BORDERLINE_WIDTH, 1.0f);
+ Visual::Base colorVisual = factory.CreateVisual( propertyMap );
+
+ DummyControl actor = DummyControl::New(true);
+ Impl::DummyControl& dummyImpl = static_cast<Impl::DummyControl&>(actor.GetImplementation());
+ dummyImpl.RegisterVisual( DummyControl::Property::TEST_VISUAL, colorVisual );
+ actor.SetProperty( Actor::Property::SIZE, Vector2( 2000.f, 2000.f ) );
+ actor.SetProperty( Actor::Property::PARENT_ORIGIN,ParentOrigin::CENTER);
+ application.GetScene().Add(actor);
+
+ DALI_TEST_EQUALS( actor.GetRendererCount(), 1u, TEST_LOCATION);
+
+ Renderer renderer = actor.GetRendererAt(0);
+
+ Property::Value blendModeValue = renderer.GetProperty( Renderer::Property::BLEND_MODE );
+ // BlendMode is ON_WITHOUT_CULL.
+ DALI_TEST_EQUALS( blendModeValue.Get<int>(), (int)BlendMode::ON_WITHOUT_CULL, TEST_LOCATION );
+
+ Animation animation = Animation::New(0.1f);
+ animation.AnimateTo( DevelControl::GetVisualProperty(actor, DummyControl::Property::TEST_VISUAL, DevelVisual::Property::CORNER_RADIUS), Vector4(1.0f, 1.0f, 1.0f, 1.0f) );
+ animation.Play();
+
+ application.SendNotification();
+ application.Render();
+ application.Render(101u); // End of animation
+
+ blendModeValue = renderer.GetProperty( Renderer::Property::BLEND_MODE );
+ // BlendMode is ON_WITHOUT_CULL.
+ DALI_TEST_EQUALS( blendModeValue.Get<int>(), (int)BlendMode::ON_WITHOUT_CULL, TEST_LOCATION );
+
+ application.GetScene().Remove(actor);
+ }
+
+ END_TEST;
+}
+
+int UtcDaliVisualBorderlineColorAnimateTest(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline( "UtcDaliVisualBorderlineColorAnimateTest color" );
+
+ TestGraphicsController& graphics = application.GetGraphicsController();
+ static std::vector<UniformData> customUniforms =
+ {
+ UniformData("mixColor", Property::Type::VECTOR3),
+ UniformData("cornerRadius", Property::Type::VECTOR4),
+ UniformData("cornerRadiusPolicy", Property::Type::FLOAT),
+ UniformData("borderlineWidth", Property::Type::FLOAT),
+ UniformData("borderlineColor", Property::Type::VECTOR4),
+ UniformData("borderlineOffset", Property::Type::FLOAT),
+ };
+ graphics.AddCustomUniforms(customUniforms);
+
+ {
+ const Vector3 INITIAL_MIX_COLOR( 1.0f,0.0f,1.0f );
+ const float INITIAL_MIX_OPACITY( 0.5f );
+ const Vector4 INITIAL_BORDERLINE_COLOR( 0.0f,1.0f,0.0f,1.0f );
+ const float INITIAL_ACTOR_OPACITY( 1.0f );
+ const Vector3 TARGET_MIX_COLOR( 1.0f, 0.0f, 0.0f );
+ const float TARGET_MIX_OPACITY( 0.8f );
+ const Vector4 TARGET_BORDERLINE_COLOR( 1.0f, 0.0f, 1.0f, 0.2f);
+ const float TARGET_ACTOR_OPACITY( 0.5f );
+
+ VisualFactory factory = VisualFactory::Get();
+ Property::Map propertyMap;
+ propertyMap.Insert(Visual::Property::TYPE, Visual::COLOR);
+ propertyMap.Insert(Visual::Property::MIX_COLOR, INITIAL_MIX_COLOR);
+ propertyMap.Insert(Visual::Property::OPACITY, INITIAL_MIX_OPACITY);
+ propertyMap.Insert(DevelVisual::Property::BORDERLINE_WIDTH, 1.0f);
+ propertyMap.Insert(DevelVisual::Property::BORDERLINE_COLOR, INITIAL_BORDERLINE_COLOR);
+ Visual::Base visual = factory.CreateVisual( propertyMap );
+
+ DummyControl actor = DummyControl::New(true);
+ Impl::DummyControl& dummyImpl = static_cast<Impl::DummyControl&>(actor.GetImplementation());
+ dummyImpl.RegisterVisual( DummyControl::Property::TEST_VISUAL, visual );
+ actor.SetProperty( Actor::Property::SIZE, Vector2( 2000.f, 2000.f ) );
+ actor.SetProperty( Actor::Property::OPACITY, INITIAL_ACTOR_OPACITY );
+ actor.SetProperty( Actor::Property::PARENT_ORIGIN,ParentOrigin::CENTER);
+ application.GetScene().Add(actor);
+
+ DALI_TEST_EQUALS( actor.GetRendererCount(), 1u, TEST_LOCATION);
+
+ Animation animation = Animation::New(4.0f);
+ animation.AnimateTo( DevelControl::GetVisualProperty(actor, DummyControl::Property::TEST_VISUAL, Visual::Property::MIX_COLOR), TARGET_MIX_COLOR );
+ animation.AnimateTo( DevelControl::GetVisualProperty(actor, DummyControl::Property::TEST_VISUAL, Visual::Property::OPACITY), TARGET_MIX_OPACITY);
+ animation.AnimateTo( DevelControl::GetVisualProperty(actor, DummyControl::Property::TEST_VISUAL, DevelVisual::Property::BORDERLINE_COLOR), TARGET_BORDERLINE_COLOR );
+ animation.AnimateTo( Property(actor, Actor::Property::OPACITY), TARGET_ACTOR_OPACITY);
+ animation.Play();
+
+ TestGlAbstraction& glAbstraction = application.GetGlAbstraction();
+
+ application.SendNotification();
+ application.Render(0);
+ application.Render(2000u); // halfway point
+ application.SendNotification();
+
+ Vector3 halfwayMixColor = (INITIAL_MIX_COLOR + TARGET_MIX_COLOR ) * 0.5f;
+ float halfwayMixOpacity = (INITIAL_MIX_OPACITY + TARGET_MIX_OPACITY ) * 0.5f;
+ Vector4 halfwayBorderlineColor = (INITIAL_BORDERLINE_COLOR + TARGET_BORDERLINE_COLOR) * 0.5f;
+ float halfwayActorOpacity = (INITIAL_ACTOR_OPACITY + TARGET_ACTOR_OPACITY ) * 0.5f;
+ halfwayMixOpacity *= halfwayActorOpacity;
+ DALI_TEST_EQUALS( glAbstraction.CheckUniformValue<Vector3>("mixColor", halfwayMixColor), true, TEST_LOCATION );
+ DALI_TEST_EQUALS( glAbstraction.CheckUniformValue<Vector4>("uColor", Vector4(1.0f, 1.0f, 1.0f, halfwayMixOpacity)), true, TEST_LOCATION );
+ DALI_TEST_EQUALS( glAbstraction.CheckUniformValue<Vector4>("uActorColor", Vector4(1.0f, 1.0f, 1.0f, halfwayActorOpacity)), true, TEST_LOCATION );
+ DALI_TEST_EQUALS( glAbstraction.CheckUniformValue<Vector4>("borderlineColor", halfwayBorderlineColor), true, TEST_LOCATION );
+
+ application.Render(2001u); // go past end
+ application.SendNotification(); // Trigger signals
+
+ DALI_TEST_EQUALS( actor.GetCurrentProperty< Vector4 >( Actor::Property::COLOR ), Vector4(1.0f, 1.0f, 1.0f, TARGET_ACTOR_OPACITY), TEST_LOCATION );
+ DALI_TEST_EQUALS( glAbstraction.CheckUniformValue<Vector3>("mixColor", TARGET_MIX_COLOR), true, TEST_LOCATION );
+ DALI_TEST_EQUALS( glAbstraction.CheckUniformValue<Vector4>("uColor", Vector4(1.0f, 1.0f, 1.0f, TARGET_MIX_OPACITY * TARGET_ACTOR_OPACITY) ), true, TEST_LOCATION );
+ DALI_TEST_EQUALS( glAbstraction.CheckUniformValue<Vector4>("uActorColor", Vector4(1.0f, 1.0f, 1.0f, TARGET_ACTOR_OPACITY)), true, TEST_LOCATION );
+ DALI_TEST_EQUALS( glAbstraction.CheckUniformValue<Vector4>("borderlineColor", TARGET_BORDERLINE_COLOR ), true, TEST_LOCATION );
+
+ actor.Unparent();
+ }
+
+ END_TEST;
+}
int UtcDaliColorVisualBlurRadius(void)
{
return controlDataImpl.GetVisualProperty(index, visualPropertyKey);
}
-void CreateTransitions(Control control, Dali::Animation& animation, Dali::Toolkit::Control source, AlphaFunction alphaFunction, TimePeriod timePeriod)
-{
- if(animation)
- {
- // make visual transition of control visual.
- Internal::Control& internalControl = Toolkit::Internal::GetImplementation(control);
- Internal::Control::Impl& controlDataImpl = Internal::Control::Impl::Get(internalControl);
- controlDataImpl.MakeVisualTransition(animation, source, Toolkit::Control::Property::BACKGROUND, alphaFunction, timePeriod);
- controlDataImpl.MakeVisualTransition(animation, source, Toolkit::DevelControl::Property::SHADOW, alphaFunction, timePeriod);
- internalControl.OnCreateTransitions(animation, source, alphaFunction, timePeriod);
- }
-}
-
static Toolkit::Internal::Control::Impl* GetControlImplementation(Dali::Actor actor)
{
Dali::Toolkit::Control control = Toolkit::Control::DownCast(actor);
DALI_TOOLKIT_API Dali::Property GetVisualProperty(Control control, Dali::Property::Index index, Dali::Property::Key visualPropertyKey);
/**
- * @brief Retrieve visual/renderer property animation between this Control and source control.
- * Input animation must be created before this method called.
- * And the animations between this method created are added the input animation.
- * This method generates visual/renderer property animation but not creates Actor property animation.
- *
- * @param[in] control The control
- * @param[in] animation generated animation
- * @param[in] source source control of the animation.
- * @param[in] alphaFunction AlphaFunction of the animation
- * @param[in] timePeriod TimePeriod of the animation
- */
-DALI_TOOLKIT_API void CreateTransitions(Control control, Dali::Animation& animation, Dali::Toolkit::Control source, AlphaFunction alphaFunction, TimePeriod timePeriod);
-
-/**
* @brief The signal is emmited as a succession of "activate" signal send by accessibility client.
* @return The signal to connect to
*/
SET( devel_api_header_files
${devel_api_src_dir}/direction-enums.h
${devel_api_src_dir}/toolkit-property-index-ranges.h
+ ${devel_api_src_dir}/toolkit-action-index-ranges.h
)
SET( devel_api_accessibility-manager_header_files
${devel_api_src_dir}/visuals/animated-image-visual-actions-devel.h
${devel_api_src_dir}/visuals/animated-vector-image-visual-actions-devel.h
${devel_api_src_dir}/visuals/animated-vector-image-visual-signals-devel.h
- ${devel_api_src_dir}/visuals/arc-visual-actions-devel.h
${devel_api_src_dir}/visuals/arc-visual-properties-devel.h
- ${devel_api_src_dir}/visuals/color-visual-actions-devel.h
${devel_api_src_dir}/visuals/color-visual-properties-devel.h
${devel_api_src_dir}/visuals/image-visual-properties-devel.h
${devel_api_src_dir}/visuals/image-visual-actions-devel.h
${devel_api_src_dir}/visuals/text-visual-properties-devel.h
+ ${devel_api_src_dir}/visuals/visual-actions-devel.h
${devel_api_src_dir}/visuals/visual-properties-devel.h
)
return GetImpl(styleManager).GetConfigurations();
}
+void SetBrokenImageUrl(StyleManager styleManager, DevelStyleManager::BrokenImageType brokenImageType, const std::string& brokenImageUrl)
+{
+ return GetImpl(styleManager).SetBrokenImageUrl(brokenImageType, brokenImageUrl);
+}
+
+std::string GetBrokenImageUrl(StyleManager styleManager, DevelStyleManager::BrokenImageType brokenImageType)
+{
+ return GetImpl(styleManager).GetBrokenImageUrl(brokenImageType);
+}
+
+std::vector<std::string> GetBrokenImageUrlList(StyleManager styleManager)
+{
+ return GetImpl(styleManager).GetBrokenImageUrlList();
+}
+
+BrokenImageChangedSignalType& BrokenImageChangedSignal(StyleManager styleManager)
+{
+ return GetImpl(styleManager).BrokenImageChangedSignal();
+}
+
} // namespace DevelStyleManager
} // namespace Toolkit
namespace DevelStyleManager
{
/**
+ * @brief The Type of BrokenImage
+ */
+enum class BrokenImageType
+{
+ SMALL,
+ NORMAL,
+ LARGE
+};
+
+using BrokenImageChangedSignalType = Signal<void(StyleManager)>;
+
+/**
* @brief Gets all currently defined configurations.
*
* @pre The Builder has been initialized.
**/
DALI_TOOLKIT_API const Property::Map GetConfigurations(StyleManager styleManager);
+/**
+ * @brief Sets an image to be used when a visual has failed to correctly render
+ * @param[in] styleManager The instance of StyleManager
+ * @param[in] brokenImageType The type of broken image
+ * @param[in] brokenImageUrl The broken image url
+ */
+DALI_TOOLKIT_API void SetBrokenImageUrl(StyleManager styleManager, DevelStyleManager::BrokenImageType brokenImageType, const std::string& brokenImageUrl);
+
+/**
+ * @brief Gets an image to be used when a visual has failed to correctly render
+ * @param[in] styleManager The instance of StyleManager
+ * @param[in] brokenImageType BrokenImage type
+ */
+DALI_TOOLKIT_API std::string GetBrokenImageUrl(StyleManager styleManager, DevelStyleManager::BrokenImageType brokenImageType);
+
+/**
+ * @brief Get the Broken Image Url List
+ *
+ * This list is broken images stored in order of SMALL, NORMAL, and LARGE values except if the value is empty.
+ * This API just makes the list without comparing size, so the application must set a value that matches the size.
+ * @param styleManager The instance of StyleManager
+ * @return A List of Broken Image Url
+ */
+DALI_TOOLKIT_API std::vector<std::string> GetBrokenImageUrlList(StyleManager styleManager);
+
+/**
+ * @brief This signal is emitted when the URL of the broken image is set
+ *
+ * A callback of the following type may be connected:
+ * @code
+ * void YourCallbackName(StyleManager styleManager)
+ * @endcode
+ * @param styleManager The instance of StyleManager
+ * @return The signal to connect to
+ */
+DALI_TOOLKIT_API BrokenImageChangedSignalType& BrokenImageChangedSignal(StyleManager styleManager);
+
} // namespace DevelStyleManager
} // namespace Toolkit
--- /dev/null
+#ifndef DALI_TOOLKIT_ACTION_INDEX_RANGES_H
+#define DALI_TOOLKIT_ACTION_INDEX_RANGES_H
+
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <dali/public-api/object/property-index-ranges.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+/**
+ * @addtogroup dali_toolkit_controls
+ * @{
+ */
+
+/**
+ * @brief Enumeration for the start and end action ranges.
+ */
+enum ActionRanges
+{
+ VISUAL_ACTION_BASE_START_INDEX = 0, ///< Visual Action Base Start Index.
+ VISUAL_ACTION_BASE_END_INDEX = VISUAL_ACTION_BASE_START_INDEX + 100, ///< Visual Action Base End Index.
+ VISUAL_ACTION_START_INDEX = VISUAL_ACTION_BASE_END_INDEX + 1, ///< Visual Action Start Index.
+ VISUAL_ACTION_END_INDEX = VISUAL_ACTION_START_INDEX + 100000, ///< Visual Action End Index.
+};
+
+/**
+ * @}
+ */
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // DALI_TOOLKIT_ACTION_INDEX_RANGES_H
#define DALI_TOOLKIT_DEVEL_API_VISUALS_ANIMATED_IMAGE_VISUAL_ACTIONS_DEVEL_H
/*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* limitations under the License.
*
*/
+#include <dali-toolkit/devel-api/toolkit-action-index-ranges.h>
namespace Dali
{
*/
enum Type
{
- PLAY, ///< Play the animated GIF. This is also Default playback mode.
- PAUSE, ///< Pause the animated GIF.
- STOP, ///< Stop the animated GIF.
- JUMP_TO ///< Jump to the specified frame. Property::INTEGER value should be passed.
+ PLAY = VISUAL_ACTION_START_INDEX, ///< Play the animated GIF. This is also Default playback mode.
+ PAUSE, ///< Pause the animated GIF.
+ STOP, ///< Stop the animated GIF.
+ JUMP_TO ///< Jump to the specified frame. Property::INTEGER value should be passed.
};
} // namespace Action
* limitations under the License.
*
*/
+#include <dali-toolkit/devel-api/toolkit-action-index-ranges.h>
namespace Dali
{
*/
enum Type
{
- PLAY, ///< Play the animated vector image.
- PAUSE, ///< Pause the animated vector image.
- STOP, ///< Stop the animated vector image. This is also Default playback mode.
- JUMP_TO, ///< Jump to the specified frame. Property::INTEGER value should be passed.
- UPDATE_PROPERTY ///< Update the properties of the animated vector image.
+ PLAY = VISUAL_ACTION_START_INDEX, ///< Play the animated vector image.
+ PAUSE, ///< Pause the animated vector image.
+ STOP, ///< Stop the animated vector image. This is also Default playback mode.
+ JUMP_TO, ///< Jump to the specified frame. Property::INTEGER value should be passed.
};
} // namespace Action
+++ /dev/null
-#ifndef DALI_TOOLKIT_DEVEL_API_VISUALS_ARC_VISUAL_ACTIONS_DEVEL_H
-#define DALI_TOOLKIT_DEVEL_API_VISUALS_ARC_VISUAL_ACTIONS_DEVEL_H
-
-/*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-namespace Dali
-{
-namespace Toolkit
-{
-namespace DevelArcVisual
-{
-/**
- * @brief Actions that the arc visual can perform. These actions are called through the Visual::Base::DoAction API.
- */
-namespace Action
-{
-/**
- * @brief The available actions for this visual
- */
-enum Type
-{
- /**
- * @brief Update the properties of the visual.
- * @note DevelArcVisual::Property::THICKNESS, DevelArcVisual::Property::START_ANGLE and DevelArcVisual::Property::SWEEP_ANGLE can be updated.
- */
- UPDATE_PROPERTY = 0
-};
-
-} // namespace Action
-
-} // namespace DevelArcVisual
-
-} // namespace Toolkit
-
-} // namespace Dali
-
-#endif // DALI_TOOLKIT_DEVEL_API_VISUALS_ARC_VISUAL_ACTIONS_DEVEL_H
#define DALI_TOOLKIT_DEVEL_API_VISUALS_IMAGE_VISUAL_ACTIONS_DEVEL_H
/*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* limitations under the License.
*
*/
+#include <dali-toolkit/devel-api/toolkit-action-index-ranges.h>
namespace Dali
{
*/
enum Type
{
- RELOAD = 0 ///< Force reloading of the image, all visuals using this image will get the latest one.
+ RELOAD = VISUAL_ACTION_START_INDEX ///< Force reloading of the image, all visuals using this image will get the latest one.
};
} // namespace Action
-#ifndef DALI_TOOLKIT_DEVEL_API_VISUALS_COLOR_VISUAL_ACTIONS_DEVEL_H
-#define DALI_TOOLKIT_DEVEL_API_VISUALS_COLOR_VISUAL_ACTIONS_DEVEL_H
+#ifndef DALI_TOOLKIT_DEVEL_API_VISUALS_VISUAL_ACTIONS_DEVEL_H
+#define DALI_TOOLKIT_DEVEL_API_VISUALS_VISUAL_ACTIONS_DEVEL_H
/*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
*
*/
+// EXTERNAL INCLUDES
+#include <dali-toolkit/devel-api/toolkit-action-index-ranges.h>
+
namespace Dali
{
namespace Toolkit
{
-namespace DevelColorVisual
+namespace DevelVisual
{
+
/**
- * @brief Actions that the color visual can perform. These actions are called through the Visual::Base::DoAction API.
+ * @brief Actions that the visual can perform. These actions are called through the Visual::Base::DoAction API.
*/
namespace Action
{
/**
* @brief Update the properties of the visual.
*/
- UPDATE_PROPERTY = 0
+ UPDATE_PROPERTY = VISUAL_ACTION_BASE_START_INDEX
};
} // namespace Action
-} // namespace DevelColorVisual
+} // namespace DevelVisual
} // namespace Toolkit
} // namespace Dali
-#endif // DALI_TOOLKIT_DEVEL_API_VISUALS_COLOR_VISUAL_ACTIONS_DEVEL_H
+#endif // DALI_TOOLKIT_DEVEL_API_VISUALS_VISUAL_ACTIONS_DEVEL_H
}
}
-void CanvasView::ApplyRasterizedImage(PixelData rasterizedPixelData)
+void CanvasView::ApplyRasterizedImage(Texture rasterizedTexture)
{
- if(rasterizedPixelData)
+ if (rasterizedTexture && rasterizedTexture.GetWidth() != 0 && rasterizedTexture.GetHeight() != 0)
{
- auto rasterizedPixelDataWidth = rasterizedPixelData.GetWidth();
- auto rasterizedPixelDataHeight = rasterizedPixelData.GetHeight();
-
- if(rasterizedPixelDataWidth > 0 && rasterizedPixelDataHeight > 0)
+ if(!mTextureSet)
{
- if(!mTexture || mTexture.GetWidth() != rasterizedPixelDataWidth || mTexture.GetHeight() != rasterizedPixelDataHeight)
- {
- mTexture = Texture::New(TextureType::TEXTURE_2D, rasterizedPixelData.GetPixelFormat(), rasterizedPixelDataWidth, rasterizedPixelDataHeight);
- mTexture.Upload(rasterizedPixelData);
-
- if(!mTextureSet)
- {
- mTextureSet = TextureSet::New();
- Geometry geometry = VisualFactoryCache::CreateQuadGeometry();
- Shader shader = Shader::New(SHADER_CANVAS_VIEW_VERT, SHADER_CANVAS_VIEW_FRAG);
- Renderer renderer = Renderer::New(geometry, shader);
- renderer.SetTextures(mTextureSet);
- renderer.SetProperty(Renderer::Property::BLEND_PRE_MULTIPLIED_ALPHA, true);
-
- Actor actor = Self();
- if(actor)
- {
- actor.AddRenderer(renderer);
- }
- }
- mTextureSet.SetTexture(0, mTexture);
- }
- else
- {
- //Update texture
- mTexture.Upload(rasterizedPixelData);
- }
+ mTextureSet = TextureSet::New();
+ Geometry geometry = VisualFactoryCache::CreateQuadGeometry();
+ Shader shader = Shader::New(SHADER_CANVAS_VIEW_VERT, SHADER_CANVAS_VIEW_FRAG);
+ Renderer renderer = Renderer::New(geometry, shader);
+ renderer.SetTextures(mTextureSet);
+ renderer.SetProperty(Renderer::Property::BLEND_PRE_MULTIPLIED_ALPHA, true);
+ Self().AddRenderer(renderer);
}
+ mTextureSet.SetTexture(0, rasterizedTexture);
}
//If there are accumulated changes to CanvasRenderer during Rasterize, Rasterize once again.
/**
* @bried Apply the rasterized image to the canvas view
*
- * @param[in] rasterizedPixelData The pixel buffer with the rasterized pixels
+ * @param[in] rasterizedTexture The texture with the rasterized pixels
*/
- void ApplyRasterizedImage(PixelData rasterizedPixelData);
+ void ApplyRasterizedImage(Texture rasterizedTexture);
private:
CanvasView(const CanvasView&) = delete;
CanvasRendererRasterizingTask::CanvasRendererRasterizingTask(CanvasView* canvasView, CanvasRenderer canvasRenderer)
: mCanvasView(canvasView),
mCanvasRenderer(canvasRenderer),
- mPixelData(PixelData()),
- mBufferSize(0, 0)
+ mRasterizedTexture()
{
}
{
if(mCanvasRenderer && mCanvasRenderer.Rasterize())
{
- Devel::PixelBuffer pixbuf = mCanvasRenderer.GetPixelBuffer();
- auto width = pixbuf.GetWidth();
- auto height = pixbuf.GetHeight();
- if(width > 0 && height > 0)
- {
- mBufferSize.width = width;
- mBufferSize.height = height;
-
- mPixelData = Devel::PixelBuffer::Convert(pixbuf);
- return true;
- }
+ return true;
}
return false;
}
return mCanvasView.Get();
}
-PixelData CanvasRendererRasterizingTask::GetPixelData() const
-{
- return mPixelData;
-}
-
-Vector2 CanvasRendererRasterizingTask::GetBufferSize() const
+Texture CanvasRendererRasterizingTask::GetRasterizedTexture()
{
- return mBufferSize;
+ return mCanvasRenderer.GetRasterizedTexture();
}
CanvasViewRasterizeThread::CanvasViewRasterizeThread()
{
while(CanvasRendererRasterizingTaskPtr task = NextCompletedTask())
{
- RasterizationCompletedSignal().Emit(task->GetPixelData());
+ RasterizationCompletedSignal().Emit(task->GetRasterizedTexture()); // Here texture get
}
UnregisterProcessor();
#include <dali/devel-api/threading/thread.h>
#include <dali/integration-api/adaptor-framework/log-factory-interface.h>
#include <dali/public-api/common/intrusive-ptr.h>
-#include <dali/public-api/images/pixel-data.h>
#include <dali/public-api/object/ref-object.h>
#include <dali/public-api/rendering/texture-set.h>
#include <memory>
/**
* Get the rasterization result.
- * @return The pixel data with the rasterized pixels.
+ * @return The texture with the rasterized pixels.
*/
- PixelData GetPixelData() const;
-
- /**
- * Get size of rasterization result.
- * @return The size of the pixel data.
- */
- Vector2 GetBufferSize() const;
+ Texture GetRasterizedTexture();
private:
// Undefined
private:
CanvasViewPtr mCanvasView;
CanvasRenderer mCanvasRenderer;
- PixelData mPixelData;
- Vector2 mBufferSize;
+ Texture mRasterizedTexture;
};
/**
{
public:
/// @brief ApplyRasterizedImage Event signal type
- using RasterizationCompletedSignalType = Signal<void(PixelData)>;
+ using RasterizationCompletedSignalType = Signal<void(Texture)>;
public:
/**
#include <limits>
// INTERNAL INCLUDES
+#include <dali-toolkit/devel-api/visuals/visual-actions-devel.h>
#include <dali-toolkit/devel-api/asset-manager/asset-manager.h>
#include <dali-toolkit/devel-api/controls/control-depth-index-ranges.h>
#include <dali-toolkit/devel-api/controls/control-devel.h>
return Dali::Property(handle, Property::INVALID_INDEX);
}
-void Control::Impl::MakeVisualTransition(Dali::Animation& animation, Dali::Toolkit::Control source, Dali::Property::Index visualIndex, AlphaFunction alphaFunction, TimePeriod timePeriod)
+void Control::Impl::CreateTransitions(std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>>& sourceProperties,
+ std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>>& destinationProperties,
+ Dali::Toolkit::Control source, Dali::Toolkit::Control destination)
{
- Dali::Toolkit::Control sourceHandle = Dali::Toolkit::Control::DownCast(source);
- Property::Map sourceMap = sourceHandle.GetProperty<Property::Map>(visualIndex);
- Dali::Toolkit::Control destinationHandle = Dali::Toolkit::Control::DownCast(mControlImpl.Self());
- Property::Map destinationMap = destinationHandle.GetProperty<Property::Map>(visualIndex);
-
- Vector4 mixColor(1.0f, 1.0f, 1.0f, 1.0f);
- Vector4 cornerRadius(0.0f, 0.0f, 0.0f, 0.0f);
- float borderlineWidth(0.0f);
- Vector4 borderlineColor(0.0f, 0.0f, 0.0f, 1.0f);
- float borderlineOffset(0.0f);
-
- if(!destinationMap.Empty())
+ // Retrieves background properties to be transitioned.
+ Dali::Property::Map backgroundSourcePropertyMap, backgroundDestinationPropertyMap;
+ mControlImpl.MakeVisualTransition(backgroundSourcePropertyMap, backgroundDestinationPropertyMap, source, destination, Toolkit::Control::Property::BACKGROUND);
+ if(backgroundSourcePropertyMap.Count() > 0)
{
- static auto findValueVector4 = [](const Property::Map& map, Property::Index index, const Vector4& defaultValue = Vector4()) -> Vector4 {
- Property::Value* propertyValue = map.Find(index);
- if(propertyValue)
- {
- return propertyValue->Get<Vector4>();
- }
- return defaultValue;
- };
-
- static auto findValueFloat = [](const Property::Map& map, Property::Index index, const float& defaultValue = 0.0f) -> float {
- Property::Value* propertyValue = map.Find(index);
- if(propertyValue)
- {
- return propertyValue->Get<float>();
- }
- return defaultValue;
- };
-
- mixColor = findValueVector4(destinationMap, Dali::Toolkit::Visual::Property::MIX_COLOR, mixColor);
- cornerRadius = findValueVector4(destinationMap, Toolkit::DevelVisual::Property::CORNER_RADIUS, cornerRadius);
- borderlineWidth = findValueFloat(destinationMap, Toolkit::DevelVisual::Property::BORDERLINE_WIDTH, borderlineWidth);
- borderlineColor = findValueVector4(destinationMap, Toolkit::DevelVisual::Property::BORDERLINE_COLOR, borderlineColor);
- borderlineOffset = findValueFloat(destinationMap, Toolkit::DevelVisual::Property::BORDERLINE_OFFSET, borderlineOffset);
-
- if(sourceMap.Empty())
- {
- sourceMap.Insert(Toolkit::Visual::Property::TYPE, Toolkit::Visual::COLOR);
- sourceMap.Insert(Dali::Toolkit::Visual::Property::MIX_COLOR, Color::TRANSPARENT);
- sourceMap.Insert(Toolkit::DevelVisual::Property::CORNER_RADIUS, cornerRadius);
- sourceMap.Insert(Toolkit::DevelVisual::Property::BORDERLINE_WIDTH, borderlineWidth);
- sourceMap.Insert(Toolkit::DevelVisual::Property::BORDERLINE_COLOR, borderlineColor);
- sourceMap.Insert(Toolkit::DevelVisual::Property::BORDERLINE_OFFSET, borderlineOffset);
- }
-
- Vector4 sourceMixColor = findValueVector4(sourceMap, Dali::Toolkit::Visual::Property::MIX_COLOR, mixColor);
- Vector4 sourceCornerRadius = findValueVector4(sourceMap, Toolkit::DevelVisual::Property::CORNER_RADIUS, cornerRadius);
- float sourceBorderlineWidth = findValueFloat(sourceMap, Toolkit::DevelVisual::Property::BORDERLINE_WIDTH, borderlineWidth);
- Vector4 sourceBorderlineColor = findValueVector4(sourceMap, Toolkit::DevelVisual::Property::BORDERLINE_COLOR, borderlineColor);
- float sourceBorderlineOffset = findValueFloat(sourceMap, Toolkit::DevelVisual::Property::BORDERLINE_OFFSET, borderlineOffset);
-
- std::vector<Dali::Property> properties;
- std::vector<std::pair<Property::Value, Property::Value>> values;
-
- if(Vector3(sourceMixColor) != Vector3(mixColor))
- {
- properties.push_back(GetVisualProperty(visualIndex, Dali::Toolkit::Visual::Property::MIX_COLOR));
- values.push_back(std::make_pair(Vector3(sourceMixColor), Vector3(mixColor)));
- }
-
- if(std::abs(sourceMixColor.a - mixColor.a) > Math::MACHINE_EPSILON_1)
- {
- properties.push_back(GetVisualProperty(visualIndex, Dali::Toolkit::Visual::Property::OPACITY));
- values.push_back(std::make_pair(sourceMixColor.a, mixColor.a));
- }
-
- if(sourceCornerRadius != cornerRadius)
- {
- properties.push_back(GetVisualProperty(visualIndex, Dali::Toolkit::DevelVisual::Property::CORNER_RADIUS));
- values.push_back(std::make_pair(sourceCornerRadius, cornerRadius));
- }
+ sourceProperties.push_back(std::pair<Dali::Property::Index, Dali::Property::Map>(Toolkit::Control::Property::BACKGROUND, backgroundSourcePropertyMap));
+ destinationProperties.push_back(std::pair<Dali::Property::Index, Dali::Property::Map>(Toolkit::Control::Property::BACKGROUND, backgroundDestinationPropertyMap));
+ }
- if(sourceBorderlineWidth != borderlineWidth)
- {
- properties.push_back(GetVisualProperty(visualIndex, Dali::Toolkit::DevelVisual::Property::BORDERLINE_WIDTH));
- values.push_back(std::make_pair(sourceBorderlineWidth, borderlineWidth));
- }
+ // Retrieves shadow properties to be transitioned.
+ Dali::Property::Map shadowSourcePropertyMap, shadowDestinationPropertyMap;
+ mControlImpl.MakeVisualTransition(shadowSourcePropertyMap, shadowDestinationPropertyMap, source, destination, Toolkit::DevelControl::Property::SHADOW);
+ if(shadowSourcePropertyMap.Count() > 0)
+ {
+ sourceProperties.push_back(std::pair<Dali::Property::Index, Dali::Property::Map>(Toolkit::DevelControl::Property::SHADOW, shadowSourcePropertyMap));
+ destinationProperties.push_back(std::pair<Dali::Property::Index, Dali::Property::Map>(Toolkit::DevelControl::Property::SHADOW, shadowDestinationPropertyMap));
+ }
- if(sourceBorderlineColor != borderlineColor)
- {
- properties.push_back(GetVisualProperty(visualIndex, Dali::Toolkit::DevelVisual::Property::BORDERLINE_COLOR));
- values.push_back(std::make_pair(sourceBorderlineColor, borderlineColor));
- }
+ // Retrieves transition from inherited class.
+ mControlImpl.OnCreateTransitions(sourceProperties, destinationProperties, source, destination);
+}
- if(sourceBorderlineOffset != borderlineOffset)
+void Control::Impl::UpdateVisualProperties(const std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>>& properties)
+{
+ for(auto&& data : properties)
+ {
+ if(data.first == Toolkit::Control::Property::BACKGROUND)
{
- properties.push_back(GetVisualProperty(visualIndex, Dali::Toolkit::DevelVisual::Property::BORDERLINE_OFFSET));
- values.push_back(std::make_pair(sourceBorderlineOffset, borderlineOffset));
+ DoAction(Toolkit::Control::Property::BACKGROUND, DevelVisual::Action::UPDATE_PROPERTY, data.second);
}
-
- for(uint32_t i = 0; i < properties.size(); ++i)
+ else if(data.first == Toolkit::DevelControl::Property::SHADOW)
{
- if(timePeriod.delaySeconds > 0.0f)
- {
- Dali::KeyFrames initialKeyframes = Dali::KeyFrames::New();
- initialKeyframes.Add(0.0f, values[i].first);
- initialKeyframes.Add(1.0f, values[i].first);
- animation.AnimateBetween(properties[i], initialKeyframes, TimePeriod(timePeriod.delaySeconds));
- }
- Dali::KeyFrames keyframes = Dali::KeyFrames::New();
- keyframes.Add(0.0f, values[i].first);
- keyframes.Add(1.0f, values[i].second);
- animation.AnimateBetween(properties[i], keyframes, alphaFunction, timePeriod);
+ DoAction(Toolkit::DevelControl::Property::SHADOW, DevelVisual::Action::UPDATE_PROPERTY, data.second);
}
}
+ mControlImpl.OnUpdateVisualProperties(properties);
}
void Control::Impl::EmitResourceReadySignal()
Dali::Property GetVisualProperty(Dali::Property::Index index, Dali::Property::Key visualPropertyKey);
/**
- * @brief Make visual transition from source control to this control about specific Property::Index
- * If both of source and this control have Property::Index property, than create animation between them.
+ * @brief Retrieves source and destination visual properties for the Transition of this Control.
+ * The properties of this Control will be transitioned from the propeties of source Control to that of destination control.
+ * If a property value is different between source and destination Control,
+ * the property information of each Control will be included in sourceProperties and destinationProperties.
*
- * @param[in] animation Return animation from source to this control.
- * @param[in] source Source control to be used property animation.
- * @param[in] visualIndex Property::Index to make animation.
- * @param[in] alphaFunction alpha function of the animation.
- * @param[in] timePeriod time period of the animation.
+ * @param[out] sourceProperties Source property list to be applied on this Control.
+ * @param[out] destinationProperties Destination property list to be applied on this Control.
+ * @param[in] source Source control of the animation.
+ * @param[in] destination Destination control of the animation.
+ *
+ * @note This method do not handle Actor properties.
+ * And the size and order of the sourceProperties and destinationProperties must be synchronized.
+ *
+ * This method triggers Control::OnCreateTransition().
+ */
+ void CreateTransitions(std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>>& sourceProperties,
+ std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>>& destinationProperties,
+ Dali::Toolkit::Control source, Dali::Toolkit::Control destination);
+
+ /**
+ * @brief Update visual properties.
+ * @param[in] properties Property list to be used to update visual properties of this Control.
+ *
+ * @note This method triggers Control::OnUpdateVisualProperties().
*/
- void MakeVisualTransition(Dali::Animation& animation, Dali::Toolkit::Control source, Dali::Property::Index visualIndex, AlphaFunction alphaFunction, TimePeriod timePeriod);
+ void UpdateVisualProperties(const std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>>& properties);
/**
* @brief Gets the current control's accessible object.
// currently not called from code so compiler will optimize these away, kept here for future debugging
#define FLEX_CONTAINER_TAG "DALI Toolkit::FlexContainer "
-#define FC_LOG(fmt, args, ...) Debug::LogMessage(Debug::DebugInfo, FLEX_CONTAINER_TAG fmt, ##args)
+#define FC_LOG(fmt, args, ...) Debug::LogMessageWithFunctionLine(Debug::DebugInfo, FLEX_CONTAINER_TAG fmt, ##args)
// #define FLEX_CONTAINER_DEBUG 1
#if defined(FLEX_CONTAINER_DEBUG)
}
}
-void GlView::RegisterGlCallback(CallbackBase* initCallback, CallbackBase* renderFrameCallback, CallbackBase* terminateCallback)
+void GlView::RegisterGlCallbacks(CallbackBase* initCallback, CallbackBase* renderFrameCallback, CallbackBase* terminateCallback)
{
if(mRenderThread)
{
- mRenderThread->RegisterGlCallback(initCallback, renderFrameCallback, terminateCallback);
+ mRenderThread->RegisterGlCallbacks(initCallback, renderFrameCallback, terminateCallback);
}
}
GlView(Dali::Toolkit::GlView::ColorFormat colorFormat);
/**
- * @copydoc Dali::Toolkit::GlView::RegisterGlCallback()
+ * @copydoc Dali::Toolkit::GlView::RegisterGlCallbacks()
*/
- void RegisterGlCallback(CallbackBase* initCallback, CallbackBase* renderFrameCallback, CallbackBase* terminateCallback);
+ void RegisterGlCallbacks(CallbackBase* initCallback, CallbackBase* renderFrameCallback, CallbackBase* terminateCallback);
/**
* @copydoc Dali::Toolkit::GlView::SetResizeCallback()
}
}
-void GlViewRenderThread::RegisterGlCallback(CallbackBase* initCallback, CallbackBase* renderFrameCallback, CallbackBase* terminateCallback)
+void GlViewRenderThread::RegisterGlCallbacks(CallbackBase* initCallback, CallbackBase* renderFrameCallback, CallbackBase* terminateCallback)
{
if(!mGlInitCallback && !mGlRenderFrameCallback && !mGlTerminateCallback)
{
virtual ~GlViewRenderThread();
/**
- * @copydoc Dali::Toolkit::GlView::RegisterGlCallback()
+ * @copydoc Dali::Toolkit::GlView::RegisterGlCallbacks()
*/
- void RegisterGlCallback(CallbackBase* initCallback, CallbackBase* renderFrameCallback, CallbackBase* terminateCallback);
+ void RegisterGlCallbacks(CallbackBase* initCallback, CallbackBase* renderFrameCallback, CallbackBase* terminateCallback);
/**
* @copydoc Dali::Toolkit::GlView::SetResizeCallback()
#include <dali/public-api/object/type-registry.h>
// INTERNAL INCLUDES
+#include <dali-toolkit/devel-api/visuals/visual-actions-devel.h>
#include <dali-toolkit/devel-api/controls/control-devel.h>
#include <dali-toolkit/devel-api/visual-factory/visual-factory.h>
#include <dali-toolkit/internal/controls/control/control-data-impl.h>
}
}
-void ImageView::OnCreateTransitions(Dali::Animation& animation, Dali::Toolkit::Control source, AlphaFunction alphaFunction, TimePeriod timePeriod)
+void ImageView::OnCreateTransitions(std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>>& sourceProperties,
+ std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>>& destinationProperties,
+ Dali::Toolkit::Control source,
+ Dali::Toolkit::Control destination)
{
- Dali::Toolkit::ImageView destinationHandle = Toolkit::ImageView(GetOwner());
- Toolkit::Visual::Base destinationVisual = DevelControl::GetVisual(GetImplementation(destinationHandle), Toolkit::ImageView::Property::IMAGE);
- Property::Map destinationMap;
-
- if(!destinationVisual)
- {
- return;
- }
-
- destinationVisual.CreatePropertyMap(destinationMap);
-
- static auto findValueVector4 = [](const Property::Map& map, Property::Index index, const Vector4& defaultValue = Vector4()) -> Vector4 {
- Property::Value* propertyValue = map.Find(index);
- if(propertyValue)
- {
- return propertyValue->Get<Vector4>();
- }
- return defaultValue;
- };
-
- static auto findValueFloat = [](const Property::Map& map, Property::Index index, const float& defaultValue = 0.0f) -> float {
- Property::Value* propertyValue = map.Find(index);
- if(propertyValue)
- {
- return propertyValue->Get<float>();
- }
- return defaultValue;
- };
-
- Vector4 sourceMixColor(0.0f, 0.0f, 0.0f, 0.0f);
- Vector4 sourceCornerRadius(0.0f, 0.0f, 0.0f, 0.0f);
- float sourceBorderlineWidth(0.0f);
- Vector4 sourceBorderlineColor(0.0f, 0.0f, 0.0f, 1.0f);
- float sourceBorderlineOffset(0.0f);
- Vector4 destinationMixColor = findValueVector4(destinationMap, Dali::Toolkit::Visual::Property::MIX_COLOR, sourceMixColor);
- Vector4 destinationCornerRadius = findValueVector4(destinationMap, Toolkit::DevelVisual::Property::CORNER_RADIUS, sourceCornerRadius);
- float destinationBorderlineWidth = findValueFloat(destinationMap, Toolkit::DevelVisual::Property::BORDERLINE_WIDTH, sourceBorderlineWidth);
- Vector4 destinationBorderlineColor = findValueVector4(destinationMap, Toolkit::DevelVisual::Property::BORDERLINE_COLOR, sourceBorderlineColor);
- float destinationBorderlineOffset = findValueFloat(destinationMap, Toolkit::DevelVisual::Property::BORDERLINE_OFFSET, sourceBorderlineOffset);
-
- Dali::Toolkit::ImageView sourceHandle = Dali::Toolkit::ImageView::DownCast(source);
- Toolkit::Visual::Base sourceVisual;
- Property::Map sourceMap;
-
- if(sourceHandle)
- {
- sourceVisual = DevelControl::GetVisual(GetImplementation(sourceHandle), Toolkit::ImageView::Property::IMAGE);
- }
-
- if(sourceVisual)
+ // Retrieves image properties to be transitioned.
+ Dali::Property::Map imageSourcePropertyMap, imageDestinationPropertyMap;
+ MakeVisualTransition(imageSourcePropertyMap, imageDestinationPropertyMap, source, destination, Toolkit::ImageView::Property::IMAGE);
+ if(imageSourcePropertyMap.Count() > 0)
{
- sourceVisual.CreatePropertyMap(sourceMap);
- sourceMixColor = findValueVector4(sourceMap, Dali::Toolkit::Visual::Property::MIX_COLOR, sourceMixColor);
- sourceCornerRadius = findValueVector4(sourceMap, Toolkit::DevelVisual::Property::CORNER_RADIUS, sourceCornerRadius);
- sourceBorderlineWidth = findValueFloat(sourceMap, Toolkit::DevelVisual::Property::BORDERLINE_WIDTH, sourceBorderlineWidth);
- sourceBorderlineColor = findValueVector4(sourceMap, Toolkit::DevelVisual::Property::BORDERLINE_COLOR, sourceBorderlineColor);
- sourceBorderlineOffset = findValueFloat(sourceMap, Toolkit::DevelVisual::Property::BORDERLINE_OFFSET, sourceBorderlineOffset);
+ sourceProperties.push_back(std::pair<Dali::Property::Index, Dali::Property::Map>(Toolkit::ImageView::Property::IMAGE, imageSourcePropertyMap));
+ destinationProperties.push_back(std::pair<Dali::Property::Index, Dali::Property::Map>(Toolkit::ImageView::Property::IMAGE, imageDestinationPropertyMap));
}
+}
- std::vector<Dali::Property> properties;
- std::vector<std::pair<Property::Value, Property::Value>> values;
-
- if(Vector3(sourceMixColor) != Vector3(destinationMixColor))
- {
- properties.push_back(DevelControl::GetVisualProperty(destinationHandle, Toolkit::ImageView::Property::IMAGE, Toolkit::Visual::Property::MIX_COLOR));
- values.push_back(std::make_pair(Vector3(sourceMixColor), Vector3(destinationMixColor)));
- }
- if(std::abs(sourceMixColor.a - destinationMixColor.a) > Math::MACHINE_EPSILON_1)
- {
- properties.push_back(DevelControl::GetVisualProperty(destinationHandle, Toolkit::ImageView::Property::IMAGE, Toolkit::Visual::Property::OPACITY));
- values.push_back(std::make_pair(sourceMixColor.a, destinationMixColor.a));
- }
- if(sourceCornerRadius != destinationCornerRadius)
- {
- properties.push_back(DevelControl::GetVisualProperty(destinationHandle, Toolkit::ImageView::Property::IMAGE, Toolkit::DevelVisual::Property::CORNER_RADIUS));
- values.push_back(std::make_pair(sourceCornerRadius, destinationCornerRadius));
- }
- if(sourceBorderlineWidth != destinationBorderlineWidth)
- {
- properties.push_back(DevelControl::GetVisualProperty(destinationHandle, Toolkit::ImageView::Property::IMAGE, Toolkit::DevelVisual::Property::BORDERLINE_WIDTH));
- values.push_back(std::make_pair(sourceBorderlineWidth, destinationBorderlineWidth));
- }
- if(sourceBorderlineColor != destinationBorderlineColor)
- {
- properties.push_back(DevelControl::GetVisualProperty(destinationHandle, Toolkit::ImageView::Property::IMAGE, Toolkit::DevelVisual::Property::BORDERLINE_COLOR));
- values.push_back(std::make_pair(sourceBorderlineColor, destinationBorderlineColor));
- }
- if(sourceBorderlineOffset != destinationBorderlineOffset)
+void ImageView::OnUpdateVisualProperties(const std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>>& properties)
+{
+ Toolkit::Visual::Base visual = DevelControl::GetVisual(*this, Toolkit::ImageView::Property::IMAGE);
+ if(visual)
{
- properties.push_back(DevelControl::GetVisualProperty(destinationHandle, Toolkit::ImageView::Property::IMAGE, Toolkit::DevelVisual::Property::BORDERLINE_OFFSET));
- values.push_back(std::make_pair(sourceBorderlineOffset, destinationBorderlineOffset));
- }
+ Dali::Toolkit::Control handle(GetOwner());
- for(uint32_t i = 0; i < properties.size(); ++i)
- {
- if(timePeriod.delaySeconds > 0.0f)
+ for(auto&& data : properties)
{
- Dali::KeyFrames initialKeyframes = Dali::KeyFrames::New();
- initialKeyframes.Add(0.0f, values[i].first);
- initialKeyframes.Add(1.0f, values[i].first);
- animation.AnimateBetween(properties[i], initialKeyframes, TimePeriod(timePeriod.delaySeconds));
+ if(data.first == Toolkit::ImageView::Property::IMAGE)
+ {
+ DevelControl::DoAction(handle, Toolkit::ImageView::Property::IMAGE, DevelVisual::Action::UPDATE_PROPERTY, data.second);
+ break;
+ }
}
- Dali::KeyFrames keyframes = Dali::KeyFrames::New();
- keyframes.Add(0.0f, values[i].first);
- keyframes.Add(1.0f, values[i].second);
- animation.AnimateBetween(properties[i], keyframes, alphaFunction, timePeriod);
}
}
/**
* @copydoc Toolkit::Control::OnCreateTransitions()
*/
- virtual void OnCreateTransitions(Dali::Animation& animation, Dali::Toolkit::Control source, AlphaFunction alphaFunction, TimePeriod timePeriod) override;
+ virtual void OnCreateTransitions(std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>>& sourceProperties,
+ std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>>& destinationProperties,
+ Dali::Toolkit::Control source,
+ Dali::Toolkit::Control destination) override;
+
+ /**
+ * @copydoc Toolkit::Control::OnUpdateVisualProperties()
+ */
+ virtual void OnUpdateVisualProperties(const std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>>& properties) override;
private:
/**
--- /dev/null
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-impl-constraints.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/public-api/controls/scrollable/scroll-view/scroll-view-constraints.h>
+#include <dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-impl.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Internal
+{
+namespace
+{
+
+float FinalDefaultAlphaFunction(float offset)
+{
+ return offset * 0.5f;
+}
+
+/**
+ * Internal Relative position Constraint
+ * Generates the relative position value of the scroll view
+ * based on the absolute position, and it's relation to the
+ * scroll domain. This is a value from 0.0f to 1.0f in each
+ * scroll position axis.
+ */
+void InternalRelativePositionConstraint(Vector2& relativePosition, const PropertyInputContainer& inputs)
+{
+ Vector2 position = -inputs[0]->GetVector2();
+ const Vector2& min = inputs[1]->GetVector2();
+ const Vector2& max = inputs[2]->GetVector2();
+ const Vector3& size = inputs[3]->GetVector3();
+
+ position.x = WrapInDomain(position.x, min.x, max.x);
+ position.y = WrapInDomain(position.y, min.y, max.y);
+
+ Vector2 domainSize = (max - min) - size.GetVectorXY();
+
+ relativePosition.x = domainSize.x > Math::MACHINE_EPSILON_1 ? fabsf((position.x - min.x) / domainSize.x) : 0.0f;
+ relativePosition.y = domainSize.y > Math::MACHINE_EPSILON_1 ? fabsf((position.y - min.y) / domainSize.y) : 0.0f;
+}
+
+/**
+ * Internal scroll domain Constraint
+ * Generates the scroll domain of the scroll view.
+ */
+void InternalScrollDomainConstraint(Vector2& scrollDomain, const PropertyInputContainer& inputs)
+{
+ const Vector2& min = inputs[0]->GetVector2();
+ const Vector2& max = inputs[1]->GetVector2();
+ const Vector3& size = inputs[2]->GetVector3();
+
+ scrollDomain = (max - min) - size.GetVectorXY();
+}
+
+/**
+ * Internal maximum scroll position Constraint
+ * Generates the maximum scroll position of the scroll view.
+ */
+void InternalPrePositionMaxConstraint(Vector2& scrollMax, const PropertyInputContainer& inputs)
+{
+ const Vector2& max = inputs[0]->GetVector2();
+ const Vector3& size = inputs[1]->GetVector3();
+
+ scrollMax = max - size.GetVectorXY();
+}
+
+/**
+ * Internal Pre-Position Property Constraint.
+ *
+ * Generates position property based on current position + gesture displacement.
+ * Or generates position property based on positionX/Y.
+ * Note: This is the position prior to any clamping at scroll boundaries.
+ */
+struct InternalPrePositionConstraint
+{
+ InternalPrePositionConstraint(const Vector2& initialPanPosition,
+ const Vector2& initialPanMask,
+ bool axisAutoLock,
+ float axisAutoLockGradient,
+ ScrollView::LockAxis initialLockAxis,
+ const Vector2& maxOvershoot,
+ const RulerPtr& rulerX,
+ const RulerPtr& rulerY)
+ : mLocalStart(initialPanPosition),
+ mInitialPanMask(initialPanMask),
+ mMaxOvershoot(maxOvershoot),
+ mAxisAutoLockGradient(axisAutoLockGradient),
+ mLockAxis(initialLockAxis),
+ mAxisAutoLock(axisAutoLock),
+ mWasPanning(false)
+ {
+ const RulerDomain& rulerDomainX = rulerX->GetDomain();
+ const RulerDomain& rulerDomainY = rulerY->GetDomain();
+ mDomainMin = Vector2(rulerDomainX.min, -rulerDomainY.min);
+ mDomainMax = Vector2(-rulerDomainX.max, -rulerDomainY.max);
+ mClampX = rulerDomainX.enabled;
+ mClampY = rulerDomainY.enabled;
+ mFixedRulerX = rulerX->GetType() == Ruler::FIXED;
+ mFixedRulerY = rulerY->GetType() == Ruler::FIXED;
+ }
+
+ void operator()(Vector2& scrollPostPosition, const PropertyInputContainer& inputs)
+ {
+ const Vector2& panPosition = inputs[0]->GetVector2();
+ const bool& inGesture = inputs[1]->GetBoolean();
+
+ // First check if we are within a gesture.
+ // The ScrollView may have received a start gesture from ::OnPan()
+ // while the finish gesture is received now in this constraint.
+ // This gesture must then be rejected as the value will be "old".
+ // Typically the last value from the end of the last gesture.
+ // If we are rejecting the gesture, we simply don't modify the constraint target.
+ if(inGesture)
+ {
+ if(!mWasPanning)
+ {
+ mPrePosition = scrollPostPosition;
+ mStartPosition = mPrePosition;
+ mCurrentPanMask = mInitialPanMask;
+ mWasPanning = true;
+ }
+
+ // Calculate Deltas...
+ const Vector2& currentPosition = panPosition;
+ Vector2 panDelta(currentPosition - mLocalStart);
+
+ // Axis Auto Lock - locks the panning to the horizontal or vertical axis if the pan
+ // appears mostly horizontal or mostly vertical respectively...
+ if(mAxisAutoLock)
+ {
+ mLockAxis = GetLockAxis(panDelta, mLockAxis, mAxisAutoLockGradient);
+ if(mLockAxis == ScrollView::LockVertical)
+ {
+ mCurrentPanMask.y = 0.0f;
+ }
+ else if(mLockAxis == ScrollView::LockHorizontal)
+ {
+ mCurrentPanMask.x = 0.0f;
+ }
+ }
+
+ // Restrict deltas based on ruler enable/disable and axis-lock state...
+ panDelta *= mCurrentPanMask;
+
+ // Perform Position transform based on input deltas...
+ scrollPostPosition = mPrePosition;
+ scrollPostPosition += panDelta;
+
+ // if no wrapping then clamp preposition to maximum overshoot amount
+ const Vector3& size = inputs[2]->GetVector3();
+ if(mClampX)
+ {
+ float newXPosition = Clamp(scrollPostPosition.x, (mDomainMax.x + size.x) - mMaxOvershoot.x, mDomainMin.x + mMaxOvershoot.x);
+ if((newXPosition < scrollPostPosition.x - Math::MACHINE_EPSILON_1) || (newXPosition > scrollPostPosition.x + Math::MACHINE_EPSILON_1))
+ {
+ mPrePosition.x = newXPosition;
+ mLocalStart.x = panPosition.x;
+ }
+ scrollPostPosition.x = newXPosition;
+ }
+ if(mClampY)
+ {
+ float newYPosition = Clamp(scrollPostPosition.y, (mDomainMax.y + size.y) - mMaxOvershoot.y, mDomainMin.y + mMaxOvershoot.y);
+ if((newYPosition < scrollPostPosition.y - Math::MACHINE_EPSILON_1) || (newYPosition > scrollPostPosition.y + Math::MACHINE_EPSILON_1))
+ {
+ mPrePosition.y = newYPosition;
+ mLocalStart.y = panPosition.y;
+ }
+ scrollPostPosition.y = newYPosition;
+ }
+
+ // If we are using a fixed ruler in a particular axis, limit the maximum pages scrolled on that axis.
+ if(mFixedRulerX || mFixedRulerY)
+ {
+ // Here we limit the maximum amount that can be moved from the starting position of the gesture to one page.
+ // We do this only if we have a fixed ruler (on that axis) and the mode is enabled.
+ // Note: 1.0f is subtracted to keep the value within one page size (otherwise we stray on to the page after).
+ // Note: A further 1.0f is subtracted to handle a compensation that happens later within the flick handling code in SnapWithVelocity().
+ // When a flick is completed, an adjustment of 1.0f is sometimes made to allow for the scenario where:
+ // A flick finishes before the update thread has advanced the scroll position past the previous snap point.
+ Vector2 viewPageSizeLimit(size.x - (1.0f + 1.0f), size.y - (1.0f - 1.0f));
+ Vector2 minPosition(mStartPosition.x - viewPageSizeLimit.x, mStartPosition.y - viewPageSizeLimit.y);
+ Vector2 maxPosition(mStartPosition.x + viewPageSizeLimit.x, mStartPosition.y + viewPageSizeLimit.y);
+
+ if(mFixedRulerX)
+ {
+ scrollPostPosition.x = Clamp(scrollPostPosition.x, minPosition.x, maxPosition.x);
+ }
+ if(mFixedRulerY)
+ {
+ scrollPostPosition.y = Clamp(scrollPostPosition.y, minPosition.y, maxPosition.y);
+ }
+ }
+ }
+ }
+
+ Vector2 mPrePosition;
+ Vector2 mLocalStart;
+ Vector2 mStartPosition; ///< The start position of the gesture - used to limit scroll amount (not modified by clamping).
+ Vector2 mInitialPanMask; ///< Initial pan mask (based on ruler settings).
+ Vector2 mCurrentPanMask; ///< Current pan mask that can be altered by axis lock mode.
+ Vector2 mDomainMin;
+ Vector2 mDomainMax;
+ Vector2 mMaxOvershoot;
+
+ float mAxisAutoLockGradient; ///< Set by ScrollView
+ ScrollView::LockAxis mLockAxis;
+
+ bool mAxisAutoLock : 1; ///< Set by ScrollView
+ bool mWasPanning : 1;
+ bool mClampX : 1;
+ bool mClampY : 1;
+ bool mFixedRulerX : 1;
+ bool mFixedRulerY : 1;
+};
+
+/**
+ * Internal Position Property Constraint.
+ *
+ * Generates position property based on pre-position
+ * Note: This is the position after clamping.
+ * (uses result of InternalPrePositionConstraint)
+ */
+struct InternalPositionConstraint
+{
+ InternalPositionConstraint(const RulerDomain& domainX, const RulerDomain& domainY, bool wrap)
+ : mDomainMin(-domainX.min, -domainY.min),
+ mDomainMax(-domainX.max, -domainY.max),
+ mClampX(domainX.enabled),
+ mClampY(domainY.enabled),
+ mWrap(wrap)
+ {
+ }
+
+ void operator()(Vector2& position, const PropertyInputContainer& inputs)
+ {
+ position = inputs[0]->GetVector2();
+ const Vector2& size = inputs[3]->GetVector3().GetVectorXY();
+ const Vector2& min = inputs[1]->GetVector2();
+ const Vector2& max = inputs[2]->GetVector2();
+
+ if(mWrap)
+ {
+ position.x = -WrapInDomain(-position.x, min.x, max.x);
+ position.y = -WrapInDomain(-position.y, min.y, max.y);
+ }
+ else
+ {
+ // clamp post position to domain
+ position.x = mClampX ? Clamp(position.x, mDomainMax.x + size.x, mDomainMin.x) : position.x;
+ position.y = mClampY ? Clamp(position.y, mDomainMax.y + size.y, mDomainMin.y) : position.y;
+ }
+ }
+
+ Vector2 mDomainMin;
+ Vector2 mDomainMax;
+ bool mClampX;
+ bool mClampY;
+ bool mWrap;
+};
+
+/**
+ * This constraint updates the X overshoot property using the difference
+ * SCROLL_PRE_POSITION.x and SCROLL_POSITION.x, returning a relative value between 0.0f and 1.0f
+ */
+struct OvershootXConstraint
+{
+ OvershootXConstraint(float maxOvershoot)
+ : mMaxOvershoot(maxOvershoot)
+ {
+ }
+
+ void operator()(float& current, const PropertyInputContainer& inputs)
+ {
+ if(inputs[2]->GetBoolean())
+ {
+ const Vector2& scrollPrePosition = inputs[0]->GetVector2();
+ const Vector2& scrollPostPosition = inputs[1]->GetVector2();
+ float newOvershoot = scrollPrePosition.x - scrollPostPosition.x;
+ current = (newOvershoot > 0.0f ? std::min(newOvershoot, mMaxOvershoot) : std::max(newOvershoot, -mMaxOvershoot)) / mMaxOvershoot;
+ }
+ else
+ {
+ current = 0.0f;
+ }
+ }
+
+ float mMaxOvershoot;
+};
+
+/**
+ * This constraint updates the Y overshoot property using the difference
+ * SCROLL_PRE_POSITION.y and SCROLL_POSITION.y, returning a relative value between 0.0f and 1.0f
+ */
+struct OvershootYConstraint
+{
+ OvershootYConstraint(float maxOvershoot)
+ : mMaxOvershoot(maxOvershoot)
+ {
+ }
+
+ void operator()(float& current, const PropertyInputContainer& inputs)
+ {
+ if(inputs[2]->GetBoolean())
+ {
+ const Vector2& scrollPrePosition = inputs[0]->GetVector2();
+ const Vector2& scrollPostPosition = inputs[1]->GetVector2();
+ float newOvershoot = scrollPrePosition.y - scrollPostPosition.y;
+ current = (newOvershoot > 0.0f ? std::min(newOvershoot, mMaxOvershoot) : std::max(newOvershoot, -mMaxOvershoot)) / mMaxOvershoot;
+ }
+ else
+ {
+ current = 0.0f;
+ }
+ }
+
+ float mMaxOvershoot;
+};
+
+/**
+ * Internal Position-Delta Property Constraint.
+ *
+ * Generates position-delta property based on scroll-position + scroll-offset properties.
+ */
+void InternalPositionDeltaConstraint(Vector2& current, const PropertyInputContainer& inputs)
+{
+ const Vector2& scrollPosition = inputs[0]->GetVector2();
+ const Vector2& scrollOffset = inputs[1]->GetVector2();
+
+ current = scrollPosition + scrollOffset;
+}
+
+/**
+ * Internal Final Position Constraint
+ * The position of content is:
+ * of scroll-position + f(scroll-overshoot)
+ * where f(...) function defines how overshoot
+ * should affect final-position.
+ */
+struct InternalFinalConstraint
+{
+ InternalFinalConstraint(AlphaFunctionPrototype functionX,
+ AlphaFunctionPrototype functionY)
+ : mFunctionX(functionX),
+ mFunctionY(functionY)
+ {
+ }
+
+ void operator()(Vector2& current, const PropertyInputContainer& inputs)
+ {
+ const float& overshootx = inputs[1]->GetFloat();
+ const float& overshooty = inputs[2]->GetFloat();
+ Vector2 offset(mFunctionX(overshootx),
+ mFunctionY(overshooty));
+
+ current = inputs[0]->GetVector2() - offset;
+ }
+
+ AlphaFunctionPrototype mFunctionX;
+ AlphaFunctionPrototype mFunctionY;
+};
+
+} // namespace
+
+void ScrollViewConstraints::UpdateMainInternalConstraint(ScrollView& scrollView)
+{
+ // TODO: Only update the constraints which have changed, rather than remove all and add all again.
+ // Requires a dali-core ApplyConstraintAt, or a ReplaceConstraint. The former is probably more flexible.
+ Actor scrollViewActor = scrollView.Self();
+ PanGestureDetector detector(scrollView.GetPanGestureDetector());
+
+ if(mScrollMainInternalPositionConstraint)
+ {
+ mScrollMainInternalPositionConstraint.Remove();
+ mScrollMainInternalDeltaConstraint.Remove();
+ mScrollMainInternalFinalConstraint.Remove();
+ mScrollMainInternalRelativeConstraint.Remove();
+ mScrollMainInternalDomainConstraint.Remove();
+ mScrollMainInternalPrePositionMaxConstraint.Remove();
+ }
+ if(mScrollMainInternalPrePositionConstraint)
+ {
+ mScrollMainInternalPrePositionConstraint.Remove();
+ }
+
+ // TODO: It's probably better to use a local displacement value as this will give a displacement when scrolling just commences
+ // but we need to make sure than the gesture system gives displacement since last frame (60Hz), not displacement since last touch event (90Hz).
+
+ // 1. First calculate the pre-position (this is the scroll position if no clamping has taken place)
+ Vector2 initialPanMask = Vector2(scrollView.mRulerX->IsEnabled() ? 1.0f : 0.0f, scrollView.mRulerY->IsEnabled() ? 1.0f : 0.0f);
+
+ if(scrollView.mLockAxis == ScrollView::LockVertical)
+ {
+ initialPanMask.y = 0.0f;
+ }
+ else if(scrollView.mLockAxis == ScrollView::LockHorizontal)
+ {
+ initialPanMask.x = 0.0f;
+ }
+
+ if(scrollView.mPanning)
+ {
+ mScrollMainInternalPrePositionConstraint = Constraint::New<Vector2>(scrollViewActor,
+ Toolkit::ScrollView::Property::SCROLL_PRE_POSITION,
+ InternalPrePositionConstraint(scrollView.mPanStartPosition,
+ initialPanMask,
+ scrollView.mAxisAutoLock,
+ scrollView.mAxisAutoLockGradient,
+ scrollView.mLockAxis,
+ scrollView.mMaxOvershoot,
+ scrollView.mRulerX,
+ scrollView.mRulerY));
+ mScrollMainInternalPrePositionConstraint.AddSource(Source(detector, PanGestureDetector::Property::LOCAL_POSITION));
+ mScrollMainInternalPrePositionConstraint.AddSource(Source(detector, PanGestureDetector::Property::PANNING));
+ mScrollMainInternalPrePositionConstraint.AddSource(Source(scrollViewActor, Actor::Property::SIZE));
+ mScrollMainInternalPrePositionConstraint.Apply();
+ }
+
+ // 2. Second calculate the clamped position (actual position)
+ mScrollMainInternalPositionConstraint = Constraint::New<Vector2>(scrollViewActor,
+ Toolkit::ScrollView::Property::SCROLL_POSITION,
+ InternalPositionConstraint(scrollView.mRulerX->GetDomain(),
+ scrollView.mRulerY->GetDomain(),
+ scrollView.mWrapMode));
+ mScrollMainInternalPositionConstraint.AddSource(LocalSource(Toolkit::ScrollView::Property::SCROLL_PRE_POSITION));
+ mScrollMainInternalPositionConstraint.AddSource(LocalSource(Toolkit::Scrollable::Property::SCROLL_POSITION_MIN));
+ mScrollMainInternalPositionConstraint.AddSource(LocalSource(Toolkit::Scrollable::Property::SCROLL_POSITION_MAX));
+ mScrollMainInternalPositionConstraint.AddSource(Source(scrollViewActor, Actor::Property::SIZE));
+ mScrollMainInternalPositionConstraint.Apply();
+
+ mScrollMainInternalDeltaConstraint = Constraint::New<Vector2>(scrollViewActor, Toolkit::ScrollView::Property::SCROLL_POSITION_DELTA, InternalPositionDeltaConstraint);
+ mScrollMainInternalDeltaConstraint.AddSource(LocalSource(Toolkit::ScrollView::Property::SCROLL_POSITION));
+ mScrollMainInternalDeltaConstraint.AddSource(LocalSource(Toolkit::ScrollView::Property::SCROLL_DOMAIN_OFFSET));
+ mScrollMainInternalDeltaConstraint.Apply();
+
+ mScrollMainInternalFinalConstraint = Constraint::New<Vector2>(scrollViewActor, Toolkit::ScrollView::Property::SCROLL_FINAL, InternalFinalConstraint(FinalDefaultAlphaFunction, FinalDefaultAlphaFunction));
+ mScrollMainInternalFinalConstraint.AddSource(LocalSource(Toolkit::ScrollView::Property::SCROLL_POSITION));
+ mScrollMainInternalFinalConstraint.AddSource(LocalSource(Toolkit::ScrollView::Property::OVERSHOOT_X));
+ mScrollMainInternalFinalConstraint.AddSource(LocalSource(Toolkit::ScrollView::Property::OVERSHOOT_Y));
+ mScrollMainInternalFinalConstraint.Apply();
+
+ mScrollMainInternalRelativeConstraint = Constraint::New<Vector2>(scrollViewActor, Toolkit::Scrollable::Property::SCROLL_RELATIVE_POSITION, InternalRelativePositionConstraint);
+ mScrollMainInternalRelativeConstraint.AddSource(LocalSource(Toolkit::ScrollView::Property::SCROLL_POSITION));
+ mScrollMainInternalRelativeConstraint.AddSource(LocalSource(Toolkit::Scrollable::Property::SCROLL_POSITION_MIN));
+ mScrollMainInternalRelativeConstraint.AddSource(LocalSource(Toolkit::Scrollable::Property::SCROLL_POSITION_MAX));
+ mScrollMainInternalRelativeConstraint.AddSource(LocalSource(Actor::Property::SIZE));
+ mScrollMainInternalRelativeConstraint.Apply();
+
+ mScrollMainInternalDomainConstraint = Constraint::New<Vector2>(scrollViewActor, Toolkit::ScrollView::Property::SCROLL_DOMAIN_SIZE, InternalScrollDomainConstraint);
+ mScrollMainInternalDomainConstraint.AddSource(LocalSource(Toolkit::Scrollable::Property::SCROLL_POSITION_MIN));
+ mScrollMainInternalDomainConstraint.AddSource(LocalSource(Toolkit::Scrollable::Property::SCROLL_POSITION_MAX));
+ mScrollMainInternalDomainConstraint.AddSource(LocalSource(Actor::Property::SIZE));
+ mScrollMainInternalDomainConstraint.Apply();
+
+ mScrollMainInternalPrePositionMaxConstraint = Constraint::New<Vector2>(scrollViewActor, Toolkit::ScrollView::Property::SCROLL_PRE_POSITION_MAX, InternalPrePositionMaxConstraint);
+ mScrollMainInternalPrePositionMaxConstraint.AddSource(LocalSource(Toolkit::Scrollable::Property::SCROLL_POSITION_MAX));
+ mScrollMainInternalPrePositionMaxConstraint.AddSource(LocalSource(Actor::Property::SIZE));
+ mScrollMainInternalPrePositionMaxConstraint.Apply();
+
+ // When panning we want to make sure overshoot values are affected by pre position and post position
+ SetOvershootConstraintsEnabled(scrollView, !scrollView.mWrapMode);
+}
+
+void ScrollViewConstraints::SetOvershootConstraintsEnabled(ScrollView& scrollView, bool enabled)
+{
+ Actor scrollViewActor(scrollView.Self());
+ // remove and reset, it may now be in wrong order with the main internal constraints
+ if(mScrollMainInternalOvershootXConstraint)
+ {
+ mScrollMainInternalOvershootXConstraint.Remove();
+ mScrollMainInternalOvershootXConstraint.Reset();
+ mScrollMainInternalOvershootYConstraint.Remove();
+ mScrollMainInternalOvershootYConstraint.Reset();
+ }
+ if(enabled)
+ {
+ mScrollMainInternalOvershootXConstraint = Constraint::New<float>(scrollViewActor, Toolkit::ScrollView::Property::OVERSHOOT_X, OvershootXConstraint(scrollView.mMaxOvershoot.x));
+ mScrollMainInternalOvershootXConstraint.AddSource(LocalSource(Toolkit::ScrollView::Property::SCROLL_PRE_POSITION));
+ mScrollMainInternalOvershootXConstraint.AddSource(LocalSource(Toolkit::ScrollView::Property::SCROLL_POSITION));
+ mScrollMainInternalOvershootXConstraint.AddSource(LocalSource(Toolkit::Scrollable::Property::CAN_SCROLL_HORIZONTAL));
+ mScrollMainInternalOvershootXConstraint.Apply();
+
+ mScrollMainInternalOvershootYConstraint = Constraint::New<float>(scrollViewActor, Toolkit::ScrollView::Property::OVERSHOOT_Y, OvershootYConstraint(scrollView.mMaxOvershoot.y));
+ mScrollMainInternalOvershootYConstraint.AddSource(LocalSource(Toolkit::ScrollView::Property::SCROLL_PRE_POSITION));
+ mScrollMainInternalOvershootYConstraint.AddSource(LocalSource(Toolkit::ScrollView::Property::SCROLL_POSITION));
+ mScrollMainInternalOvershootYConstraint.AddSource(LocalSource(Toolkit::Scrollable::Property::CAN_SCROLL_VERTICAL));
+ mScrollMainInternalOvershootYConstraint.Apply();
+ }
+ else
+ {
+ scrollViewActor.SetProperty(Toolkit::ScrollView::Property::OVERSHOOT_X, 0.0f);
+ scrollViewActor.SetProperty(Toolkit::ScrollView::Property::OVERSHOOT_Y, 0.0f);
+ }
+}
+
+void ScrollViewConstraints::SetInternalConstraints(ScrollView& scrollView)
+{
+ // Internal constraints (applied to target ScrollBase Actor itself) /////////
+ UpdateMainInternalConstraint(scrollView);
+
+ // User definable constraints to apply to all child actors //////////////////
+ Actor scrollViewActor = scrollView.Self();
+
+ // Apply some default constraints to ScrollView & its bound actors
+ // Movement + Wrap function
+
+ Constraint constraint;
+
+ // MoveActor (scrolling)
+ constraint = Constraint::New<Vector3>(scrollViewActor, Actor::Property::POSITION, MoveActorConstraint);
+ constraint.AddSource(Source(scrollViewActor, Toolkit::ScrollView::Property::SCROLL_POSITION));
+ constraint.SetRemoveAction(Constraint::DISCARD);
+ scrollView.ApplyConstraintToBoundActors(constraint);
+
+ // WrapActor (wrap functionality)
+ constraint = Constraint::New<Vector3>(scrollViewActor, Actor::Property::POSITION, WrapActorConstraint);
+ constraint.AddSource(LocalSource(Actor::Property::SCALE));
+ constraint.AddSource(LocalSource(Actor::Property::ANCHOR_POINT));
+ constraint.AddSource(LocalSource(Actor::Property::SIZE));
+ constraint.AddSource(Source(scrollViewActor, Toolkit::Scrollable::Property::SCROLL_POSITION_MIN));
+ constraint.AddSource(Source(scrollViewActor, Toolkit::Scrollable::Property::SCROLL_POSITION_MAX));
+ constraint.AddSource(Source(scrollViewActor, Toolkit::ScrollView::Property::WRAP));
+ constraint.SetRemoveAction(Constraint::DISCARD);
+ scrollView.ApplyConstraintToBoundActors(constraint);
+}
+
+
+} // namespace Internal
+
+} // namespace Toolkit
+
+} // namespace Dali
--- /dev/null
+#ifndef DALI_TOOLKIT_INTERNAL_SCROLL_VIEW_CONSTRAINTS_H
+#define DALI_TOOLKIT_INTERNAL_SCROLL_VIEW_CONSTRAINTS_H
+
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <dali/public-api/animation/constraint.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Internal
+{
+
+class ScrollView;
+
+/// Sets up and owns the Constraints used by the ScrollView class
+class ScrollViewConstraints
+{
+public:
+
+ ScrollViewConstraints() = default; ///< Default Constructor
+ ~ScrollViewConstraints() = default; ///< Default Non-Virtual Destructor
+
+ // Not copyable or moveable
+ ScrollViewConstraints(const ScrollViewConstraints&) = delete;
+ ScrollViewConstraints(ScrollViewConstraints&&) = delete;
+ ScrollViewConstraints& operator=(const ScrollViewConstraints&) = delete;
+ ScrollViewConstraints& operator=(ScrollViewConstraints&&) = delete;
+
+ /**
+ * Updates the main internal scroll constraints with new ruler and domain values
+ *
+ * @param[in] scrollView A reference to the scroll view object
+ */
+ void UpdateMainInternalConstraint(Internal::ScrollView& scrollView);
+
+ /**
+ * Enables/disables the overshoot constraints
+ *
+ * @param[in] scrollView A reference to the scroll view object
+ * @param[in] enabled whether to enable or disable the overshoot constraints
+ */
+ void SetOvershootConstraintsEnabled(ScrollView& scrollView, bool enabled);
+
+ /**
+ * Sets internal constraints for this ScrollView.
+ * Many of these internal constraints are based on properties within ScrollView.
+ *
+ * @param[in] scrollView A reference to the scroll view object
+ */
+ void SetInternalConstraints(ScrollView& scrollView);
+
+public:
+
+ Constraint mScrollMainInternalPrePositionConstraint;
+ Constraint mScrollMainInternalPositionConstraint;
+ Constraint mScrollMainInternalOvershootXConstraint;
+ Constraint mScrollMainInternalOvershootYConstraint;
+ Constraint mScrollMainInternalDeltaConstraint;
+ Constraint mScrollMainInternalFinalConstraint;
+ Constraint mScrollMainInternalRelativeConstraint;
+ Constraint mScrollMainInternalDomainConstraint;
+ Constraint mScrollMainInternalPrePositionMaxConstraint;
+};
+
+} // namespace Internal
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // DALI_TOOLKIT_INTERNAL_SCROLL_VIEW_CONSTRAINTS_H
//#define ENABLED_SCROLL_STATE_LOGGING
#ifdef ENABLED_SCROLL_STATE_LOGGING
-#define DALI_LOG_SCROLL_STATE(format, ...) Dali::Integration::Log::LogMessage(Dali::Integration::Log::DebugInfo, "%s:%d " format "\n", __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__)
+#define DALI_LOG_SCROLL_STATE(format, ...) Dali::Integration::Log::LogMessageWithFunctionLine(Dali::Integration::Log::DebugInfo, "%s:%d " format "\n", __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__)
#else
#define DALI_LOG_SCROLL_STATE(format, ...)
#endif
// TODO: Orientation.
// TODO: upgrade Vector2/3 to support returning Unit vectors, normals, & cross product (dot product is already provided)
-using namespace Dali;
-
namespace
{
-const float DEFAULT_SLOW_SNAP_ANIMATION_DURATION(0.5f); ///< Default Drag-Release animation time.
-const float DEFAULT_FAST_SNAP_ANIMATION_DURATION(0.25f); ///< Default Drag-Flick animation time.
-const float DEFAULT_SNAP_OVERSHOOT_DURATION(0.5f); ///< Default Overshoot snapping animation time.
-const float DEFAULT_MAX_OVERSHOOT(100.0f); ///< Default maximum allowed overshoot in pixels
-
-const float DEFAULT_AXIS_AUTO_LOCK_GRADIENT(0.36f); ///< Default Axis-AutoLock gradient threshold. default is 0.36:1 (20 degrees)
-const float DEFAULT_FRICTION_COEFFICIENT(1.0f); ///< Default Friction Co-efficient. (in stage diagonals per second)
-const float DEFAULT_FLICK_SPEED_COEFFICIENT(1.0f); ///< Default Flick speed coefficient (multiples input touch velocity)
-const float DEFAULT_MAX_FLICK_SPEED(3.0f); ///< Default Maximum flick speed. (in stage diagonals per second)
-
-const Vector2 DEFAULT_MIN_FLICK_DISTANCE(30.0f, 30.0f); ///< minimum distance for pan before flick allowed
-const float DEFAULT_MIN_FLICK_SPEED_THRESHOLD(500.0f); ///< Minimum pan speed required for flick in pixels/s
-const float FREE_FLICK_SPEED_THRESHOLD = 200.0f; ///< Free-Flick threshold in pixels/ms
-const float AUTOLOCK_AXIS_MINIMUM_DISTANCE2 = 100.0f; ///< Auto-lock axis after minimum distance squared.
-const float FLICK_ORTHO_ANGLE_RANGE = 75.0f; ///< degrees. (if >45, then supports diagonal flicking)
-const Vector2 DEFAULT_WHEEL_SCROLL_DISTANCE_STEP_PROPORTION = Vector2(0.17f, 0.1f); ///< The step of horizontal scroll distance in the proportion of stage size for each wheel event received.
-const unsigned long MINIMUM_TIME_BETWEEN_DOWN_AND_UP_FOR_RESET(150u);
-const float TOUCH_DOWN_TIMER_INTERVAL = 100.0f;
-const float DEFAULT_SCROLL_UPDATE_DISTANCE(30.0f); ///< Default distance to travel in pixels for scroll update signal
+using namespace Dali;
+
+constexpr float DEFAULT_SLOW_SNAP_ANIMATION_DURATION(0.5f); ///< Default Drag-Release animation time.
+constexpr float DEFAULT_FAST_SNAP_ANIMATION_DURATION(0.25f); ///< Default Drag-Flick animation time.
+constexpr float DEFAULT_SNAP_OVERSHOOT_DURATION(0.5f); ///< Default Overshoot snapping animation time.
+constexpr float DEFAULT_MAX_OVERSHOOT(100.0f); ///< Default maximum allowed overshoot in pixels
+
+constexpr float DEFAULT_AXIS_AUTO_LOCK_GRADIENT(0.36f); ///< Default Axis-AutoLock gradient threshold. default is 0.36:1 (20 degrees)
+constexpr float DEFAULT_FRICTION_COEFFICIENT(1.0f); ///< Default Friction Co-efficient. (in stage diagonals per second)
+constexpr float DEFAULT_FLICK_SPEED_COEFFICIENT(1.0f); ///< Default Flick speed coefficient (multiples input touch velocity)
+constexpr float DEFAULT_MAX_FLICK_SPEED(3.0f); ///< Default Maximum flick speed. (in stage diagonals per second)
+
+constexpr Dali::Vector2 DEFAULT_MIN_FLICK_DISTANCE(30.0f, 30.0f); ///< minimum distance for pan before flick allowed
+constexpr float DEFAULT_MIN_FLICK_SPEED_THRESHOLD(500.0f); ///< Minimum pan speed required for flick in pixels/s
+
+constexpr float FREE_FLICK_SPEED_THRESHOLD = 200.0f; ///< Free-Flick threshold in pixels/ms
+constexpr float AUTOLOCK_AXIS_MINIMUM_DISTANCE2 = 100.0f; ///< Auto-lock axis after minimum distance squared.
+constexpr float FLICK_ORTHO_ANGLE_RANGE = 75.0f; ///< degrees. (if >45, then supports diagonal flicking)
+
+constexpr Dali::Vector2 DEFAULT_WHEEL_SCROLL_DISTANCE_STEP_PROPORTION(0.17f, 0.1f); ///< The step of horizontal scroll distance in the proportion of stage size for each wheel event received.
+
+constexpr unsigned long MINIMUM_TIME_BETWEEN_DOWN_AND_UP_FOR_RESET(150u);
+constexpr float TOUCH_DOWN_TIMER_INTERVAL = 100.0f;
+constexpr float DEFAULT_SCROLL_UPDATE_DISTANCE(30.0f); ///< Default distance to travel in pixels for scroll update signal
const std::string INTERNAL_MAX_POSITION_PROPERTY_NAME("internalMaxPosition");
{
if(bias == Dali::Toolkit::DIRECTION_BIAS_NONE)
{
- return ShortestDistanceInDomain(a, b, start, end);
+ return Dali::ShortestDistanceInDomain(a, b, start, end);
}
// (a-start + end-b)
float size = end - start;
* @param anchor The Anchor point of interest.
* @return The position of the Anchor
*/
-Vector3 GetPositionOfAnchor(Actor& actor, const Vector3& anchor)
+Dali::Vector3 GetPositionOfAnchor(Dali::Actor& actor, const Dali::Vector3& anchor)
{
- Vector3 childPosition = actor.GetCurrentProperty<Vector3>(Actor::Property::POSITION);
- Vector3 childAnchor = -actor.GetCurrentProperty<Vector3>(Actor::Property::ANCHOR_POINT) + anchor;
- Vector3 childSize = actor.GetCurrentProperty<Vector3>(Actor::Property::SIZE);
+ Dali::Vector3 childPosition = actor.GetCurrentProperty<Dali::Vector3>(Dali::Actor::Property::POSITION);
+ Dali::Vector3 childAnchor = -actor.GetCurrentProperty<Dali::Vector3>(Dali::Actor::Property::ANCHOR_POINT) + anchor;
+ Dali::Vector3 childSize = actor.GetCurrentProperty<Dali::Vector3>(Dali::Actor::Property::SIZE);
return childPosition + childAnchor * childSize;
}
-// AlphaFunctions /////////////////////////////////////////////////////////////////////////////////
+/**
+ * Returns the closest actor to the given position
+ * @param[in] actor The scrollview actor
+ * @param[in] internalActor The internal actor (to ignore)
+ * @param[in] position The given position
+ * @param[in] dirX Direction to search in
+ * @param[in] dirY Direction to search in
+ * @param[in] dirZ Direction to search in
+ * @return the closest child actor
+ */
+using FindDirection = Dali::Toolkit::Internal::ScrollView::FindDirection;
-float FinalDefaultAlphaFunction(float offset)
+Actor FindClosestActorToPosition(
+ CustomActor actor, Actor internalActor, const Vector3& position, FindDirection dirX, FindDirection dirY, FindDirection dirZ)
{
- return offset * 0.5f;
+ Actor closestChild;
+ float closestDistance2 = 0.0f;
+ Vector3 actualPosition = position;
+
+ unsigned int numChildren = actor.GetChildCount();
+
+ for(unsigned int i = 0; i < numChildren; ++i)
+ {
+ Actor child = actor.GetChildAt(i);
+
+ if(internalActor == child) // ignore internal actor.
+ {
+ continue;
+ }
+
+ Vector3 childPosition = GetPositionOfAnchor(child, AnchorPoint::CENTER);
+
+ Vector3 delta = childPosition - actualPosition;
+
+ // X-axis checking (only find Actors to the [dirX] of actualPosition)
+ if(dirX > FindDirection::All) // != All,None
+ {
+ FindDirection deltaH = delta.x > 0 ? FindDirection::Right : FindDirection::Left;
+ if(dirX != deltaH)
+ {
+ continue;
+ }
+ }
+
+ // Y-axis checking (only find Actors to the [dirY] of actualPosition)
+ if(dirY > FindDirection::All) // != All,None
+ {
+ FindDirection deltaV = delta.y > 0 ? FindDirection::Down : FindDirection::Up;
+ if(dirY != deltaV)
+ {
+ continue;
+ }
+ }
+
+ // Z-axis checking (only find Actors to the [dirZ] of actualPosition)
+ if(dirZ > FindDirection::All) // != All,None
+ {
+ FindDirection deltaV = delta.y > 0 ? FindDirection::In : FindDirection::Out;
+ if(dirZ != deltaV)
+ {
+ continue;
+ }
+ }
+
+ // compare child to closest child in terms of distance.
+ float distance2 = 0.0f;
+
+ // distance2 = the Square of the relevant dimensions of delta
+ if(dirX != FindDirection::None)
+ {
+ distance2 += delta.x * delta.x;
+ }
+
+ if(dirY != FindDirection::None)
+ {
+ distance2 += delta.y * delta.y;
+ }
+
+ if(dirZ != FindDirection::None)
+ {
+ distance2 += delta.z * delta.z;
+ }
+
+ if(closestChild) // Next time.
+ {
+ if(distance2 < closestDistance2)
+ {
+ closestChild = child;
+ closestDistance2 = distance2;
+ }
+ }
+ else // First time.
+ {
+ closestChild = child;
+ closestDistance2 = distance2;
+ }
+ }
+
+ return closestChild;
}
+// AlphaFunctions /////////////////////////////////////////////////////////////////////////////////
+
/**
* ConstantDecelerationAlphaFunction
* Newtoninan distance for constant deceleration
return progress * 2.0f - progress * progress;
}
-// Internal Constraints ///////////////////////////////////////////////////////////////////////////
-
/**
- * Internal Relative position Constraint
- * Generates the relative position value of the scroll view
- * based on the absolute position, and it's relation to the
- * scroll domain. This is a value from 0.0f to 1.0f in each
- * scroll position axis.
+ * Clamp a position
+ * @param[in] size The size to clamp to
+ * @param[in] rulerX The horizontal ruler
+ * @param[in] rulerY The vertical ruler
+ * @param[in,out] position The position to clamp
+ * @param[out] clamped the clamped state
*/
-void InternalRelativePositionConstraint(Vector2& relativePosition, const PropertyInputContainer& inputs)
+void ClampPosition(const Vector3& size, Dali::Toolkit::RulerPtr rulerX, Dali::Toolkit::RulerPtr rulerY, Vector2& position, Dali::Toolkit::ClampState2D& clamped)
{
- Vector2 position = -inputs[0]->GetVector2();
- const Vector2& min = inputs[1]->GetVector2();
- const Vector2& max = inputs[2]->GetVector2();
- const Vector3& size = inputs[3]->GetVector3();
-
- position.x = WrapInDomain(position.x, min.x, max.x);
- position.y = WrapInDomain(position.y, min.y, max.y);
-
- Vector2 domainSize = (max - min) - size.GetVectorXY();
-
- relativePosition.x = domainSize.x > Math::MACHINE_EPSILON_1 ? fabsf((position.x - min.x) / domainSize.x) : 0.0f;
- relativePosition.y = domainSize.y > Math::MACHINE_EPSILON_1 ? fabsf((position.y - min.y) / domainSize.y) : 0.0f;
+ position.x = -rulerX->Clamp(-position.x, size.width, 1.0f, clamped.x); // NOTE: X & Y rulers think in -ve coordinate system.
+ position.y = -rulerY->Clamp(-position.y, size.height, 1.0f, clamped.y); // That is scrolling RIGHT (e.g. 100.0, 0.0) means moving LEFT.
}
/**
- * Internal scroll domain Constraint
- * Generates the scroll domain of the scroll view.
+ * TODO: In situations where axes are different (X snap, Y free)
+ * Each axis should really have their own independent animation (time and equation)
+ * Consider, X axis snapping to nearest grid point (EaseOut over fixed time)
+ * Consider, Y axis simulating physics to arrive at a point (Physics equation over variable time)
+ * Currently, the axes have been split however, they both use the same EaseOut equation.
+ *
+ * @param[in] scrollView The main scrollview
+ * @param[in] rulerX The X ruler
+ * @param[in] rulerY The Y ruler
+ * @param[in] lockAxis Which axis (if any) is locked.
+ * @param[in] velocity Current pan velocity
+ * @param[in] maxOvershoot Maximum overshoot
+ * @param[in] inAcessibilityPan True if we are currently panning with accessibility
+ * @param[out] positionSnap The target position of snap animation
+ * @param[out] positionDuration The duration of the snap animation
+ * @param[out] alphaFunction The snap animation alpha function
+ * @param[out] isFlick if we are flicking or not
+ * @param[out] isFreeFlick if we are free flicking or not
*/
-void InternalScrollDomainConstraint(Vector2& scrollDomain, const PropertyInputContainer& inputs)
+void SnapWithVelocity(
+ Dali::Toolkit::Internal::ScrollView& scrollView,
+ Dali::Toolkit::RulerPtr rulerX,
+ Dali::Toolkit::RulerPtr rulerY,
+ Dali::Toolkit::Internal::ScrollView::LockAxis lockAxis,
+ Vector2 velocity,
+ Vector2 maxOvershoot,
+ Vector2& positionSnap,
+ Vector2& positionDuration,
+ AlphaFunction& alphaFunction,
+ bool inAccessibilityPan,
+ bool& isFlick,
+ bool& isFreeFlick)
{
- const Vector2& min = inputs[0]->GetVector2();
- const Vector2& max = inputs[1]->GetVector2();
- const Vector3& size = inputs[2]->GetVector3();
+ // Animator takes over now, touches are assumed not to interfere.
+ // And if touches do interfere, then we'll stop animation, update PrePosition
+ // to current mScroll's properties, and then resume.
+ // Note: For Flicking this may work a bit different...
- scrollDomain = (max - min) - size.GetVectorXY();
-}
+ float angle = atan2(velocity.y, velocity.x);
+ float speed2 = velocity.LengthSquared();
+ float biasX = 0.5f;
+ float biasY = 0.5f;
+ FindDirection horizontal = FindDirection::None;
+ FindDirection vertical = FindDirection::None;
-/**
- * Internal maximum scroll position Constraint
- * Generates the maximum scroll position of the scroll view.
- */
-void InternalPrePositionMaxConstraint(Vector2& scrollMax, const PropertyInputContainer& inputs)
-{
- const Vector2& max = inputs[0]->GetVector2();
- const Vector3& size = inputs[1]->GetVector3();
+ using LockAxis = Dali::Toolkit::Internal::ScrollView::LockAxis;
+
+ // orthoAngleRange = Angle tolerance within the Exact N,E,S,W direction
+ // that will be accepted as a general N,E,S,W flick direction.
+
+ const float orthoAngleRange = FLICK_ORTHO_ANGLE_RANGE * M_PI / 180.0f;
+ const float flickSpeedThreshold2 = scrollView.GetMinimumSpeedForFlick() * scrollView.GetMinimumSpeedForFlick();
+
+ // Flick logic X Axis
+
+ if(rulerX->IsEnabled() && lockAxis != LockAxis::LockHorizontal)
+ {
+ horizontal = FindDirection::All;
+
+ if(speed2 > flickSpeedThreshold2 || // exceeds flick threshold
+ inAccessibilityPan) // With AccessibilityPan its easier to move between snap positions
+ {
+ if((angle >= -orthoAngleRange) && (angle < orthoAngleRange)) // Swiping East
+ {
+ biasX = 0.0f, horizontal = FindDirection::Left;
+
+ // This guards against an error where no movement occurs, due to the flick finishing
+ // before the update-thread has advanced mScrollPostPosition past the the previous snap point.
+ positionSnap.x += 1.0f;
+ }
+ else if((angle >= M_PI - orthoAngleRange) || (angle < -M_PI + orthoAngleRange)) // Swiping West
+ {
+ biasX = 1.0f, horizontal = FindDirection::Right;
+
+ // This guards against an error where no movement occurs, due to the flick finishing
+ // before the update-thread has advanced mScrollPostPosition past the the previous snap point.
+ positionSnap.x -= 1.0f;
+ }
+ }
+ }
+
+ // Flick logic Y Axis
+
+ if(rulerY->IsEnabled() && lockAxis != LockAxis::LockVertical)
+ {
+ vertical = FindDirection::All;
+
+ if(speed2 > flickSpeedThreshold2 || // exceeds flick threshold
+ inAccessibilityPan) // With AccessibilityPan its easier to move between snap positions
+ {
+ if((angle >= M_PI_2 - orthoAngleRange) && (angle < M_PI_2 + orthoAngleRange)) // Swiping South
+ {
+ biasY = 0.0f, vertical = FindDirection::Up;
+ }
+ else if((angle >= -M_PI_2 - orthoAngleRange) && (angle < -M_PI_2 + orthoAngleRange)) // Swiping North
+ {
+ biasY = 1.0f, vertical = FindDirection::Down;
+ }
+ }
+ }
+
+ // isFlick: Whether this gesture is a flick or not.
+ isFlick = (horizontal != FindDirection::All || vertical != FindDirection::All);
+ // isFreeFlick: Whether this gesture is a flick under free panning criteria.
+ isFreeFlick = velocity.LengthSquared() > (FREE_FLICK_SPEED_THRESHOLD * FREE_FLICK_SPEED_THRESHOLD);
+
+ if(isFlick || isFreeFlick)
+ {
+ positionDuration = Vector2::ONE * scrollView.GetScrollFlickDuration();
+ alphaFunction = scrollView.GetScrollFlickAlphaFunction();
+ }
+
+ // Calculate next positionSnap ////////////////////////////////////////////////////////////
+
+ if(scrollView.GetActorAutoSnap())
+ {
+ Vector3 size = scrollView.Self().GetCurrentProperty<Vector3>(Actor::Property::SIZE);
+
+ Actor child = scrollView.FindClosestActorToPosition(Vector3(size.width * 0.5f, size.height * 0.5f, 0.0f), horizontal, vertical);
+
+ if(!child && isFlick)
+ {
+ // If we conducted a direction limited search and found no actor, then just snap to the closest actor.
+ child = scrollView.FindClosestActorToPosition(Vector3(size.width * 0.5f, size.height * 0.5f, 0.0f));
+ }
+
+ if(child)
+ {
+ Vector2 position = scrollView.Self().GetCurrentProperty<Vector2>(Toolkit::ScrollView::Property::SCROLL_POSITION);
+
+ // Get center-point of the Actor.
+ Vector3 childPosition = GetPositionOfAnchor(child, AnchorPoint::CENTER);
+
+ if(rulerX->IsEnabled())
+ {
+ positionSnap.x = position.x - childPosition.x + size.width * 0.5f;
+ }
+ if(rulerY->IsEnabled())
+ {
+ positionSnap.y = position.y - childPosition.y + size.height * 0.5f;
+ }
+ }
+ }
+
+ Vector2 startPosition = positionSnap;
+ positionSnap.x = -rulerX->Snap(-positionSnap.x, biasX); // NOTE: X & Y rulers think in -ve coordinate system.
+ positionSnap.y = -rulerY->Snap(-positionSnap.y, biasY); // That is scrolling RIGHT (e.g. 100.0, 0.0) means moving LEFT.
+
+ Dali::Toolkit::ClampState2D clamped;
+ Vector3 size = scrollView.Self().GetCurrentProperty<Vector3>(Actor::Property::SIZE);
+ Vector2 clampDelta(Vector2::ZERO);
+ ClampPosition(size, rulerX, rulerY, positionSnap, clamped);
+
+ if((rulerX->GetType() == Dali::Toolkit::Ruler::FREE || rulerY->GetType() == Dali::Toolkit::Ruler::FREE) &&
+ isFreeFlick && !scrollView.GetActorAutoSnap())
+ {
+ // Calculate target position based on velocity of flick.
+
+ // a = Deceleration (Set to diagonal stage length * friction coefficient)
+ // u = Initial Velocity (Flick velocity)
+ // v = 0 (Final Velocity)
+ // t = Time (Velocity / Deceleration)
+ Vector2 stageSize = Stage::GetCurrent().GetSize();
+ float stageLength = Vector3(stageSize.x, stageSize.y, 0.0f).Length();
+ float a = (stageLength * scrollView.GetFrictionCoefficient());
+ Vector3 u = Vector3(velocity.x, velocity.y, 0.0f) * scrollView.GetFlickSpeedCoefficient();
+ float speed = u.Length();
+ u /= speed;
+
+ // TODO: Change this to a decay function. (faster you flick, the slower it should be)
+ speed = std::min(speed, stageLength * scrollView.GetMaxFlickSpeed());
+ u *= speed;
+ alphaFunction = ConstantDecelerationAlphaFunction;
+
+ float t = speed / a;
+
+ if(rulerX->IsEnabled() && rulerX->GetType() == Dali::Toolkit::Ruler::FREE)
+ {
+ positionSnap.x += t * u.x * 0.5f;
+ }
+
+ if(rulerY->IsEnabled() && rulerY->GetType() == Dali::Toolkit::Ruler::FREE)
+ {
+ positionSnap.y += t * u.y * 0.5f;
+ }
+
+ clampDelta = positionSnap;
+ ClampPosition(size, rulerX, rulerY, positionSnap, clamped);
+
+ if((positionSnap - startPosition).LengthSquared() > Math::MACHINE_EPSILON_0)
+ {
+ clampDelta -= positionSnap;
+ clampDelta.x = clampDelta.x > 0.0f ? std::min(clampDelta.x, maxOvershoot.x) : std::max(clampDelta.x, -maxOvershoot.x);
+ clampDelta.y = clampDelta.y > 0.0f ? std::min(clampDelta.y, maxOvershoot.y) : std::max(clampDelta.y, -maxOvershoot.y);
+ }
+ else
+ {
+ clampDelta = Vector2::ZERO;
+ }
+
+ // If Axis is Free and has velocity, then calculate time taken
+ // to reach target based on velocity in axis.
+ if(rulerX->IsEnabled() && rulerX->GetType() == Dali::Toolkit::Ruler::FREE)
+ {
+ float deltaX = fabsf(startPosition.x - positionSnap.x);
+
+ if(fabsf(u.x) > Math::MACHINE_EPSILON_1)
+ {
+ positionDuration.x = fabsf(deltaX / u.x);
+ }
+ else
+ {
+ positionDuration.x = 0;
+ }
+ }
+
+ if(rulerY->IsEnabled() && rulerY->GetType() == Dali::Toolkit::Ruler::FREE)
+ {
+ float deltaY = fabsf(startPosition.y - positionSnap.y);
+
+ if(fabsf(u.y) > Math::MACHINE_EPSILON_1)
+ {
+ positionDuration.y = fabsf(deltaY / u.y);
+ }
+ else
+ {
+ positionDuration.y = 0;
+ }
+ }
+ }
- scrollMax = max - size.GetVectorXY();
+ if(scrollView.IsOvershootEnabled())
+ {
+ // Scroll to the end of the overshoot only when overshoot is enabled.
+ positionSnap += clampDelta;
+ }
}
} // unnamed namespace
DALI_TYPE_REGISTRATION_END()
-/**
- * Returns whether to lock scrolling to a particular axis
- *
- * @param[in] panDelta Distance panned since gesture started
- * @param[in] currentLockAxis The current lock axis value
- * @param[in] lockGradient How quickly to lock to a particular axis
- *
- * @return The new axis lock state
- */
-ScrollView::LockAxis GetLockAxis(const Vector2& panDelta, ScrollView::LockAxis currentLockAxis, float lockGradient)
-{
- if(panDelta.LengthSquared() > AUTOLOCK_AXIS_MINIMUM_DISTANCE2 &&
- currentLockAxis == ScrollView::LockPossible)
- {
- float dx = fabsf(panDelta.x);
- float dy = fabsf(panDelta.y);
- if(dx * lockGradient >= dy)
- {
- // 0.36:1 gradient to the horizontal (deviate < 20 degrees)
- currentLockAxis = ScrollView::LockVertical;
- }
- else if(dy * lockGradient > dx)
- {
- // 0.36:1 gradient to the vertical (deviate < 20 degrees)
- currentLockAxis = ScrollView::LockHorizontal;
- }
- else
- {
- currentLockAxis = ScrollView::LockNone;
- }
- }
- return currentLockAxis;
-}
-
-/**
- * Internal Pre-Position Property Constraint.
- *
- * Generates position property based on current position + gesture displacement.
- * Or generates position property based on positionX/Y.
- * Note: This is the position prior to any clamping at scroll boundaries.
- */
-struct InternalPrePositionConstraint
-{
- InternalPrePositionConstraint(const Vector2& initialPanPosition,
- const Vector2& initialPanMask,
- bool axisAutoLock,
- float axisAutoLockGradient,
- ScrollView::LockAxis initialLockAxis,
- const Vector2& maxOvershoot,
- const RulerPtr& rulerX,
- const RulerPtr& rulerY)
- : mLocalStart(initialPanPosition),
- mInitialPanMask(initialPanMask),
- mMaxOvershoot(maxOvershoot),
- mAxisAutoLockGradient(axisAutoLockGradient),
- mLockAxis(initialLockAxis),
- mAxisAutoLock(axisAutoLock),
- mWasPanning(false)
- {
- const RulerDomain& rulerDomainX = rulerX->GetDomain();
- const RulerDomain& rulerDomainY = rulerY->GetDomain();
- mDomainMin = Vector2(rulerDomainX.min, -rulerDomainY.min);
- mDomainMax = Vector2(-rulerDomainX.max, -rulerDomainY.max);
- mClampX = rulerDomainX.enabled;
- mClampY = rulerDomainY.enabled;
- mFixedRulerX = rulerX->GetType() == Ruler::FIXED;
- mFixedRulerY = rulerY->GetType() == Ruler::FIXED;
- }
-
- void operator()(Vector2& scrollPostPosition, const PropertyInputContainer& inputs)
- {
- const Vector2& panPosition = inputs[0]->GetVector2();
- const bool& inGesture = inputs[1]->GetBoolean();
-
- // First check if we are within a gesture.
- // The ScrollView may have received a start gesture from ::OnPan()
- // while the finish gesture is received now in this constraint.
- // This gesture must then be rejected as the value will be "old".
- // Typically the last value from the end of the last gesture.
- // If we are rejecting the gesture, we simply don't modify the constraint target.
- if(inGesture)
- {
- if(!mWasPanning)
- {
- mPrePosition = scrollPostPosition;
- mStartPosition = mPrePosition;
- mCurrentPanMask = mInitialPanMask;
- mWasPanning = true;
- }
-
- // Calculate Deltas...
- const Vector2& currentPosition = panPosition;
- Vector2 panDelta(currentPosition - mLocalStart);
-
- // Axis Auto Lock - locks the panning to the horizontal or vertical axis if the pan
- // appears mostly horizontal or mostly vertical respectively...
- if(mAxisAutoLock)
- {
- mLockAxis = GetLockAxis(panDelta, mLockAxis, mAxisAutoLockGradient);
- if(mLockAxis == ScrollView::LockVertical)
- {
- mCurrentPanMask.y = 0.0f;
- }
- else if(mLockAxis == ScrollView::LockHorizontal)
- {
- mCurrentPanMask.x = 0.0f;
- }
- }
-
- // Restrict deltas based on ruler enable/disable and axis-lock state...
- panDelta *= mCurrentPanMask;
-
- // Perform Position transform based on input deltas...
- scrollPostPosition = mPrePosition;
- scrollPostPosition += panDelta;
-
- // if no wrapping then clamp preposition to maximum overshoot amount
- const Vector3& size = inputs[2]->GetVector3();
- if(mClampX)
- {
- float newXPosition = Clamp(scrollPostPosition.x, (mDomainMax.x + size.x) - mMaxOvershoot.x, mDomainMin.x + mMaxOvershoot.x);
- if((newXPosition < scrollPostPosition.x - Math::MACHINE_EPSILON_1) || (newXPosition > scrollPostPosition.x + Math::MACHINE_EPSILON_1))
- {
- mPrePosition.x = newXPosition;
- mLocalStart.x = panPosition.x;
- }
- scrollPostPosition.x = newXPosition;
- }
- if(mClampY)
- {
- float newYPosition = Clamp(scrollPostPosition.y, (mDomainMax.y + size.y) - mMaxOvershoot.y, mDomainMin.y + mMaxOvershoot.y);
- if((newYPosition < scrollPostPosition.y - Math::MACHINE_EPSILON_1) || (newYPosition > scrollPostPosition.y + Math::MACHINE_EPSILON_1))
- {
- mPrePosition.y = newYPosition;
- mLocalStart.y = panPosition.y;
- }
- scrollPostPosition.y = newYPosition;
- }
-
- // If we are using a fixed ruler in a particular axis, limit the maximum pages scrolled on that axis.
- if(mFixedRulerX || mFixedRulerY)
- {
- // Here we limit the maximum amount that can be moved from the starting position of the gesture to one page.
- // We do this only if we have a fixed ruler (on that axis) and the mode is enabled.
- // Note: 1.0f is subtracted to keep the value within one page size (otherwise we stray on to the page after).
- // Note: A further 1.0f is subtracted to handle a compensation that happens later within the flick handling code in SnapWithVelocity().
- // When a flick is completed, an adjustment of 1.0f is sometimes made to allow for the scenario where:
- // A flick finishes before the update thread has advanced the scroll position past the previous snap point.
- Vector2 viewPageSizeLimit(size.x - (1.0f + 1.0f), size.y - (1.0f - 1.0f));
- Vector2 minPosition(mStartPosition.x - viewPageSizeLimit.x, mStartPosition.y - viewPageSizeLimit.y);
- Vector2 maxPosition(mStartPosition.x + viewPageSizeLimit.x, mStartPosition.y + viewPageSizeLimit.y);
-
- if(mFixedRulerX)
- {
- scrollPostPosition.x = Clamp(scrollPostPosition.x, minPosition.x, maxPosition.x);
- }
- if(mFixedRulerY)
- {
- scrollPostPosition.y = Clamp(scrollPostPosition.y, minPosition.y, maxPosition.y);
- }
- }
- }
- }
-
- Vector2 mPrePosition;
- Vector2 mLocalStart;
- Vector2 mStartPosition; ///< The start position of the gesture - used to limit scroll amount (not modified by clamping).
- Vector2 mInitialPanMask; ///< Initial pan mask (based on ruler settings).
- Vector2 mCurrentPanMask; ///< Current pan mask that can be altered by axis lock mode.
- Vector2 mDomainMin;
- Vector2 mDomainMax;
- Vector2 mMaxOvershoot;
-
- float mAxisAutoLockGradient; ///< Set by ScrollView
- ScrollView::LockAxis mLockAxis;
-
- bool mAxisAutoLock : 1; ///< Set by ScrollView
- bool mWasPanning : 1;
- bool mClampX : 1;
- bool mClampY : 1;
- bool mFixedRulerX : 1;
- bool mFixedRulerY : 1;
-};
-
-/**
- * Internal Position Property Constraint.
- *
- * Generates position property based on pre-position
- * Note: This is the position after clamping.
- * (uses result of InternalPrePositionConstraint)
- */
-struct InternalPositionConstraint
-{
- InternalPositionConstraint(const RulerDomain& domainX, const RulerDomain& domainY, bool wrap)
- : mDomainMin(-domainX.min, -domainY.min),
- mDomainMax(-domainX.max, -domainY.max),
- mClampX(domainX.enabled),
- mClampY(domainY.enabled),
- mWrap(wrap)
- {
- }
-
- void operator()(Vector2& position, const PropertyInputContainer& inputs)
- {
- position = inputs[0]->GetVector2();
- const Vector2& size = inputs[3]->GetVector3().GetVectorXY();
- const Vector2& min = inputs[1]->GetVector2();
- const Vector2& max = inputs[2]->GetVector2();
-
- if(mWrap)
- {
- position.x = -WrapInDomain(-position.x, min.x, max.x);
- position.y = -WrapInDomain(-position.y, min.y, max.y);
- }
- else
- {
- // clamp post position to domain
- position.x = mClampX ? Clamp(position.x, mDomainMax.x + size.x, mDomainMin.x) : position.x;
- position.y = mClampY ? Clamp(position.y, mDomainMax.y + size.y, mDomainMin.y) : position.y;
- }
- }
-
- Vector2 mDomainMin;
- Vector2 mDomainMax;
- bool mClampX;
- bool mClampY;
- bool mWrap;
-};
-
-/**
- * This constraint updates the X overshoot property using the difference
- * SCROLL_PRE_POSITION.x and SCROLL_POSITION.x, returning a relative value between 0.0f and 1.0f
- */
-struct OvershootXConstraint
-{
- OvershootXConstraint(float maxOvershoot)
- : mMaxOvershoot(maxOvershoot)
- {
- }
-
- void operator()(float& current, const PropertyInputContainer& inputs)
- {
- if(inputs[2]->GetBoolean())
- {
- const Vector2& scrollPrePosition = inputs[0]->GetVector2();
- const Vector2& scrollPostPosition = inputs[1]->GetVector2();
- float newOvershoot = scrollPrePosition.x - scrollPostPosition.x;
- current = (newOvershoot > 0.0f ? std::min(newOvershoot, mMaxOvershoot) : std::max(newOvershoot, -mMaxOvershoot)) / mMaxOvershoot;
- }
- else
- {
- current = 0.0f;
- }
- }
-
- float mMaxOvershoot;
-};
-
-/**
- * This constraint updates the Y overshoot property using the difference
- * SCROLL_PRE_POSITION.y and SCROLL_POSITION.y, returning a relative value between 0.0f and 1.0f
- */
-struct OvershootYConstraint
-{
- OvershootYConstraint(float maxOvershoot)
- : mMaxOvershoot(maxOvershoot)
- {
- }
-
- void operator()(float& current, const PropertyInputContainer& inputs)
- {
- if(inputs[2]->GetBoolean())
- {
- const Vector2& scrollPrePosition = inputs[0]->GetVector2();
- const Vector2& scrollPostPosition = inputs[1]->GetVector2();
- float newOvershoot = scrollPrePosition.y - scrollPostPosition.y;
- current = (newOvershoot > 0.0f ? std::min(newOvershoot, mMaxOvershoot) : std::max(newOvershoot, -mMaxOvershoot)) / mMaxOvershoot;
- }
- else
- {
- current = 0.0f;
- }
- }
-
- float mMaxOvershoot;
-};
-
-/**
- * Internal Position-Delta Property Constraint.
- *
- * Generates position-delta property based on scroll-position + scroll-offset properties.
- */
-void InternalPositionDeltaConstraint(Vector2& current, const PropertyInputContainer& inputs)
-{
- const Vector2& scrollPosition = inputs[0]->GetVector2();
- const Vector2& scrollOffset = inputs[1]->GetVector2();
-
- current = scrollPosition + scrollOffset;
-}
-
-/**
- * Internal Final Position Constraint
- * The position of content is:
- * of scroll-position + f(scroll-overshoot)
- * where f(...) function defines how overshoot
- * should affect final-position.
- */
-struct InternalFinalConstraint
-{
- InternalFinalConstraint(AlphaFunctionPrototype functionX,
- AlphaFunctionPrototype functionY)
- : mFunctionX(functionX),
- mFunctionY(functionY)
- {
- }
-
- void operator()(Vector2& current, const PropertyInputContainer& inputs)
- {
- const float& overshootx = inputs[1]->GetFloat();
- const float& overshooty = inputs[2]->GetFloat();
- Vector2 offset(mFunctionX(overshootx),
- mFunctionY(overshooty));
-
- current = inputs[0]->GetVector2() - offset;
- }
-
- AlphaFunctionPrototype mFunctionX;
- AlphaFunctionPrototype mFunctionY;
-};
-
} // namespace
///////////////////////////////////////////////////////////////////////////////////////////////////
self.SetProperty(Toolkit::Scrollable::Property::CAN_SCROLL_HORIZONTAL, mCanScrollHorizontal);
UpdatePropertyDomain();
- SetInternalConstraints();
+ mConstraints.SetInternalConstraints(*this);
// Connect wheel event
self.WheelEventSignal().Connect(this, &ScrollView::OnWheelEvent);
DALI_LOG_SCROLL_STATE("[0x%X]", this);
}
-AlphaFunction ScrollView::GetScrollSnapAlphaFunction() const
-{
- return mSnapAlphaFunction;
-}
-
-void ScrollView::SetScrollSnapAlphaFunction(AlphaFunction alpha)
-{
- mSnapAlphaFunction = alpha;
-}
-
-AlphaFunction ScrollView::GetScrollFlickAlphaFunction() const
-{
- return mFlickAlphaFunction;
-}
-
-void ScrollView::SetScrollFlickAlphaFunction(AlphaFunction alpha)
-{
- mFlickAlphaFunction = alpha;
-}
-
-float ScrollView::GetScrollSnapDuration() const
-{
- return mSnapDuration;
-}
-
-void ScrollView::SetScrollSnapDuration(float time)
-{
- mSnapDuration = time;
-}
-
-float ScrollView::GetScrollFlickDuration() const
-{
- return mFlickDuration;
-}
-
-void ScrollView::SetScrollFlickDuration(float time)
-{
- mFlickDuration = time;
-}
-
void ScrollView::ApplyEffect(Toolkit::ScrollViewEffect effect)
{
Dali::Toolkit::ScrollView self = Dali::Toolkit::ScrollView::DownCast(Self());
RemoveConstraintsFromBoundActors();
}
-const RulerPtr ScrollView::GetRulerX() const
-{
- return mRulerX;
-}
-
-const RulerPtr ScrollView::GetRulerY() const
-{
- return mRulerY;
-}
-
void ScrollView::SetRulerX(RulerPtr ruler)
{
mRulerX = ruler;
UpdatePropertyDomain();
- UpdateMainInternalConstraint();
+ mConstraints.UpdateMainInternalConstraint(*this);
}
void ScrollView::SetRulerY(RulerPtr ruler)
mRulerY = ruler;
UpdatePropertyDomain();
- UpdateMainInternalConstraint();
+ mConstraints.UpdateMainInternalConstraint(*this);
}
void ScrollView::UpdatePropertyDomain()
}
}
-bool ScrollView::GetScrollSensitive()
-{
- return mSensitive;
-}
-
void ScrollView::SetScrollSensitive(bool sensitive)
{
Actor self = Self();
mMaxOvershoot.y = overshootY;
mUserMaxOvershoot = mMaxOvershoot;
mDefaultMaxOvershoot = false;
- UpdateMainInternalConstraint();
-}
-
-void ScrollView::SetSnapOvershootAlphaFunction(AlphaFunction alpha)
-{
- mSnapOvershootAlphaFunction = alpha;
-}
-
-float ScrollView::GetSnapOvershootDuration()
-{
- return mSnapOvershootDuration;
-}
-
-void ScrollView::SetSnapOvershootDuration(float duration)
-{
- mSnapOvershootDuration = duration;
+ mConstraints.UpdateMainInternalConstraint(*this);
}
bool ScrollView::GetActorAutoSnap()
return mActorAutoSnapEnabled;
}
-void ScrollView::SetActorAutoSnap(bool enable)
-{
- mActorAutoSnapEnabled = enable;
-}
-
void ScrollView::SetAutoResize(bool enable)
{
mAutoResizeContainerEnabled = enable;
// TODO: This needs a lot of issues to be addressed before working.
}
-bool ScrollView::GetWrapMode() const
-{
- return mWrapMode;
-}
-
void ScrollView::SetWrapMode(bool enable)
{
mWrapMode = enable;
Self().SetProperty(Toolkit::ScrollView::Property::WRAP, enable);
}
-int ScrollView::GetScrollUpdateDistance() const
-{
- return mScrollUpdateDistance;
-}
-
-void ScrollView::SetScrollUpdateDistance(int distance)
-{
- mScrollUpdateDistance = distance;
-}
-
-bool ScrollView::GetAxisAutoLock() const
-{
- return mAxisAutoLock;
-}
-
void ScrollView::SetAxisAutoLock(bool enable)
{
mAxisAutoLock = enable;
- UpdateMainInternalConstraint();
-}
-
-float ScrollView::GetAxisAutoLockGradient() const
-{
- return mAxisAutoLockGradient;
+ mConstraints.UpdateMainInternalConstraint(*this);
}
void ScrollView::SetAxisAutoLockGradient(float gradient)
{
DALI_ASSERT_DEBUG(gradient >= 0.0f && gradient <= 1.0f);
mAxisAutoLockGradient = gradient;
- UpdateMainInternalConstraint();
-}
-
-float ScrollView::GetFrictionCoefficient() const
-{
- return mFrictionCoefficient;
+ mConstraints.UpdateMainInternalConstraint(*this);
}
void ScrollView::SetFrictionCoefficient(float friction)
mFrictionCoefficient = friction;
}
-float ScrollView::GetFlickSpeedCoefficient() const
-{
- return mFlickSpeedCoefficient;
-}
-
-void ScrollView::SetFlickSpeedCoefficient(float speed)
-{
- mFlickSpeedCoefficient = speed;
-}
-
-Vector2 ScrollView::GetMinimumDistanceForFlick() const
-{
- return mMinFlickDistance;
-}
-
-void ScrollView::SetMinimumDistanceForFlick(const Vector2& distance)
-{
- mMinFlickDistance = distance;
-}
-
-float ScrollView::GetMinimumSpeedForFlick() const
-{
- return mFlickSpeedThreshold;
-}
-
-void ScrollView::SetMinimumSpeedForFlick(float speed)
-{
- mFlickSpeedThreshold = speed;
-}
-
-float ScrollView::GetMaxFlickSpeed() const
-{
- return mMaxFlickSpeed;
-}
-
-void ScrollView::SetMaxFlickSpeed(float speed)
-{
- mMaxFlickSpeed = speed;
-}
-
-void ScrollView::SetWheelScrollDistanceStep(Vector2 step)
-{
- mWheelScrollDistanceStep = step;
-}
-
-Vector2 ScrollView::GetWheelScrollDistanceStep() const
-{
- return mWheelScrollDistanceStep;
-}
-
unsigned int ScrollView::GetCurrentPage() const
{
// in case animation is currently taking place.
mGestureStackDepth = 0;
self.SetProperty(Toolkit::ScrollView::Property::PANNING, false);
- if(mScrollMainInternalPrePositionConstraint)
+ if(mConstraints.mScrollMainInternalPrePositionConstraint)
{
- mScrollMainInternalPrePositionConstraint.Remove();
+ mConstraints.mScrollMainInternalPrePositionConstraint.Remove();
}
}
Vector2::ONE * duration,
alpha,
true,
- horizontalBias,
- verticalBias,
- SNAP);
-
- if(!animating)
- {
- // if not animating, then this pan has completed right now.
- self.SetProperty(Toolkit::ScrollView::Property::SCROLLING, false);
- mScrolling = false;
-
- // If we have no duration, then in the next update frame, we will be at the position specified as we just set.
- // In this scenario, we cannot return the currentScrollPosition as this is out-of-date and should instead return the requested final position
- Vector2 completedPosition(currentScrollPosition);
- if(duration <= Math::MACHINE_EPSILON_10)
- {
- completedPosition = position;
- }
-
- DALI_LOG_SCROLL_STATE("[0x%X] mScrollCompletedSignal 2 [%.2f, %.2f]", this, completedPosition.x, completedPosition.y);
- SetScrollUpdateNotification(false);
- mScrollCompletedSignal.Emit(completedPosition);
- }
-}
-
-void ScrollView::ScrollTo(const Vector2& position)
-{
- ScrollTo(position, mSnapDuration);
-}
-
-void ScrollView::ScrollTo(const Vector2& position, float duration)
-{
- ScrollTo(position, duration, DIRECTION_BIAS_NONE, DIRECTION_BIAS_NONE);
-}
-
-void ScrollView::ScrollTo(const Vector2& position, float duration, AlphaFunction alpha)
-{
- ScrollTo(position, duration, alpha, DIRECTION_BIAS_NONE, DIRECTION_BIAS_NONE);
-}
-
-void ScrollView::ScrollTo(const Vector2& position, float duration, DirectionBias horizontalBias, DirectionBias verticalBias)
-{
- ScrollTo(position, duration, mSnapAlphaFunction, horizontalBias, verticalBias);
-}
-
-void ScrollView::ScrollTo(const Vector2& position, float duration, AlphaFunction alpha, DirectionBias horizontalBias, DirectionBias verticalBias)
-{
- DALI_LOG_SCROLL_STATE("[0x%X] position[%.2f, %.2f] duration[%.2f], bias[%d, %d]", this, position.x, position.y, duration, int(horizontalBias), int(verticalBias));
- TransformTo(position, duration, alpha, horizontalBias, verticalBias);
-}
-
-void ScrollView::ScrollTo(unsigned int page)
-{
- ScrollTo(page, mSnapDuration);
-}
-
-void ScrollView::ScrollTo(unsigned int page, float duration, DirectionBias bias)
-{
- Vector2 position;
- unsigned int volume;
- unsigned int libraries;
-
- // The position to scroll to is continuous and linear
- // unless a domain has been enabled on the X axis.
- // or if WrapMode has been enabled.
- bool carryX = mRulerX->GetDomain().enabled | mWrapMode;
- bool carryY = mRulerY->GetDomain().enabled | mWrapMode;
-
- position.x = mRulerX->GetPositionFromPage(page, volume, carryX);
- position.y = mRulerY->GetPositionFromPage(volume, libraries, carryY);
-
- ScrollTo(position, duration, bias, bias);
-}
-
-void ScrollView::ScrollTo(Actor& actor)
-{
- ScrollTo(actor, mSnapDuration);
-}
-
-void ScrollView::ScrollTo(Actor& actor, float duration)
-{
- DALI_ASSERT_ALWAYS(actor.GetParent() == Self());
-
- Actor self = Self();
- Vector3 size = self.GetCurrentProperty<Vector3>(Actor::Property::SIZE);
- Vector3 position = actor.GetCurrentProperty<Vector3>(Actor::Property::POSITION);
- Vector2 prePosition = GetPropertyPrePosition();
- position.GetVectorXY() -= prePosition;
-
- ScrollTo(Vector2(position.x - size.width * 0.5f, position.y - size.height * 0.5f), duration);
-}
-
-Actor ScrollView::FindClosestActor()
-{
- Actor self = Self();
- Vector3 size = self.GetCurrentProperty<Vector3>(Actor::Property::SIZE);
-
- return FindClosestActorToPosition(Vector3(size.width * 0.5f, size.height * 0.5f, 0.0f));
-}
-
-Actor ScrollView::FindClosestActorToPosition(const Vector3& position, FindDirection dirX, FindDirection dirY, FindDirection dirZ)
-{
- Actor closestChild;
- float closestDistance2 = 0.0f;
- Vector3 actualPosition = position;
-
- unsigned int numChildren = Self().GetChildCount();
-
- for(unsigned int i = 0; i < numChildren; ++i)
- {
- Actor child = Self().GetChildAt(i);
-
- if(mInternalActor == child) // ignore internal actor.
- {
- continue;
- }
-
- Vector3 childPosition = GetPositionOfAnchor(child, AnchorPoint::CENTER);
-
- Vector3 delta = childPosition - actualPosition;
-
- // X-axis checking (only find Actors to the [dirX] of actualPosition)
- if(dirX > All) // != All,None
- {
- FindDirection deltaH = delta.x > 0 ? Right : Left;
- if(dirX != deltaH)
- {
- continue;
- }
- }
-
- // Y-axis checking (only find Actors to the [dirY] of actualPosition)
- if(dirY > All) // != All,None
- {
- FindDirection deltaV = delta.y > 0 ? Down : Up;
- if(dirY != deltaV)
- {
- continue;
- }
- }
-
- // Z-axis checking (only find Actors to the [dirZ] of actualPosition)
- if(dirZ > All) // != All,None
- {
- FindDirection deltaV = delta.y > 0 ? In : Out;
- if(dirZ != deltaV)
- {
- continue;
- }
- }
-
- // compare child to closest child in terms of distance.
- float distance2 = 0.0f;
-
- // distance2 = the Square of the relevant dimensions of delta
- if(dirX != None)
- {
- distance2 += delta.x * delta.x;
- }
-
- if(dirY != None)
- {
- distance2 += delta.y * delta.y;
- }
-
- if(dirZ != None)
- {
- distance2 += delta.z * delta.z;
- }
-
- if(closestChild) // Next time.
- {
- if(distance2 < closestDistance2)
- {
- closestChild = child;
- closestDistance2 = distance2;
- }
- }
- else // First time.
- {
- closestChild = child;
- closestDistance2 = distance2;
- }
- }
-
- return closestChild;
-}
-
-bool ScrollView::ScrollToSnapPoint()
-{
- DALI_LOG_SCROLL_STATE("[0x%X]", this);
- Vector2 stationaryVelocity = Vector2(0.0f, 0.0f);
- return SnapWithVelocity(stationaryVelocity);
-}
-
-// TODO: In situations where axes are different (X snap, Y free)
-// Each axis should really have their own independent animation (time and equation)
-// Consider, X axis snapping to nearest grid point (EaseOut over fixed time)
-// Consider, Y axis simulating physics to arrive at a point (Physics equation over variable time)
-// Currently, the axes have been split however, they both use the same EaseOut equation.
-bool ScrollView::SnapWithVelocity(Vector2 velocity)
-{
- // Animator takes over now, touches are assumed not to interfere.
- // And if touches do interfere, then we'll stop animation, update PrePosition
- // to current mScroll's properties, and then resume.
- // Note: For Flicking this may work a bit different...
-
- float angle = atan2(velocity.y, velocity.x);
- float speed2 = velocity.LengthSquared();
- AlphaFunction alphaFunction = mSnapAlphaFunction;
- Vector2 positionDuration = Vector2::ONE * mSnapDuration;
- float biasX = 0.5f;
- float biasY = 0.5f;
- FindDirection horizontal = None;
- FindDirection vertical = None;
-
- // orthoAngleRange = Angle tolerance within the Exact N,E,S,W direction
- // that will be accepted as a general N,E,S,W flick direction.
-
- const float orthoAngleRange = FLICK_ORTHO_ANGLE_RANGE * M_PI / 180.0f;
- const float flickSpeedThreshold2 = mFlickSpeedThreshold * mFlickSpeedThreshold;
-
- Vector2 positionSnap = mScrollPrePosition;
-
- // Flick logic X Axis
-
- if(mRulerX->IsEnabled() && mLockAxis != LockHorizontal)
- {
- horizontal = All;
-
- if(speed2 > flickSpeedThreshold2 || // exceeds flick threshold
- mInAccessibilityPan) // With AccessibilityPan its easier to move between snap positions
- {
- if((angle >= -orthoAngleRange) && (angle < orthoAngleRange)) // Swiping East
- {
- biasX = 0.0f, horizontal = Left;
-
- // This guards against an error where no movement occurs, due to the flick finishing
- // before the update-thread has advanced mScrollPostPosition past the the previous snap point.
- positionSnap.x += 1.0f;
- }
- else if((angle >= M_PI - orthoAngleRange) || (angle < -M_PI + orthoAngleRange)) // Swiping West
- {
- biasX = 1.0f, horizontal = Right;
-
- // This guards against an error where no movement occurs, due to the flick finishing
- // before the update-thread has advanced mScrollPostPosition past the the previous snap point.
- positionSnap.x -= 1.0f;
- }
- }
- }
-
- // Flick logic Y Axis
+ horizontalBias,
+ verticalBias,
+ SNAP);
- if(mRulerY->IsEnabled() && mLockAxis != LockVertical)
+ if(!animating)
{
- vertical = All;
+ // if not animating, then this pan has completed right now.
+ self.SetProperty(Toolkit::ScrollView::Property::SCROLLING, false);
+ mScrolling = false;
- if(speed2 > flickSpeedThreshold2 || // exceeds flick threshold
- mInAccessibilityPan) // With AccessibilityPan its easier to move between snap positions
+ // If we have no duration, then in the next update frame, we will be at the position specified as we just set.
+ // In this scenario, we cannot return the currentScrollPosition as this is out-of-date and should instead return the requested final position
+ Vector2 completedPosition(currentScrollPosition);
+ if(duration <= Math::MACHINE_EPSILON_10)
{
- if((angle >= M_PI_2 - orthoAngleRange) && (angle < M_PI_2 + orthoAngleRange)) // Swiping South
- {
- biasY = 0.0f, vertical = Up;
- }
- else if((angle >= -M_PI_2 - orthoAngleRange) && (angle < -M_PI_2 + orthoAngleRange)) // Swiping North
- {
- biasY = 1.0f, vertical = Down;
- }
+ completedPosition = position;
}
- }
- // isFlick: Whether this gesture is a flick or not.
- bool isFlick = (horizontal != All || vertical != All);
- // isFreeFlick: Whether this gesture is a flick under free panning criteria.
- bool isFreeFlick = velocity.LengthSquared() > (FREE_FLICK_SPEED_THRESHOLD * FREE_FLICK_SPEED_THRESHOLD);
-
- if(isFlick || isFreeFlick)
- {
- positionDuration = Vector2::ONE * mFlickDuration;
- alphaFunction = mFlickAlphaFunction;
+ DALI_LOG_SCROLL_STATE("[0x%X] mScrollCompletedSignal 2 [%.2f, %.2f]", this, completedPosition.x, completedPosition.y);
+ SetScrollUpdateNotification(false);
+ mScrollCompletedSignal.Emit(completedPosition);
}
+}
- // Calculate next positionSnap ////////////////////////////////////////////////////////////
-
- if(mActorAutoSnapEnabled)
- {
- Vector3 size = Self().GetCurrentProperty<Vector3>(Actor::Property::SIZE);
+void ScrollView::ScrollTo(const Vector2& position)
+{
+ ScrollTo(position, mSnapDuration);
+}
- Actor child = FindClosestActorToPosition(Vector3(size.width * 0.5f, size.height * 0.5f, 0.0f), horizontal, vertical);
+void ScrollView::ScrollTo(const Vector2& position, float duration)
+{
+ ScrollTo(position, duration, DIRECTION_BIAS_NONE, DIRECTION_BIAS_NONE);
+}
- if(!child && isFlick)
- {
- // If we conducted a direction limited search and found no actor, then just snap to the closest actor.
- child = FindClosestActorToPosition(Vector3(size.width * 0.5f, size.height * 0.5f, 0.0f));
- }
+void ScrollView::ScrollTo(const Vector2& position, float duration, AlphaFunction alpha)
+{
+ ScrollTo(position, duration, alpha, DIRECTION_BIAS_NONE, DIRECTION_BIAS_NONE);
+}
- if(child)
- {
- Vector2 position = Self().GetCurrentProperty<Vector2>(Toolkit::ScrollView::Property::SCROLL_POSITION);
+void ScrollView::ScrollTo(const Vector2& position, float duration, DirectionBias horizontalBias, DirectionBias verticalBias)
+{
+ ScrollTo(position, duration, mSnapAlphaFunction, horizontalBias, verticalBias);
+}
- // Get center-point of the Actor.
- Vector3 childPosition = GetPositionOfAnchor(child, AnchorPoint::CENTER);
+void ScrollView::ScrollTo(const Vector2& position, float duration, AlphaFunction alpha, DirectionBias horizontalBias, DirectionBias verticalBias)
+{
+ DALI_LOG_SCROLL_STATE("[0x%X] position[%.2f, %.2f] duration[%.2f], bias[%d, %d]", this, position.x, position.y, duration, int(horizontalBias), int(verticalBias));
+ TransformTo(position, duration, alpha, horizontalBias, verticalBias);
+}
- if(mRulerX->IsEnabled())
- {
- positionSnap.x = position.x - childPosition.x + size.width * 0.5f;
- }
- if(mRulerY->IsEnabled())
- {
- positionSnap.y = position.y - childPosition.y + size.height * 0.5f;
- }
- }
- }
+void ScrollView::ScrollTo(unsigned int page)
+{
+ ScrollTo(page, mSnapDuration);
+}
- Vector2 startPosition = positionSnap;
- positionSnap.x = -mRulerX->Snap(-positionSnap.x, biasX); // NOTE: X & Y rulers think in -ve coordinate system.
- positionSnap.y = -mRulerY->Snap(-positionSnap.y, biasY); // That is scrolling RIGHT (e.g. 100.0, 0.0) means moving LEFT.
+void ScrollView::ScrollTo(unsigned int page, float duration, DirectionBias bias)
+{
+ Vector2 position;
+ unsigned int volume;
+ unsigned int libraries;
- Vector2 clampDelta(Vector2::ZERO);
- ClampPosition(positionSnap);
+ // The position to scroll to is continuous and linear
+ // unless a domain has been enabled on the X axis.
+ // or if WrapMode has been enabled.
+ bool carryX = mRulerX->GetDomain().enabled | mWrapMode;
+ bool carryY = mRulerY->GetDomain().enabled | mWrapMode;
- if((mRulerX->GetType() == Ruler::FREE || mRulerY->GetType() == Ruler::FREE) && isFreeFlick && !mActorAutoSnapEnabled)
- {
- // Calculate target position based on velocity of flick.
+ position.x = mRulerX->GetPositionFromPage(page, volume, carryX);
+ position.y = mRulerY->GetPositionFromPage(volume, libraries, carryY);
- // a = Deceleration (Set to diagonal stage length * friction coefficient)
- // u = Initial Velocity (Flick velocity)
- // v = 0 (Final Velocity)
- // t = Time (Velocity / Deceleration)
- Vector2 stageSize = Stage::GetCurrent().GetSize();
- float stageLength = Vector3(stageSize.x, stageSize.y, 0.0f).Length();
- float a = (stageLength * mFrictionCoefficient);
- Vector3 u = Vector3(velocity.x, velocity.y, 0.0f) * mFlickSpeedCoefficient;
- float speed = u.Length();
- u /= speed;
+ ScrollTo(position, duration, bias, bias);
+}
- // TODO: Change this to a decay function. (faster you flick, the slower it should be)
- speed = std::min(speed, stageLength * mMaxFlickSpeed);
- u *= speed;
- alphaFunction = ConstantDecelerationAlphaFunction;
+void ScrollView::ScrollTo(Actor& actor)
+{
+ ScrollTo(actor, mSnapDuration);
+}
- float t = speed / a;
+void ScrollView::ScrollTo(Actor& actor, float duration)
+{
+ DALI_ASSERT_ALWAYS(actor.GetParent() == Self());
- if(mRulerX->IsEnabled() && mRulerX->GetType() == Ruler::FREE)
- {
- positionSnap.x += t * u.x * 0.5f;
- }
+ Actor self = Self();
+ Vector3 size = self.GetCurrentProperty<Vector3>(Actor::Property::SIZE);
+ Vector3 position = actor.GetCurrentProperty<Vector3>(Actor::Property::POSITION);
+ Vector2 prePosition = GetPropertyPrePosition();
+ position.GetVectorXY() -= prePosition;
- if(mRulerY->IsEnabled() && mRulerY->GetType() == Ruler::FREE)
- {
- positionSnap.y += t * u.y * 0.5f;
- }
+ ScrollTo(Vector2(position.x - size.width * 0.5f, position.y - size.height * 0.5f), duration);
+}
- clampDelta = positionSnap;
- ClampPosition(positionSnap);
- if((positionSnap - startPosition).LengthSquared() > Math::MACHINE_EPSILON_0)
- {
- clampDelta -= positionSnap;
- clampDelta.x = clampDelta.x > 0.0f ? std::min(clampDelta.x, mMaxOvershoot.x) : std::max(clampDelta.x, -mMaxOvershoot.x);
- clampDelta.y = clampDelta.y > 0.0f ? std::min(clampDelta.y, mMaxOvershoot.y) : std::max(clampDelta.y, -mMaxOvershoot.y);
- }
- else
- {
- clampDelta = Vector2::ZERO;
- }
+Actor ScrollView::FindClosestActor()
+{
+ Actor self = Self();
+ Vector3 size = self.GetCurrentProperty<Vector3>(Actor::Property::SIZE);
- // If Axis is Free and has velocity, then calculate time taken
- // to reach target based on velocity in axis.
- if(mRulerX->IsEnabled() && mRulerX->GetType() == Ruler::FREE)
- {
- float deltaX = fabsf(startPosition.x - positionSnap.x);
+ return FindClosestActorToPosition(Vector3(size.width * 0.5f, size.height * 0.5f, 0.0f));
+}
- if(fabsf(u.x) > Math::MACHINE_EPSILON_1)
- {
- positionDuration.x = fabsf(deltaX / u.x);
- }
- else
- {
- positionDuration.x = 0;
- }
- }
+Actor ScrollView::FindClosestActorToPosition(const Vector3& position, FindDirection dirX, FindDirection dirY, FindDirection dirZ)
+{
+ return ::FindClosestActorToPosition(Self(), mInternalActor, position, dirX, dirY, dirZ);
+}
- if(mRulerY->IsEnabled() && mRulerY->GetType() == Ruler::FREE)
- {
- float deltaY = fabsf(startPosition.y - positionSnap.y);
+bool ScrollView::ScrollToSnapPoint()
+{
+ DALI_LOG_SCROLL_STATE("[0x%X]", this);
+ Vector2 stationaryVelocity = Vector2(0.0f, 0.0f);
+ return SnapWithVelocity(stationaryVelocity);
+}
- if(fabsf(u.y) > Math::MACHINE_EPSILON_1)
- {
- positionDuration.y = fabsf(deltaY / u.y);
- }
- else
- {
- positionDuration.y = 0;
- }
- }
- }
+bool ScrollView::SnapWithVelocity(Vector2 velocity)
+{
+ Vector2 positionSnap = mScrollPrePosition;
+ Vector2 positionDuration = Vector2::ONE * mSnapDuration;
+ AlphaFunction alphaFunction = mSnapAlphaFunction;
+ bool isFlick;
+ bool isFreeFlick;
- if(IsOvershootEnabled())
- {
- // Scroll to the end of the overshoot only when overshoot is enabled.
- positionSnap += clampDelta;
- }
+ ::SnapWithVelocity(*this, mRulerX, mRulerY, mLockAxis, velocity, mMaxOvershoot, positionSnap, positionDuration, alphaFunction, mInAccessibilityPan, isFlick, isFreeFlick);
bool animating = AnimateTo(positionSnap, positionDuration, alphaFunction, false, DIRECTION_BIAS_NONE, DIRECTION_BIAS_NONE, isFlick || isFreeFlick ? FLICK : SNAP);
// Position Delta ///////////////////////////////////////////////////////
if(positionChanged)
{
- UpdateMainInternalConstraint();
+ mConstraints.UpdateMainInternalConstraint(*this);
if(mWrapMode && findShortcuts)
{
// In Wrap Mode, the shortest distance is a little less intuitive...
}
}
- UpdateMainInternalConstraint();
+ mConstraints.UpdateMainInternalConstraint(*this);
}
void ScrollView::AddOverlay(Actor actor)
bool ScrollView::AccessibleImpl::ScrollToChild(Actor child)
{
auto scrollView = Dali::Toolkit::ScrollView::DownCast(Self());
- if (Toolkit::GetImpl(scrollView).FindClosestActor() == child)
+ if(Toolkit::GetImpl(scrollView).FindClosestActor() == child)
{
return false;
}
}
}
UpdatePropertyDomain();
- UpdateMainInternalConstraint();
+ mConstraints.UpdateMainInternalConstraint(*this);
if(IsOvershootEnabled())
{
mOvershootIndicator->Reset();
self.SetProperty(Toolkit::ScrollView::Property::PANNING, true);
self.SetProperty(Toolkit::ScrollView::Property::START_PAGE_POSITION, Vector3(position.x, position.y, 0.0f));
- UpdateMainInternalConstraint();
+ mConstraints.UpdateMainInternalConstraint(*this);
Toolkit::ScrollBar scrollBar = mScrollBar.GetHandle();
if(scrollBar && mTransientScrollBar)
{
mPanning = false;
self.SetProperty(Toolkit::ScrollView::Property::PANNING, false);
- if(mScrollMainInternalPrePositionConstraint)
+ if(mConstraints.mScrollMainInternalPrePositionConstraint)
{
- mScrollMainInternalPrePositionConstraint.Remove();
+ mConstraints.mScrollMainInternalPrePositionConstraint.Remove();
}
Toolkit::ScrollBar scrollBar = mScrollBar.GetHandle();
{
Vector3 size = Self().GetCurrentProperty<Vector3>(Actor::Property::SIZE);
- position.x = -mRulerX->Clamp(-position.x, size.width, 1.0f, clamped.x); // NOTE: X & Y rulers think in -ve coordinate system.
- position.y = -mRulerY->Clamp(-position.y, size.height, 1.0f, clamped.y); // That is scrolling RIGHT (e.g. 100.0, 0.0) means moving LEFT.
+ ::ClampPosition(size, mRulerX, mRulerY, position, clamped);
}
void ScrollView::WrapPosition(Vector2& position) const
}
}
-void ScrollView::UpdateMainInternalConstraint()
-{
- // TODO: Only update the constraints which have changed, rather than remove all and add all again.
- // Requires a dali-core ApplyConstraintAt, or a ReplaceConstraint. The former is probably more flexible.
- Actor self = Self();
- PanGestureDetector detector(GetPanGestureDetector());
-
- if(mScrollMainInternalPositionConstraint)
- {
- mScrollMainInternalPositionConstraint.Remove();
- mScrollMainInternalDeltaConstraint.Remove();
- mScrollMainInternalFinalConstraint.Remove();
- mScrollMainInternalRelativeConstraint.Remove();
- mScrollMainInternalDomainConstraint.Remove();
- mScrollMainInternalPrePositionMaxConstraint.Remove();
- }
- if(mScrollMainInternalPrePositionConstraint)
- {
- mScrollMainInternalPrePositionConstraint.Remove();
- }
-
- // TODO: It's probably better to use a local displacement value as this will give a displacement when scrolling just commences
- // but we need to make sure than the gesture system gives displacement since last frame (60Hz), not displacement since last touch event (90Hz).
-
- // 1. First calculate the pre-position (this is the scroll position if no clamping has taken place)
- Vector2 initialPanMask = Vector2(mRulerX->IsEnabled() ? 1.0f : 0.0f, mRulerY->IsEnabled() ? 1.0f : 0.0f);
-
- if(mLockAxis == LockVertical)
- {
- initialPanMask.y = 0.0f;
- }
- else if(mLockAxis == LockHorizontal)
- {
- initialPanMask.x = 0.0f;
- }
-
- if(mPanning)
- {
- mScrollMainInternalPrePositionConstraint = Constraint::New<Vector2>(self,
- Toolkit::ScrollView::Property::SCROLL_PRE_POSITION,
- InternalPrePositionConstraint(mPanStartPosition,
- initialPanMask,
- mAxisAutoLock,
- mAxisAutoLockGradient,
- mLockAxis,
- mMaxOvershoot,
- mRulerX,
- mRulerY));
- mScrollMainInternalPrePositionConstraint.AddSource(Source(detector, PanGestureDetector::Property::LOCAL_POSITION));
- mScrollMainInternalPrePositionConstraint.AddSource(Source(detector, PanGestureDetector::Property::PANNING));
- mScrollMainInternalPrePositionConstraint.AddSource(Source(self, Actor::Property::SIZE));
- mScrollMainInternalPrePositionConstraint.Apply();
- }
-
- // 2. Second calculate the clamped position (actual position)
- mScrollMainInternalPositionConstraint = Constraint::New<Vector2>(self,
- Toolkit::ScrollView::Property::SCROLL_POSITION,
- InternalPositionConstraint(mRulerX->GetDomain(),
- mRulerY->GetDomain(),
- mWrapMode));
- mScrollMainInternalPositionConstraint.AddSource(LocalSource(Toolkit::ScrollView::Property::SCROLL_PRE_POSITION));
- mScrollMainInternalPositionConstraint.AddSource(LocalSource(Toolkit::Scrollable::Property::SCROLL_POSITION_MIN));
- mScrollMainInternalPositionConstraint.AddSource(LocalSource(Toolkit::Scrollable::Property::SCROLL_POSITION_MAX));
- mScrollMainInternalPositionConstraint.AddSource(Source(self, Actor::Property::SIZE));
- mScrollMainInternalPositionConstraint.Apply();
-
- mScrollMainInternalDeltaConstraint = Constraint::New<Vector2>(self, Toolkit::ScrollView::Property::SCROLL_POSITION_DELTA, InternalPositionDeltaConstraint);
- mScrollMainInternalDeltaConstraint.AddSource(LocalSource(Toolkit::ScrollView::Property::SCROLL_POSITION));
- mScrollMainInternalDeltaConstraint.AddSource(LocalSource(Toolkit::ScrollView::Property::SCROLL_DOMAIN_OFFSET));
- mScrollMainInternalDeltaConstraint.Apply();
-
- mScrollMainInternalFinalConstraint = Constraint::New<Vector2>(self, Toolkit::ScrollView::Property::SCROLL_FINAL, InternalFinalConstraint(FinalDefaultAlphaFunction, FinalDefaultAlphaFunction));
- mScrollMainInternalFinalConstraint.AddSource(LocalSource(Toolkit::ScrollView::Property::SCROLL_POSITION));
- mScrollMainInternalFinalConstraint.AddSource(LocalSource(Toolkit::ScrollView::Property::OVERSHOOT_X));
- mScrollMainInternalFinalConstraint.AddSource(LocalSource(Toolkit::ScrollView::Property::OVERSHOOT_Y));
- mScrollMainInternalFinalConstraint.Apply();
-
- mScrollMainInternalRelativeConstraint = Constraint::New<Vector2>(self, Toolkit::Scrollable::Property::SCROLL_RELATIVE_POSITION, InternalRelativePositionConstraint);
- mScrollMainInternalRelativeConstraint.AddSource(LocalSource(Toolkit::ScrollView::Property::SCROLL_POSITION));
- mScrollMainInternalRelativeConstraint.AddSource(LocalSource(Toolkit::Scrollable::Property::SCROLL_POSITION_MIN));
- mScrollMainInternalRelativeConstraint.AddSource(LocalSource(Toolkit::Scrollable::Property::SCROLL_POSITION_MAX));
- mScrollMainInternalRelativeConstraint.AddSource(LocalSource(Actor::Property::SIZE));
- mScrollMainInternalRelativeConstraint.Apply();
-
- mScrollMainInternalDomainConstraint = Constraint::New<Vector2>(self, Toolkit::ScrollView::Property::SCROLL_DOMAIN_SIZE, InternalScrollDomainConstraint);
- mScrollMainInternalDomainConstraint.AddSource(LocalSource(Toolkit::Scrollable::Property::SCROLL_POSITION_MIN));
- mScrollMainInternalDomainConstraint.AddSource(LocalSource(Toolkit::Scrollable::Property::SCROLL_POSITION_MAX));
- mScrollMainInternalDomainConstraint.AddSource(LocalSource(Actor::Property::SIZE));
- mScrollMainInternalDomainConstraint.Apply();
-
- mScrollMainInternalPrePositionMaxConstraint = Constraint::New<Vector2>(self, Toolkit::ScrollView::Property::SCROLL_PRE_POSITION_MAX, InternalPrePositionMaxConstraint);
- mScrollMainInternalPrePositionMaxConstraint.AddSource(LocalSource(Toolkit::Scrollable::Property::SCROLL_POSITION_MAX));
- mScrollMainInternalPrePositionMaxConstraint.AddSource(LocalSource(Actor::Property::SIZE));
- mScrollMainInternalPrePositionMaxConstraint.Apply();
-
- // When panning we want to make sure overshoot values are affected by pre position and post position
- SetOvershootConstraintsEnabled(!mWrapMode);
-}
-
-void ScrollView::SetOvershootConstraintsEnabled(bool enabled)
-{
- Actor self(Self());
- // remove and reset, it may now be in wrong order with the main internal constraints
- if(mScrollMainInternalOvershootXConstraint)
- {
- mScrollMainInternalOvershootXConstraint.Remove();
- mScrollMainInternalOvershootXConstraint.Reset();
- mScrollMainInternalOvershootYConstraint.Remove();
- mScrollMainInternalOvershootYConstraint.Reset();
- }
- if(enabled)
- {
- mScrollMainInternalOvershootXConstraint = Constraint::New<float>(self, Toolkit::ScrollView::Property::OVERSHOOT_X, OvershootXConstraint(mMaxOvershoot.x));
- mScrollMainInternalOvershootXConstraint.AddSource(LocalSource(Toolkit::ScrollView::Property::SCROLL_PRE_POSITION));
- mScrollMainInternalOvershootXConstraint.AddSource(LocalSource(Toolkit::ScrollView::Property::SCROLL_POSITION));
- mScrollMainInternalOvershootXConstraint.AddSource(LocalSource(Toolkit::Scrollable::Property::CAN_SCROLL_HORIZONTAL));
- mScrollMainInternalOvershootXConstraint.Apply();
-
- mScrollMainInternalOvershootYConstraint = Constraint::New<float>(self, Toolkit::ScrollView::Property::OVERSHOOT_Y, OvershootYConstraint(mMaxOvershoot.y));
- mScrollMainInternalOvershootYConstraint.AddSource(LocalSource(Toolkit::ScrollView::Property::SCROLL_PRE_POSITION));
- mScrollMainInternalOvershootYConstraint.AddSource(LocalSource(Toolkit::ScrollView::Property::SCROLL_POSITION));
- mScrollMainInternalOvershootYConstraint.AddSource(LocalSource(Toolkit::Scrollable::Property::CAN_SCROLL_VERTICAL));
- mScrollMainInternalOvershootYConstraint.Apply();
- }
- else
- {
- self.SetProperty(Toolkit::ScrollView::Property::OVERSHOOT_X, 0.0f);
- self.SetProperty(Toolkit::ScrollView::Property::OVERSHOOT_Y, 0.0f);
- }
-}
-
-void ScrollView::SetInternalConstraints()
-{
- // Internal constraints (applied to target ScrollBase Actor itself) /////////
- UpdateMainInternalConstraint();
-
- // User definable constraints to apply to all child actors //////////////////
- Actor self = Self();
-
- // Apply some default constraints to ScrollView & its bound actors
- // Movement + Wrap function
-
- Constraint constraint;
-
- // MoveActor (scrolling)
- constraint = Constraint::New<Vector3>(self, Actor::Property::POSITION, MoveActorConstraint);
- constraint.AddSource(Source(self, Toolkit::ScrollView::Property::SCROLL_POSITION));
- constraint.SetRemoveAction(Constraint::DISCARD);
- ApplyConstraintToBoundActors(constraint);
-
- // WrapActor (wrap functionality)
- constraint = Constraint::New<Vector3>(self, Actor::Property::POSITION, WrapActorConstraint);
- constraint.AddSource(LocalSource(Actor::Property::SCALE));
- constraint.AddSource(LocalSource(Actor::Property::ANCHOR_POINT));
- constraint.AddSource(LocalSource(Actor::Property::SIZE));
- constraint.AddSource(Source(self, Toolkit::Scrollable::Property::SCROLL_POSITION_MIN));
- constraint.AddSource(Source(self, Toolkit::Scrollable::Property::SCROLL_POSITION_MAX));
- constraint.AddSource(Source(self, Toolkit::ScrollView::Property::WRAP));
- constraint.SetRemoveAction(Constraint::DISCARD);
- ApplyConstraintToBoundActors(constraint);
-}
-
void ScrollView::SetProperty(BaseObject* object, Property::Index index, const Property::Value& value)
{
Toolkit::ScrollView scrollView = Toolkit::ScrollView::DownCast(Dali::BaseHandle(object));
SetRulerY(rulerY);
}
+ScrollView::LockAxis GetLockAxis(const Vector2& panDelta, ScrollView::LockAxis currentLockAxis, float lockGradient)
+{
+ if(panDelta.LengthSquared() > AUTOLOCK_AXIS_MINIMUM_DISTANCE2 &&
+ currentLockAxis == ScrollView::LockPossible)
+ {
+ float dx = fabsf(panDelta.x);
+ float dy = fabsf(panDelta.y);
+ if(dx * lockGradient >= dy)
+ {
+ // 0.36:1 gradient to the horizontal (deviate < 20 degrees)
+ currentLockAxis = ScrollView::LockVertical;
+ }
+ else if(dy * lockGradient > dx)
+ {
+ // 0.36:1 gradient to the vertical (deviate < 20 degrees)
+ currentLockAxis = ScrollView::LockHorizontal;
+ }
+ else
+ {
+ currentLockAxis = ScrollView::LockNone;
+ }
+ }
+ return currentLockAxis;
+}
+
} // namespace Internal
} // namespace Toolkit
#include <dali-toolkit/public-api/controls/control-impl.h>
#include <dali-toolkit/public-api/controls/scrollable/scroll-view/scroll-view-effect.h>
#include <dali-toolkit/public-api/controls/scrollable/scroll-view/scroll-view.h>
+#include <dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-impl-constraints.h>
namespace Dali
{
/**
* @copydoc Toolkit::ScrollView::GetScrollSnapAlphaFunction
*/
- AlphaFunction GetScrollSnapAlphaFunction() const;
+ AlphaFunction GetScrollSnapAlphaFunction() const
+ {
+ return mSnapAlphaFunction;
+ }
/**
* @copydoc Toolkit::ScrollView::SetScrollSnapAlphaFunction
*/
- void SetScrollSnapAlphaFunction(AlphaFunction alpha);
+ void SetScrollSnapAlphaFunction(AlphaFunction alpha)
+ {
+ mSnapAlphaFunction = alpha;
+ }
/**
* @copydoc Toolkit::ScrollView::GetScrollFlickAlphaFunction
*/
- AlphaFunction GetScrollFlickAlphaFunction() const;
+ AlphaFunction GetScrollFlickAlphaFunction() const
+ {
+ return mFlickAlphaFunction;
+ }
/**
* @copydoc Toolkit::ScrollView::SetScrollFlickAlphaFunction
*/
- void SetScrollFlickAlphaFunction(AlphaFunction alpha);
+ void SetScrollFlickAlphaFunction(AlphaFunction alpha)
+ {
+ mFlickAlphaFunction = alpha;
+ }
/**
* @copydoc Toolkit::ScrollView::GetScrollSnapDuration
*/
- float GetScrollSnapDuration() const;
+ float GetScrollSnapDuration() const
+ {
+ return mSnapDuration;
+ }
/**
* @copydoc Toolkit::ScrollView::SetScrollSnapDuration
*/
- void SetScrollSnapDuration(float time);
+ void SetScrollSnapDuration(float time)
+ {
+ mSnapDuration = time;
+ }
/**
* @copydoc Toolkit::ScrollView::GetScrollFlickDuration
*/
- float GetScrollFlickDuration() const;
+ float GetScrollFlickDuration() const
+ {
+ return mFlickDuration;
+ }
/**
* @copydoc Toolkit::ScrollView::SetScrollFlickDuration
*/
- void SetScrollFlickDuration(float time);
+ void SetScrollFlickDuration(float time)
+ {
+ mFlickDuration = time;
+ }
/**
* @copydoc Toolkit::ScrollView::ApplyEffect
/**
* @copydoc Toolkit::ScrollView::GetRulerX
*/
- const RulerPtr GetRulerX() const;
+ const RulerPtr GetRulerX() const
+ {
+ return mRulerX;
+ }
/**
* @copydoc Toolkit::ScrollView::GetRulerY
*/
- const RulerPtr GetRulerY() const;
+ const RulerPtr GetRulerY() const
+ {
+ return mRulerY;
+ }
/**
* @copydoc Toolkit::ScrollView::SetRulerX
*
* @return whether the touch sensitivity is true or false.
*/
- bool GetScrollSensitive();
+ bool GetScrollSensitive()
+ {
+ return mSensitive;
+ }
/**
* @copydoc Toolkit::ScrollView::SetScrollSensitive
/**
* @copydoc Toolkit::ScrollView::SetSnapOvershootAlphaFunction
*/
- void SetSnapOvershootAlphaFunction(AlphaFunction alpha);
+ void SetSnapOvershootAlphaFunction(AlphaFunction alpha)
+ {
+ mSnapOvershootAlphaFunction = alpha;
+ }
/**
* Retrieve the duartion of Snap Overshoot animation
*
* @return the duration.
*/
- float GetSnapOvershootDuration();
+ float GetSnapOvershootDuration()
+ {
+ return mSnapOvershootDuration;
+ }
/**
* @copydoc Toolkit::ScrollView::SetSnapOvershootDuration
*/
- void SetSnapOvershootDuration(float duration);
+ void SetSnapOvershootDuration(float duration)
+ {
+ mSnapOvershootDuration = duration;
+ }
/**
* Retrieve whether Actor Auto-Snap mode is enabled or not.
/**
* @copydoc Toolkit::ScrollView::SetActorAutoSnap
*/
- void SetActorAutoSnap(bool enable);
+ void SetActorAutoSnap(bool enable)
+ {
+ mActorAutoSnapEnabled = enable;
+ }
/**
* Enables or Disables Auto Resizing mode for ScrollView contents.
*
* @return Wrap Mode Enabled flag.
*/
- bool GetWrapMode() const;
+ bool GetWrapMode() const
+ {
+ return mWrapMode;
+ }
/**
* @copydoc Toolkit::ScrollView::SetWrapMode
/**
* @copydoc Toolkit::ScrollView::GetScrollupdateDistance
*/
- int GetScrollUpdateDistance() const;
+ int GetScrollUpdateDistance() const
+ {
+ return mScrollUpdateDistance;
+ }
/**
* @copydoc Toolkit::ScrollView::SetScrollUpdateDistance
*/
- void SetScrollUpdateDistance(int distance);
+ void SetScrollUpdateDistance(int distance)
+ {
+ mScrollUpdateDistance = distance;
+ }
/**
* @copydoc Toolkit::ScrollView::GetAxisAutoLock
*/
- bool GetAxisAutoLock() const;
+ bool GetAxisAutoLock() const
+ {
+ return mAxisAutoLock;
+ }
/**
* @copydoc Toolkit::ScrollView::SetAxisAutoLock
/**
* @copydoc Toolkit::ScrollView::GetAxisAutoLockGradient
*/
- float GetAxisAutoLockGradient() const;
+ float GetAxisAutoLockGradient() const
+ {
+ return mAxisAutoLockGradient;
+ }
/**
* @copydoc Toolkit::ScrollView::SetAxisAutoLockGradient
/**
* @copydoc Toolkit::ScrollView::GetFrictionCoefficient
*/
- float GetFrictionCoefficient() const;
+ float GetFrictionCoefficient() const
+ {
+ return mFrictionCoefficient;
+ }
/**
* @copydoc Toolkit::ScrollView::SetFrictionCoefficient
/**
* @copydoc Toolkit::ScrollView::GetFlickSpeedCoefficient
*/
- float GetFlickSpeedCoefficient() const;
+ float GetFlickSpeedCoefficient() const
+ {
+ return mFlickSpeedCoefficient;
+ }
/**
* @copydoc Toolkit::ScrollView::SetFlickSpeedCoefficient
*/
- void SetFlickSpeedCoefficient(float speed);
+ void SetFlickSpeedCoefficient(float speed)
+ {
+ mFlickSpeedCoefficient = speed;
+ }
/**
* @copydoc Toolkit::ScrollView::GetMinimumDistanceForFlick
*/
- Vector2 GetMinimumDistanceForFlick() const;
+ Vector2 GetMinimumDistanceForFlick() const
+ {
+ return mMinFlickDistance;
+ }
/**
* @copydoc Toolkit::ScrollView::SetMinimumDistanceForFlick
*/
- void SetMinimumDistanceForFlick(const Vector2& distance);
+ void SetMinimumDistanceForFlick(const Vector2& distance)
+ {
+ mMinFlickDistance = distance;
+ }
/**
* @copydoc Toolkit::ScrollView::GetMinimumSpeedForFlick
*/
- float GetMinimumSpeedForFlick() const;
+ float GetMinimumSpeedForFlick() const
+ {
+ return mFlickSpeedThreshold;
+ }
/**
* @copydoc Toolkit::ScrollView::SetMinimumSpeedForFlick
*/
- void SetMinimumSpeedForFlick(float speed);
+ void SetMinimumSpeedForFlick(float speed)
+ {
+ mFlickSpeedThreshold = speed;
+ }
/**
* @copydoc Toolkit::ScrollView::GetMaxFlickSpeed
*/
- float GetMaxFlickSpeed() const;
+ float GetMaxFlickSpeed() const
+ {
+ return mMaxFlickSpeed;
+ }
/**
* @copydoc Toolkit::ScrollView::SetMaxFlickSpeed
*/
- void SetMaxFlickSpeed(float speed);
+ void SetMaxFlickSpeed(float speed)
+ {
+ mMaxFlickSpeed = speed;
+ }
/**
* @copydoc Toolkit::ScrollView::GetWheelScrollDistanceStep
*/
- Vector2 GetWheelScrollDistanceStep() const;
+ Vector2 GetWheelScrollDistanceStep() const
+ {
+ return mWheelScrollDistanceStep;
+ }
/**
* @copydoc Toolkit::ScrollView::SetWheelScrollDistanceStep
*/
- void SetWheelScrollDistanceStep(Vector2 step);
+ void SetWheelScrollDistanceStep(Vector2 step)
+ {
+ mWheelScrollDistanceStep = step;
+ }
/**
* @copydoc Toolkit::ScrollView::GetCurrentPage
*/
void WrapPosition(Vector2& position) const;
- /**
- * Updates the main internal scroll constraints with new ruler and domain
- * values
- */
- void UpdateMainInternalConstraint();
-
- /**
- * Enables/disables the overshoot constraints
- *
- * @param[in] enabled whether to enable or disable the overshoot constraints
- */
- void SetOvershootConstraintsEnabled(bool enabled);
-
- /**
- * Sets internal constraints for this ScrollView.
- * Many of these internal constraints are based on properties within
- * ScrollView.
- */
- void SetInternalConstraints();
-
protected:
struct AccessibleImpl : public Scrollable::AccessibleImpl
{
ScrollView& operator=(const ScrollView& rhs);
private:
+ ScrollViewConstraints mConstraints;
+
unsigned long mTouchDownTime; ///< The touch down time
int mGestureStackDepth; ///< How many gestures are currently occuring.
Vector2 mWheelScrollDistanceStep; ///< The step of scroll distance in actor coordinates in X and Y axes for each wheel event received.
- //ScrollInternalConstraintsPtr mScrollInternalConstraints;
- Constraint mScrollMainInternalPrePositionConstraint;
- Constraint mScrollMainInternalPositionConstraint;
- Constraint mScrollMainInternalOvershootXConstraint;
- Constraint mScrollMainInternalOvershootYConstraint;
- Constraint mScrollMainInternalDeltaConstraint;
- Constraint mScrollMainInternalFinalConstraint;
- Constraint mScrollMainInternalRelativeConstraint;
- Constraint mScrollMainInternalDomainConstraint;
- Constraint mScrollMainInternalPrePositionMaxConstraint;
-
ScrollOvershootIndicatorPtr mOvershootIndicator;
WeakHandle<Toolkit::ScrollBar> mScrollBar;
bool mCanScrollHorizontal : 1; ///< Local value of our property to check against
bool mCanScrollVertical : 1; ///< Local value of our property to check against
bool mTransientScrollBar : 1; ///< True if scroll-bar should be automatically show/hidden during/after panning
+
+ friend ScrollViewConstraints;
};
+/**
+ * Returns whether to lock scrolling to a particular axis
+ *
+ * @param[in] panDelta Distance panned since gesture started
+ * @param[in] currentLockAxis The current lock axis value
+ * @param[in] lockGradient How quickly to lock to a particular axis
+ *
+ * @return The new axis lock state
+ */
+ScrollView::LockAxis GetLockAxis(const Vector2& panDelta, ScrollView::LockAxis currentLockAxis, float lockGradient);
+
} // namespace Internal
// Helpers for public-api forwarding methods
// currently not called from code so compiler will optimize these away, kept here for future debugging
#define TABLEVIEW_TAG "DALI Toolkit::TableView "
-#define TV_LOG(fmt, args, ...) Debug::LogMessage(Debug::DebugInfo, TABLEVIEW_TAG fmt, ##args)
+#define TV_LOG(fmt, args, ...) Debug::LogMessageWithFunctionLine(Debug::DebugInfo, TABLEVIEW_TAG fmt, ##args)
//#define TABLEVIEW_DEBUG 1
#if defined(TABLEVIEW_DEBUG)
#include <dali-toolkit/devel-api/controls/web-view/web-context.h>
#include <dali-toolkit/devel-api/controls/web-view/web-cookie-manager.h>
#include <dali-toolkit/devel-api/controls/web-view/web-settings.h>
-#include <dali-toolkit/devel-api/image-loader/texture-manager.h>
#include <dali-toolkit/internal/visuals/visual-factory-impl.h>
#include <dali-toolkit/public-api/image-loader/image.h>
-#include <dali-toolkit/public-api/visuals/image-visual-properties.h>
#include <dali-toolkit/public-api/image-loader/image-url.h>
+#include <dali-toolkit/public-api/visuals/image-visual-properties.h>
namespace Dali
{
return Dali::Toolkit::ImageView();
}
- Dali::Toolkit::ImageUrl url = Dali::Toolkit::Image::GenerateUrl(pixel);
+ Dali::Toolkit::ImageUrl url = Dali::Toolkit::Image::GenerateUrl(pixel);
Dali::Toolkit::ImageView imageView = Dali::Toolkit::ImageView::New(url.GetUrl());
imageView.SetProperty(Dali::Actor::Property::SIZE, Vector2(pixel.GetWidth(), pixel.GetHeight()));
return imageView;
{
mWebEngine.FrameRenderedSignal().Disconnect(this, &WebView::OnInitialFrameRendered);
- Texture texture = Dali::Texture::New(*mWebEngine.GetNativeImageSource());
- const std::string nativeImageUrl = Dali::Toolkit::TextureManager::AddTexture(texture);
- mVisual = Toolkit::VisualFactory::Get().CreateVisual({{Toolkit::Visual::Property::TYPE, Toolkit::Visual::IMAGE}, {Toolkit::ImageVisual::Property::URL, nativeImageUrl}});
+ Dali::Toolkit::ImageUrl nativeImageUrl = Dali::Toolkit::Image::GenerateUrl(mWebEngine.GetNativeImageSource());
+ mVisual = Toolkit::VisualFactory::Get().CreateVisual({{Toolkit::Visual::Property::TYPE, Toolkit::Visual::IMAGE}, {Toolkit::ImageVisual::Property::URL, nativeImageUrl.GetUrl()}});
if(mVisual)
{
${toolkit_src_dir}/controls/scrollable/scroll-view/scroll-overshoot-indicator-impl.cpp
${toolkit_src_dir}/controls/scrollable/scroll-view/scroll-view-effect-impl.cpp
${toolkit_src_dir}/controls/scrollable/scroll-view/scroll-view-impl.cpp
+ ${toolkit_src_dir}/controls/scrollable/scroll-view/scroll-view-impl-constraints.cpp
${toolkit_src_dir}/controls/scrollable/scroll-view/scroll-view-page-path-effect-impl.cpp
${toolkit_src_dir}/controls/scene3d-view/scene3d-view-impl.cpp
${toolkit_src_dir}/controls/scene3d-view/gltf-loader.cpp
{
// potential is inside borderline range.
borderlineOpacity = smoothstep(gMinInlinePotential, gMaxInlinePotential, potential);
+
+ // Muliply borderlineWidth to resolve very thin borderline
+ borderlineOpacity *= min(1.0, borderlineWidth);
}
- lowp vec3 BorderlineColorRGB = borderlineColor.rgb * uActorColor.rgb;
- lowp float BorderlineColorAlpha = borderlineColor.a * uActorColor.a;
+ lowp vec3 borderlineColorRGB = borderlineColor.rgb * uActorColor.rgb;
+ lowp float borderlineColorAlpha = borderlineColor.a * uActorColor.a;
+ // NOTE : color-visual is always not preMultiplied.
- //calculate inside of borderline when outilneColor.a < 1.0
- if(borderlineColor.a < 1.0)
+ // Calculate inside of borderline when alpha is between (0.0 1.0). So we need to apply texture color.
+ // If borderlineOpacity is exactly 0.0, we always use whole texture color. In this case, we don't need to run below code.
+ // But if borderlineOpacity > 0.0 and borderlineColor.a == 0.0, we need to apply tCornerRadius.
+ if(borderlineOpacity > 0.0 && borderlineColor.a * borderlineOpacity < 1.0)
{
mediump float tCornerRadius = -gCenterPosition;
mediump float MaxTexturelinePotential = tCornerRadius + gPotentialRange;
mediump float MinTexturelinePotential = tCornerRadius - gPotentialRange;
if(potential > MaxTexturelinePotential)
{
- // potential is out of texture range. use borderline color instead of texture
- textureColor = vec4(BorderlineColorRGB, 0.0);
+ // potential is out of texture range.
+ textureColor = vec4(0.0);
}
- else if(potential > MinTexturelinePotential)
+ else
{
- // potential is in texture range
- textureColor = mix(textureColor, vec4(BorderlineColorRGB, 0.0), smoothstep(MinTexturelinePotential, MaxTexturelinePotential, potential));
+ // potential is in texture range.
+ lowp float textureAlphaScale = mix(1.0, 0.0, smoothstep(MinTexturelinePotential, MaxTexturelinePotential, potential));
+ textureColor.a *= textureAlphaScale;
+ textureColor.rgb *= textureColor.a;
}
- // TODO : need to fix here when uColor.a = 0.0 and uActorColor.a != 0
- borderlineOpacity *= borderlineColor.a;
- return mix(textureColor, vec4(BorderlineColorRGB, 1.0), borderlineOpacity);
+
+ // NOTE : color-visual is always not preMultiplied.
+ borderlineColorAlpha *= borderlineOpacity;
+ borderlineColorRGB *= borderlineColorAlpha;
+ // We use pre-multiplied color to reduce operations.
+ // In here, textureColor and borderlineColorRGB is pre-multiplied color now.
+
+ // Manual blend operation with premultiplied colors.
+ // Final alpha = borderlineColorAlpha + (1.0 - borderlineColorAlpha) * textureColor.a.
+ // (Final rgb * alpha) = borderlineColorRGB + (1.0 - borderlineColorAlpha) * textureColor.rgb
+ // If preMultipliedAlpha == 1.0, just return vec4(rgb*alpha, alpha)
+ // Else, return vec4((rgb*alpha) / alpha, alpha)
+
+ lowp float finalAlpha = mix(textureColor.a, 1.0, borderlineColorAlpha);
+ lowp vec3 finalMultipliedRGB = borderlineColorRGB + (1.0 - borderlineColorAlpha) * textureColor.rgb;
+ // TODO : Need to find some way without division
+ return vec4(finalMultipliedRGB / finalAlpha, finalAlpha);
}
- return mix(textureColor, vec4(BorderlineColorRGB, BorderlineColorAlpha), borderlineOpacity);
+ return mix(textureColor, vec4(borderlineColorRGB, borderlineColorAlpha), borderlineOpacity);
}
#endif
// solve (v.x - x)^2 + (v.y - x)^2 = (cr / cy * x)^2
#if IS_REQUIRED_ROUNDED_CORNER
- // NOTE : lowspec HW cannot calculate here. need to reduce numeric error
- mediump float A = (cr * cr - 2.0 * cy * cy);
- mediump float B = cy * (v.x + v.y);
- mediump float V = dot(v,v);
- mediump float D = B * B + A * V;
+ // Note : lowspec HW cannot calculate here. need to reduce numeric error
+ highp float A = (cr * cr - 2.0 * cy * cy);
+ highp float B = cy * (v.x + v.y);
+ highp float V = dot(v,v);
+ highp float D = B * B + A * V;
potential = V * (cr + cy) / (sqrt(D) + B);
#else
// We can simplify this value cause cy = 0.8 * blurRadius, cr = 1.2 * blurRadius
// potential = 5.0*(sqrt(4.0*(v.x+v.y)^2 + dot(v,v)) - 2.0*(v.x+v.y));
// = 10.0*(v.x+v.y) * (sqrt(1.0 + (length(v) / (2.0*(v.x+v.y)))^2) - 1.0);
// = 10.0*(v.x+v.y) * (sqrt(1.25 - x + x^2) - 1.0);
- // ~= 10.0*(v.x+v.y) * (0.11803399 - 0.44721360x + 0.35777088x^2 - 0.14310x^3 + O(x^4)) (Taylor series)
+ // ~= 10.0*(v.x+v.y) * (0.11803399 - 0.44721360x + 0.35777088x^2 - 0.14310x^3 + O(x^5)) (Taylor series)
// ~= -1.0557281 * (v.x + v.y) + 2.236068 * length(v) - ~~~ (here, x <= 0.5 * (1.0 - sqrt(0.5)) < 0.1464467)
// Note : This simplify need cause we should use it on lowspec HW.
mediump float x = 0.5 * (1.0 - length(v) / (v.x + v.y));
{
// potential is inside borderline range.
borderlineOpacity = smoothstep(gMinInlinePotential, gMaxInlinePotential, potential);
+
+ // Muliply borderlineWidth to resolve very thin borderline
+ borderlineOpacity *= min(1.0, borderlineWidth);
}
- lowp vec3 BorderlineColorRGB = borderlineColor.rgb * uActorColor.rgb;
- lowp float BorderlineColorAlpha = borderlineColor.a * uActorColor.a;
- // Gradient is always preMultiplied.
- BorderlineColorRGB *= BorderlineColorAlpha;
+ lowp vec3 borderlineColorRGB = borderlineColor.rgb * uActorColor.rgb;
+ lowp float borderlineColorAlpha = borderlineColor.a * uActorColor.a;
+ // NOTE : gradient-visual is always preMultiplied.
+ borderlineColorRGB *= borderlineColorAlpha;
- //calculate inside of borderline when outilneColor.a < 1.0
- if(borderlineColor.a < 1.0)
+ // Calculate inside of borderline when alpha is between (0.0 1.0). So we need to apply texture color.
+ // If borderlineOpacity is exactly 0.0, we always use whole texture color. In this case, we don't need to run below code.
+ // But if borderlineOpacity > 0.0 and borderlineColor.a == 0.0, we need to apply tCornerRadius.
+ if(borderlineOpacity > 0.0 && borderlineColor.a * borderlineOpacity < 1.0)
{
mediump float tCornerRadius = -gCenterPosition;
mediump float MaxTexturelinePotential = tCornerRadius + gPotentialRange;
mediump float MinTexturelinePotential = tCornerRadius - gPotentialRange;
- lowp vec3 BorderlineColorRGB = borderlineColor.xyz * borderlineColor.a;
if(potential > MaxTexturelinePotential)
{
- // potential is out of texture range. use borderline color instead of texture
- textureColor = vec4(BorderlineColorRGB, 0.0);
+ // potential is out of texture range.
+ textureColor = vec4(0.0);
}
- else if(potential > MinTexturelinePotential)
+ else
{
- // potential is in texture range
- textureColor = mix(textureColor, vec4(BorderlineColorRGB, 0.0), smoothstep(MinTexturelinePotential, MaxTexturelinePotential, potential));
+ // potential is in texture range.
+ lowp float textureAlphaScale = mix(1.0, 0.0, smoothstep(MinTexturelinePotential, MaxTexturelinePotential, potential));
+ textureColor.a *= textureAlphaScale;
+ textureColor.rgb *= textureAlphaScale;
}
- // TODO : need to fix here when uColor.a = 0.0 and uActorColor.a != 0
- borderlineOpacity *= borderlineColor.a;
- return mix(textureColor, vec4(BorderlineColorRGB, 1.0), borderlineOpacity);
+
+ // NOTE : gradient-visual is always preMultiplied.
+ borderlineColorAlpha *= borderlineOpacity;
+ borderlineColorRGB *= borderlineOpacity;
+ // We use pre-multiplied color to reduce operations.
+ // In here, textureColor and borderlineColorRGB is pre-multiplied color now.
+
+ // Manual blend operation with premultiplied colors.
+ // Final alpha = borderlineColorAlpha + (1.0 - borderlineColorAlpha) * textureColor.a.
+ // (Final rgb * alpha) = borderlineColorRGB + (1.0 - borderlineColorAlpha) * textureColor.rgb
+ // If preMultipliedAlpha == 1.0, just return vec4(rgb*alpha, alpha)
+ // Else, return vec4((rgb*alpha) / alpha, alpha)
+
+ lowp float finalAlpha = mix(textureColor.a, 1.0, borderlineColorAlpha);
+ lowp vec3 finalMultipliedRGB = borderlineColorRGB + (1.0 - borderlineColorAlpha) * textureColor.rgb;
+ return vec4(finalMultipliedRGB, finalAlpha);
}
- return mix(textureColor, vec4(BorderlineColorRGB, BorderlineColorAlpha), borderlineOpacity);
+ return mix(textureColor, vec4(borderlineColorRGB, borderlineColorAlpha), borderlineOpacity);
}
#endif
vOptRectSize -= 0.2929 * maxRadius + 1.0;
#endif
+ mediump vec4 vertexPosition = vec4(aPosition, 0.0, 1.0);
#if IS_REQUIRED_BORDERLINE
vPosition = aPosition * (visualSize + (1.0 + clamp(borderlineOffset, -1.0, 1.0)) * borderlineWidth);
+ vertexPosition.xy *= (1.0 + (1.0 + clamp(borderlineOffset, -1.0, 1.0)) * borderlineWidth / visualSize);
vOptRectSize -= (1.0 - clamp(borderlineOffset, -1.0, 1.0)) * 0.5 * borderlineWidth + 1.0;
#elif IS_REQUIRED_ROUNDED_CORNER
vPosition = aPosition * visualSize;
mediump vec2 vPosition = aPosition * visualSize;
#endif
+#if USER_SPACE
+ vertexPosition.xyz *= uSize;
+#endif
+
+ vTexCoord = (uAlignmentMatrix*vertexPosition.xyw).xy;
+
return vec4(vPosition + anchorPoint * visualSize + (visualOffset + origin) * uSize.xy, 0.0, 1.0);
}
void main()
{
- mediump vec4 vertexPosition = vec4(aPosition, 0.0, 1.0);
gl_Position = uMvpMatrix * ComputeVertexPosition();
-#if USER_SPACE
- vertexPosition.xyz *= uSize;
-#endif
- vTexCoord = (uAlignmentMatrix*vertexPosition.xyw).xy;
}
{
// potential is inside borderline range.
borderlineOpacity = smoothstep(gMinInlinePotential, gMaxInlinePotential, potential);
+
+ // Muliply borderlineWidth to resolve very thin borderline
+ borderlineOpacity *= min(1.0, borderlineWidth);
}
- lowp vec3 BorderlineColorRGB = borderlineColor.rgb * uActorColor.rgb;
- lowp float BorderlineColorAlpha = borderlineColor.a * uActorColor.a;
- BorderlineColorRGB *= mix(1.0, BorderlineColorAlpha, preMultipliedAlpha);
+ lowp vec3 borderlineColorRGB = borderlineColor.rgb * uActorColor.rgb;
+ lowp float borderlineColorAlpha = borderlineColor.a * uActorColor.a;
+ borderlineColorRGB *= mix(1.0, borderlineColorAlpha, preMultipliedAlpha);
- //calculate inside of borderline when outilneColor.a < 1.0
- if(borderlineColor.a < 1.0)
+ // Calculate inside of borderline when alpha is between (0.0 1.0). So we need to apply texture color.
+ // If borderlineOpacity is exactly 0.0, we always use whole texture color. In this case, we don't need to run below code.
+ // But if borderlineOpacity > 0.0 and borderlineColor.a == 0.0, we need to apply tCornerRadius.
+ if(borderlineOpacity > 0.0 && borderlineColor.a * borderlineOpacity < 1.0)
{
mediump float tCornerRadius = -gCenterPosition;
mediump float MaxTexturelinePotential = tCornerRadius + gPotentialRange;
mediump float MinTexturelinePotential = tCornerRadius - gPotentialRange;
if(potential > MaxTexturelinePotential)
{
- // potential is out of texture range. use borderline color instead of texture
- textureColor = vec4(BorderlineColorRGB, 0.0);
+ // potential is out of texture range.
+ textureColor = vec4(0.0);
}
- else if(potential > MinTexturelinePotential)
+ else
{
- // potential is in texture range
- textureColor = mix(textureColor, vec4(BorderlineColorRGB, 0.0), smoothstep(MinTexturelinePotential, MaxTexturelinePotential, potential));
+ // potential is in texture range.
+ lowp float textureAlphaScale = mix(1.0, 0.0, smoothstep(MinTexturelinePotential, MaxTexturelinePotential, potential));
+ textureColor.a *= textureAlphaScale;
+ textureColor.rgb *= mix(textureColor.a, textureAlphaScale, preMultipliedAlpha);
}
- // TODO : need to fix here when uColor.a = 0.0 and uActorColor.a != 0
- borderlineOpacity *= borderlineColor.a;
- return mix(textureColor, vec4(BorderlineColorRGB, 1.0), borderlineOpacity);
+
+ borderlineColorAlpha *= borderlineOpacity;
+ borderlineColorRGB *= mix(borderlineColorAlpha, borderlineOpacity, preMultipliedAlpha);
+ // We use pre-multiplied color to reduce operations.
+ // In here, textureColor and borderlineColorRGB is pre-multiplied color now.
+
+ // Manual blend operation with premultiplied colors.
+ // Final alpha = borderlineColorAlpha + (1.0 - borderlineColorAlpha) * textureColor.a.
+ // (Final rgb * alpha) = borderlineColorRGB + (1.0 - borderlineColorAlpha) * textureColor.rgb
+ // If preMultipliedAlpha == 1.0, just return vec4(rgb*alpha, alpha)
+ // Else, return vec4((rgb*alpha) / alpha, alpha)
+
+ lowp float finalAlpha = mix(textureColor.a, 1.0, borderlineColorAlpha);
+ lowp vec3 finalMultipliedRGB = borderlineColorRGB + (1.0 - borderlineColorAlpha) * textureColor.rgb;
+ // TODO : Need to find some way without division
+ return vec4(finalMultipliedRGB * mix(1.0 / finalAlpha, 1.0, preMultipliedAlpha), finalAlpha);
}
- return mix(textureColor, vec4(BorderlineColorRGB, BorderlineColorAlpha), borderlineOpacity);
+ return mix(textureColor, vec4(borderlineColorRGB, borderlineColorAlpha), borderlineOpacity);
}
#endif
const char* DEFAULT_TOOLKIT_PACKAGE_PATH = "/toolkit/";
+static constexpr int32_t COUNT_BROKEN_IMAGE_MAX = 3;
+
#if defined(DEBUG_ENABLED)
Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_STYLE");
#endif
// Sound & haptic style
mFeedbackStyle = new FeedbackStyle();
+
+ // Initialize BrokenImages
+ mBrokenImageUrls.assign(COUNT_BROKEN_IMAGE_MAX, "");
}
StyleManager::~StyleManager()
return mControlStyleChangeSignal;
}
+Toolkit::DevelStyleManager::BrokenImageChangedSignalType& StyleManager::BrokenImageChangedSignal()
+{
+ return mBrokenImageChangedSignal;
+}
+
void StyleManager::SetTheme(const std::string& themeFile)
{
bool themeLoaded = false;
return result;
}
+void StyleManager::SetBrokenImageUrl(DevelStyleManager::BrokenImageType brokenImageType, const std::string& brokenImageUrl)
+{
+ int brokenType = static_cast<int>(brokenImageType);
+ mBrokenImageUrls[brokenType] = brokenImageUrl;
+ Toolkit::StyleManager styleManager = StyleManager::Get();
+ mBrokenImageChangedSignal.Emit(styleManager);
+}
+
+std::string StyleManager::GetBrokenImageUrl(DevelStyleManager::BrokenImageType brokenImageType)
+{
+ int brokenType = static_cast<int>(brokenImageType);
+ return mBrokenImageUrls[brokenType];
+}
+
+std::vector<std::string> StyleManager::GetBrokenImageUrlList()
+{
+ // create a list for brokenImage
+ std::vector<std::string> brokenImageUrlList;
+ for(int i = 0; i < COUNT_BROKEN_IMAGE_MAX; i++)
+ {
+ if(!mBrokenImageUrls[i].empty())
+ {
+ brokenImageUrlList.push_back(mBrokenImageUrls[i]);
+ }
+ }
+ return brokenImageUrlList;
+}
+
bool StyleManager::LoadFile(const std::string& filename, std::string& stringOut)
{
DALI_ASSERT_DEBUG(0 != filename.length());
#include <dali-toolkit/devel-api/builder/builder.h>
#include <dali-toolkit/internal/builder/style.h>
#include <dali-toolkit/public-api/styling/style-manager.h>
+#include <dali-toolkit/devel-api/styling/style-manager-devel.h>
namespace Dali
{
const Property::Map GetConfigurations();
/**
+ * @copydoc Toolkit::DevelStyleManager::SetBrokenImageUrl
+ */
+ void SetBrokenImageUrl(DevelStyleManager::BrokenImageType brokenImageType, const std::string& brokenImageUrl);
+
+ /**
+ * @copydoc Toolkit::DevelStyleManager::GetBrokenImageUrl
+ */
+ std::string GetBrokenImageUrl(DevelStyleManager::BrokenImageType brokenImageType);
+
+ /**
+ * @copydoc Toolkit::DevelStyleManager::GetBrokenImageUrlList
+ */
+ std::vector<std::string> GetBrokenImageUrlList();
+
+ /**
* @brief Apply the theme style to a control.
*
* @param[in] control The control to apply style.
*/
Toolkit::StyleManager::StyleChangedSignalType& ControlStyleChangeSignal();
+ /**
+ * This signal is sent to the visual factory following a broken image change.
+ * It should not be exposed in the public API
+ */
+ Toolkit::DevelStyleManager::BrokenImageChangedSignalType& BrokenImageChangedSignal();
+
private:
typedef std::vector<std::string> StringList;
Toolkit::Internal::FeedbackStyle* mFeedbackStyle; ///< Feedback style
+ std::vector<std::string> mBrokenImageUrls; ///< Broken Image Urls received from user
+
// Signals
- Toolkit::StyleManager::StyleChangedSignalType mControlStyleChangeSignal; ///< Emitted when the style( theme/font ) changes for the controls to style themselves
- Toolkit::StyleManager::StyleChangedSignalType mStyleChangedSignal; ///< Emitted after the controls have been styled
+ Toolkit::StyleManager::StyleChangedSignalType mControlStyleChangeSignal; ///< Emitted when the style( theme/font ) changes for the controls to style themselves
+ Toolkit::StyleManager::StyleChangedSignalType mStyleChangedSignal; ///< Emitted after the controls have been styled
+ Toolkit::DevelStyleManager::BrokenImageChangedSignalType mBrokenImageChangedSignal; ///< Emitted after brokenImageChangedSignal
};
} // namespace Internal
// Check if whether is right to left markup and Keeps true if the previous value was true.
currentScriptRun.isRightToLeft = currentScriptRun.isRightToLeft || TextAbstraction::IsRightToLeftMark(character);
- if(TextAbstraction::EMOJI == currentScriptRun.script)
+ // ZWJ, ZWNJ between emojis should be treated as EMOJI.
+ if(TextAbstraction::EMOJI == currentScriptRun.script && !(TextAbstraction::IsZeroWidthJoiner(character) || TextAbstraction::IsZeroWidthNonJoiner(character)))
{
// Emojis doesn't mix well with characters common to all scripts. Insert the emoji run.
scripts.Insert(scripts.Begin() + scriptIndex, currentScriptRun);
Vector<ScriptRun>::ConstIterator scriptRunEndIt = scripts.End();
bool isNewParagraphCharacter = false;
- bool isPreviousEmojiScript = false;
+ bool isPreviousEmojiScript = false;
+ FontId previousEmojiFontId = 0u;
CharacterIndex lastCharacter = startIndex + numberOfCharacters;
for(Length index = startIndex; index < lastCharacter; ++index)
currentFontRun.isBoldRequired = false;
}
+ // ZWJ, ZWNJ between emojis should use the previous emoji font.
+ if(isEmojiScript && (TextAbstraction::IsZeroWidthJoiner(character) || TextAbstraction::IsZeroWidthNonJoiner(character)))
+ {
+ if(0u != previousEmojiFontId)
+ {
+ fontId = previousEmojiFontId;
+ isValidFont = true;
+ }
+ }
+
// If the given font is not valid, it means either:
// - there is no cached font for the current script yet or,
// - the user has set a different font than the default one for the current script or,
} // !isValidFont (2)
} // !isValidFont (1)
+ // Store the font id when the first character is an emoji.
+ if(isEmojiScript && !isPreviousEmojiScript)
+ {
+ if(0u != fontId)
+ {
+ previousEmojiFontId = fontId;
+ }
+ }
+
#ifdef DEBUG_ENABLED
{
Dali::TextAbstraction::FontDescription description;
const std::string EMPTY_STRING("");
-int ConvertPixelToPint(float pixel)
+template<typename Type>
+void EnsureCreated(Type*& object)
{
- unsigned int horizontalDpi = 0u;
- unsigned int verticalDpi = 0u;
- Dali::TextAbstraction::FontClient fontClient = Dali::TextAbstraction::FontClient::Get();
- fontClient.GetDpi(horizontalDpi, verticalDpi);
-
- return (pixel * 72.f) / static_cast<float>(horizontalDpi);
+ if(!object)
+ {
+ object = new Type();
+ }
}
-} // namespace
+template<typename Type>
+void EnsureCreated(std::unique_ptr<Type>& object)
+{
+ if(!object)
+ {
+ object = std::unique_ptr<Type>(new Type());
+ }
+}
-namespace Dali
+template<typename Type, typename Arg1>
+void EnsureCreated(Type*& object, Arg1 arg1)
{
-namespace Toolkit
+ if(!object)
+ {
+ object = new Type(arg1);
+ }
+}
+
+template<typename Type, typename Arg1, typename Arg2>
+void EnsureCreated(Type*& object, Arg1 arg1, Arg2 arg2)
{
-namespace Text
+ if(!object)
+ {
+ object = new Type(arg1, arg2);
+ }
+}
+
+float GetDpi()
{
-// public : Constructor.
+ unsigned int horizontalDpi = 0u;
+ unsigned int verticalDpi = 0u;
+ Dali::TextAbstraction::FontClient fontClient = Dali::TextAbstraction::FontClient::Get();
+ fontClient.GetDpi(horizontalDpi, verticalDpi);
+ return static_cast<float>(horizontalDpi);
+}
-ControllerPtr Controller::New()
+float ConvertPixelToPoint(float pixel)
{
- return ControllerPtr(new Controller());
+ return pixel * 72.0f / GetDpi();
}
-ControllerPtr Controller::New(ControlInterface* controlInterface)
+float ConvertPointToPixel(float point)
{
- return ControllerPtr(new Controller(controlInterface));
+ // Pixel size = Point size * DPI / 72.f
+ return point * GetDpi() / 72.0f;
}
-ControllerPtr Controller::New(ControlInterface* controlInterface,
- EditableControlInterface* editableControlInterface,
- SelectableControlInterface* selectableControlInterface,
- AnchorControlInterface* anchorControlInterface)
+void UpdateCursorPosition(Dali::Toolkit::Text::EventData* eventData)
{
- return ControllerPtr(new Controller(controlInterface,
- editableControlInterface,
- selectableControlInterface,
- anchorControlInterface));
+ if(eventData && Dali::Toolkit::Text::EventData::IsEditingState(eventData->mState))
+ {
+ // Update the cursor position if it's in editing mode
+ eventData->mDecoratorUpdated = true;
+ eventData->mUpdateCursorPosition = true; // Cursor position should be updated when the font size is updated.
+ }
}
-// public : Configure the text controller.
+} // namespace
+
+namespace Dali::Toolkit::Text
+{
void Controller::EnableTextInput(DecoratorPtr decorator, InputMethodContext& inputMethodContext)
{
return;
}
- if(NULL == mImpl->mEventData)
- {
- mImpl->mEventData = new EventData(decorator, inputMethodContext);
- }
+ EnsureCreated(mImpl->mEventData, decorator, inputMethodContext);
}
void Controller::SetGlyphType(TextAbstraction::GlyphType glyphType)
if(mImpl->mLayoutEngine.GetLayout() == Layout::Engine::SINGLE_LINE_BOX)
{
+ mImpl->mOperationsPending = static_cast<OperationsMask>(mImpl->mOperationsPending |
+ LAYOUT |
+ ALIGN |
+ UPDATE_LAYOUT_SIZE |
+ REORDER);
+
if(enable)
{
DALI_LOG_INFO(gLogFilter, Debug::General, "Controller::SetAutoScrollEnabled for SINGLE_LINE_BOX\n");
- mImpl->mOperationsPending = static_cast<OperationsMask>(mImpl->mOperationsPending |
- LAYOUT |
- ALIGN |
- UPDATE_LAYOUT_SIZE |
- UPDATE_DIRECTION |
- REORDER);
+ mImpl->mOperationsPending = static_cast<OperationsMask>(mImpl->mOperationsPending | UPDATE_DIRECTION);
}
else
{
DALI_LOG_INFO(gLogFilter, Debug::General, "Controller::SetAutoScrollEnabled Disabling autoscroll\n");
- mImpl->mOperationsPending = static_cast<OperationsMask>(mImpl->mOperationsPending |
- LAYOUT |
- ALIGN |
- UPDATE_LAYOUT_SIZE |
- REORDER);
}
mImpl->mIsAutoScrollEnabled = enable;
float Controller::GetAutoScrollLineAlignment() const
{
float offset = 0.f;
-
- if(mImpl->mModel->mVisualModel &&
- (0u != mImpl->mModel->mVisualModel->mLines.Count()))
+ if(mImpl->mModel->mVisualModel && (0u != mImpl->mModel->mVisualModel->mLines.Count()))
{
offset = (*mImpl->mModel->mVisualModel->mLines.Begin()).alignmentOffset;
}
-
return offset;
}
void Controller::SetHorizontalScrollEnabled(bool enable)
{
- if((NULL != mImpl->mEventData) &&
- mImpl->mEventData->mDecorator)
+ if(mImpl->mEventData && mImpl->mEventData->mDecorator)
{
mImpl->mEventData->mDecorator->SetHorizontalScrollEnabled(enable);
}
}
+
bool Controller::IsHorizontalScrollEnabled() const
{
- if((NULL != mImpl->mEventData) &&
- mImpl->mEventData->mDecorator)
- {
- return mImpl->mEventData->mDecorator->IsHorizontalScrollEnabled();
- }
-
- return false;
+ return mImpl->mEventData && mImpl->mEventData->mDecorator && mImpl->mEventData->mDecorator->IsHorizontalScrollEnabled();
}
void Controller::SetVerticalScrollEnabled(bool enable)
{
- if((NULL != mImpl->mEventData) &&
- mImpl->mEventData->mDecorator)
+ if(mImpl->mEventData && mImpl->mEventData->mDecorator)
{
- if(mImpl->mEventData->mDecorator)
- {
- mImpl->mEventData->mDecorator->SetVerticalScrollEnabled(enable);
- }
+ mImpl->mEventData->mDecorator->SetVerticalScrollEnabled(enable);
}
}
bool Controller::IsVerticalScrollEnabled() const
{
- if((NULL != mImpl->mEventData) &&
- mImpl->mEventData->mDecorator)
- {
- return mImpl->mEventData->mDecorator->IsVerticalScrollEnabled();
- }
-
- return false;
+ return mImpl->mEventData && mImpl->mEventData->mDecorator && mImpl->mEventData->mDecorator->IsVerticalScrollEnabled();
}
void Controller::SetSmoothHandlePanEnabled(bool enable)
{
- if((NULL != mImpl->mEventData) &&
- mImpl->mEventData->mDecorator)
+ if(mImpl->mEventData && mImpl->mEventData->mDecorator)
{
mImpl->mEventData->mDecorator->SetSmoothHandlePanEnabled(enable);
}
bool Controller::IsSmoothHandlePanEnabled() const
{
- if((NULL != mImpl->mEventData) &&
- mImpl->mEventData->mDecorator)
- {
- return mImpl->mEventData->mDecorator->IsSmoothHandlePanEnabled();
- }
-
- return false;
+ return mImpl->mEventData && mImpl->mEventData->mDecorator && mImpl->mEventData->mDecorator->IsSmoothHandlePanEnabled();
}
void Controller::SetMaximumNumberOfCharacters(Length maxCharacters)
{
DALI_ASSERT_DEBUG(NULL != mImpl->mEventData && "TextInput disabled");
- if(NULL != mImpl->mEventData)
+ if(mImpl->mEventData)
{
mImpl->mEventData->mCursorBlinkEnabled = enable;
- if(!enable &&
- mImpl->mEventData->mDecorator)
+ if(!enable && mImpl->mEventData->mDecorator)
{
mImpl->mEventData->mDecorator->StopCursorBlink();
}
bool Controller::GetEnableCursorBlink() const
{
- if(NULL != mImpl->mEventData)
- {
- return mImpl->mEventData->mCursorBlinkEnabled;
- }
-
- return false;
+ return mImpl->mEventData && mImpl->mEventData->mCursorBlinkEnabled;
}
void Controller::SetMultiLineEnabled(bool enable)
{
// Set the alignment.
mImpl->mModel->mVerticalAlignment = alignment;
-
mImpl->mOperationsPending = static_cast<OperationsMask>(mImpl->mOperationsPending | ALIGN);
-
mImpl->RequestRelayout();
}
}
void Controller::SetTextFitMinSize(float minSize, FontSizeType type)
{
- switch(type)
- {
- case POINT_SIZE:
- {
- mImpl->mTextFitMinSize = minSize;
- break;
- }
- case PIXEL_SIZE:
- {
- mImpl->mTextFitMinSize = ConvertPixelToPint(minSize);
- break;
- }
- }
+ mImpl->mTextFitMinSize = (type == POINT_SIZE) ? minSize : ConvertPixelToPoint(minSize);
}
float Controller::GetTextFitMinSize() const
void Controller::SetTextFitMaxSize(float maxSize, FontSizeType type)
{
- switch(type)
- {
- case POINT_SIZE:
- {
- mImpl->mTextFitMaxSize = maxSize;
- break;
- }
- case PIXEL_SIZE:
- {
- mImpl->mTextFitMaxSize = ConvertPixelToPint(maxSize);
- break;
- }
- }
+ mImpl->mTextFitMaxSize = (type == POINT_SIZE) ? maxSize : ConvertPixelToPoint(maxSize);
}
float Controller::GetTextFitMaxSize() const
void Controller::SetTextFitStepSize(float step, FontSizeType type)
{
- switch(type)
- {
- case POINT_SIZE:
- {
- mImpl->mTextFitStepSize = step;
- break;
- }
- case PIXEL_SIZE:
- {
- mImpl->mTextFitStepSize = ConvertPixelToPint(step);
- break;
- }
- }
+ mImpl->mTextFitStepSize = (type == POINT_SIZE) ? step : ConvertPixelToPoint(step);
}
float Controller::GetTextFitStepSize() const
return mImpl->mEventData->mGrabHandlePopupEnabled;
}
-// public : Update
-
void Controller::SetText(const std::string& text)
{
TextUpdater::SetText(*this, text);
mImpl->SendSelectionToClipboard(deleteAfterSending);
}
-// public : Default style & Input style
-
void Controller::SetDefaultFontFamily(const std::string& defaultFontFamily)
{
- if(NULL == mImpl->mFontDefaults)
- {
- mImpl->mFontDefaults = new FontDefaults();
- }
+ EnsureCreated(mImpl->mFontDefaults);
mImpl->mFontDefaults->mFontDescription.family = defaultFontFamily;
DALI_LOG_INFO(gLogFilter, Debug::General, "Controller::SetDefaultFontFamily %s\n", defaultFontFamily.c_str());
mImpl->mFontDefaults->familyDefined = !defaultFontFamily.empty();
- if(mImpl->mEventData)
- {
- // Update the cursor position if it's in editing mode
- if(EventData::IsEditingState(mImpl->mEventData->mState))
- {
- mImpl->mEventData->mDecoratorUpdated = true;
- mImpl->mEventData->mUpdateCursorPosition = true; // Cursor position should be updated when the font family is updated.
- }
- }
+ // Update the cursor position if it's in editing mode
+ UpdateCursorPosition(mImpl->mEventData);
// Clear the font-specific data
ClearFontData();
const std::string& Controller::GetDefaultFontFamily() const
{
- if(NULL != mImpl->mFontDefaults)
- {
- return mImpl->mFontDefaults->mFontDescription.family;
- }
-
- return EMPTY_STRING;
+ return mImpl->mFontDefaults ? mImpl->mFontDefaults->mFontDescription.family : EMPTY_STRING;
}
void Controller::SetPlaceholderFontFamily(const std::string& placeholderTextFontFamily)
void Controller::SetDefaultFontWeight(FontWeight weight)
{
- if(NULL == mImpl->mFontDefaults)
- {
- mImpl->mFontDefaults = new FontDefaults();
- }
+ EnsureCreated(mImpl->mFontDefaults);
mImpl->mFontDefaults->mFontDescription.weight = weight;
mImpl->mFontDefaults->weightDefined = true;
- if(mImpl->mEventData)
- {
- // Update the cursor position if it's in editing mode
- if(EventData::IsEditingState(mImpl->mEventData->mState))
- {
- mImpl->mEventData->mDecoratorUpdated = true;
- mImpl->mEventData->mUpdateCursorPosition = true; // Cursor position should be updated when the font weight is updated.
- }
- }
+ // Update the cursor position if it's in editing mode
+ UpdateCursorPosition(mImpl->mEventData);
// Clear the font-specific data
ClearFontData();
bool Controller::IsDefaultFontWeightDefined() const
{
- if(NULL != mImpl->mFontDefaults)
- {
- return mImpl->mFontDefaults->weightDefined;
- }
-
- return false;
+ return mImpl->mFontDefaults && mImpl->mFontDefaults->weightDefined;
}
FontWeight Controller::GetDefaultFontWeight() const
{
- if(NULL != mImpl->mFontDefaults)
- {
- return mImpl->mFontDefaults->mFontDescription.weight;
- }
-
- return TextAbstraction::FontWeight::NORMAL;
+ return mImpl->mFontDefaults ? mImpl->mFontDefaults->mFontDescription.weight : TextAbstraction::FontWeight::NORMAL;
}
void Controller::SetPlaceholderTextFontWeight(FontWeight weight)
bool Controller::IsPlaceholderTextFontWeightDefined() const
{
return PlaceholderHandler::IsPlaceholderTextFontWeightDefined(*this);
- ;
}
FontWeight Controller::GetPlaceholderTextFontWeight() const
void Controller::SetDefaultFontWidth(FontWidth width)
{
- if(NULL == mImpl->mFontDefaults)
- {
- mImpl->mFontDefaults = new FontDefaults();
- }
+ EnsureCreated(mImpl->mFontDefaults);
mImpl->mFontDefaults->mFontDescription.width = width;
mImpl->mFontDefaults->widthDefined = true;
- if(mImpl->mEventData)
- {
- // Update the cursor position if it's in editing mode
- if(EventData::IsEditingState(mImpl->mEventData->mState))
- {
- mImpl->mEventData->mDecoratorUpdated = true;
- mImpl->mEventData->mUpdateCursorPosition = true; // Cursor position should be updated when the font width is updated.
- }
- }
+ // Update the cursor position if it's in editing mode
+ UpdateCursorPosition(mImpl->mEventData);
// Clear the font-specific data
ClearFontData();
bool Controller::IsDefaultFontWidthDefined() const
{
- if(NULL != mImpl->mFontDefaults)
- {
- return mImpl->mFontDefaults->widthDefined;
- }
-
- return false;
+ return mImpl->mFontDefaults && mImpl->mFontDefaults->widthDefined;
}
FontWidth Controller::GetDefaultFontWidth() const
{
- if(NULL != mImpl->mFontDefaults)
- {
- return mImpl->mFontDefaults->mFontDescription.width;
- }
-
- return TextAbstraction::FontWidth::NORMAL;
+ return mImpl->mFontDefaults ? mImpl->mFontDefaults->mFontDescription.width : TextAbstraction::FontWidth::NORMAL;
}
void Controller::SetPlaceholderTextFontWidth(FontWidth width)
void Controller::SetDefaultFontSlant(FontSlant slant)
{
- if(NULL == mImpl->mFontDefaults)
- {
- mImpl->mFontDefaults = new FontDefaults();
- }
+ EnsureCreated(mImpl->mFontDefaults);
mImpl->mFontDefaults->mFontDescription.slant = slant;
mImpl->mFontDefaults->slantDefined = true;
- if(mImpl->mEventData)
- {
- // Update the cursor position if it's in editing mode
- if(EventData::IsEditingState(mImpl->mEventData->mState))
- {
- mImpl->mEventData->mDecoratorUpdated = true;
- mImpl->mEventData->mUpdateCursorPosition = true; // Cursor position should be updated when the font slant is updated.
- }
- }
+ // Update the cursor position if it's in editing mode
+ UpdateCursorPosition(mImpl->mEventData);
// Clear the font-specific data
ClearFontData();
bool Controller::IsDefaultFontSlantDefined() const
{
- if(NULL != mImpl->mFontDefaults)
- {
- return mImpl->mFontDefaults->slantDefined;
- }
- return false;
+ return mImpl->mFontDefaults && mImpl->mFontDefaults->slantDefined;
}
FontSlant Controller::GetDefaultFontSlant() const
{
- if(NULL != mImpl->mFontDefaults)
- {
- return mImpl->mFontDefaults->mFontDescription.slant;
- }
-
- return TextAbstraction::FontSlant::NORMAL;
+ return mImpl->mFontDefaults ? mImpl->mFontDefaults->mFontDescription.slant : TextAbstraction::FontSlant::NORMAL;
}
void Controller::SetPlaceholderTextFontSlant(FontSlant slant)
{
mImpl->mFontSizeScale = scale;
- if(mImpl->mEventData)
- {
- // Update the cursor position if it's in editing mode
- if(EventData::IsEditingState(mImpl->mEventData->mState))
- {
- mImpl->mEventData->mDecoratorUpdated = true;
- mImpl->mEventData->mUpdateCursorPosition = true; // Cursor position should be updated when the font size is updated.
- }
- }
+ // Update the cursor position if it's in editing mode
+ UpdateCursorPosition(mImpl->mEventData);
// Clear the font-specific data
ClearFontData();
float Controller::GetFontSizeScale() const
{
- if(nullptr != mImpl->mFontDefaults)
- {
- return mImpl->mFontSizeScale;
- }
-
- return 1.f;
+ return mImpl->mFontDefaults ? mImpl->mFontSizeScale : 1.0f;
}
void Controller::SetDefaultFontSize(float fontSize, FontSizeType type)
{
- if(NULL == mImpl->mFontDefaults)
- {
- mImpl->mFontDefaults = new FontDefaults();
- }
+ EnsureCreated(mImpl->mFontDefaults);
- switch(type)
- {
- case POINT_SIZE:
- {
- mImpl->mFontDefaults->mDefaultPointSize = fontSize;
- mImpl->mFontDefaults->sizeDefined = true;
- break;
- }
- case PIXEL_SIZE:
- {
- // Point size = Pixel size * 72.f / DPI
- unsigned int horizontalDpi = 0u;
- unsigned int verticalDpi = 0u;
- TextAbstraction::FontClient fontClient = TextAbstraction::FontClient::Get();
- fontClient.GetDpi(horizontalDpi, verticalDpi);
-
- mImpl->mFontDefaults->mDefaultPointSize = (fontSize * 72.f) / static_cast<float>(horizontalDpi);
- mImpl->mFontDefaults->sizeDefined = true;
- break;
- }
- }
+ mImpl->mFontDefaults->mDefaultPointSize = (type == POINT_SIZE) ? fontSize : ConvertPixelToPoint(fontSize);
+ mImpl->mFontDefaults->sizeDefined = true;
- if(mImpl->mEventData)
- {
- // Update the cursor position if it's in editing mode
- if(EventData::IsEditingState(mImpl->mEventData->mState))
- {
- mImpl->mEventData->mDecoratorUpdated = true;
- mImpl->mEventData->mUpdateCursorPosition = true; // Cursor position should be updated when the font size is updated.
- }
- }
+ // Update the cursor position if it's in editing mode
+ UpdateCursorPosition(mImpl->mEventData);
// Clear the font-specific data
ClearFontData();
float Controller::GetDefaultFontSize(FontSizeType type) const
{
- float value = 0.0f;
- if(NULL != mImpl->mFontDefaults)
+ if(mImpl->mFontDefaults)
{
- switch(type)
- {
- case POINT_SIZE:
- {
- value = mImpl->mFontDefaults->mDefaultPointSize;
- break;
- }
- case PIXEL_SIZE:
- {
- // Pixel size = Point size * DPI / 72.f
- unsigned int horizontalDpi = 0u;
- unsigned int verticalDpi = 0u;
- TextAbstraction::FontClient fontClient = TextAbstraction::FontClient::Get();
- fontClient.GetDpi(horizontalDpi, verticalDpi);
-
- value = mImpl->mFontDefaults->mDefaultPointSize * static_cast<float>(horizontalDpi) / 72.f;
- break;
- }
- }
- return value;
+ return (type == POINT_SIZE) ? mImpl->mFontDefaults->mDefaultPointSize : ConvertPointToPixel(mImpl->mFontDefaults->mDefaultPointSize);
}
-
- return value;
+ return 0.0f;
}
void Controller::SetPlaceholderTextFontSize(float fontSize, FontSizeType type)
if(!mImpl->IsShowingPlaceholderText())
{
mImpl->mModel->mVisualModel->SetTextColor(color);
-
mImpl->mModel->mLogicalModel->mColorRuns.Clear();
-
mImpl->mOperationsPending = static_cast<OperationsMask>(mImpl->mOperationsPending | COLOR);
-
mImpl->RequestRelayout();
}
}
void Controller::SetShadowOffset(const Vector2& shadowOffset)
{
mImpl->mModel->mVisualModel->SetShadowOffset(shadowOffset);
-
mImpl->RequestRelayout();
}
void Controller::SetShadowColor(const Vector4& shadowColor)
{
mImpl->mModel->mVisualModel->SetShadowColor(shadowColor);
-
mImpl->RequestRelayout();
}
if(fabsf(GetShadowBlurRadius() - shadowBlurRadius) > Math::MACHINE_EPSILON_1)
{
mImpl->mModel->mVisualModel->SetShadowBlurRadius(shadowBlurRadius);
-
mImpl->RequestRelayout();
}
}
void Controller::SetUnderlineColor(const Vector4& color)
{
mImpl->mModel->mVisualModel->SetUnderlineColor(color);
-
mImpl->RequestRelayout();
}
void Controller::SetUnderlineEnabled(bool enabled)
{
mImpl->mModel->mVisualModel->SetUnderlineEnabled(enabled);
-
mImpl->RequestRelayout();
}
void Controller::SetUnderlineHeight(float height)
{
mImpl->mModel->mVisualModel->SetUnderlineHeight(height);
-
mImpl->RequestRelayout();
}
void Controller::SetOutlineColor(const Vector4& color)
{
mImpl->mModel->mVisualModel->SetOutlineColor(color);
-
mImpl->RequestRelayout();
}
void Controller::SetOutlineWidth(uint16_t width)
{
mImpl->mModel->mVisualModel->SetOutlineWidth(width);
-
mImpl->RequestRelayout();
}
void Controller::SetBackgroundColor(const Vector4& color)
{
mImpl->mModel->mVisualModel->SetBackgroundColor(color);
-
mImpl->RequestRelayout();
}
void Controller::SetBackgroundEnabled(bool enabled)
{
mImpl->mModel->mVisualModel->SetBackgroundEnabled(enabled);
-
mImpl->RequestRelayout();
}
void Controller::SetDefaultEmbossProperties(const std::string& embossProperties)
{
- if(NULL == mImpl->mEmbossDefaults)
- {
- mImpl->mEmbossDefaults = new EmbossDefaults();
- }
-
+ EnsureCreated(mImpl->mEmbossDefaults);
mImpl->mEmbossDefaults->properties = embossProperties;
}
const std::string& Controller::GetDefaultEmbossProperties() const
{
- if(NULL != mImpl->mEmbossDefaults)
- {
- return mImpl->mEmbossDefaults->properties;
- }
-
- return EMPTY_STRING;
+ return mImpl->mEmbossDefaults ? mImpl->mEmbossDefaults->properties : EMPTY_STRING;
}
void Controller::SetDefaultOutlineProperties(const std::string& outlineProperties)
{
- if(NULL == mImpl->mOutlineDefaults)
- {
- mImpl->mOutlineDefaults = new OutlineDefaults();
- }
-
+ EnsureCreated(mImpl->mOutlineDefaults);
mImpl->mOutlineDefaults->properties = outlineProperties;
}
const std::string& Controller::GetDefaultOutlineProperties() const
{
- if(NULL != mImpl->mOutlineDefaults)
- {
- return mImpl->mOutlineDefaults->properties;
- }
-
- return EMPTY_STRING;
+ return mImpl->mOutlineDefaults ? mImpl->mOutlineDefaults->properties : EMPTY_STRING;
}
void Controller::RelayoutForNewLineSize()
mImpl->mOperationsPending = static_cast<OperationsMask>(mImpl->mOperationsPending | LAYOUT);
//remove selection
- if((mImpl->mEventData != nullptr) && (mImpl->mEventData->mState == EventData::SELECTING))
+ if(mImpl->mEventData && mImpl->mEventData->mState == EventData::SELECTING)
{
mImpl->ChangeState(EventData::EDITING);
}
void Controller::SetInputColor(const Vector4& color)
{
- if(NULL != mImpl->mEventData)
+ if(mImpl->mEventData)
{
mImpl->mEventData->mInputStyle.textColor = color;
mImpl->mEventData->mInputStyle.isDefaultColor = false;
const Vector4& Controller::GetInputColor() const
{
- if(NULL != mImpl->mEventData)
- {
- return mImpl->mEventData->mInputStyle.textColor;
- }
-
- // Return the default text's color if there is no EventData.
- return mImpl->mTextColor;
+ // Return event text input color if we have it, otherwise just return the default text's color
+ return mImpl->mEventData ? mImpl->mEventData->mInputStyle.textColor : mImpl->mTextColor;
}
void Controller::SetInputFontFamily(const std::string& fontFamily)
void Controller::SetInputLineSpacing(float lineSpacing)
{
- if(NULL != mImpl->mEventData)
+ if(mImpl->mEventData)
{
mImpl->mEventData->mInputStyle.lineSpacing = lineSpacing;
mImpl->mEventData->mInputStyle.isLineSpacingDefined = true;
float Controller::GetInputLineSpacing() const
{
- if(NULL != mImpl->mEventData)
- {
- return mImpl->mEventData->mInputStyle.lineSpacing;
- }
-
- return 0.f;
+ return mImpl->mEventData ? mImpl->mEventData->mInputStyle.lineSpacing : 0.0f;
}
void Controller::SetInputShadowProperties(const std::string& shadowProperties)
{
- if(NULL != mImpl->mEventData)
+ if(mImpl->mEventData)
{
mImpl->mEventData->mInputStyle.shadowProperties = shadowProperties;
}
const std::string& Controller::GetInputShadowProperties() const
{
- if(NULL != mImpl->mEventData)
- {
- return mImpl->mEventData->mInputStyle.shadowProperties;
- }
-
- return EMPTY_STRING;
+ return mImpl->mEventData ? mImpl->mEventData->mInputStyle.shadowProperties : EMPTY_STRING;
}
void Controller::SetInputUnderlineProperties(const std::string& underlineProperties)
{
- if(NULL != mImpl->mEventData)
+ if(mImpl->mEventData)
{
mImpl->mEventData->mInputStyle.underlineProperties = underlineProperties;
}
const std::string& Controller::GetInputUnderlineProperties() const
{
- if(NULL != mImpl->mEventData)
- {
- return mImpl->mEventData->mInputStyle.underlineProperties;
- }
-
- return EMPTY_STRING;
+ return mImpl->mEventData ? mImpl->mEventData->mInputStyle.underlineProperties : EMPTY_STRING;
}
void Controller::SetInputEmbossProperties(const std::string& embossProperties)
{
- if(NULL != mImpl->mEventData)
+ if(mImpl->mEventData)
{
mImpl->mEventData->mInputStyle.embossProperties = embossProperties;
}
const std::string& Controller::GetInputEmbossProperties() const
{
- if(NULL != mImpl->mEventData)
- {
- return mImpl->mEventData->mInputStyle.embossProperties;
- }
-
- return GetDefaultEmbossProperties();
+ return mImpl->mEventData ? mImpl->mEventData->mInputStyle.embossProperties : GetDefaultEmbossProperties();
}
void Controller::SetInputOutlineProperties(const std::string& outlineProperties)
{
- if(NULL != mImpl->mEventData)
+ if(mImpl->mEventData)
{
mImpl->mEventData->mInputStyle.outlineProperties = outlineProperties;
}
const std::string& Controller::GetInputOutlineProperties() const
{
- if(NULL != mImpl->mEventData)
- {
- return mImpl->mEventData->mInputStyle.outlineProperties;
- }
-
- return GetDefaultOutlineProperties();
+ return mImpl->mEventData ? mImpl->mEventData->mInputStyle.outlineProperties : GetDefaultOutlineProperties();
}
void Controller::SetInputModePassword(bool passwordInput)
{
- if(NULL != mImpl->mEventData)
+ if(mImpl->mEventData)
{
mImpl->mEventData->mPasswordInput = passwordInput;
}
bool Controller::IsInputModePassword()
{
- if(NULL != mImpl->mEventData)
- {
- return mImpl->mEventData->mPasswordInput;
- }
- return false;
+ return mImpl->mEventData && mImpl->mEventData->mPasswordInput;
}
void Controller::SetNoTextDoubleTapAction(NoTextTap::Action action)
{
- if(NULL != mImpl->mEventData)
+ if(mImpl->mEventData)
{
mImpl->mEventData->mDoubleTapAction = action;
}
Controller::NoTextTap::Action Controller::GetNoTextDoubleTapAction() const
{
- NoTextTap::Action action = NoTextTap::NO_ACTION;
-
- if(NULL != mImpl->mEventData)
- {
- action = mImpl->mEventData->mDoubleTapAction;
- }
-
- return action;
+ return mImpl->mEventData ? mImpl->mEventData->mDoubleTapAction : NoTextTap::NO_ACTION;
}
void Controller::SetNoTextLongPressAction(NoTextTap::Action action)
{
- if(NULL != mImpl->mEventData)
+ if(mImpl->mEventData)
{
mImpl->mEventData->mLongPressAction = action;
}
Controller::NoTextTap::Action Controller::GetNoTextLongPressAction() const
{
- NoTextTap::Action action = NoTextTap::NO_ACTION;
-
- if(NULL != mImpl->mEventData)
- {
- action = mImpl->mEventData->mLongPressAction;
- }
-
- return action;
+ return mImpl->mEventData ? mImpl->mEventData->mLongPressAction : NoTextTap::NO_ACTION;
}
bool Controller::IsUnderlineSetByString()
mImpl->mFontStyleSetByString = setByString;
}
-// public : Queries & retrieves.
-
Layout::Engine& Controller::GetLayoutEngine()
{
return mImpl->mLayoutEngine;
int Controller::GetLineCount(float width)
{
GetHeightForWidth(width);
- int numberofLines = mImpl->mModel->GetNumberOfLines();
- return numberofLines;
+ return mImpl->mModel->GetNumberOfLines();
}
const ModelInterface* const Controller::GetTextModel() const
void Controller::SetHiddenInputOption(const Property::Map& options)
{
- if(NULL == mImpl->mHiddenInput)
- {
- mImpl->mHiddenInput = new HiddenText(this);
- }
+ EnsureCreated<HiddenText, Controller*>(mImpl->mHiddenInput, this);
mImpl->mHiddenInput->SetProperties(options);
}
void Controller::GetHiddenInputOption(Property::Map& options)
{
- if(NULL != mImpl->mHiddenInput)
+ if(mImpl->mHiddenInput)
{
mImpl->mHiddenInput->GetProperties(options);
}
void Controller::SetInputFilterOption(const Property::Map& options)
{
- if(!mImpl->mInputFilter)
- {
- mImpl->mInputFilter = std::unique_ptr<InputFilter>(new InputFilter());
- }
+ EnsureCreated(mImpl->mInputFilter);
mImpl->mInputFilter->SetProperties(options);
}
void Controller::GetInputFilterOption(Property::Map& options)
{
- if(NULL != mImpl->mInputFilter)
+ if(mImpl->mInputFilter)
{
mImpl->mInputFilter->GetProperties(options);
}
mImpl->mModel->mVisualModel->SetEllipsisPosition(ellipsisPosition);
}
-// public : Relayout.
-
Controller::UpdateTextType Controller::Relayout(const Size& size, Dali::LayoutDirection::Type layoutDirection)
{
return Relayouter::Relayout(*this, size, layoutDirection);
mImpl->RequestRelayout();
}
-// public : Input style change signals.
-
bool Controller::IsInputStyleChangedSignalsQueueEmpty()
{
return (NULL == mImpl->mEventData) || (0u == mImpl->mEventData->mInputStyleChangedQueue.Count());
void Controller::ProcessInputStyleChangedSignals()
{
- if(NULL == mImpl->mEventData)
- {
- // Nothing to do.
- return;
- }
-
- for(Vector<InputStyle::Mask>::ConstIterator it = mImpl->mEventData->mInputStyleChangedQueue.Begin(),
- endIt = mImpl->mEventData->mInputStyleChangedQueue.End();
- it != endIt;
- ++it)
+ if(mImpl->mEventData)
{
- const InputStyle::Mask mask = *it;
-
- if(NULL != mImpl->mEditableControlInterface)
+ if(mImpl->mEditableControlInterface)
{
- // Emit the input style changed signal.
- mImpl->mEditableControlInterface->InputStyleChanged(mask);
+ // Emit the input style changed signal for each mask
+ std::for_each(mImpl->mEventData->mInputStyleChangedQueue.begin(),
+ mImpl->mEventData->mInputStyleChangedQueue.end(),
+ [&](const auto mask) { mImpl->mEditableControlInterface->InputStyleChanged(mask); } );
}
- }
- mImpl->mEventData->mInputStyleChangedQueue.Clear();
+ mImpl->mEventData->mInputStyleChangedQueue.Clear();
+ }
}
-// public : Text-input Event Queuing.
-
void Controller::KeyboardFocusGainEvent()
{
EventHandler::KeyboardFocusGainEvent(*this);
if(!IsEditable())
{
- return "";
+ return EMPTY_STRING;
}
mImpl->SendSelectionToClipboard(true); // Synchronous call to modify text
EventHandler::PasteClipboardItemEvent(*this);
}
-// protected : Inherit from Text::Decorator::ControllerInterface.
-
void Controller::GetTargetSize(Vector2& targetSize)
{
targetSize = mImpl->mModel->mVisualModel->mControlSize;
void Controller::AddDecoration(Actor& actor, bool needsClipping)
{
- if(NULL != mImpl->mEditableControlInterface)
+ if(mImpl->mEditableControlInterface)
{
mImpl->mEditableControlInterface->AddDecoration(actor, needsClipping);
}
float Controller::GetHorizontalScrollPosition()
{
- if(mImpl->mEventData)
- {
- //scroll values are negative internally so we convert them to positive numbers
- return -mImpl->mModel->mScrollPosition.x;
- }
- return 0;
+ // Scroll values are negative internally so we convert them to positive numbers
+ return mImpl->mEventData ? -mImpl->mModel->mScrollPosition.x : 0.0f;
}
float Controller::GetVerticalScrollPosition()
{
- if(mImpl->mEventData)
- {
- //scroll values are negative internally so we convert them to positive numbers
- return -mImpl->mModel->mScrollPosition.y;
- }
- return 0;
+ // Scroll values are negative internally so we convert them to positive numbers
+ return mImpl->mEventData ? -mImpl->mModel->mScrollPosition.y : 0.0f;
}
void Controller::DecorationEvent(HandleType handleType, HandleState state, float x, float y)
EventHandler::DecorationEvent(*this, handleType, state, x, y);
}
-// protected : Inherit from TextSelectionPopup::TextPopupButtonCallbackInterface.
-
void Controller::TextPopupButtonTouched(Dali::Toolkit::TextSelectionPopup::Buttons button)
{
EventHandler::TextPopupButtonTouched(*this, button);
mImpl->RequestRelayout();
}
-// private : Update.
-
void Controller::InsertText(const std::string& text, Controller::InsertType type)
{
TextUpdater::InsertText(*this, text, type);
TextUpdater::PasteText(*this, stringToPaste);
}
-bool Controller::RemoveText(int cursorOffset,
- int numberOfCharacters,
- UpdateInputStyleType type)
+bool Controller::RemoveText(int cursorOffset, int numberOfCharacters, UpdateInputStyleType type)
{
return TextUpdater::RemoveText(*this, cursorOffset, numberOfCharacters, type);
}
return TextUpdater::RemoveSelectedText(*this);
}
-void Controller::InsertTextAnchor(int numberOfCharacters,
- CharacterIndex previousCursorIndex)
+void Controller::InsertTextAnchor(int numberOfCharacters, CharacterIndex previousCursorIndex)
{
TextUpdater::InsertTextAnchor(*this, numberOfCharacters, previousCursorIndex);
}
-void Controller::RemoveTextAnchor(int cursorOffset,
- int numberOfCharacters,
- CharacterIndex previousCursorIndex)
+void Controller::RemoveTextAnchor(int cursorOffset, int numberOfCharacters, CharacterIndex previousCursorIndex)
{
TextUpdater::RemoveTextAnchor(*this, cursorOffset, numberOfCharacters, previousCursorIndex);
}
-// private : Relayout.
-
-bool Controller::DoRelayout(const Size& size,
- OperationsMask operationsRequired,
- Size& layoutSize)
+bool Controller::DoRelayout(const Size& size, OperationsMask operationsRequired, Size& layoutSize)
{
return Relayouter::DoRelayout(*this, size, operationsRequired, layoutSize);
}
Relayouter::CalculateVerticalOffset(*this, controlSize);
}
-// private : Events.
-
void Controller::ProcessModifyEvents()
{
EventHandler::ProcessModifyEvents(*this);
void Controller::ResetScrollPosition()
{
- if(NULL != mImpl->mEventData)
+ if(mImpl->mEventData)
{
// Reset the scroll position.
mImpl->mModel->mScrollPosition = Vector2::ZERO;
return mImpl->CreateBackgroundActor();
}
-// private : Private contructors & copy operator.
-
-Controller::Controller()
-: Controller(nullptr, nullptr, nullptr, nullptr)
-{
-}
-
-Controller::Controller(ControlInterface* controlInterface)
-: Controller(controlInterface, nullptr, nullptr, nullptr)
-{
-}
-
Controller::Controller(ControlInterface* controlInterface,
EditableControlInterface* editableControlInterface,
SelectableControlInterface* selectableControlInterface,
{
}
-// The copy constructor and operator are left unimplemented.
-
-// protected : Destructor.
-
Controller::~Controller()
{
delete mImpl;
}
-} // namespace Text
-
-} // namespace Toolkit
-
-} // namespace Dali
+} // namespace Dali::Toolkit::Text
#include <dali-toolkit/internal/text/text-selectable-control-interface.h>
#include <dali-toolkit/public-api/text/text-enumerations.h>
-namespace Dali
-{
-namespace Toolkit
-{
-namespace Text
+namespace Dali::Toolkit::Text
{
class Controller;
class ControlInterface;
*
* @return A pointer to a new Controller.
*/
- static ControllerPtr New();
+ static ControllerPtr New()
+ {
+ return ControllerPtr(new Controller());
+ }
/**
* @brief Create a new instance of a Controller.
*
* @return A pointer to a new Controller.
*/
- static ControllerPtr New(ControlInterface* controlInterface);
+ static ControllerPtr New(ControlInterface* controlInterface)
+ {
+ return ControllerPtr(new Controller(controlInterface));
+ }
/**
* @brief Create a new instance of a Controller.
static ControllerPtr New(ControlInterface* controlInterface,
EditableControlInterface* editableControlInterface,
SelectableControlInterface* selectableControlInterface,
- AnchorControlInterface* anchorControlInterface);
+ AnchorControlInterface* anchorControlInterface)
+ {
+ return ControllerPtr(new Controller(controlInterface,
+ editableControlInterface,
+ selectableControlInterface,
+ anchorControlInterface));
+ }
public: // Configure the text controller.
/**
/**
* @brief Private constructor.
*/
- Controller();
+ Controller()
+ : Controller(nullptr, nullptr, nullptr, nullptr)
+ {
+ }
/**
* @brief Private constructor.
*/
- Controller(ControlInterface* controlInterface);
+ Controller(ControlInterface* controlInterface)
+ : Controller(controlInterface, nullptr, nullptr, nullptr)
+ {
+ }
/**
* @brief Private constructor.
SelectableControlInterface* selectableControlInterface,
AnchorControlInterface* anchorControlInterface);
- // Undefined
- Controller(const Controller& handle);
-
- // Undefined
- Controller& operator=(const Controller& handle);
+ Controller(const Controller& handle) = delete;
+ Controller& operator=(const Controller& handle) = delete;
protected: // Destructor.
/**
Impl* mImpl;
};
-} // namespace Text
-
-} // namespace Toolkit
-
-} // namespace Dali
+} // namespace Dali::Toolkit::Text
#endif // DALI_TOOLKIT_TEXT_CONTROLLER_H
// INTERNAL INCLUDES
#include <dali-toolkit/devel-api/controls/control-devel.h>
+#include <dali-toolkit/internal/controls/control/control-data-impl.h>
namespace Dali
{
namespace
{
const Dali::AlphaFunction DEFAULT_ALPHA_FUNCTION(Dali::AlphaFunction::DEFAULT);
-
} // anonymous namespace
-TransitionPtr Transition::New(Dali::Toolkit::Control source, Dali::Toolkit::Control destination, TimePeriod timePeriod)
+TransitionPtr Transition::New(Dali::Toolkit::Control source, Dali::Toolkit::Control destination, bool useDestinationTarget, TimePeriod timePeriod)
{
float delaySeconds = timePeriod.delaySeconds;
if(delaySeconds < 0.0f)
durationSeconds = 0.0f;
}
- TransitionPtr transition = new Transition(source, destination, TimePeriod(delaySeconds, durationSeconds));
+ TransitionPtr transition = new Transition(source, destination, useDestinationTarget, TimePeriod(delaySeconds, durationSeconds));
// Second-phase construction
transition->Initialize();
return transition;
}
-Transition::Transition(Dali::Toolkit::Control source, Dali::Toolkit::Control destination, TimePeriod timePeriod)
+Transition::Transition(Dali::Toolkit::Control source, Dali::Toolkit::Control destination, bool useDestinationTarget, TimePeriod timePeriod)
: TransitionBase(),
+ mUseDestinationTarget(useDestinationTarget),
+ mOriginalSize(),
mSourceControl(source),
mDestinationControl(destination)
{
- SetTarget(destination);
+ SetTarget(mUseDestinationTarget ? destination : source);
SetTimePeriod(timePeriod);
SetPairTransition(true);
}
}
//Make startPropertyMap and finishPropertyMap to use for property animation.
- Matrix sourceWorldTransform = sourceControl[Dali::Actor::Property::WORLD_MATRIX];
+ Matrix sourceWorldTransform = GetWorldTransform(sourceControl);
Vector3 sourcePosition, sourceScale;
Quaternion sourceOrientation;
sourceWorldTransform.GetTransformComponents(sourcePosition, sourceOrientation, sourceScale);
- Vector3 destinationPosition = destinationControl[Dali::Actor::Property::POSITION];
- Vector3 destinationScale = destinationControl[Dali::Actor::Property::SCALE];
- Quaternion destinationOrientation = destinationControl[Dali::Actor::Property::ORIENTATION];
- Vector4 targetColor = destinationControl[Dali::Actor::Property::COLOR];
- Vector3 targetSize = destinationControl[Dali::Actor::Property::SIZE];
+ Matrix destinationWorldTransform = GetWorldTransform(destinationControl);
+ Vector3 destinationPosition, destinationScale;
+ Quaternion destinationOrientation;
+ destinationWorldTransform.GetTransformComponents(destinationPosition, destinationOrientation, destinationScale);
Property::Map startPropertyMap;
Property::Map finishPropertyMap;
startPropertyMap.Insert(Dali::Actor::Property::SCALE, sourceScale);
finishPropertyMap.Insert(Dali::Actor::Property::SCALE, destinationScale);
- Vector4 sourceColor = sourceControl.GetCurrentProperty<Vector4>(Dali::Actor::Property::WORLD_COLOR);
+ Vector4 sourceColor = GetWorldColor(sourceControl);
+ Vector4 destinationColor = GetWorldColor(destinationControl);
startPropertyMap.Insert(Dali::Actor::Property::COLOR, sourceColor);
- finishPropertyMap.Insert(Dali::Actor::Property::COLOR, targetColor);
+ finishPropertyMap.Insert(Dali::Actor::Property::COLOR, destinationColor);
// Set animation for other properties if source and destination is different.
- Vector3 sourceSize = sourceControl.GetCurrentProperty<Vector3>(Dali::Actor::Property::SIZE);
- if(sourceSize != targetSize)
+ Vector3 sourceSize = sourceControl[Dali::Actor::Property::SIZE];
+ Vector3 destinationSize = destinationControl[Dali::Actor::Property::SIZE];
+ if(sourceSize != destinationSize)
{
startPropertyMap.Insert(Dali::Actor::Property::SIZE, sourceSize);
- finishPropertyMap.Insert(Dali::Actor::Property::SIZE, targetSize);
+ finishPropertyMap.Insert(Dali::Actor::Property::SIZE, destinationSize);
+ if(!mUseDestinationTarget)
+ {
+ mOriginalSize = GetTargetControl().GetProperty<Vector3>(Dali::Actor::Property::SIZE);
+ }
}
SetStartPropertyMap(startPropertyMap);
SetFinishPropertyMap(finishPropertyMap);
// source View becomes transparent during transition.
+ Dali::Toolkit::Control waitingControl = GetWaitingControl();
if(IsTransitionWithChild())
{
- sourceControl[Dali::Actor::Property::VISIBLE] = false;
+ waitingControl[Dali::Actor::Property::VISIBLE] = false;
}
else
{
- GetImplementation(sourceControl).SetTransparent(true);
+ GetImplementation(waitingControl).SetTransparent(true);
}
Dali::Animation animation = GetAnimation();
DALI_LOG_ERROR("animation is still not initialized\n");
return;
}
- Dali::Toolkit::DevelControl::CreateTransitions(destinationControl, animation, sourceControl, GetAlphaFunction(), GetTimePeriod());
+
+ mOriginalVisualProperties.clear();
+ std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>> destinationVisualProperties;
+ Dali::Toolkit::Control targetControl = GetTargetControl();
+ Internal::Control& internalControl = Toolkit::Internal::GetImplementation(targetControl);
+ Internal::Control::Impl& controlDataImpl = Toolkit::Internal::Control::Impl::Get(internalControl);
+ controlDataImpl.CreateTransitions(mOriginalVisualProperties, destinationVisualProperties, sourceControl, destinationControl);
+
+ for(uint32_t index = 0; index < mOriginalVisualProperties.size(); ++index)
+ {
+ Dali::Property::Map source = mOriginalVisualProperties[index].second;
+ Dali::Property::Map destination = destinationVisualProperties[index].second;
+ for(size_t i = 0; i < source.Count(); ++i)
+ {
+ Dali::Property property = DevelControl::GetVisualProperty(targetControl, mOriginalVisualProperties[index].first, source.GetKeyAt(i));
+ if(GetTimePeriod().delaySeconds > 0.0f)
+ {
+ Dali::KeyFrames initialKeyframes = Dali::KeyFrames::New();
+ initialKeyframes.Add(0.0f, source.GetValue(i));
+ animation.AnimateBetween(property, initialKeyframes, TimePeriod(GetTimePeriod().delaySeconds));
+ }
+ Dali::KeyFrames keyframes = Dali::KeyFrames::New();
+ keyframes.Add(0.0f, source.GetValue(i));
+ keyframes.Add(1.0f, destination.GetValue(i));
+ animation.AnimateBetween(property, keyframes, GetAlphaFunction(), GetTimePeriod());
+ }
+ }
}
void Transition::OnFinished()
{
- Dali::Toolkit::Control sourceControl = mSourceControl.GetHandle();
- if(!sourceControl)
+ Dali::Toolkit::Control waitingControl = GetWaitingControl();
+ if(!waitingControl)
{
return;
}
+ if(!mUseDestinationTarget)
+ {
+ Dali::Toolkit::Control target = GetTargetControl();
+ Dali::Animation resetAnimation = Dali::Animation::New(0.0f);
+ if(mOriginalSize != target.GetProperty<Vector3>(Dali::Actor::Property::SIZE))
+ {
+ // Use Animation not to notify size change and not to change width and height resize policy.
+ resetAnimation.AnimateTo(Dali::Property(target, Dali::Actor::Property::SIZE), mOriginalSize);
+ }
+ resetAnimation.Play();
+
+ Dali::Toolkit::Control targetControl = GetTargetControl();
+ Internal::Control& internalControl = Toolkit::Internal::GetImplementation(targetControl);
+ Internal::Control::Impl& controlDataImpl = Toolkit::Internal::Control::Impl::Get(internalControl);
+ controlDataImpl.UpdateVisualProperties(mOriginalVisualProperties);
+ }
+
if(IsTransitionWithChild())
{
- sourceControl[Dali::Actor::Property::VISIBLE] = true;
+ waitingControl[Dali::Actor::Property::VISIBLE] = true;
}
else
{
- GetImplementation(sourceControl).SetTransparent(false);
+ GetImplementation(waitingControl).SetTransparent(false);
}
}
+Dali::Toolkit::Control Transition::GetTargetControl()
+{
+ Dali::Toolkit::Control target = mUseDestinationTarget ? mDestinationControl.GetHandle() : mSourceControl.GetHandle();
+ return target;
+}
+
+Dali::Toolkit::Control Transition::GetWaitingControl()
+{
+ Dali::Toolkit::Control waitingControl = mUseDestinationTarget ? mSourceControl.GetHandle() : mDestinationControl.GetHandle();
+ return waitingControl;
+}
+
} // namespace Internal
} // namespace Toolkit
* @brief Create a new Transition object.
* @param[in] source A source control of this transition.
* @param[in] destination A destination control of this transition.
+ * @param[in] useDestinationTarget True if this transition uses destination control as target.
* @param[in] timePeriod The timePeriod of the animation.
* @return A smart-pointer to the newly allocated Transition.
*/
- static TransitionPtr New(Dali::Toolkit::Control source, Dali::Toolkit::Control destination, TimePeriod timePeriod);
+ static TransitionPtr New(Dali::Toolkit::Control source, Dali::Toolkit::Control destination, bool useDestinationTarget, TimePeriod timePeriod);
protected:
/**
*/
Transition(Dali::Toolkit::Control source,
Dali::Toolkit::Control destination,
+ bool useDestinationTarget,
TimePeriod timePeriod);
/**
Transition& operator=(const Transition& rhs);
private:
- WeakHandle<Dali::Toolkit::Control> mSourceControl;
- WeakHandle<Dali::Toolkit::Control> mDestinationControl;
+ Dali::Toolkit::Control GetTargetControl();
+ Dali::Toolkit::Control GetWaitingControl();
+
+private:
+ bool mUseDestinationTarget;
+ Vector3 mOriginalSize;
+ std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>> mOriginalVisualProperties;
+ WeakHandle<Dali::Toolkit::Control> mSourceControl;
+ WeakHandle<Dali::Toolkit::Control> mDestinationControl;
};
} // namespace Internal
mUrlIndex(0),
mFrameCount(0),
mImageSize(),
+ mActionStatus(DevelAnimatedImageVisual::Action::PLAY),
mWrapModeU(WrapMode::DEFAULT),
mWrapModeV(WrapMode::DEFAULT),
- mActionStatus(DevelAnimatedImageVisual::Action::PLAY),
mStopBehavior(DevelImageVisual::StopBehavior::CURRENT_FRAME),
mStartFirstFrame(false),
mIsJumpTo(false)
DALI_LOG_INFO(gAnimImgLogFilter, Debug::Concise, "ResourceReady(ResourceStatus::FAILED)\n");
ResourceReady(Toolkit::Visual::ResourceStatus::FAILED);
- TextureSet textureSet = TextureSet::New();
- Texture brokenImage = mFactoryCache.GetBrokenVisualImage();
- textureSet.SetTexture(0u, brokenImage);
+ Actor actor = mPlacementActor.GetHandle();
+ Vector2 imageSize = Vector2::ZERO;
+ if(actor)
+ {
+ imageSize = actor.GetProperty(Actor::Property::SIZE).Get<Vector2>();
+ }
+ mFactoryCache.UpdateBrokenImageRenderer(mImpl->mRenderer, imageSize);
+ TextureSet textureSet = mImpl->mRenderer.GetTextures();
if(mFrameDelayTimer)
{
uint32_t mFrameCount; // Number of frames
ImageDimensions mImageSize;
+ DevelAnimatedImageVisual::Action::Type mActionStatus;
+
Dali::WrapMode::Type mWrapModeU : 3;
Dali::WrapMode::Type mWrapModeV : 3;
- DevelAnimatedImageVisual::Action::Type mActionStatus : 3;
DevelImageVisual::StopBehavior::Type mStopBehavior : 2;
bool mStartFirstFrame : 1;
bool mIsJumpTo : 1;
#include <dali/integration-api/debug.h>
// INTERNAL INCLUDES
+#include <dali-toolkit/devel-api/visuals/visual-actions-devel.h>
#include <dali-toolkit/devel-api/visuals/animated-vector-image-visual-signals-devel.h>
#include <dali-toolkit/devel-api/visuals/image-visual-properties-devel.h>
#include <dali-toolkit/internal/visuals/animated-vector-image/vector-animation-manager.h>
if(mLoadFailed)
{
- TextureSet textureSet = TextureSet::New();
- mImpl->mRenderer.SetTextures(textureSet);
-
- Texture brokenImage = mFactoryCache.GetBrokenVisualImage();
- textureSet.SetTexture(0u, brokenImage);
-
+ Vector2 imageSize = Vector2::ZERO;
+ imageSize = actor.GetProperty(Actor::Property::SIZE).Get<Vector2>();
+ mFactoryCache.UpdateBrokenImageRenderer(mImpl->mRenderer, imageSize);
actor.AddRenderer(mImpl->mRenderer);
-
ResourceReady(Toolkit::Visual::ResourceStatus::FAILED);
}
else
}
break;
}
- case DevelAnimatedVectorImageVisual::Action::UPDATE_PROPERTY:
- {
- const Property::Map* map = attributes.GetMap();
- if(map)
- {
- DoSetProperties(*map);
- }
- break;
- }
}
TriggerVectorRasterization();
// is casted to use the default duration.
mNextFrameStartTime = std::chrono::time_point_cast<TimePoint::duration>(mNextFrameStartTime + std::chrono::microseconds(mFrameDurationMicroSeconds));
auto current = std::chrono::steady_clock::now();
+ mDroppedFrames = 0;
+
if(renderNow)
{
mNextFrameStartTime = current;
- mDroppedFrames = 0;
}
else if(mNextFrameStartTime < current)
{
#include <dali/integration-api/debug.h>
//INTERNAL INCLUDES
-#include <dali-toolkit/devel-api/visuals/arc-visual-actions-devel.h>
#include <dali-toolkit/devel-api/visuals/visual-properties-devel.h>
#include <dali-toolkit/internal/graphics/builtin-shader-extern-gen.h>
#include <dali-toolkit/internal/visuals/visual-base-data-impl.h>
}
}
-void ArcVisual::OnDoAction(const Property::Index actionId, const Property::Value& attributes)
-{
- // Check if action is valid for this visual type and perform action if possible
- switch(actionId)
- {
- case DevelArcVisual::Action::UPDATE_PROPERTY:
- {
- const Property::Map* map = attributes.GetMap();
- if(map)
- {
- DoSetProperties(*map);
- }
- break;
- }
- }
-}
-
void ArcVisual::OnInitialize()
{
Geometry geometry = mFactoryCache.GetGeometry(VisualFactoryCache::QUAD_GEOMETRY);
*/
void OnSetTransform() override;
- /**
- * @copydoc Visual::Base::OnDoAction
- */
- void OnDoAction(const Property::Index actionId, const Property::Value& attributes) override;
-
private:
// Undefined
ArcVisual(const ArcVisual& arcVisual) = delete;
#include <dali/integration-api/debug.h>
//INTERNAL INCLUDES
-#include <dali-toolkit/devel-api/visuals/color-visual-actions-devel.h>
#include <dali-toolkit/devel-api/visuals/color-visual-properties-devel.h>
#include <dali-toolkit/internal/graphics/builtin-shader-extern-gen.h>
#include <dali-toolkit/internal/visuals/visual-base-data-impl.h>
: Visual::Base(factoryCache, Visual::FittingMode::FILL, Toolkit::Visual::COLOR),
mBlurRadius(0.0f),
mBlurRadiusIndex(Property::INVALID_INDEX),
- mNeedBlurRadius(false)
+ mAlwaysUsingBlurRadius(false)
{
}
}
}
-void ColorVisual::OnDoAction(const Property::Index actionId, const Property::Value& attributes)
-{
- // Check if action is valid for this visual type and perform action if possible
- switch(actionId)
- {
- case DevelColorVisual::Action::UPDATE_PROPERTY:
- {
- const Property::Map* map = attributes.GetMap();
- if(map)
- {
- DoSetProperties(*map);
- }
- break;
- }
- }
-}
-
void ColorVisual::UpdateShader()
{
if(mImpl->mRenderer)
bool roundedCorner = IsRoundedCornerRequired();
bool borderline = IsBorderlineRequired();
- bool blur = !EqualsZero(mBlurRadius) || mNeedBlurRadius;
+ bool blur = !EqualsZero(mBlurRadius) || mAlwaysUsingBlurRadius;
int shaderTypeFlag = ColorVisualRequireFlag::DEFAULT;
if(roundedCorner)
{
mBlurRadiusIndex = mImpl->mRenderer.RegisterProperty(DevelColorVisual::Property::BLUR_RADIUS, BLUR_RADIUS_NAME, mBlurRadius);
- mImpl->mRenderer.SetProperty(Renderer::Property::BLEND_MODE, BlendMode::ON);
+ // Blur is animated now. we always have to use blur feature.
+ mAlwaysUsingBlurRadius = true;
- mNeedBlurRadius = true;
+ mImpl->mRenderer.SetProperty(Renderer::Property::BLEND_MODE, BlendMode::ON);
// Change shader
UpdateShader();
void OnSetTransform() override;
/**
- * @copydoc Visual::Base::OnDoAction
- */
- void OnDoAction(const Property::Index actionId, const Property::Value& attributes) override;
-
- /**
* @copydoc Visual::Base::UpdateShader
*/
void UpdateShader() override;
ColorVisual& operator=(const ColorVisual& colorRenderer);
private:
- float mBlurRadius; ///< The blur radius
- Property::Index mBlurRadiusIndex; ///< The blur radius property index
- bool mNeedBlurRadius; ///< Whether we need the blur radius in shader.
+ float mBlurRadius; ///< The blur radius
+ Property::Index mBlurRadiusIndex; ///< The blur radius property index
+ bool mAlwaysUsingBlurRadius : 1; ///< Whether we need the blur radius in shader always.
};
} // namespace Internal
}
else
{
- Texture brokenImage = mFactoryCache.GetBrokenVisualImage();
-
+ Actor actor = mPlacementActor.GetHandle();
+ Vector2 imageSize = Vector2::ZERO;
+ if(actor)
+ {
+ imageSize = actor.GetProperty(Actor::Property::SIZE).Get<Vector2>();
+ }
+ mFactoryCache.UpdateBrokenImageRenderer(mImpl->mRenderer, imageSize);
+ Texture brokenImage = mImpl->mRenderer.GetTextures().GetTexture(0);
naturalSize.x = brokenImage.GetWidth();
naturalSize.y = brokenImage.GetWidth();
}
}
else if(mLoadState == TextureManager::LoadState::LOAD_FAILED)
{
- Texture brokenImage = mFactoryCache.GetBrokenVisualImage();
-
- mTextures = TextureSet::New();
- mTextures.SetTexture(0u, brokenImage);
- mImpl->mRenderer.SetTextures(mTextures);
-
+ Vector2 imageSize = Vector2::ZERO;
+ if(actor)
+ {
+ imageSize = actor.GetProperty(Actor::Property::SIZE).Get<Vector2>();
+ }
+ mFactoryCache.UpdateBrokenImageRenderer(mImpl->mRenderer, imageSize);
actor.AddRenderer(mImpl->mRenderer);
mPlacementActor.Reset();
EnablePreMultipliedAlpha(preMultiplied);
Actor actor = mPlacementActor.GetHandle();
- if(actor)
+ if(!loadingSuccess)
{
- actor.AddRenderer(mImpl->mRenderer);
- // reset the weak handle so that the renderer only get added to actor once
- mPlacementActor.Reset();
+ Vector2 imageSize = Vector2::ZERO;
+ if(actor)
+ {
+ imageSize = actor.GetProperty(Actor::Property::SIZE).Get<Vector2>();
+ }
+ mFactoryCache.UpdateBrokenImageRenderer(mImpl->mRenderer, imageSize);
+ textureSet = mImpl->mRenderer.GetTextures();
}
-
- if(!loadingSuccess)
+ else
{
- Texture brokenImage = mFactoryCache.GetBrokenVisualImage();
-
- textureSet = TextureSet::New();
- textureSet.SetTexture(0u, brokenImage);
+ Sampler sampler = Sampler::New();
+ sampler.SetWrapMode(mWrapModeU, mWrapModeV);
+ textureSet.SetSampler(0u, sampler);
mImpl->mRenderer.SetTextures(textureSet);
}
- Sampler sampler = Sampler::New();
- sampler.SetWrapMode(mWrapModeU, mWrapModeV);
- textureSet.SetSampler(0u, sampler);
- mImpl->mRenderer.SetTextures(textureSet);
+ if(actor)
+ {
+ actor.AddRenderer(mImpl->mRenderer);
+ // reset the weak handle so that the renderer only get added to actor once
+ mPlacementActor.Reset();
+ }
}
// Storing TextureSet needed when renderer staged.
newData->AddObserver(textureObserver);
mCache.PushBack(newData);
-
return newData->GetId(); // valid ids start from 1u
}
}
preMultiplyOnLoad = (preMultiplyOnLoading == TextureManager::MultiplyOnLoad::MULTIPLY_ON_LOAD) ? true : false;
data->SetLoadedNPatchData(pixelBuffer, preMultiplyOnLoad);
}
-
return data->GetId();
}
DALI_LOG_ERROR("The N patch image '%s' is not a valid N patch image\n", mImageUrl.GetUrl().c_str());
textureSet = TextureSet::New();
- Texture croppedImage = mFactoryCache.GetBrokenVisualImage();
+ Actor actor = mPlacementActor.GetHandle();
+ Vector2 imageSize = Vector2::ZERO;
+ if(actor)
+ {
+ imageSize = actor.GetProperty(Actor::Property::SIZE).Get<Vector2>();
+ }
+ mFactoryCache.UpdateBrokenImageRenderer(mImpl->mRenderer, imageSize);
+ Texture croppedImage = mImpl->mRenderer.GetTextures().GetTexture(0);
textureSet.SetTexture(0u, croppedImage);
mImpl->mRenderer.RegisterProperty("uFixed[0]", Vector2::ZERO);
mImpl->mRenderer.RegisterProperty("uFixed[1]", Vector2::ZERO);
if(mLoadFailed)
{
- Texture brokenImage = mFactoryCache.GetBrokenVisualImage();
- textureSet.SetTexture(0u, brokenImage);
-
+ Vector2 imageSize = Vector2::ZERO;
+ imageSize = actor.GetProperty(Actor::Property::SIZE).Get<Vector2>();
+ mFactoryCache.UpdateBrokenImageRenderer(mImpl->mRenderer, imageSize);
actor.AddRenderer(mImpl->mRenderer);
ResourceReady(Toolkit::Visual::ResourceStatus::FAILED);
Actor actor = mPlacementActor.GetHandle();
if(actor)
{
- TextureSet textureSet = mImpl->mRenderer.GetTextures();
-
- Texture brokenImage = mFactoryCache.GetBrokenVisualImage();
- textureSet.SetTexture(0u, brokenImage);
-
+ Vector2 imageSize = Vector2::ZERO;
+ imageSize = actor.GetProperty(Actor::Property::SIZE).Get<Vector2>();
+ mFactoryCache.UpdateBrokenImageRenderer(mImpl->mRenderer, imageSize);
actor.AddRenderer(mImpl->mRenderer);
}
mFlags(0),
mResourceStatus(Toolkit::Visual::ResourceStatus::PREPARING),
mType(type),
- mNeedCornerRadius(false),
- mNeedBorderline(false)
+ mAlwaysUsingBorderline(false),
+ mAlwaysUsingCornerRadius(false)
{
}
Property::Index mBorderlineColorIndex;
Property::Index mBorderlineOffsetIndex;
Property::Index mCornerRadiusIndex;
- FittingMode mFittingMode; //< How the contents should fit the view
+ FittingMode mFittingMode; ///< How the contents should fit the view
int mFlags;
Toolkit::Visual::ResourceStatus mResourceStatus;
const Toolkit::Visual::Type mType;
- bool mNeedCornerRadius;
- bool mNeedBorderline;
+ bool mAlwaysUsingBorderline : 1; ///< Whether we need the borderline in shader always.
+ bool mAlwaysUsingCornerRadius : 1; ///< Whether we need the corner radius in shader always.
};
} // namespace Visual
#include <dali/integration-api/debug.h>
//INTERNAL HEARDER
+#include <dali-toolkit/devel-api/visuals/visual-actions-devel.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-base-data-impl.h>
{
mImpl->mBorderlineWidth = width;
}
+
+ if(mImpl->mBorderlineWidthIndex != Property::INVALID_INDEX)
+ {
+ mImpl->mRenderer.SetProperty(mImpl->mBorderlineWidthIndex, mImpl->mBorderlineWidth);
+ }
break;
}
case Toolkit::DevelVisual::Property::BORDERLINE_COLOR:
{
mImpl->mBorderlineColor = color;
}
+
+ if(mImpl->mBorderlineColorIndex != Property::INVALID_INDEX)
+ {
+ mImpl->mRenderer.SetProperty(mImpl->mBorderlineColorIndex, mImpl->mBorderlineColor);
+ }
break;
}
case Toolkit::DevelVisual::Property::BORDERLINE_OFFSET:
{
mImpl->mBorderlineOffset = offset;
}
+
+ if(mImpl->mBorderlineOffsetIndex != Property::INVALID_INDEX)
+ {
+ mImpl->mRenderer.SetProperty(mImpl->mBorderlineOffsetIndex, mImpl->mBorderlineOffset);
+ }
break;
}
case Toolkit::DevelVisual::Property::CORNER_RADIUS:
mImpl->mCornerRadius = Vector4(radius, radius, radius, radius);
}
}
+
+ if(mImpl->mCornerRadiusIndex != Property::INVALID_INDEX)
+ {
+ mImpl->mRenderer.SetProperty(mImpl->mCornerRadiusIndex, mImpl->mCornerRadius);
+ }
break;
}
case Toolkit::DevelVisual::Property::CORNER_RADIUS_POLICY:
void Visual::Base::DoAction(const Property::Index actionId, const Property::Value attributes)
{
OnDoAction(actionId, attributes);
+
+ // Check if action is valid for this visual type and perform action if possible
+ switch(actionId)
+ {
+ case DevelVisual::Action::UPDATE_PROPERTY:
+ {
+ const Property::Map* map = attributes.GetMap();
+ if(map)
+ {
+ SetProperties(*map);
+ }
+ break;
+ }
+ }
}
void Visual::Base::SetDepthIndex(int index)
// Update values from Renderer
mImpl->mCornerRadius = mImpl->mRenderer.GetProperty<Vector4>(mImpl->mCornerRadiusIndex);
}
- return !(mImpl->mCornerRadius == Vector4::ZERO) || mImpl->mNeedCornerRadius;
+ return !(mImpl->mCornerRadius == Vector4::ZERO) || mImpl->mAlwaysUsingCornerRadius;
}
return false;
}
// Update values from Renderer
mImpl->mBorderlineWidth = mImpl->mRenderer.GetProperty<float>(mImpl->mBorderlineWidthIndex);
}
- return !EqualsZero(mImpl->mBorderlineWidth) || mImpl->mNeedBorderline;
+ return !EqualsZero(mImpl->mBorderlineWidth) || mImpl->mAlwaysUsingBorderline;
}
return false;
}
mImpl->mBorderlineWidthIndex = mImpl->mRenderer.RegisterProperty(DevelVisual::Property::BORDERLINE_WIDTH, BORDERLINE_WIDTH, mImpl->mBorderlineWidth);
mImpl->mBorderlineColorIndex = mImpl->mRenderer.RegisterProperty(DevelVisual::Property::BORDERLINE_COLOR, BORDERLINE_COLOR, mImpl->mBorderlineColor);
mImpl->mBorderlineOffsetIndex = mImpl->mRenderer.RegisterProperty(DevelVisual::Property::BORDERLINE_OFFSET, BORDERLINE_OFFSET, mImpl->mBorderlineOffset);
- mImpl->mNeedBorderline = true;
+
+ // Borderline is animated now. we always have to use borderline feature.
+ mImpl->mAlwaysUsingBorderline = true;
index = mImpl->mRenderer.GetPropertyIndex(key);
mImpl->mCornerRadiusIndex = mImpl->mRenderer.RegisterProperty(DevelVisual::Property::CORNER_RADIUS, CORNER_RADIUS, mImpl->mCornerRadius);
mImpl->mRenderer.RegisterProperty(CORNER_RADIUS_POLICY, mImpl->mCornerRadiusPolicy);
- if(!mImpl->mNeedBorderline)
+ // ConerRadius is animated now. we always have to use corner radius feature.
+ mImpl->mAlwaysUsingCornerRadius = true;
+
+ if(!IsBorderlineRequired())
{
- // If mNeedBorderline is true, BLEND_MODE is already BlendMode::ON_WITHOUT_CULL. So we don't overwrite it.
+ // If IsBorderlineRequired is true, BLEND_MODE is already BlendMode::ON_WITHOUT_CULL. So we don't overwrite it.
mImpl->mRenderer.SetProperty(Renderer::Property::BLEND_MODE, BlendMode::ON);
}
- index = mImpl->mCornerRadiusIndex;
- mImpl->mNeedCornerRadius = true;
+ index = mImpl->mCornerRadiusIndex;
// Change shader
UpdateShader();
#include <dali-toolkit/internal/visuals/color/color-visual.h>
#include <dali-toolkit/internal/visuals/image-atlas-manager.h>
#include <dali-toolkit/internal/visuals/svg/svg-visual.h>
+#include <dali-toolkit/internal/graphics/builtin-shader-extern-gen.h>
+#include <dali/integration-api/debug.h>
namespace Dali
{
{
namespace Internal
{
+namespace
+{
+
+/**
+ * @brief Creates the geometry formed from the vertices and indices
+ *
+ * @param[in] vertices The vertices to generate the geometry from
+ * @param[in] indices The indices to generate the geometry from
+ * @return The geometry formed from the vertices and indices
+ */
+Geometry GenerateGeometry(const Vector<Vector2>& vertices, const Vector<unsigned short>& indices)
+{
+ Property::Map vertexFormat;
+ vertexFormat["aPosition"] = Property::VECTOR2;
+ VertexBuffer vertexBuffer = VertexBuffer::New(vertexFormat);
+ if(vertices.Size() > 0)
+ {
+ vertexBuffer.SetData(&vertices[0], vertices.Size());
+ }
+
+ // Create the geometry object
+ Geometry geometry = Geometry::New();
+ geometry.AddVertexBuffer(vertexBuffer);
+ if(indices.Size() > 0)
+ {
+ geometry.SetIndexBuffer(&indices[0], indices.Size());
+ }
+
+ return geometry;
+}
+
+/**
+ * @brief Adds the indices to form a quad composed off two triangles where the indices are organised in a grid
+ *
+ * @param[out] indices The indices to add to
+ * @param[in] rowIdx The row index to start the quad
+ * @param[in] nextRowIdx The index to the next row
+ */
+void AddQuadIndices(Vector<unsigned short>& indices, unsigned int rowIdx, unsigned int nextRowIdx)
+{
+ indices.PushBack(rowIdx);
+ indices.PushBack(nextRowIdx + 1);
+ indices.PushBack(rowIdx + 1);
+
+ indices.PushBack(rowIdx);
+ indices.PushBack(nextRowIdx);
+ indices.PushBack(nextRowIdx + 1);
+}
+
+/**
+ * @brief Adds the vertices to create for npatch
+ * @param[out] vertices The vertices to add to
+ * @param[in] x The x value of vector
+ * @param[in] y The y value of vector
+ */
+void AddVertex(Vector<Vector2>& vertices, unsigned int x, unsigned int y)
+{
+ vertices.PushBack(Vector2(x, y));
+}
+
+} //unnamed namespace
+
VisualFactoryCache::VisualFactoryCache(bool preMultiplyOnLoad)
: mSvgRasterizeThread(NULL),
mVectorAnimationManager(),
- mBrokenImageUrl(""),
- mPreMultiplyOnLoad(preMultiplyOnLoad)
+ mPreMultiplyOnLoad(preMultiplyOnLoad),
+ mBrokenImageInfoContainer()
{
}
if(!mAtlasManager)
{
mAtlasManager = new ImageAtlasManager();
- mAtlasManager->SetBrokenImage(mBrokenImageUrl);
+ if(!mBrokenImageInfoContainer.empty())
+ {
+ mAtlasManager->SetBrokenImage(mBrokenImageInfoContainer[0].url);
+ }
}
return mAtlasManager;
return geometry;
}
-Texture VisualFactoryCache::GetBrokenVisualImage()
+Texture VisualFactoryCache::GetBrokenVisualImage(uint32_t brokenIndex)
{
- if(!mBrokenImageTexture && mBrokenImageUrl.size())
+ if(!(mBrokenImageInfoContainer[brokenIndex].texture))
{
- PixelData data;
- Devel::PixelBuffer pixelBuffer = LoadImageFromFile(mBrokenImageUrl);
+ PixelData pixelData;
+ Devel::PixelBuffer pixelBuffer = LoadImageFromFile(mBrokenImageInfoContainer[brokenIndex].url);
if(pixelBuffer)
{
- data = Devel::PixelBuffer::Convert(pixelBuffer); // takes ownership of buffer
- mBrokenImageTexture = Texture::New(Dali::TextureType::TEXTURE_2D, data.GetPixelFormat(), data.GetWidth(), data.GetHeight());
- mBrokenImageTexture.Upload(data);
+ pixelData = Devel::PixelBuffer::Convert(pixelBuffer); // takes ownership of buffer
+ mBrokenImageInfoContainer[brokenIndex].texture = Texture::New(Dali::TextureType::TEXTURE_2D, pixelData.GetPixelFormat(), pixelData.GetWidth(), pixelData.GetHeight());
+ mBrokenImageInfoContainer[brokenIndex].texture.Upload(pixelData);
+ mBrokenImageInfoContainer[brokenIndex].width = pixelData.GetWidth();
+ mBrokenImageInfoContainer[brokenIndex].height = pixelData.GetHeight();
}
}
- return mBrokenImageTexture;
+ return mBrokenImageInfoContainer[brokenIndex].texture;
}
void VisualFactoryCache::SetPreMultiplyOnLoad(bool preMultiply)
return mPreMultiplyOnLoad;
}
-void VisualFactoryCache::SetBrokenImageUrl(const std::string& brokenImageUrl)
+void VisualFactoryCache::SetBrokenImageUrl(const std::vector<std::string>& brokenImageUrlList)
{
- mBrokenImageUrl = brokenImageUrl;
+ mBrokenImageInfoContainer.clear();
+ mBrokenImageInfoContainer.assign(brokenImageUrlList.size(), BrokenImageInfo());
+ for(unsigned int i = 0; i < brokenImageUrlList.size(); i++)
+ {
+ mBrokenImageInfoContainer[i].url = brokenImageUrlList[i];
+ }
+}
- if(!mAtlasManager)
+VisualUrl::Type VisualFactoryCache::GetBrokenImageVisualType(int index)
+{
+ return mBrokenImageInfoContainer[index].visualType;
+}
+
+Geometry VisualFactoryCache::CreateNPatchGeometry(Uint16Pair gridSize)
+{
+ uint16_t gridWidth = gridSize.GetWidth();
+ uint16_t gridHeight = gridSize.GetHeight();
+
+ // Create vertices
+ Vector<Vector2> vertices;
+ vertices.Reserve((gridWidth + 1) * (gridHeight + 1));
+
+ for(int y = 0; y < gridHeight + 1; ++y)
{
- mAtlasManager = new ImageAtlasManager();
+ for(int x = 0; x < gridWidth + 1; ++x)
+ {
+ AddVertex(vertices, x, y);
+ }
+ }
+
+ // Create indices
+ Vector<unsigned short> indices;
+ indices.Reserve(gridWidth * gridHeight * 6);
+
+ unsigned int rowIdx = 0;
+ unsigned int nextRowIdx = gridWidth + 1;
+ for(int y = 0; y < gridHeight; ++y, ++nextRowIdx, ++rowIdx)
+ {
+ for(int x = 0; x < gridWidth; ++x, ++nextRowIdx, ++rowIdx)
+ {
+ AddQuadIndices(indices, rowIdx, nextRowIdx);
+ }
+ }
+
+ return GenerateGeometry(vertices, indices);
+}
+
+Geometry VisualFactoryCache::GetNPatchGeometry(int index)
+{
+ Geometry geometry;
+ const NPatchData* data;
+ if(mNPatchLoader.GetNPatchData(mBrokenImageInfoContainer[index].npatchId, data) && data->GetLoadingState() == NPatchData::LoadingState::LOAD_COMPLETE)
+ {
+ if(data->GetStretchPixelsX().Size() == 1 && data->GetStretchPixelsY().Size() == 1)
+ {
+ geometry = GetGeometry(VisualFactoryCache::NINE_PATCH_GEOMETRY);
+ if(!geometry)
+ {
+ geometry = CreateNPatchGeometry(Uint16Pair(3,3));
+ SaveGeometry(VisualFactoryCache::NINE_PATCH_GEOMETRY, geometry);
+ }
+ }
+ else if(data->GetStretchPixelsX().Size() > 0 || data->GetStretchPixelsY().Size() > 0)
+ {
+ Uint16Pair gridSize(2 * data->GetStretchPixelsX().Size() + 1, 2 * data->GetStretchPixelsY().Size() + 1);
+ geometry = CreateNPatchGeometry(gridSize);
+ }
+ }
+ else
+ {
+ // no N patch data so use default geometry
+ geometry = GetGeometry(VisualFactoryCache::NINE_PATCH_GEOMETRY);
+ if(!geometry)
+ {
+ geometry = CreateNPatchGeometry(Uint16Pair(3,3));
+ SaveGeometry(VisualFactoryCache::NINE_PATCH_GEOMETRY, geometry);
+ }
+ }
+ return geometry;
+}
+
+Shader VisualFactoryCache::GetNPatchShader(int index)
+{
+ Shader shader;
+ const NPatchData* data;
+ // 0 is either no data (load failed?) or no stretch regions on image
+ // for both cases we use the default shader
+ NPatchUtility::StretchRanges::SizeType xStretchCount = 0;
+ NPatchUtility::StretchRanges::SizeType yStretchCount = 0;
+
+ // ask loader for the regions
+ if(mNPatchLoader.GetNPatchData(mBrokenImageInfoContainer[index].npatchId, data))
+ {
+ xStretchCount = data->GetStretchPixelsX().Count();
+ yStretchCount = data->GetStretchPixelsY().Count();
+ }
+
+ if(DALI_LIKELY((xStretchCount == 0 && yStretchCount == 0)))
+ {
+ shader = GetShader(VisualFactoryCache::NINE_PATCH_SHADER);
+ if(DALI_UNLIKELY(!shader))
+ {
+ shader = Shader::New(SHADER_NPATCH_VISUAL_3X3_SHADER_VERT, SHADER_NPATCH_VISUAL_SHADER_FRAG);
+
+ // Only cache vanilla 9 patch shaders
+ SaveShader(VisualFactoryCache::NINE_PATCH_SHADER, shader);
+ }
+ }
+ else if(xStretchCount > 0 || yStretchCount > 0)
+ {
+ std::stringstream vertexShader;
+ vertexShader << "#define FACTOR_SIZE_X " << xStretchCount + 2 << "\n"
+ << "#define FACTOR_SIZE_Y " << yStretchCount + 2 << "\n"
+ << SHADER_NPATCH_VISUAL_SHADER_VERT;
+ shader = Shader::New(vertexShader.str(), SHADER_NPATCH_VISUAL_SHADER_FRAG);
+ }
+ return shader;
+}
+
+void VisualFactoryCache::RegisterStretchProperties(Renderer& renderer, const char* uniformName, const NPatchUtility::StretchRanges& stretchPixels, uint16_t imageExtent)
+{
+ uint16_t prevEnd = 0;
+ uint16_t prevFix = 0;
+ uint16_t prevStretch = 0;
+ unsigned int i = 1;
+ for(NPatchUtility::StretchRanges::ConstIterator it = stretchPixels.Begin(); it != stretchPixels.End(); ++it, ++i)
+ {
+ uint16_t start = it->GetX();
+ uint16_t end = it->GetY();
+
+ uint16_t fix = prevFix + start - prevEnd;
+ uint16_t stretch = prevStretch + end - start;
+
+ std::stringstream uniform;
+ uniform << uniformName << "[" << i << "]";
+ renderer.RegisterProperty(uniform.str(), Vector2(fix, stretch));
+
+ prevEnd = end;
+ prevFix = fix;
+ prevStretch = stretch;
+ }
+
+ {
+ prevFix += imageExtent - prevEnd;
+ std::stringstream uniform;
+ uniform << uniformName << "[" << i << "]";
+ renderer.RegisterProperty(uniform.str(), Vector2(prevFix, prevStretch));
+ }
+}
+
+void VisualFactoryCache::ApplyTextureAndUniforms(Renderer& renderer, int index)
+{
+ const NPatchData* data;
+ TextureSet textureSet;
+ if(mNPatchLoader.GetNPatchData(mBrokenImageInfoContainer[index].npatchId, data) && data->GetLoadingState() == NPatchData::LoadingState::LOAD_COMPLETE)
+ {
+ textureSet = data->GetTextures();
+ mBrokenImageInfoContainer[index].texture = data->GetTextures().GetTexture(0);
+
+ if(data->GetStretchPixelsX().Size() == 1 && data->GetStretchPixelsY().Size() == 1)
+ {
+ //special case for 9 patch
+ Uint16Pair stretchX = data->GetStretchPixelsX()[0];
+ Uint16Pair stretchY = data->GetStretchPixelsY()[0];
+
+ uint16_t stretchWidth = (stretchX.GetY() >= stretchX.GetX()) ? stretchX.GetY() - stretchX.GetX() : 0;
+ uint16_t stretchHeight = (stretchY.GetY() >= stretchY.GetX()) ? stretchY.GetY() - stretchY.GetX() : 0;
+
+ renderer.RegisterProperty("uFixed[0]", Vector2::ZERO);
+ renderer.RegisterProperty("uFixed[1]", Vector2(stretchX.GetX(), stretchY.GetX()));
+ renderer.RegisterProperty("uFixed[2]", Vector2(data->GetCroppedWidth() - stretchWidth, data->GetCroppedHeight() - stretchHeight));
+ renderer.RegisterProperty("uStretchTotal", Vector2(stretchWidth, stretchHeight));
+ }
+ else
+ {
+ renderer.RegisterProperty("uNinePatchFactorsX[0]", Vector2::ZERO);
+ renderer.RegisterProperty("uNinePatchFactorsY[0]", Vector2::ZERO);
+
+ RegisterStretchProperties(renderer, "uNinePatchFactorsX", data->GetStretchPixelsX(), data->GetCroppedWidth());
+ RegisterStretchProperties(renderer, "uNinePatchFactorsY", data->GetStretchPixelsY(), data->GetCroppedHeight());
+ }
+ renderer.SetTextures(textureSet);
+ }
+}
+
+void VisualFactoryCache::UpdateBrokenImageRenderer(Renderer& renderer, const Vector2& size)
+{
+ // Load Information for broken image
+ for(uint32_t index = 0; index < mBrokenImageInfoContainer.size(); index++)
+ {
+ if(mBrokenImageInfoContainer[index].width == 0 && mBrokenImageInfoContainer[index].height == 0)
+ {
+ if(!mBrokenImageInfoContainer[index].url.empty())
+ {
+ VisualUrl visualUrl(mBrokenImageInfoContainer[index].url);
+ mBrokenImageInfoContainer[index].visualType = visualUrl.GetType();
+ if(mBrokenImageInfoContainer[index].visualType == VisualUrl::Type::N_PATCH)
+ {
+ const NPatchData* data;
+ Rect<int> border;
+ mBrokenImageInfoContainer[index].npatchId = mNPatchLoader.Load( mTextureManager, NULL, mBrokenImageInfoContainer[index].url, border, mPreMultiplyOnLoad, true);
+ if(mNPatchLoader.GetNPatchData(mBrokenImageInfoContainer[index].npatchId, data) && data->GetLoadingState() == NPatchData::LoadingState::LOAD_COMPLETE)
+ {
+ mBrokenImageInfoContainer[index].width = data->GetCroppedWidth();
+ mBrokenImageInfoContainer[index].height = data->GetCroppedHeight();
+ }
+ else
+ {
+ DALI_LOG_ERROR("Can't update renderer for broken image. maybe image loading is failed [path:%s] \n",mBrokenImageInfoContainer[index].url.c_str());
+ }
+ }
+ else
+ {
+ GetBrokenVisualImage(index);
+ }
+ }
+ }
+ }
+
+ // Set Texutre to renderer
+ int brokenIndex = GetProperBrokenImageIndex(size);
+ if(GetBrokenImageVisualType(brokenIndex) == VisualUrl::N_PATCH)
+ {
+ // Set geometry and shader for npatch
+ Geometry geometry = GetNPatchGeometry(brokenIndex);
+ Shader shader = GetNPatchShader(brokenIndex);
+ renderer.SetGeometry(geometry);
+ renderer.SetShader(shader);
+ ApplyTextureAndUniforms(renderer, brokenIndex);
+ }
+ else
+ {
+ Texture brokenImage = GetBrokenVisualImage(brokenIndex);
+ TextureSet textureSet = TextureSet::New();
+ textureSet.SetTexture(0u, brokenImage);
+ renderer.SetTextures(textureSet);
+ }
+}
+
+int32_t VisualFactoryCache::GetProperBrokenImageIndex(const Vector2& size)
+{
+ // Sets the default broken type
+ int32_t returnIndex = 0;
+ if((size.width == 0 || size.height == 0))
+ {
+ // To do : Need to add observer about size
+ return returnIndex;
+ }
+
+ // Find the proper value if we know the size of the image
+ for(int32_t index = static_cast<int32_t>(mBrokenImageInfoContainer.size()) - 1; index >= 0; index--)
+ {
+ // Skip if the value is not set
+ if(mBrokenImageInfoContainer[index].width == 0 || mBrokenImageInfoContainer[index].height == 0)
+ {
+ continue;
+ }
+
+ if(mBrokenImageInfoContainer[index].width < size.width && mBrokenImageInfoContainer[index].height < size.height)
+ {
+ returnIndex = index;
+ break;
+ }
}
- mAtlasManager->SetBrokenImage(mBrokenImageUrl);
+ return returnIndex;
}
} // namespace Internal
#include <dali-toolkit/internal/visuals/npatch-loader.h>
#include <dali-toolkit/internal/visuals/svg/svg-rasterize-thread.h>
#include <dali-toolkit/internal/visuals/texture-manager-impl.h>
+#include <dali/devel-api/rendering/renderer-devel.h>
namespace Dali
{
static Geometry CreateGridGeometry(Uint16Pair gridSize);
/**
- * @brief Returns a new Texture to use when a visual has failed to correctly render
- * @return The broken image texture.
- */
- Texture GetBrokenVisualImage();
-
- /**
* @copydoc Toolkit::VisualFactory::SetPreMultiplyOnLoad()
*/
void SetPreMultiplyOnLoad(bool preMultiply);
/**
* @brief Set an image to be used when a visual has failed to correctly render
- * @param[in] brokenImageUrl The broken image url.
+ * @param[in] brokenImageUrlList The broken image url list
*/
- void SetBrokenImageUrl(const std::string& brokenImageUrl);
+ void SetBrokenImageUrl(const std::vector<std::string>& brokenImageUrlList);
+
+ /**
+ * @brief Update the broken image Renderer object
+ * @param[in,out] renderer renderer for broken image
+ * @param[in] size the size of actor
+ */
+ void UpdateBrokenImageRenderer(Renderer& renderer, const Vector2& size);
public:
/**
VisualFactoryCache& operator=(const VisualFactoryCache& rhs);
private:
+ /**
+ * @brief Returns a cached Texture to use when a visual has failed to correctly render
+ * @param[in] brokenIndex The index of broken image
+ *
+ * @return The broken image texture.
+ */
+ Texture GetBrokenVisualImage(uint32_t brokenIndex);
+
+ /**
+ * @brief Gets the Proper broken image index
+ * @param[in] size The size of actor
+ *
+ * @return The index of broken image
+ */
+ int32_t GetProperBrokenImageIndex(const Vector2& size);
+
+ /**
+ * @brief Apply a texture and uniforms
+ *
+ * @param[in,out] renderer The renderer for broken image
+ * @param[in] index The index of broken image
+ */
+ void ApplyTextureAndUniforms(Renderer& renderer, int index);
+
+ /**
+ * @brief Creates a Npatch Geometry object
+ *
+ * @param[in] gridSize The gridSize for creating a geometry
+ * @return The Geometry for NPatch
+ */
+ Geometry CreateNPatchGeometry(Uint16Pair gridSize);
+
+ /**
+ * @brief Gets a geometry for npatch image
+ *
+ * @param[in] index the index of broken image
+ * @return The Geometry for NPatch
+ */
+ Geometry GetNPatchGeometry(int index);
+
+ /**
+ * @brief Gets the Npatch Shader object
+ *
+ * @param[in] index The index of broken image
+ * @return The Shader for NPatch
+ */
+ Shader GetNPatchShader(int index);
+
+ /**
+ * @brief Registers a properties for Stretch Ranges
+ *
+ * @param[in,out] renderer The renderer for broken image
+ * @param[in] uniformName The name of the uniform
+ * @param[in] stretchPixels The stretchable pixels in the cropped image space
+ * @param[in] imageExtent The imageExtent
+ */
+ void RegisterStretchProperties(Renderer& renderer, const char* uniformName, const NPatchUtility::StretchRanges& stretchPixels, uint16_t imageExtent);
+
+ /**
+ * @brief Returns a broken image type
+ * @param[in] index BrokenImage index
+ * @return The broken image type.
+ */
+ VisualUrl::Type GetBrokenImageVisualType(int index);
+
+private:
+ struct BrokenImageInfo
+ {
+ BrokenImageInfo()
+ :visualType(),
+ url(""),
+ npatchId(NPatchData::INVALID_NPATCH_DATA_ID),
+ texture(),
+ width(0),
+ height(0)
+ {
+ }
+
+ ~BrokenImageInfo()
+ {
+ }
+
+ // Data
+ VisualUrl::Type visualType;
+ std::string url;
+ NPatchData::NPatchDataId npatchId;
+ Texture texture;
+ uint32_t width;
+ uint32_t height;
+ };
+
Geometry mGeometry[GEOMETRY_TYPE_MAX + 1];
Shader mShader[SHADER_TYPE_MAX + 1];
ImageAtlasManagerPtr mAtlasManager;
TextureManager mTextureManager;
NPatchLoader mNPatchLoader;
- Texture mBrokenImageTexture;
+
SvgRasterizeThread* mSvgRasterizeThread;
std::unique_ptr<VectorAnimationManager> mVectorAnimationManager;
- std::string mBrokenImageUrl;
bool mPreMultiplyOnLoad;
+ std::vector<BrokenImageInfo> mBrokenImageInfoContainer;
};
} // namespace Internal
{
if(type == StyleChange::THEME_CHANGE)
{
- const std::string imageDirPath = AssetManager::GetDaliImagePath();
- std::string brokenImageUrl = imageDirPath + BROKEN_IMAGE_FILE_NAME;
-
- Property::Map config = Toolkit::DevelStyleManager::GetConfigurations(styleManager);
- config["brokenImageUrl"].Get(brokenImageUrl);
-
- if(mFactoryCache)
- {
- mFactoryCache->SetBrokenImageUrl(brokenImageUrl);
- }
+ SetBrokenImageUrl(styleManager);
}
}
+void VisualFactory::OnBrokenImageChangedSignal(Toolkit::StyleManager styleManager)
+{
+ SetBrokenImageUrl(styleManager);
+}
+
Toolkit::Visual::Base VisualFactory::CreateVisual(const Property::Map& propertyMap)
{
Visual::BasePtr visualPtr;
visualPtr = NPatchVisual::New(GetFactoryCache(), GetImageVisualShaderFactory(), visualUrl, propertyMap);
break;
}
+ case VisualUrl::TVG:
case VisualUrl::SVG:
{
visualPtr = SvgVisual::New(GetFactoryCache(), GetImageVisualShaderFactory(), visualUrl, propertyMap);
visualPtr = NPatchVisual::New(GetFactoryCache(), GetImageVisualShaderFactory(), visualUrl);
break;
}
+ case VisualUrl::TVG:
case VisualUrl::SVG:
{
visualPtr = SvgVisual::New(GetFactoryCache(), GetImageVisualShaderFactory(), visualUrl);
return GetFactoryCache().GetTextureManager();
}
+void VisualFactory::SetBrokenImageUrl(Toolkit::StyleManager& styleManager)
+{
+ const std::string imageDirPath = AssetManager::GetDaliImagePath();
+ std::string brokenImageUrl = imageDirPath + BROKEN_IMAGE_FILE_NAME;
+ std::vector<std::string> customBrokenImageUrlList;
+
+ if(styleManager)
+ {
+ customBrokenImageUrlList = Toolkit::DevelStyleManager::GetBrokenImageUrlList(styleManager);
+ if(customBrokenImageUrlList.size() == 0)
+ {
+ Property::Map config = Toolkit::DevelStyleManager::GetConfigurations(styleManager);
+ config["brokenImageUrl"].Get(brokenImageUrl);
+ customBrokenImageUrlList.push_back(brokenImageUrl);
+ }
+ mFactoryCache->SetBrokenImageUrl(customBrokenImageUrlList);
+ }
+ else
+ {
+ // Set default image
+ customBrokenImageUrlList.push_back(brokenImageUrl);
+ mFactoryCache->SetBrokenImageUrl(customBrokenImageUrlList);
+ }
+}
+
Internal::VisualFactoryCache& VisualFactory::GetFactoryCache()
{
if(!mFactoryCache)
{
mFactoryCache = std::unique_ptr<VisualFactoryCache>(new VisualFactoryCache(mPreMultiplyOnLoad));
-
- const std::string imageDirPath = AssetManager::GetDaliImagePath();
- std::string brokenImageUrl = imageDirPath + BROKEN_IMAGE_FILE_NAME;
-
Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
if(styleManager)
{
- Property::Map config = Toolkit::DevelStyleManager::GetConfigurations(styleManager);
- config["brokenImageUrl"].Get(brokenImageUrl);
styleManager.StyleChangedSignal().Connect(mSlotDelegate, &VisualFactory::OnStyleChangedSignal);
+ Toolkit::DevelStyleManager::BrokenImageChangedSignal(styleManager).Connect(mSlotDelegate, &VisualFactory::OnBrokenImageChangedSignal);
}
-
- mFactoryCache->SetBrokenImageUrl(brokenImageUrl);
+ SetBrokenImageUrl(styleManager);
}
return *mFactoryCache;
}
void OnStyleChangedSignal(Toolkit::StyleManager styleManager, StyleChange::Type type);
/**
+ * @brief BrokenImageChanged callback
+ *
+ * @param[in] styleManager Handle for style manager.
+ */
+ void OnBrokenImageChangedSignal(Toolkit::StyleManager styleManager);
+
+ /**
* @copydoc Toolkit::VisualFactory::CreateVisual( const Property::Map& )
*/
Toolkit::Visual::Base CreateVisual(const Property::Map& propertyMap);
private:
/**
+ * @brief Set the Broken Image url
+ * @param[in] styleManager The instance of StyleManager
+ */
+ void SetBrokenImageUrl(Toolkit::StyleManager& styleManager);
+
+ /**
* Get the factory cache, creating it if necessary.
*/
Internal::VisualFactoryCache& GetFactoryCache();
char GIF[4] = {'f', 'i', 'g', '.'};
char WEBP[5] = {'p', 'b', 'e', 'w', '.'};
char JSON[5] = {'n', 'o', 's', 'j', '.'};
+ char TVG[4] = {'g', 'v', 't', '.'};
unsigned int svgScore = 0;
+ unsigned int tvgScore = 0;
unsigned int gifScore = 0;
unsigned int webpScore = 0;
unsigned int jsonScore = 0;
return VisualUrl::SVG;
}
}
+ if((offsetFromEnd < sizeof(TVG)) && (currentChar == TVG[offsetFromEnd]))
+ {
+ // early out if TVG as can't be used in N patch for now
+ if(++tvgScore == sizeof(TVG))
+ {
+ return VisualUrl::TVG;
+ }
+ }
if((offsetFromEnd < sizeof(GIF)) && (currentChar == GIF[offsetFromEnd]))
{
// early out if GIF as can't be used in N patch for now
SVG,
GIF,
WEBP,
- JSON
+ JSON,
+ TVG
};
enum ProtocolType
#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/focus-manager/keyinput-focus-manager.h>
-#include <dali-toolkit/devel-api/visuals/color-visual-actions-devel.h>
+#include <dali-toolkit/devel-api/visuals/visual-actions-devel.h>
#include <dali-toolkit/devel-api/visuals/color-visual-properties-devel.h>
#include <dali-toolkit/internal/controls/control/control-data-impl.h>
#include <dali-toolkit/internal/styling/style-manager-impl.h>
if(visual && visual.GetType() == Toolkit::Visual::COLOR)
{
// Update background color only
- mImpl->DoAction(Toolkit::Control::Property::BACKGROUND, DevelColorVisual::Action::UPDATE_PROPERTY, map);
+ mImpl->DoAction(Toolkit::Control::Property::BACKGROUND, DevelVisual::Action::UPDATE_PROPERTY, map);
return;
}
mImpl->SignalDisconnected(slotObserver, callback);
}
+void Control::MakeVisualTransition(Dali::Property::Map& sourcePropertyMap, Dali::Property::Map& destinationPropertyMap,
+ Dali::Toolkit::Control source, Dali::Toolkit::Control destination, Dali::Property::Index visualIndex)
+{
+ sourcePropertyMap.Clear();
+ destinationPropertyMap.Clear();
+
+ Toolkit::Visual::Base sourceVisual = DevelControl::GetVisual(GetImplementation(source), visualIndex);
+ Toolkit::Visual::Base destinationVisual = DevelControl::GetVisual(GetImplementation(destination), visualIndex);
+
+ // If source or destination doesn't have the visual, do not create transition for the visual.
+ if(!sourceVisual || !destinationVisual)
+ {
+ return;
+ }
+
+ Property::Map sourceMap;
+ Property::Map destinationMap;
+ sourceVisual.CreatePropertyMap(sourceMap);
+ destinationVisual.CreatePropertyMap(destinationMap);
+
+ static auto findValueVector4 = [](const Property::Map& map, Property::Index index, const Vector4& defaultValue = Vector4()) -> Vector4
+ {
+ Property::Value* propertyValue = map.Find(index);
+ if(propertyValue)
+ {
+ return propertyValue->Get<Vector4>();
+ }
+ return defaultValue;
+ };
+
+ static auto findValueFloat = [](const Property::Map& map, Property::Index index, const float& defaultValue = 0.0f) -> float
+ {
+ Property::Value* propertyValue = map.Find(index);
+ if(propertyValue)
+ {
+ return propertyValue->Get<float>();
+ }
+ return defaultValue;
+ };
+
+ Vector4 defaultMixColor(Color::TRANSPARENT);
+ Vector4 defaultCornerRadius(0.0f, 0.0f, 0.0f, 0.0f);
+ float defaultBorderlineWidth(0.0f);
+ Vector4 defaultBorderlineColor(0.0f, 0.0f, 0.0f, 1.0f);
+ float defaultBorderlineOffset(0.0f);
+
+ Vector4 sourceMixColor = findValueVector4(sourceMap, Dali::Toolkit::Visual::Property::MIX_COLOR, defaultMixColor);
+ Vector4 sourceCornerRadius = findValueVector4(sourceMap, Toolkit::DevelVisual::Property::CORNER_RADIUS, defaultCornerRadius);
+ float sourceBorderlineWidth = findValueFloat(sourceMap, Toolkit::DevelVisual::Property::BORDERLINE_WIDTH, defaultBorderlineWidth);
+ Vector4 sourceBorderlineColor = findValueVector4(sourceMap, Toolkit::DevelVisual::Property::BORDERLINE_COLOR, defaultBorderlineColor);
+ float sourceBorderlineOffset = findValueFloat(sourceMap, Toolkit::DevelVisual::Property::BORDERLINE_OFFSET, defaultBorderlineOffset);
+
+ Vector4 destinationMixColor = findValueVector4(destinationMap, Dali::Toolkit::Visual::Property::MIX_COLOR, defaultMixColor);
+ Vector4 destinationCornerRadius = findValueVector4(destinationMap, Toolkit::DevelVisual::Property::CORNER_RADIUS, defaultCornerRadius);
+ float destinationBorderlineWidth = findValueFloat(destinationMap, Toolkit::DevelVisual::Property::BORDERLINE_WIDTH, defaultBorderlineWidth);
+ Vector4 destinationBorderlineColor = findValueVector4(destinationMap, Toolkit::DevelVisual::Property::BORDERLINE_COLOR, defaultBorderlineColor);
+ float destinationBorderlineOffset = findValueFloat(destinationMap, Toolkit::DevelVisual::Property::BORDERLINE_OFFSET, defaultBorderlineOffset);
+
+ // If the value of the source Control and that of destination Control is different, the property should be transitioned.
+ if(Vector3(sourceMixColor) != Vector3(destinationMixColor))
+ {
+ sourcePropertyMap.Add(Dali::Toolkit::Visual::Property::MIX_COLOR, Vector3(sourceMixColor));
+ destinationPropertyMap.Add(Dali::Toolkit::Visual::Property::MIX_COLOR, Vector3(destinationMixColor));
+ }
+
+ if(std::abs(sourceMixColor.a - destinationMixColor.a) > Math::MACHINE_EPSILON_1)
+ {
+ sourcePropertyMap.Add(Dali::Toolkit::Visual::Property::OPACITY, sourceMixColor.a);
+ destinationPropertyMap.Add(Dali::Toolkit::Visual::Property::OPACITY, destinationMixColor.a);
+ }
+
+ if(sourceCornerRadius != destinationCornerRadius)
+ {
+ sourcePropertyMap.Add(Dali::Toolkit::DevelVisual::Property::CORNER_RADIUS, sourceCornerRadius);
+ destinationPropertyMap.Add(Dali::Toolkit::DevelVisual::Property::CORNER_RADIUS, destinationCornerRadius);
+ }
+
+ if(sourceBorderlineWidth != destinationBorderlineWidth)
+ {
+ sourcePropertyMap.Add(Dali::Toolkit::DevelVisual::Property::BORDERLINE_WIDTH, sourceBorderlineWidth);
+ destinationPropertyMap.Add(Dali::Toolkit::DevelVisual::Property::BORDERLINE_WIDTH, destinationBorderlineWidth);
+ }
+
+ if(sourceBorderlineColor != destinationBorderlineColor)
+ {
+ sourcePropertyMap.Add(Dali::Toolkit::DevelVisual::Property::BORDERLINE_COLOR, sourceBorderlineColor);
+ destinationPropertyMap.Add(Dali::Toolkit::DevelVisual::Property::BORDERLINE_COLOR, destinationBorderlineColor);
+ }
+
+ if(sourceBorderlineOffset != destinationBorderlineOffset)
+ {
+ sourcePropertyMap.Add(Dali::Toolkit::DevelVisual::Property::BORDERLINE_OFFSET, sourceBorderlineOffset);
+ destinationPropertyMap.Add(Dali::Toolkit::DevelVisual::Property::BORDERLINE_OFFSET, destinationBorderlineOffset);
+ }
+}
+
Control& GetImplementation(Dali::Toolkit::Control& handle)
{
CustomActorImpl& customInterface = handle.GetImplementation();
namespace Internal
{
+
/**
* @brief This is the internal base class for all controls.
*
return NULL;
}
- // Transition
+ // Transition APIs
+
+ /**
+ * @brief Make visual transition from source control to destination control about specific Visual.
+ * If both of source and destination control have same visual index, than generates information for the transition of this Control.
+ *
+ * @param[out] sourcePropertyMap Source property map to be applied on this Control.
+ * @param[out] destinationPropertyMap Destination property map to be applied on this Control.
+ * @param[in] source Source control of the animation.
+ * @param[in] destination Destination control of the animation.
+ * @param[in] visualIndex Property::Index to make animation.
+ */
+ void MakeVisualTransition(Dali::Property::Map& sourcePropertyMap, Dali::Property::Map& destinationPropertyMap,
+ Dali::Toolkit::Control source, Dali::Toolkit::Control destination, Dali::Property::Index visualIndex);
/**
- * @brief Retrieve visual property animations.
- * This Control is a destination.
+ * @brief Retrieves source and destination visual properties for the Transition of this Control.
+ * The properties of this Control will be transitioned from the propeties of source Control to that of destination control.
+ * If a property value is different between source and destination Control,
+ * the property information of each Control will be included in sourceProperties and destinationProperties.
+ *
+ * @param[out] sourceProperties Source property list to be applied on this Control.
+ * @param[out] destinationProperties Destination property list to be applied on this Control.
+ * @param[in] source Source control of the animation.
+ * @param[in] destination Destination control of the animation.
*
- * @param[in] animation generated animation
- * @param[in] source source control of the animation.
- * @param[in] alphaFunction AlphaFunction of the animation
- * @param[in] timePeriod TimePeriod of the animation
+ * @note This method do not handle Actor properties.
+ * And the size and order of the sourceProperties and destinationProperties must be synchronized.
+ */
+ virtual void OnCreateTransitions(std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>>& sourceProperties,
+ std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>>& destinationProperties,
+ Dali::Toolkit::Control source,
+ Dali::Toolkit::Control destination)
+ {
+ }
+
+ /**
+ * @brief Update visual properties.
+ * @param[in] properties Property list to be used to update visual properties of this Control.
*/
- virtual void OnCreateTransitions(Dali::Animation& animation, Dali::Toolkit::Control source, AlphaFunction alphaFunction, TimePeriod timePeriod)
+ virtual void OnUpdateVisualProperties(const std::vector<std::pair<Dali::Property::Index, Dali::Property::Map>>& properties)
{
}
return Control::DownCast<GlView, Internal::GlView>(handle);
}
-void GlView::RegisterGlCallback(CallbackBase* initCallback, CallbackBase* renderFrameCallback, CallbackBase* terminateCallback)
+void GlView::RegisterGlCallbacks(CallbackBase* initCallback, CallbackBase* renderFrameCallback, CallbackBase* terminateCallback)
{
- Dali::Toolkit::GetImpl(*this).RegisterGlCallback(initCallback, renderFrameCallback, terminateCallback);
+ Dali::Toolkit::GetImpl(*this).RegisterGlCallbacks(initCallback, renderFrameCallback, terminateCallback);
}
void GlView::SetResizeCallback(CallbackBase* resizeCallback)
* <b>You can't call Dali APIs in your callbacks because it is invoked in GlView's own render thread.</b>
* And this must be called before adding GlView to the scene.
*/
- void RegisterGlCallback(CallbackBase* initCallback, CallbackBase* renderFrameCallback, CallbackBase* terminateCallback);
+ void RegisterGlCallbacks(CallbackBase* initCallback, CallbackBase* renderFrameCallback, CallbackBase* terminateCallback);
/**
* @brief Sets the ResizeCallback of the GlView.
{
const unsigned int TOOLKIT_MAJOR_VERSION = 2;
const unsigned int TOOLKIT_MINOR_VERSION = 0;
-const unsigned int TOOLKIT_MICRO_VERSION = 45;
+const unsigned int TOOLKIT_MICRO_VERSION = 50;
const char* const TOOLKIT_BUILD_DATE = __DATE__ " " __TIME__;
#ifdef DEBUG_ENABLED
{
}
-Transition Transition::New(Dali::Toolkit::Control source, Dali::Toolkit::Control destination, TimePeriod timePeriod)
+Transition Transition::New(Dali::Toolkit::Control source, Dali::Toolkit::Control destination, bool useDestinationTarget, TimePeriod timePeriod)
{
- Internal::TransitionPtr internal = Dali::Toolkit::Internal::Transition::New(source, destination, timePeriod);
+ Internal::TransitionPtr internal = Dali::Toolkit::Internal::Transition::New(source, destination, useDestinationTarget, timePeriod);
return Transition(internal.Get());
}
/**
* @brief Creates an initialized Transition.
*
- * @param[in] source Source
- * @param[in] destination Destination
+ * @param[in] source A source control of this transition.
+ * @param[in] destination A destination control of this transition.
+ * @param[in] useDestinationTarget True if this transition uses destination control as target.
* @param[in] timePeriod The duration in seconds
* @return A handle to a newly allocated Dali resource
* @note durationSeconds can not be negative.
*/
- static Transition New(Dali::Toolkit::Control source, Dali::Toolkit::Control destination, TimePeriod timePeriod);
+ static Transition New(Dali::Toolkit::Control source, Dali::Toolkit::Control destination, bool useDestinationTarget, TimePeriod timePeriod);
/**
* @brief Downcasts a handle to Transition handle.
Name: dali2-toolkit
Summary: Dali 3D engine Toolkit
-Version: 2.0.45
+Version: 2.0.50
Release: 1
Group: System/Libraries
License: Apache-2.0 and BSD-3-Clause and MIT