diff --git a/Artemis/Artemis/DAL/ProfileProvider.cs b/Artemis/Artemis/DAL/ProfileProvider.cs
index 6f1ce47c8..e6c5237ec 100644
--- a/Artemis/Artemis/DAL/ProfileProvider.cs
+++ b/Artemis/Artemis/DAL/ProfileProvider.cs
@@ -6,11 +6,13 @@ using System.Xml.Serialization;
using Artemis.DeviceProviders;
using Artemis.Models;
using Artemis.Models.Profiles;
+using NLog;
namespace Artemis.DAL
{
public static class ProfileProvider
{
+ private static Logger _logger = LogManager.GetCurrentClassLogger();
private static readonly string ProfileFolder =
Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + @"\Artemis\profiles";
@@ -56,9 +58,12 @@ namespace Artemis.DAL
Directory.CreateDirectory(path);
var serializer = new XmlSerializer(typeof(ProfileModel));
- using (var file = new StreamWriter(path + $@"\{prof.Name}.xml"))
+
+ // Could use a StreamWriter but should serializing fail this method doesn't ruin the existing XML file
+ using (var xml = new StringWriter())
{
- serializer.Serialize(file, prof);
+ serializer.Serialize(xml, prof);
+ File.WriteAllText(path + $@"\{prof.Name}.xml", xml.ToString());
}
}
@@ -71,16 +76,23 @@ namespace Artemis.DAL
var profilePaths = Directory.GetFiles(ProfileFolder, "*.xml", SearchOption.AllDirectories);
// Parse the JSON files into objects and add them if they are valid
- // TODO: Invalid file handling
var deserializer = new XmlSerializer(typeof(ProfileModel));
foreach (var path in profilePaths)
{
- using (var file = new StreamReader(path))
+ try
{
- var prof = (ProfileModel) deserializer.Deserialize(file);
- if (prof.GameName?.Length > 1 && prof.KeyboardName?.Length > 1 && prof.Name?.Length > 1)
- profiles.Add(prof);
+ using (var file = new StreamReader(path))
+ {
+ var prof = (ProfileModel)deserializer.Deserialize(file);
+ if (prof.GameName?.Length > 1 && prof.KeyboardName?.Length > 1 && prof.Name?.Length > 1)
+ profiles.Add(prof);
+ }
}
+ catch (InvalidOperationException e)
+ {
+ _logger.Error("Failed to load profile: {0} - {1}", path, e.InnerException.Message);
+ }
+
}
return profiles;
diff --git a/Artemis/Artemis/Models/Profiles/LayerModel.cs b/Artemis/Artemis/Models/Profiles/LayerModel.cs
index 16a8afa72..524e62b94 100644
--- a/Artemis/Artemis/Models/Profiles/LayerModel.cs
+++ b/Artemis/Artemis/Models/Profiles/LayerModel.cs
@@ -59,12 +59,11 @@ namespace Artemis.Models.Profiles
}
else
appliedProperties = GeneralHelpers.Clone(Properties);
-
+
// Update animations on layer types that support them
- if ((LayerType == LayerType.Keyboard || LayerType == LayerType.KeyboardGif) && updateAnimations)
+ if ((LayerType == LayerType.Keyboard || LayerType == LayerType.KeyboardGif))
{
- AnimationUpdater.UpdateAnimation((KeyboardPropertiesModel) Properties,
- (KeyboardPropertiesModel) appliedProperties);
+ AnimationUpdater.UpdateAnimation((KeyboardPropertiesModel) Properties, (KeyboardPropertiesModel) appliedProperties, updateAnimations);
}
switch (LayerType)
@@ -195,6 +194,27 @@ namespace Artemis.Models.Profiles
}
#endregion
+
+ public static LayerModel CreateLayer()
+ {
+ return new LayerModel
+ {
+ Name = "New layer",
+ Enabled = true,
+ Order = -1,
+ LayerType = LayerType.Keyboard,
+ Properties = new KeyboardPropertiesModel
+ {
+ Brush = new SolidColorBrush(ColorHelpers.GetRandomRainbowMediaColor()),
+ Animation = LayerAnimation.None,
+ Height = 1,
+ Width = 1,
+ X = 0,
+ Y = 0,
+ Opacity = 1
+ }
+ };
+ }
}
public enum LayerType
diff --git a/Artemis/Artemis/Models/Profiles/ProfileModel.cs b/Artemis/Artemis/Models/Profiles/ProfileModel.cs
index 83e237b8f..58c30b6dd 100644
--- a/Artemis/Artemis/Models/Profiles/ProfileModel.cs
+++ b/Artemis/Artemis/Models/Profiles/ProfileModel.cs
@@ -28,6 +28,7 @@ namespace Artemis.Models.Profiles
public string Name { get; set; }
public string KeyboardName { get; set; }
public string GameName { get; set; }
+ public bool IsDefault { get; set; }
[XmlIgnore]
public DrawingVisual DrawingVisual { get; set; }
@@ -58,36 +59,6 @@ namespace Artemis.Models.Profiles
}
}
- ///
- /// Adds a new layer with default settings to the profile
- ///
- /// The newly added layer
- public LayerModel AddLayer()
- {
- var layer = new LayerModel
- {
- Name = "New layer",
- Enabled = true,
- Order = -1,
- LayerType = LayerType.Keyboard,
- Properties = new KeyboardPropertiesModel
- {
- Brush = new SolidColorBrush(ColorHelpers.GetRandomRainbowMediaColor()),
- Animation = LayerAnimation.None,
- Height = 1,
- Width = 1,
- X = 0,
- Y = 0,
- Opacity = 1
- }
- };
-
- Layers.Add(layer);
- FixOrder();
-
- return layer;
- }
-
public void FixOrder()
{
Layers.Sort(l => l.Order);
diff --git a/Artemis/Artemis/Models/Profiles/Properties/KeyboardPropertiesModel.cs b/Artemis/Artemis/Models/Profiles/Properties/KeyboardPropertiesModel.cs
index 50398a3ad..3f02b5950 100644
--- a/Artemis/Artemis/Models/Profiles/Properties/KeyboardPropertiesModel.cs
+++ b/Artemis/Artemis/Models/Profiles/Properties/KeyboardPropertiesModel.cs
@@ -24,6 +24,8 @@ namespace Artemis.Models.Profiles.Properties
public double AnimationSpeed { get; set; }
public string GifFile { get; set; }
public List DynamicProperties { get; set; }
+
+ [XmlIgnore]
public double AnimationProgress { get; set; }
public Rect GetRect(int scale = 4)
diff --git a/Artemis/Artemis/Services/DialogService.cs b/Artemis/Artemis/Services/DialogService.cs
index b5a312a7d..b051ab978 100644
--- a/Artemis/Artemis/Services/DialogService.cs
+++ b/Artemis/Artemis/Services/DialogService.cs
@@ -22,6 +22,7 @@
using System;
using System.Threading.Tasks;
+using MahApps.Metro.Controls.Dialogs;
namespace Artemis.Services
{
@@ -41,7 +42,7 @@ namespace Artemis.Services
public abstract bool ShowOpenDialog(out string path, string defaultExt, string filter, string initialDir = null);
- public abstract Task ShowInputDialog(string title, string message);
+ public abstract Task ShowInputDialog(string title, string message, MetroDialogSettings settings = null);
public abstract Task ShowQuestionMessageBox(string title, string message);
}
diff --git a/Artemis/Artemis/Services/MetroDialogService.cs b/Artemis/Artemis/Services/MetroDialogService.cs
index 1f4a59c54..ba7328bff 100644
--- a/Artemis/Artemis/Services/MetroDialogService.cs
+++ b/Artemis/Artemis/Services/MetroDialogService.cs
@@ -75,12 +75,12 @@ namespace Artemis.Services
}
}
- public override Task ShowInputDialog(string title, string message)
+ public override Task ShowInputDialog(string title, string message, MetroDialogSettings settings = null)
{
if (GetActiveWindow() == null)
return null;
- return GetActiveWindow().ShowInputAsync(title, message);
+ return GetActiveWindow().ShowInputAsync(title, message, settings);
}
public override bool ShowOpenDialog(out string path, string defaultExt, string filter, string initialDir = null)
diff --git a/Artemis/Artemis/Utilities/Layers/AnimationUpdater.cs b/Artemis/Artemis/Utilities/Layers/AnimationUpdater.cs
index 9745bb90e..359260155 100644
--- a/Artemis/Artemis/Utilities/Layers/AnimationUpdater.cs
+++ b/Artemis/Artemis/Utilities/Layers/AnimationUpdater.cs
@@ -4,10 +4,11 @@ namespace Artemis.Utilities.Layers
{
public static class AnimationUpdater
{
- public static void UpdateAnimation(KeyboardPropertiesModel properties, KeyboardPropertiesModel appliedProperties)
+ public static void UpdateAnimation(KeyboardPropertiesModel properties, KeyboardPropertiesModel appliedProperties, bool updateAnimations)
{
const int scale = 4;
var animateProperties = properties.Contain ? appliedProperties : properties;
+ appliedProperties.AnimationProgress = properties.AnimationProgress;
var progress = appliedProperties.AnimationProgress;
// Horizontal sliding
@@ -40,8 +41,10 @@ namespace Artemis.Utilities.Layers
}
appliedProperties.AnimationProgress = progress;
- // Store the animation progress in the actual model for the next frame
- properties.AnimationProgress = progress;
+
+ // If not previewing, store the animation progress in the actual model for the next frame
+ if (updateAnimations)
+ properties.AnimationProgress = progress;
}
}
}
\ No newline at end of file
diff --git a/Artemis/Artemis/ViewModels/Flyouts/FlyoutSettingsViewModel.cs b/Artemis/Artemis/ViewModels/Flyouts/FlyoutSettingsViewModel.cs
index 433fc4e54..d965ff689 100644
--- a/Artemis/Artemis/ViewModels/Flyouts/FlyoutSettingsViewModel.cs
+++ b/Artemis/Artemis/ViewModels/Flyouts/FlyoutSettingsViewModel.cs
@@ -6,7 +6,10 @@ using Artemis.Managers;
using Artemis.Settings;
using Caliburn.Micro;
using MahApps.Metro.Controls;
-using Ninject.Extensions.Logging;
+using NLog;
+using NLog.Config;
+using NLog.Targets;
+using ILogger = Ninject.Extensions.Logging.ILogger;
namespace Artemis.ViewModels.Flyouts
{
@@ -15,6 +18,7 @@ namespace Artemis.ViewModels.Flyouts
{
private readonly ILogger _logger;
private string _activeEffectName;
+ private bool _enableDebug;
private GeneralSettings _generalSettings;
private string _selectedKeyboardProvider;
@@ -29,6 +33,20 @@ namespace Artemis.ViewModels.Flyouts
PropertyChanged += KeyboardUpdater;
events.Subscribe(this);
+ ApplyLogging();
+ }
+
+ public MainManager MainManager { get; set; }
+
+ public bool EnableDebug
+ {
+ get { return _enableDebug; }
+ set
+ {
+ if (value == _enableDebug) return;
+ _enableDebug = value;
+ NotifyOfPropertyChange(() => EnableDebug);
+ }
}
public GeneralSettings GeneralSettings
@@ -42,8 +60,6 @@ namespace Artemis.ViewModels.Flyouts
}
}
- public MainManager MainManager { get; set; }
-
public BindableCollection KeyboardProviders
{
get
@@ -100,6 +116,27 @@ namespace Artemis.ViewModels.Flyouts
NotifyOfPropertyChange(() => Enabled);
}
+ // TODO https://github.com/ninject/Ninject.Extensions.Logging/issues/35
+ private void ApplyLogging()
+ {
+ var c = NLog.LogManager.Configuration;
+ var file = c.FindTargetByName("file") as FileTarget;
+ if (file == null)
+ return;
+
+ var rule = c.LoggingRules.FirstOrDefault(r => r.Targets.Contains(file));
+ if (rule == null)
+ return;
+
+ if (EnableDebug)
+ rule.EnableLoggingForLevel(LogLevel.Debug);
+ else
+ rule.DisableLoggingForLevel(LogLevel.Debug);
+
+ NLog.LogManager.ReconfigExistingLoggers();
+ _logger.Info("Set debug logging to: {0}", EnableDebug);
+ }
+
///
/// Takes proper action when the selected keyboard is changed in the UI
///
diff --git a/Artemis/Artemis/ViewModels/Profiles/LayerEditorViewModel.cs b/Artemis/Artemis/ViewModels/Profiles/LayerEditorViewModel.cs
index 28257dcc9..c15bbb9a7 100644
--- a/Artemis/Artemis/ViewModels/Profiles/LayerEditorViewModel.cs
+++ b/Artemis/Artemis/ViewModels/Profiles/LayerEditorViewModel.cs
@@ -120,6 +120,9 @@ namespace Artemis.ViewModels.Profiles
if (e.PropertyName != "LayerType")
return;
+ // Store the brush in case the user wants to reuse it
+ var oldBrush = LayerPropertiesViewModel?.GetAppliedProperties().Brush;
+
// Update the model
if (Layer.LayerType != LayerType)
{
@@ -127,6 +130,9 @@ namespace Artemis.ViewModels.Profiles
Layer.SetupProperties();
}
+ if (oldBrush != null)
+ Layer.Properties.Brush = oldBrush;
+
// Update the KeyboardPropertiesViewModel if it's being used
var model = LayerPropertiesViewModel as KeyboardPropertiesViewModel;
if (model != null)
diff --git a/Artemis/Artemis/ViewModels/Profiles/ProfileEditorViewModel.cs b/Artemis/Artemis/ViewModels/Profiles/ProfileEditorViewModel.cs
index b2ffce466..0b3dabf26 100644
--- a/Artemis/Artemis/ViewModels/Profiles/ProfileEditorViewModel.cs
+++ b/Artemis/Artemis/ViewModels/Profiles/ProfileEditorViewModel.cs
@@ -17,6 +17,7 @@ using Artemis.Styles.DropTargetAdorners;
using Artemis.Utilities;
using Caliburn.Micro;
using GongSolutions.Wpf.DragDrop;
+using MahApps.Metro.Controls.Dialogs;
using Ninject;
using DragDropEffects = System.Windows.DragDropEffects;
using IDropTarget = GongSolutions.Wpf.DragDrop.IDropTarget;
@@ -191,6 +192,12 @@ namespace Artemis.ViewModels.Profiles
if (e.PropertyName == "KeyboardPreview")
return;
+ if (e.PropertyName == "SelectedLayer")
+ {
+ NotifyOfPropertyChange(() => LayerSelected);
+ return;
+ }
+
if (SelectedProfile != null)
ProfileProvider.AddOrUpdate(SelectedProfile);
@@ -203,9 +210,8 @@ namespace Artemis.ViewModels.Profiles
Layers.Clear();
if (SelectedProfile != null)
Layers.AddRange(SelectedProfile.Layers);
- // Update booleans
+
NotifyOfPropertyChange(() => ProfileSelected);
- NotifyOfPropertyChange(() => LayerSelected);
}
///
@@ -226,14 +232,14 @@ namespace Artemis.ViewModels.Profiles
if (ProfileViewModel.SelectedLayer == null)
return;
- LayerEditor(ProfileViewModel.SelectedLayer);
+ EditLayer(ProfileViewModel.SelectedLayer);
}
///
/// Opens a new LayerEditorView for the given layer
///
/// The layer to open the view for
- public void LayerEditor(LayerModel layer)
+ public void EditLayer(LayerModel layer)
{
IWindowManager manager = new WindowManager();
_editorVm = new LayerEditorViewModel(_gameModel.GameDataModel, layer);
@@ -273,10 +279,27 @@ namespace Artemis.ViewModels.Profiles
if (SelectedProfile == null)
return;
- var layer = SelectedProfile.AddLayer();
- Layers.Add(layer);
+ // Create a new layer
+ var layer = LayerModel.CreateLayer();
- ProfileViewModel.SelectedLayer = layer;
+ // If there is a selected layer and it has a parent, bind the new layer to it
+ if (ProfileViewModel.SelectedLayer?.Parent != null)
+ {
+ layer.Order = ProfileViewModel.SelectedLayer.Order + 1;
+ ProfileViewModel.SelectedLayer.Parent.Children.Add(layer);
+ ProfileViewModel.SelectedLayer.Parent.FixOrder();
+ }
+ else
+ {
+ // If there was no parent but there is a layer selected, put it below the selected layer
+ if (ProfileViewModel.SelectedLayer != null)
+ layer.Order = ProfileViewModel.SelectedLayer.Order + 1;
+
+ SelectedProfile.Layers.Add(layer);
+ SelectedProfile.FixOrder();
+ }
+
+ UpdateLayerList(layer);
}
///
@@ -284,27 +307,58 @@ namespace Artemis.ViewModels.Profiles
///
public void RemoveLayer()
{
- if (SelectedProfile == null || ProfileViewModel.SelectedLayer == null)
- return;
-
- SelectedProfile.Layers.Remove(ProfileViewModel.SelectedLayer);
- Layers.Remove(ProfileViewModel.SelectedLayer);
-
- SelectedProfile.FixOrder();
+ RemoveLayer(ProfileViewModel.SelectedLayer);
}
///
/// Removes the given layer from the profile
///
///
- public void RemoveLayerFromMenu(LayerModel layer)
+ public void RemoveLayer(LayerModel layer)
{
- SelectedProfile.Layers.Remove(layer);
- Layers.Remove(layer);
+ if (layer == null)
+ return;
- SelectedProfile.FixOrder();
+ if (layer.Parent != null)
+ {
+ var parent = layer.Parent;
+ layer.Parent.Children.Remove(layer);
+ parent.FixOrder();
+ }
+ else if (layer.Profile != null)
+ {
+ var profile = layer.Profile;
+ layer.Profile.Layers.Remove(layer);
+ profile.FixOrder();
+ }
+
+ // Extra cleanup in case of a wonky layer that has no parent
+ if (SelectedProfile.Layers.Contains(layer))
+ SelectedProfile.Layers.Remove(layer);
+
+ UpdateLayerList(null);
}
+ public async void RenameLayer(LayerModel layer)
+ {
+ if (layer == null)
+ return;
+
+ var newName =
+ await
+ DialogService.ShowInputDialog("Rename layer", "Please enter a name for the layer",
+ new MetroDialogSettings {DefaultText = layer.Name});
+ // Null when the user cancelled
+ if (string.IsNullOrEmpty(newName))
+ return;
+
+ layer.Name = newName;
+ UpdateLayerList(layer);
+ }
+
+ ///
+ /// Clones the currently selected layer and adds it to the profile, on top of the original
+ ///
public void CloneLayer()
{
if (ProfileViewModel.SelectedLayer == null)
@@ -320,11 +374,20 @@ namespace Artemis.ViewModels.Profiles
public void CloneLayer(LayerModel layer)
{
var clone = GeneralHelpers.Clone(layer);
- clone.Order = layer.Order - 1;
- SelectedProfile.Layers.Add(clone);
- Layers.Add(clone);
+ clone.Order++;
- SelectedProfile.FixOrder();
+ if (layer.Parent != null)
+ {
+ layer.Parent.Children.Add(clone);
+ layer.Parent.FixOrder();
+ }
+ else if (layer.Profile != null)
+ {
+ layer.Profile.Layers.Add(clone);
+ layer.Profile.FixOrder();
+ }
+
+ UpdateLayerList(clone);
}
private void UpdateLayerList(LayerModel selectModel)
@@ -334,6 +397,9 @@ namespace Artemis.ViewModels.Profiles
if (SelectedProfile != null)
Layers.AddRange(SelectedProfile.Layers);
+ if (selectModel == null)
+ return;
+
// A small delay to allow the profile list to rebuild
Task.Factory.StartNew(() =>
{
diff --git a/Artemis/Artemis/Views/Profiles/ProfileEditorView.xaml b/Artemis/Artemis/Views/Profiles/ProfileEditorView.xaml
index 9b893fdf3..4e915fa00 100644
--- a/Artemis/Artemis/Views/Profiles/ProfileEditorView.xaml
+++ b/Artemis/Artemis/Views/Profiles/ProfileEditorView.xaml
@@ -158,10 +158,10 @@
-
+
-
-
+
+
@@ -192,7 +192,7 @@