From d82a70dff9f3217eb1f07aa3785afb5a157bc935 Mon Sep 17 00:00:00 2001 From: bshsqa <32317749+bshsqa@users.noreply.github.com> Date: Wed, 19 Aug 2020 16:03:16 +0900 Subject: [PATCH] [NUI] Sample app for Frame callback. (#1925) - Touch the screen then launcher icons are appeared - The icons can be moved by using finger gesture. - If a icon is moved by gesture, others follow it with small delay(0.03s) - the delayed animation is computed in the frame callback Signed-off-by: seungho Co-authored-by: seungho --- .../Tizen.NUI.Samples/Samples/FrameCallbackTest.cs | 757 +++++++++++++++++++++ .../FrameCallbackTest/launcher_bg_01_nor.png | Bin 0 -> 1597 bytes .../FrameCallbackTest/launcher_bg_02_nor.png | Bin 0 -> 1921 bytes .../FrameCallbackTest/launcher_bg_03_nor.png | Bin 0 -> 1925 bytes .../FrameCallbackTest/launcher_bg_04_nor.png | Bin 0 -> 2038 bytes .../FrameCallbackTest/launcher_bg_05_nor.png | Bin 0 -> 2028 bytes .../FrameCallbackTest/launcher_bg_06_nor.png | Bin 0 -> 1209 bytes .../FrameCallbackTest/launcher_bg_apps_nor.png | Bin 0 -> 1732 bytes .../FrameCallbackTest/launcher_ic_apps_nor.png | Bin 0 -> 1987 bytes .../FrameCallbackTest/launcher_ic_culinary_nor.png | Bin 0 -> 2465 bytes .../FrameCallbackTest/launcher_ic_ent_nor.png | Bin 0 -> 1914 bytes .../FrameCallbackTest/launcher_ic_family_nor.png | Bin 0 -> 2376 bytes .../FrameCallbackTest/launcher_ic_homecare_nor.png | Bin 0 -> 2645 bytes .../FrameCallbackTest/launcher_ic_internet_nor.png | Bin 0 -> 2056 bytes .../launcher_ic_logo_amazon_nor.png | Bin 0 -> 4188 bytes .../FrameCallbackTest/launcher_ic_settings_nor.png | Bin 0 -> 2013 bytes .../FrameCallbackTest/launcher_ic_timer_nor.png | Bin 0 -> 1880 bytes .../launcher_ic_viewinside_nor.png | Bin 0 -> 1627 bytes 18 files changed, 757 insertions(+) create mode 100644 test/Tizen.NUI.Samples/Tizen.NUI.Samples/Samples/FrameCallbackTest.cs create mode 100644 test/Tizen.NUI.Samples/Tizen.NUI.Samples/res/images/FrameCallbackTest/launcher_bg_01_nor.png create mode 100644 test/Tizen.NUI.Samples/Tizen.NUI.Samples/res/images/FrameCallbackTest/launcher_bg_02_nor.png create mode 100644 test/Tizen.NUI.Samples/Tizen.NUI.Samples/res/images/FrameCallbackTest/launcher_bg_03_nor.png create mode 100644 test/Tizen.NUI.Samples/Tizen.NUI.Samples/res/images/FrameCallbackTest/launcher_bg_04_nor.png create mode 100644 test/Tizen.NUI.Samples/Tizen.NUI.Samples/res/images/FrameCallbackTest/launcher_bg_05_nor.png create mode 100644 test/Tizen.NUI.Samples/Tizen.NUI.Samples/res/images/FrameCallbackTest/launcher_bg_06_nor.png create mode 100644 test/Tizen.NUI.Samples/Tizen.NUI.Samples/res/images/FrameCallbackTest/launcher_bg_apps_nor.png create mode 100644 test/Tizen.NUI.Samples/Tizen.NUI.Samples/res/images/FrameCallbackTest/launcher_ic_apps_nor.png create mode 100644 test/Tizen.NUI.Samples/Tizen.NUI.Samples/res/images/FrameCallbackTest/launcher_ic_culinary_nor.png create mode 100644 test/Tizen.NUI.Samples/Tizen.NUI.Samples/res/images/FrameCallbackTest/launcher_ic_ent_nor.png create mode 100644 test/Tizen.NUI.Samples/Tizen.NUI.Samples/res/images/FrameCallbackTest/launcher_ic_family_nor.png create mode 100644 test/Tizen.NUI.Samples/Tizen.NUI.Samples/res/images/FrameCallbackTest/launcher_ic_homecare_nor.png create mode 100644 test/Tizen.NUI.Samples/Tizen.NUI.Samples/res/images/FrameCallbackTest/launcher_ic_internet_nor.png create mode 100644 test/Tizen.NUI.Samples/Tizen.NUI.Samples/res/images/FrameCallbackTest/launcher_ic_logo_amazon_nor.png create mode 100644 test/Tizen.NUI.Samples/Tizen.NUI.Samples/res/images/FrameCallbackTest/launcher_ic_settings_nor.png create mode 100644 test/Tizen.NUI.Samples/Tizen.NUI.Samples/res/images/FrameCallbackTest/launcher_ic_timer_nor.png create mode 100644 test/Tizen.NUI.Samples/Tizen.NUI.Samples/res/images/FrameCallbackTest/launcher_ic_viewinside_nor.png diff --git a/test/Tizen.NUI.Samples/Tizen.NUI.Samples/Samples/FrameCallbackTest.cs b/test/Tizen.NUI.Samples/Tizen.NUI.Samples/Samples/FrameCallbackTest.cs new file mode 100644 index 0000000..e113d26 --- /dev/null +++ b/test/Tizen.NUI.Samples/Tizen.NUI.Samples/Samples/FrameCallbackTest.cs @@ -0,0 +1,757 @@ +using System; +using System.Threading.Tasks; +using Tizen.NUI; +using Tizen.NUI.BaseComponents; +using System.Collections.Generic; +using System.Linq; + +namespace Tizen.NUI.Samples +{ + enum TOUCH_ANIMATION_STATE + { + NO_ANIMATION = 0, + ON_ANIMATION, + ON_FINISH_ANIMATION, + END_ANIMATION = NO_ANIMATION + }; + + public class FrameCallbackTest : IExample + { + + private static string resourcePath = Tizen.Applications.Application.Current.DirectoryInfo.Resource; + private static string[] BACKGROUND_IMAGE_PATH = { + resourcePath + "/images/FrameCallbackTest/launcher_bg_02_nor.png", + resourcePath + "/images/FrameCallbackTest/launcher_bg_03_nor.png", + resourcePath + "/images/FrameCallbackTest/launcher_bg_04_nor.png", + resourcePath + "/images/FrameCallbackTest/launcher_bg_05_nor.png", + resourcePath + "/images/FrameCallbackTest/launcher_bg_06_nor.png", + resourcePath + "/images/FrameCallbackTest/launcher_bg_apps_nor.png" + }; + + private static string[] APPS_IMAGE_PATH = { + resourcePath + "/images/FrameCallbackTest/launcher_ic_culinary_nor.png", + resourcePath + "/images/FrameCallbackTest/launcher_ic_family_nor.png", + resourcePath + "/images/FrameCallbackTest/launcher_ic_ent_nor.png", + resourcePath + "/images/FrameCallbackTest/launcher_ic_homecare_nor.png" + }; + + private static string[] APPS_ICON_NAME = { + "Culinary", + "Family", + "Entertainment", + "Homecare" + }; + + private static string[] CONTROL_IMAGE_PATH = { + resourcePath + "/images/FrameCallbackTest/launcher_ic_apps_nor.png", + resourcePath + "/images/FrameCallbackTest/launcher_ic_settings_nor.png", + resourcePath + "/images/FrameCallbackTest/launcher_ic_viewinside_nor.png", + resourcePath + "/images/FrameCallbackTest/launcher_ic_timer_nor.png", + resourcePath + "/images/FrameCallbackTest/launcher_ic_internet_nor.png" + }; + + private static string[] CONTROL_ICON_NAME = { + "Apps", + "Settings", + "ViewInside", + "Timer", + "Internet" + }; + + private const int FRAME_RATE = 60; + private const int OBJECT_DELAY = 30; + private const int OBJECT_SIZE = 150; + private const int INITIAL_POSITION = 46; + private const int DEFAULT_SPACE = 9; + private const int DEVIDE_BAR_SIZE = 4; + + private TextLabel text; + public class FrameCallback : FrameCallbackInterface + { + private int mTimeInterval; + + private uint mContainerId; + private List mViewId; ///< Container of Actor IDs. + private List mViewPosition; + + // Movement is position difference of Container from start position of this animation to current position. + // Time interval between each mMovement entry is 16 milliseconds(about 60 fps) + // For example. + // mMovement[i] + mContainerStartPosition is the position of container after i*16 milliseconds from this animation started. + private List mMovement; + + // mLatestMovement is actually current movement of container. + private float mLatestMovement; + + // An icon of mTouchedViewIndex moves with container at the same time. + // Each icon of (mTouchedViewIndex -/+ i) moves as following container after i*OBJECT_DELAY milliseconds. + private int mTouchedViewIndex; + + // If every icon between mLeftIndext and mRightIndex is stopped, this frame callback can be reset. + // Then mIsResetTouchedViewPossible becomes true. + private bool mIsResetTouchedViewPossible; + private int mLeftIndex; + private int mRightIndex; + + // Total animation time from start to current. + private float mTotalAnimationTime; + // Total animation time from start to the time that last movement is added. + private float mPreviousTotalAnimationTime; + + // Start position of container in this animation. + private float mContainerStartPosition; + // Position of container at the time that last movement is added. + private float mPreviousContainerPosition; + + // This animation only need to save movement about (the number of view * OBJECT_DELAY) milliseconds. + // and this size is updated when new view is added. + // and, If the list of mMovement size become larger than this size, remove unnecessary entries. + private int mRequiredMovementSize; + private bool mNeedUpdateMovementSize; + + // current velocity. + private float mVelocity; + // dirty flag. + private bool mDirty; + + public FrameCallback() + { + mViewId = new List(); + mMovement = new List(); + mRequiredMovementSize = 0; + mNeedUpdateMovementSize = false; + mIsResetTouchedViewPossible = false; + } + + public void ResetAnimationData() + { + SetLatestMovement(0.0f); + mMovement.Clear(); + mTotalAnimationTime = 0.0f; + mPreviousTotalAnimationTime = 0.0f; + mDirty = true; + } + + public void SetTimeInterval(int timeInterval) + { + mNeedUpdateMovementSize = true; + mTimeInterval = timeInterval; + } + + public void AddId(uint id) + { + mViewId.Add(id); + mNeedUpdateMovementSize = true; + } + + public void SetContainerId(uint id) + { + mContainerId = id; + } + + public void SetContainerStartPosition(float position) + { + mContainerStartPosition = position; + } + + public void SetLatestMovement(float movement) + { + mLatestMovement = movement; + } + + public void ResetViewPosition() + { + mViewPosition = Enumerable.Repeat(0.0f, mViewId.Count).ToList(); + } + + public void SetViewPosition(int index, float position) + { + mViewPosition[index] = position; + } + + public void SetTouchedViewIndex(int controlIndex) + { + mTouchedViewIndex = controlIndex; + } + + public void AddMovement(float movement) + { + mMovement.Add(movement); + } + + public void SetLeftIndex(int leftIndex) + { + mLeftIndex = leftIndex; + } + + public void SetRightIndex(int rightIndex) + { + mRightIndex = rightIndex; + } + + public bool IsResetTouchedViewPossible() + { + return mIsResetTouchedViewPossible; + } + public void Dirty() + { + mDirty = true; + } + + public bool IsDirty() + { + return mDirty; + } + + public float GetVelocity() + { + return mVelocity; + } + + private void ComputeNewPositions(int totalTime) + { + // save latestMovement to avoid interference between thread. + float latestMovement = mLatestMovement; + bool isResetTouchedViewPossible = true; + for (int i = 0; i < mViewId.Count; ++i) + { + if (i == mTouchedViewIndex) + { + continue; + } + + // compute delay of view of i. + int totalDelay = Math.Abs(i - mTouchedViewIndex) * OBJECT_DELAY; + if (totalDelay > totalTime) + { + continue; + } + + int actorTime = totalTime - totalDelay; + int movementIndex = actorTime / mTimeInterval; + float factor = (float)(actorTime - (movementIndex * mTimeInterval)) / (float)mTimeInterval; + float movement; + if (movementIndex >= mMovement.Count - 1) + { + // 1. delay is zero(every view moves with container at the same time) + // 2. after every icons are stopped and the finger is stopped to move, the movement is still not added more. + // than the view has latestMovement. + movement = latestMovement; + } + else if (movementIndex < 0) + { + // If this animation is just staarted and the view need to wait more. + // movement is 0. + movement = 0.0f; + } + else + { + // Get the movement of ith view by interpolating mMovement + movement = factor * mMovement[movementIndex + 1] + (1.0f - factor) * mMovement[movementIndex]; + } + + // Prevent to overlap of each views. + float currentSpace = Math.Abs((mViewPosition[i] + movement) - (mViewPosition[mTouchedViewIndex] + latestMovement)); + float minimumSpace = (float)Math.Abs(mViewPosition[i] - mViewPosition[mTouchedViewIndex]); + if (currentSpace < minimumSpace) + { + movement = latestMovement; + } + + // check views in screen are still moving or stopped. + float newPosition = mViewPosition[i] + movement - latestMovement; + if (i >= mLeftIndex && i <= mRightIndex) + { + Vector3 previousPosition = new Vector3(); + GetPosition(mViewId[i], previousPosition); + if (Math.Abs(previousPosition.X - newPosition) >= 1.0f) + { + isResetTouchedViewPossible = false; + } + } + // update new position. + SetPosition(mViewId[i], new Vector3(newPosition, 0.0f, 0.0f)); + } + mIsResetTouchedViewPossible = isResetTouchedViewPossible; + } + + public override void OnUpdate(float elapsedSeconds) + { + // second -> millisecond + mTotalAnimationTime += elapsedSeconds * 1000.0f; + + Vector3 currentPosition = new Vector3(); + GetPosition(mContainerId, currentPosition); + + // Add new Movement, if there is change in position. + // 1. if dirty(there is reserved event) + // 2. if container position is changed. + // 3. if every icons in screen is stopped + if (mDirty || currentPosition.X != mPreviousContainerPosition || mIsResetTouchedViewPossible) + { + mDirty = false; + if (mTotalAnimationTime >= mMovement.Count * mTimeInterval) + { + // If the passed time is larger than mTimeInterval, add new movements. + // If we need to add more than one, compute each movement by using interpolation. + while (mMovement.Count <= mTotalAnimationTime / mTimeInterval) + { + float factor = ((float)(mMovement.Count * mTimeInterval) - mPreviousTotalAnimationTime) / (mTotalAnimationTime - mPreviousTotalAnimationTime); + float movement = (float)(factor * currentPosition.X + (1.0f - factor) * mPreviousContainerPosition) - mContainerStartPosition; + AddMovement(movement); + } + // Compute velocity. + // We need to compute velocity here to get reasonable value. + mVelocity = (currentPosition.X - mPreviousContainerPosition) / (mTotalAnimationTime - mPreviousTotalAnimationTime); + mPreviousTotalAnimationTime = mTotalAnimationTime; + mPreviousContainerPosition = currentPosition.X; + } + } + float currentMovement = currentPosition.X - mContainerStartPosition; + SetLatestMovement(currentMovement); + + // Compute positions of each icon + ComputeNewPositions((int)mTotalAnimationTime); + + // compute mRequiredMovementSize + if (mRequiredMovementSize == 0 || mNeedUpdateMovementSize) + { + mNeedUpdateMovementSize = false; + mRequiredMovementSize = mViewId.Count * OBJECT_DELAY / mTimeInterval; + } + + // Remove unnecessary movement for memory optimization. + if (mMovement.Count > mRequiredMovementSize * 2) + { + int movementNumberToRemove = mMovement.Count - mRequiredMovementSize; + mMovement.RemoveRange(0, movementNumberToRemove); + mTotalAnimationTime -= (float)(mTimeInterval * movementNumberToRemove); + } + } + } + + private Window mWindow; + + private FrameCallback mFrameCallback; ///< An instance of our implementation of the FrameCallbackInterface. + + // Views for launcher + private View mBaseView; + private View mControlView; + private View mLayoutView; + + // Variables for animation + private float mPreviousTouchedPosition; + private int mTouchedViewIndex; + private TOUCH_ANIMATION_STATE mAnimationState; + + private float mLeftDirectionLimit; + private float mRightDirectionLimit; + + + // Variables for Finish animation + // These variables are for deceleration curve. + // If we want to use another curve like bezier, uses different variables + private delegate float UserAlphaFunctionDelegate(float progress); + private UserAlphaFunctionDelegate customScrollAlphaFunction; + private float mAbsoluteVelocity = 0.0f; + private float mFinishAnimationDuration = 0.0f; + private float mFinishAnimationDelta = 0.0f; + private float mLogDeceleration = 0.0f; + private float mDecelerationRate = 0.99f; + private float mEasingThreshold = 0.1f; + + private Animation mFinishAnimation; + private Timer mAnimationOffTimer; // timer to end animation after the easing animation is finished + + // Vies of contents + private View mContentsView; + + public void Activate() + { + mFrameCallback = new FrameCallback(); + Initialize(); + } + + public void Deactivate() + { + } + + void Initialize() + { + // Set the stage background color and connect to the stage's key signal to allow Back and Escape to exit. + mWindow = Window.Instance; + mWindow.BackgroundColor = Color.White; + + mRightDirectionLimit = INITIAL_POSITION; + + // Contents + + mContentsView = new View(); + mContentsView.BackgroundColor = new Color(0.921568f, 0.9098039f, 0.890196f, 0.5f); + mContentsView.ParentOrigin = ParentOrigin.TopLeft; + mContentsView.PivotPoint = PivotPoint.TopLeft; + mContentsView.PositionUsesPivotPoint = true; + mContentsView.WidthResizePolicy = ResizePolicyType.FillToParent; + mContentsView.HeightResizePolicy = ResizePolicyType.FillToParent; + mWindow.GetDefaultLayer().Add(mContentsView); + + // Launcher + mBaseView = new View(); + mBaseView.ParentOrigin = ParentOrigin.BottomLeft; + mBaseView.PivotPoint = PivotPoint.BottomLeft; + mBaseView.PositionUsesPivotPoint = true; + mBaseView.Size = new Size(mWindow.Size.Width, 278); + mBaseView.Position = new Position(0, 0); + mWindow.GetDefaultLayer().Add(mBaseView); + + View iconBackgroundView = new View(); + iconBackgroundView.BackgroundColor = new Color(0.921568f, 0.9098039f, 0.890196f, 0.5f); + iconBackgroundView.ParentOrigin = ParentOrigin.BottomLeft; + iconBackgroundView.PivotPoint = PivotPoint.BottomLeft; + iconBackgroundView.PositionUsesPivotPoint = true; + iconBackgroundView.Size = new Size(mWindow.Size.Width, 278); + iconBackgroundView.Position = new Position(0, 0); + mBaseView.Add(iconBackgroundView); + + mControlView = new View(); + mControlView.ParentOrigin = ParentOrigin.CenterLeft; + mControlView.PivotPoint = PivotPoint.CenterLeft; + mControlView.PositionUsesPivotPoint = true; + mControlView.Position = new Position(mRightDirectionLimit, 0); + mBaseView.Add(mControlView); + mFrameCallback.SetContainerId(mControlView.ID); + + mLayoutView = new View(); + mLayoutView.ParentOrigin = ParentOrigin.CenterLeft; + mLayoutView.PivotPoint = PivotPoint.CenterLeft; + mLayoutView.PositionUsesPivotPoint = true; + mLayoutView.Layout = new LinearLayout() + { + LinearOrientation = LinearLayout.Orientation.Horizontal, + CellPadding = new Size2D(DEFAULT_SPACE, 0), + }; + mLayoutView.Position = new Position(0, 0); + mControlView.Add(mLayoutView); + + for (int i = 0; i < 4; ++i) + { + AddIcon(BACKGROUND_IMAGE_PATH[i], APPS_IMAGE_PATH[i], APPS_ICON_NAME[i], Color.White); + } + + View divideBar = new View(); + divideBar.BackgroundColor = new Color(0.0f, 0.0f, 0.0f, 0.1f); + divideBar.ParentOrigin = ParentOrigin.CenterLeft; + divideBar.PivotPoint = PivotPoint.CenterLeft; + divideBar.PositionUsesPivotPoint = true; + divideBar.Size = new Size(DEVIDE_BAR_SIZE, OBJECT_SIZE); + mLayoutView.Add(divideBar); + mFrameCallback.AddId(divideBar.ID); + + int iconNumber = 8; + for (int i = 0; i < iconNumber; ++i) + { + AddIcon(BACKGROUND_IMAGE_PATH[5], CONTROL_IMAGE_PATH[i % 5], CONTROL_ICON_NAME[i % 5], new Color(0.0f, 0.0f, 0.0f, 0.5f)); + } + + mFrameCallback.ResetViewPosition(); + mFrameCallback.SetTimeInterval(1000 / FRAME_RATE); + + mAnimationState = TOUCH_ANIMATION_STATE.NO_ANIMATION; + + mAnimationOffTimer = new Timer(16); + mAnimationOffTimer.Tick += OffAnimatable; + + mBaseView.TouchEvent += OnTouch; + + mFinishAnimation = new Animation(); + mFinishAnimation.Finished += EasingAnimationFinishedCallback; + mLogDeceleration = (float)Math.Log(mDecelerationRate); + } + + // Add icons + + void AddIcon(string background, string icon, string text, Color textColor) + { + ImageView backgroundView = new ImageView(); + backgroundView.ResourceUrl = background; + backgroundView.Size = new Size(OBJECT_SIZE, OBJECT_SIZE); + backgroundView.ParentOrigin = ParentOrigin.CenterLeft; + backgroundView.PivotPoint = PivotPoint.CenterLeft; + backgroundView.PositionUsesPivotPoint = true; + mLayoutView.Add(backgroundView); + mFrameCallback.AddId(backgroundView.ID); + + ImageView iconView = new ImageView(); + iconView.ResourceUrl = icon; + iconView.Position = new Position(0, -15); + iconView.ParentOrigin = ParentOrigin.Center; + iconView.PivotPoint = PivotPoint.Center; + iconView.PositionUsesPivotPoint = true; + backgroundView.Add(iconView); + + TextLabel label = new TextLabel(text); + label.Position = new Position(0, 30); + label.HorizontalAlignment = HorizontalAlignment.Center; + label.TextColor = textColor; + label.FontFamily = "SamsungOneUI"; + label.PointSize = 12; + label.ParentOrigin = ParentOrigin.Center; + label.PivotPoint = PivotPoint.Center; + label.PositionUsesPivotPoint = true; + backgroundView.Add(label); + } + + // Set frame callback to start drag animation. + private void SetFrameCallback(float position) + { + // remove frame callback if it is already added. + mWindow.RemoveFrameCallback(mFrameCallback); + + mFrameCallback.ResetAnimationData(); + mFrameCallback.AddMovement(0.0f); // Add first movement. + + // Set container start position and start positions of each icon(and vertical bar) + // And compute total container size. + float totalSize = 0.0f; + mFrameCallback.SetContainerStartPosition(mControlView.Position.X); + for (int i = 0; i < mLayoutView.ChildCount; ++i) + { + mFrameCallback.SetViewPosition(i, mLayoutView.Children[i].Position.X); + totalSize += (float)(mLayoutView.Children[i].Size.Width + DEFAULT_SPACE); + } + totalSize -= (float)DEFAULT_SPACE; + + // Find touched icon + for (int i = (int)mLayoutView.ChildCount - 1; i >= 0; --i) + { + if (position >= mLayoutView.Children[i].Position.X + mControlView.Position.X) + { + mFrameCallback.SetTouchedViewIndex(i); + mTouchedViewIndex = i; + break; + } + } + if (position < mLayoutView.Children[0].Position.X + mControlView.Position.X) + { + mFrameCallback.SetTouchedViewIndex(0); + mTouchedViewIndex = 0; + } + + mPreviousTouchedPosition = position; + + // Add frame callback on window. + // OnUpdate callback of mFrameCallback will be called before every render frame. + mWindow.AddFrameCallback(mFrameCallback); + + // compute limit position the container could go. + mLeftDirectionLimit = (float)mWindow.Size.Width - (totalSize + (float)(INITIAL_POSITION)); + + mWindow.RenderingBehavior = RenderingBehaviorType.Continuously; // make rendering be done for upto 60 fps even though there is no update in main thread. + mAnimationState = TOUCH_ANIMATION_STATE.ON_ANIMATION; // make rendering state on. + } + + private bool OnTouch(object source, View.TouchEventArgs e) + { + Vector2 position = e.Touch.GetScreenPosition(0); + + PointStateType state = e.Touch.GetState(0); + if (PointStateType.Down == state) + { + if (mAnimationState == TOUCH_ANIMATION_STATE.ON_FINISH_ANIMATION) + { + // re-birth current animation + // in case of touch during finish animation, + // quit easingAnimation and AnimationOffTimer because animation ownership is returned to the touch event again. + // AND, DO NOT RESET ALL PROPERTIES OF FRAMECALLBACK. + // because, for example, if touched icon index is changed, the movement is wrong and the animation can be not continous. + // This re-birthed animation is just for smooth moving during complex user interaction. + // during complex and fast interaction, this is not so noticeable. + // and reset of such properties will be done in the below Motion state + mFinishAnimation.Stop(); + mAnimationOffTimer.Stop(); + + // Set Animation State to ON_ANIMATION again + mAnimationState = TOUCH_ANIMATION_STATE.ON_ANIMATION; + // Set previousTouchPosition + mPreviousTouchedPosition = position.X; + } + else + { + // in case of stable state + // just set new framecallback for this touched position. + SetFrameCallback(position.X); + } + } + else if (PointStateType.Motion == state) + { + // if framecallback can be reset, quit current frame callback and re-launch new frame callback. + // because, if current frame callback is re-birthed one, the animation is not totally re-created one. + // So, some properties like touched icon index can be wrong for the continuous animation. + // But, some case like that finger is stopped and restart to move, this could make weired feeling. + // We reset mFrameCallback as soon as possible we can. And the conditions are ... + // 1. icons in screen is stopped. + // 2. velocity of frame callback is 0.0 (this frame callback will not move again instantly) + // 3. frame callback is not dirty (there is no reserved action) + if (mFrameCallback.IsResetTouchedViewPossible() && mFrameCallback.GetVelocity() == 0.0f && !mFrameCallback.IsDirty()) + { + SetFrameCallback(position.X); + } + + // Set new controlView(container) position + // in here, we need to consider the container is not go outside of limits. + float containerPosition = mControlView.Position.X + (position.X - mPreviousTouchedPosition); + containerPosition = Math.Min(containerPosition, mRightDirectionLimit); + containerPosition = Math.Max(containerPosition, mLeftDirectionLimit); + float adjustedPosition = containerPosition - mControlView.Position.X + mPreviousTouchedPosition; + mPreviousTouchedPosition = adjustedPosition; + mControlView.Position.X = containerPosition; + } + else if ((PointStateType.Up == state || PointStateType.Leave == state || PointStateType.Interrupted == state) && + mAnimationState == TOUCH_ANIMATION_STATE.ON_ANIMATION) + { + mAnimationState = TOUCH_ANIMATION_STATE.ON_FINISH_ANIMATION; + + // To launch finish animation, we get latest velocty from frame callback + float velocity = mFrameCallback.GetVelocity(); + + /* TUNING */ + // This is just for turning of finish animation. + // change the values if you want. + velocity = Math.Max(velocity, -3.5f); + velocity = Math.Min(velocity, 3.5f); + if (Math.Abs(velocity) < 0.0001f) + { + // If velocity is zero. just start animationOfftimer. + mAnimationOffTimer.Start(); + } + else + { + // If velocity is not zero, make decelerating animation. + Decelerating(velocity); + } + } + // set currently visible icons for optimization + SetVisibleLimit(); + // make frame callback dirty. + mFrameCallback.Dirty(); + return true; + } + + private void SetVisibleLimit() + { + int leftViewIndex = mTouchedViewIndex; + for (; leftViewIndex >= 0; --leftViewIndex) + { + float newPosition = mLayoutView.Children[leftViewIndex].Position.X + mControlView.Position.X; + if (newPosition + (float)mLayoutView.Children[leftViewIndex].Size.Width < 0.0f) + { + break; + } + } + leftViewIndex = Math.Max(leftViewIndex, 0); + int rightViewIndex = mTouchedViewIndex; + for (; rightViewIndex < mLayoutView.ChildCount; ++rightViewIndex) + { + float newPosition = mLayoutView.Children[rightViewIndex].Position.X + mControlView.Position.X; + if (newPosition > mWindow.Size.Width) + { + break; + } + } + rightViewIndex = Math.Min(rightViewIndex, (int)mLayoutView.ChildCount - 1); + + mFrameCallback.SetLeftIndex(leftViewIndex); + mFrameCallback.SetRightIndex(rightViewIndex); + } + + // set decelerating properties + // in this example, we used decelerate animation in "https://medium.com/@esskeetit/scrolling-mechanics-of-uiscrollview-142adee1142c" + // But, if this method is problematic or violate some patent of other company, change this other way. + // We didn't checked anything. + // Only thing we need to remember when we change this animation is to add "EasingAnimationFinishedCallback" for the new animation. + private void Decelerating(float velocity) + { + mAbsoluteVelocity = Math.Abs(velocity); + mFinishAnimationDelta = (mAbsoluteVelocity * mDecelerationRate) / (1 - mDecelerationRate); + float destination = (velocity > 0) ? mControlView.Position.X + mFinishAnimationDelta : mControlView.Position.X - mFinishAnimationDelta; + + if (destination < mLeftDirectionLimit || destination > mRightDirectionLimit) + { + mFinishAnimationDelta = velocity > 0 ? (mRightDirectionLimit - mControlView.Position.X) : (mControlView.Position.X - mLeftDirectionLimit); + destination = velocity > 0 ? mRightDirectionLimit : mLeftDirectionLimit; + if (mFinishAnimationDelta == 0) + { + mFinishAnimationDuration = 0.0f; + } + else + { + mFinishAnimationDuration = (float)Math.Log((mFinishAnimationDelta * mLogDeceleration / mAbsoluteVelocity + 1), mDecelerationRate); + } + } + else + { + if (mFinishAnimationDelta == 0) + { + mFinishAnimationDuration = 0.0f; + } + else + { + mFinishAnimationDuration = (float)Math.Log(-mEasingThreshold * mLogDeceleration / mAbsoluteVelocity) / mLogDeceleration; + } + } + + mFinishAnimation.Clear(); + customScrollAlphaFunction = new UserAlphaFunctionDelegate(CustomScrollAlphaFunction); + mFinishAnimation.DefaultAlphaFunction = new AlphaFunction(customScrollAlphaFunction); + GC.KeepAlive(customScrollAlphaFunction); + mFinishAnimation.Duration = (int)mFinishAnimationDuration; + mFinishAnimation.AnimateTo(mControlView, "PositionX", destination); + mFinishAnimation.Play(); + } + + private float CustomScrollAlphaFunction(float progress) + { + if (mFinishAnimationDelta == 0) + { + return 1.0f; + } + else + { + float realDuration = progress * mFinishAnimationDuration; + float realDistance = mAbsoluteVelocity * ((float)Math.Pow(mDecelerationRate, realDuration) - 1) / mLogDeceleration; + float result = Math.Min(realDistance / Math.Abs(mFinishAnimationDelta), 1.0f); + + return result; + } + } + + private void EasingAnimationFinishedCallback(object sender, EventArgs e) + { + if (mAnimationState != TOUCH_ANIMATION_STATE.ON_FINISH_ANIMATION) + { + return; + } + + // start Animation Off Timer + mFinishAnimation.Clear(); + SetVisibleLimit(); + mAnimationOffTimer.Start(); + } + + // Check each icons in screen is not moving. + // If it is, finish all animation and make animationstate End_animation(NO_ANIMATION) + private bool OffAnimatable(object target, Timer.TickEventArgs args) + { + if (mFrameCallback.IsResetTouchedViewPossible()) + { + mWindow.RenderingBehavior = RenderingBehaviorType.IfRequired; + mWindow.RemoveFrameCallback(mFrameCallback); + mAnimationOffTimer.Stop(); + mAnimationState = TOUCH_ANIMATION_STATE.END_ANIMATION; + return false; + } + SetVisibleLimit(); + return true; + } + } +} \ No newline at end of file diff --git a/test/Tizen.NUI.Samples/Tizen.NUI.Samples/res/images/FrameCallbackTest/launcher_bg_01_nor.png b/test/Tizen.NUI.Samples/Tizen.NUI.Samples/res/images/FrameCallbackTest/launcher_bg_01_nor.png new file mode 100644 index 0000000000000000000000000000000000000000..d68ad45db6977dca568d839709849805296089cc GIT binary patch literal 1597 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 W=4PhPwg`#mrx+KLD6f_3R{afZI@oLg literal 0 HcmV?d00001 diff --git a/test/Tizen.NUI.Samples/Tizen.NUI.Samples/res/images/FrameCallbackTest/launcher_bg_03_nor.png b/test/Tizen.NUI.Samples/Tizen.NUI.Samples/res/images/FrameCallbackTest/launcher_bg_03_nor.png new file mode 100644 index 0000000000000000000000000000000000000000..5075c8024997427278886b5e4373ffafac712ae6 GIT binary patch literal 1925 zcmbVNc~BEq7!MLCrqODx6k7*F5ah_Q8^~#*h6EuMFoXyMM`hW4U<%2`%|as1D1zcK zD4+q+@t}f=^%`j%t2P=uCK{Y+Jpi?>iqd+dqBUh&OVw^rZ2xdNo$k!;d*6HC@B4k{ z>>6!G$|%N13>u9#N|UPAQR`~|8#03WesL`^h*~C)$+=_}UP#&y0??EgUI17c6H)|p z0Kpb7x&Y)fT40$`pG)SZr^!&<#6$c#JiEz4p=mVvbh`yXivh_h07XW#g8lf!DK^W9 zDcCu}bST}T0t=0)%IpgEkX;$I_aF1w ztRWS$SiyefRBpPKrNRlo67ob`6iyVd#8MtCf~0~(4od*RVm>71!wFmnmO&y}f|T|8 zVN+}bRw&b{XTIj5Bn5jRNm^ulzRhOi*%Ej-QN)L(QYjx2@C5=crNOl>Hj{{*YqmxX zTTlZlN*FDq5jV5^7LfwHlvJ=OPhW*#vZSZKF>JQJP85|gz8$gfVIIUcnf!4LXMkS2l>ZT@emqxAB+i(25b#7TJ#0=Uz@qk4n`1r#1 zh8-&+CelT@jU}FCy_eFn4z%;g-+hmLk58W$Pm=^yAhckJ>7rHF=ZEZJUDvv>KIOT- zUSSX@?M33et?^l(w7&d+ zI5n?2WfEwpR2mM;N4vD_2#=t{b>@iI`5eK@!ml@gM_fnh{&t-_ITSSX9KLuO)q`zQ zmL0zd0i(%m&@#=r*zEepDKlCB9Uy#mi4Zyjkd4Dc2 z%nAa#?ku{_YvJ6A?IZTe`;=PSakDNs7#xfBhKAXHkKe~&DxHR&C4&c69u#LA_5_Rr z=VCi=Xv(InY!2_dI|IbT2iCsK*JdvW4;t)}kK5SXKc7A4o3oSK27Qw6)jJea3WfI$ z^Fr-s~&N&)7KK^RSJ>{qB$3?lAhmdXHei0nW1)ju;r? zSNIvb8JU&Gi+bjE-ffGIY)gsplIxWQqrJqX*M8uSH{Q0V~p5<7W%*pFmG>7^Y$vY$UWw2WJ75toEFg=)&5RZ zyY815W)pqjraZ2rdH?!UhHK2#6TYu#DsAl@q(W)9Bwtz;(N>i7^a?NM`^??mM|tp; f)$TzDSjP_trj75<%%S_FLw`n1a)$a~Qhw!Mo;v8M literal 0 HcmV?d00001 diff --git a/test/Tizen.NUI.Samples/Tizen.NUI.Samples/res/images/FrameCallbackTest/launcher_bg_04_nor.png b/test/Tizen.NUI.Samples/Tizen.NUI.Samples/res/images/FrameCallbackTest/launcher_bg_04_nor.png new file mode 100644 index 0000000000000000000000000000000000000000..44280c99ceeb32f24e1c6ace38bb6924a93da9bc GIT binary patch literal 2038 zcmbVNeNYo;8jl(fOs(2l3hfy~_%L8THUWX;61fv#-5*Zp=5}WH zec#>R@A>#W&okQy7HnI+>XlU#3T1Upwp>ZBM}l|Qa`JipW^xF*MB$lbcrjXqTOkag zNVTX2VdNN~YD9@Z+WNX{h?qiIu}4=@hL? z*(A(GyCQNQe9dDr79qG^!h9T5nF3_UPz+&g;ihn4ezJg(D&+E00HGk6%@6?mR34DZ z<0o+dz6eMWB?%c%E+**>(^iR;@~kJm$diOwgX1O$`UunXvQHUj4b)qk-ndBGk%gQl3@sh zqgV-w)-H7cScBrIxdt^cWU^q@(-^GnI-?e~niGO$dYrW!!E}2NZ5DhcKbkB(4 zf6M+$0LK{1)Jr+nrG=1*^$BR(@`J~PlpLHk`siHqk_qy-%}{mh#a}J#5Q*S zo$|IZU~R}Xp|$f??!{x7i5tUz-B>pT<@wtx=1&ZUeFT2~#lE|h`~NljXl^K?I&Wcr z(|gSIPQ!|PHvP77;Nx$kL(~lHNH|cGO9f8XQ{tNl%K1>|gRIxB zQTmG|>etl`D=W{iXux0c7O_>IjnLYMc4W^~I=21lg-5IN?tjUAwPXC~;gylcO9x?YJJq>^UOaFkqaZpe zbkZfg^s4(BS*qR{hn<8$)mr-P9;SOPaoGO1 zRl^g1_T}D7C_C@!@b)K^O;4A$T_|U5Uhgafrl*VAEboG&a{8?+tancO!u(0L+PUA= zG_rfVpY48s2=4RrZn*Z{8t%H04-@qVJdY#?9J7(gzKY%Yd6xbI!V4ei`2L(%GZ5=8 zyj!$4_n(qOo-cFM8)?0s+OHEfE5R$DOq9;mVUF1w5t^BsTpFS6&n8rU*~1{ z_-hM4-xXEd^ERz#wdFLz|qNX%j4@4`?d^KMa6>$;I@*15}%UL4t%`|)xaxMmPuXnD@p)bQ8Nt7}JM z3{3acubRhq#Jjh7A|11@yd(pirDPiqRJPkYYY$K(DbPPwhcK2`Ul0C?b21C$-5HgR Fe*<_zEi(WB literal 0 HcmV?d00001 diff --git a/test/Tizen.NUI.Samples/Tizen.NUI.Samples/res/images/FrameCallbackTest/launcher_bg_05_nor.png b/test/Tizen.NUI.Samples/Tizen.NUI.Samples/res/images/FrameCallbackTest/launcher_bg_05_nor.png new file mode 100644 index 0000000000000000000000000000000000000000..1a0386fb673c6ad5386599e6f9764c35374ef724 GIT binary patch literal 2028 zcmbVNeNa_@?!ErLUf%P zw2C@Sk(u0SLN3-bkJf%4IK`i`~O|Hf;GmlQU+wC-a1`V}T(HUGWmku%MOePiA zpjzupnASlxS(6t%h=CQc7|fUfHIYIdwUww1%O>MU@26li%jFLpo2(BCg_n%((3|p#(3@iJWxmxN5dBqMjxR%)_hS`z{mV;k_;4{S64)Rrf*04;`E zN>OzCVizc?Q4F%c9Os6z;xrcXocLRsYpI=bW|i z;BXYgts|_bxG$Lodjwsj1p%S}cyP%fAEC)FW^W2>I`l+rlLQ`D4lbF=+Pu771H$wx z5?}hPD}7K$Up3fsBP`)amPK{!`*7LIJV)u#fDiXu+Q>Tx-^YFRu_We&JG?#Uy=Rm1bE8IyM zg{s~c?$QQ-P?C>5*HrBORV(nvyKf!r-1k%2_|4;n(Y!l~@h^zqJYBq=+E`ZiLcIV! z-(r)g+nu6{{GpEy`-IKFC4fDS7yg;h9J}Y!&lv^&FZs2ah@c?gGqt=^kq3V-(`CpG zWe}Tf1Kp_$=g*7aaiRd;;&RdxcS1iNC~obSDO6sccP;ZT4c?*drxKdKZX4bL75F)u zFAVMe;qGN7wdYP}a9%2%A;K@h9Yjyf-PD>7e8HnRCGQ>c$&Td+CSiDd$KE(%pLcS{ zck7<53alw1S2&d0o>rdSv^UNY=#GvqL8s$<+lBXe(*$7qvV07yA48wIAQggYm=@-%1TED{Ea7zwi3Bn|uJr@5`E1vwAscQ?}pM z{jzc_FLmUK4r}12;G#aBhB($2sz&WAI1juz_SRMB#-8d+KRpc1ow##_f9Z1c!@#cILi7Pu{}$-~Ko*$EQ3F~IXAxSTQI-zP0+65EPf zi=sS_ixl(at+tg(z4pl9m4@Lm9NU~y^>s&jQtvO65nh-!IQq%=vuCI5LvMN^;P0?c zetYY;*aDaHb>G;)kC%?-1lIgrxT0fnYM%DwSl)-Pb|9!^Fs0XROlq@lSTd&uuW2v} z*tc{}4~~}}?(#kl{M(M;Ocuc`O}le#OBo>?NK!|_MT+TFV`os8Pgs#pNpKBVqbL^{ zAFP~?yF7tJ1Wkbr>)IlNjAttM2w;li^*gd~@JyIUap|MTK;W;&Vc>EeJxKBI!YPau nDT*eL>ZFBFpgH|FcOxOf;BffD)X|+Wq5rQ`QYd~`sB!%l;0+vh literal 0 HcmV?d00001 diff --git a/test/Tizen.NUI.Samples/Tizen.NUI.Samples/res/images/FrameCallbackTest/launcher_bg_06_nor.png b/test/Tizen.NUI.Samples/Tizen.NUI.Samples/res/images/FrameCallbackTest/launcher_bg_06_nor.png new file mode 100644 index 0000000000000000000000000000000000000000..d97160f382a44109ad6bb1ca5421440b8f175860 GIT binary patch literal 1209 zcmbVM&ui0A9M8Hr%5;a_rl&`WpkRKsX_~M&+GceHJ4aVok4;}**RUopCT~ktJ*X!I zkNyRE^B{4yq%|KDhlEtuV~&zSC%uX6>d9 zvCCTthL2sJvKeM&HTEsIiwJ0=9mg}+UvJ;Bz_AT>Td9dPzl^%hdOtv0{f!3f??TOH zSFeMWSf>hHL@W@yJulQ_gB|MCshk`OEEqz_uECC+YSuPE83za`e4c|+P6n#ROL~|9lJ3V9X1YpB-Bxe_X0@k(aB86G!#x*yq-q*0 zz2R-g*7I#CuR;rQirtpD4$R41p^(=&sLF*L>}1=ywl>i-jc-;|Gpi}Nk|ZjUv{oz? zl|m(}X(hE>DVmBh;a0tnSROg51g1P2X_dy_8M>|%n$F7`pWoK(F4 zu53G=jic~tQl?SVCJLN=WLE<0f?=L@XNnJ}i+{wo&ze7hIwd5{@>larj%Y_F;?XG3 z&CxI+k4{iPMJI47z`oi-4 znT(j4t+WQ|$Af!I%R_l?ekdnbtwjC@Mk!~4iK$a*`ybYtOME*v`sD7+JoEcw>dmL` R{dDp(sjh99FG{Tke*m(+YOeqQ literal 0 HcmV?d00001 diff --git a/test/Tizen.NUI.Samples/Tizen.NUI.Samples/res/images/FrameCallbackTest/launcher_bg_apps_nor.png b/test/Tizen.NUI.Samples/Tizen.NUI.Samples/res/images/FrameCallbackTest/launcher_bg_apps_nor.png new file mode 100644 index 0000000000000000000000000000000000000000..f33f6a740e8e5b093abaa5f8cfe9680207e17f8e GIT binary patch literal 1732 zcmbVNdrT8|952XR<*~I{bVc-by$Vxjdv`6bcCFa$N@LChe8$0Y}-Q zo3+&0Am|+Gri+6u5z%GHp6UcNh;&Y6zE~icit`asWGq1!WmjI?AI2=Z%l&@8@Avn8 ze7>*TrtGZrn8^8&JRUE`Y{GK5-5>h+;oN%Ya^f@G7Rwm&nOv%fsl;i5r?pd70yI1D zVj_pY?Nw!`2sMv4tAfnSXYw;MR5r>X!$UGM*5Tr`c|3I*>%who2?n$h#iUaM-8*~? z0!h0DT9cHCWV-Z332E}sM6M?*&*oWcQ`(`l<)E5XaRwX&gM+N2)ah2S8fe0qwPhi9LzZ7i=#A93B$NlFkD$#DXUb-D7qL%l}aUy$YHr$%1KDwRZa$HrB1hG z+5$$nZ8Yg(NXiL@EaFzGoY6oW(#a4UuFT9C!%p{9qPUd7Ebf9)83H>Tp|~cb-AoSg z4~!>DyYs4C1e`;-sdC!J)uTu5f8z92(Usn&gUtmtvHy+(9@QGp2#K8=0N7 zs}fTb1a7t3q}CKPRhlYKv`Li;ZXx7F$<`z}B2Td^rtLgQA2B8w6xw8iPN~(Rs6nes z)h25VDY_)B7D>erbXwQ!bThcqMojxAIp0&d*i&^?dYZr)iq4~`(&;Y9E}BcjGfC9hn5v#$*Z2EX_*uu1*+=<#6zDLk;ctGl;Hq;4jD4(>?O zlegtxjta@nyOli1uM2k2y-5VZ5|R| zfIdI-KGd-YC=lZbqjkQWVja|xF;|RQihzO-5VoX4ATC6(?!HGKtwsVZe*hBI>@CS# z4?j*b_UPByhZY8%qoD3!^{5xOmyh1$Z8-U=uy?#-C;$6>hWWU^4h3GchzcZ{+X&k~ zU)+GxRoL704iSW%u=O>ftxf80jIqEhNz)JSNOVUE2gmqE?^tci(af&ytt0Hl4t=LB zCO1zbPdELwElqg!VO-x_U;Tyqps(h`ldVy~8$w9eTs?IEv(yPq zp}mdI>Al~v3pn((KpY3WX7;Iz8x!44&hh^xrOv z_3>}TiSKnHt-i0jmx$Cy)D^g2@Ya@M5oC9H&*LS+`gwhE1Z!ej@UdlB_qBnS*Fl4K bAI`P#PJc2K9uBjL(0|2j$ifclEbspfvLb%* literal 0 HcmV?d00001 diff --git a/test/Tizen.NUI.Samples/Tizen.NUI.Samples/res/images/FrameCallbackTest/launcher_ic_apps_nor.png b/test/Tizen.NUI.Samples/Tizen.NUI.Samples/res/images/FrameCallbackTest/launcher_ic_apps_nor.png new file mode 100644 index 0000000000000000000000000000000000000000..b05bded9d0d2733b5a69b0db68173e0c7b2a365d GIT binary patch literal 1987 zcmbVNc~BEq7!Q{S9tBS*RM$um0?FngAzMO>Nf5+vE5WNK*-eOKvmsd|;DO=+g4ElJ zv|znJMWrC>Xces>Dk=^rQV>B=3bj`87!d`!;jsOKaXNi7?|tum`~ANAo81%^GJA~u zm-ZwQX-rU{ID(*J^By^ZIDN;m@M!I{7ev`07Y;)U_!MzBV^)}`}IP^-OL8bK)(nc$0rXs zC6k5$BFumQJ~R$h$zU@9E|13G(0NR@H^8JbxFDSiGFVhP1EO;v77rL)WWt&ORzVTs zfI(Zti%*WlaXkcriHV7{L>3J*s6hsg#{=n1kjbPH5>#W74wsv#I^*;q4PwNoG-&j= z2Gap%jdBH+fb+?Orvo9Nda3l2Vx4g?QAEl>lUxrnXmk)o&2jZh8}SI_A2)`THby1s z5ikNVVhIK%Q4iJhAuy4<&l@re65c?e1`SaZxmJuR6Hr8l2Z{M);tLJdz!00uLgWgC zlB(b`e5t-nwvx(Y5eLFlaTGpGI+F{thV%@Fmxx4SCXdIN#S;n{42e+4WeaEdu(@n; z0F%w;(TA`>IwLOEDUl)D8p8G<*5|WWNMu0dIA(~#FzrwmgvDYwW{k!3fJkJnx-Z}n zt*&Cj-OnCrPZU-MhvuYHf6ziQ)e zNP4>@*GlkL*F%1ys`tf1V>N%>qt4FGt@Z0~IoOFE9L3g-!eL0Zio*)G+HmDjO1EU( zy!P$RkME7%q_kPel8ucJg0VJRgq3a|UtgZTHMnm|x4@bK`s;neBX7x=*Y{a!GirM# zn@G!AALQA5w~lPv_n{?x|M#1tSx?g414fzbx@U4cEO<)=PS&C5$1NHKyEbJ_Z(~PF z`u*Gwt2RDaYh1Z1G$o@!RABw=68-EnCJcsuV+2EX@yIlv3I4t-yj-&_FPN~7wSr}#oi}pH`@d$ z8-K4knfKhaHJQ?AF*zmfBVIPD<`(C14VZ(TjK7eE?#@gpZ-22+=wC#QudkRy_n@r6 z9+dRb5?)3tPB0!;pGm#T43%ALf=_2Tsox`IsobkQP&a5fJ9|g_VbyKtt=9Wn5*)^r zFx%|v7GMgON2iaDJ2SO~5?kV|`=Vam_0Fg&JhbOVpM7j7tZ3T>OgsF*7FDGe)52{0 z&uN=&A9q!@H|Ms`y%#LpiL6l+?K~d@-v4E9+kqWUoOMZaPP8@OKsap`n)`9WCtXwV z@xopMUyN*X*|Q{{u_+mwY~|{o2faOEnSFD~JYe-9$SmUoun z;@}&1YtB~8Sf<*`E6iAIDafkEQx$k>TuaV!fy4{gWwdiI{GnYE)^t7on{2{)rCs<7_1Tc@RZbCpN=nj;IRG^$(}Z^+^6I#*wu z2v2D&2re6YpbW{@mYwaIoz+Y5!h+BLSeU8arfcoKG&q7 zXkvqFPeRGEpV8Hm59Xp4Riwz$fDs`+B8ro*)T`EB{8kuvlTtdPAhmTAEi1OYI?wfS zjOUpsB+q%Ka*=z*Pn(wIP~d3WX^dc1Y1JYQ*Yh^4<<>u=XWsMmsSBC3v$gD~?#Qab+4@dNb|sin!W V`OW&4i{{^IkR(KWV%E~szX5f64|V_m literal 0 HcmV?d00001 diff --git a/test/Tizen.NUI.Samples/Tizen.NUI.Samples/res/images/FrameCallbackTest/launcher_ic_culinary_nor.png b/test/Tizen.NUI.Samples/Tizen.NUI.Samples/res/images/FrameCallbackTest/launcher_ic_culinary_nor.png new file mode 100644 index 0000000000000000000000000000000000000000..d5f9ea09443c4b083e874aaded5f1ba199785adc GIT binary patch literal 2465 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 Rjf;B>d9l$3ZH*?q;6Ewp?=JuV literal 0 HcmV?d00001 diff --git a/test/Tizen.NUI.Samples/Tizen.NUI.Samples/res/images/FrameCallbackTest/launcher_ic_family_nor.png b/test/Tizen.NUI.Samples/Tizen.NUI.Samples/res/images/FrameCallbackTest/launcher_ic_family_nor.png new file mode 100644 index 0000000000000000000000000000000000000000..2686f3a207837847af8cef04c49cd1e152549ffa GIT binary patch literal 2376 zcmaJ@c~lcu7msWrOQj+hSu}*rh3p#{4MG+nVh}N9Qz;=cF+sAB3=q(xKqE>37gVGX zDSF%rqP8|gmQO?w#e%4)2rdX%ZGoy3X_T+ZH&OBHAD+%R^X`3b?(gpRoym`k2z9h` zvqPa!j{Gog6hgV?*VYDE1D*H&h>*E3FBV>-l)xDxHG~QQl}QkWFBffqq975Nnc4;| zMWHNpGGQznD_9ALm2$kuEQ8m|RR|h|TDnZD5{WlLFeVAwAXBigFX|hy7#YaI#?S;r zfrV zK?xAWUH;J)vSVSTFsuRygp7;~dQby2v#b^SLZ6@&ymd zK!8paNgy$aiKCDLCAcIJm4Oq9Kqih6C=rqAWJ;hIWKQY%9G=9ab2tn(olR%(NF-he zlg*1CQLSZs_Ox_fhuh76Eg&3N$EkkU7#M1s13vkqs2v(|vN@dDa7eq>xuu>yc zsxTamx$1$K1u-%OsLaqTG?(c^)Lcj{ONYSaYNZ_WKF@&cGd?iHbO|V?l5s?$M2r(N zs6<>6k&G-*5{XQvLQIK>hW&^K|B=5BeTtkQaj2%;0jNYsl*AO%a70K<$I--85GSG| z97Lmm42VId62(+30dbLFZk>O$($o>spJw*cU?7`MqXj9Dc~T>TBOJeb6NR#l=W|1Z z+TIbv+A!}Jbhg0HbT+*5^xEON3hK6a@GEY(y`E9>sN!d1BIo;G@OOE-p9zZbriTLs zn35HiC6Swpt>-7tuRB&

58M5nBCM0o?|ETQ;Pk>lgrB5^1M==mrx>ZjWv6< zx969S9hwYUT~=21WOZi13VpW4;ot>McDgCD=h(^XfBJ4?r=BiwJ@=r(jhz#T8TjvR zpGafWB|(34EZXZOVI*_oj%Ytat7l;V)r!^lcBw4;ZUd&J>7-Rcj1G$1bu{^~Fd=WI zv262IvA3ir)S-FZfmvZxw?oqwbhgb3OM33J|JYU1wWGx<8+u3XOuf%*OIqB);yFAl z@x^@dmEH2p9VPeD0gk(P+9#(b zmqM#>gX-EX)5j-)L$yevMo+GZjeYG1R(@gIRO9u-IVZ;%xlCNh@d=kU;brGNvnZTO zaAaRo+M|IBHn&Xnj~V*Ru~%SuNMXy$)RGL3hVtWkhD&px^KcyUKG~?SxaBUvMHPpc~_N@F{)gcE6sP{VjU3-eEHRn$2i_OQYRv+z30>`#o7M|3j`a^se#vn-X`Ew4^x$ePLnu?c1?1@UUuOf}Dt|41BsL?(Stz zU5cRfg=wop{+(+0Dd4fw)FBxosCpe@1^X=R+@pOr8FThO9~v6kfEpI)NDPK4L~j=t z6udd8FTT$3V`JkavB-Jnv7z0k7EWtrSqvs_*>a((y1GM$6AcBlrK)(6E^kfL7brf1f?u zvM?jDZ=UYvy?f^gt`1E(!KDpWcb@ICxTMvWqA&fHER{OBQ;MXdixlai3!BQ;cU1cJ`JR3DJkR;x&ii}c-+TK%XMJdhzzY2} z8i7Dq2?M#|@XVcfQReVSn^9N~PfmKCSieXu*C$J~5F$XPmO>bzQW6J+LlRla%2tSp zKp-;}5n{bq6wCnCN*~FDjE_O7fzb#AbAdr40TUoSMhe9#R4nZ9@l#lgLdL=_@e=_e z4F`%>1g2`CMX4bXU}^$Lmthyo$1n{HSb-AKOE3myqDsdwu&^KXGT`;ZF#(JDD56hb zVLy=)i$XCRwHCto`B3m6kxar+={`gXKqrysVn_gyN&u(?qAwmGG5`w0myY@TU}0-o znVb>M<$tyX?^xJ)y=#kxr)*01|;j!ow1HU5ZLCG2m6Y*^?T$ zkPg%;GDD4S{IR`fe7J{PMxF$;e5zvPlDmt{kx$FL6{9=p;iGWMUu!>gGowAr5AEpSon*N zOd(@X$PzgO66ttfB2A8$O2|~aL?WZ(sWiESL?QXoKpA~f&p+WwG%AG*u!(F6l}9A< z0@zeCHGoeJ2ne7Ckhyf?Bvz=>=_M)@T|zfW}vpTK@-Ch0K903?ypK|eeIffT$SNS5Ix z6nF*s`N^mdl|%+WGL`^SButdf-%4rn2(HhG<(I~QH(y!{Qo;SCg&Rkc-&Kr2n8yjZ z0TG6qPok8;QQtdO-^t49&^xYw_jBF$?Wb+s2J_7xly3}^HOKd@jn6K1%NvVpo>h_< z+uR*E{!2q(`uZ0?VU1p#jrK@OONHa|Ua|3cg?adfwDzEc1@SqmP1!ijqY|MLC@qkLq_ZosOECiEJ{tm!|QjVO*@?t!#lEbih?cid^bY z_M|)KJJeLJY^$)zxUT{i>b%Rm;%)1|VY|o!j8dXEyvXn=BL|3 zfyIj#<2V)Vb+N$MtMT!1`kLI!f!jw8t(yCNCh|fij!Y&qpS&;}JX3PYcXUbdAEV16 zBX4AMo7WTtt*lvrGr5v4Lfhv&@XpWPjxr5wVIA*%Uw`(V!MX8r-^sSNw&B#&)R3!x zUPzj1VeLd$1nljA&Yr)MzOuUYyn1AGbVs#wc}WS)(!Uq$-+SanB7wLoe!3|po>i~m z)Ya7q*37>%!1Y^;yw)HE9KVr9%svpr-}AyIK6yvY=ANhT5B>JrQo&7$^P9D1vM8Qh zF5j6|NG&X!6(be{+<7TSFAoh3Ik&Guzw^ISeo_9aG-6*U32|ew&B4dwjn+FE8&t3SskC

w0 zn>nMgbzve=o8%CG)}op0KQirckvMlxOiy1P&R7%B+&c~TDwx@SA#Z&V3UBN5>S1?x zcVR0g`e%eiEvmr1z@xy^$3FN-jAITe zCMM=>ul;uo9*sQG2|KHiqM{-}D|3Z6!nP|3u_s~9%8+K?+rljIk<4SKs>-lt{!Nz6 zGdR9ZLc{uX=z04>OBw`x{)P)~CHt0oG8#+HxNb;7Al__W^V;9a!|l%|ukM`k>s?(G zL;7Iaob26I=KakAi)Wr*V{x&urz0aGItO3B+tI%^6m5YuX4lWG`Oc@fIRD))eAh{JaamBmF?AT(|31{olwXp$diCl}7u(ucRwglqvsY|+cDYSWY%|&q=kE5E zSH8DqE~=atz^x0W{d%UPhjm%-L+OJD50)ryA&c%ioR_xFe&~S6_qtIG}pf<^1Xt4ezE*RMBzJJQnto{4a&9L$JXz9b>ZND|cc>80k&OIJoCQ$h2GzFR368K$GA+KKQbcKW78dNnk zbRFK_@+CX%#KViv4a{GS3rAX?S8cI1o07riVXVdBwb$lgucNtd9m^ipJ1*v3J>%Lq zoK;hO$8FnR-vqC)pv5>?nP&v;?PxunvO1vl+Ro%-(Nr(P;IV?_a|MR2-bGul9Abto zUtW%6Ua%8W}WC6i>4R0>g($3Uw+l_tA%c?%FAta-BO&Z ze^L2q$NLzkr?j2Dsvn`fYZup!&K1sD#hK;X_|p39P@s_$zox)s%C@PV*E%~pGw1VB z2Xc!Jzp$~qzxM{oV83dhrKRORs>H-KW>@umyJdD^Y`JjRsA}$!rzr$1*rKT{!QWSr~vta|d~$wDQi z$1Zvk+~3=9I9w4xF=nkRLEcKIo5GjZ?ez5Y>oqksIR6+I&0m{6w_e>r?0K{|?C12M zIcsd4M&2C7+6%jORn;6Vo)(2Oso1rzuk()e4f5L=q6`zpD^n){;3#D;K_HTYrdqR0PT=9x%r+sjP|BqBNRYPOfRNIUVPC**~253*y^ F{|i4{z*v3IZ`68J;} zSMy0vosvr8!AMMxf=nulg3v=5Ae&32vuIpKXfVj2(b*7<4bej=G&+yQ;)QU*XCH~M zrk5*t3BuLSY!N3uNr~e+9t34)XH&C7sF*$-qI0=ih{k{z3<@DZG301**htYD0;V(w zQ3Ik^>2MXM1sxh;8MX=MlL$|rhM>_&B+nIV4bKuqqzp2`I*3lCK^l!Ct|!t4JOTa3 zjcKI~NjW+cNa08(y4VMHB_j6k^CG4XVY(LOzMOp~_Wq zUMM>Rg=I2?B4g7z6b>U4p>RWp1!X8$GA4t@V9P_M^h}3m2tpYGCNm_0D~O=eMS=*H zKqM5gBO+KL4u`|$PGQAb0}g8ubjr4hu>B0ncp;V-sYhWP(5O9sqC&6bl7O#;dwNv($3U#eTc` z#@?;!ONQ$GV^!&S=l}e@YA|yUy)m}g{&?;i=Wk#Qlcxpb_uP&Y)Pv+5(~!p>UEuOt z2gfd4UNVFO3w-MAG0qd9cMM$CQv~hqKNSWe8^eq*`3ZuCj&_vK@V4N)<&W}Ss|O?|YP7#}=JpYLi0)PMqYm%= z?hs* zbE;vieXYXvP(}0IyqZO8avDo@iK({RFVA${;MIPY1JO4QjM1De34`y31PbyfyNb($rl5Q;Y9kYrb0^FPfcl`>&7D zv*oW1JDr@_d72b<^aJ%WzfZ`MRt2*0vWuywWRYSpkj-|>l&jY(MG7AKC(b?9nURJx zlaGt(ddk(I>wW&n+uB@bj@31F?ZOl3???H(IYPcb&EBbaC9HASIG>=jiLv zDZzW2NsCjuMn*@o%j3bgn9dIi>&$d<{h>c?8++#~$OqfoVksy-4UqFy1Nk{T8y_)p(;W0!K^p^gViu77}x`?stiUT;2L1Gx-vo)?V*BFMQQxj^KW<) zH4S5gs=A5+45|i$8S5ip2ty;Nx}ma(iV+-Up!^$a9uP!C2B5LOZF|#g|BY4tuUJh( z0v1Wc5gc$hzu#40>xCoYg1m5ekfGsW))62%C+`3ZE+k0)FipR_Ho_9TgRvMB0?r@w zSDZDy|AoW<&HrC`%>Orj5IQNyVX^$L;`x00D1=z=&dqnJ|PMK za736J={t}{moJ9m`OgbSS7c~pcFg7GUEztJvj(vd*sdf!W<`ZQxz<`<*ERGg`od$$ zE}yexG~|M-ja~>ig;BfjL-q{c(`+MK!ktruE24}iLzKUtZYl4 zU}_&WHU95d+4z}kK`Rh4P9jLQRVL~|t84shdZ$E~k6&u*=0o1WwE z>Ks(4b~$-a#DIP=W>a+L-cW^Hdp4zTyR}zdWqLrnM_%)*^0cJ!tBi3+1clv zok?49UzV3ON$v;zz3GF)MM9q?D#yg!c@P;$kmYq<<70`X=V37Uj*j7;!q*Y4>snu5 zGEKwqByC4_06c2pohxo-^uyrb=iplJ{G1L9M{|rXo8Bp=!uE~&;iWB-wrHDo^{5E0 zK5%7qc>dG8tAKl0+FPq7_2tPr?&GZAsLxIV1Uqg|3&#MhbMvydc1{$!z4Yn_#>0fu z8p0!1?lQ5QSCCfBOba_A7$14ddSUa+aKI!*MHUj$^gyV7e#8?lG2WmnV*);U6$n2% zw0Mk#MBe;i3*coWIVgPC-8cb1*b;h4YN9Uh<9iz>BAp)ELQjjJP|mN$<_Q|ENg%v7 ztN5B6V!AD+l^4pzQR@=5OgmxPsVI}!vzPidWFl$|RlT?s_NBaeE&Sc!^XE5PrK=XY z)dV??r`#{EsVS~6o^J}Rz9?2{J_SHD2UJCd{kdk7Goj7kzUZ^$-ggyX9z=flMHV=L3JTjo*DyR`$3gs2=^+r+TOmfeh5_ zmZ|FThC6L05cXX~u)E$K^}p*_6R_>X{CtV#ifsXj)l9xxaz zWHLOXHDC*&_^RD9l~!?zYquhb!XGaPjq$+BkT=^?q$Q zD7|mdC?o!Yg}S-LBqjKLZx2NF#9)kw%!$mBrKg^Os6fMmqn~aDN&=>eva+)Jp3Wl> z2a#34mF{)ED&QBf(^2JoA4KDf7T>!YvSv5p8desUF+%XTCSF}98#Yiom@JYN9TXHa z);csXQTX+1dHK7qKVunEI_B^QJA?BHcDK_T!A3yGYGnH7G*#DZBSr*fWAqce}%eK4kI9nNK zC9E)z%eyFSDZ|%&qA2?3_+(*1eyYc38qN7~s%9nXp!}#BhwP6H6=lWrwYW$W`qTc- z#HE8x2~g>=%$rm)BY{=~)R)scn;;jLL{=2g`^;#Vw3X+e>Y{lZtOj%6UinxTu%g+X z7Z$JoEc?BS?Dlu6LmD=MZ#jzG=zA++X>a(xNPVBp z*@B$K4`f0XuE}J|E6OfRUzI2f+5a&(=+I!douN`@6YI!Y;CZF_TZT|sGX>qYUA48< z(UEBT!IIQ2n_^+1uDj!6ZM|LjWHJ6qyu45MhUKO~Rdw|i_02vdpElhUS6ymTP=kE` zcG}EnT^dA{%vmDe@GL%JX#0WE`7WIcUpU>$5dmq~8k)IK)nuI@M_`?oy}=g)^w|uR zISYl?tvo&^i(r#754S#>{fy)oI453q^i=F%VPh!sY+wzCt-q5KIThP1W5ly-Z&zlL zzf?KaTcj(SVr#LE+CjTCQkkC0sBo2~o5y5HrXD?^6!HECrvn4hQR=v-j?U{@_Qa%e ziQvXc5dL0z%{D7T^U8Sbu>m<}86JgLrX1u{*{s@!yO$dUjxZ@YJ~~geKw1FGnnRaq zl*(f}^#>>Mci;%uKlr?hnRR}ADU-FioyusF<*s)@TILifa-ve~Y|LJNWBm8+WzO9% zlM)e?fz4s0Q|$|8gB)K&DDyKpC)_B`r%ROX!vn?zU5^aW`T%=;bLP30mMXyoPai!Z zxZf!%^}6#W|Iy;pOEvXBGolT2O87=x6mH!g?Vi+oT%lXi-_nz(MJ_g>eC*%J*Oxko z_@F?WHQO7WKOUAB7#L{F0e}l~SQ)zNy|FNL-h5nnM!Rn^dSx^9MQ}rA0al$ArkVT7m?-WulKGhf*!TC)_eRmCs6XZPi;CiE|bsHpVtBYJy zU#$MwbRI$efM~#uJTo2AW*+max)?uZ+>FqF(tB%0PF_CLyDR7BKr6TQraSW7U30(P z-Gx!HU|Njn@RQJ=^JHR}E8>*18FHXEwi~PxlVRMYQbX@M+K80a8 zW`U}2XE$K8TKoN5weQ{34VwzN3g-TiuDWhkIi@q9dl-VHe3J5wKVGI4z7hqw zG0v_$-4=_CvHS8R&h*Qs0BcvVKt8L#|nS<(g(T7KZEgV>Pm&`09NZ-uX&M`ts1 z%{sSwj7DbVGK5|Wo#@d@8}IN8T#9O{>yJAzH^L3P;9fC)*Y=&J#zY1y0^#`4%uE8goDBb#??! zx<(b9VVuiE5qE3he_B#e%UK$pmi@!CK_)%GV^`L4y-9+RX~B5-Q+LnAp3}MSC+EH< zTxznS^tlB}LDQS`W;TF^-a&X5uKSkysd0UTYd59bxvsIL;N^C{ok4!YOT0_dP+$E# z-E9S|rw$r1i^zF$$6}1n86?Jv@~LooPPAbT5*<0PmwG#TBF+oFbL&wGODoQn0!Ved zahYWMIbLw@@hzGbH6eBi*2Cj`y*HV}-N=tb%ZKtgo+7Y|t!X*RG{aD8Q-WUYvXtu} z68Cy7se&_{S;Lv~nnmk7&z$}+U_GCA8U}^Xgd!{>*ps`82Leizo%$(4v1!w;`-L`+ zJmGcALkE4|R7~Cj`K^qWJeseH{F(2o3%pLEY45~&ff&6~#fS_$jQWJqobws;ZY|hM^%C>8!PVR@aysG6HL6&r}s4fMmy#LxHb^4uTi0D<-qL|Ln zrlU$xIT7LPdG93gBCL*gEcEqLn0eEVQDq(&{^1~{Ei2k=^CZ9hIYLHEy1V6@ik!dr zkOwm1j3!Js4BGf0@nt7k##+iuFG&vNeR5lg!J>EK4Y||0^)Wwo2K4V2HPz@ z$n~XoXfpe@ADg=5p5E2n+8-~JxLB7g%7bpa+dcW5^ODNtBehUUxTYjhbjXNQnS4K81V@PbW<(0;P$xxEcjyI#mXmgsQZb z+%sr2jW#w9OHLtEzruK~ zwlUdaK%pemh_56xR6o*R9R*Xh`*%k!MJgJ>LIR_jqRNrrnw2_KPs$`hkov;XVp>52 zpNp#0Y7JA(=R`51;0O&9;Zh35ZgHuR%wBW0dcwSomMD0x^NANSsK<@tn~qP-fyJZp_3DfLQG6 zdK55gDW=!rCS$0pO;56xpahnOYNZ6O10L5|fITOM|Cav~y!QXr52AvCT*LCW;TgT6 zCepQiMg{8dj7+GWVh}-5CEpA1rx-XQlZcYdmz?FYgvF{!ZT$;s=2c;+Z-jSJTwpy;Gi(U>ceuJ*t9WSvKfVKH!<#bW+?k%&d8{-S5Hq@3W`*6g&|BnI3 z@a=ptUf*x=dQ|^G{~XhUtNj)IKNzpx9lC#iS=LydWQJ0d?BgdHx9FduG_lTUcAmO% z*V0??d)+bHj@@^sdD+(?Y1?WJjE{a{XxE&skY4M&mf0J94|-23x?^#Bhq2KYE>@o| z+c_pEXT;Iu#kL;PVgBOXhvu_(7B&PwSk|oeI0$qVOkceTT_*h9W)=n%(!$4BI$8t`x3qZy8}mjZZD=x;3em zky!gh-MWc4!33`;y7aE%ikridVeFb|dbn`X=6e&A9!H|SPA%}i37*cXUBCInn2s`i z@$1orSurUsL*aXUPG(=YElA&St7plU8|?XRfj_7DoOc)X8ZF2PYZ(2P=IEY`%a9>x zIsMHGBf7ex_8;8Wpl*8|_niDoBRQY$Sr}FB>CqULz%IMwUUm4_5?aIIEmMDr_L2dIbBE95P6<|T zb_kDVzsPAWxXu~0=6iSkQGRlHj=g>D{Q5_&I_GfrHgvEt?6mUBm)@G%%J5n%U%r2( zdEa1HNZwbfAV#z_cypN}UUWT98rVEkRCtwf<+m3UW$&L`K^#tPj|mue@s;5_g>9vs z+;4q4j6*)YTKLV*?!-02^)HzYKWwX+J9O^+*7fr3C$f(Y6aH)L%fNwbbWHWTH;I-`%M=`K@`^yG z&u3#pmABX3t{;bPN;PeKz0xDr2Gwf?*4BUA0%Sn;Fuj&s)% z!mk~gjhu}QI?~8`yZic{3o$cOhZ;MSGq2)yc>SELacAH2ExR~aYWPlH>F{H%^^^8p zsW>+=vE|U^Q($LeZ7HWEqBx+%e!pVVJm>-5W(Q*-wJu$WAy{;dwEM6hm IAD33}C;5*S=Kufz literal 0 HcmV?d00001 diff --git a/test/Tizen.NUI.Samples/Tizen.NUI.Samples/res/images/FrameCallbackTest/launcher_ic_timer_nor.png b/test/Tizen.NUI.Samples/Tizen.NUI.Samples/res/images/FrameCallbackTest/launcher_ic_timer_nor.png new file mode 100644 index 0000000000000000000000000000000000000000..971dc98b4567abad5753680cfa5d014946eb8e87 GIT binary patch literal 1880 zcmbVN2~ZPP7!CymK`P#cOmzts56H2bgd7kd2bc(<7^8rqvdL~FLb7qQLZE6nL}ft5 zidr00szAja2#S>v4;&3DC>}_?rrzQKUJLXB?-~o!R%^|MvU-`=8B^jhX80 z>FY_MP`s52xtiSNj@M%#xeA7_uO&As5fM+!!1P2qjH46@f@x7eX@nP`Y7|B?7M(;x zDHPWAiYIcDl0;kF`-C`qZB9wA5o&3T?42X!!=b*4w zt7B;SpnxHOxH^WALoO(!57zP^HpE9bPCXyvgK`O5!jZ_OLWvXvBP3FOFi#*5as)iN z6cTcIPOj2qAz+gZb=o$Nw)?oUPjW>v9EAxC*I-zxvkPLAF#@wBV`e}mb5vabOpG&_ z5G>s?$x)^cQOi->kcJ|WIA#QT^DHua#E1VD{|7$ufAhy8onkqf>S=35pslu~LiK>j^1PisBezR6t30RsIR)+LeD;)MJ@5Wp z<`36_Tv;ljZ~;fQWnWGT_|DB{ud6PjH4JDC_qxy6=Mz?_2`ob%HonYyvead>UQ;Ed;k-Mr^RYSsr=KPWG9Ur~e?K!_~2@!bsBwI(TIKewJ6@J6=s=N?7 z-!nMx)#XR44>l|392`n(O{>nL*;J`-o1)iUH*)XnqgGHeFD-N zYk}>+vC;rOEh@9VjJUBai$8B)&qI6nw0%R>ktN;c#D(u3jRmCAftAg5Nf9m~8Y;Is zr=a-WapkInNM2%Q>#eQj#kmKry$E5w+2*o#zo+-x<;-2upYq;EZKzP}f6=wyXLEmh j|Et$Eiq6}cD6W)6*V^3HZSdwe{&mWT82K;Kq@2G10&d>R literal 0 HcmV?d00001 diff --git a/test/Tizen.NUI.Samples/Tizen.NUI.Samples/res/images/FrameCallbackTest/launcher_ic_viewinside_nor.png b/test/Tizen.NUI.Samples/Tizen.NUI.Samples/res/images/FrameCallbackTest/launcher_ic_viewinside_nor.png new file mode 100644 index 0000000000000000000000000000000000000000..7ccebf9b4fa5aa2b19a1ebfc62f4e64e3a5590e9 GIT binary patch literal 1627 zcmeAS@N?(olHy`uVBq!ia0vp^E+EXo1|%(nCvO5$k|nMYCBgY=CFO}lsSJ)O`AMk? zp1FzXsX?iUDV2pMQ*9U+n9DLlB1$5BeXNr6bM+EIYV;~{3xK*A7;Nk-3KEmEQ%e+* zQqwc@Y?a>c-mj#PnPRIHZt82`Ti~3Uk?B!Ylp0*+7m{3+ootz+WN)WnQ(*-(AUCxn zQK2F?C$HG5!d3}vt`(3C64qBz04piUwpD^SD#ABF!8yMuRl!uxOgGuk#7M#1QqR!L zz|zP>N5ROz&|KfZT;I@G*TB%qz|6|nQUMB-fVLH-q*(>IxIyg#@@$ndN=gc>^!3Zj z%k|2Q_413-^$jg8E%gnI^o@*kfhu&1EAvVcD|GXUm0>2hq!uR^WfqiV=I1GZOiWD5 zFD#PU%0_}#n6BP2AO_EVu8M)o`HUDF34YC)x{-2sR(CaRb3oXS&*t9 zlv z=|qX+_g8y1Pr4?*LR44xmD0AO7ejUO#5DQ*f~-qkT-)gU^2rK|72O|ey!so~GF$cqU*p~wdYv=EZoQQOSCzwwW2H^;53Fx|OP+qw=$FpPANM~T z5dI+7QhPO3r7Cr0{l$#FT>Gva@(JeM6F39-cO6)Ezl9~Wl7sKvMcERW=Qq9uwOlEf z@^FK8q;^`)&h+O;ATZwI^#dXoKtr-rpK`M#yVY7@nLhvtoS+}93n`gpU?OKkRhabx}} zSC1Pz-W%?A_F%cwP-_rL-y(P6iY1fycTfLgb}HwD%4<=HX&5nw($0_$p4R173~j7Nw6?GEi_a)ep2k$w+AO)dzP}g+_`h=dEtJMjdO!@t~(pK z&oZ0(doQ2+uEt4AB+cC>=A4Y&pIDH&TQ0~)QI+@n-k?y;|96v*_Bd&@V4x+B9?xfB ZW{|yB{Nb= literal 0 HcmV?d00001 -- 2.7.4