Basic App navigation
authorLukasz Stanislawski <l.stanislaws@samsung.com>
Wed, 28 Oct 2020 11:59:13 +0000 (12:59 +0100)
committerPiotr Czaja <p.czaja@samsung.com>
Tue, 14 Sep 2021 11:01:34 +0000 (13:01 +0200)
1. Add set of controls for stack based navigation
2. Add NavigationService to manager all navigation and make it
   available to user from ViewModels

16 files changed:
Fitness/Controls/INavigationStack.cs [new file with mode: 0644]
Fitness/Controls/NavigationStack.cs [new file with mode: 0644]
Fitness/Controls/Page.cs [new file with mode: 0644]
Fitness/FitnessApp.cs
Fitness/Services/NavigationService.cs [new file with mode: 0644]
Fitness/ViewModels/MainViewModel.cs
Fitness/Views/ExercisePreviewView.cs
Fitness/Views/ExercisingView.cs
Fitness/Views/LoadingView.cs
Fitness/Views/MainView.xaml.cs
Fitness/Views/ScanningView.cs
Fitness/res/layout/ExercisePreviewView.xaml
Fitness/res/layout/ExercisingView.xaml
Fitness/res/layout/LoadingView.xaml
Fitness/res/layout/MainView.xaml
Fitness/res/layout/ScanningView.xaml

diff --git a/Fitness/Controls/INavigationStack.cs b/Fitness/Controls/INavigationStack.cs
new file mode 100644 (file)
index 0000000..b29d399
--- /dev/null
@@ -0,0 +1,15 @@
+namespace Fitness.Controls
+{
+    public interface INavigationStack
+    {
+        /// <summary>
+        /// Pushes page on navigation stack
+        /// </summary>
+        void Push(Page page);
+
+        /// <summary>
+        /// Pops top page from navigation stack
+        /// </summary>
+        void Pop();
+    }
+}
diff --git a/Fitness/Controls/NavigationStack.cs b/Fitness/Controls/NavigationStack.cs
new file mode 100644 (file)
index 0000000..55c9a28
--- /dev/null
@@ -0,0 +1,39 @@
+using System.Collections.Generic;
+using Tizen.NUI;
+using Tizen.NUI.BaseComponents;
+using Tizen.NUI.Components;
+
+namespace Fitness.Controls
+{
+    /// <summary>
+    /// Implements stack-based navigation
+    /// </summary>
+    public class NavigationStack : Control, INavigationStack
+    {
+        private Stack<Page> pages = new Stack<Page>();
+
+        public NavigationStack()
+            : base()
+        {
+            WidthResizePolicy = ResizePolicyType.FillToParent;
+            HeightResizePolicy = ResizePolicyType.FillToParent;
+        }
+
+        public List<Page> Pages { get => new List<Page>(pages); }
+
+        public void Push(Page page)
+        {
+            Add(page);
+            pages.Push(page);
+        }
+
+        public void Pop()
+        {
+            if (pages.TryPeek(out Page last))
+            {
+                Remove(last);
+                pages.Pop();
+            }
+        }
+    }
+}
diff --git a/Fitness/Controls/Page.cs b/Fitness/Controls/Page.cs
new file mode 100644 (file)
index 0000000..0a553e4
--- /dev/null
@@ -0,0 +1,19 @@
+using Tizen.NUI;
+using Tizen.NUI.BaseComponents;
+using Tizen.NUI.Components;
+
+namespace Fitness.Controls
+{
+    /// <summary>
+    /// Base class for full-screen page navigation
+    /// </summary>
+    public class Page : Control
+    {
+        public Page()
+            : base()
+        {
+            WidthResizePolicy = ResizePolicyType.FillToParent;
+            HeightResizePolicy = ResizePolicyType.FillToParent;
+        }
+    }
+}
index ef14fd0..a1508f1 100644 (file)
@@ -1,6 +1,5 @@
 using System;
 using Fitness.Services;
-using Fitness.Views;
 using Tizen.NUI;
 using Tizen.NUI.BaseComponents;
 
@@ -16,7 +15,7 @@ namespace Fitness
 
         public void Initialize()
         {
-            Window.Instance.GetDefaultLayer().Add(new MainView());
+            NavigationService.Instance.NavigateToMainView();
         }
 
         protected override void OnCreate()
diff --git a/Fitness/Services/NavigationService.cs b/Fitness/Services/NavigationService.cs
new file mode 100644 (file)
index 0000000..4ad075f
--- /dev/null
@@ -0,0 +1,56 @@
+using Fitness.Controls;
+using Fitness.Views;
+using Tizen.NUI;
+
+namespace Fitness.Services
+{
+    public sealed class NavigationService
+    {
+        private static NavigationService instance;
+        private NavigationStack navigation;
+
+        private NavigationService()
+        {
+            navigation = new NavigationStack();
+            Window.Instance.GetDefaultLayer().Add(navigation);
+        }
+
+        public static NavigationService Instance
+        {
+            get
+            {
+                if (instance == null)
+                {
+                    instance = new NavigationService();
+                }
+
+                return instance;
+            }
+        }
+
+        public void NavigateToMainView()
+        {
+            navigation.Push(new MainView());
+        }
+
+        public void NavigateToExercisingView()
+        {
+            navigation.Push(new ExercisingView());
+        }
+
+        public void NavigateToExercisePreviewView()
+        {
+            navigation.Push(new ExercisePreviewView());
+        }
+
+        public void NavigateToScanningView()
+        {
+            navigation.Push(new ScanningView());
+        }
+
+        public void NavigateToLoadingView()
+        {
+            navigation.Push(new LoadingView());
+        }
+    }
+}
index 9cc1517..6fc03c7 100644 (file)
@@ -1,7 +1,10 @@
 using System;
 using System.Collections.ObjectModel;
+using System.Windows.Input;
 using Fitness.Models;
+using Fitness.Services;
 using Tizen.Applications;
+using Tizen.NUI.Binding;
 
 namespace Fitness.ViewModels
 {
@@ -132,11 +135,24 @@ namespace Fitness.ViewModels
                 ThumbnailUrl = Application.Current.DirectoryInfo.Resource + "media/video-0002.jpeg",
               },
             });
+
+            WatchPreview = new Command(() => { NavigationService.Instance.NavigateToExercisePreviewView(); });
+            StartWorkout = new Command(() => { NavigationService.Instance.NavigateToExercisingView(); });
         }
 
         /// <summary>
         /// List of all available workouts
         /// </summary>
         public ObservableCollection<Workout> Workouts { get; private set; }
+
+        /// <summary>
+        /// Watch selected workout preview
+        /// </summary>
+        public ICommand WatchPreview { get; private set; }
+
+        /// <summary>
+        /// Start selected workout.
+        /// </summary>
+        public ICommand StartWorkout { get; private set; }
     }
 }
index 08fb6c0..5dfbf3c 100644 (file)
@@ -1,8 +1,9 @@
+using Fitness.Controls;
 using Tizen.NUI.BaseComponents;
 
 namespace Fitness.Views
 {
-    public partial class ExercisePreviewView : View
+    public partial class ExercisePreviewView : Page
     {
         public ExercisePreviewView()
         {
index 60e7bb9..2f3888e 100644 (file)
@@ -1,8 +1,9 @@
+using Fitness.Controls;
 using Tizen.NUI.BaseComponents;
 
 namespace Fitness.Views
 {
-    public partial class ExercisingView : View
+    public partial class ExercisingView : Page
     {
         public ExercisingView()
         {
index 6585649..4d41d0f 100644 (file)
@@ -1,8 +1,9 @@
+using Fitness.Controls;
 using Tizen.NUI.BaseComponents;
 
 namespace Fitness.Views
 {
-    public partial class LoadingView : View
+    public partial class LoadingView : Page
     {
         public LoadingView()
         {
index 79763f1..725fc1b 100644 (file)
@@ -1,9 +1,10 @@
+using Fitness.Controls;
 using Tizen.NUI;
 using Tizen.NUI.BaseComponents;
 
 namespace Fitness.Views
 {
-    public partial class MainView : View
+    public partial class MainView : Fitness.Controls.Page
     {
         public MainView()
         {
index e48c2a5..3de6211 100644 (file)
@@ -1,8 +1,9 @@
+using Fitness.Controls;
 using Tizen.NUI.BaseComponents;
 
 namespace Fitness.Views
 {
-    public partial class ScanningView : View
+    public partial class ScanningView : Page
     {
         public ScanningView()
         {
index 8efd3de..4bc9d70 100644 (file)
@@ -1,6 +1,7 @@
 <?xml version="1.0" encoding="UTF-8" ?>
-<View x:Class="Fitness.Views.ExercisePreviewView"
+<ctrl:Page x:Class="Fitness.Views.ExercisePreviewView"
   xmlns="http://tizen.org/Tizen.NUI/2018/XAML"
   xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
-  HeightResizePolicy="FillToParent" WidthResizePolicy="FillToParent" BackgroundColor="#EEEFF1" ParentOrigin="Center" PivotPoint="Center" PositionUsesPivotPoint="true">
-</View>
+  xmlns:ctrl="clr-namespace:Fitness.Controls"
+  HeightResizePolicy="FillToParent" WidthResizePolicy="FillToParent" BackgroundColor="Red" ParentOrigin="Center" PivotPoint="Center" PositionUsesPivotPoint="true">
+</ctrl:Page>
index 940f50f..b137d76 100644 (file)
@@ -1,6 +1,7 @@
 <?xml version="1.0" encoding="UTF-8" ?>
-<View x:Class="Fitness.Views.ExercisingView"
+<ctrl:Page x:Class="Fitness.Views.ExercisingView"
   xmlns="http://tizen.org/Tizen.NUI/2018/XAML"
   xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
-  HeightResizePolicy="FillToParent" WidthResizePolicy="FillToParent" BackgroundColor="#EEEFF1" ParentOrigin="Center" PivotPoint="Center" PositionUsesPivotPoint="true">
-</View>
+  xmlns:ctrl="clr-namespace:Fitness.Controls"
+  HeightResizePolicy="FillToParent" WidthResizePolicy="FillToParent" BackgroundColor="Red" ParentOrigin="Center" PivotPoint="Center" PositionUsesPivotPoint="true">
+</ctrl:Page>
index b0377a5..d43e190 100644 (file)
@@ -1,6 +1,7 @@
 <?xml version="1.0" encoding="UTF-8" ?>
-<View x:Class="Fitness.Views.LoadingView"
+<ctrl:Page x:Class="Fitness.Views.LoadingView"
   xmlns="http://tizen.org/Tizen.NUI/2018/XAML"
   xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+  xmlns:ctrl="clr-namespace:Fitness.Controls"
   HeightResizePolicy="FillToParent" WidthResizePolicy="FillToParent" BackgroundColor="#EEEFF1" ParentOrigin="Center" PivotPoint="Center" PositionUsesPivotPoint="true">
-</View>
+</ctrl:Page>
index c96009e..6018a36 100644 (file)
@@ -1,17 +1,18 @@
 <?xml version="1.0" encoding="UTF-8" ?>
-<View x:Class="Fitness.Views.MainView"
+<ctrl:Page x:Class="Fitness.Views.MainView"
   xmlns="http://tizen.org/Tizen.NUI/2018/XAML"
   xmlns:vm="clr-namespace:Fitness.ViewModels;"
   xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
   xmlns:views="clr-namespace:Fitness.Views"
+  xmlns:ctrl="clr-namespace:Fitness.Controls"
   xmlns:c="clr-namespace:Tizen.NUI.Components;assembly=Tizen.NUI.Components"
   HeightResizePolicy="FillToParent" WidthResizePolicy="FillToParent" BackgroundColor="#EEEFF1" ParentOrigin="Center" PivotPoint="Center" PositionUsesPivotPoint="true" Padding="{views:ExtentsInUnits Top=26}">
-  <View.BindingContext>
-    <vm:MainViewModel/>
-  </View.BindingContext>
   <View.Layout>
       <LinearLayout LinearOrientation="Vertical" LinearAlignment="Top"/>
   </View.Layout>
+  <View.BindingContext>
+    <vm:MainViewModel x:Name="mainViewModel"/>
+  </View.BindingContext>
   <View Margin="{views:ExtentsInUnits Start=16,End=16}" Weight="1.0" WidthResizePolicy="FillToParent">
       <View.Layout>
           <LinearLayout LinearOrientation="Horizontal" LinearAlignment="End"/>
               <View.Layout>
                   <LinearLayout LinearOrientation="Vertical" LinearAlignment="Center"/>
               </View.Layout>
-              <c:Button PositionUsesPivotPoint="true" ParentOrigin="0.5,0.5" PivotPoint="0.5,0.5" Text="Let's try"/>
-              <c:Button PositionUsesPivotPoint="true" ParentOrigin="0.5,0.5" PivotPoint="0.5,0.5" Text="Watch Preview"/>
+              <c:Button BindingContext="{x:Reference mainViewModel}" PositionUsesPivotPoint="true" ParentOrigin="0.5,0.5" PivotPoint="0.5,0.5" Text="Let's try" Command="{Binding StartWorkout}"/>
+              <c:Button BindingContext="{x:Reference mainViewModel}" PositionUsesPivotPoint="true" ParentOrigin="0.5,0.5" PivotPoint="0.5,0.5" Text="Watch Preview" Command="{Binding WatchPreview}"/>
           </View>
       </View>
       <TextLabel BackgroundColor="Cyan" Size="{views:SizeInUnits Width=107}" Margin="{views:ExtentsInUnits Start=8}" HeightResizePolicy="FillToParent" />
   </View>
   <TextLabel BackgroundColor="Green" Size="{views:SizeInUnits Height=44}" Margin="{views:ExtentsInUnits Top=10, Bottom=10}" WidthResizePolicy="FillToParent"/>
-</View>
+</ctrl:Page>
index e111ae9..2cdf024 100644 (file)
@@ -1,6 +1,7 @@
 <?xml version="1.0" encoding="UTF-8" ?>
-<View x:Class="Fitness.Views.ScanningView"
+<ctrl:Page x:Class="Fitness.Views.ScanningView"
   xmlns="http://tizen.org/Tizen.NUI/2018/XAML"
   xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+  xmlns:ctrl="clr-namespace:Fitness.Controls"
   HeightResizePolicy="FillToParent" WidthResizePolicy="FillToParent" BackgroundColor="#EEEFF1" ParentOrigin="Center" PivotPoint="Center" PositionUsesPivotPoint="true">
-</View>
+</ctrl:Page>