aboutsummaryrefslogtreecommitdiffstats
path: root/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Navigation/DefaultNavigationManager.cs
blob: 13ec6161d2e157c54fe00c38f7dddc1a4dde496f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
pre { line-height: 125%; }
td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
.highlight .hll { background-color: #ffffcc }
.highlight .c { color: #888888 } /* Comment */
.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */
.highlight .k { color: #008800; font-weight: bold } /* Keyword */
.highlight .ch { color: #888888 } /* Comment.Hashbang */
.highlight .cm { color: #888888 } /* Comment.Multiline */
.highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */
.highlight .cpf { color: #888888 } /* Comment.PreprocFile */
.highlight .c1 { color: #888888 } /* Comment.Single */
.highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */
.highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .ges { font-weight: bold; font-style: italic } /* Generic.EmphStrong */
.highlight .gr { color: #aa0000 } /* Generic.Error */
.highlight .gh { color: #333333 } /* Generic.Heading */
.highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
.highlight .go { color: #888888 } /* Generic.Output */
.highlight .gp { color: #555555 } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #666666 } /* Generic.Subheading */
.highlight .gt { color: #aa0000 } /* Generic.Traceback */
.highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */
.highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */
.highlight .kp { color: #008800 } /* Keyword.Pseudo */
.highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */
.highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */
.highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */
.highlight .na { color: #336699 } /* Name.Attribute */
.highlight .nb { color: #003388 } /* Name.Builtin */
.highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */
.highlight .no { color: #003366; font-weight: bold } /* Name.Constant */
.highlight .nd { color: #555555 } /* Name.Decorator */
.highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */
.highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */
.highlight .nl { color: #336699; font-style: italic } /* Name.Label */
.highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */
.highlight .py { color: #336699; font-weight: bold } /* Name.Property */
.highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */
.highlight .nv { color: #336699 } /* Name.Variable */
.highlight .ow { color: #008800 } /* Operator.Word */
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
.highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */
.highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */
.highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */
.highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */
.highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */
.highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */
.highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */
.highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */
.highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */
.highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */
.highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */
.highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */
.highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */
.highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */
.highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */
.highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */
.highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */
.highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */
.highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */
.highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */
.highlight .vc { color: #336699 } /* Name.Variable.Class */
.highlight .vg { color: #dd7700 } /* Name.Variable.Global */
.highlight .vi { color: #3333bb } /* Name.Variable.Instance */
.highlight .vm { color: #336699 } /* Name.Variable.Magic */
.highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Tango.Scripting.IDE
{
    public class Solution
    {
        public ObservableCollection<IProject> Projects { get; set; }
        public string Name{get; set;}
        public string SolutionLocation { get; set; }

        public Solution()
        {
            Projects = new ObservableCollection<IProject>();
        }
    }
}
275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Tango.Core;
using Tango.Core.Commands;
using Tango.Core.DI;
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
{
    /// <summary>
    /// Represents the Machine Studio default <see cref="INavigationManager">Navigation Manager</see>.
    /// </summary>
    /// <seealso cref="Tango.MachineStudio.Common.Navigation.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 PPC view.
        /// </summary>
        /// <param name="view">The view.</param>
        public Task<bool> NavigateTo(NavigationView view, bool pushToHistory = true)
        {
            LogManager.Log($"Navigating to: {view.ToString()}...");

            _dispatcherProvider.Invoke(() =>
            {
                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));
        }

        public void NavigateToModule<T>() where T : IStudioModule
        {
            var loader = TangoIOC.Default.GetInstance<IStudioModuleLoader>();
            var module = loader.UserModules.SingleOrDefault(x => x.GetType() == typeof(T));

            if (module != null)
            {
                TangoIOC.Default.GetInstance<ViewModels.MainViewVM>().StartModule(module);
            }
        }
    }
}