diff options
| author | Avi Levkovich <avi@twine-s.com> | 2018-02-20 16:45:00 +0200 |
|---|---|---|
| committer | Avi Levkovich <avi@twine-s.com> | 2018-02-20 16:45:00 +0200 |
| commit | 6c208c90bc45aff4a7fa214356a42fe7757c5e6f (patch) | |
| tree | 0d77bc6a0ecfbb53cf42c5462ee19212197ee1bd /Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI | |
| parent | b0823127f152fe97a6e8fce29e427c7f3db9cf5a (diff) | |
| parent | 1a573aaa346ec4b8bd58a0e35ab9df571a09b855 (diff) | |
| download | Tango-6c208c90bc45aff4a7fa214356a42fe7757c5e6f.tar.gz Tango-6c208c90bc45aff4a7fa214356a42fe7757c5e6f.zip | |
MERGE
Diffstat (limited to 'Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI')
33 files changed, 1102 insertions, 210 deletions
diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/App.xaml b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/App.xaml index 8e5876e79..fe50851a0 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/App.xaml +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/App.xaml @@ -11,7 +11,10 @@ <!-- Accent and AppTheme setting --> <ResourceDictionary Source="pack://application:,,,/Tango.MachineStudio.Common;component/Resources/MaterialDesign.xaml"></ResourceDictionary> - <!-- Include the Dragablz Material Design style --> + <!--RealTimeGraphEx--> + <ResourceDictionary Source="pack://application:,,,/RealTimeGraphEx;component/Resources/Resources.xaml"></ResourceDictionary> + + <!-- Include the Dragablz Material Design style --> <ResourceDictionary Source="pack://application:,,,/Dragablz;component/Themes/materialdesign.xaml"/> <ResourceDictionary> diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/App.xaml.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/App.xaml.cs index ca553de1e..c15a87980 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/App.xaml.cs +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/App.xaml.cs @@ -2,10 +2,14 @@ using System.Collections.Generic; using System.Configuration; using System.Data; +using System.Diagnostics; using System.Linq; using System.Threading.Tasks; using System.Windows; -using Tango.DAL.Observables; +using Tango.Integration.Observables; +using Tango.Logging; +using Tango.MachineStudio.UI.Windows; +using Tango.Settings; namespace Tango.MachineStudio.UI { @@ -14,9 +18,63 @@ namespace Tango.MachineStudio.UI /// </summary> public partial class App : Application { + private WpfGlobalExceptionTrapper exceptionTrapper; + protected override void OnStartup(StartupEventArgs e) { base.OnStartup(e); + + LogManager.Categories.Clear(); + + if (SettingsManager.Default.MachineStudio.LoggingCategories.Count == 0) + { + SettingsManager.Default.MachineStudio.LoggingCategories.Add(LogCategory.Critical); + SettingsManager.Default.MachineStudio.LoggingCategories.Add(LogCategory.Error); + SettingsManager.Default.MachineStudio.LoggingCategories.Add(LogCategory.General); + SettingsManager.Default.MachineStudio.LoggingCategories.Add(LogCategory.Warning); + } + + LogManager.Categories.AddRange(SettingsManager.Default.MachineStudio.LoggingCategories); + + LogManager.RegisterLogger(new VSOutputLogger()); + LogManager.RegisterLogger(new FileLogger()); + + exceptionTrapper = new WpfGlobalExceptionTrapper(); + exceptionTrapper.Initialize(this); + exceptionTrapper.ApplicationCrashed += ExceptionTrapper_ApplicationCrashed; } + + #region Global Exception Trapping + + /// <summary> + /// Handles the ApplicationCrashed event of the ExceptionTrapper. + /// </summary> + /// <param name="sender">The source of the event.</param> + /// <param name="e">The <see cref="ApplicationCrashedEventArgs"/> instance containing the event data.</param> + private void ExceptionTrapper_ApplicationCrashed(object sender, ApplicationCrashedEventArgs e) + { + ExceptionWindow exWin = new ExceptionWindow(e.Exception); + exWin.ShowDialog(); + + switch (exWin.Resolution) + { + case ExceptionResolutions.Ignore: + e.TryRecover = true; + break; + case ExceptionResolutions.Restart: + e.TryRecover = false; + LogManager.Log("User selection was to restart the application. Restarting..."); + Process.Start(Application.ResourceAssembly.Location); + Environment.Exit(0); + break; + case ExceptionResolutions.Shutdown: + e.TryRecover = false; + LogManager.Log("User selection was to shutdown the application. Restarting..."); + Environment.Exit(0); + break; + } + } + + #endregion } } diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Authentication/DefaultAuthenticationProvider.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Authentication/DefaultAuthenticationProvider.cs index a30cf0f92..82aba268d 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Authentication/DefaultAuthenticationProvider.cs +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Authentication/DefaultAuthenticationProvider.cs @@ -5,15 +5,22 @@ using System.Security.Authentication; using System.Text; using System.Threading.Tasks; using Tango.Core; -using Tango.DAL.Observables; +using Tango.Integration.Observables; using Tango.MachineStudio.Common.Authentication; namespace Tango.MachineStudio.UI.Authentication { + /// <summary> + /// Represents the default Machine Studio <see cref="IAuthenticationProvider">Authentication provider</see> + /// </summary> + /// <seealso cref="Tango.Core.ExtendedObject" /> + /// <seealso cref="Tango.MachineStudio.Common.Authentication.IAuthenticationProvider" /> public class DefaultAuthenticationProvider : ExtendedObject, IAuthenticationProvider { private User _currentUser; - + /// <summary> + /// Gets the current logged-in user. + /// </summary> public User CurrentUser { get { return _currentUser; } @@ -25,8 +32,18 @@ namespace Tango.MachineStudio.UI.Authentication } } + /// <summary> + /// Occurs when the current logged-in user has changed. + /// </summary> public event EventHandler<User> CurrentUserChanged; + /// <summary> + /// Performs a user login by the specified email and password. + /// </summary> + /// <param name="email">The email.</param> + /// <param name="password">The password.</param> + /// <returns></returns> + /// <exception cref="AuthenticationException">Login failed for user " + email</exception> public User Login(string email, string password) { User user = ObservablesEntitiesAdapter.Instance.Users.SingleOrDefault(x => x.Email.ToLower() == email.ToLower() && x.Password == password); @@ -40,6 +57,9 @@ namespace Tango.MachineStudio.UI.Authentication return user; } + /// <summary> + /// Logs-out the current logged-in user. + /// </summary> public void Logout() { CurrentUser = null; diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/White-Abstract.png b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/White-Abstract.png Binary files differnew file mode 100644 index 000000000..31bd18c35 --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/White-Abstract.png diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/exception.png b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/exception.png Binary files differnew file mode 100644 index 000000000..9a4abb703 --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/exception.png diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/external-bridge-tcp.png b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/external-bridge-tcp.png Binary files differindex 2d8c684b7..192cbcaa7 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/external-bridge-tcp.png +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/external-bridge-tcp.png diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/external-bridge-usb.png b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/external-bridge-usb.png Binary files differindex 62fab6225..414bbab04 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/external-bridge-usb.png +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Images/external-bridge-usb.png diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/MainWindow.xaml b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/MainWindow.xaml index f07e7f476..e0f0b1f4f 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/MainWindow.xaml +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/MainWindow.xaml @@ -8,27 +8,37 @@ xmlns:views="clr-namespace:Tango.MachineStudio.UI.Views" xmlns:sharedControls="clr-namespace:Tango.SharedUI.Controls;assembly=Tango.SharedUI" mc:Ignorable="d" - Title="Tango" Height="720" Width="1280" WindowStartupLocation="CenterOwner" WindowState="Maximized" Foreground="#494949"> + Title="Tango" Height="800" Width="1280" WindowStartupLocation="CenterOwner" WindowState="Maximized" Foreground="#494949" BorderThickness="1" BorderBrush="{StaticResource AccentColorBrush}"> + <Grid> - <sharedControls:MultiTransitionControl AlwaysFade="True" TransitionType="Zoom" x:Name="TransitionControl" x:FieldModifier="public"> - <sharedControls:MultiTransitionControl.Controls> - <ContentControl Tag="LoadingView"> - <views:LoadingView></views:LoadingView> - </ContentControl> - <ContentControl Tag="LoginView"> - <views:LoginView></views:LoginView> - </ContentControl> - <ContentControl Tag="MainView"> - <views:MainView></views:MainView> - </ContentControl> - <ContentControl Tag="ShutdownView"> - <views:ShutdownView></views:ShutdownView> - </ContentControl> - </sharedControls:MultiTransitionControl.Controls> - </sharedControls:MultiTransitionControl> + <Grid.Background> + <ImageBrush ImageSource="/Images/White-Abstract.png" Stretch="Fill"></ImageBrush> + </Grid.Background> + <Viewbox Stretch="Fill" UseLayoutRounding="True" SnapsToDevicePixels="True"> + <Grid Width="1920" Height="1145"> + <Grid> + <sharedControls:MultiTransitionControl AlwaysFade="True" TransitionType="Zoom" x:Name="TransitionControl" x:FieldModifier="public"> + <sharedControls:MultiTransitionControl.Controls> + <ContentControl Tag="LoadingView"> + <views:LoadingView></views:LoadingView> + </ContentControl> + <ContentControl Tag="LoginView"> + <views:LoginView></views:LoginView> + </ContentControl> + <ContentControl Tag="MainView"> + <views:MainView></views:MainView> + </ContentControl> + <ContentControl Tag="ShutdownView"> + <views:ShutdownView></views:ShutdownView> + </ContentControl> + </sharedControls:MultiTransitionControl.Controls> + </sharedControls:MultiTransitionControl> - <Grid Background="Black" Opacity="0.7" x:Name="shadowGrid" Visibility="Hidden"> + <Grid Background="Black" Opacity="0.7" x:Name="shadowGrid" Visibility="Hidden"> - </Grid> + </Grid> + </Grid> + </Grid> + </Viewbox> </Grid> </mahapps:MetroWindow> diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Modules/DefaultStudioModuleLoader.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Modules/DefaultStudioModuleLoader.cs index 473e66d38..5951137e3 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Modules/DefaultStudioModuleLoader.cs +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Modules/DefaultStudioModuleLoader.cs @@ -1,4 +1,5 @@ -using System; +using GalaSoft.MvvmLight.Ioc; +using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.IO; @@ -7,6 +8,8 @@ using System.Reflection; using System.Text; using System.Threading.Tasks; using Tango.Core; +using Tango.Integration.Observables; +using Tango.Logging; using Tango.MachineStudio.Common; using Tango.MachineStudio.Common.Authentication; using Tango.MachineStudio.Common.Modules; @@ -16,11 +19,21 @@ using Tango.MachineStudio.Stubs; namespace Tango.MachineStudio.UI.Modules { + /// <summary> + /// Represents the Machine Studio default <see cref="IStudioModuleLoader">module loader</see>. + /// </summary> + /// <seealso cref="Tango.Core.ExtendedObject" /> + /// <seealso cref="Tango.MachineStudio.Common.Modules.IStudioModuleLoader" /> public class DefaultStudioModuleLoader : ExtendedObject, IStudioModuleLoader { private IAuthenticationProvider _authenticationProvider; private bool _loaded; + public event EventHandler ModulesLoaded; + /// <summary> + /// Initializes a new instance of the <see cref="DefaultStudioModuleLoader"/> class. + /// </summary> + /// <param name="authenticationProvider">The authentication provider.</param> public DefaultStudioModuleLoader(IAuthenticationProvider authenticationProvider) { _authenticationProvider = authenticationProvider; @@ -29,12 +42,20 @@ namespace Tango.MachineStudio.UI.Modules _authenticationProvider.CurrentUserChanged += _authenticationProvider_CurrentUserChanged; } - private void _authenticationProvider_CurrentUserChanged(object sender, DAL.Observables.User e) + /// <summary> + /// Handles the authentication provider user changed event. + /// </summary> + /// <param name="sender">The sender.</param> + /// <param name="e">The e.</param> + private void _authenticationProvider_CurrentUserChanged(object sender, User e) { LoadModules(); } private ObservableCollection<IStudioModule> _allModules; + /// <summary> + /// Gets all loaded modules. + /// </summary> public ObservableCollection<IStudioModule> AllModules { get { return _allModules; } @@ -42,12 +63,18 @@ namespace Tango.MachineStudio.UI.Modules } private ObservableCollection<IStudioModule> _userModules; + /// <summary> + /// Gets all the user permitted modules. + /// </summary> public ObservableCollection<IStudioModule> UserModules { get { return _userModules; } private set { _userModules = value; RaisePropertyChangedAuto(); } } + /// <summary> + /// Loads all available Machine Studio modules. + /// </summary> public void LoadModules() { if (!_loaded) @@ -70,12 +97,19 @@ namespace Tango.MachineStudio.UI.Modules if (moduleAssembly != null) { - foreach (var moduleType in moduleAssembly.GetTypes().Where(x => !x.IsInterface && typeof(IStudioModule).IsAssignableFrom(x))) + foreach (var moduleType in moduleAssembly.GetTypes().Where(x => !x.IsInterface && typeof(IStudioModule).IsAssignableFrom(x) && !x.IsAbstract)) { if (!AllModules.ToList().Exists(x => x.GetType() == moduleType)) { - var module = Activator.CreateInstance(moduleType) as IStudioModule; - AllModules.Add(module); + try + { + var module = Activator.CreateInstance(moduleType) as IStudioModule; + AllModules.Add(module); + } + catch (Exception ex) + { + LogManager.Log(ex, "Could not load module " + moduleType.Name); + } } } } @@ -92,6 +126,18 @@ namespace Tango.MachineStudio.UI.Modules { UserModules = AllModules.Where(x => _authenticationProvider.CurrentUser.HasPermission(x.Permission)).ToObservableCollection(); } + + ModulesLoaded?.Invoke(this, new EventArgs()); + } + + /// <summary> + /// Gets the studio module of type T if loaded. + /// </summary> + /// <typeparam name="T"></typeparam> + /// <returns></returns> + public T GetStudioModule<T>() where T : IStudioModule + { + return UserModules.OfType<T>().FirstOrDefault(); } } } 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 15f2fe422..56abbd702 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Navigation/DefaultNavigationManager.cs +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Navigation/DefaultNavigationManager.cs @@ -3,12 +3,21 @@ using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; +using Tango.MachineStudio.Common; using Tango.MachineStudio.Common.Navigation; 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 : INavigationManager { + /// <summary> + /// Navigates to the specified view. + /// </summary> + /// <param name="view">The view.</param> public void NavigateTo(NavigationView view) { MainWindow.Instance.Dispatcher.Invoke(() => diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Notifications/DefaultNotificationProvider.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Notifications/DefaultNotificationProvider.cs index d4d053eaf..1ea22c587 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Notifications/DefaultNotificationProvider.cs +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Notifications/DefaultNotificationProvider.cs @@ -13,31 +13,68 @@ using System.Collections.ObjectModel; namespace Tango.MachineStudio.UI.Notifications { + /// <summary> + /// Represents the default Machine Studio <see cref="INotificationProvider">Notification Provider</see>. + /// </summary> + /// <seealso cref="Tango.Core.ExtendedObject" /> + /// <seealso cref="Tango.MachineStudio.Common.Notifications.INotificationProvider" /> public class DefaultNotificationProvider : ExtendedObject, INotificationProvider { + /// <summary> + /// The view types + /// </summary> private static List<Type> viewTypes; + /// <summary> + /// Gets the collection of active task items. + /// </summary> public ObservableCollection<TaskItem> TaskItems { get; private set; } + /// <summary> + /// Gets the collection of active bar items. + /// </summary> + public ObservableCollection<BarItem> BarItems { get; private set; } + + /// <summary> + /// Gets a value indicating whether there are any queued task items. + /// </summary> public bool HasTaskItems { get { return TaskItems.Count > 0; } } + /// <summary> + /// The current task item + /// </summary> private TaskItem _currentTaskItem; + /// <summary> + /// Gets the current displayed task item. + /// </summary> public TaskItem CurrentTaskItem { get { return _currentTaskItem; } set { _currentTaskItem = value; RaisePropertyChangedAuto(); RaisePropertyChanged(nameof(HasTaskItems)); } } + /// <summary> + /// Initializes a new instance of the <see cref="DefaultNotificationProvider"/> class. + /// </summary> public DefaultNotificationProvider() { TaskItems = new ObservableCollection<TaskItem>(); + BarItems = new ObservableCollection<BarItem>(); } - public bool? ShowDialog(PackIconKind icon, Brush iconColor, string message, bool hasCancel) + /// <summary> + /// Display a message box. + /// </summary> + /// <param name="icon">The icon.</param> + /// <param name="iconColor">Color of the icon.</param> + /// <param name="message">The message.</param> + /// <param name="hasCancel">if set to <c>true</c> displays the cancel button.</param> + /// <returns></returns> + public bool? ShowMessageBox(PackIconKind icon, Brush iconColor, string message, bool hasCancel) { MainWindow.Instance.shadowGrid.Visibility = Visibility.Visible; @@ -55,6 +92,13 @@ namespace Tango.MachineStudio.UI.Notifications return result; } + /// <summary> + /// Creates a new instance of the specified View type and displays it as a modal dialog. + /// </summary> + /// <typeparam name="View">The type of the view.</typeparam> + /// <typeparam name="VM">The type of the view model.</typeparam> + /// <param name="onAccept">Accept button callback.</param> + /// <param name="onCancel">Cancel button callback.</param> public void ShowModalDialog<View, VM>(Action<VM> onAccept, Action onCancel) where View : FrameworkElement where VM : DialogViewVM { var view = Activator.CreateInstance<View>(); @@ -68,7 +112,7 @@ namespace Tango.MachineStudio.UI.Notifications dialog.DataContext = context; Action onAcceptAction = null; - onAcceptAction = new Action(() => + onAcceptAction = new Action(() => { dialog.Close(); onAccept(context); @@ -76,7 +120,7 @@ namespace Tango.MachineStudio.UI.Notifications }); Action onCancelAction = null; - onCancelAction = new Action(() => + onCancelAction = new Action(() => { dialog.Close(); @@ -97,6 +141,13 @@ namespace Tango.MachineStudio.UI.Notifications MainWindow.Instance.shadowGrid.Visibility = Visibility.Hidden; } + /// <summary> + /// Creates a new view by a naming convention of the specified view model type. + /// </summary> + /// <typeparam name="VM">The type of the view model.</typeparam> + /// <param name="onAccept">Accept button callback.</param> + /// <param name="onCancel">Cancel button callback.</param> + /// <exception cref="NullReferenceException">Could not locate view " + viewName</exception> public void ShowModalDialog<VM>(Action<VM> onAccept, Action onCancel) where VM : DialogViewVM { String viewName = typeof(VM).Name.Replace("VM", ""); @@ -121,6 +172,10 @@ namespace Tango.MachineStudio.UI.Notifications view.Loaded += (x, y) => { VM context = view.DataContext as VM; + if (context == null) + { + context = Activator.CreateInstance<VM>(); + } dialog.DataContext = context; Action onAcceptAction = null; @@ -149,42 +204,73 @@ namespace Tango.MachineStudio.UI.Notifications context.OnShow(); }; - + dialog.ShowDialog(); MainWindow.Instance.shadowGrid.Visibility = Visibility.Hidden; } + /// <summary> + /// Creates a new view by a naming convention of the specified view model type. + /// </summary> + /// <typeparam name="VM">The type of the view model.</typeparam> + /// <param name="onAccept">Accept button callback.</param> public void ShowModalDialog<VM>(Action<VM> onAccept) where VM : DialogViewVM { ShowModalDialog<VM>(onAccept, null); } + /// <summary> + /// Shows an error message box. + /// </summary> + /// <param name="message">The message.</param> public void ShowError(string message) { - ShowDialog(PackIconKind.Exclamation, Brushes.Red, message, false); + ShowMessageBox(PackIconKind.Exclamation, Brushes.Red, message, false); } + /// <summary> + /// Shows an information message box. + /// </summary> + /// <param name="message">The message.</param> public void ShowInfo(string message) { - ShowDialog(PackIconKind.Information, Brushes.Black, message, false); + ShowMessageBox(PackIconKind.Information, Brushes.Black, message, false); } + /// <summary> + /// Shows a question message box. + /// </summary> + /// <param name="message">The message.</param> + /// <returns></returns> public bool ShowQuestion(string message) { - return ShowDialog(PackIconKind.CommentQuestionOutline, Brushes.Black, message, true).Value; + return ShowMessageBox(PackIconKind.CommentQuestionOutline, Brushes.Black, message, true).Value; } - public void ShowWarnning(string message) + /// <summary> + /// Shows warning message box. + /// </summary> + /// <param name="message">The message.</param> + public void ShowWarning(string message) { - ShowDialog(PackIconKind.Exclamation, Brushes.DarkOrange, message, false); + ShowMessageBox(PackIconKind.Exclamation, Brushes.DarkOrange, message, false); } + /// <summary> + /// Pushes the specified task item to the queue. + /// </summary> + /// <param name="taskItem">The task item.</param> public void PushTaskItem(TaskItem taskItem) { TaskItems.Add(taskItem); CurrentTaskItem = taskItem; } + /// <summary> + /// Create and push a new task item from the specified message. + /// </summary> + /// <param name="message">The message.</param> + /// <returns></returns> public TaskItem PushTaskItem(string message) { TaskItem item = new TaskItem(this); @@ -193,6 +279,10 @@ namespace Tango.MachineStudio.UI.Notifications return item; } + /// <summary> + /// Removed the specified task item from the queue. + /// </summary> + /// <param name="taskItem">The task item.</param> public void PopTaskItem(TaskItem taskItem) { TaskItems.Remove(taskItem); @@ -204,5 +294,65 @@ namespace Tango.MachineStudio.UI.Notifications RaisePropertyChanged(nameof(HasTaskItems)); } + + /// <summary> + /// Pushes the specified bar item. + /// </summary> + /// <param name="barItem">The bar item.</param> + /// <returns></returns> + public BarItem PushBarItem(BarItem barItem) + { + BarItems.Add(barItem); + return barItem; + } + + /// <summary> + /// Creates and push a new bar item from the specified framework element. + /// </summary> + /// <param name="element">The element.</param> + /// <returns></returns> + public BarItem PushBarItem(FrameworkElement element) + { + BarItem item = new BarItem(this); + item.Element = element; + PushBarItem(item); + return item; + } + + /// <summary> + /// Removed the specified bar item. + /// </summary> + /// <param name="barItem">The bar item.</param> + public void PopBarItem(BarItem barItem) + { + BarItems.Remove(barItem); + } + + /// <summary> + /// Shows a dialog with a text input field and returns the response. + /// </summary> + /// <param name="message">The message.</param> + /// <param name="hint">Text field hint.</param> + /// <param name="defaultResponse">Optional default response.</param> + /// <returns></returns> + public string ShowTextInput(string message, string hint, string defaultResponse = null) + { + MainWindow.Instance.shadowGrid.Visibility = Visibility.Visible; + + TextInputBoxWindow dlg = new TextInputBoxWindow() + { + Owner = Application.Current.MainWindow, + Message = message, + IconKind = PackIconKind.Pencil, + IconColor = Brushes.DimGray, + Hint = hint, + Response = defaultResponse + }; + + var result = dlg.ShowDialog(); + + MainWindow.Instance.shadowGrid.Visibility = Visibility.Hidden; + return (result.Value ? dlg.Response : null); + } } } diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Notifications/DialogWindow.xaml.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Notifications/DialogWindow.xaml.cs index d1bc0564b..8ed1a4946 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Notifications/DialogWindow.xaml.cs +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Notifications/DialogWindow.xaml.cs @@ -36,7 +36,5 @@ namespace Tango.MachineStudio.UI.Windows // Using a DependencyProperty as the backing store for InnerContent. This enables animation, styling, binding, etc... public static readonly DependencyProperty InnerContentProperty = DependencyProperty.Register("InnerContent", typeof(FrameworkElement), typeof(DialogWindow), new PropertyMetadata(null)); - - } } diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Notifications/TextInputBoxWindow.xaml b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Notifications/TextInputBoxWindow.xaml new file mode 100644 index 000000000..d2aad7cee --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Notifications/TextInputBoxWindow.xaml @@ -0,0 +1,44 @@ +<Window x:Class="Tango.MachineStudio.UI.Notifications.TextInputBoxWindow" + xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + xmlns:d="http://schemas.microsoft.com/expression/blend/2008" + xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" + xmlns:local="clr-namespace:Tango.MachineStudio.UI.Notifications" + xmlns:mahapps="http://metro.mahapps.com/winfx/xaml/controls" + xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes" + xmlns:converters="clr-namespace:Tango.SharedUI.Converters;assembly=Tango.SharedUI" + mc:Ignorable="d" + Title="Machine Studio" MinHeight="220" MaxHeight="600" SizeToContent="Height" Width="570" Opacity="0" AllowsTransparency="True" WindowStyle="None" WindowStartupLocation="CenterOwner" Background="Transparent"> + + <Window.Resources> + <BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"></BooleanToVisibilityConverter> + </Window.Resources> + + <Grid> + <Border Background="White" CornerRadius="10" Padding="10" Margin="20"> + <Border.Effect> + <DropShadowEffect ShadowDepth="0" BlurRadius="10"></DropShadowEffect> + </Border.Effect> + <DockPanel LastChildFill="True"> + <StackPanel Orientation="Horizontal" VerticalAlignment="Bottom" HorizontalAlignment="Right" DockPanel.Dock="Bottom"> + <Button Style="{StaticResource MaterialDesignFlatButton}" IsDefault="True" Margin="0 8 8 0" Click="OnOKClicked"> + ACCEPT + </Button> + <Button Style="{StaticResource MaterialDesignFlatButton}" IsCancel="False" Margin="0 8 8 0" Click="OnCancelClicked"> + CANCEL + </Button> + </StackPanel> + <Grid> + <StackPanel VerticalAlignment="Top" Margin="0 30 0 0"> + <StackPanel Orientation="Horizontal"> + <materialDesign:PackIcon Kind="{Binding RelativeSource={RelativeSource AncestorType=Window},Path=IconKind}" VerticalAlignment="Top" Width="50" Height="50" Foreground="{Binding RelativeSource={RelativeSource AncestorType=Window},Path=IconColor}" /> + <TextBlock Padding="0 10 0 0" TextWrapping="Wrap" Margin="10 0 0 0" VerticalAlignment="Top" FontSize="14" Text="{Binding RelativeSource={RelativeSource AncestorType=Window},Path=Message}" Width="400"></TextBlock> + </StackPanel> + + <TextBox x:Name="txtText" Margin="60 0 20 0" materialDesign:HintAssist.Hint="{Binding RelativeSource={RelativeSource AncestorType=Window},Path=Hint}" Text="{Binding RelativeSource={RelativeSource AncestorType=Window},Path=Response,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"></TextBox> + </StackPanel> + </Grid> + </DockPanel> + </Border> + </Grid> +</Window> diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Notifications/TextInputBoxWindow.xaml.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Notifications/TextInputBoxWindow.xaml.cs new file mode 100644 index 000000000..d774c14eb --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Notifications/TextInputBoxWindow.xaml.cs @@ -0,0 +1,99 @@ +using MahApps.Metro.Controls; +using MaterialDesignThemes.Wpf; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Animation; +using System.Windows.Media.Imaging; +using System.Windows.Shapes; + +namespace Tango.MachineStudio.UI.Notifications +{ + /// <summary> + /// Interaction logic for TextInputBoxWindow.xaml + /// </summary> + public partial class TextInputBoxWindow : Window + { + public TextInputBoxWindow() + { + InitializeComponent(); + this.Loaded += TextInputBoxWindow_Loaded; + } + + private void TextInputBoxWindow_Loaded(object sender, RoutedEventArgs e) + { + DoubleAnimation ani = new DoubleAnimation(); + ani.To = 1; + ani.Duration = TimeSpan.FromSeconds(0.5); + this.BeginAnimation(Window.OpacityProperty, ani); + + txtText.Focus(); + } + + + + public String Hint + { + get { return (String)GetValue(HintProperty); } + set { SetValue(HintProperty, value); } + } + public static readonly DependencyProperty HintProperty = + DependencyProperty.Register("Hint", typeof(String), typeof(TextInputBoxWindow), new PropertyMetadata(null)); + + + + public String Response + { + get { return (String)GetValue(ResponseProperty); } + set { SetValue(ResponseProperty, value); } + } + public static readonly DependencyProperty ResponseProperty = + DependencyProperty.Register("Response", typeof(String), typeof(TextInputBoxWindow), new PropertyMetadata(null)); + + + + public String Message + { + get { return (String)GetValue(MessageProperty); } + set { SetValue(MessageProperty, value); } + } + public static readonly DependencyProperty MessageProperty = + DependencyProperty.Register("Message", typeof(String), typeof(TextInputBoxWindow), new PropertyMetadata(null)); + + public Brush IconColor + { + get { return (Brush)GetValue(IconColorProperty); } + set { SetValue(IconColorProperty, value); } + } + public static readonly DependencyProperty IconColorProperty = + DependencyProperty.Register("IconColor", typeof(Brush), typeof(TextInputBoxWindow), new PropertyMetadata(Brushes.Black)); + + public PackIconKind IconKind + { + get { return (PackIconKind)GetValue(IconKindProperty); } + set { SetValue(IconKindProperty, value); } + } + public static readonly DependencyProperty IconKindProperty = + DependencyProperty.Register("IconKind", typeof(PackIconKind), typeof(TextInputBoxWindow), new PropertyMetadata(PackIconKind.Information)); + + private void OnOKClicked(object sender, RoutedEventArgs e) + { + DialogResult = true; + Close(); + } + + private void OnCancelClicked(object sender, RoutedEventArgs e) + { + DialogResult = false; + Close(); + } + } +} diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/StudioApplication/DefaultStudioApplicationManager.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/StudioApplication/DefaultStudioApplicationManager.cs index de8649c13..886985c92 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/StudioApplication/DefaultStudioApplicationManager.cs +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/StudioApplication/DefaultStudioApplicationManager.cs @@ -14,22 +14,50 @@ using System.Collections; using Tango.Integration.Services; using Tango.Core; using Tango.Logging; +using Tango.MachineStudio.Common.Modules; +using Tango.MachineStudio.Common; +using Tango.Settings; namespace Tango.MachineStudio.UI.StudioApplication { + /// <summary> + /// Represents the default Machine Studio <see cref="IStudioApplicationManager">Application Manager</see>. + /// </summary> + /// <seealso cref="Tango.Core.ExtendedObject" /> + /// <seealso cref="Tango.MachineStudio.Common.StudioApplication.IStudioApplicationManager" /> public class DefaultStudioApplicationManager : ExtendedObject, IStudioApplicationManager { private INavigationManager _navigationManager; + private IStudioModuleLoader _moduleLoader; - public DefaultStudioApplicationManager(INavigationManager navigationManager) + /// <summary> + /// Initializes a new instance of the <see cref="DefaultStudioApplicationManager" /> class. + /// </summary> + /// <param name="navigationManager">The navigation manager.</param> + public DefaultStudioApplicationManager(INavigationManager navigationManager, IStudioModuleLoader moduleLoader) { + _moduleLoader = moduleLoader; _navigationManager = navigationManager; } + /// <summary> + /// Gets a value indicating whether Machine Studio is shutting down. + /// </summary> public bool IsShuttingDown { get; private set; } + /// <summary> + /// The connected machine + /// </summary> private IExternalBridgeClient _connectedMachine; + /// <summary> + /// Occurs when the connected machine property has changed. + /// </summary> + public event EventHandler<IExternalBridgeClient> ConnectedMachineChanged; + + /// <summary> + /// Gets or sets the currently connected machine if any. + /// </summary> public IExternalBridgeClient ConnectedMachine { get { return _connectedMachine; } @@ -45,14 +73,24 @@ namespace Tango.MachineStudio.UI.StudioApplication _connectedMachine.StateChanged -= ConnectedMachine_StateChanged; _connectedMachine.StateChanged += ConnectedMachine_StateChanged; } + + ConnectedMachineChanged?.Invoke(this, _connectedMachine); } } + /// <summary> + /// Gets a value indicating whether the <see cref="P:Tango.MachineStudio.Common.StudioApplication.IStudioApplicationManager.ConnectedMachine" /> is valid and connected through TCP/IP. + /// </summary> public bool IsMachineConnectedViaTCP { - get { return IsMachineConnected && ConnectedMachine.Type != ExternalBridgeClientType.USB; } + get { return IsMachineConnected && ConnectedMachine is ExternalBridgeTcpClient; } } + /// <summary> + /// Handles the <see cref="ConnectedMachine"/> state changed event. + /// </summary> + /// <param name="sender">The sender.</param> + /// <param name="e">The e.</param> private void ConnectedMachine_StateChanged(object sender, Transport.TransportComponentState e) { if (e == Transport.TransportComponentState.Disconnected || e == Transport.TransportComponentState.Failed) @@ -62,11 +100,17 @@ namespace Tango.MachineStudio.UI.StudioApplication } + /// <summary> + /// Gets a value indicating whether the <see cref="P:Tango.MachineStudio.Common.StudioApplication.IStudioApplicationManager.ConnectedMachine" /> is valid. + /// </summary> public bool IsMachineConnected { get { return ConnectedMachine != null; } } + /// <summary> + /// Shutdown the application. + /// </summary> public async void ShutDown() { if (IsShuttingDown) return; @@ -75,6 +119,24 @@ namespace Tango.MachineStudio.UI.StudioApplication await Task.Factory.StartNew(async () => { + //Do Shutdown Procedures... + foreach (var vm in ServiceLocator.Current.GetAllInstancesByBase<IShutdownRequestBlocker>()) + { + try + { + var result = await vm.OnShutdownRequest(); + if (!result) + { + IsShuttingDown = false; + return; + } + } + catch (Exception ex) + { + LogManager.Log(ex, "Error on shutdown request with " + vm.GetType().Name); + } + } + try { if (ConnectedMachine != null) @@ -87,22 +149,52 @@ namespace Tango.MachineStudio.UI.StudioApplication LogManager.Log(ex, "Error disconnecting from machine."); } - //Do Shutdown Procedures... - foreach (var vm in ServiceLocator.Current.GetAllInstancesByBase<IShutdownRequestBlocker>()) + foreach (var vm in ServiceLocator.Current.GetAllInstancesByBase<IShutdownListener>()) { - var result = await vm.OnShutdownRequest(); - if (!result) - { - IsShuttingDown = false; - return; - } + vm.OnShuttingDown(); + } + + try + { + SettingsManager.SaveDefaultSettings(); + } + catch (Exception ex) + { + LogManager.Log(ex, "Error saving settings."); } _navigationManager.NavigateTo(NavigationView.ShutdownView); + Thread.Sleep(3000); + Environment.Exit(0); }); } + + /// <summary> + /// Loads the specified module if permitted. + /// </summary> + /// <param name="moduleName">Name of the module.</param> + /// <param name="args">The arguments.</param> + public void RequestModule(string moduleName, object args) + { + IStudioModule module = _moduleLoader.UserModules.SingleOrDefault(x => x.Name == moduleName); + + if (module != null) + { + ServiceLocator.Current.GetInstance<ViewModels.MainViewVM>().StartModule(module); + + //Notify request listeners. + foreach (var vm in ServiceLocator.Current.GetAllInstancesByBase<IModuleRequestListener>()) + { + vm.OnRequestModule(module, args); + } + } + else + { + throw new InvalidOperationException("The module was not found or you do not have sufficient privileges."); + } + } } } diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/SupervisingController/IMainView.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/SupervisingController/IMainView.cs index 70b57027e..fd8ef4be5 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/SupervisingController/IMainView.cs +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/SupervisingController/IMainView.cs @@ -3,12 +3,21 @@ using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; +using Tango.MachineStudio.Common; using Tango.SharedUI; namespace Tango.MachineStudio.UI.SupervisingController { + /// <summary> + /// Represents a supervising controller pattern view contract. + /// </summary> + /// <seealso cref="Tango.SharedUI.IView" /> public interface IMainView : IView { - + /// <summary> + /// Navigates to the specified studio module. + /// </summary> + /// <param name="module">The module.</param> + void NavigateToModule(IStudioModule module); } } diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Tango.MachineStudio.UI.csproj b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Tango.MachineStudio.UI.csproj index df8b65fda..f48561e40 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Tango.MachineStudio.UI.csproj +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Tango.MachineStudio.UI.csproj @@ -120,6 +120,9 @@ <Generator>MSBuild:Compile</Generator> <SubType>Designer</SubType> </ApplicationDefinition> + <Compile Include="Notifications\TextInputBoxWindow.xaml.cs"> + <DependentUpon>TextInputBoxWindow.xaml</DependentUpon> + </Compile> <Compile Include="StudioApplication\DefaultStudioApplicationManager.cs" /> <Compile Include="Authentication\DefaultAuthenticationProvider.cs" /> <Compile Include="Modules\DefaultStudioModuleLoader.cs" /> @@ -157,6 +160,10 @@ <Compile Include="Views\ShutdownView.xaml.cs"> <DependentUpon>ShutdownView.xaml</DependentUpon> </Compile> + <Compile Include="Windows\ExceptionResolutions.cs" /> + <Compile Include="Windows\ExceptionWindow.xaml.cs"> + <DependentUpon>ExceptionWindow.xaml</DependentUpon> + </Compile> <Page Include="MainWindow.xaml"> <Generator>MSBuild:Compile</Generator> <SubType>Designer</SubType> @@ -172,6 +179,10 @@ <DependentUpon>MainWindow.xaml</DependentUpon> <SubType>Code</SubType> </Compile> + <Page Include="Notifications\TextInputBoxWindow.xaml"> + <Generator>MSBuild:Compile</Generator> + <SubType>Designer</SubType> + </Page> <Page Include="Notifications\MessageBoxWindow.xaml"> <SubType>Designer</SubType> <Generator>MSBuild:Compile</Generator> @@ -208,6 +219,10 @@ <SubType>Designer</SubType> <Generator>MSBuild:Compile</Generator> </Page> + <Page Include="Windows\ExceptionWindow.xaml"> + <SubType>Designer</SubType> + <Generator>MSBuild:Compile</Generator> + </Page> </ItemGroup> <ItemGroup> <Compile Include="Properties\AssemblyInfo.cs"> @@ -241,14 +256,14 @@ <Resource Include="design.ico" /> </ItemGroup> <ItemGroup> + <ProjectReference Include="..\..\SideChains\RealTimeGraphEx\RealTimeGraphEx.csproj"> + <Project>{b9ae25d6-be35-492f-9079-21a7f3e6f7cc}</Project> + <Name>RealTimeGraphEx</Name> + </ProjectReference> <ProjectReference Include="..\..\Tango.Core\Tango.Core.csproj"> <Project>{a34ee0f0-649d-41c8-8489-b6f1cc6924ee}</Project> <Name>Tango.Core</Name> </ProjectReference> - <ProjectReference Include="..\..\Tango.DAL.Observables\Tango.DAL.Observables.csproj"> - <Project>{0ecd6da8-7aa6-48d9-8b65-279d176ad9af}</Project> - <Name>Tango.DAL.Observables</Name> - </ProjectReference> <ProjectReference Include="..\..\Tango.DAL.Remote\Tango.DAL.Remote.csproj"> <Project>{38197109-8610-4d3f-92b9-16d48df94d7c}</Project> <Name>Tango.DAL.Remote</Name> @@ -277,6 +292,10 @@ <Project>{74e700b0-1156-4126-be40-ee450d3c3026}</Project> <Name>Tango.Transport</Name> </ProjectReference> + <ProjectReference Include="..\Modules\Tango.MachineStudio.DataCapture\Tango.MachineStudio.DataCapture.csproj"> + <Project>{fc337a7f-1214-41d8-9992-78092a3b961e}</Project> + <Name>Tango.MachineStudio.DataCapture</Name> + </ProjectReference> <ProjectReference Include="..\Modules\Tango.MachineStudio.DB\Tango.MachineStudio.DB.csproj"> <Project>{94f7acf8-55e1-4a02-b9bc-a818413fdbbf}</Project> <Name>Tango.MachineStudio.DB</Name> @@ -297,6 +316,10 @@ <Project>{12d0c43c-391f-4c74-92ab-82e9a9beeb9b}</Project> <Name>Tango.MachineStudio.Synchronization</Name> </ProjectReference> + <ProjectReference Include="..\Modules\Tango.MachineStudio.Technician\Tango.MachineStudio.Technician.csproj"> + <Project>{5d39c1e1-3ecd-4634-bd1b-2bcf71c54a15}</Project> + <Name>Tango.MachineStudio.Technician</Name> + </ProjectReference> <ProjectReference Include="..\Tango.MachineStudio.Common\Tango.MachineStudio.Common.csproj"> <Project>{cb0b0aa2-bb24-4bca-a720-45e397684e12}</Project> <Name>Tango.MachineStudio.Common</Name> @@ -312,12 +335,15 @@ <Resource Include="Images\account.png" /> </ItemGroup> <ItemGroup> - <Folder Include="Controls\" /> + <Resource Include="Images\White-Abstract.png" /> </ItemGroup> <ItemGroup> <Resource Include="Images\external-bridge-tcp.png" /> <Resource Include="Images\external-bridge-usb.png" /> </ItemGroup> + <ItemGroup> + <Resource Include="Images\exception.png" /> + </ItemGroup> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <PropertyGroup> <PostBuildEvent>$(TargetDir)linkgen.exe -s "$(TargetPath)" -d "$(TargetDir)Utilities\Machine Studio.lnk" diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModelLocator.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModelLocator.cs index 70912ba98..1907074c0 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModelLocator.cs +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModelLocator.cs @@ -5,10 +5,12 @@ using System; using Tango.Integration.Services; using Tango.Logging; using Tango.MachineStudio.Common.Authentication; +using Tango.MachineStudio.Common.Diagnostics; using Tango.MachineStudio.Common.Modules; using Tango.MachineStudio.Common.Navigation; using Tango.MachineStudio.Common.Notifications; using Tango.MachineStudio.Common.StudioApplication; +using Tango.MachineStudio.Common.Video; using Tango.MachineStudio.UI.Authentication; using Tango.MachineStudio.UI.Modules; using Tango.MachineStudio.UI.Navigation; @@ -17,6 +19,7 @@ using Tango.MachineStudio.UI.StudioApplication; using Tango.MachineStudio.UI.SupervisingController; using Tango.MachineStudio.UI.ViewModels; using Tango.MachineStudio.UI.Views; +using Tango.Settings; namespace Tango.MachineStudio.UI { @@ -50,6 +53,8 @@ namespace Tango.MachineStudio.UI SimpleIoc.Default.Unregister<IStudioModuleLoader>(); SimpleIoc.Default.Unregister<IStudioApplicationManager>(); SimpleIoc.Default.Unregister<ExternalBridgeScanner>(); + SimpleIoc.Default.Unregister<IVideoCaptureProvider>(); + SimpleIoc.Default.Unregister<IDiagnosticsFrameProvider>(); SimpleIoc.Default.Register<INotificationProvider, DefaultNotificationProvider>(); SimpleIoc.Default.Register<IAuthenticationProvider, DefaultAuthenticationProvider>(); @@ -57,6 +62,8 @@ namespace Tango.MachineStudio.UI SimpleIoc.Default.Register<IStudioModuleLoader, DefaultStudioModuleLoader>(); SimpleIoc.Default.Register<IStudioApplicationManager, DefaultStudioApplicationManager>(); SimpleIoc.Default.Register<ExternalBridgeScanner, ExternalBridgeScanner>(); + SimpleIoc.Default.Register<IVideoCaptureProvider, DefaultVideoCaptureProvider>(); + SimpleIoc.Default.Register<IDiagnosticsFrameProvider, DefaultDiagnosticsFrameProvider>(); SimpleIoc.Default.Register<MainViewVM>(); SimpleIoc.Default.Register<LoadingViewVM>(); @@ -65,9 +72,6 @@ namespace Tango.MachineStudio.UI SimpleIoc.Default.Register<MachineConnectionViewVM>(); SimpleIoc.Default.Register<MachineLoginViewVM>(); - LogManager.RegisterLogger(new VSOutputLogger()); - LogManager.RegisterLogger(new FileLogger()); - //Register View (Supervising Controller Pattern). if (!ViewModelBase.IsInDesignModeStatic) { diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/LoadingViewVM.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/LoadingViewVM.cs index f213af0d4..55a54e8aa 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/LoadingViewVM.cs +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/LoadingViewVM.cs @@ -4,8 +4,8 @@ using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; -using Tango.Core.Threading; -using Tango.DAL.Observables; +using Tango.Core.Helpers; +using Tango.Integration.Observables; using Tango.MachineStudio.Common.Modules; using Tango.MachineStudio.Common.Navigation; using Tango.MachineStudio.Common.Notifications; @@ -13,12 +13,22 @@ using Tango.SharedUI; namespace Tango.MachineStudio.UI.ViewModels { + /// <summary> + /// Represents the Machine Studio loading view, view model. + /// </summary> + /// <seealso cref="Tango.SharedUI.ViewModel" /> public class LoadingViewVM : ViewModel { private INotificationProvider _notificationProvider; private INavigationManager _navigationManager; private IStudioModuleLoader _studioModuleLoader; + /// <summary> + /// Initializes a new instance of the <see cref="LoadingViewVM"/> class. + /// </summary> + /// <param name="navigationManager">The navigation manager.</param> + /// <param name="studioModuleLoader">The studio module loader.</param> + /// <param name="notificationProvider">The notification provider.</param> public LoadingViewVM(INavigationManager navigationManager, IStudioModuleLoader studioModuleLoader, INotificationProvider notificationProvider) { _navigationManager = navigationManager; @@ -27,9 +37,12 @@ namespace Tango.MachineStudio.UI.ViewModels Load(); } + /// <summary> + /// Load application modules. + /// </summary> private void Load() { - StaThreadHelper.StartStaThread(() => + ThreadsHelper.StartStaThread(() => { try { diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/LoginViewVM.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/LoginViewVM.cs index 6fe90fa99..c5936eea8 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/LoginViewVM.cs +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/LoginViewVM.cs @@ -16,6 +16,10 @@ using Tango.SharedUI; namespace Tango.MachineStudio.UI.ViewModels { + /// <summary> + /// Represents the Machine Studio login view, view model. + /// </summary> + /// <seealso cref="Tango.SharedUI.ViewModel" /> public class LoginViewVM : ViewModel { private IAuthenticationProvider _authenticationProvider; @@ -24,6 +28,9 @@ namespace Tango.MachineStudio.UI.ViewModels private Rfc2898Cryptographer cryptographer; private String _email; + /// <summary> + /// Gets or sets the email. + /// </summary> [Required(ErrorMessage = "Email is required")] [EmailAddress(ErrorMessage = "Please enter a valid email")] public String Email @@ -33,16 +40,26 @@ namespace Tango.MachineStudio.UI.ViewModels } private bool _rememberMe; - + /// <summary> + /// Gets or sets a value indicating whether to remember the last user email and password. + /// </summary> public bool RememberMe { get { return _rememberMe; } set { _rememberMe = value; RaisePropertyChangedAuto(); } } - + /// <summary> + /// Gets or sets the login command. + /// </summary> public RelayCommand<String> LoginCommand { get; set; } + /// <summary> + /// Initializes a new instance of the <see cref="LoginViewVM"/> class. + /// </summary> + /// <param name="authenticationProvider">The authentication provider.</param> + /// <param name="navigationManager">The navigation manager.</param> + /// <param name="notificationProvider">The notification provider.</param> public LoginViewVM(IAuthenticationProvider authenticationProvider, INavigationManager navigationManager, INotificationProvider notificationProvider) { _notificationProvider = notificationProvider; @@ -55,6 +72,10 @@ namespace Tango.MachineStudio.UI.ViewModels RememberMe = SettingsManager.Default.MachineStudio.RememberMe; } + /// <summary> + /// Logins the requested user. + /// </summary> + /// <param name="password">The password.</param> private void Login(String password) { if (Validate()) diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/MachineConnectionViewVM.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/MachineConnectionViewVM.cs index b8b888e86..23be8d274 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/MachineConnectionViewVM.cs +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/MachineConnectionViewVM.cs @@ -10,10 +10,16 @@ using Tango.SharedUI; namespace Tango.MachineStudio.UI.ViewModels { + /// <summary> + /// Represents the Machine Studio connection dialog, view model. + /// </summary> + /// <seealso cref="Tango.MachineStudio.Common.Notifications.DialogViewVM" /> public class MachineConnectionViewVM : DialogViewVM { private ExternalBridgeScanner _scanner; - + /// <summary> + /// Gets or sets the machine scanner. + /// </summary> public ExternalBridgeScanner Scanner { get { return _scanner; } @@ -21,15 +27,24 @@ namespace Tango.MachineStudio.UI.ViewModels } private IExternalBridgeClient _selectedMachine; - + /// <summary> + /// Gets or sets the selected machine. + /// </summary> public IExternalBridgeClient SelectedMachine { get { return _selectedMachine; } set { _selectedMachine = value; RaisePropertyChangedAuto(); InvalidateRelayCommands(); } } + /// <summary> + /// Gets or sets the connect command. + /// </summary> public RelayCommand ConnectCommand { get; set; } + /// <summary> + /// Initializes a new instance of the <see cref="MachineConnectionViewVM"/> class. + /// </summary> + /// <param name="scanner">The scanner.</param> public MachineConnectionViewVM(ExternalBridgeScanner scanner) { Scanner = scanner; @@ -37,6 +52,9 @@ namespace Tango.MachineStudio.UI.ViewModels Scanner.Start(); } + /// <summary> + /// Connect to the currently selected machine. + /// </summary> private void Connect() { if (SelectedMachine != null) @@ -45,10 +63,12 @@ namespace Tango.MachineStudio.UI.ViewModels } } + /// <summary> + /// Called when the dialog has been shown. + /// </summary> public override void OnShow() { base.OnShow(); - Scanner.AvailableMachines.Clear(); } } diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/MachineLoginViewVM.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/MachineLoginViewVM.cs index a6ee9ee2a..20c2e3afb 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/MachineLoginViewVM.cs +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/MachineLoginViewVM.cs @@ -8,20 +8,40 @@ using Tango.MachineStudio.Common.Notifications; namespace Tango.MachineStudio.UI.ViewModels { + /// <summary> + /// Represents the machine login dialog, view model. + /// </summary> + /// <seealso cref="Tango.MachineStudio.Common.Notifications.DialogViewVM" /> public class MachineLoginViewVM : DialogViewVM { + /// <summary> + /// Gets or sets the machine password. + /// </summary> public String Password { get; set; } + /// <summary> + /// Gets or sets the login command. + /// </summary> public RelayCommand<String> LoginCommand { get; set; } + /// <summary> + /// Gets or sets the cancel command. + /// </summary> public RelayCommand CancelCommand { get; set; } + /// <summary> + /// Initializes a new instance of the <see cref="MachineLoginViewVM"/> class. + /// </summary> public MachineLoginViewVM() { LoginCommand = new RelayCommand<string>(Login); CancelCommand = new RelayCommand(Cancel); } + /// <summary> + /// Invoked when user presses the login button. + /// </summary> + /// <param name="password">The password.</param> private void Login(string password) { Password = password; diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/MainViewVM.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/MainViewVM.cs index b21b23935..679ba5ff3 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/MainViewVM.cs +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/MainViewVM.cs @@ -1,4 +1,5 @@ -using System; +using GalaSoft.MvvmLight.Ioc; +using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.IO; @@ -7,6 +8,7 @@ using System.Reflection; using System.Text; using System.Threading.Tasks; using Tango.Core.Commands; +using Tango.Integration.Services; using Tango.Logging; using Tango.MachineStudio.Common; using Tango.MachineStudio.Common.Authentication; @@ -22,12 +24,19 @@ using Tango.Transport.Adapters; namespace Tango.MachineStudio.UI.ViewModels { + /// <summary> + /// Represents the Machine Studio main view, view model. + /// </summary> + /// <seealso cref="Tango.SharedUI.ViewModel{Tango.MachineStudio.UI.SupervisingController.IMainView}" /> public class MainViewVM : ViewModel<IMainView> { private IStudioModule _currentModule; private INavigationManager _navigation; private bool _isDisconnecting; + /// <summary> + /// Gets or sets the current loaded module. + /// </summary> public IStudioModule CurrentModule { get { return _currentModule; } @@ -35,33 +44,54 @@ namespace Tango.MachineStudio.UI.ViewModels } private bool _isModuleLoaded; - + /// <summary> + /// Gets or sets a value indicating whether any module is loaded at the moment. + /// </summary> public bool IsModuleLoaded { get { return _isModuleLoaded; } set { _isModuleLoaded = value; RaisePropertyChangedAuto(); } } - private bool _isMenuOpened; - + /// <summary> + /// Gets or sets a value indicating whether the side menu is opened. + /// </summary> public bool IsMenuOpened { get { return _isMenuOpened; } set { _isMenuOpened = value; RaisePropertyChangedAuto(); } } + /// <summary> + /// Gets or sets the start module command. + /// </summary> public RelayCommand<IStudioModule> StartModuleCommand { get; set; } + /// <summary> + /// Gets or sets the home command. + /// </summary> public RelayCommand HomeCommand { get; set; } + /// <summary> + /// Gets or sets the connect command. + /// </summary> public RelayCommand ConnectCommand { get; set; } + /// <summary> + /// Gets or sets the disconnect command. + /// </summary> public RelayCommand DisconnectCommand { get; set; } + /// <summary> + /// Gets or sets the sign-out command. + /// </summary> public RelayCommand SignoutCommand { get; set; } private IAuthenticationProvider _authenticationProvider; + /// <summary> + /// Gets or sets the authentication provider. + /// </summary> public IAuthenticationProvider AuthenticationProvider { get { return _authenticationProvider; } @@ -69,7 +99,9 @@ namespace Tango.MachineStudio.UI.ViewModels } private IStudioModuleLoader _studioModuleLoader; - + /// <summary> + /// Gets or sets the studio module loader. + /// </summary> public IStudioModuleLoader StudioModuleLoader { get { return _studioModuleLoader; } @@ -77,7 +109,9 @@ namespace Tango.MachineStudio.UI.ViewModels } private INotificationProvider _notificationProvider; - + /// <summary> + /// Gets or sets the notification provider. + /// </summary> public INotificationProvider NotificationProvider { get { return _notificationProvider; } @@ -85,15 +119,24 @@ namespace Tango.MachineStudio.UI.ViewModels } private IStudioApplicationManager _applicationManager; - + /// <summary> + /// Gets or sets the application manager. + /// </summary> public IStudioApplicationManager ApplicationManager { get { return _applicationManager; } set { _applicationManager = value; RaisePropertyChangedAuto(); } } - - + /// <summary> + /// Initializes a new instance of the <see cref="MainViewVM"/> class. + /// </summary> + /// <param name="view">The view.</param> + /// <param name="authenticationProvider">The authentication provider.</param> + /// <param name="studioModuleLoader">The studio module loader.</param> + /// <param name="notificationProvider">The notification provider.</param> + /// <param name="applicationManager">The application manager.</param> + /// <param name="navigationManager">The navigation manager.</param> public MainViewVM( IMainView view, IAuthenticationProvider authenticationProvider, @@ -116,6 +159,9 @@ namespace Tango.MachineStudio.UI.ViewModels DisconnectCommand = new RelayCommand(DisconnectFromMachine, (x) => ApplicationManager.IsMachineConnected && !_isDisconnecting); } + /// <summary> + /// Disconnected from the current connected machine. + /// </summary> private async void DisconnectFromMachine() { using (_notificationProvider.PushTaskItem("Disconnecting from machine...")) @@ -129,6 +175,9 @@ namespace Tango.MachineStudio.UI.ViewModels } } + /// <summary> + /// Signs-out the current logged-in user. + /// </summary> private void SignOut() { _authenticationProvider.Logout(); @@ -137,6 +186,9 @@ namespace Tango.MachineStudio.UI.ViewModels IsMenuOpened = false; } + /// <summary> + /// Opens the machine connection dialog to allow the user to scan and connect to remote machines view USB/TCP. + /// </summary> private void ConnectToMachine() { _notificationProvider.ShowModalDialog<MachineConnectionViewVM>(async (x) => @@ -152,17 +204,17 @@ namespace Tango.MachineStudio.UI.ViewModels } } - if (x.SelectedMachine.Type != Integration.Services.ExternalBridgeClientType.USB) + if (x.SelectedMachine.RequiresAuthentication) { _notificationProvider.ShowModalDialog<MachineLoginViewVM>(async (login) => { - using (NotificationProvider.PushTaskItem("Connecting to machine " + x.SelectedMachine.SerialNumber + "...")) + using (NotificationProvider.PushTaskItem("Connecting to machine " + x.SelectedMachine.ToString() + "...")) { try { await x.SelectedMachine.Connect(); - var authenticated = await x.SelectedMachine.Authenticate(login.Password); + var authenticated = await x.SelectedMachine.As<IExternalBridgeSecureClient>().Authenticate(login.Password); if (!authenticated) { _notificationProvider.ShowError("It seems like you are not authorized to access the selected machine."); @@ -184,7 +236,7 @@ namespace Tango.MachineStudio.UI.ViewModels } else { - using (NotificationProvider.PushTaskItem("Connecting to machine " + x.SelectedMachine.Device + "...")) + using (NotificationProvider.PushTaskItem("Connecting to " + x.SelectedMachine.ToString() + "...")) { try { @@ -208,26 +260,44 @@ namespace Tango.MachineStudio.UI.ViewModels }); } + /// <summary> + /// Navigates to the home screen. + /// </summary> private void Home() { StartModule(null); } - private void StartModule(IStudioModule module) + /// <summary> + /// Starts the specified module. + /// </summary> + /// <param name="module">The module.</param> + internal void StartModule(IStudioModule module) { IsMenuOpened = false; + foreach (var m in StudioModuleLoader.AllModules.Where(x => x != module)) + { + m.IsLoaded = false; + } + if (module != null) { CurrentModule = module; + CurrentModule.IsLoaded = true; IsModuleLoaded = true; + View.NavigateToModule(module); } else { IsModuleLoaded = false; + View.NavigateToModule(null); } } + /// <summary> + /// Called when the <see cref="T:Tango.SharedUI.IView" /> is loaded and attached. + /// </summary> protected override void OnViewAttached() { base.OnViewAttached(); diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/ShutdownViewVM.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/ShutdownViewVM.cs index c7a919a82..ed771f00a 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/ShutdownViewVM.cs +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModels/ShutdownViewVM.cs @@ -6,6 +6,9 @@ using System.Threading.Tasks; namespace Tango.MachineStudio.UI.ViewModels { + /// <summary> + /// Represents the Machine Studio shutdown view, view model. + /// </summary> public class ShutdownViewVM { } diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/LoadingView.xaml b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/LoadingView.xaml index 459c8fde8..2478c1155 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/LoadingView.xaml +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/LoadingView.xaml @@ -6,7 +6,7 @@ xmlns:mahapps="http://metro.mahapps.com/winfx/xaml/controls" xmlns:local="clr-namespace:Tango.MachineStudio.UI.Views" mc:Ignorable="d" - d:DesignHeight="720" d:DesignWidth="1280" Cursor="Wait" DataContext="{Binding LoadingViewVM, Source={StaticResource Locator}}" Background="White"> + d:DesignHeight="720" d:DesignWidth="1280" Cursor="Wait" DataContext="{Binding LoadingViewVM, Source={StaticResource Locator}}" Background="Transparent"> <Grid> <Grid HorizontalAlignment="Center" VerticalAlignment="Center"> <StackPanel> diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/LoginView.xaml b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/LoginView.xaml index 1531370af..84ba597f2 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/LoginView.xaml +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/LoginView.xaml @@ -7,7 +7,7 @@ xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes" xmlns:local="clr-namespace:Tango.MachineStudio.UI.Views" mc:Ignorable="d" - d:DesignHeight="720" d:DesignWidth="1280" DataContext="{Binding LoginViewVM, Source={StaticResource Locator}}" Background="White"> + d:DesignHeight="720" d:DesignWidth="1280" DataContext="{Binding LoginViewVM, Source={StaticResource Locator}}" Background="Transparent"> <UserControl.Resources> <rules:Required x:Key="Required"></rules:Required> diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/MachineConnectionView.xaml b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/MachineConnectionView.xaml index 4208c2878..1626e67ef 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/MachineConnectionView.xaml +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/MachineConnectionView.xaml @@ -5,6 +5,7 @@ xmlns:mahapps="http://metro.mahapps.com/winfx/xaml/controls" xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" + xmlns:integration="clr-namespace:Tango.Integration.Services;assembly=Tango.Integration" xmlns:converters="clr-namespace:Tango.SharedUI.Converters;assembly=Tango.SharedUI" xmlns:local="clr-namespace:Tango.MachineStudio.UI.Views" mc:Ignorable="d" @@ -43,7 +44,7 @@ </Grid.RowDefinitions> <Grid> - <TextBlock VerticalAlignment="Center" Margin="0 0 0 0" Text="Scanning for machine on your local network..."></TextBlock> + <TextBlock VerticalAlignment="Center" Margin="0 0 0 0" Text="Scanning for machines on your local environment..."></TextBlock> <!--<Button Command="{Binding ScanCommand}" HorizontalAlignment="Right" Width="40" Padding="0" Style="{StaticResource MaterialDesignFlatButton}" Foreground="Black" ToolTip="Scan"> <materialDesign:PackIcon Kind="Refresh" Width="24" Height="24"></materialDesign:PackIcon> @@ -51,21 +52,15 @@ </Grid> <Grid Grid.Row="1"> - <ListBox ItemsSource="{Binding Scanner.AvailableMachines}" SelectedItem="{Binding SelectedMachine}" Margin="0 0 0 7" BorderThickness="1" BorderBrush="Gainsboro"> - <ListBox.ItemTemplate> - <DataTemplate> - <Grid> + <ListBox ItemsSource="{Binding Scanner.AvailableMachines}" SelectedItem="{Binding SelectedMachine}" Margin="0 0 0 7" BorderThickness="1" BorderBrush="Gainsboro" HorizontalContentAlignment="Stretch"> + <ListBox.Resources> + <DataTemplate DataType="{x:Type integration:ExternalBridgeTcpClient}"> + <DockPanel> + <StackPanel Orientation="Vertical" VerticalAlignment="Center" DockPanel.Dock="Right" ToolTip="Allow incoming diagnostics data"> + <ToggleButton IsChecked="{Binding EnableDiagnostics}" VerticalAlignment="Center"></ToggleButton> + <TextBlock VerticalAlignment="Center" FontSize="10">Diagnostics</TextBlock> + </StackPanel> <StackPanel Orientation="Horizontal"> - <StackPanel.Style> - <Style TargetType="StackPanel"> - <Setter Property="Visibility" Value="Visible"></Setter> - <Style.Triggers> - <DataTrigger Binding="{Binding Type}" Value="USB"> - <Setter Property="Visibility" Value="Collapsed"></Setter> - </DataTrigger> - </Style.Triggers> - </Style> - </StackPanel.Style> <Image Source="/Images/external-bridge-tcp.png" Width="38" Height="38" RenderOptions.BitmapScalingMode="Fant"></Image> <StackPanel Margin="10 0 0 0"> <TextBlock FontSize="11"> @@ -79,18 +74,15 @@ </TextBlock> </StackPanel> </StackPanel> - + </DockPanel> + </DataTemplate> + <DataTemplate DataType="{x:Type integration:ExternalBridgeUsbClient}"> + <DockPanel> + <StackPanel Orientation="Vertical" VerticalAlignment="Center" DockPanel.Dock="Right" ToolTip="Allow incoming diagnostics data"> + <ToggleButton IsChecked="{Binding EnableDiagnostics}" VerticalAlignment="Center"></ToggleButton> + <TextBlock VerticalAlignment="Center" FontSize="10">Diagnostics</TextBlock> + </StackPanel> <StackPanel Orientation="Horizontal"> - <StackPanel.Style> - <Style TargetType="StackPanel"> - <Setter Property="Visibility" Value="Collapsed"></Setter> - <Style.Triggers> - <DataTrigger Binding="{Binding Type}" Value="USB"> - <Setter Property="Visibility" Value="Visible"></Setter> - </DataTrigger> - </Style.Triggers> - </Style> - </StackPanel.Style> <Image Source="/Images/external-bridge-usb.png" Width="38" Height="38" RenderOptions.BitmapScalingMode="Fant"></Image> <StackPanel Margin="10 0 0 0"> <TextBlock FontSize="11"> @@ -101,9 +93,9 @@ </TextBlock> </StackPanel> </StackPanel> - </Grid> + </DockPanel> </DataTemplate> - </ListBox.ItemTemplate> + </ListBox.Resources> </ListBox> <mahapps:MetroProgressBar VerticalAlignment="Bottom" Height="1" IsIndeterminate="True"></mahapps:MetroProgressBar> diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/MainView.xaml b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/MainView.xaml index d7d0f8dc3..479052cc5 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/MainView.xaml +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/MainView.xaml @@ -4,6 +4,7 @@ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mahapps="http://metro.mahapps.com/winfx/xaml/controls" + xmlns:converters="clr-namespace:Tango.SharedUI.Converters;assembly=Tango.SharedUI" xmlns:dockablz="clr-namespace:Dragablz.Dockablz;assembly=Dragablz" xmlns:dragablz="clr-namespace:Dragablz;assembly=Dragablz" xmlns:controls="clr-namespace:Tango.SharedUI.Controls;assembly=Tango.SharedUI" @@ -12,7 +13,12 @@ xmlns:db="clr-namespace:Tango.MachineStudio.DB.Views;assembly=Tango.MachineStudio.DB" xmlns:local="clr-namespace:Tango.MachineStudio.UI.Views" mc:Ignorable="d" - d:DesignHeight="720" d:DesignWidth="1270" Background="White" DataContext="{Binding MainViewVM, Source={StaticResource Locator}}"> + d:DesignHeight="720" d:DesignWidth="1270" Background="Transparent" DataContext="{Binding MainViewVM, Source={StaticResource Locator}}"> + + <UserControl.Resources> + <converters:StringEllipsisConverter x:Key="StringEllipsisConverter" /> + </UserControl.Resources> + <Grid> <Grid.Style> <Style TargetType="Grid"> @@ -125,8 +131,23 @@ </StackPanel> <Grid HorizontalAlignment="Right"> - <StackPanel Orientation="Horizontal"> - <Button Margin="10 0 0 0" Style="{StaticResource MaterialDesignFlatButton}" FontSize="12" ToolTip="Connect to machine on the local network" BorderThickness="0" Command="{Binding ConnectCommand}"> + <StackPanel Orientation="Horizontal" VerticalAlignment="Center"> + <Grid Margin="0 0 20 0"> + <ItemsControl ItemsSource="{Binding NotificationProvider.BarItems}"> + <ItemsControl.ItemsPanel> + <ItemsPanelTemplate> + <StackPanel Orientation="Horizontal" IsItemsHost="True" VerticalAlignment="Center"></StackPanel> + </ItemsPanelTemplate> + </ItemsControl.ItemsPanel> + <ItemsControl.ItemTemplate> + <DataTemplate> + <ContentControl Margin="0 0 10 0" Content="{Binding Element}" VerticalAlignment="Center"></ContentControl> + </DataTemplate> + </ItemsControl.ItemTemplate> + </ItemsControl> + </Grid> + + <Button VerticalAlignment="Center" Margin="10 0 0 0" Style="{StaticResource MaterialDesignFlatButton}" FontSize="12" ToolTip="Connect to machine on the local network" BorderThickness="0" Command="{Binding ConnectCommand}"> <!--<Button.Background> <LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1"> <GradientStop Color="White" Offset="0.4" /> @@ -134,21 +155,25 @@ </LinearGradientBrush> </Button.Background>--> <StackPanel Orientation="Horizontal"> - <TextBlock Text="Machine Connection" VerticalAlignment="Center" Foreground="White"></TextBlock> - <materialDesign:PackIcon Margin="10 0 0 0" Width="16" Height="16"> - <materialDesign:PackIcon.Style> - <Style TargetType="materialDesign:PackIcon"> - <Setter Property="Foreground" Value="#FF6767"></Setter> - <Setter Property="Kind" Value="LanDisconnect"></Setter> - <Style.Triggers> - <DataTrigger Binding="{Binding ApplicationManager.IsMachineConnected,Mode=OneWay}" Value="True"> - <Setter Property="Foreground" Value="#03FF8E"></Setter> - <Setter Property="Kind" Value="LanConnect"></Setter> - </DataTrigger> - </Style.Triggers> - </Style> - </materialDesign:PackIcon.Style> - </materialDesign:PackIcon> + <Grid> + <StackPanel Orientation="Horizontal" VerticalAlignment="Center"> + <TextBlock Text="Machine Connection" VerticalAlignment="Center" Foreground="White"></TextBlock> + <materialDesign:PackIcon Margin="10 0 0 0" Width="24" Height="24"> + <materialDesign:PackIcon.Style> + <Style TargetType="materialDesign:PackIcon"> + <Setter Property="Foreground" Value="#333333"></Setter> + <Setter Property="Kind" Value="LanDisconnect"></Setter> + <Style.Triggers> + <DataTrigger Binding="{Binding ApplicationManager.IsMachineConnected,Mode=OneWay}" Value="True"> + <Setter Property="Foreground" Value="#03FF8E"></Setter> + <Setter Property="Kind" Value="LanConnect"></Setter> + </DataTrigger> + </Style.Triggers> + </Style> + </materialDesign:PackIcon.Style> + </materialDesign:PackIcon> + </StackPanel> + </Grid> </StackPanel> </Button> </StackPanel> @@ -165,90 +190,66 @@ </Grid.RowDefinitions> <Grid Grid.Row="1"> - <Grid.RowDefinitions> - <RowDefinition Height="150"/> - <RowDefinition Height="*"/> - </Grid.RowDefinitions> - <Grid> - <StackPanel Margin="30 20" HorizontalAlignment="Left"> - <TextBlock Style="{StaticResource MaterialDesignDisplay1TextBlock}">Welcome to Machine Studio</TextBlock> - <TextBlock HorizontalAlignment="Right" Margin="0 5 -130 0" FontStyle="Italic" Style="{StaticResource MaterialDesignSubheadingTextBlock}" Foreground="{StaticResource AccentColorBrush}">Select Your Studio Module...</TextBlock> - </StackPanel> - </Grid> - <ItemsControl ItemsSource="{Binding StudioModuleLoader.UserModules}" Grid.Row="2" Margin="10"> - <ItemsControl.ItemsPanel> - <ItemsPanelTemplate> - <WrapPanel IsItemsHost="True"></WrapPanel> - </ItemsPanelTemplate> - </ItemsControl.ItemsPanel> - - <ItemsControl.ItemTemplate> - <DataTemplate> - <materialDesign:Card Width="300" Margin="10" Height="400"> - <Grid > - <Grid.RowDefinitions> - <RowDefinition Height="180" /> - <RowDefinition Height="*" /> - <RowDefinition Height="Auto" /> - </Grid.RowDefinitions> - <Image Source="{Binding Image,Mode=OneWay}" Stretch="Fill" RenderOptions.BitmapScalingMode="Fant" /> - <Button Command="{Binding RelativeSource={RelativeSource AncestorType=UserControl},Path=DataContext.StartModuleCommand}" CommandParameter="{Binding}" Grid.Row="0" Margin="0,0,20,-35" HorizontalAlignment="Right" Width="70" Height="70" VerticalAlignment="Bottom" Style="{StaticResource MaterialDesignFloatingActionMiniButton}" ToolTip="Start This Module"> - <materialDesign:PackIcon Kind="Play" Width="30" Height="30" /> - </Button> - <StackPanel Grid.Row="1" Margin="8,24,8,0"> - <TextBlock FontWeight="Bold" FontSize="20" Text="{Binding Name,Mode=OneWay}"></TextBlock> - <TextBlock VerticalAlignment="Center" Margin="0 5 0 0" FontSize="14" TextWrapping="Wrap" Text="{Binding Description,Mode=OneWay}"></TextBlock> - </StackPanel> - <StackPanel Grid.Row="2" Margin="8" HorizontalAlignment="Right" Orientation="Horizontal"> - <materialDesign:PopupBox Padding="2,0,2,0" Style="{StaticResource MaterialDesignToolPopupBox}"> - <StackPanel> - <Button Content="More" /> - <Button Content="Options" /> - </StackPanel> - </materialDesign:PopupBox> + <controls:MultiTransitionControl x:Name="TransitionControl" AlwaysFade="True" TransitionType="Zoom"> + <controls:MultiTransitionControl.Controls> + <ContentControl Tag="Home"> + <Grid> + <Grid.RowDefinitions> + <RowDefinition Height="150"/> + <RowDefinition Height="*"/> + </Grid.RowDefinitions> + <Grid> + <StackPanel Margin="30 20" HorizontalAlignment="Left"> + <TextBlock Style="{StaticResource MaterialDesignDisplay1TextBlock}">Welcome to Machine Studio</TextBlock> + <TextBlock HorizontalAlignment="Right" Margin="0 5 -130 0" FontStyle="Italic" Style="{StaticResource MaterialDesignSubheadingTextBlock}" Foreground="{StaticResource AccentColorBrush}">Select Your Studio Module...</TextBlock> </StackPanel> </Grid> - </materialDesign:Card> - </DataTemplate> - </ItemsControl.ItemTemplate> - </ItemsControl> - </Grid> - <Grid Grid.Row="1" RenderTransformOrigin="0.5,0.5"> - <Grid.Style> - <Style TargetType="Grid"> - <Setter Property="RenderTransform"> - <Setter.Value> - <ScaleTransform ScaleX="0" ScaleY="0"></ScaleTransform> - </Setter.Value> - </Setter> - <Setter Property="Opacity" Value="0"></Setter> + <Grid Grid.Row="2"> + <ScrollViewer HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto"> + <ItemsControl ItemsSource="{Binding StudioModuleLoader.UserModules}" Margin="10"> + <ItemsControl.ItemsPanel> + <ItemsPanelTemplate> + <WrapPanel IsItemsHost="True"></WrapPanel> + </ItemsPanelTemplate> + </ItemsControl.ItemsPanel> - <Style.Triggers> - <DataTrigger Binding="{Binding IsModuleLoaded}" Value="False"> - <DataTrigger.EnterActions> - <BeginStoryboard> - <Storyboard> - <DoubleAnimation Storyboard.TargetProperty="RenderTransform.ScaleX" To="0" Duration="00:00:0.5"></DoubleAnimation> - <DoubleAnimation Storyboard.TargetProperty="RenderTransform.ScaleY" To="0" Duration="00:00:0.5"></DoubleAnimation> - <DoubleAnimation Storyboard.TargetProperty="Opacity" To="0" Duration="00:00:0.5"></DoubleAnimation> - </Storyboard> - </BeginStoryboard> - </DataTrigger.EnterActions> - <DataTrigger.ExitActions> - <BeginStoryboard> - <Storyboard> - <DoubleAnimation Storyboard.TargetProperty="RenderTransform.ScaleX" To="1" Duration="00:00:0.5"></DoubleAnimation> - <DoubleAnimation Storyboard.TargetProperty="RenderTransform.ScaleY" To="1" Duration="00:00:0.5"></DoubleAnimation> - <DoubleAnimation Storyboard.TargetProperty="Opacity" To="1" Duration="00:00:0.5"></DoubleAnimation> - </Storyboard> - </BeginStoryboard> - </DataTrigger.ExitActions> - </DataTrigger> - </Style.Triggers> - </Style> - </Grid.Style> - <ContentPresenter Content="{Binding CurrentModule.MainView}"/> + <ItemsControl.ItemTemplate> + <DataTemplate> + <materialDesign:Card Width="300" Margin="10" Height="400"> + <Grid > + <Grid.RowDefinitions> + <RowDefinition Height="180" /> + <RowDefinition Height="*" /> + <RowDefinition Height="Auto" /> + </Grid.RowDefinitions> + <Image Source="{Binding Image,Mode=OneWay}" Stretch="Fill" RenderOptions.BitmapScalingMode="Fant" /> + <Button Command="{Binding RelativeSource={RelativeSource AncestorType=UserControl},Path=DataContext.StartModuleCommand}" CommandParameter="{Binding}" Grid.Row="0" Margin="0,0,20,-35" HorizontalAlignment="Right" Width="70" Height="70" VerticalAlignment="Bottom" Style="{StaticResource MaterialDesignFloatingActionMiniButton}" ToolTip="Start This Module"> + <materialDesign:PackIcon Kind="Play" Width="30" Height="30" /> + </Button> + <StackPanel Grid.Row="1" Margin="8,24,8,0"> + <TextBlock FontWeight="Bold" FontSize="20" Text="{Binding Name,Mode=OneWay}"></TextBlock> + <TextBlock VerticalAlignment="Center" Margin="0 5 0 0" FontSize="14" TextWrapping="Wrap" Text="{Binding Description,Mode=OneWay}"></TextBlock> + </StackPanel> + <StackPanel Grid.Row="2" Margin="8" HorizontalAlignment="Right" Orientation="Horizontal"> + <materialDesign:PopupBox Padding="2,0,2,0" Style="{StaticResource MaterialDesignToolPopupBox}"> + <StackPanel> + <Button Content="More" /> + <Button Content="Options" /> + </StackPanel> + </materialDesign:PopupBox> + </StackPanel> + </Grid> + </materialDesign:Card> + </DataTemplate> + </ItemsControl.ItemTemplate> + </ItemsControl> + </ScrollViewer> + </Grid> + </Grid> + </ContentControl> + </controls:MultiTransitionControl.Controls> + </controls:MultiTransitionControl> </Grid> </Grid> @@ -289,7 +290,7 @@ <StackPanel Orientation="Horizontal" VerticalAlignment="Center" Margin="20 0 0 0"> <mahapps:ProgressRing Width="24" Height="24" Foreground="White"></mahapps:ProgressRing> - <TextBlock Text="{Binding NotificationProvider.CurrentTaskItem.Message}" Foreground="White" VerticalAlignment="Center" Margin="10 0 0 0"></TextBlock> + <TextBlock Text="{Binding NotificationProvider.CurrentTaskItem.Message,Converter={StaticResource StringEllipsisConverter},ConverterParameter=35}" Foreground="White" VerticalAlignment="Center" Margin="10 0 0 0" TextWrapping="Wrap"></TextBlock> </StackPanel> </Border> </Grid> diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/MainView.xaml.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/MainView.xaml.cs index f52393e1c..e6e1557f3 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/MainView.xaml.cs +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/MainView.xaml.cs @@ -14,11 +14,17 @@ using System.Windows.Media.Animation; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; +using Tango.MachineStudio.Common.Modules; using Tango.MachineStudio.Common.Notifications; +using Tango.MachineStudio.UI.Modules; using Tango.MachineStudio.UI.Notifications; using Tango.MachineStudio.UI.SupervisingController; using Tango.SharedUI; using Tango.SharedUI.Controls; +using Tango.MachineStudio.Common; +using System.Threading; +using Tango.Core.Helpers; +using Tango.SharedUI.Helpers; namespace Tango.MachineStudio.UI.Views { @@ -27,9 +33,63 @@ namespace Tango.MachineStudio.UI.Views /// </summary> public partial class MainView : View, IMainView { + private DefaultStudioModuleLoader _loader; + public MainView() : base() { InitializeComponent(); + + _loader = ServiceLocator.Current.GetInstance<IStudioModuleLoader>() as DefaultStudioModuleLoader; + _loader.ModulesLoaded += Loader_ModulesLoaded; + } + + public void NavigateToModule(IStudioModule module) + { + TransitionControl.AutoNavigate(module != null ? module.Name : "Home"); + } + + private void Loader_ModulesLoaded(object sender, EventArgs e) + { + TransitionControl.Controls.RemoveAll((x) => x.Tag.ToString() != "Home"); + + Task.Factory.StartNew(() => + { + var item = ServiceLocator.Current.GetInstance<INotificationProvider>().PushTaskItem("Loading Modules..."); + + var modules = _loader.UserModules.ToList(); + + ThreadsHelper.InvokeUINow(() => + { + _loader.UserModules.Clear(); + }); + + Thread.Sleep(1500); + + foreach (var module in modules) + { + ThreadsHelper.InvokeUI(() => + { + TransitionControl.Controls.Add(new ContentControl() + { + Tag = module.Name, + Content = module.MainView + }); + + _loader.UserModules.Add(module); + }); + + UIHelper.DoEvents(); + + Thread.Sleep(100); + } + + ThreadsHelper.InvokeUI(() => + { + TransitionControl.RefreshControls(); + }); + + item.Pop(); + }); } } } diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/ShutdownView.xaml b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/ShutdownView.xaml index 487dfe1f8..dd86238ce 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/ShutdownView.xaml +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Views/ShutdownView.xaml @@ -6,7 +6,7 @@ xmlns:mahapps="http://metro.mahapps.com/winfx/xaml/controls" xmlns:local="clr-namespace:Tango.MachineStudio.UI.Views" mc:Ignorable="d" - d:DesignHeight="720" d:DesignWidth="1280" Cursor="Wait" Background="White" DataContext="{Binding ShutdownViewVM, Source={StaticResource Locator}}"> + d:DesignHeight="720" d:DesignWidth="1280" Cursor="Wait" Background="Transparent" DataContext="{Binding ShutdownViewVM, Source={StaticResource Locator}}"> <Grid> <Grid HorizontalAlignment="Center" VerticalAlignment="Center"> <StackPanel> diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Windows/ExceptionResolutions.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Windows/ExceptionResolutions.cs new file mode 100644 index 000000000..2e7327559 --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Windows/ExceptionResolutions.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.MachineStudio.UI.Windows +{ + public enum ExceptionResolutions + { + Shutdown, + Restart, + Ignore + } +} diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Windows/ExceptionWindow.xaml b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Windows/ExceptionWindow.xaml new file mode 100644 index 000000000..c08a08842 --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Windows/ExceptionWindow.xaml @@ -0,0 +1,61 @@ +<Window x:Class="Tango.MachineStudio.UI.Windows.ExceptionWindow" + xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + xmlns:d="http://schemas.microsoft.com/expression/blend/2008" + xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" + xmlns:local="clr-namespace:Tango.MachineStudio.UI.Windows" + mc:Ignorable="d" + WindowStyle="None" ResizeMode="NoResize" Topmost="True" AllowsTransparency="True" WindowStartupLocation="CenterScreen" d:DesignHeight="300" d:DesignWidth="300" Width="610" Height="410" Background="Transparent" d:DataContext="{d:DesignInstance Type=local:ExceptionWindow, IsDesignTimeCreatable=False}"> + <Grid> + <Border BorderThickness="1" BorderBrush="DodgerBlue" Background="White" Margin="10" CornerRadius="10"> + <Border.Effect> + <DropShadowEffect ShadowDepth="0" BlurRadius="10" /> + </Border.Effect> + <Grid> + <Grid.RowDefinitions> + <RowDefinition Height="80"/> + <RowDefinition Height="1*"/> + </Grid.RowDefinitions> + + <Grid> + <StackPanel Orientation="Horizontal" Margin="10"> + <Image Source="/Images/exception.png" RenderOptions.BitmapScalingMode="Fant"></Image> + <TextBlock Text="Machine Studio Error" VerticalAlignment="Center" Margin="10 0 0 0" FontSize="20"></TextBlock> + </StackPanel> + </Grid> + + <Grid Grid.Row="1" Margin="10 0 10 10"> + <Grid.RowDefinitions> + <RowDefinition Height="1*"/> + <RowDefinition Height="50"/> + </Grid.RowDefinitions> + + <Grid> + <Grid.RowDefinitions> + <RowDefinition Height="30"/> + <RowDefinition Height="223*"/> + </Grid.RowDefinitions> + + <Grid> + <TextBlock TextWrapping="Wrap" VerticalAlignment="Center" Margin="0 0 0 0"> + <Run>Machine Studio encountered an unexpected error. It is recommended to restart the application in order to resolve the issue.</Run> + </TextBlock> + </Grid> + + <Grid Grid.Row="1" Margin="0 10 0 0"> + <TextBox Style="{x:Null}" ScrollViewer.HorizontalScrollBarVisibility="Disabled" ScrollViewer.VerticalScrollBarVisibility="Auto" BorderBrush="#515151" IsReadOnly="True" AcceptsReturn="True" Foreground="#FF5C5C" Padding="2" TextWrapping="Wrap" Text="{Binding Exception}"></TextBox> + </Grid> + </Grid> + + <Grid Grid.Row="1"> + <Button HorizontalAlignment="Left" Width="140" Command="{Binding ResolveCommand}" CommandParameter="{x:Static local:ExceptionResolutions.Ignore}">Ignore</Button> + <StackPanel Orientation="Horizontal" HorizontalAlignment="Right"> + <Button Margin="5 0 0 0" Width="140" Command="{Binding ResolveCommand}" CommandParameter="{x:Static local:ExceptionResolutions.Shutdown}">Shutdown</Button> + <Button Margin="5 0 0 0" Width="140" Command="{Binding ResolveCommand}" CommandParameter="{x:Static local:ExceptionResolutions.Restart}">Restart</Button> + </StackPanel> + </Grid> + </Grid> + </Grid> + </Border> + </Grid> +</Window> diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Windows/ExceptionWindow.xaml.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Windows/ExceptionWindow.xaml.cs new file mode 100644 index 000000000..0f74fee17 --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Windows/ExceptionWindow.xaml.cs @@ -0,0 +1,48 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Shapes; +using Tango.Core.Commands; +using Tango.MachineStudio.UI.ViewModels; + +namespace Tango.MachineStudio.UI.Windows +{ + /// <summary> + /// Interaction logic for ExceptionWindow.xaml + /// </summary> + public partial class ExceptionWindow : Window + { + public ExceptionResolutions Resolution { get; set; } + + public String Exception { get; set; } + + public RelayCommand<ExceptionResolutions> ResolveCommand { get; set; } + + public ExceptionWindow() + { + InitializeComponent(); + DataContext = this; + } + + public ExceptionWindow(Exception ex) : this() + { + Exception = ex.FlattenException(); + ResolveCommand = new RelayCommand<ExceptionResolutions>(Resolve); + } + + private void Resolve(ExceptionResolutions resolution) + { + Resolution = resolution; + Close(); + } + } +} |
