From a6bac419bd77059181edcf4af35cbc1b3e30296c Mon Sep 17 00:00:00 2001 From: Adeel Kazmi Date: Tue, 3 Nov 2020 15:51:59 +0000 Subject: [PATCH] Reduced complexity of dali-table-view Change-Id: I5ecc880f2a0167ca1219700bad55107a675dc68d --- build/tizen/demo/CMakeLists.txt | 1 + build/tizen/examples-reel/CMakeLists.txt | 1 + build/tizen/tests-reel/CMakeLists.txt | 1 + shared/bubble-animator.cpp | 205 +++++++++++++++ shared/bubble-animator.h | 83 ++++++ shared/dali-table-view.cpp | 433 +++++++------------------------ shared/dali-table-view.h | 164 ++---------- shared/example.h | 55 ++++ 8 files changed, 465 insertions(+), 478 deletions(-) create mode 100644 shared/bubble-animator.cpp create mode 100644 shared/bubble-animator.h create mode 100644 shared/example.h diff --git a/build/tizen/demo/CMakeLists.txt b/build/tizen/demo/CMakeLists.txt index af1ed2a..855b82c 100644 --- a/build/tizen/demo/CMakeLists.txt +++ b/build/tizen/demo/CMakeLists.txt @@ -6,6 +6,7 @@ SET(DEMO_SRCS ${DEMO_SRCS} "${ROOT_SRC_DIR}/shared/resources-location.cpp" "${ROOT_SRC_DIR}/shared/dali-table-view.cpp" + "${ROOT_SRC_DIR}/shared/bubble-animator.cpp" ) IF(WIN32) diff --git a/build/tizen/examples-reel/CMakeLists.txt b/build/tizen/examples-reel/CMakeLists.txt index 16f2a0e..8b392e7 100644 --- a/build/tizen/examples-reel/CMakeLists.txt +++ b/build/tizen/examples-reel/CMakeLists.txt @@ -6,6 +6,7 @@ SET(EXAMPLES_REEL_SRCS ${EXAMPLES_REEL_SRCS} "${ROOT_SRC_DIR}/shared/resources-location.cpp" "${ROOT_SRC_DIR}/shared/dali-table-view.cpp" + "${ROOT_SRC_DIR}/shared/bubble-animator.cpp" ) IF(WIN32) diff --git a/build/tizen/tests-reel/CMakeLists.txt b/build/tizen/tests-reel/CMakeLists.txt index 728e6d4..a4d0af8 100644 --- a/build/tizen/tests-reel/CMakeLists.txt +++ b/build/tizen/tests-reel/CMakeLists.txt @@ -6,6 +6,7 @@ SET(TESTS_REEL_SRCS ${TESTS_REEL_SRCS} "${ROOT_SRC_DIR}/shared/resources-location.cpp" "${ROOT_SRC_DIR}/shared/dali-table-view.cpp" + "${ROOT_SRC_DIR}/shared/bubble-animator.cpp" ) IF(WIN32) diff --git a/shared/bubble-animator.cpp b/shared/bubble-animator.cpp new file mode 100644 index 0000000..5ce8e7c --- /dev/null +++ b/shared/bubble-animator.cpp @@ -0,0 +1,205 @@ +/* + * 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. + * + */ + +// CLASS HEADER +#include "bubble-animator.h" + +#include +#include +#include +#include +#include +#include +#include + +using namespace Dali; +using namespace Dali::Toolkit; + +namespace +{ +const char* const BUBBLE_COLOR_STYLE_NAME[] = +{ + "BubbleColor1", + "BubbleColor2", + "BubbleColor3", + "BubbleColor4" +}; +constexpr int NUMBER_OF_BUBBLE_COLORS(sizeof(BUBBLE_COLOR_STYLE_NAME) / sizeof(BUBBLE_COLOR_STYLE_NAME[0])); + +const char* const SHAPE_IMAGE_TABLE[] = +{ + DEMO_IMAGE_DIR "shape-circle.png", + DEMO_IMAGE_DIR "shape-bubble.png" +}; +constexpr int NUMBER_OF_SHAPE_IMAGES(sizeof(SHAPE_IMAGE_TABLE) / sizeof(SHAPE_IMAGE_TABLE[0])); + +constexpr int NUM_BACKGROUND_IMAGES = 18; +constexpr float BACKGROUND_SPREAD_SCALE = 1.5f; + +constexpr unsigned int BACKGROUND_ANIMATION_DURATION = 15000; // 15 secs + +constexpr float BUBBLE_MIN_Z = -1.0; +constexpr float BUBBLE_MAX_Z = 0.0f; + +/** + * Constraint to return a position for a bubble based on the scroll value and vertical wrapping + */ +struct AnimateBubbleConstraint +{ +public: + AnimateBubbleConstraint(const Vector3& initialPos, float scale) + : mInitialX(initialPos.x), + mScale(scale) + { + } + + void operator()(Vector3& position, const PropertyInputContainer& inputs) + { + const Vector3& parentSize = inputs[1]->GetVector3(); + const Vector3& childSize = inputs[2]->GetVector3(); + + // Wrap bubbles vertically. + float range = parentSize.y + childSize.y; + // This performs a float mod (we don't use fmod as we want the arithmetic modulus as opposed to the remainder). + position.y -= range * (floor(position.y / range) + 0.5f); + + // Bubbles X position moves parallax to horizontal + // panning by a scale factor unique to each bubble. + position.x = mInitialX + (inputs[0]->GetVector2().x * mScale); + } + +private: + float mInitialX; + float mScale; +}; + +} // unnamed namespace + +void BubbleAnimator::Initialize(Dali::Actor parent, Dali::Actor scrollView) +{ + mScrollView = scrollView; + + // Populate background and bubbles - needs to be scrollViewLayer so scroll ends show + Actor bubbleContainer = Actor::New(); + bubbleContainer.SetResizePolicy(ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS); + bubbleContainer.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER); + bubbleContainer.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER); + AddBackgroundActors(bubbleContainer, NUM_BACKGROUND_IMAGES); + parent.Add(bubbleContainer); + + // Background animation + mAnimationTimer = Timer::New(BACKGROUND_ANIMATION_DURATION); + mAnimationTimer.TickSignal().Connect(this, &BubbleAnimator::PauseAnimation); + mAnimationTimer.Start(); + mBackgroundAnimsPlaying = true; +} + +bool BubbleAnimator::PauseAnimation() +{ + if(mBackgroundAnimsPlaying) + { + for(auto&& anim : mBackgroundAnimations) + { + anim.Stop(); + } + + mBackgroundAnimsPlaying = false; + } + return false; +} + +void BubbleAnimator::PlayAnimation() +{ + if(!mBackgroundAnimsPlaying) + { + for(auto&& anim : mBackgroundAnimations) + { + anim.Play(); + } + + mBackgroundAnimsPlaying = true; + } + + mAnimationTimer.SetInterval(BACKGROUND_ANIMATION_DURATION); +} +void BubbleAnimator::InitializeBackgroundActors(Dali::Actor actor) +{ + // Delete current animations + mBackgroundAnimations.clear(); + + // Create new animations + const Vector3 size = actor.GetTargetSize(); + + for(unsigned int i = 0, childCount = actor.GetChildCount(); i < childCount; ++i) + { + Actor child = actor.GetChildAt(i); + + // Calculate a random position + Vector3 childPos(Random::Range(-size.x * 0.5f * BACKGROUND_SPREAD_SCALE, size.x * 0.85f * BACKGROUND_SPREAD_SCALE), + Random::Range(-size.y, size.y), + Random::Range(BUBBLE_MIN_Z, BUBBLE_MAX_Z)); + + child.SetProperty(Actor::Property::POSITION, childPos); + + // Define bubble horizontal parallax and vertical wrapping + Actor scrollView = mScrollView.GetHandle(); + if( scrollView ) + { + Constraint animConstraint = Constraint::New(child, Actor::Property::POSITION, AnimateBubbleConstraint(childPos, Random::Range(-0.85f, 0.25f))); + animConstraint.AddSource(Source(scrollView, ScrollView::Property::SCROLL_POSITION)); + animConstraint.AddSource(Dali::ParentSource(Dali::Actor::Property::SIZE)); + animConstraint.AddSource(Dali::LocalSource(Dali::Actor::Property::SIZE)); + animConstraint.SetRemoveAction(Constraint::DISCARD); + animConstraint.Apply(); + } + + // Kickoff animation + Animation animation = Animation::New(Random::Range(30.0f, 160.0f)); + animation.AnimateBy(Property(child, Actor::Property::POSITION), Vector3(0.0f, -2000.0f, 0.0f), AlphaFunction::LINEAR); + animation.SetLooping(true); + animation.Play(); + mBackgroundAnimations.push_back(animation); + } + +} + +void BubbleAnimator::AddBackgroundActors(Actor layer, int count) +{ + for(int i = 0; i < count; ++i) + { + float randSize = Random::Range(10.0f, 400.0f); + int shapeType = static_cast(Random::Range(0.0f, NUMBER_OF_SHAPE_IMAGES - 1) + 0.5f); + + ImageView dfActor = ImageView::New(); + dfActor.SetProperty(Actor::Property::SIZE, Vector2(randSize, randSize)); + dfActor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER); + + // Set the Image URL and the custom shader at the same time + Dali::Property::Map effect = Toolkit::CreateDistanceFieldEffect(); + Property::Map imageMap; + imageMap.Add(ImageVisual::Property::URL, SHAPE_IMAGE_TABLE[shapeType]); + imageMap.Add(Toolkit::Visual::Property::SHADER, effect); + dfActor.SetProperty(Toolkit::ImageView::Property::IMAGE, imageMap); + + dfActor.SetStyleName(BUBBLE_COLOR_STYLE_NAME[i % NUMBER_OF_BUBBLE_COLORS]); + + layer.Add(dfActor); + } + + // Positioning will occur when the layer is relaid out + layer.OnRelayoutSignal().Connect(this, &BubbleAnimator::InitializeBackgroundActors); +} diff --git a/shared/bubble-animator.h b/shared/bubble-animator.h new file mode 100644 index 0000000..f8f6ce9 --- /dev/null +++ b/shared/bubble-animator.h @@ -0,0 +1,83 @@ +#ifndef DALI_DEMO_BUBBLE_ANIMATOR_H +#define DALI_DEMO_BUBBLE_ANIMATOR_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. + * + */ + +// EXTERNAL INCLUDES +#include +#include +#include +#include +#include +#include + +/** + * Creates and animates random sized bubbles + */ +class BubbleAnimator : public Dali::ConnectionTracker +{ +public: + + /** + * @brief Initilizes the bubble background + * + * @param parent The actor to add all the bubbles to + * @param scrollView If provided, does a parallax effect when scrolling using this scroll-view (optional) + */ + void Initialize(Dali::Actor parent, Dali::Actor scrollView = Dali::Actor()); + + /** + * @brief Plays the bubble animation + */ + void PlayAnimation(); + +private: + + /** + * @brief Used by the timer to pause the animation + * + * @return Returns false to cancel the timer + */ + bool PauseAnimation(); + + /** + * @brief Initializes the background actors + * + * @param actor Actor which contains all the children + */ + void InitializeBackgroundActors(Dali::Actor actor); + + /** + * Create background actors for the given layer + * + * @param[in] layer The layer to add the actors to + * @param[in] count The number of actors to generate + */ + void AddBackgroundActors(Dali::Actor layer, int count); + +private: + + using AnimationList = std::vector; + + Dali::WeakHandle mScrollView; ///< Weak handle to the scroll view used to apply a parallax effect when scrolling. + AnimationList mBackgroundAnimations; ///< List of background bubble animations. + Dali::Timer mAnimationTimer; ///< Timer used to turn off animation after a specific time period. + bool mBackgroundAnimsPlaying{false}; ///< Are background animations playing. +}; + +#endif // DALI_DEMO_BUBBLE_ANIMATOR_H diff --git a/shared/dali-table-view.cpp b/shared/dali-table-view.cpp index 8d84507..3b3719a 100755 --- a/shared/dali-table-view.cpp +++ b/shared/dali-table-view.cpp @@ -62,49 +62,17 @@ const float KEYBOARD_FOCUS_MID_KEY_FRAME_TIME = KEYBOARD_FOCUS_ANIMATION_DURAT const float TILE_LABEL_PADDING = 8.0f; ///< Border between edge of tile and the example text const float BUTTON_PRESS_ANIMATION_TIME = 0.35f; ///< Time to perform button scale effect. -const float ROTATE_ANIMATION_TIME = 0.5f; ///< Time to perform rotate effect. -const int MAX_PAGES = 256; ///< Maximum pages (arbitrary safety limit) const int EXAMPLES_PER_ROW = 3; const int ROWS_PER_PAGE = 3; const int EXAMPLES_PER_PAGE = EXAMPLES_PER_ROW * ROWS_PER_PAGE; -const float LOGO_MARGIN_RATIO = 0.1f / 0.3f; -const float BOTTOM_PADDING_RATIO = 0.4f / 0.9f; -const Vector3 SCROLLVIEW_RELATIVE_SIZE(0.9f, 1.0f, 0.8f); ///< ScrollView's relative size to its parent const Vector3 TABLE_RELATIVE_SIZE(0.95f, 0.9f, 0.8f); ///< TableView's relative size to the entire stage. The Y value means sum of the logo and table relative heights. -const float STENCIL_RELATIVE_SIZE = 1.0f; - -const float EFFECT_SNAP_DURATION = 0.66f; ///< Scroll Snap Duration for Effects -const float EFFECT_FLICK_DURATION = 0.5f; ///< Scroll Flick Duration for Effects -const Vector3 ANGLE_CUBE_PAGE_ROTATE(Math::PI * 0.5f, Math::PI * 0.5f, 0.0f); - -const char* const BUBBLE_COLOR_STYLE_NAME[] = - { - "BubbleColor1", - "BubbleColor2", - "BubbleColor3", - "BubbleColor4"}; -const int NUMBER_OF_BUBBLE_COLORS(sizeof(BUBBLE_COLOR_STYLE_NAME) / sizeof(BUBBLE_COLOR_STYLE_NAME[0])); - -const char* const SHAPE_IMAGE_TABLE[] = - { - DEMO_IMAGE_DIR "shape-circle.png", - DEMO_IMAGE_DIR "shape-bubble.png"}; -const int NUMBER_OF_SHAPE_IMAGES(sizeof(SHAPE_IMAGE_TABLE) / sizeof(SHAPE_IMAGE_TABLE[0])); - -const int NUM_BACKGROUND_IMAGES = 18; -const float BACKGROUND_SPREAD_SCALE = 1.5f; - -const unsigned int BACKGROUND_ANIMATION_DURATION = 15000; // 15 secs - -const float BUBBLE_MIN_Z = -1.0; -const float BUBBLE_MAX_Z = 0.0f; const char* const DEMO_BUILD_DATE = __DATE__ " " __TIME__; /** * Creates the background image */ -Control CreateBackground(std::string stylename) +Actor CreateBackground(std::string stylename) { Control background = Control::New(); background.SetStyleName(stylename); @@ -116,38 +84,6 @@ Control CreateBackground(std::string stylename) } /** - * Constraint to return a position for a bubble based on the scroll value and vertical wrapping - */ -struct AnimateBubbleConstraint -{ -public: - AnimateBubbleConstraint(const Vector3& initialPos, float scale) - : mInitialX(initialPos.x), - mScale(scale) - { - } - - void operator()(Vector3& position, const PropertyInputContainer& inputs) - { - const Vector3& parentSize = inputs[1]->GetVector3(); - const Vector3& childSize = inputs[2]->GetVector3(); - - // Wrap bubbles vertically. - float range = parentSize.y + childSize.y; - // This performs a float mod (we don't use fmod as we want the arithmetic modulus as opposed to the remainder). - position.y -= range * (floor(position.y / range) + 0.5f); - - // Bubbles X position moves parallax to horizontal - // panning by a scale factor unique to each bubble. - position.x = mInitialX + (inputs[0]->GetVector2().x * mScale); - } - -private: - float mInitialX; - float mScale; -}; - -/** * Constraint to precalculate values from the scroll-view * and tile positions to pass to the tile shader. */ @@ -182,9 +118,94 @@ private: float mTileXOffset; }; -bool CompareByTitle(const Example& lhs, const Example& rhs) +/** + * Creates a popup that shows the version information of the DALi libraries and demo + */ +Dali::Toolkit::Popup CreateVersionPopup(Application& application, ConnectionTrackerInterface& connectionTracker) +{ + std::ostringstream stream; + stream << "DALi Core: " << CORE_MAJOR_VERSION << "." << CORE_MINOR_VERSION << "." << CORE_MICRO_VERSION << std::endl + << "(" << CORE_BUILD_DATE << ")\n"; + stream << "DALi Adaptor: " << ADAPTOR_MAJOR_VERSION << "." << ADAPTOR_MINOR_VERSION << "." << ADAPTOR_MICRO_VERSION << std::endl + << "(" << ADAPTOR_BUILD_DATE << ")\n"; + stream << "DALi Toolkit: " << TOOLKIT_MAJOR_VERSION << "." << TOOLKIT_MINOR_VERSION << "." << TOOLKIT_MICRO_VERSION << std::endl + << "(" << TOOLKIT_BUILD_DATE << ")\n"; + stream << "DALi Demo:" + << "\n(" << DEMO_BUILD_DATE << ")\n"; + + Dali::Toolkit::Popup popup = Dali::Toolkit::Popup::New(); + + Toolkit::TextLabel titleActor = Toolkit::TextLabel::New("Version information"); + titleActor.SetProperty(Actor::Property::NAME, "titleActor"); + titleActor.SetProperty(Toolkit::TextLabel::Property::HORIZONTAL_ALIGNMENT, HorizontalAlignment::CENTER); + titleActor.SetProperty(Toolkit::TextLabel::Property::TEXT_COLOR, Color::WHITE); + + Toolkit::TextLabel contentActor = Toolkit::TextLabel::New(stream.str()); + contentActor.SetProperty(Actor::Property::NAME, "contentActor"); + contentActor.SetProperty(Toolkit::TextLabel::Property::MULTI_LINE, true); + contentActor.SetProperty(Toolkit::TextLabel::Property::HORIZONTAL_ALIGNMENT, HorizontalAlignment::CENTER); + contentActor.SetProperty(Toolkit::TextLabel::Property::TEXT_COLOR, Color::WHITE); + contentActor.SetProperty(Actor::Property::PADDING, Padding(0.0f, 0.0f, 20.0f, 0.0f)); + + popup.SetTitle(titleActor); + popup.SetContent(contentActor); + + popup.SetResizePolicy(ResizePolicy::SIZE_RELATIVE_TO_PARENT, Dimension::WIDTH); + popup.SetProperty(Actor::Property::SIZE_MODE_FACTOR, Vector3(0.75f, 1.0f, 1.0f)); + popup.SetResizePolicy(ResizePolicy::FIT_TO_CHILDREN, Dimension::HEIGHT); + + application.GetWindow().Add(popup); + + // Hide the popup when touched outside + popup.OutsideTouchedSignal().Connect( + &connectionTracker, + [popup]() mutable + { + if(popup && (popup.GetDisplayState() == Toolkit::Popup::SHOWN)) + { + popup.SetDisplayState(Popup::HIDDEN); + } + }); + + return popup; +} + +/// Sets up the inner cube effect +Dali::Toolkit::ScrollViewEffect SetupInnerPageCubeEffect(const Vector2 windowSize, int totalPages) { - return lhs.title < rhs.title; + Dali::Path path = Dali::Path::New(); + Dali::Property::Array points; + points.Resize(3); + points[0] = Vector3(windowSize.x * 0.5, 0.0f, windowSize.x * 0.5f); + points[1] = Vector3(0.0f, 0.0f, 0.0f); + points[2] = Vector3(-windowSize.x * 0.5f, 0.0f, windowSize.x * 0.5f); + path.SetProperty(Path::Property::POINTS, points); + + Dali::Property::Array controlPoints; + controlPoints.Resize(4); + controlPoints[0] = Vector3(windowSize.x * 0.5f, 0.0f, windowSize.x * 0.3f); + controlPoints[1] = Vector3(windowSize.x * 0.3f, 0.0f, 0.0f); + controlPoints[2] = Vector3(-windowSize.x * 0.3f, 0.0f, 0.0f); + controlPoints[3] = Vector3(-windowSize.x * 0.5f, 0.0f, windowSize.x * 0.3f); + path.SetProperty(Path::Property::CONTROL_POINTS, controlPoints); + + return ScrollViewPagePathEffect::New(path, + Vector3(-1.0f, 0.0f, 0.0f), + Toolkit::ScrollView::Property::SCROLL_FINAL_X, + Vector3(windowSize.x * TABLE_RELATIVE_SIZE.x, windowSize.y * TABLE_RELATIVE_SIZE.y, 0.0f), + totalPages); +} + +/// Sets up the scroll view rulers +void SetupScrollViewRulers(ScrollView& scrollView, const uint16_t windowWidth, const float pageWidth, const int totalPages) +{ + // Update Ruler info. for the scroll-view + Dali::Toolkit::RulerPtr rulerX = new FixedRuler(pageWidth); + Dali::Toolkit::RulerPtr rulerY = new DefaultRuler(); + rulerX->SetDomain(RulerDomain(0.0f, (totalPages + 1) * windowWidth * TABLE_RELATIVE_SIZE.x * 0.5f, true)); + rulerY->Disable(); + scrollView.SetRulerX(rulerX); + scrollView.SetRulerY(rulerY); } } // namespace @@ -192,32 +213,22 @@ bool CompareByTitle(const Example& lhs, const Example& rhs) DaliTableView::DaliTableView(Application& application) : mApplication(application), mRootActor(), - mRotateAnimation(), mPressedAnimation(), mScrollView(), mScrollViewEffect(), - mScrollRulerX(), - mScrollRulerY(), mPressedActor(), - mAnimationTimer(), mLogoTapDetector(), mVersionPopup(), mPages(), - mBackgroundAnimations(), mExampleList(), mPageWidth(0.0f), mTotalPages(), mScrolling(false), - mSortAlphabetically(false), - mBackgroundAnimsPlaying(false) + mSortAlphabetically(false) { application.InitSignal().Connect(this, &DaliTableView::Initialize); } -DaliTableView::~DaliTableView() -{ -} - void DaliTableView::AddExample(Example example) { mExampleList.push_back(example); @@ -271,14 +282,8 @@ void DaliTableView::Initialize(Application& application) mPageWidth = windowSize.GetWidth() * TABLE_RELATIVE_SIZE.x * 0.5f; - // Populate background and bubbles - needs to be scrollViewLayer so scroll ends show - Actor bubbleContainer = Actor::New(); - bubbleContainer.SetResizePolicy(ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS); - bubbleContainer.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER); - bubbleContainer.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER); - SetupBackground(bubbleContainer); + mBubbleAnimator.Initialize(mRootActor, mScrollView); - mRootActor.Add(bubbleContainer); mRootActor.Add(mScrollView); // Add scroll view effect and setup constraints on pages @@ -307,16 +312,6 @@ void DaliTableView::Initialize(Application& application) winHandle.RemoveAvailableOrientation(Dali::Window::PORTRAIT_INVERSE); } - // Set initial orientation - unsigned int degrees = 0; - Rotate(degrees); - - // Background animation - mAnimationTimer = Timer::New(BACKGROUND_ANIMATION_DURATION); - mAnimationTimer.TickSignal().Connect(this, &DaliTableView::PauseBackgroundAnimation); - mAnimationTimer.Start(); - mBackgroundAnimsPlaying = true; - CreateFocusEffect(); } @@ -393,10 +388,6 @@ void DaliTableView::ApplyCubeEffectToPages() } } -void DaliTableView::OnButtonsPageRelayout(const Dali::Actor& actor) -{ -} - void DaliTableView::Populate() { const Window::WindowSize windowSize = mApplication.GetWindow().GetSize(); @@ -408,13 +399,13 @@ void DaliTableView::Populate() { if(mSortAlphabetically) { - sort(mExampleList.begin(), mExampleList.end(), CompareByTitle); + sort(mExampleList.begin(), mExampleList.end(), [](auto& lhs, auto& rhs)->bool { return lhs.title < rhs.title; } ); } unsigned int exampleCount = 0; ExampleListConstIter iter = mExampleList.begin(); - for(int t = 0; t < mTotalPages; t++) + for(int t = 0; t < mTotalPages && iter != mExampleList.end(); t++) { // Create Table TableView page = TableView::New(ROWS_PER_PAGE, EXAMPLES_PER_ROW); @@ -427,9 +418,9 @@ void DaliTableView::Populate() const float margin = 2.0f; const float tileParentMultiplier = 1.0f / EXAMPLES_PER_ROW; - for(int row = 0; row < ROWS_PER_PAGE; row++) + for(int row = 0; row < ROWS_PER_PAGE && iter != mExampleList.end(); row++) { - for(int column = 0; column < EXAMPLES_PER_ROW; column++) + for(int column = 0; column < EXAMPLES_PER_ROW && iter != mExampleList.end(); column++) { const Example& example = (*iter); @@ -446,59 +437,14 @@ void DaliTableView::Populate() page.AddChild(tile, TableView::CellPosition(row, column)); iter++; - - if(iter == mExampleList.end()) - { - break; - } - } - - if(iter == mExampleList.end()) - { - break; } } mPages.push_back(page); - - if(iter == mExampleList.end()) - { - break; - } } } - // Update Ruler info. - mScrollRulerX = new FixedRuler(mPageWidth); - mScrollRulerY = new DefaultRuler(); - mScrollRulerX->SetDomain(RulerDomain(0.0f, (mTotalPages + 1) * windowSize.GetWidth() * TABLE_RELATIVE_SIZE.x * 0.5f, true)); - mScrollRulerY->Disable(); - mScrollView.SetRulerX(mScrollRulerX); - mScrollView.SetRulerY(mScrollRulerY); -} - -void DaliTableView::Rotate(unsigned int degrees) -{ - // Resize the root actor - const Window::WindowSize windowSize = mApplication.GetWindow().GetSize(); - const Vector2 originalSize(windowSize.GetWidth(), windowSize.GetHeight()); - Vector3 targetSize(originalSize.x, originalSize.y, 1.0f); - - if(degrees == 90 || degrees == 270) - { - targetSize = Vector3(originalSize.y, originalSize.x, 1.0f); - } - - if(mRotateAnimation) - { - mRotateAnimation.Stop(); - mRotateAnimation.Clear(); - } - - mRotateAnimation = Animation::New(ROTATE_ANIMATION_TIME); - mRotateAnimation.AnimateTo(Property(mRootActor, Actor::Property::ORIENTATION), Quaternion(Radian(Degree(360 - degrees)), Vector3::ZAXIS), AlphaFunction::EASE_OUT); - mRotateAnimation.AnimateTo(Property(mRootActor, Actor::Property::SIZE), targetSize, AlphaFunction::EASE_OUT); - mRotateAnimation.Play(); + SetupScrollViewRulers(mScrollView, windowSize.GetWidth(), mPageWidth, mTotalPages); } Actor DaliTableView::CreateTile(const std::string& name, const std::string& title, const Dali::Vector3& sizeMultiplier, Vector2& position) @@ -587,10 +533,9 @@ bool DaliTableView::DoTilePress(Actor actor, PointState::Type pointState) if((!mScrolling) && (!mPressedAnimation)) { std::string name = actor.GetProperty(Dali::Actor::Property::NAME); - const ExampleListIter end = mExampleList.end(); - for(ExampleListIter iter = mExampleList.begin(); iter != end; ++iter) + for(Example& example : mExampleList) { - if((*iter).name == name) + if(example.name == name) { // do nothing, until pressed animation finished. consumed = true; @@ -636,7 +581,7 @@ void DaliTableView::OnScrollStart(const Dali::Vector2& position) { mScrolling = true; - PlayAnimation(); + mBubbleAnimator.PlayAnimation(); } void DaliTableView::OnScrollComplete(const Dali::Vector2& position) @@ -668,39 +613,11 @@ void DaliTableView::ApplyScrollViewEffect() } // Just one effect for now - SetupInnerPageCubeEffect(); + mScrollViewEffect = SetupInnerPageCubeEffect(mApplication.GetWindow().GetSize(), mTotalPages); mScrollView.ApplyEffect(mScrollViewEffect); } -void DaliTableView::SetupInnerPageCubeEffect() -{ - const Window::WindowSize windowDimensions = mApplication.GetWindow().GetSize(); - const Vector2 windowSize(windowDimensions.GetWidth(), windowDimensions.GetHeight()); - - Dali::Path path = Dali::Path::New(); - Dali::Property::Array points; - points.Resize(3); - points[0] = Vector3(windowSize.x * 0.5, 0.0f, windowSize.x * 0.5f); - points[1] = Vector3(0.0f, 0.0f, 0.0f); - points[2] = Vector3(-windowSize.x * 0.5f, 0.0f, windowSize.x * 0.5f); - path.SetProperty(Path::Property::POINTS, points); - - Dali::Property::Array controlPoints; - controlPoints.Resize(4); - controlPoints[0] = Vector3(windowSize.x * 0.5f, 0.0f, windowSize.x * 0.3f); - controlPoints[1] = Vector3(windowSize.x * 0.3f, 0.0f, 0.0f); - controlPoints[2] = Vector3(-windowSize.x * 0.3f, 0.0f, 0.0f); - controlPoints[3] = Vector3(-windowSize.x * 0.5f, 0.0f, windowSize.x * 0.3f); - path.SetProperty(Path::Property::CONTROL_POINTS, controlPoints); - - mScrollViewEffect = ScrollViewPagePathEffect::New(path, - Vector3(-1.0f, 0.0f, 0.0f), - Toolkit::ScrollView::Property::SCROLL_FINAL_X, - Vector3(windowSize.x * TABLE_RELATIVE_SIZE.x, windowSize.y * TABLE_RELATIVE_SIZE.y, 0.0f), - mTotalPages); -} - void DaliTableView::OnKeyEvent(const KeyEvent& event) { if(event.GetState() == KeyEvent::DOWN) @@ -721,115 +638,6 @@ void DaliTableView::OnKeyEvent(const KeyEvent& event) } } -void DaliTableView::SetupBackground(Actor bubbleContainer) -{ - // Add bubbles to the bubbleContainer. - // Note: The bubbleContainer is parented externally to this function. - AddBackgroundActors(bubbleContainer, NUM_BACKGROUND_IMAGES); -} - -void DaliTableView::InitialiseBackgroundActors(Actor actor) -{ - // Delete current animations - mBackgroundAnimations.clear(); - - // Create new animations - const Vector3 size = actor.GetTargetSize(); - - for(unsigned int i = 0, childCount = actor.GetChildCount(); i < childCount; ++i) - { - Actor child = actor.GetChildAt(i); - - // Calculate a random position - Vector3 childPos(Random::Range(-size.x * 0.5f * BACKGROUND_SPREAD_SCALE, size.x * 0.85f * BACKGROUND_SPREAD_SCALE), - Random::Range(-size.y, size.y), - Random::Range(BUBBLE_MIN_Z, BUBBLE_MAX_Z)); - - child.SetProperty(Actor::Property::POSITION, childPos); - - // Define bubble horizontal parallax and vertical wrapping - Constraint animConstraint = Constraint::New(child, Actor::Property::POSITION, AnimateBubbleConstraint(childPos, Random::Range(-0.85f, 0.25f))); - animConstraint.AddSource(Source(mScrollView, ScrollView::Property::SCROLL_POSITION)); - animConstraint.AddSource(Dali::ParentSource(Dali::Actor::Property::SIZE)); - animConstraint.AddSource(Dali::LocalSource(Dali::Actor::Property::SIZE)); - animConstraint.SetRemoveAction(Constraint::DISCARD); - animConstraint.Apply(); - - // Kickoff animation - Animation animation = Animation::New(Random::Range(30.0f, 160.0f)); - animation.AnimateBy(Property(child, Actor::Property::POSITION), Vector3(0.0f, -2000.0f, 0.0f), AlphaFunction::LINEAR); - animation.SetLooping(true); - animation.Play(); - mBackgroundAnimations.push_back(animation); - } -} - -void DaliTableView::AddBackgroundActors(Actor layer, int count) -{ - for(int i = 0; i < count; ++i) - { - float randSize = Random::Range(10.0f, 400.0f); - int shapeType = static_cast(Random::Range(0.0f, NUMBER_OF_SHAPE_IMAGES - 1) + 0.5f); - - ImageView dfActor = ImageView::New(); - dfActor.SetProperty(Actor::Property::SIZE, Vector2(randSize, randSize)); - dfActor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER); - - // Set the Image URL and the custom shader at the same time - Dali::Property::Map effect = Toolkit::CreateDistanceFieldEffect(); - Property::Map imageMap; - imageMap.Add(ImageVisual::Property::URL, SHAPE_IMAGE_TABLE[shapeType]); - imageMap.Add(Toolkit::Visual::Property::SHADER, effect); - dfActor.SetProperty(Toolkit::ImageView::Property::IMAGE, imageMap); - - dfActor.SetStyleName(BUBBLE_COLOR_STYLE_NAME[i % NUMBER_OF_BUBBLE_COLORS]); - - layer.Add(dfActor); - } - - // Positioning will occur when the layer is relaid out - layer.OnRelayoutSignal().Connect(this, &DaliTableView::InitialiseBackgroundActors); -} - -bool DaliTableView::PauseBackgroundAnimation() -{ - PauseAnimation(); - - return false; -} - -void DaliTableView::PauseAnimation() -{ - if(mBackgroundAnimsPlaying) - { - for(AnimationListIter animIter = mBackgroundAnimations.begin(); animIter != mBackgroundAnimations.end(); ++animIter) - { - Animation anim = *animIter; - - anim.Stop(); - } - - mBackgroundAnimsPlaying = false; - } -} - -void DaliTableView::PlayAnimation() -{ - if(!mBackgroundAnimsPlaying) - { - for(AnimationListIter animIter = mBackgroundAnimations.begin(); animIter != mBackgroundAnimations.end(); ++animIter) - { - Animation anim = *animIter; - - anim.Play(); - } - - mBackgroundAnimsPlaying = true; - } - - mAnimationTimer.SetInterval(BACKGROUND_ANIMATION_DURATION); -} - Dali::Actor DaliTableView::OnKeyboardPreFocusChange(Dali::Actor current, Dali::Actor proposed, Dali::Toolkit::Control::KeyboardFocus::Direction direction) { Actor nextFocusActor = proposed; @@ -914,50 +722,9 @@ void DaliTableView::OnLogoTapped(Dali::Actor actor, const Dali::TapGesture& tap) { if(!mVersionPopup) { - std::ostringstream stream; - stream << "DALi Core: " << CORE_MAJOR_VERSION << "." << CORE_MINOR_VERSION << "." << CORE_MICRO_VERSION << std::endl - << "(" << CORE_BUILD_DATE << ")\n"; - stream << "DALi Adaptor: " << ADAPTOR_MAJOR_VERSION << "." << ADAPTOR_MINOR_VERSION << "." << ADAPTOR_MICRO_VERSION << std::endl - << "(" << ADAPTOR_BUILD_DATE << ")\n"; - stream << "DALi Toolkit: " << TOOLKIT_MAJOR_VERSION << "." << TOOLKIT_MINOR_VERSION << "." << TOOLKIT_MICRO_VERSION << std::endl - << "(" << TOOLKIT_BUILD_DATE << ")\n"; - stream << "DALi Demo:" - << "\n(" << DEMO_BUILD_DATE << ")\n"; - - mVersionPopup = Dali::Toolkit::Popup::New(); - - Toolkit::TextLabel titleActor = Toolkit::TextLabel::New("Version information"); - titleActor.SetProperty(Actor::Property::NAME, "titleActor"); - titleActor.SetProperty(Toolkit::TextLabel::Property::HORIZONTAL_ALIGNMENT, HorizontalAlignment::CENTER); - titleActor.SetProperty(Toolkit::TextLabel::Property::TEXT_COLOR, Color::WHITE); - - Toolkit::TextLabel contentActor = Toolkit::TextLabel::New(stream.str()); - contentActor.SetProperty(Actor::Property::NAME, "contentActor"); - contentActor.SetProperty(Toolkit::TextLabel::Property::MULTI_LINE, true); - contentActor.SetProperty(Toolkit::TextLabel::Property::HORIZONTAL_ALIGNMENT, HorizontalAlignment::CENTER); - contentActor.SetProperty(Toolkit::TextLabel::Property::TEXT_COLOR, Color::WHITE); - contentActor.SetProperty(Actor::Property::PADDING, Padding(0.0f, 0.0f, 20.0f, 0.0f)); - - mVersionPopup.SetTitle(titleActor); - mVersionPopup.SetContent(contentActor); - - mVersionPopup.SetResizePolicy(ResizePolicy::SIZE_RELATIVE_TO_PARENT, Dimension::WIDTH); - mVersionPopup.SetProperty(Actor::Property::SIZE_MODE_FACTOR, Vector3(0.75f, 1.0f, 1.0f)); - mVersionPopup.SetResizePolicy(ResizePolicy::FIT_TO_CHILDREN, Dimension::HEIGHT); - - mVersionPopup.OutsideTouchedSignal().Connect(this, &DaliTableView::HideVersionPopup); - mApplication.GetWindow().Add(mVersionPopup); + mVersionPopup = CreateVersionPopup(mApplication, *this); } mVersionPopup.SetDisplayState(Popup::SHOWN); } } - -void DaliTableView::HideVersionPopup() -{ - // Only hide if currently fully shown. If transitioning-in, the transition will not be interrupted. - if(mVersionPopup && (mVersionPopup.GetDisplayState() == Toolkit::Popup::SHOWN)) - { - mVersionPopup.SetDisplayState(Popup::HIDDEN); - } -} diff --git a/shared/dali-table-view.h b/shared/dali-table-view.h index 44a81dd..d4fee68 100644 --- a/shared/dali-table-view.h +++ b/shared/dali-table-view.h @@ -18,48 +18,14 @@ * */ +// EXTERNAL INCLUDES #include #include #include -class Example; - -typedef std::vector ExampleList; -typedef ExampleList::iterator ExampleListIter; -typedef ExampleList::const_iterator ExampleListConstIter; - -typedef std::vector AnimationList; -typedef AnimationList::iterator AnimationListIter; -typedef AnimationList::const_iterator AnimationListConstIter; - -/** - * Example information - * - * Represents a single Example. - */ -struct Example -{ - // Constructors - - /** - * @param[in] name unique name of example - * @param[in] title The caption for the example to appear on a tile button. - */ - Example(std::string name, std::string title) - : name(name), - title(title) - { - } - - Example() - { - } - - // Data - - std::string name; ///< unique name of example - std::string title; ///< title (caption) of example to appear on tile button. -}; +// INTERNAL INCLUDES +#include "bubble-animator.h" +#include "example.h" /** * Dali-Demo instance @@ -67,8 +33,18 @@ struct Example class DaliTableView : public Dali::ConnectionTracker { public: + + /** + * Constructor + * + * @param application A reference to the application class + */ DaliTableView(Dali::Application& application); - ~DaliTableView(); + + /** + * Destructor + */ + ~DaliTableView() = default; public: /** @@ -90,17 +66,8 @@ public: */ void SortAlphabetically(bool sortAlphabetically); -private: // Application callbacks & implementation - static const unsigned int FOCUS_ANIMATION_ACTOR_NUMBER = 2; ///< The number of elements used to form the custom focus effect - - /** - * Shape enum for create function - */ - enum ShapeType - { - CIRCLE, - BUBBLE - }; +private: // Application callbacks & implementation + static constexpr unsigned int FOCUS_ANIMATION_ACTOR_NUMBER = 2; ///< The number of elements used to form the custom focus effect /** * Initialize application. @@ -117,13 +84,6 @@ private: // Application cal void Populate(); /** - * Rotates RootActor orientation to that specified. - * - * @param[in] degrees The requested angle. - */ - void Rotate(unsigned int degrees); - - /** * Creates a tile for the main menu. * * @param[in] name The unique name for this Tile @@ -175,15 +135,6 @@ private: // Application cal void OnPressedAnimationFinished(Dali::Animation& source); /** - * Signal emitted when the button has been clicked - * - * @param[in] button The Button that is clicked. - * - * @return Consume flag - */ - bool OnButtonClicked(Dali::Toolkit::Button& button); - - /** * Signal emitted when scrolling has started. * * @param[in] position The current position of the scroll contents. @@ -219,58 +170,11 @@ private: // Application cal void ApplyCubeEffectToPages(); /** - * Setup the inner cube effect - */ - void SetupInnerPageCubeEffect(); - - /** - * Apply a shader effect to a table tile - */ - void ApplyEffectToTile(Dali::Actor tile); - - /** - * Apply effect to the content of a tile - */ - void ApplyEffectToTileContent(Dali::Actor tileContent); - - /** * Key event handler */ void OnKeyEvent(const Dali::KeyEvent& event); /** - * Create a depth field background - * - * @param[in] bubbleLayer Add the graphics to this layer - */ - void SetupBackground(Dali::Actor bubbleLayer); - - /** - * Create background actors for the given layer - * - * @param[in] layer The layer to add the actors to - * @param[in] count The number of actors to generate - */ - void AddBackgroundActors(Dali::Actor layer, int count); - - /** - * Timer handler for ending background animation - * - * @return Return value for timer handler - */ - bool PauseBackgroundAnimation(); - - /** - * Pause all animations - */ - void PauseAnimation(); - - /** - * Resume all animations - */ - void PlayAnimation(); - - /** * @brief Creates and sets up the custom effect used for the keyboard (and mouse) focus. */ void CreateFocusEffect(); @@ -314,44 +218,16 @@ private: // Application cal */ void OnLogoTapped(Dali::Actor actor, const Dali::TapGesture& tap); - /** - * Hides the popup - */ - void HideVersionPopup(); - - /* - * @brief Callback called when the buttons page actor is relaid out - * - * @param[in] actor The page actor - */ - void OnButtonsPageRelayout(const Dali::Actor& actor); - - /** - * @brief The is connected to the keyboard focus highlight actor, and called when it is placed on the scene. - * @param[in] actor The actor that has been placed on the scene. - */ - void OnSceneConnect(Dali::Actor actor); - - /** - * @brief Callback called to set up background actors - * - * @param[in] actor The actor raising the callback - */ - void InitialiseBackgroundActors(Dali::Actor actor); - private: Dali::Application& mApplication; ///< Application instance. - Dali::Toolkit::Control mRootActor; ///< All content (excluding background is anchored to this Actor) - Dali::Animation mRotateAnimation; ///< Animation to rotate and resize mRootActor. + Dali::Actor mRootActor; ///< All content (excluding background is anchored to this Actor) Dali::Animation mPressedAnimation; ///< Button press scaling animation. Dali::Toolkit::ScrollView mScrollView; ///< ScrollView container (for all Examples) Dali::Toolkit::ScrollViewEffect mScrollViewEffect; ///< Effect to be applied to the scroll view - Dali::Toolkit::RulerPtr mScrollRulerX; ///< ScrollView X (horizontal) ruler - Dali::Toolkit::RulerPtr mScrollRulerY; ///< ScrollView Y (vertical) ruler Dali::Actor mPressedActor; ///< The currently pressed actor. - Dali::Timer mAnimationTimer; ///< Timer used to turn off animation after a specific time period Dali::TapGestureDetector mLogoTapDetector; ///< To detect taps on the logo Dali::Toolkit::Popup mVersionPopup; ///< Displays DALi library version information + BubbleAnimator mBubbleAnimator; ///< Provides bubble animations. /** * This struct encapsulates all data relevant to each of the elements used within the custom keyboard focus effect. @@ -364,7 +240,6 @@ private: FocusEffect mFocusEffect[FOCUS_ANIMATION_ACTOR_NUMBER]; ///< The elements used to create the custom focus effect std::vector mPages; ///< List of pages. - AnimationList mBackgroundAnimations; ///< List of background bubble animations ExampleList mExampleList; ///< List of examples. float mPageWidth; ///< The width of a page within the scroll-view, used to calculate the domain @@ -372,7 +247,6 @@ private: bool mScrolling : 1; ///< Flag indicating whether view is currently being scrolled bool mSortAlphabetically : 1; ///< Sort examples alphabetically. - bool mBackgroundAnimsPlaying : 1; ///< Are background animations playing }; #endif // DALI_DEMO_TABLEVIEW_H diff --git a/shared/example.h b/shared/example.h new file mode 100644 index 0000000..978e849 --- /dev/null +++ b/shared/example.h @@ -0,0 +1,55 @@ +#ifndef DALI_DEMO_EXAMPLE_H +#define DALI_DEMO_EXAMPLE_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. + * + */ + +// EXTERNAL INCLUDES +#include +#include + +/** + * Example information + * + * Represents a single Example. + */ +struct Example +{ + // Constructors + + /** + * @param[in] name unique name of example + * @param[in] title The caption for the example to appear on a tile button. + */ + Example(std::string name, std::string title) + : name(name), + title(title) + { + } + + ~Example() = default; + + // Data + + std::string name; ///< unique name of example + std::string title; ///< title (caption) of example to appear on tile button. +}; + +using ExampleList = std::vector; +using ExampleListConstIter = ExampleList::const_iterator; + +#endif // DALI_DEMO_SHARED_EXAMPLE_H -- 2.7.4