Add Orientational View
authorKrzysztof Wieclaw/IoT & UI Sample (PLT) /SRPOL/Engineer/Samsung Electronics <k.wieclaw@samsung.com>
Fri, 3 Sep 2021 13:33:53 +0000 (15:33 +0200)
committerKrzysztof Wieclaw/IoT & UI Sample (PLT) /SRPOL/Engineer/Samsung Electronics <k.wieclaw@samsung.com>
Fri, 3 Sep 2021 13:33:53 +0000 (15:33 +0200)
Change-Id: Ieeab61de4bbdca39183e6b2e74d702cb929ad159
Signed-off-by: Krzysztof Wieclaw/IoT & UI Sample (PLT) /SRPOL/Engineer/Samsung Electronics <k.wieclaw@samsung.com>
Oobe/Oobe.Welcome/WelcomeStep.cs
Oobe/Oobe/Managers/ProcessManager.cs
Oobe/Oobe/ScalableUI/Animation.cs [new file with mode: 0644]
Oobe/Oobe/ScalableUI/MarginalView.cs [new file with mode: 0644]
Oobe/Oobe/ScalableUI/OrientationalView.cs [new file with mode: 0644]
Oobe/Oobe/Views/MainView.cs

index 9a716024620f6e1934edc18db86e09ab9fec69b8..fbd10674a4cda398da1369de4d738d177f71e578 100644 (file)
@@ -1,21 +1,21 @@
-/*
- * 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.
- */
-
+/*\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
 using Oobe.Common.Interfaces;\r
-using Oobe.Common.Pages;
+using Oobe.Common.Pages;\r
 using Oobe.Common.Styles;\r
 using Tizen.NUI;\r
 using Tizen.NUI.BaseComponents;\r
@@ -41,12 +41,12 @@ namespace Oobe.Welcome
             content.Text = "There should be some description or information about Tizen IoT. There should be some description or information about Tizen IoT. There should be some description or information about Tizen IoT. There should be some description or information about Tizen IoT. There should be some description or information about Tizen IoT. There should be some description or information about Tizen IoT. There should be some description or information about Tizen IoT. There should be some description or information about Tizen IoT.";\r
 \r
             container.NextButton.TranslatableText = "GET_STARTED";\r
-            container.NextButton.Clicked += (obj, args) =>
+            container.NextButton.Clicked += (obj, args) =>\r
             {\r
                 nav.Finish();\r
             };\r
 \r
-            container.Content = content;
+            container.Content = content;\r
 \r
             return container;\r
         }\r
index 5a8f0e12004eb109e423bb1aa1731faa4a468b53..c26078e0294e85c065ce46d7901085313edc8ca3 100644 (file)
@@ -72,6 +72,7 @@ namespace Oobe
                 return;
             }
 
+
             ui = new MainView(Window.Instance);
             ui.PaginationVisible = true;
             ui.PagesCount = steps.Count - 1;
diff --git a/Oobe/Oobe/ScalableUI/Animation.cs b/Oobe/Oobe/ScalableUI/Animation.cs
new file mode 100644 (file)
index 0000000..82be799
--- /dev/null
@@ -0,0 +1,32 @@
+using System;
+using System.Threading.Tasks;
+using Tizen.NUI;
+using Tizen.NUI.BaseComponents;
+
+namespace ScalableUI
+{
+    public class Animation
+    {
+        public static Task AnimateTo(View view, string property, object value)
+        {
+            var taskSource = new TaskCompletionSource<object>();
+            var animation = new Tizen.NUI.Animation(200);
+
+            void Finished(object sender, EventArgs e)
+            {
+                animation.Finished -= Finished;
+                taskSource.SetResult(null);
+
+                animation.Dispose();
+                animation = null;
+            }
+
+            animation.DefaultAlphaFunction = new AlphaFunction(AlphaFunction.BuiltinFunctions.EaseInOut);
+            animation.AnimateTo(view, property, value);
+            animation.Finished += Finished;
+            animation.Play();
+
+            return taskSource.Task;
+        }
+    }
+}
diff --git a/Oobe/Oobe/ScalableUI/MarginalView.cs b/Oobe/Oobe/ScalableUI/MarginalView.cs
new file mode 100644 (file)
index 0000000..da2e7af
--- /dev/null
@@ -0,0 +1,73 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Tizen.NUI;
+using Tizen.NUI.BaseComponents;
+
+namespace ScalableUI
+{
+    public class MarginalView : View
+    {
+        private static Size MinBreakpointSize { get; } = new Size(1024, 720);
+        private static Size MaxBreakpointSize { get; } = new Size(4096, 2160);
+
+        private static Size WindowSize => Window.Instance.WindowSize;
+
+        private static bool IsLandscape => WindowSize.Width > WindowSize.Height;
+
+        private static List<float> GetBreakpoints(float min, float max, float margin)
+        {
+            var breakpoints = new List<float>();
+            float lastBreakpoint = min;
+
+            while (lastBreakpoint < max)
+            {
+                breakpoints.Add(lastBreakpoint);
+                lastBreakpoint = lastBreakpoint * (1 + margin);
+            }
+
+            return breakpoints;
+        }
+
+        private static Size GetSize(float margin)
+        {
+            float min = IsLandscape ? MinBreakpointSize.Width : MinBreakpointSize.Height;
+            float max = IsLandscape ? MaxBreakpointSize.Width : MaxBreakpointSize.Height;
+            var breakpoints = GetBreakpoints(min, max, margin);
+
+            float limit = WindowSize.Width;
+            float breakpoint = breakpoints.Where(x => x <= limit).Last();
+
+            LogToDebug(breakpoints, limit, breakpoint, margin);
+
+            // MarginalLayout controls only width margins, height always equals window size
+            return new Size(breakpoint, WindowSize.Height);
+        }
+
+        private static void LogToDebug(IEnumerable<float> breakpoints, float limit, float breakpoint, float margin)
+        {
+            var breakpoints__ = breakpoints.Select(x => Convert.ToInt32(x).ToString());
+            double effectiveMarginPixels = limit - breakpoint;
+            double effectiveMarginPercent = Math.Round(effectiveMarginPixels / limit, 2);
+            Tizen.Log.Debug(nameof(ScalableUI), $"Window size {WindowSize.Width} x {WindowSize.Height} px");
+            Tizen.Log.Debug(nameof(ScalableUI), $"Horizontal breakpoints [{string.Join(",", breakpoints__)}] px, Selected {breakpoint} px is below {WindowSize.Width} px");
+            Tizen.Log.Debug(nameof(ScalableUI), $"MaxMargin = {margin}, effective margin = {effectiveMarginPercent} ({effectiveMarginPixels} px)");
+        }
+
+        private float maxMargin;
+        public float MaxMargin
+        {
+            get => maxMargin;
+            set
+            {
+                maxMargin = value;
+
+                Size = GetSize(maxMargin);
+
+                PositionUsesPivotPoint = true;
+                ParentOrigin = Tizen.NUI.ParentOrigin.Center;
+                PivotPoint = Tizen.NUI.PivotPoint.Center;
+            }
+        }
+    }
+}
diff --git a/Oobe/Oobe/ScalableUI/OrientationalView.cs b/Oobe/Oobe/ScalableUI/OrientationalView.cs
new file mode 100644 (file)
index 0000000..49e7b9e
--- /dev/null
@@ -0,0 +1,489 @@
+using System.Threading.Tasks;
+using System.Linq;
+using Tizen.NUI;
+using Tizen.NUI.BaseComponents;
+using Tizen.NUI.Components;
+using System.Collections.Generic;
+using System;
+
+namespace ScalableUI
+{
+    public class OrientationalView : Tizen.NUI.BaseComponents.View
+    {
+        public enum Mode
+        {
+            Stacking,
+            Splitting,
+        };
+
+        public Mode LandscapeMode { get; set; } = Mode.Stacking;
+
+        public int SplittingSpacing { get; set; } = 0;
+
+        public OrientationalView()
+        {
+            Size2D = Window.Instance.Size;
+            PositionUsesPivotPoint = true;
+            ParentOrigin = Tizen.NUI.ParentOrigin.Center;
+            PivotPoint = Tizen.NUI.PivotPoint.Center;
+            
+            ClippingMode = ClippingModeType.ClipToBoundingBox;
+            pageEnterAnimation = new Tizen.NUI.Animation();
+            pageLeaveAnimation = new Tizen.NUI.Animation();
+            opacityEffectAnimation = new Tizen.NUI.Animation();
+            pageEnterAnimation.Finished += OnPageEntered;
+            pageLeaveAnimation.Finished += OnPageLeave;
+        }
+
+        public override void Add(View child)
+        {
+            child.PositionUsesPivotPoint = false;
+
+            if (LandscapeMode == Mode.Stacking)
+            {
+                AddStacking(child);
+            }
+            else if (LandscapeMode == Mode.Splitting)
+            {
+                child.Hide();
+                base.Add(child);
+                AddSplitting(child);
+            }
+        }
+
+        public override async void Remove(View child)
+        {
+            if (LandscapeMode == Mode.Stacking)
+            {
+                await RemoveStacking(child);
+            }
+            else if (LandscapeMode == Mode.Splitting)
+            {
+                await RemoveSplitting(child);
+                base.Remove(child);
+            }
+        }
+
+        public void RemoveLastAdded()
+        {
+            if (Children.Any())
+            {
+                var last = Children.Last();
+                Remove(last);
+            }
+        }
+
+        private async void AddSplitting(View child)
+        {
+            if (Children.Count == 1)
+            {
+                int width = Size2D.Width - (Padding.Start + Padding.End);
+                int height = Size2D.Height - (Padding.Top + Padding.Bottom);
+
+                // show child behind right edge
+                child.Size2D = new Size2D(width, height);
+                child.Position2D = new Position2D(Size2D.Width, Padding.Top);
+                child.Show();
+
+                // slide left onto the vieport
+                await Animation.AnimateTo(child, "PositionX", (int)Padding.Start);
+            }
+            else if (Children.Count == 2)
+            {
+                int width = (Size2D.Width - (Padding.Start + Padding.End + SplittingSpacing)) / 2;
+                int height = Size2D.Height - (Padding.Top + Padding.Bottom);
+
+                var prev = Children.Skip(Children.Count - 2).First();
+
+                // reduce width
+                await Animation.AnimateTo(prev, "SizeWidth", width);
+                // FIX ME: animating SizeWidth does animate background, but not content => thus, required to reassign size
+                prev.Size2D = new Size2D(width, height);
+
+                // show child behind right edge
+                child.Size2D = new Size2D(width, height);
+                child.Position2D = new Position2D(Size2D.Width, Padding.Top);
+                child.Show();
+
+                // slide left onto the viewport
+                await Animation.AnimateTo(child, "PositionX", Padding.Start + width + SplittingSpacing);
+            }
+            else
+            {
+                int width = (Size2D.Width - (Padding.Start + Padding.End + SplittingSpacing)) / 2;
+                int height = Size2D.Height - (Padding.Top + Padding.Bottom);
+
+                var first = Children.Skip(Children.Count - 3).First();
+                var prev = Children.Skip(Children.Count - 2).First();
+
+                // slide left out of the viewport
+                await Animation.AnimateTo(first, "PositionX", -width);
+                first.Hide();
+
+                // slide left from right
+                await Animation.AnimateTo(prev, "PositionX", (int)Padding.Start);
+
+                // show child behind right edge
+                child.Size2D = new Size2D(width, height);
+                child.Position2D = new Position2D(Size2D.Width, Padding.Top);
+                child.Show();
+
+                // slide left onto the viewport
+                await Animation.AnimateTo(child, "PositionX", Padding.Start + width + SplittingSpacing);
+            }
+        }
+
+        private async Task RemoveSplitting(View child)
+        {
+            if (Children.Count == 1)
+            {
+                // slide right out of the viewport
+                await Animation.AnimateTo(child, "PositionX", Size2D.Width);
+            }
+            else if (Children.Count == 2)
+            {
+                int width = Size2D.Width - (Padding.Start + Padding.End);
+                int height = Size2D.Height - (Padding.Top + Padding.Bottom);
+
+                var first = Children.First();
+                var last = Children.Last();
+
+                // slide right out of the viewport
+                await Animation.AnimateTo(last, "PositionX", Size2D.Width);
+
+                // increase width
+                await Animation.AnimateTo(first, "SizeWidth", width);
+                // FIX ME: animating SizeWidth does animate background, but not content => thus, required to reassign size
+                first.Size2D = new Size2D(width, height);
+            }
+            else
+            {
+                int width = (Size2D.Width - (Padding.Start + Padding.End + SplittingSpacing)) / 2;
+
+                var first = Children.Skip(Children.Count - 3).First();
+                var prev = Children.Skip(Children.Count - 2).First();
+                var last = Children.Last();
+
+                // slide right out of the viewport
+                await Animation.AnimateTo(last, "PositionX", Size2D.Width);
+                last.Hide();
+
+                // slide from left to right
+                await Animation.AnimateTo(prev, "PositionX", Padding.Start + width + SplittingSpacing);
+
+                // slide right onto the viewport
+                first.Show();
+                await Animation.AnimateTo(first, "PositionX", (int)Padding.Start);
+            }
+        }
+
+        private async void AddStacking(View child)
+        {
+            Push(child);
+            //int width = Size2D.Width - (Padding.Start + Padding.End);
+            //int height = Size2D.Height - (Padding.Top + Padding.Bottom);
+
+            //if (ChildCount > 1)
+            //{
+            //    var prev = Children.Skip(Children.Count - 2).First();
+
+            //    // fade out current item
+            //    await Animation.AnimateTo(prev, "Opacity", 0.0f);
+            //    prev.Hide();
+            //}
+
+            //// show next item behind the screen
+            //child.Size2D = new Size2D(width, height);
+            //child.Position2D = new Position2D(Size2D.Width, Padding.Top);
+            //child.Show();
+
+            //// animate next item to correct position
+            //await Animation.AnimateTo(child, "PositionX", (int)Padding.Start);
+        }
+
+        private async Task RemoveStacking(View child)
+        {
+            Pop();
+            //var last = Children.Last();
+            //await Animation.AnimateTo(last, "PositionX", Size2D.Width);
+            //last.Hide();
+
+            //var prev = Children.Skip(Children.Count - 2).First();
+            //if (prev != null)
+            //{
+            //    prev.Show();
+            //    await Animation.AnimateTo(prev, "Opacity", 1.0f);
+            //}
+        }
+
+        private List<View> views = new List<View>();
+        private List<View> viewsToRemove = new List<View>();
+
+        private Tizen.NUI.Animation pageEnterAnimation;
+        private Tizen.NUI.Animation pageLeaveAnimation;
+        private Tizen.NUI.Animation opacityEffectAnimation;
+
+        /// <summary>
+        /// Informs about transition animation end
+        /// </summary>Add
+        public event EventHandler TransitionFinished;
+
+        /// <summary>
+        /// Number of pixels between stack right boundary and newly pushed child view left boundary,
+        /// which will be applied before starting page entering animation.
+        /// </summary>
+        /// <value></value>
+        public int PagesRightPadding { get; set; } = 0;
+
+        /// <summary>
+        /// Number of pixels between stack right boundary and current top child view left boundary,
+        /// which will be applied after finishing page leaving animation
+        /// </summary>
+        public int PagesLeftPadding { get; set; } = 0;
+
+        /// <summary>
+        /// Duration of page entering and page leaving animations
+        /// </summary>
+        public int ScrollDuration { get; set; } = 125;
+
+        /// <summary>
+        /// Get view currently stacked on Top of ViewStack
+        /// </summary>
+        public View Current
+        {
+            get
+            {
+                return views.Count > 0 ? views[views.Count - 1] : null;
+            }
+        }
+
+        /// <summary>
+        /// Get view currently stacked under Current
+        /// </summary>
+        public View Previous
+        {
+            get
+            {
+                return views.Count > 1 ? views[views.Count - 2] : null;
+            }
+        }
+
+        /// <summary>
+        /// Pop Current view with animation
+        /// </summary>
+        public void Pop()
+        {
+            if (Current != null)
+            {
+                FinishAnimations();
+                RemoveAllDelayedViews();
+                StartPageLeaveAnimation(Previous, Current);
+                StartShowAnimation(Previous);
+                AddViewToDelayRemove(Current);
+                views.Remove(Current);
+            }
+        }
+
+        /// <summary>
+        /// Pushed new view on stack with animation.
+        /// </summary>
+        public void Push(View view)
+        {
+            FinishAnimations();
+            RemoveAllDelayedViews();
+            Add(view);
+            views.Add(view);
+            StartPageEnterAnimation(Previous, Current);
+            StartHideAnimation(Previous);
+        }
+
+        protected override void Dispose(Tizen.NUI.DisposeTypes type)
+        {
+            if (disposed)
+            {
+                return;
+            }
+
+            if (type == DisposeTypes.Explicit)
+            {
+                pageEnterAnimation.Dispose();
+                pageLeaveAnimation.Dispose();
+            }
+
+            base.Dispose(type);
+        }
+
+        private static void FinishAnimation(Tizen.NUI.Animation anim)
+        {
+            if (anim != null)
+            {
+                if (anim.State == Tizen.NUI.Animation.States.Playing)
+                {
+                    anim.Stop(Tizen.NUI.Animation.EndActions.StopFinal);
+                }
+
+                anim.Clear();
+            }
+        }
+
+        private void AddViewToDelayRemove(View view)
+        {
+            if (view)
+            {
+                viewsToRemove.Add(view);
+            }
+        }
+
+        private void RemoveAllDelayedViews()
+        {
+            foreach (View view in viewsToRemove)
+            {
+                // hide view to resolve issue with rendering artifacts
+                view.Hide();
+                Remove(view);
+                view.Dispose();
+            }
+
+            viewsToRemove.Clear();
+        }
+
+        private void FinishAnimations()
+        {
+            FinishAnimation(pageLeaveAnimation);
+            FinishAnimation(pageEnterAnimation);
+            FinishAnimation(opacityEffectAnimation);
+        }
+
+        private void StartPageLeaveAnimation(View back, View front)
+        {
+            pageLeaveAnimation.Duration = ScrollDuration;
+            pageLeaveAnimation.DefaultAlphaFunction = new AlphaFunction(AlphaFunction.BuiltinFunctions.EaseOutSine);
+
+            if (back != null)
+            {
+                // place 'back' out of viewport (should be already there)
+                // run animation to place 'back' in viewport
+                pageLeaveAnimation.AnimateTo(back, "PositionX", 0, null);
+            }
+
+            if (front != null)
+            {
+                // place 'front' in viewport (should be already there)
+                // run animation to place 'front' out of viewport
+                pageLeaveAnimation.AnimateTo(front, "PositionX", Size2D.Width + PagesRightPadding);
+            }
+
+            pageLeaveAnimation.Play();
+        }
+
+        private void StartPageEnterAnimation(View back, View front)
+        {
+            pageEnterAnimation.Duration = ScrollDuration;
+            pageEnterAnimation.DefaultAlphaFunction = new AlphaFunction(AlphaFunction.BuiltinFunctions.EaseOutSine);
+
+            if (back != null)
+            {
+                // place back in viewport (should be already there)
+                // run anim to place 'back' out of viewport
+                int diff = Position2D.X - PagesLeftPadding;
+                pageEnterAnimation.AnimateTo(back, "PositionX", diff);
+            }
+
+            if (front != null)
+            {
+                // place 'front' out of viewport
+                front.Position2D.X = Size2D.Width + PagesRightPadding;
+
+                // run anim to place 'front' on viewport
+                pageEnterAnimation.AnimateTo(front, "PositionX", 0, null);
+            }
+
+            pageEnterAnimation.Play();
+        }
+
+        private void OnPageEntered(object sender, EventArgs args)
+        {
+            TransitionFinished?.Invoke(this, new EventArgs());
+        }
+
+        private void OnPageLeave(object sender, EventArgs args)
+        {
+            RemoveAllDelayedViews();
+            TransitionFinished?.Invoke(this, new EventArgs());
+        }
+
+        private void StartHideAnimation(View view)
+        {
+            StartOpacityAnimation(view, 1.0f, 0.0f);
+        }
+
+        private void StartShowAnimation(View view)
+        {
+            StartOpacityAnimation(view, 0.0f, 1.0f);
+        }
+
+        private void StartOpacityAnimation(View view, float from, float to)
+        {
+            if (view != null)
+            {
+                opacityEffectAnimation.Duration = ScrollDuration;
+                view.Opacity = from;
+                opacityEffectAnimation.AnimateTo(view, "Opacity", to);
+                opacityEffectAnimation.Play();
+            }
+        }
+
+        //private class ViewStackBaseCustomLayout : LayoutGroup
+        //{
+        //    protected override void OnMeasure(MeasureSpecification widthMeasureSpec, MeasureSpecification heightMeasureSpec)
+        //    {
+        //        OrientationalView stack = this.Owner as OrientationalView;
+
+        //        if (!stack)
+        //        {
+        //            return;
+        //        }
+
+        //        int totalWidth = stack.Size2D.Width;
+        //        int totalHeight = stack.Size2D.Height;
+
+        //        SetMeasuredDimensions(
+        //                ResolveSizeAndState(new LayoutLength(totalWidth), widthMeasureSpec, MeasuredSize.StateType.MeasuredSizeOK),
+        //                ResolveSizeAndState(new LayoutLength(totalHeight), heightMeasureSpec, MeasuredSize.StateType.MeasuredSizeOK));
+        //    }
+
+        //    protected override void OnLayout(bool changed, LayoutLength left, LayoutLength top, LayoutLength right, LayoutLength bottom)
+        //    {
+        //        OrientationalView stack = this.Owner as OrientationalView;
+
+        //        if (!changed || !stack)
+        //        {
+        //            return;
+        //        }
+
+        //        int totalWidth = stack.Size2D.Width;
+        //        int totalHeight = stack.Size2D.Height;
+
+        //        foreach (LayoutItem childLayout in LayoutChildren)
+        //        {
+        //            if (childLayout.Owner == stack.Current)
+        //            {
+        //                childLayout.Layout(
+        //                    new LayoutLength(0),
+        //                    new LayoutLength(0),
+        //                    new LayoutLength(totalWidth),
+        //                    new LayoutLength(totalHeight));
+        //            }
+        //            else
+        //            {
+        //                childLayout.Layout(
+        //                    new LayoutLength(-stack.PagesLeftPadding),
+        //                    new LayoutLength(0),
+        //                    new LayoutLength(totalWidth - stack.PagesLeftPadding),
+        //                    new LayoutLength(totalHeight));
+        //            }
+        //        }
+        //    }
+        //}
+    }
+}
index a19ec804afc70c3d65624cdd40f54fe2d4cd841c..4db631e22bc49d3b5b5a2f538517e1cdeb146d50 100644 (file)
@@ -23,39 +23,54 @@ using Tizen.NUI.Components;
 namespace Oobe.Views
 {
     /// <summary>
-    /// Implementation of OOBE GUI Guideline for IoT Headed
+    /// Implementation of OOBE GUI Guideline for IoT Headed 
     /// </summary>
-    public class MainView : View
+    public class MainView : ScalableUI.MarginalView
     {
         private const int TransitionTime = 750;
         private readonly Extents stackMargin = new Extents(48, 48, 48, 48);
-        private ViewStack stack;
+        //private ViewStack stack;
+        private ScalableUI.OrientationalView orientational;
         private Pagination pagination;
 
         public MainView(Window win)
             : base()
         {
-            BackgroundImage = NUIApplication.Current.DirectoryInfo.Resource + "0_BG_dark.png";
-
             Size2D stackSize = new Size2D(
                     win.WindowSize.Width - stackMargin.Start - stackMargin.End,
                     win.WindowSize.Height - stackMargin.Top - stackMargin.Bottom);
 
+            BackgroundImage = NUIApplication.Current.DirectoryInfo.Resource + "0_BG_dark.png";
+            MaxMargin = 0.25f;
+
             /* For testing other resolutions
             stackSize.Width = 1280 - stackMargin.Start - stackMargin.End;
             stackSize.Height = 720 - stackMargin.Top - stackMargin.Bottom;
             */
 
-            stack = new ViewStack()
+            //stack = new ViewStack()
+            //{
+            //    ScrollDuration = TransitionTime,
+            //    Position2D = new Position2D(stackMargin.Start, stackMargin.Top),
+            //    Size2D = stackSize,
+            //    PagesRightPadding = stackMargin.Start,
+            //    PagesLeftPadding = (int)(0.5f * stackSize.Width),
+            //    ClippingMode = ClippingModeType.Disabled,
+            //};
+
+            orientational = new ScalableUI.OrientationalView
             {
-                ScrollDuration = TransitionTime,
-                Position2D = new Position2D(stackMargin.Start, stackMargin.Top),
-                Size2D = stackSize,
-                PagesRightPadding = stackMargin.Start,
-                PagesLeftPadding = (int)(0.5f * stackSize.Width),
-                ClippingMode = ClippingModeType.Disabled,
+                LandscapeMode = ScalableUI.OrientationalView.Mode.Stacking,
+                PositionUsesPivotPoint = true,
+                ParentOrigin = Position.ParentOriginCenter,
+                PivotPoint = Position.PivotPointCenter,
+                //Position2D = new Position2D(0, 0),
+                Padding = stackMargin,
+                Size2D = this.Size
             };
 
+            Add(orientational);
+
             pagination = new Pagination();
             pagination.PositionUsesPivotPoint = true;
             pagination.PivotPoint = new Position(0.5f, 1.0f);
@@ -69,7 +84,7 @@ namespace Oobe.Views
             };
             pagination.IndicatorSpacing = 12;
 
-            Add(stack);
+            //Add(stack);
             Add(pagination);
         }
 
@@ -101,13 +116,15 @@ namespace Oobe.Views
             view.WidthResizePolicy = ResizePolicyType.FillToParent;
 
             pagination.SelectedIndex = pagination.SelectedIndex + 1;
-            stack.Push(view);
+            orientational.Add(view);
+            //stack.Push(view);
         }
 
         public void Pop()
         {
             pagination.SelectedIndex = pagination.SelectedIndex - 1;
-            stack.Pop();
+            orientational.RemoveLastAdded();
+            //stack.Pop();
         }
 
         protected override void Dispose(DisposeTypes type)
@@ -119,8 +136,9 @@ namespace Oobe.Views
 
             if (type == DisposeTypes.Explicit)
             {
-                stack.Dispose();
+                //stack.Dispose();
                 pagination.Dispose();
+                orientational.Dispose();
             }
 
             base.Dispose(type);