diff options
| author | Roy Ben-Shabat <Roy@Twine-s.com> | 2018-08-23 09:45:01 +0300 |
|---|---|---|
| committer | Roy Ben-Shabat <Roy@Twine-s.com> | 2018-08-23 09:45:01 +0300 |
| commit | 2c8da378c82e5181f0566a564de529ab7ef96f4f (patch) | |
| tree | d450472402b15fc30d8bd482da348826caf487c5 /Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Navigation | |
| parent | 774da535e732ecd5a3737550ef1d35819a1e7fc6 (diff) | |
| download | Tango-2c8da378c82e5181f0566a564de529ab7ef96f4f.tar.gz Tango-2c8da378c82e5181f0566a564de529ab7ef96f4f.zip | |
Improvements to machine studio view models and navigation system.
Improvements to tech board selection and edit modes handling.
Diffstat (limited to 'Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Navigation')
| -rw-r--r-- | Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Navigation/DefaultNavigationManager.cs | 369 |
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)); } } } |
