1
0
mirror of https://github.com/Artemis-RGB/Artemis synced 2025-12-13 05:48:35 +00:00

UI polish

This commit is contained in:
SpoinkyNL 2016-05-30 23:53:53 +02:00
parent b01f9485ae
commit eb59ddc816
11 changed files with 194 additions and 76 deletions

View File

@ -6,11 +6,13 @@ using System.Xml.Serialization;
using Artemis.DeviceProviders; using Artemis.DeviceProviders;
using Artemis.Models; using Artemis.Models;
using Artemis.Models.Profiles; using Artemis.Models.Profiles;
using NLog;
namespace Artemis.DAL namespace Artemis.DAL
{ {
public static class ProfileProvider public static class ProfileProvider
{ {
private static Logger _logger = LogManager.GetCurrentClassLogger();
private static readonly string ProfileFolder = private static readonly string ProfileFolder =
Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + @"\Artemis\profiles"; Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + @"\Artemis\profiles";
@ -56,9 +58,12 @@ namespace Artemis.DAL
Directory.CreateDirectory(path); Directory.CreateDirectory(path);
var serializer = new XmlSerializer(typeof(ProfileModel)); 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); var profilePaths = Directory.GetFiles(ProfileFolder, "*.xml", SearchOption.AllDirectories);
// Parse the JSON files into objects and add them if they are valid // Parse the JSON files into objects and add them if they are valid
// TODO: Invalid file handling
var deserializer = new XmlSerializer(typeof(ProfileModel)); var deserializer = new XmlSerializer(typeof(ProfileModel));
foreach (var path in profilePaths) foreach (var path in profilePaths)
{ {
using (var file = new StreamReader(path)) try
{ {
var prof = (ProfileModel) deserializer.Deserialize(file); using (var file = new StreamReader(path))
if (prof.GameName?.Length > 1 && prof.KeyboardName?.Length > 1 && prof.Name?.Length > 1) {
profiles.Add(prof); 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; return profiles;

View File

@ -61,10 +61,9 @@ namespace Artemis.Models.Profiles
appliedProperties = GeneralHelpers.Clone(Properties); appliedProperties = GeneralHelpers.Clone(Properties);
// Update animations on layer types that support them // 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, AnimationUpdater.UpdateAnimation((KeyboardPropertiesModel) Properties, (KeyboardPropertiesModel) appliedProperties, updateAnimations);
(KeyboardPropertiesModel) appliedProperties);
} }
switch (LayerType) switch (LayerType)
@ -195,6 +194,27 @@ namespace Artemis.Models.Profiles
} }
#endregion #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 public enum LayerType

View File

@ -28,6 +28,7 @@ namespace Artemis.Models.Profiles
public string Name { get; set; } public string Name { get; set; }
public string KeyboardName { get; set; } public string KeyboardName { get; set; }
public string GameName { get; set; } public string GameName { get; set; }
public bool IsDefault { get; set; }
[XmlIgnore] [XmlIgnore]
public DrawingVisual DrawingVisual { get; set; } public DrawingVisual DrawingVisual { get; set; }
@ -58,36 +59,6 @@ namespace Artemis.Models.Profiles
} }
} }
/// <summary>
/// Adds a new layer with default settings to the profile
/// </summary>
/// <returns>The newly added layer</returns>
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() public void FixOrder()
{ {
Layers.Sort(l => l.Order); Layers.Sort(l => l.Order);

View File

@ -24,6 +24,8 @@ namespace Artemis.Models.Profiles.Properties
public double AnimationSpeed { get; set; } public double AnimationSpeed { get; set; }
public string GifFile { get; set; } public string GifFile { get; set; }
public List<DynamicPropertiesModel> DynamicProperties { get; set; } public List<DynamicPropertiesModel> DynamicProperties { get; set; }
[XmlIgnore]
public double AnimationProgress { get; set; } public double AnimationProgress { get; set; }
public Rect GetRect(int scale = 4) public Rect GetRect(int scale = 4)

View File

@ -22,6 +22,7 @@
using System; using System;
using System.Threading.Tasks; using System.Threading.Tasks;
using MahApps.Metro.Controls.Dialogs;
namespace Artemis.Services 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 bool ShowOpenDialog(out string path, string defaultExt, string filter, string initialDir = null);
public abstract Task<string> ShowInputDialog(string title, string message); public abstract Task<string> ShowInputDialog(string title, string message, MetroDialogSettings settings = null);
public abstract Task<bool?> ShowQuestionMessageBox(string title, string message); public abstract Task<bool?> ShowQuestionMessageBox(string title, string message);
} }

View File

@ -75,12 +75,12 @@ namespace Artemis.Services
} }
} }
public override Task<string> ShowInputDialog(string title, string message) public override Task<string> ShowInputDialog(string title, string message, MetroDialogSettings settings = null)
{ {
if (GetActiveWindow() == null) if (GetActiveWindow() == null)
return 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) public override bool ShowOpenDialog(out string path, string defaultExt, string filter, string initialDir = null)

View File

@ -4,10 +4,11 @@ namespace Artemis.Utilities.Layers
{ {
public static class AnimationUpdater 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; const int scale = 4;
var animateProperties = properties.Contain ? appliedProperties : properties; var animateProperties = properties.Contain ? appliedProperties : properties;
appliedProperties.AnimationProgress = properties.AnimationProgress;
var progress = appliedProperties.AnimationProgress; var progress = appliedProperties.AnimationProgress;
// Horizontal sliding // Horizontal sliding
@ -40,8 +41,10 @@ namespace Artemis.Utilities.Layers
} }
appliedProperties.AnimationProgress = progress; 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;
} }
} }
} }

View File

@ -6,7 +6,10 @@ using Artemis.Managers;
using Artemis.Settings; using Artemis.Settings;
using Caliburn.Micro; using Caliburn.Micro;
using MahApps.Metro.Controls; 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 namespace Artemis.ViewModels.Flyouts
{ {
@ -15,6 +18,7 @@ namespace Artemis.ViewModels.Flyouts
{ {
private readonly ILogger _logger; private readonly ILogger _logger;
private string _activeEffectName; private string _activeEffectName;
private bool _enableDebug;
private GeneralSettings _generalSettings; private GeneralSettings _generalSettings;
private string _selectedKeyboardProvider; private string _selectedKeyboardProvider;
@ -29,6 +33,20 @@ namespace Artemis.ViewModels.Flyouts
PropertyChanged += KeyboardUpdater; PropertyChanged += KeyboardUpdater;
events.Subscribe(this); 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 public GeneralSettings GeneralSettings
@ -42,8 +60,6 @@ namespace Artemis.ViewModels.Flyouts
} }
} }
public MainManager MainManager { get; set; }
public BindableCollection<string> KeyboardProviders public BindableCollection<string> KeyboardProviders
{ {
get get
@ -100,6 +116,27 @@ namespace Artemis.ViewModels.Flyouts
NotifyOfPropertyChange(() => Enabled); 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);
}
/// <summary> /// <summary>
/// Takes proper action when the selected keyboard is changed in the UI /// Takes proper action when the selected keyboard is changed in the UI
/// </summary> /// </summary>

View File

@ -120,6 +120,9 @@ namespace Artemis.ViewModels.Profiles
if (e.PropertyName != "LayerType") if (e.PropertyName != "LayerType")
return; return;
// Store the brush in case the user wants to reuse it
var oldBrush = LayerPropertiesViewModel?.GetAppliedProperties().Brush;
// Update the model // Update the model
if (Layer.LayerType != LayerType) if (Layer.LayerType != LayerType)
{ {
@ -127,6 +130,9 @@ namespace Artemis.ViewModels.Profiles
Layer.SetupProperties(); Layer.SetupProperties();
} }
if (oldBrush != null)
Layer.Properties.Brush = oldBrush;
// Update the KeyboardPropertiesViewModel if it's being used // Update the KeyboardPropertiesViewModel if it's being used
var model = LayerPropertiesViewModel as KeyboardPropertiesViewModel; var model = LayerPropertiesViewModel as KeyboardPropertiesViewModel;
if (model != null) if (model != null)

View File

@ -17,6 +17,7 @@ using Artemis.Styles.DropTargetAdorners;
using Artemis.Utilities; using Artemis.Utilities;
using Caliburn.Micro; using Caliburn.Micro;
using GongSolutions.Wpf.DragDrop; using GongSolutions.Wpf.DragDrop;
using MahApps.Metro.Controls.Dialogs;
using Ninject; using Ninject;
using DragDropEffects = System.Windows.DragDropEffects; using DragDropEffects = System.Windows.DragDropEffects;
using IDropTarget = GongSolutions.Wpf.DragDrop.IDropTarget; using IDropTarget = GongSolutions.Wpf.DragDrop.IDropTarget;
@ -191,6 +192,12 @@ namespace Artemis.ViewModels.Profiles
if (e.PropertyName == "KeyboardPreview") if (e.PropertyName == "KeyboardPreview")
return; return;
if (e.PropertyName == "SelectedLayer")
{
NotifyOfPropertyChange(() => LayerSelected);
return;
}
if (SelectedProfile != null) if (SelectedProfile != null)
ProfileProvider.AddOrUpdate(SelectedProfile); ProfileProvider.AddOrUpdate(SelectedProfile);
@ -203,9 +210,8 @@ namespace Artemis.ViewModels.Profiles
Layers.Clear(); Layers.Clear();
if (SelectedProfile != null) if (SelectedProfile != null)
Layers.AddRange(SelectedProfile.Layers); Layers.AddRange(SelectedProfile.Layers);
// Update booleans
NotifyOfPropertyChange(() => ProfileSelected); NotifyOfPropertyChange(() => ProfileSelected);
NotifyOfPropertyChange(() => LayerSelected);
} }
/// <summary> /// <summary>
@ -226,14 +232,14 @@ namespace Artemis.ViewModels.Profiles
if (ProfileViewModel.SelectedLayer == null) if (ProfileViewModel.SelectedLayer == null)
return; return;
LayerEditor(ProfileViewModel.SelectedLayer); EditLayer(ProfileViewModel.SelectedLayer);
} }
/// <summary> /// <summary>
/// Opens a new LayerEditorView for the given layer /// Opens a new LayerEditorView for the given layer
/// </summary> /// </summary>
/// <param name="layer">The layer to open the view for</param> /// <param name="layer">The layer to open the view for</param>
public void LayerEditor(LayerModel layer) public void EditLayer(LayerModel layer)
{ {
IWindowManager manager = new WindowManager(); IWindowManager manager = new WindowManager();
_editorVm = new LayerEditorViewModel(_gameModel.GameDataModel, layer); _editorVm = new LayerEditorViewModel(_gameModel.GameDataModel, layer);
@ -273,10 +279,27 @@ namespace Artemis.ViewModels.Profiles
if (SelectedProfile == null) if (SelectedProfile == null)
return; return;
var layer = SelectedProfile.AddLayer(); // Create a new layer
Layers.Add(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);
} }
/// <summary> /// <summary>
@ -284,27 +307,58 @@ namespace Artemis.ViewModels.Profiles
/// </summary> /// </summary>
public void RemoveLayer() public void RemoveLayer()
{ {
if (SelectedProfile == null || ProfileViewModel.SelectedLayer == null) RemoveLayer(ProfileViewModel.SelectedLayer);
return;
SelectedProfile.Layers.Remove(ProfileViewModel.SelectedLayer);
Layers.Remove(ProfileViewModel.SelectedLayer);
SelectedProfile.FixOrder();
} }
/// <summary> /// <summary>
/// Removes the given layer from the profile /// Removes the given layer from the profile
/// </summary> /// </summary>
/// <param name="layer"></param> /// <param name="layer"></param>
public void RemoveLayerFromMenu(LayerModel layer) public void RemoveLayer(LayerModel layer)
{ {
SelectedProfile.Layers.Remove(layer); if (layer == null)
Layers.Remove(layer); 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);
}
/// <summary>
/// Clones the currently selected layer and adds it to the profile, on top of the original
/// </summary>
public void CloneLayer() public void CloneLayer()
{ {
if (ProfileViewModel.SelectedLayer == null) if (ProfileViewModel.SelectedLayer == null)
@ -320,11 +374,20 @@ namespace Artemis.ViewModels.Profiles
public void CloneLayer(LayerModel layer) public void CloneLayer(LayerModel layer)
{ {
var clone = GeneralHelpers.Clone(layer); var clone = GeneralHelpers.Clone(layer);
clone.Order = layer.Order - 1; clone.Order++;
SelectedProfile.Layers.Add(clone);
Layers.Add(clone);
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) private void UpdateLayerList(LayerModel selectModel)
@ -334,6 +397,9 @@ namespace Artemis.ViewModels.Profiles
if (SelectedProfile != null) if (SelectedProfile != null)
Layers.AddRange(SelectedProfile.Layers); Layers.AddRange(SelectedProfile.Layers);
if (selectModel == null)
return;
// A small delay to allow the profile list to rebuild // A small delay to allow the profile list to rebuild
Task.Factory.StartNew(() => Task.Factory.StartNew(() =>
{ {

View File

@ -158,10 +158,10 @@
<StackPanel.ContextMenu> <StackPanel.ContextMenu>
<ContextMenu <ContextMenu
cal:Action.TargetWithoutContext="{Binding Path=PlacementTarget.Tag, RelativeSource={RelativeSource Self}}"> cal:Action.TargetWithoutContext="{Binding Path=PlacementTarget.Tag, RelativeSource={RelativeSource Self}}">
<MenuItem Header="Rename" /> <MenuItem Header="Rename" cal:Message.Attach="RenameLayer($datacontext)" />
<MenuItem Header="Duplicate" cal:Message.Attach="CloneLayer($datacontext)" /> <MenuItem Header="Duplicate" cal:Message.Attach="CloneLayer($datacontext)" />
<MenuItem Header="Delete" cal:Message.Attach="RemoveLayerFromMenu($datacontext)" /> <MenuItem Header="Delete" cal:Message.Attach="RemoveLayer($datacontext)" />
<MenuItem Header="Properties" cal:Message.Attach="LayerEditor($datacontext)" /> <MenuItem Header="Properties" cal:Message.Attach="EditLayer($datacontext)" />
</ContextMenu> </ContextMenu>
</StackPanel.ContextMenu> </StackPanel.ContextMenu>
<CheckBox VerticalAlignment="Center" ToolTip="Layer enabled" IsChecked="{Binding Enabled}" /> <CheckBox VerticalAlignment="Center" ToolTip="Layer enabled" IsChecked="{Binding Enabled}" />
@ -192,7 +192,7 @@
</Button.Content> </Button.Content>
</Button> </Button>
<Button x:Name="EditLayer" VerticalAlignment="Top" Style="{DynamicResource SquareButtonStyle}" <Button x:Name="EditLayer" VerticalAlignment="Top" Style="{DynamicResource SquareButtonStyle}"
Width="26" Height="26" HorizontalAlignment="Right" Margin="10,0,0,0" ToolTip="Rename layer" Width="26" Height="26" HorizontalAlignment="Right" Margin="10,0,0,0" ToolTip="Edit layer"
IsEnabled="{Binding Path=LayerSelected}"> IsEnabled="{Binding Path=LayerSelected}">
<Button.Content> <Button.Content>
<Rectangle <Rectangle