summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--build/tizen/examples/Makefile.am6
-rw-r--r--com.samsung.dali-demo.xml3
-rw-r--r--demo/dali-demo.cpp3
-rw-r--r--demo/images/icon-scroll-view-carousel.pngbin0 -> 1496 bytes
-rw-r--r--demo/images/icon-scroll-view-depth.pngbin0 -> 1965 bytes
-rw-r--r--demo/images/icon-scroll-view-inner-cube.pngbin0 -> 1991 bytes
-rw-r--r--demo/images/icon-scroll-view-normal.pngbin0 -> 1507 bytes
-rw-r--r--demo/images/icon-scroll-view-outer-cube.pngbin0 -> 2126 bytes
-rw-r--r--demo/images/icon-scroll-view-spiral.pngbin0 -> 1867 bytes
-rw-r--r--examples/scroll-view/scroll-view-example.cpp798
10 files changed, 809 insertions, 1 deletions
diff --git a/build/tizen/examples/Makefile.am b/build/tizen/examples/Makefile.am
index 6ebc93b2..8e48fd3d 100644
--- a/build/tizen/examples/Makefile.am
+++ b/build/tizen/examples/Makefile.am
@@ -28,6 +28,7 @@ bin_PROGRAMS = \
motion-blur.example \
motion-stretch.example \
page-turn-view.example \
+ scroll-view.example \
shadow-bone-lighting.example
daliimagedir = $(appdatadir)/images/
@@ -108,6 +109,11 @@ page_turn_view_example_CXXFLAGS = $(EXAMPLE_CXXFLAGS)
page_turn_view_example_DEPENDENCIES = $(EXAMPLE_DEPS)
page_turn_view_example_LDADD = $(EXAMPLE_LDADD)
+scroll_view_example_SOURCES = $(examples_src_dir)/scroll-view/scroll-view-example.cpp
+scroll_view_example_CXXFLAGS = $(EXAMPLE_CXXFLAGS)
+scroll_view_example_DEPENDENCIES = $(EXAMPLE_DEPS)
+scroll_view_example_LDADD = $(EXAMPLE_LDADD)
+
shadow_bone_lighting_example_SOURCES = $(examples_src_dir)/shadows/shadow-bone-lighting-example.cpp
shadow_bone_lighting_example_CXXFLAGS = $(EXAMPLE_CXXFLAGS)
shadow_bone_lighting_example_DEPENDENCIES = $(EXAMPLE_DEPS)
diff --git a/com.samsung.dali-demo.xml b/com.samsung.dali-demo.xml
index 13e34de5..c53e728c 100644
--- a/com.samsung.dali-demo.xml
+++ b/com.samsung.dali-demo.xml
@@ -43,6 +43,9 @@
<ui-application appid="motion-stretch.example" exec="/opt/apps/com.samsung.dali-demo/bin/motion-stretch.example" nodisplay="true" multiple="false" type="c++app" taskmanage="true">
<label>Motion Stretch</label>
</ui-application>
+ <ui-application appid="scroll-view.example" exec="/opt/apps/com.samsung.dali-demo/bin/scroll-view.example" nodisplay="true" multiple="false" type="c++app" taskmanage="true">
+ <label>Scroll View</label>
+ </ui-application>
<ui-application appid="shadow-bone-lighting.example" exec="/opt/apps/com.samsung.dali-demo/bin/shadow-bone-lighting.example" nodisplay="true" multiple="false" type="c++app" taskmanage="true">
<label>Shadows and Lights</label>
</ui-application>
diff --git a/demo/dali-demo.cpp b/demo/dali-demo.cpp
index 1ce4085c..9194f65a 100644
--- a/demo/dali-demo.cpp
+++ b/demo/dali-demo.cpp
@@ -24,6 +24,7 @@ int main(int argc, char **argv)
DaliTableView demo(app);
+ demo.AddExample(Example("bubble-effect.example", "Bubbles"));
demo.AddExample(Example("blocks.example", "Blocks"));
demo.AddExample(Example("cluster.example", "Cluster control"));
demo.AddExample(Example("cube-transition-effect.example", "Cube Transition"));
@@ -33,8 +34,8 @@ int main(int argc, char **argv)
demo.AddExample(Example("motion-blur.example", "Motion Blur"));
demo.AddExample(Example("motion-stretch.example", "Motion Stretch"));
demo.AddExample(Example("page-turn-view.example", "Page Turn View"));
+ demo.AddExample(Example("scroll-view.example", "Scroll View"));
demo.AddExample(Example("shadow-bone-lighting.example", "Lights and shadows"));
- demo.AddExample(Example("hello-world.example", "Hello World"));
app.MainLoop();
return 0;
diff --git a/demo/images/icon-scroll-view-carousel.png b/demo/images/icon-scroll-view-carousel.png
new file mode 100644
index 00000000..04c6c1fc
--- /dev/null
+++ b/demo/images/icon-scroll-view-carousel.png
Binary files differ
diff --git a/demo/images/icon-scroll-view-depth.png b/demo/images/icon-scroll-view-depth.png
new file mode 100644
index 00000000..a967dd6a
--- /dev/null
+++ b/demo/images/icon-scroll-view-depth.png
Binary files differ
diff --git a/demo/images/icon-scroll-view-inner-cube.png b/demo/images/icon-scroll-view-inner-cube.png
new file mode 100644
index 00000000..0ea192fc
--- /dev/null
+++ b/demo/images/icon-scroll-view-inner-cube.png
Binary files differ
diff --git a/demo/images/icon-scroll-view-normal.png b/demo/images/icon-scroll-view-normal.png
new file mode 100644
index 00000000..d72b93dc
--- /dev/null
+++ b/demo/images/icon-scroll-view-normal.png
Binary files differ
diff --git a/demo/images/icon-scroll-view-outer-cube.png b/demo/images/icon-scroll-view-outer-cube.png
new file mode 100644
index 00000000..2f68e531
--- /dev/null
+++ b/demo/images/icon-scroll-view-outer-cube.png
Binary files differ
diff --git a/demo/images/icon-scroll-view-spiral.png b/demo/images/icon-scroll-view-spiral.png
new file mode 100644
index 00000000..4fe3c67f
--- /dev/null
+++ b/demo/images/icon-scroll-view-spiral.png
Binary files differ
diff --git a/examples/scroll-view/scroll-view-example.cpp b/examples/scroll-view/scroll-view-example.cpp
new file mode 100644
index 00000000..c32eaa06
--- /dev/null
+++ b/examples/scroll-view/scroll-view-example.cpp
@@ -0,0 +1,798 @@
+//
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Flora License, Version 1.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://floralicense.org/license/
+//
+// 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 <sstream>
+
+// INTERNAL INCLUDES
+#include "../shared/view.h"
+#include <dali/dali.h>
+#include <dali-toolkit/dali-toolkit.h>
+
+using namespace std;
+using namespace Dali;
+using namespace Dali::Toolkit;
+
+namespace
+{
+const char * const BACKGROUND_IMAGE( DALI_IMAGE_DIR "background-default.png" );
+const char * const TOOLBAR_IMAGE( DALI_IMAGE_DIR "top-bar.png" );
+const char * const APPLICATION_TITLE( "ScrollView" );
+const char * const EFFECT_NORMAL_IMAGE( DALI_IMAGE_DIR "icon-scroll-view-normal.png" );
+const char * const EFFECT_OUTER_CUBE_IMAGE( DALI_IMAGE_DIR "icon-scroll-view-outer-cube.png" );
+const char * const EFFECT_DEPTH_IMAGE( DALI_IMAGE_DIR "icon-scroll-view-depth.png" );
+const char * const EFFECT_INNER_CUBE_IMAGE( DALI_IMAGE_DIR "icon-scroll-view-inner-cube.png" );
+const char * const EFFECT_CAROUSEL_IMAGE( DALI_IMAGE_DIR "icon-scroll-view-carousel.png" );
+const char * const EFFECT_SPIRAL_IMAGE( DALI_IMAGE_DIR "icon-scroll-view-spiral.png" );
+
+const Vector3 ICON_SIZE(100.0f, 100.0f, 0.0f);
+
+const char* EFFECT_MODE_NAME[] = { "Normal",
+ "OuterCube",
+ "Depth",
+ "InnerCube",
+ "Carousel",
+ "Spiral",
+ };
+
+const char* PEOPLE_IMAGE_PATHS[] = { DALI_IMAGE_DIR "people-medium-1.jpg",
+ DALI_IMAGE_DIR "people-medium-2.jpg",
+ DALI_IMAGE_DIR "people-medium-3.jpg",
+ DALI_IMAGE_DIR "people-medium-4.jpg",
+ DALI_IMAGE_DIR "people-medium-5.jpg",
+ DALI_IMAGE_DIR "people-medium-6.jpg",
+ DALI_IMAGE_DIR "people-medium-7.jpg",
+ DALI_IMAGE_DIR "people-medium-8.jpg",
+ NULL};
+
+const char* TODAY_IMAGE_PATHS[] = { DALI_IMAGE_DIR "gallery-medium-1.jpg",
+ DALI_IMAGE_DIR "gallery-medium-2.jpg",
+ DALI_IMAGE_DIR "gallery-medium-3.jpg",
+ DALI_IMAGE_DIR "gallery-medium-4.jpg",
+ DALI_IMAGE_DIR "gallery-medium-5.jpg",
+ NULL};
+
+const char* PHONE_IMAGE_PATHS[] = { DALI_IMAGE_DIR "gallery-medium-5.jpg",
+ DALI_IMAGE_DIR "gallery-medium-6.jpg",
+ DALI_IMAGE_DIR "gallery-medium-7.jpg",
+ DALI_IMAGE_DIR "gallery-medium-8.jpg",
+ DALI_IMAGE_DIR "gallery-medium-9.jpg",
+ NULL};
+
+const char* PICTURES_IMAGE_PATHS[] = { DALI_IMAGE_DIR "gallery-medium-10.jpg",
+ DALI_IMAGE_DIR "gallery-medium-11.jpg",
+ DALI_IMAGE_DIR "gallery-medium-12.jpg",
+ DALI_IMAGE_DIR "gallery-medium-13.jpg",
+ DALI_IMAGE_DIR "gallery-medium-14.jpg",
+ NULL};
+
+const char* MUSIC_IMAGE_PATHS[] = { DALI_IMAGE_DIR "gallery-medium-15.jpg",
+ DALI_IMAGE_DIR "gallery-medium-16.jpg",
+ DALI_IMAGE_DIR "gallery-medium-17.jpg",
+ DALI_IMAGE_DIR "gallery-medium-18.jpg",
+ DALI_IMAGE_DIR "gallery-medium-19.jpg",
+ DALI_IMAGE_DIR "gallery-medium-20.jpg",
+ NULL};
+
+const char* MAGAZINE_IMAGE_PATHS[] = { DALI_IMAGE_DIR "gallery-medium-21.jpg",
+ DALI_IMAGE_DIR "gallery-medium-22.jpg",
+ DALI_IMAGE_DIR "gallery-medium-23.jpg",
+ DALI_IMAGE_DIR "gallery-medium-24.jpg",
+ DALI_IMAGE_DIR "gallery-medium-25.jpg",
+ DALI_IMAGE_DIR "gallery-medium-26.jpg",
+ NULL};
+
+const char **IMAGE_GROUPS[] = {PEOPLE_IMAGE_PATHS,
+ TODAY_IMAGE_PATHS,
+ PHONE_IMAGE_PATHS,
+ PICTURES_IMAGE_PATHS,
+ MUSIC_IMAGE_PATHS,
+ MAGAZINE_IMAGE_PATHS,
+ NULL};
+
+const int PAGE_COLUMNS = 10; ///< Number of Pages going across (columns)
+const int PAGE_ROWS = 1; ///< Number of Pages going down (rows)
+const int IMAGE_COLUMNS = 3; ///< Number of Images going across (columns) within a Page
+const int IMAGE_ROWS = 5; ///< Number of Images going down (rows) with a Page
+
+// 3D Effect constants
+const Vector3 ANGLE_CUBE_PAGE_ROTATE(Math::PI * 0.2f, Math::PI * 0.2f, 0.0f); ///< Cube page rotates as if it has ten sides with the camera positioned inside
+const Vector2 ANGLE_CUSTOM_CUBE_SWING(-Math::PI * 0.45f, -Math::PI * 0.45f); ///< outer cube pages swing 90 degrees as they pan offscreen
+const Vector2 ANGLE_SPIRAL_SWING_IN(Math::PI * 0.45f, Math::PI * 0.45f);
+const Vector2 ANGLE_SPIRAL_SWING_OUT(Math::PI * 0.3f, Math::PI * 0.3f);
+
+// Depth Effect constants
+const Vector2 POSITION_EXTENT_DEPTH_EFFECT(0.5f, 2.5f); ///< Extent of X & Y position to alter function exponent.
+const Vector2 OFFSET_EXTENT_DEPTH_EFFECT(1.0f, 1.0f); ///< Function exponent offset constant.
+const float POSITION_SCALE_DEPTH_EFFECT(1.5f); ///< Position scaling.
+const float SCALE_EXTENT_DEPTH_EFFECT(0.5f); ///< Maximum scale factor when Actors scrolled one page away (50% size)
+
+const unsigned int IMAGE_THUMBNAIL_WIDTH = 256; ///< Width of Thumbnail Image in texels
+const unsigned int IMAGE_THUMBNAIL_HEIGHT = 256; ///< Height of Thumbnail Image in texels
+
+const float SPIN_DURATION = 5.0f; ///< Times to spin an Image by upon touching, each spin taking a second.
+
+const float EFFECT_SNAP_DURATION(0.66f); ///< Scroll Snap Duration for Effects
+const float EFFECT_FLICK_DURATION(0.5f); ///< Scroll Flick Duration for Effects
+
+/**
+ * WrapActorOffsetedConstraint
+ * Wraps an Actor's position based on its position
+ * within a scroll domain taking into account its
+ * size, anchor point, and an offset.
+ */
+struct WrapActorOffsetedConstraint
+{
+ WrapActorOffsetedConstraint(Vector2 offset)
+ : mOffset(offset)
+ {
+ }
+
+ Vector3 operator()(const Vector3& current,
+ const PropertyInput& actorScaleProperty,
+ const PropertyInput& actorAnchorPointProperty,
+ const PropertyInput& actorSizeProperty,
+ const PropertyInput& scrollPositionMin,
+ const PropertyInput& scrollPositionMax,
+ const PropertyInput& scrollWrap)
+ {
+ Vector3 position = current;
+ bool wrap = scrollWrap.GetBoolean();
+
+ if(wrap)
+ {
+ Vector3 min = scrollPositionMin.GetVector3();
+ Vector3 max = scrollPositionMax.GetVector3();
+
+ Vector3 anchor = actorAnchorPointProperty.GetVector3();
+ Vector3 scale = actorScaleProperty.GetVector3();
+ Vector3 size = actorSizeProperty.GetVector3();
+
+ if(fabsf(min.x - max.x) > Math::MACHINE_EPSILON_1)
+ {
+ // WRAP X (based on the position of the right side)
+ float offsetX = (1.0f - anchor.x) * size.x * scale.x;
+ offsetX += mOffset.x;
+ position.x = WrapInDomain(position.x + offsetX, min.x, max.x) - offsetX;
+ }
+
+ if(fabsf(min.y - max.y) > Math::MACHINE_EPSILON_1)
+ {
+ // WRAP Y (based on the position of the bottom side)
+ float offsetY = (1.0f - anchor.y) * size.y * scale.y;
+ offsetY += mOffset.y;
+ position.y = WrapInDomain(position.y + offsetY, min.y, max.y) - offsetY;
+ }
+ }
+
+ return position;
+ }
+
+private:
+
+ const Vector2 mOffset;
+
+};
+
+
+} // unnamed namespace
+
+/**
+ * This example shows how to do custom Scroll Effects
+ */
+class ExampleController : public ConnectionTracker
+{
+public:
+
+ /**
+ * Constructor
+ * @param application class, stored as reference
+ */
+ ExampleController( Application& application )
+ : mApplication( application ),
+ mView(),
+ mScrolling(false),
+ mEffectMode(CarouselEffect)
+ {
+ // Connect to the Application's Init and orientation changed signal
+ mApplication.InitSignal().Connect(this, &ExampleController::OnInit);
+ }
+
+ ~ExampleController()
+ {
+ // Nothing to do here; everything gets deleted automatically
+ }
+
+ /**
+ * This method gets called once the main loop of application is up and running
+ */
+ void OnInit(Application& app)
+ {
+ Stage::GetCurrent().KeyEventSignal().Connect(this, &ExampleController::OnKeyEvent);
+
+ // Hide the indicator bar
+ mApplication.GetWindow().ShowIndicator(false);
+
+ // Creates a default view with a default tool bar.
+ // The view is added to the stage.
+
+ mContentLayer = DemoHelper::CreateView( app,
+ mView,
+ mToolBar,
+ BACKGROUND_IMAGE,
+ TOOLBAR_IMAGE,
+ "" );
+
+ mEffectIcon[ Normal ] = Image::New( EFFECT_NORMAL_IMAGE );
+ mEffectIcon[ OuterCubeEffect ] = Image::New( EFFECT_OUTER_CUBE_IMAGE );
+ mEffectIcon[ DepthEffect ] = Image::New( EFFECT_DEPTH_IMAGE );
+ mEffectIcon[ InnerCubeEffect ] = Image::New( EFFECT_INNER_CUBE_IMAGE );
+ mEffectIcon[ CarouselEffect ] = Image::New( EFFECT_CAROUSEL_IMAGE );
+ mEffectIcon[ SpiralEffect ] = Image::New( EFFECT_SPIRAL_IMAGE );
+
+ // Create a effect change button. (right of toolbar)
+ mEffectChangeButton = Toolkit::PushButton::New();
+ mEffectChangeButton.ClickedSignal().Connect( this, &ExampleController::OnEffectTouched );
+ mToolBar.AddControl( mEffectChangeButton, DemoHelper::DEFAULT_VIEW_STYLE.mToolBarButtonPercentage, Toolkit::Alignment::HorizontalRight, DemoHelper::DEFAULT_MODE_SWITCH_PADDING );
+
+ // Create the content layer.
+ AddContentLayer();
+
+ // Hack to force screen refresh.
+ Animation animation = Animation::New(1.0f);
+ animation.AnimateTo(Property(mContentLayer, Actor::POSITION), Vector3::ZERO );
+ animation.Play();
+ }
+
+private:
+
+ /**
+ * Adds content to the ContentLayer. This is everything we see
+ * excluding the toolbar at the top.
+ */
+ void AddContentLayer()
+ {
+ Stage stage = Stage::GetCurrent();
+ Vector2 stageSize = stage.GetSize();
+
+ mScrollView = ScrollView::New();
+ mScrollView.SetAnchorPoint(AnchorPoint::CENTER);
+ mScrollView.SetParentOrigin(ParentOrigin::CENTER);
+ mContentLayer.Add( mScrollView );
+ mScrollView.SetSize( stageSize );
+ mScrollView.SetAxisAutoLock( true );
+ mScrollView.SetAxisAutoLockGradient( 1.0f );
+
+ mScrollView.ScrollStartedSignal().Connect( this, &ExampleController::OnScrollStarted );
+ mScrollView.ScrollCompletedSignal().Connect( this, &ExampleController::OnScrollCompleted );
+
+ int groupIndex = 0;
+ for(int row = 0;row<PAGE_ROWS;row++)
+ {
+ for(int column = 0;column<PAGE_COLUMNS;column++)
+ {
+ Actor page = CreatePage(IMAGE_GROUPS[groupIndex]);
+
+ page.SetPosition( column * stageSize.x, row * stageSize.y );
+ mScrollView.Add( page );
+
+ groupIndex++;
+ if(!IMAGE_GROUPS[groupIndex])
+ {
+ groupIndex = 0;
+ }
+
+ mPages.push_back(page);
+ }
+ }
+
+ Update();
+ }
+
+ /**
+ * Updates the ScrollView and it's children based
+ * on the current effect.
+ */
+ void Update()
+ {
+ std::stringstream ss(APPLICATION_TITLE);
+ ss << APPLICATION_TITLE << ": " << EFFECT_MODE_NAME[mEffectMode];
+ SetTitle(ss.str());
+
+ mEffectChangeButton.SetBackgroundImage( mEffectIcon[ mEffectMode ] );
+
+ // remove old Effect if exists.
+ if(mScrollViewEffect)
+ {
+ mScrollView.RemoveEffect(mScrollViewEffect);
+ }
+
+ // apply new Effect to ScrollView
+ ApplyEffectToScrollView();
+
+ for(ActorIter pageIter = mPages.begin(); pageIter != mPages.end(); ++pageIter)
+ {
+ Actor page = *pageIter;
+ ApplyEffectToPage( page );
+
+ unsigned int numChildren = (*pageIter).GetChildCount();
+ for(unsigned int i=0; i<numChildren; ++i)
+ {
+ Actor image = (*pageIter).GetChildAt(i);
+
+ // Remove old effect's manual constraints.
+ image.RemoveConstraints();
+
+ // Apply new effect's manual constraints.
+ ApplyEffectToActor( image, page, (rand()&1) );
+ }
+ }
+ }
+
+ /**
+ * Creates a page using a source of images.
+ * @param[in] paths pointer to Null-terminated array of Null-terminated strings.
+ */
+ Actor CreatePage(const char **paths)
+ {
+ int pathIndex = 0;
+ Actor page = Actor::New();
+ page.ApplyConstraint( Constraint::New<Vector3>( Actor::SIZE, ParentSource( Actor::SIZE ), EqualToConstraint() ) );
+ page.SetParentOrigin( ParentOrigin::CENTER );
+ page.SetAnchorPoint( AnchorPoint::CENTER );
+
+ Stage stage = Stage::GetCurrent();
+ Vector2 stageSize = stage.GetSize();
+
+ const float margin = 10.0f;
+
+ const Vector3 imageSize((stageSize.x / IMAGE_COLUMNS) - margin, (stageSize.y / IMAGE_ROWS) - margin, 0.0f);
+
+ for(int row = 0;row<IMAGE_ROWS;row++)
+ {
+ for(int column = 0;column<IMAGE_COLUMNS;column++)
+ {
+ ImageActor image = CreateImage(paths[pathIndex]);
+
+ image.SetParentOrigin( ParentOrigin::CENTER );
+ image.SetAnchorPoint( AnchorPoint::CENTER );
+
+ Vector3 position( margin * 0.5f + (imageSize.x + margin) * column - stageSize.width * 0.5f,
+ margin * 0.5f + (imageSize.y + margin) * row - stageSize.height * 0.5f,
+ 0.0f);
+ image.SetPosition( position + imageSize * 0.5f );
+ image.SetSize( imageSize );
+ page.Add(image);
+
+ pathIndex++;
+ if(!paths[pathIndex])
+ {
+ pathIndex = 0;
+ }
+ }
+ }
+
+ return page;
+ }
+
+ /**
+ * [ScrollView]
+ * Applies effect to scrollView
+ */
+ void ApplyEffectToScrollView()
+ {
+ bool wrap(true);
+ bool snap(true);
+
+ Stage stage = Stage::GetCurrent();
+ Vector2 stageSize = stage.GetSize();
+
+ switch(mEffectMode)
+ {
+ case Normal:
+ {
+ SetupNormalPageEffect();
+ break;
+ }
+
+ case OuterCubeEffect:
+ {
+ SetupOuterPageCubeEffect();
+ break;
+ }
+
+ case DepthEffect:
+ {
+ mScrollViewEffect = ScrollViewDepthEffect::New();
+ mScrollView.SetScrollSnapDuration(EFFECT_SNAP_DURATION);
+ mScrollView.SetScrollFlickDuration(EFFECT_FLICK_DURATION);
+ mScrollView.SetScrollSnapAlphaFunction(AlphaFunctions::EaseOut);
+ mScrollView.SetScrollFlickAlphaFunction(AlphaFunctions::EaseOut);
+ mScrollView.RemoveConstraintsFromChildren();
+ break;
+ }
+
+ case InnerCubeEffect:
+ {
+ SetupInnerPageCubeEffect();
+ break;
+ }
+
+ case CarouselEffect:
+ {
+ SetupCarouselPageEffect();
+ break;
+ }
+
+ case SpiralEffect:
+ {
+ SetupSpiralPageEffect();
+ break;
+ }
+
+ default:
+ {
+ break;
+ }
+ } // end switch
+
+ if(mScrollViewEffect)
+ {
+ mScrollView.ApplyEffect(mScrollViewEffect);
+ }
+
+ mScrollView.SetWrapMode(wrap);
+
+ RulerPtr rulerX = CreateRuler(snap ? stageSize.width : 0.0f);
+ RulerPtr rulerY = new DefaultRuler;
+ rulerX->SetDomain(RulerDomain(0.0f, stageSize.x * PAGE_COLUMNS, !wrap));
+ rulerY->Disable();
+
+ mScrollView.SetRulerX( rulerX );
+ mScrollView.SetRulerY( rulerY );
+ }
+
+ /**
+ * Creates a Ruler that snaps to a specified grid size.
+ * If that grid size is 0.0 then this ruler does not
+ * snap.
+ *
+ * @param[in] gridSize (optional) The grid size for the ruler,
+ * (Default = 0.0 i.e. no snapping)
+ * @return The ruler is returned.
+ */
+ RulerPtr CreateRuler(float gridSize = 0.0f)
+ {
+ if(gridSize <= Math::MACHINE_EPSILON_0)
+ {
+ return new DefaultRuler();
+ }
+ return new FixedRuler(gridSize);
+ }
+
+ void SetupNormalPageEffect()
+ {
+ mScrollViewEffect.Reset();
+ mScrollView.SetScrollSnapDuration(ScrollView::DEFAULT_SLOW_SNAP_ANIMATION_DURATION);
+ mScrollView.SetScrollFlickDuration(ScrollView::DEFAULT_FAST_SNAP_ANIMATION_DURATION);
+ mScrollView.SetScrollSnapAlphaFunction(AlphaFunctions::EaseOut);
+ mScrollView.SetScrollFlickAlphaFunction(AlphaFunctions::EaseOut);
+ mScrollView.RemoveConstraintsFromChildren();
+ }
+
+ void SetupInnerPageCubeEffect()
+ {
+ ScrollViewCustomEffect customEffect;
+ mScrollViewEffect = customEffect = ScrollViewCustomEffect::New();
+ mScrollView.SetScrollSnapDuration(EFFECT_SNAP_DURATION);
+ mScrollView.SetScrollFlickDuration(EFFECT_FLICK_DURATION);
+ mScrollView.SetScrollSnapAlphaFunction(AlphaFunctions::EaseOutBack);
+ mScrollView.SetScrollFlickAlphaFunction(AlphaFunctions::EaseOutBack);
+ mScrollView.RemoveConstraintsFromChildren();
+
+ customEffect.SetPageSpacing(Vector2(30.0f, 30.0f));
+ customEffect.SetAngledOriginPageRotation(ANGLE_CUBE_PAGE_ROTATE);
+ customEffect.SetSwingAngle(ANGLE_CUBE_PAGE_ROTATE.x, Vector3(0,-1,0));
+ customEffect.SetOpacityThreshold(0.7f);
+ }
+
+ void SetupOuterPageCubeEffect()
+ {
+ ScrollViewCustomEffect customEffect;
+ mScrollViewEffect = customEffect = ScrollViewCustomEffect::New();
+ mScrollView.SetScrollSnapDuration(EFFECT_SNAP_DURATION);
+ mScrollView.SetScrollFlickDuration(EFFECT_FLICK_DURATION);
+ mScrollView.SetScrollSnapAlphaFunction(AlphaFunctions::EaseOut);
+ mScrollView.SetScrollFlickAlphaFunction(AlphaFunctions::EaseOut);
+ mScrollView.RemoveConstraintsFromChildren();
+
+ Vector2 pageSize = Stage::GetCurrent().GetSize();
+ customEffect.SetPageTranslation(Vector3(pageSize.x, pageSize.y, 0));
+ customEffect.SetSwingAngleOut(ANGLE_CUSTOM_CUBE_SWING.x, Vector3(0.0f, -1.0f, 0.0f));
+ customEffect.SetSwingAnchor(AnchorPoint::CENTER, AnchorPoint::CENTER_LEFT);
+ customEffect.SetOpacityThreshold(0.5f);
+ }
+
+ void SetupCarouselPageEffect()
+ {
+ ScrollViewCustomEffect customEffect;
+ mScrollViewEffect = customEffect = ScrollViewCustomEffect::New();
+ mScrollView.SetScrollSnapDuration(EFFECT_SNAP_DURATION);
+ mScrollView.SetScrollFlickDuration(EFFECT_FLICK_DURATION);
+ mScrollView.SetScrollSnapAlphaFunction(AlphaFunctions::EaseOutBack);
+ mScrollView.SetScrollFlickAlphaFunction(AlphaFunctions::EaseOutBack);
+ mScrollView.RemoveConstraintsFromChildren();
+
+ customEffect.SetPageTranslation(Vector3(0,0,0), Vector3(-30, 0, 0));
+ customEffect.SetPageSpacing(Vector2(60.0f, 60.0f));
+ customEffect.SetAngledOriginPageRotation(-ANGLE_CUBE_PAGE_ROTATE);
+ customEffect.SetOpacityThreshold(0.2f, 0.6f);
+ }
+
+ void SetupSpiralPageEffect()
+ {
+ ScrollViewCustomEffect customEffect;
+ mScrollViewEffect = customEffect = ScrollViewCustomEffect::New();
+ mScrollView.SetScrollSnapDuration(EFFECT_SNAP_DURATION);
+ mScrollView.SetScrollFlickDuration(EFFECT_FLICK_DURATION);
+ mScrollView.SetScrollSnapAlphaFunction(AlphaFunctions::EaseOutBack);
+ mScrollView.SetScrollFlickAlphaFunction(AlphaFunctions::EaseOutBack);
+ mScrollView.RemoveConstraintsFromChildren();
+
+ Vector2 pageSize = Stage::GetCurrent().GetSize();
+ customEffect.SetPageTranslation(Vector3(pageSize.x, pageSize.y, 0.0f));
+ customEffect.SetSwingAngle(-ANGLE_SPIRAL_SWING_IN.x, Vector3(0.0f, -1.0f, 0.0f), ANGLE_SPIRAL_SWING_OUT.x, Vector3(0.0f, -1.0f, 0.0f));
+ customEffect.SetSwingAnchor(AnchorPoint::CENTER_RIGHT);
+ customEffect.SetPageTranslation(Vector3(pageSize.x, pageSize.y, 0), Vector3(pageSize.x, pageSize.y, 0) * 0.5f);
+ customEffect.SetOpacityThreshold(0.66f);
+ }
+
+ /**
+ * [Page]
+ * Applies effect to the pages within scroll view.
+ *
+ * @param[in] page The page Actor to apply effect to.
+ */
+ void ApplyEffectToPage(Actor page)
+ {
+ page.RemoveConstraints();
+ page.ApplyConstraint( Constraint::New<Vector3>( Actor::SIZE, ParentSource( Actor::SIZE ), EqualToConstraint() ) );
+
+ if( mEffectMode == Normal )
+ {
+ Constraint constraint;
+
+ // MoveActor (scrolling)
+ constraint = Constraint::New<Vector3>( Actor::POSITION,
+ Source( mScrollView, mScrollView.GetPropertyIndex( ScrollView::SCROLL_POSITION_PROPERTY_NAME ) ),
+ MoveActorConstraint );
+ constraint.SetRemoveAction(Constraint::Discard);
+ page.ApplyConstraint(constraint);
+
+ // WrapActor (wrap functionality) - takes into account parent origin
+ constraint = Constraint::New<Vector3>( Actor::POSITION,
+ LocalSource( Actor::SCALE ),
+ LocalSource( Actor::ANCHOR_POINT ),
+ LocalSource( Actor::SIZE ),
+ Source( mScrollView, mScrollView.GetPropertyIndex( ScrollView::SCROLL_POSITION_MIN_PROPERTY_NAME ) ),
+ Source( mScrollView, mScrollView.GetPropertyIndex( ScrollView::SCROLL_POSITION_MAX_PROPERTY_NAME ) ),
+ Source( mScrollView, mScrollView.GetPropertyIndex( ScrollView::SCROLL_WRAP_PROPERTY_NAME ) ),
+ WrapActorOffsetedConstraint( Stage::GetCurrent().GetSize() * 0.5f ) );
+ constraint.SetRemoveAction(Constraint::Discard);
+ page.ApplyConstraint(constraint);
+ }
+ else if( ( mEffectMode == InnerCubeEffect ) ||
+ ( mEffectMode == OuterCubeEffect ) ||
+ ( mEffectMode == SpiralEffect ) ||
+ ( mEffectMode == CarouselEffect) )
+ {
+ ApplyCustomEffectToPage(page);
+ }
+ }
+
+ void ApplyCustomEffectToPage(Actor page)
+ {
+ ScrollViewCustomEffect customEffect = ScrollViewCustomEffect::DownCast(mScrollViewEffect);
+ Vector2 vStageSize(Stage::GetCurrent().GetSize());
+ customEffect.ApplyToPage(page, Vector3(vStageSize.x, vStageSize.y, 1.0f));
+ }
+
+ /**
+ * [Actor]
+ * Applies effect to child which resides in page (which in turn resides in scrollview)
+ *
+ * @note Page is typically the Parent of child, although in
+ * some scenarios Page is simply a container which has a child as
+ * a descendent.
+ *
+ * @param[in] child The child actor to apply effect to
+ * @param[in] page The page which this child is inside
+ * @param[in] style The style of effect either 0 or 1. (changes anchor point)
+ */
+ void ApplyEffectToActor(Actor child, Actor page, int style)
+ {
+ if( mEffectMode == DepthEffect )
+ {
+ ApplyDepthEffectToActor(child, style);
+ }
+ }
+
+ /**
+ * Applies depth effect to the child which resides in page (which in turn resides in scrollview)
+ *
+ * @param[in] child The child actor to apply depth effect to
+ * @param[in] style The style of effect either 0 or 1. (changes anchor point)
+ */
+ void ApplyDepthEffectToActor(Actor child, int style)
+ {
+ ScrollViewDepthEffect depthEffect = ScrollViewDepthEffect::DownCast(mScrollViewEffect);
+ depthEffect.ApplyToActor( child,
+ POSITION_EXTENT_DEPTH_EFFECT,
+ OFFSET_EXTENT_DEPTH_EFFECT,
+ POSITION_SCALE_DEPTH_EFFECT,
+ SCALE_EXTENT_DEPTH_EFFECT );
+ }
+
+ /**
+ * Creates an Image (Helper)
+ *
+ * @param[in] filename the path of the image.
+ * @param[in] width the width of the image in texels
+ * @param[in] height the height of the image in texels.
+ */
+ ImageActor CreateImage( const std::string& filename, unsigned int width = IMAGE_THUMBNAIL_WIDTH, unsigned int height = IMAGE_THUMBNAIL_HEIGHT )
+ {
+ ImageAttributes attributes;
+
+ attributes.SetSize(width, height);
+ attributes.SetScalingMode(ImageAttributes::ShrinkToFit);
+ Image img = Image::New(filename, attributes);
+ ImageActor actor = ImageActor::New(img);
+ actor.SetName( filename );
+ actor.SetParentOrigin(ParentOrigin::CENTER);
+ actor.SetAnchorPoint(AnchorPoint::CENTER);
+
+ actor.TouchedSignal().Connect( this, &ExampleController::OnTouchImage );
+ return actor;
+ }
+
+ /**
+ * When scroll starts (i.e. user starts to drag scrollview),
+ * note this state (mScrolling = true)
+ * @param[in] position Current Scroll Position
+ */
+ void OnScrollStarted( const Vector3& position )
+ {
+ mScrolling = true;
+ }
+
+ /**
+ * When scroll starts (i.e. user stops dragging scrollview, and scrollview has snapped to destination),
+ * note this state (mScrolling = false)
+ * @param[in] position Current Scroll Position
+ */
+ void OnScrollCompleted( const Vector3& position )
+ {
+ mScrolling = false;
+ }
+
+ /**
+ * Upon Touching an image (Release), make it spin
+ * (provided we're not scrolling).
+ * @param[in] actor The actor touched
+ * @param[in] event The TouchEvent.
+ */
+ bool OnTouchImage( Actor actor, const TouchEvent& event )
+ {
+ if( (event.points.size() > 0) && (!mScrolling) )
+ {
+ TouchPoint point = event.points[0];
+ if(point.state == TouchPoint::Up)
+ {
+ // Spin the Image a few times.
+ Animation animation = Animation::New(SPIN_DURATION);
+ animation.RotateBy( actor, Degree(360.0f * SPIN_DURATION), Vector3::XAXIS, AlphaFunctions::EaseOut);
+ animation.Play();
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Signal handler, called when the 'Effect' button has been touched.
+ *
+ * @param[in] button The button that was pressed.
+ */
+ bool OnEffectTouched(Button button)
+ {
+ mEffectMode = static_cast<EffectMode>((static_cast<int>(mEffectMode) + 1) % static_cast<int>(Total));
+ Update();
+ return true;
+ }
+
+ /**
+ * Sets/Updates the title of the View
+ * @param[in] title The new title for the view.
+ */
+ void SetTitle(const std::string& title)
+ {
+ if(!mTitleActor)
+ {
+ mTitleActor = TextView::New();
+ // Add title to the tool bar.
+ mToolBar.AddControl( mTitleActor, DemoHelper::DEFAULT_VIEW_STYLE.mToolBarTitlePercentage, Alignment::HorizontalCenter );
+ }
+
+ Font font = Font::New();
+ mTitleActor.SetText( title );
+ mTitleActor.SetSize( font.MeasureText( title ) );
+ mTitleActor.SetStyleToCurrentText(DemoHelper::GetDefaultTextStyle());
+ }
+
+ /**
+ * Main key event handler
+ */
+ void OnKeyEvent(const KeyEvent& event)
+ {
+ if(event.state == KeyEvent::Down)
+ {
+ if( IsKey( event, Dali::DALI_KEY_ESCAPE) || IsKey( event, Dali::DALI_KEY_BACK) )
+ {
+ mApplication.Quit();
+ }
+ }
+ }
+
+private:
+
+ Application& mApplication; ///< Application instance
+ Toolkit::View mView; ///< The View instance.
+ Toolkit::ToolBar mToolBar; ///< The View's Toolbar.
+ TextView mTitleActor; ///< The Toolbar's Title.
+ Layer mContentLayer; ///< The content layer (contains game actors)
+ ScrollView mScrollView; ///< ScrollView UI Component
+ bool mScrolling; ///< ScrollView scrolling state (true = scrolling, false = stationary)
+ ScrollViewEffect mScrollViewEffect; ///< ScrollView Effect instance.
+ ActorContainer mPages; ///< Keeps track of all the pages for applying effects.
+
+ /**
+ * Enumeration of different effects this scrollview can operate under.
+ */
+ enum EffectMode
+ {
+ Normal, ///< No Effect (Standard ScrollView)
+ OuterCubeEffect, ///< 3D Rotating Cube Effect
+ DepthEffect, ///< Depth Effect
+ InnerCubeEffect, ///< Page Cube Effect
+ CarouselEffect, ///< Page Carousel Effect
+ SpiralEffect, ///< Page Spiral Effect
+
+ Total,
+ };
+
+ EffectMode mEffectMode; ///< Current Effect mode
+
+ Image mEffectIcon[Total]; ///< Icons for the effect button
+ Toolkit::PushButton mEffectChangeButton; ///< Effect Change Button
+};
+
+int main(int argc, char **argv)
+{
+ Application app = Application::New(&argc, &argv);
+ ExampleController test(app);
+ app.MainLoop();
+ return 0;
+}