diff --git a/src/Artemis.Core/Plugins/Abstract/Module.cs b/src/Artemis.Core/Plugins/Abstract/Module.cs
index 244e83ce6..9050f9646 100644
--- a/src/Artemis.Core/Plugins/Abstract/Module.cs
+++ b/src/Artemis.Core/Plugins/Abstract/Module.cs
@@ -20,6 +20,12 @@ namespace Artemis.Core.Plugins.Abstract
///
public string DisplayName { get; protected set; }
+ ///
+ /// The modules display icon that's shown in the menu see for available
+ /// icons
+ ///
+ public string DisplayIcon { get; set; }
+
///
/// Whether or not this module expands upon the main data model. If set to true any data in main data model can be
/// accessed by profiles in this module
diff --git a/src/Artemis.Plugins.Modules.General/GeneralModule.cs b/src/Artemis.Plugins.Modules.General/GeneralModule.cs
index c807b6878..c9a225ca3 100644
--- a/src/Artemis.Plugins.Modules.General/GeneralModule.cs
+++ b/src/Artemis.Plugins.Modules.General/GeneralModule.cs
@@ -14,6 +14,7 @@ namespace Artemis.Plugins.Modules.General
{
_settings = settings;
DisplayName = "General";
+ DisplayIcon = "AllInclusive";
ExpandsMainDataModel = true;
var testSetting = _settings.GetSetting("TestSetting", DateTime.Now);
diff --git a/src/Artemis.UI/App.xaml b/src/Artemis.UI/App.xaml
index 2497d359f..c46f01392 100644
--- a/src/Artemis.UI/App.xaml
+++ b/src/Artemis.UI/App.xaml
@@ -2,8 +2,7 @@
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:s="https://github.com/canton7/Stylet"
- xmlns:local="clr-namespace:Artemis.UI"
- xmlns:dragablz="http://dragablz.net/winfx/xaml/dragablz">
+ xmlns:local="clr-namespace:Artemis.UI">
@@ -13,62 +12,26 @@
-
-
-
-
-
-
-
-
+
+
+
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
..\packages\Castle.Core.4.4.0\lib\net45\Castle.Core.dll
-
- ..\packages\ControlzEx.3.0.2.4\lib\net462\ControlzEx.dll
-
-
- ..\packages\Dragablz.0.0.3.203\lib\net45\Dragablz.dll
-
..\packages\FluentValidation.8.5.0\lib\net45\FluentValidation.dll
@@ -81,19 +75,19 @@
..\packages\Humanizer.Core.2.6.2\lib\netstandard2.0\Humanizer.dll
-
- ..\packages\MahApps.Metro.1.6.5\lib\net47\MahApps.Metro.dll
-
..\packages\MaterialDesignColors.1.2.0\lib\net45\MaterialDesignColors.dll
-
- ..\packages\MaterialDesignThemes.MahApps.0.1.0\lib\net45\MaterialDesignThemes.MahApps.dll
+
+ ..\packages\MaterialDesignExtensions.2.8.0\lib\net45\MaterialDesignExtensions.dll
..\packages\MaterialDesignThemes.2.6.0\lib\net45\MaterialDesignThemes.Wpf.dll
+
+ ..\packages\System.Windows.Interactivity.WPF.2.0.20525\lib\net40\Microsoft.Expression.Interactions.dll
+
..\packages\Ninject.3.3.4\lib\net45\Ninject.dll
@@ -153,8 +147,8 @@
..\packages\System.ValueTuple.4.5.0\lib\net47\System.ValueTuple.dll
-
- ..\packages\ControlzEx.3.0.2.4\lib\net462\System.Windows.Interactivity.dll
+
+ ..\packages\System.Windows.Interactivity.WPF.2.0.20525\lib\net40\System.Windows.Interactivity.dll
@@ -181,6 +175,10 @@
+
+ SidebarView.xaml
+
+
@@ -307,6 +305,10 @@
Designer
MSBuild:Compile
+
+ Designer
+ MSBuild:Compile
+
Designer
MSBuild:Compile
diff --git a/src/Artemis.UI/Ninject/UiModule.cs b/src/Artemis.UI/Ninject/UiModule.cs
index cd64d319e..0d7773c65 100644
--- a/src/Artemis.UI/Ninject/UiModule.cs
+++ b/src/Artemis.UI/Ninject/UiModule.cs
@@ -7,7 +7,6 @@ using Artemis.UI.Stylet;
using Artemis.UI.ViewModels.Dialogs;
using FluentValidation;
using Ninject.Extensions.Conventions;
-using Ninject.Extensions.Factory;
using Ninject.Modules;
using Stylet;
@@ -26,8 +25,9 @@ namespace Artemis.UI.Ninject
{
x.FromThisAssembly()
.SelectAllClasses()
- .InheritedFrom()
- .BindAllInterfaces();
+ .InheritedFrom()
+ .BindAllBaseClasses()
+ .Configure(c => c.InSingletonScope());
});
// Bind all dialog VMs
diff --git a/src/Artemis.UI/Screens/GradientEditor/GradientEditorView.xaml b/src/Artemis.UI/Screens/GradientEditor/GradientEditorView.xaml
index db4b7c8c7..a43bd10aa 100644
--- a/src/Artemis.UI/Screens/GradientEditor/GradientEditorView.xaml
+++ b/src/Artemis.UI/Screens/GradientEditor/GradientEditorView.xaml
@@ -1,11 +1,11 @@
-
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/src/Artemis.UI/Screens/Home/HomeViewModel.cs b/src/Artemis.UI/Screens/Home/HomeViewModel.cs
index 339714fa4..2bbda6034 100644
--- a/src/Artemis.UI/Screens/Home/HomeViewModel.cs
+++ b/src/Artemis.UI/Screens/Home/HomeViewModel.cs
@@ -1,12 +1,17 @@
using System;
using System.Diagnostics;
-using Stylet;
+using MaterialDesignThemes.Wpf;
namespace Artemis.UI.Screens.Home
{
- public class HomeViewModel : Screen, IScreenViewModel
+ public class HomeViewModel : MainScreenViewModel
{
- public string Title => "Home";
+ public HomeViewModel()
+ {
+ DisplayName = "Home";
+ DisplayIcon = PackIconKind.Home;
+ DisplayOrder = 1;
+ }
public void OpenUrl(string url)
{
diff --git a/src/Artemis.UI/Screens/IScreenViewModel.cs b/src/Artemis.UI/Screens/IScreenViewModel.cs
index 71257977b..b0575c9be 100644
--- a/src/Artemis.UI/Screens/IScreenViewModel.cs
+++ b/src/Artemis.UI/Screens/IScreenViewModel.cs
@@ -1,9 +1,11 @@
-using Stylet;
+using MaterialDesignThemes.Wpf;
+using Stylet;
namespace Artemis.UI.Screens
{
- public interface IScreenViewModel : IScreen
+ public abstract class MainScreenViewModel : Screen
{
- string Title { get; }
+ public int DisplayOrder { get; set; }
+ public PackIconKind DisplayIcon { get; set; }
}
}
\ No newline at end of file
diff --git a/src/Artemis.UI/Screens/Module/ModuleRootView.xaml b/src/Artemis.UI/Screens/Module/ModuleRootView.xaml
index 399b44d17..2f4034e6c 100644
--- a/src/Artemis.UI/Screens/Module/ModuleRootView.xaml
+++ b/src/Artemis.UI/Screens/Module/ModuleRootView.xaml
@@ -3,7 +3,6 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
- xmlns:dragablz="http://dragablz.net/winfx/xaml/dragablz"
xmlns:s="https://github.com/canton7/Stylet"
xmlns:module="clr-namespace:Artemis.UI.Screens.Module"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
@@ -11,18 +10,17 @@
d:DesignHeight="450" d:DesignWidth="800"
d:DataContext="{d:DesignInstance module:ModuleRootViewModel}">
-
-
-
-
-
-
-
-
+
+
+
-
+
-
-
+
+
\ No newline at end of file
diff --git a/src/Artemis.UI/Screens/Module/ModuleRootViewModel.cs b/src/Artemis.UI/Screens/Module/ModuleRootViewModel.cs
index 07af5e8d9..5ca770c67 100644
--- a/src/Artemis.UI/Screens/Module/ModuleRootViewModel.cs
+++ b/src/Artemis.UI/Screens/Module/ModuleRootViewModel.cs
@@ -12,15 +12,15 @@ namespace Artemis.UI.Screens.Module
public ModuleRootViewModel(Core.Plugins.Abstract.Module module, IProfileEditorViewModelFactory profileEditorViewModelFactory)
{
+ DisplayName = module?.DisplayName;
Module = module;
+
_profileEditorViewModelFactory = profileEditorViewModelFactory;
Task.Run(AddTabsAsync);
}
- public string Title => Module?.DisplayName;
public Core.Plugins.Abstract.Module Module { get; }
- public int FixedHeaderCount => Items.Count;
private async Task AddTabsAsync()
{
diff --git a/src/Artemis.UI/Screens/News/NewsViewModel.cs b/src/Artemis.UI/Screens/News/NewsViewModel.cs
index 149d8d22a..01c190f3a 100644
--- a/src/Artemis.UI/Screens/News/NewsViewModel.cs
+++ b/src/Artemis.UI/Screens/News/NewsViewModel.cs
@@ -1,9 +1,15 @@
-using Stylet;
+using MaterialDesignThemes.Wpf;
+using Stylet;
namespace Artemis.UI.Screens.News
{
- public class NewsViewModel : Screen, IScreenViewModel
+ public class NewsViewModel : MainScreenViewModel
{
- public string Title => "News";
+ public NewsViewModel()
+ {
+ DisplayName = "News";
+ DisplayIcon = PackIconKind.Newspaper;
+ DisplayOrder = 2;
+ }
}
}
\ No newline at end of file
diff --git a/src/Artemis.UI/Screens/RootView.xaml b/src/Artemis.UI/Screens/RootView.xaml
index 7a7f20721..cb62adb8b 100644
--- a/src/Artemis.UI/Screens/RootView.xaml
+++ b/src/Artemis.UI/Screens/RootView.xaml
@@ -1,30 +1,26 @@
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
+
-
-
-
-
-
-
-
-
- Home
-
-
-
-
-
- News
-
-
-
-
-
- Workshop
-
-
-
-
-
- Surface Editor
-
-
-
-
-
- Settings
-
-
-
-
-
-
- Modules
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/src/Artemis.UI/Screens/RootViewModel.cs b/src/Artemis.UI/Screens/RootViewModel.cs
index bb3f6d05a..1e4f11a2a 100644
--- a/src/Artemis.UI/Screens/RootViewModel.cs
+++ b/src/Artemis.UI/Screens/RootViewModel.cs
@@ -1,18 +1,10 @@
-using System.Collections.Generic;
+using System;
using System.ComponentModel;
-using System.Linq;
+using System.Threading;
using System.Threading.Tasks;
using System.Windows;
-using System.Windows.Controls;
-using Artemis.Core.Events;
-using Artemis.Core.Services.Interfaces;
using Artemis.UI.Events;
-using Artemis.UI.Ninject.Factories;
-using Artemis.UI.Screens.Home;
-using Artemis.UI.Screens.News;
-using Artemis.UI.Screens.Settings;
-using Artemis.UI.Screens.SurfaceEditor;
-using Artemis.UI.Screens.Workshop;
+using Artemis.UI.Screens.Sidebar;
using Artemis.UI.Utilities;
using MaterialDesignThemes.Wpf;
using Stylet;
@@ -21,131 +13,53 @@ namespace Artemis.UI.Screens
{
public class RootViewModel : Conductor
{
- private readonly ICollection _artemisViewModels;
private readonly IEventAggregator _eventAggregator;
- private readonly IModuleViewModelFactory _moduleViewModelFactory;
- private readonly IPluginService _pluginService;
private bool _lostFocus;
- public RootViewModel(ICollection artemisViewModels,
- IPluginService pluginService,
- IModuleViewModelFactory moduleViewModelFactory,
- IEventAggregator eventAggregator)
+ public RootViewModel(IEventAggregator eventAggregator, SidebarViewModel sidebarViewModel)
{
- _artemisViewModels = artemisViewModels;
- _pluginService = pluginService;
- _moduleViewModelFactory = moduleViewModelFactory;
+ SidebarViewModel = sidebarViewModel;
_eventAggregator = eventAggregator;
- // Activate the home item
- ActiveItem = _artemisViewModels.First(v => v.GetType() == typeof(HomeViewModel));
- ActiveItemReady = true;
-
- // Sync up with the plugin service
- Modules = new BindableCollection();
- Modules.AddRange(_pluginService.GetPluginsOfType());
-
- _pluginService.PluginEnabled += PluginServiceOnPluginEnabled;
- _pluginService.PluginDisabled += PluginServiceOnPluginDisabled;
- PropertyChanged += OnSelectedModuleChanged;
- PropertyChanged += OnSelectedPageChanged;
-
var themeWatcher = new ThemeWatcher();
themeWatcher.ThemeChanged += (sender, args) => ApplyWindowsTheme(args.Theme);
ApplyWindowsTheme(themeWatcher.GetWindowsTheme());
+
+ ActiveItem = SidebarViewModel.SelectedItem;
+ ActiveItemReady = true;
+ SidebarViewModel.PropertyChanged += SidebarViewModelOnPropertyChanged;
}
+ private void SidebarViewModelOnPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName == nameof(SidebarViewModel.SelectedItem))
+ {
+ IsSidebarVisible = false;
+ ActiveItemReady = false;
+
+ // Allow the menu to close, it's slower but feels more responsive, funny how that works right
+ Execute.PostToUIThreadAsync(async () =>
+ {
+ await Task.Delay(400);
+ ActiveItem = SidebarViewModel.SelectedItem;
+ ActiveItemReady = true;
+ });
+ }
+ }
+
+ public SidebarViewModel SidebarViewModel { get; }
+ public bool IsSidebarVisible { get; set; }
+ public bool ActiveItemReady { get; set; }
+
private void ApplyWindowsTheme(ThemeWatcher.WindowsTheme windowsTheme)
{
var paletteHelper = new PaletteHelper();
var theme = paletteHelper.GetTheme();
-
theme.SetBaseTheme(windowsTheme == ThemeWatcher.WindowsTheme.Dark ? Theme.Dark : Theme.Light);
paletteHelper.SetTheme(theme);
- }
- public IObservableCollection Modules { get; set; }
- public bool MenuOpen { get; set; }
- public ListBoxItem SelectedPage { get; set; }
- public Core.Plugins.Abstract.Module SelectedModule { get; set; }
- public bool ActiveItemReady { get; set; }
-
- public async Task NavigateToSelectedModule()
- {
- if (SelectedModule == null)
- return;
-
- MenuOpen = false;
- SelectedPage = null;
-
- // Create a view model for the given plugin info (which will be a module)
- var viewModel = await Task.Run(() => _moduleViewModelFactory.Create(SelectedModule));
- ActivateItem(viewModel);
- }
-
- private void PluginServiceOnPluginEnabled(object sender, PluginEventArgs e)
- {
- var existing = Modules.FirstOrDefault(m => _pluginService.GetPluginInfo(m)?.Guid == e.PluginInfo.Guid);
- if (existing != null)
- {
- if (SelectedModule == existing && SelectedModule != null)
- SelectedModule = null;
- Modules.Remove(existing);
- }
-
- if (e.PluginInfo.Instance is Core.Plugins.Abstract.Module module)
- Modules.Add(module);
- }
-
- private void PluginServiceOnPluginDisabled(object sender, PluginEventArgs e)
- {
- var existing = Modules.FirstOrDefault(m => _pluginService.GetPluginInfo(m)?.Guid == e.PluginInfo.Guid);
- if (existing != null)
- {
- if (SelectedModule == existing && SelectedModule != null)
- SelectedModule = null;
- Modules.Remove(existing);
- }
- }
-
- private async void OnSelectedModuleChanged(object sender, PropertyChangedEventArgs e)
- {
- if (e.PropertyName == nameof(SelectedModule))
- await NavigateToSelectedModule();
- }
-
- private async void OnSelectedPageChanged(object sender, PropertyChangedEventArgs e)
- {
- if (e.PropertyName != "SelectedPage" || SelectedPage == null)
- return;
-
- SelectedModule = null;
- MenuOpen = false;
- ActiveItemReady = false;
-
- // Let the menu close smoothly to avoid a sluggish feeling
- await Task.Delay(400);
-
- switch (SelectedPage.Name)
- {
- case "Home":
- ActivateItem(_artemisViewModels.First(v => v is HomeViewModel));
- break;
- case "News":
- ActivateItem(_artemisViewModels.First(v => v is NewsViewModel));
- break;
- case "Workshop":
- ActivateItem(_artemisViewModels.First(v => v is WorkshopViewModel));
- break;
- case "SurfaceEditor":
- ActivateItem(_artemisViewModels.First(v => v is SurfaceEditorViewModel));
- break;
- case "Settings":
- ActivateItem(_artemisViewModels.First(v => v is SettingsViewModel));
- break;
- }
-
- ActiveItemReady = true;
+ var extensionsPaletteHelper = new MaterialDesignExtensions.Themes.PaletteHelper();
+ extensionsPaletteHelper.SetLightDark(windowsTheme == ThemeWatcher.WindowsTheme.Dark);
}
public void WindowDeactivated()
diff --git a/src/Artemis.UI/Screens/Settings/Debug/DebugView.xaml b/src/Artemis.UI/Screens/Settings/Debug/DebugView.xaml
index 64843f8ef..d4fab66fa 100644
--- a/src/Artemis.UI/Screens/Settings/Debug/DebugView.xaml
+++ b/src/Artemis.UI/Screens/Settings/Debug/DebugView.xaml
@@ -1,69 +1,23 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
In this window you can view the inner workings of Artemis.
@@ -95,4 +49,4 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/src/Artemis.UI/Screens/Settings/Debug/DebugViewModel.cs b/src/Artemis.UI/Screens/Settings/Debug/DebugViewModel.cs
index b2619e9cf..7746d7f43 100644
--- a/src/Artemis.UI/Screens/Settings/Debug/DebugViewModel.cs
+++ b/src/Artemis.UI/Screens/Settings/Debug/DebugViewModel.cs
@@ -11,7 +11,7 @@ using Stylet;
namespace Artemis.UI.Screens.Settings.Debug
{
- public class DebugViewModel : Screen, IScreenViewModel
+ public class DebugViewModel : Screen
{
private readonly ICoreService _coreService;
private readonly IRgbService _rgbService;
diff --git a/src/Artemis.UI/Screens/Settings/SettingsViewModel.cs b/src/Artemis.UI/Screens/Settings/SettingsViewModel.cs
index 1dd6095b6..86e82a38e 100644
--- a/src/Artemis.UI/Screens/Settings/SettingsViewModel.cs
+++ b/src/Artemis.UI/Screens/Settings/SettingsViewModel.cs
@@ -3,12 +3,13 @@ using Artemis.Core.Services.Storage.Interfaces;
using Artemis.UI.Ninject.Factories;
using Artemis.UI.Screens.Settings.Debug;
using Artemis.UI.Screens.Settings.Tabs.Devices;
+using MaterialDesignThemes.Wpf;
using Ninject;
using Stylet;
namespace Artemis.UI.Screens.Settings
{
- public class SettingsViewModel : Screen, IScreenViewModel
+ public class SettingsViewModel : MainScreenViewModel
{
private readonly IDeviceSettingsViewModelFactory _deviceSettingsViewModelFactory;
private readonly IKernel _kernel;
@@ -22,6 +23,10 @@ namespace Artemis.UI.Screens.Settings
ISettingsService settingsService,
IDeviceSettingsViewModelFactory deviceSettingsViewModelFactory)
{
+ DisplayName = "Settings";
+ DisplayIcon = PackIconKind.Settings;
+ DisplayOrder = 5;
+
_kernel = kernel;
_surfaceService = surfaceService;
_windowManager = windowManager;
diff --git a/src/Artemis.UI/Screens/Settings/Tabs/Devices/DeviceSettingsViewModel.cs b/src/Artemis.UI/Screens/Settings/Tabs/Devices/DeviceSettingsViewModel.cs
index 34acc4f45..4dd7be456 100644
--- a/src/Artemis.UI/Screens/Settings/Tabs/Devices/DeviceSettingsViewModel.cs
+++ b/src/Artemis.UI/Screens/Settings/Tabs/Devices/DeviceSettingsViewModel.cs
@@ -31,8 +31,7 @@ namespace Artemis.UI.Screens.Settings.Tabs.Devices
{
_deviceService.IdentifyDevice(Device);
}
-
-
+
public void ShowDeviceDebugger()
{
}
diff --git a/src/Artemis.UI/Screens/Sidebar/SidebarView.xaml b/src/Artemis.UI/Screens/Sidebar/SidebarView.xaml
new file mode 100644
index 000000000..17c80b091
--- /dev/null
+++ b/src/Artemis.UI/Screens/Sidebar/SidebarView.xaml
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+ Active module
+
+
+ Profile 1
+ Profile 2
+ Profile 3
+ Profile 4
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Artemis.UI/Screens/Sidebar/SidebarView.xaml.cs b/src/Artemis.UI/Screens/Sidebar/SidebarView.xaml.cs
new file mode 100644
index 000000000..f76766c07
--- /dev/null
+++ b/src/Artemis.UI/Screens/Sidebar/SidebarView.xaml.cs
@@ -0,0 +1,28 @@
+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.Navigation;
+using System.Windows.Shapes;
+
+namespace Artemis.UI.Screens.Sidebar
+{
+ ///
+ /// Interaction logic for SidebarView.xaml
+ ///
+ public partial class SidebarView : UserControl
+ {
+ public SidebarView()
+ {
+ InitializeComponent();
+ }
+ }
+}
diff --git a/src/Artemis.UI/Screens/Sidebar/SidebarViewModel.cs b/src/Artemis.UI/Screens/Sidebar/SidebarViewModel.cs
new file mode 100644
index 000000000..fe0372c42
--- /dev/null
+++ b/src/Artemis.UI/Screens/Sidebar/SidebarViewModel.cs
@@ -0,0 +1,123 @@
+using System.Collections.Generic;
+using System.Linq;
+using Artemis.Core.Events;
+using Artemis.Core.Services.Interfaces;
+using Artemis.UI.Ninject.Factories;
+using MaterialDesignExtensions.Controls;
+using MaterialDesignExtensions.Model;
+using MaterialDesignThemes.Wpf;
+using Stylet;
+
+namespace Artemis.UI.Screens.Sidebar
+{
+ public class SidebarViewModel : PropertyChangedBase
+ {
+ private readonly IModuleViewModelFactory _moduleViewModelFactory;
+ private readonly IPluginService _pluginService;
+
+ public SidebarViewModel(List defaultSidebarItems, IModuleViewModelFactory moduleViewModelFactory, IPluginService pluginService)
+ {
+ _moduleViewModelFactory = moduleViewModelFactory;
+ _pluginService = pluginService;
+
+ DefaultSidebarItems = defaultSidebarItems;
+ SidebarItemObjects = new Dictionary();
+ SidebarItems = new BindableCollection();
+
+ SetupSidebar();
+ _pluginService.PluginEnabled += PluginServiceOnPluginEnabled;
+ _pluginService.PluginDisabled += PluginServiceOnPluginDisabled;
+ }
+
+ public List DefaultSidebarItems { get; set; }
+ public BindableCollection SidebarItems { get; set; }
+ public Dictionary SidebarItemObjects { get; set; }
+ public IScreen SelectedItem { get; set; }
+
+ public void SetupSidebar()
+ {
+ SidebarItems.Clear();
+ SidebarItemObjects.Clear();
+
+ // Add all default sidebar items
+ SidebarItems.Add(new DividerNavigationItem());
+ foreach (var screen in DefaultSidebarItems.OrderBy(d => d.DisplayOrder))
+ {
+ var sidebarItem = new FirstLevelNavigationItem {Icon = screen.DisplayIcon, Label = screen.DisplayName};
+ SidebarItems.Add(sidebarItem);
+ SidebarItemObjects.Add(sidebarItem, screen);
+ }
+
+ // Add all activated modules
+ SidebarItems.Add(new DividerNavigationItem());
+ SidebarItems.Add(new SubheaderNavigationItem {Subheader = "Modules"});
+ var modules = _pluginService.GetPluginsOfType().ToList();
+ foreach (var module in modules)
+ AddModule(module);
+
+ // Select the top item, which will be one of the defaults
+ SidebarItems[1].IsSelected = true;
+ SelectedItem = (IScreen) SidebarItemObjects[SidebarItems[1]];
+ }
+
+ // ReSharper disable once UnusedMember.Global - Called by view
+ public void SelectItem(WillSelectNavigationItemEventArgs args)
+ {
+ if (args.NavigationItemToSelect == null)
+ {
+ SelectedItem = null;
+ return;
+ }
+
+ var sidebarItemObject = SidebarItemObjects[args.NavigationItemToSelect];
+ // The default items are singleton screens, simply set it as the selected item
+ if (sidebarItemObject is IScreen screen)
+ SelectedItem = screen;
+ // Modules have a VM that must be created, use a factory and set the result as the selected item
+ else if (sidebarItemObject is Core.Plugins.Abstract.Module module)
+ SelectedItem = _moduleViewModelFactory.Create(module);
+ }
+
+ public void AddModule(Core.Plugins.Abstract.Module module)
+ {
+ // Ensure the module is not already in the list
+ if (SidebarItemObjects.Any(io => io.Value == module))
+ return;
+
+ // Icon is provided as string to avoid having to reference MaterialDesignThemes
+ var parsedIcon = System.Enum.TryParse(module.DisplayIcon, true, out var iconEnum);
+ if (parsedIcon == false)
+ iconEnum = PackIconKind.QuestionMarkCircle;
+ var sidebarItem = new FirstLevelNavigationItem { Icon = iconEnum, Label = module.DisplayName };
+ SidebarItems.Add(sidebarItem);
+ SidebarItemObjects.Add(sidebarItem, module);
+ }
+
+ public void RemoveModule(Core.Plugins.Abstract.Module module)
+ {
+ // If not in the list there's nothing to do
+ if (SidebarItemObjects.All(io => io.Value != module))
+ return;
+
+ var existing = SidebarItemObjects.First(io => io.Value == module);
+ SidebarItems.Remove(existing.Key);
+ SidebarItemObjects.Remove(existing.Key);
+ }
+
+ #region Event handlers
+
+ private void PluginServiceOnPluginEnabled(object sender, PluginEventArgs e)
+ {
+ if (e.PluginInfo.Instance is Core.Plugins.Abstract.Module module)
+ AddModule(module);
+ }
+
+ private void PluginServiceOnPluginDisabled(object sender, PluginEventArgs e)
+ {
+ if (e.PluginInfo.Instance is Core.Plugins.Abstract.Module module)
+ RemoveModule(module);
+ }
+
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/src/Artemis.UI/Screens/Splash/SplashView.xaml b/src/Artemis.UI/Screens/Splash/SplashView.xaml
index edf44348c..e26961e6f 100644
--- a/src/Artemis.UI/Screens/Splash/SplashView.xaml
+++ b/src/Artemis.UI/Screens/Splash/SplashView.xaml
@@ -1,21 +1,17 @@
-
@@ -31,4 +27,4 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/src/Artemis.UI/Screens/SurfaceEditor/Dialogs/SurfaceDeviceConfigView.xaml b/src/Artemis.UI/Screens/SurfaceEditor/Dialogs/SurfaceDeviceConfigView.xaml
index 3e438a194..74df39c6d 100644
--- a/src/Artemis.UI/Screens/SurfaceEditor/Dialogs/SurfaceDeviceConfigView.xaml
+++ b/src/Artemis.UI/Screens/SurfaceEditor/Dialogs/SurfaceDeviceConfigView.xaml
@@ -6,47 +6,19 @@
xmlns:s="https://github.com/canton7/Stylet"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:surfaceEditor="clr-namespace:Artemis.UI.Screens.SurfaceEditor.Dialogs"
- xmlns:mah="http://metro.mahapps.com/winfx/xaml/controls"
mc:Ignorable="d"
d:DesignHeight="351.305" d:DesignWidth="262.163"
d:DataContext="{d:DesignInstance {x:Type surfaceEditor:SurfaceDeviceConfigViewModel}}">
+
+
-
-
-
-
-
-
-
-
-
-
-
+
+
+