aboutsummaryrefslogtreecommitdiffstats
path: root/Software/Visual_Studio/Tango.BL/DTO/MachineStudioVersionDTOBase.cs
blob: 116d7491055f4610b3dba84a4793c5185ea40bb2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Tango Observables Generator
// 
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated. Do not modify!
// </auto-generated>
//------------------------------------------------------------------------------

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Tango.BL.Entities;

namespace Tango.BL.DTO
{
    public abstract class MachineStudioVersionDTOBase : ObservableEntityDTO<MachineStudioVersionDTO, MachineStudioVersion>
    {

        /// <summary>
        /// version
        /// </summary>
        public String Version 
        {
            get; set; 
        }

        /// <summary>
        /// blob name
        /// </summary>
        public String BlobName 
        {
            get; set; 
        }

        /// <summary>
        /// installer blob name
        /// </summary>
        public String InstallerBlobName 
        {
            get; set; 
        }

        /// <summary>
        /// comments
        /// </summary>
        public String Comments 
        {
            get; set; 
        }

        /// <summary>
        /// user guid
        /// </summary>
        public String UserGuid 
        {
            get; set; 
        }

    }
}
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media;
using Tango.Core;
using Tango.Core.Commands;
using Tango.PPC.Common;
using Tango.PPC.Common.Modules;
using Tango.PPC.Common.Navigation;
using Tango.PPC.Common.Notifications;
using Tango.PPC.Common.Threading;
using Tango.PPC.UI.Views;
using Tango.SharedUI.Controls;

namespace Tango.PPC.UI.Navigation
{
    /// <summary>
    /// Represents the default PPC navigation manager.
    /// </summary>
    /// <seealso cref="Tango.PPC.Common.Navigation.INavigationManager" />
    public class DefaultNavigationManager : ExtendedObject, INavigationManager
    {
        //private event Action<Object, Object> NavigationCycleCompleted;
        //private event Action<Object, Object> BeforeNavigationCycleCompleted;
        private class AwaitingVMResult
        {
            public PPCViewModel FromVM { get; set; }
            public PPCViewModel ToVM { get; set; }
            public Action Action { get; set; }
        }

        private List<AwaitingVMResult> _awaitingVMResults;
        private IDispatcherProvider _dispatcherProvider;
        private IPPCModuleLoader _moduleLoader;
        private INotificationProvider _notificationProvider;
        private String _lastFullPath;
        private bool _preventHistory;
        private bool _navigating_back;

        public event EventHandler<PPCViewModel> CurrentVMChanged;

        private Stack<String> _navigationHistory;

        private Object _currentVM;
        /// <summary>
        /// Gets the current view model.
        /// </summary>
        public PPCViewModel CurrentVM
        {
            set
            {
                var previous = _currentVM;
                _currentVM = value;

                var vm = _currentVM as PPCViewModel;

                if (_currentVM != previous && vm != null)
                {
                    CurrentVMChanged?.Invoke(this, vm);
                }
            }
            get
            {
                return _currentVM as PPCViewModel;
            }
        }

        private IPPCModule _currentModule;
        /// <summary>
        /// Gets or sets the current module.
        /// </summary>
        public IPPCModule 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(IPPCModuleLoader moduleLoader, IDispatcherProvider dispatcherProvider, INotificationProvider notificationProvider)
        {
            IsBackEnabled = true;
            _awaitingVMResults = new List<AwaitingVMResult>();
            _navigationHistory = new Stack<String>();
            _moduleLoader = moduleLoader;
            _notificationProvider = notificationProvider;

            NavigateToCommand = new RelayCommand<string>(async (x) => await NavigateTo(x));
            NavigateBackCommand = new RelayCommand(async () => await NavigateBack());

            _dispatcherProvider = dispatcherProvider;
        }

        /// <summary>
        /// Navigates to the specified PPC view.
        /// </summary>
        /// <param name="view">The view.</param>
        public Task<bool> NavigateTo(NavigationView view, bool pushToHistory = true)
        {
            if (view == NavigationView.HomeModule)
            {
                _navigationHistory.Clear();
                _lastFullPath = null;

                var firstModule = _moduleLoader.UserModules.FirstOrDefault();

                if (firstModule != null)
                {
                    var moduleAtt = firstModule.GetType().GetCustomAttribute<PPCModuleAttribute>();

                    if (moduleAtt != null)
                    {
                        return NavigateTo(firstModule.GetType(), pushToHistory, moduleAtt.HomeViewName);
                    }
                    else
                    {
                        return NavigateTo(firstModule.GetType(), pushToHistory);
                    }
                }
                else
                {
                    return NavigateTo(NavigationView.NoPermissionsView);
                }
            }
            else
            {

                LogManager.Log($"Navigating to: {view.ToString()}...");

                var fromView = MainView.Instance.NavigationControl.SelectedElement;
                FrameworkElement toView = null;

                toView = MainView.Instance.NavigationControl.NavigateTo(view.ToString(), (Action)(() =>
                {
                    CurrentVM = toView.DataContext as PPCViewModel;
                    NotifyOnNavigated(fromView.DataContext, toView.DataContext);

                }));

                NotifyOnBeforeNavigated(fromView.DataContext, toView.DataContext);

                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}...");
            MainView.Instance.NavigationControl.NavigateTo(view.ToString());
            INavigationObjectReceiver<TPass> receiver = MainView.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 : IPPCModule
        {
            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 : IPPCModule
        {
            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 : IPPCModule
        {
            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, Action<PPCViewModel, PPCViewModel> onNavigating = null, Action<PPCViewModel, PPCViewModel> onNavigated = null)
        {
            try
            {
                IsNavigating = true;

                String[] path = fullPath.Split('.');
                var module = _moduleLoader.UserModules.SingleOrDefault(x => x.GetType().Name == path[0] || x.Name == path[0]);

                if (module == null)
                {
                    await _notificationProvider.ShowError("The specified module was not loaded.");
                    IsNavigating = false;
                    return false;
                }

                if (path.Length == 1 && path[0] == CurrentModule.Name)
                {
                    IsNavigating = false;
                    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())
                        {
                            IsNavigating = false;
                            return false;
                        }
                    }
                    else
                    {
                        if (!await (CurrentVM as INavigationBlocker).OnNavigateOutRequest())
                        {
                            IsNavigating = false;
                            return false;
                        }
                    }
                }



                if (pushToHistory && _lastFullPath != null && !_preventHistory)
                {
                    _navigationHistory.Push(_lastFullPath);
                    RaisePropertyChanged(nameof(CanNavigateBack));
                }

                _lastFullPath = fullPath;

                MainView.Instance.NavigationControl.NavigateTo(NavigationView.LayoutView.ToString());
                var navigationControl = LayoutView.Instance.NavigationControl;
                CurrentModule = module;
                var moduleView = navigationControl.NavigateTo(module.Name);

                CurrentVM = moduleView.DataContext as PPCViewModel;

                if (path.Length > 1)
                {
                    var moduleNavigation = moduleView.FindChildOffline<NavigationControl>();

                    if (moduleNavigation != null)
                    {
                        moduleNavigation.RegisterForLoadedOrNow(async (x, e) =>
                        {
                            var lastView = moduleNavigation.GetElement(path.Last());

                            if (lastView != null)
                            {
                                onNavigating?.Invoke(fromVM as PPCViewModel, lastView.DataContext as PPCViewModel);
                            }

                            foreach (var view in path.Skip(1))
                            {
                                await Task.Delay(100);

                                FrameworkElement v = null;

                                v = moduleNavigation.NavigateTo(view, () =>
                                {
                                    if (v != null)
                                    {
                                        NotifyOnNavigated(fromVM, v.DataContext);
                                        onNavigated?.Invoke(fromVM as PPCViewModel, v.DataContext as PPCViewModel);
                                        NotifyAwaitingVMResults(fromVM as PPCViewModel, v.DataContext as PPCViewModel);
                                    }
                                });

                                NotifyOnBeforeNavigated(fromVM, v.DataContext);

                                if (v != null)
                                {
                                    CurrentVM = v.DataContext as PPCViewModel;

                                    if (view != path.Last())
                                    {
                                        moduleNavigation = v.FindChildOffline<NavigationControl>();
                                    }
                                }
                                else
                                {
                                    throw LogManager.Log(new ArgumentNullException("Could not navigate to " + fullPath));
                                }
                            }
                        });
                    }
                    else
                    {
                        onNavigating?.Invoke(fromVM as PPCViewModel, CurrentVM as PPCViewModel);

                        NotifyOnBeforeNavigated(fromVM, CurrentVM);

                        await Task.Delay(navigationControl.TransitionDuration.TimeSpan);

                        NotifyOnNavigated(fromVM, CurrentVM);

                        onNavigated?.Invoke(fromVM as PPCViewModel, CurrentVM as PPCViewModel);
                        NotifyAwaitingVMResults(fromVM as PPCViewModel, CurrentVM as PPCViewModel);
                    }
                }
                else
                {
                    NotifyOnBeforeNavigated(fromVM, CurrentVM);

                    onNavigating?.Invoke(fromVM as PPCViewModel, CurrentVM as PPCViewModel);

                    await Task.Delay(navigationControl.TransitionDuration.TimeSpan);

                    NotifyOnNavigated(fromVM, CurrentVM);

                    onNavigated?.Invoke(fromVM as PPCViewModel, CurrentVM as PPCViewModel);
                    NotifyAwaitingVMResults(fromVM as PPCViewModel, CurrentVM as PPCViewModel);
                }

                return true;
            }
            catch (Exception ex)
            {
                IsNavigating = false;
                LogManager.Log(ex, $"Error navigating to '{fullPath}'.");
                await _notificationProvider.ShowError($"Error navigating to '{fullPath}'.");
                return false;
            }
        }

        /// <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 async Task<TResult> NavigateForResult<TModule, TView, TResult, TObject>(TObject obj, bool pushToHistory = true)
               where TModule : IPPCModule
        {
            TaskCompletionSource<TResult> source = new TaskCompletionSource<TResult>();

            var fromVM = CurrentVM;

            await NavigateTo(typeof(TModule).Name + "." + typeof(TView).Name, pushToHistory, (from, to) =>
            {
                _awaitingVMResults.Add(new AwaitingVMResult()
                {
                    FromVM = fromVM as PPCViewModel,
                    ToVM = to as PPCViewModel,
                    Action = () =>
                    {
                        if (to is INavigationResultProvider<TResult, TObject>)
                        {
                            source.SetResult((to as INavigationResultProvider<TResult, TObject>).GetNavigationResult());
                        }
                    }
                });

                if (to is INavigationResultProvider<TResult, TObject>)
                {
                    (to as INavigationResultProvider<TResult, TObject>).OnNavigationObjectReceived(obj);
                }
            });

            return await 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 : IPPCModule
        {
            return NavigateTo(typeof(TModule).Name + "." + typeof(TView).Name, pushToHistory, (fromVM, toVM) =>
            {
                if (toVM is INavigationObjectReceiver<TPass>)
                {
                    (toVM as INavigationObjectReceiver<TPass>).OnNavigatedToWithObject(obj);
                }
            });
        }

        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; }
        }

        private bool _isBackEnabled;
        /// <summary>
        /// Gets a value indicating whether the back should be enabled.
        /// </summary>
        public bool IsBackEnabled
        {
            get { return _isBackEnabled; }
            set { _isBackEnabled = value; RaisePropertyChangedAuto(); }
        }

        private bool _isNavigating;
        /// <summary>
        /// Gets or sets a value indicating whether the navigation system is currently navigating.
        /// </summary>
        public bool IsNavigating
        {
            get { return _isNavigating; }
            set
            {
                _isNavigating = value;
                RaisePropertyChangedAuto();
            }
        }

        /// <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;

            if (_navigationHistory.Count > 0)
            {
                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;
                }
            }
            else
            {
                await NavigateTo(NavigationView.HomeModule);
                RaisePropertyChanged(nameof(CanNavigateBack));
                _preventHistory = false;
                _navigating_back = false;
                return true;
            }
        }

        /// <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));
        }

        private void NotifyOnBeforeNavigated(object fromVM, object toVM)
        {
            if (fromVM == toVM) return;

            if (fromVM is PPCViewModel)
            {
                (fromVM as PPCViewModel)?.OnBeforeNavigatedFrom();
            }

            if (toVM is PPCViewModel)
            {
                (toVM as PPCViewModel)?.OnBeforeNavigatedTo();
            }
        }

        private void NotifyOnNavigated(object fromVM, object toVM)
        {
            IsNavigating = false;

            if (fromVM == toVM) return;

            if (fromVM is PPCViewModel)
            {
                (fromVM as PPCViewModel)?.OnNavigatedFrom();
            }

            if (toVM is PPCViewModel)
            {
                (toVM as PPCViewModel)?.OnNavigatedTo();
                (toVM as PPCViewModel)?.OnNavigatedTo(fromVM as PPCViewModel);
            }
        }

        private void NotifyAwaitingVMResults(PPCViewModel fromVM, PPCViewModel toVM)
        {
            var awaiter = _awaitingVMResults.SingleOrDefault(x => x.FromVM == toVM && x.ToVM == fromVM);
            if (awaiter != null)
            {
                _awaitingVMResults.Remove(awaiter);
                awaiter.Action();
            }
        }
    }
}