diff --git a/src/Artemis.Core/Plugins/Abstract/Module.cs b/src/Artemis.Core/Plugins/Abstract/Module.cs
index 5526dcea4..e710c3bb6 100644
--- a/src/Artemis.Core/Plugins/Abstract/Module.cs
+++ b/src/Artemis.Core/Plugins/Abstract/Module.cs
@@ -1,4 +1,5 @@
-using System.Drawing;
+using System.Collections.Generic;
+using System.Drawing;
using Artemis.Core.Models.Surface;
using Artemis.Core.Plugins.Models;
using RGB.NET.Core;
@@ -42,9 +43,9 @@ namespace Artemis.Core.Plugins.Abstract
public abstract void Render(double deltaTime, Surface surface, Graphics graphics);
///
- /// Called when the module's main view is being shown
+ /// Called when the module's view model is being show, return view models here to create tabs for them
///
///
- public abstract IScreen GetMainViewModel();
+ public abstract IEnumerable GetViewModels();
}
}
\ No newline at end of file
diff --git a/src/Artemis.Core/Plugins/Abstract/ModuleViewModel.cs b/src/Artemis.Core/Plugins/Abstract/ModuleViewModel.cs
index 559f5ed42..ead43c4e7 100644
--- a/src/Artemis.Core/Plugins/Abstract/ModuleViewModel.cs
+++ b/src/Artemis.Core/Plugins/Abstract/ModuleViewModel.cs
@@ -4,11 +4,13 @@ namespace Artemis.Core.Plugins.Abstract
{
public abstract class ModuleViewModel : Screen
{
- protected ModuleViewModel(Module module)
+ protected ModuleViewModel(Module module, string name)
{
Module = module;
+ Name = name;
}
+ public string Name { get; }
public Module Module { get; }
}
}
\ No newline at end of file
diff --git a/src/Artemis.Core/Services/PluginService.cs b/src/Artemis.Core/Services/PluginService.cs
index 8ec5da868..ec4a6e3ee 100644
--- a/src/Artemis.Core/Services/PluginService.cs
+++ b/src/Artemis.Core/Services/PluginService.cs
@@ -15,6 +15,7 @@ using Ninject;
using Ninject.Extensions.ChildKernel;
using Ninject.Parameters;
using RGB.NET.Core;
+using Serilog;
namespace Artemis.Core.Services
{
@@ -24,12 +25,14 @@ namespace Artemis.Core.Services
public class PluginService : IPluginService
{
private readonly IKernel _kernel;
+ private readonly ILogger _logger;
private readonly List _plugins;
private IKernel _childKernel;
- internal PluginService(IKernel kernel)
+ internal PluginService(IKernel kernel, ILogger logger)
{
_kernel = kernel;
+ _logger = logger;
_plugins = new List();
// Ensure the plugins directory exists
@@ -114,7 +117,9 @@ namespace Artemis.Core.Services
// Load the metadata
var metadataFile = Path.Combine(subDirectory.FullName, "plugin.json");
if (!File.Exists(metadataFile))
- throw new ArtemisPluginException("Couldn't find the plugins metadata file at " + metadataFile);
+ {
+ _logger.Warning(new ArtemisPluginException("Couldn't find the plugins metadata file at " + metadataFile), "Plugin exception");
+ }
// Locate the main entry
var pluginInfo = JsonConvert.DeserializeObject(File.ReadAllText(metadataFile));
@@ -124,14 +129,21 @@ namespace Artemis.Core.Services
}
catch (Exception e)
{
- throw new ArtemisPluginException("Failed to load plugin", e);
+ _logger.Warning(new ArtemisPluginException("Failed to load plugin", e), "Plugin exception");
}
}
// Activate plugins after they are all loaded
foreach (var pluginInfo in _plugins.Where(p => p.Enabled))
{
- pluginInfo.Instance.EnablePlugin();
+ try
+ {
+ pluginInfo.Instance.EnablePlugin();
+ }
+ catch (Exception e)
+ {
+ _logger.Warning(new ArtemisPluginException(pluginInfo, "Failed to load enable plugin", e), "Plugin exception");
+ }
OnPluginEnabled(new PluginEventArgs(pluginInfo));
}
diff --git a/src/Artemis.Plugins.Modules.General/GeneralModule.cs b/src/Artemis.Plugins.Modules.General/GeneralModule.cs
index 3ae230ed6..e1feab291 100644
--- a/src/Artemis.Plugins.Modules.General/GeneralModule.cs
+++ b/src/Artemis.Plugins.Modules.General/GeneralModule.cs
@@ -1,4 +1,5 @@
using System;
+using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
@@ -6,15 +7,14 @@ using Artemis.Core.Models.Surface;
using Artemis.Core.Plugins.Abstract;
using Artemis.Core.Plugins.Models;
using Artemis.Plugins.Modules.General.ViewModels;
-using Stylet;
using Device = Artemis.Core.Models.Surface.Device;
namespace Artemis.Plugins.Modules.General
{
public class GeneralModule : Module
{
- private readonly PluginSettings _settings;
private readonly ColorBlend _rainbowColorBlend;
+ private readonly PluginSettings _settings;
public GeneralModule(PluginInfo pluginInfo, PluginSettings settings) : base(pluginInfo)
{
@@ -118,9 +118,9 @@ namespace Artemis.Plugins.Modules.General
}
}
- public override IScreen GetMainViewModel()
+ public override IEnumerable GetViewModels()
{
- return new GeneralViewModel(this);
+ return new List {new GeneralViewModel(this)};
}
public override void Dispose()
diff --git a/src/Artemis.Plugins.Modules.General/ViewModels/GeneralViewModel.cs b/src/Artemis.Plugins.Modules.General/ViewModels/GeneralViewModel.cs
index b9f75f0f8..7ab14f005 100644
--- a/src/Artemis.Plugins.Modules.General/ViewModels/GeneralViewModel.cs
+++ b/src/Artemis.Plugins.Modules.General/ViewModels/GeneralViewModel.cs
@@ -5,7 +5,7 @@ namespace Artemis.Plugins.Modules.General.ViewModels
{
public class GeneralViewModel : ModuleViewModel
{
- public GeneralViewModel(Module module) : base(module)
+ public GeneralViewModel(Module module) : base(module, "General")
{
}
}
diff --git a/src/Artemis.UI/App.xaml b/src/Artemis.UI/App.xaml
index a64915a29..19257ccf3 100644
--- a/src/Artemis.UI/App.xaml
+++ b/src/Artemis.UI/App.xaml
@@ -2,7 +2,8 @@
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:local="clr-namespace:Artemis.UI"
+ xmlns:dragablz="http://dragablz.net/winfx/xaml/dragablz">
@@ -28,6 +29,9 @@
Source="pack://application:,,,/MaterialDesignColors;component/Themes/Recommended/Primary/MaterialDesignColor.Teal.xaml" />
+
+
+
@@ -54,6 +58,9 @@
+
+
+
diff --git a/src/Artemis.UI/Artemis.UI.csproj b/src/Artemis.UI/Artemis.UI.csproj
index 05276cf74..1f336f351 100644
--- a/src/Artemis.UI/Artemis.UI.csproj
+++ b/src/Artemis.UI/Artemis.UI.csproj
@@ -69,6 +69,9 @@
..\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
@@ -163,6 +166,7 @@
+
True
@@ -176,30 +180,33 @@
+
+
-
-
-
App.xaml
Code
+
+ Designer
+ MSBuild:Compile
+
MSBuild:Compile
Designer
@@ -232,6 +239,10 @@
Designer
MSBuild:Compile
+
+ Designer
+ MSBuild:Compile
+
Designer
MSBuild:Compile
diff --git a/src/Artemis.UI/Ninject/Factories/ModuleViewModelFactory.cs b/src/Artemis.UI/Ninject/Factories/ModuleViewModelFactory.cs
new file mode 100644
index 000000000..6dad4814d
--- /dev/null
+++ b/src/Artemis.UI/Ninject/Factories/ModuleViewModelFactory.cs
@@ -0,0 +1,10 @@
+using Artemis.Core.Plugins.Abstract;
+using Artemis.UI.ViewModels.Screens;
+
+namespace Artemis.UI.Ninject.Factories
+{
+ public interface IModuleViewModelFactory
+ {
+ ModuleRootViewModel CreateModuleViewModel(Module module);
+ }
+}
\ No newline at end of file
diff --git a/src/Artemis.UI/Ninject/UiModule.cs b/src/Artemis.UI/Ninject/UiModule.cs
index a2c16e716..38bf34559 100644
--- a/src/Artemis.UI/Ninject/UiModule.cs
+++ b/src/Artemis.UI/Ninject/UiModule.cs
@@ -1,9 +1,11 @@
-using Artemis.UI.Services.Interfaces;
+using Artemis.UI.Ninject.Factories;
+using Artemis.UI.Services.Interfaces;
using Artemis.UI.Stylet;
using Artemis.UI.ViewModels.Dialogs;
using Artemis.UI.ViewModels.Interfaces;
using FluentValidation;
using Ninject.Extensions.Conventions;
+using Ninject.Extensions.Factory;
using Ninject.Modules;
using Stylet;
@@ -32,6 +34,9 @@ namespace Artemis.UI.Ninject
.BindAllBaseClasses();
});
+ // Bind the module VM
+ Bind().ToFactory();
+
// Bind all UI services as singletons
Kernel.Bind(x =>
{
diff --git a/src/Artemis.UI/ViewModels/Controls/ProfileEditor/ProfileEditorViewModel.cs b/src/Artemis.UI/ViewModels/Controls/ProfileEditor/ProfileEditorViewModel.cs
new file mode 100644
index 000000000..1cda2e580
--- /dev/null
+++ b/src/Artemis.UI/ViewModels/Controls/ProfileEditor/ProfileEditorViewModel.cs
@@ -0,0 +1,16 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Artemis.Core.Plugins.Abstract;
+
+namespace Artemis.UI.ViewModels.Controls.ProfileEditor
+{
+ public class ProfileEditorViewModel : ModuleViewModel
+ {
+ public ProfileEditorViewModel(Module module) : base(module, "Profile Editor")
+ {
+ }
+ }
+}
diff --git a/src/Artemis.UI/ViewModels/Interfaces/IEditorViewModel.cs b/src/Artemis.UI/ViewModels/Interfaces/IEditorViewModel.cs
deleted file mode 100644
index 43313873d..000000000
--- a/src/Artemis.UI/ViewModels/Interfaces/IEditorViewModel.cs
+++ /dev/null
@@ -1,7 +0,0 @@
-namespace Artemis.UI.ViewModels.Interfaces
-{
- public interface ISurfaceEditorViewModel : IScreenViewModel
- {
-
- }
-}
\ No newline at end of file
diff --git a/src/Artemis.UI/ViewModels/Interfaces/IHomeViewModel.cs b/src/Artemis.UI/ViewModels/Interfaces/IHomeViewModel.cs
deleted file mode 100644
index 509d2df41..000000000
--- a/src/Artemis.UI/ViewModels/Interfaces/IHomeViewModel.cs
+++ /dev/null
@@ -1,7 +0,0 @@
-namespace Artemis.UI.ViewModels.Interfaces
-{
- public interface IHomeViewModel : IScreenViewModel
- {
- void OpenUrl(string url);
- }
-}
\ No newline at end of file
diff --git a/src/Artemis.UI/ViewModels/Interfaces/ISettingsViewModel.cs b/src/Artemis.UI/ViewModels/Interfaces/ISettingsViewModel.cs
deleted file mode 100644
index 4debbf352..000000000
--- a/src/Artemis.UI/ViewModels/Interfaces/ISettingsViewModel.cs
+++ /dev/null
@@ -1,6 +0,0 @@
-namespace Artemis.UI.ViewModels.Interfaces
-{
- public interface ISettingsViewModel : IScreenViewModel
- {
- }
-}
\ No newline at end of file
diff --git a/src/Artemis.UI/ViewModels/Screens/DebugViewModel.cs b/src/Artemis.UI/ViewModels/Screens/DebugViewModel.cs
index 04b1263f7..4b343bc0d 100644
--- a/src/Artemis.UI/ViewModels/Screens/DebugViewModel.cs
+++ b/src/Artemis.UI/ViewModels/Screens/DebugViewModel.cs
@@ -7,11 +7,12 @@ using System.Windows.Media;
using System.Windows.Media.Imaging;
using Artemis.Core.Events;
using Artemis.Core.Services.Interfaces;
+using Artemis.UI.ViewModels.Interfaces;
using Stylet;
namespace Artemis.UI.ViewModels.Screens
{
- public class DebugViewModel : Screen
+ public class DebugViewModel : Screen, IScreenViewModel
{
private readonly ICoreService _coreService;
private readonly IRgbService _rgbService;
@@ -76,5 +77,7 @@ namespace Artemis.UI.ViewModels.Screens
[DllImport("gdi32.dll", EntryPoint = "DeleteObject")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool DeleteObject([In] IntPtr hObject);
+
+ public string Title => "Debugger";
}
}
\ No newline at end of file
diff --git a/src/Artemis.UI/ViewModels/Screens/HomeViewModel.cs b/src/Artemis.UI/ViewModels/Screens/HomeViewModel.cs
index d71a83d18..94e74b5db 100644
--- a/src/Artemis.UI/ViewModels/Screens/HomeViewModel.cs
+++ b/src/Artemis.UI/ViewModels/Screens/HomeViewModel.cs
@@ -5,7 +5,7 @@ using Stylet;
namespace Artemis.UI.ViewModels.Screens
{
- public class HomeViewModel : Screen, IHomeViewModel
+ public class HomeViewModel : Screen, IScreenViewModel
{
public string Title => "Home";
diff --git a/src/Artemis.UI/ViewModels/Screens/ModuleRootViewModel.cs b/src/Artemis.UI/ViewModels/Screens/ModuleRootViewModel.cs
new file mode 100644
index 000000000..00eb1e8bf
--- /dev/null
+++ b/src/Artemis.UI/ViewModels/Screens/ModuleRootViewModel.cs
@@ -0,0 +1,21 @@
+using Artemis.Core.Plugins.Abstract;
+using Artemis.UI.ViewModels.Controls.ProfileEditor;
+using Stylet;
+
+namespace Artemis.UI.ViewModels.Screens
+{
+ public class ModuleRootViewModel : Screen
+ {
+ public ModuleRootViewModel(Module module)
+ {
+ Module = module;
+ ModuleViewModels = new BindableCollection {new ProfileEditorViewModel(Module)};
+ ModuleViewModels.AddRange(Module.GetViewModels());
+ }
+
+ public Module Module { get; }
+ public BindableCollection ModuleViewModels { get; set; }
+
+ public int FixedHeaderCount => ModuleViewModels.Count;
+ }
+}
\ No newline at end of file
diff --git a/src/Artemis.UI/ViewModels/Screens/RootViewModel.cs b/src/Artemis.UI/ViewModels/Screens/RootViewModel.cs
index 88f1f6fb5..84eb92176 100644
--- a/src/Artemis.UI/ViewModels/Screens/RootViewModel.cs
+++ b/src/Artemis.UI/ViewModels/Screens/RootViewModel.cs
@@ -1,11 +1,13 @@
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
+using System.Threading;
using System.Threading.Tasks;
using System.Windows.Controls;
using Artemis.Core.Events;
using Artemis.Core.Plugins.Abstract;
using Artemis.Core.Services.Interfaces;
+using Artemis.UI.Ninject.Factories;
using Artemis.UI.ViewModels.Interfaces;
using Stylet;
@@ -15,11 +17,13 @@ namespace Artemis.UI.ViewModels.Screens
{
private readonly ICollection _artemisViewModels;
private readonly IPluginService _pluginService;
+ private readonly IModuleViewModelFactory _moduleViewModelFactory;
- public RootViewModel(ICollection artemisViewModels, IPluginService pluginService)
+ public RootViewModel(ICollection artemisViewModels, IPluginService pluginService, IModuleViewModelFactory moduleViewModelFactory)
{
_artemisViewModels = artemisViewModels;
_pluginService = pluginService;
+ _moduleViewModelFactory = moduleViewModelFactory;
// Add the built-in items
Items.AddRange(artemisViewModels);
@@ -28,7 +32,7 @@ namespace Artemis.UI.ViewModels.Screens
// Sync up with the plugin service
Modules = new BindableCollection();
- // Modules.AddRange(_pluginService.GetPluginsOfType());
+ Modules.AddRange(_pluginService.GetPluginsOfType());
_pluginService.PluginEnabled += PluginServiceOnPluginEnabled;
_pluginService.PluginDisabled += PluginServiceOnPluginDisabled;
@@ -47,8 +51,7 @@ namespace Artemis.UI.ViewModels.Screens
return;
// Create a view model for the given plugin info (which will be a module)
- var viewModel = await Task.Run(() => SelectedModule.GetMainViewModel());
- // Tell Stylet to active the view model, the view manager will compile and show the XAML
+ var viewModel = await Task.Run(() => _moduleViewModelFactory.CreateModuleViewModel(SelectedModule));
ActivateItem(viewModel);
SelectedPage = null;
diff --git a/src/Artemis.UI/ViewModels/Screens/SettingsViewModel.cs b/src/Artemis.UI/ViewModels/Screens/SettingsViewModel.cs
index a167aac62..e09aa992c 100644
--- a/src/Artemis.UI/ViewModels/Screens/SettingsViewModel.cs
+++ b/src/Artemis.UI/ViewModels/Screens/SettingsViewModel.cs
@@ -8,7 +8,7 @@ using Stylet;
namespace Artemis.UI.ViewModels.Screens
{
- public class SettingsViewModel : Screen, ISettingsViewModel
+ public class SettingsViewModel : Screen, IScreenViewModel
{
private readonly ICoreService _coreService;
private readonly IKernel _kernel;
diff --git a/src/Artemis.UI/ViewModels/Screens/SplashViewModel.cs b/src/Artemis.UI/ViewModels/Screens/SplashViewModel.cs
index 21f396517..fe87c166e 100644
--- a/src/Artemis.UI/ViewModels/Screens/SplashViewModel.cs
+++ b/src/Artemis.UI/ViewModels/Screens/SplashViewModel.cs
@@ -1,9 +1,4 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using Artemis.Core.Services.Interfaces;
+using Artemis.Core.Services.Interfaces;
using Ninject;
using Stylet;
@@ -26,6 +21,7 @@ namespace Artemis.UI.ViewModels.Screens
var pluginService = _kernel.Get();
pluginService.CopyingBuildInPlugins += (sender, args) => Status = "Updating built-in plugins";
pluginService.PluginLoading += (sender, args) => Status = "Loading plugin: " + args.PluginInfo.Name;
+ pluginService.PluginLoaded += (sender, args) => Status = "Initializing UI";
}
}
}
\ No newline at end of file
diff --git a/src/Artemis.UI/ViewModels/Screens/SurfaceEditorViewModel.cs b/src/Artemis.UI/ViewModels/Screens/SurfaceEditorViewModel.cs
index 913b692dc..fd5310a93 100644
--- a/src/Artemis.UI/ViewModels/Screens/SurfaceEditorViewModel.cs
+++ b/src/Artemis.UI/ViewModels/Screens/SurfaceEditorViewModel.cs
@@ -17,7 +17,7 @@ using Stylet;
namespace Artemis.UI.ViewModels.Screens
{
- public class SurfaceEditorViewModel : Screen, ISurfaceEditorViewModel
+ public class SurfaceEditorViewModel : Screen, IScreenViewModel
{
private readonly IDialogService _dialogService;
private readonly ISurfaceService _surfaceService;
diff --git a/src/Artemis.UI/Views/Controls/ProfileEditor/ProfileEditorView.xaml b/src/Artemis.UI/Views/Controls/ProfileEditor/ProfileEditorView.xaml
new file mode 100644
index 000000000..97243184e
--- /dev/null
+++ b/src/Artemis.UI/Views/Controls/ProfileEditor/ProfileEditorView.xaml
@@ -0,0 +1,14 @@
+
+
+
+
+
diff --git a/src/Artemis.UI/Views/Screens/HomeView.xaml b/src/Artemis.UI/Views/Screens/HomeView.xaml
index ec6d126fd..49d621a66 100644
--- a/src/Artemis.UI/Views/Screens/HomeView.xaml
+++ b/src/Artemis.UI/Views/Screens/HomeView.xaml
@@ -4,7 +4,6 @@
xmlns:s="https://github.com/canton7/Stylet"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
- xmlns:vms="clr-namespace:Artemis.UI.ViewModels"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:screens="clr-namespace:Artemis.UI.ViewModels.Screens"
mc:Ignorable="d"
diff --git a/src/Artemis.UI/Views/Screens/ModuleRootView.xaml b/src/Artemis.UI/Views/Screens/ModuleRootView.xaml
new file mode 100644
index 000000000..e38d10d5c
--- /dev/null
+++ b/src/Artemis.UI/Views/Screens/ModuleRootView.xaml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Artemis.UI/Views/Screens/RootView.xaml b/src/Artemis.UI/Views/Screens/RootView.xaml
index 6d868fcb9..7807159a7 100644
--- a/src/Artemis.UI/Views/Screens/RootView.xaml
+++ b/src/Artemis.UI/Views/Screens/RootView.xaml
@@ -114,7 +114,7 @@
-
@@ -134,6 +134,7 @@
+
+ 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:mah="http://metro.mahapps.com/winfx/xaml/controls"
+ xmlns:screens="clr-namespace:Artemis.UI.ViewModels.Screens"
+ mc:Ignorable="d"
+ Title="Artemis"
+ Height="450"
+ Width="450"
+ ShowTitleBar="False"
+ ShowMaxRestoreButton="False"
+ ShowCloseButton="False"
+ ShowMinButton="False"
+ WindowStartupLocation="CenterScreen"
+ GlowBrush="{DynamicResource AccentColorBrush}"
+ FontFamily="{StaticResource DefaultFont}"
+ d:DataContext="{d:DesignInstance screens:SplashViewModel}">
@@ -28,7 +26,7 @@
Artemis is initializing...
-
-
+
+
\ No newline at end of file
diff --git a/src/Artemis.UI/packages.config b/src/Artemis.UI/packages.config
index 1be164a31..5c9ffce65 100644
--- a/src/Artemis.UI/packages.config
+++ b/src/Artemis.UI/packages.config
@@ -2,6 +2,7 @@
+