diff --git a/Artemis/Artemis/Artemis.csproj b/Artemis/Artemis/Artemis.csproj
index d9384595c..e62a1d2e4 100644
--- a/Artemis/Artemis/Artemis.csproj
+++ b/Artemis/Artemis/Artemis.csproj
@@ -289,7 +289,8 @@
-
+
+
diff --git a/Artemis/Artemis/InjectionFactories/ILayerEditorVmFactory.cs b/Artemis/Artemis/InjectionFactories/ILayerEditorVmFactory.cs
new file mode 100644
index 000000000..67a0e6672
--- /dev/null
+++ b/Artemis/Artemis/InjectionFactories/ILayerEditorVmFactory.cs
@@ -0,0 +1,12 @@
+using Artemis.Models.Interfaces;
+using Artemis.Models.Profiles;
+using Artemis.Services;
+using Artemis.ViewModels.Profiles;
+
+namespace Artemis.InjectionFactories
+{
+ public interface ILayerEditorVmFactory
+ {
+ LayerEditorViewModel CreateLayerEditorVm(IGameDataModel gameDataModel, LayerModel layer);
+ }
+}
\ No newline at end of file
diff --git a/Artemis/Artemis/InjectionFactories/IProfileEditorViewModelFactory.cs b/Artemis/Artemis/InjectionFactories/IProfileEditorViewModelFactory.cs
deleted file mode 100644
index 38b247a80..000000000
--- a/Artemis/Artemis/InjectionFactories/IProfileEditorViewModelFactory.cs
+++ /dev/null
@@ -1,12 +0,0 @@
-using Artemis.Managers;
-using Artemis.Models;
-using Artemis.ViewModels.Profiles;
-using Caliburn.Micro;
-
-namespace Artemis.InjectionFactories
-{
- public interface IProfileEditorViewModelFactory
- {
- ProfileEditorViewModel CreateProfileEditorViewModel(IEventAggregator events, MainManager mainManager, GameModel gameModel, string lastProfile);
- }
-}
\ No newline at end of file
diff --git a/Artemis/Artemis/InjectionFactories/IProfileEditorVmFactory.cs b/Artemis/Artemis/InjectionFactories/IProfileEditorVmFactory.cs
new file mode 100644
index 000000000..c6bc58d58
--- /dev/null
+++ b/Artemis/Artemis/InjectionFactories/IProfileEditorVmFactory.cs
@@ -0,0 +1,13 @@
+using Artemis.Managers;
+using Artemis.Models;
+using Artemis.ViewModels.Profiles;
+using Caliburn.Micro;
+
+namespace Artemis.InjectionFactories
+{
+ public interface IProfileEditorVmFactory
+ {
+ ProfileEditorViewModel CreateProfileEditorVm(IEventAggregator events, MainManager mainManager,
+ GameModel gameModel, string lastProfile);
+ }
+}
\ No newline at end of file
diff --git a/Artemis/Artemis/InjectionModules/BaseModules.cs b/Artemis/Artemis/InjectionModules/BaseModules.cs
index dcbcc440b..05805579a 100644
--- a/Artemis/Artemis/InjectionModules/BaseModules.cs
+++ b/Artemis/Artemis/InjectionModules/BaseModules.cs
@@ -16,7 +16,8 @@ namespace Artemis.InjectionModules
{
// ViewModels
Bind().To().InSingletonScope();
- Bind().ToFactory();
+ Bind().ToFactory();
+ Bind().ToFactory();
Bind().ToSelf();
Bind().To().InSingletonScope();
diff --git a/Artemis/Artemis/Modules/Games/CounterStrike/CounterStrikeViewModel.cs b/Artemis/Artemis/Modules/Games/CounterStrike/CounterStrikeViewModel.cs
index d2908da24..6bfd6008c 100644
--- a/Artemis/Artemis/Modules/Games/CounterStrike/CounterStrikeViewModel.cs
+++ b/Artemis/Artemis/Modules/Games/CounterStrike/CounterStrikeViewModel.cs
@@ -11,7 +11,7 @@ namespace Artemis.Modules.Games.CounterStrike
{
public sealed class CounterStrikeViewModel : GameViewModel
{
- public CounterStrikeViewModel(MainManager main, IEventAggregator events, IProfileEditorViewModelFactory pFactory)
+ public CounterStrikeViewModel(MainManager main, IEventAggregator events, IProfileEditorVmFactory pFactory)
: base(main, new CounterStrikeModel(main, new CounterStrikeSettings()), events, pFactory)
{
DisplayName = "CS:GO";
diff --git a/Artemis/Artemis/Modules/Games/Dota2/Dota2ViewModel.cs b/Artemis/Artemis/Modules/Games/Dota2/Dota2ViewModel.cs
index 2334c907a..2fff1cc90 100644
--- a/Artemis/Artemis/Modules/Games/Dota2/Dota2ViewModel.cs
+++ b/Artemis/Artemis/Modules/Games/Dota2/Dota2ViewModel.cs
@@ -11,7 +11,7 @@ namespace Artemis.Modules.Games.Dota2
{
public sealed class Dota2ViewModel : GameViewModel
{
- public Dota2ViewModel(MainManager main, IEventAggregator events, IProfileEditorViewModelFactory pFactory)
+ public Dota2ViewModel(MainManager main, IEventAggregator events, IProfileEditorVmFactory pFactory)
: base(main, new Dota2Model(main, new Dota2Settings()), events, pFactory)
{
DisplayName = "Dota 2";
diff --git a/Artemis/Artemis/Modules/Games/Overwatch/OverwatchViewModel.cs b/Artemis/Artemis/Modules/Games/Overwatch/OverwatchViewModel.cs
index 10953e5a0..c1765707e 100644
--- a/Artemis/Artemis/Modules/Games/Overwatch/OverwatchViewModel.cs
+++ b/Artemis/Artemis/Modules/Games/Overwatch/OverwatchViewModel.cs
@@ -12,7 +12,7 @@ namespace Artemis.Modules.Games.Overwatch
{
public sealed class OverwatchViewModel : GameViewModel
{
- public OverwatchViewModel(MainManager main, IEventAggregator events, IProfileEditorViewModelFactory pFactory)
+ public OverwatchViewModel(MainManager main, IEventAggregator events, IProfileEditorVmFactory pFactory)
: base(main, new OverwatchModel(events, main, new OverwatchSettings()), events, pFactory)
{
DisplayName = "Overwatch";
diff --git a/Artemis/Artemis/Modules/Games/RocketLeague/RocketLeagueViewModel.cs b/Artemis/Artemis/Modules/Games/RocketLeague/RocketLeagueViewModel.cs
index 2cd6d9111..b71d5d4a1 100644
--- a/Artemis/Artemis/Modules/Games/RocketLeague/RocketLeagueViewModel.cs
+++ b/Artemis/Artemis/Modules/Games/RocketLeague/RocketLeagueViewModel.cs
@@ -13,7 +13,7 @@ namespace Artemis.Modules.Games.RocketLeague
{
private string _versionText;
- public RocketLeagueViewModel(MainManager main, IEventAggregator events, IProfileEditorViewModelFactory pFactory)
+ public RocketLeagueViewModel(MainManager main, IEventAggregator events, IProfileEditorVmFactory pFactory)
: base(main, new RocketLeagueModel(main, new RocketLeagueSettings()), events, pFactory)
{
DisplayName = "Rocket League";
diff --git a/Artemis/Artemis/Modules/Games/TheDivision/TheDivisionViewModel.cs b/Artemis/Artemis/Modules/Games/TheDivision/TheDivisionViewModel.cs
index 4d33f68c2..b30a07c1c 100644
--- a/Artemis/Artemis/Modules/Games/TheDivision/TheDivisionViewModel.cs
+++ b/Artemis/Artemis/Modules/Games/TheDivision/TheDivisionViewModel.cs
@@ -7,7 +7,7 @@ namespace Artemis.Modules.Games.TheDivision
{
public sealed class TheDivisionViewModel : GameViewModel
{
- public TheDivisionViewModel(MainManager main, IEventAggregator events, IProfileEditorViewModelFactory pFactory)
+ public TheDivisionViewModel(MainManager main, IEventAggregator events, IProfileEditorVmFactory pFactory)
: base(main, new TheDivisionModel(main, new TheDivisionSettings()), events, pFactory)
{
DisplayName = "The Division";
diff --git a/Artemis/Artemis/Modules/Games/Witcher3/Witcher3ViewModel.cs b/Artemis/Artemis/Modules/Games/Witcher3/Witcher3ViewModel.cs
index d03d3ffa5..559e7c8df 100644
--- a/Artemis/Artemis/Modules/Games/Witcher3/Witcher3ViewModel.cs
+++ b/Artemis/Artemis/Modules/Games/Witcher3/Witcher3ViewModel.cs
@@ -13,7 +13,7 @@ namespace Artemis.Modules.Games.Witcher3
{
public sealed class Witcher3ViewModel : GameViewModel
{
- public Witcher3ViewModel(MainManager main, IEventAggregator events, IProfileEditorViewModelFactory pFactory)
+ public Witcher3ViewModel(MainManager main, IEventAggregator events, IProfileEditorVmFactory pFactory)
: base(main, new Witcher3Model(main, new Witcher3Settings()), events, pFactory)
{
DisplayName = "The Witcher 3";
diff --git a/Artemis/Artemis/Utilities/GeneralHelpers.cs b/Artemis/Artemis/Utilities/GeneralHelpers.cs
index fa72c5e75..627a0bb00 100644
--- a/Artemis/Artemis/Utilities/GeneralHelpers.cs
+++ b/Artemis/Artemis/Utilities/GeneralHelpers.cs
@@ -60,6 +60,21 @@ namespace Artemis.Utilities
}
}
+ public static string Serialize(T source)
+ {
+ // Don't serialize a null object, simply return the default for that object
+ if (ReferenceEquals(source, null))
+ return null;
+
+ var serializer = new XmlSerializer(typeof(T));
+ var stream = new StringWriter();
+ using (stream)
+ {
+ serializer.Serialize(stream, source);
+ return stream.ToString();
+ }
+ }
+
public static object GetPropertyValue(object o, string path)
{
var propertyNames = path.Split('.');
diff --git a/Artemis/Artemis/ViewModels/Abstract/GameViewModel.cs b/Artemis/Artemis/ViewModels/Abstract/GameViewModel.cs
index 5974812b2..c292d9542 100644
--- a/Artemis/Artemis/ViewModels/Abstract/GameViewModel.cs
+++ b/Artemis/Artemis/ViewModels/Abstract/GameViewModel.cs
@@ -16,7 +16,7 @@ namespace Artemis.ViewModels.Abstract
private GameSettings _gameSettings;
protected GameViewModel(MainManager mainManager, GameModel gameModel, IEventAggregator events,
- IProfileEditorViewModelFactory pFactory)
+ IProfileEditorVmFactory pFactory)
{
MainManager = mainManager;
GameModel = gameModel;
@@ -24,7 +24,7 @@ namespace Artemis.ViewModels.Abstract
PFactory = pFactory;
GameSettings = gameModel.Settings;
- ProfileEditor = PFactory.CreateProfileEditorViewModel(Events, mainManager, gameModel,
+ ProfileEditor = PFactory.CreateProfileEditorVm(Events, mainManager, gameModel,
GameSettings.LastProfile);
GameModel.Profile = ProfileEditor.SelectedProfile;
ProfileEditor.PropertyChanged += ProfileUpdater;
@@ -41,7 +41,7 @@ namespace Artemis.ViewModels.Abstract
public MetroDialogService DialogService { get; set; }
public IEventAggregator Events { get; set; }
- public IProfileEditorViewModelFactory PFactory { get; set; }
+ public IProfileEditorVmFactory PFactory { get; set; }
public ProfileEditorViewModel ProfileEditor { get; set; }
diff --git a/Artemis/Artemis/ViewModels/Profiles/LayerEditorViewModel.cs b/Artemis/Artemis/ViewModels/Profiles/LayerEditorViewModel.cs
index c15bbb9a7..6ce4208ae 100644
--- a/Artemis/Artemis/ViewModels/Profiles/LayerEditorViewModel.cs
+++ b/Artemis/Artemis/ViewModels/Profiles/LayerEditorViewModel.cs
@@ -1,6 +1,8 @@
-using System.ComponentModel;
+using System;
+using System.ComponentModel;
using System.IO;
using System.Linq;
+using System.Xml.Serialization;
using Artemis.Models.Interfaces;
using Artemis.Models.Profiles;
using Artemis.Models.Profiles.Properties;
@@ -8,6 +10,7 @@ using Artemis.Services;
using Artemis.Utilities;
using Artemis.ViewModels.Profiles.Properties;
using Caliburn.Micro;
+using Newtonsoft.Json;
using Ninject;
namespace Artemis.ViewModels.Profiles
@@ -26,6 +29,8 @@ namespace Artemis.ViewModels.Profiles
_gameDataModel = gameDataModel;
Layer = layer;
+ ProposedLayer = GeneralHelpers.Clone(layer);
+
if (Layer.Properties == null)
Layer.SetupProperties();
@@ -38,6 +43,8 @@ namespace Artemis.ViewModels.Profiles
PreSelect();
}
+ public bool ModelChanged { get; set; }
+
[Inject]
public MetroDialogService DialogService { get; set; }
@@ -69,17 +76,6 @@ namespace Artemis.ViewModels.Profiles
}
}
- public LayerPropertiesModel ProposedProperties
- {
- get { return _proposedProperties; }
- set
- {
- if (Equals(value, _proposedProperties)) return;
- _proposedProperties = value;
- NotifyOfPropertyChange(() => ProposedProperties);
- }
- }
-
public LayerType LayerType
{
get { return _layerType; }
@@ -102,17 +98,15 @@ namespace Artemis.ViewModels.Profiles
}
}
- public bool KeyboardGridIsVisible => Layer.LayerType == LayerType.Keyboard;
- public bool GifGridIsVisible => Layer.LayerType == LayerType.KeyboardGif;
+ public bool KeyboardGridIsVisible => ProposedLayer.LayerType == LayerType.Keyboard;
+ public bool GifGridIsVisible => ProposedLayer.LayerType == LayerType.KeyboardGif;
public void PreSelect()
{
- LayerType = Layer.LayerType;
+ LayerType = ProposedLayer.LayerType;
if (LayerType == LayerType.Folder && !(LayerPropertiesViewModel is FolderPropertiesViewModel))
- LayerPropertiesViewModel = new FolderPropertiesViewModel(_gameDataModel, Layer.Properties);
-
- ProposedProperties = GeneralHelpers.Clone(Layer.Properties);
+ LayerPropertiesViewModel = new FolderPropertiesViewModel(_gameDataModel, ProposedLayer.Properties);
}
private void PropertiesViewModelHandler(object sender, PropertyChangedEventArgs e)
@@ -124,14 +118,14 @@ namespace Artemis.ViewModels.Profiles
var oldBrush = LayerPropertiesViewModel?.GetAppliedProperties().Brush;
// Update the model
- if (Layer.LayerType != LayerType)
+ if (ProposedLayer.LayerType != LayerType)
{
- Layer.LayerType = LayerType;
- Layer.SetupProperties();
+ ProposedLayer.LayerType = LayerType;
+ ProposedLayer.SetupProperties();
}
if (oldBrush != null)
- Layer.Properties.Brush = oldBrush;
+ ProposedLayer.Properties.Brush = oldBrush;
// Update the KeyboardPropertiesViewModel if it's being used
var model = LayerPropertiesViewModel as KeyboardPropertiesViewModel;
@@ -142,17 +136,17 @@ namespace Artemis.ViewModels.Profiles
if ((LayerType == LayerType.Keyboard || LayerType == LayerType.KeyboardGif) &&
!(LayerPropertiesViewModel is KeyboardPropertiesViewModel))
{
- LayerPropertiesViewModel = new KeyboardPropertiesViewModel(_gameDataModel, Layer.Properties)
+ LayerPropertiesViewModel = new KeyboardPropertiesViewModel(_gameDataModel, ProposedLayer.Properties)
{
IsGif = LayerType == LayerType.KeyboardGif
};
}
else if (LayerType == LayerType.Mouse && !(LayerPropertiesViewModel is MousePropertiesViewModel))
- LayerPropertiesViewModel = new MousePropertiesViewModel(_gameDataModel, Layer.Properties);
+ LayerPropertiesViewModel = new MousePropertiesViewModel(_gameDataModel, ProposedLayer.Properties);
else if (LayerType == LayerType.Headset && !(LayerPropertiesViewModel is HeadsetPropertiesViewModel))
- LayerPropertiesViewModel = new HeadsetPropertiesViewModel(_gameDataModel, Layer.Properties);
+ LayerPropertiesViewModel = new HeadsetPropertiesViewModel(_gameDataModel, ProposedLayer.Properties);
else if (LayerType == LayerType.Folder && !(LayerPropertiesViewModel is FolderPropertiesViewModel))
- LayerPropertiesViewModel = new FolderPropertiesViewModel(_gameDataModel, Layer.Properties);
+ LayerPropertiesViewModel = new FolderPropertiesViewModel(_gameDataModel, ProposedLayer.Properties);
NotifyOfPropertyChange(() => LayerPropertiesViewModel);
}
@@ -165,11 +159,17 @@ namespace Artemis.ViewModels.Profiles
public void Apply()
{
+ Layer.Name = ProposedLayer.Name;
+ Layer.LayerType = ProposedLayer.LayerType;
+
if (LayerPropertiesViewModel != null)
Layer.Properties = LayerPropertiesViewModel.GetAppliedProperties();
Layer.Properties.Conditions.Clear();
foreach (var conditionViewModel in LayerConditionVms)
+ {
+
Layer.Properties.Conditions.Add(conditionViewModel.LayerConditionModel);
+ }
if (Layer.LayerType != LayerType.KeyboardGif)
return; // Don't bother checking for a GIF path unless the type is GIF
@@ -183,5 +183,29 @@ namespace Artemis.ViewModels.Profiles
LayerConditionVms.Remove(layerConditionViewModel);
Layer.Properties.Conditions.Remove(layerConditionModel);
}
+
+ public override async void CanClose(Action callback)
+ {
+ // Create a fake layer and apply the properties to it
+ var fakeLayer = GeneralHelpers.Clone(ProposedLayer);
+ if (LayerPropertiesViewModel != null)
+ fakeLayer.Properties = LayerPropertiesViewModel.GetAppliedProperties();
+ fakeLayer.Properties.Conditions.Clear();
+ foreach (var conditionViewModel in LayerConditionVms)
+ fakeLayer.Properties.Conditions.Add(conditionViewModel.LayerConditionModel);
+
+
+ var fake = GeneralHelpers.Serialize(fakeLayer);
+ var real = GeneralHelpers.Serialize(Layer);
+
+ if (fake.Equals(real))
+ {
+ callback(true);
+ return;
+ }
+
+ var close = await DialogService.ShowQuestionMessageBox("Unsaved changes", "Do you want to discard your changes?");
+ callback(close.Value);
+ }
}
}
\ No newline at end of file
diff --git a/Artemis/Artemis/ViewModels/Profiles/ProfileEditorViewModel.cs b/Artemis/Artemis/ViewModels/Profiles/ProfileEditorViewModel.cs
index 01b6381f6..b99c93683 100644
--- a/Artemis/Artemis/ViewModels/Profiles/ProfileEditorViewModel.cs
+++ b/Artemis/Artemis/ViewModels/Profiles/ProfileEditorViewModel.cs
@@ -12,6 +12,7 @@ using System.Windows.Media.Imaging;
using Artemis.DAL;
using Artemis.DeviceProviders;
using Artemis.Events;
+using Artemis.InjectionFactories;
using Artemis.Managers;
using Artemis.Models;
using Artemis.Models.Profiles;
@@ -33,18 +34,20 @@ namespace Artemis.ViewModels.Profiles
public sealed class ProfileEditorViewModel : Screen, IHandle, IDropTarget
{
private readonly GameModel _gameModel;
+ private readonly ILayerEditorVmFactory _layerEditorVmFactory;
private readonly MainManager _mainManager;
- private LayerEditorViewModel _editorVm;
private ImageSource _keyboardPreview;
private BindableCollection _layers;
private BindableCollection _profiles;
private ProfileModel _selectedProfile;
public ProfileEditorViewModel(IEventAggregator events, MainManager mainManager, GameModel gameModel,
- ProfileViewModel profileViewModel, MetroDialogService dialogService, string lastProfile)
+ ProfileViewModel profileViewModel, MetroDialogService dialogService, string lastProfile,
+ ILayerEditorVmFactory layerEditorVmFactory)
{
_mainManager = mainManager;
_gameModel = gameModel;
+ _layerEditorVmFactory = layerEditorVmFactory;
Profiles = new BindableCollection();
Layers = new BindableCollection();
@@ -263,7 +266,7 @@ namespace Artemis.ViewModels.Profiles
public void EditLayer(LayerModel layer)
{
IWindowManager manager = new WindowManager();
- _editorVm = new LayerEditorViewModel(_gameModel.GameDataModel, layer);
+ var editorVm = _layerEditorVmFactory.CreateLayerEditorVm(_gameModel.GameDataModel, layer);
dynamic settings = new ExpandoObject();
var iconImage = new Image
{
@@ -278,7 +281,7 @@ namespace Artemis.ViewModels.Profiles
settings.Title = "Artemis | Edit " + layer.Name;
settings.Icon = bitmap;
- manager.ShowDialog(_editorVm, null, settings);
+ manager.ShowDialog(editorVm, null, settings);
// If the layer was a folder, but isn't anymore, assign it's children to it's parent.
if (layer.LayerType != LayerType.Folder && layer.Children.Any())
diff --git a/Artemis/Artemis/Views/Profiles/LayerEditorView.xaml b/Artemis/Artemis/Views/Profiles/LayerEditorView.xaml
index a695107ea..a6655937f 100644
--- a/Artemis/Artemis/Views/Profiles/LayerEditorView.xaml
+++ b/Artemis/Artemis/Views/Profiles/LayerEditorView.xaml
@@ -45,7 +45,7 @@
-
+