Merge "Reduced complexity of dali-table-view" into devel/master
authorAdeel Kazmi <adeel.kazmi@samsung.com>
Thu, 5 Nov 2020 22:14:00 +0000 (22:14 +0000)
committerGerrit Code Review <gerrit@review>
Thu, 5 Nov 2020 22:14:00 +0000 (22:14 +0000)
build/tizen/demo/CMakeLists.txt
build/tizen/examples-reel/CMakeLists.txt
build/tizen/tests-reel/CMakeLists.txt
shared/bubble-animator.cpp [new file with mode: 0644]
shared/bubble-animator.h [new file with mode: 0644]
shared/dali-table-view.cpp
shared/dali-table-view.h
shared/example.h [new file with mode: 0644]

index af1ed2a..855b82c 100644 (file)
@@ -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)
index 16f2a0e..8b392e7 100644 (file)
@@ -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)
index 728e6d4..a4d0af8 100644 (file)
@@ -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 (file)
index 0000000..5ce8e7c
--- /dev/null
@@ -0,0 +1,205 @@
+/*\r
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd.\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ *\r
+ */\r
+\r
+// CLASS HEADER\r
+#include "bubble-animator.h"\r
+\r
+#include <dali/public-api/animation/constraint.h>\r
+#include <dali/public-api/math/random.h>\r
+#include <dali/public-api/rendering/shader.h>\r
+#include <dali-toolkit/public-api/controls/image-view/image-view.h>\r
+#include <dali-toolkit/public-api/controls/scrollable/scroll-view/scroll-view.h>\r
+#include <dali-toolkit/public-api/visuals/image-visual-properties.h>\r
+#include <dali-toolkit/devel-api/shader-effects/distance-field-effect.h>\r
+\r
+using namespace Dali;\r
+using namespace Dali::Toolkit;\r
+\r
+namespace\r
+{\r
+const char* const BUBBLE_COLOR_STYLE_NAME[] =\r
+{\r
+  "BubbleColor1",\r
+  "BubbleColor2",\r
+  "BubbleColor3",\r
+  "BubbleColor4"\r
+};\r
+constexpr int NUMBER_OF_BUBBLE_COLORS(sizeof(BUBBLE_COLOR_STYLE_NAME) / sizeof(BUBBLE_COLOR_STYLE_NAME[0]));\r
+\r
+const char* const SHAPE_IMAGE_TABLE[] =\r
+{\r
+  DEMO_IMAGE_DIR "shape-circle.png",\r
+  DEMO_IMAGE_DIR "shape-bubble.png"\r
+};\r
+constexpr int NUMBER_OF_SHAPE_IMAGES(sizeof(SHAPE_IMAGE_TABLE) / sizeof(SHAPE_IMAGE_TABLE[0]));\r
+\r
+constexpr int   NUM_BACKGROUND_IMAGES   = 18;\r
+constexpr float BACKGROUND_SPREAD_SCALE = 1.5f;\r
+\r
+constexpr unsigned int BACKGROUND_ANIMATION_DURATION = 15000; // 15 secs\r
+\r
+constexpr float BUBBLE_MIN_Z = -1.0;\r
+constexpr float BUBBLE_MAX_Z = 0.0f;\r
+\r
+/**\r
+ * Constraint to return a position for a bubble based on the scroll value and vertical wrapping\r
+ */\r
+struct AnimateBubbleConstraint\r
+{\r
+public:\r
+  AnimateBubbleConstraint(const Vector3& initialPos, float scale)\r
+  : mInitialX(initialPos.x),\r
+    mScale(scale)\r
+  {\r
+  }\r
+\r
+  void operator()(Vector3& position, const PropertyInputContainer& inputs)\r
+  {\r
+    const Vector3& parentSize = inputs[1]->GetVector3();\r
+    const Vector3& childSize  = inputs[2]->GetVector3();\r
+\r
+    // Wrap bubbles vertically.\r
+    float range = parentSize.y + childSize.y;\r
+    // This performs a float mod (we don't use fmod as we want the arithmetic modulus as opposed to the remainder).\r
+    position.y -= range * (floor(position.y / range) + 0.5f);\r
+\r
+    // Bubbles X position moves parallax to horizontal\r
+    // panning by a scale factor unique to each bubble.\r
+    position.x = mInitialX + (inputs[0]->GetVector2().x * mScale);\r
+  }\r
+\r
+private:\r
+  float mInitialX;\r
+  float mScale;\r
+};\r
+\r
+} // unnamed namespace\r
+\r
+void BubbleAnimator::Initialize(Dali::Actor parent, Dali::Actor scrollView)\r
+{\r
+  mScrollView = scrollView;\r
+\r
+  // Populate background and bubbles - needs to be scrollViewLayer so scroll ends show\r
+  Actor bubbleContainer = Actor::New();\r
+  bubbleContainer.SetResizePolicy(ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS);\r
+  bubbleContainer.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);\r
+  bubbleContainer.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);\r
+  AddBackgroundActors(bubbleContainer, NUM_BACKGROUND_IMAGES);\r
+  parent.Add(bubbleContainer);\r
+\r
+  // Background animation\r
+  mAnimationTimer = Timer::New(BACKGROUND_ANIMATION_DURATION);\r
+  mAnimationTimer.TickSignal().Connect(this, &BubbleAnimator::PauseAnimation);\r
+  mAnimationTimer.Start();\r
+  mBackgroundAnimsPlaying = true;\r
+}\r
+\r
+bool BubbleAnimator::PauseAnimation()\r
+{\r
+  if(mBackgroundAnimsPlaying)\r
+  {\r
+    for(auto&& anim : mBackgroundAnimations)\r
+    {\r
+      anim.Stop();\r
+    }\r
+\r
+    mBackgroundAnimsPlaying = false;\r
+  }\r
+  return false;\r
+}\r
+\r
+void BubbleAnimator::PlayAnimation()\r
+{\r
+  if(!mBackgroundAnimsPlaying)\r
+  {\r
+    for(auto&& anim : mBackgroundAnimations)\r
+    {\r
+      anim.Play();\r
+    }\r
+\r
+    mBackgroundAnimsPlaying = true;\r
+  }\r
+\r
+  mAnimationTimer.SetInterval(BACKGROUND_ANIMATION_DURATION);\r
+}\r
+void BubbleAnimator::InitializeBackgroundActors(Dali::Actor actor)\r
+{\r
+  // Delete current animations\r
+  mBackgroundAnimations.clear();\r
+\r
+  // Create new animations\r
+  const Vector3 size = actor.GetTargetSize();\r
+\r
+  for(unsigned int i = 0, childCount = actor.GetChildCount(); i < childCount; ++i)\r
+  {\r
+    Actor child = actor.GetChildAt(i);\r
+\r
+    // Calculate a random position\r
+    Vector3 childPos(Random::Range(-size.x * 0.5f * BACKGROUND_SPREAD_SCALE, size.x * 0.85f * BACKGROUND_SPREAD_SCALE),\r
+                     Random::Range(-size.y, size.y),\r
+                     Random::Range(BUBBLE_MIN_Z, BUBBLE_MAX_Z));\r
+\r
+    child.SetProperty(Actor::Property::POSITION, childPos);\r
+\r
+    // Define bubble horizontal parallax and vertical wrapping\r
+    Actor scrollView = mScrollView.GetHandle();\r
+    if( scrollView )\r
+    {\r
+      Constraint animConstraint = Constraint::New<Vector3>(child, Actor::Property::POSITION, AnimateBubbleConstraint(childPos, Random::Range(-0.85f, 0.25f)));\r
+      animConstraint.AddSource(Source(scrollView, ScrollView::Property::SCROLL_POSITION));\r
+      animConstraint.AddSource(Dali::ParentSource(Dali::Actor::Property::SIZE));\r
+      animConstraint.AddSource(Dali::LocalSource(Dali::Actor::Property::SIZE));\r
+      animConstraint.SetRemoveAction(Constraint::DISCARD);\r
+      animConstraint.Apply();\r
+    }\r
+\r
+    // Kickoff animation\r
+    Animation animation = Animation::New(Random::Range(30.0f, 160.0f));\r
+    animation.AnimateBy(Property(child, Actor::Property::POSITION), Vector3(0.0f, -2000.0f, 0.0f), AlphaFunction::LINEAR);\r
+    animation.SetLooping(true);\r
+    animation.Play();\r
+    mBackgroundAnimations.push_back(animation);\r
+  }\r
+\r
+}\r
+\r
+void BubbleAnimator::AddBackgroundActors(Actor layer, int count)\r
+{\r
+  for(int i = 0; i < count; ++i)\r
+  {\r
+    float randSize  = Random::Range(10.0f, 400.0f);\r
+    int   shapeType = static_cast<int>(Random::Range(0.0f, NUMBER_OF_SHAPE_IMAGES - 1) + 0.5f);\r
+\r
+    ImageView dfActor = ImageView::New();\r
+    dfActor.SetProperty(Actor::Property::SIZE, Vector2(randSize, randSize));\r
+    dfActor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);\r
+\r
+    // Set the Image URL and the custom shader at the same time\r
+    Dali::Property::Map effect = Toolkit::CreateDistanceFieldEffect();\r
+    Property::Map       imageMap;\r
+    imageMap.Add(ImageVisual::Property::URL, SHAPE_IMAGE_TABLE[shapeType]);\r
+    imageMap.Add(Toolkit::Visual::Property::SHADER, effect);\r
+    dfActor.SetProperty(Toolkit::ImageView::Property::IMAGE, imageMap);\r
+\r
+    dfActor.SetStyleName(BUBBLE_COLOR_STYLE_NAME[i % NUMBER_OF_BUBBLE_COLORS]);\r
+\r
+    layer.Add(dfActor);\r
+  }\r
+\r
+  // Positioning will occur when the layer is relaid out\r
+  layer.OnRelayoutSignal().Connect(this, &BubbleAnimator::InitializeBackgroundActors);\r
+}\r
diff --git a/shared/bubble-animator.h b/shared/bubble-animator.h
new file mode 100644 (file)
index 0000000..f8f6ce9
--- /dev/null
@@ -0,0 +1,83 @@
+#ifndef DALI_DEMO_BUBBLE_ANIMATOR_H\r
+#define DALI_DEMO_BUBBLE_ANIMATOR_H\r
+\r
+/*\r
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd.\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ *\r
+ */\r
+\r
+// EXTERNAL INCLUDES\r
+#include <vector>\r
+#include <dali/public-api/actors/actor.h>\r
+#include <dali/public-api/adaptor-framework/timer.h>\r
+#include <dali/public-api/animation/animation.h>\r
+#include <dali/public-api/object/weak-handle.h>\r
+#include <dali/public-api/signals/connection-tracker.h>\r
+\r
+/**\r
+ * Creates and animates random sized bubbles\r
+ */\r
+class BubbleAnimator : public Dali::ConnectionTracker\r
+{\r
+public:\r
+\r
+  /**\r
+   * @brief Initilizes the bubble background\r
+   *\r
+   * @param parent The actor to add all the bubbles to\r
+   * @param scrollView If provided, does a parallax effect when scrolling using this scroll-view (optional)\r
+   */\r
+  void Initialize(Dali::Actor parent, Dali::Actor scrollView = Dali::Actor());\r
+\r
+  /**\r
+   * @brief Plays the bubble animation\r
+   */\r
+  void PlayAnimation();\r
+\r
+private:\r
+\r
+  /**\r
+   * @brief Used by the timer to pause the animation\r
+   *\r
+   * @return Returns false to cancel the timer\r
+   */\r
+  bool PauseAnimation();\r
+\r
+  /**\r
+   * @brief Initializes the background actors\r
+   *\r
+   * @param actor Actor which contains all the children\r
+   */\r
+  void InitializeBackgroundActors(Dali::Actor actor);\r
+\r
+  /**\r
+   * Create background actors for the given layer\r
+   *\r
+   * @param[in] layer The layer to add the actors to\r
+   * @param[in] count The number of actors to generate\r
+   */\r
+  void AddBackgroundActors(Dali::Actor layer, int count);\r
+\r
+private:\r
+\r
+  using AnimationList = std::vector<Dali::Animation>;\r
+\r
+  Dali::WeakHandle<Dali::Actor> mScrollView; ///< Weak handle to the scroll view used to apply a parallax effect when scrolling.\r
+  AnimationList mBackgroundAnimations; ///< List of background bubble animations.\r
+  Dali::Timer mAnimationTimer;   ///< Timer used to turn off animation after a specific time period.\r
+  bool mBackgroundAnimsPlaying{false}; ///< Are background animations playing.\r
+};\r
+\r
+#endif // DALI_DEMO_BUBBLE_ANIMATOR_H\r
index 9bd1c3b..d45e345 100755 (executable)
@@ -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::WindowOrientation::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<std::string>(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<Vector3>(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<int>(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);
-  }
-}
index 44a81dd..d4fee68 100644 (file)
  *
  */
 
+// EXTERNAL INCLUDES
 #include <dali-toolkit/dali-toolkit.h>
 #include <dali-toolkit/devel-api/controls/popup/popup.h>
 #include <dali/dali.h>
 
-class Example;
-
-typedef std::vector<Example>        ExampleList;
-typedef ExampleList::iterator       ExampleListIter;
-typedef ExampleList::const_iterator ExampleListConstIter;
-
-typedef std::vector<Dali::Animation>  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<Dali::Actor> 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 (file)
index 0000000..978e849
--- /dev/null
@@ -0,0 +1,55 @@
+#ifndef DALI_DEMO_EXAMPLE_H\r
+#define DALI_DEMO_EXAMPLE_H\r
+\r
+/*\r
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd.\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ *\r
+ */\r
+\r
+// EXTERNAL INCLUDES\r
+#include <string>\r
+#include <vector>\r
+\r
+/**\r
+ * Example information\r
+ *\r
+ * Represents a single Example.\r
+ */\r
+struct Example\r
+{\r
+  // Constructors\r
+\r
+  /**\r
+   * @param[in] name unique name of example\r
+   * @param[in] title The caption for the example to appear on a tile button.\r
+   */\r
+  Example(std::string name, std::string title)\r
+  : name(name),\r
+    title(title)\r
+  {\r
+  }\r
+\r
+  ~Example() = default;\r
+\r
+  // Data\r
+\r
+  std::string name;  ///< unique name of example\r
+  std::string title; ///< title (caption) of example to appear on tile button.\r
+};\r
+\r
+using ExampleList = std::vector<Example>;\r
+using ExampleListConstIter = ExampleList::const_iterator;\r
+\r
+#endif // DALI_DEMO_SHARED_EXAMPLE_H\r