aboutsummaryrefslogtreecommitdiffstats
path: root/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Navigation/DefaultNavigationManager.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Navigation/DefaultNavigationManager.cs')
-rw-r--r--Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Navigation/DefaultNavigationManager.cs369
1 files changed, 364 insertions, 5 deletions
diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Navigation/DefaultNavigationManager.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Navigation/DefaultNavigationManager.cs
index 092b958cc..899ba846e 100644
--- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Navigation/DefaultNavigationManager.cs
+++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Navigation/DefaultNavigationManager.cs
@@ -3,8 +3,13 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
+using Tango.Core;
+using Tango.Core.Commands;
using Tango.MachineStudio.Common;
+using Tango.MachineStudio.Common.Modules;
using Tango.MachineStudio.Common.Navigation;
+using Tango.MachineStudio.Common.Threading;
+using Tango.SharedUI.Controls;
namespace Tango.MachineStudio.UI.Navigation
{
@@ -12,18 +17,372 @@ namespace Tango.MachineStudio.UI.Navigation
/// Represents the Machine Studio default <see cref="INavigationManager">Navigation Manager</see>.
/// </summary>
/// <seealso cref="Tango.MachineStudio.Common.Navigation.INavigationManager" />
- public class DefaultNavigationManager : INavigationManager
+ public class DefaultNavigationManager : ExtendedObject, INavigationManager
{
+ private event Action<Object, Object> NavigationCycleCompleted;
+
+ private IDispatcherProvider _dispatcherProvider;
+ private IStudioModuleLoader _moduleLoader;
+ private Object _currentVM;
+ private String _lastFullPath;
+ private bool _preventHistory;
+ private bool _navigating_back;
+
+ private Stack<String> _navigationHistory;
+
+ /// <summary>
+ /// Gets the current view model.
+ /// </summary>
+ public StudioViewModel CurrentVM
+ {
+ get { return _currentVM as StudioViewModel; }
+ }
+
+ private IStudioModule _currentModule;
+ /// <summary>
+ /// Gets or sets the current module.
+ /// </summary>
+ public IStudioModule CurrentModule
+ {
+ get { return _currentModule; }
+ private set { _currentModule = value; RaisePropertyChangedAuto(); }
+ }
+
+ /// <summary>
+ /// Navigates to the previous view.
+ /// </summary>
+ public RelayCommand NavigateBackCommand { get; private set; }
+
+ /// <summary>
+ /// Navigates to the specified full path in command parameter.
+ /// </summary>
+ public RelayCommand<String> NavigateToCommand { get; private set; }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="DefaultNavigationManager"/> class.
+ /// </summary>
+ /// <param name="moduleLoader">The module loader.</param>
+ public DefaultNavigationManager(IStudioModuleLoader moduleLoader, IDispatcherProvider dispatcherProvider)
+ {
+ _navigationHistory = new Stack<String>();
+ _moduleLoader = moduleLoader;
+
+ NavigateToCommand = new RelayCommand<string>(async (x) => await NavigateTo(x));
+ NavigateBackCommand = new RelayCommand(async () => await NavigateBack());
+
+ _dispatcherProvider = dispatcherProvider;
+ }
+
/// <summary>
- /// Navigates to the specified view.
+ /// Navigates to the specified PPC view.
/// </summary>
/// <param name="view">The view.</param>
- public void NavigateTo(NavigationView view)
+ public Task<bool> NavigateTo(NavigationView view, bool pushToHistory = true)
{
- MainWindow.Instance.Dispatcher.Invoke(() =>
+ LogManager.Log($"Navigating to: {view.ToString()}...");
+
+ _dispatcherProvider.Invoke(() =>
{
- MainWindow.Instance.TransitionControl.NavigateTo(view.ToString());
+ MainWindow.Instance.NavigationControl.NavigateTo(view.ToString());
});
+
+ return Task.FromResult(true);
+ }
+
+ /// <summary>
+ /// Navigates to the specified PPC view with the specified receive object.
+ /// </summary>
+ /// <param name="view">The view.</param>
+ /// <param name="obj"></param>
+ /// <param name="pushToHistory"></param>
+ /// <returns></returns>
+ public Task<bool> NavigateWithObject<TPass>(NavigationView view, TPass obj, bool pushToHistory = true)
+ {
+ LogManager.Log($"Navigating to: {view.ToString()}, with object {typeof(TPass).Name}...");
+ MainWindow.Instance.NavigationControl.NavigateTo(view.ToString());
+ INavigationObjectReceiver<TPass> receiver = MainWindow.Instance.NavigationControl.Elements.FirstOrDefault(x => (x.GetType().Name == view.ToString() || NavigationControl.GetNavigationName(x) == view.ToString()) && x.DataContext is INavigationObjectReceiver<TPass>).DataContext as INavigationObjectReceiver<TPass>;
+
+ if (receiver != null)
+ {
+ receiver.OnNavigatedToWithObject(obj);
+ }
+
+ return Task.FromResult(true);
+ }
+
+ /// <summary>
+ /// Navigates to the specified module.
+ /// </summary>
+ /// <typeparam name="T"></typeparam>
+ public Task<bool> NavigateTo<T>(bool pushToHistory = true) where T : IStudioModule
+ {
+ return NavigateTo(typeof(T));
+ }
+
+ /// <summary>
+ /// Navigates to the specified module using the view path (e.g MainView.JobsView).
+ /// </summary>
+ /// <typeparam name="T"></typeparam>
+ /// <param name="viewPath">The view path.</param>
+ public Task<bool> NavigateTo<T>(string viewPath, bool pushToHistory = true) where T : IStudioModule
+ {
+ return NavigateTo<T>(pushToHistory, viewPath.Split('.'));
+ }
+
+ /// <summary>
+ /// Navigates to the specified module using the view path (e.g MainView,JobsView).
+ /// This method makes it easy to do stuff like NavigateTo(nameof(MainView),nameof(JobsView));
+ /// </summary>
+ /// <typeparam name="T"></typeparam>
+ /// <param name="viewPath">The view path.</param>
+ public Task<bool> NavigateTo<T>(bool pushToHistory = true, params String[] viewPath) where T : IStudioModule
+ {
+ return NavigateTo(typeof(T), pushToHistory, viewPath);
+ }
+
+ /// <summary>
+ /// Navigates to the specified module and view by full path (e.g Jobs.JobsView).
+ /// </summary>
+ /// <param name="fullPath">The full path.</param>
+ public async Task<bool> NavigateTo(String fullPath, bool pushToHistory = true)
+ {
+ String[] path = fullPath.Split('.');
+ var module = _moduleLoader.UserModules.SingleOrDefault(x => x.GetType().Name == path[0] || x.Name == path[0]);
+
+ if (path.Length == 1 && path[0] == CurrentModule.Name) return true;
+
+ LogManager.Log($"Navigating to: {fullPath}...");
+
+ var fromVM = _currentVM;
+
+ if (_currentVM != null && _currentVM is INavigationBlocker)
+ {
+ if (_navigating_back)
+ {
+ if (!await (_currentVM as INavigationBlocker).OnNavigateBackRequest())
+ {
+ return false;
+ }
+ }
+ else
+ {
+ if (!await (_currentVM as INavigationBlocker).OnNavigateOutRequest())
+ {
+ return false;
+ }
+ }
+ }
+
+ if (pushToHistory && _lastFullPath != null && !_preventHistory)
+ {
+ _navigationHistory.Push(_lastFullPath);
+ RaisePropertyChanged(nameof(CanNavigateBack));
+ }
+
+ _lastFullPath = fullPath;
+
+ MainWindow.Instance.NavigationControl.NavigateTo(NavigationView.MainView.ToString());
+ var navigationControl = MachineStudio.UI.Views.MainView.Instance.NavigationControl;
+ CurrentModule = module;
+ var moduleView = navigationControl.NavigateTo(module.Name);
+
+ _currentVM = moduleView.DataContext;
+
+ if (path.Length > 1)
+ {
+ var moduleNavigation = moduleView.FindChildOffline<NavigationControl>();
+
+ moduleNavigation.RegisterForLoadedOrNow(async (x, e) =>
+ {
+ foreach (var view in path.Skip(1))
+ {
+ await Task.Delay(100);
+ var v = moduleNavigation.NavigateTo(view);
+
+ if (v != null)
+ {
+ _currentVM = v.DataContext;
+
+ if (view != path.Last())
+ {
+ moduleNavigation = v.FindChildOffline<NavigationControl>();
+ }
+ }
+ else
+ {
+ throw LogManager.Log(new ArgumentNullException("Could not navigate to " + fullPath));
+ }
+ }
+
+ NavigationCycleCompleted?.Invoke(fromVM, _currentVM);
+ });
+ }
+
+ return true;
+ }
+
+ /// <summary>
+ /// Navigates for result.
+ /// </summary>
+ /// <typeparam name="TModule">The type of the module.</typeparam>
+ /// <typeparam name="TView">The type of the view.</typeparam>
+ /// <typeparam name="TResult">The type of the result.</typeparam>
+ /// <typeparam name="TObject">The type of the object.</typeparam>
+ /// <param name="obj">The object.</param>
+ /// <param name="pushToHistory">if set to <c>true</c> [push to history].</param>
+ /// <returns></returns>
+ public Task<TResult> NavigateForResult<TModule, TView, TResult, TObject>(TObject obj, bool pushToHistory = true)
+ where TModule : IStudioModule
+ {
+ TaskCompletionSource<TResult> source = new TaskCompletionSource<TResult>();
+
+ var fromVM = _currentVM;
+ Object toVM = null;
+
+
+ Action<Object, Object> handler = null;
+
+ handler = (from, to) =>
+ {
+ if (toVM == null)
+ {
+ toVM = to;
+ if (toVM is INavigationResultProvider<TResult, TObject>)
+ {
+ (toVM as INavigationResultProvider<TResult, TObject>).OnNavigationObjectReceived(obj);
+ }
+ }
+ else
+ {
+ if (to == fromVM && from == toVM)
+ {
+ if (from is INavigationResultProvider<TResult, TObject>)
+ {
+ source.SetResult((from as INavigationResultProvider<TResult, TObject>).GetNavigationResult());
+ }
+ }
+
+ NavigationCycleCompleted -= handler;
+ }
+ };
+
+ NavigationCycleCompleted += handler;
+
+ NavigateTo<TModule>(typeof(TView).Name, pushToHistory);
+
+ return source.Task;
+ }
+
+ /// <summary>
+ /// Navigates to the specified module and view with the specified object.
+ /// </summary>
+ /// <typeparam name="TModule">The type of the module.</typeparam>
+ /// <typeparam name="TView">The type of the view.</typeparam>
+ /// <typeparam name="TPass">The type of the pass.</typeparam>
+ /// <param name="obj">The object.</param>
+ /// <param name="pushToHistory">if set to <c>true</c> [push to history].</param>
+ /// <returns></returns>
+ public Task<bool> NavigateWithObject<TModule, TView, TPass>(TPass obj, bool pushToHistory = true) where TModule : IStudioModule
+ {
+ TaskCompletionSource<bool> source = new TaskCompletionSource<bool>();
+
+ Action<Object, Object> handler = null;
+
+ handler = (from, to) =>
+ {
+ if (to is INavigationObjectReceiver<TPass>)
+ {
+ (to as INavigationObjectReceiver<TPass>).OnNavigatedToWithObject(obj);
+ }
+
+ NavigationCycleCompleted -= handler;
+ };
+
+ NavigationCycleCompleted += handler;
+
+ NavigateTo<TModule>(typeof(TView).Name, pushToHistory);
+
+ return source.Task;
+ }
+
+ private Task<bool> NavigateTo(Type moduleType, bool pushToHistory = true, params String[] viewPath)
+ {
+ if (viewPath != null && viewPath.Length > 0)
+ {
+ return NavigateTo(moduleType.Name + "." + String.Join(".", viewPath), pushToHistory);
+ }
+ else
+ {
+ return NavigateTo(moduleType.Name, pushToHistory);
+ }
+ }
+
+ /// <summary>
+ /// Gets a value indicating whether the navigation system is able to navigate to the previous view.
+ /// </summary>
+ public bool CanNavigateBack
+ {
+ get { return _navigationHistory.Count > 0; }
+ }
+
+ /// <summary>
+ /// Navigates to the previous view if <see cref="P:Tango.PPC.Common.Navigation.INavigationManager.CanNavigateBack" /> is true.
+ /// </summary>
+ public async Task<bool> NavigateBack()
+ {
+ LogManager.Log("Navigating back...");
+
+ _navigating_back = true;
+
+ String first = _navigationHistory.Pop();
+ _preventHistory = true;
+
+
+ if (await NavigateTo(first))
+ {
+ RaisePropertyChanged(nameof(CanNavigateBack));
+ _preventHistory = false;
+ _navigating_back = false;
+ return true;
+ }
+ else
+ {
+ _navigationHistory.Push(first);
+ _preventHistory = false;
+ _navigating_back = false;
+ RaisePropertyChanged(nameof(CanNavigateBack));
+ return false;
+ }
+ }
+
+ /// <summary>
+ /// Clears the navigation back history.
+ /// </summary>
+ public void ClearHistory()
+ {
+ LogManager.Log("Navigation history cleared.");
+ _navigationHistory.Clear();
+ RaisePropertyChanged(nameof(CanNavigateBack));
+ }
+
+ /// <summary>
+ /// Clears the navigation back history except the specified view type.
+ /// </summary>
+ /// <typeparam name="T"></typeparam>
+ public void ClearHistoryExcept<T>()
+ {
+ LogManager.Log($"Navigation history cleared except for {typeof(T).Name}.");
+
+ var history_list = _navigationHistory.ToList();
+ history_list = history_list.Where(x => x.Contains(typeof(T).Name)).Distinct().ToList();
+ _navigationHistory.Clear();
+
+ foreach (var item in history_list)
+ {
+ _navigationHistory.Push(item);
+ }
+
+ RaisePropertyChanged(nameof(CanNavigateBack));
}
}
}